📄 dce2_co.c
字号:
{ DCE2_Alert(sd, DCE2_EVENT__CO_FLEN_LT_SIZE, dce2_pdu_types[DceRpcCoPduType(co_hdr)], frag_len, sizeof(DceRpcCoBind)); 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: /* 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_22: if (cot->got_bind) return; break; case DCE2_POLICY__SAMBA_3_0_20: /* Accepts multiple binds */ break; default: DCE2_Log("%s(%d) => Invalid policy\n", __FILE__, __LINE__); return; } cot->max_xmit_frag = 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. * * Arguments: * DCE2_SsnData * * Pointer to the session data structure. * DCE2_CoTracker * * Pointer to the relevant connection-oriented tracker. * DceRpcCoHdr * * Pointer to the main header in the packet data. * const uint8_t * * Pointer to the current processing point of the DCE/RPC * pdu in the packet data. * uint16_t * Fragment length left in the pdu. * * Returns: None * ********************************************************************/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_ScPolicy(sd->sconfig); DceRpcCoAltCtx *alt_ctx = (DceRpcCoAltCtx *)frag_ptr; if (frag_len < sizeof(DceRpcCoAltCtx)) { DCE2_Alert(sd, DCE2_EVENT__CO_FLEN_LT_SIZE, dce2_pdu_types[DceRpcCoPduType(co_hdr)], frag_len, sizeof(DceRpcCoAltCtx)); 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: /* 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 != DceRpcCoByteOrder(co_hdr)) { /* This is anomalous behavior. Alert, but continue processing */ if (cot->data_byte_order != DCE2_SENTINEL) DCE2_Alert(sd, DCE2_EVENT__CO_ALTER_CHANGE_BYTE_ORDER); } break; default: DCE2_Log("%s(%d) => Invalid policy\n", __FILE__, __LINE__); break; } /* Alter context is typedef'ed as a bind */ DCE2_CoCtxReq(sd, cot, co_hdr, DceRpcCoNumCtxItems((DceRpcCoBind *)alt_ctx), frag_ptr, frag_len);}/******************************************************************** * 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. * * Arguments: * DCE2_SsnData * * Pointer to the session data structure. * DCE2_CoTracker * * Pointer to the relevant connection-oriented tracker. * DceRpcCoHdr * * Pointer to the main header in the packet data. * const uint8_t * The number of context items in the bind or alter context. * const uint8_t * * Pointer to the current processing point of the DCE/RPC * pdu in the packet data. * uint16_t * Fragment length left in the pdu. * * Returns: None * ********************************************************************/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_ScPolicy(sd->sconfig); unsigned int i; DCE2_Ret status; for (i = 0; i < num_ctx_items; i++) { DceRpcCoContElem *ctx_elem = (DceRpcCoContElem *)frag_ptr; uint16_t ctx_id; uint8_t num_tsyns; const Uuid *iface; uint16_t if_vers_maj; uint16_t if_vers_min; DCE2_CoCtxIdNode *ctx_node; int j; if (frag_len < sizeof(DceRpcCoContElem)) { DCE2_Alert(sd, DCE2_EVENT__CO_FLEN_LT_SIZE, dce2_pdu_types[DceRpcCoPduType(co_hdr)], frag_len, sizeof(DceRpcCoContElem)); return; } 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) { DCE2_Alert(sd, DCE2_EVENT__CO_ZERO_TSYNS, dce2_pdu_types[DceRpcCoPduType(co_hdr)]); return; } 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)) { DCE2_Alert(sd, DCE2_EVENT__CO_FLEN_LT_SIZE, dce2_pdu_types[DceRpcCoPduType(co_hdr)], frag_len, sizeof(DceRpcCoSynId)); return; } DCE2_MOVE(frag_ptr, frag_len, sizeof(DceRpcCoSynId)); } /* 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_ListFind(cot->ctx_ids, (void *)(uintptr_t)ctx_id); if ((ctx_node != NULL) && (ctx_node->state != DCE2_CO_CTX_STATE__REJECTED)) return; } ctx_node = (DCE2_CoCtxIdNode *)DCE2_Alloc(sizeof(DCE2_CoCtxIdNode), DCE2_MEM_TYPE__CO_CTX); if (ctx_node == NULL) return; /* Add context id to pending queue */ status = DCE2_QueueEnqueue(cot->pending_ctx_ids, ctx_node); if (status != DCE2_RET__SUCCESS) { DCE2_Free((void *)ctx_node, sizeof(DCE2_CoCtxIdNode), DCE2_MEM_TYPE__CO_CTX); return; } /* 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; DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "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_3_0_20: case DCE2_POLICY__SAMBA_3_0_22: case DCE2_POLICY__SAMBA: /* Samba only ever looks at one context item. Not sure * if this is an alertable offense */ return; default: break; } }}/******************************************************************** * 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. * * Arguments: * DCE2_SsnData * * Pointer to the session data structure. * DCE2_CoTracker * * Pointer to the relevant connection-oriented tracker. * DceRpcCoHdr * * Pointer to the main header in the packet data. * const uint8_t * * Pointer to the current processing point of the DCE/RPC * pdu in the packet data. * uint16_t * Fragment length left in the pdu. * * Returns: None * ********************************************************************/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_ScPolicy(sd->sconfig); 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; DCE2_Ret status; if (frag_len < sizeof(DceRpcCoBindAck)) { DCE2_Alert(sd, DCE2_EVENT__CO_FLEN_LT_SIZE, dce2_pdu_types[DceRpcCoPduType(co_hdr)], frag_len, sizeof(DceRpcCoBindAck)); 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 = max_recv_frag; sec_addr_len = DceRpcCoSecAddrLen(co_hdr, bind_ack); ctx_data = frag_ptr; ctx_len = frag_len; DCE2_MOVE(frag_ptr, frag_len, frag_len); /* First move past secondary address */ if (ctx_len < sec_addr_len) { DCE2_Alert(sd, DCE2_EVENT__CO_FLEN_LT_SIZE, dce2_pdu_types[DceRpcCoPduType(co_hdr)], ctx_len, sec_addr_len); 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) { DCE2_Alert(sd, DCE2_EVENT__CO_FLEN_LT_SIZE, dce2_pdu_types[DceRpcCoPduType(co_hdr)], ctx_len, pad); return; } DCE2_MOVE(ctx_data, ctx_len, pad); /* Now we're at the start of the context item results */ if (ctx_len < sizeof(DceRpcCoContResultList)) { DCE2_Alert(sd, DCE2_EVENT__CO_FLEN_LT_SIZE, dce2_pdu_types[DceRpcCoPduType(co_hdr)], ctx_len, sizeof(DceRpcCoContResultList)); 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; DCE2_CoCtxIdNode *ctx_node, *existing_ctx_node; if (ctx_len < sizeof(DceRpcCoContResult)) { DCE2_Alert(sd, DCE2_EVENT__CO_FLEN_LT_SIZE, dce2_pdu_types[DceRpcCoPduType(co_hdr)], ctx_len, sizeof(DceRpcCoContResult)); 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; /* 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -