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