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