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