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