From 0b7cdbf50dea9ee77bc8f71526a1566945672c19 Mon Sep 17 00:00:00 2001 From: Rajesh Amaravathi Date: Mon, 28 Jan 2013 18:16:32 +0530 Subject: 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 Reviewed-on: http://review.gluster.org/4439 Tested-by: Gluster Build System Reviewed-by: Anand Avati --- libglusterfs/src/common-utils.c | 71 +++++++++++++++++++++++++++++++++++++++++ libglusterfs/src/common-utils.h | 1 + rpc/rpc-lib/src/rpcsvc.c | 20 ++++++++++++ xlators/nfs/server/src/mount3.c | 4 +++ 4 files changed, 96 insertions(+) diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c index 22f138614..75b977225 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 b89a988c6..bbafd1fb0 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 7cb89db09..c8595ee8e 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 efd74aa58..255310fa8 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, }; -- cgit