ftpd.c revision 1.197
1290001Sglebius/*	$OpenBSD: ftpd.c,v 1.197 2013/07/26 18:13:02 guenther Exp $	*/
2290001Sglebius/*	$NetBSD: ftpd.c,v 1.15 1995/06/03 22:46:47 mycroft Exp $	*/
3290001Sglebius
4290001Sglebius/*
5290001Sglebius * Copyright (C) 1997 and 1998 WIDE Project.
6290001Sglebius * All rights reserved.
7290001Sglebius *
8290001Sglebius * Redistribution and use in source and binary forms, with or without
9290001Sglebius * modification, are permitted provided that the following conditions
10290001Sglebius * are met:
11290001Sglebius * 1. Redistributions of source code must retain the above copyright
12290001Sglebius *    notice, this list of conditions and the following disclaimer.
13290001Sglebius * 2. Redistributions in binary form must reproduce the above copyright
14290001Sglebius *    notice, this list of conditions and the following disclaimer in the
15290001Sglebius *    documentation and/or other materials provided with the distribution.
16290001Sglebius * 3. Neither the name of the project nor the names of its contributors
17290001Sglebius *    may be used to endorse or promote products derived from this software
18290001Sglebius *    without specific prior written permission.
19290001Sglebius *
20290001Sglebius * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21290001Sglebius * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22290001Sglebius * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23290001Sglebius * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24290001Sglebius * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25290001Sglebius * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26290001Sglebius * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27290001Sglebius * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28290001Sglebius * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29290001Sglebius * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30290001Sglebius * SUCH DAMAGE.
31290001Sglebius */
32290001Sglebius
33290001Sglebius/*
34290001Sglebius * Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994
35290001Sglebius *	The Regents of the University of California.  All rights reserved.
36290001Sglebius *
37290001Sglebius * Redistribution and use in source and binary forms, with or without
38290001Sglebius * modification, are permitted provided that the following conditions
39290001Sglebius * are met:
40290001Sglebius * 1. Redistributions of source code must retain the above copyright
41290001Sglebius *    notice, this list of conditions and the following disclaimer.
42290001Sglebius * 2. Redistributions in binary form must reproduce the above copyright
43290001Sglebius *    notice, this list of conditions and the following disclaimer in the
44290001Sglebius *    documentation and/or other materials provided with the distribution.
45290001Sglebius * 3. Neither the name of the University nor the names of its contributors
46290001Sglebius *    may be used to endorse or promote products derived from this software
47290001Sglebius *    without specific prior written permission.
48290001Sglebius *
49290001Sglebius * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50290001Sglebius * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51290001Sglebius * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52290001Sglebius * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53290001Sglebius * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54290001Sglebius * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55290001Sglebius * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56290001Sglebius * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57290001Sglebius * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58290001Sglebius * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59290001Sglebius * SUCH DAMAGE.
60290001Sglebius */
61290001Sglebius
62290001Sglebius/*
63290001Sglebius * FTP server.
64290001Sglebius */
65290001Sglebius#include <sys/stat.h>
66290001Sglebius#include <sys/ioctl.h>
67290001Sglebius#include <sys/socket.h>
68290001Sglebius#include <sys/wait.h>
69290001Sglebius#include <sys/mman.h>
70290001Sglebius
71290001Sglebius#include <netinet/in.h>
72290001Sglebius#include <netinet/in_systm.h>
73290001Sglebius#include <netinet/ip.h>
74290001Sglebius#include <netinet/tcp.h>
75290001Sglebius
76290001Sglebius#define	FTP_NAMES
77290001Sglebius#include <arpa/ftp.h>
78290001Sglebius#include <arpa/inet.h>
79290001Sglebius#include <arpa/telnet.h>
80290001Sglebius
81290001Sglebius#include <bsd_auth.h>
82290001Sglebius#include <ctype.h>
83290001Sglebius#include <dirent.h>
84290001Sglebius#include <errno.h>
85290001Sglebius#include <fcntl.h>
86290001Sglebius#include <glob.h>
87290001Sglebius#include <limits.h>
88290001Sglebius#include <login_cap.h>
89290001Sglebius#include <netdb.h>
90290001Sglebius#include <pwd.h>
91290001Sglebius#include <signal.h>
92290001Sglebius#include <stdarg.h>
93290001Sglebius#include <stdio.h>
94290001Sglebius#include <stdlib.h>
95290001Sglebius#include <string.h>
96290001Sglebius#include <syslog.h>
97290001Sglebius#include <time.h>
98290001Sglebius#include <vis.h>
99290001Sglebius#include <unistd.h>
100290001Sglebius#include <util.h>
101290001Sglebius#include <utmp.h>
102290001Sglebius#include <poll.h>
103290001Sglebius
104290001Sglebius#if defined(TCPWRAPPERS)
105290001Sglebius#include <tcpd.h>
106290001Sglebius#endif	/* TCPWRAPPERS */
107290001Sglebius
108290001Sglebius#include "pathnames.h"
109290001Sglebius#include "monitor.h"
110290001Sglebius#include "extern.h"
111290001Sglebius
112290001Sglebiusextern	off_t restart_point;
113290001Sglebiusextern	char cbuf[];
114290001Sglebius
115290001Sglebiusunion sockunion ctrl_addr;
116290001Sglebiusunion sockunion data_source;
117290001Sglebiusunion sockunion data_dest;
118290001Sglebiusunion sockunion his_addr;
119290001Sglebiusunion sockunion pasv_addr;
120290001Sglebius
121290001Sglebiussigset_t allsigs;
122290001Sglebius
123290001Sglebiusint	daemon_mode = 0;
124290001Sglebiusint	data;
125290001Sglebiusint	logged_in;
126290001Sglebiusstruct	passwd *pw;
127290001Sglebiusint	debug = 0;
128290001Sglebiusint	timeout = 900;    /* timeout after 15 minutes of inactivity */
129290001Sglebiusint	maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */
130290001Sglebiusint	logging;
131290001Sglebiusint	anon_ok = 1;
132290001Sglebiusint	anon_only = 0;
133290001Sglebiusint	multihome = 0;
134290001Sglebiusint	guest;
135290001Sglebiusint	stats;
136290001Sglebiusint	statfd = -1;
137290001Sglebiusint	portcheck = 1;
138290001Sglebiusint	dochroot;
139290001Sglebiusint	type;
140290001Sglebiusint	form;
141290001Sglebiusint	stru;			/* avoid C keyword */
142290001Sglebiusint	mode;
143290001Sglebiusint	doutmp = 0;		/* update utmp file */
144290001Sglebiusint	nowtmp = 0;		/* do not update wtmp file */
145290001Sglebiusint	usedefault = 1;		/* for data transfers */
146290001Sglebiusint	pdata = -1;		/* for passive mode */
147290001Sglebiusint	family = AF_UNSPEC;
148290001Sglebiusvolatile sig_atomic_t transflag;
149290001Sglebiusoff_t	file_size;
150290001Sglebiusoff_t	byte_count;
151290001Sglebius#if !defined(CMASK) || CMASK == 0
152290001Sglebius#undef CMASK
153290001Sglebius#define CMASK 022
154290001Sglebius#endif
155290001Sglebiusmode_t	defumask = CMASK;		/* default umask value */
156290001Sglebiusint	umaskchange = 1;		/* allow user to change umask value. */
157290001Sglebiuschar	tmpline[7];
158290001Sglebiuschar	hostname[MAXHOSTNAMELEN];
159290001Sglebiuschar	remotehost[MAXHOSTNAMELEN];
160290001Sglebiuschar	dhostname[MAXHOSTNAMELEN];
161290001Sglebiuschar	*guestpw;
162290001Sglebiuschar	ttyline[20];
163290001Sglebius#if 0
164290001Sglebiuschar	*tty = ttyline;		/* for klogin */
165290001Sglebius#endif
166290001Sglebiusstatic struct utmp utmp;	/* for utmp */
167290001Sglebiusstatic	login_cap_t *lc;
168290001Sglebiusstatic	auth_session_t *as;
169290001Sglebiusstatic	volatile sig_atomic_t recvurg;
170290001Sglebius
171290001Sglebius#if defined(TCPWRAPPERS)
172290001Sglebiusint	allow_severity = LOG_INFO;
173290001Sglebiusint	deny_severity = LOG_NOTICE;
174290001Sglebius#endif	/* TCPWRAPPERS */
175290001Sglebius
176290001Sglebiusint epsvall = 0;
177290001Sglebius
178290001Sglebius/*
179290001Sglebius * Timeout intervals for retrying connections
180290001Sglebius * to hosts that don't accept PORT cmds.  This
181290001Sglebius * is a kludge, but given the problems with TCP...
182290001Sglebius */
183290001Sglebius#define	SWAITMAX	90	/* wait at most 90 seconds */
184290001Sglebius#define	SWAITINT	5	/* interval between retries */
185290001Sglebius
186290001Sglebiusint	swaitmax = SWAITMAX;
187290001Sglebiusint	swaitint = SWAITINT;
188290001Sglebius
189290001Sglebius#ifdef HASSETPROCTITLE
190290001Sglebiuschar	proctitle[BUFSIZ];	/* initial part of title */
191290001Sglebius#endif /* HASSETPROCTITLE */
192290001Sglebius
193290001Sglebius#define LOGCMD(cmd, file) \
194290001Sglebius	if (logging > 1) \
195290001Sglebius	    syslog(LOG_INFO,"%s %s%s", cmd, \
196290001Sglebius		*(file) == '/' ? "" : curdir(), file);
197290001Sglebius#define LOGCMD2(cmd, file1, file2) \
198290001Sglebius	 if (logging > 1) \
199290001Sglebius	    syslog(LOG_INFO,"%s %s%s %s%s", cmd, \
200290001Sglebius		*(file1) == '/' ? "" : curdir(), file1, \
201290001Sglebius		*(file2) == '/' ? "" : curdir(), file2);
202290001Sglebius#define LOGBYTES(cmd, file, cnt) \
203290001Sglebius	if (logging > 1) { \
204290001Sglebius		if (cnt == (off_t)-1) \
205290001Sglebius		    syslog(LOG_INFO,"%s %s%s", cmd, \
206290001Sglebius			*(file) == '/' ? "" : curdir(), file); \
207290001Sglebius		else \
208290001Sglebius		    syslog(LOG_INFO, "%s %s%s = %qd bytes", \
209290001Sglebius			cmd, (*(file) == '/') ? "" : curdir(), file, cnt); \
210290001Sglebius	}
211290001Sglebius
212290001Sglebiusstatic void	 ack(char *);
213290001Sglebiusstatic void	 sigurg(int);
214290001Sglebiusstatic void	 myoob(void);
215290001Sglebiusstatic int	 checkuser(char *, char *);
216290001Sglebiusstatic FILE	*dataconn(char *, off_t, char *);
217290001Sglebiusstatic void	 dolog(struct sockaddr *);
218290001Sglebiusstatic char	*copy_dir(char *, struct passwd *);
219290001Sglebiusstatic char	*curdir(void);
220290001Sglebiusstatic void	 end_login(void);
221290001Sglebiusstatic FILE	*getdatasock(char *);
222290001Sglebiusstatic int	 guniquefd(char *, char **);
223290001Sglebiusstatic void	 lostconn(int);
224290001Sglebiusstatic void	 sigquit(int);
225290001Sglebiusstatic int	 receive_data(FILE *, FILE *);
226290001Sglebiusstatic void	 replydirname(const char *, const char *);
227290001Sglebiusstatic int	 send_data(FILE *, FILE *, off_t, off_t, int);
228290001Sglebiusstatic struct passwd *
229290001Sglebius		 sgetpwnam(char *, struct passwd *);
230290001Sglebiusstatic void	 reapchild(int);
231290001Sglebius#if defined(TCPWRAPPERS)
232290001Sglebiusstatic int	 check_host(struct sockaddr *);
233290001Sglebius#endif /* TCPWRAPPERS */
234290001Sglebiusstatic void	 usage(void);
235290001Sglebius
236290001Sglebiusvoid	 logxfer(char *, off_t, time_t);
237290001Sglebiusvoid	 set_slave_signals(void);
238290001Sglebius
239290001Sglebiusstatic char *
240290001Sglebiuscurdir(void)
241290001Sglebius{
242290001Sglebius	static char path[MAXPATHLEN+1];	/* path + '/' */
243290001Sglebius
244290001Sglebius	if (getcwd(path, sizeof(path)-1) == NULL)
245290001Sglebius		return ("");
246290001Sglebius	if (path[1] != '\0')		/* special case for root dir. */
247290001Sglebius		strlcat(path, "/", sizeof path);
248290001Sglebius	/* For guest account, skip / since it's chrooted */
249290001Sglebius	return (guest ? path+1 : path);
250290001Sglebius}
251290001Sglebius
252290001Sglebiuschar *argstr = "AdDhnlMSt:T:u:PUvW46";
253290001Sglebius
254293896Sglebiusstatic void
255290001Sglebiususage(void)
256290001Sglebius{
257290001Sglebius	syslog(LOG_ERR,
258290001Sglebius	    "usage: ftpd [-46ADdlMnPSUW] [-T maxtimeout] [-t timeout] [-u mask]");
259290001Sglebius	exit(2);
260290001Sglebius}
261290001Sglebius
262290001Sglebiusint
263290001Sglebiusmain(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			buf = mmap(0, fsize, PROT_READ, MAP_SHARED, filefd,
1590			    (off_t)0);
1591			if (buf == MAP_FAILED) {
1592				syslog(LOG_WARNING, "mmap(%llu): %m",
1593				    (unsigned long long)fsize);
1594				goto oldway;
1595			}
1596			bp = buf;
1597			len = fsize;
1598			do {
1599				cnt = write(netfd, bp, len);
1600				if (recvurg) {
1601					munmap(buf, fsize);
1602					goto got_oob;
1603				}
1604				len -= cnt;
1605				bp += cnt;
1606				if (cnt > 0)
1607					byte_count += cnt;
1608			} while(cnt > 0 && len > 0);
1609
1610			transflag = 0;
1611			munmap(buf, fsize);
1612			if (cnt < 0)
1613				goto data_err;
1614			reply(226, "Transfer complete.");
1615			return(0);
1616		}
1617
1618oldway:
1619		if ((buf = malloc((size_t)blksize)) == NULL) {
1620			transflag = 0;
1621			perror_reply(451, "Local resource failure: malloc");
1622			return(-1);
1623		}
1624
1625		while ((cnt = read(filefd, buf, (size_t)blksize)) > 0 &&
1626		    write(netfd, buf, cnt) == cnt)
1627			byte_count += cnt;
1628		transflag = 0;
1629		(void)free(buf);
1630		if (cnt != 0) {
1631			if (cnt < 0)
1632				goto file_err;
1633			goto data_err;
1634		}
1635		reply(226, "Transfer complete.");
1636		return(0);
1637	default:
1638		transflag = 0;
1639		reply(550, "Unimplemented TYPE %d in send_data", type);
1640		return(-1);
1641	}
1642
1643data_err:
1644	transflag = 0;
1645	reply(426, "Data connection");
1646	return(-1);
1647
1648file_err:
1649	transflag = 0;
1650	reply(551, "Error on input file");
1651	return(-1);
1652
1653got_oob:
1654	myoob();
1655	recvurg = 0;
1656	transflag = 0;
1657	return(-1);
1658}
1659
1660/*
1661 * Transfer data from peer to "outstr" using the appropriate encapulation of
1662 * the data subject to Mode, Structure, and Type.
1663 *
1664 * N.B.: Form isn't handled.
1665 */
1666static int
1667receive_data(FILE *instr, FILE *outstr)
1668{
1669	int c;
1670	int cnt;
1671	char buf[BUFSIZ];
1672	struct sigaction sa, sa_saved;
1673	volatile int bare_lfs = 0;
1674
1675	transflag++;
1676	switch (type) {
1677
1678	case TYPE_I:
1679	case TYPE_L:
1680		memset(&sa, 0, sizeof(sa));
1681		sigfillset(&sa.sa_mask);
1682		sa.sa_flags = SA_RESTART;
1683		sa.sa_handler = lostconn;
1684		(void) sigaction(SIGALRM, &sa, &sa_saved);
1685		do {
1686			(void) alarm ((unsigned) timeout);
1687			cnt = read(fileno(instr), buf, sizeof(buf));
1688			(void) alarm (0);
1689			if (recvurg)
1690				goto got_oob;
1691
1692			if (cnt > 0) {
1693				if (write(fileno(outstr), buf, cnt) != cnt)
1694					goto file_err;
1695				byte_count += cnt;
1696			}
1697		} while (cnt > 0);
1698		(void) sigaction(SIGALRM, &sa_saved, NULL);
1699		if (cnt < 0)
1700			goto data_err;
1701		transflag = 0;
1702		return (0);
1703
1704	case TYPE_E:
1705		reply(553, "TYPE E not implemented.");
1706		transflag = 0;
1707		return (-1);
1708
1709	case TYPE_A:
1710		while ((c = getc(instr)) != EOF) {
1711			if (recvurg)
1712				goto got_oob;
1713			byte_count++;
1714			if (c == '\n')
1715				bare_lfs++;
1716			while (c == '\r') {
1717				if (ferror(outstr))
1718					goto data_err;
1719				if ((c = getc(instr)) != '\n') {
1720					(void) putc ('\r', outstr);
1721					if (c == '\0' || c == EOF)
1722						goto contin2;
1723				}
1724			}
1725			(void) putc(c, outstr);
1726	contin2:	;
1727		}
1728		fflush(outstr);
1729		if (ferror(instr))
1730			goto data_err;
1731		if (ferror(outstr))
1732			goto file_err;
1733		transflag = 0;
1734		if (bare_lfs) {
1735			lreply(226,
1736			    "WARNING! %d bare linefeeds received in ASCII mode",
1737			    bare_lfs);
1738			printf("   File may not have transferred correctly.\r\n");
1739		}
1740		return (0);
1741	default:
1742		reply(550, "Unimplemented TYPE %d in receive_data", type);
1743		transflag = 0;
1744		return (-1);
1745	}
1746
1747data_err:
1748	transflag = 0;
1749	reply(426, "Data Connection");
1750	return (-1);
1751
1752file_err:
1753	transflag = 0;
1754	reply(452, "Error writing file");
1755	return (-1);
1756
1757got_oob:
1758	myoob();
1759	recvurg = 0;
1760	transflag = 0;
1761	return (-1);
1762}
1763
1764void
1765statfilecmd(char *filename)
1766{
1767	FILE *fin;
1768	int c;
1769	int atstart;
1770	char line[LINE_MAX];
1771
1772	(void)snprintf(line, sizeof(line), "/bin/ls -lgA %s", filename);
1773	fin = ftpd_popen(line, "r");
1774	if (fin == NULL) {
1775		reply(451, "Local resource failure");
1776		return;
1777	}
1778	lreply(211, "status of %s:", filename);
1779	atstart = 1;
1780	while ((c = getc(fin)) != EOF) {
1781		if (c == '\n') {
1782			if (ferror(stdout)){
1783				perror_reply(421, "control connection");
1784				(void) ftpd_pclose(fin);
1785				dologout(1);
1786				/* NOTREACHED */
1787			}
1788			if (ferror(fin)) {
1789				perror_reply(551, filename);
1790				(void) ftpd_pclose(fin);
1791				return;
1792			}
1793			(void) putc('\r', stdout);
1794		}
1795		if (atstart && isdigit(c))
1796			(void) putc(' ', stdout);
1797		(void) putc(c, stdout);
1798		atstart = (c == '\n');
1799	}
1800	(void) ftpd_pclose(fin);
1801	reply(211, "End of Status");
1802}
1803
1804void
1805statcmd(void)
1806{
1807	union sockunion *su;
1808	u_char *a, *p;
1809	char hbuf[MAXHOSTNAMELEN];
1810	int ispassive;
1811	int error;
1812
1813	lreply(211, "%s FTP server status:", hostname);
1814	error = getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len,
1815	    hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
1816	printf("     Connected to %s", remotehost);
1817	if (error == 0 && strcmp(remotehost, hbuf) != 0)
1818		printf(" (%s)", hbuf);
1819	printf("\r\n");
1820	if (logged_in) {
1821		if (guest)
1822			printf("     Logged in anonymously\r\n");
1823		else
1824			printf("     Logged in as %s\r\n", pw->pw_name);
1825	} else if (askpasswd)
1826		printf("     Waiting for password\r\n");
1827	else
1828		printf("     Waiting for user name\r\n");
1829	printf("     TYPE: %s", typenames[type]);
1830	if (type == TYPE_A || type == TYPE_E)
1831		printf(", FORM: %s", formnames[form]);
1832	if (type == TYPE_L)
1833#if NBBY == 8
1834		printf(" %d", NBBY);
1835#else
1836		printf(" %d", bytesize);	/* need definition! */
1837#endif
1838	printf("; STRUcture: %s; transfer MODE: %s\r\n",
1839	    strunames[stru], modenames[mode]);
1840	ispassive = 0;
1841	if (data != -1)
1842		printf("     Data connection open\r\n");
1843	else if (pdata != -1) {
1844		printf("     in Passive mode\r\n");
1845		su = (union sockunion *)&pasv_addr;
1846		ispassive++;
1847		goto printaddr;
1848	} else if (usedefault == 0) {
1849		size_t alen;
1850		int af, i;
1851
1852		su = (union sockunion *)&data_dest;
1853printaddr:
1854		/* PASV/PORT */
1855		if (su->su_family == AF_INET) {
1856			if (ispassive)
1857				printf("211- PASV ");
1858			else
1859				printf("211- PORT ");
1860			a = (u_char *)&su->su_sin.sin_addr;
1861			p = (u_char *)&su->su_sin.sin_port;
1862			printf("(%u,%u,%u,%u,%u,%u)\r\n",
1863			    a[0], a[1], a[2], a[3],
1864			    p[0], p[1]);
1865		}
1866
1867		/* LPSV/LPRT */
1868		alen = 0;
1869		switch (su->su_family) {
1870		case AF_INET:
1871			a = (u_char *)&su->su_sin.sin_addr;
1872			p = (u_char *)&su->su_sin.sin_port;
1873			alen = sizeof(su->su_sin.sin_addr);
1874			af = 4;
1875			break;
1876		case AF_INET6:
1877			a = (u_char *)&su->su_sin6.sin6_addr;
1878			p = (u_char *)&su->su_sin6.sin6_port;
1879			alen = sizeof(su->su_sin6.sin6_addr);
1880			af = 6;
1881			break;
1882		default:
1883			af = 0;
1884			break;
1885		}
1886		if (af) {
1887			if (ispassive)
1888				printf("211- LPSV ");
1889			else
1890				printf("211- LPRT ");
1891			printf("(%u,%llu", af, (unsigned long long)alen);
1892			for (i = 0; i < alen; i++)
1893				printf(",%u", a[i]);
1894			printf(",%u,%u,%u)\r\n", 2, p[0], p[1]);
1895		}
1896
1897		/* EPRT/EPSV */
1898		switch (su->su_family) {
1899		case AF_INET:
1900			af = 1;
1901			break;
1902		case AF_INET6:
1903			af = 2;
1904			break;
1905		default:
1906			af = 0;
1907			break;
1908		}
1909		if (af) {
1910			char pbuf[10];
1911			union sockunion tmp = *su;
1912
1913			if (tmp.su_family == AF_INET6)
1914				tmp.su_sin6.sin6_scope_id = 0;
1915			if (getnameinfo((struct sockaddr *)&tmp, tmp.su_len,
1916			    hbuf, sizeof(hbuf), pbuf, sizeof(pbuf),
1917			    NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
1918				if (ispassive)
1919					printf("211- EPSV ");
1920				else
1921					printf("211- EPRT ");
1922				printf("(|%u|%s|%s|)\r\n",
1923				    af, hbuf, pbuf);
1924			}
1925		}
1926	} else
1927		printf("     No data connection\r\n");
1928	reply(211, "End of status");
1929}
1930
1931void
1932fatal(char *s)
1933{
1934
1935	reply(451, "Error in server: %s", s);
1936	reply(221, "Closing connection due to server error.");
1937	dologout(0);
1938	/* NOTREACHED */
1939}
1940
1941void
1942reply(int n, const char *fmt, ...)
1943{
1944	char *buf, *p, *next;
1945	int rval;
1946	va_list ap;
1947
1948	va_start(ap, fmt);
1949	rval = vasprintf(&buf, fmt, ap);
1950	va_end(ap);
1951	if (rval == -1 || buf == NULL) {
1952		printf("421 Local resource failure: malloc\r\n");
1953		fflush(stdout);
1954		dologout(1);
1955	}
1956	next = buf;
1957	while ((p = strsep(&next, "\n\r"))) {
1958		printf("%d%s %s\r\n", n, (next != '\0') ? "-" : "", p);
1959		if (debug)
1960			syslog(LOG_DEBUG, "<--- %d%s %s", n,
1961			    (next != '\0') ? "-" : "", p);
1962	}
1963	(void)fflush(stdout);
1964	free(buf);
1965}
1966
1967
1968void
1969reply_r(int n, const char *fmt, ...)
1970{
1971	char *p, *next;
1972	char msg[BUFSIZ];
1973	char buf[BUFSIZ];
1974	va_list ap;
1975	struct syslog_data sdata = SYSLOG_DATA_INIT;
1976
1977	sdata.log_fac = LOG_FTP;
1978	va_start(ap, fmt);
1979	vsnprintf(msg, sizeof(msg), fmt, ap);
1980	va_end(ap);
1981
1982	next = msg;
1983
1984	while ((p = strsep(&next, "\n\r"))) {
1985		snprintf(buf, sizeof(buf), "%d%s %s\r\n", n,
1986		    (next != '\0') ? "-" : "", p);
1987		write(STDOUT_FILENO, buf, strlen(buf));
1988		if (debug) {
1989			buf[strlen(buf) - 2] = '\0';
1990			syslog_r(LOG_DEBUG, &sdata, "<--- %s", buf);
1991		}
1992	}
1993}
1994
1995void
1996lreply(int n, const char *fmt, ...)
1997{
1998	va_list ap;
1999
2000	va_start(ap, fmt);
2001	(void)printf("%d- ", n);
2002	(void)vprintf(fmt, ap);
2003	va_end(ap);
2004	(void)printf("\r\n");
2005	(void)fflush(stdout);
2006	if (debug) {
2007		va_start(ap, fmt);
2008		syslog(LOG_DEBUG, "<--- %d- ", n);
2009		vsyslog(LOG_DEBUG, fmt, ap);
2010		va_end(ap);
2011	}
2012}
2013
2014static void
2015ack(char *s)
2016{
2017
2018	reply(250, "%s command successful.", s);
2019}
2020
2021void
2022nack(char *s)
2023{
2024
2025	reply(502, "%s command not implemented.", s);
2026}
2027
2028/* ARGSUSED */
2029void
2030yyerror(char *s)
2031{
2032	cbuf[strcspn(cbuf, "\n")] = '\0';
2033	reply(500, "'%s': command not understood.", cbuf);
2034}
2035
2036void
2037delete(char *name)
2038{
2039	struct stat st;
2040
2041	LOGCMD("delete", name);
2042	if (stat(name, &st) < 0) {
2043		perror_reply(550, name);
2044		return;
2045	}
2046	if ((st.st_mode&S_IFMT) == S_IFDIR) {
2047		if (rmdir(name) < 0) {
2048			perror_reply(550, name);
2049			return;
2050		}
2051		goto done;
2052	}
2053	if (unlink(name) < 0) {
2054		perror_reply(550, name);
2055		return;
2056	}
2057done:
2058	ack("DELE");
2059}
2060
2061void
2062cwd(char *path)
2063{
2064	FILE *message;
2065
2066	if (chdir(path) < 0)
2067		perror_reply(550, path);
2068	else {
2069		if ((message = fopen(_PATH_CWDMESG, "r")) != NULL) {
2070			char line[LINE_MAX];
2071
2072			while (fgets(line, sizeof(line), message) != NULL) {
2073				line[strcspn(line, "\n")] = '\0';
2074				lreply(250, "%s", line);
2075			}
2076			(void) fflush(stdout);
2077			(void) fclose(message);
2078		}
2079		ack("CWD");
2080	}
2081}
2082
2083void
2084replydirname(const char *name, const char *message)
2085{
2086	char *p, *ep;
2087	char npath[MAXPATHLEN * 2];
2088
2089	p = npath;
2090	ep = &npath[sizeof(npath) - 1];
2091	while (*name) {
2092		if (*name == '"') {
2093			if (ep - p < 2)
2094				break;
2095			*p++ = *name++;
2096			*p++ = '"';
2097		} else {
2098			if (ep - p < 1)
2099				break;
2100			*p++ = *name++;
2101		}
2102	}
2103	*p = '\0';
2104	reply(257, "\"%s\" %s", npath, message);
2105}
2106
2107void
2108makedir(char *name)
2109{
2110
2111	LOGCMD("mkdir", name);
2112	if (mkdir(name, 0777) < 0)
2113		perror_reply(550, name);
2114	else
2115		replydirname(name, "directory created.");
2116}
2117
2118void
2119removedir(char *name)
2120{
2121
2122	LOGCMD("rmdir", name);
2123	if (rmdir(name) < 0)
2124		perror_reply(550, name);
2125	else
2126		ack("RMD");
2127}
2128
2129void
2130pwd(void)
2131{
2132	char path[MAXPATHLEN];
2133
2134	if (getcwd(path, sizeof(path)) == NULL)
2135		perror_reply(550, "Can't get current directory");
2136	else
2137		replydirname(path, "is current directory.");
2138}
2139
2140char *
2141renamefrom(char *name)
2142{
2143	struct stat st;
2144
2145	if (stat(name, &st) < 0) {
2146		perror_reply(550, name);
2147		return ((char *)0);
2148	}
2149	reply(350, "File exists, ready for destination name");
2150	return (name);
2151}
2152
2153void
2154renamecmd(char *from, char *to)
2155{
2156
2157	LOGCMD2("rename", from, to);
2158	if (rename(from, to) < 0)
2159		perror_reply(550, "rename");
2160	else
2161		ack("RNTO");
2162}
2163
2164static void
2165dolog(struct sockaddr *sa)
2166{
2167	char hbuf[sizeof(remotehost)];
2168
2169	if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0, 0) == 0)
2170		(void) strlcpy(remotehost, hbuf, sizeof(remotehost));
2171	else
2172		(void) strlcpy(remotehost, "unknown", sizeof(remotehost));
2173
2174#ifdef HASSETPROCTITLE
2175	snprintf(proctitle, sizeof(proctitle), "%s: connected", remotehost);
2176	setproctitle("%s", proctitle);
2177#endif /* HASSETPROCTITLE */
2178
2179	if (logging) {
2180		int error;
2181		error = getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf),
2182		    NULL, 0, NI_NUMERICHOST);
2183		syslog(LOG_INFO, "connection from %s [%s]", remotehost,
2184		    error ? gai_strerror(error) : hbuf);
2185	}
2186}
2187
2188/*
2189 * Record logout in wtmp file and exit with supplied status.
2190 * NOTE: because this is called from signal handlers it cannot
2191 *       use stdio (or call other functions that use stdio).
2192 */
2193void
2194dologout(int status)
2195{
2196
2197	transflag = 0;
2198
2199	if (logged_in) {
2200		sigprocmask(SIG_BLOCK, &allsigs, NULL);
2201		if (!nowtmp)
2202			ftpdlogwtmp(ttyline, "", "");
2203		if (doutmp)
2204			ftpd_logout(utmp.ut_line);
2205	}
2206	/* beware of flushing buffers after a SIGPIPE */
2207	_exit(status);
2208}
2209
2210/*ARGSUSED*/
2211static void
2212sigurg(int signo)
2213{
2214
2215	recvurg = 1;
2216}
2217
2218static void
2219myoob(void)
2220{
2221	char *cp;
2222	int ret;
2223
2224	/* only process if transfer occurring */
2225	if (!transflag)
2226		return;
2227	cp = tmpline;
2228	ret = get_line(cp, sizeof(tmpline)-1, stdin);
2229	if (ret == -1) {
2230		reply(221, "You could at least say goodbye.");
2231		dologout(0);
2232	} else if (ret == -2) {
2233		/* Ignore truncated command */
2234		return;
2235	}
2236	upper(cp);
2237	if (strcmp(cp, "ABOR\r\n") == 0) {
2238		tmpline[0] = '\0';
2239		reply(426, "Transfer aborted. Data connection closed.");
2240		reply(226, "Abort successful");
2241	}
2242	if (strcmp(cp, "STAT\r\n") == 0) {
2243		tmpline[0] = '\0';
2244		if (file_size != (off_t) -1)
2245			reply(213, "Status: %qd of %qd bytes transferred",
2246			    byte_count, file_size);
2247		else
2248			reply(213, "Status: %qd bytes transferred", byte_count);
2249	}
2250}
2251
2252/*
2253 * Note: a response of 425 is not mentioned as a possible response to
2254 *	the PASV command in RFC959. However, it has been blessed as
2255 *	a legitimate response by Jon Postel in a telephone conversation
2256 *	with Rick Adams on 25 Jan 89.
2257 */
2258void
2259passive(void)
2260{
2261	socklen_t len;
2262	int on = 1;
2263	u_char *p, *a;
2264
2265	if (pw == NULL) {
2266		reply(530, "Please login with USER and PASS");
2267		return;
2268	}
2269	if (pdata >= 0)
2270		close(pdata);
2271	/*
2272	 * XXX
2273	 * At this point, it would be nice to have an algorithm that
2274	 * inserted a growing delay in an attack scenario.  Such a thing
2275	 * would look like continual passive sockets being opened, but
2276	 * nothing serious being done with them.  They're not used to
2277	 * move data; the entire attempt is just to use tcp FIN_WAIT
2278	 * resources.
2279	 */
2280	pdata = socket(AF_INET, SOCK_STREAM, 0);
2281	if (pdata < 0) {
2282		perror_reply(425, "Can't open passive connection");
2283		return;
2284	}
2285
2286	if (setsockopt(pdata, SOL_SOCKET, SO_KEEPALIVE,
2287	    &on, sizeof(on)) < 0)
2288		goto pasv_error;
2289
2290	on = IP_PORTRANGE_HIGH;
2291	if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2292	    &on, sizeof(on)) < 0)
2293		goto pasv_error;
2294
2295	pasv_addr = ctrl_addr;
2296	pasv_addr.su_sin.sin_port = 0;
2297	if (bind(pdata, (struct sockaddr *)&pasv_addr,
2298	    pasv_addr.su_len) < 0)
2299		goto pasv_error;
2300
2301	len = sizeof(pasv_addr);
2302	if (getsockname(pdata, (struct sockaddr *)&pasv_addr, &len) < 0)
2303		goto pasv_error;
2304	if (listen(pdata, 1) < 0)
2305		goto pasv_error;
2306	a = (u_char *)&pasv_addr.su_sin.sin_addr;
2307	p = (u_char *)&pasv_addr.su_sin.sin_port;
2308
2309	reply(227, "Entering Passive Mode (%u,%u,%u,%u,%u,%u)", a[0],
2310	    a[1], a[2], a[3], p[0], p[1]);
2311	return;
2312
2313pasv_error:
2314	perror_reply(425, "Can't open passive connection");
2315	(void) close(pdata);
2316	pdata = -1;
2317	return;
2318}
2319
2320int
2321epsvproto2af(int proto)
2322{
2323
2324	switch (proto) {
2325	case 1:	return AF_INET;
2326#ifdef INET6
2327	case 2:	return AF_INET6;
2328#endif
2329	default: return -1;
2330	}
2331}
2332
2333int
2334af2epsvproto(int af)
2335{
2336
2337	switch (af) {
2338	case AF_INET:	return 1;
2339#ifdef INET6
2340	case AF_INET6:	return 2;
2341#endif
2342	default:	return -1;
2343	}
2344}
2345
2346/*
2347 * 228 Entering Long Passive Mode (af, hal, h1, h2, h3,..., pal, p1, p2...)
2348 * 229 Entering Extended Passive Mode (|||port|)
2349 */
2350void
2351long_passive(char *cmd, int pf)
2352{
2353	socklen_t len;
2354	int on = 1;
2355	u_char *p, *a;
2356
2357	if (!logged_in) {
2358		syslog(LOG_NOTICE, "long passive but not logged in");
2359		reply(503, "Login with USER first.");
2360		return;
2361	}
2362
2363	if (pf != PF_UNSPEC && ctrl_addr.su_family != pf) {
2364		/*
2365		 * XXX
2366		 * only EPRT/EPSV ready clients will understand this
2367		 */
2368		if (strcmp(cmd, "EPSV") != 0)
2369			reply(501, "Network protocol mismatch"); /*XXX*/
2370		else
2371			epsv_protounsupp("Network protocol mismatch");
2372
2373		return;
2374	}
2375
2376	if (pdata >= 0)
2377		close(pdata);
2378	/*
2379	 * XXX
2380	 * At this point, it would be nice to have an algorithm that
2381	 * inserted a growing delay in an attack scenario.  Such a thing
2382	 * would look like continual passive sockets being opened, but
2383	 * nothing serious being done with them.  They not used to move
2384	 * data; the entire attempt is just to use tcp FIN_WAIT
2385	 * resources.
2386	 */
2387	pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0);
2388	if (pdata < 0) {
2389		perror_reply(425, "Can't open passive connection");
2390		return;
2391	}
2392
2393	if (setsockopt(pdata, SOL_SOCKET, SO_KEEPALIVE,
2394	    &on, sizeof(on)) < 0)
2395		goto pasv_error;
2396
2397	switch (ctrl_addr.su_family) {
2398	case AF_INET:
2399		on = IP_PORTRANGE_HIGH;
2400		if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2401		    &on, sizeof(on)) < 0)
2402			goto pasv_error;
2403		break;
2404	case AF_INET6:
2405		on = IPV6_PORTRANGE_HIGH;
2406		if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE,
2407		    &on, sizeof(on)) < 0)
2408			goto pasv_error;
2409		break;
2410	}
2411
2412	pasv_addr = ctrl_addr;
2413	pasv_addr.su_port = 0;
2414	if (bind(pdata, (struct sockaddr *)&pasv_addr, pasv_addr.su_len) < 0)
2415		goto pasv_error;
2416	len = pasv_addr.su_len;
2417	if (getsockname(pdata, (struct sockaddr *)&pasv_addr, &len) < 0)
2418		goto pasv_error;
2419	if (listen(pdata, 1) < 0)
2420		goto pasv_error;
2421	p = (u_char *)&pasv_addr.su_port;
2422
2423	if (strcmp(cmd, "LPSV") == 0) {
2424		switch (pasv_addr.su_family) {
2425		case AF_INET:
2426			a = (u_char *)&pasv_addr.su_sin.sin_addr;
2427			reply(228,
2428			    "Entering Long Passive Mode (%u,%u,%u,%u,%u,%u,%u,%u,%u)",
2429			    4, 4, a[0], a[1], a[2], a[3], 2, p[0], p[1]);
2430			return;
2431		case AF_INET6:
2432			a = (u_char *)&pasv_addr.su_sin6.sin6_addr;
2433			reply(228,
2434			    "Entering Long Passive Mode (%u,%u,%u,%u,%u,%u,"
2435			    "%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u)",
2436				6, 16, a[0], a[1], a[2], a[3], a[4],
2437				a[5], a[6], a[7], a[8], a[9], a[10],
2438				a[11], a[12], a[13], a[14], a[15],
2439				2, p[0], p[1]);
2440			return;
2441		}
2442	} else if (strcmp(cmd, "EPSV") == 0) {
2443		switch (pasv_addr.su_family) {
2444		case AF_INET:
2445		case AF_INET6:
2446			reply(229, "Entering Extended Passive Mode (|||%u|)",
2447			    ntohs(pasv_addr.su_port));
2448			return;
2449		}
2450	} else {
2451		/* more proper error code? */
2452	}
2453
2454  pasv_error:
2455	perror_reply(425, "Can't open passive connection");
2456	(void) close(pdata);
2457	pdata = -1;
2458	return;
2459}
2460
2461/*
2462 * EPRT |proto|addr|port|
2463 */
2464int
2465extended_port(const char *arg)
2466{
2467	char *tmp = NULL;
2468	char *result[3];
2469	char *p, *q;
2470	char delim;
2471	struct addrinfo hints;
2472	struct addrinfo *res = NULL;
2473	int i;
2474	unsigned long proto;
2475
2476	if (epsvall) {
2477		reply(501, "EPRT disallowed after EPSV ALL");
2478		return -1;
2479	}
2480
2481	usedefault = 0;
2482	if (pdata >= 0) {
2483		(void) close(pdata);
2484		pdata = -1;
2485	}
2486
2487	tmp = strdup(arg);
2488	if (!tmp) {
2489		fatal("not enough core.");
2490		/*NOTREACHED*/
2491	}
2492	p = tmp;
2493	delim = p[0];
2494	p++;
2495	memset(result, 0, sizeof(result));
2496	for (i = 0; i < 3; i++) {
2497		q = strchr(p, delim);
2498		if (!q || *q != delim)
2499			goto parsefail;
2500		*q++ = '\0';
2501		result[i] = p;
2502		p = q;
2503	}
2504
2505	/* some more sanity check */
2506	p = NULL;
2507	(void)strtoul(result[2], &p, 10);
2508	if (!*result[2] || *p)
2509		goto protounsupp;
2510	p = NULL;
2511	proto = strtoul(result[0], &p, 10);
2512	if (!*result[0] || *p)
2513		goto protounsupp;
2514
2515	memset(&hints, 0, sizeof(hints));
2516	hints.ai_family = epsvproto2af((int)proto);
2517	if (hints.ai_family < 0)
2518		goto protounsupp;
2519	hints.ai_socktype = SOCK_STREAM;
2520	hints.ai_flags = AI_NUMERICHOST;	/*no DNS*/
2521	if (getaddrinfo(result[1], result[2], &hints, &res))
2522		goto parsefail;
2523	if (res->ai_next)
2524		goto parsefail;
2525	if (sizeof(data_dest) < res->ai_addrlen)
2526		goto parsefail;
2527	memcpy(&data_dest, res->ai_addr, res->ai_addrlen);
2528	if (his_addr.su_family == AF_INET6 &&
2529	    data_dest.su_family == AF_INET6) {
2530		/* XXX more sanity checks! */
2531		data_dest.su_sin6.sin6_scope_id =
2532		    his_addr.su_sin6.sin6_scope_id;
2533	}
2534	if (pdata >= 0) {
2535		(void) close(pdata);
2536		pdata = -1;
2537	}
2538	reply(200, "EPRT command successful.");
2539
2540	if (tmp)
2541		free(tmp);
2542	if (res)
2543		freeaddrinfo(res);
2544	return 0;
2545
2546parsefail:
2547	reply(500, "Invalid argument, rejected.");
2548	usedefault = 1;
2549	if (tmp)
2550		free(tmp);
2551	if (res)
2552		freeaddrinfo(res);
2553	return -1;
2554
2555protounsupp:
2556	epsv_protounsupp("Protocol not supported");
2557	usedefault = 1;
2558	if (tmp)
2559		free(tmp);
2560	if (res)
2561		freeaddrinfo(res);
2562	return -1;
2563}
2564
2565/*
2566 * 522 Protocol not supported (proto,...)
2567 * as we assume address family for control and data connections are the same,
2568 * we do not return the list of address families we support - instead, we
2569 * return the address family of the control connection.
2570 */
2571void
2572epsv_protounsupp(const char *message)
2573{
2574	int proto;
2575
2576	proto = af2epsvproto(ctrl_addr.su_family);
2577	if (proto < 0)
2578		reply(501, "%s", message);	/*XXX*/
2579	else
2580		reply(522, "%s, use (%d)", message, proto);
2581}
2582
2583/*
2584 * Generate unique name for file with basename "local".
2585 * The file named "local" is already known to exist.
2586 * Generates failure reply on error.
2587 */
2588static int
2589guniquefd(char *local, char **nam)
2590{
2591	static char new[MAXPATHLEN];
2592	struct stat st;
2593	int count, len, fd;
2594	char *cp;
2595
2596	cp = strrchr(local, '/');
2597	if (cp)
2598		*cp = '\0';
2599	if (stat(cp ? local : ".", &st) < 0) {
2600		perror_reply(553, cp ? local : ".");
2601		return (-1);
2602	}
2603	if (cp)
2604		*cp = '/';
2605	len = strlcpy(new, local, sizeof(new));
2606	if (len+2+1 >= sizeof(new)-1)
2607		return (-1);
2608	cp = new + len;
2609	*cp++ = '.';
2610	for (count = 1; count < 100; count++) {
2611		(void)snprintf(cp, sizeof(new) - (cp - new), "%d", count);
2612		fd = open(new, O_RDWR|O_CREAT|O_EXCL, 0666);
2613		if (fd == -1)
2614			continue;
2615		if (nam)
2616			*nam = new;
2617		return (fd);
2618	}
2619	reply(452, "Unique file name cannot be created.");
2620	return (-1);
2621}
2622
2623/*
2624 * Format and send reply containing system error number.
2625 */
2626void
2627perror_reply(int code, char *string)
2628{
2629
2630	reply(code, "%s: %s.", string, strerror(errno));
2631}
2632
2633static char *onefile[] = {
2634	"",
2635	0
2636};
2637
2638void
2639send_file_list(char *whichf)
2640{
2641	struct stat st;
2642	DIR *dirp = NULL;
2643	struct dirent *dir;
2644	FILE *dout = NULL;
2645	char **dirlist;
2646	char *dirname;
2647	int simple = 0;
2648	volatile int freeglob = 0;
2649	glob_t gl;
2650
2651	if (strpbrk(whichf, "~{[*?") != NULL) {
2652		memset(&gl, 0, sizeof(gl));
2653		freeglob = 1;
2654		if (glob(whichf,
2655		    GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE|GLOB_LIMIT,
2656		    0, &gl)) {
2657			reply(550, "not found");
2658			goto out;
2659		} else if (gl.gl_pathc == 0) {
2660			errno = ENOENT;
2661			perror_reply(550, whichf);
2662			goto out;
2663		}
2664		dirlist = gl.gl_pathv;
2665	} else {
2666		onefile[0] = whichf;
2667		dirlist = onefile;
2668		simple = 1;
2669	}
2670
2671	while ((dirname = *dirlist++)) {
2672		if (stat(dirname, &st) < 0) {
2673			/*
2674			 * If user typed "ls -l", etc, and the client
2675			 * used NLST, do what the user meant.
2676			 */
2677			if (dirname[0] == '-' && *dirlist == NULL &&
2678			    transflag == 0) {
2679				retrieve("/bin/ls %s", dirname);
2680				goto out;
2681			}
2682			perror_reply(550, whichf);
2683			if (dout != NULL) {
2684				(void) fclose(dout);
2685				transflag = 0;
2686				data = -1;
2687				pdata = -1;
2688			}
2689			goto out;
2690		}
2691
2692		if (S_ISREG(st.st_mode)) {
2693			if (dout == NULL) {
2694				dout = dataconn("file list", (off_t)-1, "w");
2695				if (dout == NULL)
2696					goto out;
2697				transflag++;
2698			}
2699			fprintf(dout, "%s%s\n", dirname,
2700				type == TYPE_A ? "\r" : "");
2701			byte_count += strlen(dirname) + 1;
2702			continue;
2703		} else if (!S_ISDIR(st.st_mode))
2704			continue;
2705
2706		if ((dirp = opendir(dirname)) == NULL)
2707			continue;
2708
2709		while ((dir = readdir(dirp)) != NULL) {
2710			char nbuf[MAXPATHLEN];
2711
2712			if (recvurg) {
2713				myoob();
2714				recvurg = 0;
2715				transflag = 0;
2716				goto out;
2717			}
2718
2719			if (dir->d_name[0] == '.' && dir->d_namlen == 1)
2720				continue;
2721			if (dir->d_name[0] == '.' && dir->d_name[1] == '.' &&
2722			    dir->d_namlen == 2)
2723				continue;
2724
2725			snprintf(nbuf, sizeof(nbuf), "%s/%s", dirname,
2726				 dir->d_name);
2727
2728			/*
2729			 * We have to do a stat to insure it's
2730			 * not a directory or special file.
2731			 */
2732			if (simple || (stat(nbuf, &st) == 0 &&
2733			    S_ISREG(st.st_mode))) {
2734				if (dout == NULL) {
2735					dout = dataconn("file list", (off_t)-1,
2736						"w");
2737					if (dout == NULL)
2738						goto out;
2739					transflag++;
2740				}
2741				if (nbuf[0] == '.' && nbuf[1] == '/')
2742					fprintf(dout, "%s%s\n", &nbuf[2],
2743						type == TYPE_A ? "\r" : "");
2744				else
2745					fprintf(dout, "%s%s\n", nbuf,
2746						type == TYPE_A ? "\r" : "");
2747				byte_count += strlen(nbuf) + 1;
2748			}
2749		}
2750		(void) closedir(dirp);
2751	}
2752
2753	if (dout == NULL)
2754		reply(550, "No files found.");
2755	else if (ferror(dout) != 0)
2756		perror_reply(550, "Data connection");
2757	else
2758		reply(226, "Transfer complete.");
2759
2760	transflag = 0;
2761	if (dout != NULL)
2762		(void) fclose(dout);
2763	else {
2764		if (pdata >= 0)
2765			close(pdata);
2766	}
2767	data = -1;
2768	pdata = -1;
2769out:
2770	if (freeglob) {
2771		freeglob = 0;
2772		globfree(&gl);
2773	}
2774}
2775
2776/*ARGSUSED*/
2777static void
2778reapchild(int signo)
2779{
2780	int save_errno = errno;
2781	int rval;
2782
2783	do {
2784		rval = waitpid(-1, NULL, WNOHANG);
2785	} while (rval > 0 || (rval == -1 && errno == EINTR));
2786	errno = save_errno;
2787}
2788
2789void
2790logxfer(char *name, off_t size, time_t start)
2791{
2792	char buf[400 + MAXHOSTNAMELEN*4 + MAXPATHLEN*4];
2793	char dir[MAXPATHLEN], path[MAXPATHLEN], rpath[MAXPATHLEN];
2794	char vremotehost[MAXHOSTNAMELEN*4], vpath[MAXPATHLEN*4];
2795	char *vpw;
2796	time_t now;
2797	int len;
2798
2799	if ((statfd >= 0) && (getcwd(dir, sizeof(dir)) != NULL)) {
2800		time(&now);
2801
2802		vpw = malloc(strlen(guest ? guestpw : pw->pw_name) * 4 + 1);
2803		if (vpw == NULL)
2804			return;
2805
2806		snprintf(path, sizeof(path), "%s/%s", dir, name);
2807		if (realpath(path, rpath) == NULL)
2808			strlcpy(rpath, path, sizeof(rpath));
2809		strvis(vpath, rpath, VIS_SAFE|VIS_NOSLASH);
2810
2811		strvis(vremotehost, remotehost, VIS_SAFE|VIS_NOSLASH);
2812		strvis(vpw, guest? guestpw : pw->pw_name, VIS_SAFE|VIS_NOSLASH);
2813
2814		len = snprintf(buf, sizeof(buf),
2815		    "%.24s %d %s %qd %s %c %s %c %c %s ftp %d %s %s\n",
2816		    ctime(&now), now - start + (now == start),
2817		    vremotehost, (long long)size, vpath,
2818		    ((type == TYPE_A) ? 'a' : 'b'), "*" /* none yet */,
2819		    'o', ((guest) ? 'a' : 'r'),
2820		    vpw, 0 /* none yet */,
2821		    ((guest) ? "*" : pw->pw_name), dhostname);
2822		free(vpw);
2823
2824		if (len >= sizeof(buf) || len == -1) {
2825			if ((len = strlen(buf)) == 0)
2826				return;		/* should not happen */
2827			buf[len - 1] = '\n';
2828		}
2829		write(statfd, buf, len);
2830	}
2831}
2832
2833void
2834set_slave_signals(void)
2835{
2836	struct sigaction sa;
2837
2838	sigemptyset(&sa.sa_mask);
2839	sa.sa_flags = SA_RESTART;
2840
2841	sa.sa_handler = SIG_DFL;
2842	(void) sigaction(SIGCHLD, &sa, NULL);
2843
2844	sa.sa_handler = sigurg;
2845	sa.sa_flags = 0;		/* don't restart syscalls for SIGURG */
2846	(void) sigaction(SIGURG, &sa, NULL);
2847
2848	sigfillset(&sa.sa_mask);	/* block all signals in handler */
2849	sa.sa_flags = SA_RESTART;
2850	sa.sa_handler = sigquit;
2851	(void) sigaction(SIGHUP, &sa, NULL);
2852	(void) sigaction(SIGINT, &sa, NULL);
2853	(void) sigaction(SIGQUIT, &sa, NULL);
2854	(void) sigaction(SIGTERM, &sa, NULL);
2855
2856	sa.sa_handler = lostconn;
2857	(void) sigaction(SIGPIPE, &sa, NULL);
2858
2859	sa.sa_handler = toolong;
2860	(void) sigaction(SIGALRM, &sa, NULL);
2861
2862#ifdef F_SETOWN
2863	if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1)
2864		syslog(LOG_ERR, "fcntl F_SETOWN: %m");
2865#endif
2866}
2867
2868#if defined(TCPWRAPPERS)
2869static int
2870check_host(struct sockaddr *sa)
2871{
2872	struct sockaddr_in *sin;
2873	struct hostent *hp;
2874	char *addr;
2875
2876	if (sa->sa_family != AF_INET)
2877		return 1;	/*XXX*/
2878
2879	sin = (struct sockaddr_in *)sa;
2880	hp = gethostbyaddr((char *)&sin->sin_addr,
2881	    sizeof(struct in_addr), AF_INET);
2882	addr = inet_ntoa(sin->sin_addr);
2883	if (hp) {
2884		if (!hosts_ctl("ftpd", hp->h_name, addr, STRING_UNKNOWN)) {
2885			syslog(LOG_NOTICE, "tcpwrappers rejected: %s [%s]",
2886			    hp->h_name, addr);
2887			return (0);
2888		}
2889	} else {
2890		if (!hosts_ctl("ftpd", STRING_UNKNOWN, addr, STRING_UNKNOWN)) {
2891			syslog(LOG_NOTICE, "tcpwrappers rejected: [%s]", addr);
2892			return (0);
2893		}
2894	}
2895	return (1);
2896}
2897#endif	/* TCPWRAPPERS */
2898
2899/*
2900 * Allocate space and return a copy of the specified dir.
2901 * If 'dir' begins with a tilde (~), expand it.
2902 */
2903char *
2904copy_dir(char *dir, struct passwd *pw)
2905{
2906	char *cp;
2907	char *newdir;
2908	char *user = NULL;
2909
2910	/* Nothing to expand */
2911	if (dir[0] != '~')
2912		return (strdup(dir));
2913
2914	/* "dir" is of form ~user/some/dir, lookup user. */
2915	if (dir[1] != '/' && dir[1] != '\0') {
2916		if ((cp = strchr(dir + 1, '/')) == NULL)
2917			cp = dir + strlen(dir);
2918		if ((user = malloc((size_t)(cp - dir))) == NULL)
2919			return (NULL);
2920		strlcpy(user, dir + 1, (size_t)(cp - dir));
2921
2922		/* Only do lookup if it is a different user. */
2923		if (strcmp(user, pw->pw_name) != 0) {
2924			if ((pw = getpwnam(user)) == NULL) {
2925				/* No such user, interpret literally */
2926				free(user);
2927				return(strdup(dir));
2928			}
2929		}
2930		free(user);
2931	}
2932
2933	/*
2934	 * If there is no directory separator (/) then it is just pw_dir.
2935	 * Otherwise, replace ~foo with pw_dir.
2936	 */
2937	if ((cp = strchr(dir + 1, '/')) == NULL) {
2938		newdir = strdup(pw->pw_dir);
2939	} else {
2940		if (asprintf(&newdir, "%s%s", pw->pw_dir, cp) == -1)
2941			return (NULL);
2942	}
2943
2944	return(newdir);
2945}
2946