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