ftpd.c revision 1.199
1/*	$OpenBSD: ftpd.c,v 1.199 2014/01/08 17:31:36 jca Exp $	*/
2/*	$NetBSD: ftpd.c,v 1.15 1995/06/03 22:46:47 mycroft Exp $	*/
3
4/*
5 * Copyright (C) 1997 and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*
34 * Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994
35 *	The Regents of the University of California.  All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 *    notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 *    notice, this list of conditions and the following disclaimer in the
44 *    documentation and/or other materials provided with the distribution.
45 * 3. Neither the name of the University nor the names of its contributors
46 *    may be used to endorse or promote products derived from this software
47 *    without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 */
61
62/*
63 * FTP server.
64 */
65#include <sys/stat.h>
66#include <sys/ioctl.h>
67#include <sys/socket.h>
68#include <sys/wait.h>
69#include <sys/mman.h>
70
71#include <netinet/in.h>
72#include <netinet/in_systm.h>
73#include <netinet/ip.h>
74#include <netinet/tcp.h>
75
76#define	FTP_NAMES
77#include <arpa/ftp.h>
78#include <arpa/inet.h>
79#include <arpa/telnet.h>
80
81#include <bsd_auth.h>
82#include <ctype.h>
83#include <dirent.h>
84#include <errno.h>
85#include <fcntl.h>
86#include <glob.h>
87#include <limits.h>
88#include <login_cap.h>
89#include <netdb.h>
90#include <pwd.h>
91#include <signal.h>
92#include <stdarg.h>
93#include <stdio.h>
94#include <stdlib.h>
95#include <string.h>
96#include <syslog.h>
97#include <time.h>
98#include <vis.h>
99#include <unistd.h>
100#include <util.h>
101#include <utmp.h>
102#include <poll.h>
103
104#if defined(TCPWRAPPERS)
105#include <tcpd.h>
106#endif	/* TCPWRAPPERS */
107
108#include "pathnames.h"
109#include "monitor.h"
110#include "extern.h"
111
112extern	off_t restart_point;
113extern	char cbuf[];
114
115union sockunion ctrl_addr;
116union sockunion data_source;
117union sockunion data_dest;
118union sockunion his_addr;
119union sockunion pasv_addr;
120
121sigset_t allsigs;
122
123int	daemon_mode = 0;
124int	data;
125int	logged_in;
126struct	passwd *pw;
127int	debug = 0;
128int	timeout = 900;    /* timeout after 15 minutes of inactivity */
129int	maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */
130int	logging;
131int	anon_ok = 1;
132int	anon_only = 0;
133int	multihome = 0;
134int	guest;
135int	stats;
136int	statfd = -1;
137int	portcheck = 1;
138int	dochroot;
139int	type;
140int	form;
141int	stru;			/* avoid C keyword */
142int	mode;
143int	doutmp = 0;		/* update utmp file */
144int	nowtmp = 0;		/* do not update wtmp file */
145int	usedefault = 1;		/* for data transfers */
146int	pdata = -1;		/* for passive mode */
147int	family = AF_UNSPEC;
148volatile sig_atomic_t transflag;
149off_t	file_size;
150off_t	byte_count;
151#if !defined(CMASK) || CMASK == 0
152#undef CMASK
153#define CMASK 022
154#endif
155mode_t	defumask = CMASK;		/* default umask value */
156int	umaskchange = 1;		/* allow user to change umask value. */
157char	tmpline[7];
158char	hostname[MAXHOSTNAMELEN];
159char	remotehost[MAXHOSTNAMELEN];
160char	dhostname[MAXHOSTNAMELEN];
161char	*guestpw;
162char	ttyline[20];
163#if 0
164char	*tty = ttyline;		/* for klogin */
165#endif
166static struct utmp utmp;	/* for utmp */
167static	login_cap_t *lc;
168static	auth_session_t *as;
169static	volatile sig_atomic_t recvurg;
170
171#if defined(TCPWRAPPERS)
172int	allow_severity = LOG_INFO;
173int	deny_severity = LOG_NOTICE;
174#endif	/* TCPWRAPPERS */
175
176int epsvall = 0;
177
178/*
179 * Timeout intervals for retrying connections
180 * to hosts that don't accept PORT cmds.  This
181 * is a kludge, but given the problems with TCP...
182 */
183#define	SWAITMAX	90	/* wait at most 90 seconds */
184#define	SWAITINT	5	/* interval between retries */
185
186int	swaitmax = SWAITMAX;
187int	swaitint = SWAITINT;
188
189#ifdef HASSETPROCTITLE
190char	proctitle[BUFSIZ];	/* initial part of title */
191#endif /* HASSETPROCTITLE */
192
193#define LOGCMD(cmd, file) \
194	if (logging > 1) \
195	    syslog(LOG_INFO,"%s %s%s", cmd, \
196		*(file) == '/' ? "" : curdir(), file);
197#define LOGCMD2(cmd, file1, file2) \
198	 if (logging > 1) \
199	    syslog(LOG_INFO,"%s %s%s %s%s", cmd, \
200		*(file1) == '/' ? "" : curdir(), file1, \
201		*(file2) == '/' ? "" : curdir(), file2);
202#define LOGBYTES(cmd, file, cnt) \
203	if (logging > 1) { \
204		if (cnt == (off_t)-1) \
205		    syslog(LOG_INFO,"%s %s%s", cmd, \
206			*(file) == '/' ? "" : curdir(), file); \
207		else \
208		    syslog(LOG_INFO, "%s %s%s = %qd bytes", \
209			cmd, (*(file) == '/') ? "" : curdir(), file, cnt); \
210	}
211
212static void	 ack(char *);
213static void	 sigurg(int);
214static void	 myoob(void);
215static int	 checkuser(char *, char *);
216static FILE	*dataconn(char *, off_t, char *);
217static void	 dolog(struct sockaddr *);
218static char	*copy_dir(char *, struct passwd *);
219static char	*curdir(void);
220static void	 end_login(void);
221static FILE	*getdatasock(char *);
222static int	 guniquefd(char *, char **);
223static void	 lostconn(int);
224static void	 sigquit(int);
225static int	 receive_data(FILE *, FILE *);
226static void	 replydirname(const char *, const char *);
227static int	 send_data(FILE *, FILE *, off_t, off_t, int);
228static struct passwd *
229		 sgetpwnam(char *, struct passwd *);
230static void	 reapchild(int);
231#if defined(TCPWRAPPERS)
232static int	 check_host(struct sockaddr *);
233#endif /* TCPWRAPPERS */
234static void	 usage(void);
235
236void	 logxfer(char *, off_t, time_t);
237void	 set_slave_signals(void);
238
239static char *
240curdir(void)
241{
242	static char path[MAXPATHLEN+1];	/* path + '/' */
243
244	if (getcwd(path, sizeof(path)-1) == NULL)
245		return ("");
246	if (path[1] != '\0')		/* special case for root dir. */
247		strlcat(path, "/", sizeof path);
248	/* For guest account, skip / since it's chrooted */
249	return (guest ? path+1 : path);
250}
251
252char *argstr = "AdDhnlMSt:T:u:PUvW46";
253
254static void
255usage(void)
256{
257	syslog(LOG_ERR,
258	    "usage: ftpd [-46ADdlMnPSUW] [-T maxtimeout] [-t timeout] [-u mask]");
259	exit(2);
260}
261
262int
263main(int argc, char *argv[])
264{
265	socklen_t addrlen;
266	int ch, on = 1, tos;
267	char line[LINE_MAX];
268	FILE *fp;
269	struct hostent *hp;
270	struct sigaction sa;
271	int error = 0;
272	const char *errstr;
273
274	tzset();		/* in case no timezone database in ~ftp */
275	sigfillset(&allsigs);	/* used to block signals while root */
276	sigemptyset(&sa.sa_mask);
277	sa.sa_flags = SA_RESTART;
278
279	while ((ch = getopt(argc, argv, argstr)) != -1) {
280		switch (ch) {
281		case 'A':
282			anon_only = 1;
283			break;
284
285		case 'd':
286		case 'v':		/* deprecated */
287			debug = 1;
288			break;
289
290		case 'D':
291			daemon_mode = 1;
292			break;
293
294		case 'P':
295			portcheck = 0;
296			break;
297
298		case 'h':		/* deprecated */
299			break;
300
301		case 'l':
302			logging++;	/* > 1 == extra logging */
303			break;
304
305		case 'M':
306			multihome = 1;
307			break;
308
309		case 'n':
310			anon_ok = 0;
311			break;
312
313		case 'S':
314			stats = 1;
315			break;
316
317		case 't':
318			timeout = strtonum(optarg, 0, INT_MAX, &errstr);
319			if (errstr) {
320				syslog(LOG_ERR,
321				    "%s is a bad value for -t, aborting",
322				    optarg);
323				exit(2);
324			}
325			if (maxtimeout < timeout)
326				maxtimeout = timeout;
327			break;
328
329		case 'T':
330			maxtimeout = strtonum(optarg, 0, INT_MAX,
331			    &errstr);
332			if (errstr) {
333				syslog(LOG_ERR,
334				    "%s is a bad value for -T, aborting",
335				    optarg);
336				exit(2);
337			}
338			if (timeout > maxtimeout)
339				timeout = maxtimeout;
340			break;
341
342		case 'u':
343		    {
344			long val = 0;
345			char *p;
346			umaskchange = 0;
347
348			val = strtol(optarg, &p, 8);
349			if (*optarg == '\0' || *p != '\0' || val < 0 ||
350			    (val & ~ACCESSPERMS)) {
351				syslog(LOG_ERR,
352				    "%s is a bad value for -u, aborting",
353				    optarg);
354				exit(2);
355			}
356			defumask = val;
357			break;
358		    }
359
360		case 'U':
361			doutmp = 1;
362			break;
363
364		case 'W':
365			nowtmp = 1;
366			break;
367
368		case '4':
369			family = AF_INET;
370			break;
371
372		case '6':
373			family = AF_INET6;
374			break;
375
376		default:
377			usage();
378			break;
379		}
380	}
381
382	if (nowtmp && doutmp) {
383		syslog(LOG_ERR, "options 'U' and 'W' are mutually exclusive");
384		exit(1);
385	}
386
387	(void) freopen(_PATH_DEVNULL, "w", stderr);
388
389	/*
390	 * LOG_NDELAY sets up the logging connection immediately,
391	 * necessary for anonymous ftp's that chroot and can't do it later.
392	 */
393	openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
394
395	if (getpwnam(FTPD_PRIVSEP_USER) == NULL) {
396		syslog(LOG_ERR, "privilege separation user %s not found",
397		    FTPD_PRIVSEP_USER);
398		exit(1);
399	}
400	endpwent();
401
402	if (daemon_mode) {
403		int *fds, i, fd;
404		struct pollfd *pfds;
405		struct addrinfo hints, *res, *res0;
406		nfds_t n;
407
408		/*
409		 * Detach from parent.
410		 */
411		if (daemon(1, 1) < 0) {
412			syslog(LOG_ERR, "failed to become a daemon");
413			exit(1);
414		}
415		sa.sa_handler = reapchild;
416		(void) sigaction(SIGCHLD, &sa, NULL);
417
418		memset(&hints, 0, sizeof(hints));
419		hints.ai_family = family;
420		hints.ai_socktype = SOCK_STREAM;
421		hints.ai_protocol = IPPROTO_TCP;
422		hints.ai_flags = AI_PASSIVE;
423		error = getaddrinfo(NULL, "ftp", &hints, &res0);
424		if (error) {
425			syslog(LOG_ERR, "%s", gai_strerror(error));
426			exit(1);
427		}
428
429		n = 0;
430		for (res = res0; res; res = res->ai_next)
431			n++;
432
433		fds = calloc(n, sizeof(int));
434		pfds = calloc(n, sizeof(struct pollfd));
435		if (!fds || !pfds) {
436			syslog(LOG_ERR, "%s", strerror(errno));
437			exit(1);
438		}
439
440		/*
441		 * Open sockets, bind it to the FTP port, and start
442		 * listening.
443		 */
444		n = 0;
445		for (res = res0; res; res = res->ai_next) {
446			fds[n] = socket(res->ai_family, res->ai_socktype,
447			    res->ai_protocol);
448			if (fds[n] < 0)
449				continue;
450
451			if (setsockopt(fds[n], SOL_SOCKET, SO_KEEPALIVE,
452			    &on, sizeof(on)) < 0) {
453				close(fds[n]);
454				fds[n] = -1;
455				continue;
456			}
457
458			if (setsockopt(fds[n], SOL_SOCKET, SO_REUSEADDR,
459			    &on, sizeof(on)) < 0) {
460				close(fds[n]);
461				fds[n] = -1;
462				continue;
463			}
464
465			if (bind(fds[n], res->ai_addr, res->ai_addrlen) < 0) {
466				close(fds[n]);
467				fds[n] = -1;
468				continue;
469			}
470			if (listen(fds[n], 32) < 0) {
471				close(fds[n]);
472				fds[n] = -1;
473				continue;
474			}
475
476			pfds[n].fd = fds[n];
477			pfds[n].events = POLLIN;
478			n++;
479		}
480		freeaddrinfo(res0);
481
482		if (n == 0) {
483			syslog(LOG_ERR, "could not open control socket");
484			exit(1);
485		}
486
487		/* Stash pid in pidfile */
488		if (pidfile(NULL))
489			syslog(LOG_ERR, "can't open pidfile: %m");
490		/*
491		 * Loop forever accepting connection requests and forking off
492		 * children to handle them.
493		 */
494		while (1) {
495			if (poll(pfds, n, INFTIM) < 0) {
496				if (errno == EINTR)
497					continue;
498				syslog(LOG_ERR, "poll: %m");
499				exit(1);
500			}
501			for (i = 0; i < n; i++)
502				if (pfds[i].revents & POLLIN) {
503					addrlen = sizeof(his_addr);
504					fd = accept(pfds[i].fd,
505					    (struct sockaddr *)&his_addr,
506					    &addrlen);
507					if (fd != -1) {
508						if (fork() == 0)
509							goto child;
510						close(fd);
511					}
512				}
513		}
514
515	child:
516		/* child */
517		(void)dup2(fd, STDIN_FILENO);
518		(void)dup2(fd, STDOUT_FILENO);
519		for (i = 0; i < n; i++)
520			close(fds[i]);
521#if defined(TCPWRAPPERS)
522		/* ..in the child. */
523		if (!check_host((struct sockaddr *)&his_addr))
524			exit(1);
525#endif	/* TCPWRAPPERS */
526	} else {
527		addrlen = sizeof(his_addr);
528		if (getpeername(0, (struct sockaddr *)&his_addr,
529		    &addrlen) < 0) {
530			/* syslog(LOG_ERR, "getpeername (%s): %m", argv[0]); */
531			exit(1);
532		}
533	}
534
535	/* set this here so klogin can use it... */
536	(void)snprintf(ttyline, sizeof(ttyline), "ftp%ld", (long)getpid());
537
538	set_slave_signals();
539
540	addrlen = sizeof(ctrl_addr);
541	if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) {
542		syslog(LOG_ERR, "getsockname: %m");
543		exit(1);
544	}
545	if (his_addr.su_family == AF_INET6 &&
546	    IN6_IS_ADDR_V4MAPPED(&his_addr.su_sin6.sin6_addr)) {
547#if 1
548		/*
549		 * IPv4 control connection arrived to AF_INET6 socket.
550		 * I hate to do this, but this is the easiest solution.
551		 */
552		union sockunion tmp_addr;
553		const int off = sizeof(struct in6_addr) - sizeof(struct in_addr);
554
555		tmp_addr = his_addr;
556		memset(&his_addr, 0, sizeof(his_addr));
557		his_addr.su_sin.sin_family = AF_INET;
558		his_addr.su_sin.sin_len = sizeof(his_addr.su_sin);
559		memcpy(&his_addr.su_sin.sin_addr,
560		    &tmp_addr.su_sin6.sin6_addr.s6_addr[off],
561		    sizeof(his_addr.su_sin.sin_addr));
562		his_addr.su_sin.sin_port = tmp_addr.su_sin6.sin6_port;
563
564		tmp_addr = ctrl_addr;
565		memset(&ctrl_addr, 0, sizeof(ctrl_addr));
566		ctrl_addr.su_sin.sin_family = AF_INET;
567		ctrl_addr.su_sin.sin_len = sizeof(ctrl_addr.su_sin);
568		memcpy(&ctrl_addr.su_sin.sin_addr,
569		    &tmp_addr.su_sin6.sin6_addr.s6_addr[off],
570		    sizeof(ctrl_addr.su_sin.sin_addr));
571		ctrl_addr.su_sin.sin_port = tmp_addr.su_sin6.sin6_port;
572#else
573		while (fgets(line, sizeof(line), fd) != NULL) {
574			line[strcspn(line, "\n")] = '\0';
575			lreply(530, "%s", line);
576		}
577		(void) fflush(stdout);
578		(void) close(fd);
579		reply(530,
580			"Connection from IPv4 mapped address is not supported.");
581		exit(0);
582#endif
583	}
584#ifdef IP_TOS
585	if (his_addr.su_family == AF_INET) {
586		tos = IPTOS_LOWDELAY;
587		if (setsockopt(0, IPPROTO_IP, IP_TOS, &tos,
588		    sizeof(int)) < 0)
589			syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
590	}
591#endif
592	data_source.su_port = htons(ntohs(ctrl_addr.su_port) - 1);
593
594	/* Try to handle urgent data inline */
595#ifdef SO_OOBINLINE
596	if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)) < 0)
597		syslog(LOG_ERR, "setsockopt: %m");
598#endif
599
600	dolog((struct sockaddr *)&his_addr);
601
602	/*
603	 * Set up default state
604	 */
605	data = -1;
606	type = TYPE_A;
607	form = FORM_N;
608	stru = STRU_F;
609	mode = MODE_S;
610	tmpline[0] = '\0';
611
612	/* If logins are disabled, print out the message. */
613	if ((fp = fopen(_PATH_NOLOGIN, "r")) != NULL) {
614		while (fgets(line, sizeof(line), fp) != NULL) {
615			line[strcspn(line, "\n")] = '\0';
616			lreply(530, "%s", line);
617		}
618		(void) fflush(stdout);
619		(void) fclose(fp);
620		reply(530, "System not available.");
621		exit(0);
622	}
623	if ((fp = fopen(_PATH_FTPWELCOME, "r")) != NULL) {
624		while (fgets(line, sizeof(line), fp) != NULL) {
625			line[strcspn(line, "\n")] = '\0';
626			lreply(220, "%s", line);
627		}
628		(void) fflush(stdout);
629		(void) fclose(fp);
630		/* reply(220,) must follow */
631	}
632	(void) gethostname(hostname, sizeof(hostname));
633
634	/* Make sure hostname is fully qualified. */
635	hp = gethostbyname(hostname);
636	if (hp != NULL)
637		strlcpy(hostname, hp->h_name, sizeof(hostname));
638
639	if (multihome) {
640		error = getnameinfo((struct sockaddr *)&ctrl_addr,
641		    ctrl_addr.su_len, dhostname, sizeof(dhostname), NULL, 0, 0);
642	}
643
644	if (error != 0)
645		reply(220, "FTP server ready.");
646	else
647		reply(220, "%s FTP server ready.",
648		    (multihome ? dhostname : hostname));
649
650	monitor_init();
651
652	for (;;)
653		(void) yyparse();
654	/* NOTREACHED */
655}
656
657/*
658 * Signal handlers.
659 */
660/*ARGSUSED*/
661static void
662lostconn(int signo)
663{
664	struct syslog_data sdata = SYSLOG_DATA_INIT;
665
666	sdata.log_fac = LOG_FTP;
667	if (debug)
668		syslog_r(LOG_DEBUG, &sdata, "lost connection");
669	dologout(1);
670}
671
672static void
673sigquit(int signo)
674{
675	struct syslog_data sdata = SYSLOG_DATA_INIT;
676
677	sdata.log_fac = LOG_FTP;
678	syslog_r(LOG_DEBUG, &sdata, "got signal %s", sys_signame[signo]);
679	dologout(1);
680}
681
682/*
683 * Save the result of a getpwnam.  Used for USER command, since
684 * the data returned must not be clobbered by any other command
685 * (e.g., globbing).
686 */
687static struct passwd *
688sgetpwnam(char *name, struct passwd *pw)
689{
690	static struct passwd *save;
691	struct passwd *old;
692
693	if (pw == NULL && (pw = getpwnam(name)) == NULL)
694		return (NULL);
695	old = save;
696	save = pw_dup(pw);
697	if (save == NULL) {
698		perror_reply(421, "Local resource failure: malloc");
699		dologout(1);
700		/* NOTREACHED */
701	}
702	if (old) {
703		memset(old->pw_passwd, 0, strlen(old->pw_passwd));
704		free(old);
705	}
706	return (save);
707}
708
709static int login_attempts;	/* number of failed login attempts */
710static int askpasswd;		/* had user command, ask for passwd */
711static char curname[MAXLOGNAME];	/* current USER name */
712
713/*
714 * USER command.
715 * Sets global passwd pointer pw if named account exists and is acceptable;
716 * sets askpasswd if a PASS command is expected.  If logged in previously,
717 * need to reset state.  If name is "ftp" or "anonymous", the name is not in
718 * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return.
719 * If account doesn't exist, ask for passwd anyway.  Otherwise, check user
720 * requesting login privileges.  Disallow anyone who does not have a standard
721 * shell as returned by getusershell().  Disallow anyone mentioned in the file
722 * _PATH_FTPUSERS to allow people such as root and uucp to be avoided.
723 */
724void
725user(char *name)
726{
727	char *cp, *shell, *style, *host;
728	char *class = NULL;
729
730	if (logged_in) {
731		kill_slave("user already logged in");
732		end_login();
733	}
734
735	/* Close session from previous user if there was one. */
736	if (as) {
737		auth_close(as);
738		as = NULL;
739	}
740	if (lc) {
741		login_close(lc);
742		lc = NULL;
743	}
744
745	if ((style = strchr(name, ':')) != NULL)
746		*style++ = 0;
747
748	guest = 0;
749	askpasswd = 0;
750	host = multihome ? dhostname : hostname;
751	if (anon_ok &&
752	    (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0)) {
753		if (checkuser(_PATH_FTPUSERS, "ftp") ||
754		    checkuser(_PATH_FTPUSERS, "anonymous"))
755			reply(530, "User %s access denied.", name);
756		else if ((pw = sgetpwnam("ftp", NULL)) != NULL) {
757			if ((lc = login_getclass(pw->pw_class)) == NULL ||
758			    (as = auth_open()) == NULL ||
759			    auth_setpwd(as, pw) != 0 ||
760			    auth_setoption(as, "FTPD_HOST", host) < 0) {
761				if (as) {
762					auth_close(as);
763					as = NULL;
764				}
765				if (lc) {
766					login_close(lc);
767					lc = NULL;
768				}
769				reply(421, "Local resource failure");
770				return;
771			}
772			guest = 1;
773			askpasswd = 1;
774			reply(331,
775			"Guest login ok, send your email address as password.");
776		} else
777			reply(530, "User %s unknown.", name);
778		if (!askpasswd && logging)
779			syslog(LOG_NOTICE,
780			    "ANONYMOUS FTP LOGIN REFUSED FROM %s", remotehost);
781		return;
782	}
783
784	shell = _PATH_BSHELL;
785	if ((pw = sgetpwnam(name, NULL))) {
786		class = pw->pw_class;
787		if (pw->pw_shell != NULL && *pw->pw_shell != '\0')
788			shell = pw->pw_shell;
789		while ((cp = getusershell()) != NULL)
790			if (strcmp(cp, shell) == 0)
791				break;
792		shell = cp;
793		endusershell();
794	}
795
796	/* Get login class; if invalid style treat like unknown user. */
797	lc = login_getclass(class);
798	if (lc && (style = login_getstyle(lc, style, "auth-ftp")) == NULL) {
799		login_close(lc);
800		lc = NULL;
801		pw = NULL;
802	}
803
804	/* Do pre-authentication setup. */
805	if (lc && ((as = auth_open()) == NULL ||
806	    (pw != NULL && auth_setpwd(as, pw) != 0) ||
807	    auth_setitem(as, AUTHV_STYLE, style) < 0 ||
808	    auth_setitem(as, AUTHV_NAME, name) < 0 ||
809	    auth_setitem(as, AUTHV_CLASS, class) < 0 ||
810	    auth_setoption(as, "login", "yes") < 0 ||
811	    auth_setoption(as, "notickets", "yes") < 0 ||
812	    auth_setoption(as, "FTPD_HOST", host) < 0)) {
813		if (as) {
814			auth_close(as);
815			as = NULL;
816		}
817		login_close(lc);
818		lc = NULL;
819		reply(421, "Local resource failure");
820		return;
821	}
822	if (logging)
823		strlcpy(curname, name, sizeof(curname));
824
825	dochroot = (lc && login_getcapbool(lc, "ftp-chroot", 0)) ||
826	    checkuser(_PATH_FTPCHROOT, name);
827	if (anon_only && !dochroot) {
828		reply(530, "User %s access denied.", name);
829		return;
830	}
831	if (pw) {
832		if ((!shell && !dochroot) || checkuser(_PATH_FTPUSERS, name)) {
833			reply(530, "User %s access denied.", name);
834			if (logging)
835				syslog(LOG_NOTICE,
836				    "FTP LOGIN REFUSED FROM %s, %s",
837				    remotehost, name);
838			pw = NULL;
839			return;
840		}
841	}
842
843	if (as != NULL && (cp = auth_challenge(as)) != NULL)
844		reply(331, "%s", cp);
845	else
846		reply(331, "Password required for %s.", name);
847
848	askpasswd = 1;
849	/*
850	 * Delay before reading passwd after first failed
851	 * attempt to slow down passwd-guessing programs.
852	 */
853	if (login_attempts)
854		sleep((unsigned) login_attempts);
855}
856
857/*
858 * Check if a user is in the file "fname"
859 */
860static int
861checkuser(char *fname, char *name)
862{
863	FILE *fp;
864	int found = 0;
865	char *p, line[BUFSIZ];
866
867	if ((fp = fopen(fname, "r")) != NULL) {
868		while (fgets(line, sizeof(line), fp) != NULL)
869			if ((p = strchr(line, '\n')) != NULL) {
870				*p = '\0';
871				if (line[0] == '#')
872					continue;
873				if (strcmp(line, name) == 0) {
874					found = 1;
875					break;
876				}
877			}
878		(void) fclose(fp);
879	}
880	return (found);
881}
882
883/*
884 * Terminate login as previous user, if any, resetting state;
885 * used when USER command is given or login fails.
886 */
887static void
888end_login(void)
889{
890	sigprocmask (SIG_BLOCK, &allsigs, NULL);
891	if (logged_in) {
892		if (!nowtmp)
893			ftpdlogwtmp(ttyline, "", "");
894		if (doutmp)
895			ftpd_logout(utmp.ut_line);
896	}
897	reply(530, "Please reconnect to work as another user");
898	_exit(0);
899}
900
901enum auth_ret
902pass(char *passwd)
903{
904	int authok;
905	unsigned int flags;
906	FILE *fp;
907	static char homedir[MAXPATHLEN];
908	char *motd, *dir, rootdir[MAXPATHLEN];
909	size_t sz_pw_dir;
910
911	if (logged_in || askpasswd == 0) {
912		reply(503, "Login with USER first.");
913		return (AUTH_FAILED);
914	}
915	askpasswd = 0;
916	if (!guest) {		/* "ftp" is only account allowed no password */
917		authok = 0;
918		if (pw == NULL || pw->pw_passwd[0] == '\0') {
919			useconds_t us;
920
921			/* Sleep between 1 and 3 seconds to emulate a crypt. */
922			us = arc4random_uniform(3000000);
923			usleep(us);
924			if (as != NULL) {
925				auth_close(as);
926				as = NULL;
927			}
928		} else {
929			authok = auth_userresponse(as, passwd, 0);
930			as = NULL;
931		}
932		if (authok == 0) {
933			reply(530, "Login incorrect.");
934			if (logging)
935				syslog(LOG_NOTICE,
936				    "FTP LOGIN FAILED FROM %s, %s",
937				    remotehost, curname);
938			pw = NULL;
939			if (login_attempts++ >= 5) {
940				syslog(LOG_NOTICE,
941				    "repeated login failures from %s",
942				    remotehost);
943				kill_slave("repeated login failures");
944				_exit(0);
945			}
946			return (AUTH_FAILED);
947		}
948	} else if (lc != NULL) {
949		/* Save anonymous' password. */
950		if (guestpw != NULL)
951			free(guestpw);
952		guestpw = strdup(passwd);
953		if (guestpw == NULL) {
954			kill_slave("out of mem");
955			fatal("Out of memory.");
956		}
957
958		authok = auth_approval(as, lc, pw->pw_name, "ftp");
959		auth_close(as);
960		as = NULL;
961		if (authok == 0) {
962			syslog(LOG_INFO|LOG_AUTH,
963			    "FTP LOGIN FAILED (HOST) as %s: approval failure.",
964			    pw->pw_name);
965			reply(530, "Approval failure.");
966			kill_slave("approval failure");
967			_exit(0);
968		}
969	} else {
970		syslog(LOG_INFO|LOG_AUTH,
971		    "FTP LOGIN CLASS %s MISSING for %s: approval failure.",
972		    pw->pw_class, pw->pw_name);
973		reply(530, "Permission denied.");
974		kill_slave("permission denied");
975		_exit(0);
976	}
977
978	if (monitor_post_auth() == 1) {
979		/* Post-auth monitor process */
980		logged_in = 1;
981		return (AUTH_MONITOR);
982	}
983
984	login_attempts = 0;		/* this time successful */
985	/* set umask via setusercontext() unless -u flag was given. */
986	flags = LOGIN_SETGROUP|LOGIN_SETPRIORITY|LOGIN_SETRESOURCES;
987	if (umaskchange)
988		flags |= LOGIN_SETUMASK;
989	else
990		(void) umask(defumask);
991	if (setusercontext(lc, pw, (uid_t)0, flags) != 0) {
992		perror_reply(421, "Local resource failure: setusercontext");
993		syslog(LOG_NOTICE, "setusercontext: %m");
994		dologout(1);
995		/* NOTREACHED */
996	}
997
998	/* open wtmp before chroot */
999	if (!nowtmp)
1000		ftpdlogwtmp(ttyline, pw->pw_name, remotehost);
1001
1002	/* open utmp before chroot */
1003	if (doutmp) {
1004		memset((void *)&utmp, 0, sizeof(utmp));
1005		(void)time(&utmp.ut_time);
1006		(void)strncpy(utmp.ut_name, pw->pw_name, sizeof(utmp.ut_name));
1007		(void)strncpy(utmp.ut_host, remotehost, sizeof(utmp.ut_host));
1008		(void)strncpy(utmp.ut_line, ttyline, sizeof(utmp.ut_line));
1009		ftpd_login(&utmp);
1010	}
1011
1012	/* open stats file before chroot */
1013	if (guest && (stats == 1) && (statfd < 0))
1014		if ((statfd = open(_PATH_FTPDSTATFILE, O_WRONLY|O_APPEND)) < 0)
1015			stats = 0;
1016
1017	logged_in = 1;
1018
1019	if ((dir = login_getcapstr(lc, "ftp-dir", NULL, NULL))) {
1020		char *newdir;
1021
1022		newdir = copy_dir(dir, pw);
1023		if (newdir == NULL) {
1024			perror_reply(421, "Local resource failure: malloc");
1025			dologout(1);
1026			/* NOTREACHED */
1027		}
1028		pw->pw_dir = newdir;
1029		pw = sgetpwnam(NULL, pw);
1030		free(dir);
1031		free(newdir);
1032	}
1033
1034	/* make sure pw->pw_dir is big enough to hold "/" */
1035	sz_pw_dir = strlen(pw->pw_dir) + 1;
1036	if (sz_pw_dir < 2) {
1037		pw->pw_dir = "/";
1038		pw = sgetpwnam(NULL, pw);
1039		sz_pw_dir = 2;
1040	}
1041
1042	if (guest || dochroot) {
1043		if (multihome && guest) {
1044			struct stat ts;
1045
1046			/* Compute root directory. */
1047			snprintf(rootdir, sizeof(rootdir), "%s/%s",
1048			    pw->pw_dir, dhostname);
1049			if (stat(rootdir, &ts) < 0) {
1050				snprintf(rootdir, sizeof(rootdir), "%s/%s",
1051				    pw->pw_dir, hostname);
1052			}
1053		} else
1054			strlcpy(rootdir, pw->pw_dir, sizeof(rootdir));
1055	}
1056	if (guest) {
1057		/*
1058		 * We MUST do a chdir() after the chroot. Otherwise
1059		 * the old current directory will be accessible as "."
1060		 * outside the new root!
1061		 */
1062		if (chroot(rootdir) < 0 || chdir("/") < 0) {
1063			reply(550, "Can't set guest privileges.");
1064			goto bad;
1065		}
1066		strlcpy(pw->pw_dir, "/", sz_pw_dir);
1067		if (setenv("HOME", "/", 1) == -1) {
1068			reply(550, "Can't setup environment.");
1069			goto bad;
1070		}
1071	} else if (dochroot) {
1072		if (chroot(rootdir) < 0 || chdir("/") < 0) {
1073			reply(550, "Can't change root.");
1074			goto bad;
1075		}
1076		strlcpy(pw->pw_dir, "/", sz_pw_dir);
1077		if (setenv("HOME", "/", 1) == -1) {
1078			reply(550, "Can't setup environment.");
1079			goto bad;
1080		}
1081	} else if (chdir(pw->pw_dir) < 0) {
1082		if (chdir("/") < 0) {
1083			reply(530, "User %s: can't change directory to %s.",
1084			    pw->pw_name, pw->pw_dir);
1085			goto bad;
1086		} else
1087			lreply(230, "No directory! Logging in with home=/");
1088	}
1089	if (setegid(pw->pw_gid) < 0 || setgid(pw->pw_gid) < 0) {
1090		reply(550, "Can't set gid.");
1091		goto bad;
1092	}
1093	if (seteuid(pw->pw_uid) < 0 || setuid(pw->pw_uid) < 0) {
1094		reply(550, "Can't set uid.");
1095		goto bad;
1096	}
1097	sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
1098
1099	/*
1100	 * Set home directory so that use of ~ (tilde) works correctly.
1101	 */
1102	if (getcwd(homedir, MAXPATHLEN) != NULL) {
1103		if (setenv("HOME", homedir, 1) == -1) {
1104			reply(550, "Can't setup environment.");
1105			goto bad;
1106		}
1107	}
1108
1109	/*
1110	 * Display a login message, if it exists.
1111	 * N.B. reply(230,) must follow the message.
1112	 */
1113	motd = login_getcapstr(lc, "welcome", NULL, NULL);
1114	if ((fp = fopen(motd ? motd : _PATH_FTPLOGINMESG, "r")) != NULL) {
1115		char line[LINE_MAX];
1116
1117		while (fgets(line, sizeof(line), fp) != NULL) {
1118			line[strcspn(line, "\n")] = '\0';
1119			lreply(230, "%s", line);
1120		}
1121		(void) fflush(stdout);
1122		(void) fclose(fp);
1123	}
1124	if (motd != NULL)
1125		free(motd);
1126	if (guest) {
1127		reply(230, "Guest login ok, access restrictions apply.");
1128#ifdef HASSETPROCTITLE
1129		snprintf(proctitle, sizeof(proctitle),
1130		    "%s: anonymous/%.*s", remotehost,
1131		    (int)(sizeof(proctitle) - sizeof(remotehost) -
1132		    sizeof(": anonymous/")), passwd);
1133		setproctitle("%s", proctitle);
1134#endif /* HASSETPROCTITLE */
1135		if (logging)
1136			syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s",
1137			    remotehost, passwd);
1138	} else {
1139		reply(230, "User %s logged in.", pw->pw_name);
1140#ifdef HASSETPROCTITLE
1141		snprintf(proctitle, sizeof(proctitle),
1142		    "%s: %s", remotehost, pw->pw_name);
1143		setproctitle("%s", proctitle);
1144#endif /* HASSETPROCTITLE */
1145		if (logging)
1146			syslog(LOG_INFO, "FTP LOGIN FROM %s as %s",
1147			    remotehost, pw->pw_name);
1148	}
1149	login_close(lc);
1150	lc = NULL;
1151	return (AUTH_SLAVE);
1152bad:
1153	/* Forget all about it... */
1154	login_close(lc);
1155	lc = NULL;
1156	end_login();
1157	return (AUTH_FAILED);
1158}
1159
1160void
1161retrieve(char *cmd, char *name)
1162{
1163	FILE *fin, *dout;
1164	struct stat st;
1165	int (*closefunc)(FILE *);
1166	time_t start;
1167
1168	if (cmd == 0) {
1169		fin = fopen(name, "r"), closefunc = fclose;
1170		st.st_size = 0;
1171	} else {
1172		char line[BUFSIZ];
1173
1174		(void) snprintf(line, sizeof(line), cmd, name);
1175		name = line;
1176		fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose;
1177		st.st_size = -1;
1178		st.st_blksize = BUFSIZ;
1179	}
1180	if (fin == NULL) {
1181		if (errno != 0) {
1182			perror_reply(550, name);
1183			if (cmd == 0) {
1184				LOGCMD("get", name);
1185			}
1186		}
1187		return;
1188	}
1189	byte_count = -1;
1190	if (cmd == 0 && (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode))) {
1191		reply(550, "%s: not a plain file.", name);
1192		goto done;
1193	}
1194	if (restart_point) {
1195		if (type == TYPE_A) {
1196			off_t i, n;
1197			int c;
1198
1199			n = restart_point;
1200			i = 0;
1201			while (i++ < n) {
1202				if ((c = getc(fin)) == EOF) {
1203					if (ferror(fin)) {
1204						perror_reply(550, name);
1205						goto done;
1206					} else
1207						break;
1208				}
1209				if (c == '\n')
1210					i++;
1211			}
1212		} else if (lseek(fileno(fin), restart_point, SEEK_SET) < 0) {
1213			perror_reply(550, name);
1214			goto done;
1215		}
1216	}
1217	dout = dataconn(name, st.st_size, "w");
1218	if (dout == NULL)
1219		goto done;
1220	time(&start);
1221	send_data(fin, dout, (off_t)st.st_blksize, st.st_size,
1222	    (restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode)));
1223	if ((cmd == 0) && stats)
1224		logxfer(name, byte_count, start);
1225	(void) fclose(dout);
1226	data = -1;
1227done:
1228	if (pdata >= 0)
1229		(void) close(pdata);
1230	pdata = -1;
1231	if (cmd == 0)
1232		LOGBYTES("get", name, byte_count);
1233	(*closefunc)(fin);
1234}
1235
1236void
1237store(char *name, char *mode, int unique)
1238{
1239	FILE *fout, *din;
1240	int (*closefunc)(FILE *);
1241	struct stat st;
1242	int fd;
1243
1244	if (restart_point && *mode != 'a')
1245		mode = "r+";
1246
1247	if (unique && stat(name, &st) == 0) {
1248		char *nam;
1249
1250		fd = guniquefd(name, &nam);
1251		if (fd == -1) {
1252			LOGCMD(*mode == 'w' ? "put" : "append", name);
1253			return;
1254		}
1255		name = nam;
1256		fout = fdopen(fd, mode);
1257	} else
1258		fout = fopen(name, mode);
1259
1260	closefunc = fclose;
1261	if (fout == NULL) {
1262		perror_reply(553, name);
1263		LOGCMD(*mode == 'w' ? "put" : "append", name);
1264		return;
1265	}
1266	byte_count = -1;
1267	if (restart_point) {
1268		if (type == TYPE_A) {
1269			off_t i, n;
1270			int c;
1271
1272			n = restart_point;
1273			i = 0;
1274			while (i++ < n) {
1275				if ((c = getc(fout)) == EOF) {
1276					if (ferror(fout)) {
1277						perror_reply(550, name);
1278						goto done;
1279					} else
1280						break;
1281				}
1282				if (c == '\n')
1283					i++;
1284			}
1285			/*
1286			 * We must do this seek to "current" position
1287			 * because we are changing from reading to
1288			 * writing.
1289			 */
1290			if (fseek(fout, 0L, SEEK_CUR) < 0) {
1291				perror_reply(550, name);
1292				goto done;
1293			}
1294		} else if (lseek(fileno(fout), restart_point, SEEK_SET) < 0) {
1295			perror_reply(550, name);
1296			goto done;
1297		}
1298	}
1299	din = dataconn(name, (off_t)-1, "r");
1300	if (din == NULL)
1301		goto done;
1302	if (receive_data(din, fout) == 0) {
1303		if (unique)
1304			reply(226, "Transfer complete (unique file name:%s).",
1305			    name);
1306		else
1307			reply(226, "Transfer complete.");
1308	}
1309	(void) fclose(din);
1310	data = -1;
1311	pdata = -1;
1312done:
1313	LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count);
1314	(*closefunc)(fout);
1315}
1316
1317static FILE *
1318getdatasock(char *mode)
1319{
1320	int on = 1, s, t, tries;
1321
1322	if (data >= 0)
1323		return (fdopen(data, mode));
1324	sigprocmask (SIG_BLOCK, &allsigs, NULL);
1325	s = monitor_socket(ctrl_addr.su_family);
1326	if (s < 0)
1327		goto bad;
1328	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
1329	    &on, sizeof(on)) < 0)
1330		goto bad;
1331	/* anchor socket to avoid multi-homing problems */
1332	data_source = ctrl_addr;
1333	data_source.su_port = htons(20); /* ftp-data port */
1334	for (tries = 1; ; tries++) {
1335		if (monitor_bind(s, (struct sockaddr *)&data_source,
1336		    data_source.su_len) >= 0)
1337			break;
1338		if (errno != EADDRINUSE || tries > 10)
1339			goto bad;
1340		sleep((unsigned int)tries);
1341	}
1342	sigprocmask (SIG_UNBLOCK, &allsigs, NULL);
1343
1344#ifdef IP_TOS
1345	if (ctrl_addr.su_family == AF_INET) {
1346		on = IPTOS_THROUGHPUT;
1347		if (setsockopt(s, IPPROTO_IP, IP_TOS, &on,
1348		    sizeof(int)) < 0)
1349			syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
1350	}
1351#endif
1352#ifdef TCP_NOPUSH
1353	/*
1354	 * Turn off push flag to keep sender TCP from sending short packets
1355	 * at the boundaries of each write().  Should probably do a SO_SNDBUF
1356	 * to set the send buffer size as well, but that may not be desirable
1357	 * in heavy-load situations.
1358	 */
1359	on = 1;
1360	if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, &on, sizeof(on)) < 0)
1361		syslog(LOG_WARNING, "setsockopt (TCP_NOPUSH): %m");
1362#endif
1363#ifdef SO_SNDBUF
1364	on = 65536;
1365	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &on, sizeof(on)) < 0)
1366		syslog(LOG_WARNING, "setsockopt (SO_SNDBUF): %m");
1367#endif
1368
1369	return (fdopen(s, mode));
1370bad:
1371	/* Return the real value of errno (close may change it) */
1372	t = errno;
1373	sigprocmask (SIG_UNBLOCK, &allsigs, NULL);
1374	if (s >= 0)
1375		(void) close(s);
1376	errno = t;
1377	return (NULL);
1378}
1379
1380static FILE *
1381dataconn(char *name, off_t size, char *mode)
1382{
1383	char sizebuf[32];
1384	FILE *file = NULL;
1385	int retry = 0;
1386	in_port_t *p;
1387	u_char *fa, *ha;
1388	size_t alen;
1389	int error;
1390
1391	file_size = size;
1392	byte_count = 0;
1393	if (size != (off_t) -1) {
1394		(void) snprintf(sizebuf, sizeof(sizebuf), " (%qd bytes)",
1395		    size);
1396	} else
1397		sizebuf[0] = '\0';
1398	if (pdata >= 0) {
1399		union sockunion from;
1400		int s;
1401		socklen_t fromlen = sizeof(from);
1402
1403		(void) alarm ((unsigned) timeout);
1404		s = accept(pdata, (struct sockaddr *)&from, &fromlen);
1405		(void) alarm (0);
1406		if (s < 0) {
1407			reply(425, "Can't open data connection.");
1408			(void) close(pdata);
1409			pdata = -1;
1410			return (NULL);
1411		}
1412		switch (from.su_family) {
1413		case AF_INET:
1414			p = (in_port_t *)&from.su_sin.sin_port;
1415			fa = (u_char *)&from.su_sin.sin_addr;
1416			ha = (u_char *)&his_addr.su_sin.sin_addr;
1417			alen = sizeof(struct in_addr);
1418			break;
1419		case AF_INET6:
1420			p = (in_port_t *)&from.su_sin6.sin6_port;
1421			fa = (u_char *)&from.su_sin6.sin6_addr;
1422			ha = (u_char *)&his_addr.su_sin6.sin6_addr;
1423			alen = sizeof(struct in6_addr);
1424			break;
1425		default:
1426			reply(425, "Can't build data connection: "
1427			    "unknown address family");
1428			(void) close(pdata);
1429			(void) close(s);
1430			pdata = -1;
1431			return (NULL);
1432		}
1433		if (from.su_family != his_addr.su_family ||
1434		    ntohs(*p) < IPPORT_RESERVED) {
1435			reply(425, "Can't build data connection: "
1436			    "address family or port error");
1437			(void) close(pdata);
1438			(void) close(s);
1439			pdata = -1;
1440			return (NULL);
1441		}
1442		if (portcheck && memcmp(fa, ha, alen) != 0) {
1443			reply(425, "Can't build data connection: "
1444			    "illegal port number");
1445			(void) close(pdata);
1446			(void) close(s);
1447			pdata = -1;
1448			return (NULL);
1449		}
1450		(void) close(pdata);
1451		pdata = s;
1452		reply(150, "Opening %s mode data connection for '%s'%s.",
1453		    type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1454		return (fdopen(pdata, mode));
1455	}
1456	if (data >= 0) {
1457		reply(125, "Using existing data connection for '%s'%s.",
1458		    name, sizebuf);
1459		usedefault = 1;
1460		return (fdopen(data, mode));
1461	}
1462	if (usedefault)
1463		data_dest = his_addr;
1464	usedefault = 1;
1465	do {
1466		if (file != NULL)
1467			(void) fclose(file);
1468		file = getdatasock(mode);
1469		if (file == NULL) {
1470			char hbuf[MAXHOSTNAMELEN], pbuf[10];
1471
1472			error = getnameinfo((struct sockaddr *)&data_source,
1473			    data_source.su_len, hbuf, sizeof(hbuf), pbuf,
1474			    sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV);
1475			if (error != 0)
1476				reply(425, "Can't create data socket: %s.",
1477				    strerror(errno));
1478			else
1479				reply(425,
1480				    "Can't create data socket (%s,%s): %s.",
1481				    hbuf, pbuf, strerror(errno));
1482			return (NULL);
1483		}
1484
1485		/*
1486		 * attempt to connect to reserved port on client machine;
1487		 * this looks like an attack
1488		 */
1489		switch (data_dest.su_family) {
1490		case AF_INET:
1491			p = (in_port_t *)&data_dest.su_sin.sin_port;
1492			fa = (u_char *)&data_dest.su_sin.sin_addr;
1493			ha = (u_char *)&his_addr.su_sin.sin_addr;
1494			alen = sizeof(struct in_addr);
1495			break;
1496		case AF_INET6:
1497			p = (in_port_t *)&data_dest.su_sin6.sin6_port;
1498			fa = (u_char *)&data_dest.su_sin6.sin6_addr;
1499			ha = (u_char *)&his_addr.su_sin6.sin6_addr;
1500			alen = sizeof(struct in6_addr);
1501			break;
1502		default:
1503			reply(425, "Can't build data connection: "
1504			    "unknown address family");
1505			(void) fclose(file);
1506			pdata = -1;
1507			return (NULL);
1508		}
1509		if (data_dest.su_family != his_addr.su_family ||
1510		    ntohs(*p) < IPPORT_RESERVED || ntohs(*p) == 2049) { /* XXX */
1511			reply(425, "Can't build data connection: "
1512			    "address family or port error");
1513			(void) fclose(file);
1514			return NULL;
1515		}
1516		if (portcheck && memcmp(fa, ha, alen) != 0) {
1517			reply(435, "Can't build data connection: "
1518			    "illegal port number");
1519			(void) fclose(file);
1520			return NULL;
1521		}
1522
1523		if (connect(fileno(file), (struct sockaddr *)&data_dest,
1524		    data_dest.su_len) == 0) {
1525			reply(150, "Opening %s mode data connection for '%s'%s.",
1526			    type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1527			data = fileno(file);
1528			return (file);
1529		}
1530		if (errno != EADDRINUSE)
1531			break;
1532		sleep((unsigned) swaitint);
1533		retry += swaitint;
1534	} while (retry <= swaitmax);
1535	perror_reply(425, "Can't build data connection");
1536	(void) fclose(file);
1537	return (NULL);
1538}
1539
1540/*
1541 * Transfer the contents of "instr" to "outstr" peer using the appropriate
1542 * encapsulation of the data subject to Mode, Structure, and Type.
1543 *
1544 * NB: Form isn't handled.
1545 */
1546static int
1547send_data(FILE *instr, FILE *outstr, off_t blksize, off_t filesize, int isreg)
1548{
1549	int c, cnt, filefd, netfd;
1550	char *buf, *bp;
1551	size_t len;
1552
1553	transflag++;
1554	switch (type) {
1555
1556	case TYPE_A:
1557		while ((c = getc(instr)) != EOF) {
1558			if (recvurg)
1559				goto got_oob;
1560			byte_count++;
1561			if (c == '\n') {
1562				if (ferror(outstr))
1563					goto data_err;
1564				(void) putc('\r', outstr);
1565			}
1566			(void) putc(c, outstr);
1567		}
1568		fflush(outstr);
1569		transflag = 0;
1570		if (ferror(instr))
1571			goto file_err;
1572		if (ferror(outstr))
1573			goto data_err;
1574		reply(226, "Transfer complete.");
1575		return(0);
1576
1577	case TYPE_I:
1578	case TYPE_L:
1579		/*
1580		 * isreg is only set if we are not doing restart and we
1581		 * are sending a regular file
1582		 */
1583		netfd = fileno(outstr);
1584		filefd = fileno(instr);
1585
1586		if (isreg && filesize < (off_t)16 * 1024 * 1024) {
1587			size_t fsize = (size_t)filesize;
1588
1589			if (fsize == 0) {
1590				transflag = 0;
1591				reply(226, "Transfer complete.");
1592				return(0);
1593			}
1594
1595			buf = mmap(0, fsize, PROT_READ, MAP_SHARED, filefd,
1596			    (off_t)0);
1597			if (buf == MAP_FAILED) {
1598				syslog(LOG_WARNING, "mmap(%llu): %m",
1599				    (unsigned long long)fsize);
1600				goto oldway;
1601			}
1602			bp = buf;
1603			len = fsize;
1604			do {
1605				cnt = write(netfd, bp, len);
1606				if (recvurg) {
1607					munmap(buf, fsize);
1608					goto got_oob;
1609				}
1610				len -= cnt;
1611				bp += cnt;
1612				if (cnt > 0)
1613					byte_count += cnt;
1614			} while(cnt > 0 && len > 0);
1615
1616			transflag = 0;
1617			munmap(buf, fsize);
1618			if (cnt < 0)
1619				goto data_err;
1620			reply(226, "Transfer complete.");
1621			return(0);
1622		}
1623
1624oldway:
1625		if ((buf = malloc((size_t)blksize)) == NULL) {
1626			transflag = 0;
1627			perror_reply(451, "Local resource failure: malloc");
1628			return(-1);
1629		}
1630
1631		while ((cnt = read(filefd, buf, (size_t)blksize)) > 0 &&
1632		    write(netfd, buf, cnt) == cnt)
1633			byte_count += cnt;
1634		transflag = 0;
1635		(void)free(buf);
1636		if (cnt != 0) {
1637			if (cnt < 0)
1638				goto file_err;
1639			goto data_err;
1640		}
1641		reply(226, "Transfer complete.");
1642		return(0);
1643	default:
1644		transflag = 0;
1645		reply(550, "Unimplemented TYPE %d in send_data", type);
1646		return(-1);
1647	}
1648
1649data_err:
1650	transflag = 0;
1651	reply(426, "Data connection");
1652	return(-1);
1653
1654file_err:
1655	transflag = 0;
1656	reply(551, "Error on input file");
1657	return(-1);
1658
1659got_oob:
1660	myoob();
1661	recvurg = 0;
1662	transflag = 0;
1663	return(-1);
1664}
1665
1666/*
1667 * Transfer data from peer to "outstr" using the appropriate encapulation of
1668 * the data subject to Mode, Structure, and Type.
1669 *
1670 * N.B.: Form isn't handled.
1671 */
1672static int
1673receive_data(FILE *instr, FILE *outstr)
1674{
1675	int c;
1676	int cnt;
1677	char buf[BUFSIZ];
1678	struct sigaction sa, sa_saved;
1679	volatile int bare_lfs = 0;
1680
1681	transflag++;
1682	switch (type) {
1683
1684	case TYPE_I:
1685	case TYPE_L:
1686		memset(&sa, 0, sizeof(sa));
1687		sigfillset(&sa.sa_mask);
1688		sa.sa_flags = SA_RESTART;
1689		sa.sa_handler = lostconn;
1690		(void) sigaction(SIGALRM, &sa, &sa_saved);
1691		do {
1692			(void) alarm ((unsigned) timeout);
1693			cnt = read(fileno(instr), buf, sizeof(buf));
1694			(void) alarm (0);
1695			if (recvurg)
1696				goto got_oob;
1697
1698			if (cnt > 0) {
1699				if (write(fileno(outstr), buf, cnt) != cnt)
1700					goto file_err;
1701				byte_count += cnt;
1702			}
1703		} while (cnt > 0);
1704		(void) sigaction(SIGALRM, &sa_saved, NULL);
1705		if (cnt < 0)
1706			goto data_err;
1707		transflag = 0;
1708		return (0);
1709
1710	case TYPE_E:
1711		reply(553, "TYPE E not implemented.");
1712		transflag = 0;
1713		return (-1);
1714
1715	case TYPE_A:
1716		while ((c = getc(instr)) != EOF) {
1717			if (recvurg)
1718				goto got_oob;
1719			byte_count++;
1720			if (c == '\n')
1721				bare_lfs++;
1722			while (c == '\r') {
1723				if (ferror(outstr))
1724					goto data_err;
1725				if ((c = getc(instr)) != '\n') {
1726					(void) putc ('\r', outstr);
1727					if (c == '\0' || c == EOF)
1728						goto contin2;
1729				}
1730			}
1731			(void) putc(c, outstr);
1732	contin2:	;
1733		}
1734		fflush(outstr);
1735		if (ferror(instr))
1736			goto data_err;
1737		if (ferror(outstr))
1738			goto file_err;
1739		transflag = 0;
1740		if (bare_lfs) {
1741			lreply(226,
1742			    "WARNING! %d bare linefeeds received in ASCII mode",
1743			    bare_lfs);
1744			printf("   File may not have transferred correctly.\r\n");
1745		}
1746		return (0);
1747	default:
1748		reply(550, "Unimplemented TYPE %d in receive_data", type);
1749		transflag = 0;
1750		return (-1);
1751	}
1752
1753data_err:
1754	transflag = 0;
1755	reply(426, "Data Connection");
1756	return (-1);
1757
1758file_err:
1759	transflag = 0;
1760	reply(452, "Error writing file");
1761	return (-1);
1762
1763got_oob:
1764	myoob();
1765	recvurg = 0;
1766	transflag = 0;
1767	return (-1);
1768}
1769
1770void
1771statfilecmd(char *filename)
1772{
1773	FILE *fin;
1774	int c;
1775	int atstart;
1776	char line[LINE_MAX];
1777
1778	(void)snprintf(line, sizeof(line), "/bin/ls -lgA %s", filename);
1779	fin = ftpd_popen(line, "r");
1780	if (fin == NULL) {
1781		reply(451, "Local resource failure");
1782		return;
1783	}
1784	lreply(211, "status of %s:", filename);
1785	atstart = 1;
1786	while ((c = getc(fin)) != EOF) {
1787		if (c == '\n') {
1788			if (ferror(stdout)){
1789				perror_reply(421, "control connection");
1790				(void) ftpd_pclose(fin);
1791				dologout(1);
1792				/* NOTREACHED */
1793			}
1794			if (ferror(fin)) {
1795				perror_reply(551, filename);
1796				(void) ftpd_pclose(fin);
1797				return;
1798			}
1799			(void) putc('\r', stdout);
1800		}
1801		if (atstart && isdigit(c))
1802			(void) putc(' ', stdout);
1803		(void) putc(c, stdout);
1804		atstart = (c == '\n');
1805	}
1806	(void) ftpd_pclose(fin);
1807	reply(211, "End of Status");
1808}
1809
1810void
1811statcmd(void)
1812{
1813	union sockunion *su;
1814	u_char *a, *p;
1815	char hbuf[MAXHOSTNAMELEN];
1816	int ispassive;
1817	int error;
1818
1819	lreply(211, "%s FTP server status:", hostname);
1820	error = getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len,
1821	    hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
1822	printf("     Connected to %s", remotehost);
1823	if (error == 0 && strcmp(remotehost, hbuf) != 0)
1824		printf(" (%s)", hbuf);
1825	printf("\r\n");
1826	if (logged_in) {
1827		if (guest)
1828			printf("     Logged in anonymously\r\n");
1829		else
1830			printf("     Logged in as %s\r\n", pw->pw_name);
1831	} else if (askpasswd)
1832		printf("     Waiting for password\r\n");
1833	else
1834		printf("     Waiting for user name\r\n");
1835	printf("     TYPE: %s", typenames[type]);
1836	if (type == TYPE_A || type == TYPE_E)
1837		printf(", FORM: %s", formnames[form]);
1838	if (type == TYPE_L)
1839#if NBBY == 8
1840		printf(" %d", NBBY);
1841#else
1842		printf(" %d", bytesize);	/* need definition! */
1843#endif
1844	printf("; STRUcture: %s; transfer MODE: %s\r\n",
1845	    strunames[stru], modenames[mode]);
1846	ispassive = 0;
1847	if (data != -1)
1848		printf("     Data connection open\r\n");
1849	else if (pdata != -1) {
1850		printf("     in Passive mode\r\n");
1851		su = (union sockunion *)&pasv_addr;
1852		ispassive++;
1853		goto printaddr;
1854	} else if (usedefault == 0) {
1855		size_t alen;
1856		int af, i;
1857
1858		su = (union sockunion *)&data_dest;
1859printaddr:
1860		/* PASV/PORT */
1861		if (su->su_family == AF_INET) {
1862			if (ispassive)
1863				printf("211- PASV ");
1864			else
1865				printf("211- PORT ");
1866			a = (u_char *)&su->su_sin.sin_addr;
1867			p = (u_char *)&su->su_sin.sin_port;
1868			printf("(%u,%u,%u,%u,%u,%u)\r\n",
1869			    a[0], a[1], a[2], a[3],
1870			    p[0], p[1]);
1871		}
1872
1873		/* LPSV/LPRT */
1874		alen = 0;
1875		switch (su->su_family) {
1876		case AF_INET:
1877			a = (u_char *)&su->su_sin.sin_addr;
1878			p = (u_char *)&su->su_sin.sin_port;
1879			alen = sizeof(su->su_sin.sin_addr);
1880			af = 4;
1881			break;
1882		case AF_INET6:
1883			a = (u_char *)&su->su_sin6.sin6_addr;
1884			p = (u_char *)&su->su_sin6.sin6_port;
1885			alen = sizeof(su->su_sin6.sin6_addr);
1886			af = 6;
1887			break;
1888		default:
1889			af = 0;
1890			break;
1891		}
1892		if (af) {
1893			if (ispassive)
1894				printf("211- LPSV ");
1895			else
1896				printf("211- LPRT ");
1897			printf("(%u,%llu", af, (unsigned long long)alen);
1898			for (i = 0; i < alen; i++)
1899				printf(",%u", a[i]);
1900			printf(",%u,%u,%u)\r\n", 2, p[0], p[1]);
1901		}
1902
1903		/* EPRT/EPSV */
1904		switch (su->su_family) {
1905		case AF_INET:
1906			af = 1;
1907			break;
1908		case AF_INET6:
1909			af = 2;
1910			break;
1911		default:
1912			af = 0;
1913			break;
1914		}
1915		if (af) {
1916			char pbuf[10];
1917			union sockunion tmp = *su;
1918
1919			if (tmp.su_family == AF_INET6)
1920				tmp.su_sin6.sin6_scope_id = 0;
1921			if (getnameinfo((struct sockaddr *)&tmp, tmp.su_len,
1922			    hbuf, sizeof(hbuf), pbuf, sizeof(pbuf),
1923			    NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
1924				if (ispassive)
1925					printf("211- EPSV ");
1926				else
1927					printf("211- EPRT ");
1928				printf("(|%u|%s|%s|)\r\n",
1929				    af, hbuf, pbuf);
1930			}
1931		}
1932	} else
1933		printf("     No data connection\r\n");
1934	reply(211, "End of status");
1935}
1936
1937void
1938fatal(char *s)
1939{
1940
1941	reply(451, "Error in server: %s", s);
1942	reply(221, "Closing connection due to server error.");
1943	dologout(0);
1944	/* NOTREACHED */
1945}
1946
1947void
1948reply(int n, const char *fmt, ...)
1949{
1950	char *buf, *p, *next;
1951	int rval;
1952	va_list ap;
1953
1954	va_start(ap, fmt);
1955	rval = vasprintf(&buf, fmt, ap);
1956	va_end(ap);
1957	if (rval == -1 || buf == NULL) {
1958		printf("421 Local resource failure: malloc\r\n");
1959		fflush(stdout);
1960		dologout(1);
1961	}
1962	next = buf;
1963	while ((p = strsep(&next, "\n\r"))) {
1964		printf("%d%s %s\r\n", n, (next != '\0') ? "-" : "", p);
1965		if (debug)
1966			syslog(LOG_DEBUG, "<--- %d%s %s", n,
1967			    (next != '\0') ? "-" : "", p);
1968	}
1969	(void)fflush(stdout);
1970	free(buf);
1971}
1972
1973
1974void
1975reply_r(int n, const char *fmt, ...)
1976{
1977	char *p, *next;
1978	char msg[BUFSIZ];
1979	char buf[BUFSIZ];
1980	va_list ap;
1981	struct syslog_data sdata = SYSLOG_DATA_INIT;
1982
1983	sdata.log_fac = LOG_FTP;
1984	va_start(ap, fmt);
1985	vsnprintf(msg, sizeof(msg), fmt, ap);
1986	va_end(ap);
1987
1988	next = msg;
1989
1990	while ((p = strsep(&next, "\n\r"))) {
1991		snprintf(buf, sizeof(buf), "%d%s %s\r\n", n,
1992		    (next != '\0') ? "-" : "", p);
1993		write(STDOUT_FILENO, buf, strlen(buf));
1994		if (debug) {
1995			buf[strlen(buf) - 2] = '\0';
1996			syslog_r(LOG_DEBUG, &sdata, "<--- %s", buf);
1997		}
1998	}
1999}
2000
2001void
2002lreply(int n, const char *fmt, ...)
2003{
2004	va_list ap;
2005
2006	va_start(ap, fmt);
2007	(void)printf("%d- ", n);
2008	(void)vprintf(fmt, ap);
2009	va_end(ap);
2010	(void)printf("\r\n");
2011	(void)fflush(stdout);
2012	if (debug) {
2013		va_start(ap, fmt);
2014		syslog(LOG_DEBUG, "<--- %d- ", n);
2015		vsyslog(LOG_DEBUG, fmt, ap);
2016		va_end(ap);
2017	}
2018}
2019
2020static void
2021ack(char *s)
2022{
2023
2024	reply(250, "%s command successful.", s);
2025}
2026
2027void
2028nack(char *s)
2029{
2030
2031	reply(502, "%s command not implemented.", s);
2032}
2033
2034/* ARGSUSED */
2035void
2036yyerror(char *s)
2037{
2038	cbuf[strcspn(cbuf, "\n")] = '\0';
2039	reply(500, "'%s': command not understood.", cbuf);
2040}
2041
2042void
2043delete(char *name)
2044{
2045	struct stat st;
2046
2047	LOGCMD("delete", name);
2048	if (stat(name, &st) < 0) {
2049		perror_reply(550, name);
2050		return;
2051	}
2052	if ((st.st_mode&S_IFMT) == S_IFDIR) {
2053		if (rmdir(name) < 0) {
2054			perror_reply(550, name);
2055			return;
2056		}
2057		goto done;
2058	}
2059	if (unlink(name) < 0) {
2060		perror_reply(550, name);
2061		return;
2062	}
2063done:
2064	ack("DELE");
2065}
2066
2067void
2068cwd(char *path)
2069{
2070	FILE *message;
2071
2072	if (chdir(path) < 0)
2073		perror_reply(550, path);
2074	else {
2075		if ((message = fopen(_PATH_CWDMESG, "r")) != NULL) {
2076			char line[LINE_MAX];
2077
2078			while (fgets(line, sizeof(line), message) != NULL) {
2079				line[strcspn(line, "\n")] = '\0';
2080				lreply(250, "%s", line);
2081			}
2082			(void) fflush(stdout);
2083			(void) fclose(message);
2084		}
2085		ack("CWD");
2086	}
2087}
2088
2089void
2090replydirname(const char *name, const char *message)
2091{
2092	char *p, *ep;
2093	char npath[MAXPATHLEN * 2];
2094
2095	p = npath;
2096	ep = &npath[sizeof(npath) - 1];
2097	while (*name) {
2098		if (*name == '"') {
2099			if (ep - p < 2)
2100				break;
2101			*p++ = *name++;
2102			*p++ = '"';
2103		} else {
2104			if (ep - p < 1)
2105				break;
2106			*p++ = *name++;
2107		}
2108	}
2109	*p = '\0';
2110	reply(257, "\"%s\" %s", npath, message);
2111}
2112
2113void
2114makedir(char *name)
2115{
2116
2117	LOGCMD("mkdir", name);
2118	if (mkdir(name, 0777) < 0)
2119		perror_reply(550, name);
2120	else
2121		replydirname(name, "directory created.");
2122}
2123
2124void
2125removedir(char *name)
2126{
2127
2128	LOGCMD("rmdir", name);
2129	if (rmdir(name) < 0)
2130		perror_reply(550, name);
2131	else
2132		ack("RMD");
2133}
2134
2135void
2136pwd(void)
2137{
2138	char path[MAXPATHLEN];
2139
2140	if (getcwd(path, sizeof(path)) == NULL)
2141		perror_reply(550, "Can't get current directory");
2142	else
2143		replydirname(path, "is current directory.");
2144}
2145
2146char *
2147renamefrom(char *name)
2148{
2149	struct stat st;
2150
2151	if (stat(name, &st) < 0) {
2152		perror_reply(550, name);
2153		return ((char *)0);
2154	}
2155	reply(350, "File exists, ready for destination name");
2156	return (name);
2157}
2158
2159void
2160renamecmd(char *from, char *to)
2161{
2162
2163	LOGCMD2("rename", from, to);
2164	if (rename(from, to) < 0)
2165		perror_reply(550, "rename");
2166	else
2167		ack("RNTO");
2168}
2169
2170static void
2171dolog(struct sockaddr *sa)
2172{
2173	char hbuf[sizeof(remotehost)];
2174
2175	if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0, 0) == 0)
2176		(void) strlcpy(remotehost, hbuf, sizeof(remotehost));
2177	else
2178		(void) strlcpy(remotehost, "unknown", sizeof(remotehost));
2179
2180#ifdef HASSETPROCTITLE
2181	snprintf(proctitle, sizeof(proctitle), "%s: connected", remotehost);
2182	setproctitle("%s", proctitle);
2183#endif /* HASSETPROCTITLE */
2184
2185	if (logging) {
2186		int error;
2187		error = getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf),
2188		    NULL, 0, NI_NUMERICHOST);
2189		syslog(LOG_INFO, "connection from %s [%s]", remotehost,
2190		    error ? gai_strerror(error) : hbuf);
2191	}
2192}
2193
2194/*
2195 * Record logout in wtmp file and exit with supplied status.
2196 * NOTE: because this is called from signal handlers it cannot
2197 *       use stdio (or call other functions that use stdio).
2198 */
2199void
2200dologout(int status)
2201{
2202
2203	transflag = 0;
2204
2205	if (logged_in) {
2206		sigprocmask(SIG_BLOCK, &allsigs, NULL);
2207		if (!nowtmp)
2208			ftpdlogwtmp(ttyline, "", "");
2209		if (doutmp)
2210			ftpd_logout(utmp.ut_line);
2211	}
2212	/* beware of flushing buffers after a SIGPIPE */
2213	_exit(status);
2214}
2215
2216/*ARGSUSED*/
2217static void
2218sigurg(int signo)
2219{
2220
2221	recvurg = 1;
2222}
2223
2224static void
2225myoob(void)
2226{
2227	char *cp;
2228	int ret;
2229
2230	/* only process if transfer occurring */
2231	if (!transflag)
2232		return;
2233	cp = tmpline;
2234	ret = get_line(cp, sizeof(tmpline)-1, stdin);
2235	if (ret == -1) {
2236		reply(221, "You could at least say goodbye.");
2237		dologout(0);
2238	} else if (ret == -2) {
2239		/* Ignore truncated command */
2240		return;
2241	}
2242	upper(cp);
2243	if (strcmp(cp, "ABOR\r\n") == 0) {
2244		tmpline[0] = '\0';
2245		reply(426, "Transfer aborted. Data connection closed.");
2246		reply(226, "Abort successful");
2247	}
2248	if (strcmp(cp, "STAT\r\n") == 0) {
2249		tmpline[0] = '\0';
2250		if (file_size != (off_t) -1)
2251			reply(213, "Status: %qd of %qd bytes transferred",
2252			    byte_count, file_size);
2253		else
2254			reply(213, "Status: %qd bytes transferred", byte_count);
2255	}
2256}
2257
2258/*
2259 * Note: a response of 425 is not mentioned as a possible response to
2260 *	the PASV command in RFC959. However, it has been blessed as
2261 *	a legitimate response by Jon Postel in a telephone conversation
2262 *	with Rick Adams on 25 Jan 89.
2263 */
2264void
2265passive(void)
2266{
2267	socklen_t len;
2268	int on = 1;
2269	u_char *p, *a;
2270
2271	if (pw == NULL) {
2272		reply(530, "Please login with USER and PASS");
2273		return;
2274	}
2275	if (pdata >= 0)
2276		close(pdata);
2277	/*
2278	 * XXX
2279	 * At this point, it would be nice to have an algorithm that
2280	 * inserted a growing delay in an attack scenario.  Such a thing
2281	 * would look like continual passive sockets being opened, but
2282	 * nothing serious being done with them.  They're not used to
2283	 * move data; the entire attempt is just to use tcp FIN_WAIT
2284	 * resources.
2285	 */
2286	pdata = socket(AF_INET, SOCK_STREAM, 0);
2287	if (pdata < 0) {
2288		perror_reply(425, "Can't open passive connection");
2289		return;
2290	}
2291
2292	if (setsockopt(pdata, SOL_SOCKET, SO_KEEPALIVE,
2293	    &on, sizeof(on)) < 0)
2294		goto pasv_error;
2295
2296	on = IP_PORTRANGE_HIGH;
2297	if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2298	    &on, sizeof(on)) < 0)
2299		goto pasv_error;
2300
2301	pasv_addr = ctrl_addr;
2302	pasv_addr.su_sin.sin_port = 0;
2303	if (bind(pdata, (struct sockaddr *)&pasv_addr,
2304	    pasv_addr.su_len) < 0)
2305		goto pasv_error;
2306
2307	len = sizeof(pasv_addr);
2308	if (getsockname(pdata, (struct sockaddr *)&pasv_addr, &len) < 0)
2309		goto pasv_error;
2310	if (listen(pdata, 1) < 0)
2311		goto pasv_error;
2312	a = (u_char *)&pasv_addr.su_sin.sin_addr;
2313	p = (u_char *)&pasv_addr.su_sin.sin_port;
2314
2315	reply(227, "Entering Passive Mode (%u,%u,%u,%u,%u,%u)", a[0],
2316	    a[1], a[2], a[3], p[0], p[1]);
2317	return;
2318
2319pasv_error:
2320	perror_reply(425, "Can't open passive connection");
2321	(void) close(pdata);
2322	pdata = -1;
2323	return;
2324}
2325
2326int
2327epsvproto2af(int proto)
2328{
2329
2330	switch (proto) {
2331	case 1:	return AF_INET;
2332#ifdef INET6
2333	case 2:	return AF_INET6;
2334#endif
2335	default: return -1;
2336	}
2337}
2338
2339int
2340af2epsvproto(int af)
2341{
2342
2343	switch (af) {
2344	case AF_INET:	return 1;
2345#ifdef INET6
2346	case AF_INET6:	return 2;
2347#endif
2348	default:	return -1;
2349	}
2350}
2351
2352/*
2353 * 228 Entering Long Passive Mode (af, hal, h1, h2, h3,..., pal, p1, p2...)
2354 * 229 Entering Extended Passive Mode (|||port|)
2355 */
2356void
2357long_passive(char *cmd, int pf)
2358{
2359	socklen_t len;
2360	int on = 1;
2361	u_char *p, *a;
2362
2363	if (!logged_in) {
2364		syslog(LOG_NOTICE, "long passive but not logged in");
2365		reply(503, "Login with USER first.");
2366		return;
2367	}
2368
2369	if (pf != PF_UNSPEC && ctrl_addr.su_family != pf) {
2370		/*
2371		 * XXX
2372		 * only EPRT/EPSV ready clients will understand this
2373		 */
2374		if (strcmp(cmd, "EPSV") != 0)
2375			reply(501, "Network protocol mismatch"); /*XXX*/
2376		else
2377			epsv_protounsupp("Network protocol mismatch");
2378
2379		return;
2380	}
2381
2382	if (pdata >= 0)
2383		close(pdata);
2384	/*
2385	 * XXX
2386	 * At this point, it would be nice to have an algorithm that
2387	 * inserted a growing delay in an attack scenario.  Such a thing
2388	 * would look like continual passive sockets being opened, but
2389	 * nothing serious being done with them.  They not used to move
2390	 * data; the entire attempt is just to use tcp FIN_WAIT
2391	 * resources.
2392	 */
2393	pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0);
2394	if (pdata < 0) {
2395		perror_reply(425, "Can't open passive connection");
2396		return;
2397	}
2398
2399	if (setsockopt(pdata, SOL_SOCKET, SO_KEEPALIVE,
2400	    &on, sizeof(on)) < 0)
2401		goto pasv_error;
2402
2403	switch (ctrl_addr.su_family) {
2404	case AF_INET:
2405		on = IP_PORTRANGE_HIGH;
2406		if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2407		    &on, sizeof(on)) < 0)
2408			goto pasv_error;
2409		break;
2410	case AF_INET6:
2411		on = IPV6_PORTRANGE_HIGH;
2412		if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE,
2413		    &on, sizeof(on)) < 0)
2414			goto pasv_error;
2415		break;
2416	}
2417
2418	pasv_addr = ctrl_addr;
2419	pasv_addr.su_port = 0;
2420	if (bind(pdata, (struct sockaddr *)&pasv_addr, pasv_addr.su_len) < 0)
2421		goto pasv_error;
2422	len = pasv_addr.su_len;
2423	if (getsockname(pdata, (struct sockaddr *)&pasv_addr, &len) < 0)
2424		goto pasv_error;
2425	if (listen(pdata, 1) < 0)
2426		goto pasv_error;
2427	p = (u_char *)&pasv_addr.su_port;
2428
2429	if (strcmp(cmd, "LPSV") == 0) {
2430		switch (pasv_addr.su_family) {
2431		case AF_INET:
2432			a = (u_char *)&pasv_addr.su_sin.sin_addr;
2433			reply(228,
2434			    "Entering Long Passive Mode (%u,%u,%u,%u,%u,%u,%u,%u,%u)",
2435			    4, 4, a[0], a[1], a[2], a[3], 2, p[0], p[1]);
2436			return;
2437		case AF_INET6:
2438			a = (u_char *)&pasv_addr.su_sin6.sin6_addr;
2439			reply(228,
2440			    "Entering Long Passive Mode (%u,%u,%u,%u,%u,%u,"
2441			    "%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u)",
2442				6, 16, a[0], a[1], a[2], a[3], a[4],
2443				a[5], a[6], a[7], a[8], a[9], a[10],
2444				a[11], a[12], a[13], a[14], a[15],
2445				2, p[0], p[1]);
2446			return;
2447		}
2448	} else if (strcmp(cmd, "EPSV") == 0) {
2449		switch (pasv_addr.su_family) {
2450		case AF_INET:
2451		case AF_INET6:
2452			reply(229, "Entering Extended Passive Mode (|||%u|)",
2453			    ntohs(pasv_addr.su_port));
2454			return;
2455		}
2456	} else {
2457		/* more proper error code? */
2458	}
2459
2460  pasv_error:
2461	perror_reply(425, "Can't open passive connection");
2462	(void) close(pdata);
2463	pdata = -1;
2464	return;
2465}
2466
2467/*
2468 * EPRT |proto|addr|port|
2469 */
2470int
2471extended_port(const char *arg)
2472{
2473	char *tmp = NULL;
2474	char *result[3];
2475	char *p, *q;
2476	char delim;
2477	struct addrinfo hints;
2478	struct addrinfo *res = NULL;
2479	int i;
2480	unsigned long proto;
2481
2482	if (epsvall) {
2483		reply(501, "EPRT disallowed after EPSV ALL");
2484		return -1;
2485	}
2486
2487	usedefault = 0;
2488	if (pdata >= 0) {
2489		(void) close(pdata);
2490		pdata = -1;
2491	}
2492
2493	tmp = strdup(arg);
2494	if (!tmp) {
2495		fatal("not enough core.");
2496		/*NOTREACHED*/
2497	}
2498	p = tmp;
2499	delim = p[0];
2500	p++;
2501	memset(result, 0, sizeof(result));
2502	for (i = 0; i < 3; i++) {
2503		q = strchr(p, delim);
2504		if (!q || *q != delim)
2505			goto parsefail;
2506		*q++ = '\0';
2507		result[i] = p;
2508		p = q;
2509	}
2510
2511	/* some more sanity check */
2512	p = NULL;
2513	(void)strtoul(result[2], &p, 10);
2514	if (!*result[2] || *p)
2515		goto protounsupp;
2516	p = NULL;
2517	proto = strtoul(result[0], &p, 10);
2518	if (!*result[0] || *p)
2519		goto protounsupp;
2520
2521	memset(&hints, 0, sizeof(hints));
2522	hints.ai_family = epsvproto2af((int)proto);
2523	if (hints.ai_family < 0)
2524		goto protounsupp;
2525	hints.ai_socktype = SOCK_STREAM;
2526	hints.ai_flags = AI_NUMERICHOST;	/*no DNS*/
2527	if (getaddrinfo(result[1], result[2], &hints, &res))
2528		goto parsefail;
2529	if (res->ai_next)
2530		goto parsefail;
2531	if (sizeof(data_dest) < res->ai_addrlen)
2532		goto parsefail;
2533	memcpy(&data_dest, res->ai_addr, res->ai_addrlen);
2534	if (his_addr.su_family == AF_INET6 &&
2535	    data_dest.su_family == AF_INET6) {
2536		/* XXX more sanity checks! */
2537		data_dest.su_sin6.sin6_scope_id =
2538		    his_addr.su_sin6.sin6_scope_id;
2539	}
2540	if (pdata >= 0) {
2541		(void) close(pdata);
2542		pdata = -1;
2543	}
2544	reply(200, "EPRT command successful.");
2545
2546	if (tmp)
2547		free(tmp);
2548	if (res)
2549		freeaddrinfo(res);
2550	return 0;
2551
2552parsefail:
2553	reply(500, "Invalid argument, rejected.");
2554	usedefault = 1;
2555	if (tmp)
2556		free(tmp);
2557	if (res)
2558		freeaddrinfo(res);
2559	return -1;
2560
2561protounsupp:
2562	epsv_protounsupp("Protocol not supported");
2563	usedefault = 1;
2564	if (tmp)
2565		free(tmp);
2566	if (res)
2567		freeaddrinfo(res);
2568	return -1;
2569}
2570
2571/*
2572 * 522 Protocol not supported (proto,...)
2573 * as we assume address family for control and data connections are the same,
2574 * we do not return the list of address families we support - instead, we
2575 * return the address family of the control connection.
2576 */
2577void
2578epsv_protounsupp(const char *message)
2579{
2580	int proto;
2581
2582	proto = af2epsvproto(ctrl_addr.su_family);
2583	if (proto < 0)
2584		reply(501, "%s", message);	/*XXX*/
2585	else
2586		reply(522, "%s, use (%d)", message, proto);
2587}
2588
2589/*
2590 * Generate unique name for file with basename "local".
2591 * The file named "local" is already known to exist.
2592 * Generates failure reply on error.
2593 */
2594static int
2595guniquefd(char *local, char **nam)
2596{
2597	static char new[MAXPATHLEN];
2598	struct stat st;
2599	int count, len, fd;
2600	char *cp;
2601
2602	cp = strrchr(local, '/');
2603	if (cp)
2604		*cp = '\0';
2605	if (stat(cp ? local : ".", &st) < 0) {
2606		perror_reply(553, cp ? local : ".");
2607		return (-1);
2608	}
2609	if (cp)
2610		*cp = '/';
2611	len = strlcpy(new, local, sizeof(new));
2612	if (len+2+1 >= sizeof(new)-1)
2613		return (-1);
2614	cp = new + len;
2615	*cp++ = '.';
2616	for (count = 1; count < 100; count++) {
2617		(void)snprintf(cp, sizeof(new) - (cp - new), "%d", count);
2618		fd = open(new, O_RDWR|O_CREAT|O_EXCL, 0666);
2619		if (fd == -1)
2620			continue;
2621		if (nam)
2622			*nam = new;
2623		return (fd);
2624	}
2625	reply(452, "Unique file name cannot be created.");
2626	return (-1);
2627}
2628
2629/*
2630 * Format and send reply containing system error number.
2631 */
2632void
2633perror_reply(int code, char *string)
2634{
2635
2636	reply(code, "%s: %s.", string, strerror(errno));
2637}
2638
2639static char *onefile[] = {
2640	"",
2641	0
2642};
2643
2644void
2645send_file_list(char *whichf)
2646{
2647	struct stat st;
2648	DIR *dirp = NULL;
2649	struct dirent *dir;
2650	FILE *dout = NULL;
2651	char **dirlist;
2652	char *dirname;
2653	int simple = 0;
2654	volatile int freeglob = 0;
2655	glob_t gl;
2656
2657	if (strpbrk(whichf, "~{[*?") != NULL) {
2658		memset(&gl, 0, sizeof(gl));
2659		freeglob = 1;
2660		if (glob(whichf,
2661		    GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE|GLOB_LIMIT,
2662		    0, &gl)) {
2663			reply(550, "not found");
2664			goto out;
2665		} else if (gl.gl_pathc == 0) {
2666			errno = ENOENT;
2667			perror_reply(550, whichf);
2668			goto out;
2669		}
2670		dirlist = gl.gl_pathv;
2671	} else {
2672		onefile[0] = whichf;
2673		dirlist = onefile;
2674		simple = 1;
2675	}
2676
2677	while ((dirname = *dirlist++)) {
2678		if (stat(dirname, &st) < 0) {
2679			/*
2680			 * If user typed "ls -l", etc, and the client
2681			 * used NLST, do what the user meant.
2682			 */
2683			if (dirname[0] == '-' && *dirlist == NULL &&
2684			    transflag == 0) {
2685				retrieve("/bin/ls %s", dirname);
2686				goto out;
2687			}
2688			perror_reply(550, whichf);
2689			if (dout != NULL) {
2690				(void) fclose(dout);
2691				transflag = 0;
2692				data = -1;
2693				pdata = -1;
2694			}
2695			goto out;
2696		}
2697
2698		if (S_ISREG(st.st_mode)) {
2699			if (dout == NULL) {
2700				dout = dataconn("file list", (off_t)-1, "w");
2701				if (dout == NULL)
2702					goto out;
2703				transflag++;
2704			}
2705			fprintf(dout, "%s%s\n", dirname,
2706				type == TYPE_A ? "\r" : "");
2707			byte_count += strlen(dirname) + 1;
2708			continue;
2709		} else if (!S_ISDIR(st.st_mode))
2710			continue;
2711
2712		if ((dirp = opendir(dirname)) == NULL)
2713			continue;
2714
2715		while ((dir = readdir(dirp)) != NULL) {
2716			char nbuf[MAXPATHLEN];
2717
2718			if (recvurg) {
2719				myoob();
2720				recvurg = 0;
2721				transflag = 0;
2722				goto out;
2723			}
2724
2725			if (dir->d_name[0] == '.' && dir->d_namlen == 1)
2726				continue;
2727			if (dir->d_name[0] == '.' && dir->d_name[1] == '.' &&
2728			    dir->d_namlen == 2)
2729				continue;
2730
2731			snprintf(nbuf, sizeof(nbuf), "%s/%s", dirname,
2732				 dir->d_name);
2733
2734			/*
2735			 * We have to do a stat to insure it's
2736			 * not a directory or special file.
2737			 */
2738			if (simple || (stat(nbuf, &st) == 0 &&
2739			    S_ISREG(st.st_mode))) {
2740				if (dout == NULL) {
2741					dout = dataconn("file list", (off_t)-1,
2742						"w");
2743					if (dout == NULL)
2744						goto out;
2745					transflag++;
2746				}
2747				if (nbuf[0] == '.' && nbuf[1] == '/')
2748					fprintf(dout, "%s%s\n", &nbuf[2],
2749						type == TYPE_A ? "\r" : "");
2750				else
2751					fprintf(dout, "%s%s\n", nbuf,
2752						type == TYPE_A ? "\r" : "");
2753				byte_count += strlen(nbuf) + 1;
2754			}
2755		}
2756		(void) closedir(dirp);
2757	}
2758
2759	if (dout == NULL)
2760		reply(550, "No files found.");
2761	else if (ferror(dout) != 0)
2762		perror_reply(550, "Data connection");
2763	else
2764		reply(226, "Transfer complete.");
2765
2766	transflag = 0;
2767	if (dout != NULL)
2768		(void) fclose(dout);
2769	else {
2770		if (pdata >= 0)
2771			close(pdata);
2772	}
2773	data = -1;
2774	pdata = -1;
2775out:
2776	if (freeglob) {
2777		freeglob = 0;
2778		globfree(&gl);
2779	}
2780}
2781
2782/*ARGSUSED*/
2783static void
2784reapchild(int signo)
2785{
2786	int save_errno = errno;
2787	int rval;
2788
2789	do {
2790		rval = waitpid(-1, NULL, WNOHANG);
2791	} while (rval > 0 || (rval == -1 && errno == EINTR));
2792	errno = save_errno;
2793}
2794
2795void
2796logxfer(char *name, off_t size, time_t start)
2797{
2798	char buf[400 + MAXHOSTNAMELEN*4 + MAXPATHLEN*4];
2799	char dir[MAXPATHLEN], path[MAXPATHLEN], rpath[MAXPATHLEN];
2800	char vremotehost[MAXHOSTNAMELEN*4], vpath[MAXPATHLEN*4];
2801	char *vpw;
2802	time_t now;
2803	int len;
2804
2805	if ((statfd >= 0) && (getcwd(dir, sizeof(dir)) != NULL)) {
2806		time(&now);
2807
2808		vpw = malloc(strlen(guest ? guestpw : pw->pw_name) * 4 + 1);
2809		if (vpw == NULL)
2810			return;
2811
2812		snprintf(path, sizeof(path), "%s/%s", dir, name);
2813		if (realpath(path, rpath) == NULL)
2814			strlcpy(rpath, path, sizeof(rpath));
2815		strvis(vpath, rpath, VIS_SAFE|VIS_NOSLASH);
2816
2817		strvis(vremotehost, remotehost, VIS_SAFE|VIS_NOSLASH);
2818		strvis(vpw, guest? guestpw : pw->pw_name, VIS_SAFE|VIS_NOSLASH);
2819
2820		len = snprintf(buf, sizeof(buf),
2821		    "%.24s %lld %s %qd %s %c %s %c %c %s ftp %d %s %s\n",
2822		    ctime(&now), (long long)(now - start + (now == start)),
2823		    vremotehost, (long long)size, vpath,
2824		    ((type == TYPE_A) ? 'a' : 'b'), "*" /* none yet */,
2825		    'o', ((guest) ? 'a' : 'r'),
2826		    vpw, 0 /* none yet */,
2827		    ((guest) ? "*" : pw->pw_name), dhostname);
2828		free(vpw);
2829
2830		if (len >= sizeof(buf) || len == -1) {
2831			if ((len = strlen(buf)) == 0)
2832				return;		/* should not happen */
2833			buf[len - 1] = '\n';
2834		}
2835		write(statfd, buf, len);
2836	}
2837}
2838
2839void
2840set_slave_signals(void)
2841{
2842	struct sigaction sa;
2843
2844	sigemptyset(&sa.sa_mask);
2845	sa.sa_flags = SA_RESTART;
2846
2847	sa.sa_handler = SIG_DFL;
2848	(void) sigaction(SIGCHLD, &sa, NULL);
2849
2850	sa.sa_handler = sigurg;
2851	sa.sa_flags = 0;		/* don't restart syscalls for SIGURG */
2852	(void) sigaction(SIGURG, &sa, NULL);
2853
2854	sigfillset(&sa.sa_mask);	/* block all signals in handler */
2855	sa.sa_flags = SA_RESTART;
2856	sa.sa_handler = sigquit;
2857	(void) sigaction(SIGHUP, &sa, NULL);
2858	(void) sigaction(SIGINT, &sa, NULL);
2859	(void) sigaction(SIGQUIT, &sa, NULL);
2860	(void) sigaction(SIGTERM, &sa, NULL);
2861
2862	sa.sa_handler = lostconn;
2863	(void) sigaction(SIGPIPE, &sa, NULL);
2864
2865	sa.sa_handler = toolong;
2866	(void) sigaction(SIGALRM, &sa, NULL);
2867
2868#ifdef F_SETOWN
2869	if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1)
2870		syslog(LOG_ERR, "fcntl F_SETOWN: %m");
2871#endif
2872}
2873
2874#if defined(TCPWRAPPERS)
2875static int
2876check_host(struct sockaddr *sa)
2877{
2878	struct sockaddr_in *sin;
2879	struct hostent *hp;
2880	char *addr;
2881
2882	if (sa->sa_family != AF_INET)
2883		return 1;	/*XXX*/
2884
2885	sin = (struct sockaddr_in *)sa;
2886	hp = gethostbyaddr((char *)&sin->sin_addr,
2887	    sizeof(struct in_addr), AF_INET);
2888	addr = inet_ntoa(sin->sin_addr);
2889	if (hp) {
2890		if (!hosts_ctl("ftpd", hp->h_name, addr, STRING_UNKNOWN)) {
2891			syslog(LOG_NOTICE, "tcpwrappers rejected: %s [%s]",
2892			    hp->h_name, addr);
2893			return (0);
2894		}
2895	} else {
2896		if (!hosts_ctl("ftpd", STRING_UNKNOWN, addr, STRING_UNKNOWN)) {
2897			syslog(LOG_NOTICE, "tcpwrappers rejected: [%s]", addr);
2898			return (0);
2899		}
2900	}
2901	return (1);
2902}
2903#endif	/* TCPWRAPPERS */
2904
2905/*
2906 * Allocate space and return a copy of the specified dir.
2907 * If 'dir' begins with a tilde (~), expand it.
2908 */
2909char *
2910copy_dir(char *dir, struct passwd *pw)
2911{
2912	char *cp;
2913	char *newdir;
2914	char *user = NULL;
2915
2916	/* Nothing to expand */
2917	if (dir[0] != '~')
2918		return (strdup(dir));
2919
2920	/* "dir" is of form ~user/some/dir, lookup user. */
2921	if (dir[1] != '/' && dir[1] != '\0') {
2922		if ((cp = strchr(dir + 1, '/')) == NULL)
2923			cp = dir + strlen(dir);
2924		if ((user = malloc((size_t)(cp - dir))) == NULL)
2925			return (NULL);
2926		strlcpy(user, dir + 1, (size_t)(cp - dir));
2927
2928		/* Only do lookup if it is a different user. */
2929		if (strcmp(user, pw->pw_name) != 0) {
2930			if ((pw = getpwnam(user)) == NULL) {
2931				/* No such user, interpret literally */
2932				free(user);
2933				return(strdup(dir));
2934			}
2935		}
2936		free(user);
2937	}
2938
2939	/*
2940	 * If there is no directory separator (/) then it is just pw_dir.
2941	 * Otherwise, replace ~foo with pw_dir.
2942	 */
2943	if ((cp = strchr(dir + 1, '/')) == NULL) {
2944		newdir = strdup(pw->pw_dir);
2945	} else {
2946		if (asprintf(&newdir, "%s%s", pw->pw_dir, cp) == -1)
2947			return (NULL);
2948	}
2949
2950	return(newdir);
2951}
2952