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