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