From: Russ Combs Date: Fri, 27 Jun 2014 03:37:12 +0000 (-0400) Subject: added wizard and binder inspectors X-Git-Tag: 3.0.0-233~1457 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e78603333f6e0f234a82b7fe7aaa70caeb11b1df;p=thirdparty%2Fsnort3.git added wizard and binder inspectors --- diff --git a/ChangeLog b/ChangeLog index 1fa8a89e8..3aeb753f0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,9 @@ 93 -- updated example inspector dpx.cc api -- misc tweaks +-- 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 92 -- fixed fast_pattern only auto configuration diff --git a/configure.ac b/configure.ac index f43ab0894..816f97164 100644 --- a/configure.ac +++ b/configure.ac @@ -842,6 +842,7 @@ src/stream/tcp/Makefile \ src/stream/udp/Makefile \ src/network_inspectors/Makefile \ src/network_inspectors/arp_spoof/Makefile \ +src/network_inspectors/binder/Makefile \ src/network_inspectors/normalize/Makefile \ src/network_inspectors/perf_monitor/Makefile \ src/network_inspectors/port_scan/Makefile \ @@ -853,6 +854,7 @@ src/service_inspectors/ftp_telnet/Makefile \ src/service_inspectors/http_inspect/Makefile \ src/service_inspectors/nhttp_inspect/Makefile \ src/service_inspectors/rpc_decode/Makefile \ +src/service_inspectors/wizard/Makefile \ src/protocols/Makefile \ src/search_engines/Makefile \ src/sfip/Makefile \ diff --git a/src/Makefile.am b/src/Makefile.am index b27e7cff0..e9ad6f038 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -9,11 +9,13 @@ main.h 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 \ +service_inspectors/nhttp_inspect/libnhttp_inspect.a \ service_inspectors/rpc_decode/librpc_decode.a \ -service_inspectors/nhttp_inspect/libnhttp_inspect.a +service_inspectors/wizard/libwizard.a endif # order libs to avoid undefined symbols diff --git a/src/flow/flow_control.cc b/src/flow/flow_control.cc index 621eeb3a7..56f228ff8 100644 --- a/src/flow/flow_control.cc +++ b/src/flow/flow_control.cc @@ -32,18 +32,19 @@ #include "flow/session.h" #include "packet_io/active.h" #include "packet_io/sfdaq.h" -#include "main/binder.h" #include "utils/stats.h" #include "protocols/layer.h" #include "protocols/vlan.h" +#include "managers/inspector_manager.h" -FlowControl::FlowControl() +FlowControl::FlowControl(Inspector* pi) { ip_cache = nullptr; icmp_cache = nullptr; tcp_cache = nullptr; udp_cache = nullptr; exp_cache = nullptr; + binder = pi; } FlowControl::~FlowControl() @@ -264,9 +265,11 @@ unsigned FlowControl::process(FlowCache* cache, Packet* p) if ( !flow ) return 0; + p->flow = flow; + if ( !flow->ssn_client ) { - Binder::init_flow(flow); + binder->eval(p); if ( !flow->session->setup(p) ) return 0; @@ -274,11 +277,10 @@ unsigned FlowControl::process(FlowCache* cache, Packet* p) news = 1; } - p->flow = flow; flow->session->process(p); if ( news ) - Binder::init_flow(flow, p); + binder->eval(p); if ( flow->next && is_bidirectional(flow) ) cache->unlink_uni(flow); diff --git a/src/flow/flow_control.h b/src/flow/flow_control.h index e213936c6..9a444b4e3 100644 --- a/src/flow/flow_control.h +++ b/src/flow/flow_control.h @@ -37,7 +37,7 @@ struct FlowConfig class FlowControl { public: - FlowControl(); + FlowControl(class Inspector*); ~FlowControl(); public: @@ -94,7 +94,9 @@ private: FlowCache* udp_cache; FlowCache* icmp_cache; FlowCache* ip_cache; + class ExpectCache* exp_cache; + class Inspector* binder; }; #endif diff --git a/src/framework/inspector.h b/src/framework/inspector.h index 98ea49e10..eaa734a92 100644 --- a/src/framework/inspector.h +++ b/src/framework/inspector.h @@ -100,6 +100,9 @@ public: void set_api(const InspectApi* p) { api = p; }; + const InspectApi* get_api() + { return api; }; + public: static unsigned max_slots; static THREAD_LOCAL unsigned slot; @@ -116,6 +119,8 @@ private: enum InspectorType { + IT_BINDER, + IT_WIZARD, IT_PACKET, IT_PROTOCOL, IT_STREAM, diff --git a/src/main/CMakeLists.txt b/src/main/CMakeLists.txt index e0fcca301..1b9436942 100644 --- a/src/main/CMakeLists.txt +++ b/src/main/CMakeLists.txt @@ -8,8 +8,6 @@ set (INCLUDES add_library (main STATIC analyzer.h analyzer.cc - binder.cc - binder.h build.h modules.cc modules.h diff --git a/src/main/Makefile.am b/src/main/Makefile.am index cda8f3d41..270bff5ae 100644 --- a/src/main/Makefile.am +++ b/src/main/Makefile.am @@ -12,8 +12,6 @@ thread.h libmain_a_SOURCES = \ analyzer.cc \ analyzer.h \ -binder.cc \ -binder.h \ build.h \ modules.cc \ modules.h \ diff --git a/src/main/modules.cc b/src/main/modules.cc index a915d7c57..cc9f33efb 100644 --- a/src/main/modules.cc +++ b/src/main/modules.cc @@ -33,11 +33,9 @@ using namespace std; #include "framework/module.h" #include "managers/module_manager.h" -#include "main/binder.h" #include "main.h" #include "snort.h" #include "snort_config.h" -#include "binder.h" #include "parser/parser.h" #include "parser/parse_conf.h" #include "parser/config_file.h" @@ -1636,150 +1634,6 @@ public: bool set(const char*, Value&, SnortConfig*) { return false; }; }; -//------------------------------------------------------------------------- -// binder module -//------------------------------------------------------------------------- - -static const Parameter binder_when_params[] = -{ - { "policy_id", Parameter::PT_STRING, nullptr, nullptr, - "unique ID for selection of this config by external logic" }, - - { "vlans", Parameter::PT_BIT_LIST, "4095", nullptr, - "list of VLAN IDs" }, - - { "nets", Parameter::PT_ADDR_LIST, nullptr, nullptr, - "list of networks" }, - - { "proto", Parameter::PT_ENUM, "any | ip | icmp | tcp | udp", nullptr, - "protocol" }, - - { "ports", Parameter::PT_BIT_LIST, "65535", nullptr, - "list of ports" }, - - { "role", Parameter::PT_ENUM, "client | server | any", "any", - "use the given configuration on one or any end of a session" }, - - { "service", Parameter::PT_STRING, nullptr, nullptr, - "override default configuration" }, - - { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } -}; - -static const Parameter binder_use_params[] = -{ - { "action", Parameter::PT_ENUM, "inspect | allow | block", "inspect", - "what to do with matching traffic" }, - - { "file", Parameter::PT_STRING, nullptr, nullptr, - "use configuration in given file" }, - - { "policy_id", Parameter::PT_STRING, nullptr, nullptr, - "use configuration in given policy" }, - - { "service", Parameter::PT_STRING, nullptr, nullptr, - "override automatic service identification" }, - - { "type", Parameter::PT_STRING, nullptr, nullptr, - "select module for binding" }, - - { "name", Parameter::PT_STRING, nullptr, "defaults to type", - "symbol name" }, - - { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } -}; - -static const Parameter binder_params[] = -{ - { "when", Parameter::PT_TABLE, binder_when_params, nullptr, - "match criteria" }, - - { "use", Parameter::PT_TABLE, binder_use_params, nullptr, - "target configuration" }, - - { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } -}; - -class BinderModule : public Module -{ -public: - BinderModule() : Module("binder", binder_params) { work = nullptr; }; - bool set(const char*, Value&, SnortConfig*); - bool begin(const char*, int, SnortConfig*); - bool end(const char*, int, SnortConfig*); - -private: - Binding* work; -}; - -bool BinderModule::set(const char* fqn, Value& v, SnortConfig*) -{ - // both - if ( !strcmp(fqn, "binder.when.policy_id") ) - work->when_id = v.get_string(); - - else if ( !strcmp(fqn, "binder.use.policy_id") ) - work->use_id = v.get_string(); - - else if ( !strcmp(fqn, "binder.when.service") ) - work->when_svc = v.get_string(); - - else if ( !strcmp(fqn, "binder.use.service") ) - work->use_svc = v.get_string(); - - // when - else if ( v.is("nets") ) - work->nets = v.get_string(); - - else if ( v.is("proto") ) - work->proto = (BindProto)v.get_long(); - - else if ( v.is("ports") ) - v.get_bits(work->ports); - - else if ( v.is("role") ) - work->role = (BindRole)v.get_long(); - - else if ( v.is("vlans") ) - v.get_bits(work->vlans); - - // use - else if ( v.is("action") ) - work->action = (BindAction)v.get_long(); - - else if ( v.is("file") ) - work->file = v.get_string(); - - else if ( v.is("name") ) - work->name = v.get_string(); - - else if ( v.is("type") ) - work->type = v.get_string(); - - else - return false; - - return true; -} - -bool BinderModule::begin(const char* fqn, int idx, SnortConfig*) -{ - if ( idx && !strcmp(fqn, "binder") ) - work = new Binding; - - return true; -} - -bool BinderModule::end(const char* fqn, int idx, SnortConfig*) -{ - if ( idx && !strcmp(fqn, "binder") ) - { - Binder::add(work); - work = nullptr; - } - return true; -} - //------------------------------------------------------------------------- // hosts module //------------------------------------------------------------------------- @@ -2008,8 +1862,5 @@ void module_init() // these modules replace config and hosts.xml ModuleManager::add_module(new AttributeTableModule); ModuleManager::add_module(new HostsModule); - - // and this one ties it all together - ModuleManager::add_module(new BinderModule); } diff --git a/src/main/snort.cc b/src/main/snort.cc index 696ccb67e..9f2705d6c 100644 --- a/src/main/snort.cc +++ b/src/main/snort.cc @@ -99,7 +99,6 @@ using namespace std; #include "file_api/file_service.h" #include "flow/flow_control.h" #include "main/analyzer.h" -#include "main/binder.h" #include "log/sf_textlog.h" #include "log/log_text.h" #include "time/periodic.h" @@ -390,7 +389,6 @@ static void SnortInit(int argc, char **argv) /* Need to do this after dynamic detection stuff is initialized, too */ IpsManager::verify(); - Binder::init(); if (snort_conf->file_mask != 0) umask(snort_conf->file_mask); diff --git a/src/managers/inspector_manager.cc b/src/managers/inspector_manager.cc index a64577f48..0be293e25 100644 --- a/src/managers/inspector_manager.cc +++ b/src/managers/inspector_manager.cc @@ -26,7 +26,6 @@ #include #include "module_manager.h" -#include "main/binder.h" #include "flow/flow.h" #include "framework/inspector.h" #include "detection/detection_util.h" @@ -141,20 +140,31 @@ struct FrameworkPolicy for ( auto* p : ph_list ) { - if ( p->pp_class.api.ssn ) - continue; - - else if ( p->pp_class.api.type == IT_STREAM ) - session.add(p); + switch ( p->pp_class.api.type ) + { + case IT_STREAM: + if ( !p->pp_class.api.ssn ) + session.add(p); + break; - else if ( p->pp_class.api.type < IT_STREAM ) + case IT_PACKET: + case IT_PROTOCOL: network.add(p); + break; - else if ( p->pp_class.api.type < IT_SERVICE ) + case IT_SESSION: generic.add(p); + break; - else + case IT_SERVICE: service.add(p); + break; + + case IT_BINDER: + case IT_WIZARD: + case IT_MAX: + break; + } } }; }; @@ -210,6 +220,7 @@ void InspectorManager::release_plugins () { if ( !p->init && p->api.term ) p->api.term(); + delete p; } } @@ -223,15 +234,7 @@ void InspectorManager::empty_trash() if ( !p->is_inactive() ) return; -#if 0 - // FIXIT add name to Inspector to enable proper call to dtor - InspectApi* api = (InspectApi*)get_api(PT_INSPECTOR, p->get_name()); - - if ( api ) - api->dtor(p); -#else - delete p; -#endif + free_inspector(p); s_trash.pop_front(); } } @@ -310,6 +313,11 @@ Inspector* InspectorManager::get_inspector(const char* key) return p->handler; } +void InspectorManager::free_inspector(Inspector* p) +{ + p->get_api()->dtor(p); +} + InspectSsnFunc InspectorManager::get_session(const char* key) { const InspectApi* api = get_plugin(key); diff --git a/src/managers/inspector_manager.h b/src/managers/inspector_manager.h index 8be2fd251..9f1ff4939 100644 --- a/src/managers/inspector_manager.h +++ b/src/managers/inspector_manager.h @@ -52,6 +52,7 @@ public: static void instantiate(const InspectApi*, Module*, SnortConfig*); static Inspector* get_inspector(const char* key); + static void free_inspector(Inspector*); static InspectSsnFunc get_session(const char* key); static bool configure(SnortConfig*); diff --git a/src/managers/module_manager.cc b/src/managers/module_manager.cc index 379dbc2f6..28cf98a02 100644 --- a/src/managers/module_manager.cc +++ b/src/managers/module_manager.cc @@ -387,7 +387,7 @@ void close_table(const char* s, int idx) { h->mod->end(s, idx, s_config); - if ( h->api && (key == s) ) + if ( !idx && h->api && (key == s) ) PluginManager::instantiate(h->api, h->mod, s_config); } } diff --git a/src/network_inspectors/Makefile.am b/src/network_inspectors/Makefile.am index 5b52e8000..6df016ab3 100644 --- a/src/network_inspectors/Makefile.am +++ b/src/network_inspectors/Makefile.am @@ -10,12 +10,14 @@ network_inspectors.h # FIXIT LIBADD here causes undefineds #libnetwork_inspectors_a_LIBADD = \ #arp_spoof/libarp_spoof.a \ +#binder/libbinder.a \ #normalize/libnormalize.a \ #perf_monitor/libperf_monitor.a \ #port_scan/libport_scan.a SUBDIRS = \ arp_spoof \ +binder \ normalize \ perf_monitor \ port_scan diff --git a/src/network_inspectors/binder/Makefile.am b/src/network_inspectors/binder/Makefile.am new file mode 100644 index 000000000..ee67ee13c --- /dev/null +++ b/src/network_inspectors/binder/Makefile.am @@ -0,0 +1,20 @@ +AUTOMAKE_OPTIONS=foreign no-dependencies + +file_list = \ +binder.cc binder.h \ +bind_module.cc bind_module.h + +#if STATIC_INSPECTORS +noinst_LIBRARIES = libbinder.a +libbinder_a_SOURCES = $(file_list) +#else +# need to fix undefineds first :( +#shlibdir = $(pkglibdir)/inspectors +#shlib_LTLIBRARIES = libbinder.la +#libbinder_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO +#libbinder_la_LDFLAGS = -export-dynamic -shared +#libbinder_la_SOURCES = $(file_list) +#endif + +AM_CXXFLAGS = @AM_CXXFLAGS@ + diff --git a/src/network_inspectors/binder/bind_module.cc b/src/network_inspectors/binder/bind_module.cc new file mode 100644 index 000000000..8e71243dd --- /dev/null +++ b/src/network_inspectors/binder/bind_module.cc @@ -0,0 +1,177 @@ +/* +** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License Version 2 as +** published by the Free Software Foundation. You may not use, modify or +** distribute this program under any other version of the GNU General +** Public License. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +// bind_module.cc author Russ Combs + +#include "bind_module.h" + +#include +#include + +#include +using namespace std; + +#include "binder.h" + +//------------------------------------------------------------------------- +// binder module +//------------------------------------------------------------------------- + +static const Parameter binder_when_params[] = +{ + { "policy_id", Parameter::PT_STRING, nullptr, nullptr, + "unique ID for selection of this config by external logic" }, + + { "vlans", Parameter::PT_BIT_LIST, "4095", nullptr, + "list of VLAN IDs" }, + + { "nets", Parameter::PT_ADDR_LIST, nullptr, nullptr, + "list of networks" }, + + { "proto", Parameter::PT_ENUM, "any | ip | icmp | tcp | udp", nullptr, + "protocol" }, + + { "ports", Parameter::PT_BIT_LIST, "65535", nullptr, + "list of ports" }, + + { "role", Parameter::PT_ENUM, "client | server | any", "any", + "use the given configuration on one or any end of a session" }, + + { "service", Parameter::PT_STRING, nullptr, nullptr, + "override default configuration" }, + + { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } +}; + +static const Parameter binder_use_params[] = +{ + { "action", Parameter::PT_ENUM, "inspect | allow | block", "inspect", + "what to do with matching traffic" }, + + { "file", Parameter::PT_STRING, nullptr, nullptr, + "use configuration in given file" }, + + { "policy_id", Parameter::PT_STRING, nullptr, nullptr, + "use configuration in given policy" }, + + { "service", Parameter::PT_STRING, nullptr, nullptr, + "override automatic service identification" }, + + { "type", Parameter::PT_STRING, nullptr, nullptr, + "select module for binding" }, + + { "name", Parameter::PT_STRING, nullptr, "defaults to type", + "symbol name" }, + + { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } +}; + +static const Parameter binder_params[] = +{ + { "when", Parameter::PT_TABLE, binder_when_params, nullptr, + "match criteria" }, + + { "use", Parameter::PT_TABLE, binder_use_params, nullptr, + "target configuration" }, + + { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } +}; + +BinderModule::BinderModule() : Module("binder", binder_params) +{ work = nullptr; } + +BinderModule::~BinderModule() +{ + if ( work ) + delete work; +} + +bool BinderModule::set(const char* fqn, Value& v, SnortConfig*) +{ + // both + if ( !strcmp(fqn, "binder.when.policy_id") ) + work->when_id = v.get_string(); + + else if ( !strcmp(fqn, "binder.use.policy_id") ) + work->use_id = v.get_string(); + + else if ( !strcmp(fqn, "binder.when.service") ) + work->when_svc = v.get_string(); + + else if ( !strcmp(fqn, "binder.use.service") ) + work->use_svc = v.get_string(); + + // when + else if ( v.is("nets") ) + work->nets = v.get_string(); + + else if ( v.is("proto") ) + work->proto = (BindProto)v.get_long(); + + else if ( v.is("ports") ) + v.get_bits(work->ports); + + else if ( v.is("role") ) + work->role = (BindRole)v.get_long(); + + else if ( v.is("vlans") ) + v.get_bits(work->vlans); + + // use + else if ( v.is("action") ) + work->action = (BindAction)v.get_long(); + + else if ( v.is("file") ) + work->file = v.get_string(); + + else if ( v.is("name") ) + work->name = v.get_string(); + + else if ( v.is("type") ) + work->type = v.get_string(); + + else + return false; + + return true; +} + +bool BinderModule::begin(const char* fqn, int idx, SnortConfig*) +{ + if ( idx && !strcmp(fqn, "binder") ) + work = new Binding; + + return true; +} + +bool BinderModule::end(const char* fqn, int idx, SnortConfig*) +{ + if ( idx && !strcmp(fqn, "binder") ) + { + bindings.push_back(work); + work = nullptr; + } + return true; +} + +vector BinderModule::get_data() +{ + return bindings; // move semantics +} + diff --git a/src/network_inspectors/binder/bind_module.h b/src/network_inspectors/binder/bind_module.h new file mode 100644 index 000000000..bd4e8ceee --- /dev/null +++ b/src/network_inspectors/binder/bind_module.h @@ -0,0 +1,48 @@ +/* +** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License Version 2 as +** published by the Free Software Foundation. You may not use, modify or +** distribute this program under any other version of the GNU General +** Public License. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +// bind_module.cc author Russ Combs + +#ifndef BIND_MODULE_H +#define BIND_MODULE_H + +#include + +#include "framework/module.h" + +struct Binding; + +class BinderModule : public Module +{ +public: + BinderModule(); + ~BinderModule(); + + bool set(const char*, Value&, SnortConfig*); + bool begin(const char*, int, SnortConfig*); + bool end(const char*, int, SnortConfig*); + + std::vector get_data(); +private: + Binding* work; + std::vector bindings; +}; + +#endif + diff --git a/src/main/binder.cc b/src/network_inspectors/binder/binder.cc similarity index 54% rename from src/main/binder.cc rename to src/network_inspectors/binder/binder.cc index c896609d3..92be6ed74 100644 --- a/src/main/binder.cc +++ b/src/network_inspectors/binder/binder.cc @@ -19,32 +19,41 @@ // binder.cc author Russ Combs #include "binder.h" -using namespace std; #include +using namespace std; + +#include "bind_module.h" #include "flow/flow.h" #include "framework/inspector.h" #include "stream/stream_splitter.h" #include "managers/inspector_manager.h" #include "protocols/packet.h" #include "stream/stream_api.h" +#include "time/profiler.h" +#include "utils/stats.h" +#include "log/messages.h" -static vector bindings; +static const char* mod_name = "binder"; -void Binder::init() -{ -} +#ifdef PERF_PROFILING +static THREAD_LOCAL PreprocStats bindPerfStats; -void Binder::term() +static PreprocStats* bind_get_profile(const char* key) { - for ( auto* p : bindings ) - delete p; -} + if ( !strcmp(key, mod_name) ) + return &bindPerfStats; -void Binder::add(Binding* b) -{ - bindings.push_back(b); + return nullptr; } +#endif + +static THREAD_LOCAL SimpleStats tstats; +static SimpleStats gstats; + +//------------------------------------------------------------------------- +// helpers +//------------------------------------------------------------------------- // FIXIT bind this is a temporary hack. note that both ends must be set // independently and that we must ref count inspectors. @@ -77,10 +86,61 @@ static bool check_proto(const Flow* flow, BindProto bp) return false; } +//------------------------------------------------------------------------- +// class stuff +//------------------------------------------------------------------------- + +class Binder : public Inspector { +public: + Binder(vector); + ~Binder(); + + void show(SnortConfig*) + { LogMessage("Binder\n"); }; + + void eval(Packet*); + + void add(Binding* b) + { bindings.push_back(b); }; + +private: + Inspector* get_clouseau(Flow*, Packet*); + + void init_flow(Flow*); + void init_flow(Flow*, Packet*); + +private: + vector bindings; +}; + +Binder::Binder(vector v) +{ + bindings = v; +} + +Binder::~Binder() +{ + for ( auto* p : bindings ) + delete p; +} + +void Binder::eval(Packet* p) +{ + Flow* flow = p->flow; + + if ( !flow->ssn_client ) + init_flow(p->flow); + + else if ( !flow->clouseau ) + init_flow(p->flow, p); + + ++tstats.total_packets; +} + // FIXIT bind services - this is a temporary hack that just looks at ports, // need to examine all key fields for matching. ultimately need a routing // table, scapegoat tree, magic wand, etc. -static Inspector* get_clouseau(Flow* flow, Packet* p) +Inspector* Binder::get_clouseau(Flow* flow, Packet* p) { Binding* pb; unsigned i, sz = bindings.size(); @@ -97,10 +157,14 @@ static Inspector* get_clouseau(Flow* flow, Packet* p) if ( pb->ports.test(port) ) break; } + Inspector* ins; + if ( i == sz || !pb->type.size() ) - return nullptr; + ins = InspectorManager::get_inspector("wizard"); + + else + ins = InspectorManager::get_inspector(pb->type.c_str()); - Inspector* ins = InspectorManager::get_inspector(pb->type.c_str()); return ins; } @@ -150,3 +214,84 @@ void Binder::init_flow(Flow* flow, Packet* p) flow->set_clouseau(ins); } +//------------------------------------------------------------------------- +// api stuff +//------------------------------------------------------------------------- + +static Module* mod_ctor() +{ return new BinderModule; } + +static void mod_dtor(Module* m) +{ delete m; } + +void bind_init() +{ +#ifdef PERF_PROFILING + RegisterPreprocessorProfile( + mod_name, &bindPerfStats, 0, &totalPerfStats, bind_get_profile); +#endif +} + +static Inspector* bind_ctor(Module* m) +{ + BinderModule* mod = (BinderModule*)m; + vector pb = mod->get_data(); + return new Binder(pb); +} + +static void bind_dtor(Inspector* p) +{ + delete p; +} + +static void bind_sum() +{ + sum_stats(&gstats, &tstats); +} + +static void bind_stats() +{ + show_stats(&gstats, mod_name); +} + +static void bind_reset() +{ + memset(&gstats, 0, sizeof(gstats)); +} + +static const InspectApi bind_api = +{ + { + PT_INSPECTOR, + mod_name, + INSAPI_PLUGIN_V0, + 0, + mod_ctor, + mod_dtor + }, + IT_BINDER, + PROTO_BIT__ALL, + nullptr, // buffers + nullptr, // service + bind_init, + nullptr, // term + bind_ctor, + bind_dtor, + nullptr, // pinit + nullptr, // pterm + nullptr, // ssn + bind_sum, + bind_stats, + bind_reset +}; + +#ifdef BUILDING_SO +SO_PUBLIC const BaseApi* snort_plugins[] = +{ + &bind_api.base, + nullptr +}; +#else +const BaseApi* nin_binder = &bind_api.base; +#endif + diff --git a/src/main/binder.h b/src/network_inspectors/binder/binder.h similarity index 88% rename from src/main/binder.h rename to src/network_inspectors/binder/binder.h index a46bab7e2..d76dc860c 100644 --- a/src/main/binder.h +++ b/src/network_inspectors/binder/binder.h @@ -71,15 +71,5 @@ struct Binding { role = BR_EITHER; action = BA_INSPECT; }; }; -class Binder -{ -public: - static void init(); - static void term(); - static void add(Binding*); - static void init_flow(class Flow*); - static void init_flow(class Flow*, struct Packet*); -}; - #endif diff --git a/src/network_inspectors/network_inspectors.cc b/src/network_inspectors/network_inspectors.cc index 9462ed572..7c1611541 100644 --- a/src/network_inspectors/network_inspectors.cc +++ b/src/network_inspectors/network_inspectors.cc @@ -25,6 +25,7 @@ #endif #include "framework/inspector.h" +extern const BaseApi* nin_binder; extern const BaseApi* nin_normalize; extern const BaseApi* nin_perf_monitor; extern const BaseApi* nin_stream_ip; @@ -40,6 +41,7 @@ extern const BaseApi* nin_port_scan; const BaseApi* network_inspectors[] = { + nin_binder, nin_normalize, nin_perf_monitor, nin_stream_ip, diff --git a/src/service_inspectors/Makefile.am b/src/service_inspectors/Makefile.am index b5ad88cf0..1c1048291 100644 --- a/src/service_inspectors/Makefile.am +++ b/src/service_inspectors/Makefile.am @@ -12,14 +12,17 @@ service_inspectors.h #back_orifice/libback_orifice.a \ #ftp_telnet/libftp_telnet.a \ #http_inspect/libhttp_inspect.a \ +#nhttp_inspect/libnhttp_inspect.a \ #rpc_decode/librpc_decode.a +#wizard/libwizard.a SUBDIRS = \ back_orifice \ ftp_telnet \ http_inspect \ nhttp_inspect \ -rpc_decode +rpc_decode \ +wizard AM_CXXFLAGS = @AM_CXXFLAGS@ diff --git a/src/service_inspectors/service_inspectors.cc b/src/service_inspectors/service_inspectors.cc index 2b67d9891..d9d106da8 100644 --- a/src/service_inspectors/service_inspectors.cc +++ b/src/service_inspectors/service_inspectors.cc @@ -32,9 +32,10 @@ extern const BaseApi* sin_http_server; extern const BaseApi* sin_bo; extern const BaseApi* sin_ftp_client; extern const BaseApi* sin_ftp_server; +extern const BaseApi* sin_nhttp; extern const BaseApi* sin_rpc_decode; extern const BaseApi* sin_telnet; -extern const BaseApi* sin_nhttp; +extern const BaseApi* sin_wizard; #endif const BaseApi* service_inspectors[] = @@ -46,9 +47,10 @@ const BaseApi* service_inspectors[] = sin_bo, sin_ftp_client, sin_ftp_server, + sin_nhttp, sin_rpc_decode, sin_telnet, - sin_nhttp, + sin_wizard, #endif nullptr, }; diff --git a/src/service_inspectors/wizard/Makefile.am b/src/service_inspectors/wizard/Makefile.am new file mode 100644 index 000000000..529ea7f36 --- /dev/null +++ b/src/service_inspectors/wizard/Makefile.am @@ -0,0 +1,20 @@ +AUTOMAKE_OPTIONS=foreign no-dependencies + +file_list = \ +wizard.cc wizard.h \ +wiz_module.cc wiz_module.h + +#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 + +AM_CXXFLAGS = @AM_CXXFLAGS@ + diff --git a/src/service_inspectors/wizard/wiz_module.cc b/src/service_inspectors/wizard/wiz_module.cc new file mode 100644 index 000000000..e4e34ce9b --- /dev/null +++ b/src/service_inspectors/wizard/wiz_module.cc @@ -0,0 +1,69 @@ +/* +** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License Version 2 as +** published by the Free Software Foundation. You may not use, modify or +** distribute this program under any other version of the GNU General +** Public License. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +// wiz_module.cc author Russ Combs + +#include "wiz_module.h" + +#include +#include + +#include +using namespace std; + +#include "wizard.h" + +static const char* s_name = "wizard"; + +//------------------------------------------------------------------------- +// wizard module +//------------------------------------------------------------------------- + +static const Parameter wizard_params[] = +{ + { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } +}; + +WizardModule::WizardModule() : Module(s_name, wizard_params) +{ } + +WizardModule::~WizardModule() +{ } + +bool WizardModule::set(const char*, Value&, SnortConfig*) +{ + //if ( v.is("type") ) + // work->type = v.get_string(); + + //else + // return false; + + return true; +} + +bool WizardModule::begin(const char*, int, SnortConfig*) +{ + return true; +} + +bool WizardModule::end(const char*, int, SnortConfig*) +{ + return true; +} + diff --git a/src/service_inspectors/wizard/wiz_module.h b/src/service_inspectors/wizard/wiz_module.h new file mode 100644 index 000000000..4eb52bd65 --- /dev/null +++ b/src/service_inspectors/wizard/wiz_module.h @@ -0,0 +1,41 @@ +/* +** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License Version 2 as +** published by the Free Software Foundation. You may not use, modify or +** distribute this program under any other version of the GNU General +** Public License. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +// wiz_module.cc author Russ Combs + +#ifndef WIZ_MODULE_H +#define WIZ_MODULE_H + +#include "framework/module.h" + +class WizardModule : public Module +{ +public: + WizardModule(); + ~WizardModule(); + + bool set(const char*, Value&, SnortConfig*); + bool begin(const char*, int, SnortConfig*); + bool end(const char*, int, SnortConfig*); + +private: +}; + +#endif + diff --git a/src/service_inspectors/wizard/wizard.cc b/src/service_inspectors/wizard/wizard.cc new file mode 100644 index 000000000..2ad6708da --- /dev/null +++ b/src/service_inspectors/wizard/wizard.cc @@ -0,0 +1,223 @@ +/* +** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License Version 2 as +** published by the Free Software Foundation. You may not use, modify or +** distribute this program under any other version of the GNU General +** Public License. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +// wizard.cc author Russ Combs + +#include "wizard.h" + +#include +using namespace std; + +#include "wiz_module.h" +#include "flow/flow.h" +#include "framework/inspector.h" +#include "stream/stream_splitter.h" +#include "managers/inspector_manager.h" +#include "protocols/packet.h" +#include "stream/stream_api.h" +#include "stream/stream_splitter.h" +#include "time/profiler.h" +#include "utils/stats.h" +#include "log/messages.h" + +static const char* mod_name = "wizard"; + +#ifdef PERF_PROFILING +static THREAD_LOCAL PreprocStats wizPerfStats; + +static PreprocStats* wiz_get_profile(const char* key) +{ + if ( !strcmp(key, mod_name) ) + return &wizPerfStats; + + return nullptr; +} +#endif + +static THREAD_LOCAL SimpleStats tstats; +static SimpleStats 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. +//------------------------------------------------------------------------- + +class MagicSplitter : public StreamSplitter +{ +public: + MagicSplitter(bool c2s) : StreamSplitter(c2s) { }; + ~MagicSplitter() { }; + + PAF_Status scan(Flow*, const uint8_t* data, uint32_t len, + uint32_t flags, uint32_t* fp); +}; + +PAF_Status MagicSplitter::scan ( + Flow*, const uint8_t* data, uint32_t len, + uint32_t, uint32_t* fp) +{ + // 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). + + // len + 1 means go back to the last flush point + *fp = len + 1; + + // the reset status ensures that all the + // data scanned so far is delivered to the new inspector's + // splitter. + return PAF_RESET; + } + + return PAF_SEARCH; +} + +//------------------------------------------------------------------------- +// class stuff +//------------------------------------------------------------------------- + +class Wizard : public Inspector { +public: + Wizard(); + ~Wizard(); + + void show(SnortConfig*) + { LogMessage("Wizard\n"); }; + + void eval(Packet*); + + StreamSplitter* get_splitter(bool); + +private: + +private: +}; + +Wizard::Wizard() +{ +} + +Wizard::~Wizard() +{ +} + +void Wizard::eval(Packet*) +{ + if ( !IsUDP(p) ) + return; + + // FIXIT do udp scanning here + ++tstats.total_packets; +} + +StreamSplitter* Wizard::get_splitter(bool c2s) +{ + return new MagicSplitter(c2s); +} + +//------------------------------------------------------------------------- +// api stuff +//------------------------------------------------------------------------- + +static Module* mod_ctor() +{ return new WizardModule; } + +static void mod_dtor(Module* m) +{ delete m; } + +void wiz_init() +{ +#ifdef PERF_PROFILING + RegisterPreprocessorProfile( + mod_name, &wizPerfStats, 0, &totalPerfStats, wiz_get_profile); +#endif +} + +static Inspector* wiz_ctor(Module* m) +{ + WizardModule* mod = (WizardModule*)m; + assert(mod); + return new Wizard; +} + +static void wiz_dtor(Inspector* p) +{ + delete p; +} + +static void wiz_sum() +{ + sum_stats(&gstats, &tstats); +} + +static void wiz_stats() +{ + show_stats(&gstats, mod_name); +} + +static void wiz_reset() +{ + memset(&gstats, 0, sizeof(gstats)); +} + +static const InspectApi wiz_api = +{ + { + PT_INSPECTOR, + mod_name, + INSAPI_PLUGIN_V0, + 0, + mod_ctor, + mod_dtor + }, + IT_WIZARD, + PROTO_BIT__TCP | PROTO_BIT__UDP, + nullptr, // buffers + nullptr, // service + wiz_init, + nullptr, // term + wiz_ctor, + wiz_dtor, + nullptr, // pinit + nullptr, // pterm + nullptr, // ssn + wiz_sum, + wiz_stats, + wiz_reset +}; + +#ifdef BUILDING_SO +SO_PUBLIC const BaseApi* snort_plugins[] = +{ + &wiz_api.base, + nullptr +}; +#else +const BaseApi* sin_wizard = &wiz_api.base; +#endif + diff --git a/src/service_inspectors/wizard/wizard.h b/src/service_inspectors/wizard/wizard.h new file mode 100644 index 000000000..b2029d69c --- /dev/null +++ b/src/service_inspectors/wizard/wizard.h @@ -0,0 +1,27 @@ +/* +** Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License Version 2 as +** published by the Free Software Foundation. You may not use, modify or +** distribute this program under any other version of the GNU General +** Public License. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +// wizard.cc author Russ Combs + +#ifndef WIZARD_H +#define WIZARD_H + +#include + +#endif + diff --git a/src/stream/base/stream_base.cc b/src/stream/base/stream_base.cc index b53ab29c5..7cbe3c408 100644 --- a/src/stream/base/stream_base.cc +++ b/src/stream/base/stream_base.cc @@ -141,7 +141,8 @@ StreamBase::StreamBase(const StreamConfig* c) void StreamBase::pinit() { assert(!flow_con); - flow_con = new FlowControl(); + Inspector* pi = InspectorManager::get_inspector("binder"); + flow_con = new FlowControl(pi); InspectSsnFunc f; if ( config->tcp_cfg.max_sessions ) diff --git a/src/stream/stream_splitter.h b/src/stream/stream_splitter.h index ec58c2b9e..76fa73505 100644 --- a/src/stream/stream_splitter.h +++ b/src/stream/stream_splitter.h @@ -33,7 +33,8 @@ class Flow; PAF_START, // internal use only PAF_SEARCH, // searching for next flush point PAF_FLUSH, // flush at given offset - PAF_SKIP // skip ahead to given offset + PAF_SKIP, // skip ahead to given offset + PAF_RESET // rewind to the prior flush point }; //------------------------------------------------------------------------- diff --git a/src/time/profiler.h b/src/time/profiler.h index 2abee3f51..3a2875b7b 100644 --- a/src/time/profiler.h +++ b/src/time/profiler.h @@ -149,12 +149,12 @@ void ShowRuleProfiles(void); void ResetRuleProfiling(void); /* Preprocessor stats info */ -typedef struct _PreprocStats +struct PreprocStats { uint64_t ticks, ticks_start; uint64_t checks; uint64_t exits; -} PreprocStats; +}; typedef struct _ProfileConfig {