From lxv@mix.omut.org  Thu Apr  1 08:31:02 2004
Return-Path: <lxv@mix.omut.org>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 3F04116A4CE
	for <FreeBSD-gnats-submit@freebsd.org>; Thu,  1 Apr 2004 08:31:02 -0800 (PST)
Received: from mix.omut.org (ool-43548ab5.dyn.optonline.net [67.84.138.181])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 8F53443D1F
	for <FreeBSD-gnats-submit@freebsd.org>; Thu,  1 Apr 2004 08:31:01 -0800 (PST)
	(envelope-from lxv@mix.omut.org)
Received: from mix.omut.org (IDENT:26/rbZqbAZKT/smxmj4uXX5WtLN11kcP@localhost [127.0.0.1])
	by mix.omut.org (8.12.11/8.12.11) with ESMTP id i31GV05B026300;
	Thu, 1 Apr 2004 11:31:00 -0500 (EST)
	(envelope-from lxv@mix.omut.org)
Received: (from lxv@localhost)
	by mix.omut.org (8.12.11/8.12.11/Submit) id i31GV0ZK026299;
	Thu, 1 Apr 2004 11:31:00 -0500 (EST)
	(envelope-from lxv)
Message-Id: <200404011631.i31GV0ZK026299@mix.omut.org>
Date: Thu, 1 Apr 2004 11:31:00 -0500 (EST)
From: Alex Vasylenko <lxv@omut.org>
Reply-To: Alex Vasylenko <lxv@omut.org>
To: FreeBSD-gnats-submit@freebsd.org
Cc: rsync@lists.samba.org
Subject: [patch] net/rsync: problems in client name lookup code
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         65043
>Category:       ports
>Synopsis:       [patch] net/rsync: problems in client name lookup code
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    eik
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Apr 01 08:40:09 PST 2004
>Closed-Date:    Wed Apr 28 05:13:34 PDT 2004
>Last-Modified:  Wed Apr 28 05:13:34 PDT 2004
>Originator:     Alex Vasylenko
>Release:        FreeBSD 4.8-RELEASE-p16 i386
>Organization:
>Environment:
System: FreeBSD 4.8-RELEASE-p16


	
>Description:
	rsync does reverse name lookups on a client address in lookup_name
	(called from client_name) in clientname.c The code in client_name does
	two things incorrectly:
	- fails to set ss_len member of struct sockaddr_storage, which when
	  passed to getnameinfo causes the latter to fail;
	- detection of IPv6 via counting dots is plain silly and doesn't work;

	The attached patch attempts to address these two issues.

>How-To-Repeat:
	The code in question gets exercised when "hosts allow" specifies a
	hostname

>Fix:

