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