ftpd.c revision 1.209
1/*	$OpenBSD: ftpd.c,v 1.209 2015/10/04 11:58:09 tedu 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	pid_t pid;
1164	time_t start;
1165
1166	if (cmd == 0) {
1167		fin = fopen(name, "r");
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", &pid);
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		fclose(fin);
1232	} else {
1233		ftpd_pclose(fin, pid);
1234	}
1235}
1236
1237void
1238store(char *name, char *mode, int unique)
1239{
1240	FILE *fout, *din;
1241	int (*closefunc)(FILE *);
1242	struct stat st;
1243	int fd;
1244
1245	if (restart_point && *mode != 'a')
1246		mode = "r+";
1247
1248	if (unique && stat(name, &st) == 0) {
1249		char *nam;
1250
1251		fd = guniquefd(name, &nam);
1252		if (fd == -1) {
1253			LOGCMD(*mode == 'w' ? "put" : "append", name);
1254			return;
1255		}
1256		name = nam;
1257		fout = fdopen(fd, mode);
1258	} else
1259		fout = fopen(name, mode);
1260
1261	closefunc = fclose;
1262	if (fout == NULL) {
1263		perror_reply(553, name);
1264		LOGCMD(*mode == 'w' ? "put" : "append", name);
1265		return;
1266	}
1267	byte_count = -1;
1268	if (restart_point) {
1269		if (type == TYPE_A) {
1270			off_t i, n;
1271			int c;
1272
1273			n = restart_point;
1274			i = 0;
1275			while (i++ < n) {
1276				if ((c = getc(fout)) == EOF) {
1277					if (ferror(fout)) {
1278						perror_reply(550, name);
1279						goto done;
1280					} else
1281						break;
1282				}
1283				if (c == '\n')
1284					i++;
1285			}
1286			/*
1287			 * We must do this seek to "current" position
1288			 * because we are changing from reading to
1289			 * writing.
1290			 */
1291			if (fseek(fout, 0L, SEEK_CUR) < 0) {
1292				perror_reply(550, name);
1293				goto done;
1294			}
1295		} else if (lseek(fileno(fout), restart_point, SEEK_SET) < 0) {
1296			perror_reply(550, name);
1297			goto done;
1298		}
1299	}
1300	din = dataconn(name, (off_t)-1, "r");
1301	if (din == NULL)
1302		goto done;
1303	if (receive_data(din, fout) == 0) {
1304		if (unique)
1305			reply(226, "Transfer complete (unique file name:%s).",
1306			    name);
1307		else
1308			reply(226, "Transfer complete.");
1309	}
1310	(void) fclose(din);
1311	data = -1;
1312	pdata = -1;
1313done:
1314	LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count);
1315	(*closefunc)(fout);
1316}
1317
1318static FILE *
1319getdatasock(char *mode)
1320{
1321	int on = 1, s, t, tries;
1322
1323	if (data >= 0)
1324		return (fdopen(data, mode));
1325	sigprocmask (SIG_BLOCK, &allsigs, NULL);
1326	s = monitor_socket(ctrl_addr.su_family);
1327	if (s < 0)
1328		goto bad;
1329	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
1330	    &on, sizeof(on)) < 0)
1331		goto bad;
1332	/* anchor socket to avoid multi-homing problems */
1333	data_source = ctrl_addr;
1334	data_source.su_port = htons(20); /* ftp-data port */
1335	for (tries = 1; ; tries++) {
1336		if (monitor_bind(s, (struct sockaddr *)&data_source,
1337		    data_source.su_len) >= 0)
1338			break;
1339		if (errno != EADDRINUSE || tries > 10)
1340			goto bad;
1341		sleep((unsigned int)tries);
1342	}
1343	sigprocmask (SIG_UNBLOCK, &allsigs, NULL);
1344
1345#ifdef IP_TOS
1346	if (ctrl_addr.su_family == AF_INET) {
1347		on = IPTOS_THROUGHPUT;
1348		if (setsockopt(s, IPPROTO_IP, IP_TOS, &on,
1349		    sizeof(int)) < 0)
1350			syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
1351	}
1352#endif
1353#ifdef TCP_NOPUSH
1354	/*
1355	 * Turn off push flag to keep sender TCP from sending short packets
1356	 * at the boundaries of each write().  Should probably do a SO_SNDBUF
1357	 * to set the send buffer size as well, but that may not be desirable
1358	 * in heavy-load situations.
1359	 */
1360	on = 1;
1361	if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, &on, sizeof(on)) < 0)
1362		syslog(LOG_WARNING, "setsockopt (TCP_NOPUSH): %m");
1363#endif
1364#ifdef SO_SNDBUF
1365	on = 65536;
1366	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &on, sizeof(on)) < 0)
1367		syslog(LOG_WARNING, "setsockopt (SO_SNDBUF): %m");
1368#endif
1369
1370	return (fdopen(s, mode));
1371bad:
1372	/* Return the real value of errno (close may change it) */
1373	t = errno;
1374	sigprocmask (SIG_UNBLOCK, &allsigs, NULL);
1375	if (s >= 0)
1376		(void) close(s);
1377	errno = t;
1378	return (NULL);
1379}
1380
1381static FILE *
1382dataconn(char *name, off_t size, char *mode)
1383{
1384	char sizebuf[32];
1385	FILE *file = NULL;
1386	int retry = 0;
1387	in_port_t *p;
1388	u_char *fa, *ha;
1389	size_t alen;
1390	int error;
1391
1392	file_size = size;
1393	byte_count = 0;
1394	if (size != (off_t) -1) {
1395		(void) snprintf(sizebuf, sizeof(sizebuf), " (%qd bytes)",
1396		    size);
1397	} else
1398		sizebuf[0] = '\0';
1399	if (pdata >= 0) {
1400		union sockunion from;
1401		int s;
1402		socklen_t fromlen = sizeof(from);
1403
1404		(void) alarm ((unsigned) timeout);
1405		s = accept(pdata, (struct sockaddr *)&from, &fromlen);
1406		(void) alarm (0);
1407		if (s < 0) {
1408			reply(425, "Can't open data connection.");
1409			(void) close(pdata);
1410			pdata = -1;
1411			return (NULL);
1412		}
1413		switch (from.su_family) {
1414		case AF_INET:
1415			p = (in_port_t *)&from.su_sin.sin_port;
1416			fa = (u_char *)&from.su_sin.sin_addr;
1417			ha = (u_char *)&his_addr.su_sin.sin_addr;
1418			alen = sizeof(struct in_addr);
1419			break;
1420		case AF_INET6:
1421			p = (in_port_t *)&from.su_sin6.sin6_port;
1422			fa = (u_char *)&from.su_sin6.sin6_addr;
1423			ha = (u_char *)&his_addr.su_sin6.sin6_addr;
1424			alen = sizeof(struct in6_addr);
1425			break;
1426		default:
1427			reply(425, "Can't build data connection: "
1428			    "unknown address family");
1429			(void) close(pdata);
1430			(void) close(s);
1431			pdata = -1;
1432			return (NULL);
1433		}
1434		if (from.su_family != his_addr.su_family ||
1435		    ntohs(*p) < IPPORT_RESERVED) {
1436			reply(425, "Can't build data connection: "
1437			    "address family or port error");
1438			(void) close(pdata);
1439			(void) close(s);
1440			pdata = -1;
1441			return (NULL);
1442		}
1443		if (portcheck && memcmp(fa, ha, alen) != 0) {
1444			reply(425, "Can't build data connection: "
1445			    "illegal port number");
1446			(void) close(pdata);
1447			(void) close(s);
1448			pdata = -1;
1449			return (NULL);
1450		}
1451		(void) close(pdata);
1452		pdata = s;
1453		reply(150, "Opening %s mode data connection for '%s'%s.",
1454		    type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1455		return (fdopen(pdata, mode));
1456	}
1457	if (data >= 0) {
1458		reply(125, "Using existing data connection for '%s'%s.",
1459		    name, sizebuf);
1460		usedefault = 1;
1461		return (fdopen(data, mode));
1462	}
1463	if (usedefault)
1464		data_dest = his_addr;
1465	usedefault = 1;
1466	do {
1467		if (file != NULL)
1468			(void) fclose(file);
1469		file = getdatasock(mode);
1470		if (file == NULL) {
1471			char hbuf[HOST_NAME_MAX+1], pbuf[10];
1472
1473			error = getnameinfo((struct sockaddr *)&data_source,
1474			    data_source.su_len, hbuf, sizeof(hbuf), pbuf,
1475			    sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV);
1476			if (error != 0)
1477				reply(425, "Can't create data socket: %s.",
1478				    strerror(errno));
1479			else
1480				reply(425,
1481				    "Can't create data socket (%s,%s): %s.",
1482				    hbuf, pbuf, strerror(errno));
1483			return (NULL);
1484		}
1485
1486		/*
1487		 * attempt to connect to reserved port on client machine;
1488		 * this looks like an attack
1489		 */
1490		switch (data_dest.su_family) {
1491		case AF_INET:
1492			p = (in_port_t *)&data_dest.su_sin.sin_port;
1493			fa = (u_char *)&data_dest.su_sin.sin_addr;
1494			ha = (u_char *)&his_addr.su_sin.sin_addr;
1495			alen = sizeof(struct in_addr);
1496			break;
1497		case AF_INET6:
1498			p = (in_port_t *)&data_dest.su_sin6.sin6_port;
1499			fa = (u_char *)&data_dest.su_sin6.sin6_addr;
1500			ha = (u_char *)&his_addr.su_sin6.sin6_addr;
1501			alen = sizeof(struct in6_addr);
1502			break;
1503		default:
1504			reply(425, "Can't build data connection: "
1505			    "unknown address family");
1506			(void) fclose(file);
1507			pdata = -1;
1508			return (NULL);
1509		}
1510		if (data_dest.su_family != his_addr.su_family ||
1511		    ntohs(*p) < IPPORT_RESERVED || ntohs(*p) == 2049) { /* XXX */
1512			reply(425, "Can't build data connection: "
1513			    "address family or port error");
1514			(void) fclose(file);
1515			return NULL;
1516		}
1517		if (portcheck && memcmp(fa, ha, alen) != 0) {
1518			reply(435, "Can't build data connection: "
1519			    "illegal port number");
1520			(void) fclose(file);
1521			return NULL;
1522		}
1523
1524		if (connect(fileno(file), (struct sockaddr *)&data_dest,
1525		    data_dest.su_len) == 0) {
1526			reply(150, "Opening %s mode data connection for '%s'%s.",
1527			    type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1528			data = fileno(file);
1529			return (file);
1530		}
1531		if (errno != EADDRINUSE)
1532			break;
1533		sleep((unsigned) swaitint);
1534		retry += swaitint;
1535	} while (retry <= swaitmax);
1536	perror_reply(425, "Can't build data connection");
1537	(void) fclose(file);
1538	return (NULL);
1539}
1540
1541/*
1542 * Transfer the contents of "instr" to "outstr" peer using the appropriate
1543 * encapsulation of the data subject to Mode, Structure, and Type.
1544 *
1545 * NB: Form isn't handled.
1546 */
1547static int
1548send_data(FILE *instr, FILE *outstr, off_t blksize, off_t filesize, int isreg)
1549{
1550	int c, cnt, filefd, netfd;
1551	char *buf, *bp;
1552	size_t len;
1553
1554	transflag++;
1555	switch (type) {
1556
1557	case TYPE_A:
1558		while ((c = getc(instr)) != EOF) {
1559			if (recvurg)
1560				goto got_oob;
1561			byte_count++;
1562			if (c == '\n') {
1563				if (ferror(outstr))
1564					goto data_err;
1565				(void) putc('\r', outstr);
1566			}
1567			(void) putc(c, outstr);
1568		}
1569		fflush(outstr);
1570		transflag = 0;
1571		if (ferror(instr))
1572			goto file_err;
1573		if (ferror(outstr))
1574			goto data_err;
1575		reply(226, "Transfer complete.");
1576		return(0);
1577
1578	case TYPE_I:
1579	case TYPE_L:
1580		/*
1581		 * isreg is only set if we are not doing restart and we
1582		 * are sending a regular file
1583		 */
1584		netfd = fileno(outstr);
1585		filefd = fileno(instr);
1586
1587		if (isreg && filesize < (off_t)16 * 1024 * 1024) {
1588			size_t fsize = (size_t)filesize;
1589
1590			if (fsize == 0) {
1591				transflag = 0;
1592				reply(226, "Transfer complete.");
1593				return(0);
1594			}
1595
1596			buf = mmap(0, fsize, PROT_READ, MAP_SHARED, filefd,
1597			    (off_t)0);
1598			if (buf == MAP_FAILED) {
1599				syslog(LOG_WARNING, "mmap(%llu): %m",
1600				    (unsigned long long)fsize);
1601				goto oldway;
1602			}
1603			bp = buf;
1604			len = fsize;
1605			do {
1606				cnt = write(netfd, bp, len);
1607				if (recvurg) {
1608					munmap(buf, fsize);
1609					goto got_oob;
1610				}
1611				len -= cnt;
1612				bp += cnt;
1613				if (cnt > 0)
1614					byte_count += cnt;
1615			} while(cnt > 0 && len > 0);
1616
1617			transflag = 0;
1618			munmap(buf, fsize);
1619			if (cnt < 0)
1620				goto data_err;
1621			reply(226, "Transfer complete.");
1622			return(0);
1623		}
1624
1625oldway:
1626		if ((buf = malloc((size_t)blksize)) == NULL) {
1627			transflag = 0;
1628			perror_reply(451, "Local resource failure: malloc");
1629			return(-1);
1630		}
1631
1632		while ((cnt = read(filefd, buf, (size_t)blksize)) > 0 &&
1633		    write(netfd, buf, cnt) == cnt)
1634			byte_count += cnt;
1635		transflag = 0;
1636		(void)free(buf);
1637		if (cnt != 0) {
1638			if (cnt < 0)
1639				goto file_err;
1640			goto data_err;
1641		}
1642		reply(226, "Transfer complete.");
1643		return(0);
1644	default:
1645		transflag = 0;
1646		reply(550, "Unimplemented TYPE %d in send_data", type);
1647		return(-1);
1648	}
1649
1650data_err:
1651	transflag = 0;
1652	reply(426, "Data connection");
1653	return(-1);
1654
1655file_err:
1656	transflag = 0;
1657	reply(551, "Error on input file");
1658	return(-1);
1659
1660got_oob:
1661	myoob();
1662	recvurg = 0;
1663	transflag = 0;
1664	return(-1);
1665}
1666
1667/*
1668 * Transfer data from peer to "outstr" using the appropriate encapulation of
1669 * the data subject to Mode, Structure, and Type.
1670 *
1671 * N.B.: Form isn't handled.
1672 */
1673static int
1674receive_data(FILE *instr, FILE *outstr)
1675{
1676	int c;
1677	int cnt;
1678	char buf[BUFSIZ];
1679	struct sigaction sa, sa_saved;
1680	volatile int bare_lfs = 0;
1681
1682	transflag++;
1683	switch (type) {
1684
1685	case TYPE_I:
1686	case TYPE_L:
1687		memset(&sa, 0, sizeof(sa));
1688		sigfillset(&sa.sa_mask);
1689		sa.sa_flags = SA_RESTART;
1690		sa.sa_handler = lostconn;
1691		(void) sigaction(SIGALRM, &sa, &sa_saved);
1692		do {
1693			(void) alarm ((unsigned) timeout);
1694			cnt = read(fileno(instr), buf, sizeof(buf));
1695			(void) alarm (0);
1696			if (recvurg)
1697				goto got_oob;
1698
1699			if (cnt > 0) {
1700				if (write(fileno(outstr), buf, cnt) != cnt)
1701					goto file_err;
1702				byte_count += cnt;
1703			}
1704		} while (cnt > 0);
1705		(void) sigaction(SIGALRM, &sa_saved, NULL);
1706		if (cnt < 0)
1707			goto data_err;
1708		transflag = 0;
1709		return (0);
1710
1711	case TYPE_E:
1712		reply(553, "TYPE E not implemented.");
1713		transflag = 0;
1714		return (-1);
1715
1716	case TYPE_A:
1717		while ((c = getc(instr)) != EOF) {
1718			if (recvurg)
1719				goto got_oob;
1720			byte_count++;
1721			if (c == '\n')
1722				bare_lfs++;
1723			while (c == '\r') {
1724				if (ferror(outstr))
1725					goto data_err;
1726				if ((c = getc(instr)) != '\n') {
1727					(void) putc ('\r', outstr);
1728					if (c == '\0' || c == EOF)
1729						goto contin2;
1730				}
1731			}
1732			(void) putc(c, outstr);
1733	contin2:	;
1734		}
1735		fflush(outstr);
1736		if (ferror(instr))
1737			goto data_err;
1738		if (ferror(outstr))
1739			goto file_err;
1740		transflag = 0;
1741		if (bare_lfs) {
1742			lreply(226,
1743			    "WARNING! %d bare linefeeds received in ASCII mode",
1744			    bare_lfs);
1745			printf("   File may not have transferred correctly.\r\n");
1746		}
1747		return (0);
1748	default:
1749		reply(550, "Unimplemented TYPE %d in receive_data", type);
1750		transflag = 0;
1751		return (-1);
1752	}
1753
1754data_err:
1755	transflag = 0;
1756	reply(426, "Data Connection");
1757	return (-1);
1758
1759file_err:
1760	transflag = 0;
1761	reply(452, "Error writing file");
1762	return (-1);
1763
1764got_oob:
1765	myoob();
1766	recvurg = 0;
1767	transflag = 0;
1768	return (-1);
1769}
1770
1771void
1772statfilecmd(char *filename)
1773{
1774	FILE *fin;
1775	int c;
1776	int atstart;
1777	pid_t pid;
1778	char line[LINE_MAX];
1779
1780	(void)snprintf(line, sizeof(line), "/bin/ls -lgA %s", filename);
1781	fin = ftpd_popen(line, "r", &pid);
1782	if (fin == NULL) {
1783		reply(451, "Local resource failure");
1784		return;
1785	}
1786	lreply(211, "status of %s:", filename);
1787	atstart = 1;
1788	while ((c = getc(fin)) != EOF) {
1789		if (c == '\n') {
1790			if (ferror(stdout)){
1791				perror_reply(421, "control connection");
1792				(void) ftpd_pclose(fin, pid);
1793				dologout(1);
1794				/* NOTREACHED */
1795			}
1796			if (ferror(fin)) {
1797				perror_reply(551, filename);
1798				(void) ftpd_pclose(fin, pid);
1799				return;
1800			}
1801			(void) putc('\r', stdout);
1802		}
1803		if (atstart && isdigit(c))
1804			(void) putc(' ', stdout);
1805		(void) putc(c, stdout);
1806		atstart = (c == '\n');
1807	}
1808	(void) ftpd_pclose(fin, pid);
1809	reply(211, "End of Status");
1810}
1811
1812void
1813statcmd(void)
1814{
1815	union sockunion *su;
1816	u_char *a, *p;
1817	char hbuf[HOST_NAME_MAX+1];
1818	int ispassive;
1819	int error;
1820
1821	lreply(211, "%s FTP server status:", hostname);
1822	error = getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len,
1823	    hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
1824	printf("     Connected to %s", remotehost);
1825	if (error == 0 && strcmp(remotehost, hbuf) != 0)
1826		printf(" (%s)", hbuf);
1827	printf("\r\n");
1828	if (logged_in) {
1829		if (guest)
1830			printf("     Logged in anonymously\r\n");
1831		else
1832			printf("     Logged in as %s\r\n", pw->pw_name);
1833	} else if (askpasswd)
1834		printf("     Waiting for password\r\n");
1835	else
1836		printf("     Waiting for user name\r\n");
1837	printf("     TYPE: %s", typenames[type]);
1838	if (type == TYPE_A || type == TYPE_E)
1839		printf(", FORM: %s", formnames[form]);
1840	if (type == TYPE_L)
1841#if NBBY == 8
1842		printf(" %d", NBBY);
1843#else
1844		printf(" %d", bytesize);	/* need definition! */
1845#endif
1846	printf("; STRUcture: %s; transfer MODE: %s\r\n",
1847	    strunames[stru], modenames[mode]);
1848	ispassive = 0;
1849	if (data != -1)
1850		printf("     Data connection open\r\n");
1851	else if (pdata != -1) {
1852		printf("     in Passive mode\r\n");
1853		su = (union sockunion *)&pasv_addr;
1854		ispassive++;
1855		goto printaddr;
1856	} else if (usedefault == 0) {
1857		size_t alen;
1858		int af, i;
1859
1860		su = (union sockunion *)&data_dest;
1861printaddr:
1862		/* PASV/PORT */
1863		if (su->su_family == AF_INET) {
1864			if (ispassive)
1865				printf("211- PASV ");
1866			else
1867				printf("211- PORT ");
1868			a = (u_char *)&su->su_sin.sin_addr;
1869			p = (u_char *)&su->su_sin.sin_port;
1870			printf("(%u,%u,%u,%u,%u,%u)\r\n",
1871			    a[0], a[1], a[2], a[3],
1872			    p[0], p[1]);
1873		}
1874
1875		/* LPSV/LPRT */
1876		alen = 0;
1877		switch (su->su_family) {
1878		case AF_INET:
1879			a = (u_char *)&su->su_sin.sin_addr;
1880			p = (u_char *)&su->su_sin.sin_port;
1881			alen = sizeof(su->su_sin.sin_addr);
1882			af = 4;
1883			break;
1884		case AF_INET6:
1885			a = (u_char *)&su->su_sin6.sin6_addr;
1886			p = (u_char *)&su->su_sin6.sin6_port;
1887			alen = sizeof(su->su_sin6.sin6_addr);
1888			af = 6;
1889			break;
1890		default:
1891			af = 0;
1892			break;
1893		}
1894		if (af) {
1895			if (ispassive)
1896				printf("211- LPSV ");
1897			else
1898				printf("211- LPRT ");
1899			printf("(%u,%llu", af, (unsigned long long)alen);
1900			for (i = 0; i < alen; i++)
1901				printf(",%u", a[i]);
1902			printf(",%u,%u,%u)\r\n", 2, p[0], p[1]);
1903		}
1904
1905		/* EPRT/EPSV */
1906		switch (su->su_family) {
1907		case AF_INET:
1908			af = 1;
1909			break;
1910		case AF_INET6:
1911			af = 2;
1912			break;
1913		default:
1914			af = 0;
1915			break;
1916		}
1917		if (af) {
1918			char pbuf[10];
1919			union sockunion tmp = *su;
1920
1921			if (tmp.su_family == AF_INET6)
1922				tmp.su_sin6.sin6_scope_id = 0;
1923			if (getnameinfo((struct sockaddr *)&tmp, tmp.su_len,
1924			    hbuf, sizeof(hbuf), pbuf, sizeof(pbuf),
1925			    NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
1926				if (ispassive)
1927					printf("211- EPSV ");
1928				else
1929					printf("211- EPRT ");
1930				printf("(|%u|%s|%s|)\r\n",
1931				    af, hbuf, pbuf);
1932			}
1933		}
1934	} else
1935		printf("     No data connection\r\n");
1936	reply(211, "End of status");
1937}
1938
1939void
1940fatal(char *s)
1941{
1942
1943	reply(451, "Error in server: %s", s);
1944	reply(221, "Closing connection due to server error.");
1945	dologout(0);
1946	/* NOTREACHED */
1947}
1948
1949void
1950reply(int n, const char *fmt, ...)
1951{
1952	char *buf, *p, *next;
1953	int rval;
1954	va_list ap;
1955
1956	va_start(ap, fmt);
1957	rval = vasprintf(&buf, fmt, ap);
1958	va_end(ap);
1959	if (rval == -1 || buf == NULL) {
1960		printf("421 Local resource failure: malloc\r\n");
1961		fflush(stdout);
1962		dologout(1);
1963	}
1964	next = buf;
1965	while ((p = strsep(&next, "\n\r"))) {
1966		printf("%d%s %s\r\n", n, (next != NULL) ? "-" : "", p);
1967		if (debug)
1968			syslog(LOG_DEBUG, "<--- %d%s %s", n,
1969			    (next != NULL) ? "-" : "", p);
1970	}
1971	(void)fflush(stdout);
1972	free(buf);
1973}
1974
1975
1976void
1977reply_r(int n, const char *fmt, ...)
1978{
1979	char *p, *next;
1980	char msg[BUFSIZ];
1981	char buf[BUFSIZ];
1982	va_list ap;
1983	struct syslog_data sdata = SYSLOG_DATA_INIT;
1984
1985	sdata.log_fac = LOG_FTP;
1986	va_start(ap, fmt);
1987	vsnprintf(msg, sizeof(msg), fmt, ap);
1988	va_end(ap);
1989
1990	next = msg;
1991
1992	while ((p = strsep(&next, "\n\r"))) {
1993		snprintf(buf, sizeof(buf), "%d%s %s\r\n", n,
1994		    (next != NULL) ? "-" : "", p);
1995		write(STDOUT_FILENO, buf, strlen(buf));
1996		if (debug) {
1997			buf[strlen(buf) - 2] = '\0';
1998			syslog_r(LOG_DEBUG, &sdata, "<--- %s", buf);
1999		}
2000	}
2001}
2002
2003void
2004lreply(int n, const char *fmt, ...)
2005{
2006	va_list ap;
2007
2008	va_start(ap, fmt);
2009	(void)printf("%d- ", n);
2010	(void)vprintf(fmt, ap);
2011	va_end(ap);
2012	(void)printf("\r\n");
2013	(void)fflush(stdout);
2014	if (debug) {
2015		va_start(ap, fmt);
2016		syslog(LOG_DEBUG, "<--- %d- ", n);
2017		vsyslog(LOG_DEBUG, fmt, ap);
2018		va_end(ap);
2019	}
2020}
2021
2022static void
2023ack(char *s)
2024{
2025
2026	reply(250, "%s command successful.", s);
2027}
2028
2029void
2030nack(char *s)
2031{
2032
2033	reply(502, "%s command not implemented.", s);
2034}
2035
2036/* ARGSUSED */
2037void
2038yyerror(char *s)
2039{
2040	cbuf[strcspn(cbuf, "\n")] = '\0';
2041	reply(500, "'%s': command not understood.", cbuf);
2042}
2043
2044void
2045delete(char *name)
2046{
2047	struct stat st;
2048
2049	LOGCMD("delete", name);
2050	if (stat(name, &st) < 0) {
2051		perror_reply(550, name);
2052		return;
2053	}
2054	if ((st.st_mode&S_IFMT) == S_IFDIR) {
2055		if (rmdir(name) < 0) {
2056			perror_reply(550, name);
2057			return;
2058		}
2059		goto done;
2060	}
2061	if (unlink(name) < 0) {
2062		perror_reply(550, name);
2063		return;
2064	}
2065done:
2066	ack("DELE");
2067}
2068
2069void
2070cwd(char *path)
2071{
2072	FILE *message;
2073
2074	if (chdir(path) < 0)
2075		perror_reply(550, path);
2076	else {
2077		if ((message = fopen(_PATH_CWDMESG, "r")) != NULL) {
2078			char line[LINE_MAX];
2079
2080			while (fgets(line, sizeof(line), message) != NULL) {
2081				line[strcspn(line, "\n")] = '\0';
2082				lreply(250, "%s", line);
2083			}
2084			(void) fflush(stdout);
2085			(void) fclose(message);
2086		}
2087		ack("CWD");
2088	}
2089}
2090
2091void
2092replydirname(const char *name, const char *message)
2093{
2094	char *p, *ep;
2095	char npath[PATH_MAX * 2];
2096
2097	p = npath;
2098	ep = &npath[sizeof(npath) - 1];
2099	while (*name) {
2100		if (*name == '"') {
2101			if (ep - p < 2)
2102				break;
2103			*p++ = *name++;
2104			*p++ = '"';
2105		} else {
2106			if (ep - p < 1)
2107				break;
2108			*p++ = *name++;
2109		}
2110	}
2111	*p = '\0';
2112	reply(257, "\"%s\" %s", npath, message);
2113}
2114
2115void
2116makedir(char *name)
2117{
2118
2119	LOGCMD("mkdir", name);
2120	if (mkdir(name, 0777) < 0)
2121		perror_reply(550, name);
2122	else
2123		replydirname(name, "directory created.");
2124}
2125
2126void
2127removedir(char *name)
2128{
2129
2130	LOGCMD("rmdir", name);
2131	if (rmdir(name) < 0)
2132		perror_reply(550, name);
2133	else
2134		ack("RMD");
2135}
2136
2137void
2138pwd(void)
2139{
2140	char path[PATH_MAX];
2141
2142	if (getcwd(path, sizeof(path)) == NULL)
2143		perror_reply(550, "Can't get current directory");
2144	else
2145		replydirname(path, "is current directory.");
2146}
2147
2148char *
2149renamefrom(char *name)
2150{
2151	struct stat st;
2152
2153	if (stat(name, &st) < 0) {
2154		perror_reply(550, name);
2155		return ((char *)0);
2156	}
2157	reply(350, "File exists, ready for destination name");
2158	return (name);
2159}
2160
2161void
2162renamecmd(char *from, char *to)
2163{
2164
2165	LOGCMD2("rename", from, to);
2166	if (rename(from, to) < 0)
2167		perror_reply(550, "rename");
2168	else
2169		ack("RNTO");
2170}
2171
2172static void
2173dolog(struct sockaddr *sa)
2174{
2175	char hbuf[sizeof(remotehost)];
2176
2177	if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0, 0) == 0)
2178		(void) strlcpy(remotehost, hbuf, sizeof(remotehost));
2179	else
2180		(void) strlcpy(remotehost, "unknown", sizeof(remotehost));
2181
2182#ifdef HASSETPROCTITLE
2183	snprintf(proctitle, sizeof(proctitle), "%s: connected", remotehost);
2184	setproctitle("%s", proctitle);
2185#endif /* HASSETPROCTITLE */
2186
2187	if (logging) {
2188		int error;
2189		error = getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf),
2190		    NULL, 0, NI_NUMERICHOST);
2191		syslog(LOG_INFO, "connection from %s [%s]", remotehost,
2192		    error ? gai_strerror(error) : hbuf);
2193	}
2194}
2195
2196/*
2197 * Record logout in wtmp file and exit with supplied status.
2198 * NOTE: because this is called from signal handlers it cannot
2199 *       use stdio (or call other functions that use stdio).
2200 */
2201void
2202dologout(int status)
2203{
2204
2205	transflag = 0;
2206
2207	if (logged_in) {
2208		sigprocmask(SIG_BLOCK, &allsigs, NULL);
2209		if (!nowtmp)
2210			ftpdlogwtmp(ttyline, "", "");
2211		if (doutmp)
2212			ftpd_logout(utmp.ut_line);
2213	}
2214	/* beware of flushing buffers after a SIGPIPE */
2215	_exit(status);
2216}
2217
2218/*ARGSUSED*/
2219static void
2220sigurg(int signo)
2221{
2222
2223	recvurg = 1;
2224}
2225
2226static void
2227myoob(void)
2228{
2229	char *cp;
2230	int ret;
2231
2232	/* only process if transfer occurring */
2233	if (!transflag)
2234		return;
2235	cp = tmpline;
2236	ret = get_line(cp, sizeof(tmpline)-1, stdin);
2237	if (ret == -1) {
2238		reply(221, "You could at least say goodbye.");
2239		dologout(0);
2240	} else if (ret == -2) {
2241		/* Ignore truncated command */
2242		return;
2243	}
2244	upper(cp);
2245	if (strcmp(cp, "ABOR\r\n") == 0) {
2246		tmpline[0] = '\0';
2247		reply(426, "Transfer aborted. Data connection closed.");
2248		reply(226, "Abort successful");
2249	}
2250	if (strcmp(cp, "STAT\r\n") == 0) {
2251		tmpline[0] = '\0';
2252		if (file_size != (off_t) -1)
2253			reply(213, "Status: %qd of %qd bytes transferred",
2254			    byte_count, file_size);
2255		else
2256			reply(213, "Status: %qd bytes transferred", byte_count);
2257	}
2258}
2259
2260/*
2261 * Note: a response of 425 is not mentioned as a possible response to
2262 *	the PASV command in RFC959. However, it has been blessed as
2263 *	a legitimate response by Jon Postel in a telephone conversation
2264 *	with Rick Adams on 25 Jan 89.
2265 */
2266void
2267passive(void)
2268{
2269	socklen_t len;
2270	int on = 1;
2271	u_char *p, *a;
2272
2273	if (pw == NULL) {
2274		reply(530, "Please login with USER and PASS");
2275		return;
2276	}
2277	if (pdata >= 0)
2278		close(pdata);
2279	/*
2280	 * XXX
2281	 * At this point, it would be nice to have an algorithm that
2282	 * inserted a growing delay in an attack scenario.  Such a thing
2283	 * would look like continual passive sockets being opened, but
2284	 * nothing serious being done with them.  They're not used to
2285	 * move data; the entire attempt is just to use tcp FIN_WAIT
2286	 * resources.
2287	 */
2288	pdata = socket(AF_INET, SOCK_STREAM, 0);
2289	if (pdata < 0) {
2290		perror_reply(425, "Can't open passive connection");
2291		return;
2292	}
2293
2294	if (setsockopt(pdata, SOL_SOCKET, SO_KEEPALIVE,
2295	    &on, sizeof(on)) < 0)
2296		goto pasv_error;
2297
2298	on = IP_PORTRANGE_HIGH;
2299	if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2300	    &on, sizeof(on)) < 0)
2301		goto pasv_error;
2302
2303	pasv_addr = ctrl_addr;
2304	pasv_addr.su_sin.sin_port = 0;
2305	if (bind(pdata, (struct sockaddr *)&pasv_addr,
2306	    pasv_addr.su_len) < 0)
2307		goto pasv_error;
2308
2309	len = sizeof(pasv_addr);
2310	if (getsockname(pdata, (struct sockaddr *)&pasv_addr, &len) < 0)
2311		goto pasv_error;
2312	if (listen(pdata, 1) < 0)
2313		goto pasv_error;
2314	a = (u_char *)&pasv_addr.su_sin.sin_addr;
2315	p = (u_char *)&pasv_addr.su_sin.sin_port;
2316
2317	reply(227, "Entering Passive Mode (%u,%u,%u,%u,%u,%u)", a[0],
2318	    a[1], a[2], a[3], p[0], p[1]);
2319	return;
2320
2321pasv_error:
2322	perror_reply(425, "Can't open passive connection");
2323	(void) close(pdata);
2324	pdata = -1;
2325	return;
2326}
2327
2328int
2329epsvproto2af(int proto)
2330{
2331
2332	switch (proto) {
2333	case 1:	return AF_INET;
2334#ifdef INET6
2335	case 2:	return AF_INET6;
2336#endif
2337	default: return -1;
2338	}
2339}
2340
2341int
2342af2epsvproto(int af)
2343{
2344
2345	switch (af) {
2346	case AF_INET:	return 1;
2347#ifdef INET6
2348	case AF_INET6:	return 2;
2349#endif
2350	default:	return -1;
2351	}
2352}
2353
2354/*
2355 * 228 Entering Long Passive Mode (af, hal, h1, h2, h3,..., pal, p1, p2...)
2356 * 229 Entering Extended Passive Mode (|||port|)
2357 */
2358void
2359long_passive(char *cmd, int pf)
2360{
2361	socklen_t len;
2362	int on = 1;
2363	u_char *p, *a;
2364
2365	if (!logged_in) {
2366		syslog(LOG_NOTICE, "long passive but not logged in");
2367		reply(503, "Login with USER first.");
2368		return;
2369	}
2370
2371	if (pf != PF_UNSPEC && ctrl_addr.su_family != pf) {
2372		/*
2373		 * XXX
2374		 * only EPRT/EPSV ready clients will understand this
2375		 */
2376		if (strcmp(cmd, "EPSV") != 0)
2377			reply(501, "Network protocol mismatch"); /*XXX*/
2378		else
2379			epsv_protounsupp("Network protocol mismatch");
2380
2381		return;
2382	}
2383
2384	if (pdata >= 0)
2385		close(pdata);
2386	/*
2387	 * XXX
2388	 * At this point, it would be nice to have an algorithm that
2389	 * inserted a growing delay in an attack scenario.  Such a thing
2390	 * would look like continual passive sockets being opened, but
2391	 * nothing serious being done with them.  They not used to move
2392	 * data; the entire attempt is just to use tcp FIN_WAIT
2393	 * resources.
2394	 */
2395	pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0);
2396	if (pdata < 0) {
2397		perror_reply(425, "Can't open passive connection");
2398		return;
2399	}
2400
2401	if (setsockopt(pdata, SOL_SOCKET, SO_KEEPALIVE,
2402	    &on, sizeof(on)) < 0)
2403		goto pasv_error;
2404
2405	switch (ctrl_addr.su_family) {
2406	case AF_INET:
2407		on = IP_PORTRANGE_HIGH;
2408		if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2409		    &on, sizeof(on)) < 0)
2410			goto pasv_error;
2411		break;
2412	case AF_INET6:
2413		on = IPV6_PORTRANGE_HIGH;
2414		if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE,
2415		    &on, sizeof(on)) < 0)
2416			goto pasv_error;
2417		break;
2418	}
2419
2420	pasv_addr = ctrl_addr;
2421	pasv_addr.su_port = 0;
2422	if (bind(pdata, (struct sockaddr *)&pasv_addr, pasv_addr.su_len) < 0)
2423		goto pasv_error;
2424	len = pasv_addr.su_len;
2425	if (getsockname(pdata, (struct sockaddr *)&pasv_addr, &len) < 0)
2426		goto pasv_error;
2427	if (listen(pdata, 1) < 0)
2428		goto pasv_error;
2429	p = (u_char *)&pasv_addr.su_port;
2430
2431	if (strcmp(cmd, "LPSV") == 0) {
2432		switch (pasv_addr.su_family) {
2433		case AF_INET:
2434			a = (u_char *)&pasv_addr.su_sin.sin_addr;
2435			reply(228,
2436			    "Entering Long Passive Mode (%u,%u,%u,%u,%u,%u,%u,%u,%u)",
2437			    4, 4, a[0], a[1], a[2], a[3], 2, p[0], p[1]);
2438			return;
2439		case AF_INET6:
2440			a = (u_char *)&pasv_addr.su_sin6.sin6_addr;
2441			reply(228,
2442			    "Entering Long Passive Mode (%u,%u,%u,%u,%u,%u,"
2443			    "%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u)",
2444				6, 16, a[0], a[1], a[2], a[3], a[4],
2445				a[5], a[6], a[7], a[8], a[9], a[10],
2446				a[11], a[12], a[13], a[14], a[15],
2447				2, p[0], p[1]);
2448			return;
2449		}
2450	} else if (strcmp(cmd, "EPSV") == 0) {
2451		switch (pasv_addr.su_family) {
2452		case AF_INET:
2453		case AF_INET6:
2454			reply(229, "Entering Extended Passive Mode (|||%u|)",
2455			    ntohs(pasv_addr.su_port));
2456			return;
2457		}
2458	} else {
2459		/* more proper error code? */
2460	}
2461
2462  pasv_error:
2463	perror_reply(425, "Can't open passive connection");
2464	(void) close(pdata);
2465	pdata = -1;
2466	return;
2467}
2468
2469/*
2470 * EPRT |proto|addr|port|
2471 */
2472int
2473extended_port(const char *arg)
2474{
2475	char *tmp = NULL;
2476	char *result[3];
2477	char *p, *q;
2478	char delim;
2479	struct addrinfo hints;
2480	struct addrinfo *res = NULL;
2481	int i;
2482	unsigned long proto;
2483
2484	if (epsvall) {
2485		reply(501, "EPRT disallowed after EPSV ALL");
2486		return -1;
2487	}
2488
2489	usedefault = 0;
2490	if (pdata >= 0) {
2491		(void) close(pdata);
2492		pdata = -1;
2493	}
2494
2495	tmp = strdup(arg);
2496	if (!tmp) {
2497		fatal("not enough core.");
2498		/*NOTREACHED*/
2499	}
2500	p = tmp;
2501	delim = p[0];
2502	p++;
2503	memset(result, 0, sizeof(result));
2504	for (i = 0; i < 3; i++) {
2505		q = strchr(p, delim);
2506		if (!q || *q != delim)
2507			goto parsefail;
2508		*q++ = '\0';
2509		result[i] = p;
2510		p = q;
2511	}
2512
2513	/* some more sanity check */
2514	p = NULL;
2515	(void)strtoul(result[2], &p, 10);
2516	if (!*result[2] || *p)
2517		goto protounsupp;
2518	p = NULL;
2519	proto = strtoul(result[0], &p, 10);
2520	if (!*result[0] || *p)
2521		goto protounsupp;
2522
2523	memset(&hints, 0, sizeof(hints));
2524	hints.ai_family = epsvproto2af((int)proto);
2525	if (hints.ai_family < 0)
2526		goto protounsupp;
2527	hints.ai_socktype = SOCK_STREAM;
2528	hints.ai_flags = AI_NUMERICHOST;	/*no DNS*/
2529	if (getaddrinfo(result[1], result[2], &hints, &res))
2530		goto parsefail;
2531	if (res->ai_next)
2532		goto parsefail;
2533	if (sizeof(data_dest) < res->ai_addrlen)
2534		goto parsefail;
2535	memcpy(&data_dest, res->ai_addr, res->ai_addrlen);
2536	if (his_addr.su_family == AF_INET6 &&
2537	    data_dest.su_family == AF_INET6) {
2538		/* XXX more sanity checks! */
2539		data_dest.su_sin6.sin6_scope_id =
2540		    his_addr.su_sin6.sin6_scope_id;
2541	}
2542	if (pdata >= 0) {
2543		(void) close(pdata);
2544		pdata = -1;
2545	}
2546	reply(200, "EPRT command successful.");
2547
2548	if (tmp)
2549		free(tmp);
2550	if (res)
2551		freeaddrinfo(res);
2552	return 0;
2553
2554parsefail:
2555	reply(500, "Invalid argument, rejected.");
2556	usedefault = 1;
2557	if (tmp)
2558		free(tmp);
2559	if (res)
2560		freeaddrinfo(res);
2561	return -1;
2562
2563protounsupp:
2564	epsv_protounsupp("Protocol not supported");
2565	usedefault = 1;
2566	if (tmp)
2567		free(tmp);
2568	if (res)
2569		freeaddrinfo(res);
2570	return -1;
2571}
2572
2573/*
2574 * 522 Protocol not supported (proto,...)
2575 * as we assume address family for control and data connections are the same,
2576 * we do not return the list of address families we support - instead, we
2577 * return the address family of the control connection.
2578 */
2579void
2580epsv_protounsupp(const char *message)
2581{
2582	int proto;
2583
2584	proto = af2epsvproto(ctrl_addr.su_family);
2585	if (proto < 0)
2586		reply(501, "%s", message);	/*XXX*/
2587	else
2588		reply(522, "%s, use (%d)", message, proto);
2589}
2590
2591/*
2592 * Generate unique name for file with basename "local".
2593 * The file named "local" is already known to exist.
2594 * Generates failure reply on error.
2595 */
2596static int
2597guniquefd(char *local, char **nam)
2598{
2599	static char new[PATH_MAX];
2600	struct stat st;
2601	int count, len, fd;
2602	char *cp;
2603
2604	cp = strrchr(local, '/');
2605	if (cp)
2606		*cp = '\0';
2607	if (stat(cp ? local : ".", &st) < 0) {
2608		perror_reply(553, cp ? local : ".");
2609		return (-1);
2610	}
2611	if (cp)
2612		*cp = '/';
2613	len = strlcpy(new, local, sizeof(new));
2614	if (len+2+1 >= sizeof(new)-1)
2615		return (-1);
2616	cp = new + len;
2617	*cp++ = '.';
2618	for (count = 1; count < 100; count++) {
2619		(void)snprintf(cp, sizeof(new) - (cp - new), "%d", count);
2620		fd = open(new, O_RDWR|O_CREAT|O_EXCL, 0666);
2621		if (fd == -1)
2622			continue;
2623		if (nam)
2624			*nam = new;
2625		return (fd);
2626	}
2627	reply(452, "Unique file name cannot be created.");
2628	return (-1);
2629}
2630
2631/*
2632 * Format and send reply containing system error number.
2633 */
2634void
2635perror_reply(int code, char *string)
2636{
2637
2638	reply(code, "%s: %s.", string, strerror(errno));
2639}
2640
2641static char *onefile[] = {
2642	"",
2643	0
2644};
2645
2646void
2647send_file_list(char *whichf)
2648{
2649	struct stat st;
2650	DIR *dirp = NULL;
2651	struct dirent *dir;
2652	FILE *dout = NULL;
2653	char **dirlist;
2654	char *dirname;
2655	int simple = 0;
2656	volatile int freeglob = 0;
2657	glob_t gl;
2658
2659	if (strpbrk(whichf, "~{[*?") != NULL) {
2660		memset(&gl, 0, sizeof(gl));
2661		freeglob = 1;
2662		if (glob(whichf,
2663		    GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE|GLOB_LIMIT,
2664		    0, &gl)) {
2665			reply(550, "not found");
2666			goto out;
2667		} else if (gl.gl_pathc == 0) {
2668			errno = ENOENT;
2669			perror_reply(550, whichf);
2670			goto out;
2671		}
2672		dirlist = gl.gl_pathv;
2673	} else {
2674		onefile[0] = whichf;
2675		dirlist = onefile;
2676		simple = 1;
2677	}
2678
2679	while ((dirname = *dirlist++)) {
2680		if (stat(dirname, &st) < 0) {
2681			/*
2682			 * If user typed "ls -l", etc, and the client
2683			 * used NLST, do what the user meant.
2684			 */
2685			if (dirname[0] == '-' && *dirlist == NULL &&
2686			    transflag == 0) {
2687				retrieve("/bin/ls %s", dirname);
2688				goto out;
2689			}
2690			perror_reply(550, whichf);
2691			if (dout != NULL) {
2692				(void) fclose(dout);
2693				transflag = 0;
2694				data = -1;
2695				pdata = -1;
2696			}
2697			goto out;
2698		}
2699
2700		if (S_ISREG(st.st_mode)) {
2701			if (dout == NULL) {
2702				dout = dataconn("file list", (off_t)-1, "w");
2703				if (dout == NULL)
2704					goto out;
2705				transflag++;
2706			}
2707			fprintf(dout, "%s%s\n", dirname,
2708				type == TYPE_A ? "\r" : "");
2709			byte_count += strlen(dirname) + 1;
2710			continue;
2711		} else if (!S_ISDIR(st.st_mode))
2712			continue;
2713
2714		if ((dirp = opendir(dirname)) == NULL)
2715			continue;
2716
2717		while ((dir = readdir(dirp)) != NULL) {
2718			char nbuf[PATH_MAX];
2719
2720			if (recvurg) {
2721				myoob();
2722				recvurg = 0;
2723				transflag = 0;
2724				goto out;
2725			}
2726
2727			if (dir->d_name[0] == '.' && dir->d_namlen == 1)
2728				continue;
2729			if (dir->d_name[0] == '.' && dir->d_name[1] == '.' &&
2730			    dir->d_namlen == 2)
2731				continue;
2732
2733			snprintf(nbuf, sizeof(nbuf), "%s/%s", dirname,
2734				 dir->d_name);
2735
2736			/*
2737			 * We have to do a stat to insure it's
2738			 * not a directory or special file.
2739			 */
2740			if (simple || (stat(nbuf, &st) == 0 &&
2741			    S_ISREG(st.st_mode))) {
2742				if (dout == NULL) {
2743					dout = dataconn("file list", (off_t)-1,
2744						"w");
2745					if (dout == NULL)
2746						goto out;
2747					transflag++;
2748				}
2749				if (nbuf[0] == '.' && nbuf[1] == '/')
2750					fprintf(dout, "%s%s\n", &nbuf[2],
2751						type == TYPE_A ? "\r" : "");
2752				else
2753					fprintf(dout, "%s%s\n", nbuf,
2754						type == TYPE_A ? "\r" : "");
2755				byte_count += strlen(nbuf) + 1;
2756			}
2757		}
2758		(void) closedir(dirp);
2759	}
2760
2761	if (dout == NULL)
2762		reply(550, "No files found.");
2763	else if (ferror(dout) != 0)
2764		perror_reply(550, "Data connection");
2765	else
2766		reply(226, "Transfer complete.");
2767
2768	transflag = 0;
2769	if (dout != NULL)
2770		(void) fclose(dout);
2771	else {
2772		if (pdata >= 0)
2773			close(pdata);
2774	}
2775	data = -1;
2776	pdata = -1;
2777out:
2778	if (freeglob) {
2779		freeglob = 0;
2780		globfree(&gl);
2781	}
2782}
2783
2784/*ARGSUSED*/
2785static void
2786reapchild(int signo)
2787{
2788	int save_errno = errno;
2789	int rval;
2790
2791	do {
2792		rval = waitpid(-1, NULL, WNOHANG);
2793	} while (rval > 0 || (rval == -1 && errno == EINTR));
2794	errno = save_errno;
2795}
2796
2797void
2798logxfer(char *name, off_t size, time_t start)
2799{
2800	char buf[400 + (HOST_NAME_MAX+1)*4 + PATH_MAX*4];
2801	char dir[PATH_MAX], path[PATH_MAX], rpath[PATH_MAX];
2802	char vremotehost[(HOST_NAME_MAX+1)*4], vpath[PATH_MAX*4];
2803	char *vpw;
2804	time_t now;
2805	int len;
2806
2807	if ((statfd >= 0) && (getcwd(dir, sizeof(dir)) != NULL)) {
2808		time(&now);
2809
2810		vpw = malloc(strlen(guest ? guestpw : pw->pw_name) * 4 + 1);
2811		if (vpw == NULL)
2812			return;
2813
2814		snprintf(path, sizeof(path), "%s/%s", dir, name);
2815		if (realpath(path, rpath) == NULL)
2816			strlcpy(rpath, path, sizeof(rpath));
2817		strvis(vpath, rpath, VIS_SAFE|VIS_NOSLASH);
2818
2819		strvis(vremotehost, remotehost, VIS_SAFE|VIS_NOSLASH);
2820		strvis(vpw, guest? guestpw : pw->pw_name, VIS_SAFE|VIS_NOSLASH);
2821
2822		len = snprintf(buf, sizeof(buf),
2823		    "%.24s %lld %s %qd %s %c %s %c %c %s ftp %d %s %s\n",
2824		    ctime(&now), (long long)(now - start + (now == start)),
2825		    vremotehost, (long long)size, vpath,
2826		    ((type == TYPE_A) ? 'a' : 'b'), "*" /* none yet */,
2827		    'o', ((guest) ? 'a' : 'r'),
2828		    vpw, 0 /* none yet */,
2829		    ((guest) ? "*" : pw->pw_name), dhostname);
2830		free(vpw);
2831
2832		if (len >= sizeof(buf) || len == -1) {
2833			if ((len = strlen(buf)) == 0)
2834				return;		/* should not happen */
2835			buf[len - 1] = '\n';
2836		}
2837		write(statfd, buf, len);
2838	}
2839}
2840
2841void
2842set_slave_signals(void)
2843{
2844	struct sigaction sa;
2845
2846	sigemptyset(&sa.sa_mask);
2847	sa.sa_flags = SA_RESTART;
2848
2849	sa.sa_handler = SIG_DFL;
2850	(void) sigaction(SIGCHLD, &sa, NULL);
2851
2852	sa.sa_handler = sigurg;
2853	sa.sa_flags = 0;		/* don't restart syscalls for SIGURG */
2854	(void) sigaction(SIGURG, &sa, NULL);
2855
2856	sigfillset(&sa.sa_mask);	/* block all signals in handler */
2857	sa.sa_flags = SA_RESTART;
2858	sa.sa_handler = sigquit;
2859	(void) sigaction(SIGHUP, &sa, NULL);
2860	(void) sigaction(SIGINT, &sa, NULL);
2861	(void) sigaction(SIGQUIT, &sa, NULL);
2862	(void) sigaction(SIGTERM, &sa, NULL);
2863
2864	sa.sa_handler = lostconn;
2865	(void) sigaction(SIGPIPE, &sa, NULL);
2866
2867	sa.sa_handler = toolong;
2868	(void) sigaction(SIGALRM, &sa, NULL);
2869
2870#ifdef F_SETOWN
2871	if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1)
2872		syslog(LOG_ERR, "fcntl F_SETOWN: %m");
2873#endif
2874}
2875
2876/*
2877 * Allocate space and return a copy of the specified dir.
2878 * If 'dir' begins with a tilde (~), expand it.
2879 */
2880char *
2881copy_dir(char *dir, struct passwd *pw)
2882{
2883	char *cp;
2884	char *newdir;
2885	char *user = NULL;
2886
2887	/* Nothing to expand */
2888	if (dir[0] != '~')
2889		return (strdup(dir));
2890
2891	/* "dir" is of form ~user/some/dir, lookup user. */
2892	if (dir[1] != '/' && dir[1] != '\0') {
2893		if ((cp = strchr(dir + 1, '/')) == NULL)
2894			cp = dir + strlen(dir);
2895		if ((user = malloc((size_t)(cp - dir))) == NULL)
2896			return (NULL);
2897		strlcpy(user, dir + 1, (size_t)(cp - dir));
2898
2899		/* Only do lookup if it is a different user. */
2900		if (strcmp(user, pw->pw_name) != 0) {
2901			if ((pw = getpwnam(user)) == NULL) {
2902				/* No such user, interpret literally */
2903				free(user);
2904				return(strdup(dir));
2905			}
2906		}
2907		free(user);
2908	}
2909
2910	/*
2911	 * If there is no directory separator (/) then it is just pw_dir.
2912	 * Otherwise, replace ~foo with pw_dir.
2913	 */
2914	if ((cp = strchr(dir + 1, '/')) == NULL) {
2915		newdir = strdup(pw->pw_dir);
2916	} else {
2917		if (asprintf(&newdir, "%s%s", pw->pw_dir, cp) == -1)
2918			return (NULL);
2919	}
2920
2921	return(newdir);
2922}
2923