]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #1593 in SNORT/snort3 from ~DERAMADA/snort3:appid_stash_store...
authorMike Stepanek (mstepane) <mstepane@cisco.com>
Mon, 1 Jul 2019 14:15:54 +0000 (10:15 -0400)
committerMike Stepanek (mstepane) <mstepane@cisco.com>
Mon, 1 Jul 2019 14:15:54 +0000 (10:15 -0400)
Squashed commit of the following:

commit 51382ddd1e26171b1a1ca0973ff950d1e073aa5c
Author: deramada <deramada@cisco.com>
Date:   Mon Apr 29 15:49:05 2019 -0400

    appid: use stash to store flow attributes

19 files changed:
src/flow/CMakeLists.txt
src/flow/flow.cc
src/flow/flow.h
src/flow/flow_stash.cc
src/flow/flow_stash.h
src/flow/flow_stash_keys.h [new file with mode: 0644]
src/flow/stash_item.h
src/flow/test/flow_stash_test.cc
src/network_inspectors/appid/appid_discovery.cc
src/network_inspectors/appid/appid_http_event_handler.cc
src/network_inspectors/appid/appid_http_session.cc
src/network_inspectors/appid/appid_http_session.h
src/network_inspectors/appid/appid_session.cc
src/network_inspectors/appid/appid_session.h
src/network_inspectors/appid/ips_appid_option.cc
src/network_inspectors/appid/test/appid_discovery_test.cc
src/network_inspectors/appid/test/appid_http_event_test.cc
src/network_inspectors/appid/test/appid_mock_flow.h
src/network_inspectors/appid/test/appid_mock_session.h

index f84e141317e436cee60e99b0f301a4c0c5b93879..09dcbf5bbe34e5a84a4c023a1add3813d04e9642 100644 (file)
@@ -4,6 +4,7 @@ set (FLOW_INCLUDES
     flow_key.h
     flow_stash.h
     ha.h
+    flow_stash_keys.h
     stash_item.h
 )
 
index db315555e0d802ea861077967fd35b6caeedc4f1..f7cf144ee00667655c4feead50bf49a491a7183a 100644 (file)
@@ -215,8 +215,13 @@ void Flow::restart(bool dump_flow_data)
     DetectionEngine::onload(this);
 
     if ( dump_flow_data )
+    {
         free_flow_data();
 
+        if ( stash )
+            stash->reset();
+    }
+
     clean();
 
     ssn_state.ignore_direction = 0;
index e7e3018952d802ff4cce5a54042e707b975b41e8..813c32b43241a3f30dd093c23b738f46ade2cccb 100644 (file)
@@ -191,32 +191,41 @@ public:
     void set_mpls_layer_per_dir(Packet*);
     Layer get_mpls_layer_per_dir(bool);
     void set_service(Packet* pkt, const char* new_service);
-    bool get_attr(const std::string& key, int32_t& val);
-    bool get_attr(const std::string& key, std::string& val);
-    void set_attr(const std::string& key, const int32_t& val);
-    void set_attr(const std::string& key, const std::string& val);
+
     // Use this API when the publisher of the attribute allocated memory for it and can give up its
     // ownership after the call.
-    void set_attr(const std::string& key, std::string* val)
+    void set_attr(const int& key, std::string* val)
     {
         assert(stash);
         stash->store(key, val);
     }
 
+    bool get_attr(const int& key, std::string*& val)
+    {
+        assert(stash);
+        return stash->get(key, val);
+    }
+
     template<typename T>
-    bool get_attr(const std::string& key, T& val)
+    bool get_attr(const int& key, T& val)
     {
         assert(stash);
         return stash->get(key, val);
     }
 
     template<typename T>
-    void set_attr(const std::string& key, const T& val)
+    void set_attr(const int& key, const T& val)
     {
         assert(stash);
         stash->store(key, val);
     }
 
+    void remove_attr(const FlowStashKey& key)
+    {
+        assert(stash);
+        stash->remove(key);
+    }
+
     uint32_t update_session_flags(uint32_t flags)
     { return ssn_state.session_flags = flags; }
 
index 13a2f31563834f445f458e5113a24e119d506a7d..c1c11c69989e408babac570c1b52e5bf41970386 100644 (file)
@@ -38,113 +38,131 @@ FlowStash::~FlowStash()
 
 void FlowStash::reset()
 {
-    for(map<string, StashItem*>::iterator it = container.begin(); it != container.end(); ++it)
+    for (auto& it : container)
     {
-        delete it->second;
+        if (it)
+        {
+            delete it;
+            it = nullptr;
+        }
     }
-    container.clear();
 }
 
-bool FlowStash::get(const string& key, int32_t& val)
+void FlowStash::remove(const FlowStashKey& key)
+{
+    auto& item = container[key];
+
+    if (item)
+    {
+        delete item;
+        item = nullptr;
+    }
+}
+
+bool FlowStash::get(const int& key, int32_t& val)
 {
     return get(key, val, STASH_ITEM_TYPE_INT32);
 }
 
-bool FlowStash::get(const string& key, uint32_t& val)
+bool FlowStash::get(const int& key, uint32_t& val)
 {
     return get(key, val, STASH_ITEM_TYPE_UINT32);
 }
 
-bool FlowStash::get(const string& key, string& val)
+bool FlowStash::get(const int& key, string& val)
 {
     return get(key, val, STASH_ITEM_TYPE_STRING);
 }
 
