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