Avoid DNS reverse resolution for server names (take 3)
authorSimo Sorce <simo@redhat.com>
Fri, 19 Apr 2013 14:10:33 +0000 (10:10 -0400)
committerSteve Dickson <steved@redhat.com>
Mon, 22 Apr 2013 16:47:20 +0000 (12:47 -0400)
A NFS client should be able to work properly even if the DNS Reverse
record for the server is not set. This means a DNS lookup should not be
done on server names at are passed to GSSAPI. This patch changes the default
behavior to no longer do those types of lookups

This change default behavior could negatively impact some current
environments, so the -D option is also being added that will re-enable
the DNS reverse looks on server names, which are passed to GSSAPI.

Signed-off-by: Simo Sorce <simo@redhat.com>
Signed-off-by: Steve Dickson <steved@redhat.com>
utils/gssd/gss_util.h
utils/gssd/gssd.c
utils/gssd/gssd.man
utils/gssd/gssd_proc.c

index aa9f778..c81fc5a 100644 (file)
@@ -52,4 +52,6 @@ int gssd_check_mechs(void);
                gss_krb5_set_allowable_enctypes(min, cred, num, types)
 #endif
 
+extern int avoid_dns;
+
 #endif /* _GSS_UTIL_H_ */
index 07b1e52..8ee478b 100644 (file)
@@ -85,7 +85,7 @@ sig_hup(int signal)
 static void
 usage(char *progname)
 {
-       fprintf(stderr, "usage: %s [-f] [-l] [-M] [-n] [-v] [-r] [-p pipefsdir] [-k keytab] [-d ccachedir] [-t timeout] [-R preferred realm]\n",
+       fprintf(stderr, "usage: %s [-f] [-l] [-M] [-n] [-v] [-r] [-p pipefsdir] [-k keytab] [-d ccachedir] [-t timeout] [-R preferred realm] [-D]\n",
                progname);
        exit(1);
 }
@@ -102,7 +102,7 @@ main(int argc, char *argv[])
        char *progname;
 
        memset(ccachesearch, 0, sizeof(ccachesearch));
-       while ((opt = getopt(argc, argv, "fvrlmnMp:k:d:t:R:")) != -1) {
+       while ((opt = getopt(argc, argv, "DfvrlmnMp:k:d:t:R:")) != -1) {
                switch (opt) {
                        case 'f':
                                fg = 1;
@@ -150,6 +150,9 @@ main(int argc, char *argv[])
                                errx(1, "Encryption type limits not supported by Kerberos libraries.");
 #endif
                                break;
+                       case 'D':
+                               avoid_dns = 0;
+                               break;
                        default:
                                usage(argv[0]);
                                break;
index 79d9bf9..1df75c5 100644 (file)
@@ -8,7 +8,7 @@
 rpc.gssd \- RPCSEC_GSS daemon
 .SH SYNOPSIS
 .B rpc.gssd
-.RB [ \-fMnlvr ]
+.RB [ \-DfMnlvr ]
 .RB [ \-k
 .IR keytab ]
 .RB [ \-p
@@ -195,6 +195,12 @@ option when starting
 .BR rpc.gssd .
 .SH OPTIONS
 .TP
+.B -D
+DNS Reverse lookups are not used for determining the
+server names pass to GSSAPI. This option will reverses that and forces 
+the use of DNS Reverse resolution of the server's IP address to 
+retrieve the server name to use in GSAPI authentication.
+.TP
 .B -f
 Runs
 .B rpc.gssd
index 2280088..af1844c 100644 (file)
@@ -67,6 +67,7 @@
 #include <errno.h>
 #include <gssapi/gssapi.h>
 #include <netdb.h>
+#include <ctype.h>
 
 #include "gssd.h"
 #include "err_util.h"
@@ -107,6 +108,9 @@ struct pollfd * pollarray;
 
 unsigned long pollsize;  /* the size of pollaray (in pollfd's) */
 
+/* Avoid DNS reverse lookups on server names */
+int avoid_dns = 1;
+
 /*
  * convert a presentation address string to a sockaddr_storage struct. Returns
  * true on success or false on failure.
@@ -165,12 +169,31 @@ addrstr_to_sockaddr(struct sockaddr *sa, const char *node, const char *port)
  * convert a sockaddr to a hostname
  */
 static char *
-sockaddr_to_hostname(const struct sockaddr *sa, const char *addr)
+get_servername(const char *name, const struct sockaddr *sa, const char *addr)
 {
        socklen_t               addrlen;
        int                     err;
        char                    *hostname;
        char                    hbuf[NI_MAXHOST];
+       unsigned char           buf[sizeof(struct in6_addr)];
+       int                     servername = 0;
+
+       if (avoid_dns) {
+               /*
+                * Determine if this is a server name, or an IP address.
+                * If it is an IP address, do the DNS lookup otherwise
+                * skip the DNS lookup.
+                */
+               servername = 0;
+               if (strchr(name, '.') && inet_pton(AF_INET, name, buf) == 1)
+                       servername = 1; /* IPv4 */
+               else if (strchr(name, ':') && inet_pton(AF_INET6, name, buf) == 1)
+                       servername = 1; /* or IPv6 */
+
+               if (servername) {
+                       return strdup(name);
+               }
+       }
 
        switch (sa->sa_family) {
        case AF_INET:
@@ -208,7 +231,7 @@ read_service_info(char *info_file_name, char **servicename, char **servername,
                  struct sockaddr *addr) {
 #define INFOBUFLEN 256
        char            buf[INFOBUFLEN + 1];
-       static char     dummy[128];
+       static char     server[128];
        int             nbytes;
        static char     service[128];
        static char     address[128];
@@ -236,7 +259,7 @@ read_service_info(char *info_file_name, char **servicename, char **servername,
                   "service: %127s %15s version %15s\n"
                   "address: %127s\n"
                   "protocol: %15s\n",
-                  dummy,
+                  server,
                   service, program, version,
                   address,
                   protoname);
@@ -258,7 +281,7 @@ read_service_info(char *info_file_name, char **servicename, char **servername,
        if (!addrstr_to_sockaddr(addr, address, port))
                goto fail;
 
-       *servername = sockaddr_to_hostname(addr, address);
+       *servername = get_servername(server, addr, address);
        if (*servername == NULL)
                goto fail;