Great Circle Associates Firewalls
(October 1996)
 

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

Subject: Patches to NcFTP 2.4.0 to support application proxies
From: carson @ lehman . com
Date: Wed, 23 Oct 1996 17:09:26 -0400
To: firewalls @ greatcircle . com
Cc: "Frederik H. Andersen" <fha @ dde . dk>, Adam Shostack <adam @ homeport . org>, mgleason @ probe . net
In-reply-to: <199608270229 . VAA24879 @ homeport . org>
References: <199608261740 . NAA22047 @ dragon . lehman . com> <199608270229 . VAA24879 @ homeport . org>
Reply-to: carson @ lehman . com

Here are my long-promised patches to NcFTP to add support for application
proxies. These have been very lightly tested, and may therefore contain any
number of bugs I haven't caught, but they _seem_ to be working. :)

Documentation on the new functionality is in the on-line help and in the man
page, but take a close look at:

Config.h.in:

#define USE_BASTION_APP_PROXY			/* enable app proxy support */
#define BH_NAME_ENV "INTERNET_HOST"		/* envar for BH name */
#define BH_NAME_DEF "firewall.lehman.com"	/* default BH to use */
#define BH_PORT_ENV "INTERNET_FTP_PORT"		/* envar for BH ftp port */
#define BH_PORT_SERV "ftp-passthru"		/* service for BH ftp port */
#define BH_PORT_DEF 21				/* default for BH ftp port */
#define BH_LOCALDOM_ENV "LOCAL_DOMAINS"		/* envar for local domain list */
#define BH_LOCALDOM_DEF ".lehman.com"		/* default local domain list */
#define BH_MAX_DOMAINS 100			/* max # of local domains */

Command line / open options:

-S   : Always connect locally, unless overridden by open -b
-B   : Always connect via the proxy, unless overridden by open -s
-s   : Connect directly, ignoring the local domain matching.
-b   : Connect via the proxy, ignoring the local domain matching.

Environment variables (as named in Config.h(.in)):

INTERNET_HOST
INTERNET_FTP_PORT
LOCAL_DOMAINS

--
Carson Gaspar -- carson @
 cs .
 columbia .
 edu carson @
 lehman .
 com
http://www.cs.columbia.edu/~carson/home.html
<This is the boring business .sig - no outre sayings here>

diff -c ../ncftp-2.4.0/Cmdlist.c ./Cmdlist.c
*** ../ncftp-2.4.0/Cmdlist.c	Thu Feb 22 22:07:18 1996
--- ./Cmdlist.c	Thu Oct 17 21:30:01 1996
***************
*** 285,292 ****
--- 285,295 ----
  		kCmdWaitMsg,
  		OpenCmd,
  		kNoMin, kNoMax,
+ #if defined(USE_BASTION_APP_PROXY)
  "[-flags] [sitename]\n\
  Flags:\n\
+   -s   : Connect directly, ignoring the local domain matching.\n\
+   -b   : Connect via the proxy, ignoring the local domain matching.\n\
    -a   : Open anonymously.\n\
    -u   : Open with username and password prompt.\n\
    -p X : Use port number X when opening.\n\
***************
*** 297,302 ****
--- 300,319 ----
    open sphygmomanometer.unl.edu\n\
    open -u bowser.nintendo.co.jp\n\
    open -r -d 75 -g 10 sphygmomanometer.unl.edu\n",
+ #else
+ "[-flags] [sitename]\n\
+ Flags:\n\
+   -a   : Open anonymously.\n\
+   -u   : Open with username and password prompt.\n\
+   -p X : Use port number X when opening.\n\
+   -r   : Redial until connected.\n\
+   -d X : Redial, delaying X seconds between tries.\n\
+   -g X : Give up after X redials without connection.\n\
+ Examples:\n\
+   open sphygmomanometer.unl.edu\n\
+   open -u bowser.nintendo.co.jp\n\
+   open -r -d 75 -g 10 sphygmomanometer.unl.edu\n",
+ #endif
  		"connects to a remote host",
  		kCompleteHost
  	},
