diff --git a/src/bin/network/ftpd/config.h b/src/bin/network/ftpd/config.h index ac75ac232d..8d2abec06c 100644 --- a/src/bin/network/ftpd/config.h +++ b/src/bin/network/ftpd/config.h @@ -1,4 +1,3 @@ -/* $FreeBSD: src/libexec/ftpd/config.h,v 1.1 2001/07/19 17:45:14 obrien Exp $ */ /* config.h. Generated automatically by configure. */ @@ -199,7 +198,7 @@ #define HAVE_SOCKLEN_T 1 /* Define if AF_INET6 exists in */ -/* #define HAVE_AF_INET6 1 */ +#define HAVE_AF_INET6 1 /* Define if `struct sockaddr_in6' exists in */ #define HAVE_SOCKADDR_IN6 1 diff --git a/src/bin/network/ftpd/extern.h b/src/bin/network/ftpd/extern.h index b76d299e6e..2e314ba5c1 100644 --- a/src/bin/network/ftpd/extern.h +++ b/src/bin/network/ftpd/extern.h @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * @@ -10,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -31,7 +29,6 @@ * SUCH DAMAGE. * * @(#)extern.h 8.2 (Berkeley) 4/4/94 - * $FreeBSD: src/libexec/ftpd/extern.h,v 1.19 2002/02/04 01:23:44 kris Exp $ */ #include @@ -46,7 +43,7 @@ void fatalerror(char *); void ftpd_logwtmp(char *, char *, struct sockaddr *addr); int ftpd_pclose(FILE *); FILE *ftpd_popen(char *, char *); -int *ftpd_getline(char *, int, FILE *); +int get_line(char *, int, FILE *); void lreply(int, const char *, ...) __printflike(2, 3); void makedir(char *); void nack(char *); @@ -70,6 +67,35 @@ void yyerror(char *); int yyparse(void); int ls_main(int, char **); +extern int assumeutf8; +extern char cbuf[]; +extern union sockunion data_dest; +extern int epsvall; +extern int form; +extern int ftpdebug; +extern int guest; +extern union sockunion his_addr; +extern char *homedir; +extern int hostinfo; +extern char *hostname; +extern int maxtimeout; +extern int logged_in; +extern int logging; +extern int noepsv; +extern int noguestretr; +extern int noretr; +extern int paranoid; +extern struct passwd *pw; +extern int pdata; +extern char proctitle[]; +extern int readonly; +extern off_t restart_point; +extern int timeout; +extern char tmpline[]; +extern int type; +extern char *typenames[]; /* defined in included from ftpd.c */ +extern int usedefault; + struct sockaddr_in; struct sockaddr_in6; union sockunion { diff --git a/src/bin/network/ftpd/ftpcmd.y b/src/bin/network/ftpd/ftpcmd.y index 76f6ecd08a..479cfdf053 100644 --- a/src/bin/network/ftpd/ftpcmd.y +++ b/src/bin/network/ftpd/ftpcmd.y @@ -1,4 +1,6 @@ -/* +/*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1985, 1988, 1993, 1994 * The Regents of the University of California. All rights reserved. * @@ -10,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -47,8 +45,6 @@ static char sccsid[] = "@(#)ftpcmd.y 8.3 (Berkeley) 4/6/94"; #endif /* not lint */ #include -__FBSDID("$FreeBSD: src/libexec/ftpd/ftpcmd.y,v 1.66 2007/04/18 22:43:39 yar Exp $"); - #include #include #include @@ -76,30 +72,7 @@ __FBSDID("$FreeBSD: src/libexec/ftpd/ftpcmd.y,v 1.66 2007/04/18 22:43:39 yar Exp #include "extern.h" #include "pathnames.h" -extern union sockunion data_dest, his_addr; -extern int hostinfo; -extern int logged_in; -extern struct passwd *pw; -extern int guest; -extern char *homedir; -extern int paranoid; -extern int logging; -extern int type; -extern int form; -extern int ftpdebug; -extern int timeout; -extern int maxtimeout; -extern int pdata; -extern char *hostname; -extern char proctitle[]; -extern int usedefault; -extern char tmpline[]; -extern int readonly; -extern int assumeutf8; -extern int noepsv; -extern int noretr; -extern int noguestretr; -extern char *typenames[]; /* defined in included from ftpd.c */ +#define yylex ftpcmd_yylex off_t restart_point; @@ -110,8 +83,6 @@ static int state; char cbuf[512]; char *fromname = NULL; -extern int epsvall; - #define CMD 0 /* beginning of command */ #define ARGS 1 /* expect miscellaneous arguments */ #define STR1 2 /* expect SP followed by STRING */ @@ -252,8 +223,8 @@ static int port_check(const char *); #ifdef INET6 static int port_check_v6(const char *); #endif -static int check_login1(void); static void sizecmd(char *); +static int check_login1(void); static void toolong(int); #ifdef INET6 static void v4map_data_dest(void); @@ -542,7 +513,7 @@ cmd case MODE_S: reply(200, "MODE S accepted."); break; - + default: reply(502, "Unimplemented MODE type."); } @@ -915,7 +886,7 @@ rcmd free(fromname); fromname = NULL; restart_point = $4.o; - reply(350, "Restarting at %lld. %s", + reply(350, "Restarting at %jd. %s", (intmax_t)restart_point, "Send STORE or RETRIEVE to initiate transfer."); } @@ -1194,10 +1165,10 @@ lookup(struct tab *p, char *cmd) #include /* - * ftpd_getline - a hacked up version of fgets to ignore TELNET escape codes. + * get_line - a hacked up version of fgets to ignore TELNET escape codes. */ -int * -ftpd_getline(char *s, int n, FILE *iop) +int +get_line(char *s, int n, FILE *iop) { int c; register char *cs; @@ -1316,7 +1287,7 @@ yylex(void) case CMD: (void) signal(SIGALRM, toolong); (void) alarm(timeout); - n = ftpd_getline(cbuf, sizeof(cbuf)-1, stdin); + n = get_line(cbuf, sizeof(cbuf)-1, stdin); if (n == -1) { reply(221, "You could at least say goodbye."); dologout(0); @@ -1624,7 +1595,7 @@ sizecmd(char *filename) else if (!S_ISREG(stbuf.st_mode)) reply(550, "%s: not a plain file.", filename); else - reply(213, "%lld", (intmax_t)stbuf.st_size); + reply(213, "%jd", (intmax_t)stbuf.st_size); break; } case TYPE_A: { FILE *fin; @@ -1658,7 +1629,7 @@ sizecmd(char *filename) } (void) fclose(fin); - reply(213, "%lld", (intmax_t)count); + reply(213, "%jd", (intmax_t)count); break; } default: reply(504, "SIZE not implemented for type %s.", @@ -1750,7 +1721,7 @@ exptilde(char *s) * Avoid expanding to a pathname including '\r' or '\n' in order to * not disrupt the FTP protocol. * The expansion found must be unique. - * Return the result as a malloced string, or NULL if an error occured. + * Return the result as a malloced string, or NULL if an error occurred. * * Problem: this production is used for all pathname * processing, but only gives a 550 error reply. diff --git a/src/bin/network/ftpd/ftpd.c b/src/bin/network/ftpd/ftpd.c index a88c37caa3..fdcf088e23 100644 --- a/src/bin/network/ftpd/ftpd.c +++ b/src/bin/network/ftpd/ftpd.c @@ -1,4 +1,6 @@ -/* +/*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994 * The Regents of the University of California. All rights reserved. * @@ -10,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -46,14 +44,12 @@ static char sccsid[] = "@(#)ftpd.c 8.4 (Berkeley) 4/16/94"; #endif /* not lint */ #include -__FBSDID("$FreeBSD: src/libexec/ftpd/ftpd.c,v 1.212 2007/04/18 22:43:39 yar Exp $"); - /* * FTP server. */ #include #include -//#include +#include #include #include #include @@ -111,9 +107,6 @@ __FBSDID("$FreeBSD: src/libexec/ftpd/ftpd.c,v 1.212 2007/04/18 22:43:39 yar Exp static char version[] = "Version 6.00LS"; #undef main -extern off_t restart_point; -extern char cbuf[]; - union sockunion ctrl_addr; union sockunion data_source; union sockunion data_dest; @@ -153,6 +146,7 @@ int noretr = 0; /* RETR command is disabled. */ int noguestretr = 0; /* RETR command is disabled for anon users. */ int noguestmkd = 0; /* MKD command is disabled for anon users. */ int noguestmod = 1; /* anon users may not modify existing files. */ +int use_blacklist = 0; off_t file_size; off_t byte_count; @@ -182,8 +176,7 @@ static struct ftphost { char remotehost[NI_MAXHOST]; char *ident = NULL; -static char ttyline[20]; -char *tty = ttyline; /* for klogin */ +static char wtmpid[20]; #ifdef USE_PAM static int auth_pam(struct passwd**, const char*); @@ -252,7 +245,7 @@ static void sigurg(int); static void maskurg(int); static void flagxfer(int); static int myoob(void); -static int checkuser(char *, char *, int, char **); +static int checkuser(char *, char *, int, char **, int *); static FILE *dataconn(char *, off_t, char *); static void dolog(struct sockaddr *); static void end_login(void); @@ -276,7 +269,7 @@ int main(int argc, char *argv[], char **envp) { socklen_t addrlen; - int ch, on = 1, tos; + int ch, on = 1, tos, s = STDIN_FILENO; char *cp, line[LINE_MAX]; FILE *fd; char *bindname = NULL; @@ -303,7 +296,7 @@ main(int argc, char *argv[], char **envp) openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP); while ((ch = getopt(argc, argv, - "468a:AdDEhlmMoOp:P:rRSt:T:u:UvW")) != -1) { + "468a:ABdDEhlmMoOp:P:rRSt:T:u:UvW")) != -1) { switch (ch) { case '4': family = (family == AF_INET6) ? AF_UNSPEC : AF_INET; @@ -325,6 +318,14 @@ main(int argc, char *argv[], char **envp) anon_only = 1; break; + case 'B': +#ifdef USE_BLACKLIST + use_blacklist = 1; +#else + syslog(LOG_WARNING, "not compiled with USE_BLACKLIST support"); +#endif + break; + case 'd': ftpdebug++; break; @@ -422,6 +423,10 @@ main(int argc, char *argv[], char **envp) } } + /* handle filesize limit gracefully */ + sa.sa_handler = SIG_IGN; + (void)sigaction(SIGXFSZ, &sa, NULL); + if (daemon_mode) { int *ctl_sock, fd, maxfd = -1, nfds, i; fd_set defreadfds, readfds; @@ -502,8 +507,8 @@ main(int argc, char *argv[], char **envp) switch (pid = fork()) { case 0: /* child */ - (void) dup2(fd, 0); - (void) dup2(fd, 1); + (void) dup2(fd, s); + (void) dup2(fd, STDOUT_FILENO); (void) close(fd); for (i = 1; i <= *ctl_sock; i++) close(ctl_sock[i]); @@ -520,7 +525,7 @@ main(int argc, char *argv[], char **envp) } } else { addrlen = sizeof(his_addr); - if (getpeername(0, (struct sockaddr *)&his_addr, &addrlen) < 0) { + if (getpeername(s, (struct sockaddr *)&his_addr, &addrlen) < 0) { syslog(LOG_ERR, "getpeername (%s): %m",argv[0]); exit(1); } @@ -555,7 +560,7 @@ gotchild: (void)sigaction(SIGPIPE, &sa, NULL); addrlen = sizeof(ctrl_addr); - if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) { + if (getsockname(s, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) { syslog(LOG_ERR, "getsockname (%s): %m",argv[0]); exit(1); } @@ -568,7 +573,7 @@ gotchild: if (ctrl_addr.su_family == AF_INET) { tos = IPTOS_LOWDELAY; - if (setsockopt(0, IPPROTO_IP, IP_TOS, &tos, sizeof(int)) < 0) + if (setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(int)) < 0) syslog(LOG_WARNING, "control setsockopt (IP_TOS): %m"); } #endif @@ -576,22 +581,21 @@ gotchild: * Disable Nagle on the control channel so that we don't have to wait * for peer's ACK before issuing our next reply. */ - if (setsockopt(0, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) + if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) syslog(LOG_WARNING, "control setsockopt (TCP_NODELAY): %m"); data_source.su_port = htons(ntohs(ctrl_addr.su_port) - 1); - /* set this here so klogin can use it... */ - (void)snprintf(ttyline, sizeof(ttyline), "ftp%d", (int)getpid()); + (void)snprintf(wtmpid, sizeof(wtmpid), "%xftpd", getpid()); /* Try to handle urgent data inline */ #ifdef SO_OOBINLINE - if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)) < 0) + if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)) < 0) syslog(LOG_WARNING, "control setsockopt (SO_OOBINLINE): %m"); #endif #ifdef F_SETOWN - if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1) + if (fcntl(s, F_SETOWN, getpid()) == -1) syslog(LOG_ERR, "fcntl F_SETOWN: %m"); #endif dolog((struct sockaddr *)&his_addr); @@ -1009,6 +1013,7 @@ static char curname[MAXLOGNAME]; /* current USER name */ void user(char *name) { + int ecode; char *cp, *shell; if (logged_in) { @@ -1029,8 +1034,11 @@ user(char *name) pw = sgetpwnam("ftp"); #endif if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) { - if (checkuser(_PATH_FTPUSERS, "ftp", 0, NULL) || - checkuser(_PATH_FTPUSERS, "anonymous", 0, NULL)) + if (checkuser(_PATH_FTPUSERS, "ftp", 0, NULL, &ecode) || + (ecode != 0 && ecode != ENOENT)) + reply(530, "User %s access denied.", name); + else if (checkuser(_PATH_FTPUSERS, "anonymous", 0, NULL, &ecode) || + (ecode != 0 && ecode != ENOENT)) reply(530, "User %s access denied.", name); else if (pw != NULL) { guest = 1; @@ -1048,7 +1056,7 @@ user(char *name) reply(530, "Sorry, only anonymous ftp allowed."); return; } - + if ((pw = sgetpwnam(name))) { if ((shell = pw->pw_shell) == NULL || *shell == 0) shell = _PATH_BSHELL; @@ -1058,7 +1066,9 @@ user(char *name) break; endusershell(); - if (cp == NULL || checkuser(_PATH_FTPUSERS, name, 1, NULL)) { + if (cp == NULL || + (checkuser(_PATH_FTPUSERS, name, 1, NULL, &ecode) || + (ecode != 0 && ecode != ENOENT))) { reply(530, "User %s access denied.", name); if (logging) syslog(LOG_NOTICE, @@ -1103,13 +1113,15 @@ user(char *name) * of the matching line in "residue" if not NULL. */ static int -checkuser(char *fname, char *name, int pwset, char **residue) +checkuser(char *fname, char *name, int pwset, char **residue, int *ecode) { FILE *fd; int found = 0; size_t len; char *line, *mp, *p; + if (ecode != NULL) + *ecode = 0; if ((fd = fopen(fname, "r")) != NULL) { while (!found && (line = fgetln(fd, &len)) != NULL) { /* skip comments */ @@ -1178,7 +1190,8 @@ nextline: free(mp); } (void) fclose(fd); - } + } else if (ecode != NULL) + *ecode = errno; return (found); } @@ -1194,14 +1207,14 @@ end_login(void) #endif (void) seteuid(0); - if (logged_in && dowtmp) - ftpd_logwtmp(ttyline, "", NULL); - pw = NULL; #ifdef LOGIN_CAP - setusercontext(NULL, getpwuid(0), 0, - LOGIN_SETPRIORITY|LOGIN_SETRESOURCES|LOGIN_SETUMASK| - LOGIN_SETMAC); + setusercontext(NULL, getpwuid(0), 0, LOGIN_SETALL & ~(LOGIN_SETLOGIN | + LOGIN_SETUSER | LOGIN_SETGROUP | LOGIN_SETPATH | + LOGIN_SETENV)); #endif + if (logged_in && dowtmp) + ftpd_logwtmp(wtmpid, NULL, NULL); + pw = NULL; #ifdef USE_PAM if (pamh) { if ((e = pam_setcred(pamh, PAM_DELETE_CRED)) != PAM_SUCCESS) @@ -1375,7 +1388,7 @@ auth_pam(struct passwd **ppw, const char *pass) void pass(char *passwd) { - int rval; + int rval, ecode; FILE *fd; #ifdef LOGIN_CAP login_cap_t *lc = NULL; @@ -1495,12 +1508,36 @@ skip: } #endif - /* open wtmp before chroot */ + dochroot = + checkuser(_PATH_FTPCHROOT, pw->pw_name, 1, &residue, &ecode) +#ifdef LOGIN_CAP /* Allow login.conf configuration as well */ + || login_getcapbool(lc, "ftp-chroot", 0) +#endif + ; + /* + * It is possible that checkuser() failed to open the chroot file. + * If this is the case, report that logins are un-available, since we + * have no way of checking whether or not the user should be chrooted. + * We ignore ENOENT since it is not required that this file be present. + */ + if (ecode != 0 && ecode != ENOENT) { + reply(530, "Login not available right now."); + return; + } + chrootdir = NULL; + + /* Disable wtmp logging when chrooting. */ + if (dochroot || guest) + dowtmp = 0; if (dowtmp) - ftpd_logwtmp(ttyline, pw->pw_name, + ftpd_logwtmp(wtmpid, pw->pw_name, (struct sockaddr *)&his_addr); logged_in = 1; +#ifdef LOGIN_CAP + setusercontext(lc, pw, 0, LOGIN_SETRESOURCES); +#endif + if (guest && stats && statfd < 0) { #ifdef VIRTUAL_HOSTING statfd = open(thishost->statfile, O_WRONLY|O_APPEND); @@ -1511,13 +1548,6 @@ skip: stats = 0; } - dochroot = - checkuser(_PATH_FTPCHROOT, pw->pw_name, 1, &residue) -#ifdef LOGIN_CAP /* Allow login.conf configuration as well */ - || login_getcapbool(lc, "ftp-chroot", 0) -#endif - ; - chrootdir = NULL; #if (!defined(__BEOS__) && !defined(__HAIKU__)) /* * For a chrooted local user, @@ -1579,13 +1609,20 @@ skip: * (uid 0 has no root power over NFS if not mapped explicitly.) */ if (seteuid(pw->pw_uid) < 0) { - reply(550, "Can't set uid."); - goto bad; + if (guest || dochroot) { + fatalerror("Can't set uid."); + } else { + reply(550, "Can't set uid."); + goto bad; + } } + /* + * Do not allow the session to live if we're chroot()'ed and chdir() + * fails. Otherwise the chroot jail can be escaped. + */ if (chdir(homedir) < 0) { if (guest || dochroot) { - reply(550, "Can't change to base directory."); - goto bad; + fatalerror("Can't change to base directory."); } else { if (chdir("/") < 0) { reply(550, "Root is inaccessible."); @@ -1679,14 +1716,14 @@ retrieve(char *cmd, char *name) struct stat st; int (*closefunc)(FILE *); time_t start; + char line[BUFSIZ]; if (cmd == 0) { fin = fopen(name, "r"), closefunc = fclose; st.st_size = 0; } else { - char line[BUFSIZ]; - - (void) snprintf(line, sizeof(line), cmd, name), name = line; + (void) snprintf(line, sizeof(line), cmd, name); + name = line; fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose; st.st_size = -1; st.st_blksize = BUFSIZ; @@ -1926,7 +1963,7 @@ dataconn(char *name, off_t size, char *mode) byte_count = 0; if (size != -1) (void) snprintf(sizebuf, sizeof(sizebuf), - " (%lld bytes)", (intmax_t)size); + " (%jd bytes)", (intmax_t)size); else *sizebuf = '\0'; if (pdata >= 0) { @@ -2056,7 +2093,7 @@ pdata_err: } while (0) /* - * Tranfer the contents of "instr" to "outstr" peer using the appropriate + * Transfer the contents of "instr" to "outstr" peer using the appropriate * encapsulation of the data subject to Mode, Structure, and Type. * * NB: Form isn't handled. @@ -2359,8 +2396,8 @@ statfilecmd(char *filename) (void)snprintf(line, sizeof(line), _PATH_LS " -lgA %s", filename); fin = ftpd_popen(line, "r"); if (fin == NULL) { - perror_reply(551, filename); - return; + perror_reply(551, filename); + return; } lreply(code, "Status of %s:", filename); atstart = 1; @@ -2766,7 +2803,12 @@ dologout(int status) if (logged_in && dowtmp) { (void) seteuid(0); - ftpd_logwtmp(ttyline, "", NULL); +#ifdef LOGIN_CAP + setusercontext(NULL, getpwuid(0), 0, LOGIN_SETALL & ~(LOGIN_SETLOGIN | + LOGIN_SETUSER | LOGIN_SETGROUP | LOGIN_SETPATH | + LOGIN_SETENV)); +#endif + ftpd_logwtmp(wtmpid, NULL, NULL); } /* beware of flushing buffers after a SIGPIPE */ _exit(status); @@ -2830,13 +2872,13 @@ myoob(void) return (0); } cp = tmpline; - ret = getline(cp, 7, stdin); + ret = get_line(cp, 7, stdin); if (ret == -1) { reply(221, "You could at least say goodbye."); dologout(0); } else if (ret == -2) { - /* Ignore truncated command. */ - return (0); + /* Ignore truncated command. */ + return (0); } upper(cp); if (strcmp(cp, "ABOR\r\n") == 0) { @@ -2848,10 +2890,10 @@ myoob(void) if (strcmp(cp, "STAT\r\n") == 0) { tmpline[0] = '\0'; if (file_size != -1) - reply(213, "Status: %lld of %lld bytes transferred.", + reply(213, "Status: %jd of %jd bytes transferred.", (intmax_t)byte_count, (intmax_t)file_size); else - reply(213, "Status: %lld bytes transferred.", + reply(213, "Status: %jd bytes transferred.", (intmax_t)byte_count); } return (0); @@ -2919,14 +2961,12 @@ passive(void) goto pasv_error; if (pasv_addr.su_family == AF_INET) a = (char *) &pasv_addr.su_sin.sin_addr; -#ifdef HAVE_AF_INET6 else if (pasv_addr.su_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr)) a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12]; -#endif else goto pasv_error; - + p = (char *) &pasv_addr.su_port; #define UC(b) (((int) b) & 0xff) @@ -2985,7 +3025,7 @@ long_passive(char *cmd, int pf) return; } } - + pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0); if (pdata < 0) { perror_reply(425, "Can't open passive connection"); @@ -3039,15 +3079,12 @@ long_passive(char *cmd, int pf) switch (pasv_addr.su_family) { case AF_INET: a = (char *) &pasv_addr.su_sin.sin_addr; -#ifdef HAVE_AF_INET6 v4_reply: -#endif reply(228, "Entering Long Passive Mode (%d,%d,%d,%d,%d,%d,%d,%d,%d)", 4, 4, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 2, UC(p[0]), UC(p[1])); return; -#ifdef HAVE_AF_INET6 case AF_INET6: if (IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr)) { a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12]; @@ -3063,7 +3100,6 @@ long_passive(char *cmd, int pf) UC(a[12]), UC(a[13]), UC(a[14]), UC(a[15]), 2, UC(p[0]), UC(p[1])); return; -#endif } } else if (strcmp(cmd, "EPSV") == 0) { switch (pasv_addr.su_family) { @@ -3124,7 +3160,7 @@ guniquefd(char *local, char **name) /* -4 is for the .nn we put on the end below */ (void) snprintf(new, sizeof(new) - 4, "%s", local); cp = new + strlen(new); - /* + /* * Don't generate dotfile unless requested explicitly. * This covers the case when basename gets truncated off * by buffer size. @@ -3356,7 +3392,7 @@ logcmd(char *cmd, char *file1, char *file2, off_t cnt) if (file2) appendf(&msg, " %s", file2); if (cnt >= 0) - appendf(&msg, " = %lld bytes", (intmax_t)cnt); + appendf(&msg, " = %jd bytes", (intmax_t)cnt); appendf(&msg, " (wd: %s", wd); if (guest || dochroot) appendf(&msg, "; chrooted"); @@ -3378,7 +3414,7 @@ logxfer(char *name, off_t size, time_t start) syslog(LOG_NOTICE, "realpath failed on %s: %m", path); return; } - snprintf(buf, sizeof(buf), "%.20s!%s!%s!%s!%lld!%ld\n", + snprintf(buf, sizeof(buf), "%.20s!%s!%s!%s!%jd!%ld\n", ctime(&now)+4, ident, remotehost, path, (intmax_t)size, (long)(now - start + (now == start))); @@ -3452,14 +3488,12 @@ socksetup(int af, char *bindname, const char *bindport) &on, sizeof(on)) < 0) syslog(LOG_WARNING, "control setsockopt (SO_REUSEADDR): %m"); -#ifdef HAVE_AF_INET6 if (r->ai_family == AF_INET6) { if (setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) syslog(LOG_WARNING, "control setsockopt (IPV6_V6ONLY): %m"); } -#endif if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) { syslog(LOG_DEBUG, "control bind: %m"); close(*s); diff --git a/src/bin/network/ftpd/logwtmp.c b/src/bin/network/ftpd/logwtmp.c index 63517ece62..933fca37a4 100644 --- a/src/bin/network/ftpd/logwtmp.c +++ b/src/bin/network/ftpd/logwtmp.c @@ -1,4 +1,6 @@ -/* +/*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -10,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -38,59 +36,42 @@ static char sccsid[] = "@(#)logwtmp.c 8.1 (Berkeley) 6/4/93"; #endif /* not lint */ #include -__FBSDID("$FreeBSD: src/libexec/ftpd/logwtmp.c,v 1.13 2004/11/18 13:46:29 yar Exp $"); - #include #include #include #include #include -#include -#include -#if (!defined(__BEOS__) && !defined(__HAIKU__)) -#include -#include -#endif -#include -#include +#include #include #include -#include +#include +#include #include "extern.h" -static int fd = -1; - -/* - * Modified version of logwtmp that holds wtmp file open - * after first call, for use with ftp (which may chroot - * after login, but before logout). - */ void -ftpd_logwtmp(line, name, addr) - char *line, *name; - struct sockaddr *addr; +ftpd_logwtmp(char *id, char *user, struct sockaddr *addr) { -#if (!defined(__BEOS__) && !defined(__HAIKU__)) - struct utmp ut; - struct stat buf; - char host[UT_HOSTSIZE]; + struct utmpx ut; - if (addr == NULL) - host[0] = '\0'; - else - realhostname_sa(host, sizeof(host), addr, addr->sa_len); + memset(&ut, 0, sizeof(ut)); - if (fd < 0 && (fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) < 0) - return; - if (fstat(fd, &buf) == 0) { - (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line)); - (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name)); - (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host)); - ut.ut_time = _time_to_time32(time(NULL)); - if (write(fd, &ut, sizeof(struct utmp)) != - sizeof(struct utmp)) - (void)ftruncate(fd, buf.st_size); + if (user != NULL) { + /* Log in. */ + ut.ut_type = USER_PROCESS; + (void)strncpy(ut.ut_user, user, sizeof(ut.ut_user)); + if (addr != NULL) + realhostname_sa(ut.ut_host, sizeof(ut.ut_host), + addr, addr->sa_len); + } else { + /* Log out. */ + ut.ut_type = DEAD_PROCESS; } -#endif + + ut.ut_pid = getpid(); + gettimeofday(&ut.ut_tv, NULL); + (void)strncpy(ut.ut_id, id, sizeof(ut.ut_id)); + (void)strncpy(ut.ut_line, "ftpd", sizeof(ut.ut_line)); + + pututxline(&ut); } diff --git a/src/bin/network/ftpd/pathnames.h b/src/bin/network/ftpd/pathnames.h index 24b74645ba..75bec0d18a 100644 --- a/src/bin/network/ftpd/pathnames.h +++ b/src/bin/network/ftpd/pathnames.h @@ -1,4 +1,6 @@ -/* +/*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * @@ -10,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -31,7 +29,6 @@ * SUCH DAMAGE. * * @(#)pathnames.h 8.1 (Berkeley) 6/4/93 - * $FreeBSD: src/libexec/ftpd/pathnames.h,v 1.11 1999/08/28 00:09:31 peter Exp $ */ #include diff --git a/src/bin/network/ftpd/popen.c b/src/bin/network/ftpd/popen.c index b89377408f..404d209cf4 100644 --- a/src/bin/network/ftpd/popen.c +++ b/src/bin/network/ftpd/popen.c @@ -1,4 +1,6 @@ -/* +/*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1988, 1993, 1994 * The Regents of the University of California. All rights reserved. * @@ -13,11 +15,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -41,8 +39,6 @@ static char sccsid[] = "@(#)popen.c 8.3 (Berkeley) 4/6/94"; #endif /* not lint */ #include -__FBSDID("$FreeBSD: src/libexec/ftpd/popen.c,v 1.26 2004/11/18 13:46:29 yar Exp $"); - #include #include #include @@ -64,7 +60,7 @@ __FBSDID("$FreeBSD: src/libexec/ftpd/popen.c,v 1.26 2004/11/18 13:46:29 yar Exp #define MAXGLOBARGS 1000 /* - * Special version of popen which avoids call to shell. This ensures noone + * Special version of popen which avoids call to shell. This ensures no one * may create a pipe to a hidden program as a side effect of a list or dir * command. */ @@ -147,6 +143,9 @@ ftpd_popen(char *program, char *type) (void)close(pdes[1]); } #ifdef BUILTIN_LS + /* Drop privileges before proceeding */ + if (getuid() != geteuid() && setuid(geteuid()) < 0) + _exit(1); if (strcmp(gargv[0], _PATH_LS) == 0) { /* Reset getopt for ls_main() */ optreset = optind = optopt = 1;