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