From 16d6904d54e7409f95e9e893e131b6bf11f0e4c7 Mon Sep 17 00:00:00 2001 From: Mohammed Rafi KC Date: Mon, 2 Apr 2018 12:20:47 +0530 Subject: [PATCH 653/653] server/auth: add option for strict authentication When this option is enabled, we will check for a matching username and password, if not found then the connection will be rejected. This also deos a checksum validation of volfile Change-Id: I2ac4f0cfa5b59cc789cc5a265358389b04556b59 BUG: 1559331 Signed-off-by: Mohammed Rafi KC Reviewed-on: https://code.engineering.redhat.com/gerrit/134591 Reviewed-by: Pranith Kumar Karampuri Reviewed-by: Mohit Agrawal Reviewed-by: Atin Mukherjee Tested-by: Atin Mukherjee --- xlators/mgmt/glusterd/src/glusterd-volgen.c | 15 ++++ xlators/protocol/auth/login/src/login.c | 104 +++++++++++++++++-------- xlators/protocol/server/src/authenticate.c | 32 ++++++-- xlators/protocol/server/src/authenticate.h | 6 +- xlators/protocol/server/src/server-handshake.c | 4 +- xlators/protocol/server/src/server.c | 20 ++++- xlators/protocol/server/src/server.h | 4 + 7 files changed, 136 insertions(+), 49 deletions(-) diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c index fb7c91f..02e8393 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volgen.c +++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c @@ -2145,6 +2145,7 @@ brick_graph_add_server (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, char key[1024] = {0}; char *ssl_user = NULL; char *value = NULL; + char *volname = NULL; char *address_family_data = NULL; if (!graph || !volinfo || !set_dict || !brickinfo) @@ -2220,6 +2221,20 @@ brick_graph_add_server (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, if (ret) return -1; + volname = volinfo->is_snap_volume ? + volinfo->parent_volname : volinfo->volname; + + + if (volname && !strcmp (volname, GLUSTER_SHARED_STORAGE)) { + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "strict-auth-accept"); + + ret = xlator_set_option (xl, key, "true"); + if (ret) + return -1; + } + if (dict_get_str (volinfo->dict, "auth.ssl-allow", &ssl_user) == 0) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "auth.login.%s.ssl-allow", diff --git a/xlators/protocol/auth/login/src/login.c b/xlators/protocol/auth/login/src/login.c index e799dd2..e918d38 100644 --- a/xlators/protocol/auth/login/src/login.c +++ b/xlators/protocol/auth/login/src/login.c @@ -11,45 +11,18 @@ #include #include "authenticate.h" -auth_result_t gf_auth (dict_t *input_params, dict_t *config_params) -{ +auth_result_t gf_authenticate_user (dict_t *input_params, dict_t *config_params, + char *username, char *password, + gf_boolean_t using_ssl) { auth_result_t result = AUTH_DONT_CARE; int ret = 0; data_t *allow_user = NULL; - data_t *username_data = NULL; data_t *passwd_data = NULL; - data_t *password_data = NULL; - char *username = NULL; - char *password = NULL; char *brick_name = NULL; char *searchstr = NULL; char *username_str = NULL; char *tmp = NULL; char *username_cpy = NULL; - gf_boolean_t using_ssl = _gf_false; - - username_data = dict_get (input_params, "ssl-name"); - if (username_data) { - gf_log ("auth/login", GF_LOG_INFO, - "connecting user name: %s", username_data->data); - using_ssl = _gf_true; - } - else { - 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; - } - 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); - } - username = data_to_str (username_data); brick_name = data_to_str (dict_get (input_params, "remote-subvolume")); if (!brick_name) { @@ -64,7 +37,8 @@ auth_result_t gf_auth (dict_t *input_params, dict_t *config_params) if (-1 == ret) { gf_log ("auth/login", GF_LOG_WARNING, "asprintf failed while setting search string, " - "returning DONT-CARE"); + "returning AUTH_STRICT_ACCEPT"); + result = AUTH_STRICT_ACCEPT; goto out; } @@ -84,7 +58,7 @@ auth_result_t gf_auth (dict_t *input_params, dict_t *config_params) * who do provide a valid username and password (in fact that's * pretty much the only thing we use non-SSL login auth for), * but they are allowed to connect. It's wrong, but it's not - * worth changing elsewhere. Therefore, we do the sane thing + * worth changing elsewhere. Therefore, we do the same thing * only for SSL here. * * For SSL, if there's a list *you must be on it*. Note that @@ -92,13 +66,20 @@ auth_result_t gf_auth (dict_t *input_params, dict_t *config_params) * ssl-allow=* case as well) authorization is effectively * disabled, though authentication and encryption are still * active. + * + * If option strict-auth-accept is enabled, connection + * will be rejected if you don't have any matching + * username and password (password is only for non-ssl users). */ if (using_ssl) { result = AUTH_REJECT; } username_cpy = gf_strdup (allow_user->data); - if (!username_cpy) + if (!username_cpy) { + if (!using_ssl) + result = AUTH_STRICT_ACCEPT; goto out; + } username_str = strtok_r (username_cpy, " ,", &tmp); @@ -120,6 +101,7 @@ auth_result_t gf_auth (dict_t *input_params, dict_t *config_params) if (-1 == ret) { gf_log ("auth/login", GF_LOG_WARNING, "asprintf failed while setting search string"); + result = AUTH_STRICT_ACCEPT; goto out; } passwd_data = dict_get (config_params, searchstr); @@ -145,11 +127,65 @@ auth_result_t gf_auth (dict_t *input_params, dict_t *config_params) } username_str = strtok_r (NULL, " ,", &tmp); } + } else { + result = AUTH_STRICT_ACCEPT; } - out: GF_FREE (username_cpy); + return result; +} +auth_result_t gf_auth (dict_t *input_params, dict_t *config_params) +{ + auth_result_t result = AUTH_DONT_CARE; + auth_result_t ssl_result = AUTH_DONT_CARE; + data_t *username_data = NULL; + data_t *password_data = NULL; + char *username = NULL; + char *password = NULL; + gf_boolean_t using_ssl = _gf_false; + + username_data = dict_get (input_params, "username"); + if (!username_data) { + gf_log ("auth/login", GF_LOG_DEBUG, + "username not found, returning AUTH_STRICT_ACCEPT"); + result = AUTH_STRICT_ACCEPT; + goto out; + } + password_data = dict_get (input_params, "password"); + if (!password_data) { + gf_log ("auth/login", GF_LOG_WARNING, + "password not found, returning AUTH_STRICT_ACCEPT"); + result = AUTH_STRICT_ACCEPT; + goto out; + } + password = data_to_str (password_data); + username = data_to_str (username_data); + + result = gf_authenticate_user (input_params, config_params, + username, password, using_ssl); + + username_data = dict_get (input_params, "ssl-name"); + if (username_data) { + gf_log ("auth/login", GF_LOG_INFO, + "connecting user name: %s", username_data->data); + username = data_to_str (username_data); + using_ssl = _gf_true; + ssl_result = gf_authenticate_user (input_params, config_params, + username, NULL, using_ssl); + if (ssl_result == AUTH_ACCEPT && result != AUTH_ACCEPT) { + /* + * Here, ssl authentication returns true, but non-ssl + * authentication returns differnt result. We are + * calling for a strict auth check in this case. + */ + result = AUTH_STRICT_ACCEPT; + } else { + result = ssl_result; + } + } + +out: return result; } diff --git a/xlators/protocol/server/src/authenticate.c b/xlators/protocol/server/src/authenticate.c index c000776..977ed75 100644 --- a/xlators/protocol/server/src/authenticate.c +++ b/xlators/protocol/server/src/authenticate.c @@ -18,7 +18,9 @@ #include #include #include "authenticate.h" +#include "authenticate.h" #include "server-messages.h" +#include "server.h" static int init (dict_t *this, char *key, data_t *value, void *data) @@ -173,6 +175,7 @@ gf_auth_one_method (dict_t *this, char *key, data_t *value, void *data) { gf_auth_args_t *args = data; auth_handle_t *handle = NULL; + int64_t result; if (!value) { return 0; @@ -183,10 +186,13 @@ gf_auth_one_method (dict_t *this, char *key, data_t *value, void *data) return 0; } - switch (handle->authenticate (args->iparams, args->cparams)) { + result = handle->authenticate (args->iparams, args->cparams); + switch (result) { case AUTH_ACCEPT: - if (args->result != AUTH_REJECT) { - args->result = AUTH_ACCEPT; + case AUTH_STRICT_ACCEPT: + if (args->result != AUTH_REJECT && + args->result != AUTH_STRICT_ACCEPT) { + args->result = result; } /* FALLTHROUGH */ default: @@ -198,9 +204,8 @@ gf_auth_one_method (dict_t *this, char *key, data_t *value, void *data) } auth_result_t -gf_authenticate (dict_t *input_params, - dict_t *config_params, - dict_t *auth_modules) +gf_authenticate (server_conf_t *conf, dict_t *input_params, + dict_t *config_params, dict_t *auth_modules) { char *name = NULL; data_t *peerinfo_data = NULL; @@ -210,9 +215,19 @@ gf_authenticate (dict_t *input_params, args.cparams = config_params; args.result = AUTH_DONT_CARE; + GF_VALIDATE_OR_GOTO ("authentication", conf, out); dict_foreach (auth_modules, gf_auth_one_method, &args); - if (AUTH_DONT_CARE == args.result) { + switch (args.result) { + case AUTH_STRICT_ACCEPT: + if (!conf->strict_auth_enabled) { + args.result = AUTH_ACCEPT; + break; + } + gf_msg ("auth", GF_LOG_ERROR, 0, PS_MSG_REMOTE_CLIENT_REFUSED, + "Authentication is failed due to the strict options."); + /* Fallthrough */ + case AUTH_DONT_CARE: peerinfo_data = dict_get (input_params, "peer-info-name"); if (peerinfo_data) { @@ -223,8 +238,9 @@ gf_authenticate (dict_t *input_params, "no authentication module is interested in " "accepting remote-client %s", name); args.result = AUTH_REJECT; + /* Fallthrough */ } - +out: return args.result; } diff --git a/xlators/protocol/server/src/authenticate.h b/xlators/protocol/server/src/authenticate.h index 3f80231..d5971d3 100644 --- a/xlators/protocol/server/src/authenticate.h +++ b/xlators/protocol/server/src/authenticate.h @@ -25,7 +25,8 @@ typedef enum { AUTH_ACCEPT, AUTH_REJECT, - AUTH_DONT_CARE + AUTH_DONT_CARE, + AUTH_STRICT_ACCEPT } auth_result_t; typedef auth_result_t (*auth_fn_t) (dict_t *input_params, @@ -37,9 +38,6 @@ typedef struct { volume_opt_list_t *vol_opt; } auth_handle_t; -auth_result_t gf_authenticate (dict_t *input_params, - dict_t *config_params, - dict_t *auth_modules); int32_t gf_auth_init (xlator_t *xl, dict_t *auth_modules); void gf_auth_fini (dict_t *auth_modules); diff --git a/xlators/protocol/server/src/server-handshake.c b/xlators/protocol/server/src/server-handshake.c index ba5b11a..b67ed47 100644 --- a/xlators/protocol/server/src/server-handshake.c +++ b/xlators/protocol/server/src/server-handshake.c @@ -709,7 +709,7 @@ server_setvolume (rpcsvc_request_t *req) ret = dict_get_str (params, "volfile-key", &volfile_key); if (ret) - gf_msg_debug (this->name, 0, "failed to set " + gf_msg_debug (this->name, 0, "failed to get " "'volfile-key'"); ret = _validate_volfile_checksum (this, volfile_key, @@ -765,7 +765,7 @@ server_setvolume (rpcsvc_request_t *req) PS_MSG_CLIENT_VERSION_NOT_SET, "client-version not set, may be of older version"); - ret = gf_authenticate (params, config_params, + ret = gf_authenticate (conf, params, config_params, conf->auth_modules); if (ret == AUTH_ACCEPT) { diff --git a/xlators/protocol/server/src/server.c b/xlators/protocol/server/src/server.c index 96aa012..f89e743 100644 --- a/xlators/protocol/server/src/server.c +++ b/xlators/protocol/server/src/server.c @@ -866,6 +866,10 @@ do_rpc: goto out; } + GF_OPTION_RECONF ("strict-auth-accept", conf->strict_auth_enabled, + options, bool, out); + + GF_OPTION_RECONF ("dynamic-auth", conf->dync_auth, options, bool, out); @@ -906,7 +910,7 @@ do_rpc: if (strcmp (xprt_path, auth_path) != 0) { continue; } - ret = gf_authenticate (xprt->clnt_options, + ret = gf_authenticate (conf, xprt->clnt_options, options, conf->auth_modules); if (ret == AUTH_ACCEPT) { @@ -1098,6 +1102,14 @@ init (xlator_t *this) "Failed to initialize group cache."); goto out; } + + ret = dict_get_str_boolean (this->options, "strict-auth-accept", + _gf_false); + if (ret == -1) + conf->strict_auth_enabled = _gf_false; + else + conf->strict_auth_enabled = ret; + ret = dict_get_str_boolean (this->options, "dynamic-auth", _gf_true); if (ret == -1) @@ -1738,5 +1750,11 @@ struct volume_options options[] = { "transport connection immediately in response to " "*.allow | *.reject volume set options." }, + { .key = {"strict-auth-accept"}, + .type = GF_OPTION_TYPE_BOOL, + .default_value = "off", + .description = "strict-auth-accept reject connection with out" + "a valid username and password." + }, { .key = {NULL} }, }; diff --git a/xlators/protocol/server/src/server.h b/xlators/protocol/server/src/server.h index 1be9a38..4c35aaa 100644 --- a/xlators/protocol/server/src/server.h +++ b/xlators/protocol/server/src/server.h @@ -24,6 +24,7 @@ #include "client_t.h" #include "gidcache.h" #include "defaults.h" +#include "authenticate.h" #define DEFAULT_BLOCK_SIZE 4194304 /* 4MB */ #define DEFAULT_VOLUME_FILE_PATH CONFDIR "/glusterfs.vol" @@ -111,6 +112,7 @@ struct server_conf { struct _child_status *child_status; gf_lock_t itable_lock; + gf_boolean_t strict_auth_enabled; }; typedef struct server_conf server_conf_t; @@ -243,6 +245,8 @@ serialize_rsp_dirent (gf_dirent_t *entries, gfs3_readdir_rsp *rsp); int serialize_rsp_direntp (gf_dirent_t *entries, gfs3_readdirp_rsp *rsp); +auth_result_t gf_authenticate (server_conf_t *conf, dict_t *input_params, + dict_t *config_params, dict_t *auth_modules); server_ctx_t* server_ctx_get (client_t *client, xlator_t *xlator); -- 1.8.3.1