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