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