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