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 #if 0 35 #ifndef lint 36 static char copyright[] = 37 "@(#) Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994\n\ 38 The Regents of the University of California. All rights reserved.\n"; 39 #endif /* not lint */ 40 #endif 41 42 #ifndef lint 43 #if 0 44 static char sccsid[] = "@(#)ftpd.c 8.4 (Berkeley) 4/16/94"; 45 #endif 46 static const char rcsid[] = 47 "$FreeBSD$"; 48 #endif /* not lint */ 49 50 /* 51 * FTP server. 52 */ 53 #include <sys/param.h> 54 #include <sys/stat.h> 55 #include <sys/ioctl.h> 56 #include <sys/socket.h> 57 #include <sys/wait.h> 58 #include <sys/mman.h> 59 60 #include <netinet/in.h> 61 #include <netinet/in_systm.h> 62 #include <netinet/ip.h> 63 #include <netinet/tcp.h> 64 65 #define FTP_NAMES 66 #include <arpa/ftp.h> 67 #include <arpa/inet.h> 68 #include <arpa/telnet.h> 69 70 #include <ctype.h> 71 #include <dirent.h> 72 #include <err.h> 73 #include <errno.h> 74 #include <fcntl.h> 75 #include <glob.h> 76 #include <limits.h> 77 #include <netdb.h> 78 #include <pwd.h> 79 #include <grp.h> 80 #include <setjmp.h> 81 #include <signal.h> 82 #include <stdio.h> 83 #include <stdlib.h> 84 #include <string.h> 85 #include <syslog.h> 86 #include <time.h> 87 #include <unistd.h> 88 #include <libutil.h> 89 #ifdef LOGIN_CAP 90 #include <login_cap.h> 91 #endif 92 93 #ifdef SKEY 94 #include <skey.h> 95 #endif 96 97 #if !defined(NOPAM) 98 #include <security/pam_appl.h> 99 #endif 100 101 #include "pathnames.h" 102 #include "extern.h" 103 104 #if __STDC__ 105 #include <stdarg.h> 106 #else 107 #include <varargs.h> 108 #endif 109 110 static char version[] = "Version 6.00LS"; 111 #undef main 112 113 extern off_t restart_point; 114 extern char cbuf[]; 115 116 struct sockaddr_in server_addr; 117 struct sockaddr_in ctrl_addr; 118 struct sockaddr_in data_source; 119 struct sockaddr_in data_dest; 120 struct sockaddr_in his_addr; 121 struct sockaddr_in pasv_addr; 122 123 int daemon_mode; 124 int data; 125 jmp_buf errcatch, urgcatch; 126 int logged_in; 127 struct passwd *pw; 128 int debug; 129 int timeout = 900; /* timeout after 15 minutes of inactivity */ 130 int maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */ 131 int logging; 132 int restricted_data_ports = 1; 133 int paranoid = 1; /* be extra careful about security */ 134 int anon_only = 0; /* Only anonymous ftp allowed */ 135 int guest; 136 int dochroot; 137 int stats; 138 int statfd = -1; 139 int type; 140 int form; 141 int stru; /* avoid C keyword */ 142 int mode; 143 int usedefault = 1; /* for data transfers */ 144 int pdata = -1; /* for passive mode */ 145 sig_atomic_t transflag; 146 off_t file_size; 147 off_t byte_count; 148 #if !defined(CMASK) || CMASK == 0 149 #undef CMASK 150 #define CMASK 027 151 #endif 152 int defumask = CMASK; /* default umask value */ 153 char tmpline[7]; 154 char *hostname; 155 #ifdef VIRTUAL_HOSTING 156 char *ftpuser; 157 158 static struct ftphost { 159 struct ftphost *next; 160 struct in_addr hostaddr; 161 char *hostname; 162 char *anonuser; 163 char *statfile; 164 char *welcome; 165 char *loginmsg; 166 } *thishost, *firsthost; 167 168 #endif 169 char remotehost[MAXHOSTNAMELEN]; 170 char *ident = NULL; 171 172 static char ttyline[20]; 173 char *tty = ttyline; /* for klogin */ 174 175 #if !defined(NOPAM) 176 static int auth_pam __P((struct passwd**, const char*)); 177 #endif 178 179 struct in_addr bind_address; 180 char *pid_file = NULL; 181 182 /* 183 * Timeout intervals for retrying connections 184 * to hosts that don't accept PORT cmds. This 185 * is a kludge, but given the problems with TCP... 186 */ 187 #define SWAITMAX 90 /* wait at most 90 seconds */ 188 #define SWAITINT 5 /* interval between retries */ 189 190 int swaitmax = SWAITMAX; 191 int swaitint = SWAITINT; 192 193 #ifdef SETPROCTITLE 194 #ifdef OLD_SETPROCTITLE 195 char **Argv = NULL; /* pointer to argument vector */ 196 char *LastArgv = NULL; /* end of argv */ 197 #endif /* OLD_SETPROCTITLE */ 198 char proctitle[LINE_MAX]; /* initial part of title */ 199 #endif /* SETPROCTITLE */ 200 201 #ifdef SKEY 202 int pwok = 0; 203 char addr_string[20]; /* XXX */ 204 #endif 205 206 #define LOGCMD(cmd, file) \ 207 if (logging > 1) \ 208 syslog(LOG_INFO,"%s %s%s", cmd, \ 209 *(file) == '/' ? "" : curdir(), file); 210 #define LOGCMD2(cmd, file1, file2) \ 211 if (logging > 1) \ 212 syslog(LOG_INFO,"%s %s%s %s%s", cmd, \ 213 *(file1) == '/' ? "" : curdir(), file1, \ 214 *(file2) == '/' ? "" : curdir(), file2); 215 #define LOGBYTES(cmd, file, cnt) \ 216 if (logging > 1) { \ 217 if (cnt == (off_t)-1) \ 218 syslog(LOG_INFO,"%s %s%s", cmd, \ 219 *(file) == '/' ? "" : curdir(), file); \ 220 else \ 221 syslog(LOG_INFO, "%s %s%s = %qd bytes", \ 222 cmd, (*(file) == '/') ? "" : curdir(), file, cnt); \ 223 } 224 225 #ifdef VIRTUAL_HOSTING 226 static void inithosts __P((void)); 227 static void selecthost __P((struct in_addr *)); 228 #endif 229 static void ack __P((char *)); 230 static void myoob __P((int)); 231 static int checkuser __P((char *, char *, int)); 232 static FILE *dataconn __P((char *, off_t, char *)); 233 static void dolog __P((struct sockaddr_in *)); 234 static char *curdir __P((void)); 235 static void end_login __P((void)); 236 static FILE *getdatasock __P((char *)); 237 static char *gunique __P((char *)); 238 static void lostconn __P((int)); 239 static int receive_data __P((FILE *, FILE *)); 240 static void send_data __P((FILE *, FILE *, off_t, off_t, int)); 241 static struct passwd * 242 sgetpwnam __P((char *)); 243 static char *sgetsave __P((char *)); 244 static void reapchild __P((int)); 245 static void logxfer __P((char *, long, long)); 246 247 static char * 248 curdir() 249 { 250 static char path[MAXPATHLEN+1+1]; /* path + '/' + '\0' */ 251 252 if (getcwd(path, sizeof(path)-2) == NULL) 253 return (""); 254 if (path[1] != '\0') /* special case for root dir. */ 255 strcat(path, "/"); 256 /* For guest account, skip / since it's chrooted */ 257 return (guest ? path+1 : path); 258 } 259 260 int 261 main(argc, argv, envp) 262 int argc; 263 char *argv[]; 264 char **envp; 265 { 266 int addrlen, ch, on = 1, tos; 267 char *cp, line[LINE_MAX]; 268 FILE *fd; 269 270 tzset(); /* in case no timezone database in ~ftp */ 271 272 #ifdef OLD_SETPROCTITLE 273 /* 274 * Save start and extent of argv for setproctitle. 275 */ 276 Argv = argv; 277 while (*envp) 278 envp++; 279 LastArgv = envp[-1] + strlen(envp[-1]); 280 #endif /* OLD_SETPROCTITLE */ 281 282 283 bind_address.s_addr = htonl(INADDR_ANY); 284 while ((ch = getopt(argc, argv, "AdlDSURt:T:u:va:p:")) != -1) { 285 switch (ch) { 286 case 'D': 287 daemon_mode++; 288 break; 289 290 case 'd': 291 debug++; 292 break; 293 294 case 'l': 295 logging++; /* > 1 == extra logging */ 296 break; 297 298 case 'R': 299 paranoid = 0; 300 break; 301 302 case 'S': 303 stats++; 304 break; 305 306 case 'T': 307 maxtimeout = atoi(optarg); 308 if (timeout > maxtimeout) 309 timeout = maxtimeout; 310 break; 311 312 case 't': 313 timeout = atoi(optarg); 314 if (maxtimeout < timeout) 315 maxtimeout = timeout; 316 break; 317 318 case 'U': 319 restricted_data_ports = 0; 320 break; 321 322 case 'a': 323 if (!inet_aton(optarg, &bind_address)) 324 errx(1, "invalid address for -a"); 325 break; 326 327 case 'p': 328 pid_file = optarg; 329 break; 330 331 case 'u': 332 { 333 long val = 0; 334 335 val = strtol(optarg, &optarg, 8); 336 if (*optarg != '\0' || val < 0) 337 warnx("bad value for -u"); 338 else 339 defumask = val; 340 break; 341 } 342 case 'A': 343 anon_only = 1; 344 break; 345 346 case 'v': 347 debug = 1; 348 break; 349 350 default: 351 warnx("unknown flag -%c ignored", optopt); 352 break; 353 } 354 } 355 356 #ifdef VIRTUAL_HOSTING 357 inithosts(); 358 #endif 359 (void) freopen(_PATH_DEVNULL, "w", stderr); 360 361 /* 362 * LOG_NDELAY sets up the logging connection immediately, 363 * necessary for anonymous ftp's that chroot and can't do it later. 364 */ 365 openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP); 366 367 if (daemon_mode) { 368 int ctl_sock, fd; 369 struct servent *sv; 370 371 /* 372 * Detach from parent. 373 */ 374 if (daemon(1, 1) < 0) { 375 syslog(LOG_ERR, "failed to become a daemon"); 376 exit(1); 377 } 378 (void) signal(SIGCHLD, reapchild); 379 /* 380 * Get port number for ftp/tcp. 381 */ 382 sv = getservbyname("ftp", "tcp"); 383 if (sv == NULL) { 384 syslog(LOG_ERR, "getservbyname for ftp failed"); 385 exit(1); 386 } 387 /* 388 * Open a socket, bind it to the FTP port, and start 389 * listening. 390 */ 391 ctl_sock = socket(AF_INET, SOCK_STREAM, 0); 392 if (ctl_sock < 0) { 393 syslog(LOG_ERR, "control socket: %m"); 394 exit(1); 395 } 396 if (setsockopt(ctl_sock, SOL_SOCKET, SO_REUSEADDR, 397 (char *)&on, sizeof(on)) < 0) 398 syslog(LOG_ERR, "control setsockopt: %m");; 399 server_addr.sin_family = AF_INET; 400 server_addr.sin_addr = bind_address; 401 server_addr.sin_port = sv->s_port; 402 if (bind(ctl_sock, (struct sockaddr *)&server_addr, sizeof(server_addr))) { 403 syslog(LOG_ERR, "control bind: %m"); 404 exit(1); 405 } 406 if (listen(ctl_sock, 32) < 0) { 407 syslog(LOG_ERR, "control listen: %m"); 408 exit(1); 409 } 410 /* 411 * Atomically write process ID 412 */ 413 if (pid_file) 414 { 415 int fd; 416 char buf[20]; 417 418 fd = open(pid_file, O_CREAT | O_WRONLY | O_TRUNC 419 | O_NONBLOCK | O_EXLOCK, 0644); 420 if (fd < 0) { 421 if (errno == EAGAIN) 422 errx(1, "%s: file locked", pid_file); 423 else 424 err(1, "%s", pid_file); 425 } 426 snprintf(buf, sizeof(buf), 427 "%lu\n", (unsigned long) getpid()); 428 if (write(fd, buf, strlen(buf)) < 0) 429 err(1, "%s: write", pid_file); 430 /* Leave the pid file open and locked */ 431 } 432 /* 433 * Loop forever accepting connection requests and forking off 434 * children to handle them. 435 */ 436 while (1) { 437 addrlen = sizeof(his_addr); 438 fd = accept(ctl_sock, (struct sockaddr *)&his_addr, &addrlen); 439 if (fork() == 0) { 440 /* child */ 441 (void) dup2(fd, 0); 442 (void) dup2(fd, 1); 443 close(ctl_sock); 444 break; 445 } 446 close(fd); 447 } 448 } else { 449 addrlen = sizeof(his_addr); 450 if (getpeername(0, (struct sockaddr *)&his_addr, &addrlen) < 0) { 451 syslog(LOG_ERR, "getpeername (%s): %m",argv[0]); 452 exit(1); 453 } 454 } 455 456 (void) signal(SIGCHLD, SIG_IGN); 457 (void) signal(SIGPIPE, lostconn); 458 if (signal(SIGURG, myoob) == SIG_ERR) 459 syslog(LOG_ERR, "signal: %m"); 460 461 #ifdef SKEY 462 strncpy(addr_string, inet_ntoa(his_addr.sin_addr), sizeof(addr_string)); 463 #endif 464 addrlen = sizeof(ctrl_addr); 465 if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) { 466 syslog(LOG_ERR, "getsockname (%s): %m",argv[0]); 467 exit(1); 468 } 469 #ifdef VIRTUAL_HOSTING 470 /* select our identity from virtual host table */ 471 selecthost(&ctrl_addr.sin_addr); 472 #endif 473 #ifdef IP_TOS 474 tos = IPTOS_LOWDELAY; 475 if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) 476 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); 477 #endif 478 /* 479 * Disable Nagle on the control channel so that we don't have to wait 480 * for peer's ACK before issuing our next reply. 481 */ 482 if (setsockopt(0, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) 483 syslog(LOG_WARNING, "control setsockopt TCP_NODELAY: %m"); 484 485 data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1); 486 487 /* set this here so klogin can use it... */ 488 (void)snprintf(ttyline, sizeof(ttyline), "ftp%d", getpid()); 489 490 /* Try to handle urgent data inline */ 491 #ifdef SO_OOBINLINE 492 if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) < 0) 493 syslog(LOG_ERR, "setsockopt: %m"); 494 #endif 495 496 #ifdef F_SETOWN 497 if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1) 498 syslog(LOG_ERR, "fcntl F_SETOWN: %m"); 499 #endif 500 dolog(&his_addr); 501 /* 502 * Set up default state 503 */ 504 data = -1; 505 type = TYPE_A; 506 form = FORM_N; 507 stru = STRU_F; 508 mode = MODE_S; 509 tmpline[0] = '\0'; 510 511 /* If logins are disabled, print out the message. */ 512 if ((fd = fopen(_PATH_NOLOGIN,"r")) != NULL) { 513 while (fgets(line, sizeof(line), fd) != NULL) { 514 if ((cp = strchr(line, '\n')) != NULL) 515 *cp = '\0'; 516 lreply(530, "%s", line); 517 } 518 (void) fflush(stdout); 519 (void) fclose(fd); 520 reply(530, "System not available."); 521 exit(0); 522 } 523 #ifdef VIRTUAL_HOSTING 524 if ((fd = fopen(thishost->welcome, "r")) != NULL) { 525 #else 526 if ((fd = fopen(_PATH_FTPWELCOME, "r")) != NULL) { 527 #endif 528 while (fgets(line, sizeof(line), fd) != NULL) { 529 if ((cp = strchr(line, '\n')) != NULL) 530 *cp = '\0'; 531 lreply(220, "%s", line); 532 } 533 (void) fflush(stdout); 534 (void) fclose(fd); 535 /* reply(220,) must follow */ 536 } 537 #ifndef VIRTUAL_HOSTING 538 if ((hostname = malloc(MAXHOSTNAMELEN)) == NULL) 539 fatal("Ran out of memory."); 540 (void) gethostname(hostname, MAXHOSTNAMELEN - 1); 541 hostname[MAXHOSTNAMELEN - 1] = '\0'; 542 #endif 543 reply(220, "%s FTP server (%s) ready.", hostname, version); 544 (void) setjmp(errcatch); 545 for (;;) 546 (void) yyparse(); 547 /* NOTREACHED */ 548 } 549 550 static void 551 lostconn(signo) 552 int signo; 553 { 554 555 if (debug) 556 syslog(LOG_DEBUG, "lost connection"); 557 dologout(1); 558 } 559 560 #ifdef VIRTUAL_HOSTING 561 /* 562 * read in virtual host tables (if they exist) 563 */ 564 565 static void 566 inithosts() 567 { 568 FILE *fp; 569 char *cp; 570 struct hostent *hp; 571 struct ftphost *hrp, *lhrp; 572 char line[1024]; 573 574 /* 575 * Fill in the default host information 576 */ 577 if (gethostname(line, sizeof(line)) < 0) 578 line[0] = '\0'; 579 if ((hrp = malloc(sizeof(struct ftphost))) == NULL || 580 (hrp->hostname = strdup(line)) == NULL) 581 fatal("Ran out of memory."); 582 memset(&hrp->hostaddr, 0, sizeof hrp->hostaddr); 583 if ((hp = gethostbyname(hrp->hostname)) != NULL) 584 (void) memcpy(&hrp->hostaddr, 585 hp->h_addr_list[0], 586 sizeof(hrp->hostaddr)); 587 hrp->statfile = _PATH_FTPDSTATFILE; 588 hrp->welcome = _PATH_FTPWELCOME; 589 hrp->loginmsg = _PATH_FTPLOGINMESG; 590 hrp->anonuser = "ftp"; 591 hrp->next = NULL; 592 thishost = firsthost = lhrp = hrp; 593 if ((fp = fopen(_PATH_FTPHOSTS, "r")) != NULL) { 594 while (fgets(line, sizeof(line), fp) != NULL) { 595 int i; 596 597 if ((cp = strchr(line, '\n')) == NULL) { 598 /* ignore long lines */ 599 while (fgets(line, sizeof(line), fp) != NULL && 600 strchr(line, '\n') == NULL) 601 ; 602 continue; 603 } 604 *cp = '\0'; 605 cp = strtok(line, " \t"); 606 /* skip comments and empty lines */ 607 if (cp == NULL || line[0] == '#') 608 continue; 609 /* first, try a standard gethostbyname() */ 610 if ((hp = gethostbyname(cp)) == NULL) 611 continue; 612 for (hrp = firsthost; hrp != NULL; hrp = hrp->next) { 613 if (memcmp(&hrp->hostaddr, 614 hp->h_addr_list[0], 615 sizeof(hrp->hostaddr)) == 0) 616 break; 617 } 618 if (hrp == NULL) { 619 if ((hrp = malloc(sizeof(struct ftphost))) == NULL) 620 continue; 621 /* defaults */ 622 hrp->statfile = _PATH_FTPDSTATFILE; 623 hrp->welcome = _PATH_FTPWELCOME; 624 hrp->loginmsg = _PATH_FTPLOGINMESG; 625 hrp->anonuser = "ftp"; 626 hrp->next = NULL; 627 lhrp->next = hrp; 628 lhrp = hrp; 629 } 630 (void) memcpy(&hrp->hostaddr, 631 hp->h_addr_list[0], 632 sizeof(hrp->hostaddr)); 633 /* 634 * determine hostname to use. 635 * force defined name if it is a valid alias 636 * otherwise fallback to primary hostname 637 */ 638 if ((hp = gethostbyaddr((char*)&hrp->hostaddr, 639 sizeof(hrp->hostaddr), 640 AF_INET)) != NULL) { 641 if (strcmp(cp, hp->h_name) != 0) { 642 if (hp->h_aliases == NULL) 643 cp = hp->h_name; 644 else { 645 i = 0; 646 while (hp->h_aliases[i] && 647 strcmp(cp, hp->h_aliases[i]) != 0) 648 ++i; 649 if (hp->h_aliases[i] == NULL) 650 cp = hp->h_name; 651 } 652 } 653 } 654 hrp->hostname = strdup(cp); 655 /* ok, now we now peel off the rest */ 656 i = 0; 657 while (i < 4 && (cp = strtok(NULL, " \t")) != NULL) { 658 if (*cp != '-' && (cp = strdup(cp)) != NULL) { 659 switch (i) { 660 case 0: /* anon user permissions */ 661 hrp->anonuser = cp; 662 break; 663 case 1: /* statistics file */ 664 hrp->statfile = cp; 665 break; 666 case 2: /* welcome message */ 667 hrp->welcome = cp; 668 break; 669 case 3: /* login message */ 670 hrp->loginmsg = cp; 671 break; 672 } 673 } 674 ++i; 675 } 676 } 677 (void) fclose(fp); 678 } 679 } 680 681 static void 682 selecthost(a) 683 struct in_addr *a; 684 { 685 struct ftphost *hrp; 686 687 hrp = thishost = firsthost; /* default */ 688 while (hrp != NULL) { 689 if (memcmp(a, &hrp->hostaddr, sizeof(hrp->hostaddr)) == 0) { 690 thishost = hrp; 691 break; 692 } 693 hrp = hrp->next; 694 } 695 /* setup static variables as appropriate */ 696 hostname = thishost->hostname; 697 ftpuser = thishost->anonuser; 698 } 699 #endif 700 701 /* 702 * Helper function for sgetpwnam(). 703 */ 704 static char * 705 sgetsave(s) 706 char *s; 707 { 708 char *new = malloc((unsigned) strlen(s) + 1); 709 710 if (new == NULL) { 711 perror_reply(421, "Local resource failure: malloc"); 712 dologout(1); 713 /* NOTREACHED */ 714 } 715 (void) strcpy(new, s); 716 return (new); 717 } 718 719 /* 720 * Save the result of a getpwnam. Used for USER command, since 721 * the data returned must not be clobbered by any other command 722 * (e.g., globbing). 723 */ 724 static struct passwd * 725 sgetpwnam(name) 726 char *name; 727 { 728 static struct passwd save; 729 struct passwd *p; 730 731 if ((p = getpwnam(name)) == NULL) 732 return (p); 733 if (save.pw_name) { 734 free(save.pw_name); 735 free(save.pw_passwd); 736 free(save.pw_gecos); 737 free(save.pw_dir); 738 free(save.pw_shell); 739 } 740 save = *p; 741 save.pw_name = sgetsave(p->pw_name); 742 save.pw_passwd = sgetsave(p->pw_passwd); 743 save.pw_gecos = sgetsave(p->pw_gecos); 744 save.pw_dir = sgetsave(p->pw_dir); 745 save.pw_shell = sgetsave(p->pw_shell); 746 return (&save); 747 } 748 749 static int login_attempts; /* number of failed login attempts */ 750 static int askpasswd; /* had user command, ask for passwd */ 751 static char curname[10]; /* current USER name */ 752 753 /* 754 * USER command. 755 * Sets global passwd pointer pw if named account exists and is acceptable; 756 * sets askpasswd if a PASS command is expected. If logged in previously, 757 * need to reset state. If name is "ftp" or "anonymous", the name is not in 758 * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return. 759 * If account doesn't exist, ask for passwd anyway. Otherwise, check user 760 * requesting login privileges. Disallow anyone who does not have a standard 761 * shell as returned by getusershell(). Disallow anyone mentioned in the file 762 * _PATH_FTPUSERS to allow people such as root and uucp to be avoided. 763 */ 764 void 765 user(name) 766 char *name; 767 { 768 char *cp, *shell; 769 770 if (logged_in) { 771 if (guest) { 772 reply(530, "Can't change user from guest login."); 773 return; 774 } else if (dochroot) { 775 reply(530, "Can't change user from chroot user."); 776 return; 777 } 778 end_login(); 779 } 780 781 guest = 0; 782 if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) { 783 if (checkuser(_PATH_FTPUSERS, "ftp", 0) || 784 checkuser(_PATH_FTPUSERS, "anonymous", 0)) 785 reply(530, "User %s access denied.", name); 786 #ifdef VIRTUAL_HOSTING 787 else if ((pw = sgetpwnam(thishost->anonuser)) != NULL) { 788 #else 789 else if ((pw = sgetpwnam("ftp")) != NULL) { 790 #endif 791 guest = 1; 792 askpasswd = 1; 793 reply(331, 794 "Guest login ok, send your email address as password."); 795 } else 796 reply(530, "User %s unknown.", name); 797 if (!askpasswd && logging) 798 syslog(LOG_NOTICE, 799 "ANONYMOUS FTP LOGIN REFUSED FROM %s", remotehost); 800 return; 801 } 802 if (anon_only != 0) { 803 reply(530, "Sorry, only anonymous ftp allowed."); 804 return; 805 } 806 807 if ((pw = sgetpwnam(name))) { 808 if ((shell = pw->pw_shell) == NULL || *shell == 0) 809 shell = _PATH_BSHELL; 810 while ((cp = getusershell()) != NULL) 811 if (strcmp(cp, shell) == 0) 812 break; 813 endusershell(); 814 815 if (cp == NULL || checkuser(_PATH_FTPUSERS, name, 1)) { 816 reply(530, "User %s access denied.", name); 817 if (logging) 818 syslog(LOG_NOTICE, 819 "FTP LOGIN REFUSED FROM %s, %s", 820 remotehost, name); 821 pw = (struct passwd *) NULL; 822 return; 823 } 824 } 825 if (logging) 826 strncpy(curname, name, sizeof(curname)-1); 827 #ifdef SKEY 828 pwok = skeyaccess(name, NULL, remotehost, addr_string); 829 reply(331, "%s", skey_challenge(name, pw, pwok)); 830 #else 831 reply(331, "Password required for %s.", name); 832 #endif 833 askpasswd = 1; 834 /* 835 * Delay before reading passwd after first failed 836 * attempt to slow down passwd-guessing programs. 837 */ 838 if (login_attempts) 839 sleep((unsigned) login_attempts); 840 } 841 842 /* 843 * Check if a user is in the file "fname" 844 */ 845 static int 846 checkuser(fname, name, pwset) 847 char *fname; 848 char *name; 849 int pwset; 850 { 851 FILE *fd; 852 int found = 0; 853 char *p, line[BUFSIZ]; 854 855 if ((fd = fopen(fname, "r")) != NULL) { 856 while (!found && fgets(line, sizeof(line), fd) != NULL) 857 if ((p = strchr(line, '\n')) != NULL) { 858 *p = '\0'; 859 if (line[0] == '#') 860 continue; 861 /* 862 * if first chr is '@', check group membership 863 */ 864 if (line[0] == '@') { 865 int i = 0; 866 struct group *grp; 867 868 if ((grp = getgrnam(line+1)) == NULL) 869 continue; 870 /* 871 * Check user's default group 872 */ 873 if (pwset && grp->gr_gid == pw->pw_gid) 874 found = 1; 875 /* 876 * Check supplementary groups 877 */ 878 while (!found && grp->gr_mem[i]) 879 found = strcmp(name, 880 grp->gr_mem[i++]) 881 == 0; 882 } 883 /* 884 * Otherwise, just check for username match 885 */ 886 else 887 found = strcmp(line, name) == 0; 888 } 889 (void) fclose(fd); 890 } 891 return (found); 892 } 893 894 /* 895 * Terminate login as previous user, if any, resetting state; 896 * used when USER command is given or login fails. 897 */ 898 static void 899 end_login() 900 { 901 902 (void) seteuid((uid_t)0); 903 if (logged_in) 904 ftpd_logwtmp(ttyline, "", ""); 905 pw = NULL; 906 #ifdef LOGIN_CAP 907 setusercontext(NULL, getpwuid(0), (uid_t)0, 908 LOGIN_SETPRIORITY|LOGIN_SETRESOURCES|LOGIN_SETUMASK); 909 #endif 910 logged_in = 0; 911 guest = 0; 912 dochroot = 0; 913 } 914 915 #if !defined(NOPAM) 916 917 /* 918 * the following code is stolen from imap-uw PAM authentication module and 919 * login.c 920 */ 921 #define COPY_STRING(s) (s ? strdup(s) : NULL) 922 923 struct cred_t { 924 const char *uname; /* user name */ 925 const char *pass; /* password */ 926 }; 927 typedef struct cred_t cred_t; 928 929 static int 930 auth_conv(int num_msg, const struct pam_message **msg, 931 struct pam_response **resp, void *appdata) 932 { 933 int i; 934 cred_t *cred = (cred_t *) appdata; 935 struct pam_response *reply = 936 malloc(sizeof(struct pam_response) * num_msg); 937 938 for (i = 0; i < num_msg; i++) { 939 switch (msg[i]->msg_style) { 940 case PAM_PROMPT_ECHO_ON: /* assume want user name */ 941 reply[i].resp_retcode = PAM_SUCCESS; 942 reply[i].resp = COPY_STRING(cred->uname); 943 /* PAM frees resp. */ 944 break; 945 case PAM_PROMPT_ECHO_OFF: /* assume want password */ 946 reply[i].resp_retcode = PAM_SUCCESS; 947 reply[i].resp = COPY_STRING(cred->pass); 948 /* PAM frees resp. */ 949 break; 950 case PAM_TEXT_INFO: 951 case PAM_ERROR_MSG: 952 reply[i].resp_retcode = PAM_SUCCESS; 953 reply[i].resp = NULL; 954 break; 955 default: /* unknown message style */ 956 free(reply); 957 return PAM_CONV_ERR; 958 } 959 } 960 961 *resp = reply; 962 return PAM_SUCCESS; 963 } 964 965 /* 966 * Attempt to authenticate the user using PAM. Returns 0 if the user is 967 * authenticated, or 1 if not authenticated. If some sort of PAM system 968 * error occurs (e.g., the "/etc/pam.conf" file is missing) then this 969 * function returns -1. This can be used as an indication that we should 970 * fall back to a different authentication mechanism. 971 */ 972 static int 973 auth_pam(struct passwd **ppw, const char *pass) 974 { 975 pam_handle_t *pamh = NULL; 976 const char *tmpl_user; 977 const void *item; 978 int rval; 979 int e; 980 cred_t auth_cred = { (*ppw)->pw_name, pass }; 981 struct pam_conv conv = { &auth_conv, &auth_cred }; 982 983 e = pam_start("ftpd", (*ppw)->pw_name, &conv, &pamh); 984 if (e != PAM_SUCCESS) { 985 syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, e)); 986 return -1; 987 } 988 989 e = pam_authenticate(pamh, 0); 990 switch (e) { 991 case PAM_SUCCESS: 992 /* 993 * With PAM we support the concept of a "template" 994 * user. The user enters a login name which is 995 * authenticated by PAM, usually via a remote service 996 * such as RADIUS or TACACS+. If authentication 997 * succeeds, a different but related "template" name 998 * is used for setting the credentials, shell, and 999 * home directory. The name the user enters need only 1000 * exist on the remote authentication server, but the 1001 * template name must be present in the local password 1002 * database. 1003 * 1004 * This is supported by two various mechanisms in the 1005 * individual modules. However, from the application's 1006 * point of view, the template user is always passed 1007 * back as a changed value of the PAM_USER item. 1008 */ 1009 if ((e = pam_get_item(pamh, PAM_USER, &item)) == 1010 PAM_SUCCESS) { 1011 tmpl_user = (const char *) item; 1012 if (strcmp((*ppw)->pw_name, tmpl_user) != 0) 1013 *ppw = getpwnam(tmpl_user); 1014 } else 1015 syslog(LOG_ERR, "Couldn't get PAM_USER: %s", 1016 pam_strerror(pamh, e)); 1017 rval = 0; 1018 break; 1019 1020 case PAM_AUTH_ERR: 1021 case PAM_USER_UNKNOWN: 1022 case PAM_MAXTRIES: 1023 rval = 1; 1024 break; 1025 1026 default: 1027 syslog(LOG_ERR, "auth_pam: %s", pam_strerror(pamh, e)); 1028 rval = -1; 1029 break; 1030 } 1031 1032 if ((e = pam_end(pamh, e)) != PAM_SUCCESS) { 1033 syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e)); 1034 rval = -1; 1035 } 1036 return rval; 1037 } 1038 1039 #endif /* !defined(NOPAM) */ 1040 1041 void 1042 pass(passwd) 1043 char *passwd; 1044 { 1045 int rval; 1046 FILE *fd; 1047 #ifdef LOGIN_CAP 1048 login_cap_t *lc = NULL; 1049 #endif 1050 1051 if (logged_in || askpasswd == 0) { 1052 reply(503, "Login with USER first."); 1053 return; 1054 } 1055 askpasswd = 0; 1056 if (!guest) { /* "ftp" is only account allowed no password */ 1057 if (pw == NULL) { 1058 rval = 1; /* failure below */ 1059 goto skip; 1060 } 1061 #if !defined(NOPAM) 1062 rval = auth_pam(&pw, passwd); 1063 if (rval >= 0) 1064 goto skip; 1065 #endif 1066 #ifdef SKEY 1067 rval = strcmp(skey_crypt(passwd, pw->pw_passwd, pw, pwok), 1068 pw->pw_passwd); 1069 pwok = 0; 1070 #else 1071 rval = strcmp(crypt(passwd, pw->pw_passwd), pw->pw_passwd); 1072 #endif 1073 /* The strcmp does not catch null passwords! */ 1074 if (*pw->pw_passwd == '\0' || 1075 (pw->pw_expire && time(NULL) >= pw->pw_expire)) 1076 rval = 1; /* failure */ 1077 skip: 1078 /* 1079 * If rval == 1, the user failed the authentication check 1080 * above. If rval == 0, either PAM or local authentication 1081 * succeeded. 1082 */ 1083 if (rval) { 1084 reply(530, "Login incorrect."); 1085 if (logging) 1086 syslog(LOG_NOTICE, 1087 "FTP LOGIN FAILED FROM %s, %s", 1088 remotehost, curname); 1089 pw = NULL; 1090 if (login_attempts++ >= 5) { 1091 syslog(LOG_NOTICE, 1092 "repeated login failures from %s", 1093 remotehost); 1094 exit(0); 1095 } 1096 return; 1097 } 1098 } 1099 login_attempts = 0; /* this time successful */ 1100 if (setegid((gid_t)pw->pw_gid) < 0) { 1101 reply(550, "Can't set gid."); 1102 return; 1103 } 1104 /* May be overridden by login.conf */ 1105 (void) umask(defumask); 1106 #ifdef LOGIN_CAP 1107 if ((lc = login_getpwclass(pw)) != NULL) { 1108 char remote_ip[MAXHOSTNAMELEN]; 1109 1110 strncpy(remote_ip, inet_ntoa(his_addr.sin_addr), 1111 sizeof(remote_ip) - 1); 1112 remote_ip[sizeof(remote_ip) - 1] = 0; 1113 if (!auth_hostok(lc, remotehost, remote_ip)) { 1114 syslog(LOG_INFO|LOG_AUTH, 1115 "FTP LOGIN FAILED (HOST) as %s: permission denied.", 1116 pw->pw_name); 1117 reply(530, "Permission denied.\n"); 1118 pw = NULL; 1119 return; 1120 } 1121 if (!auth_timeok(lc, time(NULL))) { 1122 reply(530, "Login not available right now.\n"); 1123 pw = NULL; 1124 return; 1125 } 1126 } 1127 setusercontext(lc, pw, (uid_t)0, 1128 LOGIN_SETLOGIN|LOGIN_SETGROUP|LOGIN_SETPRIORITY| 1129 LOGIN_SETRESOURCES|LOGIN_SETUMASK); 1130 #else 1131 setlogin(pw->pw_name); 1132 (void) initgroups(pw->pw_name, pw->pw_gid); 1133 #endif 1134 1135 /* open wtmp before chroot */ 1136 ftpd_logwtmp(ttyline, pw->pw_name, remotehost); 1137 logged_in = 1; 1138 1139 if (guest && stats && statfd < 0) 1140 #ifdef VIRTUAL_HOSTING 1141 if ((statfd = open(thishost->statfile, O_WRONLY|O_APPEND)) < 0) 1142 #else 1143 if ((statfd = open(_PATH_FTPDSTATFILE, O_WRONLY|O_APPEND)) < 0) 1144 #endif 1145 stats = 0; 1146 1147 dochroot = 1148 #ifdef LOGIN_CAP /* Allow login.conf configuration as well */ 1149 login_getcapbool(lc, "ftp-chroot", 0) || 1150 #endif 1151 checkuser(_PATH_FTPCHROOT, pw->pw_name, 1); 1152 if (guest) { 1153 /* 1154 * We MUST do a chdir() after the chroot. Otherwise 1155 * the old current directory will be accessible as "." 1156 * outside the new root! 1157 */ 1158 if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) { 1159 reply(550, "Can't set guest privileges."); 1160 goto bad; 1161 } 1162 } else if (dochroot) { 1163 if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) { 1164 reply(550, "Can't change root."); 1165 goto bad; 1166 } 1167 } else if (chdir(pw->pw_dir) < 0) { 1168 if (chdir("/") < 0) { 1169 reply(530, "User %s: can't change directory to %s.", 1170 pw->pw_name, pw->pw_dir); 1171 goto bad; 1172 } else 1173 lreply(230, "No directory! Logging in with home=/"); 1174 } 1175 if (seteuid((uid_t)pw->pw_uid) < 0) { 1176 reply(550, "Can't set uid."); 1177 goto bad; 1178 } 1179 1180 /* 1181 * Display a login message, if it exists. 1182 * N.B. reply(230,) must follow the message. 1183 */ 1184 #ifdef VIRTUAL_HOSTING 1185 if ((fd = fopen(thishost->loginmsg, "r")) != NULL) { 1186 #else 1187 if ((fd = fopen(_PATH_FTPLOGINMESG, "r")) != NULL) { 1188 #endif 1189 char *cp, line[LINE_MAX]; 1190 1191 while (fgets(line, sizeof(line), fd) != NULL) { 1192 if ((cp = strchr(line, '\n')) != NULL) 1193 *cp = '\0'; 1194 lreply(230, "%s", line); 1195 } 1196 (void) fflush(stdout); 1197 (void) fclose(fd); 1198 } 1199 if (guest) { 1200 if (ident != NULL) 1201 free(ident); 1202 ident = strdup(passwd); 1203 if (ident == NULL) 1204 fatal("Ran out of memory."); 1205 1206 reply(230, "Guest login ok, access restrictions apply."); 1207 #ifdef SETPROCTITLE 1208 #ifdef VIRTUAL_HOSTING 1209 if (thishost != firsthost) 1210 snprintf(proctitle, sizeof(proctitle), 1211 "%s: anonymous(%s)/%.*s", remotehost, hostname, 1212 (int)(sizeof(proctitle) - sizeof(remotehost) - 1213 sizeof(": anonymous/")), passwd); 1214 else 1215 #endif 1216 snprintf(proctitle, sizeof(proctitle), 1217 "%s: anonymous/%.*s", remotehost, 1218 (int)(sizeof(proctitle) - sizeof(remotehost) - 1219 sizeof(": anonymous/")), passwd); 1220 setproctitle("%s", proctitle); 1221 #endif /* SETPROCTITLE */ 1222 if (logging) 1223 syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s", 1224 remotehost, passwd); 1225 } else { 1226 if (dochroot) 1227 reply(230, "User %s logged in, access restrictions apply.", 1228 pw->pw_name); 1229 else 1230 reply(230, "User %s logged in.", pw->pw_name); 1231 1232 #ifdef SETPROCTITLE 1233 snprintf(proctitle, sizeof(proctitle), 1234 "%s: %s", remotehost, pw->pw_name); 1235 setproctitle("%s", proctitle); 1236 #endif /* SETPROCTITLE */ 1237 if (logging) 1238 syslog(LOG_INFO, "FTP LOGIN FROM %s as %s", 1239 remotehost, pw->pw_name); 1240 } 1241 #ifdef LOGIN_CAP 1242 login_close(lc); 1243 #endif 1244 return; 1245 bad: 1246 /* Forget all about it... */ 1247 #ifdef LOGIN_CAP 1248 login_close(lc); 1249 #endif 1250 end_login(); 1251 } 1252 1253 void 1254 retrieve(cmd, name) 1255 char *cmd, *name; 1256 { 1257 FILE *fin, *dout; 1258 struct stat st; 1259 int (*closefunc) __P((FILE *)); 1260 time_t start; 1261 1262 if (cmd == 0) { 1263 fin = fopen(name, "r"), closefunc = fclose; 1264 st.st_size = 0; 1265 } else { 1266 char line[BUFSIZ]; 1267 1268 (void) snprintf(line, sizeof(line), cmd, name), name = line; 1269 fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose; 1270 st.st_size = -1; 1271 st.st_blksize = BUFSIZ; 1272 } 1273 if (fin == NULL) { 1274 if (errno != 0) { 1275 perror_reply(550, name); 1276 if (cmd == 0) { 1277 LOGCMD("get", name); 1278 } 1279 } 1280 return; 1281 } 1282 byte_count = -1; 1283 if (cmd == 0 && (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode))) { 1284 reply(550, "%s: not a plain file.", name); 1285 goto done; 1286 } 1287 if (restart_point) { 1288 if (type == TYPE_A) { 1289 off_t i, n; 1290 int c; 1291 1292 n = restart_point; 1293 i = 0; 1294 while (i++ < n) { 1295 if ((c=getc(fin)) == EOF) { 1296 perror_reply(550, name); 1297 goto done; 1298 } 1299 if (c == '\n') 1300 i++; 1301 } 1302 } else if (lseek(fileno(fin), restart_point, L_SET) < 0) { 1303 perror_reply(550, name); 1304 goto done; 1305 } 1306 } 1307 dout = dataconn(name, st.st_size, "w"); 1308 if (dout == NULL) 1309 goto done; 1310 time(&start); 1311 send_data(fin, dout, st.st_blksize, st.st_size, 1312 restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode)); 1313 if (cmd == 0 && guest && stats) 1314 logxfer(name, st.st_size, start); 1315 (void) fclose(dout); 1316 data = -1; 1317 pdata = -1; 1318 done: 1319 if (cmd == 0) 1320 LOGBYTES("get", name, byte_count); 1321 (*closefunc)(fin); 1322 } 1323 1324 void 1325 store(name, mode, unique) 1326 char *name, *mode; 1327 int unique; 1328 { 1329 FILE *fout, *din; 1330 struct stat st; 1331 int (*closefunc) __P((FILE *)); 1332 1333 if ((unique || guest) && stat(name, &st) == 0 && 1334 (name = gunique(name)) == NULL) { 1335 LOGCMD(*mode == 'w' ? "put" : "append", name); 1336 return; 1337 } 1338 1339 if (restart_point) 1340 mode = "r+"; 1341 fout = fopen(name, mode); 1342 closefunc = fclose; 1343 if (fout == NULL) { 1344 perror_reply(553, name); 1345 LOGCMD(*mode == 'w' ? "put" : "append", name); 1346 return; 1347 } 1348 byte_count = -1; 1349 if (restart_point) { 1350 if (type == TYPE_A) { 1351 off_t i, n; 1352 int c; 1353 1354 n = restart_point; 1355 i = 0; 1356 while (i++ < n) { 1357 if ((c=getc(fout)) == EOF) { 1358 perror_reply(550, name); 1359 goto done; 1360 } 1361 if (c == '\n') 1362 i++; 1363 } 1364 /* 1365 * We must do this seek to "current" position 1366 * because we are changing from reading to 1367 * writing. 1368 */ 1369 if (fseek(fout, 0L, L_INCR) < 0) { 1370 perror_reply(550, name); 1371 goto done; 1372 } 1373 } else if (lseek(fileno(fout), restart_point, L_SET) < 0) { 1374 perror_reply(550, name); 1375 goto done; 1376 } 1377 } 1378 din = dataconn(name, (off_t)-1, "r"); 1379 if (din == NULL) 1380 goto done; 1381 if (receive_data(din, fout) == 0) { 1382 if (unique) 1383 reply(226, "Transfer complete (unique file name:%s).", 1384 name); 1385 else 1386 reply(226, "Transfer complete."); 1387 } 1388 (void) fclose(din); 1389 data = -1; 1390 pdata = -1; 1391 done: 1392 LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count); 1393 (*closefunc)(fout); 1394 } 1395 1396 static FILE * 1397 getdatasock(mode) 1398 char *mode; 1399 { 1400 int on = 1, s, t, tries; 1401 1402 if (data >= 0) 1403 return (fdopen(data, mode)); 1404 (void) seteuid((uid_t)0); 1405 s = socket(AF_INET, SOCK_STREAM, 0); 1406 if (s < 0) 1407 goto bad; 1408 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 1409 (char *) &on, sizeof(on)) < 0) 1410 goto bad; 1411 /* anchor socket to avoid multi-homing problems */ 1412 data_source.sin_len = sizeof(struct sockaddr_in); 1413 data_source.sin_family = AF_INET; 1414 data_source.sin_addr = ctrl_addr.sin_addr; 1415 for (tries = 1; ; tries++) { 1416 if (bind(s, (struct sockaddr *)&data_source, 1417 sizeof(data_source)) >= 0) 1418 break; 1419 if (errno != EADDRINUSE || tries > 10) 1420 goto bad; 1421 sleep(tries); 1422 } 1423 (void) seteuid((uid_t)pw->pw_uid); 1424 #ifdef IP_TOS 1425 on = IPTOS_THROUGHPUT; 1426 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) 1427 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); 1428 #endif 1429 #ifdef TCP_NOPUSH 1430 /* 1431 * Turn off push flag to keep sender TCP from sending short packets 1432 * at the boundaries of each write(). Should probably do a SO_SNDBUF 1433 * to set the send buffer size as well, but that may not be desirable 1434 * in heavy-load situations. 1435 */ 1436 on = 1; 1437 if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, (char *)&on, sizeof on) < 0) 1438 syslog(LOG_WARNING, "setsockopt (TCP_NOPUSH): %m"); 1439 #endif 1440 #ifdef SO_SNDBUF 1441 on = 65536; 1442 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&on, sizeof on) < 0) 1443 syslog(LOG_WARNING, "setsockopt (SO_SNDBUF): %m"); 1444 #endif 1445 1446 return (fdopen(s, mode)); 1447 bad: 1448 /* Return the real value of errno (close may change it) */ 1449 t = errno; 1450 (void) seteuid((uid_t)pw->pw_uid); 1451 (void) close(s); 1452 errno = t; 1453 return (NULL); 1454 } 1455 1456 static FILE * 1457 dataconn(name, size, mode) 1458 char *name; 1459 off_t size; 1460 char *mode; 1461 { 1462 char sizebuf[32]; 1463 FILE *file; 1464 int retry = 0, tos; 1465 1466 file_size = size; 1467 byte_count = 0; 1468 if (size != (off_t) -1) 1469 (void) snprintf(sizebuf, sizeof(sizebuf), " (%qd bytes)", size); 1470 else 1471 *sizebuf = '\0'; 1472 if (pdata >= 0) { 1473 struct sockaddr_in from; 1474 int s, fromlen = sizeof(from); 1475 struct timeval timeout; 1476 fd_set set; 1477 1478 FD_ZERO(&set); 1479 FD_SET(pdata, &set); 1480 1481 timeout.tv_usec = 0; 1482 timeout.tv_sec = 120; 1483 1484 if (select(pdata+1, &set, (fd_set *) 0, (fd_set *) 0, &timeout) == 0 || 1485 (s = accept(pdata, (struct sockaddr *) &from, &fromlen)) < 0) { 1486 reply(425, "Can't open data connection."); 1487 (void) close(pdata); 1488 pdata = -1; 1489 return (NULL); 1490 } 1491 (void) close(pdata); 1492 pdata = s; 1493 #ifdef IP_TOS 1494 tos = IPTOS_THROUGHPUT; 1495 (void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, 1496 sizeof(int)); 1497 #endif 1498 reply(150, "Opening %s mode data connection for '%s'%s.", 1499 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); 1500 return (fdopen(pdata, mode)); 1501 } 1502 if (data >= 0) { 1503 reply(125, "Using existing data connection for '%s'%s.", 1504 name, sizebuf); 1505 usedefault = 1; 1506 return (fdopen(data, mode)); 1507 } 1508 if (usedefault) 1509 data_dest = his_addr; 1510 usedefault = 1; 1511 file = getdatasock(mode); 1512 if (file == NULL) { 1513 reply(425, "Can't create data socket (%s,%d): %s.", 1514 inet_ntoa(data_source.sin_addr), 1515 ntohs(data_source.sin_port), strerror(errno)); 1516 return (NULL); 1517 } 1518 data = fileno(file); 1519 while (connect(data, (struct sockaddr *)&data_dest, 1520 sizeof(data_dest)) < 0) { 1521 if (errno == EADDRINUSE && retry < swaitmax) { 1522 sleep((unsigned) swaitint); 1523 retry += swaitint; 1524 continue; 1525 } 1526 perror_reply(425, "Can't build data connection"); 1527 (void) fclose(file); 1528 data = -1; 1529 return (NULL); 1530 } 1531 reply(150, "Opening %s mode data connection for '%s'%s.", 1532 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); 1533 return (file); 1534 } 1535 1536 /* 1537 * Tranfer the contents of "instr" to "outstr" peer using the appropriate 1538 * encapsulation of the data subject to Mode, Structure, and Type. 1539 * 1540 * NB: Form isn't handled. 1541 */ 1542 static void 1543 send_data(instr, outstr, blksize, filesize, isreg) 1544 FILE *instr, *outstr; 1545 off_t blksize; 1546 off_t filesize; 1547 int isreg; 1548 { 1549 int c, cnt, filefd, netfd; 1550 char *buf, *bp; 1551 size_t len; 1552 1553 transflag++; 1554 if (setjmp(urgcatch)) { 1555 transflag = 0; 1556 return; 1557 } 1558 switch (type) { 1559 1560 case TYPE_A: 1561 while ((c = getc(instr)) != EOF) { 1562 byte_count++; 1563 if (c == '\n') { 1564 if (ferror(outstr)) 1565 goto data_err; 1566 (void) putc('\r', outstr); 1567 } 1568 (void) putc(c, outstr); 1569 } 1570 fflush(outstr); 1571 transflag = 0; 1572 if (ferror(instr)) 1573 goto file_err; 1574 if (ferror(outstr)) 1575 goto data_err; 1576 reply(226, "Transfer complete."); 1577 return; 1578 1579 case TYPE_I: 1580 case TYPE_L: 1581 /* 1582 * isreg is only set if we are not doing restart and we 1583 * are sending a regular file 1584 */ 1585 netfd = fileno(outstr); 1586 filefd = fileno(instr); 1587 1588 if (isreg && filesize < (off_t)16 * 1024 * 1024) { 1589 buf = mmap(0, filesize, PROT_READ, MAP_SHARED, filefd, 1590 (off_t)0); 1591 if (buf == MAP_FAILED) { 1592 syslog(LOG_WARNING, "mmap(%lu): %m", 1593 (unsigned long)filesize); 1594 goto oldway; 1595 } 1596 bp = buf; 1597 len = filesize; 1598 do { 1599 cnt = write(netfd, bp, len); 1600 len -= cnt; 1601 bp += cnt; 1602 if (cnt > 0) byte_count += cnt; 1603 } while(cnt > 0 && len > 0); 1604 1605 transflag = 0; 1606 munmap(buf, (size_t)filesize); 1607 if (cnt < 0) 1608 goto data_err; 1609 reply(226, "Transfer complete."); 1610 return; 1611 } 1612 1613 oldway: 1614 if ((buf = malloc((u_int)blksize)) == NULL) { 1615 transflag = 0; 1616 perror_reply(451, "Local resource failure: malloc"); 1617 return; 1618 } 1619 1620 while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 && 1621 write(netfd, buf, cnt) == cnt) 1622 byte_count += cnt; 1623 transflag = 0; 1624 (void)free(buf); 1625 if (cnt != 0) { 1626 if (cnt < 0) 1627 goto file_err; 1628 goto data_err; 1629 } 1630 reply(226, "Transfer complete."); 1631 return; 1632 default: 1633 transflag = 0; 1634 reply(550, "Unimplemented TYPE %d in send_data", type); 1635 return; 1636 } 1637 1638 data_err: 1639 transflag = 0; 1640 perror_reply(426, "Data connection"); 1641 return; 1642 1643 file_err: 1644 transflag = 0; 1645 perror_reply(551, "Error on input file"); 1646 } 1647 1648 /* 1649 * Transfer data from peer to "outstr" using the appropriate encapulation of 1650 * the data subject to Mode, Structure, and Type. 1651 * 1652 * N.B.: Form isn't handled. 1653 */ 1654 static int 1655 receive_data(instr, outstr) 1656 FILE *instr, *outstr; 1657 { 1658 int c; 1659 int cnt, bare_lfs; 1660 char buf[BUFSIZ]; 1661 1662 transflag++; 1663 if (setjmp(urgcatch)) { 1664 transflag = 0; 1665 return (-1); 1666 } 1667 1668 bare_lfs = 0; 1669 1670 switch (type) { 1671 1672 case TYPE_I: 1673 case TYPE_L: 1674 while ((cnt = read(fileno(instr), buf, sizeof(buf))) > 0) { 1675 if (write(fileno(outstr), buf, cnt) != cnt) 1676 goto file_err; 1677 byte_count += cnt; 1678 } 1679 if (cnt < 0) 1680 goto data_err; 1681 transflag = 0; 1682 return (0); 1683 1684 case TYPE_E: 1685 reply(553, "TYPE E not implemented."); 1686 transflag = 0; 1687 return (-1); 1688 1689 case TYPE_A: 1690 while ((c = getc(instr)) != EOF) { 1691 byte_count++; 1692 if (c == '\n') 1693 bare_lfs++; 1694 while (c == '\r') { 1695 if (ferror(outstr)) 1696 goto data_err; 1697 if ((c = getc(instr)) != '\n') { 1698 (void) putc ('\r', outstr); 1699 if (c == '\0' || c == EOF) 1700 goto contin2; 1701 } 1702 } 1703 (void) putc(c, outstr); 1704 contin2: ; 1705 } 1706 fflush(outstr); 1707 if (ferror(instr)) 1708 goto data_err; 1709 if (ferror(outstr)) 1710 goto file_err; 1711 transflag = 0; 1712 if (bare_lfs) { 1713 lreply(226, 1714 "WARNING! %d bare linefeeds received in ASCII mode", 1715 bare_lfs); 1716 (void)printf(" File may not have transferred correctly.\r\n"); 1717 } 1718 return (0); 1719 default: 1720 reply(550, "Unimplemented TYPE %d in receive_data", type); 1721 transflag = 0; 1722 return (-1); 1723 } 1724 1725 data_err: 1726 transflag = 0; 1727 perror_reply(426, "Data Connection"); 1728 return (-1); 1729 1730 file_err: 1731 transflag = 0; 1732 perror_reply(452, "Error writing file"); 1733 return (-1); 1734 } 1735 1736 void 1737 statfilecmd(filename) 1738 char *filename; 1739 { 1740 FILE *fin; 1741 int c; 1742 char line[LINE_MAX]; 1743 1744 (void)snprintf(line, sizeof(line), _PATH_LS " -lgA %s", filename); 1745 fin = ftpd_popen(line, "r"); 1746 lreply(211, "status of %s:", filename); 1747 while ((c = getc(fin)) != EOF) { 1748 if (c == '\n') { 1749 if (ferror(stdout)){ 1750 perror_reply(421, "control connection"); 1751 (void) ftpd_pclose(fin); 1752 dologout(1); 1753 /* NOTREACHED */ 1754 } 1755 if (ferror(fin)) { 1756 perror_reply(551, filename); 1757 (void) ftpd_pclose(fin); 1758 return; 1759 } 1760 (void) putc('\r', stdout); 1761 } 1762 (void) putc(c, stdout); 1763 } 1764 (void) ftpd_pclose(fin); 1765 reply(211, "End of Status"); 1766 } 1767 1768 void 1769 statcmd() 1770 { 1771 struct sockaddr_in *sin; 1772 u_char *a, *p; 1773 1774 lreply(211, "%s FTP server status:", hostname, version); 1775 printf(" %s\r\n", version); 1776 printf(" Connected to %s", remotehost); 1777 if (!isdigit(remotehost[0])) 1778 printf(" (%s)", inet_ntoa(his_addr.sin_addr)); 1779 printf("\r\n"); 1780 if (logged_in) { 1781 if (guest) 1782 printf(" Logged in anonymously\r\n"); 1783 else 1784 printf(" Logged in as %s\r\n", pw->pw_name); 1785 } else if (askpasswd) 1786 printf(" Waiting for password\r\n"); 1787 else 1788 printf(" Waiting for user name\r\n"); 1789 printf(" TYPE: %s", typenames[type]); 1790 if (type == TYPE_A || type == TYPE_E) 1791 printf(", FORM: %s", formnames[form]); 1792 if (type == TYPE_L) 1793 #if NBBY == 8 1794 printf(" %d", NBBY); 1795 #else 1796 printf(" %d", bytesize); /* need definition! */ 1797 #endif 1798 printf("; STRUcture: %s; transfer MODE: %s\r\n", 1799 strunames[stru], modenames[mode]); 1800 if (data != -1) 1801 printf(" Data connection open\r\n"); 1802 else if (pdata != -1) { 1803 printf(" in Passive mode"); 1804 sin = &pasv_addr; 1805 goto printaddr; 1806 } else if (usedefault == 0) { 1807 printf(" PORT"); 1808 sin = &data_dest; 1809 printaddr: 1810 a = (u_char *) &sin->sin_addr; 1811 p = (u_char *) &sin->sin_port; 1812 #define UC(b) (((int) b) & 0xff) 1813 printf(" (%d,%d,%d,%d,%d,%d)\r\n", UC(a[0]), 1814 UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); 1815 #undef UC 1816 } else 1817 printf(" No data connection\r\n"); 1818 reply(211, "End of status"); 1819 } 1820 1821 void 1822 fatal(s) 1823 char *s; 1824 { 1825 1826 reply(451, "Error in server: %s\n", s); 1827 reply(221, "Closing connection due to server error."); 1828 dologout(0); 1829 /* NOTREACHED */ 1830 } 1831 1832 void 1833 #if __STDC__ 1834 reply(int n, const char *fmt, ...) 1835 #else 1836 reply(n, fmt, va_alist) 1837 int n; 1838 char *fmt; 1839 va_dcl 1840 #endif 1841 { 1842 va_list ap; 1843 #if __STDC__ 1844 va_start(ap, fmt); 1845 #else 1846 va_start(ap); 1847 #endif 1848 (void)printf("%d ", n); 1849 (void)vprintf(fmt, ap); 1850 (void)printf("\r\n"); 1851 (void)fflush(stdout); 1852 if (debug) { 1853 syslog(LOG_DEBUG, "<--- %d ", n); 1854 vsyslog(LOG_DEBUG, fmt, ap); 1855 } 1856 } 1857 1858 void 1859 #if __STDC__ 1860 lreply(int n, const char *fmt, ...) 1861 #else 1862 lreply(n, fmt, va_alist) 1863 int n; 1864 char *fmt; 1865 va_dcl 1866 #endif 1867 { 1868 va_list ap; 1869 #if __STDC__ 1870 va_start(ap, fmt); 1871 #else 1872 va_start(ap); 1873 #endif 1874 (void)printf("%d- ", n); 1875 (void)vprintf(fmt, ap); 1876 (void)printf("\r\n"); 1877 (void)fflush(stdout); 1878 if (debug) { 1879 syslog(LOG_DEBUG, "<--- %d- ", n); 1880 vsyslog(LOG_DEBUG, fmt, ap); 1881 } 1882 } 1883 1884 static void 1885 ack(s) 1886 char *s; 1887 { 1888 1889 reply(250, "%s command successful.", s); 1890 } 1891 1892 void 1893 nack(s) 1894 char *s; 1895 { 1896 1897 reply(502, "%s command not implemented.", s); 1898 } 1899 1900 /* ARGSUSED */ 1901 void 1902 yyerror(s) 1903 char *s; 1904 { 1905 char *cp; 1906 1907 if ((cp = strchr(cbuf,'\n'))) 1908 *cp = '\0'; 1909 reply(500, "'%s': command not understood.", cbuf); 1910 } 1911 1912 void 1913 delete(name) 1914 char *name; 1915 { 1916 struct stat st; 1917 1918 LOGCMD("delete", name); 1919 if (stat(name, &st) < 0) { 1920 perror_reply(550, name); 1921 return; 1922 } 1923 if ((st.st_mode&S_IFMT) == S_IFDIR) { 1924 if (rmdir(name) < 0) { 1925 perror_reply(550, name); 1926 return; 1927 } 1928 goto done; 1929 } 1930 if (unlink(name) < 0) { 1931 perror_reply(550, name); 1932 return; 1933 } 1934 done: 1935 ack("DELE"); 1936 } 1937 1938 void 1939 cwd(path) 1940 char *path; 1941 { 1942 1943 if (chdir(path) < 0) 1944 perror_reply(550, path); 1945 else 1946 ack("CWD"); 1947 } 1948 1949 void 1950 makedir(name) 1951 char *name; 1952 { 1953 1954 LOGCMD("mkdir", name); 1955 if (mkdir(name, 0777) < 0) 1956 perror_reply(550, name); 1957 else 1958 reply(257, "MKD command successful."); 1959 } 1960 1961 void 1962 removedir(name) 1963 char *name; 1964 { 1965 1966 LOGCMD("rmdir", name); 1967 if (rmdir(name) < 0) 1968 perror_reply(550, name); 1969 else 1970 ack("RMD"); 1971 } 1972 1973 void 1974 pwd() 1975 { 1976 char path[MAXPATHLEN + 1]; 1977 1978 if (getwd(path) == (char *)NULL) 1979 reply(550, "%s.", path); 1980 else 1981 reply(257, "\"%s\" is current directory.", path); 1982 } 1983 1984 char * 1985 renamefrom(name) 1986 char *name; 1987 { 1988 struct stat st; 1989 1990 if (stat(name, &st) < 0) { 1991 perror_reply(550, name); 1992 return ((char *)0); 1993 } 1994 reply(350, "File exists, ready for destination name"); 1995 return (name); 1996 } 1997 1998 void 1999 renamecmd(from, to) 2000 char *from, *to; 2001 { 2002 struct stat st; 2003 2004 LOGCMD2("rename", from, to); 2005 2006 if (guest && (stat(to, &st) == 0)) { 2007 reply(550, "%s: permission denied", to); 2008 return; 2009 } 2010 2011 if (rename(from, to) < 0) 2012 perror_reply(550, "rename"); 2013 else 2014 ack("RNTO"); 2015 } 2016 2017 static void 2018 dolog(sin) 2019 struct sockaddr_in *sin; 2020 { 2021 realhostname(remotehost, sizeof(remotehost) - 1, &sin->sin_addr); 2022 2023 #ifdef SETPROCTITLE 2024 #ifdef VIRTUAL_HOSTING 2025 if (thishost != firsthost) 2026 snprintf(proctitle, sizeof(proctitle), "%s: connected (to %s)", 2027 remotehost, hostname); 2028 else 2029 #endif 2030 snprintf(proctitle, sizeof(proctitle), "%s: connected", 2031 remotehost); 2032 setproctitle("%s", proctitle); 2033 #endif /* SETPROCTITLE */ 2034 2035 if (logging) { 2036 #ifdef VIRTUAL_HOSTING 2037 if (thishost != firsthost) 2038 syslog(LOG_INFO, "connection from %s (to %s)", 2039 remotehost, hostname); 2040 else 2041 #endif 2042 syslog(LOG_INFO, "connection from %s (%s)", remotehost, 2043 inet_ntoa(sin->sin_addr)); 2044 } 2045 } 2046 2047 /* 2048 * Record logout in wtmp file 2049 * and exit with supplied status. 2050 */ 2051 void 2052 dologout(status) 2053 int status; 2054 { 2055 /* 2056 * Prevent reception of SIGURG from resulting in a resumption 2057 * back to the main program loop. 2058 */ 2059 transflag = 0; 2060 2061 if (logged_in) { 2062 (void) seteuid((uid_t)0); 2063 ftpd_logwtmp(ttyline, "", ""); 2064 } 2065 /* beware of flushing buffers after a SIGPIPE */ 2066 _exit(status); 2067 } 2068 2069 static void 2070 myoob(signo) 2071 int signo; 2072 { 2073 char *cp; 2074 2075 /* only process if transfer occurring */ 2076 if (!transflag) 2077 return; 2078 cp = tmpline; 2079 if (getline(cp, 7, stdin) == NULL) { 2080 reply(221, "You could at least say goodbye."); 2081 dologout(0); 2082 } 2083 upper(cp); 2084 if (strcmp(cp, "ABOR\r\n") == 0) { 2085 tmpline[0] = '\0'; 2086 reply(426, "Transfer aborted. Data connection closed."); 2087 reply(226, "Abort successful"); 2088 longjmp(urgcatch, 1); 2089 } 2090 if (strcmp(cp, "STAT\r\n") == 0) { 2091 tmpline[0] = '\0'; 2092 if (file_size != (off_t) -1) 2093 reply(213, "Status: %qd of %qd bytes transferred", 2094 byte_count, file_size); 2095 else 2096 reply(213, "Status: %qd bytes transferred", byte_count); 2097 } 2098 } 2099 2100 /* 2101 * Note: a response of 425 is not mentioned as a possible response to 2102 * the PASV command in RFC959. However, it has been blessed as 2103 * a legitimate response by Jon Postel in a telephone conversation 2104 * with Rick Adams on 25 Jan 89. 2105 */ 2106 void 2107 passive() 2108 { 2109 int len; 2110 char *p, *a; 2111 2112 if (pdata >= 0) /* close old port if one set */ 2113 close(pdata); 2114 2115 pdata = socket(AF_INET, SOCK_STREAM, 0); 2116 if (pdata < 0) { 2117 perror_reply(425, "Can't open passive connection"); 2118 return; 2119 } 2120 2121 (void) seteuid((uid_t)0); 2122 2123 #ifdef IP_PORTRANGE 2124 { 2125 int on = restricted_data_ports ? IP_PORTRANGE_HIGH 2126 : IP_PORTRANGE_DEFAULT; 2127 2128 if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE, 2129 (char *)&on, sizeof(on)) < 0) 2130 goto pasv_error; 2131 } 2132 #endif 2133 2134 pasv_addr = ctrl_addr; 2135 pasv_addr.sin_port = 0; 2136 if (bind(pdata, (struct sockaddr *)&pasv_addr, 2137 sizeof(pasv_addr)) < 0) 2138 goto pasv_error; 2139 2140 (void) seteuid((uid_t)pw->pw_uid); 2141 2142 len = sizeof(pasv_addr); 2143 if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0) 2144 goto pasv_error; 2145 if (listen(pdata, 1) < 0) 2146 goto pasv_error; 2147 a = (char *) &pasv_addr.sin_addr; 2148 p = (char *) &pasv_addr.sin_port; 2149 2150 #define UC(b) (((int) b) & 0xff) 2151 2152 reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]), 2153 UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); 2154 return; 2155 2156 pasv_error: 2157 (void) seteuid((uid_t)pw->pw_uid); 2158 (void) close(pdata); 2159 pdata = -1; 2160 perror_reply(425, "Can't open passive connection"); 2161 return; 2162 } 2163 2164 /* 2165 * Generate unique name for file with basename "local". 2166 * The file named "local" is already known to exist. 2167 * Generates failure reply on error. 2168 */ 2169 static char * 2170 gunique(local) 2171 char *local; 2172 { 2173 static char new[MAXPATHLEN]; 2174 struct stat st; 2175 int count; 2176 char *cp; 2177 2178 cp = strrchr(local, '/'); 2179 if (cp) 2180 *cp = '\0'; 2181 if (stat(cp ? local : ".", &st) < 0) { 2182 perror_reply(553, cp ? local : "."); 2183 return ((char *) 0); 2184 } 2185 if (cp) 2186 *cp = '/'; 2187 /* -4 is for the .nn<null> we put on the end below */ 2188 (void) snprintf(new, sizeof(new) - 4, "%s", local); 2189 cp = new + strlen(new); 2190 *cp++ = '.'; 2191 for (count = 1; count < 100; count++) { 2192 (void)sprintf(cp, "%d", count); 2193 if (stat(new, &st) < 0) 2194 return (new); 2195 } 2196 reply(452, "Unique file name cannot be created."); 2197 return (NULL); 2198 } 2199 2200 /* 2201 * Format and send reply containing system error number. 2202 */ 2203 void 2204 perror_reply(code, string) 2205 int code; 2206 char *string; 2207 { 2208 2209 reply(code, "%s: %s.", string, strerror(errno)); 2210 } 2211 2212 static char *onefile[] = { 2213 "", 2214 0 2215 }; 2216 2217 void 2218 send_file_list(whichf) 2219 char *whichf; 2220 { 2221 struct stat st; 2222 DIR *dirp = NULL; 2223 struct dirent *dir; 2224 FILE *dout = NULL; 2225 char **dirlist, *dirname; 2226 int simple = 0; 2227 int freeglob = 0; 2228 glob_t gl; 2229 2230 if (strpbrk(whichf, "~{[*?") != NULL) { 2231 int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE; 2232 2233 memset(&gl, 0, sizeof(gl)); 2234 freeglob = 1; 2235 if (glob(whichf, flags, 0, &gl)) { 2236 reply(550, "not found"); 2237 goto out; 2238 } else if (gl.gl_pathc == 0) { 2239 errno = ENOENT; 2240 perror_reply(550, whichf); 2241 goto out; 2242 } 2243 dirlist = gl.gl_pathv; 2244 } else { 2245 onefile[0] = whichf; 2246 dirlist = onefile; 2247 simple = 1; 2248 } 2249 2250 if (setjmp(urgcatch)) { 2251 transflag = 0; 2252 goto out; 2253 } 2254 while ((dirname = *dirlist++)) { 2255 if (stat(dirname, &st) < 0) { 2256 /* 2257 * If user typed "ls -l", etc, and the client 2258 * used NLST, do what the user meant. 2259 */ 2260 if (dirname[0] == '-' && *dirlist == NULL && 2261 transflag == 0) { 2262 retrieve(_PATH_LS " %s", dirname); 2263 goto out; 2264 } 2265 perror_reply(550, whichf); 2266 if (dout != NULL) { 2267 (void) fclose(dout); 2268 transflag = 0; 2269 data = -1; 2270 pdata = -1; 2271 } 2272 goto out; 2273 } 2274 2275 if (S_ISREG(st.st_mode)) { 2276 if (dout == NULL) { 2277 dout = dataconn("file list", (off_t)-1, "w"); 2278 if (dout == NULL) 2279 goto out; 2280 transflag++; 2281 } 2282 fprintf(dout, "%s%s\n", dirname, 2283 type == TYPE_A ? "\r" : ""); 2284 byte_count += strlen(dirname) + 1; 2285 continue; 2286 } else if (!S_ISDIR(st.st_mode)) 2287 continue; 2288 2289 if ((dirp = opendir(dirname)) == NULL) 2290 continue; 2291 2292 while ((dir = readdir(dirp)) != NULL) { 2293 char nbuf[MAXPATHLEN]; 2294 2295 if (dir->d_name[0] == '.' && dir->d_namlen == 1) 2296 continue; 2297 if (dir->d_name[0] == '.' && dir->d_name[1] == '.' && 2298 dir->d_namlen == 2) 2299 continue; 2300 2301 snprintf(nbuf, sizeof(nbuf), 2302 "%s/%s", dirname, dir->d_name); 2303 2304 /* 2305 * We have to do a stat to insure it's 2306 * not a directory or special file. 2307 */ 2308 if (simple || (stat(nbuf, &st) == 0 && 2309 S_ISREG(st.st_mode))) { 2310 if (dout == NULL) { 2311 dout = dataconn("file list", (off_t)-1, 2312 "w"); 2313 if (dout == NULL) 2314 goto out; 2315 transflag++; 2316 } 2317 if (nbuf[0] == '.' && nbuf[1] == '/') 2318 fprintf(dout, "%s%s\n", &nbuf[2], 2319 type == TYPE_A ? "\r" : ""); 2320 else 2321 fprintf(dout, "%s%s\n", nbuf, 2322 type == TYPE_A ? "\r" : ""); 2323 byte_count += strlen(nbuf) + 1; 2324 } 2325 } 2326 (void) closedir(dirp); 2327 } 2328 2329 if (dout == NULL) 2330 reply(550, "No files found."); 2331 else if (ferror(dout) != 0) 2332 perror_reply(550, "Data connection"); 2333 else 2334 reply(226, "Transfer complete."); 2335 2336 transflag = 0; 2337 if (dout != NULL) 2338 (void) fclose(dout); 2339 data = -1; 2340 pdata = -1; 2341 out: 2342 if (freeglob) { 2343 freeglob = 0; 2344 globfree(&gl); 2345 } 2346 } 2347 2348 void 2349 reapchild(signo) 2350 int signo; 2351 { 2352 while (wait3(NULL, WNOHANG, NULL) > 0); 2353 } 2354 2355 #ifdef OLD_SETPROCTITLE 2356 /* 2357 * Clobber argv so ps will show what we're doing. (Stolen from sendmail.) 2358 * Warning, since this is usually started from inetd.conf, it often doesn't 2359 * have much of an environment or arglist to overwrite. 2360 */ 2361 void 2362 #if __STDC__ 2363 setproctitle(const char *fmt, ...) 2364 #else 2365 setproctitle(fmt, va_alist) 2366 char *fmt; 2367 va_dcl 2368 #endif 2369 { 2370 int i; 2371 va_list ap; 2372 char *p, *bp, ch; 2373 char buf[LINE_MAX]; 2374 2375 #if __STDC__ 2376 va_start(ap, fmt); 2377 #else 2378 va_start(ap); 2379 #endif 2380 (void)vsnprintf(buf, sizeof(buf), fmt, ap); 2381 2382 /* make ps print our process name */ 2383 p = Argv[0]; 2384 *p++ = '-'; 2385 2386 i = strlen(buf); 2387 if (i > LastArgv - p - 2) { 2388 i = LastArgv - p - 2; 2389 buf[i] = '\0'; 2390 } 2391 bp = buf; 2392 while (ch = *bp++) 2393 if (ch != '\n' && ch != '\r') 2394 *p++ = ch; 2395 while (p < LastArgv) 2396 *p++ = ' '; 2397 } 2398 #endif /* OLD_SETPROCTITLE */ 2399 2400 static void 2401 logxfer(name, size, start) 2402 char *name; 2403 long size; 2404 long start; 2405 { 2406 char buf[1024]; 2407 char path[MAXPATHLEN + 1]; 2408 time_t now; 2409 2410 if (statfd >= 0 && getwd(path) != NULL) { 2411 time(&now); 2412 snprintf(buf, sizeof(buf), "%.20s!%s!%s!%s/%s!%ld!%ld\n", 2413 ctime(&now)+4, ident, remotehost, 2414 path, name, size, now - start + (now == start)); 2415 write(statfd, buf, strlen(buf)); 2416 } 2417 } 2418