Complete support for --disable-afs-support
[heimdal.git] / appl / ftp / ftpd / ftpd.c
blob04a2ce4cf27ebbba108719ac2e293b749d628482
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("$Id$");
43 static char version[] = "Version 6.00";
45 extern off_t restart_point;
46 extern char cbuf[];
48 struct sockaddr_storage ctrl_addr_ss;
49 struct sockaddr *ctrl_addr = (struct sockaddr *)&ctrl_addr_ss;
51 struct sockaddr_storage data_source_ss;
52 struct sockaddr *data_source = (struct sockaddr *)&data_source_ss;
54 struct sockaddr_storage data_dest_ss;
55 struct sockaddr *data_dest = (struct sockaddr *)&data_dest_ss;
57 struct sockaddr_storage his_addr_ss;
58 struct sockaddr *his_addr = (struct sockaddr *)&his_addr_ss;
60 struct sockaddr_storage pasv_addr_ss;
61 struct sockaddr *pasv_addr = (struct sockaddr *)&pasv_addr_ss;
63 int data;
64 int logged_in;
65 struct passwd *pw;
66 int debug = 0;
67 int ftpd_timeout = 900; /* timeout after 15 minutes of inactivity */
68 int maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */
69 int restricted_data_ports = 1;
70 int logging;
71 int guest;
72 int dochroot;
73 int type;
74 int form;
75 int stru; /* avoid C keyword */
76 int mode;
77 int usedefault = 1; /* for data transfers */
78 int pdata = -1; /* for passive mode */
79 int allow_insecure_oob = 1;
80 static int transflag;
81 static int urgflag;
82 off_t file_size;
83 off_t byte_count;
84 #if !defined(CMASK) || CMASK == 0
85 #undef CMASK
86 #define CMASK 027
87 #endif
88 int defumask = CMASK; /* default umask value */
89 int guest_umask = 0777; /* Paranoia for anonymous users */
90 char tmpline[10240];
91 char hostname[MaxHostNameLen];
92 char remotehost[MaxHostNameLen];
93 static char ttyline[20];
94 int paranoid = 1;
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", NULL },
216 { NULL, 'i', arg_flag, &interactive_flag, "don't assume stdin is a socket",
217 NULL },
218 { NULL, 'p', arg_string, &port_string, "what port to listen to", NULL },
219 { NULL, 'g', arg_string, &guest_umask_string, "umask for guest logins",
220 NULL },
221 { NULL, 'l', arg_counter, &logging, "log more stuff", "" },
222 { NULL, 't', arg_integer, &ftpd_timeout, "initial timeout", NULL },
223 { NULL, 'T', arg_integer, &maxtimeout, "max timeout", NULL },
224 { NULL, 'u', arg_string, &umask_string, "umask for user logins", NULL },
225 { NULL, 'U', arg_negative_flag, &restricted_data_ports,
226 "don't use high data ports", NULL },
227 { NULL, 'd', arg_flag, &debug, "enable debugging", NULL },
228 { NULL, 'v', arg_flag, &debug, "enable debugging", NULL },
229 { "builtin-ls", 'B', arg_flag, &use_builtin_ls,
230 "use built-in ls to list files", NULL },
231 { "good-chars", 0, arg_string, &good_chars,
232 "allowed anonymous upload filename chars", NULL },
233 { "insecure-oob", 'I', arg_negative_flag, &allow_insecure_oob,
234 "don't allow insecure OOB ABOR/STAT", NULL },
235 #ifdef KRB5
236 { "gss-bindings", 0, arg_flag, &ftp_do_gss_bindings,
237 "Require GSS-API bindings", NULL},
238 #endif
239 { "version", 0, arg_flag, &version_flag, NULL, NULL },
240 { "help", 'h', arg_flag, &help_flag, NULL, NULL }
243 static int num_args = sizeof(args) / sizeof(args[0]);
245 static void
246 usage (int code)
248 arg_printusage(args, num_args, NULL, "");
249 exit (code);
252 /* output contents of a file */
253 static int
254 show_file(const char *file, int code)
256 FILE *f;
257 char buf[128];
259 f = fopen(file, "r");
260 if(f == NULL)
261 return -1;
262 while(fgets(buf, sizeof(buf), f)){
263 buf[strcspn(buf, "\r\n")] = '\0';
264 lreply(code, "%s", buf);
266 fclose(f);
267 return 0;
271 main(int argc, char **argv)
273 socklen_t his_addr_len, ctrl_addr_len;
274 int on = 1;
275 int port;
276 struct servent *sp;
278 int optind = 0;
280 setprogname (argv[0]);
282 if(getarg(args, num_args, argc, argv, &optind))
283 usage(1);
285 if(help_flag)
286 usage(0);
288 if(version_flag) {
289 print_version(NULL);
290 exit(0);
293 if(auth_string)
294 auth_level = parse_auth_level(auth_string);
296 char *p;
297 long val = 0;
299 if(guest_umask_string) {
300 val = strtol(guest_umask_string, &p, 8);
301 if (*p != '\0' || val < 0)
302 warnx("bad value for -g");
303 else
304 guest_umask = val;
306 if(umask_string) {
307 val = strtol(umask_string, &p, 8);
308 if (*p != '\0' || val < 0)
309 warnx("bad value for -u");
310 else
311 defumask = val;
314 sp = getservbyname("ftp", "tcp");
315 if(sp)
316 port = sp->s_port;
317 else
318 port = htons(21);
319 if(port_string) {
320 sp = getservbyname(port_string, "tcp");
321 if(sp)
322 port = sp->s_port;
323 else
324 if(isdigit((unsigned char)port_string[0]))
325 port = htons(atoi(port_string));
326 else
327 warnx("bad value for -p");
330 if (maxtimeout < ftpd_timeout)
331 maxtimeout = ftpd_timeout;
333 #if 0
334 if (ftpd_timeout > maxtimeout)
335 ftpd_timeout = maxtimeout;
336 #endif
338 if(interactive_flag)
339 mini_inetd(port, NULL);
342 * LOG_NDELAY sets up the logging connection immediately,
343 * necessary for anonymous ftp's that chroot and can't do it later.
345 openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
346 his_addr_len = sizeof(his_addr_ss);
347 if (getpeername(STDIN_FILENO, his_addr, &his_addr_len) < 0) {
348 syslog(LOG_ERR, "getpeername (%s): %m",argv[0]);
349 exit(1);
351 ctrl_addr_len = sizeof(ctrl_addr_ss);
352 if (getsockname(STDIN_FILENO, ctrl_addr, &ctrl_addr_len) < 0) {
353 syslog(LOG_ERR, "getsockname (%s): %m",argv[0]);
354 exit(1);
356 #if defined(IP_TOS)
357 if (ctrl_addr->sa_family == AF_INET)
358 socket_set_tos(STDIN_FILENO, IP_TOS);
359 #endif
360 data_source->sa_family = ctrl_addr->sa_family;
361 socket_set_port (data_source,
362 htons(ntohs(socket_get_port(ctrl_addr)) - 1));
364 /* set this here so it can be put in wtmp */
365 snprintf(ttyline, sizeof(ttyline), "ftp%u", (unsigned)getpid());
368 /* freopen(_PATH_DEVNULL, "w", stderr); */
369 signal(SIGPIPE, lostconn);
370 signal(SIGCHLD, SIG_IGN);
371 #ifdef SIGURG
372 if (signal(SIGURG, myoob) == SIG_ERR)
373 syslog(LOG_ERR, "signal: %m");
374 #endif
376 /* Try to handle urgent data inline */
377 #if defined(SO_OOBINLINE) && defined(HAVE_SETSOCKOPT)
378 if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (void *)&on,
379 sizeof(on)) < 0)
380 syslog(LOG_ERR, "setsockopt: %m");
381 #endif
383 #ifdef F_SETOWN
384 if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1)
385 syslog(LOG_ERR, "fcntl F_SETOWN: %m");
386 #endif
387 dolog(his_addr, his_addr_len);
389 * Set up default state
391 data = -1;
392 type = TYPE_A;
393 form = FORM_N;
394 stru = STRU_F;
395 mode = MODE_S;
396 tmpline[0] = '\0';
398 /* If logins are disabled, print out the message. */
399 if(show_file(_PATH_NOLOGIN, 530) == 0) {
400 reply(530, "System not available.");
401 exit(0);
403 show_file(_PATH_FTPWELCOME, 220);
404 /* reply(220,) must follow */
405 gethostname(hostname, sizeof(hostname));
407 reply(220, "%s FTP server (%s"
408 #ifdef KRB5
409 "+%s"
410 #endif
411 ") ready.", hostname, version
412 #ifdef KRB5
413 ,heimdal_version
414 #endif
417 for (;;)
418 yyparse();
419 /* NOTREACHED */
422 static RETSIGTYPE
423 lostconn(int signo)
426 if (debug)
427 syslog(LOG_DEBUG, "lost connection");
428 dologout(-1);
432 * Helper function for sgetpwnam().
434 static char *
435 sgetsave(char *s)
437 char *new = strdup(s);
439 if (new == NULL) {
440 perror_reply(421, "Local resource failure: malloc");
441 dologout(1);
442 /* NOTREACHED */
444 return new;
448 * Save the result of a getpwnam. Used for USER command, since
449 * the data returned must not be clobbered by any other command
450 * (e.g., globbing).
452 static struct passwd *
453 sgetpwnam(char *name)
455 static struct passwd save;
456 struct passwd *p;
458 if ((p = k_getpwnam(name)) == NULL)
459 return (p);
460 if (save.pw_name) {
461 free(save.pw_name);
462 free(save.pw_passwd);
463 free(save.pw_gecos);
464 free(save.pw_dir);
465 free(save.pw_shell);
467 save = *p;
468 save.pw_name = sgetsave(p->pw_name);
469 save.pw_passwd = sgetsave(p->pw_passwd);
470 save.pw_gecos = sgetsave(p->pw_gecos);
471 save.pw_dir = sgetsave(p->pw_dir);
472 save.pw_shell = sgetsave(p->pw_shell);
473 return (&save);
476 static int login_attempts; /* number of failed login attempts */
477 static int askpasswd; /* had user command, ask for passwd */
478 static char curname[10]; /* current USER name */
479 #ifdef OTP
480 OtpContext otp_ctx;
481 #endif
484 * USER command.
485 * Sets global passwd pointer pw if named account exists and is acceptable;
486 * sets askpasswd if a PASS command is expected. If logged in previously,
487 * need to reset state. If name is "ftp" or "anonymous", the name is not in
488 * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return.
489 * If account doesn't exist, ask for passwd anyway. Otherwise, check user
490 * requesting login privileges. Disallow anyone who does not have a standard
491 * shell as returned by getusershell(). Disallow anyone mentioned in the file
492 * _PATH_FTPUSERS to allow people such as root and uucp to be avoided.
494 void
495 user(char *name)
497 char *cp, *shell;
499 if(auth_level == 0 && !sec_complete){
500 reply(530, "No login allowed without authorization.");
501 return;
504 if (logged_in) {
505 if (guest) {
506 reply(530, "Can't change user from guest login.");
507 return;
508 } else if (dochroot) {
509 reply(530, "Can't change user from chroot user.");
510 return;
512 end_login();
515 guest = 0;
516 if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) {
517 if ((auth_level & AUTH_FTP) == 0 ||
518 checkaccess("ftp") ||
519 checkaccess("anonymous"))
520 reply(530, "User %s access denied.", name);
521 else if ((pw = sgetpwnam("ftp")) != NULL) {
522 guest = 1;
523 defumask = guest_umask; /* paranoia for incoming */
524 askpasswd = 1;
525 reply(331, "Guest login ok, type your name as password.");
526 } else
527 reply(530, "User %s unknown.", name);
528 if (!askpasswd && logging) {
529 char data_addr[256];
531 if (inet_ntop (his_addr->sa_family,
532 socket_get_address(his_addr),
533 data_addr, sizeof(data_addr)) == NULL)
534 strlcpy (data_addr, "unknown address",
535 sizeof(data_addr));
537 syslog(LOG_NOTICE,
538 "ANONYMOUS FTP LOGIN REFUSED FROM %s(%s)",
539 remotehost, data_addr);
541 return;
543 if((auth_level & AUTH_PLAIN) == 0 && !sec_complete){
544 reply(530, "Only authorized and anonymous login allowed.");
545 return;
547 if ((pw = sgetpwnam(name))) {
548 if ((shell = pw->pw_shell) == NULL || *shell == 0)
549 shell = _PATH_BSHELL;
550 while ((cp = getusershell()) != NULL)
551 if (strcmp(cp, shell) == 0)
552 break;
553 endusershell();
555 if (cp == NULL || checkaccess(name)) {
556 reply(530, "User %s access denied.", name);
557 if (logging) {
558 char data_addr[256];
560 if (inet_ntop (his_addr->sa_family,
561 socket_get_address(his_addr),
562 data_addr,
563 sizeof(data_addr)) == NULL)
564 strlcpy (data_addr,
565 "unknown address",
566 sizeof(data_addr));
568 syslog(LOG_NOTICE,
569 "FTP LOGIN REFUSED FROM %s(%s), %s",
570 remotehost,
571 data_addr,
572 name);
574 pw = (struct passwd *) NULL;
575 return;
578 if (logging)
579 strlcpy(curname, name, sizeof(curname));
580 if(sec_complete) {
581 if(sec_userok(name) == 0) {
582 do_login(232, name);
583 sec_session(name);
584 } else
585 reply(530, "User %s access denied.", name);
586 } else {
587 #ifdef OTP
588 char ss[256];
590 if (otp_challenge(&otp_ctx, name, ss, sizeof(ss)) == 0) {
591 reply(331, "Password %s for %s required.",
592 ss, name);
593 askpasswd = 1;
594 } else
595 #endif
596 if ((auth_level & AUTH_OTP) == 0) {
597 reply(331, "Password required for %s.", name);
598 askpasswd = 1;
599 } else {
600 #ifdef OTP
601 char *s;
603 if ((s = otp_error (&otp_ctx)) != NULL)
604 lreply(530, "OTP: %s", s);
605 #endif
606 reply(530,
607 "Only authorized, anonymous"
608 #ifdef OTP
609 " and OTP "
610 #endif
611 "login allowed.");
616 * Delay before reading passwd after first failed
617 * attempt to slow down passwd-guessing programs.
619 if (login_attempts)
620 sleep(login_attempts);
624 * Check if a user is in the file "fname"
626 static int
627 checkuser(char *fname, char *name)
629 FILE *fd;
630 int found = 0;
631 char *p, line[BUFSIZ];
633 if ((fd = fopen(fname, "r")) != NULL) {
634 while (fgets(line, sizeof(line), fd) != NULL)
635 if ((p = strchr(line, '\n')) != NULL) {
636 *p = '\0';
637 if (line[0] == '#')
638 continue;
639 if (strcmp(line, name) == 0) {
640 found = 1;
641 break;
644 fclose(fd);
646 return (found);
651 * Determine whether a user has access, based on information in
652 * _PATH_FTPUSERS. The users are listed one per line, with `allow'
653 * or `deny' after the username. If anything other than `allow', or
654 * just nothing, is given after the username, `deny' is assumed.
656 * If the user is not found in the file, but the pseudo-user `*' is,
657 * the permission is taken from that line.
659 * This preserves the old semantics where if a user was listed in the
660 * file he was denied, otherwise he was allowed.
662 * Return 1 if the user is denied, or 0 if he is allowed. */
664 static int
665 match(const char *pattern, const char *string)
667 return fnmatch(pattern, string, FNM_NOESCAPE);
670 static int
671 checkaccess(char *name)
673 #define ALLOWED 0
674 #define NOT_ALLOWED 1
675 FILE *fd;
676 int allowed = ALLOWED;
677 char *user, *perm, line[BUFSIZ];
678 char *foo;
680 fd = fopen(_PATH_FTPUSERS, "r");
682 if(fd == NULL)
683 return allowed;
685 while (fgets(line, sizeof(line), fd) != NULL) {
686 foo = NULL;
687 user = strtok_r(line, " \t\n", &foo);
688 if (user == NULL || user[0] == '#')
689 continue;
690 perm = strtok_r(NULL, " \t\n", &foo);
691 if (match(user, name) == 0){
692 if(perm && strcmp(perm, "allow") == 0)
693 allowed = ALLOWED;
694 else
695 allowed = NOT_ALLOWED;
696 break;
699 fclose(fd);
700 return allowed;
702 #undef ALLOWED
703 #undef NOT_ALLOWED
706 int do_login(int code, char *passwd)
708 login_attempts = 0; /* this time successful */
709 if (setegid((gid_t)pw->pw_gid) < 0) {
710 reply(550, "Can't set gid.");
711 return -1;
713 initgroups(pw->pw_name, pw->pw_gid);
714 #if defined(KRB5) && !defined(NO_AFS)
715 if(k_hasafs())
716 k_setpag();
717 #endif
719 /* open wtmp before chroot */
720 ftpd_logwtmp(ttyline, pw->pw_name, remotehost);
721 logged_in = 1;
723 dochroot = checkuser(_PATH_FTPCHROOT, pw->pw_name);
724 if (guest) {
726 * We MUST do a chdir() after the chroot. Otherwise
727 * the old current directory will be accessible as "."
728 * outside the new root!
730 if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
731 reply(550, "Can't set guest privileges.");
732 return -1;
734 } else if (dochroot) {
735 if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
736 reply(550, "Can't change root.");
737 return -1;
739 } else if (chdir(pw->pw_dir) < 0) {
740 if (chdir("/") < 0) {
741 reply(530, "User %s: can't change directory to %s.",
742 pw->pw_name, pw->pw_dir);
743 return -1;
744 } else
745 lreply(code, "No directory! Logging in with home=/");
747 if (seteuid((uid_t)pw->pw_uid) < 0) {
748 reply(550, "Can't set uid.");
749 return -1;
752 if(use_builtin_ls == -1) {
753 struct stat st;
754 /* if /bin/ls exist and is a regular file, use it, otherwise
755 use built-in ls */
756 if(stat("/bin/ls", &st) == 0 &&
757 S_ISREG(st.st_mode))
758 use_builtin_ls = 0;
759 else
760 use_builtin_ls = 1;
764 * Display a login message, if it exists.
765 * N.B. reply(code,) must follow the message.
767 show_file(_PATH_FTPLOGINMESG, code);
768 if(show_file(_PATH_ISSUE_NET, code) != 0)
769 show_file(_PATH_ISSUE, code);
770 if (guest) {
771 reply(code, "Guest login ok, access restrictions apply.");
772 #ifdef HAVE_SETPROCTITLE
773 snprintf (proctitle, sizeof(proctitle),
774 "%s: anonymous/%s",
775 remotehost,
776 passwd);
777 setproctitle("%s", proctitle);
778 #endif /* HAVE_SETPROCTITLE */
779 if (logging) {
780 char data_addr[256];
782 if (inet_ntop (his_addr->sa_family,
783 socket_get_address(his_addr),
784 data_addr, sizeof(data_addr)) == NULL)
785 strlcpy (data_addr, "unknown address",
786 sizeof(data_addr));
788 syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s(%s), %s",
789 remotehost,
790 data_addr,
791 passwd);
793 } else {
794 reply(code, "User %s logged in.", pw->pw_name);
795 #ifdef HAVE_SETPROCTITLE
796 snprintf(proctitle, sizeof(proctitle), "%s: %s", remotehost, pw->pw_name);
797 setproctitle("%s", proctitle);
798 #endif /* HAVE_SETPROCTITLE */
799 if (logging) {
800 char data_addr[256];
802 if (inet_ntop (his_addr->sa_family,
803 socket_get_address(his_addr),
804 data_addr, sizeof(data_addr)) == NULL)
805 strlcpy (data_addr, "unknown address",
806 sizeof(data_addr));
808 syslog(LOG_INFO, "FTP LOGIN FROM %s(%s) as %s",
809 remotehost,
810 data_addr,
811 pw->pw_name);
814 umask(defumask);
815 return 0;
819 * Terminate login as previous user, if any, resetting state;
820 * used when USER command is given or login fails.
822 static void
823 end_login(void)
826 if (seteuid((uid_t)0) < 0)
827 fatal("Failed to seteuid");
828 if (logged_in)
829 ftpd_logwtmp(ttyline, "", "");
830 pw = NULL;
831 logged_in = 0;
832 guest = 0;
833 dochroot = 0;
836 #ifdef KRB5
837 static int
838 krb5_verify(struct passwd *pwd, char *passwd)
840 krb5_context context;
841 krb5_ccache id;
842 krb5_principal princ;
843 krb5_error_code ret;
845 ret = krb5_init_context(&context);
846 if(ret)
847 return ret;
849 ret = krb5_parse_name(context, pwd->pw_name, &princ);
850 if(ret){
851 krb5_free_context(context);
852 return ret;
854 ret = krb5_cc_new_unique(context, "MEMORY", NULL, &id);
855 if(ret){
856 krb5_free_principal(context, princ);
857 krb5_free_context(context);
858 return ret;
860 ret = krb5_verify_user(context,
861 princ,
863 passwd,
865 NULL);
866 krb5_free_principal(context, princ);
867 #ifndef NO_AFS
868 if (k_hasafs()) {
869 krb5_afslog_uid_home(context, id,NULL, NULL,pwd->pw_uid, pwd->pw_dir);
871 #endif
872 krb5_cc_destroy(context, id);
873 krb5_free_context (context);
874 if(ret)
875 return ret;
876 return 0;
878 #endif /* KRB5 */
880 void
881 pass(char *passwd)
883 int rval;
885 /* some clients insists on sending a password */
886 if (logged_in && askpasswd == 0){
887 reply(230, "Password not necessary");
888 return;
891 if (logged_in || askpasswd == 0) {
892 reply(503, "Login with USER first.");
893 return;
895 askpasswd = 0;
896 rval = 1;
897 if (!guest) { /* "ftp" is only account allowed no password */
898 if (pw == NULL)
899 rval = 1; /* failure below */
900 #ifdef OTP
901 else if (otp_verify_user (&otp_ctx, passwd) == 0) {
902 rval = 0;
904 #endif
905 else if((auth_level & AUTH_OTP) == 0) {
906 #ifdef KRB5
907 rval = krb5_verify(pw, passwd);
908 #endif
909 if (rval)
910 rval = unix_verify_user(pw->pw_name, passwd);
911 } else {
912 #ifdef OTP
913 char *s;
914 if ((s = otp_error(&otp_ctx)) != NULL)
915 lreply(530, "OTP: %s", s);
916 #endif
918 memset (passwd, 0, strlen(passwd));
921 * If rval == 1, the user failed the authentication
922 * check above. If rval == 0, either Kerberos or
923 * local authentication succeeded.
925 if (rval) {
926 char data_addr[256];
928 if (inet_ntop (his_addr->sa_family,
929 socket_get_address(his_addr),
930 data_addr, sizeof(data_addr)) == NULL)
931 strlcpy (data_addr, "unknown address",
932 sizeof(data_addr));
934 reply(530, "Login incorrect.");
935 if (logging)
936 syslog(LOG_NOTICE,
937 "FTP LOGIN FAILED FROM %s(%s), %s",
938 remotehost,
939 data_addr,
940 curname);
941 pw = NULL;
942 if (login_attempts++ >= 5) {
943 syslog(LOG_NOTICE,
944 "repeated login failures from %s(%s)",
945 remotehost,
946 data_addr);
947 exit(0);
949 return;
952 if(!do_login(230, passwd))
953 return;
955 /* Forget all about it... */
956 end_login();
959 void
960 retrieve(const char *cmd, char *name)
962 FILE *fin = NULL, *dout;
963 struct stat st;
964 int (*closefunc) (FILE *);
965 char line[BUFSIZ];
968 if (cmd == 0) {
969 fin = fopen(name, "r");
970 closefunc = fclose;
971 st.st_size = 0;
972 if(fin == NULL){
973 int save_errno = errno;
974 struct cmds {
975 const char *ext;
976 const char *cmd;
977 const char *rev_cmd;
978 } cmds[] = {
979 {".tar", "/bin/gtar cPf - %s", NULL},
980 {".tar.gz", "/bin/gtar zcPf - %s", NULL},
981 {".tar.Z", "/bin/gtar ZcPf - %s", NULL},
982 {".gz", "/bin/gzip -c -- %s", "/bin/gzip -c -d -- %s"},
983 {".Z", "/bin/compress -c -- %s", "/bin/uncompress -c -- %s"},
984 {NULL, NULL, NULL}
986 struct cmds *p;
987 for(p = cmds; p->ext; p++){
988 char *tail = name + strlen(name) - strlen(p->ext);
989 char c = *tail;
991 if(strcmp(tail, p->ext) == 0 &&
992 (*tail = 0) == 0 &&
993 access(name, R_OK) == 0){
994 snprintf (line, sizeof(line), p->cmd, name);
995 *tail = c;
996 break;
998 *tail = c;
999 if (p->rev_cmd != NULL) {
1000 char *ext;
1001 int ret;
1003 ret = asprintf(&ext, "%s%s", name, p->ext);
1004 if (ret != -1) {
1005 if (access(ext, R_OK) == 0) {
1006 snprintf (line, sizeof(line),
1007 p->rev_cmd, ext);
1008 free(ext);
1009 break;
1011 free(ext);
1016 if(p->ext){
1017 fin = ftpd_popen(line, "r", 0, 0);
1018 closefunc = ftpd_pclose;
1019 st.st_size = -1;
1020 cmd = line;
1021 } else
1022 errno = save_errno;
1024 } else {
1025 snprintf(line, sizeof(line), cmd, name);
1026 name = line;
1027 fin = ftpd_popen(line, "r", 1, 0);
1028 closefunc = ftpd_pclose;
1029 st.st_size = -1;
1031 if (fin == NULL) {
1032 if (errno != 0) {
1033 perror_reply(550, name);
1034 if (cmd == 0) {
1035 LOGCMD("get", name);
1038 return;
1040 byte_count = -1;
1041 if (cmd == 0){
1042 if(fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode)) {
1043 reply(550, "%s: not a plain file.", name);
1044 goto done;
1047 if (restart_point) {
1048 if (type == TYPE_A) {
1049 off_t i, n;
1050 int c;
1052 n = restart_point;
1053 i = 0;
1054 while (i++ < n) {
1055 if ((c=getc(fin)) == EOF) {
1056 perror_reply(550, name);
1057 goto done;
1059 if (c == '\n')
1060 i++;
1062 } else if (lseek(fileno(fin), restart_point, SEEK_SET) < 0) {
1063 perror_reply(550, name);
1064 goto done;
1067 dout = dataconn(name, st.st_size, "w");
1068 if (dout == NULL)
1069 goto done;
1070 set_buffer_size(fileno(dout), 0);
1071 send_data(fin, dout);
1072 fclose(dout);
1073 data = -1;
1074 pdata = -1;
1075 done:
1076 if (cmd == 0)
1077 LOGBYTES("get", name, byte_count);
1078 (*closefunc)(fin);
1081 /* filename sanity check */
1084 filename_check(char *filename)
1086 char *p;
1088 p = strrchr(filename, '/');
1089 if(p)
1090 filename = p + 1;
1092 p = filename;
1094 if(isalnum((unsigned char)*p)){
1095 p++;
1096 while(*p && (isalnum((unsigned char)*p) || strchr(good_chars, (unsigned char)*p)))
1097 p++;
1098 if(*p == '\0')
1099 return 0;
1101 lreply(553, "\"%s\" is not an acceptable filename.", filename);
1102 lreply(553, "The filename must start with an alphanumeric "
1103 "character and must only");
1104 reply(553, "consist of alphanumeric characters or any of the following: %s",
1105 good_chars);
1106 return 1;
1109 void
1110 do_store(char *name, char *mode, int unique)
1112 FILE *fout, *din;
1113 struct stat st;
1114 int (*closefunc) (FILE *);
1116 if(guest && filename_check(name))
1117 return;
1118 if (unique) {
1119 char *uname;
1120 if (stat(name, &st) == 0) {
1121 if ((uname = gunique(name)) == NULL)
1122 return;
1123 name = uname;
1125 LOGCMD(*mode == 'w' ? "put" : "append", name);
1128 if (restart_point)
1129 mode = "r+";
1130 fout = fopen(name, mode);
1131 closefunc = fclose;
1132 if (fout == NULL) {
1133 perror_reply(553, name);
1134 LOGCMD(*mode == 'w' ? "put" : "append", name);
1135 return;
1137 byte_count = -1;
1138 if (restart_point) {
1139 if (type == TYPE_A) {
1140 off_t i, n;
1141 int c;
1143 n = restart_point;
1144 i = 0;
1145 while (i++ < n) {
1146 if ((c=getc(fout)) == EOF) {
1147 perror_reply(550, name);
1148 goto done;
1150 if (c == '\n')
1151 i++;
1154 * We must do this seek to "current" position
1155 * because we are changing from reading to
1156 * writing.
1158 if (fseek(fout, 0L, SEEK_CUR) < 0) {
1159 perror_reply(550, name);
1160 goto done;
1162 } else if (lseek(fileno(fout), restart_point, SEEK_SET) < 0) {
1163 perror_reply(550, name);
1164 goto done;
1167 din = dataconn(name, (off_t)-1, "r");
1168 if (din == NULL)
1169 goto done;
1170 set_buffer_size(fileno(din), 1);
1171 if (receive_data(din, fout) == 0) {
1172 if((*closefunc)(fout) < 0)
1173 perror_reply(552, name);
1174 else {
1175 if (unique)
1176 reply(226, "Transfer complete (unique file name:%s).",
1177 name);
1178 else
1179 reply(226, "Transfer complete.");
1181 } else
1182 (*closefunc)(fout);
1183 fclose(din);
1184 data = -1;
1185 pdata = -1;
1186 done:
1187 LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count);
1190 static FILE *
1191 getdatasock(const char *mode, int domain)
1193 int s, t, tries;
1195 if (data >= 0)
1196 return (fdopen(data, mode));
1197 if (seteuid(0) < 0)
1198 fatal("Failed to seteuid");
1199 s = socket(domain, SOCK_STREAM, 0);
1200 if (s < 0)
1201 goto bad;
1202 socket_set_reuseaddr (s, 1);
1203 /* anchor socket to avoid multi-homing problems */
1204 socket_set_address_and_port (data_source,
1205 socket_get_address (ctrl_addr),
1206 socket_get_port (data_source));
1208 for (tries = 1; ; tries++) {
1209 if (bind(s, data_source,
1210 socket_sockaddr_size (data_source)) >= 0)
1211 break;
1212 if (errno != EADDRINUSE || tries > 10)
1213 goto bad;
1214 sleep(tries);
1216 if (seteuid(pw->pw_uid) < 0)
1217 fatal("Failed to seteuid");
1218 #ifdef IPTOS_THROUGHPUT
1219 socket_set_tos (s, IPTOS_THROUGHPUT);
1220 #endif
1221 return (fdopen(s, mode));
1222 bad:
1223 /* Return the real value of errno (close may change it) */
1224 t = errno;
1225 if (seteuid((uid_t)pw->pw_uid) < 0)
1226 fatal("Failed to seteuid");
1227 close(s);
1228 errno = t;
1229 return (NULL);
1232 static int
1233 accept_with_timeout(int socket,
1234 struct sockaddr *address,
1235 socklen_t *address_len,
1236 struct timeval *timeout)
1238 int ret;
1239 fd_set rfd;
1240 FD_ZERO(&rfd);
1241 FD_SET(socket, &rfd);
1242 ret = select(socket + 1, &rfd, NULL, NULL, timeout);
1243 if(ret < 0)
1244 return ret;
1245 if(ret == 0) {
1246 errno = ETIMEDOUT;
1247 return -1;
1249 return accept(socket, address, address_len);
1252 static FILE *
1253 dataconn(const char *name, off_t size, const char *mode)
1255 char sizebuf[32];
1256 FILE *file;
1257 int domain, retry = 0;
1259 file_size = size;
1260 byte_count = 0;
1261 if (size >= 0)
1262 snprintf(sizebuf, sizeof(sizebuf), " (%ld bytes)", (long)size);
1263 else
1264 *sizebuf = '\0';
1265 if (pdata >= 0) {
1266 struct sockaddr_storage from_ss;
1267 struct sockaddr *from = (struct sockaddr *)&from_ss;
1268 struct timeval timeout;
1269 int s;
1270 socklen_t fromlen = sizeof(from_ss);
1272 timeout.tv_sec = 15;
1273 timeout.tv_usec = 0;
1274 s = accept_with_timeout(pdata, from, &fromlen, &timeout);
1275 if (s < 0) {
1276 reply(425, "Can't open data connection.");
1277 close(pdata);
1278 pdata = -1;
1279 return (NULL);
1281 close(pdata);
1282 pdata = s;
1283 #if defined(IPTOS_THROUGHPUT)
1284 if (from_ss.ss_family == AF_INET)
1285 socket_set_tos(s, IPTOS_THROUGHPUT);
1286 #endif
1287 reply(150, "Opening %s mode data connection for '%s'%s.",
1288 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1289 return (fdopen(pdata, mode));
1291 if (data >= 0) {
1292 reply(125, "Using existing data connection for '%s'%s.",
1293 name, sizebuf);
1294 usedefault = 1;
1295 return (fdopen(data, mode));
1297 if (usedefault)
1298 data_dest = his_addr;
1299 usedefault = 1;
1301 * Default to using the same socket type as the ctrl address,
1302 * unless we know the type of the data address.
1304 domain = data_dest->sa_family;
1305 if (domain == PF_UNSPEC)
1306 domain = ctrl_addr->sa_family;
1308 file = getdatasock(mode, domain);
1309 if (file == NULL) {
1310 char data_addr[256];
1312 if (inet_ntop (data_source->sa_family,
1313 socket_get_address(data_source),
1314 data_addr, sizeof(data_addr)) == NULL)
1315 strlcpy (data_addr, "unknown address",
1316 sizeof(data_addr));
1318 reply(425, "Can't create data socket (%s,%d): %s.",
1319 data_addr,
1320 socket_get_port (data_source),
1321 strerror(errno));
1322 return (NULL);
1324 data = fileno(file);
1325 while (connect(data, data_dest,
1326 socket_sockaddr_size(data_dest)) < 0) {
1327 if (errno == EADDRINUSE && retry < swaitmax) {
1328 sleep(swaitint);
1329 retry += swaitint;
1330 continue;
1332 perror_reply(425, "Can't build data connection");
1333 fclose(file);
1334 data = -1;
1335 return (NULL);
1337 reply(150, "Opening %s mode data connection for '%s'%s.",
1338 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1339 return (file);
1343 * Tranfer the contents of "instr" to "outstr" peer using the appropriate
1344 * encapsulation of the data subject * to Mode, Structure, and Type.
1346 * NB: Form isn't handled.
1348 static void
1349 send_data(FILE *instr, FILE *outstr)
1351 int c, cnt, filefd, netfd;
1352 static char *buf;
1353 static size_t bufsize;
1355 transflag = 1;
1356 switch (type) {
1358 case TYPE_A:
1359 while ((c = getc(instr)) != EOF) {
1360 if (urgflag && handleoobcmd())
1361 return;
1362 byte_count++;
1363 if(c == '\n')
1364 sec_putc('\r', outstr);
1365 sec_putc(c, outstr);
1367 sec_fflush(outstr);
1368 transflag = 0;
1369 urgflag = 0;
1370 if (ferror(instr))
1371 goto file_err;
1372 if (ferror(outstr))
1373 goto data_err;
1374 reply(226, "Transfer complete.");
1375 return;
1377 case TYPE_I:
1378 case TYPE_L:
1379 #if 0 /* XXX handle urg flag */
1380 #if defined(HAVE_MMAP) && !defined(NO_MMAP)
1381 #ifndef MAP_FAILED
1382 #define MAP_FAILED (-1)
1383 #endif
1385 struct stat st;
1386 char *chunk;
1387 int in = fileno(instr);
1388 if(fstat(in, &st) == 0 && S_ISREG(st.st_mode)
1389 && st.st_size > 0) {
1391 * mmap zero bytes has potential of loosing, don't do it.
1393 chunk = mmap(0, st.st_size, PROT_READ,
1394 MAP_SHARED, in, 0);
1395 if((void *)chunk != (void *)MAP_FAILED) {
1396 cnt = st.st_size - restart_point;
1397 sec_write(fileno(outstr), chunk + restart_point, cnt);
1398 if (munmap(chunk, st.st_size) < 0)
1399 warn ("munmap");
1400 sec_fflush(outstr);
1401 byte_count = cnt;
1402 transflag = 0;
1403 urgflag = 0;
1407 #endif
1408 #endif
1409 if(transflag) {
1410 struct stat st;
1412 netfd = fileno(outstr);
1413 filefd = fileno(instr);
1414 buf = alloc_buffer (buf, &bufsize,
1415 fstat(filefd, &st) >= 0 ? &st : NULL);
1416 if (buf == NULL) {
1417 transflag = 0;
1418 urgflag = 0;
1419 perror_reply(451, "Local resource failure: malloc");
1420 return;
1422 while ((cnt = read(filefd, buf, bufsize)) > 0 &&
1423 sec_write(netfd, buf, cnt) == cnt) {
1424 byte_count += cnt;
1425 if (urgflag && handleoobcmd())
1426 return;
1428 sec_fflush(outstr); /* to end an encrypted stream */
1429 transflag = 0;
1430 urgflag = 0;
1431 if (cnt != 0) {
1432 if (cnt < 0)
1433 goto file_err;
1434 goto data_err;
1437 reply(226, "Transfer complete.");
1438 return;
1439 default:
1440 transflag = 0;
1441 urgflag = 0;
1442 reply(550, "Unimplemented TYPE %d in send_data", type);
1443 return;
1446 data_err:
1447 transflag = 0;
1448 urgflag = 0;
1449 perror_reply(426, "Data connection");
1450 return;
1452 file_err:
1453 transflag = 0;
1454 urgflag = 0;
1455 perror_reply(551, "Error on input file");
1459 * Transfer data from peer to "outstr" using the appropriate encapulation of
1460 * the data subject to Mode, Structure, and Type.
1462 * N.B.: Form isn't handled.
1464 static int
1465 receive_data(FILE *instr, FILE *outstr)
1467 int cnt, bare_lfs = 0;
1468 static char *buf;
1469 static size_t bufsize;
1470 struct stat st;
1472 transflag = 1;
1474 buf = alloc_buffer (buf, &bufsize,
1475 fstat(fileno(outstr), &st) >= 0 ? &st : NULL);
1476 if (buf == NULL) {
1477 transflag = 0;
1478 urgflag = 0;
1479 perror_reply(451, "Local resource failure: malloc");
1480 return -1;
1483 switch (type) {
1485 case TYPE_I:
1486 case TYPE_L:
1487 while ((cnt = sec_read(fileno(instr), buf, bufsize)) > 0) {
1488 if (write(fileno(outstr), buf, cnt) != cnt)
1489 goto file_err;
1490 byte_count += cnt;
1491 if (urgflag && handleoobcmd())
1492 return (-1);
1494 if (cnt < 0)
1495 goto data_err;
1496 transflag = 0;
1497 urgflag = 0;
1498 return (0);
1500 case TYPE_E:
1501 reply(553, "TYPE E not implemented.");
1502 transflag = 0;
1503 urgflag = 0;
1504 return (-1);
1506 case TYPE_A:
1508 char *p, *q;
1509 int cr_flag = 0;
1510 while ((cnt = sec_read(fileno(instr),
1511 buf + cr_flag,
1512 bufsize - cr_flag)) > 0){
1513 if (urgflag && handleoobcmd())
1514 return (-1);
1515 byte_count += cnt;
1516 cnt += cr_flag;
1517 cr_flag = 0;
1518 for(p = buf, q = buf; p < buf + cnt;) {
1519 if(*p == '\n')
1520 bare_lfs++;
1521 if(*p == '\r') {
1522 if(p == buf + cnt - 1){
1523 cr_flag = 1;
1524 p++;
1525 continue;
1526 }else if(p[1] == '\n'){
1527 *q++ = '\n';
1528 p += 2;
1529 continue;
1532 *q++ = *p++;
1534 fwrite(buf, q - buf, 1, outstr);
1535 if(cr_flag)
1536 buf[0] = '\r';
1538 if(cr_flag)
1539 putc('\r', outstr);
1540 fflush(outstr);
1541 if (ferror(instr))
1542 goto data_err;
1543 if (ferror(outstr))
1544 goto file_err;
1545 transflag = 0;
1546 urgflag = 0;
1547 if (bare_lfs) {
1548 lreply(226, "WARNING! %d bare linefeeds received in ASCII mode\r\n"
1549 " File may not have transferred correctly.\r\n",
1550 bare_lfs);
1552 return (0);
1554 default:
1555 reply(550, "Unimplemented TYPE %d in receive_data", type);
1556 transflag = 0;
1557 urgflag = 0;
1558 return (-1);
1561 data_err:
1562 transflag = 0;
1563 urgflag = 0;
1564 perror_reply(426, "Data Connection");
1565 return (-1);
1567 file_err:
1568 transflag = 0;
1569 urgflag = 0;
1570 perror_reply(452, "Error writing file");
1571 return (-1);
1574 void
1575 statfilecmd(char *filename)
1577 FILE *fin;
1578 int c;
1579 char line[LINE_MAX];
1581 snprintf(line, sizeof(line), "/bin/ls -la -- %s", filename);
1582 fin = ftpd_popen(line, "r", 1, 0);
1583 lreply(211, "status of %s:", filename);
1584 while ((c = getc(fin)) != EOF) {
1585 if (c == '\n') {
1586 if (ferror(stdout)){
1587 perror_reply(421, "control connection");
1588 ftpd_pclose(fin);
1589 dologout(1);
1590 /* NOTREACHED */
1592 if (ferror(fin)) {
1593 perror_reply(551, filename);
1594 ftpd_pclose(fin);
1595 return;
1597 putc('\r', stdout);
1599 putc(c, stdout);
1601 ftpd_pclose(fin);
1602 reply(211, "End of Status");
1605 void
1606 statcmd(void)
1608 #if 0
1609 struct sockaddr_in *sin;
1610 u_char *a, *p;
1612 lreply(211, "%s FTP server (%s) status:", hostname, version);
1613 printf(" %s\r\n", version);
1614 printf(" Connected to %s", remotehost);
1615 if (!isdigit((unsigned char)remotehost[0]))
1616 printf(" (%s)", inet_ntoa(his_addr.sin_addr));
1617 printf("\r\n");
1618 if (logged_in) {
1619 if (guest)
1620 printf(" Logged in anonymously\r\n");
1621 else
1622 printf(" Logged in as %s\r\n", pw->pw_name);
1623 } else if (askpasswd)
1624 printf(" Waiting for password\r\n");
1625 else
1626 printf(" Waiting for user name\r\n");
1627 printf(" TYPE: %s", typenames[type]);
1628 if (type == TYPE_A || type == TYPE_E)
1629 printf(", FORM: %s", formnames[form]);
1630 if (type == TYPE_L)
1631 #if NBBY == 8
1632 printf(" %d", NBBY);
1633 #else
1634 printf(" %d", bytesize); /* need definition! */
1635 #endif
1636 printf("; STRUcture: %s; transfer MODE: %s\r\n",
1637 strunames[stru], modenames[mode]);
1638 if (data != -1)
1639 printf(" Data connection open\r\n");
1640 else if (pdata != -1) {
1641 printf(" in Passive mode");
1642 sin = &pasv_addr;
1643 goto printaddr;
1644 } else if (usedefault == 0) {
1645 printf(" PORT");
1646 sin = &data_dest;
1647 printaddr:
1648 a = (u_char *) &sin->sin_addr;
1649 p = (u_char *) &sin->sin_port;
1650 #define UC(b) (((int) b) & 0xff)
1651 printf(" (%d,%d,%d,%d,%d,%d)\r\n", UC(a[0]),
1652 UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
1653 #undef UC
1654 } else
1655 printf(" No data connection\r\n");
1656 #endif
1657 reply(211, "End of status");
1660 void
1661 fatal(char *s)
1664 reply(451, "Error in server: %s\n", s);
1665 reply(221, "Closing connection due to server error.");
1666 dologout(0);
1667 /* NOTREACHED */
1670 static void
1671 int_reply(int, char *, const char *, va_list)
1672 #ifdef __GNUC__
1673 __attribute__ ((format (printf, 3, 0)))
1674 #endif
1677 static void
1678 int_reply(int n, char *c, const char *fmt, va_list ap)
1680 char buf[10240];
1681 char *p;
1682 p=buf;
1683 if(n){
1684 snprintf(p, sizeof(buf), "%d%s", n, c);
1685 p+=strlen(p);
1687 vsnprintf(p, sizeof(buf) - strlen(p), fmt, ap);
1688 p+=strlen(p);
1689 snprintf(p, sizeof(buf) - strlen(p), "\r\n");
1690 p+=strlen(p);
1691 sec_fprintf(stdout, "%s", buf);
1692 fflush(stdout);
1693 if (debug)
1694 syslog(LOG_DEBUG, "<--- %s- ", buf);
1697 void
1698 reply(int n, const char *fmt, ...)
1700 va_list ap;
1701 va_start(ap, fmt);
1702 int_reply(n, " ", fmt, ap);
1703 delete_ftp_command();
1704 va_end(ap);
1707 void
1708 lreply(int n, const char *fmt, ...)
1710 va_list ap;
1711 va_start(ap, fmt);
1712 int_reply(n, "-", fmt, ap);
1713 va_end(ap);
1716 void
1717 nreply(const char *fmt, ...)
1719 va_list ap;
1720 va_start(ap, fmt);
1721 int_reply(0, NULL, fmt, ap);
1722 va_end(ap);
1725 static void
1726 ack(char *s)
1729 reply(250, "%s command successful.", s);
1732 void
1733 nack(char *s)
1736 reply(502, "%s command not implemented.", s);
1739 void
1740 do_delete(char *name)
1742 struct stat st;
1744 LOGCMD("delete", name);
1745 if (stat(name, &st) < 0) {
1746 perror_reply(550, name);
1747 return;
1749 if (S_ISDIR(st.st_mode)) {
1750 if (rmdir(name) < 0) {
1751 perror_reply(550, name);
1752 return;
1754 goto done;
1756 if (unlink(name) < 0) {
1757 perror_reply(550, name);
1758 return;
1760 done:
1761 ack("DELE");
1764 void
1765 cwd(const char *path)
1768 if (chdir(path) < 0)
1769 perror_reply(550, path);
1770 else
1771 ack("CWD");
1774 void
1775 makedir(char *name)
1778 LOGCMD("mkdir", name);
1779 if(guest && filename_check(name))
1780 return;
1781 if (mkdir(name, 0777) < 0)
1782 perror_reply(550, name);
1783 else{
1784 if(guest)
1785 chmod(name, 0700); /* guest has umask 777 */
1786 reply(257, "MKD command successful.");
1790 void
1791 removedir(char *name)
1794 LOGCMD("rmdir", name);
1795 if (rmdir(name) < 0)
1796 perror_reply(550, name);
1797 else
1798 ack("RMD");
1801 void
1802 pwd(void)
1804 char path[MaxPathLen];
1805 char *ret;
1807 /* SunOS has a broken getcwd that does popen(pwd) (!!!), this
1808 * failes miserably when running chroot
1810 ret = getcwd(path, sizeof(path));
1811 if (ret == NULL)
1812 reply(550, "%s.", strerror(errno));
1813 else
1814 reply(257, "\"%s\" is current directory.", path);
1817 char *
1818 renamefrom(char *name)
1820 struct stat st;
1822 if (stat(name, &st) < 0) {
1823 perror_reply(550, name);
1824 return NULL;
1826 reply(350, "File exists, ready for destination name");
1827 return (name);
1830 void
1831 renamecmd(char *from, char *to)
1834 LOGCMD2("rename", from, to);
1835 if(guest && filename_check(to))
1836 return;
1837 if (rename(from, to) < 0)
1838 perror_reply(550, "rename");
1839 else
1840 ack("RNTO");
1843 static void
1844 dolog(struct sockaddr *sa, int len)
1846 getnameinfo_verified (sa, len, remotehost, sizeof(remotehost),
1847 NULL, 0, 0);
1848 #ifdef HAVE_SETPROCTITLE
1849 snprintf(proctitle, sizeof(proctitle), "%s: connected", remotehost);
1850 setproctitle("%s", proctitle);
1851 #endif /* HAVE_SETPROCTITLE */
1853 if (logging) {
1854 char data_addr[256];
1856 if (inet_ntop (his_addr->sa_family,
1857 socket_get_address(his_addr),
1858 data_addr, sizeof(data_addr)) == NULL)
1859 strlcpy (data_addr, "unknown address",
1860 sizeof(data_addr));
1863 syslog(LOG_INFO, "connection from %s(%s)",
1864 remotehost,
1865 data_addr);
1870 * Record logout in wtmp file
1871 * and exit with supplied status.
1873 void
1874 dologout(int status)
1876 transflag = 0;
1877 urgflag = 0;
1878 if (logged_in) {
1879 #if KRB5
1880 cond_kdestroy();
1881 #endif
1882 seteuid((uid_t)0); /* No need to check, we call exit() below */
1883 ftpd_logwtmp(ttyline, "", "");
1885 /* beware of flushing buffers after a SIGPIPE */
1886 #ifdef XXX
1887 exit(status);
1888 #else
1889 _exit(status);
1890 #endif
1893 void abor(void)
1895 if (!transflag)
1896 return;
1897 reply(426, "Transfer aborted. Data connection closed.");
1898 reply(226, "Abort successful");
1899 transflag = 0;
1902 static void
1903 myoob(int signo)
1905 urgflag = 1;
1908 static char *
1909 mec_space(char *p)
1911 while(isspace(*(unsigned char *)p))
1912 p++;
1913 return p;
1916 static int
1917 handleoobcmd(void)
1919 char *cp;
1921 /* only process if transfer occurring */
1922 if (!transflag)
1923 return 0;
1925 urgflag = 0;
1927 cp = tmpline;
1928 if (ftpd_getline(cp, sizeof(tmpline)) == NULL) {
1929 reply(221, "You could at least say goodbye.");
1930 dologout(0);
1933 if (strncasecmp("MIC", cp, 3) == 0) {
1934 mec(mec_space(cp + 3), prot_safe);
1935 } else if (strncasecmp("CONF", cp, 4) == 0) {
1936 mec(mec_space(cp + 4), prot_confidential);
1937 } else if (strncasecmp("ENC", cp, 3) == 0) {
1938 mec(mec_space(cp + 3), prot_private);
1939 } else if (!allow_insecure_oob) {
1940 reply(533, "Command protection level denied "
1941 "for paranoid reasons.");
1942 goto out;
1945 if (secure_command())
1946 cp = ftp_command;
1948 if (strcasecmp(cp, "ABOR\r\n") == 0) {
1949 abor();
1950 } else if (strcasecmp(cp, "STAT\r\n") == 0) {
1951 if (file_size != (off_t) -1)
1952 reply(213, "Status: %ld of %ld bytes transferred",
1953 (long)byte_count,
1954 (long)file_size);
1955 else
1956 reply(213, "Status: %ld bytes transferred",
1957 (long)byte_count);
1959 out:
1960 return (transflag == 0);
1964 * Note: a response of 425 is not mentioned as a possible response to
1965 * the PASV command in RFC959. However, it has been blessed as
1966 * a legitimate response by Jon Postel in a telephone conversation
1967 * with Rick Adams on 25 Jan 89.
1969 void
1970 pasv(void)
1972 socklen_t len;
1973 char *p, *a;
1974 struct sockaddr_in *sin;
1976 if (ctrl_addr->sa_family != AF_INET) {
1977 reply(425,
1978 "You cannot do PASV with something that's not IPv4");
1979 return;
1982 if(pdata != -1)
1983 close(pdata);
1985 pdata = socket(ctrl_addr->sa_family, SOCK_STREAM, 0);
1986 if (pdata < 0) {
1987 perror_reply(425, "Can't open passive connection");
1988 return;
1990 pasv_addr->sa_family = ctrl_addr->sa_family;
1991 socket_set_address_and_port (pasv_addr,
1992 socket_get_address (ctrl_addr),
1994 socket_set_portrange(pdata, restricted_data_ports,
1995 pasv_addr->sa_family);
1996 if (seteuid(0) < 0)
1997 fatal("Failed to seteuid");
1998 if (bind(pdata, pasv_addr, socket_sockaddr_size (pasv_addr)) < 0) {
1999 if (seteuid(pw->pw_uid) < 0)
2000 fatal("Failed to seteuid");
2001 goto pasv_error;
2003 if (seteuid(pw->pw_uid) < 0)
2004 fatal("Failed to seteuid");
2005 len = sizeof(pasv_addr_ss);
2006 if (getsockname(pdata, pasv_addr, &len) < 0)
2007 goto pasv_error;
2008 if (listen(pdata, 1) < 0)
2009 goto pasv_error;
2010 sin = (struct sockaddr_in *)pasv_addr;
2011 a = (char *) &sin->sin_addr;
2012 p = (char *) &sin->sin_port;
2014 #define UC(b) (((int) b) & 0xff)
2016 reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]),
2017 UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
2018 return;
2020 pasv_error:
2021 close(pdata);
2022 pdata = -1;
2023 perror_reply(425, "Can't open passive connection");
2024 return;
2027 void
2028 epsv(char *proto)
2030 socklen_t len;
2032 pdata = socket(ctrl_addr->sa_family, SOCK_STREAM, 0);
2033 if (pdata < 0) {
2034 perror_reply(425, "Can't open passive connection");
2035 return;
2037 pasv_addr->sa_family = ctrl_addr->sa_family;
2038 socket_set_address_and_port (pasv_addr,
2039 socket_get_address (ctrl_addr),
2041 socket_set_portrange(pdata, restricted_data_ports,
2042 pasv_addr->sa_family);
2043 if (seteuid(0) < 0)
2044 fatal("Failed to seteuid");
2045 if (bind(pdata, pasv_addr, socket_sockaddr_size (pasv_addr)) < 0) {
2046 if (seteuid(pw->pw_uid))
2047 fatal("Failed to seteuid");
2048 goto pasv_error;
2050 if (seteuid(pw->pw_uid) < 0)
2051 fatal("Failed to seteuid");
2052 len = sizeof(pasv_addr_ss);
2053 if (getsockname(pdata, pasv_addr, &len) < 0)
2054 goto pasv_error;
2055 if (listen(pdata, 1) < 0)
2056 goto pasv_error;
2058 reply(229, "Entering Extended Passive Mode (|||%d|)",
2059 ntohs(socket_get_port (pasv_addr)));
2060 return;
2062 pasv_error:
2063 close(pdata);
2064 pdata = -1;
2065 perror_reply(425, "Can't open passive connection");
2066 return;
2069 void
2070 eprt(char *str)
2072 char *end;
2073 char sep;
2074 int af;
2075 int ret;
2076 int port;
2078 usedefault = 0;
2079 if (pdata >= 0) {
2080 close(pdata);
2081 pdata = -1;
2084 sep = *str++;
2085 if (sep == '\0') {
2086 reply(500, "Bad syntax in EPRT");
2087 return;
2089 af = strtol (str, &end, 0);
2090 if (af == 0 || *end != sep) {
2091 reply(500, "Bad syntax in EPRT");
2092 return;
2094 str = end + 1;
2095 switch (af) {
2096 #ifdef HAVE_IPV6
2097 case 2 :
2098 data_dest->sa_family = AF_INET6;
2099 break;
2100 #endif
2101 case 1 :
2102 data_dest->sa_family = AF_INET;
2103 break;
2104 default :
2105 reply(522, "Network protocol %d not supported, use (1"
2106 #ifdef HAVE_IPV6
2107 ",2"
2108 #endif
2109 ")", af);
2110 return;
2112 end = strchr (str, sep);
2113 if (end == NULL) {
2114 reply(500, "Bad syntax in EPRT");
2115 return;
2117 *end = '\0';
2118 ret = inet_pton (data_dest->sa_family, str,
2119 socket_get_address (data_dest));
2121 if (ret != 1) {
2122 reply(500, "Bad address syntax in EPRT");
2123 return;
2125 str = end + 1;
2126 port = strtol (str, &end, 0);
2127 if (port == 0 || *end != sep) {
2128 reply(500, "Bad port syntax in EPRT");
2129 return;
2131 if (port < IPPORT_RESERVED) {
2132 reply(500, "Bad port in invalid range in EPRT");
2133 return;
2135 socket_set_port (data_dest, htons(port));
2137 if (paranoid &&
2138 (data_dest->sa_family != his_addr->sa_family ||
2139 memcmp(socket_get_address(data_dest), socket_get_address(his_addr), socket_sockaddr_size(data_dest)) != 0))
2141 reply(500, "Bad address in EPRT");
2143 reply(200, "EPRT command successful.");
2147 * Generate unique name for file with basename "local".
2148 * The file named "local" is already known to exist.
2149 * Generates failure reply on error.
2151 static char *
2152 gunique(char *local)
2154 static char new[MaxPathLen];
2155 struct stat st;
2156 int count;
2157 char *cp;
2159 cp = strrchr(local, '/');
2160 if (cp)
2161 *cp = '\0';
2162 if (stat(cp ? local : ".", &st) < 0) {
2163 perror_reply(553, cp ? local : ".");
2164 return NULL;
2166 if (cp)
2167 *cp = '/';
2168 for (count = 1; count < 100; count++) {
2169 snprintf (new, sizeof(new), "%s.%d", local, count);
2170 if (stat(new, &st) < 0)
2171 return (new);
2173 reply(452, "Unique file name cannot be created.");
2174 return (NULL);
2178 * Format and send reply containing system error number.
2180 void
2181 perror_reply(int code, const char *string)
2183 reply(code, "%s: %s.", string, strerror(errno));
2186 static char *onefile[] = {
2191 void
2192 list_file(char *file)
2194 if(use_builtin_ls) {
2195 FILE *dout;
2196 dout = dataconn(file, -1, "w");
2197 if (dout == NULL)
2198 return;
2199 set_buffer_size(fileno(dout), 0);
2200 if(builtin_ls(dout, file) == 0)
2201 reply(226, "Transfer complete.");
2202 else
2203 reply(451, "Requested action aborted. Local error in processing.");
2204 fclose(dout);
2205 data = -1;
2206 pdata = -1;
2207 } else {
2208 #ifdef HAVE_LS_A
2209 const char *cmd = "/bin/ls -lA %s";
2210 #else
2211 const char *cmd = "/bin/ls -la %s";
2212 #endif
2213 retrieve(cmd, file);
2217 void
2218 send_file_list(char *whichf)
2220 struct stat st;
2221 DIR *dirp = NULL;
2222 struct dirent *dir;
2223 FILE *dout = NULL;
2224 char **dirlist, *dirname;
2225 int simple = 0;
2226 int freeglob = 0;
2227 glob_t gl;
2228 char buf[MaxPathLen];
2230 if (strpbrk(whichf, "~{[*?") != NULL) {
2231 int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE|
2232 #ifdef GLOB_MAXPATH
2233 GLOB_MAXPATH
2234 #else
2235 GLOB_LIMIT
2236 #endif
2239 memset(&gl, 0, sizeof(gl));
2240 freeglob = 1;
2241 if (glob(whichf, flags, 0, &gl)) {
2242 reply(550, "not found");
2243 goto out;
2244 } else if (gl.gl_pathc == 0) {
2245 errno = ENOENT;
2246 perror_reply(550, whichf);
2247 goto out;
2249 dirlist = gl.gl_pathv;
2250 } else {
2251 onefile[0] = whichf;
2252 dirlist = onefile;
2253 simple = 1;
2256 while ((dirname = *dirlist++)) {
2258 if (urgflag && handleoobcmd())
2259 goto out;
2261 if (stat(dirname, &st) < 0) {
2263 * If user typed "ls -l", etc, and the client
2264 * used NLST, do what the user meant.
2266 if (dirname[0] == '-' && *dirlist == NULL &&
2267 transflag == 0) {
2268 list_file(dirname);
2269 goto out;
2271 perror_reply(550, whichf);
2272 goto out;
2275 if (S_ISREG(st.st_mode)) {
2276 if (dout == NULL) {
2277 dout = dataconn("file list", (off_t)-1, "w");
2278 if (dout == NULL)
2279 goto out;
2280 transflag = 1;
2282 snprintf(buf, sizeof(buf), "%s%s\n", dirname,
2283 type == TYPE_A ? "\r" : "");
2284 sec_write(fileno(dout), buf, strlen(buf));
2285 byte_count += strlen(dirname) + 1;
2286 continue;
2287 } else if (!S_ISDIR(st.st_mode))
2288 continue;
2290 if ((dirp = opendir(dirname)) == NULL)
2291 continue;
2293 while ((dir = readdir(dirp)) != NULL) {
2294 char nbuf[MaxPathLen];
2296 if (urgflag && handleoobcmd())
2297 goto out;
2299 if (!strcmp(dir->d_name, "."))
2300 continue;
2301 if (!strcmp(dir->d_name, ".."))
2302 continue;
2304 snprintf(nbuf, sizeof(nbuf), "%s/%s", dirname, dir->d_name);
2307 * We have to do a stat to insure it's
2308 * not a directory or special file.
2310 if (simple || (stat(nbuf, &st) == 0 &&
2311 S_ISREG(st.st_mode))) {
2312 if (dout == NULL) {
2313 dout = dataconn("file list", (off_t)-1, "w");
2314 if (dout == NULL)
2315 goto out;
2316 transflag = 1;
2318 if(strncmp(nbuf, "./", 2) == 0)
2319 snprintf(buf, sizeof(buf), "%s%s\n", nbuf +2,
2320 type == TYPE_A ? "\r" : "");
2321 else
2322 snprintf(buf, sizeof(buf), "%s%s\n", nbuf,
2323 type == TYPE_A ? "\r" : "");
2324 sec_write(fileno(dout), buf, strlen(buf));
2325 byte_count += strlen(nbuf) + 1;
2328 closedir(dirp);
2330 if (dout == NULL)
2331 reply(550, "No files found.");
2332 else if (ferror(dout) != 0)
2333 perror_reply(550, "Data connection");
2334 else
2335 reply(226, "Transfer complete.");
2337 out:
2338 transflag = 0;
2339 if (dout != NULL){
2340 sec_write(fileno(dout), buf, 0); /* XXX flush */
2342 fclose(dout);
2344 data = -1;
2345 pdata = -1;
2346 if (freeglob)
2347 globfree(&gl);
2352 find(char *pattern)
2354 char line[1024];
2355 FILE *f;
2357 snprintf(line, sizeof(line),
2358 "/bin/locate -d %s -- %s",
2359 ftp_rooted("/etc/locatedb"),
2360 pattern);
2361 f = ftpd_popen(line, "r", 1, 1);
2362 if(f == NULL){
2363 perror_reply(550, "/bin/locate");
2364 return 1;
2366 lreply(200, "Output from find.");
2367 while(fgets(line, sizeof(line), f)){
2368 if(line[strlen(line)-1] == '\n')
2369 line[strlen(line)-1] = 0;
2370 nreply("%s", line);
2372 reply(200, "Done");
2373 ftpd_pclose(f);
2374 return 0;