--- linux-ftpd-0.17.orig/ftpd/extern.h +++ linux-ftpd-0.17/ftpd/extern.h @@ -43,7 +43,7 @@ void fatal __P((const char *)); int ftpd_pclose __P((FILE *)); FILE *ftpd_popen __P((char *, const char *)); -char *ftpd_getline __P((char *, int, FILE *)); +int ftpd_getline __P((char *, int, FILE *)); void ftpdlogwtmp __P((const char *, const char *, const char *)); void lreply __P((int, const char *, ...)); void makedir __P((char *)); --- linux-ftpd-0.17.orig/ftpd/ftpcmd.y +++ linux-ftpd-0.17/ftpd/ftpcmd.y @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -100,7 +101,14 @@ char cbuf[512]; char *fromname; -struct tab; +struct tab { + const char *name; + short token; + short state; + short implemented; /* 1 if command is implemented */ + const char *help; +}; + static int yylex __P((void)); static void sizecmd __P((char *)); static void help __P((struct tab *, char *)); @@ -111,8 +119,9 @@ %} %union { - int i; - char *s; + intmax_t i; + char *s; + const char *cs; } %token @@ -312,12 +321,12 @@ | LIST check_login CRLF { if ($2) - retrieve("/bin/ls -lgA", ""); + retrieve("/bin/ls -lA", ""); } | LIST check_login SP pathname CRLF { if ($2 && $4 != NULL) - retrieve("/bin/ls -lgA %s", $4); + retrieve("/bin/ls -lA %s", $4); if ($4 != NULL) free($4); } @@ -595,9 +604,9 @@ { if ($2) { fromname = (char *) 0; - restart_point = $4; /* XXX $4 is only "int" */ - reply(350, "Restarting at %qd. %s", - (quad_t) restart_point, + restart_point = $4; + reply(350, "Restarting at %jd. %s", + (intmax_t) restart_point, "Send STORE or RETRIEVE to initiate transfer."); } } @@ -832,14 +841,6 @@ #define SITECMD 7 /* SITE command */ #define NSTR 8 /* Number followed by a string */ -struct tab { - const char *name; - short token; - short state; - short implemented; /* 1 if command is implemented */ - const char *help; -}; - struct tab cmdtab[] = { /* In order defined in RFC 765 */ { "USER", USER, STR1, 1, " username" }, { "PASS", PASS, ZSTR1, 1, " password" }, @@ -919,7 +920,7 @@ /* * getline - a hacked up version of fgets to ignore TELNET escape codes. */ -char * ftpd_getline(char *s, int n, FILE *iop) +int ftpd_getline(char *s, int n, FILE *iop) { int c; register char *cs; @@ -931,9 +932,9 @@ if (tmpline[c] == '\n') { *cs++ = '\0'; if (debug) - syslog(LOG_DEBUG, "command: %s", s); + syslog(LOG_FTP | LOG_DEBUG, "command: %s", s); tmpline[0] = '\0'; - return(s); + return(0); } if (c == 0) tmpline[0] = '\0'; @@ -964,16 +965,27 @@ } } *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. + */ + while (c != '\n' && (c = getc(iop)) != EOF) + ; + return (-2); + } + if (c == '\n') break; } if (c == EOF && cs == s) - return (NULL); + return (-1); *cs++ = '\0'; if (debug) { if (!guest && strncasecmp("pass ", s, 5) == 0) { /* Don't syslog passwords */ - syslog(LOG_DEBUG, "command: %.5s ???", s); + syslog(LOG_FTP | LOG_DEBUG, "command: %.5s ???", s); } else { register char *cp; register int len; @@ -985,10 +997,10 @@ --cp; --len; } - syslog(LOG_DEBUG, "command: %.*s", len, s); + syslog(LOG_FTP | LOG_DEBUG, "command: %.*s", len, s); } } - return (s); + return (0); } void toolong(int signo) @@ -998,7 +1010,7 @@ reply(421, "Timeout (%d seconds): closing control connection.", timeout); if (logging) - syslog(LOG_INFO, "User %s timed out after %d seconds", + syslog(LOG_FTP | LOG_INFO, "User %s timed out after %d seconds", (pw ? pw -> pw_name : "unknown"), timeout); dologout(1); } @@ -1017,9 +1029,14 @@ case CMD: (void) signal(SIGALRM, toolong); (void) alarm((unsigned) timeout); - if (ftpd_getline(cbuf, sizeof(cbuf)-1, stdin)==NULL) { - reply(221, "You could at least say goodbye."); - dologout(0); + n=ftpd_getline(cbuf, sizeof(cbuf)-1, stdin); + if (n == -1) { + reply(221, "You could at least say goodbye."); + dologout(0); + } else if (n == -2) { + reply(500, "Command too long."); + alarm(0); + continue; } (void) alarm(0); if ((cp = strchr(cbuf, '\r'))) { @@ -1052,7 +1069,7 @@ /* NOTREACHED */ } state = p->state; - yylval.s = (char *)p->name; /* XXX */ + yylval.cs = p->name; return (p->token); } break; @@ -1078,7 +1095,7 @@ /* NOTREACHED */ } state = p->state; - yylval.s = (char *) p->name; /* XXX */ + yylval.cs = p->name; return (p->token); } state = CMD; @@ -1143,7 +1160,7 @@ ; c = cbuf[cpos]; cbuf[cpos] = '\0'; - yylval.i = atoi(cp); + yylval.i = strtoimax(cp, 0, 10); cbuf[cpos] = c; state = STR1; return (NUMBER); @@ -1158,7 +1175,7 @@ ; c = cbuf[cpos]; cbuf[cpos] = '\0'; - yylval.i = atoi(cp); + yylval.i = strtoimax(cp, 0, 10); cbuf[cpos] = c; return (NUMBER); } @@ -1314,7 +1331,7 @@ if (stat(filename, &stbuf) < 0 || !S_ISREG(stbuf.st_mode)) reply(550, "%s: not a plain file.", filename); else - reply(213, "%qu", (quad_t) stbuf.st_size); + reply(213, "%ju", (uintmax_t) stbuf.st_size); break; } case TYPE_A: { FILE *fin; @@ -1340,7 +1357,7 @@ } (void) fclose(fin); - reply(213, "%qd", (quad_t) count); + reply(213, "%jd", (intmax_t) count); break; } default: reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]); --- linux-ftpd-0.17.orig/ftpd/ftpd.8 +++ linux-ftpd-0.17/ftpd/ftpd.8 @@ -46,7 +46,7 @@ Internet File Transfer Protocol server .Sh SYNOPSIS .Nm ftpd -.Op Fl AdDhlMPSU +.Op Fl AdDhlMnPSU .Op Fl T Ar maxtimeout .Op Fl t Ar timeout .Op Fl u Ar mask @@ -67,7 +67,9 @@ .It Fl A Permit only anonymous ftp connections or accounts listed in .Pa /etc/ftpchroot. -Other connection attempts are refused. +Other connection attempts are refused. This option is nolonger effective if +PAM is enabled. Please refer to the README file for instructions to doing +this with PAM. .It Fl d Debugging information is written to the syslog using LOG_FTP. .It Fl D @@ -103,12 +105,8 @@ the IP number the client connected to, and located inside .Pa ~ftp is used instead. -.It Fl p -Disable passive mode ftp connections. This is useful if you are behind -a firewall that refuses connections to arbitrary high numbered ports. -Many ftp clients try passive mode first and do not always react gracefully -to a server that refuses connections to the port it asked the client to -connect to. +.It Fl n +Use numeric IP addresses in logs instead of doing hostname lookup. .It Fl P Permit illegal port numbers or addresses for PORT command initiated connects. By default @@ -356,6 +354,29 @@ .Pa motd , if present, will be printed after a successful login. These files should be mode 444. +.It Pa ~ftp/lib +Make this directory owned by +.Dq root +and unwritable by anyone (mode 511). +The libraries +.Xr ld-linux.so.2 +and +.Xr libc.so.6 +(or whatever your +.Xr ls +command is linked to) +must be present. +In order to read +.Xr passwd 5 +and +.Xr group 5 , +the library +.Xr libnss_files.so.2 +is also needed. +Note that if you're using a 2.2.* or later Linux kernel, +.Xr ld-linux.so.2 +must be executable as well as readable (555). All other files should be mode +444. .It Pa ~ftp/pub Make this directory mode 555 and owned by .Dq root . --- linux-ftpd-0.17.orig/ftpd/ftpd.c +++ linux-ftpd-0.17/ftpd/ftpd.c @@ -80,6 +80,7 @@ #include #include #include +#include #include #include #include @@ -95,8 +96,6 @@ #else #include /* for initgroups() */ /* #include * for L_SET et al. * <--- not used? */ -/*typedef int64_t quad_t;*/ -typedef unsigned int useconds_t; #endif #include "../version.h" @@ -132,6 +131,16 @@ #include #endif +#ifdef USE_PAM +#include +#include +#include +/* backward compatibility hack for libpam < 0.58 */ +#ifndef PAM_ESTABLISH_CRED +#define PAM_ESTABLISH_CRED PAM_CRED_ESTABLISH +#endif +#endif + static char versionpre[] = "Version 6.4/OpenBSD/Linux"; static char version[sizeof(versionpre)+sizeof(pkg)]; @@ -156,7 +165,8 @@ #endif int debug = 0; int timeout = 900; /* timeout after 15 minutes of inactivity */ -int maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */ +int maxtimeout = 7200; /* don't allow idle time to be set beyond 2 hours */ +int numeric_hosts = 0; /* log numeric IP rather than doing lookup */ int logging; int high_data_ports = 0; int anon_only = 0; @@ -218,29 +228,37 @@ char proctitle[BUFSIZ]; /* initial part of title */ #endif /* HASSETPROCTITLE */ +#ifdef USE_PAM +static pam_handle_t *pamh; +static char *PAM_username; +static char *PAM_password; +static char *PAM_message; +static int PAM_accepted; +#endif + #define LOGCMD(cmd, file) \ if (logging > 1) \ - syslog(LOG_INFO,"%s %s%s", cmd, \ + syslog(LOG_FTP | LOG_INFO,"%s %s%s", cmd, \ *(file) == '/' ? "" : curdir(), file); #define LOGCMD2(cmd, file1, file2) \ if (logging > 1) \ - syslog(LOG_INFO,"%s %s%s %s%s", cmd, \ + syslog(LOG_FTP | LOG_INFO,"%s %s%s %s%s", cmd, \ *(file1) == '/' ? "" : curdir(), file1, \ *(file2) == '/' ? "" : curdir(), file2); #define LOGBYTES(cmd, file, cnt) \ if (logging > 1) { \ if (cnt == (off_t)-1) \ - syslog(LOG_INFO,"%s %s%s", cmd, \ + syslog(LOG_FTP | LOG_INFO,"%s %s%s", cmd, \ *(file) == '/' ? "" : curdir(), file); \ else \ - syslog(LOG_INFO, "%s %s%s = %qd bytes", cmd, \ - *(file) == '/' ? "" : curdir(), file, (quad_t)(cnt)); \ + syslog(LOG_FTP | LOG_INFO, "%s %s%s = %jd bytes", cmd, \ + *(file) == '/' ? "" : curdir(), file, (intmax_t)(cnt)); \ } static void ack __P((const char *)); static void myoob __P((int)); static int checkuser __P((const char *, const char *)); -static FILE *dataconn __P((const char *, off_t, const char *)); +static FILE *dataconn __P((const char *, off_t, const char *, int)); static void dolog __P((struct sockaddr_in *)); static const char *curdir __P((void)); static void end_login __P((void)); @@ -255,6 +273,7 @@ sgetpwnam __P((const char *)); static char *sgetsave __P((char *)); static void reapchild __P((int)); +static void authentication_setup(const char *); #if defined(TCPWRAPPERS) static int check_host __P((struct sockaddr_in *)); @@ -294,7 +313,7 @@ socklen_t addrlen; char *cp, line[LINE_MAX]; FILE *fd; - const char *argstr = "AdDhlMSt:T:u:UvP"; + const char *argstr = "AdDhlMnSt:T:u:UvP"; struct hostent *hp; #ifdef __linux__ @@ -354,6 +373,10 @@ multihome = 1; break; + case 'n': + numeric_hosts = 1; + break; + case 'S': stats = 1; break; @@ -415,7 +438,7 @@ * Detach from parent. */ if (daemon(1, 1) < 0) { - syslog(LOG_ERR, "failed to become a daemon"); + syslog(LOG_FTP | LOG_ERR, "failed to become a daemon"); exit(1); } (void) signal(SIGCHLD, reapchild); @@ -424,7 +447,8 @@ */ sv = getservbyname("ftp", "tcp"); if (sv == NULL) { - syslog(LOG_ERR, "getservbyname for ftp failed"); + syslog(LOG_FTP | LOG_ERR, + "getservbyname for ftp failed"); exit(1); } /* @@ -433,22 +457,22 @@ */ ctl_sock = socket(AF_INET, SOCK_STREAM, 0); if (ctl_sock < 0) { - syslog(LOG_ERR, "control socket: %m"); + syslog(LOG_FTP | LOG_ERR, "control socket: %m"); exit(1); } if (setsockopt(ctl_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) - syslog(LOG_ERR, "control setsockopt: %m");; + syslog(LOG_FTP | LOG_ERR, "control setsockopt: %m");; server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = sv->s_port; if (bind(ctl_sock, (struct sockaddr *)&server_addr, sizeof(server_addr))) { - syslog(LOG_ERR, "control bind: %m"); + syslog(LOG_FTP | LOG_ERR, "control bind: %m"); exit(1); } if (listen(ctl_sock, 32) < 0) { - syslog(LOG_ERR, "control listen: %m"); + syslog(LOG_FTP | LOG_ERR, "control listen: %m"); exit(1); } /* @@ -478,7 +502,8 @@ addrlen = sizeof(his_addr); if (getpeername(0, (struct sockaddr *)&his_addr, &addrlen) < 0) { - syslog(LOG_ERR, "getpeername (%s): %m", argv[0]); + syslog(LOG_FTP | LOG_ERR, "getpeername (%s): %m", + argv[0]); exit(1); } } @@ -490,29 +515,29 @@ (void) signal(SIGPIPE, lostconn); (void) signal(SIGCHLD, SIG_IGN); if (signal(SIGURG, myoob) == SIG_ERR) - syslog(LOG_ERR, "signal: %m"); + syslog(LOG_FTP | LOG_ERR, "signal: %m"); addrlen = sizeof(ctrl_addr); if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) { - syslog(LOG_ERR, "getsockname (%s): %m", argv[0]); + syslog(LOG_FTP | LOG_ERR, "getsockname (%s): %m", argv[0]); exit(1); } #ifdef IP_TOS tos = IPTOS_LOWDELAY; if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) - syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); + syslog(LOG_FTP | LOG_WARNING, "setsockopt (IP_TOS): %m"); #endif data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1); /* Try to handle urgent data inline */ #ifdef SO_OOBINLINE if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) < 0) - syslog(LOG_ERR, "setsockopt: %m"); + syslog(LOG_FTP | LOG_ERR, "setsockopt: %m"); #endif #ifdef F_SETOWN if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1) - syslog(LOG_ERR, "fcntl F_SETOWN: %m"); + syslog(LOG_FTP | LOG_ERR, "fcntl F_SETOWN: %m"); #endif dolog(&his_addr); /* @@ -583,13 +608,13 @@ (void)signo; if (debug) - syslog(LOG_DEBUG, "lost connection"); + syslog(LOG_FTP | LOG_DEBUG, "lost connection"); dologout(-1); } static void sigquit(int signo) { - syslog(LOG_ERR, "got signal %s", strsignal(signo)); + syslog(LOG_FTP | LOG_ERR, "got signal %s", strsignal(signo)); dologout(-1); } @@ -658,10 +683,15 @@ * requesting login privileges. Disallow anyone who does not have a standard * shell as returned by getusershell(). Disallow anyone mentioned in the file * _PATH_FTPUSERS to allow people such as root and uucp to be avoided. + * + * pw maybe unset if we're using PAM and the login turns out to be anonymous. + * -- herbert */ void user(char *name) { +#ifndef USE_PAM const char *cp, *shell; +#endif if (logged_in) { if (guest) { @@ -674,6 +704,9 @@ end_login(); } +#ifdef USE_PAM + authentication_setup(name); +#else guest = 0; if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) { if (checkuser(_PATH_FTPUSERS, "ftp") || @@ -687,7 +720,7 @@ } else reply(530, "User %s unknown.", name); if (!askpasswd && logging) - syslog(LOG_NOTICE, + syslog(LOG_FTP | LOG_NOTICE, "ANONYMOUS FTP LOGIN REFUSED FROM %s", remotehost); return; } @@ -707,17 +740,13 @@ if (cp == NULL || checkuser(_PATH_FTPUSERS, name)) { reply(530, "User %s access denied.", name); if (logging) - syslog(LOG_NOTICE, + syslog(LOG_FTP | LOG_NOTICE, "FTP LOGIN REFUSED FROM %s, %s", remotehost, name); pw = (struct passwd *) NULL; return; } } - if (logging) { - strncpy(curname, name, sizeof(curname)-1); - curname[sizeof(curname)-1] = '\0'; - } #ifdef SKEY if (!skey_haskey(name)) { char *myskey, *skey_keyinfo __P((char *name)); @@ -728,6 +757,11 @@ } else #endif reply(331, "Password required for %s.", name); +#endif + if (logging) { + strncpy(curname, name, sizeof(curname)-1); + curname[sizeof(curname)-1] = '\0'; + } askpasswd = 1; /* @@ -774,9 +808,19 @@ sigprocmask (SIG_BLOCK, &allsigs, NULL); (void) seteuid((uid_t)0); if (logged_in) { +#ifdef USE_PAM + int error; + error = pam_close_session(pamh, 0); + pam_end(pamh, error); + pamh = 0; +#endif ftpdlogwtmp(ttyline, "", ""); if (doutmp) logout(utmp.ut_line); +#if defined(KERBEROS) + if (!notickets && krbtkfile_env) + unlink(krbtkfile_env); +#endif } pw = NULL; logged_in = 0; @@ -784,9 +828,214 @@ dochroot = 0; } +#ifdef USE_PAM +/* + * PAM authentication, now using the PAM's async feature. + */ +static int PAM_conv (int num_msg, const struct pam_message **msg, + struct pam_response **resp, void *appdata_ptr) +{ + struct pam_response *repl = NULL; + int retval, count = 0, replies = 0; + int size = sizeof(struct pam_response); + +#define GET_MEM \ + if (!(repl = realloc(repl, size))) \ + return PAM_CONV_ERR; \ + size += sizeof(struct pam_response) +#define COPY_STRING(s) (s) ? strdup(s) : NULL + + (void) appdata_ptr; + retval = PAM_SUCCESS; + for (count = 0; count < num_msg; count++) { + int savemsg = 0; + + switch (msg[count]->msg_style) { + case PAM_PROMPT_ECHO_ON: + GET_MEM; + repl[replies].resp_retcode = PAM_SUCCESS; + repl[replies].resp = COPY_STRING(PAM_username); + replies++; + break; + case PAM_PROMPT_ECHO_OFF: + GET_MEM; + if (PAM_password == 0) { + savemsg = 1; + retval = PAM_CONV_AGAIN; + } else { + repl[replies].resp_retcode = PAM_SUCCESS; + repl[replies].resp = COPY_STRING(PAM_password); + replies++; + } + break; + case PAM_TEXT_INFO: + savemsg = 1; + break; + case PAM_ERROR_MSG: + default: + /* Must be an error of some sort... */ + retval = PAM_CONV_ERR; + } + + if (savemsg) { + char *sp; + + if (PAM_message) { + /* XXX: make sure we split newlines correctly */ + lreply(331, "%s", PAM_message); + free(PAM_message); + } + PAM_message = COPY_STRING(msg[count]->msg); + + /* Remove trailing `: ' */ + sp = PAM_message + strlen(PAM_message); + while (sp > PAM_message && strchr(" \t\n:", *--sp)) + *sp = '\0'; + } + + /* In case of error, drop responses and return */ + if (retval) { + _pam_drop_reply(repl, replies); + return retval; + } + } + if (repl) + *resp = repl; + return PAM_SUCCESS; +} + +static struct pam_conv PAM_conversation = { + &PAM_conv, + NULL +}; + +static int pam_doit(void) +{ + int error; + + error = pam_authenticate(pamh, 0); + if (error == PAM_CONV_AGAIN || error == PAM_INCOMPLETE) { + /* Avoid overly terse passwd messages */ + if (PAM_message && !strcasecmp(PAM_message, "password")) { + free(PAM_message); + PAM_message = 0; + } + if (PAM_message == 0) { + reply(331, "Password required for %s.", PAM_username); + } else { + reply(331, "%s", PAM_message); + free(PAM_message); + PAM_message = 0; + } + return 1; + } + if (error == PAM_SUCCESS) { + const void *vp; + + /* Alright, we got it */ + error = pam_acct_mgmt(pamh, 0); + if (error == PAM_SUCCESS) + error = pam_open_session(pamh, 0); + if (error == PAM_SUCCESS) + error = pam_setcred(pamh, PAM_ESTABLISH_CRED); + if (error == PAM_SUCCESS) + error = pam_get_item(pamh, PAM_USER, &vp); + if (error == PAM_SUCCESS) { + const char *user = vp; + + if (strcmp(user, "ftp") == 0) { + guest = 1; + } + pw = sgetpwnam(user); + } + if (error == PAM_SUCCESS && pw) + PAM_accepted = 1; + } + + return (error == PAM_SUCCESS); +} + + +static void authentication_setup(const char *username) +{ + int error; + + if (pamh != 0) { + pam_end(pamh, PAM_ABORT); + pamh = 0; + } + + if (PAM_username) + free(PAM_username); + PAM_username = strdup(username); + PAM_password = 0; + PAM_message = 0; + PAM_accepted = 0; + + error = pam_start("ftp", PAM_username, &PAM_conversation, &pamh); + if (error == PAM_SUCCESS) + error = pam_set_item(pamh, PAM_RHOST, remotehost); + if (error != PAM_SUCCESS) { + reply(550, "Authentication failure"); + pam_end(pamh, error); + pamh = 0; + } + + if (pamh && !pam_doit()) + reply(550, "Authentication failure"); +} + +static int authenticate(char *passwd) +{ + if (PAM_accepted) + return 1; + + if (pamh == 0) + return 0; + + PAM_password = passwd; + pam_doit(); + PAM_password = 0; + return PAM_accepted; +} + +#else /* !USE_PAM */ +static int authenticate(char *passwd) +{ + if (pw == NULL) { + useconds_t us; + + /* Sleep between 1 and 3 seconds to emulate a crypt. */ +#ifndef __linux__ + us = arc4random() % 3000000; +#else + us = random() % 3000000; +#endif + usleep(us); + return 0; + } + +#if defined(KERBEROS) + if (klogin(pw, "", hostname, passwd) == 0) + return 1; +#endif +#ifdef SKEY + if (skey_haskey(pw->pw_name) == 0 && + (skey_passcheck(pw->pw_name, passwd) != -1)) + return 1; +#endif + /* the strcmp does not catch null passwords! */ + if (pw == NULL || *pw->pw_passwd == '\0' || + strcmp(crypt(passwd, pw->pw_passwd), pw->pw_passwd)) + return 0; /* failure */ + + return 1; +} +#endif /* !USE_PAM */ + + void pass(char *passwd) { - int rval; FILE *fd; static char homedir[MAXPATHLEN]; char rootdir[MAXPATHLEN]; @@ -797,84 +1046,54 @@ return; } askpasswd = 0; +#ifndef USE_PAM if (!guest) { /* "ftp" is only account allowed no password */ - if (pw == NULL) { - useconds_t us; - - /* Sleep between 1 and 3 seconds to emulate a crypt. */ -#ifndef __linux__ - us = arc4random() % 3000000; -#else - us = random() % 3000000; -#endif - usleep(us); - rval = 1; /* failure below */ - goto skip; - } -#if defined(KERBEROS) - rval = klogin(pw, "", hostname, passwd); - if (rval == 0) - goto skip; -#endif -#ifdef SKEY - if (skey_haskey(pw->pw_name) == 0 && - (skey_passcheck(pw->pw_name, passwd) != -1)) { - rval = 0; - goto skip; - } #endif - /* the strcmp does not catch null passwords! */ - if (strcmp(crypt(passwd, pw->pw_passwd), pw->pw_passwd) || - *pw->pw_passwd == '\0') { - rval = 1; /* failure */ - goto skip; - } - rval = 0; - -skip: /* - * If rval == 1, the user failed the authentication check - * above. If rval == 0, either Kerberos or local authentication - * succeeded. + * Try to authenticate the user */ - if (rval) { + if (!authenticate(passwd)) { reply(530, "Login incorrect."); if (logging) - syslog(LOG_NOTICE, + syslog(LOG_FTP | LOG_NOTICE, "FTP LOGIN FAILED FROM %s, %s", remotehost, curname); pw = NULL; if (login_attempts++ >= 5) { - syslog(LOG_NOTICE, + syslog(LOG_FTP | LOG_NOTICE, "repeated login failures from %s", remotehost); exit(0); } return; } +#ifdef USE_PAM + if (guest) { +#else } else { +#endif /* Save anonymous' password. */ guestpw = strdup(passwd); if (guestpw == (char *)NULL) fatal("Out of memory"); } login_attempts = 0; /* this time successful */ -#ifdef USE_SHADOW +#if defined(USE_SHADOW) && !defined(USE_PAM) switch (isexpired(spw)) { case 0: /* success */ break; case 1: - syslog(LOG_NOTICE, "expired password from %s, %s", + syslog(LOG_FTP | LOG_NOTICE, "expired password from %s, %s", remotehost, pw->pw_name); reply(530, "Please change your password and try again."); return; case 2: - syslog(LOG_NOTICE, "inactive login from %s, %s", + syslog(LOG_FTP | LOG_NOTICE, "inactive login from %s, %s", remotehost, pw->pw_name); reply(530, "Login inactive -- contact administrator."); return; case 3: - syslog(LOG_NOTICE, "expired login from %s, %s", + syslog(LOG_FTP | LOG_NOTICE, "expired login from %s, %s", remotehost, pw->pw_name); reply(530, "Account expired -- contact administrator."); return; @@ -940,6 +1159,13 @@ } strcpy(pw->pw_dir, "/"); setenv("HOME", "/", 1); + } + /* PSz 25 Aug 06 chdir for real users done after setting UID */ + if (seteuid((uid_t)pw->pw_uid) < 0) { + reply(550, "Can't set uid."); + goto bad; + } + if (guest || dochroot) { /* do nothing, handled above */ } else if (chdir(pw->pw_dir) < 0) { if (chdir("/") < 0) { reply(530, "User %s: can't change directory to %s.", @@ -948,10 +1174,7 @@ } else lreply(230, "No directory! Logging in with home=/"); } - if (seteuid((uid_t)pw->pw_uid) < 0) { - reply(550, "Can't set uid."); - goto bad; - } + sigfillset(&allsigs); sigprocmask(SIG_UNBLOCK,&allsigs,NULL); @@ -991,7 +1214,8 @@ setproctitle("%s", proctitle); #endif /* HASSETPROCTITLE */ if (logging) - syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s", + syslog(LOG_FTP | LOG_INFO, + "ANONYMOUS FTP LOGIN FROM %s, %s", remotehost, passwd); } else { reply(230, "User %s logged in.", pw->pw_name); @@ -1001,7 +1225,7 @@ setproctitle("%s", proctitle); #endif /* HASSETPROCTITLE */ if (logging) - syslog(LOG_INFO, "FTP LOGIN FROM %s as %s", + syslog(LOG_FTP | LOG_INFO, "FTP LOGIN FROM %s as %s", remotehost, pw->pw_name); } (void) umask(defumask); @@ -1064,7 +1288,7 @@ goto done; } } - dout = dataconn(name, st.st_size, "w"); + dout = dataconn(name, st.st_size, "w", 0); if (dout == NULL) goto done; time(&start); @@ -1088,6 +1312,9 @@ struct stat st; int fd; + if (restart_point && *mode != 'a') + mode = "r+"; + if (unique && stat(name, &st) == 0) { char *nam; @@ -1097,8 +1324,6 @@ return; } name = nam; - if (restart_point) - mode = "r+"; fout = fdopen(fd, mode); } else fout = fopen(name, mode); @@ -1139,7 +1364,7 @@ goto done; } } - din = dataconn(name, (off_t)-1, "r"); + din = dataconn(name, (off_t)-1, "r", unique); if (din == NULL) goto done; if (receive_data(din, fout) == 0) { @@ -1187,14 +1412,15 @@ goto bad; sleep(tries); } - (void) seteuid((uid_t)pw->pw_uid); +/* PSz 25 Aug 06 Check return status */ + if (seteuid((uid_t)pw->pw_uid) != 0) _exit(1); sigfillset(&allsigs); sigprocmask (SIG_UNBLOCK, &allsigs, NULL); #ifdef IP_TOS on = IPTOS_THROUGHPUT; if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) - syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); + syslog(LOG_FTP | LOG_WARNING, "setsockopt (IP_TOS): %m"); #endif #ifdef TCP_NOPUSH /* @@ -1205,13 +1431,13 @@ */ on = 1; if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, (char *)&on, sizeof on) < 0) - syslog(LOG_WARNING, "setsockopt (TCP_NOPUSH): %m"); + syslog(LOG_FTP | LOG_WARNING, "setsockopt (TCP_NOPUSH): %m"); #endif #if 0 /* Respect the user's settings */ #ifdef SO_SNDBUF on = 65536; if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&on, sizeof on) < 0) - syslog(LOG_WARNING, "setsockopt (SO_SNDBUF): %m"); + syslog(LOG_FTP | LOG_WARNING, "setsockopt (SO_SNDBUF): %m"); #endif #endif @@ -1219,7 +1445,8 @@ bad: /* Return the real value of errno (close may change it) */ t = errno; - (void) seteuid((uid_t)pw->pw_uid); +/* PSz 25 Aug 06 Check return status */ + if (seteuid((uid_t)pw->pw_uid) != 0) _exit(1); sigfillset (&allsigs); sigprocmask (SIG_UNBLOCK, &allsigs, NULL); (void) close(s); @@ -1227,7 +1454,7 @@ return (NULL); } -static FILE * dataconn(const char *name, off_t size, const char *mode) +static FILE * dataconn(const char *name, off_t size, const char *mode, int stou) { char sizebuf[32]; FILE *file; @@ -1236,8 +1463,8 @@ file_size = size; byte_count = 0; if (size != (off_t) -1) { - (void) snprintf(sizebuf, sizeof(sizebuf), " (%lld bytes)", - (quad_t) size); + (void) snprintf(sizebuf, sizeof(sizebuf), " (%jd bytes)", + (intmax_t) size); } else sizebuf[0] = '\0'; if (pdata >= 0) { @@ -1262,6 +1489,7 @@ pdata = -1; return (NULL); } +#ifdef BREAKRFC if (from.sin_addr.s_addr != his_addr.sin_addr.s_addr) { perror_reply(435, "Can't build data connection"); (void) close(pdata); @@ -1269,6 +1497,7 @@ pdata = -1; return (NULL); } +#endif (void) close(pdata); pdata = s; #ifdef IP_TOS @@ -1276,13 +1505,24 @@ (void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)); #endif - reply(150, "Opening %s mode data connection for '%s'%s.", - type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); + if (stou) { + reply(150, "FILE: %s", name); + } else { + reply(150, + "Opening %s mode data connection for '%s'%s.", + type == TYPE_A ? "ASCII" : "BINARY", name, + sizebuf); + } return (fdopen(pdata, mode)); } if (data >= 0) { - reply(125, "Using existing data connection for '%s'%s.", - name, sizebuf); + if (stou) { + reply(125, "FILE: %s", name); + } else { + reply(125, + "Using existing data connection for '%s'%s.", + name, sizebuf); + } usedefault = 1; return (fdopen(data, mode)); } @@ -1309,12 +1549,14 @@ data = -1; return NULL; } +#ifdef BREAKRFC if (data_dest.sin_addr.s_addr != his_addr.sin_addr.s_addr) { perror_reply(435, "Can't build data connection"); (void) fclose(file); data = -1; return NULL; } +#endif while (connect(data, (struct sockaddr *)&data_dest, sizeof(data_dest)) < 0) { if (errno == EADDRINUSE && retry < swaitmax) { @@ -1327,8 +1569,14 @@ data = -1; return (NULL); } - reply(150, "Opening %s mode data connection for '%s'%s.", - type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); + if (stou) { + reply(150, "FILE: %s", name); + } else { + reply(150, + "Opening %s mode data connection for '%s'%s.", + type == TYPE_A ? "ASCII" : "BINARY", name, + sizebuf); + } return (file); } @@ -1383,7 +1631,7 @@ buf = mmap(0, filesize, PROT_READ, MAP_SHARED, filefd, (off_t)0); if (buf==MAP_FAILED || buf==NULL) { - syslog(LOG_WARNING, "mmap(%lu): %m", + syslog(LOG_FTP | LOG_WARNING, "mmap(%lu): %m", (unsigned long)filesize); goto oldway; } @@ -1552,7 +1800,7 @@ int c; char line[LINE_MAX]; - (void)snprintf(line, sizeof(line), "/bin/ls -lgA %s", filename); + (void)snprintf(line, sizeof(line), "/bin/ls -lA %s", filename); fin = ftpd_popen(line, "r"); lreply(211, "status of %s:", filename); while ((c = getc(fin)) != EOF) { @@ -1655,8 +1903,8 @@ (void)printf("\r\n"); (void)fflush(stdout); if (debug) { - syslog(LOG_DEBUG, "<--- %d ", n); - vsyslog(LOG_DEBUG, fmt, ap); + syslog(LOG_FTP | LOG_DEBUG, "<--- %d ", n); + vsyslog(LOG_FTP | LOG_DEBUG, fmt, ap); } } @@ -1681,8 +1929,8 @@ (void)printf("\r\n"); (void)fflush(stdout); if (debug) { - syslog(LOG_DEBUG, "<--- %d- ", n); - vsyslog(LOG_DEBUG, fmt, ap); + syslog(LOG_FTP | LOG_DEBUG, "<--- %d- ", n); + vsyslog(LOG_FTP | LOG_DEBUG, fmt, ap); } } @@ -1758,15 +2006,21 @@ void replydirname(const char *name, const char *message) { + char *p, *ep; char npath[MAXPATHLEN]; - int i; - for (i = 0; *name != '\0' && i < (int)sizeof(npath) - 1; i++, name++) { - npath[i] = *name; - if (*name == '"') - npath[++i] = '"'; + p = npath; + ep = &npath[sizeof(npath) - 1]; + while (*name) { + if (*name == '"' && ep - p >= 2) { + *p++ = *name++; + *p++ = '"'; + } else if (ep - p >= 1) + *p++ = *name++; + else + break; } - npath[i] = '\0'; + *p = '\0'; reply(257, "\"%s\" %s", npath, message); } @@ -1823,10 +2077,11 @@ static void dolog(struct sockaddr_in *sn) { - struct hostent *hp = gethostbyaddr((char *)&sn->sin_addr, - sizeof(struct in_addr), AF_INET); + struct hostent *hp; - if (hp) + if (!numeric_hosts && + (hp = gethostbyaddr((char *)&sn->sin_addr, + sizeof(struct in_addr), AF_INET))) (void) strncpy(remotehost, hp->h_name, sizeof(remotehost)-1); else (void) strncpy(remotehost, inet_ntoa(sn->sin_addr), @@ -1838,7 +2093,7 @@ #endif /* HASSETPROCTITLE */ if (logging) - syslog(LOG_INFO, "connection from %s", remotehost); + syslog(LOG_FTP | LOG_INFO, "connection from %s", remotehost); } /* @@ -1847,22 +2102,8 @@ */ void dologout(int status) { - sigset_t allsigs; - transflag = 0; - - if (logged_in) { - sigfillset(&allsigs); - sigprocmask(SIG_BLOCK, &allsigs, NULL); - (void) seteuid((uid_t)0); - ftpdlogwtmp(ttyline, "", ""); - if (doutmp) - logout(utmp.ut_line); -#if defined(KERBEROS) - if (!notickets && krbtkfile_env) - unlink(krbtkfile_env); -#endif - } + end_login(); /* beware of flushing buffers after a SIGPIPE */ _exit(status); } @@ -1870,6 +2111,7 @@ static void myoob(int signo) { char *cp; + int ret; int save_errno = errno; (void)signo; @@ -1878,9 +2120,13 @@ if (!transflag) return; cp = tmpline; - if (ftpd_getline(cp, 7, stdin) == NULL) { + ret=ftpd_getline(cp, 7, stdin); + if (ret == -1) { reply(221, "You could at least say goodbye."); dologout(0); + } else if (ret == -2) { + /* Ignore truncated command */ + return; } upper(cp); if (strcmp(cp, "ABOR\r\n") == 0) { @@ -1891,11 +2137,11 @@ } if (strcmp(cp, "STAT\r\n") == 0) { if (file_size != (off_t) -1) - reply(213, "Status: %qd of %qd bytes transferred", - (quad_t) byte_count, (quad_t) file_size); + reply(213, "Status: %jd of %jd bytes transferred", + (intmax_t) byte_count, (intmax_t) file_size); else - reply(213, "Status: %qd bytes transferred", - (quad_t)byte_count); + reply(213, "Status: %jd bytes transferred", + (intmax_t)byte_count); } errno = save_errno; } @@ -2101,7 +2347,7 @@ if (S_ISREG(st.st_mode)) { if (dout == NULL) { - dout = dataconn("file list", (off_t)-1, "w"); + dout = dataconn("file list", (off_t)-1, "w", 0); if (dout == NULL) goto out; transflag++; @@ -2143,7 +2389,7 @@ S_ISREG(st.st_mode))) { if (dout == NULL) { dout = dataconn("file list", (off_t)-1, - "w"); + "w", 0); if (dout == NULL) goto out; transflag++; @@ -2238,13 +2484,15 @@ if (hp) { if (!hosts_ctl("ftpd", hp->h_name, addr, STRING_UNKNOWN)) { - syslog(LOG_NOTICE, "tcpwrappers rejected: %s [%s]", + syslog(LOG_FTP | LOG_NOTICE, + "tcpwrappers rejected: %s [%s]", hp->h_name, addr); return (0); } } else { if (!hosts_ctl("ftpd", STRING_UNKNOWN, addr, STRING_UNKNOWN)) { - syslog(LOG_NOTICE, "tcpwrappers rejected: [%s]", addr); + syslog(LOG_FTP | LOG_NOTICE, + "tcpwrappers rejected: [%s]", addr); return (0); } } --- linux-ftpd-0.17.orig/ftpd/logwtmp.c +++ linux-ftpd-0.17/ftpd/logwtmp.c @@ -41,7 +41,6 @@ "$Id: logwtmp.c,v 1.5 1999/07/16 00:34:29 dholland Exp $"; #include -#include #include #include @@ -49,6 +48,7 @@ #include #include #include +#include #include "extern.h" static int fd = -1; --- linux-ftpd-0.17.orig/ftpd/popen.c +++ linux-ftpd-0.17/ftpd/popen.c @@ -169,8 +169,13 @@ * XXX: this doesn't seem right... and shouldn't * we initgroups, or at least setgroups(0,0)? */ - setgid(getegid()); - setuid(i); + +/* + * PSz 25 Aug 06 Must check the return status of these setgid/setuid calls, + * see http://www.bress.net/blog/archives/34-setuid-madness.html + */ + if ( setgid(getegid()) != 0 ) _exit(1); + if ( setuid(i) != 0 ) _exit(1); #ifndef __linux__ /* --- linux-ftpd-0.17.orig/support/Makefile +++ linux-ftpd-0.17/support/Makefile @@ -1,6 +1,6 @@ include ../MCONFIG -OBJS=daemon.o setproctitle.o isexpired.o vis.o +OBJS=setproctitle.o isexpired.o vis.o all: libsupport.a @@ -16,4 +16,3 @@ rm -f *.o libsupport.a setproctitle.o: setproctitle.h -daemon.o: daemon.h --- linux-ftpd-0.17.orig/support/setproctitle.c +++ linux-ftpd-0.17/support/setproctitle.c @@ -139,7 +139,7 @@ (void) strcpy(Argv[0], buf); p = &Argv[0][i]; while (p < LastArgv) - *p++ = ' '; + *p++ = '\0'; Argv[1] = NULL; } --- linux-ftpd-0.17.orig/debian/README.Debian +++ linux-ftpd-0.17/debian/README.Debian @@ -0,0 +1,37 @@ +ftpd for Debian +--------------- + +ftpd now supports PAM. It is recommended that you leave the pam_ftp entry +alone in the pam configuration file since ftpd uses it to figure out prompts +and determining anonymity. + +The best way to disable anonymous ftp is to place ftp and anonymous in +/etc/ftpusers. Removing the user ftp from the system also works. + +The -A option no longer has any effect since authentication is done by PAM. +To recover its functionality, just uncomment the ftpchroot line in the pam +configuration file. + +If you wish to receive reports from users of your ftp server, you should setup +an alias for ftp-bugs@name.of.your.ftp.server. + +Globbing Attacks +---------------- + +Globbing attacks aimed at exhausting memory/CPU resources (e.g., +ls ../*/../*/../*/../*/../*/../*/../*/../*/../*/../*/../*/../*/../*) can be +countered by setting the appropriate resource limits in +/etc/security/limits.conf. To do so, you need to make sure that /etc/pam.d/ftp +contains the line + +session required pam_limits.so + +Which is the case by default. The limits which are most important on Linux are +"as" and "cpu". For example, to limit the memory usage to 10MB, you should put + +ftp hard as 10240 + +in /etc/security/limits.conf. + +Herbert +$Id: README.Debian,v 1.4 2002/10/06 22:23:49 herbert Exp $ --- linux-ftpd-0.17.orig/debian/copyright +++ linux-ftpd-0.17/debian/copyright @@ -0,0 +1,33 @@ +This package was split from netstd by Herbert Xu herbert@debian.org on +Thu, 1 Apr 1999 16:42:48 +1000. + +netstd was created by Peter Tobias tobias@et-inf.fho-emden.de on +Wed, 20 Jul 1994 17:23:21 +0200. + +It was downloaded from ftp://ftp.uk.linux.org/pub/linux/Networking/netkit/. + +Copyright: + +/************************************************************************ + Copyright 1988, 1991 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, provided +that the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation, and that the name of Carnegie Mellon University not be used +in advertising or publicity pertaining to distribution of the software +without specific, written prior permission. + +CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +************************************************************************/ + +$Id: copyright,v 1.2 2000/04/24 08:51:04 herbert Exp $ --- linux-ftpd-0.17.orig/debian/dirs +++ linux-ftpd-0.17/debian/dirs @@ -0,0 +1,4 @@ +etc/pam.d +usr/share/man/man5 +usr/share/man/man8 +usr/sbin --- linux-ftpd-0.17.orig/debian/docs +++ linux-ftpd-0.17/debian/docs @@ -0,0 +1 @@ +README --- linux-ftpd-0.17.orig/debian/ftpchroot +++ linux-ftpd-0.17/debian/ftpchroot @@ -0,0 +1 @@ +# /etc/ftpchroot: list of users who needs to be chrooted. See ftpchroot(5). --- linux-ftpd-0.17.orig/debian/ftpchroot.5 +++ linux-ftpd-0.17/debian/ftpchroot.5 @@ -0,0 +1,28 @@ +.\" Copyright (c) 1999 Herbert Xu (herbert@gondor.apana.org.au), +.\" Copyright (c) 1994 Peter Tobias (tobias@server.et-inf.fho-emden.de), +.\" This file may be distributed under the GNU General Public License. +.TH FTPCHROOT 5 "1999 April 1st" "Linux" "Linux Programmer's Manual" +.SH NAME +ftpchroot \- file which lists users who need to be chrooted +.SH DESCRIPTION +\fB/etc/ftpchroot\fP is used by +.BR ftpd(8); +the file contains a list of users who need to be chrooted before the ftp +service is offered. Blank lines and lines beginning with "#" are ignored. +Remember that the whole line will be used for the username, so please +don't use the "#" character after a name to comment this entry. +.SH EXAMPLES +.B /etc/ftpchroot +may contain the following entries: +.sp +# +.br +# /etc/ftpusers +.br +# +.br +not_so_anonymous +.SH FILES +/etc/ftpchroot +.SH "SEE ALSO" +.BR ftp "(1), " ftpd "(8)" --- linux-ftpd-0.17.orig/debian/ftpusers +++ linux-ftpd-0.17/debian/ftpusers @@ -0,0 +1,5 @@ +# /etc/ftpusers: list of users disallowed ftp access. See ftpusers(5). + +root +ftp +anonymous --- linux-ftpd-0.17.orig/debian/postinst +++ linux-ftpd-0.17/debian/postinst @@ -0,0 +1,21 @@ +#!/bin/sh -e +# $Id: postinst,v 1.7 2003/06/21 02:31:44 herbert Exp $ + +if grep -q '[[:blank:]]/usr/sbin/in\.ftpd.*-z' /etc/inetd.conf; then + update-inetd --pattern '/usr/sbin/in\.ftpd' --remove ".*ftp" +fi + +if grep -q '[[:blank:]]/usr/sbin/in\.ftpd\>' /etc/inetd.conf; then + if ! grep -q '^ftp\>' /etc/inetd.conf; then + update-inetd --pattern '/usr/sbin/in\.ftpd' --enable ftp + fi +else + FTPENTRY="ftp stream tcp nowait root /usr/sbin/tcpd /usr/sbin/in.ftpd" + if grep -q '^ftp\>' /etc/inetd.conf; then + update-inetd --group STANDARD --add "## $FTPENTRY" + else + update-inetd --group STANDARD --add "$FTPENTRY" + fi +fi + +#DEBHELPER# --- linux-ftpd-0.17.orig/debian/preinst +++ linux-ftpd-0.17/debian/preinst @@ -0,0 +1,12 @@ +#!/bin/sh -e +# $Id: preinst,v 1.1 1999/10/07 12:48:39 herbert Exp $ + +# Rename old PAM conffile. +if [ -n "$2" ] && dpkg --compare-versions "$2" lt 0.11-5; then + cd /etc/pam.d + if [ -f ftpd -a ! -f ftp ]; then + cp -p ftpd ftp + fi +fi + +#DEBHELPER# --- linux-ftpd-0.17.orig/debian/prerm +++ linux-ftpd-0.17/debian/prerm @@ -0,0 +1,6 @@ +#!/bin/sh -e +# $Id: prerm,v 1.1 1999/04/16 07:00:29 herbert Exp $ + +update-inetd --pattern '/usr/sbin/in\.ftpd' --disable ftp + +#DEBHELPER# --- linux-ftpd-0.17.orig/debian/postrm +++ linux-ftpd-0.17/debian/postrm @@ -0,0 +1,10 @@ +#!/bin/sh -e +# $Id: postrm,v 1.1 1999/04/16 07:00:28 herbert Exp $ + +if [ "$1" = purge ]; then + if command -v update-inetd >/dev/null 2>&1; then + update-inetd --pattern '/usr/sbin/in\.ftpd' --remove "## ftp" + fi +fi + +#DEBHELPER# --- linux-ftpd-0.17.orig/debian/compat +++ linux-ftpd-0.17/debian/compat @@ -0,0 +1 @@ +4 --- linux-ftpd-0.17.orig/debian/rules +++ linux-ftpd-0.17/debian/rules @@ -0,0 +1,76 @@ +#!/usr/bin/make -f +# Sample debian/rules that uses debhelper. GNU copyright 1997 by Joey Hess. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 +DEFS := -D_FILE_OFFSET_BITS=64 + +build: + dh_testdir + + if [ ! -f MCONFIG ]; then \ + USE_PAM=1 ./configure; \ + sed -e 's/^CFLAGS=\(.*\)$$/CFLAGS= -g $(DEFS) \1/' \ + MCONFIG > MCONFIG.new; \ + mv MCONFIG.new MCONFIG; \ + echo CFLAGS+=-DUSE_PAM >> MCONFIG; \ + echo LIBS+=-lpam >> MCONFIG; \ + fi + $(MAKE) + +clean: + dh_testdir + dh_testroot + + -$(MAKE) distclean + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + cp ftpd/ftpd debian/ftpd/usr/sbin/in.ftpd + cp ftpd/ftpd.8 debian/ftpd/usr/share/man/man8/in.ftpd.8 + cp ftpd/*.5 debian/*.5 debian/ftpd/usr/share/man/man5 + cp debian/ftpchroot debian/ftpusers debian/ftpd/etc + cp debian/pam.d/ftp debian/ftpd/etc/pam.d + + touch install-stamp + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install +# dh_testversion + dh_testdir + dh_testroot +# dh_installdebconf + dh_installdocs + dh_installexamples + dh_installmenu +# dh_installemacsen +# dh_installinit + dh_installcron +# dh_installmanpages +# dh_undocumented + dh_installchangelogs ChangeLog + dh_strip + dh_compress + dh_fixperms + dh_installdeb + dh_shlibdeps + dh_gencontrol +# dh_makeshlibs + dh_md5sums + dh_builddeb + +source diff: + @echo >&2 'source and diff are obsolete - use dpkg-source -b'; false + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install --- linux-ftpd-0.17.orig/debian/control +++ linux-ftpd-0.17/debian/control @@ -0,0 +1,17 @@ +Source: linux-ftpd +Section: net +Priority: extra +Maintainer: Alberto Gonzalez Iniesta +Build-Depends: bison, debhelper (>= 4.1.16), libpam0g-dev | libpam-dev +Standards-Version: 3.7.2.2 + +Package: ftpd +Architecture: any +Depends: openbsd-inetd | inet-superserver, libpam-modules, ${shlibs:Depends} +Provides: ftp-server +Conflicts: ftp-server +Replaces: netstd +Description: File Transfer Protocol (FTP) server + This is the netkit ftp server. It is recommended for you to use one of its + alternatives, such as wu-ftpd or proftpd. + --- linux-ftpd-0.17.orig/debian/changelog +++ linux-ftpd-0.17/debian/changelog @@ -0,0 +1,290 @@ +linux-ftpd (0.17-29) unstable; urgency=high + + * Ian Beckwith: + - Patch to fix cross-site request forgery (CSRF) attacks. + CVE-2008-4247 (Closes: #500278) + * Updated package description. (Closes: #493433) + + -- Alberto Gonzalez Iniesta Fri, 17 Oct 2008 20:34:17 +0200 + +linux-ftpd (0.17-28) unstable; urgency=low + + * Patch postrm/postinst files to handle update-inetd better. + Thanks Ian Beckwith for the patch. (Closes: #482912) + + -- Alberto Gonzalez Iniesta Tue, 22 Jul 2008 17:13:19 +0200 + +linux-ftpd (0.17-27) unstable; urgency=low + + * Ignore missing ../MCONFIG in clean target. (Closes: #436720) + + -- Alberto Gonzalez Iniesta Wed, 08 Aug 2007 20:49:22 +0200 + +linux-ftpd (0.17-26) unstable; urgency=low + + * Removed Depends on update-inetd, since it should be provided by + inetd-superserver. + + -- Alberto Gonzalez Iniesta Tue, 07 Aug 2007 18:02:11 +0200 + +linux-ftpd (0.17-25) unstable; urgency=low + + * Condition the call to update-inetd in postrm. (Closes: #416745) + * Moved netbase dependency to openbsd-inetd | inet-superserver. + * Added Depends on update-inetd + * Moved to debhelper compat 4. (Removed debian/conffiles) + * Bumped Standards-Version to 3.7.2.2. No change + + -- Alberto Gonzalez Iniesta Sat, 31 Mar 2007 19:43:37 +0200 + +linux-ftpd (0.17-24) unstable; urgency=low + + * pam.d/ftpd. Updated PAM configuration to used common-* files. + Thanks a lot Pierre Gaufillet for the patch (Closes: #308651) + + -- Alberto Gonzalez Iniesta Thu, 14 Dec 2006 12:14:53 +0100 + +linux-ftpd (0.17-23) unstable; urgency=high + + * Urgency set due to security fix. + * Corrected typo in patch used in previous upload that + made the server run some commands with EGID 'root'. + Thanks to Matt Power (for finding out) and + Stefan Cornelius from Gentoo (for warning me). + + -- Alberto Gonzalez Iniesta Sat, 25 Nov 2006 18:54:59 +0100 + +linux-ftpd (0.17-22) unstable; urgency=high + + * Fixing two security bugs: + - Fixed ftpd from doing chdir while running as root. + (Closes: #384454) Thanks a lot to Paul Szabo for finding out + and the patch. + - Check the return value from setuid calls to avoid running + code as root. Thanks Paul Szabo for the patch. + + -- Alberto Gonzalez Iniesta Fri, 15 Sep 2006 13:14:25 +0200 + +linux-ftpd (0.17-21) unstable; urgency=low + + * Patched ftpcmd.y to allow building on amd64 with gcc-4.0. + Thanks Andreas Jochens for the patch. (Closes: #300245) + + -- Alberto Gonzalez Iniesta Sun, 10 Jul 2005 08:48:19 +0200 + +linux-ftpd (0.17-20) unstable; urgency=low + + * New maintainer. + + -- Alberto Gonzalez Iniesta Sat, 12 Mar 2005 12:07:29 +0100 + +linux-ftpd (0.17-19) unstable; urgency=low + + * Add -n option to log numeric IPs rather than doing reverse lookup (for + improved log forensics in the event an attacker has control of their + reverse DNS.). Thanks Dean Gaudet. (Closes: #258369) + * Fix Build-Depends to avoid relying on virtual package 'libpam-dev' + exclussively. + * Convert changelog to UTF-8. + + -- Robert Millan Wed, 11 Aug 2004 22:08:44 +0200 + +linux-ftpd (0.17-18) unstable; urgency=low + + * New maintainer. (Closes: #249709) + - control (Maintainer): Set myself. + + -- Robert Millan Wed, 19 May 2004 02:09:10 +0200 + +linux-ftpd (0.17-17) unstable; urgency=low + + * Documented the need for libnss_files.so.2 (closes: #241687). + + -- Herbert Xu Sat, 24 Apr 2004 17:48:37 +1000 + +linux-ftpd (0.17-16) unstable; urgency=low + + * Fixed ftpd entry existence test in postinst. + * Added missing -q for last grep in postinst. + * Removed debconf message about globbing attacks. + * Fixed type-punning warning in pam_doit. + * Removed stamp files for build and install. + * Fixed const cast warning in ftpcmd.y. + + -- Herbert Xu Sat, 21 Jun 2003 14:20:35 +1000 + +linux-ftpd (0.17-15) unstable; urgency=low + + * Removed description of bogus -p option (closes: #180652). + + -- Herbert Xu Thu, 6 Mar 2003 20:26:16 +1100 + +linux-ftpd (0.17-14) unstable; urgency=low + + * Added Spanish debconf translation (Carlos Valdivia Yagüe, closes: #143956). + * Call ls without -g (closes #156992). + + -- Herbert Xu Sun, 25 Aug 2002 10:09:07 +1000 + +linux-ftpd (0.17-13) unstable; urgency=low + + * Added Russian debconf translation (Ilgiz Kalmetev, closes: #135840). + + -- Herbert Xu Thu, 18 Apr 2002 19:18:28 +1000 + +linux-ftpd (0.17-12) unstable; urgency=low + + * Fixed REST/STOR combination with OpenBSD patch (closes: #132974). + + -- Herbert Xu Sat, 9 Feb 2002 14:50:45 +1100 + +linux-ftpd (0.17-11) unstable; urgency=low + + * REST now accepts intmax_t (closes: #126766). + + -- Herbert Xu Sun, 20 Jan 2002 19:03:22 +1100 + +linux-ftpd (0.17-10) unstable; urgency=low + + * Built with support for large files (closes: #122961). + + -- Herbert Xu Sun, 9 Dec 2001 17:45:53 +1100 + +linux-ftpd (0.17-9) unstable; urgency=low + + * Added sample limits.conf entry against globbing (closes: #121074). + * Added Brazilian debconf template (Andre Luis Lopes, closes: #120835). + * Always specify the syslog facility explicitly (closes: #121644). + + -- Herbert Xu Sat, 1 Dec 2001 18:28:51 +1100 + +linux-ftpd (0.17-8) unstable; urgency=low + + * Added German debconf template (Sebastian Feltel, closes: #113611). + + -- Herbert Xu Sat, 13 Oct 2001 08:13:55 +1000 + +linux-ftpd (0.17-7) unstable; urgency=low + + * Added debconf about globbing attacks. + + -- Herbert Xu Thu, 23 Aug 2001 19:49:01 +1000 + +linux-ftpd (0.17-6) unstable; urgency=low + + * Register sessions with PAM. + * Use pam_limits by default. + * Documented the procedure to counter globbing attacks. + + -- Herbert Xu Sat, 9 Jun 2001 13:25:27 +1000 + +linux-ftpd (0.17-5) unstable; urgency=low + + * Removed duplicate authentication error message (closes: #96640). + + -- Herbert Xu Mon, 7 May 2001 22:08:29 +1000 + +linux-ftpd (0.17-4) unstable; urgency=low + + * The value of unique is now passed to dataconn (closes: #93217). + + -- Herbert Xu Sun, 22 Apr 2001 09:33:26 +1000 + +linux-ftpd (0.17-3) unstable; urgency=low + + * Fixed anonymous authentication bug when PAM is disabled (Liviu Daia, + Abraham vd Merwe, Rainer Weikusat, closes: #88837). + * Fixed patterns used to check for existing ftp services (closes: #85579). + + -- Herbert Xu Fri, 9 Mar 2001 22:30:37 +1100 + +linux-ftpd (0.17-2) unstable; urgency=high + + * Applied bug fix from OpenBSD (closes: #78973). + + -- Herbert Xu Thu, 7 Dec 2000 19:47:47 +1100 + +linux-ftpd (0.17-1) unstable; urgency=low + + * New upstream release (identical to 0.16-2). + + -- Herbert Xu Sat, 12 Aug 2000 13:29:38 +1000 + +linux-ftpd (0.16-2) unstable; urgency=high + + * Fixed a security hole discovered by OpenBSD, thanks to Thomas Roessler for + notifying me (closes: #66832). + * Added build-time dependency on debhelper. + + -- Herbert Xu Fri, 7 Jul 2000 10:15:38 +1000 + +linux-ftpd (0.16-1) unstable; urgency=low + + * New upstream release. + * Added Source-Depends on bison (closes: #61160). + * Removed checks on the remote address of the data connection which violated + RFC 959 (closes: #59251). + + -- Herbert Xu Mon, 24 Apr 2000 20:46:00 +1000 + +linux-ftpd (0.11-9) frozen unstable; urgency=low + + * Added Bource-Depends on libpam0g-dev (closes: #49917). + + -- Herbert Xu Sat, 18 Mar 2000 12:50:14 +1100 + +linux-ftpd (0.11-8) unstable; urgency=low + + * Added entry for ~ftp/lib in in.ftpd(8) (closes: #49035). + + -- Herbert Xu Sat, 6 Nov 1999 12:21:37 +1100 + +linux-ftpd (0.11-7) unstable; urgency=low + + * Added missing dependencies on netbase and libpam-modules (closes: #48411). + + -- Herbert Xu Wed, 27 Oct 1999 09:25:59 +1000 + +linux-ftpd (0.11-6) unstable; urgency=low + + * Anonymous users other than ftp should work now (closes: #48252). + + -- Herbert Xu Mon, 25 Oct 1999 16:38:16 +1000 + +linux-ftpd (0.11-5) unstable; urgency=low + + * Installed files according to the FHS. + * Applied PAM patch from Olaf Kirch. + * Renamed PAM file to ftp. + + -- Herbert Xu Thu, 7 Oct 1999 22:19:58 +1000 + +linux-ftpd (0.11-4) unstable; urgency=low + + * Rewritten PAM code to remove hack for ftp prompt. + * Provide/conflict with ftp-server (fixes #42412). + + -- Herbert Xu Fri, 10 Sep 1999 10:32:04 +1000 + +linux-ftpd (0.11-3) unstable; urgency=low + + * Fixed incorrect usage of update-inetd in postinst (fixes #40771). + + -- Herbert Xu Mon, 5 Jul 1999 17:46:41 +1000 + +linux-ftpd (0.11-2) unstable; urgency=low + + * Don't use absoluet paths in PAM configuration file (fixes #38985). + + -- Herbert Xu Sat, 19 Jun 1999 12:10:03 +1000 + +linux-ftpd (0.11-1) unstable; urgency=low + + * Split from netstd. + * Added support for PAM. + * Pad with zeros instead of spaces in setproctitle. + * Add a note about ftp-bugs in README (fixes #29733). + * Made response to STOU commands conform to RFC 1123 (fixes #32490). + + -- Herbert Xu Thu, 1 Apr 1999 13:45:20 +1000 + --- linux-ftpd-0.17.orig/debian/pam.d/ftp +++ linux-ftpd-0.17/debian/pam.d/ftp @@ -0,0 +1,13 @@ +# Standard behaviour for ftpd(8). +auth required pam_listfile.so item=user sense=deny file=/etc/ftpusers onerr=succeed + +# This line is required by ftpd(8). +auth sufficient pam_ftp.so + +# Uncomment this to achieve what used to be ftpd -A. +#auth required pam_listfile.so item=user sense=allow file=/etc/ftpchroot onerr=fail + +# Standard blurb. +@include common-auth +@include common-account +@include common-session