[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