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