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