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