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