-bool FlowStash::get(const std::string& key, StashGenericObject* &val)
+bool FlowStash::get(const int& key, string*& val)
+{
+    auto& it = container[key];
+
+    if (it)
+    {
+        assert(it->get_type() == STASH_ITEM_TYPE_STRING);
+        it->get_val(val);
+        return true;
+    }
+    return false;
+}
+
+bool FlowStash::get(const int& key, StashGenericObject* &val)
 {
     return get(key, val, STASH_ITEM_TYPE_GENERIC_OBJECT);
 }
 
-void FlowStash::store(const string& key, int32_t val)
+void FlowStash::store(const int& key, int32_t val)
 {
     store(key, val, STASH_ITEM_TYPE_INT32);
 }
 
-void FlowStash::store(const string& key, uint32_t val)
+void FlowStash::store(const int& key, uint32_t val)
 {
     store(key, val, STASH_ITEM_TYPE_UINT32);
 }
 
-void FlowStash::store(const string& key, const string& val)
+void FlowStash::store(const int& key, const string& val)
 {
     store(key, val, STASH_ITEM_TYPE_STRING);
 }
 
-void FlowStash::store(const std::string& key, StashGenericObject* val)
+void FlowStash::store(const int& key, StashGenericObject* val)
 {
     store(key, val, STASH_ITEM_TYPE_GENERIC_OBJECT);
 }
 
-void FlowStash::store(const string& key, StashGenericObject* &val, StashItemType type)
+void FlowStash::store(const int& key, StashGenericObject* &val, StashItemType type)
 {
 #ifdef NDEBUG
     UNUSED(type);
 #endif
-    auto item = new StashItem(val);
-    auto it_and_status = container.emplace(make_pair(key, item));
+    auto& it = container[key];
+    if (it)
+        delete it;
 
-    if (!it_and_status.second)
-    {
-        StashGenericObject* stored_object;
-        assert(it_and_status.first->second->get_type() == type);
-        it_and_status.first->second->get_val(stored_object);
-        assert(stored_object->get_object_type() == val->get_object_type());
-        delete it_and_status.first->second;
-        it_and_status.first->second = item;
-    }
+    it = new StashItem(val);
+    assert(it->get_type() == type);
 
-    StashEvent e(item);
-    DataBus::publish(key.c_str(), e);
+    StashEvent e(it);
+    DataBus::publish(get_key_name(key), e);
 }
 
-void FlowStash::store(const std::string& key, std::string* val)
+void FlowStash::store(const int& key, std::string* val)
 {
     store(key, val, STASH_ITEM_TYPE_STRING);
 }
 
 template<typename T>
-bool FlowStash::get(const string& key, T& val, StashItemType type)
+bool FlowStash::get(const int& key, T& val, StashItemType type)
 {
 #ifdef NDEBUG
     UNUSED(type);
 #endif
-    auto it = container.find(key);
+    auto& it = container[key];
 
-    if (it != container.end())
+    if (it)
     {
-        assert(it->second->get_type() == type);
-        it->second->get_val(val);
+        assert(it->get_type() == type);
+        it->get_val(val);
         return true;
     }
     return false;
 }
 
 template<typename T>
-void FlowStash::store(const string& key, T& val, StashItemType type)
+void FlowStash::store(const int& key, T& val, StashItemType type)
 {
 #ifdef NDEBUG
     UNUSED(type);
 #endif
-    auto item = new StashItem(val);
-    auto it_and_status = container.emplace(make_pair(key, item));
+    auto& it = container[key];
+    if (it)
+        delete it;
 
-    if (!it_and_status.second)
-    {
-        assert(it_and_status.first->second->get_type() == type);
-        delete it_and_status.first->second;
-        it_and_status.first->second = item;
-    }
+    it = new StashItem(val);
+    assert(it->get_type() == type);
 
-    StashEvent e(item);
-    DataBus::publish(key.c_str(), e);
+    StashEvent e(it);
+    DataBus::publish(get_key_name(key), e);
 }
index a422555e31d11413916887b204cb0be8790b3d54..8794f12406c6bbc89a61995310a382622d42c8ef 100644 (file)
 #ifndef FLOW_STASH_H
 #define FLOW_STASH_H
 
-#include <map>
 #include <string>
+#include <vector>
 
 #include "main/snort_types.h"
 
+#include "flow_stash_keys.h"
 #include "stash_item.h"
 
 namespace snort
