Subject: bin/9158: Allow ftpd(8) tp specify passive port range.
To: None <gnats-bugs@gnats.netbsd.org>
From: Takahiro Kambe <taca@sky.yamashina.kyoto.jp>
List: netbsd-bugs
Date: 01/10/2000 04:22:00
>Number: 9158
>Category: bin
>Synopsis: Allow ftpd(8) tp specify passive port range.
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: bin-bug-people (Utility Bug People)
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Mon Jan 10 04:20:59 2000
>Last-Modified:
>Originator: Takahiro Kambe
>Organization:
>Release: NetBSD-current 2000/01/09
>Environment:
System: NetBSD land.sky.yamashina.kyoto.jp 1.4P NetBSD 1.4P (LAND) #167: Mon Jan 10 11:08:46 JST 2000 taca@land.sky.yamashina.kyoto.jp:/usr/src/sys/arch/i386/compile/LAND i386
>Description:
Allow ftpd(8) tp specify passive port range.
It makes easy to write access list of a router.
>How-To-Repeat:
Not a bug.
>Fix:
Attached diff is a sample fix.
Index: libexec/extern.h
diff -u libexec/extern.h.orig libexec/extern.h
--- extern.h.orig Sun Jan 9 03:42:21 2000
+++ extern.h Mon Jan 10 20:02:49 2000
@@ -159,6 +159,9 @@
struct ftpclass {
int checkportcmd; /* Check PORT commands are valid */
+ int passive_port; /* next passive port */
+ int pasv_port_min; /* minumum port number for passive mode */
+ int pasv_port_max; /* maximum port number for passive mode */
char *classname; /* Current class */
struct ftpconv *conversions; /* List of conversions */
char *display; /* Files to display upon chdir */
Index: libexec/conf.c
diff -u libexec/conf.c.orig libexec/conf.c
--- conf.c.orig Mon Jan 10 01:51:56 2000
+++ conf.c Mon Jan 10 20:17:54 2000
@@ -89,6 +89,9 @@
free(conv);
}
curclass.checkportcmd = 0;
+ curclass.passive_port = 0;
+ curclass.pasv_port_min = 0;
+ curclass.pasv_port_max = 0;
REASSIGN(curclass.classname, NULL);
curclass.conversions = NULL;
REASSIGN(curclass.display, NULL);
@@ -127,6 +130,7 @@
size_t line;
unsigned int timeout;
struct ftpconv *conv, *cnext;
+ int port_min, port_max;
init_curclass();
REASSIGN(curclass.classname, xstrdup(findclass));
@@ -189,6 +193,30 @@
}
}
+ } else if (strcasecmp(word, "passive_port_range") == 0) {
+ if (!none && !EMPTYSTR(arg)) {
+ port_min = atoi(arg);
+ NEXTWORD(p, arg);
+ if (EMPTYSTR(arg)) {
+ syslog(LOG_WARNING,
+ "%s line %d: port range format error",
+ infile, (int)line);
+ continue;
+ }
+ port_max = atoi(arg);
+ if (port_min <= IPPORT_RESERVED ||
+ port_max <= IPPORT_RESERVED ||
+ port_min > IPPORT_ANONMAX ||
+ port_max > IPPORT_ANONMAX ||
+ port_min >= port_max) {
+ syslog(LOG_WARNING,
+ "%s line %d: port range value error",
+ infile, (int)line);
+ continue;
+ }
+ curclass.pasv_port_min = port_min;
+ curclass.pasv_port_max = port_max;
+ }
} else if (strcasecmp(word, "conversion") == 0) {
char *suffix, *types, *disable, *convcmd;
Index: libexec/ftpd.c
diff -u libexec/ftpd.c.orig libexec/ftpd.c
--- ftpd.c.orig Sun Jan 9 03:42:21 2000
+++ ftpd.c Mon Jan 10 20:04:11 2000
@@ -2239,6 +2239,7 @@
{
int len;
char *p, *a;
+ int port;
if (pdata >= 0)
close(pdata);
@@ -2248,10 +2249,33 @@
return;
}
pasv_addr = ctrl_addr;
- pasv_addr.su_port = 0;
len = pasv_addr.su_len;
- if (bind(pdata, (struct sockaddr *)&pasv_addr, len) < 0) {
- goto pasv_error;
+ if (curclass.pasv_port_min == 0 && curclass.pasv_port_max == 0) {
+ pasv_addr.su_port = 0;
+ if (bind(pdata, (struct sockaddr *)&pasv_addr, len) == 0)
+ goto pasv_error;
+ } else {
+ if (curclass.passive_port == 0) {
+#ifdef NO_RANDOM_INIT
+ curclass.passive_port = curclass.pasv_port_min;
+#else
+ srand(getpid());
+ curclass.passive_port = rand() % (curclass.pasv_port_max - curclass.pasv_port_min) + curclass.pasv_port_min;
+#endif
+ }
+ port = curclass.passive_port;
+ pasv_addr.su_port = htons(port);
+ while (bind(pdata, (struct sockaddr *)&pasv_addr, len) != 0) {
+ if (errno != EADDRINUSE)
+ goto pasv_error;
+ port++;
+ if (port > curclass.pasv_port_max)
+ port = curclass.pasv_port_min;
+ else if (port == curclass.passive_port)
+ goto pasv_error;
+ pasv_addr.su_port = htons(port);
+ }
+ curclass.passive_port = port;
}
if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
goto pasv_error;
@@ -2282,6 +2306,7 @@
{
int len;
register char *p, *a;
+ int port;
if (!logged_in) {
syslog(LOG_NOTICE, "long passive but not logged in");
@@ -2324,9 +2349,33 @@
return;
}
pasv_addr = ctrl_addr;
- pasv_addr.su_port = 0;
- if (bind(pdata, (struct sockaddr *) &pasv_addr, pasv_addr.su_len) < 0) {
- goto pasv_error;
+ if (curclass.pasv_port_min == 0 && curclass.pasv_port_max == 0) {
+ pasv_addr.su_port = 0;
+ if (bind(pdata, (struct sockaddr *) &pasv_addr, pasv_addr.su_len) < 0) {
+ goto pasv_error;
+ }
+ } else {
+ if (curclass.passive_port == 0) {
+#ifdef NO_RANDOM_INIT
+ curclass.passive_port = curclass.pasv_port_min;
+#else
+ srand(getpid());
+ curclass.passive_port = rand() % (curclass.pasv_port_max - curclass.pasv_port_min) + curclass.pasv_port_min;
+#endif
+ }
+ port = curclass.passive_port;
+ pasv_addr.su_port = htons(port);
+ while (bind(pdata, (struct sockaddr *)&pasv_addr, len) != 0) {
+ if (errno != EADDRINUSE)
+ goto pasv_error;
+ port++;
+ if (port > curclass.pasv_port_max)
+ port = curclass.pasv_port_min;
+ else if (port == curclass.passive_port)
+ goto pasv_error;
+ pasv_addr.su_port = htons(port);
+ }
+ curclass.passive_port = port;
}
len = pasv_addr.su_len;
if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
Index: libexec/ftpd.conf.5
diff -u libexec/ftpd.conf.5.orig libexec/ftpd.conf.5
--- ftpd.conf.5.orig Mon Jan 10 01:51:56 2000
+++ ftpd.conf.5 Mon Jan 10 21:10:29 2000
@@ -116,6 +116,14 @@
or
.Sy off
is given, disable this feature, otherwise enable it.
+.It Sy passive_port_range Ar class Sy min Sy max
+Set the range of port number, which will be used for passive data
+port.
+.Sy max
+must be greater than
+.Sy min
+and those number must be greater than
+.Dv IPPORT_RESERVED .
.It Sy classtype Ar class Ar type
Set the class type of
.Ar class
>Audit-Trail:
>Unformatted: