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