"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-8.2/xlators/protocol/auth/login/src/login.c" (16 Sep 2020, 7484 Bytes) of package /linux/misc/glusterfs-8.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "login.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2   Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
    3   This file is part of GlusterFS.
    4 
    5   This file is licensed to you under your choice of the GNU Lesser
    6   General Public License, version 3 or any later version (LGPLv3 or
    7   later), or the GNU General Public License, version 2 (GPLv2), in all
    8   cases as published by the Free Software Foundation.
    9 */
   10 
   11 #include <fnmatch.h>
   12 #include "authenticate.h"
   13 
   14 /* Note on strict_auth
   15  * - Strict auth kicks in when authentication is using the username, password
   16  *   in the volfile to login
   17  * - If enabled, auth is rejected if the username and password is not matched
   18  *   or is not present
   19  * - When using SSL names, this is automatically strict, and allows only those
   20  *   names that are present in the allow list, IOW strict auth checking has no
   21  *   implication when using SSL names
   22  */
   23 
   24 auth_result_t
   25 gf_auth(dict_t *input_params, dict_t *config_params)
   26 {
   27     auth_result_t result = AUTH_DONT_CARE;
   28     int ret = 0;
   29     data_t *allow_user = NULL;
   30     data_t *username_data = NULL;
   31     data_t *passwd_data = NULL;
   32     data_t *password_data = NULL;
   33     char *username = NULL;
   34     char *password = NULL;
   35     char *brick_name = NULL;
   36     char *searchstr = NULL;
   37     char *username_str = NULL;
   38     char *tmp = NULL;
   39     char *username_cpy = NULL;
   40     gf_boolean_t using_ssl = _gf_false;
   41     gf_boolean_t strict_auth = _gf_false;
   42 
   43     username_data = dict_get(input_params, "ssl-name");
   44     if (username_data) {
   45         gf_log("auth/login", GF_LOG_INFO, "connecting user name: %s",
   46                username_data->data);
   47         using_ssl = _gf_true;
   48     } else {
   49         ret = dict_get_str_boolean(config_params, "strict-auth-accept",
   50                                    _gf_false);
   51         if (ret == -1)
   52             strict_auth = _gf_false;
   53         else
   54             strict_auth = ret;
   55 
   56         username_data = dict_get(input_params, "username");
   57         if (!username_data) {
   58             if (strict_auth) {
   59                 gf_log("auth/login", GF_LOG_DEBUG,
   60                        "username not found, strict auth"
   61                        " configured returning REJECT");
   62                 result = AUTH_REJECT;
   63             } else {
   64                 gf_log("auth/login", GF_LOG_DEBUG,
   65                        "username not found, returning"
   66                        " DONT-CARE");
   67             }
   68             goto out;
   69         }
   70         password_data = dict_get(input_params, "password");
   71         if (!password_data) {
   72             if (strict_auth) {
   73                 gf_log("auth/login", GF_LOG_DEBUG,
   74                        "password not found, strict auth"
   75                        " configured returning REJECT");
   76                 result = AUTH_REJECT;
   77             } else {
   78                 gf_log("auth/login", GF_LOG_WARNING,
   79                        "password not found, returning"
   80                        " DONT-CARE");
   81             }
   82             goto out;
   83         }
   84         password = data_to_str(password_data);
   85     }
   86     username = data_to_str(username_data);
   87 
   88     brick_name = data_to_str(dict_get(input_params, "remote-subvolume"));
   89     if (!brick_name) {
   90         gf_log("auth/login", GF_LOG_ERROR, "remote-subvolume not specified");
   91         result = AUTH_REJECT;
   92         goto out;
   93     }
   94 
   95     ret = gf_asprintf(&searchstr, "auth.login.%s.%s", brick_name,
   96                       using_ssl ? "ssl-allow" : "allow");
   97     if (-1 == ret) {
   98         gf_log("auth/login", GF_LOG_ERROR,
   99                "asprintf failed while setting search string, "
  100                "returning REJECT");
  101         result = AUTH_REJECT;
  102         goto out;
  103     }
  104 
  105     allow_user = dict_get(config_params, searchstr);
  106     GF_FREE(searchstr);
  107 
  108     if (allow_user) {
  109         gf_log("auth/login", GF_LOG_INFO, "allowed user names: %s",
  110                allow_user->data);
  111         /*
  112          * There's a subtle difference between SSL and non-SSL behavior
  113          * if we can't match anything in the "while" loop below.
  114          * Intuitively, we should AUTH_REJECT if there's no match.
  115          * However, existing code depends on allowing untrusted users
  116          * to connect with *no credentials at all* by falling through
  117          * the loop.  They're still distinguished from trusted users
  118          * who do provide a valid username and password (in fact that's
  119          * pretty much the only thing we use non-SSL login auth for),
  120          * but they are allowed to connect.  It's wrong, but it's not
  121          * worth changing elsewhere.  Therefore, we do the sane thing
  122          * only for SSL here.
  123          *
  124          * For SSL, if there's a list *you must be on it*.  Note that
  125          * if there's no list we don't care.  In that case (and the
  126          * ssl-allow=* case as well) authorization is effectively
  127          * disabled, though authentication and encryption are still
  128          * active.
  129          *
  130          * Read NOTE on strict_auth above.
  131          */
  132         if (using_ssl || strict_auth) {
  133             result = AUTH_REJECT;
  134         }
  135         username_cpy = gf_strdup(allow_user->data);
  136         if (!username_cpy)
  137             goto out;
  138 
  139         username_str = strtok_r(username_cpy, " ,", &tmp);
  140 
  141         /*
  142          * We have to match a user's *authenticated* name to one in the
  143          * list.  If we're using SSL, they're already authenticated.
  144          * Otherwise, they need a matching password to complete the
  145          * process.
  146          */
  147         while (username_str) {
  148             if (!fnmatch(username_str, username, 0)) {
  149                 if (using_ssl) {
  150                     result = AUTH_ACCEPT;
  151                     break;
  152                 }
  153                 ret = gf_asprintf(&searchstr, "auth.login.%s.password",
  154                                   username);
  155                 if (-1 == ret) {
  156                     gf_log("auth/login", GF_LOG_WARNING,
  157                            "asprintf failed while setting search string");
  158                     goto out;
  159                 }
  160                 passwd_data = dict_get(config_params, searchstr);
  161                 GF_FREE(searchstr);
  162 
  163                 if (!passwd_data) {
  164                     gf_log("auth/login", GF_LOG_ERROR,
  165                            "wrong username/password combination");
  166                     result = AUTH_REJECT;
  167                     goto out;
  168                 }
  169 
  170                 result = !((strcmp(data_to_str(passwd_data), password))
  171                                ? AUTH_ACCEPT
  172                                : AUTH_REJECT);
  173                 if (result == AUTH_REJECT)
  174                     gf_log("auth/login", GF_LOG_ERROR,
  175                            "wrong password for user %s", username);
  176 
  177                 break;
  178             }
  179             username_str = strtok_r(NULL, " ,", &tmp);
  180         }
  181     }
  182 
  183 out:
  184     GF_FREE(username_cpy);
  185 
  186     return result;
  187 }
  188 
  189 struct volume_options options[] = {
  190     {
  191         .key = {"auth.login.*.allow"},
  192         .type = GF_OPTION_TYPE_ANY,
  193         .default_value = "*",
  194         .description = "Username to be allowed access to the volume",
  195         .op_version = {1},
  196         .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC,
  197         .tags = {},
  198         /* option_validation_fn validate_fn; */
  199     },
  200     {
  201         .key = {"auth.login.*.password"},
  202         .type = GF_OPTION_TYPE_ANY,
  203         .default_value = "*",
  204         .description = "Password for the allowed username",
  205         .op_version = {1},
  206         .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC,
  207         .tags = {},
  208         /* option_validation_fn validate_fn; */
  209     },
  210     {.key = {NULL}}};