Great Circle Associates Firewalls
(November 1993)
 

Indexed By Date: [Previous] [Next] Indexed By Thread: [Previous] [Next]

Subject: ftp "PASV" passive mode patch.
From: Nick Sayer <mrapple @ quack . kfu . com>
Date: Sun, 31 Oct 1993 17:32:16 -0800
To: firewalls @ greatcircle . com

Many sites on the net today choose to block most incoming TCP sessions
while allowing outgoing connections as a compromise between utility and
security. The trouble with this is that blocking incoming connections
kills traditional ftp client programs since they use the "port" command
to tell the server where to connect to send the file. The server then
opens a connection to an effectively arbitrarily chosen socket number.

Fortunately there is an alternative to this behavior that allows the
client to open the data socket, which allows you to have the firewall
and ftp too. This alternate paradigm basically emulates  proxy mode
transfers. The client sends a PASV command to the server, then opens a
data socket to the indicated address, and finally sends the transfer
command.

The only trouble with this idea is that it breaks down when the server
site has a similarly paranoid administrator and has blocked arbitrary
incoming connections. Because of this, the passive behavior should be
user-selectable. So this patch adds a 'passive' command that toggles the
behavior (defaulting to on). If you find that passive transfers aren't
working, just type 'passive' and it will revert to the traditional
"port" commands (you can of course use the "sendport" command to change
this).

Credit for the idea goes to Steve Bellovin. Many thanks for the start,
Steve.

Obtain the source to the ftp client in the BSD sources (uunet has it),
unpack it and apply this patch.

If you're building for SunOS 4.1.x, you will also want to add

typedef void (*sig_t)();

to ftp_var.h and replace the include of <paths.h> with a
#define _PATH_BSHELL "/bin/sh" in pathnames.h to make the program
compile properly.

*** ./cmds.c	Sun Oct 10 09:17:00 1993
--- ../cmds.c	Sat Oct  9 05:21:10 1993
***************
*** 2133,2135 ****
--- 2133,2150 ----
  		printf("Local file \"%s\" is newer than remote file \"%s\"\n",
  			argv[1], argv[2]);
  }
+ 
+ #ifndef NO_PASSIVE_MODE
+ /*
+  * Start up passive mode interaction
+  */
+ 
+ /*VARARGS*/
+ setpassive()
+ {
+ 
+ 	passivemode = !passivemode;
+ 	printf("Passive mode %s.\n", onoff(passivemode));
+ 	code = passivemode;
+ }
+ #endif
*** ./cmdtab.c	Sun Oct 10 09:17:04 1993
--- ../cmdtab.c	Sat Oct  9 05:24:57 1993
***************
*** 54,59 ****
--- 54,62 ----
  int	setsunique(), setrunique(), cdup(), macdef(), domacro();
  int	sizecmd(), modtime(), newer(), rmtstatus();
  int	do_chmod(), do_umask(), idle();
+ #ifndef NO_PASSIVE_MODE
+ int	setpassive();
+ #endif
  
  char	accounthelp[] =	"send account command to remote server";
  char	appendhelp[] =	"append to a file";
***************
*** 120,125 ****
--- 123,131 ----
  char	umaskhelp[] =	"get (set) umask on remote side";
  char	userhelp[] =	"send new user information";
  char	verbosehelp[] =	"toggle verbose mode";
