]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #1357 in SNORT/snort3 from firewall_appid_pub_sub to master
authorMike Stepanek (mstepane) <mstepane@cisco.com>
Tue, 11 Sep 2018 18:32:28 +0000 (14:32 -0400)
committerMike Stepanek (mstepane) <mstepane@cisco.com>
Tue, 11 Sep 2018 18:32:28 +0000 (14:32 -0400)
Squashed commit of the following:

commit 1216e90c23db8393f515bd5892c646a76e1be7c8
Author: Masud Hasan <mashasan@cisco.com>
Date:   Tue Sep 4 11:12:54 2018 -0400

    appid: Supporting pub-sub mechanism for app changes

88 files changed:
src/network_inspectors/appid/appid_api.cc
src/network_inspectors/appid/appid_app_descriptor.h
src/network_inspectors/appid/appid_detector.cc
src/network_inspectors/appid/appid_detector.h
src/network_inspectors/appid/appid_discovery.cc
src/network_inspectors/appid/appid_discovery.h
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/appid_session_api.cc
src/network_inspectors/appid/client_plugins/client_app_aim.cc
src/network_inspectors/appid/client_plugins/client_app_bit.cc
src/network_inspectors/appid/client_plugins/client_app_bit_tracker.cc
src/network_inspectors/appid/client_plugins/client_app_msn.cc
src/network_inspectors/appid/client_plugins/client_app_rtp.cc
src/network_inspectors/appid/client_plugins/client_app_ssh.cc
src/network_inspectors/appid/client_plugins/client_app_timbuktu.cc
src/network_inspectors/appid/client_plugins/client_app_tns.cc
src/network_inspectors/appid/client_plugins/client_app_vnc.cc
src/network_inspectors/appid/client_plugins/client_app_ym.cc
src/network_inspectors/appid/client_plugins/client_discovery.cc
src/network_inspectors/appid/client_plugins/client_discovery.h
src/network_inspectors/appid/detector_plugins/detector_dns.cc
src/network_inspectors/appid/detector_plugins/detector_http.cc
src/network_inspectors/appid/detector_plugins/detector_imap.cc
src/network_inspectors/appid/detector_plugins/detector_kerberos.cc
src/network_inspectors/appid/detector_plugins/detector_kerberos.h
src/network_inspectors/appid/detector_plugins/detector_pattern.cc
src/network_inspectors/appid/detector_plugins/detector_pop3.cc
src/network_inspectors/appid/detector_plugins/detector_sip.cc
src/network_inspectors/appid/detector_plugins/detector_sip.h
src/network_inspectors/appid/detector_plugins/detector_smtp.cc
src/network_inspectors/appid/detector_plugins/detector_smtp.h
src/network_inspectors/appid/lua_detector_api.cc
src/network_inspectors/appid/lua_detector_api.h
src/network_inspectors/appid/service_plugins/service_battle_field.cc
src/network_inspectors/appid/service_plugins/service_bgp.cc
src/network_inspectors/appid/service_plugins/service_bit.cc
src/network_inspectors/appid/service_plugins/service_bootp.cc
src/network_inspectors/appid/service_plugins/service_dcerpc.cc
src/network_inspectors/appid/service_plugins/service_detector.cc
src/network_inspectors/appid/service_plugins/service_detector.h
src/network_inspectors/appid/service_plugins/service_direct_connect.cc
src/network_inspectors/appid/service_plugins/service_direct_connect.h
src/network_inspectors/appid/service_plugins/service_discovery.cc
src/network_inspectors/appid/service_plugins/service_discovery.h
src/network_inspectors/appid/service_plugins/service_flap.cc
src/network_inspectors/appid/service_plugins/service_ftp.cc
src/network_inspectors/appid/service_plugins/service_irc.cc
src/network_inspectors/appid/service_plugins/service_lpr.cc
src/network_inspectors/appid/service_plugins/service_mdns.cc
src/network_inspectors/appid/service_plugins/service_mysql.cc
src/network_inspectors/appid/service_plugins/service_netbios.cc
src/network_inspectors/appid/service_plugins/service_nntp.cc
src/network_inspectors/appid/service_plugins/service_ntp.cc
src/network_inspectors/appid/service_plugins/service_radius.cc
src/network_inspectors/appid/service_plugins/service_regtest.cc
src/network_inspectors/appid/service_plugins/service_rexec.cc
src/network_inspectors/appid/service_plugins/service_rfb.cc
src/network_inspectors/appid/service_plugins/service_rlogin.cc
src/network_inspectors/appid/service_plugins/service_rpc.cc
src/network_inspectors/appid/service_plugins/service_rshell.cc
src/network_inspectors/appid/service_plugins/service_rsync.cc
src/network_inspectors/appid/service_plugins/service_rtmp.cc
src/network_inspectors/appid/service_plugins/service_snmp.cc
src/network_inspectors/appid/service_plugins/service_ssh.cc
src/network_inspectors/appid/service_plugins/service_ssl.cc
src/network_inspectors/appid/service_plugins/service_telnet.cc
src/network_inspectors/appid/service_plugins/service_tftp.cc
src/network_inspectors/appid/service_plugins/service_timbuktu.cc
src/network_inspectors/appid/service_plugins/service_tns.cc
src/network_inspectors/appid/test/CMakeLists.txt
src/network_inspectors/appid/test/appid_api_test.cc
src/network_inspectors/appid/test/appid_detector_test.cc
src/network_inspectors/appid/test/appid_discovery_test.cc [new file with mode: 0644]
src/network_inspectors/appid/test/appid_expected_flags_test.cc
src/network_inspectors/appid/test/appid_http_event_test.cc
src/network_inspectors/appid/test/appid_http_session_test.cc
src/network_inspectors/appid/test/appid_mock_http_session.h
src/network_inspectors/appid/test/appid_mock_session.h
src/network_inspectors/appid/test/appid_session_api_test.cc
src/network_inspectors/appid/test/service_state_test.cc
src/network_inspectors/appid/tp_appid_utils.cc
src/network_inspectors/appid/tp_appid_utils.h
src/pub_sub/CMakeLists.txt
src/pub_sub/appid_events.h [new file with mode: 0644]

index e00ac9cee82bb75fe3e2096ad4d2848a22719ae1..d85467e83dd99889c4c0b471dd4a4cc38e08c024 100644 (file)
@@ -167,8 +167,7 @@ uint32_t AppIdApi::consume_ha_state(Flow& flow, const uint8_t* buf, uint8_t, IpP
         if( (appHA->flags & APPID_HA_FLAGS_TP_DONE) && asd->tpsession )
         {
 #ifdef ENABLE_APPID_THIRD_PARTY
-            if( asd->tpsession)
-                asd->tpsession->set_state(TP_STATE_TERMINATED);
+            asd->tpsession->set_state(TP_STATE_TERMINATED);
 #endif
             asd->set_session_flags(APPID_SESSION_NO_TPI);
         }
index a3023749f90375521217fe40f45876105f57a5ba..8106bd166c5a53c6a2313809b85e400eb2829901 100644 (file)
@@ -47,11 +47,11 @@ public:
         my_version.clear();
     }
 
-    virtual void update(AppId id, char* vendor, char* version)
+    virtual void update(AppId id, char* vendor, char* version, AppidChangeBits& change_bits)
     {
         set_id(id);
         set_vendor(vendor);
-        set_version(version);
+        set_version(version, change_bits);
     }
 
     virtual void update_stats(AppId id) = 0;
@@ -89,10 +89,13 @@ public:
         return my_version.empty() ? nullptr : my_version.c_str();
     }
 
-    void set_version(const char* version)
+    void set_version(const char* version, AppidChangeBits& change_bits)
     {
         if ( version )
+        {
             my_version = version;
+            change_bits.set(APPID_VERSION_BIT);
+        }
     }
 
 private:
index 9913f36d057df3ba299396f0cac839c51eebd212..c3cf101588772e08ecaa0f98a9e0dc19024ab239 100644 (file)
@@ -66,12 +66,12 @@ int AppIdDetector::data_add(AppIdSession& asd, void* data, AppIdFreeFCN fcn)
     return asd.add_flow_data(data, flow_data_index, fcn);
 }
 
-void AppIdDetector::add_info(AppIdSession& asd, const char* info)
+void AppIdDetector::add_info(AppIdSession& asd, const char* info, AppidChangeBits& change_bits)
 {
     AppIdHttpSession* hsession = asd.get_http_session();
 
     if ( !hsession->get_field(MISC_URL_FID) )
-        hsession->set_field(MISC_URL_FID, new std::string(info));
+        hsession->set_field(MISC_URL_FID, new std::string(info), change_bits);
 }
 
 void AppIdDetector::add_user(AppIdSession& asd, const char* username, AppId appId, bool success)
@@ -89,10 +89,10 @@ void AppIdDetector::add_payload(AppIdSession& asd, AppId payload_id)
 }
 
 void AppIdDetector::add_app(AppIdSession& asd, AppId service_id, AppId client_id,
-    const char* version)
+    const char* version, AppidChangeBits& change_bits)
 {
     if ( version )
-        asd.client.set_version(version);
+        asd.client.set_version(version, change_bits);
 
     asd.set_client_detected();
     asd.client_inferred_service_id = service_id;
index a02737da5007f8ec29dd7b135125b26608fc4033..66f4edddb26c3792458a0cbc1df76baf85b297de 100644 (file)
@@ -75,8 +75,9 @@ typedef std::vector<ServiceDetectorPort> ServiceDetectorPorts;
 class AppIdDiscoveryArgs
 {
 public:
-    AppIdDiscoveryArgs(const uint8_t* data, uint16_t size, AppidSessionDirection dir, AppIdSession& asd,
-        snort::Packet* p) : data(data), size(size), dir(dir), asd(asd), pkt(p), config(asd.config)
+    AppIdDiscoveryArgs(const uint8_t* data, uint16_t size, AppidSessionDirection dir,
+        AppIdSession& asd, snort::Packet* p, AppidChangeBits& cb) : data(data),
+        size(size), dir(dir), asd(asd), pkt(p), config(asd.config), change_bits(cb)
     {}
 
     const uint8_t* data;
@@ -85,6 +86,7 @@ public:
     AppIdSession& asd;
     snort::Packet* pkt;
     const AppIdConfig* config = nullptr;
+    AppidChangeBits& change_bits;
 };
 
 // These numbers are what Lua (VDB/ODP) gives us. If these numbers are ever changed,
@@ -117,10 +119,10 @@ public:
 
     virtual void* data_get(AppIdSession&);
     virtual int data_add(AppIdSession&, void*, AppIdFreeFCN);
-    virtual void add_info(AppIdSession&, const char*);
+    virtual void add_info(AppIdSession&, const char*, AppidChangeBits&);
     virtual void add_user(AppIdSession&, const char*, AppId, bool);
     virtual void add_payload(AppIdSession&, AppId);
-    virtual void add_app(AppIdSession&, AppId, AppId, const char*);
+    virtual void add_app(AppIdSession&, AppId, AppId, const char*, AppidChangeBits&);
     virtual void finalize_patterns() {}
     const char* get_code_string(APPID_STATUS_CODE) const;
 
index 51ef5b59440bc2555857c64f65e7625e05d87cce..7fe94da7afd3290d0788343ac2f666cd684a78b7 100644 (file)
@@ -148,9 +148,26 @@ void AppIdDiscovery::do_application_discovery(Packet* p, AppIdInspector& inspect
         return;
 
     AppId service_id;
-    bool is_discovery_done = do_discovery(p, *asd, protocol, direction, service_id);
+    AppidChangeBits change_bits;
+    bool is_discovery_done = do_discovery(p, *asd, protocol, direction, service_id, change_bits);
 
-    do_post_discovery(p, *asd, direction, is_discovery_done, service_id);
+    do_post_discovery(p, *asd, direction, is_discovery_done, service_id, change_bits);
+}
+
+void AppIdDiscovery::publish_appid_event(AppidChangeBits& change_bits, snort::Flow* flow)
+{
+    if (change_bits.none())
+        return;
+
+    AppidEvent app_event(change_bits);
+    DataBus::publish(APPID_EVENT_ANY_CHANGE, app_event, flow);
+    if (appidDebug->is_active())
+    {
+        std::string str;
+        change_bits_to_string(change_bits, str);
+        LogMessage("AppIdDbg %s Published event for changes: %s\n",
+            appidDebug->get_debug_session(), str.c_str());
+    }
 }
 
 static inline int match_pe_network(const SfIp* pktAddr, const PortExclusion* pe)
@@ -741,8 +758,10 @@ bool AppIdDiscovery::do_pre_discovery(Packet* p, AppIdSession** p_asd, AppIdInsp
     {
         if (!asd->get_session_flags(APPID_SESSION_IGNORE_FLOW_IDED))
         {
+            AppidChangeBits change_bits;
             asd->set_application_ids(asd->pick_service_app_id(), asd->pick_client_app_id(),
-                asd->pick_payload_app_id(), asd->pick_misc_app_id());
+                asd->pick_payload_app_id(), asd->pick_misc_app_id(), change_bits);
+            publish_appid_event(change_bits, p->flow);
             asd->set_session_flags(APPID_SESSION_IGNORE_FLOW_IDED);
         }
 
@@ -829,7 +848,7 @@ bool AppIdDiscovery::do_pre_discovery(Packet* p, AppIdSession** p_asd, AppIdInsp
 }
 
 bool AppIdDiscovery::do_discovery(Packet* p, AppIdSession& asd, IpProtocol protocol,
-    AppidSessionDirection direction, AppId& service_id)
+    AppidSessionDirection direction, AppId& service_id, AppidChangeBits& change_bits)
 {
     bool is_discovery_done = false;
 
@@ -837,12 +856,12 @@ bool AppIdDiscovery::do_discovery(Packet* p, AppIdSession& asd, IpProtocol proto
     if ( !(asd.scan_flags & SCAN_HOST_PORT_FLAG) )
         lookup_appid_by_host_port(asd, p, protocol, direction);
 
-    asd.check_app_detection_restart();
+    asd.check_app_detection_restart(change_bits);
 
     // Third party detection
 #ifdef ENABLE_APPID_THIRD_PARTY
     if ( TPLibHandler::have_tp() )
-        is_discovery_done = do_tp_discovery(asd,protocol,p,direction);
+        is_discovery_done = do_tp_discovery(asd, protocol, p, direction, change_bits);
 #endif
 
     // Port-based service detection
@@ -884,7 +903,7 @@ bool AppIdDiscovery::do_discovery(Packet* p, AppIdSession& asd, IpProtocol proto
     // exceptions for rexec and any other service detector that need to see SYN and SYN/ACK
     if (asd.get_session_flags(APPID_SESSION_REXEC_STDERR))
     {
-        ServiceDiscovery::get_instance().identify_service(asd, p, direction);
+        ServiceDiscovery::get_instance().identify_service(asd, p, direction, change_bits);
         AppIdDnsSession* dsession = asd.get_dns_session();
 
         if (asd.service.get_id() == APP_ID_DNS &&
@@ -893,22 +912,22 @@ bool AppIdDiscovery::do_discovery(Packet* p, AppIdSession& asd, IpProtocol proto
             AppId client_id = APP_ID_NONE, payload_id = APP_ID_NONE;
             dns_host_scan_hostname((const uint8_t*)dsession->get_host(), dsession->get_host_len(),
                 &client_id, &payload_id);
-            asd.set_client_appid_data(client_id, nullptr);
+            asd.set_client_appid_data(client_id, nullptr, change_bits);
         }
         else if (asd.service.get_id() == APP_ID_RTMP)
-            asd.examine_rtmp_metadata();
+            asd.examine_rtmp_metadata(change_bits);
         else if (asd.get_session_flags(APPID_SESSION_SSL_SESSION) && asd.tsession)
-            asd.examine_ssl_metadata(p);
+            asd.examine_ssl_metadata(p, change_bits);
     }
     // FIXIT-M - snort 2.x has added a check for midstream pickup to this, do we need that?
     else if (protocol != IpProtocol::TCP || (p->packet_flags & PKT_STREAM_ORDER_OK))
     {
         if (asd.service_disco_state != APPID_DISCO_STATE_FINISHED)
-            is_discovery_done =
-                ServiceDiscovery::get_instance().do_service_discovery(asd, p, direction);
+            is_discovery_done = ServiceDiscovery::get_instance().do_service_discovery(asd, p,
+                direction, change_bits);
         if (asd.client_disco_state != APPID_DISCO_STATE_FINISHED)
-            is_discovery_done =
-                ClientDiscovery::get_instance().do_client_discovery(asd, p, direction);
+            is_discovery_done = ClientDiscovery::get_instance().do_client_discovery(asd, p,
+                direction, change_bits);
         asd.set_session_flags(APPID_SESSION_ADDITIONAL_PACKET);
     }
 
@@ -943,7 +962,8 @@ bool AppIdDiscovery::do_discovery(Packet* p, AppIdSession& asd, IpProtocol proto
 }
 
 void AppIdDiscovery::do_post_discovery(Packet* p, AppIdSession& asd,
-    AppidSessionDirection direction, bool is_discovery_done, AppId service_id)
+    AppidSessionDirection direction, bool is_discovery_done, AppId service_id,
+    AppidChangeBits& change_bits)
 {
     AppId payload_id = asd.pick_payload_app_id();
 
@@ -965,7 +985,7 @@ 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());
+        asd.pick_misc_app_id(), change_bits);
 
     // Set the field that the Firewall queries to see if we have a search engine
     if (asd.search_support_type == UNKNOWN_SEARCH_ENGINE && payload_id > APP_ID_NONE)
@@ -1007,8 +1027,10 @@ void AppIdDiscovery::do_post_discovery(Packet* p, AppIdSession& asd,
             asd.past_forecast = check_session_for_AF_forecast(asd, p, direction,
                 (AppId)service_id);
             asd.set_application_ids(service_id, asd.pick_client_app_id(),
-                asd.pick_payload_app_id(), asd.pick_misc_app_id());
+                asd.pick_payload_app_id(), asd.pick_misc_app_id(), change_bits);
         }
     }
+
+    publish_appid_event(change_bits, p->flow);
 }
 
index a889e03f22d38804713fbb2cb7dc69b2297a7e89..46a15e71043faabada54a08e08ee13d12438cafc 100644 (file)
 #include <string>
 #include <vector>
 
-#include "appid_types.h"
-#include "application_ids.h"
-
+#include "flow/flow.h"
 #include "protocols/protocol_ids.h"
+#include "pub_sub/appid_events.h"
 #include "search_engines/search_tool.h"
-#include "flow/flow.h"
 #include "utils/util.h"
 
+#include "appid_types.h"
+#include "application_ids.h"
+
 class AppIdInspector;
 class AppIdSession;
 class AppIdDetector;
@@ -109,6 +110,7 @@ public:
     virtual int add_service_port(AppIdDetector*, const ServiceDetectorPort&);
 
     static void do_application_discovery(snort::Packet* p, AppIdInspector&);
+    static void publish_appid_event(AppidChangeBits&, snort::Flow*);
 
     AppIdDetectors* get_tcp_detectors()
     {
@@ -137,9 +139,10 @@ private:
     static bool do_pre_discovery(snort::Packet* p, AppIdSession** p_asd, AppIdInspector& inspector,
         IpProtocol& protocol, AppidSessionDirection& direction);
     static bool do_discovery(snort::Packet* p, AppIdSession& asd, IpProtocol protocol,
-        AppidSessionDirection direction, AppId& service_id);
+        AppidSessionDirection direction, AppId& service_id, AppidChangeBits& change_bits);
     static void do_post_discovery(snort::Packet* p, AppIdSession& asd,
-        AppidSessionDirection direction, bool is_discovery_done, AppId service_id);
+        AppidSessionDirection direction, bool is_discovery_done, AppId service_id,
+        AppidChangeBits& change_bits);
     static bool handle_unmonitored_session(AppIdSession* asd, const snort::Packet* p,
         IpProtocol protocol, AppidSessionDirection dir, AppIdInspector& inspector,
         uint64_t& flow_flags);
index 88e2f7ea3acd1ecd53e98116e9fde8237e1f1f3c..5a1d59583510dfbf394e07f508b38f1222d4a1d9 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "app_info_table.h"
 #include "appid_debug.h"
+#include "appid_discovery.h"
 #include "appid_http_session.h"
 #include "appid_session.h"
 #include "utils/util.h"
@@ -39,16 +40,17 @@ using namespace snort;
 
 void HttpEventHandler::handle(DataEvent& event, Flow* flow)
 {
-    AppidSessionDirection direction;
-    const uint8_t* header_start;
-    int32_t header_length;
-    HttpEvent* http_event = (HttpEvent*)&event;
-
     assert(flow);
     AppIdSession* asd = appid_api.get_appid_session(*flow);
     if (!asd)
         return;
 
+    AppidSessionDirection direction;
+    const uint8_t* header_start;
+    int32_t header_length;
+    HttpEvent* http_event = (HttpEvent*)&event;
+    AppidChangeBits change_bits;
+
     if (appidDebug->is_active())
         LogMessage("AppIdDbg %s Processing HTTP metadata from HTTP Inspector\n",
             appidDebug->get_debug_session());
@@ -62,30 +64,30 @@ void HttpEventHandler::handle(DataEvent& event, Flow* flow)
         header_start = http_event->get_host(header_length);
         if (header_length > 0)
         {
-            hsession->set_field(REQ_HOST_FID, header_start, header_length);
+            hsession->set_field(REQ_HOST_FID, header_start, header_length, change_bits);
             asd->scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
 
             header_start = http_event->get_uri(header_length);
             if (header_length > 0)
             {
-                hsession->set_field(REQ_URI_FID, header_start, header_length);
-                hsession->update_url();
+                hsession->set_field(REQ_URI_FID, header_start, header_length, change_bits);
+                hsession->update_url(change_bits);
             }
         }
 
         header_start = http_event->get_user_agent(header_length);
         if (header_length > 0)
         {
-            hsession->set_field(REQ_AGENT_FID, header_start, header_length);
+            hsession->set_field(REQ_AGENT_FID, header_start, header_length, change_bits);
             asd->scan_flags |= SCAN_HTTP_USER_AGENT_FLAG;
         }
 
         header_start = http_event->get_cookie(header_length);
-        hsession->set_field(REQ_COOKIE_FID, header_start, header_length);
+        hsession->set_field(REQ_COOKIE_FID, header_start, header_length, change_bits);
         header_start = http_event->get_referer(header_length);
-        hsession->set_field(REQ_REFERER_FID, header_start, header_length);
+        hsession->set_field(REQ_REFERER_FID, header_start, header_length, change_bits);
         header_start = http_event->get_x_working_with(header_length);
-        hsession->set_field(MISC_XWW_FID, header_start, header_length);
+        hsession->set_field(MISC_XWW_FID, header_start, header_length, change_bits);
         hsession->set_is_webdav(http_event->contains_webdav_method());
 
         // FIXIT-M: Should we get request body (may be expensive to copy)?
@@ -95,11 +97,11 @@ void HttpEventHandler::handle(DataEvent& event, Flow* flow)
     else    // Response headers.
     {
         header_start = http_event->get_content_type(header_length);
-        hsession->set_field(RSP_CONTENT_TYPE_FID, header_start, header_length);
+        hsession->set_field(RSP_CONTENT_TYPE_FID, header_start, header_length, change_bits);
         header_start = http_event->get_location(header_length);
-        hsession->set_field(RSP_LOCATION_FID, header_start, header_length);
+        hsession->set_field(RSP_LOCATION_FID, header_start, header_length, change_bits);
         header_start = http_event->get_server(header_length);
-        hsession->set_field(MISC_SERVER_FID, header_start, header_length);
+        hsession->set_field(MISC_SERVER_FID, header_start, header_length, change_bits);
 
         int32_t responseCodeNum = http_event->get_response_code();
         if (responseCodeNum > 0 && responseCodeNum < 700)
@@ -108,7 +110,7 @@ void HttpEventHandler::handle(DataEvent& event, Flow* flow)
             char tmpstr[32];
             ret = snprintf(tmpstr, sizeof(tmpstr), "%d", responseCodeNum);
             if ( ret < sizeof(tmpstr) )
-                hsession->set_field(MISC_RESP_CODE_FID, (const uint8_t*)tmpstr, ret);
+                hsession->set_field(MISC_RESP_CODE_FID, (const uint8_t*)tmpstr, ret, change_bits);
         }
 
         // FIXIT-M: Get Location header data.
@@ -121,15 +123,17 @@ void HttpEventHandler::handle(DataEvent& event, Flow* flow)
     header_start = http_event->get_via(header_length);
     if (header_length > 0)
     {
-        hsession->set_field(MISC_VIA_FID, header_start, header_length);
+        hsession->set_field(MISC_VIA_FID, header_start, header_length, change_bits);
         asd->scan_flags |= SCAN_HTTP_VIA_FLAG;
     }
 
-    hsession->process_http_packet(direction);
+    hsession->process_http_packet(direction, change_bits);
     if (asd->service.get_id() == APP_ID_HTTP)
     {
         asd->set_application_ids(asd->pick_service_app_id(), asd->pick_client_app_id(),
-            asd->pick_payload_app_id(), asd->pick_misc_app_id());
+            asd->pick_payload_app_id(), asd->pick_misc_app_id(), change_bits);
     }
+
+    AppIdDiscovery::publish_appid_event(change_bits, flow);
 }
 
index 1b12f0ece9efef8b652e7856346e356341bd4a31..553ac32030cc7a37f067b28c17b5f936481ebb87 100644 (file)
@@ -81,6 +81,30 @@ void AppIdHttpSession::free_chp_matches(ChpMatchDescriptor& cmd, unsigned num_ma
             cmd.chp_matches[i].clear();
 }
 
+void AppIdHttpSession::set_http_change_bits(AppidChangeBits& change_bits, HttpFieldIds id)
+{
+    switch (id)
+    {
+    case REQ_HOST_FID:
+        change_bits.set(APPID_HOST_BIT);
+        break;
+    case MISC_URL_FID:
+        change_bits.set(APPID_URL_BIT);
+        break;
+    case REQ_AGENT_FID:
+        change_bits.set(APPID_USERAGENT_BIT);
+        break;
+    case MISC_RESP_CODE_FID:
+        change_bits.set(APPID_RESPONSE_BIT);
+        break;
+    case REQ_REFERER_FID:
+        change_bits.set(APPID_REFERER_BIT);
+        break;
+    default:
+        break;
+    }
+}
+
 int AppIdHttpSession::initial_chp_sweep(ChpMatchDescriptor& cmd)
 {
     CHPApp* cah = nullptr;
@@ -184,7 +208,7 @@ void AppIdHttpSession::init_chp_match_descriptor(ChpMatchDescriptor& cmd)
     }
 }
 
-void AppIdHttpSession::process_chp_buffers()
+void AppIdHttpSession::process_chp_buffers(AppidChangeBits& change_bits)
 {
     ChpMatchDescriptor cmd;
 
@@ -290,13 +314,13 @@ void AppIdHttpSession::process_chp_buffers()
                 : CHP_APPIDINSTANCE_TO_ID(chp_candidate);
 
             if (app_type_flags & APP_TYPE_SERVICE)
-                asd.set_service_appid_data(chp_final, nullptr, version);
+                asd.set_service_appid_data(chp_final, nullptr, version, change_bits);
 
             if (app_type_flags & APP_TYPE_CLIENT)
-                asd.set_client_appid_data(chp_final, version);
+                asd.set_client_appid_data(chp_final, version, change_bits);
 
             if ( app_type_flags & APP_TYPE_PAYLOAD )
-                asd.set_payload_appid_data((AppId)chp_final, version);
+                asd.set_payload_appid_data((AppId)chp_final, version, change_bits);
 
             if ( version )
             {
@@ -323,7 +347,7 @@ void AppIdHttpSession::process_chp_buffers()
                             httpFieldName[i], cmd.chp_rewritten[i]);
 
                     set_field((HttpFieldIds)i, (const uint8_t*)cmd.chp_rewritten[i],
-                        strlen(cmd.chp_rewritten[i]));
+                        strlen(cmd.chp_rewritten[i]), change_bits);
                     delete [] cmd.chp_rewritten[i];
                     cmd.chp_rewritten[i] = nullptr;
                 }
@@ -350,7 +374,8 @@ void AppIdHttpSession::process_chp_buffers()
     }
 }
 
-int AppIdHttpSession::process_http_packet(AppidSessionDirection direction)
+int AppIdHttpSession::process_http_packet(AppidSessionDirection direction,
+    AppidChangeBits& change_bits)
 {
     snort::Profile http_profile_context(httpPerfStats);
     AppId service_id = APP_ID_NONE;
@@ -412,7 +437,7 @@ int AppIdHttpSession::process_http_packet(AppidSessionDirection direction)
     }
 
     if (!chp_finished || chp_hold_flow)
-        process_chp_buffers();
+        process_chp_buffers(change_bits);
 
     if (!skip_simple_detect)  // true if processCHP found match
     {
@@ -436,7 +461,7 @@ int AppIdHttpSession::process_http_packet(AppidSessionDirection direction)
                     if (vendor || vendorVersion)
                     {
                         asd.service.set_vendor(vendor);
-                        asd.service.set_version(vendorVersion);
+                        asd.service.set_version(vendorVersion, change_bits);
                         asd.scan_flags &= ~SCAN_HTTP_VENDOR_FLAG;
 
                         snort_free(vendor);
@@ -461,7 +486,7 @@ int AppIdHttpSession::process_http_packet(AppidSessionDirection direction)
             {
                 if (appidDebug->is_active() and asd.payload.get_id() != APP_ID_WEBDAV)
                     LogMessage("AppIdDbg %s Data is webdav\n", appidDebug->get_debug_session());
-                asd.set_payload_appid_data(APP_ID_WEBDAV, nullptr);
+                asd.set_payload_appid_data(APP_ID_WEBDAV, nullptr, change_bits);
             }
 
             // Scan User-Agent for Browser types or Skype
@@ -489,8 +514,8 @@ int AppIdHttpSession::process_http_packet(AppidSessionDirection direction)
                             appidDebug->get_debug_session(), app_name ? app_name : "unknown", client_id);
                     }
                 }
-                asd.set_service_appid_data(service_id, nullptr, nullptr);
-                asd.set_client_appid_data(client_id, version);
+                asd.set_service_appid_data(service_id, nullptr, nullptr, change_bits);
+                asd.set_client_appid_data(client_id, version, change_bits);
                 asd.scan_flags &= ~SCAN_HTTP_USER_AGENT_FLAG;
                 snort_free(version);
             }
@@ -509,7 +534,7 @@ int AppIdHttpSession::process_http_packet(AppidSessionDirection direction)
                         app_name ? app_name : "unknown",
                         payload_id);
                 }
-                asd.set_payload_appid_data((AppId)payload_id, nullptr);
+                asd.set_payload_appid_data((AppId)payload_id, nullptr, change_bits);
                 asd.scan_flags &= ~SCAN_HTTP_VIA_FLAG;
             }
         }
@@ -537,7 +562,7 @@ int AppIdHttpSession::process_http_packet(AppidSessionDirection direction)
                         LogMessage("AppIdDbg %s X is client %s (%d)\n", appidDebug->get_debug_session(),
                         app_name ? app_name : "unknown", appId);
                     }
-                    asd.set_client_appid_data(appId, version);
+                    asd.set_client_appid_data(appId, version, change_bits);
                 }
                 else
                 {
@@ -548,7 +573,7 @@ int AppIdHttpSession::process_http_packet(AppidSessionDirection direction)
                         LogMessage("AppIdDbg %s X service %s (%d)\n", appidDebug->get_debug_session(),
                             app_name ? app_name : "unknown", appId);
                     }
-                    asd.set_service_appid_data(appId, nullptr, version);
+                    asd.set_service_appid_data(appId, nullptr, version, change_bits);
                 }
                 asd.scan_flags &= ~SCAN_HTTP_XWORKINGWITH_FLAG;
             }
@@ -575,7 +600,7 @@ int AppIdHttpSession::process_http_packet(AppidSessionDirection direction)
                     app_name ? app_name : "unknown",
                     payload_id);
             }
-            asd.set_payload_appid_data((AppId)payload_id, nullptr);
+            asd.set_payload_appid_data((AppId)payload_id, nullptr, change_bits);
             asd.scan_flags &= ~SCAN_HTTP_CONTENT_TYPE_FLAG;
         }
 
@@ -603,7 +628,7 @@ int AppIdHttpSession::process_http_packet(AppidSessionDirection direction)
                             app_name ? app_name : "unknown",
                             client_id);
                     }
-                    asd.set_client_appid_data(client_id, nullptr);
+                    asd.set_client_appid_data(client_id, nullptr, change_bits);
                 }
 
                 if (asd.service.get_id() <= APP_ID_NONE)
@@ -617,7 +642,7 @@ int AppIdHttpSession::process_http_packet(AppidSessionDirection direction)
                             app_name ? app_name : "unknown",
                             service_id);
                     }
-                    asd.set_service_appid_data(service_id, nullptr, nullptr);
+                    asd.set_service_appid_data(service_id, nullptr, nullptr, change_bits);
                 }
 
                 // DO overwrite a previously-set data
@@ -629,8 +654,8 @@ int AppIdHttpSession::process_http_packet(AppidSessionDirection direction)
                         app_name ? app_name : "unknown",
                         payload_id);
                 }
-                asd.set_payload_appid_data((AppId)payload_id, version);
-                asd.set_referred_payload_app_id_data(referredPayloadAppId);
+                asd.set_payload_appid_data((AppId)payload_id, version, change_bits);
+                asd.set_referred_payload_app_id_data(referredPayloadAppId, change_bits);
             }
 
             asd.scan_flags &= ~SCAN_HTTP_HOST_URL_FLAG;
@@ -674,11 +699,13 @@ int AppIdHttpSession::process_http_packet(AppidSessionDirection direction)
 
 // FIXIT-H - Implement this function when (reconfigurable) XFF is supported.
 void AppIdHttpSession::update_http_xff_address(struct XffFieldValue* xff_fields,
-    uint32_t numXffFields)
+    uint32_t numXffFields, AppidChangeBits& change_bits)
 {
     UNUSED(xff_fields);
     UNUSED(numXffFields);
+    UNUSED(change_bits);
 #if 0
+    // When this is implemented, do change_bits.set(APPID_XFF_BIT) soon after xff_addr is changed
     static const char* defaultXffPrecedence[] =
     {
         HTTP_XFF_FIELD_X_FORWARDED_FOR,
@@ -759,7 +786,7 @@ void AppIdHttpSession::update_http_xff_address(struct XffFieldValue* xff_fields,
 #endif
 }
 
-void AppIdHttpSession::update_url()
+void AppIdHttpSession::update_url(AppidChangeBits& change_bits)
 {
     const std::string* host = meta_data[REQ_HOST_FID];
     const std::string* uri = meta_data[REQ_URI_FID];
@@ -768,6 +795,7 @@ void AppIdHttpSession::update_url()
         if (meta_data[MISC_URL_FID])
             delete meta_data[MISC_URL_FID];
         meta_data[MISC_URL_FID] = new std::string(std::string("http://") + *host + *uri);
+        change_bits.set(APPID_URL_BIT);
     }
 }
 
index 70b5bb59ba6b4ba858ab60c0b1250a798604eaa9..198608fa5a3ff334adf4c1fb4ee596726670420c 100644 (file)
@@ -26,6 +26,7 @@
 #include <utility>
 
 #include "flow/flow.h"
+#include "pub_sub/appid_events.h"
 #include "sfip/sf_ip.h"
 
 #include "appid_types.h"
@@ -87,10 +88,10 @@ public:
     AppIdHttpSession(AppIdSession&);
     virtual ~AppIdHttpSession();
 
-    int process_http_packet(AppidSessionDirection direction);
-    void update_http_xff_address(struct XffFieldValue* xff_fields, uint32_t numXffFields);
+    int process_http_packet(AppidSessionDirection direction, AppidChangeBits& change_bits);
+    void update_http_xff_address(struct XffFieldValue*, uint32_t, AppidChangeBits&);
 
-    void update_url();
+    void update_url(AppidChangeBits& change_bits);
 
     snort::SfIp* get_xff_addr()
     { return xff_addr; }
@@ -101,16 +102,24 @@ public:
     const char* get_cfield(HttpFieldIds id)
     { return meta_data[id] != nullptr ? meta_data[id]->c_str() : nullptr; }
 
-    void set_field(HttpFieldIds id, const std::string* str)
+    void set_field(HttpFieldIds id, const std::string* str, AppidChangeBits& change_bits)
     {
         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)
+    void set_field(HttpFieldIds id, const uint8_t* str, int32_t len, AppidChangeBits& change_bits)
     {
         delete meta_data[id];
-        meta_data[id] = str and len ? new std::string((const char*)str, len) : nullptr;
+        if (str and len)
+        {
+            meta_data[id] = new std::string((const char*)str, len);
+            set_http_change_bits(change_bits, id);
+        }
+        else
+            meta_data[id] = nullptr;
     }
 
     bool get_offset(int id, uint16_t& start, uint16_t& end)
@@ -184,8 +193,9 @@ protected:
 
     void init_chp_match_descriptor(ChpMatchDescriptor& cmd);
     int initial_chp_sweep(ChpMatchDescriptor&);
-    void process_chp_buffers();
+    void process_chp_buffers(AppidChangeBits&);
     void free_chp_matches(ChpMatchDescriptor& cmd, unsigned max_matches);
+    void set_http_change_bits(AppidChangeBits& change_bits, HttpFieldIds id);
 
     HttpPatternMatchers* http_matchers = nullptr;
 
index 455e4b1de7d2eb0b039560a45e6c87cf7b40c087..061765dbdffb9098482ef4a6c95009ff8a8788e5 100644 (file)
@@ -104,7 +104,7 @@ 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++;
 }
 
@@ -212,7 +212,7 @@ AppIdSession* AppIdSession::create_future_session(const Packet* ctrlPkt, const S
     return asd;
 }
 
-void AppIdSession::reinit_session_data()
+void AppIdSession::reinit_session_data(AppidChangeBits& change_bits)
 {
     misc_app_id = APP_ID_NONE;
 
@@ -223,7 +223,7 @@ void AppIdSession::reinit_session_data()
         referred_payload_app_id = tp_payload_app_id = APP_ID_NONE;
         clear_session_flags(APPID_SESSION_CONTINUE);
         if ( hsession )
-            hsession->set_field(MISC_URL_FID, nullptr);
+            hsession->set_field(MISC_URL_FID, nullptr, change_bits);
     }
 
     //service
@@ -316,7 +316,7 @@ void AppIdSession::sync_with_snort_protocol_id(AppId newAppId, Packet* p)
     }
 }
 
-void AppIdSession::check_app_detection_restart()
+void AppIdSession::check_app_detection_restart(AppidChangeBits& change_bits)
 {
     if (get_session_flags(APPID_SESSION_DECRYPTED) || !flow->is_proxied())
         return;
@@ -336,7 +336,7 @@ void AppIdSession::check_app_detection_restart()
         encrypted.client_id = pick_client_app_id();
         encrypted.misc_id = pick_misc_app_id();
         encrypted.referred_id = pick_referred_payload_app_id();
-        reinit_session_data();
+        reinit_session_data(change_bits);
         if (appidDebug->is_active())
             LogMessage("AppIdDbg %s SSL decryption is available, restarting app detection\n",
                 appidDebug->get_debug_session());
@@ -398,53 +398,52 @@ void AppIdSession::update_encrypted_app_id(AppId service_id)
     }
 }
 