@@ -34,26 +35,29 @@ namespace snort
 class SO_PUBLIC FlowStash
 {
 public:
+    FlowStash() : container(STASH_MAX_SIZE, nullptr) { }
     ~FlowStash();
     void reset();
-    bool get(const std::string& key, int32_t& val);
-    bool get(const std::string& key, uint32_t& val);
-    bool get(const std::string& key, std::string& val);
-    bool get(const std::string& key, StashGenericObject* &val);
-    void store(const std::string& key, int32_t val);
-    void store(const std::string& key, uint32_t val);
-    void store(const std::string& key, const std::string& val);
-    void store(const std::string& key, std::string* val);
-    void store(const std::string& key, StashGenericObject* val);
+    bool get(const int& key, int32_t& val);
+    bool get(const int& key, uint32_t& val);
+    bool get(const int& key, std::string& val);
+    bool get(const int& key, std::string*& val);
+    bool get(const int& key, StashGenericObject* &val);
+    void store(const int& key, int32_t val);
+    void store(const int& key, uint32_t val);
+    void store(const int& key, const std::string& val);
+    void store(const int& key, std::string* val);
+    void store(const int& key, StashGenericObject* val);
+    void remove(const FlowStashKey& key);
 
 private:
-    std::map<std::string, StashItem*> container;
+    std::vector<StashItem*> container;
 
     template<typename T>
-    bool get(const std::string& key, T& val, StashItemType type);
+    bool get(const int& key, T& val, StashItemType type);
     template<typename T>
-    void store(const std::string& key, T& val, StashItemType type);
-    void store(const std::string& key, StashGenericObject* &val, StashItemType type);
+    void store(const int& key, T& val, StashItemType type);
+    void store(const int& key, StashGenericObject* &val, StashItemType type);
 };
 
 }
diff --git a/src/flow/flow_stash_keys.h b/src/flow/flow_stash_keys.h
new file mode 100644 (file)
index 0000000..39057eb
--- /dev/null
@@ -0,0 +1,69 @@
+//--------------------------------------------------------------------------
+// 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.
+//--------------------------------------------------------------------------
+
+// flow_stash_keys.h author Deepak Ramadass <deramada@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef FLOW_STASH_KEYS_H
+#define FLOW_STASH_KEYS_H
+
+enum FlowStashKey
+{
+    STASH_APPID_SERVICE = 0,
+    STASH_APPID_CLIENT,
+    STASH_APPID_PAYLOAD,
+    STASH_APPID_MISC,
+    STASH_APPID_REFERRED,
+    STASH_HOST,
+    STASH_TLS_HOST,
+    STASH_URL,
+    STASH_USER_AGENT,
+    STASH_RESPONSE_CODE,
+    STASH_REFERER,
+    STASH_XFF,
+    STASH_CLIENT_VERSION,
+
+    STASH_MAX_SIZE
+};
+
+static const char* FlowStashKeyNames[] =
+{
+    "appid-service",
+    "appid-client",
+    "appid-payload",
+    "appid-misc",
+    "appid-referred",
+    "host",
+    "tls-host",
+    "url",
+    "user-agent",
+    "response-code",
+    "referer",
+    "xff",
+    "client-version"
+};
+
+inline const char * get_key_name( int key )
+{
+    return FlowStashKeyNames[key];
+}
+#endif
index 63daf304cefaeafd62feb43a83e6c5f7a1fba7ca..cbbbe7e3578cb0128786a59de886df8aa1ad1d46 100644 (file)
@@ -101,6 +101,7 @@ public:
             break;
         case STASH_ITEM_TYPE_GENERIC_OBJECT:
             delete val.generic_obj_val;
+            break;
         default:
             break;
         }
@@ -118,6 +119,9 @@ public:
     void get_val(std::string& str_val) const
     { str_val = *(val.str_val); }
 
+    void get_val(std::string*& str_val) const
+    { str_val = val.str_val; }
+
     void get_val(StashGenericObject* &obj_val) const
     { obj_val = val.generic_obj_val; }
 
index ffd1200e41c9fef13c67c01ea3070a0a3e1163c2..311bb19cfd3075e3b903a4ec34d40fd62d51d75b 100644 (file)
@@ -47,8 +47,6 @@ class DBConsumer : public DataHandler
 {
 public:
 
-    static const char* STASH_EVENT;
-
     // event we'll be listening to on the DataBus:
     // static constexpr char STASH_EVENT[] = "foo.stash.event";
 
@@ -62,7 +60,7 @@ public:
 
     Type get_from_stash(FlowStash& stash)
     {
-        stash.get(STASH_EVENT, value);
+        stash.get(STASH_APPID_SERVICE, value);
         return value;
     }
 
@@ -72,10 +70,6 @@ private:
     Type value;
 };
 
-template<class Type>
-const char* DBConsumer<Type>::STASH_EVENT = "foo.stash.event";
-
-
 
 // DataBus mock: most functions are stubs, but _subscribe() and  _publish()
 // are (close to) real.
@@ -152,27 +146,27 @@ TEST(stash_tests, data_bus_publish_test)
     typedef int32_t value_t;
 
     // DB deletes the subscribers so make c a pointer, not a local object.
-    DBConsumer<value_t>* c = new DBConsumer<value_t>("foo");
-    DataBus::subscribe(DBConsumer<value_t>::STASH_EVENT, c);
+    DBConsumer<value_t>* c = new DBConsumer<value_t>("appid-service");
+    DataBus::subscribe("appid-service", c);
 
     FlowStash stash;
     value_t vin, vout;
 
     // stash/publish 10
     vin = 10;
-    stash.store(DBConsumer<value_t>::STASH_EVENT, vin);
+    stash.store(STASH_APPID_SERVICE, vin);
     vout = c->get_value();
     CHECK_EQUAL(vin, vout);
 
     // stash/publish 20, with the same key as before
     vin = 20;
-    stash.store(DBConsumer<value_t>::STASH_EVENT, vin);
+    stash.store(STASH_APPID_SERVICE, vin);
     vout = c->get_value();
     CHECK_EQUAL(vin, vout);
 
     // do we get some event that we're not listening to?
     value_t before = c->get_value();
