Re: [PATCH] Avoid DNS reverse resolution for server names (take 3)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Steve,
 what is the status of this issue in your mind?
 upstream nfs-utils is still vulnerable to CVE-2013-1923, so probably a few
 distros think that have addressed it by upgrading, but haven't.

 Can we get a 1.2.9 that really fixes this issue?

Thanks,
NeilBrown


On Thu, 2 May 2013 13:13:32 +1000 NeilBrown <neilb@xxxxxxx> wrote:

> 
> Coming to the party a bit late....
> 
> On Fri, 19 Apr 2013 10:16:38 -0400 Steve Dickson <steved@xxxxxxxxxx> wrote:
> 
> > From: Simo Sorce <simo@xxxxxxxxxx>
> > 
> > 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
> 
> OK, this is confusing,  When you do a "DNS lookup .. on server names",
> that is a Forward lookup, not a Reverse lookup.
> 
> > 
> > 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.
> 
> Which current environments?  Mine?  Maybe the man page update will tell me.
> I'll look.
> 
> 
> > 
> > Signed-off-by: Simo Sorce <simo@xxxxxxxxxx>
> > Signed-off-by: Steve Dickson <steved@xxxxxxxxxx>
> > ---
> >  utils/gssd/gss_util.h  |  2 ++
> >  utils/gssd/gssd.c      |  7 +++++--
> >  utils/gssd/gssd.man    |  8 +++++++-
> >  utils/gssd/gssd_proc.c | 31 +++++++++++++++++++++++++++----
> >  4 files changed, 41 insertions(+), 7 deletions(-)
> > 
> > diff --git a/utils/gssd/gss_util.h b/utils/gssd/gss_util.h
> > index aa9f778..c81fc5a 100644
> > --- a/utils/gssd/gss_util.h
> > +++ b/utils/gssd/gss_util.h
> > @@ -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_ */
> > diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c
> > index 07b1e52..8ee478b 100644
> > --- a/utils/gssd/gssd.c
> > +++ b/utils/gssd/gssd.c
> > @@ -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;
> > diff --git a/utils/gssd/gssd.man b/utils/gssd/gssd.man
> > index 79d9bf9..1df75c5 100644
> > --- a/utils/gssd/gssd.man
> > +++ b/utils/gssd/gssd.man
> > @@ -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
> 
> Nope.  "This option will reverses that" doesn't give me a lot of confidence
> either.
> May I try?
> 
> 
>  The server name passed to GSSAPI (whatever that is) for authorisation (or is
>  it authentication) is normally the name exactly as requested.  e.g. for NFS
>  it is the server name in the "servername:/path" mount request.  Only if this
>  servername appears to be an IP address (IPv4 or IPv6) will a reverse DNS lookup
>  will be performed to get the canoncial server name.
>  If this -D option is present, a reverse DNS lookup will *always* be used,
>  even if the server name looks like a canonical name.  So it is needed if partially
>  qualified, or non canonical names are regularly used.
>  Using -D can introduce a security vulnerability, so it is recommended that
>  -D not be used, and that canonical names always be used when requesting
>  services.
> 
> Ahh.. now I know if I might need -D... Assuming the code is correct..
> 
> 
> >  .B -f
> >  Runs
> >  .B rpc.gssd
> > diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
> > index d6f07e6..e4ab253 100644
> > --- a/utils/gssd/gssd_proc.c
> > +++ b/utils/gssd/gssd_proc.c
> > @@ -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);
> > +		}
> > +	}
> 
> Uh oh.  Look at that code.  Now look at me.  Now back at the code.
> Now look at this code that was prepared earlier (in Take 2).
> 
> +	if (avoid_dns) {
> +		/*
> +		 * Determine if this is a server name, or an IP address.
> +		 * If it is an IP address, do the DNS lookup
> +		 */
> +		if (strchr(name, '.') && inet_pton(AF_INET, name, buf) == 1)
> +			do_dns_lookup = 1; /* IPv4 */
> +		else if (strchr(name, ':') && inet_pton(AF_INET6, name, buf) == 1)
> +			do_dns_lookup = 1; /* or IPv6 */
> +
> +		if (!do_dns_lookup) {
> +			return strdup(name);
> +		}
> +	}
> 
> So we changed "do_dns_lookup" to "servername", set it to zero one more time
> (just to be sure), and the final condition has been REVERSED.
> So if I use an IP address, that is the string passed back to GSSAPI.
> If I used a fully qualified name (like the man page suggests), then it goes to
> do a reverse DNS lookup for me :-(
> 
> And was there a reason for dropping the test on "non-qualified host name"
> that was in the original?  That seemed like a good idea to me.
> 
> Is inet_pton so expensive that we need to do the 'strchr' first to avoid the
> extra work?
> 
> Are we going to get a 1-2-9 once this has been fixed properly ?
> 
> Possible patch below.  Note that I also needed
> 
> diff --git a/utils/statd/simu.c b/utils/statd/simu.c
> index f1d0bf8..b57e504 100644
> --- a/utils/statd/simu.c
> +++ b/utils/statd/simu.c
> @@ -7,6 +7,7 @@
>  #ifdef HAVE_CONFIG_H
>  #include <config.h>
>  #endif
> +#include <stdlib.h>
>  
>  #include <netdb.h>
>  #include <arpa/inet.h>
> 
> 
> to get a clean compile.
> 
> Or mostly clean. On openSUSE I also get:
> 
> gssd-context_lucid.o: In function `serialize_krb5_ctx':
> /home/git/nfs-utils/utils/gssd/context_lucid.c:269: undefined reference to `gss_krb5_export_lucid_sec_context'
> /home/git/nfs-utils/utils/gssd/context_lucid.c:305: undefined reference to `gss_krb5_free_lucid_sec_context'
> gssd-krb5_util.o: In function `limit_krb5_enctypes':
> /home/git/nfs-utils/utils/gssd/krb5_util.c:1441: undefined reference to `gss_krb5_set_allowable_enctypes'
> /home/git/nfs-utils/utils/gssd/krb5_util.c:1444: undefined reference to `gss_krb5_set_allowable_enctypes'
> collect2: error: ld returned 1 exit status
> 
> 
> any idea what is causing that"?
> 
> 
> Subject: Fix recent fix to Avoid DNS reverse resolution in gssd.
> 
> The final version for this fix that was committed inverted the test
> so makes no change in the important cases.
> The documentation didn't really help a naive user know when the new -D flag
> should be used.
> And the code (once fixed) avoided DNS resolution on non-qualified names too,
> which probably isn't a good idea.
> 
> This patch fixes all three issues.
> 
> Signed-off-by: NeilBrown <neilb@xxxxxxx>
> 
> 
> diff --git a/utils/gssd/gssd.man b/utils/gssd/gssd.man
> index 1df75c5..ac13fd4 100644
> --- a/utils/gssd/gssd.man
> +++ b/utils/gssd/gssd.man
> @@ -195,11 +195,28 @@ 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.
> +.B \-D
> +The server name passed to GSSAPI for authentication is normally the
> +name exactly as requested.  e.g. for NFS
> +it is the server name in the "servername:/path" mount request.  Only if this
> +servername appears to be an IP address (IPv4 or IPv6) or an
> +unqualified name (no dots) will a reverse DNS lookup
> +will be performed to get the canoncial server name.
> +
> +If
> +.B \-D
> +is present, a reverse DNS lookup will
> +.I always
> +be used, even if the server name looks like a canonical name.  So it
> +is needed if partially qualified, or non canonical names are regularly
> +used.
> +
> +Using
> +.B \-D
> +can introduce a security vulnerability, so it is recommended that
> +.B \-D
> +not be used, and that canonical names always be used when requesting
> +services.
>  .TP
>  .B -f
>  Runs
> diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
> index af1844c..d381664 100644
> --- a/utils/gssd/gssd_proc.c
> +++ b/utils/gssd/gssd_proc.c
> @@ -176,7 +176,6 @@ get_servername(const char *name, const struct sockaddr *sa, const char *addr)
>  	char			*hostname;
>  	char			hbuf[NI_MAXHOST];
>  	unsigned char		buf[sizeof(struct in6_addr)];
> -	int			servername = 0;
>  
>  	if (avoid_dns) {
>  		/*
> @@ -184,15 +183,18 @@ get_servername(const char *name, const struct sockaddr *sa, const char *addr)
>  		 * 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) {
> +		int is_fqdn = 1;
> +		if (strchr(name, '.') == NULL)
> +			is_fqdn = 0; /* local name */
> +		else if (inet_pton(AF_INET, name, buf) == 1)
> +			is_fqdn = 0; /* IPv4 address */
> +		else if (inet_pton(AF_INET6, name, buf) == 1)
> +			is_fqdn = 0; /* IPv6 addrss */
> +
> +		if (is_fqdn) {
>  			return strdup(name);
>  		}
> +		/* Sorry, cannot avoid dns after all */
>  	}
>  
>  	switch (sa->sa_family) {

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux