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