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