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; |