#define DEBUG_LOGGER 0x0040000000000000LL
#define DEBUG_DCE_TCP 0x0080000000000000LL
#define DEBUG_DCE_SMB 0x0100000000000000LL
+#define DEBUG_DCE_COMMON 0x0200000000000000LL
#ifdef PIGLET
-#define DEBUG_PIGLET 0x0200000000000000LL
+#define DEBUG_PIGLET 0x0400000000000000LL
#endif
set( FILE_LIST
+ dce_co.cc
dce_co.h
dce_common.cc
dce_common.h
file_list = \
+dce_co.cc \
dce_co.h \
dce_common.cc \
dce_common.h \
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2016-2016 Cisco and/or its affiliates. All rights reserved.
+//
+// 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.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// dce_co.cc author Rashmi Pitre <rrp@cisco.com>
+// based on work by Todd Wease
+
+#include "dce_co.h"
+
+/********************************************************************
+ * Function: DCE2_CoInitTracker()
+ *
+ * Initializes fields in the connection-oriented tracker to
+ * sentinels. Many decisions are made based on whether or not
+ * these fields have been set.
+ *
+ ********************************************************************/
+void DCE2_CoInitTracker(DCE2_CoTracker *cot)
+{
+ if (cot == NULL)
+ return;
+
+ cot->max_xmit_frag = DCE2_SENTINEL;
+ cot->data_byte_order = DCE2_SENTINEL;
+ cot->ctx_id = DCE2_SENTINEL;
+ cot->opnum = DCE2_SENTINEL;
+ cot->call_id = DCE2_SENTINEL;
+ cot->stub_data = NULL;
+ cot->got_bind = 0;
+
+ cot->frag_tracker.opnum = DCE2_SENTINEL;
+ cot->frag_tracker.ctx_id = DCE2_SENTINEL;
+ cot->frag_tracker.expected_call_id = DCE2_SENTINEL;
+ cot->frag_tracker.expected_opnum = DCE2_SENTINEL;
+ cot->frag_tracker.expected_ctx_id = DCE2_SENTINEL;
+}
+
#define DCE_CO_H
#include "dce_common.h"
+#include "dce_list.h"
#define DCE2_CO_BAD_MAJOR_VERSION 27
#define DCE2_CO_BAD_MINOR_VERSION 28
#pragma pack()
+struct DCE2_CoFragTracker
+{
+ DCE2_Buffer* cli_stub_buf;
+ DCE2_Buffer* srv_stub_buf;
+
+ int opnum; /* Opnum that is ultimatley used for request */
+ int ctx_id; /* Context id that is ultimatley used for request */
+
+ /* These are set on a first fragment received */
+ int expected_call_id; /* Expected call id for fragments */
+ int expected_opnum; /* Expected call id for fragments */
+ int expected_ctx_id; /* Expected call id for fragments */
+};
+
+struct DCE2_CoSeg
+{
+ DCE2_Buffer* buf;
+
+ /* If there is enough data in segmentation buffer for header,
+ * this will be set to the frag length in the header */
+ uint16_t frag_len;
+};
+
+struct DCE2_CoTracker
+{
+ DCE2_List* ctx_ids; /* splayed list so most recently used goes to front of list */
+ int got_bind; /* got an accepted bind */
+
+ /* Queue of pending client bind or alter context request context items
+ * Since the actual context id number doesn't have to occur sequentially
+ * in the context list in the client packet, need to keep track to match
+ * up server response since server doesn't reply with actual context id
+ * numbers, but in the order they were in the client packet */
+ DCE2_Queue* pending_ctx_ids;
+
+ /* Keeps track of fragmentation buffer and frag specfic data */
+ DCE2_CoFragTracker frag_tracker;
+
+ int max_xmit_frag; /* The maximum negotiated size of a client request */
+ int data_byte_order; /* Depending on policy is from bind or request */
+ int ctx_id; /* The current context id of the request */
+ int opnum; /* The current opnum of the request */
+ int call_id; /* The current call id of the request */
+ const uint8_t* stub_data; /* Current pointer to stub data in the request */
+
+ /* For transport segmentation */
+ DCE2_CoSeg cli_seg;
+ DCE2_CoSeg srv_seg;
+};
+
inline uint8_t DceRpcCoVersMaj(const DceRpcCoHdr* co)
{
return co->pversion.major;
return DceRpcNtohs(&co->frag_length, DceRpcCoByteOrder(co));
}
+void DCE2_CoInitTracker(DCE2_CoTracker*);
+
#endif
#include "log/messages.h"
#include "main/snort_debug.h"
-const char* dce2_get_policy_name(DCE2_POLICY policy)
+const char* dce2_get_policy_name(DCE2_Policy policy)
{
const char* policyStr = nullptr;
switch (policy)
common.max_frag_len = v.get_long();
else if ( v.is("policy") )
- common.policy = (DCE2_POLICY)v.get_long();
+ common.policy = (DCE2_Policy)v.get_long();
else
return false;
return true;
dce2_get_policy_name(common.policy));
}
-bool dce2_paf_abort(Flow* flow)
+bool dce2_paf_abort(Flow* flow, DCE2_SsnData* sd)
{
if (flow->get_session_flags() & SSNFLAG_MIDSTREAM)
{
- DebugMessage(DEBUG_DCE_TCP,
+ DebugMessage(DEBUG_DCE_COMMON,
"Aborting PAF because of midstream pickup.\n");
return true;
}
else if (!(flow->get_session_flags() & SSNFLAG_ESTABLISHED))
{
- DebugMessage(DEBUG_DCE_TCP,
+ DebugMessage(DEBUG_DCE_COMMON,
"Aborting PAF because of unestablished session.\n");
return true;
}
- // FIXIT-M add the remaining checks
+
+ if ((sd != NULL) && DCE2_SsnNoInspect(sd))
+ {
+ DebugMessage(DEBUG_DCE_COMMON, "Aborting PAF because of session data check.\n");
+ return true;
+ }
return false;
}
#include "main/snort_types.h"
#include "framework/module.h"
#include "framework/inspector.h"
+#include "protocols/packet.h"
extern const InspectApi dce2_smb_api;
extern const InspectApi dce2_tcp_api;
#define GID_DCE2 145
-enum DCE2_POLICY
+enum DCE2_Policy
{
DCE2_POLICY__WIN2000 = 0,
DCE2_POLICY__WINXP,
{
bool disable_defrag;
uint16_t max_frag_len;
- DCE2_POLICY policy;
+ DCE2_Policy policy;
};
#define DCE2_DEBUG__PAF_END_MSG "=========================================================="
const uint8_t* stub_data; /* Set to NULL if not applicable */
};
+enum DCE2_SsnFlag
+{
+ DCE2_SSN_FLAG__NONE = 0x0000,
+ DCE2_SSN_FLAG__AUTODETECTED = 0x0001,
+ DCE2_SSN_FLAG__NO_INSPECT = 0x0002,
+ DCE2_SSN_FLAG__ALL = 0xffff
+};
+
struct DCE2_SsnData
{
- DCE2_POLICY server_policy;
- DCE2_POLICY client_policy;
+ DCE2_TransType trans;
+ DCE2_Policy server_policy;
+ DCE2_Policy client_policy;
int flags;
const Packet* wire_pkt;
uint64_t alert_mask;
return ((value & 0xff00) >> 8) | ((value & 0x00ff) << 8);
}
+inline void DCE2_ResetRopts(DCE2_Roptions* ropts)
+{
+ ropts->first_frag = DCE2_SENTINEL;
+ ropts->opnum = DCE2_SENTINEL;
+ ropts->hdr_byte_order = DCE2_SENTINEL;
+ ropts->data_byte_order = DCE2_SENTINEL;
+ ropts->stub_data = NULL;
+}
+
+inline void DCE2_SsnSetAutodetected(DCE2_SsnData* sd, Packet* p)
+{
+ sd->flags |= DCE2_SSN_FLAG__AUTODETECTED;
+ sd->autodetect_dir = p->packet_flags & (PKT_FROM_CLIENT | PKT_FROM_SERVER);
+}
+
+inline int DCE2_SsnAutodetectDir(DCE2_SsnData* sd)
+{
+ return sd->autodetect_dir;
+}
+
+inline int DCE2_SsnAutodetected(DCE2_SsnData* sd)
+{
+ return sd->flags & DCE2_SSN_FLAG__AUTODETECTED;
+}
+
+inline void DCE2_SsnClearAutodetected(DCE2_SsnData* sd)
+{
+ sd->flags &= ~DCE2_SSN_FLAG__AUTODETECTED;
+ sd->autodetect_dir = 0;
+}
+
+inline void DCE2_SsnSetNoInspect(DCE2_SsnData* sd)
+{
+ sd->flags |= DCE2_SSN_FLAG__NO_INSPECT;
+}
+
+inline int DCE2_SsnNoInspect(DCE2_SsnData* sd)
+{
+ return sd->flags & DCE2_SSN_FLAG__NO_INSPECT;
+}
+
bool dce2_set_common_config(Value&, dce2CommonProtoConf&);
void print_dce2_common_config(dce2CommonProtoConf&);
-bool dce2_paf_abort(Flow*);
+bool dce2_paf_abort(Flow*, DCE2_SsnData*);
#endif
*
****************************************************************************/
-#ifndef _DCE_LIST_H_
-#define _DCE_LIST_H_
+#ifndef DCE_LIST_H
+#define DCE_LIST_H
#include "dce_utils.h"
struct DCE2_ListNode* prev;
};
+struct DCE2_QueueNode
+{
+ void* data;
+ DCE2_QueueNode* prev;
+ DCE2_QueueNode* next;
+};
+
+typedef DCE2_ListDataFree DCE2_QueueDataFree;
+
+struct DCE2_Queue
+{
+ uint32_t num_nodes;
+ DCE2_QueueDataFree data_free;
+ DCE2_QueueNode* current;
+ DCE2_QueueNode* head;
+ DCE2_QueueNode* tail;
+ DCE2_QueueNode* next;
+ DCE2_QueueNode* prev;
+};
+
/********************************************************************
* Public function prototypes
********************************************************************/
return false;
}
-#endif
+#endif
+
#include "dce_smb_module.h"
#include "dce_list.h"
#include "main/snort_debug.h"
+#include "file_api/file_service.h"
THREAD_LOCAL dce2SmbStats dce2_smb_stats;
THREAD_LOCAL ProfileStats dce2_smb_pstat_main;
THREAD_LOCAL ProfileStats dce2_smb_pstat_session;
THREAD_LOCAL ProfileStats dce2_smb_pstat_new_session;
-THREAD_LOCAL ProfileStats dce2_smb_pstat_session_state;
THREAD_LOCAL ProfileStats dce2_smb_pstat_detect;
THREAD_LOCAL ProfileStats dce2_smb_pstat_log;
THREAD_LOCAL ProfileStats dce2_smb_pstat_co_seg;
THREAD_LOCAL ProfileStats dce2_smb_pstat_smb_fingerprint;
THREAD_LOCAL ProfileStats dce2_smb_pstat_smb_negotiate;
+Dce2SmbFlowData::Dce2SmbFlowData() : FlowData(flow_id)
+{
+}
+
unsigned Dce2SmbFlowData::flow_id = 0;
DCE2_SmbSsnData* get_dce2_smb_session_data(Flow* flow)
return fd ? &fd->dce2_smb_session : nullptr;
}
+static DCE2_SmbSsnData* set_new_dce2_smb_session(Packet* p)
+{
+ Dce2SmbFlowData* fd = new Dce2SmbFlowData;
+
+ p->flow->set_application_data(fd);
+ return(&fd->dce2_smb_session);
+}
+
+static DCE2_SmbSsnData* dce2_create_new_smb_session(Packet* p, dce2SmbProtoConf config)
+{
+ DCE2_SmbSsnData* dce2_smb_sess = NULL;
+ Profile profile(dce2_smb_pstat_new_session);
+
+ if (DCE2_SmbAutodetect(p))
+ {
+ DebugMessage(DEBUG_DCE_SMB, "DCE over SMB packet detected\n");
+ DebugMessage(DEBUG_DCE_SMB, "Creating new session\n");
+
+ dce2_smb_sess = set_new_dce2_smb_session(p);
+ if ( dce2_smb_sess )
+ {
+ dce2_smb_sess->dialect_index = DCE2_SENTINEL;
+ dce2_smb_sess->max_outstanding_requests = 10; // Until Negotiate/SessionSetupAndX
+ dce2_smb_sess->cli_data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
+ dce2_smb_sess->srv_data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
+ dce2_smb_sess->pdu_state = DCE2_SMB_PDU_STATE__COMMAND;
+ dce2_smb_sess->uid = DCE2_SENTINEL;
+ dce2_smb_sess->tid = DCE2_SENTINEL;
+ dce2_smb_sess->ftracker.fid = DCE2_SENTINEL;
+ dce2_smb_sess->rtracker.mid = DCE2_SENTINEL;
+ dce2_smb_sess->max_file_depth = FileService::get_max_file_depth();
+
+ DCE2_ResetRopts(&dce2_smb_sess->sd.ropts);
+
+ dce2_smb_stats.smb_sessions++;
+ DebugFormat(DEBUG_DCE_SMB,"Created (%p)\n", (void*)dce2_smb_sess);
+
+ dce2_smb_sess->sd.trans = DCE2_TRANS_TYPE__SMB;
+ dce2_smb_sess->sd.server_policy = config.common.policy;
+ dce2_smb_sess->sd.client_policy = DCE2_POLICY__WINXP;
+ dce2_smb_sess->sd.wire_pkt = p;
+
+ DCE2_SsnSetAutodetected(&dce2_smb_sess->sd, p);
+ }
+ }
+
+ return dce2_smb_sess;
+}
+
+DCE2_SmbSsnData* dce2_handle_smb_session(Packet* p, dce2SmbProtoConf& config)
+{
+ Profile profile(dce2_smb_pstat_session);
+
+ DCE2_SmbSsnData* dce2_smb_sess = get_dce2_smb_session_data(p->flow);
+
+ if (dce2_smb_sess == nullptr)
+ {
+ dce2_smb_sess = dce2_create_new_smb_session(p, config);
+ }
+ else
+ {
+ DCE2_SsnData* sd = (DCE2_SsnData*)dce2_smb_sess;
+ sd->wire_pkt = p;
+
+ if (DCE2_SsnAutodetected(sd) && !(p->packet_flags & sd->autodetect_dir))
+ {
+ /* Try to autodetect in opposite direction */
+ if (!DCE2_SmbAutodetect(p))
+ {
+ DebugMessage(DEBUG_DCE_SMB, "Bad autodetect.\n");
+ DCE2_SsnNoInspect(sd);
+ dce2_smb_stats.sessions_aborted++;
+ dce2_smb_stats.bad_autodetects++;
+ return NULL;
+ }
+ DCE2_SsnClearAutodetected(sd);
+ }
+ }
+ DebugFormat(DEBUG_DCE_SMB, "Session pointer: %p\n", (void*)dce2_smb_sess);
+
+ // FIXIT-M add remaining session handling logic
+
+ return dce2_smb_sess;
+}
+
//-------------------------------------------------------------------------
// class stuff
//-------------------------------------------------------------------------
void Dce2Smb::eval(Packet* p)
{
- DCE2_SmbSsnData* dce2_sess = get_dce2_smb_session_data(p->flow);
+ DCE2_SmbSsnData* dce2_smb_sess;
+ Profile profile(dce2_smb_pstat_main);
+
+ assert(p->has_tcp_data());
+ assert(p->flow);
- if (dce2_sess == nullptr)
+ if (p->flow->get_session_flags() & SSNFLAG_MIDSTREAM)
{
- /*Check if it is a DCE2 over SMB packet*/
+ DebugMessage(DEBUG_DCE_SMB,
+ "Midstream - not inspecting.\n");
+ return;
+ }
- if (DCE2_SmbAutodetect(p))
- {
- DebugMessage(DEBUG_DCE_SMB, "DCE over SMB packet detected\n");
- }
+ dce2_smb_sess = dce2_handle_smb_session(p, config);
+ if (!dce2_smb_sess)
+ {
+ return;
}
+ dce2_smb_stats.smb_pkts++;
}
//-------------------------------------------------------------------------
delete m;
}
+static void dce2_smb_init()
+{
+ Dce2SmbFlowData::init();
+}
+
static Inspector* dce2_smb_ctor(Module* m)
{
Dce2SmbModule* mod = (Dce2SmbModule*)m;
(uint16_t)PktType::PDU,
nullptr, // buffers
"dce_smb",
- nullptr,
+ dce2_smb_init,
nullptr, // pterm
nullptr, // tinit
nullptr, // tterm
#define DCE_SMB_H
#include "dce_common.h"
+#include "dce_co.h"
#include "protocols/packet.h"
#include "profiler/profiler.h"
#include "framework/counts.h"
extern THREAD_LOCAL ProfileStats dce2_smb_pstat_main;
extern THREAD_LOCAL ProfileStats dce2_smb_pstat_session;
extern THREAD_LOCAL ProfileStats dce2_smb_pstat_new_session;
-extern THREAD_LOCAL ProfileStats dce2_smb_pstat_session_state;
extern THREAD_LOCAL ProfileStats dce2_smb_pstat_detect;
extern THREAD_LOCAL ProfileStats dce2_smb_pstat_log;
extern THREAD_LOCAL ProfileStats dce2_smb_pstat_co_seg;
uint8_t type;
uint8_t flags; /* Treat flags as the upper byte to length */
uint16_t length;
-} ;
+};
struct SmbNtHdr
{
};
#pragma pack()
+enum DCE2_SmbSsnState
+{
+ DCE2_SMB_SSN_STATE__START = 0x00,
+ DCE2_SMB_SSN_STATE__NEGOTIATED = 0x01,
+ DCE2_SMB_SSN_STATE__FP_CLIENT = 0x02, // Fingerprinted client
+ DCE2_SMB_SSN_STATE__FP_SERVER = 0x04 // Fingerprinted server
+};
+
+enum DCE2_SmbDataState
+{
+ DCE2_SMB_DATA_STATE__NETBIOS_HEADER,
+ DCE2_SMB_DATA_STATE__SMB_HEADER,
+ DCE2_SMB_DATA_STATE__NETBIOS_PDU
+};
+
+enum DCE2_SmbPduState
+{
+ DCE2_SMB_PDU_STATE__COMMAND,
+ DCE2_SMB_PDU_STATE__RAW_DATA
+};
+
+enum DCE2_SmbFileDirection
+{
+ DCE2_SMB_FILE_DIRECTION__UNKNOWN = 0,
+ DCE2_SMB_FILE_DIRECTION__UPLOAD,
+ DCE2_SMB_FILE_DIRECTION__DOWNLOAD
+};
+
+struct DCE2_SmbWriteAndXRaw
+{
+ int remaining; // A signed integer so it can be negative
+ DCE2_Buffer* buf;
+};
+
+struct DCE2_SmbFileChunk
+{
+ uint64_t offset;
+ uint32_t length;
+ uint8_t* data;
+};
+
+struct DCE2_SmbFileTracker
+{
+ int fid; // A signed integer so it can be set to sentinel
+ uint16_t uid;
+ uint16_t tid;
+ bool is_ipc;
+ char* file_name;
+
+ union
+ {
+ struct
+ {
+ // If pipe has been set to byte mode via TRANS_SET_NMPIPE_STATE
+ bool byte_mode;
+
+ // For Windows 2000
+ bool used;
+
+ // For WriteAndX requests that use raw mode flag
+ // Windows only
+ DCE2_SmbWriteAndXRaw* writex_raw;
+
+ // Connection-oriented DCE/RPC tracker
+ DCE2_CoTracker* co_tracker;
+ } nmpipe;
+
+ struct
+ {
+ uint64_t file_size;
+ uint64_t file_offset;
+ uint64_t bytes_processed;
+ DCE2_List* file_chunks;
+ uint32_t bytes_queued;
+ DCE2_SmbFileDirection file_direction;
+ bool sequential_only;
+ } file;
+ } tracker;
+
+#define fp_byte_mode tracker.nmpipe.byte_mode
+#define fp_used tracker.nmpipe.used
+#define fp_writex_raw tracker.nmpipe.writex_raw
+#define fp_co_tracker tracker.nmpipe.co_tracker
+#define ff_file_size tracker.file.file_size
+#define ff_file_offset tracker.file.file_offset
+#define ff_bytes_processed tracker.file.bytes_processed
+#define ff_file_direction tracker.file.file_direction
+#define ff_file_chunks tracker.file.file_chunks
+#define ff_bytes_queued tracker.file.bytes_queued
+#define ff_sequential_only tracker.file.sequential_only
+};
+
+struct DCE2_SmbTransactionTracker
+{
+ int smb_type;
+ uint8_t subcom;
+ bool one_way;
+ bool disconnect_tid;
+ bool pipe_byte_mode;
+ uint32_t tdcnt;
+ uint32_t dsent;
+ DCE2_Buffer* dbuf;
+ uint32_t tpcnt;
+ uint32_t psent;
+ DCE2_Buffer* pbuf;
+ // For Transaction2/Query File Information
+ uint16_t info_level;
+};
+
+struct DCE2_SmbRequestTracker
+{
+ int smb_com;
+
+ int mid; // A signed integer so it can be set to sentinel
+ uint16_t uid;
+ uint16_t tid;
+ uint16_t pid;
+
+ // For WriteRaw
+ bool writeraw_writethrough;
+ uint32_t writeraw_remaining;
+
+ // For Transaction/Transaction2/NtTransact
+ DCE2_SmbTransactionTracker ttracker;
+
+ // Client can chain a write to an open. Need to write data, but also
+ // need to associate tracker with fid returned from server
+ DCE2_Queue* ft_queue;
+
+ // This is a reference to an existing file tracker
+ DCE2_SmbFileTracker* ftracker;
+
+ // Used for requests to cache data that will ultimately end up in
+ // the file tracker upon response.
+ char* file_name;
+ uint64_t file_size;
+ uint64_t file_offset;
+ bool sequential_only;
+
+ // For TreeConnect to know whether it's to IPC
+ bool is_ipc;
+};
struct DCE2_SmbSsnData
{
DCE2_SsnData sd; // This member must be first
- // FIXIT-M add all the remaining fields
+
+ DCE2_Policy policy;
+
+ int dialect_index;
+ int ssn_state_flags;
+
+ DCE2_SmbDataState cli_data_state;
+ DCE2_SmbDataState srv_data_state;
+
+ DCE2_SmbPduState pdu_state;
+
+ int uid; // A signed integer so it can be set to sentinel
+ int tid; // A signed integer so it can be set to sentinel
+ DCE2_List* uids;
+ DCE2_List* tids;
+
+ // For tracking files and named pipes
+ DCE2_SmbFileTracker ftracker;
+ DCE2_List* ftrackers; // List of DCE2_SmbFileTracker
+
+ // For tracking requests / responses
+ DCE2_SmbRequestTracker rtracker;
+ //DCE2_Queue *rtrackers;
+ uint16_t max_outstanding_requests;
+ uint16_t outstanding_requests;
+
+ // The current pid/mid node for this request/response
+ DCE2_SmbRequestTracker* cur_rtracker;
+
+ // Used for TCP segmentation to get full PDU
+ DCE2_Buffer* cli_seg;
+ DCE2_Buffer* srv_seg;
+
+ // These are used for commands we don't need to process
+ uint32_t cli_ignore_bytes;
+ uint32_t srv_ignore_bytes;
+
+ // The file API supports one concurrent upload/download per session.
+ // This is a reference to a file tracker so shouldn't be freed.
+ DCE2_SmbFileTracker* fapi_ftracker;
+
+#ifdef ACTIVE_RESPONSE
+ DCE2_SmbFileTracker* fb_ftracker;
+ bool block_pdus;
+#endif
+
+ // Maximum file depth as returned from file API
+ int64_t max_file_depth;
};
inline uint32_t NbssLen(const NbssHdr* nb)
return &dce2_smb_pstat_new_session;
case 3:
- name = "dce smb session_state";
- parent = "dce smb session";
- return &dce2_smb_pstat_session_state;
-
- case 4:
name = "dce smb detect";
parent = "dce smb main";
return &dce2_smb_pstat_detect;
- case 5:
+ case 4:
name = "dce smb log";
parent = "dce smb main";
return &dce2_smb_pstat_log;
- case 6:
+ case 5:
name = "dce smb connection-oriented segment";
parent = "dce smb main";
return &dce2_smb_pstat_co_seg;
- case 7:
+ case 6:
name = "dce smb connection-oriented fragment";
parent = "dce smb main";
return &dce2_smb_pstat_co_frag;
- case 8:
+ case 7:
name = "dce smb connection-oriented reassembly";
parent = "dce smb main";
return &dce2_smb_pstat_co_reass;
- case 9:
+ case 8:
name = "dce smb connection-oriented context";
parent = "dce smb main";
return &dce2_smb_pstat_co_ctx;
- case 10:
+ case 9:
name = "dce smb segment";
parent = "dce smb main";
return &dce2_smb_pstat_smb_seg;
- case 11:
+ case 10:
name = "dce smb request";
parent = "dce smb main";
return &dce2_smb_pstat_smb_req;
- case 12:
+ case 11:
name = "dce smb uid";
parent = "dce smb main";
return &dce2_smb_pstat_smb_uid;
- case 13:
+ case 12:
name = "dce smb tid";
parent = "dce smb main";
return &dce2_smb_pstat_smb_tid;
- case 14:
+ case 13:
name = "dce smb fid";
parent = "dce smb main";
return &dce2_smb_pstat_smb_fid;
- case 15:
+ case 14:
name = "dce smb file";
parent = "dce smb main";
return &dce2_smb_pstat_smb_file;
- case 16:
+ case 15:
name = "dce smb file detect";
parent = "dce smb file";
return &dce2_smb_pstat_smb_file_detect;
- case 17:
+ case 16:
name = "dce smb file api";
parent = "dce smb file";
return &dce2_smb_pstat_smb_file_api;
- case 18:
+ case 17:
name = "dce smb fingerprint";
parent = "dce smb main";
return &dce2_smb_pstat_smb_fingerprint;
- case 19:
+ case 18:
name = "dce smb negotiate";
parent = "dce smb main";
return &dce2_smb_pstat_smb_negotiate;
StreamSplitter::Status ps = StreamSplitter::SEARCH;
uint32_t nb_hdr;
uint32_t nb_len;
+ DCE2_SmbSsnData* sd = get_dce2_smb_session_data(flow);
DebugFormat(DEBUG_DCE_SMB, "%s\n", DCE2_DEBUG__PAF_START_MSG_SMB);
DebugFormat(DEBUG_DCE_SMB, "SMB: %u bytes of data\n", len);
UNUSED(flags);
#endif
- if (dce2_paf_abort(flow))
+ if (dce2_paf_abort(flow, (DCE2_SsnData*)sd))
{
DebugFormat(DEBUG_DCE_SMB, "%s\n", DCE2_DEBUG__PAF_END_MSG);
return StreamSplitter::ABORT;
#include "dce_tcp_module.h"
#include "main/snort_debug.h"
+Dce2TcpFlowData::Dce2TcpFlowData() : FlowData(flow_id)
+{
+}
+
THREAD_LOCAL dce2TcpStats dce2_tcp_stats;
THREAD_LOCAL ProfileStats dce2_tcp_pstat_main;
THREAD_LOCAL ProfileStats dce2_tcp_pstat_session;
THREAD_LOCAL ProfileStats dce2_tcp_pstat_new_session;
-THREAD_LOCAL ProfileStats dce2_tcp_pstat_session_state;
THREAD_LOCAL ProfileStats dce2_tcp_pstat_detect;
THREAD_LOCAL ProfileStats dce2_tcp_pstat_log;
THREAD_LOCAL ProfileStats dce2_tcp_pstat_co_seg;
return fd ? &fd->dce2_tcp_session : nullptr;
}
+static DCE2_TcpSsnData* set_new_dce2_tcp_session(Packet* p)
+{
+ Dce2TcpFlowData* fd = new Dce2TcpFlowData;
+
+ p->flow->set_application_data(fd);
+ return(&fd->dce2_tcp_session);
+}
+
+static DCE2_TcpSsnData* dce2_create_new_tcp_session(Packet* p, dce2TcpProtoConf config)
+{
+ DCE2_TcpSsnData* dce2_tcp_sess = NULL;
+ Profile profile(dce2_tcp_pstat_new_session);
+
+ if (DCE2_TcpAutodetect(p))
+ {
+ DebugMessage(DEBUG_DCE_TCP, "DCE over TCP packet detected\n");
+ DebugMessage(DEBUG_DCE_TCP, "Creating new session\n");
+
+ dce2_tcp_sess = set_new_dce2_tcp_session(p);
+
+ if ( dce2_tcp_sess )
+ {
+ DCE2_CoInitTracker(&dce2_tcp_sess->co_tracker);
+ DCE2_ResetRopts(&dce2_tcp_sess->sd.ropts);
+
+ dce2_tcp_stats.tcp_sessions++;
+ DebugFormat(DEBUG_DCE_TCP,"Created (%p)\n", (void*)dce2_tcp_sess);
+
+ dce2_tcp_sess->sd.trans = DCE2_TRANS_TYPE__TCP;
+ dce2_tcp_sess->sd.server_policy = config.common.policy;
+ dce2_tcp_sess->sd.client_policy = DCE2_POLICY__WINXP;
+ dce2_tcp_sess->sd.wire_pkt = p;
+
+ DCE2_SsnSetAutodetected(&dce2_tcp_sess->sd, p);
+ }
+ }
+
+ return dce2_tcp_sess;
+}
+
+DCE2_TcpSsnData* dce2_handle_tcp_session(Packet* p, dce2TcpProtoConf& config)
+{
+ Profile profile(dce2_tcp_pstat_session);
+
+ DCE2_TcpSsnData* dce2_tcp_sess = get_dce2_tcp_session_data(p->flow);
+
+ if (dce2_tcp_sess == nullptr)
+ {
+ dce2_tcp_sess = dce2_create_new_tcp_session(p, config);
+ }
+ else
+ {
+ DCE2_SsnData* sd = (DCE2_SsnData*)dce2_tcp_sess;
+ sd->wire_pkt = p;
+
+ if (DCE2_SsnAutodetected(sd) && !(p->packet_flags & sd->autodetect_dir))
+ {
+ /* Try to autodetect in opposite direction */
+ if (!DCE2_TcpAutodetect(p))
+ {
+ DebugMessage(DEBUG_DCE_TCP, "Bad autodetect.\n");
+ DCE2_SsnNoInspect(sd);
+ dce2_tcp_stats.sessions_aborted++;
+ dce2_tcp_stats.bad_autodetects++;
+ return NULL;
+ }
+
+ DCE2_SsnClearAutodetected(sd);
+ }
+ }
+
+ DebugFormat(DEBUG_DCE_TCP, "Session pointer: %p\n", (void*)dce2_tcp_sess);
+
+ // FIXIT-M add remaining session handling logic
+
+ return dce2_tcp_sess;
+}
+
//-------------------------------------------------------------------------
// class stuff
//-------------------------------------------------------------------------
void Dce2Tcp::eval(Packet* p)
{
- DCE2_TcpSsnData* dce2_sess = get_dce2_tcp_session_data(p->flow);
+ DCE2_TcpSsnData* dce2_tcp_sess;
+ Profile profile(dce2_tcp_pstat_main);
+
+ assert(p->has_tcp_data());
+ assert(p->flow);
- if (dce2_sess == nullptr)
+ if (p->flow->get_session_flags() & SSNFLAG_MIDSTREAM)
{
- /*Check if it is a DCE2 over TCP packet*/
-
- if (DCE2_TcpAutodetect(p))
- {
- DebugMessage(DEBUG_DCE_TCP, "DCE over TCP packet detected\n");
- }
-
+ DebugMessage(DEBUG_DCE_TCP,
+ "Midstream - not inspecting.\n");
+ return;
}
+
+ dce2_tcp_sess = dce2_handle_tcp_session(p, config);
+ if (!dce2_tcp_sess)
+ {
+ return;
+ }
+ dce2_tcp_stats.tcp_pkts++;
}
//-------------------------------------------------------------------------
delete p;
}
+static void dce2_tcp_init()
+{
+ Dce2TcpFlowData::init();
+}
+
const InspectApi dce2_tcp_api =
{
{
(uint16_t)PktType::PDU,
nullptr, // buffers
"dce_tcp",
- nullptr,
+ dce2_tcp_init,
nullptr, // pterm
nullptr, // tinit
nullptr, // tterm
struct DCE2_TcpSsnData
{
DCE2_SsnData sd; // This member must be first
- // FIXIT-M add all the remaining fields
+ DCE2_CoTracker co_tracker;
};
class Dce2TcpFlowData : public FlowData
return &dce2_tcp_pstat_new_session;
case 3:
- name = "dce tcp session state";
- parent = "dce tcp session";
- return &dce2_tcp_pstat_session_state;
-
- case 4:
name = "dce tcp detect";
parent = "dce tcp main";
return &dce2_tcp_pstat_detect;
- case 5:
+ case 4:
name = "dce tcp log";
parent = "dce_tcp_main";
return &dce2_tcp_pstat_log;
- case 6:
+ case 5:
name = "dce tcp connection-oriented segment";
parent = "dce tcp main";
return &dce2_tcp_pstat_co_seg;
- case 7:
+ case 6:
name = "dce tcp connection-oriented fragment";
parent = "dce tcp main";
return &dce2_tcp_pstat_co_frag;
- case 8:
+ case 7:
name = "dce tcp connection-oriented reassembly";
parent = "dce tcp main";
return &dce2_tcp_pstat_co_reass;
- case 9:
+ case 8:
name = "dce tcp connection-oriented context";
parent = "dce tcp main";
return &dce2_tcp_pstat_co_ctx;
DebugMessage(DEBUG_DCE_TCP, "Packet from Server\n");
#endif
- if (dce2_paf_abort(flow))
+ if (dce2_paf_abort(flow, (DCE2_SsnData*)sd))
{
DebugFormat(DEBUG_DCE_TCP, "%s\n", DCE2_DEBUG__PAF_END_MSG);
return StreamSplitter::ABORT;
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-#ifndef _DCE_UTILS_H_
-#define _DCE_UTILS_H_
+#ifndef DCE_UTILS_H
+#define DCE_UTILS_H
#include <string.h>
#include <ctype.h>
DCE2_RET__DUPLICATE
};
+enum DCE2_TransType
+{
+ DCE2_TRANS_TYPE__NONE = 0,
+ DCE2_TRANS_TYPE__SMB,
+ DCE2_TRANS_TYPE__TCP,
+ DCE2_TRANS_TYPE__MAX
+};
+
enum DCE2_IntType
{
DCE2_INT_TYPE__INT8,
uint8_t node[6];
};
+struct DCE2_Buffer
+{
+ uint8_t* data;
+ uint32_t len;
+ uint32_t size;
+ uint32_t min_add_size;
+ uint32_t offset;
+};
+
/********************************************************************
* Inline function prototypes
********************************************************************/