diff options
| author | Santosh Kumar Pradhan <spradhan@redhat.com> | 2014-04-09 10:19:43 +0530 | 
|---|---|---|
| committer | Vijay Bellur <vbellur@redhat.com> | 2014-04-22 23:40:26 -0700 | 
| commit | 00e247ee44067f2b3e7ca5f7e6dc2f7934c97181 (patch) | |
| tree | 43868ec642fae37fcb013e8c2f66659bf9d7b3cc /rpc/rpc-lib/src | |
| parent | b6cc23204f1941184cb08ec3d84beecd2d06fd91 (diff) | |
gNFS: Support wildcard in RPC auth allow/reject
RFE: Support wildcard in "nfs.rpc-auth-allow" and
"nfs.rpc-auth-reject". e.g.
  *.redhat.com
  192.168.1[1-5].*
  192.168.1[1-5].*, *.redhat.com, 192.168.21.9
  Along with wildcard, support for subnetwork or IP range e.g.
  192.168.10.23/24
The option will be validated for following categories:
1) Anonymous i.e. "*"
2) Wildcard pattern i.e. string containing any ('*', '?', '[')
3) IPv4 address
4) IPv6 address
5) FQDN
6) subnetwork or IPv4 range
Currently this does not support IPv6 subnetwork.
Change-Id: Iac8caf5e490c8174d61111dad47fd547d4f67bf4
BUG: 1086097
Signed-off-by: Santosh Kumar Pradhan <spradhan@redhat.com>
Reviewed-on: http://review.gluster.org/7485
Reviewed-by: Poornima G <pgurusid@redhat.com>
Reviewed-by: Harshavardhana <harsha@harshavardhana.net>
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
Diffstat (limited to 'rpc/rpc-lib/src')
| -rw-r--r-- | rpc/rpc-lib/src/rpcsvc.c | 91 | 
1 files changed, 89 insertions, 2 deletions
diff --git a/rpc/rpc-lib/src/rpcsvc.c b/rpc/rpc-lib/src/rpcsvc.c index 8be64c18aa2..34ee6f21b49 100644 --- a/rpc/rpc-lib/src/rpcsvc.c +++ b/rpc/rpc-lib/src/rpcsvc.c @@ -59,6 +59,9 @@ int  rpcsvc_notify (rpc_transport_t *trans, void *mydata,                 rpc_transport_event_t event, void *data, ...); +static int +match_subnet_v4 (const char *addrtok, const char *ipaddr); +  rpcsvc_notify_wrapper_t *  rpcsvc_notify_wrapper_alloc (void)  { @@ -2181,6 +2184,13 @@ rpcsvc_transport_peer_check_search (dict_t *options, char *pattern,                                  goto err;                  } +                /* Compare IPv4 subnetwork */ +                if (strchr (addrtok, '/')) { +                        ret = match_subnet_v4 (addrtok, ip); +                        if (ret == 0) +                                goto err; +                } +                  addrtok = strtok_r (NULL, ",", &svptr);          } @@ -2327,8 +2337,20 @@ rpcsvc_auth_check (rpcsvc_t *svc, char *volname,          ret = dict_get_str (options, srchstr, &reject_str);          GF_FREE (srchstr); -        if (reject_str == NULL && !strcmp ("*", allow_str)) -                return RPCSVC_AUTH_ACCEPT; + +        /* +         * If "reject_str" is being set as '*' (anonymous), then NFS-server +         * would reject everything. If the "reject_str" is not set and +         * "allow_str" is set as '*' (anonymous), then NFS-server would +         * accept mount requests from all clients. +         */ +        if (reject_str != NULL) { +                if (!strcmp ("*", reject_str)) +                        return RPCSVC_AUTH_REJECT; +        } else { +                if (!strcmp ("*", allow_str)) +                        return RPCSVC_AUTH_ACCEPT; +        }          /* Non-default rule, authenticate */          if (!get_host_name (client_ip, &ip)) @@ -2461,6 +2483,71 @@ out:          return addrstr;  } +/* + * match_subnet_v4() takes subnetwork address pattern and checks + * if the target IPv4 address has the same network address with + * the help of network mask. + * + * Returns 0 for SUCCESS and -1 otherwise. + * + * NB: Validation of subnetwork address pattern is not required + *     as it's already being done at the time of CLI SET. + */ +static int +match_subnet_v4 (const char *addrtok, const char *ipaddr) +{ +        char                 *slash     = NULL; +        char                 *netaddr   = NULL; +        long                  prefixlen = -1; +        int                   ret       = -1; +        uint32_t              shift     = 0; +        struct sockaddr_in    sin1      = {0, }; +        struct sockaddr_in    sin2      = {0, }; +        struct sockaddr_in    mask      = {0, }; + +        /* Copy the input */ +        netaddr = gf_strdup (addrtok); +        if (netaddr == NULL) /* ENOMEM */ +                goto out; + +        /* Find the network socket addr of target */ +        if (inet_pton (AF_INET, ipaddr, &sin1.sin_addr) == 0) +                goto out; + +        /* Find the network socket addr of subnet pattern */ +        slash = strchr (netaddr, '/'); +        *slash = '\0'; +        if (inet_pton (AF_INET, netaddr, &sin2.sin_addr) == 0) +                goto out; + +        /* +         * Find the network mask in network byte order. +         * NB: 32 : Max len of IPv4 address. +         */ +        prefixlen = atoi (slash + 1); +        shift = 32 - (uint32_t)prefixlen; +        mask.sin_addr.s_addr = htonl ((uint32_t)~0 << shift); + +        /* +         * Check if both have same network address. +         * Extract the network address from the IP addr by applying the +         * network mask. If they match, return SUCCESS. i.e. +         * +         * (x == y) <=> (x ^ y == 0) +         * (x & y) ^ (x & z) <=> x & (y ^ z) +         * +         * ((ip1 & mask) == (ip2 & mask)) <=> ((mask & (ip1 ^ ip2)) == 0) +         */ +        if (((mask.sin_addr.s_addr) & +             (sin1.sin_addr.s_addr ^ sin2.sin_addr.s_addr)) != 0) +                goto out; + +        ret = 0; /* SUCCESS */ +out: +        GF_FREE (netaddr); +        return ret; +} +  rpcsvc_actor_t gluster_dump_actors[] = {          [GF_DUMP_NULL]      = {"NULL",     GF_DUMP_NULL,     NULL,        NULL, 0, DRC_NA},  | 
