1 /* $NetBSD: ftp.c,v 1.15 2005/03/16 05:05:06 itojun Exp $ */ 2 /* $KAME: ftp.c,v 1.23 2003/08/19 21:20:33 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 <poll.h> 45 #include <errno.h> 46 #include <ctype.h> 47 48 #include <netinet/in.h> 49 #include <arpa/inet.h> 50 #include <netdb.h> 51 52 #include "faithd.h" 53 54 static char rbuf[MSS]; 55 static char sbuf[MSS]; 56 static int passivemode = 0; 57 static int wport4 = -1; /* listen() to active */ 58 static int wport6 = -1; /* listen() to passive */ 59 static int port4 = -1; /* active: inbound passive: outbound */ 60 static int port6 = -1; /* active: outbound passive: inbound */ 61 static struct sockaddr_storage data4; /* server data address */ 62 static struct sockaddr_storage data6; /* client data address */ 63 static int epsvall = 0; 64 65 enum state { NONE, LPRT, EPRT, LPSV, EPSV }; 66 67 static int ftp_activeconn __P((void)); 68 static int ftp_passiveconn __P((void)); 69 static int ftp_copy __P((int, int)); 70 static int ftp_copyresult __P((int, int, enum state)); 71 static int ftp_copycommand __P((int, int, enum state *)); 72 73 void 74 ftp_relay(int ctl6, int ctl4) 75 { 76 struct pollfd pfd[6]; 77 int error; 78 enum state state = NONE; 79 struct timeval tv; 80 81 syslog(LOG_INFO, "starting ftp control connection"); 82 83 for (;;) { 84 pfd[0].fd = ctl4; 85 pfd[0].events = POLLIN; 86 pfd[1].fd = ctl6; 87 pfd[1].events = POLLIN; 88 if (0 <= port4) { 89 pfd[2].fd = port4; 90 pfd[2].events = POLLIN; 91 } else 92 pfd[2].fd = -1; 93 if (0 <= port6) { 94 pfd[3].fd = port6; 95 pfd[3].events = POLLIN; 96 } else 97 pfd[3].fd = -1; 98 #if 0 99 if (0 <= wport4) { 100 pfd[4].fd = wport4; 101 pfd[4].events = POLLIN; 102 } else 103 pfd[4].fd = -1; 104 if (0 <= wport6) { 105 pfd[5].fd = wport4; 106 pfd[5].events = POLLIN; 107 } else 108 pfd[5].fd = -1; 109 #else 110 pfd[4].fd = pfd[5].fd = -1; 111 pfd[4].events = pfd[5].events = 0; 112 #endif 113 tv.tv_sec = FAITH_TIMEOUT; 114 tv.tv_usec = 0; 115 116 error = poll(pfd, sizeof(pfd)/sizeof(pfd[0]), tv.tv_sec * 1000); 117 if (error == -1) { 118 exit_failure("poll: %s", strerror(errno)); 119 } 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 (pfd[1].revents & POLLIN) 130 { 131 /* 132 * copy control connection from the client. 133 * command translation is necessary. 134 */ 135 error = ftp_copycommand(ctl6, ctl4, &state); 136 137 if (error < 0) 138 goto bad; 139 else if (error == 0) { 140 close(ctl4); 141 close(ctl6); 142 exit_success("terminating ftp control connection"); 143 /*NOTREACHED*/ 144 } 145 } 146 if (pfd[0].revents & POLLIN) 147 { 148 /* 149 * copy control connection from the server 150 * translation of result code is necessary. 151 */ 152 error = ftp_copyresult(ctl4, ctl6, state); 153 154 if (error < 0) 155 goto bad; 156 else if (error == 0) { 157 close(ctl4); 158 close(ctl6); 159 exit_success("terminating ftp control connection"); 160 /*NOTREACHED*/ 161 } 162 } 163 if (0 <= port4 && 0 <= port6 && (pfd[2].revents & POLLIN)) 164 { 165 /* 166 * copy data connection. 167 * no special treatment necessary. 168 */ 169 if (pfd[2].revents & POLLIN) 170 error = ftp_copy(port4, port6); 171 switch (error) { 172 case -1: 173 goto bad; 174 case 0: 175 close(port4); 176 close(port6); 177 port4 = port6 = -1; 178 syslog(LOG_INFO, "terminating data connection"); 179 break; 180 default: 181 break; 182 } 183 } 184 if (0 <= port4 && 0 <= port6 && (pfd[3].revents & POLLIN)) 185 { 186 /* 187 * copy data connection. 188 * no special treatment necessary. 189 */ 190 if (pfd[3].revents & POLLIN) 191 error = ftp_copy(port6, port4); 192 switch (error) { 193 case -1: 194 goto bad; 195 case 0: 196 close(port4); 197 close(port6); 198 port4 = port6 = -1; 199 syslog(LOG_INFO, "terminating data connection"); 200 break; 201 default: 202 break; 203 } 204 } 205 #if 0 206 if (wport4 && (pfd[4].revents & POLLIN)) 207 { 208 /* 209 * establish active data connection from the server. 210 */ 211 ftp_activeconn(); 212 } 213 if (wport4 && (pfd[5].revents & POLLIN)) 214 { 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 socklen_t n; 231 int error; 232 struct pollfd pfd[1]; 233 struct timeval timeout; 234 struct sockaddr *sa; 235 236 /* get active connection from server */ 237 pfd[0].fd = wport4; 238 pfd[0].events = POLLIN; 239 timeout.tv_sec = 120; 240 timeout.tv_usec = 0; 241 n = sizeof(data4); 242 if (poll(pfd, sizeof(pfd)/sizeof(pfd[0]), timeout.tv_sec * 1000) == 0 || 243 (port4 = accept(wport4, (struct sockaddr *)&data4, &n)) < 0) 244 { 245 close(wport4); 246 wport4 = -1; 247 syslog(LOG_INFO, "active mode data connection failed"); 248 return -1; 249 } 250 251 /* ask active connection to client */ 252 sa = (struct sockaddr *)&data6; 253 port6 = socket(sa->sa_family, SOCK_STREAM, 0); 254 if (port6 == -1) { 255 close(port4); 256 close(wport4); 257 port4 = wport4 = -1; 258 syslog(LOG_INFO, "active mode data connection failed"); 259 return -1; 260 } 261 error = connect(port6, sa, sa->sa_len); 262 if (error < 0) { 263 close(port6); 264 close(port4); 265 close(wport4); 266 port6 = port4 = wport4 = -1; 267 syslog(LOG_INFO, "active mode data connection failed"); 268 return -1; 269 } 270 271 syslog(LOG_INFO, "active mode data connection established"); 272 return 0; 273 } 274 275 static int 276 ftp_passiveconn() 277 { 278 socklen_t len; 279 int error; 280 struct pollfd pfd[1]; 281 struct timeval timeout; 282 struct sockaddr *sa; 283 284 /* get passive connection from client */ 285 pfd[0].fd = wport6; 286 pfd[0].events = POLLIN; 287 timeout.tv_sec = 120; 288 timeout.tv_usec = 0; 289 len = sizeof(data6); 290 if (poll(pfd, sizeof(pfd)/sizeof(pfd[0]), timeout.tv_sec * 1000) == 0 || 291 (port6 = accept(wport6, (struct sockaddr *)&data6, &len)) < 0) 292 { 293 close(wport6); 294 wport6 = -1; 295 syslog(LOG_INFO, "passive mode data connection failed"); 296 return -1; 297 } 298 299 /* ask passive connection to server */ 300 sa = (struct sockaddr *)&data4; 301 port4 = socket(sa->sa_family, SOCK_STREAM, 0); 302 if (port4 == -1) { 303 close(wport6); 304 close(port6); 305 wport6 = port6 = -1; 306 syslog(LOG_INFO, "passive mode data connection failed"); 307 return -1; 308 } 309 error = connect(port4, sa, sa->sa_len); 310 if (error < 0) { 311 close(wport6); 312 close(port4); 313 close(port6); 314 wport6 = port4 = port6 = -1; 315 syslog(LOG_INFO, "passive mode data connection failed"); 316 return -1; 317 } 318 319 syslog(LOG_INFO, "passive mode data connection established"); 320 return 0; 321 } 322 323 static int 324 ftp_copy(int src, int dst) 325 { 326 int error, atmark, n; 327 328 /* OOB data handling */ 329 error = ioctl(src, SIOCATMARK, &atmark); 330 if (error != -1 && atmark == 1) { 331 n = read(src, rbuf, 1); 332 if (n == -1) 333 goto bad; 334 send(dst, rbuf, n, MSG_OOB); 335 #if 0 336 n = read(src, rbuf, sizeof(rbuf)); 337 if (n == -1) 338 goto bad; 339 write(dst, rbuf, n); 340 return n; 341 #endif 342 } 343 344 n = read(src, rbuf, sizeof(rbuf)); 345 switch (n) { 346 case -1: 347 case 0: 348 return n; 349 default: 350 write(dst, rbuf, n); 351 return n; 352 } 353 354 bad: 355 exit_failure("%s", strerror(errno)); 356 /*NOTREACHED*/ 357 return 0; /* to make gcc happy */ 358 } 359 360 static int 361 ftp_copyresult(int src, int dst, enum state state) 362 { 363 int error, atmark, n; 364 socklen_t len; 365 char *param; 366 int code; 367 char *a, *p; 368 int i; 369 370 /* OOB data handling */ 371 error = ioctl(src, SIOCATMARK, &atmark); 372 if (error != -1 && atmark == 1) { 373 n = read(src, rbuf, 1); 374 if (n == -1) 375 goto bad; 376 send(dst, rbuf, n, MSG_OOB); 377 #if 0 378 n = read(src, rbuf, sizeof(rbuf)); 379 if (n == -1) 380 goto bad; 381 write(dst, rbuf, n); 382 return n; 383 #endif 384 } 385 386 n = read(src, rbuf, sizeof(rbuf)); 387 if (n <= 0) 388 return n; 389 rbuf[n] = '\0'; 390 391 /* 392 * parse argument 393 */ 394 p = rbuf; 395 for (i = 0; i < 3; i++) { 396 if (!isdigit((unsigned char)*p)) { 397 /* invalid reply */ 398 write(dst, rbuf, n); 399 return n; 400 } 401 p++; 402 } 403 if (!isspace((unsigned char)*p)) { 404 /* invalid reply */ 405 write(dst, rbuf, n); 406 return n; 407 } 408 code = atoi(rbuf); 409 param = p; 410 /* param points to first non-command token, if any */ 411 while (*param && isspace((unsigned char)*param)) 412 param++; 413 if (!*param) 414 param = NULL; 415 416 switch (state) { 417 case NONE: 418 if (!passivemode && rbuf[0] == '1') { 419 if (ftp_activeconn() < 0) { 420 n = snprintf(rbuf, sizeof(rbuf), 421 "425 Cannot open data connetion\r\n"); 422 if (n < 0 || n >= sizeof(rbuf)) 423 n = 0; 424 } 425 } 426 if (n) 427 write(dst, rbuf, n); 428 return n; 429 case LPRT: 430 case EPRT: 431 /* expecting "200 PORT command successful." */ 432 if (code == 200) { 433 p = strstr(rbuf, "PORT"); 434 if (p) { 435 p[0] = (state == LPRT) ? 'L' : 'E'; 436 p[1] = 'P'; 437 } 438 } else { 439 close(wport4); 440 wport4 = -1; 441 } 442 write(dst, rbuf, n); 443 return n; 444 case LPSV: 445 case EPSV: 446 /* 447 * expecting "227 Entering Passive Mode (x,x,x,x,x,x,x)" 448 * (in some cases result comes without paren) 449 */ 450 if (code != 227) { 451 passivefail0: 452 close(wport6); 453 wport6 = -1; 454 write(dst, rbuf, n); 455 return n; 456 } 457 458 { 459 unsigned int ho[4], po[2]; 460 struct sockaddr_in *sin; 461 struct sockaddr_in6 *sin6; 462 u_short port; 463 464 /* 465 * PASV result -> LPSV/EPSV result 466 */ 467 p = param; 468 while (*p && *p != '(' && !isdigit((unsigned char)*p)) /*)*/ 469 p++; 470 if (!*p) 471 goto passivefail0; /*XXX*/ 472 if (*p == '(') /*)*/ 473 p++; 474 n = sscanf(p, "%u,%u,%u,%u,%u,%u", 475 &ho[0], &ho[1], &ho[2], &ho[3], &po[0], &po[1]); 476 if (n != 6) 477 goto passivefail0; /*XXX*/ 478 479 /* keep PORT parameter */ 480 memset(&data4, 0, sizeof(data4)); 481 sin = (struct sockaddr_in *)&data4; 482 sin->sin_len = sizeof(*sin); 483 sin->sin_family = AF_INET; 484 sin->sin_addr.s_addr = 0; 485 for (n = 0; n < 4; n++) { 486 sin->sin_addr.s_addr |= 487 htonl((ho[n] & 0xff) << ((3 - n) * 8)); 488 } 489 sin->sin_port = htons(((po[0] & 0xff) << 8) | (po[1] & 0xff)); 490 491 /* get ready for passive data connection */ 492 memset(&data6, 0, sizeof(data6)); 493 sin6 = (struct sockaddr_in6 *)&data6; 494 sin6->sin6_len = sizeof(*sin6); 495 sin6->sin6_family = AF_INET6; 496 wport6 = socket(sin6->sin6_family, SOCK_STREAM, 0); 497 if (wport6 == -1) { 498 passivefail: 499 n = snprintf(sbuf, sizeof(sbuf), 500 "500 could not translate from PASV\r\n"); 501 if (n < 0 || n >= sizeof(sbuf)) 502 n = 0; 503 if (n) 504 write(src, sbuf, n); 505 return n; 506 } 507 #ifdef IPV6_FAITH 508 { 509 int on = 1; 510 error = setsockopt(wport6, IPPROTO_IPV6, IPV6_FAITH, 511 &on, sizeof(on)); 512 if (error == -1) 513 exit_failure("setsockopt(IPV6_FAITH): %s", strerror(errno)); 514 } 515 #endif 516 error = bind(wport6, (struct sockaddr *)sin6, sin6->sin6_len); 517 if (error == -1) { 518 close(wport6); 519 wport6 = -1; 520 goto passivefail; 521 } 522 error = listen(wport6, 1); 523 if (error == -1) { 524 close(wport6); 525 wport6 = -1; 526 goto passivefail; 527 } 528 529 /* transmit LPSV or EPSV */ 530 /* 531 * addr from dst, port from wport6 532 */ 533 len = sizeof(data6); 534 error = getsockname(wport6, (struct sockaddr *)&data6, &len); 535 if (error == -1) { 536 close(wport6); 537 wport6 = -1; 538 goto passivefail; 539 } 540 sin6 = (struct sockaddr_in6 *)&data6; 541 port = sin6->sin6_port; 542 543 len = sizeof(data6); 544 error = getsockname(dst, (struct sockaddr *)&data6, &len); 545 if (error == -1) { 546 close(wport6); 547 wport6 = -1; 548 goto passivefail; 549 } 550 sin6 = (struct sockaddr_in6 *)&data6; 551 sin6->sin6_port = port; 552 553 if (state == LPSV) { 554 a = (char *)&sin6->sin6_addr; 555 p = (char *)&sin6->sin6_port; 556 n = snprintf(sbuf, sizeof(sbuf), 557 "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", 558 6, 16, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 559 UC(a[4]), UC(a[5]), UC(a[6]), UC(a[7]), 560 UC(a[8]), UC(a[9]), UC(a[10]), UC(a[11]), 561 UC(a[12]), UC(a[13]), UC(a[14]), UC(a[15]), 562 2, UC(p[0]), UC(p[1])); 563 if (n < 0 || n >= sizeof(sbuf)) 564 n = 0; 565 if (n) 566 write(dst, sbuf, n); 567 passivemode = 1; 568 return n; 569 } else { 570 n = snprintf(sbuf, sizeof(sbuf), 571 "229 Entering Extended Passive Mode (|||%d|)\r\n", 572 ntohs(sin6->sin6_port)); 573 if (n < 0 || n >= sizeof(sbuf)) 574 n = 0; 575 if (n) 576 write(dst, sbuf, n); 577 passivemode = 1; 578 return n; 579 } 580 } 581 } 582 583 bad: 584 exit_failure("%s", strerror(errno)); 585 /*NOTREACHED*/ 586 return 0; /* to make gcc happy */ 587 } 588 589 static int 590 ftp_copycommand(int src, int dst, enum state *state) 591 { 592 int error, atmark, n; 593 socklen_t len; 594 unsigned int af, hal, ho[16], pal, po[2]; 595 char *a, *p, *q; 596 char cmd[5], *param; 597 struct sockaddr_in *sin; 598 struct sockaddr_in6 *sin6; 599 enum state nstate; 600 char ch; 601 int i; 602 603 /* OOB data handling */ 604 error = ioctl(src, SIOCATMARK, &atmark); 605 if (error != -1 && atmark == 1) { 606 n = read(src, rbuf, 1); 607 if (n == -1) 608 goto bad; 609 send(dst, rbuf, n, MSG_OOB); 610 #if 0 611 n = read(src, rbuf, sizeof(rbuf)); 612 if (n == -1) 613 goto bad; 614 write(dst, rbuf, n); 615 return n; 616 #endif 617 } 618 619 n = read(src, rbuf, sizeof(rbuf)); 620 if (n <= 0) 621 return n; 622 rbuf[n] = '\0'; 623 624 if (n < 4) { 625 write(dst, rbuf, n); 626 return n; 627 } 628 629 /* 630 * parse argument 631 */ 632 p = rbuf; 633 q = cmd; 634 for (i = 0; i < 4; i++) { 635 if (!isalpha((unsigned char)*p)) { 636 /* invalid command */ 637 write(dst, rbuf, n); 638 return n; 639 } 640 *q++ = islower((unsigned char)*p) ? toupper((unsigned char)*p) : *p; 641 p++; 642 } 643 if (!isspace((unsigned char)*p)) { 644 /* invalid command */ 645 write(dst, rbuf, n); 646 return n; 647 } 648 *q = '\0'; 649 param = p; 650 /* param points to first non-command token, if any */ 651 while (*param && isspace((unsigned char)*param)) 652 param++; 653 if (!*param) 654 param = NULL; 655 656 *state = NONE; 657 658 if (strcmp(cmd, "LPRT") == 0 && param) { 659 /* 660 * LPRT -> PORT 661 */ 662 nstate = LPRT; 663 664 close(wport4); 665 close(wport6); 666 close(port4); 667 close(port6); 668 wport4 = wport6 = port4 = port6 = -1; 669 670 if (epsvall) { 671 n = snprintf(sbuf, sizeof(sbuf), "501 %s disallowed in EPSV ALL\r\n", 672 cmd); 673 if (n < 0 || n >= sizeof(sbuf)) 674 n = 0; 675 if (n) 676 write(src, sbuf, n); 677 return n; 678 } 679 680 n = sscanf(param, 681 "%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u", 682 &af, &hal, &ho[0], &ho[1], &ho[2], &ho[3], 683 &ho[4], &ho[5], &ho[6], &ho[7], 684 &ho[8], &ho[9], &ho[10], &ho[11], 685 &ho[12], &ho[13], &ho[14], &ho[15], 686 &pal, &po[0], &po[1]); 687 if (n != 21 || af != 6 || hal != 16|| pal != 2) { 688 n = snprintf(sbuf, sizeof(sbuf), 689 "501 illegal parameter to LPRT\r\n"); 690 if (n < 0 || n >= sizeof(sbuf)) 691 n = 0; 692 if (n) 693 write(src, sbuf, n); 694 return n; 695 } 696 697 /* keep LPRT parameter */ 698 memset(&data6, 0, sizeof(data6)); 699 sin6 = (struct sockaddr_in6 *)&data6; 700 sin6->sin6_len = sizeof(*sin6); 701 sin6->sin6_family = AF_INET6; 702 for (n = 0; n < 16; n++) 703 sin6->sin6_addr.s6_addr[n] = ho[n]; 704 sin6->sin6_port = htons(((po[0] & 0xff) << 8) | (po[1] & 0xff)); 705 706 sendport: 707 /* get ready for active data connection */ 708 len = sizeof(data4); 709 error = getsockname(dst, (struct sockaddr *)&data4, &len); 710 if (error == -1) { 711 lprtfail: 712 n = snprintf(sbuf, sizeof(sbuf), 713 "500 could not translate to PORT\r\n"); 714 if (n < 0 || n >= sizeof(sbuf)) 715 n = 0; 716 if (n) 717 write(src, sbuf, n); 718 return n; 719 } 720 if (((struct sockaddr *)&data4)->sa_family != AF_INET) 721 goto lprtfail; 722 sin = (struct sockaddr_in *)&data4; 723 sin->sin_port = 0; 724 wport4 = socket(sin->sin_family, SOCK_STREAM, 0); 725 if (wport4 == -1) 726 goto lprtfail; 727 error = bind(wport4, (struct sockaddr *)sin, sin->sin_len); 728 if (error == -1) { 729 close(wport4); 730 wport4 = -1; 731 goto lprtfail; 732 } 733 error = listen(wport4, 1); 734 if (error == -1) { 735 close(wport4); 736 wport4 = -1; 737 goto lprtfail; 738 } 739 740 /* transmit PORT */ 741 len = sizeof(data4); 742 error = getsockname(wport4, (struct sockaddr *)&data4, &len); 743 if (error == -1) { 744 close(wport4); 745 wport4 = -1; 746 goto lprtfail; 747 } 748 if (((struct sockaddr *)&data4)->sa_family != AF_INET) { 749 close(wport4); 750 wport4 = -1; 751 goto lprtfail; 752 } 753 sin = (struct sockaddr_in *)&data4; 754 a = (char *)&sin->sin_addr; 755 p = (char *)&sin->sin_port; 756 n = snprintf(sbuf, sizeof(sbuf), "PORT %d,%d,%d,%d,%d,%d\r\n", 757 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 758 UC(p[0]), UC(p[1])); 759 if (n < 0 || n >= sizeof(sbuf)) 760 n = 0; 761 if (n) 762 write(dst, sbuf, n); 763 *state = nstate; 764 passivemode = 0; 765 return n; 766 } else if (strcmp(cmd, "EPRT") == 0 && param) { 767 /* 768 * EPRT -> PORT 769 */ 770 char *afp, *hostp, *portp; 771 struct addrinfo hints, *res; 772 773 nstate = EPRT; 774 775 close(wport4); 776 close(wport6); 777 close(port4); 778 close(port6); 779 wport4 = wport6 = port4 = port6 = -1; 780 781 if (epsvall) { 782 n = snprintf(sbuf, sizeof(sbuf), "501 %s disallowed in EPSV ALL\r\n", 783 cmd); 784 if (n < 0 || n >= sizeof(sbuf)) 785 n = 0; 786 if (n) 787 write(src, sbuf, n); 788 return n; 789 } 790 791 p = param; 792 ch = *p++; /* boundary character */ 793 afp = p; 794 while (*p && *p != ch) 795 p++; 796 if (!*p) { 797 eprtparamfail: 798 n = snprintf(sbuf, sizeof(sbuf), 799 "501 illegal parameter to EPRT\r\n"); 800 if (n < 0 || n >= sizeof(sbuf)) 801 n = 0; 802 if (n) 803 write(src, sbuf, n); 804 return n; 805 } 806 *p++ = '\0'; 807 hostp = p; 808 while (*p && *p != ch) 809 p++; 810 if (!*p) 811 goto eprtparamfail; 812 *p++ = '\0'; 813 portp = p; 814 while (*p && *p != ch) 815 p++; 816 if (!*p) 817 goto eprtparamfail; 818 *p++ = '\0'; 819 820 n = sscanf(afp, "%d", &af); 821 if (n != 1 || af != 2) { 822 n = snprintf(sbuf, sizeof(sbuf), 823 "501 unsupported address family to EPRT\r\n"); 824 if (n < 0 || n >= sizeof(sbuf)) 825 n = 0; 826 if (n) 827 write(src, sbuf, n); 828 return n; 829 } 830 memset(&hints, 0, sizeof(hints)); 831 hints.ai_family = AF_UNSPEC; 832 hints.ai_socktype = SOCK_STREAM; 833 hints.ai_protocol = IPPROTO_TCP; 834 error = getaddrinfo(hostp, portp, &hints, &res); 835 if (error) { 836 n = snprintf(sbuf, sizeof(sbuf), 837 "501 EPRT: %s\r\n", gai_strerror(error)); 838 if (n < 0 || n >= sizeof(sbuf)) 839 n = 0; 840 if (n) 841 write(src, sbuf, n); 842 return n; 843 } 844 if (res->ai_next) { 845 n = snprintf(sbuf, sizeof(sbuf), 846 "501 EPRT: %s resolved to multiple addresses\r\n", hostp); 847 if (n < 0 || n >= sizeof(sbuf)) 848 n = 0; 849 if (n) 850 write(src, sbuf, n); 851 freeaddrinfo(res); 852 return n; 853 } 854 855 memcpy(&data6, res->ai_addr, res->ai_addrlen); 856 857 freeaddrinfo(res); 858 goto sendport; 859 } else if (strcmp(cmd, "LPSV") == 0 && !param) { 860 /* 861 * LPSV -> PASV 862 */ 863 nstate = LPSV; 864 865 close(wport4); 866 close(wport6); 867 close(port4); 868 close(port6); 869 wport4 = wport6 = port4 = port6 = -1; 870 871 if (epsvall) { 872 n = snprintf(sbuf, sizeof(sbuf), "501 %s disallowed in EPSV ALL\r\n", 873 cmd); 874 if (n < 0 || n >= sizeof(sbuf)) 875 n = 0; 876 if (n) 877 write(src, sbuf, n); 878 return n; 879 } 880 881 /* transmit PASV */ 882 n = snprintf(sbuf, sizeof(sbuf), "PASV\r\n"); 883 if (n < 0 || n >= sizeof(sbuf)) 884 n = 0; 885 if (n) 886 write(dst, sbuf, n); 887 *state = LPSV; 888 passivemode = 0; /* to be set to 1 later */ 889 return n; 890 } else if (strcmp(cmd, "EPSV") == 0 && !param) { 891 /* 892 * EPSV -> PASV 893 */ 894 close(wport4); 895 close(wport6); 896 close(port4); 897 close(port6); 898 wport4 = wport6 = port4 = port6 = -1; 899 900 n = snprintf(sbuf, sizeof(sbuf), "PASV\r\n"); 901 if (n < 0 || n >= sizeof(sbuf)) 902 n = 0; 903 if (n) 904 write(dst, sbuf, n); 905 *state = EPSV; 906 passivemode = 0; /* to be set to 1 later */ 907 return n; 908 } else if (strcmp(cmd, "EPSV") == 0 && param 909 && strncasecmp(param, "ALL", 3) == 0 && isspace((unsigned char)param[3])) { 910 /* 911 * EPSV ALL 912 */ 913 epsvall = 1; 914 n = snprintf(sbuf, sizeof(sbuf), "200 EPSV ALL command successful.\r\n"); 915 if (n < 0 || n >= sizeof(sbuf)) 916 n = 0; 917 if (n) 918 write(src, sbuf, n); 919 return n; 920 } else if (strcmp(cmd, "PORT") == 0 || strcmp(cmd, "PASV") == 0) { 921 /* 922 * reject PORT/PASV 923 */ 924 n = snprintf(sbuf, sizeof(sbuf), "502 %s not implemented.\r\n", cmd); 925 if (n < 0 || n >= sizeof(sbuf)) 926 n = 0; 927 if (n) 928 write(src, sbuf, n); 929 return n; 930 } else if (passivemode 931 && (strcmp(cmd, "STOR") == 0 932 || strcmp(cmd, "STOU") == 0 933 || strcmp(cmd, "RETR") == 0 934 || strcmp(cmd, "LIST") == 0 935 || strcmp(cmd, "NLST") == 0 936 || strcmp(cmd, "APPE") == 0)) { 937 /* 938 * commands with data transfer. need to care about passive 939 * mode data connection. 940 */ 941 942 if (ftp_passiveconn() < 0) { 943 n = snprintf(sbuf, sizeof(sbuf), "425 Cannot open data connetion\r\n"); 944 if (n < 0 || n >= sizeof(sbuf)) 945 n = 0; 946 if (n) 947 write(src, sbuf, n); 948 } else { 949 /* simply relay the command */ 950 write(dst, rbuf, n); 951 } 952 953 *state = NONE; 954 return n; 955 } else { 956 /* simply relay it */ 957 *state = NONE; 958 write(dst, rbuf, n); 959 return n; 960 } 961 962 bad: 963 exit_failure("%s", strerror(errno)); 964 /*NOTREACHED*/ 965 return 0; /* to make gcc happy */ 966 } 967