diff -c ../ncftp-2.4.0/Config.h.in ./Config.h.in
*** ../ncftp-2.4.0/Config.h.in	Wed Oct 16 19:10:21 1996
--- ./Config.h.in	Thu Oct 17 20:44:27 1996
***************
*** 1,5 ****
--- 1,14 ----
  /* Config.h.in.  Generated automatically from configure.in by autoheader.  */
  
+ #define USE_BASTION_APP_PROXY			/* enable app proxy support */
+ #define BH_NAME_ENV "INTERNET_HOST"		/* envar for BH name */
+ #define BH_NAME_DEF "firewall.lehman.com"	/* default BH to use */
+ #define BH_PORT_ENV "INTERNET_FTP_PORT"		/* envar for BH ftp port */
+ #define BH_PORT_SERV "ftp-passthru"		/* service for BH ftp port */
+ #define BH_PORT_DEF 21				/* default for BH ftp port */
+ #define BH_LOCALDOM_ENV "LOCAL_DOMAINS"		/* envar for local domain list */
+ #define BH_LOCALDOM_DEF ".lehman.com"		/* default local domain list */
+ #define BH_MAX_DOMAINS 100			/* max # of local domains */
  
  /* Don't define HOSTNAME or DOMAINNAME unless you have to.  After compiling,
   * a test run of the program will tell you if it couldn't determine these
diff -c ../ncftp-2.4.0/Main.c ./Main.c
*** ../ncftp-2.4.0/Main.c	Wed Oct 16 18:55:12 1996
--- ./Main.c	Wed Oct 23 16:50:01 1996
***************
*** 25,30 ****
--- 25,31 ----
  #include <signal.h>
  #include <setjmp.h>
  #include <stdlib.h>
+ #include <netdb.h>
  
  #include "Util.h"
  #include "Main.h"
***************
*** 156,161 ****
--- 157,176 ----
   */
  int gStartup = 0;
  
+ #if defined(USE_BASTION_APP_PROXY)
+ /* pointer to bastion host name */
+ char *gBastionName;
+ 
+ /* bastion host port */
+ int gBastionPort;
+ 
+ /* list of local domains */
+ char *gLocalDomains[BH_MAX_DOMAINS];
+ 
+ /* Are we using an application proxy? Default to no. */
+ int gUseBastionAppProxy = 0;
+ #endif
+ 
  extern int gStdout, gRealStdout;
  extern char *getlogin(void);
  extern longstring gLocalCWD;
***************
*** 866,871 ****
--- 881,941 ----
  	int opt, result;
  	OpenOptions openopt;
  
+ #if defined(USE_BASTION_APP_PROXY)
+ 
+ 	if (!(gBastionName = getenv(BH_NAME_ENV))) {
+ 		gBastionName = BH_NAME_DEF;
+ 	}
+ 
+ 	if (gBastionName != (char *) NULL) {
+ 		char *domainlist,*colp,*p;
+ 		int nd = 0;
+ 		struct servent *se;
+ 
+ 		gUseBastionAppProxy = 1;
+ 		if (p = getenv(BH_PORT_ENV)) {
+ 			gBastionPort = atoi(p);
+ 		} else if (se = getservbyname(BH_PORT_SERV, "tcp")) {
+ 			gBastionPort = se->s_port;
+ 		} else {
+ 			gBastionPort = BH_PORT_DEF;
+ 		}
+ 		if (!(domainlist = getenv(BH_LOCALDOM_ENV))) {
+ 			domainlist = BH_LOCALDOM_DEF;
+ 		}
+ 		if (domainlist && strlen(domainlist)) {
+ 			p = domainlist;
+ 			colp = strchr(p, ':');
+ 			while (colp) {
+ 				*colp = '\0';
+ 				gLocalDomains[nd] = (char *) malloc(strlen(p)+1);
+ 				if (gLocalDomains[nd]) {
+ 					strcpy(gLocalDomains[nd],p);
+ 					nd++;
+ 				} else {
+ 					perror("malloc failed parsing local domains:");
+ 					exit(255);
+ 				}
+ 				p = colp+1;
+ 				colp = strchr(p, ':');
+ 			}
+ 			if (strlen(p)) {
+ 				gLocalDomains[nd] = (char *) malloc(strlen(p)+1);
+ 				if (gLocalDomains[nd]) {
+ 					strcpy(gLocalDomains[nd],p);
+ 					nd++;
+ 				} else {
+ 					perror("malloc failed parsing local domains:");
+ 					exit(255);
+ 				}
+ 				gLocalDomains[nd] = (char *) 0;
+ 			}
+ 		}
+ 				
+ 	}
+ 
+ #endif /* USE_BASTION_APP_PROXY */
+ 
  	Init();
  	RunStartupScript();
  
