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