ftpd.c revision 89569
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 89569 2002-01-19 18:29:50Z des $"; 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 opieunlock(); /* XXX */ 1255 if (rval == 0 || (!pwok && rval > 0)) 1256 goto skip; 1257 xpasswd = crypt(passwd, pw->pw_passwd); 1258#else /* !USE_PAM */ 1259 if (opieverify(&opiedata, passwd) == 0) 1260 xpasswd = pw->pw_passwd; 1261 else if (pwok) 1262 xpasswd = crypt(passwd, pw->pw_passwd); 1263 else { 1264 rval = 1; 1265 goto skip; 1266 } 1267#endif /* !USE_PAM */ 1268 rval = strcmp(pw->pw_passwd, xpasswd); 1269 /* The strcmp does not catch null passwords! */ 1270 if (*pw->pw_passwd == '\0' || 1271 (pw->pw_expire && time(NULL) >= pw->pw_expire)) 1272 rval = 1; /* failure */ 1273skip: 1274 /* 1275 * If rval == 1, the user failed the authentication check 1276 * above. If rval == 0, either PAM or local authentication 1277 * succeeded. 1278 */ 1279 if (rval) { 1280 reply(530, "Login incorrect."); 1281 if (logging) 1282 syslog(LOG_NOTICE, 1283 "FTP LOGIN FAILED FROM %s, %s", 1284 remotehost, curname); 1285 pw = NULL; 1286 if (login_attempts++ >= 5) { 1287 syslog(LOG_NOTICE, 1288 "repeated login failures from %s", 1289 remotehost); 1290 exit(0); 1291 } 1292 return; 1293 } 1294 } 1295 login_attempts = 0; /* this time successful */ 1296 if (setegid((gid_t)pw->pw_gid) < 0) { 1297 reply(550, "Can't set gid."); 1298 return; 1299 } 1300 /* May be overridden by login.conf */ 1301 (void) umask(defumask); 1302#ifdef LOGIN_CAP 1303 if ((lc = login_getpwclass(pw)) != NULL) { 1304 char remote_ip[MAXHOSTNAMELEN]; 1305 1306 getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len, 1307 remote_ip, sizeof(remote_ip) - 1, NULL, 0, 1308 NI_NUMERICHOST|NI_WITHSCOPEID); 1309 remote_ip[sizeof(remote_ip) - 1] = 0; 1310 if (!auth_hostok(lc, remotehost, remote_ip)) { 1311 syslog(LOG_INFO|LOG_AUTH, 1312 "FTP LOGIN FAILED (HOST) as %s: permission denied.", 1313 pw->pw_name); 1314 reply(530, "Permission denied.\n"); 1315 pw = NULL; 1316 return; 1317 } 1318 if (!auth_timeok(lc, time(NULL))) { 1319 reply(530, "Login not available right now.\n"); 1320 pw = NULL; 1321 return; 1322 } 1323 } 1324 setusercontext(lc, pw, (uid_t)0, 1325 LOGIN_SETLOGIN|LOGIN_SETGROUP|LOGIN_SETPRIORITY| 1326 LOGIN_SETRESOURCES|LOGIN_SETUMASK); 1327#else 1328 setlogin(pw->pw_name); 1329 (void) initgroups(pw->pw_name, pw->pw_gid); 1330#endif 1331 1332#ifdef USE_PAM 1333 if (pamh) { 1334 if ((e = pam_open_session(pamh, 0)) != PAM_SUCCESS) { 1335 syslog(LOG_ERR, "pam_open_session: %s", pam_strerror(pamh, e)); 1336 } else if ((e = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS) { 1337 syslog(LOG_ERR, "pam_setcred: %s", pam_strerror(pamh, e)); 1338 } 1339 } 1340#endif 1341 1342 /* open wtmp before chroot */ 1343 ftpd_logwtmp(ttyline, pw->pw_name, remotehost); 1344 logged_in = 1; 1345 1346 if (guest && stats && statfd < 0) 1347#ifdef VIRTUAL_HOSTING 1348 if ((statfd = open(thishost->statfile, O_WRONLY|O_APPEND)) < 0) 1349#else 1350 if ((statfd = open(_PATH_FTPDSTATFILE, O_WRONLY|O_APPEND)) < 0) 1351#endif 1352 stats = 0; 1353 1354 dochroot = 1355#ifdef LOGIN_CAP /* Allow login.conf configuration as well */ 1356 login_getcapbool(lc, "ftp-chroot", 0) || 1357#endif 1358 checkuser(_PATH_FTPCHROOT, pw->pw_name, 1); 1359 if (guest) { 1360 /* 1361 * We MUST do a chdir() after the chroot. Otherwise 1362 * the old current directory will be accessible as "." 1363 * outside the new root! 1364 */ 1365 if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) { 1366 reply(550, "Can't set guest privileges."); 1367 goto bad; 1368 } 1369 } else if (dochroot) { 1370 if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) { 1371 reply(550, "Can't change root."); 1372 goto bad; 1373 } 1374 } else if (chdir(pw->pw_dir) < 0) { 1375 if (chdir("/") < 0) { 1376 reply(530, "User %s: can't change directory to %s.", 1377 pw->pw_name, pw->pw_dir); 1378 goto bad; 1379 } else 1380 lreply(230, "No directory! Logging in with home=/"); 1381 } 1382 if (seteuid((uid_t)pw->pw_uid) < 0) { 1383 reply(550, "Can't set uid."); 1384 goto bad; 1385 } 1386 1387 /* 1388 * Display a login message, if it exists. 1389 * N.B. reply(230,) must follow the message. 1390 */ 1391#ifdef VIRTUAL_HOSTING 1392 if ((fd = fopen(thishost->loginmsg, "r")) != NULL) { 1393#else 1394 if ((fd = fopen(_PATH_FTPLOGINMESG, "r")) != NULL) { 1395#endif 1396 char *cp, line[LINE_MAX]; 1397 1398 while (fgets(line, sizeof(line), fd) != NULL) { 1399 if ((cp = strchr(line, '\n')) != NULL) 1400 *cp = '\0'; 1401 lreply(230, "%s", line); 1402 } 1403 (void) fflush(stdout); 1404 (void) fclose(fd); 1405 } 1406 if (guest) { 1407 if (ident != NULL) 1408 free(ident); 1409 ident = strdup(passwd); 1410 if (ident == NULL) 1411 fatalerror("Ran out of memory."); 1412 1413 reply(230, "Guest login ok, access restrictions apply."); 1414#ifdef SETPROCTITLE 1415#ifdef VIRTUAL_HOSTING 1416 if (thishost != firsthost) 1417 snprintf(proctitle, sizeof(proctitle), 1418 "%s: anonymous(%s)/%s", remotehost, hostname, 1419 passwd); 1420 else 1421#endif 1422 snprintf(proctitle, sizeof(proctitle), 1423 "%s: anonymous/%s", remotehost, passwd); 1424 setproctitle("%s", proctitle); 1425#endif /* SETPROCTITLE */ 1426 if (logging) 1427 syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s", 1428 remotehost, passwd); 1429 } else { 1430 if (dochroot) 1431 reply(230, "User %s logged in, " 1432 "access restrictions apply.", pw->pw_name); 1433 else 1434 reply(230, "User %s logged in.", pw->pw_name); 1435 1436#ifdef SETPROCTITLE 1437 snprintf(proctitle, sizeof(proctitle), 1438 "%s: user/%s", remotehost, pw->pw_name); 1439 setproctitle("%s", proctitle); 1440#endif /* SETPROCTITLE */ 1441 if (logging) 1442 syslog(LOG_INFO, "FTP LOGIN FROM %s as %s", 1443 remotehost, pw->pw_name); 1444 } 1445#ifdef LOGIN_CAP 1446 login_close(lc); 1447#endif 1448 return; 1449bad: 1450 /* Forget all about it... */ 1451#ifdef LOGIN_CAP 1452 login_close(lc); 1453#endif 1454 end_login(); 1455} 1456 1457void 1458retrieve(cmd, name) 1459 char *cmd, *name; 1460{ 1461 FILE *fin, *dout; 1462 struct stat st; 1463 int (*closefunc) __P((FILE *)); 1464 time_t start; 1465 1466 if (cmd == 0) { 1467 fin = fopen(name, "r"), closefunc = fclose; 1468 st.st_size = 0; 1469 } else { 1470 char line[BUFSIZ]; 1471 1472 (void) snprintf(line, sizeof(line), cmd, name), name = line; 1473 fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose; 1474 st.st_size = -1; 1475 st.st_blksize = BUFSIZ; 1476 } 1477 if (fin == NULL) { 1478 if (errno != 0) { 1479 perror_reply(550, name); 1480 if (cmd == 0) { 1481 LOGCMD("get", name); 1482 } 1483 } 1484 return; 1485 } 1486 byte_count = -1; 1487 if (cmd == 0 && (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode))) { 1488 reply(550, "%s: not a plain file.", name); 1489 goto done; 1490 } 1491 if (restart_point) { 1492 if (type == TYPE_A) { 1493 off_t i, n; 1494 int c; 1495 1496 n = restart_point; 1497 i = 0; 1498 while (i++ < n) { 1499 if ((c=getc(fin)) == EOF) { 1500 perror_reply(550, name); 1501 goto done; 1502 } 1503 if (c == '\n') 1504 i++; 1505 } 1506 } else if (lseek(fileno(fin), restart_point, L_SET) < 0) { 1507 perror_reply(550, name); 1508 goto done; 1509 } 1510 } 1511 dout = dataconn(name, st.st_size, "w"); 1512 if (dout == NULL) 1513 goto done; 1514 time(&start); 1515 send_data(fin, dout, st.st_blksize, st.st_size, 1516 restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode)); 1517 if (cmd == 0 && guest && stats) 1518 logxfer(name, st.st_size, start); 1519 (void) fclose(dout); 1520 data = -1; 1521 pdata = -1; 1522done: 1523 if (cmd == 0) 1524 LOGBYTES("get", name, byte_count); 1525 (*closefunc)(fin); 1526} 1527 1528void 1529store(name, mode, unique) 1530 char *name, *mode; 1531 int unique; 1532{ 1533 FILE *fout, *din; 1534 struct stat st; 1535 int (*closefunc) __P((FILE *)); 1536 1537 if ((unique || guest) && stat(name, &st) == 0 && 1538 (name = gunique(name)) == NULL) { 1539 LOGCMD(*mode == 'w' ? "put" : "append", name); 1540 return; 1541 } 1542 1543 if (restart_point) 1544 mode = "r+"; 1545 fout = fopen(name, mode); 1546 closefunc = fclose; 1547 if (fout == NULL) { 1548 perror_reply(553, name); 1549 LOGCMD(*mode == 'w' ? "put" : "append", name); 1550 return; 1551 } 1552 byte_count = -1; 1553 if (restart_point) { 1554 if (type == TYPE_A) { 1555 off_t i, n; 1556 int c; 1557 1558 n = restart_point; 1559 i = 0; 1560 while (i++ < n) { 1561 if ((c=getc(fout)) == EOF) { 1562 perror_reply(550, name); 1563 goto done; 1564 } 1565 if (c == '\n') 1566 i++; 1567 } 1568 /* 1569 * We must do this seek to "current" position 1570 * because we are changing from reading to 1571 * writing. 1572 */ 1573 if (fseeko(fout, (off_t)0, SEEK_CUR) < 0) { 1574 perror_reply(550, name); 1575 goto done; 1576 } 1577 } else if (lseek(fileno(fout), restart_point, L_SET) < 0) { 1578 perror_reply(550, name); 1579 goto done; 1580 } 1581 } 1582 din = dataconn(name, (off_t)-1, "r"); 1583 if (din == NULL) 1584 goto done; 1585 if (receive_data(din, fout) == 0) { 1586 if (unique) 1587 reply(226, "Transfer complete (unique file name:%s).", 1588 name); 1589 else 1590 reply(226, "Transfer complete."); 1591 } 1592 (void) fclose(din); 1593 data = -1; 1594 pdata = -1; 1595done: 1596 LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count); 1597 (*closefunc)(fout); 1598} 1599 1600static FILE * 1601getdatasock(mode) 1602 char *mode; 1603{ 1604 int on = 1, s, t, tries; 1605 1606 if (data >= 0) 1607 return (fdopen(data, mode)); 1608 (void) seteuid((uid_t)0); 1609 1610 s = socket(data_dest.su_family, SOCK_STREAM, 0); 1611 if (s < 0) 1612 goto bad; 1613 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 1614 (char *) &on, sizeof(on)) < 0) 1615 goto bad; 1616 /* anchor socket to avoid multi-homing problems */ 1617 data_source = ctrl_addr; 1618 data_source.su_port = htons(20); /* ftp-data port */ 1619 for (tries = 1; ; tries++) { 1620 if (bind(s, (struct sockaddr *)&data_source, 1621 data_source.su_len) >= 0) 1622 break; 1623 if (errno != EADDRINUSE || tries > 10) 1624 goto bad; 1625 sleep(tries); 1626 } 1627 (void) seteuid((uid_t)pw->pw_uid); 1628#ifdef IP_TOS 1629 if (data_source.su_family == AF_INET) 1630 { 1631 on = IPTOS_THROUGHPUT; 1632 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) 1633 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); 1634 } 1635#endif 1636#ifdef TCP_NOPUSH 1637 /* 1638 * Turn off push flag to keep sender TCP from sending short packets 1639 * at the boundaries of each write(). Should probably do a SO_SNDBUF 1640 * to set the send buffer size as well, but that may not be desirable 1641 * in heavy-load situations. 1642 */ 1643 on = 1; 1644 if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, (char *)&on, sizeof on) < 0) 1645 syslog(LOG_WARNING, "setsockopt (TCP_NOPUSH): %m"); 1646#endif 1647#ifdef SO_SNDBUF 1648 on = 65536; 1649 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&on, sizeof on) < 0) 1650 syslog(LOG_WARNING, "setsockopt (SO_SNDBUF): %m"); 1651#endif 1652 1653 return (fdopen(s, mode)); 1654bad: 1655 /* Return the real value of errno (close may change it) */ 1656 t = errno; 1657 (void) seteuid((uid_t)pw->pw_uid); 1658 (void) close(s); 1659 errno = t; 1660 return (NULL); 1661} 1662 1663static FILE * 1664dataconn(name, size, mode) 1665 char *name; 1666 off_t size; 1667 char *mode; 1668{ 1669 char sizebuf[32]; 1670 FILE *file; 1671 int retry = 0, tos; 1672 1673 file_size = size; 1674 byte_count = 0; 1675 if (size != (off_t) -1) 1676 (void) snprintf(sizebuf, sizeof(sizebuf), " (%qd bytes)", size); 1677 else 1678 *sizebuf = '\0'; 1679 if (pdata >= 0) { 1680 union sockunion from; 1681 int flags; 1682 int s, fromlen = ctrl_addr.su_len; 1683 struct timeval timeout; 1684 fd_set set; 1685 1686 FD_ZERO(&set); 1687 FD_SET(pdata, &set); 1688 1689 timeout.tv_usec = 0; 1690 timeout.tv_sec = 120; 1691 1692 /* 1693 * Granted a socket is in the blocking I/O mode, 1694 * accept() will block after a successful select() 1695 * if the selected connection dies in between. 1696 * Therefore set the non-blocking I/O flag here. 1697 */ 1698 if ((flags = fcntl(pdata, F_GETFL, 0)) == -1 || 1699 fcntl(pdata, F_SETFL, flags | O_NONBLOCK) == -1) 1700 goto pdata_err; 1701 if (select(pdata+1, &set, (fd_set *) 0, (fd_set *) 0, &timeout) <= 0 || 1702 (s = accept(pdata, (struct sockaddr *) &from, &fromlen)) < 0) 1703 goto pdata_err; 1704 (void) close(pdata); 1705 pdata = s; 1706 /* 1707 * Unset the blocking I/O flag on the child socket 1708 * again so stdio can work on it. 1709 */ 1710 if ((flags = fcntl(pdata, F_GETFL, 0)) == -1 || 1711 fcntl(pdata, F_SETFL, flags & ~O_NONBLOCK) == -1) 1712 goto pdata_err; 1713#ifdef IP_TOS 1714 if (from.su_family == AF_INET) 1715 { 1716 tos = IPTOS_THROUGHPUT; 1717 (void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, 1718 sizeof(int)); 1719 } 1720#endif 1721 reply(150, "Opening %s mode data connection for '%s'%s.", 1722 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); 1723 return (fdopen(pdata, mode)); 1724pdata_err: 1725 reply(425, "Can't open data connection."); 1726 (void) close(pdata); 1727 pdata = -1; 1728 return (NULL); 1729 } 1730 if (data >= 0) { 1731 reply(125, "Using existing data connection for '%s'%s.", 1732 name, sizebuf); 1733 usedefault = 1; 1734 return (fdopen(data, mode)); 1735 } 1736 if (usedefault) 1737 data_dest = his_addr; 1738 usedefault = 1; 1739 file = getdatasock(mode); 1740 if (file == NULL) { 1741 char hostbuf[BUFSIZ], portbuf[BUFSIZ]; 1742 getnameinfo((struct sockaddr *)&data_source, 1743 data_source.su_len, hostbuf, sizeof(hostbuf) - 1, 1744 portbuf, sizeof(portbuf), 1745 NI_NUMERICHOST|NI_NUMERICSERV|NI_WITHSCOPEID); 1746 reply(425, "Can't create data socket (%s,%s): %s.", 1747 hostbuf, portbuf, strerror(errno)); 1748 return (NULL); 1749 } 1750 data = fileno(file); 1751 while (connect(data, (struct sockaddr *)&data_dest, 1752 data_dest.su_len) < 0) { 1753 if (errno == EADDRINUSE && retry < swaitmax) { 1754 sleep((unsigned) swaitint); 1755 retry += swaitint; 1756 continue; 1757 } 1758 perror_reply(425, "Can't build data connection"); 1759 (void) fclose(file); 1760 data = -1; 1761 return (NULL); 1762 } 1763 reply(150, "Opening %s mode data connection for '%s'%s.", 1764 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); 1765 return (file); 1766} 1767 1768/* 1769 * Tranfer the contents of "instr" to "outstr" peer using the appropriate 1770 * encapsulation of the data subject to Mode, Structure, and Type. 1771 * 1772 * NB: Form isn't handled. 1773 */ 1774static void 1775send_data(instr, outstr, blksize, filesize, isreg) 1776 FILE *instr, *outstr; 1777 off_t blksize; 1778 off_t filesize; 1779 int isreg; 1780{ 1781 int c, filefd, netfd; 1782 char *buf; 1783 size_t len; 1784 off_t cnt; 1785 1786 transflag++; 1787 if (setjmp(urgcatch)) { 1788 transflag = 0; 1789 return; 1790 } 1791 switch (type) { 1792 1793 case TYPE_A: 1794 while ((c = getc(instr)) != EOF) { 1795 byte_count++; 1796 if (c == '\n') { 1797 if (ferror(outstr)) 1798 goto data_err; 1799 (void) putc('\r', outstr); 1800 } 1801 (void) putc(c, outstr); 1802 } 1803 fflush(outstr); 1804 transflag = 0; 1805 if (ferror(instr)) 1806 goto file_err; 1807 if (ferror(outstr)) 1808 goto data_err; 1809 reply(226, "Transfer complete."); 1810 return; 1811 1812 case TYPE_I: 1813 case TYPE_L: 1814 /* 1815 * isreg is only set if we are not doing restart and we 1816 * are sending a regular file 1817 */ 1818 netfd = fileno(outstr); 1819 filefd = fileno(instr); 1820 1821 if (isreg) { 1822 1823 off_t offset; 1824 int err; 1825 1826 len = filesize; 1827 err = cnt = offset = 0; 1828 1829 while (err != -1 && cnt < filesize) { 1830 err = sendfile(filefd, netfd, offset, len, 1831 (struct sf_hdtr *) NULL, &cnt, 0); 1832 byte_count += cnt; 1833 offset += cnt; 1834 len -= cnt; 1835 1836 if (err == -1) { 1837 if (!cnt) 1838 goto oldway; 1839 1840 goto data_err; 1841 } 1842 } 1843 1844 reply(226, "Transfer complete."); 1845 return; 1846 } 1847 1848oldway: 1849 if ((buf = malloc((u_int)blksize)) == NULL) { 1850 transflag = 0; 1851 perror_reply(451, "Local resource failure: malloc"); 1852 return; 1853 } 1854 1855 while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 && 1856 write(netfd, buf, cnt) == cnt) 1857 byte_count += cnt; 1858 transflag = 0; 1859 (void)free(buf); 1860 if (cnt != 0) { 1861 if (cnt < 0) 1862 goto file_err; 1863 goto data_err; 1864 } 1865 reply(226, "Transfer complete."); 1866 return; 1867 default: 1868 transflag = 0; 1869 reply(550, "Unimplemented TYPE %d in send_data", type); 1870 return; 1871 } 1872 1873data_err: 1874 transflag = 0; 1875 perror_reply(426, "Data connection"); 1876 return; 1877 1878file_err: 1879 transflag = 0; 1880 perror_reply(551, "Error on input file"); 1881} 1882 1883/* 1884 * Transfer data from peer to "outstr" using the appropriate encapulation of 1885 * the data subject to Mode, Structure, and Type. 1886 * 1887 * N.B.: Form isn't handled. 1888 */ 1889static int 1890receive_data(instr, outstr) 1891 FILE *instr, *outstr; 1892{ 1893 int c; 1894 int cnt, bare_lfs; 1895 char buf[BUFSIZ]; 1896 1897 transflag++; 1898 if (setjmp(urgcatch)) { 1899 transflag = 0; 1900 return (-1); 1901 } 1902 1903 bare_lfs = 0; 1904 1905 switch (type) { 1906 1907 case TYPE_I: 1908 case TYPE_L: 1909 while ((cnt = read(fileno(instr), buf, sizeof(buf))) > 0) { 1910 if (write(fileno(outstr), buf, cnt) != cnt) 1911 goto file_err; 1912 byte_count += cnt; 1913 } 1914 if (cnt < 0) 1915 goto data_err; 1916 transflag = 0; 1917 return (0); 1918 1919 case TYPE_E: 1920 reply(553, "TYPE E not implemented."); 1921 transflag = 0; 1922 return (-1); 1923 1924 case TYPE_A: 1925 while ((c = getc(instr)) != EOF) { 1926 byte_count++; 1927 if (c == '\n') 1928 bare_lfs++; 1929 while (c == '\r') { 1930 if (ferror(outstr)) 1931 goto data_err; 1932 if ((c = getc(instr)) != '\n') { 1933 (void) putc ('\r', outstr); 1934 if (c == '\0' || c == EOF) 1935 goto contin2; 1936 } 1937 } 1938 (void) putc(c, outstr); 1939 contin2: ; 1940 } 1941 fflush(outstr); 1942 if (ferror(instr)) 1943 goto data_err; 1944 if (ferror(outstr)) 1945 goto file_err; 1946 transflag = 0; 1947 if (bare_lfs) { 1948 lreply(226, 1949 "WARNING! %d bare linefeeds received in ASCII mode", 1950 bare_lfs); 1951 (void)printf(" File may not have transferred correctly.\r\n"); 1952 } 1953 return (0); 1954 default: 1955 reply(550, "Unimplemented TYPE %d in receive_data", type); 1956 transflag = 0; 1957 return (-1); 1958 } 1959 1960data_err: 1961 transflag = 0; 1962 perror_reply(426, "Data Connection"); 1963 return (-1); 1964 1965file_err: 1966 transflag = 0; 1967 perror_reply(452, "Error writing file"); 1968 return (-1); 1969} 1970 1971void 1972statfilecmd(filename) 1973 char *filename; 1974{ 1975 FILE *fin; 1976 int c; 1977 char line[LINE_MAX]; 1978 1979 (void)snprintf(line, sizeof(line), _PATH_LS " -lgA %s", filename); 1980 fin = ftpd_popen(line, "r"); 1981 lreply(211, "status of %s:", filename); 1982 while ((c = getc(fin)) != EOF) { 1983 if (c == '\n') { 1984 if (ferror(stdout)){ 1985 perror_reply(421, "control connection"); 1986 (void) ftpd_pclose(fin); 1987 dologout(1); 1988 /* NOTREACHED */ 1989 } 1990 if (ferror(fin)) { 1991 perror_reply(551, filename); 1992 (void) ftpd_pclose(fin); 1993 return; 1994 } 1995 (void) putc('\r', stdout); 1996 } 1997 (void) putc(c, stdout); 1998 } 1999 (void) ftpd_pclose(fin); 2000 reply(211, "End of Status"); 2001} 2002 2003void 2004statcmd() 2005{ 2006 union sockunion *su; 2007 u_char *a, *p; 2008 char hname[INET6_ADDRSTRLEN]; 2009 int ispassive; 2010 2011 lreply(211, "%s FTP server status:", hostname, version); 2012 printf(" %s\r\n", version); 2013 printf(" Connected to %s", remotehost); 2014 if (!getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len, 2015 hname, sizeof(hname) - 1, NULL, 0, 2016 NI_NUMERICHOST|NI_WITHSCOPEID)) { 2017 if (strcmp(hname, remotehost) != 0) 2018 printf(" (%s)", hname); 2019 } 2020 printf("\r\n"); 2021 if (logged_in) { 2022 if (guest) 2023 printf(" Logged in anonymously\r\n"); 2024 else 2025 printf(" Logged in as %s\r\n", pw->pw_name); 2026 } else if (askpasswd) 2027 printf(" Waiting for password\r\n"); 2028 else 2029 printf(" Waiting for user name\r\n"); 2030 printf(" TYPE: %s", typenames[type]); 2031 if (type == TYPE_A || type == TYPE_E) 2032 printf(", FORM: %s", formnames[form]); 2033 if (type == TYPE_L) 2034#if NBBY == 8 2035 printf(" %d", NBBY); 2036#else 2037 printf(" %d", bytesize); /* need definition! */ 2038#endif 2039 printf("; STRUcture: %s; transfer MODE: %s\r\n", 2040 strunames[stru], modenames[mode]); 2041 if (data != -1) 2042 printf(" Data connection open\r\n"); 2043 else if (pdata != -1) { 2044 ispassive = 1; 2045 su = &pasv_addr; 2046 goto printaddr; 2047 } else if (usedefault == 0) { 2048 ispassive = 0; 2049 su = &data_dest; 2050printaddr: 2051#define UC(b) (((int) b) & 0xff) 2052 if (epsvall) { 2053 printf(" EPSV only mode (EPSV ALL)\r\n"); 2054 goto epsvonly; 2055 } 2056 2057 /* PORT/PASV */ 2058 if (su->su_family == AF_INET) { 2059 a = (u_char *) &su->su_sin.sin_addr; 2060 p = (u_char *) &su->su_sin.sin_port; 2061 printf(" %s (%d,%d,%d,%d,%d,%d)\r\n", 2062 ispassive ? "PASV" : "PORT", 2063 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 2064 UC(p[0]), UC(p[1])); 2065 } 2066 2067 /* LPRT/LPSV */ 2068 { 2069 int alen, af, i; 2070 2071 switch (su->su_family) { 2072 case AF_INET: 2073 a = (u_char *) &su->su_sin.sin_addr; 2074 p = (u_char *) &su->su_sin.sin_port; 2075 alen = sizeof(su->su_sin.sin_addr); 2076 af = 4; 2077 break; 2078 case AF_INET6: 2079 a = (u_char *) &su->su_sin6.sin6_addr; 2080 p = (u_char *) &su->su_sin6.sin6_port; 2081 alen = sizeof(su->su_sin6.sin6_addr); 2082 af = 6; 2083 break; 2084 default: 2085 af = 0; 2086 break; 2087 } 2088 if (af) { 2089 printf(" %s (%d,%d,", ispassive ? "LPSV" : "LPRT", 2090 af, alen); 2091 for (i = 0; i < alen; i++) 2092 printf("%d,", UC(a[i])); 2093 printf("%d,%d,%d)\r\n", 2, UC(p[0]), UC(p[1])); 2094 } 2095 } 2096 2097epsvonly:; 2098 /* EPRT/EPSV */ 2099 { 2100 int af; 2101 2102 switch (su->su_family) { 2103 case AF_INET: 2104 af = 1; 2105 break; 2106 case AF_INET6: 2107 af = 2; 2108 break; 2109 default: 2110 af = 0; 2111 break; 2112 } 2113 if (af) { 2114 if (!getnameinfo((struct sockaddr *)su, su->su_len, 2115 hname, sizeof(hname) - 1, NULL, 0, 2116 NI_NUMERICHOST)) { 2117 printf(" %s |%d|%s|%d|\r\n", 2118 ispassive ? "EPSV" : "EPRT", 2119 af, hname, htons(su->su_port)); 2120 } 2121 } 2122 } 2123#undef UC 2124 } else 2125 printf(" No data connection\r\n"); 2126 reply(211, "End of status"); 2127} 2128 2129void 2130fatalerror(s) 2131 char *s; 2132{ 2133 2134 reply(451, "Error in server: %s\n", s); 2135 reply(221, "Closing connection due to server error."); 2136 dologout(0); 2137 /* NOTREACHED */ 2138} 2139 2140void 2141#if __STDC__ 2142reply(int n, const char *fmt, ...) 2143#else 2144reply(n, fmt, va_alist) 2145 int n; 2146 char *fmt; 2147 va_dcl 2148#endif 2149{ 2150 va_list ap; 2151#if __STDC__ 2152 va_start(ap, fmt); 2153#else 2154 va_start(ap); 2155#endif 2156 (void)printf("%d ", n); 2157 (void)vprintf(fmt, ap); 2158 (void)printf("\r\n"); 2159 (void)fflush(stdout); 2160 if (ftpdebug) { 2161 syslog(LOG_DEBUG, "<--- %d ", n); 2162 vsyslog(LOG_DEBUG, fmt, ap); 2163 } 2164} 2165 2166void 2167#if __STDC__ 2168lreply(int n, const char *fmt, ...) 2169#else 2170lreply(n, fmt, va_alist) 2171 int n; 2172 char *fmt; 2173 va_dcl 2174#endif 2175{ 2176 va_list ap; 2177#if __STDC__ 2178 va_start(ap, fmt); 2179#else 2180 va_start(ap); 2181#endif 2182 (void)printf("%d- ", n); 2183 (void)vprintf(fmt, ap); 2184 (void)printf("\r\n"); 2185 (void)fflush(stdout); 2186 if (ftpdebug) { 2187 syslog(LOG_DEBUG, "<--- %d- ", n); 2188 vsyslog(LOG_DEBUG, fmt, ap); 2189 } 2190} 2191 2192static void 2193ack(s) 2194 char *s; 2195{ 2196 2197 reply(250, "%s command successful.", s); 2198} 2199 2200void 2201nack(s) 2202 char *s; 2203{ 2204 2205 reply(502, "%s command not implemented.", s); 2206} 2207 2208/* ARGSUSED */ 2209void 2210yyerror(s) 2211 char *s; 2212{ 2213 char *cp; 2214 2215 if ((cp = strchr(cbuf,'\n'))) 2216 *cp = '\0'; 2217 reply(500, "'%s': command not understood.", cbuf); 2218} 2219 2220void 2221delete(name) 2222 char *name; 2223{ 2224 struct stat st; 2225 2226 LOGCMD("delete", name); 2227 if (stat(name, &st) < 0) { 2228 perror_reply(550, name); 2229 return; 2230 } 2231 if ((st.st_mode&S_IFMT) == S_IFDIR) { 2232 if (rmdir(name) < 0) { 2233 perror_reply(550, name); 2234 return; 2235 } 2236 goto done; 2237 } 2238 if (unlink(name) < 0) { 2239 perror_reply(550, name); 2240 return; 2241 } 2242done: 2243 ack("DELE"); 2244} 2245 2246void 2247cwd(path) 2248 char *path; 2249{ 2250 2251 if (chdir(path) < 0) 2252 perror_reply(550, path); 2253 else 2254 ack("CWD"); 2255} 2256 2257void 2258makedir(name) 2259 char *name; 2260{ 2261 2262 LOGCMD("mkdir", name); 2263 if (mkdir(name, 0777) < 0) 2264 perror_reply(550, name); 2265 else 2266 reply(257, "MKD command successful."); 2267} 2268 2269void 2270removedir(name) 2271 char *name; 2272{ 2273 2274 LOGCMD("rmdir", name); 2275 if (rmdir(name) < 0) 2276 perror_reply(550, name); 2277 else 2278 ack("RMD"); 2279} 2280 2281void 2282pwd() 2283{ 2284 char path[MAXPATHLEN + 1]; 2285 2286 if (getwd(path) == (char *)NULL) 2287 reply(550, "%s.", path); 2288 else 2289 reply(257, "\"%s\" is current directory.", path); 2290} 2291 2292char * 2293renamefrom(name) 2294 char *name; 2295{ 2296 struct stat st; 2297 2298 if (stat(name, &st) < 0) { 2299 perror_reply(550, name); 2300 return ((char *)0); 2301 } 2302 reply(350, "File exists, ready for destination name"); 2303 return (name); 2304} 2305 2306void 2307renamecmd(from, to) 2308 char *from, *to; 2309{ 2310 struct stat st; 2311 2312 LOGCMD2("rename", from, to); 2313 2314 if (guest && (stat(to, &st) == 0)) { 2315 reply(550, "%s: permission denied", to); 2316 return; 2317 } 2318 2319 if (rename(from, to) < 0) 2320 perror_reply(550, "rename"); 2321 else 2322 ack("RNTO"); 2323} 2324 2325static void 2326dolog(who) 2327 struct sockaddr *who; 2328{ 2329 int error; 2330 2331 realhostname_sa(remotehost, sizeof(remotehost) - 1, who, who->sa_len); 2332 2333#ifdef SETPROCTITLE 2334#ifdef VIRTUAL_HOSTING 2335 if (thishost != firsthost) 2336 snprintf(proctitle, sizeof(proctitle), "%s: connected (to %s)", 2337 remotehost, hostname); 2338 else 2339#endif 2340 snprintf(proctitle, sizeof(proctitle), "%s: connected", 2341 remotehost); 2342 setproctitle("%s", proctitle); 2343#endif /* SETPROCTITLE */ 2344 2345 if (logging) { 2346#ifdef VIRTUAL_HOSTING 2347 if (thishost != firsthost) 2348 syslog(LOG_INFO, "connection from %s (to %s)", 2349 remotehost, hostname); 2350 else 2351#endif 2352 { 2353 char who_name[MAXHOSTNAMELEN]; 2354 2355 error = getnameinfo(who, who->sa_len, 2356 who_name, sizeof(who_name) - 1, 2357 NULL, 0, 2358 NI_NUMERICHOST|NI_WITHSCOPEID); 2359 syslog(LOG_INFO, "connection from %s (%s)", remotehost, 2360 error == 0 ? who_name : ""); 2361 } 2362 } 2363} 2364 2365/* 2366 * Record logout in wtmp file 2367 * and exit with supplied status. 2368 */ 2369void 2370dologout(status) 2371 int status; 2372{ 2373 /* 2374 * Prevent reception of SIGURG from resulting in a resumption 2375 * back to the main program loop. 2376 */ 2377 transflag = 0; 2378 2379 if (logged_in) { 2380 (void) seteuid((uid_t)0); 2381 ftpd_logwtmp(ttyline, "", ""); 2382 } 2383 /* beware of flushing buffers after a SIGPIPE */ 2384 _exit(status); 2385} 2386 2387static void 2388myoob(signo) 2389 int signo; 2390{ 2391 char *cp; 2392 2393 /* only process if transfer occurring */ 2394 if (!transflag) 2395 return; 2396 cp = tmpline; 2397 if (getline(cp, 7, stdin) == NULL) { 2398 reply(221, "You could at least say goodbye."); 2399 dologout(0); 2400 } 2401 upper(cp); 2402 if (strcmp(cp, "ABOR\r\n") == 0) { 2403 tmpline[0] = '\0'; 2404 reply(426, "Transfer aborted. Data connection closed."); 2405 reply(226, "Abort successful"); 2406 longjmp(urgcatch, 1); 2407 } 2408 if (strcmp(cp, "STAT\r\n") == 0) { 2409 tmpline[0] = '\0'; 2410 if (file_size != (off_t) -1) 2411 reply(213, "Status: %qd of %qd bytes transferred", 2412 byte_count, file_size); 2413 else 2414 reply(213, "Status: %qd bytes transferred", byte_count); 2415 } 2416} 2417 2418/* 2419 * Note: a response of 425 is not mentioned as a possible response to 2420 * the PASV command in RFC959. However, it has been blessed as 2421 * a legitimate response by Jon Postel in a telephone conversation 2422 * with Rick Adams on 25 Jan 89. 2423 */ 2424void 2425passive() 2426{ 2427 int len; 2428 char *p, *a; 2429 2430 if (pdata >= 0) /* close old port if one set */ 2431 close(pdata); 2432 2433 pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0); 2434 if (pdata < 0) { 2435 perror_reply(425, "Can't open passive connection"); 2436 return; 2437 } 2438 2439 (void) seteuid((uid_t)0); 2440 2441#ifdef IP_PORTRANGE 2442 if (ctrl_addr.su_family == AF_INET) { 2443 int on = restricted_data_ports ? IP_PORTRANGE_HIGH 2444 : IP_PORTRANGE_DEFAULT; 2445 2446 if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE, 2447 (char *)&on, sizeof(on)) < 0) 2448 goto pasv_error; 2449 } 2450#endif 2451#ifdef IPV6_PORTRANGE 2452 if (ctrl_addr.su_family == AF_INET6) { 2453 int on = restricted_data_ports ? IPV6_PORTRANGE_HIGH 2454 : IPV6_PORTRANGE_DEFAULT; 2455 2456 if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE, 2457 (char *)&on, sizeof(on)) < 0) 2458 goto pasv_error; 2459 } 2460#endif 2461 2462 pasv_addr = ctrl_addr; 2463 pasv_addr.su_port = 0; 2464 if (bind(pdata, (struct sockaddr *)&pasv_addr, pasv_addr.su_len) < 0) 2465 goto pasv_error; 2466 2467 (void) seteuid((uid_t)pw->pw_uid); 2468 2469 len = sizeof(pasv_addr); 2470 if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0) 2471 goto pasv_error; 2472 if (listen(pdata, 1) < 0) 2473 goto pasv_error; 2474 if (pasv_addr.su_family == AF_INET) 2475 a = (char *) &pasv_addr.su_sin.sin_addr; 2476 else if (pasv_addr.su_family == AF_INET6 && 2477 IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr)) 2478 a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12]; 2479 else 2480 goto pasv_error; 2481 2482 p = (char *) &pasv_addr.su_port; 2483 2484#define UC(b) (((int) b) & 0xff) 2485 2486 reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]), 2487 UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); 2488 return; 2489 2490pasv_error: 2491 (void) seteuid((uid_t)pw->pw_uid); 2492 (void) close(pdata); 2493 pdata = -1; 2494 perror_reply(425, "Can't open passive connection"); 2495 return; 2496} 2497 2498/* 2499 * Long Passive defined in RFC 1639. 2500 * 228 Entering Long Passive Mode 2501 * (af, hal, h1, h2, h3,..., pal, p1, p2...) 2502 */ 2503 2504void 2505long_passive(cmd, pf) 2506 char *cmd; 2507 int pf; 2508{ 2509 int len; 2510 char *p, *a; 2511 2512 if (pdata >= 0) /* close old port if one set */ 2513 close(pdata); 2514 2515 if (pf != PF_UNSPEC) { 2516 if (ctrl_addr.su_family != pf) { 2517 switch (ctrl_addr.su_family) { 2518 case AF_INET: 2519 pf = 1; 2520 break; 2521 case AF_INET6: 2522 pf = 2; 2523 break; 2524 default: 2525 pf = 0; 2526 break; 2527 } 2528 /* 2529 * XXX 2530 * only EPRT/EPSV ready clients will understand this 2531 */ 2532 if (strcmp(cmd, "EPSV") == 0 && pf) { 2533 reply(522, "Network protocol mismatch, " 2534 "use (%d)", pf); 2535 } else 2536 reply(501, "Network protocol mismatch"); /*XXX*/ 2537 2538 return; 2539 } 2540 } 2541 2542 pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0); 2543 if (pdata < 0) { 2544 perror_reply(425, "Can't open passive connection"); 2545 return; 2546 } 2547 2548 (void) seteuid((uid_t)0); 2549 2550 pasv_addr = ctrl_addr; 2551 pasv_addr.su_port = 0; 2552 len = pasv_addr.su_len; 2553 2554#ifdef IP_PORTRANGE 2555 if (ctrl_addr.su_family == AF_INET) { 2556 int on = restricted_data_ports ? IP_PORTRANGE_HIGH 2557 : IP_PORTRANGE_DEFAULT; 2558 2559 if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE, 2560 (char *)&on, sizeof(on)) < 0) 2561 goto pasv_error; 2562 } 2563#endif 2564#ifdef IPV6_PORTRANGE 2565 if (ctrl_addr.su_family == AF_INET6) { 2566 int on = restricted_data_ports ? IPV6_PORTRANGE_HIGH 2567 : IPV6_PORTRANGE_DEFAULT; 2568 2569 if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE, 2570 (char *)&on, sizeof(on)) < 0) 2571 goto pasv_error; 2572 } 2573#endif 2574 2575 if (bind(pdata, (struct sockaddr *)&pasv_addr, len) < 0) 2576 goto pasv_error; 2577 2578 (void) seteuid((uid_t)pw->pw_uid); 2579 2580 if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0) 2581 goto pasv_error; 2582 if (listen(pdata, 1) < 0) 2583 goto pasv_error; 2584 2585#define UC(b) (((int) b) & 0xff) 2586 2587 if (strcmp(cmd, "LPSV") == 0) { 2588 p = (char *)&pasv_addr.su_port; 2589 switch (pasv_addr.su_family) { 2590 case AF_INET: 2591 a = (char *) &pasv_addr.su_sin.sin_addr; 2592 v4_reply: 2593 reply(228, 2594"Entering Long Passive Mode (%d,%d,%d,%d,%d,%d,%d,%d,%d)", 2595 4, 4, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 2596 2, UC(p[0]), UC(p[1])); 2597 return; 2598 case AF_INET6: 2599 if (IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr)) { 2600 a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12]; 2601 goto v4_reply; 2602 } 2603 a = (char *) &pasv_addr.su_sin6.sin6_addr; 2604 reply(228, 2605"Entering Long Passive Mode " 2606"(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)", 2607 6, 16, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 2608 UC(a[4]), UC(a[5]), UC(a[6]), UC(a[7]), 2609 UC(a[8]), UC(a[9]), UC(a[10]), UC(a[11]), 2610 UC(a[12]), UC(a[13]), UC(a[14]), UC(a[15]), 2611 2, UC(p[0]), UC(p[1])); 2612 return; 2613 } 2614 } else if (strcmp(cmd, "EPSV") == 0) { 2615 switch (pasv_addr.su_family) { 2616 case AF_INET: 2617 case AF_INET6: 2618 reply(229, "Entering Extended Passive Mode (|||%d|)", 2619 ntohs(pasv_addr.su_port)); 2620 return; 2621 } 2622 } else { 2623 /* more proper error code? */ 2624 } 2625 2626pasv_error: 2627 (void) seteuid((uid_t)pw->pw_uid); 2628 (void) close(pdata); 2629 pdata = -1; 2630 perror_reply(425, "Can't open passive connection"); 2631 return; 2632} 2633 2634/* 2635 * Generate unique name for file with basename "local". 2636 * The file named "local" is already known to exist. 2637 * Generates failure reply on error. 2638 */ 2639static char * 2640gunique(local) 2641 char *local; 2642{ 2643 static char new[MAXPATHLEN]; 2644 struct stat st; 2645 int count; 2646 char *cp; 2647 2648 cp = strrchr(local, '/'); 2649 if (cp) 2650 *cp = '\0'; 2651 if (stat(cp ? local : ".", &st) < 0) { 2652 perror_reply(553, cp ? local : "."); 2653 return ((char *) 0); 2654 } 2655 if (cp) 2656 *cp = '/'; 2657 /* -4 is for the .nn<null> we put on the end below */ 2658 (void) snprintf(new, sizeof(new) - 4, "%s", local); 2659 cp = new + strlen(new); 2660 *cp++ = '.'; 2661 for (count = 1; count < 100; count++) { 2662 (void)sprintf(cp, "%d", count); 2663 if (stat(new, &st) < 0) 2664 return (new); 2665 } 2666 reply(452, "Unique file name cannot be created."); 2667 return (NULL); 2668} 2669 2670/* 2671 * Format and send reply containing system error number. 2672 */ 2673void 2674perror_reply(code, string) 2675 int code; 2676 char *string; 2677{ 2678 2679 reply(code, "%s: %s.", string, strerror(errno)); 2680} 2681 2682static char *onefile[] = { 2683 "", 2684 0 2685}; 2686 2687void 2688send_file_list(whichf) 2689 char *whichf; 2690{ 2691 struct stat st; 2692 DIR *dirp = NULL; 2693 struct dirent *dir; 2694 FILE *dout = NULL; 2695 char **dirlist, *dirname; 2696 int simple = 0; 2697 int freeglob = 0; 2698 glob_t gl; 2699 2700 if (strpbrk(whichf, "~{[*?") != NULL) { 2701 int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE; 2702 2703 memset(&gl, 0, sizeof(gl)); 2704 gl.gl_matchc = MAXGLOBARGS; 2705 flags |= GLOB_LIMIT; 2706 freeglob = 1; 2707 if (glob(whichf, flags, 0, &gl)) { 2708 reply(550, "not found"); 2709 goto out; 2710 } else if (gl.gl_pathc == 0) { 2711 errno = ENOENT; 2712 perror_reply(550, whichf); 2713 goto out; 2714 } 2715 dirlist = gl.gl_pathv; 2716 } else { 2717 onefile[0] = whichf; 2718 dirlist = onefile; 2719 simple = 1; 2720 } 2721 2722 if (setjmp(urgcatch)) { 2723 transflag = 0; 2724 goto out; 2725 } 2726 while ((dirname = *dirlist++)) { 2727 if (stat(dirname, &st) < 0) { 2728 /* 2729 * If user typed "ls -l", etc, and the client 2730 * used NLST, do what the user meant. 2731 */ 2732 if (dirname[0] == '-' && *dirlist == NULL && 2733 transflag == 0) { 2734 retrieve(_PATH_LS " %s", dirname); 2735 goto out; 2736 } 2737 perror_reply(550, whichf); 2738 if (dout != NULL) { 2739 (void) fclose(dout); 2740 transflag = 0; 2741 data = -1; 2742 pdata = -1; 2743 } 2744 goto out; 2745 } 2746 2747 if (S_ISREG(st.st_mode)) { 2748 if (dout == NULL) { 2749 dout = dataconn("file list", (off_t)-1, "w"); 2750 if (dout == NULL) 2751 goto out; 2752 transflag++; 2753 } 2754 fprintf(dout, "%s%s\n", dirname, 2755 type == TYPE_A ? "\r" : ""); 2756 byte_count += strlen(dirname) + 1; 2757 continue; 2758 } else if (!S_ISDIR(st.st_mode)) 2759 continue; 2760 2761 if ((dirp = opendir(dirname)) == NULL) 2762 continue; 2763 2764 while ((dir = readdir(dirp)) != NULL) { 2765 char nbuf[MAXPATHLEN]; 2766 2767 if (dir->d_name[0] == '.' && dir->d_namlen == 1) 2768 continue; 2769 if (dir->d_name[0] == '.' && dir->d_name[1] == '.' && 2770 dir->d_namlen == 2) 2771 continue; 2772 2773 snprintf(nbuf, sizeof(nbuf), 2774 "%s/%s", dirname, dir->d_name); 2775 2776 /* 2777 * We have to do a stat to insure it's 2778 * not a directory or special file. 2779 */ 2780 if (simple || (stat(nbuf, &st) == 0 && 2781 S_ISREG(st.st_mode))) { 2782 if (dout == NULL) { 2783 dout = dataconn("file list", (off_t)-1, 2784 "w"); 2785 if (dout == NULL) 2786 goto out; 2787 transflag++; 2788 } 2789 if (nbuf[0] == '.' && nbuf[1] == '/') 2790 fprintf(dout, "%s%s\n", &nbuf[2], 2791 type == TYPE_A ? "\r" : ""); 2792 else 2793 fprintf(dout, "%s%s\n", nbuf, 2794 type == TYPE_A ? "\r" : ""); 2795 byte_count += strlen(nbuf) + 1; 2796 } 2797 } 2798 (void) closedir(dirp); 2799 } 2800 2801 if (dout == NULL) 2802 reply(550, "No files found."); 2803 else if (ferror(dout) != 0) 2804 perror_reply(550, "Data connection"); 2805 else 2806 reply(226, "Transfer complete."); 2807 2808 transflag = 0; 2809 if (dout != NULL) 2810 (void) fclose(dout); 2811 data = -1; 2812 pdata = -1; 2813out: 2814 if (freeglob) { 2815 freeglob = 0; 2816 globfree(&gl); 2817 } 2818} 2819 2820void 2821reapchild(signo) 2822 int signo; 2823{ 2824 while (wait3(NULL, WNOHANG, NULL) > 0); 2825} 2826 2827#ifdef OLD_SETPROCTITLE 2828/* 2829 * Clobber argv so ps will show what we're doing. (Stolen from sendmail.) 2830 * Warning, since this is usually started from inetd.conf, it often doesn't 2831 * have much of an environment or arglist to overwrite. 2832 */ 2833void 2834#if __STDC__ 2835setproctitle(const char *fmt, ...) 2836#else 2837setproctitle(fmt, va_alist) 2838 char *fmt; 2839 va_dcl 2840#endif 2841{ 2842 int i; 2843 va_list ap; 2844 char *p, *bp, ch; 2845 char buf[LINE_MAX]; 2846 2847#if __STDC__ 2848 va_start(ap, fmt); 2849#else 2850 va_start(ap); 2851#endif 2852 (void)vsnprintf(buf, sizeof(buf), fmt, ap); 2853 2854 /* make ps print our process name */ 2855 p = Argv[0]; 2856 *p++ = '-'; 2857 2858 i = strlen(buf); 2859 if (i > LastArgv - p - 2) { 2860 i = LastArgv - p - 2; 2861 buf[i] = '\0'; 2862 } 2863 bp = buf; 2864 while (ch = *bp++) 2865 if (ch != '\n' && ch != '\r') 2866 *p++ = ch; 2867 while (p < LastArgv) 2868 *p++ = ' '; 2869} 2870#endif /* OLD_SETPROCTITLE */ 2871 2872static void 2873logxfer(name, size, start) 2874 char *name; 2875 off_t size; 2876 time_t start; 2877{ 2878 char buf[1024]; 2879 char path[MAXPATHLEN + 1]; 2880 time_t now; 2881 2882 if (statfd >= 0 && getwd(path) != NULL) { 2883 time(&now); 2884 snprintf(buf, sizeof(buf), "%.20s!%s!%s!%s/%s!%qd!%ld\n", 2885 ctime(&now)+4, ident, remotehost, 2886 path, name, (long long)size, 2887 (long)(now - start + (now == start))); 2888 write(statfd, buf, strlen(buf)); 2889 } 2890} 2891