]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #528 in SNORT/snort3 from smb_transaction_secondary to master
authorRuss Combs (rucombs) <rucombs@cisco.com>
Mon, 20 Jun 2016 16:03:07 +0000 (12:03 -0400)
committerRuss Combs (rucombs) <rucombs@cisco.com>
Mon, 20 Jun 2016 16:03:07 +0000 (12:03 -0400)
Squashed commit of the following:

commit a20ef7cd26f3d9479fc4ec6a0984aa5f8887e270
Author: mdagon <mdagon@cisco.com>
Date:   Thu Jun 16 17:02:16 2016 -0400

    Smb transact secondary port

src/service_inspectors/dce_rpc/dce_smb.cc
src/service_inspectors/dce_rpc/dce_smb.h
src/service_inspectors/dce_rpc/dce_smb_commands.cc
src/service_inspectors/dce_rpc/dce_smb_commands.h

index 079fde881567406384c50a422174e3418fd684a1..6fc9f4a3f6f2b597ddc5a3805ad8e6a165a26360 100644 (file)
@@ -2042,7 +2042,6 @@ static void DCE2_SmbInitGlobals()
         switch (com)
         {
         case SMB_COM_OPEN:
-            // FIXIT-M port DCE2_SmbOpen. Same for other smb_com_funcs
             smb_com_funcs[com] = DCE2_SmbOpen;
 
             smb_deprecated_coms[com] = true;
@@ -2218,8 +2217,7 @@ static void DCE2_SmbInitGlobals()
             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
             break;
         case SMB_COM_TRANSACTION_SECONDARY:
-            //smb_com_funcs[com] = DCE2_SmbTransactionSecondary;
-            smb_com_funcs[com] = DCE2_SmbComFuncPlaceholder;
+            smb_com_funcs[com] = DCE2_SmbTransactionSecondary;
             smb_deprecated_coms[com] = false;
             smb_unusual_coms[com] = false;
 
@@ -2317,8 +2315,7 @@ static void DCE2_SmbInitGlobals()
             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
             break;
         case SMB_COM_TRANSACTION2_SECONDARY:
-            //smb_com_funcs[com] = DCE2_SmbTransaction2Secondary;
-            smb_com_funcs[com] = DCE2_SmbComFuncPlaceholder;
+            smb_com_funcs[com] = DCE2_SmbTransaction2Secondary;
             smb_deprecated_coms[com] = false;
             smb_unusual_coms[com] = false;
 
@@ -2437,8 +2434,7 @@ static void DCE2_SmbInitGlobals()
             DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
             break;
         case SMB_COM_NT_TRANSACT_SECONDARY:
-            //smb_com_funcs[com] = DCE2_SmbNtTransactSecondary;
-            smb_com_funcs[com] = DCE2_SmbComFuncPlaceholder;
+            smb_com_funcs[com] = DCE2_SmbNtTransactSecondary;
             smb_deprecated_coms[com] = false;
             smb_unusual_coms[com] = false;
 
index d236c2d085084ad9e7a6b12ba2fba563e86e0d54..459f461b768422e601f1d943644b03a8121c8db1 100644 (file)
@@ -2303,8 +2303,8 @@ inline bool SmbSetFileInfoSetFileBasicInfo(const uint16_t info_level)
 
 struct SmbNtTransactReq
 {
-    uint8_t  smb_wct;
-    uint8_t  smb_max_setup_count;
+    uint8_t smb_wct;
+    uint8_t smb_max_setup_count;
     uint16_t smb_res;
     uint32_t smb_total_param_count;
     uint32_t smb_total_data_count;
@@ -2314,21 +2314,20 @@ struct SmbNtTransactReq
     uint32_t smb_param_offset;
     uint32_t smb_data_count;
     uint32_t smb_data_offset;
-    uint8_t  smb_setup_count;
+    uint8_t smb_setup_count;
     uint16_t smb_function;
 };
 
 struct SmbNtTransactInterimResp
 {
-    uint8_t  smb_wct;
+    uint8_t smb_wct;
     uint16_t smb_bcc;
-
 };
 
 struct SmbNtTransactResp
 {
-    uint8_t  smb_wct;
-    uint8_t  smb_res[3];
+    uint8_t smb_wct;
+    uint8_t smb_res[3];
     uint32_t smb_total_param_count;
     uint32_t smb_total_data_count;
     uint32_t smb_param_count;
@@ -2337,85 +2336,85 @@ struct SmbNtTransactResp
     uint32_t smb_data_count;
     uint32_t smb_data_offset;
     uint32_t smb_data_disp;
-    uint8_t  smb_setup_count;
+    uint8_t smb_setup_count;
 };
 
-inline uint16_t SmbNtTransactReqSubCom(const SmbNtTransactReq *req)
+inline uint16_t SmbNtTransactReqSubCom(const SmbNtTransactReqreq)
 {
     return alignedNtohs(&req->smb_function);
 }
 
-inline uint8_t SmbNtTransactReqSetupCnt(const SmbNtTransactReq *req)
+inline uint8_t SmbNtTransactReqSetupCnt(const SmbNtTransactReqreq)
 {
     return req->smb_setup_count;
 }
 
-inline uint32_t SmbNtTransactReqTotalParamCnt(const SmbNtTransactReq *req)
+inline uint32_t SmbNtTransactReqTotalParamCnt(const SmbNtTransactReqreq)
 {
     return alignedNtohl(&req->smb_total_param_count);
 }
 
-inline uint32_t SmbNtTransactReqParamCnt(const SmbNtTransactReq *req)
+inline uint32_t SmbNtTransactReqParamCnt(const SmbNtTransactReqreq)
 {
     return alignedNtohl(&req->smb_param_count);
 }
 
-inline uint32_t SmbNtTransactReqParamOff(const SmbNtTransactReq *req)
+inline uint32_t SmbNtTransactReqParamOff(const SmbNtTransactReqreq)
 {
     return alignedNtohl(&req->smb_param_offset);
 }
 
-inline uint32_t SmbNtTransactReqTotalDataCnt(const SmbNtTransactReq *req)
+inline uint32_t SmbNtTransactReqTotalDataCnt(const SmbNtTransactReqreq)
 {
     return alignedNtohl(&req->smb_total_data_count);
 }
 
-inline uint32_t SmbNtTransactReqDataCnt(const SmbNtTransactReq *req)
+inline uint32_t SmbNtTransactReqDataCnt(const SmbNtTransactReqreq)
 {
     return alignedNtohl(&req->smb_data_count);
 }
 
-inline uint32_t SmbNtTransactReqDataOff(const SmbNtTransactReq *req)
+inline uint32_t SmbNtTransactReqDataOff(const SmbNtTransactReqreq)
 {
     return alignedNtohl(&req->smb_data_offset);
 }
 
-inline uint32_t SmbNtTransactRespTotalParamCnt(const SmbNtTransactResp *resp)
+inline uint32_t SmbNtTransactRespTotalParamCnt(const SmbNtTransactRespresp)
 {
     return alignedNtohl(&resp->smb_total_param_count);
 }
 
-inline uint32_t SmbNtTransactRespParamCnt(const SmbNtTransactResp *resp)
+inline uint32_t SmbNtTransactRespParamCnt(const SmbNtTransactRespresp)
 {
     return alignedNtohl(&resp->smb_param_count);
 }
 
-inline uint32_t SmbNtTransactRespParamOff(const SmbNtTransactResp *resp)
+inline uint32_t SmbNtTransactRespParamOff(const SmbNtTransactRespresp)
 {
     return alignedNtohl(&resp->smb_param_offset);
 }
 
-inline uint32_t SmbNtTransactRespParamDisp(const SmbNtTransactResp *resp)
+inline uint32_t SmbNtTransactRespParamDisp(const SmbNtTransactRespresp)
 {
     return alignedNtohl(&resp->smb_param_disp);
 }
 
-inline uint32_t SmbNtTransactRespTotalDataCnt(const SmbNtTransactResp *resp)
+inline uint32_t SmbNtTransactRespTotalDataCnt(const SmbNtTransactRespresp)
 {
     return alignedNtohl(&resp->smb_total_data_count);
 }
 
-inline uint32_t SmbNtTransactRespDataCnt(const SmbNtTransactResp *resp)
+inline uint32_t SmbNtTransactRespDataCnt(const SmbNtTransactRespresp)
 {
     return alignedNtohl(&resp->smb_data_count);
 }
 
-inline uint32_t SmbNtTransactRespDataOff(const SmbNtTransactResp *resp)
+inline uint32_t SmbNtTransactRespDataOff(const SmbNtTransactRespresp)
 {
     return alignedNtohl(&resp->smb_data_offset);
 }
 
-inline uint32_t SmbNtTransactRespDataDisp(const SmbNtTransactResp *resp)
+inline uint32_t SmbNtTransactRespDataDisp(const SmbNtTransactRespresp)
 {
     return alignedNtohl(&resp->smb_data_disp);
 }
@@ -2434,33 +2433,33 @@ struct SmbNtTransactCreateReqParams
     uint32_t ea_length;
     uint32_t name_length;
     uint32_t impersonation_level;
-    uint8_t  security_flags;
+    uint8_t security_flags;
 };
 
-inline uint64_t SmbNtTransactCreateReqAllocSize(const SmbNtTransactCreateReqParams *req)
+inline uint64_t SmbNtTransactCreateReqAllocSize(const SmbNtTransactCreateReqParamsreq)
 {
     return alignedNtohq(&req->allocation_size);
 }
 
-inline uint32_t SmbNtTransactCreateReqFileNameLength(const SmbNtTransactCreateReqParams *req)
+inline uint32_t SmbNtTransactCreateReqFileNameLength(const SmbNtTransactCreateReqParamsreq)
 {
     return alignedNtohl(&req->name_length);
 }
 
-inline uint32_t SmbNtTransactCreateReqFileAttrs(const SmbNtTransactCreateReqParams *req)
+inline uint32_t SmbNtTransactCreateReqFileAttrs(const SmbNtTransactCreateReqParamsreq)
 {
     return alignedNtohl(&req->ext_file_attributes);
 }
 
-inline bool SmbNtTransactCreateReqSequentialOnly(const SmbNtTransactCreateReqParams *req)
+inline bool SmbNtTransactCreateReqSequentialOnly(const SmbNtTransactCreateReqParamsreq)
 {
     return (alignedNtohl(&req->create_options) & SMB_CREATE_OPTIONS__FILE_SEQUENTIAL_ONLY);
 }
 
 struct SmbNtTransactCreateReq
 {
-    uint8_t  smb_wct;
-    uint8_t  smb_max_setup_count;
+    uint8_t smb_wct;
+    uint8_t smb_max_setup_count;
     uint16_t smb_res;
     uint32_t smb_total_param_count;
     uint32_t smb_total_data_count;
@@ -2470,15 +2469,15 @@ struct SmbNtTransactCreateReq
     uint32_t smb_param_offset;
     uint32_t smb_data_count;
     uint32_t smb_data_offset;
-    uint8_t  smb_setup_count;   /* Must be 0x00 */
+    uint8_t smb_setup_count;    /* Must be 0x00 */
     uint16_t smb_function;      /* NT_TRANSACT_CREATE */
     uint16_t smb_bcc;
 };
 
 struct SmbNtTransactCreateRespParams
 {
-    uint8_t  op_lock_level;
-    uint8_t  reserved;
+    uint8_t op_lock_level;
+    uint8_t reserved;
     uint16_t smb_fid;
     uint32_t create_action;
     uint32_t ea_error_offset;
@@ -2491,38 +2490,38 @@ struct SmbNtTransactCreateRespParams
     uint64_t end_of_file;
     uint16_t resource_type;
     uint16_t nm_pipe_status;
-    uint8_t  directory;
+    uint8_t directory;
 };
 
-inline uint16_t SmbNtTransactCreateRespFid(const SmbNtTransactCreateRespParams *resp)
+inline uint16_t SmbNtTransactCreateRespFid(const SmbNtTransactCreateRespParamsresp)
 {
     return alignedNtohs(&resp->smb_fid);
 }
 
-inline uint32_t SmbNtTransactCreateRespCreateAction(const SmbNtTransactCreateRespParams *resp)
+inline uint32_t SmbNtTransactCreateRespCreateAction(const SmbNtTransactCreateRespParamsresp)
 {
     return alignedNtohl(&resp->create_action);
 }
 
-inline uint64_t SmbNtTransactCreateRespEndOfFile(const SmbNtTransactCreateRespParams *resp)
+inline uint64_t SmbNtTransactCreateRespEndOfFile(const SmbNtTransactCreateRespParamsresp)
 {
     return alignedNtohq(&resp->end_of_file);
 }
 
-inline uint16_t SmbNtTransactCreateRespResourceType(const SmbNtTransactCreateRespParams *resp)
+inline uint16_t SmbNtTransactCreateRespResourceType(const SmbNtTransactCreateRespParamsresp)
 {
     return alignedNtohs(&resp->resource_type);
 }
 
-inline bool SmbNtTransactCreateRespDirectory(const SmbNtTransactCreateRespParams *resp)
+inline bool SmbNtTransactCreateRespDirectory(const SmbNtTransactCreateRespParamsresp)
 {
     return (resp->directory ? true : false);
 }
 
 struct SmbNtTransactCreateResp
 {
-    uint8_t  smb_wct;
-    uint8_t  smb_res[3];
+    uint8_t smb_wct;
+    uint8_t smb_res[3];
     uint32_t smb_total_param_count;
     uint32_t smb_total_data_count;
     uint32_t smb_param_count;
@@ -2531,10 +2530,186 @@ struct SmbNtTransactCreateResp
     uint32_t smb_data_count;
     uint32_t smb_data_offset;
     uint32_t smb_data_disp;
-    uint8_t  smb_setup_count;   /* 0x00 */
+    uint8_t smb_setup_count;    /* 0x00 */
     uint16_t smb_bcc;
 };
 
