src/sfip/Makefile \
src/sfrt/Makefile \
src/target_based/Makefile \
+src/target_based/test/Makefile \
src/catch/Makefile \
src/time/Makefile \
src/ppm/Makefile \
#include <string.h>
#include <string>
+#include <memory>
using namespace std;
#include "framework/module.h"
#include "stream/stream_api.h"
#include "utils/stats.h"
#include "target_based/snort_protocols.h"
+#include "target_based/host_tracker.h"
//-------------------------------------------------------------------------
// detection module
//-------------------------------------------------------------------------
+/* *INDENT-OFF* */ // Uncrustify handles this section incorrectly.
static const Parameter detection_params[] =
{
{ "asn1", Parameter::PT_INT, "1:", "256",
{ nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
};
+/* *INDENT-ON* */
#define detection_help \
"configure general IPS rule processing parameters"
"file type version" },
{ "magic", Parameter::PT_LIST, file_magic_params, nullptr,
- "list of file magic rules" },
+ "list of file magic rules" },
{ nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
};
"print this many octets" },
{ "file_rules", Parameter::PT_LIST, file_rule_params, nullptr,
- "list of file magic rules" },
+ "list of file magic rules" },
{ "file_policy", Parameter::PT_LIST, file_policy_rule_params, nullptr,
- "list of file rules" },
+ "list of file rules" },
{ "trace_type", Parameter::PT_BOOL, nullptr, "false",
"enable runtime dump of type info" },
bool set(const char*, Value&, SnortConfig*) override;
bool begin(const char*, int, SnortConfig*) override;
bool end(const char*, int, SnortConfig*) override;
+
private:
FileMagicRule rule;
FileMagicData magic;
{
rule.clear();
}
-
else if ( !strcmp(fqn, "file_id.file_rules.magic") )
{
magic.clear();
}
-
else if ( !strcmp(fqn, "file_id.file_policy") )
{
file_rule.clear();
}
-
return true;
}
{
fc.process_file_rule(rule);
}
-
else if ( !strcmp(fqn, "file_id.file_rules.magic") )
{
fc.process_file_magic(magic);
rule.file_magics.push_back(magic);
}
-
else if ( !strcmp(fqn, "file_id.file_policy") )
{
fc.process_file_policy_rule(file_rule);
return true;
}
+
//-------------------------------------------------------------------------
// suppress module
//-------------------------------------------------------------------------
return true;
}
+//-------------------------------------------------------------------------
+// HostTracker module
+//-------------------------------------------------------------------------
+
+// FIXIT-M - Temporarily create new HostTracker module to test new
+// HostTracker object. May eventually replace old Hosts
+// module with this one.
+
+class HostTrackerModule : public Module
+{
+public:
+ HostTrackerModule() : Module("host_tracker", hosts_help, hosts_params, true)
+ {
+ host = nullptr;
+ }
+
+ ~HostTrackerModule()
+ {
+ // FIXIT-H: Change this back to an assert once we hand off the
+ // host to a cache.
+ if (host)
+ delete host;
+ }
+
+ bool set(const char*, Value&, SnortConfig*) override;
+ bool begin(const char*, int, SnortConfig*) override;
+ bool end(const char*, int, SnortConfig*) override;
+
+private:
+ HostApplicationEntry app;
+ HostTracker* host;
+};
+
+bool HostTrackerModule::set(const char*, Value& v, SnortConfig*)
+{
+ if ( host and v.is("ip") )
+ {
+ sfip_t addr;
+ v.get_addr(addr);
+ host->set_ip_addr(addr);
+ }
+ else if ( host and v.is("frag_policy") )
+ host->set_frag_policy(v.get_long() + 1);
+
+ else if ( host and v.is("tcp_policy") )
+ host->set_stream_policy(v.get_long() + 1);
+
+ else if ( v.is("name") )
+ app.protocol = AddProtocolReference(v.get_string());
+
+ else if ( v.is("proto") )
+ app.ipproto = AddProtocolReference(v.get_string());
+
+ else if ( v.is("port") )
+ app.port = v.get_long();
+
+ else
+ return false;
+
+ return true;
+}
+
+bool HostTrackerModule::begin(const char* fqn, int idx, SnortConfig*)
+{
+ if ( idx && !strcmp(fqn, "host_tracker") )
+ host = new HostTracker;
+
+ return true;
+}
+
+bool HostTrackerModule::end(const char* fqn, int idx, SnortConfig*)
+{
+ if ( idx && !strcmp(fqn, "host_tracker.services") )
+ {
+ host->add_service(app);
+ memset(&app, 0, sizeof(app));
+ }
+ else if ( idx && !strcmp(fqn, "host_tracker") )
+ {
+ // FIXIT-H: Next step will be to add the HostTracker object to
+ // a cache. For now just delete in the destructor.
+ //SFAT_AddHost(host);
+ //host = nullptr;
+ }
+
+ return true;
+}
+
#if 0
//-------------------------------------------------------------------------
// xxx module - used as copy/paste template
// these modules replace config and hosts.xml
ModuleManager::add_module(new AttributeTableModule);
ModuleManager::add_module(new HostsModule);
+ ModuleManager::add_module(new HostTrackerModule);
}
sftarget_data.h
snort_protocols.cc
snort_protocols.h
+ host_tracker.h
)
sftarget_hostentry.cc \
sftarget_hostentry.h \
sftarget_data.h \
+host_tracker.h \
snort_protocols.cc \
snort_protocols.h
+if BUILD_UNIT_TESTS
+SUBDIRS = test
+endif
+
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015 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.
+//--------------------------------------------------------------------------
+
+// host_tracker.h author Steve Chew <stechew@cisco.com>
+
+#ifndef HOST_TRACKER_H
+#define HOST_TRACKER_H
+
+// The HostTracker class holds information known about a host (may be from
+// configuration or dynamic discovery). It provides a thread-safe API to
+// set/get the host data.
+
+#include <mutex>
+#include <memory>
+#include <cstring>
+#include <list>
+#include <algorithm>
+
+#include "sfip/sfip_t.h"
+
+// FIXIT-H -- For now this emulates the Snort++ attribute table. Need
+// to add in sfrnaincludes/host_tracker.h data eventually.
+
+typedef uint16_t Port;
+typedef uint16_t Protocol;
+typedef uint8_t Policy;
+
+struct HostApplicationEntry
+{
+ Port port = 0;
+ Protocol ipproto = 0;
+ Protocol protocol = 0;
+
+ static const Protocol UNKNOWN_PROTOCOL = 0;
+
+ HostApplicationEntry()
+ {
+ }
+
+ HostApplicationEntry(Protocol ipproto_param, Port port_param, Protocol protocol_param) :
+ port(port_param),
+ ipproto(ipproto_param),
+ protocol(protocol_param)
+ {
+ }
+
+ inline bool operator==(const HostApplicationEntry& rhs) const
+ {
+ return ipproto == rhs.ipproto and port == rhs.port;
+ }
+};
+
+class HostTracker
+{
+private:
+ std::mutex host_tracker_lock; // Ensure that updates to a
+ // shared object are safe.
+
+ // FIXIT-H - Do we need to use a host_id instead of sfip_t as in sfrna?
+ sfip_t ip_addr;
+
+ // Policies to apply to this host.
+ Policy stream_policy = 0;
+ Policy frag_policy = 0;
+
+ std::list<HostApplicationEntry> services;
+ std::list<HostApplicationEntry> clients;
+
+public:
+ HostTracker(void)
+ {
+ memset(&ip_addr, 0, sizeof(ip_addr));
+ }
+
+ sfip_t get_ip_addr(void)
+ {
+ std::lock_guard<std::mutex> lck(host_tracker_lock);
+ return ip_addr;
+ }
+
+ void set_ip_addr(const sfip_t& new_ip_addr)
+ {
+ std::lock_guard<std::mutex> lck(host_tracker_lock);
+ std::memcpy(&ip_addr, &new_ip_addr, sizeof(ip_addr));
+ }
+
+ Policy get_stream_policy(void)
+ {
+ std::lock_guard<std::mutex> lck(host_tracker_lock);
+ return stream_policy;
+ }
+
+ void set_stream_policy(const Policy& policy)
+ {
+ std::lock_guard<std::mutex> lck(host_tracker_lock);
+ stream_policy = policy;
+ }
+
+ Policy get_frag_policy(void)
+ {
+ std::lock_guard<std::mutex> lck(host_tracker_lock);
+ return frag_policy;
+ }
+
+ void set_frag_policy(const Policy& policy)
+ {
+ std::lock_guard<std::mutex> lck(host_tracker_lock);
+ frag_policy = policy;
+ }
+
+ // Add host service data only if it doesn't already exist. Returns
+ // false if entry exists already, and true if entry was added.
+ bool add_service(const HostApplicationEntry& app_entry)
+ {
+ std::lock_guard<std::mutex> lck(host_tracker_lock);
+
+ auto iter = std::find(services.begin(), services.end(), app_entry);
+ if (iter != services.end())
+ return false; // Already exists.
+
+ services.push_front(app_entry);
+ return true;
+ }
+
+ // Add host service data if it doesn't already exist. If it does exist
+ // replace the previous entry with the new entry.
+ void add_or_replace_service(const HostApplicationEntry& app_entry)
+ {
+ std::lock_guard<std::mutex> lck(host_tracker_lock);
+
+ auto iter = std::find(services.begin(), services.end(), app_entry);
+ if (iter != services.end())
+ services.erase(iter);
+
+ services.push_front(app_entry);
+ }
+
+ // Returns true and fills in copy of HostApplicationEntry when found.
+ // Returns false when not found.
+ bool find_service(Protocol ipproto, Port port, HostApplicationEntry& app_entry)
+ {
+ HostApplicationEntry tmp_entry(ipproto, port, HostApplicationEntry::UNKNOWN_PROTOCOL);
+
+ std::lock_guard<std::mutex> lck(host_tracker_lock);
+
+ auto iter = std::find(services.begin(), services.end(), tmp_entry);
+ if (iter != services.end())
+ {
+ app_entry = *iter;
+ return true;
+ }
+
+ return false;
+ }
+
+ // Removes HostApplicationEntry object associated with ipproto and port.
+ // Returns true if entry existed. False otherwise.
+ bool remove_service(Protocol ipproto, Port port)
+ {
+ HostApplicationEntry tmp_entry(ipproto, port, HostApplicationEntry::UNKNOWN_PROTOCOL);
+
+ std::lock_guard<std::mutex> lck(host_tracker_lock);
+
+ auto iter = std::find(services.begin(), services.end(), tmp_entry);
+ if (iter != services.end())
+ {
+ services.erase(iter);
+ return true; // Assumes only one matching entry.
+ }
+
+ return false;
+ }
+};
+
+#endif
+
--- /dev/null
+
+AM_DEFAULT_SOURCE_EXT = .cc
+
+check_PROGRAMS = \
+host_tracker_test
+
+TESTS = $(check_PROGRAMS)
+
+host_tracker_test_CPPFLAGS = @AM_CPPFLAGS@ @CPPUTEST_CPPFLAGS@
+
+host_tracker_test_LDADD = \
+@CPPUTEST_LDFLAGS@
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015 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.
+//--------------------------------------------------------------------------
+
+// host_tracker_test.cc author Steve Chew <stechew@cisco.com>
+// unit tests for HostTracker class
+
+#include "target_based/host_tracker.h"
+
+#include <CppUTest/CommandLineTestRunner.h>
+#include <CppUTest/TestHarness.h>
+
+TEST_GROUP(host_tracker)
+{
+};
+
+// Test HostTracker ipaddr get/set functions.
+TEST(host_tracker, ipaddr_test)
+{
+ HostTracker ht;
+ sfip_t zeroed_sfip;
+ sfip_t expected_ip_addr = { 0xde,0xad,0xbe,0xef,0xab,0xcd,0xef,0x01,0x23, };
+ sfip_t actual_ip_addr;
+
+ // Test IP prior to set.
+ memset(&zeroed_sfip, 0, sizeof(zeroed_sfip));
+ actual_ip_addr = ht.get_ip_addr();
+ CHECK(0 == memcmp(&zeroed_sfip, &actual_ip_addr, sizeof(zeroed_sfip)));
+
+ ht.set_ip_addr(expected_ip_addr);
+ actual_ip_addr = ht.get_ip_addr();
+ CHECK(0 == memcmp(&expected_ip_addr, &actual_ip_addr, sizeof(expected_ip_addr)));
+}
+
+// Test HostTracker policy get/set functions.
+TEST(host_tracker, policy_test)
+{
+ HostTracker ht;
+ Policy expected_policy = 23;
+ Policy actual_policy;
+
+ actual_policy = ht.get_stream_policy();
+ CHECK(0 == actual_policy);
+
+ actual_policy = ht.get_frag_policy();
+ CHECK(0 == actual_policy);
+
+ ht.set_stream_policy(expected_policy);
+ actual_policy = ht.get_stream_policy();
+ CHECK(expected_policy == actual_policy);
+
+ expected_policy = 77;
+ ht.set_frag_policy(expected_policy);
+ actual_policy = ht.get_frag_policy();
+ CHECK(expected_policy == actual_policy);
+}
+
+// Test HostTracker add and find service functions.
+TEST(host_tracker, add_find_service_test)
+{
+ bool ret;
+ HostTracker ht;
+ HostApplicationEntry actual_entry;
+ HostApplicationEntry app_entry1(6, 2112, 3);
+ HostApplicationEntry app_entry2(17, 7777, 10);
+
+ // Try a find on an empty list.
+ ret = ht.find_service(3,1000, actual_entry);
+ CHECK(false == ret);
+
+ // Test add and find.
+ ret = ht.add_service(app_entry1);
+ CHECK(true == ret);
+
+ ret = ht.find_service(6, 2112, actual_entry);
+ CHECK(true == ret);
+ CHECK(actual_entry.port == 2112);
+ CHECK(actual_entry.ipproto == 6);
+ CHECK(actual_entry.protocol == 3);
+
+ ht.add_service(app_entry2);
+ ret = ht.find_service(6, 2112, actual_entry);
+ CHECK(true == ret);
+ CHECK(actual_entry.port == 2112);
+ CHECK(actual_entry.ipproto == 6);
+ CHECK(actual_entry.protocol == 3);
+
+ ret = ht.find_service(17, 7777, actual_entry);
+ CHECK(true == ret);
+ CHECK(actual_entry.port == 7777);
+ CHECK(actual_entry.ipproto == 17);
+ CHECK(actual_entry.protocol == 10);
+
+ // Try adding an entry that exists already.
+ ret = ht.add_service(app_entry1);
+ CHECK(false == ret);
+
+ // Try a find on a port that isn't in the list.
+ ret = ht.find_service(6, 100, actual_entry);
+ CHECK(false == ret);
+
+ // Try a find on an ipproto that isn't in the list.
+ ret = ht.find_service(17, 2112, actual_entry);
+ CHECK(false == ret);
+
+ // Try to remove an entry that's not in the list.
+ ret = ht.remove_service(6,100);
+ CHECK(false == ret);
+
+ ret = ht.remove_service(17,2112);
+ CHECK(false == ret);
+
+ // Actually remove an entry.
+ ret = ht.remove_service(6,2112);
+ CHECK(true == ret);
+}
+
+int main(int argc, char** argv)
+{
+ return CommandLineTestRunner::RunAllTests(argc, argv);
+}
+