src/service_inspectors/rpc_decode/Makefile \
src/service_inspectors/smtp/Makefile \
src/service_inspectors/ssh/Makefile \
+src/service_inspectors/ssl/Makefile \
src/service_inspectors/wizard/Makefile \
src/protocols/Makefile \
src/search_engines/Makefile \
port_scan = { }
rpc_decode = { }
ssh = { }
+ssl = { }
telnet = { }
-- use http_inspect or new_http_inspect (incomplete)
rpc_decode
smtp
ssh
+ ssl
wizard
)
endif()
service_inspectors/rpc_decode/librpc_decode.a \
service_inspectors/smtp/libsmtp.a \
service_inspectors/ssh/libssh.a \
+service_inspectors/ssl/libssl.a \
service_inspectors/wizard/libwizard.a
endif
add_subdirectory(rpc_decode)
add_subdirectory(smtp)
add_subdirectory(ssh)
+add_subdirectory(ssl)
add_subdirectory(wizard)
if (STATIC_INSPECTORS)
rpc_decode \
smtp \
ssh \
+ssl \
wizard
AM_CXXFLAGS = @AM_CXXFLAGS@
extern const BaseApi* sin_http_inspect;
#ifdef STATIC_INSPECTORS
+extern const BaseApi* ips_ssl_state;
+extern const BaseApi* ips_ssl_version;
extern const BaseApi* sin_bo;
extern const BaseApi* sin_dns;
extern const BaseApi* sin_ftp_client;
extern const BaseApi* sin_rpc_decode;
extern const BaseApi* sin_smtp;
extern const BaseApi* sin_ssh;
+extern const BaseApi* sin_ssl;
extern const BaseApi* sin_telnet;
extern const BaseApi* sin_wizard;
#endif
sin_http_inspect,
#ifdef STATIC_INSPECTORS
+ ips_ssl_state,
+ ips_ssl_version,
sin_bo,
sin_dns,
sin_ftp_client,
sin_rpc_decode,
sin_smtp,
sin_ssh,
+ sin_ssl,
sin_telnet,
sin_wizard,
#endif
static unsigned int ProcessSSHKeyExchange(SSHData*, Packet*, uint8_t, unsigned int);
static unsigned int ProcessSSHKeyInitExchange(SSHData*, Packet*, uint8_t, unsigned int);
-/* Ultimately calls SnortEventqAdd
- Arguments are: gid, sid, rev, classification, priority, message, rule_info */
-
unsigned SshFlowData::flow_id = 0;
SSHData* SetNewSSHData(Packet* p)
--- /dev/null
+
+set( FILE_LIST
+ ssl_inspector.cc
+ ssl_inspector.h
+ ssl_config.h
+ ssl_module.cc
+ ssl_module.h
+ ips_ssl_state.cc
+ ips_ssl_version.cc
+)
+
+if (STATIC_INSPECTORS)
+ add_library( ssl STATIC ${FILE_LIST})
+
+else (STATIC_INSPECTORS)
+ add_shared_library(ssl inspectors ${FILE_LIST})
+
+endif (STATIC_INSPECTORS)
--- /dev/null
+AUTOMAKE_OPTIONS=foreign no-dependencies
+
+file_list = \
+ssl_config.h \
+ssl_inspector.cc \
+ssl_inspector.h \
+ssl_module.cc \
+ssl_module.h \
+ips_ssl_state.cc \
+ips_ssl_version.cc
+
+if STATIC_INSPECTORS
+noinst_LIBRARIES = libssl.a
+libssl_a_SOURCES = $(file_list)
+else
+shlibdir = $(pkglibdir)/inspectors
+shlib_LTLIBRARIES = libssl.la
+libssl_la_CXXFLAGS = $(AM_CXXFLAGS) -DBUILDING_SO
+libssl_la_LDFLAGS = -export-dynamic -shared
+libssl_la_SOURCES = $(file_list)
+endif
+
+AM_CXXFLAGS = @AM_CXXFLAGS@
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 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.
+//--------------------------------------------------------------------------
+// ips_ssl_state.cc author Bhagyashree Bantwal <bbantwal@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "ssl_inspector.h"
+#include "protocols/ssl.h"
+#include "framework/ips_option.h"
+#include "framework/module.h"
+#include "framework/parameter.h"
+#include "detection/detect.h"
+#include "detection/detection_defines.h"
+#include "hash/sfhashfcn.h"
+#include "time/profiler.h"
+
+//-------------------------------------------------------------------------
+// ssl_state
+//-------------------------------------------------------------------------
+
+#define s_name "ssl_state"
+#define s_help \
+ "detection option for ssl state"
+
+static THREAD_LOCAL ProfileStats sslStateRuleOptionPerfStats;
+
+struct SslStateRuleOptionData
+{
+ int flags;
+ int mask;
+};
+
+class SslStateOption : public IpsOption
+{
+public:
+ SslStateOption(const SslStateRuleOptionData& c) :
+ IpsOption(s_name)
+ { ssod = c; }
+
+ uint32_t hash() const override;
+ bool operator==(const IpsOption&) const override;
+
+ int eval(Cursor&, Packet*) override;
+
+private:
+ SslStateRuleOptionData ssod;
+};
+
+//-------------------------------------------------------------------------
+// ssl_state option
+//-------------------------------------------------------------------------
+
+uint32_t SslStateOption::hash() const
+{
+ uint32_t a,b,c;
+
+ a = ssod.flags;
+ b = ssod.mask;
+ c = 0;
+
+ mix_str(a,b,c,get_name());
+ final (a,b,c);
+
+ return c;
+}
+
+bool SslStateOption::operator==(const IpsOption& ips) const
+{
+ if ( strcmp(get_name(), ips.get_name()) )
+ return false;
+
+ const SslStateOption& rhs = (SslStateOption&)ips;
+
+ if ( (ssod.flags == rhs.ssod.flags) &&
+ (ssod.mask == rhs.ssod.mask) )
+ return true;
+
+ return false;
+}
+
+int SslStateOption::eval(Cursor&, Packet* pkt)
+{
+ SSLData* sd;
+
+ PROFILE_VARS;
+ MODULE_PROFILE_START(sslStateRuleOptionPerfStats);
+
+ if ( !(pkt->packet_flags & PKT_REBUILT_STREAM) && !pkt->is_full_pdu() )
+ {
+ MODULE_PROFILE_END(sslStateRuleOptionPerfStats);
+ return DETECTION_OPTION_NO_MATCH;
+ }
+
+ if (!pkt->flow)
+ {
+ MODULE_PROFILE_END(sslStateRuleOptionPerfStats);
+ return DETECTION_OPTION_NO_MATCH;
+ }
+
+ sd = get_ssl_session_data(pkt->flow);
+
+ if (!sd)
+ {
+ MODULE_PROFILE_END(sslStateRuleOptionPerfStats);
+ return DETECTION_OPTION_NO_MATCH;
+ }
+
+ if ((ssod.flags & sd->ssn_flags) ^ ssod.mask)
+ {
+ MODULE_PROFILE_END(sslStateRuleOptionPerfStats);
+ return DETECTION_OPTION_MATCH;
+ }
+
+ MODULE_PROFILE_END(sslStateRuleOptionPerfStats);
+
+ return DETECTION_OPTION_NO_MATCH;
+}
+
+//-------------------------------------------------------------------------
+// ssl_state module
+//-------------------------------------------------------------------------
+
+static const Parameter s_params[] =
+{
+ { "client_hello", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "check for client hello" },
+
+ { "server_hello", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "check for server hello" },
+
+ { "client_keyx", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "check for client keyx" },
+
+ { "server_keyx", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "check for server keyx" },
+
+ { "unknown", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "check for unknown record" },
+
+ { "!client_hello", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "check for records that are not client hello" },
+
+ { "!server_hello", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "check for records that are not server hello" },
+
+ { "!client_keyx", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "check for records that are not client keyx" },
+
+ { "!server_keyx", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "check for records that are not server keyx" },
+
+ { "!unknown", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "check for records that are not unknown" },
+
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+class SslStateModule : public Module
+{
+public:
+ SslStateModule() : Module(s_name, s_help, s_params) { }
+
+ bool begin(const char*, int, SnortConfig*) override;
+ bool set(const char*, Value&, SnortConfig*) override;
+
+ ProfileStats* get_profile() const override
+ { return &sslStateRuleOptionPerfStats; }
+
+ SslStateRuleOptionData ssod;
+};
+
+bool SslStateModule::begin(const char*, int, SnortConfig*)
+{
+ ssod.flags = 0;
+ ssod.mask = 0;
+ return true;
+}
+
+bool SslStateModule::set(const char*, Value& v, SnortConfig*)
+{
+ if ( v.is("client_hello") )
+ ssod.flags |= SSL_CUR_CLIENT_HELLO_FLAG;
+
+ else if ( v.is("server_hello") )
+ ssod.flags |= SSL_CUR_SERVER_HELLO_FLAG;
+
+ else if ( v.is("client_keyx") )
+ ssod.flags |= SSL_CUR_CLIENT_KEYX_FLAG;
+
+ else if ( v.is("server_keyx") )
+ ssod.flags |= SSL_CUR_SERVER_KEYX_FLAG;
+
+ else if ( v.is("unknown") )
+ ssod.flags |= SSL_UNKNOWN_FLAG;
+
+ else if ( v.is("!client_hello") )
+ {
+ ssod.flags |= SSL_CUR_CLIENT_HELLO_FLAG;
+ ssod.mask |= SSL_CUR_CLIENT_HELLO_FLAG;
+ }
+ else if ( v.is("!server_hello") )
+ {
+ ssod.flags |= SSL_CUR_SERVER_HELLO_FLAG;
+ ssod.mask |= SSL_CUR_SERVER_HELLO_FLAG;
+ }
+ else if ( v.is("!client_keyx") )
+ {
+ ssod.flags |= SSL_CUR_CLIENT_KEYX_FLAG;
+ ssod.mask |= SSL_CUR_CLIENT_KEYX_FLAG;
+ }
+ else if ( v.is("!server_keyx") )
+ {
+ ssod.flags |= SSL_CUR_SERVER_KEYX_FLAG;
+ ssod.mask |= SSL_CUR_SERVER_KEYX_FLAG;
+ }
+ else if ( v.is("!unknown") )
+ {
+ ssod.flags |= SSL_UNKNOWN_FLAG;
+ ssod.mask |= SSL_UNKNOWN_FLAG;
+ }
+ else
+ return false;
+
+ return true;
+}
+
+//-------------------------------------------------------------------------
+// ssl_state api methods
+//-------------------------------------------------------------------------
+
+static Module* ssl_state_mod_ctor()
+{
+ return new SslStateModule;
+}
+
+static void mod_dtor(Module* m)
+{
+ delete m;
+}
+
+static IpsOption* ssl_state_ctor(Module* p, OptTreeNode*)
+{
+ SslStateModule* m = (SslStateModule*)p;
+ return new SslStateOption(m->ssod);
+}
+
+static void opt_dtor(IpsOption* p)
+{
+ delete p;
+}
+
+static const IpsApi ssl_state_api =
+{
+ {
+ PT_IPS_OPTION,
+ sizeof(IpsApi),
+ IPSAPI_VERSION,
+ 0,
+ API_RESERVED,
+ API_OPTIONS,
+ s_name,
+ s_help,
+ ssl_state_mod_ctor,
+ mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 0, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ ssl_state_ctor,
+ opt_dtor,
+ nullptr
+};
+
+const BaseApi* ips_ssl_state = &ssl_state_api.base;
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 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.
+//--------------------------------------------------------------------------
+// ips_ssl_version.cc author Bhagyashree Bantwal <bbantwal@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "ssl_inspector.h"
+#include "protocols/ssl.h"
+#include "framework/ips_option.h"
+#include "framework/module.h"
+#include "framework/parameter.h"
+#include "detection/detect.h"
+#include "detection/detection_defines.h"
+#include "hash/sfhashfcn.h"
+#include "time/profiler.h"
+
+//-------------------------------------------------------------------------
+// ssl_version
+//-------------------------------------------------------------------------
+
+#define s_name "ssl_version"
+#define s_help \
+ "detection option for ssl version"
+
+static THREAD_LOCAL ProfileStats sslVersionRuleOptionPerfStats;
+
+struct SslVersionRuleOptionData
+{
+ int flags;
+ int mask;
+};
+
+class SslVersionOption : public IpsOption
+{
+public:
+ SslVersionOption(const SslVersionRuleOptionData& c) :
+ IpsOption(s_name)
+ { svod = c; }
+
+ uint32_t hash() const override;
+ bool operator==(const IpsOption&) const override;
+
+ int eval(Cursor&, Packet*) override;
+
+private:
+ SslVersionRuleOptionData svod;
+};
+
+//-------------------------------------------------------------------------
+// ssl_version option
+//-------------------------------------------------------------------------
+
+uint32_t SslVersionOption::hash() const
+{
+ uint32_t a,b,c;
+
+ a = svod.flags;
+ b = svod.mask;
+ c = 0;
+
+ mix_str(a,b,c,get_name());
+ final (a,b,c);
+
+ return c;
+}
+
+bool SslVersionOption::operator==(const IpsOption& ips) const
+{
+ if ( strcmp(get_name(), ips.get_name()) )
+ return false;
+
+ const SslVersionOption& rhs = (SslVersionOption&)ips;
+
+ if ( (svod.flags == rhs.svod.flags) &&
+ (svod.mask == rhs.svod.mask) )
+ return true;
+
+ return false;
+}
+
+int SslVersionOption::eval(Cursor&, Packet* pkt)
+{
+ SSLData* sd;
+
+ PROFILE_VARS;
+ MODULE_PROFILE_START(sslVersionRuleOptionPerfStats);
+
+ if ( !(pkt->packet_flags & PKT_REBUILT_STREAM) && !pkt->is_full_pdu() )
+ {
+ MODULE_PROFILE_END(sslVersionRuleOptionPerfStats);
+ return DETECTION_OPTION_NO_MATCH;
+ }
+
+ if (!pkt->flow)
+ {
+ MODULE_PROFILE_END(sslVersionRuleOptionPerfStats);
+ return DETECTION_OPTION_NO_MATCH;
+ }
+
+ sd = get_ssl_session_data(pkt->flow);
+
+ if (!sd)
+ {
+ MODULE_PROFILE_END(sslVersionRuleOptionPerfStats);
+ return DETECTION_OPTION_NO_MATCH;
+ }
+
+ if ((svod.flags & sd->ssn_flags) ^ svod.mask)
+ {
+ MODULE_PROFILE_END(sslVersionRuleOptionPerfStats);
+ return DETECTION_OPTION_MATCH;
+ }
+
+ MODULE_PROFILE_END(sslVersionRuleOptionPerfStats);
+
+ return DETECTION_OPTION_NO_MATCH;
+}
+
+//-------------------------------------------------------------------------
+// ssl_version module
+//-------------------------------------------------------------------------
+
+static const Parameter s_params[] =
+{
+ { "sslv2", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "check for sslv2" },
+
+ { "sslv3", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "check for sslv3" },
+
+ { "tls1.0", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "check for tls1.0" },
+
+ { "tls1.1", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "check for tls1.1" },
+
+ { "tls1.2", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "check for tls1.2" },
+
+ { "!sslv2", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "check for records that are not sslv2" },
+
+ { "!sslv3", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "check for records that are not sslv3" },
+
+ { "!tls1.0", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "check for records that are not tls1.0" },
+
+ { "!tls1.1", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "check for records that are not tls1.1" },
+
+ { "!tls1.2", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "check for records that are not tls1.2" },
+
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+class SslVersionModule : public Module
+{
+public:
+ SslVersionModule() : Module(s_name, s_help, s_params) { }
+
+ bool begin(const char*, int, SnortConfig*) override;
+ bool set(const char*, Value&, SnortConfig*) override;
+
+ ProfileStats* get_profile() const override
+ { return &sslVersionRuleOptionPerfStats; }
+
+ SslVersionRuleOptionData svod;
+};
+
+bool SslVersionModule::begin(const char*, int, SnortConfig*)
+{
+ svod.flags = 0;
+ svod.mask = 0;
+ return true;
+}
+
+bool SslVersionModule::set(const char*, Value& v, SnortConfig*)
+{
+
+ if ( v.is("sslv2") )
+ svod.flags |= SSL_VER_SSLV2_FLAG;
+
+ else if ( v.is("sslv3") )
+ svod.flags |= SSL_VER_SSLV3_FLAG;
+
+ else if ( v.is("tls1.0") )
+ svod.flags |= SSL_VER_TLS10_FLAG;
+
+ else if ( v.is("tls1.1") )
+ svod.flags |= SSL_VER_TLS11_FLAG;
+
+ else if ( v.is("tls1.2") )
+ svod.flags |= SSL_VER_TLS12_FLAG;
+
+ else if ( v.is("!sslv2") )
+ {
+ svod.flags |= SSL_VER_SSLV2_FLAG;
+ svod.mask |= SSL_VER_SSLV2_FLAG;
+ }
+ else if ( v.is("!sslv3") )
+ {
+ svod.flags |= SSL_VER_SSLV3_FLAG;
+ svod.mask |= SSL_VER_SSLV3_FLAG;
+ }
+ else if ( v.is("!tls1.0") )
+ {
+ svod.flags |= SSL_VER_TLS10_FLAG;
+ svod.mask |= SSL_VER_TLS10_FLAG;
+ }
+ else if ( v.is("!tls1.1") )
+ {
+ svod.flags |= SSL_VER_TLS11_FLAG;
+ svod.mask |= SSL_VER_TLS11_FLAG;
+ }
+ else if ( v.is("!tls1.2") )
+ {
+ svod.flags |= SSL_VER_TLS12_FLAG;
+ svod.mask |= SSL_VER_TLS12_FLAG;
+ }
+ else
+ return false;
+
+ return true;
+}
+
+//-------------------------------------------------------------------------
+// ssl_version api methods
+//-------------------------------------------------------------------------
+
+static Module* ssl_version_mod_ctor()
+{
+ return new SslVersionModule;
+}
+
+static void mod_dtor(Module* m)
+{
+ delete m;
+}
+
+static IpsOption* ssl_version_ctor(Module* p, OptTreeNode*)
+{
+ SslVersionModule* m = (SslVersionModule*)p;
+ return new SslVersionOption(m->svod);
+}
+
+static void opt_dtor(IpsOption* p)
+{
+ delete p;
+}
+
+static const IpsApi ssl_version_api =
+{
+ {
+ PT_IPS_OPTION,
+ sizeof(IpsApi),
+ IPSAPI_VERSION,
+ 0,
+ API_RESERVED,
+ API_OPTIONS,
+ s_name,
+ s_help,
+ ssl_version_mod_ctor,
+ mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 0, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ ssl_version_ctor,
+ opt_dtor,
+ nullptr
+};
+
+const BaseApi* ips_ssl_version = &ssl_version_api.base;
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 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.
+//--------------------------------------------------------------------------
+//
+
+#ifndef SSL_CONFIG_H
+#define SSL_CONFIG_H
+
+#define SSLPP_TRUSTSERVER_FLAG 0x0002
+
+/*
+ * Global SSL preprocessor configuration.
+ *
+ */
+struct SSL_PROTO_CONF
+{
+ uint16_t flags;
+ int max_heartbeat_len;
+};
+
+#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 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.
+//--------------------------------------------------------------------------
+//
+
+/*
+ * SSL inspector
+ *
+ */
+
+#include "ssl_inspector.h"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "snort_types.h"
+#include "snort_debug.h"
+
+#include "ssl.h"
+#include "ssl_module.h"
+#include "profiler.h"
+#include "stream/stream_api.h"
+#include "parser.h"
+#include "framework/inspector.h"
+#include "utils/sfsnprintfappend.h"
+#include "target_based/sftarget_protocol_reference.h"
+#include "detect.h"
+
+THREAD_LOCAL ProfileStats sslPerfStats;
+THREAD_LOCAL SimpleStats sslstats;
+THREAD_LOCAL SSL_counters_t counts;
+
+/*
+ * Function prototype(s)
+ */
+static void snort_ssl(SSL_PROTO_CONF* GlobalConf, Packet* p);
+
+unsigned SslFlowData::flow_id = 0;
+
+SSLData* SetNewSSLData(Packet* p)
+{
+ SslFlowData* fd = new SslFlowData;
+ p->flow->set_application_data(fd);
+ return &fd->session;
+}
+
+SSLData* get_ssl_session_data(Flow* flow)
+{
+ SslFlowData* fd = (SslFlowData*)flow->get_application_data(
+ SslFlowData::flow_id);
+
+ return fd ? &fd->session : NULL;
+}
+
+void SSL_InitGlobals(void)
+{
+ memset(&counts, 0, sizeof(counts));
+}
+
+static void PrintSslConf(SSL_PROTO_CONF* config)
+{
+ if (config == NULL)
+ return;
+ LogMessage("SSL config:\n");
+ if ( config->flags & SSLPP_TRUSTSERVER_FLAG )
+ {
+ LogMessage(" Server side data is trusted\n");
+ }
+
+ LogMessage("\n");
+}
+
+static void SSL_UpdateCounts(const uint32_t new_flags)
+{
+ if (new_flags & SSL_CHANGE_CIPHER_FLAG)
+ counts.cipher_change++;
+
+ if (new_flags & SSL_ALERT_FLAG)
+ counts.alerts++;
+
+ if (new_flags & SSL_CLIENT_HELLO_FLAG)
+ counts.hs_chello++;
+
+ if (new_flags & SSL_SERVER_HELLO_FLAG)
+ counts.hs_shello++;
+
+ if (new_flags & SSL_CERTIFICATE_FLAG)
+ counts.hs_cert++;
+
+ if (new_flags & SSL_SERVER_KEYX_FLAG)
+ counts.hs_skey++;
+
+ if (new_flags & SSL_CLIENT_KEYX_FLAG)
+ counts.hs_ckey++;
+
+ if (new_flags & SSL_SFINISHED_FLAG)
+ counts.hs_finished++;
+
+ if (new_flags & SSL_HS_SDONE_FLAG)
+ counts.hs_sdone++;
+
+ if (new_flags & SSL_SAPP_FLAG)
+ counts.sapp++;
+
+ if (new_flags & SSL_CAPP_FLAG)
+ counts.capp++;
+}
+
+static inline bool SSLPP_is_encrypted(SSL_PROTO_CONF* config, uint32_t ssl_flags, Packet* packet)
+{
+ if (config->flags & SSLPP_TRUSTSERVER_FLAG)
+ {
+ if (ssl_flags & SSL_SAPP_FLAG)
+ return true;
+ }
+
+ if (SSL_IS_CLEAN(ssl_flags))
+ {
+ if (((ssl_flags & SSLPP_ENCRYPTED_FLAGS) == SSLPP_ENCRYPTED_FLAGS) ||
+ ((ssl_flags & SSLPP_ENCRYPTED_FLAGS2) == SSLPP_ENCRYPTED_FLAGS2))
+ {
+ counts.completed_hs++;
+ return true;
+ }
+ /* Check if we're either midstream or if packets were missed after the
+ * * connection was established */
+ else if ((stream.get_session_flags (packet->flow) & SSNFLAG_MIDSTREAM) ||
+ (stream.missed_packets(packet->flow, SSN_DIR_BOTH)))
+ {
+ if ((ssl_flags & (SSL_CAPP_FLAG | SSL_SAPP_FLAG)) == (SSL_CAPP_FLAG | SSL_SAPP_FLAG))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static inline uint32_t SSLPP_process_alert(SSL_PROTO_CONF* config, uint32_t ssn_flags, uint32_t
+ new_flags, Packet* packet)
+{
+ DEBUG_WRAP(DebugMessage(DEBUG_SSL, "Process Alert\n"); );
+
+ ssn_flags |= new_flags;
+
+ /* Check if we've seen a handshake, that this isn't it,
+ * * that the cipher flags is not set, and that we are disabling detection */
+ if (SSL_IS_HANDSHAKE(ssn_flags) &&
+ !SSL_IS_HANDSHAKE(new_flags) &&
+ !(new_flags & SSL_CHANGE_CIPHER_FLAG) &&
+ !(new_flags & SSL_HEARTBEAT_SEEN))
+ {
+ DEBUG_WRAP(DebugMessage(DEBUG_SSL, "Disabling detect\n"); );
+ DisableDetect(packet);
+ }
+
+ /* Need to negate the application flags from the opposing side. */
+
+ if (packet->packet_flags & PKT_FROM_CLIENT)
+ return ssn_flags & ~SSL_SAPP_FLAG;
+
+ else if (packet->packet_flags & PKT_FROM_SERVER)
+ return ssn_flags & ~SSL_CAPP_FLAG;
+
+ return ssn_flags;
+}
+
+static inline uint32_t SSLPP_process_hs(uint32_t ssl_flags, uint32_t new_flags)
+{
+ DEBUG_WRAP(DebugMessage(DEBUG_SSL, "Process Handshake\n"); );
+
+ if (!SSL_BAD_HS(new_flags))
+ {
+ ssl_flags |= new_flags & (SSL_CLIENT_HELLO_FLAG |
+ SSL_SERVER_HELLO_FLAG |
+ SSL_CLIENT_KEYX_FLAG |
+ SSL_SFINISHED_FLAG);
+ }
+ else
+ {
+ counts.bad_handshakes++;
+ }
+
+ return ssl_flags;
+}
+
+static inline uint32_t SSLPP_process_app(SSL_PROTO_CONF* config, uint32_t ssn_flags, uint32_t
+ new_flags, Packet* packet)
+{
+ DEBUG_WRAP(DebugMessage(DEBUG_SSL, "Process Application\n"); );
+
+ if (SSLPP_is_encrypted(config, ssn_flags | new_flags, packet) )
+ {
+ ssn_flags |= SSL_ENCRYPTED_FLAG;
+
+ // Heartbleed check is disabled. Stop inspection on this session.
+ if (!config->max_heartbeat_len)
+ {
+ DEBUG_WRAP(DebugMessage(DEBUG_SSL, "STOPPING INSPECTION (process_app)\n"); );
+ stream.stop_inspection(packet->flow,
+ packet, SSN_DIR_BOTH, -1, 0);
+ counts.stopped++;
+ }
+ else if (!(new_flags & SSL_HEARTBEAT_SEEN))
+ {
+ DisableDetect(packet);
+ }
+ }
+
+ return ssn_flags | new_flags;
+}
+
+static inline void SSLPP_process_other(SSL_PROTO_CONF* config, SSLData* sd, uint32_t new_flags,
+ Packet* packet)
+{
+ /* Encrypted SSLv2 will appear unrecognizable. Check if the handshake was
+ * * seen and stop inspecting if so. */
+ /* Check for an existing handshake from both sides */
+ if ((sd->ssn_flags & SSL_VER_SSLV2_FLAG) &&
+ SSL_IS_CHELLO(sd->ssn_flags) && SSL_IS_SHELLO(sd->ssn_flags) &&
+ !(new_flags & SSL_CHANGE_CIPHER_FLAG) &&
+ !(new_flags & SSL_HEARTBEAT_SEEN))
+ {
+ sd->ssn_flags |= SSL_ENCRYPTED_FLAG | new_flags;
+
+ if (!config->max_heartbeat_len)
+ {
+ DEBUG_WRAP(DebugMessage(DEBUG_SSL, "STOPPING INSPECTION (process_other)\n"); );
+ stream.stop_inspection(packet->flow,
+ packet, SSN_DIR_BOTH, -1, 0);
+ }
+ else if (!(new_flags & SSL_HEARTBEAT_SEEN))
+ {
+ DisableDetect(packet);
+ }
+ }
+ else
+ {
+ counts.unrecognized++;
+
+ /* Special handling for SSLv2 */
+ if (new_flags & SSL_VER_SSLV2_FLAG)
+ sd->ssn_flags |= new_flags;
+
+ if (new_flags & SSL_UNKNOWN_FLAG)
+ sd->ssn_flags |= new_flags;
+ }
+}
+
+/* Main runtime entry point for SSL preprocessor.
+ * Analyzes SSL packets for anomalies/exploits.
+ *
+ * PARAMETERS:
+ *
+ * p: Pointer to current packet to process.
+ * contextp: Pointer to context block, not used.
+ *
+ * RETURNS: Nothing.
+ */
+static void snort_ssl(SSL_PROTO_CONF* config, Packet* p)
+{
+ SSLData* sd = NULL;
+ uint8_t dir;
+ uint8_t index;
+ uint32_t new_flags;
+ uint8_t heartbleed_type = 0;
+ PROFILE_VARS;
+
+ MODULE_PROFILE_START(sslPerfStats);
+
+ /* Attempt to get a previously allocated SSL block. */
+ sd = get_ssl_session_data(p->flow);
+
+ if (sd == NULL)
+ {
+ /* Check the stream session. If it does not currently
+ * have our SSL data-block attached, create one.
+ */
+ sd = SetNewSSLData(p);
+
+ if ( !sd )
+ {
+ /* Could not get/create the session data for this packet. */
+ MODULE_PROFILE_END(sslPerfStats);
+ return;
+ }
+ }
+ SSL_CLEAR_TEMPORARY_FLAGS(sd->ssn_flags);
+
+ dir = (p->packet_flags & PKT_FROM_SERVER) ? 1 : 0;
+ index = (p->packet_flags & PKT_REBUILT_STREAM) ? 2 : 0;
+ new_flags = SSL_decode(p->data, (int)p->dsize, p->packet_flags, sd->ssn_flags,
+ &heartbleed_type, &(sd->partial_rec_len[dir+index]), config->max_heartbeat_len);
+
+ if (heartbleed_type & SSL_HEARTBLEED_REQUEST)
+ {
+ SnortEventqAdd(GID_SSL, SSL_ALERT_HB_REQUEST);
+ }
+ else if (heartbleed_type & SSL_HEARTBLEED_RESPONSE)
+ {
+ SnortEventqAdd(GID_SSL, SSL_ALERT_HB_RESPONSE);
+ }
+ else if (heartbleed_type & SSL_HEARTBLEED_UNKNOWN)
+ {
+ if (!dir)
+ {
+ SnortEventqAdd(GID_SSL, SSL_ALERT_HB_REQUEST);
+ }
+ else
+ {
+ SnortEventqAdd(GID_SSL, SSL_ALERT_HB_RESPONSE);
+ }
+ }
+ if (sd->ssn_flags & SSL_ENCRYPTED_FLAG )
+ {
+ counts.decoded++;
+
+ SSL_UpdateCounts(new_flags);
+
+ if (!(new_flags & SSL_HEARTBEAT_SEEN))
+ {
+ DisableDetect(p);
+ }
+
+ sd->ssn_flags |= new_flags;
+
+ MODULE_PROFILE_END(sslPerfStats);
+ return;
+ }
+
+// If the client used an SSLv2 ClientHello with an SSLv3/TLS version and
+// the server replied with an SSLv3/TLS ServerHello, remove the backward
+// compatibility flag and the SSLv2 flag since this session will continue
+// as SSLv3/TLS.
+
+ if ((sd->ssn_flags & SSL_V3_BACK_COMPAT_V2) && SSL_V3_SERVER_HELLO(new_flags))
+ sd->ssn_flags &= ~(SSL_VER_SSLV2_FLAG|SSL_V3_BACK_COMPAT_V2);
+
+ if ( (SSL_IS_CHELLO(new_flags) && SSL_IS_CHELLO(sd->ssn_flags) && SSL_IS_SHELLO(sd->ssn_flags) )
+ || (SSL_IS_CHELLO(new_flags) && SSL_IS_SHELLO(sd->ssn_flags) ))
+ {
+ SnortEventqAdd(GID_SSL, SSL_INVALID_CLIENT_HELLO);
+ }
+ else if (!(config->flags & SSLPP_TRUSTSERVER_FLAG))
+ {
+ if ( (SSL_IS_SHELLO(new_flags) && !SSL_IS_CHELLO(sd->ssn_flags) ))
+ {
+ if (!(stream.missed_packets(p->flow, SSN_DIR_FROM_CLIENT)))
+ SnortEventqAdd(GID_SSL, SSL_INVALID_SERVER_HELLO);
+ }
+ }
+
+ counts.decoded++;
+
+ SSL_UpdateCounts(new_flags);
+
+ /* Note, there can be multiple record types in each SSL packet.
+ * * Processing them in this order is intentional. If there is an
+ * * Alert, we don't care about the other records */
+
+ if (SSL_IS_ALERT(new_flags))
+ {
+ sd->ssn_flags = SSLPP_process_alert(config, sd->ssn_flags, new_flags, p);
+ }
+ else if (SSL_IS_HANDSHAKE(new_flags))
+ {
+ sd->ssn_flags = SSLPP_process_hs(sd->ssn_flags, new_flags);
+ }
+ else if (SSL_IS_APP(new_flags))
+ {
+ sd->ssn_flags = SSLPP_process_app(config, sd->ssn_flags, new_flags, p);
+ }
+ else
+ {
+ /* Different record type that we don't care about.
+ * * Either it's a 'change cipher spec' or we failed to recognize the
+ * * record type. Do not update session data */
+ SSLPP_process_other(config, sd, new_flags, p);
+
+ /* Application data is updated inside of SSLPP_process_other */
+
+ MODULE_PROFILE_END(sslPerfStats);
+ return;
+ }
+
+ sd->ssn_flags |= new_flags;
+
+ MODULE_PROFILE_END(sslPerfStats);
+}
+
+//-------------------------------------------------------------------------
+// class stuff
+//-------------------------------------------------------------------------
+
+class Ssl : public Inspector
+{
+public:
+ Ssl(SSL_PROTO_CONF*);
+ ~Ssl();
+
+ void show(SnortConfig*) override;
+ void eval(Packet*) override;
+
+private:
+ SSL_PROTO_CONF* config;
+};
+
+Ssl::Ssl(SSL_PROTO_CONF* pc)
+{
+ config = pc;
+}
+
+Ssl::~Ssl()
+{
+ if ( config )
+ delete config;
+}
+
+void Ssl::show(SnortConfig*)
+{
+ PrintSslConf(config);
+}
+
+void Ssl::eval(Packet* p)
+{
+ // precondition - what we registered for
+ assert(p->is_tcp() && p->dsize && p->data);
+
+ ++sslstats.total_packets;
+ snort_ssl(config, p);
+}
+
+//-------------------------------------------------------------------------
+// api stuff
+//-------------------------------------------------------------------------
+
+static Module* mod_ctor()
+{ return new SslModule; }
+
+static void mod_dtor(Module* m)
+{ delete m; }
+
+static void ssl_init()
+{
+ SslFlowData::init();
+}
+
+static Inspector* ssl_ctor(Module* m)
+{
+ SslModule* mod = (SslModule*)m;
+ return new Ssl(mod->get_data());
+}
+
+static void ssl_dtor(Inspector* p)
+{
+ delete p;
+}
+
+const InspectApi ssl_api =
+{
+ {
+ PT_INSPECTOR,
+ sizeof(InspectApi),
+ INSAPI_VERSION,
+ 0,
+ API_RESERVED,
+ API_OPTIONS,
+ SSL_NAME,
+ SSL_HELP,
+ mod_ctor,
+ mod_dtor
+ },
+ IT_SERVICE,
+ (uint16_t)PktType::TCP,
+ nullptr, // buffers
+ "ssl",
+ ssl_init,
+ nullptr, // pterm
+ nullptr, // tinit
+ nullptr, // tterm
+ ssl_ctor,
+ ssl_dtor,
+ nullptr, // ssn
+ nullptr // reset
+};
+
+#ifdef BUILDING_SO
+SO_PUBLIC const BaseApi* snort_plugins[] =
+{
+ &ssl_api.base,
+ nullptr
+};
+#else
+const BaseApi* sin_ssl = &ssl_api.base;
+#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 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.
+//--------------------------------------------------------------------------
+//
+
+/*
+ * ssl.h: Definitions, structs, function prototype(s) for
+ * the SSL service inspectors.
+ */
+
+#ifndef SSL_INSPECTOR_H
+#define SSL_INSPECTOR_H
+
+#include "protocols/packet.h"
+#include "stream/stream_api.h"
+#include "profiler.h"
+#include "ssl_config.h"
+
+#define SSLPP_ENCRYPTED_FLAGS \
+ (SSL_HS_SDONE_FLAG | SSL_CLIENT_KEYX_FLAG | \
+ SSL_CAPP_FLAG | SSL_SAPP_FLAG)
+#define SSLPP_ENCRYPTED_FLAGS2 \
+ (SSL_HS_SDONE_FLAG | SSL_CHANGE_CIPHER_FLAG | \
+ SSL_CAPP_FLAG | SSL_SAPP_FLAG)
+
+struct SSLData
+{
+ uint32_t ssn_flags;
+ uint16_t partial_rec_len[4];
+};
+
+struct SSL_counters_t
+{
+ uint64_t stopped;
+ uint64_t disabled;
+ uint64_t decoded;
+ uint64_t alerts;
+ uint64_t cipher_change;
+ uint64_t unrecognized;
+ uint64_t completed_hs;
+ uint64_t bad_handshakes;
+ uint64_t hs_chello;
+ uint64_t hs_shello;
+ uint64_t hs_cert;
+ uint64_t hs_skey;
+ uint64_t hs_ckey;
+ uint64_t hs_finished;
+ uint64_t hs_sdone;
+ uint64_t capp;
+ uint64_t sapp;
+};
+
+class SslFlowData : public FlowData
+{
+public:
+ SslFlowData() : FlowData(flow_id)
+ { memset(&session, 0, sizeof(session)); }
+
+ ~SslFlowData() { }
+
+ static void init()
+ { flow_id = FlowData::get_flow_id(); }
+
+public:
+ static unsigned flow_id;
+ SSLData session;
+};
+
+SSLData* get_ssl_session_data(Flow* flow);
+void SSL_InitGlobals(void);
+
+#endif /* SSL_INSPECTOR_H */
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 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.
+//--------------------------------------------------------------------------
+
+// ssl_module.cc author Bhagyashree Bantwal <bbantwal@cisco.com>
+
+#include "ssl_module.h"
+
+#include <assert.h>
+#include <sstream>
+
+#include "parser.h"
+#include "ssl_inspector.h"
+
+using namespace std;
+
+#define SSL_INVALID_CLIENT_HELLO_STR "Invalid Client HELLO after Server HELLO Detected"
+#define SSL_INVALID_SERVER_HELLO_STR "Invalid Server HELLO without Client HELLO Detected"
+#define SSL_HEARTBLEED_REQUEST_STR "Heartbeat Read Overrun Attempt Detected"
+#define SSL_HEARTBLEED_RESPONSE_STR "Large Heartbeat Response Detected"
+
+static const Parameter s_params[] =
+{
+ { "trust_servers", Parameter::PT_BOOL, nullptr, "false",
+ "disables requirement that application (encrypted) data must be observed on both sides" },
+
+ { "max_heartbeat_length", Parameter::PT_INT, "0:65535", "0",
+ "maximum length of heartbeat record allowed" },
+
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+static const RuleMap ssl_rules[] =
+{
+ { SSL_INVALID_CLIENT_HELLO, SSL_INVALID_CLIENT_HELLO_STR },
+ { SSL_INVALID_SERVER_HELLO, SSL_INVALID_SERVER_HELLO_STR },
+ { SSL_ALERT_HB_REQUEST, SSL_HEARTBLEED_REQUEST_STR },
+ { SSL_ALERT_HB_RESPONSE, SSL_HEARTBLEED_RESPONSE_STR },
+
+ { 0, nullptr }
+};
+
+//-------------------------------------------------------------------------
+// ssl module
+//-------------------------------------------------------------------------
+
+SslModule::SslModule() : Module(SSL_NAME, SSL_HELP, s_params)
+{
+ conf = nullptr;
+}
+
+SslModule::~SslModule()
+{
+ if ( conf )
+ delete conf;
+}
+
+const RuleMap* SslModule::get_rules() const
+{ return ssl_rules; }
+
+const PegInfo* SslModule::get_pegs() const
+{ return simple_pegs; }
+
+PegCount* SslModule::get_counts() const
+{ return (PegCount*)&sslstats; }
+
+ProfileStats* SslModule::get_profile() const
+{ return &sslPerfStats; }
+
+bool SslModule::set(const char*, Value& v, SnortConfig*)
+{
+ if ( v.is("trust_servers") )
+ {
+ if (v.get_bool())
+ conf->flags |= SSLPP_TRUSTSERVER_FLAG;
+ }
+ else if ( v.is("max_heartbeat_length") )
+ conf->max_heartbeat_len = v.get_long();
+
+ else
+ return false;
+
+ return true;
+}
+
+SSL_PROTO_CONF* SslModule::get_data()
+{
+ SSL_PROTO_CONF* tmp = conf;
+ conf = nullptr;
+ return tmp;
+}
+
+bool SslModule::begin(const char*, int, SnortConfig*)
+{
+ conf = new SSL_PROTO_CONF;
+ conf->max_heartbeat_len = 0;
+ conf->flags = 0;
+ return true;
+}
+
+bool SslModule::end(const char*, int, SnortConfig*)
+{
+ SSL_InitGlobals();
+
+ return true;
+}
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 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.
+//--------------------------------------------------------------------------
+
+// ssl_module.h author Bhagyashree Bantwal <bbantwal@cisco.com>
+
+#ifndef SSL_MODULE_H
+#define SSL_MODULE_H
+
+#include "framework/module.h"
+#include "framework/bits.h"
+#include "main/thread.h"
+#include "ssl_config.h"
+
+#define GID_SSL 137
+
+#define SSL_INVALID_CLIENT_HELLO 1
+#define SSL_INVALID_SERVER_HELLO 2
+#define SSL_ALERT_HB_REQUEST 3
+#define SSL_ALERT_HB_RESPONSE 4
+
+#define SSL_NAME "ssl"
+#define SSL_HELP "ssl inspection"
+
+struct SnortConfig;
+
+extern THREAD_LOCAL SimpleStats sslstats;
+extern THREAD_LOCAL ProfileStats sslPerfStats;
+
+class SslModule : public Module
+{
+public:
+ SslModule();
+ ~SslModule();
+
+ bool set(const char*, Value&, SnortConfig*) override;
+ bool begin(const char*, int, SnortConfig*) override;
+ bool end(const char*, int, SnortConfig*) override;
+
+ unsigned get_gid() const override
+ { return GID_SSL; }
+
+ const RuleMap* get_rules() const override;
+ const PegInfo* get_pegs() const override;
+ PegCount* get_counts() const override;
+ ProfileStats* get_profile() const override;
+
+ SSL_PROTO_CONF* get_data();
+
+private:
+ SSL_PROTO_CONF* conf;
+};
+
+#endif
+
pps_perfmonitor.cc
pps_rpc_decode.cc
pps_ssh.cc
+ pps_ssl.cc
pps_dns.cc
pps_pop.cc
pps_imap.cc
pps_perfmonitor.cc \
pps_rpc_decode.cc \
pps_ssh.cc \
+pps_ssl.cc \
pps_dns.cc \
pps_pop.cc \
pps_imap.cc \
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 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.
+//--------------------------------------------------------------------------
+// pps_ssl.cc author Bhagya Bantwal <bbantwal@cisco.com>
+
+#include <sstream>
+#include <vector>
+
+#include "conversion_state.h"
+#include "helpers/s2l_util.h"
+#include "helpers/util_binder.h"
+
+namespace preprocessors
+{
+namespace
+{
+class Ssl : public ConversionState
+{
+public:
+ Ssl(Converter& c) : ConversionState(c) { }
+ virtual ~Ssl() { }
+ virtual bool convert(std::istringstream& data_stream);
+};
+} // namespace
+
+bool Ssl::convert(std::istringstream& data_stream)
+{
+ std::string keyword;
+ bool retval = true;
+ bool ports_set = false;
+ Binder bind(table_api);
+
+ bind.set_when_proto("tcp");
+ bind.set_use_type("ssl");
+
+ table_api.open_table("ssl");
+
+ // parse the file configuration
+ while (util::get_string(data_stream, keyword, ","))
+ {
+ bool tmpval = true;
+ std::istringstream arg_stream(keyword);
+
+ // should be gauranteed to happen. Checking for error just cause
+ if (!(arg_stream >> keyword))
+ tmpval = false;
+
+ else if (!keyword.compare("noinspect_encrypted"))
+ table_api.add_deleted_comment("noinspect_encrypted");
+
+ else if (!keyword.compare("trustservers"))
+ tmpval = table_api.add_option("trust_servers", true);
+
+ else if (!keyword.compare("max_heartbeat_length"))
+ {
+ tmpval = parse_int_option("max_heartbeat_length", arg_stream, false);
+ }
+ else if (!keyword.compare("ports"))
+ {
+ std::string tmp = "";
+ table_api.add_diff_option_comment("ports", "bindings");
+
+ if (arg_stream >> keyword)
+ {
+ if (!keyword.compare("{"))
+ {
+ while (arg_stream >> keyword && keyword.compare("}"))
+ {
+ ports_set = true;
+ bind.add_when_port(keyword);
+ }
+ }
+ else
+ {
+ data_api.failed_conversion(arg_stream, "ports <bracketed_port_list>");
+ retval = false;
+ }
+ }
+ }
+ else
+ {
+ tmpval = false;
+ }
+
+ if (!tmpval)
+ {
+ data_api.failed_conversion(arg_stream, keyword);
+ retval = false;
+ }
+ }
+
+ if (!ports_set)
+ {
+ bind.add_when_port("443");
+ bind.add_when_port("465");
+ bind.add_when_port("563");
+ bind.add_when_port("639");
+ bind.add_when_port("989");
+ bind.add_when_port("992");
+ bind.add_when_port("993");
+ bind.add_when_port("994");
+ bind.add_when_port("995");
+ bind.add_when_port("7801");
+ bind.add_when_port("7802");
+ bind.add_when_port("7900");
+ bind.add_when_port("7901");
+ bind.add_when_port("7902");
+ bind.add_when_port("7903");
+ bind.add_when_port("7904");
+ bind.add_when_port("7905");
+ bind.add_when_port("7906");
+ bind.add_when_port("7907");
+ bind.add_when_port("7908");
+ bind.add_when_port("7909");
+ bind.add_when_port("7910");
+ bind.add_when_port("7911");
+ bind.add_when_port("7912");
+ bind.add_when_port("7913");
+ bind.add_when_port("7914");
+ bind.add_when_port("7915");
+ bind.add_when_port("7916");
+ bind.add_when_port("7917");
+ bind.add_when_port("7918");
+ bind.add_when_port("7919");
+ bind.add_when_port("7920");
+ }
+
+ return retval;
+}
+
+/**************************
+ ******* A P I ***********
+ **************************/
+
+static ConversionState* ctor(Converter& c)
+{
+ return new Ssl(c);
+}
+
+static const ConvertMap preprocessor_ssl =
+{
+ "ssl",
+ ctor,
+};
+
+const ConvertMap* ssl_map = &preprocessor_ssl;
+}
+
extern const ConvertMap* perfmonitor_map;
extern const ConvertMap* rpc_decode_map;
extern const ConvertMap* ssh_map;
+extern const ConvertMap* ssl_map;
extern const ConvertMap* dns_map;
extern const ConvertMap* pop_map;
extern const ConvertMap* imap_map;
perfmonitor_map,
rpc_decode_map,
ssh_map,
+ ssl_map,
dns_map,
pop_map,
imap_map,
extern const ConvertMap* sid_map;
extern const ConvertMap* stream_reassemble_map;
extern const ConvertMap* stream_size_map;
+extern const ConvertMap* ssl_state_map;
+extern const ConvertMap* ssl_version_map;
extern const ConvertMap* tag_map;
extern const ConvertMap* threshold_map;
extern const ConvertMap* ttl_map;
sid_map,
stream_reassemble_map,
stream_size_map,
+ ssl_state_map,
+ ssl_version_map,
tag_map,
threshold_map,
ttl_map,
};
const ConvertMap* priority_map = &rule_priority;
+
+/************************************
+ ********* SSL STATE **************
+ ************************************/
+
+static const std::string ssl_state = "ssl_state";
+static const ConvertMap rule_ssl_state =
+{
+ ssl_state,
+ unchanged_rule_ctor<& ssl_state>,
+};
+
+const ConvertMap* ssl_state_map = &rule_ssl_state;
+
+/************************************
+ ********* SSL VERSION **************
+ ************************************/
+
+static const std::string ssl_version = "ssl_version";
+static const ConvertMap rule_ssl_version =
+{
+ ssl_version,
+ unchanged_rule_ctor<& ssl_version>,
+};
+
+const ConvertMap* ssl_version_map = &rule_ssl_version;
+
} // namespace rule