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