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)
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;
}
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 */
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)); }
};
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:
DCE2_DbMapConntracker conn_trackers;
DCE2_DbMapTtracker tree_trackers;
+ Smb2SidHashKey session_key;
uint64_t session_id = 0;
};
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 */
if (str)
{
str->removeSessionFromAllConnection();
- DCE2_SmbSessionCacheRemove(sid);
+ DCE2_SmbSessionCacheRemove(str->session_key);
}
}
else
{
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;
}
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);
}
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
{
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);
}
}
}
#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);
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;
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.
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);
}