Subject: bin/9606: patches to facilitate passive ftp server protocol behind firewall
To: None <gnats-bugs@gnats.netbsd.org>
From: None <srp@zgi.com>
List: netbsd-bugs
Date: 03/12/2000 11:21:53
>Number: 9606
>Category: bin
>Synopsis: patches to facilitate passive ftp server protocol behind firewall
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: bin-bug-people (Utility Bug People)
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Sun Mar 12 11:21:00 2000
>Last-Modified:
>Originator: Scott Presnell
>Organization:
self
>Release: 1.4.1 on i386 platform
>Environment:
NetBSD srp4 1.4.1 NetBSD 1.4.1 (RHINE) #16: Sat Mar 11 21:11:18 PST 2000 srp@srp4:/usr/src/sys/arch/i386/compile/RHINE i386
>Description:
My ftp server lives at a "bimap"ed address in private address space,
behind a firewall. To facilitate the passive ftp server protocol I
made the advertized address configurable so clients could contact
the appropriate real IP world address. I also made the port range
used in a passive protocol connection configurable so that I only
have to open a specific range of ports to connections from the
outside. These changes are similar parts of other ftp servers,
but use the NetBSD ftpd.conf interface.
Unified patches follow in fix. Thanks. - Scott
>How-To-Repeat:
>Fix:
--- extern.h.orig Wed Mar 8 08:07:35 2000
+++ extern.h Wed Mar 8 14:02:43 2000
@@ -90,6 +90,9 @@
int modify; /* Allow dele, mkd, rmd, umask, chmod */
char *notify; /* Files to notify about upon chdir */
int passive; /* Allow pasv */
+ char *paddr; /* Passive advertized inet_addr */
+ int phigh; /* Passive high port */
+ int plow; /* Passive low port */
unsigned int timeout; /* Default timeout */
mode_t umask; /* Umask to use */
};
--- conf.c.orig Wed Mar 8 08:07:21 2000
+++ conf.c Wed Mar 8 08:25:59 2000
@@ -107,6 +107,9 @@
curclass.modify = 1;
REASSIGN(curclass.notify, NULL);
curclass.passive = 1;
+ REASSIGN(curclass.paddr, NULL);
+ curclass.phigh = 0;
+ curclass.plow = 0;
curclass.timeout = 900; /* 15 minutes */
curclass.umask = 027;
@@ -259,6 +262,32 @@
curclass.passive = 0;
else
curclass.passive = 1;
+ } else if (strcasecmp(word, "paddr") == 0) {
+ if (none || EMPTYSTR(arg))
+ arg = NULL;
+ else
+ arg = strdup(arg);
+ REASSIGN(curclass.paddr, arg);
+ } else if (strcasecmp(word, "pports") == 0) {
+ unsigned int low = 0;
+ unsigned int high = 0;
+ if (none || EMPTYSTR(arg)) {
+ arg = NULL;
+ } else {
+ arg = strdup(arg);
+ if (sscanf(arg, "%d-%d", &low, &high) != 2) {
+ syslog(LOG_WARNING,
+ "%s line %d: bad pports range '%s'",
+ infile, line, arg);
+ }
+ if (low > high) {
+ unsigned int temp = low;
+ low = high;
+ high = temp;
+ }
+ }
+ curclass.plow = low;
+ curclass.phigh = high;
} else if (strcasecmp(word, "timeout") == 0) {
if (none || EMPTYSTR(arg))
continue;
--- ftpd.c.orig Sun Dec 27 20:54:01 1998
+++ ftpd.c Wed Mar 8 12:27:33 2000
@@ -1579,7 +1579,10 @@
passive()
{
int len;
+ int j;
+ int berror;
char *p, *a;
+ struct in_addr pasv_advert;
pdata = socket(AF_INET, SOCK_STREAM, 0);
if (pdata < 0 || !logged_in) {
@@ -1587,19 +1590,44 @@
return;
}
pasv_addr = ctrl_addr;
- pasv_addr.sin_port = 0;
+ if (curclass.paddr) {
+ pasv_advert.s_addr = inet_addr(curclass.paddr);
+ } else {
+ pasv_advert.s_addr = pasv_addr.sin_addr.s_addr;
+ }
+
(void) seteuid((uid_t)0);
- if (bind(pdata, (struct sockaddr *)&pasv_addr, sizeof(pasv_addr)) < 0) {
+
+ berror = -1;
+ errno = EADDRINUSE;
+ if (curclass.plow && curclass.phigh) {
+ for (j = curclass.phigh;
+ (berror < 0) && (errno == EADDRINUSE) &&
+ (j > curclass.plow);
+ j--) {
+ pasv_addr.sin_port = htons(j);
+ berror = bind(pdata, (struct sockaddr *)&pasv_addr,
+ sizeof(pasv_addr));
+ }
+
+ } else {
+ pasv_addr.sin_port = 0;
+ berror = bind(pdata, (struct sockaddr *)&pasv_addr,
+ sizeof(pasv_addr));
+ }
+
+ if (berror < 0) {
(void) seteuid((uid_t)pw->pw_uid);
goto pasv_error;
}
+
(void) seteuid((uid_t)pw->pw_uid);
len = sizeof(pasv_addr);
if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
goto pasv_error;
if (listen(pdata, 1) < 0)
goto pasv_error;
- a = (char *) &pasv_addr.sin_addr;
+ a = (char *) &pasv_advert;
p = (char *) &pasv_addr.sin_port;
#define UC(b) (((int) b) & 0xff)
--- ftpd.8.orig Wed Mar 8 12:18:50 2000
+++ ftpd.8 Wed Mar 8 12:24:33 2000
@@ -448,6 +448,13 @@
or
.Sy off
is given, disallow passive (PASV) connections. Otherwise, enable them.
+.It Sy paddr Ar class Op Sy inet addr
+When using the passive protocol, advertize this address as the inet
+address to connect: useful when the ftp server is mapped to a different
+network behind a firewall.
+.It Sy pports Ar class Op Sy low-high
+When using the passive protocol, use a port number within this range
+for the connection: useful in limiting port range opening at firewall.
.It Sy timeout Ar class Ar time
Set the inactivity timeout period.
(the default is fifteen minutes).
>Audit-Trail:
>Unformatted: