ftpd.c revision 1.207
1/*	$OpenBSD: ftpd.c,v 1.207 2015/01/19 01:24:39 deraadt 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 <util.h>
100#include <utmp.h>
101#include <poll.h>
102
103#include "pathnames.h"
104#include "monitor.h"
105#include "extern.h"
106
107extern	off_t restart_point;
108extern	char cbuf[];
109
110union sockunion ctrl_addr;
111union sockunion data_source;
112union sockunion data_dest;
113union sockunion his_addr;
114union sockunion pasv_addr;
115
116sigset_t allsigs;
117
118int	daemon_mode = 0;
119int	data;
120int	logged_in;
121struct	passwd *pw;
122int	debug = 0;
123int	timeout = 900;    /* timeout after 15 minutes of inactivity */
124int	maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */
125int	logging;
126int	anon_ok = 1;
127int	anon_only = 0;
128unsigned int minuid = 1000;
129int	multihome = 0;
130int	guest;
131int	stats;
132int	statfd = -1;
133int	portcheck = 1;
134int	dochroot;
135int	type;
136int	form;
137int	stru;			/* avoid C keyword */
138int	mode;
139int	doutmp = 0;		/* update utmp file */
140int	nowtmp = 0;		/* do not update wtmp file */
141int	usedefault = 1;		/* for data transfers */
142int	pdata = -1;		/* for passive mode */
143int	family = AF_UNSPEC;
144volatile sig_atomic_t transflag;
145off_t	file_size;
146off_t	byte_count;
147mode_t	defumask = S_IWGRP|S_IWOTH;		/* default umask value */
148int	umaskchange = 1;		/* allow user to change umask value. */
149char	tmpline[7];
150char	hostname[HOST_NAME_MAX+1];
151char	remotehost[HOST_NAME_MAX+1];
152char	dhostname[HOST_NAME_MAX+1];
153char	*guestpw;
154char	ttyline[20];
155#if 0
156char	*tty = ttyline;		/* for klogin */
157#endif
158static struct utmp utmp;	/* for utmp */
159static	login_cap_t *lc;
160static	auth_session_t *as;
161static	volatile sig_atomic_t recvurg;
162
163int epsvall = 0;
164
165/*
166 * Timeout intervals for retrying connections
167 * to hosts that don't accept PORT cmds.  This
168 * is a kludge, but given the problems with TCP...
169 */
170#define	SWAITMAX	90	/* wait at most 90 seconds */
171#define	SWAITINT	5	/* interval between retries */
172
173int	swaitmax = SWAITMAX;
174int	swaitint = SWAITINT;
175
176#ifdef HASSETPROCTITLE
177char	proctitle[BUFSIZ];	/* initial part of title */
178#endif /* HASSETPROCTITLE */
179
180#define LOGCMD(cmd, file) \
181	if (logging > 1) \
182	    syslog(LOG_INFO,"%s %s%s", cmd, \
183		*(file) == '/' ? "" : curdir(), file);
184#define LOGCMD2(cmd, file1, file2) \
185	 if (logging > 1) \
186	    syslog(LOG_INFO,"%s %s%s %s%s", cmd, \
187		*(file1) == '/' ? "" : curdir(), file1, \
188		*(file2) == '/' ? "" : curdir(), file2);
189#define LOGBYTES(cmd, file, cnt) \
190	if (logging > 1) { \
191		if (cnt == (off_t)-1) \
192		    syslog(LOG_INFO,"%s %s%s", cmd, \
193			*(file) == '/' ? "" : curdir(), file); \
194		else \
195		    syslog(LOG_INFO, "%s %s%s = %qd bytes", \
196			cmd, (*(file) == '/') ? "" : curdir(), file, cnt); \
197	}
198
199static void	 ack(char *);
200static void	 sigurg(int);
201static void	 myoob(void);
202static int	 checkuser(char *, char *);
203static FILE	*dataconn(char *, off_t, char *);
204static void	 dolog(struct sockaddr *);
205static char	*copy_dir(char *, struct passwd *);
206static char	*curdir(void);
207static void	 end_login(void);
208static FILE	*getdatasock(char *);
209static int	 guniquefd(char *, char **);
210static void	 lostconn(int);
211static void	 sigquit(int);
212static int	 receive_data(FILE *, FILE *);
213static void	 replydirname(const char *, const char *);
214static int	 send_data(FILE *, FILE *, off_t, off_t, int);
215static struct passwd *
216		 sgetpwnam(char *, struct passwd *);
217static void	 reapchild(int);
218static void	 usage(void);
219
220void	 logxfer(char *, off_t, time_t);
221void	 set_slave_signals(void);
222
223static char *
224curdir(void)
225{
226	static char path[PATH_MAX+1];	/* path + '/' */
227
228	if (getcwd(path, sizeof(path)-1) == NULL)
229		return ("");
230	if (path[1] != '\0')		/* special case for root dir. */
231		strlcat(path, "/", sizeof path);
232	/* For guest account, skip / since it's chrooted */
233	return (guest ? path+1 : path);
234}
235
236char *argstr = "AdDhnlm:MSt:T:u:PUvW46";
237
238static void
239usage(void)
240{
241	syslog(LOG_ERR,
242	    "usage: ftpd [-46ADdlMnPSUW] [-m minuid] [-T maxtimeout] "
243	    "[-t timeout] [-u mask]");
244	exit(2);
245}
246
247int
248main(int argc, char *argv[])
249{
250	socklen_t addrlen;
251	int ch, on = 1, tos;
252	char line[LINE_MAX];
253	FILE *fp;
254	struct hostent *hp;
255	struct sigaction sa;
256	int error = 0;
257	const char *errstr;
258
259	tzset();		/* in case no timezone database in ~ftp */
260	sigfillset(&allsigs);	/* used to block signals while root */
261	sigemptyset(&sa.sa_mask);
262	sa.sa_flags = SA_RESTART;
263
264	while ((ch = getopt(argc, argv, argstr)) != -1) {
265		switch (ch) {
266		case 'A':
267			anon_only = 1;
268			break;
269
270		case 'd':
271		case 'v':		/* deprecated */
272			debug = 1;
273			break;
274
275		case 'D':
276			daemon_mode = 1;
277			break;
278
279		case 'P':
280			portcheck = 0;
281			break;
282
283		case 'h':		/* deprecated */
284			break;
285
286		case 'l':
287			logging++;	/* > 1 == extra logging */
288			break;
289
290		case 'm':
291			minuid = strtonum(optarg, 0, UINT_MAX, &errstr);
292			if (errstr) {
293				syslog(LOG_ERR,
294				    "%s is a bad value for -m, aborting",
295				    optarg);
296				exit(2);
297			}
298			break;
299
300		case 'M':
301			multihome = 1;
302			break;
303
304		case 'n':
305			anon_ok = 0;
306			break;
307
308		case 'S':
309			stats = 1;
310			break;
311
312		case 't':
313			timeout = strtonum(optarg, 0, INT_MAX, &errstr);
314			if (errstr) {
315				syslog(LOG_ERR,
316				    "%s is a bad value for -t, aborting",
317				    optarg);
318				exit(2);
319			}
320			if (maxtimeout < timeout)
321				maxtimeout = timeout;
322			break;
323
324		case 'T':
325			maxtimeout = strtonum(optarg, 0, INT_MAX,
326			    &errstr);
327			if (errstr) {
328				syslog(LOG_ERR,
329				    "%s is a bad value for -T, aborting",
330				    optarg);
331				exit(2);
332			}
333			if (timeout > maxtimeout)
334				timeout = maxtimeout;
335			break;
336
337		case 'u':
338		    {
339			long val = 0;
340			char *p;
341			umaskchange = 0;
342
343			val = strtol(optarg, &p, 8);
344			if (*optarg == '\0' || *p != '\0' || val < 0 ||
345			    (val & ~ACCESSPERMS)) {
346				syslog(LOG_ERR,
347				    "%s is a bad value for -u, aborting",
348				    optarg);
349				exit(2);
350			}
351			defumask = val;
352			break;
353		    }
354
355		case 'U':
356			doutmp = 1;
357			break;
358
359		case 'W':
360			nowtmp = 1;
361			break;
362
363		case '4':
364			family = AF_INET;
365			break;
366
367		case '6':
368			family = AF_INET6;
369			break;
370
371		default:
372			usage();
373			break;
374		}
375	}
376
377	if (nowtmp && doutmp) {
378		syslog(LOG_ERR, "options 'U' and 'W' are mutually exclusive");
379		exit(1);
380	}
381
382	(void) freopen(_PATH_DEVNULL, "w", stderr);
383
384	/*
385	 * LOG_NDELAY sets up the logging connection immediately,
386	 * necessary for anonymous ftp's that chroot and can't do it later.
387	 */
388	openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
389
390	if (getpwnam(FTPD_PRIVSEP_USER) == NULL) {
391		syslog(LOG_ERR, "privilege separation user %s not found",
392		    FTPD_PRIVSEP_USER);
393		exit(1);
394	}
395	endpwent();
396
397	if (daemon_mode) {
398		int *fds, i, fd;
399		struct pollfd *pfds;
400		struct addrinfo hints, *res, *res0;
401		nfds_t n;
402
403		/*
404		 * Detach from parent.
405		 */
406		if (daemon(1, 1) < 0) {
407			syslog(LOG_ERR, "failed to become a daemon");
408			exit(1);
409		}
410		sa.sa_handler = reapchild;
411		(void) sigaction(SIGCHLD, &sa, NULL);
412
413		memset(&hints, 0, sizeof(hints));
414		hints.ai_family = family;
415		hints.ai_socktype = SOCK_STREAM;
416		hints.ai_protocol = IPPROTO_TCP;
417		hints.ai_flags = AI_PASSIVE;
418		error = getaddrinfo(NULL, "ftp", &hints, &res0);
419		if (error) {
420			syslog(LOG_ERR, "%s", gai_strerror(error));
421			exit(1);
422		}
423
424		n = 0;
425		for (res = res0; res; res = res->ai_next)
426			n++;
427
428		fds = calloc(n, sizeof(int));
429		pfds = calloc(n, sizeof(struct pollfd));
430		if (!fds || !pfds) {
431			syslog(LOG_ERR, "%s", strerror(errno));
432			exit(1);
433		}
434
435		/*
436		 * Open sockets, bind it to the FTP port, and start
437		 * listening.
438		 */
439		n = 0;
440		for (res = res0; res; res = res->ai_next) {
441			fds[n] = socket(res->ai_family, res->ai_socktype,
442			    res->ai_protocol);
443			if (fds[n] < 0)
444				continue;
445
446			if (setsockopt(fds[n], SOL_SOCKET, SO_KEEPALIVE,
447			    &on, sizeof(on)) < 0) {
448				close(fds[n]);
449				fds[n] = -1;
450				continue;
451			}
452
453			if (setsockopt(fds[n], SOL_SOCKET, SO_REUSEADDR,
454			    &on, sizeof(on)) < 0) {
455				close(fds[n]);
456				fds[n] = -1;
457				continue;
458			}
459
460			if (bind(fds[n], res->ai_addr, res->ai_addrlen) < 0) {
461				close(fds[n]);
462				fds[n] = -1;
463				continue;
464			}
465			if (listen(fds[n], 32) < 0) {
466				close(fds[n]);
467				fds[n] = -1;
468				continue;
469			}
470
471			pfds[n].fd = fds[n];
472			pfds[n].events = POLLIN;
473			n++;
474		}
475		freeaddrinfo(res0);
476
477		if (n == 0) {
478			syslog(LOG_ERR, "could not open control socket");
479			exit(1);
480		}
481
482		/* Stash pid in pidfile */
483		if (pidfile(NULL))
484			syslog(LOG_ERR, "can't open pidfile: %m");
485		/*
486		 * Loop forever accepting connection requests and forking off
487		 * children to handle them.
488		 */
489		while (1) {
490			if (poll(pfds, n, INFTIM) < 0) {
491				if (errno == EINTR)
492					continue;
493				syslog(LOG_ERR, "poll: %m");
494				exit(1);
495			}
496			for (i = 0; i < n; i++)
497				if (pfds[i].revents & POLLIN) {
498					addrlen = sizeof(his_addr);
499					fd = accept(pfds[i].fd,
500					    (struct sockaddr *)&his_addr,
501					    &addrlen);
502					if (fd != -1) {
503						if (fork() == 0)
504							goto child;
505						close(fd);
506					}
507				}
508		}
509
510	child:
511		/* child */
512		(void)dup2(fd, STDIN_FILENO);
513		(void)dup2(fd, STDOUT_FILENO);
514		for (i = 0; i < n; i++)
515			close(fds[i]);
516	} else {
517		addrlen = sizeof(his_addr);
518		if (getpeername(0, (struct sockaddr *)&his_addr,
519		    &addrlen) < 0) {
520			/* syslog(LOG_ERR, "getpeername (%s): %m", argv[0]); */
521			exit(1);
522		}
523	}
524
525	/* set this here so klogin can use it... */
526	(void)snprintf(ttyline, sizeof(ttyline), "ftp%ld", (long)getpid());
527
528	set_slave_signals();
529
530	addrlen = sizeof(ctrl_addr);
531	if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) {
532		syslog(LOG_ERR, "getsockname: %m");
533		exit(1);
534	}
535	if (his_addr.su_family == AF_INET6 &&
536	    IN6_IS_ADDR_V4MAPPED(&his_addr.su_sin6.sin6_addr)) {
537#if 1
538		/*
539		 * IPv4 control connection arrived to AF_INET6 socket.
540		 * I hate to do this, but this is the easiest solution.
541		 */
542		union sockunion tmp_addr;
543		const int off = sizeof(struct in6_addr) - sizeof(struct in_addr);
544
545		tmp_addr = his_addr;
546		memset(&his_addr, 0, sizeof(his_addr));
547		his_addr.su_sin.sin_family = AF_INET;
548		his_addr.su_sin.sin_len = sizeof(his_addr.su_sin);
549		memcpy(&his_addr.su_sin.sin_addr,
550		    &tmp_addr.su_sin6.sin6_addr.s6_addr[off],
551		    sizeof(his_addr.su_sin.sin_addr));
552		his_addr.su_sin.sin_port = tmp_addr.su_sin6.sin6_port;
553
554		tmp_addr = ctrl_addr;
555		memset(&ctrl_addr, 0, sizeof(ctrl_addr));
556		ctrl_addr.su_sin.sin_family = AF_INET;
557		ctrl_addr.su_sin.sin_len = sizeof(ctrl_addr.su_sin);
558		memcpy(&ctrl_addr.su_sin.sin_addr,
559		    &tmp_addr.su_sin6.sin6_addr.s6_addr[off],
560		    sizeof(ctrl_addr.su_sin.sin_addr));
561		ctrl_addr.su_sin.sin_port = tmp_addr.su_sin6.sin6_port;
562#else
563		while (fgets(line, sizeof(line), fd) != NULL) {
564			line[strcspn(line, "\n")] = '\0';
565			lreply(530, "%s", line);
566		}
567		(void) fflush(stdout);
568		(void) close(fd);
569		reply(530,
570			"Connection from IPv4 mapped address is not supported.");
571		exit(0);
572#endif
573	}
574#ifdef IP_TOS
575	if (his_addr.su_family == AF_INET) {
576		tos = IPTOS_LOWDELAY;
577		if (setsockopt(0, IPPROTO_IP, IP_TOS, &tos,
578		    sizeof(int)) < 0)
579			syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
580	}
581#endif
582	data_source.su_port = htons(ntohs(ctrl_addr.su_port) - 1);
583
584	/* Try to handle urgent data inline */
585#ifdef SO_OOBINLINE
586	if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)) < 0)
587		syslog(LOG_ERR, "setsockopt: %m");
588#endif
589
590	dolog((struct sockaddr *)&his_addr);
591
592	/*
593	 * Set up default state
594	 */
595	data = -1;
596	type = TYPE_A;
597	form = FORM_N;
598	stru = STRU_F;
599	mode = MODE_S;
600	tmpline[0] = '\0';
601
602	/* If logins are disabled, print out the message. */
603	if ((fp = fopen(_PATH_NOLOGIN, "r")) != NULL) {
604		while (fgets(line, sizeof(line), fp) != NULL) {
605			line[strcspn(line, "\n")] = '\0';
606			lreply(530, "%s", line);
607		}
608		(void) fflush(stdout);
609		(void) fclose(fp);
610		reply(530, "System not available.");
611		exit(0);
612	}
613	if ((fp = fopen(_PATH_FTPWELCOME, "r")) != NULL) {
614		while (fgets(line, sizeof(line), fp) != NULL) {
615			line[strcspn(line, "\n")] = '\0';
616			lreply(220, "%s", line);
617		}
618		(void) fflush(stdout);
619		(void) fclose(fp);
620		/* reply(220,) must follow */
621	}
622	(void) gethostname(hostname, sizeof(hostname));
623
624	/* Make sure hostname is fully qualified. */
625	hp = gethostbyname(hostname);
626	if (hp != NULL)
627		strlcpy(hostname, hp->h_name, sizeof(hostname));
628
629	if (multihome) {
630		error = getnameinfo((struct sockaddr *)&ctrl_addr,
631		    ctrl_addr.su_len, dhostname, sizeof(dhostname), NULL, 0, 0);
632	}
633
634	if (error != 0)
635		reply(220, "FTP server ready.");
636	else
637		reply(220, "%s FTP server ready.",
638		    (multihome ? dhostname : hostname));
639
640	monitor_init();
641
642	for (;;)
643		(void) yyparse();
644	/* NOTREACHED */
645}
646
647/*
648 * Signal handlers.
649 */
650/*ARGSUSED*/
651static void
652lostconn(int signo)
653{
654	struct syslog_data sdata = SYSLOG_DATA_INIT;
655
656	sdata.log_fac = LOG_FTP;
657	if (debug)
658		syslog_r(LOG_DEBUG, &sdata, "lost connection");
659	dologout(1);
660}
661
662static void
663sigquit(int signo)
664{
665	struct syslog_data sdata = SYSLOG_DATA_INIT;
666
667	sdata.log_fac = LOG_FTP;
668	syslog_r(LOG_DEBUG, &sdata, "got signal %s", sys_signame[signo]);
669	dologout(1);
670}
671
672/*
673 * Save the result of a getpwnam.  Used for USER command, since
674 * the data returned must not be clobbered by any other command
675 * (e.g., globbing).
676 */
677static struct passwd *
678sgetpwnam(char *name, struct passwd *pw)
679{
680	static struct passwd *save;
681	struct passwd *old;
682
683	if (pw == NULL && (pw = getpwnam(name)) == NULL)
684		return (NULL);
685	old = save;
686	save = pw_dup(pw);
687	if (save == NULL) {
688		perror_reply(421, "Local resource failure: malloc");
689		dologout(1);
690		/* NOTREACHED */
691	}
692	if (old) {
693		explicit_bzero(old->pw_passwd, strlen(old->pw_passwd));
694		free(old);
695	}
696	return (save);
697}
698
699static int login_attempts;	/* number of failed login attempts */
700static int askpasswd;		/* had user command, ask for passwd */
701static char curname[LOGIN_NAME_MAX];	/* current USER name */
702
703/*
704 * USER command.
705 * Sets global passwd pointer pw if named account exists and is acceptable;
706 * sets askpasswd if a PASS command is expected.  If logged in previously,
707 * need to reset state.  If name is "ftp" or "anonymous", the name is not in
708 * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return.
709 * If account doesn't exist, ask for passwd anyway.  Otherwise, check user
710 * requesting login privileges.  Disallow anyone who does not have a standard
711 * shell as returned by getusershell().  Disallow anyone mentioned in the file
712 * _PATH_FTPUSERS to allow people such as root and uucp to be avoided.
713 */
714void
715user(char *name)
716{
717	char *cp, *shell, *style, *host;
718	char *class = NULL;
719
720	if (logged_in) {
721		kill_slave("user already logged in");
722		end_login();
723	}
724
725	/* Close session from previous user if there was one. */
726	if (as) {
727		auth_close(as);
728		as = NULL;
729	}
730	if (lc) {
731		login_close(lc);
732		lc = NULL;
733	}
734
735	if ((style = strchr(name, ':')) != NULL)
736		*style++ = 0;
737
738	guest = 0;
739	askpasswd = 0;
740	host = multihome ? dhostname : hostname;
741	if (anon_ok &&
742	    (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0)) {
743		if (checkuser(_PATH_FTPUSERS, "ftp") ||
744		    checkuser(_PATH_FTPUSERS, "anonymous"))
745			reply(530, "User %s access denied.", name);
746		else if ((pw = sgetpwnam("ftp", NULL)) != NULL) {
747			if ((lc = login_getclass(pw->pw_class)) == NULL ||
748			    (as = auth_open()) == NULL ||
749			    auth_setpwd(as, pw) != 0 ||
750			    auth_setoption(as, "FTPD_HOST", host) < 0) {
751				if (as) {
752					auth_close(as);
753					as = NULL;
754				}
755				if (lc) {
756					login_close(lc);
757					lc = NULL;
758				}
759				reply(421, "Local resource failure");
760				return;
761			}
762			guest = 1;
763			askpasswd = 1;
764			reply(331,
765			"Guest login ok, send your email address as password.");
766		} else
767			reply(530, "User %s unknown.", name);
768		if (!askpasswd && logging)
769			syslog(LOG_NOTICE,
770			    "ANONYMOUS FTP LOGIN REFUSED FROM %s", remotehost);
771		return;
772	}
773
774	shell = _PATH_BSHELL;
775	if ((pw = sgetpwnam(name, NULL))) {
776		class = pw->pw_class;
777		if (pw->pw_shell != NULL && *pw->pw_shell != '\0')
778			shell = pw->pw_shell;
779		while ((cp = getusershell()) != NULL)
780			if (strcmp(cp, shell) == 0)
781				break;
782		shell = cp;
783		endusershell();
784	}
785
786	/* Get login class; if invalid style treat like unknown user. */
787	lc = login_getclass(class);
788	if (lc && (style = login_getstyle(lc, style, "auth-ftp")) == NULL) {
789		login_close(lc);
790		lc = NULL;
791		pw = NULL;
792	}
793
794	/* Do pre-authentication setup. */
795	if (lc && ((as = auth_open()) == NULL ||
796	    (pw != NULL && auth_setpwd(as, pw) != 0) ||
797	    auth_setitem(as, AUTHV_STYLE, style) < 0 ||
798	    auth_setitem(as, AUTHV_NAME, name) < 0 ||
799	    auth_setitem(as, AUTHV_CLASS, class) < 0 ||
800	    auth_setoption(as, "login", "yes") < 0 ||
801	    auth_setoption(as, "notickets", "yes") < 0 ||
802	    auth_setoption(as, "FTPD_HOST", host) < 0)) {
803		if (as) {
804			auth_close(as);
805			as = NULL;
806		}
807		login_close(lc);
808		lc = NULL;
809		reply(421, "Local resource failure");
810		return;
811	}
812	if (logging)
813		strlcpy(curname, name, sizeof(curname));
814
815	dochroot = (lc && login_getcapbool(lc, "ftp-chroot", 0)) ||
816	    checkuser(_PATH_FTPCHROOT, name);
817	if (anon_only && !dochroot) {
818		reply(530, "User %s access denied.", name);
819		return;
820	}
821	if (pw) {
822		if (pw->pw_uid < minuid) {
823			reply(530, "User %s access denied.", name);
824			if (logging)
825				syslog(LOG_NOTICE,
826				    "FTP LOGIN REFUSED FROM %s, %s (UID))",
827				    remotehost, name);
828			return;
829		}
830		if ((!shell && !dochroot) || checkuser(_PATH_FTPUSERS, name)) {
831			reply(530, "User %s access denied.", name);
832			if (logging)
833				syslog(LOG_NOTICE,
834				    "FTP LOGIN REFUSED FROM %s, %s",
835				    remotehost, name);
836			pw = NULL;
837			return;
838		}
839	}
840
841	if (as != NULL && (cp = auth_challenge(as)) != NULL)
842		reply(331, "%s", cp);
843	else
844		reply(331, "Password required for %s.", name);
845
846	askpasswd = 1;
847	/*
848	 * Delay before reading passwd after first failed
849	 * attempt to slow down passwd-guessing programs.
850	 */
851	if (login_attempts)
852		sleep((unsigned) login_attempts);
853}
854
855/*
856 * Check if a user is in the file "fname"
857 */
858static int
859checkuser(char *fname, char *name)
860{
861	FILE *fp;
862	int found = 0;
863	char *p, line[BUFSIZ];
864
865	if ((fp = fopen(fname, "r")) != NULL) {
866		while (fgets(line, sizeof(line), fp) != NULL)
867			if ((p = strchr(line, '\n')) != NULL) {
868				*p = '\0';
869				if (line[0] == '#')
870					continue;
871				if (strcmp(line, name) == 0) {
872					found = 1;
873					break;
874				}
875			}
876		(void) fclose(fp);
877	}
878	return (found);
879}
880
881/*
882 * Terminate login as previous user, if any, resetting state;
883 * used when USER command is given or login fails.
884 */
885static void
886end_login(void)
887{
888	sigprocmask (SIG_BLOCK, &allsigs, NULL);
889	if (logged_in) {
890		if (!nowtmp)
891			ftpdlogwtmp(ttyline, "", "");
892		if (doutmp)
893			ftpd_logout(utmp.ut_line);
894	}
895	reply(530, "Please reconnect to work as another user");
896	_exit(0);
897}
898
899enum auth_ret
900pass(char *passwd)
901{
902	int authok;
903	unsigned int flags;
904	FILE *fp;
905	static char homedir[PATH_MAX];
906	char *motd, *dir, rootdir[PATH_MAX];
907	size_t sz_pw_dir;
908
909	if (logged_in || askpasswd == 0) {
910		reply(503, "Login with USER first.");
911		return (AUTH_FAILED);
912	}
913	askpasswd = 0;
914	if (!guest) {		/* "ftp" is only account allowed no password */
915		authok = 0;
916		if (pw == NULL || pw->pw_passwd[0] == '\0') {
917			useconds_t us;
918
919			/* Sleep between 1 and 3 seconds to emulate a crypt. */
920			us = arc4random_uniform(3000000);
921			usleep(us);
922			if (as != NULL) {
923				auth_close(as);
924				as = NULL;
925			}
926		} else {
927			authok = auth_userresponse(as, passwd, 0);
928			as = NULL;
929		}
930		if (authok == 0) {
931			reply(530, "Login incorrect.");
932			if (logging)
933				syslog(LOG_NOTICE,
934				    "FTP LOGIN FAILED FROM %s, %s",
935				    remotehost, curname);
936			pw = NULL;
937			if (login_attempts++ >= 5) {
938				syslog(LOG_NOTICE,
939				    "repeated login failures from %s",
940				    remotehost);
941				kill_slave("repeated login failures");
942				_exit(0);
943			}
944			return (AUTH_FAILED);
945		}
946	} else if (lc != NULL) {
947		/* Save anonymous' password. */
948		if (guestpw != NULL)
949			free(guestpw);
950		guestpw = strdup(passwd);
951		if (guestpw == NULL) {
952			kill_slave("out of mem");
953			fatal("Out of memory.");
954		}
955
956		authok = auth_approval(as, lc, pw->pw_name, "ftp");
957		auth_close(as);
958		as = NULL;
959		if (authok == 0) {
960			syslog(LOG_INFO|LOG_AUTH,
961			    "FTP LOGIN FAILED (HOST) as %s: approval failure.",
962			    pw->pw_name);
963			reply(530, "Approval failure.");
964			kill_slave("approval failure");
965			_exit(0);
966		}
967	} else {
968		syslog(LOG_INFO|LOG_AUTH,
969		    "FTP LOGIN CLASS %s MISSING for %s: approval failure.",
970		    pw->pw_class, pw->pw_name);
971		reply(530, "Permission denied.");
972		kill_slave("permission denied");
973		_exit(0);
974	}
975
976	if (monitor_post_auth() == 1) {
977		/* Post-auth monitor process */
978		logged_in = 1;
979		return (AUTH_MONITOR);
980	}
981
982	login_attempts = 0;		/* this time successful */
983	/* set umask via setusercontext() unless -u flag was given. */
984	flags = LOGIN_SETGROUP|LOGIN_SETPRIORITY|LOGIN_SETRESOURCES;
985	if (umaskchange)
986		flags |= LOGIN_SETUMASK;
987	else
988		(void) umask(defumask);
989	if (setusercontext(lc, pw, (uid_t)0, flags) != 0) {
990		perror_reply(421, "Local resource failure: setusercontext");
991		syslog(LOG_NOTICE, "setusercontext: %m");
992		dologout(1);
993		/* NOTREACHED */
994	}
995
996	/* open wtmp before chroot */
997	if (!nowtmp)
998		ftpdlogwtmp(ttyline, pw->pw_name, remotehost);
999
1000	/* open utmp before chroot */
1001	if (doutmp) {
1002		memset((void *)&utmp, 0, sizeof(utmp));
1003		(void)time(&utmp.ut_time);
1004		(void)strncpy(utmp.ut_name, pw->pw_name, sizeof(utmp.ut_name));
1005		(void)strncpy(utmp.ut_host, remotehost, sizeof(utmp.ut_host));
1006		(void)strncpy(utmp.ut_line, ttyline, sizeof(utmp.ut_line));
1007		ftpd_login(&utmp);
1008	}
1009
1010	/* open stats file before chroot */
1011	if (guest && (stats == 1) && (statfd < 0))
1012		if ((statfd = open(_PATH_FTPDSTATFILE, O_WRONLY|O_APPEND)) < 0)
1013			stats = 0;
1014
1015	logged_in = 1;
1016
1017	if ((dir = login_getcapstr(lc, "ftp-dir", NULL, NULL))) {
1018		char *newdir;
1019
1020		newdir = copy_dir(dir, pw);
1021		if (newdir == NULL) {
1022			perror_reply(421, "Local resource failure: malloc");
1023			dologout(1);
1024			/* NOTREACHED */
1025		}
1026		pw->pw_dir = newdir;
1027		pw = sgetpwnam(NULL, pw);
1028		free(dir);
1029		free(newdir);
1030	}
1031
1032	/* make sure pw->pw_dir is big enough to hold "/" */
1033	sz_pw_dir = strlen(pw->pw_dir) + 1;
1034	if (sz_pw_dir < 2) {
1035		pw->pw_dir = "/";
1036		pw = sgetpwnam(NULL, pw);
1037		sz_pw_dir = 2;
1038	}
1039
1040	if (guest || dochroot) {
1041		if (multihome && guest) {
1042			struct stat ts;
1043
1044			/* Compute root directory. */
1045			snprintf(rootdir, sizeof(rootdir), "%s/%s",
1046			    pw->pw_dir, dhostname);
1047			if (stat(rootdir, &ts) < 0) {
1048				snprintf(rootdir, sizeof(rootdir), "%s/%s",
1049				    pw->pw_dir, hostname);
1050			}
1051		} else
1052			strlcpy(rootdir, pw->pw_dir, sizeof(rootdir));
1053	}
1054	if (guest) {
1055		/*
1056		 * We MUST do a chdir() after the chroot. Otherwise
1057		 * the old current directory will be accessible as "."
1058		 * outside the new root!
1059		 */
1060		if (chroot(rootdir) < 0 || chdir("/") < 0) {
1061			reply(550, "Can't set guest privileges.");
1062			goto bad;
1063		}
1064		strlcpy(pw->pw_dir, "/", sz_pw_dir);
1065		if (setenv("HOME", "/", 1) == -1) {
1066			reply(550, "Can't setup environment.");
1067			goto bad;
1068		}
1069	} else if (dochroot) {
1070		if (chroot(rootdir) < 0 || chdir("/") < 0) {
1071			reply(550, "Can't change root.");
1072			goto bad;
1073		}
1074		strlcpy(pw->pw_dir, "/", sz_pw_dir);
1075		if (setenv("HOME", "/", 1) == -1) {
1076			reply(550, "Can't setup environment.");
1077			goto bad;
1078		}
1079	} else if (chdir(pw->pw_dir) < 0) {
1080		if (chdir("/") < 0) {
1081			reply(530, "User %s: can't change directory to %s.",
1082			    pw->pw_name, pw->pw_dir);
1083			goto bad;
1084		} else
1085			lreply(230, "No directory! Logging in with home=/");
1086	}
1087	if (setegid(pw->pw_gid) < 0 || setgid(pw->pw_gid) < 0) {
1088		reply(550, "Can't set gid.");
1089		goto bad;
1090	}
1091	if (seteuid(pw->pw_uid) < 0 || setuid(pw->pw_uid) < 0) {
1092		reply(550, "Can't set uid.");
1093		goto bad;
1094	}
1095	sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
1096
1097	/*
1098	 * Set home directory so that use of ~ (tilde) works correctly.
1099	 */
1100	if (getcwd(homedir, PATH_MAX) != NULL) {
1101		if (setenv("HOME", homedir, 1) == -1) {
1102			reply(550, "Can't setup environment.");
1103			goto bad;
1104		}
1105	}
1106
1107	/*
1108	 * Display a login message, if it exists.
1109	 * N.B. reply(230,) must follow the message.
1110	 */
1111	motd = login_getcapstr(lc, "welcome", NULL, NULL);
1112	if ((fp = fopen(motd ? motd : _PATH_FTPLOGINMESG, "r")) != NULL) {
1113		char line[LINE_MAX];
1114
1115		while (fgets(line, sizeof(line), fp) != NULL) {
1116			line[strcspn(line, "\n")] = '\0';
1117			lreply(230, "%s", line);
1118		}
1119		(void) fflush(stdout);
1120		(void) fclose(fp);
1121	}
1122	if (motd != NULL)
1123		free(motd);
1124	if (guest) {
1125		reply(230, "Guest login ok, access restrictions apply.");
1126#ifdef HASSETPROCTITLE
1127		snprintf(proctitle, sizeof(proctitle),
1128		    "%s: anonymous/%.*s", remotehost,
1129		    (int)(sizeof(proctitle) - sizeof(remotehost) -
1130		    sizeof(": anonymous/")), passwd);
1131		setproctitle("%s", proctitle);
1132#endif /* HASSETPROCTITLE */
1133		if (logging)
1134			syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s",
1135			    remotehost, passwd);
1136	} else {
1137		reply(230, "User %s logged in.", pw->pw_name);
1138#ifdef HASSETPROCTITLE
1139		snprintf(proctitle, sizeof(proctitle),
1140		    "%s: %s", remotehost, pw->pw_name);
1141		setproctitle("%s", proctitle);
1142#endif /* HASSETPROCTITLE */
1143		if (logging)
1144			syslog(LOG_INFO, "FTP LOGIN FROM %s as %s",
1145			    remotehost, pw->pw_name);
1146	}
1147	login_close(lc);
1148	lc = NULL;
1149	return (AUTH_SLAVE);
1150bad:
1151	/* Forget all about it... */
1152	login_close(lc);
1153	lc = NULL;
1154	end_login();
1155	return (AUTH_FAILED);
1156}
1157
1158void
1159retrieve(char *cmd, char *name)
1160{
1161	FILE *fin, *dout;
1162	struct stat st;
1163	int (*closefunc)(FILE *);
1164	time_t start;
1165
1166	if (cmd == 0) {
1167		fin = fopen(name, "r"), closefunc = fclose;
1168		st.st_size = 0;
1169	} else {
1170		char line[BUFSIZ];
1171
1172		(void) snprintf(line, sizeof(line), cmd, name);
1173		name = line;
1174		fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose;
1175		st.st_size = -1;
1176		st.st_blksize = BUFSIZ;
1177	}
1178	if (fin == NULL) {
1179		if (errno != 0) {
1180			perror_reply(550, name);
1181			if (cmd == 0) {
1182				LOGCMD("get", name);
1183			}
1184		}
1185		return;
1186	}
1187	byte_count = -1;
1188	if (cmd == 0 && (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode))) {
1189		reply(550, "%s: not a plain file.", name);
1190		goto done;
1191	}
1192	if (restart_point) {
1193		if (type == TYPE_A) {
1194			off_t i, n;
1195			int c;
1196
1197			n = restart_point;
1198			i = 0;
1199			while (i++ < n) {
1200				if ((c = getc(fin)) == EOF) {
1201					if (ferror(fin)) {
1202						perror_reply(550, name);
1203						goto done;
1204					} else
1205						break;
1206				}
1207				if (c == '\n')
1208					i++;
1209			}
1210		} else if (lseek(fileno(fin), restart_point, SEEK_SET) < 0) {
1211			perror_reply(550, name);
1212			goto done;
1213		}
1214	}
1215	dout = dataconn(name, st.st_size, "w");
1216	if (dout == NULL)
1217		goto done;
1218	time(&start);
1219	send_data(fin, dout, (off_t)st.st_blksize, st.st_size,
1220	    (restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode)));
1221	if ((cmd == 0) && stats)
1222		logxfer(name, byte_count, start);
1223	(void) fclose(dout);
1224	data = -1;
1225done:
1226	if (pdata >= 0)
1227		(void) close(pdata);
1228	pdata = -1;
1229	if (cmd == 0)
1230		LOGBYTES("get", name, byte_count);
1231	(*closefunc)(fin);
1232}
1233
1234void
1235store(char *name, char *mode, int unique)
1236{
1237	FILE *fout, *din;
1238	int (*closefunc)(FILE *);
1239	struct stat st;
1240	int fd;
1241
1242	if (restart_point && *mode != 'a')
1243		mode = "r+";
1244
1245	if (unique && stat(name, &st) == 0) {
1246		char *nam;
1247
1248		fd = guniquefd(name, &nam);
1249		if (fd == -1) {
1250			LOGCMD(*mode == 'w' ? "put" : "append", name);
1251			return;
1252		}
1253		name = nam;
1254		fout = fdopen(fd, mode);
1255	} else
1256		fout = fopen(name, mode);
1257
1258	closefunc = fclose;
1259	if (fout == NULL) {
1260		perror_reply(553, name);
1261		LOGCMD(*mode == 'w' ? "put" : "append", name);
1262		return;
1263	}
1264	byte_count = -1;
1265	if (restart_point) {
1266		if (type == TYPE_A) {
1267			off_t i, n;
1268			int c;
1269
1270			n = restart_point;
1271			i = 0;
1272			while (i++ < n) {
1273				if ((c = getc(fout)) == EOF) {
1274					if (ferror(fout)) {
1275						perror_reply(550, name);
1276						goto done;
1277					} else
1278						break;
1279				}
1280				if (c == '\n')
1281					i++;
1282			}
1283			/*
1284			 * We must do this seek to "current" position
1285			 * because we are changing from reading to
1286			 * writing.
1287			 */
1288			if (fseek(fout, 0L, SEEK_CUR) < 0) {
1289				perror_reply(550, name);
1290				goto done;
1291			}
1292		} else if (lseek(fileno(fout), restart_point, SEEK_SET) < 0) {
1293			perror_reply(550, name);
1294			goto done;
1295		}
1296	}
1297	din = dataconn(name, (off_t)-1, "r");
1298	if (din == NULL)
1299		goto done;
1300	if (receive_data(din, fout) == 0) {
1301		if (unique)
1302			reply(226, "Transfer complete (unique file name:%s).",
1303			    name);
1304		else
1305			reply(226, "Transfer complete.");
1306	}
1307	(void) fclose(din);
1308	data = -1;
1309	pdata = -1;
1310done:
1311	LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count);
1312	(*closefunc)(fout);
1313}
1314
1315static FILE *
1316getdatasock(char *mode)
1317{
1318	int on = 1, s, t, tries;
1319
1320	if (data >= 0)
1321		return (fdopen(data, mode));
1322	sigprocmask (SIG_BLOCK, &allsigs, NULL);
1323	s = monitor_socket(ctrl_addr.su_family);
1324	if (s < 0)
1325		goto bad;
1326	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
1327	    &on, sizeof(on)) < 0)
1328		goto bad;
1329	/* anchor socket to avoid multi-homing problems */
1330	data_source = ctrl_addr;
1331	data_source.su_port = htons(20); /* ftp-data port */
1332	for (tries = 1; ; tries++) {
1333		if (monitor_bind(s, (struct sockaddr *)&data_source,
1334		    data_source.su_len) >= 0)
1335			break;
1336		if (errno != EADDRINUSE || tries > 10)
1337			goto bad;
1338		sleep((unsigned int)tries);
1339	}
1340	sigprocmask (SIG_UNBLOCK, &allsigs, NULL);
1341
1342#ifdef IP_TOS
1343	if (ctrl_addr.su_family == AF_INET) {
1344		on = IPTOS_THROUGHPUT;
1345		if (setsockopt(s, IPPROTO_IP, IP_TOS, &on,
1346		    sizeof(int)) < 0)
1347			syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
1348	}
1349#endif
1350#ifdef TCP_NOPUSH
1351	/*
1352	 * Turn off push flag to keep sender TCP from sending short packets
1353	 * at the boundaries of each write().  Should probably do a SO_SNDBUF
1354	 * to set the send buffer size as well, but that may not be desirable
1355	 * in heavy-load situations.
1356	 */
1357	on = 1;
1358	if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, &on, sizeof(on)) < 0)
1359		syslog(LOG_WARNING, "setsockopt (TCP_NOPUSH): %m");
1360#endif
1361#ifdef SO_SNDBUF
1362	on = 65536;
1363	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &on, sizeof(on)) < 0)
1364		syslog(LOG_WARNING, "setsockopt (SO_SNDBUF): %m");
1365#endif
1366
1367	return (fdopen(s, mode));
1368bad:
1369	/* Return the real value of errno (close may change it) */
1370	t = errno;
1371	sigprocmask (SIG_UNBLOCK, &allsigs, NULL);
1372	if (s >= 0)
1373		(void) close(s);
1374	errno = t;
1375	return (NULL);
1376}
1377
1378static FILE *
1379dataconn(char *name, off_t size, char *mode)
1380{
1381	char sizebuf[32];
1382	FILE *file = NULL;
1383	int retry = 0;
1384	in_port_t *p;
1385	u_char *fa, *ha;
1386	size_t alen;
1387	int error;
1388
1389	file_size = size;
1390	byte_count = 0;
1391	if (size != (off_t) -1) {
1392		(void) snprintf(sizebuf, sizeof(sizebuf), " (%qd bytes)",
1393		    size);
1394	} else
1395		sizebuf[0] = '\0';
1396	if (pdata >= 0) {
1397		union sockunion from;
1398		int s;
1399		socklen_t fromlen = sizeof(from);
1400
1401		(void) alarm ((unsigned) timeout);
1402		s = accept(pdata, (struct sockaddr *)&from, &fromlen);
1403		(void) alarm (0);
1404		if (s < 0) {
1405			reply(425, "Can't open data connection.");
1406			(void) close(pdata);
1407			pdata = -1;
1408			return (NULL);
1409		}
1410		switch (from.su_family) {
1411		case AF_INET:
1412			p = (in_port_t *)&from.su_sin.sin_port;
1413			fa = (u_char *)&from.su_sin.sin_addr;
1414			ha = (u_char *)&his_addr.su_sin.sin_addr;
1415			alen = sizeof(struct in_addr);
1416			break;
1417		case AF_INET6:
1418			p = (in_port_t *)&from.su_sin6.sin6_port;
1419			fa = (u_char *)&from.su_sin6.sin6_addr;
1420			ha = (u_char *)&his_addr.su_sin6.sin6_addr;
1421			alen = sizeof(struct in6_addr);
1422			break;
1423		default:
1424			reply(425, "Can't build data connection: "
1425			    "unknown address family");
1426			(void) close(pdata);
1427			(void) close(s);
1428			pdata = -1;
1429			return (NULL);
1430		}
1431		if (from.su_family != his_addr.su_family ||
1432		    ntohs(*p) < IPPORT_RESERVED) {
1433			reply(425, "Can't build data connection: "
1434			    "address family or port error");
1435			(void) close(pdata);
1436			(void) close(s);
1437			pdata = -1;
1438			return (NULL);
1439		}
1440		if (portcheck && memcmp(fa, ha, alen) != 0) {
1441			reply(425, "Can't build data connection: "
1442			    "illegal port number");
1443			(void) close(pdata);
1444			(void) close(s);
1445			pdata = -1;
1446			return (NULL);
1447		}
1448		(void) close(pdata);
1449		pdata = s;
1450		reply(150, "Opening %s mode data connection for '%s'%s.",
1451		    type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1452		return (fdopen(pdata, mode));
1453	}
1454	if (data >= 0) {
1455		reply(125, "Using existing data connection for '%s'%s.",
1456		    name, sizebuf);
1457		usedefault = 1;
1458		return (fdopen(data, mode));
1459	}
1460	if (usedefault)
1461		data_dest = his_addr;
1462	usedefault = 1;
1463	do {
1464		if (file != NULL)
1465			(void) fclose(file);
1466		file = getdatasock(mode);
1467		if (file == NULL) {
1468			char hbuf[HOST_NAME_MAX+1], pbuf[10];
1469
1470			error = getnameinfo((struct sockaddr *)&data_source,
1471			    data_source.su_len, hbuf, sizeof(hbuf), pbuf,
1472			    sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV);
1473			if (error != 0)
1474				reply(425, "Can't create data socket: %s.",
1475				    strerror(errno));
1476			else
1477				reply(425,
1478				    "Can't create data socket (%s,%s): %s.",
1479				    hbuf, pbuf, strerror(errno));
1480			return (NULL);
1481		}
1482
1483		/*
1484		 * attempt to connect to reserved port on client machine;
1485		 * this looks like an attack
1486		 */
1487		switch (data_dest.su_family) {
1488		case AF_INET:
1489			p = (in_port_t *)&data_dest.su_sin.sin_port;
1490			fa = (u_char *)&data_dest.su_sin.sin_addr;
1491			ha = (u_char *)&his_addr.su_sin.sin_addr;
1492			alen = sizeof(struct in_addr);
1493			break;
1494		case AF_INET6:
1495			p = (in_port_t *)&data_dest.su_sin6.sin6_port;
1496			fa = (u_char *)&data_dest.su_sin6.sin6_addr;
1497			ha = (u_char *)&his_addr.su_sin6.sin6_addr;
1498			alen = sizeof(struct in6_addr);
1499			break;
1500		default:
1501			reply(425, "Can't build data connection: "
1502			    "unknown address family");
1503			(void) fclose(file);
1504			pdata = -1;
1505			return (NULL);
1506		}
1507		if (data_dest.su_family != his_addr.su_family ||
1508		    ntohs(*p) < IPPORT_RESERVED || ntohs(*p) == 2049) { /* XXX */
1509			reply(425, "Can't build data connection: "
1510			    "address family or port error");
1511			(void) fclose(file);
1512			return NULL;
1513		}
1514		if (portcheck && memcmp(fa, ha, alen) != 0) {
1515			reply(435, "Can't build data connection: "
1516			    "illegal port number");
1517			(void) fclose(file);
1518			return NULL;
1519		}
1520
1521		if (connect(fileno(file), (struct sockaddr *)&data_dest,
1522		    data_dest.su_len) == 0) {
1523			reply(150, "Opening %s mode data connection for '%s'%s.",
1524			    type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1525			data = fileno(file);
1526			return (file);
1527		}
1528		if (errno != EADDRINUSE)
1529			break;
1530		sleep((unsigned) swaitint);
1531		retry += swaitint;
1532	} while (retry <= swaitmax);
1533	perror_reply(425, "Can't build data connection");
1534	(void) fclose(file);
1535	return (NULL);
1536}
1537
1538/*
1539 * Transfer the contents of "instr" to "outstr" peer using the appropriate
1540 * encapsulation of the data subject to Mode, Structure, and Type.
1541 *
1542 * NB: Form isn't handled.
1543 */
1544static int
1545send_data(FILE *instr, FILE *outstr, off_t blksize, off_t filesize, int isreg)
1546{
1547	int c, cnt, filefd, netfd;
1548	char *buf, *bp;
1549	size_t len;
1550
1551	transflag++;
1552	switch (type) {
1553
1554	case TYPE_A:
1555		while ((c = getc(instr)) != EOF) {
1556			if (recvurg)
1557				goto got_oob;
1558			byte_count++;
1559			if (c == '\n') {
1560				if (ferror(outstr))
1561					goto data_err;
1562				(void) putc('\r', outstr);
1563			}
1564			(void) putc(c, outstr);
1565		}
1566		fflush(outstr);
1567		transflag = 0;
1568		if (ferror(instr))
1569			goto file_err;
1570		if (ferror(outstr))
1571			goto data_err;
1572		reply(226, "Transfer complete.");
1573		return(0);
1574
1575	case TYPE_I:
1576	case TYPE_L:
1577		/*
1578		 * isreg is only set if we are not doing restart and we
1579		 * are sending a regular file
1580		 */
1581		netfd = fileno(outstr);
1582		filefd = fileno(instr);
1583
1584		if (isreg && filesize < (off_t)16 * 1024 * 1024) {
1585			size_t fsize = (size_t)filesize;
1586
1587			if (fsize == 0) {
1588				transflag = 0;
1589				reply(226, "Transfer complete.");
1590				return(0);
1591			}
1592
1593			buf = mmap(0, fsize, PROT_READ, MAP_SHARED, filefd,
1594			    (off_t)0);
1595			if (buf == MAP_FAILED) {
1596				syslog(LOG_WARNING, "mmap(%llu): %m",
1597				    (unsigned long long)fsize);
1598				goto oldway;
1599			}
1600			bp = buf;
1601			len = fsize;
1602			do {
1603				cnt = write(netfd, bp, len);
1604				if (recvurg) {
1605					munmap(buf, fsize);
1606					goto got_oob;
1607				}
1608				len -= cnt;
1609				bp += cnt;
1610				if (cnt > 0)
1611					byte_count += cnt;
1612			} while(cnt > 0 && len > 0);
1613
1614			transflag = 0;
1615			munmap(buf, fsize);
1616			if (cnt < 0)
1617				goto data_err;
1618			reply(226, "Transfer complete.");
1619			return(0);
1620		}
1621
1622oldway:
1623		if ((buf = malloc((size_t)blksize)) == NULL) {
1624			transflag = 0;
1625			perror_reply(451, "Local resource failure: malloc");
1626			return(-1);
1627		}
1628
1629		while ((cnt = read(filefd, buf, (size_t)blksize)) > 0 &&
1630		    write(netfd, buf, cnt) == cnt)
1631			byte_count += cnt;
1632		transflag = 0;
1633		(void)free(buf);
1634		if (cnt != 0) {
1635			if (cnt < 0)
1636				goto file_err;
1637			goto data_err;
1638		}
1639		reply(226, "Transfer complete.");
1640		return(0);
1641	default:
1642		transflag = 0;
1643		reply(550, "Unimplemented TYPE %d in send_data", type);
1644		return(-1);
1645	}
1646
1647data_err:
1648	transflag = 0;
1649	reply(426, "Data connection");
1650	return(-1);
1651
1652file_err:
1653	transflag = 0;
1654	reply(551, "Error on input file");
1655	return(-1);
1656
1657got_oob:
1658	myoob();
1659	recvurg = 0;
1660	transflag = 0;
1661	return(-1);
1662}
1663
1664/*
1665 * Transfer data from peer to "outstr" using the appropriate encapulation of
1666 * the data subject to Mode, Structure, and Type.
1667 *
1668 * N.B.: Form isn't handled.
1669 */
1670static int
1671receive_data(FILE *instr, FILE *outstr)
1672{
1673	int c;
1674	int cnt;
1675	char buf[BUFSIZ];
1676	struct sigaction sa, sa_saved;
1677	volatile int bare_lfs = 0;
1678
1679	transflag++;
1680	switch (type) {
1681
1682	case TYPE_I:
1683	case TYPE_L:
1684		memset(&sa, 0, sizeof(sa));
1685		sigfillset(&sa.sa_mask);
1686		sa.sa_flags = SA_RESTART;
1687		sa.sa_handler = lostconn;
1688		(void) sigaction(SIGALRM, &sa, &sa_saved);
1689		do {
1690			(void) alarm ((unsigned) timeout);
1691			cnt = read(fileno(instr), buf, sizeof(buf));
1692			(void) alarm (0);
1693			if (recvurg)
1694				goto got_oob;
1695
1696			if (cnt > 0) {
1697				if (write(fileno(outstr), buf, cnt) != cnt)
1698					goto file_err;
1699				byte_count += cnt;
1700			}
1701		} while (cnt > 0);
1702		(void) sigaction(SIGALRM, &sa_saved, NULL);
1703		if (cnt < 0)
1704			goto data_err;
1705		transflag = 0;
1706		return (0);
1707
1708	case TYPE_E:
1709		reply(553, "TYPE E not implemented.");
1710		transflag = 0;
1711		return (-1);
1712
1713	case TYPE_A:
1714		while ((c = getc(instr)) != EOF) {
1715			if (recvurg)
1716				goto got_oob;
1717			byte_count++;
1718			if (c == '\n')
1719				bare_lfs++;
1720			while (c == '\r') {
1721				if (ferror(outstr))
1722					goto data_err;
1723				if ((c = getc(instr)) != '\n') {
1724					(void) putc ('\r', outstr);
1725					if (c == '\0' || c == EOF)
1726						goto contin2;
1727				}
1728			}
1729			(void) putc(c, outstr);
1730	contin2:	;
1731		}
1732		fflush(outstr);
1733		if (ferror(instr))
1734			goto data_err;
1735		if (ferror(outstr))
1736			goto file_err;
1737		transflag = 0;
1738		if (bare_lfs) {
1739			lreply(226,
1740			    "WARNING! %d bare linefeeds received in ASCII mode",
1741			    bare_lfs);
1742			printf("   File may not have transferred correctly.\r\n");
1743		}
1744		return (0);
1745	default:
1746		reply(550, "Unimplemented TYPE %d in receive_data", type);
1747		transflag = 0;
1748		return (-1);
1749	}
1750
1751data_err:
1752	transflag = 0;
1753	reply(426, "Data Connection");
1754	return (-1);
1755
1756file_err:
1757	transflag = 0;
1758	reply(452, "Error writing file");
1759	return (-1);
1760
1761got_oob:
1762	myoob();
1763	recvurg = 0;
1764	transflag = 0;
1765	return (-1);
1766}
1767
1768void
1769statfilecmd(char *filename)
1770{
1771	FILE *fin;
1772	int c;
1773	int atstart;
1774	char line[LINE_MAX];
1775
1776	(void)snprintf(line, sizeof(line), "/bin/ls -lgA %s", filename);
1777	fin = ftpd_popen(line, "r");
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);
1789				dologout(1);
1790				/* NOTREACHED */
1791			}
1792			if (ferror(fin)) {
1793				perror_reply(551, filename);
1794				(void) ftpd_pclose(fin);
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);
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 != '\0') ? "-" : "", p);
1963		if (debug)
1964			syslog(LOG_DEBUG, "<--- %d%s %s", n,
1965			    (next != '\0') ? "-" : "", 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 != '\0') ? "-" : "", 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