ftpd.c revision 89569
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 89569 2002-01-19 18:29:50Z des $";
48#endif /* not lint */
49
50/*
51 * FTP server.
52 */
53#include <sys/param.h>
54#include <sys/ioctl.h>
55#include <sys/mman.h>
56#include <sys/socket.h>
57#include <sys/stat.h>
58#include <sys/time.h>
59#include <sys/wait.h>
60
61#include <netinet/in.h>
62#include <netinet/in_systm.h>
63#include <netinet/ip.h>
64#include <netinet/tcp.h>
65
66#define	FTP_NAMES
67#include <arpa/ftp.h>
68#include <arpa/inet.h>
69#include <arpa/telnet.h>
70
71#include <ctype.h>
72#include <dirent.h>
73#include <err.h>
74#include <errno.h>
75#include <fcntl.h>
76#include <glob.h>
77#include <limits.h>
78#include <netdb.h>
79#include <pwd.h>
80#include <grp.h>
81#include <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, "", "");
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		opieunlock();   /* XXX */
1255		if (rval == 0 || (!pwok && rval > 0))
1256			goto skip;
1257		xpasswd = crypt(passwd, pw->pw_passwd);
1258#else /* !USE_PAM */
1259		if (opieverify(&opiedata, passwd) == 0)
1260			xpasswd = pw->pw_passwd;
1261		else if (pwok)
1262			xpasswd = crypt(passwd, pw->pw_passwd);
1263		else {
1264			rval = 1;
1265			goto skip;
1266		}
1267#endif /* !USE_PAM */
1268		rval = strcmp(pw->pw_passwd, xpasswd);
1269		/* The strcmp does not catch null passwords! */
1270		if (*pw->pw_passwd == '\0' ||
1271		    (pw->pw_expire && time(NULL) >= pw->pw_expire))
1272			rval = 1;	/* failure */
1273skip:
1274		/*
1275		 * If rval == 1, the user failed the authentication check
1276		 * above.  If rval == 0, either PAM or local authentication
1277		 * succeeded.
1278		 */
1279		if (rval) {
1280			reply(530, "Login incorrect.");
1281			if (logging)
1282				syslog(LOG_NOTICE,
1283				    "FTP LOGIN FAILED FROM %s, %s",
1284				    remotehost, curname);
1285			pw = NULL;
1286			if (login_attempts++ >= 5) {
1287				syslog(LOG_NOTICE,
1288				    "repeated login failures from %s",
1289				    remotehost);
1290				exit(0);
1291			}
1292			return;
1293		}
1294	}
1295	login_attempts = 0;		/* this time successful */
1296	if (setegid((gid_t)pw->pw_gid) < 0) {
1297		reply(550, "Can't set gid.");
1298		return;
1299	}
1300	/* May be overridden by login.conf */
1301	(void) umask(defumask);
1302#ifdef	LOGIN_CAP
1303	if ((lc = login_getpwclass(pw)) != NULL) {
1304		char	remote_ip[MAXHOSTNAMELEN];
1305
1306		getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len,
1307			remote_ip, sizeof(remote_ip) - 1, NULL, 0,
1308			NI_NUMERICHOST|NI_WITHSCOPEID);
1309		remote_ip[sizeof(remote_ip) - 1] = 0;
1310		if (!auth_hostok(lc, remotehost, remote_ip)) {
1311			syslog(LOG_INFO|LOG_AUTH,
1312			    "FTP LOGIN FAILED (HOST) as %s: permission denied.",
1313			    pw->pw_name);
1314			reply(530, "Permission denied.\n");
1315			pw = NULL;
1316			return;
1317		}
1318		if (!auth_timeok(lc, time(NULL))) {
1319			reply(530, "Login not available right now.\n");
1320			pw = NULL;
1321			return;
1322		}
1323	}
1324	setusercontext(lc, pw, (uid_t)0,
1325		LOGIN_SETLOGIN|LOGIN_SETGROUP|LOGIN_SETPRIORITY|
1326		LOGIN_SETRESOURCES|LOGIN_SETUMASK);
1327#else
1328	setlogin(pw->pw_name);
1329	(void) initgroups(pw->pw_name, pw->pw_gid);
1330#endif
1331
1332#ifdef USE_PAM
1333	if (pamh) {
1334		if ((e = pam_open_session(pamh, 0)) != PAM_SUCCESS) {
1335			syslog(LOG_ERR, "pam_open_session: %s", pam_strerror(pamh, e));
1336		} else if ((e = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS) {
1337			syslog(LOG_ERR, "pam_setcred: %s", pam_strerror(pamh, e));
1338		}
1339	}
1340#endif
1341
1342	/* open wtmp before chroot */
1343	ftpd_logwtmp(ttyline, pw->pw_name, remotehost);
1344	logged_in = 1;
1345
1346	if (guest && stats && statfd < 0)
1347#ifdef VIRTUAL_HOSTING
1348		if ((statfd = open(thishost->statfile, O_WRONLY|O_APPEND)) < 0)
1349#else
1350		if ((statfd = open(_PATH_FTPDSTATFILE, O_WRONLY|O_APPEND)) < 0)
1351#endif
1352			stats = 0;
1353
1354	dochroot =
1355#ifdef	LOGIN_CAP	/* Allow login.conf configuration as well */
1356		login_getcapbool(lc, "ftp-chroot", 0) ||
1357#endif
1358		checkuser(_PATH_FTPCHROOT, pw->pw_name, 1);
1359	if (guest) {
1360		/*
1361		 * We MUST do a chdir() after the chroot. Otherwise
1362		 * the old current directory will be accessible as "."
1363		 * outside the new root!
1364		 */
1365		if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
1366			reply(550, "Can't set guest privileges.");
1367			goto bad;
1368		}
1369	} else if (dochroot) {
1370		if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
1371			reply(550, "Can't change root.");
1372			goto bad;
1373		}
1374	} else if (chdir(pw->pw_dir) < 0) {
1375		if (chdir("/") < 0) {
1376			reply(530, "User %s: can't change directory to %s.",
1377			    pw->pw_name, pw->pw_dir);
1378			goto bad;
1379		} else
1380			lreply(230, "No directory! Logging in with home=/");
1381	}
1382	if (seteuid((uid_t)pw->pw_uid) < 0) {
1383		reply(550, "Can't set uid.");
1384		goto bad;
1385	}
1386
1387	/*
1388	 * Display a login message, if it exists.
1389	 * N.B. reply(230,) must follow the message.
1390	 */
1391#ifdef VIRTUAL_HOSTING
1392	if ((fd = fopen(thishost->loginmsg, "r")) != NULL) {
1393#else
1394	if ((fd = fopen(_PATH_FTPLOGINMESG, "r")) != NULL) {
1395#endif
1396		char *cp, line[LINE_MAX];
1397
1398		while (fgets(line, sizeof(line), fd) != NULL) {
1399			if ((cp = strchr(line, '\n')) != NULL)
1400				*cp = '\0';
1401			lreply(230, "%s", line);
1402		}
1403		(void) fflush(stdout);
1404		(void) fclose(fd);
1405	}
1406	if (guest) {
1407		if (ident != NULL)
1408			free(ident);
1409		ident = strdup(passwd);
1410		if (ident == NULL)
1411			fatalerror("Ran out of memory.");
1412
1413		reply(230, "Guest login ok, access restrictions apply.");
1414#ifdef SETPROCTITLE
1415#ifdef VIRTUAL_HOSTING
1416		if (thishost != firsthost)
1417			snprintf(proctitle, sizeof(proctitle),
1418				 "%s: anonymous(%s)/%s", remotehost, hostname,
1419				 passwd);
1420		else
1421#endif
1422			snprintf(proctitle, sizeof(proctitle),
1423				 "%s: anonymous/%s", remotehost, passwd);
1424		setproctitle("%s", proctitle);
1425#endif /* SETPROCTITLE */
1426		if (logging)
1427			syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s",
1428			    remotehost, passwd);
1429	} else {
1430		if (dochroot)
1431			reply(230, "User %s logged in, "
1432				   "access restrictions apply.", pw->pw_name);
1433		else
1434			reply(230, "User %s logged in.", pw->pw_name);
1435
1436#ifdef SETPROCTITLE
1437		snprintf(proctitle, sizeof(proctitle),
1438			 "%s: user/%s", remotehost, pw->pw_name);
1439		setproctitle("%s", proctitle);
1440#endif /* SETPROCTITLE */
1441		if (logging)
1442			syslog(LOG_INFO, "FTP LOGIN FROM %s as %s",
1443			    remotehost, pw->pw_name);
1444	}
1445#ifdef	LOGIN_CAP
1446	login_close(lc);
1447#endif
1448	return;
1449bad:
1450	/* Forget all about it... */
1451#ifdef	LOGIN_CAP
1452	login_close(lc);
1453#endif
1454	end_login();
1455}
1456
1457void
1458retrieve(cmd, name)
1459	char *cmd, *name;
1460{
1461	FILE *fin, *dout;
1462	struct stat st;
1463	int (*closefunc) __P((FILE *));
1464	time_t start;
1465
1466	if (cmd == 0) {
1467		fin = fopen(name, "r"), closefunc = fclose;
1468		st.st_size = 0;
1469	} else {
1470		char line[BUFSIZ];
1471
1472		(void) snprintf(line, sizeof(line), cmd, name), name = line;
1473		fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose;
1474		st.st_size = -1;
1475		st.st_blksize = BUFSIZ;
1476	}
1477	if (fin == NULL) {
1478		if (errno != 0) {
1479			perror_reply(550, name);
1480			if (cmd == 0) {
1481				LOGCMD("get", name);
1482			}
1483		}
1484		return;
1485	}
1486	byte_count = -1;
1487	if (cmd == 0 && (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode))) {
1488		reply(550, "%s: not a plain file.", name);
1489		goto done;
1490	}
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(fin)) == EOF) {
1500					perror_reply(550, name);
1501					goto done;
1502				}
1503				if (c == '\n')
1504					i++;
1505			}
1506		} else if (lseek(fileno(fin), restart_point, L_SET) < 0) {
1507			perror_reply(550, name);
1508			goto done;
1509		}
1510	}
1511	dout = dataconn(name, st.st_size, "w");
1512	if (dout == NULL)
1513		goto done;
1514	time(&start);
1515	send_data(fin, dout, st.st_blksize, st.st_size,
1516		  restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode));
1517	if (cmd == 0 && guest && stats)
1518		logxfer(name, st.st_size, start);
1519	(void) fclose(dout);
1520	data = -1;
1521	pdata = -1;
1522done:
1523	if (cmd == 0)
1524		LOGBYTES("get", name, byte_count);
1525	(*closefunc)(fin);
1526}
1527
1528void
1529store(name, mode, unique)
1530	char *name, *mode;
1531	int unique;
1532{
1533	FILE *fout, *din;
1534	struct stat st;
1535	int (*closefunc) __P((FILE *));
1536
1537	if ((unique || guest) && stat(name, &st) == 0 &&
1538	    (name = gunique(name)) == NULL) {
1539		LOGCMD(*mode == 'w' ? "put" : "append", name);
1540		return;
1541	}
1542
1543	if (restart_point)
1544		mode = "r+";
1545	fout = fopen(name, mode);
1546	closefunc = fclose;
1547	if (fout == NULL) {
1548		perror_reply(553, name);
1549		LOGCMD(*mode == 'w' ? "put" : "append", name);
1550		return;
1551	}
1552	byte_count = -1;
1553	if (restart_point) {
1554		if (type == TYPE_A) {
1555			off_t i, n;
1556			int c;
1557
1558			n = restart_point;
1559			i = 0;
1560			while (i++ < n) {
1561				if ((c=getc(fout)) == EOF) {
1562					perror_reply(550, name);
1563					goto done;
1564				}
1565				if (c == '\n')
1566					i++;
1567			}
1568			/*
1569			 * We must do this seek to "current" position
1570			 * because we are changing from reading to
1571			 * writing.
1572			 */
1573			if (fseeko(fout, (off_t)0, SEEK_CUR) < 0) {
1574				perror_reply(550, name);
1575				goto done;
1576			}
1577		} else if (lseek(fileno(fout), restart_point, L_SET) < 0) {
1578			perror_reply(550, name);
1579			goto done;
1580		}
1581	}
1582	din = dataconn(name, (off_t)-1, "r");
1583	if (din == NULL)
1584		goto done;
1585	if (receive_data(din, fout) == 0) {
1586		if (unique)
1587			reply(226, "Transfer complete (unique file name:%s).",
1588			    name);
1589		else
1590			reply(226, "Transfer complete.");
1591	}
1592	(void) fclose(din);
1593	data = -1;
1594	pdata = -1;
1595done:
1596	LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count);
1597	(*closefunc)(fout);
1598}
1599
1600static FILE *
1601getdatasock(mode)
1602	char *mode;
1603{
1604	int on = 1, s, t, tries;
1605
1606	if (data >= 0)
1607		return (fdopen(data, mode));
1608	(void) seteuid((uid_t)0);
1609
1610	s = socket(data_dest.su_family, SOCK_STREAM, 0);
1611	if (s < 0)
1612		goto bad;
1613	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
1614	    (char *) &on, sizeof(on)) < 0)
1615		goto bad;
1616	/* anchor socket to avoid multi-homing problems */
1617	data_source = ctrl_addr;
1618	data_source.su_port = htons(20); /* ftp-data port */
1619	for (tries = 1; ; tries++) {
1620		if (bind(s, (struct sockaddr *)&data_source,
1621		    data_source.su_len) >= 0)
1622			break;
1623		if (errno != EADDRINUSE || tries > 10)
1624			goto bad;
1625		sleep(tries);
1626	}
1627	(void) seteuid((uid_t)pw->pw_uid);
1628#ifdef IP_TOS
1629	if (data_source.su_family == AF_INET)
1630      {
1631	on = IPTOS_THROUGHPUT;
1632	if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
1633		syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
1634      }
1635#endif
1636#ifdef TCP_NOPUSH
1637	/*
1638	 * Turn off push flag to keep sender TCP from sending short packets
1639	 * at the boundaries of each write().  Should probably do a SO_SNDBUF
1640	 * to set the send buffer size as well, but that may not be desirable
1641	 * in heavy-load situations.
1642	 */
1643	on = 1;
1644	if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, (char *)&on, sizeof on) < 0)
1645		syslog(LOG_WARNING, "setsockopt (TCP_NOPUSH): %m");
1646#endif
1647#ifdef SO_SNDBUF
1648	on = 65536;
1649	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&on, sizeof on) < 0)
1650		syslog(LOG_WARNING, "setsockopt (SO_SNDBUF): %m");
1651#endif
1652
1653	return (fdopen(s, mode));
1654bad:
1655	/* Return the real value of errno (close may change it) */
1656	t = errno;
1657	(void) seteuid((uid_t)pw->pw_uid);
1658	(void) close(s);
1659	errno = t;
1660	return (NULL);
1661}
1662
1663static FILE *
1664dataconn(name, size, mode)
1665	char *name;
1666	off_t size;
1667	char *mode;
1668{
1669	char sizebuf[32];
1670	FILE *file;
1671	int retry = 0, tos;
1672
1673	file_size = size;
1674	byte_count = 0;
1675	if (size != (off_t) -1)
1676		(void) snprintf(sizebuf, sizeof(sizebuf), " (%qd bytes)", size);
1677	else
1678		*sizebuf = '\0';
1679	if (pdata >= 0) {
1680		union sockunion from;
1681		int flags;
1682		int s, fromlen = ctrl_addr.su_len;
1683		struct timeval timeout;
1684		fd_set set;
1685
1686		FD_ZERO(&set);
1687		FD_SET(pdata, &set);
1688
1689		timeout.tv_usec = 0;
1690		timeout.tv_sec = 120;
1691
1692		/*
1693		 * Granted a socket is in the blocking I/O mode,
1694		 * accept() will block after a successful select()
1695		 * if the selected connection dies in between.
1696		 * Therefore set the non-blocking I/O flag here.
1697		 */
1698		if ((flags = fcntl(pdata, F_GETFL, 0)) == -1 ||
1699		    fcntl(pdata, F_SETFL, flags | O_NONBLOCK) == -1)
1700			goto pdata_err;
1701		if (select(pdata+1, &set, (fd_set *) 0, (fd_set *) 0, &timeout) <= 0 ||
1702		    (s = accept(pdata, (struct sockaddr *) &from, &fromlen)) < 0)
1703			goto pdata_err;
1704		(void) close(pdata);
1705		pdata = s;
1706		/*
1707		 * Unset the blocking I/O flag on the child socket
1708		 * again so stdio can work on it.
1709		 */
1710		if ((flags = fcntl(pdata, F_GETFL, 0)) == -1 ||
1711		    fcntl(pdata, F_SETFL, flags & ~O_NONBLOCK) == -1)
1712			goto pdata_err;
1713#ifdef IP_TOS
1714		if (from.su_family == AF_INET)
1715	      {
1716		tos = IPTOS_THROUGHPUT;
1717		(void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos,
1718		    sizeof(int));
1719	      }
1720#endif
1721		reply(150, "Opening %s mode data connection for '%s'%s.",
1722		     type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1723		return (fdopen(pdata, mode));
1724pdata_err:
1725		reply(425, "Can't open data connection.");
1726		(void) close(pdata);
1727		pdata = -1;
1728		return (NULL);
1729	}
1730	if (data >= 0) {
1731		reply(125, "Using existing data connection for '%s'%s.",
1732		    name, sizebuf);
1733		usedefault = 1;
1734		return (fdopen(data, mode));
1735	}
1736	if (usedefault)
1737		data_dest = his_addr;
1738	usedefault = 1;
1739	file = getdatasock(mode);
1740	if (file == NULL) {
1741		char hostbuf[BUFSIZ], portbuf[BUFSIZ];
1742		getnameinfo((struct sockaddr *)&data_source,
1743			data_source.su_len, hostbuf, sizeof(hostbuf) - 1,
1744			portbuf, sizeof(portbuf),
1745			NI_NUMERICHOST|NI_NUMERICSERV|NI_WITHSCOPEID);
1746		reply(425, "Can't create data socket (%s,%s): %s.",
1747			hostbuf, portbuf, strerror(errno));
1748		return (NULL);
1749	}
1750	data = fileno(file);
1751	while (connect(data, (struct sockaddr *)&data_dest,
1752	    data_dest.su_len) < 0) {
1753		if (errno == EADDRINUSE && retry < swaitmax) {
1754			sleep((unsigned) swaitint);
1755			retry += swaitint;
1756			continue;
1757		}
1758		perror_reply(425, "Can't build data connection");
1759		(void) fclose(file);
1760		data = -1;
1761		return (NULL);
1762	}
1763	reply(150, "Opening %s mode data connection for '%s'%s.",
1764	     type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1765	return (file);
1766}
1767
1768/*
1769 * Tranfer the contents of "instr" to "outstr" peer using the appropriate
1770 * encapsulation of the data subject to Mode, Structure, and Type.
1771 *
1772 * NB: Form isn't handled.
1773 */
1774static void
1775send_data(instr, outstr, blksize, filesize, isreg)
1776	FILE *instr, *outstr;
1777	off_t blksize;
1778	off_t filesize;
1779	int isreg;
1780{
1781	int c, filefd, netfd;
1782	char *buf;
1783	size_t len;
1784	off_t cnt;
1785
1786	transflag++;
1787	if (setjmp(urgcatch)) {
1788		transflag = 0;
1789		return;
1790	}
1791	switch (type) {
1792
1793	case TYPE_A:
1794		while ((c = getc(instr)) != EOF) {
1795			byte_count++;
1796			if (c == '\n') {
1797				if (ferror(outstr))
1798					goto data_err;
1799				(void) putc('\r', outstr);
1800			}
1801			(void) putc(c, outstr);
1802		}
1803		fflush(outstr);
1804		transflag = 0;
1805		if (ferror(instr))
1806			goto file_err;
1807		if (ferror(outstr))
1808			goto data_err;
1809		reply(226, "Transfer complete.");
1810		return;
1811
1812	case TYPE_I:
1813	case TYPE_L:
1814		/*
1815		 * isreg is only set if we are not doing restart and we
1816		 * are sending a regular file
1817		 */
1818		netfd = fileno(outstr);
1819		filefd = fileno(instr);
1820
1821		if (isreg) {
1822
1823			off_t offset;
1824			int err;
1825
1826			len = filesize;
1827			err = cnt = offset = 0;
1828
1829			while (err != -1 && cnt < filesize) {
1830				err = sendfile(filefd, netfd, offset, len,
1831					(struct sf_hdtr *) NULL, &cnt, 0);
1832				byte_count += cnt;
1833				offset += cnt;
1834				len -= cnt;
1835
1836				if (err == -1) {
1837					if (!cnt)
1838						goto oldway;
1839
1840					goto data_err;
1841				}
1842			}
1843
1844			reply(226, "Transfer complete.");
1845			return;
1846		}
1847
1848oldway:
1849		if ((buf = malloc((u_int)blksize)) == NULL) {
1850			transflag = 0;
1851			perror_reply(451, "Local resource failure: malloc");
1852			return;
1853		}
1854
1855		while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 &&
1856		    write(netfd, buf, cnt) == cnt)
1857			byte_count += cnt;
1858		transflag = 0;
1859		(void)free(buf);
1860		if (cnt != 0) {
1861			if (cnt < 0)
1862				goto file_err;
1863			goto data_err;
1864		}
1865		reply(226, "Transfer complete.");
1866		return;
1867	default:
1868		transflag = 0;
1869		reply(550, "Unimplemented TYPE %d in send_data", type);
1870		return;
1871	}
1872
1873data_err:
1874	transflag = 0;
1875	perror_reply(426, "Data connection");
1876	return;
1877
1878file_err:
1879	transflag = 0;
1880	perror_reply(551, "Error on input file");
1881}
1882
1883/*
1884 * Transfer data from peer to "outstr" using the appropriate encapulation of
1885 * the data subject to Mode, Structure, and Type.
1886 *
1887 * N.B.: Form isn't handled.
1888 */
1889static int
1890receive_data(instr, outstr)
1891	FILE *instr, *outstr;
1892{
1893	int c;
1894	int cnt, bare_lfs;
1895	char buf[BUFSIZ];
1896
1897	transflag++;
1898	if (setjmp(urgcatch)) {
1899		transflag = 0;
1900		return (-1);
1901	}
1902
1903	bare_lfs = 0;
1904
1905	switch (type) {
1906
1907	case TYPE_I:
1908	case TYPE_L:
1909		while ((cnt = read(fileno(instr), buf, sizeof(buf))) > 0) {
1910			if (write(fileno(outstr), buf, cnt) != cnt)
1911				goto file_err;
1912			byte_count += cnt;
1913		}
1914		if (cnt < 0)
1915			goto data_err;
1916		transflag = 0;
1917		return (0);
1918
1919	case TYPE_E:
1920		reply(553, "TYPE E not implemented.");
1921		transflag = 0;
1922		return (-1);
1923
1924	case TYPE_A:
1925		while ((c = getc(instr)) != EOF) {
1926			byte_count++;
1927			if (c == '\n')
1928				bare_lfs++;
1929			while (c == '\r') {
1930				if (ferror(outstr))
1931					goto data_err;
1932				if ((c = getc(instr)) != '\n') {
1933					(void) putc ('\r', outstr);
1934					if (c == '\0' || c == EOF)
1935						goto contin2;
1936				}
1937			}
1938			(void) putc(c, outstr);
1939	contin2:	;
1940		}
1941		fflush(outstr);
1942		if (ferror(instr))
1943			goto data_err;
1944		if (ferror(outstr))
1945			goto file_err;
1946		transflag = 0;
1947		if (bare_lfs) {
1948			lreply(226,
1949		"WARNING! %d bare linefeeds received in ASCII mode",
1950			    bare_lfs);
1951		(void)printf("   File may not have transferred correctly.\r\n");
1952		}
1953		return (0);
1954	default:
1955		reply(550, "Unimplemented TYPE %d in receive_data", type);
1956		transflag = 0;
1957		return (-1);
1958	}
1959
1960data_err:
1961	transflag = 0;
1962	perror_reply(426, "Data Connection");
1963	return (-1);
1964
1965file_err:
1966	transflag = 0;
1967	perror_reply(452, "Error writing file");
1968	return (-1);
1969}
1970
1971void
1972statfilecmd(filename)
1973	char *filename;
1974{
1975	FILE *fin;
1976	int c;
1977	char line[LINE_MAX];
1978
1979	(void)snprintf(line, sizeof(line), _PATH_LS " -lgA %s", filename);
1980	fin = ftpd_popen(line, "r");
1981	lreply(211, "status of %s:", filename);
1982	while ((c = getc(fin)) != EOF) {
1983		if (c == '\n') {
1984			if (ferror(stdout)){
1985				perror_reply(421, "control connection");
1986				(void) ftpd_pclose(fin);
1987				dologout(1);
1988				/* NOTREACHED */
1989			}
1990			if (ferror(fin)) {
1991				perror_reply(551, filename);
1992				(void) ftpd_pclose(fin);
1993				return;
1994			}
1995			(void) putc('\r', stdout);
1996		}
1997		(void) putc(c, stdout);
1998	}
1999	(void) ftpd_pclose(fin);
2000	reply(211, "End of Status");
2001}
2002
2003void
2004statcmd()
2005{
2006	union sockunion *su;
2007	u_char *a, *p;
2008	char hname[INET6_ADDRSTRLEN];
2009	int ispassive;
2010
2011	lreply(211, "%s FTP server status:", hostname, version);
2012	printf("     %s\r\n", version);
2013	printf("     Connected to %s", remotehost);
2014	if (!getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len,
2015			 hname, sizeof(hname) - 1, NULL, 0,
2016			 NI_NUMERICHOST|NI_WITHSCOPEID)) {
2017		if (strcmp(hname, remotehost) != 0)
2018			printf(" (%s)", hname);
2019	}
2020	printf("\r\n");
2021	if (logged_in) {
2022		if (guest)
2023			printf("     Logged in anonymously\r\n");
2024		else
2025			printf("     Logged in as %s\r\n", pw->pw_name);
2026	} else if (askpasswd)
2027		printf("     Waiting for password\r\n");
2028	else
2029		printf("     Waiting for user name\r\n");
2030	printf("     TYPE: %s", typenames[type]);
2031	if (type == TYPE_A || type == TYPE_E)
2032		printf(", FORM: %s", formnames[form]);
2033	if (type == TYPE_L)
2034#if NBBY == 8
2035		printf(" %d", NBBY);
2036#else
2037		printf(" %d", bytesize);	/* need definition! */
2038#endif
2039	printf("; STRUcture: %s; transfer MODE: %s\r\n",
2040	    strunames[stru], modenames[mode]);
2041	if (data != -1)
2042		printf("     Data connection open\r\n");
2043	else if (pdata != -1) {
2044		ispassive = 1;
2045		su = &pasv_addr;
2046		goto printaddr;
2047	} else if (usedefault == 0) {
2048		ispassive = 0;
2049		su = &data_dest;
2050printaddr:
2051#define UC(b) (((int) b) & 0xff)
2052		if (epsvall) {
2053			printf("     EPSV only mode (EPSV ALL)\r\n");
2054			goto epsvonly;
2055		}
2056
2057		/* PORT/PASV */
2058		if (su->su_family == AF_INET) {
2059			a = (u_char *) &su->su_sin.sin_addr;
2060			p = (u_char *) &su->su_sin.sin_port;
2061			printf("     %s (%d,%d,%d,%d,%d,%d)\r\n",
2062				ispassive ? "PASV" : "PORT",
2063				UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
2064				UC(p[0]), UC(p[1]));
2065		}
2066
2067		/* LPRT/LPSV */
2068	    {
2069		int alen, af, i;
2070
2071		switch (su->su_family) {
2072		case AF_INET:
2073			a = (u_char *) &su->su_sin.sin_addr;
2074			p = (u_char *) &su->su_sin.sin_port;
2075			alen = sizeof(su->su_sin.sin_addr);
2076			af = 4;
2077			break;
2078		case AF_INET6:
2079			a = (u_char *) &su->su_sin6.sin6_addr;
2080			p = (u_char *) &su->su_sin6.sin6_port;
2081			alen = sizeof(su->su_sin6.sin6_addr);
2082			af = 6;
2083			break;
2084		default:
2085			af = 0;
2086			break;
2087		}
2088		if (af) {
2089			printf("     %s (%d,%d,", ispassive ? "LPSV" : "LPRT",
2090				af, alen);
2091			for (i = 0; i < alen; i++)
2092				printf("%d,", UC(a[i]));
2093			printf("%d,%d,%d)\r\n", 2, UC(p[0]), UC(p[1]));
2094		}
2095	    }
2096
2097epsvonly:;
2098		/* EPRT/EPSV */
2099	    {
2100		int af;
2101
2102		switch (su->su_family) {
2103		case AF_INET:
2104			af = 1;
2105			break;
2106		case AF_INET6:
2107			af = 2;
2108			break;
2109		default:
2110			af = 0;
2111			break;
2112		}
2113		if (af) {
2114			if (!getnameinfo((struct sockaddr *)su, su->su_len,
2115					hname, sizeof(hname) - 1, NULL, 0,
2116					NI_NUMERICHOST)) {
2117				printf("     %s |%d|%s|%d|\r\n",
2118					ispassive ? "EPSV" : "EPRT",
2119					af, hname, htons(su->su_port));
2120			}
2121		}
2122	    }
2123#undef UC
2124	} else
2125		printf("     No data connection\r\n");
2126	reply(211, "End of status");
2127}
2128
2129void
2130fatalerror(s)
2131	char *s;
2132{
2133
2134	reply(451, "Error in server: %s\n", s);
2135	reply(221, "Closing connection due to server error.");
2136	dologout(0);
2137	/* NOTREACHED */
2138}
2139
2140void
2141#if __STDC__
2142reply(int n, const char *fmt, ...)
2143#else
2144reply(n, fmt, va_alist)
2145	int n;
2146	char *fmt;
2147        va_dcl
2148#endif
2149{
2150	va_list ap;
2151#if __STDC__
2152	va_start(ap, fmt);
2153#else
2154	va_start(ap);
2155#endif
2156	(void)printf("%d ", n);
2157	(void)vprintf(fmt, ap);
2158	(void)printf("\r\n");
2159	(void)fflush(stdout);
2160	if (ftpdebug) {
2161		syslog(LOG_DEBUG, "<--- %d ", n);
2162		vsyslog(LOG_DEBUG, fmt, ap);
2163	}
2164}
2165
2166void
2167#if __STDC__
2168lreply(int n, const char *fmt, ...)
2169#else
2170lreply(n, fmt, va_alist)
2171	int n;
2172	char *fmt;
2173        va_dcl
2174#endif
2175{
2176	va_list ap;
2177#if __STDC__
2178	va_start(ap, fmt);
2179#else
2180	va_start(ap);
2181#endif
2182	(void)printf("%d- ", n);
2183	(void)vprintf(fmt, ap);
2184	(void)printf("\r\n");
2185	(void)fflush(stdout);
2186	if (ftpdebug) {
2187		syslog(LOG_DEBUG, "<--- %d- ", n);
2188		vsyslog(LOG_DEBUG, fmt, ap);
2189	}
2190}
2191
2192static void
2193ack(s)
2194	char *s;
2195{
2196
2197	reply(250, "%s command successful.", s);
2198}
2199
2200void
2201nack(s)
2202	char *s;
2203{
2204
2205	reply(502, "%s command not implemented.", s);
2206}
2207
2208/* ARGSUSED */
2209void
2210yyerror(s)
2211	char *s;
2212{
2213	char *cp;
2214
2215	if ((cp = strchr(cbuf,'\n')))
2216		*cp = '\0';
2217	reply(500, "'%s': command not understood.", cbuf);
2218}
2219
2220void
2221delete(name)
2222	char *name;
2223{
2224	struct stat st;
2225
2226	LOGCMD("delete", name);
2227	if (stat(name, &st) < 0) {
2228		perror_reply(550, name);
2229		return;
2230	}
2231	if ((st.st_mode&S_IFMT) == S_IFDIR) {
2232		if (rmdir(name) < 0) {
2233			perror_reply(550, name);
2234			return;
2235		}
2236		goto done;
2237	}
2238	if (unlink(name) < 0) {
2239		perror_reply(550, name);
2240		return;
2241	}
2242done:
2243	ack("DELE");
2244}
2245
2246void
2247cwd(path)
2248	char *path;
2249{
2250
2251	if (chdir(path) < 0)
2252		perror_reply(550, path);
2253	else
2254		ack("CWD");
2255}
2256
2257void
2258makedir(name)
2259	char *name;
2260{
2261
2262	LOGCMD("mkdir", name);
2263	if (mkdir(name, 0777) < 0)
2264		perror_reply(550, name);
2265	else
2266		reply(257, "MKD command successful.");
2267}
2268
2269void
2270removedir(name)
2271	char *name;
2272{
2273
2274	LOGCMD("rmdir", name);
2275	if (rmdir(name) < 0)
2276		perror_reply(550, name);
2277	else
2278		ack("RMD");
2279}
2280
2281void
2282pwd()
2283{
2284	char path[MAXPATHLEN + 1];
2285
2286	if (getwd(path) == (char *)NULL)
2287		reply(550, "%s.", path);
2288	else
2289		reply(257, "\"%s\" is current directory.", path);
2290}
2291
2292char *
2293renamefrom(name)
2294	char *name;
2295{
2296	struct stat st;
2297
2298	if (stat(name, &st) < 0) {
2299		perror_reply(550, name);
2300		return ((char *)0);
2301	}
2302	reply(350, "File exists, ready for destination name");
2303	return (name);
2304}
2305
2306void
2307renamecmd(from, to)
2308	char *from, *to;
2309{
2310	struct stat st;
2311
2312	LOGCMD2("rename", from, to);
2313
2314	if (guest && (stat(to, &st) == 0)) {
2315		reply(550, "%s: permission denied", to);
2316		return;
2317	}
2318
2319	if (rename(from, to) < 0)
2320		perror_reply(550, "rename");
2321	else
2322		ack("RNTO");
2323}
2324
2325static void
2326dolog(who)
2327	struct sockaddr *who;
2328{
2329	int error;
2330
2331	realhostname_sa(remotehost, sizeof(remotehost) - 1, who, who->sa_len);
2332
2333#ifdef SETPROCTITLE
2334#ifdef VIRTUAL_HOSTING
2335	if (thishost != firsthost)
2336		snprintf(proctitle, sizeof(proctitle), "%s: connected (to %s)",
2337			 remotehost, hostname);
2338	else
2339#endif
2340		snprintf(proctitle, sizeof(proctitle), "%s: connected",
2341			 remotehost);
2342	setproctitle("%s", proctitle);
2343#endif /* SETPROCTITLE */
2344
2345	if (logging) {
2346#ifdef VIRTUAL_HOSTING
2347		if (thishost != firsthost)
2348			syslog(LOG_INFO, "connection from %s (to %s)",
2349			       remotehost, hostname);
2350		else
2351#endif
2352		{
2353			char	who_name[MAXHOSTNAMELEN];
2354
2355			error = getnameinfo(who, who->sa_len,
2356					    who_name, sizeof(who_name) - 1,
2357					    NULL, 0,
2358					    NI_NUMERICHOST|NI_WITHSCOPEID);
2359			syslog(LOG_INFO, "connection from %s (%s)", remotehost,
2360			       error == 0 ? who_name : "");
2361		}
2362	}
2363}
2364
2365/*
2366 * Record logout in wtmp file
2367 * and exit with supplied status.
2368 */
2369void
2370dologout(status)
2371	int status;
2372{
2373	/*
2374	 * Prevent reception of SIGURG from resulting in a resumption
2375	 * back to the main program loop.
2376	 */
2377	transflag = 0;
2378
2379	if (logged_in) {
2380		(void) seteuid((uid_t)0);
2381		ftpd_logwtmp(ttyline, "", "");
2382	}
2383	/* beware of flushing buffers after a SIGPIPE */
2384	_exit(status);
2385}
2386
2387static void
2388myoob(signo)
2389	int signo;
2390{
2391	char *cp;
2392
2393	/* only process if transfer occurring */
2394	if (!transflag)
2395		return;
2396	cp = tmpline;
2397	if (getline(cp, 7, stdin) == NULL) {
2398		reply(221, "You could at least say goodbye.");
2399		dologout(0);
2400	}
2401	upper(cp);
2402	if (strcmp(cp, "ABOR\r\n") == 0) {
2403		tmpline[0] = '\0';
2404		reply(426, "Transfer aborted. Data connection closed.");
2405		reply(226, "Abort successful");
2406		longjmp(urgcatch, 1);
2407	}
2408	if (strcmp(cp, "STAT\r\n") == 0) {
2409		tmpline[0] = '\0';
2410		if (file_size != (off_t) -1)
2411			reply(213, "Status: %qd of %qd bytes transferred",
2412			    byte_count, file_size);
2413		else
2414			reply(213, "Status: %qd bytes transferred", byte_count);
2415	}
2416}
2417
2418/*
2419 * Note: a response of 425 is not mentioned as a possible response to
2420 *	the PASV command in RFC959. However, it has been blessed as
2421 *	a legitimate response by Jon Postel in a telephone conversation
2422 *	with Rick Adams on 25 Jan 89.
2423 */
2424void
2425passive()
2426{
2427	int len;
2428	char *p, *a;
2429
2430	if (pdata >= 0)		/* close old port if one set */
2431		close(pdata);
2432
2433	pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0);
2434	if (pdata < 0) {
2435		perror_reply(425, "Can't open passive connection");
2436		return;
2437	}
2438
2439	(void) seteuid((uid_t)0);
2440
2441#ifdef IP_PORTRANGE
2442	if (ctrl_addr.su_family == AF_INET) {
2443	    int on = restricted_data_ports ? IP_PORTRANGE_HIGH
2444					   : IP_PORTRANGE_DEFAULT;
2445
2446	    if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2447			    (char *)&on, sizeof(on)) < 0)
2448		    goto pasv_error;
2449	}
2450#endif
2451#ifdef IPV6_PORTRANGE
2452	if (ctrl_addr.su_family == AF_INET6) {
2453	    int on = restricted_data_ports ? IPV6_PORTRANGE_HIGH
2454					   : IPV6_PORTRANGE_DEFAULT;
2455
2456	    if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE,
2457			    (char *)&on, sizeof(on)) < 0)
2458		    goto pasv_error;
2459	}
2460#endif
2461
2462	pasv_addr = ctrl_addr;
2463	pasv_addr.su_port = 0;
2464	if (bind(pdata, (struct sockaddr *)&pasv_addr, pasv_addr.su_len) < 0)
2465		goto pasv_error;
2466
2467	(void) seteuid((uid_t)pw->pw_uid);
2468
2469	len = sizeof(pasv_addr);
2470	if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
2471		goto pasv_error;
2472	if (listen(pdata, 1) < 0)
2473		goto pasv_error;
2474	if (pasv_addr.su_family == AF_INET)
2475		a = (char *) &pasv_addr.su_sin.sin_addr;
2476	else if (pasv_addr.su_family == AF_INET6 &&
2477		 IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr))
2478		a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12];
2479	else
2480		goto pasv_error;
2481
2482	p = (char *) &pasv_addr.su_port;
2483
2484#define UC(b) (((int) b) & 0xff)
2485
2486	reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]),
2487		UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
2488	return;
2489
2490pasv_error:
2491	(void) seteuid((uid_t)pw->pw_uid);
2492	(void) close(pdata);
2493	pdata = -1;
2494	perror_reply(425, "Can't open passive connection");
2495	return;
2496}
2497
2498/*
2499 * Long Passive defined in RFC 1639.
2500 *     228 Entering Long Passive Mode
2501 *         (af, hal, h1, h2, h3,..., pal, p1, p2...)
2502 */
2503
2504void
2505long_passive(cmd, pf)
2506	char *cmd;
2507	int pf;
2508{
2509	int len;
2510	char *p, *a;
2511
2512	if (pdata >= 0)		/* close old port if one set */
2513		close(pdata);
2514
2515	if (pf != PF_UNSPEC) {
2516		if (ctrl_addr.su_family != pf) {
2517			switch (ctrl_addr.su_family) {
2518			case AF_INET:
2519				pf = 1;
2520				break;
2521			case AF_INET6:
2522				pf = 2;
2523				break;
2524			default:
2525				pf = 0;
2526				break;
2527			}
2528			/*
2529			 * XXX
2530			 * only EPRT/EPSV ready clients will understand this
2531			 */
2532			if (strcmp(cmd, "EPSV") == 0 && pf) {
2533				reply(522, "Network protocol mismatch, "
2534					"use (%d)", pf);
2535			} else
2536				reply(501, "Network protocol mismatch"); /*XXX*/
2537
2538			return;
2539		}
2540	}
2541
2542	pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0);
2543	if (pdata < 0) {
2544		perror_reply(425, "Can't open passive connection");
2545		return;
2546	}
2547
2548	(void) seteuid((uid_t)0);
2549
2550	pasv_addr = ctrl_addr;
2551	pasv_addr.su_port = 0;
2552	len = pasv_addr.su_len;
2553
2554#ifdef IP_PORTRANGE
2555	if (ctrl_addr.su_family == AF_INET) {
2556	    int on = restricted_data_ports ? IP_PORTRANGE_HIGH
2557					   : IP_PORTRANGE_DEFAULT;
2558
2559	    if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2560			    (char *)&on, sizeof(on)) < 0)
2561		    goto pasv_error;
2562	}
2563#endif
2564#ifdef IPV6_PORTRANGE
2565	if (ctrl_addr.su_family == AF_INET6) {
2566	    int on = restricted_data_ports ? IPV6_PORTRANGE_HIGH
2567					   : IPV6_PORTRANGE_DEFAULT;
2568
2569	    if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE,
2570			    (char *)&on, sizeof(on)) < 0)
2571		    goto pasv_error;
2572	}
2573#endif
2574
2575	if (bind(pdata, (struct sockaddr *)&pasv_addr, len) < 0)
2576		goto pasv_error;
2577
2578	(void) seteuid((uid_t)pw->pw_uid);
2579
2580	if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
2581		goto pasv_error;
2582	if (listen(pdata, 1) < 0)
2583		goto pasv_error;
2584
2585#define UC(b) (((int) b) & 0xff)
2586
2587	if (strcmp(cmd, "LPSV") == 0) {
2588		p = (char *)&pasv_addr.su_port;
2589		switch (pasv_addr.su_family) {
2590		case AF_INET:
2591			a = (char *) &pasv_addr.su_sin.sin_addr;
2592		v4_reply:
2593			reply(228,
2594"Entering Long Passive Mode (%d,%d,%d,%d,%d,%d,%d,%d,%d)",
2595			      4, 4, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
2596			      2, UC(p[0]), UC(p[1]));
2597			return;
2598		case AF_INET6:
2599			if (IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr)) {
2600				a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12];
2601				goto v4_reply;
2602			}
2603			a = (char *) &pasv_addr.su_sin6.sin6_addr;
2604			reply(228,
2605"Entering Long Passive Mode "
2606"(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)",
2607			      6, 16, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
2608			      UC(a[4]), UC(a[5]), UC(a[6]), UC(a[7]),
2609			      UC(a[8]), UC(a[9]), UC(a[10]), UC(a[11]),
2610			      UC(a[12]), UC(a[13]), UC(a[14]), UC(a[15]),
2611			      2, UC(p[0]), UC(p[1]));
2612			return;
2613		}
2614	} else if (strcmp(cmd, "EPSV") == 0) {
2615		switch (pasv_addr.su_family) {
2616		case AF_INET:
2617		case AF_INET6:
2618			reply(229, "Entering Extended Passive Mode (|||%d|)",
2619				ntohs(pasv_addr.su_port));
2620			return;
2621		}
2622	} else {
2623		/* more proper error code? */
2624	}
2625
2626pasv_error:
2627	(void) seteuid((uid_t)pw->pw_uid);
2628	(void) close(pdata);
2629	pdata = -1;
2630	perror_reply(425, "Can't open passive connection");
2631	return;
2632}
2633
2634/*
2635 * Generate unique name for file with basename "local".
2636 * The file named "local" is already known to exist.
2637 * Generates failure reply on error.
2638 */
2639static char *
2640gunique(local)
2641	char *local;
2642{
2643	static char new[MAXPATHLEN];
2644	struct stat st;
2645	int count;
2646	char *cp;
2647
2648	cp = strrchr(local, '/');
2649	if (cp)
2650		*cp = '\0';
2651	if (stat(cp ? local : ".", &st) < 0) {
2652		perror_reply(553, cp ? local : ".");
2653		return ((char *) 0);
2654	}
2655	if (cp)
2656		*cp = '/';
2657	/* -4 is for the .nn<null> we put on the end below */
2658	(void) snprintf(new, sizeof(new) - 4, "%s", local);
2659	cp = new + strlen(new);
2660	*cp++ = '.';
2661	for (count = 1; count < 100; count++) {
2662		(void)sprintf(cp, "%d", count);
2663		if (stat(new, &st) < 0)
2664			return (new);
2665	}
2666	reply(452, "Unique file name cannot be created.");
2667	return (NULL);
2668}
2669
2670/*
2671 * Format and send reply containing system error number.
2672 */
2673void
2674perror_reply(code, string)
2675	int code;
2676	char *string;
2677{
2678
2679	reply(code, "%s: %s.", string, strerror(errno));
2680}
2681
2682static char *onefile[] = {
2683	"",
2684	0
2685};
2686
2687void
2688send_file_list(whichf)
2689	char *whichf;
2690{
2691	struct stat st;
2692	DIR *dirp = NULL;
2693	struct dirent *dir;
2694	FILE *dout = NULL;
2695	char **dirlist, *dirname;
2696	int simple = 0;
2697	int freeglob = 0;
2698	glob_t gl;
2699
2700	if (strpbrk(whichf, "~{[*?") != NULL) {
2701		int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
2702
2703		memset(&gl, 0, sizeof(gl));
2704		gl.gl_matchc = MAXGLOBARGS;
2705		flags |= GLOB_LIMIT;
2706		freeglob = 1;
2707		if (glob(whichf, flags, 0, &gl)) {
2708			reply(550, "not found");
2709			goto out;
2710		} else if (gl.gl_pathc == 0) {
2711			errno = ENOENT;
2712			perror_reply(550, whichf);
2713			goto out;
2714		}
2715		dirlist = gl.gl_pathv;
2716	} else {
2717		onefile[0] = whichf;
2718		dirlist = onefile;
2719		simple = 1;
2720	}
2721
2722	if (setjmp(urgcatch)) {
2723		transflag = 0;
2724		goto out;
2725	}
2726	while ((dirname = *dirlist++)) {
2727		if (stat(dirname, &st) < 0) {
2728			/*
2729			 * If user typed "ls -l", etc, and the client
2730			 * used NLST, do what the user meant.
2731			 */
2732			if (dirname[0] == '-' && *dirlist == NULL &&
2733			    transflag == 0) {
2734				retrieve(_PATH_LS " %s", dirname);
2735				goto out;
2736			}
2737			perror_reply(550, whichf);
2738			if (dout != NULL) {
2739				(void) fclose(dout);
2740				transflag = 0;
2741				data = -1;
2742				pdata = -1;
2743			}
2744			goto out;
2745		}
2746
2747		if (S_ISREG(st.st_mode)) {
2748			if (dout == NULL) {
2749				dout = dataconn("file list", (off_t)-1, "w");
2750				if (dout == NULL)
2751					goto out;
2752				transflag++;
2753			}
2754			fprintf(dout, "%s%s\n", dirname,
2755				type == TYPE_A ? "\r" : "");
2756			byte_count += strlen(dirname) + 1;
2757			continue;
2758		} else if (!S_ISDIR(st.st_mode))
2759			continue;
2760
2761		if ((dirp = opendir(dirname)) == NULL)
2762			continue;
2763
2764		while ((dir = readdir(dirp)) != NULL) {
2765			char nbuf[MAXPATHLEN];
2766
2767			if (dir->d_name[0] == '.' && dir->d_namlen == 1)
2768				continue;
2769			if (dir->d_name[0] == '.' && dir->d_name[1] == '.' &&
2770			    dir->d_namlen == 2)
2771				continue;
2772
2773			snprintf(nbuf, sizeof(nbuf),
2774				"%s/%s", dirname, dir->d_name);
2775
2776			/*
2777			 * We have to do a stat to insure it's
2778			 * not a directory or special file.
2779			 */
2780			if (simple || (stat(nbuf, &st) == 0 &&
2781			    S_ISREG(st.st_mode))) {
2782				if (dout == NULL) {
2783					dout = dataconn("file list", (off_t)-1,
2784						"w");
2785					if (dout == NULL)
2786						goto out;
2787					transflag++;
2788				}
2789				if (nbuf[0] == '.' && nbuf[1] == '/')
2790					fprintf(dout, "%s%s\n", &nbuf[2],
2791						type == TYPE_A ? "\r" : "");
2792				else
2793					fprintf(dout, "%s%s\n", nbuf,
2794						type == TYPE_A ? "\r" : "");
2795				byte_count += strlen(nbuf) + 1;
2796			}
2797		}
2798		(void) closedir(dirp);
2799	}
2800
2801	if (dout == NULL)
2802		reply(550, "No files found.");
2803	else if (ferror(dout) != 0)
2804		perror_reply(550, "Data connection");
2805	else
2806		reply(226, "Transfer complete.");
2807
2808	transflag = 0;
2809	if (dout != NULL)
2810		(void) fclose(dout);
2811	data = -1;
2812	pdata = -1;
2813out:
2814	if (freeglob) {
2815		freeglob = 0;
2816		globfree(&gl);
2817	}
2818}
2819
2820void
2821reapchild(signo)
2822	int signo;
2823{
2824	while (wait3(NULL, WNOHANG, NULL) > 0);
2825}
2826
2827#ifdef OLD_SETPROCTITLE
2828/*
2829 * Clobber argv so ps will show what we're doing.  (Stolen from sendmail.)
2830 * Warning, since this is usually started from inetd.conf, it often doesn't
2831 * have much of an environment or arglist to overwrite.
2832 */
2833void
2834#if __STDC__
2835setproctitle(const char *fmt, ...)
2836#else
2837setproctitle(fmt, va_alist)
2838	char *fmt;
2839        va_dcl
2840#endif
2841{
2842	int i;
2843	va_list ap;
2844	char *p, *bp, ch;
2845	char buf[LINE_MAX];
2846
2847#if __STDC__
2848	va_start(ap, fmt);
2849#else
2850	va_start(ap);
2851#endif
2852	(void)vsnprintf(buf, sizeof(buf), fmt, ap);
2853
2854	/* make ps print our process name */
2855	p = Argv[0];
2856	*p++ = '-';
2857
2858	i = strlen(buf);
2859	if (i > LastArgv - p - 2) {
2860		i = LastArgv - p - 2;
2861		buf[i] = '\0';
2862	}
2863	bp = buf;
2864	while (ch = *bp++)
2865		if (ch != '\n' && ch != '\r')
2866			*p++ = ch;
2867	while (p < LastArgv)
2868		*p++ = ' ';
2869}
2870#endif /* OLD_SETPROCTITLE */
2871
2872static void
2873logxfer(name, size, start)
2874	char *name;
2875	off_t size;
2876	time_t start;
2877{
2878	char buf[1024];
2879	char path[MAXPATHLEN + 1];
2880	time_t now;
2881
2882	if (statfd >= 0 && getwd(path) != NULL) {
2883		time(&now);
2884		snprintf(buf, sizeof(buf), "%.20s!%s!%s!%s/%s!%qd!%ld\n",
2885			ctime(&now)+4, ident, remotehost,
2886			path, name, (long long)size,
2887			(long)(now - start + (now == start)));
2888		write(statfd, buf, strlen(buf));
2889	}
2890}
2891