diff options
author | cjc <cjc@FreeBSD.org> | 2003-01-21 05:13:02 +0000 |
---|---|---|
committer | cjc <cjc@FreeBSD.org> | 2003-01-21 05:13:02 +0000 |
commit | 29a813efb6672f6dfe60ef33e869adbd662cf866 (patch) | |
tree | b18f9ebde4f2e8b1174dc86dae83fb4552b3e4ac /libexec/ftpd | |
parent | 9d5889a3d98b3a2e7b8c3f82bf7630c443e23054 (diff) | |
download | FreeBSD-src-29a813efb6672f6dfe60ef33e869adbd662cf866.zip FreeBSD-src-29a813efb6672f6dfe60ef33e869adbd662cf866.tar.gz |
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
Diffstat (limited to 'libexec/ftpd')
-rw-r--r-- | libexec/ftpd/ftpd.c | 45 |
1 files changed, 26 insertions, 19 deletions
diff --git a/libexec/ftpd/ftpd.c b/libexec/ftpd/ftpd.c index 1f5ce00..d59edd6 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) { + 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); + } + 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; - continue; + } else { + break; } + } while (retry <= swaitmax); + if (conerrno != 0) { perror_reply(425, "Can't build data connection"); - (void) fclose(file); - data = -1; return (NULL); } reply(150, "Opening %s mode data connection for '%s'%s.", |