SO_PUBLIC int SnortEventqAdd(uint32_t gid, uint32_t sid, RuleType = RULE_TYPE__NONE);
SO_PUBLIC bool event_is_enabled(uint32_t gid, uint32_t sid);
-SO_PUBLIC void SnortEventqPush(void);
-SO_PUBLIC void SnortEventqPop(void);
+void SnortEventqPush(void);
+void SnortEventqPop(void);
#endif
// based on work by Todd Wease
#include "dce_co.h"
-#include "dce_tcp.h"
-#include "dce_smb.h"
-#include "dce_list.h"
-#include "dce_utils.h"
-#include "profiler/profiler.h"
-#include "main/snort_debug.h"
-#include "log/messages.h"
-
-THREAD_LOCAL int co_reassembled = 0;
/********************************************************************
* Function: DCE2_CoInitTracker()
* these fields have been set.
*
********************************************************************/
-void DCE2_CoInitTracker(DCE2_CoTracker* cot)
+void DCE2_CoInitTracker(DCE2_CoTracker *cot)
{
- if (cot == nullptr)
+ if (cot == NULL)
return;
cot->max_xmit_frag = DCE2_SENTINEL;
cot->ctx_id = DCE2_SENTINEL;
cot->opnum = DCE2_SENTINEL;
cot->call_id = DCE2_SENTINEL;
- cot->stub_data = nullptr;
+ cot->stub_data = NULL;
cot->got_bind = 0;
cot->frag_tracker.opnum = DCE2_SENTINEL;
cot->frag_tracker.expected_ctx_id = DCE2_SENTINEL;
}
-/********************************************************************
- * Function: DCE2_CoResetFragTracker()
- *
- * Resets frag tracker fields after having reassembled.
- *
- ********************************************************************/
-static inline void DCE2_CoResetFragTracker(DCE2_CoFragTracker* ft)
-{
- if (ft == nullptr)
- return;
-
- ft->opnum = DCE2_SENTINEL;
- ft->ctx_id = DCE2_SENTINEL;
- ft->expected_call_id = DCE2_SENTINEL;
- ft->expected_ctx_id = DCE2_SENTINEL;
- ft->expected_opnum = DCE2_SENTINEL;
-}
-
-/********************************************************************
- * Function: DCE2_CoResetTracker()
- *
- * Resets fields that are transient for requests after the bind or
- * alter context. The context id and opnum are dependent on the
- * request and in the case of fragmented requests are set until all
- * fragments are received. If we got a full request or all of the
- * fragments, these should be reset.
- *
- ********************************************************************/
-static inline void DCE2_CoResetTracker(DCE2_CoTracker* cot)
-{
- if (cot == nullptr)
- return;
-
- cot->ctx_id = DCE2_SENTINEL;
- cot->opnum = DCE2_SENTINEL;
- cot->call_id = DCE2_SENTINEL;
- cot->stub_data = nullptr;
-
- DCE2_CoResetFragTracker(&cot->frag_tracker);
-}
-
-static inline bool DCE2_CoIsSegBuf(DCE2_SsnData* sd, DCE2_CoTracker* cot, const uint8_t* ptr)
-{
- DCE2_Buffer* seg_buf;
-
- if (DCE2_SsnFromServer(sd->wire_pkt))
- seg_buf = cot->srv_seg.buf;
- else
- seg_buf = cot->cli_seg.buf;
-
- if (DCE2_BufferIsEmpty(seg_buf))
- return 0;
-
- /* See if we're looking at a segmentation buffer */
- if ((ptr < DCE2_BufferData(seg_buf)) ||
- (ptr > (DCE2_BufferData(seg_buf) + DCE2_BufferLength(seg_buf))))
- {
- return 0;
- }
-
- return 1;
-}
-
-static inline DCE2_CoSeg* DCE2_CoGetSegPtr(DCE2_SsnData* sd, DCE2_CoTracker* cot)
-{
- if (DCE2_SsnFromServer(sd->wire_pkt))
- return &cot->srv_seg;
-
- return &cot->cli_seg;
-}
-
-/********************************************************************
- * Function: DCE2_CoSetIface()
- *
- * Sets the interface UUID for the rules options. Looks in the
- * context id list. If nothing found there, it looks in the pending
- * list (in case we never saw the server response because of
- * missed packets) to see if something is there.
- *
- ********************************************************************/
-static DCE2_Ret DCE2_CoSetIface(DCE2_SsnData* sd, DCE2_CoTracker* cot, uint16_t ctx_id)
-{
- DCE2_CoCtxIdNode* ctx_id_node;
-
- /* This should be set if we've gotten a Bind */
- if (cot->ctx_ids == nullptr)
- return DCE2_RET__ERROR;
- if (sd->trans == DCE2_TRANS_TYPE__TCP)
- {
- Profile profile(dce2_tcp_pstat_co_ctx);
- }
- else
- {
- Profile profile(dce2_smb_pstat_co_ctx);
- }
-
- ctx_id_node = (DCE2_CoCtxIdNode*)DCE2_ListFind(cot->ctx_ids, (void*)(uintptr_t)ctx_id);
- if (ctx_id_node == nullptr) /* context id not found in list */
- {
- /* See if it's in the queue. An easy evasion would be to stagger the writes
- * and reads such that we see a request before seeing the server bind ack */
- if (cot->pending_ctx_ids != nullptr)
- {
- for (ctx_id_node = (DCE2_CoCtxIdNode*)DCE2_QueueFirst(cot->pending_ctx_ids);
- ctx_id_node != nullptr;
- ctx_id_node = (DCE2_CoCtxIdNode*)DCE2_QueueNext(cot->pending_ctx_ids))
- {
- if (ctx_id_node->ctx_id == ctx_id)
- break;
- }
- }
-
- if (ctx_id_node == nullptr)
- {
- return DCE2_RET__ERROR;
- }
- }
-
- if (ctx_id_node->state == DCE2_CO_CTX_STATE__REJECTED)
- {
- return DCE2_RET__ERROR;
- }
-
- DCE2_CopyUuid(&sd->ropts.iface, &ctx_id_node->iface, DCERPC_BO_FLAG__NONE);
- sd->ropts.iface_vers_maj = ctx_id_node->iface_vers_maj;
- sd->ropts.iface_vers_min = ctx_id_node->iface_vers_min;
-
- return DCE2_RET__SUCCESS;
-}
-
-/********************************************************************
- * Function: DCE2_CoSetRopts()
- *
- * Sets values necessary for the rule options.
- *
- ********************************************************************/
-static inline void DCE2_CoSetRopts(DCE2_SsnData* sd, DCE2_CoTracker* cot, const
- DceRpcCoHdr* co_hdr)
-{
- DCE2_CoFragTracker* ft = &cot->frag_tracker;
- int opnum = (ft->opnum != DCE2_SENTINEL) ? ft->opnum : cot->opnum;
- int ctx_id = (ft->ctx_id != DCE2_SENTINEL) ? ft->ctx_id : cot->ctx_id;
-
- int data_byte_order =
- (cot->data_byte_order != DCE2_SENTINEL) ?
- cot->data_byte_order : (int)DceRpcCoByteOrder(co_hdr);
-
- if (DCE2_CoSetIface(sd, cot, (uint16_t)ctx_id) != DCE2_RET__SUCCESS)
- sd->ropts.first_frag = DCE2_SENTINEL;
- else
- sd->ropts.first_frag = DceRpcCoFirstFrag(co_hdr);
-
- sd->ropts.hdr_byte_order = DceRpcCoByteOrder(co_hdr);
- sd->ropts.data_byte_order = data_byte_order;
- sd->ropts.opnum = opnum;
- sd->ropts.stub_data = cot->stub_data;
-}
-
-static inline dce2CommonStats* dce_get_proto_stats_ptr(DCE2_SsnData* sd)
-{
- if (sd->trans == DCE2_TRANS_TYPE__TCP)
- {
- return((dce2CommonStats*)&dce2_tcp_stats);
- }
- else
- {
- return((dce2CommonStats*)&dce2_smb_stats);
- }
-}
-
-/********************************************************************
- * Function: DCE2_CoHdrChecks()
- *
- * Checks some relevant fields in the header to make sure they're
- * sane.
- *
- ********************************************************************/
-static DCE2_Ret DCE2_CoHdrChecks(DCE2_SsnData* sd, DCE2_CoTracker* cot, const DceRpcCoHdr* co_hdr)
-{
- uint16_t frag_len = DceRpcCoFragLen(co_hdr);
- DceRpcPduType pdu_type = DceRpcCoPduType(co_hdr);
- dce2CommonStats* dce_common_stats = dce_get_proto_stats_ptr(sd);
-
- if (frag_len < sizeof(DceRpcCoHdr))
- {
- /* Assume we autodetected incorrectly or that DCE/RPC is not running
- * over the SMB named pipe */
- if (!DCE2_SsnAutodetected(sd) && (sd->trans != DCE2_TRANS_TYPE__SMB))
- {
- //FIXIT-M add segment check
- dce_alert(GID_DCE2, DCE2_CO_FRAG_LEN_LT_HDR,dce_common_stats);
- }
-
- return DCE2_RET__ERROR;
- }
-
- if (DceRpcCoVersMaj(co_hdr) != DCERPC_PROTO_MAJOR_VERS__5)
- {
- if (!DCE2_SsnAutodetected(sd) && (sd->trans != DCE2_TRANS_TYPE__SMB))
- {
- //FIXIT-M add segment check
- dce_alert(GID_DCE2, DCE2_CO_BAD_MAJOR_VERSION,dce_common_stats);
- }
-
- return DCE2_RET__ERROR;
- }
-
- if (DceRpcCoVersMin(co_hdr) != DCERPC_PROTO_MINOR_VERS__0)
- {
- if (!DCE2_SsnAutodetected(sd) && (sd->trans != DCE2_TRANS_TYPE__SMB))
- {
- //FIXIT-M add segment check
- dce_alert(GID_DCE2, DCE2_CO_BAD_MINOR_VERSION,dce_common_stats);
- }
-
- return DCE2_RET__ERROR;
- }
- if (pdu_type >= DCERPC_PDU_TYPE__MAX)
- {
- if (!DCE2_SsnAutodetected(sd) && (sd->trans != DCE2_TRANS_TYPE__SMB))
- {
- //FIXIT-M add segment check
-
- dce_alert(GID_DCE2, DCE2_CO_BAD_PDU_TYPE,dce_common_stats);
- }
-
- return DCE2_RET__ERROR;
- }
-
- if (DCE2_SsnFromClient(sd->wire_pkt) && (cot->max_xmit_frag != DCE2_SENTINEL))
- {
- if (frag_len > cot->max_xmit_frag)
- {
- //FIXIT-M add segment check
- dce_alert(GID_DCE2, DCE2_CO_FRAG_GT_MAX_XMIT_FRAG,dce_common_stats);
- }
- else if (!DceRpcCoLastFrag(co_hdr) && (pdu_type == DCERPC_PDU_TYPE__REQUEST)
- && ((((int)cot->max_xmit_frag - DCE2_MAX_XMIT_SIZE_FUZZ) < 0)
- || ((int)frag_len < ((int)cot->max_xmit_frag - DCE2_MAX_XMIT_SIZE_FUZZ))))
- {
- /* If client needs to fragment the DCE/RPC request, it shouldn't be less than the
- * maximum xmit size negotiated. Only if it's not a last fragment. Make this alert
- * only if it is considerably less - have seen legitimate fragments that are just
- * slightly less the negotiated fragment size. */
-
- //FIXIT-M add segment check
- dce_alert(GID_DCE2, DCE2_CO_FRAG_LT_MAX_XMIT_FRAG,dce_common_stats);
- }
-
- /* Continue processing */
- }
-
- return DCE2_RET__SUCCESS;
-}
-
-/********************************************************************
- * Function: DCE2_CoCtxCompare()
- *
- * Callback to context id list for finding the right interface
- * UUID node. Values passed in are context ids which are used as
- * the keys for the list.
- *
- ********************************************************************/
-static int DCE2_CoCtxCompare(const void* a, const void* b)
-{
- int x = (int)(uintptr_t)a;
- int y = (int)(uintptr_t)b;
-
- if (x == y)
- return 0;
-
- /* Only care about equality for finding */
- return -1;
-}
-
-/********************************************************************
- * Function: DCE2_CoCtxFree()
- *
- * Callback to context id list for freeing context id nodes in
- * the list.
- *
- ********************************************************************/
-static void DCE2_CoCtxFree(void* data)
-{
- if (data == nullptr)
- return;
-
- free(data);
-}
-
-/********************************************************************
- * Function: DCE2_CoInitCtxStorage()
- *
- * Allocates, if necessary, and initializes the context id list
- * and the context id pending queue.
- *
- *
- ********************************************************************/
-static inline DCE2_Ret DCE2_CoInitCtxStorage(DCE2_CoTracker* cot)
-{
- if (cot == nullptr)
- return DCE2_RET__ERROR;
-
- if (cot->ctx_ids == nullptr)
- {
- cot->ctx_ids = DCE2_ListNew(DCE2_LIST_TYPE__SPLAYED, DCE2_CoCtxCompare, DCE2_CoCtxFree,
- nullptr, DCE2_LIST_FLAG__NO_DUPS);
- if (cot->ctx_ids == nullptr)
- return DCE2_RET__ERROR;
- }
-
- if (cot->pending_ctx_ids == nullptr)
- {
- cot->pending_ctx_ids = DCE2_QueueNew(DCE2_CoCtxFree);
- if (cot->pending_ctx_ids == nullptr)
- {
- DCE2_ListDestroy(cot->ctx_ids);
- cot->ctx_ids = nullptr;
- return DCE2_RET__ERROR;
- }
- }
- else if (!DCE2_QueueIsEmpty(cot->pending_ctx_ids))
- {
- DCE2_QueueEmpty(cot->pending_ctx_ids);
- }
-
- return DCE2_RET__SUCCESS;
-}
-
-/********************************************************************
- * Function: DCE2_CoEraseCtxIds()
- *
- * Empties out the context id list and the pending context id
- * queue. Does not free the list and queue - might need to still
- * use them.
- *
- ********************************************************************/
-static inline void DCE2_CoEraseCtxIds(DCE2_CoTracker* cot)
-{
- if (cot == nullptr)
- return;
-
- DCE2_QueueEmpty(cot->pending_ctx_ids);
- DCE2_ListEmpty(cot->ctx_ids);
-}
-
-DCE2_CoCtxIdNode* dce_process_ctx_id(DCE2_SsnData* sd,DCE2_CoTracker* cot,
- const DceRpcCoHdr* co_hdr,DCE2_Policy policy,
- const uint8_t* frag_ptr, uint16_t frag_len)
-{
- DCE2_CoCtxIdNode* ctx_node;
- DCE2_Ret status;
- uint16_t ctx_id;
- uint8_t num_tsyns;
- const Uuid* iface;
- uint16_t if_vers_maj;
- uint16_t if_vers_min;
- DceRpcCoContElem* ctx_elem = (DceRpcCoContElem*)frag_ptr;
- dce2CommonStats* dce_common_stats = dce_get_proto_stats_ptr(sd);
-
- int j;
-
- if (frag_len < sizeof(DceRpcCoContElem))
- {
- dce_alert(GID_DCE2, DCE2_CO_REM_FRAG_LEN_LT_SIZE, dce_common_stats);
- return nullptr;
- }
-
- ctx_id = DceRpcCoContElemCtxId(co_hdr, ctx_elem);
- num_tsyns = DceRpcCoContElemNumTransSyntaxes(ctx_elem);
- iface = DceRpcCoContElemIface(ctx_elem);
- if_vers_maj = DceRpcCoContElemIfaceVersMaj(co_hdr, ctx_elem);
- if_vers_min = DceRpcCoContElemIfaceVersMin(co_hdr, ctx_elem);
-
- /* No transfer syntaxes */
- if (num_tsyns == 0)
- {
- dce_alert(GID_DCE2, DCE2_CO_NO_TFER_SYNTAX_SPECFD,dce_common_stats);
- return nullptr;
- }
-
- DCE2_MOVE(frag_ptr, frag_len, sizeof(DceRpcCoContElem));
-
- /* Don't really care about the transfer syntaxes */
- for (j = 0; j < num_tsyns; j++)
- {
- if (frag_len < sizeof(DceRpcCoSynId))
- {
- dce_alert(GID_DCE2, DCE2_CO_REM_FRAG_LEN_LT_SIZE, dce_common_stats);
- return nullptr;
- }
-
- DCE2_MOVE(frag_ptr, frag_len, sizeof(DceRpcCoSynId));
- }
- if (sd->trans == DCE2_TRANS_TYPE__TCP)
- {
- Profile profile(dce2_tcp_pstat_co_ctx);
- }
- else
- {
- Profile profile(dce2_smb_pstat_co_ctx);
- }
-
- /* If there is already an accepted node with in the list
- * with this ctx, just return */
- if (policy == DCE2_POLICY__SAMBA_3_0_20)
- {
- ctx_node = (DCE2_CoCtxIdNode*)DCE2_ListFind(cot->ctx_ids, (void*)(uintptr_t)ctx_id);
- if ((ctx_node != nullptr) && (ctx_node->state != DCE2_CO_CTX_STATE__REJECTED))
- {
- return nullptr;
- }
- }
-
- ctx_node = (DCE2_CoCtxIdNode*)calloc(sizeof(DCE2_CoCtxIdNode),1);
- if (ctx_node == nullptr)
- {
- return nullptr;
- }
-
- /* Add context id to pending queue */
- status = DCE2_QueueEnqueue(cot->pending_ctx_ids, ctx_node);
- if (status != DCE2_RET__SUCCESS)
- {
- free(ctx_node);
- return nullptr;
- }
-
- /* This node will get moved to the context id list upon server response */
- ctx_node->ctx_id = ctx_id;
- DCE2_CopyUuid(&ctx_node->iface, iface, DceRpcCoByteOrder(co_hdr));
- ctx_node->iface_vers_maj = if_vers_maj;
- ctx_node->iface_vers_min = if_vers_min;
- ctx_node->state = DCE2_CO_CTX_STATE__PENDING;
- return ctx_node;
-}
-
-/********************************************************************
- * Function: DCE2_CoCtxReq()
- *
- * Handles parsing the context id list out of the packet.
- * Context ids and associated uuids are stored in a queue and
- * dequeued upon server response. Server response doesn't
- * indicate by context id which bindings were accepted or
- * rejected, but the index or order they were in in the client
- * bind or alter context, hence the queue.
- *
- ********************************************************************/
-static void DCE2_CoCtxReq(DCE2_SsnData* sd, DCE2_CoTracker* cot, const DceRpcCoHdr* co_hdr,
- const uint8_t num_ctx_items, const uint8_t* frag_ptr, uint16_t frag_len)
-{
- DCE2_Policy policy = DCE2_SsnGetServerPolicy(sd);
- unsigned int i;
- dce2CommonStats* dce_common_stats = dce_get_proto_stats_ptr(sd);
-
- if (num_ctx_items == 0)
- {
- dce_alert(GID_DCE2, DCE2_CO_NO_CTX_ITEMS_SPECFD, dce_common_stats);
- return;
- }
-
- for (i = 0; i < num_ctx_items; i++)
- {
- DCE2_CoCtxIdNode* ctx_node;
-
- ctx_node = dce_process_ctx_id(sd,cot,co_hdr,policy,frag_ptr,frag_len);
- if ((ctx_node == nullptr))
- {
- return;
- }
-
- DebugFormat(DEBUG_DCE_COMMON, "Added Context item to queue.\n"
- " Context id: %u\n"
- " Interface: %s\n"
- " Interface major version: %u\n"
- " Interface minor version: %u\n",
- ctx_node->ctx_id,
- DCE2_UuidToStr(&ctx_node->iface, DCERPC_BO_FLAG__NONE),
- ctx_node->iface_vers_maj, ctx_node->iface_vers_min);
-
- switch (policy)
- {
- case DCE2_POLICY__SAMBA:
- case DCE2_POLICY__SAMBA_3_0_37:
- case DCE2_POLICY__SAMBA_3_0_22:
- case DCE2_POLICY__SAMBA_3_0_20:
- /* Samba only ever looks at one context item. Not sure
- * if this is an alertable offense */
- return;
-
- default:
- break;
- }
- }
-}
-
-void dce_process_ctx_result(DCE2_SsnData* sd,DCE2_CoTracker* cot,
- const DceRpcCoHdr* co_hdr,DCE2_Policy policy,
- uint16_t result)
-{
- DCE2_CoCtxIdNode* ctx_node, * existing_ctx_node;
- DCE2_Ret status;
-
- if (sd->trans == DCE2_TRANS_TYPE__TCP)
- {
- Profile profile(dce2_tcp_pstat_co_ctx);
- }
- else
- {
- Profile profile(dce2_smb_pstat_co_ctx);
- }
-
- /* Dequeue context item in pending queue - this will get put in the permanent
- * context id list or free'd */
- ctx_node = (DCE2_CoCtxIdNode*)DCE2_QueueDequeue(cot->pending_ctx_ids);
- if (ctx_node == nullptr)
- {
- LogMessage("%s(%d) Failed to dequeue a context id node.\n",
- __FILE__, __LINE__);
- return;
- }
-
- DebugFormat(DEBUG_DCE_COMMON, "Adding Context item to context item list.\n"
- " Context id: %u\n"
- " Interface: %s\n"
- " Interface major version: %u\n"
- " Interface minor version: %u\n",
- ctx_node->ctx_id,
- DCE2_UuidToStr(&ctx_node->iface, DCERPC_BO_FLAG__NONE),
- ctx_node->iface_vers_maj, ctx_node->iface_vers_min);
-
- if (result == DCERPC_CO_CONT_DEF_RESULT__ACCEPTANCE)
- {
- DebugMessage(DEBUG_DCE_COMMON, "Server accepted context item.\n");
- ctx_node->state = DCE2_CO_CTX_STATE__ACCEPTED;
- if (DceRpcCoPduType(co_hdr) == DCERPC_PDU_TYPE__BIND_ACK)
- cot->got_bind = 1;
- }
- else
- {
- DebugMessage(DEBUG_DCE_COMMON, "Server rejected context item.\n");
- ctx_node->state = DCE2_CO_CTX_STATE__REJECTED;
- cot->got_bind = 0;
- }
-
- existing_ctx_node =
- (DCE2_CoCtxIdNode*)DCE2_ListFind(cot->ctx_ids, (void*)(uintptr_t)ctx_node->ctx_id);
-
- if (existing_ctx_node != nullptr)
- {
- switch (policy)
- {
- case DCE2_POLICY__WIN2000:
- case DCE2_POLICY__WIN2003:
- case DCE2_POLICY__WINXP:
- case DCE2_POLICY__WINVISTA:
- case DCE2_POLICY__WIN2008:
- case DCE2_POLICY__WIN7:
- if (ctx_node->state == DCE2_CO_CTX_STATE__REJECTED)
- break;
-
- if (existing_ctx_node->state == DCE2_CO_CTX_STATE__REJECTED)
- {
- existing_ctx_node->ctx_id = ctx_node->ctx_id;
- DCE2_CopyUuid(&existing_ctx_node->iface, &ctx_node->iface, DCERPC_BO_FLAG__NONE);
- existing_ctx_node->iface_vers_maj = ctx_node->iface_vers_maj;
- existing_ctx_node->iface_vers_min = ctx_node->iface_vers_min;
- existing_ctx_node->state = ctx_node->state;
- }
-
- break;
-
- case DCE2_POLICY__SAMBA:
- case DCE2_POLICY__SAMBA_3_0_37:
- case DCE2_POLICY__SAMBA_3_0_22:
- case DCE2_POLICY__SAMBA_3_0_20:
- /* Samba actually alters the context. Windows keeps the old */
- if (ctx_node->state != DCE2_CO_CTX_STATE__REJECTED)
- {
- existing_ctx_node->ctx_id = ctx_node->ctx_id;
- DCE2_CopyUuid(&existing_ctx_node->iface, &ctx_node->iface, DCERPC_BO_FLAG__NONE);
- existing_ctx_node->iface_vers_maj = ctx_node->iface_vers_maj;
- existing_ctx_node->iface_vers_min = ctx_node->iface_vers_min;
- existing_ctx_node->state = ctx_node->state;
- }
-
- break;
-
- default:
- break;
- }
-
- free((void*)ctx_node);
- }
- else
- {
- status = DCE2_ListInsert(cot->ctx_ids, (void*)(uintptr_t)ctx_node->ctx_id,
- (void*)ctx_node);
- if (status != DCE2_RET__SUCCESS)
- {
- free((void*)ctx_node);
- DebugMessage(DEBUG_DCE_COMMON,
- "Failed to add context id node to list.\n");
- return;
- }
- }
-}
-
-/********************************************************************
- * Function: DCE2_CoBindAck()
- *
- * Handles the processing of a server bind ack or a server alter
- * context response since they share the same header.
- * Moves context id items from the pending queue into a list
- * ultimately used by the rule options and sets each context item
- * as accepted or rejected based on the server response.
- *
- ********************************************************************/
-static void DCE2_CoBindAck(DCE2_SsnData* sd, DCE2_CoTracker* cot,
- const DceRpcCoHdr* co_hdr, const uint8_t* frag_ptr, uint16_t frag_len)
-{
- DCE2_Policy policy = DCE2_SsnGetServerPolicy(sd);
- DceRpcCoBindAck* bind_ack = (DceRpcCoBindAck*)frag_ptr;
- uint16_t sec_addr_len;
- const uint8_t* ctx_data;
- uint16_t ctx_len;
- uint16_t pad = 0;
- DceRpcCoContResultList* ctx_list;
- uint8_t num_ctx_results;
- unsigned int i;
- uint16_t max_recv_frag;
- dce2CommonStats* dce_common_stats = dce_get_proto_stats_ptr(sd);
-
- if (frag_len < sizeof(DceRpcCoBindAck))
- {
- dce_alert(GID_DCE2, DCE2_CO_REM_FRAG_LEN_LT_SIZE,dce_common_stats);
- return;
- }
-
- DCE2_MOVE(frag_ptr, frag_len, sizeof(DceRpcCoBindAck));
-
- /* Set what should be the maximum amount of data a client can send in a fragment */
- max_recv_frag = DceRpcCoBindAckMaxRecvFrag(co_hdr, bind_ack);
- if ((cot->max_xmit_frag == DCE2_SENTINEL) || (max_recv_frag < cot->max_xmit_frag))
- cot->max_xmit_frag = (int)max_recv_frag;
-
- sec_addr_len = DceRpcCoSecAddrLen(co_hdr, bind_ack);
-
- ctx_data = frag_ptr;
- ctx_len = frag_len;
-
- /* First move past secondary address */
- if (ctx_len < sec_addr_len)
- {
- dce_alert(GID_DCE2, DCE2_CO_REM_FRAG_LEN_LT_SIZE,dce_common_stats);
- return;
- }
-
- DCE2_MOVE(ctx_data, ctx_len, sec_addr_len);
-
- /* padded to 4 octet */
- if ((sizeof(DceRpcCoBindAck) + sec_addr_len) & 3)
- pad = (4 - ((sizeof(DceRpcCoBindAck) + sec_addr_len) & 3));
-
- if (ctx_len < pad)
- {
- dce_alert(GID_DCE2, DCE2_CO_REM_FRAG_LEN_LT_SIZE,dce_common_stats);
- return;
- }
-
- DCE2_MOVE(ctx_data, ctx_len, pad);
-
- /* Now we're at the start of the context item results */
- if (ctx_len < sizeof(DceRpcCoContResultList))
- {
- dce_alert(GID_DCE2, DCE2_CO_REM_FRAG_LEN_LT_SIZE,dce_common_stats);
- return;
- }
-
- ctx_list = (DceRpcCoContResultList*)ctx_data;
- num_ctx_results = DceRpcCoContNumResults(ctx_list);
-
- DCE2_MOVE(ctx_data, ctx_len, sizeof(DceRpcCoContResultList));
-
- for (i = 0; i < num_ctx_results; i++)
- {
- DceRpcCoContResult* ctx_result;
- uint16_t result;
-
- if (ctx_len < sizeof(DceRpcCoContResult))
- {
- dce_alert(GID_DCE2, DCE2_CO_REM_FRAG_LEN_LT_SIZE,dce_common_stats);
- return;
- }
- ctx_result = (DceRpcCoContResult*)ctx_data;
- result = DceRpcCoContRes(co_hdr, ctx_result);
-
- DCE2_MOVE(ctx_data, ctx_len, sizeof(DceRpcCoContResult));
-
- if (DCE2_QueueIsEmpty(cot->pending_ctx_ids))
- return;
-
- dce_process_ctx_result(sd,cot,co_hdr,policy,result);
- }
-}
-
-/********************************************************************
- * Function: DCE2_CoBind()
- *
- * Handles the processing of a client bind request. There are
- * differences between Windows and Samba and even early Samba in
- * how multiple binds on the session are handled. Processing of
- * the context id bindings is handed off.
- *
- ********************************************************************/
-static void DCE2_CoBind(DCE2_SsnData* sd, DCE2_CoTracker* cot,
- const DceRpcCoHdr* co_hdr, const uint8_t* frag_ptr, uint16_t frag_len)
-{
- DCE2_Policy policy = DCE2_SsnGetServerPolicy(sd);
- DceRpcCoBind* bind = (DceRpcCoBind*)frag_ptr;
- dce2CommonStats* dce_common_stats = dce_get_proto_stats_ptr(sd);
-
- if (frag_len < sizeof(DceRpcCoBind))
- {
- dce_alert(GID_DCE2, DCE2_CO_REM_FRAG_LEN_LT_SIZE,dce_common_stats);
- return;
- }
-
- DCE2_MOVE(frag_ptr, frag_len, sizeof(DceRpcCoBind));
-
- switch (policy)
- {
- case DCE2_POLICY__WIN2000:
- case DCE2_POLICY__WIN2003:
- case DCE2_POLICY__WINXP:
- case DCE2_POLICY__WINVISTA:
- case DCE2_POLICY__WIN2008:
- case DCE2_POLICY__WIN7:
- /* Windows will not accept more than one bind */
- if (!DCE2_ListIsEmpty(cot->ctx_ids))
- {
- /* Delete context id list if anything there */
- DCE2_CoEraseCtxIds(cot);
- return;
- }
-
- /* Byte order of stub data will be that of the bind */
- cot->data_byte_order = DceRpcCoByteOrder(co_hdr);
-
- break;
-
- case DCE2_POLICY__SAMBA:
- case DCE2_POLICY__SAMBA_3_0_37:
- case DCE2_POLICY__SAMBA_3_0_22:
- if (cot->got_bind)
- return;
-
- break;
-
- case DCE2_POLICY__SAMBA_3_0_20:
- /* Accepts multiple binds */
- break;
-
- default:
- LogMessage("%s(%d) Invalid policy: %d\n",
- __FILE__, __LINE__, policy);
- return;
- }
-
- cot->max_xmit_frag = (int)DceRpcCoBindMaxXmitFrag(co_hdr, bind);
- DCE2_CoCtxReq(sd, cot, co_hdr, DceRpcCoNumCtxItems(bind), frag_ptr, frag_len);
-}
-
-/********************************************************************
- * Function: DCE2_CoAlterCtx()
- *
- * Handles the processing of a client alter context request.
- * Again, differences in how this is handled - whether we've seen
- * a bind yet or not, altering the data byte order. Processing
- * of the context id bindings is handed off.
- *
- ********************************************************************/
-static void DCE2_CoAlterCtx(DCE2_SsnData* sd, DCE2_CoTracker* cot,
- const DceRpcCoHdr* co_hdr, const uint8_t* frag_ptr, uint16_t frag_len)
-{
- DCE2_Policy policy = DCE2_SsnGetServerPolicy(sd);
- DceRpcCoAltCtx* alt_ctx = (DceRpcCoAltCtx*)frag_ptr;
- dce2CommonStats* dce_common_stats = dce_get_proto_stats_ptr(sd);
-
- if (frag_len < sizeof(DceRpcCoAltCtx))
- {
- dce_alert(GID_DCE2, DCE2_CO_REM_FRAG_LEN_LT_SIZE,dce_common_stats);
- return;
- }
-
- DCE2_MOVE(frag_ptr, frag_len, sizeof(DceRpcCoAltCtx));
-
- switch (policy)
- {
- case DCE2_POLICY__WIN2000:
- case DCE2_POLICY__WIN2003:
- case DCE2_POLICY__WINXP:
- case DCE2_POLICY__WINVISTA:
- case DCE2_POLICY__WIN2008:
- case DCE2_POLICY__WIN7:
- /* Windows will not accept an alter context before
- * bind and will bind_nak it */
- if (DCE2_ListIsEmpty(cot->ctx_ids))
- return;
-
- if (cot->data_byte_order != (int)DceRpcCoByteOrder(co_hdr))
- {
- /* This is anomalous behavior. Alert, but continue processing */
- if (cot->data_byte_order != DCE2_SENTINEL)
- dce_alert(GID_DCE2, DCE2_CO_ALTER_CHANGE_BYTE_ORDER,dce_common_stats);
- }
-
- break;
-
- case DCE2_POLICY__SAMBA:
- case DCE2_POLICY__SAMBA_3_0_37:
- case DCE2_POLICY__SAMBA_3_0_22:
- case DCE2_POLICY__SAMBA_3_0_20:
- /* Nothing for Samba */
- break;
-
- default:
- LogMessage("%s(%d) Invalid policy: %d\n",
- __FILE__, __LINE__, policy);
- break;
- }
-
- /* Alter context is typedef'ed as a bind */
- DCE2_CoCtxReq(sd, cot, co_hdr, DceRpcCoNumCtxItems((DceRpcCoBind*)alt_ctx), frag_ptr,
- frag_len);
-}
-
-static int DCE2_CoGetAuthLen(DCE2_SsnData* sd, const DceRpcCoHdr* co_hdr,
- const uint8_t* frag_ptr, uint16_t frag_len)
-{
- DceRpcCoAuthVerifier* auth_hdr;
- uint16_t auth_len = DceRpcCoAuthLen(co_hdr);
- dce2CommonStats* dce_common_stats = dce_get_proto_stats_ptr(sd);
-
- if (auth_len == 0)
- return 0;
-
- auth_len += sizeof(DceRpcCoAuthVerifier);
-
- /* This means the auth len was bogus */
- if (auth_len > frag_len)
- {
- dce_alert(GID_DCE2, DCE2_CO_REM_FRAG_LEN_LT_SIZE,dce_common_stats);
- return -1;
- }
-
- auth_hdr = (DceRpcCoAuthVerifier*)(frag_ptr + (frag_len - auth_len));
- if (DceRpcCoAuthLevel(auth_hdr) == DCERPC_CO_AUTH_LEVEL__PKT_PRIVACY)
- {
- /* Data is encrypted - don't inspect */
- return -1;
- }
-
- auth_len += DceRpcCoAuthPad(auth_hdr);
-
- /* This means the auth pad len was bogus */
- if (auth_len > frag_len)
- {
- dce_alert(GID_DCE2, DCE2_CO_REM_FRAG_LEN_LT_SIZE,dce_common_stats);
- return -1;
- }
-
- return (int)auth_len;
-}
-
-/********************************************************************
- * Function: DCE2_CoRequest()
- *
- * Handles a DCE/RPC request from the client. This is were the
- * client actually asks the server to do stuff on it's behalf.
- * If it's a first/last fragment, set relevant rule option
- * data and return. If it's a true fragment, do some target
- * based futzing to set the right opnum and context id for
- * the to be reassembled packet.
- *
- *
- ********************************************************************/
-static void DCE2_CoRequest(DCE2_SsnData* sd, DCE2_CoTracker* cot,
- const DceRpcCoHdr* co_hdr, const uint8_t* frag_ptr, uint16_t frag_len)
-{
- DceRpcCoRequest* rhdr = (DceRpcCoRequest*)frag_ptr;
- uint16_t req_size = sizeof(DceRpcCoRequest);
- DCE2_Policy policy = DCE2_SsnGetServerPolicy(sd);
- dce2CommonStats* dce_common_stats = dce_get_proto_stats_ptr(sd);
-
- /* Account for possible object uuid */
- if (DceRpcCoObjectFlag(co_hdr))
- req_size += sizeof(Uuid);
-
- if (frag_len < req_size)
- {
- dce_alert(GID_DCE2, DCE2_CO_REM_FRAG_LEN_LT_SIZE,dce_common_stats);
- return;
- }
-
- switch (policy)
- {
- /* After 3.0.37 up to 3.5.2 byte order of stub data is always
- * interpreted as little endian */
- case DCE2_POLICY__SAMBA:
- cot->data_byte_order = DCERPC_BO_FLAG__LITTLE_ENDIAN;
- break;
-
- case DCE2_POLICY__SAMBA_3_0_37:
- case DCE2_POLICY__SAMBA_3_0_22:
- case DCE2_POLICY__SAMBA_3_0_20:
- cot->data_byte_order = DceRpcCoByteOrder(co_hdr);
- break;
-
- default:
- break;
- }
-
- /* Move past header */
- DCE2_MOVE(frag_ptr, frag_len, req_size);
-
- //FIXIT-M frag stuff
-
- cot->stub_data = frag_ptr;
- cot->opnum = DceRpcCoOpnum(co_hdr, rhdr);
- cot->ctx_id = DceRpcCoCtxId(co_hdr, rhdr);
- cot->call_id = DceRpcCoCallId(co_hdr);
-
- if (DceRpcCoFirstFrag(co_hdr) && DceRpcCoLastFrag(co_hdr))
- {
- int auth_len = DCE2_CoGetAuthLen(sd, co_hdr, frag_ptr, frag_len);
- DebugMessage(DEBUG_DCE_COMMON, "First and last fragment.\n");
- if (auth_len == -1)
- return;
- DCE2_CoSetRopts(sd, cot, co_hdr);
- }
- else
- {
- //FIXIT-M frag stuff
- }
-}
-
-/********************************************************************
- * Function: DCE2_CoResponse()
- *
- * Handles a DCE/RPC response from the server.
- * Samba responds to SMB bind write, request write before read with
- * a response to the request and doesn't send a bind ack. Get the
- * context id from the pending context id list and put in stable
- * list.
- *
-
- ********************************************************************/
-static void DCE2_CoResponse(DCE2_SsnData* sd, DCE2_CoTracker* cot,
- const DceRpcCoHdr* co_hdr, const uint8_t* frag_ptr, uint16_t frag_len)
-{
- DceRpcCoResponse* rhdr = (DceRpcCoResponse*)frag_ptr;
- uint16_t ctx_id;
- DCE2_Policy policy = DCE2_SsnGetServerPolicy(sd);
- dce2CommonStats* dce_common_stats = dce_get_proto_stats_ptr(sd);
-
- if (frag_len < sizeof(DceRpcCoResponse))
- {
- dce_alert(GID_DCE2, DCE2_CO_REM_FRAG_LEN_LT_SIZE,dce_common_stats);
-
- return;
- }
-
- switch (policy)
- {
- case DCE2_POLICY__SAMBA:
- cot->data_byte_order = DCERPC_BO_FLAG__LITTLE_ENDIAN;
- break;
-
- case DCE2_POLICY__SAMBA_3_0_37:
- case DCE2_POLICY__SAMBA_3_0_22:
- case DCE2_POLICY__SAMBA_3_0_20:
- cot->data_byte_order = DceRpcCoByteOrder(co_hdr);
- break;
-
- default:
- break;
- }
-
- ctx_id = DceRpcCoCtxIdResp(co_hdr, rhdr);
-
- /* If pending queue is not empty, add this context id as accepted and all
- * others as pending */
- while (!DCE2_QueueIsEmpty(cot->pending_ctx_ids))
- {
- DCE2_Ret status;
- DCE2_CoCtxIdNode* ctx_node = (DCE2_CoCtxIdNode*)DCE2_QueueDequeue(cot->pending_ctx_ids);
-
- if (ctx_node == nullptr)
- {
- LogMessage("%s(%d) Failed to dequeue a context id node.\n",
- __FILE__, __LINE__);
- return;
- }
-
- if (ctx_node->ctx_id == ctx_id)
- ctx_node->state = DCE2_CO_CTX_STATE__ACCEPTED;
-
- status = DCE2_ListInsert(cot->ctx_ids, (void*)(uintptr_t)ctx_node->ctx_id,
- (void*)ctx_node);
- if (status != DCE2_RET__SUCCESS)
- {
- /* Might be a duplicate in there already. If there is we would have used it
- * anyway before looking at the pending queue. Just get rid of it */
- free((void*)ctx_node);
- return;
- }
- }
-
- /* Move past header */
- DCE2_MOVE(frag_ptr, frag_len, sizeof(DceRpcCoResponse));
-
- //FIXIT-M frag stuff
-
- cot->stub_data = frag_ptr;
- /* Opnum not in response header - have to use previous client's */
- cot->ctx_id = ctx_id;
- cot->call_id = DceRpcCoCallId(co_hdr);
-
- if (DceRpcCoFirstFrag(co_hdr) && DceRpcCoLastFrag(co_hdr))
- {
- int auth_len = DCE2_CoGetAuthLen(sd, co_hdr, frag_ptr, frag_len);
- DebugMessage(DEBUG_DCE_COMMON, "First and last fragment.\n");
- if (auth_len == -1)
- return;
- DCE2_CoSetRopts(sd, cot, co_hdr);
- }
- else
- {
- /* FIXIT-M frag stuff */
- }
-}
-
-/********************************************************************
- * Function: DCE2_CoDecode()
- *
- * Main processing for the DCE/RPC pdu types. Most are not
- * implemented as, currently, they are not necessary and only
- * stats are kept for them. Important are the bind, alter context
- * and request.
- *
- ********************************************************************/
-static void DCE2_CoDecode(DCE2_SsnData* sd, DCE2_CoTracker* cot,
- const uint8_t* frag_ptr, uint16_t frag_len)
-{
- /* Already checked that we have enough data for header */
- const DceRpcCoHdr* co_hdr = (DceRpcCoHdr*)frag_ptr;
- int pdu_type = DceRpcCoPduType(co_hdr);
- dce2CommonStats* dce_common_stats = dce_get_proto_stats_ptr(sd);
-
- /* We've got the main header. Move past it to the
- * start of the pdu */
- DCE2_MOVE(frag_ptr, frag_len, sizeof(DceRpcCoHdr));
-
- DebugMessage(DEBUG_DCE_COMMON, "PDU type: ");
-
- /* Client specific pdu types - some overlap with server */
- if (DCE2_SsnFromClient(sd->wire_pkt))
- {
- switch (pdu_type)
- {
- case DCERPC_PDU_TYPE__BIND:
- DebugMessage(DEBUG_DCE_COMMON, "Bind\n");
- dce_common_stats->co_bind++;
-
- /* Make sure context id list and queue are initialized */
- if (DCE2_CoInitCtxStorage(cot) != DCE2_RET__SUCCESS)
- return;
-
- DCE2_CoBind(sd, cot, co_hdr, frag_ptr, frag_len);
-
- break;
-
- case DCERPC_PDU_TYPE__ALTER_CONTEXT:
- DebugMessage(DEBUG_DCE_COMMON, "Alter Context\n");
- dce_common_stats->co_alter_ctx++;
-
- if (DCE2_CoInitCtxStorage(cot) != DCE2_RET__SUCCESS)
- return;
-
- DCE2_CoAlterCtx(sd, cot, co_hdr, frag_ptr, frag_len);
-
- break;
-
- case DCERPC_PDU_TYPE__REQUEST:
- DebugMessage(DEBUG_DCE_COMMON, "Request\n");
- dce_common_stats->co_request++;
-
- if (DCE2_ListIsEmpty(cot->ctx_ids) &&
- DCE2_QueueIsEmpty(cot->pending_ctx_ids))
- {
- return;
- }
-
- DCE2_CoRequest(sd, cot, co_hdr, frag_ptr, frag_len);
-
- break;
-
- case DCERPC_PDU_TYPE__AUTH3:
- DebugMessage(DEBUG_DCE_COMMON, "Auth3\n");
- dce_common_stats->co_auth3++;
- break;
-
- case DCERPC_PDU_TYPE__CO_CANCEL:
- DebugMessage(DEBUG_DCE_COMMON, "Cancel\n");
- dce_common_stats->co_cancel++;
- break;
-
- case DCERPC_PDU_TYPE__ORPHANED:
- DebugMessage(DEBUG_DCE_COMMON, "Orphaned\n");
- dce_common_stats->co_orphaned++;
- break;
-
- case DCERPC_PDU_TYPE__MICROSOFT_PROPRIETARY_OUTLOOK2003_RPC_OVER_HTTP:
- DebugMessage(DEBUG_DCE_COMMON, "Microsoft Request To Send RPC over HTTP\n");
- dce_common_stats->co_ms_pdu++;
- break;
-
- default:
- DebugFormat(DEBUG_DCE_COMMON, "Unknown (0x%02x)\n", pdu_type);
- dce_common_stats->co_other_req++;
- break;
- }
- }
- else
- {
- switch (pdu_type)
- {
- case DCERPC_PDU_TYPE__BIND_ACK:
- case DCERPC_PDU_TYPE__ALTER_CONTEXT_RESP:
- if (pdu_type == DCERPC_PDU_TYPE__BIND_ACK)
- {
- DebugMessage(DEBUG_DCE_COMMON, "Bind Ack\n");
- dce_common_stats->co_bind_ack++;
- }
- else
- {
- DebugMessage(DEBUG_DCE_COMMON, "Alter Context Response\n");
- dce_common_stats->co_alter_ctx_resp++;
- }
-
- if (DCE2_QueueIsEmpty(cot->pending_ctx_ids))
- return;
-
- /* Bind ack and alter context response have the same
- * header structure, just different pdu type */
- DCE2_CoBindAck(sd, cot, co_hdr, frag_ptr, frag_len);
-
- /* Got the bind/alter response - clear out the pending queue */
- DCE2_QueueEmpty(cot->pending_ctx_ids);
-
- break;
-
- case DCERPC_PDU_TYPE__BIND_NACK:
- DebugMessage(DEBUG_DCE_COMMON, "Bind Nack\n");
- dce_common_stats->co_bind_nack++;
-
- /* Bind nack in Windows seems to blow any previous context away */
- switch (DCE2_SsnGetServerPolicy(sd))
- {
- case DCE2_POLICY__WIN2000:
- case DCE2_POLICY__WIN2003:
- case DCE2_POLICY__WINXP:
- case DCE2_POLICY__WINVISTA:
- case DCE2_POLICY__WIN2008:
- case DCE2_POLICY__WIN7:
- DCE2_CoEraseCtxIds(cot);
- break;
-
- default:
- break;
- }
-
- cot->got_bind = 0;
-
- break;
-
- case DCERPC_PDU_TYPE__RESPONSE:
- DebugMessage(DEBUG_DCE_COMMON, "Response\n");
- dce_common_stats->co_response++;
- DCE2_CoResponse(sd, cot, co_hdr, frag_ptr, frag_len);
- break;
-
- case DCERPC_PDU_TYPE__FAULT:
- DebugMessage(DEBUG_DCE_COMMON, "Fault\n");
- dce_common_stats->co_fault++;
-
- /* Clear out the client side */
- DCE2_QueueEmpty(cot->pending_ctx_ids);
- DCE2_BufferEmpty(cot->cli_seg.buf);
- DCE2_BufferEmpty(cot->frag_tracker.cli_stub_buf);
-
- DCE2_CoResetTracker(cot);
-
- break;
-
- case DCERPC_PDU_TYPE__SHUTDOWN:
- DebugMessage(DEBUG_DCE_COMMON, "Shutdown\n");
- dce_common_stats->co_shutdown++;
- break;
-
- case DCERPC_PDU_TYPE__REJECT:
- DebugMessage(DEBUG_DCE_COMMON, "Reject\n");
- dce_common_stats->co_reject++;
-
- DCE2_QueueEmpty(cot->pending_ctx_ids);
-
- break;
-
- case DCERPC_PDU_TYPE__MICROSOFT_PROPRIETARY_OUTLOOK2003_RPC_OVER_HTTP:
- DebugMessage(DEBUG_DCE_COMMON, "Microsoft Request To Send RPC over HTTP\n");
- dce_common_stats->co_ms_pdu++;
- break;
-
- default:
- DebugFormat(DEBUG_DCE_COMMON, "Unknown (0x%02x)\n", pdu_type);
- dce_common_stats->co_other_resp++;
- break;
- }
- }
-}
-
-/********************************************************************
- * Function: DCE2_CoProcess()
- *
- * Main entry point for connection-oriented DCE/RPC processing.
- * Since there can be more than one DCE/RPC pdu in the packet, it
- * loops through the packet data until none is left. It handles
- * transport layer segmentation and buffers data until it gets the
- * full pdu, then hands off to pdu processing.
- *
- *
- ********************************************************************/
-void DCE2_CoProcess(DCE2_SsnData* sd, DCE2_CoTracker* cot,
- const uint8_t* data_ptr, uint16_t data_len)
-{
- DCE2_CoSeg* seg = DCE2_CoGetSegPtr(sd, cot);
- uint32_t num_frags = 0;
- dce2CommonStats* dce_common_stats = dce_get_proto_stats_ptr(sd);
-
- dce_common_stats->co_pdus++;
-
- co_reassembled = 0;
-
- while (data_len > 0)
- {
- num_frags++;
-
- DebugFormat(DEBUG_DCE_COMMON, "DCE/RPC message number: %u\n", num_frags);
-
- /* Fast track full fragments */
- if (DCE2_BufferIsEmpty(seg->buf))
- {
- const uint8_t* frag_ptr = data_ptr;
- uint16_t frag_len;
-
- /* Not enough data left for a header. Buffer it and return */
- if (data_len < sizeof(DceRpcCoHdr))
- {
- // FIXIT-M add logic for this case
- break;
- }
-
- if (DCE2_CoHdrChecks(sd, cot, (DceRpcCoHdr*)data_ptr) != DCE2_RET__SUCCESS)
- return;
-
- frag_len = DceRpcCoFragLen((DceRpcCoHdr*)data_ptr);
-
- /* Not enough data left for the pdu. */
- if (data_len < frag_len)
- {
- // FIXIT-M add logic for this case
- break;
- }
-
- DCE2_MOVE(data_ptr, data_len, frag_len);
-
- /* Got a full DCE/RPC pdu */
- DCE2_CoDecode(sd, cot, frag_ptr, frag_len);
-
- /* If we're configured to do defragmentation only detect on first frag
- * since we'll detect on reassembled */
- if (!DCE2_GcDceDefrag((dce2CommonProtoConf*)sd->config) ||
- ((num_frags == 1) && !co_reassembled))
- DCE2_Detect(sd);
-
- /* Reset if this is a last frag */
- if (DceRpcCoLastFrag((DceRpcCoHdr*)frag_ptr))
- num_frags = 0;
- }
- else /* We've already buffered data */
- {
- // FIXIT-M add logic for this case
- }
- }
-
- // FIXIT-M add reassemble logic
-}
-
#include "dce_common.h"
#include "dce_list.h"
-#include "dce_utils.h"
#define DCE2_CO_BAD_MAJOR_VERSION 27
#define DCE2_CO_BAD_MINOR_VERSION 28
"Connection-oriented DCE/RPC - Context id of non first/last fragment different \
from context id established for fragmented request."
-#define DCE2_MAX_XMIT_SIZE_FUZZ 500
-
#pragma pack(1)
struct DceRpcCoVersion
uint32_t call_id;
};
-/* Bind */
-struct DceRpcCoBind
-{
- uint16_t max_xmit_frag;
- uint16_t max_recv_frag;
- uint32_t assoc_group_id;
- uint8_t n_context_elem; /* number of context elements */
- uint8_t reserved;
- uint16_t reserved2;
-};
-
-struct DceRpcCoSynId
-{
- Uuid if_uuid;
- uint32_t if_version;
-};
-
-struct DceRpcCoContElem
-{
- uint16_t p_cont_id;
- uint8_t n_transfer_syn; /* number of transfer syntaxes */
- uint8_t reserved;
- DceRpcCoSynId abstract_syntax;
-};
-
-struct DceRpcCoBindAck
-{
- uint16_t max_xmit_frag;
- uint16_t max_recv_frag;
- uint32_t assoc_group_id;
- uint16_t sec_addr_len;
-};
-
-struct DceRpcCoContResult
-{
- uint16_t result;
- uint16_t reason;
- DceRpcCoSynId transfer_syntax;
-};
-
-struct DceRpcCoAuthVerifier
-{
- uint8_t auth_type;
- uint8_t auth_level;
- uint8_t auth_pad_length;
- uint8_t auth_reserved;
- uint32_t auth_context_id;
-};
-
-struct DceRpcCoRequest
-{
- uint32_t alloc_hint;
- uint16_t context_id;
- uint16_t opnum;
-};
-
-struct DceRpcCoResponse
-{
- uint32_t alloc_hint;
- uint16_t context_id;
- uint8_t cancel_count;
- uint8_t reserved;
-};
-
-struct DceRpcCoContResultList
-{
- uint8_t n_results;
- uint8_t reserved;
- uint16_t reserved2;
-};
-
-typedef DceRpcCoBind DceRpcCoAltCtx;
-typedef DceRpcCoBindAck DceRpcCoAltCtxResp;
-
#pragma pack()
struct DCE2_CoFragTracker
DCE2_CoSeg srv_seg;
};
-/*
- * Connection oriented
- */
-enum DceRpcCoPfcFlags
-{
- DCERPC_CO_PFC_FLAGS__FIRST_FRAG = 0x01,
- DCERPC_CO_PFC_FLAGS__LAST_FRAG = 0x02,
- DCERPC_CO_PFC_FLAGS__PENDING_CANCEL = 0x04,
- DCERPC_CO_PFC_FLAGS__RESERVED_1 = 0x08,
- DCERPC_CO_PFC_FLAGS__CONC_MPX = 0x10,
- DCERPC_CO_PFC_FLAGS__DID_NOT_EXECUTE = 0x20,
- DCERPC_CO_PFC_FLAGS__MAYBE = 0x40,
- DCERPC_CO_PFC_FLAGS__OBJECT_UUID = 0x80
-};
-
-enum DCE2_CoCtxState
-{
- DCE2_CO_CTX_STATE__ACCEPTED,
- DCE2_CO_CTX_STATE__REJECTED,
- DCE2_CO_CTX_STATE__PENDING
-};
-
-struct DCE2_CoCtxIdNode
-{
- uint16_t ctx_id; /* The context id */
- Uuid iface; /* The presentation syntax uuid for the interface */
- uint16_t iface_vers_maj; /* The major version of the interface */
- uint16_t iface_vers_min; /* The minor version of the interface */
-
- /* Whether or not the server accepted or rejected the client bind/alter context
- * request. Initially set to pending until server response */
- DCE2_CoCtxState state;
-};
-
-enum DceRpcCoAuthLevelType
-{
- DCERPC_CO_AUTH_LEVEL__NONE = 1,
- DCERPC_CO_AUTH_LEVEL__CONNECT,
- DCERPC_CO_AUTH_LEVEL__CALL,
- DCERPC_CO_AUTH_LEVEL__PKT,
- DCERPC_CO_AUTH_LEVEL__PKT_INTEGRITY,
- DCERPC_CO_AUTH_LEVEL__PKT_PRIVACY
-};
-
-enum DceRpcCoContDefResult
-{
- DCERPC_CO_CONT_DEF_RESULT__ACCEPTANCE = 0,
- DCERPC_CO_CONT_DEF_RESULT__USER_REJECTION,
- DCERPC_CO_CONT_DEF_RESULT__PROVIDER_REJECTION
-};
inline uint8_t DceRpcCoVersMaj(const DceRpcCoHdr* co)
{
return co->pversion.major;
return DceRpcNtohs(&co->frag_length, DceRpcCoByteOrder(co));
}
-inline uint8_t DceRpcCoNumCtxItems(const DceRpcCoBind* cob)
-{
- return cob->n_context_elem;
-}
-
-inline uint16_t DceRpcCoContElemCtxId(const DceRpcCoHdr* co, const DceRpcCoContElem* coce)
-{
- return DceRpcNtohs(&coce->p_cont_id, DceRpcCoByteOrder(co));
-}
-
-inline uint8_t DceRpcCoContElemNumTransSyntaxes(const DceRpcCoContElem* coce)
-{
- return coce->n_transfer_syn;
-}
-
-inline const Uuid* DceRpcCoContElemIface(const DceRpcCoContElem* coce)
-{
- return &coce->abstract_syntax.if_uuid;
-}
-
-inline uint16_t DceRpcCoContElemIfaceVersMaj(const DceRpcCoHdr* co, const DceRpcCoContElem* coce)
-{
- return (uint16_t)(DceRpcNtohl(&coce->abstract_syntax.if_version, DceRpcCoByteOrder(co)) &
- 0x0000ffff);
-}
-
-inline uint16_t DceRpcCoContElemIfaceVersMin(const DceRpcCoHdr* co, const DceRpcCoContElem* coce)
-{
- return (uint16_t)(DceRpcNtohl(&coce->abstract_syntax.if_version, DceRpcCoByteOrder(co)) >> 16);
-}
-
-inline uint16_t DceRpcCoBindAckMaxRecvFrag(const DceRpcCoHdr* co, const DceRpcCoBindAck* coba)
-{
- return DceRpcNtohs(&coba->max_recv_frag, DceRpcCoByteOrder(co));
-}
-
-inline uint16_t DceRpcCoSecAddrLen(const DceRpcCoHdr* co, const DceRpcCoBindAck* coba)
-{
- return DceRpcNtohs(&coba->sec_addr_len, DceRpcCoByteOrder(co));
-}
-
-inline uint16_t DceRpcCoContRes(const DceRpcCoHdr* co, const DceRpcCoContResult* cocr)
-{
- return DceRpcNtohs(&cocr->result, DceRpcCoByteOrder(co));
-}
-
-inline int DceRpcCoObjectFlag(const DceRpcCoHdr* co)
-{
- return co->pfc_flags & DCERPC_CO_PFC_FLAGS__OBJECT_UUID;
-}
-
-inline int DceRpcCoFirstFrag(const DceRpcCoHdr* co)
-{
- return co->pfc_flags & DCERPC_CO_PFC_FLAGS__FIRST_FRAG;
-}
-
-inline int DceRpcCoLastFrag(const DceRpcCoHdr* co)
-{
- return co->pfc_flags & DCERPC_CO_PFC_FLAGS__LAST_FRAG;
-}
-
-inline uint16_t DceRpcCoAuthLen(const DceRpcCoHdr* co)
-{
- return DceRpcNtohs(&co->auth_length, DceRpcCoByteOrder(co));
-}
-
-inline uint8_t DceRpcCoAuthLevel(const DceRpcCoAuthVerifier* coav)
-{
- return coav->auth_level;
-}
-
-inline uint16_t DceRpcCoAuthPad(const DceRpcCoAuthVerifier* coav)
-{
- return coav->auth_pad_length;
-}
-
-inline uint16_t DceRpcCoCtxIdResp(const DceRpcCoHdr* co, const DceRpcCoResponse* cor)
-{
- return DceRpcNtohs(&cor->context_id, DceRpcCoByteOrder(co));
-}
-
-inline uint16_t DceRpcCoBindMaxXmitFrag(const DceRpcCoHdr* co, const DceRpcCoBind* cob)
-{
- return DceRpcNtohs(&cob->max_xmit_frag, DceRpcCoByteOrder(co));
-}
-
-inline uint8_t DceRpcCoContNumResults(const DceRpcCoContResultList* cocrl)
-{
- return cocrl->n_results;
-}
-
-inline uint32_t DceRpcCoCallId(const DceRpcCoHdr* co)
-{
- return DceRpcNtohl(&co->call_id, DceRpcCoByteOrder(co));
-}
-
-inline uint16_t DceRpcCoOpnum(const DceRpcCoHdr* co, const DceRpcCoRequest* cor)
-{
- return DceRpcNtohs(&cor->opnum, DceRpcCoByteOrder(co));
-}
-
-inline uint16_t DceRpcCoCtxId(const DceRpcCoHdr* co, const DceRpcCoRequest* cor)
-{
- return DceRpcNtohs(&cor->context_id, DceRpcCoByteOrder(co));
-}
-
void DCE2_CoInitTracker(DCE2_CoTracker*);
-void DCE2_CoProcess(DCE2_SsnData*, DCE2_CoTracker*,
- const uint8_t*, uint16_t);
#endif
// dce_common.cc author Rashmi Pitre <rrp@cisco.com>
#include "dce_common.h"
-#include "dce_tcp.h"
-#include "dce_smb.h"
#include "framework/base_api.h"
#include "framework/module.h"
#include "flow/flow.h"
#include "log/messages.h"
#include "main/snort_debug.h"
-#include "detection/detect.h"
-
-THREAD_LOCAL int dce2_detected = 0;
const char* dce2_get_policy_name(DCE2_Policy policy)
{
return true;
}
- if ((sd != nullptr) && DCE2_SsnNoInspect(sd))
+ if ((sd != NULL) && DCE2_SsnNoInspect(sd))
{
DebugMessage(DEBUG_DCE_COMMON, "Aborting PAF because of session data check.\n");
return true;
return false;
}
-void DCE2_PrintRoptions(DCE2_Roptions* ropts)
-{
- DebugFormat(DEBUG_DCE_COMMON,
- " First frag: %s\n", ropts->first_frag == 1 ? "yes" : (ropts->first_frag == 0 ? "no" :
- "unset"));
- if (ropts->first_frag == DCE2_SENTINEL)
- {
- DebugMessage(DEBUG_DCE_COMMON, " Iface: unset\n");
- DebugMessage(DEBUG_DCE_COMMON, " Iface version: unset\n");
- }
- else
- {
- DebugFormat(DEBUG_DCE_COMMON, " Iface: %s\n", DCE2_UuidToStr(&ropts->iface,
- DCERPC_BO_FLAG__NONE));
- DebugFormat(DEBUG_DCE_COMMON, " Iface version: %u\n", ropts->iface_vers_maj);
- }
- if (ropts->opnum == DCE2_SENTINEL)
- DebugMessage(DEBUG_DCE_COMMON, " Opnum: unset\n");
- else
- DebugFormat(DEBUG_DCE_COMMON, " Opnum: %u\n", ropts->opnum);
- DebugFormat(DEBUG_DCE_COMMON, " Header byte order: %s\n",
- ropts->hdr_byte_order == DCERPC_BO_FLAG__LITTLE_ENDIAN ? "little endian" :
- (ropts->hdr_byte_order == DCERPC_BO_FLAG__BIG_ENDIAN ? "big endian" : "unset"));
- DebugFormat(DEBUG_DCE_COMMON, " Data byte order: %s\n",
- ropts->data_byte_order == DCERPC_BO_FLAG__LITTLE_ENDIAN ? "little endian" :
- (ropts->data_byte_order == DCERPC_BO_FLAG__BIG_ENDIAN ? "big endian" : "unset"));
- if (ropts->stub_data != nullptr)
- DebugFormat(DEBUG_DCE_COMMON, " Stub data: %p\n", ropts->stub_data);
- else
- DebugMessage(DEBUG_DCE_COMMON, " Stub data: NULL\n");
-}
-
-static void dce2_protocol_detect(DCE2_SsnData* sd, Packet* pkt)
-{
- if (sd->trans == DCE2_TRANS_TYPE__TCP)
- {
- Profile profile(dce2_tcp_pstat_detect);
- }
- else
- {
- Profile profile(dce2_smb_pstat_detect);
- }
- SnortEventqPush();
- snort_detect(pkt);
- SnortEventqPop();
-
- dce2_detected = 1;
-}
-
-void DCE2_Detect(DCE2_SsnData* sd)
-{
- Packet* top_pkt = sd->wire_pkt;
- //FIXIT-M Get packet from stack
-
- DebugMessage(DEBUG_DCE_COMMON, "Detecting ------------------------------------------------\n");
- DebugMessage(DEBUG_DCE_COMMON, " Rule options:\n");
- DCE2_PrintRoptions(&sd->ropts);
- DebugMessage(DEBUG_DCE_COMMON, "Payload:\n");
- DCE2_PrintPktData(top_pkt->data, top_pkt->dsize);
- if (sd->ropts.stub_data != nullptr)
- {
- DebugMessage(DEBUG_DCE_COMMON,"\nStub data:\n");
- DCE2_PrintPktData(sd->ropts.stub_data,
- top_pkt->dsize - (sd->ropts.stub_data - top_pkt->data));
- }
-
- dce2_protocol_detect(sd, top_pkt);
- /* Always reset rule option data after detecting */
- DCE2_ResetRopts(&sd->ropts);
- DebugMessage(DEBUG_DCE_COMMON, "----------------------------------------------------------\n");
-}
-
#ifdef BUILDING_SO
extern const BaseApi* ips_dce_iface;
#include "framework/module.h"
#include "framework/inspector.h"
#include "protocols/packet.h"
-#include "events/event_queue.h"
extern const InspectApi dce2_smb_api;
extern const InspectApi dce2_tcp_api;
-extern THREAD_LOCAL int dce2_detected;
#define GID_DCE2 145
DCE2_POLICY__SAMBA_3_0_20,
};
-struct dce2CommonStats
-{
- PegCount events;
- PegCount sessions_aborted;
- PegCount bad_autodetects;
-
- PegCount co_pdus;
- PegCount co_bind;
- PegCount co_bind_ack;
- PegCount co_alter_ctx;
- PegCount co_alter_ctx_resp;
- PegCount co_bind_nack;
- PegCount co_request;
- PegCount co_response;
- PegCount co_cancel;
- PegCount co_orphaned;
- PegCount co_fault;
- PegCount co_auth3;
- PegCount co_shutdown;
- PegCount co_reject;
- PegCount co_ms_pdu;
- PegCount co_other_req;
- PegCount co_other_resp;
- PegCount co_req_fragments;
- PegCount co_resp_fragments;
- PegCount co_cli_max_frag_size;
- PegCount co_cli_min_frag_size;
- PegCount co_cli_seg_reassembled;
- PegCount co_cli_frag_reassembled;
- PegCount co_srv_max_frag_size;
- PegCount co_srv_min_frag_size;
- PegCount co_srv_seg_reassembled;
- PegCount co_srv_frag_reassembled;
-};
#define DCE2_SARG__POLICY_WIN2000 "Win2000"
#define DCE2_SARG__POLICY_WINXP "WinXP"
#define DCE2_SARG__POLICY_WINVISTA "WinVista"
#define DCE2_DEBUG__PAF_END_MSG "=========================================================="
+/* DCE/RPC byte order flag */
+enum DceRpcBoFlag
+{
+ DCERPC_BO_FLAG__NONE,
+ DCERPC_BO_FLAG__BIG_ENDIAN,
+ DCERPC_BO_FLAG__LITTLE_ENDIAN
+};
+
enum DceRpcPduType
{
DCERPC_PDU_TYPE__REQUEST = 0,
DCE2_Policy server_policy;
DCE2_Policy client_policy;
int flags;
- Packet* wire_pkt;
+ const Packet* wire_pkt;
uint64_t alert_mask;
DCE2_Roptions ropts;
int autodetect_dir;
- void* config;
uint32_t cli_seq;
uint32_t cli_nseq;
uint32_t srv_nseq;
};
+inline DceRpcBoFlag DceRpcByteOrder(const uint8_t value)
+{
+ if ((value & 0x10) >> 4)
+ return DCERPC_BO_FLAG__LITTLE_ENDIAN;
+
+ return DCERPC_BO_FLAG__BIG_ENDIAN;
+}
+
+inline uint16_t DceRpcNtohs(const uint16_t* ptr, const DceRpcBoFlag bo_flag)
+{
+ uint16_t value;
+
+ if (ptr == NULL)
+ return 0;
+
+#ifdef WORDS_MUSTALIGN
+ value = *((uint8_t*)ptr) << 8 | *((uint8_t*)ptr + 1);
+#else
+ value = *ptr;
+#endif /* WORDS_MUSTALIGN */
+
+ if (bo_flag == DCERPC_BO_FLAG__NONE)
+ return value;
+
+#ifdef WORDS_BIGENDIAN
+ if (bo_flag == DCERPC_BO_FLAG__BIG_ENDIAN)
+#else
+ if (bo_flag == DCERPC_BO_FLAG__LITTLE_ENDIAN)
+#endif /* WORDS_BIGENDIAN */
+ return value;
+
+ return ((value & 0xff00) >> 8) | ((value & 0x00ff) << 8);
+}
+
inline void DCE2_ResetRopts(DCE2_Roptions* ropts)
{
ropts->first_frag = DCE2_SENTINEL;
ropts->opnum = DCE2_SENTINEL;
ropts->hdr_byte_order = DCE2_SENTINEL;
ropts->data_byte_order = DCE2_SENTINEL;
- ropts->stub_data = nullptr;
+ ropts->stub_data = NULL;
}
inline void DCE2_SsnSetAutodetected(DCE2_SsnData* sd, Packet* p)
return sd->flags & DCE2_SSN_FLAG__NO_INSPECT;
}
-inline bool DCE2_GcDceDefrag(dce2CommonProtoConf* config)
-{
- return config->disable_defrag;
-}
-
-inline int DCE2_SsnFromServer(Packet* p)
-{
- return p->from_server();
-}
-
-inline int DCE2_SsnFromClient(Packet* p)
-{
- return p->from_client();
-}
-
-inline DCE2_Policy DCE2_SsnGetServerPolicy(DCE2_SsnData* sd)
-{
- return sd->server_policy;
-}
-
-inline void dce_alert(uint32_t gid, uint32_t sid, dce2CommonStats* stats)
-{
- SnortEventqAdd(gid,sid);
- stats->events++;
-}
-
bool dce2_set_common_config(Value&, dce2CommonProtoConf&);
void print_dce2_common_config(dce2CommonProtoConf&);
bool dce2_paf_abort(Flow*, DCE2_SsnData*);
-void DCE2_Detect(DCE2_SsnData*);
#endif
return list;
}
-
/********************************************************************
* Function: DCE2_ListInsert()
*
return DCE2_RET__SUCCESS;
}
+
/********************************************************************
* Function: DCE2_ListFirst()
*
return nullptr;
}
+
/********************************************************************
* Function: DCE2_ListEmpty()
*
list->num_nodes++;
}
}
-
-/********************************************************************
- * Function: DCE2_ListFind()
- *
- * Trys to find a node in the list using key passed in. If list
- * is splayed, found node is moved to front of list. The data
- * associated with the node is returned.
- *
- * Arguments:
- * DCE2_List *
- * A pointer to the list object.
- * void *
- * Pointer to a key.
- *
- * Returns:
- * void *
- * If the key is found, the data associated with the node
- * is returned.
- * NULL is returned if the item cannot be found given the key.
- *
- ********************************************************************/
-void* DCE2_ListFind(DCE2_List* list, void* key)
-{
- DCE2_ListNode* n;
-
- if (list == nullptr)
- return nullptr;
-
- for (n = list->head; n != nullptr; n = n->next)
- {
- int comp = list->compare(key, n->key);
- if (comp == 0)
- {
- /* Found it, break out */
- break;
- }
- else if ((comp < 0) && (list->type == DCE2_LIST_TYPE__SORTED))
- {
- /* Don't look any more if the list is sorted */
- return nullptr;
- }
- }
-
- if (n != nullptr)
- {
- /* If list is splayed, move found node to front of list */
- if ((list->type == DCE2_LIST_TYPE__SPLAYED) &&
- (n != list->head))
- {
- n->prev->next = n->next;
-
- if (n->next != nullptr)
- n->next->prev = n->prev;
- else /* it's the tail */
- list->tail = n->prev;
-
- n->prev = nullptr;
- n->next = list->head;
- list->head->prev = n;
- list->head = n;
- }
-
- return n->data;
- }
-
- return nullptr;
-}
-
-/********************************************************************
- * Function: DCE2_QueueNew()
- *
- * Creates and initializes a new queue object.
- *
- * Arguments:
- * DCE2_QueueDataFree
- * An optional free function for the data inserted into
- * the queue. If NULL is passed in, the user will be
- * responsible for freeing data left in the queue.
- *
- * Returns:
- * DCE2_Queue *
- * Pointer to a new queue object.
- * NULL if unable to allocate memory for the object.
- *
- ********************************************************************/
-DCE2_Queue* DCE2_QueueNew(DCE2_QueueDataFree df)
-{
- DCE2_Queue* queue;
-
- queue = (DCE2_Queue*)SnortAlloc(sizeof(DCE2_Queue));
- if (queue == nullptr)
- return nullptr;
-
- queue->data_free = df;
-
- return queue;
-}
-
-/********************************************************************
- * Function: DCE2_QueueEnqueue()
- *
- * Inserts data into the queue.
- *
- * Arguments:
- * DCE2_Queue *
- * A pointer to the queue object.
- * void *
- * Pointer to the data to insert into the queue.
- *
- * Returns:
- * DCE2_Ret
- * DCE2_RET__ERROR if memory cannot be allocated for a new
- * queue node or the queue object passed in is NULL.
- * DCE2_RET__SUCCESS if the data is successfully added to
- * the queue.
- *
- ********************************************************************/
-DCE2_Ret DCE2_QueueEnqueue(DCE2_Queue* queue, void* data)
-{
- DCE2_QueueNode* n;
-
- if (queue == nullptr)
- return DCE2_RET__ERROR;
-
- n = (DCE2_QueueNode*)SnortAlloc(sizeof(DCE2_QueueNode));
- if (n == nullptr)
- return DCE2_RET__ERROR;
-
- n->data = data;
-
- if (queue->tail == nullptr)
- {
- queue->head = queue->tail = n;
- n->next = nullptr;
- }
- else
- {
- queue->tail->next = n;
- n->prev = queue->tail;
- queue->tail = n;
- }
-
- queue->num_nodes++;
-
- return DCE2_RET__SUCCESS;
-}
-
-/********************************************************************
- * Function: DCE2_QueueDequeue()
- *
- * Removes and returns the data in the first node in the queue.
- * Note that the user will have to free the data returned. The
- * data free function only applies to data that is in the queue
- * when it is emptied or destroyed.
- *
- * Arguments:
- * DCE2_Queue *
- * A pointer to the queue object.
- *
- * Returns:
- * void *
- * The data in the first node in the queue.
- * NULL if there are no items in the queue or the queue object
- * passed in is NULL.
- *
- ********************************************************************/
-void* DCE2_QueueDequeue(DCE2_Queue* queue)
-{
- DCE2_QueueNode* n;
-
- if (queue == nullptr)
- return nullptr;
-
- n = queue->head;
-
- if (n != nullptr)
- {
- void* data = n->data;
-
- if (queue->head == queue->tail)
- {
- queue->head = queue->tail = nullptr;
- }
- else
- {
- queue->head->next->prev = nullptr;
- queue->head = queue->head->next;
- }
-
- free((void*)n);
-
- queue->num_nodes--;
-
- return data;
- }
-
- return nullptr;
-}
-
-/********************************************************************
- * Function: DCE2_QueueEmpty()
- *
- * Removes all of the nodes in a queue. Does not delete the queue
- * object itself. Calls data free function for data if it is
- * not NULL.
- *
- * Arguments:
- * DCE2_Queue *
- * A pointer to the queue object.
- *
- * Returns: None
- *
- ********************************************************************/
-void DCE2_QueueEmpty(DCE2_Queue* queue)
-{
- DCE2_QueueNode* n;
-
- if (queue == nullptr)
- return;
-
- n = queue->head;
-
- while (n != nullptr)
- {
- DCE2_QueueNode* tmp = n->next;
-
- if (queue->data_free != nullptr)
- queue->data_free(n->data);
-
- free((void*)n);
- n = tmp;
- }
-
- queue->head = queue->tail = queue->current = nullptr;
- queue->num_nodes = 0;
-}
-
-/********************************************************************
- * Function: DCE2_QueueFirst()
- *
- * Returns a pointer to the data of the first node in the queue.
- * Sets a current pointer to the first node in the queue for
- * iterating over the queue.
- *
- * Arguments:
- * DCE2_Queue *
- * A pointer to the queue object.
- *
- * Returns:
- * void *
- * The data in the first node in the queue.
- * NULL if the queue object passed in is NULL, or there are
- * no items in the queue.
- *
- ********************************************************************/
-void* DCE2_QueueFirst(DCE2_Queue* queue)
-{
- if (queue == nullptr)
- return nullptr;
-
- queue->current = queue->head;
- queue->next = nullptr;
-
- if (queue->current != nullptr)
- return queue->current->data;
-
- return nullptr;
-}
-
-/********************************************************************
- * Function: DCE2_QueueNext()
- *
- * Increments the current pointer in the queue to the next node in
- * the queue and returns the data associated with it. This in
- * combination with DCE2_QueueFirst is useful in a for loop to
- * iterate over the items in a queue.
- *
- * Arguments:
- * DCE2_Queue *
- * A pointer to the queue object.
- *
- * Returns:
- * void *
- * The data in the next node in the queue.
- * NULL if the queue object passed in is NULL, or we are at
- * the end of the queue and there are no next nodes.
- *
- ********************************************************************/
-void* DCE2_QueueNext(DCE2_Queue* queue)
-{
- if (queue == nullptr)
- return nullptr;
-
- if (queue->next != nullptr)
- {
- queue->current = queue->next;
- queue->next = nullptr;
- return queue->current->data;
- }
- else if (queue->current != nullptr)
- {
- queue->current = queue->current->next;
- if (queue->current != nullptr)
- return queue->current->data;
- }
-
- return nullptr;
-}
-
inline bool DCE2_ListIsEmpty(DCE2_List*);
void DCE2_ListEmpty(DCE2_List*);
void DCE2_ListDestroy(DCE2_List*);
-void* DCE2_ListFind(DCE2_List*, void*);
-
-DCE2_Queue* DCE2_QueueNew(DCE2_QueueDataFree);
-DCE2_Ret DCE2_QueueEnqueue(DCE2_Queue*, void*);
-void* DCE2_QueueDequeue(DCE2_Queue*);
-static inline bool DCE2_QueueIsEmpty(DCE2_Queue*);
-void DCE2_QueueEmpty(DCE2_Queue*);
-void* DCE2_QueueFirst(DCE2_Queue*);
-void* DCE2_QueueNext(DCE2_Queue*);
/********************************************************************
* Function: DCE2_ListIsEmpty()
return false;
}
-/********************************************************************
- * Function: DCE2_QueueIsEmpty()
- *
- * Determines whether or not the queue has any items in it
- * currently.
- *
- ********************************************************************/
-inline bool DCE2_QueueIsEmpty(DCE2_Queue* queue)
-{
- if (queue == nullptr)
- return 1;
- if (queue->num_nodes == 0)
- return 1;
- return 0;
-}
-
#endif
return(&fd->dce2_smb_session);
}
-static DCE2_SmbSsnData* dce2_create_new_smb_session(Packet* p, dce2SmbProtoConf* config)
+static DCE2_SmbSsnData* dce2_create_new_smb_session(Packet* p, dce2SmbProtoConf config)
{
- DCE2_SmbSsnData* dce2_smb_sess = nullptr;
+ DCE2_SmbSsnData* dce2_smb_sess = NULL;
Profile profile(dce2_smb_pstat_new_session);
- //FIXIT-M Re-evaluate after infrastructure/binder support if autodetect here
- //is necessary
-
if (DCE2_SmbAutodetect(p))
{
DebugMessage(DEBUG_DCE_SMB, "DCE over SMB packet detected\n");
DebugFormat(DEBUG_DCE_SMB,"Created (%p)\n", (void*)dce2_smb_sess);
dce2_smb_sess->sd.trans = DCE2_TRANS_TYPE__SMB;
- dce2_smb_sess->sd.server_policy = config->common.policy;
+ dce2_smb_sess->sd.server_policy = config.common.policy;
dce2_smb_sess->sd.client_policy = DCE2_POLICY__WINXP;
dce2_smb_sess->sd.wire_pkt = p;
- dce2_smb_sess->sd.config = (void*)config;
DCE2_SsnSetAutodetected(&dce2_smb_sess->sd, p);
}
return dce2_smb_sess;
}
-DCE2_SmbSsnData* dce2_handle_smb_session(Packet* p, dce2SmbProtoConf* config)
+DCE2_SmbSsnData* dce2_handle_smb_session(Packet* p, dce2SmbProtoConf& config)
{
Profile profile(dce2_smb_pstat_session);
DCE2_SsnNoInspect(sd);
dce2_smb_stats.sessions_aborted++;
dce2_smb_stats.bad_autodetects++;
- return nullptr;
+ return NULL;
}
DCE2_SsnClearAutodetected(sd);
}
return;
}
- dce2_smb_sess = dce2_handle_smb_session(p, &config);
+ dce2_smb_sess = dce2_handle_smb_session(p, config);
if (!dce2_smb_sess)
{
return;
PegCount sessions_aborted;
PegCount bad_autodetects;
+ PegCount smb_sessions;
+ PegCount smb_pkts;
+
PegCount co_pdus;
PegCount co_bind;
PegCount co_bind_ack;
PegCount co_auth3;
PegCount co_shutdown;
PegCount co_reject;
- PegCount co_ms_pdu;
PegCount co_other_req;
PegCount co_other_resp;
PegCount co_req_fragments;
PegCount co_srv_seg_reassembled;
PegCount co_srv_frag_reassembled;
- PegCount smb_sessions;
- PegCount smb_pkts;
PegCount smb_ignored_bytes;
PegCount smb_cli_seg_reassembled;
PegCount smb_srv_seg_reassembled;
// For tracking requests / responses
DCE2_SmbRequestTracker rtracker;
- DCE2_Queue* rtrackers;
+ //DCE2_Queue *rtrackers;
uint16_t max_outstanding_requests;
uint16_t outstanding_requests;
{ "events", "total events" },
{ "aborted sessions", "total aborted sessions" },
{ "bad autodetects", "total bad autodetects" },
- { "PDUs", "total connection-oriented PDUs" },
- { "Binds", "total connection-oriented binds" },
- { "Bind acks", "total connection-oriented binds acks" },
- { "Alter contexts", "total connection-oriented alter contexts" },
- { "Alter context responses",
+ { "smb sessions", "total smb sessions" },
+ { "smb packets", "total smb packets" },
+ { "connection-oriented PDUs", "total connection-oriented PDUs" },
+ { "connection-oriented binds", "total connection-oriented binds" },
+ { "connection-oriented bind acks", "total connection-oriented binds acks" },
+ { "connection-oriented alter contexts", "total connection-oriented alter contexts" },
+ { "connection-oriented alter context responses",
"total connection-oriented alter context responses" },
- { "Bind naks", "total connection-oriented bind naks" },
- { "Requests", "total connection-oriented requests" },
- { "Responses", "total connection-oriented responses" },
- { "Cancels", "total connection-oriented cancels" },
- { "Orphaned", "total connection-oriented orphaned" },
- { "Faults", "total connection-oriented faults" },
- { "Auth3s", "total connection-oriented auth3s" },
- { "Shutdowns", "total connection-oriented shutdowns" },
- { "Rejects", "total connection-oriented rejects" },
- { "MS RPC/HTTP PDUs", "total connection-oriented MS requests to send RPC over HTTP" },
- { "Other requests", "total connection-oriented other requests" },
- { "Other responses", "total connection-oriented other responses" },
- { "Request fragments", "total connection-oriented request fragments" },
- { "Response fragments", "total connection-oriented response fragments" },
- { "Client max fragment size",
+ { "connection-oriented bind naks", "total connection-oriented bind naks" },
+ { "connection-oriented requests", "total connection-oriented requests" },
+ { "connection-oriented responses", "total connection-oriented responses" },
+ { "connection-oriented cancels", "total connection-oriented cancels" },
+ { "connection-oriented orphaned", "total connection-oriented orphaned" },
+ { "connection-oriented faults", "total connection-oriented faults" },
+ { "connection-oriented auth3s", "total connection-oriented auth3s" },
+ { "connection-oriented shutdowns", "total connection-oriented shutdowns" },
+ { "connection-oriented rejects", "total connection-oriented rejects" },
+ { "connection-oriented other requests", "total connection-oriented other requests" },
+ { "connection-oriented other responses", "total connection-oriented other responses" },
+ { "connection-oriented request fragments", "total connection-oriented request fragments" },
+ { "connection-oriented response fragments", "total connection-oriented response fragments" },
+ { "connection-oriented client maximum fragment size",
"connection-oriented client maximum fragment size" },
- { "Client min fragment size",
+ { "connection-oriented client minimum fragment size",
"connection-oriented client minimum fragment size" },
- { "Client segs reassembled",
+ { "connection-oriented client segments reassembled",
"total connection-oriented client segments reassembled" },
- { "Client frags reassembled",
+ { "connection-oriented client fragments reassembled",
"total connection-oriented client fragments reassembled" },
- { "Server max fragment size",
+ { "connection-oriented server maximum fragment size",
"connection-oriented server maximum fragment size" },
- { "Server min fragment size",
+ { "connection-oriented server minimum fragment size",
"connection-oriented server minimum fragment size" },
- { "Server segs reassembled",
+ { "connection-oriented server segments reassembled",
"total connection-oriented server segments reassembled" },
- { "Server frags reassembled",
+ { "connection-oriented server fragments reassembled",
"total connection-oriented server fragments reassembled" },
- { "Sessions", "total smb sessions" },
- { "Packets", "total smb packets" },
- { "Client segs reassembled", "total smb client segments reassembled" },
- { "Server segs reassembled", "total smb server segments reassembled" },
- { "Max outstanding requests", "total smb maximum outstanding requests" },
- { "Files processed", "total smb files processed" },
+ { "smb client segments reassembled", "total smb client segments reassembled" },
+ { "smb server segments reassembled", "total smb server segments reassembled" },
+ { "smb maximum outstanding requests", "total smb maximum outstanding requests" },
+ { "smb files processed", "total smb files processed" },
{ nullptr, nullptr }
};
switch ( index )
{
case 0:
- name = "dce_smb_main";
+ name = "dce smb main";
parent = nullptr;
return &dce2_smb_pstat_main;
case 1:
- name = "dce_smb_session";
- parent = "dce_smb_main";
+ name = "dce smb session";
+ parent = "dce smb main";
return &dce2_smb_pstat_session;
case 2:
- name = "dce_smb_new_session";
- parent = "dce_smb_session";
+ name = "dce smb new_session";
+ parent = "dce smb session";
return &dce2_smb_pstat_new_session;
case 3:
- name = "dce_smb_detect";
- parent = "dce_smb_main";
+ name = "dce smb detect";
+ parent = "dce smb main";
return &dce2_smb_pstat_detect;
case 4:
- name = "dce_smb_log";
- parent = "dce_smb_main";
+ name = "dce smb log";
+ parent = "dce smb main";
return &dce2_smb_pstat_log;
case 5:
- name = "dce_smb_co_segment";
- parent = "dce_smb_main";
+ name = "dce smb connection-oriented segment";
+ parent = "dce smb main";
return &dce2_smb_pstat_co_seg;
case 6:
- name = "dce_smb_co_fragment";
- parent = "dce_smb_main";
+ name = "dce smb connection-oriented fragment";
+ parent = "dce smb main";
return &dce2_smb_pstat_co_frag;
case 7:
- name = "dce_smb_co_reassembly";
- parent = "dce_smb_main";
+ name = "dce smb connection-oriented reassembly";
+ parent = "dce smb main";
return &dce2_smb_pstat_co_reass;
case 8:
- name = "dce_smb_co_context";
- parent = "dce_smb_main";
+ name = "dce smb connection-oriented context";
+ parent = "dce smb main";
return &dce2_smb_pstat_co_ctx;
case 9:
- name = "dce_smb_segment";
- parent = "dce_smb_main";
+ name = "dce smb segment";
+ parent = "dce smb main";
return &dce2_smb_pstat_smb_seg;
case 10:
- name = "dce_smb_request";
- parent = "dce_smb_main";
+ name = "dce smb request";
+ parent = "dce smb main";
return &dce2_smb_pstat_smb_req;
case 11:
- name = "dce_smb_uid";
- parent = "dce_smb_main";
+ name = "dce smb uid";
+ parent = "dce smb main";
return &dce2_smb_pstat_smb_uid;
case 12:
- name = "dce_smb_tid";
- parent = "dce_smb_main";
+ name = "dce smb tid";
+ parent = "dce smb main";
return &dce2_smb_pstat_smb_tid;
case 13:
- name = "dce_smb_fid";
- parent = "dce_smb_main";
+ name = "dce smb fid";
+ parent = "dce smb main";
return &dce2_smb_pstat_smb_fid;
case 14:
- name = "dce_smb_file";
- parent = "dce_smb_main";
+ name = "dce smb file";
+ parent = "dce smb main";
return &dce2_smb_pstat_smb_file;
case 15:
- name = "dce_smb_file_detect";
- parent = "dce_smb_file";
+ name = "dce smb file detect";
+ parent = "dce smb file";
return &dce2_smb_pstat_smb_file_detect;
case 16:
- name = "dce_smb_file_api";
- parent = "dce_smb_file";
+ name = "dce smb file api";
+ parent = "dce smb file";
return &dce2_smb_pstat_smb_file_api;
case 17:
- name = "dce_smb_fingerprint";
- parent = "dce_smb_main";
+ name = "dce smb fingerprint";
+ parent = "dce smb main";
return &dce2_smb_pstat_smb_fingerprint;
case 18:
- name = "dce_smb_negotiate";
- parent = "dce_smb_main";
+ name = "dce smb negotiate";
+ parent = "dce smb main";
return &dce2_smb_pstat_smb_negotiate;
}
return nullptr;
dce2SmbShare* ashare = (dce2SmbShare*)a;
dce2SmbShare* bshare = (dce2SmbShare*)b;
- if ((ashare == nullptr) || (bshare == nullptr))
+ if ((ashare == NULL) || (bshare == NULL))
return -1;
/* Just check the ascii string */
{
dce2SmbShare* smb_share = (dce2SmbShare*)data;
- if (smb_share == nullptr)
+ if (smb_share == NULL)
return;
free(smb_share->unicode_str);
smb_share = (dce2SmbShare*)calloc(sizeof(dce2SmbShare),1);
smb_share_key = (dce2SmbShare*)calloc(sizeof(dce2SmbShare),1);
- if ((smb_share == nullptr) || (smb_share_key == nullptr))
+ if ((smb_share == NULL) || (smb_share_key == NULL))
{
FatalError("DCE2 - Could not allocate memory for config\n");
}
smb_share->ascii_str_len = share_len + 1;
smb_share->ascii_str = (char*)calloc(smb_share->ascii_str_len,1);
- if ((smb_share->unicode_str == nullptr) || (smb_share->ascii_str == nullptr))
+ if ((smb_share->unicode_str == NULL) || (smb_share->ascii_str == NULL))
{
FatalError("DCE2 - Could not allocate memory for config\n");
}
smb_share_key->ascii_str_len = smb_share->ascii_str_len;
smb_share_key->ascii_str = (char*)calloc(smb_share_key->ascii_str_len,1);
- if (smb_share_key->ascii_str == nullptr)
+ if (smb_share_key->ascii_str == NULL)
{
FatalError("DCE2 - Could not allocate memory for config\n");
}
if (error)
{
DCE2_ListDestroy(config.smb_invalid_shares);
- config.smb_invalid_shares = nullptr;
+ config.smb_invalid_shares = NULL;
return error;
}
{
LogMessage(" SMB valid versions : all\n");
}
- if (config.smb_invalid_shares != nullptr)
+ if (config.smb_invalid_shares != NULL)
{
dce2SmbShare* share;
LogMessage(" Invalid SMB shares:\n");
for (share = (dce2SmbShare*)DCE2_ListFirst(config.smb_invalid_shares);
- share != nullptr;
+ share != NULL;
share = (dce2SmbShare*)DCE2_ListNext(config.smb_invalid_shares))
{
LogMessage(" %s\n",share->ascii_str);
while (n < len)
{
- Debug::print(nullptr, 0, DEBUG_DCE_SMB, " State %d : 0x%02x\n", ss->paf_state, data[n]);
+ DebugFormat(DEBUG_DCE_SMB, " State %d : 0x%02x", ss->paf_state, data[n]);
switch (ss->paf_state)
{
DebugFormat(DEBUG_DCE_SMB, "%s\n", DCE2_DEBUG__PAF_END_MSG);
return StreamSplitter::FLUSH;
}
- Debug::print(nullptr, 0, DEBUG_DCE_SMB, "%s", "Invalid NetBIOS header - "
+ DebugMessage(DEBUG_DCE_SMB, "Invalid NetBIOS header - "
"entering junk data states.\n");
ss->paf_state = (DCE2_PafSmbStates)(((int)ss->paf_state) + 1);
break;
if (!DCE2_PafSmbIsValidNetbiosHdr((uint32_t)(ss->nb_hdr >> 32), true))
{
- Debug::print(nullptr, 0, DEBUG_DCE_SMB, "%s", "Invalid NetBIOS header - "
+ DebugMessage(DEBUG_DCE_SMB, "Invalid NetBIOS header - "
"staying in State 7.\n");
break;
}
if (((uint32_t)ss->nb_hdr != DCE2_SMB_ID)
&& ((uint32_t)ss->nb_hdr != DCE2_SMB2_ID))
{
- Debug::print(nullptr, 0, DEBUG_DCE_SMB, "%s", "Invalid SMB ID - "
+ DebugMessage(DEBUG_DCE_SMB, "Invalid SMB ID - "
"staying in State 7.\n");
break;
}
#include "dce_tcp.h"
#include "dce_tcp_paf.h"
#include "dce_tcp_module.h"
-#include "dce_co.h"
#include "main/snort_debug.h"
-#include "detection/detect.h"
Dce2TcpFlowData::Dce2TcpFlowData() : FlowData(flow_id)
{
return(&fd->dce2_tcp_session);
}
-static DCE2_TcpSsnData* dce2_create_new_tcp_session(Packet* p, dce2TcpProtoConf* config)
+static DCE2_TcpSsnData* dce2_create_new_tcp_session(Packet* p, dce2TcpProtoConf config)
{
- DCE2_TcpSsnData* dce2_tcp_sess = nullptr;
+ DCE2_TcpSsnData* dce2_tcp_sess = NULL;
Profile profile(dce2_tcp_pstat_new_session);
- //FIXIT-M Re-evaluate after infrastructure/binder support if autodetect here
- //is necessary
if (DCE2_TcpAutodetect(p))
{
DebugMessage(DEBUG_DCE_TCP, "DCE over TCP packet detected\n");
DebugFormat(DEBUG_DCE_TCP,"Created (%p)\n", (void*)dce2_tcp_sess);
dce2_tcp_sess->sd.trans = DCE2_TRANS_TYPE__TCP;
- dce2_tcp_sess->sd.server_policy = config->common.policy;
+ dce2_tcp_sess->sd.server_policy = config.common.policy;
dce2_tcp_sess->sd.client_policy = DCE2_POLICY__WINXP;
dce2_tcp_sess->sd.wire_pkt = p;
- dce2_tcp_sess->sd.config = (void*)config;
DCE2_SsnSetAutodetected(&dce2_tcp_sess->sd, p);
}
return dce2_tcp_sess;
}
-DCE2_TcpSsnData* dce2_handle_tcp_session(Packet* p, dce2TcpProtoConf* config)
+DCE2_TcpSsnData* dce2_handle_tcp_session(Packet* p, dce2TcpProtoConf& config)
{
Profile profile(dce2_tcp_pstat_session);
DCE2_SsnNoInspect(sd);
dce2_tcp_stats.sessions_aborted++;
dce2_tcp_stats.bad_autodetects++;
- return nullptr;
+ return NULL;
}
DCE2_SsnClearAutodetected(sd);
}
DebugFormat(DEBUG_DCE_TCP, "Session pointer: %p\n", (void*)dce2_tcp_sess);
- if (dce2_tcp_sess)
- {
- //FIXIT-M Stack push
- p->packet_flags |= PKT_ALLOW_MULTIPLE_DETECT;
- dce2_detected = 0;
- }
+ // FIXIT-M add remaining session handling logic
return dce2_tcp_sess;
}
{
DCE2_TcpSsnData* dce2_tcp_sess;
Profile profile(dce2_tcp_pstat_main);
- if (DCE2_SsnFromServer(p))
- {
- DebugMessage(DEBUG_DCE_TCP, "Packet from Server.\n");
- }
- else
- {
- DebugMessage(DEBUG_DCE_TCP, "Packet from Client.\n");
- }
assert(p->has_tcp_data());
assert(p->flow);
return;
}
- dce2_tcp_sess = dce2_handle_tcp_session(p, &config);
- if (dce2_tcp_sess)
+ dce2_tcp_sess = dce2_handle_tcp_session(p, config);
+ if (!dce2_tcp_sess)
{
- dce2_tcp_stats.tcp_pkts++;
- DCE2_CoProcess(&dce2_tcp_sess->sd, &dce2_tcp_sess->co_tracker, p->data,
- p->dsize);
-
- if (!dce2_detected)
- DCE2_Detect(&dce2_tcp_sess->sd);
-
- DCE2_ResetRopts(&dce2_tcp_sess->sd.ropts);
- //FIXIT-M DCE2_PopPkt(sd);
-
- if (!DCE2_SsnAutodetected(&dce2_tcp_sess->sd))
- DisableInspection();
+ return;
}
+ dce2_tcp_stats.tcp_pkts++;
}
//-------------------------------------------------------------------------
PegCount autoports[65535][DCE2_TRANS_TYPE__MAX];
#endif
*/
- /* The common stats block has to be at the beginning followed
- by the protocol specific stats */
-
- /*common stats -defined in common.h*/
PegCount events;
PegCount sessions_aborted;
PegCount bad_autodetects;
+ PegCount tcp_sessions;
+ PegCount tcp_pkts;
+
PegCount co_pdus;
PegCount co_bind;
PegCount co_bind_ack;
PegCount co_auth3;
PegCount co_shutdown;
PegCount co_reject;
- PegCount co_ms_pdu;
PegCount co_other_req;
PegCount co_other_resp;
PegCount co_req_fragments;
PegCount co_srv_min_frag_size;
PegCount co_srv_seg_reassembled;
PegCount co_srv_frag_reassembled;
-
- /*DCE TCP specific*/
- PegCount tcp_sessions;
- PegCount tcp_pkts;
};
extern THREAD_LOCAL dce2TcpStats dce2_tcp_stats;
&& (DceRpcCoVersMin(co_hdr) == DCERPC_PROTO_MINOR_VERS__0)
&& ((p->from_client()
&& DceRpcCoPduType(co_hdr) == DCERPC_PDU_TYPE__BIND)
- || (DCE2_SsnFromServer(p)
+ || (p->from_server()
&& DceRpcCoPduType(co_hdr) == DCERPC_PDU_TYPE__BIND_ACK))
&& (DceRpcCoFragLen(co_hdr) >= sizeof(DceRpcCoHdr)))
{
{ "events", "total events" },
{ "aborted sessions", "total aborted sessions" },
{ "bad autodetects", "total bad autodetects" },
- { "PDUs", "total connection-oriented PDUs" },
- { "Binds", "total connection-oriented binds" },
- { "Bind acks", "total connection-oriented binds acks" },
- { "Alter contexts", "total connection-oriented alter contexts" },
- { "Alter context responses",
+ { "tcp sessions", "total tcp sessions" },
+ { "tcp packets", "total tcp packets" },
+ { "connection-oriented PDUs", "total connection-oriented PDUs" },
+ { "connection-oriented binds", "total connection-oriented binds" },
+ { "connection-oriented bind acks", "total connection-oriented binds acks" },
+ { "connection-oriented alter contexts", "total connection-oriented alter contexts" },
+ { "connection-oriented alter context responses",
"total connection-oriented alter context responses" },
- { "Bind naks", "total connection-oriented bind naks" },
- { "Requests", "total connection-oriented requests" },
- { "Responses", "total connection-oriented responses" },
- { "Cancels", "total connection-oriented cancels" },
- { "Orphaned", "total connection-oriented orphaned" },
- { "Faults", "total connection-oriented faults" },
- { "Auth3s", "total connection-oriented auth3s" },
- { "Shutdowns", "total connection-oriented shutdowns" },
- { "Rejects", "total connection-oriented rejects" },
- { "MS RPC/HTTP PDUs", "total connection-oriented MS requests to send RPC over HTTP" },
- { "Other requests", "total connection-oriented other requests" },
- { "Other responses", "total connection-oriented other responses" },
- { "Request fragments", "total connection-oriented request fragments" },
- { "Response fragments", "total connection-oriented response fragments" },
- { "Client max fragment size",
+ { "connection-oriented bind naks", "total connection-oriented bind naks" },
+ { "connection-oriented requests", "total connection-oriented requests" },
+ { "connection-oriented responses", "total connection-oriented responses" },
+ { "connection-oriented cancels", "total connection-oriented cancels" },
+ { "connection-oriented orphaned", "total connection-oriented orphaned" },
+ { "connection-oriented faults", "total connection-oriented faults" },
+ { "connection-oriented auth3s", "total connection-oriented auth3s" },
+ { "connection-oriented shutdowns", "total connection-oriented shutdowns" },
+ { "connection-oriented rejects", "total connection-oriented rejects" },
+ { "connection-oriented other requests", "total connection-oriented other requests" },
+ { "connection-oriented other responses", "total connection-oriented other responses" },
+ { "connection-oriented request fragments", "total connection-oriented request fragments" },
+ { "connection-oriented response fragments", "total connection-oriented response fragments" },
+ { "connection-oriented client maximum fragment size",
"connection-oriented client maximum fragment size" },
- { "Client min fragment size",
+ { "connection-oriented client minimum fragment size",
"connection-oriented client minimum fragment size" },
- { "Client segs reassembled",
+ { "connection-oriented client segments reassembled",
"total connection-oriented client segments reassembled" },
- { "Client frags reassembled",
+ { "connection-oriented client fragments reassembled",
"total connection-oriented client fragments reassembled" },
- { "Server max fragment size",
+ { "connection-oriented server maximum fragment size",
"connection-oriented server maximum fragment size" },
- { "Server min fragment size",
+ { "connection-oriented server minimum fragment size",
"connection-oriented server minimum fragment size" },
- { "Server segs reassembled",
+ { "connection-oriented server segments reassembled",
"total connection-oriented server segments reassembled" },
- { "Server frags reassembled",
+ { "connection-oriented server fragments reassembled",
"total connection-oriented server fragments reassembled" },
- { "tcp sessions", "total tcp sessions" },
- { "tcp packets", "total tcp packets" },
{ nullptr, nullptr }
};
switch ( index )
{
case 0:
- name = "dce_tcp_main";
+ name = "dce tcp main";
parent = nullptr;
return &dce2_tcp_pstat_main;
case 1:
- name = "dce_tcp_session";
- parent = "dce_tcp_main";
+ name = "dce tcp session";
+ parent = "dce tcp main";
return &dce2_tcp_pstat_session;
case 2:
- name = "dce_tcp_new_session";
- parent = "dce_tcp_session";
+ name = "dce tcp new session";
+ parent = "dce tcp session";
return &dce2_tcp_pstat_new_session;
case 3:
- name = "dce_tcp_detect";
- parent = "dce_tcp_main";
+ name = "dce tcp detect";
+ parent = "dce tcp main";
return &dce2_tcp_pstat_detect;
case 4:
- name = "dce_tcp_log";
+ name = "dce tcp log";
parent = "dce_tcp_main";
return &dce2_tcp_pstat_log;
case 5:
- name = "dce_tcp_co_segment";
- parent = "dce_tcp_main";
+ name = "dce tcp connection-oriented segment";
+ parent = "dce tcp main";
return &dce2_tcp_pstat_co_seg;
case 6:
- name = "dce_tcp_co_fragment";
- parent = "dce_tcp_main";
+ name = "dce tcp connection-oriented fragment";
+ parent = "dce tcp main";
return &dce2_tcp_pstat_co_frag;
case 7:
- name = "dce_tcp_co_reassembly";
- parent = "dce_tcp_main";
+ name = "dce tcp connection-oriented reassembly";
+ parent = "dce tcp main";
return &dce2_tcp_pstat_co_reass;
case 8:
- name = "dce_tcp_co_context";
- parent = "dce_tcp_main";
+ name = "dce tcp connection-oriented context";
+ parent = "dce tcp main";
return &dce2_tcp_pstat_co_ctx;
}
return nullptr;
return StreamSplitter::ABORT;
}
- if (sd == nullptr)
+ if (sd == NULL)
{
bool autodetected = false;
DebugMessage(DEBUG_DCE_TCP, "No session data - autodetecting\n");
while (n < len)
{
- Debug::print(nullptr, 0, DEBUG_DCE_TCP, " State %d : 0x%02x\n", ds->paf_state, data[n]);
+ DebugFormat(DEBUG_DCE_TCP, " State %d : 0x%02x", ds->paf_state, data[n]);
switch (ds->paf_state)
{
ds->paf_state = (DCE2_PafTcpStates)(((int)ds->paf_state) + 1);
if (ds->byte_order == DCERPC_BO_FLAG__LITTLE_ENDIAN)
{
- Debug::print(nullptr, 0, DEBUG_DCE_TCP, "%s","Byte order: Little endian\n");
+ DebugMessage(DEBUG_DCE_TCP, "Byte order: Little endian\n");
}
else
{
- Debug::print(nullptr, 0, DEBUG_DCE_TCP, "%s","Byte order: Big endian\n");
+ DebugMessage(DEBUG_DCE_TCP, "Byte order: Big endian\n");
}
break;
case DCE2_PAF_TCP_STATES__8:
- Debug::print(nullptr, 0, DEBUG_DCE_TCP, "%s", "First byte of fragment length\n");
+ DebugMessage(DEBUG_DCE_TCP, "First byte of fragment length\n");
if (ds->byte_order == DCERPC_BO_FLAG__LITTLE_ENDIAN)
ds->frag_len = data[n];
else
ds->paf_state = (DCE2_PafTcpStates)(((int)ds->paf_state) + 1);
break;
case DCE2_PAF_TCP_STATES__9:
- Debug::print(nullptr, 0, DEBUG_DCE_TCP, "%s", "Second byte of fragment length\n");
+ DebugMessage(DEBUG_DCE_TCP, "Second byte of fragment length\n");
if (ds->byte_order == DCERPC_BO_FLAG__LITTLE_ENDIAN)
ds->frag_len |= data[n] << 8;
else
/* If we get a bad frag length abort */
if (ds->frag_len < sizeof(DceRpcCoHdr))
{
- Debug::print(nullptr, 0, DEBUG_DCE_TCP, "%s\n", DCE2_DEBUG__PAF_END_MSG);
+ DebugFormat(DEBUG_DCE_TCP, "%s\n", DCE2_DEBUG__PAF_END_MSG);
return StreamSplitter::ABORT;
}
- Debug::print(nullptr, 0, DEBUG_DCE_TCP, "Fragment length: %u\n", ds->frag_len);
+ DebugFormat(DEBUG_DCE_TCP, "Fragment length: %u\n", ds->frag_len);
/* Increment n here so we can continue */
n += ds->frag_len - (uint8_t)ds->paf_state;
* flush just before it */
if ((num_requests == 1) || (n <= len))
tmp_fp += ds->frag_len;
- Debug::print(nullptr, 0, DEBUG_DCE_TCP, "Requests: %u\n", num_requests);
+ DebugFormat(DEBUG_DCE_TCP, "Requests: %u\n", num_requests);
ds->paf_state = DCE2_PAF_TCP_STATES__0;
continue; // we incremented n already
default:
//--------------------------------------------------------------------------
#include "dce_utils.h"
-#include "main/snort_debug.h"
+
/********************************************************************
* Function: DCE2_GetValue()
uint64_t place = 1;
uint64_t max_value = 0;
- if ((end == nullptr) || (start == nullptr) || (int_value == nullptr))
+ if ((end == NULL) || (start == NULL) || (int_value == NULL))
return DCE2_RET__ERROR;
if (start >= end)
return DCE2_RET__SUCCESS;
}
-const char* DCE2_UuidToStr(const Uuid* uuid, DceRpcBoFlag byte_order)
-{
-#define UUID_BUF_SIZE 50
- static char uuid_buf1[UUID_BUF_SIZE];
- static char uuid_buf2[UUID_BUF_SIZE];
- static int buf_num = 0;
- char* uuid_buf;
-
- if (buf_num == 0)
- {
- uuid_buf = uuid_buf1;
- buf_num = 1;
- }
- else
- {
- uuid_buf = uuid_buf2;
- buf_num = 0;
- }
-
- snprintf(uuid_buf, UUID_BUF_SIZE,
- "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- DceRpcHtonl(&uuid->time_low, byte_order),
- DceRpcHtons(&uuid->time_mid, byte_order),
- DceRpcHtons(&uuid->time_high_and_version, byte_order),
- uuid->clock_seq_and_reserved, uuid->clock_seq_low,
- uuid->node[0], uuid->node[1], uuid->node[2],
- uuid->node[3], uuid->node[4], uuid->node[5]);
-
- uuid_buf[UUID_BUF_SIZE - 1] = '\0';
-
- return uuid_buf;
-}
-
-void DCE2_PrintPktData(const uint8_t* data, const uint16_t len)
-{
- unsigned int i, j = 0, line_len = 0;
- uint8_t hex_buf[16];
- uint8_t char_buf[16];
-
- for (i = 0; i < len; i++)
- {
- hex_buf[j] = data[i];
-
- if (isascii((int)data[i]) && isprint((int)data[i]))
- char_buf[j] = data[i];
- else
- char_buf[j] = '.';
-
- if (line_len == 15)
- {
- unsigned int k, sub_line_len = 0;
- for (k = 0; k <= j; k++)
- {
- Debug::print(nullptr, 0, DEBUG_DCE_COMMON,"%02x ", hex_buf[k]);
- if (sub_line_len >= 7)
- {
- Debug::print(nullptr, 0, DEBUG_DCE_COMMON,"%s"," ");
- sub_line_len = 0;
- }
- else
- {
- sub_line_len++;
- }
- }
-
- Debug::print(nullptr, 0, DEBUG_DCE_COMMON,"%s"," ");
-
- sub_line_len = 0;
- for (k = 0; k <= j; k++)
- {
- Debug::print(nullptr, 0, DEBUG_DCE_COMMON,"%c", char_buf[k]);
- if (sub_line_len >= 7)
- {
- Debug::print(nullptr, 0, DEBUG_DCE_COMMON,"%s"," ");
- sub_line_len = 0;
- }
- else
- {
- sub_line_len++;
- }
- }
-
- Debug::print(nullptr, 0, DEBUG_DCE_COMMON,"%s","\n");
-
- j = line_len = 0;
- }
- else
- {
- j++;
- line_len++;
- }
- }
-
- if (line_len > 0)
- {
- unsigned int k, sub_line_len = 0;
- for (k = 0; k < j; k++)
- {
- Debug::print(nullptr, 0, DEBUG_DCE_COMMON,"%02x ", hex_buf[k]);
- if (sub_line_len >= 7)
- {
- Debug::print(nullptr, 0, DEBUG_DCE_COMMON,"%s"," ");
- sub_line_len = 0;
- }
- else
- {
- sub_line_len++;
- }
- }
-
- if (k < 8)
- Debug::print(nullptr, 0, DEBUG_DCE_COMMON,"%s"," ");
- else
- Debug::print(nullptr, 0, DEBUG_DCE_COMMON,"%s"," ");
-
- while (k < 16)
- {
- Debug::print(nullptr, 0, DEBUG_DCE_COMMON,"%s"," ");
- k++;
- }
-
- sub_line_len = 0;
- for (k = 0; k < j; k++)
- {
- Debug::print(nullptr, 0, DEBUG_DCE_COMMON,"%c", char_buf[k]);
- if (sub_line_len >= 7)
- {
- Debug::print(nullptr, 0, DEBUG_DCE_COMMON,"%s"," ");
- sub_line_len = 0;
- }
- else
- {
- sub_line_len++;
- }
- }
- }
-
- Debug::print(nullptr, 0, DEBUG_DCE_COMMON,"%s","\n");
-}
-
DCE2_INT_TYPE__UINT64
};
-/* DCE/RPC byte order flag */
-enum DceRpcBoFlag
-{
- DCERPC_BO_FLAG__NONE,
- DCERPC_BO_FLAG__BIG_ENDIAN,
- DCERPC_BO_FLAG__LITTLE_ENDIAN
-};
-
/********************************************************************
* Structures
********************************************************************/
inline bool DCE2_IsEmptyStr(char*);
inline int DCE2_UuidCompare(const void*, const void*);
-const char* DCE2_UuidToStr(const Uuid*, DceRpcBoFlag);
-void DCE2_PrintPktData(const uint8_t*, const uint16_t);
/********************************************************************
* Public function prototypes
return -1;
}
-inline DceRpcBoFlag DceRpcByteOrder(const uint8_t value)
-{
- if ((value & 0x10) >> 4)
- return DCERPC_BO_FLAG__LITTLE_ENDIAN;
-
- return DCERPC_BO_FLAG__BIG_ENDIAN;
-}
-
-inline uint16_t DceRpcNtohs(const uint16_t* ptr, const DceRpcBoFlag bo_flag)
-{
- uint16_t value;
-
- if (ptr == nullptr)
- return 0;
-
-#ifdef WORDS_MUSTALIGN
- value = *((uint8_t*)ptr) << 8 | *((uint8_t*)ptr + 1);
-#else
- value = *ptr;
-#endif /* WORDS_MUSTALIGN */
-
- if (bo_flag == DCERPC_BO_FLAG__NONE)
- return value;
-
-#ifdef WORDS_BIGENDIAN
- if (bo_flag == DCERPC_BO_FLAG__BIG_ENDIAN)
-#else
- if (bo_flag == DCERPC_BO_FLAG__LITTLE_ENDIAN)
-#endif /* WORDS_BIGENDIAN */
- return value;
-
- return ((value & 0xff00) >> 8) | ((value & 0x00ff) << 8);
-}
-
-inline uint16_t DceRpcHtons(const uint16_t* ptr, const DceRpcBoFlag bo_flag)
-{
- return DceRpcNtohs(ptr, bo_flag);
-}
-
-inline uint32_t DceRpcNtohl(const uint32_t* ptr, const DceRpcBoFlag bo_flag)
-{
- uint32_t value;
-
- if (ptr == nullptr)
- return 0;
-
-#ifdef WORDS_MUSTALIGN
- value = *((uint8_t*)ptr) << 24 | *((uint8_t*)ptr + 1) << 16 |
- *((uint8_t*)ptr + 2) << 8 | *((uint8_t*)ptr + 3);
-#else
- value = *ptr;
-#endif /* WORDS_MUSTALIGN */
-
- if (bo_flag == DCERPC_BO_FLAG__NONE)
- return value;
-
-#ifdef WORDS_BIGENDIAN
- if (bo_flag == DCERPC_BO_FLAG__BIG_ENDIAN)
-#else
- if (bo_flag == DCERPC_BO_FLAG__LITTLE_ENDIAN)
-#endif /* WORDS_BIGENDIAN */
- return value;
-
- return ((value & 0xff000000) >> 24) | ((value & 0x00ff0000) >> 8) |
- ((value & 0x0000ff00) << 8) | ((value & 0x000000ff) << 24);
-}
-
-inline uint32_t DceRpcHtonl(const uint32_t* ptr, const DceRpcBoFlag bo_flag)
-{
- return DceRpcNtohl(ptr, bo_flag);
-}
-
-inline void DCE2_CopyUuid(Uuid* dst_uuid, const Uuid* pkt_uuid, const DceRpcBoFlag byte_order)
-{
- dst_uuid->time_low = DceRpcNtohl(&pkt_uuid->time_low, byte_order);
- dst_uuid->time_mid = DceRpcNtohs(&pkt_uuid->time_mid, byte_order);
- dst_uuid->time_high_and_version = DceRpcNtohs(&pkt_uuid->time_high_and_version, byte_order);
- dst_uuid->clock_seq_and_reserved = pkt_uuid->clock_seq_and_reserved;
- dst_uuid->clock_seq_low = pkt_uuid->clock_seq_low;
- memcpy(dst_uuid->node, pkt_uuid->node, sizeof(dst_uuid->node));
-}
-
-inline int DCE2_BufferIsEmpty(DCE2_Buffer* buf)
-{
- if (buf == nullptr)
- return 1;
- if ((buf->data == nullptr) || (buf->len == 0))
- return 1;
- return 0;
-}
-
-inline uint32_t DCE2_BufferLength(DCE2_Buffer* buf)
-{
- if (buf == nullptr)
- return 0;
- return buf->len;
-}
-
-inline uint8_t* DCE2_BufferData(DCE2_Buffer* buf)
-{
- if (buf == nullptr)
- return nullptr;
- return buf->data;
-}
-
-inline void DCE2_BufferEmpty(DCE2_Buffer* buf)
-{
- if (buf == nullptr)
- return;
- buf->len = 0;
-}
-
-#define DCE2_MOVE(data_ptr, data_len, amount) \
- { data_len -= (amount); data_ptr = (uint8_t*)data_ptr + (amount); }
-
#endif /* _DCE2_UTILS_H_ */