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