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