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 * $FreeBSD$ 34 */ 35 36 #if 0 37 #ifndef lint 38 static char copyright[] = 39 "@(#) Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994\n\ 40 The Regents of the University of California. All rights reserved.\n"; 41 #endif /* not lint */ 42 #endif 43 44 #if 0 45 #ifndef lint 46 static char sccsid[] = "@(#)ftpd.c 8.4 (Berkeley) 4/16/94"; 47 #endif /* not lint */ 48 #endif 49 50 /* 51 * FTP server. 52 */ 53 #include <sys/param.h> 54 #include <sys/stat.h> 55 #include <sys/ioctl.h> 56 #include <sys/socket.h> 57 #include <sys/wait.h> 58 #include <sys/mman.h> 59 60 #include <netinet/in.h> 61 #include <netinet/in_systm.h> 62 #include <netinet/ip.h> 63 #include <netinet/tcp.h> 64 65 #define FTP_NAMES 66 #include <arpa/ftp.h> 67 #include <arpa/inet.h> 68 #include <arpa/telnet.h> 69 70 #include <ctype.h> 71 #include <dirent.h> 72 #include <err.h> 73 #include <errno.h> 74 #include <fcntl.h> 75 #include <glob.h> 76 #include <limits.h> 77 #include <netdb.h> 78 #include <pwd.h> 79 #include <setjmp.h> 80 #include <signal.h> 81 #include <stdio.h> 82 #include <stdlib.h> 83 #include <string.h> 84 #include <syslog.h> 85 #include <time.h> 86 #include <unistd.h> 87 #include <libutil.h> 88 89 #ifdef SKEY 90 #include <skey.h> 91 #endif 92 93 #include "pathnames.h" 94 #include "extern.h" 95 96 #if __STDC__ 97 #include <stdarg.h> 98 #else 99 #include <varargs.h> 100 #endif 101 102 static char version[] = "Version 6.00"; 103 104 extern off_t restart_point; 105 extern char cbuf[]; 106 107 struct sockaddr_in server_addr; 108 struct sockaddr_in ctrl_addr; 109 struct sockaddr_in data_source; 110 struct sockaddr_in data_dest; 111 struct sockaddr_in his_addr; 112 struct sockaddr_in pasv_addr; 113 114 int daemon_mode; 115 int data; 116 jmp_buf errcatch, urgcatch; 117 int logged_in; 118 struct passwd *pw; 119 int debug; 120 int timeout = 900; /* timeout after 15 minutes of inactivity */ 121 int maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */ 122 int logging; 123 int restricted_data_ports = 1; 124 int paranoid = 1; /* be extra careful about security */ 125 int anon_only = 0; /* Only anonymous ftp allowed */ 126 int guest; 127 int dochroot; 128 int stats; 129 int statfd = -1; 130 int type; 131 int form; 132 int stru; /* avoid C keyword */ 133 int mode; 134 int usedefault = 1; /* for data transfers */ 135 int pdata = -1; /* for passive mode */ 136 sig_atomic_t transflag; 137 off_t file_size; 138 off_t byte_count; 139 #if !defined(CMASK) || CMASK == 0 140 #undef CMASK 141 #define CMASK 027 142 #endif 143 int defumask = CMASK; /* default umask value */ 144 char tmpline[7]; 145 char hostname[MAXHOSTNAMELEN]; 146 char remotehost[MAXHOSTNAMELEN]; 147 char *ident = NULL; 148 149 static char ttyline[20]; 150 char *tty = ttyline; /* for klogin */ 151 152 #ifdef KERBEROS 153 int klogin __P((struct passwd *, char *, char *, char *)); 154 #endif 155 156 struct in_addr bind_address; 157 char *pid_file = NULL; 158 159 #if defined(KERBEROS) 160 int notickets = 1; 161 int noticketsdontcomplain = 1; 162 char *krbtkfile_env = NULL; 163 #endif 164 165 /* 166 * Timeout intervals for retrying connections 167 * to hosts that don't accept PORT cmds. This 168 * is a kludge, but given the problems with TCP... 169 */ 170 #define SWAITMAX 90 /* wait at most 90 seconds */ 171 #define SWAITINT 5 /* interval between retries */ 172 173 int swaitmax = SWAITMAX; 174 int swaitint = SWAITINT; 175 176 #ifdef SETPROCTITLE 177 #ifdef OLD_SETPROCTITLE 178 char **Argv = NULL; /* pointer to argument vector */ 179 char *LastArgv = NULL; /* end of argv */ 180 #endif /* OLD_SETPROCTITLE */ 181 char proctitle[LINE_MAX]; /* initial part of title */ 182 #endif /* SETPROCTITLE */ 183 184 #ifdef SKEY 185 int pwok = 0; 186 char addr_string[20]; /* XXX */ 187 #endif 188 189 #define LOGCMD(cmd, file) \ 190 if (logging > 1) \ 191 syslog(LOG_INFO,"%s %s%s", cmd, \ 192 *(file) == '/' ? "" : curdir(), file); 193 #define LOGCMD2(cmd, file1, file2) \ 194 if (logging > 1) \ 195 syslog(LOG_INFO,"%s %s%s %s%s", cmd, \ 196 *(file1) == '/' ? "" : curdir(), file1, \ 197 *(file2) == '/' ? "" : curdir(), file2); 198 #define LOGBYTES(cmd, file, cnt) \ 199 if (logging > 1) { \ 200 if (cnt == (off_t)-1) \ 201 syslog(LOG_INFO,"%s %s%s", cmd, \ 202 *(file) == '/' ? "" : curdir(), file); \ 203 else \ 204 syslog(LOG_INFO, "%s %s%s = %qd bytes", \ 205 cmd, (*(file) == '/') ? "" : curdir(), file, cnt); \ 206 } 207 208 static void ack __P((char *)); 209 static void myoob __P((int)); 210 static int checkuser __P((char *, char *)); 211 static FILE *dataconn __P((char *, off_t, char *)); 212 static void dolog __P((struct sockaddr_in *)); 213 static char *curdir __P((void)); 214 static void end_login __P((void)); 215 static FILE *getdatasock __P((char *)); 216 static char *gunique __P((char *)); 217 static void lostconn __P((int)); 218 static int receive_data __P((FILE *, FILE *)); 219 static void send_data __P((FILE *, FILE *, off_t, off_t, int)); 220 static struct passwd * 221 sgetpwnam __P((char *)); 222 static char *sgetsave __P((char *)); 223 static void reapchild __P((int)); 224 static void logxfer __P((char *, long, long)); 225 226 static char * 227 curdir() 228 { 229 static char path[MAXPATHLEN+1+1]; /* path + '/' + '\0' */ 230 231 if (getcwd(path, sizeof(path)-2) == NULL) 232 return (""); 233 if (path[1] != '\0') /* special case for root dir. */ 234 strcat(path, "/"); 235 /* For guest account, skip / since it's chrooted */ 236 return (guest ? path+1 : path); 237 } 238 239 int 240 main(argc, argv, envp) 241 int argc; 242 char *argv[]; 243 char **envp; 244 { 245 int addrlen, ch, on = 1, tos; 246 char *cp, line[LINE_MAX]; 247 FILE *fd; 248 249 tzset(); /* in case no timezone database in ~ftp */ 250 251 #ifdef OLD_SETPROCTITLE 252 /* 253 * Save start and extent of argv for setproctitle. 254 */ 255 Argv = argv; 256 while (*envp) 257 envp++; 258 LastArgv = envp[-1] + strlen(envp[-1]); 259 #endif /* OLD_SETPROCTITLE */ 260 261 262 bind_address.s_addr = htonl(INADDR_ANY); 263 while ((ch = getopt(argc, argv, "AdlDSURt:T:u:va:p:")) != EOF) { 264 switch (ch) { 265 case 'D': 266 daemon_mode++; 267 break; 268 269 case 'd': 270 debug++; 271 break; 272 273 case 'l': 274 logging++; /* > 1 == extra logging */ 275 break; 276 277 case 'R': 278 paranoid = 0; 279 break; 280 281 case 'S': 282 stats++; 283 break; 284 285 case 'T': 286 maxtimeout = atoi(optarg); 287 if (timeout > maxtimeout) 288 timeout = maxtimeout; 289 break; 290 291 case 't': 292 timeout = atoi(optarg); 293 if (maxtimeout < timeout) 294 maxtimeout = timeout; 295 break; 296 297 case 'U': 298 restricted_data_ports = 0; 299 break; 300 301 case 'a': 302 if (!inet_aton(optarg, &bind_address)) 303 errx(1, "invalid address for -a"); 304 break; 305 306 case 'p': 307 pid_file = optarg; 308 break; 309 310 case 'u': 311 { 312 long val = 0; 313 314 val = strtol(optarg, &optarg, 8); 315 if (*optarg != '\0' || val < 0) 316 warnx("bad value for -u"); 317 else 318 defumask = val; 319 break; 320 } 321 case 'A': 322 anon_only = 1; 323 break; 324 325 case 'v': 326 debug = 1; 327 break; 328 329 default: 330 warnx("unknown flag -%c ignored", optopt); 331 break; 332 } 333 } 334 335 (void) freopen(_PATH_DEVNULL, "w", stderr); 336 337 /* 338 * LOG_NDELAY sets up the logging connection immediately, 339 * necessary for anonymous ftp's that chroot and can't do it later. 340 */ 341 openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP); 342 343 if (daemon_mode) { 344 int ctl_sock, fd; 345 struct servent *sv; 346 347 /* 348 * Detach from parent. 349 */ 350 if (daemon(1, 1) < 0) { 351 syslog(LOG_ERR, "failed to become a daemon"); 352 exit(1); 353 } 354 (void) signal(SIGCHLD, reapchild); 355 /* 356 * Get port number for ftp/tcp. 357 */ 358 sv = getservbyname("ftp", "tcp"); 359 if (sv == NULL) { 360 syslog(LOG_ERR, "getservbyname for ftp failed"); 361 exit(1); 362 } 363 /* 364 * Open a socket, bind it to the FTP port, and start 365 * listening. 366 */ 367 ctl_sock = socket(AF_INET, SOCK_STREAM, 0); 368 if (ctl_sock < 0) { 369 syslog(LOG_ERR, "control socket: %m"); 370 exit(1); 371 } 372 if (setsockopt(ctl_sock, SOL_SOCKET, SO_REUSEADDR, 373 (char *)&on, sizeof(on)) < 0) 374 syslog(LOG_ERR, "control setsockopt: %m");; 375 server_addr.sin_family = AF_INET; 376 server_addr.sin_addr = bind_address; 377 server_addr.sin_port = sv->s_port; 378 if (bind(ctl_sock, (struct sockaddr *)&server_addr, sizeof(server_addr))) { 379 syslog(LOG_ERR, "control bind: %m"); 380 exit(1); 381 } 382 if (listen(ctl_sock, 32) < 0) { 383 syslog(LOG_ERR, "control listen: %m"); 384 exit(1); 385 } 386 /* 387 * Atomically write process ID 388 */ 389 if (pid_file) 390 { 391 int fd; 392 char buf[20]; 393 394 fd = open(pid_file, O_CREAT | O_WRONLY | O_TRUNC 395 | O_NONBLOCK | O_EXLOCK, 0644); 396 if (fd < 0) 397 if (errno == EAGAIN) 398 errx(1, "%s: file locked", pid_file); 399 else 400 err(1, "%s", pid_file); 401 snprintf(buf, sizeof(buf), 402 "%lu\n", (unsigned long) getpid()); 403 if (write(fd, buf, strlen(buf)) < 0) 404 err(1, "%s: write", pid_file); 405 /* Leave the pid file open and locked */ 406 } 407 /* 408 * Loop forever accepting connection requests and forking off 409 * children to handle them. 410 */ 411 while (1) { 412 addrlen = sizeof(his_addr); 413 fd = accept(ctl_sock, (struct sockaddr *)&his_addr, &addrlen); 414 if (fork() == 0) { 415 /* child */ 416 (void) dup2(fd, 0); 417 (void) dup2(fd, 1); 418 close(ctl_sock); 419 break; 420 } 421 close(fd); 422 } 423 } else { 424 addrlen = sizeof(his_addr); 425 if (getpeername(0, (struct sockaddr *)&his_addr, &addrlen) < 0) { 426 syslog(LOG_ERR, "getpeername (%s): %m",argv[0]); 427 exit(1); 428 } 429 } 430 431 (void) signal(SIGCHLD, SIG_IGN); 432 (void) signal(SIGPIPE, lostconn); 433 if ((int)signal(SIGURG, myoob) < 0) 434 syslog(LOG_ERR, "signal: %m"); 435 436 #ifdef SKEY 437 strncpy(addr_string, inet_ntoa(his_addr.sin_addr), sizeof(addr_string)); 438 #endif 439 addrlen = sizeof(ctrl_addr); 440 if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) { 441 syslog(LOG_ERR, "getsockname (%s): %m",argv[0]); 442 exit(1); 443 } 444 #ifdef IP_TOS 445 tos = IPTOS_LOWDELAY; 446 if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) 447 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); 448 #endif 449 data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1); 450 451 /* set this here so klogin can use it... */ 452 (void)sprintf(ttyline, "ftp%d", getpid()); 453 454 /* Try to handle urgent data inline */ 455 #ifdef SO_OOBINLINE 456 if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) < 0) 457 syslog(LOG_ERR, "setsockopt: %m"); 458 #endif 459 460 #ifdef F_SETOWN 461 if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1) 462 syslog(LOG_ERR, "fcntl F_SETOWN: %m"); 463 #endif 464 dolog(&his_addr); 465 /* 466 * Set up default state 467 */ 468 data = -1; 469 type = TYPE_A; 470 form = FORM_N; 471 stru = STRU_F; 472 mode = MODE_S; 473 tmpline[0] = '\0'; 474 475 /* If logins are disabled, print out the message. */ 476 if ((fd = fopen(_PATH_NOLOGIN,"r")) != NULL) { 477 while (fgets(line, sizeof(line), fd) != NULL) { 478 if ((cp = strchr(line, '\n')) != NULL) 479 *cp = '\0'; 480 lreply(530, "%s", line); 481 } 482 (void) fflush(stdout); 483 (void) fclose(fd); 484 reply(530, "System not available."); 485 exit(0); 486 } 487 if ((fd = fopen(_PATH_FTPWELCOME, "r")) != NULL) { 488 while (fgets(line, sizeof(line), fd) != NULL) { 489 if ((cp = strchr(line, '\n')) != NULL) 490 *cp = '\0'; 491 lreply(220, "%s", line); 492 } 493 (void) fflush(stdout); 494 (void) fclose(fd); 495 /* reply(220,) must follow */ 496 } 497 (void) gethostname(hostname, sizeof(hostname)); 498 reply(220, "%s FTP server (%s) ready.", hostname, version); 499 (void) setjmp(errcatch); 500 for (;;) 501 (void) yyparse(); 502 /* NOTREACHED */ 503 } 504 505 static void 506 lostconn(signo) 507 int signo; 508 { 509 510 if (debug) 511 syslog(LOG_DEBUG, "lost connection"); 512 dologout(-1); 513 } 514 515 /* 516 * Helper function for sgetpwnam(). 517 */ 518 static char * 519 sgetsave(s) 520 char *s; 521 { 522 char *new = malloc((unsigned) strlen(s) + 1); 523 524 if (new == NULL) { 525 perror_reply(421, "Local resource failure: malloc"); 526 dologout(1); 527 /* NOTREACHED */ 528 } 529 (void) strcpy(new, s); 530 return (new); 531 } 532 533 /* 534 * Save the result of a getpwnam. Used for USER command, since 535 * the data returned must not be clobbered by any other command 536 * (e.g., globbing). 537 */ 538 static struct passwd * 539 sgetpwnam(name) 540 char *name; 541 { 542 static struct passwd save; 543 struct passwd *p; 544 545 if ((p = getpwnam(name)) == NULL) 546 return (p); 547 if (save.pw_name) { 548 free(save.pw_name); 549 free(save.pw_passwd); 550 free(save.pw_gecos); 551 free(save.pw_dir); 552 free(save.pw_shell); 553 } 554 save = *p; 555 save.pw_name = sgetsave(p->pw_name); 556 save.pw_passwd = sgetsave(p->pw_passwd); 557 save.pw_gecos = sgetsave(p->pw_gecos); 558 save.pw_dir = sgetsave(p->pw_dir); 559 save.pw_shell = sgetsave(p->pw_shell); 560 return (&save); 561 } 562 563 static int login_attempts; /* number of failed login attempts */ 564 static int askpasswd; /* had user command, ask for passwd */ 565 static char curname[10]; /* current USER name */ 566 567 /* 568 * USER command. 569 * Sets global passwd pointer pw if named account exists and is acceptable; 570 * sets askpasswd if a PASS command is expected. If logged in previously, 571 * need to reset state. If name is "ftp" or "anonymous", the name is not in 572 * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return. 573 * If account doesn't exist, ask for passwd anyway. Otherwise, check user 574 * requesting login privileges. Disallow anyone who does not have a standard 575 * shell as returned by getusershell(). Disallow anyone mentioned in the file 576 * _PATH_FTPUSERS to allow people such as root and uucp to be avoided. 577 */ 578 void 579 user(name) 580 char *name; 581 { 582 char *cp, *shell; 583 584 if (logged_in) { 585 if (guest) { 586 reply(530, "Can't change user from guest login."); 587 return; 588 } else if (dochroot) { 589 reply(530, "Can't change user from chroot user."); 590 return; 591 } 592 end_login(); 593 } 594 595 guest = 0; 596 if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) { 597 if (checkuser(_PATH_FTPUSERS, "ftp") || 598 checkuser(_PATH_FTPUSERS, "anonymous")) 599 reply(530, "User %s access denied.", name); 600 else if ((pw = sgetpwnam("ftp")) != NULL) { 601 guest = 1; 602 askpasswd = 1; 603 reply(331, 604 "Guest login ok, send your email address as password."); 605 } else 606 reply(530, "User %s unknown.", name); 607 if (!askpasswd && logging) 608 syslog(LOG_NOTICE, 609 "ANONYMOUS FTP LOGIN REFUSED FROM %s", remotehost); 610 return; 611 } 612 if (anon_only != 0) { 613 reply(530, "Sorry, only anonymous ftp allowed."); 614 return; 615 } 616 617 if ((pw = sgetpwnam(name))) { 618 if ((shell = pw->pw_shell) == NULL || *shell == 0) 619 shell = _PATH_BSHELL; 620 while ((cp = getusershell()) != NULL) 621 if (strcmp(cp, shell) == 0) 622 break; 623 endusershell(); 624 625 if (cp == NULL || checkuser(_PATH_FTPUSERS, name)) { 626 reply(530, "User %s access denied.", name); 627 if (logging) 628 syslog(LOG_NOTICE, 629 "FTP LOGIN REFUSED FROM %s, %s", 630 remotehost, name); 631 pw = (struct passwd *) NULL; 632 return; 633 } 634 } 635 if (logging) 636 strncpy(curname, name, sizeof(curname)-1); 637 #ifdef SKEY 638 pwok = skeyaccess(name, NULL, remotehost, addr_string); 639 reply(331, "%s", skey_challenge(name, pw, pwok)); 640 #else 641 reply(331, "Password required for %s.", name); 642 #endif 643 askpasswd = 1; 644 /* 645 * Delay before reading passwd after first failed 646 * attempt to slow down passwd-guessing programs. 647 */ 648 if (login_attempts) 649 sleep((unsigned) login_attempts); 650 } 651 652 /* 653 * Check if a user is in the file "fname" 654 */ 655 static int 656 checkuser(fname, name) 657 char *fname; 658 char *name; 659 { 660 FILE *fd; 661 int found = 0; 662 char *p, line[BUFSIZ]; 663 664 if ((fd = fopen(fname, "r")) != NULL) { 665 while (fgets(line, sizeof(line), fd) != NULL) 666 if ((p = strchr(line, '\n')) != NULL) { 667 *p = '\0'; 668 if (line[0] == '#') 669 continue; 670 if (strcmp(line, name) == 0) { 671 found = 1; 672 break; 673 } 674 } 675 (void) fclose(fd); 676 } 677 return (found); 678 } 679 680 /* 681 * Terminate login as previous user, if any, resetting state; 682 * used when USER command is given or login fails. 683 */ 684 static void 685 end_login() 686 { 687 688 (void) seteuid((uid_t)0); 689 if (logged_in) 690 logwtmp(ttyline, "", ""); 691 pw = NULL; 692 logged_in = 0; 693 guest = 0; 694 dochroot = 0; 695 } 696 697 void 698 pass(passwd) 699 char *passwd; 700 { 701 int rval; 702 FILE *fd; 703 static char homedir[MAXPATHLEN]; 704 705 if (logged_in || askpasswd == 0) { 706 reply(503, "Login with USER first."); 707 return; 708 } 709 askpasswd = 0; 710 if (!guest) { /* "ftp" is only account allowed no password */ 711 if (pw == NULL) { 712 rval = 1; /* failure below */ 713 goto skip; 714 } 715 #if defined(KERBEROS) 716 rval = klogin(pw, "", hostname, passwd); 717 if (rval == 0) 718 goto skip; 719 #endif 720 #ifdef SKEY 721 rval = strcmp(skey_crypt(passwd, pw->pw_passwd, pw, pwok), 722 pw->pw_passwd); 723 pwok = 0; 724 #else 725 rval = strcmp(crypt(passwd, pw->pw_passwd), pw->pw_passwd); 726 #endif 727 /* The strcmp does not catch null passwords! */ 728 if (*pw->pw_passwd == '\0' || 729 (pw->pw_expire && time(NULL) >= pw->pw_expire)) 730 rval = 1; /* failure */ 731 skip: 732 /* 733 * If rval == 1, the user failed the authentication check 734 * above. If rval == 0, either Kerberos or local authentication 735 * succeeded. 736 */ 737 if (rval) { 738 reply(530, "Login incorrect."); 739 if (logging) 740 syslog(LOG_NOTICE, 741 "FTP LOGIN FAILED FROM %s, %s", 742 remotehost, curname); 743 pw = NULL; 744 if (login_attempts++ >= 5) { 745 syslog(LOG_NOTICE, 746 "repeated login failures from %s", 747 remotehost); 748 exit(0); 749 } 750 return; 751 } 752 } 753 login_attempts = 0; /* this time successful */ 754 if (setegid((gid_t)pw->pw_gid) < 0) { 755 reply(550, "Can't set gid."); 756 return; 757 } 758 (void) initgroups(pw->pw_name, pw->pw_gid); 759 760 /* open wtmp before chroot */ 761 logwtmp(ttyline, pw->pw_name, remotehost); 762 logged_in = 1; 763 764 if (guest && stats && statfd < 0) 765 if ((statfd = open(_PATH_FTPDSTATFILE, O_WRONLY|O_APPEND)) < 0) 766 stats = 0; 767 768 dochroot = checkuser(_PATH_FTPCHROOT, pw->pw_name); 769 if (guest) { 770 /* 771 * We MUST do a chdir() after the chroot. Otherwise 772 * the old current directory will be accessible as "." 773 * outside the new root! 774 */ 775 if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) { 776 reply(550, "Can't set guest privileges."); 777 goto bad; 778 } 779 } else if (dochroot) { 780 if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) { 781 reply(550, "Can't change root."); 782 goto bad; 783 } 784 } else if (chdir(pw->pw_dir) < 0) { 785 if (chdir("/") < 0) { 786 reply(530, "User %s: can't change directory to %s.", 787 pw->pw_name, pw->pw_dir); 788 goto bad; 789 } else 790 lreply(230, "No directory! Logging in with home=/"); 791 } 792 if (seteuid((uid_t)pw->pw_uid) < 0) { 793 reply(550, "Can't set uid."); 794 goto bad; 795 } 796 797 /* 798 * Set home directory so that use of ~ (tilde) works correctly. 799 */ 800 if (getcwd(homedir, MAXPATHLEN) != NULL) 801 setenv("HOME", homedir, 1); 802 803 /* 804 * Display a login message, if it exists. 805 * N.B. reply(230,) must follow the message. 806 */ 807 if ((fd = fopen(_PATH_FTPLOGINMESG, "r")) != NULL) { 808 char *cp, line[LINE_MAX]; 809 810 while (fgets(line, sizeof(line), fd) != NULL) { 811 if ((cp = strchr(line, '\n')) != NULL) 812 *cp = '\0'; 813 lreply(230, "%s", line); 814 } 815 (void) fflush(stdout); 816 (void) fclose(fd); 817 } 818 if (guest) { 819 if (ident != NULL) 820 free(ident); 821 ident = strdup(passwd); 822 if (ident == NULL) 823 fatal("Ran out of memory."); 824 825 reply(230, "Guest login ok, access restrictions apply."); 826 #ifdef SETPROCTITLE 827 snprintf(proctitle, sizeof(proctitle), 828 "%s: anonymous/%.*s", remotehost, 829 sizeof(proctitle) - sizeof(remotehost) - 830 sizeof(": anonymous/"), passwd); 831 setproctitle("%s", proctitle); 832 #endif /* SETPROCTITLE */ 833 if (logging) 834 syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s", 835 remotehost, passwd); 836 } else { 837 reply(230, "User %s logged in.", pw->pw_name); 838 #ifdef SETPROCTITLE 839 snprintf(proctitle, sizeof(proctitle), 840 "%s: %s", remotehost, pw->pw_name); 841 setproctitle("%s", proctitle); 842 #endif /* SETPROCTITLE */ 843 if (logging) 844 syslog(LOG_INFO, "FTP LOGIN FROM %s as %s", 845 remotehost, pw->pw_name); 846 } 847 (void) umask(defumask); 848 return; 849 bad: 850 /* Forget all about it... */ 851 end_login(); 852 } 853 854 void 855 retrieve(cmd, name) 856 char *cmd, *name; 857 { 858 FILE *fin, *dout; 859 struct stat st; 860 int (*closefunc) __P((FILE *)); 861 long start; 862 863 if (cmd == 0) { 864 fin = fopen(name, "r"), closefunc = fclose; 865 st.st_size = 0; 866 } else { 867 char line[BUFSIZ]; 868 869 (void) sprintf(line, cmd, name), name = line; 870 fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose; 871 st.st_size = -1; 872 st.st_blksize = BUFSIZ; 873 } 874 if (fin == NULL) { 875 if (errno != 0) { 876 perror_reply(550, name); 877 if (cmd == 0) { 878 LOGCMD("get", name); 879 } 880 } 881 return; 882 } 883 byte_count = -1; 884 if (cmd == 0 && (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode))) { 885 reply(550, "%s: not a plain file.", name); 886 goto done; 887 } 888 if (restart_point) { 889 if (type == TYPE_A) { 890 off_t i, n; 891 int c; 892 893 n = restart_point; 894 i = 0; 895 while (i++ < n) { 896 if ((c=getc(fin)) == EOF) { 897 perror_reply(550, name); 898 goto done; 899 } 900 if (c == '\n') 901 i++; 902 } 903 } else if (lseek(fileno(fin), restart_point, L_SET) < 0) { 904 perror_reply(550, name); 905 goto done; 906 } 907 } 908 dout = dataconn(name, st.st_size, "w"); 909 if (dout == NULL) 910 goto done; 911 time(&start); 912 send_data(fin, dout, st.st_blksize, st.st_size, 913 restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode)); 914 if (cmd == 0 && guest && stats) 915 logxfer(name, st.st_size, start); 916 (void) fclose(dout); 917 data = -1; 918 pdata = -1; 919 done: 920 if (cmd == 0) 921 LOGBYTES("get", name, byte_count); 922 (*closefunc)(fin); 923 } 924 925 void 926 store(name, mode, unique) 927 char *name, *mode; 928 int unique; 929 { 930 FILE *fout, *din; 931 struct stat st; 932 int (*closefunc) __P((FILE *)); 933 934 if ((unique || guest) && stat(name, &st) == 0 && 935 (name = gunique(name)) == NULL) { 936 LOGCMD(*mode == 'w' ? "put" : "append", name); 937 return; 938 } 939 940 if (restart_point) 941 mode = "r+"; 942 fout = fopen(name, mode); 943 closefunc = fclose; 944 if (fout == NULL) { 945 perror_reply(553, name); 946 LOGCMD(*mode == 'w' ? "put" : "append", name); 947 return; 948 } 949 byte_count = -1; 950 if (restart_point) { 951 if (type == TYPE_A) { 952 off_t i, n; 953 int c; 954 955 n = restart_point; 956 i = 0; 957 while (i++ < n) { 958 if ((c=getc(fout)) == EOF) { 959 perror_reply(550, name); 960 goto done; 961 } 962 if (c == '\n') 963 i++; 964 } 965 /* 966 * We must do this seek to "current" position 967 * because we are changing from reading to 968 * writing. 969 */ 970 if (fseek(fout, 0L, L_INCR) < 0) { 971 perror_reply(550, name); 972 goto done; 973 } 974 } else if (lseek(fileno(fout), restart_point, L_SET) < 0) { 975 perror_reply(550, name); 976 goto done; 977 } 978 } 979 din = dataconn(name, (off_t)-1, "r"); 980 if (din == NULL) 981 goto done; 982 if (receive_data(din, fout) == 0) { 983 if (unique) 984 reply(226, "Transfer complete (unique file name:%s).", 985 name); 986 else 987 reply(226, "Transfer complete."); 988 } 989 (void) fclose(din); 990 data = -1; 991 pdata = -1; 992 done: 993 LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count); 994 (*closefunc)(fout); 995 } 996 997 static FILE * 998 getdatasock(mode) 999 char *mode; 1000 { 1001 int on = 1, s, t, tries; 1002 1003 if (data >= 0) 1004 return (fdopen(data, mode)); 1005 (void) seteuid((uid_t)0); 1006 s = socket(AF_INET, SOCK_STREAM, 0); 1007 if (s < 0) 1008 goto bad; 1009 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 1010 (char *) &on, sizeof(on)) < 0) 1011 goto bad; 1012 /* anchor socket to avoid multi-homing problems */ 1013 data_source.sin_len = sizeof(struct sockaddr_in); 1014 data_source.sin_family = AF_INET; 1015 data_source.sin_addr = ctrl_addr.sin_addr; 1016 for (tries = 1; ; tries++) { 1017 if (bind(s, (struct sockaddr *)&data_source, 1018 sizeof(data_source)) >= 0) 1019 break; 1020 if (errno != EADDRINUSE || tries > 10) 1021 goto bad; 1022 sleep(tries); 1023 } 1024 (void) seteuid((uid_t)pw->pw_uid); 1025 #ifdef IP_TOS 1026 on = IPTOS_THROUGHPUT; 1027 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) 1028 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); 1029 #endif 1030 #ifdef TCP_NOPUSH 1031 /* 1032 * Turn off push flag to keep sender TCP from sending short packets 1033 * at the boundaries of each write(). Should probably do a SO_SNDBUF 1034 * to set the send buffer size as well, but that may not be desirable 1035 * in heavy-load situations. 1036 */ 1037 on = 1; 1038 if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, (char *)&on, sizeof on) < 0) 1039 syslog(LOG_WARNING, "setsockopt (TCP_NOPUSH): %m"); 1040 #endif 1041 #ifdef SO_SNDBUF 1042 on = 65536; 1043 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&on, sizeof on) < 0) 1044 syslog(LOG_WARNING, "setsockopt (SO_SNDBUF): %m"); 1045 #endif 1046 1047 return (fdopen(s, mode)); 1048 bad: 1049 /* Return the real value of errno (close may change it) */ 1050 t = errno; 1051 (void) seteuid((uid_t)pw->pw_uid); 1052 (void) close(s); 1053 errno = t; 1054 return (NULL); 1055 } 1056 1057 static FILE * 1058 dataconn(name, size, mode) 1059 char *name; 1060 off_t size; 1061 char *mode; 1062 { 1063 char sizebuf[32]; 1064 FILE *file; 1065 int retry = 0, tos; 1066 1067 file_size = size; 1068 byte_count = 0; 1069 if (size != (off_t) -1) 1070 (void) sprintf(sizebuf, " (%qd bytes)", size); 1071 else 1072 (void) strcpy(sizebuf, ""); 1073 if (pdata >= 0) { 1074 struct sockaddr_in from; 1075 int s, fromlen = sizeof(from); 1076 struct timeval timeout; 1077 fd_set set; 1078 1079 FD_ZERO(&set); 1080 FD_SET(pdata, &set); 1081 1082 timeout.tv_usec = 0; 1083 timeout.tv_sec = 120; 1084 1085 if (select(pdata+1, &set, (fd_set *) 0, (fd_set *) 0, &timeout) == 0 || 1086 (s = accept(pdata, (struct sockaddr *) &from, &fromlen)) < 0) { 1087 reply(425, "Can't open data connection."); 1088 (void) close(pdata); 1089 pdata = -1; 1090 return (NULL); 1091 } 1092 (void) close(pdata); 1093 pdata = s; 1094 #ifdef IP_TOS 1095 tos = IPTOS_THROUGHPUT; 1096 (void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, 1097 sizeof(int)); 1098 #endif 1099 reply(150, "Opening %s mode data connection for '%s'%s.", 1100 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); 1101 return (fdopen(pdata, mode)); 1102 } 1103 if (data >= 0) { 1104 reply(125, "Using existing data connection for '%s'%s.", 1105 name, sizebuf); 1106 usedefault = 1; 1107 return (fdopen(data, mode)); 1108 } 1109 if (usedefault) 1110 data_dest = his_addr; 1111 usedefault = 1; 1112 file = getdatasock(mode); 1113 if (file == NULL) { 1114 reply(425, "Can't create data socket (%s,%d): %s.", 1115 inet_ntoa(data_source.sin_addr), 1116 ntohs(data_source.sin_port), strerror(errno)); 1117 return (NULL); 1118 } 1119 data = fileno(file); 1120 while (connect(data, (struct sockaddr *)&data_dest, 1121 sizeof(data_dest)) < 0) { 1122 if (errno == EADDRINUSE && retry < swaitmax) { 1123 sleep((unsigned) swaitint); 1124 retry += swaitint; 1125 continue; 1126 } 1127 perror_reply(425, "Can't build data connection"); 1128 (void) fclose(file); 1129 data = -1; 1130 return (NULL); 1131 } 1132 reply(150, "Opening %s mode data connection for '%s'%s.", 1133 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); 1134 return (file); 1135 } 1136 1137 /* 1138 * Tranfer the contents of "instr" to "outstr" peer using the appropriate 1139 * encapsulation of the data subject to Mode, Structure, and Type. 1140 * 1141 * NB: Form isn't handled. 1142 */ 1143 static void 1144 send_data(instr, outstr, blksize, filesize, isreg) 1145 FILE *instr, *outstr; 1146 off_t blksize; 1147 off_t filesize; 1148 int isreg; 1149 { 1150 int c, cnt, filefd, netfd; 1151 char *buf, *bp; 1152 size_t len; 1153 1154 transflag++; 1155 if (setjmp(urgcatch)) { 1156 transflag = 0; 1157 return; 1158 } 1159 switch (type) { 1160 1161 case TYPE_A: 1162 while ((c = getc(instr)) != EOF) { 1163 byte_count++; 1164 if (c == '\n') { 1165 if (ferror(outstr)) 1166 goto data_err; 1167 (void) putc('\r', outstr); 1168 } 1169 (void) putc(c, outstr); 1170 } 1171 fflush(outstr); 1172 transflag = 0; 1173 if (ferror(instr)) 1174 goto file_err; 1175 if (ferror(outstr)) 1176 goto data_err; 1177 reply(226, "Transfer complete."); 1178 return; 1179 1180 case TYPE_I: 1181 case TYPE_L: 1182 /* 1183 * isreg is only set if we are not doing restart and we 1184 * are sending a regular file 1185 */ 1186 netfd = fileno(outstr); 1187 filefd = fileno(instr); 1188 1189 if (isreg && filesize < (off_t)16 * 1024 * 1024) { 1190 buf = mmap(0, filesize, PROT_READ, MAP_SHARED, filefd, 1191 (off_t)0); 1192 if (buf == MAP_FAILED) { 1193 syslog(LOG_WARNING, "mmap(%lu): %m", 1194 (unsigned long)filesize); 1195 goto oldway; 1196 } 1197 bp = buf; 1198 len = filesize; 1199 do { 1200 cnt = write(netfd, bp, len); 1201 len -= cnt; 1202 bp += cnt; 1203 if (cnt > 0) byte_count += cnt; 1204 } while(cnt > 0 && len > 0); 1205 1206 transflag = 0; 1207 munmap(buf, (size_t)filesize); 1208 if (cnt < 0) 1209 goto data_err; 1210 reply(226, "Transfer complete."); 1211 return; 1212 } 1213 1214 oldway: 1215 if ((buf = malloc((u_int)blksize)) == NULL) { 1216 transflag = 0; 1217 perror_reply(451, "Local resource failure: malloc"); 1218 return; 1219 } 1220 1221 while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 && 1222 write(netfd, buf, cnt) == cnt) 1223 byte_count += cnt; 1224 transflag = 0; 1225 (void)free(buf); 1226 if (cnt != 0) { 1227 if (cnt < 0) 1228 goto file_err; 1229 goto data_err; 1230 } 1231 reply(226, "Transfer complete."); 1232 return; 1233 default: 1234 transflag = 0; 1235 reply(550, "Unimplemented TYPE %d in send_data", type); 1236 return; 1237 } 1238 1239 data_err: 1240 transflag = 0; 1241 perror_reply(426, "Data connection"); 1242 return; 1243 1244 file_err: 1245 transflag = 0; 1246 perror_reply(551, "Error on input file"); 1247 } 1248 1249 /* 1250 * Transfer data from peer to "outstr" using the appropriate encapulation of 1251 * the data subject to Mode, Structure, and Type. 1252 * 1253 * N.B.: Form isn't handled. 1254 */ 1255 static int 1256 receive_data(instr, outstr) 1257 FILE *instr, *outstr; 1258 { 1259 int c; 1260 int cnt, bare_lfs; 1261 char buf[BUFSIZ]; 1262 1263 transflag++; 1264 if (setjmp(urgcatch)) { 1265 transflag = 0; 1266 return (-1); 1267 } 1268 1269 bare_lfs = 0; 1270 1271 switch (type) { 1272 1273 case TYPE_I: 1274 case TYPE_L: 1275 while ((cnt = read(fileno(instr), buf, sizeof(buf))) > 0) { 1276 if (write(fileno(outstr), buf, cnt) != cnt) 1277 goto file_err; 1278 byte_count += cnt; 1279 } 1280 if (cnt < 0) 1281 goto data_err; 1282 transflag = 0; 1283 return (0); 1284 1285 case TYPE_E: 1286 reply(553, "TYPE E not implemented."); 1287 transflag = 0; 1288 return (-1); 1289 1290 case TYPE_A: 1291 while ((c = getc(instr)) != EOF) { 1292 byte_count++; 1293 if (c == '\n') 1294 bare_lfs++; 1295 while (c == '\r') { 1296 if (ferror(outstr)) 1297 goto data_err; 1298 if ((c = getc(instr)) != '\n') { 1299 (void) putc ('\r', outstr); 1300 if (c == '\0' || c == EOF) 1301 goto contin2; 1302 } 1303 } 1304 (void) putc(c, outstr); 1305 contin2: ; 1306 } 1307 fflush(outstr); 1308 if (ferror(instr)) 1309 goto data_err; 1310 if (ferror(outstr)) 1311 goto file_err; 1312 transflag = 0; 1313 if (bare_lfs) { 1314 lreply(226, 1315 "WARNING! %d bare linefeeds received in ASCII mode", 1316 bare_lfs); 1317 (void)printf(" File may not have transferred correctly.\r\n"); 1318 } 1319 return (0); 1320 default: 1321 reply(550, "Unimplemented TYPE %d in receive_data", type); 1322 transflag = 0; 1323 return (-1); 1324 } 1325 1326 data_err: 1327 transflag = 0; 1328 perror_reply(426, "Data Connection"); 1329 return (-1); 1330 1331 file_err: 1332 transflag = 0; 1333 perror_reply(452, "Error writing file"); 1334 return (-1); 1335 } 1336 1337 void 1338 statfilecmd(filename) 1339 char *filename; 1340 { 1341 FILE *fin; 1342 int c; 1343 char line[LINE_MAX]; 1344 1345 (void)snprintf(line, sizeof(line), "/bin/ls -lgA %s", filename); 1346 fin = ftpd_popen(line, "r"); 1347 lreply(211, "status of %s:", filename); 1348 while ((c = getc(fin)) != EOF) { 1349 if (c == '\n') { 1350 if (ferror(stdout)){ 1351 perror_reply(421, "control connection"); 1352 (void) ftpd_pclose(fin); 1353 dologout(1); 1354 /* NOTREACHED */ 1355 } 1356 if (ferror(fin)) { 1357 perror_reply(551, filename); 1358 (void) ftpd_pclose(fin); 1359 return; 1360 } 1361 (void) putc('\r', stdout); 1362 } 1363 (void) putc(c, stdout); 1364 } 1365 (void) ftpd_pclose(fin); 1366 reply(211, "End of Status"); 1367 } 1368 1369 void 1370 statcmd() 1371 { 1372 struct sockaddr_in *sin; 1373 u_char *a, *p; 1374 1375 lreply(211, "%s FTP server status:", hostname, version); 1376 printf(" %s\r\n", version); 1377 printf(" Connected to %s", remotehost); 1378 if (!isdigit(remotehost[0])) 1379 printf(" (%s)", inet_ntoa(his_addr.sin_addr)); 1380 printf("\r\n"); 1381 if (logged_in) { 1382 if (guest) 1383 printf(" Logged in anonymously\r\n"); 1384 else 1385 printf(" Logged in as %s\r\n", pw->pw_name); 1386 } else if (askpasswd) 1387 printf(" Waiting for password\r\n"); 1388 else 1389 printf(" Waiting for user name\r\n"); 1390 printf(" TYPE: %s", typenames[type]); 1391 if (type == TYPE_A || type == TYPE_E) 1392 printf(", FORM: %s", formnames[form]); 1393 if (type == TYPE_L) 1394 #if NBBY == 8 1395 printf(" %d", NBBY); 1396 #else 1397 printf(" %d", bytesize); /* need definition! */ 1398 #endif 1399 printf("; STRUcture: %s; transfer MODE: %s\r\n", 1400 strunames[stru], modenames[mode]); 1401 if (data != -1) 1402 printf(" Data connection open\r\n"); 1403 else if (pdata != -1) { 1404 printf(" in Passive mode"); 1405 sin = &pasv_addr; 1406 goto printaddr; 1407 } else if (usedefault == 0) { 1408 printf(" PORT"); 1409 sin = &data_dest; 1410 printaddr: 1411 a = (u_char *) &sin->sin_addr; 1412 p = (u_char *) &sin->sin_port; 1413 #define UC(b) (((int) b) & 0xff) 1414 printf(" (%d,%d,%d,%d,%d,%d)\r\n", UC(a[0]), 1415 UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); 1416 #undef UC 1417 } else 1418 printf(" No data connection\r\n"); 1419 reply(211, "End of status"); 1420 } 1421 1422 void 1423 fatal(s) 1424 char *s; 1425 { 1426 1427 reply(451, "Error in server: %s\n", s); 1428 reply(221, "Closing connection due to server error."); 1429 dologout(0); 1430 /* NOTREACHED */ 1431 } 1432 1433 void 1434 #if __STDC__ 1435 reply(int n, const char *fmt, ...) 1436 #else 1437 reply(n, fmt, va_alist) 1438 int n; 1439 char *fmt; 1440 va_dcl 1441 #endif 1442 { 1443 va_list ap; 1444 #if __STDC__ 1445 va_start(ap, fmt); 1446 #else 1447 va_start(ap); 1448 #endif 1449 (void)printf("%d ", n); 1450 (void)vprintf(fmt, ap); 1451 (void)printf("\r\n"); 1452 (void)fflush(stdout); 1453 if (debug) { 1454 syslog(LOG_DEBUG, "<--- %d ", n); 1455 vsyslog(LOG_DEBUG, fmt, ap); 1456 } 1457 } 1458 1459 void 1460 #if __STDC__ 1461 lreply(int n, const char *fmt, ...) 1462 #else 1463 lreply(n, fmt, va_alist) 1464 int n; 1465 char *fmt; 1466 va_dcl 1467 #endif 1468 { 1469 va_list ap; 1470 #if __STDC__ 1471 va_start(ap, fmt); 1472 #else 1473 va_start(ap); 1474 #endif 1475 (void)printf("%d- ", n); 1476 (void)vprintf(fmt, ap); 1477 (void)printf("\r\n"); 1478 (void)fflush(stdout); 1479 if (debug) { 1480 syslog(LOG_DEBUG, "<--- %d- ", n); 1481 vsyslog(LOG_DEBUG, fmt, ap); 1482 } 1483 } 1484 1485 static void 1486 ack(s) 1487 char *s; 1488 { 1489 1490 reply(250, "%s command successful.", s); 1491 } 1492 1493 void 1494 nack(s) 1495 char *s; 1496 { 1497 1498 reply(502, "%s command not implemented.", s); 1499 } 1500 1501 /* ARGSUSED */ 1502 void 1503 yyerror(s) 1504 char *s; 1505 { 1506 char *cp; 1507 1508 if ((cp = strchr(cbuf,'\n'))) 1509 *cp = '\0'; 1510 reply(500, "'%s': command not understood.", cbuf); 1511 } 1512 1513 void 1514 delete(name) 1515 char *name; 1516 { 1517 struct stat st; 1518 1519 LOGCMD("delete", name); 1520 if (stat(name, &st) < 0) { 1521 perror_reply(550, name); 1522 return; 1523 } 1524 if ((st.st_mode&S_IFMT) == S_IFDIR) { 1525 if (rmdir(name) < 0) { 1526 perror_reply(550, name); 1527 return; 1528 } 1529 goto done; 1530 } 1531 if (unlink(name) < 0) { 1532 perror_reply(550, name); 1533 return; 1534 } 1535 done: 1536 ack("DELE"); 1537 } 1538 1539 void 1540 cwd(path) 1541 char *path; 1542 { 1543 1544 if (chdir(path) < 0) 1545 perror_reply(550, path); 1546 else 1547 ack("CWD"); 1548 } 1549 1550 void 1551 makedir(name) 1552 char *name; 1553 { 1554 1555 LOGCMD("mkdir", name); 1556 if (mkdir(name, 0777) < 0) 1557 perror_reply(550, name); 1558 else 1559 reply(257, "MKD command successful."); 1560 } 1561 1562 void 1563 removedir(name) 1564 char *name; 1565 { 1566 1567 LOGCMD("rmdir", name); 1568 if (rmdir(name) < 0) 1569 perror_reply(550, name); 1570 else 1571 ack("RMD"); 1572 } 1573 1574 void 1575 pwd() 1576 { 1577 char path[MAXPATHLEN + 1]; 1578 1579 if (getwd(path) == (char *)NULL) 1580 reply(550, "%s.", path); 1581 else 1582 reply(257, "\"%s\" is current directory.", path); 1583 } 1584 1585 char * 1586 renamefrom(name) 1587 char *name; 1588 { 1589 struct stat st; 1590 1591 if (stat(name, &st) < 0) { 1592 perror_reply(550, name); 1593 return ((char *)0); 1594 } 1595 reply(350, "File exists, ready for destination name"); 1596 return (name); 1597 } 1598 1599 void 1600 renamecmd(from, to) 1601 char *from, *to; 1602 { 1603 struct stat st; 1604 1605 LOGCMD2("rename", from, to); 1606 1607 if (guest && (stat(to, &st) == 0)) { 1608 reply(550, "%s: permission denied", to); 1609 return; 1610 } 1611 1612 if (rename(from, to) < 0) 1613 perror_reply(550, "rename"); 1614 else 1615 ack("RNTO"); 1616 } 1617 1618 static void 1619 dolog(sin) 1620 struct sockaddr_in *sin; 1621 { 1622 struct hostent *hp = gethostbyaddr((char *)&sin->sin_addr, 1623 sizeof(struct in_addr), AF_INET); 1624 1625 if (hp) 1626 (void) strncpy(remotehost, hp->h_name, sizeof(remotehost)); 1627 else 1628 (void) strncpy(remotehost, inet_ntoa(sin->sin_addr), 1629 sizeof(remotehost)); 1630 #ifdef SETPROCTITLE 1631 snprintf(proctitle, sizeof(proctitle), "%s: connected", remotehost); 1632 setproctitle("%s", proctitle); 1633 #endif /* SETPROCTITLE */ 1634 1635 if (logging) 1636 syslog(LOG_INFO, "connection from %s", remotehost); 1637 } 1638 1639 /* 1640 * Record logout in wtmp file 1641 * and exit with supplied status. 1642 */ 1643 void 1644 dologout(status) 1645 int status; 1646 { 1647 /* 1648 * Prevent reception of SIGURG from resulting in a resumption 1649 * back to the main program loop. 1650 */ 1651 transflag = 0; 1652 1653 if (logged_in) { 1654 (void) seteuid((uid_t)0); 1655 logwtmp(ttyline, "", ""); 1656 #if defined(KERBEROS) 1657 if (!notickets && krbtkfile_env) 1658 unlink(krbtkfile_env); 1659 #endif 1660 } 1661 /* beware of flushing buffers after a SIGPIPE */ 1662 _exit(status); 1663 } 1664 1665 static void 1666 myoob(signo) 1667 int signo; 1668 { 1669 char *cp; 1670 1671 /* only process if transfer occurring */ 1672 if (!transflag) 1673 return; 1674 cp = tmpline; 1675 if (getline(cp, 7, stdin) == NULL) { 1676 reply(221, "You could at least say goodbye."); 1677 dologout(0); 1678 } 1679 upper(cp); 1680 if (strcmp(cp, "ABOR\r\n") == 0) { 1681 tmpline[0] = '\0'; 1682 reply(426, "Transfer aborted. Data connection closed."); 1683 reply(226, "Abort successful"); 1684 longjmp(urgcatch, 1); 1685 } 1686 if (strcmp(cp, "STAT\r\n") == 0) { 1687 if (file_size != (off_t) -1) 1688 reply(213, "Status: %qd of %qd bytes transferred", 1689 byte_count, file_size); 1690 else 1691 reply(213, "Status: %qd bytes transferred", byte_count); 1692 } 1693 } 1694 1695 /* 1696 * Note: a response of 425 is not mentioned as a possible response to 1697 * the PASV command in RFC959. However, it has been blessed as 1698 * a legitimate response by Jon Postel in a telephone conversation 1699 * with Rick Adams on 25 Jan 89. 1700 */ 1701 void 1702 passive() 1703 { 1704 int len; 1705 char *p, *a; 1706 1707 if (pdata >= 0) /* close old port if one set */ 1708 close(pdata); 1709 1710 pdata = socket(AF_INET, SOCK_STREAM, 0); 1711 if (pdata < 0) { 1712 perror_reply(425, "Can't open passive connection"); 1713 return; 1714 } 1715 1716 (void) seteuid((uid_t)0); 1717 1718 #ifdef IP_PORTRANGE 1719 { 1720 int on = restricted_data_ports ? IP_PORTRANGE_HIGH 1721 : IP_PORTRANGE_DEFAULT; 1722 1723 if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE, 1724 (char *)&on, sizeof(on)) < 0) 1725 goto pasv_error; 1726 } 1727 #endif 1728 1729 pasv_addr = ctrl_addr; 1730 pasv_addr.sin_port = 0; 1731 if (bind(pdata, (struct sockaddr *)&pasv_addr, 1732 sizeof(pasv_addr)) < 0) 1733 goto pasv_error; 1734 1735 (void) seteuid((uid_t)pw->pw_uid); 1736 1737 len = sizeof(pasv_addr); 1738 if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0) 1739 goto pasv_error; 1740 if (listen(pdata, 1) < 0) 1741 goto pasv_error; 1742 a = (char *) &pasv_addr.sin_addr; 1743 p = (char *) &pasv_addr.sin_port; 1744 1745 #define UC(b) (((int) b) & 0xff) 1746 1747 reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]), 1748 UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); 1749 return; 1750 1751 pasv_error: 1752 (void) seteuid((uid_t)pw->pw_uid); 1753 (void) close(pdata); 1754 pdata = -1; 1755 perror_reply(425, "Can't open passive connection"); 1756 return; 1757 } 1758 1759 /* 1760 * Generate unique name for file with basename "local". 1761 * The file named "local" is already known to exist. 1762 * Generates failure reply on error. 1763 */ 1764 static char * 1765 gunique(local) 1766 char *local; 1767 { 1768 static char new[MAXPATHLEN]; 1769 struct stat st; 1770 int count; 1771 char *cp; 1772 1773 cp = strrchr(local, '/'); 1774 if (cp) 1775 *cp = '\0'; 1776 if (stat(cp ? local : ".", &st) < 0) { 1777 perror_reply(553, cp ? local : "."); 1778 return ((char *) 0); 1779 } 1780 if (cp) 1781 *cp = '/'; 1782 (void) snprintf(new, sizeof(new), "%s", local); 1783 cp = new + strlen(new); 1784 *cp++ = '.'; 1785 for (count = 1; count < 100; count++) { 1786 (void)sprintf(cp, "%d", count); 1787 if (stat(new, &st) < 0) 1788 return (new); 1789 } 1790 reply(452, "Unique file name cannot be created."); 1791 return (NULL); 1792 } 1793 1794 /* 1795 * Format and send reply containing system error number. 1796 */ 1797 void 1798 perror_reply(code, string) 1799 int code; 1800 char *string; 1801 { 1802 1803 reply(code, "%s: %s.", string, strerror(errno)); 1804 } 1805 1806 static char *onefile[] = { 1807 "", 1808 0 1809 }; 1810 1811 void 1812 send_file_list(whichf) 1813 char *whichf; 1814 { 1815 struct stat st; 1816 DIR *dirp = NULL; 1817 struct dirent *dir; 1818 FILE *dout = NULL; 1819 char **dirlist, *dirname; 1820 int simple = 0; 1821 int freeglob = 0; 1822 glob_t gl; 1823 1824 if (strpbrk(whichf, "~{[*?") != NULL) { 1825 int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE; 1826 1827 memset(&gl, 0, sizeof(gl)); 1828 freeglob = 1; 1829 if (glob(whichf, flags, 0, &gl)) { 1830 reply(550, "not found"); 1831 goto out; 1832 } else if (gl.gl_pathc == 0) { 1833 errno = ENOENT; 1834 perror_reply(550, whichf); 1835 goto out; 1836 } 1837 dirlist = gl.gl_pathv; 1838 } else { 1839 onefile[0] = whichf; 1840 dirlist = onefile; 1841 simple = 1; 1842 } 1843 1844 if (setjmp(urgcatch)) { 1845 transflag = 0; 1846 goto out; 1847 } 1848 while ((dirname = *dirlist++)) { 1849 if (stat(dirname, &st) < 0) { 1850 /* 1851 * If user typed "ls -l", etc, and the client 1852 * used NLST, do what the user meant. 1853 */ 1854 if (dirname[0] == '-' && *dirlist == NULL && 1855 transflag == 0) { 1856 retrieve("/bin/ls %s", dirname); 1857 goto out; 1858 } 1859 perror_reply(550, whichf); 1860 if (dout != NULL) { 1861 (void) fclose(dout); 1862 transflag = 0; 1863 data = -1; 1864 pdata = -1; 1865 } 1866 goto out; 1867 } 1868 1869 if (S_ISREG(st.st_mode)) { 1870 if (dout == NULL) { 1871 dout = dataconn("file list", (off_t)-1, "w"); 1872 if (dout == NULL) 1873 goto out; 1874 transflag++; 1875 } 1876 fprintf(dout, "%s%s\n", dirname, 1877 type == TYPE_A ? "\r" : ""); 1878 byte_count += strlen(dirname) + 1; 1879 continue; 1880 } else if (!S_ISDIR(st.st_mode)) 1881 continue; 1882 1883 if ((dirp = opendir(dirname)) == NULL) 1884 continue; 1885 1886 while ((dir = readdir(dirp)) != NULL) { 1887 char nbuf[MAXPATHLEN]; 1888 1889 if (dir->d_name[0] == '.' && dir->d_namlen == 1) 1890 continue; 1891 if (dir->d_name[0] == '.' && dir->d_name[1] == '.' && 1892 dir->d_namlen == 2) 1893 continue; 1894 1895 sprintf(nbuf, "%s/%s", dirname, dir->d_name); 1896 1897 /* 1898 * We have to do a stat to insure it's 1899 * not a directory or special file. 1900 */ 1901 if (simple || (stat(nbuf, &st) == 0 && 1902 S_ISREG(st.st_mode))) { 1903 if (dout == NULL) { 1904 dout = dataconn("file list", (off_t)-1, 1905 "w"); 1906 if (dout == NULL) 1907 goto out; 1908 transflag++; 1909 } 1910 if (nbuf[0] == '.' && nbuf[1] == '/') 1911 fprintf(dout, "%s%s\n", &nbuf[2], 1912 type == TYPE_A ? "\r" : ""); 1913 else 1914 fprintf(dout, "%s%s\n", nbuf, 1915 type == TYPE_A ? "\r" : ""); 1916 byte_count += strlen(nbuf) + 1; 1917 } 1918 } 1919 (void) closedir(dirp); 1920 } 1921 1922 if (dout == NULL) 1923 reply(550, "No files found."); 1924 else if (ferror(dout) != 0) 1925 perror_reply(550, "Data connection"); 1926 else 1927 reply(226, "Transfer complete."); 1928 1929 transflag = 0; 1930 if (dout != NULL) 1931 (void) fclose(dout); 1932 data = -1; 1933 pdata = -1; 1934 out: 1935 if (freeglob) { 1936 freeglob = 0; 1937 globfree(&gl); 1938 } 1939 } 1940 1941 void 1942 reapchild(signo) 1943 int signo; 1944 { 1945 while (wait3(NULL, WNOHANG, NULL) > 0); 1946 } 1947 1948 #ifdef OLD_SETPROCTITLE 1949 /* 1950 * Clobber argv so ps will show what we're doing. (Stolen from sendmail.) 1951 * Warning, since this is usually started from inetd.conf, it often doesn't 1952 * have much of an environment or arglist to overwrite. 1953 */ 1954 void 1955 #if __STDC__ 1956 setproctitle(const char *fmt, ...) 1957 #else 1958 setproctitle(fmt, va_alist) 1959 char *fmt; 1960 va_dcl 1961 #endif 1962 { 1963 int i; 1964 va_list ap; 1965 char *p, *bp, ch; 1966 char buf[LINE_MAX]; 1967 1968 #if __STDC__ 1969 va_start(ap, fmt); 1970 #else 1971 va_start(ap); 1972 #endif 1973 (void)vsnprintf(buf, sizeof(buf), fmt, ap); 1974 1975 /* make ps print our process name */ 1976 p = Argv[0]; 1977 *p++ = '-'; 1978 1979 i = strlen(buf); 1980 if (i > LastArgv - p - 2) { 1981 i = LastArgv - p - 2; 1982 buf[i] = '\0'; 1983 } 1984 bp = buf; 1985 while (ch = *bp++) 1986 if (ch != '\n' && ch != '\r') 1987 *p++ = ch; 1988 while (p < LastArgv) 1989 *p++ = ' '; 1990 } 1991 #endif /* OLD_SETPROCTITLE */ 1992 1993 static void 1994 logxfer(name, size, start) 1995 char *name; 1996 long size; 1997 long start; 1998 { 1999 char buf[1024]; 2000 char path[MAXPATHLEN + 1]; 2001 long now; 2002 2003 if (statfd >= 0 && getwd(path) != NULL) { 2004 time(&now); 2005 snprintf(buf, sizeof(buf), "%.20s!%s!%s!%s/%s!%ld!%ld\n", 2006 ctime(&now)+4, ident, remotehost, 2007 path, name, size, now - start + (now == start)); 2008 write(statfd, buf, strlen(buf)); 2009 } 2010 } 2011