-void AppIdSession::examine_ssl_metadata(Packet* p)
+void AppIdSession::examine_ssl_metadata(Packet* p, AppidChangeBits& change_bits)
 {
     int ret;
     AppId client_id = 0;
     AppId payload_id = 0;
+    const char* tls_str = tsession->get_tls_host();
 
-    if ((scan_flags & SCAN_SSL_HOST_FLAG) && tsession->tls_host)
+    if ((scan_flags & SCAN_SSL_HOST_FLAG) and tls_str)
     {
-        size_t size = strlen(tsession->tls_host);
-        if ((ret = ssl_scan_hostname((const uint8_t*)tsession->tls_host, size,
+        size_t size = strlen(tls_str);
+        if ((ret = ssl_scan_hostname((const uint8_t*)tls_str, size,
                 &client_id, &payload_id)))
         {
-            set_client_appid_data(client_id, nullptr);
-            set_payload_appid_data((AppId)payload_id, nullptr);
+            set_client_appid_data(client_id, nullptr, change_bits);
+            set_payload_appid_data((AppId)payload_id, nullptr, change_bits);
             setSSLSquelch(p, ret, (ret == 1 ? payload_id : client_id), inspector);
         }
         scan_flags &= ~SCAN_SSL_HOST_FLAG;
     }
-    if (tsession->tls_cname)
+    if ((tls_str = tsession->get_tls_cname()))
     {
-        size_t size = strlen(tsession->tls_cname);
-        if ((ret = ssl_scan_cname((const uint8_t*)tsession->tls_cname, size,
+        size_t size = strlen(tls_str);
+        if ((ret = ssl_scan_cname((const uint8_t*)tls_str, size,
                 &client_id, &payload_id)))
         {
-            set_client_appid_data(client_id, nullptr);
-            set_payload_appid_data((AppId)payload_id, nullptr);
+            set_client_appid_data(client_id, nullptr, change_bits);
+            set_payload_appid_data((AppId)payload_id, nullptr, change_bits);
             setSSLSquelch(p, ret, (ret == 1 ? payload_id : client_id), inspector);
         }
-        snort_free(tsession->tls_cname);
-        tsession->tls_cname = nullptr;
+        tsession->set_tls_cname(nullptr, 0);
     }
-    if (tsession->tls_orgUnit)
+    if ((tls_str = tsession->get_tls_org_unit()))
     {
-        size_t size = strlen(tsession->tls_orgUnit);
-        if ((ret = ssl_scan_cname((const uint8_t*)tsession->tls_orgUnit, size,
+        size_t size = strlen(tls_str);
+        if ((ret = ssl_scan_cname((const uint8_t*)tls_str, size,
                 &client_id, &payload_id)))
         {
-            set_client_appid_data(client_id, nullptr);
-            set_payload_appid_data((AppId)payload_id, nullptr);
+            set_client_appid_data(client_id, nullptr, change_bits);
+            set_payload_appid_data((AppId)payload_id, nullptr, change_bits);
             setSSLSquelch(p, ret, (ret == 1 ? payload_id : client_id), inspector);
         }
-        snort_free(tsession->tls_orgUnit);
-        tsession->tls_orgUnit = nullptr;
+        tsession->set_tls_org_unit(nullptr, 0);
     }
 }
 
-void AppIdSession::examine_rtmp_metadata()
+void AppIdSession::examine_rtmp_metadata(AppidChangeBits& change_bits)
 {
     AppId service_id = APP_ID_NONE;
     AppId client_id = APP_ID_NONE;
@@ -469,18 +468,18 @@ void AppIdSession::examine_rtmp_metadata()
         {
             /* do not overwrite a previously-set client or service */
             if (client.get_id() <= APP_ID_NONE)
-                set_client_appid_data(payload_id, nullptr);
+                set_client_appid_data(payload_id, nullptr, change_bits);
             if (service.get_id() <= APP_ID_NONE)
-                set_service_appid_data(service_id, nullptr, nullptr);
+                set_service_appid_data(service_id, nullptr, nullptr, change_bits);
 
             /* DO overwrite a previously-set data */
-            set_payload_appid_data((AppId)payload.get_id(), nullptr);
-            set_referred_payload_app_id_data(referred_payload_id);
+            set_payload_appid_data((AppId)payload.get_id(), nullptr, change_bits);
+            set_referred_payload_app_id_data(referred_payload_id, change_bits);
         }
     }
 }
 
-void AppIdSession::set_client_appid_data(AppId id, char* version)
+void AppIdSession::set_client_appid_data(AppId id, char* version, AppidChangeBits& change_bits)
 {
     if ( id <= APP_ID_NONE || id == APP_ID_HTTP )
         return;
@@ -495,19 +494,22 @@ void AppIdSession::set_client_appid_data(AppId id, char* version)
         client.set_id(id);
     }
 
-    client.set_version(version);
+    client.set_version(version, change_bits);
 }
 
-void AppIdSession::set_referred_payload_app_id_data(AppId id)
+void AppIdSession::set_referred_payload_app_id_data(AppId id, AppidChangeBits& change_bits)
 {
     if (id <= APP_ID_NONE)
         return;
 
     if (referred_payload_app_id != id)
+    {
         referred_payload_app_id = id;
+        change_bits.set(APPID_REFERRED_BIT);
+    }
 }
 
-void AppIdSession::set_payload_appid_data(AppId id, char* version)
+void AppIdSession::set_payload_appid_data(AppId id, char* version, AppidChangeBits& change_bits)
 {
     if ( id <= APP_ID_NONE )
         return;
@@ -515,10 +517,11 @@ void AppIdSession::set_payload_appid_data(AppId id, char* version)
     if ( app_info_mgr->get_priority(payload.get_id()) > app_info_mgr->get_priority(id) )
         return;
     payload.set_id(id);
-    payload.set_version(version);
+    payload.set_version(version, change_bits);
 }
 
-void AppIdSession::set_service_appid_data(AppId id, char* vendor, char* version)
+void AppIdSession::set_service_appid_data(AppId id, char* vendor, char* version,
+    AppidChangeBits& change_bits)
 {
     if (id <= APP_ID_NONE)
         return;
@@ -531,19 +534,14 @@ void AppIdSession::set_service_appid_data(AppId id, char* vendor, char* version)
         return;
     }
 
-    service.update(id, vendor, version);
+    service.update(id, vendor, version, change_bits);
 }
 
 void AppIdSession::free_tls_session_data()
 {
     if ( tsession )
     {
-        if (tsession->tls_host)
-            snort_free(tsession->tls_host);
-        if (tsession->tls_cname)
-            snort_free(tsession->tls_cname);
-        if (tsession->tls_orgUnit)
-            snort_free(tsession->tls_orgUnit);
+        tsession->free_data();
         snort_free(tsession);
         tsession = nullptr;
     }
@@ -774,12 +772,28 @@ AppId AppIdSession::pick_referred_payload_app_id()
 }
 
 void AppIdSession::set_application_ids(AppId service_id, AppId client_id,
-    AppId payload_id, AppId misc_id)
+    AppId payload_id, AppId misc_id, AppidChangeBits& change_bits)
 {
-    application_ids[APP_PROTOID_SERVICE] = service_id;
-    application_ids[APP_PROTOID_CLIENT] = client_id;
-    application_ids[APP_PROTOID_PAYLOAD] = payload_id;
-    application_ids[APP_PROTOID_MISC] = misc_id;
+    if (application_ids[APP_PROTOID_SERVICE] != service_id)
+    {
+        application_ids[APP_PROTOID_SERVICE] = service_id;
+        change_bits.set(APPID_SERVICE_BIT);
+    }
+    if (application_ids[APP_PROTOID_CLIENT] != client_id)
+    {
+        application_ids[APP_PROTOID_CLIENT] = client_id;
+        change_bits.set(APPID_CLIENT_BIT);
+    }
+    if (application_ids[APP_PROTOID_PAYLOAD] != payload_id)
+    {
+        application_ids[APP_PROTOID_PAYLOAD] = payload_id;
+        change_bits.set(APPID_PAYLOAD_BIT);
+    }
+    if (application_ids[APP_PROTOID_MISC] != misc_id)
+    {
+        application_ids[APP_PROTOID_MISC] = misc_id;
+        change_bits.set(APPID_MISC_BIT);
+    }
 }
 
 void AppIdSession::get_application_ids(AppId& service_id, AppId& client_id,
index be446f84be1c2d6bc33b787997ba41fe5d917915..1b677e4bac60650171c86a7eea6863d2e8a7528a 100644 (file)
 #include <string>
 #include <unordered_map>
 
-#include "detector_plugins/http_url_patterns.h"
+#include "pub_sub/appid_events.h"
+
 #include "app_info_table.h"
 #include "appid_api.h"
 #include "appid_app_descriptor.h"
 #include "appid_types.h"
 #include "application_ids.h"
+#include "detector_plugins/http_url_patterns.h"
 #include "length_app_cache.h"
 #include "service_state.h"
 
@@ -127,33 +129,57 @@ struct CommonAppIdData
 // FIXIT-L: make these const strings
 struct TlsSession
 {
-    char* tls_host = nullptr;
-    int tls_host_strlen = 0;     // FIXIT-M: not rvalue, remove
-    char* tls_cname = nullptr;
-    int tls_cname_strlen = 0;    // FIXIT-M: not rvalue, remove
-    char* tls_orgUnit = nullptr;
-    int tls_orgUnit_strlen = 0;  // FIXiT-M: not rvalue, remove
+    char* get_tls_host() { return tls_host; }
+
+    char* get_tls_cname() { return tls_cname; }
 
-    void set_tls_host(const char* new_tls_host, uint32_t len)
+    char* get_tls_org_unit() { return tls_org_unit; }
+
+    // Duplicate only if len > 0, otherwise simply set (i.e., own the argument)
+    void set_tls_host(const char* new_tls_host, uint32_t len, AppidChangeBits& change_bits)
     {
-        if (tls_host) snort_free(tls_host);
-        tls_host = snort::snort_strndup(new_tls_host,len);
-        tls_host_strlen = len;
+        if (tls_host)
+            snort_free(tls_host);
+        if (!new_tls_host)
+        {
+            tls_host = nullptr;
+            return;
+        }
+        tls_host = len? snort::snort_strndup(new_tls_host,len) : const_cast<char*>(new_tls_host);
+        change_bits.set(APPID_TLSHOST_BIT);
     }
 
     void set_tls_cname(const char* new_tls_cname, uint32_t len)
     {
-        if (tls_cname) snort_free(tls_cname);
-        tls_cname = snort::snort_strndup(new_tls_cname,len);
-        tls_cname_strlen = len;
+        if (tls_cname)
+            snort_free(tls_cname);
+        tls_cname = len? snort::snort_strndup(new_tls_cname,len) :
+            const_cast<char*>(new_tls_cname);
     }
 
     void set_tls_org_unit(const char* new_tls_org_unit, uint32_t len)
     {
-        if (tls_orgUnit) snort_free(tls_orgUnit);
-        tls_orgUnit = snort::snort_strndup(new_tls_org_unit,len);
-        tls_orgUnit_strlen = len;
+        if (tls_org_unit)
+            snort_free(tls_org_unit);
+        tls_org_unit = len? snort::snort_strndup(new_tls_org_unit,len) :
+            const_cast<char*>(new_tls_org_unit);
     }
+
+    void free_data()
+    {
+        if (tls_host)
+            snort_free(tls_host);
+        if (tls_cname)
+            snort_free(tls_cname);
+        if (tls_org_unit)
+            snort_free(tls_org_unit);
+        tls_host = tls_cname = tls_org_unit = nullptr;
+    }
+
+private:
+    char* tls_host = nullptr;
+    char* tls_cname = nullptr;
+    char* tls_org_unit = nullptr;
 };
 
 class AppIdSession : public snort::FlowData
@@ -274,7 +300,8 @@ public:
     AppId pick_client_app_id();
     AppId pick_payload_app_id();
     AppId pick_referred_payload_app_id();
-    void set_application_ids(AppId service, AppId client, AppId payload, AppId misc);
+    void set_application_ids(AppId service, AppId client, AppId payload, AppId misc,
+        AppidChangeBits& change_bits);
     void get_application_ids(AppId& service, AppId& client, AppId& payload, AppId& misc);
     void get_application_ids(AppId& service, AppId& client, AppId& payload);
     AppId get_application_ids_service();
@@ -283,14 +310,14 @@ public:
     AppId get_application_ids_misc();
 
     bool is_ssl_session_decrypted();
-    void examine_ssl_metadata(snort::Packet*);
-    void set_client_appid_data(AppId, char*);
-    void set_service_appid_data(AppId, char*, char*);
-    void set_referred_payload_app_id_data(AppId);
-    void set_payload_appid_data(AppId, char*);
-    void check_app_detection_restart();
+    void examine_ssl_metadata(snort::Packet*, AppidChangeBits& change_bits);
+    void set_client_appid_data(AppId, char*, AppidChangeBits& change_bits);
+    void set_service_appid_data(AppId, char*, char*, AppidChangeBits& change_bits);
+    void set_referred_payload_app_id_data(AppId, AppidChangeBits& change_bits);
+    void set_payload_appid_data(AppId, char*, AppidChangeBits& change_bits);
+    void check_app_detection_restart(AppidChangeBits& change_bits);
     void update_encrypted_app_id(AppId);
-    void examine_rtmp_metadata();
+    void examine_rtmp_metadata(AppidChangeBits& change_bits);
     void sync_with_snort_protocol_id(AppId, snort::Packet*);
     void stop_rna_service_inspection(snort::Packet*,  AppidSessionDirection);
 
@@ -332,7 +359,7 @@ private:
     AppIdHttpSession* hsession = nullptr;
     AppIdDnsSession* dsession = nullptr;
 
-    void reinit_session_data();
+    void reinit_session_data(AppidChangeBits& change_bits);
     void delete_session_data();
 
     static THREAD_LOCAL uint32_t appid_flow_data_id;
index 17b7523455df1cdfdb0bdbe764192da764202588..cab58eaa7fa91a1fee45265b7e8df4df020f786d 100644 (file)
@@ -177,7 +177,7 @@ short AppIdSessionApi::get_service_port()
 char* AppIdSessionApi::get_tls_host()
 {
     if (asd->tsession)
-        return asd->tsession->tls_host;
+        return asd->tsession->get_tls_host();
 
     return nullptr;
 }
index 7e55e741c79016dcc3b9383bd381ecef1acefe4e..a74d2c451192ee9a444ecaa5186df36cf17788b6 100644 (file)
@@ -228,7 +228,7 @@ int AimClientDetector::validate(AppIdDiscoveryArgs& args)
 
                 snprintf(version, sizeof(version), "%d.%d.%d", major, minor, lesser);
                 add_app(args.asd, APP_ID_AOL_INSTANT_MESSENGER, APP_ID_AOL_INSTANT_MESSENGER,
-                    version);
+                    version, args.change_bits);
             }
         }
     }
index 52aaee676f2d10a38420863e3b0117949a9508e4..540643b2231f965cf34917e0521eb7b8839a3784 100644 (file)
@@ -154,7 +154,7 @@ inprocess:
     return APPID_INPROCESS;
 
 done:
-    add_app(args.asd, APP_ID_BITTORRENT, APP_ID_BITTORRENT, nullptr);
+    add_app(args.asd, APP_ID_BITTORRENT, APP_ID_BITTORRENT, nullptr, args.change_bits);
     return APPID_SUCCESS;
 }
 
index 8e3addced025f43b0f886800965852aeaaa3eb9e..b2c8af034d586c93adb23b4b79f2b683ef3d730f 100644 (file)
@@ -200,7 +200,7 @@ inprocess:
     return APPID_INPROCESS;
 
 done:
-    add_app(args.asd, APP_ID_BITTORRENT, APP_ID_BITTRACKER_CLIENT, nullptr);
+    add_app(args.asd, APP_ID_BITTORRENT, APP_ID_BITTRACKER_CLIENT, nullptr, args.change_bits);
     return APPID_SUCCESS;
 }
 
index 8a6f845a85eb7e2f48dc47c1921bd3e4428c1c04..e3f80ed53b3e3e6d2c006c956801e4820d180747 100644 (file)
@@ -147,7 +147,7 @@ int MsnClientDetector::validate(AppIdDiscoveryArgs& args)
     return APPID_INPROCESS;
 
 done:
-    add_app(args.asd, APP_ID_MSN_MESSENGER, product_id, (char*)version);
+    add_app(args.asd, APP_ID_MSN_MESSENGER, product_id, (char*)version, args.change_bits);
     return APPID_SUCCESS;
 }
 
index 8d80997404e9c59064c9a18dd38a89b28836b474..29924b3eb36dd78c88a84473864e29da09578a5f 100644 (file)
@@ -285,7 +285,7 @@ int RtpClientDetector::validate(AppIdDiscoveryArgs& args)
         return APPID_INPROCESS;
     }
 
-    add_app(args.asd, APP_ID_RTP, APP_ID_RTP, nullptr);
+    add_app(args.asd, APP_ID_RTP, APP_ID_RTP, nullptr, args.change_bits);
     return APPID_SUCCESS;
 }
 
index d26539f933e00f4df89d1b12d381bf8fec554d71..608fd449ff76bd78405a508b02847a2751aed7fb 100644 (file)
@@ -568,7 +568,7 @@ int SshClientDetector::validate(AppIdDiscoveryArgs& args)
     if (sm_ret != APPID_SUCCESS)
         return sm_ret;
 
-    add_app(args.asd, APP_ID_SSH, fd->client_id, (const char*)fd->version);
+    add_app(args.asd, APP_ID_SSH, fd->client_id, (const char*)fd->version, args.change_bits);
     return APPID_SUCCESS;
 }
 
index 237590cf1059d9f566aafa555bf1dd1901b579e2..3f67ef58121b56edc4457d816b40960b9050b004 100644 (file)
@@ -169,7 +169,7 @@ inprocess:
     return APPID_INPROCESS;
 
 done:
-    add_app(args.asd, APP_ID_TIMBUKTU, APP_ID_TIMBUKTU, nullptr);
+    add_app(args.asd, APP_ID_TIMBUKTU, APP_ID_TIMBUKTU, nullptr, args.change_bits);
     return APPID_SUCCESS;
 }
 
index 612279505a2c2c8ff0c9e13c1417e3437e840400..e53ad25a3b1701047fdabd225e11c8eb55cb627c 100644 (file)
@@ -332,7 +332,7 @@ inprocess:
     return APPID_INPROCESS;
 
 done:
-    add_app(args.asd, APP_ID_ORACLE_TNS, APP_ID_ORACLE_DATABASE, fd->version);
+    add_app(args.asd, APP_ID_ORACLE_TNS, APP_ID_ORACLE_DATABASE, fd->version, args.change_bits);
     if (user_start && user_end && ((user_size = user_end - user_start) > 0))
     {
         /* we truncate extra long usernames */
index 3798eecee753f290557dedd63bd7a4f885348166..0bf3f09e3e625c4975eb7b7dc56405560b9232cb 100644 (file)
@@ -127,7 +127,7 @@ inprocess:
     return APPID_INPROCESS;
 
 done:
-    add_app(args.asd, APP_ID_VNC_RFB, APP_ID_VNC, (const char*)fd->version);
+    add_app(args.asd, APP_ID_VNC_RFB, APP_ID_VNC, (const char*)fd->version, args.change_bits);
     return APPID_SUCCESS;
 }
 
index d55b54542f8ff7f06555ece86105ffbaa9a39897..32d57619cf97262cf7c4d98392bf725a92635deb 100644 (file)
@@ -148,7 +148,7 @@ int YmDetector::validate(AppIdDiscoveryArgs& args)
     return APPID_INPROCESS;
 
 done:
-    add_app(args.asd, APP_ID_YAHOO, product_id, (char*)version);
+    add_app(args.asd, APP_ID_YAHOO, product_id, (char*)version, args.change_bits);
     return APPID_SUCCESS;
 }
 
index 2cd57004a69817e03b9b81aa6d911d5e872c5d0c..fcd48468b445c1ec791fe0a3ae4d339e5506a1a0 100644 (file)
@@ -294,13 +294,14 @@ int ClientDiscovery::get_detector_candidates_list(AppIdSession& asd, Packet* p,
     return APPID_SESSION_SUCCESS;
 }
 
-int ClientDiscovery::exec_client_detectors(AppIdSession& asd, Packet* p, AppidSessionDirection direction)
+int ClientDiscovery::exec_client_detectors(AppIdSession& asd, Packet* p,
+    AppidSessionDirection direction, AppidChangeBits& change_bits)
 {
     int ret = APPID_INPROCESS;
 
     if (asd.client_detector != nullptr)
     {
-        AppIdDiscoveryArgs disco_args(p->data, p->dsize, direction, asd, p);
+        AppIdDiscoveryArgs disco_args(p->data, p->dsize, direction, asd, p, change_bits);
         ret = asd.client_detector->validate(disco_args);
         if (appidDebug->is_active())
             LogMessage("AppIdDbg %s %s client detector returned %s (%d)\n",
@@ -311,7 +312,7 @@ int ClientDiscovery::exec_client_detectors(AppIdSession& asd, Packet* p, AppidSe
     {
         for ( auto kv = asd.client_candidates.begin(); kv != asd.client_candidates.end(); )
         {
-            AppIdDiscoveryArgs disco_args(p->data, p->dsize, direction, asd, p);
+            AppIdDiscoveryArgs disco_args(p->data, p->dsize, direction, asd, p, change_bits);
             int result = kv->second->validate(disco_args);
             if (appidDebug->is_active())
                 LogMessage("AppIdDbg %s %s client candidate returned %s (%d)\n",
@@ -336,7 +337,8 @@ int ClientDiscovery::exec_client_detectors(AppIdSession& asd, Packet* p, AppidSe
     return ret;
 }
 
-bool ClientDiscovery::do_client_discovery(AppIdSession& asd, Packet* p, AppidSessionDirection direction)
+bool ClientDiscovery::do_client_discovery(AppIdSession& asd, Packet* p,
+    AppidSessionDirection direction, AppidChangeBits& change_bits)
 {
     bool isTpAppidDiscoveryDone = false;
     AppInfoTableEntry* entry;
@@ -403,12 +405,12 @@ bool ClientDiscovery::do_client_discovery(AppIdSession& asd, Packet* p, AppidSes
         {
             /* get out if we've already tried to validate a client app */
             if (!asd.is_client_detected() )
-                ret = exec_client_detectors(asd, p, direction);
+                ret = exec_client_detectors(asd, p, direction, change_bits);
         }
         else if ( asd.service_disco_state != APPID_DISCO_STATE_STATEFUL
             && asd.get_session_flags(APPID_SESSION_CLIENT_GETS_SERVER_PACKETS) )
         {
-            ret = exec_client_detectors(asd, p, direction);
+            ret = exec_client_detectors(asd, p, direction, change_bits);
         }
 
         switch (ret)
@@ -431,11 +433,11 @@ bool ClientDiscovery::do_client_discovery(AppIdSession& asd, Packet* p, AppidSes
             {
                 /* get out if we've already tried to validate a client app */
                 if (!asd.is_client_detected())
-                    ret = exec_client_detectors(asd, p, direction);
+                    ret = exec_client_detectors(asd, p, direction, change_bits);
             }
             else if ( asd.service_disco_state != APPID_DISCO_STATE_STATEFUL
                 && asd.get_session_flags(APPID_SESSION_CLIENT_GETS_SERVER_PACKETS) )
-                ret = exec_client_detectors(asd, p, direction);
+                ret = exec_client_detectors(asd, p, direction, change_bits);
 
             if ( ret < 0 )
             {
index 4d197063d466d3f1ece395afb30665dc09c4f2e2..83d9eeafbd7426d332c033956da65a6dbdd0310f 100644 (file)
@@ -50,12 +50,14 @@ public:
 
     void finalize_client_plugins();
     void release_thread_resources();
-    bool do_client_discovery(AppIdSession&, snort::Packet*, AppidSessionDirection direction);
+    bool do_client_discovery(AppIdSession&, snort::Packet*,
+        AppidSessionDirection direction, AppidChangeBits& change_bits);
 
 private:
     ClientDiscovery(AppIdInspector& ins);
     void initialize() override;
-    int exec_client_detectors(AppIdSession&, snort::Packet*, AppidSessionDirection direction);
+    int exec_client_detectors(AppIdSession&, snort::Packet*,
+        AppidSessionDirection direction, AppidChangeBits& change_bits);
     ClientAppMatch* find_detector_candidates(const snort::Packet* pkt, IpProtocol);
     void create_detector_candidates_list(AppIdSession&, snort::Packet*);
     int get_detector_candidates_list(AppIdSession&, snort::Packet*, AppidSessionDirection direction);
index 1dbde4e014d4c8649483605b793cd28f9a7c6534..850a0ffe41154e6b51b1d8a80abd264fe194c090 100644 (file)
@@ -627,7 +627,7 @@ udp_done:
     case APPID_SUCCESS:
 success:
         args.asd.set_session_flags(APPID_SESSION_CONTINUE);
-        return add_service(args.asd, args.pkt, args.dir, APP_ID_DNS);
+        return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_DNS);
 
     case APPID_INVALID_CLIENT:
 invalid:
@@ -641,7 +641,7 @@ nomatch:
 
     case APPID_INPROCESS:
 inprocess:
-        add_app(args.asd, APP_ID_NONE, APP_ID_DNS, nullptr);
+        add_app(args.asd, APP_ID_NONE, APP_ID_DNS, nullptr, args.change_bits);
         service_inprocess(args.asd, args.pkt, args.dir);
         return APPID_INPROCESS;
 
@@ -723,7 +723,7 @@ tcp_done:
 
 success:
     args.asd.set_session_flags(APPID_SESSION_CONTINUE);
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_DNS);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_DNS);
 
 not_compatible:
     incompatible_data(args.asd, args.pkt, args.dir);
@@ -734,7 +734,7 @@ fail:
     return APPID_NOMATCH;
 
 inprocess:
-    add_app(args.asd, APP_ID_NONE, APP_ID_DNS, nullptr);
+    add_app(args.asd, APP_ID_NONE, APP_ID_DNS, nullptr, args.change_bits);
     service_inprocess(args.asd, args.pkt, args.dir);
     return APPID_INPROCESS;
 }
index 659ce24a6dface6d6d794d4262114236db1fd386..9afe1dbafc9df0dfafc89b149f6c8d8d8f95f08d 100644 (file)
@@ -62,9 +62,10 @@ HttpClientDetector::HttpClientDetector(ClientDiscovery* cdm)
 
 int HttpClientDetector::validate(AppIdDiscoveryArgs& args)
 {
-    add_app(args.asd, APP_ID_HTTP, APP_ID_HTTP + GENERIC_APP_OFFSET, nullptr);
+    add_app(args.asd, APP_ID_HTTP, APP_ID_HTTP + GENERIC_APP_OFFSET, nullptr, args.change_bits);
     args.asd.client_disco_state = APPID_DISCO_STATE_FINISHED;
-    http_service_detector->add_service(args.asd, args.pkt, args.dir, APP_ID_HTTP);
+    http_service_detector->add_service(args.change_bits, args.asd, args.pkt,
+        args.dir, APP_ID_HTTP);
     args.asd.service_disco_state = APPID_DISCO_STATE_FINISHED;
     args.asd.set_session_flags(APPID_SESSION_CLIENT_DETECTED | APPID_SESSION_SERVICE_DETECTED);
     args.asd.clear_session_flags(APPID_SESSION_CONTINUE);
index e71f603517a251edaaea7faf09927528d24e76d9..e21097007fd65c16ec08b148af1b0be4e184cdca 100644 (file)
@@ -683,7 +683,7 @@ int ImapClientDetector::validate(AppIdDiscoveryArgs& args)
                                 fd->count++;
                                 if (fd->count == MIN_CMDS)
                                 {
-                                    add_app(args.asd, APP_ID_IMAP, APP_ID_IMAP, nullptr);
+                                    add_app(args.asd, APP_ID_IMAP, APP_ID_IMAP, nullptr, args.change_bits);
                                     fd->detected = 1;
                                     if (fd->got_user)
                                     {
@@ -728,7 +728,7 @@ int ImapClientDetector::validate(AppIdDiscoveryArgs& args)
                                 fd->count++;
                                 if (fd->count == MIN_CMDS)
                                 {
-                                    add_app(args.asd, APP_ID_IMAP, APP_ID_IMAP, nullptr);
+                                    add_app(args.asd, APP_ID_IMAP, APP_ID_IMAP, nullptr, args.change_bits);
                                     fd->detected = 1;
                                     if (fd->got_user)
                                     {
@@ -777,7 +777,7 @@ int ImapClientDetector::validate(AppIdDiscoveryArgs& args)
                 fd->count++;
                 if (fd->count == MIN_CMDS)
                 {
-                    add_app(args.asd, APP_ID_IMAP, APP_ID_IMAP, nullptr);
+                    add_app(args.asd, APP_ID_IMAP, APP_ID_IMAP, nullptr, args.change_bits);
                     fd->detected = 1;
                     if (fd->got_user)
                     {
@@ -799,7 +799,7 @@ int ImapClientDetector::validate(AppIdDiscoveryArgs& args)
             fd->count++;
             if (fd->count == MIN_CMDS)
             {
-                add_app(args.asd, APP_ID_IMAP, APP_ID_IMAP, nullptr);
+                add_app(args.asd, APP_ID_IMAP, APP_ID_IMAP, nullptr, args.change_bits);
                 fd->detected = 1;
                 if (fd->got_user)
                 {
@@ -883,10 +883,10 @@ int ImapServiceDetector::validate(AppIdDiscoveryArgs& args)
     {
         if ((id->flags & IMAP_FLAG_RESULT_OK) &&
             dd->client.state == IMAP_CLIENT_STATE_STARTTLS_CMD)
-            return add_service(args.asd, args.pkt, args.dir, APP_ID_IMAPS);
+            return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_IMAPS);
 
         if (id->count >= IMAP_COUNT_THRESHOLD && !args.asd.is_service_detected())
-            return add_service(args.asd, args.pkt, args.dir, APP_ID_IMAP);
+            return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_IMAP);
     }
     else if (!args.asd.is_service_detected())
     {
index bc94cff99d5514e83e0500d4c2ab28875ccc06d6..acc3b2d3d04268e2b7eb2fc10b43a8f2c1616ab0 100644 (file)
@@ -115,7 +115,8 @@ static KerberosClientDetector* krb_client_detector;
 static KerberosServiceDetector* krb_service_detector;
 
 static int krb_walk_server_packet(KRBState* krbs, const uint8_t* s, const uint8_t* end,
-    AppIdSession& asd, snort::Packet* pkt, const AppidSessionDirection dir, const char* reqCname)
+    AppIdSession& asd, snort::Packet* pkt, const AppidSessionDirection dir,
+    const char* reqCname, AppidChangeBits& change_bits)
 {
     static const uint8_t KRB_SERVER_VERSION[] = "\x0a0\x003\x002\x001";
     static const uint8_t KRB_SERVER_TYPE[] = "\x0a1\x003\x002\x001";
@@ -410,7 +411,7 @@ static int krb_walk_server_packet(KRBState* krbs, const uint8_t* s, const uint8_
         /*end of server response message */
         if (krbs->flags & KRB_FLAG_SERVICE_DETECTED)
             if (!asd.is_service_detected() && pkt)
-                krb_service_detector->add_service(asd, pkt, dir, APP_ID_KERBEROS,
+                krb_service_detector->add_service(change_bits, asd, pkt, dir, APP_ID_KERBEROS,
                     nullptr, krbs->ver, nullptr);
 
         if (krbs->flags & KRB_FLAG_AUTH_FAILED)
@@ -500,8 +501,8 @@ int KerberosServiceDetector::validate(AppIdDiscoveryArgs& args)
             return APPID_SUCCESS;
     }
 
-    if (krb_walk_server_packet(&fd->svr_state, s, end, args.asd, args.pkt, args.dir, fd->clnt_state.cname) ==
-        KRB_FAILED)
+    if (krb_walk_server_packet(&fd->svr_state, s, end, args.asd, args.pkt, args.dir,
+        fd->clnt_state.cname, args.change_bits) == KRB_FAILED)
     {
         if (!args.asd.is_service_detected())
         {
@@ -551,7 +552,7 @@ KerberosClientDetector::KerberosClientDetector(ClientDiscovery* cdm)
 
 
 int KerberosClientDetector::krb_walk_client_packet(KRBState* krbs, const uint8_t* s,
-    const  uint8_t* end, AppIdSession& asd)
+    const  uint8_t* end, AppIdSession& asd, AppidChangeBits& change_bits)
 {
     static const uint8_t KRB_CLIENT_VERSION[] = "\x0a1\x003\x002\x001";
     static const uint8_t KRB_CLIENT_TYPE[] = "\x0a2\x003\x002\x001";
@@ -660,7 +661,7 @@ int KerberosClientDetector::krb_walk_client_packet(KRBState* krbs, const uint8_t
                 {
                     if (!krbs->added)
                     {
-                        add_app(asd, APP_ID_KERBEROS, APP_ID_KERBEROS, krbs->ver);
+                        add_app(asd, APP_ID_KERBEROS, APP_ID_KERBEROS, krbs->ver, change_bits);
                         krbs->added = 1;
                     }
                     krbs->state = KRB_STATE_APP;
@@ -906,7 +907,7 @@ int KerberosClientDetector::validate(AppIdDiscoveryArgs& args)
 
     if (args.dir == APP_ID_FROM_INITIATOR)
     {
-        if (krb_walk_client_packet(&fd->clnt_state, s, end, args.asd) == KRB_FAILED)
+        if (krb_walk_client_packet(&fd->clnt_state, s, end, args.asd, args.change_bits) == KRB_FAILED)
         {
             args.asd.set_client_detected();
             args.asd.clear_session_flags(APPID_SESSION_CLIENT_GETS_SERVER_PACKETS);
@@ -914,7 +915,7 @@ int KerberosClientDetector::validate(AppIdDiscoveryArgs& args)
         }
     }
     else if (krb_walk_server_packet(&fd->svr_state, s, end, args.asd, nullptr, args.dir,
-        fd->clnt_state.cname) == KRB_FAILED)
+        fd->clnt_state.cname, args.change_bits) == KRB_FAILED)
     {
         args.asd.clear_session_flags(APPID_SESSION_CLIENT_GETS_SERVER_PACKETS);
     }
index 7dcbf6a1b7106082fd2444a1e0f7c02cf68fb5e2..06acf52b5cf7c5f758c60ef10520c58639ec21c8 100644 (file)
@@ -39,7 +39,8 @@ public:
     bool failed_login = false;
 
 private:
-    int krb_walk_client_packet(KRBState*, const uint8_t*, const uint8_t*, AppIdSession&);
+    int krb_walk_client_packet(KRBState*, const uint8_t*, const uint8_t*,
+        AppIdSession&, AppidChangeBits&);
 };
 
 class KerberosServiceDetector : public ServiceDetector
index da6c8c0871c909d19ec4dda94a808cfd105787c3..37fce1d74ec258098579d6634f3fb9546e74bcd1 100644 (file)
@@ -490,7 +490,7 @@ int PatternServiceDetector::validate(AppIdDiscoveryArgs& args)
         return APPID_NOMATCH;
     }
 
-    return add_service(args.asd, args.pkt, args.dir, id);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, id);
 }
 
 PatternClientDetector::PatternClientDetector(ClientDiscovery* cdm)
@@ -548,7 +548,7 @@ int PatternClientDetector::validate(AppIdDiscoveryArgs& args)
     if (!id)
         return APPID_EINVALID;
 
-    add_app(args.asd, id, id, nullptr);
+    add_app(args.asd, id, id, nullptr, args.change_bits);
     return APPID_SUCCESS;
 }
 
index 1448f20a3526aa99294ecc12193aa3ed914fb091..dd724ea3b6f499271f8ed08b92be7bd3c5f094e1 100644 (file)
@@ -283,7 +283,7 @@ static int pop3_check_line(const uint8_t** data, const uint8_t* end)
 }
 
 static int pop3_server_validate(POP3DetectorData* dd, const uint8_t* data, uint16_t size,
-    AppIdSession& asd, int server)
+    AppIdSession& asd, int server, AppidChangeBits& change_bits)
 {
     ServicePOP3Data* pd = &dd->server;
     const uint8_t* begin = nullptr;
@@ -337,7 +337,7 @@ static int pop3_server_validate(POP3DetectorData* dd, const uint8_t* data, uint1
                 // we are potentially overriding the APP_ID_POP3 assessment that was made earlier.
                 asd.set_session_flags(APPID_SESSION_ENCRYPTED);
                 asd.clear_session_flags(APPID_SESSION_CLIENT_GETS_SERVER_PACKETS);
-                pop3_client_detector->add_app(asd, APP_ID_POP3S, APP_ID_POP3S, nullptr);
+                pop3_client_detector->add_app(asd, APP_ID_POP3S, APP_ID_POP3S, nullptr, change_bits);
             }
         }
         else if (dd->client.username) // possible only with non-TLS auth, therefore APP_ID_POP3
@@ -572,7 +572,7 @@ int Pop3ClientDetector::validate(AppIdDiscoveryArgs& args)
 
     if (args.dir == APP_ID_FROM_RESPONDER)
     {
-        if (pop3_server_validate(dd, args.data, args.size, args.asd, 0))
+        if (pop3_server_validate(dd, args.data, args.size, args.asd, 0, args.change_bits))
             args.asd.clear_session_flags(APPID_SESSION_CLIENT_GETS_SERVER_PACKETS);
         return APPID_INPROCESS;
     }
@@ -709,7 +709,7 @@ int Pop3ClientDetector::validate(AppIdDiscoveryArgs& args)
             if (pattern_index >= PATTERN_POP3_OTHER)
             {
                 // Still in non-secure mode and received a TRANSACTION-state command: POP3 found
-                add_app(args.asd, APP_ID_POP3, APP_ID_POP3, nullptr);
+                add_app(args.asd, APP_ID_POP3, APP_ID_POP3, nullptr, args.change_bits);
                 fd->detected = 1;
             }
             else
@@ -787,14 +787,14 @@ int Pop3ServiceDetector::validate(AppIdDiscoveryArgs& args)
             return APPID_SUCCESS;
     }
 
-    if (!pop3_server_validate(dd, args.data, args.size, args.asd, 1))
+    if (!pop3_server_validate(dd, args.data, args.size, args.asd, 1, args.change_bits))
     {
         if (pd->count >= POP3_COUNT_THRESHOLD
             && !args.asd.is_service_detected())
         {
             add_service_consume_subtype(args.asd, args.pkt, args.dir,
                 dd->client.state == POP3_CLIENT_STATE_STLS_CMD ? APP_ID_POP3S : APP_ID_POP3,
-                pd->vendor, pd->version[0] ? pd->version : nullptr, pd->subtype);
+                pd->vendor, pd->version[0] ? pd->version : nullptr, pd->subtype, args.change_bits);
             pd->subtype = nullptr;
             return APPID_SUCCESS;
         }
index 03315f904e60c882304811913c2aaf0fa2a66175..1b870d11f69a723ce55b374551766d0dc4920c01 100644 (file)
@@ -473,11 +473,14 @@ void SipEventHandler::handle(DataEvent& event, Flow* flow)
             client->get_handler().get_inspector());
     }
 
-    client_handler(sip_event, *asd);
-    service_handler(sip_event, *asd);
+    AppidChangeBits change_bits;
+    client_handler(sip_event, *asd, change_bits);
+    service_handler(sip_event, *asd, change_bits);
+    AppIdDiscovery::publish_appid_event(change_bits, flow);
 }
 
-void SipEventHandler::client_handler(SipEvent& sip_event, AppIdSession& asd)
+void SipEventHandler::client_handler(SipEvent& sip_event, AppIdSession& asd,
+    AppidChangeBits& change_bits)
 {
     AppId ClientAppId = APP_ID_SIP;
     char* clientVersion = nullptr;
@@ -529,13 +532,14 @@ void SipEventHandler::client_handler(SipEvent& sip_event, AppIdSession& asd)
 
 success:
     if( !asd.is_client_detected() )
-        client->add_app(asd, APP_ID_SIP, ClientAppId, clientVersion);
+        client->add_app(asd, APP_ID_SIP, ClientAppId, clientVersion, change_bits);
 
     if ( !fd->user_name.empty() )
         client->add_user(asd, fd->user_name.c_str(), APP_ID_SIP, true);
 }
 
-void SipEventHandler::service_handler(SipEvent& sip_event, AppIdSession& asd)
+void SipEventHandler::service_handler(SipEvent& sip_event, AppIdSession& asd,
+    AppidChangeBits& change_bits)
 {
     ServiceSIPData* ss = (ServiceSIPData*)service->data_get(asd);
     if ( !ss )
@@ -575,7 +579,7 @@ void SipEventHandler::service_handler(SipEvent& sip_event, AppIdSession& asd)
         if ( !asd.is_service_detected() )
         {
             asd.set_session_flags(APPID_SESSION_CONTINUE);
-            service->add_service(asd, sip_event.get_packet(), direction, APP_ID_SIP,
+            service->add_service(change_bits, asd, sip_event.get_packet(), direction, APP_ID_SIP,
                 ss->vendor[0] ? ss->vendor : nullptr);
             if (appidDebug->is_active())
                 LogMessage("AppIdDbg %s Sip service detected. Setting APPID_SESSION_CONTINUE flag\n",
index 4bd2d740f083e58c3c6bf423fee4c0293df472eb..0a42bccde8b66e512358f2201dee300ee5197bbd 100644 (file)
@@ -106,8 +106,8 @@ public:
 
 private:
     SipEventHandler() = default;
-    void client_handler(SipEvent&, AppIdSession&);
-    void service_handler(SipEvent&, AppIdSession&);
+    void client_handler(SipEvent&, AppIdSession&, AppidChangeBits&);
+    void service_handler(SipEvent&, AppIdSession&, AppidChangeBits&);
 
     static SipUdpClientDetector* client;
     static SipServiceDetector* service;
index b4a6f43662ff24dda8fdd51336b096054e35a33f..bbffdff4f251eb6e95f07421ea03368c3ac16dac 100644 (file)
@@ -183,7 +183,7 @@ SmtpClientDetector::SmtpClientDetector(ClientDiscovery* cdm)
 // FIXIT-M - refactor this to reduce the number of function parameters
 int SmtpClientDetector::extract_version_and_add_client_app(AppId clientId, const int prefix_len,
     const uint8_t* product, const uint8_t* product_end, ClientSMTPData* const client_data,
-    AppIdSession& asd, AppId appId)
+    AppIdSession& asd, AppId appId, AppidChangeBits& change_bits)
 {
     uint8_t* v_end = client_data->version + MAX_VERSION_SIZE - 1;
 
@@ -196,7 +196,7 @@ int SmtpClientDetector::extract_version_and_add_client_app(AppId clientId, const
     for (v = client_data->version; v < v_end && p < product_end; v++,p++)
         *v = *p;
     *v = 0;
-    add_app(asd, appId, clientId, (char*)client_data->version);
+    add_app(asd, appId, clientId, (char*)client_data->version, change_bits);
     return 0;
 }
 
@@ -206,7 +206,7 @@ int SmtpClientDetector::extract_version_and_add_client_app(AppId clientId, const
  *  Returns 0 if a recognized product is found.  Otherwise returns 1.
  */
 int SmtpClientDetector::identify_client_version(ClientSMTPData* const fd, const uint8_t* product,
-    const uint8_t* data_end, AppIdSession& asd, snort::Packet*)
+    const uint8_t* data_end, AppIdSession& asd, snort::Packet*, AppidChangeBits& change_bits)
 {
     const uint8_t* p;
     AppId appId = APP_ID_SMTP;
@@ -227,7 +227,7 @@ int SmtpClientDetector::identify_client_version(ClientSMTPData* const fd, const
                 if (p >= data_end || *p != ' ')
                     return 1;
                 return extract_version_and_add_client_app(APP_ID_OUTLOOK,
-                    2, p, data_end, fd, asd, appId);
+                    2, p, data_end, fd, asd, appId, change_bits);
             }
             else if (*p == ' ')
             {
@@ -235,12 +235,12 @@ int SmtpClientDetector::identify_client_version(ClientSMTPData* const fd, const
                 if (data_end-p >= (int)sizeof(EXPRESS) && memcmp(p, EXPRESS, sizeof(EXPRESS)-1) == 0)
                 {
                     return extract_version_and_add_client_app(APP_ID_OUTLOOK_EXPRESS,
-                        sizeof(EXPRESS), p, data_end, fd, asd, appId);
+                        sizeof(EXPRESS), p, data_end, fd, asd, appId, change_bits);
                 }
                 else if (data_end-p >= (int)sizeof(IMO) && memcmp(p, IMO, sizeof(IMO)-1) == 0)
                 {
                     return extract_version_and_add_client_app(APP_ID_OUTLOOK,
-                        sizeof(IMO), p, data_end, fd, asd, appId);
+                        sizeof(IMO), p, data_end, fd, asd, appId, change_bits);
                 }
             }
         }
@@ -249,13 +249,13 @@ int SmtpClientDetector::identify_client_version(ClientSMTPData* const fd, const
         sizeof(APP_SMTP_EVOLUTION)-1) == 0)
     {
         return extract_version_and_add_client_app(APP_ID_EVOLUTION,
-            sizeof(APP_SMTP_EVOLUTION), product, data_end, fd, asd, appId);
+            sizeof(APP_SMTP_EVOLUTION), product, data_end, fd, asd, appId, change_bits);
     }
     else if (len >= sizeof(APP_SMTP_LOTUS_NOTES) && memcmp(product, APP_SMTP_LOTUS_NOTES,
         sizeof(APP_SMTP_LOTUS_NOTES)-1) == 0)
     {
         return extract_version_and_add_client_app(APP_ID_LOTUS_NOTES,
-            sizeof(APP_SMTP_LOTUS_NOTES), product, data_end, fd, asd, appId);
+            sizeof(APP_SMTP_LOTUS_NOTES), product, data_end, fd, asd, appId, change_bits);
     }
     else if (len >= sizeof(APP_SMTP_APPLEMAIL) && memcmp(product, APP_SMTP_APPLEMAIL,
         sizeof(APP_SMTP_APPLEMAIL)-1) == 0)
@@ -271,50 +271,50 @@ int SmtpClientDetector::identify_client_version(ClientSMTPData* const fd, const
         }
         *v = 0;
 
-        add_app(asd, appId, APP_ID_APPLE_EMAIL, (char*)fd->version);
+        add_app(asd, appId, APP_ID_APPLE_EMAIL, (char*)fd->version, change_bits);
         return 0;
     }
     else if (len >= sizeof(APP_SMTP_EUDORA) && memcmp(product, APP_SMTP_EUDORA,
         sizeof(APP_SMTP_EUDORA)-1) == 0)
     {
         return extract_version_and_add_client_app(APP_ID_EUDORA,
-            sizeof(APP_SMTP_EUDORA), product, data_end, fd, asd, appId);
+            sizeof(APP_SMTP_EUDORA), product, data_end, fd, asd, appId, change_bits);
     }
     else if (len >= sizeof(APP_SMTP_EUDORAPRO) && memcmp(product, APP_SMTP_EUDORAPRO,
         sizeof(APP_SMTP_EUDORAPRO)-1) == 0)
     {
         return extract_version_and_add_client_app(APP_ID_EUDORA_PRO,
-            sizeof(APP_SMTP_EUDORAPRO), product, data_end, fd, asd, appId);
+            sizeof(APP_SMTP_EUDORAPRO), product, data_end, fd, asd, appId, change_bits);
     }
     else if (len >= sizeof(APP_SMTP_AOL) && memcmp(product, APP_SMTP_AOL,
         sizeof(APP_SMTP_AOL)-1) == 0)
     {
         return extract_version_and_add_client_app(APP_ID_AOL_EMAIL,
-            sizeof(APP_SMTP_AOL), product, data_end, fd, asd, appId);
+            sizeof(APP_SMTP_AOL), product, data_end, fd, asd, appId, change_bits);
     }
     else if (len >= sizeof(APP_SMTP_MUTT) && memcmp(product, APP_SMTP_MUTT,
         sizeof(APP_SMTP_MUTT)-1) == 0)
     {
         return extract_version_and_add_client_app(APP_ID_MUTT,
-            sizeof(APP_SMTP_MUTT), product, data_end, fd, asd, appId);
+            sizeof(APP_SMTP_MUTT), product, data_end, fd, asd, appId, change_bits);
     }
     else if (len >= sizeof(APP_SMTP_KMAIL) && memcmp(product, APP_SMTP_KMAIL,
         sizeof(APP_SMTP_KMAIL)-1) == 0)
     {
         return extract_version_and_add_client_app(APP_ID_KMAIL,
-            sizeof(APP_SMTP_KMAIL), product, data_end, fd, asd, appId);
+            sizeof(APP_SMTP_KMAIL), product, data_end, fd, asd, appId, change_bits);
     }
     else if (len >= sizeof(APP_SMTP_THUNDERBIRD) && memcmp(product, APP_SMTP_THUNDERBIRD,
         sizeof(APP_SMTP_THUNDERBIRD)-1) == 0)
     {
         return extract_version_and_add_client_app(APP_ID_THUNDERBIRD,
-            sizeof(APP_SMTP_THUNDERBIRD), product, data_end, fd, asd, appId);
+            sizeof(APP_SMTP_THUNDERBIRD), product, data_end, fd, asd, appId, change_bits);
     }
     else if (len >= sizeof(APP_SMTP_MTHUNDERBIRD) && memcmp(product, APP_SMTP_MTHUNDERBIRD,
         sizeof(APP_SMTP_MTHUNDERBIRD)-1) == 0)
     {
         return extract_version_and_add_client_app(APP_ID_THUNDERBIRD,
-            sizeof(APP_SMTP_MTHUNDERBIRD), product, data_end, fd, asd, appId);
+            sizeof(APP_SMTP_MTHUNDERBIRD), product, data_end, fd, asd, appId, change_bits);
     }
     else if (len >= sizeof(APP_SMTP_MOZILLA) && memcmp(product, APP_SMTP_MOZILLA,
         sizeof(APP_SMTP_MOZILLA)-1) == 0)
@@ -329,7 +329,7 @@ int SmtpClientDetector::identify_client_version(ClientSMTPData* const fd, const
                 {
                     return extract_version_and_add_client_app(
                         APP_ID_THUNDERBIRD, sizeof(APP_SMTP_THUNDERBIRD_SHORT),
-                        p, data_end, fd, asd, appId);
+                        p, data_end, fd, asd, appId, change_bits);
                 }
             }
         }
@@ -387,7 +387,7 @@ int SmtpClientDetector::validate(AppIdDiscoveryArgs& args)
                 /* Because we can't see any further info without decryption we settle for
                    plain APP_ID_SMTPS instead of perhaps finding data that would make calling
                    ExtractVersion() worthwhile, So set the appid and call it good. */
-                add_app(args.asd, APP_ID_SMTPS, APP_ID_SMTPS, nullptr);
+                add_app(args.asd, APP_ID_SMTPS, APP_ID_SMTPS, nullptr, args.change_bits);
                 goto done;
             }
         }
@@ -517,7 +517,7 @@ int SmtpClientDetector::validate(AppIdDiscoveryArgs& args)
                     (len >= 1 && args.data[1] == '\n') ||
                     (len >= 2 && args.data[1] == '\r' && args.data[2] == '\n'))
                 {
-                    add_app(args.asd, APP_ID_SMTP, APP_ID_SMTP, nullptr);
+                    add_app(args.asd, APP_ID_SMTP, APP_ID_SMTP, nullptr, args.change_bits);
                     goto done;
                 }
             }
@@ -545,7 +545,7 @@ int SmtpClientDetector::validate(AppIdDiscoveryArgs& args)
             {
                 if (fd->headerline && fd->pos)
                 {
-                    identify_client_version(fd, fd->headerline, fd->headerline + fd->pos, args.asd, args.pkt);
+                    identify_client_version(fd, fd->headerline, fd->headerline + fd->pos, args.asd, args.pkt, args.change_bits);
                     snort_free(fd->headerline);
                     fd->headerline = nullptr;
                     fd->pos = 0;
@@ -842,7 +842,7 @@ int SmtpServiceDetector::validate(AppIdDiscoveryArgs& args)
                     dd->client.decryption_countdown = 1
 #endif
 
-                add_service(args.asd, args.pkt, args.dir,  APP_ID_SMTPS);
+                add_service(args.change_bits, args.asd, args.pkt, args.dir,  APP_ID_SMTPS);
 
                 if(dd->need_continue > 0)
                     args.asd.set_session_flags(APPID_SESSION_ENCRYPTED | APPID_SESSION_STICKY_SERVICE | APPID_SESSION_CONTINUE);
@@ -869,7 +869,7 @@ success:
     if (dd->need_continue > 0)
         args.asd.set_session_flags(APPID_SESSION_CONTINUE);
 
-    return add_service(args.asd, args.pkt, args.dir,
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir,
         (fd->state == SMTP_SERVICE_STATE_STARTTLS) ? APP_ID_SMTPS : APP_ID_SMTP);
 
 fail:
index a3e972a703d3ef0c82b0eeecbb1e6eb9f99983fc..62502dcbfd80fba10d38af4e4658d6835ca1ea83 100644 (file)
@@ -40,9 +40,9 @@ public:
 private:
     int extract_version_and_add_client_app(AppId, const int prefix_len,
         const uint8_t* product, const uint8_t* product_end, ClientSMTPData* const,
-        AppIdSession&, AppId);
+        AppIdSession&, AppId, AppidChangeBits&);
     int identify_client_version(ClientSMTPData* const, const uint8_t* product,
-        const uint8_t* data_end, AppIdSession&, snort::Packet*);
+        const uint8_t* data_end, AppIdSession&, snort::Packet*, AppidChangeBits&);
 };
 
 class SmtpServiceDetector : public ServiceDetector
