From: Bhargava Jandhyala (bjandhya) Date: Wed, 5 Aug 2020 17:29:00 +0000 (+0000) Subject: Merge pull request #2377 in SNORT/snort3 from ~DIPANDIT/snort3:smb_cleanup_issue... X-Git-Tag: 3.0.2-4~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=08316cf20bb43e13ae95e09b08bcae4f887f7dd7;p=thirdparty%2Fsnort3.git Merge pull request #2377 in SNORT/snort3 from ~DIPANDIT/snort3:smb_cleanup_issue to master Squashed commit of the following: commit a95dd780fea35355517468baedc519ae5e6c0c2f Author: dipto Date: Wed Aug 5 10:49:23 2020 -0400 dce_rpc: fix for smb crash while tcp session pruning --- diff --git a/src/service_inspectors/dce_rpc/dce_smb2.cc b/src/service_inspectors/dce_rpc/dce_smb2.cc index 1afb65ea7..57642c723 100644 --- a/src/service_inspectors/dce_rpc/dce_smb2.cc +++ b/src/service_inspectors/dce_rpc/dce_smb2.cc @@ -31,27 +31,30 @@ 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; } diff --git a/src/service_inspectors/dce_rpc/dce_smb2.h b/src/service_inspectors/dce_rpc/dce_smb2.h index 43a23a4f1..0e6c3b0f8 100644 --- a/src/service_inspectors/dce_rpc/dce_smb2.h +++ b/src/service_inspectors/dce_rpc/dce_smb2.h @@ -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 > DCE2_DbMapTtracker; -typedef DCE2_DbMap DCE2_DbMapConntracker; +typedef DCE2_DbMap 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 */ diff --git a/src/service_inspectors/dce_rpc/dce_smb2_commands.cc b/src/service_inspectors/dce_rpc/dce_smb2_commands.cc index b17dea4a5..14db10c18 100644 --- a/src/service_inspectors/dce_rpc/dce_smb2_commands.cc +++ b/src/service_inspectors/dce_rpc/dce_smb2_commands.cc @@ -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 diff --git a/src/service_inspectors/dce_rpc/dce_smb2_utils.cc b/src/service_inspectors/dce_rpc/dce_smb2_utils.cc index 9e68f5d52..efd95c14f 100644 --- a/src/service_inspectors/dce_rpc/dce_smb2_utils.cc +++ b/src/service_inspectors/dce_rpc/dce_smb2_utils.cc @@ -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); } } } diff --git a/src/service_inspectors/dce_rpc/dce_smb2_utils.h b/src/service_inspectors/dce_rpc/dce_smb2_utils.h index 8375f5e79..290eeff5e 100644 --- a/src/service_inspectors/dce_rpc/dce_smb2_utils.h +++ b/src/service_inspectors/dce_rpc/dce_smb2_utils.h @@ -25,65 +25,6 @@ #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 SmbSessionCache; +typedef SmbSessionCache_map 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); }