From 29a813efb6672f6dfe60ef33e869adbd662cf866 Mon Sep 17 00:00:00 2001 From: cjc Date: Tue, 21 Jan 2003 05:13:02 +0000 Subject: [PATCH] The FTP daemon was vulnerable to a DoS where an attacker could bind() up port 20 for an extended period of time and thus lock out all other users from establishing PORT data connections. Don't hold on to the bind() while we loop around waiting to see if we can make our connection. Being a DoS, it has security implications, giving it a short MFC time. MFC after: 1 day --- libexec/ftpd/ftpd.c | 47 ++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/libexec/ftpd/ftpd.c b/libexec/ftpd/ftpd.c index 1f5ce004baf9..d59edd61eade 100644 --- a/libexec/ftpd/ftpd.c +++ b/libexec/ftpd/ftpd.c @@ -1772,7 +1772,7 @@ dataconn(char *name, off_t size, char *mode) { char sizebuf[32]; FILE *file; - int retry = 0, tos; + int retry = 0, tos, conerrno; file_size = size; byte_count = 0; @@ -1840,28 +1840,35 @@ dataconn(char *name, off_t size, char *mode) if (usedefault) data_dest = his_addr; usedefault = 1; - file = getdatasock(mode); - if (file == NULL) { - char hostbuf[BUFSIZ], portbuf[BUFSIZ]; - getnameinfo((struct sockaddr *)&data_source, - data_source.su_len, hostbuf, sizeof(hostbuf) - 1, - portbuf, sizeof(portbuf), - NI_NUMERICHOST|NI_NUMERICSERV); - reply(425, "Can't create data socket (%s,%s): %s.", - hostbuf, portbuf, strerror(errno)); - return (NULL); - } - data = fileno(file); - while (connect(data, (struct sockaddr *)&data_dest, - data_dest.su_len) < 0) { - if (errno == EADDRINUSE && retry < swaitmax) { - sleep((unsigned) swaitint); - retry += swaitint; - continue; + do { + file = getdatasock(mode); + if (file == NULL) { + char hostbuf[BUFSIZ], portbuf[BUFSIZ]; + getnameinfo((struct sockaddr *)&data_source, + data_source.su_len, hostbuf, sizeof(hostbuf) - 1, + portbuf, sizeof(portbuf), + NI_NUMERICHOST|NI_NUMERICSERV); + reply(425, "Can't create data socket (%s,%s): %s.", + hostbuf, portbuf, strerror(errno)); + return (NULL); } - perror_reply(425, "Can't build data connection"); + data = fileno(file); + conerrno = 0; + if (connect(data, (struct sockaddr *)&data_dest, + data_dest.su_len) == 0) + break; + conerrno = errno; (void) fclose(file); data = -1; + if (conerrno == EADDRINUSE) { + sleep((unsigned) swaitint); + retry += swaitint; + } else { + break; + } + } while (retry <= swaitmax); + if (conerrno != 0) { + perror_reply(425, "Can't build data connection"); return (NULL); } reply(150, "Opening %s mode data connection for '%s'%s.",