index de4e9b9ed6f957c0d13a3aebb84424158604d26a..b724e31f682ea4140ba7f2c59d9d3a052bc0cfd6 100644 (file)
@@ -518,8 +518,8 @@ static int service_add_service(lua_State* L)
 
     /*Phase2 - discuss AppIdServiceSubtype will be maintained on lua side therefore the last
       parameter on the following call is nullptr. Subtype is not displayed on DC at present. */
-    unsigned int retValue = ud->sd->add_service(*lsd->ldp.asd, lsd->ldp.pkt, lsd->ldp.dir,
-        AppInfoManager::get_instance().get_appid_by_service_id(service_id),
+    unsigned int retValue = ud->sd->add_service(*lsd->ldp.change_bits, *lsd->ldp.asd, lsd->ldp.pkt,
+        lsd->ldp.dir, AppInfoManager::get_instance().get_appid_by_service_id(service_id),
         vendor, version, nullptr);
 
     lua_pushnumber(L, retValue);
@@ -902,7 +902,7 @@ static int service_add_client(lua_State* L)
         return 1;
     }
 
-    ud->cd->add_app(*lsd->ldp.asd, service_id, client_id, version);
+    ud->cd->add_app(*lsd->ldp.asd, service_id, client_id, version, *lsd->ldp.change_bits);
     lua_pushnumber(L, 0);
     return 1;
 }
@@ -918,7 +918,8 @@ static int client_add_application(lua_State* L)
     const char* version = lua_tostring(L, 5);
     ud->cd->add_app(*lsd->ldp.asd,
         AppInfoManager::get_instance().get_appid_by_service_id(service_id),
-        AppInfoManager::get_instance().get_appid_by_client_id(productId), version);
+        AppInfoManager::get_instance().get_appid_by_client_id(productId), version,
+        *lsd->ldp.change_bits);
 
     lua_pushnumber(L, 0);
     return 1;
@@ -931,7 +932,7 @@ static int client_add_info(lua_State* L)
     LuaStateDescriptor* lsd = ud->validate_lua_state(true);
 
     const char* info = lua_tostring(L, 2);
-    ud->cd->add_info(*lsd->ldp.asd, info);
+    ud->cd->add_info(*lsd->ldp.asd, info, *lsd->ldp.change_bits);
     lua_pushnumber(L, 0);
     return 1;
 }
@@ -1933,7 +1934,7 @@ static int add_client_application(lua_State* L)
     unsigned int service_id = lua_tonumber(L, 2);
     unsigned int client_id = lua_tonumber(L, 3);
 
-    ud->cd->add_app(*lsd->ldp.asd, service_id, client_id, "");
+    ud->cd->add_app(*lsd->ldp.asd, service_id, client_id, "", *lsd->ldp.change_bits);
     lua_pushnumber(L, 0);
     return 1;
 }
@@ -1959,7 +1960,7 @@ static int add_service_application(lua_State* L)
     /*Phase2 - discuss AppIdServiceSubtype will be maintained on lua side therefore the last
       parameter on the following call is nullptr.
       Subtype is not displayed on DC at present. */
-    unsigned retValue = ud->sd->add_service(*lsd->ldp.asd, lsd->ldp.pkt,
+    unsigned retValue = ud->sd->add_service(*lsd->ldp.change_bits, *lsd->ldp.asd, lsd->ldp.pkt,
         lsd->ldp.dir, service_id);
 
     lua_pushnumber(L, retValue);
@@ -2502,6 +2503,7 @@ int LuaStateDescriptor::lua_validate(AppIdDiscoveryArgs& args)
     ldp.size = args.size;
     ldp.dir = args.dir;
     ldp.asd = &args.asd;
+    ldp.change_bits = &args.change_bits;
     ldp.pkt = args.pkt;
     const char* validateFn = package_info.validateFunctionName.c_str();
 
index 8b41df110f08645bf02a406a5d0e718f7071d218..f938658321d2820c390044b7d4289d9c38590ee6 100644 (file)
@@ -62,6 +62,7 @@ struct LuaDetectorParameters
         size = args.size;
         dir = args.dir;
         asd = &args.asd;
+        change_bits = &args.change_bits;
         pkt = args.pkt;
     }
 
@@ -69,6 +70,7 @@ struct LuaDetectorParameters
     uint16_t size = 0;
     AppidSessionDirection dir = APP_ID_FROM_INITIATOR;
     AppIdSession* asd;
+    AppidChangeBits* change_bits = nullptr;
     snort::Packet* pkt = nullptr;
     uint8_t macAddress[6] = { 0 };
 };
index 9720ac2729b12204928936d7b37730e59ee65ec9..05fd5dec8b951feebc20ffce78ccfe3260628f03 100644 (file)
@@ -187,7 +187,7 @@ success:
         goto inprocess;
     }
 
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_BATTLEFIELD);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_BATTLEFIELD);
 
 fail:
     fail_service(args.asd, args.pkt, args.dir);
index 6cd04b4a3f9dc7c060b49150773f030700214d14..74e6f3275f99e1c81e3153e226f3e113e87dc5c4 100644 (file)
@@ -219,6 +219,6 @@ fail:
     return APPID_NOMATCH;
 
 success:
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_BGP);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_BGP);
 }
 
index cf3f524ed940a376efc01c00c590e198ec50f31a..b2416506761955c4477873bcffbedd00a12d8506 100644 (file)
@@ -170,7 +170,7 @@ inprocess:
     return APPID_INPROCESS;
 
 success:
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_BITTORRENT);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_BITTORRENT);
 
 fail:
     fail_service(args.asd, args.pkt, args.dir);
index b269dec090ae4969a2815a3d897cb2f1d0b2c229..b0fa70e9be88cbebf14c8a113cb142b8156c3eec 100644 (file)
@@ -296,7 +296,7 @@ success:
     if (!args.asd.is_service_detected())
     {
         args.asd.set_session_flags(APPID_SESSION_CONTINUE);
-        add_service(args.asd, args.pkt, args.dir, APP_ID_DHCP);
+        add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_DHCP);
     }
     return APPID_SUCCESS;
 
index 094880024069f6700a57b70aeb427ca423ab7ef1..676749eba26c57627e10d9b943889340f952efa2 100644 (file)
@@ -99,7 +99,7 @@ int DceRpcServiceDetector::tcp_validate(AppIdDiscoveryArgs& args)
         size -= length;
     }
     if (retval == APPID_SUCCESS)
-        return add_service(args.asd, args.pkt, args.dir, APP_ID_DCE_RPC);
+        return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_DCE_RPC);
 
 inprocess:
     service_inprocess(args.asd, args.pkt, args.dir);
@@ -142,7 +142,7 @@ int DceRpcServiceDetector::udp_validate(AppIdDiscoveryArgs& args)
         size -= length;
     }
     if (retval == APPID_SUCCESS)
-        return add_service(args.asd, args.pkt, args.dir, APP_ID_DCE_RPC);
+        return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_DCE_RPC);
 
 inprocess:
     service_inprocess(args.asd, args.pkt, args.dir);
index 5a4241f4a82e2bd20b25c5ebb3978b185e43f5cf..bf9f7a8448fddb26b9e816a54d0aefef40a39a4b 100644 (file)
@@ -81,14 +81,14 @@ int ServiceDetector::service_inprocess(AppIdSession& asd, const Packet* pkt, App
 }
 
 int ServiceDetector::update_service_data(AppIdSession& asd, const Packet* pkt, AppidSessionDirection dir, AppId appId,
-    const char* vendor, const char* version)
+    const char* vendor, const char* version, AppidChangeBits& change_bits)
 {
     uint16_t port = 0;
     const SfIp* ip = nullptr;
 
     asd.service_detector = this;
     asd.service.set_vendor(vendor);
-    asd.service.set_version(version);
+    asd.service.set_version(version, change_bits);
     asd.set_service_detected();
     asd.service.set_id(appId);
 
@@ -134,14 +134,15 @@ int ServiceDetector::update_service_data(AppIdSession& asd, const Packet* pkt, A
 
 int ServiceDetector::add_service_consume_subtype(AppIdSession& asd, const Packet* pkt,
     AppidSessionDirection dir, AppId appId, const char* vendor, const char* version,
-    AppIdServiceSubtype* subtype)
+    AppIdServiceSubtype* subtype, AppidChangeBits& change_bits)
 {
     asd.subtype = subtype;
-    return update_service_data(asd, pkt, dir, appId, vendor, version);
+    return update_service_data(asd, pkt, dir, appId, vendor, version, change_bits);
 }
 
-int ServiceDetector::add_service(AppIdSession& asd, const Packet* pkt, AppidSessionDirection dir,
-    AppId appId, const char* vendor, const char* version, const AppIdServiceSubtype* subtype)
+int ServiceDetector::add_service(AppidChangeBits& change_bits, AppIdSession& asd,
+    const Packet* pkt, AppidSessionDirection dir, AppId appId, const char* vendor,
+    const char* version, const AppIdServiceSubtype* subtype)
 {
     AppIdServiceSubtype* new_subtype = nullptr;
 
@@ -162,7 +163,7 @@ int ServiceDetector::add_service(AppIdSession& asd, const Packet* pkt, AppidSess
         new_subtype = tmp_subtype;
     }
     asd.subtype = new_subtype;
-    return update_service_data(asd, pkt, dir, appId, vendor, version);
+    return update_service_data(asd, pkt, dir, appId, vendor, version, change_bits);
 }
 
 int ServiceDetector::incompatible_data(AppIdSession& asd, const Packet* pkt, AppidSessionDirection dir)
index 0cb25c77600b994ee8b3b0aaef992cc7946808e4..6b0cd14624b1871eb260c57d62c4b2ca3174f9e0 100644 (file)
@@ -35,10 +35,12 @@ public:
     void release_thread_resources() override { }
     void register_appid(AppId, unsigned extractsInfo) override;
     int service_inprocess(AppIdSession&, const snort::Packet*, AppidSessionDirection dir);
-    int add_service(AppIdSession&, const snort::Packet*, AppidSessionDirection dir, AppId, const char* vendor = nullptr,
-        const char* version = nullptr, const snort::AppIdServiceSubtype* = nullptr);
-    int add_service_consume_subtype(AppIdSession&, const snort::Packet*, AppidSessionDirection dir, AppId,
-        const char* vendor, const char* version, snort::AppIdServiceSubtype*);
+    int add_service(AppidChangeBits&, AppIdSession&, const snort::Packet*, AppidSessionDirection dir, AppId,
+        const char* vendor = nullptr, const char* version = nullptr,
+        const snort::AppIdServiceSubtype* = nullptr);
+    int add_service_consume_subtype(AppIdSession&, const snort::Packet*,
+        AppidSessionDirection dir, AppId, const char* vendor, const char* version,
+        snort::AppIdServiceSubtype*, AppidChangeBits&);
     int incompatible_data(AppIdSession&, const snort::Packet*, AppidSessionDirection dir);
     int fail_service(AppIdSession&, const snort::Packet*, AppidSessionDirection dir);
 
@@ -55,8 +57,8 @@ public:
     void initialize_expected_session(AppIdSession&, AppIdSession&, uint64_t flags, AppidSessionDirection dir);
 
 private:
-    int update_service_data(AppIdSession&, const snort::Packet*, AppidSessionDirection dir, AppId, const char* vendor,
-        const char* version);
+    int update_service_data(AppIdSession&, const snort::Packet*, AppidSessionDirection dir, AppId,
+        const char* vendor, const char* version, AppidChangeBits& change_bits);
 };
 #endif
 
index 8ea469bb92900d07cd10ce4e1ae4898a629e82d8..f83eaccc0e8d9b1b49a2da22ab4ecd6145b03d5a 100644 (file)
@@ -111,13 +111,13 @@ int DirectConnectServiceDetector::validate(AppIdDiscoveryArgs& args)
     }
 
     if (args.asd.protocol == IpProtocol::TCP)
-        return tcp_validate(data, size, args.dir, args.asd, args.pkt, fd);
+        return tcp_validate(data, size, args.dir, args.asd, args.pkt, fd, args.change_bits);
     else
-        return udp_validate(data, size, args.dir, args.asd, args.pkt, fd);
+        return udp_validate(data, size, args.dir, args.asd, args.pkt, fd, args.change_bits);
 }
 
 int DirectConnectServiceDetector::tcp_validate(const uint8_t* data, uint16_t size, const AppidSessionDirection dir,
-    AppIdSession& asd, const Packet* pkt, ServiceData* serviceData)
+    AppIdSession& asd, const Packet* pkt, ServiceData* serviceData, AppidChangeBits& change_bits)
 {
     switch (serviceData->state)
     {
@@ -215,7 +215,7 @@ success:
         goto inprocess;
     }
 
-    return add_service(asd, pkt, dir, APP_ID_DIRECT_CONNECT);
+    return add_service(change_bits, asd, pkt, dir, APP_ID_DIRECT_CONNECT);
 
 fail:
     fail_service(asd, pkt, dir);
@@ -223,7 +223,7 @@ fail:
 }
 
 int DirectConnectServiceDetector::udp_validate(const uint8_t* data, uint16_t size, const AppidSessionDirection dir,
-    AppIdSession& asd, const Packet* pkt, ServiceData* serviceData)
+    AppIdSession& asd, const Packet* pkt, ServiceData* serviceData, AppidChangeBits& change_bits)
 {
     if (dir == APP_ID_FROM_RESPONDER && serviceData->state == CONN_STATE_SERVICE_DETECTED)
     {
@@ -263,7 +263,7 @@ success:
     }
 
 reportSuccess:
-    return add_service(asd, pkt, dir, APP_ID_DIRECT_CONNECT);
+    return add_service(change_bits, asd, pkt, dir, APP_ID_DIRECT_CONNECT);
 
 fail:
     fail_service(asd, pkt, dir);
index 7befc565eb4d4888ae18d07f299c95f5786eaa34..b8c6634f68858631fe8031973b5193847c52cdd3 100644 (file)
@@ -37,9 +37,9 @@ public:
 
 private:
     int tcp_validate(const uint8_t* data, uint16_t size, const AppidSessionDirection dir, AppIdSession&,
-        const snort::Packet*, ServiceData*);
+        const snort::Packet*, ServiceData*, AppidChangeBits&);
     int udp_validate(const uint8_t* data, uint16_t size, const AppidSessionDirection dir, AppIdSession&,
-        const snort::Packet*, ServiceData*);
+        const snort::Packet*, ServiceData*, AppidChangeBits&);
 };
 
 #endif
index 1b27be301c4d655167320660784e4781a9b51fc4..51f812568cca4609d64f043fe994a16a69e7b82e 100644 (file)
@@ -409,7 +409,8 @@ void ServiceDiscovery::get_next_service(const Packet* p, const AppidSessionDirec
     }
 }
 
-int ServiceDiscovery::identify_service(AppIdSession& asd, Packet* p, AppidSessionDirection dir)
+int ServiceDiscovery::identify_service(AppIdSession& asd, Packet* p,
+    AppidSessionDirection dir, AppidChangeBits& change_bits)
 {
     ServiceDiscoveryState* sds = nullptr;
     bool got_brute_force = false;
@@ -472,7 +473,7 @@ int ServiceDiscovery::identify_service(AppIdSession& asd, Packet* p, AppidSessio
     int ret = APPID_NOMATCH;
     bool got_incompatible_service = false;
     bool got_fail_service = false;
-    AppIdDiscoveryArgs args(p->data, p->dsize, dir, asd, p);
+    AppIdDiscoveryArgs args(p->data, p->dsize, dir, asd, p, change_bits);
     /* If we already have a service to try, then try it out. */
     if ( asd.service_detector )
     {
@@ -580,7 +581,8 @@ int ServiceDiscovery::add_ftp_service_state(AppIdSession& asd)
     return asd.add_flow_data_id(21, ftp_service);
 }
 
-bool ServiceDiscovery::do_service_discovery(AppIdSession& asd, Packet* p, AppidSessionDirection direction)
+bool ServiceDiscovery::do_service_discovery(AppIdSession& asd, Packet* p,
+    AppidSessionDirection direction, AppidChangeBits& change_bits)
 {
     bool isTpAppidDiscoveryDone = false;
 
@@ -693,7 +695,7 @@ bool ServiceDiscovery::do_service_discovery(AppIdSession& asd, Packet* p, AppidS
 
     if (asd.service_disco_state == APPID_DISCO_STATE_STATEFUL)
     {
-        identify_service(asd, p, direction);
+        identify_service(asd, p, direction, change_bits);
         isTpAppidDiscoveryDone = true;
         //to stop executing validator after service has been detected by RNA.
         if (asd.get_session_flags(APPID_SESSION_SERVICE_DETECTED |
@@ -716,12 +718,12 @@ bool ServiceDiscovery::do_service_discovery(AppIdSession& asd, Packet* p, AppidS
             AppId payload_id = APP_ID_NONE;
             dns_host_scan_hostname((const uint8_t*)(dsession->get_host()), dsession->get_host_len(),
                 &client_id, &payload_id);
-            asd.set_client_appid_data(client_id, nullptr);
+            asd.set_client_appid_data(client_id, nullptr, change_bits);
         }
         else if (asd.service.get_id() == APP_ID_RTMP)
-            asd.examine_rtmp_metadata();
+            asd.examine_rtmp_metadata(change_bits);
         else if (asd.get_session_flags(APPID_SESSION_SSL_SESSION) && asd.tsession)
-            asd.examine_ssl_metadata(p);
+            asd.examine_ssl_metadata(p, change_bits);
 
         if (tp_app_id <= APP_ID_NONE && asd.get_session_flags(
             APPID_SESSION_SERVICE_DETECTED | APPID_SESSION_NOT_A_SERVICE |
index 74844a9339a4f7af55b69131f9413b387156a009..55aa3cc316aa9ef70b929274dcd62099952a32ad 100644 (file)
@@ -78,8 +78,9 @@ public:
     ServiceDetector* get_next_tcp_detector(AppIdDetectorsIterator&);
     ServiceDetector* get_next_udp_detector(AppIdDetectorsIterator&);
 
-    bool do_service_discovery(AppIdSession&, snort::Packet*, AppidSessionDirection dir);
-    int identify_service(AppIdSession&, snort::Packet*, AppidSessionDirection dir);
+    bool do_service_discovery(AppIdSession&, snort::Packet*, AppidSessionDirection dir,
+        AppidChangeBits& change_bits);
+    int identify_service(AppIdSession&, snort::Packet*, AppidSessionDirection, AppidChangeBits&);
     int fail_service(AppIdSession&, const snort::Packet*, AppidSessionDirection dir, ServiceDetector*, ServiceDiscoveryState* sds = nullptr);
     int incompatible_data(AppIdSession&, const snort::Packet*, AppidSessionDirection dir, ServiceDetector*);
     static int add_ftp_service_state(AppIdSession&);
index 567a2bb75bacc3252dce2456f3dbe26e5fe0cab3..282f3bcc19af75de97ddeb01676dc594d46e6598 100644 (file)
@@ -202,7 +202,8 @@ fail:
     return APPID_NOMATCH;
 
 success:
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_AOL_INSTANT_MESSENGER);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir,
+        APP_ID_AOL_INSTANT_MESSENGER);
 
 inprocess:
     service_inprocess(args.asd, args.pkt, args.dir);
index ca8030b160f62756a2158db121da028339433f24..e48c01cafeea1df3fbafef12007d859d3d74b07f 100644 (file)
@@ -1228,8 +1228,8 @@ inprocess:
                 | APPID_SESSION_DECRYPTED);
 
             // FTPS only when encrypted==1 decrypted==0
-            add_service(args.asd, args.pkt, args.dir, flags == APPID_SESSION_ENCRYPTED ?
-                APP_ID_FTPS : APP_ID_FTP_CONTROL,
+            add_service(args.change_bits, args.asd, args.pkt, args.dir,
+                flags == APPID_SESSION_ENCRYPTED ? APP_ID_FTPS : APP_ID_FTP_CONTROL,
                 fd->vendor[0] ? fd->vendor : nullptr,
                 fd->version[0] ? fd->version : nullptr, nullptr);
         }
index 04f06fd79e23db058f4cf42524682d3b51cddeb9..3377653028bd1d41e1d96f58bbc3b8e831f0faee 100644 (file)
@@ -283,7 +283,7 @@ inprocess:
     return APPID_INPROCESS;
 
 success:
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_IRCD);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_IRCD);
 
 fail:
     if (args.dir == APP_ID_FROM_RESPONDER)
index ed5da28bdba897cc0ef06d49d360f25dcb8f6529..00855987d5ca9aea4ab681d6baa335e292fbbae8 100644 (file)
@@ -211,7 +211,7 @@ inprocess:
     return APPID_INPROCESS;
 
 success:
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_PRINTSRV);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_PRINTSRV);
 
 fail:
     fail_service(args.asd, args.pkt, args.dir);
index f52278c44d03f45066db9dc97ac2c28e8a23d6fd..00d30d0cdfca79604564943d408dc1db06664776 100644 (file)
@@ -165,7 +165,7 @@ int MdnsServiceDetector::validate(AppIdDiscoveryArgs& args)
         goto fail;
 
 success:
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_MDNS);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_MDNS);
 
 fail:
     fail_service(args.asd, args.pkt, args.dir);
index 3f73772bb20b0865f6a9321da91037869e1a8c11..3a26b96b867ef12ef664209cdcafe99268f27e81 100644 (file)
@@ -115,7 +115,8 @@ int MySqlServiceDetector::validate(AppIdDiscoveryArgs& args)
     data += 6;
     if (data >= end)
         goto fail;
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_MYSQL, nullptr, (const char*)p, nullptr);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_MYSQL,
+        nullptr, (const char*)p, nullptr);
 
 inprocess:
     service_inprocess(args.asd, args.pkt, args.dir);
index b7578274218d9407a9c33a94f7fa1d23bdb758ef..f9b1fefcec09e824ae560a79b060d5573731dbbc 100644 (file)
@@ -548,7 +548,7 @@ int NbnsServiceDetector::validate(AppIdDiscoveryArgs& args)
     }
 
 success:
