>From 621b5e9573179818f23cb6d749794d8f34b5e885 Mon Sep 17 00:00:00 2001 This code checks whether a particular user (as authenticated by SSL) should be allowed to connect to a particular brick, instead of allowing any authenticated user to connect to any brick. This only matters if multiple bricks are exported through a single protocol/server instance. When using Gluster tools this won't be the case because volfiles are written to associate only one brick with each server, so each server can just use a different valid-certificate list (ssl-ca-list). With the CloudFS tools multiple bricks are associated with each server, so that wouldn't work. This method also allows unauthorized connections to fail more cleanly at the gf_auth level with error messages and such, instead of failing at the SSL level due to lack of an accepted certificate. Signed-off-by: Jeff Darcy <jdarcy@xxxxxxxxxx> --- rpc/rpc-lib/src/rpc-transport.h | 1 + rpc/rpc-transport/socket/src/socket.c | 30 +++++++++++++------ xlators/protocol/auth/login/src/login.c | 37 ++++++++++++++++------- xlators/protocol/server/src/server-handshake.c | 9 ++++++ 4 files changed, 56 insertions(+), 21 deletions(-) diff --git a/rpc/rpc-lib/src/rpc-transport.h b/rpc/rpc-lib/src/rpc-transport.h index 3161ec9..99add67 100644 --- a/rpc/rpc-lib/src/rpc-transport.h +++ b/rpc/rpc-lib/src/rpc-transport.h @@ -216,6 +216,7 @@ struct rpc_transport { struct list_head list; int client_bind_insecure; + char *ssl_name; }; struct rpc_transport_ops { diff --git a/rpc/rpc-transport/socket/src/socket.c b/rpc/rpc-transport/socket/src/socket.c index 762426d..876add3 100644 --- a/rpc/rpc-transport/socket/src/socket.c +++ b/rpc/rpc-transport/socket/src/socket.c @@ -143,12 +143,13 @@ int socket_init (rpc_transport_t *this); -int +char * ssl_setup_connection (socket_private_t *priv, int server) { - X509 *peer; - char peer_CN[256]; - int ret; + X509 *peer = NULL; + char peer_CN[256] = ""; + int ret = -1; + char *value = NULL; priv->ssl_ssl = SSL_new(priv->ssl_ctx); priv->ssl_sbio = BIO_new_socket(priv->sock,BIO_NOCLOSE); @@ -159,6 +160,7 @@ ssl_setup_connection (socket_private_t *priv, int server) else { ret = SSL_connect(priv->ssl_ssl); } + if (ret >= 0) { gf_log(__func__,GF_LOG_DEBUG,"verify_result = %lu (%d)", SSL_get_verify_result(priv->ssl_ssl), X509_V_OK); @@ -168,6 +170,8 @@ ssl_setup_connection (socket_private_t *priv, int server) NID_commonName, peer_CN, sizeof(peer_CN)-1); peer_CN[sizeof(peer_CN)-1] = '\0'; gf_log(__func__,GF_LOG_DEBUG,"peer CN = %s", peer_CN); + /* Stop complaining, it's already length-limited. */ + value = gf_strdup(peer_CN); } } else { @@ -181,7 +185,8 @@ ssl_setup_connection (socket_private_t *priv, int server) gf_log(__func__,GF_LOG_ERROR," %s",errbuf); } } - return ret; + + return value; } int @@ -2029,15 +2034,16 @@ int socket_server_event_handler (int fd, int idx, void *data, int poll_in, int poll_out, int poll_err) { - rpc_transport_t *this = NULL; + rpc_transport_t *this = NULL; socket_private_t *priv = NULL; int ret = 0; int new_sock = -1; - rpc_transport_t *new_trans = NULL; + rpc_transport_t *new_trans = NULL; struct sockaddr_storage new_sockaddr = {0, }; socklen_t addrlen = sizeof (new_sockaddr); socket_private_t *new_priv = NULL; glusterfs_ctx_t *ctx = NULL; + char *cname = NULL; this = data; GF_VALIDATE_OR_GOTO ("socket", this, out); @@ -2126,12 +2132,14 @@ socket_server_event_handler (int fd, int idx, void *data, if (priv->use_ssl) { new_priv->ssl_ctx = priv->ssl_ctx; - if (ssl_setup_connection(new_priv,1) < 0) { + cname = ssl_setup_connection(new_priv,1); + if (!cname) { gf_log(this->name,GF_LOG_ERROR, "server setup failed"); close(new_sock); goto unlock; } + new_trans->ssl_name = cname; } if (!priv->bio) { @@ -2227,6 +2235,7 @@ socket_connect (rpc_transport_t *this, int port) glusterfs_ctx_t *ctx = NULL; sa_family_t sa_family = {0, }; union gf_sock_union sock_union; + char *cname = NULL; GF_VALIDATE_OR_GOTO ("socket", this, err); GF_VALIDATE_OR_GOTO ("socket", this->private, err); @@ -2351,14 +2360,15 @@ socket_connect (rpc_transport_t *this, int port) } if (priv->use_ssl) { - ret = ssl_setup_connection(priv,0); - if (ret < 0) { + cname = ssl_setup_connection(priv,0); + if (!cname) { gf_log(this->name,GF_LOG_ERROR, "client setup failed"); close(priv->sock); priv->sock = -1; goto unlock; } + this->ssl_name = cname; } if (!priv->bio) { diff --git a/xlators/protocol/auth/login/src/login.c b/xlators/protocol/auth/login/src/login.c index 81b8efa..8583548 100644 --- a/xlators/protocol/auth/login/src/login.c +++ b/xlators/protocol/auth/login/src/login.c @@ -40,24 +40,30 @@ auth_result_t gf_auth (dict_t *input_params, dict_t *config_params) char *username_str = NULL; char *tmp = NULL; char *username_cpy = NULL; + int using_ssl = 0; username_data = dict_get (input_params, "username"); if (!username_data) { - gf_log ("auth/login", GF_LOG_DEBUG, - "username not found, returning DONT-CARE"); - goto out; + username_data = dict_get(input_params,"ssl-name"); + if (!username_data) { + gf_log ("auth/login", GF_LOG_DEBUG, + "username not found, returning DONT-CARE"); + goto out; + } + using_ssl = 1; } username = data_to_str (username_data); - password_data = dict_get (input_params, "password"); - if (!password_data) { - gf_log ("auth/login", GF_LOG_WARNING, - "password not found, returning DONT-CARE"); - goto out; - } - - password = data_to_str (password_data); + if (!using_ssl) { + password_data = dict_get (input_params, "password"); + if (!password_data) { + gf_log ("auth/login", GF_LOG_WARNING, + "password not found, returning DONT-CARE"); + goto out; + } + password = data_to_str (password_data); + } brick_name = data_to_str (dict_get (input_params, "remote-subvolume")); if (!brick_name) { @@ -87,6 +93,15 @@ auth_result_t gf_auth (dict_t *input_params, dict_t *config_params) while (username_str) { if (!fnmatch (username_str, username, 0)) { + if (using_ssl) { + /* + * SSL code already did a much stronger + * kind of authentication, so we don't + * need a password. + */ + result = AUTH_ACCEPT; + break; + } ret = gf_asprintf (&searchstr, "auth.login.%s.password", username); diff --git a/xlators/protocol/server/src/server-handshake.c b/xlators/protocol/server/src/server-handshake.c index 66b9ea7..2764239 100644 --- a/xlators/protocol/server/src/server-handshake.c +++ b/xlators/protocol/server/src/server-handshake.c @@ -409,6 +409,15 @@ server_setvolume (rpcsvc_request_t *req) goto fail; } + if (req->trans->ssl_name) { + ret = dict_set_dynstr(params,"ssl-name",req->trans->ssl_name); + if (ret < 0) { + gf_log (this->name, GF_LOG_DEBUG, + "failed to set SSL name"); + /* Not fatal. */ + } + } + conn = server_connection_get (this, process_uuid); if (req->trans->xl_private != conn) -- 1.7.3.4