]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #1984 in SNORT/snort3 from ~NEHASH4/snort3:CSCvh17903 to master
authorGeorge Koikara (gkoikara) <gkoikara@cisco.com>
Tue, 24 Mar 2020 18:18:28 +0000 (18:18 +0000)
committerGeorge Koikara (gkoikara) <gkoikara@cisco.com>
Tue, 24 Mar 2020 18:18:28 +0000 (18:18 +0000)
Squashed commit of the following:

commit fe0e3ebb85728a7ace9022accf90046561a843ce
Author: neha sharma <nehash4@cisco.com>
Date:   Tue Dec 17 05:53:19 2019 -0500

    smb: inspect midstream sessions for file inspection

src/service_inspectors/dce_rpc/dce_common.cc
src/service_inspectors/dce_rpc/dce_common.h
src/service_inspectors/dce_rpc/dce_smb.cc
src/service_inspectors/dce_rpc/dce_smb2.cc
src/service_inspectors/dce_rpc/dce_smb2.h
src/service_inspectors/dce_rpc/dce_smb_paf.cc
src/service_inspectors/dce_rpc/dce_tcp_paf.cc

index 366e763c8c761e633d15591151bb64ce94886e4d..d1469648e4032b95db45f497aa8c1e5eca3aba7a 100644 (file)
@@ -85,7 +85,7 @@ static const char* dce2_get_policy_name(DCE2_Policy policy)
 bool dce2_set_common_config(Value& v, dce2CommonProtoConf& common)
 {
     if ( v.is("limit_alerts") )
-            common.limit_alerts = v.get_bool();
+        common.limit_alerts = v.get_bool();
 
     else if ( v.is("disable_defrag") )
         common.disable_defrag = v.get_bool();
@@ -138,22 +138,14 @@ void print_dce2_co_config(dce2CoProtoConf& co)
         co.co_reassemble_threshold);
 }
 
-bool dce2_paf_abort(Flow* flow, DCE2_SsnData* sd)
+bool dce2_paf_abort(DCE2_SsnData* sd)
 {
-    // FIXIT-L Checking flags from flow is okay here because this is in paf?
-    if ( (flow->get_session_flags() & SSNFLAG_MIDSTREAM) )
-        return true;
-
-    else if ( !(flow->get_session_flags() & SSNFLAG_ESTABLISHED) )
-        return true;
-
     if ((sd != nullptr) && DCE2_SsnNoInspect(sd))
         return true;
 
     return false;
 }
 
-
 void DCE2_Detect(DCE2_SsnData* sd)
 {
     DceContextData::set_current_ropts(sd);
@@ -168,7 +160,7 @@ void DCE2_Detect(DCE2_SsnData* sd)
     DetectionEngine::detect(top_pkt);
     dce2_detected = 1;
     /* Always reset rule option data after detecting */
-    DCE2_ResetRopts(sd , top_pkt);
+    DCE2_ResetRopts(sd, top_pkt);
 }
 
 DCE2_TransType get_dce2_trans_type(const Packet* p)
index 8661441180aa9124a55c3b043b092cee03d9c7b9..94f4740bec4733ab70af38ffedd9cd74daf6e9e9 100644 (file)
@@ -399,7 +399,7 @@ bool dce2_set_common_config(snort::Value&, dce2CommonProtoConf&);
 void print_dce2_common_config(dce2CommonProtoConf&);
 bool dce2_set_co_config(snort::Value&, dce2CoProtoConf&);
 void print_dce2_co_config(dce2CoProtoConf&);
-bool dce2_paf_abort(snort::Flow*, DCE2_SsnData*);
+bool dce2_paf_abort(DCE2_SsnData*);
 void DCE2_Detect(DCE2_SsnData*);
 snort::Packet* DCE2_GetRpkt(snort::Packet*, DCE2_RpktType, const uint8_t*, uint32_t);
 uint16_t DCE2_GetRpktMaxData(DCE2_RpktType);
index 9140ef011d3bb3eda8849a48d30771bce44da953..4b165a57385aa65dbbc5e3ace262623d4ff51b6b 100644 (file)
@@ -359,9 +359,6 @@ void Dce2Smb::eval(Packet* p)
     assert(p->has_tcp_data());
     assert(p->flow);
 
