ftpd.c revision 132894
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 132894 2004-07-30 17:30:07Z 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	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(0);
1159	if (logged_in && dowtmp)
1160		ftpd_logwtmp(ttyline, "", NULL);
1161	pw = NULL;
1162#ifdef	LOGIN_CAP
1163	setusercontext(NULL, getpwuid(0), 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(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, 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(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
1814	s = socket(data_dest.su_family, SOCK_STREAM, 0);
1815	if (s < 0)
1816		goto bad;
1817	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
1818		syslog(LOG_WARNING, "data setsockopt (SO_REUSEADDR): %m");
1819	/* anchor socket to avoid multi-homing problems */
1820	data_source = ctrl_addr;
1821	data_source.su_port = htons(dataport);
1822	(void) seteuid(0);
1823	for (tries = 1; ; tries++) {
1824		/*
1825		 * We should loop here since it's possible that
1826		 * another ftpd instance has passed this point and is
1827		 * trying to open a data connection in active mode now.
1828		 * Until the other connection is opened, we'll be getting
1829		 * EADDRINUSE because no SOCK_STREAM sockets in the system
1830		 * can share both local and remote addresses, localIP:20
1831		 * and *:* in this case.
1832		 */
1833		if (bind(s, (struct sockaddr *)&data_source,
1834		    data_source.su_len) >= 0)
1835			break;
1836		if (errno != EADDRINUSE || tries > 10)
1837			goto bad;
1838		sleep(tries);
1839	}
1840	(void) seteuid(pw->pw_uid);
1841#ifdef IP_TOS
1842	if (data_source.su_family == AF_INET)
1843      {
1844	on = IPTOS_THROUGHPUT;
1845	if (setsockopt(s, IPPROTO_IP, IP_TOS, &on, sizeof(int)) < 0)
1846		syslog(LOG_WARNING, "data setsockopt (IP_TOS): %m");
1847      }
1848#endif
1849#ifdef TCP_NOPUSH
1850	/*
1851	 * Turn off push flag to keep sender TCP from sending short packets
1852	 * at the boundaries of each write().  Should probably do a SO_SNDBUF
1853	 * to set the send buffer size as well, but that may not be desirable
1854	 * in heavy-load situations.
1855	 */
1856	on = 1;
1857	if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, &on, sizeof on) < 0)
1858		syslog(LOG_WARNING, "data setsockopt (TCP_NOPUSH): %m");
1859#endif
1860#ifdef SO_SNDBUF
1861	on = 65536;
1862	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &on, sizeof on) < 0)
1863		syslog(LOG_WARNING, "data setsockopt (SO_SNDBUF): %m");
1864#endif
1865
1866	return (fdopen(s, mode));
1867bad:
1868	/* Return the real value of errno (close may change it) */
1869	t = errno;
1870	(void) seteuid(pw->pw_uid);
1871	(void) close(s);
1872	errno = t;
1873	return (NULL);
1874}
1875
1876static FILE *
1877dataconn(char *name, off_t size, char *mode)
1878{
1879	char sizebuf[32];
1880	FILE *file;
1881	int retry = 0, tos, conerrno;
1882
1883	file_size = size;
1884	byte_count = 0;
1885	if (size != (off_t) -1)
1886		(void) snprintf(sizebuf, sizeof(sizebuf), " (%qd bytes)", size);
1887	else
1888		*sizebuf = '\0';
1889	if (pdata >= 0) {
1890		union sockunion from;
1891		int flags;
1892		int s, fromlen = ctrl_addr.su_len;
1893		struct timeval timeout;
1894		fd_set set;
1895
1896		FD_ZERO(&set);
1897		FD_SET(pdata, &set);
1898
1899		timeout.tv_usec = 0;
1900		timeout.tv_sec = 120;
1901
1902		/*
1903		 * Granted a socket is in the blocking I/O mode,
1904		 * accept() will block after a successful select()
1905		 * if the selected connection dies in between.
1906		 * Therefore set the non-blocking I/O flag here.
1907		 */
1908		if ((flags = fcntl(pdata, F_GETFL, 0)) == -1 ||
1909		    fcntl(pdata, F_SETFL, flags | O_NONBLOCK) == -1)
1910			goto pdata_err;
1911		if (select(pdata+1, &set, (fd_set *) 0, (fd_set *) 0, &timeout) <= 0 ||
1912		    (s = accept(pdata, (struct sockaddr *) &from, &fromlen)) < 0)
1913			goto pdata_err;
1914		(void) close(pdata);
1915		pdata = s;
1916		/*
1917		 * Unset the inherited non-blocking I/O flag
1918		 * on the child socket so stdio can work on it.
1919		 */
1920		if ((flags = fcntl(pdata, F_GETFL, 0)) == -1 ||
1921		    fcntl(pdata, F_SETFL, flags & ~O_NONBLOCK) == -1)
1922			goto pdata_err;
1923#ifdef IP_TOS
1924		if (from.su_family == AF_INET)
1925	      {
1926		tos = IPTOS_THROUGHPUT;
1927		if (setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(int)) < 0)
1928			syslog(LOG_WARNING, "pdata setsockopt (IP_TOS): %m");
1929	      }
1930#endif
1931		reply(150, "Opening %s mode data connection for '%s'%s.",
1932		     type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1933		return (fdopen(pdata, mode));
1934pdata_err:
1935		reply(425, "Can't open data connection.");
1936		(void) close(pdata);
1937		pdata = -1;
1938		return (NULL);
1939	}
1940	if (data >= 0) {
1941		reply(125, "Using existing data connection for '%s'%s.",
1942		    name, sizebuf);
1943		usedefault = 1;
1944		return (fdopen(data, mode));
1945	}
1946	if (usedefault)
1947		data_dest = his_addr;
1948	usedefault = 1;
1949	do {
1950		file = getdatasock(mode);
1951		if (file == NULL) {
1952			char hostbuf[BUFSIZ], portbuf[BUFSIZ];
1953			getnameinfo((struct sockaddr *)&data_source,
1954				data_source.su_len, hostbuf, sizeof(hostbuf) - 1,
1955				portbuf, sizeof(portbuf),
1956				NI_NUMERICHOST|NI_NUMERICSERV);
1957			reply(425, "Can't create data socket (%s,%s): %s.",
1958				hostbuf, portbuf, strerror(errno));
1959			return (NULL);
1960		}
1961		data = fileno(file);
1962		conerrno = 0;
1963		if (connect(data, (struct sockaddr *)&data_dest,
1964		    data_dest.su_len) == 0)
1965			break;
1966		conerrno = errno;
1967		(void) fclose(file);
1968		data = -1;
1969		if (conerrno == EADDRINUSE) {
1970			sleep((unsigned) swaitint);
1971			retry += swaitint;
1972		} else {
1973			break;
1974		}
1975	} while (retry <= swaitmax);
1976	if (conerrno != 0) {
1977		perror_reply(425, "Can't build data connection");
1978		return (NULL);
1979	}
1980	reply(150, "Opening %s mode data connection for '%s'%s.",
1981	     type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1982	return (file);
1983}
1984
1985/*
1986 * Tranfer the contents of "instr" to "outstr" peer using the appropriate
1987 * encapsulation of the data subject to Mode, Structure, and Type.
1988 *
1989 * NB: Form isn't handled.
1990 */
1991static int
1992send_data(FILE *instr, FILE *outstr, off_t blksize, off_t filesize, int isreg)
1993{
1994	int c, cp, filefd, netfd;
1995	char *buf;
1996	off_t cnt;
1997
1998	transflag++;
1999	switch (type) {
2000
2001	case TYPE_A:
2002		cp = '\0';
2003		while ((c = getc(instr)) != EOF) {
2004			if (recvurg)
2005				goto got_oob;
2006			byte_count++;
2007			if (c == '\n' && cp != '\r') {
2008				if (ferror(outstr))
2009					goto data_err;
2010				(void) putc('\r', outstr);
2011			}
2012			(void) putc(c, outstr);
2013			cp = c;
2014		}
2015		if (recvurg)
2016			goto got_oob;
2017		fflush(outstr);
2018		transflag = 0;
2019		if (ferror(instr))
2020			goto file_err;
2021		if (ferror(outstr))
2022			goto data_err;
2023		reply(226, "Transfer complete.");
2024		return (0);
2025
2026	case TYPE_I:
2027	case TYPE_L:
2028		/*
2029		 * isreg is only set if we are not doing restart and we
2030		 * are sending a regular file
2031		 */
2032		netfd = fileno(outstr);
2033		filefd = fileno(instr);
2034
2035		if (isreg) {
2036
2037			off_t offset;
2038			int err;
2039
2040			err = cnt = offset = 0;
2041
2042			while (err != -1 && filesize > 0) {
2043				err = sendfile(filefd, netfd, offset, 0,
2044					(struct sf_hdtr *) NULL, &cnt, 0);
2045				/*
2046				 * Calculate byte_count before OOB processing.
2047				 * It can be used in myoob() later.
2048				 */
2049				byte_count += cnt;
2050				if (recvurg)
2051					goto got_oob;
2052				offset += cnt;
2053				filesize -= cnt;
2054
2055				if (err == -1) {
2056					if (!cnt)
2057						goto oldway;
2058
2059					goto data_err;
2060				}
2061			}
2062
2063			transflag = 0;
2064			reply(226, "Transfer complete.");
2065			return (0);
2066		}
2067
2068oldway:
2069		if ((buf = malloc((u_int)blksize)) == NULL) {
2070			transflag = 0;
2071			perror_reply(451, "Local resource failure: malloc");
2072			return (-1);
2073		}
2074
2075		while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 &&
2076		    write(netfd, buf, cnt) == cnt)
2077			byte_count += cnt;
2078		transflag = 0;
2079		(void)free(buf);
2080		if (cnt != 0) {
2081			if (cnt < 0)
2082				goto file_err;
2083			goto data_err;
2084		}
2085		reply(226, "Transfer complete.");
2086		return (0);
2087	default:
2088		transflag = 0;
2089		reply(550, "Unimplemented TYPE %d in send_data", type);
2090		return (-1);
2091	}
2092
2093data_err:
2094	transflag = 0;
2095	perror_reply(426, "Data connection");
2096	return (-1);
2097
2098file_err:
2099	transflag = 0;
2100	perror_reply(551, "Error on input file");
2101	return (-1);
2102
2103got_oob:
2104	myoob();
2105	recvurg = 0;
2106	transflag = 0;
2107	return (-1);
2108}
2109
2110/*
2111 * Transfer data from peer to "outstr" using the appropriate encapulation of
2112 * the data subject to Mode, Structure, and Type.
2113 *
2114 * N.B.: Form isn't handled.
2115 */
2116static int
2117receive_data(FILE *instr, FILE *outstr)
2118{
2119	int c;
2120	int cnt, bare_lfs;
2121	char buf[BUFSIZ];
2122
2123	transflag++;
2124	bare_lfs = 0;
2125
2126	switch (type) {
2127
2128	case TYPE_I:
2129	case TYPE_L:
2130		while ((cnt = read(fileno(instr), buf, sizeof(buf))) > 0) {
2131			if (recvurg)
2132				goto got_oob;
2133			if (write(fileno(outstr), buf, cnt) != cnt)
2134				goto file_err;
2135			byte_count += cnt;
2136		}
2137		if (recvurg)
2138			goto got_oob;
2139		if (cnt < 0)
2140			goto data_err;
2141		transflag = 0;
2142		return (0);
2143
2144	case TYPE_E:
2145		reply(553, "TYPE E not implemented.");
2146		transflag = 0;
2147		return (-1);
2148
2149	case TYPE_A:
2150		while ((c = getc(instr)) != EOF) {
2151			if (recvurg)
2152				goto got_oob;
2153			byte_count++;
2154			if (c == '\n')
2155				bare_lfs++;
2156			while (c == '\r') {
2157				if (ferror(outstr))
2158					goto data_err;
2159				if ((c = getc(instr)) != '\n') {
2160					(void) putc ('\r', outstr);
2161					if (c == '\0' || c == EOF)
2162						goto contin2;
2163				}
2164			}
2165			(void) putc(c, outstr);
2166	contin2:	;
2167		}
2168		if (recvurg)
2169			goto got_oob;
2170		fflush(outstr);
2171		if (ferror(instr))
2172			goto data_err;
2173		if (ferror(outstr))
2174			goto file_err;
2175		transflag = 0;
2176		if (bare_lfs) {
2177			lreply(226,
2178		"WARNING! %d bare linefeeds received in ASCII mode",
2179			    bare_lfs);
2180		(void)printf("   File may not have transferred correctly.\r\n");
2181		}
2182		return (0);
2183	default:
2184		reply(550, "Unimplemented TYPE %d in receive_data", type);
2185		transflag = 0;
2186		return (-1);
2187	}
2188
2189data_err:
2190	transflag = 0;
2191	perror_reply(426, "Data Connection");
2192	return (-1);
2193
2194file_err:
2195	transflag = 0;
2196	perror_reply(452, "Error writing file");
2197	return (-1);
2198
2199got_oob:
2200	myoob();
2201	recvurg = 0;
2202	transflag = 0;
2203	return (-1);
2204}
2205
2206void
2207statfilecmd(char *filename)
2208{
2209	FILE *fin;
2210	int atstart;
2211	int c;
2212	char line[LINE_MAX];
2213
2214	(void)snprintf(line, sizeof(line), _PATH_LS " -lgA %s", filename);
2215	fin = ftpd_popen(line, "r");
2216	lreply(211, "status of %s:", filename);
2217	atstart = 1;
2218	while ((c = getc(fin)) != EOF) {
2219		if (c == '\n') {
2220			if (ferror(stdout)){
2221				perror_reply(421, "control connection");
2222				(void) ftpd_pclose(fin);
2223				dologout(1);
2224				/* NOTREACHED */
2225			}
2226			if (ferror(fin)) {
2227				perror_reply(551, filename);
2228				(void) ftpd_pclose(fin);
2229				return;
2230			}
2231			(void) putc('\r', stdout);
2232		}
2233		/*
2234		 * RFC 959 says neutral text should be prepended before
2235		 * a leading 3-digit number followed by whitespace, but
2236		 * many ftp clients can be confused by any leading digits,
2237		 * as a matter of fact.
2238		 */
2239		if (atstart && isdigit(c))
2240			(void) putc(' ', stdout);
2241		(void) putc(c, stdout);
2242		atstart = (c == '\n');
2243	}
2244	(void) ftpd_pclose(fin);
2245	reply(211, "End of Status");
2246}
2247
2248void
2249statcmd(void)
2250{
2251	union sockunion *su;
2252	u_char *a, *p;
2253	char hname[NI_MAXHOST];
2254	int ispassive;
2255
2256	if (hostinfo) {
2257		lreply(211, "%s FTP server status:", hostname);
2258		printf("     %s\r\n", version);
2259	} else
2260		lreply(211, "FTP server status:");
2261	printf("     Connected to %s", remotehost);
2262	if (!getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len,
2263			 hname, sizeof(hname) - 1, NULL, 0, NI_NUMERICHOST)) {
2264		if (strcmp(hname, remotehost) != 0)
2265			printf(" (%s)", hname);
2266	}
2267	printf("\r\n");
2268	if (logged_in) {
2269		if (guest)
2270			printf("     Logged in anonymously\r\n");
2271		else
2272			printf("     Logged in as %s\r\n", pw->pw_name);
2273	} else if (askpasswd)
2274		printf("     Waiting for password\r\n");
2275	else
2276		printf("     Waiting for user name\r\n");
2277	printf("     TYPE: %s", typenames[type]);
2278	if (type == TYPE_A || type == TYPE_E)
2279		printf(", FORM: %s", formnames[form]);
2280	if (type == TYPE_L)
2281#if CHAR_BIT == 8
2282		printf(" %d", CHAR_BIT);
2283#else
2284		printf(" %d", bytesize);	/* need definition! */
2285#endif
2286	printf("; STRUcture: %s; transfer MODE: %s\r\n",
2287	    strunames[stru], modenames[mode]);
2288	if (data != -1)
2289		printf("     Data connection open\r\n");
2290	else if (pdata != -1) {
2291		ispassive = 1;
2292		su = &pasv_addr;
2293		goto printaddr;
2294	} else if (usedefault == 0) {
2295		ispassive = 0;
2296		su = &data_dest;
2297printaddr:
2298#define UC(b) (((int) b) & 0xff)
2299		if (epsvall) {
2300			printf("     EPSV only mode (EPSV ALL)\r\n");
2301			goto epsvonly;
2302		}
2303
2304		/* PORT/PASV */
2305		if (su->su_family == AF_INET) {
2306			a = (u_char *) &su->su_sin.sin_addr;
2307			p = (u_char *) &su->su_sin.sin_port;
2308			printf("     %s (%d,%d,%d,%d,%d,%d)\r\n",
2309				ispassive ? "PASV" : "PORT",
2310				UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
2311				UC(p[0]), UC(p[1]));
2312		}
2313
2314		/* LPRT/LPSV */
2315	    {
2316		int alen, af, i;
2317
2318		switch (su->su_family) {
2319		case AF_INET:
2320			a = (u_char *) &su->su_sin.sin_addr;
2321			p = (u_char *) &su->su_sin.sin_port;
2322			alen = sizeof(su->su_sin.sin_addr);
2323			af = 4;
2324			break;
2325		case AF_INET6:
2326			a = (u_char *) &su->su_sin6.sin6_addr;
2327			p = (u_char *) &su->su_sin6.sin6_port;
2328			alen = sizeof(su->su_sin6.sin6_addr);
2329			af = 6;
2330			break;
2331		default:
2332			af = 0;
2333			break;
2334		}
2335		if (af) {
2336			printf("     %s (%d,%d,", ispassive ? "LPSV" : "LPRT",
2337				af, alen);
2338			for (i = 0; i < alen; i++)
2339				printf("%d,", UC(a[i]));
2340			printf("%d,%d,%d)\r\n", 2, UC(p[0]), UC(p[1]));
2341		}
2342	    }
2343
2344epsvonly:;
2345		/* EPRT/EPSV */
2346	    {
2347		int af;
2348
2349		switch (su->su_family) {
2350		case AF_INET:
2351			af = 1;
2352			break;
2353		case AF_INET6:
2354			af = 2;
2355			break;
2356		default:
2357			af = 0;
2358			break;
2359		}
2360		if (af) {
2361			union sockunion tmp;
2362
2363			tmp = *su;
2364			if (tmp.su_family == AF_INET6)
2365				tmp.su_sin6.sin6_scope_id = 0;
2366			if (!getnameinfo((struct sockaddr *)&tmp, tmp.su_len,
2367					hname, sizeof(hname) - 1, NULL, 0,
2368					NI_NUMERICHOST)) {
2369				printf("     %s |%d|%s|%d|\r\n",
2370					ispassive ? "EPSV" : "EPRT",
2371					af, hname, htons(tmp.su_port));
2372			}
2373		}
2374	    }
2375#undef UC
2376	} else
2377		printf("     No data connection\r\n");
2378	reply(211, "End of status");
2379}
2380
2381void
2382fatalerror(char *s)
2383{
2384
2385	reply(451, "Error in server: %s\n", s);
2386	reply(221, "Closing connection due to server error.");
2387	dologout(0);
2388	/* NOTREACHED */
2389}
2390
2391void
2392reply(int n, const char *fmt, ...)
2393{
2394	va_list ap;
2395
2396	(void)printf("%d ", n);
2397	va_start(ap, fmt);
2398	(void)vprintf(fmt, ap);
2399	va_end(ap);
2400	(void)printf("\r\n");
2401	(void)fflush(stdout);
2402	if (ftpdebug) {
2403		syslog(LOG_DEBUG, "<--- %d ", n);
2404		va_start(ap, fmt);
2405		vsyslog(LOG_DEBUG, fmt, ap);
2406		va_end(ap);
2407	}
2408}
2409
2410void
2411lreply(int n, const char *fmt, ...)
2412{
2413	va_list ap;
2414
2415	(void)printf("%d- ", n);
2416	va_start(ap, fmt);
2417	(void)vprintf(fmt, ap);
2418	va_end(ap);
2419	(void)printf("\r\n");
2420	(void)fflush(stdout);
2421	if (ftpdebug) {
2422		syslog(LOG_DEBUG, "<--- %d- ", n);
2423		va_start(ap, fmt);
2424		vsyslog(LOG_DEBUG, fmt, ap);
2425		va_end(ap);
2426	}
2427}
2428
2429static void
2430ack(char *s)
2431{
2432
2433	reply(250, "%s command successful.", s);
2434}
2435
2436void
2437nack(char *s)
2438{
2439
2440	reply(502, "%s command not implemented.", s);
2441}
2442
2443/* ARGSUSED */
2444void
2445yyerror(char *s)
2446{
2447	char *cp;
2448
2449	if ((cp = strchr(cbuf,'\n')))
2450		*cp = '\0';
2451	reply(500, "'%s': command not understood.", cbuf);
2452}
2453
2454void
2455delete(char *name)
2456{
2457	struct stat st;
2458
2459	LOGCMD("delete", name);
2460	if (lstat(name, &st) < 0) {
2461		perror_reply(550, name);
2462		return;
2463	}
2464	if ((st.st_mode&S_IFMT) == S_IFDIR) {
2465		if (rmdir(name) < 0) {
2466			perror_reply(550, name);
2467			return;
2468		}
2469		goto done;
2470	}
2471	if (guest && noguestmod) {
2472		reply(550, "Operation not permitted");
2473		return;
2474	}
2475	if (unlink(name) < 0) {
2476		perror_reply(550, name);
2477		return;
2478	}
2479done:
2480	ack("DELE");
2481}
2482
2483void
2484cwd(char *path)
2485{
2486
2487	if (chdir(path) < 0)
2488		perror_reply(550, path);
2489	else
2490		ack("CWD");
2491}
2492
2493void
2494makedir(char *name)
2495{
2496	char *s;
2497
2498	LOGCMD("mkdir", name);
2499	if (guest && noguestmkd)
2500		reply(550, "%s: permission denied", name);
2501	else if (mkdir(name, 0777) < 0)
2502		perror_reply(550, name);
2503	else {
2504		if ((s = doublequote(name)) == NULL)
2505			fatalerror("Ran out of memory.");
2506		reply(257, "\"%s\" directory created.", s);
2507		free(s);
2508	}
2509}
2510
2511void
2512removedir(char *name)
2513{
2514
2515	LOGCMD("rmdir", name);
2516	if (rmdir(name) < 0)
2517		perror_reply(550, name);
2518	else
2519		ack("RMD");
2520}
2521
2522void
2523pwd(void)
2524{
2525	char *s, path[MAXPATHLEN + 1];
2526
2527	if (getwd(path) == (char *)NULL)
2528		reply(550, "%s.", path);
2529	else {
2530		if ((s = doublequote(path)) == NULL)
2531			fatalerror("Ran out of memory.");
2532		reply(257, "\"%s\" is current directory.", s);
2533		free(s);
2534	}
2535}
2536
2537char *
2538renamefrom(char *name)
2539{
2540	struct stat st;
2541
2542	if (guest && noguestmod) {
2543		reply(550, "Operation not permitted");
2544		return (NULL);
2545	}
2546	if (lstat(name, &st) < 0) {
2547		perror_reply(550, name);
2548		return (NULL);
2549	}
2550	reply(350, "File exists, ready for destination name");
2551	return (name);
2552}
2553
2554void
2555renamecmd(char *from, char *to)
2556{
2557	struct stat st;
2558
2559	LOGCMD2("rename", from, to);
2560
2561	if (guest && (stat(to, &st) == 0)) {
2562		reply(550, "%s: permission denied", to);
2563		return;
2564	}
2565
2566	if (rename(from, to) < 0)
2567		perror_reply(550, "rename");
2568	else
2569		ack("RNTO");
2570}
2571
2572static void
2573dolog(struct sockaddr *who)
2574{
2575	int error;
2576
2577	realhostname_sa(remotehost, sizeof(remotehost) - 1, who, who->sa_len);
2578
2579#ifdef SETPROCTITLE
2580#ifdef VIRTUAL_HOSTING
2581	if (thishost != firsthost)
2582		snprintf(proctitle, sizeof(proctitle), "%s: connected (to %s)",
2583			 remotehost, hostname);
2584	else
2585#endif
2586		snprintf(proctitle, sizeof(proctitle), "%s: connected",
2587			 remotehost);
2588	setproctitle("%s", proctitle);
2589#endif /* SETPROCTITLE */
2590
2591	if (logging) {
2592#ifdef VIRTUAL_HOSTING
2593		if (thishost != firsthost)
2594			syslog(LOG_INFO, "connection from %s (to %s)",
2595			       remotehost, hostname);
2596		else
2597#endif
2598		{
2599			char	who_name[MAXHOSTNAMELEN];
2600
2601			error = getnameinfo(who, who->sa_len,
2602					    who_name, sizeof(who_name) - 1,
2603					    NULL, 0, NI_NUMERICHOST);
2604			syslog(LOG_INFO, "connection from %s (%s)", remotehost,
2605			       error == 0 ? who_name : "");
2606		}
2607	}
2608}
2609
2610/*
2611 * Record logout in wtmp file
2612 * and exit with supplied status.
2613 */
2614void
2615dologout(int status)
2616{
2617	/*
2618	 * Prevent reception of SIGURG from resulting in a resumption
2619	 * back to the main program loop.
2620	 */
2621	transflag = 0;
2622
2623	if (logged_in && dowtmp) {
2624		(void) seteuid(0);
2625		ftpd_logwtmp(ttyline, "", NULL);
2626	}
2627	/* beware of flushing buffers after a SIGPIPE */
2628	_exit(status);
2629}
2630
2631static void
2632sigurg(int signo)
2633{
2634
2635	recvurg = 1;
2636}
2637
2638static void
2639myoob(void)
2640{
2641	char *cp;
2642
2643	/* only process if transfer occurring */
2644	if (!transflag)
2645		return;
2646	cp = tmpline;
2647	if (getline(cp, 7, stdin) == NULL) {
2648		reply(221, "You could at least say goodbye.");
2649		dologout(0);
2650	}
2651	upper(cp);
2652	if (strcmp(cp, "ABOR\r\n") == 0) {
2653		tmpline[0] = '\0';
2654		reply(426, "Transfer aborted. Data connection closed.");
2655		reply(226, "Abort successful");
2656	}
2657	if (strcmp(cp, "STAT\r\n") == 0) {
2658		tmpline[0] = '\0';
2659		if (file_size != (off_t) -1)
2660			reply(213, "Status: %qd of %qd bytes transferred",
2661			    byte_count, file_size);
2662		else
2663			reply(213, "Status: %qd bytes transferred", byte_count);
2664	}
2665}
2666
2667/*
2668 * Note: a response of 425 is not mentioned as a possible response to
2669 *	the PASV command in RFC959. However, it has been blessed as
2670 *	a legitimate response by Jon Postel in a telephone conversation
2671 *	with Rick Adams on 25 Jan 89.
2672 */
2673void
2674passive(void)
2675{
2676	int len, on;
2677	char *p, *a;
2678
2679	if (pdata >= 0)		/* close old port if one set */
2680		close(pdata);
2681
2682	pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0);
2683	if (pdata < 0) {
2684		perror_reply(425, "Can't open passive connection");
2685		return;
2686	}
2687	on = 1;
2688	if (setsockopt(pdata, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
2689		syslog(LOG_WARNING, "pdata setsockopt (SO_REUSEADDR): %m");
2690
2691	(void) seteuid(0);
2692
2693#ifdef IP_PORTRANGE
2694	if (ctrl_addr.su_family == AF_INET) {
2695	    on = restricted_data_ports ? IP_PORTRANGE_HIGH
2696				       : IP_PORTRANGE_DEFAULT;
2697
2698	    if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2699			    &on, sizeof(on)) < 0)
2700		    goto pasv_error;
2701	}
2702#endif
2703#ifdef IPV6_PORTRANGE
2704	if (ctrl_addr.su_family == AF_INET6) {
2705	    on = restricted_data_ports ? IPV6_PORTRANGE_HIGH
2706				       : IPV6_PORTRANGE_DEFAULT;
2707
2708	    if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE,
2709			    &on, sizeof(on)) < 0)
2710		    goto pasv_error;
2711	}
2712#endif
2713
2714	pasv_addr = ctrl_addr;
2715	pasv_addr.su_port = 0;
2716	if (bind(pdata, (struct sockaddr *)&pasv_addr, pasv_addr.su_len) < 0)
2717		goto pasv_error;
2718
2719	(void) seteuid(pw->pw_uid);
2720
2721	len = sizeof(pasv_addr);
2722	if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
2723		goto pasv_error;
2724	if (listen(pdata, 1) < 0)
2725		goto pasv_error;
2726	if (pasv_addr.su_family == AF_INET)
2727		a = (char *) &pasv_addr.su_sin.sin_addr;
2728	else if (pasv_addr.su_family == AF_INET6 &&
2729		 IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr))
2730		a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12];
2731	else
2732		goto pasv_error;
2733
2734	p = (char *) &pasv_addr.su_port;
2735
2736#define UC(b) (((int) b) & 0xff)
2737
2738	reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]),
2739		UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
2740	return;
2741
2742pasv_error:
2743	(void) seteuid(pw->pw_uid);
2744	(void) close(pdata);
2745	pdata = -1;
2746	perror_reply(425, "Can't open passive connection");
2747	return;
2748}
2749
2750/*
2751 * Long Passive defined in RFC 1639.
2752 *     228 Entering Long Passive Mode
2753 *         (af, hal, h1, h2, h3,..., pal, p1, p2...)
2754 */
2755
2756void
2757long_passive(char *cmd, int pf)
2758{
2759	int len, on;
2760	char *p, *a;
2761
2762	if (pdata >= 0)		/* close old port if one set */
2763		close(pdata);
2764
2765	if (pf != PF_UNSPEC) {
2766		if (ctrl_addr.su_family != pf) {
2767			switch (ctrl_addr.su_family) {
2768			case AF_INET:
2769				pf = 1;
2770				break;
2771			case AF_INET6:
2772				pf = 2;
2773				break;
2774			default:
2775				pf = 0;
2776				break;
2777			}
2778			/*
2779			 * XXX
2780			 * only EPRT/EPSV ready clients will understand this
2781			 */
2782			if (strcmp(cmd, "EPSV") == 0 && pf) {
2783				reply(522, "Network protocol mismatch, "
2784					"use (%d)", pf);
2785			} else
2786				reply(501, "Network protocol mismatch"); /*XXX*/
2787
2788			return;
2789		}
2790	}
2791
2792	pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0);
2793	if (pdata < 0) {
2794		perror_reply(425, "Can't open passive connection");
2795		return;
2796	}
2797	on = 1;
2798	if (setsockopt(pdata, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
2799		syslog(LOG_WARNING, "pdata setsockopt (SO_REUSEADDR): %m");
2800
2801	(void) seteuid(0);
2802
2803	pasv_addr = ctrl_addr;
2804	pasv_addr.su_port = 0;
2805	len = pasv_addr.su_len;
2806
2807#ifdef IP_PORTRANGE
2808	if (ctrl_addr.su_family == AF_INET) {
2809	    on = restricted_data_ports ? IP_PORTRANGE_HIGH
2810				       : IP_PORTRANGE_DEFAULT;
2811
2812	    if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2813			    &on, sizeof(on)) < 0)
2814		    goto pasv_error;
2815	}
2816#endif
2817#ifdef IPV6_PORTRANGE
2818	if (ctrl_addr.su_family == AF_INET6) {
2819	    on = restricted_data_ports ? IPV6_PORTRANGE_HIGH
2820				       : IPV6_PORTRANGE_DEFAULT;
2821
2822	    if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE,
2823			    &on, sizeof(on)) < 0)
2824		    goto pasv_error;
2825	}
2826#endif
2827
2828	if (bind(pdata, (struct sockaddr *)&pasv_addr, len) < 0)
2829		goto pasv_error;
2830
2831	(void) seteuid(pw->pw_uid);
2832
2833	if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
2834		goto pasv_error;
2835	if (listen(pdata, 1) < 0)
2836		goto pasv_error;
2837
2838#define UC(b) (((int) b) & 0xff)
2839
2840	if (strcmp(cmd, "LPSV") == 0) {
2841		p = (char *)&pasv_addr.su_port;
2842		switch (pasv_addr.su_family) {
2843		case AF_INET:
2844			a = (char *) &pasv_addr.su_sin.sin_addr;
2845		v4_reply:
2846			reply(228,
2847"Entering Long Passive Mode (%d,%d,%d,%d,%d,%d,%d,%d,%d)",
2848			      4, 4, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
2849			      2, UC(p[0]), UC(p[1]));
2850			return;
2851		case AF_INET6:
2852			if (IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr)) {
2853				a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12];
2854				goto v4_reply;
2855			}
2856			a = (char *) &pasv_addr.su_sin6.sin6_addr;
2857			reply(228,
2858"Entering Long Passive Mode "
2859"(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)",
2860			      6, 16, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
2861			      UC(a[4]), UC(a[5]), UC(a[6]), UC(a[7]),
2862			      UC(a[8]), UC(a[9]), UC(a[10]), UC(a[11]),
2863			      UC(a[12]), UC(a[13]), UC(a[14]), UC(a[15]),
2864			      2, UC(p[0]), UC(p[1]));
2865			return;
2866		}
2867	} else if (strcmp(cmd, "EPSV") == 0) {
2868		switch (pasv_addr.su_family) {
2869		case AF_INET:
2870		case AF_INET6:
2871			reply(229, "Entering Extended Passive Mode (|||%d|)",
2872				ntohs(pasv_addr.su_port));
2873			return;
2874		}
2875	} else {
2876		/* more proper error code? */
2877	}
2878
2879pasv_error:
2880	(void) seteuid(pw->pw_uid);
2881	(void) close(pdata);
2882	pdata = -1;
2883	perror_reply(425, "Can't open passive connection");
2884	return;
2885}
2886
2887/*
2888 * Generate unique name for file with basename "local"
2889 * and open the file in order to avoid possible races.
2890 * Try "local" first, then "local.1", "local.2" etc, up to "local.99".
2891 * Return descriptor to the file, set "name" to its name.
2892 *
2893 * Generates failure reply on error.
2894 */
2895static int
2896guniquefd(char *local, char **name)
2897{
2898	static char new[MAXPATHLEN];
2899	struct stat st;
2900	char *cp;
2901	int count;
2902	int fd;
2903
2904	cp = strrchr(local, '/');
2905	if (cp)
2906		*cp = '\0';
2907	if (stat(cp ? local : ".", &st) < 0) {
2908		perror_reply(553, cp ? local : ".");
2909		return (-1);
2910	}
2911	if (cp) {
2912		/*
2913		 * Let not overwrite dirname with counter suffix.
2914		 * -4 is for /nn\0
2915		 * In this extreme case dot won't be put in front of suffix.
2916		 */
2917		if (strlen(local) > sizeof(new) - 4) {
2918			reply(553, "Pathname too long");
2919			return (-1);
2920		}
2921		*cp = '/';
2922	}
2923	/* -4 is for the .nn<null> we put on the end below */
2924	(void) snprintf(new, sizeof(new) - 4, "%s", local);
2925	cp = new + strlen(new);
2926	/*
2927	 * Don't generate dotfile unless requested explicitly.
2928	 * This covers the case when basename gets truncated off
2929	 * by buffer size.
2930	 */
2931	if (cp > new && cp[-1] != '/')
2932		*cp++ = '.';
2933	for (count = 0; count < 100; count++) {
2934		/* At count 0 try unmodified name */
2935		if (count)
2936			(void)sprintf(cp, "%d", count);
2937		if ((fd = open(count ? new : local,
2938		    O_RDWR | O_CREAT | O_EXCL, 0666)) >= 0) {
2939			*name = count ? new : local;
2940			return (fd);
2941		}
2942		if (errno != EEXIST) {
2943			perror_reply(553, count ? new : local);
2944			return (-1);
2945		}
2946	}
2947	reply(452, "Unique file name cannot be created.");
2948	return (-1);
2949}
2950
2951/*
2952 * Format and send reply containing system error number.
2953 */
2954void
2955perror_reply(int code, char *string)
2956{
2957
2958	reply(code, "%s: %s.", string, strerror(errno));
2959}
2960
2961static char *onefile[] = {
2962	"",
2963	0
2964};
2965
2966void
2967send_file_list(char *whichf)
2968{
2969	struct stat st;
2970	DIR *dirp = NULL;
2971	struct dirent *dir;
2972	FILE *dout = NULL;
2973	char **dirlist, *dirname;
2974	int simple = 0;
2975	int freeglob = 0;
2976	glob_t gl;
2977
2978	if (strpbrk(whichf, "~{[*?") != NULL) {
2979		int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_TILDE;
2980
2981		memset(&gl, 0, sizeof(gl));
2982		gl.gl_matchc = MAXGLOBARGS;
2983		flags |= GLOB_LIMIT;
2984		freeglob = 1;
2985		if (glob(whichf, flags, 0, &gl)) {
2986			reply(550, "not found");
2987			goto out;
2988		} else if (gl.gl_pathc == 0) {
2989			errno = ENOENT;
2990			perror_reply(550, whichf);
2991			goto out;
2992		}
2993		dirlist = gl.gl_pathv;
2994	} else {
2995		onefile[0] = whichf;
2996		dirlist = onefile;
2997		simple = 1;
2998	}
2999
3000	while ((dirname = *dirlist++)) {
3001		if (stat(dirname, &st) < 0) {
3002			/*
3003			 * If user typed "ls -l", etc, and the client
3004			 * used NLST, do what the user meant.
3005			 */
3006			if (dirname[0] == '-' && *dirlist == NULL &&
3007			    transflag == 0) {
3008				retrieve(_PATH_LS " %s", dirname);
3009				goto out;
3010			}
3011			perror_reply(550, whichf);
3012			if (dout != NULL) {
3013				(void) fclose(dout);
3014				transflag = 0;
3015				data = -1;
3016				pdata = -1;
3017			}
3018			goto out;
3019		}
3020
3021		if (S_ISREG(st.st_mode)) {
3022			if (dout == NULL) {
3023				dout = dataconn("file list", (off_t)-1, "w");
3024				if (dout == NULL)
3025					goto out;
3026				transflag++;
3027			}
3028			fprintf(dout, "%s%s\n", dirname,
3029				type == TYPE_A ? "\r" : "");
3030			byte_count += strlen(dirname) + 1;
3031			continue;
3032		} else if (!S_ISDIR(st.st_mode))
3033			continue;
3034
3035		if ((dirp = opendir(dirname)) == NULL)
3036			continue;
3037
3038		while ((dir = readdir(dirp)) != NULL) {
3039			char nbuf[MAXPATHLEN];
3040
3041			if (recvurg) {
3042				myoob();
3043				recvurg = 0;
3044				transflag = 0;
3045				goto out;
3046			}
3047
3048			if (dir->d_name[0] == '.' && dir->d_namlen == 1)
3049				continue;
3050			if (dir->d_name[0] == '.' && dir->d_name[1] == '.' &&
3051			    dir->d_namlen == 2)
3052				continue;
3053
3054			snprintf(nbuf, sizeof(nbuf),
3055				"%s/%s", dirname, dir->d_name);
3056
3057			/*
3058			 * We have to do a stat to insure it's
3059			 * not a directory or special file.
3060			 */
3061			if (simple || (stat(nbuf, &st) == 0 &&
3062			    S_ISREG(st.st_mode))) {
3063				if (dout == NULL) {
3064					dout = dataconn("file list", (off_t)-1,
3065						"w");
3066					if (dout == NULL)
3067						goto out;
3068					transflag++;
3069				}
3070				if (nbuf[0] == '.' && nbuf[1] == '/')
3071					fprintf(dout, "%s%s\n", &nbuf[2],
3072						type == TYPE_A ? "\r" : "");
3073				else
3074					fprintf(dout, "%s%s\n", nbuf,
3075						type == TYPE_A ? "\r" : "");
3076				byte_count += strlen(nbuf) + 1;
3077			}
3078		}
3079		(void) closedir(dirp);
3080	}
3081
3082	if (dout == NULL)
3083		reply(550, "No files found.");
3084	else if (ferror(dout) != 0)
3085		perror_reply(550, "Data connection");
3086	else
3087		reply(226, "Transfer complete.");
3088
3089	transflag = 0;
3090	if (dout != NULL)
3091		(void) fclose(dout);
3092	data = -1;
3093	pdata = -1;
3094out:
3095	if (freeglob) {
3096		freeglob = 0;
3097		globfree(&gl);
3098	}
3099}
3100
3101void
3102reapchild(int signo)
3103{
3104	while (wait3(NULL, WNOHANG, NULL) > 0);
3105}
3106
3107#ifdef OLD_SETPROCTITLE
3108/*
3109 * Clobber argv so ps will show what we're doing.  (Stolen from sendmail.)
3110 * Warning, since this is usually started from inetd.conf, it often doesn't
3111 * have much of an environment or arglist to overwrite.
3112 */
3113void
3114setproctitle(const char *fmt, ...)
3115{
3116	int i;
3117	va_list ap;
3118	char *p, *bp, ch;
3119	char buf[LINE_MAX];
3120
3121	va_start(ap, fmt);
3122	(void)vsnprintf(buf, sizeof(buf), fmt, ap);
3123
3124	/* make ps print our process name */
3125	p = Argv[0];
3126	*p++ = '-';
3127
3128	i = strlen(buf);
3129	if (i > LastArgv - p - 2) {
3130		i = LastArgv - p - 2;
3131		buf[i] = '\0';
3132	}
3133	bp = buf;
3134	while (ch = *bp++)
3135		if (ch != '\n' && ch != '\r')
3136			*p++ = ch;
3137	while (p < LastArgv)
3138		*p++ = ' ';
3139}
3140#endif /* OLD_SETPROCTITLE */
3141
3142static void
3143logxfer(char *name, off_t size, time_t start)
3144{
3145	char buf[1024];
3146	char path[MAXPATHLEN + 1];
3147	time_t now;
3148
3149	if (statfd >= 0 && getwd(path) != NULL) {
3150		time(&now);
3151		snprintf(buf, sizeof(buf), "%.20s!%s!%s!%s/%s!%qd!%ld\n",
3152			ctime(&now)+4, ident, remotehost,
3153			path, name, (long long)size,
3154			(long)(now - start + (now == start)));
3155		write(statfd, buf, strlen(buf));
3156	}
3157}
3158
3159static char *
3160doublequote(char *s)
3161{
3162	int n;
3163	char *p, *s2;
3164
3165	for (p = s, n = 0; *p; p++)
3166		if (*p == '"')
3167			n++;
3168
3169	if ((s2 = malloc(p - s + n + 1)) == NULL)
3170		return (NULL);
3171
3172	for (p = s2; *s; s++, p++) {
3173		if ((*p = *s) == '"')
3174			*(++p) = '"';
3175	}
3176	*p = '\0';
3177
3178	return (s2);
3179}
3180
3181/* setup server socket for specified address family */
3182/* if af is PF_UNSPEC more than one socket may be returned */
3183/* the returned list is dynamically allocated, so caller needs to free it */
3184static int *
3185socksetup(int af, char *bindname, const char *bindport)
3186{
3187	struct addrinfo hints, *res, *r;
3188	int error, maxs, *s, *socks;
3189	const int on = 1;
3190
3191	memset(&hints, 0, sizeof(hints));
3192	hints.ai_flags = AI_PASSIVE;
3193	hints.ai_family = af;
3194	hints.ai_socktype = SOCK_STREAM;
3195	error = getaddrinfo(bindname, bindport, &hints, &res);
3196	if (error) {
3197		syslog(LOG_ERR, "%s", gai_strerror(error));
3198		if (error == EAI_SYSTEM)
3199			syslog(LOG_ERR, "%s", strerror(errno));
3200		return NULL;
3201	}
3202
3203	/* Count max number of sockets we may open */
3204	for (maxs = 0, r = res; r; r = r->ai_next, maxs++)
3205		;
3206	socks = malloc((maxs + 1) * sizeof(int));
3207	if (!socks) {
3208		freeaddrinfo(res);
3209		syslog(LOG_ERR, "couldn't allocate memory for sockets");
3210		return NULL;
3211	}
3212
3213	*socks = 0;   /* num of sockets counter at start of array */
3214	s = socks + 1;
3215	for (r = res; r; r = r->ai_next) {
3216		*s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
3217		if (*s < 0) {
3218			syslog(LOG_DEBUG, "control socket: %m");
3219			continue;
3220		}
3221		if (setsockopt(*s, SOL_SOCKET, SO_REUSEADDR,
3222		    &on, sizeof(on)) < 0)
3223			syslog(LOG_WARNING,
3224			    "control setsockopt (SO_REUSEADDR): %m");
3225		if (r->ai_family == AF_INET6) {
3226			if (setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY,
3227			    &on, sizeof(on)) < 0)
3228				syslog(LOG_WARNING,
3229				    "control setsockopt (IPV6_V6ONLY): %m");
3230		}
3231		if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) {
3232			syslog(LOG_DEBUG, "control bind: %m");
3233			close(*s);
3234			continue;
3235		}
3236		(*socks)++;
3237		s++;
3238	}
3239
3240	if (res)
3241		freeaddrinfo(res);
3242
3243	if (*socks == 0) {
3244		syslog(LOG_ERR, "control socket: Couldn't bind to any socket");
3245		free(socks);
3246		return NULL;
3247	}
3248	return(socks);
3249}
3250