***************
*** 883,892 ****
  	 * commands' flags and the program must use mutually exclusive
  	 * sets of flags.
  	 */
  	while ((opt = Getopt(argc, argv, "aiup:rd:g:cmCfGRn:zDLVH")) >= 0) {
  		if (strchr("aiup:rd:g:cmCfGRn:z", opt) == NULL) {
  			switch (opt) {
! 				case 'D':
  					gDebug = kDebuggingOn;
  					gTrace = kTracingOn;
  					break;
--- 953,971 ----
  	 * commands' flags and the program must use mutually exclusive
  	 * sets of flags.
  	 */
+ #if defined(USE_BASTION_APP_PROXY)
+ 	while ((opt = Getopt(argc, argv, "aiup:rd:g:cmCfGRn:zsbSBDLVH")) >= 0) {
+ 		if (strchr("aiup:rd:g:cmCfGRn:zsb", opt) == NULL) {
+ #else
  	while ((opt = Getopt(argc, argv, "aiup:rd:g:cmCfGRn:zDLVH")) >= 0) {
  		if (strchr("aiup:rd:g:cmCfGRn:z", opt) == NULL) {
+ #endif
  			switch (opt) {
! #if defined(USE_BASTION_APP_PROXY)
! 				case 'S': gUseBastionAppProxy = -1; break;
! 				case 'B': gUseBastionAppProxy = 2; break;
! #endif
!  				case 'D':
  					gDebug = kDebuggingOn;
  					gTrace = kTracingOn;
  					break;
***************
*** 897,914 ****
--- 976,1015 ----
  				usage:
  					EPrintF(
  		"Usage: ncftp [options] [hostname[:path]]\n");
+ #if defined(USE_BASTION_APP_PROXY)
  					EPrintF("Program options:\n\
+   -S   : Always connect locally, unless overridden by open -b\n\
+   -B   : Always connect via the proxy, unless overridden by open -s\n\
    -D   : Turn debug mode and trace mode on.\n\
    -L   : Don't use visual mode (use line mode).\n\
    -V   : Use visual mode.\n\
    -H   : Dump the version information.\n");
+ #else
+ 					EPrintF("Program options:\n\
+   -D   : Turn debug mode and trace mode on.\n\
+   -L   : Don't use visual mode (use line mode).\n\
+   -V   : Use visual mode.\n\
+   -H   : Dump the version information.\n");
+ #endif
+ #if defined(USE_BASTION_APP_PROXY)
  					EPrintF("Command-line open options:\n\
+   -s   : Connect directly, ignoring the local domain matching.\n\
+   -b   : Connect via the proxy, ignoring the local domain matching.\n\
    -a   : Open anonymously.\n\
    -u   : Open with username and password prompt.\n\
    -p X : Use port number X when opening.\n\
    -r   : Redial until connected.\n\
    -d X : Redial, delaying X seconds between tries.\n\
    -g X : Give up after X redials without connection.\n");
+ #else
+ 					EPrintF("Command-line open options:\n\
+   -a   : Open anonymously.\n\
+   -u   : Open with username and password prompt.\n\
+   -p X : Use port number X when opening.\n\
+   -r   : Redial until connected.\n\
+   -d X : Redial, delaying X seconds between tries.\n\
+   -g X : Give up after X redials without connection.\n");
+ #endif
  					EPrintF("Command-line retrieve options:\n\
    -C   : Force continuation (reget).\n\
    -f   : Force overwrite.\n\
diff -c ../ncftp-2.4.0/Open.c ./Open.c
*** ../ncftp-2.4.0/Open.c	Wed Oct 16 16:33:51 1996
--- ./Open.c	Wed Oct 23 16:46:41 1996
***************
*** 5,10 ****
--- 5,13 ----
  #ifdef SYSLOG
  #	include <syslog.h>
  #endif
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #include <netdb.h>
  
  #include "Util.h"
  #include "Open.h"
***************
*** 60,65 ****
--- 63,74 ----
  int gSavePasswords = 0;
  
  /* Open.c externs */
+ #if defined(USE_BASTION_APP_PROXY)
+ extern char *gBastionName;
+ extern int gBastionPort, gUseBastionAppProxy;
+ extern char *gLocalDomains[];
+ extern struct hostent *GetHostEntry(char *host, struct in_addr *ip_address);
+ #endif
  extern char *gOptArg;
  extern int gOptInd, gIsToTTY;
  extern unsigned int gFTPPort;
***************
*** 105,111 ****
--- 114,193 ----
  
  
  
+ #if defined(USE_BASTION_APP_PROXY)
+ int LocalDomain(char *h, char **dl)
+ {
+ 	char *dom, *p, *q, **a;
+ 	int nd = 0, dlen, hlen, ret;
+ 	struct hostent *hp;
+ 	struct in_addr ha, la, lm, ipaddr;
+ 
+ 	hp = GetHostEntry(h, &ipaddr);
+ 
+ 	while (dl[nd]) {
+ 		if (dl[nd][0] == '!') {
+ 			ret = 0;
+ 			p = (dl[nd])+1;
+ 		} else {
+ 			ret = 1;
+ 			p = dl[nd];
+ 		}
+ 		if (p[0] == '.' && hp) {
+ 			dlen = strlen(p);
+ 			if (hp->h_name) {
+ 				hlen = strlen(hp->h_name);
+ 				if ((hlen > dlen) && (strcasecmp((hp->h_name)+hlen-dlen,p) == 0)) {
+ 					return ret;
+ 				}
+ 			}
+ 			for (a = hp->h_aliases; *a != 0; a++) {
+ 				hlen = strlen(*a);
+ 				if ((hlen > dlen) && (strcasecmp((*a)+hlen-dlen,p) == 0)) {
+ 					return ret;
+ 				}
+ 			}
+ 		} else if ((p[0] >= '0' && p[0] <= '9') && (hp || ipaddr.s_addr)) {
+ 			q = strchr(p, '/');
+ 			if (q == 0) {
+ 				lm.s_addr = 0xffffffff;
+ 				la.s_addr = inet_addr(p);
+ 			} else {
+ 				*q = '\0';
+ 				lm.s_addr = inet_addr(p+1);
+ 				la.s_addr = inet_addr(p);
+ 			}
+ 			if (la.s_addr == -1) {
+ 				fprintf(stderr, "%s is not a valid IP address!\n", p);
+ 				DoQuit(255);
+ 			}
+ 
+ 			*q = '/';
+ 
+ 			if (hp) {
+ 			  for (a = hp->h_addr_list; *a != 0; a++) {
+ 			    (void) memcpy(&ha.s_addr, *a, sizeof (ha.s_addr));
+ 			    if (((la.s_addr & lm.s_addr) ^ (ha.s_addr & lm.s_addr)) == 0) {
+ 			      return ret;
+ 			    }
+ 			  }
+ 			} else {
+ 			  if (((la.s_addr & lm.s_addr) ^ (ipaddr.s_addr & lm.s_addr)) == 0) {
+ 			    return ret;
+ 			  }
+ 			}
+ 		} else if (hp || (ipaddr.s_addr && (p[0] >= '0' && p[0] <= '9'))) {
+ 			fprintf(stderr,"bad local domain format - does not start with a period or a digit\n");
+ 			DoQuit(255);
+ 		}
+ 		nd++;
+ 	}
+ 	return(0);
+ }
+ 
+ int Login(char *u, char *p, char *a, char *h, int port)
+ #else
  int Login(char *u, char *p, char *a)
+ #endif
  {
  	string u2, p2, a2;
  	ResponsePtr rp;
***************
*** 119,125 ****
--- 201,226 ----
  	rp = InitResponse();
  	if (LoginQuestion("User", u2, sizeof(u2), "anonymous", 0) < 0)
  		goto done;
+ #if defined(USE_BASTION_APP_PROXY)
+ 	if ((gUseBastionAppProxy==2) || (gUseBastionAppProxy==1 && !LocalDomain(h, gLocalDomains))) {
+ 		char bh_user[1024];
+ 		char bh_port[255];
+ 		
+ 		strncpy(bh_user, u2, 1024);
+ 		strncat(bh_user, "@", 1024 - strlen(bh_user));
+ 		strncat(bh_user, h, 1024 - strlen(bh_user));
+ 		if (port != 21) {
+ 			sprintf(bh_port," %d",port);
+ 			strncat(bh_user, bh_port, 1024 - strlen(bh_user));
+ 		}
+ 		RCmd(rp, "USER %s", bh_user);
+ 	}
+ 	else {
+ 		RCmd(rp, "USER %s", u2);
+ 	}
+ #else
  	RCmd(rp, "USER %s", u2);
+ #endif
  
  	for (;;) {
  		/* Here's a mini finite-automaton for the login process.
***************
*** 334,341 ****
--- 435,456 ----
  
  	/* Tell Getopt() that we want to start over with a new command. */
  	GetoptReset();
+ #if defined(USE_BASTION_APP_PROXY)
+ 	while ((opt = Getopt(argc, argv, "aiup:rd:g:cmCfGRn:sb")) >= 0) {
+ 		switch (opt) {		
+ 			case 's':
+ 				/* Don't use the proxy */
+ 				openopt->useproxy = -1;
+ 				break;
+ 
+ 			case 'b':
+ 				/* Use the proxy */
+ 				openopt->useproxy = 2;
+ 				break;
+ #else
  	while ((opt = Getopt(argc, argv, "aiup:rd:g:cmCfGRn:")) >= 0) {
  		switch (opt) {		
+ #endif
  			case 'a':
  				/* User wants to open anonymously. */
  				openopt->openmode = kOpenExplicitAnon;
***************
*** 810,816 ****
--- 925,949 ----
  
  		SetBar(NULL, "CONNECTING", NULL, 1, 1);
  		gAttemptingConnection = 1;
+ #if defined(USE_BASTION_APP_PROXY)
+ 		if (openopt->useproxy == 2
+ 		    || (openopt->useproxy != -1
+ 			&& gUseBastionAppProxy != -1
+ 			&& (gUseBastionAppProxy==2
+ 			    || (gUseBastionAppProxy==1
+ 				&& !LocalDomain(openopt->hostname, gLocalDomains))))) {
+ 			if (gBastionPort) {
+ 				hErr = OpenControlConnection(gBastionName, gBastionPort);
+ 			} else {
+ 				hErr = OpenControlConnection(gBastionName, BH_PORT_DEF);
+ 			}
+ 		}
+ 		else {
+ 			hErr = OpenControlConnection(openopt->hostname, openopt->port);
+ 		}
+ #else
  		hErr = OpenControlConnection(openopt->hostname, openopt->port);
+ #endif
  		if (hErr == kConnectErrFatal) {
  			/* Irrecoverable error, so don't bother redialing.
  			 * The error message should have already been printed
***************
*** 826,832 ****
--- 959,969 ----
  			/* This updates the status bar (for visual mode). */
  			SetBar(NULL, "LOGGING IN", NULL, 1, 1);
  			SetPostHangupOnServerProc(PostCloseStuff);
+ #if defined(USE_BASTION_APP_PROXY)
+ 			loginResult = Login(user, pass, r_acct, openopt->hostname, openopt->port);
+ #else
  			loginResult = Login(user, pass, r_acct);
+ #endif
  			
  			if (loginResult == 0) {
  				PostLoginStuff(openopt);
diff -c ../ncftp-2.4.0/Open.h ./Open.h
*** ../ncftp-2.4.0/Open.h	Sun Nov 26 01:06:24 1995
--- ./Open.h	Thu Oct 17 21:12:57 1996
***************
*** 21,26 ****
--- 21,27 ----
  	char			colonModePath[256];
  	int				interactiveColonMode;
  	GetOptions		gopt;
+ 	int				useproxy;
  } OpenOptions;
  
  /* Open modes. */
***************
*** 43,49 ****
--- 44,54 ----
  
  /* Protos: */
  int LoginQuestion(char *, char *, size_t, char *, int);
+ #if defined(USE_BASTION_APP_PROXY)
+ int Login(char *, char *, char *, char *, int);
+ #else
  int Login(char *, char *, char *);
+ #endif
  void PostCloseStuff(void);
  void DoClose(int);
  int CloseCmd(int, char **);
diff -c ../ncftp-2.4.0/ncftp.1 ./ncftp.1
*** ../ncftp-2.4.0/ncftp.1	Wed Oct 16 21:11:08 1996
--- ./ncftp.1	Thu Oct 17 21:36:59 1996
***************
*** 1,4 ****
! .\"-------
  .\" Man page portability notes
  .\"
  .\" These are some notes on conventions to maintain for greatest
--- 1,4 ----
! 				 .\"-------
  .\" Man page portability notes
  .\"
  .\" These are some notes on conventions to maintain for greatest
***************
*** 75,86 ****
--- 75,90 ----
  .\"-------
  .PP
  Program options:
+   -S   : Always connect locally, unless overridden by open -b
+   -B   : Always connect via the proxy, unless overridden by open -s
    -D   : Turn debug mode and trace mode on.
    -L   : Don't use visual mode (use line mode).
    -V   : Use visual mode.
    -H   : Dump the version information.
  .PP
  Command-line open options:
+   -s   : Connect directly, ignoring the local domain matching.
+   -b   : Connect via the proxy, ignoring the local domain matching.
    -a   : Open anonymously.
    -u   : Open with username and password prompt.
    -p X : Use port number X when opening.
***************
*** 1618,1623 ****
--- 1622,1669 ----
  .PP
  This tries redialing that host every two minutes, and fetching all files
  from the ``/pub/stuff'' directory that are 3 days old or newer.
+ .\"-------
+ .SH "ENVIRONMENT VARIABLES"
+ .\"-------
+ .I NcFTP
+ will use the proxy host listed in
+ .I INTERNET_HOST,
+ or will default to the compiled-in option (firewall.lehman.com).
+ .PP
+ .I NcFTP
+ will connect to the proxy port listed in
+ .I INTERNET_FTP_PORT.
+ If
+ .I INTERNET_FTP_PORT
+ is not set,
+ .I NcFTP
+ will fall back to the port for the service ftp-passthru/tcp. If there is no
+ entry for the service ftp-passthru/tcp,
+ .I NcFTP
+ will use a default of 21.
+ .PP
+ .I NcFTP
+ will match all hosts against those listed in
+ .I LOCAL_DOMAINS.
+ If the IP address or domain matches, it will try and connect locally (or
+ remotely if the rule is negated). Otherwise, it will try to use the bastion
+ host defined by
+ .I INTERNET_HOST.
+ This behaviour is overridden by the -S and -B program options, and by the -s
+ and -b options to open.
+ .PP
+ The format of
+ .I LOCAL_DOMAINS
+ is a colon seperated list of IP address / netmask pairs (with the netmask
+ being optional and defaulting to 255.255.255.255), and domain names with a
+ leading period. Any entry beginning with an exclamation point is treated as
+ a non-local domain (entries are matched left to right, returning on the
+ first match). For example:
+ .Ds
+ csh> setenv LOCAL_DOMAIN "!.firewall.lehman.com:.lehman.com:146.127.0.0/255.255.0.0:198.242.89.1"
+ .De
+ would match the 146.127 network, the host 198.242.89.1, and any host whose
+ name ends in .lehman.com, except for those whose names ended in .firewall.lehman.com.
  .\"-------
  .SH "AUTHOR"
  .\"-------

Indexed By Date Previous: Re: CERN httpd and MS IE3: memory hog
From: Robert Olsson <robban @ bigfoot . com>
Next: port 113
From: jconnary @ shepards . com
Indexed By Thread Previous: Re: Web Site Blocking
From: robw @ marineterminals . com (Robert Williams)
Next: port 113
From: jconnary @ shepards . com

Google
 
Search Internet Search www.greatcircle.com