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