Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 1 Apr 2004 11:31:00 -0500 (EST)
From:      Alex Vasylenko <lxv@omut.org>
To:        FreeBSD-gnats-submit@FreeBSD.org
Cc:        rsync@lists.samba.org
Subject:   ports/65043: [patch] net/rsync: problems in client name lookup code
Message-ID:  <200404011631.i31GV0ZK026299@mix.omut.org>
Resent-Message-ID: <200404011640.i31Ge9T0059182@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         65043
>Category:       ports
>Synopsis:       [patch] net/rsync: problems in client name lookup code
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Apr 01 08:40:09 PST 2004
>Closed-Date:
>Last-Modified:
>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:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200404011631.i31GV0ZK026299>