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