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