Hello community, here is the log from the commit of package cryptctl for openSUSE:Factory checked in at 2017-06-08 15:03:27 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/cryptctl (Old) and /work/SRC/openSUSE:Factory/.cryptctl.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "cryptctl" Thu Jun 8 15:03:27 2017 rev:4 rq:501709 version:2.2 Changes: -------- --- /work/SRC/openSUSE:Factory/cryptctl/cryptctl.changes 2017-06-04 02:00:23.083493983 +0200 +++ /work/SRC/openSUSE:Factory/.cryptctl.new/cryptctl.changes 2017-06-08 15:03:30.130797457 +0200 @@ -1,0 +2,11 @@ +Wed Jun 7 12:11:50 UTC 2017 - h...@suse.com + +- Upgrade to upstream release 2.2 that brings important enhancements + in effor tof implementing fate#322979: + * System administrator may now optionally turn off TLS certificate + verification on KMIP server. Note that, certificate verification + is enforced by default. + * Improve handling of boolean answers from interactive command line. + * Improve error handling in KMIP client. + +------------------------------------------------------------------- Old: ---- cryptctl-2.1.tgz New: ---- cryptctl-2.2.tgz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ cryptctl.spec ++++++ --- /var/tmp/diff_new_pack.LcuzH4/_old 2017-06-08 15:03:30.586733111 +0200 +++ /var/tmp/diff_new_pack.LcuzH4/_new 2017-06-08 15:03:30.586733111 +0200 @@ -17,7 +17,7 @@ Name: cryptctl -Version: 2.1 +Version: 2.2 Release: 0 Summary: A utility for setting up LUKS-based disk encryption License: GPL-3.0 ++++++ cryptctl-2.1.tgz -> cryptctl-2.2.tgz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/command/client.go new/command/client.go --- old/command/client.go 2017-05-31 13:42:19.429519219 +0200 +++ new/command/client.go 2017-06-06 13:56:24.447582048 +0200 @@ -102,7 +102,7 @@ } storedHost := sysconf.GetString(keyserv.CLIENT_CONF_HOST, "") if storedHost != "" && host != storedHost { - if !sys.InputBool(MSG_ASK_DIFF_HOST, storedHost, host) { + if !sys.InputBool(false, MSG_ASK_DIFF_HOST, storedHost, host) { return errors.New(MSG_E_CANCELLED) } } @@ -138,7 +138,7 @@ // Prompt user for confirmation and then proceed fmt.Printf(MSG_ENC_SEQUENCE, encDisk, srcDir) - if !sys.InputBool(MSG_ASK_PROCEED) { + if !sys.InputBool(false, MSG_ASK_PROCEED) { return errors.New(MSG_E_CANCELLED) } // Alive-report interval is hard coded for now until there is a very good reason to change it diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/command/server.go new/command/server.go --- old/command/server.go 2017-06-01 12:42:35.899886409 +0200 +++ new/command/server.go 2017-06-07 11:47:29.907094109 +0200 @@ -106,7 +106,7 @@ var reconfigure bool if sysconf.GetString(keyserv.SRV_CONF_PASS_HASH, "") != "" { reconfigure = true - if !sys.InputBool(`You appear to have already initialised the configuration on this key server. + if !sys.InputBool(false, `You appear to have already initialised the configuration on this key server. Would you like to re-configure it?`) { fmt.Println("OK, existing configuration is left untouched.") return nil @@ -219,35 +219,40 @@ // Walk through the remaining mandatory configuration keys if listenAddr := sys.Input(false, - sysconf.GetString(keyserv.SRV_CONF_LISTEN_ADDR, ""), + sysconf.GetString(keyserv.SRV_CONF_LISTEN_ADDR, "0.0.0.0"), "IP address for the server to listen on (0.0.0.0 to listen on all network interfaces)"); listenAddr != "" { sysconf.Set(keyserv.SRV_CONF_LISTEN_ADDR, listenAddr) } if listenPort := sys.InputInt(false, - sysconf.GetInt(keyserv.SRV_CONF_LISTEN_PORT, 0), 1, 65535, + sysconf.GetInt(keyserv.SRV_CONF_LISTEN_PORT, 3737), 1, 65535, "TCP port number to listen on"); listenPort != 0 { sysconf.Set(keyserv.SRV_CONF_LISTEN_PORT, listenPort) } if keyDBDir := sys.InputAbsFilePath(true, - sysconf.GetString(keyserv.SRV_CONF_KEYDB_DIR, ""), + sysconf.GetString(keyserv.SRV_CONF_KEYDB_DIR, "/var/lib/cryptctl/keydb"), "Key database directory"); keyDBDir != "" { sysconf.Set(keyserv.SRV_CONF_KEYDB_DIR, keyDBDir) } // Walk through client certificate verification settings - validateClient := sys.InputBool("Should clients present their certificate in order to access this server?") + validateClient := sys.InputBool(sysconf.GetString(keyserv.SRV_CONF_TLS_CA, "") != "", + "Should clients present their certificate in order to access this server?") sysconf.Set(keyserv.SRV_CONF_TLS_VALIDATE_CLIENT, validateClient) if validateClient { - sysconf.Set(keyserv.SRV_CONF_TLS_CA, sys.Input(true, "", "PEM-encoded TLS certificate authority that will issue client certificates")) + sysconf.Set(keyserv.SRV_CONF_TLS_CA, + sys.InputAbsFilePath(true, + sysconf.GetString(keyserv.SRV_CONF_TLS_CA, ""), + "PEM-encoded TLS certificate authority that will issue client certificates")) } // Walk through KMIP settings - useExternalKMIPServer := sys.InputBool("Should encryption keys be kept on a KMIP-compatible key management appliance?") + useExternalKMIPServer := sys.InputBool(sysconf.GetString(keyserv.SRV_CONF_KMIP_SERVER_ADDRS, "") != "", + "Should encryption keys be kept on a KMIP-compatible key management appliance?") if useExternalKMIPServer { sysconf.Set(keyserv.SRV_CONF_KMIP_SERVER_ADDRS, sys.Input(true, "", "Space-separated KMIP server addresses (host1:port1 host2:port2 ...)")) sysconf.Set(keyserv.SRV_CONF_KMIP_SERVER_USER, sys.Input(false, "", "KMIP username")) sysconf.Set(keyserv.SRV_CONF_KMIP_SERVER_PASS, sys.InputPassword(false, "", "KMIP password")) - sysconf.Set(keyserv.SRV_CONF_KMIP_SERVER_TLS_CA, sys.Input(false, "", "PEM-encoded TLS certificate authority that issued KMIP server certificate")) - sysconf.Set(keyserv.SRV_CONF_KMIP_SERVER_TLS_CERT, sys.Input(false, "", "PEM-encoded TLS client identitiy certificate")) - sysconf.Set(keyserv.SRV_CONF_KMIP_SERVER_TLS_KEY, sys.Input(false, "", "PEM-encoded TLS client identitiy certificate key")) + sysconf.Set(keyserv.SRV_CONF_KMIP_SERVER_TLS_CA, sys.InputAbsFilePath(false, "", "PEM-encoded TLS certificate authority of KMIP server")) + sysconf.Set(keyserv.SRV_CONF_KMIP_SERVER_TLS_CERT, sys.InputAbsFilePath(false, "", "PEM-encoded TLS client identity certificate")) + sysconf.Set(keyserv.SRV_CONF_KMIP_SERVER_TLS_KEY, sys.InputAbsFilePath(false, "", "PEM-encoded TLS client identity certificate key")) } // Walk through optional email settings fmt.Println("\nTo enable Email notifications, enter the following parameters:") @@ -305,9 +310,9 @@ fmt.Println("\nSettings have been saved successfully!") var start bool if sys.SystemctlIsRunning(SERVER_DAEMON) { - start = sys.InputBool("Would you like to restart key server (%s) to apply the new settings?", SERVER_DAEMON) + start = sys.InputBool(true, "Would you like to restart key server (%s) to apply the new settings?", SERVER_DAEMON) } else { - start = sys.InputBool("Would you like to start key server (%s) now?", SERVER_DAEMON) + start = sys.InputBool(true, "Would you like to start key server (%s) now?", SERVER_DAEMON) } if !start { return nil diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/keyserv/kmip_client.go new/keyserv/kmip_client.go --- old/keyserv/kmip_client.go 2017-06-01 14:52:47.172639453 +0200 +++ new/keyserv/kmip_client.go 2017-06-06 11:40:30.483632264 +0200 @@ -115,7 +115,8 @@ } // Always prefer to use the first server among the list of servers addr := client.ServerAddrs[i%len(client.ServerAddrs)] - conn, err := tls.Dial("tcp", addr, client.TLSConfig) + var conn *tls.Conn + conn, err = tls.Dial("tcp", addr, client.TLSConfig) if err != nil { log.Printf("KMIPClient.ConverseWithRetry: IO failure occured with KMIP server %s", addr) continue @@ -125,7 +126,8 @@ conn.Close() continue } - ttlvResp, err := ReadFullTTLV(conn) + var ttlvResp ttlv.Item + ttlvResp, err = ReadFullTTLV(conn) if err != nil { log.Printf("KMIPClient.ConverseWithRetry: IO failure occured with KMIP server %s", addr) conn.Close() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/keyserv/rpc_svc.go new/keyserv/rpc_svc.go --- old/keyserv/rpc_svc.go 2017-06-01 12:41:26.439420140 +0200 +++ new/keyserv/rpc_svc.go 2017-06-07 11:55:14.869941696 +0200 @@ -49,6 +49,7 @@ SRV_CONF_KMIP_SERVER_ADDRS = "KMIP_SERVER_ADDRESSES" SRV_CONF_KMIP_SERVER_USER = "KMIP_SERVER_USER" SRV_CONF_KMIP_SERVER_PASS = "KMIP_SERVER_PASS" + SRV_CONF_KMIP_TLS_DO_VERIFY = "KMIP_TLS_DO_VERIFY" SRV_CONF_KMIP_SERVER_TLS_CA = "KMIP_CA_PEM" SRV_CONF_KMIP_SERVER_TLS_CERT = "KMIP_TLS_CERT_PEM" SRV_CONF_KMIP_SERVER_TLS_KEY = "KMIP_TLS_CERT_KEY_PEM" @@ -107,6 +108,7 @@ KMIPUser string // optional KMIP service access user KMIPPass string // optional KMIP service access password KMIPCertAuthorityPEM string // optional KMIP server CA certificate + KMIPTLSDoVerify bool // Enable verification on KMIP server's TLS certificate KMIPCertPEM string // optional KMIP client certificate KMIPKeyPEM string // optional KMIP client certificate key } @@ -155,10 +157,10 @@ conf.KeyRetrievalGreeting = sysconf.GetString(SRV_CONF_MAIL_RETRIEVAL_TEXT, "The key server has sent the following encryption key to allow access to its file systems:") conf.KMIPAddresses = sysconf.GetStringArray(SRV_CONF_KMIP_SERVER_ADDRS, []string{}) - conf.KMIPUser = sysconf.GetString(SRV_CONF_KMIP_SERVER_USER, "") conf.KMIPPass = sysconf.GetString(SRV_CONF_KMIP_SERVER_PASS, "") conf.KMIPCertAuthorityPEM = sysconf.GetString(SRV_CONF_KMIP_SERVER_TLS_CA, "") + conf.KMIPTLSDoVerify = sysconf.GetBool(SRV_CONF_KMIP_TLS_DO_VERIFY, true) conf.KMIPCertPEM = sysconf.GetString(SRV_CONF_KMIP_SERVER_TLS_CERT, "") conf.KMIPKeyPEM = sysconf.GetString(SRV_CONF_KMIP_SERVER_TLS_KEY, "") return conf.Validate() @@ -254,6 +256,10 @@ caCert, srv.Config.KMIPCertPEM, srv.Config.KMIPKeyPEM); err != nil { return err } + if !srv.Config.KMIPTLSDoVerify { + log.Printf("CryptServer.ListenRPC: KMIP client will not verify KMIP server's identity, as instructed by configuration.") + srv.KMIPClient.TLSConfig.InsecureSkipVerify = !srv.Config.KMIPTLSDoVerify + } } // Start ordinary RPC server if srv.Listener, err = tls.Listen("tcp", fmt.Sprintf("%s:%d", srv.Config.Address, srv.Config.Port), srv.TLSConfig); err != nil { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/keyserv/rpc_svc_test.go new/keyserv/rpc_svc_test.go --- old/keyserv/rpc_svc_test.go 2017-06-01 14:25:52.106974576 +0200 +++ new/keyserv/rpc_svc_test.go 2017-06-07 13:24:43.921729751 +0200 @@ -108,6 +108,7 @@ KeyRetrievalSubject: "c", KeyRetrievalGreeting: "d", KMIPAddresses: []string{}, + KMIPTLSDoVerify: true, }) { t.Fatalf("%+v", svcConf) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ospackage/etc/sysconfig/cryptctl-server new/ospackage/etc/sysconfig/cryptctl-server --- old/ospackage/etc/sysconfig/cryptctl-server 2017-06-01 13:50:17.938692498 +0200 +++ new/ospackage/etc/sysconfig/cryptctl-server 2017-06-07 12:01:50.276439134 +0200 @@ -160,3 +160,10 @@ # If key server should act as KMIP proxy, this is the KMIP client certificate key. KMIP_TLS_CERT_KEY_PEM="" +## Type: boolean +## Default: "yes" +# +# For security reasons, you are strongly recommended to leave the setting at its default "yes". +# If set to "no", cryptctl server will reduce its security measures by not verifying KMIP server's TLS certificate. +# Remember to restart cryptctl-server.service after changing any value of this file. +KMIP_TLS_DO_VERIFY="yes" \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ospackage/man/cryptctl.8 new/ospackage/man/cryptctl.8 --- old/ospackage/man/cryptctl.8 2017-05-31 13:45:21.458563746 +0200 +++ new/ospackage/man/cryptctl.8 2017-06-07 14:10:57.740164268 +0200 @@ -59,9 +59,11 @@ administrator can always retrieve encryption keys by using key server's access password. .I cryptctl -can utilise an external key management appliance that understands KMIP v1.3 to store the actual encryption keys. The server -setup sequence asks the system administrator for KMIP connectivity details such as host name, port, certificate, and user -credentials. Of course cryptctl functions perfectly well without using an external key management appliance. +can optionally utilise an external key management appliance that understands KMIP v1.3 to store the actual disk encryption keys. +Should you choose to use the external appliance, you may enter KMIP connectivity details such as host name, port, certificate, +and user credentials during server initialisation sequence. If you do not wish to use the external appliance, +.I cryptctl +will store encryption keys in its own database. .SH KEY SERVER ACTIONS .SS @@ -123,7 +125,8 @@ unavailable or the communication be cut off, already unlocked file systems will remain mounted, however locked file systems will not be able to retrieve encryption keys from the key server. Hence, this manual procedure has been designed to allow unlocking of encrypted disks directly from key database record, via physical access to both the key -server and client computer. This procedure will not trigger Email notification or track key usage. +server and client computer. This procedure is not applicable should you have used an external KMIP appliance to store +encryption keys, nor will it trigger Email notification or track key usage. .nr step 1 1 .IP \n[step] @@ -156,11 +159,32 @@ to every operation: -ca=/path/to/testing.crt -If you wish to maintain a certificate infrastructure for multiple key servers in a production environment, the YaST -Certificate Management program may come in handy. +By default, the key server accepts encryption requests from all password-authenticated clients, and hands out encryption +keys to all clients that request keys for a valid disk UUID. If you wish to further strengthen verification on client +identity, you may enter an authority certificate file during server's initialisation sequence, from there all clients must +present valid certificate issued by the specified CA in order to contact the key server. + +In order to build a public key infrastructure to issue server and client certificates, consider using lightweight tools + such as "easy-rsa" by OpenVPN, or YaST Certificate Management program. + +.SH ON USING EXTERNAL KMIP SERVER APPLIANCE +By default, the key server stores all disk encryption keys along with key usage tracking data in a built-in database. If +you decide to use an external KMIP server appliance to store and manage disk encryption keys, you may enter its connectivity +details during server's initialisation sequence. You must make the decision on whether to use external KMIP server before +any disk is encrypted using the key server, and you may not change the settings (e.g. turn off KMIP and use built-in +database again) once a disk has been encrypted. -The server can optionally enforce verification of clients' certificate, should you decide to let server verify clients' -identity before serving them encryption keys. The behaviour is setup during server's and client's setup sequence. +By default, +.I cryptctl +performs strong verification on all TLS certificates. When it acts as a KMIP client, it verifies the common name of KMIP +server against the certificate presented by it, along with other checks such as validity date. Should any certificate +verification error occur, cryptctl will report back with the error reason and temporarily cease conversation with the KMIP +server. It is strongly recommended to leave certificate verification enabled. + +However, should you wish not to verify KMIP server certificate, you may turn it off by editing server configuration file +.I /etc/sysconfig/cryptctl-server +, find key "KMIP_TLS_DO_VERIFY" and change its value to "no", then restart cryptctl-server.service. Turning off the +verification opens up the risk of leaking disk encryption keys to eavesdroppers. .SH CHANGE/REVOKE OR DELETE ENCRYPTION KEY If you decide to revoke or change encryption key for an encrypted file system, please back up the encrypted data onto a @@ -168,8 +192,8 @@ revoke or change encryption key. Destroy an encryption key will render an encrypted file system irreversibly lost, execute "cryptctl erase" on the client -computer and enter the file system UUID will proceed to erase metadata of the encrypted file system, and then contact -key server to erase its encryption record as well. +computer and enter the file system UUID will erase the key tracking record from key server, the key content from KMIP server +(if used), and the metadata of encrypted file system. .SH FILES .NF diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sys/sysconfig.go new/sys/sysconfig.go --- old/sys/sysconfig.go 2017-05-31 13:44:56.394419921 +0200 +++ new/sys/sysconfig.go 2017-06-07 11:50:29.568205501 +0200 @@ -187,7 +187,7 @@ defaultValStr = "yes" } value := strings.ToLower(conf.GetString(key, defaultValStr)) - return (value == "yes" || value == "true") + return value == "yes" || value == "true" } // Convert key-value pairs back into text. Values are always surrounded by double-quotes. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/sys/term.go new/sys/term.go --- old/sys/term.go 2017-05-31 13:44:56.442420197 +0200 +++ new/sys/term.go 2017-06-06 14:03:45.021994085 +0200 @@ -93,14 +93,14 @@ } // Print a prompt in stdout and return a boolean value read from stdin. -func InputBool(format string, values ...interface{}) bool { - fmt.Printf(format+": ", values...) +func InputBool(defaultHint bool, format string, values ...interface{}) bool { + defaultStr := "yes" + if !defaultHint { + defaultStr = "no" + } for { - str, err := bufio.NewReader(os.Stdin).ReadString('\n') - if err != nil { - log.Panicf("Input: failed to read from stadard input - %v", err) - } - switch strings.TrimSpace(strings.ToLower(str)) { + answer := Input(false, defaultStr, format, values...) + switch strings.TrimSpace(strings.ToLower(answer)) { case "y": fallthrough case "yes": @@ -113,6 +113,8 @@ fallthrough case "nein": return false + case "": + return defaultHint default: fmt.Print("Please enter \"yes\" or \"no\": ") os.Stdout.Sync() @@ -126,7 +128,7 @@ for { val := Input(mandatory, defaultHint, format, values...) if val == "" { - return val + return defaultHint } if val[0] != '/' { fmt.Println("Please enter an absolute path led by a slash.")