1 /* $OpenBSD: ftp.c,v 1.79 2009/06/06 23:14:44 martynas Exp $ */ 2 /* $NetBSD: ftp.c,v 1.27 1997/08/18 10:20:23 lukem Exp $ */ 3 4 /* 5 * Copyright (C) 1997 and 1998 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the project nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 /* 34 * Copyright (c) 1985, 1989, 1993, 1994 35 * The Regents of the University of California. All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. Neither the name of the University nor the names of its contributors 46 * may be used to endorse or promote products derived from this software 47 * without specific prior written permission. 48 * 49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 * SUCH DAMAGE. 60 */ 61 62 #include <sys/types.h> 63 #include <sys/stat.h> 64 #include <sys/socket.h> 65 66 #include <netinet/in.h> 67 #include <netinet/in_systm.h> 68 #include <netinet/ip.h> 69 #include <arpa/inet.h> 70 #include <arpa/ftp.h> 71 #include <arpa/telnet.h> 72 73 #include <ctype.h> 74 #include <err.h> 75 #include <errno.h> 76 #include <netdb.h> 77 #include <poll.h> 78 #include <stdarg.h> 79 #include <stdio.h> 80 #include <stdlib.h> 81 #include <string.h> 82 #include <unistd.h> 83 #include <utime.h> 84 85 #include "ftp_var.h" 86 87 union sockunion { 88 struct sockinet { 89 u_char si_len; 90 u_char si_family; 91 u_short si_port; 92 } su_si; 93 struct sockaddr_in su_sin; 94 struct sockaddr_in6 su_sin6; 95 }; 96 #define su_len su_si.si_len 97 #define su_family su_si.si_family 98 #define su_port su_si.si_port 99 100 union sockunion myctladdr, hisctladdr, data_addr; 101 102 int data = -1; 103 int abrtflag = 0; 104 jmp_buf ptabort; 105 int ptabflg; 106 int ptflag = 0; 107 off_t restart_point = 0; 108 109 110 FILE *cin, *cout; 111 112 char * 113 hookup(char *host, char *port) 114 { 115 int s, tos, error; 116 static char hostnamebuf[MAXHOSTNAMELEN]; 117 struct addrinfo hints, *res, *res0; 118 char hbuf[NI_MAXHOST]; 119 char *cause = "unknown"; 120 socklen_t namelen; 121 122 epsv4bad = 0; 123 124 memset((char *)&hisctladdr, 0, sizeof (hisctladdr)); 125 memset(&hints, 0, sizeof(hints)); 126 hints.ai_flags = AI_CANONNAME; 127 hints.ai_family = family; 128 hints.ai_socktype = SOCK_STREAM; 129 hints.ai_protocol = 0; 130 error = getaddrinfo(host, port, &hints, &res0); 131 if (error == EAI_SERVICE) { 132 /* 133 * If the services file is corrupt/missing, fall back 134 * on our hard-coded defines. 135 */ 136 char pbuf[NI_MAXSERV]; 137 138 pbuf[0] = '\0'; 139 if (strcmp(port, "ftp") == 0) 140 snprintf(pbuf, sizeof(pbuf), "%d", FTP_PORT); 141 else if (strcmp(port, "ftpgate") == 0) 142 snprintf(pbuf, sizeof(pbuf), "%d", GATE_PORT); 143 else if (strcmp(port, "http") == 0) 144 snprintf(pbuf, sizeof(pbuf), "%d", HTTP_PORT); 145 #ifndef SMALL 146 else if (strcmp(port, "https") == 0) 147 snprintf(pbuf, sizeof(pbuf), "%d", HTTPS_PORT); 148 #endif /* !SMALL */ 149 if (pbuf[0]) 150 error = getaddrinfo(host, pbuf, &hints, &res0); 151 } 152 if (error) { 153 if (error == EAI_SERVICE) 154 warnx("%s: bad port number `%s'", host, port); 155 else 156 warnx("%s: %s", host, gai_strerror(error)); 157 code = -1; 158 return (0); 159 } 160 161 if (res0->ai_canonname) 162 strlcpy(hostnamebuf, res0->ai_canonname, sizeof(hostnamebuf)); 163 else 164 strlcpy(hostnamebuf, host, sizeof(hostnamebuf)); 165 hostname = hostnamebuf; 166 167 s = -1; 168 for (res = res0; res; res = res->ai_next) { 169 #if 0 /*old behavior*/ 170 if (res != res0) /* not on the first address */ 171 #else 172 if (res0->ai_next) /* if we have multiple possibilities */ 173 #endif 174 { 175 if (getnameinfo(res->ai_addr, res->ai_addrlen, 176 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) 177 strlcpy(hbuf, "unknown", sizeof(hbuf)); 178 if (verbose) 179 fprintf(ttyout, "Trying %s...\n", hbuf); 180 } 181 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 182 if (s < 0) { 183 cause = "socket"; 184 continue; 185 } 186 while ((error = connect(s, res->ai_addr, res->ai_addrlen)) < 0 187 && errno == EINTR) { 188 ; 189 } 190 if (error) { 191 /* this "if" clause is to prevent print warning twice */ 192 if (verbose && res->ai_next) { 193 if (getnameinfo(res->ai_addr, res->ai_addrlen, 194 hbuf, sizeof(hbuf), NULL, 0, 195 NI_NUMERICHOST) != 0) 196 strlcpy(hbuf, "(unknown)", 197 sizeof(hbuf)); 198 warn("connect to address %s", hbuf); 199 } 200 cause = "connect"; 201 error = errno; 202 close(s); 203 errno = error; 204 s = -1; 205 continue; 206 } 207 208 /* finally we got one */ 209 break; 210 } 211 if (s < 0) { 212 warn("%s", cause); 213 code = -1; 214 freeaddrinfo(res0); 215 return 0; 216 } 217 memcpy(&hisctladdr, res->ai_addr, res->ai_addrlen); 218 namelen = res->ai_addrlen; 219 freeaddrinfo(res0); 220 res0 = res = NULL; 221 if (getsockname(s, (struct sockaddr *)&myctladdr, &namelen) < 0) { 222 warn("getsockname"); 223 code = -1; 224 goto bad; 225 } 226 #if defined(IPPROTO_IP) && defined(IP_TOS) 227 if (hisctladdr.su_family == AF_INET) { 228 tos = IPTOS_LOWDELAY; 229 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) 230 warn("setsockopt TOS (ignored)"); 231 } 232 #endif 233 cin = fdopen(s, "r"); 234 cout = fdopen(s, "w"); 235 if (cin == NULL || cout == NULL) { 236 warnx("fdopen failed."); 237 if (cin) 238 (void)fclose(cin); 239 if (cout) 240 (void)fclose(cout); 241 code = -1; 242 goto bad; 243 } 244 if (verbose) 245 fprintf(ttyout, "Connected to %s.\n", hostname); 246 if (getreply(0) > 2) { /* read startup message from server */ 247 if (cin) 248 (void)fclose(cin); 249 if (cout) 250 (void)fclose(cout); 251 code = -1; 252 goto bad; 253 } 254 #ifdef SO_OOBINLINE 255 { 256 int ret, on = 1; 257 258 ret = setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)); 259 #ifndef SMALL 260 if (ret < 0 && debug) 261 warn("setsockopt"); 262 #endif /* !SMALL */ 263 } 264 #endif /* SO_OOBINLINE */ 265 266 return (hostname); 267 bad: 268 (void)close(s); 269 return ((char *)0); 270 } 271 272 /* ARGSUSED */ 273 void 274 cmdabort(int signo) 275 { 276 277 alarmtimer(0); 278 putc('\n', ttyout); 279 (void)fflush(ttyout); 280 abrtflag++; 281 if (ptflag) 282 longjmp(ptabort, 1); 283 } 284 285 /*VARARGS*/ 286 int 287 command(const char *fmt, ...) 288 { 289 va_list ap; 290 int r; 291 sig_t oldintr; 292 293 abrtflag = 0; 294 #ifndef SMALL 295 if (debug) { 296 fputs("---> ", ttyout); 297 va_start(ap, fmt); 298 if (strncmp("PASS ", fmt, 5) == 0) 299 fputs("PASS XXXX", ttyout); 300 else if (strncmp("ACCT ", fmt, 5) == 0) 301 fputs("ACCT XXXX", ttyout); 302 else 303 vfprintf(ttyout, fmt, ap); 304 va_end(ap); 305 putc('\n', ttyout); 306 (void)fflush(ttyout); 307 } 308 #endif /* !SMALL */ 309 if (cout == NULL) { 310 warnx("No control connection for command."); 311 code = -1; 312 return (0); 313 } 314 oldintr = signal(SIGINT, cmdabort); 315 va_start(ap, fmt); 316 vfprintf(cout, fmt, ap); 317 va_end(ap); 318 fputs("\r\n", cout); 319 (void)fflush(cout); 320 cpend = 1; 321 r = getreply(!strcmp(fmt, "QUIT")); 322 if (abrtflag && oldintr != SIG_IGN) 323 (*oldintr)(SIGINT); 324 (void)signal(SIGINT, oldintr); 325 return (r); 326 } 327 328 int keep_alive_timeout = 60; /* 0 -> no timeout */ 329 330 static int full_noops_sent = 0; 331 static time_t last_timestamp = 0; /* 0 -> no measurement yet */ 332 static char noop[] = "NOOP\r\n"; 333 #define NOOP_LENGTH (sizeof noop - 1) 334 static int current_nop_pos = 0; /* 0 -> no noop started */ 335 336 /* to achieve keep alive, we send noop one byte at a time */ 337 void 338 send_noop_char() 339 { 340 #ifndef SMALL 341 if (debug) 342 fprintf(ttyout, "---> %c\n", noop[current_nop_pos]); 343 #endif /* !SMALL */ 344 fputc(noop[current_nop_pos++], cout); 345 (void)fflush(cout); 346 if (current_nop_pos >= NOOP_LENGTH) { 347 full_noops_sent++; 348 current_nop_pos = 0; 349 } 350 } 351 352 void 353 may_reset_noop_timeout() 354 { 355 if (keep_alive_timeout != 0) 356 last_timestamp = time(NULL); 357 } 358 359 void 360 may_receive_noop_ack() 361 { 362 int i; 363 364 if (cout == NULL) { 365 /* Lost connection; so just pretend we're fine. */ 366 current_nop_pos = full_noops_sent = 0; 367 return; 368 } 369 370 /* finish sending last incomplete noop */ 371 if (current_nop_pos != 0) { 372 fputs(&(noop[current_nop_pos]), cout); 373 #ifndef SMALL 374 if (debug) 375 fprintf(ttyout, "---> %s\n", &(noop[current_nop_pos])); 376 #endif /* !SMALL */ 377 (void)fflush(cout); 378 current_nop_pos = 0; 379 full_noops_sent++; 380 } 381 /* and get the replies */ 382 for (i = 0; i < full_noops_sent; i++) 383 (void)getreply(0); 384 385 full_noops_sent = 0; 386 } 387 388 void 389 may_send_noop_char() 390 { 391 if (keep_alive_timeout != 0) { 392 if (last_timestamp != 0) { 393 time_t t = time(NULL); 394 395 if (t - last_timestamp >= keep_alive_timeout) { 396 last_timestamp = t; 397 send_noop_char(); 398 } 399 } else { 400 last_timestamp = time(NULL); 401 } 402 } 403 } 404 405 char reply_string[BUFSIZ]; /* first line of previous reply */ 406 407 int 408 getreply(int expecteof) 409 { 410 char current_line[BUFSIZ]; /* last line of previous reply */ 411 int c, n, lineno; 412 int dig; 413 int originalcode = 0, continuation = 0; 414 sig_t oldintr; 415 int pflag = 0; 416 char *cp, *pt = pasv; 417 418 memset(current_line, 0, sizeof(current_line)); 419 oldintr = signal(SIGINT, cmdabort); 420 for (lineno = 0 ;; lineno++) { 421 dig = n = code = 0; 422 cp = current_line; 423 while ((c = fgetc(cin)) != '\n') { 424 if (c == IAC) { /* handle telnet commands */ 425 switch (c = fgetc(cin)) { 426 case WILL: 427 case WONT: 428 c = fgetc(cin); 429 fprintf(cout, "%c%c%c", IAC, DONT, c); 430 (void)fflush(cout); 431 break; 432 case DO: 433 case DONT: 434 c = fgetc(cin); 435 fprintf(cout, "%c%c%c", IAC, WONT, c); 436 (void)fflush(cout); 437 break; 438 default: 439 break; 440 } 441 continue; 442 } 443 dig++; 444 if (c == EOF) { 445 if (expecteof) { 446 (void)signal(SIGINT, oldintr); 447 code = 221; 448 return (0); 449 } 450 lostpeer(); 451 if (verbose) { 452 fputs( 453 "421 Service not available, remote server has closed connection.\n", ttyout); 454 (void)fflush(ttyout); 455 } 456 code = 421; 457 return (4); 458 } 459 if (c != '\r' && (verbose > 0 || 460 ((verbose > -1 && n == '5' && dig > 4) && 461 (((!n && c < '5') || (n && n < '5')) 462 || !retry_connect)))) { 463 if (proxflag && 464 (dig == 1 || (dig == 5 && verbose == 0))) 465 fprintf(ttyout, "%s:", hostname); 466 (void)putc(c, ttyout); 467 } 468 if (dig < 4 && isdigit(c)) 469 code = code * 10 + (c - '0'); 470 if (!pflag && (code == 227 || code == 228)) 471 pflag = 1; 472 else if (!pflag && code == 229) 473 pflag = 100; 474 if (dig > 4 && pflag == 1 && isdigit(c)) 475 pflag = 2; 476 if (pflag == 2) { 477 if (c != '\r' && c != ')') { 478 if (pt < &pasv[sizeof(pasv) - 1]) 479 *pt++ = c; 480 } else { 481 *pt = '\0'; 482 pflag = 3; 483 } 484 } 485 if (pflag == 100 && c == '(') 486 pflag = 2; 487 if (dig == 4 && c == '-') { 488 if (continuation) 489 code = 0; 490 continuation++; 491 } 492 if (n == 0) 493 n = c; 494 if (cp < ¤t_line[sizeof(current_line) - 1]) 495 *cp++ = c; 496 } 497 if (verbose > 0 || ((verbose > -1 && n == '5') && 498 (n < '5' || !retry_connect))) { 499 (void)putc(c, ttyout); 500 (void)fflush (ttyout); 501 } 502 if (lineno == 0) { 503 size_t len = cp - current_line; 504 505 if (len > sizeof(reply_string)) 506 len = sizeof(reply_string); 507 508 (void)strlcpy(reply_string, current_line, len); 509 } 510 if (continuation && code != originalcode) { 511 if (originalcode == 0) 512 originalcode = code; 513 continue; 514 } 515 *cp = '\0'; 516 if (n != '1') 517 cpend = 0; 518 (void)signal(SIGINT, oldintr); 519 if (code == 421 || originalcode == 421) 520 lostpeer(); 521 if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) 522 (*oldintr)(SIGINT); 523 return (n - '0'); 524 } 525 } 526 527 #ifndef SMALL 528 jmp_buf sendabort; 529 530 /* ARGSUSED */ 531 void 532 abortsend(int signo) 533 { 534 535 alarmtimer(0); 536 mflag = 0; 537 abrtflag = 0; 538 fputs("\nsend aborted\nwaiting for remote to finish abort.\n", ttyout); 539 (void)fflush(ttyout); 540 longjmp(sendabort, 1); 541 } 542 543 void 544 sendrequest(const char *cmd, const char *local, const char *remote, 545 int printnames) 546 { 547 struct stat st; 548 int c, d; 549 FILE * volatile fin, * volatile dout; 550 int (* volatile closefunc)(FILE *); 551 volatile sig_t oldinti, oldintr, oldintp; 552 volatile off_t hashbytes; 553 char * volatile lmode; 554 char buf[BUFSIZ], *bufp; 555 int oprogress, serrno; 556 557 hashbytes = mark; 558 direction = "sent"; 559 dout = NULL; 560 bytes = 0; 561 filesize = -1; 562 oprogress = progress; 563 if (verbose && printnames) { 564 if (local && *local != '-') 565 fprintf(ttyout, "local: %s ", local); 566 if (remote) 567 fprintf(ttyout, "remote: %s\n", remote); 568 } 569 if (proxy) { 570 proxtrans(cmd, local, remote); 571 return; 572 } 573 if (curtype != type) 574 changetype(type, 0); 575 closefunc = NULL; 576 oldintr = NULL; 577 oldintp = NULL; 578 oldinti = NULL; 579 lmode = "w"; 580 if (setjmp(sendabort)) { 581 while (cpend) { 582 (void)getreply(0); 583 } 584 if (data >= 0) { 585 (void)close(data); 586 data = -1; 587 } 588 if (oldintr) 589 (void)signal(SIGINT, oldintr); 590 if (oldintp) 591 (void)signal(SIGPIPE, oldintp); 592 if (oldinti) 593 (void)signal(SIGINFO, oldinti); 594 progress = oprogress; 595 code = -1; 596 return; 597 } 598 oldintr = signal(SIGINT, abortsend); 599 oldinti = signal(SIGINFO, psummary); 600 if (strcmp(local, "-") == 0) { 601 fin = stdin; 602 if (progress == 1) 603 progress = 0; 604 } else if (*local == '|') { 605 oldintp = signal(SIGPIPE, SIG_IGN); 606 fin = popen(local + 1, "r"); 607 if (fin == NULL) { 608 warn("%s", local + 1); 609 (void)signal(SIGINT, oldintr); 610 (void)signal(SIGPIPE, oldintp); 611 (void)signal(SIGINFO, oldinti); 612 code = -1; 613 return; 614 } 615 if (progress == 1) 616 progress = 0; 617 closefunc = pclose; 618 } else { 619 fin = fopen(local, "r"); 620 if (fin == NULL) { 621 warn("local: %s", local); 622 (void)signal(SIGINT, oldintr); 623 (void)signal(SIGINFO, oldinti); 624 code = -1; 625 return; 626 } 627 closefunc = fclose; 628 if (fstat(fileno(fin), &st) < 0 || 629 (st.st_mode & S_IFMT) != S_IFREG) { 630 fprintf(ttyout, "%s: not a plain file.\n", local); 631 (void)signal(SIGINT, oldintr); 632 (void)signal(SIGINFO, oldinti); 633 fclose(fin); 634 code = -1; 635 return; 636 } 637 filesize = st.st_size; 638 } 639 if (initconn()) { 640 (void)signal(SIGINT, oldintr); 641 (void)signal(SIGINFO, oldinti); 642 if (oldintp) 643 (void)signal(SIGPIPE, oldintp); 644 code = -1; 645 progress = oprogress; 646 if (closefunc != NULL) 647 (*closefunc)(fin); 648 return; 649 } 650 if (setjmp(sendabort)) 651 goto abort; 652 653 if (restart_point && 654 (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) { 655 int rc = -1; 656 657 switch (curtype) { 658 case TYPE_A: 659 rc = fseeko(fin, restart_point, SEEK_SET); 660 break; 661 case TYPE_I: 662 case TYPE_L: 663 if (lseek(fileno(fin), restart_point, SEEK_SET) != -1) 664 rc = 0; 665 break; 666 } 667 if (rc == -1) { 668 warn("local: %s", local); 669 progress = oprogress; 670 if (closefunc != NULL) 671 (*closefunc)(fin); 672 return; 673 } 674 if (command("REST %lld", (long long) restart_point) 675 != CONTINUE) { 676 progress = oprogress; 677 if (closefunc != NULL) 678 (*closefunc)(fin); 679 return; 680 } 681 lmode = "r+w"; 682 } 683 if (remote) { 684 if (command("%s %s", cmd, remote) != PRELIM) { 685 (void)signal(SIGINT, oldintr); 686 (void)signal(SIGINFO, oldinti); 687 progress = oprogress; 688 if (oldintp) 689 (void)signal(SIGPIPE, oldintp); 690 if (closefunc != NULL) 691 (*closefunc)(fin); 692 return; 693 } 694 } else 695 if (command("%s", cmd) != PRELIM) { 696 (void)signal(SIGINT, oldintr); 697 (void)signal(SIGINFO, oldinti); 698 progress = oprogress; 699 if (oldintp) 700 (void)signal(SIGPIPE, oldintp); 701 if (closefunc != NULL) 702 (*closefunc)(fin); 703 return; 704 } 705 dout = dataconn(lmode); 706 if (dout == NULL) 707 goto abort; 708 progressmeter(-1, remote); 709 may_reset_noop_timeout(); 710 oldintp = signal(SIGPIPE, SIG_IGN); 711 switch (curtype) { 712 713 case TYPE_I: 714 case TYPE_L: 715 d = 0; 716 while ((c = read(fileno(fin), buf, sizeof(buf))) > 0) { 717 may_send_noop_char(); 718 bytes += c; 719 for (bufp = buf; c > 0; c -= d, bufp += d) 720 if ((d = write(fileno(dout), bufp, (size_t)c)) 721 <= 0) 722 break; 723 if (hash && (!progress || filesize < 0) ) { 724 while (bytes >= hashbytes) { 725 (void)putc('#', ttyout); 726 hashbytes += mark; 727 } 728 (void)fflush(ttyout); 729 } 730 } 731 if (c == -1 || d == -1) 732 serrno = errno; 733 if (hash && (!progress || filesize < 0) && bytes > 0) { 734 if (bytes < mark) 735 (void)putc('#', ttyout); 736 (void)putc('\n', ttyout); 737 (void)fflush(ttyout); 738 } 739 if (c < 0) 740 warnx("local: %s: %s", local, strerror(serrno)); 741 if (d < 0) { 742 if (serrno != EPIPE) 743 warnx("netout: %s", strerror(serrno)); 744 bytes = -1; 745 } 746 break; 747 748 case TYPE_A: 749 while ((c = fgetc(fin)) != EOF) { 750 may_send_noop_char(); 751 if (c == '\n') { 752 while (hash && (!progress || filesize < 0) && 753 (bytes >= hashbytes)) { 754 (void)putc('#', ttyout); 755 (void)fflush(ttyout); 756 hashbytes += mark; 757 } 758 if (ferror(dout)) 759 break; 760 (void)putc('\r', dout); 761 bytes++; 762 } 763 (void)putc(c, dout); 764 bytes++; 765 #if 0 /* this violates RFC */ 766 if (c == '\r') { 767 (void)putc('\0', dout); 768 bytes++; 769 } 770 #endif 771 } 772 if (ferror(fin) || ferror(dout)) 773 serrno = errno; 774 if (hash && (!progress || filesize < 0)) { 775 if (bytes < hashbytes) 776 (void)putc('#', ttyout); 777 (void)putc('\n', ttyout); 778 (void)fflush(ttyout); 779 } 780 if (ferror(fin)) 781 warnx("local: %s: %s", local, strerror(serrno)); 782 if (ferror(dout)) { 783 if (errno != EPIPE) 784 warnx("netout: %s", strerror(serrno)); 785 bytes = -1; 786 } 787 break; 788 } 789 progressmeter(1, NULL); 790 progress = oprogress; 791 if (closefunc != NULL) 792 (*closefunc)(fin); 793 (void)fclose(dout); 794 (void)getreply(0); 795 may_receive_noop_ack(); 796 (void)signal(SIGINT, oldintr); 797 (void)signal(SIGINFO, oldinti); 798 if (oldintp) 799 (void)signal(SIGPIPE, oldintp); 800 if (bytes > 0) 801 ptransfer(0); 802 return; 803 abort: 804 (void)signal(SIGINT, oldintr); 805 (void)signal(SIGINFO, oldinti); 806 progress = oprogress; 807 if (oldintp) 808 (void)signal(SIGPIPE, oldintp); 809 if (!cpend) { 810 code = -1; 811 return; 812 } 813 if (data >= 0) { 814 (void)close(data); 815 data = -1; 816 } 817 if (dout) 818 (void)fclose(dout); 819 (void)getreply(0); 820 code = -1; 821 if (closefunc != NULL && fin != NULL) 822 (*closefunc)(fin); 823 if (bytes > 0) 824 ptransfer(0); 825 } 826 #endif /* !SMALL */ 827 828 jmp_buf recvabort; 829 830 /* ARGSUSED */ 831 void 832 abortrecv(int signo) 833 { 834 835 alarmtimer(0); 836 mflag = 0; 837 abrtflag = 0; 838 fputs("\nreceive aborted\nwaiting for remote to finish abort.\n", ttyout); 839 (void)fflush(ttyout); 840 longjmp(recvabort, 1); 841 } 842 843 void 844 recvrequest(const char *cmd, const char * volatile local, const char *remote, 845 const char *lmode, int printnames, int ignorespecial) 846 { 847 FILE * volatile fout, * volatile din; 848 int (* volatile closefunc)(FILE *); 849 volatile sig_t oldinti, oldintr, oldintp; 850 int c, d, serrno; 851 volatile int is_retr, tcrflag, bare_lfs; 852 static size_t bufsize; 853 static char *buf; 854 volatile off_t hashbytes; 855 struct stat st; 856 time_t mtime; 857 int oprogress; 858 int opreserve; 859 860 fout = NULL; 861 din = NULL; 862 oldinti = NULL; 863 hashbytes = mark; 864 direction = "received"; 865 bytes = 0; 866 bare_lfs = 0; 867 filesize = -1; 868 oprogress = progress; 869 opreserve = preserve; 870 is_retr = strcmp(cmd, "RETR") == 0; 871 if (is_retr && verbose && printnames) { 872 if (local && (ignorespecial || *local != '-')) 873 fprintf(ttyout, "local: %s ", local); 874 if (remote) 875 fprintf(ttyout, "remote: %s\n", remote); 876 } 877 if (proxy && is_retr) { 878 proxtrans(cmd, local, remote); 879 return; 880 } 881 closefunc = NULL; 882 oldintr = NULL; 883 oldintp = NULL; 884 tcrflag = !crflag && is_retr; 885 if (setjmp(recvabort)) { 886 while (cpend) { 887 (void)getreply(0); 888 } 889 if (data >= 0) { 890 (void)close(data); 891 data = -1; 892 } 893 if (oldintr) 894 (void)signal(SIGINT, oldintr); 895 if (oldinti) 896 (void)signal(SIGINFO, oldinti); 897 progress = oprogress; 898 preserve = opreserve; 899 code = -1; 900 return; 901 } 902 oldintr = signal(SIGINT, abortrecv); 903 oldinti = signal(SIGINFO, psummary); 904 if (ignorespecial || (strcmp(local, "-") && *local != '|')) { 905 if (access(local, W_OK) < 0) { 906 char *dir; 907 908 if (errno != ENOENT && errno != EACCES) { 909 warn("local: %s", local); 910 (void)signal(SIGINT, oldintr); 911 (void)signal(SIGINFO, oldinti); 912 code = -1; 913 return; 914 } 915 dir = strrchr(local, '/'); 916 if (dir != NULL) 917 *dir = 0; 918 d = access(dir == local ? "/" : dir ? local : ".", W_OK); 919 if (dir != NULL) 920 *dir = '/'; 921 if (d < 0) { 922 warn("local: %s", local); 923 (void)signal(SIGINT, oldintr); 924 (void)signal(SIGINFO, oldinti); 925 code = -1; 926 return; 927 } 928 if (!runique && errno == EACCES && 929 chmod(local, (S_IRUSR|S_IWUSR)) < 0) { 930 warn("local: %s", local); 931 (void)signal(SIGINT, oldintr); 932 (void)signal(SIGINFO, oldinti); 933 code = -1; 934 return; 935 } 936 if (runique && errno == EACCES && 937 (local = gunique(local)) == NULL) { 938 (void)signal(SIGINT, oldintr); 939 (void)signal(SIGINFO, oldinti); 940 code = -1; 941 return; 942 } 943 } 944 else if (runique && (local = gunique(local)) == NULL) { 945 (void)signal(SIGINT, oldintr); 946 (void)signal(SIGINFO, oldinti); 947 code = -1; 948 return; 949 } 950 } 951 if (!is_retr) { 952 if (curtype != TYPE_A) 953 changetype(TYPE_A, 0); 954 } else { 955 if (curtype != type) 956 changetype(type, 0); 957 filesize = remotesize(remote, 0); 958 } 959 if (initconn()) { 960 (void)signal(SIGINT, oldintr); 961 (void)signal(SIGINFO, oldinti); 962 code = -1; 963 return; 964 } 965 if (setjmp(recvabort)) 966 goto abort; 967 if (is_retr && restart_point && 968 command("REST %lld", (long long) restart_point) != CONTINUE) 969 return; 970 if (remote) { 971 if (command("%s %s", cmd, remote) != PRELIM) { 972 (void)signal(SIGINT, oldintr); 973 (void)signal(SIGINFO, oldinti); 974 return; 975 } 976 } else { 977 if (command("%s", cmd) != PRELIM) { 978 (void)signal(SIGINT, oldintr); 979 (void)signal(SIGINFO, oldinti); 980 return; 981 } 982 } 983 din = dataconn("r"); 984 if (din == NULL) 985 goto abort; 986 if (!ignorespecial && strcmp(local, "-") == 0) { 987 fout = stdout; 988 preserve = 0; 989 } else if (!ignorespecial && *local == '|') { 990 oldintp = signal(SIGPIPE, SIG_IGN); 991 fout = popen(local + 1, "w"); 992 if (fout == NULL) { 993 warn("%s", local+1); 994 goto abort; 995 } 996 if (progress == 1) 997 progress = 0; 998 preserve = 0; 999 closefunc = pclose; 1000 } else { 1001 fout = fopen(local, lmode); 1002 if (fout == NULL) { 1003 warn("local: %s", local); 1004 goto abort; 1005 } 1006 closefunc = fclose; 1007 } 1008 if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0) 1009 st.st_blksize = BUFSIZ; 1010 if (st.st_blksize > bufsize) { 1011 (void)free(buf); 1012 buf = malloc((unsigned)st.st_blksize); 1013 if (buf == NULL) { 1014 warn("malloc"); 1015 bufsize = 0; 1016 goto abort; 1017 } 1018 bufsize = st.st_blksize; 1019 } 1020 if ((st.st_mode & S_IFMT) != S_IFREG) { 1021 if (progress == 1) 1022 progress = 0; 1023 preserve = 0; 1024 } 1025 progressmeter(-1, remote); 1026 may_reset_noop_timeout(); 1027 switch (curtype) { 1028 1029 case TYPE_I: 1030 case TYPE_L: 1031 if (restart_point && 1032 lseek(fileno(fout), restart_point, SEEK_SET) < 0) { 1033 warn("local: %s", local); 1034 progress = oprogress; 1035 preserve = opreserve; 1036 if (closefunc != NULL) 1037 (*closefunc)(fout); 1038 return; 1039 } 1040 errno = d = 0; 1041 while ((c = read(fileno(din), buf, bufsize)) > 0) { 1042 ssize_t wr; 1043 size_t rd = c; 1044 1045 may_send_noop_char(); 1046 d = 0; 1047 do { 1048 wr = write(fileno(fout), buf + d, rd); 1049 if (wr == -1 && errno == EPIPE) 1050 break; 1051 d += wr; 1052 rd -= wr; 1053 } while (d < c); 1054 if (rd != 0) 1055 break; 1056 bytes += c; 1057 if (hash && (!progress || filesize < 0)) { 1058 while (bytes >= hashbytes) { 1059 (void)putc('#', ttyout); 1060 hashbytes += mark; 1061 } 1062 (void)fflush(ttyout); 1063 } 1064 } 1065 if (c == -1 || d < c) 1066 serrno = errno; 1067 if (hash && (!progress || filesize < 0) && bytes > 0) { 1068 if (bytes < mark) 1069 (void)putc('#', ttyout); 1070 (void)putc('\n', ttyout); 1071 (void)fflush(ttyout); 1072 } 1073 if (c < 0) { 1074 if (serrno != EPIPE) 1075 warnx("netin: %s", strerror(serrno)); 1076 bytes = -1; 1077 } 1078 if (d < c) { 1079 if (d < 0) 1080 warnx("local: %s: %s", local, strerror(serrno)); 1081 else 1082 warnx("%s: short write", local); 1083 } 1084 break; 1085 1086 case TYPE_A: 1087 if (restart_point) { 1088 int i, n, ch; 1089 1090 if (fseek(fout, 0L, SEEK_SET) < 0) 1091 goto done; 1092 n = restart_point; 1093 for (i = 0; i++ < n;) { 1094 if ((ch = fgetc(fout)) == EOF) { 1095 if (!ferror(fout)) 1096 errno = 0; 1097 goto done; 1098 } 1099 if (ch == '\n') 1100 i++; 1101 } 1102 if (fseek(fout, 0L, SEEK_CUR) < 0) { 1103 done: 1104 if (errno) 1105 warn("local: %s", local); 1106 else 1107 warnx("local: %s", local); 1108 progress = oprogress; 1109 preserve = opreserve; 1110 if (closefunc != NULL) 1111 (*closefunc)(fout); 1112 return; 1113 } 1114 } 1115 while ((c = fgetc(din)) != EOF) { 1116 may_send_noop_char(); 1117 if (c == '\n') 1118 bare_lfs++; 1119 while (c == '\r') { 1120 while (hash && (!progress || filesize < 0) && 1121 (bytes >= hashbytes)) { 1122 (void)putc('#', ttyout); 1123 (void)fflush(ttyout); 1124 hashbytes += mark; 1125 } 1126 bytes++; 1127 if ((c = fgetc(din)) != '\n' || tcrflag) { 1128 if (ferror(fout)) 1129 goto break2; 1130 (void)putc('\r', fout); 1131 if (c == '\0') { 1132 bytes++; 1133 goto contin2; 1134 } 1135 if (c == EOF) 1136 goto contin2; 1137 } 1138 } 1139 (void)putc(c, fout); 1140 bytes++; 1141 contin2: ; 1142 } 1143 break2: 1144 if (ferror(din) || ferror(fout)) 1145 serrno = errno; 1146 if (bare_lfs) { 1147 fprintf(ttyout, 1148 "WARNING! %d bare linefeeds received in ASCII mode.\n", bare_lfs); 1149 fputs("File may not have transferred correctly.\n", 1150 ttyout); 1151 } 1152 if (hash && (!progress || filesize < 0)) { 1153 if (bytes < hashbytes) 1154 (void)putc('#', ttyout); 1155 (void)putc('\n', ttyout); 1156 (void)fflush(ttyout); 1157 } 1158 if (ferror(din)) { 1159 if (serrno != EPIPE) 1160 warnx("netin: %s", strerror(serrno)); 1161 bytes = -1; 1162 } 1163 if (ferror(fout)) 1164 warnx("local: %s: %s", local, strerror(serrno)); 1165 break; 1166 } 1167 progressmeter(1, NULL); 1168 progress = oprogress; 1169 preserve = opreserve; 1170 if (closefunc != NULL) 1171 (*closefunc)(fout); 1172 (void)signal(SIGINT, oldintr); 1173 (void)signal(SIGINFO, oldinti); 1174 if (oldintp) 1175 (void)signal(SIGPIPE, oldintp); 1176 (void)fclose(din); 1177 (void)getreply(0); 1178 may_receive_noop_ack(); 1179 if (bytes >= 0 && is_retr) { 1180 if (bytes > 0) 1181 ptransfer(0); 1182 if (preserve && (closefunc == fclose)) { 1183 mtime = remotemodtime(remote, 0); 1184 if (mtime != -1) { 1185 struct utimbuf ut; 1186 1187 ut.actime = time(NULL); 1188 ut.modtime = mtime; 1189 if (utime(local, &ut) == -1) 1190 fprintf(ttyout, 1191 "Can't change modification time on %s to %s", 1192 local, asctime(localtime(&mtime))); 1193 } 1194 } 1195 } 1196 return; 1197 1198 abort: 1199 /* abort using RFC959 recommended IP,SYNC sequence */ 1200 progress = oprogress; 1201 preserve = opreserve; 1202 if (oldintp) 1203 (void)signal(SIGPIPE, oldintp); 1204 (void)signal(SIGINT, SIG_IGN); 1205 if (!cpend) { 1206 code = -1; 1207 (void)signal(SIGINT, oldintr); 1208 (void)signal(SIGINFO, oldinti); 1209 return; 1210 } 1211 1212 abort_remote(din); 1213 code = -1; 1214 if (data >= 0) { 1215 (void)close(data); 1216 data = -1; 1217 } 1218 if (closefunc != NULL && fout != NULL) 1219 (*closefunc)(fout); 1220 if (din) 1221 (void)fclose(din); 1222 if (bytes > 0) 1223 ptransfer(0); 1224 (void)signal(SIGINT, oldintr); 1225 (void)signal(SIGINFO, oldinti); 1226 } 1227 1228 /* 1229 * Need to start a listen on the data channel before we send the command, 1230 * otherwise the server's connect may fail. 1231 */ 1232 int 1233 initconn(void) 1234 { 1235 char *p, *a; 1236 int result = ERROR, tmpno = 0; 1237 int on = 1; 1238 int error; 1239 u_int addr[16], port[2]; 1240 u_int af, hal, pal; 1241 char *pasvcmd = NULL; 1242 socklen_t namelen; 1243 1244 if (myctladdr.su_family == AF_INET6 1245 && (IN6_IS_ADDR_LINKLOCAL(&myctladdr.su_sin6.sin6_addr) 1246 || IN6_IS_ADDR_SITELOCAL(&myctladdr.su_sin6.sin6_addr))) { 1247 warnx("use of scoped address can be troublesome"); 1248 } 1249 reinit: 1250 if (passivemode) { 1251 data_addr = myctladdr; 1252 data = socket(data_addr.su_family, SOCK_STREAM, 0); 1253 if (data < 0) { 1254 warn("socket"); 1255 return (1); 1256 } 1257 #ifndef SMALL 1258 if ((options & SO_DEBUG) && 1259 setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, 1260 sizeof(on)) < 0) 1261 warn("setsockopt (ignored)"); 1262 #endif /* !SMALL */ 1263 switch (data_addr.su_family) { 1264 case AF_INET: 1265 if (epsv4 && !epsv4bad) { 1266 int ov; 1267 /* shut this command up in case it fails */ 1268 ov = verbose; 1269 verbose = -1; 1270 result = command(pasvcmd = "EPSV"); 1271 /* 1272 * now back to whatever verbosity we had before 1273 * and we can try PASV 1274 */ 1275 verbose = ov; 1276 if (code / 10 == 22 && code != 229) { 1277 fputs( 1278 "wrong server: return code must be 229\n", 1279 ttyout); 1280 result = COMPLETE + 1; 1281 } 1282 if (result != COMPLETE) { 1283 epsv4bad = 1; 1284 #ifndef SMALL 1285 if (debug) { 1286 fputs( 1287 "disabling epsv4 for this connection\n", 1288 ttyout); 1289 } 1290 #endif /* !SMALL */ 1291 } 1292 } 1293 if (result != COMPLETE) 1294 result = command(pasvcmd = "PASV"); 1295 break; 1296 case AF_INET6: 1297 result = command(pasvcmd = "EPSV"); 1298 if (code / 10 == 22 && code != 229) { 1299 fputs( 1300 "wrong server: return code must be 229\n", 1301 ttyout); 1302 result = COMPLETE + 1; 1303 } 1304 if (result != COMPLETE) 1305 result = command(pasvcmd = "LPSV"); 1306 break; 1307 default: 1308 result = COMPLETE + 1; 1309 break; 1310 } 1311 if (result != COMPLETE) { 1312 if (activefallback) { 1313 (void)close(data); 1314 data = -1; 1315 passivemode = 0; 1316 activefallback = 0; 1317 goto reinit; 1318 } 1319 fputs("Passive mode refused.\n", ttyout); 1320 goto bad; 1321 } 1322 1323 #define pack2(var, off) \ 1324 (((var[(off) + 0] & 0xff) << 8) | ((var[(off) + 1] & 0xff) << 0)) 1325 #define pack4(var, off) \ 1326 (((var[(off) + 0] & 0xff) << 24) | ((var[(off) + 1] & 0xff) << 16) | \ 1327 ((var[(off) + 2] & 0xff) << 8) | ((var[(off) + 3] & 0xff) << 0)) 1328 1329 /* 1330 * What we've got at this point is a string of comma separated 1331 * one-byte unsigned integer values, separated by commas. 1332 */ 1333 if (!pasvcmd) 1334 goto bad; 1335 if (strcmp(pasvcmd, "PASV") == 0) { 1336 if (data_addr.su_family != AF_INET) { 1337 fputs( 1338 "Passive mode AF mismatch. Shouldn't happen!\n", ttyout); 1339 error = 1; 1340 goto bad; 1341 } 1342 if (code / 10 == 22 && code != 227) { 1343 fputs("wrong server: return code must be 227\n", 1344 ttyout); 1345 error = 1; 1346 goto bad; 1347 } 1348 error = sscanf(pasv, "%u,%u,%u,%u,%u,%u", 1349 &addr[0], &addr[1], &addr[2], &addr[3], 1350 &port[0], &port[1]); 1351 if (error != 6) { 1352 fputs( 1353 "Passive mode address scan failure. Shouldn't happen!\n", ttyout); 1354 error = 1; 1355 goto bad; 1356 } 1357 error = 0; 1358 memset(&data_addr, 0, sizeof(data_addr)); 1359 data_addr.su_family = AF_INET; 1360 data_addr.su_len = sizeof(struct sockaddr_in); 1361 data_addr.su_sin.sin_addr.s_addr = 1362 htonl(pack4(addr, 0)); 1363 data_addr.su_port = htons(pack2(port, 0)); 1364 } else if (strcmp(pasvcmd, "LPSV") == 0) { 1365 if (code / 10 == 22 && code != 228) { 1366 fputs("wrong server: return code must be 228\n", 1367 ttyout); 1368 error = 1; 1369 goto bad; 1370 } 1371 switch (data_addr.su_family) { 1372 case AF_INET: 1373 error = sscanf(pasv, 1374 "%u,%u,%u,%u,%u,%u,%u,%u,%u", 1375 &af, &hal, 1376 &addr[0], &addr[1], &addr[2], &addr[3], 1377 &pal, &port[0], &port[1]); 1378 if (error != 9) { 1379 fputs( 1380 "Passive mode address scan failure. Shouldn't happen!\n", ttyout); 1381 error = 1; 1382 goto bad; 1383 } 1384 if (af != 4 || hal != 4 || pal != 2) { 1385 fputs( 1386 "Passive mode AF mismatch. Shouldn't happen!\n", ttyout); 1387 error = 1; 1388 goto bad; 1389 } 1390 1391 error = 0; 1392 memset(&data_addr, 0, sizeof(data_addr)); 1393 data_addr.su_family = AF_INET; 1394 data_addr.su_len = sizeof(struct sockaddr_in); 1395 data_addr.su_sin.sin_addr.s_addr = 1396 htonl(pack4(addr, 0)); 1397 data_addr.su_port = htons(pack2(port, 0)); 1398 break; 1399 case AF_INET6: 1400 error = sscanf(pasv, 1401 "%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u", 1402 &af, &hal, 1403 &addr[0], &addr[1], &addr[2], &addr[3], 1404 &addr[4], &addr[5], &addr[6], &addr[7], 1405 &addr[8], &addr[9], &addr[10], 1406 &addr[11], &addr[12], &addr[13], 1407 &addr[14], &addr[15], 1408 &pal, &port[0], &port[1]); 1409 if (error != 21) { 1410 fputs( 1411 "Passive mode address scan failure. Shouldn't happen!\n", ttyout); 1412 error = 1; 1413 goto bad; 1414 } 1415 if (af != 6 || hal != 16 || pal != 2) { 1416 fputs( 1417 "Passive mode AF mismatch. Shouldn't happen!\n", ttyout); 1418 error = 1; 1419 goto bad; 1420 } 1421 1422 error = 0; 1423 memset(&data_addr, 0, sizeof(data_addr)); 1424 data_addr.su_family = AF_INET6; 1425 data_addr.su_len = sizeof(struct sockaddr_in6); 1426 { 1427 u_int32_t *p32; 1428 p32 = (u_int32_t *)&data_addr.su_sin6.sin6_addr; 1429 p32[0] = htonl(pack4(addr, 0)); 1430 p32[1] = htonl(pack4(addr, 4)); 1431 p32[2] = htonl(pack4(addr, 8)); 1432 p32[3] = htonl(pack4(addr, 12)); 1433 } 1434 data_addr.su_port = htons(pack2(port, 0)); 1435 break; 1436 default: 1437 error = 1; 1438 } 1439 } else if (strcmp(pasvcmd, "EPSV") == 0) { 1440 char delim[4]; 1441 1442 port[0] = 0; 1443 if (code / 10 == 22 && code != 229) { 1444 fputs("wrong server: return code must be 229\n", 1445 ttyout); 1446 error = 1; 1447 goto bad; 1448 } 1449 if (sscanf(pasv, "%c%c%c%d%c", &delim[0], 1450 &delim[1], &delim[2], &port[1], 1451 &delim[3]) != 5) { 1452 fputs("parse error!\n", ttyout); 1453 error = 1; 1454 goto bad; 1455 } 1456 if (delim[0] != delim[1] || delim[0] != delim[2] 1457 || delim[0] != delim[3]) { 1458 fputs("parse error!\n", ttyout); 1459 error = 1; 1460 goto bad; 1461 } 1462 data_addr = hisctladdr; 1463 data_addr.su_port = htons(port[1]); 1464 } else 1465 goto bad; 1466 1467 while (connect(data, (struct sockaddr *)&data_addr, 1468 data_addr.su_len) < 0) { 1469 if (errno == EINTR) 1470 continue; 1471 if (activefallback) { 1472 (void)close(data); 1473 data = -1; 1474 passivemode = 0; 1475 activefallback = 0; 1476 goto reinit; 1477 } 1478 warn("connect"); 1479 goto bad; 1480 } 1481 #if defined(IPPROTO_IP) && defined(IP_TOS) 1482 if (data_addr.su_family == AF_INET) { 1483 on = IPTOS_THROUGHPUT; 1484 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, 1485 sizeof(int)) < 0) 1486 warn("setsockopt TOS (ignored)"); 1487 } 1488 #endif 1489 return (0); 1490 } 1491 1492 noport: 1493 data_addr = myctladdr; 1494 if (sendport) 1495 data_addr.su_port = 0; /* let system pick one */ 1496 if (data != -1) 1497 (void)close(data); 1498 data = socket(data_addr.su_family, SOCK_STREAM, 0); 1499 if (data < 0) { 1500 warn("socket"); 1501 if (tmpno) 1502 sendport = 1; 1503 return (1); 1504 } 1505 if (!sendport) 1506 if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, 1507 sizeof(on)) < 0) { 1508 warn("setsockopt (reuse address)"); 1509 goto bad; 1510 } 1511 switch (data_addr.su_family) { 1512 case AF_INET: 1513 on = IP_PORTRANGE_HIGH; 1514 if (setsockopt(data, IPPROTO_IP, IP_PORTRANGE, 1515 (char *)&on, sizeof(on)) < 0) 1516 warn("setsockopt IP_PORTRANGE (ignored)"); 1517 break; 1518 case AF_INET6: 1519 on = IPV6_PORTRANGE_HIGH; 1520 if (setsockopt(data, IPPROTO_IPV6, IPV6_PORTRANGE, 1521 (char *)&on, sizeof(on)) < 0) 1522 warn("setsockopt IPV6_PORTRANGE (ignored)"); 1523 break; 1524 } 1525 if (bind(data, (struct sockaddr *)&data_addr, data_addr.su_len) < 0) { 1526 warn("bind"); 1527 goto bad; 1528 } 1529 #ifndef SMALL 1530 if (options & SO_DEBUG && 1531 setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, 1532 sizeof(on)) < 0) 1533 warn("setsockopt (ignored)"); 1534 #endif /* !SMALL */ 1535 namelen = sizeof(data_addr); 1536 if (getsockname(data, (struct sockaddr *)&data_addr, &namelen) < 0) { 1537 warn("getsockname"); 1538 goto bad; 1539 } 1540 if (listen(data, 1) < 0) 1541 warn("listen"); 1542 1543 #define UC(b) (((int)b)&0xff) 1544 1545 if (sendport) { 1546 char hname[NI_MAXHOST], pbuf[NI_MAXSERV]; 1547 int af_tmp; 1548 union sockunion tmp; 1549 1550 tmp = data_addr; 1551 switch (tmp.su_family) { 1552 case AF_INET: 1553 if (!epsv4 || epsv4bad) { 1554 result = COMPLETE +1; 1555 break; 1556 } 1557 /*FALLTHROUGH*/ 1558 case AF_INET6: 1559 if (tmp.su_family == AF_INET6) 1560 tmp.su_sin6.sin6_scope_id = 0; 1561 af_tmp = (tmp.su_family == AF_INET) ? 1 : 2; 1562 if (getnameinfo((struct sockaddr *)&tmp, 1563 tmp.su_len, hname, sizeof(hname), 1564 pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV)) { 1565 result = ERROR; 1566 } else { 1567 result = command("EPRT |%d|%s|%s|", 1568 af_tmp, hname, pbuf); 1569 if (result != COMPLETE) { 1570 epsv4bad = 1; 1571 #ifndef SMALL 1572 if (debug) { 1573 fputs( 1574 "disabling epsv4 for this connection\n", 1575 ttyout); 1576 } 1577 #endif /* !SMALL */ 1578 } 1579 } 1580 break; 1581 default: 1582 result = COMPLETE + 1; 1583 break; 1584 } 1585 if (result == COMPLETE) 1586 goto skip_port; 1587 1588 switch (data_addr.su_family) { 1589 case AF_INET: 1590 a = (char *)&data_addr.su_sin.sin_addr; 1591 p = (char *)&data_addr.su_port; 1592 result = command("PORT %d,%d,%d,%d,%d,%d", 1593 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 1594 UC(p[0]), UC(p[1])); 1595 break; 1596 case AF_INET6: 1597 a = (char *)&data_addr.su_sin6.sin6_addr; 1598 p = (char *)&data_addr.su_port; 1599 result = command( 1600 "LPRT %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", 1601 6, 16, 1602 UC(a[0]),UC(a[1]),UC(a[2]),UC(a[3]), 1603 UC(a[4]),UC(a[5]),UC(a[6]),UC(a[7]), 1604 UC(a[8]),UC(a[9]),UC(a[10]),UC(a[11]), 1605 UC(a[12]),UC(a[13]),UC(a[14]),UC(a[15]), 1606 2, UC(p[0]), UC(p[1])); 1607 break; 1608 default: 1609 result = COMPLETE + 1; /* xxx */ 1610 } 1611 skip_port: 1612 1613 if (result == ERROR && sendport == -1) { 1614 sendport = 0; 1615 tmpno = 1; 1616 goto noport; 1617 } 1618 return (result != COMPLETE); 1619 } 1620 if (tmpno) 1621 sendport = 1; 1622 #if defined(IPPROTO_IP) && defined(IP_TOS) 1623 if (data_addr.su_family == AF_INET) { 1624 on = IPTOS_THROUGHPUT; 1625 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, 1626 sizeof(int)) < 0) 1627 warn("setsockopt TOS (ignored)"); 1628 } 1629 #endif 1630 return (0); 1631 bad: 1632 (void)close(data), data = -1; 1633 if (tmpno) 1634 sendport = 1; 1635 return (1); 1636 } 1637 1638 FILE * 1639 dataconn(const char *lmode) 1640 { 1641 union sockunion from; 1642 socklen_t fromlen = myctladdr.su_len; 1643 int s; 1644 1645 if (passivemode) 1646 return (fdopen(data, lmode)); 1647 1648 s = accept(data, (struct sockaddr *) &from, &fromlen); 1649 if (s < 0) { 1650 warn("accept"); 1651 (void)close(data), data = -1; 1652 return (NULL); 1653 } 1654 (void)close(data); 1655 data = s; 1656 #if defined(IPPROTO_IP) && defined(IP_TOS) 1657 if (from.su_family == AF_INET) { 1658 int tos = IPTOS_THROUGHPUT; 1659 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, 1660 sizeof(int)) < 0) { 1661 warn("setsockopt TOS (ignored)"); 1662 } 1663 } 1664 #endif 1665 return (fdopen(data, lmode)); 1666 } 1667 1668 /* ARGSUSED */ 1669 void 1670 psummary(int signo) 1671 { 1672 int save_errno = errno; 1673 1674 if (bytes > 0) 1675 ptransfer(1); 1676 errno = save_errno; 1677 } 1678 1679 /* ARGSUSED */ 1680 void 1681 psabort(int signo) 1682 { 1683 1684 alarmtimer(0); 1685 abrtflag++; 1686 } 1687 1688 void 1689 pswitch(int flag) 1690 { 1691 sig_t oldintr; 1692 static struct comvars { 1693 int connect; 1694 char name[MAXHOSTNAMELEN]; 1695 union sockunion mctl; 1696 union sockunion hctl; 1697 FILE *in; 1698 FILE *out; 1699 int tpe; 1700 int curtpe; 1701 int cpnd; 1702 int sunqe; 1703 int runqe; 1704 int mcse; 1705 int ntflg; 1706 char nti[17]; 1707 char nto[17]; 1708 int mapflg; 1709 char mi[MAXPATHLEN]; 1710 char mo[MAXPATHLEN]; 1711 } proxstruct, tmpstruct; 1712 struct comvars *ip, *op; 1713 1714 abrtflag = 0; 1715 oldintr = signal(SIGINT, psabort); 1716 if (flag) { 1717 if (proxy) 1718 return; 1719 ip = &tmpstruct; 1720 op = &proxstruct; 1721 proxy++; 1722 } else { 1723 if (!proxy) 1724 return; 1725 ip = &proxstruct; 1726 op = &tmpstruct; 1727 proxy = 0; 1728 } 1729 ip->connect = connected; 1730 connected = op->connect; 1731 if (hostname) { 1732 (void)strlcpy(ip->name, hostname, sizeof(ip->name)); 1733 } else 1734 ip->name[0] = '\0'; 1735 hostname = op->name; 1736 ip->hctl = hisctladdr; 1737 hisctladdr = op->hctl; 1738 ip->mctl = myctladdr; 1739 myctladdr = op->mctl; 1740 ip->in = cin; 1741 cin = op->in; 1742 ip->out = cout; 1743 cout = op->out; 1744 ip->tpe = type; 1745 type = op->tpe; 1746 ip->curtpe = curtype; 1747 curtype = op->curtpe; 1748 ip->cpnd = cpend; 1749 cpend = op->cpnd; 1750 ip->sunqe = sunique; 1751 sunique = op->sunqe; 1752 ip->runqe = runique; 1753 runique = op->runqe; 1754 ip->mcse = mcase; 1755 mcase = op->mcse; 1756 ip->ntflg = ntflag; 1757 ntflag = op->ntflg; 1758 (void)strlcpy(ip->nti, ntin, sizeof(ip->nti)); 1759 (void)strlcpy(ntin, op->nti, sizeof ntin); 1760 (void)strlcpy(ip->nto, ntout, sizeof(ip->nto)); 1761 (void)strlcpy(ntout, op->nto, sizeof ntout); 1762 ip->mapflg = mapflag; 1763 mapflag = op->mapflg; 1764 (void)strlcpy(ip->mi, mapin, sizeof(ip->mi)); 1765 (void)strlcpy(mapin, op->mi, sizeof mapin); 1766 (void)strlcpy(ip->mo, mapout, sizeof(ip->mo)); 1767 (void)strlcpy(mapout, op->mo, sizeof mapout); 1768 (void)signal(SIGINT, oldintr); 1769 if (abrtflag) { 1770 abrtflag = 0; 1771 (*oldintr)(SIGINT); 1772 } 1773 } 1774 1775 /* ARGSUSED */ 1776 void 1777 abortpt(int signo) 1778 { 1779 1780 alarmtimer(0); 1781 putc('\n', ttyout); 1782 (void)fflush(ttyout); 1783 ptabflg++; 1784 mflag = 0; 1785 abrtflag = 0; 1786 longjmp(ptabort, 1); 1787 } 1788 1789 void 1790 proxtrans(const char *cmd, const char *local, const char *remote) 1791 { 1792 volatile sig_t oldintr; 1793 int prox_type, nfnd; 1794 volatile int secndflag; 1795 char * volatile cmd2; 1796 struct pollfd pfd[1]; 1797 1798 oldintr = NULL; 1799 secndflag = 0; 1800 if (strcmp(cmd, "RETR")) 1801 cmd2 = "RETR"; 1802 else 1803 cmd2 = runique ? "STOU" : "STOR"; 1804 if ((prox_type = type) == 0) { 1805 if (unix_server && unix_proxy) 1806 prox_type = TYPE_I; 1807 else 1808 prox_type = TYPE_A; 1809 } 1810 if (curtype != prox_type) 1811 changetype(prox_type, 1); 1812 if (command("PASV") != COMPLETE) { 1813 fputs("proxy server does not support third party transfers.\n", 1814 ttyout); 1815 return; 1816 } 1817 pswitch(0); 1818 if (!connected) { 1819 fputs("No primary connection.\n", ttyout); 1820 pswitch(1); 1821 code = -1; 1822 return; 1823 } 1824 if (curtype != prox_type) 1825 changetype(prox_type, 1); 1826 if (command("PORT %s", pasv) != COMPLETE) { 1827 pswitch(1); 1828 return; 1829 } 1830 if (setjmp(ptabort)) 1831 goto abort; 1832 oldintr = signal(SIGINT, abortpt); 1833 if (command("%s %s", cmd, remote) != PRELIM) { 1834 (void)signal(SIGINT, oldintr); 1835 pswitch(1); 1836 return; 1837 } 1838 sleep(2); 1839 pswitch(1); 1840 secndflag++; 1841 if (command("%s %s", cmd2, local) != PRELIM) 1842 goto abort; 1843 ptflag++; 1844 (void)getreply(0); 1845 pswitch(0); 1846 (void)getreply(0); 1847 (void)signal(SIGINT, oldintr); 1848 pswitch(1); 1849 ptflag = 0; 1850 fprintf(ttyout, "local: %s remote: %s\n", local, remote); 1851 return; 1852 abort: 1853 (void)signal(SIGINT, SIG_IGN); 1854 ptflag = 0; 1855 if (strcmp(cmd, "RETR") && !proxy) 1856 pswitch(1); 1857 else if (!strcmp(cmd, "RETR") && proxy) 1858 pswitch(0); 1859 if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 1860 if (command("%s %s", cmd2, local) != PRELIM) { 1861 pswitch(0); 1862 if (cpend) 1863 abort_remote(NULL); 1864 } 1865 pswitch(1); 1866 if (ptabflg) 1867 code = -1; 1868 (void)signal(SIGINT, oldintr); 1869 return; 1870 } 1871 if (cpend) 1872 abort_remote(NULL); 1873 pswitch(!proxy); 1874 if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 1875 if (command("%s %s", cmd2, local) != PRELIM) { 1876 pswitch(0); 1877 if (cpend) 1878 abort_remote(NULL); 1879 pswitch(1); 1880 if (ptabflg) 1881 code = -1; 1882 (void)signal(SIGINT, oldintr); 1883 return; 1884 } 1885 } 1886 if (cpend) 1887 abort_remote(NULL); 1888 pswitch(!proxy); 1889 if (cpend) { 1890 pfd[0].fd = fileno(cin); 1891 pfd[0].events = POLLIN; 1892 if ((nfnd = poll(pfd, 1, 10 * 1000)) <= 0) { 1893 if (nfnd < 0) 1894 warn("abort"); 1895 if (ptabflg) 1896 code = -1; 1897 lostpeer(); 1898 } 1899 (void)getreply(0); 1900 (void)getreply(0); 1901 } 1902 if (proxy) 1903 pswitch(0); 1904 pswitch(1); 1905 if (ptabflg) 1906 code = -1; 1907 (void)signal(SIGINT, oldintr); 1908 } 1909 1910 /* ARGSUSED */ 1911 void 1912 reset(int argc, char *argv[]) 1913 { 1914 struct pollfd pfd[1]; 1915 int nfnd = 1; 1916 1917 pfd[0].fd = fileno(cin); 1918 pfd[0].events = POLLIN; 1919 while (nfnd > 0) { 1920 if ((nfnd = poll(pfd, 1, 0)) < 0) { 1921 warn("reset"); 1922 code = -1; 1923 lostpeer(); 1924 } else if (nfnd) { 1925 (void)getreply(0); 1926 } 1927 } 1928 } 1929 1930 char * 1931 gunique(const char *local) 1932 { 1933 static char new[MAXPATHLEN]; 1934 char *cp = strrchr(local, '/'); 1935 int d, count=0; 1936 char ext = '1'; 1937 1938 if (cp) 1939 *cp = '\0'; 1940 d = access(cp == local ? "/" : cp ? local : ".", W_OK); 1941 if (cp) 1942 *cp = '/'; 1943 if (d < 0) { 1944 warn("local: %s", local); 1945 return ((char *) 0); 1946 } 1947 (void)strlcpy(new, local, sizeof new); 1948 cp = new + strlen(new); 1949 *cp++ = '.'; 1950 while (!d) { 1951 if (++count == 100) { 1952 fputs("runique: can't find unique file name.\n", ttyout); 1953 return ((char *) 0); 1954 } 1955 *cp++ = ext; 1956 *cp = '\0'; 1957 if (ext == '9') 1958 ext = '0'; 1959 else 1960 ext++; 1961 if ((d = access(new, F_OK)) < 0) 1962 break; 1963 if (ext != '0') 1964 cp--; 1965 else if (*(cp - 2) == '.') 1966 *(cp - 1) = '1'; 1967 else { 1968 *(cp - 2) = *(cp - 2) + 1; 1969 cp--; 1970 } 1971 } 1972 return (new); 1973 } 1974 1975 jmp_buf forceabort; 1976 1977 /* ARGSUSED */ 1978 void 1979 abortforce(int signo) 1980 { 1981 fputs("Forced abort. The connection will be closed.\n", ttyout); 1982 (void)fflush(ttyout); 1983 1984 if (cout) { 1985 (void)fclose(cout); 1986 } 1987 cout = NULL; 1988 1989 longjmp(forceabort, 1); 1990 } 1991 1992 void 1993 abort_remote(FILE *din) 1994 { 1995 char buf[BUFSIZ]; 1996 int nfnd; 1997 struct pollfd pfd[2]; 1998 sig_t oldintr; 1999 2000 if (cout == NULL || setjmp(forceabort)) { 2001 warnx("Lost control connection for abort."); 2002 if (ptabflg) 2003 code = -1; 2004 lostpeer(); 2005 return; 2006 } 2007 2008 oldintr = signal(SIGINT, abortforce); 2009 2010 /* 2011 * send IAC in urgent mode instead of DM because 4.3BSD places oob mark 2012 * after urgent byte rather than before as is protocol now 2013 */ 2014 snprintf(buf, sizeof buf, "%c%c%c", IAC, IP, IAC); 2015 if (send(fileno(cout), buf, 3, MSG_OOB) != 3) 2016 warn("abort"); 2017 fprintf(cout, "%cABOR\r\n", DM); 2018 (void)fflush(cout); 2019 pfd[0].fd = fileno(cin); 2020 pfd[0].events = POLLIN; 2021 nfnd = 1; 2022 if (din) { 2023 pfd[1].fd = fileno(din); 2024 pfd[1].events = POLLIN; 2025 nfnd++; 2026 } 2027 if ((nfnd = poll(pfd, nfnd, 10 * 1000)) <= 0) { 2028 if (nfnd < 0) 2029 warn("abort"); 2030 if (ptabflg) 2031 code = -1; 2032 lostpeer(); 2033 } 2034 if (din && (pfd[1].revents & POLLIN)) { 2035 while (read(fileno(din), buf, BUFSIZ) > 0) 2036 /* LOOP */; 2037 } 2038 if (getreply(0) == ERROR && code == 552) { 2039 /* 552 needed for nic style abort */ 2040 (void)getreply(0); 2041 } 2042 (void)getreply(0); 2043 (void)signal(SIGINT, oldintr); 2044 } 2045