-    return add_service(args.asd, args.pkt, dir, APP_ID_NETBIOS_NS);
+    return add_service(args.change_bits, args.asd, args.pkt, dir, APP_ID_NETBIOS_NS);
 
 inprocess:
     service_inprocess(args.asd, args.pkt, dir);
@@ -983,7 +983,7 @@ int NbssServiceDetector::validate(AppIdDiscoveryArgs& args)
         goto inprocess;
 
     if ( !args.asd.is_service_detected() )
-        if ( add_service(args.asd, args.pkt, dir, nd->serviceAppId) == APPID_SUCCESS )
+        if ( add_service(args.change_bits, args.asd, args.pkt, dir, nd->serviceAppId) == APPID_SUCCESS )
             add_miscellaneous_info(args.asd, nd->miscAppId);
     return APPID_SUCCESS;
 
@@ -1166,7 +1166,7 @@ success:
     {
         if ( dir == APP_ID_FROM_RESPONDER )
         {
-            if ( add_service(args.asd, args.pkt, dir, serviceAppId) == APPID_SUCCESS )
+            if ( add_service(args.change_bits, args.asd, args.pkt, dir, serviceAppId) == APPID_SUCCESS )
                 add_miscellaneous_info(args.asd, miscAppId);
         }
     }
index c02deb865948d83af95c9e50f423543afe6287c7..ed1153696b96abaf1d041c9d61df2c26ba7bacfd 100644 (file)
@@ -345,7 +345,7 @@ inprocess:
     return APPID_INPROCESS;
 
 success:
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_NNTP);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_NNTP);
 
 fail:
     fail_service(args.asd, args.pkt, args.dir);
index 8e91be15f8e1db619dad531323510cd71b0c708d..44182010d91814e7e9f3c1fc4bd044163fc49293 100644 (file)
@@ -127,7 +127,7 @@ int NtpServiceDetector::validate(AppIdDiscoveryArgs& args)
             goto fail;
     }
 
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_NTP);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_NTP);
 
 inprocess:
     service_inprocess(args.asd, args.pkt, args.dir);
index 469a0582412fdc895465586ea5f3af20c20936bd..7e3e42047ce0af88f1ff7e67d446a0351fbfce8b 100644 (file)
@@ -168,7 +168,7 @@ inprocess:
     return APPID_INPROCESS;
 
 success:
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_RADIUS);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_RADIUS);
 
 not_compatible:
     incompatible_data(args.asd, args.pkt, args.dir);
@@ -283,7 +283,7 @@ inprocess:
     return APPID_INPROCESS;
 
 success:
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_RADIUS_ACCT);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_RADIUS_ACCT);
 
 not_compatible:
     incompatible_data(args.asd, args.pkt, args.dir);
index 7fe1720bbcebb78b454f5e65e4841b6e451952d1..fc20718e924d6b5ff9fa7aef6f6855412e236603 100644 (file)
@@ -80,7 +80,8 @@ int RegTestServiceDetector::validate(AppIdDiscoveryArgs& args)
         p++;
     }
     *v = 0;
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_REGTEST, nullptr, version, nullptr);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_REGTEST, nullptr,
+        version, nullptr);
 
 inprocess:
     service_inprocess(args.asd, args.pkt, args.dir);
@@ -138,7 +139,8 @@ int RegTestServiceDetector1::validate(AppIdDiscoveryArgs& args)
         p++;
     }
     *v = 0;
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_REGTEST1, nullptr, version, nullptr);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_REGTEST1, nullptr,
+        version, nullptr);
 
 inprocess:
     service_inprocess(args.asd, args.pkt, args.dir);
@@ -191,7 +193,8 @@ int RegTestServiceDetector2::validate(AppIdDiscoveryArgs& args)
         p++;
     }
     *v = 0;
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_REGTEST2, nullptr, version, nullptr);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_REGTEST2, nullptr,
+        version, nullptr);
 
 inprocess:
     service_inprocess(args.asd, args.pkt, args.dir);
index 50164acccbed812e114bbec6298616ee24e6fa6b..69264fa0e9cee0a864a6cea53c3574bddbbc1c17 100644 (file)
@@ -272,7 +272,7 @@ inprocess:
 
 success:
     if (!args.asd.is_service_detected())
-        return add_service(args.asd, args.pkt, args.dir, APP_ID_EXEC);
+        return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_EXEC);
 
 bail:
     if (!args.asd.is_service_detected())
index 4a1f04c977f5b226dfe59dc7249060209ae13168..967ff2106e79dff974a2687b20abc4f1724c653a 100644 (file)
@@ -97,7 +97,8 @@ int RfbServiceDetector::validate(AppIdDiscoveryArgs& args)
         p++;
     }
     *v = 0;
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_VNC_RFB, nullptr, version, nullptr);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_VNC_RFB,
+        nullptr, version, nullptr);
 
 inprocess:
     service_inprocess(args.asd, args.pkt, args.dir);
index aebffa51d3e5d3526f857e8498058c23d15d1be2..eb9b177e8bf517fe752c218d3f7f51a552fe4e28 100644 (file)
@@ -129,7 +129,7 @@ inprocess:
     return APPID_INPROCESS;
 
 success:
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_RLOGIN);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_RLOGIN);
 
 fail:
     fail_service(args.asd, args.pkt, args.dir);
index a6e5d0b2cd662bfa1d71e82f878faa7fd0425b5c..6fad6cb753fba56ef2ed96cc592e8db12e33c00d 100644 (file)
@@ -512,7 +512,8 @@ done:
             else
                 subtype = nullptr;
 
-            add_service(args.asd, pkt, dir, APP_ID_SUN_RPC, nullptr, nullptr, subtype);
+            add_service(args.change_bits, args.asd, pkt, dir, APP_ID_SUN_RPC,
+                nullptr, nullptr, subtype);
         }
         args.asd.set_session_flags(APPID_SESSION_CONTINUE);
         return APPID_SUCCESS;
@@ -857,7 +858,8 @@ inprocess:
             }
             else
                 subtype = nullptr;
-            add_service(args.asd, pkt, dir, APP_ID_SUN_RPC, nullptr, nullptr, subtype);
+            add_service(args.change_bits, args.asd, pkt, dir, APP_ID_SUN_RPC,
+                nullptr, nullptr, subtype);
         }
         args.asd.set_session_flags(APPID_SESSION_CONTINUE);
         return APPID_SUCCESS;
index 24169ef77d4c508f8b1d561d50025d1010001f79..2f59940500667f317bd4bdfdbab59e316244a8c9 100644 (file)
@@ -283,7 +283,7 @@ inprocess:
     return APPID_INPROCESS;
 
 success:
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_SHELL);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_SHELL);
 
 bail:
     incompatible_data(args.asd, args.pkt, args.dir);
index 70bc2822df682f1c9c8f529352a53aa383a6e419..111934cd856b1297d6c2fd2e01285d2ab51d3a06 100644 (file)
@@ -121,7 +121,7 @@ inprocess:
     return APPID_INPROCESS;
 
 success:
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_RSYNC);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_RSYNC);
 
 fail:
     fail_service(args.asd, args.pkt, args.dir);
index b36a31077c369018b77a1e986c67428844aa31ef..80ae9a8e45ce187abbbc1f5fda84e55b91d74adf 100644 (file)
@@ -637,7 +637,7 @@ success:
     {
         if ( !hsession->get_field(MISC_URL_FID) )
         {
-            hsession->set_field(MISC_URL_FID, new std::string(ss->swfUrl));
+            hsession->set_field(MISC_URL_FID, new std::string(ss->swfUrl), args.change_bits);
             args.asd.scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
         }
 
@@ -649,12 +649,12 @@ success:
     {
         if ( !hsession->get_field(REQ_REFERER_FID) &&
             !args.asd.config->mod_config->referred_appId_disabled )
-            hsession->set_field(REQ_REFERER_FID, new std::string(ss->pageUrl));
+            hsession->set_field(REQ_REFERER_FID, new std::string(ss->pageUrl), args.change_bits);
 
         snort_free(ss->pageUrl);
         ss->pageUrl = nullptr;
     }
 
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_RTMP);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_RTMP);
 }
 
index c403a6775ac8c70298c92378470f33910cdde845..6df490da39654fc625d27c08acdd6b850e6f661d 100644 (file)
@@ -572,7 +572,8 @@ success:
         version_str = nullptr;
         break;
     }
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_SNMP, SNMP_VENDOR_STR, version_str, nullptr);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_SNMP,
+        SNMP_VENDOR_STR, version_str, nullptr);
 
 bail:
     incompatible_data(args.asd, args.pkt, args.dir);
index af6d3143699cbda8a11725ce43657483459234d2..959310105e192d051c68f9224a747dfe7a7cd86c 100644 (file)
@@ -536,7 +536,8 @@ inprocess:
         return APPID_INPROCESS;
 
     case APPID_SUCCESS:
-        return add_service(args.asd, args.pkt, args.dir, APP_ID_SSH, ss->vendor, ss->version, nullptr);
+        return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_SSH,
+            ss->vendor, ss->version, nullptr);
 
     case APPID_NOMATCH:
 fail:
index d5cc5911693a3c62d863f8485107ffd15699dab7..96ea2a063a203ec858e623bd9e18fc4984eaab57 100644 (file)
@@ -876,45 +876,29 @@ success:
         /* TLS Host */
         if (ss->host_name)
         {
-            if (args.asd.tsession->tls_host)
-                snort_free(args.asd.tsession->tls_host);
-            args.asd.tsession->tls_host = ss->host_name;
-            args.asd.tsession->tls_host_strlen = ss->host_name_strlen;
+            args.asd.tsession->set_tls_host(ss->host_name, 0, args.change_bits);
             args.asd.scan_flags |= SCAN_SSL_HOST_FLAG;
         }
         else if (ss->common_name)
         {
             // use common name (from server) if we didn't see host name (from client)
-            char* common_name = snort_strdup(ss->common_name);
-
-            if (args.asd.tsession->tls_host)
-                snort_free(args.asd.tsession->tls_host);
-            args.asd.tsession->tls_host = common_name;
-            args.asd.tsession->tls_host_strlen = ss->common_name_strlen;
+            args.asd.tsession->set_tls_host(ss->common_name, ss->common_name_strlen,
+                args.change_bits);
             args.asd.scan_flags |= SCAN_SSL_HOST_FLAG;
         }
 
         /* TLS Common Name */
         if (ss->common_name)
-        {
-            if (args.asd.tsession->tls_cname)
-                snort_free(args.asd.tsession->tls_cname);
-            args.asd.tsession->tls_cname = ss->common_name;
-            args.asd.tsession->tls_cname_strlen = ss->common_name_strlen;
-        }
+            args.asd.tsession->set_tls_cname(ss->common_name, 0);
 
         /* TLS Org Unit */
         if (ss->org_name)
-        {
-            if (args.asd.tsession->tls_orgUnit)
-                snort_free(args.asd.tsession->tls_orgUnit);
-            args.asd.tsession->tls_orgUnit = ss->org_name;
-            args.asd.tsession->tls_orgUnit_strlen = ss->org_name_strlen;
-        }
+            args.asd.tsession->set_tls_org_unit(ss->org_name, 0);
 
         ss->host_name = ss->common_name = ss->org_name = nullptr;
     }
-    return add_service(args.asd, args.pkt, args.dir, getSslServiceAppId(args.pkt->ptrs.sp));
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir,
+        getSslServiceAppId(args.pkt->ptrs.sp));
 }
 
 AppId getSslServiceAppId(short srcPort)
index e811cac40bb8176bb2036eee0c284015acda4a55..7d13f15ff980455114116d37bc0b11fadcb811d4 100644 (file)
@@ -143,7 +143,7 @@ inprocess:
     return APPID_INPROCESS;
 
 success:
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_TELNET);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_TELNET);
 
 fail:
     fail_service(args.asd, args.pkt, args.dir);
index e39e4b97635e1a9b8484de488e2b7c019e34f3be..7448fdb563f3b95c2629ce7fece92d02ee704fba 100644 (file)
@@ -326,7 +326,7 @@ inprocess:
 success:
     if (appidDebug->is_active())
         LogMessage("AppIdDbg %s TFTP success\n", appidDebug->get_debug_session());
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_TFTP);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_TFTP);
 
 bail:
     incompatible_data(args.asd, args.pkt, args.dir);
index 53d962e2c5d1f6f29f34cd545061916e1ac06b05..18b5c054be661191be488473e5d37f9c8d059dc4 100644 (file)
@@ -154,7 +154,7 @@ inprocess:
     return APPID_INPROCESS;
 
 success:
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_TIMBUKTU);
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_TIMBUKTU);
 
 fail:
     fail_service(args.asd, args.pkt, args.dir);
index a87e86e33c2681e5d85835a6c2a1df7956cb5964..6da9570c2ee822197dd44a7e3201016aa69134d3 100644 (file)
@@ -276,7 +276,7 @@ inprocess:
     return APPID_INPROCESS;
 
 success:
-    return add_service(args.asd, args.pkt, args.dir, APP_ID_ORACLE_TNS,
+    return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_ORACLE_TNS,
         nullptr, ss->version ? ss->version : nullptr, nullptr);
 
 fail:
index f5ab54a37b3653569d70760baa48db935c457ad1..3fd626d798388dd25dba832b84e640495a30766a 100644 (file)
@@ -14,6 +14,10 @@ add_cpputest( appid_detector_test
     SOURCES $<TARGET_OBJECTS:appid_cpputest_deps>
 )
 
+add_cpputest( appid_discovery_test
+    SOURCES $<TARGET_OBJECTS:appid_cpputest_deps>
+)
+
 add_cpputest( appid_expected_flags_test
     SOURCES $<TARGET_OBJECTS:appid_cpputest_deps>
 )
index 2b7c16b508140090bcd6b170f7a2bd3da34cdaee..2da4d830f23d8ce597077f087950dfdeed1b9fa0 100644 (file)
@@ -118,7 +118,7 @@ TEST(appid_api, produce_ha_state)
     mock_flow_data= nullptr;
     SfIp ip;
     ip.pton(AF_INET, "192.168.1.222");
-    val = appid_api.consume_ha_state(flow, (uint8_t*)&appHA, 0, IpProtocol::TCP, &ip, 1066);
+    appid_api.consume_ha_state(flow, (uint8_t*)&appHA, 0, IpProtocol::TCP, &ip, 1066);
     AppIdSession* session = (AppIdSession*)flow->get_flow_data(AppIdSession::inspector_id);
     CHECK_TRUE(session);
     CHECK_TRUE(session->get_tp_app_id() == appHA.appId[0]);
@@ -136,7 +136,7 @@ TEST(appid_api, produce_ha_state)
     // test logic when service app is ftp control
     appHA.appId[1] = APP_ID_FTP_CONTROL;
     mock_flow_data= nullptr;
