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