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