ftpd.c revision 1.228
1/*	$OpenBSD: ftpd.c,v 1.228 2019/07/03 03:24:04 deraadt 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) == -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) 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)) == -1)
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) == -1) {
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) == -1 || chdir("/") == -1) {
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) == -1 || chdir("/") == -1) {
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) == -1) {
1042		if (chdir("/") == -1) {
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) == -1) {
1050		reply(550, "Can't set gid.");
1051		goto bad;
1052	}
1053	if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1) {
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(enum ret_cmd cmd, char *name)
1117{
1118	FILE *fin, *dout;
1119	struct stat st;
1120	pid_t pid;
1121	time_t start;
1122
1123	if (cmd == RET_FILE) {
1124		fin = fopen(name, "r");
1125		st.st_size = 0;
1126	} else {
1127		fin = ftpd_ls("-lgA", name, &pid);
1128		st.st_size = -1;
1129		st.st_blksize = BUFSIZ;
1130	}
1131	if (fin == NULL) {
1132		if (errno != 0) {
1133			perror_reply(550, name);
1134			if (cmd == RET_FILE) {
1135				LOGCMD("get", name);
1136			}
1137		}
1138		return;
1139	}
1140	byte_count = -1;
1141	if (cmd == RET_FILE &&
1142	    (fstat(fileno(fin), &st) == -1 || !S_ISREG(st.st_mode))) {
1143		reply(550, "%s: not a plain file.", name);
1144		goto done;
1145	}
1146	if (restart_point) {
1147		if (type == TYPE_A) {
1148			off_t i, n;
1149			int c;
1150
1151			n = restart_point;
1152			i = 0;
1153			while (i++ < n) {
1154				if ((c = getc(fin)) == EOF) {
1155					if (ferror(fin)) {
1156						perror_reply(550, name);
1157						goto done;
1158					} else
1159						break;
1160				}
1161				if (c == '\n')
1162					i++;
1163			}
1164		} else if (lseek(fileno(fin), restart_point, SEEK_SET) == -1) {
1165			perror_reply(550, name);
1166			goto done;
1167		}
1168	}
1169	dout = dataconn(name, st.st_size, "w");
1170	if (dout == NULL)
1171		goto done;
1172	time(&start);
1173	send_data(fin, dout, st.st_blksize, st.st_size,
1174	    (restart_point == 0 && cmd == RET_FILE && S_ISREG(st.st_mode)));
1175	if ((cmd == RET_FILE) && stats)
1176		logxfer(name, byte_count, start);
1177	(void) fclose(dout);
1178	data = -1;
1179done:
1180	if (pdata >= 0)
1181		(void) close(pdata);
1182	pdata = -1;
1183	if (cmd == RET_FILE) {
1184		LOGBYTES("get", name, byte_count);
1185		fclose(fin);
1186	} else {
1187		ftpd_pclose(fin, pid);
1188	}
1189}
1190
1191void
1192store(char *name, char *mode, int unique)
1193{
1194	FILE *fout, *din;
1195	int (*closefunc)(FILE *);
1196	struct stat st;
1197	int fd;
1198
1199	if (restart_point && *mode != 'a')
1200		mode = "r+";
1201
1202	if (unique && stat(name, &st) == 0) {
1203		char *nam;
1204
1205		fd = guniquefd(name, &nam);
1206		if (fd == -1) {
1207			LOGCMD(*mode == 'w' ? "put" : "append", name);
1208			return;
1209		}
1210		name = nam;
1211		fout = fdopen(fd, mode);
1212	} else
1213		fout = fopen(name, mode);
1214
1215	closefunc = fclose;
1216	if (fout == NULL) {
1217		perror_reply(553, name);
1218		LOGCMD(*mode == 'w' ? "put" : "append", name);
1219		return;
1220	}
1221	byte_count = -1;
1222	if (restart_point) {
1223		if (type == TYPE_A) {
1224			off_t i, n;
1225			int c;
1226
1227			n = restart_point;
1228			i = 0;
1229			while (i++ < n) {
1230				if ((c = getc(fout)) == EOF) {
1231					if (ferror(fout)) {
1232						perror_reply(550, name);
1233						goto done;
1234					} else
1235						break;
1236				}
1237				if (c == '\n')
1238					i++;
1239			}
1240			/*
1241			 * We must do this seek to "current" position
1242			 * because we are changing from reading to
1243			 * writing.
1244			 */
1245			if (fseek(fout, 0, SEEK_CUR) == -1) {
1246				perror_reply(550, name);
1247				goto done;
1248			}
1249		} else if (lseek(fileno(fout), restart_point, SEEK_SET) == -1) {
1250			perror_reply(550, name);
1251			goto done;
1252		}
1253	}
1254	din = dataconn(name, -1, "r");
1255	if (din == NULL)
1256		goto done;
1257	if (receive_data(din, fout) == 0) {
1258		if (unique)
1259			reply(226, "Transfer complete (unique file name:%s).",
1260			    name);
1261		else
1262			reply(226, "Transfer complete.");
1263	}
1264	(void) fclose(din);
1265	data = -1;
1266	pdata = -1;
1267done:
1268	LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count);
1269	(*closefunc)(fout);
1270}
1271
1272static FILE *
1273getdatasock(char *mode)
1274{
1275	int opt, s, t, tries;
1276
1277	if (data >= 0)
1278		return (fdopen(data, mode));
1279	sigprocmask (SIG_BLOCK, &allsigs, NULL);
1280	s = monitor_socket(ctrl_addr.su_family);
1281	if (s < 0)
1282		goto bad;
1283	opt = 1;
1284	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
1285	    &opt, sizeof(opt)) == -1)
1286		goto bad;
1287	/* anchor socket to avoid multi-homing problems */
1288	data_source = ctrl_addr;
1289	data_source.su_port = htons(20); /* ftp-data port */
1290	for (tries = 1; ; tries++) {
1291		if (monitor_bind(s, (struct sockaddr *)&data_source,
1292		    data_source.su_len) >= 0)
1293			break;
1294		if (errno != EADDRINUSE || tries > 10)
1295			goto bad;
1296		sleep((unsigned int)tries);
1297	}
1298	sigprocmask (SIG_UNBLOCK, &allsigs, NULL);
1299
1300	opt = IPTOS_THROUGHPUT;
1301	switch (ctrl_addr.su_family) {
1302	case AF_INET:
1303		if (setsockopt(s, IPPROTO_IP, IP_TOS, &opt,
1304		    sizeof(opt)) == -1)
1305			syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
1306		break;
1307	case AF_INET6:
1308		if (setsockopt(s, IPPROTO_IPV6, IPV6_TCLASS, &opt,
1309		    sizeof(opt)) == -1)
1310			syslog(LOG_WARNING, "setsockopt (IPV6_TCLASS): %m");
1311		break;
1312	}
1313	/*
1314	 * Turn off push flag to keep sender TCP from sending short packets
1315	 * at the boundaries of each write().  Should probably do a SO_SNDBUF
1316	 * to set the send buffer size as well, but that may not be desirable
1317	 * in heavy-load situations.
1318	 */
1319	opt = 1;
1320	if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, &opt, sizeof(opt)) == -1)
1321		syslog(LOG_WARNING, "setsockopt (TCP_NOPUSH): %m");
1322	opt = 65536;
1323	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)) == -1)
1324		syslog(LOG_WARNING, "setsockopt (SO_SNDBUF): %m");
1325
1326	return (fdopen(s, mode));
1327bad:
1328	/* Return the real value of errno (close may change it) */
1329	t = errno;
1330	sigprocmask (SIG_UNBLOCK, &allsigs, NULL);
1331	if (s >= 0)
1332		(void) close(s);
1333	errno = t;
1334	return (NULL);
1335}
1336
1337static FILE *
1338dataconn(char *name, off_t size, char *mode)
1339{
1340	char sizebuf[32];
1341	FILE *file = NULL;
1342	int retry = 0;
1343	in_port_t *p;
1344	u_char *fa, *ha;
1345	size_t alen;
1346	int error;
1347
1348	file_size = size;
1349	byte_count = 0;
1350	if (size != -1) {
1351		(void) snprintf(sizebuf, sizeof(sizebuf), " (%lld bytes)",
1352		    (long long)size);
1353	} else
1354		sizebuf[0] = '\0';
1355	if (pdata >= 0) {
1356		union sockunion from;
1357		int s;
1358		socklen_t fromlen = sizeof(from);
1359
1360		(void) alarm ((unsigned) timeout);
1361		s = accept(pdata, (struct sockaddr *)&from, &fromlen);
1362		(void) alarm (0);
1363		if (s == -1) {
1364			reply(425, "Can't open data connection.");
1365			(void) close(pdata);
1366			pdata = -1;
1367			return (NULL);
1368		}
1369		switch (from.su_family) {
1370		case AF_INET:
1371			p = (in_port_t *)&from.su_sin.sin_port;
1372			fa = (u_char *)&from.su_sin.sin_addr;
1373			ha = (u_char *)&his_addr.su_sin.sin_addr;
1374			alen = sizeof(struct in_addr);
1375			break;
1376		case AF_INET6:
1377			p = (in_port_t *)&from.su_sin6.sin6_port;
1378			fa = (u_char *)&from.su_sin6.sin6_addr;
1379			ha = (u_char *)&his_addr.su_sin6.sin6_addr;
1380			alen = sizeof(struct in6_addr);
1381			break;
1382		default:
1383			reply(425, "Can't build data connection: "
1384			    "unknown address family");
1385			(void) close(pdata);
1386			(void) close(s);
1387			pdata = -1;
1388			return (NULL);
1389		}
1390		if (from.su_family != his_addr.su_family ||
1391		    ntohs(*p) < IPPORT_RESERVED) {
1392			reply(425, "Can't build data connection: "
1393			    "address family or port error");
1394			(void) close(pdata);
1395			(void) close(s);
1396			pdata = -1;
1397			return (NULL);
1398		}
1399		if (portcheck && memcmp(fa, ha, alen) != 0) {
1400			reply(425, "Can't build data connection: "
1401			    "illegal port number");
1402			(void) close(pdata);
1403			(void) close(s);
1404			pdata = -1;
1405			return (NULL);
1406		}
1407		(void) close(pdata);
1408		pdata = s;
1409		reply(150, "Opening %s mode data connection for '%s'%s.",
1410		    type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1411		return (fdopen(pdata, mode));
1412	}
1413	if (data >= 0) {
1414		reply(125, "Using existing data connection for '%s'%s.",
1415		    name, sizebuf);
1416		usedefault = 1;
1417		return (fdopen(data, mode));
1418	}
1419	if (usedefault)
1420		data_dest = his_addr;
1421	usedefault = 1;
1422	do {
1423		if (file != NULL)
1424			(void) fclose(file);
1425		file = getdatasock(mode);
1426		if (file == NULL) {
1427			char hbuf[HOST_NAME_MAX+1], pbuf[10];
1428
1429			error = getnameinfo((struct sockaddr *)&data_source,
1430			    data_source.su_len, hbuf, sizeof(hbuf), pbuf,
1431			    sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV);
1432			if (error != 0)
1433				reply(425, "Can't create data socket: %s.",
1434				    strerror(errno));
1435			else
1436				reply(425,
1437				    "Can't create data socket (%s,%s): %s.",
1438				    hbuf, pbuf, strerror(errno));
1439			return (NULL);
1440		}
1441
1442		/*
1443		 * attempt to connect to reserved port on client machine;
1444		 * this looks like an attack
1445		 */
1446		switch (data_dest.su_family) {
1447		case AF_INET:
1448			p = (in_port_t *)&data_dest.su_sin.sin_port;
1449			fa = (u_char *)&data_dest.su_sin.sin_addr;
1450			ha = (u_char *)&his_addr.su_sin.sin_addr;
1451			alen = sizeof(struct in_addr);
1452			break;
1453		case AF_INET6:
1454			p = (in_port_t *)&data_dest.su_sin6.sin6_port;
1455			fa = (u_char *)&data_dest.su_sin6.sin6_addr;
1456			ha = (u_char *)&his_addr.su_sin6.sin6_addr;
1457			alen = sizeof(struct in6_addr);
1458			break;
1459		default:
1460			reply(425, "Can't build data connection: "
1461			    "unknown address family");
1462			(void) fclose(file);
1463			pdata = -1;
1464			return (NULL);
1465		}
1466		if (data_dest.su_family != his_addr.su_family ||
1467		    ntohs(*p) < IPPORT_RESERVED || ntohs(*p) == 2049) { /* XXX */
1468			reply(425, "Can't build data connection: "
1469			    "address family or port error");
1470			(void) fclose(file);
1471			return NULL;
1472		}
1473		if (portcheck && memcmp(fa, ha, alen) != 0) {
1474			reply(435, "Can't build data connection: "
1475			    "illegal port number");
1476			(void) fclose(file);
1477			return NULL;
1478		}
1479
1480		if (connect(fileno(file), (struct sockaddr *)&data_dest,
1481		    data_dest.su_len) == 0) {
1482			reply(150, "Opening %s mode data connection for '%s'%s.",
1483			    type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1484			data = fileno(file);
1485			return (file);
1486		}
1487		if (errno != EADDRINUSE)
1488			break;
1489		sleep((unsigned) swaitint);
1490		retry += swaitint;
1491	} while (retry <= swaitmax);
1492	perror_reply(425, "Can't build data connection");
1493	(void) fclose(file);
1494	return (NULL);
1495}
1496
1497/*
1498 * Transfer the contents of "instr" to "outstr" peer using the appropriate
1499 * encapsulation of the data subject to Mode, Structure, and Type.
1500 *
1501 * NB: Form isn't handled.
1502 */
1503static int
1504send_data(FILE *instr, FILE *outstr, off_t blksize, off_t filesize, int isreg)
1505{
1506	int c, cnt, filefd, netfd;
1507	char *buf, *bp;
1508	size_t len;
1509
1510	transflag++;
1511	switch (type) {
1512
1513	case TYPE_A:
1514		while ((c = getc(instr)) != EOF) {
1515			if (recvurg)
1516				goto got_oob;
1517			byte_count++;
1518			if (c == '\n') {
1519				if (ferror(outstr))
1520					goto data_err;
1521				(void) putc('\r', outstr);
1522			}
1523			(void) putc(c, outstr);
1524		}
1525		fflush(outstr);
1526		transflag = 0;
1527		if (ferror(instr))
1528			goto file_err;
1529		if (ferror(outstr))
1530			goto data_err;
1531		reply(226, "Transfer complete.");
1532		return(0);
1533
1534	case TYPE_I:
1535	case TYPE_L:
1536		/*
1537		 * isreg is only set if we are not doing restart and we
1538		 * are sending a regular file
1539		 */
1540		netfd = fileno(outstr);
1541		filefd = fileno(instr);
1542
1543		if (isreg && filesize < 16 * 1024 * 1024) {
1544			size_t fsize = (size_t)filesize;
1545
1546			if (fsize == 0) {
1547				transflag = 0;
1548				reply(226, "Transfer complete.");
1549				return(0);
1550			}
1551
1552			buf = mmap(0, fsize, PROT_READ, MAP_SHARED, filefd, 0);
1553			if (buf == MAP_FAILED) {
1554				syslog(LOG_WARNING, "mmap(%llu): %m",
1555				    (unsigned long long)fsize);
1556				goto oldway;
1557			}
1558			bp = buf;
1559			len = fsize;
1560			do {
1561				cnt = write(netfd, bp, len);
1562				if (recvurg) {
1563					munmap(buf, fsize);
1564					goto got_oob;
1565				}
1566				len -= cnt;
1567				bp += cnt;
1568				if (cnt > 0)
1569					byte_count += cnt;
1570			} while(cnt > 0 && len > 0);
1571
1572			transflag = 0;
1573			munmap(buf, fsize);
1574			if (cnt < 0)
1575				goto data_err;
1576			reply(226, "Transfer complete.");
1577			return(0);
1578		}
1579
1580oldway:
1581		if ((buf = malloc((size_t)blksize)) == NULL) {
1582			transflag = 0;
1583			perror_reply(451, "Local resource failure: malloc");
1584			return(-1);
1585		}
1586
1587		while ((cnt = read(filefd, buf, (size_t)blksize)) > 0 &&
1588		    write(netfd, buf, cnt) == cnt)
1589			byte_count += cnt;
1590		transflag = 0;
1591		(void)free(buf);
1592		if (cnt != 0) {
1593			if (cnt == -1)
1594				goto file_err;
1595			goto data_err;
1596		}
1597		reply(226, "Transfer complete.");
1598		return(0);
1599	default:
1600		transflag = 0;
1601		reply(550, "Unimplemented TYPE %d in send_data", type);
1602		return(-1);
1603	}
1604
1605data_err:
1606	transflag = 0;
1607	reply(426, "Data connection");
1608	return(-1);
1609
1610file_err:
1611	transflag = 0;
1612	reply(551, "Error on input file");
1613	return(-1);
1614
1615got_oob:
1616	myoob();
1617	recvurg = 0;
1618	transflag = 0;
1619	return(-1);
1620}
1621
1622/*
1623 * Transfer data from peer to "outstr" using the appropriate encapulation of
1624 * the data subject to Mode, Structure, and Type.
1625 *
1626 * N.B.: Form isn't handled.
1627 */
1628static int
1629receive_data(FILE *instr, FILE *outstr)
1630{
1631	int c;
1632	int cnt;
1633	char buf[BUFSIZ];
1634	struct sigaction sa, sa_saved;
1635	volatile int bare_lfs = 0;
1636
1637	transflag++;
1638	switch (type) {
1639
1640	case TYPE_I:
1641	case TYPE_L:
1642		memset(&sa, 0, sizeof(sa));
1643		sigfillset(&sa.sa_mask);
1644		sa.sa_flags = SA_RESTART;
1645		sa.sa_handler = lostconn;
1646		(void) sigaction(SIGALRM, &sa, &sa_saved);
1647		do {
1648			(void) alarm ((unsigned) timeout);
1649			cnt = read(fileno(instr), buf, sizeof(buf));
1650			(void) alarm (0);
1651			if (recvurg)
1652				goto got_oob;
1653
1654			if (cnt > 0) {
1655				if (write(fileno(outstr), buf, cnt) != cnt)
1656					goto file_err;
1657				byte_count += cnt;
1658			}
1659		} while (cnt > 0);
1660		(void) sigaction(SIGALRM, &sa_saved, NULL);
1661		if (cnt == -1)
1662			goto data_err;
1663		transflag = 0;
1664		return (0);
1665
1666	case TYPE_E:
1667		reply(553, "TYPE E not implemented.");
1668		transflag = 0;
1669		return (-1);
1670
1671	case TYPE_A:
1672		while ((c = getc(instr)) != EOF) {
1673			if (recvurg)
1674				goto got_oob;
1675			byte_count++;
1676			if (c == '\n')
1677				bare_lfs++;
1678			while (c == '\r') {
1679				if (ferror(outstr))
1680					goto data_err;
1681				if ((c = getc(instr)) != '\n') {
1682					(void) putc ('\r', outstr);
1683					if (c == '\0' || c == EOF)
1684						goto contin2;
1685				}
1686			}
1687			(void) putc(c, outstr);
1688	contin2:	;
1689		}
1690		fflush(outstr);
1691		if (ferror(instr))
1692			goto data_err;
1693		if (ferror(outstr))
1694			goto file_err;
1695		transflag = 0;
1696		if (bare_lfs) {
1697			lreply(226,
1698			    "WARNING! %d bare linefeeds received in ASCII mode",
1699			    bare_lfs);
1700			printf("   File may not have transferred correctly.\r\n");
1701		}
1702		return (0);
1703	default:
1704		reply(550, "Unimplemented TYPE %d in receive_data", type);
1705		transflag = 0;
1706		return (-1);
1707	}
1708
1709data_err:
1710	transflag = 0;
1711	reply(426, "Data Connection");
1712	return (-1);
1713
1714file_err:
1715	transflag = 0;
1716	reply(452, "Error writing file");
1717	return (-1);
1718
1719got_oob:
1720	myoob();
1721	recvurg = 0;
1722	transflag = 0;
1723	return (-1);
1724}
1725
1726void
1727statfilecmd(char *filename)
1728{
1729	FILE *fin;
1730	int c;
1731	int atstart;
1732	pid_t pid;
1733	fin = ftpd_ls("-lgA", filename, &pid);
1734	if (fin == NULL) {
1735		reply(451, "Local resource failure");
1736		return;
1737	}
1738	lreply(211, "status of %s:", filename);
1739	atstart = 1;
1740	while ((c = getc(fin)) != EOF) {
1741		if (c == '\n') {
1742			if (ferror(stdout)){
1743				perror_reply(421, "control connection");
1744				(void) ftpd_pclose(fin, pid);
1745				dologout(1);
1746				/* NOTREACHED */
1747			}
1748			if (ferror(fin)) {
1749				perror_reply(551, filename);
1750				(void) ftpd_pclose(fin, pid);
1751				return;
1752			}
1753			(void) putc('\r', stdout);
1754		}
1755		if (atstart && isdigit(c))
1756			(void) putc(' ', stdout);
1757		(void) putc(c, stdout);
1758		atstart = (c == '\n');
1759	}
1760	(void) ftpd_pclose(fin, pid);
1761	reply(211, "End of Status");
1762}
1763
1764void
1765statcmd(void)
1766{
1767	union sockunion *su;
1768	u_char *a, *p;
1769	char hbuf[HOST_NAME_MAX+1];
1770	int ispassive;
1771	int error;
1772
1773	lreply(211, "%s FTP server status:", hostname);
1774	error = getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len,
1775	    hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
1776	printf("     Connected to %s", remotehost);
1777	if (error == 0 && strcmp(remotehost, hbuf) != 0)
1778		printf(" (%s)", hbuf);
1779	printf("\r\n");
1780	if (logged_in) {
1781		if (guest)
1782			printf("     Logged in anonymously\r\n");
1783		else
1784			printf("     Logged in as %s\r\n", pw->pw_name);
1785	} else if (askpasswd)
1786		printf("     Waiting for password\r\n");
1787	else
1788		printf("     Waiting for user name\r\n");
1789	printf("     TYPE: %s", typenames[type]);
1790	if (type == TYPE_A || type == TYPE_E)
1791		printf(", FORM: %s", formnames[form]);
1792	if (type == TYPE_L)
1793		printf(" 8");
1794	printf("; STRUcture: %s; transfer MODE: %s\r\n",
1795	    strunames[stru], modenames[mode]);
1796	ispassive = 0;
1797	if (data != -1)
1798		printf("     Data connection open\r\n");
1799	else if (pdata != -1) {
1800		printf("     in Passive mode\r\n");
1801		su = (union sockunion *)&pasv_addr;
1802		ispassive++;
1803		goto printaddr;
1804	} else if (usedefault == 0) {
1805		size_t alen, i;
1806		int af;
1807
1808		su = (union sockunion *)&data_dest;
1809printaddr:
1810		/* PASV/PORT */
1811		if (su->su_family == AF_INET) {
1812			if (ispassive)
1813				printf("211- PASV ");
1814			else
1815				printf("211- PORT ");
1816			a = (u_char *)&su->su_sin.sin_addr;
1817			p = (u_char *)&su->su_sin.sin_port;
1818			printf("(%u,%u,%u,%u,%u,%u)\r\n",
1819			    a[0], a[1], a[2], a[3],
1820			    p[0], p[1]);
1821		}
1822
1823		/* LPSV/LPRT */
1824		alen = 0;
1825		switch (su->su_family) {
1826		case AF_INET:
1827			a = (u_char *)&su->su_sin.sin_addr;
1828			p = (u_char *)&su->su_sin.sin_port;
1829			alen = sizeof(su->su_sin.sin_addr);
1830			af = 4;
1831			break;
1832		case AF_INET6:
1833			a = (u_char *)&su->su_sin6.sin6_addr;
1834			p = (u_char *)&su->su_sin6.sin6_port;
1835			alen = sizeof(su->su_sin6.sin6_addr);
1836			af = 6;
1837			break;
1838		default:
1839			af = 0;
1840			break;
1841		}
1842		if (af) {
1843			if (ispassive)
1844				printf("211- LPSV ");
1845			else
1846				printf("211- LPRT ");
1847			printf("(%u,%llu", af, (unsigned long long)alen);
1848			for (i = 0; i < alen; i++)
1849				printf(",%u", a[i]);
1850			printf(",%u,%u,%u)\r\n", 2, p[0], p[1]);
1851		}
1852
1853		/* EPRT/EPSV */
1854		switch (su->su_family) {
1855		case AF_INET:
1856			af = 1;
1857			break;
1858		case AF_INET6:
1859			af = 2;
1860			break;
1861		default:
1862			af = 0;
1863			break;
1864		}
1865		if (af) {
1866			char pbuf[10];
1867			union sockunion tmp = *su;
1868
1869			if (tmp.su_family == AF_INET6)
1870				tmp.su_sin6.sin6_scope_id = 0;
1871			if (getnameinfo((struct sockaddr *)&tmp, tmp.su_len,
1872			    hbuf, sizeof(hbuf), pbuf, sizeof(pbuf),
1873			    NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
1874				if (ispassive)
1875					printf("211- EPSV ");
1876				else
1877					printf("211- EPRT ");
1878				printf("(|%u|%s|%s|)\r\n",
1879				    af, hbuf, pbuf);
1880			}
1881		}
1882	} else
1883		printf("     No data connection\r\n");
1884	reply(211, "End of status");
1885}
1886
1887void
1888fatal(char *s)
1889{
1890
1891	reply(451, "Error in server: %s", s);
1892	reply(221, "Closing connection due to server error.");
1893	dologout(0);
1894	/* NOTREACHED */
1895}
1896
1897void
1898reply(int n, const char *fmt, ...)
1899{
1900	char *buf, *p, *next;
1901	int rval;
1902	va_list ap;
1903
1904	va_start(ap, fmt);
1905	rval = vasprintf(&buf, fmt, ap);
1906	va_end(ap);
1907	if (rval == -1 || buf == NULL) {
1908		printf("421 Local resource failure: malloc\r\n");
1909		fflush(stdout);
1910		dologout(1);
1911	}
1912	next = buf;
1913	while ((p = strsep(&next, "\n\r"))) {
1914		printf("%d%s %s\r\n", n, (next != NULL) ? "-" : "", p);
1915		if (debug)
1916			syslog(LOG_DEBUG, "<--- %d%s %s", n,
1917			    (next != NULL) ? "-" : "", p);
1918	}
1919	(void)fflush(stdout);
1920	free(buf);
1921}
1922
1923
1924void
1925reply_r(int n, const char *fmt, ...)
1926{
1927	char *p, *next;
1928	char msg[BUFSIZ];
1929	char buf[BUFSIZ];
1930	va_list ap;
1931	struct syslog_data sdata = SYSLOG_DATA_INIT;
1932
1933	sdata.log_fac = LOG_FTP;
1934	va_start(ap, fmt);
1935	vsnprintf(msg, sizeof(msg), fmt, ap);
1936	va_end(ap);
1937
1938	next = msg;
1939
1940	while ((p = strsep(&next, "\n\r"))) {
1941		snprintf(buf, sizeof(buf), "%d%s %s\r\n", n,
1942		    (next != NULL) ? "-" : "", p);
1943		write(STDOUT_FILENO, buf, strlen(buf));
1944		if (debug) {
1945			buf[strlen(buf) - 2] = '\0';
1946			syslog_r(LOG_DEBUG, &sdata, "<--- %s", buf);
1947		}
1948	}
1949}
1950
1951void
1952lreply(int n, const char *fmt, ...)
1953{
1954	va_list ap;
1955
1956	va_start(ap, fmt);
1957	(void)printf("%d- ", n);
1958	(void)vprintf(fmt, ap);
1959	va_end(ap);
1960	(void)printf("\r\n");
1961	(void)fflush(stdout);
1962	if (debug) {
1963		va_start(ap, fmt);
1964		syslog(LOG_DEBUG, "<--- %d- ", n);
1965		vsyslog(LOG_DEBUG, fmt, ap);
1966		va_end(ap);
1967	}
1968}
1969
1970static void
1971ack(char *s)
1972{
1973
1974	reply(250, "%s command successful.", s);
1975}
1976
1977void
1978nack(char *s)
1979{
1980
1981	reply(502, "%s command not implemented.", s);
1982}
1983
1984/* ARGSUSED */
1985void
1986yyerror(char *s)
1987{
1988	cbuf[strcspn(cbuf, "\n")] = '\0';
1989	reply(500, "'%s': command not understood.", cbuf);
1990}
1991
1992void
1993delete(char *name)
1994{
1995	struct stat st;
1996
1997	LOGCMD("delete", name);
1998	if (stat(name, &st) == -1) {
1999		perror_reply(550, name);
2000		return;
2001	}
2002	if ((st.st_mode&S_IFMT) == S_IFDIR) {
2003		if (rmdir(name) == -1) {
2004			perror_reply(550, name);
2005			return;
2006		}
2007		goto done;
2008	}
2009	if (unlink(name) == -1) {
2010		perror_reply(550, name);
2011		return;
2012	}
2013done:
2014	ack("DELE");
2015}
2016
2017void
2018cwd(char *path)
2019{
2020	FILE *message;
2021
2022	if (chdir(path) == -1)
2023		perror_reply(550, path);
2024	else {
2025		if ((message = fopen(_PATH_CWDMESG, "r")) != NULL) {
2026			char line[LINE_MAX];
2027
2028			while (fgets(line, sizeof(line), message) != NULL) {
2029				line[strcspn(line, "\n")] = '\0';
2030				lreply(250, "%s", line);
2031			}
2032			(void) fflush(stdout);
2033			(void) fclose(message);
2034		}
2035		ack("CWD");
2036	}
2037}
2038
2039void
2040replydirname(const char *name, const char *message)
2041{
2042	char *p, *ep;
2043	char npath[PATH_MAX * 2];
2044
2045	p = npath;
2046	ep = &npath[sizeof(npath) - 1];
2047	while (*name) {
2048		if (*name == '"') {
2049			if (ep - p < 2)
2050				break;
2051			*p++ = *name++;
2052			*p++ = '"';
2053		} else {
2054			if (ep - p < 1)
2055				break;
2056			*p++ = *name++;
2057		}
2058	}
2059	*p = '\0';
2060	reply(257, "\"%s\" %s", npath, message);
2061}
2062
2063void
2064makedir(char *name)
2065{
2066
2067	LOGCMD("mkdir", name);
2068	if (mkdir(name, 0777) == -1)
2069		perror_reply(550, name);
2070	else
2071		replydirname(name, "directory created.");
2072}
2073
2074void
2075removedir(char *name)
2076{
2077
2078	LOGCMD("rmdir", name);
2079	if (rmdir(name) == -1)
2080		perror_reply(550, name);
2081	else
2082		ack("RMD");
2083}
2084
2085void
2086pwd(void)
2087{
2088	char path[PATH_MAX];
2089
2090	if (getcwd(path, sizeof(path)) == NULL)
2091		perror_reply(550, "Can't get current directory");
2092	else
2093		replydirname(path, "is current directory.");
2094}
2095
2096char *
2097renamefrom(char *name)
2098{
2099	struct stat st;
2100
2101	if (stat(name, &st) == -1) {
2102		perror_reply(550, name);
2103		return (NULL);
2104	}
2105	reply(350, "File exists, ready for destination name");
2106	return (name);
2107}
2108
2109void
2110renamecmd(char *from, char *to)
2111{
2112
2113	LOGCMD2("rename", from, to);
2114	if (rename(from, to) == -1)
2115		perror_reply(550, "rename");
2116	else
2117		ack("RNTO");
2118}
2119
2120static void
2121dolog(struct sockaddr *sa)
2122{
2123	char hbuf[sizeof(remotehost)];
2124
2125	if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0, 0) == 0)
2126		(void) strlcpy(remotehost, hbuf, sizeof(remotehost));
2127	else
2128		(void) strlcpy(remotehost, "unknown", sizeof(remotehost));
2129
2130	snprintf(proctitle, sizeof(proctitle), "%s: connected", remotehost);
2131	setproctitle("%s", proctitle);
2132
2133	if (logging) {
2134		int error;
2135		error = getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf),
2136		    NULL, 0, NI_NUMERICHOST);
2137		syslog(LOG_INFO, "connection from %s [%s]", remotehost,
2138		    error ? gai_strerror(error) : hbuf);
2139	}
2140}
2141
2142/*
2143 * Record logout in wtmp file and exit with supplied status.
2144 * NOTE: because this is called from signal handlers it cannot
2145 *       use stdio (or call other functions that use stdio).
2146 */
2147void
2148dologout(int status)
2149{
2150
2151	transflag = 0;
2152
2153	if (logged_in) {
2154		sigprocmask(SIG_BLOCK, &allsigs, NULL);
2155		if (!nowtmp)
2156			ftpdlogwtmp(ttyline, "", "");
2157		if (doutmp)
2158			ftpd_logout(utmp.ut_line);
2159	}
2160	/* beware of flushing buffers after a SIGPIPE */
2161	_exit(status);
2162}
2163
2164/*ARGSUSED*/
2165static void
2166sigurg(int signo)
2167{
2168
2169	recvurg = 1;
2170}
2171
2172static void
2173myoob(void)
2174{
2175	char *cp;
2176	int ret;
2177
2178	/* only process if transfer occurring */
2179	if (!transflag)
2180		return;
2181	cp = tmpline;
2182	ret = get_line(cp, sizeof(tmpline)-1, stdin);
2183	if (ret == -1) {
2184		reply(221, "You could at least say goodbye.");
2185		dologout(0);
2186	} else if (ret == -2) {
2187		/* Ignore truncated command */
2188		return;
2189	}
2190	upper(cp);
2191	if (strcmp(cp, "ABOR\r\n") == 0) {
2192		tmpline[0] = '\0';
2193		reply(426, "Transfer aborted. Data connection closed.");
2194		reply(226, "Abort successful");
2195	}
2196	if (strcmp(cp, "STAT\r\n") == 0) {
2197		tmpline[0] = '\0';
2198		if (file_size != -1)
2199			reply(213, "Status: %lld of %lld bytes transferred",
2200			    (long long)byte_count, (long long)file_size);
2201		else
2202			reply(213, "Status: %lld bytes transferred",
2203			    (long long)byte_count);
2204	}
2205}
2206
2207/*
2208 * Note: a response of 425 is not mentioned as a possible response to
2209 *	the PASV command in RFC959. However, it has been blessed as
2210 *	a legitimate response by Jon Postel in a telephone conversation
2211 *	with Rick Adams on 25 Jan 89.
2212 */
2213void
2214passive(void)
2215{
2216	socklen_t len;
2217	int on = 1;
2218	u_char *p, *a;
2219
2220	if (pw == NULL) {
2221		reply(530, "Please login with USER and PASS");
2222		return;
2223	}
2224	if (pdata >= 0)
2225		close(pdata);
2226	/*
2227	 * XXX
2228	 * At this point, it would be nice to have an algorithm that
2229	 * inserted a growing delay in an attack scenario.  Such a thing
2230	 * would look like continual passive sockets being opened, but
2231	 * nothing serious being done with them.  They're not used to
2232	 * move data; the entire attempt is just to use tcp FIN_WAIT
2233	 * resources.
2234	 */
2235	pdata = socket(AF_INET, SOCK_STREAM, 0);
2236	if (pdata == -1) {
2237		perror_reply(425, "Can't open passive connection");
2238		return;
2239	}
2240
2241	if (setsockopt(pdata, SOL_SOCKET, SO_KEEPALIVE,
2242	    &on, sizeof(on)) == -1)
2243		goto pasv_error;
2244
2245	on = IP_PORTRANGE_HIGH;
2246	if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2247	    &on, sizeof(on)) == -1)
2248		goto pasv_error;
2249
2250	pasv_addr = ctrl_addr;
2251	pasv_addr.su_sin.sin_port = 0;
2252	if (bind(pdata, (struct sockaddr *)&pasv_addr,
2253	    pasv_addr.su_len) == -1)
2254		goto pasv_error;
2255
2256	len = sizeof(pasv_addr);
2257	if (getsockname(pdata, (struct sockaddr *)&pasv_addr, &len) == -1)
2258		goto pasv_error;
2259	if (listen(pdata, 1) == -1)
2260		goto pasv_error;
2261	a = (u_char *)&pasv_addr.su_sin.sin_addr;
2262	p = (u_char *)&pasv_addr.su_sin.sin_port;
2263
2264	reply(227, "Entering Passive Mode (%u,%u,%u,%u,%u,%u)", a[0],
2265	    a[1], a[2], a[3], p[0], p[1]);
2266	return;
2267
2268pasv_error:
2269	perror_reply(425, "Can't open passive connection");
2270	(void) close(pdata);
2271	pdata = -1;
2272	return;
2273}
2274
2275int
2276epsvproto2af(int proto)
2277{
2278
2279	switch (proto) {
2280	case 1:	return AF_INET;
2281	case 2:	return AF_INET6;
2282	default: return -1;
2283	}
2284}
2285
2286int
2287af2epsvproto(int af)
2288{
2289
2290	switch (af) {
2291	case AF_INET:	return 1;
2292	case AF_INET6:	return 2;
2293	default:	return -1;
2294	}
2295}
2296
2297/*
2298 * 228 Entering Long Passive Mode (af, hal, h1, h2, h3,..., pal, p1, p2...)
2299 * 229 Entering Extended Passive Mode (|||port|)
2300 */
2301void
2302long_passive(char *cmd, int pf)
2303{
2304	socklen_t len;
2305	int on = 1;
2306	u_char *p, *a;
2307
2308	if (!logged_in) {
2309		syslog(LOG_NOTICE, "long passive but not logged in");
2310		reply(503, "Login with USER first.");
2311		return;
2312	}
2313
2314	if (pf != PF_UNSPEC && ctrl_addr.su_family != pf) {
2315		/*
2316		 * XXX
2317		 * only EPRT/EPSV ready clients will understand this
2318		 */
2319		if (strcmp(cmd, "EPSV") != 0)
2320			reply(501, "Network protocol mismatch"); /*XXX*/
2321		else
2322			epsv_protounsupp("Network protocol mismatch");
2323
2324		return;
2325	}
2326
2327	if (pdata >= 0)
2328		close(pdata);
2329	/*
2330	 * XXX
2331	 * At this point, it would be nice to have an algorithm that
2332	 * inserted a growing delay in an attack scenario.  Such a thing
2333	 * would look like continual passive sockets being opened, but
2334	 * nothing serious being done with them.  They not used to move
2335	 * data; the entire attempt is just to use tcp FIN_WAIT
2336	 * resources.
2337	 */
2338	pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0);
2339	if (pdata == -1) {
2340		perror_reply(425, "Can't open passive connection");
2341		return;
2342	}
2343
2344	if (setsockopt(pdata, SOL_SOCKET, SO_KEEPALIVE,
2345	    &on, sizeof(on)) == -1)
2346		goto pasv_error;
2347
2348	switch (ctrl_addr.su_family) {
2349	case AF_INET:
2350		on = IP_PORTRANGE_HIGH;
2351		if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2352		    &on, sizeof(on)) == -1)
2353			goto pasv_error;
2354		break;
2355	case AF_INET6:
2356		on = IPV6_PORTRANGE_HIGH;
2357		if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE,
2358		    &on, sizeof(on)) == -1)
2359			goto pasv_error;
2360		break;
2361	}
2362
2363	pasv_addr = ctrl_addr;
2364	pasv_addr.su_port = 0;
2365	if (bind(pdata, (struct sockaddr *)&pasv_addr, pasv_addr.su_len) == -1)
2366		goto pasv_error;
2367	len = pasv_addr.su_len;
2368	if (getsockname(pdata, (struct sockaddr *)&pasv_addr, &len) == -1)
2369		goto pasv_error;
2370	if (listen(pdata, 1) == -1)
2371		goto pasv_error;
2372	p = (u_char *)&pasv_addr.su_port;
2373
2374	if (strcmp(cmd, "LPSV") == 0) {
2375		switch (pasv_addr.su_family) {
2376		case AF_INET:
2377			a = (u_char *)&pasv_addr.su_sin.sin_addr;
2378			reply(228,
2379			    "Entering Long Passive Mode (%u,%u,%u,%u,%u,%u,%u,%u,%u)",
2380			    4, 4, a[0], a[1], a[2], a[3], 2, p[0], p[1]);
2381			return;
2382		case AF_INET6:
2383			a = (u_char *)&pasv_addr.su_sin6.sin6_addr;
2384			reply(228,
2385			    "Entering Long Passive Mode (%u,%u,%u,%u,%u,%u,"
2386			    "%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u)",
2387				6, 16, a[0], a[1], a[2], a[3], a[4],
2388				a[5], a[6], a[7], a[8], a[9], a[10],
2389				a[11], a[12], a[13], a[14], a[15],
2390				2, p[0], p[1]);
2391			return;
2392		}
2393	} else if (strcmp(cmd, "EPSV") == 0) {
2394		switch (pasv_addr.su_family) {
2395		case AF_INET:
2396		case AF_INET6:
2397			reply(229, "Entering Extended Passive Mode (|||%u|)",
2398			    ntohs(pasv_addr.su_port));
2399			return;
2400		}
2401	} else {
2402		/* more proper error code? */
2403	}
2404
2405  pasv_error:
2406	perror_reply(425, "Can't open passive connection");
2407	(void) close(pdata);
2408	pdata = -1;
2409	return;
2410}
2411
2412/*
2413 * EPRT |proto|addr|port|
2414 */
2415int
2416extended_port(const char *arg)
2417{
2418	char *tmp = NULL;
2419	char *result[3];
2420	char *p, *q;
2421	char delim;
2422	struct addrinfo hints;
2423	struct addrinfo *res = NULL;
2424	int i;
2425	unsigned long proto;
2426
2427	if (epsvall) {
2428		reply(501, "EPRT disallowed after EPSV ALL");
2429		return -1;
2430	}
2431
2432	usedefault = 0;
2433	if (pdata >= 0) {
2434		(void) close(pdata);
2435		pdata = -1;
2436	}
2437
2438	tmp = strdup(arg);
2439	if (!tmp) {
2440		fatal("not enough core.");
2441		/*NOTREACHED*/
2442	}
2443	p = tmp;
2444	delim = p[0];
2445	p++;
2446	memset(result, 0, sizeof(result));
2447	for (i = 0; i < 3; i++) {
2448		q = strchr(p, delim);
2449		if (!q || *q != delim)
2450			goto parsefail;
2451		*q++ = '\0';
2452		result[i] = p;
2453		p = q;
2454	}
2455
2456	/* some more sanity check */
2457	p = NULL;
2458	(void)strtoul(result[2], &p, 10);
2459	if (!*result[2] || *p)
2460		goto protounsupp;
2461	p = NULL;
2462	proto = strtoul(result[0], &p, 10);
2463	if (!*result[0] || *p)
2464		goto protounsupp;
2465
2466	memset(&hints, 0, sizeof(hints));
2467	hints.ai_family = epsvproto2af((int)proto);
2468	if (hints.ai_family < 0)
2469		goto protounsupp;
2470	hints.ai_socktype = SOCK_STREAM;
2471	hints.ai_flags = AI_NUMERICHOST;	/*no DNS*/
2472	if (getaddrinfo(result[1], result[2], &hints, &res))
2473		goto parsefail;
2474	if (res->ai_next)
2475		goto parsefail;
2476	if (sizeof(data_dest) < res->ai_addrlen)
2477		goto parsefail;
2478	memcpy(&data_dest, res->ai_addr, res->ai_addrlen);
2479	if (his_addr.su_family == AF_INET6 &&
2480	    data_dest.su_family == AF_INET6) {
2481		/* XXX more sanity checks! */
2482		data_dest.su_sin6.sin6_scope_id =
2483		    his_addr.su_sin6.sin6_scope_id;
2484	}
2485	if (pdata >= 0) {
2486		(void) close(pdata);
2487		pdata = -1;
2488	}
2489	reply(200, "EPRT command successful.");
2490
2491	free(tmp);
2492	if (res)
2493		freeaddrinfo(res);
2494	return 0;
2495
2496parsefail:
2497	reply(500, "Invalid argument, rejected.");
2498	usedefault = 1;
2499	free(tmp);
2500	if (res)
2501		freeaddrinfo(res);
2502	return -1;
2503
2504protounsupp:
2505	epsv_protounsupp("Protocol not supported");
2506	usedefault = 1;
2507	free(tmp);
2508	if (res)
2509		freeaddrinfo(res);
2510	return -1;
2511}
2512
2513/*
2514 * 522 Protocol not supported (proto,...)
2515 * as we assume address family for control and data connections are the same,
2516 * we do not return the list of address families we support - instead, we
2517 * return the address family of the control connection.
2518 */
2519void
2520epsv_protounsupp(const char *message)
2521{
2522	int proto;
2523
2524	proto = af2epsvproto(ctrl_addr.su_family);
2525	if (proto < 0)
2526		reply(501, "%s", message);	/*XXX*/
2527	else
2528		reply(522, "%s, use (%d)", message, proto);
2529}
2530
2531/*
2532 * Generate unique name for file with basename "local".
2533 * The file named "local" is already known to exist.
2534 * Generates failure reply on error.
2535 */
2536static int
2537guniquefd(char *local, char **nam)
2538{
2539	static char new[PATH_MAX];
2540	struct stat st;
2541	size_t len;
2542	int count, fd;
2543	char *cp;
2544
2545	cp = strrchr(local, '/');
2546	if (cp)
2547		*cp = '\0';
2548	if (stat(cp ? local : ".", &st) == -1) {
2549		perror_reply(553, cp ? local : ".");
2550		return (-1);
2551	}
2552	if (cp)
2553		*cp = '/';
2554	len = strlcpy(new, local, sizeof(new));
2555	if (len+2+1 >= sizeof(new)-1)
2556		return (-1);
2557	cp = new + len;
2558	*cp++ = '.';
2559	for (count = 1; count < 100; count++) {
2560		(void)snprintf(cp, sizeof(new) - (cp - new), "%d", count);
2561		fd = open(new, O_RDWR|O_CREAT|O_EXCL, 0666);
2562		if (fd == -1)
2563			continue;
2564		if (nam)
2565			*nam = new;
2566		return (fd);
2567	}
2568	reply(452, "Unique file name cannot be created.");
2569	return (-1);
2570}
2571
2572/*
2573 * Format and send reply containing system error number.
2574 */
2575void
2576perror_reply(int code, char *string)
2577{
2578
2579	reply(code, "%s: %s.", string, strerror(errno));
2580}
2581
2582static char *onefile[] = {
2583	"",
2584	0
2585};
2586
2587void
2588send_file_list(char *whichf)
2589{
2590	struct stat st;
2591	DIR *dirp = NULL;
2592	struct dirent *dir;
2593	FILE *dout = NULL;
2594	char **dirlist;
2595	char *dirname;
2596	int simple = 0;
2597	volatile int freeglob = 0;
2598	glob_t gl;
2599	size_t prefixlen;
2600
2601	if (strpbrk(whichf, "~{[*?") != NULL) {
2602		memset(&gl, 0, sizeof(gl));
2603		freeglob = 1;
2604		if (glob(whichf,
2605		    GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE|GLOB_LIMIT,
2606		    0, &gl)) {
2607			reply(550, "not found");
2608			goto out;
2609		} else if (gl.gl_pathc == 0) {
2610			errno = ENOENT;
2611			perror_reply(550, whichf);
2612			goto out;
2613		}
2614		dirlist = gl.gl_pathv;
2615	} else {
2616		onefile[0] = whichf;
2617		dirlist = onefile;
2618		simple = 1;
2619	}
2620
2621	while ((dirname = *dirlist++)) {
2622		if (stat(dirname, &st) == -1) {
2623			/*
2624			 * If user typed "ls -l", etc, and the client
2625			 * used NLST, do what the user meant.
2626			 */
2627			if (dirname[0] == '-' && *dirlist == NULL &&
2628			    transflag == 0) {
2629				retrieve(RET_FILE, dirname);
2630				goto out;
2631			}
2632			perror_reply(550, whichf);
2633			if (dout != NULL) {
2634				(void) fclose(dout);
2635				transflag = 0;
2636				data = -1;
2637				pdata = -1;
2638			}
2639			goto out;
2640		}
2641
2642		if (S_ISREG(st.st_mode)) {
2643			if (dout == NULL) {
2644				dout = dataconn("file list", -1, "w");
2645				if (dout == NULL)
2646					goto out;
2647				transflag++;
2648			}
2649			fprintf(dout, "%s%s\n", dirname,
2650				type == TYPE_A ? "\r" : "");
2651			byte_count += strlen(dirname) + 1;
2652			continue;
2653		} else if (!S_ISDIR(st.st_mode))
2654			continue;
2655
2656		if ((dirp = opendir(dirname)) == NULL)
2657			continue;
2658
2659		if (dirname[0] == '.' && dirname[1] == '\0')
2660			prefixlen = 0;
2661		else
2662			prefixlen = strlen(dirname) + 1;
2663		while ((dir = readdir(dirp)) != NULL) {
2664			if (recvurg) {
2665				myoob();
2666				recvurg = 0;
2667				transflag = 0;
2668				goto out;
2669			}
2670
2671			if (dir->d_name[0] == '.' && dir->d_namlen == 1)
2672				continue;
2673			if (dir->d_name[0] == '.' && dir->d_name[1] == '.' &&
2674			    dir->d_namlen == 2)
2675				continue;
2676
2677			/*
2678			 * We have to do a stat to insure it's
2679			 * not a directory or special file.
2680			 */
2681			if (simple ||
2682			    (fstatat(dirfd(dirp), dir->d_name, &st, 0) == 0 &&
2683			    S_ISREG(st.st_mode))) {
2684				if (dout == NULL) {
2685					dout = dataconn("file list", -1, "w");
2686					if (dout == NULL)
2687						goto out;
2688					transflag++;
2689				}
2690
2691				if (prefixlen) {
2692					fprintf(dout, "%s/", dirname);
2693					byte_count += prefixlen;
2694				}
2695				fprintf(dout, "%s%s\n", dir->d_name,
2696				    type == TYPE_A ? "\r" : "");
2697				byte_count += dir->d_namlen + 1;
2698			}
2699		}
2700		(void) closedir(dirp);
2701	}
2702
2703	if (dout == NULL)
2704		reply(550, "No files found.");
2705	else if (ferror(dout) != 0)
2706		perror_reply(550, "Data connection");
2707	else
2708		reply(226, "Transfer complete.");
2709
2710	transflag = 0;
2711	if (dout != NULL)
2712		(void) fclose(dout);
2713	else {
2714		if (pdata >= 0)
2715			close(pdata);
2716	}
2717	data = -1;
2718	pdata = -1;
2719out:
2720	if (freeglob) {
2721		freeglob = 0;
2722		globfree(&gl);
2723	}
2724}
2725
2726/*ARGSUSED*/
2727static void
2728reapchild(int signo)
2729{
2730	int save_errno = errno;
2731	int rval;
2732
2733	do {
2734		rval = waitpid(-1, NULL, WNOHANG);
2735	} while (rval > 0 || (rval == -1 && errno == EINTR));
2736	errno = save_errno;
2737}
2738
2739void
2740logxfer(char *name, off_t size, time_t start)
2741{
2742	char buf[400 + (HOST_NAME_MAX+1)*4 + PATH_MAX*4];
2743	char dir[PATH_MAX], path[PATH_MAX], rpath[PATH_MAX];
2744	char vremotehost[(HOST_NAME_MAX+1)*4], vpath[PATH_MAX*4];
2745	char *vpw;
2746	time_t now;
2747	int len;
2748
2749	if ((statfd >= 0) && (getcwd(dir, sizeof(dir)) != NULL)) {
2750		time(&now);
2751
2752		vpw = malloc(strlen(guest ? guestpw : pw->pw_name) * 4 + 1);
2753		if (vpw == NULL)
2754			return;
2755
2756		snprintf(path, sizeof(path), "%s/%s", dir, name);
2757		if (realpath(path, rpath) == NULL)
2758			strlcpy(rpath, path, sizeof(rpath));
2759		strvis(vpath, rpath, VIS_SAFE|VIS_NOSLASH);
2760
2761		strvis(vremotehost, remotehost, VIS_SAFE|VIS_NOSLASH);
2762		strvis(vpw, guest? guestpw : pw->pw_name, VIS_SAFE|VIS_NOSLASH);
2763
2764		len = snprintf(buf, sizeof(buf),
2765		    "%.24s %lld %s %lld %s %c %s %c %c %s ftp %d %s %s\n",
2766		    ctime(&now), (long long)(now - start + (now == start)),
2767		    vremotehost, (long long)size, vpath,
2768		    ((type == TYPE_A) ? 'a' : 'b'), "*" /* none yet */,
2769		    'o', ((guest) ? 'a' : 'r'),
2770		    vpw, 0 /* none yet */,
2771		    ((guest) ? "*" : pw->pw_name), dhostname);
2772		free(vpw);
2773
2774		if (len < 0 || len >= sizeof(buf)) {
2775			if ((len = strlen(buf)) == 0)
2776				return;		/* should not happen */
2777			buf[len - 1] = '\n';
2778		}
2779		write(statfd, buf, len);
2780	}
2781}
2782
2783void
2784set_slave_signals(void)
2785{
2786	struct sigaction sa;
2787
2788	sigemptyset(&sa.sa_mask);
2789	sa.sa_flags = SA_RESTART;
2790
2791	sa.sa_handler = SIG_DFL;
2792	(void) sigaction(SIGCHLD, &sa, NULL);
2793
2794	sa.sa_handler = sigurg;
2795	sa.sa_flags = 0;		/* don't restart syscalls for SIGURG */
2796	(void) sigaction(SIGURG, &sa, NULL);
2797
2798	sigfillset(&sa.sa_mask);	/* block all signals in handler */
2799	sa.sa_flags = SA_RESTART;
2800	sa.sa_handler = sigquit;
2801	(void) sigaction(SIGHUP, &sa, NULL);
2802	(void) sigaction(SIGINT, &sa, NULL);
2803	(void) sigaction(SIGQUIT, &sa, NULL);
2804	(void) sigaction(SIGTERM, &sa, NULL);
2805
2806	sa.sa_handler = lostconn;
2807	(void) sigaction(SIGPIPE, &sa, NULL);
2808
2809	sa.sa_handler = toolong;
2810	(void) sigaction(SIGALRM, &sa, NULL);
2811
2812	if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1)
2813		syslog(LOG_ERR, "fcntl F_SETOWN: %m");
2814}
2815
2816/*
2817 * Allocate space and return a copy of the specified dir.
2818 * If 'dir' begins with a tilde (~), expand it.
2819 */
2820char *
2821copy_dir(char *dir, struct passwd *pw)
2822{
2823	char *cp;
2824	char *newdir;
2825	char *user = NULL;
2826
2827	/* Nothing to expand */
2828	if (dir[0] != '~')
2829		return (strdup(dir));
2830
2831	/* "dir" is of form ~user/some/dir, lookup user. */
2832	if (dir[1] != '/' && dir[1] != '\0') {
2833		if ((cp = strchr(dir + 1, '/')) == NULL)
2834			cp = dir + strlen(dir);
2835		if ((user = malloc((size_t)(cp - dir))) == NULL)
2836			return (NULL);
2837		strlcpy(user, dir + 1, (size_t)(cp - dir));
2838
2839		/* Only do lookup if it is a different user. */
2840		if (strcmp(user, pw->pw_name) != 0) {
2841			if ((pw = getpwnam(user)) == NULL) {
2842				/* No such user, interpret literally */
2843				free(user);
2844				return(strdup(dir));
2845			}
2846		}
2847		free(user);
2848	}
2849
2850	/*
2851	 * If there is no directory separator (/) then it is just pw_dir.
2852	 * Otherwise, replace ~foo with pw_dir.
2853	 */
2854	if ((cp = strchr(dir + 1, '/')) == NULL) {
2855		newdir = strdup(pw->pw_dir);
2856	} else {
2857		if (asprintf(&newdir, "%s%s", pw->pw_dir, cp) == -1)
2858			return (NULL);
2859	}
2860
2861	return(newdir);
2862}
2863