alias_ftp.c revision 1a074ca60647580af3ac625d40694bbcf83a18c9
42576743851c3c956ad7e867e74df1084c30d434vboxsync * Copyright (c) 2001 Charles Mott <cm@linktel.net>
42576743851c3c956ad7e867e74df1084c30d434vboxsync * All rights reserved.
42576743851c3c956ad7e867e74df1084c30d434vboxsync * Redistribution and use in source and binary forms, with or without
42576743851c3c956ad7e867e74df1084c30d434vboxsync * modification, are permitted provided that the following conditions
42576743851c3c956ad7e867e74df1084c30d434vboxsync * 1. Redistributions of source code must retain the above copyright
42576743851c3c956ad7e867e74df1084c30d434vboxsync * notice, this list of conditions and the following disclaimer.
42576743851c3c956ad7e867e74df1084c30d434vboxsync * 2. Redistributions in binary form must reproduce the above copyright
42576743851c3c956ad7e867e74df1084c30d434vboxsync * notice, this list of conditions and the following disclaimer in the
42576743851c3c956ad7e867e74df1084c30d434vboxsync * documentation and/or other materials provided with the distribution.
42576743851c3c956ad7e867e74df1084c30d434vboxsync * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
42576743851c3c956ad7e867e74df1084c30d434vboxsync * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42576743851c3c956ad7e867e74df1084c30d434vboxsync * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
42576743851c3c956ad7e867e74df1084c30d434vboxsync * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
42576743851c3c956ad7e867e74df1084c30d434vboxsync * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
42576743851c3c956ad7e867e74df1084c30d434vboxsync * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
42576743851c3c956ad7e867e74df1084c30d434vboxsync * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42576743851c3c956ad7e867e74df1084c30d434vboxsync * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42576743851c3c956ad7e867e74df1084c30d434vboxsync * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42576743851c3c956ad7e867e74df1084c30d434vboxsync * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42576743851c3c956ad7e867e74df1084c30d434vboxsync * SUCH DAMAGE.
42576743851c3c956ad7e867e74df1084c30d434vboxsync__FBSDID("$FreeBSD: src/sys/netinet/libalias/alias_ftp.c,v 1.29.2.1.4.1 2009/04/15 03:14:26 kensmith Exp $");
42576743851c3c956ad7e867e74df1084c30d434vboxsync Alias_ftp.c performs special processing for FTP sessions under
42576743851c3c956ad7e867e74df1084c30d434vboxsync TCP. Specifically, when a PORT/EPRT command from the client
42576743851c3c956ad7e867e74df1084c30d434vboxsync side or 227/229 reply from the server is sent, it is intercepted
6998b7cea7c904f33047cd17b05bea760a5839a9vboxsync and modified. The address is changed to the gateway machine
02f73b88a6e96b7f1b8ab0bbb98cfb798b566fbdvboxsync and an aliasing port is used.
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync For this routine to work, the message must fit entirely into a
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync single TCP packet. This is typically the case, but exceptions
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync can easily be envisioned under the actual specifications.
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync Probably the most troubling aspect of the approach taken here is
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync that the new message will typically be a different length, and
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync this causes a certain amount of bookkeeping to keep track of the
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync changes of sequence and acknowledgment numbers, since the client
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync machine is totally unaware of the modification to the TCP stream.
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync References: RFC 959, RFC 2428.
42576743851c3c956ad7e867e74df1084c30d434vboxsync Initial version: August, 1996 (cjm)
02f73b88a6e96b7f1b8ab0bbb98cfb798b566fbdvboxsync Version 1.6
02f73b88a6e96b7f1b8ab0bbb98cfb798b566fbdvboxsync Brian Somers and Martin Renters identified an IP checksum
02f73b88a6e96b7f1b8ab0bbb98cfb798b566fbdvboxsync error for modified IP packets.
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync Version 1.7: January 9, 1996 (cjm)
cfeffc352a20376569f3feb9c5b4918ffe4c73c6vboxsync Differential checksum computation for change
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync in IP packet length.
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync Version 2.1: May, 1997 (cjm)
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync Very minor changes to conform with
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync local/global/function naming conventions
42576743851c3c956ad7e867e74df1084c30d434vboxsync within the packet aliasing module.
1379dfd407ada5fab15655776896f13b61a951fdvboxsync Version 3.1: May, 2000 (eds)
1379dfd407ada5fab15655776896f13b61a951fdvboxsync Add support for passive mode, alias the 227 replies.
1379dfd407ada5fab15655776896f13b61a951fdvboxsync See HISTORY file for record of revisions.
1379dfd407ada5fab15655776896f13b61a951fdvboxsync/* Includes */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync#else /* VBOX */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync#endif /* VBOX */
1379dfd407ada5fab15655776896f13b61a951fdvboxsyncAliasHandleFtpOut(struct libalias *, struct ip *, struct alias_link *,
1379dfd407ada5fab15655776896f13b61a951fdvboxsyncfingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah)
cb70b5cc08e3b666361766188f99cc86ed1626fbvboxsync if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync return (-1);
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync return (0);
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync return (-1);
42576743851c3c956ad7e867e74df1084c30d434vboxsyncprotohandler(struct libalias *la, struct ip *pip, struct alias_data *ah)
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync AliasHandleFtpOut(la, pip, ah->lnk, ah->maxpktsize);
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync return (0);
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync#else /* !VBOX */
e80aaa9a63f82ac2cece3a2d5a415774a72b0c82vboxsync#endif /* VBOX */
1379dfd407ada5fab15655776896f13b61a951fdvboxsyncstatic int ftp_alias_handler(PNATState pData, int type);
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync handlers = RTMemAllocZ(2 * sizeof(struct proto_handler));
1379dfd407ada5fab15655776896f13b61a951fdvboxsync#endif /* VBOX */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync#endif /*!VBOX*/
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsyncDECLARE_MODULE(alias_ftp, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND);
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync/* FTP protocol flags. */
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsyncstatic int ParseFtpPortCommand(struct libalias *la, char *, int);
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsyncstatic int ParseFtpEprtCommand(struct libalias *la, char *, int);
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsyncstatic int ParseFtp227Reply(struct libalias *la, char *, int);
06b49f334535705aeae0ac0572fc5142dc589153vboxsyncstatic int ParseFtp229Reply(struct libalias *la, char *, int);
06b49f334535705aeae0ac0572fc5142dc589153vboxsyncstatic void NewFtpMessage(struct libalias *la, struct ip *, struct alias_link *, int, int);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync struct alias_link *lnk, /* The link to go through (aliased port) */
6998b7cea7c904f33047cd17b05bea760a5839a9vboxsync int maxpacketsize /* The maximum size this packet can grow to
6998b7cea7c904f33047cd17b05bea760a5839a9vboxsync (including headers) */ )
6998b7cea7c904f33047cd17b05bea760a5839a9vboxsync/* Calculate data length of TCP packet */
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync/* Place string pointer and beginning of data */
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync * Check that data length is not too long and previous message was
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync * properly terminated with CRLF.
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync if (dlen <= MAX_MESSAGE_SIZE && !(pflags & WAIT_CRLF)) {
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER) {
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsync * When aliasing a client, check for the PORT/EPRT command.
6998b7cea7c904f33047cd17b05bea760a5839a9vboxsync * When aliasing a server, check for the 227/229 reply.
6998b7cea7c904f33047cd17b05bea760a5839a9vboxsync NewFtpMessage(la, pip, lnk, maxpacketsize, ftp_message_type);
6998b7cea7c904f33047cd17b05bea760a5839a9vboxsync/* Track the msgs which are CRLF term'd for PORT/PASV FW breach */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync * have grown */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync if (sptr[tlen - 2] == '\r' && sptr[tlen - 1] == '\n')
42576743851c3c956ad7e867e74df1084c30d434vboxsyncParseFtpPortCommand(struct libalias *la, char *sptr, int dlen)
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync /* Format: "PORT A,D,D,R,PO,RT". */
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync /* Return if data length is too short. */
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync return (0);
b32be08cd134577ca98e517c019c867c416ec0f2vboxsync return (0);
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync return (0);
b32be08cd134577ca98e517c019c867c416ec0f2vboxsync return (0);
42576743851c3c956ad7e867e74df1084c30d434vboxsync return (0);
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync return (1);
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync return (0);
cdcfac625bb49f1d4b67aaf8fb8b1cdb69fe49c2vboxsyncParseFtpEprtCommand(struct libalias *la, char *sptr, int dlen)
62eba2c4d39256b293dc23f1608c5ae26d412c0fvboxsync /* Format: "EPRT |1|A.D.D.R|PORT|". */
06b49f334535705aeae0ac0572fc5142dc589153vboxsync /* Return if data length is too short. */
b32be08cd134577ca98e517c019c867c416ec0f2vboxsync return (0);
b32be08cd134577ca98e517c019c867c416ec0f2vboxsync return (0);
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync return (0);
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync return (0);
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync return (0);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync return (0);
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync return (0);
68f6401ff0e0eac2b9dcb0c71f233cd27b289c24vboxsync return (0);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync return (1);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync return (0);
20f21077abf35d7b7b618acb159267933907407fvboxsyncParseFtp227Reply(struct libalias *la, char *sptr, int dlen)
e250515922582e0410c9bcb6d24b0f17bef083a0vboxsync /* Format: "227 Entering Passive Mode (A,D,D,R,PO,RT)" */
e250515922582e0410c9bcb6d24b0f17bef083a0vboxsync /* Return if data length is too short. */
e250515922582e0410c9bcb6d24b0f17bef083a0vboxsync return (0);
074ccc67396b8d3dbf725e280c6a9ab1a0610083vboxsync return (0);
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync return (0);
b32be08cd134577ca98e517c019c867c416ec0f2vboxsync return (0);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync else if (ch == ',' || (state == 12 && ch == ')')) {
1379dfd407ada5fab15655776896f13b61a951fdvboxsync return (0);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync return (1);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync return (0);
1379dfd407ada5fab15655776896f13b61a951fdvboxsyncParseFtp229Reply(struct libalias *la, char *sptr, int dlen)
1379dfd407ada5fab15655776896f13b61a951fdvboxsync /* Format: "229 Entering Extended Passive Mode (|||PORT|)" */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync /* Return if data length is too short. */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync return (0);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync return (0);
20f21077abf35d7b7b618acb159267933907407fvboxsync return (0);
20f21077abf35d7b7b618acb159267933907407fvboxsync return (0);
20f21077abf35d7b7b618acb159267933907407fvboxsync return (0);
20f21077abf35d7b7b618acb159267933907407fvboxsync return (0);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync return (1);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync return (0);
1379dfd407ada5fab15655776896f13b61a951fdvboxsync/* Security checks. */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync/* Establish link to address and port found in FTP control message. */
82e3a4017d20f44c30ff909e6b825ff78139cbbbvboxsync ftp_lnk = FindUdpTcpOut(la, la->true_addr, GetDestAddress(lnk),
1379dfd407ada5fab15655776896f13b61a951fdvboxsync /* Punch hole in firewall */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync/* Calculate data length of TCP packet */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync/* Create new FTP message. */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync/* Decompose alias address into quad format */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync/* Prepare new command */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync /* Decompose alias port into pair format. */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync /* Generate PORT command string. */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync RTStrPrintf(stemp, sizeof(stemp), "PORT %d,%d,%d,%d,%d,%d\r\n",
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync /* Generate 227 reply string. */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n",
1379dfd407ada5fab15655776896f13b61a951fdvboxsync "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n",
1379dfd407ada5fab15655776896f13b61a951fdvboxsync /* Generate EPRT command string. */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync RTStrPrintf(stemp, sizeof(stemp), "EPRT |1|%d.%d.%d.%d|%d|\r\n",
1379dfd407ada5fab15655776896f13b61a951fdvboxsync /* Generate 229 reply string. */
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync sprintf(stemp, "229 Entering Extended Passive Mode (|||%d|)\r\n",
1379dfd407ada5fab15655776896f13b61a951fdvboxsync RTStrPrintf(stemp, sizeof(stemp), "229 Entering Extended Passive Mode (|||%d|)\r\n",
1379dfd407ada5fab15655776896f13b61a951fdvboxsync/* Save string length for IP header modification */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync/* Copy modified buffer into IP packet. */
e89bf42607ac3c1b6c60fabbf6067a38adb1284bvboxsync/* Save information regarding modified seq and ack numbers */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync/* Revise IP header */
1379dfd407ada5fab15655776896f13b61a951fdvboxsync/* Compute TCP checksum for revised packet */
42576743851c3c956ad7e867e74df1084c30d434vboxsync "PacketAlias/HandleFtpOut: Cannot allocate FTP data port\n");