-    stash.store("bar.stash.event", 30);
+    stash.store(STASH_APPID_CLIENT, 30);
     value_t after = c->get_value();
     CHECK_EQUAL(before, after);
 
@@ -188,11 +182,11 @@ TEST(stash_tests, new_int32_item)
 {
     FlowStash stash;
 
-    stash.store("item_1", 10);
+    stash.store(STASH_APPID_SERVICE, 10);
 
     int32_t val;
 
-    CHECK(stash.get("item_1", val));
+    CHECK(stash.get(STASH_APPID_SERVICE, val));
     CHECK_EQUAL(val, 10);
 }
 
@@ -200,12 +194,12 @@ TEST(stash_tests, update_int32_item)
 {
     FlowStash stash;
 
-    stash.store("item_1", 10);
-    stash.store("item_1", 20);
+    stash.store(STASH_APPID_SERVICE, 10);
+    stash.store(STASH_APPID_SERVICE, 20);
 
     int32_t val;
 
-    CHECK(stash.get("item_1", val));
+    CHECK(stash.get(STASH_APPID_SERVICE, val));
     CHECK_EQUAL(val, 20);
 }
 
@@ -213,11 +207,11 @@ TEST(stash_tests, new_uint32_item)
 {
     FlowStash stash;
 
-    stash.store("item_1", 10u);
+    stash.store(STASH_APPID_SERVICE, 10u);
 
     uint32_t val;
 
-    CHECK(stash.get("item_1", val));
+    CHECK(stash.get(STASH_APPID_SERVICE, val));
     CHECK_EQUAL(val, 10u);
 }
 
@@ -225,12 +219,12 @@ TEST(stash_tests, update_uint32_item)
 {
     FlowStash stash;
 
-    stash.store("item_1", 10u);
-    stash.store("item_1", 20u);
+    stash.store(STASH_APPID_SERVICE, 10u);
+    stash.store(STASH_APPID_SERVICE, 20u);
 
     uint32_t val;
 
-    CHECK(stash.get("item_1", val));
+    CHECK(stash.get(STASH_APPID_SERVICE, val));
     CHECK_EQUAL(val, 20u);
 }
 
@@ -238,11 +232,11 @@ TEST(stash_tests, new_str_item_ref)
 {
     FlowStash stash;
 
-    stash.store("item_1", "value_1");
+    stash.store(STASH_HOST, "value_1");
 
     string val;
 
-    CHECK(stash.get("item_1", val));
+    CHECK(stash.get(STASH_HOST, val));
     STRCMP_EQUAL(val.c_str(), "value_1");
 }
 
@@ -250,11 +244,11 @@ TEST(stash_tests, new_str_item_ptr)
 {
     FlowStash stash;
 
-    stash.store("item_1", new string("value_1"));
+    stash.store(STASH_HOST, new string("value_1"));
 
     string val;
 
-    CHECK(stash.get("item_1", val));
+    CHECK(stash.get(STASH_HOST, val));
     STRCMP_EQUAL(val.c_str(), "value_1");
 }
 
@@ -262,12 +256,12 @@ TEST(stash_tests, update_str_item)
 {
     FlowStash stash;
 
-    stash.store("item_1", "value_1");
-    stash.store("item_1", new string("value_2"));
+    stash.store(STASH_HOST, "value_1");
+    stash.store(STASH_HOST, new string("value_2"));
 
     string val;
 
-    CHECK(stash.get("item_1", val));
+    CHECK(stash.get(STASH_HOST, val));
     STRCMP_EQUAL(val.c_str(), "value_2");
 }
 
@@ -275,11 +269,11 @@ TEST(stash_tests, non_existent_item)
 {
     FlowStash stash;
 
-    stash.store("item_1", 10);
+    stash.store(STASH_HOST, 10);
 
     int32_t val;
 
-    CHECK_FALSE(stash.get("item_2", val));
+    CHECK_FALSE(stash.get(STASH_URL, val));
 }
 
 TEST(stash_tests, new_generic_object)
@@ -287,10 +281,10 @@ TEST(stash_tests, new_generic_object)
     FlowStash stash;
     TestStashObject *test_object = new TestStashObject(111);
 
-    stash.store("item_1", test_object);
+    stash.store(STASH_XFF, test_object);
 
     StashGenericObject *retrieved_object;
-    CHECK(stash.get("item_1", retrieved_object));
+    CHECK(stash.get(STASH_XFF, retrieved_object));
     POINTERS_EQUAL(test_object, retrieved_object);
     CHECK_EQUAL(test_object->get_object_type(), ((TestStashObject*)retrieved_object)->get_object_type());
 }
@@ -299,13 +293,13 @@ TEST(stash_tests, update_generic_object)
 {
     FlowStash stash;
     TestStashObject *test_object = new TestStashObject(111);
-    stash.store("item_1", test_object);
+    stash.store(STASH_XFF, test_object);
 
     TestStashObject *new_test_object = new TestStashObject(111);
-    stash.store("item_1", new_test_object);
+    stash.store(STASH_XFF, new_test_object);
 
     StashGenericObject *retrieved_object;
-    CHECK(stash.get("item_1", retrieved_object));
+    CHECK(stash.get(STASH_XFF, retrieved_object));
     POINTERS_EQUAL(new_test_object, retrieved_object);
 }
 
