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