📄 dce2_co.c
字号:
if (ctx_node == NULL) { DCE2_Log("%s(%d) => Failed to dequeue a context id node\n", __FILE__, __LINE__); return; } DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "Adding ctx node to context id 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) { DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "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 { DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "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 != NULL) { switch (policy) { case DCE2_POLICY__WIN2000: case DCE2_POLICY__WIN2003: case DCE2_POLICY__WINXP: case DCE2_POLICY__WINVISTA: 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_3_0_20: case DCE2_POLICY__SAMBA_3_0_22: case DCE2_POLICY__SAMBA: /* 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; } DCE2_Free((void *)ctx_node, sizeof(DCE2_CoCtxIdNode), DCE2_MEM_TYPE__CO_CTX); } else { status = DCE2_ListInsert(cot->ctx_ids, (void *)(uintptr_t)ctx_node->ctx_id, (void *)ctx_node); if (status != DCE2_RET__SUCCESS) { DCE2_Free((void *)ctx_node, sizeof(DCE2_CoCtxIdNode), DCE2_MEM_TYPE__CO_CTX); DCE2_Log("%s(%d) => Failed to add context id node to list\n", __FILE__, __LINE__); return; } } }}/******************************************************************** * 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. * * 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_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_ScPolicy(sd->sconfig); /* Account for possible object uuid */ if (DceRpcCoObjectFlag(co_hdr)) req_size += sizeof(Uuid); if (frag_len < req_size) { DCE2_Alert(sd, DCE2_EVENT__CO_FLEN_LT_SIZE, dce2_pdu_types[DceRpcCoPduType(co_hdr)], frag_len, req_size); return; } switch (policy) { case DCE2_POLICY__SAMBA_3_0_20: case DCE2_POLICY__SAMBA_3_0_22: case DCE2_POLICY__SAMBA: cot->data_byte_order = DceRpcCoByteOrder(co_hdr); break; default: break; } /* Move past header */ DCE2_MOVE(frag_ptr, frag_len, req_size); /* If for some reason we had some fragments queued */ if (DceRpcCoFirstFrag(co_hdr) && !DCE2_BufferIsEmpty(cot->frag_tracker.frag_buf)) { DCE2_CoFragReassemble(sd, cot); DCE2_BufferEmpty(cot->frag_tracker.frag_buf); DCE2_CoResetTracker(cot); } 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)) { DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "First and last fragment.\n"); DCE2_CoSetRopts(sd, cot, co_hdr); DCE2_CoResetTracker(cot); } else { DCE2_CoFragTracker *ft = &cot->frag_tracker; uint16_t auth_len = DceRpcCoAuthLen(co_hdr); dce2_stats.co_fragments++; DCE2_DEBUG_CODE(DCE2_DEBUG__CO, if (DceRpcCoFirstFrag(co_hdr)) DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "First fragment.\n"); else if (DceRpcCoLastFrag(co_hdr)) DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "Last fragment.\n"); else DCE2_DEBUG_MSG(DCE2_DEBUG__CO, "Middle fragment.\n"); DCE2_PrintPktData(frag_ptr, frag_len);); if (DCE2_BufferIsEmpty(ft->frag_buf)) { ft->expected_opnum = cot->opnum; ft->expected_ctx_id = cot->ctx_id; ft->expected_call_id = cot->call_id; } else { /* Don't return for these, because we can still process and servers * will still accept and deal with the anomalies in their own way */ if ((ft->expected_opnum != DCE2_SENTINEL) && (ft->expected_opnum != cot->opnum)) { DCE2_Alert(sd, DCE2_EVENT__CO_FRAG_DIFF_OPNUM, cot->opnum, ft->expected_opnum); } if ((ft->expected_ctx_id != DCE2_SENTINEL) && (ft->expected_ctx_id != cot->ctx_id)) { DCE2_Alert(sd, DCE2_EVENT__CO_FRAG_DIFF_CTX_ID, cot->ctx_id, ft->expected_ctx_id); } if ((ft->expected_call_id != DCE2_SENTINEL) && (ft->expected_call_id != cot->call_id)) { DCE2_Alert(sd, DCE2_EVENT__CO_FRAG_DIFF_CALL_ID, cot->call_id, ft->expected_call_id); } } /* Possibly set opnum in frag tracker */ switch (policy) { case DCE2_POLICY__WIN2000: case DCE2_POLICY__WIN2003: case DCE2_POLICY__WINXP: case DCE2_POLICY__SAMBA: case DCE2_POLICY__SAMBA_3_0_20: case DCE2_POLICY__SAMBA_3_0_22: if (DceRpcCoLastFrag(co_hdr)) ft->opnum = cot->opnum; break; case DCE2_POLICY__WINVISTA: if (DceRpcCoFirstFrag(co_hdr)) ft->opnum = cot->opnum; break; default: DCE2_Log("%s(%d) => Invalid policy\n", __FILE__, __LINE__); break; } /* Possibly set context id in frag tracker */ switch (DCE2_ScPolicy(sd->sconfig)) { case DCE2_POLICY__WIN2000: case DCE2_POLICY__WIN2003: case DCE2_POLICY__WINXP: case DCE2_POLICY__WINVISTA: if (DceRpcCoFirstFrag(co_hdr)) { ft->ctx_id = cot->ctx_id; } else if ((ft->expected_call_id != DCE2_SENTINEL) && (ft->expected_call_id != cot->call_id)) { /* Server won't accept frag */ return; } break; case DCE2_POLICY__SAMBA: case DCE2_POLICY__SAMBA_3_0_20: case DCE2_POLICY__SAMBA_3_0_22: if (DceRpcCoLastFrag(co_hdr)) { ft->ctx_id = cot->ctx_id; } break; default: DCE2_Log("%s(%d) => Invalid policy\n", __FILE__, __LINE__); break; } /* Don't want to include authentication data in fragment */ if (auth_len != 0) { DceRpcCoAuthVerifier *auth_hdr; auth_len += sizeof(DceRpcCoAuthVerifier); /* This means the auth len was bogus */ if (auth_len > frag_len) { DCE2_Alert(sd, DCE2_EVENT__CO_FLEN_LT_SIZE, dce2_pdu_types[DceRpcCoPduType(co_hdr)], frag_len, auth_len); return; } auth_hdr = (DceRpcCoAuthVerifier *)(frag_ptr + (frag_len - auth_len)); auth_len += DceRpcCoAuthPad(auth_hdr); /* This means the auth pad len was bogus */ if (auth_len > frag_len) { DCE2_Alert(sd, DCE2_EVENT__CO_FLEN_LT_SIZE, dce2_pdu_types[DceRpcCoPduType(co_hdr)], frag_len, auth_len); return; } } DCE2_CoSetRopts(sd, cot, co_hdr); /* If we're configured to do defragmentation */ if (DCE2_GcDceDefrag()) DCE2_CoHandleFrag(sd, cot, co_hdr, frag_ptr, (uint16_t)(frag_len - auth_len)); }}/******************************************************************** * 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. Otherwise the bind ack might have been missed. Might as * well just move items from pending queue to list. * * 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_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; if (DCE2_QueueIsEmpty(cot->pending_ctx_ids)) return; if (frag_len < sizeof(DceRpcCoResponse)) { DCE2_Alert(sd, DCE2_EVENT__CO_FLEN_LT_SIZE, dce2_pdu_types[DceRpcCoPduType(co_hdr)], frag_len, sizeof(DceRpcCoResponse)); return; } ctx_id = DceRpcCoCtxIdResp(co_hdr, rhdr); 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 == NULL) { DCE2_Log("%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 */ DCE2_Free((void *)ctx_node, sizeof(DCE2_CoCtxIdNode), DCE2_MEM_TYPE__CO_CTX); return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -