ftpd.c revision 154634
1169695Skan/*
2169695Skan * Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994
3169695Skan *	The Regents of the University of California.  All rights reserved.
4169695Skan *
5169695Skan * Redistribution and use in source and binary forms, with or without
6169695Skan * modification, are permitted provided that the following conditions
7169695Skan * are met:
8169695Skan * 1. Redistributions of source code must retain the above copyright
9169695Skan *    notice, this list of conditions and the following disclaimer.
10169695Skan * 2. Redistributions in binary form must reproduce the above copyright
11169695Skan *    notice, this list of conditions and the following disclaimer in the
12169695Skan *    documentation and/or other materials provided with the distribution.
13169695Skan * 3. All advertising materials mentioning features or use of this software
14169695Skan *    must display the following acknowledgement:
15169695Skan *	This product includes software developed by the University of
16169695Skan *	California, Berkeley and its contributors.
17169695Skan * 4. Neither the name of the University nor the names of its contributors
18169695Skan *    may be used to endorse or promote products derived from this software
19169695Skan *    without specific prior written permission.
20169695Skan *
21169695Skan * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22169695Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23169695Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24169695Skan * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25169695Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26169695Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27169695Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28169695Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29169695Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30169695Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31169695Skan * SUCH DAMAGE.
32169695Skan */
33169695Skan
34169695Skan#if 0
35169695Skan#ifndef lint
36169695Skanstatic char copyright[] =
37169695Skan"@(#) Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994\n\
38169695Skan	The Regents of the University of California.  All rights reserved.\n";
39169695Skan#endif /* not lint */
40169695Skan#endif
41169695Skan
42169695Skan#ifndef lint
43169695Skan#if 0
44169695Skanstatic char sccsid[] = "@(#)ftpd.c	8.4 (Berkeley) 4/16/94";
45169695Skan#endif
46169695Skan#endif /* not lint */
47169695Skan
48169695Skan#include <sys/cdefs.h>
49169695Skan__FBSDID("$FreeBSD: head/libexec/ftpd/ftpd.c 154634 2006-01-21 13:06:37Z yar $");
50169695Skan
51169695Skan/*
52169695Skan * FTP server.
53169695Skan */
54169695Skan#include <sys/param.h>
55169695Skan#include <sys/ioctl.h>
56169695Skan#include <sys/mman.h>
57169695Skan#include <sys/socket.h>
58169695Skan#include <sys/stat.h>
59169695Skan#include <sys/time.h>
60169695Skan#include <sys/wait.h>
61169695Skan
62169695Skan#include <netinet/in.h>
63169695Skan#include <netinet/in_systm.h>
64169695Skan#include <netinet/ip.h>
65169695Skan#include <netinet/tcp.h>
66169695Skan
67169695Skan#define	FTP_NAMES
68169695Skan#include <arpa/ftp.h>
69169695Skan#include <arpa/inet.h>
70169695Skan#include <arpa/telnet.h>
71169695Skan
72169695Skan#include <ctype.h>
73169695Skan#include <dirent.h>
74169695Skan#include <err.h>
75169695Skan#include <errno.h>
76169695Skan#include <fcntl.h>
77169695Skan#include <glob.h>
78169695Skan#include <limits.h>
79169695Skan#include <netdb.h>
80169695Skan#include <pwd.h>
81169695Skan#include <grp.h>
82169695Skan#include <opie.h>
83169695Skan#include <signal.h>
84169695Skan#include <stdint.h>
85169695Skan#include <stdio.h>
86169695Skan#include <stdlib.h>
87169695Skan#include <string.h>
88169695Skan#include <syslog.h>
89169695Skan#include <time.h>
90169695Skan#include <unistd.h>
91169695Skan#include <libutil.h>
92169695Skan#ifdef	LOGIN_CAP
93169695Skan#include <login_cap.h>
94169695Skan#endif
95169695Skan
96169695Skan#ifdef USE_PAM
97169695Skan#include <security/pam_appl.h>
98169695Skan#endif
99169695Skan
100169695Skan#include "pathnames.h"
101169695Skan#include "extern.h"
102169695Skan
103169695Skan#include <stdarg.h>
104169695Skan
105169695Skanstatic char version[] = "Version 6.00LS";
106169695Skan#undef main
107169695Skan
108169695Skanextern	off_t restart_point;
109169695Skanextern	char cbuf[];
110169695Skan
111169695Skanunion sockunion ctrl_addr;
112169695Skanunion sockunion data_source;
113169695Skanunion sockunion data_dest;
114169695Skanunion sockunion his_addr;
115169695Skanunion sockunion pasv_addr;
116169695Skan
117169695Skanint	daemon_mode;
118169695Skanint	data;
119169695Skanint	dataport;
120169695Skanint	hostinfo = 1;	/* print host-specific info in messages */
121169695Skanint	logged_in;
122169695Skanstruct	passwd *pw;
123169695Skanchar	*homedir;
124169695Skanint	ftpdebug;
125169695Skanint	timeout = 900;    /* timeout after 15 minutes of inactivity */
126169695Skanint	maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */
127int	logging;
128int	restricted_data_ports = 1;
129int	paranoid = 1;	  /* be extra careful about security */
130int	anon_only = 0;    /* Only anonymous ftp allowed */
131int	guest;
132int	dochroot;
133char	*chrootdir;
134int	dowtmp = 1;
135int	stats;
136int	statfd = -1;
137int	type;
138int	form;
139int	stru;			/* avoid C keyword */
140int	mode;
141int	usedefault = 1;		/* for data transfers */
142int	pdata = -1;		/* for passive mode */
143int	readonly = 0;		/* Server is in readonly mode.	*/
144int	noepsv = 0;		/* EPSV command is disabled.	*/
145int	noretr = 0;		/* RETR command is disabled.	*/
146int	noguestretr = 0;	/* RETR command is disabled for anon users. */
147int	noguestmkd = 0;		/* MKD command is disabled for anon users. */
148int	noguestmod = 1;		/* anon users may not modify existing files. */
149
150off_t	file_size;
151off_t	byte_count;
152#if !defined(CMASK) || CMASK == 0
153#undef CMASK
154#define CMASK 027
155#endif
156int	defumask = CMASK;		/* default umask value */
157char	tmpline[7];
158char	*hostname;
159int	epsvall = 0;
160
161#ifdef VIRTUAL_HOSTING
162char	*ftpuser;
163
164static struct ftphost {
165	struct ftphost	*next;
166	struct addrinfo *hostinfo;
167	char		*hostname;
168	char		*anonuser;
169	char		*statfile;
170	char		*welcome;
171	char		*loginmsg;
172} *thishost, *firsthost;
173
174#endif
175char	remotehost[NI_MAXHOST];
176char	*ident = NULL;
177
178static char	ttyline[20];
179char		*tty = ttyline;		/* for klogin */
180
181#ifdef USE_PAM
182static int	auth_pam(struct passwd**, const char*);
183pam_handle_t	*pamh = NULL;
184#endif
185
186static struct opie	opiedata;
187static char		opieprompt[OPIE_CHALLENGE_MAX+1];
188static int		pwok;
189
190char	*pid_file = NULL; /* means default location to pidfile(3) */
191
192/*
193 * Limit number of pathnames that glob can return.
194 * A limit of 0 indicates the number of pathnames is unlimited.
195 */
196#define MAXGLOBARGS	16384
197#
198
199/*
200 * Timeout intervals for retrying connections
201 * to hosts that don't accept PORT cmds.  This
202 * is a kludge, but given the problems with TCP...
203 */
204#define	SWAITMAX	90	/* wait at most 90 seconds */
205#define	SWAITINT	5	/* interval between retries */
206
207int	swaitmax = SWAITMAX;
208int	swaitint = SWAITINT;
209
210#ifdef SETPROCTITLE
211#ifdef OLD_SETPROCTITLE
212char	**Argv = NULL;		/* pointer to argument vector */
213char	*LastArgv = NULL;	/* end of argv */
214#endif /* OLD_SETPROCTITLE */
215char	proctitle[LINE_MAX];	/* initial part of title */
216#endif /* SETPROCTITLE */
217
218#define LOGCMD(cmd, file)		logcmd((cmd), (file), NULL, -1)
219#define LOGCMD2(cmd, file1, file2)	logcmd((cmd), (file1), (file2), -1)
220#define LOGBYTES(cmd, file, cnt)	logcmd((cmd), (file), NULL, (cnt))
221
222static	volatile sig_atomic_t recvurg;
223static	int transflag;		/* NB: for debugging only */
224
225#define STARTXFER	flagxfer(1)
226#define ENDXFER		flagxfer(0)
227
228#define START_UNSAFE	maskurg(1)
229#define END_UNSAFE	maskurg(0)
230
231/* It's OK to put an `else' clause after this macro. */
232#define CHECKOOB(action)						\
233	if (recvurg) {							\
234		recvurg = 0;						\
235		if (myoob()) {						\
236			ENDXFER;					\
237			action;						\
238		}							\
239	}
240
241#ifdef VIRTUAL_HOSTING
242static void	 inithosts(void);
243static void	 selecthost(union sockunion *);
244#endif
245static void	 ack(char *);
246static void	 sigurg(int);
247static void	 maskurg(int);
248static void	 flagxfer(int);
249static int	 myoob(void);
250static int	 checkuser(char *, char *, int, char **);
251static FILE	*dataconn(char *, off_t, char *);
252static void	 dolog(struct sockaddr *);
253static void	 end_login(void);
254static FILE	*getdatasock(char *);
255static int	 guniquefd(char *, char **);
256static void	 lostconn(int);
257static void	 sigquit(int);
258static int	 receive_data(FILE *, FILE *);
259static int	 send_data(FILE *, FILE *, size_t, off_t, int);
260static struct passwd *
261		 sgetpwnam(char *);
262static char	*sgetsave(char *);
263static void	 reapchild(int);
264static void	 appendf(char **, char *, ...) __printflike(2, 3);
265static void	 logcmd(char *, char *, char *, off_t);
266static void      logxfer(char *, off_t, time_t);
267static char	*doublequote(char *);
268static int	*socksetup(int, char *, const char *);
269
270int
271main(int argc, char *argv[], char **envp)
272{
273	socklen_t addrlen;
274	int ch, on = 1, tos;
275	char *cp, line[LINE_MAX];
276	FILE *fd;
277	char	*bindname = NULL;
278	const char *bindport = "ftp";
279	int	family = AF_UNSPEC;
280	struct sigaction sa;
281
282	tzset();		/* in case no timezone database in ~ftp */
283	sigemptyset(&sa.sa_mask);
284	sa.sa_flags = SA_RESTART;
285
286#ifdef OLD_SETPROCTITLE
287	/*
288	 *  Save start and extent of argv for setproctitle.
289	 */
290	Argv = argv;
291	while (*envp)
292		envp++;
293	LastArgv = envp[-1] + strlen(envp[-1]);
294#endif /* OLD_SETPROCTITLE */
295
296	/*
297	 * Prevent diagnostic messages from appearing on stderr.
298	 * We run as a daemon or from inetd; in both cases, there's
299	 * more reason in logging to syslog.
300	 */
301	(void) freopen(_PATH_DEVNULL, "w", stderr);
302	opterr = 0;
303
304	/*
305	 * LOG_NDELAY sets up the logging connection immediately,
306	 * necessary for anonymous ftp's that chroot and can't do it later.
307	 */
308	openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
309
310	while ((ch = getopt(argc, argv,
311	                    "46a:AdDEhlmMoOp:P:rRSt:T:u:UvW")) != -1) {
312		switch (ch) {
313		case '4':
314			family = (family == AF_INET6) ? AF_UNSPEC : AF_INET;
315			break;
316
317		case '6':
318			family = (family == AF_INET) ? AF_UNSPEC : AF_INET6;
319			break;
320
321		case 'a':
322			bindname = optarg;
323			break;
324
325		case 'A':
326			anon_only = 1;
327			break;
328
329		case 'd':
330			ftpdebug++;
331			break;
332
333		case 'D':
334			daemon_mode++;
335			break;
336
337		case 'E':
338			noepsv = 1;
339			break;
340
341		case 'h':
342			hostinfo = 0;
343			break;
344
345		case 'l':
346			logging++;	/* > 1 == extra logging */
347			break;
348
349		case 'm':
350			noguestmod = 0;
351			break;
352
353		case 'M':
354			noguestmkd = 1;
355			break;
356
357		case 'o':
358			noretr = 1;
359			break;
360
361		case 'O':
362			noguestretr = 1;
363			break;
364
365		case 'p':
366			pid_file = optarg;
367			break;
368
369		case 'P':
370			bindport = optarg;
371			break;
372
373		case 'r':
374			readonly = 1;
375			break;
376
377		case 'R':
378			paranoid = 0;
379			break;
380
381		case 'S':
382			stats++;
383			break;
384
385		case 't':
386			timeout = atoi(optarg);
387			if (maxtimeout < timeout)
388				maxtimeout = timeout;
389			break;
390
391		case 'T':
392			maxtimeout = atoi(optarg);
393			if (timeout > maxtimeout)
394				timeout = maxtimeout;
395			break;
396
397		case 'u':
398		    {
399			long val = 0;
400
401			val = strtol(optarg, &optarg, 8);
402			if (*optarg != '\0' || val < 0)
403				syslog(LOG_WARNING, "bad value for -u");
404			else
405				defumask = val;
406			break;
407		    }
408		case 'U':
409			restricted_data_ports = 0;
410			break;
411
412		case 'v':
413			ftpdebug++;
414			break;
415
416		case 'W':
417			dowtmp = 0;
418			break;
419
420		default:
421			syslog(LOG_WARNING, "unknown flag -%c ignored", optopt);
422			break;
423		}
424	}
425
426#ifdef VIRTUAL_HOSTING
427	inithosts();
428#endif
429
430	if (daemon_mode) {
431		int *ctl_sock, fd, maxfd = -1, nfds, i;
432		fd_set defreadfds, readfds;
433		pid_t pid;
434		struct pidfh *pfh;
435
436		if ((pfh = pidfile_open(pid_file, 0600, &pid)) == NULL) {
437			if (errno == EEXIST) {
438				syslog(LOG_ERR, "%s already running, pid %d",
439				       getprogname(), (int)pid);
440				exit(1);
441			}
442			syslog(LOG_WARNING, "pidfile_open: %m");
443		}
444
445		/*
446		 * Detach from parent.
447		 */
448		if (daemon(1, 1) < 0) {
449			syslog(LOG_ERR, "failed to become a daemon");
450			exit(1);
451		}
452
453		if (pfh != NULL && pidfile_write(pfh) == -1)
454			syslog(LOG_WARNING, "pidfile_write: %m");
455
456		sa.sa_handler = reapchild;
457		(void)sigaction(SIGCHLD, &sa, NULL);
458
459		/*
460		 * Open a socket, bind it to the FTP port, and start
461		 * listening.
462		 */
463		ctl_sock = socksetup(family, bindname, bindport);
464		if (ctl_sock == NULL)
465			exit(1);
466
467		FD_ZERO(&defreadfds);
468		for (i = 1; i <= *ctl_sock; i++) {
469			FD_SET(ctl_sock[i], &defreadfds);
470			if (listen(ctl_sock[i], 32) < 0) {
471				syslog(LOG_ERR, "control listen: %m");
472				exit(1);
473			}
474			if (maxfd < ctl_sock[i])
475				maxfd = ctl_sock[i];
476		}
477
478		/*
479		 * Loop forever accepting connection requests and forking off
480		 * children to handle them.
481		 */
482		while (1) {
483			FD_COPY(&defreadfds, &readfds);
484			nfds = select(maxfd + 1, &readfds, NULL, NULL, 0);
485			if (nfds <= 0) {
486				if (nfds < 0 && errno != EINTR)
487					syslog(LOG_WARNING, "select: %m");
488				continue;
489			}
490
491			pid = -1;
492                        for (i = 1; i <= *ctl_sock; i++)
493				if (FD_ISSET(ctl_sock[i], &readfds)) {
494					addrlen = sizeof(his_addr);
495					fd = accept(ctl_sock[i],
496					    (struct sockaddr *)&his_addr,
497					    &addrlen);
498					if (fd == -1) {
499						syslog(LOG_WARNING,
500						       "accept: %m");
501						continue;
502					}
503					switch (pid = fork()) {
504					case 0:
505						/* child */
506						(void) dup2(fd, 0);
507						(void) dup2(fd, 1);
508						(void) close(fd);
509						for (i = 1; i <= *ctl_sock; i++)
510							close(ctl_sock[i]);
511						if (pfh != NULL)
512							pidfile_close(pfh);
513						goto gotchild;
514					case -1:
515						syslog(LOG_WARNING, "fork: %m");
516						/* FALLTHROUGH */
517					default:
518						close(fd);
519					}
520				}
521		}
522	} else {
523		addrlen = sizeof(his_addr);
524		if (getpeername(0, (struct sockaddr *)&his_addr, &addrlen) < 0) {
525			syslog(LOG_ERR, "getpeername (%s): %m",argv[0]);
526			exit(1);
527		}
528	}
529
530gotchild:
531	sa.sa_handler = SIG_DFL;
532	(void)sigaction(SIGCHLD, &sa, NULL);
533
534	sa.sa_handler = sigurg;
535	sa.sa_flags = 0;		/* don't restart syscalls for SIGURG */
536	(void)sigaction(SIGURG, &sa, NULL);
537
538	sigfillset(&sa.sa_mask);	/* block all signals in handler */
539	sa.sa_flags = SA_RESTART;
540	sa.sa_handler = sigquit;
541	(void)sigaction(SIGHUP, &sa, NULL);
542	(void)sigaction(SIGINT, &sa, NULL);
543	(void)sigaction(SIGQUIT, &sa, NULL);
544	(void)sigaction(SIGTERM, &sa, NULL);
545
546	sa.sa_handler = lostconn;
547	(void)sigaction(SIGPIPE, &sa, NULL);
548
549	addrlen = sizeof(ctrl_addr);
550	if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) {
551		syslog(LOG_ERR, "getsockname (%s): %m",argv[0]);
552		exit(1);
553	}
554	dataport = ntohs(ctrl_addr.su_port) - 1; /* as per RFC 959 */
555#ifdef VIRTUAL_HOSTING
556	/* select our identity from virtual host table */
557	selecthost(&ctrl_addr);
558#endif
559#ifdef IP_TOS
560	if (ctrl_addr.su_family == AF_INET)
561      {
562	tos = IPTOS_LOWDELAY;
563	if (setsockopt(0, IPPROTO_IP, IP_TOS, &tos, sizeof(int)) < 0)
564		syslog(LOG_WARNING, "control setsockopt (IP_TOS): %m");
565      }
566#endif
567	/*
568	 * Disable Nagle on the control channel so that we don't have to wait
569	 * for peer's ACK before issuing our next reply.
570	 */
571	if (setsockopt(0, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
572		syslog(LOG_WARNING, "control setsockopt (TCP_NODELAY): %m");
573
574	data_source.su_port = htons(ntohs(ctrl_addr.su_port) - 1);
575
576	/* set this here so klogin can use it... */
577	(void)snprintf(ttyline, sizeof(ttyline), "ftp%d", getpid());
578
579	/* Try to handle urgent data inline */
580#ifdef SO_OOBINLINE
581	if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)) < 0)
582		syslog(LOG_WARNING, "control setsockopt (SO_OOBINLINE): %m");
583#endif
584
585#ifdef	F_SETOWN
586	if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1)
587		syslog(LOG_ERR, "fcntl F_SETOWN: %m");
588#endif
589	dolog((struct sockaddr *)&his_addr);
590	/*
591	 * Set up default state
592	 */
593	data = -1;
594	type = TYPE_A;
595	form = FORM_N;
596	stru = STRU_F;
597	mode = MODE_S;
598	tmpline[0] = '\0';
599
600	/* If logins are disabled, print out the message. */
601	if ((fd = fopen(_PATH_NOLOGIN,"r")) != NULL) {
602		while (fgets(line, sizeof(line), fd) != NULL) {
603			if ((cp = strchr(line, '\n')) != NULL)
604				*cp = '\0';
605			lreply(530, "%s", line);
606		}
607		(void) fflush(stdout);
608		(void) fclose(fd);
609		reply(530, "System not available.");
610		exit(0);
611	}
612#ifdef VIRTUAL_HOSTING
613	fd = fopen(thishost->welcome, "r");
614#else
615	fd = fopen(_PATH_FTPWELCOME, "r");
616#endif
617	if (fd != NULL) {
618		while (fgets(line, sizeof(line), fd) != NULL) {
619			if ((cp = strchr(line, '\n')) != NULL)
620				*cp = '\0';
621			lreply(220, "%s", line);
622		}
623		(void) fflush(stdout);
624		(void) fclose(fd);
625		/* reply(220,) must follow */
626	}
627#ifndef VIRTUAL_HOSTING
628	if ((hostname = malloc(MAXHOSTNAMELEN)) == NULL)
629		fatalerror("Ran out of memory.");
630	if (gethostname(hostname, MAXHOSTNAMELEN - 1) < 0)
631		hostname[0] = '\0';
632	hostname[MAXHOSTNAMELEN - 1] = '\0';
633#endif
634	if (hostinfo)
635		reply(220, "%s FTP server (%s) ready.", hostname, version);
636	else
637		reply(220, "FTP server ready.");
638	for (;;)
639		(void) yyparse();
640	/* NOTREACHED */
641}
642
643static void
644lostconn(int signo)
645{
646
647	if (ftpdebug)
648		syslog(LOG_DEBUG, "lost connection");
649	dologout(1);
650}
651
652static void
653sigquit(int signo)
654{
655
656	syslog(LOG_ERR, "got signal %d", signo);
657	dologout(1);
658}
659
660#ifdef VIRTUAL_HOSTING
661/*
662 * read in virtual host tables (if they exist)
663 */
664
665static void
666inithosts(void)
667{
668	int insert;
669	size_t len;
670	FILE *fp;
671	char *cp, *mp, *line;
672	char *hostname;
673	char *vhost, *anonuser, *statfile, *welcome, *loginmsg;
674	struct ftphost *hrp, *lhrp;
675	struct addrinfo hints, *res, *ai;
676
677	/*
678	 * Fill in the default host information
679	 */
680	if ((hostname = malloc(MAXHOSTNAMELEN)) == NULL)
681		fatalerror("Ran out of memory.");
682	if (gethostname(hostname, MAXHOSTNAMELEN - 1) < 0)
683		hostname[0] = '\0';
684	hostname[MAXHOSTNAMELEN - 1] = '\0';
685	if ((hrp = malloc(sizeof(struct ftphost))) == NULL)
686		fatalerror("Ran out of memory.");
687	hrp->hostname = hostname;
688	hrp->hostinfo = NULL;
689
690	memset(&hints, 0, sizeof(hints));
691	hints.ai_flags = AI_CANONNAME;
692	hints.ai_family = AF_UNSPEC;
693	if (getaddrinfo(hrp->hostname, NULL, &hints, &res) == 0)
694		hrp->hostinfo = res;
695	hrp->statfile = _PATH_FTPDSTATFILE;
696	hrp->welcome  = _PATH_FTPWELCOME;
697	hrp->loginmsg = _PATH_FTPLOGINMESG;
698	hrp->anonuser = "ftp";
699	hrp->next = NULL;
700	thishost = firsthost = lhrp = hrp;
701	if ((fp = fopen(_PATH_FTPHOSTS, "r")) != NULL) {
702		int addrsize, gothost;
703		void *addr;
704		struct hostent *hp;
705
706		while ((line = fgetln(fp, &len)) != NULL) {
707			int	i, hp_error;
708
709			/* skip comments */
710			if (line[0] == '#')
711				continue;
712			if (line[len - 1] == '\n') {
713				line[len - 1] = '\0';
714				mp = NULL;
715			} else {
716				if ((mp = malloc(len + 1)) == NULL)
717					fatalerror("Ran out of memory.");
718				memcpy(mp, line, len);
719				mp[len] = '\0';
720				line = mp;
721			}
722			cp = strtok(line, " \t");
723			/* skip empty lines */
724			if (cp == NULL)
725				goto nextline;
726			vhost = cp;
727
728			/* set defaults */
729			anonuser = "ftp";
730			statfile = _PATH_FTPDSTATFILE;
731			welcome  = _PATH_FTPWELCOME;
732			loginmsg = _PATH_FTPLOGINMESG;
733
734			/*
735			 * Preparse the line so we can use its info
736			 * for all the addresses associated with
737			 * the virtual host name.
738			 * Field 0, the virtual host name, is special:
739			 * it's already parsed off and will be strdup'ed
740			 * later, after we know its canonical form.
741			 */
742			for (i = 1; i < 5 && (cp = strtok(NULL, " \t")); i++)
743				if (*cp != '-' && (cp = strdup(cp)))
744					switch (i) {
745					case 1:	/* anon user permissions */
746						anonuser = cp;
747						break;
748					case 2: /* statistics file */
749						statfile = cp;
750						break;
751					case 3: /* welcome message */
752						welcome  = cp;
753						break;
754					case 4: /* login message */
755						loginmsg = cp;
756						break;
757					default: /* programming error */
758						abort();
759						/* NOTREACHED */
760					}
761
762			hints.ai_flags = 0;
763			hints.ai_family = AF_UNSPEC;
764			hints.ai_flags = AI_PASSIVE;
765			if (getaddrinfo(vhost, NULL, &hints, &res) != 0)
766				goto nextline;
767			for (ai = res; ai != NULL && ai->ai_addr != NULL;
768			     ai = ai->ai_next) {
769
770			gothost = 0;
771			for (hrp = firsthost; hrp != NULL; hrp = hrp->next) {
772				struct addrinfo *hi;
773
774				for (hi = hrp->hostinfo; hi != NULL;
775				     hi = hi->ai_next)
776					if (hi->ai_addrlen == ai->ai_addrlen &&
777					    memcmp(hi->ai_addr,
778						   ai->ai_addr,
779						   ai->ai_addr->sa_len) == 0) {
780						gothost++;
781						break;
782					}
783				if (gothost)
784					break;
785			}
786			if (hrp == NULL) {
787				if ((hrp = malloc(sizeof(struct ftphost))) == NULL)
788					goto nextline;
789				hrp->hostname = NULL;
790				insert = 1;
791			} else {
792				if (hrp->hostinfo && hrp->hostinfo != res)
793					freeaddrinfo(hrp->hostinfo);
794				insert = 0; /* host already in the chain */
795			}
796			hrp->hostinfo = res;
797
798			/*
799			 * determine hostname to use.
800			 * force defined name if there is a valid alias
801			 * otherwise fallback to primary hostname
802			 */
803			/* XXX: getaddrinfo() can't do alias check */
804			switch(hrp->hostinfo->ai_family) {
805			case AF_INET:
806				addr = &((struct sockaddr_in *)hrp->hostinfo->ai_addr)->sin_addr;
807				addrsize = sizeof(struct in_addr);
808				break;
809			case AF_INET6:
810				addr = &((struct sockaddr_in6 *)hrp->hostinfo->ai_addr)->sin6_addr;
811				addrsize = sizeof(struct in6_addr);
812				break;
813			default:
814				/* should not reach here */
815				freeaddrinfo(hrp->hostinfo);
816				if (insert)
817					free(hrp); /*not in chain, can free*/
818				else
819					hrp->hostinfo = NULL; /*mark as blank*/
820				goto nextline;
821				/* NOTREACHED */
822			}
823			if ((hp = getipnodebyaddr(addr, addrsize,
824						  hrp->hostinfo->ai_family,
825						  &hp_error)) != NULL) {
826				if (strcmp(vhost, hp->h_name) != 0) {
827					if (hp->h_aliases == NULL)
828						vhost = hp->h_name;
829					else {
830						i = 0;
831						while (hp->h_aliases[i] &&
832						       strcmp(vhost, hp->h_aliases[i]) != 0)
833							++i;
834						if (hp->h_aliases[i] == NULL)
835							vhost = hp->h_name;
836					}
837				}
838			}
839			if (hrp->hostname &&
840			    strcmp(hrp->hostname, vhost) != 0) {
841				free(hrp->hostname);
842				hrp->hostname = NULL;
843			}
844			if (hrp->hostname == NULL &&
845			    (hrp->hostname = strdup(vhost)) == NULL) {
846				freeaddrinfo(hrp->hostinfo);
847				hrp->hostinfo = NULL; /* mark as blank */
848				if (hp)
849					freehostent(hp);
850				goto nextline;
851			}
852			hrp->anonuser = anonuser;
853			hrp->statfile = statfile;
854			hrp->welcome  = welcome;
855			hrp->loginmsg = loginmsg;
856			if (insert) {
857				hrp->next  = NULL;
858				lhrp->next = hrp;
859				lhrp = hrp;
860			}
861			if (hp)
862				freehostent(hp);
863		      }
864nextline:
865			if (mp)
866				free(mp);
867		}
868		(void) fclose(fp);
869	}
870}
871
872static void
873selecthost(union sockunion *su)
874{
875	struct ftphost	*hrp;
876	u_int16_t port;
877#ifdef INET6
878	struct in6_addr *mapped_in6 = NULL;
879#endif
880	struct addrinfo *hi;
881
882#ifdef INET6
883	/*
884	 * XXX IPv4 mapped IPv6 addr consideraton,
885	 * specified in rfc2373.
886	 */
887	if (su->su_family == AF_INET6 &&
888	    IN6_IS_ADDR_V4MAPPED(&su->su_sin6.sin6_addr))
889		mapped_in6 = &su->su_sin6.sin6_addr;
890#endif
891
892	hrp = thishost = firsthost;	/* default */
893	port = su->su_port;
894	su->su_port = 0;
895	while (hrp != NULL) {
896	    for (hi = hrp->hostinfo; hi != NULL; hi = hi->ai_next) {
897		if (memcmp(su, hi->ai_addr, hi->ai_addrlen) == 0) {
898			thishost = hrp;
899			goto found;
900		}
901#ifdef INET6
902		/* XXX IPv4 mapped IPv6 addr consideraton */
903		if (hi->ai_addr->sa_family == AF_INET && mapped_in6 != NULL &&
904		    (memcmp(&mapped_in6->s6_addr[12],
905			    &((struct sockaddr_in *)hi->ai_addr)->sin_addr,
906			    sizeof(struct in_addr)) == 0)) {
907			thishost = hrp;
908			goto found;
909		}
910#endif
911	    }
912	    hrp = hrp->next;
913	}
914found:
915	su->su_port = port;
916	/* setup static variables as appropriate */
917	hostname = thishost->hostname;
918	ftpuser = thishost->anonuser;
919}
920#endif
921
922/*
923 * Helper function for sgetpwnam().
924 */
925static char *
926sgetsave(char *s)
927{
928	char *new = malloc(strlen(s) + 1);
929
930	if (new == NULL) {
931		reply(421, "Ran out of memory.");
932		dologout(1);
933		/* NOTREACHED */
934	}
935	(void) strcpy(new, s);
936	return (new);
937}
938
939/*
940 * Save the result of a getpwnam.  Used for USER command, since
941 * the data returned must not be clobbered by any other command
942 * (e.g., globbing).
943 * NB: The data returned by sgetpwnam() will remain valid until
944 * the next call to this function.  Its difference from getpwnam()
945 * is that sgetpwnam() is known to be called from ftpd code only.
946 */
947static struct passwd *
948sgetpwnam(char *name)
949{
950	static struct passwd save;
951	struct passwd *p;
952
953	if ((p = getpwnam(name)) == NULL)
954		return (p);
955	if (save.pw_name) {
956		free(save.pw_name);
957		free(save.pw_passwd);
958		free(save.pw_gecos);
959		free(save.pw_dir);
960		free(save.pw_shell);
961	}
962	save = *p;
963	save.pw_name = sgetsave(p->pw_name);
964	save.pw_passwd = sgetsave(p->pw_passwd);
965	save.pw_gecos = sgetsave(p->pw_gecos);
966	save.pw_dir = sgetsave(p->pw_dir);
967	save.pw_shell = sgetsave(p->pw_shell);
968	return (&save);
969}
970
971static int login_attempts;	/* number of failed login attempts */
972static int askpasswd;		/* had user command, ask for passwd */
973static char curname[MAXLOGNAME];	/* current USER name */
974
975/*
976 * USER command.
977 * Sets global passwd pointer pw if named account exists and is acceptable;
978 * sets askpasswd if a PASS command is expected.  If logged in previously,
979 * need to reset state.  If name is "ftp" or "anonymous", the name is not in
980 * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return.
981 * If account doesn't exist, ask for passwd anyway.  Otherwise, check user
982 * requesting login privileges.  Disallow anyone who does not have a standard
983 * shell as returned by getusershell().  Disallow anyone mentioned in the file
984 * _PATH_FTPUSERS to allow people such as root and uucp to be avoided.
985 */
986void
987user(char *name)
988{
989	char *cp, *shell;
990
991	if (logged_in) {
992		if (guest) {
993			reply(530, "Can't change user from guest login.");
994			return;
995		} else if (dochroot) {
996			reply(530, "Can't change user from chroot user.");
997			return;
998		}
999		end_login();
1000	}
1001
1002	guest = 0;
1003#ifdef VIRTUAL_HOSTING
1004	pw = sgetpwnam(thishost->anonuser);
1005#else
1006	pw = sgetpwnam("ftp");
1007#endif
1008	if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) {
1009		if (checkuser(_PATH_FTPUSERS, "ftp", 0, NULL) ||
1010		    checkuser(_PATH_FTPUSERS, "anonymous", 0, NULL))
1011			reply(530, "User %s access denied.", name);
1012		else if (pw != NULL) {
1013			guest = 1;
1014			askpasswd = 1;
1015			reply(331,
1016			"Guest login ok, send your email address as password.");
1017		} else
1018			reply(530, "User %s unknown.", name);
1019		if (!askpasswd && logging)
1020			syslog(LOG_NOTICE,
1021			    "ANONYMOUS FTP LOGIN REFUSED FROM %s", remotehost);
1022		return;
1023	}
1024	if (anon_only != 0) {
1025		reply(530, "Sorry, only anonymous ftp allowed.");
1026		return;
1027	}
1028
1029	if ((pw = sgetpwnam(name))) {
1030		if ((shell = pw->pw_shell) == NULL || *shell == 0)
1031			shell = _PATH_BSHELL;
1032		setusershell();
1033		while ((cp = getusershell()) != NULL)
1034			if (strcmp(cp, shell) == 0)
1035				break;
1036		endusershell();
1037
1038		if (cp == NULL || checkuser(_PATH_FTPUSERS, name, 1, NULL)) {
1039			reply(530, "User %s access denied.", name);
1040			if (logging)
1041				syslog(LOG_NOTICE,
1042				    "FTP LOGIN REFUSED FROM %s, %s",
1043				    remotehost, name);
1044			pw = NULL;
1045			return;
1046		}
1047	}
1048	if (logging)
1049		strncpy(curname, name, sizeof(curname)-1);
1050
1051	pwok = 0;
1052#ifdef USE_PAM
1053	/* XXX Kluge! The conversation mechanism needs to be fixed. */
1054#endif
1055	if (opiechallenge(&opiedata, name, opieprompt) == 0) {
1056		pwok = (pw != NULL) &&
1057		       opieaccessfile(remotehost) &&
1058		       opiealways(pw->pw_dir);
1059		reply(331, "Response to %s %s for %s.",
1060		      opieprompt, pwok ? "requested" : "required", name);
1061	} else {
1062		pwok = 1;
1063		reply(331, "Password required for %s.", name);
1064	}
1065	askpasswd = 1;
1066	/*
1067	 * Delay before reading passwd after first failed
1068	 * attempt to slow down passwd-guessing programs.
1069	 */
1070	if (login_attempts)
1071		sleep(login_attempts);
1072}
1073
1074/*
1075 * Check if a user is in the file "fname",
1076 * return a pointer to a malloc'd string with the rest
1077 * of the matching line in "residue" if not NULL.
1078 */
1079static int
1080checkuser(char *fname, char *name, int pwset, char **residue)
1081{
1082	FILE *fd;
1083	int found = 0;
1084	size_t len;
1085	char *line, *mp, *p;
1086
1087	if ((fd = fopen(fname, "r")) != NULL) {
1088		while (!found && (line = fgetln(fd, &len)) != NULL) {
1089			/* skip comments */
1090			if (line[0] == '#')
1091				continue;
1092			if (line[len - 1] == '\n') {
1093				line[len - 1] = '\0';
1094				mp = NULL;
1095			} else {
1096				if ((mp = malloc(len + 1)) == NULL)
1097					fatalerror("Ran out of memory.");
1098				memcpy(mp, line, len);
1099				mp[len] = '\0';
1100				line = mp;
1101			}
1102			/* avoid possible leading and trailing whitespace */
1103			p = strtok(line, " \t");
1104			/* skip empty lines */
1105			if (p == NULL)
1106				goto nextline;
1107			/*
1108			 * if first chr is '@', check group membership
1109			 */
1110			if (p[0] == '@') {
1111				int i = 0;
1112				struct group *grp;
1113
1114				if (p[1] == '\0') /* single @ matches anyone */
1115					found = 1;
1116				else {
1117					if ((grp = getgrnam(p+1)) == NULL)
1118						goto nextline;
1119					/*
1120					 * Check user's default group
1121					 */
1122					if (pwset && grp->gr_gid == pw->pw_gid)
1123						found = 1;
1124					/*
1125					 * Check supplementary groups
1126					 */
1127					while (!found && grp->gr_mem[i])
1128						found = strcmp(name,
1129							grp->gr_mem[i++])
1130							== 0;
1131				}
1132			}
1133			/*
1134			 * Otherwise, just check for username match
1135			 */
1136			else
1137				found = strcmp(p, name) == 0;
1138			/*
1139			 * Save the rest of line to "residue" if matched
1140			 */
1141			if (found && residue) {
1142				if ((p = strtok(NULL, "")) != NULL)
1143					p += strspn(p, " \t");
1144				if (p && *p) {
1145				 	if ((*residue = strdup(p)) == NULL)
1146						fatalerror("Ran out of memory.");
1147				} else
1148					*residue = NULL;
1149			}
1150nextline:
1151			if (mp)
1152				free(mp);
1153		}
1154		(void) fclose(fd);
1155	}
1156	return (found);
1157}
1158
1159/*
1160 * Terminate login as previous user, if any, resetting state;
1161 * used when USER command is given or login fails.
1162 */
1163static void
1164end_login(void)
1165{
1166#ifdef USE_PAM
1167	int e;
1168#endif
1169
1170	(void) seteuid(0);
1171	if (logged_in && dowtmp)
1172		ftpd_logwtmp(ttyline, "", NULL);
1173	pw = NULL;
1174#ifdef	LOGIN_CAP
1175	setusercontext(NULL, getpwuid(0), 0,
1176		       LOGIN_SETPRIORITY|LOGIN_SETRESOURCES|LOGIN_SETUMASK|
1177		       LOGIN_SETMAC);
1178#endif
1179#ifdef USE_PAM
1180	if (pamh) {
1181		if ((e = pam_setcred(pamh, PAM_DELETE_CRED)) != PAM_SUCCESS)
1182			syslog(LOG_ERR, "pam_setcred: %s", pam_strerror(pamh, e));
1183		if ((e = pam_close_session(pamh,0)) != PAM_SUCCESS)
1184			syslog(LOG_ERR, "pam_close_session: %s", pam_strerror(pamh, e));
1185		if ((e = pam_end(pamh, e)) != PAM_SUCCESS)
1186			syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
1187		pamh = NULL;
1188	}
1189#endif
1190	logged_in = 0;
1191	guest = 0;
1192	dochroot = 0;
1193}
1194
1195#ifdef USE_PAM
1196
1197/*
1198 * the following code is stolen from imap-uw PAM authentication module and
1199 * login.c
1200 */
1201#define COPY_STRING(s) (s ? strdup(s) : NULL)
1202
1203struct cred_t {
1204	const char *uname;		/* user name */
1205	const char *pass;		/* password */
1206};
1207typedef struct cred_t cred_t;
1208
1209static int
1210auth_conv(int num_msg, const struct pam_message **msg,
1211	  struct pam_response **resp, void *appdata)
1212{
1213	int i;
1214	cred_t *cred = (cred_t *) appdata;
1215	struct pam_response *reply;
1216
1217	reply = calloc(num_msg, sizeof *reply);
1218	if (reply == NULL)
1219		return PAM_BUF_ERR;
1220
1221	for (i = 0; i < num_msg; i++) {
1222		switch (msg[i]->msg_style) {
1223		case PAM_PROMPT_ECHO_ON:	/* assume want user name */
1224			reply[i].resp_retcode = PAM_SUCCESS;
1225			reply[i].resp = COPY_STRING(cred->uname);
1226			/* PAM frees resp. */
1227			break;
1228		case PAM_PROMPT_ECHO_OFF:	/* assume want password */
1229			reply[i].resp_retcode = PAM_SUCCESS;
1230			reply[i].resp = COPY_STRING(cred->pass);
1231			/* PAM frees resp. */
1232			break;
1233		case PAM_TEXT_INFO:
1234		case PAM_ERROR_MSG:
1235			reply[i].resp_retcode = PAM_SUCCESS;
1236			reply[i].resp = NULL;
1237			break;
1238		default:			/* unknown message style */
1239			free(reply);
1240			return PAM_CONV_ERR;
1241		}
1242	}
1243
1244	*resp = reply;
1245	return PAM_SUCCESS;
1246}
1247
1248/*
1249 * Attempt to authenticate the user using PAM.  Returns 0 if the user is
1250 * authenticated, or 1 if not authenticated.  If some sort of PAM system
1251 * error occurs (e.g., the "/etc/pam.conf" file is missing) then this
1252 * function returns -1.  This can be used as an indication that we should
1253 * fall back to a different authentication mechanism.
1254 */
1255static int
1256auth_pam(struct passwd **ppw, const char *pass)
1257{
1258	const char *tmpl_user;
1259	const void *item;
1260	int rval;
1261	int e;
1262	cred_t auth_cred = { (*ppw)->pw_name, pass };
1263	struct pam_conv conv = { &auth_conv, &auth_cred };
1264
1265	e = pam_start("ftpd", (*ppw)->pw_name, &conv, &pamh);
1266	if (e != PAM_SUCCESS) {
1267		/*
1268		 * In OpenPAM, it's OK to pass NULL to pam_strerror()
1269		 * if context creation has failed in the first place.
1270		 */
1271		syslog(LOG_ERR, "pam_start: %s", pam_strerror(NULL, e));
1272		return -1;
1273	}
1274
1275	e = pam_set_item(pamh, PAM_RHOST, remotehost);
1276	if (e != PAM_SUCCESS) {
1277		syslog(LOG_ERR, "pam_set_item(PAM_RHOST): %s",
1278			pam_strerror(pamh, e));
1279		if ((e = pam_end(pamh, e)) != PAM_SUCCESS) {
1280			syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
1281		}
1282		pamh = NULL;
1283		return -1;
1284	}
1285
1286	e = pam_authenticate(pamh, 0);
1287	switch (e) {
1288	case PAM_SUCCESS:
1289		/*
1290		 * With PAM we support the concept of a "template"
1291		 * user.  The user enters a login name which is
1292		 * authenticated by PAM, usually via a remote service
1293		 * such as RADIUS or TACACS+.  If authentication
1294		 * succeeds, a different but related "template" name
1295		 * is used for setting the credentials, shell, and
1296		 * home directory.  The name the user enters need only
1297		 * exist on the remote authentication server, but the
1298		 * template name must be present in the local password
1299		 * database.
1300		 *
1301		 * This is supported by two various mechanisms in the
1302		 * individual modules.  However, from the application's
1303		 * point of view, the template user is always passed
1304		 * back as a changed value of the PAM_USER item.
1305		 */
1306		if ((e = pam_get_item(pamh, PAM_USER, &item)) ==
1307		    PAM_SUCCESS) {
1308			tmpl_user = (const char *) item;
1309			if (strcmp((*ppw)->pw_name, tmpl_user) != 0)
1310				*ppw = getpwnam(tmpl_user);
1311		} else
1312			syslog(LOG_ERR, "Couldn't get PAM_USER: %s",
1313			    pam_strerror(pamh, e));
1314		rval = 0;
1315		break;
1316
1317	case PAM_AUTH_ERR:
1318	case PAM_USER_UNKNOWN:
1319	case PAM_MAXTRIES:
1320		rval = 1;
1321		break;
1322
1323	default:
1324		syslog(LOG_ERR, "pam_authenticate: %s", pam_strerror(pamh, e));
1325		rval = -1;
1326		break;
1327	}
1328
1329	if (rval == 0) {
1330		e = pam_acct_mgmt(pamh, 0);
1331		if (e != PAM_SUCCESS) {
1332			syslog(LOG_ERR, "pam_acct_mgmt: %s",
1333						pam_strerror(pamh, e));
1334			rval = 1;
1335		}
1336	}
1337
1338	if (rval != 0) {
1339		if ((e = pam_end(pamh, e)) != PAM_SUCCESS) {
1340			syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
1341		}
1342		pamh = NULL;
1343	}
1344	return rval;
1345}
1346
1347#endif /* USE_PAM */
1348
1349void
1350pass(char *passwd)
1351{
1352	int rval;
1353	FILE *fd;
1354#ifdef	LOGIN_CAP
1355	login_cap_t *lc = NULL;
1356#endif
1357#ifdef USE_PAM
1358	int e;
1359#endif
1360	char *residue = NULL;
1361	char *xpasswd;
1362
1363	if (logged_in || askpasswd == 0) {
1364		reply(503, "Login with USER first.");
1365		return;
1366	}
1367	askpasswd = 0;
1368	if (!guest) {		/* "ftp" is only account allowed no password */
1369		if (pw == NULL) {
1370			rval = 1;	/* failure below */
1371			goto skip;
1372		}
1373#ifdef USE_PAM
1374		rval = auth_pam(&pw, passwd);
1375		if (rval >= 0) {
1376			opieunlock();
1377			goto skip;
1378		}
1379#endif
1380		if (opieverify(&opiedata, passwd) == 0)
1381			xpasswd = pw->pw_passwd;
1382		else if (pwok) {
1383			xpasswd = crypt(passwd, pw->pw_passwd);
1384			if (passwd[0] == '\0' && pw->pw_passwd[0] != '\0')
1385				xpasswd = ":";
1386		} else {
1387			rval = 1;
1388			goto skip;
1389		}
1390		rval = strcmp(pw->pw_passwd, xpasswd);
1391		if (pw->pw_expire && time(NULL) >= pw->pw_expire)
1392			rval = 1;	/* failure */
1393skip:
1394		/*
1395		 * If rval == 1, the user failed the authentication check
1396		 * above.  If rval == 0, either PAM or local authentication
1397		 * succeeded.
1398		 */
1399		if (rval) {
1400			reply(530, "Login incorrect.");
1401			if (logging) {
1402				syslog(LOG_NOTICE,
1403				    "FTP LOGIN FAILED FROM %s",
1404				    remotehost);
1405				syslog(LOG_AUTHPRIV | LOG_NOTICE,
1406				    "FTP LOGIN FAILED FROM %s, %s",
1407				    remotehost, curname);
1408			}
1409			pw = NULL;
1410			if (login_attempts++ >= 5) {
1411				syslog(LOG_NOTICE,
1412				    "repeated login failures from %s",
1413				    remotehost);
1414				exit(0);
1415			}
1416			return;
1417		}
1418	}
1419	login_attempts = 0;		/* this time successful */
1420	if (setegid(pw->pw_gid) < 0) {
1421		reply(550, "Can't set gid.");
1422		return;
1423	}
1424	/* May be overridden by login.conf */
1425	(void) umask(defumask);
1426#ifdef	LOGIN_CAP
1427	if ((lc = login_getpwclass(pw)) != NULL) {
1428		char	remote_ip[NI_MAXHOST];
1429
1430		if (getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len,
1431			remote_ip, sizeof(remote_ip) - 1, NULL, 0,
1432			NI_NUMERICHOST))
1433				*remote_ip = 0;
1434		remote_ip[sizeof(remote_ip) - 1] = 0;
1435		if (!auth_hostok(lc, remotehost, remote_ip)) {
1436			syslog(LOG_INFO|LOG_AUTH,
1437			    "FTP LOGIN FAILED (HOST) as %s: permission denied.",
1438			    pw->pw_name);
1439			reply(530, "Permission denied.");
1440			pw = NULL;
1441			return;
1442		}
1443		if (!auth_timeok(lc, time(NULL))) {
1444			reply(530, "Login not available right now.");
1445			pw = NULL;
1446			return;
1447		}
1448	}
1449	setusercontext(lc, pw, 0,
1450		LOGIN_SETLOGIN|LOGIN_SETGROUP|LOGIN_SETPRIORITY|
1451		LOGIN_SETRESOURCES|LOGIN_SETUMASK|LOGIN_SETMAC);
1452#else
1453	setlogin(pw->pw_name);
1454	(void) initgroups(pw->pw_name, pw->pw_gid);
1455#endif
1456
1457#ifdef USE_PAM
1458	if (pamh) {
1459		if ((e = pam_open_session(pamh, 0)) != PAM_SUCCESS) {
1460			syslog(LOG_ERR, "pam_open_session: %s", pam_strerror(pamh, e));
1461		} else if ((e = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS) {
1462			syslog(LOG_ERR, "pam_setcred: %s", pam_strerror(pamh, e));
1463		}
1464	}
1465#endif
1466
1467	/* open wtmp before chroot */
1468	if (dowtmp)
1469		ftpd_logwtmp(ttyline, pw->pw_name,
1470		    (struct sockaddr *)&his_addr);
1471	logged_in = 1;
1472
1473	if (guest && stats && statfd < 0)
1474#ifdef VIRTUAL_HOSTING
1475		statfd = open(thishost->statfile, O_WRONLY|O_APPEND);
1476#else
1477		statfd = open(_PATH_FTPDSTATFILE, O_WRONLY|O_APPEND);
1478#endif
1479		if (statfd < 0)
1480			stats = 0;
1481
1482	dochroot =
1483		checkuser(_PATH_FTPCHROOT, pw->pw_name, 1, &residue)
1484#ifdef	LOGIN_CAP	/* Allow login.conf configuration as well */
1485		|| login_getcapbool(lc, "ftp-chroot", 0)
1486#endif
1487	;
1488	chrootdir = NULL;
1489	/*
1490	 * For a chrooted local user,
1491	 * a) see whether ftpchroot(5) specifies a chroot directory,
1492	 * b) extract the directory pathname from the line,
1493	 * c) expand it to the absolute pathname if necessary.
1494	 */
1495	if (dochroot && residue &&
1496	    (chrootdir = strtok(residue, " \t")) != NULL) {
1497		if (chrootdir[0] != '/')
1498			asprintf(&chrootdir, "%s/%s", pw->pw_dir, chrootdir);
1499		else
1500			chrootdir = strdup(chrootdir); /* make it permanent */
1501		if (chrootdir == NULL)
1502			fatalerror("Ran out of memory.");
1503	}
1504	if (guest || dochroot) {
1505		/*
1506		 * If no chroot directory set yet, use the login directory.
1507		 * Copy it so it can be modified while pw->pw_dir stays intact.
1508		 */
1509		if (chrootdir == NULL &&
1510		    (chrootdir = strdup(pw->pw_dir)) == NULL)
1511			fatalerror("Ran out of memory.");
1512		/*
1513		 * Check for the "/chroot/./home" syntax,
1514		 * separate the chroot and home directory pathnames.
1515		 */
1516		if ((homedir = strstr(chrootdir, "/./")) != NULL) {
1517			*(homedir++) = '\0';	/* wipe '/' */
1518			homedir++;		/* skip '.' */
1519		} else {
1520			/*
1521			 * We MUST do a chdir() after the chroot. Otherwise
1522			 * the old current directory will be accessible as "."
1523			 * outside the new root!
1524			 */
1525			homedir = "/";
1526		}
1527		/*
1528		 * Finally, do chroot()
1529		 */
1530		if (chroot(chrootdir) < 0) {
1531			reply(550, "Can't change root.");
1532			goto bad;
1533		}
1534	} else	/* real user w/o chroot */
1535		homedir = pw->pw_dir;
1536	/*
1537	 * Set euid *before* doing chdir() so
1538	 * a) the user won't be carried to a directory that he couldn't reach
1539	 *    on his own due to no permission to upper path components,
1540	 * b) NFS mounted homedirs w/restrictive permissions will be accessible
1541	 *    (uid 0 has no root power over NFS if not mapped explicitly.)
1542	 */
1543	if (seteuid(pw->pw_uid) < 0) {
1544		reply(550, "Can't set uid.");
1545		goto bad;
1546	}
1547	if (chdir(homedir) < 0) {
1548		if (guest || dochroot) {
1549			reply(550, "Can't change to base directory.");
1550			goto bad;
1551		} else {
1552			if (chdir("/") < 0) {
1553				reply(550, "Root is inaccessible.");
1554				goto bad;
1555			}
1556			lreply(230, "No directory! Logging in with home=/.");
1557		}
1558	}
1559
1560	/*
1561	 * Display a login message, if it exists.
1562	 * N.B. reply(230,) must follow the message.
1563	 */
1564#ifdef VIRTUAL_HOSTING
1565	fd = fopen(thishost->loginmsg, "r");
1566#else
1567	fd = fopen(_PATH_FTPLOGINMESG, "r");
1568#endif
1569	if (fd != NULL) {
1570		char *cp, line[LINE_MAX];
1571
1572		while (fgets(line, sizeof(line), fd) != NULL) {
1573			if ((cp = strchr(line, '\n')) != NULL)
1574				*cp = '\0';
1575			lreply(230, "%s", line);
1576		}
1577		(void) fflush(stdout);
1578		(void) fclose(fd);
1579	}
1580	if (guest) {
1581		if (ident != NULL)
1582			free(ident);
1583		ident = strdup(passwd);
1584		if (ident == NULL)
1585			fatalerror("Ran out of memory.");
1586
1587		reply(230, "Guest login ok, access restrictions apply.");
1588#ifdef SETPROCTITLE
1589#ifdef VIRTUAL_HOSTING
1590		if (thishost != firsthost)
1591			snprintf(proctitle, sizeof(proctitle),
1592				 "%s: anonymous(%s)/%s", remotehost, hostname,
1593				 passwd);
1594		else
1595#endif
1596			snprintf(proctitle, sizeof(proctitle),
1597				 "%s: anonymous/%s", remotehost, passwd);
1598		setproctitle("%s", proctitle);
1599#endif /* SETPROCTITLE */
1600		if (logging)
1601			syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s",
1602			    remotehost, passwd);
1603	} else {
1604		if (dochroot)
1605			reply(230, "User %s logged in, "
1606				   "access restrictions apply.", pw->pw_name);
1607		else
1608			reply(230, "User %s logged in.", pw->pw_name);
1609
1610#ifdef SETPROCTITLE
1611		snprintf(proctitle, sizeof(proctitle),
1612			 "%s: user/%s", remotehost, pw->pw_name);
1613		setproctitle("%s", proctitle);
1614#endif /* SETPROCTITLE */
1615		if (logging)
1616			syslog(LOG_INFO, "FTP LOGIN FROM %s as %s",
1617			    remotehost, pw->pw_name);
1618	}
1619	if (logging && (guest || dochroot))
1620		syslog(LOG_INFO, "session root changed to %s", chrootdir);
1621#ifdef	LOGIN_CAP
1622	login_close(lc);
1623#endif
1624	if (residue)
1625		free(residue);
1626	return;
1627bad:
1628	/* Forget all about it... */
1629#ifdef	LOGIN_CAP
1630	login_close(lc);
1631#endif
1632	if (residue)
1633		free(residue);
1634	end_login();
1635}
1636
1637void
1638retrieve(char *cmd, char *name)
1639{
1640	FILE *fin, *dout;
1641	struct stat st;
1642	int (*closefunc)(FILE *);
1643	time_t start;
1644
1645	if (cmd == 0) {
1646		fin = fopen(name, "r"), closefunc = fclose;
1647		st.st_size = 0;
1648	} else {
1649		char line[BUFSIZ];
1650
1651		(void) snprintf(line, sizeof(line), cmd, name), name = line;
1652		fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose;
1653		st.st_size = -1;
1654		st.st_blksize = BUFSIZ;
1655	}
1656	if (fin == NULL) {
1657		if (errno != 0) {
1658			perror_reply(550, name);
1659			if (cmd == 0) {
1660				LOGCMD("get", name);
1661			}
1662		}
1663		return;
1664	}
1665	byte_count = -1;
1666	if (cmd == 0) {
1667		if (fstat(fileno(fin), &st) < 0) {
1668			perror_reply(550, name);
1669			goto done;
1670		}
1671		if (!S_ISREG(st.st_mode)) {
1672			/*
1673			 * Never sending a raw directory is a workaround
1674			 * for buggy clients that will attempt to RETR
1675			 * a directory before listing it, e.g., Mozilla.
1676			 * Preventing a guest from getting irregular files
1677			 * is a simple security measure.
1678			 */
1679			if (S_ISDIR(st.st_mode) || guest) {
1680				reply(550, "%s: not a plain file.", name);
1681				goto done;
1682			}
1683			st.st_size = -1;
1684			/* st.st_blksize is set for all descriptor types */
1685		}
1686	}
1687	if (restart_point) {
1688		if (type == TYPE_A) {
1689			off_t i, n;
1690			int c;
1691
1692			n = restart_point;
1693			i = 0;
1694			while (i++ < n) {
1695				if ((c=getc(fin)) == EOF) {
1696					perror_reply(550, name);
1697					goto done;
1698				}
1699				if (c == '\n')
1700					i++;
1701			}
1702		} else if (lseek(fileno(fin), restart_point, L_SET) < 0) {
1703			perror_reply(550, name);
1704			goto done;
1705		}
1706	}
1707	dout = dataconn(name, st.st_size, "w");
1708	if (dout == NULL)
1709		goto done;
1710	time(&start);
1711	send_data(fin, dout, st.st_blksize, st.st_size,
1712		  restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode));
1713	if (cmd == 0 && guest && stats && byte_count > 0)
1714		logxfer(name, byte_count, start);
1715	(void) fclose(dout);
1716	data = -1;
1717	pdata = -1;
1718done:
1719	if (cmd == 0)
1720		LOGBYTES("get", name, byte_count);
1721	(*closefunc)(fin);
1722}
1723
1724void
1725store(char *name, char *mode, int unique)
1726{
1727	int fd;
1728	FILE *fout, *din;
1729	int (*closefunc)(FILE *);
1730
1731	if (*mode == 'a') {		/* APPE */
1732		if (unique) {
1733			/* Programming error */
1734			syslog(LOG_ERR, "Internal: unique flag to APPE");
1735			unique = 0;
1736		}
1737		if (guest && noguestmod) {
1738			reply(550, "Appending to existing file denied.");
1739			goto err;
1740		}
1741		restart_point = 0;	/* not affected by preceding REST */
1742	}
1743	if (unique)			/* STOU overrides REST */
1744		restart_point = 0;
1745	if (guest && noguestmod) {
1746		if (restart_point) {	/* guest STOR w/REST */
1747			reply(550, "Modifying existing file denied.");
1748			goto err;
1749		} else			/* treat guest STOR as STOU */
1750			unique = 1;
1751	}
1752
1753	if (restart_point)
1754		mode = "r+";	/* so ASCII manual seek can work */
1755	if (unique) {
1756		if ((fd = guniquefd(name, &name)) < 0)
1757			goto err;
1758		fout = fdopen(fd, mode);
1759	} else
1760		fout = fopen(name, mode);
1761	closefunc = fclose;
1762	if (fout == NULL) {
1763		perror_reply(553, name);
1764		goto err;
1765	}
1766	byte_count = -1;
1767	if (restart_point) {
1768		if (type == TYPE_A) {
1769			off_t i, n;
1770			int c;
1771
1772			n = restart_point;
1773			i = 0;
1774			while (i++ < n) {
1775				if ((c=getc(fout)) == EOF) {
1776					perror_reply(550, name);
1777					goto done;
1778				}
1779				if (c == '\n')
1780					i++;
1781			}
1782			/*
1783			 * We must do this seek to "current" position
1784			 * because we are changing from reading to
1785			 * writing.
1786			 */
1787			if (fseeko(fout, 0, SEEK_CUR) < 0) {
1788				perror_reply(550, name);
1789				goto done;
1790			}
1791		} else if (lseek(fileno(fout), restart_point, L_SET) < 0) {
1792			perror_reply(550, name);
1793			goto done;
1794		}
1795	}
1796	din = dataconn(name, -1, "r");
1797	if (din == NULL)
1798		goto done;
1799	if (receive_data(din, fout) == 0) {
1800		if (unique)
1801			reply(226, "Transfer complete (unique file name:%s).",
1802			    name);
1803		else
1804			reply(226, "Transfer complete.");
1805	}
1806	(void) fclose(din);
1807	data = -1;
1808	pdata = -1;
1809done:
1810	LOGBYTES(*mode == 'a' ? "append" : "put", name, byte_count);
1811	(*closefunc)(fout);
1812	return;
1813err:
1814	LOGCMD(*mode == 'a' ? "append" : "put" , name);
1815	return;
1816}
1817
1818static FILE *
1819getdatasock(char *mode)
1820{
1821	int on = 1, s, t, tries;
1822
1823	if (data >= 0)
1824		return (fdopen(data, mode));
1825
1826	s = socket(data_dest.su_family, SOCK_STREAM, 0);
1827	if (s < 0)
1828		goto bad;
1829	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
1830		syslog(LOG_WARNING, "data setsockopt (SO_REUSEADDR): %m");
1831	/* anchor socket to avoid multi-homing problems */
1832	data_source = ctrl_addr;
1833	data_source.su_port = htons(dataport);
1834	(void) seteuid(0);
1835	for (tries = 1; ; tries++) {
1836		/*
1837		 * We should loop here since it's possible that
1838		 * another ftpd instance has passed this point and is
1839		 * trying to open a data connection in active mode now.
1840		 * Until the other connection is opened, we'll be getting
1841		 * EADDRINUSE because no SOCK_STREAM sockets in the system
1842		 * can share both local and remote addresses, localIP:20
1843		 * and *:* in this case.
1844		 */
1845		if (bind(s, (struct sockaddr *)&data_source,
1846		    data_source.su_len) >= 0)
1847			break;
1848		if (errno != EADDRINUSE || tries > 10)
1849			goto bad;
1850		sleep(tries);
1851	}
1852	(void) seteuid(pw->pw_uid);
1853#ifdef IP_TOS
1854	if (data_source.su_family == AF_INET)
1855      {
1856	on = IPTOS_THROUGHPUT;
1857	if (setsockopt(s, IPPROTO_IP, IP_TOS, &on, sizeof(int)) < 0)
1858		syslog(LOG_WARNING, "data setsockopt (IP_TOS): %m");
1859      }
1860#endif
1861#ifdef TCP_NOPUSH
1862	/*
1863	 * Turn off push flag to keep sender TCP from sending short packets
1864	 * at the boundaries of each write().  Should probably do a SO_SNDBUF
1865	 * to set the send buffer size as well, but that may not be desirable
1866	 * in heavy-load situations.
1867	 */
1868	on = 1;
1869	if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, &on, sizeof on) < 0)
1870		syslog(LOG_WARNING, "data setsockopt (TCP_NOPUSH): %m");
1871#endif
1872#ifdef SO_SNDBUF
1873	on = 65536;
1874	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &on, sizeof on) < 0)
1875		syslog(LOG_WARNING, "data setsockopt (SO_SNDBUF): %m");
1876#endif
1877
1878	return (fdopen(s, mode));
1879bad:
1880	/* Return the real value of errno (close may change it) */
1881	t = errno;
1882	(void) seteuid(pw->pw_uid);
1883	(void) close(s);
1884	errno = t;
1885	return (NULL);
1886}
1887
1888static FILE *
1889dataconn(char *name, off_t size, char *mode)
1890{
1891	char sizebuf[32];
1892	FILE *file;
1893	int retry = 0, tos, conerrno;
1894
1895	file_size = size;
1896	byte_count = 0;
1897	if (size != -1)
1898		(void) snprintf(sizebuf, sizeof(sizebuf),
1899				" (%jd bytes)", (intmax_t)size);
1900	else
1901		*sizebuf = '\0';
1902	if (pdata >= 0) {
1903		union sockunion from;
1904		socklen_t fromlen = ctrl_addr.su_len;
1905		int flags, s;
1906		struct timeval timeout;
1907		fd_set set;
1908
1909		FD_ZERO(&set);
1910		FD_SET(pdata, &set);
1911
1912		timeout.tv_usec = 0;
1913		timeout.tv_sec = 120;
1914
1915		/*
1916		 * Granted a socket is in the blocking I/O mode,
1917		 * accept() will block after a successful select()
1918		 * if the selected connection dies in between.
1919		 * Therefore set the non-blocking I/O flag here.
1920		 */
1921		if ((flags = fcntl(pdata, F_GETFL, 0)) == -1 ||
1922		    fcntl(pdata, F_SETFL, flags | O_NONBLOCK) == -1)
1923			goto pdata_err;
1924		if (select(pdata+1, &set, NULL, NULL, &timeout) <= 0 ||
1925		    (s = accept(pdata, (struct sockaddr *) &from, &fromlen)) < 0)
1926			goto pdata_err;
1927		(void) close(pdata);
1928		pdata = s;
1929		/*
1930		 * Unset the inherited non-blocking I/O flag
1931		 * on the child socket so stdio can work on it.
1932		 */
1933		if ((flags = fcntl(pdata, F_GETFL, 0)) == -1 ||
1934		    fcntl(pdata, F_SETFL, flags & ~O_NONBLOCK) == -1)
1935			goto pdata_err;
1936#ifdef IP_TOS
1937		if (from.su_family == AF_INET)
1938	      {
1939		tos = IPTOS_THROUGHPUT;
1940		if (setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(int)) < 0)
1941			syslog(LOG_WARNING, "pdata setsockopt (IP_TOS): %m");
1942	      }
1943#endif
1944		reply(150, "Opening %s mode data connection for '%s'%s.",
1945		     type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1946		return (fdopen(pdata, mode));
1947pdata_err:
1948		reply(425, "Can't open data connection.");
1949		(void) close(pdata);
1950		pdata = -1;
1951		return (NULL);
1952	}
1953	if (data >= 0) {
1954		reply(125, "Using existing data connection for '%s'%s.",
1955		    name, sizebuf);
1956		usedefault = 1;
1957		return (fdopen(data, mode));
1958	}
1959	if (usedefault)
1960		data_dest = his_addr;
1961	usedefault = 1;
1962	do {
1963		file = getdatasock(mode);
1964		if (file == NULL) {
1965			char hostbuf[NI_MAXHOST], portbuf[NI_MAXSERV];
1966
1967			if (getnameinfo((struct sockaddr *)&data_source,
1968				data_source.su_len,
1969				hostbuf, sizeof(hostbuf) - 1,
1970				portbuf, sizeof(portbuf) - 1,
1971				NI_NUMERICHOST|NI_NUMERICSERV))
1972					*hostbuf = *portbuf = 0;
1973			hostbuf[sizeof(hostbuf) - 1] = 0;
1974			portbuf[sizeof(portbuf) - 1] = 0;
1975			reply(425, "Can't create data socket (%s,%s): %s.",
1976				hostbuf, portbuf, strerror(errno));
1977			return (NULL);
1978		}
1979		data = fileno(file);
1980		conerrno = 0;
1981		if (connect(data, (struct sockaddr *)&data_dest,
1982		    data_dest.su_len) == 0)
1983			break;
1984		conerrno = errno;
1985		(void) fclose(file);
1986		data = -1;
1987		if (conerrno == EADDRINUSE) {
1988			sleep(swaitint);
1989			retry += swaitint;
1990		} else {
1991			break;
1992		}
1993	} while (retry <= swaitmax);
1994	if (conerrno != 0) {
1995		reply(425, "Can't build data connection: %s.",
1996			   strerror(conerrno));
1997		return (NULL);
1998	}
1999	reply(150, "Opening %s mode data connection for '%s'%s.",
2000	     type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
2001	return (file);
2002}
2003
2004/*
2005 * A helper macro to avoid code duplication
2006 * in send_data() and receive_data().
2007 *
2008 * XXX We have to block SIGURG during putc() because BSD stdio
2009 * is unable to restart interrupted write operations and hence
2010 * the entire buffer contents will be lost as soon as a write()
2011 * call indicates EINTR to stdio.
2012 */
2013#define FTPD_PUTC(ch, file, label)					\
2014	do {								\
2015		int ret;						\
2016									\
2017		do {							\
2018			START_UNSAFE;					\
2019			ret = putc((ch), (file));			\
2020			END_UNSAFE;					\
2021			CHECKOOB(return (-1))				\
2022			else if (ferror(file))				\
2023				goto label;				\
2024			clearerr(file);					\
2025		} while (ret == EOF);					\
2026	} while (0)
2027
2028/*
2029 * Tranfer the contents of "instr" to "outstr" peer using the appropriate
2030 * encapsulation of the data subject to Mode, Structure, and Type.
2031 *
2032 * NB: Form isn't handled.
2033 */
2034static int
2035send_data(FILE *instr, FILE *outstr, size_t blksize, off_t filesize, int isreg)
2036{
2037	int c, cp, filefd, netfd;
2038	char *buf;
2039
2040	STARTXFER;
2041
2042	switch (type) {
2043
2044	case TYPE_A:
2045		cp = EOF;
2046		for (;;) {
2047			c = getc(instr);
2048			CHECKOOB(return (-1))
2049			else if (c == EOF && ferror(instr))
2050				goto file_err;
2051			if (c == EOF) {
2052				if (ferror(instr)) {	/* resume after OOB */
2053					clearerr(instr);
2054					continue;
2055				}
2056				if (feof(instr))	/* EOF */
2057					break;
2058				syslog(LOG_ERR, "Internal: impossible condition"
2059						" on file after getc()");
2060				goto file_err;
2061			}
2062			if (c == '\n' && cp != '\r') {
2063				FTPD_PUTC('\r', outstr, data_err);
2064				byte_count++;
2065			}
2066			FTPD_PUTC(c, outstr, data_err);
2067			byte_count++;
2068			cp = c;
2069		}
2070#ifdef notyet	/* BSD stdio isn't ready for that */
2071		while (fflush(outstr) == EOF) {
2072			CHECKOOB(return (-1))
2073			else
2074				goto data_err;
2075			clearerr(outstr);
2076		}
2077		ENDXFER;
2078#else
2079		ENDXFER;
2080		if (fflush(outstr) == EOF)
2081			goto data_err;
2082#endif
2083		reply(226, "Transfer complete.");
2084		return (0);
2085
2086	case TYPE_I:
2087	case TYPE_L:
2088		/*
2089		 * isreg is only set if we are not doing restart and we
2090		 * are sending a regular file
2091		 */
2092		netfd = fileno(outstr);
2093		filefd = fileno(instr);
2094
2095		if (isreg) {
2096			char *msg = "Transfer complete.";
2097			off_t cnt, offset;
2098			int err;
2099
2100			cnt = offset = 0;
2101
2102			while (filesize > 0) {
2103				err = sendfile(filefd, netfd, offset, 0,
2104					       NULL, &cnt, 0);
2105				/*
2106				 * Calculate byte_count before OOB processing.
2107				 * It can be used in myoob() later.
2108				 */
2109				byte_count += cnt;
2110				offset += cnt;
2111				filesize -= cnt;
2112				CHECKOOB(return (-1))
2113				else if (err == -1) {
2114					if (errno != EINTR &&
2115					    cnt == 0 && offset == 0)
2116						goto oldway;
2117					goto data_err;
2118				}
2119				if (err == -1)	/* resume after OOB */
2120					continue;
2121				/*
2122				 * We hit the EOF prematurely.
2123				 * Perhaps the file was externally truncated.
2124				 */
2125				if (cnt == 0) {
2126					msg = "Transfer finished due to "
2127					      "premature end of file.";
2128					break;
2129				}
2130			}
2131			ENDXFER;
2132			reply(226, msg);
2133			return (0);
2134		}
2135
2136oldway:
2137		if ((buf = malloc(blksize)) == NULL) {
2138			ENDXFER;
2139			reply(451, "Ran out of memory.");
2140			return (-1);
2141		}
2142
2143		for (;;) {
2144			int cnt, len;
2145			char *bp;
2146
2147			cnt = read(filefd, buf, blksize);
2148			CHECKOOB(free(buf); return (-1))
2149			else if (cnt < 0) {
2150				free(buf);
2151				goto file_err;
2152			}
2153			if (cnt < 0)	/* resume after OOB */
2154				continue;
2155			if (cnt == 0)	/* EOF */
2156				break;
2157			for (len = cnt, bp = buf; len > 0;) {
2158				cnt = write(netfd, bp, len);
2159				CHECKOOB(free(buf); return (-1))
2160				else if (cnt < 0) {
2161					free(buf);
2162					goto data_err;
2163				}
2164				if (cnt <= 0)
2165					continue;
2166				len -= cnt;
2167				bp += cnt;
2168				byte_count += cnt;
2169			}
2170		}
2171		ENDXFER;
2172		free(buf);
2173		reply(226, "Transfer complete.");
2174		return (0);
2175	default:
2176		ENDXFER;
2177		reply(550, "Unimplemented TYPE %d in send_data.", type);
2178		return (-1);
2179	}
2180
2181data_err:
2182	ENDXFER;
2183	perror_reply(426, "Data connection");
2184	return (-1);
2185
2186file_err:
2187	ENDXFER;
2188	perror_reply(551, "Error on input file");
2189	return (-1);
2190}
2191
2192/*
2193 * Transfer data from peer to "outstr" using the appropriate encapulation of
2194 * the data subject to Mode, Structure, and Type.
2195 *
2196 * N.B.: Form isn't handled.
2197 */
2198static int
2199receive_data(FILE *instr, FILE *outstr)
2200{
2201	int c, cp;
2202	int bare_lfs = 0;
2203
2204	STARTXFER;
2205
2206	switch (type) {
2207
2208	case TYPE_I:
2209	case TYPE_L:
2210		for (;;) {
2211			int cnt, len;
2212			char *bp;
2213			char buf[BUFSIZ];
2214
2215			cnt = read(fileno(instr), buf, sizeof(buf));
2216			CHECKOOB(return (-1))
2217			else if (cnt < 0)
2218				goto data_err;
2219			if (cnt < 0)	/* resume after OOB */
2220				continue;
2221			if (cnt == 0)	/* EOF */
2222				break;
2223			for (len = cnt, bp = buf; len > 0;) {
2224				cnt = write(fileno(outstr), bp, len);
2225				CHECKOOB(return (-1))
2226				else if (cnt < 0)
2227					goto file_err;
2228				if (cnt <= 0)
2229					continue;
2230				len -= cnt;
2231				bp += cnt;
2232				byte_count += cnt;
2233			}
2234		}
2235		ENDXFER;
2236		return (0);
2237
2238	case TYPE_E:
2239		ENDXFER;
2240		reply(553, "TYPE E not implemented.");
2241		return (-1);
2242
2243	case TYPE_A:
2244		cp = EOF;
2245		for (;;) {
2246			c = getc(instr);
2247			CHECKOOB(return (-1))
2248			else if (c == EOF && ferror(instr))
2249				goto data_err;
2250			if (c == EOF && ferror(instr)) { /* resume after OOB */
2251				clearerr(instr);
2252				continue;
2253			}
2254
2255			if (cp == '\r') {
2256				if (c != '\n')
2257					FTPD_PUTC('\r', outstr, file_err);
2258			} else
2259				if (c == '\n')
2260					bare_lfs++;
2261			if (c == '\r') {
2262				byte_count++;
2263				cp = c;
2264				continue;
2265			}
2266
2267			/* Check for EOF here in order not to lose last \r. */
2268			if (c == EOF) {
2269				if (feof(instr))	/* EOF */
2270					break;
2271				syslog(LOG_ERR, "Internal: impossible condition"
2272						" on data stream after getc()");
2273				goto data_err;
2274			}
2275
2276			byte_count++;
2277			FTPD_PUTC(c, outstr, file_err);
2278			cp = c;
2279		}
2280#ifdef notyet	/* BSD stdio isn't ready for that */
2281		while (fflush(outstr) == EOF) {
2282			CHECKOOB(return (-1))
2283			else
2284				goto file_err;
2285			clearerr(outstr);
2286		}
2287		ENDXFER;
2288#else
2289		ENDXFER;
2290		if (fflush(outstr) == EOF)
2291			goto file_err;
2292#endif
2293		if (bare_lfs) {
2294			lreply(226,
2295		"WARNING! %d bare linefeeds received in ASCII mode.",
2296			    bare_lfs);
2297		(void)printf("   File may not have transferred correctly.\r\n");
2298		}
2299		return (0);
2300	default:
2301		ENDXFER;
2302		reply(550, "Unimplemented TYPE %d in receive_data.", type);
2303		return (-1);
2304	}
2305
2306data_err:
2307	ENDXFER;
2308	perror_reply(426, "Data connection");
2309	return (-1);
2310
2311file_err:
2312	ENDXFER;
2313	perror_reply(452, "Error writing to file");
2314	return (-1);
2315}
2316
2317void
2318statfilecmd(char *filename)
2319{
2320	FILE *fin;
2321	int atstart;
2322	int c, code;
2323	char line[LINE_MAX];
2324	struct stat st;
2325
2326	code = lstat(filename, &st) == 0 && S_ISDIR(st.st_mode) ? 212 : 213;
2327	(void)snprintf(line, sizeof(line), _PATH_LS " -lgA %s", filename);
2328	fin = ftpd_popen(line, "r");
2329	lreply(code, "Status of %s:", filename);
2330	atstart = 1;
2331	while ((c = getc(fin)) != EOF) {
2332		if (c == '\n') {
2333			if (ferror(stdout)){
2334				perror_reply(421, "Control connection");
2335				(void) ftpd_pclose(fin);
2336				dologout(1);
2337				/* NOTREACHED */
2338			}
2339			if (ferror(fin)) {
2340				perror_reply(551, filename);
2341				(void) ftpd_pclose(fin);
2342				return;
2343			}
2344			(void) putc('\r', stdout);
2345		}
2346		/*
2347		 * RFC 959 says neutral text should be prepended before
2348		 * a leading 3-digit number followed by whitespace, but
2349		 * many ftp clients can be confused by any leading digits,
2350		 * as a matter of fact.
2351		 */
2352		if (atstart && isdigit(c))
2353			(void) putc(' ', stdout);
2354		(void) putc(c, stdout);
2355		atstart = (c == '\n');
2356	}
2357	(void) ftpd_pclose(fin);
2358	reply(code, "End of status.");
2359}
2360
2361void
2362statcmd(void)
2363{
2364	union sockunion *su;
2365	u_char *a, *p;
2366	char hname[NI_MAXHOST];
2367	int ispassive;
2368
2369	if (hostinfo) {
2370		lreply(211, "%s FTP server status:", hostname);
2371		printf("     %s\r\n", version);
2372	} else
2373		lreply(211, "FTP server status:");
2374	printf("     Connected to %s", remotehost);
2375	if (!getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len,
2376			 hname, sizeof(hname) - 1, NULL, 0, NI_NUMERICHOST)) {
2377		hname[sizeof(hname) - 1] = 0;
2378		if (strcmp(hname, remotehost) != 0)
2379			printf(" (%s)", hname);
2380	}
2381	printf("\r\n");
2382	if (logged_in) {
2383		if (guest)
2384			printf("     Logged in anonymously\r\n");
2385		else
2386			printf("     Logged in as %s\r\n", pw->pw_name);
2387	} else if (askpasswd)
2388		printf("     Waiting for password\r\n");
2389	else
2390		printf("     Waiting for user name\r\n");
2391	printf("     TYPE: %s", typenames[type]);
2392	if (type == TYPE_A || type == TYPE_E)
2393		printf(", FORM: %s", formnames[form]);
2394	if (type == TYPE_L)
2395#if CHAR_BIT == 8
2396		printf(" %d", CHAR_BIT);
2397#else
2398		printf(" %d", bytesize);	/* need definition! */
2399#endif
2400	printf("; STRUcture: %s; transfer MODE: %s\r\n",
2401	    strunames[stru], modenames[mode]);
2402	if (data != -1)
2403		printf("     Data connection open\r\n");
2404	else if (pdata != -1) {
2405		ispassive = 1;
2406		su = &pasv_addr;
2407		goto printaddr;
2408	} else if (usedefault == 0) {
2409		ispassive = 0;
2410		su = &data_dest;
2411printaddr:
2412#define UC(b) (((int) b) & 0xff)
2413		if (epsvall) {
2414			printf("     EPSV only mode (EPSV ALL)\r\n");
2415			goto epsvonly;
2416		}
2417
2418		/* PORT/PASV */
2419		if (su->su_family == AF_INET) {
2420			a = (u_char *) &su->su_sin.sin_addr;
2421			p = (u_char *) &su->su_sin.sin_port;
2422			printf("     %s (%d,%d,%d,%d,%d,%d)\r\n",
2423				ispassive ? "PASV" : "PORT",
2424				UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
2425				UC(p[0]), UC(p[1]));
2426		}
2427
2428		/* LPRT/LPSV */
2429	    {
2430		int alen, af, i;
2431
2432		switch (su->su_family) {
2433		case AF_INET:
2434			a = (u_char *) &su->su_sin.sin_addr;
2435			p = (u_char *) &su->su_sin.sin_port;
2436			alen = sizeof(su->su_sin.sin_addr);
2437			af = 4;
2438			break;
2439		case AF_INET6:
2440			a = (u_char *) &su->su_sin6.sin6_addr;
2441			p = (u_char *) &su->su_sin6.sin6_port;
2442			alen = sizeof(su->su_sin6.sin6_addr);
2443			af = 6;
2444			break;
2445		default:
2446			af = 0;
2447			break;
2448		}
2449		if (af) {
2450			printf("     %s (%d,%d,", ispassive ? "LPSV" : "LPRT",
2451				af, alen);
2452			for (i = 0; i < alen; i++)
2453				printf("%d,", UC(a[i]));
2454			printf("%d,%d,%d)\r\n", 2, UC(p[0]), UC(p[1]));
2455		}
2456	    }
2457
2458epsvonly:;
2459		/* EPRT/EPSV */
2460	    {
2461		int af;
2462
2463		switch (su->su_family) {
2464		case AF_INET:
2465			af = 1;
2466			break;
2467		case AF_INET6:
2468			af = 2;
2469			break;
2470		default:
2471			af = 0;
2472			break;
2473		}
2474		if (af) {
2475			union sockunion tmp;
2476
2477			tmp = *su;
2478			if (tmp.su_family == AF_INET6)
2479				tmp.su_sin6.sin6_scope_id = 0;
2480			if (!getnameinfo((struct sockaddr *)&tmp, tmp.su_len,
2481					hname, sizeof(hname) - 1, NULL, 0,
2482					NI_NUMERICHOST)) {
2483				hname[sizeof(hname) - 1] = 0;
2484				printf("     %s |%d|%s|%d|\r\n",
2485					ispassive ? "EPSV" : "EPRT",
2486					af, hname, htons(tmp.su_port));
2487			}
2488		}
2489	    }
2490#undef UC
2491	} else
2492		printf("     No data connection\r\n");
2493	reply(211, "End of status.");
2494}
2495
2496void
2497fatalerror(char *s)
2498{
2499
2500	reply(451, "Error in server: %s", s);
2501	reply(221, "Closing connection due to server error.");
2502	dologout(0);
2503	/* NOTREACHED */
2504}
2505
2506void
2507reply(int n, const char *fmt, ...)
2508{
2509	va_list ap;
2510
2511	(void)printf("%d ", n);
2512	va_start(ap, fmt);
2513	(void)vprintf(fmt, ap);
2514	va_end(ap);
2515	(void)printf("\r\n");
2516	(void)fflush(stdout);
2517	if (ftpdebug) {
2518		syslog(LOG_DEBUG, "<--- %d ", n);
2519		va_start(ap, fmt);
2520		vsyslog(LOG_DEBUG, fmt, ap);
2521		va_end(ap);
2522	}
2523}
2524
2525void
2526lreply(int n, const char *fmt, ...)
2527{
2528	va_list ap;
2529
2530	(void)printf("%d- ", n);
2531	va_start(ap, fmt);
2532	(void)vprintf(fmt, ap);
2533	va_end(ap);
2534	(void)printf("\r\n");
2535	(void)fflush(stdout);
2536	if (ftpdebug) {
2537		syslog(LOG_DEBUG, "<--- %d- ", n);
2538		va_start(ap, fmt);
2539		vsyslog(LOG_DEBUG, fmt, ap);
2540		va_end(ap);
2541	}
2542}
2543
2544static void
2545ack(char *s)
2546{
2547
2548	reply(250, "%s command successful.", s);
2549}
2550
2551void
2552nack(char *s)
2553{
2554
2555	reply(502, "%s command not implemented.", s);
2556}
2557
2558/* ARGSUSED */
2559void
2560yyerror(char *s)
2561{
2562	char *cp;
2563
2564	if ((cp = strchr(cbuf,'\n')))
2565		*cp = '\0';
2566	reply(500, "%s: command not understood.", cbuf);
2567}
2568
2569void
2570delete(char *name)
2571{
2572	struct stat st;
2573
2574	LOGCMD("delete", name);
2575	if (lstat(name, &st) < 0) {
2576		perror_reply(550, name);
2577		return;
2578	}
2579	if (S_ISDIR(st.st_mode)) {
2580		if (rmdir(name) < 0) {
2581			perror_reply(550, name);
2582			return;
2583		}
2584		goto done;
2585	}
2586	if (guest && noguestmod) {
2587		reply(550, "Operation not permitted.");
2588		return;
2589	}
2590	if (unlink(name) < 0) {
2591		perror_reply(550, name);
2592		return;
2593	}
2594done:
2595	ack("DELE");
2596}
2597
2598void
2599cwd(char *path)
2600{
2601
2602	if (chdir(path) < 0)
2603		perror_reply(550, path);
2604	else
2605		ack("CWD");
2606}
2607
2608void
2609makedir(char *name)
2610{
2611	char *s;
2612
2613	LOGCMD("mkdir", name);
2614	if (guest && noguestmkd)
2615		reply(550, "Operation not permitted.");
2616	else if (mkdir(name, 0777) < 0)
2617		perror_reply(550, name);
2618	else {
2619		if ((s = doublequote(name)) == NULL)
2620			fatalerror("Ran out of memory.");
2621		reply(257, "\"%s\" directory created.", s);
2622		free(s);
2623	}
2624}
2625
2626void
2627removedir(char *name)
2628{
2629
2630	LOGCMD("rmdir", name);
2631	if (rmdir(name) < 0)
2632		perror_reply(550, name);
2633	else
2634		ack("RMD");
2635}
2636
2637void
2638pwd(void)
2639{
2640	char *s, path[MAXPATHLEN + 1];
2641
2642	if (getcwd(path, sizeof(path)) == NULL)
2643		perror_reply(550, "Get current directory");
2644	else {
2645		if ((s = doublequote(path)) == NULL)
2646			fatalerror("Ran out of memory.");
2647		reply(257, "\"%s\" is current directory.", s);
2648		free(s);
2649	}
2650}
2651
2652char *
2653renamefrom(char *name)
2654{
2655	struct stat st;
2656
2657	if (guest && noguestmod) {
2658		reply(550, "Operation not permitted.");
2659		return (NULL);
2660	}
2661	if (lstat(name, &st) < 0) {
2662		perror_reply(550, name);
2663		return (NULL);
2664	}
2665	reply(350, "File exists, ready for destination name.");
2666	return (name);
2667}
2668
2669void
2670renamecmd(char *from, char *to)
2671{
2672	struct stat st;
2673
2674	LOGCMD2("rename", from, to);
2675
2676	if (guest && (stat(to, &st) == 0)) {
2677		reply(550, "%s: permission denied.", to);
2678		return;
2679	}
2680
2681	if (rename(from, to) < 0)
2682		perror_reply(550, "rename");
2683	else
2684		ack("RNTO");
2685}
2686
2687static void
2688dolog(struct sockaddr *who)
2689{
2690	char who_name[NI_MAXHOST];
2691
2692	realhostname_sa(remotehost, sizeof(remotehost) - 1, who, who->sa_len);
2693	remotehost[sizeof(remotehost) - 1] = 0;
2694	if (getnameinfo(who, who->sa_len,
2695		who_name, sizeof(who_name) - 1, NULL, 0, NI_NUMERICHOST))
2696			*who_name = 0;
2697	who_name[sizeof(who_name) - 1] = 0;
2698
2699#ifdef SETPROCTITLE
2700#ifdef VIRTUAL_HOSTING
2701	if (thishost != firsthost)
2702		snprintf(proctitle, sizeof(proctitle), "%s: connected (to %s)",
2703			 remotehost, hostname);
2704	else
2705#endif
2706		snprintf(proctitle, sizeof(proctitle), "%s: connected",
2707			 remotehost);
2708	setproctitle("%s", proctitle);
2709#endif /* SETPROCTITLE */
2710
2711	if (logging) {
2712#ifdef VIRTUAL_HOSTING
2713		if (thishost != firsthost)
2714			syslog(LOG_INFO, "connection from %s (%s) to %s",
2715			       remotehost, who_name, hostname);
2716		else
2717#endif
2718			syslog(LOG_INFO, "connection from %s (%s)",
2719			       remotehost, who_name);
2720	}
2721}
2722
2723/*
2724 * Record logout in wtmp file
2725 * and exit with supplied status.
2726 */
2727void
2728dologout(int status)
2729{
2730
2731	if (logged_in && dowtmp) {
2732		(void) seteuid(0);
2733		ftpd_logwtmp(ttyline, "", NULL);
2734	}
2735	/* beware of flushing buffers after a SIGPIPE */
2736	_exit(status);
2737}
2738
2739static void
2740sigurg(int signo)
2741{
2742
2743	recvurg = 1;
2744}
2745
2746static void
2747maskurg(int flag)
2748{
2749	int oerrno;
2750	sigset_t sset;
2751
2752	if (!transflag) {
2753		syslog(LOG_ERR, "Internal: maskurg() while no transfer");
2754		return;
2755	}
2756	oerrno = errno;
2757	sigemptyset(&sset);
2758	sigaddset(&sset, SIGURG);
2759	sigprocmask(flag ? SIG_BLOCK : SIG_UNBLOCK, &sset, NULL);
2760	errno = oerrno;
2761}
2762
2763static void
2764flagxfer(int flag)
2765{
2766
2767	if (flag) {
2768		if (transflag)
2769			syslog(LOG_ERR, "Internal: flagxfer(1): "
2770					"transfer already under way");
2771		transflag = 1;
2772		maskurg(0);
2773		recvurg = 0;
2774	} else {
2775		if (!transflag)
2776			syslog(LOG_ERR, "Internal: flagxfer(0): "
2777					"no active transfer");
2778		maskurg(1);
2779		transflag = 0;
2780	}
2781}
2782
2783/*
2784 * Returns 0 if OK to resume or -1 if abort requested.
2785 */
2786static int
2787myoob(void)
2788{
2789	char *cp;
2790
2791	if (!transflag) {
2792		syslog(LOG_ERR, "Internal: myoob() while no transfer");
2793		return (0);
2794	}
2795	cp = tmpline;
2796	if (getline(cp, 7, stdin) == NULL) {
2797		reply(221, "You could at least say goodbye.");
2798		dologout(0);
2799	}
2800	upper(cp);
2801	if (strcmp(cp, "ABOR\r\n") == 0) {
2802		tmpline[0] = '\0';
2803		reply(426, "Transfer aborted. Data connection closed.");
2804		reply(226, "Abort successful.");
2805		return (-1);
2806	}
2807	if (strcmp(cp, "STAT\r\n") == 0) {
2808		tmpline[0] = '\0';
2809		if (file_size != -1)
2810			reply(213, "Status: %jd of %jd bytes transferred.",
2811				   (intmax_t)byte_count, (intmax_t)file_size);
2812		else
2813			reply(213, "Status: %jd bytes transferred.",
2814				   (intmax_t)byte_count);
2815	}
2816	return (0);
2817}
2818
2819/*
2820 * Note: a response of 425 is not mentioned as a possible response to
2821 *	the PASV command in RFC959. However, it has been blessed as
2822 *	a legitimate response by Jon Postel in a telephone conversation
2823 *	with Rick Adams on 25 Jan 89.
2824 */
2825void
2826passive(void)
2827{
2828	socklen_t len;
2829	int on;
2830	char *p, *a;
2831
2832	if (pdata >= 0)		/* close old port if one set */
2833		close(pdata);
2834
2835	pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0);
2836	if (pdata < 0) {
2837		perror_reply(425, "Can't open passive connection");
2838		return;
2839	}
2840	on = 1;
2841	if (setsockopt(pdata, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
2842		syslog(LOG_WARNING, "pdata setsockopt (SO_REUSEADDR): %m");
2843
2844	(void) seteuid(0);
2845
2846#ifdef IP_PORTRANGE
2847	if (ctrl_addr.su_family == AF_INET) {
2848	    on = restricted_data_ports ? IP_PORTRANGE_HIGH
2849				       : IP_PORTRANGE_DEFAULT;
2850
2851	    if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2852			    &on, sizeof(on)) < 0)
2853		    goto pasv_error;
2854	}
2855#endif
2856#ifdef IPV6_PORTRANGE
2857	if (ctrl_addr.su_family == AF_INET6) {
2858	    on = restricted_data_ports ? IPV6_PORTRANGE_HIGH
2859				       : IPV6_PORTRANGE_DEFAULT;
2860
2861	    if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE,
2862			    &on, sizeof(on)) < 0)
2863		    goto pasv_error;
2864	}
2865#endif
2866
2867	pasv_addr = ctrl_addr;
2868	pasv_addr.su_port = 0;
2869	if (bind(pdata, (struct sockaddr *)&pasv_addr, pasv_addr.su_len) < 0)
2870		goto pasv_error;
2871
2872	(void) seteuid(pw->pw_uid);
2873
2874	len = sizeof(pasv_addr);
2875	if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
2876		goto pasv_error;
2877	if (listen(pdata, 1) < 0)
2878		goto pasv_error;
2879	if (pasv_addr.su_family == AF_INET)
2880		a = (char *) &pasv_addr.su_sin.sin_addr;
2881	else if (pasv_addr.su_family == AF_INET6 &&
2882		 IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr))
2883		a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12];
2884	else
2885		goto pasv_error;
2886
2887	p = (char *) &pasv_addr.su_port;
2888
2889#define UC(b) (((int) b) & 0xff)
2890
2891	reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]),
2892		UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
2893	return;
2894
2895pasv_error:
2896	(void) seteuid(pw->pw_uid);
2897	(void) close(pdata);
2898	pdata = -1;
2899	perror_reply(425, "Can't open passive connection");
2900	return;
2901}
2902
2903/*
2904 * Long Passive defined in RFC 1639.
2905 *     228 Entering Long Passive Mode
2906 *         (af, hal, h1, h2, h3,..., pal, p1, p2...)
2907 */
2908
2909void
2910long_passive(char *cmd, int pf)
2911{
2912	socklen_t len;
2913	int on;
2914	char *p, *a;
2915
2916	if (pdata >= 0)		/* close old port if one set */
2917		close(pdata);
2918
2919	if (pf != PF_UNSPEC) {
2920		if (ctrl_addr.su_family != pf) {
2921			switch (ctrl_addr.su_family) {
2922			case AF_INET:
2923				pf = 1;
2924				break;
2925			case AF_INET6:
2926				pf = 2;
2927				break;
2928			default:
2929				pf = 0;
2930				break;
2931			}
2932			/*
2933			 * XXX
2934			 * only EPRT/EPSV ready clients will understand this
2935			 */
2936			if (strcmp(cmd, "EPSV") == 0 && pf) {
2937				reply(522, "Network protocol mismatch, "
2938					"use (%d)", pf);
2939			} else
2940				reply(501, "Network protocol mismatch."); /*XXX*/
2941
2942			return;
2943		}
2944	}
2945
2946	pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0);
2947	if (pdata < 0) {
2948		perror_reply(425, "Can't open passive connection");
2949		return;
2950	}
2951	on = 1;
2952	if (setsockopt(pdata, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
2953		syslog(LOG_WARNING, "pdata setsockopt (SO_REUSEADDR): %m");
2954
2955	(void) seteuid(0);
2956
2957	pasv_addr = ctrl_addr;
2958	pasv_addr.su_port = 0;
2959	len = pasv_addr.su_len;
2960
2961#ifdef IP_PORTRANGE
2962	if (ctrl_addr.su_family == AF_INET) {
2963	    on = restricted_data_ports ? IP_PORTRANGE_HIGH
2964				       : IP_PORTRANGE_DEFAULT;
2965
2966	    if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2967			    &on, sizeof(on)) < 0)
2968		    goto pasv_error;
2969	}
2970#endif
2971#ifdef IPV6_PORTRANGE
2972	if (ctrl_addr.su_family == AF_INET6) {
2973	    on = restricted_data_ports ? IPV6_PORTRANGE_HIGH
2974				       : IPV6_PORTRANGE_DEFAULT;
2975
2976	    if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE,
2977			    &on, sizeof(on)) < 0)
2978		    goto pasv_error;
2979	}
2980#endif
2981
2982	if (bind(pdata, (struct sockaddr *)&pasv_addr, len) < 0)
2983		goto pasv_error;
2984
2985	(void) seteuid(pw->pw_uid);
2986
2987	if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
2988		goto pasv_error;
2989	if (listen(pdata, 1) < 0)
2990		goto pasv_error;
2991
2992#define UC(b) (((int) b) & 0xff)
2993
2994	if (strcmp(cmd, "LPSV") == 0) {
2995		p = (char *)&pasv_addr.su_port;
2996		switch (pasv_addr.su_family) {
2997		case AF_INET:
2998			a = (char *) &pasv_addr.su_sin.sin_addr;
2999		v4_reply:
3000			reply(228,
3001"Entering Long Passive Mode (%d,%d,%d,%d,%d,%d,%d,%d,%d)",
3002			      4, 4, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
3003			      2, UC(p[0]), UC(p[1]));
3004			return;
3005		case AF_INET6:
3006			if (IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr)) {
3007				a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12];
3008				goto v4_reply;
3009			}
3010			a = (char *) &pasv_addr.su_sin6.sin6_addr;
3011			reply(228,
3012"Entering Long Passive Mode "
3013"(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)",
3014			      6, 16, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
3015			      UC(a[4]), UC(a[5]), UC(a[6]), UC(a[7]),
3016			      UC(a[8]), UC(a[9]), UC(a[10]), UC(a[11]),
3017			      UC(a[12]), UC(a[13]), UC(a[14]), UC(a[15]),
3018			      2, UC(p[0]), UC(p[1]));
3019			return;
3020		}
3021	} else if (strcmp(cmd, "EPSV") == 0) {
3022		switch (pasv_addr.su_family) {
3023		case AF_INET:
3024		case AF_INET6:
3025			reply(229, "Entering Extended Passive Mode (|||%d|)",
3026				ntohs(pasv_addr.su_port));
3027			return;
3028		}
3029	} else {
3030		/* more proper error code? */
3031	}
3032
3033pasv_error:
3034	(void) seteuid(pw->pw_uid);
3035	(void) close(pdata);
3036	pdata = -1;
3037	perror_reply(425, "Can't open passive connection");
3038	return;
3039}
3040
3041/*
3042 * Generate unique name for file with basename "local"
3043 * and open the file in order to avoid possible races.
3044 * Try "local" first, then "local.1", "local.2" etc, up to "local.99".
3045 * Return descriptor to the file, set "name" to its name.
3046 *
3047 * Generates failure reply on error.
3048 */
3049static int
3050guniquefd(char *local, char **name)
3051{
3052	static char new[MAXPATHLEN];
3053	struct stat st;
3054	char *cp;
3055	int count;
3056	int fd;
3057
3058	cp = strrchr(local, '/');
3059	if (cp)
3060		*cp = '\0';
3061	if (stat(cp ? local : ".", &st) < 0) {
3062		perror_reply(553, cp ? local : ".");
3063		return (-1);
3064	}
3065	if (cp) {
3066		/*
3067		 * Let not overwrite dirname with counter suffix.
3068		 * -4 is for /nn\0
3069		 * In this extreme case dot won't be put in front of suffix.
3070		 */
3071		if (strlen(local) > sizeof(new) - 4) {
3072			reply(553, "Pathname too long.");
3073			return (-1);
3074		}
3075		*cp = '/';
3076	}
3077	/* -4 is for the .nn<null> we put on the end below */
3078	(void) snprintf(new, sizeof(new) - 4, "%s", local);
3079	cp = new + strlen(new);
3080	/*
3081	 * Don't generate dotfile unless requested explicitly.
3082	 * This covers the case when basename gets truncated off
3083	 * by buffer size.
3084	 */
3085	if (cp > new && cp[-1] != '/')
3086		*cp++ = '.';
3087	for (count = 0; count < 100; count++) {
3088		/* At count 0 try unmodified name */
3089		if (count)
3090			(void)sprintf(cp, "%d", count);
3091		if ((fd = open(count ? new : local,
3092		    O_RDWR | O_CREAT | O_EXCL, 0666)) >= 0) {
3093			*name = count ? new : local;
3094			return (fd);
3095		}
3096		if (errno != EEXIST) {
3097			perror_reply(553, count ? new : local);
3098			return (-1);
3099		}
3100	}
3101	reply(452, "Unique file name cannot be created.");
3102	return (-1);
3103}
3104
3105/*
3106 * Format and send reply containing system error number.
3107 */
3108void
3109perror_reply(int code, char *string)
3110{
3111
3112	reply(code, "%s: %s.", string, strerror(errno));
3113}
3114
3115static char *onefile[] = {
3116	"",
3117	0
3118};
3119
3120void
3121send_file_list(char *whichf)
3122{
3123	struct stat st;
3124	DIR *dirp = NULL;
3125	struct dirent *dir;
3126	FILE *dout = NULL;
3127	char **dirlist, *dirname;
3128	int simple = 0;
3129	int freeglob = 0;
3130	glob_t gl;
3131
3132	if (strpbrk(whichf, "~{[*?") != NULL) {
3133		int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_TILDE;
3134
3135		memset(&gl, 0, sizeof(gl));
3136		gl.gl_matchc = MAXGLOBARGS;
3137		flags |= GLOB_LIMIT;
3138		freeglob = 1;
3139		if (glob(whichf, flags, 0, &gl)) {
3140			reply(550, "No matching files found.");
3141			goto out;
3142		} else if (gl.gl_pathc == 0) {
3143			errno = ENOENT;
3144			perror_reply(550, whichf);
3145			goto out;
3146		}
3147		dirlist = gl.gl_pathv;
3148	} else {
3149		onefile[0] = whichf;
3150		dirlist = onefile;
3151		simple = 1;
3152	}
3153
3154	while ((dirname = *dirlist++)) {
3155		if (stat(dirname, &st) < 0) {
3156			/*
3157			 * If user typed "ls -l", etc, and the client
3158			 * used NLST, do what the user meant.
3159			 */
3160			if (dirname[0] == '-' && *dirlist == NULL &&
3161			    dout == NULL)
3162				retrieve(_PATH_LS " %s", dirname);
3163			else
3164				perror_reply(550, whichf);
3165			goto out;
3166		}
3167
3168		if (S_ISREG(st.st_mode)) {
3169			if (dout == NULL) {
3170				dout = dataconn("file list", -1, "w");
3171				if (dout == NULL)
3172					goto out;
3173				STARTXFER;
3174			}
3175			START_UNSAFE;
3176			fprintf(dout, "%s%s\n", dirname,
3177				type == TYPE_A ? "\r" : "");
3178			END_UNSAFE;
3179			if (ferror(dout))
3180				goto data_err;
3181			byte_count += strlen(dirname) +
3182				      (type == TYPE_A ? 2 : 1);
3183			CHECKOOB(goto abrt);
3184			continue;
3185		} else if (!S_ISDIR(st.st_mode))
3186			continue;
3187
3188		if ((dirp = opendir(dirname)) == NULL)
3189			continue;
3190
3191		while ((dir = readdir(dirp)) != NULL) {
3192			char nbuf[MAXPATHLEN];
3193
3194			CHECKOOB(goto abrt);
3195
3196			if (dir->d_name[0] == '.' && dir->d_namlen == 1)
3197				continue;
3198			if (dir->d_name[0] == '.' && dir->d_name[1] == '.' &&
3199			    dir->d_namlen == 2)
3200				continue;
3201
3202			snprintf(nbuf, sizeof(nbuf),
3203				"%s/%s", dirname, dir->d_name);
3204
3205			/*
3206			 * We have to do a stat to insure it's
3207			 * not a directory or special file.
3208			 */
3209			if (simple || (stat(nbuf, &st) == 0 &&
3210			    S_ISREG(st.st_mode))) {
3211				if (dout == NULL) {
3212					dout = dataconn("file list", -1, "w");
3213					if (dout == NULL)
3214						goto out;
3215					STARTXFER;
3216				}
3217				START_UNSAFE;
3218				if (nbuf[0] == '.' && nbuf[1] == '/')
3219					fprintf(dout, "%s%s\n", &nbuf[2],
3220						type == TYPE_A ? "\r" : "");
3221				else
3222					fprintf(dout, "%s%s\n", nbuf,
3223						type == TYPE_A ? "\r" : "");
3224				END_UNSAFE;
3225				if (ferror(dout))
3226					goto data_err;
3227				byte_count += strlen(nbuf) +
3228					      (type == TYPE_A ? 2 : 1);
3229				CHECKOOB(goto abrt);
3230			}
3231		}
3232		(void) closedir(dirp);
3233		dirp = NULL;
3234	}
3235
3236	if (dout == NULL)
3237		reply(550, "No files found.");
3238	else if (ferror(dout))
3239data_err:	perror_reply(550, "Data connection");
3240	else
3241		reply(226, "Transfer complete.");
3242out:
3243	if (dout) {
3244		ENDXFER;
3245abrt:
3246		(void) fclose(dout);
3247		data = -1;
3248		pdata = -1;
3249	}
3250	if (dirp)
3251		(void) closedir(dirp);
3252	if (freeglob) {
3253		freeglob = 0;
3254		globfree(&gl);
3255	}
3256}
3257
3258void
3259reapchild(int signo)
3260{
3261	while (waitpid(-1, NULL, WNOHANG) > 0);
3262}
3263
3264#ifdef OLD_SETPROCTITLE
3265/*
3266 * Clobber argv so ps will show what we're doing.  (Stolen from sendmail.)
3267 * Warning, since this is usually started from inetd.conf, it often doesn't
3268 * have much of an environment or arglist to overwrite.
3269 */
3270void
3271setproctitle(const char *fmt, ...)
3272{
3273	int i;
3274	va_list ap;
3275	char *p, *bp, ch;
3276	char buf[LINE_MAX];
3277
3278	va_start(ap, fmt);
3279	(void)vsnprintf(buf, sizeof(buf), fmt, ap);
3280
3281	/* make ps print our process name */
3282	p = Argv[0];
3283	*p++ = '-';
3284
3285	i = strlen(buf);
3286	if (i > LastArgv - p - 2) {
3287		i = LastArgv - p - 2;
3288		buf[i] = '\0';
3289	}
3290	bp = buf;
3291	while (ch = *bp++)
3292		if (ch != '\n' && ch != '\r')
3293			*p++ = ch;
3294	while (p < LastArgv)
3295		*p++ = ' ';
3296}
3297#endif /* OLD_SETPROCTITLE */
3298
3299static void
3300appendf(char **strp, char *fmt, ...)
3301{
3302	va_list ap;
3303	char *ostr, *p;
3304
3305	va_start(ap, fmt);
3306	vasprintf(&p, fmt, ap);
3307	va_end(ap);
3308	if (p == NULL)
3309		fatalerror("Ran out of memory.");
3310	if (*strp == NULL)
3311		*strp = p;
3312	else {
3313		ostr = *strp;
3314		asprintf(strp, "%s%s", ostr, p);
3315		if (*strp == NULL)
3316			fatalerror("Ran out of memory.");
3317		free(ostr);
3318	}
3319}
3320
3321static void
3322logcmd(char *cmd, char *file1, char *file2, off_t cnt)
3323{
3324	char *msg = NULL;
3325	char wd[MAXPATHLEN + 1];
3326
3327	if (logging <= 1)
3328		return;
3329
3330	if (getcwd(wd, sizeof(wd) - 1) == NULL)
3331		strcpy(wd, strerror(errno));
3332
3333	appendf(&msg, "%s", cmd);
3334	if (file1)
3335		appendf(&msg, " %s", file1);
3336	if (file2)
3337		appendf(&msg, " %s", file2);
3338	if (cnt >= 0)
3339		appendf(&msg, " = %jd bytes", (intmax_t)cnt);
3340	appendf(&msg, " (wd: %s", wd);
3341	if (guest || dochroot)
3342		appendf(&msg, "; chrooted");
3343	appendf(&msg, ")");
3344	syslog(LOG_INFO, "%s", msg);
3345	free(msg);
3346}
3347
3348static void
3349logxfer(char *name, off_t size, time_t start)
3350{
3351	char buf[MAXPATHLEN + 1024];
3352	char path[MAXPATHLEN + 1];
3353	time_t now;
3354
3355	if (statfd >= 0) {
3356		time(&now);
3357		if (realpath(name, path) == NULL) {
3358			syslog(LOG_NOTICE, "realpath failed on %s: %m", path);
3359			return;
3360		}
3361		snprintf(buf, sizeof(buf), "%.20s!%s!%s!%s!%jd!%ld\n",
3362			ctime(&now)+4, ident, remotehost,
3363			path, (intmax_t)size,
3364			(long)(now - start + (now == start)));
3365		write(statfd, buf, strlen(buf));
3366	}
3367}
3368
3369static char *
3370doublequote(char *s)
3371{
3372	int n;
3373	char *p, *s2;
3374
3375	for (p = s, n = 0; *p; p++)
3376		if (*p == '"')
3377			n++;
3378
3379	if ((s2 = malloc(p - s + n + 1)) == NULL)
3380		return (NULL);
3381
3382	for (p = s2; *s; s++, p++) {
3383		if ((*p = *s) == '"')
3384			*(++p) = '"';
3385	}
3386	*p = '\0';
3387
3388	return (s2);
3389}
3390
3391/* setup server socket for specified address family */
3392/* if af is PF_UNSPEC more than one socket may be returned */
3393/* the returned list is dynamically allocated, so caller needs to free it */
3394static int *
3395socksetup(int af, char *bindname, const char *bindport)
3396{
3397	struct addrinfo hints, *res, *r;
3398	int error, maxs, *s, *socks;
3399	const int on = 1;
3400
3401	memset(&hints, 0, sizeof(hints));
3402	hints.ai_flags = AI_PASSIVE;
3403	hints.ai_family = af;
3404	hints.ai_socktype = SOCK_STREAM;
3405	error = getaddrinfo(bindname, bindport, &hints, &res);
3406	if (error) {
3407		syslog(LOG_ERR, "%s", gai_strerror(error));
3408		if (error == EAI_SYSTEM)
3409			syslog(LOG_ERR, "%s", strerror(errno));
3410		return NULL;
3411	}
3412
3413	/* Count max number of sockets we may open */
3414	for (maxs = 0, r = res; r; r = r->ai_next, maxs++)
3415		;
3416	socks = malloc((maxs + 1) * sizeof(int));
3417	if (!socks) {
3418		freeaddrinfo(res);
3419		syslog(LOG_ERR, "couldn't allocate memory for sockets");
3420		return NULL;
3421	}
3422
3423	*socks = 0;   /* num of sockets counter at start of array */
3424	s = socks + 1;
3425	for (r = res; r; r = r->ai_next) {
3426		*s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
3427		if (*s < 0) {
3428			syslog(LOG_DEBUG, "control socket: %m");
3429			continue;
3430		}
3431		if (setsockopt(*s, SOL_SOCKET, SO_REUSEADDR,
3432		    &on, sizeof(on)) < 0)
3433			syslog(LOG_WARNING,
3434			    "control setsockopt (SO_REUSEADDR): %m");
3435		if (r->ai_family == AF_INET6) {
3436			if (setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY,
3437			    &on, sizeof(on)) < 0)
3438				syslog(LOG_WARNING,
3439				    "control setsockopt (IPV6_V6ONLY): %m");
3440		}
3441		if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) {
3442			syslog(LOG_DEBUG, "control bind: %m");
3443			close(*s);
3444			continue;
3445		}
3446		(*socks)++;
3447		s++;
3448	}
3449
3450	if (res)
3451		freeaddrinfo(res);
3452
3453	if (*socks == 0) {
3454		syslog(LOG_ERR, "control socket: Couldn't bind to any socket");
3455		free(socks);
3456		return NULL;
3457	}
3458	return(socks);
3459}
3460