+/********************************************************************
+ * SMB_COM_TRANSACTION_SECONDARY
+ *  Continuation command for SMB_COM_TRANSACTION requests if all
+ *  data wasn't sent.
+ ********************************************************************/
+struct SmbTransactionSecondaryReq   /* smb_wct = 8 */
+{
+    uint8_t smb_wct;       /* count of 16-bit words that follow */
+    uint16_t smb_tpscnt;   /* total number of parameter bytes being sent */
+    uint16_t smb_tdscnt;   /* total number of data bytes being sent */
+    uint16_t smb_pscnt;    /* number of parameter bytes being sent this buffer */
+    uint16_t smb_psoff;    /* offset (from start of SMB hdr) to parameter bytes */
+    uint16_t smb_psdisp;   /* byte displacement for these parameter bytes */
+    uint16_t smb_dscnt;    /* number of data bytes being sent this buffer */
+    uint16_t smb_dsoff;    /* offset (from start of SMB hdr) to data bytes */
+    uint16_t smb_dsdisp;   /* byte displacement for these data bytes */
+    uint16_t smb_bcc;      /* total bytes (including pad bytes) following */
+};
+
+inline uint16_t SmbTransactionSecondaryReqTotalDataCnt(const SmbTransactionSecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_tdscnt);
+}
+
+inline uint16_t SmbTransactionSecondaryReqDataCnt(const SmbTransactionSecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_dscnt);
+}
+
+inline uint16_t SmbTransactionSecondaryReqDataOff(const SmbTransactionSecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_dsoff);
+}
+
+inline uint16_t SmbTransactionSecondaryReqDataDisp(const SmbTransactionSecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_dsdisp);
+}
+
+inline uint16_t SmbTransactionSecondaryReqTotalParamCnt(const SmbTransactionSecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_tpscnt);
+}
+
+inline uint16_t SmbTransactionSecondaryReqParamCnt(const SmbTransactionSecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_pscnt);
+}
+
+inline uint16_t SmbTransactionSecondaryReqParamOff(const SmbTransactionSecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_psoff);
+}
+
+inline uint16_t SmbTransactionSecondaryReqParamDisp(const SmbTransactionSecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_psdisp);
+}
+
+/********************************************************************
+ * SMB_COM_TRANSACTION2_SECONDARY
+ *  Continuation command for SMB_COM_TRANSACTION2 requests if all
+ *  data wasn't sent.
+ ********************************************************************/
+struct SmbTransaction2SecondaryReq
+{
+    uint8_t smb_wct;
+    uint16_t smb_total_param_count;
+    uint16_t smb_total_data_count;
+    uint16_t smb_param_count;
+    uint16_t smb_param_offset;
+    uint16_t smb_param_disp;
+    uint16_t smb_data_count;
+    uint16_t smb_data_offset;
+    uint16_t smb_data_disp;
+    uint16_t smb_fid;
+    uint16_t smb_bcc;
+};
+
+inline uint16_t SmbTransaction2SecondaryReqTotalParamCnt(const SmbTransaction2SecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_total_param_count);
+}
+
+inline uint16_t SmbTransaction2SecondaryReqParamCnt(const SmbTransaction2SecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_param_count);
+}
+
+inline uint16_t SmbTransaction2SecondaryReqParamOff(const SmbTransaction2SecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_param_offset);
+}
+
+inline uint16_t SmbTransaction2SecondaryReqParamDisp(const SmbTransaction2SecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_param_disp);
+}
+
+inline uint16_t SmbTransaction2SecondaryReqTotalDataCnt(const SmbTransaction2SecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_total_data_count);
+}
+
+inline uint16_t SmbTransaction2SecondaryReqDataCnt(const SmbTransaction2SecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_data_count);
+}
+
+inline uint16_t SmbTransaction2SecondaryReqDataOff(const SmbTransaction2SecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_data_offset);
+}
+
+inline uint16_t SmbTransaction2SecondaryReqDataDisp(const SmbTransaction2SecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_data_disp);
+}
+
+/********************************************************************
+ * SMB_COM_NT_TRANSACT_SECONDARY
+ ********************************************************************/
+struct SmbNtTransactSecondaryReq
+{
+    uint8_t smb_wct;
+    uint8_t smb_res[3];
+    uint32_t smb_total_param_count;
+    uint32_t smb_total_data_count;
+    uint32_t smb_param_count;
+    uint32_t smb_param_offset;
+    uint32_t smb_param_disp;
+    uint32_t smb_data_count;
+    uint32_t smb_data_offset;
+    uint32_t smb_data_disp;
+    uint8_t smb_res2;
+};
+
+inline uint32_t SmbNtTransactSecondaryReqTotalParamCnt(const SmbNtTransactSecondaryReq* req)
+{
+    return alignedNtohl(&req->smb_total_param_count);
+}
+
+inline uint32_t SmbNtTransactSecondaryReqParamCnt(const SmbNtTransactSecondaryReq* req)
+{
+    return alignedNtohl(&req->smb_param_count);
+}
+
+inline uint32_t SmbNtTransactSecondaryReqParamOff(const SmbNtTransactSecondaryReq* req)
+{
+    return alignedNtohl(&req->smb_param_offset);
+}
+
+inline uint32_t SmbNtTransactSecondaryReqParamDisp(const SmbNtTransactSecondaryReq* req)
+{
+    return alignedNtohl(&req->smb_param_disp);
+}
+
+inline uint32_t SmbNtTransactSecondaryReqTotalDataCnt(const SmbNtTransactSecondaryReq* req)
+{
+    return alignedNtohl(&req->smb_total_data_count);
+}
+
+inline uint32_t SmbNtTransactSecondaryReqDataCnt(const SmbNtTransactSecondaryReq* req)
+{
+    return alignedNtohl(&req->smb_data_count);
+}
+
+inline uint32_t SmbNtTransactSecondaryReqDataOff(const SmbNtTransactSecondaryReq* req)
+{
+    return alignedNtohl(&req->smb_data_offset);
+}
+
+inline uint32_t SmbNtTransactSecondaryReqDataDisp(const SmbNtTransactSecondaryReq* req)
+{
+    return alignedNtohl(&req->smb_data_disp);
+}
 
 #pragma pack()
 
index a67c3696d4ae3d01893c8710ed93ed7a12753e87..a517868a830230199166513aa62b5c79e2cde6f4 100644 (file)
 #include "utils/util.h"
 #include "detection/detect.h"
 
