1 /* 2 * Copyright (c) 1985, 1988 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1985, 1988 Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)ftpd.c 5.36 (Berkeley) 06/01/90"; 16 #endif /* not lint */ 17 18 /* 19 * FTP server. 20 */ 21 #include <sys/param.h> 22 #include <sys/stat.h> 23 #include <sys/ioctl.h> 24 #include <sys/socket.h> 25 #include <sys/file.h> 26 #include <sys/wait.h> 27 #include <sys/dir.h> 28 29 #include <netinet/in.h> 30 31 #define FTP_NAMES 32 #include <arpa/ftp.h> 33 #include <arpa/inet.h> 34 #include <arpa/telnet.h> 35 36 #include <ctype.h> 37 #include <stdio.h> 38 #include <signal.h> 39 #include <pwd.h> 40 #include <setjmp.h> 41 #include <netdb.h> 42 #include <errno.h> 43 #include <string.h> 44 #include <syslog.h> 45 #include <varargs.h> 46 #include "pathnames.h" 47 48 /* 49 * File containing login names 50 * NOT to be used on this machine. 51 * Commonly used to disallow uucp. 52 */ 53 extern int errno; 54 extern char *crypt(); 55 extern char version[]; 56 extern char *home; /* pointer to home directory for glob */ 57 extern FILE *ftpd_popen(), *fopen(), *freopen(); 58 extern int ftpd_pclose(), fclose(); 59 extern char *getline(); 60 extern char cbuf[]; 61 extern off_t restart_point; 62 63 struct sockaddr_in ctrl_addr; 64 struct sockaddr_in data_source; 65 struct sockaddr_in data_dest; 66 struct sockaddr_in his_addr; 67 struct sockaddr_in pasv_addr; 68 69 int data; 70 jmp_buf errcatch, urgcatch; 71 int logged_in; 72 struct passwd *pw; 73 int debug; 74 int timeout = 900; /* timeout after 15 minutes of inactivity */ 75 int maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */ 76 int logging; 77 int guest; 78 int type; 79 int form; 80 int stru; /* avoid C keyword */ 81 int mode; 82 int usedefault = 1; /* for data transfers */ 83 int pdata = -1; /* for passive mode */ 84 int transflag; 85 off_t file_size; 86 off_t byte_count; 87 #if !defined(CMASK) || CMASK == 0 88 #undef CMASK 89 #define CMASK 027 90 #endif 91 int defumask = CMASK; /* default umask value */ 92 char tmpline[7]; 93 char hostname[MAXHOSTNAMELEN]; 94 char remotehost[MAXHOSTNAMELEN]; 95 96 /* 97 * Timeout intervals for retrying connections 98 * to hosts that don't accept PORT cmds. This 99 * is a kludge, but given the problems with TCP... 100 */ 101 #define SWAITMAX 90 /* wait at most 90 seconds */ 102 #define SWAITINT 5 /* interval between retries */ 103 104 int swaitmax = SWAITMAX; 105 int swaitint = SWAITINT; 106 107 int lostconn(); 108 int myoob(); 109 FILE *getdatasock(), *dataconn(); 110 111 #ifdef SETPROCTITLE 112 char **Argv = NULL; /* pointer to argument vector */ 113 char *LastArgv = NULL; /* end of argv */ 114 char proctitle[BUFSIZ]; /* initial part of title */ 115 #endif /* SETPROCTITLE */ 116 117 main(argc, argv, envp) 118 int argc; 119 char *argv[]; 120 char **envp; 121 { 122 int addrlen, on = 1; 123 char *cp; 124 125 addrlen = sizeof (his_addr); 126 if (getpeername(0, (struct sockaddr *)&his_addr, &addrlen) < 0) { 127 syslog(LOG_ERR, "getpeername (%s): %m",argv[0]); 128 exit(1); 129 } 130 addrlen = sizeof (ctrl_addr); 131 if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) { 132 syslog(LOG_ERR, "getsockname (%s): %m",argv[0]); 133 exit(1); 134 } 135 data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1); 136 debug = 0; 137 openlog("ftpd", LOG_PID, LOG_DAEMON); 138 #ifdef SETPROCTITLE 139 /* 140 * Save start and extent of argv for setproctitle. 141 */ 142 Argv = argv; 143 while (*envp) 144 envp++; 145 LastArgv = envp[-1] + strlen(envp[-1]); 146 #endif /* SETPROCTITLE */ 147 148 argc--, argv++; 149 while (argc > 0 && *argv[0] == '-') { 150 for (cp = &argv[0][1]; *cp; cp++) switch (*cp) { 151 152 case 'v': 153 debug = 1; 154 break; 155 156 case 'd': 157 debug = 1; 158 break; 159 160 case 'l': 161 logging = 1; 162 break; 163 164 case 't': 165 timeout = atoi(++cp); 166 if (maxtimeout < timeout) 167 maxtimeout = timeout; 168 goto nextopt; 169 170 case 'T': 171 maxtimeout = atoi(++cp); 172 if (timeout > maxtimeout) 173 timeout = maxtimeout; 174 goto nextopt; 175 176 case 'u': 177 { 178 int val = 0; 179 180 while (*++cp && *cp >= '0' && *cp <= '9') 181 val = val*8 + *cp - '0'; 182 if (*cp) 183 fprintf(stderr, "ftpd: Bad value for -u\n"); 184 else 185 defumask = val; 186 goto nextopt; 187 } 188 189 default: 190 fprintf(stderr, "ftpd: Unknown flag -%c ignored.\n", 191 *cp); 192 break; 193 } 194 nextopt: 195 argc--, argv++; 196 } 197 (void) freopen(_PATH_DEVNULL, "w", stderr); 198 (void) signal(SIGPIPE, lostconn); 199 (void) signal(SIGCHLD, SIG_IGN); 200 if ((int)signal(SIGURG, myoob) < 0) 201 syslog(LOG_ERR, "signal: %m"); 202 203 /* Try to handle urgent data inline */ 204 #ifdef SO_OOBINLINE 205 if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) < 0) 206 syslog(LOG_ERR, "setsockopt: %m"); 207 #endif 208 209 #ifdef F_SETOWN 210 if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1) 211 syslog(LOG_ERR, "fcntl F_SETOWN: %m"); 212 #endif 213 dolog(&his_addr); 214 /* 215 * Set up default state 216 */ 217 data = -1; 218 type = TYPE_A; 219 form = FORM_N; 220 stru = STRU_F; 221 mode = MODE_S; 222 tmpline[0] = '\0'; 223 (void) gethostname(hostname, sizeof (hostname)); 224 reply(220, "%s FTP server (%s) ready.", hostname, version); 225 (void) setjmp(errcatch); 226 for (;;) 227 (void) yyparse(); 228 /* NOTREACHED */ 229 } 230 231 lostconn() 232 { 233 234 if (debug) 235 syslog(LOG_DEBUG, "lost connection"); 236 dologout(-1); 237 } 238 239 static char ttyline[20]; 240 241 /* 242 * Helper function for sgetpwnam(). 243 */ 244 char * 245 sgetsave(s) 246 char *s; 247 { 248 char *malloc(); 249 char *new = malloc((unsigned) strlen(s) + 1); 250 251 if (new == NULL) { 252 perror_reply(421, "Local resource failure: malloc"); 253 dologout(1); 254 /* NOTREACHED */ 255 } 256 (void) strcpy(new, s); 257 return (new); 258 } 259 260 /* 261 * Save the result of a getpwnam. Used for USER command, since 262 * the data returned must not be clobbered by any other command 263 * (e.g., globbing). 264 */ 265 struct passwd * 266 sgetpwnam(name) 267 char *name; 268 { 269 static struct passwd save; 270 register struct passwd *p; 271 char *sgetsave(); 272 273 if ((p = getpwnam(name)) == NULL) 274 return (p); 275 if (save.pw_name) { 276 free(save.pw_name); 277 free(save.pw_passwd); 278 free(save.pw_gecos); 279 free(save.pw_dir); 280 free(save.pw_shell); 281 } 282 save = *p; 283 save.pw_name = sgetsave(p->pw_name); 284 save.pw_passwd = sgetsave(p->pw_passwd); 285 save.pw_gecos = sgetsave(p->pw_gecos); 286 save.pw_dir = sgetsave(p->pw_dir); 287 save.pw_shell = sgetsave(p->pw_shell); 288 return (&save); 289 } 290 291 int login_attempts; /* number of failed login attempts */ 292 int askpasswd; /* had user command, ask for passwd */ 293 294 /* 295 * USER command. 296 * Sets global passwd pointer pw if named account exists and is acceptable; 297 * sets askpasswd if a PASS command is expected. If logged in previously, 298 * need to reset state. If name is "ftp" or "anonymous", the name is not in 299 * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return. 300 * If account doesn't exist, ask for passwd anyway. Otherwise, check user 301 * requesting login privileges. Disallow anyone who does not have a standard 302 * shell as returned by getusershell(). Disallow anyone mentioned in the file 303 * _PATH_FTPUSERS to allow people such as root and uucp to be avoided. 304 */ 305 user(name) 306 char *name; 307 { 308 register char *cp; 309 char *shell; 310 char *getusershell(); 311 312 if (logged_in) { 313 if (guest) { 314 reply(530, "Can't change user from guest login."); 315 return; 316 } 317 end_login(); 318 } 319 320 guest = 0; 321 if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) { 322 if (checkuser("ftp") || checkuser("anonymous")) 323 reply(530, "User %s access denied.", name); 324 else if ((pw = sgetpwnam("ftp")) != NULL) { 325 guest = 1; 326 askpasswd = 1; 327 reply(331, "Guest login ok, send ident as password."); 328 } else 329 reply(530, "User %s unknown.", name); 330 return; 331 } 332 if (pw = sgetpwnam(name)) { 333 if ((shell = pw->pw_shell) == NULL || *shell == 0) 334 shell = _PATH_BSHELL; 335 while ((cp = getusershell()) != NULL) 336 if (strcmp(cp, shell) == 0) 337 break; 338 endusershell(); 339 if (cp == NULL || checkuser(name)) { 340 reply(530, "User %s access denied.", name); 341 if (logging) 342 syslog(LOG_NOTICE, 343 "FTP LOGIN REFUSED FROM %s, %s", 344 remotehost, name); 345 pw = (struct passwd *) NULL; 346 return; 347 } 348 } 349 reply(331, "Password required for %s.", name); 350 askpasswd = 1; 351 /* 352 * Delay before reading passwd after first failed 353 * attempt to slow down passwd-guessing programs. 354 */ 355 if (login_attempts) 356 sleep((unsigned) login_attempts); 357 } 358 359 /* 360 * Check if a user is in the file _PATH_FTPUSERS 361 */ 362 checkuser(name) 363 char *name; 364 { 365 register FILE *fd; 366 register char *p; 367 char line[BUFSIZ]; 368 369 if ((fd = fopen(_PATH_FTPUSERS, "r")) != NULL) { 370 while (fgets(line, sizeof(line), fd) != NULL) 371 if ((p = index(line, '\n')) != NULL) { 372 *p = '\0'; 373 if (line[0] == '#') 374 continue; 375 if (strcmp(line, name) == 0) 376 return (1); 377 } 378 (void) fclose(fd); 379 } 380 return (0); 381 } 382 383 /* 384 * Terminate login as previous user, if any, resetting state; 385 * used when USER command is given or login fails. 386 */ 387 end_login() 388 { 389 390 (void) seteuid((uid_t)0); 391 if (logged_in) 392 logwtmp(ttyline, "", ""); 393 pw = NULL; 394 logged_in = 0; 395 guest = 0; 396 } 397 398 pass(passwd) 399 char *passwd; 400 { 401 char *xpasswd, *salt; 402 403 if (logged_in || askpasswd == 0) { 404 reply(503, "Login with USER first."); 405 return; 406 } 407 askpasswd = 0; 408 if (!guest) { /* "ftp" is only account allowed no password */ 409 if (pw == NULL) 410 salt = "xx"; 411 else 412 salt = pw->pw_passwd; 413 xpasswd = crypt(passwd, salt); 414 /* The strcmp does not catch null passwords! */ 415 if (pw == NULL || *pw->pw_passwd == '\0' || 416 strcmp(xpasswd, pw->pw_passwd)) { 417 reply(530, "Login incorrect."); 418 pw = NULL; 419 if (login_attempts++ >= 5) { 420 syslog(LOG_NOTICE, 421 "repeated login failures from %s", 422 remotehost); 423 exit(0); 424 } 425 return; 426 } 427 } 428 login_attempts = 0; /* this time successful */ 429 (void) setegid((gid_t)pw->pw_gid); 430 (void) initgroups(pw->pw_name, pw->pw_gid); 431 432 /* open wtmp before chroot */ 433 (void)sprintf(ttyline, "ftp%d", getpid()); 434 logwtmp(ttyline, pw->pw_name, remotehost); 435 logged_in = 1; 436 437 if (guest) { 438 /* 439 * We MUST do a chdir() after the chroot. Otherwise 440 * the old current directory will be accessible as "." 441 * outside the new root! 442 */ 443 if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) { 444 reply(550, "Can't set guest privileges."); 445 goto bad; 446 } 447 } else if (chdir(pw->pw_dir) < 0) { 448 if (chdir("/") < 0) { 449 reply(530, "User %s: can't change directory to %s.", 450 pw->pw_name, pw->pw_dir); 451 goto bad; 452 } else 453 lreply(230, "No directory! Logging in with home=/"); 454 } 455 if (seteuid((uid_t)pw->pw_uid) < 0) { 456 reply(550, "Can't set uid."); 457 goto bad; 458 } 459 if (guest) { 460 reply(230, "Guest login ok, access restrictions apply."); 461 #ifdef SETPROCTITLE 462 sprintf(proctitle, "%s: anonymous/%.*s", remotehost, 463 sizeof(proctitle) - sizeof(remotehost) - 464 sizeof(": anonymous/"), passwd); 465 setproctitle(proctitle); 466 #endif /* SETPROCTITLE */ 467 if (logging) 468 syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s", 469 remotehost, passwd); 470 } else { 471 reply(230, "User %s logged in.", pw->pw_name); 472 #ifdef SETPROCTITLE 473 sprintf(proctitle, "%s: %s", remotehost, pw->pw_name); 474 setproctitle(proctitle); 475 #endif /* SETPROCTITLE */ 476 if (logging) 477 syslog(LOG_INFO, "FTP LOGIN FROM %s, %s", 478 remotehost, pw->pw_name); 479 } 480 home = pw->pw_dir; /* home dir for globbing */ 481 (void) umask(defumask); 482 return; 483 bad: 484 /* Forget all about it... */ 485 end_login(); 486 } 487 488 retrieve(cmd, name) 489 char *cmd, *name; 490 { 491 FILE *fin, *dout; 492 struct stat st; 493 int (*closefunc)(); 494 495 if (cmd == 0) { 496 fin = fopen(name, "r"), closefunc = fclose; 497 st.st_size = 0; 498 } else { 499 char line[BUFSIZ]; 500 501 (void) sprintf(line, cmd, name), name = line; 502 fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose; 503 st.st_size = -1; 504 st.st_blksize = BUFSIZ; 505 } 506 if (fin == NULL) { 507 if (errno != 0) 508 perror_reply(550, name); 509 return; 510 } 511 if (cmd == 0 && 512 (fstat(fileno(fin), &st) < 0 || (st.st_mode&S_IFMT) != S_IFREG)) { 513 reply(550, "%s: not a plain file.", name); 514 goto done; 515 } 516 if (restart_point) { 517 if (type == TYPE_A) { 518 register int i, n, c; 519 520 n = restart_point; 521 i = 0; 522 while (i++ < n) { 523 if ((c=getc(fin)) == EOF) { 524 perror_reply(550, name); 525 goto done; 526 } 527 if (c == '\n') 528 i++; 529 } 530 } else if (lseek(fileno(fin), restart_point, L_SET) < 0) { 531 perror_reply(550, name); 532 goto done; 533 } 534 } 535 dout = dataconn(name, st.st_size, "w"); 536 if (dout == NULL) 537 goto done; 538 send_data(fin, dout, st.st_blksize); 539 (void) fclose(dout); 540 data = -1; 541 pdata = -1; 542 done: 543 (*closefunc)(fin); 544 } 545 546 store(name, mode, unique) 547 char *name, *mode; 548 int unique; 549 { 550 FILE *fout, *din; 551 struct stat st; 552 int (*closefunc)(); 553 char *gunique(); 554 555 if (unique && stat(name, &st) == 0 && 556 (name = gunique(name)) == NULL) 557 return; 558 559 if (restart_point) 560 mode = "r+w"; 561 fout = fopen(name, mode); 562 closefunc = fclose; 563 if (fout == NULL) { 564 perror_reply(553, name); 565 return; 566 } 567 if (restart_point) { 568 if (type == TYPE_A) { 569 register int i, n, c; 570 571 n = restart_point; 572 i = 0; 573 while (i++ < n) { 574 if ((c=getc(fout)) == EOF) { 575 perror_reply(550, name); 576 goto done; 577 } 578 if (c == '\n') 579 i++; 580 } 581 /* 582 * We must do this seek to "current" position 583 * because we are changing from reading to 584 * writing. 585 */ 586 if (fseek(fout, 0L, L_INCR) < 0) { 587 perror_reply(550, name); 588 goto done; 589 } 590 } else if (lseek(fileno(fout), restart_point, L_SET) < 0) { 591 perror_reply(550, name); 592 goto done; 593 } 594 } 595 din = dataconn(name, (off_t)-1, "r"); 596 if (din == NULL) 597 goto done; 598 if (receive_data(din, fout) == 0) { 599 if (unique) 600 reply(226, "Transfer complete (unique file name:%s).", 601 name); 602 else 603 reply(226, "Transfer complete."); 604 } 605 (void) fclose(din); 606 data = -1; 607 pdata = -1; 608 done: 609 (*closefunc)(fout); 610 } 611 612 FILE * 613 getdatasock(mode) 614 char *mode; 615 { 616 int s, on = 1, tries; 617 618 if (data >= 0) 619 return (fdopen(data, mode)); 620 s = socket(AF_INET, SOCK_STREAM, 0); 621 if (s < 0) 622 return (NULL); 623 (void) seteuid((uid_t)0); 624 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 625 (char *) &on, sizeof (on)) < 0) 626 goto bad; 627 /* anchor socket to avoid multi-homing problems */ 628 data_source.sin_family = AF_INET; 629 data_source.sin_addr = ctrl_addr.sin_addr; 630 for (tries = 1; ; tries++) { 631 if (bind(s, (struct sockaddr *)&data_source, 632 sizeof (data_source)) >= 0) 633 break; 634 if (errno != EADDRINUSE || tries > 10) 635 goto bad; 636 sleep(tries); 637 } 638 (void) seteuid((uid_t)pw->pw_uid); 639 return (fdopen(s, mode)); 640 bad: 641 (void) seteuid((uid_t)pw->pw_uid); 642 (void) close(s); 643 return (NULL); 644 } 645 646 FILE * 647 dataconn(name, size, mode) 648 char *name; 649 off_t size; 650 char *mode; 651 { 652 char sizebuf[32]; 653 FILE *file; 654 int retry = 0; 655 656 file_size = size; 657 byte_count = 0; 658 if (size != (off_t) -1) 659 (void) sprintf (sizebuf, " (%ld bytes)", size); 660 else 661 (void) strcpy(sizebuf, ""); 662 if (pdata >= 0) { 663 struct sockaddr_in from; 664 int s, fromlen = sizeof(from); 665 666 s = accept(pdata, (struct sockaddr *)&from, &fromlen); 667 if (s < 0) { 668 reply(425, "Can't open data connection."); 669 (void) close(pdata); 670 pdata = -1; 671 return(NULL); 672 } 673 (void) close(pdata); 674 pdata = s; 675 reply(150, "Opening %s mode data connection for %s%s.", 676 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); 677 return(fdopen(pdata, mode)); 678 } 679 if (data >= 0) { 680 reply(125, "Using existing data connection for %s%s.", 681 name, sizebuf); 682 usedefault = 1; 683 return (fdopen(data, mode)); 684 } 685 if (usedefault) 686 data_dest = his_addr; 687 usedefault = 1; 688 file = getdatasock(mode); 689 if (file == NULL) { 690 reply(425, "Can't create data socket (%s,%d): %s.", 691 inet_ntoa(data_source.sin_addr), 692 ntohs(data_source.sin_port), strerror(errno)); 693 return (NULL); 694 } 695 data = fileno(file); 696 while (connect(data, (struct sockaddr *)&data_dest, 697 sizeof (data_dest)) < 0) { 698 if (errno == EADDRINUSE && retry < swaitmax) { 699 sleep((unsigned) swaitint); 700 retry += swaitint; 701 continue; 702 } 703 perror_reply(425, "Can't build data connection"); 704 (void) fclose(file); 705 data = -1; 706 return (NULL); 707 } 708 reply(150, "Opening %s mode data connection for %s%s.", 709 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); 710 return (file); 711 } 712 713 /* 714 * Tranfer the contents of "instr" to 715 * "outstr" peer using the appropriate 716 * encapsulation of the data subject 717 * to Mode, Structure, and Type. 718 * 719 * NB: Form isn't handled. 720 */ 721 send_data(instr, outstr, blksize) 722 FILE *instr, *outstr; 723 off_t blksize; 724 { 725 register int c, cnt; 726 register char *buf; 727 int netfd, filefd; 728 729 transflag++; 730 if (setjmp(urgcatch)) { 731 transflag = 0; 732 return; 733 } 734 switch (type) { 735 736 case TYPE_A: 737 while ((c = getc(instr)) != EOF) { 738 byte_count++; 739 if (c == '\n') { 740 if (ferror(outstr)) 741 goto data_err; 742 (void) putc('\r', outstr); 743 } 744 (void) putc(c, outstr); 745 } 746 fflush(outstr); 747 transflag = 0; 748 if (ferror(instr)) 749 goto file_err; 750 if (ferror(outstr)) 751 goto data_err; 752 reply(226, "Transfer complete."); 753 return; 754 755 case TYPE_I: 756 case TYPE_L: 757 if ((buf = malloc((u_int)blksize)) == NULL) { 758 transflag = 0; 759 perror_reply(451, "Local resource failure: malloc"); 760 return; 761 } 762 netfd = fileno(outstr); 763 filefd = fileno(instr); 764 while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 && 765 write(netfd, buf, cnt) == cnt) 766 byte_count += cnt; 767 transflag = 0; 768 (void)free(buf); 769 if (cnt != 0) { 770 if (cnt < 0) 771 goto file_err; 772 goto data_err; 773 } 774 reply(226, "Transfer complete."); 775 return; 776 default: 777 transflag = 0; 778 reply(550, "Unimplemented TYPE %d in send_data", type); 779 return; 780 } 781 782 data_err: 783 transflag = 0; 784 perror_reply(426, "Data connection"); 785 return; 786 787 file_err: 788 transflag = 0; 789 perror_reply(551, "Error on input file"); 790 } 791 792 /* 793 * Transfer data from peer to 794 * "outstr" using the appropriate 795 * encapulation of the data subject 796 * to Mode, Structure, and Type. 797 * 798 * N.B.: Form isn't handled. 799 */ 800 receive_data(instr, outstr) 801 FILE *instr, *outstr; 802 { 803 register int c; 804 int cnt, bare_lfs = 0; 805 char buf[BUFSIZ]; 806 807 transflag++; 808 if (setjmp(urgcatch)) { 809 transflag = 0; 810 return (-1); 811 } 812 switch (type) { 813 814 case TYPE_I: 815 case TYPE_L: 816 while ((cnt = read(fileno(instr), buf, sizeof buf)) > 0) { 817 if (write(fileno(outstr), buf, cnt) != cnt) 818 goto file_err; 819 byte_count += cnt; 820 } 821 if (cnt < 0) 822 goto data_err; 823 transflag = 0; 824 return (0); 825 826 case TYPE_E: 827 reply(553, "TYPE E not implemented."); 828 transflag = 0; 829 return (-1); 830 831 case TYPE_A: 832 while ((c = getc(instr)) != EOF) { 833 byte_count++; 834 if (c == '\n') 835 bare_lfs++; 836 while (c == '\r') { 837 if (ferror(outstr)) 838 goto data_err; 839 if ((c = getc(instr)) != '\n') { 840 (void) putc ('\r', outstr); 841 if (c == '\0' || c == EOF) 842 goto contin2; 843 } 844 } 845 (void) putc(c, outstr); 846 contin2: ; 847 } 848 fflush(outstr); 849 if (ferror(instr)) 850 goto data_err; 851 if (ferror(outstr)) 852 goto file_err; 853 transflag = 0; 854 if (bare_lfs) { 855 lreply(230, "WARNING! %d bare linefeeds received in ASCII mode", bare_lfs); 856 printf(" File may not have transferred correctly.\r\n"); 857 } 858 return (0); 859 default: 860 reply(550, "Unimplemented TYPE %d in receive_data", type); 861 transflag = 0; 862 return (-1); 863 } 864 865 data_err: 866 transflag = 0; 867 perror_reply(426, "Data Connection"); 868 return (-1); 869 870 file_err: 871 transflag = 0; 872 perror_reply(452, "Error writing file"); 873 return (-1); 874 } 875 876 statfilecmd(filename) 877 char *filename; 878 { 879 char line[BUFSIZ]; 880 FILE *fin; 881 int c; 882 883 (void) sprintf(line, "/bin/ls -lgA %s", filename); 884 fin = ftpd_popen(line, "r"); 885 lreply(211, "status of %s:", filename); 886 while ((c = getc(fin)) != EOF) { 887 if (c == '\n') { 888 if (ferror(stdout)){ 889 perror_reply(421, "control connection"); 890 (void) ftpd_pclose(fin); 891 dologout(1); 892 /* NOTREACHED */ 893 } 894 if (ferror(fin)) { 895 perror_reply(551, filename); 896 (void) ftpd_pclose(fin); 897 return; 898 } 899 (void) putc('\r', stdout); 900 } 901 (void) putc(c, stdout); 902 } 903 (void) ftpd_pclose(fin); 904 reply(211, "End of Status"); 905 } 906 907 statcmd() 908 { 909 struct sockaddr_in *sin; 910 u_char *a, *p; 911 912 lreply(211, "%s FTP server status:", hostname, version); 913 printf(" %s\r\n", version); 914 printf(" Connected to %s", remotehost); 915 if (!isdigit(remotehost[0])) 916 printf(" (%s)", inet_ntoa(his_addr.sin_addr)); 917 printf("\r\n"); 918 if (logged_in) { 919 if (guest) 920 printf(" Logged in anonymously\r\n"); 921 else 922 printf(" Logged in as %s\r\n", pw->pw_name); 923 } else if (askpasswd) 924 printf(" Waiting for password\r\n"); 925 else 926 printf(" Waiting for user name\r\n"); 927 printf(" TYPE: %s", typenames[type]); 928 if (type == TYPE_A || type == TYPE_E) 929 printf(", FORM: %s", formnames[form]); 930 if (type == TYPE_L) 931 #if NBBY == 8 932 printf(" %d", NBBY); 933 #else 934 printf(" %d", bytesize); /* need definition! */ 935 #endif 936 printf("; STRUcture: %s; transfer MODE: %s\r\n", 937 strunames[stru], modenames[mode]); 938 if (data != -1) 939 printf(" Data connection open\r\n"); 940 else if (pdata != -1) { 941 printf(" in Passive mode"); 942 sin = &pasv_addr; 943 goto printaddr; 944 } else if (usedefault == 0) { 945 printf(" PORT"); 946 sin = &data_dest; 947 printaddr: 948 a = (u_char *) &sin->sin_addr; 949 p = (u_char *) &sin->sin_port; 950 #define UC(b) (((int) b) & 0xff) 951 printf(" (%d,%d,%d,%d,%d,%d)\r\n", UC(a[0]), 952 UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); 953 #undef UC 954 } else 955 printf(" No data connection\r\n"); 956 reply(211, "End of status"); 957 } 958 959 fatal(s) 960 char *s; 961 { 962 reply(451, "Error in server: %s\n", s); 963 reply(221, "Closing connection due to server error."); 964 dologout(0); 965 /* NOTREACHED */ 966 } 967 968 /* VARARGS2 */ 969 reply(n, fmt, p0, p1, p2, p3, p4, p5) 970 int n; 971 char *fmt; 972 { 973 printf("%d ", n); 974 printf(fmt, p0, p1, p2, p3, p4, p5); 975 printf("\r\n"); 976 (void)fflush(stdout); 977 if (debug) { 978 syslog(LOG_DEBUG, "<--- %d ", n); 979 syslog(LOG_DEBUG, fmt, p0, p1, p2, p3, p4, p5); 980 } 981 } 982 983 /* VARARGS2 */ 984 lreply(n, fmt, p0, p1, p2, p3, p4, p5) 985 int n; 986 char *fmt; 987 { 988 printf("%d- ", n); 989 printf(fmt, p0, p1, p2, p3, p4, p5); 990 printf("\r\n"); 991 (void)fflush(stdout); 992 if (debug) { 993 syslog(LOG_DEBUG, "<--- %d- ", n); 994 syslog(LOG_DEBUG, fmt, p0, p1, p2, p3, p4, p5); 995 } 996 } 997 998 ack(s) 999 char *s; 1000 { 1001 reply(250, "%s command successful.", s); 1002 } 1003 1004 nack(s) 1005 char *s; 1006 { 1007 reply(502, "%s command not implemented.", s); 1008 } 1009 1010 /* ARGSUSED */ 1011 yyerror(s) 1012 char *s; 1013 { 1014 char *cp; 1015 1016 if (cp = index(cbuf,'\n')) 1017 *cp = '\0'; 1018 reply(500, "'%s': command not understood.", cbuf); 1019 } 1020 1021 delete(name) 1022 char *name; 1023 { 1024 struct stat st; 1025 1026 if (stat(name, &st) < 0) { 1027 perror_reply(550, name); 1028 return; 1029 } 1030 if ((st.st_mode&S_IFMT) == S_IFDIR) { 1031 if (rmdir(name) < 0) { 1032 perror_reply(550, name); 1033 return; 1034 } 1035 goto done; 1036 } 1037 if (unlink(name) < 0) { 1038 perror_reply(550, name); 1039 return; 1040 } 1041 done: 1042 ack("DELE"); 1043 } 1044 1045 cwd(path) 1046 char *path; 1047 { 1048 if (chdir(path) < 0) 1049 perror_reply(550, path); 1050 else 1051 ack("CWD"); 1052 } 1053 1054 makedir(name) 1055 char *name; 1056 { 1057 if (mkdir(name, 0777) < 0) 1058 perror_reply(550, name); 1059 else 1060 reply(257, "MKD command successful."); 1061 } 1062 1063 removedir(name) 1064 char *name; 1065 { 1066 if (rmdir(name) < 0) 1067 perror_reply(550, name); 1068 else 1069 ack("RMD"); 1070 } 1071 1072 pwd() 1073 { 1074 char path[MAXPATHLEN + 1]; 1075 extern char *getwd(); 1076 1077 if (getwd(path) == (char *)NULL) 1078 reply(550, "%s.", path); 1079 else 1080 reply(257, "\"%s\" is current directory.", path); 1081 } 1082 1083 char * 1084 renamefrom(name) 1085 char *name; 1086 { 1087 struct stat st; 1088 1089 if (stat(name, &st) < 0) { 1090 perror_reply(550, name); 1091 return ((char *)0); 1092 } 1093 reply(350, "File exists, ready for destination name"); 1094 return (name); 1095 } 1096 1097 renamecmd(from, to) 1098 char *from, *to; 1099 { 1100 if (rename(from, to) < 0) 1101 perror_reply(550, "rename"); 1102 else 1103 ack("RNTO"); 1104 } 1105 1106 dolog(sin) 1107 struct sockaddr_in *sin; 1108 { 1109 struct hostent *hp = gethostbyaddr((char *)&sin->sin_addr, 1110 sizeof (struct in_addr), AF_INET); 1111 time_t t, time(); 1112 extern char *ctime(); 1113 1114 if (hp) 1115 (void) strncpy(remotehost, hp->h_name, sizeof (remotehost)); 1116 else 1117 (void) strncpy(remotehost, inet_ntoa(sin->sin_addr), 1118 sizeof (remotehost)); 1119 #ifdef SETPROCTITLE 1120 sprintf(proctitle, "%s: connected", remotehost); 1121 setproctitle(proctitle); 1122 #endif /* SETPROCTITLE */ 1123 1124 if (logging) { 1125 t = time((time_t *) 0); 1126 syslog(LOG_INFO, "connection from %s at %s", 1127 remotehost, ctime(&t)); 1128 } 1129 } 1130 1131 /* 1132 * Record logout in wtmp file 1133 * and exit with supplied status. 1134 */ 1135 dologout(status) 1136 int status; 1137 { 1138 if (logged_in) { 1139 (void) seteuid((uid_t)0); 1140 logwtmp(ttyline, "", ""); 1141 } 1142 /* beware of flushing buffers after a SIGPIPE */ 1143 _exit(status); 1144 } 1145 1146 myoob() 1147 { 1148 char *cp; 1149 1150 /* only process if transfer occurring */ 1151 if (!transflag) 1152 return; 1153 cp = tmpline; 1154 if (getline(cp, 7, stdin) == NULL) { 1155 reply(221, "You could at least say goodbye."); 1156 dologout(0); 1157 } 1158 upper(cp); 1159 if (strcmp(cp, "ABOR\r\n") == 0) { 1160 tmpline[0] = '\0'; 1161 reply(426, "Transfer aborted. Data connection closed."); 1162 reply(226, "Abort successful"); 1163 longjmp(urgcatch, 1); 1164 } 1165 if (strcmp(cp, "STAT\r\n") == 0) { 1166 if (file_size != (off_t) -1) 1167 reply(213, "Status: %lu of %lu bytes transferred", 1168 byte_count, file_size); 1169 else 1170 reply(213, "Status: %lu bytes transferred", byte_count); 1171 } 1172 } 1173 1174 /* 1175 * Note: a response of 425 is not mentioned as a possible response to 1176 * the PASV command in RFC959. However, it has been blessed as 1177 * a legitimate response by Jon Postel in a telephone conversation 1178 * with Rick Adams on 25 Jan 89. 1179 */ 1180 passive() 1181 { 1182 int len; 1183 register char *p, *a; 1184 1185 pdata = socket(AF_INET, SOCK_STREAM, 0); 1186 if (pdata < 0) { 1187 perror_reply(425, "Can't open passive connection"); 1188 return; 1189 } 1190 pasv_addr = ctrl_addr; 1191 pasv_addr.sin_port = 0; 1192 (void) seteuid((uid_t)0); 1193 if (bind(pdata, (struct sockaddr *)&pasv_addr, sizeof(pasv_addr)) < 0) { 1194 (void) seteuid((uid_t)pw->pw_uid); 1195 goto pasv_error; 1196 } 1197 (void) seteuid((uid_t)pw->pw_uid); 1198 len = sizeof(pasv_addr); 1199 if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0) 1200 goto pasv_error; 1201 if (listen(pdata, 1) < 0) 1202 goto pasv_error; 1203 a = (char *) &pasv_addr.sin_addr; 1204 p = (char *) &pasv_addr.sin_port; 1205 1206 #define UC(b) (((int) b) & 0xff) 1207 1208 reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]), 1209 UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); 1210 return; 1211 1212 pasv_error: 1213 (void) close(pdata); 1214 pdata = -1; 1215 perror_reply(425, "Can't open passive connection"); 1216 return; 1217 } 1218 1219 /* 1220 * Generate unique name for file with basename "local". 1221 * The file named "local" is already known to exist. 1222 * Generates failure reply on error. 1223 */ 1224 char * 1225 gunique(local) 1226 char *local; 1227 { 1228 static char new[MAXPATHLEN]; 1229 struct stat st; 1230 char *cp = rindex(local, '/'); 1231 int count = 0; 1232 1233 if (cp) 1234 *cp = '\0'; 1235 if (stat(cp ? local : ".", &st) < 0) { 1236 perror_reply(553, cp ? local : "."); 1237 return((char *) 0); 1238 } 1239 if (cp) 1240 *cp = '/'; 1241 (void) strcpy(new, local); 1242 cp = new + strlen(new); 1243 *cp++ = '.'; 1244 for (count = 1; count < 100; count++) { 1245 (void) sprintf(cp, "%d", count); 1246 if (stat(new, &st) < 0) 1247 return(new); 1248 } 1249 reply(452, "Unique file name cannot be created."); 1250 return((char *) 0); 1251 } 1252 1253 /* 1254 * Format and send reply containing system error number. 1255 */ 1256 perror_reply(code, string) 1257 int code; 1258 char *string; 1259 { 1260 reply(code, "%s: %s.", string, strerror(errno)); 1261 } 1262 1263 static char *onefile[] = { 1264 "", 1265 0 1266 }; 1267 1268 send_file_list(whichfiles) 1269 char *whichfiles; 1270 { 1271 struct stat st; 1272 DIR *dirp = NULL; 1273 struct direct *dir; 1274 FILE *dout = NULL; 1275 register char **dirlist, *dirname; 1276 int simple = 0; 1277 char *strpbrk(); 1278 1279 if (strpbrk(whichfiles, "~{[*?") != NULL) { 1280 extern char **glob(), *globerr; 1281 1282 globerr = NULL; 1283 dirlist = glob(whichfiles); 1284 if (globerr != NULL) { 1285 reply(550, globerr); 1286 return; 1287 } else if (dirlist == NULL) { 1288 errno = ENOENT; 1289 perror_reply(550, whichfiles); 1290 return; 1291 } 1292 } else { 1293 onefile[0] = whichfiles; 1294 dirlist = onefile; 1295 simple = 1; 1296 } 1297 1298 if (setjmp(urgcatch)) { 1299 transflag = 0; 1300 return; 1301 } 1302 while (dirname = *dirlist++) { 1303 if (stat(dirname, &st) < 0) { 1304 /* 1305 * If user typed "ls -l", etc, and the client 1306 * used NLST, do what the user meant. 1307 */ 1308 if (dirname[0] == '-' && *dirlist == NULL && 1309 transflag == 0) { 1310 retrieve("/bin/ls %s", dirname); 1311 return; 1312 } 1313 perror_reply(550, whichfiles); 1314 if (dout != NULL) { 1315 (void) fclose(dout); 1316 transflag = 0; 1317 data = -1; 1318 pdata = -1; 1319 } 1320 return; 1321 } 1322 1323 if ((st.st_mode&S_IFMT) == S_IFREG) { 1324 if (dout == NULL) { 1325 dout = dataconn("file list", (off_t)-1, "w"); 1326 if (dout == NULL) 1327 return; 1328 transflag++; 1329 } 1330 fprintf(dout, "%s%s\n", dirname, 1331 type == TYPE_A ? "\r" : ""); 1332 byte_count += strlen(dirname) + 1; 1333 continue; 1334 } else if ((st.st_mode&S_IFMT) != S_IFDIR) 1335 continue; 1336 1337 if ((dirp = opendir(dirname)) == NULL) 1338 continue; 1339 1340 while ((dir = readdir(dirp)) != NULL) { 1341 char nbuf[MAXPATHLEN]; 1342 1343 if (dir->d_name[0] == '.' && dir->d_namlen == 1) 1344 continue; 1345 if (dir->d_name[0] == '.' && dir->d_name[1] == '.' && 1346 dir->d_namlen == 2) 1347 continue; 1348 1349 sprintf(nbuf, "%s/%s", dirname, dir->d_name); 1350 1351 /* 1352 * We have to do a stat to insure it's 1353 * not a directory or special file. 1354 */ 1355 if (simple || (stat(nbuf, &st) == 0 && 1356 (st.st_mode&S_IFMT) == S_IFREG)) { 1357 if (dout == NULL) { 1358 dout = dataconn("file list", (off_t)-1, 1359 "w"); 1360 if (dout == NULL) 1361 return; 1362 transflag++; 1363 } 1364 if (nbuf[0] == '.' && nbuf[1] == '/') 1365 fprintf(dout, "%s%s\n", &nbuf[2], 1366 type == TYPE_A ? "\r" : ""); 1367 else 1368 fprintf(dout, "%s%s\n", nbuf, 1369 type == TYPE_A ? "\r" : ""); 1370 byte_count += strlen(nbuf) + 1; 1371 } 1372 } 1373 (void) closedir(dirp); 1374 } 1375 1376 if (dout == NULL) 1377 reply(550, "No files found."); 1378 else if (ferror(dout) != 0) 1379 perror_reply(550, "Data connection"); 1380 else 1381 reply(226, "Transfer complete."); 1382 1383 transflag = 0; 1384 if (dout != NULL) 1385 (void) fclose(dout); 1386 data = -1; 1387 pdata = -1; 1388 } 1389 1390 #ifdef SETPROCTITLE 1391 /* 1392 * clobber argv so ps will show what we're doing. 1393 * (stolen from sendmail) 1394 * warning, since this is usually started from inetd.conf, it 1395 * often doesn't have much of an environment or arglist to overwrite. 1396 */ 1397 1398 /*VARARGS1*/ 1399 setproctitle(fmt, a, b, c) 1400 char *fmt; 1401 { 1402 register char *p, *bp, ch; 1403 register int i; 1404 char buf[BUFSIZ]; 1405 1406 (void) sprintf(buf, fmt, a, b, c); 1407 1408 /* make ps print our process name */ 1409 p = Argv[0]; 1410 *p++ = '-'; 1411 1412 i = strlen(buf); 1413 if (i > LastArgv - p - 2) { 1414 i = LastArgv - p - 2; 1415 buf[i] = '\0'; 1416 } 1417 bp = buf; 1418 while (ch = *bp++) 1419 if (ch != '\n' && ch != '\r') 1420 *p++ = ch; 1421 while (p < LastArgv) 1422 *p++ = ' '; 1423 } 1424 #endif /* SETPROCTITLE */ 1425