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