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