1 /* 2 * Copyright (c) 1985 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 char copyright[] = 9 "@(#) Copyright (c) 1985 Regents of the University of California.\n\ 10 All rights reserved.\n"; 11 #endif not lint 12 13 #ifndef lint 14 static char sccsid[] = "@(#)ftpd.c 5.8 (Berkeley) 11/18/86"; 15 #endif not lint 16 17 /* 18 * FTP server. 19 */ 20 #include <sys/param.h> 21 #include <sys/stat.h> 22 #include <sys/ioctl.h> 23 #include <sys/socket.h> 24 #include <sys/file.h> 25 #include <sys/wait.h> 26 27 #include <netinet/in.h> 28 29 #include <arpa/ftp.h> 30 #include <arpa/inet.h> 31 #include <arpa/telnet.h> 32 33 #include <stdio.h> 34 #include <signal.h> 35 #include <pwd.h> 36 #include <setjmp.h> 37 #include <netdb.h> 38 #include <errno.h> 39 #include <strings.h> 40 #include <syslog.h> 41 42 /* 43 * File containing login names 44 * NOT to be used on this machine. 45 * Commonly used to disallow uucp. 46 */ 47 #define FTPUSERS "/etc/ftpusers" 48 49 extern int errno; 50 extern char *sys_errlist[]; 51 extern char *crypt(); 52 extern char version[]; 53 extern char *home; /* pointer to home directory for glob */ 54 extern FILE *popen(), *fopen(), *freopen(); 55 extern int pclose(), fclose(); 56 extern char *getline(); 57 extern char cbuf[]; 58 59 struct sockaddr_in ctrl_addr; 60 struct sockaddr_in data_source; 61 struct sockaddr_in data_dest; 62 struct sockaddr_in his_addr; 63 64 int data; 65 jmp_buf errcatch, urgcatch; 66 int logged_in; 67 struct passwd *pw; 68 int debug; 69 int timeout = 900; /* timeout after 15 minutes of inactivity */ 70 int logging; 71 int guest; 72 int wtmp; 73 int type; 74 int form; 75 int stru; /* avoid C keyword */ 76 int mode; 77 int usedefault = 1; /* for data transfers */ 78 int pdata; /* for passive mode */ 79 int unique; 80 int transflag; 81 char tmpline[7]; 82 char hostname[32]; 83 char remotehost[32]; 84 85 /* 86 * Timeout intervals for retrying connections 87 * to hosts that don't accept PORT cmds. This 88 * is a kludge, but given the problems with TCP... 89 */ 90 #define SWAITMAX 90 /* wait at most 90 seconds */ 91 #define SWAITINT 5 /* interval between retries */ 92 93 int swaitmax = SWAITMAX; 94 int swaitint = SWAITINT; 95 96 int lostconn(); 97 int myoob(); 98 FILE *getdatasock(), *dataconn(); 99 100 main(argc, argv) 101 int argc; 102 char *argv[]; 103 { 104 int addrlen, on = 1; 105 long pgid; 106 char *cp; 107 108 addrlen = sizeof (his_addr); 109 if (getpeername(0, &his_addr, &addrlen) < 0) { 110 syslog(LOG_ERR, "getpeername (%s): %m",argv[0]); 111 exit(1); 112 } 113 addrlen = sizeof (ctrl_addr); 114 if (getsockname(0, (char *) &ctrl_addr, &addrlen) < 0) { 115 syslog(LOG_ERR, "getsockname (%s): %m",argv[0]); 116 exit(1); 117 } 118 data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1); 119 debug = 0; 120 openlog("ftpd", LOG_PID, LOG_DAEMON); 121 argc--, argv++; 122 while (argc > 0 && *argv[0] == '-') { 123 for (cp = &argv[0][1]; *cp; cp++) switch (*cp) { 124 125 case 'v': 126 debug = 1; 127 break; 128 129 case 'd': 130 debug = 1; 131 break; 132 133 case 'l': 134 logging = 1; 135 break; 136 137 case 't': 138 timeout = atoi(++cp); 139 goto nextopt; 140 break; 141 142 default: 143 fprintf(stderr, "ftpd: Unknown flag -%c ignored.\n", 144 *cp); 145 break; 146 } 147 nextopt: 148 argc--, argv++; 149 } 150 (void) signal(SIGPIPE, lostconn); 151 (void) signal(SIGCHLD, SIG_IGN); 152 if (signal(SIGURG, myoob) < 0) { 153 syslog(LOG_ERR, "signal: %m"); 154 } 155 /* handle urgent data inline */ 156 #ifdef SO_OOBINLINE 157 if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) < 0) { 158 syslog(LOG_ERR, "setsockopt: %m"); 159 } 160 #endif SO_OOBINLINE 161 pgid = getpid(); 162 if (ioctl(fileno(stdin), SIOCSPGRP, (char *) &pgid) < 0) { 163 syslog(LOG_ERR, "ioctl: %m"); 164 } 165 dolog(&his_addr); 166 /* do telnet option negotiation here */ 167 /* 168 * Set up default state 169 */ 170 logged_in = 0; 171 data = -1; 172 type = TYPE_A; 173 form = FORM_N; 174 stru = STRU_F; 175 mode = MODE_S; 176 tmpline[0] = '\0'; 177 (void) gethostname(hostname, sizeof (hostname)); 178 reply(220, "%s FTP server (%s) ready.", 179 hostname, version); 180 for (;;) { 181 (void) setjmp(errcatch); 182 (void) yyparse(); 183 } 184 } 185 186 lostconn() 187 { 188 189 if (debug) 190 syslog(LOG_DEBUG, "lost connection"); 191 dologout(-1); 192 } 193 194 pass(passwd) 195 char *passwd; 196 { 197 char *xpasswd, *savestr(); 198 static struct passwd save; 199 200 if (logged_in || pw == NULL) { 201 reply(503, "Login with USER first."); 202 return; 203 } 204 if (!guest) { /* "ftp" is only account allowed no password */ 205 xpasswd = crypt(passwd, pw->pw_passwd); 206 /* The strcmp does not catch null passwords! */ 207 if (*pw->pw_passwd == '\0' || strcmp(xpasswd, pw->pw_passwd)) { 208 reply(530, "Login incorrect."); 209 pw = NULL; 210 return; 211 } 212 } 213 setegid(pw->pw_gid); 214 initgroups(pw->pw_name, pw->pw_gid); 215 if (chdir(pw->pw_dir)) { 216 reply(530, "User %s: can't change directory to %s.", 217 pw->pw_name, pw->pw_dir); 218 goto bad; 219 } 220 221 /* grab wtmp before chroot */ 222 wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND); 223 if (guest && chroot(pw->pw_dir) < 0) { 224 reply(550, "Can't set guest privileges."); 225 if (wtmp >= 0) { 226 (void) close(wtmp); 227 wtmp = -1; 228 } 229 goto bad; 230 } 231 if (!guest) 232 reply(230, "User %s logged in.", pw->pw_name); 233 else 234 reply(230, "Guest login ok, access restrictions apply."); 235 logged_in = 1; 236 dologin(pw); 237 seteuid(pw->pw_uid); 238 /* 239 * Save everything so globbing doesn't 240 * clobber the fields. 241 */ 242 save = *pw; 243 save.pw_name = savestr(pw->pw_name); 244 save.pw_passwd = savestr(pw->pw_passwd); 245 save.pw_comment = savestr(pw->pw_comment); 246 save.pw_gecos = savestr(pw->pw_gecos); 247 save.pw_dir = savestr(pw->pw_dir); 248 save.pw_shell = savestr(pw->pw_shell); 249 pw = &save; 250 home = pw->pw_dir; /* home dir for globbing */ 251 return; 252 bad: 253 seteuid(0); 254 pw = NULL; 255 } 256 257 char * 258 savestr(s) 259 char *s; 260 { 261 char *malloc(); 262 char *new = malloc((unsigned) strlen(s) + 1); 263 264 if (new != NULL) 265 (void) strcpy(new, s); 266 return (new); 267 } 268 269 retrieve(cmd, name) 270 char *cmd, *name; 271 { 272 FILE *fin, *dout; 273 struct stat st; 274 int (*closefunc)(), tmp; 275 276 if (cmd == 0) { 277 #ifdef notdef 278 /* no remote command execution -- it's a security hole */ 279 if (*name == '|') 280 fin = popen(name + 1, "r"), closefunc = pclose; 281 else 282 #endif 283 fin = fopen(name, "r"), closefunc = fclose; 284 } else { 285 char line[BUFSIZ]; 286 287 (void) sprintf(line, cmd, name), name = line; 288 fin = popen(line, "r"), closefunc = pclose; 289 } 290 if (fin == NULL) { 291 if (errno != 0) 292 reply(550, "%s: %s.", name, sys_errlist[errno]); 293 return; 294 } 295 st.st_size = 0; 296 if (cmd == 0 && 297 (stat(name, &st) < 0 || (st.st_mode&S_IFMT) != S_IFREG)) { 298 reply(550, "%s: not a plain file.", name); 299 goto done; 300 } 301 dout = dataconn(name, st.st_size, "w"); 302 if (dout == NULL) 303 goto done; 304 if ((tmp = send_data(fin, dout)) > 0 || ferror(dout) > 0) { 305 reply(550, "%s: %s.", name, sys_errlist[errno]); 306 } 307 else if (tmp == 0) { 308 reply(226, "Transfer complete."); 309 } 310 (void) fclose(dout); 311 data = -1; 312 pdata = -1; 313 done: 314 (*closefunc)(fin); 315 } 316 317 store(name, mode) 318 char *name, *mode; 319 { 320 FILE *fout, *din; 321 int (*closefunc)(), dochown = 0, tmp; 322 char *gunique(), *local; 323 324 #ifdef notdef 325 /* no remote command execution -- it's a security hole */ 326 if (name[0] == '|') 327 fout = popen(&name[1], "w"), closefunc = pclose; 328 else 329 #endif 330 { 331 struct stat st; 332 333 local = name; 334 if (stat(name, &st) < 0) { 335 dochown++; 336 } 337 else if (unique) { 338 if ((local = gunique(name)) == NULL) { 339 return; 340 } 341 dochown++; 342 } 343 fout = fopen(local, mode), closefunc = fclose; 344 } 345 if (fout == NULL) { 346 reply(553, "%s: %s.", local, sys_errlist[errno]); 347 return; 348 } 349 din = dataconn(local, (off_t)-1, "r"); 350 if (din == NULL) 351 goto done; 352 if ((tmp = receive_data(din, fout)) > 0 || ferror(fout) > 0) { 353 reply(552, "%s: %s.", local, sys_errlist[errno]); 354 } 355 else if (tmp == 0 && !unique) { 356 reply(226, "Transfer complete."); 357 } 358 else if (tmp == 0 && unique) { 359 reply(226, "Transfer complete (unique file name:%s).", local); 360 } 361 (void) fclose(din); 362 data = -1; 363 pdata = -1; 364 done: 365 if (dochown) 366 (void) chown(local, pw->pw_uid, -1); 367 (*closefunc)(fout); 368 } 369 370 FILE * 371 getdatasock(mode) 372 char *mode; 373 { 374 int s, on = 1; 375 376 if (data >= 0) 377 return (fdopen(data, mode)); 378 s = socket(AF_INET, SOCK_STREAM, 0); 379 if (s < 0) 380 return (NULL); 381 seteuid(0); 382 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof (on)) < 0) 383 goto bad; 384 /* anchor socket to avoid multi-homing problems */ 385 data_source.sin_family = AF_INET; 386 data_source.sin_addr = ctrl_addr.sin_addr; 387 if (bind(s, &data_source, sizeof (data_source)) < 0) 388 goto bad; 389 seteuid(pw->pw_uid); 390 return (fdopen(s, mode)); 391 bad: 392 seteuid(pw->pw_uid); 393 (void) close(s); 394 return (NULL); 395 } 396 397 FILE * 398 dataconn(name, size, mode) 399 char *name; 400 off_t size; 401 char *mode; 402 { 403 char sizebuf[32]; 404 FILE *file; 405 int retry = 0; 406 407 if (size >= 0) 408 (void) sprintf (sizebuf, " (%ld bytes)", size); 409 else 410 (void) strcpy(sizebuf, ""); 411 if (pdata > 0) { 412 struct sockaddr_in from; 413 int s, fromlen = sizeof(from); 414 415 s = accept(pdata, &from, &fromlen); 416 if (s < 0) { 417 reply(425, "Can't open data connection."); 418 (void) close(pdata); 419 pdata = -1; 420 return(NULL); 421 } 422 (void) close(pdata); 423 pdata = s; 424 reply(150, "Openning data connection for %s (%s,%d)%s.", 425 name, inet_ntoa(from.sin_addr), 426 ntohs(from.sin_port), sizebuf); 427 return(fdopen(pdata, mode)); 428 } 429 if (data >= 0) { 430 reply(125, "Using existing data connection for %s%s.", 431 name, sizebuf); 432 usedefault = 1; 433 return (fdopen(data, mode)); 434 } 435 if (usedefault) 436 data_dest = his_addr; 437 usedefault = 1; 438 file = getdatasock(mode); 439 if (file == NULL) { 440 reply(425, "Can't create data socket (%s,%d): %s.", 441 inet_ntoa(data_source.sin_addr), 442 ntohs(data_source.sin_port), 443 sys_errlist[errno]); 444 return (NULL); 445 } 446 data = fileno(file); 447 while (connect(data, &data_dest, sizeof (data_dest)) < 0) { 448 if (errno == EADDRINUSE && retry < swaitmax) { 449 sleep((unsigned) swaitint); 450 retry += swaitint; 451 continue; 452 } 453 reply(425, "Can't build data connection: %s.", 454 sys_errlist[errno]); 455 (void) fclose(file); 456 data = -1; 457 return (NULL); 458 } 459 reply(150, "Opening data connection for %s (%s,%d)%s.", 460 name, inet_ntoa(data_dest.sin_addr), 461 ntohs(data_dest.sin_port), sizebuf); 462 return (file); 463 } 464 465 /* 466 * Tranfer the contents of "instr" to 467 * "outstr" peer using the appropriate 468 * encapulation of the date subject 469 * to Mode, Structure, and Type. 470 * 471 * NB: Form isn't handled. 472 */ 473 send_data(instr, outstr) 474 FILE *instr, *outstr; 475 { 476 register int c; 477 int netfd, filefd, cnt; 478 char buf[BUFSIZ]; 479 480 transflag++; 481 if (setjmp(urgcatch)) { 482 transflag = 0; 483 return(-1); 484 } 485 switch (type) { 486 487 case TYPE_A: 488 while ((c = getc(instr)) != EOF) { 489 if (c == '\n') { 490 if (ferror (outstr)) { 491 transflag = 0; 492 return (1); 493 } 494 (void) putc('\r', outstr); 495 } 496 (void) putc(c, outstr); 497 /* if (c == '\r') */ 498 /* putc ('\0', outstr); */ 499 } 500 transflag = 0; 501 if (ferror (instr) || ferror (outstr)) { 502 return (1); 503 } 504 return (0); 505 506 case TYPE_I: 507 case TYPE_L: 508 netfd = fileno(outstr); 509 filefd = fileno(instr); 510 511 while ((cnt = read(filefd, buf, sizeof (buf))) > 0) { 512 if (write(netfd, buf, cnt) < 0) { 513 transflag = 0; 514 return (1); 515 } 516 } 517 transflag = 0; 518 return (cnt < 0); 519 } 520 reply(550, "Unimplemented TYPE %d in send_data", type); 521 transflag = 0; 522 return (-1); 523 } 524 525 /* 526 * Transfer data from peer to 527 * "outstr" using the appropriate 528 * encapulation of the data subject 529 * to Mode, Structure, and Type. 530 * 531 * N.B.: Form isn't handled. 532 */ 533 receive_data(instr, outstr) 534 FILE *instr, *outstr; 535 { 536 register int c; 537 int cnt; 538 char buf[BUFSIZ]; 539 540 541 transflag++; 542 if (setjmp(urgcatch)) { 543 transflag = 0; 544 return(-1); 545 } 546 switch (type) { 547 548 case TYPE_I: 549 case TYPE_L: 550 while ((cnt = read(fileno(instr), buf, sizeof buf)) > 0) { 551 if (write(fileno(outstr), buf, cnt) < 0) { 552 transflag = 0; 553 return (1); 554 } 555 } 556 transflag = 0; 557 return (cnt < 0); 558 559 case TYPE_E: 560 reply(553, "TYPE E not implemented."); 561 transflag = 0; 562 return (-1); 563 564 case TYPE_A: 565 while ((c = getc(instr)) != EOF) { 566 while (c == '\r') { 567 if (ferror (outstr)) { 568 transflag = 0; 569 return (1); 570 } 571 if ((c = getc(instr)) != '\n') 572 (void) putc ('\r', outstr); 573 /* if (c == '\0') */ 574 /* continue; */ 575 } 576 (void) putc (c, outstr); 577 } 578 transflag = 0; 579 if (ferror (instr) || ferror (outstr)) 580 return (1); 581 return (0); 582 } 583 transflag = 0; 584 fatal("Unknown type in receive_data."); 585 /*NOTREACHED*/ 586 } 587 588 fatal(s) 589 char *s; 590 { 591 reply(451, "Error in server: %s\n", s); 592 reply(221, "Closing connection due to server error."); 593 dologout(0); 594 } 595 596 /*VARARGS2*/ 597 reply(n, s, args) 598 int n; 599 char *s; 600 { 601 602 printf("%d ", n); 603 _doprnt(s, &args, stdout); 604 printf("\r\n"); 605 (void) fflush(stdout); 606 if (debug) { 607 syslog(LOG_DEBUG, "<--- %d ", n); 608 syslog(LOG_DEBUG, s, &args); 609 } 610 } 611 612 /*VARARGS2*/ 613 lreply(n, s, args) 614 int n; 615 char *s; 616 { 617 printf("%d-", n); 618 _doprnt(s, &args, stdout); 619 printf("\r\n"); 620 (void) fflush(stdout); 621 if (debug) { 622 syslog(LOG_DEBUG, "<--- %d- ", n); 623 syslog(LOG_DEBUG, s, &args); 624 } 625 } 626 627 ack(s) 628 char *s; 629 { 630 reply(250, "%s command successful.", s); 631 } 632 633 nack(s) 634 char *s; 635 { 636 reply(502, "%s command not implemented.", s); 637 } 638 639 yyerror(s) 640 char *s; 641 { 642 char *cp; 643 644 cp = index(cbuf,'\n'); 645 *cp = '\0'; 646 reply(500, "'%s': command not understood.",cbuf); 647 } 648 649 delete(name) 650 char *name; 651 { 652 struct stat st; 653 654 if (stat(name, &st) < 0) { 655 reply(550, "%s: %s.", name, sys_errlist[errno]); 656 return; 657 } 658 if ((st.st_mode&S_IFMT) == S_IFDIR) { 659 if (rmdir(name) < 0) { 660 reply(550, "%s: %s.", name, sys_errlist[errno]); 661 return; 662 } 663 goto done; 664 } 665 if (unlink(name) < 0) { 666 reply(550, "%s: %s.", name, sys_errlist[errno]); 667 return; 668 } 669 done: 670 ack("DELE"); 671 } 672 673 cwd(path) 674 char *path; 675 { 676 677 if (chdir(path) < 0) { 678 reply(550, "%s: %s.", path, sys_errlist[errno]); 679 return; 680 } 681 ack("CWD"); 682 } 683 684 makedir(name) 685 char *name; 686 { 687 struct stat st; 688 int dochown = stat(name, &st) < 0; 689 690 if (mkdir(name, 0777) < 0) { 691 reply(550, "%s: %s.", name, sys_errlist[errno]); 692 return; 693 } 694 if (dochown) 695 (void) chown(name, pw->pw_uid, -1); 696 reply(257, "MKD command successful."); 697 } 698 699 removedir(name) 700 char *name; 701 { 702 703 if (rmdir(name) < 0) { 704 reply(550, "%s: %s.", name, sys_errlist[errno]); 705 return; 706 } 707 ack("RMD"); 708 } 709 710 pwd() 711 { 712 char path[MAXPATHLEN + 1]; 713 714 if (getwd(path) == NULL) { 715 reply(550, "%s.", path); 716 return; 717 } 718 reply(257, "\"%s\" is current directory.", path); 719 } 720 721 char * 722 renamefrom(name) 723 char *name; 724 { 725 struct stat st; 726 727 if (stat(name, &st) < 0) { 728 reply(550, "%s: %s.", name, sys_errlist[errno]); 729 return ((char *)0); 730 } 731 reply(350, "File exists, ready for destination name"); 732 return (name); 733 } 734 735 renamecmd(from, to) 736 char *from, *to; 737 { 738 739 if (rename(from, to) < 0) { 740 reply(550, "rename: %s.", sys_errlist[errno]); 741 return; 742 } 743 ack("RNTO"); 744 } 745 746 dolog(sin) 747 struct sockaddr_in *sin; 748 { 749 struct hostent *hp = gethostbyaddr(&sin->sin_addr, 750 sizeof (struct in_addr), AF_INET); 751 time_t t; 752 extern char *ctime(); 753 754 if (hp) { 755 (void) strncpy(remotehost, hp->h_name, sizeof (remotehost)); 756 endhostent(); 757 } else 758 (void) strncpy(remotehost, inet_ntoa(sin->sin_addr), 759 sizeof (remotehost)); 760 if (!logging) 761 return; 762 t = time((time_t *) 0); 763 syslog(LOG_INFO,"FTPD: connection from %s at %s", remotehost, ctime(&t)); 764 } 765 766 #include <utmp.h> 767 768 #define SCPYN(a, b) (void) strncpy(a, b, sizeof (a)) 769 struct utmp utmp; 770 771 /* 772 * Record login in wtmp file. 773 */ 774 dologin(pw) 775 struct passwd *pw; 776 { 777 char line[32]; 778 779 if (wtmp >= 0) { 780 /* hack, but must be unique and no tty line */ 781 (void) sprintf(line, "ftp%d", getpid()); 782 SCPYN(utmp.ut_line, line); 783 SCPYN(utmp.ut_name, pw->pw_name); 784 SCPYN(utmp.ut_host, remotehost); 785 utmp.ut_time = (long) time((time_t *) 0); 786 (void) write(wtmp, (char *)&utmp, sizeof (utmp)); 787 if (!guest) { /* anon must hang on */ 788 (void) close(wtmp); 789 wtmp = -1; 790 } 791 } 792 } 793 794 /* 795 * Record logout in wtmp file 796 * and exit with supplied status. 797 */ 798 dologout(status) 799 int status; 800 { 801 802 if (logged_in) { 803 (void) seteuid(0); 804 if (wtmp < 0) 805 wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND); 806 if (wtmp >= 0) { 807 SCPYN(utmp.ut_name, ""); 808 SCPYN(utmp.ut_host, ""); 809 utmp.ut_time = (long) time((time_t *) 0); 810 (void) write(wtmp, (char *)&utmp, sizeof (utmp)); 811 (void) close(wtmp); 812 } 813 } 814 /* beware of flushing buffers after a SIGPIPE */ 815 _exit(status); 816 } 817 818 /* 819 * Special version of popen which avoids 820 * call to shell. This insures noone may 821 * create a pipe to a hidden program as a side 822 * effect of a list or dir command. 823 */ 824 #define tst(a,b) (*mode == 'r'? (b) : (a)) 825 #define RDR 0 826 #define WTR 1 827 static int popen_pid[5]; 828 829 static char * 830 nextarg(cpp) 831 char *cpp; 832 { 833 register char *cp = cpp; 834 835 if (cp == 0) 836 return (cp); 837 while (*cp && *cp != ' ' && *cp != '\t') 838 cp++; 839 if (*cp == ' ' || *cp == '\t') { 840 *cp++ = '\0'; 841 while (*cp == ' ' || *cp == '\t') 842 cp++; 843 } 844 if (cp == cpp) 845 return ((char *)0); 846 return (cp); 847 } 848 849 FILE * 850 popen(cmd, mode) 851 char *cmd, *mode; 852 { 853 int p[2], ac, gac; 854 register myside, hisside, pid; 855 char *av[20], *gav[512]; 856 register char *cp; 857 858 if (pipe(p) < 0) 859 return (NULL); 860 cp = cmd, ac = 0; 861 /* break up string into pieces */ 862 do { 863 av[ac++] = cp; 864 cp = nextarg(cp); 865 } while (cp && *cp && ac < 20); 866 av[ac] = (char *)0; 867 gav[0] = av[0]; 868 /* glob each piece */ 869 for (gac = ac = 1; av[ac] != NULL; ac++) { 870 char **pop; 871 extern char **glob(), **copyblk(); 872 873 pop = glob(av[ac]); 874 if (pop == (char **)NULL) { /* globbing failed */ 875 char *vv[2]; 876 877 vv[0] = av[ac]; 878 vv[1] = 0; 879 pop = copyblk(vv); 880 } 881 av[ac] = (char *)pop; /* save to free later */ 882 while (*pop && gac < 512) 883 gav[gac++] = *pop++; 884 } 885 gav[gac] = (char *)0; 886 myside = tst(p[WTR], p[RDR]); 887 hisside = tst(p[RDR], p[WTR]); 888 if ((pid = fork()) == 0) { 889 /* myside and hisside reverse roles in child */ 890 (void) close(myside); 891 (void) dup2(hisside, tst(0, 1)); 892 (void) close(hisside); 893 execv(gav[0], gav); 894 _exit(1); 895 } 896 for (ac = 1; av[ac] != NULL; ac++) 897 blkfree((char **)av[ac]); 898 if (pid == -1) 899 return (NULL); 900 popen_pid[myside] = pid; 901 (void) close(hisside); 902 return (fdopen(myside, mode)); 903 } 904 905 pclose(ptr) 906 FILE *ptr; 907 { 908 register f, r, (*hstat)(), (*istat)(), (*qstat)(); 909 int status; 910 911 f = fileno(ptr); 912 (void) fclose(ptr); 913 istat = signal(SIGINT, SIG_IGN); 914 qstat = signal(SIGQUIT, SIG_IGN); 915 hstat = signal(SIGHUP, SIG_IGN); 916 while ((r = wait(&status)) != popen_pid[f] && r != -1) 917 ; 918 if (r == -1) 919 status = -1; 920 (void) signal(SIGINT, istat); 921 (void) signal(SIGQUIT, qstat); 922 (void) signal(SIGHUP, hstat); 923 return (status); 924 } 925 926 /* 927 * Check user requesting login priviledges. 928 * Disallow anyone who does not have a standard 929 * shell returned by getusershell() (/etc/shells). 930 * Disallow anyone mentioned in the file FTPUSERS 931 * to allow people such as uucp to be avoided. 932 */ 933 checkuser(name) 934 register char *name; 935 { 936 register char *cp; 937 char line[BUFSIZ], *index(), *getusershell(); 938 FILE *fd; 939 struct passwd *pw; 940 int found = 0; 941 942 pw = getpwnam(name); 943 if (pw == NULL) 944 return (0); 945 if (pw ->pw_shell == NULL || pw->pw_shell[0] == NULL) 946 pw->pw_shell = "/bin/sh"; 947 while ((cp = getusershell()) != NULL) 948 if (strcmp(cp, pw->pw_shell) == 0) 949 break; 950 endusershell(); 951 if (cp == NULL) 952 return (0); 953 fd = fopen(FTPUSERS, "r"); 954 if (fd == NULL) 955 return (1); 956 while (fgets(line, sizeof (line), fd) != NULL) { 957 cp = index(line, '\n'); 958 if (cp) 959 *cp = '\0'; 960 if (strcmp(line, name) == 0) { 961 found++; 962 break; 963 } 964 } 965 (void) fclose(fd); 966 return (!found); 967 } 968 969 myoob() 970 { 971 char *cp; 972 973 /* only process if transfer occurring */ 974 if (!transflag) { 975 return; 976 } 977 cp = tmpline; 978 if (getline(cp, 7, stdin) == NULL) { 979 reply(221, "You could at least say goodby."); 980 dologout(0); 981 } 982 upper(cp); 983 if (strcmp(cp, "ABOR\r\n")) 984 return; 985 tmpline[0] = '\0'; 986 reply(426,"Transfer aborted. Data connection closed."); 987 reply(226,"Abort successful"); 988 longjmp(urgcatch, 1); 989 } 990 991 /* 992 * Note: The 530 reply codes could be 4xx codes, except nothing is 993 * given in the state tables except 421 which implies an exit. (RFC959) 994 */ 995 passive() 996 { 997 int len; 998 struct sockaddr_in tmp; 999 register char *p, *a; 1000 1001 pdata = socket(AF_INET, SOCK_STREAM, 0); 1002 if (pdata < 0) { 1003 reply(530, "Can't open passive connection"); 1004 return; 1005 } 1006 tmp = ctrl_addr; 1007 tmp.sin_port = 0; 1008 seteuid(0); 1009 if (bind(pdata, (struct sockaddr *) &tmp, sizeof(tmp)) < 0) { 1010 seteuid(pw->pw_uid); 1011 (void) close(pdata); 1012 pdata = -1; 1013 reply(530, "Can't open passive connection"); 1014 return; 1015 } 1016 seteuid(pw->pw_uid); 1017 len = sizeof(tmp); 1018 if (getsockname(pdata, (char *) &tmp, &len) < 0) { 1019 (void) close(pdata); 1020 pdata = -1; 1021 reply(530, "Can't open passive connection"); 1022 return; 1023 } 1024 if (listen(pdata, 1) < 0) { 1025 (void) close(pdata); 1026 pdata = -1; 1027 reply(530, "Can't open passive connection"); 1028 return; 1029 } 1030 a = (char *) &tmp.sin_addr; 1031 p = (char *) &tmp.sin_port; 1032 1033 #define UC(b) (((int) b) & 0xff) 1034 1035 reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]), 1036 UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); 1037 } 1038 1039 char * 1040 gunique(local) 1041 char *local; 1042 { 1043 static char new[MAXPATHLEN]; 1044 char *cp = rindex(local, '/'); 1045 int d, count=0; 1046 char ext = '1'; 1047 1048 if (cp) { 1049 *cp = '\0'; 1050 } 1051 d = access(cp ? local : ".", 2); 1052 if (cp) { 1053 *cp = '/'; 1054 } 1055 if (d < 0) { 1056 syslog(LOG_ERR, "%s: %m", local); 1057 return((char *) 0); 1058 } 1059 (void) strcpy(new, local); 1060 cp = new + strlen(new); 1061 *cp++ = '.'; 1062 while (!d) { 1063 if (++count == 100) { 1064 reply(452, "Unique file name not cannot be created."); 1065 return((char *) 0); 1066 } 1067 *cp++ = ext; 1068 *cp = '\0'; 1069 if (ext == '9') { 1070 ext = '0'; 1071 } 1072 else { 1073 ext++; 1074 } 1075 if ((d = access(new, 0)) < 0) { 1076 break; 1077 } 1078 if (ext != '0') { 1079 cp--; 1080 } 1081 else if (*(cp - 2) == '.') { 1082 *(cp - 1) = '1'; 1083 } 1084 else { 1085 *(cp - 2) = *(cp - 2) + 1; 1086 cp--; 1087 } 1088 } 1089 return(new); 1090 } 1091