1 #ifndef lint 2 static char sccsid[] = "@(#)ftpd.c 4.20 (Berkeley) 06/12/83"; 3 #endif 4 5 /* 6 * FTP server. 7 */ 8 #include <sys/param.h> 9 #include <sys/stat.h> 10 #include <sys/ioctl.h> 11 #include <sys/socket.h> 12 13 #include <netinet/in.h> 14 15 #include <arpa/ftp.h> 16 17 #include <stdio.h> 18 #include <signal.h> 19 #include <wait.h> 20 #include <pwd.h> 21 #include <setjmp.h> 22 #include <netdb.h> 23 #include <errno.h> 24 25 /* 26 * File containing login names 27 * NOT to be used on this machine. 28 * Commonly used to disallow uucp. 29 */ 30 #define FTPUSERS "/etc/ftpusers" 31 32 extern int errno; 33 extern char *sys_errlist[]; 34 extern char *crypt(); 35 extern char version[]; 36 extern char *home; /* pointer to home directory for glob */ 37 extern FILE *popen(), *fopen(); 38 extern int pclose(), fclose(); 39 40 struct sockaddr_in ctrl_addr; 41 struct sockaddr_in data_source; 42 struct sockaddr_in data_dest; 43 struct sockaddr_in his_addr; 44 45 struct hostent *hp; 46 47 int data; 48 jmp_buf errcatch; 49 int logged_in; 50 struct passwd *pw; 51 int debug; 52 int timeout; 53 int logging; 54 int guest; 55 int type; 56 int form; 57 int stru; /* avoid C keyword */ 58 int mode; 59 int usedefault = 1; /* for data transfers */ 60 char hostname[32]; 61 char *remotehost; 62 struct servent *sp; 63 64 /* 65 * Timeout intervals for retrying connections 66 * to hosts that don't accept PORT cmds. This 67 * is a kludge, but given the problems with TCP... 68 */ 69 #define SWAITMAX 90 /* wait at most 90 seconds */ 70 #define SWAITINT 5 /* interval between retries */ 71 72 int swaitmax = SWAITMAX; 73 int swaitint = SWAITINT; 74 75 int lostconn(); 76 int reapchild(); 77 FILE *getdatasock(), *dataconn(); 78 char *ntoa(); 79 80 main(argc, argv) 81 int argc; 82 char *argv[]; 83 { 84 int ctrl, s, options = 0; 85 char *cp; 86 87 sp = getservbyname("ftp", "tcp"); 88 if (sp == 0) { 89 fprintf(stderr, "ftpd: ftp/tcp: unknown service\n"); 90 exit(1); 91 } 92 ctrl_addr.sin_port = sp->s_port; 93 data_source.sin_port = htons(ntohs(sp->s_port) - 1); 94 signal(SIGPIPE, lostconn); 95 debug = 0; 96 argc--, argv++; 97 while (argc > 0 && *argv[0] == '-') { 98 for (cp = &argv[0][1]; *cp; cp++) switch (*cp) { 99 100 case 'v': 101 debug = 1; 102 break; 103 104 case 'd': 105 debug = 1; 106 options |= SO_DEBUG; 107 break; 108 109 case 'l': 110 logging = 1; 111 break; 112 113 case 't': 114 timeout = atoi(++cp); 115 goto nextopt; 116 break; 117 118 default: 119 fprintf(stderr, "Unknown flag -%c ignored.\n", *cp); 120 break; 121 } 122 nextopt: 123 argc--, argv++; 124 } 125 #ifndef DEBUG 126 if (fork()) 127 exit(0); 128 for (s = 0; s < 10; s++) 129 if (!logging || (s != 2)) 130 (void) close(s); 131 (void) open("/", 0); 132 (void) dup2(0, 1); 133 if (!logging) 134 (void) dup2(0, 2); 135 { int tt = open("/dev/tty", 2); 136 if (tt > 0) { 137 ioctl(tt, TIOCNOTTY, 0); 138 close(tt); 139 } 140 } 141 #endif 142 while ((s = socket(AF_INET, SOCK_STREAM, 0, 0)) < 0) { 143 perror("ftpd: socket"); 144 sleep(5); 145 } 146 if (options & SO_DEBUG) 147 if (setsockopt(s, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) 148 perror("ftpd: setsockopt (SO_DEBUG)"); 149 #ifdef notdef 150 if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, 0, 0) < 0) 151 perror("ftpd: setsockopt (SO_KEEPALIVE)"); 152 #endif 153 while (bind(s, &ctrl_addr, sizeof (ctrl_addr), 0) < 0) { 154 perror("ftpd: bind"); 155 sleep(5); 156 } 157 signal(SIGCHLD, reapchild); 158 listen(s, 10); 159 for (;;) { 160 int hisaddrlen = sizeof (his_addr); 161 162 ctrl = accept(s, &his_addr, &hisaddrlen, 0); 163 if (ctrl < 0) { 164 if (errno == EINTR) 165 continue; 166 perror("ftpd: accept"); 167 continue; 168 } 169 if (fork() == 0) { 170 signal (SIGCHLD, SIG_IGN); 171 if (logging) 172 dolog(&his_addr); 173 close(s); 174 dup2(ctrl, 0), close(ctrl), dup2(0, 1); 175 /* do telnet option negotiation here */ 176 /* 177 * Set up default state 178 */ 179 logged_in = 0; 180 data = -1; 181 type = TYPE_A; 182 form = FORM_N; 183 stru = STRU_F; 184 mode = MODE_S; 185 gethostname(hostname, sizeof (hostname)); 186 reply(220, "%s FTP server (%s) ready.", 187 hostname, version); 188 /* 189 * Anchor data source address to that 190 * of the control port so hosts with 191 * multiple address won't have data 192 * connections bound to an address different 193 * than the control port. 194 */ 195 if (getsockname(0, &ctrl_addr, sizeof (ctrl_addr)) >= 0) 196 data_source.sin_addr = ctrl_addr.sin_addr; 197 for (;;) { 198 setjmp(errcatch); 199 yyparse(); 200 } 201 } 202 close(ctrl); 203 } 204 } 205 206 reapchild() 207 { 208 union wait status; 209 210 while (wait3(&status, WNOHANG, 0) > 0) 211 ; 212 } 213 214 lostconn() 215 { 216 217 fatal("Connection closed."); 218 } 219 220 pass(passwd) 221 char *passwd; 222 { 223 char *xpasswd, *savestr(); 224 static struct passwd save; 225 226 if (logged_in || pw == NULL) { 227 reply(503, "Login with USER first."); 228 return; 229 } 230 if (!guest) { /* "ftp" is only account allowed no password */ 231 xpasswd = crypt(passwd, pw->pw_passwd); 232 if (strcmp(xpasswd, pw->pw_passwd) != 0) { 233 reply(530, "Login incorrect."); 234 pw = NULL; 235 return; 236 } 237 } 238 setegid(pw->pw_gid); 239 initgroups(pw->pw_name, pw->pw_gid); 240 if (chdir(pw->pw_dir)) { 241 reply(550, "User %s: can't change directory to $s.", 242 pw->pw_name, pw->pw_dir); 243 goto bad; 244 } 245 if (guest && chroot(pw->pw_dir) < 0) { 246 reply(550, "Can't set guest privileges."); 247 goto bad; 248 } 249 if (!guest) 250 reply(230, "User %s logged in.", pw->pw_name); 251 else 252 reply(230, "Guest login ok, access restrictions apply."); 253 logged_in = 1; 254 seteuid(pw->pw_uid); 255 /* 256 * Save everything so globbing doesn't 257 * clobber the fields. 258 */ 259 save = *pw; 260 save.pw_name = savestr(pw->pw_name); 261 save.pw_passwd = savestr(pw->pw_passwd); 262 save.pw_comment = savestr(pw->pw_comment); 263 save.pw_gecos = savestr(pw->pw_gecos, &save.pw_gecos); 264 save.pw_dir = savestr(pw->pw_dir); 265 save.pw_shell = savestr(pw->pw_shell); 266 pw = &save; 267 home = pw->pw_dir; /* home dir for globbing */ 268 return; 269 bad: 270 seteuid(0); 271 pw = NULL; 272 } 273 274 char * 275 savestr(s) 276 char *s; 277 { 278 char *malloc(); 279 char *new = malloc(strlen(s) + 1); 280 281 if (new != NULL) 282 strcpy(new, s); 283 return (new); 284 } 285 286 retrieve(cmd, name) 287 char *cmd, *name; 288 { 289 FILE *fin, *dout; 290 struct stat st; 291 int (*closefunc)(); 292 293 if (cmd == 0) { 294 #ifdef notdef 295 /* no remote command execution -- it's a security hole */ 296 if (*name == '|') 297 fin = popen(name + 1, "r"), closefunc = pclose; 298 else 299 #endif 300 fin = fopen(name, "r"), closefunc = fclose; 301 } else { 302 char line[BUFSIZ]; 303 304 sprintf(line, cmd, name), name = line; 305 fin = popen(line, "r"), closefunc = pclose; 306 } 307 if (fin == NULL) { 308 reply(550, "%s: %s.", name, sys_errlist[errno]); 309 return; 310 } 311 st.st_size = 0; 312 if (cmd == 0 && 313 (stat(name, &st) < 0 || (st.st_mode&S_IFMT) != S_IFREG)) { 314 reply(550, "%s: not a plain file.", name); 315 goto done; 316 } 317 dout = dataconn(name, st.st_size, "w"); 318 if (dout == NULL) 319 goto done; 320 if (send_data(fin, dout) || ferror(dout)) 321 reply(550, "%s: %s.", name, sys_errlist[errno]); 322 else 323 reply(226, "Transfer complete."); 324 fclose(dout), data = -1; 325 done: 326 (*closefunc)(fin); 327 } 328 329 store(name, mode) 330 char *name, *mode; 331 { 332 FILE *fout, *din; 333 int (*closefunc)(), dochown = 0; 334 335 #ifdef notdef 336 /* no remote command execution -- it's a security hole */ 337 if (name[0] == '|') 338 fout = popen(&name[1], "w"), closefunc = pclose; 339 else 340 #endif 341 { 342 struct stat st; 343 344 if (stat(name, &st) < 0) 345 dochown++; 346 fout = fopen(name, mode), closefunc = fclose; 347 } 348 if (fout == NULL) { 349 reply(550, "%s: %s.", name, sys_errlist[errno]); 350 return; 351 } 352 din = dataconn(name, (off_t)-1, "r"); 353 if (din == NULL) 354 goto done; 355 if (receive_data(din, fout) || ferror(fout)) 356 reply(550, "%s: %s.", name, sys_errlist[errno]); 357 else 358 reply(226, "Transfer complete."); 359 fclose(din), data = -1; 360 done: 361 if (dochown) 362 (void) chown(name, pw->pw_uid, -1); 363 (*closefunc)(fout); 364 } 365 366 FILE * 367 getdatasock(mode) 368 char *mode; 369 { 370 int s, linger; 371 372 if (data >= 0) 373 return (fdopen(data, mode)); 374 s = socket(AF_INET, SOCK_STREAM, 0, 0); 375 if (s < 0) 376 return (NULL); 377 seteuid(0); 378 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 0, 0) < 0) 379 goto bad; 380 if (bind(s, &data_source, sizeof (data_source), 0) < 0) 381 goto bad; 382 linger = 60; /* value ignored by system */ 383 (void) setsockopt(s, SOL_SOCKET, SO_LINGER, &linger, sizeof (linger)); 384 seteuid(pw->pw_uid); 385 return (fdopen(s, mode)); 386 bad: 387 seteuid(pw->pw_uid); 388 close(s); 389 return (NULL); 390 } 391 392 FILE * 393 dataconn(name, size, mode) 394 char *name; 395 off_t size; 396 char *mode; 397 { 398 char sizebuf[32]; 399 FILE *file; 400 int retry = 0; 401 402 if (size >= 0) 403 sprintf (sizebuf, " (%ld bytes)", size); 404 else 405 (void) strcpy(sizebuf, ""); 406 if (data >= 0) { 407 reply(125, "Using existing data connection for %s%s.", 408 name, sizebuf); 409 usedefault = 1; 410 return (fdopen(data, mode)); 411 } 412 if (usedefault) 413 data_dest = his_addr; 414 usedefault = 1; 415 file = getdatasock(mode); 416 if (file == NULL) { 417 reply(425, "Can't create data socket (%s,%d): %s.", 418 ntoa(data_source.sin_addr), 419 ntohs(data_source.sin_port), 420 sys_errlist[errno]); 421 return (NULL); 422 } 423 reply(150, "Opening data connection for %s (%s,%d)%s.", 424 name, ntoa(data_dest.sin_addr.s_addr), 425 ntohs(data_dest.sin_port), sizebuf); 426 data = fileno(file); 427 while (connect(data, &data_dest, sizeof (data_dest), 0) < 0) { 428 if (errno == EADDRINUSE && retry < swaitmax) { 429 sleep(swaitint); 430 retry += swaitint; 431 continue; 432 } 433 reply(425, "Can't build data connection: %s.", 434 sys_errlist[errno]); 435 (void) fclose(file); 436 data = -1; 437 return (NULL); 438 } 439 return (file); 440 } 441 442 /* 443 * Tranfer the contents of "instr" to 444 * "outstr" peer using the appropriate 445 * encapulation of the date subject 446 * to Mode, Structure, and Type. 447 * 448 * NB: Form isn't handled. 449 */ 450 send_data(instr, outstr) 451 FILE *instr, *outstr; 452 { 453 register int c; 454 int netfd, filefd, cnt; 455 char buf[BUFSIZ]; 456 457 switch (type) { 458 459 case TYPE_A: 460 while ((c = getc(instr)) != EOF) { 461 if (c == '\n') { 462 if (ferror (outstr)) 463 return (1); 464 putc('\r', outstr); 465 } 466 putc(c, outstr); 467 if (c == '\r') 468 putc ('\0', outstr); 469 } 470 if (ferror (instr) || ferror (outstr)) 471 return (1); 472 return (0); 473 474 case TYPE_I: 475 case TYPE_L: 476 netfd = fileno(outstr); 477 filefd = fileno(instr); 478 479 while ((cnt = read(filefd, buf, sizeof (buf))) > 0) 480 if (write(netfd, buf, cnt) < 0) 481 return (1); 482 return (cnt < 0); 483 } 484 reply(504,"Unimplemented TYPE %d in send_data", type); 485 return (1); 486 } 487 488 /* 489 * Transfer data from peer to 490 * "outstr" using the appropriate 491 * encapulation of the data subject 492 * to Mode, Structure, and Type. 493 * 494 * N.B.: Form isn't handled. 495 */ 496 receive_data(instr, outstr) 497 FILE *instr, *outstr; 498 { 499 register int c; 500 int cnt; 501 char buf[BUFSIZ]; 502 503 504 switch (type) { 505 506 case TYPE_I: 507 case TYPE_L: 508 while ((cnt = read(fileno(instr), buf, sizeof buf)) > 0) 509 if (write(fileno(outstr), buf, cnt) < 0) 510 return (1); 511 return (cnt < 0); 512 513 case TYPE_E: 514 reply(504, "TYPE E not implemented."); 515 return (1); 516 517 case TYPE_A: 518 while ((c = getc(instr)) != EOF) { 519 if (c == '\r') { 520 if (ferror (outstr)) 521 return (1); 522 if ((c = getc(instr)) != '\n') 523 putc ('\r', outstr); 524 if (c == '\0') 525 continue; 526 } 527 putc (c, outstr); 528 } 529 if (ferror (instr) || ferror (outstr)) 530 return (1); 531 return (0); 532 } 533 fatal("Unknown type in receive_data."); 534 /*NOTREACHED*/ 535 } 536 537 fatal(s) 538 char *s; 539 { 540 reply(451, "Error in server: %s\n", s); 541 reply(221, "Closing connection due to server error."); 542 exit(0); 543 } 544 545 reply(n, s, args) 546 int n; 547 char *s; 548 { 549 550 printf("%d ", n); 551 _doprnt(s, &args, stdout); 552 printf("\r\n"); 553 fflush(stdout); 554 if (debug) { 555 fprintf(stderr, "<--- %d ", n); 556 _doprnt(s, &args, stderr); 557 fprintf(stderr, "\n"); 558 fflush(stderr); 559 } 560 } 561 562 lreply(n, s, args) 563 int n; 564 char *s; 565 { 566 printf("%d-", n); 567 _doprnt(s, &args, stdout); 568 printf("\r\n"); 569 fflush(stdout); 570 if (debug) { 571 fprintf(stderr, "<--- %d-", n); 572 _doprnt(s, &args, stderr); 573 fprintf(stderr, "\n"); 574 } 575 } 576 577 replystr(s) 578 char *s; 579 { 580 printf("%s\r\n", s); 581 fflush(stdout); 582 if (debug) 583 fprintf(stderr, "<--- %s\n", s); 584 } 585 586 ack(s) 587 char *s; 588 { 589 reply(200, "%s command okay.", s); 590 } 591 592 nack(s) 593 char *s; 594 { 595 reply(502, "%s command not implemented.", s); 596 } 597 598 yyerror() 599 { 600 reply(500, "Command not understood."); 601 } 602 603 delete(name) 604 char *name; 605 { 606 struct stat st; 607 608 if (stat(name, &st) < 0) { 609 reply(550, "%s: %s.", name, sys_errlist[errno]); 610 return; 611 } 612 if ((st.st_mode&S_IFMT) == S_IFDIR) { 613 if (rmdir(name) < 0) { 614 reply(550, "%s: %s.", name, sys_errlist[errno]); 615 return; 616 } 617 goto done; 618 } 619 if (unlink(name) < 0) { 620 reply(550, "%s: %s.", name, sys_errlist[errno]); 621 return; 622 } 623 done: 624 ack("DELE"); 625 } 626 627 cwd(path) 628 char *path; 629 { 630 631 if (chdir(path) < 0) { 632 reply(550, "%s: %s.", path, sys_errlist[errno]); 633 return; 634 } 635 ack("CWD"); 636 } 637 638 makedir(name) 639 char *name; 640 { 641 struct stat st; 642 int dochown = stat(name, &st) < 0; 643 644 if (mkdir(name, 0777) < 0) { 645 reply(550, "%s: %s.", name, sys_errlist[errno]); 646 return; 647 } 648 if (dochown) 649 (void) chown(name, pw->pw_uid, -1); 650 ack("MKDIR"); 651 } 652 653 removedir(name) 654 char *name; 655 { 656 657 if (rmdir(name) < 0) { 658 reply(550, "%s: %s.", name, sys_errlist[errno]); 659 return; 660 } 661 ack("RMDIR"); 662 } 663 664 pwd() 665 { 666 char path[MAXPATHLEN + 1]; 667 668 if (getwd(path) == NULL) { 669 reply(451, "%s.", path); 670 return; 671 } 672 reply(251, "\"%s\" is current directory.", path); 673 } 674 675 char * 676 renamefrom(name) 677 char *name; 678 { 679 struct stat st; 680 681 if (stat(name, &st) < 0) { 682 reply(550, "%s: %s.", name, sys_errlist[errno]); 683 return ((char *)0); 684 } 685 reply(350, "File exists, ready for destination name"); 686 return (name); 687 } 688 689 renamecmd(from, to) 690 char *from, *to; 691 { 692 693 if (rename(from, to) < 0) { 694 reply(550, "rename: %s.", sys_errlist[errno]); 695 return; 696 } 697 ack("RNTO"); 698 } 699 700 /* 701 * Convert network-format internet address 702 * to base 256 d.d.d.d representation. 703 */ 704 char * 705 ntoa(in) 706 struct in_addr in; 707 { 708 static char b[18]; 709 register char *p; 710 711 p = (char *)∈ 712 #define UC(b) (((int)b)&0xff) 713 sprintf(b, "%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3])); 714 return (b); 715 } 716 717 dolog(sin) 718 struct sockaddr_in *sin; 719 { 720 struct hostent *hp = gethostbyaddr(&sin->sin_addr, 721 sizeof (struct in_addr), AF_INET); 722 char *remotehost; 723 time_t t; 724 725 if (hp) 726 remotehost = hp->h_name; 727 else 728 remotehost = "UNKNOWNHOST"; 729 t = time(0); 730 fprintf(stderr,"FTPD: connection from %s at %s", remotehost, ctime(&t)); 731 fflush(stderr); 732 } 733 734 /* 735 * Special version of popen which avoids 736 * call to shell. This insures noone may 737 * create a pipe to a hidden program as a side 738 * effect of a list or dir command. 739 */ 740 #define tst(a,b) (*mode == 'r'? (b) : (a)) 741 #define RDR 0 742 #define WTR 1 743 static int popen_pid[5]; 744 745 static char * 746 nextarg(cpp) 747 char *cpp; 748 { 749 register char *cp = cpp; 750 751 if (cp == 0) 752 return (cp); 753 while (*cp && *cp != ' ' && *cp != '\t') 754 cp++; 755 if (*cp == ' ' || *cp == '\t') { 756 *cp++ = '\0'; 757 while (*cp == ' ' || *cp == '\t') 758 cp++; 759 } 760 if (cp == cpp) 761 return ((char *)0); 762 return (cp); 763 } 764 765 FILE * 766 popen(cmd, mode) 767 char *cmd, *mode; 768 { 769 int p[2], ac; 770 register myside, hisside, pid; 771 char *av[512]; 772 char **pop, **popargs = NULL; 773 extern char **glob(); 774 register char *cp; 775 776 if (pipe(p) < 0) 777 return (NULL); 778 cp = cmd, ac = 0; 779 do { 780 av[ac++] = cp; 781 cp = nextarg(cp); 782 } while (cp && *cp); 783 av[ac] = (char *)0; 784 if (ac > 1) { 785 popargs = glob(&av[1]); 786 if (popargs == NULL) 787 return (NULL); 788 for (ac = 1, pop = popargs; *pop;) 789 av[ac++] = *pop++; 790 } 791 av[ac] = (char *)0; 792 myside = tst(p[WTR], p[RDR]); 793 hisside = tst(p[RDR], p[WTR]); 794 if ((pid = fork()) == 0) { 795 /* myside and hisside reverse roles in child */ 796 close(myside); 797 dup2(hisside, tst(0, 1)); 798 close(hisside); 799 execv(av[0], av); 800 _exit(1); 801 } 802 if (popargs != NULL) 803 blkfree(popargs); 804 if (pid == -1) 805 return (NULL); 806 popen_pid[myside] = pid; 807 close(hisside); 808 return (fdopen(myside, mode)); 809 } 810 811 pclose(ptr) 812 FILE *ptr; 813 { 814 register f, r, (*hstat)(), (*istat)(), (*qstat)(); 815 int status; 816 817 f = fileno(ptr); 818 fclose(ptr); 819 istat = signal(SIGINT, SIG_IGN); 820 qstat = signal(SIGQUIT, SIG_IGN); 821 hstat = signal(SIGHUP, SIG_IGN); 822 while ((r = wait(&status)) != popen_pid[f] && r != -1) 823 ; 824 if (r == -1) 825 status = -1; 826 signal(SIGINT, istat); 827 signal(SIGQUIT, qstat); 828 signal(SIGHUP, hstat); 829 return (status); 830 } 831 832 /* 833 * Check user requesting login priviledges. 834 * Disallow anyone mentioned in the file FTPUSERS 835 * to allow people such as uucp to be avoided. 836 */ 837 checkuser(name) 838 register char *name; 839 { 840 char line[BUFSIZ], *index(); 841 FILE *fd; 842 int found = 0; 843 844 fd = fopen(FTPUSERS, "r"); 845 if (fd == NULL) 846 return (1); 847 while (fgets(line, sizeof (line), fd) != NULL) { 848 register char *cp = index(line, '\n'); 849 850 if (cp) 851 *cp = '\0'; 852 if (strcmp(line, name) == 0) { 853 found++; 854 break; 855 } 856 } 857 fclose(fd); 858 return (!found); 859 } 860