ftpd.c revision 70205
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 70205 2000-12-20 03:34:54Z dan $";
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				offset += cnt;
1753				len -= cnt;
1754
1755				if (err == -1) {
1756					if (!cnt)
1757						goto oldway;
1758
1759					goto data_err;
1760				}
1761			}
1762
1763			reply(226, "Transfer complete.");
1764			return;
1765		}
1766
1767oldway:
1768		if ((buf = malloc((u_int)blksize)) == NULL) {
1769			transflag = 0;
1770			perror_reply(451, "Local resource failure: malloc");
1771			return;
1772		}
1773
1774		while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 &&
1775		    write(netfd, buf, cnt) == cnt)
1776			byte_count += cnt;
1777		transflag = 0;
1778		(void)free(buf);
1779		if (cnt != 0) {
1780			if (cnt < 0)
1781				goto file_err;
1782			goto data_err;
1783		}
1784		reply(226, "Transfer complete.");
1785		return;
1786	default:
1787		transflag = 0;
1788		reply(550, "Unimplemented TYPE %d in send_data", type);
1789		return;
1790	}
1791
1792data_err:
1793	transflag = 0;
1794	perror_reply(426, "Data connection");
1795	return;
1796
1797file_err:
1798	transflag = 0;
1799	perror_reply(551, "Error on input file");
1800}
1801
1802/*
1803 * Transfer data from peer to "outstr" using the appropriate encapulation of
1804 * the data subject to Mode, Structure, and Type.
1805 *
1806 * N.B.: Form isn't handled.
1807 */
1808static int
1809receive_data(instr, outstr)
1810	FILE *instr, *outstr;
1811{
1812	int c;
1813	int cnt, bare_lfs;
1814	char buf[BUFSIZ];
1815
1816	transflag++;
1817	if (setjmp(urgcatch)) {
1818		transflag = 0;
1819		return (-1);
1820	}
1821
1822	bare_lfs = 0;
1823
1824	switch (type) {
1825
1826	case TYPE_I:
1827	case TYPE_L:
1828		while ((cnt = read(fileno(instr), buf, sizeof(buf))) > 0) {
1829			if (write(fileno(outstr), buf, cnt) != cnt)
1830				goto file_err;
1831			byte_count += cnt;
1832		}
1833		if (cnt < 0)
1834			goto data_err;
1835		transflag = 0;
1836		return (0);
1837
1838	case TYPE_E:
1839		reply(553, "TYPE E not implemented.");
1840		transflag = 0;
1841		return (-1);
1842
1843	case TYPE_A:
1844		while ((c = getc(instr)) != EOF) {
1845			byte_count++;
1846			if (c == '\n')
1847				bare_lfs++;
1848			while (c == '\r') {
1849				if (ferror(outstr))
1850					goto data_err;
1851				if ((c = getc(instr)) != '\n') {
1852					(void) putc ('\r', outstr);
1853					if (c == '\0' || c == EOF)
1854						goto contin2;
1855				}
1856			}
1857			(void) putc(c, outstr);
1858	contin2:	;
1859		}
1860		fflush(outstr);
1861		if (ferror(instr))
1862			goto data_err;
1863		if (ferror(outstr))
1864			goto file_err;
1865		transflag = 0;
1866		if (bare_lfs) {
1867			lreply(226,
1868		"WARNING! %d bare linefeeds received in ASCII mode",
1869			    bare_lfs);
1870		(void)printf("   File may not have transferred correctly.\r\n");
1871		}
1872		return (0);
1873	default:
1874		reply(550, "Unimplemented TYPE %d in receive_data", type);
1875		transflag = 0;
1876		return (-1);
1877	}
1878
1879data_err:
1880	transflag = 0;
1881	perror_reply(426, "Data Connection");
1882	return (-1);
1883
1884file_err:
1885	transflag = 0;
1886	perror_reply(452, "Error writing file");
1887	return (-1);
1888}
1889
1890void
1891statfilecmd(filename)
1892	char *filename;
1893{
1894	FILE *fin;
1895	int c;
1896	char line[LINE_MAX];
1897
1898	(void)snprintf(line, sizeof(line), _PATH_LS " -lgA %s", filename);
1899	fin = ftpd_popen(line, "r");
1900	lreply(211, "status of %s:", filename);
1901	while ((c = getc(fin)) != EOF) {
1902		if (c == '\n') {
1903			if (ferror(stdout)){
1904				perror_reply(421, "control connection");
1905				(void) ftpd_pclose(fin);
1906				dologout(1);
1907				/* NOTREACHED */
1908			}
1909			if (ferror(fin)) {
1910				perror_reply(551, filename);
1911				(void) ftpd_pclose(fin);
1912				return;
1913			}
1914			(void) putc('\r', stdout);
1915		}
1916		(void) putc(c, stdout);
1917	}
1918	(void) ftpd_pclose(fin);
1919	reply(211, "End of Status");
1920}
1921
1922void
1923statcmd()
1924{
1925	union sockunion *su;
1926	u_char *a, *p;
1927	char hname[INET6_ADDRSTRLEN];
1928	int ispassive;
1929
1930	lreply(211, "%s FTP server status:", hostname, version);
1931	printf("     %s\r\n", version);
1932	printf("     Connected to %s", remotehost);
1933	if (!getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len,
1934			 hname, sizeof(hname) - 1, NULL, 0,
1935			 NI_NUMERICHOST|NI_WITHSCOPEID)) {
1936		if (strcmp(hname, remotehost) != 0)
1937			printf(" (%s)", hname);
1938	}
1939	printf("\r\n");
1940	if (logged_in) {
1941		if (guest)
1942			printf("     Logged in anonymously\r\n");
1943		else
1944			printf("     Logged in as %s\r\n", pw->pw_name);
1945	} else if (askpasswd)
1946		printf("     Waiting for password\r\n");
1947	else
1948		printf("     Waiting for user name\r\n");
1949	printf("     TYPE: %s", typenames[type]);
1950	if (type == TYPE_A || type == TYPE_E)
1951		printf(", FORM: %s", formnames[form]);
1952	if (type == TYPE_L)
1953#if NBBY == 8
1954		printf(" %d", NBBY);
1955#else
1956		printf(" %d", bytesize);	/* need definition! */
1957#endif
1958	printf("; STRUcture: %s; transfer MODE: %s\r\n",
1959	    strunames[stru], modenames[mode]);
1960	if (data != -1)
1961		printf("     Data connection open\r\n");
1962	else if (pdata != -1) {
1963		ispassive = 1;
1964		su = &pasv_addr;
1965		goto printaddr;
1966	} else if (usedefault == 0) {
1967		ispassive = 0;
1968		su = &data_dest;
1969printaddr:
1970#define UC(b) (((int) b) & 0xff)
1971		if (epsvall) {
1972			printf("     EPSV only mode (EPSV ALL)\r\n");
1973			goto epsvonly;
1974		}
1975
1976		/* PORT/PASV */
1977		if (su->su_family == AF_INET) {
1978			a = (u_char *) &su->su_sin.sin_addr;
1979			p = (u_char *) &su->su_sin.sin_port;
1980			printf("     %s (%d,%d,%d,%d,%d,%d)\r\n",
1981				ispassive ? "PASV" : "PORT",
1982				UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
1983				UC(p[0]), UC(p[1]));
1984		}
1985
1986		/* LPRT/LPSV */
1987	    {
1988		int alen, af, i;
1989
1990		switch (su->su_family) {
1991		case AF_INET:
1992			a = (u_char *) &su->su_sin.sin_addr;
1993			p = (u_char *) &su->su_sin.sin_port;
1994			alen = sizeof(su->su_sin.sin_addr);
1995			af = 4;
1996			break;
1997		case AF_INET6:
1998			a = (u_char *) &su->su_sin6.sin6_addr;
1999			p = (u_char *) &su->su_sin6.sin6_port;
2000			alen = sizeof(su->su_sin6.sin6_addr);
2001			af = 6;
2002			break;
2003		default:
2004			af = 0;
2005			break;
2006		}
2007		if (af) {
2008			printf("     %s (%d,%d,", ispassive ? "LPSV" : "LPRT",
2009				af, alen);
2010			for (i = 0; i < alen; i++)
2011				printf("%d,", UC(a[i]));
2012			printf("%d,%d,%d)\r\n", 2, UC(p[0]), UC(p[1]));
2013		}
2014	    }
2015
2016epsvonly:;
2017		/* EPRT/EPSV */
2018	    {
2019		int af;
2020
2021		switch (su->su_family) {
2022		case AF_INET:
2023			af = 1;
2024			break;
2025		case AF_INET6:
2026			af = 2;
2027			break;
2028		default:
2029			af = 0;
2030			break;
2031		}
2032		if (af) {
2033			if (!getnameinfo((struct sockaddr *)su, su->su_len,
2034					hname, sizeof(hname) - 1, NULL, 0,
2035					NI_NUMERICHOST)) {
2036				printf("     %s |%d|%s|%d|\r\n",
2037					ispassive ? "EPSV" : "EPRT",
2038					af, hname, htons(su->su_port));
2039			}
2040		}
2041	    }
2042#undef UC
2043	} else
2044		printf("     No data connection\r\n");
2045	reply(211, "End of status");
2046}
2047
2048void
2049fatal(s)
2050	char *s;
2051{
2052
2053	reply(451, "Error in server: %s\n", s);
2054	reply(221, "Closing connection due to server error.");
2055	dologout(0);
2056	/* NOTREACHED */
2057}
2058
2059void
2060#if __STDC__
2061reply(int n, const char *fmt, ...)
2062#else
2063reply(n, fmt, va_alist)
2064	int n;
2065	char *fmt;
2066        va_dcl
2067#endif
2068{
2069	va_list ap;
2070#if __STDC__
2071	va_start(ap, fmt);
2072#else
2073	va_start(ap);
2074#endif
2075	(void)printf("%d ", n);
2076	(void)vprintf(fmt, ap);
2077	(void)printf("\r\n");
2078	(void)fflush(stdout);
2079	if (debug) {
2080		syslog(LOG_DEBUG, "<--- %d ", n);
2081		vsyslog(LOG_DEBUG, fmt, ap);
2082	}
2083}
2084
2085void
2086#if __STDC__
2087lreply(int n, const char *fmt, ...)
2088#else
2089lreply(n, fmt, va_alist)
2090	int n;
2091	char *fmt;
2092        va_dcl
2093#endif
2094{
2095	va_list ap;
2096#if __STDC__
2097	va_start(ap, fmt);
2098#else
2099	va_start(ap);
2100#endif
2101	(void)printf("%d- ", n);
2102	(void)vprintf(fmt, ap);
2103	(void)printf("\r\n");
2104	(void)fflush(stdout);
2105	if (debug) {
2106		syslog(LOG_DEBUG, "<--- %d- ", n);
2107		vsyslog(LOG_DEBUG, fmt, ap);
2108	}
2109}
2110
2111static void
2112ack(s)
2113	char *s;
2114{
2115
2116	reply(250, "%s command successful.", s);
2117}
2118
2119void
2120nack(s)
2121	char *s;
2122{
2123
2124	reply(502, "%s command not implemented.", s);
2125}
2126
2127/* ARGSUSED */
2128void
2129yyerror(s)
2130	char *s;
2131{
2132	char *cp;
2133
2134	if ((cp = strchr(cbuf,'\n')))
2135		*cp = '\0';
2136	reply(500, "'%s': command not understood.", cbuf);
2137}
2138
2139void
2140delete(name)
2141	char *name;
2142{
2143	struct stat st;
2144
2145	LOGCMD("delete", name);
2146	if (stat(name, &st) < 0) {
2147		perror_reply(550, name);
2148		return;
2149	}
2150	if ((st.st_mode&S_IFMT) == S_IFDIR) {
2151		if (rmdir(name) < 0) {
2152			perror_reply(550, name);
2153			return;
2154		}
2155		goto done;
2156	}
2157	if (unlink(name) < 0) {
2158		perror_reply(550, name);
2159		return;
2160	}
2161done:
2162	ack("DELE");
2163}
2164
2165void
2166cwd(path)
2167	char *path;
2168{
2169
2170	if (chdir(path) < 0)
2171		perror_reply(550, path);
2172	else
2173		ack("CWD");
2174}
2175
2176void
2177makedir(name)
2178	char *name;
2179{
2180
2181	LOGCMD("mkdir", name);
2182	if (mkdir(name, 0777) < 0)
2183		perror_reply(550, name);
2184	else
2185		reply(257, "MKD command successful.");
2186}
2187
2188void
2189removedir(name)
2190	char *name;
2191{
2192
2193	LOGCMD("rmdir", name);
2194	if (rmdir(name) < 0)
2195		perror_reply(550, name);
2196	else
2197		ack("RMD");
2198}
2199
2200void
2201pwd()
2202{
2203	char path[MAXPATHLEN + 1];
2204
2205	if (getwd(path) == (char *)NULL)
2206		reply(550, "%s.", path);
2207	else
2208		reply(257, "\"%s\" is current directory.", path);
2209}
2210
2211char *
2212renamefrom(name)
2213	char *name;
2214{
2215	struct stat st;
2216
2217	if (stat(name, &st) < 0) {
2218		perror_reply(550, name);
2219		return ((char *)0);
2220	}
2221	reply(350, "File exists, ready for destination name");
2222	return (name);
2223}
2224
2225void
2226renamecmd(from, to)
2227	char *from, *to;
2228{
2229	struct stat st;
2230
2231	LOGCMD2("rename", from, to);
2232
2233	if (guest && (stat(to, &st) == 0)) {
2234		reply(550, "%s: permission denied", to);
2235		return;
2236	}
2237
2238	if (rename(from, to) < 0)
2239		perror_reply(550, "rename");
2240	else
2241		ack("RNTO");
2242}
2243
2244static void
2245dolog(who)
2246	struct sockaddr *who;
2247{
2248	int error;
2249
2250	realhostname_sa(remotehost, sizeof(remotehost) - 1, who, who->sa_len);
2251
2252#ifdef SETPROCTITLE
2253#ifdef VIRTUAL_HOSTING
2254	if (thishost != firsthost)
2255		snprintf(proctitle, sizeof(proctitle), "%s: connected (to %s)",
2256			 remotehost, hostname);
2257	else
2258#endif
2259		snprintf(proctitle, sizeof(proctitle), "%s: connected",
2260			 remotehost);
2261	setproctitle("%s", proctitle);
2262#endif /* SETPROCTITLE */
2263
2264	if (logging) {
2265#ifdef VIRTUAL_HOSTING
2266		if (thishost != firsthost)
2267			syslog(LOG_INFO, "connection from %s (to %s)",
2268			       remotehost, hostname);
2269		else
2270#endif
2271		{
2272			char	who_name[MAXHOSTNAMELEN];
2273
2274			error = getnameinfo(who, who->sa_len,
2275					    who_name, sizeof(who_name) - 1,
2276					    NULL, 0,
2277					    NI_NUMERICHOST|NI_WITHSCOPEID);
2278			syslog(LOG_INFO, "connection from %s (%s)", remotehost,
2279			       error == 0 ? who_name : "");
2280		}
2281	}
2282}
2283
2284/*
2285 * Record logout in wtmp file
2286 * and exit with supplied status.
2287 */
2288void
2289dologout(status)
2290	int status;
2291{
2292	/*
2293	 * Prevent reception of SIGURG from resulting in a resumption
2294	 * back to the main program loop.
2295	 */
2296	transflag = 0;
2297
2298	if (logged_in) {
2299		(void) seteuid((uid_t)0);
2300		ftpd_logwtmp(ttyline, "", "");
2301	}
2302	/* beware of flushing buffers after a SIGPIPE */
2303	_exit(status);
2304}
2305
2306static void
2307myoob(signo)
2308	int signo;
2309{
2310	char *cp;
2311
2312	/* only process if transfer occurring */
2313	if (!transflag)
2314		return;
2315	cp = tmpline;
2316	if (getline(cp, 7, stdin) == NULL) {
2317		reply(221, "You could at least say goodbye.");
2318		dologout(0);
2319	}
2320	upper(cp);
2321	if (strcmp(cp, "ABOR\r\n") == 0) {
2322		tmpline[0] = '\0';
2323		reply(426, "Transfer aborted. Data connection closed.");
2324		reply(226, "Abort successful");
2325		longjmp(urgcatch, 1);
2326	}
2327	if (strcmp(cp, "STAT\r\n") == 0) {
2328		tmpline[0] = '\0';
2329		if (file_size != (off_t) -1)
2330			reply(213, "Status: %qd of %qd bytes transferred",
2331			    byte_count, file_size);
2332		else
2333			reply(213, "Status: %qd bytes transferred", byte_count);
2334	}
2335}
2336
2337/*
2338 * Note: a response of 425 is not mentioned as a possible response to
2339 *	the PASV command in RFC959. However, it has been blessed as
2340 *	a legitimate response by Jon Postel in a telephone conversation
2341 *	with Rick Adams on 25 Jan 89.
2342 */
2343void
2344passive()
2345{
2346	int len;
2347	char *p, *a;
2348
2349	if (pdata >= 0)		/* close old port if one set */
2350		close(pdata);
2351
2352	pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0);
2353	if (pdata < 0) {
2354		perror_reply(425, "Can't open passive connection");
2355		return;
2356	}
2357
2358	(void) seteuid((uid_t)0);
2359
2360#ifdef IP_PORTRANGE
2361	if (ctrl_addr.su_family == AF_INET) {
2362	    int on = restricted_data_ports ? IP_PORTRANGE_HIGH
2363					   : IP_PORTRANGE_DEFAULT;
2364
2365	    if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2366			    (char *)&on, sizeof(on)) < 0)
2367		    goto pasv_error;
2368	}
2369#endif
2370#ifdef IPV6_PORTRANGE
2371	if (ctrl_addr.su_family == AF_INET6) {
2372	    int on = restricted_data_ports ? IPV6_PORTRANGE_HIGH
2373					   : IPV6_PORTRANGE_DEFAULT;
2374
2375	    if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE,
2376			    (char *)&on, sizeof(on)) < 0)
2377		    goto pasv_error;
2378	}
2379#endif
2380
2381	pasv_addr = ctrl_addr;
2382	pasv_addr.su_port = 0;
2383	if (bind(pdata, (struct sockaddr *)&pasv_addr, pasv_addr.su_len) < 0)
2384		goto pasv_error;
2385
2386	(void) seteuid((uid_t)pw->pw_uid);
2387
2388	len = sizeof(pasv_addr);
2389	if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
2390		goto pasv_error;
2391	if (listen(pdata, 1) < 0)
2392		goto pasv_error;
2393	if (pasv_addr.su_family == AF_INET)
2394		a = (char *) &pasv_addr.su_sin.sin_addr;
2395	else if (pasv_addr.su_family == AF_INET6 &&
2396		 IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr))
2397		a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12];
2398	else
2399		goto pasv_error;
2400
2401	p = (char *) &pasv_addr.su_port;
2402
2403#define UC(b) (((int) b) & 0xff)
2404
2405	reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]),
2406		UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
2407	return;
2408
2409pasv_error:
2410	(void) seteuid((uid_t)pw->pw_uid);
2411	(void) close(pdata);
2412	pdata = -1;
2413	perror_reply(425, "Can't open passive connection");
2414	return;
2415}
2416
2417/*
2418 * Long Passive defined in RFC 1639.
2419 *     228 Entering Long Passive Mode
2420 *         (af, hal, h1, h2, h3,..., pal, p1, p2...)
2421 */
2422
2423void
2424long_passive(cmd, pf)
2425	char *cmd;
2426	int pf;
2427{
2428	int len;
2429	char *p, *a;
2430
2431	if (pdata >= 0)		/* close old port if one set */
2432		close(pdata);
2433
2434	if (pf != PF_UNSPEC) {
2435		if (ctrl_addr.su_family != pf) {
2436			switch (ctrl_addr.su_family) {
2437			case AF_INET:
2438				pf = 1;
2439				break;
2440			case AF_INET6:
2441				pf = 2;
2442				break;
2443			default:
2444				pf = 0;
2445				break;
2446			}
2447			/*
2448			 * XXX
2449			 * only EPRT/EPSV ready clients will understand this
2450			 */
2451			if (strcmp(cmd, "EPSV") == 0 && pf) {
2452				reply(522, "Network protocol mismatch, "
2453					"use (%d)", pf);
2454			} else
2455				reply(501, "Network protocol mismatch"); /*XXX*/
2456
2457			return;
2458		}
2459	}
2460
2461	pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0);
2462	if (pdata < 0) {
2463		perror_reply(425, "Can't open passive connection");
2464		return;
2465	}
2466
2467	(void) seteuid((uid_t)0);
2468
2469	pasv_addr = ctrl_addr;
2470	pasv_addr.su_port = 0;
2471	len = pasv_addr.su_len;
2472
2473#ifdef IP_PORTRANGE
2474	if (ctrl_addr.su_family == AF_INET) {
2475	    int on = restricted_data_ports ? IP_PORTRANGE_HIGH
2476					   : IP_PORTRANGE_DEFAULT;
2477
2478	    if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2479			    (char *)&on, sizeof(on)) < 0)
2480		    goto pasv_error;
2481	}
2482#endif
2483#ifdef IPV6_PORTRANGE
2484	if (ctrl_addr.su_family == AF_INET6) {
2485	    int on = restricted_data_ports ? IPV6_PORTRANGE_HIGH
2486					   : IPV6_PORTRANGE_DEFAULT;
2487
2488	    if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE,
2489			    (char *)&on, sizeof(on)) < 0)
2490		    goto pasv_error;
2491	}
2492#endif
2493
2494	if (bind(pdata, (struct sockaddr *)&pasv_addr, len) < 0)
2495		goto pasv_error;
2496
2497	(void) seteuid((uid_t)pw->pw_uid);
2498
2499	if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
2500		goto pasv_error;
2501	if (listen(pdata, 1) < 0)
2502		goto pasv_error;
2503
2504#define UC(b) (((int) b) & 0xff)
2505
2506	if (strcmp(cmd, "LPSV") == 0) {
2507		p = (char *)&pasv_addr.su_port;
2508		switch (pasv_addr.su_family) {
2509		case AF_INET:
2510			a = (char *) &pasv_addr.su_sin.sin_addr;
2511		v4_reply:
2512			reply(228,
2513"Entering Long Passive Mode (%d,%d,%d,%d,%d,%d,%d,%d,%d)",
2514			      4, 4, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
2515			      2, UC(p[0]), UC(p[1]));
2516			return;
2517		case AF_INET6:
2518			if (IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr)) {
2519				a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12];
2520				goto v4_reply;
2521			}
2522			a = (char *) &pasv_addr.su_sin6.sin6_addr;
2523			reply(228,
2524"Entering Long Passive Mode "
2525"(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)",
2526			      6, 16, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
2527			      UC(a[4]), UC(a[5]), UC(a[6]), UC(a[7]),
2528			      UC(a[8]), UC(a[9]), UC(a[10]), UC(a[11]),
2529			      UC(a[12]), UC(a[13]), UC(a[14]), UC(a[15]),
2530			      2, UC(p[0]), UC(p[1]));
2531			return;
2532		}
2533	} else if (strcmp(cmd, "EPSV") == 0) {
2534		switch (pasv_addr.su_family) {
2535		case AF_INET:
2536		case AF_INET6:
2537			reply(229, "Entering Extended Passive Mode (|||%d|)",
2538				ntohs(pasv_addr.su_port));
2539			return;
2540		}
2541	} else {
2542		/* more proper error code? */
2543	}
2544
2545pasv_error:
2546	(void) seteuid((uid_t)pw->pw_uid);
2547	(void) close(pdata);
2548	pdata = -1;
2549	perror_reply(425, "Can't open passive connection");
2550	return;
2551}
2552
2553/*
2554 * Generate unique name for file with basename "local".
2555 * The file named "local" is already known to exist.
2556 * Generates failure reply on error.
2557 */
2558static char *
2559gunique(local)
2560	char *local;
2561{
2562	static char new[MAXPATHLEN];
2563	struct stat st;
2564	int count;
2565	char *cp;
2566
2567	cp = strrchr(local, '/');
2568	if (cp)
2569		*cp = '\0';
2570	if (stat(cp ? local : ".", &st) < 0) {
2571		perror_reply(553, cp ? local : ".");
2572		return ((char *) 0);
2573	}
2574	if (cp)
2575		*cp = '/';
2576	/* -4 is for the .nn<null> we put on the end below */
2577	(void) snprintf(new, sizeof(new) - 4, "%s", local);
2578	cp = new + strlen(new);
2579	*cp++ = '.';
2580	for (count = 1; count < 100; count++) {
2581		(void)sprintf(cp, "%d", count);
2582		if (stat(new, &st) < 0)
2583			return (new);
2584	}
2585	reply(452, "Unique file name cannot be created.");
2586	return (NULL);
2587}
2588
2589/*
2590 * Format and send reply containing system error number.
2591 */
2592void
2593perror_reply(code, string)
2594	int code;
2595	char *string;
2596{
2597
2598	reply(code, "%s: %s.", string, strerror(errno));
2599}
2600
2601static char *onefile[] = {
2602	"",
2603	0
2604};
2605
2606void
2607send_file_list(whichf)
2608	char *whichf;
2609{
2610	struct stat st;
2611	DIR *dirp = NULL;
2612	struct dirent *dir;
2613	FILE *dout = NULL;
2614	char **dirlist, *dirname;
2615	int simple = 0;
2616	int freeglob = 0;
2617	glob_t gl;
2618
2619	if (strpbrk(whichf, "~{[*?") != NULL) {
2620		int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
2621
2622		memset(&gl, 0, sizeof(gl));
2623		freeglob = 1;
2624		if (glob(whichf, flags, 0, &gl)) {
2625			reply(550, "not found");
2626			goto out;
2627		} else if (gl.gl_pathc == 0) {
2628			errno = ENOENT;
2629			perror_reply(550, whichf);
2630			goto out;
2631		}
2632		dirlist = gl.gl_pathv;
2633	} else {
2634		onefile[0] = whichf;
2635		dirlist = onefile;
2636		simple = 1;
2637	}
2638
2639	if (setjmp(urgcatch)) {
2640		transflag = 0;
2641		goto out;
2642	}
2643	while ((dirname = *dirlist++)) {
2644		if (stat(dirname, &st) < 0) {
2645			/*
2646			 * If user typed "ls -l", etc, and the client
2647			 * used NLST, do what the user meant.
2648			 */
2649			if (dirname[0] == '-' && *dirlist == NULL &&
2650			    transflag == 0) {
2651				retrieve(_PATH_LS " %s", dirname);
2652				goto out;
2653			}
2654			perror_reply(550, whichf);
2655			if (dout != NULL) {
2656				(void) fclose(dout);
2657				transflag = 0;
2658				data = -1;
2659				pdata = -1;
2660			}
2661			goto out;
2662		}
2663
2664		if (S_ISREG(st.st_mode)) {
2665			if (dout == NULL) {
2666				dout = dataconn("file list", (off_t)-1, "w");
2667				if (dout == NULL)
2668					goto out;
2669				transflag++;
2670			}
2671			fprintf(dout, "%s%s\n", dirname,
2672				type == TYPE_A ? "\r" : "");
2673			byte_count += strlen(dirname) + 1;
2674			continue;
2675		} else if (!S_ISDIR(st.st_mode))
2676			continue;
2677
2678		if ((dirp = opendir(dirname)) == NULL)
2679			continue;
2680
2681		while ((dir = readdir(dirp)) != NULL) {
2682			char nbuf[MAXPATHLEN];
2683
2684			if (dir->d_name[0] == '.' && dir->d_namlen == 1)
2685				continue;
2686			if (dir->d_name[0] == '.' && dir->d_name[1] == '.' &&
2687			    dir->d_namlen == 2)
2688				continue;
2689
2690			snprintf(nbuf, sizeof(nbuf),
2691				"%s/%s", dirname, dir->d_name);
2692
2693			/*
2694			 * We have to do a stat to insure it's
2695			 * not a directory or special file.
2696			 */
2697			if (simple || (stat(nbuf, &st) == 0 &&
2698			    S_ISREG(st.st_mode))) {
2699				if (dout == NULL) {
2700					dout = dataconn("file list", (off_t)-1,
2701						"w");
2702					if (dout == NULL)
2703						goto out;
2704					transflag++;
2705				}
2706				if (nbuf[0] == '.' && nbuf[1] == '/')
2707					fprintf(dout, "%s%s\n", &nbuf[2],
2708						type == TYPE_A ? "\r" : "");
2709				else
2710					fprintf(dout, "%s%s\n", nbuf,
2711						type == TYPE_A ? "\r" : "");
2712				byte_count += strlen(nbuf) + 1;
2713			}
2714		}
2715		(void) closedir(dirp);
2716	}
2717
2718	if (dout == NULL)
2719		reply(550, "No files found.");
2720	else if (ferror(dout) != 0)
2721		perror_reply(550, "Data connection");
2722	else
2723		reply(226, "Transfer complete.");
2724
2725	transflag = 0;
2726	if (dout != NULL)
2727		(void) fclose(dout);
2728	data = -1;
2729	pdata = -1;
2730out:
2731	if (freeglob) {
2732		freeglob = 0;
2733		globfree(&gl);
2734	}
2735}
2736
2737void
2738reapchild(signo)
2739	int signo;
2740{
2741	while (wait3(NULL, WNOHANG, NULL) > 0);
2742}
2743
2744#ifdef OLD_SETPROCTITLE
2745/*
2746 * Clobber argv so ps will show what we're doing.  (Stolen from sendmail.)
2747 * Warning, since this is usually started from inetd.conf, it often doesn't
2748 * have much of an environment or arglist to overwrite.
2749 */
2750void
2751#if __STDC__
2752setproctitle(const char *fmt, ...)
2753#else
2754setproctitle(fmt, va_alist)
2755	char *fmt;
2756        va_dcl
2757#endif
2758{
2759	int i;
2760	va_list ap;
2761	char *p, *bp, ch;
2762	char buf[LINE_MAX];
2763
2764#if __STDC__
2765	va_start(ap, fmt);
2766#else
2767	va_start(ap);
2768#endif
2769	(void)vsnprintf(buf, sizeof(buf), fmt, ap);
2770
2771	/* make ps print our process name */
2772	p = Argv[0];
2773	*p++ = '-';
2774
2775	i = strlen(buf);
2776	if (i > LastArgv - p - 2) {
2777		i = LastArgv - p - 2;
2778		buf[i] = '\0';
2779	}
2780	bp = buf;
2781	while (ch = *bp++)
2782		if (ch != '\n' && ch != '\r')
2783			*p++ = ch;
2784	while (p < LastArgv)
2785		*p++ = ' ';
2786}
2787#endif /* OLD_SETPROCTITLE */
2788
2789static void
2790logxfer(name, size, start)
2791	char *name;
2792	long size;
2793	long start;
2794{
2795	char buf[1024];
2796	char path[MAXPATHLEN + 1];
2797	time_t now;
2798
2799	if (statfd >= 0 && getwd(path) != NULL) {
2800		time(&now);
2801		snprintf(buf, sizeof(buf), "%.20s!%s!%s!%s/%s!%ld!%ld\n",
2802			ctime(&now)+4, ident, remotehost,
2803			path, name, size, now - start + (now == start));
2804		write(statfd, buf, strlen(buf));
2805	}
2806}
2807