diff options
| -rw-r--r-- | rpc/rpc-lib/src/rpcsvc-auth.c | 70 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/rpcsvc.c | 506 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/rpcsvc.h | 8 | ||||
| -rwxr-xr-x | tests/bugs/bug-921072.t | 135 | ||||
| -rw-r--r-- | xlators/nfs/server/src/mount3.c | 3 | 
5 files changed, 268 insertions, 454 deletions
diff --git a/rpc/rpc-lib/src/rpcsvc-auth.c b/rpc/rpc-lib/src/rpcsvc-auth.c index 04b66091f73..1082794568c 100644 --- a/rpc/rpc-lib/src/rpcsvc-auth.c +++ b/rpc/rpc-lib/src/rpcsvc-auth.c @@ -366,14 +366,10 @@ err:  int  rpcsvc_auth_array (rpcsvc_t *svc, char *volname, int *autharr, int arrlen)  { -        int             count = 0; -        int             gen = RPCSVC_AUTH_REJECT; -        int             spec = RPCSVC_AUTH_REJECT; -        int             final = RPCSVC_AUTH_REJECT; -        char            *srchstr = NULL; -        char            *valstr = NULL; -        gf_boolean_t    boolval = _gf_false; -        int             ret = 0; +        int             count      = 0; +        int             result     = RPCSVC_AUTH_REJECT; +        char           *srchstr    = NULL; +        int             ret        = 0;          struct rpcsvc_auth_list *auth = NULL;          struct rpcsvc_auth_list *tmp = NULL; @@ -391,59 +387,27 @@ rpcsvc_auth_array (rpcsvc_t *svc, char *volname, int *autharr, int arrlen)                  if (count >= arrlen)                          break; -                gen = gf_asprintf (&srchstr, "rpc-auth.%s", auth->name); -                if (gen == -1) { +                result = gf_asprintf (&srchstr, "rpc-auth.%s.%s", +                                      auth->name, volname); +                if (result == -1) {                          count = -1;                          goto err;                  } -                gen = RPCSVC_AUTH_REJECT; -                if (dict_get (svc->options, srchstr)) { -                        ret = dict_get_str (svc->options, srchstr, &valstr); -                        if (ret == 0) { -                                ret = gf_string2boolean (valstr, &boolval); -                                if (ret == 0) { -                                        if (boolval == _gf_true) -                                                gen = RPCSVC_AUTH_ACCEPT; -                                } else -                                        gf_log (GF_RPCSVC, GF_LOG_ERROR, "Faile" -                                                "d to read auth val"); -                        } else -                                gf_log (GF_RPCSVC, GF_LOG_ERROR, "Faile" -                                        "d to read auth val"); -                } - +                ret = dict_get_str_boolean (svc->options, srchstr, 0xC00FFEE);                  GF_FREE (srchstr); -                spec = gf_asprintf (&srchstr, "rpc-auth.%s.%s", auth->name, -                                    volname); -                if (spec == -1) { -                        count = -1; -                        goto err; -                } -                spec = RPCSVC_AUTH_DONTCARE; -                if (dict_get (svc->options, srchstr)) { -                        ret = dict_get_str (svc->options, srchstr, &valstr); -                        if (ret == 0) { -                                ret = gf_string2boolean (valstr, &boolval); -                                if (ret == 0) { -                                        if (boolval == _gf_true) -                                                spec = RPCSVC_AUTH_ACCEPT; -                                        else -                                                spec = RPCSVC_AUTH_REJECT; -                                } else -                                        gf_log (GF_RPCSVC, GF_LOG_ERROR, "Faile" -                                                "d to read auth val"); -                        } else -                                gf_log (GF_RPCSVC, GF_LOG_ERROR, "Faile" -                                        "d to read auth val"); -                } - -                GF_FREE (srchstr); -                final = rpcsvc_combine_gen_spec_volume_checks (gen, spec); -                if (final == RPCSVC_AUTH_ACCEPT) { +                switch (ret) { +                case _gf_true: +                        result = RPCSVC_AUTH_ACCEPT;                          autharr[count] = auth->auth->authnum;                          ++count; +                        break; +                case _gf_false: +                        result = RPCSVC_AUTH_REJECT; +                        break; +                default: +                        result = RPCSVC_AUTH_DONTCARE;                  }          } diff --git a/rpc/rpc-lib/src/rpcsvc.c b/rpc/rpc-lib/src/rpcsvc.c index 078adc06256..af01c1715ac 100644 --- a/rpc/rpc-lib/src/rpcsvc.c +++ b/rpc/rpc-lib/src/rpcsvc.c @@ -207,7 +207,7 @@ rpcsvc_program_actor (rpcsvc_request_t *req)                  goto err;          } -	req->synctask = program->synctask; +        req->synctask = program->synctask;          err = SUCCESS;          gf_log (GF_RPCSVC, GF_LOG_TRACE, "Actor found: %s - %s", @@ -439,9 +439,9 @@ err:  int  rpcsvc_check_and_reply_error (int ret, call_frame_t *frame, void *opaque)  { -	rpcsvc_request_t  *req = NULL; +        rpcsvc_request_t  *req = NULL; -	req = opaque; +        req = opaque;          if (ret)                  gf_log ("rpcsvc", GF_LOG_ERROR, @@ -454,7 +454,7 @@ rpcsvc_check_and_reply_error (int ret, call_frame_t *frame, void *opaque)                                  "failed to queue error reply");          } -	return 0; +        return 0;  }  int @@ -462,7 +462,7 @@ rpcsvc_handle_rpc_call (rpcsvc_t *svc, rpc_transport_t *trans,                          rpc_transport_pollin_t *msg)  {          rpcsvc_actor_t          *actor = NULL; -	rpcsvc_actor            actor_fn = NULL; +        rpcsvc_actor            actor_fn = NULL;          rpcsvc_request_t        *req = NULL;          int                     ret = -1;          uint16_t                port = 0; @@ -525,28 +525,28 @@ rpcsvc_handle_rpc_call (rpcsvc_t *svc, rpc_transport_t *trans,                  /* Before going to xlator code, set the THIS properly */                  THIS = svc->mydata; -		actor_fn = actor->actor; +                actor_fn = actor->actor; -		if (!actor_fn) { -			rpcsvc_request_seterr (req, PROC_UNAVAIL); -			/* LOG TODO: print more info about procnum, -			   prognum etc, also print transport info */ -			gf_log (GF_RPCSVC, GF_LOG_ERROR, -				"No vectored handler present"); -			ret = RPCSVC_ACTOR_ERROR; -			goto err_reply; -		} +                if (!actor_fn) { +                        rpcsvc_request_seterr (req, PROC_UNAVAIL); +                        /* LOG TODO: print more info about procnum, +                           prognum etc, also print transport info */ +                        gf_log (GF_RPCSVC, GF_LOG_ERROR, +                                "No vectored handler present"); +                        ret = RPCSVC_ACTOR_ERROR; +                        goto err_reply; +                } -		if (req->synctask) { +                if (req->synctask) {                          if (msg->hdr_iobuf)                                  req->hdr_iobuf = iobuf_ref (msg->hdr_iobuf); -			ret = synctask_new (THIS->ctx->env, -					    (synctask_fn_t) actor_fn, -					    rpcsvc_check_and_reply_error, NULL, +                        ret = synctask_new (THIS->ctx->env, +                                            (synctask_fn_t) actor_fn, +                                            rpcsvc_check_and_reply_error, NULL,                                              req);                  } else { -			ret = actor_fn (req); +                        ret = actor_fn (req);                          req->hdr_iobuf = NULL;                  }          } @@ -1918,21 +1918,16 @@ free_svc:  int -rpcsvc_transport_peer_check_search (dict_t *options, char *pattern, char *clstr) +rpcsvc_transport_peer_check_search (dict_t *options, char *pattern, +                                    char *ip, char *hostname)  { -        int                     ret = -1; -        char                    *addrtok = NULL; -        char                    *addrstr = NULL; -        char                    *dup_addrstr = NULL; -        char                    *svptr = NULL; -        char                    *fqdn        = NULL; - -        if ((!options) || (!clstr)) -                return -1; - -        ret = dict_get_str (options, "fqdn", &fqdn); +        int                      ret           = -1; +        char                    *addrtok       = NULL; +        char                    *addrstr       = NULL; +        char                    *dup_addrstr   = NULL; +        char                    *svptr         = NULL; -        if (!dict_get (options, pattern)) +        if ((!options) || (!ip))                  return -1;          ret = dict_get_str (options, pattern, &addrstr); @@ -1952,19 +1947,19 @@ rpcsvc_transport_peer_check_search (dict_t *options, char *pattern, char *clstr)                  /* CASEFOLD not present on Solaris */  #ifdef FNM_CASEFOLD -                ret = fnmatch (addrtok, clstr, FNM_CASEFOLD); +                ret = fnmatch (addrtok, ip, FNM_CASEFOLD);  #else -                ret = fnmatch (addrtok, clstr, 0); +                ret = fnmatch (addrtok, ip, 0);  #endif                  if (ret == 0)                          goto err;                  /* compare hostnames if applicable */ -                if (fqdn) { +                if (hostname) {  #ifdef FNM_CASEFOLD -                        ret = fnmatch (addrtok, fqdn, FNM_CASEFOLD); +                        ret = fnmatch (addrtok, hostname, FNM_CASEFOLD);  #else -                        ret = fnmatch (addrtok, fqdn, 0); +                        ret = fnmatch (addrtok, hostname, 0);  #endif                          if (ret == 0)                                  goto err; @@ -1982,65 +1977,55 @@ err:  int -rpcsvc_transport_peer_check_allow (dict_t *options, char *volname, char *clstr) +rpcsvc_transport_peer_check_allow (dict_t *options, char *volname, +                                   char *ip, char *hostname)  { -        int     ret = RPCSVC_AUTH_DONTCARE; +        int      ret     = RPCSVC_AUTH_DONTCARE;          char    *srchstr = NULL; -        char    globalrule[] = "rpc-auth.addr.allow"; -        if ((!options) || (!clstr)) +        if ((!options) || (!ip) || (!volname))                  return ret; -        /* If volname is NULL, then we're searching for the general rule to -         * determine the current address in clstr is allowed or not for all -         * subvolumes. -         */ -        if (volname) { -                ret = gf_asprintf (&srchstr, "rpc-auth.addr.%s.allow", volname); -                if (ret == -1) { -                        gf_log (GF_RPCSVC, GF_LOG_ERROR, "asprintf failed"); -                        ret = RPCSVC_AUTH_DONTCARE; -                        goto out; -                } -        } else -                srchstr = globalrule; +        ret = gf_asprintf (&srchstr, "rpc-auth.addr.%s.allow", volname); +        if (ret == -1) { +                gf_log (GF_RPCSVC, GF_LOG_ERROR, "asprintf failed"); +                ret = RPCSVC_AUTH_DONTCARE; +                goto out; +        } -        ret = rpcsvc_transport_peer_check_search (options, srchstr, clstr); -        if (volname) -                GF_FREE (srchstr); +        ret = rpcsvc_transport_peer_check_search (options, srchstr, +                                                  ip, hostname); +        GF_FREE (srchstr);          if (ret == 0)                  ret = RPCSVC_AUTH_ACCEPT;          else -                ret = RPCSVC_AUTH_DONTCARE; +                ret = RPCSVC_AUTH_REJECT;  out:          return ret;  }  int -rpcsvc_transport_peer_check_reject (dict_t *options, char *volname, char *clstr) +rpcsvc_transport_peer_check_reject (dict_t *options, char *volname, +                                    char *ip, char *hostname)  { -        int     ret = RPCSVC_AUTH_DONTCARE; +        int      ret     = RPCSVC_AUTH_DONTCARE;          char    *srchstr = NULL; -        char    generalrule[] = "rpc-auth.addr.reject"; -        if ((!options) || (!clstr)) +        if ((!options) || (!ip) || (!volname))                  return ret; -        if (volname) { -                ret = gf_asprintf (&srchstr, "rpc-auth.addr.%s.reject", -                                   volname); -                if (ret == -1) { -                        gf_log (GF_RPCSVC, GF_LOG_ERROR, "asprintf failed"); -                        ret = RPCSVC_AUTH_REJECT; -                        goto out; -                } -        } else -                srchstr = generalrule; +        ret = gf_asprintf (&srchstr, "rpc-auth.addr.%s.reject", +                           volname); +        if (ret == -1) { +                gf_log (GF_RPCSVC, GF_LOG_ERROR, "asprintf failed"); +                ret = RPCSVC_AUTH_REJECT; +                goto out; +        } -        ret = rpcsvc_transport_peer_check_search (options, srchstr, clstr); -        if (volname) -                GF_FREE (srchstr); +        ret = rpcsvc_transport_peer_check_search (options, srchstr, +                                                  ip, hostname); +        GF_FREE (srchstr);          if (ret == 0)                  ret = RPCSVC_AUTH_REJECT; @@ -2051,309 +2036,63 @@ out:  } -/* This function tests the results of the allow rule and the reject rule to - * combine them into a single result that can be used to determine if the - * connection should be allowed to proceed. - * Heres the test matrix we need to follow in this function. - * - * A -  Allow, the result of the allow test. Never returns R. - * R - Reject, result of the reject test. Never returns A. - * Both can return D or dont care if no rule was given. - * - * | @allow | @reject | Result | - * |    A   |   R     | R      | - * |    D   |   D     | D      | - * |    A   |   D     | A      | - * |    D   |   R     | R      | +/* Combines rpc auth's allow and reject options. + * Order of checks is important. + * First,              REJECT if either rejects. + * If neither rejects, ACCEPT if either accepts. + * If neither accepts, DONTCARE   */  int  rpcsvc_combine_allow_reject_volume_check (int allow, int reject)  { -        int     final = RPCSVC_AUTH_REJECT; - -        /* If allowed rule allows but reject rule rejects, we stay cautious -         * and reject. */ -        if ((allow == RPCSVC_AUTH_ACCEPT) && (reject == RPCSVC_AUTH_REJECT)) -                final = RPCSVC_AUTH_REJECT; -        /* if both are dont care, that is user did not specify for either allow -         * or reject, we leave it up to the general rule to apply, in the hope -         * that there is one. -         */ -        else if ((allow == RPCSVC_AUTH_DONTCARE) && -                 (reject == RPCSVC_AUTH_DONTCARE)) -                final = RPCSVC_AUTH_DONTCARE; -        /* If one is dont care, the other one applies. */ -        else if ((allow == RPCSVC_AUTH_ACCEPT) && -                 (reject == RPCSVC_AUTH_DONTCARE)) -                final = RPCSVC_AUTH_ACCEPT; -        else if ((allow == RPCSVC_AUTH_DONTCARE) && -                 (reject == RPCSVC_AUTH_REJECT)) -                final = RPCSVC_AUTH_REJECT; - -        return final; -} - - -/* Combines the result of the general rule test against, the specific rule - * to determine final permission for the client's address. - * - * | @gen   | @spec   | Result | - * |    A   |   A     | A      | - * |    A   |   R     | R      | - * |    A   |   D     | A      | - * |    D   |   A     | A      | - * |    D   |   R     | R      | - * |    D   |   D     | D      | - * |    R   |   A     | A      | - * |    R   |   D     | R      | - * |    R   |   R     | R      | - */ -int -rpcsvc_combine_gen_spec_addr_checks (int gen, int spec) -{ -        int     final = RPCSVC_AUTH_REJECT; - -        if ((gen == RPCSVC_AUTH_ACCEPT) && (spec == RPCSVC_AUTH_ACCEPT)) -                final = RPCSVC_AUTH_ACCEPT; -        else if ((gen == RPCSVC_AUTH_ACCEPT) && (spec == RPCSVC_AUTH_REJECT)) -                final = RPCSVC_AUTH_REJECT; -        else if ((gen == RPCSVC_AUTH_ACCEPT) && (spec == RPCSVC_AUTH_DONTCARE)) -                final = RPCSVC_AUTH_ACCEPT; -        else if ((gen == RPCSVC_AUTH_DONTCARE) && (spec == RPCSVC_AUTH_ACCEPT)) -                final = RPCSVC_AUTH_ACCEPT; -        else if ((gen == RPCSVC_AUTH_DONTCARE) && (spec == RPCSVC_AUTH_REJECT)) -                final = RPCSVC_AUTH_REJECT; -        else if ((gen == RPCSVC_AUTH_DONTCARE) && (spec== RPCSVC_AUTH_DONTCARE)) -                final = RPCSVC_AUTH_DONTCARE; -        else if ((gen == RPCSVC_AUTH_REJECT) && (spec == RPCSVC_AUTH_ACCEPT)) -                final = RPCSVC_AUTH_ACCEPT; -        else if ((gen == RPCSVC_AUTH_REJECT) && (spec == RPCSVC_AUTH_DONTCARE)) -                final = RPCSVC_AUTH_REJECT; -        else if ((gen == RPCSVC_AUTH_REJECT) && (spec == RPCSVC_AUTH_REJECT)) -                final = RPCSVC_AUTH_REJECT; - -        return final; -} - - - -/* Combines the result of the general rule test against, the specific rule - * to determine final test for the connection coming in for a given volume. - * - * | @gen   | @spec   | Result | - * |    A   |   A     | A      | - * |    A   |   R     | R      | - * |    A   |   D     | A      | - * |    D   |   A     | A      | - * |    D   |   R     | R      | - * |    D   |   D     | R      |, special case, we intentionally disallow this. - * |    R   |   A     | A      | - * |    R   |   D     | R      | - * |    R   |   R     | R      | - */ -int -rpcsvc_combine_gen_spec_volume_checks (int gen, int spec) -{ -        int     final = RPCSVC_AUTH_REJECT; - -        if ((gen == RPCSVC_AUTH_ACCEPT) && (spec == RPCSVC_AUTH_ACCEPT)) -                final = RPCSVC_AUTH_ACCEPT; -        else if ((gen == RPCSVC_AUTH_ACCEPT) && (spec == RPCSVC_AUTH_REJECT)) -                final = RPCSVC_AUTH_REJECT; -        else if ((gen == RPCSVC_AUTH_ACCEPT) && (spec == RPCSVC_AUTH_DONTCARE)) -                final = RPCSVC_AUTH_ACCEPT; -        else if ((gen == RPCSVC_AUTH_DONTCARE) && (spec == RPCSVC_AUTH_ACCEPT)) -                final = RPCSVC_AUTH_ACCEPT; -        else if ((gen == RPCSVC_AUTH_DONTCARE) && (spec == RPCSVC_AUTH_REJECT)) -                final = RPCSVC_AUTH_REJECT; -        /* On no rule, we reject. */ -        else if ((gen == RPCSVC_AUTH_DONTCARE) && (spec== RPCSVC_AUTH_DONTCARE)) -                final = RPCSVC_AUTH_REJECT; -        else if ((gen == RPCSVC_AUTH_REJECT) && (spec == RPCSVC_AUTH_ACCEPT)) -                final = RPCSVC_AUTH_ACCEPT; -        else if ((gen == RPCSVC_AUTH_REJECT) && (spec == RPCSVC_AUTH_DONTCARE)) -                final = RPCSVC_AUTH_REJECT; -        else if ((gen == RPCSVC_AUTH_REJECT) && (spec == RPCSVC_AUTH_REJECT)) -                final = RPCSVC_AUTH_REJECT; - -        return final; -} - - -int -rpcsvc_transport_peer_check_name (dict_t *options, char *volname, -                                  rpc_transport_t *trans) -{ -        int     ret = RPCSVC_AUTH_REJECT; -        int     aret = RPCSVC_AUTH_REJECT; -        int     rjret = RPCSVC_AUTH_REJECT; -        char    clstr[RPCSVC_PEER_STRLEN]; -        char   *hostname    = NULL; - -        if (!trans) -                return ret; - -        ret = rpcsvc_transport_peername (trans, clstr, RPCSVC_PEER_STRLEN); -        if (ret != 0) { -                gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to get remote addr: " -                        "%s", gai_strerror (ret)); -                ret = RPCSVC_AUTH_REJECT; -                goto err; -        } - -        ret = gf_get_hostname_from_ip (clstr, &hostname); -        if (!ret) -                ret = dict_set_dynstr (options, "fqdn", -                                       hostname); - -        aret = rpcsvc_transport_peer_check_allow (options, volname, clstr); -        rjret = rpcsvc_transport_peer_check_reject (options, volname, clstr); +        if (allow == RPCSVC_AUTH_REJECT || +            reject == RPCSVC_AUTH_REJECT) +                return RPCSVC_AUTH_REJECT; -        ret = rpcsvc_combine_allow_reject_volume_check (aret, rjret); +        if (allow == RPCSVC_AUTH_ACCEPT || +            reject == RPCSVC_AUTH_ACCEPT) +                return RPCSVC_AUTH_ACCEPT; -err: -        return ret; +        return RPCSVC_AUTH_DONTCARE;  } -  int -rpcsvc_transport_peer_check_addr (dict_t *options, char *volname, -                                  rpc_transport_t *trans) +rpcsvc_auth_check (dict_t *options, char *volname, +                   rpc_transport_t *trans)  { -        int     ret = RPCSVC_AUTH_REJECT; -        int     aret = RPCSVC_AUTH_DONTCARE; -        int     rjret = RPCSVC_AUTH_REJECT; -        char    clstr[RPCSVC_PEER_STRLEN]; -        char   *tmp   = NULL; -        union gf_sock_union sock_union; - -        if (!trans) +        int     ret                            = RPCSVC_AUTH_REJECT; +        int     accept                         = RPCSVC_AUTH_REJECT; +        int     reject                         = RPCSVC_AUTH_REJECT; +        char   *hostname                       = NULL; +        char   *ip                             = NULL; +        char    client_ip[RPCSVC_PEER_STRLEN]  = {0}; + +        if (!options || !volname || !trans)                  return ret; -        ret = rpcsvc_transport_peeraddr (trans, clstr, RPCSVC_PEER_STRLEN, -                                         &sock_union.storage, -                                         sizeof (sock_union.storage)); +        ret = rpcsvc_transport_peername (trans, client_ip, RPCSVC_PEER_STRLEN);          if (ret != 0) {                  gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to get remote addr: "                          "%s", gai_strerror (ret)); -                ret = RPCSVC_AUTH_REJECT; -                goto err; -        } - -        switch (sock_union.sa.sa_family) { - -        case AF_INET: -        case AF_INET6: -                tmp = strrchr (clstr, ':'); -                if (tmp) -                        *tmp = '\0'; -                break; -        } - -        aret = rpcsvc_transport_peer_check_allow (options, volname, clstr); -        rjret = rpcsvc_transport_peer_check_reject (options, volname, clstr); - -        ret = rpcsvc_combine_allow_reject_volume_check (aret, rjret); -err: -        return ret; -} - - -int -rpcsvc_transport_check_volume_specific (dict_t *options, char *volname, -                                        rpc_transport_t *trans) -{ -        int             namechk = RPCSVC_AUTH_REJECT; -        int             addrchk = RPCSVC_AUTH_REJECT; -        gf_boolean_t    namelookup = _gf_false; -        char            *namestr = NULL; -        int             ret = 0; - -        if ((!options) || (!volname) || (!trans))                  return RPCSVC_AUTH_REJECT; - -        /* Disabled by default */ -        if ((dict_get (options, "rpc-auth.addr.namelookup"))) { -                ret = dict_get_str (options, "rpc-auth.addr.namelookup" -                                    , &namestr); -                if (ret == 0) -                        ret = gf_string2boolean (namestr, &namelookup);          } -        /* We need two separate checks because the rules with addresses in them -         * can be network addresses which can be general and names can be -         * specific which will over-ride the network address rules. -         */ -        if (namelookup) -                namechk = rpcsvc_transport_peer_check_name (options, volname, -                                                            trans); -        addrchk = rpcsvc_transport_peer_check_addr (options, volname, trans); - -        if (namelookup) -                ret = rpcsvc_combine_gen_spec_addr_checks (addrchk, -                                                               namechk); -        else -                ret = addrchk; - -        return ret; -} +        get_host_name (client_ip, &ip); +        /* addr-namelookup disabled by default */ +        ret = dict_get_str_boolean (options, "rpc-auth.addr.namelookup", 0); +        if (ret == _gf_true) +                gf_get_hostname_from_ip (ip, &hostname); -int -rpcsvc_transport_check_volume_general (dict_t *options, rpc_transport_t *trans) -{ -        int             addrchk = RPCSVC_AUTH_REJECT; -        int             namechk = RPCSVC_AUTH_REJECT; -        gf_boolean_t    namelookup = _gf_false; -        char            *namestr = NULL; -        int             ret = 0; +        accept = rpcsvc_transport_peer_check_allow (options, volname, +                                                    ip, hostname); -        if ((!options) || (!trans)) -                return RPCSVC_AUTH_REJECT; +        reject = rpcsvc_transport_peer_check_reject (options, volname, +                                                     ip, hostname); -        /* Disabled by default */ -        if ((dict_get (options, "rpc-auth.addr.namelookup"))) { -                ret = dict_get_str (options, "rpc-auth.addr.namelookup" -                                    , &namestr); -                if (ret == 0) -                        ret = gf_string2boolean (namestr, &namelookup); -        } - -        /* We need two separate checks because the rules with addresses in them -         * can be network addresses which can be general and names can be -         * specific which will over-ride the network address rules. -         */ -        if (namelookup) -                namechk = rpcsvc_transport_peer_check_name (options, NULL, trans); -        addrchk = rpcsvc_transport_peer_check_addr (options, NULL, trans); - -        if (namelookup) -                ret = rpcsvc_combine_gen_spec_addr_checks (addrchk, namechk); -        else -                ret = addrchk; - -        return ret; -} - -int -rpcsvc_transport_peer_check (dict_t *options, char *volname, -                             rpc_transport_t *trans) -{ -        int     general_chk = RPCSVC_AUTH_REJECT; -        int     specific_chk = RPCSVC_AUTH_REJECT; - -        if ((!options) || (!volname) || (!trans)) -                return RPCSVC_AUTH_REJECT; - -        general_chk = rpcsvc_transport_check_volume_general (options, trans); -        specific_chk = rpcsvc_transport_check_volume_specific (options, volname, -                                                               trans); - -        return rpcsvc_combine_gen_spec_volume_checks (general_chk, -                                                      specific_chk); +        return rpcsvc_combine_allow_reject_volume_check (accept, reject);  } -  int  rpcsvc_transport_privport_check (rpcsvc_t *svc, char *volname,                                   rpc_transport_t *trans) @@ -2363,8 +2102,6 @@ rpcsvc_transport_privport_check (rpcsvc_t *svc, char *volname,          socklen_t               sinsize = sizeof (&sock_union.sin);          char                    *srchstr = NULL;          char                    *valstr = NULL; -        int                     globalinsecure = RPCSVC_AUTH_REJECT; -        int                     exportinsecure = RPCSVC_AUTH_DONTCARE;          uint16_t                port = 0;          gf_boolean_t            insecure = _gf_false; @@ -2393,23 +2130,6 @@ rpcsvc_transport_privport_check (rpcsvc_t *svc, char *volname,          }          /* Disabled by default */ -        if ((dict_get (svc->options, "rpc-auth.ports.insecure"))) { -                ret = dict_get_str (svc->options, "rpc-auth.ports.insecure" -                                    , &srchstr); -                if (ret == 0) { -                        ret = gf_string2boolean (srchstr, &insecure); -                        if (ret == 0) { -                                if (insecure == _gf_true) -                                        globalinsecure = RPCSVC_AUTH_ACCEPT; -                        } else -                                gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to" -                                        " read rpc-auth.ports.insecure value"); -                } else -                        gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to" -                                " read rpc-auth.ports.insecure value"); -        } - -        /* Disabled by default */          ret = gf_asprintf (&srchstr, "rpc-auth.ports.%s.insecure", volname);          if (ret == -1) {                  gf_log (GF_RPCSVC, GF_LOG_ERROR, "asprintf failed"); @@ -2417,25 +2137,22 @@ rpcsvc_transport_privport_check (rpcsvc_t *svc, char *volname,                  goto err;          } -        if (dict_get (svc->options, srchstr)) { -                ret = dict_get_str (svc->options, srchstr, &valstr); -                if (ret == 0) { -                        ret = gf_string2boolean (valstr, &insecure); -                        if (ret == 0) { -                                if (insecure == _gf_true) -                                       exportinsecure = RPCSVC_AUTH_ACCEPT; -                                else -                                        exportinsecure = RPCSVC_AUTH_REJECT; -                        } else -                                gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to" -                                        " read rpc-auth.ports.insecure value"); -                } else -                        gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to" -                                " read rpc-auth.ports.insecure value"); -        } - -        ret = rpcsvc_combine_gen_spec_volume_checks (globalinsecure, -                                                         exportinsecure); +        ret = dict_get_str (svc->options, srchstr, &valstr); +        if (ret) { +                gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to" +                        " read rpc-auth.ports.insecure value"); +                goto err; +        } + +        ret = gf_string2boolean (valstr, &insecure); +        if (ret) { +                gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to" +                        " convert rpc-auth.ports.insecure value"); +                goto err; +        } + +        ret = insecure ? RPCSVC_AUTH_ACCEPT : RPCSVC_AUTH_REJECT; +          if (ret == RPCSVC_AUTH_ACCEPT)                  gf_log (GF_RPCSVC, GF_LOG_DEBUG, "Unprivileged port allowed");          else @@ -2443,7 +2160,8 @@ rpcsvc_transport_privport_check (rpcsvc_t *svc, char *volname,                          " allowed");  err: -        GF_FREE (srchstr); +        if (srchstr) +                GF_FREE (srchstr);          return ret;  } diff --git a/rpc/rpc-lib/src/rpcsvc.h b/rpc/rpc-lib/src/rpcsvc.h index 1323c8b7aee..afa7c992634 100644 --- a/rpc/rpc-lib/src/rpcsvc.h +++ b/rpc/rpc-lib/src/rpcsvc.h @@ -473,12 +473,13 @@ rpcsvc_transport_peeraddr (rpc_transport_t *trans, char *addrstr, int addrlen,                             struct sockaddr_storage *returnsa, socklen_t sasize);  extern int -rpcsvc_transport_peer_check (dict_t *options, char *volname, -                             rpc_transport_t *trans); +rpcsvc_auth_check (dict_t *options, char *volname, +                   rpc_transport_t *trans);  extern int  rpcsvc_transport_privport_check (rpcsvc_t *svc, char *volname,                                   rpc_transport_t *trans); +  #define rpcsvc_request_seterr(req, err)                 (req)->rpc_err = err  #define rpcsvc_request_set_autherr(req, err)            (req)->auth_err = err @@ -550,9 +551,6 @@ rpcsvc_auth_array (rpcsvc_t *svc, char *volname, int *autharr, int arrlen);  extern gid_t *  rpcsvc_auth_unix_auxgids (rpcsvc_request_t *req, int *arrlen); -extern int -rpcsvc_combine_gen_spec_volume_checks (int gen, int spec); -  extern char *  rpcsvc_volume_allowed (dict_t *options, char *volname); diff --git a/tests/bugs/bug-921072.t b/tests/bugs/bug-921072.t new file mode 100755 index 00000000000..c7fff75f103 --- /dev/null +++ b/tests/bugs/bug-921072.t @@ -0,0 +1,135 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc + +cleanup; + +# sleeps till the portmap registration of nfs services is done +# NOTE: may take some time for nfs to export all volumes, hence, +# showmount -e succeeding does NOT mean all volumes are available +# for mount. In this case, its a single single-brick volume, +# so no problem. +sleep_till_nfs_awakens () +{ +    while true +    do +        showmount -e 0 > /dev/null 2>&1; +        if [ $? -eq 0 ]; then +            return; +        else +            sleep 1; +        fi +    done +} + +#1 +TEST glusterd +TEST pidof glusterd + +TEST $CLI volume create $V0 $H0:$B0/$V0 +TEST $CLI volume start $V0 +sleep_till_nfs_awakens +TEST mount -t nfs -o vers=3,nolock,soft,intr $H0:/$V0 $N0 +TEST umount $N0 + +# based on ip addresses (1-4) +# case 1: allow only localhost ip +TEST $CLI volume set $V0 nfs.rpc-auth-allow 127.0.0.1 +sleep_till_nfs_awakens + +TEST mount -t nfs -o vers=3,nolock,soft,intr localhost:/$V0 $N0 +TEST umount $N0 + +# case 2: allow only non-localhost ip +TEST $CLI volume set $V0 nfs.rpc-auth-allow 192.168.1.1 +sleep_till_nfs_awakens +#11 +TEST ! mount -t nfs -o vers=3,nolock,soft,intr localhost:/$V0 $N0 +TEST $CLI volume reset --mode=script $V0 +# case 3: reject only localhost ip +TEST $CLI volume set $V0 nfs.rpc-auth-reject 127.0.0.1 +sleep_till_nfs_awakens + +TEST ! mount -t nfs -o vers=3,nolock,soft,intr localhost:/$V0 $N0 + +# case 4: reject only non-localhost ip +TEST $CLI volume set $V0 nfs.rpc-auth-reject 192.168.1.1 +sleep_till_nfs_awakens + +TEST mount -t nfs -o vers=3,nolock,soft,intr localhost:/$V0 $N0 +TEST umount $N0 + + + +# NEED TO CHECK BOTH IP AND NAME BASED AUTH. +# CASES WITH NFS.ADDR-NAMELOOKUP ON (5-12) +TEST $CLI volume reset --mode=script $V0 +TEST $CLI volume set $V0 nfs.addr-namelookup on +sleep_till_nfs_awakens +#20 +TEST mount -t nfs -o vers=3,nolock,soft,intr localhost:/$V0 $N0 +TEST umount $N0 + +# case 5: allow only localhost +TEST $CLI volume set $V0 nfs.rpc-auth-allow localhost +sleep_till_nfs_awakens + +TEST mount -t nfs -o vers=3,nolock,soft,intr localhost:/$V0 $N0 +TEST umount $N0 + +# case 6: allow only somehost +TEST $CLI volume set $V0 nfs.rpc-auth-allow somehost +sleep_till_nfs_awakens + +TEST ! mount -t nfs -o vers=3,nolock,soft,intr localhost:/$V0 $N0 + +# case 7: reject only localhost +TEST $CLI volume reset --mode=script $V0 +TEST $CLI volume set $V0 nfs.addr-namelookup on +TEST $CLI volume set $V0 nfs.rpc-auth-reject localhost +sleep_till_nfs_awakens +#30 +TEST ! mount -t nfs -o vers=3,nolock,soft,intr localhost:/$V0 $N0 + +# case 8: reject only somehost +TEST $CLI volume set $V0 nfs.rpc-auth-reject somehost +sleep_till_nfs_awakens + +TEST mount -t nfs -o vers=3,nolock,soft,intr localhost:/$V0 $N0 +TEST umount $N0 + +# based on ip addresses: repeat of cases 1-4 +# case 9: allow only localhost ip +TEST $CLI volume reset --mode=script $V0 +TEST $CLI volume set $V0 nfs.addr-namelookup on +TEST $CLI volume set $V0 nfs.rpc-auth-allow 127.0.0.1 +sleep_till_nfs_awakens + +TEST mount -t nfs -o vers=3,nolock,soft,intr localhost:/$V0 $N0 +TEST umount $N0 + +# case 10: allow a non-localhost ip +TEST $CLI volume set $V0 nfs.rpc-auth-allow 192.168.1.1 +sleep_till_nfs_awakens +#40 +TEST ! mount -t nfs -o vers=3,nolock,soft,intr localhost:/$V0 $N0 + +# case 11: reject only localhost ip +TEST $CLI volume reset --mode=script $V0 +TEST $CLI volume set $V0 nfs.addr-namelookup on +TEST $CLI volume set $V0 nfs.rpc-auth-reject 127.0.0.1 +sleep_till_nfs_awakens + +TEST ! mount -t nfs -o vers=3,nolock,soft,intr localhost:/$V0 $N0 + +# case 12: reject only non-localhost ip +TEST $CLI volume set $V0 nfs.rpc-auth-reject 192.168.1.1 +sleep_till_nfs_awakens + +TEST mount -t nfs -o vers=3,nolock,soft,intr localhost:/$V0 $N0 +TEST umount $N0 + +TEST $CLI volume stop --mode=script $V0 +#49 +TEST $CLI volume delete --mode=script $V0 +cleanup diff --git a/xlators/nfs/server/src/mount3.c b/xlators/nfs/server/src/mount3.c index 255310fa800..39d736e7d17 100644 --- a/xlators/nfs/server/src/mount3.c +++ b/xlators/nfs/server/src/mount3.c @@ -781,8 +781,7 @@ mnt3_check_client_net (struct mount3_state *ms, rpcsvc_request_t *req,                          gai_strerror (ret));          } -        ret = rpcsvc_transport_peer_check (svc->options, targetxl->name, -                                           trans); +        ret = rpcsvc_auth_check (svc->options, targetxl->name, trans);          if (ret == RPCSVC_AUTH_REJECT) {                  gf_log (GF_MNT, GF_LOG_INFO, "Peer %s  not allowed", peer);                  goto err;  | 