+#define DCE2_SMB_TRANS__NONE    0x00
+#define DCE2_SMB_TRANS__DATA    0x01
+#define DCE2_SMB_TRANS__PARAMS  0x02
+#define DCE2_SMB_TRANS__BOTH    (DCE2_SMB_TRANS__DATA|DCE2_SMB_TRANS__PARAMS)
+
 enum SmbNtTransactSubcommand
 {
     NT_TRANSACT_UNKNOWN_0000            = 0x0000,
@@ -202,6 +207,12 @@ static DCE2_Ret DCE2_SmbWriteAndXRawRequest(DCE2_SmbSsnData*, const SmbNtHdr*,
     const DCE2_SmbComInfo*, const uint8_t*, uint32_t);
 static DCE2_Ret DCE2_SmbNtTransactCreateReq(DCE2_SmbSsnData*,
     const uint8_t*, uint32_t, bool);
+static DCE2_Ret DCE2_SmbUpdateTransSecondary(DCE2_SmbSsnData*, const SmbNtHdr*,
+    const DCE2_SmbComInfo*, const uint8_t*, uint32_t);
+static DCE2_Ret DCE2_SmbBufferTransactionData(DCE2_SmbTransactionTracker*,
+    const uint8_t*, uint16_t, uint16_t);
+static DCE2_Ret DCE2_SmbBufferTransactionParameters(DCE2_SmbTransactionTracker*,
+    const uint8_t*, uint16_t, uint16_t);
 
 /*********************************************************************
  * Private functions
@@ -423,6 +434,239 @@ static DCE2_Ret DCE2_SmbNtTransactCreateReq(DCE2_SmbSsnData* ssd,
     return DCE2_RET__SUCCESS;
 }
 
+/********************************************************************
+ * Function: DCE2_SmbUpdateTransSecondary()
+ *
+ * Purpose:
+ *  Handles common checks and updates of transaction secondary
+ *  requests - SMB_COM_TRANSACTION_SECONDARY,
+ *  SMB_COM_TRANSACTION2_SECONDARY and
+ *  SMB_COM_NT_TRANSACT_SECONDARY
+ *
+ * Arguments:
+ *  DCE2_SmbSsnData *       - pointer to SMB session data
+ *  const SmbNtHdr *        - pointer to SMB header
+ *  const DCE2_SmbComInfo * - pointer to com info structure
+ *  const uint8_t *         - pointer to data
+ *  uint32_t                - data length
+ *
+ * Returns:
+ *  DCE2_Ret
+ *      DCE2_RET__IGNORE if we don't process the subcommand
+ *      DCE2_RET__FULL if the transaction is complete
+ *      DCE2_RET__ERROR if an error occurred.
+ *      DCE2_RET__SUCCESS if ok (but not complete).
+ *
+ ********************************************************************/
+static DCE2_Ret DCE2_SmbUpdateTransSecondary(DCE2_SmbSsnData* ssd,
+    const SmbNtHdr* smb_hdr, const DCE2_SmbComInfo* com_info,
+    const uint8_t* nb_ptr, uint32_t nb_len)
+{
+    uint16_t com_size = DCE2_ComInfoCommandSize(com_info);
+    uint16_t byte_count = DCE2_ComInfoByteCount(com_info);
+    uint32_t tdcnt, doff, dcnt, ddisp;
+    uint32_t tpcnt, poff, pcnt, pdisp;
+    DCE2_SmbTransactionTracker* ttracker = &ssd->cur_rtracker->ttracker;
+    uint16_t sub_com = ttracker->subcom;
+    int data_params = DCE2_SMB_TRANS__NONE;
+    uint8_t smb_com = DCE2_ComInfoSmbCom(com_info);
+
+    switch (smb_com)
+    {
+    case SMB_COM_TRANSACTION_SECONDARY:
+        tdcnt = SmbTransactionSecondaryReqTotalDataCnt((SmbTransactionSecondaryReq*)nb_ptr);
+        doff = SmbTransactionSecondaryReqDataOff((SmbTransactionSecondaryReq*)nb_ptr);
+        dcnt = SmbTransactionSecondaryReqDataCnt((SmbTransactionSecondaryReq*)nb_ptr);
+        ddisp = SmbTransactionSecondaryReqDataDisp((SmbTransactionSecondaryReq*)nb_ptr);
+        tpcnt = SmbTransactionSecondaryReqTotalParamCnt((SmbTransactionSecondaryReq*)nb_ptr);
+        poff = SmbTransactionSecondaryReqParamOff((SmbTransactionSecondaryReq*)nb_ptr);
+        pcnt = SmbTransactionSecondaryReqParamCnt((SmbTransactionSecondaryReq*)nb_ptr);
+        pdisp = SmbTransactionSecondaryReqParamDisp((SmbTransactionSecondaryReq*)nb_ptr);
+
+        switch (sub_com)
+        {
+        case TRANS_TRANSACT_NMPIPE:
+        case TRANS_WRITE_NMPIPE:
+            data_params = DCE2_SMB_TRANS__DATA;
+            break;
+        case TRANS_SET_NMPIPE_STATE:
+            data_params = DCE2_SMB_TRANS__PARAMS;
+            break;
+        default:
+            return DCE2_RET__IGNORE;
+        }
+        break;
+
+    case SMB_COM_TRANSACTION2_SECONDARY:
+        tdcnt = SmbTransaction2SecondaryReqTotalDataCnt((SmbTransaction2SecondaryReq*)nb_ptr);
+        doff = SmbTransaction2SecondaryReqDataOff((SmbTransaction2SecondaryReq*)nb_ptr);
+        dcnt = SmbTransaction2SecondaryReqDataCnt((SmbTransaction2SecondaryReq*)nb_ptr);
+        ddisp = SmbTransaction2SecondaryReqDataDisp((SmbTransaction2SecondaryReq*)nb_ptr);
+        tpcnt = SmbTransaction2SecondaryReqTotalParamCnt((SmbTransaction2SecondaryReq*)nb_ptr);
+        poff = SmbTransaction2SecondaryReqParamOff((SmbTransaction2SecondaryReq*)nb_ptr);
+        pcnt = SmbTransaction2SecondaryReqParamCnt((SmbTransaction2SecondaryReq*)nb_ptr);
+        pdisp = SmbTransaction2SecondaryReqParamDisp((SmbTransaction2SecondaryReq*)nb_ptr);
+
+        switch (sub_com)
+        {
+        case TRANS2_OPEN2:
+        case TRANS2_QUERY_FILE_INFORMATION:
+            data_params = DCE2_SMB_TRANS__PARAMS;
+            break;
+        case TRANS2_SET_FILE_INFORMATION:
+            data_params = DCE2_SMB_TRANS__BOTH;
+            break;
+        default:
+            return DCE2_RET__IGNORE;
+        }
+        break;
+
+    case SMB_COM_NT_TRANSACT_SECONDARY:
+        tdcnt = SmbNtTransactSecondaryReqTotalDataCnt((SmbNtTransactSecondaryReq*)nb_ptr);
+        doff = SmbNtTransactSecondaryReqDataOff((SmbNtTransactSecondaryReq*)nb_ptr);
+        dcnt = SmbNtTransactSecondaryReqDataCnt((SmbNtTransactSecondaryReq*)nb_ptr);
+        ddisp = SmbNtTransactSecondaryReqDataDisp((SmbNtTransactSecondaryReq*)nb_ptr);
+        tpcnt = SmbNtTransactSecondaryReqTotalParamCnt((SmbNtTransactSecondaryReq*)nb_ptr);
+        poff = SmbNtTransactSecondaryReqParamOff((SmbNtTransactSecondaryReq*)nb_ptr);
+        pcnt = SmbNtTransactSecondaryReqParamCnt((SmbNtTransactSecondaryReq*)nb_ptr);
+        pdisp = SmbNtTransactSecondaryReqParamDisp((SmbNtTransactSecondaryReq*)nb_ptr);
+
+        switch (sub_com)
+        {
+        case NT_TRANSACT_CREATE:
+            data_params = DCE2_SMB_TRANS__PARAMS;
+            break;
+        default:
+            return DCE2_RET__IGNORE;
+        }
+        break;
+
+    default:
+        return DCE2_RET__ERROR;
+    }
+
+    if (DCE2_SsnIsSambaPolicy(&ssd->sd))
+    {
+        // If the total count decreases, Samba will reset this to the new
+        // total count.
+        if (tdcnt < ttracker->tdcnt)
+            ttracker->tdcnt = tdcnt;
+        if (tpcnt < ttracker->tpcnt)
+            ttracker->tpcnt = tpcnt;
+    }
+    else
+    {
+        // Windows always uses the total data count from the first transaction.
+        tdcnt = (uint16_t)ttracker->tdcnt;
+        tpcnt = (uint16_t)ttracker->tpcnt;
+    }
+
+    DCE2_MOVE(nb_ptr, nb_len, com_size);
+
+    if (DCE2_SmbValidateTransactionFields((uint8_t*)smb_hdr, nb_ptr, nb_len,
+        byte_count, tdcnt, tpcnt, dcnt, doff, ddisp, pcnt, poff, pdisp) != DCE2_RET__SUCCESS)
+        return DCE2_RET__ERROR;
+
+    if (DCE2_SmbValidateTransactionSent(ttracker->dsent, dcnt, ttracker->tdcnt,
+        ttracker->psent, pcnt, ttracker->tpcnt) != DCE2_RET__SUCCESS)
+        return DCE2_RET__IGNORE;
+
+    ttracker->dsent += dcnt;
+    ttracker->psent += pcnt;
+
+    DebugFormat(DEBUG_DCE_SMB, "Data displacement: %u, "
+        "Data count: %u, Total data count: %u\n"
+        "Parameter displacement: %u, "
+        "Parameter count: %u, Total parameter count: %u\n",
+        ddisp, dcnt, tdcnt, pdisp, pcnt, tpcnt);
+
+    if (data_params & DCE2_SMB_TRANS__DATA)
+    {
+        DCE2_MOVE(nb_ptr, nb_len, ((uint8_t*)smb_hdr + doff) - nb_ptr);
+
+        if ((dcnt != 0)
+            && (DCE2_SmbBufferTransactionData(ttracker, nb_ptr, dcnt, ddisp)
+            != DCE2_RET__SUCCESS))
+        {
+            return DCE2_RET__ERROR;
+        }
+    }
+
+    if (data_params & DCE2_SMB_TRANS__PARAMS)
+    {
+        DCE2_MOVE(nb_ptr, nb_len, ((uint8_t*)smb_hdr + poff) - nb_ptr);
+
+        if ((pcnt != 0)
+            && (DCE2_SmbBufferTransactionParameters(ttracker, nb_ptr, pcnt, pdisp)
+            != DCE2_RET__SUCCESS))
+        {
+            return DCE2_RET__ERROR;
+        }
+    }
+
+    if ((ttracker->dsent == ttracker->tdcnt)
+        && (ttracker->psent == ttracker->tpcnt))
+    {
+        return DCE2_RET__FULL;
+    }
+
+    return DCE2_RET__SUCCESS;
+}
+
+static DCE2_Ret DCE2_SmbBufferTransactionData(DCE2_SmbTransactionTracker* ttracker,
+    const uint8_t* data_ptr, uint16_t dcnt, uint16_t ddisp)
+{
+    Profile profile(dce2_smb_pstat_smb_req);
+
+    DebugMessage(DEBUG_DCE_SMB, "Buffering transaction data.\n");
+
+    if (ttracker->dbuf == nullptr)
+    {
+        /* Buf size should be the total data count we need */
+        ttracker->dbuf = DCE2_BufferNew(ttracker->tdcnt, 0);
+    }
+
+    if (DCE2_BufferAddData(ttracker->dbuf, data_ptr, dcnt, ddisp,
+        DCE2_BUFFER_MIN_ADD_FLAG__IGNORE) != DCE2_RET__SUCCESS)
+    {
+        DebugMessage(DEBUG_DCE_SMB,
+            "Failed to buffer transaction data.\n");
+        return DCE2_RET__ERROR;
+    }
+
+    DebugMessage(DEBUG_DCE_SMB,
+        "Successfully buffered transaction data.\n");
+
+    return DCE2_RET__SUCCESS;
+}
+
+static DCE2_Ret DCE2_SmbBufferTransactionParameters(DCE2_SmbTransactionTracker* ttracker,
+    const uint8_t* param_ptr, uint16_t pcnt, uint16_t pdisp)
+{
+    Profile profile(dce2_smb_pstat_smb_req);
+
+    DebugMessage(DEBUG_DCE_SMB, "Buffering transaction parameters.\n");
+
+    if (ttracker->pbuf == nullptr)
+    {
+        /* Buf size should be the total data count we need */
+        ttracker->pbuf = DCE2_BufferNew(ttracker->tpcnt, 0);
+    }
+
+    if (DCE2_BufferAddData(ttracker->pbuf, param_ptr, pcnt, pdisp,
+        DCE2_BUFFER_MIN_ADD_FLAG__IGNORE) != DCE2_RET__SUCCESS)
+    {
+        DebugMessage(DEBUG_DCE_SMB,
+            "Failed to buffer transaction parameter data.\n");
+        return DCE2_RET__ERROR;
+    }
+
+    DebugMessage(DEBUG_DCE_SMB,
+        "Successfully buffered transaction parameter data.\n");
+
+    return DCE2_RET__SUCCESS;
+}
+
 /********************************************************************
  * Functions:
  *   DCE2_SmbOpen()
@@ -2332,12 +2576,34 @@ static DCE2_Ret DCE2_SmbUpdateTransRequest(DCE2_SmbSsnData* ssd,
 
     if (data_params & DCE2_SMB_TRANS__DATA)
     {
-        // FIXIT-M port
+        if (tdcnt == 0)
+            dce_alert(GID_DCE2, DCE2_SMB_DCNT_ZERO, (dce2CommonStats*)&dce2_smb_stats);
+
+        DCE2_MOVE(nb_ptr, nb_len, ((uint8_t*)smb_hdr + doff) - nb_ptr);
+
+        // If all of the data and parameters weren't sent, buffer what was sent
+        if (((dcnt != tdcnt) || (pcnt != tpcnt)) && (dcnt != 0)
+            && (DCE2_SmbBufferTransactionData(ttracker,
+            nb_ptr, dcnt, 0) != DCE2_RET__SUCCESS))
+        {
+            return DCE2_RET__ERROR;
+        }
     }
 
     if (data_params & DCE2_SMB_TRANS__PARAMS)
     {
-        // FIXIT-M port
+        if (tpcnt == 0)
+            dce_alert(GID_DCE2, DCE2_SMB_DCNT_ZERO, (dce2CommonStats*)&dce2_smb_stats);
+
+        DCE2_MOVE(nb_ptr, nb_len, ((uint8_t*)smb_hdr + poff) - nb_ptr);
+
+        // If all of the data and parameters weren't sent, buffer what was sent
+        if (((pcnt != tpcnt) || (dcnt != tdcnt)) && (pcnt != 0)
+            && (DCE2_SmbBufferTransactionParameters(ttracker,
+            nb_ptr, pcnt, 0) != DCE2_RET__SUCCESS))
+        {
+            return DCE2_RET__ERROR;
+        }
     }
 
     if ((dcnt == tdcnt) && (pcnt == tpcnt))
@@ -2517,12 +2783,26 @@ static DCE2_Ret DCE2_SmbUpdateTransResponse(DCE2_SmbSsnData* ssd,
 
     if (data_params & DCE2_SMB_TRANS__DATA)
     {
-        // FIXIT-M port
+        DCE2_MOVE(nb_ptr, nb_len, ((uint8_t*)smb_hdr + doff) - nb_ptr);
+
+        if ((dcnt != 0)
+            && (DCE2_SmbBufferTransactionData(ttracker, nb_ptr, dcnt, ddisp)
+            != DCE2_RET__SUCCESS))
+        {
+            return DCE2_RET__ERROR;
+        }
     }
 
     if (data_params & DCE2_SMB_TRANS__PARAMS)
     {
-        // FIXIT-M port
+        DCE2_MOVE(nb_ptr, nb_len, ((uint8_t*)smb_hdr + poff) - nb_ptr);
+
+        if ((pcnt != 0)
+            && (DCE2_SmbBufferTransactionParameters(ttracker, nb_ptr, pcnt, pdisp)
+            != DCE2_RET__SUCCESS))
+        {
+            return DCE2_RET__ERROR;
+        }
     }
 
     if ((ttracker->dsent == ttracker->tdcnt)
@@ -3266,3 +3546,128 @@ DCE2_Ret DCE2_SmbNtTransact(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
     return DCE2_RET__SUCCESS;
 }
 
+// SMB_COM_TRANSACTION_SECONDARY
+DCE2_Ret DCE2_SmbTransactionSecondary(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
+    const DCE2_SmbComInfo* com_info, const uint8_t* nb_ptr, uint32_t nb_len)
+{
+    DCE2_SmbTransactionTracker* ttracker = &ssd->cur_rtracker->ttracker;
+    DCE2_Ret status;
+
+    if (!DCE2_ComInfoCanProcessCommand(com_info))
+        return DCE2_RET__ERROR;
+
+    status = DCE2_SmbUpdateTransSecondary(ssd, smb_hdr, com_info, nb_ptr, nb_len);
+    if (status != DCE2_RET__FULL)
+        return status;
+
+    switch (ttracker->subcom)
+    {
+    case TRANS_TRANSACT_NMPIPE:
+    case TRANS_WRITE_NMPIPE:
+    {
+// FIXIT-M uncomment after porting packet reassembly code
+/*
+                const uint8_t *data_ptr = DCE2_BufferData(ttracker->dbuf);
+                uint32_t data_len = DCE2_BufferLength(ttracker->dbuf);
+                rpkt = DCE2_SmbGetRpkt(ssd, &data_ptr, &data_len, DCE2_RPKT_TYPE__SMB_TRANS);
+
+                if (rpkt == nullptr)
+                    return DCE2_RET__ERROR;
+
+                DebugMessage(DEBUG_DCE_SMB, "Reassembled Transaction request\n"));
+                DCE2_DEBUG_CODE(DCE2_DEBUG__MAIN, DCE2_PrintPktData(rpkt->payload, rpkt->payload_size););
+
+                status = DCE2_SmbTransactionReq(ssd, ttracker, data_ptr, data_len,
+                        DCE2_BufferData(ttracker->pbuf), DCE2_BufferLength(ttracker->pbuf));
+
+                DCE2_SmbReturnRpkt();
+*/
+    }
+    break;
+
+    default:
+        status = DCE2_SmbTransactionReq(ssd, ttracker,
+            DCE2_BufferData(ttracker->dbuf), DCE2_BufferLength(ttracker->dbuf),
+            DCE2_BufferData(ttracker->pbuf), DCE2_BufferLength(ttracker->pbuf));
+        break;
+    }
+
+    return status;
+}
+
+// SMB_COM_TRANSACTION2_SECONDARY
+DCE2_Ret DCE2_SmbTransaction2Secondary(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
+    const DCE2_SmbComInfo* com_info, const uint8_t* nb_ptr, uint32_t nb_len)
+{
+    DCE2_Ret status;
+    DCE2_SmbTransactionTracker* ttracker = &ssd->cur_rtracker->ttracker;
+
+    if (!DCE2_ComInfoCanProcessCommand(com_info))
+        return DCE2_RET__ERROR;
+
+    status = DCE2_SmbUpdateTransSecondary(ssd, smb_hdr, com_info, nb_ptr, nb_len);
+    if (status != DCE2_RET__FULL)
+        return status;
+
+    switch (ttracker->subcom)
+    {
+    case TRANS2_OPEN2:
+        status = DCE2_SmbTrans2Open2Req(ssd, DCE2_BufferData(ttracker->pbuf),
+            DCE2_BufferLength(ttracker->pbuf), SmbUnicode(smb_hdr));
+        if (status != DCE2_RET__SUCCESS)
+            return status;
+        break;
+
+    case TRANS2_QUERY_FILE_INFORMATION:
+        status = DCE2_SmbTrans2QueryFileInfoReq(ssd, DCE2_BufferData(ttracker->pbuf),
+            DCE2_BufferLength(ttracker->pbuf));
+        if (status != DCE2_RET__SUCCESS)
+            return status;
+        break;
+
+    case TRANS2_SET_FILE_INFORMATION:
+        status = DCE2_SmbTrans2SetFileInfoReq(ssd, DCE2_BufferData(ttracker->pbuf),
+            DCE2_BufferLength(ttracker->pbuf),
+            DCE2_BufferData(ttracker->dbuf),
+            DCE2_BufferLength(ttracker->dbuf));
+        if (status != DCE2_RET__SUCCESS)
+            return status;
+        break;
+
+    default:
+        break;
+    }
+
+    return DCE2_RET__SUCCESS;
+}
+
+// SMB_COM_NT_TRANSACT_SECONDARY
+DCE2_Ret DCE2_SmbNtTransactSecondary(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
+    const DCE2_SmbComInfo* com_info, const uint8_t* nb_ptr, uint32_t nb_len)
+{
+    DCE2_Ret status;
+    DCE2_SmbTransactionTracker* ttracker = &ssd->cur_rtracker->ttracker;
+
+    if (!DCE2_ComInfoCanProcessCommand(com_info))
+        return DCE2_RET__ERROR;
+
+    status = DCE2_SmbUpdateTransSecondary(ssd, smb_hdr, com_info, nb_ptr, nb_len);
+    if (status != DCE2_RET__FULL)
+        return status;
+
+    switch (ttracker->subcom)
+    {
+    case NT_TRANSACT_CREATE:
+        status = DCE2_SmbNtTransactCreateReq(ssd, DCE2_BufferData(ttracker->pbuf),
+            DCE2_BufferLength(ttracker->pbuf), SmbUnicode(smb_hdr));
+        if (status != DCE2_RET__SUCCESS)
+            return status;
+        break;
+
+    default:
+        break;
+    }
+
+    return DCE2_RET__SUCCESS;
+}
+
index 5fa9be60bc958bcbbdd68b28eaf8ede1c15dcc35..f302cb7429bc702122289e8ff19d942920355536 100644 (file)
@@ -69,8 +69,14 @@ DCE2_Ret DCE2_SmbTransaction(DCE2_SmbSsnData*, const SmbNtHdr*,
     const DCE2_SmbComInfo*, const uint8_t*, uint32_t);
 DCE2_Ret DCE2_SmbTransaction2(DCE2_SmbSsnData*, const SmbNtHdr*,
     const DCE2_SmbComInfo*, const uint8_t*, uint32_t);
-DCE2_Ret DCE2_SmbNtTransact(DCE2_SmbSsnData *, const SmbNtHdr *,
-       const DCE2_SmbComInfo *, const uint8_t *, uint32_t);
+DCE2_Ret DCE2_SmbNtTransact(DCE2_SmbSsnData*, const SmbNtHdr*,
+    const DCE2_SmbComInfo*, const uint8_t*, uint32_t);
+DCE2_Ret DCE2_SmbTransactionSecondary(DCE2_SmbSsnData*, const SmbNtHdr*,
+    const DCE2_SmbComInfo*, const uint8_t*, uint32_t);
+DCE2_Ret DCE2_SmbTransaction2Secondary(DCE2_SmbSsnData*, const SmbNtHdr*,
+    const DCE2_SmbComInfo*, const uint8_t*, uint32_t);
+DCE2_Ret DCE2_SmbNtTransactSecondary(DCE2_SmbSsnData*, const SmbNtHdr*,
+    const DCE2_SmbComInfo*, const uint8_t*, uint32_t);
 
 #endif