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