-    val = appid_api.consume_ha_state(flow, (uint8_t*)&appHA, 0, IpProtocol::TCP, &ip, 1066);
+    appid_api.consume_ha_state(flow, (uint8_t*)&appHA, 0, IpProtocol::TCP, &ip, 1066);
     session = (AppIdSession*)flow->get_flow_data(AppIdSession::inspector_id);
     CHECK_TRUE(session);
     uint64_t flags = session->get_session_flags(APPID_SESSION_CLIENT_DETECTED |
index a423b38a497ea2ffa82a4bc1bee9d744e0a19986..463680e1a2dad30e69939d098577a3ff06ba2cdd 100644 (file)
@@ -39,6 +39,8 @@
 Flow* flow = nullptr;
 AppIdSession* mock_session = nullptr;
 
+void AppIdHttpSession::set_http_change_bits(AppidChangeBits&, HttpFieldIds) {}
+
 class TestDetector : public AppIdDetector
 {
 public:
@@ -69,12 +71,13 @@ TEST_GROUP(appid_detector_tests)
 TEST(appid_detector_tests, add_info)
 {
     const char* info_url = "https://tools.ietf.org/html/rfc793";
+    AppidChangeBits change_bits;
     AppIdDetector* ad = new TestDetector;
     MockAppIdHttpSession* hsession = (MockAppIdHttpSession*)mock_session->get_http_session();
-    ad->add_info(*mock_session, info_url);
+    ad->add_info(*mock_session, info_url, change_bits);
     STRCMP_EQUAL(hsession->get_cfield(MISC_URL_FID), URL);
     hsession->reset();
-    ad->add_info(*mock_session, info_url);
+    ad->add_info(*mock_session, info_url, change_bits);
     STRCMP_EQUAL(mock_session->get_http_session()->get_cfield(MISC_URL_FID), info_url);
     delete ad;
 }
diff --git a/src/network_inspectors/appid/test/appid_discovery_test.cc b/src/network_inspectors/appid/test/appid_discovery_test.cc
new file mode 100644 (file)
index 0000000..5455dfa
--- /dev/null
@@ -0,0 +1,438 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2018-2018 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.
+//--------------------------------------------------------------------------
+// appid_discovery_test.cc author Masud Hasan <mashasan@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define APPID_MOCK_INSPECTOR_H // avoiding mocked inspector
+
+#include "network_inspectors/appid/appid_discovery.cc"
+
+#include "search_engines/search_tool.h"
+#include "utils/sflsq.cc"
+
+#include "appid_mock_session.h"
+
+#include <CppUTest/CommandLineTestRunner.h>
+#include <CppUTest/TestHarness.h>
+
+namespace snort
+{
+// Stubs for packet
+Packet::Packet(bool) {}
+Packet::~Packet() {}
+
+// Stubs for inspector
+Inspector::Inspector()
+{
+    set_api(nullptr);
+}
+Inspector::~Inspector() = default;
+bool Inspector::likes(Packet*) { return true; }
+bool Inspector::get_buf(const char*, Packet*, InspectionBuffer&) { return true; }
+class StreamSplitter* Inspector::get_splitter(bool) { return nullptr; }
+
+// Stubs for module
+Module::Module(char const*, char const*) {}
+bool Module::set(const char*, Value&, SnortConfig*) { return true; }
+void Module::sum_stats(bool) {}
+void Module::show_interval_stats(std::vector<unsigned>&, FILE*) {}
+void Module::show_stats() {}
+void Module::reset_stats() {}
+PegCount Module::get_global_count(char const*) const { return 0; }
+
+// Stubs for logs
+void LogMessage(const char*,...) {}
+void ErrorMessage(const char*,...) {}
+void LogLabel(const char*, FILE*) {}
+
+// Stubs for utils
+char* snort_strdup(const char* str)
+{
+    assert(str);
+    size_t n = strlen(str) + 1;
+    char* p = (char*)snort_alloc(n);
+    memcpy(p, str, n);
+    return p;
+}
+char* snort_strndup(const char* src, size_t)
+{
+    return snort_strdup(src);
+}
+time_t packet_time() { return std::time(0); }
+
+// Stubs for search_tool
+SearchTool::SearchTool(const char*, bool) {}
+SearchTool::~SearchTool() {}
+void SearchTool::add(const char*, unsigned, int, bool) {}
+void SearchTool::add(const char*, unsigned, void*, bool) {}
+void SearchTool::add(const uint8_t*, unsigned, int, bool) {}
+void SearchTool::add(const uint8_t*, unsigned, void*, bool) {}
+
+// Stubs for ip
+namespace ip
+{
+void IpApi::set(const SfIp& sip, const SfIp& dip)
+{
+    type = IAT_DATA;
+    src.set(sip);
+    dst.set(dip);
+    iph = nullptr;
+}
+} // namespace ip
+
+} // namespace snort
+
+// Stubs for publish
+static bool databus_publish_called = false;
+static char test_log[256];
+void DataBus::publish(const char*, DataEvent& event, Flow*)
+{
+    databus_publish_called = true;
+    AppidEvent* appid_event = (AppidEvent*)&event;
+    snprintf(test_log, 256, "Published change_bits == %s",
+        appid_event->get_change_bitset().to_string().c_str());
+}
+
+// Stubs for matchers
+static HttpPatternMatchers* http_matchers;
+HttpPatternMatchers::~HttpPatternMatchers() {}
+void HttpPatternMatchers::get_http_offsets(snort::Packet*, AppIdHttpSession*) {}
+HttpPatternMatchers* HttpPatternMatchers::get_instance()
+{
+    return http_matchers;
+}
+
+// Stubs for AppIdModule
+AppIdModule::AppIdModule(): snort::Module("appid_mock", "appid_mock_help") {}
+AppIdModule::~AppIdModule() {}
+void AppIdModule::sum_stats(bool) {}
+void AppIdModule::show_dynamic_stats() {}
+bool AppIdModule::begin(char const*, int, snort::SnortConfig*) { return true; }
+bool AppIdModule::end(char const*, int, snort::SnortConfig*) { return true; }
+bool AppIdModule::set(char const*, snort::Value&, snort::SnortConfig*) { return true; }
+const snort::Command* AppIdModule::get_commands() const { return nullptr; }
+const PegInfo* AppIdModule::get_pegs() const { return nullptr; }
+PegCount* AppIdModule::get_counts() const { return nullptr; }
+snort::ProfileStats* AppIdModule::get_profile() const { return nullptr; }
+
+// Stubs for config
+AppIdModuleConfig::~AppIdModuleConfig() {}
+AppIdConfig::AppIdConfig(AppIdModuleConfig*) {}
+AppIdConfig::~AppIdConfig() {}
+static AppIdModuleConfig app_config;
+static AppIdConfig my_app_config(&app_config);
+AppId AppIdConfig::get_port_service_id(IpProtocol, uint16_t)
+{
+    return APP_ID_NONE;
+}
+
+// Stubs for AppIdInspector
+AppIdInspector::AppIdInspector(AppIdModule&) {}
+AppIdInspector::~AppIdInspector() = default;
+void AppIdInspector::eval(snort::Packet*) { }
+bool AppIdInspector::configure(snort::SnortConfig*) { return true; }
+void AppIdInspector::show(snort::SnortConfig*) { }
+void AppIdInspector::tinit() { }
+void AppIdInspector::tterm() { }
+AppIdConfig* AppIdInspector::get_appid_config()
+{
+    my_app_config.mod_config = &app_config;
+    return &my_app_config;
+}
+
+// Stubs for AppInfoManager
+AppInfoTableEntry* AppInfoManager::get_app_info_entry(AppId)
+{
+    return nullptr;
+}
+const char* AppInfoManager::get_app_name(int32_t)
+{
+    return nullptr;
+}
+
+// Stubs for AppIdSession
+void AppIdSession::sync_with_snort_protocol_id(AppId, Packet*) {}
+void AppIdSession::check_app_detection_restart(AppidChangeBits&) {}
+void AppIdSession::set_client_appid_data(AppId, char*, AppidChangeBits&) {}
+void AppIdSession::examine_rtmp_metadata(AppidChangeBits&) {}
+void AppIdSession::examine_ssl_metadata(Packet*, AppidChangeBits&) {}
+void AppIdSession::update_encrypted_app_id(AppId) {}
+AppIdSession* AppIdSession::allocate_session(const Packet*, IpProtocol,
+    AppidSessionDirection, AppIdInspector&)
+{
+    return nullptr;
+}
+
+// Stubs for ServiceDiscovery
+void ServiceDiscovery::initialize() {}
+void ServiceDiscovery::finalize_service_patterns() {}
+void ServiceDiscovery::match_by_pattern(AppIdSession&, const Packet*, IpProtocol) {}
+void ServiceDiscovery::get_port_based_services(IpProtocol, uint16_t, AppIdSession&) {}
+void ServiceDiscovery::get_next_service(const Packet*, const AppidSessionDirection, AppIdSession&) {}
+int ServiceDiscovery::identify_service(AppIdSession&, Packet*, AppidSessionDirection,
+    AppidChangeBits&) { return 0; }
+int ServiceDiscovery::add_ftp_service_state(AppIdSession&) { return 0; }
+bool ServiceDiscovery::do_service_discovery(AppIdSession&, Packet*, AppidSessionDirection,
+    AppidChangeBits&) { return 0; }
+int ServiceDiscovery::incompatible_data(AppIdSession&, const Packet*,AppidSessionDirection,
+    ServiceDetector*) { return 0; }
+int ServiceDiscovery::fail_service(AppIdSession&, const Packet*, AppidSessionDirection,
+    ServiceDetector*, ServiceDiscoveryState*) { return 0; }
+int ServiceDiscovery::add_service_port(AppIdDetector*,
+    const ServiceDetectorPort&) { return APPID_EINVALID; }
+ServiceDiscovery::ServiceDiscovery(AppIdInspector& ins)
+    : AppIdDiscovery(ins) {}
+void ServiceDiscovery::release_instance() {}
+void ServiceDiscovery::release_thread_resources() {}
+ServiceDiscovery& ServiceDiscovery::get_instance(AppIdInspector* ins)
+{
+    static ServiceDiscovery s_discovery_manager(*ins);
+    return s_discovery_manager;
+}
+
+// Stubs for ClientDiscovery
+ClientDiscovery::ClientDiscovery(AppIdInspector& ins)
+    : AppIdDiscovery(ins) {}
+ClientDiscovery::~ClientDiscovery() {}
+void ClientDiscovery::initialize() {}
+void ClientDiscovery::finalize_client_plugins() {}
+void ClientDiscovery::release_instance() {}
+void ClientDiscovery::release_thread_resources() {}
+ClientDiscovery& ClientDiscovery::get_instance(AppIdInspector* ins)
+{
+    static ClientDiscovery c_discovery_manager(*ins);
+    return c_discovery_manager;
+}
+bool ClientDiscovery::do_client_discovery(AppIdSession&, Packet*,
+    AppidSessionDirection, AppidChangeBits&)
+{
+    return false;
+}
+
+// Stubs for misc items
+HostPortVal* HostPortCache::find(const SfIp*, uint16_t, IpProtocol)
+{
+    return nullptr;
+}
+void AppIdServiceState::check_reset(AppIdSession&, const SfIp*, uint16_t) {}
+int dns_host_scan_hostname(const uint8_t*, size_t, AppId*, AppId*)
+{
+    return 0;
+}
+bool do_tp_discovery(AppIdSession&, IpProtocol,
+    Packet*, AppidSessionDirection&, AppidChangeBits&)
+{
+    return true;
+}
+TPLibHandler* TPLibHandler::self = nullptr;
+THREAD_LOCAL AppIdStats appid_stats;
+THREAD_LOCAL AppIdDebug* appidDebug = nullptr;
+void AppIdDebug::activate(const Flow*, const AppIdSession*, bool) { active = false; }
+AppId find_length_app_cache(const LengthKey&)
+{
+    return APP_ID_NONE;
+}
+void check_session_for_AF_indicator(Packet*, AppidSessionDirection, AppId) {}
+AppId check_session_for_AF_forecast(AppIdSession&, Packet*, AppidSessionDirection, AppId)
+{
+    return APP_ID_UNKNOWN;
+}
+
+TEST_GROUP(appid_discovery_tests)
+{
+    void setup() override
+    {
+        appidDebug = new AppIdDebug();
+        http_matchers = new HttpPatternMatchers;
+        AppIdPegCounts::init_pegs();
+    }
+
+    void teardown() override
+    {
+        delete appidDebug;
+        delete http_matchers;
+        AppIdPegCounts::cleanup_pegs();
+        AppIdPegCounts::cleanup_peg_info();
+    }
+};
+
+TEST(appid_discovery_tests, event_published_when_ignoring_flow)
+{
+    // Testing event from do_pre_discovery() path
+    databus_publish_called = false;
+    test_log[0] = '\0';
+    Packet p;
+    DAQ_PktHdr_t pkth;
+    p.pkth = &pkth;
+    SfIp ip;
+    p.ptrs.ip_api.set(ip, ip);
+    AppIdModule app_module;
+    AppIdInspector ins(app_module);
+    AppIdSession* asd = new AppIdSession(IpProtocol::TCP, nullptr, 21, ins);
+    Flow* flow = new Flow;
+    flow->set_flow_data(asd);
+    p.flow = flow;
+    asd->config = &my_app_config;
+    asd->common.initiator_port = 21;
+    asd->common.initiator_ip.set("1.2.3.4");
+    asd->set_session_flags(APPID_SESSION_IGNORE_FLOW);
+
+    AppIdDiscovery::do_application_discovery(&p, ins);
+
+    // Detect changes in service, client, payload, and misc appid
+    CHECK_EQUAL(databus_publish_called, true);
+    STRCMP_EQUAL(test_log, "Published change_bits == 0000000001111");
+    delete asd;
+    delete flow;
+}
+
+TEST(appid_discovery_tests, event_published_when_processing_flow)
+{
+    // Testing event from do_discovery() path
+    databus_publish_called = false;
+    test_log[0] = '\0';
+    Packet p;
+    DAQ_PktHdr_t pkth;
+    p.pkth = &pkth;
+    SfIp ip;
+    p.ptrs.ip_api.set(ip, ip);
+    AppIdModule app_module;
+    AppIdInspector ins(app_module);
+    AppIdSession* asd = new AppIdSession(IpProtocol::TCP, nullptr, 21, ins);
+    Flow* flow = new Flow;
+    flow->set_flow_data(asd);
+    p.flow = flow;
+    asd->config = &my_app_config;
+    asd->common.initiator_port = 21;
+    asd->common.initiator_ip.set("1.2.3.4");
+
+    AppIdDiscovery::do_application_discovery(&p, ins);
+
+    // Detect changes in service, client, payload, and misc appid
+    CHECK_EQUAL(databus_publish_called, true);
+    STRCMP_EQUAL(test_log, "Published change_bits == 0000000001111");
+    delete asd;
+    delete flow;
+}
+
+TEST(appid_discovery_tests, change_bits_for_client_version)
+{
+    // Testing set_version
+    AppidChangeBits change_bits;
+    AppIdModule app_module;
+    AppIdInspector ins(app_module);
+    AppIdSession* asd = new AppIdSession(IpProtocol::TCP, nullptr, 21, ins);
+    const char* version = "3.0";
+    asd->client.set_version(version, change_bits);
+
+    // Detect changes in client version
+    CHECK_EQUAL(change_bits.test(APPID_VERSION_BIT), true);
+    delete asd;
+}
+
+TEST(appid_discovery_tests, change_bits_for_tls_host)
+{
+    // Testing set_tls_host
+    AppidChangeBits change_bits;
+    const char* host = "www.cisco.com";
+    TlsSession tls;
+    tls.set_tls_host(host, 0, change_bits);
+
+    // Detect changes in tls_host
+    CHECK_EQUAL(change_bits.test(APPID_TLSHOST_BIT), true);
+}
+
+TEST(appid_discovery_tests, change_bits_for_non_http_appid)
+{
+    // Testing FTP appid
+    databus_publish_called = false;
+    Packet p;
+    DAQ_PktHdr_t pkth;
+    p.pkth = &pkth;
+    SfIp ip;
+    p.ptrs.ip_api.set(ip, ip);
+    AppIdModule app_module;
+    AppIdInspector ins(app_module);
+    AppIdSession* asd = new AppIdSession(IpProtocol::TCP, nullptr, 21, ins);
+    Flow* flow = new Flow;
+    flow->set_flow_data(asd);
+    p.flow = flow;
+    asd->config = &my_app_config;
+    asd->common.initiator_port = 21;
+    asd->common.initiator_ip.set("1.2.3.4");
+    asd->misc_app_id = APP_ID_NONE;
+    asd->payload.set_id(APP_ID_NONE);
+    asd->client.set_id(APP_ID_CURL);
+    asd->service.set_id(APP_ID_FTP);
+
+    AppIdDiscovery::do_application_discovery(&p, ins);
+
+    // Detect event for FTP service and CURL client
+    CHECK_EQUAL(databus_publish_called, true);
+    CHECK_EQUAL(asd->client.get_id(), APP_ID_CURL);
+    CHECK_EQUAL(asd->service.get_id(), APP_ID_FTP);
+
+    // Testing DNS appid
+    databus_publish_called = false;
+    asd->misc_app_id = APP_ID_NONE;
+    asd->payload.set_id(APP_ID_NONE);
+    asd->client.set_id(APP_ID_NONE);
+    asd->service.set_id(APP_ID_DNS);
+    AppIdDiscovery::do_application_discovery(&p, ins);
+
+    // Detect event for DNS service
+    CHECK_EQUAL(databus_publish_called, true);
+    CHECK_EQUAL(asd->service.get_id(), APP_ID_DNS);
+
+    delete asd;
+    delete flow;
+}
+
+TEST(appid_discovery_tests, change_bits_to_string)
+{
+    // Testing that all bits from AppidChangeBit enum get translated
+    AppidChangeBits change_bits;
+    std::string str;
+
+    // Detect empty
+    change_bits_to_string(change_bits, str);
+    STRCMP_EQUAL(str.c_str(), "");
+
+    // Detect all; failure of this test means some bits from enum are missed in translation
+    change_bits.set();
+    change_bits_to_string(change_bits, str);
+    STRCMP_EQUAL(str.c_str(), "service, client, payload, misc, referred, host,"
+        " tls-host, url, user-agent, response, referrer, xff, client-version");
+
+    // Detect enum vs translator mismatch actually working
+    std::bitset<APPID_MAX_BIT+1> change_bits_extra;
+    change_bits_extra.set();
+    str.clear();
+    change_bits_to_string(*((AppidChangeBits*) &change_bits_extra), str);
+    STRCMP_EQUAL(str.c_str(), "service, client, payload, misc, referred, host, tls-host, url,"
+        " user-agent, response, referrer, xff, client-version, change_bits_to_string error!");
+}
+
+int main(int argc, char** argv)
+{
+    int rc = CommandLineTestRunner::RunAllTests(argc, argv);
+    return rc;
+}
index 2566107be83235be29725ca8425907f4ef46ef1c..535143485f805b57870e40827e62016d03268eeb 100644 (file)
@@ -28,6 +28,8 @@
 #include <CppUTest/CommandLineTestRunner.h>
 #include <CppUTest/TestHarness.h>
 
+void AppIdHttpSession::set_http_change_bits(AppidChangeBits&, HttpFieldIds) {}
+
 class MockServiceDetector : public ServiceDetector
 {
 public:
index 3fd01a84a54c31d02cf8a51f90ce23f6c13177ff..e292138c78072f66e362162378d6f023f08260fa 100644 (file)
@@ -68,6 +68,10 @@ class FakeHttpMsgHeader
 };
 FakeHttpMsgHeader* fake_msg_header = nullptr;
 
+void AppIdDiscovery::publish_appid_event(AppidChangeBits&, snort::Flow*) {}
+
+void AppIdHttpSession::set_http_change_bits(AppidChangeBits&, HttpFieldIds) {}
+
 const uint8_t* HttpEvent::get_content_type(int32_t& length)
 {
     global_field.set(0, nullptr);
index 20bc67d125bd0a183b26cb2d7769268e4143bb54..2afc0fd9aae7b028c57397d8dbd3d96e6dd71cbe 100644 (file)
@@ -91,8 +91,9 @@ AppId HttpPatternMatchers::get_appid_by_content_type(const char*, int)
 }
 
 bool HttpPatternMatchers::get_appid_from_url(char*, const char*, char**,
-    const char*, AppId*, AppId*, AppId*, AppId*, bool)
+    const char*, AppId*, AppId*, AppId*, AppId* referredPayloadAppId, bool)
 {
+    *referredPayloadAppId = APP_ID_FACEBOOK;
     return true;
 }
 
@@ -106,15 +107,15 @@ AppIdSession::~AppIdSession()
 {
 }
 
-void AppIdSession::set_client_appid_data(AppId, char*)
+void AppIdSession::set_client_appid_data(AppId, char*, AppidChangeBits&)
 {
 }
 
-void AppIdSession::set_service_appid_data(AppId, char*, char*)
+void AppIdSession::set_service_appid_data(AppId, char*, char*, AppidChangeBits&)
 {
 }
 
-void AppIdSession::set_payload_appid_data(AppId, char*)
+void AppIdSession::set_payload_appid_data(AppId, char*, AppidChangeBits&)
 {
 }
 
@@ -131,8 +132,16 @@ bool AppIdSession::is_payload_appid_set()
     return true;
 }
 
-void AppIdSession::set_referred_payload_app_id_data(AppId)
+void AppIdSession::set_referred_payload_app_id_data(AppId id, AppidChangeBits& change_bits)
 {
+    if (id <= APP_ID_NONE)
+        return;
+
+    if (referred_payload_app_id != id)
+    {
+        referred_payload_app_id = id;
+        change_bits.set(APPID_REFERRED_BIT);
+    }
 }
 
 // AppIdDebug mock functions
@@ -205,20 +214,22 @@ TEST(appid_http_session, http_field_ids_enum_order)
     // Set the fields using integers, then get them by HttpFieldIds,
     // to make sure the order of the HttpFieldIds has not changed
     // in appid_http_session.h.
-    hsession.set_field( (HttpFieldIds)0, new std::string("agent") );
-    hsession.set_field( (HttpFieldIds)1, new std::string("host") );
-    hsession.set_field( (HttpFieldIds)2, new std::string("referer") );
-    hsession.set_field( (HttpFieldIds)3, new std::string("uri") );
-    hsession.set_field( (HttpFieldIds)4, new std::string("cookie") );
-    hsession.set_field( (HttpFieldIds)5, new std::string("req_body") );
-    hsession.set_field( (HttpFieldIds)6, new std::string("content_type") );
-    hsession.set_field( (HttpFieldIds)7, new std::string("location") );
-    hsession.set_field( (HttpFieldIds)8, new std::string("rsp_body") );
-    hsession.set_field( (HttpFieldIds)9, new std::string("via") );
-    hsession.set_field( (HttpFieldIds)10, new std::string("response_code") );
-    hsession.set_field( (HttpFieldIds)11, new std::string("server") );
-    hsession.set_field( (HttpFieldIds)12, new std::string("xww") );
-    hsession.set_field( (HttpFieldIds)13, new std::string("url") );
+    AppidChangeBits change_bits;
+
+    hsession.set_field( (HttpFieldIds)0, new std::string("agent"), change_bits );
+    hsession.set_field( (HttpFieldIds)1, new std::string("host"), change_bits );
+    hsession.set_field( (HttpFieldIds)2, new std::string("referer"), change_bits );
+    hsession.set_field( (HttpFieldIds)3, new std::string("uri"), change_bits );
+    hsession.set_field( (HttpFieldIds)4, new std::string("cookie"), change_bits );
+    hsession.set_field( (HttpFieldIds)5, new std::string("req_body"), change_bits );
+    hsession.set_field( (HttpFieldIds)6, new std::string("content_type"), change_bits );
+    hsession.set_field( (HttpFieldIds)7, new std::string("location"), change_bits );
+    hsession.set_field( (HttpFieldIds)8, new std::string("rsp_body"), change_bits );
+    hsession.set_field( (HttpFieldIds)9, new std::string("via"), change_bits );
+    hsession.set_field( (HttpFieldIds)10, new std::string("response_code"), change_bits );
+    hsession.set_field( (HttpFieldIds)11, new std::string("server"), change_bits );
+    hsession.set_field( (HttpFieldIds)12, new std::string("xww"), change_bits );
+    hsession.set_field( (HttpFieldIds)13, new std::string("url"), change_bits );
 
     const std::string* field;
     field = hsession.get_field(REQ_AGENT_FID);
@@ -249,6 +260,29 @@ TEST(appid_http_session, http_field_ids_enum_order)
     STRCMP_EQUAL(field->c_str(), "xww");
     field = hsession.get_field(MISC_URL_FID);
     STRCMP_EQUAL(field->c_str(), "url");
+
+    // Detect changes in host, url, user agent, response, and referer fields
+    // that generate appid event consumed by subscribers
+    CHECK_EQUAL(change_bits.test(APPID_HOST_BIT), true);
+    CHECK_EQUAL(change_bits.test(APPID_URL_BIT), true);
+    CHECK_EQUAL(change_bits.test(APPID_USERAGENT_BIT), true);
+    CHECK_EQUAL(change_bits.test(APPID_RESPONSE_BIT), true);
+    CHECK_EQUAL(change_bits.test(APPID_REFERER_BIT), true);
+}
+
+TEST(appid_http_session, change_bits_for_referred_appid)
+{
+    // Testing set_referred_payload_app_id_data
+    AppidChangeBits change_bits;
+    AppIdPegCounts::init_pegs();
+    session.service.set_id(APP_ID_HTTP);
+    session.scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
+    hsession.set_skip_simple_detect(false);
+    hsession.set_field( (HttpFieldIds)2, new std::string("referer"), change_bits );
+    hsession.process_http_packet(APP_ID_FROM_INITIATOR, change_bits);
+
+    // Detect changes in referred appid
+    CHECK_EQUAL(change_bits.test(APPID_REFERRED_BIT), true);
 }
 
 int main(int argc, char** argv)
index e29551568454809b7afeb87f09c082633618f833..b2410d701bf2c4e0d3f804f3b04e0ef6236086e9 100644 (file)
@@ -43,7 +43,7 @@ AppIdHttpSession::~AppIdHttpSession()
     }
 }
 
-int AppIdHttpSession::process_http_packet(AppidSessionDirection) { return 0; }
+int AppIdHttpSession::process_http_packet(AppidSessionDirection, AppidChangeBits&) { return 0; }
 
 char const* APPID_UT_XFF_IP_ADDR = "192.168.0.1";
 char const* CONTENT_TYPE = "html/text";
@@ -65,7 +65,7 @@ char const* RSP_BODY = "this is the body of the http response";
 #define URI_OFFSET 22
 #define COOKIE_OFFSET 44
 
-void AppIdHttpSession::update_url()
+void AppIdHttpSession::update_url(AppidChangeBits&)
 {
     const std::string* host = meta_data[REQ_HOST_FID];
     const std::string* uri = meta_data[REQ_URI_FID];
@@ -108,19 +108,6 @@ public:
         meta_offset[REQ_COOKIE_FID].second = COOKIE_OFFSET + strlen(NEW_COOKIE);
     }
 
-    void init_hsession_new_fields()
-    {
-        set_field(REQ_AGENT_FID, new std::string(USERAGENT));
-        set_field(REQ_HOST_FID, new std::string(HOST));
-        set_field(REQ_REFERER_FID, new std::string(REFERER));
-        set_field(REQ_URI_FID, new std::string(URI));
-        set_field(REQ_COOKIE_FID, new std::string(COOKIE));
-        set_field(REQ_BODY_FID, new std::string(REQ_BODY));
-        set_field(RSP_CONTENT_TYPE_FID, new std::string(CONTENT_TYPE));
-        set_field(RSP_LOCATION_FID, new std::string(LOCATION));
-        set_field(RSP_BODY_FID, new std::string(RSP_BODY));
-    }
-
     void reset()
     {
         for ( int i = 0; i < NUM_METADATA_FIELDS; i++)
index 2af7082d131d3eba921fae377c2947b846a2783d..d5cc0f372048f4cd25154c156941f40b4e5df338 100644 (file)
@@ -73,18 +73,18 @@ AppIdSession::AppIdSession(IpProtocol, const SfIp*, uint16_t, AppIdInspector& in
 {
     common.flow_type = APPID_FLOW_TYPE_NORMAL;
     service_port = APPID_UT_SERVICE_PORT;
+    AppidChangeBits change_bits;
 
     client.update_user(APPID_UT_ID, APPID_UT_USERNAME);
-    client.set_version(APPID_UT_CLIENT_VERSION);
+    client.set_version(APPID_UT_CLIENT_VERSION, change_bits);
 
     service.set_vendor(APPID_UT_SERVICE_VENDOR);
-    service.set_version(APPID_UT_SERVICE_VERSION);
+    service.set_version(APPID_UT_SERVICE_VERSION, change_bits);
     subtype = &APPID_UT_SERVICE_SUBTYPE;
 
     search_support_type = UNKNOWN_SEARCH_ENGINE;
 
     tsession = new TlsSession;
-    tsession->tls_host = (char*)APPID_UT_TLS_HOST;
 
     service_ip.pton(AF_INET, APPID_UT_SERVICE_IP_ADDR);
     common.initiator_ip.pton(AF_INET, APPID_UT_INITIATOR_IP_ADDR);
@@ -166,26 +166,49 @@ void* AppIdSession::remove_flow_data(unsigned type)
     return data;
 }
 
-void AppIdSession::set_application_ids(AppId, AppId, AppId, AppId) { }
+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)
+    {
+        application_ids[APP_PROTOID_SERVICE] = service_id;
+        change_bits.set(APPID_SERVICE_BIT);
+    }
+    if (application_ids[APP_PROTOID_CLIENT] != client_id)
+    {
+        application_ids[APP_PROTOID_CLIENT] = client_id;
+        change_bits.set(APPID_CLIENT_BIT);
+    }
+    if (application_ids[APP_PROTOID_PAYLOAD] != payload_id)
+    {
+        application_ids[APP_PROTOID_PAYLOAD] = payload_id;
+        change_bits.set(APPID_PAYLOAD_BIT);
+    }
+    if (application_ids[APP_PROTOID_MISC] != misc_id)
+    {
+        application_ids[APP_PROTOID_MISC] = misc_id;
+        change_bits.set(APPID_MISC_BIT);
+    }
+}
 
 AppId AppIdSession::pick_service_app_id()
 {
-    return APPID_UT_ID;
+    return service.get_id();
 }
 
 AppId AppIdSession::pick_misc_app_id()
 {
-    return APPID_UT_ID;
+    return misc_app_id;
 }
 
 AppId AppIdSession::pick_client_app_id()
 {
-    return APPID_UT_ID;
+    return client.get_id();
 }
 
 AppId AppIdSession::pick_payload_app_id()
 {
-    return APPID_UT_ID;
+    return payload.get_id();
 }
 
 AppId AppIdSession::pick_referred_payload_app_id()
index 929e6f0e6621bb25cbb555fabd8c1586bfa70b75..11276a14894f2ddf8b57b2783dd56cdd9937050e 100644 (file)
@@ -129,6 +129,8 @@ TEST(appid_session_api, get_http_search)
 
 TEST(appid_session_api, get_tls_host)
 {
+    AppidChangeBits change_bits;
+    mock_session->tsession->set_tls_host(APPID_UT_TLS_HOST, 0, change_bits);
     const char* val = appid_session_api->get_tls_host();
     STRCMP_EQUAL(val, APPID_UT_TLS_HOST);
 }
