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