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