ftpd.c revision 137660
1285242Sachim/* 2285242Sachim * Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994 3285242Sachim * The Regents of the University of California. All rights reserved. 4285242Sachim * 5285242Sachim * Redistribution and use in source and binary forms, with or without 6285242Sachim * modification, are permitted provided that the following conditions 7285242Sachim * are met: 8285242Sachim * 1. Redistributions of source code must retain the above copyright 9285242Sachim * notice, this list of conditions and the following disclaimer. 10285242Sachim * 2. Redistributions in binary form must reproduce the above copyright 11285242Sachim * notice, this list of conditions and the following disclaimer in the 12285242Sachim * documentation and/or other materials provided with the distribution. 13285242Sachim * 3. All advertising materials mentioning features or use of this software 14285242Sachim * must display the following acknowledgement: 15285242Sachim * This product includes software developed by the University of 16285242Sachim * California, Berkeley and its contributors. 17285242Sachim * 4. Neither the name of the University nor the names of its contributors 18285242Sachim * may be used to endorse or promote products derived from this software 19285242Sachim * without specific prior written permission. 20285242Sachim * 21285242Sachim * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22285242Sachim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23285242Sachim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24285242Sachim * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25285242Sachim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26285242Sachim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27285242Sachim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28285242Sachim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29285242Sachim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30285242Sachim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31285242Sachim * SUCH DAMAGE. 32285242Sachim */ 33285242Sachim 34285242Sachim#if 0 35285242Sachim#ifndef lint 36285242Sachimstatic char copyright[] = 37285242Sachim"@(#) Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994\n\ 38285242Sachim The Regents of the University of California. All rights reserved.\n"; 39285242Sachim#endif /* not lint */ 40285242Sachim#endif 41285242Sachim 42285242Sachim#ifndef lint 43285242Sachim#if 0 44285242Sachimstatic char sccsid[] = "@(#)ftpd.c 8.4 (Berkeley) 4/16/94"; 45285242Sachim#endif 46285242Sachimstatic const char rcsid[] = 47285242Sachim "$FreeBSD: head/libexec/ftpd/ftpd.c 137660 2004-11-13 13:42:43Z yar $"; 48285242Sachim#endif /* not lint */ 49285242Sachim 50285242Sachim/* 51285242Sachim * FTP server. 52285242Sachim */ 53285242Sachim#include <sys/param.h> 54285242Sachim#include <sys/ioctl.h> 55285242Sachim#include <sys/mman.h> 56285242Sachim#include <sys/socket.h> 57285242Sachim#include <sys/stat.h> 58285242Sachim#include <sys/time.h> 59285242Sachim#include <sys/wait.h> 60285242Sachim 61285242Sachim#include <netinet/in.h> 62285242Sachim#include <netinet/in_systm.h> 63285242Sachim#include <netinet/ip.h> 64285242Sachim#include <netinet/tcp.h> 65285242Sachim 66285242Sachim#define FTP_NAMES 67285242Sachim#include <arpa/ftp.h> 68285242Sachim#include <arpa/inet.h> 69285242Sachim#include <arpa/telnet.h> 70285242Sachim 71285242Sachim#include <ctype.h> 72285242Sachim#include <dirent.h> 73285242Sachim#include <err.h> 74285242Sachim#include <errno.h> 75285242Sachim#include <fcntl.h> 76285242Sachim#include <glob.h> 77285242Sachim#include <limits.h> 78285242Sachim#include <netdb.h> 79285242Sachim#include <pwd.h> 80285242Sachim#include <grp.h> 81285242Sachim#include <opie.h> 82285242Sachim#include <signal.h> 83285242Sachim#include <stdint.h> 84285242Sachim#include <stdio.h> 85285242Sachim#include <stdlib.h> 86285242Sachim#include <string.h> 87285242Sachim#include <syslog.h> 88285242Sachim#include <time.h> 89285242Sachim#include <unistd.h> 90285242Sachim#include <libutil.h> 91285242Sachim#ifdef LOGIN_CAP 92285242Sachim#include <login_cap.h> 93285242Sachim#endif 94285242Sachim 95285242Sachim#ifdef USE_PAM 96285242Sachim#include <security/pam_appl.h> 97285242Sachim#endif 98285242Sachim 99285242Sachim#include "pathnames.h" 100285242Sachim#include "extern.h" 101285242Sachim 102285242Sachim#include <stdarg.h> 103285242Sachim 104285242Sachimstatic char version[] = "Version 6.00LS"; 105285242Sachim#undef main 106285242Sachim 107285242Sachimextern off_t restart_point; 108285242Sachimextern char cbuf[]; 109285242Sachim 110285242Sachimunion sockunion ctrl_addr; 111285242Sachimunion sockunion data_source; 112285242Sachimunion sockunion data_dest; 113285242Sachimunion sockunion his_addr; 114285242Sachimunion sockunion pasv_addr; 115285242Sachim 116285242Sachimint daemon_mode; 117285242Sachimint data; 118285242Sachimint dataport; 119285242Sachimint hostinfo = 1; /* print host-specific info in messages */ 120285242Sachimint logged_in; 121285242Sachimstruct passwd *pw; 122285242Sachimchar *homedir; 123285242Sachimint ftpdebug; 124285242Sachimint timeout = 900; /* timeout after 15 minutes of inactivity */ 125285242Sachimint maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */ 126285242Sachimint logging; 127285242Sachimint restricted_data_ports = 1; 128285242Sachimint paranoid = 1; /* be extra careful about security */ 129285242Sachimint anon_only = 0; /* Only anonymous ftp allowed */ 130285242Sachimint guest; 131285242Sachimint dochroot; 132285242Sachimint dowtmp = 1; 133285242Sachimint stats; 134285242Sachimint statfd = -1; 135285242Sachimint type; 136285242Sachimint form; 137285242Sachimint stru; /* avoid C keyword */ 138285242Sachimint mode; 139285242Sachimint usedefault = 1; /* for data transfers */ 140285242Sachimint pdata = -1; /* for passive mode */ 141285242Sachimint readonly=0; /* Server is in readonly mode. */ 142285242Sachimint noepsv=0; /* EPSV command is disabled. */ 143285242Sachimint noretr=0; /* RETR command is disabled. */ 144285242Sachimint noguestretr=0; /* RETR command is disabled for anon users. */ 145285242Sachimint noguestmkd=0; /* MKD command is disabled for anon users. */ 146285242Sachimint noguestmod=1; /* anon users may not modify existing files. */ 147285242Sachim 148285242Sachimstatic volatile sig_atomic_t recvurg; 149285242Sachimsig_atomic_t transflag; 150285242Sachimoff_t file_size; 151285242Sachimoff_t byte_count; 152285242Sachim#if !defined(CMASK) || CMASK == 0 153285242Sachim#undef CMASK 154285242Sachim#define CMASK 027 155285242Sachim#endif 156285242Sachimint defumask = CMASK; /* default umask value */ 157285242Sachimchar tmpline[7]; 158285242Sachimchar *hostname; 159285242Sachimint epsvall = 0; 160285242Sachim 161285242Sachim#ifdef VIRTUAL_HOSTING 162285242Sachimchar *ftpuser; 163285242Sachim 164285242Sachimstatic struct ftphost { 165285242Sachim struct ftphost *next; 166285242Sachim struct addrinfo *hostinfo; 167285242Sachim char *hostname; 168285242Sachim char *anonuser; 169285242Sachim char *statfile; 170285242Sachim char *welcome; 171285242Sachim char *loginmsg; 172285242Sachim} *thishost, *firsthost; 173285242Sachim 174285242Sachim#endif 175285242Sachimchar remotehost[MAXHOSTNAMELEN]; 176285242Sachimchar *ident = NULL; 177285242Sachim 178285242Sachimstatic char ttyline[20]; 179285242Sachimchar *tty = ttyline; /* for klogin */ 180285242Sachim 181285242Sachim#ifdef USE_PAM 182285242Sachimstatic int auth_pam(struct passwd**, const char*); 183285242Sachimpam_handle_t *pamh = NULL; 184285242Sachim#endif 185285242Sachim 186285242Sachimstatic struct opie opiedata; 187285242Sachimstatic char opieprompt[OPIE_CHALLENGE_MAX+1]; 188285242Sachimstatic int pwok; 189285242Sachim 190285242Sachimchar *pid_file = NULL; 191285242Sachim 192285242Sachim/* 193285242Sachim * Limit number of pathnames that glob can return. 194285242Sachim * A limit of 0 indicates the number of pathnames is unlimited. 195285242Sachim */ 196285242Sachim#define MAXGLOBARGS 16384 197285242Sachim# 198285242Sachim 199285242Sachim/* 200285242Sachim * Timeout intervals for retrying connections 201285242Sachim * to hosts that don't accept PORT cmds. This 202285242Sachim * is a kludge, but given the problems with TCP... 203285242Sachim */ 204285242Sachim#define SWAITMAX 90 /* wait at most 90 seconds */ 205285242Sachim#define SWAITINT 5 /* interval between retries */ 206285242Sachim 207285242Sachimint swaitmax = SWAITMAX; 208285242Sachimint swaitint = SWAITINT; 209285242Sachim 210285242Sachim#ifdef SETPROCTITLE 211285242Sachim#ifdef OLD_SETPROCTITLE 212285242Sachimchar **Argv = NULL; /* pointer to argument vector */ 213285242Sachimchar *LastArgv = NULL; /* end of argv */ 214285242Sachim#endif /* OLD_SETPROCTITLE */ 215285242Sachimchar proctitle[LINE_MAX]; /* initial part of title */ 216285242Sachim#endif /* SETPROCTITLE */ 217285242Sachim 218285242Sachim#define LOGCMD(cmd, file) \ 219285242Sachim if (logging > 1) \ 220285242Sachim syslog(LOG_INFO,"%s %s%s", cmd, \ 221285242Sachim *(file) == '/' ? "" : curdir(), file); 222285242Sachim#define LOGCMD2(cmd, file1, file2) \ 223285242Sachim if (logging > 1) \ 224285242Sachim syslog(LOG_INFO,"%s %s%s %s%s", cmd, \ 225285242Sachim *(file1) == '/' ? "" : curdir(), file1, \ 226285242Sachim *(file2) == '/' ? "" : curdir(), file2); 227285242Sachim#define LOGBYTES(cmd, file, cnt) \ 228285242Sachim if (logging > 1) { \ 229285242Sachim if (cnt == -1) \ 230285242Sachim syslog(LOG_INFO,"%s %s%s", cmd, \ 231285242Sachim *(file) == '/' ? "" : curdir(), file); \ 232285242Sachim else \ 233285242Sachim syslog(LOG_INFO, "%s %s%s = %jd bytes", \ 234285242Sachim cmd, (*(file) == '/') ? "" : curdir(), file, \ 235285242Sachim (intmax_t)cnt); \ 236285242Sachim } 237285242Sachim 238285242Sachim#ifdef VIRTUAL_HOSTING 239285242Sachimstatic void inithosts(void); 240285242Sachimstatic void selecthost(union sockunion *); 241285242Sachim#endif 242285242Sachimstatic void ack(char *); 243285242Sachimstatic void sigurg(int); 244285242Sachimstatic void myoob(void); 245285242Sachimstatic int checkuser(char *, char *, int, char **); 246285242Sachimstatic FILE *dataconn(char *, off_t, char *); 247285242Sachimstatic void dolog(struct sockaddr *); 248285242Sachimstatic char *curdir(void); 249285242Sachimstatic void end_login(void); 250285242Sachimstatic FILE *getdatasock(char *); 251285242Sachimstatic int guniquefd(char *, char **); 252285242Sachimstatic void lostconn(int); 253285242Sachimstatic void sigquit(int); 254285242Sachimstatic int receive_data(FILE *, FILE *); 255285242Sachimstatic int send_data(FILE *, FILE *, size_t, off_t, int); 256285242Sachimstatic struct passwd * 257285242Sachim sgetpwnam(char *); 258285242Sachimstatic char *sgetsave(char *); 259285242Sachimstatic void reapchild(int); 260285242Sachimstatic void logxfer(char *, off_t, time_t); 261285242Sachimstatic char *doublequote(char *); 262285242Sachimstatic int *socksetup(int, char *, const char *); 263285242Sachim 264285242Sachimstatic char * 265285242Sachimcurdir(void) 266285242Sachim{ 267285242Sachim static char path[MAXPATHLEN+1+1]; /* path + '/' + '\0' */ 268285242Sachim 269285242Sachim if (getcwd(path, sizeof(path)-2) == NULL) 270285242Sachim return (""); 271285242Sachim if (path[1] != '\0') /* special case for root dir. */ 272285242Sachim strcat(path, "/"); 273285242Sachim /* For guest account, skip / since it's chrooted */ 274285242Sachim return (guest ? path+1 : path); 275285242Sachim} 276285242Sachim 277285242Sachimint 278285242Sachimmain(int argc, char *argv[], char **envp) 279285242Sachim{ 280285242Sachim int addrlen, ch, on = 1, tos; 281285242Sachim char *cp, line[LINE_MAX]; 282285242Sachim FILE *fd; 283285242Sachim char *bindname = NULL; 284285242Sachim const char *bindport = "ftp"; 285285242Sachim int family = AF_UNSPEC; 286285242Sachim struct sigaction sa; 287285242Sachim 288285242Sachim tzset(); /* in case no timezone database in ~ftp */ 289285242Sachim sigemptyset(&sa.sa_mask); 290285242Sachim sa.sa_flags = SA_RESTART; 291285242Sachim 292285242Sachim#ifdef OLD_SETPROCTITLE 293285242Sachim /* 294285242Sachim * Save start and extent of argv for setproctitle. 295285242Sachim */ 296285242Sachim Argv = argv; 297285242Sachim while (*envp) 298285242Sachim envp++; 299285242Sachim LastArgv = envp[-1] + strlen(envp[-1]); 300285242Sachim#endif /* OLD_SETPROCTITLE */ 301285242Sachim 302285242Sachim 303285242Sachim while ((ch = getopt(argc, argv, 304285242Sachim "46a:AdDEhlmMoOp:P:rRSt:T:u:UvW")) != -1) { 305285242Sachim switch (ch) { 306285242Sachim case '4': 307285242Sachim family = (family == AF_INET6) ? AF_UNSPEC : AF_INET; 308285242Sachim break; 309285242Sachim 310285242Sachim case '6': 311285242Sachim family = (family == AF_INET) ? AF_UNSPEC : AF_INET6; 312285242Sachim break; 313285242Sachim 314285242Sachim case 'a': 315285242Sachim bindname = optarg; 316285242Sachim break; 317285242Sachim 318285242Sachim case 'A': 319285242Sachim anon_only = 1; 320285242Sachim break; 321285242Sachim 322285242Sachim case 'd': 323285242Sachim ftpdebug++; 324285242Sachim break; 325285242Sachim 326285242Sachim case 'D': 327285242Sachim daemon_mode++; 328285242Sachim break; 329285242Sachim 330285242Sachim case 'E': 331285242Sachim noepsv = 1; 332285242Sachim break; 333285242Sachim 334285242Sachim case 'h': 335285242Sachim hostinfo = 0; 336285242Sachim break; 337285242Sachim 338285242Sachim case 'l': 339285242Sachim logging++; /* > 1 == extra logging */ 340285242Sachim break; 341285242Sachim 342285242Sachim case 'm': 343285242Sachim noguestmod = 0; 344285242Sachim break; 345285242Sachim 346285242Sachim case 'M': 347285242Sachim noguestmkd = 1; 348285242Sachim break; 349285242Sachim 350285242Sachim case 'o': 351285242Sachim noretr = 1; 352285242Sachim break; 353285242Sachim 354285242Sachim case 'O': 355285242Sachim noguestretr = 1; 356285242Sachim break; 357285242Sachim 358285242Sachim case 'p': 359285242Sachim pid_file = optarg; 360285242Sachim break; 361285242Sachim 362285242Sachim case 'P': 363285242Sachim bindport = optarg; 364285242Sachim break; 365285242Sachim 366285242Sachim case 'r': 367285242Sachim readonly = 1; 368285242Sachim break; 369285242Sachim 370285242Sachim case 'R': 371285242Sachim paranoid = 0; 372285242Sachim break; 373285242Sachim 374285242Sachim case 'S': 375285242Sachim stats++; 376285242Sachim break; 377285242Sachim 378285242Sachim case 't': 379285242Sachim timeout = atoi(optarg); 380285242Sachim if (maxtimeout < timeout) 381285242Sachim maxtimeout = timeout; 382285242Sachim break; 383285242Sachim 384285242Sachim case 'T': 385285242Sachim maxtimeout = atoi(optarg); 386285242Sachim if (timeout > maxtimeout) 387285242Sachim timeout = maxtimeout; 388285242Sachim break; 389285242Sachim 390285242Sachim case 'u': 391285242Sachim { 392285242Sachim long val = 0; 393285242Sachim 394285242Sachim val = strtol(optarg, &optarg, 8); 395285242Sachim if (*optarg != '\0' || val < 0) 396285242Sachim warnx("bad value for -u"); 397285242Sachim else 398285242Sachim defumask = val; 399285242Sachim break; 400285242Sachim } 401285242Sachim case 'U': 402285242Sachim restricted_data_ports = 0; 403285242Sachim break; 404285242Sachim 405285242Sachim case 'v': 406285242Sachim ftpdebug++; 407285242Sachim break; 408285242Sachim 409285242Sachim case 'W': 410285242Sachim dowtmp = 0; 411 break; 412 413 default: 414 warnx("unknown flag -%c ignored", optopt); 415 break; 416 } 417 } 418 419#ifdef VIRTUAL_HOSTING 420 inithosts(); 421#endif 422 (void) freopen(_PATH_DEVNULL, "w", stderr); 423 424 /* 425 * LOG_NDELAY sets up the logging connection immediately, 426 * necessary for anonymous ftp's that chroot and can't do it later. 427 */ 428 openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP); 429 430 if (daemon_mode) { 431 int *ctl_sock, fd, maxfd = -1, nfds, i; 432 fd_set defreadfds, readfds; 433 pid_t pid; 434 435 /* 436 * Detach from parent. 437 */ 438 if (daemon(1, 1) < 0) { 439 syslog(LOG_ERR, "failed to become a daemon"); 440 exit(1); 441 } 442 sa.sa_handler = reapchild; 443 (void)sigaction(SIGCHLD, &sa, NULL); 444 445 /* 446 * Open a socket, bind it to the FTP port, and start 447 * listening. 448 */ 449 ctl_sock = socksetup(family, bindname, bindport); 450 if (ctl_sock == NULL) 451 exit(1); 452 453 FD_ZERO(&defreadfds); 454 for (i = 1; i <= *ctl_sock; i++) { 455 FD_SET(ctl_sock[i], &defreadfds); 456 if (listen(ctl_sock[i], 32) < 0) { 457 syslog(LOG_ERR, "control listen: %m"); 458 exit(1); 459 } 460 if (maxfd < ctl_sock[i]) 461 maxfd = ctl_sock[i]; 462 } 463 464 /* 465 * Atomically write process ID 466 */ 467 if (pid_file) 468 { 469 int fd; 470 char buf[20]; 471 472 fd = open(pid_file, O_CREAT | O_WRONLY | O_TRUNC 473 | O_NONBLOCK | O_EXLOCK, 0644); 474 if (fd < 0) { 475 if (errno == EAGAIN) 476 errx(1, "%s: file locked", pid_file); 477 else 478 err(1, "%s", pid_file); 479 } 480 snprintf(buf, sizeof(buf), 481 "%lu\n", (unsigned long) getpid()); 482 if (write(fd, buf, strlen(buf)) < 0) 483 err(1, "%s: write", pid_file); 484 /* Leave the pid file open and locked */ 485 } 486 /* 487 * Loop forever accepting connection requests and forking off 488 * children to handle them. 489 */ 490 while (1) { 491 FD_COPY(&defreadfds, &readfds); 492 nfds = select(maxfd + 1, &readfds, NULL, NULL, 0); 493 if (nfds <= 0) { 494 if (nfds < 0 && errno != EINTR) 495 syslog(LOG_WARNING, "select: %m"); 496 continue; 497 } 498 499 pid = -1; 500 for (i = 1; i <= *ctl_sock; i++) 501 if (FD_ISSET(ctl_sock[i], &readfds)) { 502 addrlen = sizeof(his_addr); 503 fd = accept(ctl_sock[i], 504 (struct sockaddr *)&his_addr, 505 &addrlen); 506 if (fd >= 0) { 507 if ((pid = fork()) == 0) { 508 /* child */ 509 (void) dup2(fd, 0); 510 (void) dup2(fd, 1); 511 close(ctl_sock[i]); 512 } else 513 close(fd); 514 } 515 } 516 if (pid == 0) 517 break; 518 } 519 } else { 520 addrlen = sizeof(his_addr); 521 if (getpeername(0, (struct sockaddr *)&his_addr, &addrlen) < 0) { 522 syslog(LOG_ERR, "getpeername (%s): %m",argv[0]); 523 exit(1); 524 } 525 } 526 527 sa.sa_handler = SIG_DFL; 528 (void)sigaction(SIGCHLD, &sa, NULL); 529 530 sa.sa_handler = sigurg; 531 sa.sa_flags = 0; /* don't restart syscalls for SIGURG */ 532 (void)sigaction(SIGURG, &sa, NULL); 533 534 sigfillset(&sa.sa_mask); /* block all signals in handler */ 535 sa.sa_flags = SA_RESTART; 536 sa.sa_handler = sigquit; 537 (void)sigaction(SIGHUP, &sa, NULL); 538 (void)sigaction(SIGINT, &sa, NULL); 539 (void)sigaction(SIGQUIT, &sa, NULL); 540 (void)sigaction(SIGTERM, &sa, NULL); 541 542 sa.sa_handler = lostconn; 543 (void)sigaction(SIGPIPE, &sa, NULL); 544 545 addrlen = sizeof(ctrl_addr); 546 if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) { 547 syslog(LOG_ERR, "getsockname (%s): %m",argv[0]); 548 exit(1); 549 } 550 dataport = ntohs(ctrl_addr.su_port) - 1; /* as per RFC 959 */ 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, &tos, sizeof(int)) < 0) 560 syslog(LOG_WARNING, "control 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, &on, sizeof(on)) < 0) 578 syslog(LOG_WARNING, "control setsockopt (SO_OOBINLINE): %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 fd = fopen(thishost->welcome, "r"); 610#else 611 fd = fopen(_PATH_FTPWELCOME, "r"); 612#endif 613 if (fd != NULL) { 614 while (fgets(line, sizeof(line), fd) != NULL) { 615 if ((cp = strchr(line, '\n')) != NULL) 616 *cp = '\0'; 617 lreply(220, "%s", line); 618 } 619 (void) fflush(stdout); 620 (void) fclose(fd); 621 /* reply(220,) must follow */ 622 } 623#ifndef VIRTUAL_HOSTING 624 if ((hostname = malloc(MAXHOSTNAMELEN)) == NULL) 625 fatalerror("Ran out of memory."); 626 (void) gethostname(hostname, MAXHOSTNAMELEN - 1); 627 hostname[MAXHOSTNAMELEN - 1] = '\0'; 628#endif 629 if (hostinfo) 630 reply(220, "%s FTP server (%s) ready.", hostname, version); 631 else 632 reply(220, "FTP server ready."); 633 for (;;) 634 (void) yyparse(); 635 /* NOTREACHED */ 636} 637 638static void 639lostconn(int signo) 640{ 641 642 if (ftpdebug) 643 syslog(LOG_DEBUG, "lost connection"); 644 dologout(1); 645} 646 647static void 648sigquit(int signo) 649{ 650 651 syslog(LOG_ERR, "got signal %d", signo); 652 dologout(1); 653} 654 655#ifdef VIRTUAL_HOSTING 656/* 657 * read in virtual host tables (if they exist) 658 */ 659 660static void 661inithosts(void) 662{ 663 int insert; 664 size_t len; 665 FILE *fp; 666 char *cp, *mp, *line; 667 char *hostname; 668 char *vhost, *anonuser, *statfile, *welcome, *loginmsg; 669 struct ftphost *hrp, *lhrp; 670 struct addrinfo hints, *res, *ai; 671 672 /* 673 * Fill in the default host information 674 */ 675 if ((hostname = malloc(MAXHOSTNAMELEN)) == NULL) 676 fatalerror("Ran out of memory."); 677 if (gethostname(hostname, MAXHOSTNAMELEN) < 0) 678 hostname[0] = '\0'; 679 hostname[MAXHOSTNAMELEN - 1] = '\0'; 680 if ((hrp = malloc(sizeof(struct ftphost))) == NULL) 681 fatalerror("Ran out of memory."); 682 hrp->hostname = hostname; 683 hrp->hostinfo = NULL; 684 685 memset(&hints, 0, sizeof(hints)); 686 hints.ai_flags = AI_CANONNAME; 687 hints.ai_family = AF_UNSPEC; 688 if (getaddrinfo(hrp->hostname, NULL, &hints, &res) == 0) 689 hrp->hostinfo = res; 690 hrp->statfile = _PATH_FTPDSTATFILE; 691 hrp->welcome = _PATH_FTPWELCOME; 692 hrp->loginmsg = _PATH_FTPLOGINMESG; 693 hrp->anonuser = "ftp"; 694 hrp->next = NULL; 695 thishost = firsthost = lhrp = hrp; 696 if ((fp = fopen(_PATH_FTPHOSTS, "r")) != NULL) { 697 int addrsize, gothost; 698 void *addr; 699 struct hostent *hp; 700 701 while ((line = fgetln(fp, &len)) != NULL) { 702 int i, hp_error; 703 704 /* skip comments */ 705 if (line[0] == '#') 706 continue; 707 if (line[len - 1] == '\n') { 708 line[len - 1] = '\0'; 709 mp = NULL; 710 } else { 711 if ((mp = malloc(len + 1)) == NULL) 712 fatalerror("Ran out of memory."); 713 memcpy(mp, line, len); 714 mp[len] = '\0'; 715 line = mp; 716 } 717 cp = strtok(line, " \t"); 718 /* skip empty lines */ 719 if (cp == NULL) 720 goto nextline; 721 vhost = cp; 722 723 /* set defaults */ 724 anonuser = "ftp"; 725 statfile = _PATH_FTPDSTATFILE; 726 welcome = _PATH_FTPWELCOME; 727 loginmsg = _PATH_FTPLOGINMESG; 728 729 /* 730 * Preparse the line so we can use its info 731 * for all the addresses associated with 732 * the virtual host name. 733 * Field 0, the virtual host name, is special: 734 * it's already parsed off and will be strdup'ed 735 * later, after we know its canonical form. 736 */ 737 for (i = 1; i < 5 && (cp = strtok(NULL, " \t")); i++) 738 if (*cp != '-' && (cp = strdup(cp))) 739 switch (i) { 740 case 1: /* anon user permissions */ 741 anonuser = cp; 742 break; 743 case 2: /* statistics file */ 744 statfile = cp; 745 break; 746 case 3: /* welcome message */ 747 welcome = cp; 748 break; 749 case 4: /* login message */ 750 loginmsg = cp; 751 break; 752 default: /* programming error */ 753 abort(); 754 /* NOTREACHED */ 755 } 756 757 hints.ai_flags = 0; 758 hints.ai_family = AF_UNSPEC; 759 hints.ai_flags = AI_PASSIVE; 760 if (getaddrinfo(vhost, NULL, &hints, &res) != 0) 761 goto nextline; 762 for (ai = res; ai != NULL && ai->ai_addr != NULL; 763 ai = ai->ai_next) { 764 765 gothost = 0; 766 for (hrp = firsthost; hrp != NULL; hrp = hrp->next) { 767 struct addrinfo *hi; 768 769 for (hi = hrp->hostinfo; hi != NULL; 770 hi = hi->ai_next) 771 if (hi->ai_addrlen == ai->ai_addrlen && 772 memcmp(hi->ai_addr, 773 ai->ai_addr, 774 ai->ai_addr->sa_len) == 0) { 775 gothost++; 776 break; 777 } 778 if (gothost) 779 break; 780 } 781 if (hrp == NULL) { 782 if ((hrp = malloc(sizeof(struct ftphost))) == NULL) 783 goto nextline; 784 hrp->hostname = NULL; 785 insert = 1; 786 } else { 787 if (hrp->hostinfo && hrp->hostinfo != res) 788 freeaddrinfo(hrp->hostinfo); 789 insert = 0; /* host already in the chain */ 790 } 791 hrp->hostinfo = res; 792 793 /* 794 * determine hostname to use. 795 * force defined name if there is a valid alias 796 * otherwise fallback to primary hostname 797 */ 798 /* XXX: getaddrinfo() can't do alias check */ 799 switch(hrp->hostinfo->ai_family) { 800 case AF_INET: 801 addr = &((struct sockaddr_in *)hrp->hostinfo->ai_addr)->sin_addr; 802 addrsize = sizeof(struct in_addr); 803 break; 804 case AF_INET6: 805 addr = &((struct sockaddr_in6 *)hrp->hostinfo->ai_addr)->sin6_addr; 806 addrsize = sizeof(struct in6_addr); 807 break; 808 default: 809 /* should not reach here */ 810 freeaddrinfo(hrp->hostinfo); 811 if (insert) 812 free(hrp); /*not in chain, can free*/ 813 else 814 hrp->hostinfo = NULL; /*mark as blank*/ 815 goto nextline; 816 /* NOTREACHED */ 817 } 818 if ((hp = getipnodebyaddr(addr, addrsize, 819 hrp->hostinfo->ai_family, 820 &hp_error)) != NULL) { 821 if (strcmp(vhost, hp->h_name) != 0) { 822 if (hp->h_aliases == NULL) 823 vhost = hp->h_name; 824 else { 825 i = 0; 826 while (hp->h_aliases[i] && 827 strcmp(vhost, hp->h_aliases[i]) != 0) 828 ++i; 829 if (hp->h_aliases[i] == NULL) 830 vhost = hp->h_name; 831 } 832 } 833 } 834 if (hrp->hostname && 835 strcmp(hrp->hostname, vhost) != 0) { 836 free(hrp->hostname); 837 hrp->hostname = NULL; 838 } 839 if (hrp->hostname == NULL && 840 (hrp->hostname = strdup(vhost)) == NULL) { 841 freeaddrinfo(hrp->hostinfo); 842 hrp->hostinfo = NULL; /* mark as blank */ 843 if (hp) 844 freehostent(hp); 845 goto nextline; 846 } 847 hrp->anonuser = anonuser; 848 hrp->statfile = statfile; 849 hrp->welcome = welcome; 850 hrp->loginmsg = loginmsg; 851 if (insert) { 852 hrp->next = NULL; 853 lhrp->next = hrp; 854 lhrp = hrp; 855 } 856 if (hp) 857 freehostent(hp); 858 } 859nextline: 860 if (mp) 861 free(mp); 862 } 863 (void) fclose(fp); 864 } 865} 866 867static void 868selecthost(union sockunion *su) 869{ 870 struct ftphost *hrp; 871 u_int16_t port; 872#ifdef INET6 873 struct in6_addr *mapped_in6 = NULL; 874#endif 875 struct addrinfo *hi; 876 877#ifdef INET6 878 /* 879 * XXX IPv4 mapped IPv6 addr consideraton, 880 * specified in rfc2373. 881 */ 882 if (su->su_family == AF_INET6 && 883 IN6_IS_ADDR_V4MAPPED(&su->su_sin6.sin6_addr)) 884 mapped_in6 = &su->su_sin6.sin6_addr; 885#endif 886 887 hrp = thishost = firsthost; /* default */ 888 port = su->su_port; 889 su->su_port = 0; 890 while (hrp != NULL) { 891 for (hi = hrp->hostinfo; hi != NULL; hi = hi->ai_next) { 892 if (memcmp(su, hi->ai_addr, hi->ai_addrlen) == 0) { 893 thishost = hrp; 894 break; 895 } 896#ifdef INET6 897 /* XXX IPv4 mapped IPv6 addr consideraton */ 898 if (hi->ai_addr->sa_family == AF_INET && mapped_in6 != NULL && 899 (memcmp(&mapped_in6->s6_addr[12], 900 &((struct sockaddr_in *)hi->ai_addr)->sin_addr, 901 sizeof(struct in_addr)) == 0)) { 902 thishost = hrp; 903 break; 904 } 905#endif 906 } 907 hrp = hrp->next; 908 } 909 su->su_port = port; 910 /* setup static variables as appropriate */ 911 hostname = thishost->hostname; 912 ftpuser = thishost->anonuser; 913} 914#endif 915 916/* 917 * Helper function for sgetpwnam(). 918 */ 919static char * 920sgetsave(char *s) 921{ 922 char *new = malloc(strlen(s) + 1); 923 924 if (new == NULL) { 925 perror_reply(421, "Local resource failure: malloc"); 926 dologout(1); 927 /* NOTREACHED */ 928 } 929 (void) strcpy(new, s); 930 return (new); 931} 932 933/* 934 * Save the result of a getpwnam. Used for USER command, since 935 * the data returned must not be clobbered by any other command 936 * (e.g., globbing). 937 * NB: The data returned by sgetpwnam() will remain valid until 938 * the next call to this function. Its difference from getpwnam() 939 * is that sgetpwnam() is known to be called from ftpd code only. 940 */ 941static struct passwd * 942sgetpwnam(char *name) 943{ 944 static struct passwd save; 945 struct passwd *p; 946 947 if ((p = getpwnam(name)) == NULL) 948 return (p); 949 if (save.pw_name) { 950 free(save.pw_name); 951 free(save.pw_passwd); 952 free(save.pw_gecos); 953 free(save.pw_dir); 954 free(save.pw_shell); 955 } 956 save = *p; 957 save.pw_name = sgetsave(p->pw_name); 958 save.pw_passwd = sgetsave(p->pw_passwd); 959 save.pw_gecos = sgetsave(p->pw_gecos); 960 save.pw_dir = sgetsave(p->pw_dir); 961 save.pw_shell = sgetsave(p->pw_shell); 962 return (&save); 963} 964 965static int login_attempts; /* number of failed login attempts */ 966static int askpasswd; /* had user command, ask for passwd */ 967static char curname[MAXLOGNAME]; /* current USER name */ 968 969/* 970 * USER command. 971 * Sets global passwd pointer pw if named account exists and is acceptable; 972 * sets askpasswd if a PASS command is expected. If logged in previously, 973 * need to reset state. If name is "ftp" or "anonymous", the name is not in 974 * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return. 975 * If account doesn't exist, ask for passwd anyway. Otherwise, check user 976 * requesting login privileges. Disallow anyone who does not have a standard 977 * shell as returned by getusershell(). Disallow anyone mentioned in the file 978 * _PATH_FTPUSERS to allow people such as root and uucp to be avoided. 979 */ 980void 981user(char *name) 982{ 983 char *cp, *shell; 984 985 if (logged_in) { 986 if (guest) { 987 reply(530, "Can't change user from guest login."); 988 return; 989 } else if (dochroot) { 990 reply(530, "Can't change user from chroot user."); 991 return; 992 } 993 end_login(); 994 } 995 996 guest = 0; 997#ifdef VIRTUAL_HOSTING 998 pw = sgetpwnam(thishost->anonuser); 999#else 1000 pw = sgetpwnam("ftp"); 1001#endif 1002 if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) { 1003 if (checkuser(_PATH_FTPUSERS, "ftp", 0, NULL) || 1004 checkuser(_PATH_FTPUSERS, "anonymous", 0, NULL)) 1005 reply(530, "User %s access denied.", name); 1006 else if (pw != NULL) { 1007 guest = 1; 1008 askpasswd = 1; 1009 reply(331, 1010 "Guest login ok, send your email address as password."); 1011 } else 1012 reply(530, "User %s unknown.", name); 1013 if (!askpasswd && logging) 1014 syslog(LOG_NOTICE, 1015 "ANONYMOUS FTP LOGIN REFUSED FROM %s", remotehost); 1016 return; 1017 } 1018 if (anon_only != 0) { 1019 reply(530, "Sorry, only anonymous ftp allowed."); 1020 return; 1021 } 1022 1023 if ((pw = sgetpwnam(name))) { 1024 if ((shell = pw->pw_shell) == NULL || *shell == 0) 1025 shell = _PATH_BSHELL; 1026 setusershell(); 1027 while ((cp = getusershell()) != NULL) 1028 if (strcmp(cp, shell) == 0) 1029 break; 1030 endusershell(); 1031 1032 if (cp == NULL || checkuser(_PATH_FTPUSERS, name, 1, NULL)) { 1033 reply(530, "User %s access denied.", name); 1034 if (logging) 1035 syslog(LOG_NOTICE, 1036 "FTP LOGIN REFUSED FROM %s, %s", 1037 remotehost, name); 1038 pw = (struct passwd *) NULL; 1039 return; 1040 } 1041 } 1042 if (logging) 1043 strncpy(curname, name, sizeof(curname)-1); 1044 1045 pwok = 0; 1046#ifdef USE_PAM 1047 /* XXX Kluge! The conversation mechanism needs to be fixed. */ 1048#endif 1049 if (opiechallenge(&opiedata, name, opieprompt) == 0) { 1050 pwok = (pw != NULL) && 1051 opieaccessfile(remotehost) && 1052 opiealways(pw->pw_dir); 1053 reply(331, "Response to %s %s for %s.", 1054 opieprompt, pwok ? "requested" : "required", name); 1055 } else { 1056 pwok = 1; 1057 reply(331, "Password required for %s.", name); 1058 } 1059 askpasswd = 1; 1060 /* 1061 * Delay before reading passwd after first failed 1062 * attempt to slow down passwd-guessing programs. 1063 */ 1064 if (login_attempts) 1065 sleep(login_attempts); 1066} 1067 1068/* 1069 * Check if a user is in the file "fname", 1070 * return a pointer to a malloc'd string with the rest 1071 * of the matching line in "residue" if not NULL. 1072 */ 1073static int 1074checkuser(char *fname, char *name, int pwset, char **residue) 1075{ 1076 FILE *fd; 1077 int found = 0; 1078 size_t len; 1079 char *line, *mp, *p; 1080 1081 if ((fd = fopen(fname, "r")) != NULL) { 1082 while (!found && (line = fgetln(fd, &len)) != NULL) { 1083 /* skip comments */ 1084 if (line[0] == '#') 1085 continue; 1086 if (line[len - 1] == '\n') { 1087 line[len - 1] = '\0'; 1088 mp = NULL; 1089 } else { 1090 if ((mp = malloc(len + 1)) == NULL) 1091 fatalerror("Ran out of memory."); 1092 memcpy(mp, line, len); 1093 mp[len] = '\0'; 1094 line = mp; 1095 } 1096 /* avoid possible leading and trailing whitespace */ 1097 p = strtok(line, " \t"); 1098 /* skip empty lines */ 1099 if (p == NULL) 1100 goto nextline; 1101 /* 1102 * if first chr is '@', check group membership 1103 */ 1104 if (p[0] == '@') { 1105 int i = 0; 1106 struct group *grp; 1107 1108 if (p[1] == '\0') /* single @ matches anyone */ 1109 found = 1; 1110 else { 1111 if ((grp = getgrnam(p+1)) == NULL) 1112 goto nextline; 1113 /* 1114 * Check user's default group 1115 */ 1116 if (pwset && grp->gr_gid == pw->pw_gid) 1117 found = 1; 1118 /* 1119 * Check supplementary groups 1120 */ 1121 while (!found && grp->gr_mem[i]) 1122 found = strcmp(name, 1123 grp->gr_mem[i++]) 1124 == 0; 1125 } 1126 } 1127 /* 1128 * Otherwise, just check for username match 1129 */ 1130 else 1131 found = strcmp(p, name) == 0; 1132 /* 1133 * Save the rest of line to "residue" if matched 1134 */ 1135 if (found && residue) { 1136 if ((p = strtok(NULL, "")) != NULL) 1137 p += strspn(p, " \t"); 1138 if (p && *p) { 1139 if ((*residue = strdup(p)) == NULL) 1140 fatalerror("Ran out of memory."); 1141 } else 1142 *residue = NULL; 1143 } 1144nextline: 1145 if (mp) 1146 free(mp); 1147 } 1148 (void) fclose(fd); 1149 } 1150 return (found); 1151} 1152 1153/* 1154 * Terminate login as previous user, if any, resetting state; 1155 * used when USER command is given or login fails. 1156 */ 1157static void 1158end_login(void) 1159{ 1160#ifdef USE_PAM 1161 int e; 1162#endif 1163 1164 (void) seteuid(0); 1165 if (logged_in && dowtmp) 1166 ftpd_logwtmp(ttyline, "", NULL); 1167 pw = NULL; 1168#ifdef LOGIN_CAP 1169 setusercontext(NULL, getpwuid(0), 0, 1170 LOGIN_SETPRIORITY|LOGIN_SETRESOURCES|LOGIN_SETUMASK| 1171 LOGIN_SETMAC); 1172#endif 1173#ifdef USE_PAM 1174 if (pamh) { 1175 if ((e = pam_setcred(pamh, PAM_DELETE_CRED)) != PAM_SUCCESS) 1176 syslog(LOG_ERR, "pam_setcred: %s", pam_strerror(pamh, e)); 1177 if ((e = pam_close_session(pamh,0)) != PAM_SUCCESS) 1178 syslog(LOG_ERR, "pam_close_session: %s", pam_strerror(pamh, e)); 1179 if ((e = pam_end(pamh, e)) != PAM_SUCCESS) 1180 syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e)); 1181 pamh = NULL; 1182 } 1183#endif 1184 logged_in = 0; 1185 guest = 0; 1186 dochroot = 0; 1187} 1188 1189#ifdef USE_PAM 1190 1191/* 1192 * the following code is stolen from imap-uw PAM authentication module and 1193 * login.c 1194 */ 1195#define COPY_STRING(s) (s ? strdup(s) : NULL) 1196 1197struct cred_t { 1198 const char *uname; /* user name */ 1199 const char *pass; /* password */ 1200}; 1201typedef struct cred_t cred_t; 1202 1203static int 1204auth_conv(int num_msg, const struct pam_message **msg, 1205 struct pam_response **resp, void *appdata) 1206{ 1207 int i; 1208 cred_t *cred = (cred_t *) appdata; 1209 struct pam_response *reply; 1210 1211 reply = calloc(num_msg, sizeof *reply); 1212 if (reply == NULL) 1213 return PAM_BUF_ERR; 1214 1215 for (i = 0; i < num_msg; i++) { 1216 switch (msg[i]->msg_style) { 1217 case PAM_PROMPT_ECHO_ON: /* assume want user name */ 1218 reply[i].resp_retcode = PAM_SUCCESS; 1219 reply[i].resp = COPY_STRING(cred->uname); 1220 /* PAM frees resp. */ 1221 break; 1222 case PAM_PROMPT_ECHO_OFF: /* assume want password */ 1223 reply[i].resp_retcode = PAM_SUCCESS; 1224 reply[i].resp = COPY_STRING(cred->pass); 1225 /* PAM frees resp. */ 1226 break; 1227 case PAM_TEXT_INFO: 1228 case PAM_ERROR_MSG: 1229 reply[i].resp_retcode = PAM_SUCCESS; 1230 reply[i].resp = NULL; 1231 break; 1232 default: /* unknown message style */ 1233 free(reply); 1234 return PAM_CONV_ERR; 1235 } 1236 } 1237 1238 *resp = reply; 1239 return PAM_SUCCESS; 1240} 1241 1242/* 1243 * Attempt to authenticate the user using PAM. Returns 0 if the user is 1244 * authenticated, or 1 if not authenticated. If some sort of PAM system 1245 * error occurs (e.g., the "/etc/pam.conf" file is missing) then this 1246 * function returns -1. This can be used as an indication that we should 1247 * fall back to a different authentication mechanism. 1248 */ 1249static int 1250auth_pam(struct passwd **ppw, const char *pass) 1251{ 1252 const char *tmpl_user; 1253 const void *item; 1254 int rval; 1255 int e; 1256 cred_t auth_cred = { (*ppw)->pw_name, pass }; 1257 struct pam_conv conv = { &auth_conv, &auth_cred }; 1258 1259 e = pam_start("ftpd", (*ppw)->pw_name, &conv, &pamh); 1260 if (e != PAM_SUCCESS) { 1261 /* 1262 * In OpenPAM, it's OK to pass NULL to pam_strerror() 1263 * if context creation has failed in the first place. 1264 */ 1265 syslog(LOG_ERR, "pam_start: %s", pam_strerror(NULL, e)); 1266 return -1; 1267 } 1268 1269 e = pam_set_item(pamh, PAM_RHOST, remotehost); 1270 if (e != PAM_SUCCESS) { 1271 syslog(LOG_ERR, "pam_set_item(PAM_RHOST): %s", 1272 pam_strerror(pamh, e)); 1273 if ((e = pam_end(pamh, e)) != PAM_SUCCESS) { 1274 syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e)); 1275 } 1276 pamh = NULL; 1277 return -1; 1278 } 1279 1280 e = pam_authenticate(pamh, 0); 1281 switch (e) { 1282 case PAM_SUCCESS: 1283 /* 1284 * With PAM we support the concept of a "template" 1285 * user. The user enters a login name which is 1286 * authenticated by PAM, usually via a remote service 1287 * such as RADIUS or TACACS+. If authentication 1288 * succeeds, a different but related "template" name 1289 * is used for setting the credentials, shell, and 1290 * home directory. The name the user enters need only 1291 * exist on the remote authentication server, but the 1292 * template name must be present in the local password 1293 * database. 1294 * 1295 * This is supported by two various mechanisms in the 1296 * individual modules. However, from the application's 1297 * point of view, the template user is always passed 1298 * back as a changed value of the PAM_USER item. 1299 */ 1300 if ((e = pam_get_item(pamh, PAM_USER, &item)) == 1301 PAM_SUCCESS) { 1302 tmpl_user = (const char *) item; 1303 if (strcmp((*ppw)->pw_name, tmpl_user) != 0) 1304 *ppw = getpwnam(tmpl_user); 1305 } else 1306 syslog(LOG_ERR, "Couldn't get PAM_USER: %s", 1307 pam_strerror(pamh, e)); 1308 rval = 0; 1309 break; 1310 1311 case PAM_AUTH_ERR: 1312 case PAM_USER_UNKNOWN: 1313 case PAM_MAXTRIES: 1314 rval = 1; 1315 break; 1316 1317 default: 1318 syslog(LOG_ERR, "pam_authenticate: %s", pam_strerror(pamh, e)); 1319 rval = -1; 1320 break; 1321 } 1322 1323 if (rval == 0) { 1324 e = pam_acct_mgmt(pamh, 0); 1325 if (e == PAM_NEW_AUTHTOK_REQD) { 1326 e = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK); 1327 if (e != PAM_SUCCESS) { 1328 syslog(LOG_ERR, "pam_chauthtok: %s", pam_strerror(pamh, e)); 1329 rval = 1; 1330 } 1331 } else if (e != PAM_SUCCESS) { 1332 rval = 1; 1333 } 1334 } 1335 1336 if (rval != 0) { 1337 if ((e = pam_end(pamh, e)) != PAM_SUCCESS) { 1338 syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e)); 1339 } 1340 pamh = NULL; 1341 } 1342 return rval; 1343} 1344 1345#endif /* USE_PAM */ 1346 1347void 1348pass(char *passwd) 1349{ 1350 int rval; 1351 FILE *fd; 1352#ifdef LOGIN_CAP 1353 login_cap_t *lc = NULL; 1354#endif 1355#ifdef USE_PAM 1356 int e; 1357#endif 1358 char *chrootdir; 1359 char *residue = NULL; 1360 char *xpasswd; 1361 1362 if (logged_in || askpasswd == 0) { 1363 reply(503, "Login with USER first."); 1364 return; 1365 } 1366 askpasswd = 0; 1367 if (!guest) { /* "ftp" is only account allowed no password */ 1368 if (pw == NULL) { 1369 rval = 1; /* failure below */ 1370 goto skip; 1371 } 1372#ifdef USE_PAM 1373 rval = auth_pam(&pw, passwd); 1374 if (rval >= 0) { 1375 opieunlock(); 1376 goto skip; 1377 } 1378#endif 1379 if (opieverify(&opiedata, passwd) == 0) 1380 xpasswd = pw->pw_passwd; 1381 else if (pwok) { 1382 xpasswd = crypt(passwd, pw->pw_passwd); 1383 if (passwd[0] == '\0' && pw->pw_passwd[0] != '\0') 1384 xpasswd = ":"; 1385 } else { 1386 rval = 1; 1387 goto skip; 1388 } 1389 rval = strcmp(pw->pw_passwd, xpasswd); 1390 if (pw->pw_expire && time(NULL) >= pw->pw_expire) 1391 rval = 1; /* failure */ 1392skip: 1393 /* 1394 * If rval == 1, the user failed the authentication check 1395 * above. If rval == 0, either PAM or local authentication 1396 * succeeded. 1397 */ 1398 if (rval) { 1399 reply(530, "Login incorrect."); 1400 if (logging) { 1401 syslog(LOG_NOTICE, 1402 "FTP LOGIN FAILED FROM %s", 1403 remotehost); 1404 syslog(LOG_AUTHPRIV | LOG_NOTICE, 1405 "FTP LOGIN FAILED FROM %s, %s", 1406 remotehost, curname); 1407 } 1408 pw = NULL; 1409 if (login_attempts++ >= 5) { 1410 syslog(LOG_NOTICE, 1411 "repeated login failures from %s", 1412 remotehost); 1413 exit(0); 1414 } 1415 return; 1416 } 1417 } 1418 login_attempts = 0; /* this time successful */ 1419 if (setegid(pw->pw_gid) < 0) { 1420 reply(550, "Can't set gid."); 1421 return; 1422 } 1423 /* May be overridden by login.conf */ 1424 (void) umask(defumask); 1425#ifdef LOGIN_CAP 1426 if ((lc = login_getpwclass(pw)) != NULL) { 1427 char remote_ip[MAXHOSTNAMELEN]; 1428 1429 getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len, 1430 remote_ip, sizeof(remote_ip) - 1, NULL, 0, 1431 NI_NUMERICHOST); 1432 remote_ip[sizeof(remote_ip) - 1] = 0; 1433 if (!auth_hostok(lc, remotehost, remote_ip)) { 1434 syslog(LOG_INFO|LOG_AUTH, 1435 "FTP LOGIN FAILED (HOST) as %s: permission denied.", 1436 pw->pw_name); 1437 reply(530, "Permission denied.\n"); 1438 pw = NULL; 1439 return; 1440 } 1441 if (!auth_timeok(lc, time(NULL))) { 1442 reply(530, "Login not available right now.\n"); 1443 pw = NULL; 1444 return; 1445 } 1446 } 1447 setusercontext(lc, pw, 0, 1448 LOGIN_SETLOGIN|LOGIN_SETGROUP|LOGIN_SETPRIORITY| 1449 LOGIN_SETRESOURCES|LOGIN_SETUMASK|LOGIN_SETMAC); 1450#else 1451 setlogin(pw->pw_name); 1452 (void) initgroups(pw->pw_name, pw->pw_gid); 1453#endif 1454 1455#ifdef USE_PAM 1456 if (pamh) { 1457 if ((e = pam_open_session(pamh, 0)) != PAM_SUCCESS) { 1458 syslog(LOG_ERR, "pam_open_session: %s", pam_strerror(pamh, e)); 1459 } else if ((e = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS) { 1460 syslog(LOG_ERR, "pam_setcred: %s", pam_strerror(pamh, e)); 1461 } 1462 } 1463#endif 1464 1465 /* open wtmp before chroot */ 1466 if (dowtmp) 1467 ftpd_logwtmp(ttyline, pw->pw_name, 1468 (struct sockaddr *)&his_addr); 1469 logged_in = 1; 1470 1471 if (guest && stats && statfd < 0) 1472#ifdef VIRTUAL_HOSTING 1473 statfd = open(thishost->statfile, O_WRONLY|O_APPEND); 1474#else 1475 statfd = open(_PATH_FTPDSTATFILE, O_WRONLY|O_APPEND); 1476#endif 1477 if (statfd < 0) 1478 stats = 0; 1479 1480 dochroot = 1481 checkuser(_PATH_FTPCHROOT, pw->pw_name, 1, &residue) 1482#ifdef LOGIN_CAP /* Allow login.conf configuration as well */ 1483 || login_getcapbool(lc, "ftp-chroot", 0) 1484#endif 1485 ; 1486 chrootdir = NULL; 1487 /* 1488 * For a chrooted local user, 1489 * a) see whether ftpchroot(5) specifies a chroot directory, 1490 * b) extract the directory pathname from the line, 1491 * c) expand it to the absolute pathname if necessary. 1492 */ 1493 if (dochroot && residue && 1494 (chrootdir = strtok(residue, " \t")) != NULL) { 1495 if (chrootdir[0] != '/') 1496 asprintf(&chrootdir, "%s/%s", pw->pw_dir, chrootdir); 1497 else 1498 chrootdir = strdup(chrootdir); /* so it can be freed */ 1499 if (chrootdir == NULL) 1500 fatalerror("Ran out of memory."); 1501 } 1502 if (guest || dochroot) { 1503 /* 1504 * If no chroot directory set yet, use the login directory. 1505 * Copy it so it can be modified while pw->pw_dir stays intact. 1506 */ 1507 if (chrootdir == NULL && 1508 (chrootdir = strdup(pw->pw_dir)) == NULL) 1509 fatalerror("Ran out of memory."); 1510 /* 1511 * Check for the "/chroot/./home" syntax, 1512 * separate the chroot and home directory pathnames. 1513 */ 1514 if ((homedir = strstr(chrootdir, "/./")) != NULL) { 1515 *(homedir++) = '\0'; /* wipe '/' */ 1516 homedir++; /* skip '.' */ 1517 /* so chrootdir can be freed later */ 1518 if ((homedir = strdup(homedir)) == NULL) 1519 fatalerror("Ran out of memory."); 1520 } else { 1521 /* 1522 * We MUST do a chdir() after the chroot. Otherwise 1523 * the old current directory will be accessible as "." 1524 * outside the new root! 1525 */ 1526 homedir = "/"; 1527 } 1528 /* 1529 * Finally, do chroot() 1530 */ 1531 if (chroot(chrootdir) < 0) { 1532 reply(550, "Can't change root."); 1533 goto bad; 1534 } 1535 } else /* real user w/o chroot */ 1536 homedir = pw->pw_dir; 1537 /* 1538 * Set euid *before* doing chdir() so 1539 * a) the user won't be carried to a directory that he couldn't reach 1540 * on his own due to no permission to upper path components, 1541 * b) NFS mounted homedirs w/restrictive permissions will be accessible 1542 * (uid 0 has no root power over NFS if not mapped explicitly.) 1543 */ 1544 if (seteuid(pw->pw_uid) < 0) { 1545 reply(550, "Can't set uid."); 1546 goto bad; 1547 } 1548 if (chdir(homedir) < 0) { 1549 if (guest || dochroot) { 1550 reply(550, "Can't change to base directory."); 1551 goto bad; 1552 } else { 1553 if (chdir("/") < 0) { 1554 reply(550, "Root is inaccessible."); 1555 goto bad; 1556 } 1557 lreply(230, "No directory! Logging in with home=/"); 1558 } 1559 } 1560 1561 /* 1562 * Display a login message, if it exists. 1563 * N.B. reply(230,) must follow the message. 1564 */ 1565#ifdef VIRTUAL_HOSTING 1566 fd = fopen(thishost->loginmsg, "r"); 1567#else 1568 fd = fopen(_PATH_FTPLOGINMESG, "r"); 1569#endif 1570 if (fd != NULL) { 1571 char *cp, line[LINE_MAX]; 1572 1573 while (fgets(line, sizeof(line), fd) != NULL) { 1574 if ((cp = strchr(line, '\n')) != NULL) 1575 *cp = '\0'; 1576 lreply(230, "%s", line); 1577 } 1578 (void) fflush(stdout); 1579 (void) fclose(fd); 1580 } 1581 if (guest) { 1582 if (ident != NULL) 1583 free(ident); 1584 ident = strdup(passwd); 1585 if (ident == NULL) 1586 fatalerror("Ran out of memory."); 1587 1588 reply(230, "Guest login ok, access restrictions apply."); 1589#ifdef SETPROCTITLE 1590#ifdef VIRTUAL_HOSTING 1591 if (thishost != firsthost) 1592 snprintf(proctitle, sizeof(proctitle), 1593 "%s: anonymous(%s)/%s", remotehost, hostname, 1594 passwd); 1595 else 1596#endif 1597 snprintf(proctitle, sizeof(proctitle), 1598 "%s: anonymous/%s", remotehost, passwd); 1599 setproctitle("%s", proctitle); 1600#endif /* SETPROCTITLE */ 1601 if (logging) 1602 syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s", 1603 remotehost, passwd); 1604 } else { 1605 if (dochroot) 1606 reply(230, "User %s logged in, " 1607 "access restrictions apply.", pw->pw_name); 1608 else 1609 reply(230, "User %s logged in.", pw->pw_name); 1610 1611#ifdef SETPROCTITLE 1612 snprintf(proctitle, sizeof(proctitle), 1613 "%s: user/%s", remotehost, pw->pw_name); 1614 setproctitle("%s", proctitle); 1615#endif /* SETPROCTITLE */ 1616 if (logging) 1617 syslog(LOG_INFO, "FTP LOGIN FROM %s as %s", 1618 remotehost, pw->pw_name); 1619 } 1620#ifdef LOGIN_CAP 1621 login_close(lc); 1622#endif 1623 if (chrootdir) 1624 free(chrootdir); 1625 if (residue) 1626 free(residue); 1627 return; 1628bad: 1629 /* Forget all about it... */ 1630#ifdef LOGIN_CAP 1631 login_close(lc); 1632#endif 1633 if (chrootdir) 1634 free(chrootdir); 1635 if (residue) 1636 free(residue); 1637 end_login(); 1638} 1639 1640void 1641retrieve(char *cmd, char *name) 1642{ 1643 FILE *fin, *dout; 1644 struct stat st; 1645 int (*closefunc)(FILE *); 1646 time_t start; 1647 1648 if (cmd == 0) { 1649 fin = fopen(name, "r"), closefunc = fclose; 1650 st.st_size = 0; 1651 } else { 1652 char line[BUFSIZ]; 1653 1654 (void) snprintf(line, sizeof(line), cmd, name), name = line; 1655 fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose; 1656 st.st_size = -1; 1657 st.st_blksize = BUFSIZ; 1658 } 1659 if (fin == NULL) { 1660 if (errno != 0) { 1661 perror_reply(550, name); 1662 if (cmd == 0) { 1663 LOGCMD("get", name); 1664 } 1665 } 1666 return; 1667 } 1668 byte_count = -1; 1669 if (cmd == 0) { 1670 if (fstat(fileno(fin), &st) < 0) { 1671 perror_reply(550, name); 1672 goto done; 1673 } 1674 if (!S_ISREG(st.st_mode)) { 1675 /* 1676 * Never sending a raw directory is a workaround 1677 * for buggy clients that will attempt to RETR 1678 * a directory before listing it, e.g., Mozilla. 1679 * Preventing a guest from getting irregular files 1680 * is a simple security measure. 1681 */ 1682 if (S_ISDIR(st.st_mode) || guest) { 1683 reply(550, "%s: not a plain file.", name); 1684 goto done; 1685 } 1686 st.st_size = -1; 1687 /* st.st_blksize is set for all descriptor types */ 1688 } 1689 } 1690 if (restart_point) { 1691 if (type == TYPE_A) { 1692 off_t i, n; 1693 int c; 1694 1695 n = restart_point; 1696 i = 0; 1697 while (i++ < n) { 1698 if ((c=getc(fin)) == EOF) { 1699 perror_reply(550, name); 1700 goto done; 1701 } 1702 if (c == '\n') 1703 i++; 1704 } 1705 } else if (lseek(fileno(fin), restart_point, L_SET) < 0) { 1706 perror_reply(550, name); 1707 goto done; 1708 } 1709 } 1710 dout = dataconn(name, st.st_size, "w"); 1711 if (dout == NULL) 1712 goto done; 1713 time(&start); 1714 send_data(fin, dout, st.st_blksize, st.st_size, 1715 restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode)); 1716 if (cmd == 0 && guest && stats && byte_count > 0) 1717 logxfer(name, byte_count, start); 1718 (void) fclose(dout); 1719 data = -1; 1720 pdata = -1; 1721done: 1722 if (cmd == 0) 1723 LOGBYTES("get", name, byte_count); 1724 (*closefunc)(fin); 1725} 1726 1727void 1728store(char *name, char *mode, int unique) 1729{ 1730 int fd; 1731 FILE *fout, *din; 1732 int (*closefunc)(FILE *); 1733 1734 if (*mode == 'a') { /* APPE */ 1735 if (unique) { 1736 /* Programming error */ 1737 syslog(LOG_ERR, "Internal: unique flag to APPE"); 1738 unique = 0; 1739 } 1740 if (guest && noguestmod) { 1741 reply(550, "Appending to existing file denied"); 1742 goto err; 1743 } 1744 restart_point = 0; /* not affected by preceding REST */ 1745 } 1746 if (unique) /* STOU overrides REST */ 1747 restart_point = 0; 1748 if (guest && noguestmod) { 1749 if (restart_point) { /* guest STOR w/REST */ 1750 reply(550, "Modifying existing file denied"); 1751 goto err; 1752 } else /* treat guest STOR as STOU */ 1753 unique = 1; 1754 } 1755 1756 if (restart_point) 1757 mode = "r+"; /* so ASCII manual seek can work */ 1758 if (unique) { 1759 if ((fd = guniquefd(name, &name)) < 0) 1760 goto err; 1761 fout = fdopen(fd, mode); 1762 } else 1763 fout = fopen(name, mode); 1764 closefunc = fclose; 1765 if (fout == NULL) { 1766 perror_reply(553, name); 1767 goto err; 1768 } 1769 byte_count = -1; 1770 if (restart_point) { 1771 if (type == TYPE_A) { 1772 off_t i, n; 1773 int c; 1774 1775 n = restart_point; 1776 i = 0; 1777 while (i++ < n) { 1778 if ((c=getc(fout)) == EOF) { 1779 perror_reply(550, name); 1780 goto done; 1781 } 1782 if (c == '\n') 1783 i++; 1784 } 1785 /* 1786 * We must do this seek to "current" position 1787 * because we are changing from reading to 1788 * writing. 1789 */ 1790 if (fseeko(fout, 0, SEEK_CUR) < 0) { 1791 perror_reply(550, name); 1792 goto done; 1793 } 1794 } else if (lseek(fileno(fout), restart_point, L_SET) < 0) { 1795 perror_reply(550, name); 1796 goto done; 1797 } 1798 } 1799 din = dataconn(name, -1, "r"); 1800 if (din == NULL) 1801 goto done; 1802 if (receive_data(din, fout) == 0) { 1803 if (unique) 1804 reply(226, "Transfer complete (unique file name:%s).", 1805 name); 1806 else 1807 reply(226, "Transfer complete."); 1808 } 1809 (void) fclose(din); 1810 data = -1; 1811 pdata = -1; 1812done: 1813 LOGBYTES(*mode == 'a' ? "append" : "put", name, byte_count); 1814 (*closefunc)(fout); 1815 return; 1816err: 1817 LOGCMD(*mode == 'a' ? "append" : "put" , name); 1818 return; 1819} 1820 1821static FILE * 1822getdatasock(char *mode) 1823{ 1824 int on = 1, s, t, tries; 1825 1826 if (data >= 0) 1827 return (fdopen(data, mode)); 1828 1829 s = socket(data_dest.su_family, SOCK_STREAM, 0); 1830 if (s < 0) 1831 goto bad; 1832 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 1833 syslog(LOG_WARNING, "data setsockopt (SO_REUSEADDR): %m"); 1834 /* anchor socket to avoid multi-homing problems */ 1835 data_source = ctrl_addr; 1836 data_source.su_port = htons(dataport); 1837 (void) seteuid(0); 1838 for (tries = 1; ; tries++) { 1839 /* 1840 * We should loop here since it's possible that 1841 * another ftpd instance has passed this point and is 1842 * trying to open a data connection in active mode now. 1843 * Until the other connection is opened, we'll be getting 1844 * EADDRINUSE because no SOCK_STREAM sockets in the system 1845 * can share both local and remote addresses, localIP:20 1846 * and *:* in this case. 1847 */ 1848 if (bind(s, (struct sockaddr *)&data_source, 1849 data_source.su_len) >= 0) 1850 break; 1851 if (errno != EADDRINUSE || tries > 10) 1852 goto bad; 1853 sleep(tries); 1854 } 1855 (void) seteuid(pw->pw_uid); 1856#ifdef IP_TOS 1857 if (data_source.su_family == AF_INET) 1858 { 1859 on = IPTOS_THROUGHPUT; 1860 if (setsockopt(s, IPPROTO_IP, IP_TOS, &on, sizeof(int)) < 0) 1861 syslog(LOG_WARNING, "data setsockopt (IP_TOS): %m"); 1862 } 1863#endif 1864#ifdef TCP_NOPUSH 1865 /* 1866 * Turn off push flag to keep sender TCP from sending short packets 1867 * at the boundaries of each write(). Should probably do a SO_SNDBUF 1868 * to set the send buffer size as well, but that may not be desirable 1869 * in heavy-load situations. 1870 */ 1871 on = 1; 1872 if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, &on, sizeof on) < 0) 1873 syslog(LOG_WARNING, "data setsockopt (TCP_NOPUSH): %m"); 1874#endif 1875#ifdef SO_SNDBUF 1876 on = 65536; 1877 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &on, sizeof on) < 0) 1878 syslog(LOG_WARNING, "data setsockopt (SO_SNDBUF): %m"); 1879#endif 1880 1881 return (fdopen(s, mode)); 1882bad: 1883 /* Return the real value of errno (close may change it) */ 1884 t = errno; 1885 (void) seteuid(pw->pw_uid); 1886 (void) close(s); 1887 errno = t; 1888 return (NULL); 1889} 1890 1891static FILE * 1892dataconn(char *name, off_t size, char *mode) 1893{ 1894 char sizebuf[32]; 1895 FILE *file; 1896 int retry = 0, tos, conerrno; 1897 1898 file_size = size; 1899 byte_count = 0; 1900 if (size != -1) 1901 (void) snprintf(sizebuf, sizeof(sizebuf), 1902 " (%jd bytes)", (intmax_t)size); 1903 else 1904 *sizebuf = '\0'; 1905 if (pdata >= 0) { 1906 union sockunion from; 1907 int flags; 1908 int s, fromlen = ctrl_addr.su_len; 1909 struct timeval timeout; 1910 fd_set set; 1911 1912 FD_ZERO(&set); 1913 FD_SET(pdata, &set); 1914 1915 timeout.tv_usec = 0; 1916 timeout.tv_sec = 120; 1917 1918 /* 1919 * Granted a socket is in the blocking I/O mode, 1920 * accept() will block after a successful select() 1921 * if the selected connection dies in between. 1922 * Therefore set the non-blocking I/O flag here. 1923 */ 1924 if ((flags = fcntl(pdata, F_GETFL, 0)) == -1 || 1925 fcntl(pdata, F_SETFL, flags | O_NONBLOCK) == -1) 1926 goto pdata_err; 1927 if (select(pdata+1, &set, NULL, NULL, &timeout) <= 0 || 1928 (s = accept(pdata, (struct sockaddr *) &from, &fromlen)) < 0) 1929 goto pdata_err; 1930 (void) close(pdata); 1931 pdata = s; 1932 /* 1933 * Unset the inherited non-blocking I/O flag 1934 * on the child socket so stdio can work on it. 1935 */ 1936 if ((flags = fcntl(pdata, F_GETFL, 0)) == -1 || 1937 fcntl(pdata, F_SETFL, flags & ~O_NONBLOCK) == -1) 1938 goto pdata_err; 1939#ifdef IP_TOS 1940 if (from.su_family == AF_INET) 1941 { 1942 tos = IPTOS_THROUGHPUT; 1943 if (setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(int)) < 0) 1944 syslog(LOG_WARNING, "pdata setsockopt (IP_TOS): %m"); 1945 } 1946#endif 1947 reply(150, "Opening %s mode data connection for '%s'%s.", 1948 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); 1949 return (fdopen(pdata, mode)); 1950pdata_err: 1951 reply(425, "Can't open data connection."); 1952 (void) close(pdata); 1953 pdata = -1; 1954 return (NULL); 1955 } 1956 if (data >= 0) { 1957 reply(125, "Using existing data connection for '%s'%s.", 1958 name, sizebuf); 1959 usedefault = 1; 1960 return (fdopen(data, mode)); 1961 } 1962 if (usedefault) 1963 data_dest = his_addr; 1964 usedefault = 1; 1965 do { 1966 file = getdatasock(mode); 1967 if (file == NULL) { 1968 char hostbuf[BUFSIZ], portbuf[BUFSIZ]; 1969 getnameinfo((struct sockaddr *)&data_source, 1970 data_source.su_len, hostbuf, sizeof(hostbuf) - 1, 1971 portbuf, sizeof(portbuf), 1972 NI_NUMERICHOST|NI_NUMERICSERV); 1973 reply(425, "Can't create data socket (%s,%s): %s.", 1974 hostbuf, portbuf, strerror(errno)); 1975 return (NULL); 1976 } 1977 data = fileno(file); 1978 conerrno = 0; 1979 if (connect(data, (struct sockaddr *)&data_dest, 1980 data_dest.su_len) == 0) 1981 break; 1982 conerrno = errno; 1983 (void) fclose(file); 1984 data = -1; 1985 if (conerrno == EADDRINUSE) { 1986 sleep(swaitint); 1987 retry += swaitint; 1988 } else { 1989 break; 1990 } 1991 } while (retry <= swaitmax); 1992 if (conerrno != 0) { 1993 perror_reply(425, "Can't build data connection"); 1994 return (NULL); 1995 } 1996 reply(150, "Opening %s mode data connection for '%s'%s.", 1997 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); 1998 return (file); 1999} 2000 2001/* 2002 * Tranfer the contents of "instr" to "outstr" peer using the appropriate 2003 * encapsulation of the data subject to Mode, Structure, and Type. 2004 * 2005 * NB: Form isn't handled. 2006 */ 2007static int 2008send_data(FILE *instr, FILE *outstr, size_t blksize, off_t filesize, int isreg) 2009{ 2010 int c, cp, filefd, netfd; 2011 char *buf; 2012 off_t cnt; 2013 2014 transflag++; 2015 switch (type) { 2016 2017 case TYPE_A: 2018 cp = '\0'; 2019 while ((c = getc(instr)) != EOF) { 2020 if (recvurg) 2021 goto got_oob; 2022 byte_count++; 2023 if (c == '\n' && cp != '\r') { 2024 if (ferror(outstr)) 2025 goto data_err; 2026 (void) putc('\r', outstr); 2027 } 2028 (void) putc(c, outstr); 2029 cp = c; 2030 } 2031 if (recvurg) 2032 goto got_oob; 2033 fflush(outstr); 2034 transflag = 0; 2035 if (ferror(instr)) 2036 goto file_err; 2037 if (ferror(outstr)) 2038 goto data_err; 2039 reply(226, "Transfer complete."); 2040 return (0); 2041 2042 case TYPE_I: 2043 case TYPE_L: 2044 /* 2045 * isreg is only set if we are not doing restart and we 2046 * are sending a regular file 2047 */ 2048 netfd = fileno(outstr); 2049 filefd = fileno(instr); 2050 2051 if (isreg) { 2052 2053 char *msg = "Transfer complete."; 2054 off_t offset; 2055 int err; 2056 2057 cnt = offset = 0; 2058 2059 while (filesize > 0) { 2060 err = sendfile(filefd, netfd, offset, 0, 2061 (struct sf_hdtr *) NULL, &cnt, 0); 2062 /* 2063 * Calculate byte_count before OOB processing. 2064 * It can be used in myoob() later. 2065 */ 2066 byte_count += cnt; 2067 if (recvurg) 2068 goto got_oob; 2069 offset += cnt; 2070 filesize -= cnt; 2071 2072 if (err == -1) { 2073 if (cnt == 0 && offset == 0) 2074 goto oldway; 2075 2076 goto data_err; 2077 } 2078 2079 /* 2080 * We hit the EOF prematurely. 2081 * Perhaps the file was externally truncated. 2082 */ 2083 if (cnt == 0) { 2084 msg = "Transfer finished due to " 2085 "premature end of file."; 2086 break; 2087 } 2088 } 2089 2090 transflag = 0; 2091 reply(226, msg); 2092 return (0); 2093 } 2094 2095oldway: 2096 if ((buf = malloc(blksize)) == NULL) { 2097 transflag = 0; 2098 perror_reply(451, "Local resource failure: malloc"); 2099 return (-1); 2100 } 2101 2102 while ((cnt = read(filefd, buf, blksize)) > 0 && 2103 write(netfd, buf, cnt) == cnt) 2104 byte_count += cnt; 2105 transflag = 0; 2106 (void)free(buf); 2107 if (cnt != 0) { 2108 if (cnt < 0) 2109 goto file_err; 2110 goto data_err; 2111 } 2112 reply(226, "Transfer complete."); 2113 return (0); 2114 default: 2115 transflag = 0; 2116 reply(550, "Unimplemented TYPE %d in send_data", type); 2117 return (-1); 2118 } 2119 2120data_err: 2121 transflag = 0; 2122 perror_reply(426, "Data connection"); 2123 return (-1); 2124 2125file_err: 2126 transflag = 0; 2127 perror_reply(551, "Error on input file"); 2128 return (-1); 2129 2130got_oob: 2131 myoob(); 2132 recvurg = 0; 2133 transflag = 0; 2134 return (-1); 2135} 2136 2137/* 2138 * Transfer data from peer to "outstr" using the appropriate encapulation of 2139 * the data subject to Mode, Structure, and Type. 2140 * 2141 * N.B.: Form isn't handled. 2142 */ 2143static int 2144receive_data(FILE *instr, FILE *outstr) 2145{ 2146 int c; 2147 int cnt, bare_lfs; 2148 char buf[BUFSIZ]; 2149 2150 transflag++; 2151 bare_lfs = 0; 2152 2153 switch (type) { 2154 2155 case TYPE_I: 2156 case TYPE_L: 2157 while ((cnt = read(fileno(instr), buf, sizeof(buf))) > 0) { 2158 if (recvurg) 2159 goto got_oob; 2160 if (write(fileno(outstr), buf, cnt) != cnt) 2161 goto file_err; 2162 byte_count += cnt; 2163 } 2164 if (recvurg) 2165 goto got_oob; 2166 if (cnt < 0) 2167 goto data_err; 2168 transflag = 0; 2169 return (0); 2170 2171 case TYPE_E: 2172 reply(553, "TYPE E not implemented."); 2173 transflag = 0; 2174 return (-1); 2175 2176 case TYPE_A: 2177 while ((c = getc(instr)) != EOF) { 2178 if (recvurg) 2179 goto got_oob; 2180 byte_count++; 2181 if (c == '\n') 2182 bare_lfs++; 2183 while (c == '\r') { 2184 if (ferror(outstr)) 2185 goto data_err; 2186 if ((c = getc(instr)) != '\n') { 2187 (void) putc ('\r', outstr); 2188 if (c == '\0' || c == EOF) 2189 goto contin2; 2190 } 2191 } 2192 (void) putc(c, outstr); 2193 contin2: ; 2194 } 2195 if (recvurg) 2196 goto got_oob; 2197 fflush(outstr); 2198 if (ferror(instr)) 2199 goto data_err; 2200 if (ferror(outstr)) 2201 goto file_err; 2202 transflag = 0; 2203 if (bare_lfs) { 2204 lreply(226, 2205 "WARNING! %d bare linefeeds received in ASCII mode", 2206 bare_lfs); 2207 (void)printf(" File may not have transferred correctly.\r\n"); 2208 } 2209 return (0); 2210 default: 2211 reply(550, "Unimplemented TYPE %d in receive_data", type); 2212 transflag = 0; 2213 return (-1); 2214 } 2215 2216data_err: 2217 transflag = 0; 2218 perror_reply(426, "Data Connection"); 2219 return (-1); 2220 2221file_err: 2222 transflag = 0; 2223 perror_reply(452, "Error writing file"); 2224 return (-1); 2225 2226got_oob: 2227 myoob(); 2228 recvurg = 0; 2229 transflag = 0; 2230 return (-1); 2231} 2232 2233void 2234statfilecmd(char *filename) 2235{ 2236 FILE *fin; 2237 int atstart; 2238 int c; 2239 char line[LINE_MAX]; 2240 2241 (void)snprintf(line, sizeof(line), _PATH_LS " -lgA %s", filename); 2242 fin = ftpd_popen(line, "r"); 2243 lreply(211, "status of %s:", filename); 2244 atstart = 1; 2245 while ((c = getc(fin)) != EOF) { 2246 if (c == '\n') { 2247 if (ferror(stdout)){ 2248 perror_reply(421, "control connection"); 2249 (void) ftpd_pclose(fin); 2250 dologout(1); 2251 /* NOTREACHED */ 2252 } 2253 if (ferror(fin)) { 2254 perror_reply(551, filename); 2255 (void) ftpd_pclose(fin); 2256 return; 2257 } 2258 (void) putc('\r', stdout); 2259 } 2260 /* 2261 * RFC 959 says neutral text should be prepended before 2262 * a leading 3-digit number followed by whitespace, but 2263 * many ftp clients can be confused by any leading digits, 2264 * as a matter of fact. 2265 */ 2266 if (atstart && isdigit(c)) 2267 (void) putc(' ', stdout); 2268 (void) putc(c, stdout); 2269 atstart = (c == '\n'); 2270 } 2271 (void) ftpd_pclose(fin); 2272 reply(211, "End of Status"); 2273} 2274 2275void 2276statcmd(void) 2277{ 2278 union sockunion *su; 2279 u_char *a, *p; 2280 char hname[NI_MAXHOST]; 2281 int ispassive; 2282 2283 if (hostinfo) { 2284 lreply(211, "%s FTP server status:", hostname); 2285 printf(" %s\r\n", version); 2286 } else 2287 lreply(211, "FTP server status:"); 2288 printf(" Connected to %s", remotehost); 2289 if (!getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len, 2290 hname, sizeof(hname) - 1, NULL, 0, NI_NUMERICHOST)) { 2291 if (strcmp(hname, remotehost) != 0) 2292 printf(" (%s)", hname); 2293 } 2294 printf("\r\n"); 2295 if (logged_in) { 2296 if (guest) 2297 printf(" Logged in anonymously\r\n"); 2298 else 2299 printf(" Logged in as %s\r\n", pw->pw_name); 2300 } else if (askpasswd) 2301 printf(" Waiting for password\r\n"); 2302 else 2303 printf(" Waiting for user name\r\n"); 2304 printf(" TYPE: %s", typenames[type]); 2305 if (type == TYPE_A || type == TYPE_E) 2306 printf(", FORM: %s", formnames[form]); 2307 if (type == TYPE_L) 2308#if CHAR_BIT == 8 2309 printf(" %d", CHAR_BIT); 2310#else 2311 printf(" %d", bytesize); /* need definition! */ 2312#endif 2313 printf("; STRUcture: %s; transfer MODE: %s\r\n", 2314 strunames[stru], modenames[mode]); 2315 if (data != -1) 2316 printf(" Data connection open\r\n"); 2317 else if (pdata != -1) { 2318 ispassive = 1; 2319 su = &pasv_addr; 2320 goto printaddr; 2321 } else if (usedefault == 0) { 2322 ispassive = 0; 2323 su = &data_dest; 2324printaddr: 2325#define UC(b) (((int) b) & 0xff) 2326 if (epsvall) { 2327 printf(" EPSV only mode (EPSV ALL)\r\n"); 2328 goto epsvonly; 2329 } 2330 2331 /* PORT/PASV */ 2332 if (su->su_family == AF_INET) { 2333 a = (u_char *) &su->su_sin.sin_addr; 2334 p = (u_char *) &su->su_sin.sin_port; 2335 printf(" %s (%d,%d,%d,%d,%d,%d)\r\n", 2336 ispassive ? "PASV" : "PORT", 2337 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 2338 UC(p[0]), UC(p[1])); 2339 } 2340 2341 /* LPRT/LPSV */ 2342 { 2343 int alen, af, i; 2344 2345 switch (su->su_family) { 2346 case AF_INET: 2347 a = (u_char *) &su->su_sin.sin_addr; 2348 p = (u_char *) &su->su_sin.sin_port; 2349 alen = sizeof(su->su_sin.sin_addr); 2350 af = 4; 2351 break; 2352 case AF_INET6: 2353 a = (u_char *) &su->su_sin6.sin6_addr; 2354 p = (u_char *) &su->su_sin6.sin6_port; 2355 alen = sizeof(su->su_sin6.sin6_addr); 2356 af = 6; 2357 break; 2358 default: 2359 af = 0; 2360 break; 2361 } 2362 if (af) { 2363 printf(" %s (%d,%d,", ispassive ? "LPSV" : "LPRT", 2364 af, alen); 2365 for (i = 0; i < alen; i++) 2366 printf("%d,", UC(a[i])); 2367 printf("%d,%d,%d)\r\n", 2, UC(p[0]), UC(p[1])); 2368 } 2369 } 2370 2371epsvonly:; 2372 /* EPRT/EPSV */ 2373 { 2374 int af; 2375 2376 switch (su->su_family) { 2377 case AF_INET: 2378 af = 1; 2379 break; 2380 case AF_INET6: 2381 af = 2; 2382 break; 2383 default: 2384 af = 0; 2385 break; 2386 } 2387 if (af) { 2388 union sockunion tmp; 2389 2390 tmp = *su; 2391 if (tmp.su_family == AF_INET6) 2392 tmp.su_sin6.sin6_scope_id = 0; 2393 if (!getnameinfo((struct sockaddr *)&tmp, tmp.su_len, 2394 hname, sizeof(hname) - 1, NULL, 0, 2395 NI_NUMERICHOST)) { 2396 printf(" %s |%d|%s|%d|\r\n", 2397 ispassive ? "EPSV" : "EPRT", 2398 af, hname, htons(tmp.su_port)); 2399 } 2400 } 2401 } 2402#undef UC 2403 } else 2404 printf(" No data connection\r\n"); 2405 reply(211, "End of status"); 2406} 2407 2408void 2409fatalerror(char *s) 2410{ 2411 2412 reply(451, "Error in server: %s\n", s); 2413 reply(221, "Closing connection due to server error."); 2414 dologout(0); 2415 /* NOTREACHED */ 2416} 2417 2418void 2419reply(int n, const char *fmt, ...) 2420{ 2421 va_list ap; 2422 2423 (void)printf("%d ", n); 2424 va_start(ap, fmt); 2425 (void)vprintf(fmt, ap); 2426 va_end(ap); 2427 (void)printf("\r\n"); 2428 (void)fflush(stdout); 2429 if (ftpdebug) { 2430 syslog(LOG_DEBUG, "<--- %d ", n); 2431 va_start(ap, fmt); 2432 vsyslog(LOG_DEBUG, fmt, ap); 2433 va_end(ap); 2434 } 2435} 2436 2437void 2438lreply(int n, const char *fmt, ...) 2439{ 2440 va_list ap; 2441 2442 (void)printf("%d- ", n); 2443 va_start(ap, fmt); 2444 (void)vprintf(fmt, ap); 2445 va_end(ap); 2446 (void)printf("\r\n"); 2447 (void)fflush(stdout); 2448 if (ftpdebug) { 2449 syslog(LOG_DEBUG, "<--- %d- ", n); 2450 va_start(ap, fmt); 2451 vsyslog(LOG_DEBUG, fmt, ap); 2452 va_end(ap); 2453 } 2454} 2455 2456static void 2457ack(char *s) 2458{ 2459 2460 reply(250, "%s command successful.", s); 2461} 2462 2463void 2464nack(char *s) 2465{ 2466 2467 reply(502, "%s command not implemented.", s); 2468} 2469 2470/* ARGSUSED */ 2471void 2472yyerror(char *s) 2473{ 2474 char *cp; 2475 2476 if ((cp = strchr(cbuf,'\n'))) 2477 *cp = '\0'; 2478 reply(500, "'%s': command not understood.", cbuf); 2479} 2480 2481void 2482delete(char *name) 2483{ 2484 struct stat st; 2485 2486 LOGCMD("delete", name); 2487 if (lstat(name, &st) < 0) { 2488 perror_reply(550, name); 2489 return; 2490 } 2491 if ((st.st_mode&S_IFMT) == S_IFDIR) { 2492 if (rmdir(name) < 0) { 2493 perror_reply(550, name); 2494 return; 2495 } 2496 goto done; 2497 } 2498 if (guest && noguestmod) { 2499 reply(550, "Operation not permitted"); 2500 return; 2501 } 2502 if (unlink(name) < 0) { 2503 perror_reply(550, name); 2504 return; 2505 } 2506done: 2507 ack("DELE"); 2508} 2509 2510void 2511cwd(char *path) 2512{ 2513 2514 if (chdir(path) < 0) 2515 perror_reply(550, path); 2516 else 2517 ack("CWD"); 2518} 2519 2520void 2521makedir(char *name) 2522{ 2523 char *s; 2524 2525 LOGCMD("mkdir", name); 2526 if (guest && noguestmkd) 2527 reply(550, "%s: permission denied", name); 2528 else if (mkdir(name, 0777) < 0) 2529 perror_reply(550, name); 2530 else { 2531 if ((s = doublequote(name)) == NULL) 2532 fatalerror("Ran out of memory."); 2533 reply(257, "\"%s\" directory created.", s); 2534 free(s); 2535 } 2536} 2537 2538void 2539removedir(char *name) 2540{ 2541 2542 LOGCMD("rmdir", name); 2543 if (rmdir(name) < 0) 2544 perror_reply(550, name); 2545 else 2546 ack("RMD"); 2547} 2548 2549void 2550pwd(void) 2551{ 2552 char *s, path[MAXPATHLEN + 1]; 2553 2554 if (getwd(path) == (char *)NULL) 2555 reply(550, "%s.", path); 2556 else { 2557 if ((s = doublequote(path)) == NULL) 2558 fatalerror("Ran out of memory."); 2559 reply(257, "\"%s\" is current directory.", s); 2560 free(s); 2561 } 2562} 2563 2564char * 2565renamefrom(char *name) 2566{ 2567 struct stat st; 2568 2569 if (guest && noguestmod) { 2570 reply(550, "Operation not permitted"); 2571 return (NULL); 2572 } 2573 if (lstat(name, &st) < 0) { 2574 perror_reply(550, name); 2575 return (NULL); 2576 } 2577 reply(350, "File exists, ready for destination name"); 2578 return (name); 2579} 2580 2581void 2582renamecmd(char *from, char *to) 2583{ 2584 struct stat st; 2585 2586 LOGCMD2("rename", from, to); 2587 2588 if (guest && (stat(to, &st) == 0)) { 2589 reply(550, "%s: permission denied", to); 2590 return; 2591 } 2592 2593 if (rename(from, to) < 0) 2594 perror_reply(550, "rename"); 2595 else 2596 ack("RNTO"); 2597} 2598 2599static void 2600dolog(struct sockaddr *who) 2601{ 2602 int error; 2603 2604 realhostname_sa(remotehost, sizeof(remotehost) - 1, who, who->sa_len); 2605 2606#ifdef SETPROCTITLE 2607#ifdef VIRTUAL_HOSTING 2608 if (thishost != firsthost) 2609 snprintf(proctitle, sizeof(proctitle), "%s: connected (to %s)", 2610 remotehost, hostname); 2611 else 2612#endif 2613 snprintf(proctitle, sizeof(proctitle), "%s: connected", 2614 remotehost); 2615 setproctitle("%s", proctitle); 2616#endif /* SETPROCTITLE */ 2617 2618 if (logging) { 2619#ifdef VIRTUAL_HOSTING 2620 if (thishost != firsthost) 2621 syslog(LOG_INFO, "connection from %s (to %s)", 2622 remotehost, hostname); 2623 else 2624#endif 2625 { 2626 char who_name[MAXHOSTNAMELEN]; 2627 2628 error = getnameinfo(who, who->sa_len, 2629 who_name, sizeof(who_name) - 1, 2630 NULL, 0, NI_NUMERICHOST); 2631 syslog(LOG_INFO, "connection from %s (%s)", remotehost, 2632 error == 0 ? who_name : ""); 2633 } 2634 } 2635} 2636 2637/* 2638 * Record logout in wtmp file 2639 * and exit with supplied status. 2640 */ 2641void 2642dologout(int status) 2643{ 2644 /* 2645 * Prevent reception of SIGURG from resulting in a resumption 2646 * back to the main program loop. 2647 */ 2648 transflag = 0; 2649 2650 if (logged_in && dowtmp) { 2651 (void) seteuid(0); 2652 ftpd_logwtmp(ttyline, "", NULL); 2653 } 2654 /* beware of flushing buffers after a SIGPIPE */ 2655 _exit(status); 2656} 2657 2658static void 2659sigurg(int signo) 2660{ 2661 2662 recvurg = 1; 2663} 2664 2665static void 2666myoob(void) 2667{ 2668 char *cp; 2669 2670 /* only process if transfer occurring */ 2671 if (!transflag) 2672 return; 2673 cp = tmpline; 2674 if (getline(cp, 7, stdin) == NULL) { 2675 reply(221, "You could at least say goodbye."); 2676 dologout(0); 2677 } 2678 upper(cp); 2679 if (strcmp(cp, "ABOR\r\n") == 0) { 2680 tmpline[0] = '\0'; 2681 reply(426, "Transfer aborted. Data connection closed."); 2682 reply(226, "Abort successful"); 2683 } 2684 if (strcmp(cp, "STAT\r\n") == 0) { 2685 tmpline[0] = '\0'; 2686 if (file_size != -1) 2687 reply(213, "Status: %jd of %jd bytes transferred", 2688 (intmax_t)byte_count, (intmax_t)file_size); 2689 else 2690 reply(213, "Status: %jd bytes transferred", 2691 (intmax_t)byte_count); 2692 } 2693} 2694 2695/* 2696 * Note: a response of 425 is not mentioned as a possible response to 2697 * the PASV command in RFC959. However, it has been blessed as 2698 * a legitimate response by Jon Postel in a telephone conversation 2699 * with Rick Adams on 25 Jan 89. 2700 */ 2701void 2702passive(void) 2703{ 2704 int len, on; 2705 char *p, *a; 2706 2707 if (pdata >= 0) /* close old port if one set */ 2708 close(pdata); 2709 2710 pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0); 2711 if (pdata < 0) { 2712 perror_reply(425, "Can't open passive connection"); 2713 return; 2714 } 2715 on = 1; 2716 if (setsockopt(pdata, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 2717 syslog(LOG_WARNING, "pdata setsockopt (SO_REUSEADDR): %m"); 2718 2719 (void) seteuid(0); 2720 2721#ifdef IP_PORTRANGE 2722 if (ctrl_addr.su_family == AF_INET) { 2723 on = restricted_data_ports ? IP_PORTRANGE_HIGH 2724 : IP_PORTRANGE_DEFAULT; 2725 2726 if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE, 2727 &on, sizeof(on)) < 0) 2728 goto pasv_error; 2729 } 2730#endif 2731#ifdef IPV6_PORTRANGE 2732 if (ctrl_addr.su_family == AF_INET6) { 2733 on = restricted_data_ports ? IPV6_PORTRANGE_HIGH 2734 : IPV6_PORTRANGE_DEFAULT; 2735 2736 if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE, 2737 &on, sizeof(on)) < 0) 2738 goto pasv_error; 2739 } 2740#endif 2741 2742 pasv_addr = ctrl_addr; 2743 pasv_addr.su_port = 0; 2744 if (bind(pdata, (struct sockaddr *)&pasv_addr, pasv_addr.su_len) < 0) 2745 goto pasv_error; 2746 2747 (void) seteuid(pw->pw_uid); 2748 2749 len = sizeof(pasv_addr); 2750 if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0) 2751 goto pasv_error; 2752 if (listen(pdata, 1) < 0) 2753 goto pasv_error; 2754 if (pasv_addr.su_family == AF_INET) 2755 a = (char *) &pasv_addr.su_sin.sin_addr; 2756 else if (pasv_addr.su_family == AF_INET6 && 2757 IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr)) 2758 a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12]; 2759 else 2760 goto pasv_error; 2761 2762 p = (char *) &pasv_addr.su_port; 2763 2764#define UC(b) (((int) b) & 0xff) 2765 2766 reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]), 2767 UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); 2768 return; 2769 2770pasv_error: 2771 (void) seteuid(pw->pw_uid); 2772 (void) close(pdata); 2773 pdata = -1; 2774 perror_reply(425, "Can't open passive connection"); 2775 return; 2776} 2777 2778/* 2779 * Long Passive defined in RFC 1639. 2780 * 228 Entering Long Passive Mode 2781 * (af, hal, h1, h2, h3,..., pal, p1, p2...) 2782 */ 2783 2784void 2785long_passive(char *cmd, int pf) 2786{ 2787 int len, on; 2788 char *p, *a; 2789 2790 if (pdata >= 0) /* close old port if one set */ 2791 close(pdata); 2792 2793 if (pf != PF_UNSPEC) { 2794 if (ctrl_addr.su_family != pf) { 2795 switch (ctrl_addr.su_family) { 2796 case AF_INET: 2797 pf = 1; 2798 break; 2799 case AF_INET6: 2800 pf = 2; 2801 break; 2802 default: 2803 pf = 0; 2804 break; 2805 } 2806 /* 2807 * XXX 2808 * only EPRT/EPSV ready clients will understand this 2809 */ 2810 if (strcmp(cmd, "EPSV") == 0 && pf) { 2811 reply(522, "Network protocol mismatch, " 2812 "use (%d)", pf); 2813 } else 2814 reply(501, "Network protocol mismatch"); /*XXX*/ 2815 2816 return; 2817 } 2818 } 2819 2820 pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0); 2821 if (pdata < 0) { 2822 perror_reply(425, "Can't open passive connection"); 2823 return; 2824 } 2825 on = 1; 2826 if (setsockopt(pdata, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 2827 syslog(LOG_WARNING, "pdata setsockopt (SO_REUSEADDR): %m"); 2828 2829 (void) seteuid(0); 2830 2831 pasv_addr = ctrl_addr; 2832 pasv_addr.su_port = 0; 2833 len = pasv_addr.su_len; 2834 2835#ifdef IP_PORTRANGE 2836 if (ctrl_addr.su_family == AF_INET) { 2837 on = restricted_data_ports ? IP_PORTRANGE_HIGH 2838 : IP_PORTRANGE_DEFAULT; 2839 2840 if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE, 2841 &on, sizeof(on)) < 0) 2842 goto pasv_error; 2843 } 2844#endif 2845#ifdef IPV6_PORTRANGE 2846 if (ctrl_addr.su_family == AF_INET6) { 2847 on = restricted_data_ports ? IPV6_PORTRANGE_HIGH 2848 : IPV6_PORTRANGE_DEFAULT; 2849 2850 if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE, 2851 &on, sizeof(on)) < 0) 2852 goto pasv_error; 2853 } 2854#endif 2855 2856 if (bind(pdata, (struct sockaddr *)&pasv_addr, len) < 0) 2857 goto pasv_error; 2858 2859 (void) seteuid(pw->pw_uid); 2860 2861 if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0) 2862 goto pasv_error; 2863 if (listen(pdata, 1) < 0) 2864 goto pasv_error; 2865 2866#define UC(b) (((int) b) & 0xff) 2867 2868 if (strcmp(cmd, "LPSV") == 0) { 2869 p = (char *)&pasv_addr.su_port; 2870 switch (pasv_addr.su_family) { 2871 case AF_INET: 2872 a = (char *) &pasv_addr.su_sin.sin_addr; 2873 v4_reply: 2874 reply(228, 2875"Entering Long Passive Mode (%d,%d,%d,%d,%d,%d,%d,%d,%d)", 2876 4, 4, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 2877 2, UC(p[0]), UC(p[1])); 2878 return; 2879 case AF_INET6: 2880 if (IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr)) { 2881 a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12]; 2882 goto v4_reply; 2883 } 2884 a = (char *) &pasv_addr.su_sin6.sin6_addr; 2885 reply(228, 2886"Entering Long Passive Mode " 2887"(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)", 2888 6, 16, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 2889 UC(a[4]), UC(a[5]), UC(a[6]), UC(a[7]), 2890 UC(a[8]), UC(a[9]), UC(a[10]), UC(a[11]), 2891 UC(a[12]), UC(a[13]), UC(a[14]), UC(a[15]), 2892 2, UC(p[0]), UC(p[1])); 2893 return; 2894 } 2895 } else if (strcmp(cmd, "EPSV") == 0) { 2896 switch (pasv_addr.su_family) { 2897 case AF_INET: 2898 case AF_INET6: 2899 reply(229, "Entering Extended Passive Mode (|||%d|)", 2900 ntohs(pasv_addr.su_port)); 2901 return; 2902 } 2903 } else { 2904 /* more proper error code? */ 2905 } 2906 2907pasv_error: 2908 (void) seteuid(pw->pw_uid); 2909 (void) close(pdata); 2910 pdata = -1; 2911 perror_reply(425, "Can't open passive connection"); 2912 return; 2913} 2914 2915/* 2916 * Generate unique name for file with basename "local" 2917 * and open the file in order to avoid possible races. 2918 * Try "local" first, then "local.1", "local.2" etc, up to "local.99". 2919 * Return descriptor to the file, set "name" to its name. 2920 * 2921 * Generates failure reply on error. 2922 */ 2923static int 2924guniquefd(char *local, char **name) 2925{ 2926 static char new[MAXPATHLEN]; 2927 struct stat st; 2928 char *cp; 2929 int count; 2930 int fd; 2931 2932 cp = strrchr(local, '/'); 2933 if (cp) 2934 *cp = '\0'; 2935 if (stat(cp ? local : ".", &st) < 0) { 2936 perror_reply(553, cp ? local : "."); 2937 return (-1); 2938 } 2939 if (cp) { 2940 /* 2941 * Let not overwrite dirname with counter suffix. 2942 * -4 is for /nn\0 2943 * In this extreme case dot won't be put in front of suffix. 2944 */ 2945 if (strlen(local) > sizeof(new) - 4) { 2946 reply(553, "Pathname too long"); 2947 return (-1); 2948 } 2949 *cp = '/'; 2950 } 2951 /* -4 is for the .nn<null> we put on the end below */ 2952 (void) snprintf(new, sizeof(new) - 4, "%s", local); 2953 cp = new + strlen(new); 2954 /* 2955 * Don't generate dotfile unless requested explicitly. 2956 * This covers the case when basename gets truncated off 2957 * by buffer size. 2958 */ 2959 if (cp > new && cp[-1] != '/') 2960 *cp++ = '.'; 2961 for (count = 0; count < 100; count++) { 2962 /* At count 0 try unmodified name */ 2963 if (count) 2964 (void)sprintf(cp, "%d", count); 2965 if ((fd = open(count ? new : local, 2966 O_RDWR | O_CREAT | O_EXCL, 0666)) >= 0) { 2967 *name = count ? new : local; 2968 return (fd); 2969 } 2970 if (errno != EEXIST) { 2971 perror_reply(553, count ? new : local); 2972 return (-1); 2973 } 2974 } 2975 reply(452, "Unique file name cannot be created."); 2976 return (-1); 2977} 2978 2979/* 2980 * Format and send reply containing system error number. 2981 */ 2982void 2983perror_reply(int code, char *string) 2984{ 2985 2986 reply(code, "%s: %s.", string, strerror(errno)); 2987} 2988 2989static char *onefile[] = { 2990 "", 2991 0 2992}; 2993 2994void 2995send_file_list(char *whichf) 2996{ 2997 struct stat st; 2998 DIR *dirp = NULL; 2999 struct dirent *dir; 3000 FILE *dout = NULL; 3001 char **dirlist, *dirname; 3002 int simple = 0; 3003 int freeglob = 0; 3004 glob_t gl; 3005 3006 if (strpbrk(whichf, "~{[*?") != NULL) { 3007 int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_TILDE; 3008 3009 memset(&gl, 0, sizeof(gl)); 3010 gl.gl_matchc = MAXGLOBARGS; 3011 flags |= GLOB_LIMIT; 3012 freeglob = 1; 3013 if (glob(whichf, flags, 0, &gl)) { 3014 reply(550, "not found"); 3015 goto out; 3016 } else if (gl.gl_pathc == 0) { 3017 errno = ENOENT; 3018 perror_reply(550, whichf); 3019 goto out; 3020 } 3021 dirlist = gl.gl_pathv; 3022 } else { 3023 onefile[0] = whichf; 3024 dirlist = onefile; 3025 simple = 1; 3026 } 3027 3028 while ((dirname = *dirlist++)) { 3029 if (stat(dirname, &st) < 0) { 3030 /* 3031 * If user typed "ls -l", etc, and the client 3032 * used NLST, do what the user meant. 3033 */ 3034 if (dirname[0] == '-' && *dirlist == NULL && 3035 transflag == 0) { 3036 retrieve(_PATH_LS " %s", dirname); 3037 goto out; 3038 } 3039 perror_reply(550, whichf); 3040 if (dout != NULL) { 3041 (void) fclose(dout); 3042 transflag = 0; 3043 data = -1; 3044 pdata = -1; 3045 } 3046 goto out; 3047 } 3048 3049 if (S_ISREG(st.st_mode)) { 3050 if (dout == NULL) { 3051 dout = dataconn("file list", -1, "w"); 3052 if (dout == NULL) 3053 goto out; 3054 transflag++; 3055 } 3056 fprintf(dout, "%s%s\n", dirname, 3057 type == TYPE_A ? "\r" : ""); 3058 byte_count += strlen(dirname) + 1; 3059 continue; 3060 } else if (!S_ISDIR(st.st_mode)) 3061 continue; 3062 3063 if ((dirp = opendir(dirname)) == NULL) 3064 continue; 3065 3066 while ((dir = readdir(dirp)) != NULL) { 3067 char nbuf[MAXPATHLEN]; 3068 3069 if (recvurg) { 3070 myoob(); 3071 recvurg = 0; 3072 transflag = 0; 3073 goto out; 3074 } 3075 3076 if (dir->d_name[0] == '.' && dir->d_namlen == 1) 3077 continue; 3078 if (dir->d_name[0] == '.' && dir->d_name[1] == '.' && 3079 dir->d_namlen == 2) 3080 continue; 3081 3082 snprintf(nbuf, sizeof(nbuf), 3083 "%s/%s", dirname, dir->d_name); 3084 3085 /* 3086 * We have to do a stat to insure it's 3087 * not a directory or special file. 3088 */ 3089 if (simple || (stat(nbuf, &st) == 0 && 3090 S_ISREG(st.st_mode))) { 3091 if (dout == NULL) { 3092 dout = dataconn("file list", -1, "w"); 3093 if (dout == NULL) 3094 goto out; 3095 transflag++; 3096 } 3097 if (nbuf[0] == '.' && nbuf[1] == '/') 3098 fprintf(dout, "%s%s\n", &nbuf[2], 3099 type == TYPE_A ? "\r" : ""); 3100 else 3101 fprintf(dout, "%s%s\n", nbuf, 3102 type == TYPE_A ? "\r" : ""); 3103 byte_count += strlen(nbuf) + 1; 3104 } 3105 } 3106 (void) closedir(dirp); 3107 } 3108 3109 if (dout == NULL) 3110 reply(550, "No files found."); 3111 else if (ferror(dout) != 0) 3112 perror_reply(550, "Data connection"); 3113 else 3114 reply(226, "Transfer complete."); 3115 3116 transflag = 0; 3117 if (dout != NULL) 3118 (void) fclose(dout); 3119 data = -1; 3120 pdata = -1; 3121out: 3122 if (freeglob) { 3123 freeglob = 0; 3124 globfree(&gl); 3125 } 3126} 3127 3128void 3129reapchild(int signo) 3130{ 3131 while (wait3(NULL, WNOHANG, NULL) > 0); 3132} 3133 3134#ifdef OLD_SETPROCTITLE 3135/* 3136 * Clobber argv so ps will show what we're doing. (Stolen from sendmail.) 3137 * Warning, since this is usually started from inetd.conf, it often doesn't 3138 * have much of an environment or arglist to overwrite. 3139 */ 3140void 3141setproctitle(const char *fmt, ...) 3142{ 3143 int i; 3144 va_list ap; 3145 char *p, *bp, ch; 3146 char buf[LINE_MAX]; 3147 3148 va_start(ap, fmt); 3149 (void)vsnprintf(buf, sizeof(buf), fmt, ap); 3150 3151 /* make ps print our process name */ 3152 p = Argv[0]; 3153 *p++ = '-'; 3154 3155 i = strlen(buf); 3156 if (i > LastArgv - p - 2) { 3157 i = LastArgv - p - 2; 3158 buf[i] = '\0'; 3159 } 3160 bp = buf; 3161 while (ch = *bp++) 3162 if (ch != '\n' && ch != '\r') 3163 *p++ = ch; 3164 while (p < LastArgv) 3165 *p++ = ' '; 3166} 3167#endif /* OLD_SETPROCTITLE */ 3168 3169static void 3170logxfer(char *name, off_t size, time_t start) 3171{ 3172 char buf[MAXPATHLEN + 1024]; 3173 char path[MAXPATHLEN + 1]; 3174 time_t now; 3175 3176 if (statfd >= 0) { 3177 time(&now); 3178 if (realpath(name, path) == NULL) { 3179 syslog(LOG_NOTICE, "realpath failed on %s: %m", path); 3180 return; 3181 } 3182 snprintf(buf, sizeof(buf), "%.20s!%s!%s!%s!%jd!%ld\n", 3183 ctime(&now)+4, ident, remotehost, 3184 path, (intmax_t)size, 3185 (long)(now - start + (now == start))); 3186 write(statfd, buf, strlen(buf)); 3187 } 3188} 3189 3190static char * 3191doublequote(char *s) 3192{ 3193 int n; 3194 char *p, *s2; 3195 3196 for (p = s, n = 0; *p; p++) 3197 if (*p == '"') 3198 n++; 3199 3200 if ((s2 = malloc(p - s + n + 1)) == NULL) 3201 return (NULL); 3202 3203 for (p = s2; *s; s++, p++) { 3204 if ((*p = *s) == '"') 3205 *(++p) = '"'; 3206 } 3207 *p = '\0'; 3208 3209 return (s2); 3210} 3211 3212/* setup server socket for specified address family */ 3213/* if af is PF_UNSPEC more than one socket may be returned */ 3214/* the returned list is dynamically allocated, so caller needs to free it */ 3215static int * 3216socksetup(int af, char *bindname, const char *bindport) 3217{ 3218 struct addrinfo hints, *res, *r; 3219 int error, maxs, *s, *socks; 3220 const int on = 1; 3221 3222 memset(&hints, 0, sizeof(hints)); 3223 hints.ai_flags = AI_PASSIVE; 3224 hints.ai_family = af; 3225 hints.ai_socktype = SOCK_STREAM; 3226 error = getaddrinfo(bindname, bindport, &hints, &res); 3227 if (error) { 3228 syslog(LOG_ERR, "%s", gai_strerror(error)); 3229 if (error == EAI_SYSTEM) 3230 syslog(LOG_ERR, "%s", strerror(errno)); 3231 return NULL; 3232 } 3233 3234 /* Count max number of sockets we may open */ 3235 for (maxs = 0, r = res; r; r = r->ai_next, maxs++) 3236 ; 3237 socks = malloc((maxs + 1) * sizeof(int)); 3238 if (!socks) { 3239 freeaddrinfo(res); 3240 syslog(LOG_ERR, "couldn't allocate memory for sockets"); 3241 return NULL; 3242 } 3243 3244 *socks = 0; /* num of sockets counter at start of array */ 3245 s = socks + 1; 3246 for (r = res; r; r = r->ai_next) { 3247 *s = socket(r->ai_family, r->ai_socktype, r->ai_protocol); 3248 if (*s < 0) { 3249 syslog(LOG_DEBUG, "control socket: %m"); 3250 continue; 3251 } 3252 if (setsockopt(*s, SOL_SOCKET, SO_REUSEADDR, 3253 &on, sizeof(on)) < 0) 3254 syslog(LOG_WARNING, 3255 "control setsockopt (SO_REUSEADDR): %m"); 3256 if (r->ai_family == AF_INET6) { 3257 if (setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY, 3258 &on, sizeof(on)) < 0) 3259 syslog(LOG_WARNING, 3260 "control setsockopt (IPV6_V6ONLY): %m"); 3261 } 3262 if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) { 3263 syslog(LOG_DEBUG, "control bind: %m"); 3264 close(*s); 3265 continue; 3266 } 3267 (*socks)++; 3268 s++; 3269 } 3270 3271 if (res) 3272 freeaddrinfo(res); 3273 3274 if (*socks == 0) { 3275 syslog(LOG_ERR, "control socket: Couldn't bind to any socket"); 3276 free(socks); 3277 return NULL; 3278 } 3279 return(socks); 3280} 3281