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