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