summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/netinet/libalias/alias_ftp.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/netinet/libalias/alias_ftp.c')
-rw-r--r--freebsd/sys/netinet/libalias/alias_ftp.c124
1 files changed, 103 insertions, 21 deletions
diff --git a/freebsd/sys/netinet/libalias/alias_ftp.c b/freebsd/sys/netinet/libalias/alias_ftp.c
index c8a09413..43411d41 100644
--- a/freebsd/sys/netinet/libalias/alias_ftp.c
+++ b/freebsd/sys/netinet/libalias/alias_ftp.c
@@ -102,38 +102,68 @@ __FBSDID("$FreeBSD$");
#define FTP_CONTROL_PORT_NUMBER 21
static void
-AliasHandleFtpOut(struct libalias *, struct ip *, struct alias_link *,
- int maxpacketsize);
+AliasHandleFtpOut(struct libalias *, struct ip *, struct alias_link *,
+ int maxpacketsize);
+static void
+AliasHandleFtpIn(struct libalias *, struct ip *, struct alias_link *);
-static int
-fingerprint(struct libalias *la, struct alias_data *ah)
+static int
+fingerprint_out(struct libalias *la, struct alias_data *ah)
{
- if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
- ah->maxpktsize == 0)
+ if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
+ ah->maxpktsize == 0)
return (-1);
- if (ntohs(*ah->dport) == FTP_CONTROL_PORT_NUMBER
- || ntohs(*ah->sport) == FTP_CONTROL_PORT_NUMBER)
+ if (ntohs(*ah->dport) == FTP_CONTROL_PORT_NUMBER ||
+ ntohs(*ah->sport) == FTP_CONTROL_PORT_NUMBER)
return (0);
return (-1);
}
-static int
-protohandler(struct libalias *la, struct ip *pip, struct alias_data *ah)
+static int
+fingerprint_in(struct libalias *la, struct alias_data *ah)
+{
+
+ if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL)
+ return (-1);
+ if (ntohs(*ah->dport) == FTP_CONTROL_PORT_NUMBER ||
+ ntohs(*ah->sport) == FTP_CONTROL_PORT_NUMBER)
+ return (0);
+ return (-1);
+}
+
+static int
+protohandler_out(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
-
+
AliasHandleFtpOut(la, pip, ah->lnk, ah->maxpktsize);
return (0);
}
+
+static int
+protohandler_in(struct libalias *la, struct ip *pip, struct alias_data *ah)
+{
+
+ AliasHandleFtpIn(la, pip, ah->lnk);
+ return (0);
+}
+
struct proto_handler handlers[] = {
- {
- .pri = 80,
- .dir = OUT,
- .proto = TCP,
- .fingerprint = &fingerprint,
- .protohandler = &protohandler
- },
+ {
+ .pri = 80,
+ .dir = OUT,
+ .proto = TCP,
+ .fingerprint = &fingerprint_out,
+ .protohandler = &protohandler_out
+ },
+ {
+ .pri = 80,
+ .dir = IN,
+ .proto = TCP,
+ .fingerprint = &fingerprint_in,
+ .protohandler = &protohandler_in
+ },
{ EOH }
};
@@ -258,6 +288,57 @@ AliasHandleFtpOut(
}
}
+static void
+AliasHandleFtpIn(struct libalias *la,
+ struct ip *pip, /* IP packet to examine/patch */
+ struct alias_link *lnk) /* The link to go through (aliased port) */
+{
+ int hlen, tlen, dlen, pflags;
+ char *sptr;
+ struct tcphdr *tc;
+
+ /* Calculate data length of TCP packet */
+ tc = (struct tcphdr *)ip_next(pip);
+ hlen = (pip->ip_hl + tc->th_off) << 2;
+ tlen = ntohs(pip->ip_len);
+ dlen = tlen - hlen;
+
+ /* Place string pointer and beginning of data */
+ sptr = (char *)pip;
+ sptr += hlen;
+
+ /*
+ * Check that data length is not too long and previous message was
+ * properly terminated with CRLF.
+ */
+ pflags = GetProtocolFlags(lnk);
+ if (dlen <= MAX_MESSAGE_SIZE && (pflags & WAIT_CRLF) == 0 &&
+ ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER &&
+ (ParseFtpPortCommand(la, sptr, dlen) != 0 ||
+ ParseFtpEprtCommand(la, sptr, dlen) != 0)) {
+ /*
+ * Alias active mode client requesting data from server
+ * behind NAT. We need to alias server->client connection
+ * to external address client is connecting to.
+ */
+ AddLink(la, GetOriginalAddress(lnk), la->true_addr,
+ GetAliasAddress(lnk), htons(FTP_CONTROL_PORT_NUMBER - 1),
+ htons(la->true_port), GET_ALIAS_PORT, IPPROTO_TCP);
+ }
+ /* Track the msgs which are CRLF term'd for PORT/PASV FW breach */
+ if (dlen) {
+ sptr = (char *)pip; /* start over at beginning */
+ tlen = ntohs(pip->ip_len); /* recalc tlen, pkt may
+ * have grown.
+ */
+ if (sptr[tlen - 2] == '\r' && sptr[tlen - 1] == '\n')
+ pflags &= ~WAIT_CRLF;
+ else
+ pflags |= WAIT_CRLF;
+ SetProtocolFlags(lnk, pflags);
+ }
+}
+
static int
ParseFtpPortCommand(struct libalias *la, char *sptr, int dlen)
{
@@ -578,9 +659,10 @@ NewFtpMessage(struct libalias *la, struct ip *pip,
if (la->true_port < IPPORT_RESERVED)
return;
-/* Establish link to address and port found in FTP control message. */
- ftp_lnk = FindUdpTcpOut(la, la->true_addr, GetDestAddress(lnk),
- htons(la->true_port), 0, IPPROTO_TCP, 1);
+ /* Establish link to address and port found in FTP control message. */
+ ftp_lnk = AddLink(la, la->true_addr, GetDestAddress(lnk),
+ GetAliasAddress(lnk), htons(la->true_port), 0, GET_ALIAS_PORT,
+ IPPROTO_TCP);
if (ftp_lnk != NULL) {
int slen, hlen, tlen, dlen;