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