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