1 /* 2 * Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#) Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994 The Regents of the University of California. All rights reserved. 34 * @(#)ftpd.c 8.4 (Berkeley) 4/16/94 35 */ 36 37 #if 0 38 static const char rcsid[] = 39 "$FreeBSD: src/libexec/ftpd/ftpd.c,v 1.62.2.48 2003/02/14 12:42:42 yar Exp $"; 40 "$DragonFly: src/libexec/ftpd/ftpd.c,v 1.6 2005/08/08 16:17:04 joerg Exp $"; 41 #endif /* not lint */ 42 43 /* 44 * FTP server. 45 */ 46 #include <sys/param.h> 47 #include <sys/ioctl.h> 48 #include <sys/mman.h> 49 #include <sys/socket.h> 50 #include <sys/stat.h> 51 #include <sys/time.h> 52 #include <sys/wait.h> 53 54 #include <netinet/in.h> 55 #include <netinet/in_systm.h> 56 #include <netinet/ip.h> 57 #include <netinet/tcp.h> 58 59 #define FTP_NAMES 60 #include <arpa/ftp.h> 61 #include <arpa/inet.h> 62 #include <arpa/telnet.h> 63 64 #include <ctype.h> 65 #include <dirent.h> 66 #include <err.h> 67 #include <errno.h> 68 #include <fcntl.h> 69 #include <glob.h> 70 #include <limits.h> 71 #include <netdb.h> 72 #include <pwd.h> 73 #include <grp.h> 74 #include <signal.h> 75 #include <stdio.h> 76 #include <stdlib.h> 77 #include <string.h> 78 #include <syslog.h> 79 #include <time.h> 80 #include <unistd.h> 81 #include <libutil.h> 82 #ifdef LOGIN_CAP 83 #include <login_cap.h> 84 #endif 85 86 #ifdef SKEY 87 #include <skey.h> 88 #endif 89 90 #if !defined(NOPAM) 91 #include <security/pam_appl.h> 92 #endif 93 94 #include "pathnames.h" 95 #include "extern.h" 96 97 #if __STDC__ 98 #include <stdarg.h> 99 #else 100 #include <varargs.h> 101 #endif 102 103 static char version[] = "Version 6.00LS"; 104 #undef main 105 106 extern off_t restart_point; 107 extern char cbuf[]; 108 109 union sockunion server_addr; 110 union sockunion ctrl_addr; 111 union sockunion data_source; 112 union sockunion data_dest; 113 union sockunion his_addr; 114 union sockunion pasv_addr; 115 116 int daemon_mode; 117 int data; 118 int dataport; 119 int hostinfo = 1; /* print host-specific info in messages */ 120 int logged_in; 121 struct passwd *pw; 122 char *homedir; 123 int ftpdebug; 124 int timeout = 900; /* timeout after 15 minutes of inactivity */ 125 int maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */ 126 int logging; 127 int restricted_data_ports = 1; 128 int paranoid = 1; /* be extra careful about security */ 129 int anon_only = 0; /* Only anonymous ftp allowed */ 130 int guest; 131 int dochroot; 132 int dowtmp = 1; 133 int stats; 134 int statfd = -1; 135 int type; 136 int form; 137 int stru; /* avoid C keyword */ 138 int mode; 139 int usedefault = 1; /* for data transfers */ 140 int pdata = -1; /* for passive mode */ 141 int readonly=0; /* Server is in readonly mode. */ 142 int noepsv=0; /* EPSV command is disabled. */ 143 int noretr=0; /* RETR command is disabled. */ 144 int noguestretr=0; /* RETR command is disabled for anon users. */ 145 int noguestmkd=0; /* MKD command is disabled for anon users. */ 146 int noguestmod=1; /* anon users may not modify existing files. */ 147 148 static volatile sig_atomic_t recvurg; 149 sig_atomic_t transflag; 150 off_t file_size; 151 off_t byte_count; 152 #if !defined(CMASK) || CMASK == 0 153 #undef CMASK 154 #define CMASK 027 155 #endif 156 int defumask = CMASK; /* default umask value */ 157 char tmpline[7]; 158 char *hostname; 159 int epsvall = 0; 160 161 #ifdef VIRTUAL_HOSTING 162 char *ftpuser; 163 164 static struct ftphost { 165 struct ftphost *next; 166 struct addrinfo *hostinfo; 167 char *hostname; 168 char *anonuser; 169 char *statfile; 170 char *welcome; 171 char *loginmsg; 172 } *thishost, *firsthost; 173 174 #endif 175 char remotehost[MAXHOSTNAMELEN]; 176 char *ident = NULL; 177 178 static char ttyline[20]; 179 char *tty = ttyline; /* for klogin */ 180 181 #if !defined(NOPAM) 182 static int auth_pam (struct passwd**, const char*); 183 #endif 184 185 char *pid_file = NULL; 186 187 /* 188 * Limit number of pathnames that glob can return. 189 * A limit of 0 indicates the number of pathnames is unlimited. 190 */ 191 #define MAXGLOBARGS 16384 192 # 193 194 /* 195 * Timeout intervals for retrying connections 196 * to hosts that don't accept PORT cmds. This 197 * is a kludge, but given the problems with TCP... 198 */ 199 #define SWAITMAX 90 /* wait at most 90 seconds */ 200 #define SWAITINT 5 /* interval between retries */ 201 202 int swaitmax = SWAITMAX; 203 int swaitint = SWAITINT; 204 205 #ifdef SETPROCTITLE 206 #ifdef OLD_SETPROCTITLE 207 char **Argv = NULL; /* pointer to argument vector */ 208 char *LastArgv = NULL; /* end of argv */ 209 #endif /* OLD_SETPROCTITLE */ 210 char proctitle[LINE_MAX]; /* initial part of title */ 211 #endif /* SETPROCTITLE */ 212 213 #ifdef SKEY 214 int pwok = 0; 215 #endif 216 217 #define LOGCMD(cmd, file) \ 218 if (logging > 1) \ 219 syslog(LOG_INFO,"%s %s%s", cmd, \ 220 *(file) == '/' ? "" : curdir(), file); 221 #define LOGCMD2(cmd, file1, file2) \ 222 if (logging > 1) \ 223 syslog(LOG_INFO,"%s %s%s %s%s", cmd, \ 224 *(file1) == '/' ? "" : curdir(), file1, \ 225 *(file2) == '/' ? "" : curdir(), file2); 226 #define LOGBYTES(cmd, file, cnt) \ 227 if (logging > 1) { \ 228 if (cnt == (off_t)-1) \ 229 syslog(LOG_INFO,"%s %s%s", cmd, \ 230 *(file) == '/' ? "" : curdir(), file); \ 231 else \ 232 syslog(LOG_INFO, "%s %s%s = %qd bytes", \ 233 cmd, (*(file) == '/') ? "" : curdir(), file, cnt); \ 234 } 235 236 #ifdef VIRTUAL_HOSTING 237 static void inithosts (void); 238 static void selecthost (union sockunion *); 239 #endif 240 static void ack (char *); 241 static void sigurg (int); 242 static void myoob (void); 243 static int checkuser (char *, char *, int, char **); 244 static FILE *dataconn (char *, off_t, char *); 245 static void dolog (struct sockaddr *); 246 static char *curdir (void); 247 static void end_login (void); 248 static FILE *getdatasock (char *); 249 static int guniquefd (char *, char **); 250 static void lostconn (int); 251 static void sigquit (int); 252 static int receive_data (FILE *, FILE *); 253 static int send_data (FILE *, FILE *, off_t, off_t, int); 254 static struct passwd * 255 sgetpwnam (char *); 256 static char *sgetsave (char *); 257 static void reapchild (int); 258 static void logxfer (char *, off_t, time_t); 259 static char *doublequote (char *); 260 261 static char * 262 curdir() 263 { 264 static char path[MAXPATHLEN+1+1]; /* path + '/' + '\0' */ 265 266 if (getcwd(path, sizeof(path)-2) == NULL) 267 return (""); 268 if (path[1] != '\0') /* special case for root dir. */ 269 strcat(path, "/"); 270 /* For guest account, skip / since it's chrooted */ 271 return (guest ? path+1 : path); 272 } 273 274 int 275 main(argc, argv, envp) 276 int argc; 277 char *argv[]; 278 char **envp; 279 { 280 int addrlen, ch, on = 1, tos; 281 char *cp, line[LINE_MAX]; 282 FILE *fd; 283 int error; 284 char *bindname = NULL; 285 const char *bindport = "ftp"; 286 int family = AF_UNSPEC; 287 int enable_v4 = 0; 288 struct sigaction sa; 289 290 tzset(); /* in case no timezone database in ~ftp */ 291 sigemptyset(&sa.sa_mask); 292 sa.sa_flags = SA_RESTART; 293 294 #ifdef OLD_SETPROCTITLE 295 /* 296 * Save start and extent of argv for setproctitle. 297 */ 298 Argv = argv; 299 while (*envp) 300 envp++; 301 LastArgv = envp[-1] + strlen(envp[-1]); 302 #endif /* OLD_SETPROCTITLE */ 303 304 305 while ((ch = getopt(argc, argv, 306 "46a:AdDEhlmMoOp:P:rRSt:T:u:UvW")) != -1) { 307 switch (ch) { 308 case '4': 309 enable_v4 = 1; 310 if (family == AF_UNSPEC) 311 family = AF_INET; 312 break; 313 314 case '6': 315 family = AF_INET6; 316 break; 317 318 case 'a': 319 bindname = optarg; 320 break; 321 322 case 'A': 323 anon_only = 1; 324 break; 325 326 case 'd': 327 ftpdebug++; 328 break; 329 330 case 'D': 331 daemon_mode++; 332 break; 333 334 case 'E': 335 noepsv = 1; 336 break; 337 338 case 'h': 339 hostinfo = 0; 340 break; 341 342 case 'l': 343 logging++; /* > 1 == extra logging */ 344 break; 345 346 case 'm': 347 noguestmod = 0; 348 break; 349 350 case 'M': 351 noguestmkd = 1; 352 break; 353 354 case 'o': 355 noretr = 1; 356 break; 357 358 case 'O': 359 noguestretr = 1; 360 break; 361 362 case 'p': 363 pid_file = optarg; 364 break; 365 366 case 'P': 367 bindport = optarg; 368 break; 369 370 case 'r': 371 readonly = 1; 372 break; 373 374 case 'R': 375 paranoid = 0; 376 break; 377 378 case 'S': 379 stats++; 380 break; 381 382 case 't': 383 timeout = atoi(optarg); 384 if (maxtimeout < timeout) 385 maxtimeout = timeout; 386 break; 387 388 case 'T': 389 maxtimeout = atoi(optarg); 390 if (timeout > maxtimeout) 391 timeout = maxtimeout; 392 break; 393 394 case 'u': 395 { 396 long val = 0; 397 398 val = strtol(optarg, &optarg, 8); 399 if (*optarg != '\0' || val < 0) 400 warnx("bad value for -u"); 401 else 402 defumask = val; 403 break; 404 } 405 case 'U': 406 restricted_data_ports = 0; 407 break; 408 409 case 'v': 410 ftpdebug++; 411 break; 412 413 case 'W': 414 dowtmp = 0; 415 break; 416 417 default: 418 warnx("unknown flag -%c ignored", optopt); 419 break; 420 } 421 } 422 423 #ifdef VIRTUAL_HOSTING 424 inithosts(); 425 #endif 426 (void) freopen(_PATH_DEVNULL, "w", stderr); 427 428 /* 429 * LOG_NDELAY sets up the logging connection immediately, 430 * necessary for anonymous ftp's that chroot and can't do it later. 431 */ 432 openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP); 433 434 if (daemon_mode) { 435 int ctl_sock, fd; 436 struct addrinfo hints, *res; 437 438 /* 439 * Detach from parent. 440 */ 441 if (daemon(1, 1) < 0) { 442 syslog(LOG_ERR, "failed to become a daemon"); 443 exit(1); 444 } 445 sa.sa_handler = reapchild; 446 (void)sigaction(SIGCHLD, &sa, NULL); 447 /* init bind_sa */ 448 memset(&hints, 0, sizeof(hints)); 449 450 hints.ai_family = family == AF_UNSPEC ? AF_INET : family; 451 hints.ai_socktype = SOCK_STREAM; 452 hints.ai_protocol = 0; 453 hints.ai_flags = AI_PASSIVE; 454 error = getaddrinfo(bindname, bindport, &hints, &res); 455 if (error) { 456 if (family == AF_UNSPEC) { 457 hints.ai_family = AF_UNSPEC; 458 error = getaddrinfo(bindname, bindport, &hints, 459 &res); 460 } 461 } 462 if (error) { 463 syslog(LOG_ERR, "%s", gai_strerror(error)); 464 if (error == EAI_SYSTEM) 465 syslog(LOG_ERR, "%s", strerror(errno)); 466 exit(1); 467 } 468 if (res->ai_addr == NULL) { 469 syslog(LOG_ERR, "-a %s: getaddrinfo failed", hostname); 470 exit(1); 471 } else 472 family = res->ai_addr->sa_family; 473 /* 474 * Open a socket, bind it to the FTP port, and start 475 * listening. 476 */ 477 ctl_sock = socket(family, SOCK_STREAM, 0); 478 if (ctl_sock < 0) { 479 syslog(LOG_ERR, "control socket: %m"); 480 exit(1); 481 } 482 if (setsockopt(ctl_sock, SOL_SOCKET, SO_REUSEADDR, 483 &on, sizeof(on)) < 0) 484 syslog(LOG_WARNING, 485 "control setsockopt (SO_REUSEADDR): %m"); 486 if (family == AF_INET6 && enable_v4 == 0) { 487 if (setsockopt(ctl_sock, IPPROTO_IPV6, IPV6_V6ONLY, 488 &on, sizeof (on)) < 0) 489 syslog(LOG_WARNING, 490 "control setsockopt (IPV6_V6ONLY): %m"); 491 } 492 memcpy(&server_addr, res->ai_addr, res->ai_addr->sa_len); 493 if (bind(ctl_sock, (struct sockaddr *)&server_addr, 494 server_addr.su_len) < 0) { 495 syslog(LOG_ERR, "control bind: %m"); 496 exit(1); 497 } 498 if (listen(ctl_sock, 32) < 0) { 499 syslog(LOG_ERR, "control listen: %m"); 500 exit(1); 501 } 502 /* 503 * Atomically write process ID 504 */ 505 if (pid_file) 506 { 507 int fd; 508 char buf[20]; 509 510 fd = open(pid_file, O_CREAT | O_WRONLY | O_TRUNC 511 | O_NONBLOCK | O_EXLOCK, 0644); 512 if (fd < 0) { 513 if (errno == EAGAIN) 514 errx(1, "%s: file locked", pid_file); 515 else 516 err(1, "%s", pid_file); 517 } 518 snprintf(buf, sizeof(buf), 519 "%lu\n", (unsigned long) getpid()); 520 if (write(fd, buf, strlen(buf)) < 0) 521 err(1, "%s: write", pid_file); 522 /* Leave the pid file open and locked */ 523 } 524 /* 525 * Loop forever accepting connection requests and forking off 526 * children to handle them. 527 */ 528 while (1) { 529 addrlen = server_addr.su_len; 530 fd = accept(ctl_sock, (struct sockaddr *)&his_addr, &addrlen); 531 532 if (fd >= 0) { 533 if (fork() == 0) { 534 /* child */ 535 (void) dup2(fd, 0); 536 (void) dup2(fd, 1); 537 close(ctl_sock); 538 break; 539 } 540 close(fd); 541 } 542 } 543 } else { 544 addrlen = sizeof(his_addr); 545 if (getpeername(0, (struct sockaddr *)&his_addr, &addrlen) < 0) { 546 syslog(LOG_ERR, "getpeername (%s): %m",argv[0]); 547 exit(1); 548 } 549 } 550 551 sa.sa_handler = SIG_DFL; 552 (void)sigaction(SIGCHLD, &sa, NULL); 553 554 sa.sa_handler = sigurg; 555 sa.sa_flags = 0; /* don't restart syscalls for SIGURG */ 556 (void)sigaction(SIGURG, &sa, NULL); 557 558 sigfillset(&sa.sa_mask); /* block all signals in handler */ 559 sa.sa_flags = SA_RESTART; 560 sa.sa_handler = sigquit; 561 (void)sigaction(SIGHUP, &sa, NULL); 562 (void)sigaction(SIGINT, &sa, NULL); 563 (void)sigaction(SIGQUIT, &sa, NULL); 564 (void)sigaction(SIGTERM, &sa, NULL); 565 566 sa.sa_handler = lostconn; 567 (void)sigaction(SIGPIPE, &sa, NULL); 568 569 addrlen = sizeof(ctrl_addr); 570 if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) { 571 syslog(LOG_ERR, "getsockname (%s): %m",argv[0]); 572 exit(1); 573 } 574 dataport = ntohs(ctrl_addr.su_port) - 1; /* as per RFC 959 */ 575 #ifdef VIRTUAL_HOSTING 576 /* select our identity from virtual host table */ 577 selecthost(&ctrl_addr); 578 #endif 579 #ifdef IP_TOS 580 if (ctrl_addr.su_family == AF_INET) 581 { 582 tos = IPTOS_LOWDELAY; 583 if (setsockopt(0, IPPROTO_IP, IP_TOS, &tos, sizeof(int)) < 0) 584 syslog(LOG_WARNING, "control setsockopt (IP_TOS): %m"); 585 } 586 #endif 587 /* 588 * Disable Nagle on the control channel so that we don't have to wait 589 * for peer's ACK before issuing our next reply. 590 */ 591 if (setsockopt(0, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) 592 syslog(LOG_WARNING, "control setsockopt (TCP_NODELAY): %m"); 593 594 data_source.su_port = htons(ntohs(ctrl_addr.su_port) - 1); 595 596 /* set this here so klogin can use it... */ 597 (void)snprintf(ttyline, sizeof(ttyline), "ftp%d", getpid()); 598 599 /* Try to handle urgent data inline */ 600 #ifdef SO_OOBINLINE 601 if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)) < 0) 602 syslog(LOG_WARNING, "control setsockopt (SO_OOBINLINE): %m"); 603 #endif 604 605 #ifdef F_SETOWN 606 if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1) 607 syslog(LOG_ERR, "fcntl F_SETOWN: %m"); 608 #endif 609 dolog((struct sockaddr *)&his_addr); 610 /* 611 * Set up default state 612 */ 613 data = -1; 614 type = TYPE_A; 615 form = FORM_N; 616 stru = STRU_F; 617 mode = MODE_S; 618 tmpline[0] = '\0'; 619 620 /* If logins are disabled, print out the message. */ 621 if ((fd = fopen(_PATH_NOLOGIN,"r")) != NULL) { 622 while (fgets(line, sizeof(line), fd) != NULL) { 623 if ((cp = strchr(line, '\n')) != NULL) 624 *cp = '\0'; 625 lreply(530, "%s", line); 626 } 627 (void) fflush(stdout); 628 (void) fclose(fd); 629 reply(530, "System not available."); 630 exit(0); 631 } 632 #ifdef VIRTUAL_HOSTING 633 if ((fd = fopen(thishost->welcome, "r")) != NULL) { 634 #else 635 if ((fd = fopen(_PATH_FTPWELCOME, "r")) != NULL) { 636 #endif 637 while (fgets(line, sizeof(line), fd) != NULL) { 638 if ((cp = strchr(line, '\n')) != NULL) 639 *cp = '\0'; 640 lreply(220, "%s", line); 641 } 642 (void) fflush(stdout); 643 (void) fclose(fd); 644 /* reply(220,) must follow */ 645 } 646 #ifndef VIRTUAL_HOSTING 647 if ((hostname = malloc(MAXHOSTNAMELEN)) == NULL) 648 fatalerror("Ran out of memory."); 649 (void) gethostname(hostname, MAXHOSTNAMELEN - 1); 650 hostname[MAXHOSTNAMELEN - 1] = '\0'; 651 #endif 652 if (hostinfo) 653 reply(220, "%s FTP server (%s) ready.", hostname, version); 654 else 655 reply(220, "FTP server ready."); 656 for (;;) 657 (void) yyparse(); 658 /* NOTREACHED */ 659 } 660 661 static void 662 lostconn(signo) 663 int signo; 664 { 665 666 if (ftpdebug) 667 syslog(LOG_DEBUG, "lost connection"); 668 dologout(1); 669 } 670 671 static void 672 sigquit(signo) 673 int signo; 674 { 675 676 syslog(LOG_ERR, "got signal %d", signo); 677 dologout(1); 678 } 679 680 #ifdef VIRTUAL_HOSTING 681 /* 682 * read in virtual host tables (if they exist) 683 */ 684 685 static void 686 inithosts() 687 { 688 int insert; 689 size_t len; 690 FILE *fp; 691 char *cp, *mp, *line; 692 char *hostname; 693 char *vhost, *anonuser, *statfile, *welcome, *loginmsg; 694 struct ftphost *hrp, *lhrp; 695 struct addrinfo hints, *res, *ai; 696 697 /* 698 * Fill in the default host information 699 */ 700 if ((hostname = malloc(MAXHOSTNAMELEN)) == NULL) 701 fatalerror("Ran out of memory."); 702 if (gethostname(hostname, MAXHOSTNAMELEN) < 0) 703 hostname[0] = '\0'; 704 hostname[MAXHOSTNAMELEN - 1] = '\0'; 705 if ((hrp = malloc(sizeof(struct ftphost))) == NULL) 706 fatalerror("Ran out of memory."); 707 hrp->hostname = hostname; 708 hrp->hostinfo = NULL; 709 710 memset(&hints, 0, sizeof(hints)); 711 hints.ai_flags = AI_CANONNAME; 712 hints.ai_family = AF_UNSPEC; 713 if (getaddrinfo(hrp->hostname, NULL, &hints, &res) == 0) 714 hrp->hostinfo = res; 715 hrp->statfile = _PATH_FTPDSTATFILE; 716 hrp->welcome = _PATH_FTPWELCOME; 717 hrp->loginmsg = _PATH_FTPLOGINMESG; 718 hrp->anonuser = "ftp"; 719 hrp->next = NULL; 720 thishost = firsthost = lhrp = hrp; 721 if ((fp = fopen(_PATH_FTPHOSTS, "r")) != NULL) { 722 int addrsize, gothost; 723 void *addr; 724 struct hostent *hp; 725 726 while ((line = fgetln(fp, &len)) != NULL) { 727 int i, hp_error; 728 729 /* skip comments */ 730 if (line[0] == '#') 731 continue; 732 if (line[len - 1] == '\n') { 733 line[len - 1] = '\0'; 734 mp = NULL; 735 } else { 736 if ((mp = malloc(len + 1)) == NULL) 737 fatalerror("Ran out of memory."); 738 memcpy(mp, line, len); 739 mp[len] = '\0'; 740 line = mp; 741 } 742 cp = strtok(line, " \t"); 743 /* skip empty lines */ 744 if (cp == NULL) 745 goto nextline; 746 vhost = cp; 747 748 /* set defaults */ 749 anonuser = "ftp"; 750 statfile = _PATH_FTPDSTATFILE; 751 welcome = _PATH_FTPWELCOME; 752 loginmsg = _PATH_FTPLOGINMESG; 753 754 /* 755 * Preparse the line so we can use its info 756 * for all the addresses associated with 757 * the virtual host name. 758 * Field 0, the virtual host name, is special: 759 * it's already parsed off and will be strdup'ed 760 * later, after we know its canonical form. 761 */ 762 for (i = 1; i < 5 && (cp = strtok(NULL, " \t")); i++) 763 if (*cp != '-' && (cp = strdup(cp))) 764 switch (i) { 765 case 1: /* anon user permissions */ 766 anonuser = cp; 767 break; 768 case 2: /* statistics file */ 769 statfile = cp; 770 break; 771 case 3: /* welcome message */ 772 welcome = cp; 773 break; 774 case 4: /* login message */ 775 loginmsg = cp; 776 break; 777 default: /* programming error */ 778 abort(); 779 /* NOTREACHED */ 780 } 781 782 hints.ai_flags = 0; 783 hints.ai_family = AF_UNSPEC; 784 hints.ai_flags = AI_PASSIVE; 785 if (getaddrinfo(vhost, NULL, &hints, &res) != 0) 786 goto nextline; 787 for (ai = res; ai != NULL && ai->ai_addr != NULL; 788 ai = ai->ai_next) { 789 790 gothost = 0; 791 for (hrp = firsthost; hrp != NULL; hrp = hrp->next) { 792 struct addrinfo *hi; 793 794 for (hi = hrp->hostinfo; hi != NULL; 795 hi = hi->ai_next) 796 if (hi->ai_addrlen == ai->ai_addrlen && 797 memcmp(hi->ai_addr, 798 ai->ai_addr, 799 ai->ai_addr->sa_len) == 0) { 800 gothost++; 801 break; 802 } 803 if (gothost) 804 break; 805 } 806 if (hrp == NULL) { 807 if ((hrp = malloc(sizeof(struct ftphost))) == NULL) 808 goto nextline; 809 hrp->hostname = NULL; 810 insert = 1; 811 } else { 812 if (hrp->hostinfo && hrp->hostinfo != res) 813 freeaddrinfo(hrp->hostinfo); 814 insert = 0; /* host already in the chain */ 815 } 816 hrp->hostinfo = res; 817 818 /* 819 * determine hostname to use. 820 * force defined name if there is a valid alias 821 * otherwise fallback to primary hostname 822 */ 823 /* XXX: getaddrinfo() can't do alias check */ 824 switch(hrp->hostinfo->ai_family) { 825 case AF_INET: 826 addr = &((struct sockaddr_in *)hrp->hostinfo->ai_addr)->sin_addr; 827 addrsize = sizeof(struct in_addr); 828 break; 829 case AF_INET6: 830 addr = &((struct sockaddr_in6 *)hrp->hostinfo->ai_addr)->sin6_addr; 831 addrsize = sizeof(struct in6_addr); 832 break; 833 default: 834 /* should not reach here */ 835 freeaddrinfo(hrp->hostinfo); 836 if (insert) 837 free(hrp); /*not in chain, can free*/ 838 else 839 hrp->hostinfo = NULL; /*mark as blank*/ 840 goto nextline; 841 /* NOTREACHED */ 842 } 843 if ((hp = getipnodebyaddr(addr, addrsize, 844 hrp->hostinfo->ai_family, 845 &hp_error)) != NULL) { 846 if (strcmp(vhost, hp->h_name) != 0) { 847 if (hp->h_aliases == NULL) 848 vhost = hp->h_name; 849 else { 850 i = 0; 851 while (hp->h_aliases[i] && 852 strcmp(vhost, hp->h_aliases[i]) != 0) 853 ++i; 854 if (hp->h_aliases[i] == NULL) 855 vhost = hp->h_name; 856 } 857 } 858 } 859 if (hrp->hostname && 860 strcmp(hrp->hostname, vhost) != 0) { 861 free(hrp->hostname); 862 hrp->hostname = NULL; 863 } 864 if (hrp->hostname == NULL && 865 (hrp->hostname = strdup(vhost)) == NULL) { 866 freeaddrinfo(hrp->hostinfo); 867 hrp->hostinfo = NULL; /* mark as blank */ 868 if (hp) 869 freehostent(hp); 870 goto nextline; 871 } 872 hrp->anonuser = anonuser; 873 hrp->statfile = statfile; 874 hrp->welcome = welcome; 875 hrp->loginmsg = loginmsg; 876 if (insert) { 877 hrp->next = NULL; 878 lhrp->next = hrp; 879 lhrp = hrp; 880 } 881 if (hp) 882 freehostent(hp); 883 } 884 nextline: 885 if (mp) 886 free(mp); 887 } 888 (void) fclose(fp); 889 } 890 } 891 892 static void 893 selecthost(su) 894 union sockunion *su; 895 { 896 struct ftphost *hrp; 897 u_int16_t port; 898 #ifdef INET6 899 struct in6_addr *mapped_in6 = NULL; 900 #endif 901 struct addrinfo *hi; 902 903 #ifdef INET6 904 /* 905 * XXX IPv4 mapped IPv6 addr consideraton, 906 * specified in rfc2373. 907 */ 908 if (su->su_family == AF_INET6 && 909 IN6_IS_ADDR_V4MAPPED(&su->su_sin6.sin6_addr)) 910 mapped_in6 = &su->su_sin6.sin6_addr; 911 #endif 912 913 hrp = thishost = firsthost; /* default */ 914 port = su->su_port; 915 su->su_port = 0; 916 while (hrp != NULL) { 917 for (hi = hrp->hostinfo; hi != NULL; hi = hi->ai_next) { 918 if (memcmp(su, hi->ai_addr, hi->ai_addrlen) == 0) { 919 thishost = hrp; 920 break; 921 } 922 #ifdef INET6 923 /* XXX IPv4 mapped IPv6 addr consideraton */ 924 if (hi->ai_addr->sa_family == AF_INET && mapped_in6 != NULL && 925 (memcmp(&mapped_in6->s6_addr[12], 926 &((struct sockaddr_in *)hi->ai_addr)->sin_addr, 927 sizeof(struct in_addr)) == 0)) { 928 thishost = hrp; 929 break; 930 } 931 #endif 932 } 933 hrp = hrp->next; 934 } 935 su->su_port = port; 936 /* setup static variables as appropriate */ 937 hostname = thishost->hostname; 938 ftpuser = thishost->anonuser; 939 } 940 #endif 941 942 /* 943 * Helper function for sgetpwnam(). 944 */ 945 static char * 946 sgetsave(s) 947 char *s; 948 { 949 char *new = malloc((unsigned) strlen(s) + 1); 950 951 if (new == NULL) { 952 perror_reply(421, "Local resource failure: malloc"); 953 dologout(1); 954 /* NOTREACHED */ 955 } 956 (void) strcpy(new, s); 957 return (new); 958 } 959 960 /* 961 * Save the result of a getpwnam. Used for USER command, since 962 * the data returned must not be clobbered by any other command 963 * (e.g., globbing). 964 */ 965 static struct passwd * 966 sgetpwnam(name) 967 char *name; 968 { 969 static struct passwd save; 970 struct passwd *p; 971 972 if ((p = getpwnam(name)) == NULL) 973 return (p); 974 if (save.pw_name) { 975 free(save.pw_name); 976 free(save.pw_passwd); 977 free(save.pw_gecos); 978 free(save.pw_dir); 979 free(save.pw_shell); 980 } 981 save = *p; 982 save.pw_name = sgetsave(p->pw_name); 983 save.pw_passwd = sgetsave(p->pw_passwd); 984 save.pw_gecos = sgetsave(p->pw_gecos); 985 save.pw_dir = sgetsave(p->pw_dir); 986 save.pw_shell = sgetsave(p->pw_shell); 987 return (&save); 988 } 989 990 static int login_attempts; /* number of failed login attempts */ 991 static int askpasswd; /* had user command, ask for passwd */ 992 static char curname[MAXLOGNAME]; /* current USER name */ 993 994 /* 995 * USER command. 996 * Sets global passwd pointer pw if named account exists and is acceptable; 997 * sets askpasswd if a PASS command is expected. If logged in previously, 998 * need to reset state. If name is "ftp" or "anonymous", the name is not in 999 * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return. 1000 * If account doesn't exist, ask for passwd anyway. Otherwise, check user 1001 * requesting login privileges. Disallow anyone who does not have a standard 1002 * shell as returned by getusershell(). Disallow anyone mentioned in the file 1003 * _PATH_FTPUSERS to allow people such as root and uucp to be avoided. 1004 */ 1005 void 1006 user(name) 1007 char *name; 1008 { 1009 char *cp, *shell; 1010 1011 if (logged_in) { 1012 if (guest) { 1013 reply(530, "Can't change user from guest login."); 1014 return; 1015 } else if (dochroot) { 1016 reply(530, "Can't change user from chroot user."); 1017 return; 1018 } 1019 end_login(); 1020 } 1021 1022 guest = 0; 1023 if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) { 1024 if (checkuser(_PATH_FTPUSERS, "ftp", 0, NULL) || 1025 checkuser(_PATH_FTPUSERS, "anonymous", 0, NULL)) 1026 reply(530, "User %s access denied.", name); 1027 #ifdef VIRTUAL_HOSTING 1028 else if ((pw = sgetpwnam(thishost->anonuser)) != NULL) { 1029 #else 1030 else if ((pw = sgetpwnam("ftp")) != NULL) { 1031 #endif 1032 guest = 1; 1033 askpasswd = 1; 1034 reply(331, 1035 "Guest login ok, send your email address as password."); 1036 } else 1037 reply(530, "User %s unknown.", name); 1038 if (!askpasswd && logging) 1039 syslog(LOG_NOTICE, 1040 "ANONYMOUS FTP LOGIN REFUSED FROM %s", remotehost); 1041 return; 1042 } 1043 if (anon_only != 0) { 1044 reply(530, "Sorry, only anonymous ftp allowed."); 1045 return; 1046 } 1047 1048 if ((pw = sgetpwnam(name))) { 1049 if ((shell = pw->pw_shell) == NULL || *shell == 0) 1050 shell = _PATH_BSHELL; 1051 while ((cp = getusershell()) != NULL) 1052 if (strcmp(cp, shell) == 0) 1053 break; 1054 endusershell(); 1055 1056 if (cp == NULL || checkuser(_PATH_FTPUSERS, name, 1, NULL)) { 1057 reply(530, "User %s access denied.", name); 1058 if (logging) 1059 syslog(LOG_NOTICE, 1060 "FTP LOGIN REFUSED FROM %s, %s", 1061 remotehost, name); 1062 pw = (struct passwd *) NULL; 1063 return; 1064 } 1065 } 1066 if (logging) 1067 strncpy(curname, name, sizeof(curname)-1); 1068 #ifdef SKEY 1069 pwok = skeyaccess(name, NULL, remotehost, remotehost); 1070 reply(331, "%s", skey_challenge(name, pw, pwok)); 1071 #else 1072 reply(331, "Password required for %s.", name); 1073 #endif 1074 askpasswd = 1; 1075 /* 1076 * Delay before reading passwd after first failed 1077 * attempt to slow down passwd-guessing programs. 1078 */ 1079 if (login_attempts) 1080 sleep((unsigned) login_attempts); 1081 } 1082 1083 /* 1084 * Check if a user is in the file "fname", 1085 * return a pointer to a malloc'd string with the rest 1086 * of the matching line in "residue" if not NULL. 1087 */ 1088 static int 1089 checkuser(fname, name, pwset, residue) 1090 char *fname; 1091 char *name; 1092 int pwset; 1093 char **residue; 1094 { 1095 FILE *fd; 1096 int found = 0; 1097 size_t len; 1098 char *line, *mp, *p; 1099 1100 if ((fd = fopen(fname, "r")) != NULL) { 1101 while (!found && (line = fgetln(fd, &len)) != NULL) { 1102 /* skip comments */ 1103 if (line[0] == '#') 1104 continue; 1105 if (line[len - 1] == '\n') { 1106 line[len - 1] = '\0'; 1107 mp = NULL; 1108 } else { 1109 if ((mp = malloc(len + 1)) == NULL) 1110 fatalerror("Ran out of memory."); 1111 memcpy(mp, line, len); 1112 mp[len] = '\0'; 1113 line = mp; 1114 } 1115 /* avoid possible leading and trailing whitespace */ 1116 p = strtok(line, " \t"); 1117 /* skip empty lines */ 1118 if (p == NULL) 1119 goto nextline; 1120 /* 1121 * if first chr is '@', check group membership 1122 */ 1123 if (p[0] == '@') { 1124 int i = 0; 1125 struct group *grp; 1126 1127 if (p[1] == '\0') /* single @ matches anyone */ 1128 found = 1; 1129 else { 1130 if ((grp = getgrnam(p+1)) == NULL) 1131 goto nextline; 1132 /* 1133 * Check user's default group 1134 */ 1135 if (pwset && grp->gr_gid == pw->pw_gid) 1136 found = 1; 1137 /* 1138 * Check supplementary groups 1139 */ 1140 while (!found && grp->gr_mem[i]) 1141 found = strcmp(name, 1142 grp->gr_mem[i++]) 1143 == 0; 1144 } 1145 } 1146 /* 1147 * Otherwise, just check for username match 1148 */ 1149 else 1150 found = strcmp(p, name) == 0; 1151 /* 1152 * Save the rest of line to "residue" if matched 1153 */ 1154 if (found && residue) { 1155 if ((p = strtok(NULL, "")) != NULL) 1156 p += strspn(p, " \t"); 1157 if (p && *p) { 1158 if ((*residue = strdup(p)) == NULL) 1159 fatalerror("Ran out of memory."); 1160 } else 1161 *residue = NULL; 1162 } 1163 nextline: 1164 if (mp) 1165 free(mp); 1166 } 1167 (void) fclose(fd); 1168 } 1169 return (found); 1170 } 1171 1172 /* 1173 * Terminate login as previous user, if any, resetting state; 1174 * used when USER command is given or login fails. 1175 */ 1176 static void 1177 end_login() 1178 { 1179 1180 (void) seteuid((uid_t)0); 1181 if (logged_in && dowtmp) 1182 ftpd_logwtmp(ttyline, "", NULL); 1183 pw = NULL; 1184 #ifdef LOGIN_CAP 1185 setusercontext(NULL, getpwuid(0), (uid_t)0, 1186 LOGIN_SETPRIORITY|LOGIN_SETRESOURCES|LOGIN_SETUMASK); 1187 #endif 1188 logged_in = 0; 1189 guest = 0; 1190 dochroot = 0; 1191 } 1192 1193 #if !defined(NOPAM) 1194 1195 /* 1196 * the following code is stolen from imap-uw PAM authentication module and 1197 * login.c 1198 */ 1199 #define COPY_STRING(s) (s ? strdup(s) : NULL) 1200 1201 struct cred_t { 1202 const char *uname; /* user name */ 1203 const char *pass; /* password */ 1204 }; 1205 typedef struct cred_t cred_t; 1206 1207 static int 1208 auth_conv(int num_msg, const struct pam_message **msg, 1209 struct pam_response **resp, void *appdata) 1210 { 1211 int i; 1212 cred_t *cred = (cred_t *) appdata; 1213 struct pam_response *reply = 1214 malloc(sizeof(struct pam_response) * num_msg); 1215 1216 for (i = 0; i < num_msg; i++) { 1217 switch (msg[i]->msg_style) { 1218 case PAM_PROMPT_ECHO_ON: /* assume want user name */ 1219 reply[i].resp_retcode = PAM_SUCCESS; 1220 reply[i].resp = COPY_STRING(cred->uname); 1221 /* PAM frees resp. */ 1222 break; 1223 case PAM_PROMPT_ECHO_OFF: /* assume want password */ 1224 reply[i].resp_retcode = PAM_SUCCESS; 1225 reply[i].resp = COPY_STRING(cred->pass); 1226 /* PAM frees resp. */ 1227 break; 1228 case PAM_TEXT_INFO: 1229 case PAM_ERROR_MSG: 1230 reply[i].resp_retcode = PAM_SUCCESS; 1231 reply[i].resp = NULL; 1232 break; 1233 default: /* unknown message style */ 1234 free(reply); 1235 return PAM_CONV_ERR; 1236 } 1237 } 1238 1239 *resp = reply; 1240 return PAM_SUCCESS; 1241 } 1242 1243 /* 1244 * Attempt to authenticate the user using PAM. Returns 0 if the user is 1245 * authenticated, or 1 if not authenticated. If some sort of PAM system 1246 * error occurs (e.g., the "/etc/pam.conf" file is missing) then this 1247 * function returns -1. This can be used as an indication that we should 1248 * fall back to a different authentication mechanism. 1249 */ 1250 static int 1251 auth_pam(struct passwd **ppw, const char *pass) 1252 { 1253 pam_handle_t *pamh = NULL; 1254 const char *tmpl_user; 1255 const void *item; 1256 int rval; 1257 int e; 1258 cred_t auth_cred = { (*ppw)->pw_name, pass }; 1259 struct pam_conv conv = { &auth_conv, &auth_cred }; 1260 1261 e = pam_start("ftpd", (*ppw)->pw_name, &conv, &pamh); 1262 if (e != PAM_SUCCESS) { 1263 syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, e)); 1264 return -1; 1265 } 1266 1267 e = pam_set_item(pamh, PAM_RHOST, remotehost); 1268 if (e != PAM_SUCCESS) { 1269 syslog(LOG_ERR, "pam_set_item(PAM_RHOST): %s", 1270 pam_strerror(pamh, e)); 1271 return -1; 1272 } 1273 1274 e = pam_authenticate(pamh, 0); 1275 switch (e) { 1276 case PAM_SUCCESS: 1277 /* 1278 * With PAM we support the concept of a "template" 1279 * user. The user enters a login name which is 1280 * authenticated by PAM, usually via a remote service 1281 * such as RADIUS or TACACS+. If authentication 1282 * succeeds, a different but related "template" name 1283 * is used for setting the credentials, shell, and 1284 * home directory. The name the user enters need only 1285 * exist on the remote authentication server, but the 1286 * template name must be present in the local password 1287 * database. 1288 * 1289 * This is supported by two various mechanisms in the 1290 * individual modules. However, from the application's 1291 * point of view, the template user is always passed 1292 * back as a changed value of the PAM_USER item. 1293 */ 1294 if ((e = pam_get_item(pamh, PAM_USER, &item)) == 1295 PAM_SUCCESS) { 1296 tmpl_user = (const char *) item; 1297 if (strcmp((*ppw)->pw_name, tmpl_user) != 0) 1298 *ppw = getpwnam(tmpl_user); 1299 } else 1300 syslog(LOG_ERR, "Couldn't get PAM_USER: %s", 1301 pam_strerror(pamh, e)); 1302 rval = 0; 1303 break; 1304 1305 case PAM_AUTH_ERR: 1306 case PAM_USER_UNKNOWN: 1307 case PAM_MAXTRIES: 1308 rval = 1; 1309 break; 1310 1311 default: 1312 syslog(LOG_ERR, "auth_pam: %s", pam_strerror(pamh, e)); 1313 rval = -1; 1314 break; 1315 } 1316 1317 if ((e = pam_end(pamh, e)) != PAM_SUCCESS) { 1318 syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e)); 1319 rval = -1; 1320 } 1321 return rval; 1322 } 1323 1324 #endif /* !defined(NOPAM) */ 1325 1326 void 1327 pass(passwd) 1328 char *passwd; 1329 { 1330 int rval; 1331 FILE *fd; 1332 #ifdef LOGIN_CAP 1333 login_cap_t *lc = NULL; 1334 #endif 1335 char *chrootdir; 1336 char *residue = NULL; 1337 1338 if (logged_in || askpasswd == 0) { 1339 reply(503, "Login with USER first."); 1340 return; 1341 } 1342 askpasswd = 0; 1343 if (!guest) { /* "ftp" is only account allowed no password */ 1344 if (pw == NULL) { 1345 rval = 1; /* failure below */ 1346 goto skip; 1347 } 1348 #if !defined(NOPAM) 1349 rval = auth_pam(&pw, passwd); 1350 if (rval >= 0) 1351 goto skip; 1352 #endif 1353 #ifdef SKEY 1354 if (pwok) 1355 rval = strcmp(pw->pw_passwd, 1356 crypt(passwd, pw->pw_passwd)); 1357 if (rval) 1358 rval = strcmp(pw->pw_passwd, 1359 skey_crypt(passwd, pw->pw_passwd, pw, pwok)); 1360 #else 1361 rval = strcmp(pw->pw_passwd, crypt(passwd, pw->pw_passwd)); 1362 #endif 1363 /* The strcmp does not catch null passwords! */ 1364 if (*pw->pw_passwd == '\0' || 1365 (pw->pw_expire && time(NULL) >= pw->pw_expire)) 1366 rval = 1; /* failure */ 1367 skip: 1368 /* 1369 * If rval == 1, the user failed the authentication check 1370 * above. If rval == 0, either PAM or local authentication 1371 * succeeded. 1372 */ 1373 if (rval) { 1374 reply(530, "Login incorrect."); 1375 if (logging) { 1376 syslog(LOG_NOTICE, 1377 "FTP LOGIN FAILED FROM %s", 1378 remotehost); 1379 syslog(LOG_AUTHPRIV | LOG_NOTICE, 1380 "FTP LOGIN FAILED FROM %s, %s", 1381 remotehost, curname); 1382 } 1383 pw = NULL; 1384 if (login_attempts++ >= 5) { 1385 syslog(LOG_NOTICE, 1386 "repeated login failures from %s", 1387 remotehost); 1388 exit(0); 1389 } 1390 return; 1391 } 1392 } 1393 #ifdef SKEY 1394 pwok = 0; 1395 #endif 1396 login_attempts = 0; /* this time successful */ 1397 if (setegid((gid_t)pw->pw_gid) < 0) { 1398 reply(550, "Can't set gid."); 1399 return; 1400 } 1401 /* May be overridden by login.conf */ 1402 (void) umask(defumask); 1403 #ifdef LOGIN_CAP 1404 if ((lc = login_getpwclass(pw)) != NULL) { 1405 char remote_ip[MAXHOSTNAMELEN]; 1406 1407 getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len, 1408 remote_ip, sizeof(remote_ip) - 1, NULL, 0, 1409 NI_NUMERICHOST); 1410 remote_ip[sizeof(remote_ip) - 1] = 0; 1411 if (!auth_hostok(lc, remotehost, remote_ip)) { 1412 syslog(LOG_INFO|LOG_AUTH, 1413 "FTP LOGIN FAILED (HOST) as %s: permission denied.", 1414 pw->pw_name); 1415 reply(530, "Permission denied.\n"); 1416 pw = NULL; 1417 return; 1418 } 1419 if (!auth_timeok(lc, time(NULL))) { 1420 reply(530, "Login not available right now.\n"); 1421 pw = NULL; 1422 return; 1423 } 1424 } 1425 setusercontext(lc, pw, (uid_t)0, 1426 LOGIN_SETLOGIN|LOGIN_SETGROUP|LOGIN_SETPRIORITY| 1427 LOGIN_SETRESOURCES|LOGIN_SETUMASK); 1428 #else 1429 setlogin(pw->pw_name); 1430 (void) initgroups(pw->pw_name, pw->pw_gid); 1431 #endif 1432 1433 /* open wtmp before chroot */ 1434 if (dowtmp) 1435 ftpd_logwtmp(ttyline, pw->pw_name, 1436 (struct sockaddr *)&his_addr); 1437 logged_in = 1; 1438 1439 if (guest && stats && statfd < 0) 1440 #ifdef VIRTUAL_HOSTING 1441 if ((statfd = open(thishost->statfile, O_WRONLY|O_APPEND)) < 0) 1442 #else 1443 if ((statfd = open(_PATH_FTPDSTATFILE, O_WRONLY|O_APPEND)) < 0) 1444 #endif 1445 stats = 0; 1446 1447 dochroot = 1448 checkuser(_PATH_FTPCHROOT, pw->pw_name, 1, &residue) 1449 #ifdef LOGIN_CAP /* Allow login.conf configuration as well */ 1450 || login_getcapbool(lc, "ftp-chroot", 0) 1451 #endif 1452 ; 1453 chrootdir = NULL; 1454 /* 1455 * For a chrooted local user, 1456 * a) see whether ftpchroot(5) specifies a chroot directory, 1457 * b) extract the directory pathname from the line, 1458 * c) expand it to the absolute pathname if necessary. 1459 */ 1460 if (dochroot && residue && 1461 (chrootdir = strtok(residue, " \t")) != NULL && 1462 chrootdir[0] != '/') { 1463 asprintf(&chrootdir, "%s/%s", pw->pw_dir, chrootdir); 1464 if (chrootdir == NULL) 1465 fatalerror("Ran out of memory."); 1466 } 1467 if (guest || dochroot) { 1468 /* 1469 * If no chroot directory set yet, use the login directory. 1470 * Copy it so it can be modified while pw->pw_dir stays intact. 1471 */ 1472 if (chrootdir == NULL && 1473 (chrootdir = strdup(pw->pw_dir)) == NULL) 1474 fatalerror("Ran out of memory."); 1475 /* 1476 * Check for the "/chroot/./home" syntax, 1477 * separate the chroot and home directory pathnames. 1478 */ 1479 if ((homedir = strstr(chrootdir, "/./")) != NULL) { 1480 *(homedir++) = '\0'; /* wipe '/' */ 1481 homedir++; /* skip '.' */ 1482 /* so chrootdir can be freed later */ 1483 if ((homedir = strdup(homedir)) == NULL) 1484 fatalerror("Ran out of memory."); 1485 } else { 1486 /* 1487 * We MUST do a chdir() after the chroot. Otherwise 1488 * the old current directory will be accessible as "." 1489 * outside the new root! 1490 */ 1491 homedir = "/"; 1492 } 1493 /* 1494 * Finally, do chroot() 1495 */ 1496 if (chroot(chrootdir) < 0) { 1497 reply(550, "Can't change root."); 1498 goto bad; 1499 } 1500 } else /* real user w/o chroot */ 1501 homedir = pw->pw_dir; 1502 /* 1503 * Set euid *before* doing chdir() so 1504 * a) the user won't be carried to a directory that he couldn't reach 1505 * on his own due to no permission to upper path components, 1506 * b) NFS mounted homedirs w/restrictive permissions will be accessible 1507 * (uid 0 has no root power over NFS if not mapped explicitly.) 1508 */ 1509 if (seteuid((uid_t)pw->pw_uid) < 0) { 1510 reply(550, "Can't set uid."); 1511 goto bad; 1512 } 1513 if (chdir(homedir) < 0) { 1514 if (guest || dochroot) { 1515 reply(550, "Can't change to base directory."); 1516 goto bad; 1517 } else { 1518 if (chdir("/") < 0) { 1519 reply(550, "Root is inaccessible."); 1520 goto bad; 1521 } 1522 lreply(230, "No directory! Logging in with home=/"); 1523 } 1524 } 1525 1526 /* 1527 * Display a login message, if it exists. 1528 * N.B. reply(230,) must follow the message. 1529 */ 1530 #ifdef VIRTUAL_HOSTING 1531 if ((fd = fopen(thishost->loginmsg, "r")) != NULL) { 1532 #else 1533 if ((fd = fopen(_PATH_FTPLOGINMESG, "r")) != NULL) { 1534 #endif 1535 char *cp, line[LINE_MAX]; 1536 1537 while (fgets(line, sizeof(line), fd) != NULL) { 1538 if ((cp = strchr(line, '\n')) != NULL) 1539 *cp = '\0'; 1540 lreply(230, "%s", line); 1541 } 1542 (void) fflush(stdout); 1543 (void) fclose(fd); 1544 } 1545 if (guest) { 1546 if (ident != NULL) 1547 free(ident); 1548 ident = strdup(passwd); 1549 if (ident == NULL) 1550 fatalerror("Ran out of memory."); 1551 1552 reply(230, "Guest login ok, access restrictions apply."); 1553 #ifdef SETPROCTITLE 1554 #ifdef VIRTUAL_HOSTING 1555 if (thishost != firsthost) 1556 snprintf(proctitle, sizeof(proctitle), 1557 "%s: anonymous(%s)/%s", remotehost, hostname, 1558 passwd); 1559 else 1560 #endif 1561 snprintf(proctitle, sizeof(proctitle), 1562 "%s: anonymous/%s", remotehost, passwd); 1563 setproctitle("%s", proctitle); 1564 #endif /* SETPROCTITLE */ 1565 if (logging) 1566 syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s", 1567 remotehost, passwd); 1568 } else { 1569 if (dochroot) 1570 reply(230, "User %s logged in, " 1571 "access restrictions apply.", pw->pw_name); 1572 else 1573 reply(230, "User %s logged in.", pw->pw_name); 1574 1575 #ifdef SETPROCTITLE 1576 snprintf(proctitle, sizeof(proctitle), 1577 "%s: user/%s", remotehost, pw->pw_name); 1578 setproctitle("%s", proctitle); 1579 #endif /* SETPROCTITLE */ 1580 if (logging) 1581 syslog(LOG_INFO, "FTP LOGIN FROM %s as %s", 1582 remotehost, pw->pw_name); 1583 } 1584 #ifdef LOGIN_CAP 1585 login_close(lc); 1586 #endif 1587 if (chrootdir) 1588 free(chrootdir); 1589 if (residue) 1590 free(residue); 1591 return; 1592 bad: 1593 /* Forget all about it... */ 1594 #ifdef LOGIN_CAP 1595 login_close(lc); 1596 #endif 1597 if (chrootdir) 1598 free(chrootdir); 1599 if (residue) 1600 free(residue); 1601 end_login(); 1602 } 1603 1604 void 1605 retrieve(cmd, name) 1606 char *cmd, *name; 1607 { 1608 FILE *fin, *dout; 1609 struct stat st; 1610 int (*closefunc) (FILE *); 1611 time_t start; 1612 1613 if (cmd == 0) { 1614 fin = fopen(name, "r"), closefunc = fclose; 1615 st.st_size = 0; 1616 } else { 1617 char line[BUFSIZ]; 1618 1619 (void) snprintf(line, sizeof(line), cmd, name), name = line; 1620 fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose; 1621 st.st_size = -1; 1622 st.st_blksize = BUFSIZ; 1623 } 1624 if (fin == NULL) { 1625 if (errno != 0) { 1626 perror_reply(550, name); 1627 if (cmd == 0) { 1628 LOGCMD("get", name); 1629 } 1630 } 1631 return; 1632 } 1633 byte_count = -1; 1634 if (cmd == 0) { 1635 if (fstat(fileno(fin), &st) < 0) { 1636 perror_reply(550, name); 1637 goto done; 1638 } 1639 if (!S_ISREG(st.st_mode)) { 1640 if (guest) { 1641 reply(550, "%s: not a plain file.", name); 1642 goto done; 1643 } 1644 st.st_size = -1; 1645 /* st.st_blksize is set for all descriptor types */ 1646 } 1647 } 1648 if (restart_point) { 1649 if (type == TYPE_A) { 1650 off_t i, n; 1651 int c; 1652 1653 n = restart_point; 1654 i = 0; 1655 while (i++ < n) { 1656 if ((c=getc(fin)) == EOF) { 1657 perror_reply(550, name); 1658 goto done; 1659 } 1660 if (c == '\n') 1661 i++; 1662 } 1663 } else if (lseek(fileno(fin), restart_point, L_SET) < 0) { 1664 perror_reply(550, name); 1665 goto done; 1666 } 1667 } 1668 dout = dataconn(name, st.st_size, "w"); 1669 if (dout == NULL) 1670 goto done; 1671 time(&start); 1672 send_data(fin, dout, st.st_blksize, st.st_size, 1673 restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode)); 1674 if (cmd == 0 && guest && stats) 1675 logxfer(name, st.st_size, start); 1676 (void) fclose(dout); 1677 data = -1; 1678 pdata = -1; 1679 done: 1680 if (cmd == 0) 1681 LOGBYTES("get", name, byte_count); 1682 (*closefunc)(fin); 1683 } 1684 1685 void 1686 store(name, mode, unique) 1687 char *name, *mode; 1688 int unique; 1689 { 1690 int fd; 1691 FILE *fout, *din; 1692 int (*closefunc) (FILE *); 1693 1694 if (*mode == 'a') { /* APPE */ 1695 if (unique) { 1696 /* Programming error */ 1697 syslog(LOG_ERR, "Internal: unique flag to APPE"); 1698 unique = 0; 1699 } 1700 if (guest && noguestmod) { 1701 reply(550, "Appending to existing file denied"); 1702 goto err; 1703 } 1704 restart_point = 0; /* not affected by preceding REST */ 1705 } 1706 if (unique) /* STOU overrides REST */ 1707 restart_point = 0; 1708 if (guest && noguestmod) { 1709 if (restart_point) { /* guest STOR w/REST */ 1710 reply(550, "Modifying existing file denied"); 1711 goto err; 1712 } else /* treat guest STOR as STOU */ 1713 unique = 1; 1714 } 1715 1716 if (restart_point) 1717 mode = "r+"; /* so ASCII manual seek can work */ 1718 if (unique) { 1719 if ((fd = guniquefd(name, &name)) < 0) 1720 goto err; 1721 fout = fdopen(fd, mode); 1722 } else 1723 fout = fopen(name, mode); 1724 closefunc = fclose; 1725 if (fout == NULL) { 1726 perror_reply(553, name); 1727 goto err; 1728 } 1729 byte_count = -1; 1730 if (restart_point) { 1731 if (type == TYPE_A) { 1732 off_t i, n; 1733 int c; 1734 1735 n = restart_point; 1736 i = 0; 1737 while (i++ < n) { 1738 if ((c=getc(fout)) == EOF) { 1739 perror_reply(550, name); 1740 goto done; 1741 } 1742 if (c == '\n') 1743 i++; 1744 } 1745 /* 1746 * We must do this seek to "current" position 1747 * because we are changing from reading to 1748 * writing. 1749 */ 1750 if (fseeko(fout, (off_t)0, SEEK_CUR) < 0) { 1751 perror_reply(550, name); 1752 goto done; 1753 } 1754 } else if (lseek(fileno(fout), restart_point, L_SET) < 0) { 1755 perror_reply(550, name); 1756 goto done; 1757 } 1758 } 1759 din = dataconn(name, (off_t)-1, "r"); 1760 if (din == NULL) 1761 goto done; 1762 if (receive_data(din, fout) == 0) { 1763 if (unique) 1764 reply(226, "Transfer complete (unique file name:%s).", 1765 name); 1766 else 1767 reply(226, "Transfer complete."); 1768 } 1769 (void) fclose(din); 1770 data = -1; 1771 pdata = -1; 1772 done: 1773 LOGBYTES(*mode == 'a' ? "append" : "put", name, byte_count); 1774 (*closefunc)(fout); 1775 return; 1776 err: 1777 LOGCMD(*mode == 'a' ? "append" : "put" , name); 1778 return; 1779 } 1780 1781 static FILE * 1782 getdatasock(mode) 1783 char *mode; 1784 { 1785 int on = 1, s, t, tries; 1786 1787 if (data >= 0) 1788 return (fdopen(data, mode)); 1789 1790 s = socket(data_dest.su_family, SOCK_STREAM, 0); 1791 if (s < 0) 1792 goto bad; 1793 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 1794 syslog(LOG_WARNING, "data setsockopt (SO_REUSEADDR): %m"); 1795 /* anchor socket to avoid multi-homing problems */ 1796 data_source = ctrl_addr; 1797 data_source.su_port = htons(dataport); 1798 (void) seteuid((uid_t)0); 1799 for (tries = 1; ; tries++) { 1800 if (bind(s, (struct sockaddr *)&data_source, 1801 data_source.su_len) >= 0) 1802 break; 1803 if (errno != EADDRINUSE || tries > 10) 1804 goto bad; 1805 sleep(tries); 1806 } 1807 (void) seteuid((uid_t)pw->pw_uid); 1808 #ifdef IP_TOS 1809 if (data_source.su_family == AF_INET) 1810 { 1811 on = IPTOS_THROUGHPUT; 1812 if (setsockopt(s, IPPROTO_IP, IP_TOS, &on, sizeof(int)) < 0) 1813 syslog(LOG_WARNING, "data setsockopt (IP_TOS): %m"); 1814 } 1815 #endif 1816 #ifdef TCP_NOPUSH 1817 /* 1818 * Turn off push flag to keep sender TCP from sending short packets 1819 * at the boundaries of each write(). Should probably do a SO_SNDBUF 1820 * to set the send buffer size as well, but that may not be desirable 1821 * in heavy-load situations. 1822 */ 1823 on = 1; 1824 if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, &on, sizeof on) < 0) 1825 syslog(LOG_WARNING, "data setsockopt (TCP_NOPUSH): %m"); 1826 #endif 1827 #ifdef SO_SNDBUF 1828 on = 65536; 1829 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &on, sizeof on) < 0) 1830 syslog(LOG_WARNING, "data setsockopt (SO_SNDBUF): %m"); 1831 #endif 1832 1833 return (fdopen(s, mode)); 1834 bad: 1835 /* Return the real value of errno (close may change it) */ 1836 t = errno; 1837 (void) seteuid((uid_t)pw->pw_uid); 1838 (void) close(s); 1839 errno = t; 1840 return (NULL); 1841 } 1842 1843 static FILE * 1844 dataconn(name, size, mode) 1845 char *name; 1846 off_t size; 1847 char *mode; 1848 { 1849 char sizebuf[32]; 1850 FILE *file; 1851 int retry = 0, tos, conerrno; 1852 1853 file_size = size; 1854 byte_count = 0; 1855 if (size != (off_t) -1) 1856 (void) snprintf(sizebuf, sizeof(sizebuf), " (%qd bytes)", size); 1857 else 1858 *sizebuf = '\0'; 1859 if (pdata >= 0) { 1860 union sockunion from; 1861 int flags; 1862 int s, fromlen = ctrl_addr.su_len; 1863 struct timeval timeout; 1864 fd_set set; 1865 1866 FD_ZERO(&set); 1867 FD_SET(pdata, &set); 1868 1869 timeout.tv_usec = 0; 1870 timeout.tv_sec = 120; 1871 1872 /* 1873 * Granted a socket is in the blocking I/O mode, 1874 * accept() will block after a successful select() 1875 * if the selected connection dies in between. 1876 * Therefore set the non-blocking I/O flag here. 1877 */ 1878 if ((flags = fcntl(pdata, F_GETFL, 0)) == -1 || 1879 fcntl(pdata, F_SETFL, flags | O_NONBLOCK) == -1) 1880 goto pdata_err; 1881 if (select(pdata+1, &set, (fd_set *) 0, (fd_set *) 0, &timeout) <= 0 || 1882 (s = accept(pdata, (struct sockaddr *) &from, &fromlen)) < 0) 1883 goto pdata_err; 1884 (void) close(pdata); 1885 pdata = s; 1886 /* 1887 * Unset the inherited non-blocking I/O flag 1888 * on the child socket so stdio can work on it. 1889 */ 1890 if ((flags = fcntl(pdata, F_GETFL, 0)) == -1 || 1891 fcntl(pdata, F_SETFL, flags & ~O_NONBLOCK) == -1) 1892 goto pdata_err; 1893 #ifdef IP_TOS 1894 if (from.su_family == AF_INET) 1895 { 1896 tos = IPTOS_THROUGHPUT; 1897 if (setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(int)) < 0) 1898 syslog(LOG_WARNING, "pdata setsockopt (IP_TOS): %m"); 1899 } 1900 #endif 1901 reply(150, "Opening %s mode data connection for '%s'%s.", 1902 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); 1903 return (fdopen(pdata, mode)); 1904 pdata_err: 1905 reply(425, "Can't open data connection."); 1906 (void) close(pdata); 1907 pdata = -1; 1908 return (NULL); 1909 } 1910 if (data >= 0) { 1911 reply(125, "Using existing data connection for '%s'%s.", 1912 name, sizebuf); 1913 usedefault = 1; 1914 return (fdopen(data, mode)); 1915 } 1916 if (usedefault) 1917 data_dest = his_addr; 1918 usedefault = 1; 1919 do { 1920 file = getdatasock(mode); 1921 if (file == NULL) { 1922 char hostbuf[BUFSIZ], portbuf[BUFSIZ]; 1923 getnameinfo((struct sockaddr *)&data_source, 1924 data_source.su_len, hostbuf, sizeof(hostbuf) - 1, 1925 portbuf, sizeof(portbuf), 1926 NI_NUMERICHOST|NI_NUMERICSERV); 1927 reply(425, "Can't create data socket (%s,%s): %s.", 1928 hostbuf, portbuf, strerror(errno)); 1929 return (NULL); 1930 } 1931 data = fileno(file); 1932 conerrno = 0; 1933 if (connect(data, (struct sockaddr *)&data_dest, 1934 data_dest.su_len) == 0) 1935 break; 1936 conerrno = errno; 1937 (void) fclose(file); 1938 data = -1; 1939 if (conerrno == EADDRINUSE) { 1940 sleep((unsigned) swaitint); 1941 retry += swaitint; 1942 } else { 1943 break; 1944 } 1945 } while (retry <= swaitmax); 1946 if (conerrno != 0) { 1947 perror_reply(425, "Can't build data connection"); 1948 return (NULL); 1949 } 1950 reply(150, "Opening %s mode data connection for '%s'%s.", 1951 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); 1952 return (file); 1953 } 1954 1955 /* 1956 * Tranfer the contents of "instr" to "outstr" peer using the appropriate 1957 * encapsulation of the data subject to Mode, Structure, and Type. 1958 * 1959 * NB: Form isn't handled. 1960 */ 1961 static int 1962 send_data(instr, outstr, blksize, filesize, isreg) 1963 FILE *instr, *outstr; 1964 off_t blksize; 1965 off_t filesize; 1966 int isreg; 1967 { 1968 int c, filefd, netfd; 1969 char *buf; 1970 off_t cnt; 1971 1972 transflag++; 1973 switch (type) { 1974 1975 case TYPE_A: 1976 while ((c = getc(instr)) != EOF) { 1977 if (recvurg) 1978 goto got_oob; 1979 byte_count++; 1980 if (c == '\n') { 1981 if (ferror(outstr)) 1982 goto data_err; 1983 (void) putc('\r', outstr); 1984 } 1985 (void) putc(c, outstr); 1986 } 1987 if (recvurg) 1988 goto got_oob; 1989 fflush(outstr); 1990 transflag = 0; 1991 if (ferror(instr)) 1992 goto file_err; 1993 if (ferror(outstr)) 1994 goto data_err; 1995 reply(226, "Transfer complete."); 1996 return (0); 1997 1998 case TYPE_I: 1999 case TYPE_L: 2000 /* 2001 * isreg is only set if we are not doing restart and we 2002 * are sending a regular file 2003 */ 2004 netfd = fileno(outstr); 2005 filefd = fileno(instr); 2006 2007 if (isreg) { 2008 2009 off_t offset; 2010 int err; 2011 2012 err = cnt = offset = 0; 2013 2014 while (err != -1 && filesize > 0) { 2015 err = sendfile(filefd, netfd, offset, 0, 2016 (struct sf_hdtr *) NULL, &cnt, 0); 2017 /* 2018 * Calculate byte_count before OOB processing. 2019 * It can be used in myoob() later. 2020 */ 2021 byte_count += cnt; 2022 if (recvurg) 2023 goto got_oob; 2024 offset += cnt; 2025 filesize -= cnt; 2026 2027 if (err == -1) { 2028 if (!cnt) 2029 goto oldway; 2030 2031 goto data_err; 2032 } 2033 } 2034 2035 transflag = 0; 2036 reply(226, "Transfer complete."); 2037 return (0); 2038 } 2039 2040 oldway: 2041 if ((buf = malloc((u_int)blksize)) == NULL) { 2042 transflag = 0; 2043 perror_reply(451, "Local resource failure: malloc"); 2044 return (-1); 2045 } 2046 2047 while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 && 2048 write(netfd, buf, cnt) == cnt) 2049 byte_count += cnt; 2050 transflag = 0; 2051 (void)free(buf); 2052 if (cnt != 0) { 2053 if (cnt < 0) 2054 goto file_err; 2055 goto data_err; 2056 } 2057 reply(226, "Transfer complete."); 2058 return (0); 2059 default: 2060 transflag = 0; 2061 reply(550, "Unimplemented TYPE %d in send_data", type); 2062 return (-1); 2063 } 2064 2065 data_err: 2066 transflag = 0; 2067 perror_reply(426, "Data connection"); 2068 return (-1); 2069 2070 file_err: 2071 transflag = 0; 2072 perror_reply(551, "Error on input file"); 2073 return (-1); 2074 2075 got_oob: 2076 myoob(); 2077 recvurg = 0; 2078 transflag = 0; 2079 return (-1); 2080 } 2081 2082 /* 2083 * Transfer data from peer to "outstr" using the appropriate encapulation of 2084 * the data subject to Mode, Structure, and Type. 2085 * 2086 * N.B.: Form isn't handled. 2087 */ 2088 static int 2089 receive_data(instr, outstr) 2090 FILE *instr, *outstr; 2091 { 2092 int c; 2093 int cnt, bare_lfs; 2094 char buf[BUFSIZ]; 2095 2096 transflag++; 2097 bare_lfs = 0; 2098 2099 switch (type) { 2100 2101 case TYPE_I: 2102 case TYPE_L: 2103 while ((cnt = read(fileno(instr), buf, sizeof(buf))) > 0) { 2104 if (recvurg) 2105 goto got_oob; 2106 if (write(fileno(outstr), buf, cnt) != cnt) 2107 goto file_err; 2108 byte_count += cnt; 2109 } 2110 if (recvurg) 2111 goto got_oob; 2112 if (cnt < 0) 2113 goto data_err; 2114 transflag = 0; 2115 return (0); 2116 2117 case TYPE_E: 2118 reply(553, "TYPE E not implemented."); 2119 transflag = 0; 2120 return (-1); 2121 2122 case TYPE_A: 2123 while ((c = getc(instr)) != EOF) { 2124 if (recvurg) 2125 goto got_oob; 2126 byte_count++; 2127 if (c == '\n') 2128 bare_lfs++; 2129 while (c == '\r') { 2130 if (ferror(outstr)) 2131 goto data_err; 2132 if ((c = getc(instr)) != '\n') { 2133 (void) putc ('\r', outstr); 2134 if (c == '\0' || c == EOF) 2135 goto contin2; 2136 } 2137 } 2138 (void) putc(c, outstr); 2139 contin2: ; 2140 } 2141 if (recvurg) 2142 goto got_oob; 2143 fflush(outstr); 2144 if (ferror(instr)) 2145 goto data_err; 2146 if (ferror(outstr)) 2147 goto file_err; 2148 transflag = 0; 2149 if (bare_lfs) { 2150 lreply(226, 2151 "WARNING! %d bare linefeeds received in ASCII mode", 2152 bare_lfs); 2153 (void)printf(" File may not have transferred correctly.\r\n"); 2154 } 2155 return (0); 2156 default: 2157 reply(550, "Unimplemented TYPE %d in receive_data", type); 2158 transflag = 0; 2159 return (-1); 2160 } 2161 2162 data_err: 2163 transflag = 0; 2164 perror_reply(426, "Data Connection"); 2165 return (-1); 2166 2167 file_err: 2168 transflag = 0; 2169 perror_reply(452, "Error writing file"); 2170 return (-1); 2171 2172 got_oob: 2173 myoob(); 2174 recvurg = 0; 2175 transflag = 0; 2176 return (-1); 2177 } 2178 2179 void 2180 statfilecmd(filename) 2181 char *filename; 2182 { 2183 FILE *fin; 2184 int atstart; 2185 int c; 2186 char line[LINE_MAX]; 2187 2188 (void)snprintf(line, sizeof(line), _PATH_LS " -lgA %s", filename); 2189 fin = ftpd_popen(line, "r"); 2190 lreply(211, "status of %s:", filename); 2191 atstart = 1; 2192 while ((c = getc(fin)) != EOF) { 2193 if (c == '\n') { 2194 if (ferror(stdout)){ 2195 perror_reply(421, "control connection"); 2196 (void) ftpd_pclose(fin); 2197 dologout(1); 2198 /* NOTREACHED */ 2199 } 2200 if (ferror(fin)) { 2201 perror_reply(551, filename); 2202 (void) ftpd_pclose(fin); 2203 return; 2204 } 2205 (void) putc('\r', stdout); 2206 } 2207 /* 2208 * RFC 959 says neutral text should be prepended before 2209 * a leading 3-digit number followed by whitespace, but 2210 * many ftp clients can be confused by any leading digits, 2211 * as a matter of fact. 2212 */ 2213 if (atstart && isdigit(c)) 2214 (void) putc(' ', stdout); 2215 (void) putc(c, stdout); 2216 atstart = (c == '\n'); 2217 } 2218 (void) ftpd_pclose(fin); 2219 reply(211, "End of Status"); 2220 } 2221 2222 void 2223 statcmd() 2224 { 2225 union sockunion *su; 2226 u_char *a, *p; 2227 char hname[NI_MAXHOST]; 2228 int ispassive; 2229 2230 if (hostinfo) { 2231 lreply(211, "%s FTP server status:", hostname); 2232 printf(" %s\r\n", version); 2233 } else 2234 lreply(211, "FTP server status:"); 2235 printf(" Connected to %s", remotehost); 2236 if (!getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len, 2237 hname, sizeof(hname) - 1, NULL, 0, NI_NUMERICHOST)) { 2238 if (strcmp(hname, remotehost) != 0) 2239 printf(" (%s)", hname); 2240 } 2241 printf("\r\n"); 2242 if (logged_in) { 2243 if (guest) 2244 printf(" Logged in anonymously\r\n"); 2245 else 2246 printf(" Logged in as %s\r\n", pw->pw_name); 2247 } else if (askpasswd) 2248 printf(" Waiting for password\r\n"); 2249 else 2250 printf(" Waiting for user name\r\n"); 2251 printf(" TYPE: %s", typenames[type]); 2252 if (type == TYPE_A || type == TYPE_E) 2253 printf(", FORM: %s", formnames[form]); 2254 if (type == TYPE_L) 2255 #if NBBY == 8 2256 printf(" %d", NBBY); 2257 #else 2258 printf(" %d", bytesize); /* need definition! */ 2259 #endif 2260 printf("; STRUcture: %s; transfer MODE: %s\r\n", 2261 strunames[stru], modenames[mode]); 2262 if (data != -1) 2263 printf(" Data connection open\r\n"); 2264 else if (pdata != -1) { 2265 ispassive = 1; 2266 su = &pasv_addr; 2267 goto printaddr; 2268 } else if (usedefault == 0) { 2269 ispassive = 0; 2270 su = &data_dest; 2271 printaddr: 2272 #define UC(b) (((int) b) & 0xff) 2273 if (epsvall) { 2274 printf(" EPSV only mode (EPSV ALL)\r\n"); 2275 goto epsvonly; 2276 } 2277 2278 /* PORT/PASV */ 2279 if (su->su_family == AF_INET) { 2280 a = (u_char *) &su->su_sin.sin_addr; 2281 p = (u_char *) &su->su_sin.sin_port; 2282 printf(" %s (%d,%d,%d,%d,%d,%d)\r\n", 2283 ispassive ? "PASV" : "PORT", 2284 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 2285 UC(p[0]), UC(p[1])); 2286 } 2287 2288 /* LPRT/LPSV */ 2289 { 2290 int alen, af, i; 2291 2292 switch (su->su_family) { 2293 case AF_INET: 2294 a = (u_char *) &su->su_sin.sin_addr; 2295 p = (u_char *) &su->su_sin.sin_port; 2296 alen = sizeof(su->su_sin.sin_addr); 2297 af = 4; 2298 break; 2299 case AF_INET6: 2300 a = (u_char *) &su->su_sin6.sin6_addr; 2301 p = (u_char *) &su->su_sin6.sin6_port; 2302 alen = sizeof(su->su_sin6.sin6_addr); 2303 af = 6; 2304 break; 2305 default: 2306 af = 0; 2307 break; 2308 } 2309 if (af) { 2310 printf(" %s (%d,%d,", ispassive ? "LPSV" : "LPRT", 2311 af, alen); 2312 for (i = 0; i < alen; i++) 2313 printf("%d,", UC(a[i])); 2314 printf("%d,%d,%d)\r\n", 2, UC(p[0]), UC(p[1])); 2315 } 2316 } 2317 2318 epsvonly:; 2319 /* EPRT/EPSV */ 2320 { 2321 int af; 2322 2323 switch (su->su_family) { 2324 case AF_INET: 2325 af = 1; 2326 break; 2327 case AF_INET6: 2328 af = 2; 2329 break; 2330 default: 2331 af = 0; 2332 break; 2333 } 2334 if (af) { 2335 union sockunion tmp; 2336 2337 tmp = *su; 2338 if (tmp.su_family == AF_INET6) 2339 tmp.su_sin6.sin6_scope_id = 0; 2340 if (!getnameinfo((struct sockaddr *)&tmp, tmp.su_len, 2341 hname, sizeof(hname) - 1, NULL, 0, 2342 NI_NUMERICHOST)) { 2343 printf(" %s |%d|%s|%d|\r\n", 2344 ispassive ? "EPSV" : "EPRT", 2345 af, hname, htons(tmp.su_port)); 2346 } 2347 } 2348 } 2349 #undef UC 2350 } else 2351 printf(" No data connection\r\n"); 2352 reply(211, "End of status"); 2353 } 2354 2355 void 2356 fatalerror(s) 2357 char *s; 2358 { 2359 2360 reply(451, "Error in server: %s\n", s); 2361 reply(221, "Closing connection due to server error."); 2362 dologout(0); 2363 /* NOTREACHED */ 2364 } 2365 2366 void 2367 #if __STDC__ 2368 reply(int n, const char *fmt, ...) 2369 #else 2370 reply(n, fmt, va_alist) 2371 int n; 2372 char *fmt; 2373 va_dcl 2374 #endif 2375 { 2376 va_list ap; 2377 #if __STDC__ 2378 va_start(ap, fmt); 2379 #else 2380 va_start(ap); 2381 #endif 2382 (void)printf("%d ", n); 2383 (void)vprintf(fmt, ap); 2384 (void)printf("\r\n"); 2385 (void)fflush(stdout); 2386 if (ftpdebug) { 2387 syslog(LOG_DEBUG, "<--- %d ", n); 2388 vsyslog(LOG_DEBUG, fmt, ap); 2389 } 2390 } 2391 2392 void 2393 #if __STDC__ 2394 lreply(int n, const char *fmt, ...) 2395 #else 2396 lreply(n, fmt, va_alist) 2397 int n; 2398 char *fmt; 2399 va_dcl 2400 #endif 2401 { 2402 va_list ap; 2403 #if __STDC__ 2404 va_start(ap, fmt); 2405 #else 2406 va_start(ap); 2407 #endif 2408 (void)printf("%d- ", n); 2409 (void)vprintf(fmt, ap); 2410 (void)printf("\r\n"); 2411 (void)fflush(stdout); 2412 if (ftpdebug) { 2413 syslog(LOG_DEBUG, "<--- %d- ", n); 2414 vsyslog(LOG_DEBUG, fmt, ap); 2415 } 2416 } 2417 2418 static void 2419 ack(s) 2420 char *s; 2421 { 2422 2423 reply(250, "%s command successful.", s); 2424 } 2425 2426 void 2427 nack(s) 2428 char *s; 2429 { 2430 2431 reply(502, "%s command not implemented.", s); 2432 } 2433 2434 /* ARGSUSED */ 2435 void 2436 yyerror(s) 2437 char *s; 2438 { 2439 char *cp; 2440 2441 if ((cp = strchr(cbuf,'\n'))) 2442 *cp = '\0'; 2443 reply(500, "'%s': command not understood.", cbuf); 2444 } 2445 2446 void 2447 delete(name) 2448 char *name; 2449 { 2450 struct stat st; 2451 2452 LOGCMD("delete", name); 2453 if (lstat(name, &st) < 0) { 2454 perror_reply(550, name); 2455 return; 2456 } 2457 if ((st.st_mode&S_IFMT) == S_IFDIR) { 2458 if (rmdir(name) < 0) { 2459 perror_reply(550, name); 2460 return; 2461 } 2462 goto done; 2463 } 2464 if (unlink(name) < 0) { 2465 perror_reply(550, name); 2466 return; 2467 } 2468 done: 2469 ack("DELE"); 2470 } 2471 2472 void 2473 cwd(path) 2474 char *path; 2475 { 2476 2477 if (chdir(path) < 0) 2478 perror_reply(550, path); 2479 else 2480 ack("CWD"); 2481 } 2482 2483 void 2484 makedir(name) 2485 char *name; 2486 { 2487 char *s; 2488 2489 LOGCMD("mkdir", name); 2490 if (guest && noguestmkd) 2491 reply(550, "%s: permission denied", name); 2492 else if (mkdir(name, 0777) < 0) 2493 perror_reply(550, name); 2494 else { 2495 if ((s = doublequote(name)) == NULL) 2496 fatalerror("Ran out of memory."); 2497 reply(257, "\"%s\" directory created.", s); 2498 free(s); 2499 } 2500 } 2501 2502 void 2503 removedir(name) 2504 char *name; 2505 { 2506 2507 LOGCMD("rmdir", name); 2508 if (rmdir(name) < 0) 2509 perror_reply(550, name); 2510 else 2511 ack("RMD"); 2512 } 2513 2514 void 2515 pwd() 2516 { 2517 char *s, path[MAXPATHLEN + 1]; 2518 2519 if (getwd(path) == (char *)NULL) 2520 reply(550, "%s.", path); 2521 else { 2522 if ((s = doublequote(path)) == NULL) 2523 fatalerror("Ran out of memory."); 2524 reply(257, "\"%s\" is current directory.", s); 2525 free(s); 2526 } 2527 } 2528 2529 char * 2530 renamefrom(name) 2531 char *name; 2532 { 2533 struct stat st; 2534 2535 if (lstat(name, &st) < 0) { 2536 perror_reply(550, name); 2537 return ((char *)0); 2538 } 2539 reply(350, "File exists, ready for destination name"); 2540 return (name); 2541 } 2542 2543 void 2544 renamecmd(from, to) 2545 char *from, *to; 2546 { 2547 struct stat st; 2548 2549 LOGCMD2("rename", from, to); 2550 2551 if (guest && (stat(to, &st) == 0)) { 2552 reply(550, "%s: permission denied", to); 2553 return; 2554 } 2555 2556 if (rename(from, to) < 0) 2557 perror_reply(550, "rename"); 2558 else 2559 ack("RNTO"); 2560 } 2561 2562 static void 2563 dolog(who) 2564 struct sockaddr *who; 2565 { 2566 int error; 2567 2568 realhostname_sa(remotehost, sizeof(remotehost) - 1, who, who->sa_len); 2569 2570 #ifdef SETPROCTITLE 2571 #ifdef VIRTUAL_HOSTING 2572 if (thishost != firsthost) 2573 snprintf(proctitle, sizeof(proctitle), "%s: connected (to %s)", 2574 remotehost, hostname); 2575 else 2576 #endif 2577 snprintf(proctitle, sizeof(proctitle), "%s: connected", 2578 remotehost); 2579 setproctitle("%s", proctitle); 2580 #endif /* SETPROCTITLE */ 2581 2582 if (logging) { 2583 #ifdef VIRTUAL_HOSTING 2584 if (thishost != firsthost) 2585 syslog(LOG_INFO, "connection from %s (to %s)", 2586 remotehost, hostname); 2587 else 2588 #endif 2589 { 2590 char who_name[MAXHOSTNAMELEN]; 2591 2592 error = getnameinfo(who, who->sa_len, 2593 who_name, sizeof(who_name) - 1, 2594 NULL, 0, NI_NUMERICHOST); 2595 syslog(LOG_INFO, "connection from %s (%s)", remotehost, 2596 error == 0 ? who_name : ""); 2597 } 2598 } 2599 } 2600 2601 /* 2602 * Record logout in wtmp file 2603 * and exit with supplied status. 2604 */ 2605 void 2606 dologout(status) 2607 int status; 2608 { 2609 /* 2610 * Prevent reception of SIGURG from resulting in a resumption 2611 * back to the main program loop. 2612 */ 2613 transflag = 0; 2614 2615 if (logged_in && dowtmp) { 2616 (void) seteuid((uid_t)0); 2617 ftpd_logwtmp(ttyline, "", NULL); 2618 } 2619 /* beware of flushing buffers after a SIGPIPE */ 2620 _exit(status); 2621 } 2622 2623 static void 2624 sigurg(signo) 2625 int signo; 2626 { 2627 2628 recvurg = 1; 2629 } 2630 2631 static void 2632 myoob() 2633 { 2634 char *cp; 2635 2636 /* only process if transfer occurring */ 2637 if (!transflag) 2638 return; 2639 cp = tmpline; 2640 if (getline(cp, 7, stdin) == NULL) { 2641 reply(221, "You could at least say goodbye."); 2642 dologout(0); 2643 } 2644 upper(cp); 2645 if (strcmp(cp, "ABOR\r\n") == 0) { 2646 tmpline[0] = '\0'; 2647 reply(426, "Transfer aborted. Data connection closed."); 2648 reply(226, "Abort successful"); 2649 } 2650 if (strcmp(cp, "STAT\r\n") == 0) { 2651 tmpline[0] = '\0'; 2652 if (file_size != (off_t) -1) 2653 reply(213, "Status: %qd of %qd bytes transferred", 2654 byte_count, file_size); 2655 else 2656 reply(213, "Status: %qd bytes transferred", byte_count); 2657 } 2658 } 2659 2660 /* 2661 * Note: a response of 425 is not mentioned as a possible response to 2662 * the PASV command in RFC959. However, it has been blessed as 2663 * a legitimate response by Jon Postel in a telephone conversation 2664 * with Rick Adams on 25 Jan 89. 2665 */ 2666 void 2667 passive() 2668 { 2669 int len, on; 2670 char *p, *a; 2671 2672 if (pdata >= 0) /* close old port if one set */ 2673 close(pdata); 2674 2675 pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0); 2676 if (pdata < 0) { 2677 perror_reply(425, "Can't open passive connection"); 2678 return; 2679 } 2680 on = 1; 2681 if (setsockopt(pdata, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 2682 syslog(LOG_WARNING, "pdata setsockopt (SO_REUSEADDR): %m"); 2683 2684 (void) seteuid((uid_t)0); 2685 2686 #ifdef IP_PORTRANGE 2687 if (ctrl_addr.su_family == AF_INET) { 2688 on = restricted_data_ports ? IP_PORTRANGE_HIGH 2689 : IP_PORTRANGE_DEFAULT; 2690 2691 if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE, 2692 &on, sizeof(on)) < 0) 2693 goto pasv_error; 2694 } 2695 #endif 2696 #ifdef IPV6_PORTRANGE 2697 if (ctrl_addr.su_family == AF_INET6) { 2698 on = restricted_data_ports ? IPV6_PORTRANGE_HIGH 2699 : IPV6_PORTRANGE_DEFAULT; 2700 2701 if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE, 2702 &on, sizeof(on)) < 0) 2703 goto pasv_error; 2704 } 2705 #endif 2706 2707 pasv_addr = ctrl_addr; 2708 pasv_addr.su_port = 0; 2709 if (bind(pdata, (struct sockaddr *)&pasv_addr, pasv_addr.su_len) < 0) 2710 goto pasv_error; 2711 2712 (void) seteuid((uid_t)pw->pw_uid); 2713 2714 len = sizeof(pasv_addr); 2715 if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0) 2716 goto pasv_error; 2717 if (listen(pdata, 1) < 0) 2718 goto pasv_error; 2719 if (pasv_addr.su_family == AF_INET) 2720 a = (char *) &pasv_addr.su_sin.sin_addr; 2721 else if (pasv_addr.su_family == AF_INET6 && 2722 IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr)) 2723 a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12]; 2724 else 2725 goto pasv_error; 2726 2727 p = (char *) &pasv_addr.su_port; 2728 2729 #define UC(b) (((int) b) & 0xff) 2730 2731 reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]), 2732 UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); 2733 return; 2734 2735 pasv_error: 2736 (void) seteuid((uid_t)pw->pw_uid); 2737 (void) close(pdata); 2738 pdata = -1; 2739 perror_reply(425, "Can't open passive connection"); 2740 return; 2741 } 2742 2743 /* 2744 * Long Passive defined in RFC 1639. 2745 * 228 Entering Long Passive Mode 2746 * (af, hal, h1, h2, h3,..., pal, p1, p2...) 2747 */ 2748 2749 void 2750 long_passive(cmd, pf) 2751 char *cmd; 2752 int pf; 2753 { 2754 int len, on; 2755 char *p, *a; 2756 2757 if (pdata >= 0) /* close old port if one set */ 2758 close(pdata); 2759 2760 if (pf != PF_UNSPEC) { 2761 if (ctrl_addr.su_family != pf) { 2762 switch (ctrl_addr.su_family) { 2763 case AF_INET: 2764 pf = 1; 2765 break; 2766 case AF_INET6: 2767 pf = 2; 2768 break; 2769 default: 2770 pf = 0; 2771 break; 2772 } 2773 /* 2774 * XXX 2775 * only EPRT/EPSV ready clients will understand this 2776 */ 2777 if (strcmp(cmd, "EPSV") == 0 && pf) { 2778 reply(522, "Network protocol mismatch, " 2779 "use (%d)", pf); 2780 } else 2781 reply(501, "Network protocol mismatch"); /*XXX*/ 2782 2783 return; 2784 } 2785 } 2786 2787 pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0); 2788 if (pdata < 0) { 2789 perror_reply(425, "Can't open passive connection"); 2790 return; 2791 } 2792 on = 1; 2793 if (setsockopt(pdata, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 2794 syslog(LOG_WARNING, "pdata setsockopt (SO_REUSEADDR): %m"); 2795 2796 (void) seteuid((uid_t)0); 2797 2798 pasv_addr = ctrl_addr; 2799 pasv_addr.su_port = 0; 2800 len = pasv_addr.su_len; 2801 2802 #ifdef IP_PORTRANGE 2803 if (ctrl_addr.su_family == AF_INET) { 2804 on = restricted_data_ports ? IP_PORTRANGE_HIGH 2805 : IP_PORTRANGE_DEFAULT; 2806 2807 if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE, 2808 &on, sizeof(on)) < 0) 2809 goto pasv_error; 2810 } 2811 #endif 2812 #ifdef IPV6_PORTRANGE 2813 if (ctrl_addr.su_family == AF_INET6) { 2814 on = restricted_data_ports ? IPV6_PORTRANGE_HIGH 2815 : IPV6_PORTRANGE_DEFAULT; 2816 2817 if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE, 2818 &on, sizeof(on)) < 0) 2819 goto pasv_error; 2820 } 2821 #endif 2822 2823 if (bind(pdata, (struct sockaddr *)&pasv_addr, len) < 0) 2824 goto pasv_error; 2825 2826 (void) seteuid((uid_t)pw->pw_uid); 2827 2828 if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0) 2829 goto pasv_error; 2830 if (listen(pdata, 1) < 0) 2831 goto pasv_error; 2832 2833 #define UC(b) (((int) b) & 0xff) 2834 2835 if (strcmp(cmd, "LPSV") == 0) { 2836 p = (char *)&pasv_addr.su_port; 2837 switch (pasv_addr.su_family) { 2838 case AF_INET: 2839 a = (char *) &pasv_addr.su_sin.sin_addr; 2840 v4_reply: 2841 reply(228, 2842 "Entering Long Passive Mode (%d,%d,%d,%d,%d,%d,%d,%d,%d)", 2843 4, 4, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 2844 2, UC(p[0]), UC(p[1])); 2845 return; 2846 case AF_INET6: 2847 if (IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr)) { 2848 a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12]; 2849 goto v4_reply; 2850 } 2851 a = (char *) &pasv_addr.su_sin6.sin6_addr; 2852 reply(228, 2853 "Entering Long Passive Mode " 2854 "(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)", 2855 6, 16, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 2856 UC(a[4]), UC(a[5]), UC(a[6]), UC(a[7]), 2857 UC(a[8]), UC(a[9]), UC(a[10]), UC(a[11]), 2858 UC(a[12]), UC(a[13]), UC(a[14]), UC(a[15]), 2859 2, UC(p[0]), UC(p[1])); 2860 return; 2861 } 2862 } else if (strcmp(cmd, "EPSV") == 0) { 2863 switch (pasv_addr.su_family) { 2864 case AF_INET: 2865 case AF_INET6: 2866 reply(229, "Entering Extended Passive Mode (|||%d|)", 2867 ntohs(pasv_addr.su_port)); 2868 return; 2869 } 2870 } else { 2871 /* more proper error code? */ 2872 } 2873 2874 pasv_error: 2875 (void) seteuid((uid_t)pw->pw_uid); 2876 (void) close(pdata); 2877 pdata = -1; 2878 perror_reply(425, "Can't open passive connection"); 2879 return; 2880 } 2881 2882 /* 2883 * Generate unique name for file with basename "local" 2884 * and open the file in order to avoid possible races. 2885 * Try "local" first, then "local.1", "local.2" etc, up to "local.99". 2886 * Return descriptor to the file, set "name" to its name. 2887 * 2888 * Generates failure reply on error. 2889 */ 2890 static int 2891 guniquefd(local, name) 2892 char *local; 2893 char **name; 2894 { 2895 static char new[MAXPATHLEN]; 2896 struct stat st; 2897 char *cp; 2898 int count; 2899 int fd; 2900 2901 cp = strrchr(local, '/'); 2902 if (cp) 2903 *cp = '\0'; 2904 if (stat(cp ? local : ".", &st) < 0) { 2905 perror_reply(553, cp ? local : "."); 2906 return (-1); 2907 } 2908 if (cp) { 2909 /* 2910 * Let not overwrite dirname with counter suffix. 2911 * -4 is for /nn\0 2912 * In this extreme case dot won't be put in front of suffix. 2913 */ 2914 if (strlen(local) > sizeof(new) - 4) { 2915 reply(553, "Pathname too long"); 2916 return (-1); 2917 } 2918 *cp = '/'; 2919 } 2920 /* -4 is for the .nn<null> we put on the end below */ 2921 (void) snprintf(new, sizeof(new) - 4, "%s", local); 2922 cp = new + strlen(new); 2923 /* 2924 * Don't generate dotfile unless requested explicitly. 2925 * This covers the case when basename gets truncated off 2926 * by buffer size. 2927 */ 2928 if (cp > new && cp[-1] != '/') 2929 *cp++ = '.'; 2930 for (count = 0; count < 100; count++) { 2931 /* At count 0 try unmodified name */ 2932 if (count) 2933 (void)sprintf(cp, "%d", count); 2934 if ((fd = open(count ? new : local, 2935 O_RDWR | O_CREAT | O_EXCL, 0666)) >= 0) { 2936 *name = count ? new : local; 2937 return (fd); 2938 } 2939 if (errno != EEXIST) { 2940 perror_reply(553, count ? new : local); 2941 return (-1); 2942 } 2943 } 2944 reply(452, "Unique file name cannot be created."); 2945 return (-1); 2946 } 2947 2948 /* 2949 * Format and send reply containing system error number. 2950 */ 2951 void 2952 perror_reply(code, string) 2953 int code; 2954 char *string; 2955 { 2956 2957 reply(code, "%s: %s.", string, strerror(errno)); 2958 } 2959 2960 static char *onefile[] = { 2961 "", 2962 0 2963 }; 2964 2965 void 2966 send_file_list(whichf) 2967 char *whichf; 2968 { 2969 struct stat st; 2970 DIR *dirp = NULL; 2971 struct dirent *dir; 2972 FILE *dout = NULL; 2973 char **dirlist, *dirname; 2974 int simple = 0; 2975 int freeglob = 0; 2976 glob_t gl; 2977 2978 if (strpbrk(whichf, "~{[*?") != NULL) { 2979 int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE; 2980 2981 memset(&gl, 0, sizeof(gl)); 2982 gl.gl_matchc = MAXGLOBARGS; 2983 flags |= GLOB_LIMIT; 2984 freeglob = 1; 2985 if (glob(whichf, flags, 0, &gl)) { 2986 reply(550, "not found"); 2987 goto out; 2988 } else if (gl.gl_pathc == 0) { 2989 errno = ENOENT; 2990 perror_reply(550, whichf); 2991 goto out; 2992 } 2993 dirlist = gl.gl_pathv; 2994 } else { 2995 onefile[0] = whichf; 2996 dirlist = onefile; 2997 simple = 1; 2998 } 2999 3000 while ((dirname = *dirlist++)) { 3001 if (stat(dirname, &st) < 0) { 3002 /* 3003 * If user typed "ls -l", etc, and the client 3004 * used NLST, do what the user meant. 3005 */ 3006 if (dirname[0] == '-' && *dirlist == NULL && 3007 transflag == 0) { 3008 retrieve(_PATH_LS " %s", dirname); 3009 goto out; 3010 } 3011 perror_reply(550, whichf); 3012 if (dout != NULL) { 3013 (void) fclose(dout); 3014 transflag = 0; 3015 data = -1; 3016 pdata = -1; 3017 } 3018 goto out; 3019 } 3020 3021 if (S_ISREG(st.st_mode)) { 3022 if (dout == NULL) { 3023 dout = dataconn("file list", (off_t)-1, "w"); 3024 if (dout == NULL) 3025 goto out; 3026 transflag++; 3027 } 3028 fprintf(dout, "%s%s\n", dirname, 3029 type == TYPE_A ? "\r" : ""); 3030 byte_count += strlen(dirname) + 1; 3031 continue; 3032 } else if (!S_ISDIR(st.st_mode)) 3033 continue; 3034 3035 if ((dirp = opendir(dirname)) == NULL) 3036 continue; 3037 3038 while ((dir = readdir(dirp)) != NULL) { 3039 char nbuf[MAXPATHLEN]; 3040 3041 if (recvurg) { 3042 myoob(); 3043 recvurg = 0; 3044 transflag = 0; 3045 goto out; 3046 } 3047 3048 if (strcmp(dir->d_name, ".") == 0) 3049 continue; 3050 if (strcmp(dir->d_name, "..") == 0) 3051 continue; 3052 3053 snprintf(nbuf, sizeof(nbuf), 3054 "%s/%s", dirname, dir->d_name); 3055 3056 /* 3057 * We have to do a stat to insure it's 3058 * not a directory or special file. 3059 */ 3060 if (simple || (stat(nbuf, &st) == 0 && 3061 S_ISREG(st.st_mode))) { 3062 if (dout == NULL) { 3063 dout = dataconn("file list", (off_t)-1, 3064 "w"); 3065 if (dout == NULL) 3066 goto out; 3067 transflag++; 3068 } 3069 if (nbuf[0] == '.' && nbuf[1] == '/') 3070 fprintf(dout, "%s%s\n", &nbuf[2], 3071 type == TYPE_A ? "\r" : ""); 3072 else 3073 fprintf(dout, "%s%s\n", nbuf, 3074 type == TYPE_A ? "\r" : ""); 3075 byte_count += strlen(nbuf) + 1; 3076 } 3077 } 3078 (void) closedir(dirp); 3079 } 3080 3081 if (dout == NULL) 3082 reply(550, "No files found."); 3083 else if (ferror(dout) != 0) 3084 perror_reply(550, "Data connection"); 3085 else 3086 reply(226, "Transfer complete."); 3087 3088 transflag = 0; 3089 if (dout != NULL) 3090 (void) fclose(dout); 3091 data = -1; 3092 pdata = -1; 3093 out: 3094 if (freeglob) { 3095 freeglob = 0; 3096 globfree(&gl); 3097 } 3098 } 3099 3100 void 3101 reapchild(signo) 3102 int signo; 3103 { 3104 while (wait3(NULL, WNOHANG, NULL) > 0); 3105 } 3106 3107 #ifdef OLD_SETPROCTITLE 3108 /* 3109 * Clobber argv so ps will show what we're doing. (Stolen from sendmail.) 3110 * Warning, since this is usually started from inetd.conf, it often doesn't 3111 * have much of an environment or arglist to overwrite. 3112 */ 3113 void 3114 #if __STDC__ 3115 setproctitle(const char *fmt, ...) 3116 #else 3117 setproctitle(fmt, va_alist) 3118 char *fmt; 3119 va_dcl 3120 #endif 3121 { 3122 int i; 3123 va_list ap; 3124 char *p, *bp, ch; 3125 char buf[LINE_MAX]; 3126 3127 #if __STDC__ 3128 va_start(ap, fmt); 3129 #else 3130 va_start(ap); 3131 #endif 3132 (void)vsnprintf(buf, sizeof(buf), fmt, ap); 3133 3134 /* make ps print our process name */ 3135 p = Argv[0]; 3136 *p++ = '-'; 3137 3138 i = strlen(buf); 3139 if (i > LastArgv - p - 2) { 3140 i = LastArgv - p - 2; 3141 buf[i] = '\0'; 3142 } 3143 bp = buf; 3144 while (ch = *bp++) 3145 if (ch != '\n' && ch != '\r') 3146 *p++ = ch; 3147 while (p < LastArgv) 3148 *p++ = ' '; 3149 } 3150 #endif /* OLD_SETPROCTITLE */ 3151 3152 static void 3153 logxfer(name, size, start) 3154 char *name; 3155 off_t size; 3156 time_t start; 3157 { 3158 char buf[1024]; 3159 char path[MAXPATHLEN + 1]; 3160 time_t now; 3161 3162 if (statfd >= 0 && getwd(path) != NULL) { 3163 time(&now); 3164 snprintf(buf, sizeof(buf), "%.20s!%s!%s!%s/%s!%qd!%ld\n", 3165 ctime(&now)+4, ident, remotehost, 3166 path, name, (long long)size, 3167 (long)(now - start + (now == start))); 3168 write(statfd, buf, strlen(buf)); 3169 } 3170 } 3171 3172 static char * 3173 doublequote(s) 3174 char *s; 3175 { 3176 int n; 3177 char *p, *s2; 3178 3179 for (p = s, n = 0; *p; p++) 3180 if (*p == '"') 3181 n++; 3182 3183 if ((s2 = malloc(p - s + n + 1)) == NULL) 3184 return (NULL); 3185 3186 for (p = s2; *s; s++, p++) { 3187 if ((*p = *s) == '"') 3188 *(++p) = '"'; 3189 } 3190 *p = '\0'; 3191 3192 return (s2); 3193 } 3194