@@ -313,7 +307,7 @@ TEST(stash_tests, non_existent_generic_object)
 {
     FlowStash stash;
     StashGenericObject *retrieved_object;
-    CHECK_FALSE(stash.get("item_1", retrieved_object));
+    CHECK_FALSE(stash.get(STASH_XFF, retrieved_object));
 }
 
 TEST(stash_tests, mixed_items)
@@ -321,23 +315,23 @@ TEST(stash_tests, mixed_items)
     FlowStash stash;
     TestStashObject *test_object = new TestStashObject(111);
 
-    stash.store("item_1", 10);
-    stash.store("item_2", "value_2");
-    stash.store("item_3", 30);
-    stash.store("item_4", test_object);
+    stash.store(STASH_APPID_SERVICE, 10);
+    stash.store(STASH_HOST, "value_2");
+    stash.store(STASH_APPID_CLIENT, 30);
+    stash.store(STASH_XFF, test_object);
 
     int32_t int32_val;
     string str_val;
 
-    CHECK(stash.get("item_1", int32_val));
+    CHECK(stash.get(STASH_APPID_SERVICE, int32_val));
     CHECK_EQUAL(int32_val, 10);
-    CHECK(stash.get("item_2", str_val));
+    CHECK(stash.get(STASH_HOST, str_val));
     STRCMP_EQUAL(str_val.c_str(), "value_2");
-    CHECK(stash.get("item_3", int32_val));
+    CHECK(stash.get(STASH_APPID_CLIENT, int32_val));
     CHECK_EQUAL(int32_val, 30);
 
     StashGenericObject *retrieved_object;
-    CHECK(stash.get("item_4", retrieved_object));
+    CHECK(stash.get(STASH_XFF, retrieved_object));
     POINTERS_EQUAL(test_object, retrieved_object);
     CHECK_EQUAL(test_object->get_object_type(), ((TestStashObject*)retrieved_object)->get_object_type());
 }
index aae4e48f7432e03a6d80031ad5bab791e054275c..d416107aa07cb1abab9f7420db1557f40e86c94a 100644 (file)
@@ -1080,5 +1080,6 @@ void AppIdDiscovery::do_post_discovery(Packet* p, AppIdSession& asd,
 
     asd.set_application_ids(service_id, asd.pick_client_app_id(), payload_id,
         asd.pick_misc_app_id(), change_bits);
+    asd.update_flow_attrs(change_bits);
     publish_appid_event(change_bits, p->flow);
 }
index cd3c48fe311273a6017ca579629e28af7bd2f3c8..d8993fd7d531cb58607424e9f412e2731dabacc5 100644 (file)
@@ -134,7 +134,7 @@ void HttpEventHandler::handle(DataEvent& event, Flow* flow)
         asd->set_application_ids(asd->pick_service_app_id(), asd->pick_client_app_id(),
             asd->pick_payload_app_id(), asd->pick_misc_app_id(), change_bits);
     }
-
+    asd->update_flow_attrs(change_bits);
     AppIdDiscovery::publish_appid_event(change_bits, flow);
 }
 
index d7b9ef8f7df3ddb0030c5f91b7934d528961222f..a08948ea62b032f2a26f29b069587ff13d98819f 100644 (file)
@@ -103,6 +103,49 @@ void AppIdHttpSession::set_http_change_bits(AppidChangeBits& change_bits, HttpFi
     }
 }
 
