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