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