diff --git a/libexec/ftpd/Makefile b/libexec/ftpd/Makefile index a3065e72793f..0780113196d1 100644 --- a/libexec/ftpd/Makefile +++ b/libexec/ftpd/Makefile @@ -4,7 +4,7 @@ PROG= ftpd MAN8= ftpd.8 SRCS= ftpd.c ftpcmd.c logwtmp.c popen.c skey-stuff.c -CFLAGS+=-DSETPROCTITLE -DSKEY -DSTATS +CFLAGS+=-DSETPROCTITLE -DSKEY -DSTATS -DPARANOID LDADD= -lskey -lmd -lcrypt -lutil DPADD= ${LIBSKEY} ${LIBMD} ${LIBCRYPT} ${LIBUTIL} diff --git a/libexec/ftpd/extern.h b/libexec/ftpd/extern.h index fe784c89f25f..9805cabc5013 100644 --- a/libexec/ftpd/extern.h +++ b/libexec/ftpd/extern.h @@ -65,3 +65,7 @@ void store __P((char *, char *, int)); void upper __P((char *)); void user __P((char *)); void yyerror __P((char *)); +int yyparse __P((void)); +#if defined(SKEY) && defined(_PWD_H_) /* XXX evil */ +char *skey_challenge __P((char *, struct passwd *, int)); +#endif diff --git a/libexec/ftpd/ftpcmd.y b/libexec/ftpd/ftpcmd.y index 4473b154df46..aa0a67d76179 100644 --- a/libexec/ftpd/ftpcmd.y +++ b/libexec/ftpd/ftpcmd.y @@ -67,7 +67,7 @@ static char sccsid[] = "@(#)ftpcmd.y 8.3 (Berkeley) 4/6/94"; #include "extern.h" -extern struct sockaddr_in data_dest; +extern struct sockaddr_in data_dest, his_addr; extern int logged_in; extern struct passwd *pw; extern int guest; @@ -149,18 +149,35 @@ cmd pass($3); free($3); } - | PORT SP host_port CRLF + | PORT check_login SP host_port CRLF { - usedefault = 0; - if (pdata >= 0) { - (void) close(pdata); - pdata = -1; + if ($2) { +#ifdef PARANOID + if ((ntohs(data_dest.sin_port) < + IPPORT_RESERVED) || + memcmp(&data_dest.sin_addr, + &his_addr.sin_addr, + sizeof(data_dest.sin_addr))) + { + usedefault = 1; + reply(500, + "Illegal PORT range rejected."); + } else +#endif + { + usedefault = 0; + if (pdata >= 0) { + (void) close(pdata); + pdata = -1; + } + reply(200, "PORT command successful."); + } } - reply(200, "PORT command successful."); } - | PASV CRLF + | PASV check_login CRLF { - passive(); + if ($2) + passive(); } | TYPE SP type_code CRLF { @@ -292,16 +309,18 @@ cmd if ($4 != NULL) free($4); } - | RNTO SP pathname CRLF + | RNTO check_login SP pathname CRLF { - if (fromname) { - renamecmd(fromname, $3); - free(fromname); - fromname = (char *) 0; - } else { - reply(503, "Bad sequence of commands."); + if ($2) { + if (fromname) { + renamecmd(fromname, $4); + free(fromname); + fromname = (char *) 0; + } else { + reply(503, "Bad sequence of commands."); + } } - free($3); + free($4); } | ABOR CRLF { diff --git a/libexec/ftpd/ftpd.c b/libexec/ftpd/ftpd.c index e91c51354ebd..cb4b12536d2c 100644 --- a/libexec/ftpd/ftpd.c +++ b/libexec/ftpd/ftpd.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ftpd.c,v 1.16 1996/04/11 10:22:16 davidg Exp $ + * $Id: ftpd.c,v 1.17 1996/05/31 03:10:25 peter Exp $ */ #ifndef lint @@ -202,6 +202,9 @@ static struct passwd * sgetpwnam __P((char *)); static char *sgetsave __P((char *)); static void reapchild __P((int)); +#ifdef STATS +static void logxfer __P((char *, long, long)); +#endif static char * curdir() @@ -380,7 +383,7 @@ main(argc, argv, envp) syslog(LOG_ERR, "signal: %m"); #ifdef SKEY - strcpy(addr_string, inet_ntoa(his_addr.sin_addr)); + strncpy(addr_string, inet_ntoa(his_addr.sin_addr), sizeof(addr_string)); #endif addrlen = sizeof(ctrl_addr); if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) { @@ -739,7 +742,10 @@ pass(passwd) if (ident != NULL) free(ident); - ident = (char *) copy(passwd); + ident = strdup(passwd); + if (ident == NULL) + fatal("Ran out of memory."); + #endif reply(230, "Guest login ok, access restrictions apply."); #ifdef SETPROCTITLE @@ -836,7 +842,7 @@ retrieve(cmd, name) restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode)); #ifdef STATS if (cmd == 0 && guest && stats) - logxfer( name, st.st_size, start); + logxfer(name, st.st_size, start); #endif (void) fclose(dout); data = -1; @@ -856,7 +862,7 @@ store(name, mode, unique) struct stat st; int (*closefunc) __P((FILE *)); - if (unique && stat(name, &st) == 0 && + if ((unique || guest) && stat(name, &st) == 0 && (name = gunique(name)) == NULL) { LOGCMD(*mode == 'w' ? "put" : "append", name); return; @@ -1181,7 +1187,7 @@ receive_data(instr, outstr) FILE *instr, *outstr; { int c; - int cnt, bare_lfs = 0; + int cnt, bare_lfs; char buf[BUFSIZ]; transflag++; @@ -1189,6 +1195,9 @@ receive_data(instr, outstr) transflag = 0; return (-1); } + + bare_lfs = 0; + switch (type) { case TYPE_I: @@ -1521,8 +1530,15 @@ void renamecmd(from, to) char *from, *to; { + struct stat st; LOGCMD2("rename", from, to); + + if (guest && (stat(to, &st) == 0)) { + reply(550, "%s: permission denied", to); + return; + } + if (rename(from, to) < 0) perror_reply(550, "rename"); else @@ -1607,35 +1623,31 @@ void passive() { int len, on; - u_short port; char *p, *a; - if (pw == NULL) { - reply(530, "Please login with USER and PASS"); - return; - } + if (pdata >= 0) /* close old port if one set */ + close(pdata); + pdata = socket(AF_INET, SOCK_STREAM, 0); if (pdata < 0) { perror_reply(425, "Can't open passive connection"); return; } - on = restricted_data_ports ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT; (void) seteuid((uid_t)0); + + on = restricted_data_ports ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT; if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE, (char *)&on, sizeof(on)) < 0) { - (void) seteuid((uid_t)pw->pw_uid); goto pasv_error; } pasv_addr = ctrl_addr; pasv_addr.sin_port = 0; - (void) seteuid((uid_t)0); if (bind(pdata, (struct sockaddr *)&pasv_addr, - sizeof(pasv_addr)) < 0) { - (void) seteuid((uid_t)pw->pw_uid); + sizeof(pasv_addr)) < 0) goto pasv_error; - } + (void) seteuid((uid_t)pw->pw_uid); len = sizeof(pasv_addr); @@ -1653,6 +1665,7 @@ passive() return; pasv_error: + (void) seteuid((uid_t)pw->pw_uid); (void) close(pdata); pdata = -1; perror_reply(425, "Can't open passive connection"); @@ -1682,7 +1695,7 @@ gunique(local) } if (cp) *cp = '/'; - (void) strcpy(new, local); + (void) snprintf(new, sizeof(new), "%s", local); cp = new + strlen(new); *cp++ = '.'; for (count = 1; count < 100; count++) { @@ -1894,6 +1907,7 @@ setproctitle(fmt, va_alist) #endif /* OLD_SETPROCTITLE */ #ifdef STATS +static void logxfer(name, size, start) char *name; long size; @@ -1905,23 +1919,10 @@ logxfer(name, size, start) if (statfd >= 0 && getwd(path) != NULL) { time(&now); - sprintf(buf, "%.20s!%s!%s!%s/%s!%ld!%ld\n", + snprintf(buf, sizeof(buf), "%.20s!%s!%s!%s/%s!%ld!%ld\n", ctime(&now)+4, ident, remotehost, path, name, size, now - start + (now == start)); write(statfd, buf, strlen(buf)); } } - -char * -copy(s) - char *s; -{ - char *p; - - p = malloc((unsigned) strlen(s) + 1); - if (p == NULL) - fatal("Ran out of memory."); - (void) strcpy(p, s); - return (p); -} #endif