]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #2377 in SNORT/snort3 from ~DIPANDIT/snort3:smb_cleanup_issue...
authorBhargava Jandhyala (bjandhya) <bjandhya@cisco.com>
Wed, 5 Aug 2020 17:29:00 +0000 (17:29 +0000)
committerBhargava Jandhyala (bjandhya) <bjandhya@cisco.com>
Wed, 5 Aug 2020 17:29:00 +0000 (17:29 +0000)
Squashed commit of the following:

commit a95dd780fea35355517468baedc519ae5e6c0c2f
Author: dipto <dipandit@cisco.com>
Date:   Wed Aug 5 10:49:23 2020 -0400

    dce_rpc: fix for smb crash while tcp session pruning

src/service_inspectors/dce_rpc/dce_smb2.cc
src/service_inspectors/dce_rpc/dce_smb2.h
src/service_inspectors/dce_rpc/dce_smb2_commands.cc
src/service_inspectors/dce_rpc/dce_smb2_utils.cc
src/service_inspectors/dce_rpc/dce_smb2_utils.h

index 1afb65ea787e917cebfbe6bdb0c2676be72ca38d..57642c723ec3000b81d72954aa4035bddeaf56d9 100644 (file)
 
 using namespace snort;
 
-void get_flow_key(SmbFlowKey* key)
+static inline SmbFlowKey get_flow_key(void)
 {
+    SmbFlowKey key;
     const FlowKey* flow_key = DetectionEngine::get_current_packet()->flow->key;
 
-    key->ip_l[0] = flow_key->ip_l[0];
-    key->ip_l[1] = flow_key->ip_l[1];
-    key->ip_l[2] = flow_key->ip_l[2];
-    key->ip_l[3] = flow_key->ip_l[3];
-    key->ip_h[0] = flow_key->ip_h[0];
-    key->ip_h[1] = flow_key->ip_h[1];
-    key->ip_h[2] = flow_key->ip_h[2];
-    key->ip_h[3] = flow_key->ip_h[3];
-    key->mplsLabel = flow_key->mplsLabel;
-    key->port_l = flow_key->port_l;
-    key->port_h = flow_key->port_h;
-    key->vlan_tag = flow_key->vlan_tag;
-    key->addressSpaceId = flow_key->addressSpaceId;
-    key->ip_protocol = flow_key->ip_protocol;
-    key->pkt_type = (uint8_t)flow_key->pkt_type;
-    key->version = flow_key->version;
-    key->padding = 0;
+    key.ip_l[0] = flow_key->ip_l[0];
+    key.ip_l[1] = flow_key->ip_l[1];
+    key.ip_l[2] = flow_key->ip_l[2];
+    key.ip_l[3] = flow_key->ip_l[3];
+    key.ip_h[0] = flow_key->ip_h[0];
+    key.ip_h[1] = flow_key->ip_h[1];
+    key.ip_h[2] = flow_key->ip_h[2];
+    key.ip_h[3] = flow_key->ip_h[3];
+    key.mplsLabel = flow_key->mplsLabel;
+    key.port_l = flow_key->port_l;
+    key.port_h = flow_key->port_h;
+    key.vlan_tag = flow_key->vlan_tag;
+    key.addressSpaceId = flow_key->addressSpaceId;
+    key.ip_protocol = flow_key->ip_protocol;
+    key.pkt_type = (uint8_t)flow_key->pkt_type;
+    key.version = flow_key->version;
+    key.padding = 0;
+
+    return key;
 }
 
 DCE2_Smb2FileTracker::~DCE2_Smb2FileTracker(void)
@@ -282,6 +285,7 @@ DCE2_Ret DCE2_Smb2InitData(DCE2_Smb2SsnData* ssd)
     ssd->ssn_state_flags = 0;
     ssd->ftracker_tcp = nullptr;
     ssd->max_file_depth = FileService::get_max_file_depth();
+    ssd->flow_key = get_flow_key();
     return DCE2_RET__SUCCESS;
 }
 
