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