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