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