@@ -226,7 +228,7 @@ TEST(appid_session_api, get_user_name)
     CHECK_TRUE(service == APPID_UT_ID);
     CHECK_TRUE(!isLoginSuccessful);
     mock_session->set_session_flags(APPID_SESSION_LOGIN_SUCCEEDED);
-    val = appid_session_api->get_user_name(&service, &isLoginSuccessful);
+    appid_session_api->get_user_name(&service, &isLoginSuccessful);
     CHECK_TRUE(service == APPID_UT_ID);
     CHECK_TRUE(isLoginSuccessful);
 }
index 389065c7b37196c87971706727137e0d93f91d41..797859f52880a9c07a9c6b5de01aa8b9da13bf41 100644 (file)
@@ -88,9 +88,11 @@ void ServiceDiscovery::finalize_service_patterns() {}
 void ServiceDiscovery::match_by_pattern(AppIdSession&, const Packet*, IpProtocol) {}
 void ServiceDiscovery::get_port_based_services(IpProtocol, uint16_t, AppIdSession&) {}
 void ServiceDiscovery::get_next_service(const Packet*, const AppidSessionDirection, AppIdSession&) {}
-int ServiceDiscovery::identify_service(AppIdSession&, Packet*, AppidSessionDirection) { return 0; }
+int ServiceDiscovery::identify_service(AppIdSession&, Packet*, AppidSessionDirection,
+    AppidChangeBits&) { return 0; }
 int ServiceDiscovery::add_ftp_service_state(AppIdSession&) { return 0; }
-bool ServiceDiscovery::do_service_discovery(AppIdSession&, Packet*, AppidSessionDirection) { return 0; }
+bool ServiceDiscovery::do_service_discovery(AppIdSession&, Packet*, AppidSessionDirection,
+    AppidChangeBits&) { return 0; }
 int ServiceDiscovery::incompatible_data(AppIdSession&, const Packet*,AppidSessionDirection,
     ServiceDetector*) { return 0; }
 int ServiceDiscovery::fail_service(AppIdSession&, const Packet*, AppidSessionDirection,
index b6973e6d97dcbc3ce4957e854cf46d6b074f8641..5a9f64240a13e9f758a3bdd628936eb73f8a2c3b 100644 (file)
@@ -95,7 +95,7 @@ static inline int check_ssl_appid_for_reinspect(AppId app_id)
 // Or, register observers with THirdPartyAppIDAttributeData and modify the
 // set functions to copy the tp buffers directly into the appropriate observer.
 static inline void process_http_session(AppIdSession& asd,
-    ThirdPartyAppIDAttributeData& attribute_data)
+    ThirdPartyAppIDAttributeData& attribute_data, AppidChangeBits& change_bits)
 {
     AppIdHttpSession* hsession = asd.get_http_session();
     string* field=0;
@@ -125,7 +125,7 @@ static inline void process_http_session(AppIdSession& asd,
             if ( hsession->get_field(MISC_URL_FID) )
                 hsession->set_chp_finished(false);
 
-            hsession->set_field(MISC_URL_FID, url);
+            hsession->set_field(MISC_URL_FID, url, change_bits);
             asd.scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
         }
 
@@ -134,7 +134,7 @@ static inline void process_http_session(AppIdSession& asd,
             if (hsession->get_field(REQ_HOST_FID))
                 hsession->set_chp_finished(false);
 
-            hsession->set_field(REQ_HOST_FID, spdyRequestHost);
+            hsession->set_field(REQ_HOST_FID, spdyRequestHost, change_bits);
             hsession->set_offset(REQ_HOST_FID,
                 attribute_data.spdy_request_host_begin(),
                 attribute_data.spdy_request_host_end());
@@ -152,7 +152,7 @@ static inline void process_http_session(AppIdSession& asd,
             if ( hsession->get_field(REQ_URI_FID) )
                 hsession->set_chp_finished(false);
 
-            hsession->set_field(REQ_URI_FID, spdyRequestPath);
+            hsession->set_field(REQ_URI_FID, spdyRequestPath, change_bits);
             hsession->set_offset(REQ_URI_FID,
                 attribute_data.spdy_request_path_begin(),
                 attribute_data.spdy_request_path_end());
@@ -171,7 +171,7 @@ static inline void process_http_session(AppIdSession& asd,
                 if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
                     hsession->set_chp_finished(false);
 
-            hsession->set_field(REQ_HOST_FID, field);
+            hsession->set_field(REQ_HOST_FID, field, change_bits);
             hsession->set_offset(REQ_HOST_FID,
                 attribute_data.http_request_host_begin(),
                 attribute_data.http_request_host_end());
@@ -201,7 +201,7 @@ static inline void process_http_session(AppIdSession& asd,
                 // In all other cases field can be const string*.
                 field->insert(4, 1, 's');
             }
-            hsession->set_field(MISC_URL_FID, field);
+            hsession->set_field(MISC_URL_FID, field, change_bits);
             asd.scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
         }
 
@@ -211,7 +211,7 @@ static inline void process_http_session(AppIdSession& asd,
                 if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
                     hsession->set_chp_finished(false);
 
-            hsession->set_field(REQ_URI_FID, field);
+            hsession->set_field(REQ_URI_FID, field, change_bits);
             hsession->set_offset(REQ_URI_FID,
                 attribute_data.http_request_uri_begin(),
                 attribute_data.http_request_uri_end());
@@ -230,7 +230,7 @@ static inline void process_http_session(AppIdSession& asd,
             if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
                 hsession->set_chp_finished(false);
 
-        hsession->set_field(MISC_VIA_FID, field);
+        hsession->set_field(MISC_VIA_FID, field, change_bits);
         asd.scan_flags |= SCAN_HTTP_VIA_FLAG;
     }
     else if ( (field=attribute_data.http_response_via(own)) != nullptr )
@@ -239,7 +239,7 @@ static inline void process_http_session(AppIdSession& asd,
             if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
                 hsession->set_chp_finished(false);
 
-        hsession->set_field(MISC_VIA_FID, field);
+        hsession->set_field(MISC_VIA_FID, field, change_bits);
         asd.scan_flags |= SCAN_HTTP_VIA_FLAG;
     }
 
@@ -249,7 +249,7 @@ static inline void process_http_session(AppIdSession& asd,
             if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
                 hsession->set_chp_finished(false);
 
-        hsession->set_field(REQ_AGENT_FID, field);
+        hsession->set_field(REQ_AGENT_FID, field, change_bits);
         hsession->set_offset(REQ_AGENT_FID,
             attribute_data.http_request_user_agent_begin(),
             attribute_data.http_request_user_agent_end());
@@ -286,7 +286,7 @@ static inline void process_http_session(AppIdSession& asd,
             if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
                 hsession->set_chp_finished(false);
 
-        hsession->set_field(MISC_RESP_CODE_FID, field);
+        hsession->set_field(MISC_RESP_CODE_FID, field, change_bits);
     }
 
     // Check to see if we've got an upgrade to HTTP/2 (if enabled).
@@ -318,7 +318,7 @@ static inline void process_http_session(AppIdSession& asd,
             if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
                 hsession->set_chp_finished(false);
 
-        hsession->set_field(REQ_REFERER_FID, field);
+        hsession->set_field(REQ_REFERER_FID, field, change_bits);
         hsession->set_offset(REQ_REFERER_FID,
             attribute_data.http_request_referer_begin(),
             attribute_data.http_request_referer_end());
@@ -335,7 +335,7 @@ static inline void process_http_session(AppIdSession& asd,
             if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
                 hsession->set_chp_finished(false);
 
-        hsession->set_field(REQ_COOKIE_FID, field);
+        hsession->set_field(REQ_COOKIE_FID, field, change_bits);
         hsession->set_offset(REQ_COOKIE_FID,
             attribute_data.http_request_cookie_begin(),
             attribute_data.http_request_cookie_end());
@@ -352,7 +352,7 @@ static inline void process_http_session(AppIdSession& asd,
             if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
                 hsession->set_chp_finished(false);
 
-        hsession->set_field(RSP_CONTENT_TYPE_FID, field);
+        hsession->set_field(RSP_CONTENT_TYPE_FID, field, change_bits);
         asd.scan_flags |= SCAN_HTTP_CONTENT_TYPE_FLAG;
     }
 
@@ -362,7 +362,7 @@ static inline void process_http_session(AppIdSession& asd,
         if ( hsession->get_field(RSP_LOCATION_FID) )
             if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
                 hsession->set_chp_finished(false);
-        hsession->set_field(RSP_LOCATION_FID, field);
+        hsession->set_field(RSP_LOCATION_FID, field, change_bits);
     }
 
     if ( (field=attribute_data.http_request_body(own)) != nullptr )
@@ -373,7 +373,7 @@ static inline void process_http_session(AppIdSession& asd,
         if ( hsession->get_field(REQ_BODY_FID) )
             if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
                 hsession->set_chp_finished(false);
-        hsession->set_field(REQ_BODY_FID, field);
+        hsession->set_field(REQ_BODY_FID, field, change_bits);
     }
 
     if (hsession->get_ptype_scan_count(RSP_BODY_FID) &&
@@ -382,12 +382,12 @@ static inline void process_http_session(AppIdSession& asd,
         if (hsession->get_field(RSP_BODY_FID) )
             if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
                 hsession->set_chp_finished(false);
-        hsession->set_field(RSP_BODY_FID, field);
+        hsession->set_field(RSP_BODY_FID, field, change_bits);
     }
 
     if (attribute_data.numXffFields)
         hsession->update_http_xff_address(attribute_data.xffFieldValue,
-            attribute_data.numXffFields);
+            attribute_data.numXffFields, change_bits);
 
     if (!hsession->is_chp_finished() || hsession->is_chp_hold_flow())
     {
@@ -397,19 +397,19 @@ static inline void process_http_session(AppIdSession& asd,
 
     if ( (field=attribute_data.http_response_server(own)) != nullptr)
     {
-        hsession->set_field(MISC_SERVER_FID, field);
+        hsession->set_field(MISC_SERVER_FID, field, change_bits);
         asd.scan_flags |= SCAN_HTTP_VENDOR_FLAG;
     }
 
     if ( (field=attribute_data.http_request_x_working_with(own)) != nullptr )
     {
-        hsession->set_field(MISC_XWW_FID, field);
+        hsession->set_field(MISC_XWW_FID, field, change_bits);
         asd.scan_flags |= SCAN_HTTP_XWORKINGWITH_FLAG;
     }
 }
 
 static inline void process_rtmp(AppIdSession& asd,
-    ThirdPartyAppIDAttributeData& attribute_data, int confidence)
+    ThirdPartyAppIDAttributeData& attribute_data, int confidence, AppidChangeBits& change_bits)
 {
     AppIdHttpSession* hsession = asd.get_http_session();
     AppId service_id = 0;
@@ -425,7 +425,7 @@ static inline void process_rtmp(AppIdSession& asd,
     {
         if ( ( field=attribute_data.http_request_url(own) ) != nullptr )
         {
-            hsession->set_field(MISC_URL_FID, field);
+            hsession->set_field(MISC_URL_FID, field, change_bits);
             asd.scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
         }
     }
@@ -435,7 +435,7 @@ static inline void process_rtmp(AppIdSession& asd,
     {
         if ( ( field=attribute_data.http_request_referer(own) ) != nullptr )
         {
-            hsession->set_field(REQ_REFERER_FID, field);
+            hsession->set_field(REQ_REFERER_FID, field, change_bits);
         }
     }
 
@@ -443,7 +443,7 @@ static inline void process_rtmp(AppIdSession& asd,
     {
         if ( ( field=attribute_data.http_request_user_agent(own) ) != nullptr )
         {
-            hsession->set_field(REQ_AGENT_FID, field);
+            hsession->set_field(REQ_AGENT_FID, field, change_bits);
             hsession->set_offset(REQ_AGENT_FID,
                 attribute_data.http_request_user_agent_begin(),
                 attribute_data.http_request_user_agent_end());
@@ -464,11 +464,11 @@ static inline void process_rtmp(AppIdSession& asd,
         http_matchers->identify_user_agent(field->c_str(), size, service_id, 
         client_id, &version);
         
-        asd.set_client_appid_data(client_id, version);
+        asd.set_client_appid_data(client_id, version, change_bits);
         
         // do not overwrite a previously-set service
         if ( service_id <= APP_ID_NONE )
-            asd.set_service_appid_data(service_id, nullptr, nullptr);
+            asd.set_service_appid_data(service_id, nullptr, nullptr, change_bits);
         
         asd.scan_flags |= ~SCAN_HTTP_USER_AGENT_FLAG;
         snort_free(version);
@@ -492,13 +492,13 @@ static inline void process_rtmp(AppIdSession& asd,
             {
                 // do not overwrite a previously-set client or service
                 if ( client_id <= APP_ID_NONE )
-                    asd.set_client_appid_data(client_id, nullptr);
+                    asd.set_client_appid_data(client_id, nullptr, change_bits);
                 if ( service_id <= APP_ID_NONE )
-                    asd.set_service_appid_data(service_id, nullptr, nullptr);
+                    asd.set_service_appid_data(service_id, nullptr, nullptr, change_bits);
 
                 // DO overwrite a previously-set data
-                asd.set_payload_appid_data(payload_id, nullptr);
-                asd.set_referred_payload_app_id_data(referred_payload_app_id);
+                asd.set_payload_appid_data(payload_id, nullptr, change_bits);
+                asd.set_referred_payload_app_id_data(referred_payload_app_id, change_bits);
             }
         }
 
@@ -511,7 +511,7 @@ static inline void process_rtmp(AppIdSession& asd,
 }
 
 static inline void process_ssl(AppIdSession& asd,
-    ThirdPartyAppIDAttributeData& attribute_data)
+    ThirdPartyAppIDAttributeData& attribute_data, AppidChangeBits& change_bits)
 {
     AppId tmpAppId = APP_ID_NONE;
     int tmpConfidence = 0;
@@ -526,11 +526,11 @@ static inline void process_ssl(AppIdSession& asd,
         asd.tsession = (TlsSession*)snort_calloc(sizeof(TlsSession));
 
     if (!asd.client.get_id())
-        asd.set_client_appid_data(APP_ID_SSL_CLIENT, nullptr);
+        asd.set_client_appid_data(APP_ID_SSL_CLIENT, nullptr, change_bits);
 
     if ( (field=attribute_data.tls_host(false)) != nullptr )
     {
-        asd.tsession->set_tls_host(field->c_str(), field->size());
+        asd.tsession->set_tls_host(field->c_str(), field->size(), change_bits);
         if (check_ssl_appid_for_reinspect(tmpAppId))
             asd.scan_flags |= SCAN_SSL_HOST_FLAG;
     }
@@ -563,7 +563,8 @@ static inline void process_ftp_control(AppIdSession& asd,
 }
 
 static inline void process_third_party_results(AppIdSession& asd, int confidence,
-    vector<AppId>& proto_list, ThirdPartyAppIDAttributeData& attribute_data)
+    vector<AppId>& proto_list, ThirdPartyAppIDAttributeData& attribute_data,
+    AppidChangeBits& change_bits)
 {
     if ( asd.payload.get_id() == APP_ID_NONE and contains(proto_list, APP_ID_EXCHANGE) )
         asd.payload.set_id(APP_ID_EXCHANGE);
@@ -584,14 +585,14 @@ static inline void process_third_party_results(AppIdSession& asd, int confidence
     }
 
     if (asd.get_session_flags(APPID_SESSION_HTTP_SESSION))
-        process_http_session(asd, attribute_data);
+        process_http_session(asd, attribute_data, change_bits);
 
     else if (contains(proto_list, APP_ID_RTMP) ||
         contains(proto_list, APP_ID_RTSP) )
-        process_rtmp(asd, attribute_data, confidence);
+        process_rtmp(asd, attribute_data, confidence, change_bits);
 
     else if (contains(proto_list, APP_ID_SSL))
-        process_ssl(asd, attribute_data);
+        process_ssl(asd, attribute_data, change_bits);
 
     else if (contains(proto_list, APP_ID_FTP_CONTROL))
         process_ftp_control(asd, attribute_data);
@@ -620,7 +621,7 @@ static inline void check_terminate_tp_module(AppIdSession& asd, uint16_t tpPktCo
 }
 
 bool do_tp_discovery(AppIdSession& asd, IpProtocol protocol,
-    Packet* p, AppidSessionDirection& direction)
+    Packet* p, AppidSessionDirection& direction, AppidChangeBits& change_bits)
 {
     if ( !TPLibHandler::have_tp() )
         return true;
@@ -717,7 +718,8 @@ bool do_tp_discovery(AppIdSession& asd, IpProtocol protocol,
                 if ( app_info_flags & APPINFO_FLAG_TP_CLIENT )
                     asd.client.set_id(tp_app_id);
 
-                process_third_party_results(asd, tp_confidence, tp_proto_list, tp_attribute_data);
+                process_third_party_results(asd, tp_confidence, tp_proto_list, tp_attribute_data,
+                    change_bits);
 
                 if (asd.get_session_flags(APPID_SESSION_SSL_SESSION) &&
                     !(asd.scan_flags & SCAN_SSL_HOST_FLAG))
@@ -776,13 +778,13 @@ bool do_tp_discovery(AppIdSession& asd, IpProtocol protocol,
 
                     // Handle HTTP tunneling and SSL possibly then being used in that tunnel
                     if (tp_app_id == APP_ID_HTTP_TUNNEL)
-                        asd.set_payload_appid_data(APP_ID_HTTP_TUNNEL, NULL);
+                        asd.set_payload_appid_data(APP_ID_HTTP_TUNNEL, NULL, change_bits);
                     else if ((asd.payload.get_id() == APP_ID_HTTP_TUNNEL) &&
                         (tp_app_id == APP_ID_SSL))
-                        asd.set_payload_appid_data(APP_ID_HTTP_SSL_TUNNEL, NULL);
+                        asd.set_payload_appid_data(APP_ID_HTTP_SSL_TUNNEL, NULL, change_bits);
 
                     AppIdHttpSession* hsession = asd.get_http_session();
-                    hsession->process_http_packet(direction);
+                    hsession->process_http_packet(direction, change_bits);
 
                     // If SSL over HTTP tunnel, make sure Snort knows that it's encrypted.
                     if (asd.payload.get_id() == APP_ID_HTTP_SSL_TUNNEL)
@@ -811,7 +813,7 @@ bool do_tp_discovery(AppIdSession& asd, IpProtocol protocol,
                 }
                 else if (asd.get_session_flags(APPID_SESSION_SSL_SESSION) && asd.tsession)
                 {
-                    asd.examine_ssl_metadata(p);
+                    asd.examine_ssl_metadata(p, change_bits);
                     uint16_t serverPort;
                     AppId portAppId;
                     serverPort = (direction == APP_ID_FROM_INITIATOR) ? p->ptrs.dp : p->ptrs.sp;
index d3398f039aa3f5e42f09b15b6e7aef0513eb4d66..089ea1d743dccaeb6fc4384f9912aff644d7fd5e 100644 (file)
@@ -26,6 +26,7 @@
 
 class AppIdSession;
 
-bool do_tp_discovery(AppIdSession&, IpProtocol, snort::Packet*, AppidSessionDirection&);
+bool do_tp_discovery(AppIdSession&, IpProtocol, snort::Packet*, AppidSessionDirection&,
+    AppidChangeBits&);
 
 #endif
index e3c60d48e534dfbec4736e8b654b2df7acd3aed8..0d32afee12d1ea49f828d9c38565777db8332f30 100644 (file)
@@ -1,4 +1,5 @@
 set (PUB_SUB_INCLUDES
+    appid_events.h
     expect_events.h
     http_events.h
     sip_events.h
diff --git a/src/pub_sub/appid_events.h b/src/pub_sub/appid_events.h
new file mode 100644 (file)
index 0000000..794af10
--- /dev/null
@@ -0,0 +1,105 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2017-2018 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.
+//--------------------------------------------------------------------------
+// appid_events.h author Masud Hasan <mashasan@cisco.com>
+
+#ifndef APPID_EVENTS_H
+#define APPID_EVENTS_H
+
+// This event conveys data published by the appid module to be consumed by data bus subscribers
+
+#include <bitset>
+
+#include "framework/data_bus.h"
+
+#define APPID_EVENT_ANY_CHANGE "appid_event_any_change"
+
+// Events are added as needed by subscribers
+// Any change here should also change change_bits_to_string()
+enum AppidChangeBit
+{
+    // id
+    APPID_SERVICE_BIT = 0,
+    APPID_CLIENT_BIT,
+    APPID_PAYLOAD_BIT,
+    APPID_MISC_BIT,
+    APPID_REFERRED_BIT,
+
+    // http
+    APPID_HOST_BIT,
+    APPID_TLSHOST_BIT,
+    APPID_URL_BIT,
+    APPID_USERAGENT_BIT,
+    APPID_RESPONSE_BIT,
+    APPID_REFERER_BIT,
+    APPID_XFF_BIT,
+
+    // other
+    APPID_VERSION_BIT,
+
+    APPID_MAX_BIT
+};
+
+typedef std::bitset<APPID_MAX_BIT> AppidChangeBits;
+
+inline void change_bits_to_string(AppidChangeBits& change_bits, std::string& str)
+{
+    size_t n = change_bits.count();
+
+    if (change_bits.test(APPID_SERVICE_BIT))
+        --n? str.append("service, ") : str.append("service");
+    if (change_bits.test(APPID_CLIENT_BIT))
+        --n? str.append("client, ") : str.append("client");
+    if (change_bits.test(APPID_PAYLOAD_BIT))
+        --n? str.append("payload, ") : str.append("payload");
+    if (change_bits.test(APPID_MISC_BIT))
+        --n? str.append("misc, ") : str.append("misc");
+    if (change_bits.test(APPID_REFERRED_BIT))
+        --n? str.append("referred, ") : str.append("referred");
+    if (change_bits.test(APPID_HOST_BIT))
+        --n? str.append("host, ") : str.append("host");
+    if (change_bits.test(APPID_TLSHOST_BIT))
+        --n? str.append("tls-host, ") : str.append("tls-host");
+    if (change_bits.test(APPID_URL_BIT))
+        --n? str.append("url, ") : str.append("url");
+    if (change_bits.test(APPID_USERAGENT_BIT))
+        --n? str.append("user-agent, ") : str.append("user-agent");
+    if (change_bits.test(APPID_RESPONSE_BIT))
+        --n? str.append("response, ") : str.append("response");
+    if (change_bits.test(APPID_REFERER_BIT))
+        --n? str.append("referrer, ") : str.append("referrer");
+    if (change_bits.test(APPID_XFF_BIT))
+        --n? str.append("xff, ") : str.append("xff");
+    if (change_bits.test(APPID_VERSION_BIT))
+        --n? str.append("client-version, ") : str.append("client-version");
+    if (n != 0) // make sure all bits from AppidChangeBit enum get translated
+        str.append("change_bits_to_string error!");
+}
+
+class AppidEvent : public snort::DataEvent
+{
+public:
+    AppidEvent(const AppidChangeBits& ac) : ac_bits(ac) {}
+
+    const AppidChangeBits& get_change_bitset()
+    { return ac_bits; }
+
+private:
+    const AppidChangeBits& ac_bits;
+};
+
+#endif