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