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