index 43a23a4f113a78bb660dd54595b8a70b2462ddab..0e6c3b0f87a660db5e606c35946ad1b3f937fd5e 100644 (file)
@@ -252,6 +252,29 @@ private:
     DCE2_DbMapFtracker file_trackers;
 };
 
+PADDING_GUARD_BEGIN
+struct Smb2SidHashKey
+{
+    //must be of size 3*x*sizeof(uint32_t)
+    uint32_t cip[4];
+    uint32_t sip[4];
+    uint64_t sid;
+    uint64_t padding;
+
+    bool operator== (const Smb2SidHashKey &other) const
+    {
+        return( sid == other.sid and
+                cip[0] == other.cip[0] and
+                cip[1] == other.cip[1] and
+                cip[2] == other.cip[2] and
+                cip[3] == other.cip[3] and
+                sip[0] == other.sip[0] and
+                sip[1] == other.sip[1] and
+                sip[2] == other.sip[2] and
+                sip[3] == other.sip[3]);
+    }
+};
+
 struct SmbFlowKey
 {
     uint32_t ip_l[4];   /* Low IP */
@@ -286,46 +309,35 @@ struct SmbFlowKey
                version == other.version);
     }
 };
+PADDING_GUARD_END
 
-void get_flow_key(SmbFlowKey* key);
+//The below value is taken from Hash Key class static hash hardener
+#define SMB_KEY_HASH_HARDENER 133824503
 
-struct SmbFlowKeyHash
+struct SmbKeyHash
 {
-    size_t operator()(const struct SmbFlowKey& key) const
+    size_t operator() (const SmbFlowKey& key) const
     {
-        uint32_t a, b, c;
-        a = b = c = 133824503;
-
-        const uint32_t* d = (const uint32_t*)&key;
-
-        a += d[0];   // IPv6 lo[0]
-        b += d[1];   // IPv6 lo[1]
-        c += d[2];   // IPv6 lo[2]
-
-        mix(a, b, c);
-
-        a += d[3];   // IPv6 lo[3]
-        b += d[4];   // IPv6 hi[0]
-        c += d[5];   // IPv6 hi[1]
-
-        mix(a, b, c);
-
-        a += d[6];   // IPv6 hi[2]
-        b += d[7];   // IPv6 hi[3]
-        c += d[8];   // mpls label
-
-        mix(a, b, c);
-
-        a += d[9];   // port lo & port hi
-        b += d[10];  // vlan tag, address space id
-        c += d[11];  // ip_proto, pkt_type, version, and 8 bits of zeroed pad
+        return  do_hash((const uint32_t*)&key);
+    }
 
-        finalize(a, b, c);
+    size_t operator() (const Smb2SidHashKey& key) const
+    {
+        return do_hash((const uint32_t*)&key);
+    }
 
+private:
+    size_t do_hash(const uint32_t* d) const
+    {
+        uint32_t a, b, c;
+        a = b = c = SMB_KEY_HASH_HARDENER;
+        a += d[0]; b += d[1];  c += d[2];  mix(a, b, c);
+        a += d[3]; b += d[4];  c += d[5];  mix(a, b, c);
+        a += d[6]; b += d[7];  c += d[8];  mix(a, b, c);
+        a += d[9]; b += d[10]; c += d[11]; finalize(a, b, c);
         return c;
     }
 
-private:
     inline uint32_t rot(uint32_t x, unsigned k) const
     { return (x << k) | (x >> (32 - k)); }
 
@@ -352,7 +364,7 @@ private:
 };
 
 typedef DCE2_DbMap<uint32_t, DCE2_Smb2TreeTracker*, std::hash<uint32_t> > DCE2_DbMapTtracker;
-typedef DCE2_DbMap<struct SmbFlowKey, DCE2_Smb2SsnData*, SmbFlowKeyHash> DCE2_DbMapConntracker;
+typedef DCE2_DbMap<struct SmbFlowKey, DCE2_Smb2SsnData*, SmbKeyHash> DCE2_DbMapConntracker;
 class DCE2_Smb2SessionTracker
 {
 public:
@@ -419,6 +431,7 @@ public:
 
     DCE2_DbMapConntracker conn_trackers;
     DCE2_DbMapTtracker tree_trackers;
+    Smb2SidHashKey session_key;
     uint64_t session_id = 0;
 };
 
