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