+ #ifndef NO_PASSIVE_MODE
+ char	setpassivehelp[] = "enter passive transfer mode";
+ #endif
  
  struct cmd cmdtab[] = {
  	{ "!",		shellhelp,	0,	0,	0,	shell },
***************
*** 164,169 ****
--- 170,178 ----
  	{ "ntrans",	ntranshelp,	0,	0,	1,	setntrans },
  	{ "open",	connecthelp,	0,	0,	1,	setpeer },
  	{ "prompt",	prompthelp,	0,	0,	0,	setprompt },
+ #ifndef NO_PASSIVE_MODE
+ 	{ "passive",	setpassivehelp,	0,	0,	0,	setpassive },
+ #endif
  	{ "proxy",	proxyhelp,	0,	0,	1,	doproxy },
  	{ "sendport",	porthelp,	0,	0,	0,	setport },
  	{ "put",	sendhelp,	1,	1,	1,	put },
*** ./ftp.c	Sun Oct 10 09:17:29 1993
--- ../ftp.c	Sat Oct  9 05:44:04 1993
***************
*** 1002,1008 ****
--- 1002,1057 ----
  	register char *p, *a;
  	int result, len, tmpno = 0;
  	int on = 1;
+ #ifndef NO_PASSIVE_MODE
+ 	int a1,a2,a3,a4,p1,p2;
  
+ 	if (passivemode) {
+ 		data = socket(AF_INET, SOCK_STREAM, 0);
+ 		if (data < 0) {
+ 			perror("ftp: socket");
+ 			return(1);
+ 		}
+ 		if (options & SO_DEBUG &&
+ 		    setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
+ 			perror("ftp: setsockopt (ignored)");
+ 		if (command("PASV") != COMPLETE) {
+ 			printf("Passive mode refused.\n");
+ 			return(1);
+ 		}
+ 
+ /*
+  * What we've got at this point is a string of comma separated
+  * one-byte unsigned integer values, separated by commas.
+  * The first four are the an IP address. The fifth is the MSB
+  * of the port number, the sixth is the LSB. From that we'll
+  * prepare a sockaddr_in.
+  */
+ 
+ 		if (sscanf(pasv,"%d,%d,%d,%d,%d,%d",&a1,&a2,&a3,&a4,&p1,&p2) != 6) {
+ 			printf("Passive mode address scan failure. Shouldn't happen!\n");
+ 			return(1);
+ 		};
+ 
+ 		data_addr.sin_family = AF_INET;
+ 		data_addr.sin_addr.S_un.S_un_b.s_b1 = a1;
+ 		data_addr.sin_addr.S_un.S_un_b.s_b2 = a2;
+ 		data_addr.sin_addr.S_un.S_un_b.s_b3 = a3;
+ 		data_addr.sin_addr.S_un.S_un_b.s_b4 = a4;
+ 		data_addr.sin_port = (p1<<8)|p2;
+ 
+ 		if (connect(data, (struct sockaddr *) &data_addr, sizeof(data_addr))<0) {
+ 			perror("ftp: connect");
+ 			return(1);
+ 		}
+ #ifdef IP_TOS
+ 	on = IPTOS_THROUGHPUT;
+ 	if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
+ 		perror("ftp: setsockopt TOS (ignored)");
+ #endif
+ 		return(0);
+ 	}
+ #endif
+ 
  noport:
  	data_addr = myctladdr;
  	if (sendport)
***************
*** 1072,1077 ****
--- 1121,1130 ----
  	struct sockaddr_in from;
  	int s, fromlen = sizeof (from), tos;
  
+ #ifndef NO_PASSIVE_MODE
+ if (passivemode)
+ 	return (fdopen(data, lmode));
+ #endif
  	s = accept(data, (struct sockaddr *) &from, &fromlen);
  	if (s < 0) {
  		perror("ftp: accept");
*** ./ftp_var.h	Sun Oct 10 09:17:33 1993
--- ../ftp_var.h	Sat Oct  9 04:50:51 1993
***************
*** 61,66 ****
--- 63,71 ----
  int	code;			/* return/reply code for ftp command */
  int	crflag;			/* if 1, strip car. rets. on ascii gets */
  char	pasv[64];		/* passive port for proxy data connection */
+ #ifndef NO_PASSIVE_MODE
+ int	passivemode;		/* passive mode enabled */
+ #endif
  char	*altarg;		/* argv[1] with no shell-like preprocessing  */
  char	ntin[17];		/* input translation table */
  char	ntout[17];		/* output translation table */
*** ./main.c	Sun Oct 10 09:17:45 1993
--- ../main.c	Sat Oct  9 05:42:13 1993
***************
*** 121,126 ****
--- 121,129 ----
  		verbose++;
  	cpend = 0;	/* no pending replies */
  	proxy = 0;	/* proxy not active */
+ #ifndef NO_PASSIVE_MODE
+ 	passivemode = 1; /* passive mode active */
+ #endif
  	crflag = 1;	/* strip c.r. on ascii gets */
  	sendport = -1;	/* not using ports */
  	/*



Follow-Ups:
Indexed By Date Previous:
From: (nil)
Next: approaches to estab. firewall host
From: Matthew Cilento <technet!mtc @ uunet . UU . NET>
Indexed By Thread Previous:
From: (nil)
Next: Re: ftp "PASV" passive mode patch.
From: Brad Huntting <huntting @ advtech . uswest . com>

Google
 
Search Internet Search www.greatcircle.com