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