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