📄 dce2_cl.c
字号:
/**************************************************************************** * Copyright (C) 2008-2008 Sourcefire,Inc * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License Version 2 as * published by the Free Software Foundation. You may not use, modify or * distribute this program under any other version of the GNU General * Public License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * **************************************************************************** * Module for handling connectionless DCE/RPC processing. Provides * functionality for tracking sub-sessions or activities within a * connectionless conversation and for tracking and reassembling fragments * within each activity. Also sets appropriate data for use with * preprocessor rule options. * * 8/17/2008 - Initial implementation ... Todd Wease <twease@sourcefire.com> * ****************************************************************************/#include "dce2_cl.h"#include "snort_dce2.h"#include "dce2_list.h"#include "dce2_memory.h"#include "dce2_utils.h"#include "dce2_stats.h"#include "dce2_session.h"#include "dce2_event.h"#include "dcerpc.h"#include "sf_types.h"#include "debug.h"#include "sf_snort_packet.h"#include "sf_dynamic_preprocessor.h"/******************************************************************** * Global variables ********************************************************************/static uint8_t dce2_cl_rbuf[IP_MAXPKT];/******************************************************************** * Extern variables ********************************************************************/extern DynamicPreprocessorData _dpd;extern DCE2_Stats dce2_stats;extern char *dce2_pdu_types[DCERPC_PDU_TYPE__MAX];/******************************************************************** * Macros ********************************************************************/#define DCE2_CL__MAX_SEQ_NUM UINT32_MAX/******************************************************************** * Structures ********************************************************************/typedef struct _DCE2_ClFragNode{ uint32_t frag_number; uint16_t frag_len; uint8_t *frag_data;} DCE2_ClFragNode;typedef struct _DCE2_ClFragTracker{ Uuid iface; /* only set on first fragment received */ uint32_t iface_vers; /* only set on first fragment received */ int opnum; /* set to that of first fragment, i.e fragment number == 0. * initialize to a sentinel */ int data_byte_order; /* set to that of first fragment, i.e fragment number == 0. * initialize to sentinel */ DCE2_List *frags; /* sorted by fragment number */ int num_expected_frags; /* set when we get last frag */} DCE2_ClFragTracker;typedef struct _DCE2_ClActTracker{ Uuid act; uint32_t seq_num; uint8_t seq_num_invalid; DCE2_ClFragTracker frag_tracker;#if 0 /* Not currently used. These are related to getting a sequence number that * is at the end of the sequence number space */ uint32_t last_pkt_sec; uint8_t no_frags; uint8_t no_requests;#endif} DCE2_ClActTracker;/******************************************************************** * Private function prototypes ********************************************************************/static DCE2_Ret DCE2_ClHdrChecks(DCE2_SsnData *, const DceRpcClHdr *);static DCE2_ClActTracker * DCE2_ClGetActTracker(DCE2_ClTracker *, DceRpcClHdr *);static DCE2_ClActTracker * DCE2_ClInsertActTracker(DCE2_ClTracker *, DceRpcClHdr *);static void DCE2_ClRequest(DCE2_SsnData *, DCE2_ClActTracker *, DceRpcClHdr *, const uint8_t *, uint16_t);static void DCE2_ClHandleFrag(DCE2_SsnData *, DCE2_ClActTracker *, DceRpcClHdr *, const uint8_t *, uint16_t);static void DCE2_ClFragReassemble(DCE2_SsnData*, DCE2_ClActTracker *, const DceRpcClHdr *);static void DCE2_ClResetFragTracker(DCE2_ClFragTracker *);static INLINE void DCE2_ClSetRdata(DCE2_ClActTracker *, const DceRpcClHdr *, uint8_t *, uint16_t);/* Callbacks */static int DCE2_ClFragCompare(const void *, const void *);static void DCE2_ClActDataFree(void *);static void DCE2_ClActKeyFree(void *);static void DCE2_ClFragDataFree(void *);/******************************************************************** * Function: DCE2_ClInitRdata() * * Initializes static values in the global CL data reassembly * buffer. These values should never need to be changed after * this initialization. * * Arguments: * uint8_t * * Pointer to the data reassembly buffer. * * Returns: None * ********************************************************************/void DCE2_ClInitRdata(uint8_t *buf){ DceRpcClHdr *cl_hdr = (DceRpcClHdr *)buf; /* Set some relevant fields. These should never get reset */ cl_hdr->rpc_vers = DCERPC_PROTO_MAJOR_VERS__4; cl_hdr->ptype = DCERPC_PDU_TYPE__REQUEST; cl_hdr->drep[0] = 0x10; /* Little endian */}/******************************************************************** * Function: DCE2_ClSetRdata() * * Sets relevant data fields in the reassembly packet. * * Arguments: * DCE2_ClActTracker * * Pointer to the activity tracker associated with the * reassemble packet. * DceRpcClHdr * * Pointer to the connectionless header in the wire packet. * uint8_t * * Pointer to the start of the reassembly buffer. * uint16_t * The length of the stub data. * * Returns: None * ********************************************************************/static INLINE void DCE2_ClSetRdata(DCE2_ClActTracker *at, const DceRpcClHdr *pkt_cl_hdr, uint8_t *cl_ptr, uint16_t stub_len){ DCE2_ClFragTracker *ft = &at->frag_tracker; DceRpcClHdr *cl_hdr = (DceRpcClHdr *)cl_ptr; uint16_t opnum = (ft->opnum != DCE2_SENTINEL) ? (uint16_t)ft->opnum : DceRpcClOpnum(pkt_cl_hdr); cl_hdr->len = DceRpcHtons(stub_len, DCERPC_BO_FLAG__LITTLE_ENDIAN); DCE2_CopyUuid(&cl_hdr->object, &pkt_cl_hdr->object, DceRpcClByteOrder(cl_hdr)); DCE2_CopyUuid(&cl_hdr->if_id, &ft->iface, DCERPC_BO_FLAG__LITTLE_ENDIAN); DCE2_CopyUuid(&cl_hdr->act_id, &at->act, DCERPC_BO_FLAG__LITTLE_ENDIAN); cl_hdr->if_vers = DceRpcHtonl(ft->iface_vers, DCERPC_BO_FLAG__LITTLE_ENDIAN); cl_hdr->opnum = DceRpcHtons(opnum, DCERPC_BO_FLAG__LITTLE_ENDIAN);}/******************************************************************** * Function: DCE2_ClProcess() * * Main entry point for connectionless DCE/RPC processing. Gets * the activity tracker associated with this session and passes * along to client or server handling. * * Arguments: * DCE2_SsnData * * Pointer to the session data structure. * DCE2_ClTracker * * Pointer to the connectionless tracker structure. * * Returns: None * ********************************************************************/void DCE2_ClProcess(DCE2_SsnData *sd, DCE2_ClTracker *clt){ DceRpcClHdr *cl_hdr; DCE2_ClActTracker *at; const uint8_t *data_ptr = sd->wire_pkt->payload; uint16_t data_len = sd->wire_pkt->payload_size; DCE2_DEBUG_MSG(DCE2_DEBUG__CL, "Cl processing ...\n"); dce2_stats.cl_pkts++; if (data_len < sizeof(DceRpcClHdr)) { if (DCE2_SsnAutodetected(sd)) DCE2_SsnSetHdrAnomaly(sd); else DCE2_Alert(sd, DCE2_EVENT__CL_DATA_LT_HDR, data_len, sizeof(DceRpcClHdr)); return; } cl_hdr = (DceRpcClHdr *)data_ptr; DCE2_MOVE(data_ptr, data_len, sizeof(DceRpcClHdr)); if (DCE2_ClHdrChecks(sd, cl_hdr) != DCE2_RET__SUCCESS) return; at = DCE2_ClGetActTracker(clt, cl_hdr); if (at == NULL) return; if (DCE2_SsnFromClient(sd->wire_pkt)) { switch (DceRpcClPduType(cl_hdr)) { case DCERPC_PDU_TYPE__REQUEST: DCE2_DEBUG_MSG(DCE2_DEBUG__CL, "Request\n"); dce2_stats.cl_request++; DCE2_ClRequest(sd, at, cl_hdr, data_ptr, data_len); break; case DCERPC_PDU_TYPE__ACK: DCE2_DEBUG_MSG(DCE2_DEBUG__CL, "Ack\n"); dce2_stats.cl_ack++; break; case DCERPC_PDU_TYPE__CL_CANCEL: DCE2_DEBUG_MSG(DCE2_DEBUG__CL, "Cancel\n"); dce2_stats.cl_cancel++; break; case DCERPC_PDU_TYPE__FACK: DCE2_DEBUG_MSG(DCE2_DEBUG__CL, "Fack\n"); dce2_stats.cl_cli_fack++; break; case DCERPC_PDU_TYPE__PING: DCE2_DEBUG_MSG(DCE2_DEBUG__CL, "Ping\n"); dce2_stats.cl_ping++; break; case DCERPC_PDU_TYPE__RESPONSE: DCE2_DEBUG_MSG(DCE2_DEBUG__CL, "Response from client. Changing stream direction."); _dpd.streamAPI->update_direction(sd->wire_pkt->stream_session_ptr, SSN_DIR_RESPONDER, GET_SRC_IP(((SFSnortPacket *)sd->wire_pkt)), sd->wire_pkt->src_port); break; default: DCE2_DEBUG_MSG(DCE2_DEBUG__CL, "Other pdu type\n"); dce2_stats.cl_other_req++; break; } } else { switch (DceRpcClPduType(cl_hdr)) { case DCERPC_PDU_TYPE__RESPONSE: DCE2_DEBUG_MSG(DCE2_DEBUG__CL, "Response\n"); dce2_stats.cl_response++; break; case DCERPC_PDU_TYPE__REJECT: DCE2_DEBUG_MSG(DCE2_DEBUG__CL, "Reject\n"); dce2_stats.cl_reject++; if (DceRpcClSeqNum(cl_hdr) == at->seq_num) { DCE2_ClResetFragTracker(&at->frag_tracker); at->seq_num_invalid = 1; } break; case DCERPC_PDU_TYPE__CANCEL_ACK: DCE2_DEBUG_MSG(DCE2_DEBUG__CL, "Cancel Ack\n"); dce2_stats.cl_cancel_ack++; break; case DCERPC_PDU_TYPE__FACK: DCE2_DEBUG_MSG(DCE2_DEBUG__CL, "Fack\n"); dce2_stats.cl_srv_fack++; break; case DCERPC_PDU_TYPE__FAULT: DCE2_DEBUG_MSG(DCE2_DEBUG__CL, "Fault\n"); dce2_stats.cl_fault++; break; case DCERPC_PDU_TYPE__NOCALL: DCE2_DEBUG_MSG(DCE2_DEBUG__CL, "No call\n"); dce2_stats.cl_nocall++; break; case DCERPC_PDU_TYPE__WORKING: DCE2_DEBUG_MSG(DCE2_DEBUG__CL, "Working\n"); dce2_stats.cl_working++; break; default: DCE2_DEBUG_MSG(DCE2_DEBUG__CL, "Other pdu type\n"); dce2_stats.cl_other_resp++; break; } }}/******************************************************************** * Function: DCE2_ClHdrChecks() *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -