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