ftpd.c revision 1.193
1/*	$OpenBSD: ftpd.c,v 1.193 2011/02/09 21:13:31 millert Exp $	*/
2/*	$NetBSD: ftpd.c,v 1.15 1995/06/03 22:46:47 mycroft Exp $	*/
3
4/*
5 * Copyright (C) 1997 and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*
34 * Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994
35 *	The Regents of the University of California.  All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 *    notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 *    notice, this list of conditions and the following disclaimer in the
44 *    documentation and/or other materials provided with the distribution.
45 * 3. Neither the name of the University nor the names of its contributors
46 *    may be used to endorse or promote products derived from this software
47 *    without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 */
61
62/*
63 * FTP server.
64 */
65#include <sys/param.h>
66#include <sys/stat.h>
67#include <sys/ioctl.h>
68#include <sys/socket.h>
69#include <sys/wait.h>
70#include <sys/mman.h>
71
72#include <netinet/in.h>
73#include <netinet/in_systm.h>
74#include <netinet/ip.h>
75#include <netinet/tcp.h>
76
77#define	FTP_NAMES
78#include <arpa/ftp.h>
79#include <arpa/inet.h>
80#include <arpa/telnet.h>
81
82#include <bsd_auth.h>
83#include <ctype.h>
84#include <dirent.h>
85#include <errno.h>
86#include <fcntl.h>
87#include <glob.h>
88#include <limits.h>
89#include <login_cap.h>
90#include <netdb.h>
91#include <pwd.h>
92#include <signal.h>
93#include <stdarg.h>
94#include <stdio.h>
95#include <stdlib.h>
96#include <string.h>
97#include <syslog.h>
98#include <time.h>
99#include <vis.h>
100#include <unistd.h>
101#include <util.h>
102#include <utmp.h>
103#include <poll.h>
104
105#if defined(TCPWRAPPERS)
106#include <tcpd.h>
107#endif	/* TCPWRAPPERS */
108
109#include "pathnames.h"
110#include "monitor.h"
111#include "extern.h"
112
113extern	off_t restart_point;
114extern	char cbuf[];
115
116union sockunion ctrl_addr;
117union sockunion data_source;
118union sockunion data_dest;
119union sockunion his_addr;
120union sockunion pasv_addr;
121
122sigset_t allsigs;
123
124int	daemon_mode = 0;
125int	data;
126int	logged_in;
127struct	passwd *pw;
128int	debug = 0;
129int	timeout = 900;    /* timeout after 15 minutes of inactivity */
130int	maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */
131int	logging;
132int	anon_ok = 1;
133int	anon_only = 0;
134int	multihome = 0;
135int	guest;
136int	stats;
137int	statfd = -1;
138int	portcheck = 1;
139int	dochroot;
140int	type;
141int	form;
142int	stru;			/* avoid C keyword */
143int	mode;
144int	doutmp = 0;		/* update utmp file */
145int	usedefault = 1;		/* for data transfers */
146int	pdata = -1;		/* for passive mode */
147int	family = AF_UNSPEC;
148volatile sig_atomic_t transflag;
149off_t	file_size;
150off_t	byte_count;
151#if !defined(CMASK) || CMASK == 0
152#undef CMASK
153#define CMASK 022
154#endif
155mode_t	defumask = CMASK;		/* default umask value */
156int	umaskchange = 1;		/* allow user to change umask value. */
157char	tmpline[7];
158char	hostname[MAXHOSTNAMELEN];
159char	remotehost[MAXHOSTNAMELEN];
160char	dhostname[MAXHOSTNAMELEN];
161char	*guestpw;
162char	ttyline[20];
163#if 0
164char	*tty = ttyline;		/* for klogin */
165#endif
166static struct utmp utmp;	/* for utmp */
167static	login_cap_t *lc;
168static	auth_session_t *as;
169static	volatile sig_atomic_t recvurg;
170
171#if defined(TCPWRAPPERS)
172int	allow_severity = LOG_INFO;
173int	deny_severity = LOG_NOTICE;
174#endif	/* TCPWRAPPERS */
175
176int epsvall = 0;
177
178/*
179 * Timeout intervals for retrying connections
180 * to hosts that don't accept PORT cmds.  This
181 * is a kludge, but given the problems with TCP...
182 */
183#define	SWAITMAX	90	/* wait at most 90 seconds */
184#define	SWAITINT	5	/* interval between retries */
185
186int	swaitmax = SWAITMAX;
187int	swaitint = SWAITINT;
188
189#ifdef HASSETPROCTITLE
190char	proctitle[BUFSIZ];	/* initial part of title */
191#endif /* HASSETPROCTITLE */
192
193#define LOGCMD(cmd, file) \
194	if (logging > 1) \
195	    syslog(LOG_INFO,"%s %s%s", cmd, \
196		*(file) == '/' ? "" : curdir(), file);
197#define LOGCMD2(cmd, file1, file2) \
198	 if (logging > 1) \
199	    syslog(LOG_INFO,"%s %s%s %s%s", cmd, \
200		*(file1) == '/' ? "" : curdir(), file1, \
201		*(file2) == '/' ? "" : curdir(), file2);
202#define LOGBYTES(cmd, file, cnt) \
203	if (logging > 1) { \
204		if (cnt == (off_t)-1) \
205		    syslog(LOG_INFO,"%s %s%s", cmd, \
206			*(file) == '/' ? "" : curdir(), file); \
207		else \
208		    syslog(LOG_INFO, "%s %s%s = %qd bytes", \
209			cmd, (*(file) == '/') ? "" : curdir(), file, cnt); \
210	}
211
212static void	 ack(char *);
213static void	 sigurg(int);
214static void	 myoob(void);
215static int	 checkuser(char *, char *);
216static FILE	*dataconn(char *, off_t, char *);
217static void	 dolog(struct sockaddr *);
218static char	*copy_dir(char *, struct passwd *);
219static char	*curdir(void);
220static void	 end_login(void);
221static FILE	*getdatasock(char *);
222static int	 guniquefd(char *, char **);
223static void	 lostconn(int);
224static void	 sigquit(int);
225static int	 receive_data(FILE *, FILE *);
226static void	 replydirname(const char *, const char *);
227static int	 send_data(FILE *, FILE *, off_t, off_t, int);
228static struct passwd *
229		 sgetpwnam(char *, struct passwd *);
230static void	 reapchild(int);
231#if defined(TCPWRAPPERS)
232static int	 check_host(struct sockaddr *);
233#endif /* TCPWRAPPERS */
234static void	 usage(void);
235
236void	 logxfer(char *, off_t, time_t);
237void	 set_slave_signals(void);
238
239static char *
240curdir(void)
241{
242	static char path[MAXPATHLEN+1];	/* path + '/' */
243
244	if (getcwd(path, sizeof(path)-1) == NULL)
245		return ("");
246	if (path[1] != '\0')		/* special case for root dir. */
247		strlcat(path, "/", sizeof path);
248	/* For guest account, skip / since it's chrooted */
249	return (guest ? path+1 : path);
250}
251
252char *argstr = "AdDhnlMSt:T:u:UvP46";
253
254static void
255usage(void)
256{
257	syslog(LOG_ERR,
258	    "usage: ftpd [-46ADdlMnPSU] [-T maxtimeout] [-t timeout] [-u mask]");
259	exit(2);
260}
261
262int
263main(int argc, char *argv[])
264{
265	socklen_t addrlen;
266	int ch, on = 1, tos;
267	char line[LINE_MAX];
268	FILE *fp;
269	struct hostent *hp;
270	struct sigaction sa;
271	int error = 0;
272	const char *errstr;
273
274	tzset();		/* in case no timezone database in ~ftp */
275	sigfillset(&allsigs);	/* used to block signals while root */
276	sigemptyset(&sa.sa_mask);
277	sa.sa_flags = SA_RESTART;
278
279	while ((ch = getopt(argc, argv, argstr)) != -1) {
280		switch (ch) {
281		case 'A':
282			anon_only = 1;
283			break;
284
285		case 'd':
286		case 'v':		/* deprecated */
287			debug = 1;
288			break;
289
290		case 'D':
291			daemon_mode = 1;
292			break;
293
294		case 'P':
295			portcheck = 0;
296			break;
297
298		case 'h':		/* deprecated */
299			break;
300
301		case 'l':
302			logging++;	/* > 1 == extra logging */
303			break;
304
305		case 'M':
306			multihome = 1;
307			break;
308
309		case 'n':
310			anon_ok = 0;
311			break;
312
313		case 'S':
314			stats = 1;
315			break;
316
317		case 't':
318			timeout = strtonum(optarg, 0, INT_MAX, &errstr);
319			if (errstr) {
320				syslog(LOG_ERR,
321				    "%s is a bad value for -t, aborting",
322				    optarg);
323				exit(2);
324			}
325			if (maxtimeout < timeout)
326				maxtimeout = timeout;
327			break;
328
329		case 'T':
330			maxtimeout = strtonum(optarg, 0, INT_MAX,
331			    &errstr);
332			if (errstr) {
333				syslog(LOG_ERR,
334				    "%s is a bad value for -T, aborting",
335				    optarg);
336				exit(2);
337			}
338			if (timeout > maxtimeout)
339				timeout = maxtimeout;
340			break;
341
342		case 'u':
343		    {
344			long val = 0;
345			char *p;
346			umaskchange = 0;
347
348			val = strtol(optarg, &p, 8);
349			if (*optarg == '\0' || *p != '\0' || val < 0 ||
350			    (val & ~ACCESSPERMS)) {
351				syslog(LOG_ERR,
352				    "%s is a bad value for -u, aborting",
353				    optarg);
354				exit(2);
355			}
356			defumask = val;
357			break;
358		    }
359
360		case 'U':
361			doutmp = 1;
362			break;
363
364		case '4':
365			family = AF_INET;
366			break;
367
368		case '6':
369			family = AF_INET6;
370			break;
371
372		default:
373			usage();
374			break;
375		}
376	}
377
378	(void) freopen(_PATH_DEVNULL, "w", stderr);
379
380	/*
381	 * LOG_NDELAY sets up the logging connection immediately,
382	 * necessary for anonymous ftp's that chroot and can't do it later.
383	 */
384	openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
385
386	if (getpwnam(FTPD_PRIVSEP_USER) == NULL) {
387		syslog(LOG_ERR, "privilege separation user %s not found",
388		    FTPD_PRIVSEP_USER);
389		exit(1);
390	}
391	endpwent();
392
393	if (daemon_mode) {
394		int *fds, i, fd;
395		struct pollfd *pfds;
396		struct addrinfo hints, *res, *res0;
397		nfds_t n;
398
399		/*
400		 * Detach from parent.
401		 */
402		if (daemon(1, 1) < 0) {
403			syslog(LOG_ERR, "failed to become a daemon");
404			exit(1);
405		}
406		sa.sa_handler = reapchild;
407		(void) sigaction(SIGCHLD, &sa, NULL);
408
409		memset(&hints, 0, sizeof(hints));
410		hints.ai_family = family;
411		hints.ai_socktype = SOCK_STREAM;
412		hints.ai_protocol = IPPROTO_TCP;
413		hints.ai_flags = AI_PASSIVE;
414		error = getaddrinfo(NULL, "ftp", &hints, &res0);
415		if (error) {
416			syslog(LOG_ERR, "%s", gai_strerror(error));
417			exit(1);
418		}
419
420		n = 0;
421		for (res = res0; res; res = res->ai_next)
422			n++;
423
424		fds = calloc(n, sizeof(int));
425		pfds = calloc(n, sizeof(struct pollfd));
426		if (!fds || !pfds) {
427			syslog(LOG_ERR, "%s", strerror(errno));
428			exit(1);
429		}
430
431		/*
432		 * Open sockets, bind it to the FTP port, and start
433		 * listening.
434		 */
435		n = 0;
436		for (res = res0; res; res = res->ai_next) {
437			fds[n] = socket(res->ai_family, res->ai_socktype,
438			    res->ai_protocol);
439			if (fds[n] < 0)
440				continue;
441
442			if (setsockopt(fds[n], SOL_SOCKET, SO_KEEPALIVE,
443			    &on, sizeof(on)) < 0) {
444				close(fds[n]);
445				fds[n] = -1;
446				continue;
447			}
448
449			if (setsockopt(fds[n], SOL_SOCKET, SO_REUSEADDR,
450			    &on, sizeof(on)) < 0) {
451				close(fds[n]);
452				fds[n] = -1;
453				continue;
454			}
455
456			if (bind(fds[n], res->ai_addr, res->ai_addrlen) < 0) {
457				close(fds[n]);
458				fds[n] = -1;
459				continue;
460			}
461			if (listen(fds[n], 32) < 0) {
462				close(fds[n]);
463				fds[n] = -1;
464				continue;
465			}
466
467			pfds[n].fd = fds[n];
468			pfds[n].events = POLLIN;
469			n++;
470		}
471		freeaddrinfo(res0);
472
473		if (n == 0) {
474			syslog(LOG_ERR, "could not open control socket");
475			exit(1);
476		}
477
478		/* Stash pid in pidfile */
479		if (pidfile(NULL))
480			syslog(LOG_ERR, "can't open pidfile: %m");
481		/*
482		 * Loop forever accepting connection requests and forking off
483		 * children to handle them.
484		 */
485		while (1) {
486			if (poll(pfds, n, INFTIM) < 0) {
487				if (errno == EINTR)
488					continue;
489				syslog(LOG_ERR, "poll: %m");
490				exit(1);
491			}
492			for (i = 0; i < n; i++)
493				if (pfds[i].revents & POLLIN) {
494					addrlen = sizeof(his_addr);
495					fd = accept(pfds[i].fd,
496					    (struct sockaddr *)&his_addr,
497					    &addrlen);
498					if (fd != -1) {
499						if (fork() == 0)
500							goto child;
501						close(fd);
502					}
503				}
504		}
505
506	child:
507		/* child */
508		(void)dup2(fd, STDIN_FILENO);
509		(void)dup2(fd, STDOUT_FILENO);
510		for (i = 0; i < n; i++)
511			close(fds[i]);
512#if defined(TCPWRAPPERS)
513		/* ..in the child. */
514		if (!check_host((struct sockaddr *)&his_addr))
515			exit(1);
516#endif	/* TCPWRAPPERS */
517	} else {
518		addrlen = sizeof(his_addr);
519		if (getpeername(0, (struct sockaddr *)&his_addr,
520		    &addrlen) < 0) {
521			/* syslog(LOG_ERR, "getpeername (%s): %m", argv[0]); */
522			exit(1);
523		}
524	}
525
526	/* set this here so klogin can use it... */
527	(void)snprintf(ttyline, sizeof(ttyline), "ftp%ld", (long)getpid());
528
529	set_slave_signals();
530
531	addrlen = sizeof(ctrl_addr);
532	if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) {
533		syslog(LOG_ERR, "getsockname: %m");
534		exit(1);
535	}
536	if (his_addr.su_family == AF_INET6 &&
537	    IN6_IS_ADDR_V4MAPPED(&his_addr.su_sin6.sin6_addr)) {
538#if 1
539		/*
540		 * IPv4 control connection arrived to AF_INET6 socket.
541		 * I hate to do this, but this is the easiest solution.
542		 */
543		union sockunion tmp_addr;
544		const int off = sizeof(struct in6_addr) - sizeof(struct in_addr);
545
546		tmp_addr = his_addr;
547		memset(&his_addr, 0, sizeof(his_addr));
548		his_addr.su_sin.sin_family = AF_INET;
549		his_addr.su_sin.sin_len = sizeof(his_addr.su_sin);
550		memcpy(&his_addr.su_sin.sin_addr,
551		    &tmp_addr.su_sin6.sin6_addr.s6_addr[off],
552		    sizeof(his_addr.su_sin.sin_addr));
553		his_addr.su_sin.sin_port = tmp_addr.su_sin6.sin6_port;
554
555		tmp_addr = ctrl_addr;
556		memset(&ctrl_addr, 0, sizeof(ctrl_addr));
557		ctrl_addr.su_sin.sin_family = AF_INET;
558		ctrl_addr.su_sin.sin_len = sizeof(ctrl_addr.su_sin);
559		memcpy(&ctrl_addr.su_sin.sin_addr,
560		    &tmp_addr.su_sin6.sin6_addr.s6_addr[off],
561		    sizeof(ctrl_addr.su_sin.sin_addr));
562		ctrl_addr.su_sin.sin_port = tmp_addr.su_sin6.sin6_port;
563#else
564		while (fgets(line, sizeof(line), fd) != NULL) {
565			line[strcspn(line, "\n")] = '\0';
566			lreply(530, "%s", line);
567		}
568		(void) fflush(stdout);
569		(void) close(fd);
570		reply(530,
571			"Connection from IPv4 mapped address is not supported.");
572		exit(0);
573#endif
574	}
575#ifdef IP_TOS
576	if (his_addr.su_family == AF_INET) {
577		tos = IPTOS_LOWDELAY;
578		if (setsockopt(0, IPPROTO_IP, IP_TOS, &tos,
579		    sizeof(int)) < 0)
580			syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
581	}
582#endif
583	data_source.su_port = htons(ntohs(ctrl_addr.su_port) - 1);
584
585	/* Try to handle urgent data inline */
586#ifdef SO_OOBINLINE
587	if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)) < 0)
588		syslog(LOG_ERR, "setsockopt: %m");
589#endif
590
591	dolog((struct sockaddr *)&his_addr);
592
593	/*
594	 * Set up default state
595	 */
596	data = -1;
597	type = TYPE_A;
598	form = FORM_N;
599	stru = STRU_F;
600	mode = MODE_S;
601	tmpline[0] = '\0';
602
603	/* If logins are disabled, print out the message. */
604	if ((fp = fopen(_PATH_NOLOGIN, "r")) != NULL) {
605		while (fgets(line, sizeof(line), fp) != NULL) {
606			line[strcspn(line, "\n")] = '\0';
607			lreply(530, "%s", line);
608		}
609		(void) fflush(stdout);
610		(void) fclose(fp);
611		reply(530, "System not available.");
612		exit(0);
613	}
614	if ((fp = fopen(_PATH_FTPWELCOME, "r")) != NULL) {
615		while (fgets(line, sizeof(line), fp) != NULL) {
616			line[strcspn(line, "\n")] = '\0';
617			lreply(220, "%s", line);
618		}
619		(void) fflush(stdout);
620		(void) fclose(fp);
621		/* reply(220,) must follow */
622	}
623	(void) gethostname(hostname, sizeof(hostname));
624
625	/* Make sure hostname is fully qualified. */
626	hp = gethostbyname(hostname);
627	if (hp != NULL)
628		strlcpy(hostname, hp->h_name, sizeof(hostname));
629
630	if (multihome) {
631		error = getnameinfo((struct sockaddr *)&ctrl_addr,
632		    ctrl_addr.su_len, dhostname, sizeof(dhostname), NULL, 0, 0);
633	}
634
635	if (error != 0)
636		reply(220, "FTP server ready.");
637	else
638		reply(220, "%s FTP server ready.",
639		    (multihome ? dhostname : hostname));
640
641	monitor_init();
642
643	for (;;)
644		(void) yyparse();
645	/* NOTREACHED */
646}
647
648/*
649 * Signal handlers.
650 */
651/*ARGSUSED*/
652static void
653lostconn(int signo)
654{
655	struct syslog_data sdata = SYSLOG_DATA_INIT;
656
657	sdata.log_fac = LOG_FTP;
658	if (debug)
659		syslog_r(LOG_DEBUG, &sdata, "lost connection");
660	dologout(1);
661}
662
663static void
664sigquit(int signo)
665{
666	struct syslog_data sdata = SYSLOG_DATA_INIT;
667
668	sdata.log_fac = LOG_FTP;
669	syslog_r(LOG_DEBUG, &sdata, "got signal %s", sys_signame[signo]);
670	dologout(1);
671}
672
673/*
674 * Save the result of a getpwnam.  Used for USER command, since
675 * the data returned must not be clobbered by any other command
676 * (e.g., globbing).
677 */
678static struct passwd *
679sgetpwnam(char *name, struct passwd *pw)
680{
681	static struct passwd *save;
682	struct passwd *old;
683
684	if (pw == NULL && (pw = getpwnam(name)) == NULL)
685		return (NULL);
686	old = save;
687	save = pw_dup(pw);
688	if (save == NULL) {
689		perror_reply(421, "Local resource failure: malloc");
690		dologout(1);
691		/* NOTREACHED */
692	}
693	if (old) {
694		memset(old->pw_passwd, 0, strlen(old->pw_passwd));
695		free(old);
696	}
697	return (save);
698}
699
700static int login_attempts;	/* number of failed login attempts */
701static int askpasswd;		/* had user command, ask for passwd */
702static char curname[MAXLOGNAME];	/* current USER name */
703
704/*
705 * USER command.
706 * Sets global passwd pointer pw if named account exists and is acceptable;
707 * sets askpasswd if a PASS command is expected.  If logged in previously,
708 * need to reset state.  If name is "ftp" or "anonymous", the name is not in
709 * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return.
710 * If account doesn't exist, ask for passwd anyway.  Otherwise, check user
711 * requesting login privileges.  Disallow anyone who does not have a standard
712 * shell as returned by getusershell().  Disallow anyone mentioned in the file
713 * _PATH_FTPUSERS to allow people such as root and uucp to be avoided.
714 */
715void
716user(char *name)
717{
718	char *cp, *shell, *style, *host;
719	char *class = NULL;
720
721	if (logged_in) {
722		kill_slave("user already logged in");
723		end_login();
724	}
725
726	/* Close session from previous user if there was one. */
727	if (as) {
728		auth_close(as);
729		as = NULL;
730	}
731	if (lc) {
732		login_close(lc);
733		lc = NULL;
734	}
735
736	if ((style = strchr(name, ':')) != NULL)
737		*style++ = 0;
738
739	guest = 0;
740	askpasswd = 0;
741	host = multihome ? dhostname : hostname;
742	if (anon_ok &&
743	    (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0)) {
744		if (checkuser(_PATH_FTPUSERS, "ftp") ||
745		    checkuser(_PATH_FTPUSERS, "anonymous"))
746			reply(530, "User %s access denied.", name);
747		else if ((pw = sgetpwnam("ftp", NULL)) != NULL) {
748			if ((lc = login_getclass(pw->pw_class)) == NULL ||
749			    (as = auth_open()) == NULL ||
750			    auth_setpwd(as, pw) != 0 ||
751			    auth_setoption(as, "FTPD_HOST", host) < 0) {
752				if (as) {
753					auth_close(as);
754					as = NULL;
755				}
756				if (lc) {
757					login_close(lc);
758					lc = NULL;
759				}
760				reply(421, "Local resource failure");
761				return;
762			}
763			guest = 1;
764			askpasswd = 1;
765			reply(331,
766			"Guest login ok, send your email address as password.");
767		} else
768			reply(530, "User %s unknown.", name);
769		if (!askpasswd && logging)
770			syslog(LOG_NOTICE,
771			    "ANONYMOUS FTP LOGIN REFUSED FROM %s", remotehost);
772		return;
773	}
774
775	shell = _PATH_BSHELL;
776	if ((pw = sgetpwnam(name, NULL))) {
777		class = pw->pw_class;
778		if (pw->pw_shell != NULL && *pw->pw_shell != '\0')
779			shell = pw->pw_shell;
780		while ((cp = getusershell()) != NULL)
781			if (strcmp(cp, shell) == 0)
782				break;
783		shell = cp;
784		endusershell();
785	}
786
787	/* Get login class; if invalid style treat like unknown user. */
788	lc = login_getclass(class);
789	if (lc && (style = login_getstyle(lc, style, "auth-ftp")) == NULL) {
790		login_close(lc);
791		lc = NULL;
792		pw = NULL;
793	}
794
795	/* Do pre-authentication setup. */
796	if (lc && ((as = auth_open()) == NULL ||
797	    (pw != NULL && auth_setpwd(as, pw) != 0) ||
798	    auth_setitem(as, AUTHV_STYLE, style) < 0 ||
799	    auth_setitem(as, AUTHV_NAME, name) < 0 ||
800	    auth_setitem(as, AUTHV_CLASS, class) < 0 ||
801	    auth_setoption(as, "login", "yes") < 0 ||
802	    auth_setoption(as, "notickets", "yes") < 0 ||
803	    auth_setoption(as, "FTPD_HOST", host) < 0)) {
804		if (as) {
805			auth_close(as);
806			as = NULL;
807		}
808		login_close(lc);
809		lc = NULL;
810		reply(421, "Local resource failure");
811		return;
812	}
813	if (logging)
814		strlcpy(curname, name, sizeof(curname));
815
816	dochroot = (lc && login_getcapbool(lc, "ftp-chroot", 0)) ||
817	    checkuser(_PATH_FTPCHROOT, name);
818	if (anon_only && !dochroot) {
819		reply(530, "User %s access denied.", name);
820		return;
821	}
822	if (pw) {
823		if ((!shell && !dochroot) || checkuser(_PATH_FTPUSERS, name)) {
824			reply(530, "User %s access denied.", name);
825			if (logging)
826				syslog(LOG_NOTICE,
827				    "FTP LOGIN REFUSED FROM %s, %s",
828				    remotehost, name);
829			pw = NULL;
830			return;
831		}
832	}
833
834	if (as != NULL && (cp = auth_challenge(as)) != NULL)
835		reply(331, "%s", cp);
836	else
837		reply(331, "Password required for %s.", name);
838
839	askpasswd = 1;
840	/*
841	 * Delay before reading passwd after first failed
842	 * attempt to slow down passwd-guessing programs.
843	 */
844	if (login_attempts)
845		sleep((unsigned) login_attempts);
846}
847
848/*
849 * Check if a user is in the file "fname"
850 */
851static int
852checkuser(char *fname, char *name)
853{
854	FILE *fp;
855	int found = 0;
856	char *p, line[BUFSIZ];
857
858	if ((fp = fopen(fname, "r")) != NULL) {
859		while (fgets(line, sizeof(line), fp) != NULL)
860			if ((p = strchr(line, '\n')) != NULL) {
861				*p = '\0';
862				if (line[0] == '#')
863					continue;
864				if (strcmp(line, name) == 0) {
865					found = 1;
866					break;
867				}
868			}
869		(void) fclose(fp);
870	}
871	return (found);
872}
873
874/*
875 * Terminate login as previous user, if any, resetting state;
876 * used when USER command is given or login fails.
877 */
878static void
879end_login(void)
880{
881	sigprocmask (SIG_BLOCK, &allsigs, NULL);
882	if (logged_in) {
883		ftpdlogwtmp(ttyline, "", "");
884		if (doutmp)
885			ftpd_logout(utmp.ut_line);
886	}
887	reply(530, "Please reconnect to work as another user");
888	_exit(0);
889}
890
891enum auth_ret
892pass(char *passwd)
893{
894	int authok;
895	unsigned int flags;
896	FILE *fp;
897	static char homedir[MAXPATHLEN];
898	char *motd, *dir, rootdir[MAXPATHLEN];
899	size_t sz_pw_dir;
900
901	if (logged_in || askpasswd == 0) {
902		reply(503, "Login with USER first.");
903		return (AUTH_FAILED);
904	}
905	askpasswd = 0;
906	if (!guest) {		/* "ftp" is only account allowed no password */
907		authok = 0;
908		if (pw == NULL || pw->pw_passwd[0] == '\0') {
909			useconds_t us;
910
911			/* Sleep between 1 and 3 seconds to emulate a crypt. */
912			us = arc4random_uniform(3000000);
913			usleep(us);
914			if (as != NULL) {
915				auth_close(as);
916				as = NULL;
917			}
918		} else {
919			authok = auth_userresponse(as, passwd, 0);
920			as = NULL;
921		}
922		if (authok == 0) {
923			reply(530, "Login incorrect.");
924			if (logging)
925				syslog(LOG_NOTICE,
926				    "FTP LOGIN FAILED FROM %s, %s",
927				    remotehost, curname);
928			pw = NULL;
929			if (login_attempts++ >= 5) {
930				syslog(LOG_NOTICE,
931				    "repeated login failures from %s",
932				    remotehost);
933				kill_slave("repeated login failures");
934				_exit(0);
935			}
936			return (AUTH_FAILED);
937		}
938	} else if (lc != NULL) {
939		/* Save anonymous' password. */
940		if (guestpw != NULL)
941			free(guestpw);
942		guestpw = strdup(passwd);
943		if (guestpw == NULL) {
944			kill_slave("out of mem");
945			fatal("Out of memory.");
946		}
947
948		authok = auth_approval(as, lc, pw->pw_name, "ftp");
949		auth_close(as);
950		as = NULL;
951		if (authok == 0) {
952			syslog(LOG_INFO|LOG_AUTH,
953			    "FTP LOGIN FAILED (HOST) as %s: approval failure.",
954			    pw->pw_name);
955			reply(530, "Approval failure.");
956			kill_slave("approval failure");
957			_exit(0);
958		}
959	} else {
960		syslog(LOG_INFO|LOG_AUTH,
961		    "FTP LOGIN CLASS %s MISSING for %s: approval failure.",
962		    pw->pw_class, pw->pw_name);
963		reply(530, "Permission denied.");
964		kill_slave("permission denied");
965		_exit(0);
966	}
967
968	if (monitor_post_auth() == 1) {
969		/* Post-auth monitor process */
970		logged_in = 1;
971		return (AUTH_MONITOR);
972	}
973
974	login_attempts = 0;		/* this time successful */
975	/* set umask via setusercontext() unless -u flag was given. */
976	flags = LOGIN_SETGROUP|LOGIN_SETPRIORITY|LOGIN_SETRESOURCES;
977	if (umaskchange)
978		flags |= LOGIN_SETUMASK;
979	else
980		(void) umask(defumask);
981	if (setusercontext(lc, pw, (uid_t)0, flags) != 0) {
982		perror_reply(421, "Local resource failure: setusercontext");
983		syslog(LOG_NOTICE, "setusercontext: %m");
984		dologout(1);
985		/* NOTREACHED */
986	}
987
988	/* open wtmp before chroot */
989	ftpdlogwtmp(ttyline, pw->pw_name, remotehost);
990
991	/* open utmp before chroot */
992	if (doutmp) {
993		memset((void *)&utmp, 0, sizeof(utmp));
994		(void)time(&utmp.ut_time);
995		(void)strncpy(utmp.ut_name, pw->pw_name, sizeof(utmp.ut_name));
996		(void)strncpy(utmp.ut_host, remotehost, sizeof(utmp.ut_host));
997		(void)strncpy(utmp.ut_line, ttyline, sizeof(utmp.ut_line));
998		ftpd_login(&utmp);
999	}
1000
1001	/* open stats file before chroot */
1002	if (guest && (stats == 1) && (statfd < 0))
1003		if ((statfd = open(_PATH_FTPDSTATFILE, O_WRONLY|O_APPEND)) < 0)
1004			stats = 0;
1005
1006	logged_in = 1;
1007
1008	if ((dir = login_getcapstr(lc, "ftp-dir", NULL, NULL))) {
1009		char *newdir;
1010
1011		newdir = copy_dir(dir, pw);
1012		if (newdir == NULL) {
1013			perror_reply(421, "Local resource failure: malloc");
1014			dologout(1);
1015			/* NOTREACHED */
1016		}
1017		pw->pw_dir = newdir;
1018		pw = sgetpwnam(NULL, pw);
1019		free(dir);
1020		free(newdir);
1021	}
1022
1023	/* make sure pw->pw_dir is big enough to hold "/" */
1024	sz_pw_dir = strlen(pw->pw_dir) + 1;
1025	if (sz_pw_dir < 2) {
1026		pw->pw_dir = "/";
1027		pw = sgetpwnam(NULL, pw);
1028		sz_pw_dir = 2;
1029	}
1030
1031	if (guest || dochroot) {
1032		if (multihome && guest) {
1033			struct stat ts;
1034
1035			/* Compute root directory. */
1036			snprintf(rootdir, sizeof(rootdir), "%s/%s",
1037			    pw->pw_dir, dhostname);
1038			if (stat(rootdir, &ts) < 0) {
1039				snprintf(rootdir, sizeof(rootdir), "%s/%s",
1040				    pw->pw_dir, hostname);
1041			}
1042		} else
1043			strlcpy(rootdir, pw->pw_dir, sizeof(rootdir));
1044	}
1045	if (guest) {
1046		/*
1047		 * We MUST do a chdir() after the chroot. Otherwise
1048		 * the old current directory will be accessible as "."
1049		 * outside the new root!
1050		 */
1051		if (chroot(rootdir) < 0 || chdir("/") < 0) {
1052			reply(550, "Can't set guest privileges.");
1053			goto bad;
1054		}
1055		strlcpy(pw->pw_dir, "/", sz_pw_dir);
1056		if (setenv("HOME", "/", 1) == -1) {
1057			reply(550, "Can't setup environment.");
1058			goto bad;
1059		}
1060	} else if (dochroot) {
1061		if (chroot(rootdir) < 0 || chdir("/") < 0) {
1062			reply(550, "Can't change root.");
1063			goto bad;
1064		}
1065		strlcpy(pw->pw_dir, "/", sz_pw_dir);
1066		if (setenv("HOME", "/", 1) == -1) {
1067			reply(550, "Can't setup environment.");
1068			goto bad;
1069		}
1070	} else if (chdir(pw->pw_dir) < 0) {
1071		if (chdir("/") < 0) {
1072			reply(530, "User %s: can't change directory to %s.",
1073			    pw->pw_name, pw->pw_dir);
1074			goto bad;
1075		} else
1076			lreply(230, "No directory! Logging in with home=/");
1077	}
1078	if (setegid(pw->pw_gid) < 0 || setgid(pw->pw_gid) < 0) {
1079		reply(550, "Can't set gid.");
1080		goto bad;
1081	}
1082	if (seteuid(pw->pw_uid) < 0 || setuid(pw->pw_uid) < 0) {
1083		reply(550, "Can't set uid.");
1084		goto bad;
1085	}
1086	sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
1087
1088	/*
1089	 * Set home directory so that use of ~ (tilde) works correctly.
1090	 */
1091	if (getcwd(homedir, MAXPATHLEN) != NULL) {
1092		if (setenv("HOME", homedir, 1) == -1) {
1093			reply(550, "Can't setup environment.");
1094			goto bad;
1095		}
1096	}
1097
1098	/*
1099	 * Display a login message, if it exists.
1100	 * N.B. reply(230,) must follow the message.
1101	 */
1102	motd = login_getcapstr(lc, "welcome", NULL, NULL);
1103	if ((fp = fopen(motd ? motd : _PATH_FTPLOGINMESG, "r")) != NULL) {
1104		char line[LINE_MAX];
1105
1106		while (fgets(line, sizeof(line), fp) != NULL) {
1107			line[strcspn(line, "\n")] = '\0';
1108			lreply(230, "%s", line);
1109		}
1110		(void) fflush(stdout);
1111		(void) fclose(fp);
1112	}
1113	if (motd != NULL)
1114		free(motd);
1115	if (guest) {
1116		reply(230, "Guest login ok, access restrictions apply.");
1117#ifdef HASSETPROCTITLE
1118		snprintf(proctitle, sizeof(proctitle),
1119		    "%s: anonymous/%.*s", remotehost,
1120		    (int)(sizeof(proctitle) - sizeof(remotehost) -
1121		    sizeof(": anonymous/")), passwd);
1122		setproctitle("%s", proctitle);
1123#endif /* HASSETPROCTITLE */
1124		if (logging)
1125			syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s",
1126			    remotehost, passwd);
1127	} else {
1128		reply(230, "User %s logged in.", pw->pw_name);
1129#ifdef HASSETPROCTITLE
1130		snprintf(proctitle, sizeof(proctitle),
1131		    "%s: %s", remotehost, pw->pw_name);
1132		setproctitle("%s", proctitle);
1133#endif /* HASSETPROCTITLE */
1134		if (logging)
1135			syslog(LOG_INFO, "FTP LOGIN FROM %s as %s",
1136			    remotehost, pw->pw_name);
1137	}
1138	login_close(lc);
1139	lc = NULL;
1140	return (AUTH_SLAVE);
1141bad:
1142	/* Forget all about it... */
1143	login_close(lc);
1144	lc = NULL;
1145	end_login();
1146	return (AUTH_FAILED);
1147}
1148
1149void
1150retrieve(char *cmd, char *name)
1151{
1152	FILE *fin, *dout;
1153	struct stat st;
1154	int (*closefunc)(FILE *);
1155	time_t start;
1156
1157	if (cmd == 0) {
1158		fin = fopen(name, "r"), closefunc = fclose;
1159		st.st_size = 0;
1160	} else {
1161		char line[BUFSIZ];
1162
1163		(void) snprintf(line, sizeof(line), cmd, name);
1164		name = line;
1165		fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose;
1166		st.st_size = -1;
1167		st.st_blksize = BUFSIZ;
1168	}
1169	if (fin == NULL) {
1170		if (errno != 0) {
1171			perror_reply(550, name);
1172			if (cmd == 0) {
1173				LOGCMD("get", name);
1174			}
1175		}
1176		return;
1177	}
1178	byte_count = -1;
1179	if (cmd == 0 && (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode))) {
1180		reply(550, "%s: not a plain file.", name);
1181		goto done;
1182	}
1183	if (restart_point) {
1184		if (type == TYPE_A) {
1185			off_t i, n;
1186			int c;
1187
1188			n = restart_point;
1189			i = 0;
1190			while (i++ < n) {
1191				if ((c = getc(fin)) == EOF) {
1192					if (ferror(fin)) {
1193						perror_reply(550, name);
1194						goto done;
1195					} else
1196						break;
1197				}
1198				if (c == '\n')
1199					i++;
1200			}
1201		} else if (lseek(fileno(fin), restart_point, SEEK_SET) < 0) {
1202			perror_reply(550, name);
1203			goto done;
1204		}
1205	}
1206	dout = dataconn(name, st.st_size, "w");
1207	if (dout == NULL)
1208		goto done;
1209	time(&start);
1210	send_data(fin, dout, (off_t)st.st_blksize, st.st_size,
1211	    (restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode)));
1212	if ((cmd == 0) && stats)
1213		logxfer(name, byte_count, start);
1214	(void) fclose(dout);
1215	data = -1;
1216done:
1217	if (pdata >= 0)
1218		(void) close(pdata);
1219	pdata = -1;
1220	if (cmd == 0)
1221		LOGBYTES("get", name, byte_count);
1222	(*closefunc)(fin);
1223}
1224
1225void
1226store(char *name, char *mode, int unique)
1227{
1228	FILE *fout, *din;
1229	int (*closefunc)(FILE *);
1230	struct stat st;
1231	int fd;
1232
1233	if (restart_point && *mode != 'a')
1234		mode = "r+";
1235
1236	if (unique && stat(name, &st) == 0) {
1237		char *nam;
1238
1239		fd = guniquefd(name, &nam);
1240		if (fd == -1) {
1241			LOGCMD(*mode == 'w' ? "put" : "append", name);
1242			return;
1243		}
1244		name = nam;
1245		fout = fdopen(fd, mode);
1246	} else
1247		fout = fopen(name, mode);
1248
1249	closefunc = fclose;
1250	if (fout == NULL) {
1251		perror_reply(553, name);
1252		LOGCMD(*mode == 'w' ? "put" : "append", name);
1253		return;
1254	}
1255	byte_count = -1;
1256	if (restart_point) {
1257		if (type == TYPE_A) {
1258			off_t i, n;
1259			int c;
1260
1261			n = restart_point;
1262			i = 0;
1263			while (i++ < n) {
1264				if ((c = getc(fout)) == EOF) {
1265					if (ferror(fout)) {
1266						perror_reply(550, name);
1267						goto done;
1268					} else
1269						break;
1270				}
1271				if (c == '\n')
1272					i++;
1273			}
1274			/*
1275			 * We must do this seek to "current" position
1276			 * because we are changing from reading to
1277			 * writing.
1278			 */
1279			if (fseek(fout, 0L, SEEK_CUR) < 0) {
1280				perror_reply(550, name);
1281				goto done;
1282			}
1283		} else if (lseek(fileno(fout), restart_point, SEEK_SET) < 0) {
1284			perror_reply(550, name);
1285			goto done;
1286		}
1287	}
1288	din = dataconn(name, (off_t)-1, "r");
1289	if (din == NULL)
1290		goto done;
1291	if (receive_data(din, fout) == 0) {
1292		if (unique)
1293			reply(226, "Transfer complete (unique file name:%s).",
1294			    name);
1295		else
1296			reply(226, "Transfer complete.");
1297	}
1298	(void) fclose(din);
1299	data = -1;
1300	pdata = -1;
1301done:
1302	LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count);
1303	(*closefunc)(fout);
1304}
1305
1306static FILE *
1307getdatasock(char *mode)
1308{
1309	int on = 1, s, t, tries;
1310
1311	if (data >= 0)
1312		return (fdopen(data, mode));
1313	sigprocmask (SIG_BLOCK, &allsigs, NULL);
1314	s = monitor_socket(ctrl_addr.su_family);
1315	if (s < 0)
1316		goto bad;
1317	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
1318	    &on, sizeof(on)) < 0)
1319		goto bad;
1320	/* anchor socket to avoid multi-homing problems */
1321	data_source = ctrl_addr;
1322	data_source.su_port = htons(20); /* ftp-data port */
1323	for (tries = 1; ; tries++) {
1324		if (monitor_bind(s, (struct sockaddr *)&data_source,
1325		    data_source.su_len) >= 0)
1326			break;
1327		if (errno != EADDRINUSE || tries > 10)
1328			goto bad;
1329		sleep((unsigned int)tries);
1330	}
1331	sigprocmask (SIG_UNBLOCK, &allsigs, NULL);
1332
1333#ifdef IP_TOS
1334	if (ctrl_addr.su_family == AF_INET) {
1335		on = IPTOS_THROUGHPUT;
1336		if (setsockopt(s, IPPROTO_IP, IP_TOS, &on,
1337		    sizeof(int)) < 0)
1338			syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
1339	}
1340#endif
1341#ifdef TCP_NOPUSH
1342	/*
1343	 * Turn off push flag to keep sender TCP from sending short packets
1344	 * at the boundaries of each write().  Should probably do a SO_SNDBUF
1345	 * to set the send buffer size as well, but that may not be desirable
1346	 * in heavy-load situations.
1347	 */
1348	on = 1;
1349	if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, &on, sizeof(on)) < 0)
1350		syslog(LOG_WARNING, "setsockopt (TCP_NOPUSH): %m");
1351#endif
1352#ifdef SO_SNDBUF
1353	on = 65536;
1354	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &on, sizeof(on)) < 0)
1355		syslog(LOG_WARNING, "setsockopt (SO_SNDBUF): %m");
1356#endif
1357
1358	return (fdopen(s, mode));
1359bad:
1360	/* Return the real value of errno (close may change it) */
1361	t = errno;
1362	sigprocmask (SIG_UNBLOCK, &allsigs, NULL);
1363	if (s >= 0)
1364		(void) close(s);
1365	errno = t;
1366	return (NULL);
1367}
1368
1369static FILE *
1370dataconn(char *name, off_t size, char *mode)
1371{
1372	char sizebuf[32];
1373	FILE *file = NULL;
1374	int retry = 0;
1375	in_port_t *p;
1376	u_char *fa, *ha;
1377	size_t alen;
1378	int error;
1379
1380	file_size = size;
1381	byte_count = 0;
1382	if (size != (off_t) -1) {
1383		(void) snprintf(sizebuf, sizeof(sizebuf), " (%qd bytes)",
1384		    size);
1385	} else
1386		sizebuf[0] = '\0';
1387	if (pdata >= 0) {
1388		union sockunion from;
1389		int s;
1390		socklen_t fromlen = sizeof(from);
1391
1392		(void) alarm ((unsigned) timeout);
1393		s = accept(pdata, (struct sockaddr *)&from, &fromlen);
1394		(void) alarm (0);
1395		if (s < 0) {
1396			reply(425, "Can't open data connection.");
1397			(void) close(pdata);
1398			pdata = -1;
1399			return (NULL);
1400		}
1401		switch (from.su_family) {
1402		case AF_INET:
1403			p = (in_port_t *)&from.su_sin.sin_port;
1404			fa = (u_char *)&from.su_sin.sin_addr;
1405			ha = (u_char *)&his_addr.su_sin.sin_addr;
1406			alen = sizeof(struct in_addr);
1407			break;
1408		case AF_INET6:
1409			p = (in_port_t *)&from.su_sin6.sin6_port;
1410			fa = (u_char *)&from.su_sin6.sin6_addr;
1411			ha = (u_char *)&his_addr.su_sin6.sin6_addr;
1412			alen = sizeof(struct in6_addr);
1413			break;
1414		default:
1415			reply(425, "Can't build data connection: "
1416			    "unknown address family");
1417			(void) close(pdata);
1418			(void) close(s);
1419			pdata = -1;
1420			return (NULL);
1421		}
1422		if (from.su_family != his_addr.su_family ||
1423		    ntohs(*p) < IPPORT_RESERVED) {
1424			reply(425, "Can't build data connection: "
1425			    "address family or port error");
1426			(void) close(pdata);
1427			(void) close(s);
1428			pdata = -1;
1429			return (NULL);
1430		}
1431		if (portcheck && memcmp(fa, ha, alen) != 0) {
1432			reply(425, "Can't build data connection: "
1433			    "illegal port number");
1434			(void) close(pdata);
1435			(void) close(s);
1436			pdata = -1;
1437			return (NULL);
1438		}
1439		(void) close(pdata);
1440		pdata = s;
1441		reply(150, "Opening %s mode data connection for '%s'%s.",
1442		    type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1443		return (fdopen(pdata, mode));
1444	}
1445	if (data >= 0) {
1446		reply(125, "Using existing data connection for '%s'%s.",
1447		    name, sizebuf);
1448		usedefault = 1;
1449		return (fdopen(data, mode));
1450	}
1451	if (usedefault)
1452		data_dest = his_addr;
1453	usedefault = 1;
1454	do {
1455		if (file != NULL)
1456			(void) fclose(file);
1457		file = getdatasock(mode);
1458		if (file == NULL) {
1459			char hbuf[MAXHOSTNAMELEN], pbuf[10];
1460
1461			error = getnameinfo((struct sockaddr *)&data_source,
1462			    data_source.su_len, hbuf, sizeof(hbuf), pbuf,
1463			    sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV);
1464			if (error != 0)
1465				reply(425, "Can't create data socket: %s.",
1466				    strerror(errno));
1467			else
1468				reply(425,
1469				    "Can't create data socket (%s,%s): %s.",
1470				    hbuf, pbuf, strerror(errno));
1471			return (NULL);
1472		}
1473
1474		/*
1475		 * attempt to connect to reserved port on client machine;
1476		 * this looks like an attack
1477		 */
1478		switch (data_dest.su_family) {
1479		case AF_INET:
1480			p = (in_port_t *)&data_dest.su_sin.sin_port;
1481			fa = (u_char *)&data_dest.su_sin.sin_addr;
1482			ha = (u_char *)&his_addr.su_sin.sin_addr;
1483			alen = sizeof(struct in_addr);
1484			break;
1485		case AF_INET6:
1486			p = (in_port_t *)&data_dest.su_sin6.sin6_port;
1487			fa = (u_char *)&data_dest.su_sin6.sin6_addr;
1488			ha = (u_char *)&his_addr.su_sin6.sin6_addr;
1489			alen = sizeof(struct in6_addr);
1490			break;
1491		default:
1492			reply(425, "Can't build data connection: "
1493			    "unknown address family");
1494			(void) fclose(file);
1495			pdata = -1;
1496			return (NULL);
1497		}
1498		if (data_dest.su_family != his_addr.su_family ||
1499		    ntohs(*p) < IPPORT_RESERVED || ntohs(*p) == 2049) { /* XXX */
1500			reply(425, "Can't build data connection: "
1501			    "address family or port error");
1502			(void) fclose(file);
1503			return NULL;
1504		}
1505		if (portcheck && memcmp(fa, ha, alen) != 0) {
1506			reply(435, "Can't build data connection: "
1507			    "illegal port number");
1508			(void) fclose(file);
1509			return NULL;
1510		}
1511
1512		if (connect(fileno(file), (struct sockaddr *)&data_dest,
1513		    data_dest.su_len) == 0) {
1514			reply(150, "Opening %s mode data connection for '%s'%s.",
1515			    type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1516			data = fileno(file);
1517			return (file);
1518		}
1519		if (errno != EADDRINUSE)
1520			break;
1521		sleep((unsigned) swaitint);
1522		retry += swaitint;
1523	} while (retry <= swaitmax);
1524	perror_reply(425, "Can't build data connection");
1525	(void) fclose(file);
1526	return (NULL);
1527}
1528
1529/*
1530 * Transfer the contents of "instr" to "outstr" peer using the appropriate
1531 * encapsulation of the data subject to Mode, Structure, and Type.
1532 *
1533 * NB: Form isn't handled.
1534 */
1535static int
1536send_data(FILE *instr, FILE *outstr, off_t blksize, off_t filesize, int isreg)
1537{
1538	int c, cnt, filefd, netfd;
1539	char *buf, *bp;
1540	size_t len;
1541
1542	transflag++;
1543	switch (type) {
1544
1545	case TYPE_A:
1546		while ((c = getc(instr)) != EOF) {
1547			if (recvurg)
1548				goto got_oob;
1549			byte_count++;
1550			if (c == '\n') {
1551				if (ferror(outstr))
1552					goto data_err;
1553				(void) putc('\r', outstr);
1554			}
1555			(void) putc(c, outstr);
1556		}
1557		fflush(outstr);
1558		transflag = 0;
1559		if (ferror(instr))
1560			goto file_err;
1561		if (ferror(outstr))
1562			goto data_err;
1563		reply(226, "Transfer complete.");
1564		return(0);
1565
1566	case TYPE_I:
1567	case TYPE_L:
1568		/*
1569		 * isreg is only set if we are not doing restart and we
1570		 * are sending a regular file
1571		 */
1572		netfd = fileno(outstr);
1573		filefd = fileno(instr);
1574
1575		if (isreg && filesize < (off_t)16 * 1024 * 1024) {
1576			size_t fsize = (size_t)filesize;
1577
1578			buf = mmap(0, fsize, PROT_READ, MAP_SHARED, filefd,
1579			    (off_t)0);
1580			if (buf == MAP_FAILED) {
1581				syslog(LOG_WARNING, "mmap(%llu): %m",
1582				    (unsigned long long)fsize);
1583				goto oldway;
1584			}
1585			bp = buf;
1586			len = fsize;
1587			do {
1588				cnt = write(netfd, bp, len);
1589				if (recvurg) {
1590					munmap(buf, fsize);
1591					goto got_oob;
1592				}
1593				len -= cnt;
1594				bp += cnt;
1595				if (cnt > 0)
1596					byte_count += cnt;
1597			} while(cnt > 0 && len > 0);
1598
1599			transflag = 0;
1600			munmap(buf, fsize);
1601			if (cnt < 0)
1602				goto data_err;
1603			reply(226, "Transfer complete.");
1604			return(0);
1605		}
1606
1607oldway:
1608		if ((buf = malloc((size_t)blksize)) == NULL) {
1609			transflag = 0;
1610			perror_reply(451, "Local resource failure: malloc");
1611			return(-1);
1612		}
1613
1614		while ((cnt = read(filefd, buf, (size_t)blksize)) > 0 &&
1615		    write(netfd, buf, cnt) == cnt)
1616			byte_count += cnt;
1617		transflag = 0;
1618		(void)free(buf);
1619		if (cnt != 0) {
1620			if (cnt < 0)
1621				goto file_err;
1622			goto data_err;
1623		}
1624		reply(226, "Transfer complete.");
1625		return(0);
1626	default:
1627		transflag = 0;
1628		reply(550, "Unimplemented TYPE %d in send_data", type);
1629		return(-1);
1630	}
1631
1632data_err:
1633	transflag = 0;
1634	reply(426, "Data connection");
1635	return(-1);
1636
1637file_err:
1638	transflag = 0;
1639	reply(551, "Error on input file");
1640	return(-1);
1641
1642got_oob:
1643	myoob();
1644	recvurg = 0;
1645	transflag = 0;
1646	return(-1);
1647}
1648
1649/*
1650 * Transfer data from peer to "outstr" using the appropriate encapulation of
1651 * the data subject to Mode, Structure, and Type.
1652 *
1653 * N.B.: Form isn't handled.
1654 */
1655static int
1656receive_data(FILE *instr, FILE *outstr)
1657{
1658	int c;
1659	int cnt;
1660	char buf[BUFSIZ];
1661	struct sigaction sa, sa_saved;
1662	volatile int bare_lfs = 0;
1663
1664	transflag++;
1665	switch (type) {
1666
1667	case TYPE_I:
1668	case TYPE_L:
1669		memset(&sa, 0, sizeof(sa));
1670		sigfillset(&sa.sa_mask);
1671		sa.sa_flags = SA_RESTART;
1672		sa.sa_handler = lostconn;
1673		(void) sigaction(SIGALRM, &sa, &sa_saved);
1674		do {
1675			(void) alarm ((unsigned) timeout);
1676			cnt = read(fileno(instr), buf, sizeof(buf));
1677			(void) alarm (0);
1678			if (recvurg)
1679				goto got_oob;
1680
1681			if (cnt > 0) {
1682				if (write(fileno(outstr), buf, cnt) != cnt)
1683					goto file_err;
1684				byte_count += cnt;
1685			}
1686		} while (cnt > 0);
1687		(void) sigaction(SIGALRM, &sa_saved, NULL);
1688		if (cnt < 0)
1689			goto data_err;
1690		transflag = 0;
1691		return (0);
1692
1693	case TYPE_E:
1694		reply(553, "TYPE E not implemented.");
1695		transflag = 0;
1696		return (-1);
1697
1698	case TYPE_A:
1699		while ((c = getc(instr)) != EOF) {
1700			if (recvurg)
1701				goto got_oob;
1702			byte_count++;
1703			if (c == '\n')
1704				bare_lfs++;
1705			while (c == '\r') {
1706				if (ferror(outstr))
1707					goto data_err;
1708				if ((c = getc(instr)) != '\n') {
1709					(void) putc ('\r', outstr);
1710					if (c == '\0' || c == EOF)
1711						goto contin2;
1712				}
1713			}
1714			(void) putc(c, outstr);
1715	contin2:	;
1716		}
1717		fflush(outstr);
1718		if (ferror(instr))
1719			goto data_err;
1720		if (ferror(outstr))
1721			goto file_err;
1722		transflag = 0;
1723		if (bare_lfs) {
1724			lreply(226,
1725			    "WARNING! %d bare linefeeds received in ASCII mode",
1726			    bare_lfs);
1727			printf("   File may not have transferred correctly.\r\n");
1728		}
1729		return (0);
1730	default:
1731		reply(550, "Unimplemented TYPE %d in receive_data", type);
1732		transflag = 0;
1733		return (-1);
1734	}
1735
1736data_err:
1737	transflag = 0;
1738	reply(426, "Data Connection");
1739	return (-1);
1740
1741file_err:
1742	transflag = 0;
1743	reply(452, "Error writing file");
1744	return (-1);
1745
1746got_oob:
1747	myoob();
1748	recvurg = 0;
1749	transflag = 0;
1750	return (-1);
1751}
1752
1753void
1754statfilecmd(char *filename)
1755{
1756	FILE *fin;
1757	int c;
1758	int atstart;
1759	char line[LINE_MAX];
1760
1761	(void)snprintf(line, sizeof(line), "/bin/ls -lgA %s", filename);
1762	fin = ftpd_popen(line, "r");
1763	if (fin == NULL) {
1764		reply(451, "Local resource failure");
1765		return;
1766	}
1767	lreply(211, "status of %s:", filename);
1768	atstart = 1;
1769	while ((c = getc(fin)) != EOF) {
1770		if (c == '\n') {
1771			if (ferror(stdout)){
1772				perror_reply(421, "control connection");
1773				(void) ftpd_pclose(fin);
1774				dologout(1);
1775				/* NOTREACHED */
1776			}
1777			if (ferror(fin)) {
1778				perror_reply(551, filename);
1779				(void) ftpd_pclose(fin);
1780				return;
1781			}
1782			(void) putc('\r', stdout);
1783		}
1784		if (atstart && isdigit(c))
1785			(void) putc(' ', stdout);
1786		(void) putc(c, stdout);
1787		atstart = (c == '\n');
1788	}
1789	(void) ftpd_pclose(fin);
1790	reply(211, "End of Status");
1791}
1792
1793void
1794statcmd(void)
1795{
1796	union sockunion *su;
1797	u_char *a, *p;
1798	char hbuf[MAXHOSTNAMELEN];
1799	int ispassive;
1800	int error;
1801
1802	lreply(211, "%s FTP server status:", hostname);
1803	error = getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len,
1804	    hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
1805	printf("     Connected to %s", remotehost);
1806	if (error == 0 && strcmp(remotehost, hbuf) != 0)
1807		printf(" (%s)", hbuf);
1808	printf("\r\n");
1809	if (logged_in) {
1810		if (guest)
1811			printf("     Logged in anonymously\r\n");
1812		else
1813			printf("     Logged in as %s\r\n", pw->pw_name);
1814	} else if (askpasswd)
1815		printf("     Waiting for password\r\n");
1816	else
1817		printf("     Waiting for user name\r\n");
1818	printf("     TYPE: %s", typenames[type]);
1819	if (type == TYPE_A || type == TYPE_E)
1820		printf(", FORM: %s", formnames[form]);
1821	if (type == TYPE_L)
1822#if NBBY == 8
1823		printf(" %d", NBBY);
1824#else
1825		printf(" %d", bytesize);	/* need definition! */
1826#endif
1827	printf("; STRUcture: %s; transfer MODE: %s\r\n",
1828	    strunames[stru], modenames[mode]);
1829	ispassive = 0;
1830	if (data != -1)
1831		printf("     Data connection open\r\n");
1832	else if (pdata != -1) {
1833		printf("     in Passive mode\r\n");
1834		su = (union sockunion *)&pasv_addr;
1835		ispassive++;
1836		goto printaddr;
1837	} else if (usedefault == 0) {
1838		size_t alen;
1839		int af, i;
1840
1841		su = (union sockunion *)&data_dest;
1842printaddr:
1843		/* PASV/PORT */
1844		if (su->su_family == AF_INET) {
1845			if (ispassive)
1846				printf("211- PASV ");
1847			else
1848				printf("211- PORT ");
1849			a = (u_char *)&su->su_sin.sin_addr;
1850			p = (u_char *)&su->su_sin.sin_port;
1851			printf("(%u,%u,%u,%u,%u,%u)\r\n",
1852			    a[0], a[1], a[2], a[3],
1853			    p[0], p[1]);
1854		}
1855
1856		/* LPSV/LPRT */
1857		alen = 0;
1858		switch (su->su_family) {
1859		case AF_INET:
1860			a = (u_char *)&su->su_sin.sin_addr;
1861			p = (u_char *)&su->su_sin.sin_port;
1862			alen = sizeof(su->su_sin.sin_addr);
1863			af = 4;
1864			break;
1865		case AF_INET6:
1866			a = (u_char *)&su->su_sin6.sin6_addr;
1867			p = (u_char *)&su->su_sin6.sin6_port;
1868			alen = sizeof(su->su_sin6.sin6_addr);
1869			af = 6;
1870			break;
1871		default:
1872			af = 0;
1873			break;
1874		}
1875		if (af) {
1876			if (ispassive)
1877				printf("211- LPSV ");
1878			else
1879				printf("211- LPRT ");
1880			printf("(%u,%llu", af, (unsigned long long)alen);
1881			for (i = 0; i < alen; i++)
1882				printf(",%u", a[i]);
1883			printf(",%u,%u,%u)\r\n", 2, p[0], p[1]);
1884		}
1885
1886		/* EPRT/EPSV */
1887		switch (su->su_family) {
1888		case AF_INET:
1889			af = 1;
1890			break;
1891		case AF_INET6:
1892			af = 2;
1893			break;
1894		default:
1895			af = 0;
1896			break;
1897		}
1898		if (af) {
1899			char pbuf[10];
1900			union sockunion tmp = *su;
1901
1902			if (tmp.su_family == AF_INET6)
1903				tmp.su_sin6.sin6_scope_id = 0;
1904			if (getnameinfo((struct sockaddr *)&tmp, tmp.su_len,
1905			    hbuf, sizeof(hbuf), pbuf, sizeof(pbuf),
1906			    NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
1907				if (ispassive)
1908					printf("211- EPSV ");
1909				else
1910					printf("211- EPRT ");
1911				printf("(|%u|%s|%s|)\r\n",
1912				    af, hbuf, pbuf);
1913			}
1914		}
1915	} else
1916		printf("     No data connection\r\n");
1917	reply(211, "End of status");
1918}
1919
1920void
1921fatal(char *s)
1922{
1923
1924	reply(451, "Error in server: %s", s);
1925	reply(221, "Closing connection due to server error.");
1926	dologout(0);
1927	/* NOTREACHED */
1928}
1929
1930void
1931reply(int n, const char *fmt, ...)
1932{
1933	char *buf, *p, *next;
1934	int rval;
1935	va_list ap;
1936
1937	va_start(ap, fmt);
1938	rval = vasprintf(&buf, fmt, ap);
1939	va_end(ap);
1940	if (rval == -1 || buf == NULL) {
1941		printf("421 Local resource failure: malloc\r\n");
1942		fflush(stdout);
1943		dologout(1);
1944	}
1945	next = buf;
1946	while ((p = strsep(&next, "\n\r"))) {
1947		printf("%d%s %s\r\n", n, (next != '\0') ? "-" : "", p);
1948		if (debug)
1949			syslog(LOG_DEBUG, "<--- %d%s %s", n,
1950			    (next != '\0') ? "-" : "", p);
1951	}
1952	(void)fflush(stdout);
1953	free(buf);
1954}
1955
1956
1957void
1958reply_r(int n, const char *fmt, ...)
1959{
1960	char *p, *next;
1961	char msg[BUFSIZ];
1962	char buf[BUFSIZ];
1963	va_list ap;
1964	struct syslog_data sdata = SYSLOG_DATA_INIT;
1965
1966	sdata.log_fac = LOG_FTP;
1967	va_start(ap, fmt);
1968	vsnprintf(msg, sizeof(msg), fmt, ap);
1969	va_end(ap);
1970
1971	next = msg;
1972
1973	while ((p = strsep(&next, "\n\r"))) {
1974		snprintf(buf, sizeof(buf), "%d%s %s\r\n", n,
1975		    (next != '\0') ? "-" : "", p);
1976		write(STDOUT_FILENO, buf, strlen(buf));
1977		if (debug) {
1978			buf[strlen(buf) - 2] = '\0';
1979			syslog_r(LOG_DEBUG, &sdata, "<--- %s", buf);
1980		}
1981	}
1982}
1983
1984void
1985lreply(int n, const char *fmt, ...)
1986{
1987	va_list ap;
1988
1989	va_start(ap, fmt);
1990	(void)printf("%d- ", n);
1991	(void)vprintf(fmt, ap);
1992	va_end(ap);
1993	(void)printf("\r\n");
1994	(void)fflush(stdout);
1995	if (debug) {
1996		va_start(ap, fmt);
1997		syslog(LOG_DEBUG, "<--- %d- ", n);
1998		vsyslog(LOG_DEBUG, fmt, ap);
1999		va_end(ap);
2000	}
2001}
2002
2003static void
2004ack(char *s)
2005{
2006
2007	reply(250, "%s command successful.", s);
2008}
2009
2010void
2011nack(char *s)
2012{
2013
2014	reply(502, "%s command not implemented.", s);
2015}
2016
2017/* ARGSUSED */
2018void
2019yyerror(char *s)
2020{
2021	cbuf[strcspn(cbuf, "\n")] = '\0';
2022	reply(500, "'%s': command not understood.", cbuf);
2023}
2024
2025void
2026delete(char *name)
2027{
2028	struct stat st;
2029
2030	LOGCMD("delete", name);
2031	if (stat(name, &st) < 0) {
2032		perror_reply(550, name);
2033		return;
2034	}
2035	if ((st.st_mode&S_IFMT) == S_IFDIR) {
2036		if (rmdir(name) < 0) {
2037			perror_reply(550, name);
2038			return;
2039		}
2040		goto done;
2041	}
2042	if (unlink(name) < 0) {
2043		perror_reply(550, name);
2044		return;
2045	}
2046done:
2047	ack("DELE");
2048}
2049
2050void
2051cwd(char *path)
2052{
2053	FILE *message;
2054
2055	if (chdir(path) < 0)
2056		perror_reply(550, path);
2057	else {
2058		if ((message = fopen(_PATH_CWDMESG, "r")) != NULL) {
2059			char line[LINE_MAX];
2060
2061			while (fgets(line, sizeof(line), message) != NULL) {
2062				line[strcspn(line, "\n")] = '\0';
2063				lreply(250, "%s", line);
2064			}
2065			(void) fflush(stdout);
2066			(void) fclose(message);
2067		}
2068		ack("CWD");
2069	}
2070}
2071
2072void
2073replydirname(const char *name, const char *message)
2074{
2075	char *p, *ep;
2076	char npath[MAXPATHLEN * 2];
2077
2078	p = npath;
2079	ep = &npath[sizeof(npath) - 1];
2080	while (*name) {
2081		if (*name == '"') {
2082			if (ep - p < 2)
2083				break;
2084			*p++ = *name++;
2085			*p++ = '"';
2086		} else {
2087			if (ep - p < 1)
2088				break;
2089			*p++ = *name++;
2090		}
2091	}
2092	*p = '\0';
2093	reply(257, "\"%s\" %s", npath, message);
2094}
2095
2096void
2097makedir(char *name)
2098{
2099
2100	LOGCMD("mkdir", name);
2101	if (mkdir(name, 0777) < 0)
2102		perror_reply(550, name);
2103	else
2104		replydirname(name, "directory created.");
2105}
2106
2107void
2108removedir(char *name)
2109{
2110
2111	LOGCMD("rmdir", name);
2112	if (rmdir(name) < 0)
2113		perror_reply(550, name);
2114	else
2115		ack("RMD");
2116}
2117
2118void
2119pwd(void)
2120{
2121	char path[MAXPATHLEN];
2122
2123	if (getcwd(path, sizeof(path)) == NULL)
2124		perror_reply(550, "Can't get current directory");
2125	else
2126		replydirname(path, "is current directory.");
2127}
2128
2129char *
2130renamefrom(char *name)
2131{
2132	struct stat st;
2133
2134	if (stat(name, &st) < 0) {
2135		perror_reply(550, name);
2136		return ((char *)0);
2137	}
2138	reply(350, "File exists, ready for destination name");
2139	return (name);
2140}
2141
2142void
2143renamecmd(char *from, char *to)
2144{
2145
2146	LOGCMD2("rename", from, to);
2147	if (rename(from, to) < 0)
2148		perror_reply(550, "rename");
2149	else
2150		ack("RNTO");
2151}
2152
2153static void
2154dolog(struct sockaddr *sa)
2155{
2156	char hbuf[sizeof(remotehost)];
2157
2158	if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0, 0) == 0)
2159		(void) strlcpy(remotehost, hbuf, sizeof(remotehost));
2160	else
2161		(void) strlcpy(remotehost, "unknown", sizeof(remotehost));
2162
2163#ifdef HASSETPROCTITLE
2164	snprintf(proctitle, sizeof(proctitle), "%s: connected", remotehost);
2165	setproctitle("%s", proctitle);
2166#endif /* HASSETPROCTITLE */
2167
2168	if (logging) {
2169		int error;
2170		error = getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf),
2171		    NULL, 0, NI_NUMERICHOST);
2172		syslog(LOG_INFO, "connection from %s [%s]", remotehost,
2173		    error ? gai_strerror(error) : hbuf);
2174	}
2175}
2176
2177/*
2178 * Record logout in wtmp file and exit with supplied status.
2179 * NOTE: because this is called from signal handlers it cannot
2180 *       use stdio (or call other functions that use stdio).
2181 */
2182void
2183dologout(int status)
2184{
2185
2186	transflag = 0;
2187
2188	if (logged_in) {
2189		sigprocmask(SIG_BLOCK, &allsigs, NULL);
2190		ftpdlogwtmp(ttyline, "", "");
2191		if (doutmp)
2192			ftpd_logout(utmp.ut_line);
2193	}
2194	/* beware of flushing buffers after a SIGPIPE */
2195	_exit(status);
2196}
2197
2198/*ARGSUSED*/
2199static void
2200sigurg(int signo)
2201{
2202
2203	recvurg = 1;
2204}
2205
2206static void
2207myoob(void)
2208{
2209	char *cp;
2210	int ret;
2211
2212	/* only process if transfer occurring */
2213	if (!transflag)
2214		return;
2215	cp = tmpline;
2216	ret = getline(cp, 7, stdin);
2217	if (ret == -1) {
2218		reply(221, "You could at least say goodbye.");
2219		dologout(0);
2220	} else if (ret == -2) {
2221		/* Ignore truncated command */
2222		return;
2223	}
2224	upper(cp);
2225	if (strcmp(cp, "ABOR\r\n") == 0) {
2226		tmpline[0] = '\0';
2227		reply(426, "Transfer aborted. Data connection closed.");
2228		reply(226, "Abort successful");
2229	}
2230	if (strcmp(cp, "STAT\r\n") == 0) {
2231		tmpline[0] = '\0';
2232		if (file_size != (off_t) -1)
2233			reply(213, "Status: %qd of %qd bytes transferred",
2234			    byte_count, file_size);
2235		else
2236			reply(213, "Status: %qd bytes transferred", byte_count);
2237	}
2238}
2239
2240/*
2241 * Note: a response of 425 is not mentioned as a possible response to
2242 *	the PASV command in RFC959. However, it has been blessed as
2243 *	a legitimate response by Jon Postel in a telephone conversation
2244 *	with Rick Adams on 25 Jan 89.
2245 */
2246void
2247passive(void)
2248{
2249	socklen_t len;
2250	int on = 1;
2251	u_char *p, *a;
2252
2253	if (pw == NULL) {
2254		reply(530, "Please login with USER and PASS");
2255		return;
2256	}
2257	if (pdata >= 0)
2258		close(pdata);
2259	/*
2260	 * XXX
2261	 * At this point, it would be nice to have an algorithm that
2262	 * inserted a growing delay in an attack scenario.  Such a thing
2263	 * would look like continual passive sockets being opened, but
2264	 * nothing serious being done with them.  They're not used to
2265	 * move data; the entire attempt is just to use tcp FIN_WAIT
2266	 * resources.
2267	 */
2268	pdata = socket(AF_INET, SOCK_STREAM, 0);
2269	if (pdata < 0) {
2270		perror_reply(425, "Can't open passive connection");
2271		return;
2272	}
2273
2274	if (setsockopt(pdata, SOL_SOCKET, SO_KEEPALIVE,
2275	    &on, sizeof(on)) < 0)
2276		goto pasv_error;
2277
2278	on = IP_PORTRANGE_HIGH;
2279	if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2280	    &on, sizeof(on)) < 0)
2281		goto pasv_error;
2282
2283	pasv_addr = ctrl_addr;
2284	pasv_addr.su_sin.sin_port = 0;
2285	if (bind(pdata, (struct sockaddr *)&pasv_addr,
2286	    pasv_addr.su_len) < 0)
2287		goto pasv_error;
2288
2289	len = sizeof(pasv_addr);
2290	if (getsockname(pdata, (struct sockaddr *)&pasv_addr, &len) < 0)
2291		goto pasv_error;
2292	if (listen(pdata, 1) < 0)
2293		goto pasv_error;
2294	a = (u_char *)&pasv_addr.su_sin.sin_addr;
2295	p = (u_char *)&pasv_addr.su_sin.sin_port;
2296
2297	reply(227, "Entering Passive Mode (%u,%u,%u,%u,%u,%u)", a[0],
2298	    a[1], a[2], a[3], p[0], p[1]);
2299	return;
2300
2301pasv_error:
2302	perror_reply(425, "Can't open passive connection");
2303	(void) close(pdata);
2304	pdata = -1;
2305	return;
2306}
2307
2308int
2309epsvproto2af(int proto)
2310{
2311
2312	switch (proto) {
2313	case 1:	return AF_INET;
2314#ifdef INET6
2315	case 2:	return AF_INET6;
2316#endif
2317	default: return -1;
2318	}
2319}
2320
2321int
2322af2epsvproto(int af)
2323{
2324
2325	switch (af) {
2326	case AF_INET:	return 1;
2327#ifdef INET6
2328	case AF_INET6:	return 2;
2329#endif
2330	default:	return -1;
2331	}
2332}
2333
2334/*
2335 * 228 Entering Long Passive Mode (af, hal, h1, h2, h3,..., pal, p1, p2...)
2336 * 229 Entering Extended Passive Mode (|||port|)
2337 */
2338void
2339long_passive(char *cmd, int pf)
2340{
2341	socklen_t len;
2342	int on = 1;
2343	u_char *p, *a;
2344
2345	if (!logged_in) {
2346		syslog(LOG_NOTICE, "long passive but not logged in");
2347		reply(503, "Login with USER first.");
2348		return;
2349	}
2350
2351	if (pf != PF_UNSPEC && ctrl_addr.su_family != pf) {
2352		/*
2353		 * XXX
2354		 * only EPRT/EPSV ready clients will understand this
2355		 */
2356		if (strcmp(cmd, "EPSV") != 0)
2357			reply(501, "Network protocol mismatch"); /*XXX*/
2358		else
2359			epsv_protounsupp("Network protocol mismatch");
2360
2361		return;
2362	}
2363
2364	if (pdata >= 0)
2365		close(pdata);
2366	/*
2367	 * XXX
2368	 * At this point, it would be nice to have an algorithm that
2369	 * inserted a growing delay in an attack scenario.  Such a thing
2370	 * would look like continual passive sockets being opened, but
2371	 * nothing serious being done with them.  They not used to move
2372	 * data; the entire attempt is just to use tcp FIN_WAIT
2373	 * resources.
2374	 */
2375	pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0);
2376	if (pdata < 0) {
2377		perror_reply(425, "Can't open passive connection");
2378		return;
2379	}
2380
2381	if (setsockopt(pdata, SOL_SOCKET, SO_KEEPALIVE,
2382	    &on, sizeof(on)) < 0)
2383		goto pasv_error;
2384
2385	switch (ctrl_addr.su_family) {
2386	case AF_INET:
2387		on = IP_PORTRANGE_HIGH;
2388		if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2389		    &on, sizeof(on)) < 0)
2390			goto pasv_error;
2391		break;
2392	case AF_INET6:
2393		on = IPV6_PORTRANGE_HIGH;
2394		if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE,
2395		    &on, sizeof(on)) < 0)
2396			goto pasv_error;
2397		break;
2398	}
2399
2400	pasv_addr = ctrl_addr;
2401	pasv_addr.su_port = 0;
2402	if (bind(pdata, (struct sockaddr *)&pasv_addr, pasv_addr.su_len) < 0)
2403		goto pasv_error;
2404	len = pasv_addr.su_len;
2405	if (getsockname(pdata, (struct sockaddr *)&pasv_addr, &len) < 0)
2406		goto pasv_error;
2407	if (listen(pdata, 1) < 0)
2408		goto pasv_error;
2409	p = (u_char *)&pasv_addr.su_port;
2410
2411	if (strcmp(cmd, "LPSV") == 0) {
2412		switch (pasv_addr.su_family) {
2413		case AF_INET:
2414			a = (u_char *)&pasv_addr.su_sin.sin_addr;
2415			reply(228,
2416			    "Entering Long Passive Mode (%u,%u,%u,%u,%u,%u,%u,%u,%u)",
2417			    4, 4, a[0], a[1], a[2], a[3], 2, p[0], p[1]);
2418			return;
2419		case AF_INET6:
2420			a = (u_char *)&pasv_addr.su_sin6.sin6_addr;
2421			reply(228,
2422			    "Entering Long Passive Mode (%u,%u,%u,%u,%u,%u,"
2423			    "%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u)",
2424				6, 16, a[0], a[1], a[2], a[3], a[4],
2425				a[5], a[6], a[7], a[8], a[9], a[10],
2426				a[11], a[12], a[13], a[14], a[15],
2427				2, p[0], p[1]);
2428			return;
2429		}
2430	} else if (strcmp(cmd, "EPSV") == 0) {
2431		switch (pasv_addr.su_family) {
2432		case AF_INET:
2433		case AF_INET6:
2434			reply(229, "Entering Extended Passive Mode (|||%u|)",
2435			    ntohs(pasv_addr.su_port));
2436			return;
2437		}
2438	} else {
2439		/* more proper error code? */
2440	}
2441
2442  pasv_error:
2443	perror_reply(425, "Can't open passive connection");
2444	(void) close(pdata);
2445	pdata = -1;
2446	return;
2447}
2448
2449/*
2450 * EPRT |proto|addr|port|
2451 */
2452int
2453extended_port(const char *arg)
2454{
2455	char *tmp = NULL;
2456	char *result[3];
2457	char *p, *q;
2458	char delim;
2459	struct addrinfo hints;
2460	struct addrinfo *res = NULL;
2461	int i;
2462	unsigned long proto;
2463
2464	if (epsvall) {
2465		reply(501, "EPRT disallowed after EPSV ALL");
2466		return -1;
2467	}
2468
2469	usedefault = 0;
2470	if (pdata >= 0) {
2471		(void) close(pdata);
2472		pdata = -1;
2473	}
2474
2475	tmp = strdup(arg);
2476	if (!tmp) {
2477		fatal("not enough core.");
2478		/*NOTREACHED*/
2479	}
2480	p = tmp;
2481	delim = p[0];
2482	p++;
2483	memset(result, 0, sizeof(result));
2484	for (i = 0; i < 3; i++) {
2485		q = strchr(p, delim);
2486		if (!q || *q != delim)
2487			goto parsefail;
2488		*q++ = '\0';
2489		result[i] = p;
2490		p = q;
2491	}
2492
2493	/* some more sanity check */
2494	p = NULL;
2495	(void)strtoul(result[2], &p, 10);
2496	if (!*result[2] || *p)
2497		goto protounsupp;
2498	p = NULL;
2499	proto = strtoul(result[0], &p, 10);
2500	if (!*result[0] || *p)
2501		goto protounsupp;
2502
2503	memset(&hints, 0, sizeof(hints));
2504	hints.ai_family = epsvproto2af((int)proto);
2505	if (hints.ai_family < 0)
2506		goto protounsupp;
2507	hints.ai_socktype = SOCK_STREAM;
2508	hints.ai_flags = AI_NUMERICHOST;	/*no DNS*/
2509	if (getaddrinfo(result[1], result[2], &hints, &res))
2510		goto parsefail;
2511	if (res->ai_next)
2512		goto parsefail;
2513	if (sizeof(data_dest) < res->ai_addrlen)
2514		goto parsefail;
2515	memcpy(&data_dest, res->ai_addr, res->ai_addrlen);
2516	if (his_addr.su_family == AF_INET6 &&
2517	    data_dest.su_family == AF_INET6) {
2518		/* XXX more sanity checks! */
2519		data_dest.su_sin6.sin6_scope_id =
2520		    his_addr.su_sin6.sin6_scope_id;
2521	}
2522	if (pdata >= 0) {
2523		(void) close(pdata);
2524		pdata = -1;
2525	}
2526	reply(200, "EPRT command successful.");
2527
2528	if (tmp)
2529		free(tmp);
2530	if (res)
2531		freeaddrinfo(res);
2532	return 0;
2533
2534parsefail:
2535	reply(500, "Invalid argument, rejected.");
2536	usedefault = 1;
2537	if (tmp)
2538		free(tmp);
2539	if (res)
2540		freeaddrinfo(res);
2541	return -1;
2542
2543protounsupp:
2544	epsv_protounsupp("Protocol not supported");
2545	usedefault = 1;
2546	if (tmp)
2547		free(tmp);
2548	if (res)
2549		freeaddrinfo(res);
2550	return -1;
2551}
2552
2553/*
2554 * 522 Protocol not supported (proto,...)
2555 * as we assume address family for control and data connections are the same,
2556 * we do not return the list of address families we support - instead, we
2557 * return the address family of the control connection.
2558 */
2559void
2560epsv_protounsupp(const char *message)
2561{
2562	int proto;
2563
2564	proto = af2epsvproto(ctrl_addr.su_family);
2565	if (proto < 0)
2566		reply(501, "%s", message);	/*XXX*/
2567	else
2568		reply(522, "%s, use (%d)", message, proto);
2569}
2570
2571/*
2572 * Generate unique name for file with basename "local".
2573 * The file named "local" is already known to exist.
2574 * Generates failure reply on error.
2575 */
2576static int
2577guniquefd(char *local, char **nam)
2578{
2579	static char new[MAXPATHLEN];
2580	struct stat st;
2581	int count, len, fd;
2582	char *cp;
2583
2584	cp = strrchr(local, '/');
2585	if (cp)
2586		*cp = '\0';
2587	if (stat(cp ? local : ".", &st) < 0) {
2588		perror_reply(553, cp ? local : ".");
2589		return (-1);
2590	}
2591	if (cp)
2592		*cp = '/';
2593	len = strlcpy(new, local, sizeof(new));
2594	if (len+2+1 >= sizeof(new)-1)
2595		return (-1);
2596	cp = new + len;
2597	*cp++ = '.';
2598	for (count = 1; count < 100; count++) {
2599		(void)snprintf(cp, sizeof(new) - (cp - new), "%d", count);
2600		fd = open(new, O_RDWR|O_CREAT|O_EXCL, 0666);
2601		if (fd == -1)
2602			continue;
2603		if (nam)
2604			*nam = new;
2605		return (fd);
2606	}
2607	reply(452, "Unique file name cannot be created.");
2608	return (-1);
2609}
2610
2611/*
2612 * Format and send reply containing system error number.
2613 */
2614void
2615perror_reply(int code, char *string)
2616{
2617
2618	reply(code, "%s: %s.", string, strerror(errno));
2619}
2620
2621static char *onefile[] = {
2622	"",
2623	0
2624};
2625
2626void
2627send_file_list(char *whichf)
2628{
2629	struct stat st;
2630	DIR *dirp = NULL;
2631	struct dirent *dir;
2632	FILE *dout = NULL;
2633	char **dirlist;
2634	char *dirname;
2635	int simple = 0;
2636	volatile int freeglob = 0;
2637	glob_t gl;
2638
2639	if (strpbrk(whichf, "~{[*?") != NULL) {
2640		memset(&gl, 0, sizeof(gl));
2641		freeglob = 1;
2642		if (glob(whichf,
2643		    GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE|GLOB_LIMIT,
2644		    0, &gl)) {
2645			reply(550, "not found");
2646			goto out;
2647		} else if (gl.gl_pathc == 0) {
2648			errno = ENOENT;
2649			perror_reply(550, whichf);
2650			goto out;
2651		}
2652		dirlist = gl.gl_pathv;
2653	} else {
2654		onefile[0] = whichf;
2655		dirlist = onefile;
2656		simple = 1;
2657	}
2658
2659	while ((dirname = *dirlist++)) {
2660		if (stat(dirname, &st) < 0) {
2661			/*
2662			 * If user typed "ls -l", etc, and the client
2663			 * used NLST, do what the user meant.
2664			 */
2665			if (dirname[0] == '-' && *dirlist == NULL &&
2666			    transflag == 0) {
2667				retrieve("/bin/ls %s", dirname);
2668				goto out;
2669			}
2670			perror_reply(550, whichf);
2671			if (dout != NULL) {
2672				(void) fclose(dout);
2673				transflag = 0;
2674				data = -1;
2675				pdata = -1;
2676			}
2677			goto out;
2678		}
2679
2680		if (S_ISREG(st.st_mode)) {
2681			if (dout == NULL) {
2682				dout = dataconn("file list", (off_t)-1, "w");
2683				if (dout == NULL)
2684					goto out;
2685				transflag++;
2686			}
2687			fprintf(dout, "%s%s\n", dirname,
2688				type == TYPE_A ? "\r" : "");
2689			byte_count += strlen(dirname) + 1;
2690			continue;
2691		} else if (!S_ISDIR(st.st_mode))
2692			continue;
2693
2694		if ((dirp = opendir(dirname)) == NULL)
2695			continue;
2696
2697		while ((dir = readdir(dirp)) != NULL) {
2698			char nbuf[MAXPATHLEN];
2699
2700			if (recvurg) {
2701				myoob();
2702				recvurg = 0;
2703				transflag = 0;
2704				goto out;
2705			}
2706
2707			if (dir->d_name[0] == '.' && dir->d_namlen == 1)
2708				continue;
2709			if (dir->d_name[0] == '.' && dir->d_name[1] == '.' &&
2710			    dir->d_namlen == 2)
2711				continue;
2712
2713			snprintf(nbuf, sizeof(nbuf), "%s/%s", dirname,
2714				 dir->d_name);
2715
2716			/*
2717			 * We have to do a stat to insure it's
2718			 * not a directory or special file.
2719			 */
2720			if (simple || (stat(nbuf, &st) == 0 &&
2721			    S_ISREG(st.st_mode))) {
2722				if (dout == NULL) {
2723					dout = dataconn("file list", (off_t)-1,
2724						"w");
2725					if (dout == NULL)
2726						goto out;
2727					transflag++;
2728				}
2729				if (nbuf[0] == '.' && nbuf[1] == '/')
2730					fprintf(dout, "%s%s\n", &nbuf[2],
2731						type == TYPE_A ? "\r" : "");
2732				else
2733					fprintf(dout, "%s%s\n", nbuf,
2734						type == TYPE_A ? "\r" : "");
2735				byte_count += strlen(nbuf) + 1;
2736			}
2737		}
2738		(void) closedir(dirp);
2739	}
2740
2741	if (dout == NULL)
2742		reply(550, "No files found.");
2743	else if (ferror(dout) != 0)
2744		perror_reply(550, "Data connection");
2745	else
2746		reply(226, "Transfer complete.");
2747
2748	transflag = 0;
2749	if (dout != NULL)
2750		(void) fclose(dout);
2751	else {
2752		if (pdata >= 0)
2753			close(pdata);
2754	}
2755	data = -1;
2756	pdata = -1;
2757out:
2758	if (freeglob) {
2759		freeglob = 0;
2760		globfree(&gl);
2761	}
2762}
2763
2764/*ARGSUSED*/
2765static void
2766reapchild(int signo)
2767{
2768	int save_errno = errno;
2769	int rval;
2770
2771	do {
2772		rval = waitpid(-1, NULL, WNOHANG);
2773	} while (rval > 0 || (rval == -1 && errno == EINTR));
2774	errno = save_errno;
2775}
2776
2777void
2778logxfer(char *name, off_t size, time_t start)
2779{
2780	char buf[400 + MAXHOSTNAMELEN*4 + MAXPATHLEN*4];
2781	char dir[MAXPATHLEN], path[MAXPATHLEN], rpath[MAXPATHLEN];
2782	char vremotehost[MAXHOSTNAMELEN*4], vpath[MAXPATHLEN*4];
2783	char *vpw;
2784	time_t now;
2785	int len;
2786
2787	if ((statfd >= 0) && (getcwd(dir, sizeof(dir)) != NULL)) {
2788		time(&now);
2789
2790		vpw = malloc(strlen(guest ? guestpw : pw->pw_name) * 4 + 1);
2791		if (vpw == NULL)
2792			return;
2793
2794		snprintf(path, sizeof(path), "%s/%s", dir, name);
2795		if (realpath(path, rpath) == NULL)
2796			strlcpy(rpath, path, sizeof(rpath));
2797		strvis(vpath, rpath, VIS_SAFE|VIS_NOSLASH);
2798
2799		strvis(vremotehost, remotehost, VIS_SAFE|VIS_NOSLASH);
2800		strvis(vpw, guest? guestpw : pw->pw_name, VIS_SAFE|VIS_NOSLASH);
2801
2802		len = snprintf(buf, sizeof(buf),
2803		    "%.24s %d %s %qd %s %c %s %c %c %s ftp %d %s %s\n",
2804		    ctime(&now), now - start + (now == start),
2805		    vremotehost, (long long)size, vpath,
2806		    ((type == TYPE_A) ? 'a' : 'b'), "*" /* none yet */,
2807		    'o', ((guest) ? 'a' : 'r'),
2808		    vpw, 0 /* none yet */,
2809		    ((guest) ? "*" : pw->pw_name), dhostname);
2810		free(vpw);
2811
2812		if (len >= sizeof(buf) || len == -1) {
2813			if ((len = strlen(buf)) == 0)
2814				return;		/* should not happen */
2815			buf[len - 1] = '\n';
2816		}
2817		write(statfd, buf, len);
2818	}
2819}
2820
2821void
2822set_slave_signals(void)
2823{
2824	struct sigaction sa;
2825
2826	sigemptyset(&sa.sa_mask);
2827	sa.sa_flags = SA_RESTART;
2828
2829	sa.sa_handler = SIG_DFL;
2830	(void) sigaction(SIGCHLD, &sa, NULL);
2831
2832	sa.sa_handler = sigurg;
2833	sa.sa_flags = 0;		/* don't restart syscalls for SIGURG */
2834	(void) sigaction(SIGURG, &sa, NULL);
2835
2836	sigfillset(&sa.sa_mask);	/* block all signals in handler */
2837	sa.sa_flags = SA_RESTART;
2838	sa.sa_handler = sigquit;
2839	(void) sigaction(SIGHUP, &sa, NULL);
2840	(void) sigaction(SIGINT, &sa, NULL);
2841	(void) sigaction(SIGQUIT, &sa, NULL);
2842	(void) sigaction(SIGTERM, &sa, NULL);
2843
2844	sa.sa_handler = lostconn;
2845	(void) sigaction(SIGPIPE, &sa, NULL);
2846
2847	sa.sa_handler = toolong;
2848	(void) sigaction(SIGALRM, &sa, NULL);
2849
2850#ifdef F_SETOWN
2851	if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1)
2852		syslog(LOG_ERR, "fcntl F_SETOWN: %m");
2853#endif
2854}
2855
2856#if defined(TCPWRAPPERS)
2857static int
2858check_host(struct sockaddr *sa)
2859{
2860	struct sockaddr_in *sin;
2861	struct hostent *hp;
2862	char *addr;
2863
2864	if (sa->sa_family != AF_INET)
2865		return 1;	/*XXX*/
2866
2867	sin = (struct sockaddr_in *)sa;
2868	hp = gethostbyaddr((char *)&sin->sin_addr,
2869	    sizeof(struct in_addr), AF_INET);
2870	addr = inet_ntoa(sin->sin_addr);
2871	if (hp) {
2872		if (!hosts_ctl("ftpd", hp->h_name, addr, STRING_UNKNOWN)) {
2873			syslog(LOG_NOTICE, "tcpwrappers rejected: %s [%s]",
2874			    hp->h_name, addr);
2875			return (0);
2876		}
2877	} else {
2878		if (!hosts_ctl("ftpd", STRING_UNKNOWN, addr, STRING_UNKNOWN)) {
2879			syslog(LOG_NOTICE, "tcpwrappers rejected: [%s]", addr);
2880			return (0);
2881		}
2882	}
2883	return (1);
2884}
2885#endif	/* TCPWRAPPERS */
2886
2887/*
2888 * Allocate space and return a copy of the specified dir.
2889 * If 'dir' begins with a tilde (~), expand it.
2890 */
2891char *
2892copy_dir(char *dir, struct passwd *pw)
2893{
2894	char *cp;
2895	char *newdir;
2896	char *user = NULL;
2897
2898	/* Nothing to expand */
2899	if (dir[0] != '~')
2900		return (strdup(dir));
2901
2902	/* "dir" is of form ~user/some/dir, lookup user. */
2903	if (dir[1] != '/' && dir[1] != '\0') {
2904		if ((cp = strchr(dir + 1, '/')) == NULL)
2905			cp = dir + strlen(dir);
2906		if ((user = malloc((size_t)(cp - dir))) == NULL)
2907			return (NULL);
2908		strlcpy(user, dir + 1, (size_t)(cp - dir));
2909
2910		/* Only do lookup if it is a different user. */
2911		if (strcmp(user, pw->pw_name) != 0) {
2912			if ((pw = getpwnam(user)) == NULL) {
2913				/* No such user, interpret literally */
2914				free(user);
2915				return(strdup(dir));
2916			}
2917		}
2918		free(user);
2919	}
2920
2921	/*
2922	 * If there is no directory separator (/) then it is just pw_dir.
2923	 * Otherwise, replace ~foo with pw_dir.
2924	 */
2925	if ((cp = strchr(dir + 1, '/')) == NULL) {
2926		newdir = strdup(pw->pw_dir);
2927	} else {
2928		if (asprintf(&newdir, "%s%s", pw->pw_dir, cp) == -1)
2929			return (NULL);
2930	}
2931
2932	return(newdir);
2933}
2934