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