1/* $KAME: ftp.c,v 1.24 2005/03/16 05:05:48 itojun Exp $ */ 2 3/* 4 * Copyright (C) 1997 and 1998 WIDE Project. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * $FreeBSD$ 32 */ 33 34#include <sys/param.h> 35#include <sys/types.h> 36#include <sys/socket.h> 37#include <sys/ioctl.h> 38#include <sys/time.h> 39 40#include <stdio.h> 41#include <stdlib.h> 42#include <string.h> 43#include <syslog.h> 44#include <unistd.h> 45#ifdef HAVE_POLL_H 46#include <poll.h> 47#endif 48#include <errno.h> 49#include <ctype.h> 50 51#include <netinet/in.h> 52#include <arpa/inet.h> 53#include <netdb.h> 54 55#include "faithd.h" 56 57static char rbuf[MSS]; 58static char sbuf[MSS]; 59static int passivemode = 0; 60static int wport4 = -1; /* listen() to active */ 61static int wport6 = -1; /* listen() to passive */ 62static int port4 = -1; /* active: inbound passive: outbound */ 63static int port6 = -1; /* active: outbound passive: inbound */ 64static struct sockaddr_storage data4; /* server data address */ 65static struct sockaddr_storage data6; /* client data address */ 66static int epsvall = 0; 67 68enum state { NONE, LPRT, EPRT, LPSV, EPSV }; 69 70static int ftp_activeconn(void); 71static int ftp_passiveconn(void); 72static int ftp_copy(int, int); 73static int ftp_copyresult(int, int, enum state); 74static int ftp_copycommand(int, int, enum state *); 75 76void 77ftp_relay(int ctl6, int ctl4) 78{ 79#ifdef HAVE_POLL_H 80 struct pollfd pfd[6]; 81#else 82 fd_set readfds; 83#endif 84 int error; 85 enum state state = NONE; 86 struct timeval tv; 87 88 syslog(LOG_INFO, "starting ftp control connection"); 89 90 for (;;) { 91#ifdef HAVE_POLL_H 92 pfd[0].fd = ctl4; 93 pfd[0].events = POLLIN; 94 pfd[1].fd = ctl6; 95 pfd[1].events = POLLIN; 96 if (0 <= port4) { 97 pfd[2].fd = port4; 98 pfd[2].events = POLLIN; 99 } else 100 pfd[2].fd = -1; 101 if (0 <= port6) { 102 pfd[3].fd = port6; 103 pfd[3].events = POLLIN; 104 } else 105 pfd[3].fd = -1; 106#if 0 107 if (0 <= wport4) { 108 pfd[4].fd = wport4; 109 pfd[4].events = POLLIN; 110 } else 111 pfd[4].fd = -1; 112 if (0 <= wport6) { 113 pfd[5].fd = wport4; 114 pfd[5].events = POLLIN; 115 } else 116 pfd[5].fd = -1; 117#else 118 pfd[4].fd = pfd[5].fd = -1; 119 pfd[4].events = pfd[5].events = 0; 120#endif 121#else 122 int maxfd = 0; 123 124 FD_ZERO(&readfds); 125 if (ctl4 >= FD_SETSIZE) 126 exit_failure("descriptor too big"); 127 FD_SET(ctl4, &readfds); 128 maxfd = ctl4; 129 if (ctl6 >= FD_SETSIZE) 130 exit_failure("descriptor too big"); 131 FD_SET(ctl6, &readfds); 132 maxfd = (ctl6 > maxfd) ? ctl6 : maxfd; 133 if (0 <= port4) { 134 if (port4 >= FD_SETSIZE) 135 exit_failure("descriptor too big"); 136 FD_SET(port4, &readfds); 137 maxfd = (port4 > maxfd) ? port4 : maxfd; 138 } 139 if (0 <= port6) { 140 if (port6 >= FD_SETSIZE) 141 exit_failure("descriptor too big"); 142 FD_SET(port6, &readfds); 143 maxfd = (port6 > maxfd) ? port6 : maxfd; 144 } 145#if 0 146 if (0 <= wport4) { 147 if (wport4 >= FD_SETSIZE) 148 exit_failure("descriptor too big"); 149 FD_SET(wport4, &readfds); 150 maxfd = (wport4 > maxfd) ? wport4 : maxfd; 151 } 152 if (0 <= wport6) { 153 if (wport6 >= FD_SETSIZE) 154 exit_failure("descriptor too big"); 155 FD_SET(wport6, &readfds); 156 maxfd = (wport6 > maxfd) ? wport6 : maxfd; 157 } 158#endif 159#endif 160 tv.tv_sec = FAITH_TIMEOUT; 161 tv.tv_usec = 0; 162 163#ifdef HAVE_POLL_H 164 error = poll(pfd, sizeof(pfd)/sizeof(pfd[0]), tv.tv_sec * 1000); 165#else 166 error = select(maxfd + 1, &readfds, NULL, NULL, &tv); 167#endif 168 if (error == -1) { 169#ifdef HAVE_POLL_H 170 exit_failure("poll: %s", strerror(errno)); 171#else 172 exit_failure("select: %s", strerror(errno)); 173#endif 174 } 175 else if (error == 0) 176 exit_failure("connection timeout"); 177 178 /* 179 * The order of the following checks does (slightly) matter. 180 * It is important to visit all checks (do not use "continue"), 181 * otherwise some of the pipe may become full and we cannot 182 * relay correctly. 183 */ 184#ifdef HAVE_POLL_H 185 if (pfd[1].revents & POLLIN) 186#else 187 if (FD_ISSET(ctl6, &readfds)) 188#endif 189 { 190 /* 191 * copy control connection from the client. 192 * command translation is necessary. 193 */ 194 error = ftp_copycommand(ctl6, ctl4, &state); 195 196 if (error < 0) 197 goto bad; 198 else if (error == 0) { 199 close(ctl4); 200 close(ctl6); 201 exit_success("terminating ftp control connection"); 202 /*NOTREACHED*/ 203 } 204 } 205#ifdef HAVE_POLL_H 206 if (pfd[0].revents & POLLIN) 207#else 208 if (FD_ISSET(ctl4, &readfds)) 209#endif 210 { 211 /* 212 * copy control connection from the server 213 * translation of result code is necessary. 214 */ 215 error = ftp_copyresult(ctl4, ctl6, state); 216 217 if (error < 0) 218 goto bad; 219 else if (error == 0) { 220 close(ctl4); 221 close(ctl6); 222 exit_success("terminating ftp control connection"); 223 /*NOTREACHED*/ 224 } 225 } 226#ifdef HAVE_POLL_H 227 if (0 <= port4 && 0 <= port6 && (pfd[2].revents & POLLIN)) 228#else 229 if (0 <= port4 && 0 <= port6 && FD_ISSET(port4, &readfds)) 230#endif 231 { 232 /* 233 * copy data connection. 234 * no special treatment necessary. 235 */ 236#ifdef HAVE_POLL_H 237 if (pfd[2].revents & POLLIN) 238#else 239 if (FD_ISSET(port4, &readfds)) 240#endif 241 error = ftp_copy(port4, port6); 242 switch (error) { 243 case -1: 244 goto bad; 245 case 0: 246 close(port4); 247 close(port6); 248 port4 = port6 = -1; 249 syslog(LOG_INFO, "terminating data connection"); 250 break; 251 default: 252 break; 253 } 254 } 255#ifdef HAVE_POLL_H 256 if (0 <= port4 && 0 <= port6 && (pfd[3].revents & POLLIN)) 257#else 258 if (0 <= port4 && 0 <= port6 && FD_ISSET(port6, &readfds)) 259#endif 260 { 261 /* 262 * copy data connection. 263 * no special treatment necessary. 264 */ 265#ifdef HAVE_POLL_H 266 if (pfd[3].revents & POLLIN) 267#else 268 if (FD_ISSET(port6, &readfds)) 269#endif 270 error = ftp_copy(port6, port4); 271 switch (error) { 272 case -1: 273 goto bad; 274 case 0: 275 close(port4); 276 close(port6); 277 port4 = port6 = -1; 278 syslog(LOG_INFO, "terminating data connection"); 279 break; 280 default: 281 break; 282 } 283 } 284#if 0 285#ifdef HAVE_POLL_H 286 if (wport4 && (pfd[4].revents & POLLIN)) 287#else 288 if (wport4 && FD_ISSET(wport4, &readfds)) 289#endif 290 { 291 /* 292 * establish active data connection from the server. 293 */ 294 ftp_activeconn(); 295 } 296#ifdef HAVE_POLL_H 297 if (wport4 && (pfd[5].revents & POLLIN)) 298#else 299 if (wport6 && FD_ISSET(wport6, &readfds)) 300#endif 301 { 302 /* 303 * establish passive data connection from the client. 304 */ 305 ftp_passiveconn(); 306 } 307#endif 308 } 309 310 bad: 311 exit_failure("%s", strerror(errno)); 312} 313 314static int 315ftp_activeconn() 316{ 317 socklen_t n; 318 int error; 319#ifdef HAVE_POLL_H 320 struct pollfd pfd[1]; 321#else 322 fd_set set; 323#endif 324 struct timeval timeout; 325 struct sockaddr *sa; 326 327 /* get active connection from server */ 328#ifdef HAVE_POLL_H 329 pfd[0].fd = wport4; 330 pfd[0].events = POLLIN; 331#else 332 FD_ZERO(&set); 333 if (wport4 >= FD_SETSIZE) 334 exit_failure("descriptor too big"); 335 FD_SET(wport4, &set); 336#endif 337 timeout.tv_sec = 120; 338 timeout.tv_usec = 0; 339 n = sizeof(data4); 340#ifdef HAVE_POLL_H 341 if (poll(pfd, sizeof(pfd)/sizeof(pfd[0]), timeout.tv_sec * 1000) == 0 || 342 (port4 = accept(wport4, (struct sockaddr *)&data4, &n)) < 0) 343#else 344 if (select(wport4 + 1, &set, NULL, NULL, &timeout) == 0 || 345 (port4 = accept(wport4, (struct sockaddr *)&data4, &n)) < 0) 346#endif 347 { 348 close(wport4); 349 wport4 = -1; 350 syslog(LOG_INFO, "active mode data connection failed"); 351 return -1; 352 } 353 354 /* ask active connection to client */ 355 sa = (struct sockaddr *)&data6; 356 port6 = socket(sa->sa_family, SOCK_STREAM, 0); 357 if (port6 == -1) { 358 close(port4); 359 close(wport4); 360 port4 = wport4 = -1; 361 syslog(LOG_INFO, "active mode data connection failed"); 362 return -1; 363 } 364 error = connect(port6, sa, sa->sa_len); 365 if (error < 0) { 366 close(port6); 367 close(port4); 368 close(wport4); 369 port6 = port4 = wport4 = -1; 370 syslog(LOG_INFO, "active mode data connection failed"); 371 return -1; 372 } 373 374 syslog(LOG_INFO, "active mode data connection established"); 375 return 0; 376} 377 378static int 379ftp_passiveconn() 380{ 381 socklen_t len; 382 int error; 383#ifdef HAVE_POLL_H 384 struct pollfd pfd[1]; 385#else 386 fd_set set; 387#endif 388 struct timeval timeout; 389 struct sockaddr *sa; 390 391 /* get passive connection from client */ 392#ifdef HAVE_POLL_H 393 pfd[0].fd = wport6; 394 pfd[0].events = POLLIN; 395#else 396 FD_ZERO(&set); 397 if (wport6 >= FD_SETSIZE) 398 exit_failure("descriptor too big"); 399 FD_SET(wport6, &set); 400#endif 401 timeout.tv_sec = 120; 402 timeout.tv_usec = 0; 403 len = sizeof(data6); 404#ifdef HAVE_POLL_H 405 if (poll(pfd, sizeof(pfd)/sizeof(pfd[0]), timeout.tv_sec * 1000) == 0 || 406 (port6 = accept(wport6, (struct sockaddr *)&data6, &len)) < 0) 407#else 408 if (select(wport6 + 1, &set, NULL, NULL, &timeout) == 0 || 409 (port6 = accept(wport6, (struct sockaddr *)&data6, &len)) < 0) 410#endif 411 { 412 close(wport6); 413 wport6 = -1; 414 syslog(LOG_INFO, "passive mode data connection failed"); 415 return -1; 416 } 417 418 /* ask passive connection to server */ 419 sa = (struct sockaddr *)&data4; 420 port4 = socket(sa->sa_family, SOCK_STREAM, 0); 421 if (port4 == -1) { 422 close(wport6); 423 close(port6); 424 wport6 = port6 = -1; 425 syslog(LOG_INFO, "passive mode data connection failed"); 426 return -1; 427 } 428 error = connect(port4, sa, sa->sa_len); 429 if (error < 0) { 430 close(wport6); 431 close(port4); 432 close(port6); 433 wport6 = port4 = port6 = -1; 434 syslog(LOG_INFO, "passive mode data connection failed"); 435 return -1; 436 } 437 438 syslog(LOG_INFO, "passive mode data connection established"); 439 return 0; 440} 441 442static int 443ftp_copy(int src, int dst) 444{ 445 int error, atmark, n; 446 447 /* OOB data handling */ 448 error = ioctl(src, SIOCATMARK, &atmark); 449 if (error != -1 && atmark == 1) { 450 n = read(src, rbuf, 1); 451 if (n == -1) 452 goto bad; 453 send(dst, rbuf, n, MSG_OOB); 454#if 0 455 n = read(src, rbuf, sizeof(rbuf)); 456 if (n == -1) 457 goto bad; 458 write(dst, rbuf, n); 459 return n; 460#endif 461 } 462 463 n = read(src, rbuf, sizeof(rbuf)); 464 switch (n) { 465 case -1: 466 case 0: 467 return n; 468 default: 469 write(dst, rbuf, n); 470 return n; 471 } 472 473 bad: 474 exit_failure("%s", strerror(errno)); 475 /*NOTREACHED*/ 476 return 0; /* to make gcc happy */ 477} 478 479static int 480ftp_copyresult(int src, int dst, enum state state) 481{ 482 int error, atmark, n; 483 socklen_t len; 484 char *param; 485 int code; 486 char *a, *p; 487 int i; 488 489 /* OOB data handling */ 490 error = ioctl(src, SIOCATMARK, &atmark); 491 if (error != -1 && atmark == 1) { 492 n = read(src, rbuf, 1); 493 if (n == -1) 494 goto bad; 495 send(dst, rbuf, n, MSG_OOB); 496#if 0 497 n = read(src, rbuf, sizeof(rbuf)); 498 if (n == -1) 499 goto bad; 500 write(dst, rbuf, n); 501 return n; 502#endif 503 } 504 505 n = read(src, rbuf, sizeof(rbuf)); 506 if (n <= 0) 507 return n; 508 rbuf[n] = '\0'; 509 510 /* 511 * parse argument 512 */ 513 p = rbuf; 514 for (i = 0; i < 3; i++) { 515 if (!isdigit(*p)) { 516 /* invalid reply */ 517 write(dst, rbuf, n); 518 return n; 519 } 520 p++; 521 } 522 if (!isspace(*p)) { 523 /* invalid reply */ 524 write(dst, rbuf, n); 525 return n; 526 } 527 code = atoi(rbuf); 528 param = p; 529 /* param points to first non-command token, if any */ 530 while (*param && isspace(*param)) 531 param++; 532 if (!*param) 533 param = NULL; 534 535 switch (state) { 536 case NONE: 537 if (!passivemode && rbuf[0] == '1') { 538 if (ftp_activeconn() < 0) { 539 n = snprintf(rbuf, sizeof(rbuf), 540 "425 Cannot open data connetion\r\n"); 541 if (n < 0 || n >= sizeof(rbuf)) 542 n = 0; 543 } 544 } 545 if (n) 546 write(dst, rbuf, n); 547 return n; 548 case LPRT: 549 case EPRT: 550 /* expecting "200 PORT command successful." */ 551 if (code == 200) { 552 p = strstr(rbuf, "PORT"); 553 if (p) { 554 p[0] = (state == LPRT) ? 'L' : 'E'; 555 p[1] = 'P'; 556 } 557 } else { 558 close(wport4); 559 wport4 = -1; 560 } 561 write(dst, rbuf, n); 562 return n; 563 case LPSV: 564 case EPSV: 565 /* 566 * expecting "227 Entering Passive Mode (x,x,x,x,x,x,x)" 567 * (in some cases result comes without paren) 568 */ 569 if (code != 227) { 570passivefail0: 571 close(wport6); 572 wport6 = -1; 573 write(dst, rbuf, n); 574 return n; 575 } 576 577 { 578 unsigned int ho[4], po[2]; 579 struct sockaddr_in *sin; 580 struct sockaddr_in6 *sin6; 581 u_short port; 582 583 /* 584 * PASV result -> LPSV/EPSV result 585 */ 586 p = param; 587 while (*p && *p != '(' && !isdigit(*p)) /*)*/ 588 p++; 589 if (!*p) 590 goto passivefail0; /*XXX*/ 591 if (*p == '(') /*)*/ 592 p++; 593 n = sscanf(p, "%u,%u,%u,%u,%u,%u", 594 &ho[0], &ho[1], &ho[2], &ho[3], &po[0], &po[1]); 595 if (n != 6) 596 goto passivefail0; /*XXX*/ 597 598 /* keep PORT parameter */ 599 memset(&data4, 0, sizeof(data4)); 600 sin = (struct sockaddr_in *)&data4; 601 sin->sin_len = sizeof(*sin); 602 sin->sin_family = AF_INET; 603 sin->sin_addr.s_addr = 0; 604 for (n = 0; n < 4; n++) { 605 sin->sin_addr.s_addr |= 606 htonl((ho[n] & 0xff) << ((3 - n) * 8)); 607 } 608 sin->sin_port = htons(((po[0] & 0xff) << 8) | (po[1] & 0xff)); 609 610 /* get ready for passive data connection */ 611 memset(&data6, 0, sizeof(data6)); 612 sin6 = (struct sockaddr_in6 *)&data6; 613 sin6->sin6_len = sizeof(*sin6); 614 sin6->sin6_family = AF_INET6; 615 wport6 = socket(sin6->sin6_family, SOCK_STREAM, 0); 616 if (wport6 == -1) { 617passivefail: 618 n = snprintf(sbuf, sizeof(sbuf), 619 "500 could not translate from PASV\r\n"); 620 if (n < 0 || n >= sizeof(sbuf)) 621 n = 0; 622 if (n) 623 write(src, sbuf, n); 624 return n; 625 } 626#ifdef IPV6_FAITH 627 { 628 int on = 1; 629 error = setsockopt(wport6, IPPROTO_IPV6, IPV6_FAITH, 630 &on, sizeof(on)); 631 if (error == -1) 632 exit_failure("setsockopt(IPV6_FAITH): %s", strerror(errno)); 633 } 634#endif 635 error = bind(wport6, (struct sockaddr *)sin6, sin6->sin6_len); 636 if (error == -1) { 637 close(wport6); 638 wport6 = -1; 639 goto passivefail; 640 } 641 error = listen(wport6, 1); 642 if (error == -1) { 643 close(wport6); 644 wport6 = -1; 645 goto passivefail; 646 } 647 648 /* transmit LPSV or EPSV */ 649 /* 650 * addr from dst, port from wport6 651 */ 652 len = sizeof(data6); 653 error = getsockname(wport6, (struct sockaddr *)&data6, &len); 654 if (error == -1) { 655 close(wport6); 656 wport6 = -1; 657 goto passivefail; 658 } 659 sin6 = (struct sockaddr_in6 *)&data6; 660 port = sin6->sin6_port; 661 662 len = sizeof(data6); 663 error = getsockname(dst, (struct sockaddr *)&data6, &len); 664 if (error == -1) { 665 close(wport6); 666 wport6 = -1; 667 goto passivefail; 668 } 669 sin6 = (struct sockaddr_in6 *)&data6; 670 sin6->sin6_port = port; 671 672 if (state == LPSV) { 673 a = (char *)&sin6->sin6_addr; 674 p = (char *)&sin6->sin6_port; 675 n = snprintf(sbuf, sizeof(sbuf), 676"228 Entering Long Passive Mode (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)\r\n", 677 6, 16, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 678 UC(a[4]), UC(a[5]), UC(a[6]), UC(a[7]), 679 UC(a[8]), UC(a[9]), UC(a[10]), UC(a[11]), 680 UC(a[12]), UC(a[13]), UC(a[14]), UC(a[15]), 681 2, UC(p[0]), UC(p[1])); 682 if (n < 0 || n >= sizeof(sbuf)) 683 n = 0; 684 if (n) 685 write(dst, sbuf, n); 686 passivemode = 1; 687 return n; 688 } else { 689 n = snprintf(sbuf, sizeof(sbuf), 690"229 Entering Extended Passive Mode (|||%d|)\r\n", 691 ntohs(sin6->sin6_port)); 692 if (n < 0 || n >= sizeof(sbuf)) 693 n = 0; 694 if (n) 695 write(dst, sbuf, n); 696 passivemode = 1; 697 return n; 698 } 699 } 700 } 701 702 bad: 703 exit_failure("%s", strerror(errno)); 704 /*NOTREACHED*/ 705 return 0; /* to make gcc happy */ 706} 707 708static int 709ftp_copycommand(int src, int dst, enum state *state) 710{ 711 int error, atmark, n; 712 socklen_t len; 713 unsigned int af, hal, ho[16], pal, po[2]; 714 char *a, *p, *q; 715 char cmd[5], *param; 716 struct sockaddr_in *sin; 717 struct sockaddr_in6 *sin6; 718 enum state nstate; 719 char ch; 720 int i; 721 722 /* OOB data handling */ 723 error = ioctl(src, SIOCATMARK, &atmark); 724 if (error != -1 && atmark == 1) { 725 n = read(src, rbuf, 1); 726 if (n == -1) 727 goto bad; 728 send(dst, rbuf, n, MSG_OOB); 729#if 0 730 n = read(src, rbuf, sizeof(rbuf)); 731 if (n == -1) 732 goto bad; 733 write(dst, rbuf, n); 734 return n; 735#endif 736 } 737 738 n = read(src, rbuf, sizeof(rbuf)); 739 if (n <= 0) 740 return n; 741 rbuf[n] = '\0'; 742 743 if (n < 4) { 744 write(dst, rbuf, n); 745 return n; 746 } 747 748 /* 749 * parse argument 750 */ 751 p = rbuf; 752 q = cmd; 753 for (i = 0; i < 4; i++) { 754 if (!isalpha(*p)) { 755 /* invalid command */ 756 write(dst, rbuf, n); 757 return n; 758 } 759 *q++ = islower(*p) ? toupper(*p) : *p; 760 p++; 761 } 762 if (!isspace(*p)) { 763 /* invalid command */ 764 write(dst, rbuf, n); 765 return n; 766 } 767 *q = '\0'; 768 param = p; 769 /* param points to first non-command token, if any */ 770 while (*param && isspace(*param)) 771 param++; 772 if (!*param) 773 param = NULL; 774 775 *state = NONE; 776 777 if (strcmp(cmd, "LPRT") == 0 && param) { 778 /* 779 * LPRT -> PORT 780 */ 781 nstate = LPRT; 782 783 close(wport4); 784 close(wport6); 785 close(port4); 786 close(port6); 787 wport4 = wport6 = port4 = port6 = -1; 788 789 if (epsvall) { 790 n = snprintf(sbuf, sizeof(sbuf), "501 %s disallowed in EPSV ALL\r\n", 791 cmd); 792 if (n < 0 || n >= sizeof(sbuf)) 793 n = 0; 794 if (n) 795 write(src, sbuf, n); 796 return n; 797 } 798 799 n = sscanf(param, 800"%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u", 801 &af, &hal, &ho[0], &ho[1], &ho[2], &ho[3], 802 &ho[4], &ho[5], &ho[6], &ho[7], 803 &ho[8], &ho[9], &ho[10], &ho[11], 804 &ho[12], &ho[13], &ho[14], &ho[15], 805 &pal, &po[0], &po[1]); 806 if (n != 21 || af != 6 || hal != 16|| pal != 2) { 807 n = snprintf(sbuf, sizeof(sbuf), 808 "501 illegal parameter to LPRT\r\n"); 809 if (n < 0 || n >= sizeof(sbuf)) 810 n = 0; 811 if (n) 812 write(src, sbuf, n); 813 return n; 814 } 815 816 /* keep LPRT parameter */ 817 memset(&data6, 0, sizeof(data6)); 818 sin6 = (struct sockaddr_in6 *)&data6; 819 sin6->sin6_len = sizeof(*sin6); 820 sin6->sin6_family = AF_INET6; 821 for (n = 0; n < 16; n++) 822 sin6->sin6_addr.s6_addr[n] = ho[n]; 823 sin6->sin6_port = htons(((po[0] & 0xff) << 8) | (po[1] & 0xff)); 824 825sendport: 826 /* get ready for active data connection */ 827 len = sizeof(data4); 828 error = getsockname(dst, (struct sockaddr *)&data4, &len); 829 if (error == -1) { 830lprtfail: 831 n = snprintf(sbuf, sizeof(sbuf), 832 "500 could not translate to PORT\r\n"); 833 if (n < 0 || n >= sizeof(sbuf)) 834 n = 0; 835 if (n) 836 write(src, sbuf, n); 837 return n; 838 } 839 if (((struct sockaddr *)&data4)->sa_family != AF_INET) 840 goto lprtfail; 841 sin = (struct sockaddr_in *)&data4; 842 sin->sin_port = 0; 843 wport4 = socket(sin->sin_family, SOCK_STREAM, 0); 844 if (wport4 == -1) 845 goto lprtfail; 846 error = bind(wport4, (struct sockaddr *)sin, sin->sin_len); 847 if (error == -1) { 848 close(wport4); 849 wport4 = -1; 850 goto lprtfail; 851 } 852 error = listen(wport4, 1); 853 if (error == -1) { 854 close(wport4); 855 wport4 = -1; 856 goto lprtfail; 857 } 858 859 /* transmit PORT */ 860 len = sizeof(data4); 861 error = getsockname(wport4, (struct sockaddr *)&data4, &len); 862 if (error == -1) { 863 close(wport4); 864 wport4 = -1; 865 goto lprtfail; 866 } 867 if (((struct sockaddr *)&data4)->sa_family != AF_INET) { 868 close(wport4); 869 wport4 = -1; 870 goto lprtfail; 871 } 872 sin = (struct sockaddr_in *)&data4; 873 a = (char *)&sin->sin_addr; 874 p = (char *)&sin->sin_port; 875 n = snprintf(sbuf, sizeof(sbuf), "PORT %d,%d,%d,%d,%d,%d\r\n", 876 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 877 UC(p[0]), UC(p[1])); 878 if (n < 0 || n >= sizeof(sbuf)) 879 n = 0; 880 if (n) 881 write(dst, sbuf, n); 882 *state = nstate; 883 passivemode = 0; 884 return n; 885 } else if (strcmp(cmd, "EPRT") == 0 && param) { 886 /* 887 * EPRT -> PORT 888 */ 889 char *afp, *hostp, *portp; 890 struct addrinfo hints, *res; 891 892 nstate = EPRT; 893 894 close(wport4); 895 close(wport6); 896 close(port4); 897 close(port6); 898 wport4 = wport6 = port4 = port6 = -1; 899 900 if (epsvall) { 901 n = snprintf(sbuf, sizeof(sbuf), "501 %s disallowed in EPSV ALL\r\n", 902 cmd); 903 if (n < 0 || n >= sizeof(sbuf)) 904 n = 0; 905 if (n) 906 write(src, sbuf, n); 907 return n; 908 } 909 910 p = param; 911 ch = *p++; /* boundary character */ 912 afp = p; 913 while (*p && *p != ch) 914 p++; 915 if (!*p) { 916eprtparamfail: 917 n = snprintf(sbuf, sizeof(sbuf), 918 "501 illegal parameter to EPRT\r\n"); 919 if (n < 0 || n >= sizeof(sbuf)) 920 n = 0; 921 if (n) 922 write(src, sbuf, n); 923 return n; 924 } 925 *p++ = '\0'; 926 hostp = p; 927 while (*p && *p != ch) 928 p++; 929 if (!*p) 930 goto eprtparamfail; 931 *p++ = '\0'; 932 portp = p; 933 while (*p && *p != ch) 934 p++; 935 if (!*p) 936 goto eprtparamfail; 937 *p++ = '\0'; 938 939 n = sscanf(afp, "%d", &af); 940 if (n != 1 || af != 2) { 941 n = snprintf(sbuf, sizeof(sbuf), 942 "501 unsupported address family to EPRT\r\n"); 943 if (n < 0 || n >= sizeof(sbuf)) 944 n = 0; 945 if (n) 946 write(src, sbuf, n); 947 return n; 948 } 949 memset(&hints, 0, sizeof(hints)); 950 hints.ai_family = AF_UNSPEC; 951 hints.ai_socktype = SOCK_STREAM; 952 hints.ai_protocol = IPPROTO_TCP; 953 error = getaddrinfo(hostp, portp, &hints, &res); 954 if (error) { 955 n = snprintf(sbuf, sizeof(sbuf), 956 "501 EPRT: %s\r\n", gai_strerror(error)); 957 if (n < 0 || n >= sizeof(sbuf)) 958 n = 0; 959 if (n) 960 write(src, sbuf, n); 961 return n; 962 } 963 if (res->ai_next) { 964 n = snprintf(sbuf, sizeof(sbuf), 965 "501 EPRT: %s resolved to multiple addresses\r\n", hostp); 966 if (n < 0 || n >= sizeof(sbuf)) 967 n = 0; 968 if (n) 969 write(src, sbuf, n); 970 freeaddrinfo(res); 971 return n; 972 } 973 974 memcpy(&data6, res->ai_addr, res->ai_addrlen); 975 976 freeaddrinfo(res); 977 goto sendport; 978 } else if (strcmp(cmd, "LPSV") == 0 && !param) { 979 /* 980 * LPSV -> PASV 981 */ 982 nstate = LPSV; 983 984 close(wport4); 985 close(wport6); 986 close(port4); 987 close(port6); 988 wport4 = wport6 = port4 = port6 = -1; 989 990 if (epsvall) { 991 n = snprintf(sbuf, sizeof(sbuf), "501 %s disallowed in EPSV ALL\r\n", 992 cmd); 993 if (n < 0 || n >= sizeof(sbuf)) 994 n = 0; 995 if (n) 996 write(src, sbuf, n); 997 return n; 998 } 999 1000 /* transmit PASV */ 1001 n = snprintf(sbuf, sizeof(sbuf), "PASV\r\n"); 1002 if (n < 0 || n >= sizeof(sbuf)) 1003 n = 0; 1004 if (n) 1005 write(dst, sbuf, n); 1006 *state = LPSV; 1007 passivemode = 0; /* to be set to 1 later */ 1008 return n; 1009 } else if (strcmp(cmd, "EPSV") == 0 && !param) { 1010 /* 1011 * EPSV -> PASV 1012 */ 1013 close(wport4); 1014 close(wport6); 1015 close(port4); 1016 close(port6); 1017 wport4 = wport6 = port4 = port6 = -1; 1018 1019 n = snprintf(sbuf, sizeof(sbuf), "PASV\r\n"); 1020 if (n < 0 || n >= sizeof(sbuf)) 1021 n = 0; 1022 if (n) 1023 write(dst, sbuf, n); 1024 *state = EPSV; 1025 passivemode = 0; /* to be set to 1 later */ 1026 return n; 1027 } else if (strcmp(cmd, "EPSV") == 0 && param 1028 && strncasecmp(param, "ALL", 3) == 0 && isspace(param[3])) { 1029 /* 1030 * EPSV ALL 1031 */ 1032 epsvall = 1; 1033 n = snprintf(sbuf, sizeof(sbuf), "200 EPSV ALL command successful.\r\n"); 1034 if (n < 0 || n >= sizeof(sbuf)) 1035 n = 0; 1036 if (n) 1037 write(src, sbuf, n); 1038 return n; 1039 } else if (strcmp(cmd, "PORT") == 0 || strcmp(cmd, "PASV") == 0) { 1040 /* 1041 * reject PORT/PASV 1042 */ 1043 n = snprintf(sbuf, sizeof(sbuf), "502 %s not implemented.\r\n", cmd); 1044 if (n < 0 || n >= sizeof(sbuf)) 1045 n = 0; 1046 if (n) 1047 write(src, sbuf, n); 1048 return n; 1049 } else if (passivemode 1050 && (strcmp(cmd, "STOR") == 0 1051 || strcmp(cmd, "STOU") == 0 1052 || strcmp(cmd, "RETR") == 0 1053 || strcmp(cmd, "LIST") == 0 1054 || strcmp(cmd, "NLST") == 0 1055 || strcmp(cmd, "APPE") == 0)) { 1056 /* 1057 * commands with data transfer. need to care about passive 1058 * mode data connection. 1059 */ 1060 1061 if (ftp_passiveconn() < 0) { 1062 n = snprintf(sbuf, sizeof(sbuf), "425 Cannot open data connetion\r\n"); 1063 if (n < 0 || n >= sizeof(sbuf)) 1064 n = 0; 1065 if (n) 1066 write(src, sbuf, n); 1067 } else { 1068 /* simply relay the command */ 1069 write(dst, rbuf, n); 1070 } 1071 1072 *state = NONE; 1073 return n; 1074 } else { 1075 /* simply relay it */ 1076 *state = NONE; 1077 write(dst, rbuf, n); 1078 return n; 1079 } 1080 1081 bad: 1082 exit_failure("%s", strerror(errno)); 1083 /*NOTREACHED*/ 1084 return 0; /* to make gcc happy */ 1085} 1086