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