+void AppIdHttpSession::update_flow_attrs(AppidChangeBits& change_bits)
+{
+    if (change_bits[APPID_HOST_BIT])
+    {
+        if (meta_data[REQ_HOST_FID] and !meta_data[REQ_HOST_FID]->empty())
+            asd.flow->set_attr(STASH_HOST, *meta_data[REQ_HOST_FID]);
+        else
+            asd.flow->remove_attr(STASH_HOST);
+    }
+    
+    if (change_bits[APPID_URL_BIT])
+    {
+       if (meta_data[MISC_URL_FID] and !meta_data[MISC_URL_FID]->empty())
+            asd.flow->set_attr(STASH_URL, *meta_data[MISC_URL_FID]);
+        else
+            asd.flow->remove_attr(STASH_URL);
+    }
+
+    if (change_bits[APPID_USERAGENT_BIT])
+    {
+        if (meta_data[REQ_AGENT_FID] and !meta_data[REQ_AGENT_FID]->empty())
+            asd.flow->set_attr(STASH_USER_AGENT, *meta_data[REQ_AGENT_FID]);
+        else
+            asd.flow->remove_attr(STASH_USER_AGENT);
+    }
+
+    if (change_bits[APPID_RESPONSE_BIT])
+    {
+        if (meta_data[MISC_RESP_CODE_FID] and !meta_data[MISC_RESP_CODE_FID]->empty())
+            asd.flow->set_attr(STASH_RESPONSE_CODE, *meta_data[MISC_RESP_CODE_FID]);
+        else
+            asd.flow->remove_attr(STASH_RESPONSE_CODE);
+    }
+
+    if (change_bits[APPID_REFERER_BIT])
+    {
+        if (meta_data[REQ_REFERER_FID] and !meta_data[REQ_REFERER_FID]->empty())
+            asd.flow->set_attr(STASH_REFERER, *meta_data[REQ_REFERER_FID]);
+        else
+            asd.flow->remove_attr(STASH_REFERER);
+    }
+}
+
 int AppIdHttpSession::initial_chp_sweep(ChpMatchDescriptor& cmd)
 {
     CHPApp* cah = nullptr;
index e507f0c545585ac22b7d9a6f410c4322b66c99bb..10fde2d650cc69bf62783ad048728e563ea41350 100644 (file)
@@ -26,6 +26,7 @@
 #include <utility>
 
 #include "flow/flow.h"
+#include "flow/flow_stash_keys.h"
 #include "pub_sub/appid_events.h"
 #include "sfip/sf_ip.h"
 
@@ -106,8 +107,11 @@ public:
     {
         delete meta_data[id];
         meta_data[id] = str;
+
         if (str)
+        {
             set_http_change_bits(change_bits, id);
+        }
     }
 
     void set_field(HttpFieldIds id, const uint8_t* str, int32_t len, AppidChangeBits& change_bits)
@@ -189,6 +193,8 @@ public:
 
     void clear_all_fields();
 
+    void update_flow_attrs(AppidChangeBits& change_bits);
+
 protected:
 
     void init_chp_match_descriptor(ChpMatchDescriptor& cmd);
index 2255ee18f715a06de0c14f1b5550db842a8c2a7d..f9458bb8ca21b85709de1423ac0ede950c00415e 100644 (file)
@@ -104,7 +104,6 @@ AppIdSession::AppIdSession(IpProtocol proto, const SfIp* ip, uint16_t port,
     length_sequence.proto = IpProtocol::PROTO_NOT_SET;
     length_sequence.sequence_cnt = 0;
     memset(length_sequence.sequence, '\0', sizeof(length_sequence.sequence));
-    memset(application_ids, 0, sizeof(application_ids));
     appid_stats.total_sessions++;
 }
 
@@ -778,63 +777,103 @@ AppId AppIdSession::pick_referred_payload_app_id()
 void AppIdSession::set_application_ids(AppId service_id, AppId client_id,
     AppId payload_id, AppId misc_id, AppidChangeBits& change_bits)
 {
-    if (application_ids[APP_PROTOID_SERVICE] != service_id)
+    AppId service, client, payload, misc;
+    service = client = payload = misc = APP_ID_NONE;
+
+    flow->get_attr(STASH_APPID_SERVICE, service);
+    if (service != service_id)
     {
-        application_ids[APP_PROTOID_SERVICE] = service_id;
+        flow->set_attr(STASH_APPID_SERVICE, service_id);
         change_bits.set(APPID_SERVICE_BIT);
     }
-    if (application_ids[APP_PROTOID_CLIENT] != client_id)
+
+    flow->get_attr(STASH_APPID_CLIENT, client);
+    if (client != client_id)
     {
-        application_ids[APP_PROTOID_CLIENT] = client_id;
+        flow->set_attr(STASH_APPID_CLIENT, client_id);
         change_bits.set(APPID_CLIENT_BIT);
     }
-    if (application_ids[APP_PROTOID_PAYLOAD] != payload_id)
+
+    flow->get_attr(STASH_APPID_PAYLOAD, payload);
+    if (payload != payload_id)
     {
-        application_ids[APP_PROTOID_PAYLOAD] = payload_id;
+        flow->set_attr(STASH_APPID_PAYLOAD, payload_id);
         change_bits.set(APPID_PAYLOAD_BIT);
     }
-    if (application_ids[APP_PROTOID_MISC] != misc_id)
+
+    flow->get_attr(STASH_APPID_MISC, misc);
+    if (misc != misc_id)
     {
-        application_ids[APP_PROTOID_MISC] = misc_id;
+        flow->set_attr(STASH_APPID_MISC, misc_id);
         change_bits.set(APPID_MISC_BIT);
     }
 }
 
+ void AppIdSession::update_flow_attrs(AppidChangeBits& change_bits)
+ {
+    if (change_bits[APPID_REFERRED_BIT])
+        flow->set_attr(STASH_APPID_REFERRED, referred_payload_app_id);
+
+    if (change_bits[APPID_TLSHOST_BIT] and tsession and tsession->get_tls_host())
+        flow->set_attr(STASH_TLS_HOST, tsession->get_tls_host());
+
+    if (change_bits[APPID_VERSION_BIT])
+    {
+        if  (client.get_version())
+            flow->set_attr(STASH_CLIENT_VERSION, client.get_version());
+        else
+            flow->remove_attr(STASH_CLIENT_VERSION);
+    }
+
+    if (hsession)
+        hsession->update_flow_attrs(change_bits);
+}
+
 void AppIdSession::get_application_ids(AppId& service_id, AppId& client_id,
     AppId& payload_id, AppId& misc_id)
 {
-    service_id = application_ids[APP_PROTOID_SERVICE];
-    client_id  = application_ids[APP_PROTOID_CLIENT];
-    payload_id = application_ids[APP_PROTOID_PAYLOAD];
-    misc_id    = application_ids[APP_PROTOID_MISC];
+    service_id = client_id = payload_id = misc_id = APP_ID_NONE;
+    flow->get_attr(STASH_APPID_SERVICE, service_id);
+    flow->get_attr(STASH_APPID_CLIENT, client_id);
+    flow->get_attr(STASH_APPID_PAYLOAD, payload_id);
+    flow->get_attr(STASH_APPID_MISC, misc_id);
 }
 
 void AppIdSession::get_application_ids(AppId& service_id, AppId& client_id,
     AppId& payload_id)
-{
-    service_id = application_ids[APP_PROTOID_SERVICE];
-    client_id  = application_ids[APP_PROTOID_CLIENT];
-    payload_id = application_ids[APP_PROTOID_PAYLOAD];
+{    
+    service_id = client_id = payload_id = APP_ID_NONE;
+    flow->get_attr(STASH_APPID_SERVICE, service_id);
+    flow->get_attr(STASH_APPID_CLIENT, client_id);
+    flow->get_attr(STASH_APPID_PAYLOAD, payload_id);
 }
 
 AppId AppIdSession::get_application_ids_service()
 {
-    return application_ids[APP_PROTOID_SERVICE];
+    AppId service_id = APP_ID_NONE;;
+    flow->get_attr(STASH_APPID_SERVICE, service_id);
+    return service_id;
 }
 
 AppId AppIdSession::get_application_ids_client()
 {
-    return application_ids[APP_PROTOID_CLIENT];
+    AppId client_id = APP_ID_NONE;;
+    flow->get_attr(STASH_APPID_CLIENT, client_id);
+    return client_id;
 }
 
 AppId AppIdSession::get_application_ids_payload()
 {
-    return application_ids[APP_PROTOID_PAYLOAD];
+    AppId payload_id = APP_ID_NONE;;
+    flow->get_attr(STASH_APPID_PAYLOAD, payload_id);
+    return payload_id;
 }
 
 AppId AppIdSession::get_application_ids_misc()
 {
-    return application_ids[APP_PROTOID_MISC];
+    AppId misc_id = APP_ID_NONE;;
+    flow->get_attr(STASH_APPID_MISC, misc_id);
+    return misc_id;
 }
 
 bool AppIdSession::is_ssl_session_decrypted()
index 8a1493a040dc9324d196fea9a8fe8fb8712d7193..3bc3cf1b719c2cc8d52e0269f60c9e9407c17ac0 100644 (file)
@@ -27,6 +27,8 @@
 #include <unordered_map>
 
 #include "pub_sub/appid_events.h"
+#include "flow/flow.h"
+#include "flow/flow_stash_keys.h"
 
 #include "app_info_table.h"
 #include "appid_api.h"
 #include "length_app_cache.h"
 #include "service_state.h"
 
-class ClientDetector;
-class ServiceDetector;
 class AppIdDnsSession;
 class AppIdHttpSession;
+class ClientDetector;
+class ServiceDetector;
 class ThirdPartyAppIDSession;
 
 using AppIdFreeFCN = void (*)(void*);
@@ -306,6 +308,7 @@ public:
     AppId get_application_ids_client();
     AppId get_application_ids_payload();
     AppId get_application_ids_misc();
+    void update_flow_attrs(AppidChangeBits& change_bits);
 
     bool is_ssl_session_decrypted();
     void examine_ssl_metadata(snort::Packet*, AppidChangeBits& change_bits);
@@ -361,7 +364,6 @@ private:
     void delete_session_data();
 
     static THREAD_LOCAL uint32_t appid_flow_data_id;
-    AppId application_ids[APP_PROTOID_MAX];
     bool tp_app_id_deferred = false;
     bool tp_payload_app_id_deferred = false;
 
index c8f5d0120efe09d2604739414b80b55b20d2ad08..e2c5b7f0e9e6c0541d6e6a6d983c1f542c8b42c9 100644 (file)
@@ -108,6 +108,9 @@ bool AppIdIpsOption::match_id_against_rule(int32_t id)
     if ( nullptr != app_name_key )
     {
         string app_name(app_name_key);
+        //FIXIT-L: Inbuilt find of the set class does a partial (equivalent) key
+        //match. It does not match the complete appid id. Ex: "foo" will be
+        //matched with "foo bar"
         if ( appid_table.find(app_name) != appid_table.end() )
             return true;
     }
index 8e843ab156420d58e8d3ab80b21b5bf88bdc27f3..98041f695157d6f2b394b0a8fc3e9e93ced10007 100644 (file)
@@ -188,6 +188,7 @@ AppIdSession* AppIdSession::allocate_session(const Packet*, IpProtocol,
 {
     return nullptr;
 }
+void AppIdSession::update_flow_attrs(AppidChangeBits&) {}
 
 // Stubs for ServiceDiscovery
 void ServiceDiscovery::initialize() {}
@@ -268,6 +269,8 @@ AppId check_session_for_AF_forecast(AppIdSession&, Packet*, AppidSessionDirectio
     return APP_ID_UNKNOWN;
 }
 
+void AppIdHttpSession::update_flow_attrs(AppidChangeBits&) {}
+
 TEST_GROUP(appid_discovery_tests)
 {
     void setup() override
@@ -316,6 +319,7 @@ TEST(appid_discovery_tests, event_published_when_ignoring_flow)
     AppIdSession* asd = new AppIdSession(IpProtocol::TCP, nullptr, 21, ins);
     Flow* flow = new Flow;
     flow->set_flow_data(asd);
+    flow->stash = new snort::FlowStash;
     p.flow = flow;
     asd->config = &my_app_config;
     asd->common.initiator_port = 21;
@@ -328,6 +332,7 @@ TEST(appid_discovery_tests, event_published_when_ignoring_flow)
     CHECK_EQUAL(databus_publish_called, true);
     STRCMP_EQUAL(test_log, "Published change_bits == 0000000001111");
     delete asd;
+    delete flow->stash;
     delete flow;
 }
 
@@ -347,6 +352,7 @@ TEST(appid_discovery_tests, event_published_when_processing_flow)
     AppIdSession* asd = new AppIdSession(IpProtocol::TCP, nullptr, 21, ins);
     Flow* flow = new Flow;
     flow->set_flow_data(asd);
+    flow->stash = new snort::FlowStash;
     p.flow = flow;
     asd->config = &my_app_config;
     asd->common.initiator_port = 21;
@@ -356,8 +362,9 @@ TEST(appid_discovery_tests, event_published_when_processing_flow)
 
     // Detect changes in service, client, payload, and misc appid
     CHECK_EQUAL(databus_publish_called, true);
-    STRCMP_EQUAL(test_log, "Published change_bits == 0000000001111");
+    STRCMP_EQUAL(test_log, "Published change_bits == 0000000001110");
     delete asd;
+    delete flow->stash;
     delete flow;
 }
 
@@ -401,8 +408,9 @@ TEST(appid_discovery_tests, change_bits_for_non_http_appid)
     AppIdModule app_module;
     AppIdInspector ins(app_module);
     AppIdSession* asd = new AppIdSession(IpProtocol::TCP, nullptr, 21, ins);
-    Flow* flow = new Flow;
+    FakeFlow* flow = new FakeFlow;
     flow->set_flow_data(asd);
+    flow->stash = new snort::FlowStash;
     p.flow = flow;
     asd->config = &my_app_config;
     asd->common.initiator_port = 21;
@@ -432,6 +440,7 @@ TEST(appid_discovery_tests, change_bits_for_non_http_appid)
     CHECK_EQUAL(asd->service.get_id(), APP_ID_DNS);
 
     delete asd;
+    delete flow->stash;
     delete flow;
 }
 
index 171d44a0497d9c8b20bc73a3c823f083eb4b9176..140d121e06259b3a33c1f447022d6ae07a91bc93 100644 (file)
@@ -44,6 +44,9 @@
 THREAD_LOCAL AppIdDebug* appidDebug = nullptr;
 void AppIdDebug::activate(const Flow*, const AppIdSession*, bool) { active = true; }
 
+//Stubs for AppIdHttpSession
+void AppIdSession::update_flow_attrs(AppidChangeBits&) {}
+
 using namespace snort;
 
 namespace snort
index 39dbe6f03285211996c9e6943ae278fc2c0e8979..846c9ccaca2150795c00ef0b021b903b86cc9fe6 100644 (file)
@@ -51,7 +51,11 @@ int Flow::set_flow_data(FlowData* fd)
     return 0;
 }
 
