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