-- changed binder to inspector with designated type
-- added prototype wizard inspector for service selection magic
-- fixed plugin instantiation when top level table is a list
+-- changed http_inspect to optionally build dynamically
92
-- fixed fast_pattern only auto configuration
# initialization
#--------------------------------------------------------------------------
-AC_INIT([snort], [2.10.092])
+AC_INIT([snort], [2.10.093])
AC_PREREQ([2.68])
AC_CONFIG_SRCDIR([src/main.h])
-- configure builtin features
---------------------------------------------------------------------------
+cd_udp = { gtp_ports = GTP_PORTS }
+
-- Configure active response for non inline operation.
active =
{
post_depth = 65495,
}
-nhttp_inspect = { }
+--nhttp_inspect = { }
---------------------------------------------------------------------------
-- ftp / telnet normalization and anomaly detection
#alert tcp any any -> any any ( sid:402; content:"ABA"; content:"C", offset 5; )
#alert tcp any any -> any any ( sid:403; content:"ABA"; content:"C", offset 6; )
#alert tcp any any -> any any ( sid:404; content:"ABA"; content:"C", offset 5, depth 6; )
-alert tcp any any -> any any ( sid:510; content:"ABA"; content:"C", within 1; )
-alert tcp any any -> any any ( sid:110; pcre:"/ABA/"; )
-alert tcp any any -> any any ( sid:210; raw_data; pcre:"/ABA/"; )
-alert tcp any any -> any any ( sid:310; pkt_data; pcre:"/ABA/"; )
-alert tcp any any -> any any ( sid:410; pcre:"/ABA/"; pcre:"/C/"; )
-alert tcp any any -> any any ( sid:411; pcre:"/ABA/"; pcre:"/AC/R"; )
-alert tcp any any -> any any ( sid:412; pcre:"/ABA/"; pcre:"/AC/"; )
-alert tcp any any -> any any ( sid:414; pcre:"/ABA/"; pcre:"/C/R"; )
+#alert tcp any any -> any any ( sid:510; content:"ABA"; content:"C", within 1; )
+#alert tcp any any -> any any ( sid:110; pcre:"/ABA/"; )
+#alert tcp any any -> any any ( sid:210; raw_data; pcre:"/ABA/"; )
+#alert tcp any any -> any any ( sid:310; pkt_data; pcre:"/ABA/"; )
+#alert tcp any any -> any any ( sid:410; pcre:"/ABA/"; pcre:"/C/"; )
+#alert tcp any any -> any any ( sid:411; pcre:"/ABA/"; pcre:"/AC/R"; )
+#alert tcp any any -> any any ( sid:412; pcre:"/ABA/"; pcre:"/AC/"; )
+#alert tcp any any -> any any ( sid:414; pcre:"/ABA/"; pcre:"/C/R"; )
+
+alert ( gid:134; sid:1; )
+alert ( gid:134; sid:2; )
+alert ( gid:134; sid:3; )
]]
network =
{
include = '../active.rules',
rules = default_rules,
- enable_builtin_rules = true
+ enable_builtin_rules = false
}
--[[
}
}
+---------------------------------------------------------------------------
+-- prototype wizard
+---------------------------------------------------------------------------
+
+ftp_commands = { 'USER' } -- add others
+sip_methods = { 'INVITE', 'NOTIFY' } -- add others
+
+telnet_commands =
+{
+ '|FF F0|', '|FF F1|', '|FF F2|', '|FF F3|',
+ '|FF F4|', '|FF F5|', '|FF F6|', '|FF F7|',
+ '|FF F8|', '|FF F9|', '|FF FA|', '|FF FB|',
+ '|FF FC|', '|FF FD|', '|FF FE|', '|FF FF|'
+}
+
+xwizard =
+{
+ spells =
+ {
+ { service = 'ftp', proto = 'tcp', client_first = false,
+ to_client = ftp_commands, to_server = { '220*FTP' } },
+
+ { service = 'http', proto = 'tcp', client_first = true,
+ to_server = default_http_methods, to_client = { 'HTTP/' } },
+
+ { service = 'imap', proto = 'tcp', client_first = false,
+ to_client = { 'LOGIN', 'AUTHENTICATE', 'STARTTLS' },
+ to_server = { '**OK', '**BYE' } },
+
+ { service = 'pop', proto = 'tcp', client_first = false,
+ to_client = { 'USER', 'APOP' },
+ to_server = { '+OK', '-ERR' } },
+
+ { service = 'sip', proto = 'tcp', client_first = true,
+ to_server = sip_methods, to_client = { 'SIP/' } },
+
+ { service = 'smtp', proto = 'tcp', client_first = false,
+ to_client = { 'HELO', 'EHLO' },
+ to_server = { '220*SMTP', '220*MAIL' } },
+
+ { service = 'ssh', proto = 'tcp', client_first = true,
+ to_server = { '*SSH' }, to_client = { '*SSH' } }
+ },
+ hexes =
+ {
+ { service = 'dce/rpc', proto = 'tcp', client_first = true,
+ to_server = { '|05 00|' }, to_client = { '|05 00|' } },
+
+ { service = 'dnp3', proto = 'tcp', client_first = true,
+ to_server = { '|05 64|' }, to_client = { '|05 64|' } },
+
+ { service = 'isakmp', proto = 'udp', client_first = true,
+ to_server = { '+17 |01|', '+17 |10|' },
+ to_client = { '+17 |01|', '+17 |10|' } },
+
+ { service = 'modbus', proto = 'tcp', client_first = true,
+ to_server = { '+2 |0 0|' } },
+
+ { service = 'rpc', proto = 'tcp', client_first = true,
+ to_server = { '+4 |0 0 0 0 0 0 0 1|' },
+ to_client = { '+4 |0 0 0 0 0 0 0 1|' } },
+
+ { service = 'smb', proto = 'tcp', client_first = true,
+ to_server = { '|FF|SMB' }, to_client = { '|FF|SMB' } },
+
+ { service = 'smb', proto = 'udp', client_first = true,
+ to_server = { '|FF|SMB' }, to_client = { '|FF|SMB' } },
+
+ { service = 'ssl', proto = 'tcp', client_first = true,
+ to_server = { '|16 03|' }, to_client = { '|16 03|' } },
+
+ { service = 'telnet', proto = 'tcp', client_first = true,
+ to_server = telnet_commands, to_client = telnet_commands },
+ }
+}
+
---------------------------------------------------------------------------
-- prototype bindings:
--
if STATIC_INSPECTORS
lib_list = \
network_inspectors/arp_spoof/libarp_spoof.a \
-network_inspectors/binder/libbinder.a \
network_inspectors/port_scan/libport_scan.a \
service_inspectors/back_orifice/libback_orifice.a \
service_inspectors/ftp_telnet/libftp_telnet.a \
codecs/root/libroot_codecs.a \
codecs/libcodec_utils.a \
network_inspectors/libnetwork_inspectors.a \
+network_inspectors/binder/libbinder.a \
network_inspectors/normalize/libnormalize.a \
network_inspectors/perf_monitor/libperf_monitor.a \
service_inspectors/libservice_inspectors.a \
class FlowData
{
public:
- FlowData(unsigned u, Inspector* ph = nullptr);
+ FlowData(unsigned u, Inspector* = nullptr);
virtual ~FlowData();
unsigned get_id()
bind_reset
};
-#ifdef BUILDING_SO
-SO_PUBLIC const BaseApi* snort_plugins[] =
-{
- &bind_api.base,
- nullptr
-};
-#else
const BaseApi* nin_binder = &bind_api.base;
-#endif
/* otherwise defined in /usr/include/ppp_defs.h */
#define UDP_HEADER_LEN 8
-#define IsUDP(p) (IsIP(p) && p->udph)
+// FIXIT udph should not be set for udp tunnel
+// (only if innermost layer == udp)
+#define IsUDP(p) (IsIP(p) && !IsTCP(p) && p->udph)
namespace udp
hi_util_xmalloc.h
)
-#if (STATIC_INSPECTORS)
+if (STATIC_INSPECTORS)
add_library(http_inspect STATIC ${FILE_LIST})
-#else (STATIC_INSPECTORS)
-# add_shared_library(http_inspect inspectors ${FILE_LIST})
+else (STATIC_INSPECTORS)
+ add_shared_library(http_inspect inspectors ${FILE_LIST})
-#endif (STATIC_INSPECTORS)
+endif (STATIC_INSPECTORS)
hi_util_kmap.cc hi_util_kmap.h \
hi_util_xmalloc.cc hi_util_xmalloc.h
-#if STATIC_INSPECTORS
+if STATIC_INSPECTORS
noinst_LIBRARIES = libhttp_inspect.a
libhttp_inspect_a_SOURCES = $(file_list)
-#else
-# need to fix undefineds first :(
-#shlibdir = $(pkglibdir)/inspectors
-#shlib_LTLIBRARIES = libhttp_inspect.la
-#libhttp_inspect_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO
-#libhttp_inspect_la_LDFLAGS = -export-dynamic -shared
-#libhttp_inspect_la_SOURCES = $(file_list)
-#endif
+else
+shlibdir = $(pkglibdir)/inspectors
+shlib_LTLIBRARIES = libhttp_inspect.la
+libhttp_inspect_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO
+libhttp_inspect_la_LDFLAGS = -export-dynamic -shared
+libhttp_inspect_la_SOURCES = $(file_list)
+endif
AM_CXXFLAGS = @AM_CXXFLAGS@
unsigned HttpFlowData::flow_id = 0;
+void HttpFlowData::init()
+{
+ flow_id = FlowData::get_flow_id();
+}
+
HttpFlowData::HttpFlowData() : FlowData(flow_id)
{
memset(&session, 0, sizeof(session));
HttpFlowData();
~HttpFlowData();
- static void init()
- { flow_id = FlowData::get_flow_id(); };
+ static void init();
public:
static unsigned flow_id;
** - 2.10.03: Initial Development. DJR
*/
-/*
-FIXIT if HI is built dynamically, Snort get these undefineds:
-Undefined symbols for architecture x86_64:
- "IsGzipData(Flow*)", referenced from:
- LogIPPkt(_TextLog*, int, Packet*) in liblog.a(log_text.o)
- "IsJSNormData(Flow*)", referenced from:
- LogIPPkt(_TextLog*, int, Packet*) in liblog.a(log_text.o)
- "GetHttpUriData(Flow*, unsigned char**, unsigned int*, unsigned int*)", referenced from:
- add_file_to_block(Packet*, _File_Verdict, unsigned int, unsigned char*) in libfile_api.a(file_service.o)
- check_http_partial_content(Packet*) in libfile_api.a(file_service.o)
-*/
-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* Find and cache protocol ID for packet comparison */
hi_app_protocol_id = AddProtocolReference("http");
- hi_paf_init(0); // FIXTHIS is cap needed?
HttpFlowData::init();
HI_SearchInit();
+ hi_paf_init(0); // FIXTHIS is cap needed?
InitLookupTables();
InitJSNormLookupTable();
}
static void hs_term()
{
- hi_paf_term();
HI_SearchFree();
+ hi_paf_term();
}
static Inspector* hs_ctor(Module* m)
nhttp_stream_splitter.cc nhttp_stream_splitter.h \
nhttp_scratch_pad.h nhttp_enum.h
-
-#if STATIC_INSPECTORS
+if STATIC_INSPECTORS
noinst_LIBRARIES = libnhttp_inspect.a
libnhttp_inspect_a_SOURCES = $(file_list)
-#else
-# need to fix undefineds first :(
-#shlibdir = $(pkglibdir)/inspectors
-#shlib_LTLIBRARIES = libnhttp_inspect.la
-#libnhttp_inspect_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO
-#libnhttp_inspect_la_LDFLAGS = -export-dynamic -shared
-#libnhttp_inspect_la_SOURCES = $(file_list)
-#endif
+else
+shlibdir = $(pkglibdir)/inspectors
+shlib_LTLIBRARIES = libnhttp_inspect.la
+libnhttp_inspect_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO
+libnhttp_inspect_la_LDFLAGS = -export-dynamic -shared
+libnhttp_inspect_la_SOURCES = $(file_list)
+endif
AM_CXXFLAGS = @AM_CXXFLAGS@
#endif
#include "framework/inspector.h"
-extern const BaseApi* sin_http_global;
-extern const BaseApi* sin_http_server;
-
#ifdef STATIC_INSPECTORS
extern const BaseApi* sin_bo;
extern const BaseApi* sin_ftp_client;
extern const BaseApi* sin_ftp_server;
+extern const BaseApi* sin_http_global;
+extern const BaseApi* sin_http_server;
extern const BaseApi* sin_nhttp;
extern const BaseApi* sin_rpc_decode;
extern const BaseApi* sin_telnet;
const BaseApi* service_inspectors[] =
{
- sin_http_global,
- sin_http_server,
-
#ifdef STATIC_INSPECTORS
sin_bo,
sin_ftp_client,
sin_ftp_server,
+ sin_http_global,
+ sin_http_server,
sin_nhttp,
sin_rpc_decode,
sin_telnet,
wizard.cc wizard.h \
wiz_module.cc wiz_module.h
-#if STATIC_INSPECTORS
+if STATIC_INSPECTORS
noinst_LIBRARIES = libwizard.a
libwizard_a_SOURCES = $(file_list)
-#else
-# need to fix undefineds first :(
-#shlibdir = $(pkglibdir)/inspectors
-#shlib_LTLIBRARIES = libwizard.la
-#libwizard_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO
-#libwizard_la_LDFLAGS = -export-dynamic -shared
-#libwizard_la_SOURCES = $(file_list)
-#endif
+else
+shlibdir = $(pkglibdir)/inspectors
+shlib_LTLIBRARIES = libwizard.la
+libwizard_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO
+libwizard_la_LDFLAGS = -export-dynamic -shared
+libwizard_la_SOURCES = $(file_list)
+endif
AM_CXXFLAGS = @AM_CXXFLAGS@
}
#endif
-static THREAD_LOCAL SimpleStats tstats;
-static SimpleStats gstats;
+struct WizStats
+{
+ PegCount tcp_scans;
+ PegCount tcp_hits;
+ PegCount udp_pkts;
+ PegCount udp_hits;
+};
+
+static const char* wiz_pegs[] =
+{
+ "tcp scans",
+ "tcp hits",
+ "udp packets",
+ "udp hits"
+};
+
+static THREAD_LOCAL WizStats tstats;
+static WizStats gstats;
//-------------------------------------------------------------------------
-// splitter - this doesn't actually split the stream but it applies
-// basic magic type logic to determine the appropriate inspector that
-// will split the stream.
+// configuration
+// -- spells are used for text protocols
+// -- must compile spells into fsm like hi paf
+//
+// -- hexes are used for binary protocols
+// -- must build a tree trie like file magic
//-------------------------------------------------------------------------
-class MagicSplitter : public StreamSplitter
+struct Spell
{
-public:
- MagicSplitter(bool c2s) : StreamSplitter(c2s) { };
- ~MagicSplitter() { };
+ const char* dummy;
+};
- PAF_Status scan(Flow*, const uint8_t* data, uint32_t len,
- uint32_t flags, uint32_t* fp);
+struct Hex
+{
+ const char* dummy;
};
-PAF_Status MagicSplitter::scan (
- Flow*, const uint8_t* data, uint32_t len,
- uint32_t, uint32_t* fp)
+struct Wand
{
- // this is a basic hack to find http requests so that the overall
- // processing flow can be determined at which point the real magic
- // can begin.
- if ( len >= 3 && !strncmp((const char*)data, "GET", 3) )
- {
- // FIXIT here we have determined that the inspector should
- // be http and must somehow tell the binder so it can set
- // inspector gadget.
+ unsigned index;
+};
- // the real magic must check direction and protocol
- // (and should be called from eval() for udp and from
- // here for tcp).
+class Wizard;
- // len + 1 means go back to the last flush point
- *fp = len + 1;
+class MagicSplitter : public StreamSplitter
+{
+public:
+ MagicSplitter(bool, class Wizard*);
+ ~MagicSplitter();
- // the reset status ensures that all the
- // data scanned so far is delivered to the new inspector's
- // splitter.
- return PAF_RESET;
- }
+ PAF_Status scan(Flow*, const uint8_t* data, uint32_t len,
+ uint32_t flags, uint32_t* fp);
- return PAF_SEARCH;
-}
+ bool is_paf() { return true; };
-//-------------------------------------------------------------------------
-// class stuff
-//-------------------------------------------------------------------------
+private:
+ Wizard* wizard;
+ Wand wand;
+};
class Wizard : public Inspector {
public:
StreamSplitter* get_splitter(bool);
-private:
+ bool check(Wand&, const uint8_t*, unsigned, vector<Spell>&, vector<Hex>&);
-private:
+public:
+ vector<Spell> tcp_c2s_spells;
+ vector<Spell> tcp_s2c_spells;
+
+ vector<Spell> udp_c2s_spells;
+ vector<Spell> udp_s2c_spells;
+
+ vector<Hex> tcp_c2s_hexes;
+ vector<Hex> tcp_s2c_hexes;
+
+ vector<Hex> udp_c2s_hexes;
+ vector<Hex> udp_s2c_hexes;
};
+//-------------------------------------------------------------------------
+// splitter - this doesn't actually split the stream but it applies
+// basic magic type logic to determine the appropriate inspector that
+// will split the stream.
+//-------------------------------------------------------------------------
+
+MagicSplitter::MagicSplitter(bool c2s, class Wizard* w) : StreamSplitter(c2s)
+{
+ wizard = w;
+ w->add_ref();
+}
+
+MagicSplitter::~MagicSplitter()
+{
+ wizard->rem_ref();
+}
+
+PAF_Status MagicSplitter::scan (
+ Flow*, const uint8_t* data, uint32_t len,
+ uint32_t, uint32_t* fp)
+{
+ ++tstats.tcp_scans;
+
+ if ( to_server() )
+ {
+ if ( wizard->check(wand, data, len, wizard->tcp_c2s_spells, wizard->tcp_c2s_hexes) )
+ {
+ /* set inspector gadget */
+ // len + 1 means go back to the last flush point
+ // (0 means start of this buffer)
+ *fp = len + 1;
+ return PAF_RESET;
+ }
+ }
+ else
+ {
+ if ( wizard->check(wand, data, len, wizard->tcp_s2c_spells, wizard->tcp_s2c_hexes) )
+ {
+ /* set inspector gadget */
+ *fp = len + 1;
+ return PAF_RESET;
+ }
+ }
+ return PAF_SEARCH;
+}
+
+//-------------------------------------------------------------------------
+// class stuff
+//-------------------------------------------------------------------------
+
Wizard::Wizard()
{
}
{
}
-void Wizard::eval(Packet*)
+void Wizard::eval(Packet* p)
{
if ( !IsUDP(p) )
return;
- // FIXIT do udp scanning here
- ++tstats.total_packets;
+ if ( !p->data || !p->dsize )
+ return;
+
+ Wand wand;
+
+ if ( p->packet_flags & PKT_FROM_CLIENT )
+ {
+ if ( check(wand, p->data, p->dsize, udp_c2s_spells, udp_c2s_hexes) )
+ { /* set inspector gadget */ }
+ }
+
+ else
+ {
+ if ( check(wand, p->data, p->dsize, udp_s2c_spells, udp_s2c_hexes) )
+ { /* set inspector gadget */ }
+ }
+
+ ++tstats.udp_pkts;
}
StreamSplitter* Wizard::get_splitter(bool c2s)
{
- return new MagicSplitter(c2s);
+ return new MagicSplitter(c2s, this);
+}
+
+bool Wizard::check(
+ Wand&, const uint8_t* data, unsigned len, vector<Spell>&, vector<Hex>&)
+{
+ // this is a basic hack to find http requests so that the overall
+ // processing flow can be determined at which point the real magic
+ // can begin.
+
+ if ( len >= 3 && !strncmp((const char*)data, "GET", 3) )
+ {
+ // FIXIT here we have determined that the inspector should
+ // be http and must somehow tell the binder so it can set
+ // inspector gadget.
+
+ // the real magic must check direction and protocol
+ // (and should be called from eval() for udp and from
+ // here for tcp).
+
+ // the reset status ensures that all the
+ // data scanned so far is delivered to the new inspector's
+ // splitter.
+ ++tstats.tcp_hits;
+ return true;
+ }
+ return false;
}
//-------------------------------------------------------------------------
static void wiz_sum()
{
- sum_stats(&gstats, &tstats);
+ sum_stats((PegCount*)&gstats, (PegCount*)&tstats, array_size(wiz_pegs));
}
static void wiz_stats()
{
- show_stats(&gstats, mod_name);
+ show_stats((PegCount*)&gstats, wiz_pegs, array_size(wiz_pegs), mod_name);
}
static void wiz_reset()
trk = &tcpssn->client;
}
- if ( trk->splitter && tcpssn->tcp_init )
- delete trk->splitter;
+ // FIXIT we have a sequencing issue with binder
+ //if ( trk->splitter && tcpssn->tcp_init )
+ // delete trk->splitter;
trk->splitter = ss;
STREAM5_DEBUG_WRAP( DebugMessage(DEBUG_STREAM_STATE,
"After cleaning, %lu bytes in use\n", tcp_memcap->used()););
+ memset(&tcpssn->client, 0, sizeof(tcpssn->client));
+ memset(&tcpssn->server, 0, sizeof(tcpssn->server));
+
tcpssn->lws_init = tcpssn->tcp_init = false;
}
tmp->ecn = 0;
tmp->tcp_init = true;
+
PREPROC_PROFILE_END(s5TcpNewSessPerfStats);
return 1;
}