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
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)
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)
{
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);
{
/* 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;
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)
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);
ssd->pdu_state = DCE2_SMB_PDU_STATE__RAW_DATA;
}
-
/********************************************************************
*
* Process write command
{
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;
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)
{
{
/* 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);
inline void DCE2_SMB_PAF_SHIFT(uint64_t& x64, const uint8_t& x8)
{
x64 <<= 8;
- x64 |= (uint64_t) x8;
+ x64 |= (uint64_t)x8;
}
}
* 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);
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;
}
{
uint32_t n = 0;
StreamSplitter::Status ps = StreamSplitter::SEARCH;
- const SmbNtHdr *nt_hdr = nullptr;
+ const SmbNtHdr* nt_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;
}
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;
//(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;