summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCamiel Dobbelaar <camield@cvs.openbsd.org>2007-08-15 15:18:03 +0000
committerCamiel Dobbelaar <camield@cvs.openbsd.org>2007-08-15 15:18:03 +0000
commit98d9ef4ebea954237354f05151ebc389d3fabdac (patch)
tree4f3dcfe00b3c4a7caec0ce583f450af956c6b1ec
parentcde03a4a0a3c7469d5d22de04feafcb05d2c595a (diff)
Some servers / proxies out there like to open the data connection
immediately after the client sends the PORT command. The "normal" behaviour is to wait for the client to actually request a transfer. Make ftp-proxy add the active mode rules immediately too, so that both scenario's work. ok david pyr Tested by Frank Denis, Stephan A. Rickauer, Ingo Schwarze, Stuart Henderson. Thanks.
-rw-r--r--usr.sbin/ftp-proxy/ftp-proxy.c45
1 files changed, 34 insertions, 11 deletions
diff --git a/usr.sbin/ftp-proxy/ftp-proxy.c b/usr.sbin/ftp-proxy/ftp-proxy.c
index a5e585ecbe1..3a691859c32 100644
--- a/usr.sbin/ftp-proxy/ftp-proxy.c
+++ b/usr.sbin/ftp-proxy/ftp-proxy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ftp-proxy.c,v 1.14 2007/08/01 09:31:41 henning Exp $ */
+/* $OpenBSD: ftp-proxy.c,v 1.15 2007/08/15 15:18:02 camield Exp $ */
/*
* Copyright (c) 2004, 2005 Camiel Dobbelaar, <cd@sentia.nl>
@@ -102,6 +102,7 @@ u_int16_t pick_proxy_port(void);
void proxy_reply(int, struct sockaddr *, u_int16_t);
void server_error(struct bufferevent *, short, void *);
int server_parse(struct session *s);
+int allow_data_connection(struct session *s);
void server_read(struct bufferevent *, void *);
const char *sock_ntop(struct sockaddr *);
void usage(void);
@@ -149,8 +150,19 @@ client_parse(struct session *s)
return (1);
if (linebuf[0] == 'P' || linebuf[0] == 'p' ||
- linebuf[0] == 'E' || linebuf[0] == 'e')
- return (client_parse_cmd(s));
+ linebuf[0] == 'E' || linebuf[0] == 'e') {
+ if (!client_parse_cmd(s))
+ return (0);
+
+ /*
+ * Allow active mode connections immediately, instead of
+ * waiting for a positive reply from the server. Some
+ * rare servers/proxies try to probe or setup the data
+ * connection before an actual transfer request.
+ */
+ if (s->cmd == CMD_PORT || s->cmd == CMD_EPRT)
+ return (allow_data_connection(s));
+ }
if (anonymous_only && (linebuf[0] == 'U' || linebuf[0] == 'u'))
return (client_parse_anon(s));
@@ -894,12 +906,26 @@ server_error(struct bufferevent *bufev, short what, void *arg)
int
server_parse(struct session *s)
{
- struct sockaddr *client_sa, *orig_sa, *proxy_sa, *server_sa;
- int prepared = 0;
-
if (s->cmd == CMD_NONE || linelen < 4 || linebuf[0] != '2')
goto out;
+ if ((s->cmd == CMD_PASV && strncmp("227 ", linebuf, 4) == 0) ||
+ (s->cmd == CMD_EPSV && strncmp("229 ", linebuf, 4) == 0))
+ return (allow_data_connection(s));
+
+ out:
+ s->cmd = CMD_NONE;
+ s->port = 0;
+
+ return (1);
+}
+
+int
+allow_data_connection(struct session *s)
+{
+ struct sockaddr *client_sa, *orig_sa, *proxy_sa, *server_sa;
+ int prepared = 0;
+
/*
* The pf rules below do quite some NAT rewriting, to keep up
* appearances. Points to keep in mind:
@@ -924,8 +950,7 @@ server_parse(struct session *s)
orig_sa = sstosa(&s->server_ss);
/* Passive modes. */
- if ((s->cmd == CMD_PASV && strncmp("227 ", linebuf, 4) == 0) ||
- (s->cmd == CMD_EPSV && strncmp("229 ", linebuf, 4) == 0)) {
+ if (s->cmd == CMD_PASV || s->cmd == CMD_EPSV) {
s->port = parse_port(s->cmd);
if (s->port < MIN_PORT) {
logmsg(LOG_CRIT, "#%d bad port in '%s'", s->id,
@@ -966,8 +991,7 @@ server_parse(struct session *s)
}
/* Active modes. */
- if ((s->cmd == CMD_PORT || s->cmd == CMD_EPRT) &&
- strncmp("200 ", linebuf, 4) == 0) {
+ if (s->cmd == CMD_PORT || s->cmd == CMD_EPRT) {
logmsg(LOG_INFO, "#%d active: server to client port %d"
" via port %d", s->id, s->port, s->proxy_port);
@@ -1017,7 +1041,6 @@ server_parse(struct session *s)
goto fail;
}
- out:
s->cmd = CMD_NONE;
s->port = 0;