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