1 /* $NetBSD: ftp.c,v 1.123 2003/12/10 12:34:28 lukem Exp $ */ 2 3 /*- 4 * Copyright (c) 1996-2002 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.123 2003/12/10 12:34:28 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 int abrtflag = 0; 135 volatile int timeoutflag = 0; 136 sigjmp_buf ptabort; 137 int ptabflg; 138 int ptflag = 0; 139 char pasv[BUFSIZ]; /* passive port for proxy data connection */ 140 141 static int empty(FILE *, FILE *, int); 142 143 struct sockinet { 144 union sockunion { 145 struct sockaddr_in su_sin; 146 #ifdef INET6 147 struct sockaddr_in6 su_sin6; 148 #endif 149 } si_su; 150 #if !HAVE_SOCKADDR_SA_LEN 151 int si_len; 152 #endif 153 }; 154 155 #if !HAVE_SOCKADDR_SA_LEN 156 # define su_len si_len 157 #else 158 # define su_len si_su.su_sin.sin_len 159 #endif 160 #define su_family si_su.su_sin.sin_family 161 #define su_port si_su.su_sin.sin_port 162 163 struct sockinet myctladdr, hisctladdr, data_addr; 164 165 char * 166 hookup(char *host, char *port) 167 { 168 int s = -1, len, error, portnum; 169 struct addrinfo hints, *res, *res0; 170 char hbuf[MAXHOSTNAMELEN]; 171 static char hostnamebuf[MAXHOSTNAMELEN]; 172 char *cause = "unknown"; 173 174 memset((char *)&hisctladdr, 0, sizeof (hisctladdr)); 175 memset((char *)&myctladdr, 0, sizeof (myctladdr)); 176 memset(&hints, 0, sizeof(hints)); 177 portnum = parseport(port, FTP_PORT); 178 hints.ai_flags = AI_CANONNAME; 179 hints.ai_family = family; 180 hints.ai_socktype = SOCK_STREAM; 181 hints.ai_protocol = 0; 182 error = getaddrinfo(host, NULL, &hints, &res0); 183 if (error) { 184 warnx("%s", gai_strerror(error)); 185 code = -1; 186 return (0); 187 } 188 189 if (res0->ai_canonname) 190 (void)strlcpy(hostnamebuf, res0->ai_canonname, 191 sizeof(hostnamebuf)); 192 else 193 (void)strlcpy(hostnamebuf, host, sizeof(hostnamebuf)); 194 hostname = hostnamebuf; 195 196 for (res = res0; res; res = res->ai_next) { 197 /* 198 * make sure that ai_addr is NOT an IPv4 mapped address. 199 * IPv4 mapped address complicates too many things in FTP 200 * protocol handling, as FTP protocol is defined differently 201 * between IPv4 and IPv6. 202 * 203 * This may not be the best way to handle this situation, 204 * since the semantics of IPv4 mapped address is defined in 205 * the kernel. There are configurations where we should use 206 * IPv4 mapped address as native IPv6 address, not as 207 * "an IPv6 address that embeds IPv4 address" (namely, SIIT). 208 * 209 * More complete solution would be to have an additional 210 * getsockopt to grab "real" peername/sockname. "real" 211 * peername/sockname will be AF_INET if IPv4 mapped address 212 * is used to embed IPv4 address, and will be AF_INET6 if 213 * we use it as native. What a mess! 214 */ 215 ai_unmapped(res); 216 #if 0 /*old behavior*/ 217 if (res != res0) /* not on the first address */ 218 #else 219 if (res0->ai_next) /* if we have multiple possibilities */ 220 #endif 221 { 222 if (getnameinfo(res->ai_addr, res->ai_addrlen, 223 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST)) 224 strlcpy(hbuf, "?", sizeof(hbuf)); 225 fprintf(ttyout, "Trying %s...\n", hbuf); 226 } 227 ((struct sockaddr_in *)res->ai_addr)->sin_port = htons(portnum); 228 s = socket(res->ai_family, SOCK_STREAM, res->ai_protocol); 229 if (s < 0) { 230 cause = "socket"; 231 continue; 232 } 233 while ((error = xconnect(s, res->ai_addr, res->ai_addrlen)) < 0 234 && errno == EINTR) { 235 ; 236 } 237 if (error) { 238 /* this "if" clause is to prevent print warning twice */ 239 if (res->ai_next) { 240 if (getnameinfo(res->ai_addr, res->ai_addrlen, 241 hbuf, sizeof(hbuf), NULL, 0, 242 NI_NUMERICHOST)) 243 strlcpy(hbuf, "?", sizeof(hbuf)); 244 warn("connect to address %s", hbuf); 245 } 246 cause = "connect"; 247 close(s); 248 s = -1; 249 continue; 250 } 251 252 /* finally we got one */ 253 break; 254 } 255 if (s < 0) { 256 warn("%s", cause); 257 code = -1; 258 freeaddrinfo(res0); 259 return 0; 260 } 261 memcpy(&hisctladdr.si_su, res->ai_addr, res->ai_addrlen); 262 hisctladdr.su_len = res->ai_addrlen; 263 freeaddrinfo(res0); 264 res0 = res = NULL; 265 266 len = hisctladdr.su_len; 267 if (getsockname(s, (struct sockaddr *)&myctladdr.si_su, &len) < 0) { 268 warn("getsockname"); 269 code = -1; 270 goto bad; 271 } 272 myctladdr.su_len = len; 273 274 #ifdef IPTOS_LOWDELAY 275 if (hisctladdr.su_family == AF_INET) { 276 int tos = IPTOS_LOWDELAY; 277 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, 278 sizeof(int)) < 0) 279 if (debug) 280 warn("setsockopt TOS (ignored)"); 281 } 282 #endif 283 cin = fdopen(s, "r"); 284 cout = fdopen(s, "w"); 285 if (cin == NULL || cout == NULL) { 286 warnx("fdopen failed."); 287 if (cin) 288 (void)fclose(cin); 289 if (cout) 290 (void)fclose(cout); 291 code = -1; 292 goto bad; 293 } 294 if (verbose) 295 fprintf(ttyout, "Connected to %s.\n", hostname); 296 if (getreply(0) > 2) { /* read startup message from server */ 297 if (cin) 298 (void)fclose(cin); 299 if (cout) 300 (void)fclose(cout); 301 code = -1; 302 goto bad; 303 } 304 { 305 int on = 1; 306 307 if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) 308 < 0 && debug) { 309 warn("setsockopt"); 310 } 311 } 312 313 return (hostname); 314 bad: 315 (void)close(s); 316 return (NULL); 317 } 318 319 void 320 cmdabort(int notused) 321 { 322 int oerrno = errno; 323 324 alarmtimer(0); 325 if (fromatty) 326 write(fileno(ttyout), "\n", 1); 327 abrtflag++; 328 if (ptflag) 329 siglongjmp(ptabort, 1); 330 errno = oerrno; 331 } 332 333 void 334 cmdtimeout(int notused) 335 { 336 int oerrno = errno; 337 338 alarmtimer(0); 339 if (fromatty) 340 write(fileno(ttyout), "\n", 1); 341 timeoutflag++; 342 if (ptflag) 343 siglongjmp(ptabort, 1); 344 errno = oerrno; 345 } 346 347 /*VARARGS*/ 348 int 349 command(const char *fmt, ...) 350 { 351 va_list ap; 352 int r; 353 sigfunc oldsigint; 354 355 if (debug) { 356 fputs("---> ", ttyout); 357 va_start(ap, fmt); 358 if (strncmp("PASS ", fmt, 5) == 0) 359 fputs("PASS XXXX", ttyout); 360 else if (strncmp("ACCT ", fmt, 5) == 0) 361 fputs("ACCT XXXX", ttyout); 362 else 363 vfprintf(ttyout, fmt, ap); 364 va_end(ap); 365 putc('\n', ttyout); 366 } 367 if (cout == NULL) { 368 warnx("No control connection for command."); 369 code = -1; 370 return (0); 371 } 372 373 abrtflag = 0; 374 375 oldsigint = xsignal(SIGINT, cmdabort); 376 377 va_start(ap, fmt); 378 vfprintf(cout, fmt, ap); 379 va_end(ap); 380 fputs("\r\n", cout); 381 (void)fflush(cout); 382 cpend = 1; 383 r = getreply(!strcmp(fmt, "QUIT")); 384 if (abrtflag && oldsigint != SIG_IGN) 385 (*oldsigint)(SIGINT); 386 (void)xsignal(SIGINT, oldsigint); 387 return (r); 388 } 389 390 int 391 getreply(int expecteof) 392 { 393 char current_line[BUFSIZ]; /* last line of previous reply */ 394 int c, n, line; 395 int dig; 396 int originalcode = 0, continuation = 0; 397 sigfunc oldsigint, oldsigalrm; 398 int pflag = 0; 399 char *cp, *pt = pasv; 400 401 abrtflag = 0; 402 timeoutflag = 0; 403 404 oldsigint = xsignal(SIGINT, cmdabort); 405 oldsigalrm = xsignal(SIGALRM, cmdtimeout); 406 407 for (line = 0 ;; line++) { 408 dig = n = code = 0; 409 cp = current_line; 410 while (alarmtimer(60),((c = getc(cin)) != '\n')) { 411 if (c == IAC) { /* handle telnet commands */ 412 switch (c = getc(cin)) { 413 case WILL: 414 case WONT: 415 c = getc(cin); 416 fprintf(cout, "%c%c%c", IAC, DONT, c); 417 (void)fflush(cout); 418 break; 419 case DO: 420 case DONT: 421 c = getc(cin); 422 fprintf(cout, "%c%c%c", IAC, WONT, c); 423 (void)fflush(cout); 424 break; 425 default: 426 break; 427 } 428 continue; 429 } 430 dig++; 431 if (c == EOF) { 432 /* 433 * these will get trashed by pswitch() 434 * in lostpeer() 435 */ 436 int reply_timeoutflag = timeoutflag; 437 int reply_abrtflag = abrtflag; 438 439 alarmtimer(0); 440 if (expecteof && feof(cin)) { 441 (void)xsignal(SIGINT, oldsigint); 442 (void)xsignal(SIGALRM, oldsigalrm); 443 code = 221; 444 return (0); 445 } 446 cpend = 0; 447 lostpeer(0); 448 if (verbose) { 449 if (reply_timeoutflag) 450 fputs( 451 "421 Service not available, remote server timed out. Connection closed\n", 452 ttyout); 453 else if (reply_abrtflag) 454 fputs( 455 "421 Service not available, user interrupt. Connection closed.\n", 456 ttyout); 457 else 458 fputs( 459 "421 Service not available, remote server has closed connection.\n", 460 ttyout); 461 (void)fflush(ttyout); 462 } 463 code = 421; 464 (void)xsignal(SIGINT, oldsigint); 465 (void)xsignal(SIGALRM, oldsigalrm); 466 return (4); 467 } 468 if (c != '\r' && (verbose > 0 || 469 ((verbose > -1 && n == '5' && dig > 4) && 470 (((!n && c < '5') || (n && n < '5')) 471 || !retry_connect)))) { 472 if (proxflag && 473 (dig == 1 || (dig == 5 && verbose == 0))) 474 fprintf(ttyout, "%s:", hostname); 475 (void)putc(c, ttyout); 476 } 477 if (dig < 4 && isdigit(c)) 478 code = code * 10 + (c - '0'); 479 if (!pflag && (code == 227 || code == 228)) 480 pflag = 1; 481 else if (!pflag && code == 229) 482 pflag = 100; 483 if (dig > 4 && pflag == 1 && isdigit(c)) 484 pflag = 2; 485 if (pflag == 2) { 486 if (c != '\r' && c != ')') { 487 if (pt < &pasv[sizeof(pasv) - 1]) 488 *pt++ = c; 489 } else { 490 *pt = '\0'; 491 pflag = 3; 492 } 493 } 494 if (pflag == 100 && c == '(') 495 pflag = 2; 496 if (dig == 4 && c == '-') { 497 if (continuation) 498 code = 0; 499 continuation++; 500 } 501 if (n == 0) 502 n = c; 503 if (cp < ¤t_line[sizeof(current_line) - 1]) 504 *cp++ = c; 505 } 506 if (verbose > 0 || ((verbose > -1 && n == '5') && 507 (n < '5' || !retry_connect))) { 508 (void)putc(c, ttyout); 509 (void)fflush (ttyout); 510 } 511 if (cp[-1] == '\r') 512 cp[-1] = '\0'; 513 *cp = '\0'; 514 if (line == 0) 515 (void)strlcpy(reply_string, current_line, 516 sizeof(reply_string)); 517 if (line > 0 && code == 0 && reply_callback != NULL) 518 (*reply_callback)(current_line); 519 if (continuation && code != originalcode) { 520 if (originalcode == 0) 521 originalcode = code; 522 continue; 523 } 524 if (n != '1') 525 cpend = 0; 526 alarmtimer(0); 527 (void)xsignal(SIGINT, oldsigint); 528 (void)xsignal(SIGALRM, oldsigalrm); 529 if (code == 421 || originalcode == 421) 530 lostpeer(0); 531 if (abrtflag && oldsigint != cmdabort && oldsigint != SIG_IGN) 532 (*oldsigint)(SIGINT); 533 if (timeoutflag && oldsigalrm != cmdtimeout && 534 oldsigalrm != SIG_IGN) 535 (*oldsigalrm)(SIGINT); 536 return (n - '0'); 537 } 538 } 539 540 static int 541 empty(FILE *cin, FILE *din, int sec) 542 { 543 int nr; 544 int nfd = 0; 545 546 #ifdef USE_SELECT 547 struct timeval t; 548 fd_set rmask; 549 550 FD_ZERO(&rmask); 551 if (cin) { 552 if (nfd < fileno(cin)) 553 nfd = fileno(cin); 554 FD_SET(fileno(cin), &rmask); 555 } 556 if (din) { 557 if (nfd < fileno(din)) 558 nfd = fileno(din); 559 FD_SET(fileno(din), &rmask); 560 } 561 562 t.tv_sec = (long) sec; 563 t.tv_usec = 0; 564 if ((nr = select(nfd, &rmask, NULL, NULL, &t)) <= 0) 565 return nr; 566 567 nr = 0; 568 if (cin) 569 nr |= FD_ISSET(fileno(cin), &rmask) ? 1 : 0; 570 if (din) 571 nr |= FD_ISSET(fileno(din), &rmask) ? 2 : 0; 572 573 #else 574 struct pollfd pfd[2]; 575 576 if (cin) { 577 pfd[nfd].fd = fileno(cin); 578 pfd[nfd++].events = POLLIN; 579 } 580 581 if (din) { 582 pfd[nfd].fd = fileno(din); 583 pfd[nfd++].events = POLLIN; 584 } 585 586 if ((nr = poll(pfd, nfd, sec * 1000)) <= 0) 587 return nr; 588 589 nr = 0; 590 nfd = 0; 591 if (cin) 592 nr |= (pfd[nfd++].revents & POLLIN) ? 1 : 0; 593 if (din) 594 nr |= (pfd[nfd++].revents & POLLIN) ? 2 : 0; 595 #endif 596 return nr; 597 } 598 599 sigjmp_buf xferabort; 600 601 void 602 abortxfer(int notused) 603 { 604 char msgbuf[100]; 605 int len; 606 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 (errno == EINTR) 1550 continue; 1551 if (activefallback) { 1552 (void)close(data); 1553 data = -1; 1554 passivemode = 0; 1555 #if 0 1556 activefallback = 0; 1557 #endif 1558 goto reinit; 1559 } 1560 warn("connect"); 1561 goto bad; 1562 } 1563 #ifdef IPTOS_THROUGHPUT 1564 if (data_addr.su_family == AF_INET) { 1565 on = IPTOS_THROUGHPUT; 1566 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, 1567 sizeof(int)) < 0) 1568 if (debug) 1569 warn("setsockopt TOS (ignored)"); 1570 } 1571 #endif 1572 return (0); 1573 } 1574 1575 noport: 1576 data_addr = myctladdr; 1577 if (sendport) 1578 data_addr.su_port = 0; /* let system pick one */ 1579 if (data != -1) 1580 (void)close(data); 1581 data = socket(data_addr.su_family, SOCK_STREAM, 0); 1582 if (data < 0) { 1583 warn("socket"); 1584 if (tmpno) 1585 sendport = 1; 1586 return (1); 1587 } 1588 if (!sendport) 1589 if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, 1590 sizeof(on)) < 0) { 1591 warn("setsockopt (reuse address)"); 1592 goto bad; 1593 } 1594 if (bind(data, (struct sockaddr *)&data_addr.si_su, 1595 data_addr.su_len) < 0) { 1596 warn("bind"); 1597 goto bad; 1598 } 1599 if (options & SO_DEBUG && 1600 setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, 1601 sizeof(on)) < 0) 1602 if (debug) 1603 warn("setsockopt (ignored)"); 1604 len = sizeof(data_addr.si_su); 1605 memset((char *)&data_addr, 0, sizeof (data_addr)); 1606 if (getsockname(data, (struct sockaddr *)&data_addr.si_su, &len) < 0) { 1607 warn("getsockname"); 1608 goto bad; 1609 } 1610 data_addr.su_len = len; 1611 if (xlisten(data, 1) < 0) 1612 warn("listen"); 1613 1614 if (sendport) { 1615 char hname[NI_MAXHOST], sname[NI_MAXSERV]; 1616 int af; 1617 struct sockinet tmp; 1618 1619 switch (data_addr.su_family) { 1620 case AF_INET: 1621 if (!epsv4 || epsv4bad) { 1622 result = COMPLETE + 1; 1623 break; 1624 } 1625 /* FALLTHROUGH */ 1626 #ifdef INET6 1627 case AF_INET6: 1628 #endif 1629 af = (data_addr.su_family == AF_INET) ? 1 : 2; 1630 tmp = data_addr; 1631 #ifdef INET6 1632 if (tmp.su_family == AF_INET6) 1633 tmp.si_su.su_sin6.sin6_scope_id = 0; 1634 #endif 1635 if (getnameinfo((struct sockaddr *)&tmp.si_su, 1636 tmp.su_len, hname, sizeof(hname), sname, 1637 sizeof(sname), NI_NUMERICHOST | NI_NUMERICSERV)) { 1638 result = ERROR; 1639 } else { 1640 result = command("EPRT |%d|%s|%s|", af, hname, 1641 sname); 1642 if (!connected) 1643 return (1); 1644 if (result != COMPLETE) { 1645 epsv4bad = 1; 1646 if (debug) 1647 fputs( 1648 "disabling epsv4 for this connection\n", 1649 ttyout); 1650 } 1651 } 1652 break; 1653 default: 1654 result = COMPLETE + 1; 1655 break; 1656 } 1657 if (result == COMPLETE) 1658 goto skip_port; 1659 1660 switch (data_addr.su_family) { 1661 case AF_INET: 1662 a = (char *)&data_addr.si_su.su_sin.sin_addr; 1663 p = (char *)&data_addr.su_port; 1664 result = command("PORT %d,%d,%d,%d,%d,%d", 1665 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 1666 UC(p[0]), UC(p[1])); 1667 break; 1668 #ifdef INET6 1669 case AF_INET6: 1670 a = (char *)&data_addr.si_su.su_sin6.sin6_addr; 1671 p = (char *)&data_addr.su_port; 1672 result = command( 1673 "LPRT %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", 1674 6, 16, 1675 UC(a[0]),UC(a[1]),UC(a[2]),UC(a[3]), 1676 UC(a[4]),UC(a[5]),UC(a[6]),UC(a[7]), 1677 UC(a[8]),UC(a[9]),UC(a[10]),UC(a[11]), 1678 UC(a[12]),UC(a[13]),UC(a[14]),UC(a[15]), 1679 2, UC(p[0]), UC(p[1])); 1680 break; 1681 #endif 1682 default: 1683 result = COMPLETE + 1; /* xxx */ 1684 } 1685 if (!connected) 1686 return (1); 1687 skip_port: 1688 1689 if (result == ERROR && sendport == -1) { 1690 sendport = 0; 1691 tmpno = 1; 1692 goto noport; 1693 } 1694 return (result != COMPLETE); 1695 } 1696 if (tmpno) 1697 sendport = 1; 1698 #ifdef IPTOS_THROUGHPUT 1699 if (data_addr.su_family == AF_INET) { 1700 on = IPTOS_THROUGHPUT; 1701 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, 1702 sizeof(int)) < 0) 1703 if (debug) 1704 warn("setsockopt TOS (ignored)"); 1705 } 1706 #endif 1707 return (0); 1708 bad: 1709 (void)close(data), data = -1; 1710 if (tmpno) 1711 sendport = 1; 1712 return (1); 1713 } 1714 1715 FILE * 1716 dataconn(const char *lmode) 1717 { 1718 struct sockinet from; 1719 int s, fromlen = myctladdr.su_len; 1720 1721 if (passivemode) 1722 return (fdopen(data, lmode)); 1723 1724 s = accept(data, (struct sockaddr *) &from.si_su, &fromlen); 1725 if (s < 0) { 1726 warn("accept"); 1727 (void)close(data), data = -1; 1728 return (NULL); 1729 } 1730 (void)close(data); 1731 data = s; 1732 #ifdef IPTOS_THROUGHPUT 1733 if (from.su_family == AF_INET) { 1734 int tos = IPTOS_THROUGHPUT; 1735 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, 1736 sizeof(int)) < 0) { 1737 if (debug) 1738 warn("setsockopt TOS (ignored)"); 1739 } 1740 } 1741 #endif 1742 return (fdopen(data, lmode)); 1743 } 1744 1745 void 1746 psabort(int notused) 1747 { 1748 int oerrno = errno; 1749 1750 alarmtimer(0); 1751 abrtflag++; 1752 errno = oerrno; 1753 } 1754 1755 void 1756 pswitch(int flag) 1757 { 1758 sigfunc oldintr; 1759 static struct comvars { 1760 int connect; 1761 char name[MAXHOSTNAMELEN]; 1762 struct sockinet mctl; 1763 struct sockinet hctl; 1764 FILE *in; 1765 FILE *out; 1766 int tpe; 1767 int curtpe; 1768 int cpnd; 1769 int sunqe; 1770 int runqe; 1771 int mcse; 1772 int ntflg; 1773 char nti[17]; 1774 char nto[17]; 1775 int mapflg; 1776 char mi[MAXPATHLEN]; 1777 char mo[MAXPATHLEN]; 1778 } proxstruct, tmpstruct; 1779 struct comvars *ip, *op; 1780 1781 abrtflag = 0; 1782 oldintr = xsignal(SIGINT, psabort); 1783 if (flag) { 1784 if (proxy) 1785 return; 1786 ip = &tmpstruct; 1787 op = &proxstruct; 1788 proxy++; 1789 } else { 1790 if (!proxy) 1791 return; 1792 ip = &proxstruct; 1793 op = &tmpstruct; 1794 proxy = 0; 1795 } 1796 ip->connect = connected; 1797 connected = op->connect; 1798 if (hostname) 1799 (void)strlcpy(ip->name, hostname, sizeof(ip->name)); 1800 else 1801 ip->name[0] = '\0'; 1802 hostname = op->name; 1803 ip->hctl = hisctladdr; 1804 hisctladdr = op->hctl; 1805 ip->mctl = myctladdr; 1806 myctladdr = op->mctl; 1807 ip->in = cin; 1808 cin = op->in; 1809 ip->out = cout; 1810 cout = op->out; 1811 ip->tpe = type; 1812 type = op->tpe; 1813 ip->curtpe = curtype; 1814 curtype = op->curtpe; 1815 ip->cpnd = cpend; 1816 cpend = op->cpnd; 1817 ip->sunqe = sunique; 1818 sunique = op->sunqe; 1819 ip->runqe = runique; 1820 runique = op->runqe; 1821 ip->mcse = mcase; 1822 mcase = op->mcse; 1823 ip->ntflg = ntflag; 1824 ntflag = op->ntflg; 1825 (void)strlcpy(ip->nti, ntin, sizeof(ip->nti)); 1826 (void)strlcpy(ntin, op->nti, sizeof(ntin)); 1827 (void)strlcpy(ip->nto, ntout, sizeof(ip->nto)); 1828 (void)strlcpy(ntout, op->nto, sizeof(ntout)); 1829 ip->mapflg = mapflag; 1830 mapflag = op->mapflg; 1831 (void)strlcpy(ip->mi, mapin, sizeof(ip->mi)); 1832 (void)strlcpy(mapin, op->mi, sizeof(mapin)); 1833 (void)strlcpy(ip->mo, mapout, sizeof(ip->mo)); 1834 (void)strlcpy(mapout, op->mo, sizeof(mapout)); 1835 (void)xsignal(SIGINT, oldintr); 1836 if (abrtflag) { 1837 abrtflag = 0; 1838 (*oldintr)(SIGINT); 1839 } 1840 } 1841 1842 void 1843 abortpt(int notused) 1844 { 1845 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 alarmtimer(0); 2065 len = strlcpy(msgbuf, "\nremote abort aborted; closing connection.\n", 2066 sizeof(msgbuf)); 2067 write(fileno(ttyout), msgbuf, len); 2068 lostpeer(0); 2069 siglongjmp(xferabort, 1); 2070 } 2071 2072 void 2073 abort_remote(FILE *din) 2074 { 2075 char buf[BUFSIZ]; 2076 int nfnd; 2077 2078 if (cout == NULL) { 2079 warnx("Lost control connection for abort."); 2080 if (ptabflg) 2081 code = -1; 2082 lostpeer(0); 2083 return; 2084 } 2085 /* 2086 * send IAC in urgent mode instead of DM because 4.3BSD places oob mark 2087 * after urgent byte rather than before as is protocol now 2088 */ 2089 buf[0] = IAC; 2090 buf[1] = IP; 2091 buf[2] = IAC; 2092 if (send(fileno(cout), buf, 3, MSG_OOB) != 3) 2093 warn("abort"); 2094 fprintf(cout, "%cABOR\r\n", DM); 2095 (void)fflush(cout); 2096 if ((nfnd = empty(cin, din, 10)) <= 0) { 2097 if (nfnd < 0) 2098 warn("abort"); 2099 if (ptabflg) 2100 code = -1; 2101 lostpeer(0); 2102 } 2103 if (din && (nfnd & 2)) { 2104 while (read(fileno(din), buf, BUFSIZ) > 0) 2105 continue; 2106 } 2107 if (getreply(0) == ERROR && code == 552) { 2108 /* 552 needed for nic style abort */ 2109 (void)getreply(0); 2110 } 2111 (void)getreply(0); 2112 } 2113 2114 void 2115 ai_unmapped(struct addrinfo *ai) 2116 { 2117 #ifdef INET6 2118 struct sockaddr_in6 *sin6; 2119 struct sockaddr_in sin; 2120 int len; 2121 2122 if (ai->ai_family != AF_INET6) 2123 return; 2124 if (ai->ai_addrlen != sizeof(struct sockaddr_in6) || 2125 sizeof(sin) > ai->ai_addrlen) 2126 return; 2127 sin6 = (struct sockaddr_in6 *)ai->ai_addr; 2128 if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) 2129 return; 2130 2131 memset(&sin, 0, sizeof(sin)); 2132 sin.sin_family = AF_INET; 2133 len = sizeof(struct sockaddr_in); 2134 memcpy(&sin.sin_addr, &sin6->sin6_addr.s6_addr[12], 2135 sizeof(sin.sin_addr)); 2136 sin.sin_port = sin6->sin6_port; 2137 2138 ai->ai_family = AF_INET; 2139 #if HAVE_SOCKADDR_SA_LEN 2140 sin.sin_len = len; 2141 #endif 2142 memcpy(ai->ai_addr, &sin, len); 2143 ai->ai_addrlen = len; 2144 #endif 2145 } 2146