xref: /freebsd/libexec/ftpd/ftpd.c (revision 8e537d168674d6b65869f73c20813001af875738)
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  *	$Id: ftpd.c,v 1.22 1996/08/09 09:02:26 markm Exp $
34  */
35 
36 #if 0
37 #ifndef lint
38 static char copyright[] =
39 "@(#) Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994\n\
40 	The Regents of the University of California.  All rights reserved.\n";
41 #endif /* not lint */
42 #endif
43 
44 #if 0
45 #ifndef lint
46 static char sccsid[] = "@(#)ftpd.c	8.4 (Berkeley) 4/16/94";
47 #endif /* not lint */
48 #endif
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 <setjmp.h>
80 #include <signal.h>
81 #include <stdio.h>
82 #include <stdlib.h>
83 #include <string.h>
84 #include <syslog.h>
85 #include <time.h>
86 #include <unistd.h>
87 #include <libutil.h>
88 
89 #ifdef	SKEY
90 #include <skey.h>
91 #endif
92 
93 #include "pathnames.h"
94 #include "extern.h"
95 
96 #if __STDC__
97 #include <stdarg.h>
98 #else
99 #include <varargs.h>
100 #endif
101 
102 static char version[] = "Version 6.00";
103 
104 extern	off_t restart_point;
105 extern	char cbuf[];
106 
107 struct	sockaddr_in server_addr;
108 struct	sockaddr_in ctrl_addr;
109 struct	sockaddr_in data_source;
110 struct	sockaddr_in data_dest;
111 struct	sockaddr_in his_addr;
112 struct	sockaddr_in pasv_addr;
113 
114 int	daemon_mode;
115 int	data;
116 jmp_buf	errcatch, urgcatch;
117 int	logged_in;
118 struct	passwd *pw;
119 int	debug;
120 int	timeout = 900;    /* timeout after 15 minutes of inactivity */
121 int	maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */
122 int	logging;
123 int	restricted_data_ports = 1;
124 int	paranoid = 1;	  /* be extra careful about security */
125 int	guest;
126 int	dochroot;
127 int	stats;
128 int	statfd = -1;
129 int	type;
130 int	form;
131 int	stru;			/* avoid C keyword */
132 int	mode;
133 int	usedefault = 1;		/* for data transfers */
134 int	pdata = -1;		/* for passive mode */
135 sig_atomic_t transflag;
136 off_t	file_size;
137 off_t	byte_count;
138 #if !defined(CMASK) || CMASK == 0
139 #undef CMASK
140 #define CMASK 027
141 #endif
142 int	defumask = CMASK;		/* default umask value */
143 char	tmpline[7];
144 char	hostname[MAXHOSTNAMELEN];
145 char	remotehost[MAXHOSTNAMELEN];
146 char	*ident = NULL;
147 
148 static char ttyline[20];
149 char	*tty = ttyline;		/* for klogin */
150 
151 #ifdef KERBEROS
152 int	 klogin __P((struct passwd *, char *, char *, char *));
153 #endif
154 
155 struct	in_addr bind_address;
156 char	*pid_file = NULL;
157 
158 #if defined(KERBEROS)
159 int	notickets = 1;
160 int	noticketsdontcomplain = 1;
161 char	*krbtkfile_env = NULL;
162 #endif
163 
164 /*
165  * Timeout intervals for retrying connections
166  * to hosts that don't accept PORT cmds.  This
167  * is a kludge, but given the problems with TCP...
168  */
169 #define	SWAITMAX	90	/* wait at most 90 seconds */
170 #define	SWAITINT	5	/* interval between retries */
171 
172 int	swaitmax = SWAITMAX;
173 int	swaitint = SWAITINT;
174 
175 #ifdef SETPROCTITLE
176 #ifdef OLD_SETPROCTITLE
177 char	**Argv = NULL;		/* pointer to argument vector */
178 char	*LastArgv = NULL;	/* end of argv */
179 #endif /* OLD_SETPROCTITLE */
180 char	proctitle[LINE_MAX];	/* initial part of title */
181 #endif /* SETPROCTITLE */
182 
183 #ifdef SKEY
184 int	pwok = 0;
185 char	addr_string[20];	/* XXX */
186 #endif
187 
188 #define LOGCMD(cmd, file) \
189 	if (logging > 1) \
190 	    syslog(LOG_INFO,"%s %s%s", cmd, \
191 		*(file) == '/' ? "" : curdir(), file);
192 #define LOGCMD2(cmd, file1, file2) \
193 	 if (logging > 1) \
194 	    syslog(LOG_INFO,"%s %s%s %s%s", cmd, \
195 		*(file1) == '/' ? "" : curdir(), file1, \
196 		*(file2) == '/' ? "" : curdir(), file2);
197 #define LOGBYTES(cmd, file, cnt) \
198 	if (logging > 1) { \
199 		if (cnt == (off_t)-1) \
200 		    syslog(LOG_INFO,"%s %s%s", cmd, \
201 			*(file) == '/' ? "" : curdir(), file); \
202 		else \
203 		    syslog(LOG_INFO, "%s %s%s = %qd bytes", \
204 			cmd, (*(file) == '/') ? "" : curdir(), file, cnt); \
205 	}
206 
207 static void	 ack __P((char *));
208 static void	 myoob __P((int));
209 static int	 checkuser __P((char *, char *));
210 static FILE	*dataconn __P((char *, off_t, char *));
211 static void	 dolog __P((struct sockaddr_in *));
212 static char	*curdir __P((void));
213 static void	 end_login __P((void));
214 static FILE	*getdatasock __P((char *));
215 static char	*gunique __P((char *));
216 static void	 lostconn __P((int));
217 static int	 receive_data __P((FILE *, FILE *));
218 static void	 send_data __P((FILE *, FILE *, off_t, off_t, int));
219 static struct passwd *
220 		 sgetpwnam __P((char *));
221 static char	*sgetsave __P((char *));
222 static void	 reapchild __P((int));
223 static void      logxfer __P((char *, long, long));
224 
225 static char *
226 curdir()
227 {
228 	static char path[MAXPATHLEN+1+1];	/* path + '/' + '\0' */
229 
230 	if (getcwd(path, sizeof(path)-2) == NULL)
231 		return ("");
232 	if (path[1] != '\0')		/* special case for root dir. */
233 		strcat(path, "/");
234 	/* For guest account, skip / since it's chrooted */
235 	return (guest ? path+1 : path);
236 }
237 
238 int
239 main(argc, argv, envp)
240 	int argc;
241 	char *argv[];
242 	char **envp;
243 {
244 	int addrlen, ch, on = 1, tos;
245 	char *cp, line[LINE_MAX];
246 	FILE *fd;
247 
248 	tzset();		/* in case no timezone database in ~ftp */
249 
250 #ifdef OLD_SETPROCTITLE
251 	/*
252 	 *  Save start and extent of argv for setproctitle.
253 	 */
254 	Argv = argv;
255 	while (*envp)
256 		envp++;
257 	LastArgv = envp[-1] + strlen(envp[-1]);
258 #endif /* OLD_SETPROCTITLE */
259 
260 
261 	bind_address.s_addr = htonl(INADDR_ANY);
262 	while ((ch = getopt(argc, argv, "dlDSUt:T:u:va:p:")) != EOF) {
263 		switch (ch) {
264 		case 'D':
265 			daemon_mode++;
266 			break;
267 
268 		case 'd':
269 			debug++;
270 			break;
271 
272 		case 'l':
273 			logging++;	/* > 1 == extra logging */
274 			break;
275 
276 		case 'R':
277 			paranoid = 0;
278 			break;
279 
280 		case 'S':
281 			stats++;
282 			break;
283 
284 		case 'T':
285 			maxtimeout = atoi(optarg);
286 			if (timeout > maxtimeout)
287 				timeout = maxtimeout;
288 			break;
289 
290 		case 't':
291 			timeout = atoi(optarg);
292 			if (maxtimeout < timeout)
293 				maxtimeout = timeout;
294 			break;
295 
296 		case 'U':
297 			restricted_data_ports = 0;
298 			break;
299 
300 		case 'a':
301 			if (!inet_aton(optarg, &bind_address))
302 				errx(1, "invalid address for -a");
303 			break;
304 
305 		case 'p':
306 			pid_file = optarg;
307 			break;
308 
309 		case 'u':
310 		    {
311 			long val = 0;
312 
313 			val = strtol(optarg, &optarg, 8);
314 			if (*optarg != '\0' || val < 0)
315 				warnx("bad value for -u");
316 			else
317 				defumask = val;
318 			break;
319 		    }
320 
321 		case 'v':
322 			debug = 1;
323 			break;
324 
325 		default:
326 			warnx("unknown flag -%c ignored", optopt);
327 			break;
328 		}
329 	}
330 
331 	(void) freopen(_PATH_DEVNULL, "w", stderr);
332 
333 	/*
334 	 * LOG_NDELAY sets up the logging connection immediately,
335 	 * necessary for anonymous ftp's that chroot and can't do it later.
336 	 */
337 	openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
338 
339 	if (daemon_mode) {
340 		int ctl_sock, fd;
341 		struct servent *sv;
342 
343 		/*
344 		 * Detach from parent.
345 		 */
346 		if (daemon(1, 1) < 0) {
347 			syslog(LOG_ERR, "failed to become a daemon");
348 			exit(1);
349 		}
350 		(void) signal(SIGCHLD, reapchild);
351 		/*
352 		 * Get port number for ftp/tcp.
353 		 */
354 		sv = getservbyname("ftp", "tcp");
355 		if (sv == NULL) {
356 			syslog(LOG_ERR, "getservbyname for ftp failed");
357 			exit(1);
358 		}
359 		/*
360 		 * Open a socket, bind it to the FTP port, and start
361 		 * listening.
362 		 */
363 		ctl_sock = socket(AF_INET, SOCK_STREAM, 0);
364 		if (ctl_sock < 0) {
365 			syslog(LOG_ERR, "control socket: %m");
366 			exit(1);
367 		}
368 		if (setsockopt(ctl_sock, SOL_SOCKET, SO_REUSEADDR,
369 		    (char *)&on, sizeof(on)) < 0)
370 			syslog(LOG_ERR, "control setsockopt: %m");;
371 		server_addr.sin_family = AF_INET;
372 		server_addr.sin_addr = bind_address;
373 		server_addr.sin_port = sv->s_port;
374 		if (bind(ctl_sock, (struct sockaddr *)&server_addr, sizeof(server_addr))) {
375 			syslog(LOG_ERR, "control bind: %m");
376 			exit(1);
377 		}
378 		if (listen(ctl_sock, 32) < 0) {
379 			syslog(LOG_ERR, "control listen: %m");
380 			exit(1);
381 		}
382 		/*
383 		 * Atomically write process ID
384 		 */
385 		if (pid_file)
386 		{
387 			int fd;
388 			char buf[20];
389 
390 			fd = open(pid_file, O_CREAT | O_WRONLY | O_TRUNC
391 				| O_NONBLOCK | O_EXLOCK, 0644);
392 			if (fd < 0)
393 				if (errno == EAGAIN)
394 					errx(1, "%s: file locked", pid_file);
395 				else
396 					err(1, "%s", pid_file);
397 			snprintf(buf, sizeof(buf),
398 				"%lu\n", (unsigned long) getpid());
399 			if (write(fd, buf, strlen(buf)) < 0)
400 				err(1, "%s: write", pid_file);
401 			/* Leave the pid file open and locked */
402 		}
403 		/*
404 		 * Loop forever accepting connection requests and forking off
405 		 * children to handle them.
406 		 */
407 		while (1) {
408 			addrlen = sizeof(his_addr);
409 			fd = accept(ctl_sock, (struct sockaddr *)&his_addr, &addrlen);
410 			if (fork() == 0) {
411 				/* child */
412 				(void) dup2(fd, 0);
413 				(void) dup2(fd, 1);
414 				close(ctl_sock);
415 				break;
416 			}
417 			close(fd);
418 		}
419 	} else {
420 		addrlen = sizeof(his_addr);
421 		if (getpeername(0, (struct sockaddr *)&his_addr, &addrlen) < 0) {
422 			syslog(LOG_ERR, "getpeername (%s): %m",argv[0]);
423 			exit(1);
424 		}
425 	}
426 
427 	(void) signal(SIGCHLD, SIG_IGN);
428 	(void) signal(SIGPIPE, lostconn);
429 	if ((int)signal(SIGURG, myoob) < 0)
430 		syslog(LOG_ERR, "signal: %m");
431 
432 #ifdef SKEY
433 	strncpy(addr_string, inet_ntoa(his_addr.sin_addr), sizeof(addr_string));
434 #endif
435 	addrlen = sizeof(ctrl_addr);
436 	if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) {
437 		syslog(LOG_ERR, "getsockname (%s): %m",argv[0]);
438 		exit(1);
439 	}
440 #ifdef IP_TOS
441 	tos = IPTOS_LOWDELAY;
442 	if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
443 		syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
444 #endif
445 	data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1);
446 
447 	/* set this here so klogin can use it... */
448 	(void)sprintf(ttyline, "ftp%d", getpid());
449 
450 	/* Try to handle urgent data inline */
451 #ifdef SO_OOBINLINE
452 	if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) < 0)
453 		syslog(LOG_ERR, "setsockopt: %m");
454 #endif
455 
456 #ifdef	F_SETOWN
457 	if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1)
458 		syslog(LOG_ERR, "fcntl F_SETOWN: %m");
459 #endif
460 	dolog(&his_addr);
461 	/*
462 	 * Set up default state
463 	 */
464 	data = -1;
465 	type = TYPE_A;
466 	form = FORM_N;
467 	stru = STRU_F;
468 	mode = MODE_S;
469 	tmpline[0] = '\0';
470 
471 	/* If logins are disabled, print out the message. */
472 	if ((fd = fopen(_PATH_NOLOGIN,"r")) != NULL) {
473 		while (fgets(line, sizeof(line), fd) != NULL) {
474 			if ((cp = strchr(line, '\n')) != NULL)
475 				*cp = '\0';
476 			lreply(530, "%s", line);
477 		}
478 		(void) fflush(stdout);
479 		(void) fclose(fd);
480 		reply(530, "System not available.");
481 		exit(0);
482 	}
483 	if ((fd = fopen(_PATH_FTPWELCOME, "r")) != NULL) {
484 		while (fgets(line, sizeof(line), fd) != NULL) {
485 			if ((cp = strchr(line, '\n')) != NULL)
486 				*cp = '\0';
487 			lreply(220, "%s", line);
488 		}
489 		(void) fflush(stdout);
490 		(void) fclose(fd);
491 		/* reply(220,) must follow */
492 	}
493 	(void) gethostname(hostname, sizeof(hostname));
494 	reply(220, "%s FTP server (%s) ready.", hostname, version);
495 	(void) setjmp(errcatch);
496 	for (;;)
497 		(void) yyparse();
498 	/* NOTREACHED */
499 }
500 
501 static void
502 lostconn(signo)
503 	int signo;
504 {
505 
506 	if (debug)
507 		syslog(LOG_DEBUG, "lost connection");
508 	dologout(-1);
509 }
510 
511 /*
512  * Helper function for sgetpwnam().
513  */
514 static char *
515 sgetsave(s)
516 	char *s;
517 {
518 	char *new = malloc((unsigned) strlen(s) + 1);
519 
520 	if (new == NULL) {
521 		perror_reply(421, "Local resource failure: malloc");
522 		dologout(1);
523 		/* NOTREACHED */
524 	}
525 	(void) strcpy(new, s);
526 	return (new);
527 }
528 
529 /*
530  * Save the result of a getpwnam.  Used for USER command, since
531  * the data returned must not be clobbered by any other command
532  * (e.g., globbing).
533  */
534 static struct passwd *
535 sgetpwnam(name)
536 	char *name;
537 {
538 	static struct passwd save;
539 	struct passwd *p;
540 
541 	if ((p = getpwnam(name)) == NULL)
542 		return (p);
543 	if (save.pw_name) {
544 		free(save.pw_name);
545 		free(save.pw_passwd);
546 		free(save.pw_gecos);
547 		free(save.pw_dir);
548 		free(save.pw_shell);
549 	}
550 	save = *p;
551 	save.pw_name = sgetsave(p->pw_name);
552 	save.pw_passwd = sgetsave(p->pw_passwd);
553 	save.pw_gecos = sgetsave(p->pw_gecos);
554 	save.pw_dir = sgetsave(p->pw_dir);
555 	save.pw_shell = sgetsave(p->pw_shell);
556 	return (&save);
557 }
558 
559 static int login_attempts;	/* number of failed login attempts */
560 static int askpasswd;		/* had user command, ask for passwd */
561 static char curname[10];	/* current USER name */
562 
563 /*
564  * USER command.
565  * Sets global passwd pointer pw if named account exists and is acceptable;
566  * sets askpasswd if a PASS command is expected.  If logged in previously,
567  * need to reset state.  If name is "ftp" or "anonymous", the name is not in
568  * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return.
569  * If account doesn't exist, ask for passwd anyway.  Otherwise, check user
570  * requesting login privileges.  Disallow anyone who does not have a standard
571  * shell as returned by getusershell().  Disallow anyone mentioned in the file
572  * _PATH_FTPUSERS to allow people such as root and uucp to be avoided.
573  */
574 void
575 user(name)
576 	char *name;
577 {
578 	char *cp, *shell;
579 
580 	if (logged_in) {
581 		if (guest) {
582 			reply(530, "Can't change user from guest login.");
583 			return;
584 		} else if (dochroot) {
585 			reply(530, "Can't change user from chroot user.");
586 			return;
587 		}
588 		end_login();
589 	}
590 
591 	guest = 0;
592 	if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) {
593 		if (checkuser(_PATH_FTPUSERS, "ftp") ||
594 		    checkuser(_PATH_FTPUSERS, "anonymous"))
595 			reply(530, "User %s access denied.", name);
596 		else if ((pw = sgetpwnam("ftp")) != NULL) {
597 			guest = 1;
598 			askpasswd = 1;
599 			reply(331,
600 			"Guest login ok, send your email address as password.");
601 		} else
602 			reply(530, "User %s unknown.", name);
603 		if (!askpasswd && logging)
604 			syslog(LOG_NOTICE,
605 			    "ANONYMOUS FTP LOGIN REFUSED FROM %s", remotehost);
606 		return;
607 	}
608 	if ((pw = sgetpwnam(name))) {
609 		if ((shell = pw->pw_shell) == NULL || *shell == 0)
610 			shell = _PATH_BSHELL;
611 		while ((cp = getusershell()) != NULL)
612 			if (strcmp(cp, shell) == 0)
613 				break;
614 		endusershell();
615 
616 		if (cp == NULL || checkuser(_PATH_FTPUSERS, name)) {
617 			reply(530, "User %s access denied.", name);
618 			if (logging)
619 				syslog(LOG_NOTICE,
620 				    "FTP LOGIN REFUSED FROM %s, %s",
621 				    remotehost, name);
622 			pw = (struct passwd *) NULL;
623 			return;
624 		}
625 	}
626 	if (logging)
627 		strncpy(curname, name, sizeof(curname)-1);
628 #ifdef SKEY
629 	pwok = skeyaccess(name, NULL, remotehost, addr_string);
630 	reply(331, "%s", skey_challenge(name, pw, pwok));
631 #else
632 	reply(331, "Password required for %s.", name);
633 #endif
634 	askpasswd = 1;
635 	/*
636 	 * Delay before reading passwd after first failed
637 	 * attempt to slow down passwd-guessing programs.
638 	 */
639 	if (login_attempts)
640 		sleep((unsigned) login_attempts);
641 }
642 
643 /*
644  * Check if a user is in the file "fname"
645  */
646 static int
647 checkuser(fname, name)
648 	char *fname;
649 	char *name;
650 {
651 	FILE *fd;
652 	int found = 0;
653 	char *p, line[BUFSIZ];
654 
655 	if ((fd = fopen(fname, "r")) != NULL) {
656 		while (fgets(line, sizeof(line), fd) != NULL)
657 			if ((p = strchr(line, '\n')) != NULL) {
658 				*p = '\0';
659 				if (line[0] == '#')
660 					continue;
661 				if (strcmp(line, name) == 0) {
662 					found = 1;
663 					break;
664 				}
665 			}
666 		(void) fclose(fd);
667 	}
668 	return (found);
669 }
670 
671 /*
672  * Terminate login as previous user, if any, resetting state;
673  * used when USER command is given or login fails.
674  */
675 static void
676 end_login()
677 {
678 
679 	(void) seteuid((uid_t)0);
680 	if (logged_in)
681 		logwtmp(ttyline, "", "");
682 	pw = NULL;
683 	logged_in = 0;
684 	guest = 0;
685 	dochroot = 0;
686 }
687 
688 void
689 pass(passwd)
690 	char *passwd;
691 {
692 	int rval;
693 	FILE *fd;
694 	static char homedir[MAXPATHLEN];
695 
696 	if (logged_in || askpasswd == 0) {
697 		reply(503, "Login with USER first.");
698 		return;
699 	}
700 	askpasswd = 0;
701 	if (!guest) {		/* "ftp" is only account allowed no password */
702 		if (pw == NULL) {
703 			rval = 1;	/* failure below */
704 			goto skip;
705 		}
706 #if defined(KERBEROS)
707 		rval = klogin(pw, "", hostname, passwd);
708 		if (rval == 0)
709 			goto skip;
710 #endif
711 #ifdef SKEY
712 		rval = strcmp(skey_crypt(passwd, pw->pw_passwd, pw, pwok),
713 			      pw->pw_passwd);
714 		pwok = 0;
715 #else
716 		rval = strcmp(crypt(passwd, pw->pw_passwd), pw->pw_passwd);
717 #endif
718 		/* The strcmp does not catch null passwords! */
719 		if (*pw->pw_passwd == '\0' ||
720 		    (pw->pw_expire && time(NULL) >= pw->pw_expire))
721 			rval = 1;	/* failure */
722 skip:
723 		/*
724 		 * If rval == 1, the user failed the authentication check
725 		 * above.  If rval == 0, either Kerberos or local authentication
726 		 * succeeded.
727 		 */
728 		if (rval) {
729 			reply(530, "Login incorrect.");
730 			if (logging)
731 				syslog(LOG_NOTICE,
732 				    "FTP LOGIN FAILED FROM %s, %s",
733 				    remotehost, curname);
734 			pw = NULL;
735 			if (login_attempts++ >= 5) {
736 				syslog(LOG_NOTICE,
737 				    "repeated login failures from %s",
738 				    remotehost);
739 				exit(0);
740 			}
741 			return;
742 		}
743 	}
744 	login_attempts = 0;		/* this time successful */
745 	if (setegid((gid_t)pw->pw_gid) < 0) {
746 		reply(550, "Can't set gid.");
747 		return;
748 	}
749 	(void) initgroups(pw->pw_name, pw->pw_gid);
750 
751 	/* open wtmp before chroot */
752 	logwtmp(ttyline, pw->pw_name, remotehost);
753 	logged_in = 1;
754 
755 	if (guest && stats && statfd < 0)
756 		if ((statfd = open(_PATH_FTPDSTATFILE, O_WRONLY|O_APPEND)) < 0)
757 			stats = 0;
758 
759 	dochroot = checkuser(_PATH_FTPCHROOT, pw->pw_name);
760 	if (guest) {
761 		/*
762 		 * We MUST do a chdir() after the chroot. Otherwise
763 		 * the old current directory will be accessible as "."
764 		 * outside the new root!
765 		 */
766 		if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
767 			reply(550, "Can't set guest privileges.");
768 			goto bad;
769 		}
770 	} else if (dochroot) {
771 		if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
772 			reply(550, "Can't change root.");
773 			goto bad;
774 		}
775 	} else if (chdir(pw->pw_dir) < 0) {
776 		if (chdir("/") < 0) {
777 			reply(530, "User %s: can't change directory to %s.",
778 			    pw->pw_name, pw->pw_dir);
779 			goto bad;
780 		} else
781 			lreply(230, "No directory! Logging in with home=/");
782 	}
783 	if (seteuid((uid_t)pw->pw_uid) < 0) {
784 		reply(550, "Can't set uid.");
785 		goto bad;
786 	}
787 
788 	/*
789 	 * Set home directory so that use of ~ (tilde) works correctly.
790 	 */
791 	if (getcwd(homedir, MAXPATHLEN) != NULL)
792 		setenv("HOME", homedir, 1);
793 
794 	/*
795 	 * Display a login message, if it exists.
796 	 * N.B. reply(230,) must follow the message.
797 	 */
798 	if ((fd = fopen(_PATH_FTPLOGINMESG, "r")) != NULL) {
799 		char *cp, line[LINE_MAX];
800 
801 		while (fgets(line, sizeof(line), fd) != NULL) {
802 			if ((cp = strchr(line, '\n')) != NULL)
803 				*cp = '\0';
804 			lreply(230, "%s", line);
805 		}
806 		(void) fflush(stdout);
807 		(void) fclose(fd);
808 	}
809 	if (guest) {
810 		if (ident != NULL)
811 			free(ident);
812 		ident = strdup(passwd);
813 		if (ident == NULL)
814 			fatal("Ran out of memory.");
815 
816 		reply(230, "Guest login ok, access restrictions apply.");
817 #ifdef SETPROCTITLE
818 		snprintf(proctitle, sizeof(proctitle),
819 		    "%s: anonymous/%.*s", remotehost,
820 		    sizeof(proctitle) - sizeof(remotehost) -
821 		    sizeof(": anonymous/"), passwd);
822 		setproctitle("%s", proctitle);
823 #endif /* SETPROCTITLE */
824 		if (logging)
825 			syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s",
826 			    remotehost, passwd);
827 	} else {
828 		reply(230, "User %s logged in.", pw->pw_name);
829 #ifdef SETPROCTITLE
830 		snprintf(proctitle, sizeof(proctitle),
831 		    "%s: %s", remotehost, pw->pw_name);
832 		setproctitle("%s", proctitle);
833 #endif /* SETPROCTITLE */
834 		if (logging)
835 			syslog(LOG_INFO, "FTP LOGIN FROM %s as %s",
836 			    remotehost, pw->pw_name);
837 	}
838 	(void) umask(defumask);
839 	return;
840 bad:
841 	/* Forget all about it... */
842 	end_login();
843 }
844 
845 void
846 retrieve(cmd, name)
847 	char *cmd, *name;
848 {
849 	FILE *fin, *dout;
850 	struct stat st;
851 	int (*closefunc) __P((FILE *));
852 	long start;
853 
854 	if (cmd == 0) {
855 		fin = fopen(name, "r"), closefunc = fclose;
856 		st.st_size = 0;
857 	} else {
858 		char line[BUFSIZ];
859 
860 		(void) sprintf(line, cmd, name), name = line;
861 		fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose;
862 		st.st_size = -1;
863 		st.st_blksize = BUFSIZ;
864 	}
865 	if (fin == NULL) {
866 		if (errno != 0) {
867 			perror_reply(550, name);
868 			if (cmd == 0) {
869 				LOGCMD("get", name);
870 			}
871 		}
872 		return;
873 	}
874 	byte_count = -1;
875 	if (cmd == 0 && (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode))) {
876 		reply(550, "%s: not a plain file.", name);
877 		goto done;
878 	}
879 	if (restart_point) {
880 		if (type == TYPE_A) {
881 			off_t i, n;
882 			int c;
883 
884 			n = restart_point;
885 			i = 0;
886 			while (i++ < n) {
887 				if ((c=getc(fin)) == EOF) {
888 					perror_reply(550, name);
889 					goto done;
890 				}
891 				if (c == '\n')
892 					i++;
893 			}
894 		} else if (lseek(fileno(fin), restart_point, L_SET) < 0) {
895 			perror_reply(550, name);
896 			goto done;
897 		}
898 	}
899 	dout = dataconn(name, st.st_size, "w");
900 	if (dout == NULL)
901 		goto done;
902 	time(&start);
903 	send_data(fin, dout, st.st_blksize, st.st_size,
904 		  restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode));
905 	if (cmd == 0 && guest && stats)
906 		logxfer(name, st.st_size, start);
907 	(void) fclose(dout);
908 	data = -1;
909 	pdata = -1;
910 done:
911 	if (cmd == 0)
912 		LOGBYTES("get", name, byte_count);
913 	(*closefunc)(fin);
914 }
915 
916 void
917 store(name, mode, unique)
918 	char *name, *mode;
919 	int unique;
920 {
921 	FILE *fout, *din;
922 	struct stat st;
923 	int (*closefunc) __P((FILE *));
924 
925 	if ((unique || guest) && stat(name, &st) == 0 &&
926 	    (name = gunique(name)) == NULL) {
927 		LOGCMD(*mode == 'w' ? "put" : "append", name);
928 		return;
929 	}
930 
931 	if (restart_point)
932 		mode = "r+";
933 	fout = fopen(name, mode);
934 	closefunc = fclose;
935 	if (fout == NULL) {
936 		perror_reply(553, name);
937 		LOGCMD(*mode == 'w' ? "put" : "append", name);
938 		return;
939 	}
940 	byte_count = -1;
941 	if (restart_point) {
942 		if (type == TYPE_A) {
943 			off_t i, n;
944 			int c;
945 
946 			n = restart_point;
947 			i = 0;
948 			while (i++ < n) {
949 				if ((c=getc(fout)) == EOF) {
950 					perror_reply(550, name);
951 					goto done;
952 				}
953 				if (c == '\n')
954 					i++;
955 			}
956 			/*
957 			 * We must do this seek to "current" position
958 			 * because we are changing from reading to
959 			 * writing.
960 			 */
961 			if (fseek(fout, 0L, L_INCR) < 0) {
962 				perror_reply(550, name);
963 				goto done;
964 			}
965 		} else if (lseek(fileno(fout), restart_point, L_SET) < 0) {
966 			perror_reply(550, name);
967 			goto done;
968 		}
969 	}
970 	din = dataconn(name, (off_t)-1, "r");
971 	if (din == NULL)
972 		goto done;
973 	if (receive_data(din, fout) == 0) {
974 		if (unique)
975 			reply(226, "Transfer complete (unique file name:%s).",
976 			    name);
977 		else
978 			reply(226, "Transfer complete.");
979 	}
980 	(void) fclose(din);
981 	data = -1;
982 	pdata = -1;
983 done:
984 	LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count);
985 	(*closefunc)(fout);
986 }
987 
988 static FILE *
989 getdatasock(mode)
990 	char *mode;
991 {
992 	int on = 1, s, t, tries;
993 
994 	if (data >= 0)
995 		return (fdopen(data, mode));
996 	(void) seteuid((uid_t)0);
997 	s = socket(AF_INET, SOCK_STREAM, 0);
998 	if (s < 0)
999 		goto bad;
1000 	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
1001 	    (char *) &on, sizeof(on)) < 0)
1002 		goto bad;
1003 	/* anchor socket to avoid multi-homing problems */
1004 	data_source.sin_len = sizeof(struct sockaddr_in);
1005 	data_source.sin_family = AF_INET;
1006 	data_source.sin_addr = ctrl_addr.sin_addr;
1007 	for (tries = 1; ; tries++) {
1008 		if (bind(s, (struct sockaddr *)&data_source,
1009 		    sizeof(data_source)) >= 0)
1010 			break;
1011 		if (errno != EADDRINUSE || tries > 10)
1012 			goto bad;
1013 		sleep(tries);
1014 	}
1015 	(void) seteuid((uid_t)pw->pw_uid);
1016 #ifdef IP_TOS
1017 	on = IPTOS_THROUGHPUT;
1018 	if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
1019 		syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
1020 #endif
1021 #ifdef TCP_NOPUSH
1022 	/*
1023 	 * Turn off push flag to keep sender TCP from sending short packets
1024 	 * at the boundaries of each write().  Should probably do a SO_SNDBUF
1025 	 * to set the send buffer size as well, but that may not be desirable
1026 	 * in heavy-load situations.
1027 	 */
1028 	on = 1;
1029 	if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, (char *)&on, sizeof on) < 0)
1030 		syslog(LOG_WARNING, "setsockopt (TCP_NOPUSH): %m");
1031 #endif
1032 #ifdef SO_SNDBUF
1033 	on = 65536;
1034 	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&on, sizeof on) < 0)
1035 		syslog(LOG_WARNING, "setsockopt (SO_SNDBUF): %m");
1036 #endif
1037 
1038 	return (fdopen(s, mode));
1039 bad:
1040 	/* Return the real value of errno (close may change it) */
1041 	t = errno;
1042 	(void) seteuid((uid_t)pw->pw_uid);
1043 	(void) close(s);
1044 	errno = t;
1045 	return (NULL);
1046 }
1047 
1048 static FILE *
1049 dataconn(name, size, mode)
1050 	char *name;
1051 	off_t size;
1052 	char *mode;
1053 {
1054 	char sizebuf[32];
1055 	FILE *file;
1056 	int retry = 0, tos;
1057 
1058 	file_size = size;
1059 	byte_count = 0;
1060 	if (size != (off_t) -1)
1061 		(void) sprintf(sizebuf, " (%qd bytes)", size);
1062 	else
1063 		(void) strcpy(sizebuf, "");
1064 	if (pdata >= 0) {
1065 		struct sockaddr_in from;
1066 		int s, fromlen = sizeof(from);
1067 		struct timeval timeout;
1068 		fd_set set;
1069 
1070 		FD_ZERO(&set);
1071 		FD_SET(pdata, &set);
1072 
1073 		timeout.tv_usec = 0;
1074 		timeout.tv_sec = 120;
1075 
1076 		if (select(pdata+1, &set, (fd_set *) 0, (fd_set *) 0, &timeout) == 0 ||
1077 		    (s = accept(pdata, (struct sockaddr *) &from, &fromlen)) < 0) {
1078 			reply(425, "Can't open data connection.");
1079 			(void) close(pdata);
1080 			pdata = -1;
1081 			return (NULL);
1082 		}
1083 		(void) close(pdata);
1084 		pdata = s;
1085 #ifdef IP_TOS
1086 		tos = IPTOS_THROUGHPUT;
1087 		(void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos,
1088 		    sizeof(int));
1089 #endif
1090 		reply(150, "Opening %s mode data connection for '%s'%s.",
1091 		     type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1092 		return (fdopen(pdata, mode));
1093 	}
1094 	if (data >= 0) {
1095 		reply(125, "Using existing data connection for '%s'%s.",
1096 		    name, sizebuf);
1097 		usedefault = 1;
1098 		return (fdopen(data, mode));
1099 	}
1100 	if (usedefault)
1101 		data_dest = his_addr;
1102 	usedefault = 1;
1103 	file = getdatasock(mode);
1104 	if (file == NULL) {
1105 		reply(425, "Can't create data socket (%s,%d): %s.",
1106 		    inet_ntoa(data_source.sin_addr),
1107 		    ntohs(data_source.sin_port), strerror(errno));
1108 		return (NULL);
1109 	}
1110 	data = fileno(file);
1111 	while (connect(data, (struct sockaddr *)&data_dest,
1112 	    sizeof(data_dest)) < 0) {
1113 		if (errno == EADDRINUSE && retry < swaitmax) {
1114 			sleep((unsigned) swaitint);
1115 			retry += swaitint;
1116 			continue;
1117 		}
1118 		perror_reply(425, "Can't build data connection");
1119 		(void) fclose(file);
1120 		data = -1;
1121 		return (NULL);
1122 	}
1123 	reply(150, "Opening %s mode data connection for '%s'%s.",
1124 	     type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1125 	return (file);
1126 }
1127 
1128 /*
1129  * Tranfer the contents of "instr" to "outstr" peer using the appropriate
1130  * encapsulation of the data subject to Mode, Structure, and Type.
1131  *
1132  * NB: Form isn't handled.
1133  */
1134 static void
1135 send_data(instr, outstr, blksize, filesize, isreg)
1136 	FILE *instr, *outstr;
1137 	off_t blksize;
1138 	off_t filesize;
1139 	int isreg;
1140 {
1141 	int c, cnt, filefd, netfd;
1142 	char *buf, *bp;
1143 	size_t len;
1144 
1145 	transflag++;
1146 	if (setjmp(urgcatch)) {
1147 		transflag = 0;
1148 		return;
1149 	}
1150 	switch (type) {
1151 
1152 	case TYPE_A:
1153 		while ((c = getc(instr)) != EOF) {
1154 			byte_count++;
1155 			if (c == '\n') {
1156 				if (ferror(outstr))
1157 					goto data_err;
1158 				(void) putc('\r', outstr);
1159 			}
1160 			(void) putc(c, outstr);
1161 		}
1162 		fflush(outstr);
1163 		transflag = 0;
1164 		if (ferror(instr))
1165 			goto file_err;
1166 		if (ferror(outstr))
1167 			goto data_err;
1168 		reply(226, "Transfer complete.");
1169 		return;
1170 
1171 	case TYPE_I:
1172 	case TYPE_L:
1173 		/*
1174 		 * isreg is only set if we are not doing restart and we
1175 		 * are sending a regular file
1176 		 */
1177 		netfd = fileno(outstr);
1178 		filefd = fileno(instr);
1179 
1180 		if (isreg && filesize < (off_t)16 * 1024 * 1024) {
1181 			buf = mmap(0, filesize, PROT_READ, MAP_SHARED, filefd,
1182 				   (off_t)0);
1183 			if (!buf) {
1184 				syslog(LOG_WARNING, "mmap(%lu): %m",
1185 				       (unsigned long)filesize);
1186 				goto oldway;
1187 			}
1188 			bp = buf;
1189 			len = filesize;
1190 			do {
1191 				cnt = write(netfd, bp, len);
1192 				len -= cnt;
1193 				bp += cnt;
1194 				if (cnt > 0) byte_count += cnt;
1195 			} while(cnt > 0 && len > 0);
1196 
1197 			transflag = 0;
1198 			munmap(buf, (size_t)filesize);
1199 			if (cnt < 0)
1200 				goto data_err;
1201 			reply(226, "Transfer complete.");
1202 			return;
1203 		}
1204 
1205 oldway:
1206 		if ((buf = malloc((u_int)blksize)) == NULL) {
1207 			transflag = 0;
1208 			perror_reply(451, "Local resource failure: malloc");
1209 			return;
1210 		}
1211 
1212 		while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 &&
1213 		    write(netfd, buf, cnt) == cnt)
1214 			byte_count += cnt;
1215 		transflag = 0;
1216 		(void)free(buf);
1217 		if (cnt != 0) {
1218 			if (cnt < 0)
1219 				goto file_err;
1220 			goto data_err;
1221 		}
1222 		reply(226, "Transfer complete.");
1223 		return;
1224 	default:
1225 		transflag = 0;
1226 		reply(550, "Unimplemented TYPE %d in send_data", type);
1227 		return;
1228 	}
1229 
1230 data_err:
1231 	transflag = 0;
1232 	perror_reply(426, "Data connection");
1233 	return;
1234 
1235 file_err:
1236 	transflag = 0;
1237 	perror_reply(551, "Error on input file");
1238 }
1239 
1240 /*
1241  * Transfer data from peer to "outstr" using the appropriate encapulation of
1242  * the data subject to Mode, Structure, and Type.
1243  *
1244  * N.B.: Form isn't handled.
1245  */
1246 static int
1247 receive_data(instr, outstr)
1248 	FILE *instr, *outstr;
1249 {
1250 	int c;
1251 	int cnt, bare_lfs;
1252 	char buf[BUFSIZ];
1253 
1254 	transflag++;
1255 	if (setjmp(urgcatch)) {
1256 		transflag = 0;
1257 		return (-1);
1258 	}
1259 
1260 	bare_lfs = 0;
1261 
1262 	switch (type) {
1263 
1264 	case TYPE_I:
1265 	case TYPE_L:
1266 		while ((cnt = read(fileno(instr), buf, sizeof(buf))) > 0) {
1267 			if (write(fileno(outstr), buf, cnt) != cnt)
1268 				goto file_err;
1269 			byte_count += cnt;
1270 		}
1271 		if (cnt < 0)
1272 			goto data_err;
1273 		transflag = 0;
1274 		return (0);
1275 
1276 	case TYPE_E:
1277 		reply(553, "TYPE E not implemented.");
1278 		transflag = 0;
1279 		return (-1);
1280 
1281 	case TYPE_A:
1282 		while ((c = getc(instr)) != EOF) {
1283 			byte_count++;
1284 			if (c == '\n')
1285 				bare_lfs++;
1286 			while (c == '\r') {
1287 				if (ferror(outstr))
1288 					goto data_err;
1289 				if ((c = getc(instr)) != '\n') {
1290 					(void) putc ('\r', outstr);
1291 					if (c == '\0' || c == EOF)
1292 						goto contin2;
1293 				}
1294 			}
1295 			(void) putc(c, outstr);
1296 	contin2:	;
1297 		}
1298 		fflush(outstr);
1299 		if (ferror(instr))
1300 			goto data_err;
1301 		if (ferror(outstr))
1302 			goto file_err;
1303 		transflag = 0;
1304 		if (bare_lfs) {
1305 			lreply(226,
1306 		"WARNING! %d bare linefeeds received in ASCII mode",
1307 			    bare_lfs);
1308 		(void)printf("   File may not have transferred correctly.\r\n");
1309 		}
1310 		return (0);
1311 	default:
1312 		reply(550, "Unimplemented TYPE %d in receive_data", type);
1313 		transflag = 0;
1314 		return (-1);
1315 	}
1316 
1317 data_err:
1318 	transflag = 0;
1319 	perror_reply(426, "Data Connection");
1320 	return (-1);
1321 
1322 file_err:
1323 	transflag = 0;
1324 	perror_reply(452, "Error writing file");
1325 	return (-1);
1326 }
1327 
1328 void
1329 statfilecmd(filename)
1330 	char *filename;
1331 {
1332 	FILE *fin;
1333 	int c;
1334 	char line[LINE_MAX];
1335 
1336 	(void)snprintf(line, sizeof(line), "/bin/ls -lgA %s", filename);
1337 	fin = ftpd_popen(line, "r");
1338 	lreply(211, "status of %s:", filename);
1339 	while ((c = getc(fin)) != EOF) {
1340 		if (c == '\n') {
1341 			if (ferror(stdout)){
1342 				perror_reply(421, "control connection");
1343 				(void) ftpd_pclose(fin);
1344 				dologout(1);
1345 				/* NOTREACHED */
1346 			}
1347 			if (ferror(fin)) {
1348 				perror_reply(551, filename);
1349 				(void) ftpd_pclose(fin);
1350 				return;
1351 			}
1352 			(void) putc('\r', stdout);
1353 		}
1354 		(void) putc(c, stdout);
1355 	}
1356 	(void) ftpd_pclose(fin);
1357 	reply(211, "End of Status");
1358 }
1359 
1360 void
1361 statcmd()
1362 {
1363 	struct sockaddr_in *sin;
1364 	u_char *a, *p;
1365 
1366 	lreply(211, "%s FTP server status:", hostname, version);
1367 	printf("     %s\r\n", version);
1368 	printf("     Connected to %s", remotehost);
1369 	if (!isdigit(remotehost[0]))
1370 		printf(" (%s)", inet_ntoa(his_addr.sin_addr));
1371 	printf("\r\n");
1372 	if (logged_in) {
1373 		if (guest)
1374 			printf("     Logged in anonymously\r\n");
1375 		else
1376 			printf("     Logged in as %s\r\n", pw->pw_name);
1377 	} else if (askpasswd)
1378 		printf("     Waiting for password\r\n");
1379 	else
1380 		printf("     Waiting for user name\r\n");
1381 	printf("     TYPE: %s", typenames[type]);
1382 	if (type == TYPE_A || type == TYPE_E)
1383 		printf(", FORM: %s", formnames[form]);
1384 	if (type == TYPE_L)
1385 #if NBBY == 8
1386 		printf(" %d", NBBY);
1387 #else
1388 		printf(" %d", bytesize);	/* need definition! */
1389 #endif
1390 	printf("; STRUcture: %s; transfer MODE: %s\r\n",
1391 	    strunames[stru], modenames[mode]);
1392 	if (data != -1)
1393 		printf("     Data connection open\r\n");
1394 	else if (pdata != -1) {
1395 		printf("     in Passive mode");
1396 		sin = &pasv_addr;
1397 		goto printaddr;
1398 	} else if (usedefault == 0) {
1399 		printf("     PORT");
1400 		sin = &data_dest;
1401 printaddr:
1402 		a = (u_char *) &sin->sin_addr;
1403 		p = (u_char *) &sin->sin_port;
1404 #define UC(b) (((int) b) & 0xff)
1405 		printf(" (%d,%d,%d,%d,%d,%d)\r\n", UC(a[0]),
1406 			UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
1407 #undef UC
1408 	} else
1409 		printf("     No data connection\r\n");
1410 	reply(211, "End of status");
1411 }
1412 
1413 void
1414 fatal(s)
1415 	char *s;
1416 {
1417 
1418 	reply(451, "Error in server: %s\n", s);
1419 	reply(221, "Closing connection due to server error.");
1420 	dologout(0);
1421 	/* NOTREACHED */
1422 }
1423 
1424 void
1425 #if __STDC__
1426 reply(int n, const char *fmt, ...)
1427 #else
1428 reply(n, fmt, va_alist)
1429 	int n;
1430 	char *fmt;
1431         va_dcl
1432 #endif
1433 {
1434 	va_list ap;
1435 #if __STDC__
1436 	va_start(ap, fmt);
1437 #else
1438 	va_start(ap);
1439 #endif
1440 	(void)printf("%d ", n);
1441 	(void)vprintf(fmt, ap);
1442 	(void)printf("\r\n");
1443 	(void)fflush(stdout);
1444 	if (debug) {
1445 		syslog(LOG_DEBUG, "<--- %d ", n);
1446 		vsyslog(LOG_DEBUG, fmt, ap);
1447 	}
1448 }
1449 
1450 void
1451 #if __STDC__
1452 lreply(int n, const char *fmt, ...)
1453 #else
1454 lreply(n, fmt, va_alist)
1455 	int n;
1456 	char *fmt;
1457         va_dcl
1458 #endif
1459 {
1460 	va_list ap;
1461 #if __STDC__
1462 	va_start(ap, fmt);
1463 #else
1464 	va_start(ap);
1465 #endif
1466 	(void)printf("%d- ", n);
1467 	(void)vprintf(fmt, ap);
1468 	(void)printf("\r\n");
1469 	(void)fflush(stdout);
1470 	if (debug) {
1471 		syslog(LOG_DEBUG, "<--- %d- ", n);
1472 		vsyslog(LOG_DEBUG, fmt, ap);
1473 	}
1474 }
1475 
1476 static void
1477 ack(s)
1478 	char *s;
1479 {
1480 
1481 	reply(250, "%s command successful.", s);
1482 }
1483 
1484 void
1485 nack(s)
1486 	char *s;
1487 {
1488 
1489 	reply(502, "%s command not implemented.", s);
1490 }
1491 
1492 /* ARGSUSED */
1493 void
1494 yyerror(s)
1495 	char *s;
1496 {
1497 	char *cp;
1498 
1499 	if ((cp = strchr(cbuf,'\n')))
1500 		*cp = '\0';
1501 	reply(500, "'%s': command not understood.", cbuf);
1502 }
1503 
1504 void
1505 delete(name)
1506 	char *name;
1507 {
1508 	struct stat st;
1509 
1510 	LOGCMD("delete", name);
1511 	if (stat(name, &st) < 0) {
1512 		perror_reply(550, name);
1513 		return;
1514 	}
1515 	if ((st.st_mode&S_IFMT) == S_IFDIR) {
1516 		if (rmdir(name) < 0) {
1517 			perror_reply(550, name);
1518 			return;
1519 		}
1520 		goto done;
1521 	}
1522 	if (unlink(name) < 0) {
1523 		perror_reply(550, name);
1524 		return;
1525 	}
1526 done:
1527 	ack("DELE");
1528 }
1529 
1530 void
1531 cwd(path)
1532 	char *path;
1533 {
1534 
1535 	if (chdir(path) < 0)
1536 		perror_reply(550, path);
1537 	else
1538 		ack("CWD");
1539 }
1540 
1541 void
1542 makedir(name)
1543 	char *name;
1544 {
1545 
1546 	LOGCMD("mkdir", name);
1547 	if (mkdir(name, 0777) < 0)
1548 		perror_reply(550, name);
1549 	else
1550 		reply(257, "MKD command successful.");
1551 }
1552 
1553 void
1554 removedir(name)
1555 	char *name;
1556 {
1557 
1558 	LOGCMD("rmdir", name);
1559 	if (rmdir(name) < 0)
1560 		perror_reply(550, name);
1561 	else
1562 		ack("RMD");
1563 }
1564 
1565 void
1566 pwd()
1567 {
1568 	char path[MAXPATHLEN + 1];
1569 
1570 	if (getwd(path) == (char *)NULL)
1571 		reply(550, "%s.", path);
1572 	else
1573 		reply(257, "\"%s\" is current directory.", path);
1574 }
1575 
1576 char *
1577 renamefrom(name)
1578 	char *name;
1579 {
1580 	struct stat st;
1581 
1582 	if (stat(name, &st) < 0) {
1583 		perror_reply(550, name);
1584 		return ((char *)0);
1585 	}
1586 	reply(350, "File exists, ready for destination name");
1587 	return (name);
1588 }
1589 
1590 void
1591 renamecmd(from, to)
1592 	char *from, *to;
1593 {
1594 	struct stat st;
1595 
1596 	LOGCMD2("rename", from, to);
1597 
1598 	if (guest && (stat(to, &st) == 0)) {
1599 		reply(550, "%s: permission denied", to);
1600 		return;
1601 	}
1602 
1603 	if (rename(from, to) < 0)
1604 		perror_reply(550, "rename");
1605 	else
1606 		ack("RNTO");
1607 }
1608 
1609 static void
1610 dolog(sin)
1611 	struct sockaddr_in *sin;
1612 {
1613 	struct hostent *hp = gethostbyaddr((char *)&sin->sin_addr,
1614 		sizeof(struct in_addr), AF_INET);
1615 
1616 	if (hp)
1617 		(void) strncpy(remotehost, hp->h_name, sizeof(remotehost));
1618 	else
1619 		(void) strncpy(remotehost, inet_ntoa(sin->sin_addr),
1620 		    sizeof(remotehost));
1621 #ifdef SETPROCTITLE
1622 	snprintf(proctitle, sizeof(proctitle), "%s: connected", remotehost);
1623 	setproctitle("%s", proctitle);
1624 #endif /* SETPROCTITLE */
1625 
1626 	if (logging)
1627 		syslog(LOG_INFO, "connection from %s", remotehost);
1628 }
1629 
1630 /*
1631  * Record logout in wtmp file
1632  * and exit with supplied status.
1633  */
1634 void
1635 dologout(status)
1636 	int status;
1637 {
1638 
1639 	if (logged_in) {
1640 		(void) seteuid((uid_t)0);
1641 		logwtmp(ttyline, "", "");
1642 #if defined(KERBEROS)
1643 		if (!notickets && krbtkfile_env)
1644 			unlink(krbtkfile_env);
1645 #endif
1646 	}
1647 	/* beware of flushing buffers after a SIGPIPE */
1648 	_exit(status);
1649 }
1650 
1651 static void
1652 myoob(signo)
1653 	int signo;
1654 {
1655 	char *cp;
1656 
1657 	/* only process if transfer occurring */
1658 	if (!transflag)
1659 		return;
1660 	cp = tmpline;
1661 	if (getline(cp, 7, stdin) == NULL) {
1662 		reply(221, "You could at least say goodbye.");
1663 		dologout(0);
1664 	}
1665 	upper(cp);
1666 	if (strcmp(cp, "ABOR\r\n") == 0) {
1667 		tmpline[0] = '\0';
1668 		reply(426, "Transfer aborted. Data connection closed.");
1669 		reply(226, "Abort successful");
1670 		longjmp(urgcatch, 1);
1671 	}
1672 	if (strcmp(cp, "STAT\r\n") == 0) {
1673 		if (file_size != (off_t) -1)
1674 			reply(213, "Status: %qd of %qd bytes transferred",
1675 			    byte_count, file_size);
1676 		else
1677 			reply(213, "Status: %qd bytes transferred", byte_count);
1678 	}
1679 }
1680 
1681 /*
1682  * Note: a response of 425 is not mentioned as a possible response to
1683  *	the PASV command in RFC959. However, it has been blessed as
1684  *	a legitimate response by Jon Postel in a telephone conversation
1685  *	with Rick Adams on 25 Jan 89.
1686  */
1687 void
1688 passive()
1689 {
1690 	int len, on;
1691 	char *p, *a;
1692 
1693 	if (pdata >= 0)		/* close old port if one set */
1694 		close(pdata);
1695 
1696 	pdata = socket(AF_INET, SOCK_STREAM, 0);
1697 	if (pdata < 0) {
1698 		perror_reply(425, "Can't open passive connection");
1699 		return;
1700 	}
1701 
1702 	(void) seteuid((uid_t)0);
1703 
1704 	on = restricted_data_ports ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT;
1705 	if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
1706 			(char *)&on, sizeof(on)) < 0) {
1707 		goto pasv_error;
1708 	}
1709 
1710 	pasv_addr = ctrl_addr;
1711 	pasv_addr.sin_port = 0;
1712 	if (bind(pdata, (struct sockaddr *)&pasv_addr,
1713 		 sizeof(pasv_addr)) < 0)
1714 		goto pasv_error;
1715 
1716 	(void) seteuid((uid_t)pw->pw_uid);
1717 
1718 	len = sizeof(pasv_addr);
1719 	if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
1720 		goto pasv_error;
1721 	if (listen(pdata, 1) < 0)
1722 		goto pasv_error;
1723 	a = (char *) &pasv_addr.sin_addr;
1724 	p = (char *) &pasv_addr.sin_port;
1725 
1726 #define UC(b) (((int) b) & 0xff)
1727 
1728 	reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]),
1729 		UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
1730 	return;
1731 
1732 pasv_error:
1733 	(void) seteuid((uid_t)pw->pw_uid);
1734 	(void) close(pdata);
1735 	pdata = -1;
1736 	perror_reply(425, "Can't open passive connection");
1737 	return;
1738 }
1739 
1740 /*
1741  * Generate unique name for file with basename "local".
1742  * The file named "local" is already known to exist.
1743  * Generates failure reply on error.
1744  */
1745 static char *
1746 gunique(local)
1747 	char *local;
1748 {
1749 	static char new[MAXPATHLEN];
1750 	struct stat st;
1751 	int count;
1752 	char *cp;
1753 
1754 	cp = strrchr(local, '/');
1755 	if (cp)
1756 		*cp = '\0';
1757 	if (stat(cp ? local : ".", &st) < 0) {
1758 		perror_reply(553, cp ? local : ".");
1759 		return ((char *) 0);
1760 	}
1761 	if (cp)
1762 		*cp = '/';
1763 	(void) snprintf(new, sizeof(new), "%s", local);
1764 	cp = new + strlen(new);
1765 	*cp++ = '.';
1766 	for (count = 1; count < 100; count++) {
1767 		(void)sprintf(cp, "%d", count);
1768 		if (stat(new, &st) < 0)
1769 			return (new);
1770 	}
1771 	reply(452, "Unique file name cannot be created.");
1772 	return (NULL);
1773 }
1774 
1775 /*
1776  * Format and send reply containing system error number.
1777  */
1778 void
1779 perror_reply(code, string)
1780 	int code;
1781 	char *string;
1782 {
1783 
1784 	reply(code, "%s: %s.", string, strerror(errno));
1785 }
1786 
1787 static char *onefile[] = {
1788 	"",
1789 	0
1790 };
1791 
1792 void
1793 send_file_list(whichf)
1794 	char *whichf;
1795 {
1796 	struct stat st;
1797 	DIR *dirp = NULL;
1798 	struct dirent *dir;
1799 	FILE *dout = NULL;
1800 	char **dirlist, *dirname;
1801 	int simple = 0;
1802 	int freeglob = 0;
1803 	glob_t gl;
1804 
1805 	if (strpbrk(whichf, "~{[*?") != NULL) {
1806 		int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
1807 
1808 		memset(&gl, 0, sizeof(gl));
1809 		freeglob = 1;
1810 		if (glob(whichf, flags, 0, &gl)) {
1811 			reply(550, "not found");
1812 			goto out;
1813 		} else if (gl.gl_pathc == 0) {
1814 			errno = ENOENT;
1815 			perror_reply(550, whichf);
1816 			goto out;
1817 		}
1818 		dirlist = gl.gl_pathv;
1819 	} else {
1820 		onefile[0] = whichf;
1821 		dirlist = onefile;
1822 		simple = 1;
1823 	}
1824 
1825 	if (setjmp(urgcatch)) {
1826 		transflag = 0;
1827 		goto out;
1828 	}
1829 	while ((dirname = *dirlist++)) {
1830 		if (stat(dirname, &st) < 0) {
1831 			/*
1832 			 * If user typed "ls -l", etc, and the client
1833 			 * used NLST, do what the user meant.
1834 			 */
1835 			if (dirname[0] == '-' && *dirlist == NULL &&
1836 			    transflag == 0) {
1837 				retrieve("/bin/ls %s", dirname);
1838 				goto out;
1839 			}
1840 			perror_reply(550, whichf);
1841 			if (dout != NULL) {
1842 				(void) fclose(dout);
1843 				transflag = 0;
1844 				data = -1;
1845 				pdata = -1;
1846 			}
1847 			goto out;
1848 		}
1849 
1850 		if (S_ISREG(st.st_mode)) {
1851 			if (dout == NULL) {
1852 				dout = dataconn("file list", (off_t)-1, "w");
1853 				if (dout == NULL)
1854 					goto out;
1855 				transflag++;
1856 			}
1857 			fprintf(dout, "%s%s\n", dirname,
1858 				type == TYPE_A ? "\r" : "");
1859 			byte_count += strlen(dirname) + 1;
1860 			continue;
1861 		} else if (!S_ISDIR(st.st_mode))
1862 			continue;
1863 
1864 		if ((dirp = opendir(dirname)) == NULL)
1865 			continue;
1866 
1867 		while ((dir = readdir(dirp)) != NULL) {
1868 			char nbuf[MAXPATHLEN];
1869 
1870 			if (dir->d_name[0] == '.' && dir->d_namlen == 1)
1871 				continue;
1872 			if (dir->d_name[0] == '.' && dir->d_name[1] == '.' &&
1873 			    dir->d_namlen == 2)
1874 				continue;
1875 
1876 			sprintf(nbuf, "%s/%s", dirname, dir->d_name);
1877 
1878 			/*
1879 			 * We have to do a stat to insure it's
1880 			 * not a directory or special file.
1881 			 */
1882 			if (simple || (stat(nbuf, &st) == 0 &&
1883 			    S_ISREG(st.st_mode))) {
1884 				if (dout == NULL) {
1885 					dout = dataconn("file list", (off_t)-1,
1886 						"w");
1887 					if (dout == NULL)
1888 						goto out;
1889 					transflag++;
1890 				}
1891 				if (nbuf[0] == '.' && nbuf[1] == '/')
1892 					fprintf(dout, "%s%s\n", &nbuf[2],
1893 						type == TYPE_A ? "\r" : "");
1894 				else
1895 					fprintf(dout, "%s%s\n", nbuf,
1896 						type == TYPE_A ? "\r" : "");
1897 				byte_count += strlen(nbuf) + 1;
1898 			}
1899 		}
1900 		(void) closedir(dirp);
1901 	}
1902 
1903 	if (dout == NULL)
1904 		reply(550, "No files found.");
1905 	else if (ferror(dout) != 0)
1906 		perror_reply(550, "Data connection");
1907 	else
1908 		reply(226, "Transfer complete.");
1909 
1910 	transflag = 0;
1911 	if (dout != NULL)
1912 		(void) fclose(dout);
1913 	data = -1;
1914 	pdata = -1;
1915 out:
1916 	if (freeglob) {
1917 		freeglob = 0;
1918 		globfree(&gl);
1919 	}
1920 }
1921 
1922 void
1923 reapchild(signo)
1924 	int signo;
1925 {
1926 	while (wait3(NULL, WNOHANG, NULL) > 0);
1927 }
1928 
1929 #ifdef OLD_SETPROCTITLE
1930 /*
1931  * Clobber argv so ps will show what we're doing.  (Stolen from sendmail.)
1932  * Warning, since this is usually started from inetd.conf, it often doesn't
1933  * have much of an environment or arglist to overwrite.
1934  */
1935 void
1936 #if __STDC__
1937 setproctitle(const char *fmt, ...)
1938 #else
1939 setproctitle(fmt, va_alist)
1940 	char *fmt;
1941         va_dcl
1942 #endif
1943 {
1944 	int i;
1945 	va_list ap;
1946 	char *p, *bp, ch;
1947 	char buf[LINE_MAX];
1948 
1949 #if __STDC__
1950 	va_start(ap, fmt);
1951 #else
1952 	va_start(ap);
1953 #endif
1954 	(void)vsnprintf(buf, sizeof(buf), fmt, ap);
1955 
1956 	/* make ps print our process name */
1957 	p = Argv[0];
1958 	*p++ = '-';
1959 
1960 	i = strlen(buf);
1961 	if (i > LastArgv - p - 2) {
1962 		i = LastArgv - p - 2;
1963 		buf[i] = '\0';
1964 	}
1965 	bp = buf;
1966 	while (ch = *bp++)
1967 		if (ch != '\n' && ch != '\r')
1968 			*p++ = ch;
1969 	while (p < LastArgv)
1970 		*p++ = ' ';
1971 }
1972 #endif /* OLD_SETPROCTITLE */
1973 
1974 static void
1975 logxfer(name, size, start)
1976 	char *name;
1977 	long size;
1978 	long start;
1979 {
1980 	char buf[1024];
1981 	char path[MAXPATHLEN + 1];
1982 	long now;
1983 
1984 	if (statfd >= 0 && getwd(path) != NULL) {
1985 		time(&now);
1986 		snprintf(buf, sizeof(buf), "%.20s!%s!%s!%s/%s!%ld!%ld\n",
1987 			ctime(&now)+4, ident, remotehost,
1988 			path, name, size, now - start + (now == start));
1989 		write(statfd, buf, strlen(buf));
1990 	}
1991 }
1992