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