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