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