@@ -434,6 +447,7 @@ struct DCE2_Smb2SsnData
     int16_t max_outstanding_requests; // Maximum number of request that can stay pending
     DCE2_DbMapStracker session_trackers;
     DCE2_Smb2FileTracker* ftracker_tcp; //To keep tab of current file being transferred over TCP
+    SmbFlowKey flow_key;
 };
 
 /* SMB2 command codes */
index b17dea4a5c1c18fa8c527a559e11aec49137afe5..14db10c182f4e97a20f31b1a4e58c3465051a910 100644 (file)
@@ -747,7 +747,7 @@ void DCE2_Smb2Logoff(DCE2_Smb2SsnData* ssd, const uint8_t* smb_data,
         if (str)
         {
             str->removeSessionFromAllConnection();
-            DCE2_SmbSessionCacheRemove(sid);
+            DCE2_SmbSessionCacheRemove(str->session_key);
         }
     }
     else
index 9e68f5d523811d3937ccfc9a2f280da720acfc8d..efd95c14f0e76c9702ffd0a4a4e94cd709372477 100644 (file)
@@ -38,9 +38,10 @@ Smb2SidHashKey get_key(uint64_t sid)
 {
     Smb2SidHashKey key;
     Flow* flow = DetectionEngine::get_current_packet()->flow;
-    memcpy(&key.cip, &flow->client_ip, sizeof(SfIp));
-    memcpy(&key.sip, &flow->server_ip, sizeof(SfIp));
+    memcpy(key.cip, flow->client_ip.get_ip6_ptr(), 4*sizeof(uint32_t));
+    memcpy(key.sip, flow->server_ip.get_ip6_ptr(), 4*sizeof(uint32_t));
     key.sid = sid;
+    key.padding = 0;
     return key;
 }
 
@@ -57,7 +58,10 @@ DCE2_Smb2SessionTracker* DCE2_Smb2FindElseCreateSid(DCE2_Smb2SsnData* ssd, const
         stracker = DCE2_SmbSessionCacheFindElseCreate(sid, &entry_created);
         assert(stracker);
         if (entry_created)
+        {
             stracker->set_session_id(sid);
+            stracker->session_key = get_key(sid);
+        }
 
         DCE2_Smb2InsertSidInSsd(ssd, sid, stracker);
     }
