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