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