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