From 209804912e8e3cd49e6fa9d510f699cd9137d299 Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Mon, 9 Jul 2012 23:02:55 -0400 Subject: [PATCH] support for passive mode --- bin/ftp/cmds.c | 75 ++++++++++++++++++++++---------- bin/ftp/cmds.h | 2 + bin/ftp/cmdtab.c | 22 ++++++---- bin/ftp/ftp.c | 66 ++++++++++++++++++++++++++++ bin/ftp/{ftp_var.c => ftp.var.c} | 1 + bin/ftp/ftp.var.h | 1 + bin/ftp/main.c | 2 + 7 files changed, 137 insertions(+), 32 deletions(-) rename bin/ftp/{ftp_var.c => ftp.var.c} (98%) diff --git a/bin/ftp/cmds.c b/bin/ftp/cmds.c index 988e267..2bea1e1 100644 --- a/bin/ftp/cmds.c +++ b/bin/ftp/cmds.c @@ -46,6 +46,29 @@ extern char reply_string[]; char *mname; jmp_buf jabort; + +/* + * Toggle a variable + */ +int togglevar(int argc, char ** argv, int *var, const char *mesg) +{ + if (argc < 2) { + *var = !*var; + } else if (argc == 2 && strcasecmp(argv[1], "on") == 0) { + *var = 1; + } else if (argc == 2 && strcasecmp(argv[1], "off") == 0) { + *var = 0; + } else { + printf("usage: %s [ on | off ]\n", argv[0]); + return (-1); + } + if (mesg) + printf("%s %s.\n", mesg, onoff(*var)); + return (*var); +} + + + /* * `Another' gets another argument, and stores the new argc and argv. * It reverts to the top level (via main.c's intr()) on EOF/error. @@ -830,9 +853,7 @@ int i; /*VARARGS*/ void setbell (int argc, char **argv) { - bell = !bell; - printf("Bell mode %s.\n", onoff(bell)); - code = bell; + code = togglevar(argc, argv, &bell, "Bell mode"); } /* @@ -841,9 +862,7 @@ void setbell (int argc, char **argv) /*VARARGS*/ void settrace (int argc, char **argv) { - trace = !trace; - printf("Packet tracing %s.\n", onoff(trace)); - code = trace; + code = togglevar(argc, argv, &trace, "Packet tracing"); } /* @@ -866,9 +885,7 @@ void sethash (int argc, char **argv) /*VARARGS*/ void setverbose (int argc, char **argv) { - verbose = !verbose; - printf("Verbose mode %s.\n", onoff(verbose)); - code = verbose; + code = togglevar(argc, argv, &verbose, "Verbose mode"); } /* @@ -877,9 +894,7 @@ void setverbose (int argc, char **argv) /*VARARGS*/ void setport (int argc, char **argv) { - sendport = !sendport; - printf("Use of PORT cmds %s.\n", onoff(sendport)); - code = sendport; + code = togglevar(argc, argv, &sendport, "Use of PORT cmds"); } /* @@ -889,9 +904,7 @@ void setport (int argc, char **argv) /*VARARGS*/ void setprompt (int argc, char **argv) { - interactive = !interactive; - printf("Interactive mode %s.\n", onoff(interactive)); - code = interactive; + code = togglevar(argc, argv, &interactive, "Interactive mode"); } /* @@ -901,9 +914,7 @@ void setprompt (int argc, char **argv) /*VARARGS*/ void setglob (int argc, char **argv) { - doglob = !doglob; - printf("Globbing %s.\n", onoff(doglob)); - code = doglob; + code = togglevar(argc, argv, &doglob, "Globbing"); } /* @@ -979,6 +990,19 @@ static char buf[MAXPATHLEN]; code = 0; } +void lpwd(int argc, char **argv) +{ + static char buf[MAXPATHLEN]; + + if (getcwd(buf, sizeof(buf)) != NULL) + printf("Local directory %s\n", buf); + else + fprintf(stderr, "getcwd: %s\n", strerror(errno)); + code = 0; +} + + + /* * Delete a single file. */ @@ -1844,18 +1868,21 @@ LOOP: return(new); } + +void setpassive(int argc, char **argv) +{ + code = togglevar(argc, argv, &passivemode, + verbose ? "Passive mode" : (char *)NULL); +} + void setsunique (int argc, char **argv) { - sunique = !sunique; - printf("Store unique %s.\n", onoff(sunique)); - code = sunique; + code = togglevar(argc, argv, &sunique, "Store unique"); } void setrunique (int argc, char **argv) { - runique = !runique; - printf("Receive unique %s.\n", onoff(runique)); - code = runique; + code = togglevar(argc, argv, &runique, "Receive unique"); } /* change directory to perent directory */ diff --git a/bin/ftp/cmds.h b/bin/ftp/cmds.h index 72101ac..118c9a8 100644 --- a/bin/ftp/cmds.h +++ b/bin/ftp/cmds.h @@ -10,6 +10,7 @@ void setbell (int argc, char **argv); void settrace (int argc, char **argv); void sethash (int argc, char **argv); void setverbose (int argc, char **argv); +void setpassive (int argc, char **argv); void setport (int argc, char **argv); void setprompt (int argc, char **argv); void setglob (int argc, char **argv); @@ -45,6 +46,7 @@ void mget (int argc, char **argv); void status (int argc, char **argv); void cd (int argc, char **argv); void lcd (int argc, char **argv); +void lpwd (int argc, char **argv); void delete (int argc, char **argv); void mdelete (int argc, char **argv); void renamefile (int argc, char **argv); diff --git a/bin/ftp/cmdtab.c b/bin/ftp/cmdtab.c index 9f32813..996d98d 100644 --- a/bin/ftp/cmdtab.c +++ b/bin/ftp/cmdtab.c @@ -34,6 +34,7 @@ char hashhelp[] = "toggle printing `#' for each buffer transferred"; char helphelp[] = "print local help information"; char idlehelp[] = "get (set) idle timer on remote side"; char lcdhelp[] = "change local working directory"; +char lpwdhelp[] = "print local working directory"; char lshelp[] = "list contents of remote directory"; char macdefhelp[] = "define a macro"; char mdeletehelp[] = "delete multiple files"; @@ -48,6 +49,7 @@ char newerhelp[] = "get file if remote file is newer than local file "; char nlisthelp[] = "nlist contents of remote directory"; char nmaphelp[] = "set templates for default file name mapping"; char ntranshelp[] = "set translation table for default file name mapping"; +char passivehelp[] = "enter passive transfer mode"; char porthelp[] = "toggle use of PORT cmd for each data connection"; char prompthelp[] = "force interactive prompting on multiple commands"; char proxyhelp[] = "issue command on alternate connection"; @@ -64,7 +66,9 @@ char rmtstatushelp[]="show status of remote machine"; char runiquehelp[] = "toggle store unique for local files"; char resethelp[] = "clear queued command replies"; char sendhelp[] = "send one file"; -char sitehelp[] = "send site specific command to remote server\n\t\tTry \"rhelp site\" or \"site help\" for more information"; +char sitehelp[] = "send site specific command to remote server\n" + "\t\tTry \"rhelp site\" or \"site help\" " + "for more information"; char shellhelp[] = "escape to the shell"; char sizecmdhelp[] = "show size of remote file"; char statushelp[] = "show current status"; @@ -93,8 +97,8 @@ struct cmd cmdtab[] = { { "chmod", chmodhelp, 0, 1, 1, do_chmod }, { "close", disconhelp, 0, 1, 1, disconnect }, { "cr", crhelp, 0, 0, 0, setcr }, - { "delete", deletehelp, 0, 1, 1, delete }, { "debug", debughelp, 0, 0, 0, ftpsetdebug }, + { "delete", deletehelp, 0, 1, 1, delete }, { "dir", dirhelp, 1, 1, 1, ls }, { "disconnect", disconhelp, 0, 1, 1, disconnect }, { "form", formhelp, 0, 1, 1, setform }, @@ -105,6 +109,7 @@ struct cmd cmdtab[] = { { "idle", idlehelp, 0, 1, 1, idle }, { "image", binaryhelp, 0, 1, 1, setbinary }, { "lcd", lcdhelp, 0, 0, 0, lcd }, + { "lpwd", lpwdhelp, 0, 0, 0, lpwd }, { "ls", lshelp, 1, 1, 1, ls }, { "macdef", macdefhelp, 0, 0, 0, macdef }, { "mdelete", mdeletehelp, 1, 1, 1, mdelete }, @@ -116,38 +121,39 @@ struct cmd cmdtab[] = { { "modtime", modtimehelp, 0, 1, 1, modtime }, { "mput", mputhelp, 1, 1, 1, mput }, { "newer", newerhelp, 1, 1, 1, newer }, - { "nmap", nmaphelp, 0, 0, 1, setnmap }, { "nlist", nlisthelp, 1, 1, 1, ls }, + { "nmap", nmaphelp, 0, 0, 1, setnmap }, { "ntrans", ntranshelp, 0, 0, 1, setntrans }, { "open", connecthelp, 0, 0, 1, setpeer }, + { "passive", passivehelp, 0, 0, 0, setpassive }, { "prompt", prompthelp, 0, 0, 0, setprompt }, { "proxy", proxyhelp, 0, 0, 1, doproxy }, - { "sendport", porthelp, 0, 0, 0, setport }, { "put", sendhelp, 1, 1, 1, put }, { "pwd", pwdhelp, 0, 1, 1, pwd }, { "quit", quithelp, 0, 0, 0, quit }, { "quote", quotehelp, 1, 1, 1, quote }, { "recv", receivehelp, 1, 1, 1, get }, { "reget", regethelp, 1, 1, 1, reget }, - { "rstatus", rmtstatushelp, 0, 1, 1, rmtstatus }, - { "rhelp", remotehelp, 0, 1, 1, rmthelp }, { "rename", renamehelp, 0, 1, 1, renamefile }, { "reset", resethelp, 0, 1, 1, reset }, { "restart", restarthelp, 1, 1, 1, restart }, + { "rhelp", remotehelp, 0, 1, 1, rmthelp }, { "rmdir", rmdirhelp, 0, 1, 1, removedir }, + { "rstatus", rmtstatushelp, 0, 1, 1, rmtstatus }, { "runique", runiquehelp, 0, 0, 1, setrunique }, { "send", sendhelp, 1, 1, 1, put }, + { "sendport", porthelp, 0, 0, 0, setport }, { "site", sitehelp, 0, 1, 1, site }, { "size", sizecmdhelp, 1, 1, 1, sizecmd }, { "status", statushelp, 0, 0, 1, status }, { "struct", structhelp, 0, 1, 1, setstruct }, - { "system", systemhelp, 0, 1, 1, syst }, { "sunique", suniquehelp, 0, 0, 1, setsunique }, + { "system", systemhelp, 0, 1, 1, syst }, { "tenex", tenexhelp, 0, 1, 1, settenex }, { "trace", tracehelp, 0, 0, 0, settrace }, { "type", typehelp, 0, 1, 1, settype }, - { "user", userhelp, 0, 1, 1, user }, { "umask", umaskhelp, 0, 1, 1, do_umask }, + { "user", userhelp, 0, 1, 1, user }, { "verbose", verbosehelp, 0, 0, 0, setverbose }, { "?", helphelp, 0, 0, 1, help }, { 0 }, diff --git a/bin/ftp/ftp.c b/bin/ftp/ftp.c index 242f167..0a44ddb 100644 --- a/bin/ftp/ftp.c +++ b/bin/ftp/ftp.c @@ -1,5 +1,6 @@ #ifdef __ORCAC__ segment "ftpftp1 "; +#pragma noroot #endif static char sccsid[] = "@(#)ftp.c 5.38 (Berkeley) 4/22/91"; @@ -974,6 +975,67 @@ int initconn (void) unsigned char *p, *a; int result, len, tmpno = 0; int on = 1; +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; + #ifdef __GNO__ + // s_addr is a 32-bit value which overflows the + // int shift. + 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; + #else + data_addr.sin_addr.s_addr = htonl((a1 << 24) | (a2 << 16) | + (a3 << 8) | a4); + #endif + data_addr.sin_port = htons((p1 << 8) | p2); + + if (connect(data, (struct __SOCKADDR *) &data_addr, sizeof(data_addr)) < 0) { + perror("ftp: connect"); + return(1); + } + + #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT) + on = IPTOS_THROUGHPUT; + if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, + sizeof(int)) < 0) + perror("ftp: setsockopt TOS (ignored)"); + #endif + return(0); + } + + noport: data_addr = myctladdr; @@ -1042,6 +1104,10 @@ FILE *dataconn (char *lmode) struct sockaddr_in from; int s, fromlen = sizeof (from), tos; + + if (passivemode) + return (fdopen(data, lmode)); + s = accept(data, (struct __SOCKADDR *) &from, &fromlen); if (s < 0) { perror("ftp: accept"); diff --git a/bin/ftp/ftp_var.c b/bin/ftp/ftp.var.c similarity index 98% rename from bin/ftp/ftp_var.c rename to bin/ftp/ftp.var.c index 2c0002e..eb891d3 100644 --- a/bin/ftp/ftp_var.c +++ b/bin/ftp/ftp.var.c @@ -30,6 +30,7 @@ int mapflag; /* use mapin mapout templates on file names */ 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 */ +int passivemode; /* passive mode enabled */ char *altarg; /* argv[1] with no shell-like preprocessing */ char ntin[17]; /* input translation table */ char ntout[17]; /* output translation table */ diff --git a/bin/ftp/ftp.var.h b/bin/ftp/ftp.var.h index 957a2a9..15f0dc9 100644 --- a/bin/ftp/ftp.var.h +++ b/bin/ftp/ftp.var.h @@ -61,6 +61,7 @@ extern int mapflag; /* use mapin mapout templates on file names */ extern int code; /* return/reply code for ftp command */ extern int crflag; /* if 1, strip car. rets. on ascii gets */ extern char pasv[64]; /* passive port for proxy data connection */ +extern int passivemode; /* passive mode enabled */ extern char *altarg; /* argv[1] with no shell-like preprocessing */ extern char ntin[17]; /* input translation table */ extern char ntout[17]; /* output translation table */ diff --git a/bin/ftp/main.c b/bin/ftp/main.c index 1a68ebc..26b9698 100644 --- a/bin/ftp/main.c +++ b/bin/ftp/main.c @@ -53,6 +53,8 @@ static char homedir[MAXPATHLEN]; doglob = 1; interactive = 1; autologin = 1; + passivemode = 1; + argc--, argv++; while (argc > 0 && **argv == '-') { for (cp = *argv + 1; *cp; cp++)