--- ftpd.c.orig 2002-10-01 15:39:24.000000000 -0400 +++ ftpd.c 2002-10-02 12:06:47.000000000 -0400 @@ -170,6 +170,8 @@ int stru; /* avoid C keyword */ int mode; int usedefault = 1; /* for data transfers */ int pdata = -1; /* for passive mode */ +int pasv_start_port = 0; /* for passive mode */ +int pasv_end_port = 0; /* for passive mode */ sig_atomic_t transflag; off_t file_size; off_t byte_count; @@ -325,16 +327,28 @@ main(argc, argv, envp) LastArgv = envp[-1] + strlen(envp[-1]); #endif /* SETPROCTITLE */ - while ((ch = getopt(argc, argv, "dlt:T:u:v")) != EOF) { + while ((ch = getopt(argc, argv, "de:ls:t:T:u:v")) != EOF) { switch (ch) { case 'd': debug = 1; break; + case 'e': + pasv_end_port = atoi(optarg); + if (pasv_end_port < 0) + pasv_end_port = 0; + break; + case 'l': logging++; /* > 1 == extra logging */ break; + case 's': + pasv_start_port = atoi(optarg); + if (pasv_start_port < 0) + pasv_start_port = 0; + break; + case 't': timeout = atoi(optarg); if (maxtimeout < timeout) @@ -370,6 +384,9 @@ main(argc, argv, envp) break; } } + if (pasv_end_port < pasv_start_port) + pasv_end_port = pasv_start_port; + (void) freopen(PATH_DEVNULL, "w", stderr); (void) signal(SIGPIPE, lostconn); (void) signal(SIGCHLD, SIG_IGN); @@ -1582,6 +1599,7 @@ void passive() { int len; + int pasv_port; char *p, *a; pdata = socket(AF_INET, SOCK_STREAM, 0); @@ -1589,12 +1607,16 @@ passive() perror_reply(425, "Can't open passive connection"); return; } - pasv_addr = ctrl_addr; - pasv_addr.sin_port = 0; (void) seteuid(getuid ()); - if (bind(pdata, (struct sockaddr *)&pasv_addr, sizeof(pasv_addr)) < 0) { - (void) seteuid((uid_t)pw->pw_uid); - goto pasv_error; + pasv_addr = ctrl_addr; + for (pasv_port = pasv_start_port; pasv_port <= pasv_end_port; pasv_port++) { + pasv_addr.sin_port = htons(pasv_port); + if (bind(pdata, (struct sockaddr *)&pasv_addr, sizeof(pasv_addr)) == 0) + break; + if (errno != EADDRINUSE || pasv_port == pasv_end_port) { + (void) seteuid((uid_t)pw->pw_uid); + goto pasv_error; + } } (void) seteuid((uid_t)pw->pw_uid); len = sizeof(pasv_addr);