-    if ( p->test_session_flags(SSNFLAG_MIDSTREAM) )
-        return;
-
     dce2_smb_sess = dce2_handle_smb_session(p, &config);
 
     if (dce2_smb_sess)
index e5c2cf885b7913523dc4e43285c33578e03220cf..bf6dad521dcec3ba3f63069ed62ec8a2c259033f 100644 (file)
@@ -36,6 +36,7 @@
 using namespace snort;
 
 #define   UNKNOWN_FILE_SIZE                  ~0
+#define   SMB2_MAX_OUTSTANDING_REQUESTS      128
 
 // FIXIT-L port fileCache related code along with
 // DCE2_Smb2Init, DCE2_Smb2Close and DCE2_Smb2UpdateStats
@@ -60,24 +61,19 @@ static int DCE2_Smb2TidCompare(const void* a, const void* b)
     return -1;
 }
 
-static inline void DCE2_Smb2InsertTid(DCE2_SmbSsnData* ssd, const uint32_t tid,
+static inline DCE2_Ret DCE2_Smb2InsertTid(DCE2_SmbSsnData* ssd, const uint32_t tid,
     const uint8_t share_type)
 {
-    bool is_ipc = (share_type != SMB2_SHARE_TYPE_DISK);
+    DCE2_Ret ret = DCE2_RET__ERROR;
 
-    if ( !is_ipc and
-        ssd->max_file_depth == -1 and DCE2_ScSmbFileDepth((dce2SmbProtoConf*)ssd->sd.config) == -1 )
+    if ( (share_type == SMB2_SHARE_TYPE_DISK)and
+            (ssd->max_file_depth ==
+            -1 and DCE2_ScSmbFileDepth((dce2SmbProtoConf*)ssd->sd.config) == -1) )
     {
-        trace_logf(dce_smb, "Not inserting TID (%u) because it's "
-            "not IPC and not inspecting normal file data.\n", tid);
-        return;
-    }
-
-    if (is_ipc)
-    {
-        trace_logf(dce_smb, "Not inserting TID (%u) "
-            "because it's IPC and only inspecting normal file data.\n", tid);
-        return;
+        trace_logf(dce_smb, "Not inserting TID (%u) for DISK share type"
+            "as mandatory configuration max_file_depth is not present."
+            "This will result in non-inspection of file data.\n", tid);
+        return ret;
     }
 
     if (ssd->tids == nullptr)
@@ -87,32 +83,42 @@ static inline void DCE2_Smb2InsertTid(DCE2_SmbSsnData* ssd, const uint32_t tid,
 
         if (ssd->tids == nullptr)
         {
-            return;
+            return ret;
         }
     }
 
-    DCE2_ListInsert(ssd->tids, (void*)(uintptr_t)tid, (void*)(uintptr_t)share_type);
+    if (ssd->outstanding_requests >= SMB2_MAX_OUTSTANDING_REQUESTS)
+    {
+        return ret;
+    }
+
+    ret = DCE2_ListInsert(ssd->tids, (void*)(uintptr_t)tid, (void*)(uintptr_t)share_type);
+    if (DCE2_RET__SUCCESS == ret)
+    {
+        ssd->outstanding_requests++;
+    }
+
+    return ret;
 }
 
-static DCE2_Ret DCE2_Smb2FindTid(DCE2_SmbSsnData* ssd, const Smb2Hdr* smb_hdr)
+static inline uint8_t DCE2_Smb2GetShareType(DCE2_SmbSsnData* ssd, const uint32_t tid)
 {
-    /* Still process async commands*/
-    if (alignedNtohl(&(smb_hdr->flags)) & SMB2_FLAGS_ASYNC_COMMAND)
-        return DCE2_RET__SUCCESS;
+    if ( DCE2_RET__SUCCESS == DCE2_ListFindKey(ssd->tids, (void*)(uintptr_t)tid) )
+        return ((uint8_t)(uintptr_t)DCE2_ListFind(ssd->tids, (void*)(uintptr_t)tid));
 
-    return DCE2_ListFindKey(ssd->tids, (void*)(uintptr_t)Smb2Tid(smb_hdr));
+    return SMB2_SHARE_TYPE_NONE;
 }
 
 static inline void DCE2_Smb2RemoveTid(DCE2_SmbSsnData* ssd, const uint32_t tid)
 {
-    DCE2_ListRemove(ssd->tids, (void*)(uintptr_t)tid);
+    if ( DCE2_RET__SUCCESS == DCE2_ListRemove(ssd->tids, (void*)(uintptr_t)tid) )
+        ssd->outstanding_requests--;
 }
 
 static inline void DCE2_Smb2StoreRequest(DCE2_SmbSsnData* ssd,
     uint64_t message_id, uint64_t offset, uint64_t file_id)
 {
     Smb2Request* request = ssd->smb2_requests;
-    ssd->max_outstanding_requests = 128; /* windows client max */
 
     while (request)
     {
@@ -121,7 +127,7 @@ static inline void DCE2_Smb2StoreRequest(DCE2_SmbSsnData* ssd,
         request = request->next;
     }
 
-    if ( ssd->outstanding_requests >= (ssd->max_outstanding_requests - 1) )
+    if (ssd->outstanding_requests >= SMB2_MAX_OUTSTANDING_REQUESTS)
     {
         dce_alert(GID_DCE2, DCE2_SMB_MAX_REQS_EXCEEDED, (dce2CommonStats*)&dce2_smb_stats,
             ssd->sd);
@@ -254,7 +260,8 @@ static void DCE2_Smb2TreeConnect(DCE2_SmbSsnData* ssd, const Smb2Hdr* smb_hdr,
 {
     /* Using structure size to decide whether it is response or request*/
     uint16_t structure_size;
-    const Smb2TreeConnectResponseHdr* smb_tree_connect_hdr = (const Smb2TreeConnectResponseHdr*)smb_data;
+    const Smb2TreeConnectResponseHdr* smb_tree_connect_hdr =
+        (const Smb2TreeConnectResponseHdr*)smb_data;
 
     if ((const uint8_t*)smb_tree_connect_hdr + SMB2_TREE_CONNECT_RESPONSE_STRUC_SIZE > end)
         return;
@@ -336,7 +343,6 @@ static void DCE2_Smb2CreateResponse(DCE2_SmbSsnData* ssd, const Smb2Hdr*,
     uint64_t fileId_persistent;
     uint64_t file_size = UNKNOWN_FILE_SIZE;
 
-
     fileId_persistent = alignedNtohq((const uint64_t*)(&(smb_create_hdr->fileId_persistent)));
     ssd->ftracker.fid_v2 = fileId_persistent;
     if (smb_create_hdr->end_of_file)
@@ -455,7 +461,8 @@ static void DCE2_Smb2SetInfo(DCE2_SmbSsnData* ssd, const Smb2Hdr*,
 
     if (structure_size == SMB2_SET_INFO_REQUEST_STRUC_SIZE)
     {
-        const uint8_t* file_data =  (const uint8_t*)smb_set_info_hdr + SMB2_SET_INFO_REQUEST_STRUC_SIZE - 1;
+        const uint8_t* file_data =  (const uint8_t*)smb_set_info_hdr +
+            SMB2_SET_INFO_REQUEST_STRUC_SIZE - 1;
         if (smb_set_info_hdr->file_info_class == SMB2_FILE_ENDOFFILE_INFO)
         {
             uint64_t file_size = alignedNtohq((const uint64_t*)file_data);
@@ -617,7 +624,6 @@ static void DCE2_Smb2WriteRequest(DCE2_SmbSsnData* ssd, const Smb2Hdr* smb_hdr,
         ssd->pdu_state = DCE2_SMB_PDU_STATE__RAW_DATA;
 }
 
-
 /********************************************************************
  *
  * Process write command
@@ -655,35 +661,49 @@ static void DCE2_Smb2Inspect(DCE2_SmbSsnData* ssd, const Smb2Hdr* smb_hdr, const
 {
     const uint8_t* smb_data = (const uint8_t*)smb_hdr + SMB2_HEADER_LENGTH;
     uint16_t command = alignedNtohs(&(smb_hdr->command));
+    uint8_t share_type = DCE2_Smb2GetShareType(ssd, Smb2Tid(smb_hdr));
     switch (command)
     {
     case SMB2_COM_CREATE:
         dce2_smb_stats.smb2_create++;
-        if (DCE2_Smb2FindTid(ssd, smb_hdr) != DCE2_RET__SUCCESS)
-            return;
-        DCE2_Smb2Create(ssd, smb_hdr, smb_data, end);
+
+        if ( SMB2_SHARE_TYPE_NONE == share_type )
+        {
+            if ( DCE2_RET__SUCCESS ==
+                DCE2_Smb2InsertTid(ssd, Smb2Tid(smb_hdr), SMB2_SHARE_TYPE_DISK) )
+                DCE2_Smb2Create(ssd, smb_hdr, smb_data, end);
+        }
+        else if ( SMB2_SHARE_TYPE_DISK == share_type )
+        {
+            DCE2_Smb2Create(ssd, smb_hdr, smb_data, end);
+        }
+        else
+        {
+            trace_logf(dce_smb, "Not handling create request for IPC with TID (%u)\n",
+                Smb2Tid(smb_hdr));
+        }
         break;
     case SMB2_COM_READ:
         dce2_smb_stats.smb2_read++;
-        if (DCE2_Smb2FindTid(ssd, smb_hdr) != DCE2_RET__SUCCESS)
+        if ( SMB2_SHARE_TYPE_DISK != share_type )
             return;
         DCE2_Smb2Read(ssd, smb_hdr, smb_data, end);
         break;
     case SMB2_COM_WRITE:
         dce2_smb_stats.smb2_write++;
-        if (DCE2_Smb2FindTid(ssd, smb_hdr) != DCE2_RET__SUCCESS)
+        if ( SMB2_SHARE_TYPE_DISK != share_type )
             return;
         DCE2_Smb2Write(ssd, smb_hdr, smb_data, end);
         break;
     case SMB2_COM_SET_INFO:
         dce2_smb_stats.smb2_set_info++;
-        if (DCE2_Smb2FindTid(ssd, smb_hdr) != DCE2_RET__SUCCESS)
+        if ( SMB2_SHARE_TYPE_DISK != share_type )
             return;
         DCE2_Smb2SetInfo(ssd, smb_hdr, smb_data, end);
         break;
     case SMB2_COM_CLOSE:
         dce2_smb_stats.smb2_close++;
-        if (DCE2_Smb2FindTid(ssd, smb_hdr) != DCE2_RET__SUCCESS)
+        if ( SMB2_SHARE_TYPE_DISK != share_type )
             return;
         DCE2_Smb2CloseCmd(ssd, smb_hdr, smb_data, end);
         break;
@@ -734,18 +754,19 @@ void DCE2_Smb2Process(DCE2_SmbSsnData* ssd)
             DCE2_Smb2Inspect(ssd, smb_hdr, data_ptr +  data_len);
             /* In case of message compounding, find the offset of the next smb command */
             next_command_offset = alignedNtohl(&(smb_hdr->next_command));
-            if (next_command_offset + (const uint8_t *)smb_hdr > (data_ptr + data_len))
+            if (next_command_offset + (const uint8_t*)smb_hdr > (data_ptr + data_len))
             {
                 dce_alert(GID_DCE2, DCE2_SMB_BAD_NEXT_COMMAND_OFFSET,
-                        (dce2CommonStats*)&dce2_smb_stats, ssd->sd);
+                    (dce2CommonStats*)&dce2_smb_stats, ssd->sd);
 
                 return;
             }
             if (next_command_offset)
             {
-                smb_hdr = (const Smb2Hdr *)((const uint8_t *)smb_hdr + next_command_offset);
+                smb_hdr = (const Smb2Hdr*)((const uint8_t*)smb_hdr + next_command_offset);
             }
-        } while (next_command_offset && smb_hdr);
+        }
+        while (next_command_offset && smb_hdr);
     }
     else if (ssd->pdu_state == DCE2_SMB_PDU_STATE__RAW_DATA)
     {
@@ -780,7 +801,7 @@ DCE2_SmbVersion DCE2_Smb2Version(const Packet* p)
 {
     /* Only check reassembled SMB2 packet*/
     if ( p->has_paf_payload() and
-        (p->dsize > sizeof(NbssHdr) + DCE2_SMB_ID_SIZE) ) // DCE2_SMB_ID is u32
+            (p->dsize > sizeof(NbssHdr) + DCE2_SMB_ID_SIZE) ) // DCE2_SMB_ID is u32
     {
         const Smb2Hdr* smb_hdr = (const Smb2Hdr*)(p->data + sizeof(NbssHdr));
         uint32_t smb_version_id = SmbId((const SmbNtHdr*)smb_hdr);
index 6009f889aa300ef9df4c1233f56785e7e8e5cea3..8bc2fdb2822b085752ecfc36a873412aa88995da 100644 (file)
@@ -164,7 +164,7 @@ struct Smb2SetInfoRequestHdr
     uint16_t buffer_offset;    /* buffer offset */
     uint16_t reserved;         /* reserved */
     uint32_t additional_info;  /* additional information */
-    uint64_t fileId_persistent;/* fileId that is persistent */
+    uint64_t fileId_persistent; /* fileId that is persistent */
     uint64_t fileId_volatile;  /* fileId that is volatile */
 };
 
@@ -216,6 +216,7 @@ struct Smb2CloseRequestHdr
     uint64_t fileId_volatile;         /* fileId that is volatile */
 };
 
+#define SMB2_SHARE_TYPE_NONE  0x00
 #define SMB2_SHARE_TYPE_DISK  0x01
 #define SMB2_SHARE_TYPE_PIPE  0x02
 #define SMB2_SHARE_TYPE_PRINT 0x03
index 84e09a4207580b0abbeea8198c86bcc8c6f2967b..730458de5b6bb491cfb77bf27614b3b2c78e3203 100644 (file)
@@ -32,7 +32,7 @@ namespace
 inline void DCE2_SMB_PAF_SHIFT(uint64_t& x64, const uint8_t& x8)
 {
     x64 <<= 8;
-    x64 |= (uint64_t) x8;
+    x64 |= (uint64_t)x8;
 }
 }
 
@@ -45,7 +45,8 @@ using namespace snort;
  *          junk states, header type must be Session Message.
  *
  *********************************************************************/
-static inline bool DCE2_PafSmbIsValidNetbiosHdr(uint32_t nb_hdr, bool junk, const SmbNtHdr *nt_hdr, uint32_t *nb_len)
+static inline bool DCE2_PafSmbIsValidNetbiosHdr(uint32_t nb_hdr, bool junk, const SmbNtHdr* nt_hdr,
+    uint32_t* nb_len)
 {
     uint8_t type = (uint8_t)(nb_hdr >> 24);
     uint8_t bit = (uint8_t)((nb_hdr & 0x00ff0000) >> 16);
@@ -72,19 +73,20 @@ static inline bool DCE2_PafSmbIsValidNetbiosHdr(uint32_t nb_hdr, bool junk, cons
             return false;
         }
     }
-    //The bit should be checked only for SMB1, because the length in NetBIOS header should not exceed 0x1FFFF.
+    //The bit should be checked only for SMB1, because the length in NetBIOS header should not
+    // exceed 0x1FFFF.
     //See [MS-SMB] 2.1 Transport. There is no such limit for SMB2 or SMB3
-    if(is_smb1)
+    if (is_smb1)
     {
         if ((bit != 0x00) && (bit != 0x01))
             return false;
     }
     nbs_hdr = htonl(nb_hdr);
 
-    if(is_smb1)
-        *nb_len = NbssLen((const NbssHdr *)&nbs_hdr);
+    if (is_smb1)
+        *nb_len = NbssLen((const NbssHdr*)&nbs_hdr);
     else
-        *nb_len = NbssLen2((const NbssHdr *)&nbs_hdr);
+        *nb_len = NbssLen2((const NbssHdr*)&nbs_hdr);
 
     return true;
 }
@@ -109,12 +111,12 @@ static StreamSplitter::Status dce2_smb_paf(DCE2_PafSmbData* ss, Flow* flow, cons
 {
     uint32_t n = 0;
     StreamSplitter::Status ps = StreamSplitter::SEARCH;
-    const SmbNtHdr *nt_hdr = nullptr;
+    const SmbNtHdrnt_hdr = nullptr;
     uint32_t nb_len = 0;
 
     DCE2_SmbSsnData* sd = get_dce2_smb_session_data(flow);
 
-    if (dce2_paf_abort(flow, (DCE2_SsnData*)sd))
+    if ( dce2_paf_abort((DCE2_SsnData*)sd) )
     {
         return StreamSplitter::ABORT;
     }
@@ -131,7 +133,7 @@ static StreamSplitter::Status dce2_smb_paf(DCE2_PafSmbData* ss, Flow* flow, cons
             DCE2_SMB_PAF_SHIFT(ss->nb_hdr, data[n]);
             //(data + n + 1) points to the SMB header protocol identifier
             //(0xFF,'SMB' or 0xFE,'SMB'), which follows the NetBIOS header
-            nt_hdr = (const SmbNtHdr *)(data + n + 1);
+            nt_hdr = (const SmbNtHdr*)(data + n + 1);
             if (DCE2_PafSmbIsValidNetbiosHdr((uint32_t)ss->nb_hdr, false, nt_hdr, &nb_len))
             {
                 *fp = (nb_len + sizeof(NbssHdr) + n) - ss->paf_state;
@@ -146,9 +148,10 @@ static StreamSplitter::Status dce2_smb_paf(DCE2_PafSmbData* ss, Flow* flow, cons
 
             //(data + n - sizeof(DCE2_SMB_ID) + 1) points to the smb_idf field
             //in SmbNtHdr (0xFF,'SMB' or 0xFE,'SMB'), which follows the NetBIOS header
-            nt_hdr = (const SmbNtHdr *)(data + n - DCE2_SMB_ID_SIZE + 1);
+            nt_hdr = (const SmbNtHdr*)(data + n - DCE2_SMB_ID_SIZE + 1);
             //ss->nb_hdr is the value to 4 bytes of NetBIOS header + 4 bytes of
-            //SMB header protocol identifier . Right shift by 32 bits to get the value of NetBIOS header
+            //SMB header protocol identifier . Right shift by 32 bits to get the value of NetBIOS
+            // header
             if (!DCE2_PafSmbIsValidNetbiosHdr((uint32_t)(ss->nb_hdr >> 32), true, nt_hdr, &nb_len))
             {
                 break;
index 1d04b77635e6797387a94b02d57a6f74cbf7023c..374816ef39025f08f761d798c31bdb6934e1f02a 100644 (file)
@@ -51,7 +51,7 @@ static StreamSplitter::Status dce2_tcp_paf(DCE2_PafTcpData* ds, Flow* flow, cons
 
     int num_requests = 0;
 
-    if (dce2_paf_abort(flow, (DCE2_SsnData*)sd))
+    if ( dce2_paf_abort((DCE2_SsnData*)sd) )
     {
         return StreamSplitter::ABORT;
     }
@@ -66,9 +66,9 @@ static StreamSplitter::Status dce2_tcp_paf(DCE2_PafTcpData* ds, Flow* flow, cons
             if ((DceRpcCoVersMaj(co_hdr) == DCERPC_PROTO_MAJOR_VERS__5)
                 && (DceRpcCoVersMin(co_hdr) == DCERPC_PROTO_MINOR_VERS__0)
                 && (((flags & PKT_FROM_CLIENT)
-                && DceRpcCoPduType(co_hdr) == DCERPC_PDU_TYPE__BIND)
-                || ((flags & PKT_FROM_SERVER)
-                && DceRpcCoPduType(co_hdr) == DCERPC_PDU_TYPE__BIND_ACK))
+                        && DceRpcCoPduType(co_hdr) == DCERPC_PDU_TYPE__BIND)
+                    || ((flags & PKT_FROM_SERVER)
+                        && DceRpcCoPduType(co_hdr) == DCERPC_PDU_TYPE__BIND_ACK))
                 && (DceRpcCoFragLen(co_hdr) >= sizeof(DceRpcCoHdr)))
             {
                 autodetected = true;