head 1.2; access; symbols; locks; strict; comment @# @; 1.2 date 2015.09.01.16.02.54; author manu; state dead; branches; next 1.1; commitid lga69YxNqJyCczzy; 1.1 date 2015.08.02.02.48.34; author manu; state Exp; branches; next ; commitid lJ1HXa9cYcqrLDvy; desc @@ 1.2 log @Maintenance upgrade to 3.7.4 @ text @$NetBSD: patch-11763,v 1.1 2015/08/02 02:48:34 manu Exp $ From upstream: http://review.gluster.org/11763 SSL improvements: ECDH, DH, CRL, and accessible options - Introduce ssl.dh-param option to specify a file containinf DH parameters. If it is provided, EDH ciphers are available. - Introduce ssl.ec-curve option to specify an elliptic curve name. If unspecified, ECDH ciphers are available using the prime256v1 curve. - Introduce ssl.crl-path option to specify the directory where the CRL hash file can be found. Setting to NULL disable CRL checking, just like the default. - Make all ssl.* options accessible through gluster volume set - In default cipher list, exclude weak ciphers instead of listing the strong ones. - Enforce server cipher preference. - introduce RPC_SET_OPT macro to factor repetitive code in glusterd-volgen.c - Add ssl-ciphers.t test to check all the features touched by this change. Backport of I7bfd433df6bbf176f4a58e770e06bcdbe22a101a Change-Id: I2947eabe76ae0487ecad52a60befb7de473fc90c BUG: 1247153 Signed-off-by: Emmanuel Dreyfus --- ./xlators/mgmt/glusterd/src/glusterd-volgen.c.orig 2015-07-28 08:28:31.000000000 +0200 +++ ./xlators/mgmt/glusterd/src/glusterd-volgen.c 2015-07-28 10:36:56.000000000 +0200 @@@@ -41,8 +41,22 @@@@ #include "glusterd-snapd-svc-helper.h" extern struct volopt_map_entry glusterd_volopt_map[]; +#define RPC_SET_OPT(XL, CLI_OPT, XLATOR_OPT, ERROR_CMD) do { \ + char *_value = NULL; \ + \ + if (dict_get_str (set_dict, CLI_OPT, &_value) == 0) { \ + if (xlator_set_option (XL, \ + "transport.socket." XLATOR_OPT, _value) != 0) { \ + gf_msg ("glusterd", GF_LOG_WARNING, errno, \ + GD_MSG_XLATOR_SET_OPT_FAIL, \ + "failed to set " XLATOR_OPT); \ + ERROR_CMD; \ + } \ + } \ +} while (0 /* CONSTCOND */) + /********************************************* * * xlator generation / graph manipulation API * @@@@ -2075,27 +2089,16 @@@@ if (ret) return -1; } - if (dict_get_str (set_dict, SSL_CERT_DEPTH_OPT, &value) == 0) { - ret = xlator_set_option (xl, "ssl-cert-depth", value); - if (ret) { - gf_msg ("glusterd", GF_LOG_WARNING, 0, - GD_MSG_XLATOR_SET_OPT_FAIL, - "failed to set ssl-cert-depth"); - return -1; - } - } - - if (dict_get_str (set_dict, SSL_CIPHER_LIST_OPT, &value) == 0) { - ret = xlator_set_option (xl, "ssl-cipher-list", value); - if (ret) { - gf_msg ("glusterd", GF_LOG_WARNING, 0, - GD_MSG_XLATOR_SET_OPT_FAIL, - "failed to set ssl-cipher-list"); - return -1; - } - } + RPC_SET_OPT(xl, SSL_OWN_CERT_OPT, "ssl-own-cert", return -1); + RPC_SET_OPT(xl, SSL_PRIVATE_KEY_OPT,"ssl-private-key", return -1); + RPC_SET_OPT(xl, SSL_CA_LIST_OPT, "ssl-ca-list", return -1); + RPC_SET_OPT(xl, SSL_CRL_PATH_OPT, "ssl-crl-path", return -1); + RPC_SET_OPT(xl, SSL_CERT_DEPTH_OPT, "ssl-cetificate-depth", return -1); + RPC_SET_OPT(xl, SSL_CIPHER_LIST_OPT,"ssl-cipher-list", return -1); + RPC_SET_OPT(xl, SSL_DH_PARAM_OPT, "ssl-dh-param", return -1); + RPC_SET_OPT(xl, SSL_EC_CURVE_OPT, "ssl-ec-curve", return -1); if (username) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "auth.login.%s.allow", @@@@ -2169,28 +2172,24 @@@@ ptranst = glusterd_get_trans_type_rb (volinfo->transport_type); if (NULL == ptranst) return -1; - if (dict_get_str (set_dict, SSL_CERT_DEPTH_OPT, &value) == 0) { - ret = xlator_set_option (rbxl, "ssl-cert-depth", value); - if (ret) { - gf_msg ("glusterd", GF_LOG_WARNING, errno, - GD_MSG_DICT_GET_FAILED, - "failed to set ssl-cert-depth"); - return -1; - } - } - - if (dict_get_str (set_dict, SSL_CIPHER_LIST_OPT, &value) == 0) { - ret = xlator_set_option (rbxl, "ssl-cipher-list", - value); - if (ret) { - gf_msg ("glusterd", GF_LOG_WARNING, errno, - GD_MSG_DICT_GET_FAILED, - "failed to set ssl-cipher-list"); - return -1; - } - } + RPC_SET_OPT(rbxl, SSL_OWN_CERT_OPT, "ssl-own-cert", + return -1); + RPC_SET_OPT(rbxl, SSL_PRIVATE_KEY_OPT,"ssl-private-key", + return -1); + RPC_SET_OPT(rbxl, SSL_CA_LIST_OPT, "ssl-ca-list", + return -1); + RPC_SET_OPT(rbxl, SSL_CRL_PATH_OPT, "ssl-crl-path", + return -1); + RPC_SET_OPT(rbxl, SSL_CERT_DEPTH_OPT, "ssl-cetificate-depth", + return -1); + RPC_SET_OPT(rbxl, SSL_CIPHER_LIST_OPT,"ssl-cipher-list", + return -1); + RPC_SET_OPT(rbxl, SSL_DH_PARAM_OPT, "ssl-dh-param", + return -1); + RPC_SET_OPT(rbxl, SSL_EC_CURVE_OPT, "ssl-ec-curve", + return -1); if (username) { ret = xlator_set_option (rbxl, "username", username); if (ret) @@@@ -2747,27 +2746,16 @@@@ } } } - if (dict_get_str (set_dict, SSL_CERT_DEPTH_OPT, &value) == 0) { - ret = xlator_set_option (xl, "ssl-cert-depth", value); - if (ret) { - gf_msg ("glusterd", GF_LOG_WARNING, errno, - GD_MSG_DICT_GET_FAILED, - "failed to set ssl-cert-depth"); - goto err; - } - } - - if (dict_get_str (set_dict, SSL_CIPHER_LIST_OPT, &value) == 0) { - ret = xlator_set_option (xl, "ssl-cipher-list", value); - if (ret) { - gf_msg ("glusterd", GF_LOG_WARNING, errno, - GD_MSG_DICT_GET_FAILED, - "failed to set ssl-cipher-list"); - goto err; - } - } + RPC_SET_OPT(xl, SSL_OWN_CERT_OPT, "ssl-own-cert", goto err); + RPC_SET_OPT(xl, SSL_PRIVATE_KEY_OPT,"ssl-private-key", goto err); + RPC_SET_OPT(xl, SSL_CA_LIST_OPT, "ssl-ca-list", goto err); + RPC_SET_OPT(xl, SSL_CRL_PATH_OPT, "ssl-crl-path", goto err); + RPC_SET_OPT(xl, SSL_CERT_DEPTH_OPT, "ssl-cetificate-depth", goto err); + RPC_SET_OPT(xl, SSL_CIPHER_LIST_OPT,"ssl-cipher-list", goto err); + RPC_SET_OPT(xl, SSL_DH_PARAM_OPT, "ssl-dh-param", goto err); + RPC_SET_OPT(xl, SSL_EC_CURVE_OPT, "ssl-ec-curve", goto err); return xl; err: return NULL; @@@@ -4961,27 +4949,16 @@@@ ret = xlator_set_option (xl, "transport-type", "tcp"); if (ret) return -1; - if (dict_get_str (set_dict, SSL_CERT_DEPTH_OPT, &value) == 0) { - ret = xlator_set_option (xl, "ssl-cert-depth", value); - if (ret) { - gf_msg ("glusterd", GF_LOG_WARNING, 0, - GD_MSG_XLATOR_SET_OPT_FAIL, - "failed to set ssl-cert-depth"); - return -1; - } - } - - if (dict_get_str (set_dict, SSL_CIPHER_LIST_OPT, &value) == 0) { - ret = xlator_set_option (xl, "ssl-cipher-list", value); - if (ret) { - gf_msg ("glusterd", GF_LOG_WARNING, 0, - GD_MSG_XLATOR_SET_OPT_FAIL, - "failed to set ssl-cipher-list"); - return -1; - } - } + RPC_SET_OPT(xl, SSL_OWN_CERT_OPT, "ssl-own-cert", return -1); + RPC_SET_OPT(xl, SSL_PRIVATE_KEY_OPT,"ssl-private-key", return -1); + RPC_SET_OPT(xl, SSL_CA_LIST_OPT, "ssl-ca-list", return -1); + RPC_SET_OPT(xl, SSL_CRL_PATH_OPT, "ssl-crl-path", return -1); + RPC_SET_OPT(xl, SSL_CERT_DEPTH_OPT, "ssl-cetificate-depth", return -1); + RPC_SET_OPT(xl, SSL_CIPHER_LIST_OPT,"ssl-cipher-list", return -1); + RPC_SET_OPT(xl, SSL_DH_PARAM_OPT, "ssl-dh-param", return -1); + RPC_SET_OPT(xl, SSL_EC_CURVE_OPT, "ssl-ec-curve", return -1); username = glusterd_auth_get_username (volinfo); passwd = glusterd_auth_get_password (volinfo); --- ./xlators/mgmt/glusterd/src/glusterd-volgen.h.orig 2015-07-28 08:28:31.000000000 +0200 +++ ./xlators/mgmt/glusterd/src/glusterd-volgen.h 2015-07-28 10:36:56.000000000 +0200 @@@@ -44,10 +44,16 @@@@ #define AUTH_ALLOW_OPT_KEY "auth.addr.*.allow" #define AUTH_REJECT_OPT_KEY "auth.addr.*.reject" #define NFS_DISABLE_OPT_KEY "nfs.*.disable" +#define SSL_OWN_CERT_OPT "ssl.own-cert" +#define SSL_PRIVATE_KEY_OPT "ssl.private-key" +#define SSL_CA_LIST_OPT "ssl.ca-list" +#define SSL_CRL_PATH_OPT "ssl.crl-path" #define SSL_CERT_DEPTH_OPT "ssl.certificate-depth" #define SSL_CIPHER_LIST_OPT "ssl.cipher-list" +#define SSL_DH_PARAM_OPT "ssl.dh-param" +#define SSL_EC_CURVE_OPT "ssl.ec-curve" typedef enum { GF_CLIENT_TRUSTED, --- ./xlators/mgmt/glusterd/src/glusterd-volume-set.c.orig 2015-07-28 08:28:31.000000000 +0200 +++ ./xlators/mgmt/glusterd/src/glusterd-volume-set.c 2015-07-28 10:36:56.000000000 +0200 @@@@ -1081,8 +1081,28 @@@@ .op_version = GD_OP_VERSION_3_7_0, }, /* Generic transport options */ + { .key = SSL_OWN_CERT_OPT, + .voltype = "rpc-transport/socket", + .option = "!ssl-own-cert", + .op_version = GD_OP_VERSION_3_7_0, + }, + { .key = SSL_PRIVATE_KEY_OPT, + .voltype = "rpc-transport/socket", + .option = "!ssl-private-key", + .op_version = GD_OP_VERSION_3_7_0, + }, + { .key = SSL_CA_LIST_OPT, + .voltype = "rpc-transport/socket", + .option = "!ssl-ca-list", + .op_version = GD_OP_VERSION_3_7_0, + }, + { .key = SSL_CRL_PATH_OPT, + .voltype = "rpc-transport/socket", + .option = "!ssl-crl-path", + .op_version = GD_OP_VERSION_3_7_0, + }, { .key = SSL_CERT_DEPTH_OPT, .voltype = "rpc-transport/socket", .option = "!ssl-cert-depth", .op_version = GD_OP_VERSION_3_6_0, @@@@ -1091,8 +1111,18 @@@@ .voltype = "rpc-transport/socket", .option = "!ssl-cipher-list", .op_version = GD_OP_VERSION_3_6_0, }, + { .key = SSL_DH_PARAM_OPT, + .voltype = "rpc-transport/socket", + .option = "!ssl-dh-param", + .op_version = GD_OP_VERSION_3_7_0, + }, + { .key = SSL_EC_CURVE_OPT, + .voltype = "rpc-transport/socket", + .option = "!ssl-ec-curve", + .op_version = GD_OP_VERSION_3_7_0, + }, /* Performance xlators enable/disbable options */ { .key = "performance.write-behind", .voltype = "performance/write-behind", --- ./rpc/rpc-transport/socket/src/socket.c.orig 2015-07-28 08:28:30.000000000 +0200 +++ ./rpc/rpc-transport/socket/src/socket.c 2015-07-28 10:36:56.000000000 +0200 @@@@ -48,76 +48,15 @@@@ #define SSL_ENABLED_OPT "transport.socket.ssl-enabled" #define SSL_OWN_CERT_OPT "transport.socket.ssl-own-cert" #define SSL_PRIVATE_KEY_OPT "transport.socket.ssl-private-key" #define SSL_CA_LIST_OPT "transport.socket.ssl-ca-list" +#define SSL_CERT_DEPTH_OPT "transport.socket.ssl-cert-depth" +#define SSL_CIPHER_LIST_OPT "transport.socket.ssl-cipher-list" +#define SSL_DH_PARAM_OPT "transport.socket.ssl-dh-param" +#define SSL_EC_CURVE_OPT "transport.socket.ssl-ec-curve" +#define SSL_CRL_PATH_OPT "transport.socket.ssl-crl-path" #define OWN_THREAD_OPT "transport.socket.own-thread" -/* - * This list was derived by taking the cipher list "HIGH:!SSLv2" (the previous - * default) and excluding CBC entries to mitigate the "POODLE" attack. It - * should be re-evaluated in light of each future vulnerability, as those are - * discovered. - */ -static char *default_cipher_list = - "ECDHE-RSA-AES256-GCM-SHA384:" - "ECDHE-ECDSA-AES256-GCM-SHA384:" - "ECDHE-RSA-AES256-SHA384:" - "ECDHE-ECDSA-AES256-SHA384:" - "ECDHE-RSA-AES256-SHA:" - "ECDHE-ECDSA-AES256-SHA:" - "DHE-DSS-AES256-GCM-SHA384:" - "DHE-RSA-AES256-GCM-SHA384:" - "DHE-RSA-AES256-SHA256:" - "DHE-DSS-AES256-SHA256:" - "DHE-RSA-AES256-SHA:" - "DHE-DSS-AES256-SHA:" - "DHE-RSA-CAMELLIA256-SHA:" - "DHE-DSS-CAMELLIA256-SHA:" - "AECDH-AES256-SHA:" - "ADH-AES256-GCM-SHA384:" - "ADH-AES256-SHA256:" - "ADH-AES256-SHA:" - "ADH-CAMELLIA256-SHA:" - "ECDH-RSA-AES256-GCM-SHA384:" - "ECDH-ECDSA-AES256-GCM-SHA384:" - "ECDH-RSA-AES256-SHA384:" - "ECDH-ECDSA-AES256-SHA384:" - "ECDH-RSA-AES256-SHA:" - "ECDH-ECDSA-AES256-SHA:" - "AES256-GCM-SHA384:" - "AES256-SHA256:" - "AES256-SHA:" - "CAMELLIA256-SHA:" - "ECDHE-RSA-AES128-GCM-SHA256:" - "ECDHE-ECDSA-AES128-GCM-SHA256:" - "ECDHE-RSA-AES128-SHA256:" - "ECDHE-ECDSA-AES128-SHA256:" - "ECDHE-RSA-AES128-SHA:" - "ECDHE-ECDSA-AES128-SHA:" - "DHE-DSS-AES128-GCM-SHA256:" - "DHE-RSA-AES128-GCM-SHA256:" - "DHE-RSA-AES128-SHA256:" - "DHE-DSS-AES128-SHA256:" - "DHE-RSA-AES128-SHA:" - "DHE-DSS-AES128-SHA:" - "DHE-RSA-CAMELLIA128-SHA:" - "DHE-DSS-CAMELLIA128-SHA:" - "AECDH-AES128-SHA:" - "ADH-AES128-GCM-SHA256:" - "ADH-AES128-SHA256:" - "ADH-AES128-SHA:" - "ADH-CAMELLIA128-SHA:" - "ECDH-RSA-AES128-GCM-SHA256:" - "ECDH-ECDSA-AES128-GCM-SHA256:" - "ECDH-RSA-AES128-SHA256:" - "ECDH-ECDSA-AES128-SHA256:" - "ECDH-RSA-AES128-SHA:" - "ECDH-ECDSA-AES128-SHA:" - "AES128-GCM-SHA256:" - "AES128-SHA256:" - "AES128-SHA:" - "CAMELLIA128-SHA"; /* no colon for last entry */ - /* TBD: do automake substitutions etc. (ick) to set these. */ #if !defined(DEFAULT_ETC_SSL) # ifdef GF_LINUX_HOST_OS # define DEFAULT_ETC_SSL "/etc/ssl" @@@@ -131,8 +70,9 @@@@ # if !defined(DEFAULT_ETC_SSL) # define DEFAULT_ETC_SSL "/etc/ssl" # endif #endif + #if !defined(DEFAULT_CERT_PATH) #define DEFAULT_CERT_PATH DEFAULT_ETC_SSL "/glusterfs.pem" #endif #if !defined(DEFAULT_KEY_PATH) @@@@ -140,8 +80,14 @@@@ #endif #if !defined(DEFAULT_CA_PATH) #define DEFAULT_CA_PATH DEFAULT_ETC_SSL "/glusterfs.ca" #endif +#if !defined(DEFAULT_VERIFY_DEPTH) +#define DEFAULT_VERIFY_DEPTH 1 +#endif +#define DEFAULT_CIPHER_LIST "EECDH:EDH:HIGH:!3DES:!RC4:!DES:!MD5:!aNULL:!eNULL" +#define DEFAULT_DH_PARAM DEFAULT_ETC_SSL "/dhparam.pem" +#define DEFAULT_EC_CURVE "prime256v1" #define POLL_MASK_INPUT (POLLIN | POLLPRI) #define POLL_MASK_OUTPUT (POLLOUT) #define POLL_MASK_ERROR (POLLERR | POLLHUP | POLLNVAL) @@@@ -3778,11 +3724,13 @@@@ uint32_t keepalive = 0; uint32_t timeout = 0; uint32_t backlog = 0; int session_id = 0; - int32_t cert_depth = 1; - char *cipher_list = default_cipher_list; - int ret; + int32_t cert_depth = DEFAULT_VERIFY_DEPTH; + char *cipher_list = DEFAULT_CIPHER_LIST; + char *dh_param = DEFAULT_DH_PARAM; + char *ec_curve = DEFAULT_EC_CURVE; + char *crl_path = NULL; if (this->private) { gf_log_callingfn (this->name, GF_LOG_ERROR, "double init attempted"); @@@@ -3962,8 +3910,20 @@@@ priv->ssl_ca_list = optstr; } priv->ssl_ca_list = gf_strdup(priv->ssl_ca_list); + if (dict_get_str(this->options,SSL_CRL_PATH_OPT,&optstr) == 0) { + if (!priv->ssl_enabled) { + gf_log(this->name,GF_LOG_WARNING, + "%s specified without %s (ignored)", + SSL_CRL_PATH_OPT, SSL_ENABLED_OPT); + } + if (strcasecmp(optstr, "NULL") == 0) + crl_path = NULL; + else + crl_path = optstr; + } + gf_log(this->name, priv->ssl_enabled ? GF_LOG_INFO: GF_LOG_DEBUG, "SSL support on the I/O path is %s", priv->ssl_enabled ? "ENABLED" : "NOT enabled"); gf_log(this->name, priv->mgmt_ssl ? GF_LOG_INFO: GF_LOG_DEBUG, @@@@ -3986,18 +3946,28 @@@@ gf_log(this->name, priv->own_thread ? GF_LOG_INFO: GF_LOG_DEBUG, "using %s polling thread", priv->own_thread ? "private" : "system"); - if (!dict_get_int32 (this->options, "ssl-cert-depth", &cert_depth)) { + if (!dict_get_int32 (this->options, SSL_CERT_DEPTH_OPT, &cert_depth)) { gf_log (this->name, GF_LOG_INFO, "using certificate depth %d", cert_depth); } - if (!dict_get_str (this->options, "ssl-cipher-list", &cipher_list)) { + if (!dict_get_str (this->options, SSL_CIPHER_LIST_OPT, &cipher_list)) { gf_log (this->name, GF_LOG_INFO, "using cipher list %s", cipher_list); } + if (!dict_get_str (this->options, SSL_DH_PARAM_OPT, &dh_param)) { + gf_log (this->name, GF_LOG_INFO, + "using DH parameters %s", dh_param); + } + if (!dict_get_str (this->options, SSL_EC_CURVE_OPT, &ec_curve)) { + gf_log (this->name, GF_LOG_INFO, + "using EC curve %s", ec_curve); + } if (priv->ssl_enabled || priv->mgmt_ssl) { + BIO *bio = NULL; + /* * The right time to check this is after all of our relevant * fields have been set, but before we start issuing OpenSSL * calls for the current translator. In other words, now. @@@@ -4010,20 +3980,96 @@@@ } #if HAVE_TLSV1_2_METHOD priv->ssl_meth = (SSL_METHOD *)TLSv1_2_method(); -#else /* old openssl */ -#warning TLSv1.2 is not available, using insecure TLSv1 support - priv->ssl_meth = (SSL_METHOD *)TLSv1_method(); +#else +/* + * Nobody should use an OpenSSL so old it does not support TLS 1.2. + * If that is really required, build with -DUSE_INSECURE_OPENSSL + */ +#ifndef USE_INSECURE_OPENSSL +#error Old and insecure OpenSSL, use -DUSE_INSECURE_OPENSSL to use it anyway +#endif + /* SSLv23_method uses highest available protocol */ + priv->ssl_meth = (SSL_METHOD *)SSLv23_method(); #endif priv->ssl_ctx = SSL_CTX_new(priv->ssl_meth); + SSL_CTX_set_options(priv->ssl_ctx, SSL_OP_NO_SSLv2); + SSL_CTX_set_options(priv->ssl_ctx, SSL_OP_NO_SSLv3); + SSL_CTX_set_options(priv->ssl_ctx, SSL_OP_NO_TICKET); + SSL_CTX_set_options(priv->ssl_ctx, SSL_OP_NO_COMPRESSION); + + if ((bio = BIO_new_file(dh_param, "r")) == NULL) { + gf_log(this->name,GF_LOG_ERROR, + "failed to open %s, " + "DH ciphers are disabled", dh_param); + } + + if (bio != NULL) { +#ifdef ERR_R_DH_LIB + DH *dh; + unsigned long err; + + dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + if (dh != NULL) { + SSL_CTX_set_options(priv->ssl_ctx, + SSL_OP_SINGLE_DH_USE); + SSL_CTX_set_tmp_dh(priv->ssl_ctx, dh); + DH_free(dh); + } else { + err = ERR_get_error(); + gf_log(this->name,GF_LOG_ERROR, + "failed to read DH param from %s: %s " + "DH ciphers are disabled.", + dh_param, ERR_error_string(err, NULL)); + } +#else /* ERR_R_DH_LIB */ + BIO_free(bio); + gf_log(this->name, GF_LOG_ERROR, + "OpenSSL has no DH support"); +#endif /* ERR_R_DH_LIB */ + } + + if (ec_curve != NULL) { +#ifdef ERR_R_ECDH_LIB + EC_KEY *ecdh = NULL; + int nid; + unsigned long err; + + nid = OBJ_sn2nid(ec_curve); + if (nid != 0) + ecdh = EC_KEY_new_by_curve_name(nid); + + if (ecdh != NULL) { + SSL_CTX_set_options(priv->ssl_ctx, + SSL_OP_SINGLE_ECDH_USE); + SSL_CTX_set_tmp_ecdh(priv->ssl_ctx, ecdh); + EC_KEY_free(ecdh); + } else { + err = ERR_get_error(); + gf_log(this->name, GF_LOG_ERROR, + "failed to load EC curve %s: %s. " + "ECDH ciphers are disabled.", + ec_curve, ERR_error_string(err, NULL)); + } +#else /* ERR_R_ECDH_LIB */ + gf_log(this->name, GF_LOG_ERROR, + "OpenSSL has no ECDH support"); +#endif /* ERR_R_ECDH_LIB */ + } + + /* This must be done after DH and ECDH setups */ if (SSL_CTX_set_cipher_list(priv->ssl_ctx, cipher_list) == 0) { gf_log(this->name,GF_LOG_ERROR, "failed to find any valid ciphers"); goto err; } + SSL_CTX_set_options(priv->ssl_ctx, + SSL_OP_CIPHER_SERVER_PREFERENCE); + if (!SSL_CTX_use_certificate_chain_file(priv->ssl_ctx, priv->ssl_own_cert)) { gf_log(this->name,GF_LOG_ERROR, "could not load our cert"); @@@@ -4038,9 +4084,10 @@@@ goto err; } if (!SSL_CTX_load_verify_locations(priv->ssl_ctx, - priv->ssl_ca_list,0)) { + priv->ssl_ca_list, + crl_path)) { gf_log(this->name,GF_LOG_ERROR, "could not load CA list"); goto err; } @@@@ -4048,8 +4095,21 @@@@ #if (OPENSSL_VERSION_NUMBER < 0x00905100L) SSL_CTX_set_verify_depth(ctx,cert_depth); #endif + if (crl_path) { +#ifdef X509_V_FLAG_CRL_CHECK_ALL + X509_STORE *x509store; + + x509store = SSL_CTX_get_cert_store(priv->ssl_ctx); + X509_STORE_set_flags(x509store, + X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); +#else + gf_log(this->name,GF_LOG_ERROR, + "OpenSSL version does not support CRL"); +#endif + } + priv->ssl_session_id = ++session_id; SSL_CTX_set_session_id_context(priv->ssl_ctx, (void *)&priv->ssl_session_id, sizeof(priv->ssl_session_id)); @@@@ -4201,21 +4261,61 @@@@ }, { .key = {SSL_CA_LIST_OPT}, .type = GF_OPTION_TYPE_STR }, + { .key = {SSL_CERT_DEPTH_OPT}, + .type = GF_OPTION_TYPE_STR + }, + { .key = {SSL_CIPHER_LIST_OPT}, + .type = GF_OPTION_TYPE_STR + }, + { .key = {SSL_DH_PARAM_OPT}, + .type = GF_OPTION_TYPE_STR + }, + { .key = {SSL_EC_CURVE_OPT}, + .type = GF_OPTION_TYPE_STR + }, + { .key = {SSL_CRL_PATH_OPT}, + .type = GF_OPTION_TYPE_STR + }, { .key = {OWN_THREAD_OPT}, .type = GF_OPTION_TYPE_BOOL }, - { .key = {"ssl-cert-depth"}, - .type = GF_OPTION_TYPE_INT, + { .key = {"ssl-own-cert"}, + .type = GF_OPTION_TYPE_STR, + .description = "SSL certificate. Ignored if SSL is not enabled." + }, + { .key = {"ssl-private-key"}, + .type = GF_OPTION_TYPE_STR, + .description = "SSL private key. Ignored if SSL is not enabled." + }, + { .key = {"ssl-ca-list"}, + .type = GF_OPTION_TYPE_STR, + .description = "SSL CA list. Ignored if SSL is not enabled." + }, + { .key = {"ssl-cert-depth"}, + .type = GF_OPTION_TYPE_INT, .description = "Maximum certificate-chain depth. If zero, the " "peer's certificate itself must be in the local " "certificate list. Otherwise, there may be up to N " "signing certificates between the peer's and the " "local list. Ignored if SSL is not enabled." }, - { .key = {"ssl-cipher-list"}, - .type = GF_OPTION_TYPE_STR, - .description = "Allowed SSL ciphers Ignored if SSL is not enabled." + { .key = {"ssl-cipher-list"}, + .type = GF_OPTION_TYPE_STR, + .description = "Allowed SSL ciphers. Ignored if SSL is not enabled." + }, + { .key = {"ssl-dh-param"}, + .type = GF_OPTION_TYPE_STR, + .description = "DH parameters file. Ignored if SSL is not enabled." + }, + { .key = {"ssl-ec-curve"}, + .type = GF_OPTION_TYPE_STR, + .description = "ECDH curve name. Ignored if SSL is not enabled." + }, + { .key = {"ssl-crl-path"}, + .type = GF_OPTION_TYPE_STR, + .description = "Path to directory containing CRL. " + "Ignored if SSL is not enabled." }, { .key = {NULL} } }; --- ./rpc/rpc-transport/socket/src/socket.h.orig 2015-07-28 08:28:30.000000000 +0200 +++ ./rpc/rpc-transport/socket/src/socket.h 2015-07-28 10:36:56.000000000 +0200 @@@@ -12,8 +12,15 @@@@ #define _SOCKET_H #include #include +#ifdef ERR_R_DH_LIB +#include +#endif +#ifdef ERR_R_ECDH_LIB +#include +#include +#endif #ifndef _CONFIG_H #define _CONFIG_H #include "config.h" --- ./tests/features/openssl.cnf.in.orig 2015-07-28 10:36:56.000000000 +0200 +++ ./tests/features/openssl.cnf.in 2015-07-28 10:36:56.000000000 +0200 @@@@ -0,0 +1,41 @@@@ +[ req ] +distinguished_name = req_distinguished_name +x509_extensions = v3_ca +[ req_distinguished_name ] +commonName = Common Name +commonName_max = 64 +[ v3_ca ] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always +basicConstraints = CA:true +[ ca ] +default_ca = CA_default +[ CA_default ] +dir = @@TMPDIR@@ +certs = $dir/certs +crl_dir = $dir/crl +database = $dir/index.txt +unique_subjecta = no +new_certs_dir = $dir/newcerts +certificate = $dir/ca.crt +serial = $dir/serial +crl = $dir/crl.pem +private_key = $dir/self.key +x509_extensions = usr_cert +name_opt = ca_default +cert_opt = ca_default +default_days = 365 +default_crl_days = 30 +crl_extensions = crl_ext +default_md = sha256 +preserve = no +policy = policy_test +[ policy_test ] +commonName = supplied +[ usr_cert ] +basicConstraints = CA:FALSE +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always +crlDistributionPoints = URI:file://@@TMPDIR@@/crl.pem +[ crl_ext ] +authorityKeyIdentifier = keyid:always,issuer:always --- ./tests/features/dh1024.pem.orig 2015-07-28 10:36:56.000000000 +0200 +++ ./tests/features/dh1024.pem 2015-07-28 10:36:56.000000000 +0200 @@@@ -0,0 +1,5 @@@@ +-----BEGIN DH PARAMETERS----- +MIGHAoGBAL2k+efZ6g50PpL41G96IaRw2OTH921yhHMNSXBE/K+R6oTkJFcNJs1N +q+a1Ko2xCBDa5MgvudqWep6PvE06rzEaJPW8ITdu8j3Eo9T1rorJ3CctpE/CaRl2 +7v4DNe+Mho6q1MPlG5PfXEZWgbT7tjn/Y6lwD/B2CoMzAx+4DXgbAgEC +-----END DH PARAMETERS----- --- ./tests/features/ssl-ciphers.t.orig 2015-07-28 10:36:56.000000000 +0200 +++ ./tests/features/ssl-ciphers.t 2015-07-28 10:36:56.000000000 +0200 @@@@ -0,0 +1,204 @@@@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc + +brick_port() { + $CLI volume status $1 | awk ' + ($3 == "") { p = $0; next; } + { $0 = p $0; p = ""; } + /^Brick/ { print $3; } + ' +} + +wait_mount() { + i=1 + while [ $i -lt $CONFIG_UPDATE_TIMEOUT ] ; do + sleep 1 + i=$(( $i + 1 )) + mounted=`mount|awk -v m=$1 ' + BEGIN {r = "N";} + ($3 == m) {r = "Y"; exit;} + END {print r;} + '` + if [ "x${mounted}" = "xY" ] ; then + ls $M0 2>/dev/null || continue + break; + fi + done + + if [ "x${mounted}" = "xY" ] ; then + ls $M0 2>/dev/null || mounted="N" + fi + + echo $mounted +} + +openssl_connect() { + ssl_opt="-verify 3 -verify_return_error -CAfile $SSL_CA" + ssl_opt="$ssl_opt -crl_check_all -CApath $TMPDIR" + CIPHER=`echo "" | + openssl s_client $ssl_opt $@@ 2>/dev/null | + awk '/^ Cipher/{print $3}'` + if [ "x${CIPHER}" = "x" -o "x${CIPHER}" = "x0000" ] ; then + echo "N" + else + echo "Y" + fi +} + +cleanup; +mkdir -p $B0 +mkdir -p $M0 + +TMPDIR=`mktemp -d /tmp/${0##*/}.XXXXXX` +TEST test -d $TMPDIR + +SSL_KEY=$TMPDIR/self.key +SSL_CSR=$TMPDIR/self.csr +SSL_CERT=$TMPDIR/self.crt +SSL_CA=$TMPDIR/ca.crt +SSL_CFG=$TMPDIR/openssl.cnf +SSL_CRL=$TMPDIR/crl.pem + +sed "s|@@TMPDIR@@|${TMPDIR}|" `pwd`/`dirname $0`/openssl.cnf.in > $SSL_CFG + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume info; + +TEST openssl genrsa -out $SSL_KEY 1024 2>/dev/null +TEST openssl req -config $SSL_CFG -new -key $SSL_KEY -x509 \ + -subj /CN=CA -out $SSL_CA +TEST openssl req -config $SSL_CFG -new -key $SSL_KEY \ + -subj /CN=$H0 -out $SSL_CSR + +echo "01" > $TMPDIR/serial +TEST touch $TMPDIR/index.txt $TMPDIR/index.txx.attr +TEST mkdir -p $TMPDIR/certs $TMPDIR/newcerts $TMPDIR/crl +TEST openssl ca -batch -config $SSL_CFG -in $SSL_CSR -out $SSL_CERT 2>&1 + +touch $SSL_CRL +CRLHASH=`openssl x509 -hash -fingerprint -noout -in $SSL_CA|sed -n '1s/$/.r0/p'` +ln -sf $SSL_CRL $TMPDIR/$CRLHASH +TEST openssl ca -config $SSL_CFG -gencrl -out $SSL_CRL 2>&1 + + +TEST $CLI volume create $V0 $H0:$B0/1 +TEST $CLI volume set $V0 server.ssl on +TEST $CLI volume set $V0 client.ssl on +TEST $CLI volume set $V0 ssl.private-key $SSL_KEY +TEST $CLI volume set $V0 ssl.own-cert $SSL_CERT +TEST $CLI volume set $V0 ssl.ca-list $SSL_CA +TEST $CLI volume start $V0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" online_brick_count + +BRICK_PORT=`brick_port $V0` + +# Test we can connect +EXPECT "Y" openssl_connect -connect $H0:$BRICK_PORT + +# Test SSLv2 protocol fails +EXPECT "N" openssl_connect -ssl2 -connect $H0:$BRICK_PORT + +# Test SSLv3 protocol fails +EXPECT "N" openssl_connect -ssl3 -connect $H0:$BRICK_PORT + +# Test TLSv1 protocol fails +EXPECT "N" openssl_connect -tls1 -connect $H0:$BRICK_PORT + +# Test a HIGH CBC cipher +EXPECT "Y" openssl_connect -cipher AES256-SHA -connect $H0:$BRICK_PORT + +# Test EECDH +EXPECT "Y" openssl_connect -cipher EECDH -connect $H0:$BRICK_PORT + +# test MD5 fails +EXPECT "N" openssl_connect -cipher DES-CBC3-MD5 -connect $H0:$BRICK_PORT + +# test RC4 fails +EXPECT "N" openssl_connect -cipher RC4-SHA -connect $H0:$BRICK_PORT + +# test eNULL fails +EXPECT "N" openssl_connect -cipher NULL-SHA256 -connect $H0:$BRICK_PORT + +# test SHA2 +EXPECT "Y" openssl_connect -cipher AES256-SHA256 -connect $H0:$BRICK_PORT + +# test GCM +EXPECT "Y" openssl_connect -cipher AES256-GCM-SHA384 -connect $H0:$BRICK_PORT + +# Test DH fails without DH params +EXPECT "N" openssl_connect -cipher EDH -connect $H0:$BRICK_PORT + +# Test DH with DH params +TEST $CLI volume set $V0 ssl.dh-param `pwd`/`dirname $0`/dh1024.pem +EXPECT "`pwd`/`dirname $0`/dh1024.pem" volume_option $V0 ssl.dh-param +TEST $CLI volume stop $V0 +TEST $CLI volume start $V0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" online_brick_count +EXPECT "Y" openssl_connect -cipher EDH -connect $H0:$BRICK_PORT + +# Test the cipher-list option +TEST $CLI volume set $V0 ssl.cipher-list AES256-SHA +EXPECT AES256-SHA volume_option $V0 ssl.cipher-list +TEST $CLI volume stop $V0 +TEST $CLI volume start $V0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" online_brick_count +EXPECT "Y" openssl_connect -cipher AES256-SHA -connect $H0:$BRICK_PORT +EXPECT "N" openssl_connect -cipher AES128-SHA -connect $H0:$BRICK_PORT + +# Test the ec-curve option +TEST $CLI volume set $V0 ssl.cipher-list EECDH:EDH:!TLSv1 +EXPECT EECDH:EDH:!TLSv1 volume_option $V0 ssl.cipher-list +TEST $CLI volume stop $V0 +TEST $CLI volume start $V0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" online_brick_count +EXPECT "N" openssl_connect -cipher AES256-SHA -connect $H0:$BRICK_PORT +EXPECT "Y" openssl_connect -cipher EECDH -connect $H0:$BRICK_PORT + +TEST $CLI volume set $V0 ssl.ec-curve invalid +EXPECT invalid volume_option $V0 ssl.ec-curve +TEST $CLI volume stop $V0 +TEST $CLI volume start $V0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" online_brick_count +EXPECT "N" openssl_connect -cipher EECDH -connect $H0:$BRICK_PORT + +TEST $CLI volume set $V0 ssl.ec-curve secp521r1 +EXPECT secp521r1 volume_option $V0 ssl.ec-curve +TEST $CLI volume stop $V0 +TEST $CLI volume start $V0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" online_brick_count +EXPECT "Y" openssl_connect -cipher EECDH -connect $H0:$BRICK_PORT + +# test revocation +# no need to restart the volume since the options are used +# by the client here. +TEST $CLI volume set $V0 ssl.crl-path $TMPDIR +EXPECT $TMPDIR volume_option $V0 ssl.crl-path +$GFS --volfile-id=$V0 --volfile-server=$H0 $M0 +EXPECT "Y" wait_mount $M0 +TEST_FILE=`mktemp $M0/${0##*/}.XXXXXX` +TEST test -f $TEST_FILE +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 + +TEST openssl ca -batch -config $SSL_CFG -revoke $SSL_CERT 2>&1 +TEST openssl ca -config $SSL_CFG -gencrl -out $SSL_CRL 2>&1 + +# Failed once revoked +$GFS --volfile-id=$V0 --volfile-server=$H0 $M0 +EXPECT "N" wait_mount $M0 +TEST ! test -f $TEST_FILE +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 + +# Succeed with CRL disabled +TEST $CLI volume set $V0 ssl.crl-path NULL +EXPECT NULL volume_option $V0 ssl.crl-path +$GFS --volfile-id=$V0 --volfile-server=$H0 $M0 +EXPECT "Y" wait_mount $M0 +TEST test -f $TEST_FILE + +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 + +rm -rf $TMPDIR +cleanup; @ 1.1 log @Upgrade glusterfs to 3.7.3 This is a maintenance upgrade, complete bugfix list is available from distribution ChangeLog @ text @d1 1 a1 1 $NetBSD$ @