From e5094456895656170800a0b4c8745314134694cd Mon Sep 17 00:00:00 2001 From: "Crist J. Clark" 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 1f5ce004baf..d59edd61ead 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 @@ pdata_err: 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.",