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