diff options
| -rw-r--r-- | cli/src/cli.c | 29 | ||||
| -rw-r--r-- | glusterfsd/src/glusterfsd.c | 23 | ||||
| -rw-r--r-- | glusterfsd/src/glusterfsd.h | 1 | ||||
| -rw-r--r-- | libglusterfs/src/glusterfs.h | 50 | ||||
| -rw-r--r-- | rpc/rpc-transport/socket/src/socket.c | 72 | ||||
| -rw-r--r-- | rpc/rpc-transport/socket/src/socket.h | 4 | ||||
| -rwxr-xr-x | tests/bugs/bug-873367.t | 8 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd.c | 37 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server.c | 6 | 
9 files changed, 197 insertions, 33 deletions
diff --git a/cli/src/cli.c b/cli/src/cli.c index 745b0b45bf5..fa3c747d154 100644 --- a/cli/src/cli.c +++ b/cli/src/cli.c @@ -297,7 +297,8 @@ cli_rpc_notify (struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event,  int  cli_opt_parse (char *opt, struct cli_state *state)  { -        char *oarg; +        char            *oarg           = NULL; +        gf_boolean_t    secure_mgmt_tmp = 0;          if (strcmp (opt, "") == 0)                  return 1; @@ -370,6 +371,20 @@ cli_opt_parse (char *opt, struct cli_state *state)                  return 0;          } +        oarg = strtail (opt, "secure-mgmt="); +        if (oarg) { +                if (gf_string2boolean(oarg,&secure_mgmt_tmp) == 0) { +                        if (secure_mgmt_tmp) { +                                /* See declaration for why this is an int. */ +                                state->ctx->secure_mgmt = 1; +                        } +                } +                else { +                        cli_err ("invalide secure-mgmt value (ignored)"); +                } +                return 0; +        } +          return -1;  } @@ -384,6 +399,11 @@ parse_cmdline (int argc, char *argv[], struct cli_state *state)          state->argc=argc-1;          state->argv=&argv[1]; +        /* Do this first so that an option can override. */ +        if (access(SECURE_ACCESS_FILE,F_OK) == 0) { +                state->ctx->secure_mgmt = 1; +        } +          for (i = 0; i < state->argc; i++) {                  opt = strtail (state->argv[i], "--");                  if (opt) { @@ -546,7 +566,6 @@ cli_rpc_init (struct cli_state *state)          int                     port = CLI_GLUSTERD_PORT;          xlator_t                *this = NULL; -          this = THIS;          cli_rpc_prog = &cli_prog;          options = dict_new (); @@ -565,7 +584,8 @@ cli_rpc_init (struct cli_state *state)                                                          0);                  if (ret)                          goto out; -        } else if (state->remote_host) { +        } +        else if (state->remote_host) {                  gf_log ("cli", GF_LOG_INFO, "Connecting to remote glusterd at "                          "%s", state->remote_host);                  ret = dict_set_str (options, "remote-host", state->remote_host); @@ -583,7 +603,8 @@ cli_rpc_init (struct cli_state *state)                                      "inet");                  if (ret)                          goto out; -        } else { +        } +        else {                  gf_log ("cli", GF_LOG_DEBUG, "Connecting to glusterd using "                          "default socket");                  ret = rpc_transport_unix_options_build diff --git a/glusterfsd/src/glusterfsd.c b/glusterfsd/src/glusterfsd.c index 79e6e593a53..3c92783cb3d 100644 --- a/glusterfsd/src/glusterfsd.c +++ b/glusterfsd/src/glusterfsd.c @@ -218,6 +218,8 @@ static struct argp_option gf_options[] = {          {"use-readdirp", ARGP_FUSE_USE_READDIRP_KEY, "BOOL", OPTION_ARG_OPTIONAL,           "Use readdirp mode in fuse kernel module"           " [default: \"off\"]"}, +        {"secure-mgmt", ARGP_SECURE_MGMT_KEY, "BOOL", OPTION_ARG_OPTIONAL, +         "Override default for secure (SSL) management connections"},          {0, 0, 0, 0, "Miscellaneous Options:"},          {0, }  }; @@ -1145,6 +1147,19 @@ parse_opts (int key, char *arg, struct argp_state *state)                  }                  break; + +        case ARGP_SECURE_MGMT_KEY: +                if (!arg) +                        arg = "yes"; + +                if (gf_string2boolean (arg, &b) == 0) { +                        cmd_args->secure_mgmt = b ? 1 : 0; +                        break; +                } + +                argp_failure (state, -1, 0, +                              "unknown secure-mgmt setting \"%s\"", arg); +                break;  	}          return 0; @@ -1493,8 +1508,15 @@ parse_cmdline (int argc, char *argv[], glusterfs_ctx_t *ctx)          cmd_args = &ctx->cmd_args; +        /* Do this before argp_parse so it can be overridden. */ +        if (access(SECURE_ACCESS_FILE,F_OK) == 0) { +                cmd_args->secure_mgmt = 1; +        } +          argp_parse (&argp, argc, argv, ARGP_IN_ORDER, NULL, cmd_args); +        ctx->secure_mgmt = cmd_args->secure_mgmt; +          if (ENABLE_DEBUG_MODE == cmd_args->debug_mode) {                  cmd_args->log_level = GF_LOG_DEBUG;                  cmd_args->log_file = gf_strdup ("/dev/stderr"); @@ -1985,6 +2007,7 @@ main (int argc, char *argv[])          if (ret)                  goto out; +          /* log the version of glusterfs running here along with the actual             command line options. */          { diff --git a/glusterfsd/src/glusterfsd.h b/glusterfsd/src/glusterfsd.h index a75369a24f5..41f7b1d9a38 100644 --- a/glusterfsd/src/glusterfsd.h +++ b/glusterfsd/src/glusterfsd.h @@ -91,6 +91,7 @@ enum argp_option_keys {          ARGP_LOG_FORMAT                   = 169,          ARGP_LOG_BUF_SIZE                 = 170,          ARGP_LOG_FLUSH_TIMEOUT            = 171, +        ARGP_SECURE_MGMT_KEY              = 172,  };  struct _gfd_vol_top_priv_t { diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h index 4867da42aff..3b0cc4b4eaa 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -414,6 +414,9 @@ struct _cmd_args {          int             brick_port;          char           *brick_name;          int             brick_port2; + +        /* Should management connections use SSL? */ +        int             secure_mgmt;  };  typedef struct _cmd_args cmd_args_t; @@ -435,6 +438,13 @@ typedef struct _glusterfs_graph glusterfs_graph_t;  typedef int32_t (*glusterfsd_mgmt_event_notify_fn_t) (int32_t event, void *data,                                                        ...); + +typedef enum { +        MGMT_SSL_NEVER = 0, +        MGMT_SSL_COPY_IO, +        MGMT_SSL_ALWAYS +} mgmt_ssl_t; +  struct _glusterfs_ctx {          cmd_args_t          cmd_args;          char               *process_uuid; @@ -483,6 +493,26 @@ struct _glusterfs_ctx {          int                 daemon_pipe[2];          struct clienttable *clienttable; + +        /* +         * Should management connections use SSL?  This is the only place we +         * can put it where both daemon-startup and socket code will see it. +         * +         * Why is it an int?  Because we're included before common-utils.h, +         * which defines gf_boolean_t (what we really want).  It doesn't make +         * any sense, but it's not worth turning the codebase upside-down to +         * fix it.  Thus, an int. +         */ +        int                 secure_mgmt; + +        /* +         * Should *our* server/inbound connections use SSL?  This is only true +         * if we're glusterd and secure_mgmt is set, or if we're glusterfsd +         * and SSL is set on the I/O path.  It should never be set e.g. for +         * NFS. +         */ +        mgmt_ssl_t          secure_srvr; +  };  typedef struct _glusterfs_ctx glusterfs_ctx_t; @@ -528,6 +558,26 @@ struct gf_flock {   */  #define GF_UNUSED __attribute__((unused)) +/* + * If present, this has the following effects: + * + *      glusterd enables privileged commands over TCP + * + *      all code enables SSL for outbound connections to management port + * + *      glusterd enables SSL for inbound connections + * + * Servers and clients enable/disable SSL among themselves by other means. + * Making secure management connections conditional on a file is a bit of a + * hack, but we don't have any other place for such global settings across + * all of the affected components.  Making it a compile-time option would + * reduce functionality, both for users and for testing (which can now be + * done using secure connections for all tests without change elsewhere). + * + * Nonetheless, TBD: define in terms of build-time PREFIX + */ +#define SECURE_ACCESS_FILE      "/var/lib/glusterd/secure-access" +  int glusterfs_graph_prepare (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx);  int glusterfs_graph_destroy (glusterfs_graph_t *graph);  int glusterfs_graph_activate (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx); diff --git a/rpc/rpc-transport/socket/src/socket.c b/rpc/rpc-transport/socket/src/socket.c index ccef2f605cc..e969a5cf7fd 100644 --- a/rpc/rpc-transport/socket/src/socket.c +++ b/rpc/rpc-transport/socket/src/socket.c @@ -318,6 +318,7 @@ ssl_teardown_connection (socket_private_t *priv)          SSL_clear(priv->ssl_ssl);          SSL_free(priv->ssl_ssl);          priv->ssl_ssl = NULL; +        priv->use_ssl = _gf_false;  } @@ -2563,12 +2564,29 @@ socket_server_event_handler (int fd, int idx, void *data,                          new_trans->listener = this;                          new_priv = new_trans->private; -			new_priv->use_ssl = priv->use_ssl; +                        if (new_sockaddr.ss_family == AF_UNIX) { +                                new_priv->use_ssl = _gf_false; +                        } +                        else { +                                switch (priv->srvr_ssl) { +                                case MGMT_SSL_ALWAYS: +                                        /* Glusterd with secure_mgmt. */ +                                        new_priv->use_ssl = _gf_true; +                                        break; +                                case MGMT_SSL_COPY_IO: +                                        /* Glusterfsd. */ +                                        new_priv->use_ssl = priv->ssl_enabled; +                                        break; +                                default: +                                        new_priv->use_ssl = _gf_false; +                                } +                        } +  			new_priv->sock = new_sock;  			new_priv->own_thread = priv->own_thread;                          new_priv->ssl_ctx = priv->ssl_ctx; -			if (priv->use_ssl && !priv->own_thread) { +			if (new_priv->use_ssl && !new_priv->own_thread) {  				cname = ssl_setup_connection(new_trans,1);                                  if (!cname) {  					gf_log(this->name,GF_LOG_ERROR, @@ -2692,6 +2710,23 @@ socket_connect_error_cbk (void *opaque)          return NULL;  } +static void +socket_fix_ssl_opts (rpc_transport_t *this, socket_private_t *priv, +                     uint16_t port) +{ +        if (port == GF_DEFAULT_SOCKET_LISTEN_PORT) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "%s SSL for portmapper connection", +                        priv->mgmt_ssl ? "enabling" : "disabling"); +                priv->use_ssl = priv->mgmt_ssl; +        } +        else if (priv->ssl_enabled && !priv->use_ssl) { +                gf_log(this->name,GF_LOG_DEBUG, +                       "re-enabling SSL for I/O connection"); +                priv->use_ssl = _gf_true; +        } +} +  static int  socket_connect (rpc_transport_t *this, int port)  { @@ -2744,23 +2779,16 @@ socket_connect (rpc_transport_t *this, int port)                          goto unlock;                  } -                if (port > 0) { -                        sock_union.sin.sin_port = htons (port); -                } -                if (ntohs(sock_union.sin.sin_port) == -                    GF_DEFAULT_SOCKET_LISTEN_PORT) { -                        if (priv->use_ssl) { -                                gf_log(this->name,GF_LOG_DEBUG, -                                "disabling SSL for portmapper connection"); -                                priv->use_ssl = _gf_false; -                        } +                if (sa_family == AF_UNIX) { +                        priv->ssl_enabled = _gf_false; +                        priv->mgmt_ssl = _gf_false;                  }                  else { -                        if (priv->ssl_enabled && !priv->use_ssl) { -                                gf_log(this->name,GF_LOG_DEBUG, -                                       "re-enabling SSL for I/O connection"); -                                priv->use_ssl = _gf_true; +                        if (port > 0) { +                                sock_union.sin.sin_port = htons (port);                          } +                        socket_fix_ssl_opts (this, priv, +                                             ntohs(sock_union.sin.sin_port));                  }                  memcpy (&this->peerinfo.sockaddr, &sock_union.storage, @@ -3621,6 +3649,8 @@ socket_init (rpc_transport_t *this)  				"invalid value given for ssl-enabled boolean");  		}  	} +        priv->mgmt_ssl = this->ctx->secure_mgmt; +        priv->srvr_ssl = this->ctx->secure_srvr;          priv->ssl_own_cert = DEFAULT_CERT_PATH;  	if (dict_get_str(this->options,SSL_OWN_CERT_OPT,&optstr) == 0) { @@ -3656,8 +3686,11 @@ socket_init (rpc_transport_t *this)          priv->ssl_ca_list = gf_strdup(priv->ssl_ca_list);          gf_log(this->name, priv->ssl_enabled ? GF_LOG_INFO: GF_LOG_DEBUG, -               "SSL support is %s", +               "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, +               "SSL support for glusterd is %s", +               priv->mgmt_ssl ? "ENABLED" : "NOT enabled");          /*           * This might get overridden temporarily in socket_connect (q.v.)           * if we're using the glusterd portmapper. @@ -3666,8 +3699,9 @@ socket_init (rpc_transport_t *this)  	priv->own_thread = priv->use_ssl;  	if (dict_get_str(this->options,OWN_THREAD_OPT,&optstr) == 0) { +                gf_log (this->name, GF_LOG_INFO, "OWN_THREAD_OPT found");                  if (gf_string2boolean (optstr, &priv->own_thread) != 0) { -                        gf_log (this->name, GF_LOG_ERROR, +                        gf_log (this->name, GF_LOG_WARNING,  				"invalid value given for own-thread boolean");  		}  	} @@ -3684,7 +3718,7 @@ socket_init (rpc_transport_t *this)                          "using cipher list %s", cipher_list);          } -	if (priv->use_ssl) { +	if (priv->ssl_enabled || priv->mgmt_ssl) {  		SSL_library_init();  		SSL_load_error_strings();  		priv->ssl_meth = (SSL_METHOD *)TLSv1_method(); diff --git a/rpc/rpc-transport/socket/src/socket.h b/rpc/rpc-transport/socket/src/socket.h index e0b412fcce1..33c936938eb 100644 --- a/rpc/rpc-transport/socket/src/socket.h +++ b/rpc/rpc-transport/socket/src/socket.h @@ -217,7 +217,9 @@ typedef struct {          int                    keepaliveintvl;          uint32_t               backlog;          gf_boolean_t           read_fail_log; -        gf_boolean_t           ssl_enabled; +        gf_boolean_t           ssl_enabled;     /* outbound I/O */ +        gf_boolean_t           mgmt_ssl;        /* outbound mgmt */ +        mgmt_ssl_t             srvr_ssl;  	gf_boolean_t           use_ssl;  	SSL_METHOD            *ssl_meth;  	SSL_CTX               *ssl_ctx; diff --git a/tests/bugs/bug-873367.t b/tests/bugs/bug-873367.t index 4849c2fea31..771c8628219 100755 --- a/tests/bugs/bug-873367.t +++ b/tests/bugs/bug-873367.t @@ -13,14 +13,14 @@ rm -f $SSL_BASE/glusterfs.*  mkdir -p $B0/1  mkdir -p $M0 -TEST glusterd -TEST pidof glusterd -TEST $CLI volume info; -  TEST openssl genrsa -out $SSL_KEY 1024  TEST openssl req -new -x509 -key $SSL_KEY -subj /CN=Anyone -out $SSL_CERT  ln $SSL_CERT $SSL_CA +TEST glusterd +TEST pidof glusterd +TEST $CLI volume info; +  TEST $CLI volume create $V0 $H0:$B0/1  TEST $CLI volume set $V0 server.ssl on  TEST $CLI volume set $V0 client.ssl on diff --git a/xlators/mgmt/glusterd/src/glusterd.c b/xlators/mgmt/glusterd/src/glusterd.c index 3e8a3e2e17a..adf58cc7dde 100644 --- a/xlators/mgmt/glusterd/src/glusterd.c +++ b/xlators/mgmt/glusterd/src/glusterd.c @@ -68,7 +68,7 @@ rpcsvc_cbk_program_t glusterd_cbk_prog = {  struct rpcsvc_program *gd_inet_programs[] = {          &gd_svc_peer_prog, -        &gd_svc_cli_trusted_progs, +        &gd_svc_cli_trusted_progs, /* Must be index 1 for secure_mgmt! */          &gd_svc_mgmt_prog,          &gd_svc_mgmt_v3_prog,          &gluster_pmap_prog, @@ -1327,8 +1327,34 @@ init (xlator_t *this)                  goto out;          } +        if (this->ctx->secure_mgmt) { +                /* +                 * The socket code will turn on SSL based on the same check, +                 * but that will by default turn on own-thread as well and +                 * we're not multi-threaded enough to handle that.  Thus, we +                 * override the value here. +                 */ +                ret = dict_set_str (this->options, +                                    "transport.socket.own-thread", "off"); +                if (ret != 0) { +                        gf_log (this->name, GF_LOG_ERROR, +                                "failed to clear own-thread"); +                        goto out; +                } +                /* +                 * With strong authentication, we can afford to allow +                 * privileged operations over TCP. +                 */ +                gd_inet_programs[1] = &gd_svc_cli_prog; +                /* +                 * This is the only place where we want secure_srvr to reflect +                 * the management-plane setting. +                 */ +                this->ctx->secure_srvr = MGMT_SSL_ALWAYS; +        } +          /* -         * only one (atmost a pair - rdma and socket) listener for +         * only one (at most a pair - rdma and socket) listener for           * glusterd1_mop_prog, gluster_pmap_prog and gluster_handshake_prog.           */          ret = rpcsvc_create_listeners (rpc, this->options, this->name); @@ -1352,9 +1378,10 @@ init (xlator_t *this)                  }          } -        /* Start a unix domain socket listener just for cli commands -         * This should prevent ports from being wasted by being in TIMED_WAIT -         * when cli commands are done continuously +        /* +         * Start a unix domain socket listener just for cli commands This +         * should prevent ports from being wasted by being in TIMED_WAIT when +         * cli commands are done continuously           */          uds_rpc = glusterd_init_uds_listener (this);          if (uds_rpc == NULL) { diff --git a/xlators/protocol/server/src/server.c b/xlators/protocol/server/src/server.c index 3de856e8e09..6c4f81067cb 100644 --- a/xlators/protocol/server/src/server.c +++ b/xlators/protocol/server/src/server.c @@ -913,6 +913,12 @@ init (xlator_t *this)                  goto out;          } +        /* +         * This is the only place where we want secure_srvr to reflect +         * the data-plane setting. +         */ +        this->ctx->secure_srvr = MGMT_SSL_COPY_IO; +          ret = rpcsvc_create_listeners (conf->rpc, this->options,                                         this->name);          if (ret < 1) {  | 
