Index: contrib/lukemftpd/src/ftpcmd.y =================================================================== --- contrib/lukemftpd/src/ftpcmd.y (revision 186403) +++ contrib/lukemftpd/src/ftpcmd.y (working copy) @@ -1363,8 +1363,12 @@ /* * getline - a hacked up version of fgets to ignore TELNET escape codes. + * `s' is the buffer to read into. + * `n' is the 1 less than the size of the buffer, to allow trailing NUL + * `iop' is the FILE to read from. + * Returns 0 on success, -1 on EOF, -2 if the command was too long. */ -char * +int getline(char *s, int n, FILE *iop) { int c; @@ -1379,7 +1383,7 @@ if (ftpd_debug) syslog(LOG_DEBUG, "command: %s", s); tmpline[0] = '\0'; - return(s); + return(0); } if (c == 0) tmpline[0] = '\0'; @@ -1418,11 +1422,25 @@ } } *cs++ = c; - if (--n <= 0 || c == '\n') + if (--n <= 0) { + /* + * If command doesn't fit into buffer, discard the + * rest of the command and indicate truncation. + * This prevents the command to be split up into + * multiple commands. + */ + if (ftpd_debug) + syslog(LOG_DEBUG, + "command too long, last char: %d", c); + while (c != '\n' && (c = getc(iop)) != EOF) + continue; + return (-2); + } + if (c == '\n') break; } if (c == EOF && cs == s) - return (NULL); + return (-1); *cs++ = '\0'; if (ftpd_debug) { if ((curclass.type != CLASS_GUEST && @@ -1444,7 +1462,7 @@ syslog(LOG_DEBUG, "command: %.*s", len, s); } } - return (s); + return (0); } void @@ -1458,15 +1476,20 @@ void ftp_loop(void) { + int ret; while (1) { (void) alarm(curclass.timeout); - if (getline(cbuf, sizeof(cbuf)-1, stdin) == NULL) { + ret = getline(cbuf, sizeof(cbuf)-1, stdin); + (void) alarm(0); + if (ret == -1) { reply(221, "You could at least say goodbye."); dologout(0); + } else if (ret == -2) { + reply(500, "Command too long."); + } else { + ftp_handle_line(cbuf); } - (void) alarm(0); - ftp_handle_line(cbuf); } /*NOTREACHED*/ } Index: contrib/lukemftpd/src/extern.h =================================================================== --- contrib/lukemftpd/src/extern.h (revision 186403) +++ contrib/lukemftpd/src/extern.h (working copy) @@ -139,7 +139,7 @@ void format_path(char *, const char *); int ftpd_pclose(FILE *); FILE *ftpd_popen(char *[], const char *, int); -char *getline(char *, int, FILE *); +int getline(char *, int, FILE *); void init_curclass(void); void logxfer(const char *, off_t, const char *, const char *, const struct timeval *, const char *); Index: contrib/lukemftpd/src/ftpd.c =================================================================== --- contrib/lukemftpd/src/ftpd.c (revision 186403) +++ contrib/lukemftpd/src/ftpd.c (working copy) @@ -1,4 +1,4 @@ -/* $NetBSD: ftpd.c,v 1.176 2006/05/09 20:18:06 mrg Exp $ */ +/* $NetBSD: ftpd.c,v 1.187 2008/09/13 03:30:35 lukem Exp $ */ /* * Copyright (c) 1997-2004 The NetBSD Foundation, Inc. @@ -2896,6 +2896,7 @@ handleoobcmd() { char *cp; + int ret; if (!urgflag) return (0); @@ -2904,9 +2905,14 @@ if (!transflag) return (0); cp = tmpline; - if (getline(cp, sizeof(tmpline), stdin) == NULL) { + ret = getline(cp, sizeof(tmpline)-1, stdin); + if (ret == -1) { reply(221, "You could at least say goodbye."); dologout(0); + } else if (ret == -2) { + /* Ignore truncated command */ + /* XXX: abort xfer with "500 command too long", & return 1 ? */ + return 0; } /* * Manually parse OOB commands, because we can't