summaryrefslogtreecommitdiffstats
path: root/usr.sbin/faithd/ftp.c
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2003-11-14 17:34:08 +0000
committerume <ume@FreeBSD.org>2003-11-14 17:34:08 +0000
commit1cc5ee037b36b56016d408fee3bd873ba27cfa3d (patch)
treefb19cd0cd36a6f4dd9086dce6e3848ffb6d89f51 /usr.sbin/faithd/ftp.c
parentb0479caf614810b424cbb8e80b47db2da6b2ca71 (diff)
downloadFreeBSD-src-1cc5ee037b36b56016d408fee3bd873ba27cfa3d.zip
FreeBSD-src-1cc5ee037b36b56016d408fee3bd873ba27cfa3d.tar.gz
- poll(2) support.
- simplify by strdup. - set ai_protocol in hints to TCP. - g/c FAITH_NS (no description, not maintained for years) - warn if connection from IPv4 mapped is reached. - IPV6_V6ONLY if possible. - unifdef -UFAITH4. - drop rsh/rlogin support. - deal with negative return value from wait3. Obtained from: KAME
Diffstat (limited to 'usr.sbin/faithd/ftp.c')
-rw-r--r--usr.sbin/faithd/ftp.c592
1 files changed, 275 insertions, 317 deletions
diff --git a/usr.sbin/faithd/ftp.c b/usr.sbin/faithd/ftp.c
index 5664681..6ceb24d 100644
--- a/usr.sbin/faithd/ftp.c
+++ b/usr.sbin/faithd/ftp.c
@@ -1,4 +1,4 @@
-/* $KAME: ftp.c,v 1.11 2001/07/02 14:36:49 itojun Exp $ */
+/* $KAME: ftp.c,v 1.23 2003/08/19 21:20:33 itojun Exp $ */
/*
* Copyright (C) 1997 and 1998 WIDE Project.
@@ -42,6 +42,9 @@
#include <string.h>
#include <syslog.h>
#include <unistd.h>
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
#include <errno.h>
#include <ctype.h>
@@ -62,11 +65,7 @@ static struct sockaddr_storage data4; /* server data address */
static struct sockaddr_storage data6; /* client data address */
static int epsvall = 0;
-#ifdef FAITH4
-enum state { NONE, LPRT, EPRT, PORT, LPSV, EPSV, PASV };
-#else
enum state { NONE, LPRT, EPRT, LPSV, EPSV };
-#endif
static int ftp_activeconn __P((void));
static int ftp_passiveconn __P((void));
@@ -77,7 +76,11 @@ static int ftp_copycommand __P((int, int, enum state *));
void
ftp_relay(int ctl6, int ctl4)
{
+#ifdef HAVE_POLL_H
+ struct pollfd pfd[6];
+#else
fd_set readfds;
+#endif
int error;
enum state state = NONE;
struct timeval tv;
@@ -85,25 +88,90 @@ ftp_relay(int ctl6, int ctl4)
syslog(LOG_INFO, "starting ftp control connection");
for (;;) {
+#ifdef HAVE_POLL_H
+ pfd[0].fd = ctl4;
+ pfd[0].events = POLLIN;
+ pfd[1].fd = ctl6;
+ pfd[1].events = POLLIN;
+ if (0 <= port4) {
+ pfd[2].fd = port4;
+ pfd[2].events = POLLIN;
+ } else
+ pfd[2].fd = -1;
+ if (0 <= port6) {
+ pfd[3].fd = port6;
+ pfd[3].events = POLLIN;
+ } else
+ pfd[3].fd = -1;
+#if 0
+ if (0 <= wport4) {
+ pfd[4].fd = wport4;
+ pfd[4].events = POLLIN;
+ } else
+ pfd[4].fd = -1;
+ if (0 <= wport6) {
+ pfd[5].fd = wport4;
+ pfd[5].events = POLLIN;
+ } else
+ pfd[5].fd = -1;
+#else
+ pfd[4].fd = pfd[5].fd = -1;
+ pfd[4].events = pfd[5].events = 0;
+#endif
+#else
+ int maxfd = 0;
+
FD_ZERO(&readfds);
+ if (ctl4 >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_SET(ctl4, &readfds);
+ maxfd = ctl4;
+ if (ctl6 >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_SET(ctl6, &readfds);
- if (0 <= port4)
+ maxfd = (ctl6 > maxfd) ? ctl6 : maxfd;
+ if (0 <= port4) {
+ if (port4 >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_SET(port4, &readfds);
- if (0 <= port6)
+ maxfd = (port4 > maxfd) ? port4 : maxfd;
+ }
+ if (0 <= port6) {
+ if (port6 >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_SET(port6, &readfds);
+ maxfd = (port6 > maxfd) ? port6 : maxfd;
+ }
#if 0
- if (0 <= wport4)
+ if (0 <= wport4) {
+ if (wport4 >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_SET(wport4, &readfds);
- if (0 <= wport6)
+ maxfd = (wport4 > maxfd) ? wport4 : maxfd;
+ }
+ if (0 <= wport6) {
+ if (wport6 >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_SET(wport6, &readfds);
+ maxfd = (wport6 > maxfd) ? wport6 : maxfd;
+ }
+#endif
#endif
tv.tv_sec = FAITH_TIMEOUT;
tv.tv_usec = 0;
- error = select(256, &readfds, NULL, NULL, &tv);
- if (error == -1)
+#ifdef HAVE_POLL_H
+ error = poll(pfd, sizeof(pfd)/sizeof(pfd[0]), tv.tv_sec * 1000);
+#else
+ error = select(maxfd + 1, &readfds, NULL, NULL, &tv);
+#endif
+ if (error == -1) {
+#ifdef HAVE_POLL_H
+ exit_failure("poll: %s", strerror(errno));
+#else
exit_failure("select: %s", strerror(errno));
+#endif
+ }
else if (error == 0)
exit_failure("connection timeout");
@@ -113,7 +181,12 @@ ftp_relay(int ctl6, int ctl4)
* otherwise some of the pipe may become full and we cannot
* relay correctly.
*/
- if (FD_ISSET(ctl6, &readfds)) {
+#ifdef HAVE_POLL_H
+ if (pfd[1].revents & POLLIN)
+#else
+ if (FD_ISSET(ctl6, &readfds))
+#endif
+ {
/*
* copy control connection from the client.
* command translation is necessary.
@@ -126,9 +199,15 @@ ftp_relay(int ctl6, int ctl4)
close(ctl4);
close(ctl6);
exit_success("terminating ftp control connection");
+ /*NOTREACHED*/
}
}
- if (FD_ISSET(ctl4, &readfds)) {
+#ifdef HAVE_POLL_H
+ if (pfd[0].revents & POLLIN)
+#else
+ if (FD_ISSET(ctl4, &readfds))
+#endif
+ {
/*
* copy control connection from the server
* translation of result code is necessary.
@@ -141,14 +220,24 @@ ftp_relay(int ctl6, int ctl4)
close(ctl4);
close(ctl6);
exit_success("terminating ftp control connection");
+ /*NOTREACHED*/
}
}
- if (0 <= port4 && 0 <= port6 && FD_ISSET(port4, &readfds)) {
+#ifdef HAVE_POLL_H
+ if (0 <= port4 && 0 <= port6 && (pfd[2].revents & POLLIN))
+#else
+ if (0 <= port4 && 0 <= port6 && FD_ISSET(port4, &readfds))
+#endif
+ {
/*
* copy data connection.
* no special treatment necessary.
*/
+#ifdef HAVE_POLL_H
+ if (pfd[2].revents & POLLIN)
+#else
if (FD_ISSET(port4, &readfds))
+#endif
error = ftp_copy(port4, port6);
switch (error) {
case -1:
@@ -163,12 +252,21 @@ ftp_relay(int ctl6, int ctl4)
break;
}
}
- if (0 <= port4 && 0 <= port6 && FD_ISSET(port6, &readfds)) {
+#ifdef HAVE_POLL_H
+ if (0 <= port4 && 0 <= port6 && (pfd[3].revents & POLLIN))
+#else
+ if (0 <= port4 && 0 <= port6 && FD_ISSET(port6, &readfds))
+#endif
+ {
/*
* copy data connection.
* no special treatment necessary.
*/
+#ifdef HAVE_POLL_H
+ if (pfd[3].revents & POLLIN)
+#else
if (FD_ISSET(port6, &readfds))
+#endif
error = ftp_copy(port6, port4);
switch (error) {
case -1:
@@ -184,13 +282,23 @@ ftp_relay(int ctl6, int ctl4)
}
}
#if 0
- if (wport4 && FD_ISSET(wport4, &readfds)) {
+#ifdef HAVE_POLL_H
+ if (wport4 && (pfd[4].revents & POLLIN))
+#else
+ if (wport4 && FD_ISSET(wport4, &readfds))
+#endif
+ {
/*
* establish active data connection from the server.
*/
ftp_activeconn();
}
- if (wport6 && FD_ISSET(wport6, &readfds)) {
+#ifdef HAVE_POLL_H
+ if (wport4 && (pfd[5].revents & POLLIN))
+#else
+ if (wport6 && FD_ISSET(wport6, &readfds))
+#endif
+ {
/*
* establish passive data connection from the client.
*/
@@ -206,20 +314,37 @@ ftp_relay(int ctl6, int ctl4)
static int
ftp_activeconn()
{
- int n;
+ socklen_t n;
int error;
+#ifdef HAVE_POLL_H
+ struct pollfd pfd[1];
+#else
fd_set set;
+#endif
struct timeval timeout;
struct sockaddr *sa;
/* get active connection from server */
+#ifdef HAVE_POLL_H
+ pfd[0].fd = wport4;
+ pfd[0].events = POLLIN;
+#else
FD_ZERO(&set);
+ if (wport4 >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_SET(wport4, &set);
+#endif
timeout.tv_sec = 120;
- timeout.tv_usec = -1;
+ timeout.tv_usec = 0;
n = sizeof(data4);
- if (select(wport4 + 1, &set, NULL, NULL, &timeout) == 0
- || (port4 = accept(wport4, (struct sockaddr *)&data4, &n)) < 0) {
+#ifdef HAVE_POLL_H
+ if (poll(pfd, sizeof(pfd)/sizeof(pfd[0]), timeout.tv_sec * 1000) == 0 ||
+ (port4 = accept(wport4, (struct sockaddr *)&data4, &n)) < 0)
+#else
+ if (select(wport4 + 1, &set, NULL, NULL, &timeout) == 0 ||
+ (port4 = accept(wport4, (struct sockaddr *)&data4, &n)) < 0)
+#endif
+ {
close(wport4);
wport4 = -1;
syslog(LOG_INFO, "active mode data connection failed");
@@ -253,20 +378,37 @@ ftp_activeconn()
static int
ftp_passiveconn()
{
- int n;
+ socklen_t len;
int error;
+#ifdef HAVE_POLL_H
+ struct pollfd pfd[1];
+#else
fd_set set;
+#endif
struct timeval timeout;
struct sockaddr *sa;
/* get passive connection from client */
+#ifdef HAVE_POLL_H
+ pfd[0].fd = wport6;
+ pfd[0].events = POLLIN;
+#else
FD_ZERO(&set);
+ if (wport6 >= FD_SETSIZE)
+ exit_failure("descriptor too big");
FD_SET(wport6, &set);
+#endif
timeout.tv_sec = 120;
timeout.tv_usec = 0;
- n = sizeof(data6);
- if (select(wport6 + 1, &set, NULL, NULL, &timeout) == 0
- || (port6 = accept(wport6, (struct sockaddr *)&data6, &n)) < 0) {
+ len = sizeof(data6);
+#ifdef HAVE_POLL_H
+ if (poll(pfd, sizeof(pfd)/sizeof(pfd[0]), timeout.tv_sec * 1000) == 0 ||
+ (port6 = accept(wport6, (struct sockaddr *)&data6, &len)) < 0)
+#else
+ if (select(wport6 + 1, &set, NULL, NULL, &timeout) == 0 ||
+ (port6 = accept(wport6, (struct sockaddr *)&data6, &len)) < 0)
+#endif
+ {
close(wport6);
wport6 = -1;
syslog(LOG_INFO, "passive mode data connection failed");
@@ -300,8 +442,7 @@ ftp_passiveconn()
static int
ftp_copy(int src, int dst)
{
- int error, atmark;
- int n;
+ int error, atmark, n;
/* OOB data handling */
error = ioctl(src, SIOCATMARK, &atmark);
@@ -338,10 +479,12 @@ ftp_copy(int src, int dst)
static int
ftp_copyresult(int src, int dst, enum state state)
{
- int error, atmark;
- int n;
+ int error, atmark, n;
+ socklen_t len;
char *param;
int code;
+ char *a, *p;
+ int i;
/* OOB data handling */
error = ioctl(src, SIOCATMARK, &atmark);
@@ -367,10 +510,6 @@ ftp_copyresult(int src, int dst, enum state state)
/*
* parse argument
*/
- {
- char *p;
- int i;
-
p = rbuf;
for (i = 0; i < 3; i++) {
if (!isdigit(*p)) {
@@ -392,7 +531,6 @@ ftp_copyresult(int src, int dst, enum state state)
param++;
if (!*param)
param = NULL;
- }
switch (state) {
case NONE:
@@ -400,15 +538,17 @@ ftp_copyresult(int src, int dst, enum state state)
if (ftp_activeconn() < 0) {
n = snprintf(rbuf, sizeof(rbuf),
"425 Cannot open data connetion\r\n");
+ if (n < 0 || n >= sizeof(rbuf))
+ n = 0;
}
}
- return n > 0 ? write(dst, rbuf, n) : n;
+ if (n)
+ write(dst, rbuf, n);
+ return n;
case LPRT:
case EPRT:
/* expecting "200 PORT command successful." */
if (code == 200) {
- char *p;
-
p = strstr(rbuf, "PORT");
if (p) {
p[0] = (state == LPRT) ? 'L' : 'E';
@@ -420,24 +560,6 @@ ftp_copyresult(int src, int dst, enum state state)
}
write(dst, rbuf, n);
return n;
-#ifdef FAITH4
- case PORT:
- /* expecting "200 EPRT command successful." */
- if (code == 200) {
- char *p;
-
- p = strstr(rbuf, "EPRT");
- if (p) {
- p[0] = 'P';
- p[1] = 'O';
- }
- } else {
- close(wport4);
- wport4 = -1;
- }
- write(dst, rbuf, n);
- return n;
-#endif
case LPSV:
case EPSV:
/*
@@ -457,7 +579,6 @@ passivefail0:
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
u_short port;
- char *p;
/*
* PASV result -> LPSV/EPSV result
@@ -496,7 +617,11 @@ passivefail0:
passivefail:
n = snprintf(sbuf, sizeof(sbuf),
"500 could not translate from PASV\r\n");
- return n > 0 ? write(src, sbuf, n) : n;
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
+ return n;
}
#ifdef IPV6_FAITH
{
@@ -524,8 +649,8 @@ passivefail:
/*
* addr from dst, port from wport6
*/
- n = sizeof(data6);
- error = getsockname(wport6, (struct sockaddr *)&data6, &n);
+ len = sizeof(data6);
+ error = getsockname(wport6, (struct sockaddr *)&data6, &len);
if (error == -1) {
close(wport6);
wport6 = -1;
@@ -534,8 +659,8 @@ passivefail:
sin6 = (struct sockaddr_in6 *)&data6;
port = sin6->sin6_port;
- n = sizeof(data6);
- error = getsockname(dst, (struct sockaddr *)&data6, &n);
+ len = sizeof(data6);
+ error = getsockname(dst, (struct sockaddr *)&data6, &len);
if (error == -1) {
close(wport6);
wport6 = -1;
@@ -545,8 +670,6 @@ passivefail:
sin6->sin6_port = port;
if (state == LPSV) {
- char *a, *p;
-
a = (char *)&sin6->sin6_addr;
p = (char *)&sin6->sin6_port;
n = snprintf(sbuf, sizeof(sbuf),
@@ -556,132 +679,24 @@ passivefail:
UC(a[8]), UC(a[9]), UC(a[10]), UC(a[11]),
UC(a[12]), UC(a[13]), UC(a[14]), UC(a[15]),
2, UC(p[0]), UC(p[1]));
- if (n > 0)
- n = write(dst, sbuf, n);
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(dst, sbuf, n);
passivemode = 1;
return n;
} else {
n = snprintf(sbuf, sizeof(sbuf),
"229 Entering Extended Passive Mode (|||%d|)\r\n",
ntohs(sin6->sin6_port));
- if (n > 0)
- n = write(dst, sbuf, n);
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(dst, sbuf, n);
passivemode = 1;
return n;
}
}
-#ifdef FAITH4
- case PASV:
- /* expecting "229 Entering Extended Passive Mode (|||x|)" */
- if (code != 229) {
-passivefail1:
- close(wport6);
- wport6 = -1;
- write(dst, rbuf, n);
- return n;
- }
-
- {
- u_short port;
- char *p;
- struct sockaddr_in *sin;
- struct sockaddr_in6 *sin6;
-
- /*
- * EPSV result -> PORT result
- */
- p = param;
- while (*p && *p != '(') /*)*/
- p++;
- if (!*p)
- goto passivefail1; /*XXX*/
- p++;
- n = sscanf(p, "|||%hu|", &port);
- if (n != 1)
- goto passivefail1; /*XXX*/
-
- /* keep EPRT parameter */
- n = sizeof(data4);
- error = getpeername(src, (struct sockaddr *)&data4, &n);
- if (error == -1)
- goto passivefail1; /*XXX*/
- sin6 = (struct sockaddr_in6 *)&data4;
- sin6->sin6_port = htons(port);
-
- /* get ready for passive data connection */
- memset(&data6, 0, sizeof(data6));
- sin = (struct sockaddr_in *)&data6;
- sin->sin_len = sizeof(*sin);
- sin->sin_family = AF_INET;
- wport6 = socket(sin->sin_family, SOCK_STREAM, 0);
- if (wport6 == -1) {
-passivefail2:
- n = snprintf(sbuf, sizeof(sbuf),
- "500 could not translate from EPSV\r\n");
- return n > 0 ? write(src, sbuf, n) : n;
- }
-#ifdef IP_FAITH
- {
- int on = 1;
- error = setsockopt(wport6, IPPROTO_IP, IP_FAITH,
- &on, sizeof(on));
- if (error == -1)
- exit_error("setsockopt(IP_FAITH): %s", strerror(errno));
- }
-#endif
- error = bind(wport6, (struct sockaddr *)sin, sin->sin_len);
- if (error == -1) {
- close(wport6);
- wport6 = -1;
- goto passivefail2;
- }
- error = listen(wport6, 1);
- if (error == -1) {
- close(wport6);
- wport6 = -1;
- goto passivefail2;
- }
-
- /* transmit PORT */
- /*
- * addr from dst, port from wport6
- */
- n = sizeof(data6);
- error = getsockname(wport6, (struct sockaddr *)&data6, &n);
- if (error == -1) {
- close(wport6);
- wport6 = -1;
- goto passivefail2;
- }
- sin = (struct sockaddr_in *)&data6;
- port = sin->sin_port;
-
- n = sizeof(data6);
- error = getsockname(dst, (struct sockaddr *)&data6, &n);
- if (error == -1) {
- close(wport6);
- wport6 = -1;
- goto passivefail2;
- }
- sin = (struct sockaddr_in *)&data6;
- sin->sin_port = port;
-
- {
- char *a, *p;
-
- a = (char *)&sin->sin_addr;
- p = (char *)&sin->sin_port;
- n = snprintf(sbuf, sizeof(sbuf),
-"227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n",
- UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
- UC(p[0]), UC(p[1]));
- if (n > 0)
- n = write(dst, sbuf, n);
- passivemode = 1;
- return n;
- }
- }
-#endif /* FAITH4 */
}
bad:
@@ -693,15 +708,16 @@ passivefail2:
static int
ftp_copycommand(int src, int dst, enum state *state)
{
- int error, atmark;
- int n;
+ int error, atmark, n;
+ socklen_t len;
unsigned int af, hal, ho[16], pal, po[2];
- char *a, *p;
+ char *a, *p, *q;
char cmd[5], *param;
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
enum state nstate;
char ch;
+ int i;
/* OOB data handling */
error = ioctl(src, SIOCATMARK, &atmark);
@@ -732,10 +748,6 @@ ftp_copycommand(int src, int dst, enum state *state)
/*
* parse argument
*/
- {
- char *p, *q;
- int i;
-
p = rbuf;
q = cmd;
for (i = 0; i < 4; i++) {
@@ -759,7 +771,6 @@ ftp_copycommand(int src, int dst, enum state *state)
param++;
if (!*param)
param = NULL;
- }
*state = NONE;
@@ -778,7 +789,11 @@ ftp_copycommand(int src, int dst, enum state *state)
if (epsvall) {
n = snprintf(sbuf, sizeof(sbuf), "501 %s disallowed in EPSV ALL\r\n",
cmd);
- return n > 0 ? write(src, sbuf, n) : n;
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
+ return n;
}
n = sscanf(param,
@@ -791,7 +806,11 @@ ftp_copycommand(int src, int dst, enum state *state)
if (n != 21 || af != 6 || hal != 16|| pal != 2) {
n = snprintf(sbuf, sizeof(sbuf),
"501 illegal parameter to LPRT\r\n");
- return n > 0 ? write(src, sbuf, n) : n;
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
+ return n;
}
/* keep LPRT parameter */
@@ -805,13 +824,17 @@ ftp_copycommand(int src, int dst, enum state *state)
sendport:
/* get ready for active data connection */
- n = sizeof(data4);
- error = getsockname(dst, (struct sockaddr *)&data4, &n);
+ len = sizeof(data4);
+ error = getsockname(dst, (struct sockaddr *)&data4, &len);
if (error == -1) {
lprtfail:
n = snprintf(sbuf, sizeof(sbuf),
"500 could not translate to PORT\r\n");
- return n > 0 ? write(src, sbuf, n) : n;
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
+ return n;
}
if (((struct sockaddr *)&data4)->sa_family != AF_INET)
goto lprtfail;
@@ -834,8 +857,8 @@ lprtfail:
}
/* transmit PORT */
- n = sizeof(data4);
- error = getsockname(wport4, (struct sockaddr *)&data4, &n);
+ len = sizeof(data4);
+ error = getsockname(wport4, (struct sockaddr *)&data4, &len);
if (error == -1) {
close(wport4);
wport4 = -1;
@@ -852,8 +875,10 @@ lprtfail:
n = snprintf(sbuf, sizeof(sbuf), "PORT %d,%d,%d,%d,%d,%d\r\n",
UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
UC(p[0]), UC(p[1]));
- if (n > 0)
- n = write(dst, sbuf, n);
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(dst, sbuf, n);
*state = nstate;
passivemode = 0;
return n;
@@ -875,7 +900,11 @@ lprtfail:
if (epsvall) {
n = snprintf(sbuf, sizeof(sbuf), "501 %s disallowed in EPSV ALL\r\n",
cmd);
- return n > 0 ? write(src, sbuf, n) : n;
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
+ return n;
}
p = param;
@@ -887,7 +916,11 @@ lprtfail:
eprtparamfail:
n = snprintf(sbuf, sizeof(sbuf),
"501 illegal parameter to EPRT\r\n");
- return n > 0 ? write(src, sbuf, n) : n;
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
+ return n;
}
*p++ = '\0';
hostp = p;
@@ -907,21 +940,34 @@ eprtparamfail:
if (n != 1 || af != 2) {
n = snprintf(sbuf, sizeof(sbuf),
"501 unsupported address family to EPRT\r\n");
- return n > 0 ? write(src, sbuf, n) : n;
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
+ return n;
}
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
error = getaddrinfo(hostp, portp, &hints, &res);
if (error) {
n = snprintf(sbuf, sizeof(sbuf),
"501 EPRT: %s\r\n", gai_strerror(error));
- return n > 0 ? write(src, sbuf, n) : n;
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
+ return n;
}
if (res->ai_next) {
n = snprintf(sbuf, sizeof(sbuf),
"501 EPRT: %s resolved to multiple addresses\r\n", hostp);
- return n > 0 ? write(src, sbuf, n) : n;
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
+ return n;
}
memcpy(&data6, res->ai_addr, res->ai_addrlen);
@@ -942,13 +988,19 @@ eprtparamfail:
if (epsvall) {
n = snprintf(sbuf, sizeof(sbuf), "501 %s disallowed in EPSV ALL\r\n",
cmd);
- return n > 0 ? write(src, sbuf, n) : n;
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
+ return n;
}
/* transmit PASV */
n = snprintf(sbuf, sizeof(sbuf), "PASV\r\n");
- if (n > 0)
- n = write(dst, sbuf, n);
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(dst, sbuf, n);
*state = LPSV;
passivemode = 0; /* to be set to 1 later */
return n;
@@ -963,8 +1015,10 @@ eprtparamfail:
wport4 = wport6 = port4 = port6 = -1;
n = snprintf(sbuf, sizeof(sbuf), "PASV\r\n");
- if (n > 0)
- n = write(dst, sbuf, n);
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(dst, sbuf, n);
*state = EPSV;
passivemode = 0; /* to be set to 1 later */
return n;
@@ -975,120 +1029,21 @@ eprtparamfail:
*/
epsvall = 1;
n = snprintf(sbuf, sizeof(sbuf), "200 EPSV ALL command successful.\r\n");
- return n > 0 ? write(src, sbuf, n) : n;
-#ifdef FAITH4
- } else if (strcmp(cmd, "PORT") == 0 && param) {
- /*
- * PORT -> EPRT
- */
- char host[NI_MAXHOST], serv[NI_MAXSERV];
-
- nstate = PORT;
-
- close(wport4);
- close(wport6);
- close(port4);
- close(port6);
- wport4 = wport6 = port4 = port6 = -1;
-
- p = param;
- n = sscanf(p, "%u,%u,%u,%u,%u,%u",
- &ho[0], &ho[1], &ho[2], &ho[3], &po[0], &po[1]);
- if (n != 6) {
- n = snprintf(sbuf, sizeof(sbuf),
- "501 illegal parameter to PORT\r\n");
- return n > 0 ? write(src, sbuf, n) : n;
- }
-
- memset(&data6, 0, sizeof(data6));
- sin = (struct sockaddr_in *)&data6;
- sin->sin_len = sizeof(*sin);
- sin->sin_family = AF_INET;
- sin->sin_addr.s_addr = htonl(
- ((ho[0] & 0xff) << 24) | ((ho[1] & 0xff) << 16) |
- ((ho[2] & 0xff) << 8) | (ho[3] & 0xff));
- sin->sin_port = htons(((po[0] & 0xff) << 8) | (po[1] & 0xff));
-
- /* get ready for active data connection */
- n = sizeof(data4);
- error = getsockname(dst, (struct sockaddr *)&data4, &n);
- if (error == -1) {
-portfail:
- n = snprintf(sbuf, sizeof(sbuf),
- "500 could not translate to EPRT\r\n");
- return n > 0 ? write(src, sbuf, n) : n;
- }
- if (((struct sockaddr *)&data4)->sa_family != AF_INET6)
- goto portfail;
-
- ((struct sockaddr_in6 *)&data4)->sin6_port = 0;
- sa = (struct sockaddr *)&data4;
- wport4 = socket(sa->sa_family, SOCK_STREAM, 0);
- if (wport4 == -1)
- goto portfail;
- error = bind(wport4, sa, sa->sa_len);
- if (error == -1) {
- close(wport4);
- wport4 = -1;
- goto portfail;
- }
- error = listen(wport4, 1);
- if (error == -1) {
- close(wport4);
- wport4 = -1;
- goto portfail;
- }
-
- /* transmit EPRT */
- n = sizeof(data4);
- error = getsockname(wport4, (struct sockaddr *)&data4, &n);
- if (error == -1) {
- close(wport4);
- wport4 = -1;
- goto portfail;
- }
- af = 2;
- sa = (struct sockaddr *)&data4;
- if (getnameinfo(sa, sa->sa_len, host, sizeof(host),
- serv, sizeof(serv), NI_NUMERICHOST | NI_NUMERICSERV)) {
- close(wport4);
- wport4 = -1;
- goto portfail;
- }
- n = snprintf(sbuf, sizeof(sbuf), "EPRT |%d|%s|%s|\r\n", af, host, serv);
- if (n > 0)
- n = write(dst, sbuf, n);
- *state = nstate;
- passivemode = 0;
- return n;
- } else if (strcmp(cmd, "PASV") == 0 && !param) {
- /*
- * PASV -> EPSV
- */
-
- nstate = PASV;
-
- close(wport4);
- close(wport6);
- close(port4);
- close(port6);
- wport4 = wport6 = port4 = port6 = -1;
-
- /* transmit EPSV */
- n = snprintf(sbuf, sizeof(sbuf), "EPSV\r\n");
- if (n > 0)
- n = write(dst, sbuf, n);
- *state = PASV;
- passivemode = 0; /* to be set to 1 later */
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
return n;
-#else /* FAITH4 */
} else if (strcmp(cmd, "PORT") == 0 || strcmp(cmd, "PASV") == 0) {
/*
* reject PORT/PASV
*/
n = snprintf(sbuf, sizeof(sbuf), "502 %s not implemented.\r\n", cmd);
- return n > 0 ? write(src, sbuf, n) : n;
-#endif /* FAITH4 */
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
+ return n;
} else if (passivemode
&& (strcmp(cmd, "STOR") == 0
|| strcmp(cmd, "STOU") == 0
@@ -1103,8 +1058,10 @@ portfail:
if (ftp_passiveconn() < 0) {
n = snprintf(sbuf, sizeof(sbuf), "425 Cannot open data connetion\r\n");
- if (n > 0)
- n = write(src, sbuf, n);
+ if (n < 0 || n >= sizeof(sbuf))
+ n = 0;
+ if (n)
+ write(src, sbuf, n);
} else {
/* simply relay the command */
write(dst, rbuf, n);
@@ -1115,7 +1072,8 @@ portfail:
} else {
/* simply relay it */
*state = NONE;
- return write(dst, rbuf, n);
+ write(dst, rbuf, n);
+ return n;
}
bad:
OpenPOWER on IntegriCloud