From: Russ Combs (rucombs) Date: Mon, 20 Jun 2016 16:03:07 +0000 (-0400) Subject: Merge pull request #528 in SNORT/snort3 from smb_transaction_secondary to master X-Git-Tag: 3.0.0-233~362 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dd7e04384a8a39c69a7f5f3891e30804dbbba647;p=thirdparty%2Fsnort3.git Merge pull request #528 in SNORT/snort3 from smb_transaction_secondary to master Squashed commit of the following: commit a20ef7cd26f3d9479fc4ec6a0984aa5f8887e270 Author: mdagon Date: Thu Jun 16 17:02:16 2016 -0400 Smb transact secondary port --- diff --git a/src/service_inspectors/dce_rpc/dce_smb.cc b/src/service_inspectors/dce_rpc/dce_smb.cc index 079fde881..6fc9f4a3f 100644 --- a/src/service_inspectors/dce_rpc/dce_smb.cc +++ b/src/service_inspectors/dce_rpc/dce_smb.cc @@ -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; diff --git a/src/service_inspectors/dce_rpc/dce_smb.h b/src/service_inspectors/dce_rpc/dce_smb.h index d236c2d08..459f461b7 100644 --- a/src/service_inspectors/dce_rpc/dce_smb.h +++ b/src/service_inspectors/dce_rpc/dce_smb.h @@ -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 SmbNtTransactReq* req) { return alignedNtohs(&req->smb_function); } -inline uint8_t SmbNtTransactReqSetupCnt(const SmbNtTransactReq *req) +inline uint8_t SmbNtTransactReqSetupCnt(const SmbNtTransactReq* req) { return req->smb_setup_count; } -inline uint32_t SmbNtTransactReqTotalParamCnt(const SmbNtTransactReq *req) +inline uint32_t SmbNtTransactReqTotalParamCnt(const SmbNtTransactReq* req) { return alignedNtohl(&req->smb_total_param_count); } -inline uint32_t SmbNtTransactReqParamCnt(const SmbNtTransactReq *req) +inline uint32_t SmbNtTransactReqParamCnt(const SmbNtTransactReq* req) { return alignedNtohl(&req->smb_param_count); } -inline uint32_t SmbNtTransactReqParamOff(const SmbNtTransactReq *req) +inline uint32_t SmbNtTransactReqParamOff(const SmbNtTransactReq* req) { return alignedNtohl(&req->smb_param_offset); } -inline uint32_t SmbNtTransactReqTotalDataCnt(const SmbNtTransactReq *req) +inline uint32_t SmbNtTransactReqTotalDataCnt(const SmbNtTransactReq* req) { return alignedNtohl(&req->smb_total_data_count); } -inline uint32_t SmbNtTransactReqDataCnt(const SmbNtTransactReq *req) +inline uint32_t SmbNtTransactReqDataCnt(const SmbNtTransactReq* req) { return alignedNtohl(&req->smb_data_count); } -inline uint32_t SmbNtTransactReqDataOff(const SmbNtTransactReq *req) +inline uint32_t SmbNtTransactReqDataOff(const SmbNtTransactReq* req) { return alignedNtohl(&req->smb_data_offset); } -inline uint32_t SmbNtTransactRespTotalParamCnt(const SmbNtTransactResp *resp) +inline uint32_t SmbNtTransactRespTotalParamCnt(const SmbNtTransactResp* resp) { return alignedNtohl(&resp->smb_total_param_count); } -inline uint32_t SmbNtTransactRespParamCnt(const SmbNtTransactResp *resp) +inline uint32_t SmbNtTransactRespParamCnt(const SmbNtTransactResp* resp) { return alignedNtohl(&resp->smb_param_count); } -inline uint32_t SmbNtTransactRespParamOff(const SmbNtTransactResp *resp) +inline uint32_t SmbNtTransactRespParamOff(const SmbNtTransactResp* resp) { return alignedNtohl(&resp->smb_param_offset); } -inline uint32_t SmbNtTransactRespParamDisp(const SmbNtTransactResp *resp) +inline uint32_t SmbNtTransactRespParamDisp(const SmbNtTransactResp* resp) { return alignedNtohl(&resp->smb_param_disp); } -inline uint32_t SmbNtTransactRespTotalDataCnt(const SmbNtTransactResp *resp) +inline uint32_t SmbNtTransactRespTotalDataCnt(const SmbNtTransactResp* resp) { return alignedNtohl(&resp->smb_total_data_count); } -inline uint32_t SmbNtTransactRespDataCnt(const SmbNtTransactResp *resp) +inline uint32_t SmbNtTransactRespDataCnt(const SmbNtTransactResp* resp) { return alignedNtohl(&resp->smb_data_count); } -inline uint32_t SmbNtTransactRespDataOff(const SmbNtTransactResp *resp) +inline uint32_t SmbNtTransactRespDataOff(const SmbNtTransactResp* resp) { return alignedNtohl(&resp->smb_data_offset); } -inline uint32_t SmbNtTransactRespDataDisp(const SmbNtTransactResp *resp) +inline uint32_t SmbNtTransactRespDataDisp(const SmbNtTransactResp* resp) { 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 SmbNtTransactCreateReqParams* req) { return alignedNtohq(&req->allocation_size); } -inline uint32_t SmbNtTransactCreateReqFileNameLength(const SmbNtTransactCreateReqParams *req) +inline uint32_t SmbNtTransactCreateReqFileNameLength(const SmbNtTransactCreateReqParams* req) { return alignedNtohl(&req->name_length); } -inline uint32_t SmbNtTransactCreateReqFileAttrs(const SmbNtTransactCreateReqParams *req) +inline uint32_t SmbNtTransactCreateReqFileAttrs(const SmbNtTransactCreateReqParams* req) { return alignedNtohl(&req->ext_file_attributes); } -inline bool SmbNtTransactCreateReqSequentialOnly(const SmbNtTransactCreateReqParams *req) +inline bool SmbNtTransactCreateReqSequentialOnly(const SmbNtTransactCreateReqParams* req) { 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 SmbNtTransactCreateRespParams* resp) { return alignedNtohs(&resp->smb_fid); } -inline uint32_t SmbNtTransactCreateRespCreateAction(const SmbNtTransactCreateRespParams *resp) +inline uint32_t SmbNtTransactCreateRespCreateAction(const SmbNtTransactCreateRespParams* resp) { return alignedNtohl(&resp->create_action); } -inline uint64_t SmbNtTransactCreateRespEndOfFile(const SmbNtTransactCreateRespParams *resp) +inline uint64_t SmbNtTransactCreateRespEndOfFile(const SmbNtTransactCreateRespParams* resp) { return alignedNtohq(&resp->end_of_file); } -inline uint16_t SmbNtTransactCreateRespResourceType(const SmbNtTransactCreateRespParams *resp) +inline uint16_t SmbNtTransactCreateRespResourceType(const SmbNtTransactCreateRespParams* resp) { return alignedNtohs(&resp->resource_type); } -inline bool SmbNtTransactCreateRespDirectory(const SmbNtTransactCreateRespParams *resp) +inline bool SmbNtTransactCreateRespDirectory(const SmbNtTransactCreateRespParams* resp) { 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() diff --git a/src/service_inspectors/dce_rpc/dce_smb_commands.cc b/src/service_inspectors/dce_rpc/dce_smb_commands.cc index a67c3696d..a517868a8 100644 --- a/src/service_inspectors/dce_rpc/dce_smb_commands.cc +++ b/src/service_inspectors/dce_rpc/dce_smb_commands.cc @@ -29,6 +29,11 @@ #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; +} + diff --git a/src/service_inspectors/dce_rpc/dce_smb_commands.h b/src/service_inspectors/dce_rpc/dce_smb_commands.h index 5fa9be60b..f302cb742 100644 --- a/src/service_inspectors/dce_rpc/dce_smb_commands.h +++ b/src/service_inspectors/dce_rpc/dce_smb_commands.h @@ -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