📄 dce2_cl.c
字号:
* Checks to make sure header fields are sane. If they aren't, * alert on the header anomaly. If we've autodetected the session, * however, don't alert, but set a header anomaly flag, so we can * re-autodetect on the next go around. * * Arguments: * DCE2_SsnData * * Pointer to the session data structure. * DceRpcClHdr * * Pointer to the connectionless header in the packet. * * Returns: * DCE2_Ret * DCE2_RET__ERROR * We should not continue to inspect. * DCE2_RET__SUCCESS * Continue inspection. * ********************************************************************/static DCE2_Ret DCE2_ClHdrChecks(DCE2_SsnData *sd, const DceRpcClHdr *cl_hdr){ if (DceRpcClRpcVers(cl_hdr) != DCERPC_PROTO_MAJOR_VERS__4) { /* If we autodetected the session, we probably guessed wrong */ if (DCE2_SsnAutodetected(sd)) DCE2_SsnSetHdrAnomaly(sd); else DCE2_Alert(sd, DCE2_EVENT__CL_BAD_MAJ_VERSION, DceRpcClRpcVers(cl_hdr)); return DCE2_RET__ERROR; } if (DceRpcClPduType(cl_hdr) >= DCERPC_PDU_TYPE__MAX) { if (DCE2_SsnAutodetected(sd)) DCE2_SsnSetHdrAnomaly(sd); else DCE2_Alert(sd, DCE2_EVENT__CL_BAD_PDU_TYPE, DceRpcClPduType(cl_hdr)); return DCE2_RET__ERROR; } return DCE2_RET__SUCCESS;}/******************************************************************** * Function: DCE2_ClGetActTracker() * * Searches for activity tracker in list using activity UUID in * packet. If the activity tracker list is NULL, a new one is * created. If the activity tracker is not found, it is inserted * into the list. * * Arguments: * DCE2_ClTracker * * Pointer to the connectionless tracker. * DceRpcClHdr * * Pointer to the connectionless header in the packet. * * Returns: * DCE2_ClActTracker * * A valid pointer to an activity tracker on success. * NULL on error. * ********************************************************************/static DCE2_ClActTracker * DCE2_ClGetActTracker(DCE2_ClTracker *clt, DceRpcClHdr *cl_hdr){ DCE2_ClActTracker *at = NULL; /* Try to find a currently active activity tracker */ if (clt->act_trackers != NULL) { Uuid uuid; DCE2_CopyUuid(&uuid, &cl_hdr->act_id, DceRpcClByteOrder(cl_hdr)); at = DCE2_ListFind(clt->act_trackers, (void *)&uuid); } else { /* Create a new activity tracker list */ clt->act_trackers = DCE2_ListNew(DCE2_LIST_TYPE__SPLAYED, DCE2_UuidCompare, DCE2_ClActDataFree, DCE2_ClActKeyFree, DCE2_LIST_FLAG__NO_DUPS, DCE2_MEM_TYPE__CL_ACT); if (clt->act_trackers == NULL) return NULL; } /* Didn't find a currently active activity tracker */ if (at == NULL) { /* Insert a new activity tracker */ at = DCE2_ClInsertActTracker(clt, cl_hdr); if (at == NULL) return NULL; } return at;}/******************************************************************** * Function: DCE2_ClInsertActTracker() * * Creates and inserts a new activity tracker into a list. * * Arguments: * DCE2_ClTracker * * Pointer to connectionless tracker. * DceRpcClHdr * * Pointer to the connectionless header in the packet. * * Returns: * DCE2_ClActTracker * * A valid pointer to an activity tracker on success. * NULL on error. * ********************************************************************/static DCE2_ClActTracker * DCE2_ClInsertActTracker(DCE2_ClTracker *clt, DceRpcClHdr *cl_hdr){ Uuid *uuid = (Uuid *)DCE2_Alloc(sizeof(Uuid), DCE2_MEM_TYPE__CL_ACT); DCE2_ClActTracker *at; DCE2_Ret status; if (uuid == NULL) return NULL; at = (DCE2_ClActTracker *)DCE2_Alloc(sizeof(DCE2_ClActTracker), DCE2_MEM_TYPE__CL_ACT); if (at == NULL) { DCE2_Free((void *)uuid, sizeof(Uuid), DCE2_MEM_TYPE__CL_ACT); return NULL; } DCE2_CopyUuid(uuid, &cl_hdr->act_id, DceRpcClByteOrder(cl_hdr)); DCE2_CopyUuid(&at->act, &cl_hdr->act_id, DceRpcClByteOrder(cl_hdr)); status = DCE2_ListInsert(clt->act_trackers, (void *)uuid, (void *)at); if (status != DCE2_RET__SUCCESS) { DCE2_Free((void *)uuid, sizeof(Uuid), DCE2_MEM_TYPE__CL_ACT); DCE2_Free((void *)at, sizeof(DCE2_ClActTracker), DCE2_MEM_TYPE__CL_ACT); return NULL; } return at;}/******************************************************************** * Function: DCE2_ClRequest() * * Handles a client request. * * Arguments: * DCE2_SsnData * * Pointer to the session data structure. * DCE2_ClActTracker * * Pointer to the connectionless activity tracker. * DceRpcClHdr * * Pointer to the connectionless header in the packet. * const uint8_t * * Pointer to current position in the packet payload. * uint16_t * Length of packet payload left from current pointer * position. * * Returns: None * ********************************************************************/static void DCE2_ClRequest(DCE2_SsnData *sd, DCE2_ClActTracker *at, DceRpcClHdr *cl_hdr, const uint8_t *data_ptr, uint16_t data_len){ uint32_t seq_num = DceRpcClSeqNum(cl_hdr); DCE2_DEBUG_MSG(DCE2_DEBUG__CL, "Processing Request ...\n"); if (seq_num > at->seq_num) { /* This is the normal case where the sequence number is incremented * for each request. Set the new sequence number and mark it valid. */ at->seq_num = seq_num; at->seq_num_invalid = 0; /* If there are any fragments, the new sequence number invalidates * all of the frags that might be currently stored. */ DCE2_ClResetFragTracker(&at->frag_tracker); } else if ((seq_num < at->seq_num) || at->seq_num_invalid) {#if 0 /* If we get a seqence number less than what we're at, the * server won't look at it. If we get the same sequence number, * but we've already processed a previous request, it's bad. * Fragments will have the same sequence number, but we won't * mark the seq number invalid until we've gotten all of them. */ /* Comment for now since we're not able to detect retransmits */ DCE2_Alert(sd, DCE2_EVENT__CL_BAD_SEQ_NUM, dce2_pdu_types[DceRpcClPduType(cl_hdr)]);#endif return; } DCE2_ResetRopts(&sd->ropts); if (DceRpcClFrag(cl_hdr)) /* It's a frag */ { dce2_stats.cl_fragments++; DCE2_ClHandleFrag(sd, at, cl_hdr, data_ptr, data_len); } else /* It's a full request */ { if ((at->frag_tracker.frags != NULL) && !DCE2_ListIsEmpty(at->frag_tracker.frags)) { /* If we get a full request, i.e. not a frag, any frags * we have collected are invalidated */ DCE2_ClResetFragTracker(&at->frag_tracker); } else if (seq_num != DCE2_CL__MAX_SEQ_NUM) { /* This sequence number is now invalid. 0xffffffff is the end of * the sequence number space and can be reused */ at->seq_num_invalid = 1; } else { /* Got the last sequence number in the sequence number space */ dce2_stats.cl_max_seqnum++; } /* Cache relevant values for rule option processing */ sd->ropts.first_frag = 1; DCE2_CopyUuid(&sd->ropts.iface, &cl_hdr->if_id, DceRpcClByteOrder(cl_hdr)); sd->ropts.iface_vers = DceRpcClIfaceVers(cl_hdr); sd->ropts.hdr_byte_order = DceRpcClByteOrder(cl_hdr); sd->ropts.data_byte_order = DceRpcClByteOrder(cl_hdr); sd->ropts.opnum = DceRpcClOpnum(cl_hdr); sd->ropts.stub_data = (uint8_t *)cl_hdr + sizeof(DceRpcClHdr); DCE2_Detect(sd); }}/******************************************************************** * Function: DCE2_ClHandleFrag() * * Handles connectionless fragments. Creates a new fragment list * if necessary and inserts fragment into list. Sets rule option * values based on the fragment. * * Arguments: * DCE2_SsnData * * Pointer to the session data structure. * DCE2_ClActTracker * * Pointer to the connectionless activity tracker. * DceRpcClHdr * * Pointer to the connectionless header in the packet. * const uint8_t * * Pointer to current position in the packet payload. * uint16_t * Length of packet payload left from current pointer * position. * * Returns: None * ********************************************************************/static void DCE2_ClHandleFrag(DCE2_SsnData *sd, DCE2_ClActTracker *at, DceRpcClHdr *cl_hdr, const uint8_t *data_ptr, uint16_t data_len){ DCE2_ClFragTracker *ft = &at->frag_tracker; DCE2_ClFragNode *fn; uint16_t frag_len; int status; /* If the frag length is less than data length there might be authentication * data that we don't want to include, otherwise just set to data len */ if (DceRpcClLen(cl_hdr) < data_len) frag_len = DceRpcClLen(cl_hdr); else frag_len = data_len; if (frag_len == 0) return; if (frag_len > dce2_stats.cl_max_frag_size) dce2_stats.cl_max_frag_size = frag_len; if (ft->frags == NULL) { /* Create new list if we don't have one already */ ft->frags = DCE2_ListNew(DCE2_LIST_TYPE__SORTED, DCE2_ClFragCompare, DCE2_ClFragDataFree, NULL, DCE2_LIST_FLAG__NO_DUPS | DCE2_LIST_FLAG__INS_TAIL, DCE2_MEM_TYPE__CL_FRAG); if (ft->frags == NULL) return; } else { /* If we already have a fragment in the list with the same fragment number, * that fragment will take precedence over this fragment and this fragment * will not be used by the server */ fn = (DCE2_ClFragNode *)DCE2_ListFind(ft->frags, (void *)(uintptr_t)DceRpcClFragNum(cl_hdr)); if (fn != NULL) return; } /* Create a new frag node to insert into the list */ fn = (DCE2_ClFragNode *)DCE2_Alloc(sizeof(DCE2_ClFragNode), DCE2_MEM_TYPE__CL_FRAG); if (fn == NULL) { DCE2_ClFragReassemble(sd, at, cl_hdr); return; } fn->frag_number = DceRpcClFragNum(cl_hdr); fn->frag_len = frag_len; /* Allocate space for the fragment data */ fn->frag_data = (uint8_t *)DCE2_Alloc(frag_len, DCE2_MEM_TYPE__CL_FRAG); if (fn->frag_data == NULL) { DCE2_Free((void *)fn, sizeof(DCE2_ClFragNode), DCE2_MEM_TYPE__CL_FRAG); DCE2_ClFragReassemble(sd, at, cl_hdr); return; } /* Copy the fragment data in the packet to the space just allocated */ status = DCE2_Memcpy(fn->frag_data, data_ptr, frag_len, fn->frag_data, fn->frag_data + frag_len); if (status != DCE2_RET__SUCCESS) { DCE2_Free((void *)fn->frag_data, frag_len, DCE2_MEM_TYPE__CL_FRAG); DCE2_Free((void *)fn, sizeof(DCE2_ClFragNode), DCE2_MEM_TYPE__CL_FRAG);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -