📄 dce2_co.c
字号:
* Length of data from current data cursor. * uint16_t * Length of data that we need in order to consider * desegmentation complete. * uint16_t * * Pointer to basically a return value for the amount of * data in the packet that was actually used for * desegmentation. * * Returns: * DCE2_Ret * DCE2_RET__ERROR if an error occured. Nothing can * be trusted. * DCE2_RET__SEG if there is still more desegmentation * to go, i.e. the need length has not been met by * the data length. * DCE2_RET__SUCCESS if desegmentation is complete, * i.e. the need length was met. * ********************************************************************/static INLINE DCE2_Ret DCE2_CoHandleSegmentation(DCE2_CoSeg *seg, const uint8_t *data_ptr, uint16_t data_len, uint16_t need_len, uint16_t *data_used){ if (seg == NULL) return DCE2_RET__ERROR; if (seg->buf == NULL) { /* No initial size or min alloc size */ seg->buf = DCE2_BufferNew(need_len, need_len, DCE2_MEM_TYPE__CO_SEG); if (seg->buf == NULL) return DCE2_RET__ERROR; } else if (DCE2_BufferMinAllocSize(seg->buf) != need_len) { DCE2_BufferSetMinAllocSize(seg->buf, need_len); } return DCE2_HandleSegmentation(seg->buf, data_ptr, data_len, need_len, data_used);}/******************************************************************** * Function: DCE2_CoHdrChecks() * * Checks some relevant fields in the header to make sure they're * sane. * * Arguments: * DCE2_SsnData * * Pointer to the session data structure. * DCE2_CoTracker * * Pointer to the relevant connection-oriented tracker. * DceRpcCoHdr * * Pointer to the header struct layed over the packet data. * * Returns: * DCE2_Ret * DCE2_RET__ERROR if we should not continue processing. * DCE2_RET__SUCCESS if we should continue processing. * ********************************************************************/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); int is_seg_buf = DCE2_CoIsSegBuf(sd, cot, (uint8_t *)co_hdr); if (frag_len < sizeof(DceRpcCoHdr)) { if (is_seg_buf) DCE2_CoSegAlert(sd, cot, DCE2_EVENT__CO_FLEN_LT_HDR); else DCE2_Alert(sd, DCE2_EVENT__CO_FLEN_LT_HDR, frag_len, sizeof(DceRpcCoHdr)); return DCE2_RET__ERROR; } if (DceRpcCoVersMaj(co_hdr) != DCERPC_PROTO_MAJOR_VERS__5) { if (is_seg_buf) DCE2_CoSegAlert(sd, cot, DCE2_EVENT__CO_BAD_MAJ_VERSION); else DCE2_Alert(sd, DCE2_EVENT__CO_BAD_MAJ_VERSION, DceRpcCoVersMaj(co_hdr)); return DCE2_RET__ERROR; } if (DceRpcCoVersMin(co_hdr) != DCERPC_PROTO_MINOR_VERS__0) { if (is_seg_buf) DCE2_CoSegAlert(sd, cot, DCE2_EVENT__CO_BAD_MIN_VERSION); else DCE2_Alert(sd, DCE2_EVENT__CO_BAD_MIN_VERSION, DceRpcCoVersMin(co_hdr)); return DCE2_RET__ERROR; } if (DceRpcCoPduType(co_hdr) >= DCERPC_PDU_TYPE__MAX) { if (is_seg_buf) DCE2_CoSegAlert(sd, cot, DCE2_EVENT__CO_BAD_PDU_TYPE); else DCE2_Alert(sd, DCE2_EVENT__CO_BAD_PDU_TYPE, DceRpcCoPduType(co_hdr)); return DCE2_RET__ERROR; } if (DCE2_SsnFromClient(sd->wire_pkt) && (cot->max_xmit_frag != DCE2_SENTINEL)) { if (frag_len > cot->max_xmit_frag) { if (is_seg_buf) { DCE2_CoSegAlert(sd, cot, DCE2_EVENT__CO_FRAG_GT_MAX_XMIT_FRAG); } else { DCE2_Alert(sd, DCE2_EVENT__CO_FRAG_GT_MAX_XMIT_FRAG, dce2_pdu_types[pdu_type], frag_len, cot->max_xmit_frag); } } else if (!DceRpcCoLastFrag(co_hdr) && (frag_len < cot->max_xmit_frag)) { /* 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. */ if (is_seg_buf) { DCE2_CoSegAlert(sd, cot, DCE2_EVENT__CO_FRAG_LT_MAX_XMIT_FRAG); } else { DCE2_Alert(sd, DCE2_EVENT__CO_FRAG_LT_MAX_XMIT_FRAG, dce2_pdu_types[pdu_type], frag_len, cot->max_xmit_frag); } } /* Continue processing */ } return DCE2_RET__SUCCESS;}/******************************************************************** * 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. * * Arguments: * DCE2_SsnData * * Pointer to the session data structure * DCE2_CoTracker * * Pointer to the relevant connection-oriented tracker. * const uint8_t * * Pointer to the start of the DCE/RPC pdu in the packet data. * uint16_t * Fragment length of the pdu. * * Returns: None * ********************************************************************/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); /* We've got the main header. Move past it to the * start of the pdu */ DCE2_MOVE(frag_ptr, frag_len, sizeof(DceRpcCoHdr)); /* Client specific pdu types - some overlap with server */ if (DCE2_SsnFromClient(sd->wire_pkt)) { switch (pdu_type) { case DCERPC_PDU_TYPE__BIND: DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "CO Bind\n"); dce2_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: DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "CO Alter Context\n"); dce2_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: DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "CO Request\n"); dce2_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: DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "CO Auth3\n"); dce2_stats.co_auth3++; break; case DCERPC_PDU_TYPE__CO_CANCEL: DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "CO Cancel\n"); dce2_stats.co_cancel++; break; case DCERPC_PDU_TYPE__ORPHANED: DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "CO Orphaned\n"); dce2_stats.co_orphaned++; break; case DCERPC_PDU_TYPE__MICROSOFT_PROPRIETARY_OUTLOOK2003_RPC_OVER_HTTP: DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "CO Microsoft unknown pdu type\n"); dce2_stats.co_ms_pdu++; break; default: DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "CO Unknown request pdu type: 0x%02x\n", pdu_type); dce2_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) { DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "CO Bind Ack\n"); dce2_stats.co_bind_ack++; } else { DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "CO Alter Context Response\n"); dce2_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: DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "CO Bind Nack\n"); dce2_stats.co_bind_nack++; /* Bind nack in Windows seems to blow any previous context away */ switch (DCE2_ScPolicy(sd->sconfig)) { case DCE2_POLICY__WIN2000: case DCE2_POLICY__WIN2003: case DCE2_POLICY__WINXP: case DCE2_POLICY__WINVISTA: DCE2_CoEraseCtxIds(cot); break; default: break; } cot->got_bind = 0; break; case DCERPC_PDU_TYPE__RESPONSE: DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "CO Response\n"); dce2_stats.co_response++; DCE2_CoResponse(sd, cot, co_hdr, frag_ptr, frag_len); break; case DCERPC_PDU_TYPE__FAULT: DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "CO Fault\n"); dce2_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.frag_buf); DCE2_CoResetTracker(cot); break; case DCERPC_PDU_TYPE__SHUTDOWN: DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "CO Shutdown\n"); dce2_stats.co_shutdown++; break; case DCERPC_PDU_TYPE__REJECT: DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "CO Reject\n"); dce2_stats.co_reject++; DCE2_QueueEmpty(cot->pending_ctx_ids); break; case DCERPC_PDU_TYPE__MICROSOFT_PROPRIETARY_OUTLOOK2003_RPC_OVER_HTTP: DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "CO Microsoft Exchange/Outlook 2003 pdu type\n"); dce2_stats.co_ms_pdu++; break; default: DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "CO Unknown response pdu type: 0x%02x\n", pdu_type); dce2_stats.co_other_resp++; break; } }}/******************************************************************** * 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. * * 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_CoBind(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); DceRpcCoBind *bind = (DceRpcCoBind *)frag_ptr; if (frag_len < sizeof(DceRpcCoBind))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -