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