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