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