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