diff options
author | Rajesh Amaravathi <rajesh@redhat.com> | 2013-01-28 18:16:32 +0530 |
---|---|---|
committer | Anand Avati <avati@redhat.com> | 2013-02-06 16:15:54 -0800 |
commit | 0b7cdbf50dea9ee77bc8f71526a1566945672c19 (patch) | |
tree | b574ace1e33b0d234e9986545747e625b614de04 | |
parent | 2197c8b41423a7a9a5e55db0d3a5a27131966e72 (diff) |
rpc: get hostnames of client to allow FQDN based authentication
If FQDNs are used to authenticate clients, then from
this commit forth, the client ip(v4,6) is reverse looked up
using getnameinfo to get a hostname associated with it,
if any, thereby making FQDN-based rpc authentication possible.
Change-Id: I4c5241e7079a2560de79ca15f611e65c0b858f9b
BUG: 903553
Signed-off-by: Rajesh Amaravathi <rajesh@redhat.com>
Reviewed-on: http://review.gluster.org/4439
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Anand Avati <avati@redhat.com>
-rw-r--r-- | libglusterfs/src/common-utils.c | 71 | ||||
-rw-r--r-- | libglusterfs/src/common-utils.h | 1 | ||||
-rw-r--r-- | rpc/rpc-lib/src/rpcsvc.c | 20 | ||||
-rw-r--r-- | xlators/nfs/server/src/mount3.c | 4 |
4 files changed, 96 insertions, 0 deletions
diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c index 22f13861451..75b97722513 100644 --- a/libglusterfs/src/common-utils.c +++ b/libglusterfs/src/common-utils.c @@ -2337,3 +2337,74 @@ gf_ports_reserved (char *blocked_port, gf_boolean_t *ports) out: return result; } + +/* Takes in client ip{v4,v6} and returns associated hostname, if any + * Also, allocates memory for the hostname. + * Returns: 0 for success, -1 for failure + */ +int +gf_get_hostname_from_ip (char *client_ip, char **hostname) +{ + int ret = -1; + struct sockaddr *client_sockaddr = NULL; + struct sockaddr_in client_sock_in = {0}; + struct sockaddr_in6 client_sock_in6 = {0}; + char client_hostname[NI_MAXHOST] = {0}; + char *client_ip_copy = NULL; + char *tmp = NULL; + char *ip = NULL; + + /* if ipv4, reverse lookup the hostname to + * allow FQDN based rpc authentication + */ + if (valid_ipv4_address (client_ip, strlen (client_ip), 0) == _gf_false) { + /* most times, we get a.b.c.d:port form, so check that */ + client_ip_copy = gf_strdup (client_ip); + if (!client_ip_copy) + goto out; + + ip = strtok_r (client_ip_copy, ":", &tmp); + } else { + ip = client_ip; + } + + if (valid_ipv4_address (ip, strlen (ip), 0) == _gf_true) { + client_sockaddr = (struct sockaddr *)&client_sock_in; + client_sock_in.sin_family = AF_INET; + ret = inet_pton (AF_INET, ip, + (void *)&client_sock_in.sin_addr.s_addr); + + } else if (valid_ipv6_address (ip, strlen (ip), 0) == _gf_true) { + client_sockaddr = (struct sockaddr *) &client_sock_in6; + + client_sock_in6.sin6_family = AF_INET6; + ret = inet_pton (AF_INET6, ip, + (void *)&client_sock_in6.sin6_addr); + } else { + goto out; + } + + if (ret != 1) { + ret = -1; + goto out; + } + + ret = getnameinfo (client_sockaddr, + sizeof (*client_sockaddr), + client_hostname, sizeof (client_hostname), + NULL, 0, 0); + if (ret) { + gf_log ("common-utils", GF_LOG_ERROR, + "Could not lookup hostname of %s : %s", + client_ip, gai_strerror (ret)); + ret = -1; + goto out; + } + + *hostname = gf_strdup ((char *)client_hostname); + out: + if (client_ip_copy) + GF_FREE (client_ip_copy); + + return ret; +} diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h index b89a988c62c..bbafd1fb039 100644 --- a/libglusterfs/src/common-utils.h +++ b/libglusterfs/src/common-utils.h @@ -575,5 +575,6 @@ char *generate_glusterfs_ctx_id (void); char *gf_get_reserved_ports(); int gf_process_reserved_ports (gf_boolean_t ports[]); gf_boolean_t gf_ports_reserved (char *blocked_port, gf_boolean_t *ports); +int gf_get_hostname_from_ip (char *client_ip, char **hostname); #endif /* _COMMON_UTILS_H */ diff --git a/rpc/rpc-lib/src/rpcsvc.c b/rpc/rpc-lib/src/rpcsvc.c index 7cb89db0946..c8595ee8ed1 100644 --- a/rpc/rpc-lib/src/rpcsvc.c +++ b/rpc/rpc-lib/src/rpcsvc.c @@ -1925,10 +1925,13 @@ rpcsvc_transport_peer_check_search (dict_t *options, char *pattern, char *clstr) char *addrstr = NULL; char *dup_addrstr = NULL; char *svptr = NULL; + char *fqdn = NULL; if ((!options) || (!clstr)) return -1; + ret = dict_get_str (options, "client.fqdn", &fqdn); + if (!dict_get (options, pattern)) return -1; @@ -1956,6 +1959,17 @@ rpcsvc_transport_peer_check_search (dict_t *options, char *pattern, char *clstr) if (ret == 0) goto err; + /* compare hostnames if applicable */ + if (fqdn) { +#ifdef FNM_CASEFOLD + ret = fnmatch (addrtok, fqdn, FNM_CASEFOLD); +#else + ret = fnmatch (addrtok, fqdn, 0); +#endif + if (ret == 0) + goto err; + } + addrtok = strtok_r (NULL, ",", &svptr); } @@ -2174,6 +2188,7 @@ rpcsvc_transport_peer_check_name (dict_t *options, char *volname, int aret = RPCSVC_AUTH_REJECT; int rjret = RPCSVC_AUTH_REJECT; char clstr[RPCSVC_PEER_STRLEN]; + char *hostname = NULL; if (!trans) return ret; @@ -2186,6 +2201,11 @@ rpcsvc_transport_peer_check_name (dict_t *options, char *volname, goto err; } + ret = gf_get_hostname_from_ip (clstr, &hostname); + if (!ret) + ret = dict_set_dynstr (options, "client.fqdn", + hostname); + aret = rpcsvc_transport_peer_check_allow (options, volname, clstr); rjret = rpcsvc_transport_peer_check_reject (options, volname, clstr); diff --git a/xlators/nfs/server/src/mount3.c b/xlators/nfs/server/src/mount3.c index efd74aa58ac..255310fa800 100644 --- a/xlators/nfs/server/src/mount3.c +++ b/xlators/nfs/server/src/mount3.c @@ -1856,6 +1856,8 @@ rpcsvc_actor_t mnt3svc_actors[MOUNT3_PROC_COUNT] = { /* Static init parts are assigned here, dynamic ones are done in * mnt3svc_init and mnt3_init_state. + * Making MOUNT3 a synctask so that the blocking DNS calls during rpc auth + * gets offloaded to syncenv, keeping the main/poll thread unblocked */ rpcsvc_program_t mnt3prog = { .progname = "MOUNT3", @@ -1865,6 +1867,7 @@ rpcsvc_program_t mnt3prog = { .actors = mnt3svc_actors, .numactors = MOUNT3_PROC_COUNT, .min_auth = AUTH_NULL, + .synctask = _gf_true, }; @@ -1953,6 +1956,7 @@ rpcsvc_program_t mnt1prog = { .actors = mnt1svc_actors, .numactors = MOUNT1_PROC_COUNT, .min_auth = AUTH_NULL, + .synctask = _gf_true, }; |