ftpd: Synchronize with FreeBSD 13.3.

This commit is contained in:
Augustin Cavalier
2024-05-28 16:08:22 -04:00
parent 45383846d8
commit 0c84b78dd3
7 changed files with 201 additions and 194 deletions
+1 -2
View File
@@ -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. */ /* config.h. Generated automatically by configure. */
@@ -199,7 +198,7 @@
#define HAVE_SOCKLEN_T 1 #define HAVE_SOCKLEN_T 1
/* Define if AF_INET6 exists in <sys/socket.h> */ /* Define if AF_INET6 exists in <sys/socket.h> */
/* #define HAVE_AF_INET6 1 */ #define HAVE_AF_INET6 1
/* Define if `struct sockaddr_in6' exists in <netinet/in.h> */ /* Define if `struct sockaddr_in6' exists in <netinet/in.h> */
#define HAVE_SOCKADDR_IN6 1 #define HAVE_SOCKADDR_IN6 1
+33 -7
View File
@@ -1,4 +1,6 @@
/*- /*-
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 1992, 1993 * Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved. * The Regents of the University of California. All rights reserved.
* *
@@ -10,11 +12,7 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software * 3. Neither the name of the University nor the names of its contributors
* 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
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@@ -31,7 +29,6 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)extern.h 8.2 (Berkeley) 4/4/94 * @(#)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 <sys/types.h> #include <sys/types.h>
@@ -46,7 +43,7 @@ void fatalerror(char *);
void ftpd_logwtmp(char *, char *, struct sockaddr *addr); void ftpd_logwtmp(char *, char *, struct sockaddr *addr);
int ftpd_pclose(FILE *); int ftpd_pclose(FILE *);
FILE *ftpd_popen(char *, char *); 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 lreply(int, const char *, ...) __printflike(2, 3);
void makedir(char *); void makedir(char *);
void nack(char *); void nack(char *);
@@ -70,6 +67,35 @@ void yyerror(char *);
int yyparse(void); int yyparse(void);
int ls_main(int, char **); 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 <arpa/ftp.h> included from ftpd.c */
extern int usedefault;
struct sockaddr_in; struct sockaddr_in;
struct sockaddr_in6; struct sockaddr_in6;
union sockunion { union sockunion {
+15 -44
View File
@@ -1,4 +1,6 @@
/* /*-
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 1985, 1988, 1993, 1994 * Copyright (c) 1985, 1988, 1993, 1994
* The Regents of the University of California. All rights reserved. * The Regents of the University of California. All rights reserved.
* *
@@ -10,11 +12,7 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software * 3. Neither the name of the University nor the names of its contributors
* 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
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@@ -47,8 +45,6 @@ static char sccsid[] = "@(#)ftpcmd.y 8.3 (Berkeley) 4/6/94";
#endif /* not lint */ #endif /* not lint */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/libexec/ftpd/ftpcmd.y,v 1.66 2007/04/18 22:43:39 yar Exp $");
#include <sys/param.h> #include <sys/param.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/stat.h> #include <sys/stat.h>
@@ -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 "extern.h"
#include "pathnames.h" #include "pathnames.h"
extern union sockunion data_dest, his_addr; #define yylex ftpcmd_yylex
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 <arpa/ftp.h> included from ftpd.c */
off_t restart_point; off_t restart_point;
@@ -110,8 +83,6 @@ static int state;
char cbuf[512]; char cbuf[512];
char *fromname = NULL; char *fromname = NULL;
extern int epsvall;
#define CMD 0 /* beginning of command */ #define CMD 0 /* beginning of command */
#define ARGS 1 /* expect miscellaneous arguments */ #define ARGS 1 /* expect miscellaneous arguments */
#define STR1 2 /* expect SP followed by STRING */ #define STR1 2 /* expect SP followed by STRING */
@@ -252,8 +223,8 @@ static int port_check(const char *);
#ifdef INET6 #ifdef INET6
static int port_check_v6(const char *); static int port_check_v6(const char *);
#endif #endif
static int check_login1(void);
static void sizecmd(char *); static void sizecmd(char *);
static int check_login1(void);
static void toolong(int); static void toolong(int);
#ifdef INET6 #ifdef INET6
static void v4map_data_dest(void); static void v4map_data_dest(void);
@@ -542,7 +513,7 @@ cmd
case MODE_S: case MODE_S:
reply(200, "MODE S accepted."); reply(200, "MODE S accepted.");
break; break;
default: default:
reply(502, "Unimplemented MODE type."); reply(502, "Unimplemented MODE type.");
} }
@@ -915,7 +886,7 @@ rcmd
free(fromname); free(fromname);
fromname = NULL; fromname = NULL;
restart_point = $4.o; restart_point = $4.o;
reply(350, "Restarting at %lld. %s", reply(350, "Restarting at %jd. %s",
(intmax_t)restart_point, (intmax_t)restart_point,
"Send STORE or RETRIEVE to initiate transfer."); "Send STORE or RETRIEVE to initiate transfer.");
} }
@@ -1194,10 +1165,10 @@ lookup(struct tab *p, char *cmd)
#include <arpa/telnet.h> #include <arpa/telnet.h>
/* /*
* 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 * int
ftpd_getline(char *s, int n, FILE *iop) get_line(char *s, int n, FILE *iop)
{ {
int c; int c;
register char *cs; register char *cs;
@@ -1316,7 +1287,7 @@ yylex(void)
case CMD: case CMD:
(void) signal(SIGALRM, toolong); (void) signal(SIGALRM, toolong);
(void) alarm(timeout); (void) alarm(timeout);
n = ftpd_getline(cbuf, sizeof(cbuf)-1, stdin); n = get_line(cbuf, sizeof(cbuf)-1, stdin);
if (n == -1) { if (n == -1) {
reply(221, "You could at least say goodbye."); reply(221, "You could at least say goodbye.");
dologout(0); dologout(0);
@@ -1624,7 +1595,7 @@ sizecmd(char *filename)
else if (!S_ISREG(stbuf.st_mode)) else if (!S_ISREG(stbuf.st_mode))
reply(550, "%s: not a plain file.", filename); reply(550, "%s: not a plain file.", filename);
else else
reply(213, "%lld", (intmax_t)stbuf.st_size); reply(213, "%jd", (intmax_t)stbuf.st_size);
break; } break; }
case TYPE_A: { case TYPE_A: {
FILE *fin; FILE *fin;
@@ -1658,7 +1629,7 @@ sizecmd(char *filename)
} }
(void) fclose(fin); (void) fclose(fin);
reply(213, "%lld", (intmax_t)count); reply(213, "%jd", (intmax_t)count);
break; } break; }
default: default:
reply(504, "SIZE not implemented for type %s.", 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 * Avoid expanding to a pathname including '\r' or '\n' in order to
* not disrupt the FTP protocol. * not disrupt the FTP protocol.
* The expansion found must be unique. * 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 * Problem: this production is used for all pathname
* processing, but only gives a 550 error reply. * processing, but only gives a 550 error reply.
+113 -79
View File
@@ -1,4 +1,6 @@
/* /*-
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994 * Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994
* The Regents of the University of California. All rights reserved. * The Regents of the University of California. All rights reserved.
* *
@@ -10,11 +12,7 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software * 3. Neither the name of the University nor the names of its contributors
* 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
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@@ -46,14 +44,12 @@ static char sccsid[] = "@(#)ftpd.c 8.4 (Berkeley) 4/16/94";
#endif /* not lint */ #endif /* not lint */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/libexec/ftpd/ftpd.c,v 1.212 2007/04/18 22:43:39 yar Exp $");
/* /*
* FTP server. * FTP server.
*/ */
#include <sys/param.h> #include <sys/param.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
//#include <sys/mman.h> #include <sys/mman.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/time.h> #include <sys/time.h>
@@ -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"; static char version[] = "Version 6.00LS";
#undef main #undef main
extern off_t restart_point;
extern char cbuf[];
union sockunion ctrl_addr; union sockunion ctrl_addr;
union sockunion data_source; union sockunion data_source;
union sockunion data_dest; 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 noguestretr = 0; /* RETR command is disabled for anon users. */
int noguestmkd = 0; /* MKD 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 noguestmod = 1; /* anon users may not modify existing files. */
int use_blacklist = 0;
off_t file_size; off_t file_size;
off_t byte_count; off_t byte_count;
@@ -182,8 +176,7 @@ static struct ftphost {
char remotehost[NI_MAXHOST]; char remotehost[NI_MAXHOST];
char *ident = NULL; char *ident = NULL;
static char ttyline[20]; static char wtmpid[20];
char *tty = ttyline; /* for klogin */
#ifdef USE_PAM #ifdef USE_PAM
static int auth_pam(struct passwd**, const char*); static int auth_pam(struct passwd**, const char*);
@@ -252,7 +245,7 @@ static void sigurg(int);
static void maskurg(int); static void maskurg(int);
static void flagxfer(int); static void flagxfer(int);
static int myoob(void); 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 FILE *dataconn(char *, off_t, char *);
static void dolog(struct sockaddr *); static void dolog(struct sockaddr *);
static void end_login(void); static void end_login(void);
@@ -276,7 +269,7 @@ int
main(int argc, char *argv[], char **envp) main(int argc, char *argv[], char **envp)
{ {
socklen_t addrlen; socklen_t addrlen;
int ch, on = 1, tos; int ch, on = 1, tos, s = STDIN_FILENO;
char *cp, line[LINE_MAX]; char *cp, line[LINE_MAX];
FILE *fd; FILE *fd;
char *bindname = NULL; char *bindname = NULL;
@@ -303,7 +296,7 @@ main(int argc, char *argv[], char **envp)
openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP); openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
while ((ch = getopt(argc, argv, while ((ch = getopt(argc, argv,
"468a:AdDEhlmMoOp:P:rRSt:T:u:UvW")) != -1) { "468a:ABdDEhlmMoOp:P:rRSt:T:u:UvW")) != -1) {
switch (ch) { switch (ch) {
case '4': case '4':
family = (family == AF_INET6) ? AF_UNSPEC : AF_INET; family = (family == AF_INET6) ? AF_UNSPEC : AF_INET;
@@ -325,6 +318,14 @@ main(int argc, char *argv[], char **envp)
anon_only = 1; anon_only = 1;
break; break;
case 'B':
#ifdef USE_BLACKLIST
use_blacklist = 1;
#else
syslog(LOG_WARNING, "not compiled with USE_BLACKLIST support");
#endif
break;
case 'd': case 'd':
ftpdebug++; ftpdebug++;
break; 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) { if (daemon_mode) {
int *ctl_sock, fd, maxfd = -1, nfds, i; int *ctl_sock, fd, maxfd = -1, nfds, i;
fd_set defreadfds, readfds; fd_set defreadfds, readfds;
@@ -502,8 +507,8 @@ main(int argc, char *argv[], char **envp)
switch (pid = fork()) { switch (pid = fork()) {
case 0: case 0:
/* child */ /* child */
(void) dup2(fd, 0); (void) dup2(fd, s);
(void) dup2(fd, 1); (void) dup2(fd, STDOUT_FILENO);
(void) close(fd); (void) close(fd);
for (i = 1; i <= *ctl_sock; i++) for (i = 1; i <= *ctl_sock; i++)
close(ctl_sock[i]); close(ctl_sock[i]);
@@ -520,7 +525,7 @@ main(int argc, char *argv[], char **envp)
} }
} else { } else {
addrlen = sizeof(his_addr); 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]); syslog(LOG_ERR, "getpeername (%s): %m",argv[0]);
exit(1); exit(1);
} }
@@ -555,7 +560,7 @@ gotchild:
(void)sigaction(SIGPIPE, &sa, NULL); (void)sigaction(SIGPIPE, &sa, NULL);
addrlen = sizeof(ctrl_addr); 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]); syslog(LOG_ERR, "getsockname (%s): %m",argv[0]);
exit(1); exit(1);
} }
@@ -568,7 +573,7 @@ gotchild:
if (ctrl_addr.su_family == AF_INET) if (ctrl_addr.su_family == AF_INET)
{ {
tos = IPTOS_LOWDELAY; 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"); syslog(LOG_WARNING, "control setsockopt (IP_TOS): %m");
} }
#endif #endif
@@ -576,22 +581,21 @@ gotchild:
* Disable Nagle on the control channel so that we don't have to wait * Disable Nagle on the control channel so that we don't have to wait
* for peer's ACK before issuing our next reply. * 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"); syslog(LOG_WARNING, "control setsockopt (TCP_NODELAY): %m");
data_source.su_port = htons(ntohs(ctrl_addr.su_port) - 1); data_source.su_port = htons(ntohs(ctrl_addr.su_port) - 1);
/* set this here so klogin can use it... */ (void)snprintf(wtmpid, sizeof(wtmpid), "%xftpd", getpid());
(void)snprintf(ttyline, sizeof(ttyline), "ftp%d", (int)getpid());
/* Try to handle urgent data inline */ /* Try to handle urgent data inline */
#ifdef SO_OOBINLINE #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"); syslog(LOG_WARNING, "control setsockopt (SO_OOBINLINE): %m");
#endif #endif
#ifdef F_SETOWN #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"); syslog(LOG_ERR, "fcntl F_SETOWN: %m");
#endif #endif
dolog((struct sockaddr *)&his_addr); dolog((struct sockaddr *)&his_addr);
@@ -1009,6 +1013,7 @@ static char curname[MAXLOGNAME]; /* current USER name */
void void
user(char *name) user(char *name)
{ {
int ecode;
char *cp, *shell; char *cp, *shell;
if (logged_in) { if (logged_in) {
@@ -1029,8 +1034,11 @@ user(char *name)
pw = sgetpwnam("ftp"); pw = sgetpwnam("ftp");
#endif #endif
if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) { if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) {
if (checkuser(_PATH_FTPUSERS, "ftp", 0, NULL) || if (checkuser(_PATH_FTPUSERS, "ftp", 0, NULL, &ecode) ||
checkuser(_PATH_FTPUSERS, "anonymous", 0, NULL)) (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); reply(530, "User %s access denied.", name);
else if (pw != NULL) { else if (pw != NULL) {
guest = 1; guest = 1;
@@ -1048,7 +1056,7 @@ user(char *name)
reply(530, "Sorry, only anonymous ftp allowed."); reply(530, "Sorry, only anonymous ftp allowed.");
return; return;
} }
if ((pw = sgetpwnam(name))) { if ((pw = sgetpwnam(name))) {
if ((shell = pw->pw_shell) == NULL || *shell == 0) if ((shell = pw->pw_shell) == NULL || *shell == 0)
shell = _PATH_BSHELL; shell = _PATH_BSHELL;
@@ -1058,7 +1066,9 @@ user(char *name)
break; break;
endusershell(); 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); reply(530, "User %s access denied.", name);
if (logging) if (logging)
syslog(LOG_NOTICE, syslog(LOG_NOTICE,
@@ -1103,13 +1113,15 @@ user(char *name)
* of the matching line in "residue" if not NULL. * of the matching line in "residue" if not NULL.
*/ */
static int static int
checkuser(char *fname, char *name, int pwset, char **residue) checkuser(char *fname, char *name, int pwset, char **residue, int *ecode)
{ {
FILE *fd; FILE *fd;
int found = 0; int found = 0;
size_t len; size_t len;
char *line, *mp, *p; char *line, *mp, *p;
if (ecode != NULL)
*ecode = 0;
if ((fd = fopen(fname, "r")) != NULL) { if ((fd = fopen(fname, "r")) != NULL) {
while (!found && (line = fgetln(fd, &len)) != NULL) { while (!found && (line = fgetln(fd, &len)) != NULL) {
/* skip comments */ /* skip comments */
@@ -1178,7 +1190,8 @@ nextline:
free(mp); free(mp);
} }
(void) fclose(fd); (void) fclose(fd);
} } else if (ecode != NULL)
*ecode = errno;
return (found); return (found);
} }
@@ -1194,14 +1207,14 @@ end_login(void)
#endif #endif
(void) seteuid(0); (void) seteuid(0);
if (logged_in && dowtmp)
ftpd_logwtmp(ttyline, "", NULL);
pw = NULL;
#ifdef LOGIN_CAP #ifdef LOGIN_CAP
setusercontext(NULL, getpwuid(0), 0, setusercontext(NULL, getpwuid(0), 0, LOGIN_SETALL & ~(LOGIN_SETLOGIN |
LOGIN_SETPRIORITY|LOGIN_SETRESOURCES|LOGIN_SETUMASK| LOGIN_SETUSER | LOGIN_SETGROUP | LOGIN_SETPATH |
LOGIN_SETMAC); LOGIN_SETENV));
#endif #endif
if (logged_in && dowtmp)
ftpd_logwtmp(wtmpid, NULL, NULL);
pw = NULL;
#ifdef USE_PAM #ifdef USE_PAM
if (pamh) { if (pamh) {
if ((e = pam_setcred(pamh, PAM_DELETE_CRED)) != PAM_SUCCESS) if ((e = pam_setcred(pamh, PAM_DELETE_CRED)) != PAM_SUCCESS)
@@ -1375,7 +1388,7 @@ auth_pam(struct passwd **ppw, const char *pass)
void void
pass(char *passwd) pass(char *passwd)
{ {
int rval; int rval, ecode;
FILE *fd; FILE *fd;
#ifdef LOGIN_CAP #ifdef LOGIN_CAP
login_cap_t *lc = NULL; login_cap_t *lc = NULL;
@@ -1495,12 +1508,36 @@ skip:
} }
#endif #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) if (dowtmp)
ftpd_logwtmp(ttyline, pw->pw_name, ftpd_logwtmp(wtmpid, pw->pw_name,
(struct sockaddr *)&his_addr); (struct sockaddr *)&his_addr);
logged_in = 1; logged_in = 1;
#ifdef LOGIN_CAP
setusercontext(lc, pw, 0, LOGIN_SETRESOURCES);
#endif
if (guest && stats && statfd < 0) { if (guest && stats && statfd < 0) {
#ifdef VIRTUAL_HOSTING #ifdef VIRTUAL_HOSTING
statfd = open(thishost->statfile, O_WRONLY|O_APPEND); statfd = open(thishost->statfile, O_WRONLY|O_APPEND);
@@ -1511,13 +1548,6 @@ skip:
stats = 0; 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__)) #if (!defined(__BEOS__) && !defined(__HAIKU__))
/* /*
* For a chrooted local user, * For a chrooted local user,
@@ -1579,13 +1609,20 @@ skip:
* (uid 0 has no root power over NFS if not mapped explicitly.) * (uid 0 has no root power over NFS if not mapped explicitly.)
*/ */
if (seteuid(pw->pw_uid) < 0) { if (seteuid(pw->pw_uid) < 0) {
reply(550, "Can't set uid."); if (guest || dochroot) {
goto bad; 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 (chdir(homedir) < 0) {
if (guest || dochroot) { if (guest || dochroot) {
reply(550, "Can't change to base directory."); fatalerror("Can't change to base directory.");
goto bad;
} else { } else {
if (chdir("/") < 0) { if (chdir("/") < 0) {
reply(550, "Root is inaccessible."); reply(550, "Root is inaccessible.");
@@ -1679,14 +1716,14 @@ retrieve(char *cmd, char *name)
struct stat st; struct stat st;
int (*closefunc)(FILE *); int (*closefunc)(FILE *);
time_t start; time_t start;
char line[BUFSIZ];
if (cmd == 0) { if (cmd == 0) {
fin = fopen(name, "r"), closefunc = fclose; fin = fopen(name, "r"), closefunc = fclose;
st.st_size = 0; st.st_size = 0;
} else { } 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; fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose;
st.st_size = -1; st.st_size = -1;
st.st_blksize = BUFSIZ; st.st_blksize = BUFSIZ;
@@ -1926,7 +1963,7 @@ dataconn(char *name, off_t size, char *mode)
byte_count = 0; byte_count = 0;
if (size != -1) if (size != -1)
(void) snprintf(sizebuf, sizeof(sizebuf), (void) snprintf(sizebuf, sizeof(sizebuf),
" (%lld bytes)", (intmax_t)size); " (%jd bytes)", (intmax_t)size);
else else
*sizebuf = '\0'; *sizebuf = '\0';
if (pdata >= 0) { if (pdata >= 0) {
@@ -2056,7 +2093,7 @@ pdata_err:
} while (0) } 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. * encapsulation of the data subject to Mode, Structure, and Type.
* *
* NB: Form isn't handled. * NB: Form isn't handled.
@@ -2359,8 +2396,8 @@ statfilecmd(char *filename)
(void)snprintf(line, sizeof(line), _PATH_LS " -lgA %s", filename); (void)snprintf(line, sizeof(line), _PATH_LS " -lgA %s", filename);
fin = ftpd_popen(line, "r"); fin = ftpd_popen(line, "r");
if (fin == NULL) { if (fin == NULL) {
perror_reply(551, filename); perror_reply(551, filename);
return; return;
} }
lreply(code, "Status of %s:", filename); lreply(code, "Status of %s:", filename);
atstart = 1; atstart = 1;
@@ -2766,7 +2803,12 @@ dologout(int status)
if (logged_in && dowtmp) { if (logged_in && dowtmp) {
(void) seteuid(0); (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 */ /* beware of flushing buffers after a SIGPIPE */
_exit(status); _exit(status);
@@ -2830,13 +2872,13 @@ myoob(void)
return (0); return (0);
} }
cp = tmpline; cp = tmpline;
ret = getline(cp, 7, stdin); ret = get_line(cp, 7, stdin);
if (ret == -1) { if (ret == -1) {
reply(221, "You could at least say goodbye."); reply(221, "You could at least say goodbye.");
dologout(0); dologout(0);
} else if (ret == -2) { } else if (ret == -2) {
/* Ignore truncated command. */ /* Ignore truncated command. */
return (0); return (0);
} }
upper(cp); upper(cp);
if (strcmp(cp, "ABOR\r\n") == 0) { if (strcmp(cp, "ABOR\r\n") == 0) {
@@ -2848,10 +2890,10 @@ myoob(void)
if (strcmp(cp, "STAT\r\n") == 0) { if (strcmp(cp, "STAT\r\n") == 0) {
tmpline[0] = '\0'; tmpline[0] = '\0';
if (file_size != -1) 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); (intmax_t)byte_count, (intmax_t)file_size);
else else
reply(213, "Status: %lld bytes transferred.", reply(213, "Status: %jd bytes transferred.",
(intmax_t)byte_count); (intmax_t)byte_count);
} }
return (0); return (0);
@@ -2919,14 +2961,12 @@ passive(void)
goto pasv_error; goto pasv_error;
if (pasv_addr.su_family == AF_INET) if (pasv_addr.su_family == AF_INET)
a = (char *) &pasv_addr.su_sin.sin_addr; a = (char *) &pasv_addr.su_sin.sin_addr;
#ifdef HAVE_AF_INET6
else if (pasv_addr.su_family == AF_INET6 && else if (pasv_addr.su_family == AF_INET6 &&
IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr)) IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr))
a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12]; a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12];
#endif
else else
goto pasv_error; goto pasv_error;
p = (char *) &pasv_addr.su_port; p = (char *) &pasv_addr.su_port;
#define UC(b) (((int) b) & 0xff) #define UC(b) (((int) b) & 0xff)
@@ -2985,7 +3025,7 @@ long_passive(char *cmd, int pf)
return; return;
} }
} }
pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0); pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0);
if (pdata < 0) { if (pdata < 0) {
perror_reply(425, "Can't open passive connection"); perror_reply(425, "Can't open passive connection");
@@ -3039,15 +3079,12 @@ long_passive(char *cmd, int pf)
switch (pasv_addr.su_family) { switch (pasv_addr.su_family) {
case AF_INET: case AF_INET:
a = (char *) &pasv_addr.su_sin.sin_addr; a = (char *) &pasv_addr.su_sin.sin_addr;
#ifdef HAVE_AF_INET6
v4_reply: v4_reply:
#endif
reply(228, reply(228,
"Entering Long Passive Mode (%d,%d,%d,%d,%d,%d,%d,%d,%d)", "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]), 4, 4, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
2, UC(p[0]), UC(p[1])); 2, UC(p[0]), UC(p[1]));
return; return;
#ifdef HAVE_AF_INET6
case AF_INET6: case AF_INET6:
if (IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr)) { if (IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr)) {
a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12]; 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]), UC(a[12]), UC(a[13]), UC(a[14]), UC(a[15]),
2, UC(p[0]), UC(p[1])); 2, UC(p[0]), UC(p[1]));
return; return;
#endif
} }
} else if (strcmp(cmd, "EPSV") == 0) { } else if (strcmp(cmd, "EPSV") == 0) {
switch (pasv_addr.su_family) { switch (pasv_addr.su_family) {
@@ -3124,7 +3160,7 @@ guniquefd(char *local, char **name)
/* -4 is for the .nn<null> we put on the end below */ /* -4 is for the .nn<null> we put on the end below */
(void) snprintf(new, sizeof(new) - 4, "%s", local); (void) snprintf(new, sizeof(new) - 4, "%s", local);
cp = new + strlen(new); cp = new + strlen(new);
/* /*
* Don't generate dotfile unless requested explicitly. * Don't generate dotfile unless requested explicitly.
* This covers the case when basename gets truncated off * This covers the case when basename gets truncated off
* by buffer size. * by buffer size.
@@ -3356,7 +3392,7 @@ logcmd(char *cmd, char *file1, char *file2, off_t cnt)
if (file2) if (file2)
appendf(&msg, " %s", file2); appendf(&msg, " %s", file2);
if (cnt >= 0) if (cnt >= 0)
appendf(&msg, " = %lld bytes", (intmax_t)cnt); appendf(&msg, " = %jd bytes", (intmax_t)cnt);
appendf(&msg, " (wd: %s", wd); appendf(&msg, " (wd: %s", wd);
if (guest || dochroot) if (guest || dochroot)
appendf(&msg, "; chrooted"); 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); syslog(LOG_NOTICE, "realpath failed on %s: %m", path);
return; 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, ctime(&now)+4, ident, remotehost,
path, (intmax_t)size, path, (intmax_t)size,
(long)(now - start + (now == start))); (long)(now - start + (now == start)));
@@ -3452,14 +3488,12 @@ socksetup(int af, char *bindname, const char *bindport)
&on, sizeof(on)) < 0) &on, sizeof(on)) < 0)
syslog(LOG_WARNING, syslog(LOG_WARNING,
"control setsockopt (SO_REUSEADDR): %m"); "control setsockopt (SO_REUSEADDR): %m");
#ifdef HAVE_AF_INET6
if (r->ai_family == AF_INET6) { if (r->ai_family == AF_INET6) {
if (setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY, if (setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY,
&on, sizeof(on)) < 0) &on, sizeof(on)) < 0)
syslog(LOG_WARNING, syslog(LOG_WARNING,
"control setsockopt (IPV6_V6ONLY): %m"); "control setsockopt (IPV6_V6ONLY): %m");
} }
#endif
if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) { if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) {
syslog(LOG_DEBUG, "control bind: %m"); syslog(LOG_DEBUG, "control bind: %m");
close(*s); close(*s);
+27 -46
View File
@@ -1,4 +1,6 @@
/* /*-
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 1988, 1993 * Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved. * The Regents of the University of California. All rights reserved.
* *
@@ -10,11 +12,7 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software * 3. Neither the name of the University nor the names of its contributors
* 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
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@@ -38,59 +36,42 @@ static char sccsid[] = "@(#)logwtmp.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint */ #endif /* not lint */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/libexec/ftpd/logwtmp.c,v 1.13 2004/11/18 13:46:29 yar Exp $");
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <fcntl.h> #include <libutil.h>
#include <time.h>
#if (!defined(__BEOS__) && !defined(__HAIKU__))
#include <timeconv.h>
#include <utmp.h>
#endif
#include <netdb.h>
#include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <libutil.h> #include <unistd.h>
#include <utmpx.h>
#include "extern.h" #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 void
ftpd_logwtmp(line, name, addr) ftpd_logwtmp(char *id, char *user, struct sockaddr *addr)
char *line, *name;
struct sockaddr *addr;
{ {
#if (!defined(__BEOS__) && !defined(__HAIKU__)) struct utmpx ut;
struct utmp ut;
struct stat buf;
char host[UT_HOSTSIZE];
if (addr == NULL) memset(&ut, 0, sizeof(ut));
host[0] = '\0';
else
realhostname_sa(host, sizeof(host), addr, addr->sa_len);
if (fd < 0 && (fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) < 0) if (user != NULL) {
return; /* Log in. */
if (fstat(fd, &buf) == 0) { ut.ut_type = USER_PROCESS;
(void)strncpy(ut.ut_line, line, sizeof(ut.ut_line)); (void)strncpy(ut.ut_user, user, sizeof(ut.ut_user));
(void)strncpy(ut.ut_name, name, sizeof(ut.ut_name)); if (addr != NULL)
(void)strncpy(ut.ut_host, host, sizeof(ut.ut_host)); realhostname_sa(ut.ut_host, sizeof(ut.ut_host),
ut.ut_time = _time_to_time32(time(NULL)); addr, addr->sa_len);
if (write(fd, &ut, sizeof(struct utmp)) != } else {
sizeof(struct utmp)) /* Log out. */
(void)ftruncate(fd, buf.st_size); 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);
} }
+4 -7
View File
@@ -1,4 +1,6 @@
/* /*-
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 1989, 1993 * Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved. * The Regents of the University of California. All rights reserved.
* *
@@ -10,11 +12,7 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software * 3. Neither the name of the University nor the names of its contributors
* 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
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@@ -31,7 +29,6 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)pathnames.h 8.1 (Berkeley) 6/4/93 * @(#)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 <paths.h> #include <paths.h>
+8 -9
View File
@@ -1,4 +1,6 @@
/* /*-
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 1988, 1993, 1994 * Copyright (c) 1988, 1993, 1994
* The Regents of the University of California. All rights reserved. * The Regents of the University of California. All rights reserved.
* *
@@ -13,11 +15,7 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software * 3. Neither the name of the University nor the names of its contributors
* 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
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@@ -41,8 +39,6 @@ static char sccsid[] = "@(#)popen.c 8.3 (Berkeley) 4/6/94";
#endif /* not lint */ #endif /* not lint */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/libexec/ftpd/popen.c,v 1.26 2004/11/18 13:46:29 yar Exp $");
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <netinet/in.h> #include <netinet/in.h>
@@ -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 #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 * may create a pipe to a hidden program as a side effect of a list or dir
* command. * command.
*/ */
@@ -147,6 +143,9 @@ ftpd_popen(char *program, char *type)
(void)close(pdes[1]); (void)close(pdes[1]);
} }
#ifdef BUILTIN_LS #ifdef BUILTIN_LS
/* Drop privileges before proceeding */
if (getuid() != geteuid() && setuid(geteuid()) < 0)
_exit(1);
if (strcmp(gargv[0], _PATH_LS) == 0) { if (strcmp(gargv[0], _PATH_LS) == 0) {
/* Reset getopt for ls_main() */ /* Reset getopt for ls_main() */
optreset = optind = optopt = 1; optreset = optind = optopt = 1;