From eab93e766ac7e51f4a9bc43a1ba58004cf167b27 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Tue, 16 Mar 2010 16:35:23 -0700 Subject: [PATCH] Do policy lookup for defrag. Add unit test for a default host os policy. Update example config to use a default. Add 2 new policies to the stream to cover all the policies for stream and defrag. --- src/defrag.c | 127 +++++++++++++++++++++++++++--------- src/stream-tcp-reassemble.h | 2 + src/stream-tcp.c | 5 ++ src/util-host-os-info.c | 31 +++++---- suricata.yaml | 9 ++- 5 files changed, 129 insertions(+), 45 deletions(-) diff --git a/src/defrag.c b/src/defrag.c index 8e27606b50..625983d0ad 100644 --- a/src/defrag.c +++ b/src/defrag.c @@ -32,6 +32,9 @@ #include "util-debug.h" #include "util-fix_checksum.h" #include "util-random.h" +#include "stream-tcp-private.h" +#include "stream-tcp-reassemble.h" +#include "util-host-os-info.h" #ifdef UNITTESTS #include "util-unittest.h" @@ -57,15 +60,15 @@ /** Fragment reassembly policies. */ enum defrag_policies { - POLICY_FIRST = 0, - POLICY_LAST, - POLICY_BSD, - POLICY_BSD_RIGHT, - POLICY_LINUX, - POLICY_WINDOWS, - POLICY_SOLARIS, - - POLICY_DEFAULT = POLICY_BSD, + DEFRAG_POLICY_FIRST = 1, + DEFRAG_POLICY_LAST, + DEFRAG_POLICY_BSD, + DEFRAG_POLICY_BSD_RIGHT, + DEFRAG_POLICY_LINUX, + DEFRAG_POLICY_WINDOWS, + DEFRAG_POLICY_SOLARIS, + + DEFRAG_POLICY_DEFAULT = DEFRAG_POLICY_BSD, }; /** @@ -797,7 +800,7 @@ DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragContext *dc, next = TAILQ_NEXT(prev, next); switch (tracker->policy) { - case POLICY_BSD: + case DEFRAG_POLICY_BSD: if (frag_offset < prev->offset + prev->data_len) { if (frag_offset >= prev->offset) { ltrim = prev->offset + prev->data_len - frag_offset; @@ -812,7 +815,7 @@ DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragContext *dc, goto insert; } break; - case POLICY_LINUX: + case DEFRAG_POLICY_LINUX: if (frag_offset < prev->offset + prev->data_len) { if (frag_offset > prev->offset) { ltrim = prev->offset + prev->data_len - frag_offset; @@ -827,7 +830,7 @@ DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragContext *dc, goto insert; } break; - case POLICY_WINDOWS: + case DEFRAG_POLICY_WINDOWS: if (frag_offset < prev->offset + prev->data_len) { if (frag_offset >= prev->offset) { ltrim = prev->offset + prev->data_len - frag_offset; @@ -839,7 +842,7 @@ DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragContext *dc, goto insert; } break; - case POLICY_SOLARIS: + case DEFRAG_POLICY_SOLARIS: if (frag_offset < prev->offset + prev->data_len) { if (frag_offset >= prev->offset) { ltrim = prev->offset + prev->data_len - frag_offset; @@ -851,7 +854,7 @@ DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragContext *dc, goto insert; } break; - case POLICY_FIRST: + case DEFRAG_POLICY_FIRST: if ((frag_offset >= prev->offset) && (frag_end <= prev->offset + prev->data_len)) goto done; @@ -862,7 +865,7 @@ DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragContext *dc, goto insert; } break; - case POLICY_LAST: + case DEFRAG_POLICY_LAST: if (frag_offset <= prev->offset) { if (frag_end > prev->offset) prev->ltrim = frag_end - prev->offset; @@ -986,6 +989,72 @@ DefragTimeoutTracker(ThreadVars *tv, DecodeThreadVars *dtv, DefragContext *dc, } } +/** + * \brief Get the defrag policy based on the destination address of + * the packet. + * + * \param p The packet used to get the destination address. + * + * \retval The defrag policy to use. + */ +static uint8_t +DefragGetOsPolicy(Packet *p, uint8_t default_policy) +{ + uint8_t policy; + + if (PKT_IS_IPV4(p)) { + policy = SCHInfoGetIPv4HostOSFlavour((uint8_t *)GET_IPV4_DST_ADDR_PTR(p)); + } + else if (PKT_IS_IPV6(p)) { + policy = SCHInfoGetIPv6HostOSFlavour((uint8_t *)GET_IPV6_DST_ADDR(p)); + } + else + policy = default_policy; + + /* Map the OS policies returned from the configured host info to + * defrag specific policies. */ + switch (policy) { + /* BSD. */ + case OS_POLICY_BSD: + case OS_POLICY_HPUX10: + case OS_POLICY_IRIX: + return DEFRAG_POLICY_BSD; + + /* BSD-Right. */ + case OS_POLICY_BSD_RIGHT: + return DEFRAG_POLICY_BSD_RIGHT; + + /* Linux. */ + case OS_POLICY_OLD_LINUX: + case OS_POLICY_LINUX: + return DEFRAG_POLICY_LINUX; + + /* First. */ + case OS_POLICY_OLD_SOLARIS: + case OS_POLICY_HPUX11: + case OS_POLICY_MACOS: + case OS_POLICY_FIRST: + return DEFRAG_POLICY_FIRST; + + /* Solaris. */ + case OS_POLICY_SOLARIS: + return DEFRAG_POLICY_SOLARIS; + + /* Windows. */ + case OS_POLICY_WINDOWS: + case OS_POLICY_VISTA: + case OS_POLICY_WINDOWS2K3: + return DEFRAG_POLICY_WINDOWS; + + /* Last. */ + case OS_POLICY_LAST: + return DEFRAG_POLICY_LAST; + + default: + return default_policy; + } +} + static DefragTracker * DefragGetTracker(ThreadVars *tv, DecodeThreadVars *dtv, DefragContext *dc, DefragTracker *lookup_key, Packet *p) @@ -1014,9 +1083,7 @@ DefragGetTracker(ThreadVars *tv, DecodeThreadVars *dtv, DefragContext *dc, tracker->id = lookup_key->id; tracker->src_addr = lookup_key->src_addr; tracker->dst_addr = lookup_key->dst_addr; - - /* XXX Do policy lookup. */ - tracker->policy = dc->default_policy; + tracker->policy = DefragGetOsPolicy(p, dc->default_policy); if (HashListTableAdd(dc->frag_table, tracker, sizeof(*tracker)) != 0) { /* Failed to add new tracker. */ @@ -1905,7 +1972,7 @@ DefragSturgesNovakBsdTest(void) "QQQQQQQQ" }; - return DefragDoSturgesNovakTest(POLICY_BSD, expected, sizeof(expected)); + return DefragDoSturgesNovakTest(DEFRAG_POLICY_BSD, expected, sizeof(expected)); } static int @@ -1939,7 +2006,7 @@ IPV6DefragSturgesNovakBsdTest(void) "QQQQQQQQ" }; - return IPV6DefragDoSturgesNovakTest(POLICY_BSD, expected, sizeof(expected)); + return IPV6DefragDoSturgesNovakTest(DEFRAG_POLICY_BSD, expected, sizeof(expected)); } static int @@ -1973,7 +2040,7 @@ DefragSturgesNovakLinuxTest(void) "QQQQQQQQ" }; - return DefragDoSturgesNovakTest(POLICY_LINUX, expected, sizeof(expected)); + return DefragDoSturgesNovakTest(DEFRAG_POLICY_LINUX, expected, sizeof(expected)); } static int @@ -2007,7 +2074,7 @@ IPV6DefragSturgesNovakLinuxTest(void) "QQQQQQQQ" }; - return IPV6DefragDoSturgesNovakTest(POLICY_LINUX, expected, + return IPV6DefragDoSturgesNovakTest(DEFRAG_POLICY_LINUX, expected, sizeof(expected)); } @@ -2042,7 +2109,7 @@ DefragSturgesNovakWindowsTest(void) "QQQQQQQQ" }; - return DefragDoSturgesNovakTest(POLICY_WINDOWS, expected, sizeof(expected)); + return DefragDoSturgesNovakTest(DEFRAG_POLICY_WINDOWS, expected, sizeof(expected)); } static int @@ -2076,7 +2143,7 @@ IPV6DefragSturgesNovakWindowsTest(void) "QQQQQQQQ" }; - return IPV6DefragDoSturgesNovakTest(POLICY_WINDOWS, expected, + return IPV6DefragDoSturgesNovakTest(DEFRAG_POLICY_WINDOWS, expected, sizeof(expected)); } @@ -2111,7 +2178,7 @@ DefragSturgesNovakSolarisTest(void) "QQQQQQQQ" }; - return DefragDoSturgesNovakTest(POLICY_SOLARIS, expected, sizeof(expected)); + return DefragDoSturgesNovakTest(DEFRAG_POLICY_SOLARIS, expected, sizeof(expected)); } static int @@ -2145,7 +2212,7 @@ IPV6DefragSturgesNovakSolarisTest(void) "QQQQQQQQ" }; - return IPV6DefragDoSturgesNovakTest(POLICY_SOLARIS, expected, + return IPV6DefragDoSturgesNovakTest(DEFRAG_POLICY_SOLARIS, expected, sizeof(expected)); } @@ -2180,7 +2247,7 @@ DefragSturgesNovakFirstTest(void) "QQQQQQQQ" }; - return DefragDoSturgesNovakTest(POLICY_FIRST, expected, sizeof(expected)); + return DefragDoSturgesNovakTest(DEFRAG_POLICY_FIRST, expected, sizeof(expected)); } static int @@ -2214,7 +2281,7 @@ IPV6DefragSturgesNovakFirstTest(void) "QQQQQQQQ" }; - return IPV6DefragDoSturgesNovakTest(POLICY_FIRST, expected, + return IPV6DefragDoSturgesNovakTest(DEFRAG_POLICY_FIRST, expected, sizeof(expected)); } @@ -2249,7 +2316,7 @@ DefragSturgesNovakLastTest(void) "QQQQQQQQ" }; - return DefragDoSturgesNovakTest(POLICY_LAST, expected, sizeof(expected)); + return DefragDoSturgesNovakTest(DEFRAG_POLICY_LAST, expected, sizeof(expected)); } static int @@ -2283,7 +2350,7 @@ IPV6DefragSturgesNovakLastTest(void) "QQQQQQQQ" }; - return IPV6DefragDoSturgesNovakTest(POLICY_LAST, expected, + return IPV6DefragDoSturgesNovakTest(DEFRAG_POLICY_LAST, expected, sizeof(expected)); } diff --git a/src/stream-tcp-reassemble.h b/src/stream-tcp-reassemble.h index 973ad58b9b..576b36209c 100644 --- a/src/stream-tcp-reassemble.h +++ b/src/stream-tcp-reassemble.h @@ -16,8 +16,10 @@ enum { OS_POLICY_NONE = 1, OS_POLICY_BSD, + OS_POLICY_BSD_RIGHT, OS_POLICY_OLD_LINUX, OS_POLICY_LINUX, + OS_POLICY_OLD_SOLARIS, OS_POLICY_SOLARIS, OS_POLICY_HPUX10, OS_POLICY_HPUX11, diff --git a/src/stream-tcp.c b/src/stream-tcp.c index b4d00ee072..594b53b5be 100644 --- a/src/stream-tcp.c +++ b/src/stream-tcp.c @@ -447,6 +447,11 @@ void StreamTcpSetOSPolicy(TcpStream *stream, Packet *p) stream->os_policy = OS_POLICY_DEFAULT; } + if (stream->os_policy == OS_POLICY_BSD_RIGHT) + stream->os_policy = OS_POLICY_BSD; + else if (stream->os_policy == OS_POLICY_OLD_SOLARIS) + stream->os_policy = OS_POLICY_SOLARIS; + SCLogDebug("Policy is %"PRIu8"", stream->os_policy); } diff --git a/src/util-host-os-info.c b/src/util-host-os-info.c index 92ddb866fd..16a9e971e0 100644 --- a/src/util-host-os-info.c +++ b/src/util-host-os-info.c @@ -18,19 +18,21 @@ /** Enum map for the various OS flavours */ SCEnumCharMap sc_hinfo_os_policy_map[ ] = { - { "none", OS_POLICY_NONE }, - { "bsd", OS_POLICY_BSD }, - { "old_linux", OS_POLICY_OLD_LINUX }, - { "linux", OS_POLICY_LINUX }, - { "solaris", OS_POLICY_SOLARIS }, - { "hpux10", OS_POLICY_HPUX10 }, - { "hpux11", OS_POLICY_HPUX11 }, - { "irix", OS_POLICY_IRIX }, - { "macos", OS_POLICY_MACOS }, - { "windows", OS_POLICY_WINDOWS }, - { "vista", OS_POLICY_VISTA }, - { "windows2k3", OS_POLICY_WINDOWS2K3 }, - { NULL, -1 }, + { "none", OS_POLICY_NONE }, + { "bsd", OS_POLICY_BSD }, + { "bsd_right", OS_POLICY_BSD_RIGHT }, + { "old_linux", OS_POLICY_OLD_LINUX }, + { "linux", OS_POLICY_LINUX }, + { "old_solaris", OS_POLICY_OLD_SOLARIS }, + { "solaris", OS_POLICY_SOLARIS }, + { "hpux10", OS_POLICY_HPUX10 }, + { "hpux11", OS_POLICY_HPUX11 }, + { "irix", OS_POLICY_IRIX }, + { "macos", OS_POLICY_MACOS }, + { "windows", OS_POLICY_WINDOWS }, + { "vista", OS_POLICY_VISTA }, + { "windows2k3", OS_POLICY_WINDOWS2K3 }, + { NULL, -1 }, }; /** Radix tree that holds the host OS information */ @@ -992,6 +994,7 @@ int SCHInfoTestLoadFromConfig01(void) %YAML 1.1\n\ ---\n\ host-os-policy:\n\ + bsd: [0.0.0.0/0]\n\ windows: [10.0.0.0/8, 192.168.1.0/24]\n\ linux: [10.0.0.5/32]\n\ \n"; @@ -1007,6 +1010,8 @@ host-os-policy:\n\ return 0; if (SCHInfoGetHostOSFlavour("192.168.1.1") != OS_POLICY_WINDOWS) return 0; + if (SCHInfoGetHostOSFlavour("172.168.1.1") != OS_POLICY_BSD) + return 0; ConfDeInit(); ConfRestoreContextBackup(); diff --git a/suricata.yaml b/suricata.yaml index ef8c23dbab..4ad70fb69e 100644 --- a/suricata.yaml +++ b/suricata.yaml @@ -365,16 +365,21 @@ vars: SSH_PORTS: 22 +# Host specific policies for defragmentation and TCP stream +# reassembly. The host OS lookup is done using a radix tree, just +# like a routing table so the most specific entry matches. host-os-policy: - + # Make the default policy windows. + windows: [0.0.0.0/0] bsd: [] + bsd_right: [] old_linux: [] linux: [10.0.0.0/8, 192.168.1.100, "8762:2352:6241:7245:E000:0000:0000:0000"] + old_solaris: [] solaris: ["::1"] hpux10: [] hpux11: [] irix: [] macos: [] - windows: [192.168.1.0/24, 192.168.2.0/24] vista: [] windows2k3: []