xref: /freebsd/crypto/heimdal/appl/ftp/ftpd/ftpd.c (revision 9a14aa017b21c292740c00ee098195cd46642730)
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 #define	FTP_NAMES
35 #include "ftpd_locl.h"
36 #ifdef KRB5
37 #include <krb5.h>
38 #endif
39 #include "getarg.h"
40 
41 RCSID("$Id: ftpd.c 21222 2007-06-20 10:11:14Z lha $");
42 
43 static char version[] = "Version 6.00";
44 
45 extern	off_t restart_point;
46 extern	char cbuf[];
47 
48 struct  sockaddr_storage ctrl_addr_ss;
49 struct  sockaddr *ctrl_addr = (struct sockaddr *)&ctrl_addr_ss;
50 
51 struct  sockaddr_storage data_source_ss;
52 struct  sockaddr *data_source = (struct sockaddr *)&data_source_ss;
53 
54 struct  sockaddr_storage data_dest_ss;
55 struct  sockaddr *data_dest = (struct sockaddr *)&data_dest_ss;
56 
57 struct  sockaddr_storage his_addr_ss;
58 struct  sockaddr *his_addr = (struct sockaddr *)&his_addr_ss;
59 
60 struct  sockaddr_storage pasv_addr_ss;
61 struct  sockaddr *pasv_addr = (struct sockaddr *)&pasv_addr_ss;
62 
63 int	data;
64 int	logged_in;
65 struct	passwd *pw;
66 int	debug = 0;
67 int	ftpd_timeout = 900;    /* timeout after 15 minutes of inactivity */
68 int	maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */
69 int	restricted_data_ports = 1;
70 int	logging;
71 int	guest;
72 int	dochroot;
73 int	type;
74 int	form;
75 int	stru;			/* avoid C keyword */
76 int	mode;
77 int	usedefault = 1;		/* for data transfers */
78 int	pdata = -1;		/* for passive mode */
79 int	allow_insecure_oob = 1;
80 static int transflag;
81 static int urgflag;
82 off_t	file_size;
83 off_t	byte_count;
84 #if !defined(CMASK) || CMASK == 0
85 #undef CMASK
86 #define CMASK 027
87 #endif
88 int	defumask = CMASK;		/* default umask value */
89 int	guest_umask = 0777;	/* Paranoia for anonymous users */
90 char	tmpline[10240];
91 char	hostname[MaxHostNameLen];
92 char	remotehost[MaxHostNameLen];
93 static char ttyline[20];
94 
95 #define AUTH_PLAIN	(1 << 0) /* allow sending passwords */
96 #define AUTH_OTP	(1 << 1) /* passwords are one-time */
97 #define AUTH_FTP	(1 << 2) /* allow anonymous login */
98 
99 static int auth_level = 0; /* Only allow kerberos login by default */
100 
101 /*
102  * Timeout intervals for retrying connections
103  * to hosts that don't accept PORT cmds.  This
104  * is a kludge, but given the problems with TCP...
105  */
106 #define	SWAITMAX	90	/* wait at most 90 seconds */
107 #define	SWAITINT	5	/* interval between retries */
108 
109 int	swaitmax = SWAITMAX;
110 int	swaitint = SWAITINT;
111 
112 #ifdef HAVE_SETPROCTITLE
113 char	proctitle[BUFSIZ];	/* initial part of title */
114 #endif /* HAVE_SETPROCTITLE */
115 
116 #define LOGCMD(cmd, file) \
117 	if (logging > 1) \
118 	    syslog(LOG_INFO,"%s %s%s", cmd, \
119 		*(file) == '/' ? "" : curdir(), file);
120 #define LOGCMD2(cmd, file1, file2) \
121 	 if (logging > 1) \
122 	    syslog(LOG_INFO,"%s %s%s %s%s", cmd, \
123 		*(file1) == '/' ? "" : curdir(), file1, \
124 		*(file2) == '/' ? "" : curdir(), file2);
125 #define LOGBYTES(cmd, file, cnt) \
126 	if (logging > 1) { \
127 		if (cnt == (off_t)-1) \
128 		    syslog(LOG_INFO,"%s %s%s", cmd, \
129 			*(file) == '/' ? "" : curdir(), file); \
130 		else \
131 		    syslog(LOG_INFO, "%s %s%s = %ld bytes", \
132 			cmd, (*(file) == '/') ? "" : curdir(), file, (long)cnt); \
133 	}
134 
135 static void	 ack (char *);
136 static void	 myoob (int);
137 static int	 handleoobcmd(void);
138 static int	 checkuser (char *, char *);
139 static int	 checkaccess (char *);
140 static FILE	*dataconn (const char *, off_t, const char *);
141 static void	 dolog (struct sockaddr *, int);
142 static void	 end_login (void);
143 static FILE	*getdatasock (const char *, int);
144 static char	*gunique (char *);
145 static RETSIGTYPE	 lostconn (int);
146 static int	 receive_data (FILE *, FILE *);
147 static void	 send_data (FILE *, FILE *);
148 static struct passwd * sgetpwnam (char *);
149 
150 static char *
151 curdir(void)
152 {
153 	static char path[MaxPathLen+1];	/* path + '/' + '\0' */
154 
155 	if (getcwd(path, sizeof(path)-1) == NULL)
156 		return ("");
157 	if (path[1] != '\0')		/* special case for root dir. */
158 		strlcat(path, "/", sizeof(path));
159 	/* For guest account, skip / since it's chrooted */
160 	return (guest ? path+1 : path);
161 }
162 
163 #ifndef LINE_MAX
164 #define LINE_MAX 1024
165 #endif
166 
167 static int
168 parse_auth_level(char *str)
169 {
170     char *p;
171     int ret = 0;
172     char *foo = NULL;
173 
174     for(p = strtok_r(str, ",", &foo);
175 	p;
176 	p = strtok_r(NULL, ",", &foo)) {
177 	if(strcmp(p, "user") == 0)
178 	    ;
179 #ifdef OTP
180 	else if(strcmp(p, "otp") == 0)
181 	    ret |= AUTH_PLAIN|AUTH_OTP;
182 #endif
183 	else if(strcmp(p, "ftp") == 0 ||
184 		strcmp(p, "safe") == 0)
185 	    ret |= AUTH_FTP;
186 	else if(strcmp(p, "plain") == 0)
187 	    ret |= AUTH_PLAIN;
188 	else if(strcmp(p, "none") == 0)
189 	    ret |= AUTH_PLAIN|AUTH_FTP;
190 	else
191 	    warnx("bad value for -a: `%s'", p);
192     }
193     return ret;
194 }
195 
196 /*
197  * Print usage and die.
198  */
199 
200 static int interactive_flag;
201 static char *guest_umask_string;
202 static char *port_string;
203 static char *umask_string;
204 static char *auth_string;
205 
206 int use_builtin_ls = -1;
207 
208 static int help_flag;
209 static int version_flag;
210 
211 static const char *good_chars = "+-=_,.";
212 
213 struct getargs args[] = {
214     { NULL, 'a', arg_string, &auth_string, "required authentication" },
215     { NULL, 'i', arg_flag, &interactive_flag, "don't assume stdin is a socket" },
216     { NULL, 'p', arg_string, &port_string, "what port to listen to" },
217     { NULL, 'g', arg_string, &guest_umask_string, "umask for guest logins" },
218     { NULL, 'l', arg_counter, &logging, "log more stuff", "" },
219     { NULL, 't', arg_integer, &ftpd_timeout, "initial timeout" },
220     { NULL, 'T', arg_integer, &maxtimeout, "max timeout" },
221     { NULL, 'u', arg_string, &umask_string, "umask for user logins" },
222     { NULL, 'U', arg_negative_flag, &restricted_data_ports, "don't use high data ports" },
223     { NULL, 'd', arg_flag, &debug, "enable debugging" },
224     { NULL, 'v', arg_flag, &debug, "enable debugging" },
225     { "builtin-ls", 'B', arg_flag, &use_builtin_ls, "use built-in ls to list files" },
226     { "good-chars", 0, arg_string, &good_chars, "allowed anonymous upload filename chars" },
227     { "insecure-oob", 'I', arg_negative_flag, &allow_insecure_oob, "don't allow insecure OOB ABOR/STAT" },
228 #ifdef KRB5
229     { "gss-bindings", 0,  arg_flag, &ftp_do_gss_bindings, "Require GSS-API bindings", NULL},
230 #endif
231     { "version", 0, arg_flag, &version_flag },
232     { "help", 'h', arg_flag, &help_flag }
233 };
234 
235 static int num_args = sizeof(args) / sizeof(args[0]);
236 
237 static void
238 usage (int code)
239 {
240     arg_printusage(args, num_args, NULL, "");
241     exit (code);
242 }
243 
244 /* output contents of a file */
245 static int
246 show_file(const char *file, int code)
247 {
248     FILE *f;
249     char buf[128];
250 
251     f = fopen(file, "r");
252     if(f == NULL)
253 	return -1;
254     while(fgets(buf, sizeof(buf), f)){
255 	buf[strcspn(buf, "\r\n")] = '\0';
256 	lreply(code, "%s", buf);
257     }
258     fclose(f);
259     return 0;
260 }
261 
262 int
263 main(int argc, char **argv)
264 {
265     socklen_t his_addr_len, ctrl_addr_len;
266     int on = 1;
267     int port;
268     struct servent *sp;
269 
270     int optind = 0;
271 
272     setprogname (argv[0]);
273 
274     /* detach from any tickets and tokens */
275     {
276 #ifdef KRB4
277 	char tkfile[1024];
278 	snprintf(tkfile, sizeof(tkfile),
279 		 "/tmp/ftp_%u", (unsigned)getpid());
280 	krb_set_tkt_string(tkfile);
281 #endif
282     }
283 
284     if(getarg(args, num_args, argc, argv, &optind))
285 	usage(1);
286 
287     if(help_flag)
288 	usage(0);
289 
290     if(version_flag) {
291 	print_version(NULL);
292 	exit(0);
293     }
294 
295     if(auth_string)
296 	auth_level = parse_auth_level(auth_string);
297     {
298 	char *p;
299 	long val = 0;
300 
301 	if(guest_umask_string) {
302 	    val = strtol(guest_umask_string, &p, 8);
303 	    if (*p != '\0' || val < 0)
304 		warnx("bad value for -g");
305 	    else
306 		guest_umask = val;
307 	}
308 	if(umask_string) {
309 	    val = strtol(umask_string, &p, 8);
310 	    if (*p != '\0' || val < 0)
311 		warnx("bad value for -u");
312 	    else
313 		defumask = val;
314 	}
315     }
316     sp = getservbyname("ftp", "tcp");
317     if(sp)
318 	port = sp->s_port;
319     else
320 	port = htons(21);
321     if(port_string) {
322 	sp = getservbyname(port_string, "tcp");
323 	if(sp)
324 	    port = sp->s_port;
325 	else
326 	    if(isdigit((unsigned char)port_string[0]))
327 		port = htons(atoi(port_string));
328 	    else
329 		warnx("bad value for -p");
330     }
331 
332     if (maxtimeout < ftpd_timeout)
333 	maxtimeout = ftpd_timeout;
334 
335 #if 0
336     if (ftpd_timeout > maxtimeout)
337 	ftpd_timeout = maxtimeout;
338 #endif
339 
340     if(interactive_flag)
341 	mini_inetd (port);
342 
343     /*
344      * LOG_NDELAY sets up the logging connection immediately,
345      * necessary for anonymous ftp's that chroot and can't do it later.
346      */
347     openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
348     his_addr_len = sizeof(his_addr_ss);
349     if (getpeername(STDIN_FILENO, his_addr, &his_addr_len) < 0) {
350 	syslog(LOG_ERR, "getpeername (%s): %m",argv[0]);
351 	exit(1);
352     }
353     ctrl_addr_len = sizeof(ctrl_addr_ss);
354     if (getsockname(STDIN_FILENO, ctrl_addr, &ctrl_addr_len) < 0) {
355 	syslog(LOG_ERR, "getsockname (%s): %m",argv[0]);
356 	exit(1);
357     }
358 #if defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
359     {
360 	int tos = IPTOS_LOWDELAY;
361 
362 	if (setsockopt(STDIN_FILENO, IPPROTO_IP, IP_TOS,
363 		       (void *)&tos, sizeof(int)) < 0)
364 	    syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
365     }
366 #endif
367     data_source->sa_family = ctrl_addr->sa_family;
368     socket_set_port (data_source,
369 		     htons(ntohs(socket_get_port(ctrl_addr)) - 1));
370 
371     /* set this here so it can be put in wtmp */
372     snprintf(ttyline, sizeof(ttyline), "ftp%u", (unsigned)getpid());
373 
374 
375     /*	freopen(_PATH_DEVNULL, "w", stderr); */
376     signal(SIGPIPE, lostconn);
377     signal(SIGCHLD, SIG_IGN);
378 #ifdef SIGURG
379     if (signal(SIGURG, myoob) == SIG_ERR)
380 	syslog(LOG_ERR, "signal: %m");
381 #endif
382 
383     /* Try to handle urgent data inline */
384 #if defined(SO_OOBINLINE) && defined(HAVE_SETSOCKOPT)
385     if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (void *)&on,
386 		   sizeof(on)) < 0)
387 	syslog(LOG_ERR, "setsockopt: %m");
388 #endif
389 
390 #ifdef	F_SETOWN
391     if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1)
392 	syslog(LOG_ERR, "fcntl F_SETOWN: %m");
393 #endif
394     dolog(his_addr, his_addr_len);
395     /*
396      * Set up default state
397      */
398     data = -1;
399     type = TYPE_A;
400     form = FORM_N;
401     stru = STRU_F;
402     mode = MODE_S;
403     tmpline[0] = '\0';
404 
405     /* If logins are disabled, print out the message. */
406     if(show_file(_PATH_NOLOGIN, 530) == 0) {
407 	reply(530, "System not available.");
408 	exit(0);
409     }
410     show_file(_PATH_FTPWELCOME, 220);
411     /* reply(220,) must follow */
412     gethostname(hostname, sizeof(hostname));
413 
414     reply(220, "%s FTP server (%s"
415 #ifdef KRB5
416 	  "+%s"
417 #endif
418 #ifdef KRB4
419 	  "+%s"
420 #endif
421 	  ") ready.", hostname, version
422 #ifdef KRB5
423 	  ,heimdal_version
424 #endif
425 #ifdef KRB4
426 	  ,krb4_version
427 #endif
428 	  );
429 
430     for (;;)
431 	yyparse();
432     /* NOTREACHED */
433 }
434 
435 static RETSIGTYPE
436 lostconn(int signo)
437 {
438 
439 	if (debug)
440 		syslog(LOG_DEBUG, "lost connection");
441 	dologout(-1);
442 }
443 
444 /*
445  * Helper function for sgetpwnam().
446  */
447 static char *
448 sgetsave(char *s)
449 {
450 	char *new = strdup(s);
451 
452 	if (new == NULL) {
453 		perror_reply(421, "Local resource failure: malloc");
454 		dologout(1);
455 		/* NOTREACHED */
456 	}
457 	return new;
458 }
459 
460 /*
461  * Save the result of a getpwnam.  Used for USER command, since
462  * the data returned must not be clobbered by any other command
463  * (e.g., globbing).
464  */
465 static struct passwd *
466 sgetpwnam(char *name)
467 {
468 	static struct passwd save;
469 	struct passwd *p;
470 
471 	if ((p = k_getpwnam(name)) == NULL)
472 		return (p);
473 	if (save.pw_name) {
474 		free(save.pw_name);
475 		free(save.pw_passwd);
476 		free(save.pw_gecos);
477 		free(save.pw_dir);
478 		free(save.pw_shell);
479 	}
480 	save = *p;
481 	save.pw_name = sgetsave(p->pw_name);
482 	save.pw_passwd = sgetsave(p->pw_passwd);
483 	save.pw_gecos = sgetsave(p->pw_gecos);
484 	save.pw_dir = sgetsave(p->pw_dir);
485 	save.pw_shell = sgetsave(p->pw_shell);
486 	return (&save);
487 }
488 
489 static int login_attempts;	/* number of failed login attempts */
490 static int askpasswd;		/* had user command, ask for passwd */
491 static char curname[10];	/* current USER name */
492 #ifdef OTP
493 OtpContext otp_ctx;
494 #endif
495 
496 /*
497  * USER command.
498  * Sets global passwd pointer pw if named account exists and is acceptable;
499  * sets askpasswd if a PASS command is expected.  If logged in previously,
500  * need to reset state.  If name is "ftp" or "anonymous", the name is not in
501  * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return.
502  * If account doesn't exist, ask for passwd anyway.  Otherwise, check user
503  * requesting login privileges.  Disallow anyone who does not have a standard
504  * shell as returned by getusershell().  Disallow anyone mentioned in the file
505  * _PATH_FTPUSERS to allow people such as root and uucp to be avoided.
506  */
507 void
508 user(char *name)
509 {
510 	char *cp, *shell;
511 
512 	if(auth_level == 0 && !sec_complete){
513 	    reply(530, "No login allowed without authorization.");
514 	    return;
515 	}
516 
517 	if (logged_in) {
518 		if (guest) {
519 			reply(530, "Can't change user from guest login.");
520 			return;
521 		} else if (dochroot) {
522 			reply(530, "Can't change user from chroot user.");
523 			return;
524 		}
525 		end_login();
526 	}
527 
528 	guest = 0;
529 	if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) {
530 	    if ((auth_level & AUTH_FTP) == 0 ||
531 		checkaccess("ftp") ||
532 		checkaccess("anonymous"))
533 		reply(530, "User %s access denied.", name);
534 	    else if ((pw = sgetpwnam("ftp")) != NULL) {
535 		guest = 1;
536 		defumask = guest_umask;	/* paranoia for incoming */
537 		askpasswd = 1;
538 		reply(331, "Guest login ok, type your name as password.");
539 	    } else
540 		reply(530, "User %s unknown.", name);
541 	    if (!askpasswd && logging) {
542 		char data_addr[256];
543 
544 		if (inet_ntop (his_addr->sa_family,
545 			       socket_get_address(his_addr),
546 			       data_addr, sizeof(data_addr)) == NULL)
547 			strlcpy (data_addr, "unknown address",
548 					 sizeof(data_addr));
549 
550 		syslog(LOG_NOTICE,
551 		       "ANONYMOUS FTP LOGIN REFUSED FROM %s(%s)",
552 		       remotehost, data_addr);
553 	    }
554 	    return;
555 	}
556 	if((auth_level & AUTH_PLAIN) == 0 && !sec_complete){
557 	    reply(530, "Only authorized and anonymous login allowed.");
558 	    return;
559 	}
560 	if ((pw = sgetpwnam(name))) {
561 		if ((shell = pw->pw_shell) == NULL || *shell == 0)
562 			shell = _PATH_BSHELL;
563 		while ((cp = getusershell()) != NULL)
564 			if (strcmp(cp, shell) == 0)
565 				break;
566 		endusershell();
567 
568 		if (cp == NULL || checkaccess(name)) {
569 			reply(530, "User %s access denied.", name);
570 			if (logging) {
571 				char data_addr[256];
572 
573 				if (inet_ntop (his_addr->sa_family,
574 					       socket_get_address(his_addr),
575 					       data_addr,
576 					       sizeof(data_addr)) == NULL)
577 					strlcpy (data_addr,
578 							 "unknown address",
579 							 sizeof(data_addr));
580 
581 				syslog(LOG_NOTICE,
582 				       "FTP LOGIN REFUSED FROM %s(%s), %s",
583 				       remotehost,
584 				       data_addr,
585 				       name);
586 			}
587 			pw = (struct passwd *) NULL;
588 			return;
589 		}
590 	}
591 	if (logging)
592 	    strlcpy(curname, name, sizeof(curname));
593 	if(sec_complete) {
594 	    if(sec_userok(name) == 0) {
595 		do_login(232, name);
596 		sec_session(name);
597 	    } else
598 		reply(530, "User %s access denied.", name);
599 	} else {
600 #ifdef OTP
601 		char ss[256];
602 
603 		if (otp_challenge(&otp_ctx, name, ss, sizeof(ss)) == 0) {
604 			reply(331, "Password %s for %s required.",
605 			      ss, name);
606 			askpasswd = 1;
607 		} else
608 #endif
609 		if ((auth_level & AUTH_OTP) == 0) {
610 		    reply(331, "Password required for %s.", name);
611 		    askpasswd = 1;
612 		} else {
613 #ifdef OTP
614 		    char *s;
615 
616 		    if ((s = otp_error (&otp_ctx)) != NULL)
617 			lreply(530, "OTP: %s", s);
618 #endif
619 		    reply(530,
620 			  "Only authorized, anonymous"
621 #ifdef OTP
622 			  " and OTP "
623 #endif
624 			  "login allowed.");
625 		}
626 
627 	}
628 	/*
629 	 * Delay before reading passwd after first failed
630 	 * attempt to slow down passwd-guessing programs.
631 	 */
632 	if (login_attempts)
633 		sleep(login_attempts);
634 }
635 
636 /*
637  * Check if a user is in the file "fname"
638  */
639 static int
640 checkuser(char *fname, char *name)
641 {
642 	FILE *fd;
643 	int found = 0;
644 	char *p, line[BUFSIZ];
645 
646 	if ((fd = fopen(fname, "r")) != NULL) {
647 		while (fgets(line, sizeof(line), fd) != NULL)
648 			if ((p = strchr(line, '\n')) != NULL) {
649 				*p = '\0';
650 				if (line[0] == '#')
651 					continue;
652 				if (strcmp(line, name) == 0) {
653 					found = 1;
654 					break;
655 				}
656 			}
657 		fclose(fd);
658 	}
659 	return (found);
660 }
661 
662 
663 /*
664  * Determine whether a user has access, based on information in
665  * _PATH_FTPUSERS. The users are listed one per line, with `allow'
666  * or `deny' after the username. If anything other than `allow', or
667  * just nothing, is given after the username, `deny' is assumed.
668  *
669  * If the user is not found in the file, but the pseudo-user `*' is,
670  * the permission is taken from that line.
671  *
672  * This preserves the old semantics where if a user was listed in the
673  * file he was denied, otherwise he was allowed.
674  *
675  * Return 1 if the user is denied, or 0 if he is allowed.  */
676 
677 static int
678 match(const char *pattern, const char *string)
679 {
680     return fnmatch(pattern, string, FNM_NOESCAPE);
681 }
682 
683 static int
684 checkaccess(char *name)
685 {
686 #define ALLOWED		0
687 #define	NOT_ALLOWED	1
688     FILE *fd;
689     int allowed = ALLOWED;
690     char *user, *perm, line[BUFSIZ];
691     char *foo;
692 
693     fd = fopen(_PATH_FTPUSERS, "r");
694 
695     if(fd == NULL)
696 	return allowed;
697 
698     while (fgets(line, sizeof(line), fd) != NULL)  {
699 	foo = NULL;
700 	user = strtok_r(line, " \t\n", &foo);
701 	if (user == NULL || user[0] == '#')
702 	    continue;
703 	perm = strtok_r(NULL, " \t\n", &foo);
704 	if (match(user, name) == 0){
705 	    if(perm && strcmp(perm, "allow") == 0)
706 		allowed = ALLOWED;
707 	    else
708 		allowed = NOT_ALLOWED;
709 	    break;
710 	}
711     }
712     fclose(fd);
713     return allowed;
714 }
715 #undef	ALLOWED
716 #undef	NOT_ALLOWED
717 
718 
719 int do_login(int code, char *passwd)
720 {
721     login_attempts = 0;		/* this time successful */
722     if (setegid((gid_t)pw->pw_gid) < 0) {
723 	reply(550, "Can't set gid.");
724 	return -1;
725     }
726     initgroups(pw->pw_name, pw->pw_gid);
727 #if defined(KRB4) || defined(KRB5)
728     if(k_hasafs())
729 	k_setpag();
730 #endif
731 
732     /* open wtmp before chroot */
733     ftpd_logwtmp(ttyline, pw->pw_name, remotehost);
734     logged_in = 1;
735 
736     dochroot = checkuser(_PATH_FTPCHROOT, pw->pw_name);
737     if (guest) {
738 	/*
739 	 * We MUST do a chdir() after the chroot. Otherwise
740 	 * the old current directory will be accessible as "."
741 	 * outside the new root!
742 	 */
743 	if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
744 	    reply(550, "Can't set guest privileges.");
745 	    return -1;
746 	}
747     } else if (dochroot) {
748 	if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
749 	    reply(550, "Can't change root.");
750 	    return -1;
751 	}
752     } else if (chdir(pw->pw_dir) < 0) {
753 	if (chdir("/") < 0) {
754 	    reply(530, "User %s: can't change directory to %s.",
755 		  pw->pw_name, pw->pw_dir);
756 	    return -1;
757 	} else
758 	    lreply(code, "No directory! Logging in with home=/");
759     }
760     if (seteuid((uid_t)pw->pw_uid) < 0) {
761 	reply(550, "Can't set uid.");
762 	return -1;
763     }
764 
765     if(use_builtin_ls == -1) {
766 	struct stat st;
767 	/* if /bin/ls exist and is a regular file, use it, otherwise
768            use built-in ls */
769 	if(stat("/bin/ls", &st) == 0 &&
770 	   S_ISREG(st.st_mode))
771 	    use_builtin_ls = 0;
772 	else
773 	    use_builtin_ls = 1;
774     }
775 
776     /*
777      * Display a login message, if it exists.
778      * N.B. reply(code,) must follow the message.
779      */
780     show_file(_PATH_FTPLOGINMESG, code);
781     if(show_file(_PATH_ISSUE_NET, code) != 0)
782 	show_file(_PATH_ISSUE, code);
783     if (guest) {
784 	reply(code, "Guest login ok, access restrictions apply.");
785 #ifdef HAVE_SETPROCTITLE
786 	snprintf (proctitle, sizeof(proctitle),
787 		  "%s: anonymous/%s",
788 		  remotehost,
789 		  passwd);
790 	setproctitle("%s", proctitle);
791 #endif /* HAVE_SETPROCTITLE */
792 	if (logging) {
793 	    char data_addr[256];
794 
795 	    if (inet_ntop (his_addr->sa_family,
796 			   socket_get_address(his_addr),
797 			   data_addr, sizeof(data_addr)) == NULL)
798 		strlcpy (data_addr, "unknown address",
799 				 sizeof(data_addr));
800 
801 	    syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s(%s), %s",
802 		   remotehost,
803 		   data_addr,
804 		   passwd);
805 	}
806     } else {
807 	reply(code, "User %s logged in.", pw->pw_name);
808 #ifdef HAVE_SETPROCTITLE
809 	snprintf(proctitle, sizeof(proctitle), "%s: %s", remotehost, pw->pw_name);
810 	setproctitle("%s", proctitle);
811 #endif /* HAVE_SETPROCTITLE */
812 	if (logging) {
813 	    char data_addr[256];
814 
815 	    if (inet_ntop (his_addr->sa_family,
816 			   socket_get_address(his_addr),
817 			   data_addr, sizeof(data_addr)) == NULL)
818 		strlcpy (data_addr, "unknown address",
819 				 sizeof(data_addr));
820 
821 	    syslog(LOG_INFO, "FTP LOGIN FROM %s(%s) as %s",
822 		   remotehost,
823 		   data_addr,
824 		   pw->pw_name);
825 	}
826     }
827     umask(defumask);
828     return 0;
829 }
830 
831 /*
832  * Terminate login as previous user, if any, resetting state;
833  * used when USER command is given or login fails.
834  */
835 static void
836 end_login(void)
837 {
838 
839 	if (seteuid((uid_t)0) < 0)
840 		fatal("Failed to seteuid");
841 	if (logged_in)
842 		ftpd_logwtmp(ttyline, "", "");
843 	pw = NULL;
844 	logged_in = 0;
845 	guest = 0;
846 	dochroot = 0;
847 }
848 
849 #ifdef KRB5
850 static int
851 krb5_verify(struct passwd *pwd, char *passwd)
852 {
853    krb5_context context;
854    krb5_ccache  id;
855    krb5_principal princ;
856    krb5_error_code ret;
857 
858    ret = krb5_init_context(&context);
859    if(ret)
860         return ret;
861 
862   ret = krb5_parse_name(context, pwd->pw_name, &princ);
863   if(ret){
864         krb5_free_context(context);
865         return ret;
866   }
867   ret = krb5_cc_gen_new(context, &krb5_mcc_ops, &id);
868   if(ret){
869         krb5_free_principal(context, princ);
870         krb5_free_context(context);
871         return ret;
872   }
873   ret = krb5_verify_user(context,
874                          princ,
875                          id,
876                          passwd,
877                          1,
878                          NULL);
879   krb5_free_principal(context, princ);
880   if (k_hasafs()) {
881       krb5_afslog_uid_home(context, id,NULL, NULL,pwd->pw_uid, pwd->pw_dir);
882   }
883   krb5_cc_destroy(context, id);
884   krb5_free_context (context);
885   if(ret)
886       return ret;
887   return 0;
888 }
889 #endif /* KRB5 */
890 
891 void
892 pass(char *passwd)
893 {
894 	int rval;
895 
896 	/* some clients insists on sending a password */
897 	if (logged_in && askpasswd == 0){
898 	    reply(230, "Password not necessary");
899 	    return;
900 	}
901 
902 	if (logged_in || askpasswd == 0) {
903 		reply(503, "Login with USER first.");
904 		return;
905 	}
906 	askpasswd = 0;
907 	rval = 1;
908 	if (!guest) {		/* "ftp" is only account allowed no password */
909 		if (pw == NULL)
910 			rval = 1;	/* failure below */
911 #ifdef OTP
912 		else if (otp_verify_user (&otp_ctx, passwd) == 0) {
913 		    rval = 0;
914 		}
915 #endif
916 		else if((auth_level & AUTH_OTP) == 0) {
917 #ifdef KRB5
918 		    rval = krb5_verify(pw, passwd);
919 #endif
920 #ifdef KRB4
921 		    if (rval) {
922 			char realm[REALM_SZ];
923 			if((rval = krb_get_lrealm(realm, 1)) == KSUCCESS)
924 			    rval = krb_verify_user(pw->pw_name,
925 						   "", realm,
926 						   passwd,
927 						   KRB_VERIFY_SECURE, NULL);
928 			if (rval == KSUCCESS ) {
929 			    chown (tkt_string(), pw->pw_uid, pw->pw_gid);
930 			    if(k_hasafs())
931 				krb_afslog(0, 0);
932 			}
933 		    }
934 #endif
935 		    if (rval)
936 			rval = unix_verify_user(pw->pw_name, passwd);
937 		} else {
938 #ifdef OTP
939 		    char *s;
940 		    if ((s = otp_error(&otp_ctx)) != NULL)
941 			lreply(530, "OTP: %s", s);
942 #endif
943 		}
944 		memset (passwd, 0, strlen(passwd));
945 
946 		/*
947 		 * If rval == 1, the user failed the authentication
948 		 * check above.  If rval == 0, either Kerberos or
949 		 * local authentication succeeded.
950 		 */
951 		if (rval) {
952 			char data_addr[256];
953 
954 			if (inet_ntop (his_addr->sa_family,
955 				       socket_get_address(his_addr),
956 				       data_addr, sizeof(data_addr)) == NULL)
957 				strlcpy (data_addr, "unknown address",
958 						 sizeof(data_addr));
959 
960 			reply(530, "Login incorrect.");
961 			if (logging)
962 				syslog(LOG_NOTICE,
963 				    "FTP LOGIN FAILED FROM %s(%s), %s",
964 				       remotehost,
965 				       data_addr,
966 				       curname);
967 			pw = NULL;
968 			if (login_attempts++ >= 5) {
969 				syslog(LOG_NOTICE,
970 				       "repeated login failures from %s(%s)",
971 				       remotehost,
972 				       data_addr);
973 				exit(0);
974 			}
975 			return;
976 		}
977 	}
978 	if(!do_login(230, passwd))
979 	  return;
980 
981 	/* Forget all about it... */
982 	end_login();
983 }
984 
985 void
986 retrieve(const char *cmd, char *name)
987 {
988 	FILE *fin = NULL, *dout;
989 	struct stat st;
990 	int (*closefunc) (FILE *);
991 	char line[BUFSIZ];
992 
993 
994 	if (cmd == 0) {
995 		fin = fopen(name, "r");
996 		closefunc = fclose;
997 		st.st_size = 0;
998 		if(fin == NULL){
999 		    int save_errno = errno;
1000 		    struct cmds {
1001 			const char *ext;
1002 			const char *cmd;
1003 		        const char *rev_cmd;
1004 		    } cmds[] = {
1005 			{".tar", "/bin/gtar cPf - %s", NULL},
1006 			{".tar.gz", "/bin/gtar zcPf - %s", NULL},
1007 			{".tar.Z", "/bin/gtar ZcPf - %s", NULL},
1008 			{".gz", "/bin/gzip -c -- %s", "/bin/gzip -c -d -- %s"},
1009 			{".Z", "/bin/compress -c -- %s", "/bin/uncompress -c -- %s"},
1010 			{NULL, NULL}
1011 		    };
1012 		    struct cmds *p;
1013 		    for(p = cmds; p->ext; p++){
1014 			char *tail = name + strlen(name) - strlen(p->ext);
1015 			char c = *tail;
1016 
1017 			if(strcmp(tail, p->ext) == 0 &&
1018 			   (*tail  = 0) == 0 &&
1019 			   access(name, R_OK) == 0){
1020 			    snprintf (line, sizeof(line), p->cmd, name);
1021 			    *tail  = c;
1022 			    break;
1023 			}
1024 			*tail = c;
1025 			if (p->rev_cmd != NULL) {
1026 			    char *ext;
1027 			    int ret;
1028 
1029 			    ret = asprintf(&ext, "%s%s", name, p->ext);
1030 			    if (ret != -1) {
1031   			        if (access(ext, R_OK) == 0) {
1032 				    snprintf (line, sizeof(line),
1033 					      p->rev_cmd, ext);
1034 				    free(ext);
1035 				    break;
1036 				}
1037 			        free(ext);
1038 			    }
1039 			}
1040 
1041 		    }
1042 		    if(p->ext){
1043 			fin = ftpd_popen(line, "r", 0, 0);
1044 			closefunc = ftpd_pclose;
1045 			st.st_size = -1;
1046 			cmd = line;
1047 		    } else
1048 			errno = save_errno;
1049 		}
1050 	} else {
1051 		snprintf(line, sizeof(line), cmd, name);
1052 		name = line;
1053 		fin = ftpd_popen(line, "r", 1, 0);
1054 		closefunc = ftpd_pclose;
1055 		st.st_size = -1;
1056 	}
1057 	if (fin == NULL) {
1058 		if (errno != 0) {
1059 			perror_reply(550, name);
1060 			if (cmd == 0) {
1061 				LOGCMD("get", name);
1062 			}
1063 		}
1064 		return;
1065 	}
1066 	byte_count = -1;
1067 	if (cmd == 0){
1068 	    if(fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode)) {
1069 		reply(550, "%s: not a plain file.", name);
1070 		goto done;
1071 	    }
1072 	}
1073 	if (restart_point) {
1074 		if (type == TYPE_A) {
1075 			off_t i, n;
1076 			int c;
1077 
1078 			n = restart_point;
1079 			i = 0;
1080 			while (i++ < n) {
1081 				if ((c=getc(fin)) == EOF) {
1082 					perror_reply(550, name);
1083 					goto done;
1084 				}
1085 				if (c == '\n')
1086 					i++;
1087 			}
1088 		} else if (lseek(fileno(fin), restart_point, SEEK_SET) < 0) {
1089 			perror_reply(550, name);
1090 			goto done;
1091 		}
1092 	}
1093 	dout = dataconn(name, st.st_size, "w");
1094 	if (dout == NULL)
1095 		goto done;
1096 	set_buffer_size(fileno(dout), 0);
1097 	send_data(fin, dout);
1098 	fclose(dout);
1099 	data = -1;
1100 	pdata = -1;
1101 done:
1102 	if (cmd == 0)
1103 		LOGBYTES("get", name, byte_count);
1104 	(*closefunc)(fin);
1105 }
1106 
1107 /* filename sanity check */
1108 
1109 int
1110 filename_check(char *filename)
1111 {
1112     char *p;
1113 
1114     p = strrchr(filename, '/');
1115     if(p)
1116 	filename = p + 1;
1117 
1118     p = filename;
1119 
1120     if(isalnum((unsigned char)*p)){
1121 	p++;
1122 	while(*p && (isalnum((unsigned char)*p) || strchr(good_chars, (unsigned char)*p)))
1123 	    p++;
1124 	if(*p == '\0')
1125 	    return 0;
1126     }
1127     lreply(553, "\"%s\" is not an acceptable filename.", filename);
1128     lreply(553, "The filename must start with an alphanumeric "
1129 	   "character and must only");
1130     reply(553, "consist of alphanumeric characters or any of the following: %s",
1131 	  good_chars);
1132     return 1;
1133 }
1134 
1135 void
1136 do_store(char *name, char *mode, int unique)
1137 {
1138 	FILE *fout, *din;
1139 	struct stat st;
1140 	int (*closefunc) (FILE *);
1141 
1142 	if(guest && filename_check(name))
1143 	    return;
1144 	if (unique && stat(name, &st) == 0 &&
1145 	    (name = gunique(name)) == NULL) {
1146 		LOGCMD(*mode == 'w' ? "put" : "append", name);
1147 		return;
1148 	}
1149 
1150 	if (restart_point)
1151 		mode = "r+";
1152 	fout = fopen(name, mode);
1153 	closefunc = fclose;
1154 	if (fout == NULL) {
1155 		perror_reply(553, name);
1156 		LOGCMD(*mode == 'w' ? "put" : "append", name);
1157 		return;
1158 	}
1159 	byte_count = -1;
1160 	if (restart_point) {
1161 		if (type == TYPE_A) {
1162 			off_t i, n;
1163 			int c;
1164 
1165 			n = restart_point;
1166 			i = 0;
1167 			while (i++ < n) {
1168 				if ((c=getc(fout)) == EOF) {
1169 					perror_reply(550, name);
1170 					goto done;
1171 				}
1172 				if (c == '\n')
1173 					i++;
1174 			}
1175 			/*
1176 			 * We must do this seek to "current" position
1177 			 * because we are changing from reading to
1178 			 * writing.
1179 			 */
1180 			if (fseek(fout, 0L, SEEK_CUR) < 0) {
1181 				perror_reply(550, name);
1182 				goto done;
1183 			}
1184 		} else if (lseek(fileno(fout), restart_point, SEEK_SET) < 0) {
1185 			perror_reply(550, name);
1186 			goto done;
1187 		}
1188 	}
1189 	din = dataconn(name, (off_t)-1, "r");
1190 	if (din == NULL)
1191 		goto done;
1192 	set_buffer_size(fileno(din), 1);
1193 	if (receive_data(din, fout) == 0) {
1194 	    if((*closefunc)(fout) < 0)
1195 		perror_reply(552, name);
1196 	    else {
1197 		if (unique)
1198 			reply(226, "Transfer complete (unique file name:%s).",
1199 			    name);
1200 		else
1201 			reply(226, "Transfer complete.");
1202 	    }
1203 	} else
1204 	    (*closefunc)(fout);
1205 	fclose(din);
1206 	data = -1;
1207 	pdata = -1;
1208 done:
1209 	LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count);
1210 }
1211 
1212 static FILE *
1213 getdatasock(const char *mode, int domain)
1214 {
1215 	int s, t, tries;
1216 
1217 	if (data >= 0)
1218 		return (fdopen(data, mode));
1219 	if (seteuid(0) < 0)
1220 		fatal("Failed to seteuid");
1221 	s = socket(domain, SOCK_STREAM, 0);
1222 	if (s < 0)
1223 		goto bad;
1224 	socket_set_reuseaddr (s, 1);
1225 	/* anchor socket to avoid multi-homing problems */
1226 	socket_set_address_and_port (data_source,
1227 				     socket_get_address (ctrl_addr),
1228 				     socket_get_port (data_source));
1229 
1230 	for (tries = 1; ; tries++) {
1231 		if (bind(s, data_source,
1232 			 socket_sockaddr_size (data_source)) >= 0)
1233 			break;
1234 		if (errno != EADDRINUSE || tries > 10)
1235 			goto bad;
1236 		sleep(tries);
1237 	}
1238 	if (seteuid(pw->pw_uid) < 0)
1239 		fatal("Failed to seteuid");
1240 #ifdef IPTOS_THROUGHPUT
1241 	socket_set_tos (s, IPTOS_THROUGHPUT);
1242 #endif
1243 	return (fdopen(s, mode));
1244 bad:
1245 	/* Return the real value of errno (close may change it) */
1246 	t = errno;
1247 	if (seteuid((uid_t)pw->pw_uid) < 0)
1248 		fatal("Failed to seteuid");
1249 	close(s);
1250 	errno = t;
1251 	return (NULL);
1252 }
1253 
1254 static int
1255 accept_with_timeout(int socket,
1256 		    struct sockaddr *address,
1257 		    socklen_t *address_len,
1258 		    struct timeval *timeout)
1259 {
1260     int ret;
1261     fd_set rfd;
1262     FD_ZERO(&rfd);
1263     FD_SET(socket, &rfd);
1264     ret = select(socket + 1, &rfd, NULL, NULL, timeout);
1265     if(ret < 0)
1266 	return ret;
1267     if(ret == 0) {
1268 	errno = ETIMEDOUT;
1269 	return -1;
1270     }
1271     return accept(socket, address, address_len);
1272 }
1273 
1274 static FILE *
1275 dataconn(const char *name, off_t size, const char *mode)
1276 {
1277 	char sizebuf[32];
1278 	FILE *file;
1279 	int domain, retry = 0;
1280 
1281 	file_size = size;
1282 	byte_count = 0;
1283 	if (size >= 0)
1284 	    snprintf(sizebuf, sizeof(sizebuf), " (%ld bytes)", (long)size);
1285 	else
1286 	    *sizebuf = '\0';
1287 	if (pdata >= 0) {
1288 		struct sockaddr_storage from_ss;
1289 		struct sockaddr *from = (struct sockaddr *)&from_ss;
1290 		struct timeval timeout;
1291 		int s;
1292 		socklen_t fromlen = sizeof(from_ss);
1293 
1294 		timeout.tv_sec = 15;
1295 		timeout.tv_usec = 0;
1296 		s = accept_with_timeout(pdata, from, &fromlen, &timeout);
1297 		if (s < 0) {
1298 			reply(425, "Can't open data connection.");
1299 			close(pdata);
1300 			pdata = -1;
1301 			return (NULL);
1302 		}
1303 		close(pdata);
1304 		pdata = s;
1305 #if defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
1306 		{
1307 		    int tos = IPTOS_THROUGHPUT;
1308 
1309 		    setsockopt(s, IPPROTO_IP, IP_TOS, (void *)&tos,
1310 			       sizeof(tos));
1311 		}
1312 #endif
1313 		reply(150, "Opening %s mode data connection for '%s'%s.",
1314 		     type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1315 		return (fdopen(pdata, mode));
1316 	}
1317 	if (data >= 0) {
1318 		reply(125, "Using existing data connection for '%s'%s.",
1319 		    name, sizebuf);
1320 		usedefault = 1;
1321 		return (fdopen(data, mode));
1322 	}
1323 	if (usedefault)
1324 		data_dest = his_addr;
1325 	usedefault = 1;
1326 	/*
1327 	 * Default to using the same socket type as the ctrl address,
1328 	 * unless we know the type of the data address.
1329 	 */
1330 	domain = data_dest->sa_family;
1331 	if (domain == PF_UNSPEC)
1332 	    domain = ctrl_addr->sa_family;
1333 
1334 	file = getdatasock(mode, domain);
1335 	if (file == NULL) {
1336 		char data_addr[256];
1337 
1338 		if (inet_ntop (data_source->sa_family,
1339 			       socket_get_address(data_source),
1340 			       data_addr, sizeof(data_addr)) == NULL)
1341 			strlcpy (data_addr, "unknown address",
1342 					 sizeof(data_addr));
1343 
1344 		reply(425, "Can't create data socket (%s,%d): %s.",
1345 		      data_addr,
1346 		      socket_get_port (data_source),
1347 		      strerror(errno));
1348 		return (NULL);
1349 	}
1350 	data = fileno(file);
1351 	while (connect(data, data_dest,
1352 		       socket_sockaddr_size(data_dest)) < 0) {
1353 		if (errno == EADDRINUSE && retry < swaitmax) {
1354 			sleep(swaitint);
1355 			retry += swaitint;
1356 			continue;
1357 		}
1358 		perror_reply(425, "Can't build data connection");
1359 		fclose(file);
1360 		data = -1;
1361 		return (NULL);
1362 	}
1363 	reply(150, "Opening %s mode data connection for '%s'%s.",
1364 	     type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1365 	return (file);
1366 }
1367 
1368 /*
1369  * Tranfer the contents of "instr" to "outstr" peer using the appropriate
1370  * encapsulation of the data subject * to Mode, Structure, and Type.
1371  *
1372  * NB: Form isn't handled.
1373  */
1374 static void
1375 send_data(FILE *instr, FILE *outstr)
1376 {
1377 	int c, cnt, filefd, netfd;
1378 	static char *buf;
1379 	static size_t bufsize;
1380 
1381 	transflag = 1;
1382 	switch (type) {
1383 
1384 	case TYPE_A:
1385 	    while ((c = getc(instr)) != EOF) {
1386 		if (urgflag && handleoobcmd())
1387 		    return;
1388 		byte_count++;
1389 		if(c == '\n')
1390 		    sec_putc('\r', outstr);
1391 		sec_putc(c, outstr);
1392 	    }
1393 	    sec_fflush(outstr);
1394 	    transflag = 0;
1395 	    urgflag = 0;
1396 	    if (ferror(instr))
1397 		goto file_err;
1398 	    if (ferror(outstr))
1399 		goto data_err;
1400 	    reply(226, "Transfer complete.");
1401 	    return;
1402 
1403 	case TYPE_I:
1404 	case TYPE_L:
1405 #if 0 /* XXX handle urg flag */
1406 #if defined(HAVE_MMAP) && !defined(NO_MMAP)
1407 #ifndef MAP_FAILED
1408 #define MAP_FAILED (-1)
1409 #endif
1410 	    {
1411 		struct stat st;
1412 		char *chunk;
1413 		int in = fileno(instr);
1414 		if(fstat(in, &st) == 0 && S_ISREG(st.st_mode)
1415 		   && st.st_size > 0) {
1416 		    /*
1417 		     * mmap zero bytes has potential of loosing, don't do it.
1418 		     */
1419 		    chunk = mmap(0, st.st_size, PROT_READ,
1420 				 MAP_SHARED, in, 0);
1421 		    if((void *)chunk != (void *)MAP_FAILED) {
1422 			cnt = st.st_size - restart_point;
1423 			sec_write(fileno(outstr), chunk + restart_point, cnt);
1424 			if (munmap(chunk, st.st_size) < 0)
1425 			    warn ("munmap");
1426 			sec_fflush(outstr);
1427 			byte_count = cnt;
1428 			transflag = 0;
1429 			urgflag = 0;
1430 		    }
1431 		}
1432 	    }
1433 #endif
1434 #endif
1435 	if(transflag) {
1436 	    struct stat st;
1437 
1438 	    netfd = fileno(outstr);
1439 	    filefd = fileno(instr);
1440 	    buf = alloc_buffer (buf, &bufsize,
1441 				fstat(filefd, &st) >= 0 ? &st : NULL);
1442 	    if (buf == NULL) {
1443 		transflag = 0;
1444 		urgflag = 0;
1445 		perror_reply(451, "Local resource failure: malloc");
1446 		return;
1447 	    }
1448 	    while ((cnt = read(filefd, buf, bufsize)) > 0 &&
1449 		   sec_write(netfd, buf, cnt) == cnt) {
1450 		byte_count += cnt;
1451 		if (urgflag && handleoobcmd())
1452 		    return;
1453 	    }
1454 	    sec_fflush(outstr); /* to end an encrypted stream */
1455 	    transflag = 0;
1456 	    urgflag = 0;
1457 	    if (cnt != 0) {
1458 		if (cnt < 0)
1459 		    goto file_err;
1460 		goto data_err;
1461 	    }
1462 	}
1463 	reply(226, "Transfer complete.");
1464 	return;
1465 	default:
1466 	    transflag = 0;
1467 	    urgflag = 0;
1468 	    reply(550, "Unimplemented TYPE %d in send_data", type);
1469 	    return;
1470 	}
1471 
1472 data_err:
1473 	transflag = 0;
1474 	urgflag = 0;
1475 	perror_reply(426, "Data connection");
1476 	return;
1477 
1478 file_err:
1479 	transflag = 0;
1480 	urgflag = 0;
1481 	perror_reply(551, "Error on input file");
1482 }
1483 
1484 /*
1485  * Transfer data from peer to "outstr" using the appropriate encapulation of
1486  * the data subject to Mode, Structure, and Type.
1487  *
1488  * N.B.: Form isn't handled.
1489  */
1490 static int
1491 receive_data(FILE *instr, FILE *outstr)
1492 {
1493     int cnt, bare_lfs = 0;
1494     static char *buf;
1495     static size_t bufsize;
1496     struct stat st;
1497 
1498     transflag = 1;
1499 
1500     buf = alloc_buffer (buf, &bufsize,
1501 			fstat(fileno(outstr), &st) >= 0 ? &st : NULL);
1502     if (buf == NULL) {
1503 	transflag = 0;
1504 	urgflag = 0;
1505 	perror_reply(451, "Local resource failure: malloc");
1506 	return -1;
1507     }
1508 
1509     switch (type) {
1510 
1511     case TYPE_I:
1512     case TYPE_L:
1513 	while ((cnt = sec_read(fileno(instr), buf, bufsize)) > 0) {
1514 	    if (write(fileno(outstr), buf, cnt) != cnt)
1515 		goto file_err;
1516 	    byte_count += cnt;
1517 	    if (urgflag && handleoobcmd())
1518 		return (-1);
1519 	}
1520 	if (cnt < 0)
1521 	    goto data_err;
1522 	transflag = 0;
1523 	urgflag = 0;
1524 	return (0);
1525 
1526     case TYPE_E:
1527 	reply(553, "TYPE E not implemented.");
1528 	transflag = 0;
1529 	urgflag = 0;
1530 	return (-1);
1531 
1532     case TYPE_A:
1533     {
1534 	char *p, *q;
1535 	int cr_flag = 0;
1536 	while ((cnt = sec_read(fileno(instr),
1537 				buf + cr_flag,
1538 				bufsize - cr_flag)) > 0){
1539 	    if (urgflag && handleoobcmd())
1540 		return (-1);
1541 	    byte_count += cnt;
1542 	    cnt += cr_flag;
1543 	    cr_flag = 0;
1544 	    for(p = buf, q = buf; p < buf + cnt;) {
1545 		if(*p == '\n')
1546 		    bare_lfs++;
1547 		if(*p == '\r') {
1548 		    if(p == buf + cnt - 1){
1549 			cr_flag = 1;
1550 			p++;
1551 			continue;
1552 		    }else if(p[1] == '\n'){
1553 			*q++ = '\n';
1554 			p += 2;
1555 			continue;
1556 		    }
1557 		}
1558 		*q++ = *p++;
1559 	    }
1560 	    fwrite(buf, q - buf, 1, outstr);
1561 	    if(cr_flag)
1562 		buf[0] = '\r';
1563 	}
1564 	if(cr_flag)
1565 	    putc('\r', outstr);
1566 	fflush(outstr);
1567 	if (ferror(instr))
1568 	    goto data_err;
1569 	if (ferror(outstr))
1570 	    goto file_err;
1571 	transflag = 0;
1572 	urgflag = 0;
1573 	if (bare_lfs) {
1574 	    lreply(226, "WARNING! %d bare linefeeds received in ASCII mode\r\n"
1575 		   "    File may not have transferred correctly.\r\n",
1576 		   bare_lfs);
1577 	}
1578 	return (0);
1579     }
1580     default:
1581 	reply(550, "Unimplemented TYPE %d in receive_data", type);
1582 	transflag = 0;
1583 	urgflag = 0;
1584 	return (-1);
1585     }
1586 
1587 data_err:
1588     transflag = 0;
1589     urgflag = 0;
1590     perror_reply(426, "Data Connection");
1591     return (-1);
1592 
1593 file_err:
1594     transflag = 0;
1595     urgflag = 0;
1596     perror_reply(452, "Error writing file");
1597     return (-1);
1598 }
1599 
1600 void
1601 statfilecmd(char *filename)
1602 {
1603 	FILE *fin;
1604 	int c;
1605 	char line[LINE_MAX];
1606 
1607 	snprintf(line, sizeof(line), "/bin/ls -la -- %s", filename);
1608 	fin = ftpd_popen(line, "r", 1, 0);
1609 	lreply(211, "status of %s:", filename);
1610 	while ((c = getc(fin)) != EOF) {
1611 		if (c == '\n') {
1612 			if (ferror(stdout)){
1613 				perror_reply(421, "control connection");
1614 				ftpd_pclose(fin);
1615 				dologout(1);
1616 				/* NOTREACHED */
1617 			}
1618 			if (ferror(fin)) {
1619 				perror_reply(551, filename);
1620 				ftpd_pclose(fin);
1621 				return;
1622 			}
1623 			putc('\r', stdout);
1624 		}
1625 		putc(c, stdout);
1626 	}
1627 	ftpd_pclose(fin);
1628 	reply(211, "End of Status");
1629 }
1630 
1631 void
1632 statcmd(void)
1633 {
1634 #if 0
1635 	struct sockaddr_in *sin;
1636 	u_char *a, *p;
1637 
1638 	lreply(211, "%s FTP server (%s) status:", hostname, version);
1639 	printf("     %s\r\n", version);
1640 	printf("     Connected to %s", remotehost);
1641 	if (!isdigit((unsigned char)remotehost[0]))
1642 		printf(" (%s)", inet_ntoa(his_addr.sin_addr));
1643 	printf("\r\n");
1644 	if (logged_in) {
1645 		if (guest)
1646 			printf("     Logged in anonymously\r\n");
1647 		else
1648 			printf("     Logged in as %s\r\n", pw->pw_name);
1649 	} else if (askpasswd)
1650 		printf("     Waiting for password\r\n");
1651 	else
1652 		printf("     Waiting for user name\r\n");
1653 	printf("     TYPE: %s", typenames[type]);
1654 	if (type == TYPE_A || type == TYPE_E)
1655 		printf(", FORM: %s", formnames[form]);
1656 	if (type == TYPE_L)
1657 #if NBBY == 8
1658 		printf(" %d", NBBY);
1659 #else
1660 		printf(" %d", bytesize);	/* need definition! */
1661 #endif
1662 	printf("; STRUcture: %s; transfer MODE: %s\r\n",
1663 	    strunames[stru], modenames[mode]);
1664 	if (data != -1)
1665 		printf("     Data connection open\r\n");
1666 	else if (pdata != -1) {
1667 		printf("     in Passive mode");
1668 		sin = &pasv_addr;
1669 		goto printaddr;
1670 	} else if (usedefault == 0) {
1671 		printf("     PORT");
1672 		sin = &data_dest;
1673 printaddr:
1674 		a = (u_char *) &sin->sin_addr;
1675 		p = (u_char *) &sin->sin_port;
1676 #define UC(b) (((int) b) & 0xff)
1677 		printf(" (%d,%d,%d,%d,%d,%d)\r\n", UC(a[0]),
1678 			UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
1679 #undef UC
1680 	} else
1681 		printf("     No data connection\r\n");
1682 #endif
1683 	reply(211, "End of status");
1684 }
1685 
1686 void
1687 fatal(char *s)
1688 {
1689 
1690 	reply(451, "Error in server: %s\n", s);
1691 	reply(221, "Closing connection due to server error.");
1692 	dologout(0);
1693 	/* NOTREACHED */
1694 }
1695 
1696 static void
1697 int_reply(int, char *, const char *, va_list)
1698 #ifdef __GNUC__
1699 __attribute__ ((format (printf, 3, 0)))
1700 #endif
1701 ;
1702 
1703 static void
1704 int_reply(int n, char *c, const char *fmt, va_list ap)
1705 {
1706     char buf[10240];
1707     char *p;
1708     p=buf;
1709     if(n){
1710 	snprintf(p, sizeof(buf), "%d%s", n, c);
1711 	p+=strlen(p);
1712     }
1713     vsnprintf(p, sizeof(buf) - strlen(p), fmt, ap);
1714     p+=strlen(p);
1715     snprintf(p, sizeof(buf) - strlen(p), "\r\n");
1716     p+=strlen(p);
1717     sec_fprintf(stdout, "%s", buf);
1718     fflush(stdout);
1719     if (debug)
1720 	syslog(LOG_DEBUG, "<--- %s- ", buf);
1721 }
1722 
1723 void
1724 reply(int n, const char *fmt, ...)
1725 {
1726   va_list ap;
1727   va_start(ap, fmt);
1728   int_reply(n, " ", fmt, ap);
1729   delete_ftp_command();
1730   va_end(ap);
1731 }
1732 
1733 void
1734 lreply(int n, const char *fmt, ...)
1735 {
1736   va_list ap;
1737   va_start(ap, fmt);
1738   int_reply(n, "-", fmt, ap);
1739   va_end(ap);
1740 }
1741 
1742 void
1743 nreply(const char *fmt, ...)
1744 {
1745   va_list ap;
1746   va_start(ap, fmt);
1747   int_reply(0, NULL, fmt, ap);
1748   va_end(ap);
1749 }
1750 
1751 static void
1752 ack(char *s)
1753 {
1754 
1755 	reply(250, "%s command successful.", s);
1756 }
1757 
1758 void
1759 nack(char *s)
1760 {
1761 
1762 	reply(502, "%s command not implemented.", s);
1763 }
1764 
1765 void
1766 do_delete(char *name)
1767 {
1768 	struct stat st;
1769 
1770 	LOGCMD("delete", name);
1771 	if (stat(name, &st) < 0) {
1772 		perror_reply(550, name);
1773 		return;
1774 	}
1775 	if ((st.st_mode&S_IFMT) == S_IFDIR) {
1776 		if (rmdir(name) < 0) {
1777 			perror_reply(550, name);
1778 			return;
1779 		}
1780 		goto done;
1781 	}
1782 	if (unlink(name) < 0) {
1783 		perror_reply(550, name);
1784 		return;
1785 	}
1786 done:
1787 	ack("DELE");
1788 }
1789 
1790 void
1791 cwd(char *path)
1792 {
1793 
1794 	if (chdir(path) < 0)
1795 		perror_reply(550, path);
1796 	else
1797 		ack("CWD");
1798 }
1799 
1800 void
1801 makedir(char *name)
1802 {
1803 
1804 	LOGCMD("mkdir", name);
1805 	if(guest && filename_check(name))
1806 	    return;
1807 	if (mkdir(name, 0777) < 0)
1808 		perror_reply(550, name);
1809 	else{
1810 	    if(guest)
1811 		chmod(name, 0700); /* guest has umask 777 */
1812 	    reply(257, "MKD command successful.");
1813 	}
1814 }
1815 
1816 void
1817 removedir(char *name)
1818 {
1819 
1820 	LOGCMD("rmdir", name);
1821 	if (rmdir(name) < 0)
1822 		perror_reply(550, name);
1823 	else
1824 		ack("RMD");
1825 }
1826 
1827 void
1828 pwd(void)
1829 {
1830     char path[MaxPathLen];
1831     char *ret;
1832 
1833     /* SunOS has a broken getcwd that does popen(pwd) (!!!), this
1834      * failes miserably when running chroot
1835      */
1836     ret = getcwd(path, sizeof(path));
1837     if (ret == NULL)
1838 	reply(550, "%s.", strerror(errno));
1839     else
1840 	reply(257, "\"%s\" is current directory.", path);
1841 }
1842 
1843 char *
1844 renamefrom(char *name)
1845 {
1846 	struct stat st;
1847 
1848 	if (stat(name, &st) < 0) {
1849 		perror_reply(550, name);
1850 		return NULL;
1851 	}
1852 	reply(350, "File exists, ready for destination name");
1853 	return (name);
1854 }
1855 
1856 void
1857 renamecmd(char *from, char *to)
1858 {
1859 
1860 	LOGCMD2("rename", from, to);
1861 	if(guest && filename_check(to))
1862 	    return;
1863 	if (rename(from, to) < 0)
1864 		perror_reply(550, "rename");
1865 	else
1866 		ack("RNTO");
1867 }
1868 
1869 static void
1870 dolog(struct sockaddr *sa, int len)
1871 {
1872 	getnameinfo_verified (sa, len, remotehost, sizeof(remotehost),
1873 			      NULL, 0, 0);
1874 #ifdef HAVE_SETPROCTITLE
1875 	snprintf(proctitle, sizeof(proctitle), "%s: connected", remotehost);
1876 	setproctitle("%s", proctitle);
1877 #endif /* HAVE_SETPROCTITLE */
1878 
1879 	if (logging) {
1880 		char data_addr[256];
1881 
1882 		if (inet_ntop (his_addr->sa_family,
1883 			       socket_get_address(his_addr),
1884 			       data_addr, sizeof(data_addr)) == NULL)
1885 			strlcpy (data_addr, "unknown address",
1886 					 sizeof(data_addr));
1887 
1888 
1889 		syslog(LOG_INFO, "connection from %s(%s)",
1890 		       remotehost,
1891 		       data_addr);
1892 	}
1893 }
1894 
1895 /*
1896  * Record logout in wtmp file
1897  * and exit with supplied status.
1898  */
1899 void
1900 dologout(int status)
1901 {
1902     transflag = 0;
1903     urgflag = 0;
1904     if (logged_in) {
1905 #if KRB4 || KRB5
1906 	cond_kdestroy();
1907 #endif
1908 	seteuid((uid_t)0); /* No need to check, we call exit() below */
1909 	ftpd_logwtmp(ttyline, "", "");
1910     }
1911     /* beware of flushing buffers after a SIGPIPE */
1912 #ifdef XXX
1913     exit(status);
1914 #else
1915     _exit(status);
1916 #endif
1917 }
1918 
1919 void abor(void)
1920 {
1921     if (!transflag)
1922 	return;
1923     reply(426, "Transfer aborted. Data connection closed.");
1924     reply(226, "Abort successful");
1925     transflag = 0;
1926 }
1927 
1928 static void
1929 myoob(int signo)
1930 {
1931     urgflag = 1;
1932 }
1933 
1934 static char *
1935 mec_space(char *p)
1936 {
1937     while(isspace(*(unsigned char *)p))
1938 	  p++;
1939     return p;
1940 }
1941 
1942 static int
1943 handleoobcmd(void)
1944 {
1945 	char *cp;
1946 
1947 	/* only process if transfer occurring */
1948 	if (!transflag)
1949 		return 0;
1950 
1951 	urgflag = 0;
1952 
1953 	cp = tmpline;
1954 	if (ftpd_getline(cp, sizeof(tmpline)) == NULL) {
1955 		reply(221, "You could at least say goodbye.");
1956 		dologout(0);
1957 	}
1958 
1959 	if (strncasecmp("MIC", cp, 3) == 0) {
1960 	    mec(mec_space(cp + 3), prot_safe);
1961 	} else if (strncasecmp("CONF", cp, 4) == 0) {
1962 	    mec(mec_space(cp + 4), prot_confidential);
1963 	} else if (strncasecmp("ENC", cp, 3) == 0) {
1964 	    mec(mec_space(cp + 3), prot_private);
1965 	} else if (!allow_insecure_oob) {
1966 	    reply(533, "Command protection level denied "
1967 		  "for paranoid reasons.");
1968 	    goto out;
1969 	}
1970 
1971 	if (secure_command())
1972 	    cp = ftp_command;
1973 
1974 	if (strcasecmp(cp, "ABOR\r\n") == 0) {
1975 		abor();
1976 	} else if (strcasecmp(cp, "STAT\r\n") == 0) {
1977 		if (file_size != (off_t) -1)
1978 			reply(213, "Status: %ld of %ld bytes transferred",
1979 			      (long)byte_count,
1980 			      (long)file_size);
1981 		else
1982 			reply(213, "Status: %ld bytes transferred",
1983 			      (long)byte_count);
1984 	}
1985 out:
1986 	return (transflag == 0);
1987 }
1988 
1989 /*
1990  * Note: a response of 425 is not mentioned as a possible response to
1991  *	the PASV command in RFC959. However, it has been blessed as
1992  *	a legitimate response by Jon Postel in a telephone conversation
1993  *	with Rick Adams on 25 Jan 89.
1994  */
1995 void
1996 pasv(void)
1997 {
1998 	socklen_t len;
1999 	char *p, *a;
2000 	struct sockaddr_in *sin;
2001 
2002 	if (ctrl_addr->sa_family != AF_INET) {
2003 		reply(425,
2004 		      "You cannot do PASV with something that's not IPv4");
2005 		return;
2006 	}
2007 
2008 	if(pdata != -1)
2009 	    close(pdata);
2010 
2011 	pdata = socket(ctrl_addr->sa_family, SOCK_STREAM, 0);
2012 	if (pdata < 0) {
2013 		perror_reply(425, "Can't open passive connection");
2014 		return;
2015 	}
2016 	pasv_addr->sa_family = ctrl_addr->sa_family;
2017 	socket_set_address_and_port (pasv_addr,
2018 				     socket_get_address (ctrl_addr),
2019 				     0);
2020 	socket_set_portrange(pdata, restricted_data_ports,
2021 	    pasv_addr->sa_family);
2022 	if (seteuid(0) < 0)
2023 		fatal("Failed to seteuid");
2024 	if (bind(pdata, pasv_addr, socket_sockaddr_size (pasv_addr)) < 0) {
2025 		if (seteuid(pw->pw_uid) < 0)
2026 			fatal("Failed to seteuid");
2027 		goto pasv_error;
2028 	}
2029 	if (seteuid(pw->pw_uid) < 0)
2030 		fatal("Failed to seteuid");
2031 	len = sizeof(pasv_addr_ss);
2032 	if (getsockname(pdata, pasv_addr, &len) < 0)
2033 		goto pasv_error;
2034 	if (listen(pdata, 1) < 0)
2035 		goto pasv_error;
2036 	sin = (struct sockaddr_in *)pasv_addr;
2037 	a = (char *) &sin->sin_addr;
2038 	p = (char *) &sin->sin_port;
2039 
2040 #define UC(b) (((int) b) & 0xff)
2041 
2042 	reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]),
2043 		UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
2044 	return;
2045 
2046 pasv_error:
2047 	close(pdata);
2048 	pdata = -1;
2049 	perror_reply(425, "Can't open passive connection");
2050 	return;
2051 }
2052 
2053 void
2054 epsv(char *proto)
2055 {
2056 	socklen_t len;
2057 
2058 	pdata = socket(ctrl_addr->sa_family, SOCK_STREAM, 0);
2059 	if (pdata < 0) {
2060 		perror_reply(425, "Can't open passive connection");
2061 		return;
2062 	}
2063 	pasv_addr->sa_family = ctrl_addr->sa_family;
2064 	socket_set_address_and_port (pasv_addr,
2065 				     socket_get_address (ctrl_addr),
2066 				     0);
2067 	socket_set_portrange(pdata, restricted_data_ports,
2068 	    pasv_addr->sa_family);
2069 	if (seteuid(0) < 0)
2070 		fatal("Failed to seteuid");
2071 	if (bind(pdata, pasv_addr, socket_sockaddr_size (pasv_addr)) < 0) {
2072 		if (seteuid(pw->pw_uid))
2073 			fatal("Failed to seteuid");
2074 		goto pasv_error;
2075 	}
2076 	if (seteuid(pw->pw_uid) < 0)
2077 		fatal("Failed to seteuid");
2078 	len = sizeof(pasv_addr_ss);
2079 	if (getsockname(pdata, pasv_addr, &len) < 0)
2080 		goto pasv_error;
2081 	if (listen(pdata, 1) < 0)
2082 		goto pasv_error;
2083 
2084 	reply(229, "Entering Extended Passive Mode (|||%d|)",
2085 	      ntohs(socket_get_port (pasv_addr)));
2086 	return;
2087 
2088 pasv_error:
2089 	close(pdata);
2090 	pdata = -1;
2091 	perror_reply(425, "Can't open passive connection");
2092 	return;
2093 }
2094 
2095 void
2096 eprt(char *str)
2097 {
2098 	char *end;
2099 	char sep;
2100 	int af;
2101 	int ret;
2102 	int port;
2103 
2104 	usedefault = 0;
2105 	if (pdata >= 0) {
2106 	    close(pdata);
2107 	    pdata = -1;
2108 	}
2109 
2110 	sep = *str++;
2111 	if (sep == '\0') {
2112 		reply(500, "Bad syntax in EPRT");
2113 		return;
2114 	}
2115 	af = strtol (str, &end, 0);
2116 	if (af == 0 || *end != sep) {
2117 		reply(500, "Bad syntax in EPRT");
2118 		return;
2119 	}
2120 	str = end + 1;
2121 	switch (af) {
2122 #ifdef HAVE_IPV6
2123 	case 2 :
2124 	    data_dest->sa_family = AF_INET6;
2125 	    break;
2126 #endif
2127 	case 1 :
2128 	    data_dest->sa_family = AF_INET;
2129 		break;
2130 	default :
2131 		reply(522, "Network protocol %d not supported, use (1"
2132 #ifdef HAVE_IPV6
2133 		      ",2"
2134 #endif
2135 		      ")", af);
2136 		return;
2137 	}
2138 	end = strchr (str, sep);
2139 	if (end == NULL) {
2140 		reply(500, "Bad syntax in EPRT");
2141 		return;
2142 	}
2143 	*end = '\0';
2144 	ret = inet_pton (data_dest->sa_family, str,
2145 			 socket_get_address (data_dest));
2146 
2147 	if (ret != 1) {
2148 		reply(500, "Bad address syntax in EPRT");
2149 		return;
2150 	}
2151 	str = end + 1;
2152 	port = strtol (str, &end, 0);
2153 	if (port == 0 || *end != sep) {
2154 		reply(500, "Bad port syntax in EPRT");
2155 		return;
2156 	}
2157 	socket_set_port (data_dest, htons(port));
2158 	reply(200, "EPRT command successful.");
2159 }
2160 
2161 /*
2162  * Generate unique name for file with basename "local".
2163  * The file named "local" is already known to exist.
2164  * Generates failure reply on error.
2165  */
2166 static char *
2167 gunique(char *local)
2168 {
2169 	static char new[MaxPathLen];
2170 	struct stat st;
2171 	int count;
2172 	char *cp;
2173 
2174 	cp = strrchr(local, '/');
2175 	if (cp)
2176 		*cp = '\0';
2177 	if (stat(cp ? local : ".", &st) < 0) {
2178 		perror_reply(553, cp ? local : ".");
2179 		return NULL;
2180 	}
2181 	if (cp)
2182 		*cp = '/';
2183 	for (count = 1; count < 100; count++) {
2184 		snprintf (new, sizeof(new), "%s.%d", local, count);
2185 		if (stat(new, &st) < 0)
2186 			return (new);
2187 	}
2188 	reply(452, "Unique file name cannot be created.");
2189 	return (NULL);
2190 }
2191 
2192 /*
2193  * Format and send reply containing system error number.
2194  */
2195 void
2196 perror_reply(int code, const char *string)
2197 {
2198 	reply(code, "%s: %s.", string, strerror(errno));
2199 }
2200 
2201 static char *onefile[] = {
2202 	"",
2203 	0
2204 };
2205 
2206 void
2207 list_file(char *file)
2208 {
2209     if(use_builtin_ls) {
2210 	FILE *dout;
2211 	dout = dataconn(file, -1, "w");
2212 	if (dout == NULL)
2213 	    return;
2214 	set_buffer_size(fileno(dout), 0);
2215 	if(builtin_ls(dout, file) == 0)
2216 	    reply(226, "Transfer complete.");
2217 	else
2218 	    reply(451, "Requested action aborted. Local error in processing.");
2219 	fclose(dout);
2220 	data = -1;
2221 	pdata = -1;
2222     } else {
2223 #ifdef HAVE_LS_A
2224 	const char *cmd = "/bin/ls -lA %s";
2225 #else
2226 	const char *cmd = "/bin/ls -la %s";
2227 #endif
2228 	retrieve(cmd, file);
2229     }
2230 }
2231 
2232 void
2233 send_file_list(char *whichf)
2234 {
2235     struct stat st;
2236     DIR *dirp = NULL;
2237     struct dirent *dir;
2238     FILE *dout = NULL;
2239     char **dirlist, *dirname;
2240     int simple = 0;
2241     int freeglob = 0;
2242     glob_t gl;
2243     char buf[MaxPathLen];
2244 
2245     if (strpbrk(whichf, "~{[*?") != NULL) {
2246 	int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE|
2247 #ifdef GLOB_MAXPATH
2248 	    GLOB_MAXPATH
2249 #else
2250 	    GLOB_LIMIT
2251 #endif
2252 	    ;
2253 
2254 	memset(&gl, 0, sizeof(gl));
2255 	freeglob = 1;
2256 	if (glob(whichf, flags, 0, &gl)) {
2257 	    reply(550, "not found");
2258 	    goto out;
2259 	} else if (gl.gl_pathc == 0) {
2260 	    errno = ENOENT;
2261 	    perror_reply(550, whichf);
2262 	    goto out;
2263 	}
2264 	dirlist = gl.gl_pathv;
2265     } else {
2266 	onefile[0] = whichf;
2267 	dirlist = onefile;
2268 	simple = 1;
2269     }
2270 
2271     while ((dirname = *dirlist++)) {
2272 
2273 	if (urgflag && handleoobcmd())
2274 	    goto out;
2275 
2276 	if (stat(dirname, &st) < 0) {
2277 	    /*
2278 	     * If user typed "ls -l", etc, and the client
2279 	     * used NLST, do what the user meant.
2280 	     */
2281 	    if (dirname[0] == '-' && *dirlist == NULL &&
2282 		transflag == 0) {
2283 		list_file(dirname);
2284 		goto out;
2285 	    }
2286 	    perror_reply(550, whichf);
2287 	    goto out;
2288 	}
2289 
2290 	if (S_ISREG(st.st_mode)) {
2291 	    if (dout == NULL) {
2292 		dout = dataconn("file list", (off_t)-1, "w");
2293 		if (dout == NULL)
2294 		    goto out;
2295 		transflag = 1;
2296 	    }
2297 	    snprintf(buf, sizeof(buf), "%s%s\n", dirname,
2298 		     type == TYPE_A ? "\r" : "");
2299 	    sec_write(fileno(dout), buf, strlen(buf));
2300 	    byte_count += strlen(dirname) + 1;
2301 	    continue;
2302 	} else if (!S_ISDIR(st.st_mode))
2303 	    continue;
2304 
2305 	if ((dirp = opendir(dirname)) == NULL)
2306 	    continue;
2307 
2308 	while ((dir = readdir(dirp)) != NULL) {
2309 	    char nbuf[MaxPathLen];
2310 
2311 	    if (urgflag && handleoobcmd())
2312 		goto out;
2313 
2314 	    if (!strcmp(dir->d_name, "."))
2315 		continue;
2316 	    if (!strcmp(dir->d_name, ".."))
2317 		continue;
2318 
2319 	    snprintf(nbuf, sizeof(nbuf), "%s/%s", dirname, dir->d_name);
2320 
2321 	    /*
2322 	     * We have to do a stat to insure it's
2323 	     * not a directory or special file.
2324 	     */
2325 	    if (simple || (stat(nbuf, &st) == 0 &&
2326 			   S_ISREG(st.st_mode))) {
2327 		if (dout == NULL) {
2328 		    dout = dataconn("file list", (off_t)-1, "w");
2329 		    if (dout == NULL)
2330 			goto out;
2331 		    transflag = 1;
2332 		}
2333 		if(strncmp(nbuf, "./", 2) == 0)
2334 		    snprintf(buf, sizeof(buf), "%s%s\n", nbuf +2,
2335 			     type == TYPE_A ? "\r" : "");
2336 		else
2337 		    snprintf(buf, sizeof(buf), "%s%s\n", nbuf,
2338 			     type == TYPE_A ? "\r" : "");
2339 		sec_write(fileno(dout), buf, strlen(buf));
2340 		byte_count += strlen(nbuf) + 1;
2341 	    }
2342 	}
2343 	closedir(dirp);
2344     }
2345     if (dout == NULL)
2346 	reply(550, "No files found.");
2347     else if (ferror(dout) != 0)
2348 	perror_reply(550, "Data connection");
2349     else
2350 	reply(226, "Transfer complete.");
2351 
2352 out:
2353     transflag = 0;
2354     if (dout != NULL){
2355 	sec_write(fileno(dout), buf, 0); /* XXX flush */
2356 
2357 	fclose(dout);
2358     }
2359     data = -1;
2360     pdata = -1;
2361     if (freeglob) {
2362 	freeglob = 0;
2363 	globfree(&gl);
2364     }
2365 }
2366 
2367 
2368 int
2369 find(char *pattern)
2370 {
2371     char line[1024];
2372     FILE *f;
2373 
2374     snprintf(line, sizeof(line),
2375 	     "/bin/locate -d %s -- %s",
2376 	     ftp_rooted("/etc/locatedb"),
2377 	     pattern);
2378     f = ftpd_popen(line, "r", 1, 1);
2379     if(f == NULL){
2380 	perror_reply(550, "/bin/locate");
2381 	return 1;
2382     }
2383     lreply(200, "Output from find.");
2384     while(fgets(line, sizeof(line), f)){
2385 	if(line[strlen(line)-1] == '\n')
2386 	    line[strlen(line)-1] = 0;
2387 	nreply("%s", line);
2388     }
2389     reply(200, "Done");
2390     ftpd_pclose(f);
2391     return 0;
2392 }
2393 
2394