[patch] net/rsync: problems in client name lookup code
Alex Vasylenko
lxv at omut.org
Thu Apr 1 16:31:00 GMT 2004
>Submitter-Id: current-users
>Originator: Alex Vasylenko
>Organization:
>Confidential: no
>Synopsis: [patch] net/rsync: problems in client name lookup code
>Severity: non-critical
>Priority: low
>Category: ports
>Class: sw-bug
>Release: FreeBSD 4.8-RELEASE-p16 i386
>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);
More information about the rsync
mailing list