--- proto.h.orig	Sat Dec  6 16:07:27 2003
+++ proto.h	Thu Apr  1 10:54:19 2004
@@ -42,7 +42,6 @@
 		     struct sockaddr_storage *ss,
 		     socklen_t *ss_len);
 int lookup_name(int fd, const struct sockaddr_storage *ss,
-		socklen_t ss_len,
 		char *name_buf, size_t name_buf_len,
 		char *port_buf, size_t port_buf_len);
 int compare_addrinfo_sockaddr(const struct addrinfo *ai,
--- clientname.c.orig	Fri Jan 10 21:05:56 2003
+++ clientname.c	Thu Apr  1 10:57:05 2004
@@ -101,58 +101,58 @@ char *client_name(int fd)
 	static char name_buf[100];
 	static char port_buf[100];
 	static int initialised;
-	struct sockaddr_storage ss, *ssp;
-	struct sockaddr_in sin;
-#ifdef INET6
-	struct sockaddr_in6 sin6;
-#endif
-	socklen_t ss_len;
+	struct sockaddr_storage ss;
 
-	if (initialised) return name_buf;
+	if (initialised)
+		return name_buf;
 
 	strcpy(name_buf, default_name);
 	initialised = 1;
 
+	memset(&ss, 0, sizeof(ss));
+
 	if (am_server) {
 		/* daemon over --rsh mode */
 
 		char *addr = client_addr(fd);
-#ifdef INET6
-		int dots = 0;
-		char *p;
 
-		for (p = addr; *p && (dots <= 3); p++) {
-		    if (*p == '.')
-			dots++;
-		}
-		if (dots > 3) {
-			/* more than 4 parts to IP address, must be ipv6 */
-			ssp = (struct sockaddr_storage *) &sin6;
-			ss_len = sizeof sin6;
-			memset(ssp, 0, ss_len);
-			inet_pton(AF_INET6, addr, &sin6.sin6_addr);
-			sin6.sin6_family = AF_INET6;
-		} else
-#endif
-		{
-			ssp = (struct sockaddr_storage *) &sin;
-			ss_len = sizeof sin;
-			memset(ssp, 0, ss_len);
-			inet_pton(AF_INET, addr, &sin.sin_addr);
-			sin.sin_family = AF_INET;
+		struct addrinfo hint;
+		struct addrinfo *answer;
+		int err;
+
+		memset(&hint, 0, sizeof(hint));
+
+		hint.ai_flags = AI_NUMERICHOST;
+		hint.ai_socktype = SOCK_STREAM;
+
+		err = getaddrinfo(addr, NULL, &hint, &answer);
+		if (err) {
+			rprintf(FERROR, RSYNC_NAME ": malformed address %s: %s\n",
+			        addr, gai_strerror(err));
+			return name_buf;
 		}
 
+		switch (answer->ai_family) {
+		case AF_INET:
+			memcpy(&ss, answer->ai_addr, sizeof(struct sockaddr_in));
+			break;
+#ifdef INET6
+		case AF_INET6:
+			memcpy(&ss, answer->ai_addr, sizeof(struct sockaddr_in6));
+			break;
+		}
+#endif
+		freeaddrinfo(answer);
 	} else {
-		ss_len = sizeof ss;
-		ssp = &ss;
+		socklen_t ss_len = sizeof ss;
 
 		client_sockaddr(fd, &ss, &ss_len);
-
+		ss.ss_len = ss_len;
 	}
 
-	if (!lookup_name(fd, ssp, ss_len, name_buf, sizeof name_buf, 
+	if (!lookup_name(fd, &ss, name_buf, sizeof name_buf, 
 			port_buf, sizeof port_buf))
-		check_name(fd, ssp, name_buf);
+		check_name(fd, &ss, name_buf);
 
 	return name_buf;
 }
@@ -216,14 +216,13 @@ void client_sockaddr(int fd,
  * @param fd file descriptor for client socket.
  **/
 int lookup_name(int fd, const struct sockaddr_storage *ss,
-		socklen_t ss_len,
 		char *name_buf, size_t name_buf_len,
 		char *port_buf, size_t port_buf_len)
 {
 	int name_err;
 	
 	/* reverse lookup */
-	name_err = getnameinfo((struct sockaddr *) ss, ss_len,
+	name_err = getnameinfo((struct sockaddr *) ss, ss->ss_len,
 			       name_buf, name_buf_len,
 			       port_buf, port_buf_len,
 			       NI_NAMEREQD | NI_NUMERICSERV);
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-ports-bugs->eik  
Responsible-Changed-By: krion 
Responsible-Changed-When: Thu Apr 1 10:11:56 PST 2004 
Responsible-Changed-Why:  
Over to maintainer. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=65043 

From: Alex Vasylenko <lxv@omut.org>
To: Wayne Davison <wayned@samba.org>
Cc: FreeBSD-gnats-submit@freebsd.org, rsync@lists.samba.org
Subject: Re: ports/65043: [patch] net/rsync: problems in client name lookup
 code
Date: Thu, 01 Apr 2004 18:38:04 -0500

 Wayne,
 
 I'm changing the subject and keeping your text in an attempt to get this 
 recorded in gnats.
 
 Wayne Davison wrote:
 > On Thu, Apr 01, 2004 at 11:31:00AM -0500, Alex Vasylenko wrote:
 > 
 >>	- detection of IPv6 via counting dots is plain silly and doesn't work;
 > 
 > 
 > Thanks, I've tweaked your patch for this a little and checked it in.
 > It's attached to this email.
 > 
 >>	- fails to set ss_len member of struct sockaddr_storage, which when
 >>	  passed to getnameinfo causes the latter to fail;
 > 
 > 
 > Not everyone has ss_len in sockaddr_storage, so this part of the patch
 > doesn't work.  It looked like the only place you set the value was after
 > calling client_sockaddr() (though you only affected one of the two
 > places it was called).  
 
 ss.ss_len is set correctly in the answer structure returned from 
 getnameinfo, so no need to set it explicitly there. Setting ss_len 
 inside "switch (answer->ai_family)" like you do is OK, as long as ss_len 
 must be passed as a parameter to lookup_name.
 
 > So, might it be better to set the value inside
 > the client_sockaddr() routine?
 > 
 > Attached is my guess at how this might be fixed.  This looks odd,
 > though, so I think this is probably not the right fix.  Can you (or
 > anyone with access to a system that uses ss_len) let me know if this
 > second patch is what we need, and if not, what the correct fix is.
 
 I think your second patch is superfluous, as getpeername returns a 
 correctly formatted sockaddr (with _len set, if it's there), so it 
 should be sufficient to simply drop the "ss.ss_len = ss_len;" line from 
 my original patch
 
 > 
 > ------------------------------------------------------------------------
 > 
 > --- clientname.c	1 Apr 2004 21:08:24 -0000	1.20
 > +++ clientname.c	1 Apr 2004 21:36:31 -0000
 > @@ -100,11 +100,7 @@ char *client_name(int fd)
 >  	static char name_buf[100];
 >  	static char port_buf[100];
 >  	static int initialised;
 > -	struct sockaddr_storage ss, *ssp;
 > -	struct sockaddr_in sin;
 > -#ifdef INET6
 > -	struct sockaddr_in6 sin6;
 > -#endif
 > +	struct sockaddr_storage ss;
 >  	socklen_t ss_len;
 >  
 >  	if (initialised)
 > @@ -113,43 +109,45 @@ char *client_name(int fd)
 >  	strcpy(name_buf, default_name);
 >  	initialised = 1;
 >  
 > +	memset(&ss, 0, sizeof ss);
 > +
 >  	if (am_server) {	/* daemon over --rsh mode */
 >  		char *addr = client_addr(fd);
 > -#ifdef INET6
 > -		int dots = 0;
 > -		char *p;
 > +		struct addrinfo hint, *answer;
 > +		int err;
 > +
 > +		memset(&hint, 0, sizeof hint);
 >  
 > -		for (p = addr; *p && (dots <= 3); p++) {
 > -			if (*p == '.')
 > -				dots++;
 > +		hint.ai_flags = AI_NUMERICHOST;
 > +		hint.ai_socktype = SOCK_STREAM;
 > +
 > +		if ((err = getaddrinfo(addr, NULL, &hint, &answer)) != 0) {
 > +			rprintf(FERROR, RSYNC_NAME ": malformed address %s: %s\n",
 > +			        addr, gai_strerror(err));
 > +			return name_buf;
 >  		}
 > -		if (dots > 3) {
 > -			/* more than 4 parts to IP address, must be ipv6 */
 > -			ssp = (struct sockaddr_storage *) &sin6;
 > -			ss_len = sizeof sin6;
 > -			memset(ssp, 0, ss_len);
 > -			inet_pton(AF_INET6, addr, &sin6.sin6_addr);
 > -			sin6.sin6_family = AF_INET6;
 > -		} else
 > +
 > +		switch (answer->ai_family) {
 > +		case AF_INET:
 > +			ss_len = sizeof (struct sockaddr_in);
 > +			memcpy(&ss, answer->ai_addr, ss_len);
 > +			break;
 > +#ifdef INET6
 > +		case AF_INET6:
 > +			ss_len = sizeof (struct sockaddr_in6);
 > +			memcpy(&ss, answer->ai_addr, ss_len);
 > +			break;
 >  #endif
 > -		{
 > -			ssp = (struct sockaddr_storage *) &sin;
 > -			ss_len = sizeof sin;
 > -			memset(ssp, 0, ss_len);
 > -			inet_pton(AF_INET, addr, &sin.sin_addr);
 > -			sin.sin_family = AF_INET;
 >  		}
 > -
 > +		freeaddrinfo(answer);
 >  	} else {
 >  		ss_len = sizeof ss;
 > -		ssp = &ss;
 > -
 >  		client_sockaddr(fd, &ss, &ss_len);
 >  	}
 >  
 > -	if (!lookup_name(fd, ssp, ss_len, name_buf, sizeof name_buf,
 > +	if (!lookup_name(fd, &ss, ss_len, name_buf, sizeof name_buf,
 >  			port_buf, sizeof port_buf))
 > -		check_name(fd, ssp, name_buf);
 > +		check_name(fd, &ss, name_buf);
 >  
 >  	return name_buf;
 >  }
 > 
 > 
 > ------------------------------------------------------------------------
 > 
 > --- clientname.c	1 Apr 2004 21:39:35 -0000	1.21
 > +++ clientname.c	1 Apr 2004 22:00:22 -0000
 > @@ -190,9 +190,6 @@ void client_sockaddr(int fd,
 >  		memset(sin, 0, sizeof *sin);
 >  		sin->sin_family = AF_INET;
 >  		*ss_len = sizeof (struct sockaddr_in);
 > -#if HAVE_SOCKADDR_IN_LEN
 > -		sin->sin_len = *ss_len;
 > -#endif
 >  		sin->sin_port = sin6.sin6_port;
 >  
 >  		/* There is a macro to extract the mapped part
 > @@ -201,6 +198,10 @@ void client_sockaddr(int fd,
 >  		memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12],
 >  		    sizeof sin->sin_addr);
 >  	}
 > +#endif /* INET6 */
 > +
 > +#if HAVE_SOCKADDR_IN_LEN
 > +	ss->ss_len = *ss_len;
 >  #endif
 >  }
 >  
 
 --
 Alex.
 

From: Oliver Eikemeier <eikemeier@fillmore-labs.com>
To: Alex Vasylenko <lxv@omut.org>
Cc: Wayne Davison <wayned@samba.org>,
	FreeBSD-gnats-submit@freebsd.org
Subject: Re: ports/65043: [patch] net/rsync: problems in client name lookup
 code
Date: Fri, 02 Apr 2004 01:54:12 +0200

 Alex Vasylenko wrote:
 
 >  Wayne,
 >  
 >  I'm changing the subject and keeping your text in an attempt to get this 
 >  recorded in gnats.
 
 I appreciate your patch, and I'm happy that this is worked on in the samba
 team, but why should this discussion be archived in FreeBSD GNATS?
 
 -Oliver

From: Ceri Davies <ceri@FreeBSD.org>
To: FreeBSD Gnats Submit <freebsd-gnats-submit@FreeBSD.org>
Cc:  
Subject: Re: ports/65043: [patch] net/rsync: problems in client name lookup code
Date: Fri, 2 Apr 2004 11:18:42 +0100

 Adding to audit trail, from misfiled PR ports/65051:
 
 Date: Thu, 1 Apr 2004 14:00:49 -0800
 From: Wayne Davison <wayned@samba.org>
 Message-Id: <20040401220049.GG14934@blorf.net>
 References: <200404011631.i31GV0ZK026299@mix.omut.org>
 
  --zhXaljGHf11kAtnf
  Content-Type: text/plain; charset=us-ascii
  Content-Disposition: inline
  
  On Thu, Apr 01, 2004 at 11:31:00AM -0500, Alex Vasylenko wrote:
  > 	- detection of IPv6 via counting dots is plain silly and doesn't work;
  
  Thanks, I've tweaked your patch for this a little and checked it in.
  It's attached to this email.
  
  > 	- fails to set ss_len member of struct sockaddr_storage, which when
  > 	  passed to getnameinfo causes the latter to fail;
  
  Not everyone has ss_len in sockaddr_storage, so this part of the patch
  doesn't work.  It looked like the only place you set the value was after
  calling client_sockaddr() (though you only affected one of the two
  places it was called).  So, might it be better to set the value inside
  the client_sockaddr() routine?
  
  Attached is my guess at how this might be fixed.  This looks odd,
  though, so I think this is probably not the right fix.  Can you (or
  anyone with access to a system that uses ss_len) let me know if this
  second patch is what we need, and if not, what the correct fix is.
  
  Thanks,
  
  ..wayne..
  
  --zhXaljGHf11kAtnf
  Content-Type: text/plain; charset=us-ascii
  Content-Disposition: attachment; filename="4vs6.patch"
  
  --- clientname.c	1 Apr 2004 21:08:24 -0000	1.20
  +++ clientname.c	1 Apr 2004 21:36:31 -0000
  @@ -100,11 +100,7 @@ char *client_name(int fd)
   	static char name_buf[100];
   	static char port_buf[100];
   	static int initialised;
  -	struct sockaddr_storage ss, *ssp;
  -	struct sockaddr_in sin;
  -#ifdef INET6
  -	struct sockaddr_in6 sin6;
  -#endif
  +	struct sockaddr_storage ss;
   	socklen_t ss_len;
   
   	if (initialised)
  @@ -113,43 +109,45 @@ char *client_name(int fd)
   	strcpy(name_buf, default_name);
   	initialised = 1;
   
  +	memset(&ss, 0, sizeof ss);
  +
   	if (am_server) {	/* daemon over --rsh mode */
   		char *addr = client_addr(fd);
  -#ifdef INET6
  -		int dots = 0;
  -		char *p;
  +		struct addrinfo hint, *answer;
  +		int err;
  +
  +		memset(&hint, 0, sizeof hint);
   
  -		for (p = addr; *p && (dots <= 3); p++) {
  -			if (*p == '.')
  -				dots++;
  +		hint.ai_flags = AI_NUMERICHOST;
  +		hint.ai_socktype = SOCK_STREAM;
  +
  +		if ((err = getaddrinfo(addr, NULL, &hint, &answer)) != 0) {
  +			rprintf(FERROR, RSYNC_NAME ": malformed address %s: %s\n",
  +			        addr, gai_strerror(err));
  +			return name_buf;
   		}
  -		if (dots > 3) {
  -			/* more than 4 parts to IP address, must be ipv6 */
  -			ssp = (struct sockaddr_storage *) &sin6;
  -			ss_len = sizeof sin6;
  -			memset(ssp, 0, ss_len);
  -			inet_pton(AF_INET6, addr, &sin6.sin6_addr);
  -			sin6.sin6_family = AF_INET6;
  -		} else
  +
  +		switch (answer->ai_family) {
  +		case AF_INET:
  +			ss_len = sizeof (struct sockaddr_in);
  +			memcpy(&ss, answer->ai_addr, ss_len);
  +			break;
  +#ifdef INET6
  +		case AF_INET6:
  +			ss_len = sizeof (struct sockaddr_in6);
  +			memcpy(&ss, answer->ai_addr, ss_len);
  +			break;
   #endif
  -		{
  -			ssp = (struct sockaddr_storage *) &sin;
  -			ss_len = sizeof sin;
  -			memset(ssp, 0, ss_len);
  -			inet_pton(AF_INET, addr, &sin.sin_addr);
  -			sin.sin_family = AF_INET;
   		}
  -
  +		freeaddrinfo(answer);
   	} else {
   		ss_len = sizeof ss;
  -		ssp = &ss;
  -
   		client_sockaddr(fd, &ss, &ss_len);
   	}
   
  -	if (!lookup_name(fd, ssp, ss_len, name_buf, sizeof name_buf,
  +	if (!lookup_name(fd, &ss, ss_len, name_buf, sizeof name_buf,
   			port_buf, sizeof port_buf))
  -		check_name(fd, ssp, name_buf);
  +		check_name(fd, &ss, name_buf);
   
   	return name_buf;
   }
  
  --zhXaljGHf11kAtnf
  Content-Type: text/plain; charset=us-ascii
  Content-Disposition: attachment; filename="socklen.patch"
  
  --- clientname.c	1 Apr 2004 21:39:35 -0000	1.21
  +++ clientname.c	1 Apr 2004 22:00:22 -0000
  @@ -190,9 +190,6 @@ void client_sockaddr(int fd,
   		memset(sin, 0, sizeof *sin);
   		sin->sin_family = AF_INET;
   		*ss_len = sizeof (struct sockaddr_in);
  -#if HAVE_SOCKADDR_IN_LEN
  -		sin->sin_len = *ss_len;
  -#endif
   		sin->sin_port = sin6.sin6_port;
   
   		/* There is a macro to extract the mapped part
  @@ -201,6 +198,10 @@ void client_sockaddr(int fd,
   		memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12],
   		    sizeof sin->sin_addr);
   	}
  +#endif /* INET6 */
  +
  +#if HAVE_SOCKADDR_IN_LEN
  +	ss->ss_len = *ss_len;
   #endif
   }
   
  
  --zhXaljGHf11kAtnf--
 
State-Changed-From-To: open->suspended 
State-Changed-By: eik 
State-Changed-When: Mon Apr 12 11:49:49 CEST 2004 
State-Changed-Why:  
Wayne Davison is working on this. I'll prefer to wait 
until rsync 2.6.1 is released to avoid introducing  
conflicting patches. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=65043 
State-Changed-From-To: suspended->closed 
State-Changed-By: eik 
State-Changed-When: Wed Apr 28 14:13:13 CEST 2004 
State-Changed-Why:  
Fixed in 2.6.1 

http://www.freebsd.org/cgi/query-pr.cgi?pr=65043 
>Unformatted:
