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