diff options
author | Niels de Vos <ndevos@redhat.com> | 2014-06-29 16:30:30 +0200 |
---|---|---|
committer | Niels de Vos <ndevos@redhat.com> | 2014-07-02 00:53:18 -0700 |
commit | cacc1311626aa8b2dfe9f937cf1b14bb534a8937 (patch) | |
tree | 63369e3f37d058444f2ce93640684af0f407ecae /rpc/rpc-lib | |
parent | cf5a5ab1a81bb61bb66982757ccd301d015ac16e (diff) |
gNFS: Fix multi-homed m/c issue in NFS subdir auth
NFS subdir authentication doesn't correctly handle multi-homed
(host with multiple NIC having multiple IP addr) OR multi-protocol
(IPv4 and IPv6) network addresses.
When user/admin sets HOSTNAME in gluster CLI for NFS subdir auth,
mnt3_verify_auth() routine does not iterate over all the resolved
n/w addrs returned by getaddrinfo() n/w API. Instead, it just tests
with the one returned first.
1. Iterate over all the n/w addrs (linked list) returned by getaddrinfo().
2. Move the n/w mask calculation part to mnt3_export_fill_hostspec()
instead of doing it in mnt3_verify_auth() i.e. calculating for each
mount request. It does not change for MOUNT req.
3. Integrate "subnet support code rpc-auth.addr.<volname>.allow"
and "NFS subdir auth code" to remove code duplication.
Cherry-picked from commit d3f0de90d0c5166e63f5764d2f21703fd29ce976:
> Change-Id: I26b0def52c22cda35ca11766afca3df5fd4360bf
> BUG: 1102293
> Signed-off-by: Santosh Kumar Pradhan <spradhan@redhat.com>
> Reviewed-on: http://review.gluster.org/8048
> Reviewed-by: Rajesh Joseph <rjoseph@redhat.com>
> Tested-by: Gluster Build System <jenkins@build.gluster.com>
> Reviewed-by: Niels de Vos <ndevos@redhat.com>
Change-Id: Ie92a8ac602bec2cd77268acb7b23ad8ba3c52f5f
BUG: 1112980
Signed-off-by: Niels de Vos <ndevos@redhat.com>
Reviewed-on: http://review.gluster.org/8198
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Santosh Pradhan <spradhan@redhat.com>
Diffstat (limited to 'rpc/rpc-lib')
-rw-r--r-- | rpc/rpc-lib/src/rpcsvc.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/rpc/rpc-lib/src/rpcsvc.c b/rpc/rpc-lib/src/rpcsvc.c index 9374ee7328f..a751330a7c9 100644 --- a/rpc/rpc-lib/src/rpcsvc.c +++ b/rpc/rpc-lib/src/rpcsvc.c @@ -60,6 +60,9 @@ int rpcsvc_notify (rpc_transport_t *trans, void *mydata, rpc_transport_event_t event, void *data, ...); +static int +rpcsvc_match_subnet_v4 (const char *addrtok, const char *ipaddr); + rpcsvc_notify_wrapper_t * rpcsvc_notify_wrapper_alloc (void) { @@ -2236,6 +2239,13 @@ rpcsvc_transport_peer_check_search (dict_t *options, char *pattern, goto err; } + /* Compare IPv4 subnetwork, TODO: IPv6 subnet support */ + if (strchr (addrtok, '/')) { + ret = rpcsvc_match_subnet_v4 (addrtok, ip); + if (ret == 0) + goto err; + } + addrtok = strtok_r (NULL, ",", &svptr); } @@ -2516,6 +2526,62 @@ out: return addrstr; } +/* + * rpcsvc_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 +rpcsvc_match_subnet_v4 (const char *addrtok, const char *ipaddr) +{ + char *slash = NULL; + char *netaddr = NULL; + int ret = -1; + uint32_t prefixlen = 0; + 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 IPv4 network mask in network byte order. + * IMP: String slash+1 is already validated, it cant have value + * more than IPv4_ADDR_SIZE (32). + */ + prefixlen = (uint32_t) atoi (slash + 1); + shift = IPv4_ADDR_SIZE - prefixlen; + mask.sin_addr.s_addr = htonl ((uint32_t)~0 << shift); + + if (mask_match (sin1.sin_addr.s_addr, + sin2.sin_addr.s_addr, + mask.sin_addr.s_addr)) { + 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}, |