add_subdirectory(perf_monitor)
add_subdirectory(port_scan)
add_subdirectory(reputation)
+add_subdirectory(rna)
if(STATIC_INSPECTORS)
set(STATIC_INSPECTOR_OBJS
$<TARGET_OBJECTS:packet_tracer>
$<TARGET_OBJECTS:port_scan>
$<TARGET_OBJECTS:reputation>
+ $<TARGET_OBJECTS:rna>
${STATIC_INSPECTOR_OBJS}
CACHE INTERNAL "STATIC_NETWORK_INSPECTOR_PLUGINS"
)
extern const BaseApi* nin_appid[];
extern const BaseApi* nin_port_scan[];
+extern const BaseApi* nin_rna[];
#ifdef STATIC_INSPECTORS
extern const BaseApi* nin_arp_spoof[];
PluginManager::load_plugins(network_inspectors);
PluginManager::load_plugins(nin_appid);
PluginManager::load_plugins(nin_port_scan);
+ PluginManager::load_plugins(nin_rna);
#ifdef STATIC_INSPECTORS
PluginManager::load_plugins(nin_arp_spoof);
--- /dev/null
+
+set ( RNA_SOURCES
+ rna_inspector.cc
+ rna_inspector.h
+ rna_module.cc
+ rna_module.h
+)
+
+#if (STATIC_INSPECTORS)
+add_library( rna OBJECT
+ ${RNA_SOURCES}
+ )
+#else (STATIC_INSPECTORS)
+# add_dynamic_module(rna inspectors
+# ${RNA_SOURCES}
+# )
+#endif (STATIC_INSPECTORS)
\ No newline at end of file
--- /dev/null
+[ This inspector is still in experimental (work-in-progress) state! ]
+
+The Real-time Network Awareness (RNA) inspector provides visibility into
+a network using Passive Network Discovery (PND). RNA analyzes traffic
+to discover hosts on the network, and detect operating systems, protocols and
+applications running on these hosts. It does not generate or alter traffic on its own.
+
+RNA generates events for the information it discovers by parsing
+TCP/UDP/IP/Link-layer protocols and analyzing data found by other
+inspectors (e.g., monitoring application IDs, client versions, user-agents from stash).
+Operating systems have different signatures which are apparent in different parameters
+in the packets that it sends. These parameters include things like TCP window sizes,
+TCP options, segment sizes, etc. Such fingerprinting information is provided to RNA
+as input so that RNA can analyze traffic.
+
+RNA discoveries will be stored globally in host_tracker objects and to be shared among
+multiple threads. RNA memory and discovery are bounded by the memcap in host_tracker.
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2019 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.
+//--------------------------------------------------------------------------
+
+// rna_config.h author Masud Hasan <mashasan@cisco.com>
+
+#ifndef RNA_CONFIG_H
+#define RNA_CONFIG_H
+
+struct RnaModuleConfig
+{
+ std::string rna_conf_path;
+ std::string rna_util_lib_path;
+ std::string fingerprint_dir;
+ std::string custom_fingerprint_dir;
+};
+
+// Give default values so that RNA can work even if rna_conf_path is not provided
+struct RnaConfig
+{
+ uint32_t update_timeout = 3600;
+ uint16_t max_host_client_apps = 16;
+ uint16_t max_payloads = 100;
+ uint16_t max_host_services = 100;
+ uint16_t max_host_service_info = 16;
+ bool enable_banner_grab = 0;
+};
+
+#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2019 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.
+//--------------------------------------------------------------------------
+
+// rna_inspector.cc author Masud Hasan <mashasan@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "rna_inspector.h"
+
+#include <cassert>
+#include <fstream>
+#include <sstream>
+#include <string>
+
+#include "log/messages.h"
+#include "managers/inspector_manager.h"
+#include "profiler/profiler.h"
+#include "protocols/packet.h"
+
+#ifdef UNIT_TEST
+#include "catch/snort_catch.h"
+#endif
+
+using namespace snort;
+using namespace std;
+
+THREAD_LOCAL SimpleStats rna_stats;
+THREAD_LOCAL ProfileStats rna_perf_stats;
+
+//-------------------------------------------------------------------------
+// class stuff
+//-------------------------------------------------------------------------
+
+RnaInspector::RnaInspector(RnaModule* mod)
+{
+ mod_conf = mod->get_config();
+ if (!load_rna_conf())
+ WarningMessage("RNA: Failed to load configurations from file! Using defaults.\n");
+}
+
+RnaInspector::~RnaInspector()
+{
+ delete mod_conf;
+ delete rna_conf;
+}
+
+void RnaInspector::eval(Packet* p)
+{
+ Profile profile(rna_perf_stats);
+
+ if (p->packet_flags & PKT_REBUILT_STREAM)
+ return;
+
+ ++rna_stats.total_packets;
+}
+
+void RnaInspector::show(SnortConfig*)
+{
+ LogMessage("RNA Configuration\n");
+
+ if (mod_conf)
+ {
+ if (!mod_conf->rna_conf_path.empty())
+ LogMessage(" Config path: %s\n", mod_conf->rna_conf_path.c_str());
+ if (!mod_conf->rna_util_lib_path.empty())
+ LogMessage(" Library path: %s\n", mod_conf->rna_util_lib_path.c_str());
+ if (!mod_conf->fingerprint_dir.empty())
+ LogMessage(" Fingerprint dir: %s\n", mod_conf->fingerprint_dir.c_str());
+ if (!mod_conf->custom_fingerprint_dir.empty())
+ LogMessage(" Custom fingerprint dir: %s\n",
+ mod_conf->custom_fingerprint_dir.c_str());
+ }
+
+ if (rna_conf)
+ {
+ LogMessage(" Update timeout: %u secs\n", rna_conf->update_timeout);
+ LogMessage(" Max host client apps: %u\n", rna_conf->max_host_client_apps);
+ LogMessage(" Max payloads: %u\n", rna_conf->max_payloads);
+ LogMessage(" Max host services: %u\n", rna_conf->max_host_services);
+ LogMessage(" Max host service info: %u\n", rna_conf->max_host_service_info);
+ LogMessage(" Banner grab: %d\n", rna_conf->enable_banner_grab);
+ }
+
+ LogMessage("\n");
+}
+
+void RnaInspector::tinit()
+{
+ // thread local initialization
+}
+
+void RnaInspector::tterm()
+{
+ // thread local cleanup
+}
+
+bool RnaInspector::load_rna_conf()
+{
+ if (rna_conf)
+ delete rna_conf;
+ rna_conf = new RnaConfig; // initialize with defaults
+
+ if (!mod_conf)
+ return false;
+
+ ifstream in_stream(mod_conf->rna_conf_path);
+ if (!in_stream)
+ return false;
+
+ uint32_t line_num = 0;
+
+ while (in_stream)
+ {
+ string line;
+ getline(in_stream, line);
+ line_num++;
+ if (line.empty() or line.front() == '#')
+ continue;
+
+ string config_type;
+ string config_key;
+ string config_value;
+ istringstream line_stream(line);
+
+ line_stream >> config_type >> config_key >> config_value;
+ if (config_type.empty() or config_key.empty() or config_value.empty())
+ {
+ WarningMessage("RNA: Empty configuration items at line %u from %s\n",
+ line_num, mod_conf->rna_conf_path.c_str());
+ continue;
+ }
+
+ if (config_type == "pnd" and config_key == "UpdateTimeout")
+ rna_conf->update_timeout = stoi(config_value);
+ else if (config_type == "config" and config_key == "MaxHostClientApps")
+ rna_conf->max_host_client_apps = stoi(config_value);
+ else if (config_type == "config" and config_key == "MaxPayloads")
+ rna_conf->max_payloads = stoi(config_value);
+ else if (config_type == "config" and config_key == "MaxHostServices")
+ rna_conf->max_host_services = stoi(config_value);
+ else if (config_type == "config" and config_key == "MaxHostServiceInfo")
+ rna_conf->max_host_service_info = stoi(config_value);
+ else if (config_type == "protoid" and config_key == "BannerGrab" and config_value != "0")
+ rna_conf->enable_banner_grab = true;
+ }
+
+ in_stream.close();
+ return true;
+}
+
+//-------------------------------------------------------------------------
+// api stuff
+//-------------------------------------------------------------------------
+
+static Module* rna_mod_ctor()
+{ return new RnaModule; }
+
+static void rna_mod_dtor(Module* m)
+{ delete m; }
+
+static void rna_inspector_pinit()
+{
+ // global initialization
+}
+
+static void rna_inspector_pterm()
+{
+ // global cleanup
+}
+
+static Inspector* rna_inspector_ctor(Module* m)
+{ return new RnaInspector((RnaModule*)m); }
+
+static void rna_inspector_dtor(Inspector* p)
+{ delete p; }
+
+static const InspectApi rna_inspector_api =
+{
+ {
+ PT_INSPECTOR,
+ sizeof(InspectApi),
+ INSAPI_VERSION,
+ 0,
+ API_RESERVED,
+ API_OPTIONS,
+ RNA_NAME,
+ RNA_HELP,
+ rna_mod_ctor,
+ rna_mod_dtor
+ },
+ IT_CONTROL,
+ PROTO_BIT__ANY_IP,
+ nullptr, // buffers
+ nullptr, // service
+ rna_inspector_pinit,
+ rna_inspector_pterm,
+ nullptr, // pre-config tinit
+ nullptr, // pre-config tterm
+ rna_inspector_ctor,
+ rna_inspector_dtor,
+ nullptr, // ssn
+ nullptr // reset
+};
+
+#ifdef BUILDING_SO
+SO_PUBLIC const BaseApi* snort_plugins[] =
+#else
+const BaseApi* nin_rna[] =
+#endif
+{
+ &rna_inspector_api.base,
+ nullptr
+};
+
+#ifdef UNIT_TEST
+TEST_CASE("RNA inspector", "[rna_inspector]")
+{
+ SECTION("inspector show")
+ {
+ RnaModule mod;
+ RnaInspector ins(&mod);
+ ins.show(nullptr);
+ }
+}
+#endif
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2019 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.
+//--------------------------------------------------------------------------
+
+// rna_inspector.h author Masud Hasan <mashasan@cisco.com>
+
+#ifndef RNA_INSPECTOR_H
+#define RNA_INSPECTOR_H
+
+#include "framework/inspector.h"
+
+#include "rna_module.h"
+
+namespace snort
+{
+struct Packet;
+}
+
+class RnaInspector : public snort::Inspector
+{
+public:
+ RnaInspector(RnaModule*);
+ ~RnaInspector() override;
+
+ void eval(snort::Packet*) override;
+ void show(snort::SnortConfig*) override;
+ void tinit() override;
+ void tterm() override;
+
+private:
+ bool load_rna_conf();
+ const RnaModuleConfig* mod_conf = nullptr;
+ RnaConfig* rna_conf = nullptr;
+};
+
+#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2019 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.
+//--------------------------------------------------------------------------
+
+// rna_module.cc author Masud Hasan <mashasan@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "rna_module.h"
+
+#include <cassert>
+
+#include "log/messages.h"
+
+#ifdef UNIT_TEST
+#include "catch/snort_catch.h"
+#endif
+
+using namespace snort;
+
+//-------------------------------------------------------------------------
+// rna params
+//-------------------------------------------------------------------------
+
+static const Parameter rna_params[] =
+{
+ { "rna_conf_path", Parameter::PT_STRING, nullptr, nullptr,
+ "path to RNA configuration" },
+
+ { "rna_util_lib_path", Parameter::PT_STRING, nullptr, nullptr,
+ "path to library for utilities such as fingerprint decoder" },
+
+ { "fingerprint_dir", Parameter::PT_STRING, nullptr, nullptr,
+ "directory to fingerprint patterns" },
+
+ { "custom_fingerprint_dir", Parameter::PT_STRING, nullptr, nullptr,
+ "directory to custom fingerprint patterns" },
+
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+//-------------------------------------------------------------------------
+// rna module
+//-------------------------------------------------------------------------
+
+RnaModule::RnaModule() : Module(RNA_NAME, RNA_HELP, rna_params)
+{ }
+
+RnaModule::~RnaModule()
+{
+ delete mod_conf;
+}
+
+bool RnaModule::begin(const char* fqn, int, SnortConfig*)
+{
+ if (strcmp(fqn, "rna"))
+ return false;
+ else if (!mod_conf)
+ mod_conf = new RnaModuleConfig;
+ return true;
+}
+
+bool RnaModule::set(const char*, Value& v, SnortConfig*)
+{
+ if (v.is("rna_conf_path"))
+ mod_conf->rna_conf_path = std::string(v.get_string());
+ else if (v.is("rna_util_lib_path"))
+ mod_conf->rna_util_lib_path = std::string(v.get_string());
+ else if (v.is("fingerprint_dir"))
+ mod_conf->fingerprint_dir = std::string(v.get_string());
+ else if (v.is("custom_fingerprint_dir"))
+ mod_conf->custom_fingerprint_dir = std::string(v.get_string());
+ else
+ return false;
+
+ return true;
+}
+
+bool RnaModule::end(const char* fqn, int, SnortConfig*)
+{
+ if (mod_conf == nullptr and strcmp(fqn, "rna") == 0)
+ return false;
+
+ return true;
+}
+
+RnaModuleConfig* RnaModule::get_config()
+{
+ RnaModuleConfig* tmp = mod_conf;
+ mod_conf = nullptr;
+ return tmp;
+}
+
+PegCount* RnaModule::get_counts() const
+{ return (PegCount*)&rna_stats; }
+
+const PegInfo* RnaModule::get_pegs() const
+{ return snort::simple_pegs; }
+
+ProfileStats* RnaModule::get_profile() const
+{ return &rna_perf_stats; }
+
+#ifdef UNIT_TEST
+TEST_CASE("RNA module", "[rna_module]")
+{
+ SECTION("module begin, set, end")
+ {
+ RnaModule mod;
+
+ CHECK_FALSE(mod.begin("dummy", 0, nullptr));
+ CHECK(mod.end("rna", 0, nullptr) == false);
+ CHECK(mod.begin("rna", 0, nullptr) == true);
+
+ Value v1("rna.conf");
+ v1.set(Parameter::find(rna_params, "rna_conf_path"));
+ CHECK(mod.set(nullptr, v1, nullptr) == true);
+
+ Value v2("rna_util.so");
+ v2.set(Parameter::find(rna_params, "rna_util_lib_path"));
+ CHECK(mod.set(nullptr, v2, nullptr) == true);
+
+ Value v3("/dir/fingerprints");
+ v3.set(Parameter::find(rna_params, "fingerprint_dir"));
+ CHECK(mod.set(nullptr, v3, nullptr) == true);
+
+ Value v4("/dir/custom_fingerprints");
+ v4.set(Parameter::find(rna_params, "custom_fingerprint_dir"));
+ CHECK(mod.set(nullptr, v4, nullptr) == true);
+
+ Value v5("dummy");
+ CHECK(mod.set(nullptr, v5, nullptr) == false);
+ CHECK(mod.end("rna", 0, nullptr) == true);
+
+ RnaModuleConfig* rc = mod.get_config();
+ CHECK(rc != nullptr);
+ CHECK(rc->rna_conf_path == "rna.conf");
+ CHECK(rc->rna_util_lib_path == "rna_util.so");
+ CHECK(rc->fingerprint_dir == "/dir/fingerprints");
+ CHECK(rc->custom_fingerprint_dir == "/dir/custom_fingerprints");
+
+ delete rc;
+ }
+}
+#endif
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2019 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.
+//--------------------------------------------------------------------------
+
+// rna_module.h author Masud Hasan <mashasan@cisco.com>
+
+#ifndef RNA_MODULE_H
+#define RNA_MODULE_H
+
+#include "framework/module.h"
+
+#include "rna_config.h"
+
+#define RNA_NAME "rna"
+#define RNA_HELP "Real-time network awareness and OS fingerprinting (experimental)"
+
+extern THREAD_LOCAL SimpleStats rna_stats;
+extern THREAD_LOCAL snort::ProfileStats rna_perf_stats;
+
+class RnaModule : public snort::Module
+{
+public:
+ RnaModule();
+ ~RnaModule() override;
+
+ bool begin(const char*, int, snort::SnortConfig*) override;
+ bool set(const char*, snort::Value&, snort::SnortConfig*) override;
+ bool end(const char*, int, snort::SnortConfig*) override;
+ RnaModuleConfig* get_config();
+ PegCount* get_counts() const override;
+ const PegInfo* get_pegs() const override;
+ snort::ProfileStats* get_profile() const override;
+
+ Usage get_usage() const override
+ { return CONTEXT; }
+
+private:
+ RnaModuleConfig* mod_conf = nullptr;
+};
+
+#endif
+
pps_pop.cc
pps_imap.cc
pps_modbus.cc
+ pps_rna.cc
pps_smtp.cc
pps_sfportscan.cc
pps_stream5_ip.cc
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2019 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.
+//--------------------------------------------------------------------------
+// pps_rna.cc author Masud Hasan <mashasan@cisco.com>
+
+#include <sstream>
+
+#include "conversion_state.h"
+#include "helpers/converter.h"
+
+namespace preprocessors
+{
+ namespace
+ {
+ class Rna : public ConversionState
+ {
+ public:
+ Rna(Converter& c) : ConversionState(c) { }
+ bool convert(std::istringstream& data) override;
+ };
+ }
+
+ bool Rna::convert(std::istringstream& data_stream)
+ {
+ bool retval = true;
+
+ table_api.open_table("rna");
+
+ std::string keyword;
+ while (data_stream >> keyword)
+ {
+ bool tmpval = true;
+
+ if (keyword == "rna_conf")
+ tmpval = parse_string_option("rna_conf_path", data_stream);
+ else if (keyword == "memcap")
+ {
+ int ignored_val;
+ data_stream >> ignored_val;
+ }
+ else
+ tmpval = false;
+
+ if (!tmpval)
+ {
+ data_api.failed_conversion(data_stream, keyword);
+ retval = false;
+ }
+ }
+
+ return retval;
+ }
+
+ /**************************
+ ******* A P I ***********
+ **************************/
+
+ static ConversionState* ctor(Converter& c)
+ {
+ return new Rna(c);
+ }
+
+ static const ConvertMap rna_api =
+ {
+ "rna",
+ ctor,
+ };
+
+ const ConvertMap* rna_map = &rna_api;
+} // namespace preprocessors
extern const ConvertMap* normalizer_tcp_map;
extern const ConvertMap* perfmonitor_map;
extern const ConvertMap* reputation_map;
+extern const ConvertMap* rna_map;
extern const ConvertMap* rpc_decode_map;
extern const ConvertMap* sip_map;
extern const ConvertMap* ssh_map;
perfmonitor_map,
pop_map,
reputation_map,
+ rna_map,
rpc_decode_map,
sdf_map,
sfportscan_map,