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