#define DEBUG_MPSE 0x0010000000000000LL
#define DEBUG_SO_RULE 0x0020000000000000LL
#define DEBUG_LOGGER 0x0040000000000000LL
+#define DEBUG_DCE_TCP 0x0080000000000000LL
+#define DEBUG_DCE_SMB 0x0100000000000000LL
#ifdef PIGLET
-#define DEBUG_PIGLET 0x0080000000000000LL
+#define DEBUG_PIGLET 0x0200000000000000LL
#endif
+
#ifdef DEBUG_MSGS
class SO_PUBLIC Debug
set( FILE_LIST
- dce2_co.h
- dce2_common.cc
- dce2_common.h
- dce2_list.h
- dce2_list.cc
- dce2_smb.cc
- dce2_smb.h
- dce2_smb_module.cc
- dce2_smb_module.h
- dce2_tcp.cc
- dce2_tcp.h
- dce2_tcp_module.cc
- dce2_tcp_module.h
- dce2_utils.cc
- dce2_utils.h
- ips_dce2_iface.cc
- ips_dce2_opnum.cc
- ips_dce2_stub_data.cc
+ dce_co.h
+ dce_common.cc
+ dce_common.h
+ dce_list.h
+ dce_list.cc
+ dce_smb.cc
+ dce_smb.h
+ dce_smb_module.cc
+ dce_smb_module.h
+ dce_smb_paf.cc
+ dce_smb_paf.h
+ dce_tcp.cc
+ dce_tcp.h
+ dce_tcp_module.cc
+ dce_tcp_module.h
+ dce_tcp_paf.cc
+ dce_tcp_paf.h
+ dce_utils.cc
+ dce_utils.h
+ ips_dce_iface.cc
+ ips_dce_opnum.cc
+ ips_dce_stub_data.cc
)
file_list = \
-dce2_co.h \
-dce2_common.cc \
-dce2_common.h \
-dce2_list.cc \
-dce2_list.h \
-dce2_smb.cc \
-dce2_smb.h \
-dce2_smb_module.cc \
-dce2_smb_module.h \
-dce2_tcp.cc\
-dce2_tcp.h \
-dce2_tcp_module.cc \
-dce2_tcp_module.h \
-dce2_utils.cc \
-dce2_utils.h \
-ips_dce2_iface.cc \
-ips_dce2_opnum.cc \
-ips_dce2_stub_data.cc
+dce_co.h \
+dce_common.cc \
+dce_common.h \
+dce_list.cc \
+dce_list.h \
+dce_smb.cc \
+dce_smb.h \
+dce_smb_module.cc \
+dce_smb_module.h \
+dce_smb_paf.cc \
+dce_smb_paf.h \
+dce_tcp.cc\
+dce_tcp.h \
+dce_tcp_module.cc \
+dce_tcp_module.h \
+dce_tcp_paf.cc \
+dce_tcp_paf.h \
+dce_utils.cc \
+dce_utils.h \
+ips_dce_iface.cc \
+ips_dce_opnum.cc \
+ips_dce_stub_data.cc
if STATIC_INSPECTORS
+++ /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.
-//-------------------------------------------------------------------------
-
-//dce2_common.h author Rashmi Pitre <rrp@cisco.com>
-
-#ifndef DCE2_COMMON_H
-#define DCE2_COMMON_H
-
-#include "main/snort_types.h"
-#include "framework/module.h"
-#include "framework/inspector.h"
-
-extern const InspectApi dce2_smb_api;
-extern const InspectApi dce2_tcp_api;
-
-#define GID_DCE2 145
-
-enum DCE2_POLICY
-{
- DCE2_POLICY__WIN2000 = 0,
- DCE2_POLICY__WINXP,
- DCE2_POLICY__WINVISTA,
- DCE2_POLICY__WIN2003,
- DCE2_POLICY__WIN2008,
- DCE2_POLICY__WIN7,
- DCE2_POLICY__SAMBA,
- DCE2_POLICY__SAMBA_3_0_37,
- DCE2_POLICY__SAMBA_3_0_22,
- DCE2_POLICY__SAMBA_3_0_20,
-};
-
-#define DCE2_SARG__POLICY_WIN2000 "Win2000"
-#define DCE2_SARG__POLICY_WINXP "WinXP"
-#define DCE2_SARG__POLICY_WINVISTA "WinVista"
-#define DCE2_SARG__POLICY_WIN2003 "Win2003"
-#define DCE2_SARG__POLICY_WIN2008 "Win2008"
-#define DCE2_SARG__POLICY_WIN7 "Win7"
-#define DCE2_SARG__POLICY_SAMBA "Samba"
-#define DCE2_SARG__POLICY_SAMBA_3_0_37 "Samba-3.0.37" /* Samba version 3.0.37 and previous */
-#define DCE2_SARG__POLICY_SAMBA_3_0_22 "Samba-3.0.22" /* Samba version 3.0.22 and previous */
-#define DCE2_SARG__POLICY_SAMBA_3_0_20 "Samba-3.0.20" /* Samba version 3.0.20 and previous */
-
-struct dce2CommonProtoConf
-{
- bool disable_defrag;
- uint16_t max_frag_len;
- DCE2_POLICY policy;
-};
-
-bool dce2_set_common_config(Value&, dce2CommonProtoConf&);
-void print_dce2_common_config(dce2CommonProtoConf&);
-
-#endif
-
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// dce2_co.h author Rashmi Pitre <rrp@cisco.com>
+// dce_co.h author Rashmi Pitre <rrp@cisco.com>
// based on work by Todd Wease
-#ifndef DCE2_CO_H
-#define DCE2_CO_H
+#ifndef DCE_CO_H
+#define DCE_CO_H
+
+#include "dce_common.h"
#define DCE2_CO_BAD_MAJOR_VERSION 27
#define DCE2_CO_BAD_MINOR_VERSION 28
"Connection-oriented DCE/RPC - Context id of non first/last fragment different \
from context id established for fragmented request."
+#pragma pack(1)
+
+struct DceRpcCoVersion
+{
+ uint8_t major;
+ uint8_t minor;
+};
+
+/* Connection oriented common header */
+struct DceRpcCoHdr
+{
+ DceRpcCoVersion pversion;
+ uint8_t ptype;
+ uint8_t pfc_flags;
+ uint8_t packed_drep[4];
+ uint16_t frag_length;
+ uint16_t auth_length;
+ uint32_t call_id;
+};
+
+#pragma pack()
+
+static inline uint8_t DceRpcCoVersMaj(const DceRpcCoHdr* co)
+{
+ return co->pversion.major;
+}
+
+static inline uint8_t DceRpcCoVersMin(const DceRpcCoHdr* co)
+{
+ return co->pversion.minor;
+}
+
+static inline DceRpcPduType DceRpcCoPduType(const DceRpcCoHdr* co)
+{
+ return (DceRpcPduType)co->ptype;
+}
+
+static inline DceRpcBoFlag DceRpcCoByteOrder(const DceRpcCoHdr* co)
+{
+ return DceRpcByteOrder(co->packed_drep[0]);
+}
+
+static inline uint16_t DceRpcCoFragLen(const DceRpcCoHdr* co)
+{
+ return DceRpcNtohs(&co->frag_length, DceRpcCoByteOrder(co));
+}
+
#endif
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// dce2_common.cc author Rashmi Pitre <rrp@cisco.com>
+// dce_common.cc author Rashmi Pitre <rrp@cisco.com>
-#include "dce2_common.h"
-#include "framework/module.h"
+#include "dce_common.h"
#include "framework/base_api.h"
+#include "framework/module.h"
+#include "flow/flow.h"
#include "log/messages.h"
+#include "main/snort_debug.h"
const char* dce2_get_policy_name(DCE2_POLICY policy)
{
dce2_get_policy_name(common.policy));
}
+bool dce2_paf_abort(Flow* flow)
+{
+ if (flow->get_session_flags() & SSNFLAG_MIDSTREAM)
+ {
+ DebugMessage(DEBUG_DCE_TCP,
+ "Aborting PAF because of midstream pickup.\n");
+ return true;
+ }
+ else if (!(flow->get_session_flags() & SSNFLAG_ESTABLISHED))
+ {
+ DebugMessage(DEBUG_DCE_TCP,
+ "Aborting PAF because of unestablished session.\n");
+ return true;
+ }
+ // FIXIT-M add the remaining checks
+
+ return false;
+}
+
#ifdef BUILDING_SO
extern const BaseApi* ips_dce_iface;
--- /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_common.h author Rashmi Pitre <rrp@cisco.com>
+
+#ifndef DCE_COMMON_H
+#define DCE_COMMON_H
+
+#include "dce_utils.h"
+#include "main/snort_types.h"
+#include "framework/module.h"
+#include "framework/inspector.h"
+
+extern const InspectApi dce2_smb_api;
+extern const InspectApi dce2_tcp_api;
+
+#define GID_DCE2 145
+
+enum DCE2_POLICY
+{
+ DCE2_POLICY__WIN2000 = 0,
+ DCE2_POLICY__WINXP,
+ DCE2_POLICY__WINVISTA,
+ DCE2_POLICY__WIN2003,
+ DCE2_POLICY__WIN2008,
+ DCE2_POLICY__WIN7,
+ DCE2_POLICY__SAMBA,
+ DCE2_POLICY__SAMBA_3_0_37,
+ DCE2_POLICY__SAMBA_3_0_22,
+ DCE2_POLICY__SAMBA_3_0_20,
+};
+
+#define DCE2_SARG__POLICY_WIN2000 "Win2000"
+#define DCE2_SARG__POLICY_WINXP "WinXP"
+#define DCE2_SARG__POLICY_WINVISTA "WinVista"
+#define DCE2_SARG__POLICY_WIN2003 "Win2003"
+#define DCE2_SARG__POLICY_WIN2008 "Win2008"
+#define DCE2_SARG__POLICY_WIN7 "Win7"
+#define DCE2_SARG__POLICY_SAMBA "Samba"
+#define DCE2_SARG__POLICY_SAMBA_3_0_37 "Samba-3.0.37" /* Samba version 3.0.37 and previous */
+#define DCE2_SARG__POLICY_SAMBA_3_0_22 "Samba-3.0.22" /* Samba version 3.0.22 and previous */
+#define DCE2_SARG__POLICY_SAMBA_3_0_20 "Samba-3.0.20" /* Samba version 3.0.20 and previous */
+
+struct dce2CommonProtoConf
+{
+ bool disable_defrag;
+ uint16_t max_frag_len;
+ DCE2_POLICY policy;
+};
+
+#define DCE2_DEBUG__PAF_END_MSG "=========================================================="
+
+/* DCE/RPC byte order flag */
+enum DceRpcBoFlag
+{
+ DCERPC_BO_FLAG__NONE,
+ DCERPC_BO_FLAG__BIG_ENDIAN,
+ DCERPC_BO_FLAG__LITTLE_ENDIAN
+};
+
+enum DceRpcPduType
+{
+ DCERPC_PDU_TYPE__REQUEST = 0,
+ DCERPC_PDU_TYPE__PING,
+ DCERPC_PDU_TYPE__RESPONSE,
+ DCERPC_PDU_TYPE__FAULT,
+ DCERPC_PDU_TYPE__WORKING,
+ DCERPC_PDU_TYPE__NOCALL,
+ DCERPC_PDU_TYPE__REJECT,
+ DCERPC_PDU_TYPE__ACK,
+ DCERPC_PDU_TYPE__CL_CANCEL,
+ DCERPC_PDU_TYPE__FACK,
+ DCERPC_PDU_TYPE__CANCEL_ACK,
+ DCERPC_PDU_TYPE__BIND,
+ DCERPC_PDU_TYPE__BIND_ACK,
+ DCERPC_PDU_TYPE__BIND_NACK,
+ DCERPC_PDU_TYPE__ALTER_CONTEXT,
+ DCERPC_PDU_TYPE__ALTER_CONTEXT_RESP,
+ DCERPC_PDU_TYPE__AUTH3,
+ DCERPC_PDU_TYPE__SHUTDOWN,
+ DCERPC_PDU_TYPE__CO_CANCEL,
+ DCERPC_PDU_TYPE__ORPHANED,
+ DCERPC_PDU_TYPE__MICROSOFT_PROPRIETARY_OUTLOOK2003_RPC_OVER_HTTP,
+ DCERPC_PDU_TYPE__MAX
+};
+
+/* Version 4 is for Connectionless
+ * Version 5 is for Connection oriented */
+enum DceRpcProtoMajorVers
+{
+ DCERPC_PROTO_MAJOR_VERS__4 = 4,
+ DCERPC_PROTO_MAJOR_VERS__5 = 5
+};
+
+enum DceRpcProtoMinorVers
+{
+ DCERPC_PROTO_MINOR_VERS__0 = 0,
+ DCERPC_PROTO_MINOR_VERS__1 = 1
+};
+
+struct DCE2_Roptions
+{
+ /* dce_iface */
+ int first_frag; /* Set to sentinel if not applicable */
+ Uuid iface;
+ /* For connectionless */
+ uint32_t iface_vers; /* For connectionless */
+
+ /* For connection-oriented */
+ uint16_t iface_vers_maj;
+ uint16_t iface_vers_min;
+
+ /* dce_opnum */
+ int opnum; /* Set to sentinel if not applicable */
+
+ /* dce_byte_test */
+ int hdr_byte_order; /* Set to sentinel if not applicable */
+ int data_byte_order; /* Set to sentinel if not applicable */
+
+ /* dce_stub_data */
+ const uint8_t* stub_data; /* Set to NULL if not applicable */
+};
+
+struct DCE2_SsnData
+{
+ DCE2_POLICY server_policy;
+ DCE2_POLICY client_policy;
+ int flags;
+ const Packet* wire_pkt;
+ uint64_t alert_mask;
+ DCE2_Roptions ropts;
+ int autodetect_dir;
+
+ uint32_t cli_seq;
+ uint32_t cli_nseq;
+ uint32_t srv_seq;
+ uint32_t srv_nseq;
+};
+
+inline DceRpcBoFlag DceRpcByteOrder(const uint8_t value)
+{
+ if ((value & 0x10) >> 4)
+ return DCERPC_BO_FLAG__LITTLE_ENDIAN;
+
+ return DCERPC_BO_FLAG__BIG_ENDIAN;
+}
+
+inline uint16_t DceRpcNtohs(const uint16_t* ptr, const DceRpcBoFlag bo_flag)
+{
+ uint16_t value;
+
+ if (ptr == NULL)
+ return 0;
+
+#ifdef WORDS_MUSTALIGN
+ value = *((uint8_t*)ptr) << 8 | *((uint8_t*)ptr + 1);
+#else
+ value = *ptr;
+#endif /* WORDS_MUSTALIGN */
+
+ if (bo_flag == DCERPC_BO_FLAG__NONE)
+ return value;
+
+#ifdef WORDS_BIGENDIAN
+ if (bo_flag == DCERPC_BO_FLAG__BIG_ENDIAN)
+#else
+ if (bo_flag == DCERPC_BO_FLAG__LITTLE_ENDIAN)
+#endif /* WORDS_BIGENDIAN */
+ return value;
+
+ return ((value & 0xff00) >> 8) | ((value & 0x00ff) << 8);
+}
+
+bool dce2_set_common_config(Value&, dce2CommonProtoConf&);
+void print_dce2_common_config(dce2CommonProtoConf&);
+bool dce2_paf_abort(Flow*);
+
+#endif
+
*
****************************************************************************/
-#include "dce2_list.h"
-#include "dce2_utils.h"
+#include "dce_list.h"
+#include "dce_utils.h"
#include "log/messages.h"
#include "utils/util.h"
*
****************************************************************************/
-#ifndef _DCE2_LIST_H_
-#define _DCE2_LIST_H_
+#ifndef _DCE_LIST_H_
+#define _DCE_LIST_H_
-#include "dce2_utils.h"
+#include "dce_utils.h"
#include "main/snort_types.h"
// dce_smb.cc author Rashmi Pitre <rrp@cisco.com>
-#include "dce2_smb.h"
-#include "dce2_smb_module.h"
-#include "dce2_list.h"
+#include "dce_smb.h"
+#include "dce_smb_paf.h"
+#include "dce_smb_module.h"
+#include "dce_list.h"
+#include "main/snort_debug.h"
THREAD_LOCAL dce2SmbStats dce2_smb_stats;
THREAD_LOCAL ProfileStats dce2_smb_pstat_smb_fingerprint;
THREAD_LOCAL ProfileStats dce2_smb_pstat_smb_negotiate;
+unsigned Dce2SmbFlowData::flow_id = 0;
+
+DCE2_SmbSsnData* get_dce2_smb_session_data(Flow* flow)
+{
+ Dce2SmbFlowData* fd = (Dce2SmbFlowData*)flow->get_application_data(
+ Dce2SmbFlowData::flow_id);
+
+ return fd ? &fd->dce2_smb_session : nullptr;
+}
+
//-------------------------------------------------------------------------
// class stuff
//-------------------------------------------------------------------------
void show(SnortConfig*) override;
void eval(Packet*) override;
+ StreamSplitter* get_splitter(bool c2s) override
+ {
+ return new Dce2SmbSplitter(c2s);
+ }
private:
dce2SmbProtoConf config;
void Dce2Smb::eval(Packet* p)
{
- UNUSED(p);
+ DCE2_SmbSsnData* dce2_sess = get_dce2_smb_session_data(p->flow);
+
+ if (dce2_sess == nullptr)
+ {
+ /*Check if it is a DCE2 over SMB packet*/
+
+ if (DCE2_SmbAutodetect(p))
+ {
+ DebugMessage(DEBUG_DCE_SMB, "DCE over SMB packet detected\n");
+ }
+ }
}
//-------------------------------------------------------------------------
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-//dce2_smb.h author Rashmi Pitre <rrp@cisco.com>
+//dce_smb.h author Rashmi Pitre <rrp@cisco.com>
// based on work by Todd Wease
-#ifndef DCE2_SMB_H
-#define DCE2_SMB_H
+#ifndef DCE_SMB_H
+#define DCE_SMB_H
+#include "dce_common.h"
#include "protocols/packet.h"
#include "profiler/profiler.h"
#include "framework/counts.h"
extern THREAD_LOCAL ProfileStats dce2_smb_pstat_smb_file_api;
extern THREAD_LOCAL ProfileStats dce2_smb_pstat_smb_fingerprint;
extern THREAD_LOCAL ProfileStats dce2_smb_pstat_smb_negotiate;
+
+#define NBSS_SESSION_TYPE__MESSAGE 0x00
+#define NBSS_SESSION_TYPE__REQUEST 0x81
+#define NBSS_SESSION_TYPE__POS_RESPONSE 0x82
+#define NBSS_SESSION_TYPE__NEG_RESPONSE 0x83
+#define NBSS_SESSION_TYPE__RETARGET_RESPONSE 0x84
+#define NBSS_SESSION_TYPE__KEEP_ALIVE 0x85
+
+#define DCE2_SMB_ID 0xff534d42 /* \xffSMB */
+#define DCE2_SMB2_ID 0xfe534d42 /* \xfeSMB */
+
+#pragma pack(1)
+
+/********************************************************************
+ * NetBIOS Session Service header
+ ********************************************************************/
+struct NbssHdr
+{
+ uint8_t type;
+ uint8_t flags; /* Treat flags as the upper byte to length */
+ uint16_t length;
+} ;
+
+struct SmbNtHdr
+{
+ uint8_t smb_idf[4]; /* contains 0xFF, 'SMB' */
+ uint8_t smb_com; /* command code */
+ union
+ {
+ struct
+ {
+ uint8_t smb_class; /* dos error class */
+ uint8_t smb_res; /* reserved for future */
+ uint16_t smb_code; /* dos error code */
+ } smb_status;
+ uint32_t nt_status; /* nt status */
+ } smb_status;
+ uint8_t smb_flg; /* flags */
+ uint16_t smb_flg2; /* flags */
+ uint16_t smb_pid_high;
+ uint64_t smb_signature;
+ uint16_t smb_res; /* reserved for future */
+ uint16_t smb_tid; /* tree id */
+ uint16_t smb_pid; /* caller's process id */
+ uint16_t smb_uid; /* authenticated user id */
+ uint16_t smb_mid; /* multiplex id */
+};
+
+#pragma pack()
+
+struct DCE2_SmbSsnData
+{
+ DCE2_SsnData sd; // This member must be first
+ // FIXIT-M add all the remaining fields
+};
+
+static inline uint32_t NbssLen(const NbssHdr* nb)
+{
+ /* Treat first bit of flags as the upper byte to length */
+ return ((nb->flags & 0x01) << 16) | ntohs(nb->length);
+}
+
+static inline uint8_t NbssType(const NbssHdr* nb)
+{
+ return nb->type;
+}
+
+static inline uint32_t SmbId(const SmbNtHdr* hdr)
+{
+#ifdef WORDS_MUSTALIGN
+ uint8_t* idf = (uint8_t*)hdr->smb_idf;
+ return *idf << 24 | *(idf + 1) << 16 | *(idf + 2) << 8 | *(idf + 3);
+#else
+ return ntohl(*((uint32_t*)hdr->smb_idf));
+#endif /* WORDS_MUSTALIGN */
+}
+
+static inline bool DCE2_SmbAutodetect(Packet* p)
+{
+ if (p->dsize > (sizeof(NbssHdr) + sizeof(SmbNtHdr)))
+ {
+ NbssHdr* nb_hdr = (NbssHdr*)p->data;
+
+ switch (NbssType(nb_hdr))
+ {
+ case NBSS_SESSION_TYPE__MESSAGE:
+ {
+ SmbNtHdr* smb_hdr = (SmbNtHdr*)(p->data + sizeof(NbssHdr));
+
+ if ((SmbId(smb_hdr) == DCE2_SMB_ID)
+ || (SmbId(smb_hdr) == DCE2_SMB2_ID))
+ {
+ return true;
+ }
+ }
+
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return false;
+}
+
+class Dce2SmbFlowData : public FlowData
+{
+public:
+ Dce2SmbFlowData();
+
+ static void init()
+ {
+ flow_id = FlowData::get_flow_id();
+ }
+
+public:
+ static unsigned flow_id;
+ DCE2_SmbSsnData dce2_smb_session;
+};
+
+DCE2_SmbSsnData* get_dce2_smb_session_data(Flow*);
+
#endif
// dce_smb_module.cc author Rashmi Pitre <rrp@cisco.com>
-#include "dce2_smb_module.h"
-#include "dce2_smb.h"
-#include "dce2_common.h"
-#include "dce2_co.h"
+#include "dce_smb_module.h"
+#include "dce_smb.h"
+#include "dce_common.h"
+#include "dce_co.h"
#include "main/snort_config.h"
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
//
-// dce2_smb_module.h author Rashmi Pitre <rrp@cisco.com>
+// dce_smb_module.h author Rashmi Pitre <rrp@cisco.com>
-#ifndef DCE2_SMB_MODULE_H
-#define DCE2_SMB_MODULE_H
+#ifndef DCE_SMB_MODULE_H
+#define DCE_SMB_MODULE_H
-#include "dce2_common.h"
+#include "dce_common.h"
#include "framework/module.h"
-#include "dce2_list.h"
+#include "dce_list.h"
struct SnortConfig;
--- /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_smb_paf.cc author Rashmi Pitre <rrp@cisco.com>
+// based on work by Todd Wease
+
+#include "dce_smb_paf.h"
+#include "dce_smb.h"
+#include "dce_common.h"
+#include "main/snort_debug.h"
+#include "protocols/packet.h"
+
+/*********************************************************************
+ * Function: DCE2_PafSmbIsValidNetbiosHdr()
+ *
+ * Purpose: Validates that the NetBIOS header is valid. If in
+ * junk states, header type must be Session Message.
+ *
+ *********************************************************************/
+static inline bool DCE2_PafSmbIsValidNetbiosHdr(uint32_t nb_hdr, bool junk)
+{
+ uint8_t type = (uint8_t)(nb_hdr >> 24);
+ uint8_t bit = (uint8_t)((nb_hdr & 0x00ff0000) >> 16);
+
+ if (junk)
+ {
+ if (type != NBSS_SESSION_TYPE__MESSAGE)
+ return false;
+ }
+ else
+ {
+ switch (type)
+ {
+ case NBSS_SESSION_TYPE__MESSAGE:
+ case NBSS_SESSION_TYPE__REQUEST:
+ case NBSS_SESSION_TYPE__POS_RESPONSE:
+ case NBSS_SESSION_TYPE__NEG_RESPONSE:
+ case NBSS_SESSION_TYPE__RETARGET_RESPONSE:
+ case NBSS_SESSION_TYPE__KEEP_ALIVE:
+ break;
+ default:
+ return false;
+ }
+ }
+
+ if ((bit != 0x00) && (bit != 0x01))
+ return false;
+
+ return true;
+}
+
+/*********************************************************************
+ * Function: DCE2_SmbPaf()
+ *
+ * Purpose: The DCE/RPC over SMB PAF callback.
+ * Inspects a byte at a time changing state and shifting
+ * bytes onto the 64bit nb_hdr member. At state 3
+ * determines if NetBIOS header is valid and if so sets
+ * flush point. If not valid goes to states 4-7 where
+ * there is the possibility that junk data was inserted
+ * before request/response. Needs to validate SMB ID at
+ * this point. At state 7 determines if NetBIOS header
+ * is valid and that the SMB ID is present. Stays in
+ * state 7 until this is the case.
+ *
+ *********************************************************************/
+StreamSplitter::Status dce2_smb_paf(DCE2_PafSmbData* ss, Flow* flow, const uint8_t* data,
+ uint32_t len, uint32_t flags, uint32_t* fp)
+{
+ uint32_t n = 0;
+ StreamSplitter::Status ps = StreamSplitter::SEARCH;
+ uint32_t nb_hdr;
+ uint32_t nb_len;
+
+ DebugFormat(DEBUG_DCE_SMB, "%s\n", DCE2_DEBUG__PAF_START_MSG_SMB);
+ DebugFormat(DEBUG_DCE_SMB, "SMB: %u bytes of data\n", len);
+
+ if (flags & PKT_FROM_CLIENT)
+ DebugMessage(DEBUG_DCE_SMB, "Packet from Client\n");
+ else
+ DebugMessage(DEBUG_DCE_SMB, "Packet from Server\n");
+
+ if (dce2_paf_abort(flow))
+ {
+ DebugFormat(DEBUG_DCE_SMB, "%s\n", DCE2_DEBUG__PAF_END_MSG);
+ return StreamSplitter::ABORT;
+ }
+
+ DebugFormat(DEBUG_DCE_SMB, "Start state: %u\n", ss->paf_state);
+
+ while (n < len)
+ {
+ DebugFormat(DEBUG_DCE_SMB, " State %d : 0x%02x", ss->paf_state, data[n]);
+
+ switch (ss->paf_state)
+ {
+ case DCE2_PAF_SMB_STATES__0:
+ ss->nb_hdr = (uint64_t)data[n];
+ ss->paf_state = (DCE2_PafSmbStates)(((int)ss->paf_state) + 1);
+ break;
+ case DCE2_PAF_SMB_STATES__3:
+ DCE2_SMB_PAF_SHIFT(ss->nb_hdr, data[n]);
+ if (DCE2_PafSmbIsValidNetbiosHdr((uint32_t)ss->nb_hdr, false))
+ {
+ nb_hdr = htonl((uint32_t)ss->nb_hdr);
+ nb_len = NbssLen((const NbssHdr*)&nb_hdr);
+ *fp = (nb_len + sizeof(NbssHdr) + n) - ss->paf_state;
+ ss->paf_state = DCE2_PAF_SMB_STATES__0;
+ DebugFormat(DEBUG_DCE_SMB,
+ "Setting flush point: %u\n", *fp);
+ DebugFormat(DEBUG_DCE_SMB, "%s\n", DCE2_DEBUG__PAF_END_MSG);
+ return StreamSplitter::FLUSH;
+ }
+ DebugMessage(DEBUG_DCE_SMB, "Invalid NetBIOS header - "
+ "entering junk data states.\n");
+ ss->paf_state = (DCE2_PafSmbStates)(((int)ss->paf_state) + 1);
+ break;
+ case DCE2_PAF_SMB_STATES__7:
+ DCE2_SMB_PAF_SHIFT(ss->nb_hdr, data[n]);
+
+ if (!DCE2_PafSmbIsValidNetbiosHdr((uint32_t)(ss->nb_hdr >> 32), true))
+ {
+ DebugMessage(DEBUG_DCE_SMB, "Invalid NetBIOS header - "
+ "staying in State 7.\n");
+ break;
+ }
+ if (((uint32_t)ss->nb_hdr != DCE2_SMB_ID)
+ && ((uint32_t)ss->nb_hdr != DCE2_SMB2_ID))
+ {
+ DebugMessage(DEBUG_DCE_SMB, "Invalid SMB ID - "
+ "staying in State 7.\n");
+ break;
+ }
+
+ nb_hdr = htonl((uint32_t)(ss->nb_hdr >> 32));
+ nb_len = NbssLen((const NbssHdr*)&nb_hdr);
+ *fp = (nb_len + sizeof(NbssHdr) + n) - ss->paf_state;
+ DebugFormat(DEBUG_DCE_SMB,
+ "Setting flush point: %u\n", *fp);
+ ss->paf_state = DCE2_PAF_SMB_STATES__0;
+ DebugFormat(DEBUG_DCE_SMB, "%s\n", DCE2_DEBUG__PAF_END_MSG);
+ return StreamSplitter::FLUSH;
+ default:
+ DCE2_SMB_PAF_SHIFT(ss->nb_hdr, data[n]);
+ ss->paf_state = (DCE2_PafSmbStates)(((int)ss->paf_state) + 1);
+ break;
+ }
+
+ n++;
+ }
+
+ DebugFormat(DEBUG_DCE_SMB, "%s\n", DCE2_DEBUG__PAF_END_MSG);
+ return ps;
+}
+
+Dce2SmbSplitter::Dce2SmbSplitter(bool c2s) : StreamSplitter(c2s)
+{
+ state.paf_state = DCE2_PAF_SMB_STATES__0;
+ state.nb_hdr = 0;
+}
+
+StreamSplitter::Status Dce2SmbSplitter::scan(
+ Flow* flow, const uint8_t* data, uint32_t len,
+ uint32_t flags, uint32_t* fp)
+{
+ DCE2_PafSmbData* pfdata = &state;
+ return dce2_smb_paf(pfdata, flow, data, len, flags, fp);
+}
+
--- /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_smb_paf.h author Rashmi Pitre <rrp@cisco.com>
+// based on work by Todd Wease
+
+#ifndef DCE_SMB_PAF_H
+#define DCE_SMB_PAF_H
+
+#include "main/snort_types.h"
+#include "stream/stream_api.h"
+#include "stream/stream_splitter.h"
+
+#define DCE2_SMB_PAF_SHIFT(x64, x8) { x64 <<= 8; x64 |= (uint64_t)x8; }
+#define DCE2_DEBUG__PAF_START_MSG_SMB "DCE/RPC over SMB PAF ====================================="
+
+// Enumerations for PAF states
+enum DCE2_PafSmbStates
+{
+ DCE2_PAF_SMB_STATES__0 = 0, // NetBIOS type
+ DCE2_PAF_SMB_STATES__1, // Added bit of NetBIOS length
+ DCE2_PAF_SMB_STATES__2, // First byte of NetBIOS length
+ DCE2_PAF_SMB_STATES__3, // Second byte of NetBIOS length
+ // Junk states
+ DCE2_PAF_SMB_STATES__4, // 0xff
+ DCE2_PAF_SMB_STATES__5, // 'S'
+ DCE2_PAF_SMB_STATES__6, // 'M'
+ DCE2_PAF_SMB_STATES__7 // 'B'
+};
+
+// State tracker for DCE/RPC over SMB PAF
+struct DCE2_PafSmbData
+{
+ DCE2_PafSmbStates paf_state;
+ uint64_t nb_hdr; // Enough for NetBIOS header and 4 bytes SMB header
+};
+
+class Dce2SmbSplitter : public StreamSplitter
+{
+public:
+ Dce2SmbSplitter(bool c2s);
+
+ Status scan(Flow*, const uint8_t* data, uint32_t len,
+ uint32_t flags, uint32_t* fp) override;
+
+ bool is_paf() override
+ {
+ return true;
+ }
+
+public:
+ DCE2_PafSmbData state;
+};
+
+#endif
+
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// dce2_tcp.cc author Rashmi Pitre <rrp@cisco.com>
+// dce_tcp.cc author Rashmi Pitre <rrp@cisco.com>
// based on work by Todd Wease
-#include "dce2_tcp.h"
-#include "dce2_tcp_module.h"
+#include "dce_tcp.h"
+#include "dce_tcp_paf.h"
+#include "dce_tcp_module.h"
+#include "main/snort_debug.h"
THREAD_LOCAL dce2TcpStats dce2_tcp_stats;
THREAD_LOCAL ProfileStats dce2_tcp_pstat_co_reass;
THREAD_LOCAL ProfileStats dce2_tcp_pstat_co_ctx;
+unsigned Dce2TcpFlowData::flow_id = 0;
+
+DCE2_TcpSsnData* get_dce2_tcp_session_data(Flow* flow)
+{
+ Dce2TcpFlowData* fd = (Dce2TcpFlowData*)flow->get_application_data(
+ Dce2TcpFlowData::flow_id);
+
+ return fd ? &fd->dce2_tcp_session : nullptr;
+}
+
//-------------------------------------------------------------------------
// class stuff
//-------------------------------------------------------------------------
void show(SnortConfig*) override;
void eval(Packet*) override;
+ StreamSplitter* get_splitter(bool c2s) override
+ {
+ return new Dce2TcpSplitter(c2s);
+ }
private:
dce2TcpProtoConf config;
void Dce2Tcp::eval(Packet* p)
{
- UNUSED(p);
+ DCE2_TcpSsnData* dce2_sess = get_dce2_tcp_session_data(p->flow);
+
+ if (dce2_sess == nullptr)
+ {
+ /*Check if it is a DCE2 over TCP packet*/
+
+ if (DCE2_TcpAutodetect(p))
+ {
+ DebugMessage(DEBUG_DCE_TCP, "DCE over TCP packet detected\n");
+ }
+
+ }
}
//-------------------------------------------------------------------------
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-//dce2_tcp.h author Rashmi Pitre <rrp@cisco.com>
+//dce_tcp.h author Rashmi Pitre <rrp@cisco.com>
// based on work by Todd Wease
-#ifndef DCE2_TCP_H
-#define DCE2_TCP_H
+#ifndef DCE_TCP_H
+#define DCE_TCP_H
+#include "dce_co.h"
#include "protocols/packet.h"
#include "profiler/profiler.h"
#include "framework/counts.h"
extern THREAD_LOCAL ProfileStats dce2_tcp_pstat_co_reass;
extern THREAD_LOCAL ProfileStats dce2_tcp_pstat_co_ctx;
+static inline bool DCE2_TcpAutodetect(Packet* p)
+{
+ if (p->dsize >= sizeof(DceRpcCoHdr))
+ {
+ DceRpcCoHdr* co_hdr = (DceRpcCoHdr*)p->data;
+
+ if ((DceRpcCoVersMaj(co_hdr) == DCERPC_PROTO_MAJOR_VERS__5)
+ && (DceRpcCoVersMin(co_hdr) == DCERPC_PROTO_MINOR_VERS__0)
+ && ((p->from_client()
+ && DceRpcCoPduType(co_hdr) == DCERPC_PDU_TYPE__BIND)
+ || (p->from_server()
+ && DceRpcCoPduType(co_hdr) == DCERPC_PDU_TYPE__BIND_ACK))
+ && (DceRpcCoFragLen(co_hdr) >= sizeof(DceRpcCoHdr)))
+ {
+ return true;
+ }
+ }
+ else if ((*p->data == DCERPC_PROTO_MAJOR_VERS__5) && p->from_client())
+ {
+ return true;
+ }
+
+ return false;
+}
+
+struct DCE2_TcpSsnData
+{
+ DCE2_SsnData sd; // This member must be first
+ // FIXIT-M add all the remaining fields
+};
+
+class Dce2TcpFlowData : public FlowData
+{
+public:
+ Dce2TcpFlowData();
+
+ static void init()
+ {
+ flow_id = FlowData::get_flow_id();
+ }
+
+public:
+ static unsigned flow_id;
+ DCE2_TcpSsnData dce2_tcp_session;
+};
+
+DCE2_TcpSsnData* get_dce2_tcp_session_data(Flow*);
+
#endif
// dce_tcp_module.cc author Rashmi Pitre <rrp@cisco.com>
-#include "dce2_tcp_module.h"
-#include "dce2_tcp.h"
-#include "dce2_common.h"
+#include "dce_tcp_module.h"
+#include "dce_tcp.h"
+#include "dce_common.h"
#include "main/snort_config.h"
-#include "dce2_co.h"
+#include "dce_co.h"
using namespace std;
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
//
-// dce2_tcp_module.h author Rashmi Pitre <rrp@cisco.com>
+// dce_tcp_module.h author Rashmi Pitre <rrp@cisco.com>
#ifndef DCE2_TCP_MODULE_H
#define DCE2_TCP_MODULE_H
-#include "dce2_common.h"
+#include "dce_common.h"
#include "framework/module.h"
struct SnortConfig;
--- /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_tcp_paf.cc author Rashmi Pitre <rrp@cisco.com>
+// based on work by Todd Wease
+
+#include "dce_tcp_paf.h"
+#include "dce_tcp.h"
+#include "dce_common.h"
+#include "main/snort_debug.h"
+
+/*********************************************************************
+ * Function: dce2_tcp_paf()
+ *
+ * Purpose: The DCE/RPC over TCP PAF callback.
+ * Inspects a byte at a time changing state. At state 4
+ * gets byte order of PDU. At states 8 and 9 gets
+ * fragment length and sets flush point if no more data.
+ * Otherwise accumulates flush points because there can
+ * be multiple PDUs in a single TCP segment (evasion case).
+ *
+ *********************************************************************/
+static StreamSplitter::Status dce2_tcp_paf(DCE2_PafTcpData* ds, Flow* flow, const uint8_t* data,
+ uint32_t len, uint32_t flags, uint32_t* fp)
+{
+ uint32_t n = 0;
+ int start_state;
+ StreamSplitter::Status ps = StreamSplitter::SEARCH;
+ uint32_t tmp_fp = 0;
+ DCE2_TcpSsnData* sd = get_dce2_tcp_session_data(flow);
+
+ int num_requests = 0;
+
+ DebugFormat(DEBUG_DCE_TCP, "%s\n", DCE2_DEBUG__PAF_START_MSG_TCP);
+ DebugFormat(DEBUG_DCE_TCP, "TCP: %u bytes of data\n", len);
+
+ if (flags & PKT_FROM_CLIENT)
+ DebugMessage(DEBUG_DCE_TCP, "Packet from Client\n");
+ else
+ DebugMessage(DEBUG_DCE_TCP, "Packet from Server\n");
+
+ if (dce2_paf_abort(flow))
+ {
+ DebugFormat(DEBUG_DCE_TCP, "%s\n", DCE2_DEBUG__PAF_END_MSG);
+ return StreamSplitter::ABORT;
+ }
+
+ if (sd == NULL)
+ {
+ bool autodetected = false;
+ DebugMessage(DEBUG_DCE_TCP, "No session data - autodetecting\n");
+
+ if (len >= sizeof(DceRpcCoHdr))
+ {
+ DceRpcCoHdr* co_hdr = (DceRpcCoHdr*)data;
+
+ if ((DceRpcCoVersMaj(co_hdr) == DCERPC_PROTO_MAJOR_VERS__5)
+ && (DceRpcCoVersMin(co_hdr) == DCERPC_PROTO_MINOR_VERS__0)
+ && (((flags & PKT_FROM_CLIENT)
+ && DceRpcCoPduType(co_hdr) == DCERPC_PDU_TYPE__BIND)
+ || ((flags & PKT_FROM_SERVER)
+ && DceRpcCoPduType(co_hdr) == DCERPC_PDU_TYPE__BIND_ACK))
+ && (DceRpcCoFragLen(co_hdr) >= sizeof(DceRpcCoHdr)))
+ {
+ autodetected = true;
+ DebugMessage(DEBUG_DCE_TCP, "Autodetected!\n");
+ }
+ }
+ else if ((*data == DCERPC_PROTO_MAJOR_VERS__5) && (flags & PKT_FROM_CLIENT))
+ {
+ autodetected = true;
+ DebugMessage(DEBUG_DCE_TCP, "Autodetected!\n");
+ }
+
+ if (!autodetected)
+ {
+ DebugMessage(DEBUG_DCE_TCP, "Couldn't autodetect - aborting\n");
+ DebugFormat(DEBUG_DCE_TCP, "%s\n", DCE2_DEBUG__PAF_END_MSG);
+ return StreamSplitter::ABORT;
+ }
+ }
+
+ DebugFormat(DEBUG_DCE_TCP, "Start state: %u\n", ds->paf_state);
+ start_state = (uint8_t)ds->paf_state;
+
+ while (n < len)
+ {
+ DebugFormat(DEBUG_DCE_TCP, " State %d : 0x%02x", ds->paf_state, data[n]);
+
+ switch (ds->paf_state)
+ {
+ case DCE2_PAF_TCP_STATES__4: // Get byte order
+ ds->byte_order = DceRpcByteOrder(data[n]);
+ ds->paf_state = (DCE2_PafTcpStates)(((int)ds->paf_state) + 1);
+ if (ds->byte_order == DCERPC_BO_FLAG__LITTLE_ENDIAN)
+ {
+ DebugMessage(DEBUG_DCE_TCP, "Byte order: Little endian\n");
+ }
+ else
+ {
+ DebugMessage(DEBUG_DCE_TCP, "Byte order: Big endian\n");
+ }
+ break;
+ case DCE2_PAF_TCP_STATES__8:
+ DebugMessage(DEBUG_DCE_TCP, "First byte of fragment length\n");
+ if (ds->byte_order == DCERPC_BO_FLAG__LITTLE_ENDIAN)
+ ds->frag_len = data[n];
+ else
+ ds->frag_len = data[n] << 8;
+ ds->paf_state = (DCE2_PafTcpStates)(((int)ds->paf_state) + 1);
+ break;
+ case DCE2_PAF_TCP_STATES__9:
+ DebugMessage(DEBUG_DCE_TCP, "Second byte of fragment length\n");
+ if (ds->byte_order == DCERPC_BO_FLAG__LITTLE_ENDIAN)
+ ds->frag_len |= data[n] << 8;
+ else
+ ds->frag_len |= data[n];
+
+ /* If we get a bad frag length abort */
+ if (ds->frag_len < sizeof(DceRpcCoHdr))
+ {
+ DebugFormat(DEBUG_DCE_TCP, "%s\n", DCE2_DEBUG__PAF_END_MSG);
+ return StreamSplitter::ABORT;
+ }
+
+ DebugFormat(DEBUG_DCE_TCP, "Fragment length: %u\n", ds->frag_len);
+
+ /* Increment n here so we can continue */
+ n += ds->frag_len - (uint8_t)ds->paf_state;
+ num_requests++;
+ /* Might have multiple PDUs in one segment. If the last PDU is partial,
+ * flush just before it */
+ if ((num_requests == 1) || (n <= len))
+ tmp_fp += ds->frag_len;
+ DebugFormat(DEBUG_DCE_TCP, "Requests: %u\n", num_requests);
+ ds->paf_state = DCE2_PAF_TCP_STATES__0;
+ continue; // we incremented n already
+ default:
+ ds->paf_state = (DCE2_PafTcpStates)(((int)ds->paf_state) + 1);
+ break;
+ }
+
+ n++;
+ }
+
+ if (tmp_fp != 0)
+ {
+ *fp = tmp_fp - start_state;
+ DebugFormat(DEBUG_DCE_TCP, "Setting flush point: %u\n", *fp);
+ DebugFormat(DEBUG_DCE_TCP, "%s\n", DCE2_DEBUG__PAF_END_MSG);
+ return StreamSplitter::FLUSH;
+ }
+
+ DebugFormat(DEBUG_DCE_TCP, "%s\n", DCE2_DEBUG__PAF_END_MSG);
+ return ps;
+}
+
+Dce2TcpSplitter::Dce2TcpSplitter(bool c2s) : StreamSplitter(c2s)
+{
+ state.paf_state = DCE2_PAF_TCP_STATES__0;
+ state.byte_order = DCERPC_BO_FLAG__NONE;
+ state.frag_len = 0;
+}
+
+StreamSplitter::Status Dce2TcpSplitter::scan(
+ Flow* flow, const uint8_t* data, uint32_t len,
+ uint32_t flags, uint32_t* fp)
+{
+ DCE2_PafTcpData* pfdata = &state;
+ return dce2_tcp_paf(pfdata, flow, data, len, flags, fp);
+}
+
--- /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_tcp_paf.h author Rashmi Pitre <rrp@cisco.com>
+// based on work by Todd Wease
+
+#ifndef DCE_TCP_PAF_H
+#define DCE_TCP_PAF_H
+
+#include "dce_common.h"
+#include "main/snort_types.h"
+#include "stream/stream_api.h"
+#include "stream/stream_splitter.h"
+
+#define DCE2_DEBUG__PAF_START_MSG_TCP "DCE/RPC over TCP PAF ====================================="
+
+enum DCE2_PafTcpStates
+{
+ DCE2_PAF_TCP_STATES__0 = 0,
+ DCE2_PAF_TCP_STATES__1,
+ DCE2_PAF_TCP_STATES__2,
+ DCE2_PAF_TCP_STATES__3,
+ DCE2_PAF_TCP_STATES__4, // Byte order
+ DCE2_PAF_TCP_STATES__5,
+ DCE2_PAF_TCP_STATES__6,
+ DCE2_PAF_TCP_STATES__7,
+ DCE2_PAF_TCP_STATES__8, // First byte of fragment length
+ DCE2_PAF_TCP_STATES__9 // Second byte of fragment length
+};
+
+// State tracker for DCE/RPC over TCP PAF
+struct DCE2_PafTcpData
+{
+ DCE2_PafTcpStates paf_state;
+ DceRpcBoFlag byte_order;
+ uint16_t frag_len;
+};
+
+class Dce2TcpSplitter : public StreamSplitter
+{
+public:
+ Dce2TcpSplitter(bool c2s);
+
+ Status scan(Flow*, const uint8_t* data, uint32_t len,
+ uint32_t flags, uint32_t* fp) override;
+
+ bool is_paf() override
+ {
+ return true;
+ }
+
+public:
+ DCE2_PafTcpData state;
+};
+
+#endif
+
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-#include "dce2_utils.h"
+#include "dce_utils.h"
/********************************************************************
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-#ifndef _DCE2_UTILS_H_
-#define _DCE2_UTILS_H_
+#ifndef _DCE_UTILS_H_
+#define _DCE_UTILS_H_
#include <string.h>
#include <ctype.h>
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// ips_dce2_iface.cc author Maya Dagon <mdagon@cisco.com>
+// ips_dce_iface.cc author Maya Dagon <mdagon@cisco.com>
// based on work by Todd Wease
-#include "dce2_utils.h"
+#include "dce_utils.h"
#include "framework/ips_option.h"
#include "framework/module.h"
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// ips_dce2_opnum.cc author Maya Dagon <mdagon@cisco.com>
+// ips_dce_opnum.cc author Maya Dagon <mdagon@cisco.com>
// based on work by Todd Wease
-#include "dce2_utils.h"
+#include "dce_utils.h"
#include "framework/ips_option.h"
#include "framework/module.h"
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// ips_dce2_stub_data.cc author Maya Dagon <mdagon@cisco.com>
+// ips_dce_stub_data.cc author Maya Dagon <mdagon@cisco.com>
// based on work by Todd Wease
#include "detection/detection_defines.h"