summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cli/src/cli.c29
-rw-r--r--glusterfsd/src/glusterfsd.c23
-rw-r--r--glusterfsd/src/glusterfsd.h1
-rw-r--r--libglusterfs/src/glusterfs.h50
-rw-r--r--rpc/rpc-transport/socket/src/socket.c72
-rw-r--r--rpc/rpc-transport/socket/src/socket.h4
-rwxr-xr-xtests/bugs/bug-873367.t8
-rw-r--r--xlators/mgmt/glusterd/src/glusterd.c37
-rw-r--r--xlators/protocol/server/src/server.c6
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) {