-FlowStash::~FlowStash() { }
+bool snort::FlowStash::get(const int&, int32_t&) { return true; }
+void snort::FlowStash::store(const int&, const int32_t) { }
+void snort::FlowStash::store(const int&, const std::string&) { }
+void snort::FlowStash::remove(const FlowStashKey&) { }
+snort::FlowStash::~FlowStash() { }
 
 #endif
 
index 5bc9334bcef10a5c4cce7b03146a9c6817f5fcf0..ffb990823b7fb3154b32ad2fb48b869510d7068b 100644 (file)
@@ -167,26 +167,36 @@ void* AppIdSession::remove_flow_data(unsigned type)
 }
 
 void AppIdSession::set_application_ids(AppId service_id, AppId client_id,
-    AppId payload_id, AppId misc_id, AppidChangeBits& change_bits)
+     AppId payload_id, AppId misc_id, AppidChangeBits& change_bits)
 {
-    if (application_ids[APP_PROTOID_SERVICE] != service_id)
+    AppId service, client, payload, misc;
+    service = client = payload = misc = APP_ID_NONE;
+
+    flow->get_attr(STASH_APPID_SERVICE, service);
+    if (service != service_id)
     {
-        application_ids[APP_PROTOID_SERVICE] = service_id;
+        flow->set_attr(STASH_APPID_SERVICE, service_id);
         change_bits.set(APPID_SERVICE_BIT);
     }
-    if (application_ids[APP_PROTOID_CLIENT] != client_id)
+
+    flow->get_attr(STASH_APPID_CLIENT, client);
+    if (client != client_id)
     {
-        application_ids[APP_PROTOID_CLIENT] = client_id;
+        flow->set_attr(STASH_APPID_CLIENT, client_id);
         change_bits.set(APPID_CLIENT_BIT);
     }
-    if (application_ids[APP_PROTOID_PAYLOAD] != payload_id)
+
+    flow->get_attr(STASH_APPID_PAYLOAD, payload);
+    if (payload != payload_id)
     {
-        application_ids[APP_PROTOID_PAYLOAD] = payload_id;
+        flow->set_attr(STASH_APPID_PAYLOAD, payload_id);
         change_bits.set(APPID_PAYLOAD_BIT);
     }
-    if (application_ids[APP_PROTOID_MISC] != misc_id)
+
+    flow->get_attr(STASH_APPID_MISC, misc);
+    if (misc != misc_id)
     {
-        application_ids[APP_PROTOID_MISC] = misc_id;
+        flow->set_attr(STASH_APPID_MISC, misc_id);
         change_bits.set(APPID_MISC_BIT);
     }
 }