[Gluster-devel] [PATCH BUG:2999] Add SSL-based authorization as well as authentication.

Jeff Darcy jdarcy at redhat.com
Fri Jun 24 15:20:59 UTC 2011


>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 at redhat.com>
---
 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




More information about the Gluster-devel mailing list