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 if (opiechallenge(&opiedata, name, opieprompt) == 0) 976 reply(331, "Response to %s required for %s.", 977 opieprompt, name); 978 else 979 reply(331, "Password required for %s.", name); 980 #else 981 reply(331, "Password required for %s.", name); 982 #endif 983 askpasswd = 1; 984 /* 985 * Delay before reading passwd after first failed 986 * attempt to slow down passwd-guessing programs. 987 */ 988 if (login_attempts) 989 sleep((unsigned) login_attempts); 990 } 991 992 /* 993 * Check if a user is in the file "fname" 994 */ 995 static int 996 checkuser(fname, name, pwset) 997 char *fname; 998 char *name; 999 int pwset; 1000 { 1001 FILE *fd; 1002 int found = 0; 1003 char *p, line[BUFSIZ]; 1004 1005 if ((fd = fopen(fname, "r")) != NULL) { 1006 while (!found && fgets(line, sizeof(line), fd) != NULL) 1007 if ((p = strchr(line, '\n')) != NULL) { 1008 *p = '\0'; 1009 if (line[0] == '#') 1010 continue; 1011 /* 1012 * if first chr is '@', check group membership 1013 */ 1014 if (line[0] == '@') { 1015 int i = 0; 1016 struct group *grp; 1017 1018 if ((grp = getgrnam(line+1)) == NULL) 1019 continue; 1020 /* 1021 * Check user's default group 1022 */ 1023 if (pwset && grp->gr_gid == pw->pw_gid) 1024 found = 1; 1025 /* 1026 * Check supplementary groups 1027 */ 1028 while (!found && grp->gr_mem[i]) 1029 found = strcmp(name, 1030 grp->gr_mem[i++]) 1031 == 0; 1032 } 1033 /* 1034 * Otherwise, just check for username match 1035 */ 1036 else 1037 found = strcmp(line, name) == 0; 1038 } 1039 (void) fclose(fd); 1040 } 1041 return (found); 1042 } 1043 1044 /* 1045 * Terminate login as previous user, if any, resetting state; 1046 * used when USER command is given or login fails. 1047 */ 1048 static void 1049 end_login() 1050 { 1051 #ifdef USE_PAM 1052 int e; 1053 #endif 1054 1055 (void) seteuid((uid_t)0); 1056 if (logged_in) 1057 ftpd_logwtmp(ttyline, "", ""); 1058 pw = NULL; 1059 #ifdef LOGIN_CAP 1060 setusercontext(NULL, getpwuid(0), (uid_t)0, 1061 LOGIN_SETPRIORITY|LOGIN_SETRESOURCES|LOGIN_SETUMASK); 1062 #endif 1063 #ifdef USE_PAM 1064 if ((e = pam_setcred(pamh, PAM_DELETE_CRED)) != PAM_SUCCESS) 1065 syslog(LOG_ERR, "pam_setcred: %s", pam_strerror(pamh, e)); 1066 if ((e = pam_close_session(pamh,0)) != PAM_SUCCESS) 1067 syslog(LOG_ERR, "pam_close_session: %s", pam_strerror(pamh, e)); 1068 if ((e = pam_end(pamh, e)) != PAM_SUCCESS) 1069 syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e)); 1070 pamh = NULL; 1071 #endif 1072 logged_in = 0; 1073 guest = 0; 1074 dochroot = 0; 1075 } 1076 1077 #ifdef USE_PAM 1078 1079 /* 1080 * the following code is stolen from imap-uw PAM authentication module and 1081 * login.c 1082 */ 1083 #define COPY_STRING(s) (s ? strdup(s) : NULL) 1084 1085 struct cred_t { 1086 const char *uname; /* user name */ 1087 const char *pass; /* password */ 1088 }; 1089 typedef struct cred_t cred_t; 1090 1091 static int 1092 auth_conv(int num_msg, const struct pam_message **msg, 1093 struct pam_response **resp, void *appdata) 1094 { 1095 int i; 1096 cred_t *cred = (cred_t *) appdata; 1097 struct pam_response *reply = 1098 malloc(sizeof(struct pam_response) * num_msg); 1099 1100 for (i = 0; i < num_msg; i++) { 1101 switch (msg[i]->msg_style) { 1102 case PAM_PROMPT_ECHO_ON: /* assume want user name */ 1103 reply[i].resp_retcode = PAM_SUCCESS; 1104 reply[i].resp = COPY_STRING(cred->uname); 1105 /* PAM frees resp. */ 1106 break; 1107 case PAM_PROMPT_ECHO_OFF: /* assume want password */ 1108 reply[i].resp_retcode = PAM_SUCCESS; 1109 reply[i].resp = COPY_STRING(cred->pass); 1110 /* PAM frees resp. */ 1111 break; 1112 case PAM_TEXT_INFO: 1113 case PAM_ERROR_MSG: 1114 reply[i].resp_retcode = PAM_SUCCESS; 1115 reply[i].resp = NULL; 1116 break; 1117 default: /* unknown message style */ 1118 free(reply); 1119 return PAM_CONV_ERR; 1120 } 1121 } 1122 1123 *resp = reply; 1124 return PAM_SUCCESS; 1125 } 1126 1127 /* 1128 * Attempt to authenticate the user using PAM. Returns 0 if the user is 1129 * authenticated, or 1 if not authenticated. If some sort of PAM system 1130 * error occurs (e.g., the "/etc/pam.conf" file is missing) then this 1131 * function returns -1. This can be used as an indication that we should 1132 * fall back to a different authentication mechanism. 1133 */ 1134 static int 1135 auth_pam(struct passwd **ppw, const char *pass) 1136 { 1137 pam_handle_t *pamh = NULL; 1138 const char *tmpl_user; 1139 const void *item; 1140 int rval; 1141 int e; 1142 cred_t auth_cred = { (*ppw)->pw_name, pass }; 1143 struct pam_conv conv = { &auth_conv, &auth_cred }; 1144 1145 e = pam_start("ftpd", (*ppw)->pw_name, &conv, &pamh); 1146 if (e != PAM_SUCCESS) { 1147 syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, e)); 1148 return -1; 1149 } 1150 1151 e = pam_set_item(pamh, PAM_RHOST, remotehost); 1152 if (e != PAM_SUCCESS) { 1153 syslog(LOG_ERR, "pam_set_item(PAM_RHOST): %s", 1154 pam_strerror(pamh, e)); 1155 return -1; 1156 } 1157 1158 e = pam_authenticate(pamh, 0); 1159 switch (e) { 1160 case PAM_SUCCESS: 1161 /* 1162 * With PAM we support the concept of a "template" 1163 * user. The user enters a login name which is 1164 * authenticated by PAM, usually via a remote service 1165 * such as RADIUS or TACACS+. If authentication 1166 * succeeds, a different but related "template" name 1167 * is used for setting the credentials, shell, and 1168 * home directory. The name the user enters need only 1169 * exist on the remote authentication server, but the 1170 * template name must be present in the local password 1171 * database. 1172 * 1173 * This is supported by two various mechanisms in the 1174 * individual modules. However, from the application's 1175 * point of view, the template user is always passed 1176 * back as a changed value of the PAM_USER item. 1177 */ 1178 if ((e = pam_get_item(pamh, PAM_USER, &item)) == 1179 PAM_SUCCESS) { 1180 tmpl_user = (const char *) item; 1181 if (strcmp((*ppw)->pw_name, tmpl_user) != 0) 1182 *ppw = getpwnam(tmpl_user); 1183 } else 1184 syslog(LOG_ERR, "Couldn't get PAM_USER: %s", 1185 pam_strerror(pamh, e)); 1186 rval = 0; 1187 break; 1188 1189 case PAM_AUTH_ERR: 1190 case PAM_USER_UNKNOWN: 1191 case PAM_MAXTRIES: 1192 rval = 1; 1193 break; 1194 1195 default: 1196 syslog(LOG_ERR, "pam_authenticate: %s", pam_strerror(pamh, e)); 1197 rval = -1; 1198 break; 1199 } 1200 1201 if (rval == 0) { 1202 e = pam_acct_mgmt(pamh, 0); 1203 if (e == PAM_NEW_AUTHTOK_REQD) { 1204 e = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK); 1205 if (e != PAM_SUCCESS) { 1206 syslog(LOG_ERR, "pam_chauthtok: %s", pam_strerror(pamh, e)); 1207 rval = 1; 1208 } 1209 } else if (e != PAM_SUCCESS) { 1210 rval = 1; 1211 } 1212 } 1213 1214 if (rval != 0) { 1215 if ((e = pam_end(pamh, e)) != PAM_SUCCESS) { 1216 syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e)); 1217 } 1218 pamh = NULL; 1219 } 1220 return rval; 1221 } 1222 1223 #endif /* USE_PAM */ 1224 1225 void 1226 pass(passwd) 1227 char *passwd; 1228 { 1229 int rval; 1230 FILE *fd; 1231 #ifdef LOGIN_CAP 1232 login_cap_t *lc = NULL; 1233 #endif 1234 #ifdef USE_PAM 1235 int e; 1236 #endif 1237 1238 if (logged_in || askpasswd == 0) { 1239 reply(503, "Login with USER first."); 1240 return; 1241 } 1242 askpasswd = 0; 1243 if (!guest) { /* "ftp" is only account allowed no password */ 1244 if (pw == NULL) { 1245 rval = 1; /* failure below */ 1246 goto skip; 1247 } 1248 #ifdef USE_PAM 1249 rval = auth_pam(&pw, passwd); 1250 if (rval >= 0) 1251 goto skip; 1252 #endif 1253 rval = strcmp(pw->pw_passwd, crypt(passwd, pw->pw_passwd)); 1254 /* The strcmp does not catch null passwords! */ 1255 if (*pw->pw_passwd == '\0' || 1256 (pw->pw_expire && time(NULL) >= pw->pw_expire)) 1257 rval = 1; /* failure */ 1258 skip: 1259 /* 1260 * If rval == 1, the user failed the authentication check 1261 * above. If rval == 0, either PAM or local authentication 1262 * succeeded. 1263 */ 1264 if (rval) { 1265 reply(530, "Login incorrect."); 1266 if (logging) 1267 syslog(LOG_NOTICE, 1268 "FTP LOGIN FAILED FROM %s, %s", 1269 remotehost, curname); 1270 pw = NULL; 1271 if (login_attempts++ >= 5) { 1272 syslog(LOG_NOTICE, 1273 "repeated login failures from %s", 1274 remotehost); 1275 exit(0); 1276 } 1277 return; 1278 } 1279 } 1280 login_attempts = 0; /* this time successful */ 1281 if (setegid((gid_t)pw->pw_gid) < 0) { 1282 reply(550, "Can't set gid."); 1283 return; 1284 } 1285 /* May be overridden by login.conf */ 1286 (void) umask(defumask); 1287 #ifdef LOGIN_CAP 1288 if ((lc = login_getpwclass(pw)) != NULL) { 1289 char remote_ip[MAXHOSTNAMELEN]; 1290 1291 getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len, 1292 remote_ip, sizeof(remote_ip) - 1, NULL, 0, 1293 NI_NUMERICHOST|NI_WITHSCOPEID); 1294 remote_ip[sizeof(remote_ip) - 1] = 0; 1295 if (!auth_hostok(lc, remotehost, remote_ip)) { 1296 syslog(LOG_INFO|LOG_AUTH, 1297 "FTP LOGIN FAILED (HOST) as %s: permission denied.", 1298 pw->pw_name); 1299 reply(530, "Permission denied.\n"); 1300 pw = NULL; 1301 return; 1302 } 1303 if (!auth_timeok(lc, time(NULL))) { 1304 reply(530, "Login not available right now.\n"); 1305 pw = NULL; 1306 return; 1307 } 1308 } 1309 setusercontext(lc, pw, (uid_t)0, 1310 LOGIN_SETLOGIN|LOGIN_SETGROUP|LOGIN_SETPRIORITY| 1311 LOGIN_SETRESOURCES|LOGIN_SETUMASK); 1312 #else 1313 setlogin(pw->pw_name); 1314 (void) initgroups(pw->pw_name, pw->pw_gid); 1315 #endif 1316 1317 #ifdef USE_PAM 1318 if (pamh) { 1319 if ((e = pam_open_session(pamh, 0)) != PAM_SUCCESS) { 1320 syslog(LOG_ERR, "pam_open_session: %s", pam_strerror(pamh, e)); 1321 } else if ((e = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS) { 1322 syslog(LOG_ERR, "pam_setcred: %s", pam_strerror(pamh, e)); 1323 } 1324 } 1325 #endif 1326 1327 /* open wtmp before chroot */ 1328 ftpd_logwtmp(ttyline, pw->pw_name, remotehost); 1329 logged_in = 1; 1330 1331 if (guest && stats && statfd < 0) 1332 #ifdef VIRTUAL_HOSTING 1333 if ((statfd = open(thishost->statfile, O_WRONLY|O_APPEND)) < 0) 1334 #else 1335 if ((statfd = open(_PATH_FTPDSTATFILE, O_WRONLY|O_APPEND)) < 0) 1336 #endif 1337 stats = 0; 1338 1339 dochroot = 1340 #ifdef LOGIN_CAP /* Allow login.conf configuration as well */ 1341 login_getcapbool(lc, "ftp-chroot", 0) || 1342 #endif 1343 checkuser(_PATH_FTPCHROOT, pw->pw_name, 1); 1344 if (guest) { 1345 /* 1346 * We MUST do a chdir() after the chroot. Otherwise 1347 * the old current directory will be accessible as "." 1348 * outside the new root! 1349 */ 1350 if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) { 1351 reply(550, "Can't set guest privileges."); 1352 goto bad; 1353 } 1354 } else if (dochroot) { 1355 if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) { 1356 reply(550, "Can't change root."); 1357 goto bad; 1358 } 1359 } else if (chdir(pw->pw_dir) < 0) { 1360 if (chdir("/") < 0) { 1361 reply(530, "User %s: can't change directory to %s.", 1362 pw->pw_name, pw->pw_dir); 1363 goto bad; 1364 } else 1365 lreply(230, "No directory! Logging in with home=/"); 1366 } 1367 if (seteuid((uid_t)pw->pw_uid) < 0) { 1368 reply(550, "Can't set uid."); 1369 goto bad; 1370 } 1371 1372 /* 1373 * Display a login message, if it exists. 1374 * N.B. reply(230,) must follow the message. 1375 */ 1376 #ifdef VIRTUAL_HOSTING 1377 if ((fd = fopen(thishost->loginmsg, "r")) != NULL) { 1378 #else 1379 if ((fd = fopen(_PATH_FTPLOGINMESG, "r")) != NULL) { 1380 #endif 1381 char *cp, line[LINE_MAX]; 1382 1383 while (fgets(line, sizeof(line), fd) != NULL) { 1384 if ((cp = strchr(line, '\n')) != NULL) 1385 *cp = '\0'; 1386 lreply(230, "%s", line); 1387 } 1388 (void) fflush(stdout); 1389 (void) fclose(fd); 1390 } 1391 if (guest) { 1392 if (ident != NULL) 1393 free(ident); 1394 ident = strdup(passwd); 1395 if (ident == NULL) 1396 fatalerror("Ran out of memory."); 1397 1398 reply(230, "Guest login ok, access restrictions apply."); 1399 #ifdef SETPROCTITLE 1400 #ifdef VIRTUAL_HOSTING 1401 if (thishost != firsthost) 1402 snprintf(proctitle, sizeof(proctitle), 1403 "%s: anonymous(%s)/%s", remotehost, hostname, 1404 passwd); 1405 else 1406 #endif 1407 snprintf(proctitle, sizeof(proctitle), 1408 "%s: anonymous/%s", remotehost, passwd); 1409 setproctitle("%s", proctitle); 1410 #endif /* SETPROCTITLE */ 1411 if (logging) 1412 syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s", 1413 remotehost, passwd); 1414 } else { 1415 if (dochroot) 1416 reply(230, "User %s logged in, " 1417 "access restrictions apply.", pw->pw_name); 1418 else 1419 reply(230, "User %s logged in.", pw->pw_name); 1420 1421 #ifdef SETPROCTITLE 1422 snprintf(proctitle, sizeof(proctitle), 1423 "%s: user/%s", remotehost, pw->pw_name); 1424 setproctitle("%s", proctitle); 1425 #endif /* SETPROCTITLE */ 1426 if (logging) 1427 syslog(LOG_INFO, "FTP LOGIN FROM %s as %s", 1428 remotehost, pw->pw_name); 1429 } 1430 #ifdef LOGIN_CAP 1431 login_close(lc); 1432 #endif 1433 return; 1434 bad: 1435 /* Forget all about it... */ 1436 #ifdef LOGIN_CAP 1437 login_close(lc); 1438 #endif 1439 end_login(); 1440 } 1441 1442 void 1443 retrieve(cmd, name) 1444 char *cmd, *name; 1445 { 1446 FILE *fin, *dout; 1447 struct stat st; 1448 int (*closefunc) __P((FILE *)); 1449 time_t start; 1450 1451 if (cmd == 0) { 1452 fin = fopen(name, "r"), closefunc = fclose; 1453 st.st_size = 0; 1454 } else { 1455 char line[BUFSIZ]; 1456 1457 (void) snprintf(line, sizeof(line), cmd, name), name = line; 1458 fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose; 1459 st.st_size = -1; 1460 st.st_blksize = BUFSIZ; 1461 } 1462 if (fin == NULL) { 1463 if (errno != 0) { 1464 perror_reply(550, name); 1465 if (cmd == 0) { 1466 LOGCMD("get", name); 1467 } 1468 } 1469 return; 1470 } 1471 byte_count = -1; 1472 if (cmd == 0 && (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode))) { 1473 reply(550, "%s: not a plain file.", name); 1474 goto done; 1475 } 1476 if (restart_point) { 1477 if (type == TYPE_A) { 1478 off_t i, n; 1479 int c; 1480 1481 n = restart_point; 1482 i = 0; 1483 while (i++ < n) { 1484 if ((c=getc(fin)) == EOF) { 1485 perror_reply(550, name); 1486 goto done; 1487 } 1488 if (c == '\n') 1489 i++; 1490 } 1491 } else if (lseek(fileno(fin), restart_point, L_SET) < 0) { 1492 perror_reply(550, name); 1493 goto done; 1494 } 1495 } 1496 dout = dataconn(name, st.st_size, "w"); 1497 if (dout == NULL) 1498 goto done; 1499 time(&start); 1500 send_data(fin, dout, st.st_blksize, st.st_size, 1501 restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode)); 1502 if (cmd == 0 && guest && stats) 1503 logxfer(name, st.st_size, start); 1504 (void) fclose(dout); 1505 data = -1; 1506 pdata = -1; 1507 done: 1508 if (cmd == 0) 1509 LOGBYTES("get", name, byte_count); 1510 (*closefunc)(fin); 1511 } 1512 1513 void 1514 store(name, mode, unique) 1515 char *name, *mode; 1516 int unique; 1517 { 1518 FILE *fout, *din; 1519 struct stat st; 1520 int (*closefunc) __P((FILE *)); 1521 1522 if ((unique || guest) && stat(name, &st) == 0 && 1523 (name = gunique(name)) == NULL) { 1524 LOGCMD(*mode == 'w' ? "put" : "append", name); 1525 return; 1526 } 1527 1528 if (restart_point) 1529 mode = "r+"; 1530 fout = fopen(name, mode); 1531 closefunc = fclose; 1532 if (fout == NULL) { 1533 perror_reply(553, name); 1534 LOGCMD(*mode == 'w' ? "put" : "append", name); 1535 return; 1536 } 1537 byte_count = -1; 1538 if (restart_point) { 1539 if (type == TYPE_A) { 1540 off_t i, n; 1541 int c; 1542 1543 n = restart_point; 1544 i = 0; 1545 while (i++ < n) { 1546 if ((c=getc(fout)) == EOF) { 1547 perror_reply(550, name); 1548 goto done; 1549 } 1550 if (c == '\n') 1551 i++; 1552 } 1553 /* 1554 * We must do this seek to "current" position 1555 * because we are changing from reading to 1556 * writing. 1557 */ 1558 if (fseeko(fout, (off_t)0, SEEK_CUR) < 0) { 1559 perror_reply(550, name); 1560 goto done; 1561 } 1562 } else if (lseek(fileno(fout), restart_point, L_SET) < 0) { 1563 perror_reply(550, name); 1564 goto done; 1565 } 1566 } 1567 din = dataconn(name, (off_t)-1, "r"); 1568 if (din == NULL) 1569 goto done; 1570 if (receive_data(din, fout) == 0) { 1571 if (unique) 1572 reply(226, "Transfer complete (unique file name:%s).", 1573 name); 1574 else 1575 reply(226, "Transfer complete."); 1576 } 1577 (void) fclose(din); 1578 data = -1; 1579 pdata = -1; 1580 done: 1581 LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count); 1582 (*closefunc)(fout); 1583 } 1584 1585 static FILE * 1586 getdatasock(mode) 1587 char *mode; 1588 { 1589 int on = 1, s, t, tries; 1590 1591 if (data >= 0) 1592 return (fdopen(data, mode)); 1593 (void) seteuid((uid_t)0); 1594 1595 s = socket(data_dest.su_family, SOCK_STREAM, 0); 1596 if (s < 0) 1597 goto bad; 1598 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 1599 (char *) &on, sizeof(on)) < 0) 1600 goto bad; 1601 /* anchor socket to avoid multi-homing problems */ 1602 data_source = ctrl_addr; 1603 data_source.su_port = htons(20); /* ftp-data port */ 1604 for (tries = 1; ; tries++) { 1605 if (bind(s, (struct sockaddr *)&data_source, 1606 data_source.su_len) >= 0) 1607 break; 1608 if (errno != EADDRINUSE || tries > 10) 1609 goto bad; 1610 sleep(tries); 1611 } 1612 (void) seteuid((uid_t)pw->pw_uid); 1613 #ifdef IP_TOS 1614 if (data_source.su_family == AF_INET) 1615 { 1616 on = IPTOS_THROUGHPUT; 1617 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) 1618 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); 1619 } 1620 #endif 1621 #ifdef TCP_NOPUSH 1622 /* 1623 * Turn off push flag to keep sender TCP from sending short packets 1624 * at the boundaries of each write(). Should probably do a SO_SNDBUF 1625 * to set the send buffer size as well, but that may not be desirable 1626 * in heavy-load situations. 1627 */ 1628 on = 1; 1629 if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, (char *)&on, sizeof on) < 0) 1630 syslog(LOG_WARNING, "setsockopt (TCP_NOPUSH): %m"); 1631 #endif 1632 #ifdef SO_SNDBUF 1633 on = 65536; 1634 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&on, sizeof on) < 0) 1635 syslog(LOG_WARNING, "setsockopt (SO_SNDBUF): %m"); 1636 #endif 1637 1638 return (fdopen(s, mode)); 1639 bad: 1640 /* Return the real value of errno (close may change it) */ 1641 t = errno; 1642 (void) seteuid((uid_t)pw->pw_uid); 1643 (void) close(s); 1644 errno = t; 1645 return (NULL); 1646 } 1647 1648 static FILE * 1649 dataconn(name, size, mode) 1650 char *name; 1651 off_t size; 1652 char *mode; 1653 { 1654 char sizebuf[32]; 1655 FILE *file; 1656 int retry = 0, tos; 1657 1658 file_size = size; 1659 byte_count = 0; 1660 if (size != (off_t) -1) 1661 (void) snprintf(sizebuf, sizeof(sizebuf), " (%qd bytes)", size); 1662 else 1663 *sizebuf = '\0'; 1664 if (pdata >= 0) { 1665 union sockunion from; 1666 int s, fromlen = ctrl_addr.su_len; 1667 struct timeval timeout; 1668 fd_set set; 1669 1670 FD_ZERO(&set); 1671 FD_SET(pdata, &set); 1672 1673 timeout.tv_usec = 0; 1674 timeout.tv_sec = 120; 1675 1676 if (select(pdata+1, &set, (fd_set *) 0, (fd_set *) 0, &timeout) == 0 || 1677 (s = accept(pdata, (struct sockaddr *) &from, &fromlen)) < 0) { 1678 reply(425, "Can't open data connection."); 1679 (void) close(pdata); 1680 pdata = -1; 1681 return (NULL); 1682 } 1683 (void) close(pdata); 1684 pdata = s; 1685 #ifdef IP_TOS 1686 if (from.su_family == AF_INET) 1687 { 1688 tos = IPTOS_THROUGHPUT; 1689 (void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, 1690 sizeof(int)); 1691 } 1692 #endif 1693 reply(150, "Opening %s mode data connection for '%s'%s.", 1694 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); 1695 return (fdopen(pdata, mode)); 1696 } 1697 if (data >= 0) { 1698 reply(125, "Using existing data connection for '%s'%s.", 1699 name, sizebuf); 1700 usedefault = 1; 1701 return (fdopen(data, mode)); 1702 } 1703 if (usedefault) 1704 data_dest = his_addr; 1705 usedefault = 1; 1706 file = getdatasock(mode); 1707 if (file == NULL) { 1708 char hostbuf[BUFSIZ], portbuf[BUFSIZ]; 1709 getnameinfo((struct sockaddr *)&data_source, 1710 data_source.su_len, hostbuf, sizeof(hostbuf) - 1, 1711 portbuf, sizeof(portbuf), 1712 NI_NUMERICHOST|NI_NUMERICSERV|NI_WITHSCOPEID); 1713 reply(425, "Can't create data socket (%s,%s): %s.", 1714 hostbuf, portbuf, strerror(errno)); 1715 return (NULL); 1716 } 1717 data = fileno(file); 1718 while (connect(data, (struct sockaddr *)&data_dest, 1719 data_dest.su_len) < 0) { 1720 if (errno == EADDRINUSE && retry < swaitmax) { 1721 sleep((unsigned) swaitint); 1722 retry += swaitint; 1723 continue; 1724 } 1725 perror_reply(425, "Can't build data connection"); 1726 (void) fclose(file); 1727 data = -1; 1728 return (NULL); 1729 } 1730 reply(150, "Opening %s mode data connection for '%s'%s.", 1731 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); 1732 return (file); 1733 } 1734 1735 /* 1736 * Tranfer the contents of "instr" to "outstr" peer using the appropriate 1737 * encapsulation of the data subject to Mode, Structure, and Type. 1738 * 1739 * NB: Form isn't handled. 1740 */ 1741 static void 1742 send_data(instr, outstr, blksize, filesize, isreg) 1743 FILE *instr, *outstr; 1744 off_t blksize; 1745 off_t filesize; 1746 int isreg; 1747 { 1748 int c, filefd, netfd; 1749 char *buf; 1750 size_t len; 1751 off_t cnt; 1752 1753 transflag++; 1754 if (setjmp(urgcatch)) { 1755 transflag = 0; 1756 return; 1757 } 1758 switch (type) { 1759 1760 case TYPE_A: 1761 while ((c = getc(instr)) != EOF) { 1762 byte_count++; 1763 if (c == '\n') { 1764 if (ferror(outstr)) 1765 goto data_err; 1766 (void) putc('\r', outstr); 1767 } 1768 (void) putc(c, outstr); 1769 } 1770 fflush(outstr); 1771 transflag = 0; 1772 if (ferror(instr)) 1773 goto file_err; 1774 if (ferror(outstr)) 1775 goto data_err; 1776 reply(226, "Transfer complete."); 1777 return; 1778 1779 case TYPE_I: 1780 case TYPE_L: 1781 /* 1782 * isreg is only set if we are not doing restart and we 1783 * are sending a regular file 1784 */ 1785 netfd = fileno(outstr); 1786 filefd = fileno(instr); 1787 1788 if (isreg) { 1789 1790 off_t offset; 1791 int err; 1792 1793 len = filesize; 1794 err = cnt = offset = 0; 1795 1796 while (err != -1 && cnt < filesize) { 1797 err = sendfile(filefd, netfd, offset, len, 1798 (struct sf_hdtr *) NULL, &cnt, 0); 1799 byte_count += cnt; 1800 offset += cnt; 1801 len -= cnt; 1802 1803 if (err == -1) { 1804 if (!cnt) 1805 goto oldway; 1806 1807 goto data_err; 1808 } 1809 } 1810 1811 reply(226, "Transfer complete."); 1812 return; 1813 } 1814 1815 oldway: 1816 if ((buf = malloc((u_int)blksize)) == NULL) { 1817 transflag = 0; 1818 perror_reply(451, "Local resource failure: malloc"); 1819 return; 1820 } 1821 1822 while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 && 1823 write(netfd, buf, cnt) == cnt) 1824 byte_count += cnt; 1825 transflag = 0; 1826 (void)free(buf); 1827 if (cnt != 0) { 1828 if (cnt < 0) 1829 goto file_err; 1830 goto data_err; 1831 } 1832 reply(226, "Transfer complete."); 1833 return; 1834 default: 1835 transflag = 0; 1836 reply(550, "Unimplemented TYPE %d in send_data", type); 1837 return; 1838 } 1839 1840 data_err: 1841 transflag = 0; 1842 perror_reply(426, "Data connection"); 1843 return; 1844 1845 file_err: 1846 transflag = 0; 1847 perror_reply(551, "Error on input file"); 1848 } 1849 1850 /* 1851 * Transfer data from peer to "outstr" using the appropriate encapulation of 1852 * the data subject to Mode, Structure, and Type. 1853 * 1854 * N.B.: Form isn't handled. 1855 */ 1856 static int 1857 receive_data(instr, outstr) 1858 FILE *instr, *outstr; 1859 { 1860 int c; 1861 int cnt, bare_lfs; 1862 char buf[BUFSIZ]; 1863 1864 transflag++; 1865 if (setjmp(urgcatch)) { 1866 transflag = 0; 1867 return (-1); 1868 } 1869 1870 bare_lfs = 0; 1871 1872 switch (type) { 1873 1874 case TYPE_I: 1875 case TYPE_L: 1876 while ((cnt = read(fileno(instr), buf, sizeof(buf))) > 0) { 1877 if (write(fileno(outstr), buf, cnt) != cnt) 1878 goto file_err; 1879 byte_count += cnt; 1880 } 1881 if (cnt < 0) 1882 goto data_err; 1883 transflag = 0; 1884 return (0); 1885 1886 case TYPE_E: 1887 reply(553, "TYPE E not implemented."); 1888 transflag = 0; 1889 return (-1); 1890 1891 case TYPE_A: 1892 while ((c = getc(instr)) != EOF) { 1893 byte_count++; 1894 if (c == '\n') 1895 bare_lfs++; 1896 while (c == '\r') { 1897 if (ferror(outstr)) 1898 goto data_err; 1899 if ((c = getc(instr)) != '\n') { 1900 (void) putc ('\r', outstr); 1901 if (c == '\0' || c == EOF) 1902 goto contin2; 1903 } 1904 } 1905 (void) putc(c, outstr); 1906 contin2: ; 1907 } 1908 fflush(outstr); 1909 if (ferror(instr)) 1910 goto data_err; 1911 if (ferror(outstr)) 1912 goto file_err; 1913 transflag = 0; 1914 if (bare_lfs) { 1915 lreply(226, 1916 "WARNING! %d bare linefeeds received in ASCII mode", 1917 bare_lfs); 1918 (void)printf(" File may not have transferred correctly.\r\n"); 1919 } 1920 return (0); 1921 default: 1922 reply(550, "Unimplemented TYPE %d in receive_data", type); 1923 transflag = 0; 1924 return (-1); 1925 } 1926 1927 data_err: 1928 transflag = 0; 1929 perror_reply(426, "Data Connection"); 1930 return (-1); 1931 1932 file_err: 1933 transflag = 0; 1934 perror_reply(452, "Error writing file"); 1935 return (-1); 1936 } 1937 1938 void 1939 statfilecmd(filename) 1940 char *filename; 1941 { 1942 FILE *fin; 1943 int c; 1944 char line[LINE_MAX]; 1945 1946 (void)snprintf(line, sizeof(line), _PATH_LS " -lgA %s", filename); 1947 fin = ftpd_popen(line, "r"); 1948 lreply(211, "status of %s:", filename); 1949 while ((c = getc(fin)) != EOF) { 1950 if (c == '\n') { 1951 if (ferror(stdout)){ 1952 perror_reply(421, "control connection"); 1953 (void) ftpd_pclose(fin); 1954 dologout(1); 1955 /* NOTREACHED */ 1956 } 1957 if (ferror(fin)) { 1958 perror_reply(551, filename); 1959 (void) ftpd_pclose(fin); 1960 return; 1961 } 1962 (void) putc('\r', stdout); 1963 } 1964 (void) putc(c, stdout); 1965 } 1966 (void) ftpd_pclose(fin); 1967 reply(211, "End of Status"); 1968 } 1969 1970 void 1971 statcmd() 1972 { 1973 union sockunion *su; 1974 u_char *a, *p; 1975 char hname[INET6_ADDRSTRLEN]; 1976 int ispassive; 1977 1978 lreply(211, "%s FTP server status:", hostname, version); 1979 printf(" %s\r\n", version); 1980 printf(" Connected to %s", remotehost); 1981 if (!getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len, 1982 hname, sizeof(hname) - 1, NULL, 0, 1983 NI_NUMERICHOST|NI_WITHSCOPEID)) { 1984 if (strcmp(hname, remotehost) != 0) 1985 printf(" (%s)", hname); 1986 } 1987 printf("\r\n"); 1988 if (logged_in) { 1989 if (guest) 1990 printf(" Logged in anonymously\r\n"); 1991 else 1992 printf(" Logged in as %s\r\n", pw->pw_name); 1993 } else if (askpasswd) 1994 printf(" Waiting for password\r\n"); 1995 else 1996 printf(" Waiting for user name\r\n"); 1997 printf(" TYPE: %s", typenames[type]); 1998 if (type == TYPE_A || type == TYPE_E) 1999 printf(", FORM: %s", formnames[form]); 2000 if (type == TYPE_L) 2001 #if NBBY == 8 2002 printf(" %d", NBBY); 2003 #else 2004 printf(" %d", bytesize); /* need definition! */ 2005 #endif 2006 printf("; STRUcture: %s; transfer MODE: %s\r\n", 2007 strunames[stru], modenames[mode]); 2008 if (data != -1) 2009 printf(" Data connection open\r\n"); 2010 else if (pdata != -1) { 2011 ispassive = 1; 2012 su = &pasv_addr; 2013 goto printaddr; 2014 } else if (usedefault == 0) { 2015 ispassive = 0; 2016 su = &data_dest; 2017 printaddr: 2018 #define UC(b) (((int) b) & 0xff) 2019 if (epsvall) { 2020 printf(" EPSV only mode (EPSV ALL)\r\n"); 2021 goto epsvonly; 2022 } 2023 2024 /* PORT/PASV */ 2025 if (su->su_family == AF_INET) { 2026 a = (u_char *) &su->su_sin.sin_addr; 2027 p = (u_char *) &su->su_sin.sin_port; 2028 printf(" %s (%d,%d,%d,%d,%d,%d)\r\n", 2029 ispassive ? "PASV" : "PORT", 2030 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 2031 UC(p[0]), UC(p[1])); 2032 } 2033 2034 /* LPRT/LPSV */ 2035 { 2036 int alen, af, i; 2037 2038 switch (su->su_family) { 2039 case AF_INET: 2040 a = (u_char *) &su->su_sin.sin_addr; 2041 p = (u_char *) &su->su_sin.sin_port; 2042 alen = sizeof(su->su_sin.sin_addr); 2043 af = 4; 2044 break; 2045 case AF_INET6: 2046 a = (u_char *) &su->su_sin6.sin6_addr; 2047 p = (u_char *) &su->su_sin6.sin6_port; 2048 alen = sizeof(su->su_sin6.sin6_addr); 2049 af = 6; 2050 break; 2051 default: 2052 af = 0; 2053 break; 2054 } 2055 if (af) { 2056 printf(" %s (%d,%d,", ispassive ? "LPSV" : "LPRT", 2057 af, alen); 2058 for (i = 0; i < alen; i++) 2059 printf("%d,", UC(a[i])); 2060 printf("%d,%d,%d)\r\n", 2, UC(p[0]), UC(p[1])); 2061 } 2062 } 2063 2064 epsvonly:; 2065 /* EPRT/EPSV */ 2066 { 2067 int af; 2068 2069 switch (su->su_family) { 2070 case AF_INET: 2071 af = 1; 2072 break; 2073 case AF_INET6: 2074 af = 2; 2075 break; 2076 default: 2077 af = 0; 2078 break; 2079 } 2080 if (af) { 2081 if (!getnameinfo((struct sockaddr *)su, su->su_len, 2082 hname, sizeof(hname) - 1, NULL, 0, 2083 NI_NUMERICHOST)) { 2084 printf(" %s |%d|%s|%d|\r\n", 2085 ispassive ? "EPSV" : "EPRT", 2086 af, hname, htons(su->su_port)); 2087 } 2088 } 2089 } 2090 #undef UC 2091 } else 2092 printf(" No data connection\r\n"); 2093 reply(211, "End of status"); 2094 } 2095 2096 void 2097 fatalerror(s) 2098 char *s; 2099 { 2100 2101 reply(451, "Error in server: %s\n", s); 2102 reply(221, "Closing connection due to server error."); 2103 dologout(0); 2104 /* NOTREACHED */ 2105 } 2106 2107 void 2108 #if __STDC__ 2109 reply(int n, const char *fmt, ...) 2110 #else 2111 reply(n, fmt, va_alist) 2112 int n; 2113 char *fmt; 2114 va_dcl 2115 #endif 2116 { 2117 va_list ap; 2118 #if __STDC__ 2119 va_start(ap, fmt); 2120 #else 2121 va_start(ap); 2122 #endif 2123 (void)printf("%d ", n); 2124 (void)vprintf(fmt, ap); 2125 (void)printf("\r\n"); 2126 (void)fflush(stdout); 2127 if (ftpdebug) { 2128 syslog(LOG_DEBUG, "<--- %d ", n); 2129 vsyslog(LOG_DEBUG, fmt, ap); 2130 } 2131 } 2132 2133 void 2134 #if __STDC__ 2135 lreply(int n, const char *fmt, ...) 2136 #else 2137 lreply(n, fmt, va_alist) 2138 int n; 2139 char *fmt; 2140 va_dcl 2141 #endif 2142 { 2143 va_list ap; 2144 #if __STDC__ 2145 va_start(ap, fmt); 2146 #else 2147 va_start(ap); 2148 #endif 2149 (void)printf("%d- ", n); 2150 (void)vprintf(fmt, ap); 2151 (void)printf("\r\n"); 2152 (void)fflush(stdout); 2153 if (ftpdebug) { 2154 syslog(LOG_DEBUG, "<--- %d- ", n); 2155 vsyslog(LOG_DEBUG, fmt, ap); 2156 } 2157 } 2158 2159 static void 2160 ack(s) 2161 char *s; 2162 { 2163 2164 reply(250, "%s command successful.", s); 2165 } 2166 2167 void 2168 nack(s) 2169 char *s; 2170 { 2171 2172 reply(502, "%s command not implemented.", s); 2173 } 2174 2175 /* ARGSUSED */ 2176 void 2177 yyerror(s) 2178 char *s; 2179 { 2180 char *cp; 2181 2182 if ((cp = strchr(cbuf,'\n'))) 2183 *cp = '\0'; 2184 reply(500, "'%s': command not understood.", cbuf); 2185 } 2186 2187 void 2188 delete(name) 2189 char *name; 2190 { 2191 struct stat st; 2192 2193 LOGCMD("delete", name); 2194 if (stat(name, &st) < 0) { 2195 perror_reply(550, name); 2196 return; 2197 } 2198 if ((st.st_mode&S_IFMT) == S_IFDIR) { 2199 if (rmdir(name) < 0) { 2200 perror_reply(550, name); 2201 return; 2202 } 2203 goto done; 2204 } 2205 if (unlink(name) < 0) { 2206 perror_reply(550, name); 2207 return; 2208 } 2209 done: 2210 ack("DELE"); 2211 } 2212 2213 void 2214 cwd(path) 2215 char *path; 2216 { 2217 2218 if (chdir(path) < 0) 2219 perror_reply(550, path); 2220 else 2221 ack("CWD"); 2222 } 2223 2224 void 2225 makedir(name) 2226 char *name; 2227 { 2228 2229 LOGCMD("mkdir", name); 2230 if (mkdir(name, 0777) < 0) 2231 perror_reply(550, name); 2232 else 2233 reply(257, "MKD command successful."); 2234 } 2235 2236 void 2237 removedir(name) 2238 char *name; 2239 { 2240 2241 LOGCMD("rmdir", name); 2242 if (rmdir(name) < 0) 2243 perror_reply(550, name); 2244 else 2245 ack("RMD"); 2246 } 2247 2248 void 2249 pwd() 2250 { 2251 char path[MAXPATHLEN + 1]; 2252 2253 if (getwd(path) == (char *)NULL) 2254 reply(550, "%s.", path); 2255 else 2256 reply(257, "\"%s\" is current directory.", path); 2257 } 2258 2259 char * 2260 renamefrom(name) 2261 char *name; 2262 { 2263 struct stat st; 2264 2265 if (stat(name, &st) < 0) { 2266 perror_reply(550, name); 2267 return ((char *)0); 2268 } 2269 reply(350, "File exists, ready for destination name"); 2270 return (name); 2271 } 2272 2273 void 2274 renamecmd(from, to) 2275 char *from, *to; 2276 { 2277 struct stat st; 2278 2279 LOGCMD2("rename", from, to); 2280 2281 if (guest && (stat(to, &st) == 0)) { 2282 reply(550, "%s: permission denied", to); 2283 return; 2284 } 2285 2286 if (rename(from, to) < 0) 2287 perror_reply(550, "rename"); 2288 else 2289 ack("RNTO"); 2290 } 2291 2292 static void 2293 dolog(who) 2294 struct sockaddr *who; 2295 { 2296 int error; 2297 2298 realhostname_sa(remotehost, sizeof(remotehost) - 1, who, who->sa_len); 2299 2300 #ifdef SETPROCTITLE 2301 #ifdef VIRTUAL_HOSTING 2302 if (thishost != firsthost) 2303 snprintf(proctitle, sizeof(proctitle), "%s: connected (to %s)", 2304 remotehost, hostname); 2305 else 2306 #endif 2307 snprintf(proctitle, sizeof(proctitle), "%s: connected", 2308 remotehost); 2309 setproctitle("%s", proctitle); 2310 #endif /* SETPROCTITLE */ 2311 2312 if (logging) { 2313 #ifdef VIRTUAL_HOSTING 2314 if (thishost != firsthost) 2315 syslog(LOG_INFO, "connection from %s (to %s)", 2316 remotehost, hostname); 2317 else 2318 #endif 2319 { 2320 char who_name[MAXHOSTNAMELEN]; 2321 2322 error = getnameinfo(who, who->sa_len, 2323 who_name, sizeof(who_name) - 1, 2324 NULL, 0, 2325 NI_NUMERICHOST|NI_WITHSCOPEID); 2326 syslog(LOG_INFO, "connection from %s (%s)", remotehost, 2327 error == 0 ? who_name : ""); 2328 } 2329 } 2330 } 2331 2332 /* 2333 * Record logout in wtmp file 2334 * and exit with supplied status. 2335 */ 2336 void 2337 dologout(status) 2338 int status; 2339 { 2340 /* 2341 * Prevent reception of SIGURG from resulting in a resumption 2342 * back to the main program loop. 2343 */ 2344 transflag = 0; 2345 2346 if (logged_in) { 2347 (void) seteuid((uid_t)0); 2348 ftpd_logwtmp(ttyline, "", ""); 2349 } 2350 /* beware of flushing buffers after a SIGPIPE */ 2351 _exit(status); 2352 } 2353 2354 static void 2355 myoob(signo) 2356 int signo; 2357 { 2358 char *cp; 2359 2360 /* only process if transfer occurring */ 2361 if (!transflag) 2362 return; 2363 cp = tmpline; 2364 if (getline(cp, 7, stdin) == NULL) { 2365 reply(221, "You could at least say goodbye."); 2366 dologout(0); 2367 } 2368 upper(cp); 2369 if (strcmp(cp, "ABOR\r\n") == 0) { 2370 tmpline[0] = '\0'; 2371 reply(426, "Transfer aborted. Data connection closed."); 2372 reply(226, "Abort successful"); 2373 longjmp(urgcatch, 1); 2374 } 2375 if (strcmp(cp, "STAT\r\n") == 0) { 2376 tmpline[0] = '\0'; 2377 if (file_size != (off_t) -1) 2378 reply(213, "Status: %qd of %qd bytes transferred", 2379 byte_count, file_size); 2380 else 2381 reply(213, "Status: %qd bytes transferred", byte_count); 2382 } 2383 } 2384 2385 /* 2386 * Note: a response of 425 is not mentioned as a possible response to 2387 * the PASV command in RFC959. However, it has been blessed as 2388 * a legitimate response by Jon Postel in a telephone conversation 2389 * with Rick Adams on 25 Jan 89. 2390 */ 2391 void 2392 passive() 2393 { 2394 int len; 2395 char *p, *a; 2396 2397 if (pdata >= 0) /* close old port if one set */ 2398 close(pdata); 2399 2400 pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0); 2401 if (pdata < 0) { 2402 perror_reply(425, "Can't open passive connection"); 2403 return; 2404 } 2405 2406 (void) seteuid((uid_t)0); 2407 2408 #ifdef IP_PORTRANGE 2409 if (ctrl_addr.su_family == AF_INET) { 2410 int on = restricted_data_ports ? IP_PORTRANGE_HIGH 2411 : IP_PORTRANGE_DEFAULT; 2412 2413 if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE, 2414 (char *)&on, sizeof(on)) < 0) 2415 goto pasv_error; 2416 } 2417 #endif 2418 #ifdef IPV6_PORTRANGE 2419 if (ctrl_addr.su_family == AF_INET6) { 2420 int on = restricted_data_ports ? IPV6_PORTRANGE_HIGH 2421 : IPV6_PORTRANGE_DEFAULT; 2422 2423 if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE, 2424 (char *)&on, sizeof(on)) < 0) 2425 goto pasv_error; 2426 } 2427 #endif 2428 2429 pasv_addr = ctrl_addr; 2430 pasv_addr.su_port = 0; 2431 if (bind(pdata, (struct sockaddr *)&pasv_addr, pasv_addr.su_len) < 0) 2432 goto pasv_error; 2433 2434 (void) seteuid((uid_t)pw->pw_uid); 2435 2436 len = sizeof(pasv_addr); 2437 if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0) 2438 goto pasv_error; 2439 if (listen(pdata, 1) < 0) 2440 goto pasv_error; 2441 if (pasv_addr.su_family == AF_INET) 2442 a = (char *) &pasv_addr.su_sin.sin_addr; 2443 else if (pasv_addr.su_family == AF_INET6 && 2444 IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr)) 2445 a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12]; 2446 else 2447 goto pasv_error; 2448 2449 p = (char *) &pasv_addr.su_port; 2450 2451 #define UC(b) (((int) b) & 0xff) 2452 2453 reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]), 2454 UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); 2455 return; 2456 2457 pasv_error: 2458 (void) seteuid((uid_t)pw->pw_uid); 2459 (void) close(pdata); 2460 pdata = -1; 2461 perror_reply(425, "Can't open passive connection"); 2462 return; 2463 } 2464 2465 /* 2466 * Long Passive defined in RFC 1639. 2467 * 228 Entering Long Passive Mode 2468 * (af, hal, h1, h2, h3,..., pal, p1, p2...) 2469 */ 2470 2471 void 2472 long_passive(cmd, pf) 2473 char *cmd; 2474 int pf; 2475 { 2476 int len; 2477 char *p, *a; 2478 2479 if (pdata >= 0) /* close old port if one set */ 2480 close(pdata); 2481 2482 if (pf != PF_UNSPEC) { 2483 if (ctrl_addr.su_family != pf) { 2484 switch (ctrl_addr.su_family) { 2485 case AF_INET: 2486 pf = 1; 2487 break; 2488 case AF_INET6: 2489 pf = 2; 2490 break; 2491 default: 2492 pf = 0; 2493 break; 2494 } 2495 /* 2496 * XXX 2497 * only EPRT/EPSV ready clients will understand this 2498 */ 2499 if (strcmp(cmd, "EPSV") == 0 && pf) { 2500 reply(522, "Network protocol mismatch, " 2501 "use (%d)", pf); 2502 } else 2503 reply(501, "Network protocol mismatch"); /*XXX*/ 2504 2505 return; 2506 } 2507 } 2508 2509 pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0); 2510 if (pdata < 0) { 2511 perror_reply(425, "Can't open passive connection"); 2512 return; 2513 } 2514 2515 (void) seteuid((uid_t)0); 2516 2517 pasv_addr = ctrl_addr; 2518 pasv_addr.su_port = 0; 2519 len = pasv_addr.su_len; 2520 2521 #ifdef IP_PORTRANGE 2522 if (ctrl_addr.su_family == AF_INET) { 2523 int on = restricted_data_ports ? IP_PORTRANGE_HIGH 2524 : IP_PORTRANGE_DEFAULT; 2525 2526 if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE, 2527 (char *)&on, sizeof(on)) < 0) 2528 goto pasv_error; 2529 } 2530 #endif 2531 #ifdef IPV6_PORTRANGE 2532 if (ctrl_addr.su_family == AF_INET6) { 2533 int on = restricted_data_ports ? IPV6_PORTRANGE_HIGH 2534 : IPV6_PORTRANGE_DEFAULT; 2535 2536 if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE, 2537 (char *)&on, sizeof(on)) < 0) 2538 goto pasv_error; 2539 } 2540 #endif 2541 2542 if (bind(pdata, (struct sockaddr *)&pasv_addr, len) < 0) 2543 goto pasv_error; 2544 2545 (void) seteuid((uid_t)pw->pw_uid); 2546 2547 if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0) 2548 goto pasv_error; 2549 if (listen(pdata, 1) < 0) 2550 goto pasv_error; 2551 2552 #define UC(b) (((int) b) & 0xff) 2553 2554 if (strcmp(cmd, "LPSV") == 0) { 2555 p = (char *)&pasv_addr.su_port; 2556 switch (pasv_addr.su_family) { 2557 case AF_INET: 2558 a = (char *) &pasv_addr.su_sin.sin_addr; 2559 v4_reply: 2560 reply(228, 2561 "Entering Long Passive Mode (%d,%d,%d,%d,%d,%d,%d,%d,%d)", 2562 4, 4, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 2563 2, UC(p[0]), UC(p[1])); 2564 return; 2565 case AF_INET6: 2566 if (IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr)) { 2567 a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12]; 2568 goto v4_reply; 2569 } 2570 a = (char *) &pasv_addr.su_sin6.sin6_addr; 2571 reply(228, 2572 "Entering Long Passive Mode " 2573 "(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)", 2574 6, 16, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 2575 UC(a[4]), UC(a[5]), UC(a[6]), UC(a[7]), 2576 UC(a[8]), UC(a[9]), UC(a[10]), UC(a[11]), 2577 UC(a[12]), UC(a[13]), UC(a[14]), UC(a[15]), 2578 2, UC(p[0]), UC(p[1])); 2579 return; 2580 } 2581 } else if (strcmp(cmd, "EPSV") == 0) { 2582 switch (pasv_addr.su_family) { 2583 case AF_INET: 2584 case AF_INET6: 2585 reply(229, "Entering Extended Passive Mode (|||%d|)", 2586 ntohs(pasv_addr.su_port)); 2587 return; 2588 } 2589 } else { 2590 /* more proper error code? */ 2591 } 2592 2593 pasv_error: 2594 (void) seteuid((uid_t)pw->pw_uid); 2595 (void) close(pdata); 2596 pdata = -1; 2597 perror_reply(425, "Can't open passive connection"); 2598 return; 2599 } 2600 2601 /* 2602 * Generate unique name for file with basename "local". 2603 * The file named "local" is already known to exist. 2604 * Generates failure reply on error. 2605 */ 2606 static char * 2607 gunique(local) 2608 char *local; 2609 { 2610 static char new[MAXPATHLEN]; 2611 struct stat st; 2612 int count; 2613 char *cp; 2614 2615 cp = strrchr(local, '/'); 2616 if (cp) 2617 *cp = '\0'; 2618 if (stat(cp ? local : ".", &st) < 0) { 2619 perror_reply(553, cp ? local : "."); 2620 return ((char *) 0); 2621 } 2622 if (cp) 2623 *cp = '/'; 2624 /* -4 is for the .nn<null> we put on the end below */ 2625 (void) snprintf(new, sizeof(new) - 4, "%s", local); 2626 cp = new + strlen(new); 2627 *cp++ = '.'; 2628 for (count = 1; count < 100; count++) { 2629 (void)sprintf(cp, "%d", count); 2630 if (stat(new, &st) < 0) 2631 return (new); 2632 } 2633 reply(452, "Unique file name cannot be created."); 2634 return (NULL); 2635 } 2636 2637 /* 2638 * Format and send reply containing system error number. 2639 */ 2640 void 2641 perror_reply(code, string) 2642 int code; 2643 char *string; 2644 { 2645 2646 reply(code, "%s: %s.", string, strerror(errno)); 2647 } 2648 2649 static char *onefile[] = { 2650 "", 2651 0 2652 }; 2653 2654 void 2655 send_file_list(whichf) 2656 char *whichf; 2657 { 2658 struct stat st; 2659 DIR *dirp = NULL; 2660 struct dirent *dir; 2661 FILE *dout = NULL; 2662 char **dirlist, *dirname; 2663 int simple = 0; 2664 int freeglob = 0; 2665 glob_t gl; 2666 2667 if (strpbrk(whichf, "~{[*?") != NULL) { 2668 int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE; 2669 2670 memset(&gl, 0, sizeof(gl)); 2671 gl.gl_matchc = MAXGLOBARGS; 2672 flags |= GLOB_LIMIT; 2673 freeglob = 1; 2674 if (glob(whichf, flags, 0, &gl)) { 2675 reply(550, "not found"); 2676 goto out; 2677 } else if (gl.gl_pathc == 0) { 2678 errno = ENOENT; 2679 perror_reply(550, whichf); 2680 goto out; 2681 } 2682 dirlist = gl.gl_pathv; 2683 } else { 2684 onefile[0] = whichf; 2685 dirlist = onefile; 2686 simple = 1; 2687 } 2688 2689 if (setjmp(urgcatch)) { 2690 transflag = 0; 2691 goto out; 2692 } 2693 while ((dirname = *dirlist++)) { 2694 if (stat(dirname, &st) < 0) { 2695 /* 2696 * If user typed "ls -l", etc, and the client 2697 * used NLST, do what the user meant. 2698 */ 2699 if (dirname[0] == '-' && *dirlist == NULL && 2700 transflag == 0) { 2701 retrieve(_PATH_LS " %s", dirname); 2702 goto out; 2703 } 2704 perror_reply(550, whichf); 2705 if (dout != NULL) { 2706 (void) fclose(dout); 2707 transflag = 0; 2708 data = -1; 2709 pdata = -1; 2710 } 2711 goto out; 2712 } 2713 2714 if (S_ISREG(st.st_mode)) { 2715 if (dout == NULL) { 2716 dout = dataconn("file list", (off_t)-1, "w"); 2717 if (dout == NULL) 2718 goto out; 2719 transflag++; 2720 } 2721 fprintf(dout, "%s%s\n", dirname, 2722 type == TYPE_A ? "\r" : ""); 2723 byte_count += strlen(dirname) + 1; 2724 continue; 2725 } else if (!S_ISDIR(st.st_mode)) 2726 continue; 2727 2728 if ((dirp = opendir(dirname)) == NULL) 2729 continue; 2730 2731 while ((dir = readdir(dirp)) != NULL) { 2732 char nbuf[MAXPATHLEN]; 2733 2734 if (dir->d_name[0] == '.' && dir->d_namlen == 1) 2735 continue; 2736 if (dir->d_name[0] == '.' && dir->d_name[1] == '.' && 2737 dir->d_namlen == 2) 2738 continue; 2739 2740 snprintf(nbuf, sizeof(nbuf), 2741 "%s/%s", dirname, dir->d_name); 2742 2743 /* 2744 * We have to do a stat to insure it's 2745 * not a directory or special file. 2746 */ 2747 if (simple || (stat(nbuf, &st) == 0 && 2748 S_ISREG(st.st_mode))) { 2749 if (dout == NULL) { 2750 dout = dataconn("file list", (off_t)-1, 2751 "w"); 2752 if (dout == NULL) 2753 goto out; 2754 transflag++; 2755 } 2756 if (nbuf[0] == '.' && nbuf[1] == '/') 2757 fprintf(dout, "%s%s\n", &nbuf[2], 2758 type == TYPE_A ? "\r" : ""); 2759 else 2760 fprintf(dout, "%s%s\n", nbuf, 2761 type == TYPE_A ? "\r" : ""); 2762 byte_count += strlen(nbuf) + 1; 2763 } 2764 } 2765 (void) closedir(dirp); 2766 } 2767 2768 if (dout == NULL) 2769 reply(550, "No files found."); 2770 else if (ferror(dout) != 0) 2771 perror_reply(550, "Data connection"); 2772 else 2773 reply(226, "Transfer complete."); 2774 2775 transflag = 0; 2776 if (dout != NULL) 2777 (void) fclose(dout); 2778 data = -1; 2779 pdata = -1; 2780 out: 2781 if (freeglob) { 2782 freeglob = 0; 2783 globfree(&gl); 2784 } 2785 } 2786 2787 void 2788 reapchild(signo) 2789 int signo; 2790 { 2791 while (wait3(NULL, WNOHANG, NULL) > 0); 2792 } 2793 2794 #ifdef OLD_SETPROCTITLE 2795 /* 2796 * Clobber argv so ps will show what we're doing. (Stolen from sendmail.) 2797 * Warning, since this is usually started from inetd.conf, it often doesn't 2798 * have much of an environment or arglist to overwrite. 2799 */ 2800 void 2801 #if __STDC__ 2802 setproctitle(const char *fmt, ...) 2803 #else 2804 setproctitle(fmt, va_alist) 2805 char *fmt; 2806 va_dcl 2807 #endif 2808 { 2809 int i; 2810 va_list ap; 2811 char *p, *bp, ch; 2812 char buf[LINE_MAX]; 2813 2814 #if __STDC__ 2815 va_start(ap, fmt); 2816 #else 2817 va_start(ap); 2818 #endif 2819 (void)vsnprintf(buf, sizeof(buf), fmt, ap); 2820 2821 /* make ps print our process name */ 2822 p = Argv[0]; 2823 *p++ = '-'; 2824 2825 i = strlen(buf); 2826 if (i > LastArgv - p - 2) { 2827 i = LastArgv - p - 2; 2828 buf[i] = '\0'; 2829 } 2830 bp = buf; 2831 while (ch = *bp++) 2832 if (ch != '\n' && ch != '\r') 2833 *p++ = ch; 2834 while (p < LastArgv) 2835 *p++ = ' '; 2836 } 2837 #endif /* OLD_SETPROCTITLE */ 2838 2839 static void 2840 logxfer(name, size, start) 2841 char *name; 2842 off_t size; 2843 time_t start; 2844 { 2845 char buf[1024]; 2846 char path[MAXPATHLEN + 1]; 2847 time_t now; 2848 2849 if (statfd >= 0 && getwd(path) != NULL) { 2850 time(&now); 2851 snprintf(buf, sizeof(buf), "%.20s!%s!%s!%s/%s!%qd!%ld\n", 2852 ctime(&now)+4, ident, remotehost, 2853 path, name, (long long)size, 2854 (long)(now - start + (now == start))); 2855 write(statfd, buf, strlen(buf)); 2856 } 2857 } 2858