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