diff options
| -rw-r--r-- | libglusterfs/src/globals.h | 4 | ||||
| -rw-r--r-- | rpc/rpc-transport/socket/src/socket.c | 260 | ||||
| -rw-r--r-- | tests/features/dh1024.pem | 5 | ||||
| -rw-r--r-- | tests/features/openssl.cnf.in | 41 | ||||
| -rw-r--r-- | tests/features/ssl-ciphers.t | 204 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volgen.c | 131 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volgen.h | 6 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volume-set.c | 30 | 
8 files changed, 523 insertions, 158 deletions
diff --git a/libglusterfs/src/globals.h b/libglusterfs/src/globals.h index 8b513d03646..3f91363a7c9 100644 --- a/libglusterfs/src/globals.h +++ b/libglusterfs/src/globals.h @@ -37,7 +37,7 @@   */  #define GD_OP_VERSION_MIN  1 /* MIN is the fresh start op-version, mostly                                  should not change */ -#define GD_OP_VERSION_MAX  GD_OP_VERSION_3_7_3 /* MAX VERSION is the maximum +#define GD_OP_VERSION_MAX  GD_OP_VERSION_3_7_4 /* MAX VERSION is the maximum                                                    count in VME table, should                                                    keep changing with                                                    introduction of newer @@ -53,6 +53,8 @@  #define GD_OP_VERSION_3_7_3    30703 /* Op-version for GlusterFS 3.7.3 */ +#define GD_OP_VERSION_3_7_4    30704 /* Op-version for GlusterFS 3.7.4 */ +  #define GD_OP_VER_PERSISTENT_AFR_XATTRS GD_OP_VERSION_3_6_0  #include "xlator.h" diff --git a/rpc/rpc-transport/socket/src/socket.c b/rpc/rpc-transport/socket/src/socket.c index d7b639c95ee..52b3e4bebd4 100644 --- a/rpc/rpc-transport/socket/src/socket.c +++ b/rpc/rpc-transport/socket/src/socket.c @@ -44,74 +44,13 @@  #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 @@ -127,6 +66,7 @@ static char *default_cipher_list =  #    define DEFAULT_ETC_SSL "/etc/ssl"  #  endif  #endif +  #if !defined(DEFAULT_CERT_PATH)  #define DEFAULT_CERT_PATH   DEFAULT_ETC_SSL "/glusterfs.pem"  #endif @@ -136,6 +76,12 @@ static char *default_cipher_list =  #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) @@ -3774,9 +3720,11 @@ socket_init (rpc_transport_t *this)          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, @@ -3958,6 +3906,18 @@ socket_init (rpc_transport_t *this)  	}          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"); @@ -3982,16 +3942,26 @@ socket_init (rpc_transport_t *this)                 "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 @@ -4006,18 +3976,94 @@ socket_init (rpc_transport_t *this)  #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, @@ -4034,7 +4080,8 @@ socket_init (rpc_transport_t *this)  		}  		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; @@ -4044,6 +4091,19 @@ socket_init (rpc_transport_t *this)  		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, @@ -4197,20 +4257,60 @@ struct volume_options options[] = {  	{ .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} }  }; diff --git a/tests/features/dh1024.pem b/tests/features/dh1024.pem new file mode 100644 index 00000000000..fe514bd4ee5 --- /dev/null +++ b/tests/features/dh1024.pem @@ -0,0 +1,5 @@ +-----BEGIN DH PARAMETERS----- +MIGHAoGBAL2k+efZ6g50PpL41G96IaRw2OTH921yhHMNSXBE/K+R6oTkJFcNJs1N +q+a1Ko2xCBDa5MgvudqWep6PvE06rzEaJPW8ITdu8j3Eo9T1rorJ3CctpE/CaRl2 +7v4DNe+Mho6q1MPlG5PfXEZWgbT7tjn/Y6lwD/B2CoMzAx+4DXgbAgEC +-----END DH PARAMETERS----- diff --git a/tests/features/openssl.cnf.in b/tests/features/openssl.cnf.in new file mode 100644 index 00000000000..1fce34b11b9 --- /dev/null +++ b/tests/features/openssl.cnf.in @@ -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 diff --git a/tests/features/ssl-ciphers.t b/tests/features/ssl-ciphers.t new file mode 100644 index 00000000000..9ee7fc6c16f --- /dev/null +++ b/tests/features/ssl-ciphers.t @@ -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; diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c index 75f64fad2c0..5ac392c309e 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volgen.c +++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c @@ -37,6 +37,20 @@  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 @@ -2071,25 +2085,14 @@ brick_graph_add_server (volgen_graph_t *graph, glusterd_volinfo_t *volinfo,                          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)); @@ -2165,26 +2168,22 @@ brick_graph_add_pump (volgen_graph_t *graph, glusterd_volinfo_t *volinfo,                  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); @@ -2743,25 +2742,14 @@ volgen_graph_build_client (volgen_graph_t *graph, glusterd_volinfo_t *volinfo,                  }          } -        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: @@ -5007,25 +4995,14 @@ glusterd_snapdsvc_generate_volfile (volgen_graph_t *graph,          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); diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.h b/xlators/mgmt/glusterd/src/glusterd-volgen.h index 9a0c9798a9e..cbd3cf38d51 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volgen.h +++ b/xlators/mgmt/glusterd/src/glusterd-volgen.h @@ -40,8 +40,14 @@  #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 { diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-set.c b/xlators/mgmt/glusterd/src/glusterd-volume-set.c index f1413dbf525..eb079d072b6 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volume-set.c +++ b/xlators/mgmt/glusterd/src/glusterd-volume-set.c @@ -1077,6 +1077,26 @@ struct volopt_map_entry glusterd_volopt_map[] = {          },          /* Generic transport options */ +        { .key         = SSL_OWN_CERT_OPT, +          .voltype     = "rpc-transport/socket", +          .option      = "!ssl-own-cert", +          .op_version  = GD_OP_VERSION_3_7_4, +        }, +        { .key         = SSL_PRIVATE_KEY_OPT, +          .voltype     = "rpc-transport/socket", +          .option      = "!ssl-private-key", +          .op_version  = GD_OP_VERSION_3_7_4, +        }, +        { .key         = SSL_CA_LIST_OPT, +          .voltype     = "rpc-transport/socket", +          .option      = "!ssl-ca-list", +          .op_version  = GD_OP_VERSION_3_7_4, +        }, +        { .key         = SSL_CRL_PATH_OPT, +          .voltype     = "rpc-transport/socket", +          .option      = "!ssl-crl-path", +          .op_version  = GD_OP_VERSION_3_7_4, +        },          { .key         = SSL_CERT_DEPTH_OPT,            .voltype     = "rpc-transport/socket",            .option      = "!ssl-cert-depth", @@ -1087,6 +1107,16 @@ struct volopt_map_entry glusterd_volopt_map[] = {            .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_4, +        }, +        { .key        = SSL_EC_CURVE_OPT, +          .voltype     = "rpc-transport/socket", +          .option     = "!ssl-ec-curve", +          .op_version = GD_OP_VERSION_3_7_4, +        },          /* Performance xlators enable/disbable options */          { .key         = "performance.write-behind",  | 
