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