@@ -89,8 +93,6 @@ DCE2_Smb2TreeTracker* DCE2_Smb2InsertTid(DCE2_Smb2SsnData* ssd, const uint32_t t
 
 void DCE2_Smb2RemoveAllSession(DCE2_Smb2SsnData* ssd)
 {
-    SmbFlowKey key;
-    get_flow_key(&key);
     ssd->ftracker_tcp = nullptr;
 
     // iterate over smb sessions for this tcp connection and cleanup its instance from them
@@ -99,11 +101,11 @@ void DCE2_Smb2RemoveAllSession(DCE2_Smb2SsnData* ssd)
     {
         ssd->session_trackers.Remove(h.second->session_id);  // remove session tracker from this
                                                              // tcp conn
-        h.second->removeConnTracker(key); // remove tcp connection from session tracker
+        h.second->removeConnTracker(ssd->flow_key); // remove tcp connection from session tracker
         if (!h.second->getConnTrackerSize()) // if no tcp connection present in session tracker,
                                              // delete session tracker
         {
-            DCE2_SmbSessionCacheRemove(h.second->session_id);
+            DCE2_SmbSessionCacheRemove(h.second->session_key);
         }
     }
 }
index 8375f5e796cf93ac15b55e94f18fcc983445b987..290eeff5ed7c019a16c06b429caa784b69b86d1a 100644 (file)
 #include "dce_smb.h"
 #include "dce_smb2.h"
 #include "file_api/file_flows.h"
-#include "sfip/sf_ip.h"
-
-struct Smb2SidHashKey
-{
-    snort::SfIp cip; // client ip
-    snort::SfIp sip; // server ip
-    uint64_t sid;
-    bool operator==(const Smb2SidHashKey& other) const
-    {
-        return( sid == other.sid and
-               cip == other.cip and
-               sip == other.sip );
-    }
-};
-
-struct Smb2SidHash
-{
-    size_t operator()(const Smb2SidHashKey& key) const
-    {
-        const uint32_t* cip64 = key.cip.get_ip6_ptr();
-        const uint32_t* sip64 = key.cip.get_ip6_ptr();
-        const uint32_t sid_lo = key.sid & 0xFFFFFFFF;
-        const uint32_t sid_hi = key.sid >> 32;
-        uint32_t a, b, c;
-        a = b = c = 133824503;
-        a += cip64[0]; b += cip64[1]; c += cip64[2];
-        mix(a, b, c);
-        a += cip64[3]; b += sip64[0]; c += sip64[2];
-        mix(a, b, c);
-        a += sip64[3]; b += sid_lo; c += sid_hi;
-        finalize(a, b, c);
-        return c;
-    }
-
-private:
-    inline uint32_t rot(uint32_t x, unsigned k) const
-    { return (x << k) | (x >> (32 - k)); }
-
-    inline void mix(uint32_t& a, uint32_t& b, uint32_t& c) const
-    {
-        a -= c; a ^= rot(c, 4); c += b;
-        b -= a; b ^= rot(a, 6); a += c;
-        c -= b; c ^= rot(b, 8); b += a;
-        a -= c; a ^= rot(c,16); c += b;
-        b -= a; b ^= rot(a,19); a += c;
-        c -= b; c ^= rot(b, 4); b += a;
-    }
-
-    inline void finalize(uint32_t& a, uint32_t& b, uint32_t& c) const
-    {
-        c ^= b; c -= rot(b,14);
-        a ^= c; a -= rot(c,11);
-        b ^= a; b -= rot(a,25);
-        c ^= b; c -= rot(b,16);
-        a ^= c; a -= rot(c,4);
-        b ^= a; b -= rot(a,14);
-        c ^= b; c -= rot(b,24);
-    }
-};
 
 Smb2SidHashKey get_key(uint64_t sid);
 
@@ -100,7 +41,7 @@ public:
     virtual ~SmbSessionCache_map() { }
 };
 
-typedef SmbSessionCache_map<Smb2SidHashKey, DCE2_Smb2SessionTracker, Smb2SidHash> SmbSessionCache;
+typedef SmbSessionCache_map<Smb2SidHashKey, DCE2_Smb2SessionTracker, SmbKeyHash> SmbSessionCache;
 
 extern THREAD_LOCAL SmbSessionCache* smb2_session_cache;
 extern size_t session_cache_size;
@@ -122,9 +63,9 @@ inline DCE2_Smb2SessionTracker* DCE2_SmbSessionCacheFindElseCreate(uint64_t sid,
     return (smb2_session_cache->find_else_create(get_key(sid), entry_created)).get();
 }
 
-inline bool DCE2_SmbSessionCacheRemove(uint64_t sid)
+inline bool DCE2_SmbSessionCacheRemove(Smb2SidHashKey key)
 {
-    return smb2_session_cache->remove(get_key(sid));
+    return smb2_session_cache->remove(key);
 }
 
 // SMB2 functions for fetching sid, tid, request type and so on.
@@ -158,9 +99,7 @@ inline void DCE2_Smb2InsertSidInSsd(DCE2_Smb2SsnData* ssd, const uint64_t sid,
     DCE2_Smb2SessionTracker* stracker)
 {
     // add ssd in session tracker's tcp trackers database
-    SmbFlowKey key;
-    get_flow_key(&key);
-    stracker->insertConnTracker(key, ssd);
+    stracker->insertConnTracker(ssd->flow_key, ssd);
 
     ssd->session_trackers.Insert(sid, stracker);
 }