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>