# features
option ( ENABLE_SHELL "enable shell support" OFF )
+option ( ENABLE_APPID_THIRD_PARTY "enable third party appid" OFF )
option ( ENABLE_UNIT_TESTS "enable unit tests" OFF )
option ( ENABLE_PIGLET "enable piglet test harness" OFF )
set(UUID_CPPFLAGS "-I${UUID_INCLUDE_DIR}")
endif()
+if(ENABLE_APPID_THIRD_PARTY)
+ set(TP_APPID_CPPFLAGS "-DENABLE_APPID_THIRD_PARTY")
+endif()
# create & install pkgconfig file
configure_file(
/* include internal inspectors in binary */
#cmakedefine STATIC_SEARCH_ENGINES 1
+/* enable third party appid */
+#cmakedefine ENABLE_APPID_THIRD_PARTY 1
+
/* enable unit tests */
#cmakedefine UNIT_TEST 1
string ( REGEX REPLACE "[\r\n]" " " CPPFLAGS "${CPPFLAGS}" )
set ( ${OPT}_CPPFLAGS "${CPPFLAGS}" CACHE STRING "" )
+
+ set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${${OPT}_CPPFLAGS}" CACHE STRING "" FORCE )
+ set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${${OPT}_CPPFLAGS}" CACHE STRING "" FORCE )
endforeach ( OPT )
# Set these after all tests are done but *before* any subdirectories are included
+include(CheckIncludeFileCXX)
+
add_subdirectory ( codecs )
add_subdirectory ( daqs )
add_subdirectory ( inspectors )
add_subdirectory ( loggers )
add_subdirectory ( search_engines )
add_subdirectory ( so_rules )
+
+CHECK_INCLUDE_FILE_CXX( "${CMAKE_INSTALL_PREFIX}/include/snort/network_inspectors/appid/tp_appid_module_api.h" ENABLE_APPID_THIRD_PARTY ${CMAKE_CXX_FLAGS})
+
+if ( ENABLE_APPID_THIRD_PARTY )
+ add_subdirectory ( tp_appid )
+endif()
--- /dev/null
+add_subdirectory ( mock )
--- /dev/null
+cmake_minimum_required ( VERSION 3.4.3 )
+project ( lowmem CXX )
+
+set (CMAKE_CXX_STANDARD 11)
+set (CMAKE_CXX_STANDARD_REQUIRED ON)
+set (CMAKE_CXX_EXTENSIONS OFF)
+
+if ( APPLE )
+ set ( CMAKE_MACOSX_RPATH OFF )
+endif ( APPLE )
+
+include ( FindPkgConfig )
+pkg_search_module ( SNORT3 REQUIRED snort>=3 )
+
+add_library (
+ tp_mock MODULE
+ tp_mock.cc
+)
+
+if ( APPLE )
+ set_target_properties (
+ tp_lib
+ PROPERTIES
+ LINK_FLAGS "-undefined dynamic_lookup"
+ )
+endif ( APPLE )
+
+set_target_properties (
+ tp_mock
+ PROPERTIES
+ PREFIX ""
+ )
+
+set_property(TARGET tp_mock PROPERTY ENABLE_EXPORTS 1)
+
+target_include_directories (
+ tp_mock PUBLIC
+ ${SNORT3_INCLUDE_DIRS}
+)
+
+install (
+ TARGETS tp_mock
+ LIBRARY
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/${CMAKE_PROJECT_NAME}/tp_appid"
+)
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2016-2018 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.
+//--------------------------------------------------------------------------
+
+// Brief description:
+//
+// Minimalist example of an implementation of a third party library for appid
+// detection.
+// Snort interacts with this library via 3 classes:
+// 1) TPLibHandler - to load the third party library.
+// 2) ThirdPartyAppIDModule - to initialize and clean-up whatever we might need
+// 3) ThirdPartyAppIDSession - for the actual information extracted from packets
+// The third party library must provide implementations to the abstract classes
+// ThirdPartyAppIDModule and ThirdPartyAppIDSession and must also implement the
+// object factory functions returning pointers to the derived classes.
+//
+//
+// Standalone compilation:
+// g++ -g -Wall -I/path/to/snort3/src -c tp_mock.cc
+// g++ -std=c++11 -g -Wall -I/path/to/snort3/src -shared -fPIC -o libtp_mock.so tp_mock.cc
+// As a module (dynamically loaded) - see CMakeLists.txt
+
+#include <iostream>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main/snort_types.h"
+
+#include "network_inspectors/appid/tp_appid_module_api.h"
+#include "network_inspectors/appid/tp_appid_session_api.h"
+
+#define THIRD_PARTY_APPID_MODULE_NAME "NAVL"
+
+#define WhereMacro __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__
+
+using namespace std;
+
+class ThirdPartyAppIDModuleImpl : public ThirdPartyAppIDModule
+{
+public:
+ ThirdPartyAppIDModuleImpl(uint32_t ver, const char* mname)
+ : ThirdPartyAppIDModule(ver, mname)
+ {
+ cerr << WhereMacro << endl;
+ }
+
+ ~ThirdPartyAppIDModuleImpl()
+ {
+ cerr << WhereMacro << endl;
+ }
+
+ int pinit(ThirdPartyConfig& config)
+ {
+ cerr << WhereMacro
+ << ": main thread initialization, possibly load other libraries." << endl;
+ return 0;
+ }
+
+ int tinit()
+ {
+ cerr << WhereMacro << ": per worker thread initialization." << endl;
+ return 0;
+ }
+
+ int reconfigure(const ThirdPartyConfig& config)
+ {
+ cerr << WhereMacro << ": do not call pinit() during reconfigure." << endl;
+ return 0;
+ }
+
+ int pfini()
+ {
+ cerr << WhereMacro << ": main thread clean-up." << endl;
+ return 0;
+ }
+
+ int tfini()
+ {
+ cerr << WhereMacro << ": per worker-thread clean-up." << endl;
+ return 0;
+ }
+
+ int print_stats() { return 0; }
+ int reset_stats() { return 0; }
+};
+
+class ThirdPartyAppIDSessionImpl : public ThirdPartyAppIDSession
+{
+public:
+
+ bool reset() { return 1; }
+ bool process(const snort::Packet&,
+ AppidSessionDirection direction,
+ vector<AppId>& proto_list,
+ ThirdPartyAppIDAttributeData& attribute_data)
+ {
+ cerr << WhereMacro
+ << ": third party packet parsing and appid processing." << endl;
+ return 1;
+ }
+
+ int disable_flags(uint32_t session_flags) { return 0; }
+ TPState get_state() { return state; }
+ void set_state(TPState s) { state=s; }
+ void clear_attr(TPSessionAttr attr) { flags &= ~attr; }
+ void set_attr(TPSessionAttr attr) { flags |= attr; }
+ unsigned get_attr(TPSessionAttr attr) { return flags & attr; }
+
+private:
+ unsigned flags=0;
+};
+
+// Object factories to create module and session.
+// This is the only way for outside callers to create module and session
+// once the .so has been loaded.
+extern "C"
+{
+ SO_PUBLIC ThirdPartyAppIDModuleImpl* create_third_party_appid_module()
+ {
+ return new ThirdPartyAppIDModuleImpl(1,"third party");
+ }
+}
+
+extern "C"
+{
+ SO_PUBLIC ThirdPartyAppIDSessionImpl* create_third_party_appid_session()
+ {
+ return new ThirdPartyAppIDSessionImpl;
+ }
+}
+
infodir=@infodir@
cpp_opts=DAQ LUAJIT
-cpp_opts_other=DNET FLATBUFFERS HWLOC HYPERSCAN LZMA OPENSSL PCAP PCRE UUID
+cpp_opts_other=DNET FLATBUFFERS HWLOC HYPERSCAN LZMA OPENSSL PCAP PCRE UUID TP_APPID
+TP_APPID_CPPFLAGS=@TP_APPID_CPPFLAGS@
PCAP_CPPFLAGS=@PCAP_CPPFLAGS@
LUAJIT_CPPFLAGS=@LUAJIT_CPPFLAGS@
DNET_CPPFLAGS=@DNET_CPPFLAGS@
+if ( ENABLE_APPID_THIRD_PARTY )
+ set (APPID_TP_INCLUDES
+ tp_appid_module_api.h
+ tp_appid_session_api.h
+ tp_appid_types.h
+ http_xff_fields.h
+ )
+endif()
+
set (APPID_INCLUDES
appid_api.h
appid_dns_session.h
appid_http_session.h
+ appid_types.h
application_ids.h
+ http_xff_fields.h
+ ${APPID_TP_INCLUDES}
)
set ( APPID_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR} )
appid_utils/sf_multi_mpse.h
)
+if ( ENABLE_APPID_THIRD_PARTY )
+ set( APPID_TP_SOURCES
+ tp_lib_handler.cc
+ tp_appid_utils.cc
+ tp_lib_handler.h
+ tp_appid_types.h
+ )
+endif()
+
set ( APPID_SOURCES
app_forecast.cc
app_forecast.h
appid_peg_counts.cc
appid_session.cc
appid_session.h
+ appid_types.h
appid_inspector.cc
appid_inspector.h
appid_module.cc
lua_detector_util.h
service_state.cc
service_state.h
- thirdparty_appid_api.h
- thirdparty_appid_types.h
- thirdparty_appid_utils.cc
- thirdparty_appid_utils.h
+ http_xff_fields.h
+ ${APPID_TP_SOURCES}
)
ErrorMessage("LuaDetectorApi:Failed to add AFElement for appId %d", indicator);
}
-static inline void rekey_master_AF_key(Packet* p, int dir, AppId forecast)
+static inline void rekey_master_AF_key(Packet* p, AppidSessionDirection dir, AppId forecast)
{
const SfIp* src = dir ? p->ptrs.ip_api.get_dst() : p->ptrs.ip_api.get_src();
master_key.forecast = forecast;
}
-void check_session_for_AF_indicator(Packet* p, int dir, AppId indicator)
+void check_session_for_AF_indicator(Packet* p, AppidSessionDirection dir, AppId indicator)
{
AFElement* ind_element;
if (!(ind_element = (AFElement*)xhash_find(AF_indicators, &indicator)))
xhash_add(AF_actives, &master_key, &new_active_value);
}
-AppId check_session_for_AF_forecast(AppIdSession& asd, Packet* p, int dir, AppId forecast)
+AppId check_session_for_AF_forecast(AppIdSession& asd, Packet* p, AppidSessionDirection dir, AppId forecast)
{
AFActVal* check_act_val;
#include <ctime>
#include "flow/flow.h"
+#include "appid_types.h"
#include "application_ids.h"
class AppIdSession;
int init_appid_forecast();
void clean_appid_forecast();
void add_af_indicator(AppId, AppId, AppId);
-void check_session_for_AF_indicator(snort::Packet*, int, AppId);
-AppId check_session_for_AF_forecast(AppIdSession&, snort::Packet*, int, AppId);
+void check_session_for_AF_indicator(snort::Packet*, AppidSessionDirection, AppId);
+AppId check_session_for_AF_forecast(AppIdSession&, snort::Packet*, AppidSessionDirection, AppId);
#endif
#include "appid_api.h"
#include "app_info_table.h"
-#include "thirdparty_appid_utils.h"
#include "service_plugins/service_bootp.h"
#include "service_plugins/service_netbios.h"
#include "utils/util.h"
+#ifdef ENABLE_APPID_THIRD_PARTY
+#include "tp_appid_session_api.h"
+#endif
using namespace snort;
if ( asd->common.flow_type == APPID_FLOW_TYPE_NORMAL )
{
if ( asd->service_disco_state != APPID_DISCO_STATE_FINISHED ||
- !is_third_party_appid_done(asd->tpsession) ||
- asd->get_session_flags(APPID_SESSION_HTTP_SESSION | APPID_SESSION_CONTINUE) ||
- (asd->get_session_flags(APPID_SESSION_ENCRYPTED) &&
- (asd->get_session_flags(APPID_SESSION_DECRYPTED) ||
- asd->session_packet_count < SSL_WHITELIST_PKT_LIMIT)) )
+ !asd->is_third_party_appid_done() ||
+ asd->get_session_flags(APPID_SESSION_HTTP_SESSION | APPID_SESSION_CONTINUE) ||
+ (asd->get_session_flags(APPID_SESSION_ENCRYPTED) &&
+ (asd->get_session_flags(APPID_SESSION_DECRYPTED) ||
+ asd->session_packet_count < SSL_WHITELIST_PKT_LIMIT)) )
{
return true;
}
// FIXIT-M: If a third-party module is not available then this
// should probably check if an appId has been discovered
// by the local AppId module.
- return is_third_party_appid_available(asd->tpsession);
+ return asd->is_third_party_appid_available();
}
return false;
if ( asd && ( get_flow_type(flow) == APPID_FLOW_TYPE_NORMAL ) )
{
appHA->flags = APPID_HA_FLAGS_APP;
- if ( is_third_party_appid_available(asd->tpsession) )
+ if ( asd->is_third_party_appid_available() )
appHA->flags |= APPID_HA_FLAGS_TP_DONE;
if ( asd->is_service_detected() )
appHA->flags |= APPID_HA_FLAGS_SVC_DONE;
asd->service_disco_state = APPID_DISCO_STATE_FINISHED;
asd->client_disco_state = APPID_DISCO_STATE_FINISHED;
- if ( thirdparty_appid_module )
- thirdparty_appid_module->session_state_set(asd->tpsession, TP_STATE_HA);
+#ifdef ENABLE_APPID_THIRD_PARTY
+ if (asd->tpsession)
+ asd->tpsession->set_state(TP_STATE_HA);
+#endif
}
#else
if ( !asd )
}
#endif
- if ( ( appHA->flags & APPID_HA_FLAGS_TP_DONE ) && thirdparty_appid_module )
+ if( (appHA->flags & APPID_HA_FLAGS_TP_DONE) && asd->tpsession )
{
- thirdparty_appid_module->session_state_set(asd->tpsession, TP_STATE_TERMINATED);
+#ifdef ENABLE_APPID_THIRD_PARTY
+ if( asd->tpsession)
+ asd->tpsession->set_state(TP_STATE_TERMINATED);
+#endif
asd->set_session_flags(APPID_SESSION_NO_TPI);
}
if ( AppIdSession* asd = get_appid_session(flow) )
if ( ( asd->common.flow_type == APPID_FLOW_TYPE_NORMAL ) &&
- !is_third_party_appid_done(asd->tpsession) )
+ !asd->is_third_party_appid_done() )
done = false;
return done;
#include "app_info_table.h"
#include "appid_session.h"
-#include "thirdparty_appid_utils.h"
#ifdef USE_RNA_CONFIG
#include "appid_utils/network_set.h"
#include "appid_utils/ip_funcs.h"
#include "log/messages.h"
#include "utils/util.h"
#include "target_based/snort_protocols.h"
+#ifdef ENABLE_APPID_THIRD_PARTY
+#include "tp_lib_handler.h"
+#endif
+
#define ODP_PORT_DETECTORS "odp/port/*"
#define CUSTOM_PORT_DETECTORS "custom/port/*"
snort_free((void*)conf_file);
#endif
snort_free((void*)app_detector_dir);
- snort_free((void*)thirdparty_appid_dir);
}
AppIdConfig::AppIdConfig(AppIdModuleConfig* config)
cleanup();
}
+const TPLibHandler * AppIdConfig::tp_handler() const
+{
+#ifdef ENABLE_APPID_THIRD_PARTY
+ return tph;
+#else
+ return nullptr;
+#endif
+}
+
+bool AppIdConfig::have_tp() const
+{
+#ifdef ENABLE_APPID_THIRD_PARTY
+ return tph != nullptr && tph->have_tp();
+#else
+ return false;
+#endif
+}
+
+void AppIdConfig::tp_appid_module_tinit()
+{
+#ifdef ENABLE_APPID_THIRD_PARTY
+ if(tph) tph->tinit();
+#endif
+}
+
+void AppIdConfig::tp_appid_module_tterm()
+{
+#ifdef ENABLE_APPID_THIRD_PARTY
+ if(tph) tph->tterm();
+#endif
+}
+
void AppIdConfig::read_port_detectors(const char* files)
{
int rval;
#endif
read_port_detectors(ODP_PORT_DETECTORS);
read_port_detectors(CUSTOM_PORT_DETECTORS);
- ThirdPartyAppIDInit(mod_config);
+
+#ifdef ENABLE_APPID_THIRD_PARTY
+ tph=TPLibHandler::get();
+ tph->pinit(mod_config);
+#endif
map_app_names_to_snort_ids(sc);
return true;
}
void AppIdConfig::cleanup()
{
- if (thirdparty_appid_module != nullptr)
- thirdparty_appid_module->print_stats();
- ThirdPartyAppIDFini();
-
+#ifdef ENABLE_APPID_THIRD_PARTY
+ tph->pfini(0);
+ TPLibHandler::destroy(tph);
+#endif
+
app_info_mgr.cleanup_appid_info_table();
#ifdef USE_RNA_CONFIG
{
unsigned i;
- if (mod_config->thirdparty_appid_dir)
- LogMessage(" 3rd Party Dir: %s\n", mod_config->thirdparty_appid_dir);
+ if (!mod_config->tp_appid_path.empty())
+ LogMessage(" 3rd Party Dir: %s\n", mod_config->tp_appid_path.c_str());
#ifdef USE_RNA_CONFIG
struct in_addr ia;
#define APP_ID_CONFIG_H
#include <array>
+#include <string>
#include "application_ids.h"
#include "framework/decode_data.h"
struct NetworkSet;
class AppInfoManager;
+class TPLibHandler;
extern unsigned appIdPolicyId;
extern uint32_t app_id_netmasks[];
unsigned long app_stats_rollover_size = 0;
unsigned long app_stats_rollover_time = 0;
const char* app_detector_dir = nullptr;
- const char* thirdparty_appid_dir = nullptr;
+ std::string tp_appid_path = "";
+ std::string tp_appid_config = "";
uint32_t instance_id = 0;
uint32_t memcap = 0;
bool debug = false;
AppIdModuleConfig* mod_config = nullptr;
unsigned appIdPolicyId = 53;
+ const TPLibHandler * tp_handler() const;
+ bool have_tp() const;
+ void tp_appid_module_tinit();
+ void tp_appid_module_tterm();
+
private:
void read_port_detectors(const char* files);
void configure_analysis_networks(char* toklist[], uint32_t flag);
void display_port_config();
AppInfoManager& app_info_mgr;
+
+// #ifdef ENABLE_APPID_THIRD_PARTY
+ // class that holds pointers to third party objects in thirdparty.so
+ TPLibHandler* tph = nullptr;
+// #endif
};
#endif
class AppIdDiscoveryArgs
{
public:
- AppIdDiscoveryArgs(const uint8_t* data, uint16_t size, int dir, AppIdSession& asd,
+ AppIdDiscoveryArgs(const uint8_t* data, uint16_t size, AppidSessionDirection dir, AppIdSession& asd,
snort::Packet* p) : data(data), size(size), dir(dir), asd(asd), pkt(p), config(asd.config)
{}
const uint8_t* data;
uint16_t size;
- int dir;
+ AppidSessionDirection dir;
AppIdSession& asd;
snort::Packet* pkt;
const AppIdConfig* config = nullptr;
AppIdDiscovery& get_handler() const
{ return *handler; }
- bool is_client() const
- { return client; }
+ bool is_client() const
+ { return client; }
- virtual LuaStateDescriptor* validate_lua_state(bool /*packet_context*/)
- { return nullptr; }
+ virtual LuaStateDescriptor* validate_lua_state(bool /*packet_context*/)
+ { return nullptr; }
protected:
AppIdDiscovery* handler = nullptr;
#include "detector_plugins/http_url_patterns.h"
#include "host_port_app_cache.h"
#include "service_plugins/service_discovery.h"
-#include "thirdparty_appid_utils.h"
+#ifdef ENABLE_THIRD_PARTY_APPID
+#include "tp_appid_session_api.h"
+#endif
using namespace snort;
+bool do_discovery(AppIdSession&, IpProtocol, Packet*, AppidSessionDirection&);
+
AppIdDiscovery::AppIdDiscovery(AppIdInspector& ins)
: inspector(ins)
{
}
static bool set_network_attributes(AppIdSession* asd, Packet* p, IpProtocol& protocol,
- int& direction)
+ AppidSessionDirection& direction)
{
if (asd)
{
return true;
}
-static bool is_packet_ignored(AppIdSession* asd, Packet* p, int& direction)
+static bool is_packet_ignored(AppIdSession* asd, Packet* p, AppidSessionDirection& direction)
{
// FIXIT-M - Need to convert this _dpd stream api call to the correct snort++ method
#ifdef REMOVED_WHILE_NOT_IN_USE
return false;
}
-static uint64_t is_session_monitored(AppIdSession& asd, const Packet* p, int dir,
+static uint64_t is_session_monitored(AppIdSession& asd, const Packet* p, AppidSessionDirection dir,
AppIdInspector& inspector)
{
uint64_t flags = 0;
return flow_flags;
}
-static uint64_t is_session_monitored(const Packet* p, int dir, AppIdInspector& inspector)
+static uint64_t is_session_monitored(const Packet* p, AppidSessionDirection dir, AppIdInspector& inspector)
{
uint64_t flags = 0;
uint64_t flow_flags = APPID_SESSION_DISCOVER_APP;
}
static void lookup_appid_by_host_port(AppIdSession& asd, Packet* p, IpProtocol protocol,
- int direction)
+ AppidSessionDirection direction)
{
HostPortVal* hv = nullptr;
uint16_t port = 0;
asd.service_disco_state = APPID_DISCO_STATE_FINISHED;
asd.client_disco_state = APPID_DISCO_STATE_FINISHED;
asd.set_session_flags(APPID_SESSION_SERVICE_DETECTED);
- if (thirdparty_appid_module)
- thirdparty_appid_module->session_delete(asd.tpsession, 1);
-
- asd.tpsession = nullptr;
+#ifdef ENABLE_THIRD_PARTY_APPID
+ if (asd.tpsession)
+ asd.tpsession->reset();
+#endif
}
}
}
void AppIdDiscovery::do_application_discovery(Packet* p, AppIdInspector& inspector)
{
IpProtocol protocol = IpProtocol::PROTO_NOT_SET;
- bool isTpAppidDiscoveryDone = false;
- int direction = 0;
+ bool isTpAppidDiscoveryDone = true;
+ AppidSessionDirection direction = APP_ID_FROM_INITIATOR;
AppIdSession* asd = (AppIdSession*)p->flow->get_flow_data(AppIdSession::inspector_id);
if ( !set_network_attributes(asd, p, protocol, direction) )
if ( is_packet_ignored(asd, p, direction) )
return;
+ // Create a TPDiscovery object from a TPLibHandle.
uint64_t flow_flags;
if (asd)
flow_flags = is_session_monitored(*asd, p, direction, inspector);
asd->check_app_detection_restart();
-#ifdef REMOVED_WHILE_NOT_IN_USE
- // do third party detector processing
- isTpAppidDiscoveryDone = do_third_party_discovery(asd, protocol, ip, p, direction);
+// #ifdef ENABLE_APPID_THIRD_PARTY
+#if(0) // FIXIT-H switch to ENABLE_APPID_THIRD_PARTY once bugs fixed
+ if(asd->config->have_tp())
+ isTpAppidDiscoveryDone = do_discovery(*asd,protocol,p,direction);
#endif
if ( !asd->get_session_flags(APPID_SESSION_PORT_SERVICE_DONE) )
{
public:
AppIdPatternMatchNode(AppIdDetector* detector, int start, unsigned len)
- : service(detector), pattern_start_pos(start), size(len)
- {}
+ : service(detector), pattern_start_pos(start), size(len) { }
bool valid_match(int end_position)
{
void HttpEventHandler::handle(DataEvent& event, Flow* flow)
{
- int direction;
+ AppidSessionDirection direction;
const uint8_t* header_start;
int32_t header_length;
HttpEvent* http_event = (HttpEvent*)&event;
#include "appid_debug.h"
#include "appid_session.h"
#include "detector_plugins/http_url_patterns.h"
-#include "thirdparty_appid_utils.h"
+#include "http_xff_fields.h"
+#ifdef ENABLE_APPID_THIRD_PARTY
+#include "tp_appid_session_api.h"
+#endif
static const char* httpFieldName[ MAX_HTTP_FIELD_ID ] = // for use in debug messages
{
&& !asd.get_session_flags(APPID_SESSION_SPDY_SESSION))
{
asd.clear_session_flags(APPID_SESSION_CHP_INSPECTING);
- if (thirdparty_appid_module)
- thirdparty_appid_module->session_attr_clear(asd.tpsession,
- TP_ATTR_CONTINUE_MONITORING);
+#ifdef ENABLE_APPID_THIRD_PARTY
+ if (asd.tpsession)
+ asd.tpsession->clear_attr(TP_ATTR_CONTINUE_MONITORING);
+#endif
}
}
chp_candidate = cah->appIdInstance;
num_matches = cah->num_matches;
num_scans = cah->num_scans;
- if (thirdparty_appid_module)
+#ifdef ENABLE_APPID_THIRD_PARTY
+ if (asd.tpsession)
{
if ((ptype_scan_counts[RSP_CONTENT_TYPE_FID]))
- thirdparty_appid_module->session_attr_set(asd.tpsession,
- TP_ATTR_COPY_RESPONSE_CONTENT);
+ asd.tpsession->set_attr(TP_ATTR_COPY_RESPONSE_CONTENT);
else
- thirdparty_appid_module->session_attr_clear(asd.tpsession,
- TP_ATTR_COPY_RESPONSE_CONTENT);
+ asd.tpsession->clear_attr(TP_ATTR_COPY_RESPONSE_CONTENT);
if ((ptype_scan_counts[RSP_LOCATION_FID]))
- thirdparty_appid_module->session_attr_set(asd.tpsession,
- TP_ATTR_COPY_RESPONSE_LOCATION);
+ asd.tpsession->set_attr(TP_ATTR_COPY_RESPONSE_LOCATION);
else
- thirdparty_appid_module->session_attr_clear(asd.tpsession,
- TP_ATTR_COPY_RESPONSE_LOCATION);
+ asd.tpsession->clear_attr(TP_ATTR_COPY_RESPONSE_LOCATION);
if ((ptype_scan_counts[RSP_BODY_FID]))
- thirdparty_appid_module->session_attr_set(asd.tpsession, TP_ATTR_COPY_RESPONSE_BODY);
+ asd.tpsession->set_attr(TP_ATTR_COPY_RESPONSE_BODY);
else
- thirdparty_appid_module->session_attr_clear(asd.tpsession,
- TP_ATTR_COPY_RESPONSE_BODY);
+ asd.tpsession->clear_attr(TP_ATTR_COPY_RESPONSE_BODY);
}
+#endif
return 1;
}
}
}
-int AppIdHttpSession::process_http_packet(int direction)
+int AppIdHttpSession::process_http_packet(AppidSessionDirection direction)
{
snort::Profile http_profile_context(httpPerfStats);
AppId service_id = APP_ID_NONE;
AppId client_id = APP_ID_NONE;
AppId payload_id = APP_ID_NONE;
-
+ bool have_tp = asd.tpsession != nullptr;
+
// For fragmented HTTP headers, do not process if none of the fields are set.
// These fields will get set when the HTTP header is reassembled.
if ( useragent.empty() && host.empty() && referer.empty() && uri.empty() )
{
// Scan Server Header for Vendor & Version
// FIXIT-M: Should we be checking the scan_flags even when
- // thirdparty_appid_module is off?
- if ( (thirdparty_appid_module && (asd.scan_flags & SCAN_HTTP_VENDOR_FLAG) &&
- !server.empty()) || (!thirdparty_appid_module && !server.empty()) )
+ // tp_appid_module is off?
+ if ( (have_tp && (asd.scan_flags & SCAN_HTTP_VENDOR_FLAG) &&
+ !server.empty()) || (!have_tp && !server.empty()) )
{
if ( asd.service.get_id() == APP_ID_NONE || asd.service.get_id() == APP_ID_HTTP )
{
/* Scan X-Working-With HTTP header */
// FIXIT-M: Should we be checking the scan_flags even when
- // thirdparty_appid_module is off?
- if ( (thirdparty_appid_module && (asd.scan_flags & SCAN_HTTP_XWORKINGWITH_FLAG) &&
- !x_working_with.empty()) || (!thirdparty_appid_module && !x_working_with.empty()) )
+ // tp_appid_module is off?
+ if ( (have_tp && (asd.scan_flags & SCAN_HTTP_XWORKINGWITH_FLAG) &&
+ !x_working_with.empty()) || (!have_tp && !x_working_with.empty()))
{
AppId appId;
char* version = nullptr;
// Scan Content-Type Header for multimedia types and scan contents
// FIXIT-M: Should we be checking the scan_flags even when
- // thirdparty_appid_module is off?
- if ( (thirdparty_appid_module && (asd.scan_flags & SCAN_HTTP_CONTENT_TYPE_FLAG)
- && !content_type.empty() && !asd.is_payload_appid_set())
- || (!thirdparty_appid_module && !asd.is_payload_appid_set() && !content_type.empty()) )
+ // tp_appid_module is off?
+ if ( (have_tp && (asd.scan_flags & SCAN_HTTP_CONTENT_TYPE_FLAG)
+ && !content_type.empty() && !asd.is_payload_appid_set())
+ || (!have_tp && !asd.is_payload_appid_set() && !content_type.empty()) )
{
payload_id = http_matchers->get_appid_by_content_type(content_type.c_str(), content_type.size());
if (appidDebug->is_active() && payload_id > APP_ID_NONE
return 0;
}
-// FIXIT-H - This function is unused and untested currently... need to figure who wants it
-// and what it should do
-void AppIdHttpSession::update_http_xff_address(struct XffFieldValue* /*xff_fields*/,
- uint32_t /*numXffFields*/)
+// FIXIT-H - Implement this function when (reconfigurable) XFF is supported.
+void AppIdHttpSession::update_http_xff_address(struct XffFieldValue* xff_fields,
+ uint32_t numXffFields)
{
+ UNUSED(xff_fields);
+ UNUSED(numXffFields);
#if 0
static const char* defaultXffPrecedence[] =
{
{
for (unsigned i = 0; i < numXffFields; i++)
LogMessage("AppIdDbg %s XFF %s : %s\n", appidDebug->get_debug_session(),
- xff_fields[i].field, xff_fields[i].value.empty()? "(empty)": xff_fields[i].value);
+ xff_fields[i].field.c_str(), xff_fields[i].value.empty()? "(empty)": xff_fields[i].value);
}
// xffPrecedence array is sorted based on precedence
xff_addr = nullptr;
}
- if (strncasecmp(xff_fields[j].field, xffPrecedence[i], UINT8_MAX) == 0)
+ if (strncasecmp(xff_fields[j].field.c_str(), xffPrecedence[i], UINT8_MAX) == 0)
{
- if (!xff_fields[j].value || (xff_fields[j].value[0] == '\0'))
+ if(xff_fields[j].value.empty())
return;
// For a comma-separated list of addresses, pick the last address
// FIXIT-L: change to select last address port from 2.9.10-42..not tested
- xff_addr = new snort::SfIp();
- char* xff_addr_str = nullptr;
- char* tmp = strchr(xff_fields[j].value, ',');
-
- if (tmp)
- {
- xff_addr_str = tmp + 1;
- }
- else
- {
- xff_fields[j].value[tmp - xff_fields[j].value] = '\0';
- xff_addr_str = xff_fields[j].value;
- }
- if (xff_addr->set(xff_addr_str) != SFIP_SUCCESS)
- {
- delete xff_addr;
- xff_addr = nullptr;
- }
+ // FIXIT_H: - this code is wrong. We can't have
+ // tmp-xff_fields[j].value when tmp=0.
+
+ // xff_addr = new snort::SfIp();
+ // char* xff_addr_str = nullptr;
+ // char* tmp = strchr(xff_fields[j].value, ',');
+
+ // if (tmp)
+ // {
+ // xff_addr_str = tmp + 1;
+ // }
+ // else
+ // {
+ // xff_fields[j].value[tmp - xff_fields[j].value] = '\0';
+ // xff_addr_str = xff_fields[j].value;
+ // }
+
+ // if (xff_addr->set(xff_addr_str) != SFIP_SUCCESS)
+ // {
+ // delete xff_addr;
+ // xff_addr = nullptr;
+ // }
break;
}
}
return http_fields[REQ_COOKIE_FID].end_offset;
}
-static void replace_header_data(std::string& header, const uint8_t* content, int32_t clen)
-{
- if (clen <= 0)
- return;
-
- header.clear();
- header.append((const char*) content, clen);
-}
-
void AppIdHttpSession::update_host(const uint8_t* new_host, int32_t len)
{
- replace_header_data(host, new_host, len);
+ host.assign((const char*)new_host, len);
}
void AppIdHttpSession::update_uri(const uint8_t* new_uri, int32_t len)
{
- replace_header_data(uri, new_uri, len);
+ uri.assign((const char*)new_uri, len);
}
void AppIdHttpSession::update_url()
void AppIdHttpSession::update_useragent(const uint8_t* new_ua, int32_t len)
{
- replace_header_data(useragent, new_ua, len);
+ useragent.assign((const char*)new_ua, len);
}
void AppIdHttpSession::update_cookie(const uint8_t* new_cookie, int32_t len)
{
- replace_header_data(cookie, new_cookie, len);
+ cookie.assign((const char*)new_cookie, len);
}
void AppIdHttpSession::update_referer(const uint8_t* new_referer, int32_t len)
{
- replace_header_data(referer, new_referer, len);
+ referer.assign((const char*)new_referer, len);
}
void AppIdHttpSession::update_x_working_with(const uint8_t* new_xww, int32_t len)
{
- replace_header_data(x_working_with, new_xww, len);
+ x_working_with.assign((const char*)new_xww, len);
}
void AppIdHttpSession::update_content_type(const uint8_t* new_content_type, int32_t len)
{
- replace_header_data(content_type, new_content_type, len);
+ content_type.assign((const char*)new_content_type, len);
}
void AppIdHttpSession::update_location(const uint8_t* new_location, int32_t len)
{
- replace_header_data(location, new_location, len);
+ location.assign((const char*)new_location, len);
}
void AppIdHttpSession::update_server(const uint8_t* new_server, int32_t len)
{
- replace_header_data(server, new_server, len);
+ server.assign((const char*)new_server, len);
}
void AppIdHttpSession::update_via(const uint8_t* new_via, int32_t len)
{
- replace_header_data(via, new_via, len);
+ via.assign((const char*)new_via, len);
}
void AppIdHttpSession::update_body(const uint8_t* new_body, int32_t len)
{
- replace_header_data(body, new_body, len);
+ body.assign((const char*)new_body, len);
}
void AppIdHttpSession::update_req_body(const uint8_t* new_req_body, int32_t len)
{
- replace_header_data(req_body, new_req_body, len);
+ req_body.assign((const char*)new_req_body, len);
}
void AppIdHttpSession::update_response_code(const char* new_rc)
#include <string>
#include <vector>
-#include "application_ids.h"
#include "flow/flow.h"
#include "sfip/sf_ip.h"
+#include "appid_types.h"
+#include "application_ids.h"
+#include "http_xff_fields.h"
class AppIdSession;
class ChpMatchDescriptor;
uint16_t end_offset = 0;
};
-struct XffFieldValue
-{
- char* field;
- char* value;
-};
-
class AppIdHttpSession
{
public:
AppIdHttpSession(AppIdSession&);
virtual ~AppIdHttpSession();
- int process_http_packet(int);
+ int process_http_packet(AppidSessionDirection direction);
void update_http_xff_address(struct XffFieldValue* xff_fields, uint32_t numXffFields);
const char* get_user_agent()
#include "lua_detector_module.h"
#include "service_plugins/service_discovery.h"
#include "service_plugins/service_ssl.h"
-#include "thirdparty_appid_utils.h"
using namespace snort;
static THREAD_LOCAL PacketTracer::TracerMute appid_mute;
if (session)
{
AppId service_id, client_id, payload_id, misc_id;
- const char *service_app_name, *client_app_name, *payload_app_name, *misc_name;
+ const char* service_app_name, * client_app_name, * payload_app_name, * misc_name;
session->get_application_ids(service_id, client_id, payload_id, misc_id);
service_app_name = appid_api.get_application_name(service_id);
client_app_name = appid_api.get_application_name(client_id);
appidDebug = new AppIdDebug();
if (active_config->mod_config and active_config->mod_config->log_all_sessions)
appidDebug->set_enabled(true);
+#ifdef ENABLE_APPID_THIRD_PARTY
+ active_config->tp_appid_module_tinit();
+#endif
}
void AppIdInspector::tterm()
delete HttpPatternMatchers::get_instance();
delete appidDebug;
appidDebug = nullptr;
+#ifdef ENABLE_APPID_THIRD_PARTY
+ active_config->tp_appid_module_tterm();
+#endif
}
void AppIdInspector::eval(Packet* p)
static Inspector* appid_inspector_ctor(Module* m)
{
- assert(m);
+ assert(m);
return new AppIdInspector((AppIdModule&)*m);
}
if (serverName)
{
ssl_scan_hostname((const uint8_t*)serverName, strlen(serverName), client_id,
- payload_app_id,
- &get_appid_config()->serviceSslConfig);
+ payload_app_id, &get_appid_config()->serviceSslConfig);
}
if (ssnptr && (asd = appid_api.get_appid_session(ssnptr)))
"enable appid debug logging" },
{ "dump_ports", Parameter::PT_BOOL, nullptr, "false",
"enable dump of appid port information" },
-#ifdef REMOVED_WHILE_NOT_IN_USE
- { "thirdparty_appid_dir", Parameter::PT_STRING, nullptr, nullptr,
- "directory to load thirdparty appid detectors from" },
-#endif
+ { "tp_appid_path", Parameter::PT_STRING, nullptr, nullptr,
+ "path to third party appid dynamic library" },
+ { "tp_appid_config", Parameter::PT_STRING, nullptr, nullptr,
+ "path to third party appid configuration file" },
{ "log_all_sessions", Parameter::PT_BOOL, nullptr, "false",
"enable logging of all appid sessions" },
{ nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
config->app_stats_rollover_time = v.get_long();
else if ( v.is("app_detector_dir") )
config->app_detector_dir = snort_strdup(v.get_string());
- else if ( v.is("thirdparty_appid_dir") )
- config->thirdparty_appid_dir = snort_strdup(v.get_string());
+ else if ( v.is("tp_appid_path") )
+ config->tp_appid_path = std::string(v.get_string());
+ else if ( v.is("tp_appid_config") )
+ config->tp_appid_config = std::string(v.get_string());
else if ( v.is("instance_id") )
config->instance_id = v.get_long();
else if ( v.is("debug") )
#include "appid_stats.h"
#include "appid_utils/ip_funcs.h"
#include "service_plugins/service_ssl.h"
-#include "thirdparty_appid_utils.h"
+#ifdef ENABLE_APPID_THIRD_PARTY
+#include "tp_appid_session_api.h"
+#endif
using namespace snort;
return nullptr;
}
-AppIdSession* AppIdSession::allocate_session(const Packet* p, IpProtocol proto, int direction,
+AppIdSession* AppIdSession::allocate_session(const Packet* p, IpProtocol proto,
+ AppidSessionDirection direction,
AppIdInspector& inspector)
{
uint16_t port = 0;
AppIdSession::AppIdSession(IpProtocol proto, const SfIp* ip, uint16_t port,
AppIdInspector& inspector)
: FlowData(inspector_id, &inspector), config(inspector.get_appid_config()),
- protocol(proto), inspector(inspector)
+ protocol(proto), inspector(inspector)
{
service_ip.clear();
session_id = ++appid_flow_data_id;
common.initiator_ip = *ip;
common.initiator_port = port;
app_info_mgr = &AppInfoManager::get_instance();
- if (thirdparty_appid_module)
- if (!(tpsession = thirdparty_appid_module->session_create()))
- ErrorMessage("Could not allocate third party session data");
length_sequence.proto = IpProtocol::PROTO_NOT_SET;
length_sequence.sequence_cnt = 0;
}
}
- if (thirdparty_appid_module)
+#ifdef ENABLE_APPID_THIRD_PARTY
+ if (tpsession)
{
- thirdparty_appid_module->session_delete(tpsession, 0);
+ delete tpsession;
tpsession = nullptr;
}
+#endif
delete_session_data();
free_flow_data();
client_disco_state = APPID_DISCO_STATE_NONE;
free_flow_data_by_mask(APPID_SESSION_DATA_CLIENT_MODSTATE_BIT);
+#ifdef ENABLE_APPID_THIRD_PARTY
//3rd party cleaning
- if (thirdparty_appid_module)
- thirdparty_appid_module->session_delete(tpsession, 1);
+ if (tpsession)
+ tpsession->reset();
+#endif
+
init_tpPackets = 0;
resp_tpPackets = 0;
{
SnortProtocolId tmp_snort_protocol_id = entry->snort_protocol_id;
// A particular APP_ID_xxx may not be assigned a service_snort_key value
- // in the rna_app.yaml file entry; so ignore the snort_protocol_id == UNKNOWN_PROTOCOL_ID case.
+ // in the rna_app.yaml file entry; so ignore the snort_protocol_id ==
+ // UNKNOWN_PROTOCOL_ID case.
if ( tmp_snort_protocol_id == UNKNOWN_PROTOCOL_ID && (newAppId == APP_ID_HTTP2))
tmp_snort_protocol_id = snortId_for_http2;
if ( tmp_snort_protocol_id != snort_protocol_id )
{
snort_protocol_id = tmp_snort_protocol_id;
- if (appidDebug->is_active() && tmp_snort_protocol_id == snortId_for_http2)
+ if (appidDebug->is_active() && tmp_snort_protocol_id == snortId_for_http2)
LogMessage("AppIdDbg %s Telling Snort that it's HTTP/2\n",
appidDebug->get_debug_session());
return;
if ( app_info_mgr->get_priority(payload.get_id()) > app_info_mgr->get_priority(id) )
- return;
+ return;
payload.set_id(id);
payload.set_version(version);
}
delete dsession;
}
-
int AppIdSession::add_flow_data(void* data, unsigned id, AppIdFreeFCN fcn)
{
AppIdFlowDataIter it = flow_data.find(id);
return 0;
}
-void AppIdSession::stop_rna_service_inspection(Packet* p, int direction)
+void AppIdSession::stop_rna_service_inspection(Packet* p, AppidSessionDirection direction)
{
if (direction == APP_ID_FROM_INITIATOR)
{
if (service.get_id() > APP_ID_NONE && !deferred)
return service.get_id();
- if (is_third_party_appid_available(tpsession))
+ if (is_third_party_appid_available())
{
if (tp_app_id > APP_ID_NONE)
return tp_app_id;
if (service.get_id() > APP_ID_NONE && !deferred)
return service.get_id();
- if (is_third_party_appid_available(tpsession) && tp_app_id > APP_ID_NONE)
+ if (is_third_party_appid_available() && tp_app_id > APP_ID_NONE)
return tp_app_id;
else if (deferred)
return service.get_id();
}
void AppIdSession::set_application_ids(AppId service_id, AppId client_id,
- AppId payload_id, AppId misc_id)
+ AppId payload_id, AppId misc_id)
{
application_ids[APP_PROTOID_SERVICE] = service_id;
application_ids[APP_PROTOID_CLIENT] = client_id;
}
void AppIdSession::get_application_ids(AppId& service_id, AppId& client_id,
- AppId& payload_id, AppId& misc_id)
+ AppId& payload_id, AppId& misc_id)
{
service_id = application_ids[APP_PROTOID_SERVICE];
client_id = application_ids[APP_PROTOID_CLIENT];
tp_payload_app_id = APP_ID_UNKNOWN;
tp_app_id = APP_ID_UNKNOWN;
- if (thirdparty_appid_module)
- thirdparty_appid_module->session_delete(tpsession, 1);
+#ifdef ENABLE_APPID_THIRD_PARTY
+ if (this->tpsession)
+ this->tpsession->reset();
+#endif
}
bool AppIdSession::is_payload_appid_set()
if (!get_session_flags(APPID_SESSION_SPDY_SESSION))
{
clear_session_flags(APPID_SESSION_CHP_INSPECTING);
- if (thirdparty_appid_module)
- thirdparty_appid_module->session_attr_clear(tpsession,
- TP_ATTR_CONTINUE_MONITORING);
+#ifdef ENABLE_APPID_THIRD_PARTY
+ if (this->tpsession)
+ this->tpsession->clear_attr(TP_ATTR_CONTINUE_MONITORING);
+#endif
}
}
dsession = new AppIdDnsSession();
return dsession;
}
+
+bool AppIdSession::is_third_party_appid_done() const
+{
+#ifdef ENABLE_APPID_THIRD_PARTY
+ if (config->have_tp())
+ {
+ unsigned state;
+
+ if (tpsession)
+ state = tpsession->get_state();
+ else
+ state = TP_STATE_INIT;
+
+ return (state == TP_STATE_CLASSIFIED || state == TP_STATE_TERMINATED
+ || state == TP_STATE_HA);
+ }
+#endif
+
+ return true;
+}
+
+bool AppIdSession::is_third_party_appid_available() const
+{
+#ifdef ENABLE_APPID_THIRD_PARTY
+ if (config->have_tp())
+ {
+ unsigned state;
+
+ if (tpsession)
+ state = tpsession->get_state();
+ else
+ state = TP_STATE_INIT;
+
+ return (state == TP_STATE_CLASSIFIED || state == TP_STATE_TERMINATED
+ || state == TP_STATE_MONITORING);
+ }
+#endif
+
+ return false;
+}
#include <map>
#include <string>
+#include "detector_plugins/http_url_patterns.h"
#include "app_info_table.h"
#include "appid_api.h"
#include "appid_app_descriptor.h"
+#include "appid_types.h"
#include "application_ids.h"
#include "length_app_cache.h"
#include "service_state.h"
-#include "detector_plugins/http_url_patterns.h"
class ClientDetector;
class ServiceDetector;
class AppIdDnsSession;
class AppIdHttpSession;
+class ThirdPartyAppIDSession;
using AppIdFreeFCN = void (*)(void*);
APPID_DISCO_STATE_FINISHED
};
-enum APPID_SESSION_DIRECTION
-{
- APP_ID_FROM_INITIATOR,
- APP_ID_FROM_RESPONDER,
- APP_ID_APPID_SESSION_DIRECTION_MAX // Maximum value of a direction (must be last in the list)
-};
-
class AppIdFlowData
{
public:
uint16_t initiator_port = 0;
};
+// FIXIT-L: make these const strings
struct TlsSession
{
char* tls_host = nullptr;
AppIdSession(IpProtocol, const snort::SfIp*, uint16_t port, AppIdInspector&);
~AppIdSession() override;
- static AppIdSession* allocate_session(const snort::Packet*, IpProtocol, int, AppIdInspector&);
- static AppIdSession* create_future_session(const snort::Packet*, const snort::SfIp*, uint16_t, const snort::SfIp*,
+ static AppIdSession* allocate_session(const snort::Packet*, IpProtocol,
+ AppidSessionDirection, AppIdInspector&);
+ static AppIdSession* create_future_session(const snort::Packet*, const snort::SfIp*, uint16_t,
+ const snort::SfIp*,
uint16_t, IpProtocol, SnortProtocolId, int, AppIdInspector&);
AppIdInspector& get_inspector() const
TlsSession* tsession = nullptr;
unsigned scan_flags = 0;
- void* tpsession = nullptr;
+ ThirdPartyAppIDSession* tpsession = nullptr;
uint16_t init_tpPackets = 0;
uint16_t resp_tpPackets = 0;
bool tp_reinspect_by_initiator = false;
static unsigned inspector_id;
static void init() { inspector_id = FlowData::create_flow_data_id(); }
- void set_session_flags(uint64_t flags){ common.flags |= flags; }
+ void set_session_flags(uint64_t flags) { common.flags |= flags; }
void clear_session_flags(uint64_t flags) { common.flags &= ~flags; }
- uint64_t get_session_flags(uint64_t flags) { return (common.flags & flags); }
+ uint64_t get_session_flags(uint64_t flags) const { return (common.flags & flags); }
void set_service_detected() { common.flags |= APPID_SESSION_SERVICE_DETECTED; }
bool is_service_detected() { return common.flags & APPID_SESSION_SERVICE_DETECTED; }
void set_client_detected() { common.flags |= APPID_SESSION_CLIENT_DETECTED; }
void update_encrypted_app_id(AppId);
void examine_rtmp_metadata();
void sync_with_snort_protocol_id(AppId, snort::Packet*);
- void stop_rna_service_inspection(snort::Packet*, int);
+ void stop_rna_service_inspection(snort::Packet*, AppidSessionDirection);
bool is_payload_appid_set();
void clear_http_flags();
AppIdHttpSession* get_http_session();
AppIdDnsSession* get_dns_session();
+ bool is_third_party_appid_done() const;
+ bool is_third_party_appid_available() const;
+
private:
AppIdHttpSession* hsession = nullptr;
AppIdDnsSession* dsession = nullptr;
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2014-2018 Cisco and/or its affiliates. All rights reserved.
+// Copyright (C) 2005-2013 Sourcefire, Inc.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// appid_session.h author Sourcefire Inc.
+
+#ifndef APPID_TYPES_H
+#define APPID_TYPES_H
+
+enum AppidSessionDirection
+{
+ APP_ID_FROM_INITIATOR,
+ APP_ID_FROM_RESPONDER,
+ APP_ID_APPID_SESSION_DIRECTION_MAX
+};
+
+#endif
#include "detector_plugins/detector_pop3.h"
#include "detector_plugins/detector_sip.h"
#include "detector_plugins/detector_smtp.h"
-#include "thirdparty_appid_utils.h"
using namespace snort;
free_matched_list(&match_list);
}
-int ClientDiscovery::get_detector_candidates_list(AppIdSession& asd, Packet* p, int direction)
+int ClientDiscovery::get_detector_candidates_list(AppIdSession& asd, Packet* p, AppidSessionDirection direction)
{
if (direction == APP_ID_FROM_INITIATOR)
{
return APPID_SESSION_SUCCESS;
}
-int ClientDiscovery::exec_client_detectors(AppIdSession& asd, Packet* p, int direction)
+int ClientDiscovery::exec_client_detectors(AppIdSession& asd, Packet* p, AppidSessionDirection direction)
{
int ret = APPID_INPROCESS;
return ret;
}
-bool ClientDiscovery::do_client_discovery(AppIdSession& asd, Packet* p, int direction)
+bool ClientDiscovery::do_client_discovery(AppIdSession& asd, Packet* p, AppidSessionDirection direction)
{
bool isTpAppidDiscoveryDone = false;
AppInfoTableEntry* entry;
{
if ( p->flow->get_session_flags() & SSNFLAG_MIDSTREAM )
asd.client_disco_state = APPID_DISCO_STATE_FINISHED;
- else if ( is_third_party_appid_available(asd.tpsession)
+ else if ( asd.is_third_party_appid_available()
&& ( asd.tp_app_id > APP_ID_NONE && asd.tp_app_id < SF_APPID_MAX ) )
{
//tp has positively identified appId, Dig deeper only if sourcefire
//stop rna inspection as soon as tp has classified a valid AppId
if ( ( asd.client_disco_state == APPID_DISCO_STATE_STATEFUL ||
- asd.client_disco_state == APPID_DISCO_STATE_DIRECT) &&
- asd.client_disco_state == prevRnaClientState &&
- !asd.get_session_flags(APPID_SESSION_NO_TPI) &&
- is_third_party_appid_available(asd.tpsession) &&
- asd.tp_app_id > APP_ID_NONE && asd.tp_app_id < SF_APPID_MAX)
+ asd.client_disco_state == APPID_DISCO_STATE_DIRECT) &&
+ asd.client_disco_state == prevRnaClientState &&
+ !asd.get_session_flags(APPID_SESSION_NO_TPI) &&
+ asd.is_third_party_appid_available() &&
+ asd.tp_app_id > APP_ID_NONE && asd.tp_app_id < SF_APPID_MAX)
{
entry = asd.app_info_mgr->get_app_info_entry(asd.tp_app_id);
if ( !( entry && entry->client_detector
#include "flow/flow.h"
#include "log/messages.h"
+#include "appid_types.h"
+
class ClientDetector;
class AppIdSession;
static ClientDiscovery& get_instance(AppIdInspector* ins = nullptr);
void finalize_client_plugins();
- bool do_client_discovery(AppIdSession&, snort::Packet*, int direction);
+ bool do_client_discovery(AppIdSession&, snort::Packet*, AppidSessionDirection direction);
private:
ClientDiscovery(AppIdInspector& ins);
void initialize() override;
- int exec_client_detectors(AppIdSession&, snort::Packet*, int direction);
+ int exec_client_detectors(AppIdSession&, snort::Packet*, AppidSessionDirection direction);
ClientAppMatch* find_detector_candidates(const snort::Packet* pkt, IpProtocol);
void create_detector_candidates_list(AppIdSession&, snort::Packet*);
- int get_detector_candidates_list(AppIdSession&, snort::Packet*, int direction);
+ int get_detector_candidates_list(AppIdSession&, snort::Packet*, AppidSessionDirection direction);
};
#endif
return ret;
}
-int DnsValidator::dns_validate_header(const int dir, const DNSHeader* hdr,
+int DnsValidator::dns_validate_header(const AppidSessionDirection dir, const DNSHeader* hdr,
bool host_reporting, AppIdSession& asd)
{
if (hdr->Opcode > MAX_OPCODE || hdr->Opcode == INVALID_OPCODE)
uint16_t id, bool host_reporting, AppIdSession&);
int dns_validate_answer(const uint8_t* data, uint16_t* offset, uint16_t size,
uint16_t id, uint8_t rcode, bool host_reporting, AppIdSession&);
- int dns_validate_header(const int dir, const DNSHeader*, bool host_reporting, AppIdSession&);
+ int dns_validate_header(const AppidSessionDirection dir, const DNSHeader*, bool host_reporting, AppIdSession&);
int validate_packet(const uint8_t* data, uint16_t size, const int,
bool host_reporting, AppIdSession&);
};
static THREAD_LOCAL KerberosServiceDetector* krb_service_detector = nullptr;
static int krb_walk_server_packet(KRBState* krbs, const uint8_t* s, const uint8_t* end,
- AppIdSession& asd, snort::Packet* pkt, const int dir, const char* reqCname)
+ AppIdSession& asd, snort::Packet* pkt, const AppidSessionDirection dir, const char* reqCname)
{
static const uint8_t KRB_SERVER_VERSION[] = "\x0a0\x003\x002\x001";
static const uint8_t KRB_SERVER_TYPE[] = "\x0a1\x003\x002\x001";
{
const Packet* p = sip_event.get_packet();
IpProtocol protocol = p->is_tcp() ? IpProtocol::TCP : IpProtocol::UDP;
- int direction = p->is_from_client() ? APP_ID_FROM_INITIATOR : APP_ID_FROM_RESPONDER;
+ AppidSessionDirection direction = p->is_from_client() ? APP_ID_FROM_INITIATOR : APP_ID_FROM_RESPONDER;
asd = AppIdSession::allocate_session(p, protocol, direction,
client->get_handler().get_inspector());
}
asd.set_session_flags(APPID_SESSION_CLIENT_GETS_SERVER_PACKETS);
}
- int direction = (sip_event.get_packet()->is_from_client()) ?
+ AppidSessionDirection direction = (sip_event.get_packet()->is_from_client()) ?
APP_ID_FROM_INITIATOR : APP_ID_FROM_RESPONDER;
if ( sip_event.is_invite() && direction == APP_ID_FROM_INITIATOR )
}
ss->serverPkt = 0;
- int direction = sip_event.get_packet()->is_from_client() ? APP_ID_FROM_INITIATOR :
+ AppidSessionDirection direction = sip_event.get_packet()->is_from_client() ? APP_ID_FROM_INITIATOR :
APP_ID_FROM_RESPONDER;
if ( direction == APP_ID_FROM_RESPONDER )
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2014-2018 Cisco and/or its affiliates. All rights reserved.
+// Copyright (C) 2005-2013 Sourcefire, Inc.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// http_xff_fields.h author Sourcefire Inc.
+
+#ifndef HTTP_XFF_FIELDS_H
+#define HTTP_XFF_FIELDS_H
+
+#include <string>
+
+// FIXIT-L refactor
+#define HTTP_XFF_FIELD_X_FORWARDED_FOR "X-Forwarded-For"
+#define HTTP_XFF_FIELD_TRUE_CLIENT_IP "True-Client-IP"
+/* #define HTTP_MAX_XFF_FIELDS 8 */
+/* #define HTTP_XFF_FIELD_X_FORWARDED_FOR "" */
+/* #define HTTP_XFF_FIELD_TRUE_CLIENT_IP "" */
+
+#define HTTP_MAX_XFF_FIELDS 8
+
+struct XffFieldValue
+{
+ std::string field;
+ std::string value;
+};
+
+
+#endif
#ifndef LENGTH_APP_CACHE_H
#define LENGTH_APP_CACHE_H
-#include "application_ids.h"
#include "protocols/protocol_ids.h"
+#include "appid_types.h"
+#include "application_ids.h"
#define LENGTH_SEQUENCE_CNT_MAX (5)
struct LengthSequenceEntry
{
- uint8_t direction = 0; /* APP_ID_FROM_INITIATOR or APP_ID_FROM_RESPONDER */
+ AppidSessionDirection direction = APP_ID_FROM_INITIATOR;
uint16_t length = 0; /* payload size (bytes) */
};
}
// FIXIT-M - the comments and code below for service_get_service_id don't appear to be useful
-// the ud->server.service_id field is set to APP_ID_UNKNOWN at init time and never updated
+// the ud->server.service_id field is set to APP_ID_UNKNOWN at init time and never
+// updated
// is this function ever used?
/**design: don't store service_id in detector structure since a single detector
* can get service_id for multiple protocols. For example SIP which gets Id for RTP and
const uint8_t* pattern_str = (const uint8_t*)lua_tolstring(L, ++index, &pattern_size);
uint32_t app_id = lua_tointeger(L, ++index);
DetectorHTTPPattern pattern;
- if( pattern.init(pattern_str, pattern_size, seq, service_id, client_id,
+ if ( pattern.init(pattern_str, pattern_size, seq, service_id, client_id,
payload_id, app_id) )
{
HttpPatternMatchers::get_instance()->insert_http_pattern(pat_type, pattern);
auto& ud = *UserData<AppIdDetector>::check(L, DETECTOR, index);
ud->validate_lua_state(false);
-
// Parameter 1
AppId appId = lua_tointeger(L, ++index);
AppId appIdInstance = CHP_APPID_SINGLE_INSTANCE(appId); // Last instance for the old API
size_t pattern_size = 0;
const uint8_t* pattern_str = (const uint8_t*)lua_tolstring(L, ++index, &pattern_size);
DetectorHTTPPattern pattern;
- if( pattern.init(pattern_str, pattern_size, seq, service_id, client_id,
+ if ( pattern.init(pattern_str, pattern_size, seq, service_id, client_id,
payload_id, APP_ID_NONE) )
{
HttpPatternMatchers::get_instance()->insert_http_pattern(pat_type, pattern);
{
/* Obsolete API names. No longer use these! They are here for backward
* compatibility and will eventually be removed. */
- { "memcmp", detector_memcmp }, // - "memcmp" is now "matchSimplePattern" (below)
- { "getProtocolType", detector_get_protocol_type }, // - "getProtocolType" is now "getL4Protocol" (below)
- { "inCompatibleData", service_set_incompatible_data }, // - "inCompatibleData" is now "markIncompleteData" (below)
- { "addDataId", service_add_data_id }, // - "addDataId" is now "addAppIdDataToFlow" (below)
- { "service_inCompatibleData", service_set_incompatible_data }, // - "service_inCompatibleData" is now "service_markIncompleteData" (below)
- { "service_addDataId", service_add_data_id }, // - "service_addDataId" is now "service_addAppIdDataToFlow" (below)
+ { "memcmp", detector_memcmp }, // - "memcmp" is now
+ // "matchSimplePattern"
+ // (below)
+ { "getProtocolType", detector_get_protocol_type }, // - "getProtocolType" is now
+ // "getL4Protocol" (below)
+ { "inCompatibleData", service_set_incompatible_data }, // - "inCompatibleData" is
+ // now "markIncompleteData"
+ // (below)
+ { "addDataId", service_add_data_id }, // - "addDataId" is now
+ // "addAppIdDataToFlow"
+ // (below)
+ { "service_inCompatibleData", service_set_incompatible_data }, // - "service_inCompatibleData"
+ // is now
+ // "service_markIncompleteData"
+ // (below)
+ { "service_addDataId", service_add_data_id }, // - "service_addDataId" is
+ // now
+ // "service_addAppIdDataToFlow"
+ // (below)
{ "getPacketSize", detector_get_packet_size },
{ "getPacketDir", detector_get_packet_direction },
return rc;
}
-static inline void init_lsd(LuaStateDescriptor* lsd, const std::string& detector_name, lua_State* L)
+static inline void init_lsd(LuaStateDescriptor* lsd, const std::string& detector_name,
+ lua_State* L)
{
- lsd->service_id = APP_ID_UNKNOWN;
- get_lua_field(L, -1, "init", lsd->package_info.initFunctionName);
- get_lua_field(L, -1, "clean", lsd->package_info.cleanFunctionName);
- get_lua_field(L, -1, "validate", lsd->package_info.validateFunctionName);
- get_lua_field(L, -1, "minimum_matches", lsd->package_info.minimum_matches);
- lsd->package_info.name = detector_name;
+ lsd->service_id = APP_ID_UNKNOWN;
+ get_lua_field(L, -1, "init", lsd->package_info.initFunctionName);
+ get_lua_field(L, -1, "clean", lsd->package_info.cleanFunctionName);
+ get_lua_field(L, -1, "validate", lsd->package_info.validateFunctionName);
+ get_lua_field(L, -1, "minimum_matches", lsd->package_info.minimum_matches);
+ lsd->package_info.name = detector_name;
lua_pop(L, 1); // pop client table
lua_pop(L, 1); // pop DetectorPackageInfo table
lsd->my_lua_state = L;
static inline bool lua_params_validator(LuaDetectorParameters& ldp, bool packet_context)
{
- if ( packet_context )
- {
- assert(ldp.asd);
- assert(ldp.pkt);
- }
- else
- {
- assert(!ldp.pkt);
- }
+ if ( packet_context )
+ {
+ assert(ldp.asd);
+ assert(ldp.pkt);
+ }
+ else
+ {
+ assert(!ldp.pkt);
+ }
#ifdef NDEBUG
UNUSED(ldp);
#endif
- return true;
+ return true;
}
LuaServiceDetector::LuaServiceDetector(AppIdDiscovery* sdm, const std::string& detector_name,
name = detector_name;
proto = protocol;
handler->register_detector(name, this, proto);
- init_lsd(&lsd, detector_name, L);
+ init_lsd(&lsd, detector_name, L);
UserData<AppIdDetector>::push(L, DETECTOR, this);
// add a lua reference so the detector doesn't get garbage-collected
lua_pushvalue(L, -1);
LuaStateDescriptor* LuaServiceDetector::validate_lua_state(bool packet_context)
{
- lua_params_validator(lsd.ldp, packet_context);
- return &lsd;
+ lua_params_validator(lsd.ldp, packet_context);
+ return &lsd;
}
int LuaServiceDetector::validate(AppIdDiscoveryArgs& args)
LuaClientDetector::LuaClientDetector(AppIdDiscovery* cdm, const std::string& detector_name,
IpProtocol protocol, lua_State* L)
- {
- handler = cdm;
- name = detector_name;
- proto = protocol;
- handler->register_detector(name, this, proto);
- init_lsd(&lsd, detector_name, L);
- UserData<AppIdDetector>::push(L, DETECTOR, this);
- // add a lua reference so the detector doesn't get garbage-collected
- lua_pushvalue(L, -1);
- lsd.detector_user_data_ref = luaL_ref(L, LUA_REGISTRYINDEX);
- }
+{
+ handler = cdm;
+ name = detector_name;
+ proto = protocol;
+ handler->register_detector(name, this, proto);
+ init_lsd(&lsd, detector_name, L);
+ UserData<AppIdDetector>::push(L, DETECTOR, this);
+ // add a lua reference so the detector doesn't get garbage-collected
+ lua_pushvalue(L, -1);
+ lsd.detector_user_data_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+}
LuaStateDescriptor* LuaClientDetector::validate_lua_state(bool packet_context)
{
- lua_params_validator(lsd.ldp, packet_context);
- return &lsd;
+ lua_params_validator(lsd.ldp, packet_context);
+ return &lsd;
}
int LuaClientDetector::validate(AppIdDiscoveryArgs& args)
const uint8_t* data = nullptr;
uint16_t size = 0;
- int dir = 0;
+ AppidSessionDirection dir = APP_ID_FROM_INITIATOR;
AppIdSession* asd;
snort::Packet* pkt = nullptr;
uint8_t macAddress[6] = { 0 };
class LuaStateDescriptor
{
public:
- LuaStateDescriptor() = default;
+ LuaStateDescriptor() = default;
virtual ~LuaStateDescriptor();
LuaDetectorParameters ldp;
{
public:
LuaServiceDetector(AppIdDiscovery* sdm, const std::string& detector_name, IpProtocol protocol,
- lua_State* L);
+ lua_State* L);
int validate(AppIdDiscoveryArgs&) override;
LuaStateDescriptor* validate_lua_state(bool packet_context) override;
LuaDetectorManager::add_detector_flow(detector_flow);
detector_flow->asd = AppIdSession::create_future_session(lsd->ldp.pkt, &saddr, sport,
- &daddr, dport, proto, 0, 0, ud->get_handler().get_inspector());
+ &daddr, dport, proto, 0, 0, ud->get_handler().get_inspector());
if (!detector_flow->asd)
{
pEntry->flags |= extractsInfo;
}
-int ServiceDetector::service_inprocess(AppIdSession& asd, const Packet* pkt, int dir)
+int ServiceDetector::service_inprocess(AppIdSession& asd, const Packet* pkt, AppidSessionDirection dir)
{
if (dir == APP_ID_FROM_INITIATOR ||
asd.get_session_flags(APPID_SESSION_IGNORE_HOST | APPID_SESSION_UDP_REVERSED))
return APPID_SUCCESS;
}
-int ServiceDetector::update_service_data(AppIdSession& asd, const Packet* pkt, int dir, AppId appId,
+int ServiceDetector::update_service_data(AppIdSession& asd, const Packet* pkt, AppidSessionDirection dir, AppId appId,
const char* vendor, const char* version)
{
uint16_t port = 0;
return APPID_SUCCESS;
}
-int ServiceDetector::add_service_consume_subtype(AppIdSession& asd, const Packet* pkt, int dir,
- AppId appId, const char* vendor, const char* version, AppIdServiceSubtype* subtype)
+int ServiceDetector::add_service_consume_subtype(AppIdSession& asd, const Packet* pkt,
+ AppidSessionDirection dir, AppId appId, const char* vendor, const char* version,
+ AppIdServiceSubtype* subtype)
{
asd.subtype = subtype;
return update_service_data(asd, pkt, dir, appId, vendor, version);
}
-int ServiceDetector::add_service(AppIdSession& asd, const Packet* pkt, int dir, AppId appId,
- const char* vendor, const char* version, const AppIdServiceSubtype* subtype)
+int ServiceDetector::add_service(AppIdSession& asd, const Packet* pkt, AppidSessionDirection dir,
+ AppId appId, const char* vendor, const char* version, const AppIdServiceSubtype* subtype)
{
AppIdServiceSubtype* new_subtype = nullptr;
return update_service_data(asd, pkt, dir, appId, vendor, version);
}
-int ServiceDetector::incompatible_data(AppIdSession& asd, const Packet* pkt, int dir)
+int ServiceDetector::incompatible_data(AppIdSession& asd, const Packet* pkt, AppidSessionDirection dir)
{
return static_cast<ServiceDiscovery*>(handler)->incompatible_data(asd, pkt, dir, this);
}
-int ServiceDetector::fail_service(AppIdSession& asd, const Packet* pkt, int dir)
+int ServiceDetector::fail_service(AppIdSession& asd, const Packet* pkt, AppidSessionDirection dir)
{
return static_cast<ServiceDiscovery*>(handler)->fail_service(asd, pkt, dir, this);
}
void ServiceDetector::initialize_expected_session(AppIdSession& parent, AppIdSession& expected,
- uint64_t flags, APPID_SESSION_DIRECTION dir)
+ uint64_t flags, AppidSessionDirection dir)
{
if (dir == APP_ID_FROM_INITIATOR)
{
void do_custom_init() override { }
void register_appid(AppId, unsigned extractsInfo) override;
- int service_inprocess(AppIdSession&, const snort::Packet*, int dir);
- int add_service(AppIdSession&, const snort::Packet*, int dir, AppId, const char* vendor = nullptr,
+ int service_inprocess(AppIdSession&, const snort::Packet*, AppidSessionDirection dir);
+ int add_service(AppIdSession&, const snort::Packet*, AppidSessionDirection dir, AppId, const char* vendor = nullptr,
const char* version = nullptr, const snort::AppIdServiceSubtype* = nullptr);
- int add_service_consume_subtype(AppIdSession&, const snort::Packet*, int dir, AppId,
+ int add_service_consume_subtype(AppIdSession&, const snort::Packet*, AppidSessionDirection dir, AppId,
const char* vendor, const char* version, snort::AppIdServiceSubtype*);
- int incompatible_data(AppIdSession&, const snort::Packet*, int dir);
- int fail_service(AppIdSession&, const snort::Packet*, int dir);
+ int incompatible_data(AppIdSession&, const snort::Packet*, AppidSessionDirection dir);
+ int fail_service(AppIdSession&, const snort::Packet*, AppidSessionDirection dir);
void add_host_info(AppIdSession&, SERVICE_HOST_INFO_CODE, const void*)
{
asd.misc_app_id = miscId;
}
- void initialize_expected_session(AppIdSession&, AppIdSession&, uint64_t flags, APPID_SESSION_DIRECTION dir);
+ void initialize_expected_session(AppIdSession&, AppIdSession&, uint64_t flags, AppidSessionDirection dir);
private:
- int update_service_data(AppIdSession&, const snort::Packet*, int dir, AppId, const char* vendor,
+ int update_service_data(AppIdSession&, const snort::Packet*, AppidSessionDirection dir, AppId, const char* vendor,
const char* version);
};
#endif
return udp_validate(data, size, args.dir, args.asd, args.pkt, fd);
}
-int DirectConnectServiceDetector::tcp_validate(const uint8_t* data, uint16_t size, const int dir,
+int DirectConnectServiceDetector::tcp_validate(const uint8_t* data, uint16_t size, const AppidSessionDirection dir,
AppIdSession& asd, const Packet* pkt, ServiceData* serviceData)
{
switch (serviceData->state)
return APPID_NOMATCH;
}
-int DirectConnectServiceDetector::udp_validate(const uint8_t* data, uint16_t size, const int dir,
+int DirectConnectServiceDetector::udp_validate(const uint8_t* data, uint16_t size, const AppidSessionDirection dir,
AppIdSession& asd, const Packet* pkt, ServiceData* serviceData)
{
if (dir == APP_ID_FROM_RESPONDER && serviceData->state == CONN_STATE_SERVICE_DETECTED)
int validate(AppIdDiscoveryArgs&) override;
private:
- int tcp_validate(const uint8_t* data, uint16_t size, const int dir, AppIdSession&,
+ int tcp_validate(const uint8_t* data, uint16_t size, const AppidSessionDirection dir, AppIdSession&,
const snort::Packet*, ServiceData*);
- int udp_validate(const uint8_t* data, uint16_t size, const int dir, AppIdSession&,
+ int udp_validate(const uint8_t* data, uint16_t size, const AppidSessionDirection dir, AppIdSession&,
const snort::Packet*, ServiceData*);
};
#include "service_tftp.h"
#include "service_timbuktu.h"
#include "service_tns.h"
-#include "thirdparty_appid_utils.h"
#ifdef REG_TEST
#include "service_regtest.h"
#endif
+#ifdef ENABLE_APPID_THIRD_PARTY
+#include "tp_appid_session_api.h"
+#endif
+
using namespace snort;
static THREAD_LOCAL ServiceDetector* ftp_service = nullptr;
* been specified (service_detector). Basically, this function handles going
* through the main port/pattern search (and returning which detector to add
* next to the list of detectors to try (even if only 1)). */
-void ServiceDiscovery::get_next_service(const Packet* p, const int dir, AppIdSession& asd)
+void ServiceDiscovery::get_next_service(const Packet* p, const AppidSessionDirection dir, AppIdSession& asd)
{
auto proto = asd.protocol;
}
}
-int ServiceDiscovery::identify_service(AppIdSession& asd, Packet* p, int dir)
+int ServiceDiscovery::identify_service(AppIdSession& asd, Packet* p, AppidSessionDirection dir)
{
ServiceDiscoveryState* sds = nullptr;
bool got_brute_force = false;
return asd.add_flow_data_id(21, ftp_service);
}
-bool ServiceDiscovery::do_service_discovery(AppIdSession& asd, Packet* p, int direction)
+bool ServiceDiscovery::do_service_discovery(AppIdSession& asd, Packet* p, AppidSessionDirection direction)
{
bool isTpAppidDiscoveryDone = false;
asd.service_disco_state = APPID_DISCO_STATE_FINISHED;
}
}
- else if (is_third_party_appid_available(asd.tpsession))
+ else if (asd.is_third_party_appid_available())
{
if (asd.tp_app_id > APP_ID_NONE)
{
//stop rna inspection as soon as tp has classified a valid AppId later in the session
if ( asd.service_disco_state == APPID_DISCO_STATE_STATEFUL &&
- prevRnaServiceState == APPID_DISCO_STATE_STATEFUL &&
- !asd.get_session_flags(APPID_SESSION_NO_TPI) &&
- is_third_party_appid_available(asd.tpsession) &&
- asd.tp_app_id > APP_ID_NONE && asd.tp_app_id < SF_APPID_MAX)
+ prevRnaServiceState == APPID_DISCO_STATE_STATEFUL &&
+ !asd.get_session_flags(APPID_SESSION_NO_TPI) &&
+ asd.is_third_party_appid_available() &&
+ asd.tp_app_id > APP_ID_NONE && asd.tp_app_id < SF_APPID_MAX)
{
AppInfoTableEntry* entry = asd.app_info_mgr->get_app_info_entry(asd.tp_app_id);
if ( entry && entry->service_detector &&
asd.stop_rna_service_inspection(p, direction);
asd.service_disco_state = APPID_DISCO_STATE_FINISHED;
// - Shut down TP.
- thirdparty_appid_module->session_state_set(asd.tpsession, TP_STATE_TERMINATED);
+
+#ifdef ENABLE_APPID_THIRD_PARTY
+ asd.tpsession->set_state(TP_STATE_TERMINATED);
+#endif
// - Just ignore everything from now on.
asd.set_session_flags(APPID_SESSION_IGNORE_FLOW);
}
* client ultimately we will have to fail the service. If the same behavior is seen from different
* clients going to same service then this most likely the service is something else.
*/
-int ServiceDiscovery::incompatible_data(AppIdSession& asd, const Packet* pkt, int dir,
+int ServiceDiscovery::incompatible_data(AppIdSession& asd, const Packet* pkt, AppidSessionDirection dir,
ServiceDetector* service)
{
if (service)
return APPID_SUCCESS;
}
-int ServiceDiscovery::fail_service(AppIdSession& asd, const Packet* pkt, int dir,
+int ServiceDiscovery::fail_service(AppIdSession& asd, const Packet* pkt, AppidSessionDirection dir,
ServiceDetector* service, ServiceDiscoveryState* sds)
{
if ( service )
#include "log/messages.h"
#include "utils/sflsq.h"
+#include "appid_types.h"
+
class AppIdConfig;
class AppIdSession;
class ServiceDetector;
ServiceDetector* get_next_tcp_detector(AppIdDetectorsIterator&);
ServiceDetector* get_next_udp_detector(AppIdDetectorsIterator&);
- bool do_service_discovery(AppIdSession&, snort::Packet*, int);
- int identify_service(AppIdSession&, snort::Packet*, int dir);
- int fail_service(AppIdSession&, const snort::Packet*, int dir, ServiceDetector*,
- ServiceDiscoveryState* sds = nullptr);
- int incompatible_data(AppIdSession&, const snort::Packet*, int dir, ServiceDetector*);
+ bool do_service_discovery(AppIdSession&, snort::Packet*, AppidSessionDirection dir);
+ int identify_service(AppIdSession&, snort::Packet*, AppidSessionDirection dir);
+ int fail_service(AppIdSession&, const snort::Packet*, AppidSessionDirection dir, ServiceDetector*, ServiceDiscoveryState* sds = nullptr);
+ int incompatible_data(AppIdSession&, const snort::Packet*, AppidSessionDirection dir, ServiceDetector*);
static int add_ftp_service_state(AppIdSession&);
private:
ServiceDiscovery(AppIdInspector& ins);
void initialize() override;
- void get_next_service(const snort::Packet*, const int dir, AppIdSession&);
+ void get_next_service(const snort::Packet*, const AppidSessionDirection dir, AppIdSession&);
void get_port_based_services(IpProtocol, uint16_t port, AppIdSession&);
void match_by_pattern(AppIdSession&, const snort::Packet*, IpProtocol);
void FtpServiceDetector::create_expected_session(AppIdSession& asd, const Packet* pkt, const SfIp* cliIp,
uint16_t cliPort, const SfIp* srvIp, uint16_t srvPort, IpProtocol proto,
- int flags, APPID_SESSION_DIRECTION dir)
+ int flags, AppidSessionDirection dir)
{
if(ftp_data_snort_protocol_id == UNKNOWN_PROTOCOL_ID)
ftp_data_snort_protocol_id = SnortConfig::get_conf()->proto_ref->find("ftp-data");
private:
void create_expected_session(AppIdSession& asd,const snort::Packet* pkt,
const snort::SfIp* cliIp, uint16_t cliPort, const snort::SfIp* srvIp,
- uint16_t srvPort, IpProtocol proto, int flags, APPID_SESSION_DIRECTION dir);
+ uint16_t srvPort, IpProtocol proto, int flags, AppidSessionDirection dir);
SnortProtocolId ftp_data_snort_protocol_id = UNKNOWN_PROTOCOL_ID;
};
const uint8_t* begin;
const uint8_t* end;
const uint8_t* data = args.data;
- const int dir = args.dir;
+ const AppidSessionDirection dir = args.dir;
uint16_t size = args.size;
if (!size)
uint32_t tmp;
int retval = -1;
const uint8_t* data = args.data;
- const int dir = args.dir;
+ const AppidSessionDirection dir = args.dir;
uint16_t size = args.size;
if (dir != APP_ID_FROM_RESPONDER)
AppId serviceAppId = APP_ID_NETBIOS_DGM;
AppId miscAppId = APP_ID_NONE;
const uint8_t* data = args.data;
- const int dir = args.dir;
+ const AppidSessionDirection dir = args.dir;
uint16_t size = args.size;
if (!size)
return rpc;
}
-int RpcServiceDetector::validate_packet(const uint8_t* data, uint16_t size, int dir,
+int RpcServiceDetector::validate_packet(const uint8_t* data, uint16_t size, AppidSessionDirection dir,
AppIdSession& asd, Packet* pkt, ServiceRPCData* rd, const char** pname, uint32_t* program)
{
const ServiceRPCCall* call = nullptr;
int rval;
const uint8_t* data = args.data;
Packet* pkt = args.pkt;
- const int dir = args.dir;
+ const AppidSessionDirection dir = args.dir;
uint16_t size = args.size;
if (!size)
const char* pname = nullptr;
const uint8_t* data = args.data;
Packet* pkt = args.pkt;
- const int dir = args.dir;
+ const AppidSessionDirection dir = args.dir;
uint16_t size = args.size;
if (!size)
private:
int rpc_udp_validate(AppIdDiscoveryArgs&);
int rpc_tcp_validate(AppIdDiscoveryArgs&);
- int validate_packet(const uint8_t* data, uint16_t size, int dir, AppIdSession&,
+ int validate_packet(const uint8_t* data, uint16_t size, AppidSessionDirection dir, AppIdSession&,
snort::Packet*, ServiceRPCData*, const char** pname, uint32_t* program);
SnortProtocolId sunrpc_snort_protocol_id = UNKNOWN_PROTOCOL_ID;
};
-
add_library(appid_cpputest_deps OBJECT ../appid_peg_counts.cc ../../../sfip/sf_ip.cc ../../../utils/util_cstring.cc)
-include_directories ( appid PRIVATE ${APPID_INCLUDE_DIR} )
-# add_cpputest( app_info_table_test
-# SOURCES $<TARGET_OBJECTS:appid_cpputest_deps>
-# )
+include_directories ( appid PRIVATE ${APPID_INCLUDE_DIR} )
add_cpputest( appid_api_test
SOURCES $<TARGET_OBJECTS:appid_cpputest_deps>
SOURCES $<TARGET_OBJECTS:appid_cpputest_deps>
)
+if ( ENABLE_APPID_THIRD_PARTY )
+ add_library(tp_mock MODULE tp_mock.cc)
+
+ add_cpputest( tp_lib_handler_test
+ SOURCES tp_lib_handler_test.cc
+ ../tp_lib_handler.cc
+ LIBS dl
+ )
+
+ add_cpputest( tp_appid_types_test
+ SOURCES tp_appid_types_test.cc
+ )
+
+ set_property(TARGET tp_mock PROPERTY ENABLE_EXPORTS 1)
+endif()
+
#include "framework/data_bus.h"
#include "protocols/protocol_ids.h"
#include "service_inspectors/http_inspect/http_msg_header.h"
-#include "thirdparty_appid_api.h"
+#include "tp_appid_module_api.h"
+#include "tp_appid_session_api.h"
+#include "appid_http_session.h"
#include "appid_mock_definitions.h"
#include "appid_mock_http_session.h"
CHECK_EQUAL(appidDebug->is_active(), true);
// get_debug_session()
+#ifdef REG_TEST
const char* str = "2001:0db8:85a3:0000:0000:8a2e:0370:7334 1234 -> "
"2001:0db8:85a3:0000:0000:8a2e:0370:7335 443 17 AS=100 ID=3";
+#else
+ const char* str = "2001:db8:85a3::8a2e:370:7334 1234 -> "
+ "2001:db8:85a3::8a2e:370:7335 443 17 AS=100 ID=3";
+#endif
CHECK_TRUE(strcmp(appidDebug->get_debug_session(), str) == 0);
}
#include "network_inspectors/appid/appid_http_event_handler.cc"
#include "protocols/protocol_ids.h"
#include "service_inspectors/http_inspect/http_msg_header.h"
-#include "thirdparty_appid_api.h"
+#include "tp_appid_module_api.h"
+#include "tp_appid_session_api.h"
#include "appid_mock_definitions.h"
#include "appid_mock_inspector.h"
struct ThirdPartyAppIDModule;
AppIdConfig* pAppidActiveConfig = nullptr;
-THREAD_LOCAL ThirdPartyAppIDModule* thirdparty_appid_module = nullptr;
+ThirdPartyAppIDModule* tp_appid_module = nullptr;
char* snort_strndup(const char* src, size_t dst_size)
{
void ServiceDiscoveryState::set_service_id_valid(ServiceDetector*) { }
// Stubs for service_plugins/service_discovery.h
-int ServiceDiscovery::incompatible_data(AppIdSession&, const Packet*, int, ServiceDetector*)
+int ServiceDiscovery::incompatible_data(AppIdSession&, const Packet*, AppidSessionDirection, ServiceDetector*)
{
return 0;
}
-int ServiceDiscovery::fail_service(AppIdSession&, const Packet*, int, ServiceDetector*,
- ServiceDiscoveryState*)
+int ServiceDiscovery::fail_service(AppIdSession&, const Packet*, AppidSessionDirection, ServiceDetector*, ServiceDiscoveryState*)
{
return 0;
}
delete xff_addr;
}
-int AppIdHttpSession::process_http_packet(int) { return 0; }
+int AppIdHttpSession::process_http_packet(AppidSessionDirection) { return 0; }
char const* APPID_UT_XFF_IP_ADDR = "192.168.0.1";
char const* CONTENT_TYPE = "html/text";
return dsession;
}
+bool AppIdSession::is_third_party_appid_done() const
+{
+ return true;
+}
+
+bool AppIdSession::is_third_party_appid_available() const
+{
+ return false;
+}
+
#endif
--- /dev/null
+#ifndef LOG_MESSGE_MOCK
+#define LOG_MESSAGE_MOCK
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <cstdarg>
+
+using namespace std;
+
+// Note: without SO_PUBLIC this is not being exported so tp_mock.so won't
+// load because of undefined symbol error.
+SO_PUBLIC void ErrorMessage(const char* format,...)
+{
+ va_list ap;
+ va_start(ap,format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+}
+
+SO_PUBLIC [[noreturn]] void FatalError(const char* format,...)
+{
+ ErrorMessage(format);
+ exit(1);
+}
+
+
+SO_PUBLIC void WarningMessage(const char* format,...)
+{
+ va_list ap;
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+}
+
+SO_PUBLIC void LogMessage(const char* format,...)
+{
+ va_list ap;
+ va_start(ap, format);
+ vfprintf(stdout, format, ap);
+ va_end(ap);
+}
+
+// void Debug::print(const char*, int, uint64_t, const char*, ...) { }
+
+#endif
+
void ServiceDiscovery::finalize_service_patterns() {}
void ServiceDiscovery::match_by_pattern(AppIdSession&, const Packet*, IpProtocol) {}
void ServiceDiscovery::get_port_based_services(IpProtocol, uint16_t, AppIdSession&) {}
-void ServiceDiscovery::get_next_service(const Packet*, const int, AppIdSession&) {}
-int ServiceDiscovery::identify_service(AppIdSession&, Packet*, int) { return 0; }
+void ServiceDiscovery::get_next_service(const Packet*, const AppidSessionDirection, AppIdSession&) {}
+int ServiceDiscovery::identify_service(AppIdSession&, Packet*, AppidSessionDirection) { return 0; }
int ServiceDiscovery::add_ftp_service_state(AppIdSession&) { return 0; }
-bool ServiceDiscovery::do_service_discovery(AppIdSession&, Packet*, int) { return 0; }
-int ServiceDiscovery::incompatible_data(AppIdSession&, const Packet*,int,
+bool ServiceDiscovery::do_service_discovery(AppIdSession&, Packet*, AppidSessionDirection) { return 0; }
+int ServiceDiscovery::incompatible_data(AppIdSession&, const Packet*,AppidSessionDirection,
ServiceDetector*) { return 0; }
-int ServiceDiscovery::fail_service(AppIdSession&, const Packet*, int,
+int ServiceDiscovery::fail_service(AppIdSession&, const Packet*, AppidSessionDirection,
ServiceDetector*, ServiceDiscoveryState*) { return 0; }
int ServiceDiscovery::add_service_port(AppIdDetector*,
const ServiceDetectorPort&) { return APPID_EINVALID; }
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2016-2018 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.
+//--------------------------------------------------------------------------
+
+// tp_appid_types_test.cc author Silviu Minut <sminut@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <iostream>
+#include <string>
+
+#include "tp_appid_types.h"
+
+#include <CppUTest/CommandLineTestRunner.h>
+#include <CppUTest/TestHarness.h>
+
+// 1st CHECK_EQUAL checks that what comes out is what went in
+// 2nd CHECK_EQUAL checks that AttributeData still has it
+// 3rd CHECK_EQUAL checks that AttributeData doesn't leak memory upon consecutive sets
+// finally check that we don't leak or double free memory when caller owns it
+#define SET_GET_MACRO(func) \
+ ad.set_ ## func(abc.c_str(), abc.size()); \
+ outField=ad.func(0); \
+ CHECK_EQUAL(*outField,abc); \
+ outField=ad.func(0); \
+ CHECK_EQUAL(*outField,abc); \
+ ad.set_ ## func(def.c_str(), def.size()); \
+ outField=ad.func(0); \
+ CHECK_EQUAL(*outField,def); \
+ outField=ad.func(1); \
+ delete outField;
+
+#define SET_GET_OFFSET_MACRO(func) \
+ ad.set_ ## func(abc.c_str(), abc.size(), start, end); \
+ outField=ad.func(0); \
+ CHECK_EQUAL(*outField,abc); \
+ outField=ad.func(0); \
+ CHECK_EQUAL(*outField,abc); \
+ ad.set_ ## func(def.c_str(), def.size(), start, end); \
+ outField=ad.func(0); \
+ CHECK_EQUAL(*outField,def); \
+ outField=ad.func(1); \
+ delete outField;
+
+TEST_GROUP(tp_appid_types)
+{
+ void setup() override
+ {
+ }
+
+ void teardown() override
+ {
+ }
+};
+
+TEST(tp_appid_types, get_set)
+{
+ ThirdPartyAppIDAttributeData ad;
+ uint16_t start=0, end=3;
+ string abc("abc");
+ string def("def");
+ const string* outField=nullptr;
+
+ SET_GET_OFFSET_MACRO(spdy_request_path);
+ SET_GET_MACRO(spdy_request_scheme);
+ SET_GET_OFFSET_MACRO(spdy_request_host);
+ SET_GET_MACRO(http_request_url);
+ SET_GET_OFFSET_MACRO(http_request_uri);
+ SET_GET_OFFSET_MACRO(http_request_host);
+ SET_GET_OFFSET_MACRO(http_request_cookie);
+ SET_GET_MACRO(http_request_via);
+ SET_GET_MACRO(http_response_via);
+ SET_GET_MACRO(http_response_upgrade);
+ SET_GET_OFFSET_MACRO(http_request_user_agent);
+ SET_GET_MACRO(http_response_version);
+ SET_GET_MACRO(http_response_code);
+ SET_GET_MACRO(http_response_content);
+ SET_GET_MACRO(http_response_location);
+ SET_GET_MACRO(http_response_body);
+ SET_GET_MACRO(http_request_body);
+ SET_GET_MACRO(http_response_server);
+ SET_GET_MACRO(http_request_x_working_with);
+ SET_GET_MACRO(tls_host);
+ SET_GET_MACRO(tls_cname);
+ SET_GET_MACRO(tls_org_unit);
+ SET_GET_OFFSET_MACRO(http_request_referer);
+ SET_GET_MACRO(ftp_command_user);
+}
+
+int main(int argc, char** argv)
+{
+ int rc = CommandLineTestRunner::RunAllTests(argc, argv);
+ return rc;
+}
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2018-2018 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.
+//--------------------------------------------------------------------------
+
+// tp_lib_handler_test.cc author Silviu Minut <sminut@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <iostream>
+#include <string>
+
+#define TP_SUPPORTED 1
+
+#include "tp_lib_handler.h"
+#include "appid_config.h"
+#include "main/snort_debug.h"
+#include "log_message_mock.h"
+
+#include <CppUTest/CommandLineTestRunner.h>
+#include <CppUTest/TestHarness.h>
+
+using namespace std;
+
+TPLibHandler* tph = nullptr;
+AppIdModuleConfig config;
+
+AppIdModuleConfig::~AppIdModuleConfig() { }
+
+#ifdef DEBUG_MSGS
+void Debug::print(const char*, int, uint64_t, const char*, ...) { }
+#endif
+
+TEST_GROUP(tp_lib_handler)
+{
+};
+
+TEST(tp_lib_handler, load_unload)
+{
+ tph->pinit(&config);
+ CHECK_TRUE(tph->have_tp());
+
+ CreateThirdPartyAppIDSession_t asf = tph->tpsession_factory();
+ ThirdPartyAppIDSession* tpsession = asf();
+
+ CHECK_TRUE(tpsession != nullptr);
+
+ delete tpsession;
+
+ tph->pfini();
+}
+
+TEST(tp_lib_handler, tp_lib_handler_get)
+{
+ TPLibHandler* tph2=TPLibHandler::get();
+ CHECK_EQUAL(tph,tph2);
+}
+
+TEST(tp_lib_handler, load_error)
+{
+ // Trigger load error:
+ AppIdModuleConfig config;
+ config.tp_appid_path="nonexistent.so";
+ tph=TPLibHandler::get();
+ tph->pinit(&config);
+ CHECK_FALSE(tph->have_tp());
+ tph->pfini();
+}
+
+TEST(tp_lib_handler, tp_appid_module_pinit_error)
+{
+ // Trigger MODULE pinit error:
+ AppIdModuleConfig config;
+ config.tp_appid_path="./libtp_mock.so";
+ config.tp_appid_config=""; // forces MODULE::pinit() to return 1.
+ tph=TPLibHandler::get();
+ tph->pinit(&config);
+ CHECK_FALSE(tph->have_tp());
+ tph->pfini(1); // print stats too.
+}
+
+int main(int argc, char** argv)
+{
+ config.tp_appid_path="./libtp_mock.so";
+ config.tp_appid_config="./tp.config";
+ tph=TPLibHandler::get();
+
+ int rc = CommandLineTestRunner::RunAllTests(argc, argv);
+
+ TPLibHandler::destroy(tph);
+
+ return rc;
+}
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2016-2018 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.
+//--------------------------------------------------------------------------
+
+// tp_mock.cc author Silviu Minut <sminut@cisco.com>
+
+// Standalone compilation:
+// g++ -g -Wall -I.. -I/path/to/snort3/src -c tp_mock.cc
+// g++ -std=c++11 -g -Wall -I.. -I/path/to/snort3/src -shared -fPIC -o libtp_mock.so tp_mock.cc
+// As a module (dynamically loaded) - see CMakeLists.txt
+
+#include <iostream>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main/snort_types.h"
+
+#include "tp_appid_module_api.h"
+#include "tp_appid_session_api.h"
+
+#define THIRD_PARTY_APPID_MODULE_NAME "NAVL"
+
+#define WhereMacro __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__
+
+using namespace std;
+
+class ThirdPartyAppIDModuleImpl : public ThirdPartyAppIDModule
+{
+public:
+ ThirdPartyAppIDModuleImpl(uint32_t ver, const char* mname)
+ : ThirdPartyAppIDModule(ver, mname)
+ {
+ cerr << WhereMacro << endl;
+ }
+
+ ~ThirdPartyAppIDModuleImpl()
+ {
+ cerr << WhereMacro << endl;
+ }
+
+ // Hack: use cfg to manipulate pinit to return 1, so we can hit the
+ // if (ret != 0) case in tp_lib_handler.cc.
+ int pinit(ThirdPartyConfig& cfg)
+ {
+ cerr << WhereMacro << endl;
+ return cfg.tp_appid_config.empty() ? 1 : 0;
+ }
+
+ int tinit() { return 0; }
+ int reconfigure(const ThirdPartyConfig&) { return 0; }
+ int pfini()
+ {
+ cerr << WhereMacro << endl;
+ return 0;
+ }
+
+ int tfini() { return 0; }
+ int print_stats() { return 0; }
+ int reset_stats() { return 0; }
+};
+
+class ThirdPartyAppIDSessionImpl : public ThirdPartyAppIDSession
+{
+public:
+
+ bool reset() { return 1; }
+ bool process(const snort::Packet&, AppidSessionDirection, vector<AppId>&,
+ ThirdPartyAppIDAttributeData&) { return 1; }
+
+ int disable_flags(uint32_t) { return 0; }
+ TPState get_state() { return state; }
+ void set_state(TPState s) { state=s; }
+ void clear_attr(TPSessionAttr attr) { flags &= ~attr; }
+ void set_attr(TPSessionAttr attr) { flags |= attr; }
+ unsigned get_attr(TPSessionAttr attr) { return flags & attr; }
+
+private:
+ unsigned flags = 0;
+};
+
+// Object factories to create module and session.
+// This is the only way for outside callers to create module and session
+// once the .so has been loaded.
+extern "C"
+{
+ SO_PUBLIC ThirdPartyAppIDModuleImpl* create_third_party_appid_module();
+ SO_PUBLIC ThirdPartyAppIDSessionImpl* create_third_party_appid_session();
+
+ SO_PUBLIC ThirdPartyAppIDModuleImpl* create_third_party_appid_module()
+ {
+ return new ThirdPartyAppIDModuleImpl(1,"foobar");
+ }
+
+ SO_PUBLIC ThirdPartyAppIDSessionImpl* create_third_party_appid_session()
+ {
+ return new ThirdPartyAppIDSessionImpl;
+ }
+}
+
+++ /dev/null
-//--------------------------------------------------------------------------
-// Copyright (C) 2014-2018 Cisco and/or its affiliates. All rights reserved.
-// Copyright (C) 2005-2013 Sourcefire, Inc.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation. You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// thirdparty_appid_api.h author Sourcefire Inc.
-
-#ifndef THIRDPARTY_APPID_API_H
-#define THIRDPARTY_APPID_API_H
-
-#include "application_ids.h"
-#include "thirdparty_appid_types.h"
-
-namespace snort
-{
-struct Packet;
-}
-
-#define THIRD_PARTY_APP_ID_API_VERSION 1
-
-#define TP_PATH_MAX 4096
-
-struct ThirdPartyConfig
-{
- unsigned chp_body_collection_max;
- unsigned ftp_userid_disabled : 1;
- unsigned chp_body_collection_disabled : 1;
- unsigned tp_allow_probes : 1;
- unsigned http_upgrade_reporting_enabled : 1;
- char appid_tp_dir[TP_PATH_MAX];
- unsigned numXffFields;
- char** xffFields;
- unsigned oldNumXffFields;
- char** oldXffFields;
-};
-
-struct ThirdPartyUtils
-{
- void (* logMsg)(const char*, ...);
- uint32_t (* getSnortInstance)();
-};
-
-using ThirdPartyAppIDModInit = int (*)(ThirdPartyConfig*, ThirdPartyUtils*);
-using ThirdPartyAppIDModReconfigure = int (*)(ThirdPartyConfig*);
-using ThirdPartyAppIDModFini = int (*)();
-using ThirdPartyAppIDSessionCreate = void*(*)();
-using ThirdPartyAppIDSessionDelete = int (*)(void* tpsession, int just_reset_state);
-using ThirdPartyAppIDSessionProcess = int (*)(void* tpsession, snort::Packet*, int direction, // in
- AppId*, int* confidence, AppId** proto_list, ThirdPartyAppIDAttributeData** attribute_data);
-using ThirdPartyAppIDPrintStats = int (*)();
-using ThirdPartyAppIDResetStats = int (*)();
-using ThirdPartyAppIDDisableFlags = int (*)(void* tpsession, uint32_t session_flags);
-using ThirdPartyAppIDSessionStateGet = TPState (*)(void* tpsession);
-using ThirdPartyAppIDSessionStateSet = void (*)(void* tpsession, TPState);
-using ThirdPartyAppIDSessionAttrSet = void (*)(void* tpsession, TPSessionAttr);
-using ThirdPartyAppIDSessionAttrClear = void (*)(void* tpsession, TPSessionAttr);
-using ThirdPartyAppIDSessionAttrGet = unsigned (*)(void* tpsession, TPSessionAttr);
-using ThirdPartyAppIDSessionCurrenAppIdGet = AppId (*)(void* tpsession);
-
-// SO_PUBLIC const ThirdPartyAppIDModule thirdparty_appid_impl_module
-struct ThirdPartyAppIDModule
-{
- const uint32_t api_version;
- const char* module_name;
- ThirdPartyAppIDModInit init;
- ThirdPartyAppIDModReconfigure reconfigure;
- ThirdPartyAppIDModFini fini;
- ThirdPartyAppIDSessionCreate session_create;
- ThirdPartyAppIDSessionDelete session_delete;
- ThirdPartyAppIDSessionProcess session_process;
- ThirdPartyAppIDPrintStats print_stats;
- ThirdPartyAppIDResetStats reset_stats;
- ThirdPartyAppIDDisableFlags disable_flags;
-
- ThirdPartyAppIDSessionStateGet session_state_get;
- ThirdPartyAppIDSessionStateSet session_state_set;
- ThirdPartyAppIDSessionAttrSet session_attr_set;
- ThirdPartyAppIDSessionAttrClear session_attr_clear;
- ThirdPartyAppIDSessionAttrGet session_attr_get;
- ThirdPartyAppIDSessionCurrenAppIdGet session_appid_get;
-};
-
-#endif
-
+++ /dev/null
-//--------------------------------------------------------------------------
-// Copyright (C) 2014-2018 Cisco and/or its affiliates. All rights reserved.
-// Copyright (C) 2005-2013 Sourcefire, Inc.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation. You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// thirdparty_appid_types.h author Sourcefire Inc.
-
-#ifndef THIRDPARTY_APPID_TYPES_H
-#define THIRDPARTY_APPID_TYPES_H
-
-//#define BUILD_NAVL_SUPPORT 1
-
-#include <cstdint>
-
-#include "appid_http_session.h"
-
-#define TP_SESSION_FLAG_DPI 0x00000001
-#define TP_SESSION_FLAG_MUTABLE 0x00000002
-#define TP_SESSION_FLAG_FUTUREFLOW 0x00000004
-#define TP_SESSION_FLAG_ATTRIBUTE 0x00000008
-#define TP_SESSION_FLAG_TUNNELING 0x00000010
-
-#define HTTP_XFF_FIELD_X_FORWARDED_FOR ""
-#define HTTP_XFF_FIELD_TRUE_CLIENT_IP ""
-#define HTTP_MAX_XFF_FIELDS 255
-
-enum TPState
-{
- TP_STATE_INIT,
- TP_STATE_TERMINATED,
- TP_STATE_INSPECTING,
- TP_STATE_MONITORING,
- TP_STATE_CLASSIFIED,
- TP_STATE_HA = 21
-};
-
-enum TPSessionAttr
-{
- TP_ATTR_CONTINUE_MONITORING = (1 << 0),
- TP_ATTR_COPY_RESPONSE_CONTENT = (1 << 1),
- TP_ATTR_COPY_RESPONSE_LOCATION = (1 << 2),
- TP_ATTR_COPY_RESPONSE_BODY = (1 << 3),
-};
-
-struct ThirdPartyAppIDAttributeData
-{
- char* spdyRequestPath;
- char* spdyRequestScheme;
- char* spdyRequestHost;
- char* httpRequestUrl;
- char* httpRequestUri;
- uint16_t httpRequestUriLen;
- uint16_t httpRequestUriOffset;
- uint16_t httpRequestUriEndOffset;
- char* httpRequestHost;
- uint16_t httpRequestHostLen;
- char* httpRequestCookie;
- uint16_t httpRequestCookieLen;
- uint16_t httpRequestCookieOffset;
- uint16_t httpRequestCookieEndOffset;
- char* httpRequestVia;
- char* httpResponseVia;
- char* httpResponseUpgrade;
- char* httpRequestUserAgent;
- uint16_t httpRequestUserAgentLen;
- char* httpResponseVersion;
- char* httpResponseCode;
- uint16_t httpResponseCodeLen;
- char* httpResponseContent;
- uint16_t httpResponseContentLen;
- char* httpResponseLocation;
- uint16_t httpResponseLocationLen;
- char* httpResponseBody;
- uint16_t httpResponseBodyLen;
- char* httpRequestBody;
- uint16_t httpRequestBodyLen;
- char* httpResponseServer;
- char* httpRequestXWorkingWith;
- char* tlsHost;
- char* tlsCname;
- char* tlsOrgUnit;
- char* httpRequestReferer;
- uint16_t httpRequestRefererLen;
- char* ftpCommandUser;
- struct XffFieldValue xffFieldValue[HTTP_MAX_XFF_FIELDS];
- uint8_t numXffFields;
- uint16_t httpRequestUserAgentOffset;
- uint16_t httpRequestUserAgentEndOffset;
- uint16_t httpRequestHostOffset;
- uint16_t httpRequestHostEndOffset;
- uint16_t httpRequestRefererOffset;
- uint16_t httpRequestRefererEndOffset;
- uint16_t spdyRequestHostOffset;
- uint16_t spdyRequestHostEndOffset;
- uint16_t spdyRequestPathOffset;
- uint16_t spdyRequestPathEndOffset;
-};
-
-#endif
-
+++ /dev/null
-//--------------------------------------------------------------------------
-// Copyright (C) 2014-2018 Cisco and/or its affiliates. All rights reserved.
-// Copyright (C) 2005-2013 Sourcefire, Inc.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation. You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// thirdparty_appid_utils.cc author Sourcefire Inc.
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "thirdparty_appid_utils.h"
-
-#include <dlfcn.h>
-
-#include "log/messages.h"
-#include "profiler/profiler.h"
-#include "protocols/packet.h"
-#include "stream/stream.h"
-
-#include "app_info_table.h"
-#include "appid_config.h"
-#include "appid_debug.h"
-#include "appid_http_session.h"
-#include "appid_inspector.h"
-#include "detector_plugins/http_url_patterns.h"
-#include "service_plugins/service_ssl.h"
-
-using namespace snort;
-
-#define MODULE_SYMBOL "thirdparty_appid_impl_module"
-
-static THREAD_LOCAL void* module_handle = nullptr;
-static THREAD_LOCAL struct ThirdPartyConfig thirdpartyConfig;
-THREAD_LOCAL ThirdPartyAppIDModule* thirdparty_appid_module = nullptr;
-
-static char const* defaultXffFields[] = { HTTP_XFF_FIELD_X_FORWARDED_FOR,
- HTTP_XFF_FIELD_TRUE_CLIENT_IP };
-
-ProfileStats tpLibPerfStats;
-ProfileStats tpPerfStats;
-
-inline int testSSLAppIdForReinspect(AppId app_id)
-{
- if (app_id <= SF_APPID_MAX &&
- (app_id == APP_ID_SSL || AppInfoManager::get_instance().get_app_info_flags(app_id,
- APPINFO_FLAG_SSL_INSPECT)))
- return 1;
- else
- return 0;
-}
-
-#ifdef BUILD_NAVL_SUPPORT
-static int LoadCallback(const char* const path, int /* indent */)
-{
- void* handle;
- ThirdPartyAppIDModule* tp_module;
-
- if (thirdparty_appid_module != nullptr)
- {
- ErrorMessage("Ignoring additional 3rd party AppID module (%s)!\n", path);
- return 0;
- }
-
- handle = dlopen(path, RTLD_NOW | RTLD_LOCAL);
- if (handle == nullptr)
- {
- ErrorMessage("Failed to load 3rd party AppID module: %s - %s\n", path, dlerror());
- return 0;
- }
-
- tp_module = (ThirdPartyAppIDModule*)dlsym(handle, MODULE_SYMBOL);
- if (tp_module == nullptr)
- {
- ErrorMessage("Failed to fine symbol %s in library %s\n", MODULE_SYMBOL, path);
- dlclose(handle);
- return 0;
- }
-
- if ( (tp_module->api_version != THIRD_PARTY_APP_ID_API_VERSION)
- || ((tp_module->module_name == nullptr) || (tp_module->module_name[0] == 0))
- || (tp_module->init == nullptr)
- || (tp_module->fini == nullptr)
- || (tp_module->session_create == nullptr)
- || (tp_module->session_delete == nullptr)
- || (tp_module->session_process == nullptr)
- || (tp_module->print_stats == nullptr)
- || (tp_module->reset_stats == nullptr)
- || (tp_module->disable_flags == nullptr) )
- {
- ErrorMessage("Ignoring incomplete 3rd party AppID module (%s)!\n", path);
- dlclose(handle);
- return 0;
- }
-
- module_handle = handle;
- thirdparty_appid_module = tp_module;
- return 0;
-}
-
-#endif
-
-static void getXffFields()
-{
- // FIXIT-M need to get xff fields from http config
- const char** xffFields = nullptr; // = _dpd.getHttpXffFields(&thirdpartyConfig.numXffFields);
- //if (!xffFields) FIXIT-W always true
- {
- xffFields = defaultXffFields;
- thirdpartyConfig.numXffFields = sizeof(defaultXffFields) / sizeof(defaultXffFields[0]);
- }
- thirdpartyConfig.xffFields = (char**)snort_alloc(thirdpartyConfig.numXffFields *
- sizeof(char*));
- for (unsigned i = 0; i < thirdpartyConfig.numXffFields; i++)
- thirdpartyConfig.xffFields[i] = snort_strndup(xffFields[i], UINT8_MAX);
-}
-
-void ThirdPartyAppIDInit(const AppIdModuleConfig* config)
-{
- const char* thirdparty_appid_dir = config->thirdparty_appid_dir;
- int ret;
- struct ThirdPartyUtils thirdpartyUtils;
-
- if ( ( thirdparty_appid_module != nullptr ) || ( thirdparty_appid_dir == nullptr )
- || ( thirdparty_appid_dir[0] == 0 ) )
- return;
-
- // FIXIT-L need to port loadAllLibs function to snort3
- // _dpd.loadAllLibs(thirdparty_appid_dir, LoadCallback);
- if (thirdparty_appid_module == nullptr)
- {
- return;
- }
- memset(&thirdpartyConfig, 0, sizeof(thirdpartyConfig));
- thirdpartyConfig.chp_body_collection_max = config->chp_body_collection_max;
- thirdpartyConfig.ftp_userid_disabled = config->ftp_userid_disabled;
- thirdpartyConfig.chp_body_collection_disabled =
- config->chp_body_collection_disabled;
- thirdpartyConfig.tp_allow_probes = config->tp_allow_probes;
- if (config->http2_detection_enabled)
- thirdpartyConfig.http_upgrade_reporting_enabled = 1;
- else
- thirdpartyConfig.http_upgrade_reporting_enabled = 0;
- thirdpartyConfig.appid_tp_dir[0] = '\0'; // use default path
-
- // FIXIT-M need to provide log function and getSnortInstance function to 3rd party utils
-#ifdef BUILD_NAVL_SUPPORT
- //thirdpartyUtils.logMsg = &DebugFormat;
- //thirdpartyUtils.getSnortInstance = _dpd.getSnortInstance;
-#endif
-
- getXffFields();
-
- ret = thirdparty_appid_module->init(&thirdpartyConfig, &thirdpartyUtils);
- if (ret != 0)
- {
- ErrorMessage("Unable to initialize 3rd party AppID module (%d)!\n", ret);
- dlclose(module_handle);
- module_handle = nullptr;
- thirdparty_appid_module = nullptr;
- return;
- }
-}
-
-void ThirdPartyAppIDReconfigure()
-{
- int ret;
-
- if (thirdparty_appid_module == nullptr)
- {
- return;
- }
-
- thirdpartyConfig.oldNumXffFields = thirdpartyConfig.numXffFields;
- thirdpartyConfig.oldXffFields = thirdpartyConfig.xffFields;
- getXffFields();
-
- ret = thirdparty_appid_module->reconfigure(&thirdpartyConfig);
- for (unsigned i = 0; i < thirdpartyConfig.oldNumXffFields; i++)
- snort_free(thirdpartyConfig.oldXffFields[i]);
- snort_free(thirdpartyConfig.oldXffFields);
-
- if (ret != 0)
- {
- ErrorMessage("Unable to reconfigure 3rd party AppID module (%d)!\n", ret);
- return;
- }
-}
-
-void ThirdPartyAppIDFini()
-{
- if (thirdparty_appid_module != nullptr)
- {
- int ret = thirdparty_appid_module->fini();
-
- if (ret != 0)
- ErrorMessage("Could not finalize 3rd party AppID module (%d)!\n", ret);
-
- dlclose(module_handle);
- module_handle = nullptr;
- thirdparty_appid_module = nullptr;
-
- }
-}
-
-#ifdef BUILD_NAVL_SUPPORT
-
-// FIXIT-L bogus placeholder for this func, need to find out what it should do
-static inline bool TPIsAppIdDone(void*)
-{
- return false;
-}
-
-inline int ThirdPartyAppIDFoundProto(AppId proto, AppId* proto_list)
-{
- unsigned int proto_cnt = 0;
- while (proto_list[proto_cnt] != APP_ID_NONE)
- if (proto_list[proto_cnt++] == proto)
- return 1;
- // found
-
- return 0; // not found
-}
-
-bool checkThirdPartyReinspect(const Packet* p, AppIdSession& asd)
-{
- return p->dsize && !asd.get_session_flags(APPID_SESSION_NO_TPI) &&
- asd.get_session_flags(APPID_SESSION_HTTP_SESSION) && TPIsAppIdDone(asd.tpsession);
-}
-
-static void ProcessThirdPartyResults(AppIdSession& asd, int confidence, AppId* proto_list,
- ThirdPartyAppIDAttributeData* attribute_data)
-{
- AppId serviceAppId = 0;
- AppId client_id = 0;
- AppId payload_id = 0;
- AppId referred_payload_app_id = 0;
-
- if (ThirdPartyAppIDFoundProto(APP_ID_EXCHANGE, proto_list))
- {
- if (!payload_id)
- payload_id = APP_ID_EXCHANGE;
- }
-
- if (ThirdPartyAppIDFoundProto(APP_ID_HTTP, proto_list))
- {
- if (appidDebug->is_active())
- LogMessage("AppIdDbg %s HTTP flow\n", appidDebug->get_debug_session());
- asd.set_session_flags(APPID_SESSION_HTTP_SESSION);
- }
- if (ThirdPartyAppIDFoundProto(APP_ID_SPDY, proto_list))
- {
- if (appidDebug->is_active())
- LogMessage("AppIdDbg %s SPDY flow\n", appidDebug->get_debug_session());
-
- asd.set_session_flags(APPID_SESSION_HTTP_SESSION | APPID_SESSION_SPDY_SESSION);
- }
-
- if (asd.get_session_flags(APPID_SESSION_HTTP_SESSION))
- {
- AppIdHttpSession* hsession = asd.get_http_session();
- hsession->reset_ptype_scan_counts();
-
- if (asd.get_session_flags(APPID_SESSION_SPDY_SESSION))
- {
- if (attribute_data->spdyRequestScheme &&
- attribute_data->spdyRequestHost &&
- attribute_data->spdyRequestPath)
- {
- static const char httpsScheme[] = "https";
- static const char httpScheme[] = "http";
- std::string url;
- if (asd.get_session_flags(APPID_SESSION_DECRYPTED)
- &&
- memcmp(attribute_data->spdyRequestScheme, httpScheme,
- sizeof(httpScheme) - 1) == 0)
- {
- url = httpsScheme;
- }
- else
- {
- url = attribute_data->spdyRequestScheme;
- }
-
-
- if (hsession->get_url())
- hsession->set_chp_finished(false);
-
- url += "://";
- url += attribute_data->spdyRequestHost;
- url += attribute_data->spdyRequestPath;
- hsession->set_url(url.c_str());
- asd.scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
-
- snort_free(attribute_data->spdyRequestScheme);
- attribute_data->spdyRequestScheme = nullptr;
- }
- else if (attribute_data->spdyRequestScheme)
- {
- snort_free(attribute_data->spdyRequestScheme);
- attribute_data->spdyRequestScheme = nullptr;
- }
-
- if (attribute_data->spdyRequestHost)
- {
- if (hsession->get_host())
- hsession->set_chp_finished(false);
-
- hsession->update_host((const uint8_t*)attribute_data->spdyRequestHost,
- strlen(attribute_data->spdyRequestHost));
- // FIXIT-M do we need to free this memory and set to null
- // attribute_data->spdyRequestHost = nullptr;
- hsession->set_field_offset(REQ_HOST_FID, attribute_data->spdyRequestHostOffset);
- hsession->set_field_end_offset(REQ_HOST_FID,
- attribute_data->spdyRequestHostEndOffset);
- if (appidDebug->is_active())
- LogMessage("AppIdDbg %s SPDY host (%u-%u) is %s\n", appidDebug->get_debug_session(),
- hsession->get_field_offset(REQ_HOST_FID),
- hsession->get_field_end_offset(REQ_HOST_FID), hsession->get_host());
- asd.scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
- }
-
- if (attribute_data->spdyRequestPath)
- {
- if (hsession->get_uri())
- hsession->set_chp_finished(false);
-
- hsession->update_uri((const uint8_t*)attribute_data->spdyRequestPath,
- strlen(attribute_data->spdyRequestPath));
- // FIXIT-M do we need to free this memory and set to null
- //attribute_data->spdyRequestPath = nullptr;
- hsession->set_field_offset(REQ_URI_FID, attribute_data->spdyRequestPathOffset);
- hsession->set_field_end_offset(REQ_URI_FID, attribute_data->spdyRequestPathEndOffset);
- if (appidDebug->is_active())
- LogMessage("AppIdDbg %s SPDY URI (%u-%u) is %s\n", appidDebug->get_debug_session(),
- hsession->get_field_offset(REQ_URI_FID),
- hsession->get_field_end_offset(REQ_URI_FID), hsession->get_uri());
- }
- }
- else
- {
- if (attribute_data->httpRequestHost)
- {
- if (hsession->get_host())
- if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
- hsession->set_chp_finished(false);
-
- hsession->update_host((const uint8_t*)attribute_data->httpRequestHost,
- attribute_data->httpRequestHostLen);
- hsession->set_field_offset(REQ_HOST_FID, attribute_data->httpRequestHostOffset);
- hsession->set_field_end_offset(REQ_HOST_FID, attribute_data->httpRequestHostEndOffset);
- // FIXIT-M do we need to free this memory and set to null
- //attribute_data->httpRequestHost = nullptr;
- if (appidDebug->is_active())
- LogMessage("AppIdDbg %s HTTP host (%u-%u) is %s\n",
- appidDebug->get_debug_session(), hsession->get_field_offset(REQ_HOST_FID),
- hsession->get_field_end_offset(REQ_HOST_FID), attribute_data->httpRequestHost);
- asd.scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
- }
-
- if (attribute_data->httpRequestUrl)
- {
- static const char httpScheme[] = "http://";
-
- if (hsession->get_url())
- if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
- hsession->set_chp_finished(false);
-
- //change http to https if session was decrypted.
- if (asd.get_session_flags(APPID_SESSION_DECRYPTED)
- &&
- memcmp(attribute_data->httpRequestUrl, httpScheme, sizeof(httpScheme)-1) == 0)
- {
- char* req_url = attribute_data->httpRequestUrl + sizeof(httpScheme) - 1;
- std::string url = "https://";
- url += req_url;
-
- snort_free(attribute_data->httpRequestUrl);
- attribute_data->httpRequestUrl = nullptr;
- }
- else
- {
- hsession->set_url(attribute_data->httpRequestUrl);
- snort_free(attribute_data->httpRequestUrl);
- attribute_data->httpRequestUrl = nullptr;
- }
-
- asd.scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
- }
-
- if (attribute_data->httpRequestUri)
- {
- if (hsession->get_uri())
- if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
- hsession->set_chp_finished(false);
-
- hsession->update_uri((const uint8_t*)attribute_data->httpRequestUri,
- attribute_data->httpRequestUriLen);
- hsession->set_field_offset(REQ_URI_FID, attribute_data->httpRequestUriOffset);
- hsession->set_field_end_offset(REQ_URI_FID, attribute_data->httpRequestUriEndOffset);
- snort_free(attribute_data->httpRequestUri);
- attribute_data->httpRequestUri = nullptr;
- if (appidDebug->is_active())
- LogMessage("AppIdDbg %s URI (%u-%u) is %s\n", appidDebug->get_debug_session(),
- hsession->get_field_offset(REQ_URI_FID),
- hsession->get_field_end_offset(REQ_URI_FID), hsession->get_uri());
- }
- }
-
- if (attribute_data->httpRequestVia)
- {
- if (hsession->get_via())
- if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
- hsession->set_chp_finished(false);
-
- hsession->update_via((const uint8_t*)attribute_data->httpRequestVia,
- strlen(attribute_data->httpRequestVia));
- snort_free(attribute_data->httpRequestVia);
- attribute_data->httpRequestVia = nullptr;
- asd.scan_flags |= SCAN_HTTP_VIA_FLAG;
- }
- else if (attribute_data->httpResponseVia)
- {
- if (hsession->get_via())
- if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
- hsession->set_chp_finished(false);
-
- hsession->update_via((const uint8_t*)attribute_data->httpResponseVia,
- strlen(attribute_data->httpResponseVia));
- snort_free(attribute_data->httpResponseVia);
- attribute_data->httpResponseVia = nullptr;
- asd.scan_flags |= SCAN_HTTP_VIA_FLAG;
- }
-
- if (attribute_data->httpRequestUserAgent)
- {
- if (hsession->get_user_agent())
- if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
- hsession->set_chp_finished(false);
-
- hsession->update_useragent((const uint8_t*)attribute_data->httpRequestUserAgent,
- strlen(attribute_data->httpRequestUserAgent));
- snort_free(attribute_data->httpRequestUserAgent);
- attribute_data->httpRequestUserAgent = nullptr;
- if (appidDebug->is_active())
- LogMessage("AppIdDbg %s User Agent (%u-%u) is %s\n",
- appidDebug->get_debug_session(), hsession->get_field_offset(REQ_AGENT_FID),
- hsession->get_field_end_offset(REQ_AGENT_FID), hsession->get_user_agent());
- asd.scan_flags |= SCAN_HTTP_USER_AGENT_FLAG;
- }
-
- // Check to see if third party discovered HTTP/2. - once it supports it...
- if (attribute_data->httpResponseVersion)
- {
- if (appidDebug->is_active())
- LogMessage("AppIdDbg %s HTTP response version is %s\n", appidDebug->get_debug_session(),
- attribute_data->httpResponseVersion);
- if (strncmp(attribute_data->httpResponseVersion, "HTTP/2", 6) == 0)
- {
- if (appidDebug->is_active())
- LogMessage("AppIdDbg %s 3rd party detected and parsed HTTP/2\n",
- appidDebug->get_debug_session());
- asd.is_http2 = true;
- }
- snort_free(attribute_data->httpResponseVersion);
- attribute_data->httpResponseVersion = nullptr;
- }
- if (attribute_data->httpResponseCode)
- {
- if (appidDebug->is_active())
- LogMessage("AppIdDbg %s HTTP response code is %s\n", appidDebug->get_debug_session(),
- attribute_data->httpResponseCode);
- if (hsession->get_response_code())
- if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
- hsession->set_chp_finished(false);
-
- hsession->update_response_code((const char*)attribute_data->httpResponseCode);
- snort_free(attribute_data->httpResponseCode);
- attribute_data->httpResponseCode = nullptr;
- }
- // Check to see if we've got an upgrade to HTTP/2 (if enabled).
- // - This covers the "without prior knowledge" case (i.e., the client
- // asks the server to upgrade to HTTP/2).
- if (attribute_data->httpResponseUpgrade)
- {
- if (appidDebug->is_active())
- LogMessage("AppIdDbg %s HTTP response upgrade is %s\n", appidDebug->get_debug_session(),
- attribute_data->httpResponseUpgrade);
- if (asd.config->mod_config->http2_detection_enabled)
- if ( hsession->get_response_code()
- && (strncmp(hsession->get_response_code(), "101", 3) == 0) )
- if (strncmp(attribute_data->httpResponseUpgrade, "h2c", 3) == 0)
- {
- if (appidDebug->is_active())
- LogMessage("AppIdDbg %s Got an upgrade to HTTP/2\n",
- appidDebug->get_debug_session());
- asd.is_http2 = true;
- }
- snort_free(attribute_data->httpResponseUpgrade);
- attribute_data->httpResponseUpgrade = nullptr;
- }
- if (attribute_data->httpRequestReferer)
- {
- if (hsession->get_referer())
- if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
- hsession->set_chp_finished(false);
-
- hsession->update_referer((const uint8_t*)attribute_data->httpRequestReferer,
- attribute_data->httpRequestRefererLen);
- snort_free(attribute_data->httpRequestReferer);
- attribute_data->httpRequestReferer = nullptr;
- hsession->set_field_offset(REQ_REFERER_FID, attribute_data->httpRequestRefererOffset);
- hsession->set_field_end_offset(REQ_REFERER_FID, attribute_data->httpRequestRefererEndOffset);
- if (appidDebug->is_active())
- LogMessage("AppIdDbg %s Referrer (%u-%u) is %s\n", appidDebug->get_debug_session(),
- hsession->get_field_offset(REQ_REFERER_FID),
- hsession->get_field_end_offset(REQ_REFERER_FID),
- hsession->get_referer());
- }
-
- if (attribute_data->httpRequestCookie)
- {
- if (hsession->get_cookie())
- if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
- hsession->set_chp_finished(false);
-
- hsession->update_cookie((const uint8_t*)attribute_data->httpRequestCookie,
- attribute_data->httpRequestCookieLen);
- hsession->set_field_offset(REQ_COOKIE_FID, attribute_data->httpRequestCookieOffset);
- hsession->set_field_end_offset(REQ_COOKIE_FID, attribute_data->httpRequestCookieEndOffset);
- snort_free(attribute_data->httpRequestCookie);
- attribute_data->httpRequestCookie = nullptr;
- attribute_data->httpRequestCookieOffset = 0;
- attribute_data->httpRequestCookieEndOffset = 0;
- if (appidDebug->is_active())
- LogMessage("AppIdDbg %s Cookie (%u-%u) is %s\n", appidDebug->get_debug_session(),
- hsession->get_field_offset(REQ_COOKIE_FID),
- hsession->get_field_offset(REQ_COOKIE_FID),
- hsession->get_cookie());
- }
-
- if (attribute_data->httpResponseContent)
- {
- if (hsession->get_content_type())
- if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
- hsession->set_chp_finished(false);
-
- hsession->update_content_type((const uint8_t*)attribute_data->httpResponseContent,
- attribute_data->httpResponseContentLen);
- snort_free(attribute_data->httpResponseContent);
- attribute_data->httpResponseContent = nullptr;
- asd.scan_flags |= SCAN_HTTP_CONTENT_TYPE_FLAG;
- }
-
- if (hsession->get_ptype_scan_count(RSP_LOCATION_FID) && attribute_data->httpResponseLocation)
- {
- if (hsession->get_location())
- if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
- hsession->set_chp_finished(false);
-
- hsession->update_location((const uint8_t*)attribute_data->httpResponseLocation,
- attribute_data->httpResponseLocationLen);
- snort_free(attribute_data->httpResponseLocation);
- attribute_data->httpResponseLocation = nullptr;
- }
-
- if (attribute_data->httpRequestBody)
- {
- if (appidDebug->is_active())
- LogMessage("AppIdDbg %s Got a request body %s\n", appidDebug->get_debug_session(),
- attribute_data->httpRequestBody);
- if (hsession->get_req_body())
- if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
- hsession->set_chp_finished(false);
-
- hsession->update_req_body((const uint8_t*)attribute_data->httpRequestBody,
- attribute_data->httpRequestBodyLen);
- snort_free(attribute_data->httpRequestBody);
- attribute_data->httpRequestBody = nullptr;
- }
-
- if (hsession->get_ptype_scan_count(RSP_BODY_FID) && attribute_data->httpResponseBody)
- {
- if (hsession->get_body())
- if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
- hsession->set_chp_finished(false);
-
- hsession->update_body((const uint8_t*)attribute_data->httpResponseBody,
- attribute_data->httpResponseBodyLen);
- snort_free(attribute_data->httpResponseBody);
- attribute_data->httpResponseBody = nullptr;
- }
-
- if (attribute_data->numXffFields)
- hsession->update_http_xff_address(attribute_data->xffFieldValue, attribute_data->numXffFields);
-
- if (!hsession->is_chp_finished() || hsession->is_chp_hold_flow())
- {
- asd.set_session_flags(APPID_SESSION_CHP_INSPECTING);
- if (thirdparty_appid_module)
- thirdparty_appid_module->session_attr_set(asd.tpsession,
- TP_ATTR_CONTINUE_MONITORING);
- }
-
- if (attribute_data->httpResponseServer)
- {
- hsession->update_server((const uint8_t*)attribute_data->httpResponseServer,
- strlen(attribute_data->httpResponseServer));
- snort_free(attribute_data->httpResponseServer);
- attribute_data->httpResponseServer = nullptr;
- asd.scan_flags |= SCAN_HTTP_VENDOR_FLAG;
- }
-
- if (attribute_data->httpRequestXWorkingWith)
- {
- hsession->update_x_working_with((const uint8_t*)attribute_data->httpRequestXWorkingWith,
- strlen(attribute_data->httpRequestXWorkingWith));
- snort_free(attribute_data->httpRequestXWorkingWith);
- attribute_data->httpRequestXWorkingWith = nullptr;
- asd.scan_flags |= SCAN_HTTP_XWORKINGWITH_FLAG;
- }
- }
- else if (ThirdPartyAppIDFoundProto(APP_ID_RTMP, proto_list) ||
- ThirdPartyAppIDFoundProto(APP_ID_RTSP, proto_list))
- {
- AppIdHttpSession* hsession = asd.get_http_session();
-
- if (!hsession->get_url())
- {
- if (attribute_data->httpRequestUrl)
- {
- hsession->set_url(attribute_data->httpRequestUrl);
- snort_free(attribute_data->httpRequestUrl);
- attribute_data->httpRequestUrl = nullptr;
- asd.scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
- }
- }
-
- if ( !asd.config->mod_config->referred_appId_disabled && !hsession->get_referer() )
- {
- if (attribute_data->httpRequestReferer)
- {
- hsession->update_referer((const uint8_t*)attribute_data->httpRequestReferer, strlen(attribute_data->httpRequestReferer));
- snort_free(attribute_data->httpRequestReferer);
- attribute_data->httpRequestReferer = nullptr;
- }
- }
-
- if (hsession->get_url() || (confidence == 100 &&
- asd.session_packet_count > asd.config->mod_config->rtmp_max_packets))
- {
- if (hsession->get_url())
- {
- HttpPatternMatchers* http_matchers = HttpPatternMatchers::get_instance();
-
- if ( ( ( http_matchers->get_appid_from_url(nullptr, hsession->get_url(),
- nullptr, hsession->get_referer(), &client_id, &serviceAppId,
- &payload_id, &referred_payload_app_id, 1) )
- ||
- ( http_matchers->get_appid_from_url(nullptr, hsession->get_url(), nullptr,
- hsession->get_referer(), &client_id, &serviceAppId, &payload_id,
- &referred_payload_app_id, 0) ) ) == 1 )
- {
- // do not overwrite a previously-set client or service
- if (client_id <= APP_ID_NONE)
- asd.set_client_appid_data(client_id, nullptr);
- if (serviceAppId <= APP_ID_NONE)
- asd.set_service_appid_data(serviceAppId, nullptr, nullptr);
-
- // DO overwrite a previously-set data
- asd.set_payload_appid_data(payload_id, nullptr);
- asd.set_referred_payload_app_id_data(referred_payload_app_id);
- }
- }
-
- if (thirdparty_appid_module)
- {
- thirdparty_appid_module->disable_flags(asd.tpsession,
- TP_SESSION_FLAG_ATTRIBUTE | TP_SESSION_FLAG_TUNNELING |
- TP_SESSION_FLAG_FUTUREFLOW);
- thirdparty_appid_module->session_delete(asd.tpsession, 1);
- }
- asd.tpsession = nullptr;
- asd.clear_session_flags(APPID_SESSION_APP_REINSPECT);
- }
- }
- else if (ThirdPartyAppIDFoundProto(APP_ID_SSL, proto_list))
- {
- AppId tmpAppId = APP_ID_NONE;
-
- if (thirdparty_appid_module && asd.tpsession)
- tmpAppId = thirdparty_appid_module->session_appid_get(asd.tpsession);
-
- asd.set_session_flags(APPID_SESSION_SSL_SESSION);
-
- if (!asd.tsession)
- asd.tsession = (TlsSession*)snort_calloc(sizeof(TlsSession));
-
- if (!client_id)
- asd.set_client_appid_data(APP_ID_SSL_CLIENT, nullptr);
-
- if (attribute_data->tlsHost)
- {
- if (asd.tsession->tls_host)
- snort_free(asd.tsession->tls_host);
- asd.tsession->tls_host = attribute_data->tlsHost;
- attribute_data->tlsHost = nullptr;
- if (testSSLAppIdForReinspect(tmpAppId))
- asd.scan_flags |= SCAN_SSL_HOST_FLAG;
- }
- if (testSSLAppIdForReinspect(tmpAppId))
- {
- if (attribute_data->tlsCname)
- {
- if (asd.tsession->tls_cname)
- snort_free(asd.tsession->tls_cname);
- asd.tsession->tls_cname = attribute_data->tlsCname;
- attribute_data->tlsCname = nullptr;
- }
- if (attribute_data->tlsOrgUnit)
- {
- if (asd.tsession->tls_orgUnit)
- snort_free(asd.tsession->tls_orgUnit);
- asd.tsession->tls_orgUnit = attribute_data->tlsOrgUnit;
- attribute_data->tlsOrgUnit = nullptr;
- }
- }
- }
- else if (ThirdPartyAppIDFoundProto(APP_ID_FTP_CONTROL, proto_list))
- {
- if (!asd.config->mod_config->ftp_userid_disabled && attribute_data->ftpCommandUser)
- {
- asd.client.update_user(APP_ID_FTP_CONTROL, attribute_data->ftpCommandUser);
- asd.set_session_flags(APPID_SESSION_LOGIN_SUCCEEDED);
- attribute_data->ftpCommandUser = nullptr;
- }
- }
-}
-
-void checkTerminateTpModule(AppIdSession& asd, uint16_t tpPktCount)
-{
- AppIdHttpSession* hsession = asd.get_http_session();
-
- if ((tpPktCount >= asd.config->mod_config->max_tp_flow_depth) ||
- (asd.get_session_flags(APPID_SESSION_HTTP_SESSION | APPID_SESSION_APP_REINSPECT) ==
- (APPID_SESSION_HTTP_SESSION | APPID_SESSION_APP_REINSPECT) &&
- hsession->get_uri() && (!hsession->get_chp_candidate() || hsession->is_chp_finished())))
- {
- if (asd.tp_app_id == APP_ID_NONE)
- asd.tp_app_id = APP_ID_UNKNOWN;
- if (asd.payload.get_id() == APP_ID_NONE)
- asd.payload.set_id(APP_ID_UNKNOWN);
- if (thirdparty_appid_module)
- thirdparty_appid_module->session_delete(asd.tpsession, 1);
- }
-}
-
-bool do_third_party_discovery(AppIdSession& asd, IpProtocol protocol, const SfIp* ip,
- Packet* p, int& direction)
-{
- ThirdPartyAppIDAttributeData* tp_attribute_data;
- AppId* tp_proto_list;
- int tp_confidence;
- bool isTpAppidDiscoveryDone = false;
-
- //restart inspection by 3rd party
- if (!asd.tp_reinspect_by_initiator && (direction == APP_ID_FROM_INITIATOR) &&
- checkThirdPartyReinspect(p, asd))
- {
- asd.tp_reinspect_by_initiator = true;
- asd.set_session_flags(APPID_SESSION_APP_REINSPECT);
- if (appidDebug->is_active())
- LogMessage("AppIdDbg %s 3rd party allow reinspect http\n",
- appidDebug->get_debug_session());
- asd.reset_session_data();
- }
-
- if (asd.tp_app_id == APP_ID_SSH && asd.payload.get_id() != APP_ID_SFTP &&
- asd.session_packet_count >= MIN_SFTP_PACKET_COUNT &&
- asd.session_packet_count < MAX_SFTP_PACKET_COUNT)
- {
- if ( p->ptrs.ip_api.tos() == 8 )
- {
- asd.payload.set_id(APP_ID_SFTP);
- if (appidDebug->is_active())
- LogMessage("AppIdDbg %s Payload is SFTP\n", appidDebug->get_debug_session());
- }
- }
-
- Profile tpPerfStats_profile_context(tpPerfStats);
-
- /*** Start of third-party processing. ***/
- if (thirdparty_appid_module && !asd.get_session_flags(APPID_SESSION_NO_TPI)
- && (!TPIsAppIdDone(asd.tpsession)
- || asd.get_session_flags(APPID_SESSION_APP_REINSPECT | APPID_SESSION_APP_REINSPECT_SSL)))
- {
- // First SSL decrypted packet is now being inspected. Reset the flag so that SSL decrypted
- // traffic gets processed like regular traffic from next packet onwards
- if (asd.get_session_flags(APPID_SESSION_APP_REINSPECT_SSL))
- asd.clear_session_flags(APPID_SESSION_APP_REINSPECT_SSL);
-
- if (p->dsize || asd.config->mod_config->tp_allow_probes)
- {
- if (protocol != IpProtocol::TCP || (p->packet_flags & PKT_STREAM_ORDER_OK)
- || asd.config->mod_config->tp_allow_probes)
- {
- Profile tpLibPerfStats_profile_context(tpLibPerfStats);
- if (!asd.tpsession)
- {
- if (!(asd.tpsession = thirdparty_appid_module->session_create()))
- FatalError("Could not allocate asd.tpsession data");
- } // debug output of packet content
- thirdparty_appid_module->session_process(asd.tpsession, p, direction,
- &asd.tp_app_id, &tp_confidence,
- &tp_proto_list, &tp_attribute_data);
-
- isTpAppidDiscoveryDone = true;
- if (thirdparty_appid_module->session_state_get(asd.tpsession) ==
- TP_STATE_CLASSIFIED)
- asd.clear_session_flags(APPID_SESSION_APP_REINSPECT);
-
- if (appidDebug->is_active())
- LogMessage("AppIdDbg %s 3rd party returned %d\n", appidDebug->get_debug_session(),
- asd.tp_app_id);
-
- // For now, third party can detect HTTP/2 (w/o metadata) for
- // some cases. Treat it like HTTP w/ is_http2 flag set.
- if ((asd.tp_app_id == APP_ID_HTTP2) && (tp_confidence == 100))
- {
- if (appidDebug->is_active())
- LogMessage("AppIdDbg %s 3rd party saw HTTP/2\n", appidDebug->get_debug_session());
-
- asd.tp_app_id = APP_ID_HTTP;
- asd.is_http2 = true;
- }
- // if the third-party appId must be treated as a client, do it now
- if (asd.app_info_mgr->get_app_info_flags(asd.tp_app_id, APPINFO_FLAG_TP_CLIENT))
- asd.client.set_id(asd.tp_app_id);
-
- ProcessThirdPartyResults(asd, tp_confidence, tp_proto_list, tp_attribute_data);
-
- if (asd.get_session_flags(APPID_SESSION_SSL_SESSION) &&
- !(asd.scan_flags & SCAN_SSL_HOST_FLAG))
- {
- setSSLSquelch(p, 1, asd.tp_app_id, asd.get_inspector());
- }
-
- if (asd.app_info_mgr->get_app_info_flags(asd.tp_app_id, APPINFO_FLAG_IGNORE))
- {
- if (appidDebug->is_active())
- LogMessage("AppIdDbg %s 3rd party ignored\n", appidDebug->get_debug_session());
-
- if (asd.get_session_flags(APPID_SESSION_HTTP_SESSION))
- asd.tp_app_id = APP_ID_HTTP;
- else
- asd.tp_app_id = APP_ID_NONE;
- }
- }
- else
- {
- asd.tp_app_id = APP_ID_NONE;
- if (appidDebug->is_active() && !asd.get_session_flags(
- APPID_SESSION_TPI_OOO_LOGGED))
- {
- asd.set_session_flags(APPID_SESSION_TPI_OOO_LOGGED);
- LogMessage("AppIdDbg %s 3rd party packet out-of-order\n",
- appidDebug->get_debug_session());
- }
- }
-
- if (thirdparty_appid_module->session_state_get(asd.tpsession) == TP_STATE_MONITORING)
- {
- thirdparty_appid_module->disable_flags(asd.tpsession,
- TP_SESSION_FLAG_ATTRIBUTE | TP_SESSION_FLAG_TUNNELING |
- TP_SESSION_FLAG_FUTUREFLOW);
- }
-
- if (asd.tp_app_id == APP_ID_SSL &&
- (Stream::get_snort_protocol_id(p->flow) == snortId_for_ftp_data))
- {
- // If we see SSL on an FTP data channel set tpAppId back
- // to APP_ID_NONE so the FTP preprocessor picks up the flow.
- asd.tp_app_id = APP_ID_NONE;
- }
-
- if ( asd.tp_app_id > APP_ID_NONE
- && (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT)
- || asd.payload.get_id() > APP_ID_NONE) )
- {
- AppId snort_app_id;
- AppIdHttpSession* hsession = asd.get_http_session();
-
- // if the packet is HTTP, then search for via pattern
- if ( asd.get_session_flags(APPID_SESSION_HTTP_SESSION) )
- {
- snort_app_id = APP_ID_HTTP;
- //data should never be APP_ID_HTTP
- if (asd.tp_app_id != APP_ID_HTTP)
- asd.tp_payload_app_id = asd.tp_app_id;
-
- asd.tp_app_id = APP_ID_HTTP;
- // Handle HTTP tunneling and SSL possibly then being used in that tunnel
- if (asd.tp_app_id == APP_ID_HTTP_TUNNEL)
- asd.set_payload_appid_data(APP_ID_HTTP_TUNNEL, NULL);
- if ((asd.payload.get_id() == APP_ID_HTTP_TUNNEL) && (asd.tp_app_id ==
- APP_ID_SSL))
- asd.set_payload_appid_data(APP_ID_HTTP_SSL_TUNNEL, NULL);
-
- hsession->process_http_packet(direction);
-
- // If SSL over HTTP tunnel, make sure Snort knows that it's encrypted.
- if (asd.payload.get_id() == APP_ID_HTTP_SSL_TUNNEL)
- snort_app_id = APP_ID_SSL;
-
- if (is_third_party_appid_available(asd.tpsession) && asd.tp_app_id ==
- APP_ID_HTTP
- && !asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
- {
- asd.client_disco_state = APPID_DISCO_STATE_FINISHED;
- asd.set_session_flags(APPID_SESSION_CLIENT_DETECTED |
- APPID_SESSION_SERVICE_DETECTED);
- asd.client_disco_state = APPID_DISCO_STATE_FINISHED;
- asd.clear_session_flags(APPID_SESSION_CONTINUE);
- if (direction == APP_ID_FROM_INITIATOR)
- {
- ip = p->ptrs.ip_api.get_dst();
- asd.service_ip = *ip;
- asd.service_port = p->ptrs.dp;
- }
- else
- {
- ip = p->ptrs.ip_api.get_src();
- asd.service_ip = *ip;
- asd.service_port = p->ptrs.sp;
- }
- }
- }
- else if (asd.get_session_flags(APPID_SESSION_SSL_SESSION) && asd.tsession)
- {
- asd.examine_ssl_metadata(p);
- uint16_t serverPort;
- AppId porAppId;
- serverPort = (direction == APP_ID_FROM_INITIATOR) ? p->ptrs.dp : p->ptrs.sp;
- porAppId = serverPort;
- if (asd.tp_app_id == APP_ID_SSL)
- {
- asd.tp_app_id = porAppId;
- //SSL policy determines IMAPS/POP3S etc before appId sees first server
- // packet
- asd.service.set_port_service_id(porAppId);
- if (appidDebug->is_active())
- LogMessage("AppIdDbg %s SSL is service %d, portServiceAppId %d\n",
- appidDebug->get_debug_session(),
- asd.tp_app_id, asd.service.get_port_service_id());
- }
- else
- {
- asd.tp_payload_app_id = asd.tp_app_id;
- asd.tp_app_id = porAppId;
- if (appidDebug->is_active())
- LogMessage("AppIdDbg %s SSL is %d\n", appidDebug->get_debug_session(),
- asd.tp_app_id);
- }
- snort_app_id = APP_ID_SSL;
- }
- else
- {
- //for non-http protocols, tp id is treated like serviceId
- snort_app_id = asd.tp_app_id;
- }
-
- asd.sync_with_snort_protocol_id(snort_app_id, p);
- }
- else
- {
- if (protocol != IpProtocol::TCP ||
- (p->packet_flags & (PKT_STREAM_ORDER_OK | PKT_STREAM_ORDER_BAD)))
- {
- if (direction == APP_ID_FROM_INITIATOR)
- {
- asd.init_tpPackets++;
- checkTerminateTpModule(asd, asd.init_tpPackets);
- }
- else
- {
- asd.resp_tpPackets++;
- checkTerminateTpModule(asd, asd.resp_tpPackets);
- }
- }
- }
- }
- }
-
- if ( asd.tp_reinspect_by_initiator && checkThirdPartyReinspect(p, asd) )
- {
- asd.clear_session_flags(APPID_SESSION_APP_REINSPECT);
- if (direction == APP_ID_FROM_RESPONDER)
- asd.tp_reinspect_by_initiator = false; //toggle at OK response
- }
-
- return isTpAppidDiscoveryDone;
-}
-
-#endif
-
+++ /dev/null
-//--------------------------------------------------------------------------
-// Copyright (C) 2014-2018 Cisco and/or its affiliates. All rights reserved.
-// Copyright (C) 2005-2013 Sourcefire, Inc.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation. You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// thirdparty_appid_utils.h author Sourcefire Inc.
-
-#ifndef THIRDPARTY_APPID_UTILS_H
-#define THIRDPARTY_APPID_UTILS_H
-
-#include "thirdparty_appid_api.h"
-
-#include "main/thread.h"
-#include "flow/flow.h"
-#include "protocols/protocol_ids.h"
-#include "sfip/sf_ip.h"
-
-class AppIdModuleConfig;
-class AppIdSession;
-struct ThirdPartyAppIDModule;
-struct ThirdPartyAppIDAttributeData;
-namespace snort
-{
-struct Packet;
-}
-
-extern THREAD_LOCAL ThirdPartyAppIDModule* thirdparty_appid_module;
-
-void ThirdPartyAppIDInit(const AppIdModuleConfig*);
-void ThirdPartyAppIDReconfigure();
-void ThirdPartyAppIDFini();
-bool do_third_party_discovery(AppIdSession&, IpProtocol, const snort::SfIp*, snort::Packet*, int&);
-
-inline bool is_third_party_appid_done(void* tp_session)
-{
- if (thirdparty_appid_module)
- {
- unsigned state;
-
- if (tp_session)
- state = thirdparty_appid_module->session_state_get(tp_session);
- else
- state = TP_STATE_INIT;
-
- return (state == TP_STATE_CLASSIFIED || state == TP_STATE_TERMINATED
- || state == TP_STATE_HA);
- }
-
- return true;
-}
-
-inline bool is_third_party_appid_available(void* tp_session)
-{
- if (thirdparty_appid_module)
- {
- unsigned state;
-
- if (tp_session)
- state = thirdparty_appid_module->session_state_get(tp_session);
- else
- state = TP_STATE_INIT;
-
- return (state == TP_STATE_CLASSIFIED || state == TP_STATE_TERMINATED
- || state == TP_STATE_MONITORING);
- }
-
- return false;
-}
-
-#endif
-
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2018-2018 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.
+//--------------------------------------------------------------------------
+
+// tp_appid_module_api.h author Silviu Minut <sminut@cisco.com>
+
+#ifndef TP_APPID_MODULE_API_H
+#define TP_APPID_MODULE_API_H
+
+#include <vector>
+#include <string>
+#include "tp_appid_types.h"
+
+#define THIRD_PARTY_APP_ID_API_VERSION 1
+
+class ThirdPartyConfig
+{
+public:
+ unsigned chp_body_collection_max;
+ unsigned ftp_userid_disabled : 1;
+ unsigned chp_body_collection_disabled : 1;
+ unsigned tp_allow_probes : 1;
+ unsigned http_upgrade_reporting_enabled : 1;
+ unsigned http_response_version_enabled : 1;
+ std::string tp_appid_config;
+ std::vector<std::string> xff_fields;
+ std::vector<std::string> old_xff_fields;
+
+ ThirdPartyConfig()
+ {
+ getXffFields();
+ }
+
+ void getXffFields()
+ {
+ xff_fields.clear();
+ xff_fields.push_back(HTTP_XFF_FIELD_X_FORWARDED_FOR);
+ xff_fields.push_back(HTTP_XFF_FIELD_TRUE_CLIENT_IP);
+ }
+};
+
+class ThirdPartyAppIDModule
+{
+public:
+
+ /* ThirdPartyAppIdConfig tpac; */
+
+ ThirdPartyAppIDModule(uint32_t ver, const char* mname)
+ : version(ver), name(mname) { }
+
+ virtual ~ThirdPartyAppIDModule() { }
+
+ uint32_t api_version() const { return version; }
+ const std::string& module_name() const { return name; }
+
+ virtual int pinit(ThirdPartyConfig&) = 0;
+ virtual int pfini() = 0;
+
+ virtual int tinit() = 0;
+ virtual int tfini() = 0;
+
+ virtual int reconfigure(const ThirdPartyConfig&) = 0;
+ virtual int print_stats() = 0;
+ virtual int reset_stats() = 0;
+
+private:
+
+ // No implicit constructor as derived classes need to provide
+ // version and name.
+ ThirdPartyAppIDModule() : version(0), name("") { }
+
+ const uint32_t version;
+ const std::string name;
+};
+
+// Function pointer to object factory that returns a pointer to a newly
+// created object of a derived class.
+// This needs to be exported (SO_PUBLIC) by any third party .so library.
+// Must return NULL if it fails to create the object.
+typedef ThirdPartyAppIDModule* (* CreateThirdPartyAppIDModule_t)();
+
+#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2018-2018 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.
+//--------------------------------------------------------------------------
+
+// tp_appid_session_api.h author Silviu Minut <sminut@cisco.com>
+
+#ifndef TP_APPID_SESSION_API_H
+#define TP_APPID_SESSION_API_H
+
+#include <vector>
+#include <string>
+#include "appid_types.h"
+#include "application_ids.h"
+#include "tp_appid_types.h"
+
+namespace snort
+{
+struct Packet;
+}
+
+#define THIRD_PARTY_APP_ID_API_VERSION 1
+
+class ThirdPartyAppIDSession
+{
+public:
+
+ ThirdPartyAppIDSession()
+ : appid(APP_ID_NONE), confidence(100), state(TP_STATE_INIT) { }
+ virtual ~ThirdPartyAppIDSession() { }
+
+ virtual bool reset() = 0; // just reset state
+ virtual bool process(const snort::Packet&,
+ AppidSessionDirection direction,
+ std::vector<AppId>& proto_list,
+ ThirdPartyAppIDAttributeData& attribute_data) = 0;
+
+ virtual int disable_flags(uint32_t session_flags) = 0;
+ virtual TPState get_state() { return state; }
+ virtual void set_state(TPState) = 0;
+ virtual void clear_attr(TPSessionAttr) = 0;
+ virtual void set_attr(TPSessionAttr) = 0;
+ virtual unsigned get_attr(TPSessionAttr) = 0;
+ virtual AppId get_appid(int& conf) { conf=confidence; return appid; }
+
+protected:
+ AppId appid;
+ int confidence;
+ TPState state;
+};
+
+// Function pointer to object factory that returns a pointer to a newly
+// created object of a derived class.
+// This needs to be exported (SO_PUBLIC) by any third party .so library.
+// Must return NULL if it fails to create the object.
+typedef ThirdPartyAppIDSession* (* CreateThirdPartyAppIDSession_t)();
+
+#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2014-2018 Cisco and/or its affiliates. All rights reserved.
+// Copyright (C) 2005-2013 Sourcefire, Inc.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tp_appid_types.h author Sourcefire Inc.
+
+#ifndef TP_APPID_TYPES_H
+#define TP_APPID_TYPES_H
+
+#include <cstdint>
+#include <string>
+
+#include "http_xff_fields.h"
+
+using std::string;
+
+// FIXIT-L: these need to disappear from here and go to appid_navl.
+enum TPFlags
+{
+ TP_SESSION_FLAG_DPI = 0x00000001,
+ TP_SESSION_FLAG_MUTABLE = 0x00000002,
+ TP_SESSION_FLAG_FUTUREFLOW = 0x00000004,
+ TP_SESSION_FLAG_ATTRIBUTE = 0x00000008,
+ TP_SESSION_FLAG_TUNNELING = 0x00000010
+};
+
+enum TPState
+{
+ TP_STATE_INIT,
+ TP_STATE_TERMINATED,
+ TP_STATE_INSPECTING,
+ TP_STATE_MONITORING,
+ TP_STATE_CLASSIFIED,
+ TP_STATE_HA = 21
+};
+
+enum TPSessionAttr
+{
+ TP_ATTR_CONTINUE_MONITORING = (1 << 0),
+ TP_ATTR_COPY_RESPONSE_CONTENT = (1 << 1),
+ TP_ATTR_COPY_RESPONSE_LOCATION = (1 << 2),
+ TP_ATTR_COPY_RESPONSE_BODY = (1 << 3),
+};
+
+#define TPAD_GET(func) \
+ const string* func(bool caller_owns_it = 0) \
+ { \
+ const string* tmp = func ## _buf; \
+ if (caller_owns_it) \
+ func ## _buf = nullptr; \
+ return tmp; \
+ }
+
+#define TPAD_SET_OFFSET(func) \
+ void set_ ## func(const char* buf, size_t len, uint16_t offset, uint16_t endOffset) \
+ { \
+ if (func ## _buf) \
+ delete func ## _buf; \
+ func ## _buf=new string(buf,len); \
+ func ## _offset=offset; \
+ func ## _end_offset=endOffset; \
+ }
+
+#define TPAD_SET(func) \
+ void set_ ## func(const char* buf, size_t len) \
+ { \
+ if (func ## _buf) \
+ delete func ## _buf; \
+ func ## _buf=new string(buf,len); \
+ }
+
+// The ThirdPartyAppIDAttributeData class acts as a per packet cache for
+// various fields coming out of that packet, that need to be analyzed
+// simultaneously.
+//
+// Consumers of these fields should grab the pointers and avoid an extra copy,
+// if speed is of the essence. Once they grab a string* pointer from
+// ThirdPartyAppIDAttributeData, then they own it. That is, the consumers
+// are responsible for deleting the pointers they grabbed.
+//
+// If you get it, you own it.
+//
+// However, currently tp_appid_utils.cc retrieves these, but the
+// AppIdHttpSession::set() functions make copies anyway.
+// Therefore, for now there is no need for any caller to own these
+// pointers yet. We therefore allow callers to just peek at the string*
+// buffers inside this class, without owning them. Hence the "caller_owns_it"
+// flag in the get functions below.
+//
+class ThirdPartyAppIDAttributeData
+{
+ string* spdy_request_path_buf = nullptr;
+ string* spdy_request_scheme_buf = nullptr;
+ string* spdy_request_host_buf = nullptr;
+ string* http_request_url_buf = nullptr;
+ string* http_request_uri_buf = nullptr;
+ string* http_request_host_buf = nullptr;
+ string* http_request_cookie_buf = nullptr;
+ string* http_request_via_buf = nullptr;
+ string* http_response_via_buf = nullptr;
+ string* http_response_upgrade_buf = nullptr;
+ string* http_request_user_agent_buf = nullptr;
+ string* http_response_version_buf = nullptr;
+ string* http_response_code_buf = nullptr;
+ string* http_response_content_buf = nullptr;
+ string* http_response_location_buf = nullptr;
+ string* http_response_body_buf = nullptr;
+ string* http_request_body_buf = nullptr;
+ string* http_response_server_buf = nullptr;
+ string* http_request_x_working_with_buf = nullptr;
+ string* tls_host_buf = nullptr;
+ string* tls_cname_buf = nullptr;
+ string* tls_org_unit_buf = nullptr;
+ string* http_request_referer_buf = nullptr;
+ string* ftp_command_user_buf = nullptr;
+
+ uint16_t http_request_uri_offset = 0;
+ uint16_t http_request_uri_end_offset = 0;
+
+ uint16_t http_request_cookie_offset = 0;
+ uint16_t http_request_cookie_end_offset = 0;
+
+ uint16_t http_request_user_agent_offset = 0;
+ uint16_t http_request_user_agent_end_offset = 0;
+
+ uint16_t http_request_host_offset = 0;
+ uint16_t http_request_host_end_offset = 0;
+
+ uint16_t http_request_referer_offset = 0;
+ uint16_t http_request_referer_end_offset = 0;
+
+ uint16_t spdy_request_host_offset = 0;
+ uint16_t spdy_request_host_end_offset = 0;
+
+ uint16_t spdy_request_path_offset = 0;
+ uint16_t spdy_request_path_end_offset = 0;
+
+ // FIXIT-L: make these private too. Figure out how these get set in tp.
+
+public:
+ XffFieldValue xffFieldValue[HTTP_MAX_XFF_FIELDS];
+ uint8_t numXffFields = 0;
+
+ ThirdPartyAppIDAttributeData() { }
+
+ ~ThirdPartyAppIDAttributeData()
+ {
+ // Only delete the pointers that we own (i.e. non null pointers).
+ if (spdy_request_path_buf) delete spdy_request_path_buf;
+ if (spdy_request_scheme_buf) delete spdy_request_scheme_buf;
+ if (spdy_request_host_buf) delete spdy_request_host_buf;
+ if (http_request_url_buf) delete http_request_url_buf;
+ if (http_request_uri_buf) delete http_request_uri_buf;
+ if (http_request_host_buf) delete http_request_host_buf;
+ if (http_request_cookie_buf) delete http_request_cookie_buf;
+ if (http_request_via_buf) delete http_request_via_buf;
+ if (http_response_via_buf) delete http_response_via_buf;
+ if (http_response_upgrade_buf) delete http_response_upgrade_buf;
+ if (http_request_user_agent_buf) delete http_request_user_agent_buf;
+ if (http_response_version_buf) delete http_response_version_buf;
+ if (http_response_code_buf) delete http_response_code_buf;
+ if (http_response_content_buf) delete http_response_content_buf;
+ if (http_response_location_buf) delete http_response_location_buf;
+ if (http_response_body_buf) delete http_response_body_buf;
+ if (http_request_body_buf) delete http_request_body_buf;
+ if (http_response_server_buf) delete http_response_server_buf;
+ if (http_request_x_working_with_buf) delete http_request_x_working_with_buf;
+ if (tls_host_buf) delete tls_host_buf;
+ if (tls_cname_buf) delete tls_cname_buf;
+ if (tls_org_unit_buf) delete tls_org_unit_buf;
+ if (http_request_referer_buf) delete http_request_referer_buf;
+ if (ftp_command_user_buf) delete ftp_command_user_buf;
+ }
+
+ // Note: calling these 2 times in a row, the 2nd time it returns null.
+ TPAD_GET(spdy_request_path)
+ TPAD_GET(spdy_request_scheme)
+ TPAD_GET(spdy_request_host)
+ TPAD_GET(http_request_url)
+ TPAD_GET(http_request_uri)
+ TPAD_GET(http_request_host)
+ TPAD_GET(http_request_cookie)
+ TPAD_GET(http_request_via)
+ TPAD_GET(http_response_via)
+ TPAD_GET(http_response_upgrade)
+ TPAD_GET(http_request_user_agent)
+ TPAD_GET(http_response_version)
+ TPAD_GET(http_response_code)
+ TPAD_GET(http_response_content)
+ TPAD_GET(http_response_location)
+ TPAD_GET(http_response_body)
+ TPAD_GET(http_request_body)
+ TPAD_GET(http_response_server)
+ TPAD_GET(http_request_x_working_with)
+ TPAD_GET(tls_host)
+ TPAD_GET(tls_cname)
+ TPAD_GET(tls_org_unit)
+ TPAD_GET(http_request_referer)
+ TPAD_GET(ftp_command_user)
+
+ uint16_t http_request_uri_begin() { return http_request_uri_offset; }
+ uint16_t http_request_uri_end() { return http_request_uri_end_offset; }
+
+ uint16_t http_request_cookie_begin() { return http_request_cookie_offset; }
+ uint16_t http_request_cookie_end() { return http_request_cookie_end_offset; }
+
+ uint16_t http_request_user_agent_begin() { return http_request_user_agent_offset; }
+ uint16_t http_request_user_agent_end() { return http_request_user_agent_end_offset; }
+
+ uint16_t http_request_host_begin() { return http_request_host_offset; }
+ uint16_t http_request_host_end() { return http_request_host_end_offset; }
+
+ uint16_t http_request_referer_begin() { return http_request_referer_offset; }
+ uint16_t http_request_referer_end() { return http_request_referer_end_offset; }
+
+ uint16_t spdy_request_host_begin() { return spdy_request_host_offset; }
+ uint16_t spdy_request_host_end() { return spdy_request_host_end_offset; }
+
+ uint16_t spdy_request_path_begin() { return spdy_request_path_offset; }
+ uint16_t spdy_request_path_end() { return spdy_request_path_end_offset; }
+
+ // set functions
+ TPAD_SET_OFFSET(spdy_request_path)
+ TPAD_SET(spdy_request_scheme)
+ TPAD_SET_OFFSET(spdy_request_host)
+ TPAD_SET(http_request_url)
+ TPAD_SET_OFFSET(http_request_uri)
+ TPAD_SET_OFFSET(http_request_host)
+ TPAD_SET_OFFSET(http_request_cookie)
+ TPAD_SET(http_request_via)
+ TPAD_SET(http_response_via)
+ TPAD_SET(http_response_upgrade)
+ TPAD_SET_OFFSET(http_request_user_agent)
+ TPAD_SET(http_response_version)
+ TPAD_SET(http_response_code)
+ TPAD_SET(http_response_content)
+ TPAD_SET(http_response_location)
+ TPAD_SET(http_response_body)
+ TPAD_SET(http_request_body)
+ TPAD_SET(http_response_server)
+ TPAD_SET(http_request_x_working_with)
+ TPAD_SET(tls_host)
+ TPAD_SET(tls_cname)
+ TPAD_SET(tls_org_unit)
+ TPAD_SET_OFFSET(http_request_referer)
+ TPAD_SET(ftp_command_user)
+};
+
+#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2014-2018 Cisco and/or its affiliates. All rights reserved.
+// Copyright (C) 2005-2013 Sourcefire, Inc.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tp_appid_utils.cc author Sourcefire Inc.
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <iostream>
+#include <dlfcn.h>
+
+#include "log/messages.h"
+#include "profiler/profiler.h"
+#include "protocols/packet.h"
+#include "stream/stream.h"
+
+#include "app_info_table.h"
+#include "appid_config.h"
+#include "appid_debug.h"
+#include "appid_http_session.h"
+#include "appid_inspector.h"
+#include "detector_plugins/http_url_patterns.h"
+#include "service_plugins/service_ssl.h"
+#include "protocols/packet.h"
+#include "main/snort_debug.h"
+#include "log/messages.h"
+#include "profiler/profiler.h"
+#include "stream/stream.h"
+#include "tp_appid_types.h"
+#include "tp_appid_session_api.h"
+#include "tp_lib_handler.h"
+
+using namespace std;
+using namespace snort;
+
+THREAD_LOCAL ProfileStats tpLibPerfStats;
+THREAD_LOCAL ProfileStats tpPerfStats;
+
+bool do_discovery(AppIdSession&, IpProtocol, Packet*, AppidSessionDirection&);
+
+// std::vector does not have a convenient find() function.
+// There is a generic std::find() in <algorithm>, but this might be faster.
+template<class Type_t, class ValType_t>
+static bool contains(const vector<Type_t>& vec, const ValType_t& val)
+{
+ const Type_t* v=&vec[0], * vend=v+vec.size();
+ while (v<vend)
+ if ( *(v++)==(Type_t)val )
+ return true;
+ return false;
+}
+
+// FIXIT-L bogus placeholder for this func, need to find out what it should do
+static inline bool is_appid_done(const ThirdPartyAppIDSession* tpsession)
+{
+ UNUSED(tpsession);
+ return false;
+}
+
+static inline bool check_reinspect(const Packet* p, const AppIdSession& asd)
+{
+ return p->dsize && !asd.get_session_flags(APPID_SESSION_NO_TPI) &&
+ asd.get_session_flags(APPID_SESSION_HTTP_SESSION) && is_appid_done(asd.tpsession);
+}
+
+static inline int check_ssl_appid_for_reinspect(AppId app_id)
+{
+ if (app_id <= SF_APPID_MAX &&
+ (app_id == APP_ID_SSL ||
+ AppInfoManager::get_instance().get_app_info_flags(app_id,
+ APPINFO_FLAG_SSL_INSPECT)))
+ return 1;
+ else
+ return 0;
+}
+
+// FIXIT-M: All the AppIdHttpSession::set/update functions make an
+// internal copy. That needs to change, as that's already the 2nd copy - the
+// first copy happens when third party calls ThirdPartyAppIDAttributeData::set
+// functions and that's unavoidable.
+// Consider passing all the metadata pointers (e.g. host, url, etc.)
+// to AppIdHttpSession directly from the thirdparty.so callbacks.
+//
+// Or, register observers with THirdPartyAppIDAttributeData and modify the
+// set functions to copy the tp buffers directly into the appropriate observer.
+static inline void process_http_session(AppIdSession& asd,
+ ThirdPartyAppIDAttributeData& attribute_data)
+{
+ AppIdHttpSession* hsession = asd.get_http_session();
+ const string* field=0;
+
+ hsession->reset_ptype_scan_counts();
+
+ if (asd.get_session_flags(APPID_SESSION_SPDY_SESSION))
+ {
+ const string* spdyRequestScheme=attribute_data.spdy_request_scheme();
+ const string* spdyRequestHost=attribute_data.spdy_request_host();
+ const string* spdyRequestPath=attribute_data.spdy_request_path();
+
+ if (spdyRequestScheme && spdyRequestHost && spdyRequestPath )
+ {
+ static const char httpsScheme[] = "https";
+ static const char httpScheme[] = "http";
+ std::string url;
+
+ if (asd.get_session_flags(APPID_SESSION_DECRYPTED)
+ &&
+ memcmp(spdyRequestScheme->c_str(), httpScheme,
+ sizeof(httpScheme) - 1) == 0)
+ {
+ url = httpsScheme;
+ }
+ else
+ {
+ url = *spdyRequestScheme;
+ }
+
+ if (hsession->get_url())
+ hsession->set_chp_finished(false);
+
+ url += "://" + *spdyRequestHost + *spdyRequestPath;
+ hsession->set_url(url.c_str());
+ asd.scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
+ }
+
+ if (spdyRequestHost)
+ {
+ if (hsession->get_host())
+ hsession->set_chp_finished(false);
+
+ hsession->update_host((const uint8_t*)spdyRequestHost->c_str(),
+ spdyRequestHost->size());
+ hsession->set_field_offset(REQ_HOST_FID,
+ attribute_data.spdy_request_host_begin());
+ hsession->set_field_end_offset(REQ_HOST_FID,
+ attribute_data.spdy_request_host_end());
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s SPDY host (%u-%u) is %s\n",
+ appidDebug->get_debug_session(),
+ hsession->get_field_offset(REQ_HOST_FID),
+ hsession->get_field_end_offset(REQ_HOST_FID), hsession->get_host());
+ asd.scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
+ }
+
+ if (spdyRequestPath)
+ {
+ if (hsession->get_uri())
+ hsession->set_chp_finished(false);
+
+ hsession->update_uri((const uint8_t*)spdyRequestPath->c_str(),
+ spdyRequestPath->size());
+ hsession->set_field_offset(REQ_URI_FID, attribute_data.spdy_request_path_begin());
+ hsession->set_field_end_offset(REQ_URI_FID, attribute_data.spdy_request_path_end());
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s SPDY URI (%u-%u) is %s\n", appidDebug->get_debug_session(),
+ hsession->get_field_offset(REQ_URI_FID),
+ hsession->get_field_end_offset(REQ_URI_FID), hsession->get_uri());
+ }
+ }
+ else
+ {
+ if ( (field=attribute_data.http_request_host()) != nullptr )
+ {
+ if (hsession->get_host())
+ if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
+ hsession->set_chp_finished(false);
+
+ hsession->update_host((const uint8_t*)field->c_str(),
+ field->size());
+ hsession->set_field_offset(REQ_HOST_FID, attribute_data.http_request_host_begin());
+ hsession->set_field_end_offset(REQ_HOST_FID, attribute_data.http_request_host_end());
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s HTTP host is %s\n",
+ appidDebug->get_debug_session(), field->c_str());
+ asd.scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
+ }
+
+ if ( (field=attribute_data.http_request_url()) != nullptr )
+ {
+ static const char httpScheme[] = "http://";
+
+ if (hsession->get_url() and !asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
+ hsession->set_chp_finished(false);
+
+ // Change http to https if session was decrypted.
+ if (asd.get_session_flags(APPID_SESSION_DECRYPTED) and
+ memcmp(field->c_str(), httpScheme, sizeof(httpScheme)-1)==0)
+ {
+ std::string url("https://");
+ url.append(field->c_str() + sizeof(httpScheme)-1);
+ hsession->set_url(url.c_str());
+ }
+ else
+ hsession->set_url(field->c_str());
+
+ asd.scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
+ }
+
+ if ( (field=attribute_data.http_request_uri()) != nullptr)
+ {
+ if (hsession->get_uri())
+ if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
+ hsession->set_chp_finished(false);
+
+ hsession->update_uri((const uint8_t*)field->c_str(),field->size());
+ hsession->set_field_offset(REQ_URI_FID, attribute_data.http_request_uri_begin());
+ hsession->set_field_end_offset(REQ_URI_FID, attribute_data.http_request_uri_end());
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s uri (%u-%u) is %s\n", appidDebug->get_debug_session(),
+ hsession->get_field_offset(REQ_URI_FID),
+ hsession->get_field_end_offset(REQ_URI_FID), hsession->get_uri());
+ }
+ }
+
+ // FIXIT-M: these cases are duplicate.
+ if ( (field=attribute_data.http_request_via()) != nullptr )
+ {
+ if (hsession->get_via())
+ if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
+ hsession->set_chp_finished(false);
+
+ hsession->update_via((const uint8_t*)field->c_str(),field->size());
+ asd.scan_flags |= SCAN_HTTP_VIA_FLAG;
+ }
+ else if ( (field=attribute_data.http_response_via()) != nullptr )
+ {
+ if (hsession->get_via())
+ if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
+ hsession->set_chp_finished(false);
+
+ hsession->update_via((const uint8_t*)field->c_str(),field->size());
+ asd.scan_flags |= SCAN_HTTP_VIA_FLAG;
+ }
+
+ if ( (field=attribute_data.http_request_user_agent()) != nullptr )
+ {
+ if (hsession->get_user_agent())
+ if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
+ hsession->set_chp_finished(false);
+
+ hsession->update_useragent((const uint8_t*)field->c_str(),field->size());
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s User Agent (%u-%u) is %s\n",
+ appidDebug->get_debug_session(), hsession->get_field_offset(REQ_AGENT_FID),
+ hsession->get_field_end_offset(REQ_AGENT_FID), hsession->get_user_agent());
+ asd.scan_flags |= SCAN_HTTP_USER_AGENT_FLAG;
+ }
+
+ // Check to see if third party discovered HTTP/2. - once it supports it...
+ if ( (field=attribute_data.http_response_version()) != nullptr )
+ {
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s HTTP response version is %s\n",
+ appidDebug->get_debug_session(), field->c_str());
+ if (strncmp(field->c_str(), "HTTP/2", 6) == 0)
+ {
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s 3rd party detected and parsed HTTP/2\n",
+ appidDebug->get_debug_session());
+ asd.is_http2 = true;
+ }
+ }
+
+ if ( (field=attribute_data.http_response_code()) != nullptr )
+ {
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s HTTP response code is %s\n",
+ appidDebug->get_debug_session(), field->c_str());
+ if (hsession->get_response_code())
+ if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
+ hsession->set_chp_finished(false);
+
+ hsession->update_response_code((const char*)field->c_str());
+ }
+
+ // Check to see if we've got an upgrade to HTTP/2 (if enabled).
+ // - This covers the "without prior knowledge" case (i.e., the client
+ // asks the server to upgrade to HTTP/2).
+ if ( (field=attribute_data.http_response_upgrade()) != nullptr )
+ {
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s HTTP response upgrade is %s\n",
+ appidDebug->get_debug_session(),field->c_str());
+
+ if (asd.config->mod_config->http2_detection_enabled)
+ if ( hsession->get_response_code()
+ && (strncmp(hsession->get_response_code(), "101", 3) == 0) )
+ if (strncmp(field->c_str(), "h2c", 3) == 0)
+ {
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s Got an upgrade to HTTP/2\n",
+ appidDebug->get_debug_session());
+ asd.is_http2 = true;
+ }
+ }
+
+ if ( (field=attribute_data.http_request_referer()) != nullptr )
+ {
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s referrer is %s\n",
+ appidDebug->get_debug_session(), field->c_str());
+ if (hsession->get_referer())
+ if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
+ hsession->set_chp_finished(false);
+
+ hsession->update_referer((const uint8_t*)field->c_str(), field->size());
+ hsession->set_field_offset(REQ_REFERER_FID, attribute_data.http_request_referer_begin());
+ hsession->set_field_end_offset(REQ_REFERER_FID, attribute_data.http_request_referer_end());
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s Referer (%u-%u) is %s\n", appidDebug->get_debug_session(),
+ hsession->get_field_offset(REQ_REFERER_FID),
+ hsession->get_field_end_offset(REQ_REFERER_FID),
+ hsession->get_referer());
+ }
+
+ if ( (field=attribute_data.http_request_cookie()) != nullptr )
+ {
+ if (hsession->get_cookie())
+ if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
+ hsession->set_chp_finished(false);
+
+ hsession->update_cookie((const uint8_t*)field->c_str(), field->size());
+ hsession->set_field_offset(REQ_COOKIE_FID, attribute_data.http_request_cookie_begin());
+ hsession->set_field_end_offset(REQ_COOKIE_FID, attribute_data.http_request_cookie_end());
+ // FIXIT-M currently we're not doing this, check if necessary
+ // attribute_data.httpRequestCookie = nullptr;
+ // attribute_data.httpRequestCookieOffset = 0;
+ // attribute_data.httpRequestCookieEndOffset = 0;
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s cookie (%u-%u) is %s\n", appidDebug->get_debug_session(),
+ hsession->get_field_offset(REQ_COOKIE_FID),
+ hsession->get_field_offset(REQ_COOKIE_FID),
+ hsession->get_cookie());
+ }
+
+ if ( (field=attribute_data.http_response_content()) != nullptr )
+ {
+ if (hsession->get_content_type())
+ if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
+ hsession->set_chp_finished(false);
+
+ hsession->update_content_type((const uint8_t*)field->c_str(), field->size());
+ asd.scan_flags |= SCAN_HTTP_CONTENT_TYPE_FLAG;
+ }
+
+ if (hsession->get_ptype_scan_count(RSP_LOCATION_FID) &&
+ (field=attribute_data.http_response_location()) != nullptr)
+ {
+ if (hsession->get_location())
+ if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
+ hsession->set_chp_finished(false);
+
+ hsession->update_location((const uint8_t*)field->c_str(), field->size());
+ }
+
+ if ( (field=attribute_data.http_request_body()) != nullptr )
+ {
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s got a request body %s\n",
+ appidDebug->get_debug_session(), field->c_str());
+ if (hsession->get_req_body())
+ if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
+ hsession->set_chp_finished(false);
+ hsession->update_req_body((const uint8_t*)field->c_str(), field->size());
+ }
+
+ if (hsession->get_ptype_scan_count(RSP_BODY_FID) &&
+ (field=attribute_data.http_response_body()) != nullptr)
+ {
+ if (hsession->get_body())
+ if (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
+ hsession->set_chp_finished(false);
+
+ hsession->update_body((const uint8_t*)field->c_str(), field->size());
+ }
+
+ if (attribute_data.numXffFields)
+ hsession->update_http_xff_address(attribute_data.xffFieldValue,
+ attribute_data.numXffFields);
+
+ if (!hsession->is_chp_finished() || hsession->is_chp_hold_flow())
+ {
+ asd.set_session_flags(APPID_SESSION_CHP_INSPECTING);
+ asd.tpsession->set_attr(TP_ATTR_CONTINUE_MONITORING);
+ }
+
+ if ( (field=attribute_data.http_response_server()) != nullptr)
+ {
+ hsession->update_server((const uint8_t*)field->c_str(), field->size());
+ asd.scan_flags |= SCAN_HTTP_VENDOR_FLAG;
+ }
+
+ if ( (field=attribute_data.http_request_x_working_with()) != nullptr )
+ {
+ hsession->update_x_working_with((const uint8_t*)field->c_str(), field->size());
+ asd.scan_flags |= SCAN_HTTP_XWORKINGWITH_FLAG;
+ }
+}
+
+static inline void process_rtmp(AppIdSession& asd,
+ ThirdPartyAppIDAttributeData& attribute_data, int confidence)
+{
+ AppIdHttpSession* hsession = asd.get_http_session();
+ AppId serviceAppId = 0;
+ AppId client_id = 0;
+ AppId payload_id = 0;
+ AppId referred_payload_app_id = 0;
+
+ const string* field=0;
+
+ if (!hsession->get_url())
+ {
+ if ( (field=attribute_data.http_request_url()) != nullptr )
+ {
+ hsession->set_url(field->c_str());
+ asd.scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
+ }
+ }
+
+ if ( !asd.config->mod_config->referred_appId_disabled && !hsession->get_referer() )
+ {
+ if ( (field=attribute_data.http_request_referer()) != nullptr )
+ {
+ hsession->update_referer((const uint8_t*)field->c_str(), field->size());
+ }
+ }
+
+ if (hsession->get_url() || (confidence == 100 &&
+ asd.session_packet_count > asd.config->mod_config->rtmp_max_packets))
+ {
+ if (hsession->get_url())
+ {
+ HttpPatternMatchers* http_matchers = HttpPatternMatchers::get_instance();
+
+ if ( ( ( http_matchers->get_appid_from_url(nullptr, hsession->get_url(),
+ nullptr, hsession->get_referer(), &client_id, &serviceAppId,
+ &payload_id, &referred_payload_app_id, 1) )
+ ||
+ ( http_matchers->get_appid_from_url(nullptr, hsession->get_url(), nullptr,
+ hsession->get_referer(), &client_id, &serviceAppId, &payload_id,
+ &referred_payload_app_id, 0) ) ) == 1 )
+ {
+ // do not overwrite a previously-set client or service
+ if (client_id <= APP_ID_NONE)
+ asd.set_client_appid_data(client_id, nullptr);
+ if (serviceAppId <= APP_ID_NONE)
+ asd.set_service_appid_data(serviceAppId, nullptr, nullptr);
+
+ // DO overwrite a previously-set data
+ asd.set_payload_appid_data(payload_id, nullptr);
+ asd.set_referred_payload_app_id_data(referred_payload_app_id);
+ }
+ }
+
+ asd.tpsession->disable_flags(
+ TP_SESSION_FLAG_ATTRIBUTE | TP_SESSION_FLAG_TUNNELING |
+ TP_SESSION_FLAG_FUTUREFLOW);
+ asd.tpsession->reset();
+ asd.clear_session_flags(APPID_SESSION_APP_REINSPECT);
+ }
+}
+
+static inline void process_ssl(AppIdSession& asd,
+ ThirdPartyAppIDAttributeData& attribute_data)
+{
+ AppId tmpAppId = APP_ID_NONE;
+ int tmpConfidence = 0;
+ const string* field=0;
+
+ // if (tp_appid_module && asd.tpsession)
+ tmpAppId = asd.tpsession->get_appid(tmpConfidence);
+
+ asd.set_session_flags(APPID_SESSION_SSL_SESSION);
+
+ if (!asd.tsession)
+ asd.tsession = (TlsSession*)snort_calloc(sizeof(TlsSession));
+
+ if (!asd.client.get_id())
+ asd.set_client_appid_data(APP_ID_SSL_CLIENT, nullptr);
+
+ if ( (field=attribute_data.tls_host()) != nullptr )
+ {
+ if (asd.tsession->tls_host)
+ snort_free(asd.tsession->tls_host);
+ asd.tsession->tls_host = snort_strdup(field->c_str());
+ if (check_ssl_appid_for_reinspect(tmpAppId))
+ asd.scan_flags |= SCAN_SSL_HOST_FLAG;
+ }
+
+ if (check_ssl_appid_for_reinspect(tmpAppId))
+ {
+ if ( (field=attribute_data.tls_cname()) != nullptr )
+ {
+ if (asd.tsession->tls_cname)
+ snort_free(asd.tsession->tls_cname);
+ asd.tsession->tls_cname = snort_strdup(field->c_str());
+ }
+
+ if ( (field=attribute_data.tls_org_unit()) != nullptr )
+ {
+ if (asd.tsession->tls_orgUnit)
+ snort_free(asd.tsession->tls_orgUnit);
+ asd.tsession->tls_orgUnit = snort_strdup(field->c_str());
+ }
+ }
+}
+
+static inline void process_ftp_control(AppIdSession& asd,
+ ThirdPartyAppIDAttributeData& attribute_data)
+{
+ const string* field=0;
+ if (!asd.config->mod_config->ftp_userid_disabled &&
+ (field=attribute_data.ftp_command_user()) != nullptr)
+ {
+ asd.client.update_user(APP_ID_FTP_CONTROL, field->c_str());
+ asd.set_session_flags(APPID_SESSION_LOGIN_SUCCEEDED);
+ // attribute_data.ftpCommandUser = nullptr;
+ }
+}
+
+static inline void process_third_party_results(AppIdSession& asd, int confidence,
+ vector<AppId>& proto_list, ThirdPartyAppIDAttributeData& attribute_data)
+{
+ if ( asd.payload.get_id() == APP_ID_NONE and contains(proto_list, APP_ID_EXCHANGE) )
+ asd.payload.set_id(APP_ID_EXCHANGE);
+
+ if ( contains(proto_list, APP_ID_HTTP) )
+ {
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s flow is HTTP\n", appidDebug->get_debug_session());
+ asd.set_session_flags(APPID_SESSION_HTTP_SESSION);
+ }
+
+ if ( contains(proto_list, APP_ID_SPDY) )
+ {
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s flow is SPDY\n", appidDebug->get_debug_session());
+
+ asd.set_session_flags(APPID_SESSION_HTTP_SESSION | APPID_SESSION_SPDY_SESSION);
+ }
+
+ if (asd.get_session_flags(APPID_SESSION_HTTP_SESSION))
+ process_http_session(asd, attribute_data);
+
+ else if (contains(proto_list, APP_ID_RTMP) ||
+ contains(proto_list, APP_ID_RTSP) )
+ process_rtmp(asd, attribute_data, confidence);
+
+ else if (contains(proto_list, APP_ID_SSL))
+ process_ssl(asd, attribute_data);
+
+ else if (contains(proto_list, APP_ID_FTP_CONTROL))
+ process_ftp_control(asd, attribute_data);
+}
+
+static inline void check_terminate_tp_module(AppIdSession& asd, uint16_t tpPktCount)
+{
+ AppIdHttpSession* hsession = asd.get_http_session();
+
+ if ((tpPktCount >= asd.config->mod_config->max_tp_flow_depth) ||
+ (asd.get_session_flags(APPID_SESSION_HTTP_SESSION | APPID_SESSION_APP_REINSPECT) ==
+ (APPID_SESSION_HTTP_SESSION | APPID_SESSION_APP_REINSPECT) &&
+ hsession->get_uri() && (!hsession->get_chp_candidate() || hsession->is_chp_finished())))
+ {
+ if (asd.tp_app_id == APP_ID_NONE)
+ asd.tp_app_id = APP_ID_UNKNOWN;
+ if (asd.payload.get_id() == APP_ID_NONE)
+ asd.payload.set_id(APP_ID_UNKNOWN);
+
+ if (asd.tpsession)
+ asd.tpsession->reset();
+ }
+}
+
+bool do_discovery(AppIdSession& asd, IpProtocol protocol,
+ Packet* p, AppidSessionDirection& direction)
+{
+ ThirdPartyAppIDAttributeData tp_attribute_data;
+ vector<AppId> tp_proto_list;
+ bool isTpAppidDiscoveryDone = false;
+
+ if ( !asd.config->have_tp() )
+ return true;
+
+ //restart inspection by 3rd party
+ if (!asd.tp_reinspect_by_initiator && (direction == APP_ID_FROM_INITIATOR) &&
+ check_reinspect(p, asd))
+ {
+ asd.tp_reinspect_by_initiator = true;
+ asd.set_session_flags(APPID_SESSION_APP_REINSPECT);
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s 3rd party allow reinspect http\n",
+ appidDebug->get_debug_session());
+ asd.reset_session_data();
+ }
+
+ if (asd.tp_app_id == APP_ID_SSH && asd.payload.get_id() != APP_ID_SFTP &&
+ asd.session_packet_count >= MIN_SFTP_PACKET_COUNT &&
+ asd.session_packet_count < MAX_SFTP_PACKET_COUNT)
+ {
+ if ( p->ptrs.ip_api.tos() == 8 )
+ {
+ asd.payload.set_id(APP_ID_SFTP);
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s Payload is SFTP\n", appidDebug->get_debug_session());
+ }
+ }
+
+ Profile tpPerfStats_profile_context(tpPerfStats);
+
+ /*** Start of third-party processing. ***/
+ if ( asd.config->have_tp()
+ && !asd.get_session_flags(APPID_SESSION_NO_TPI)
+ && (!is_appid_done(asd.tpsession)
+ || asd.get_session_flags(APPID_SESSION_APP_REINSPECT
+ | APPID_SESSION_APP_REINSPECT_SSL)))
+ {
+ // First SSL decrypted packet is now being inspected. Reset the flag so that SSL decrypted
+ // traffic gets processed like regular traffic from next packet onwards
+ if (asd.get_session_flags(APPID_SESSION_APP_REINSPECT_SSL))
+ asd.clear_session_flags(APPID_SESSION_APP_REINSPECT_SSL);
+
+ if (p->dsize || asd.config->mod_config->tp_allow_probes)
+ {
+ if (protocol != IpProtocol::TCP || (p->packet_flags & PKT_STREAM_ORDER_OK)
+ || asd.config->mod_config->tp_allow_probes)
+ {
+ Profile tpLibPerfStats_profile_context(tpLibPerfStats);
+ int tp_confidence;
+ if (!asd.tpsession)
+ {
+ const TPLibHandler* tph = asd.config->tp_handler();
+ CreateThirdPartyAppIDSession_t tpsf = tph->tpsession_factory();
+ if ( !(asd.tpsession = tpsf()) )
+ FatalError("Could not allocate asd.tpsession data");
+ } // debug output of packet content
+
+ asd.tpsession->process(*p, direction,
+ tp_proto_list, tp_attribute_data);
+ asd.tp_app_id=asd.tpsession->get_appid(tp_confidence);
+
+ isTpAppidDiscoveryDone = true;
+ if (asd.tpsession->get_state() == TP_STATE_CLASSIFIED)
+ asd.clear_session_flags(APPID_SESSION_APP_REINSPECT);
+
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s 3rd party returned %d\n",
+ appidDebug->get_debug_session(),
+ asd.tp_app_id);
+
+ // For now, third party can detect HTTP/2 (w/o metadata) for
+ // some cases. Treat it like HTTP w/ is_http2 flag set.
+ if ((asd.tp_app_id == APP_ID_HTTP2) && (tp_confidence == 100))
+ {
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s 3rd party saw HTTP/2\n",
+ appidDebug->get_debug_session());
+
+ asd.tp_app_id = APP_ID_HTTP;
+ asd.is_http2 = true;
+ }
+ // if the third-party appId must be treated as a client, do it now
+ if (asd.app_info_mgr->get_app_info_flags(asd.tp_app_id, APPINFO_FLAG_TP_CLIENT))
+ asd.client.set_id(asd.tp_app_id);
+
+ process_third_party_results(asd, tp_confidence, tp_proto_list, tp_attribute_data);
+
+ if (asd.get_session_flags(APPID_SESSION_SSL_SESSION) &&
+ !(asd.scan_flags & SCAN_SSL_HOST_FLAG))
+ {
+ setSSLSquelch(p, 1, asd.tp_app_id, asd.get_inspector());
+ }
+
+ if (asd.app_info_mgr->get_app_info_flags(asd.tp_app_id, APPINFO_FLAG_IGNORE))
+ {
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s 3rd party ignored\n",
+ appidDebug->get_debug_session());
+
+ if (asd.get_session_flags(APPID_SESSION_HTTP_SESSION))
+ asd.tp_app_id = APP_ID_HTTP;
+ else
+ asd.tp_app_id = APP_ID_NONE;
+ }
+ }
+ else
+ {
+ asd.tp_app_id = APP_ID_NONE;
+ if (appidDebug->is_active() && !asd.get_session_flags(
+ APPID_SESSION_TPI_OOO_LOGGED))
+ {
+ asd.set_session_flags(APPID_SESSION_TPI_OOO_LOGGED);
+ LogMessage("AppIdDbg %s 3rd party packet out-of-order\n",
+ appidDebug->get_debug_session());
+ }
+ }
+
+ if (asd.tpsession and asd.tpsession->get_state() == TP_STATE_MONITORING)
+ {
+ asd.tpsession->disable_flags(TP_SESSION_FLAG_ATTRIBUTE |
+ TP_SESSION_FLAG_TUNNELING | TP_SESSION_FLAG_FUTUREFLOW);
+ }
+
+ if (asd.tp_app_id == APP_ID_SSL &&
+ (Stream::get_snort_protocol_id(p->flow) == snortId_for_ftp_data))
+ {
+ // If we see SSL on an FTP data channel set tpAppId back
+ // to APP_ID_NONE so the FTP preprocessor picks up the flow.
+ asd.tp_app_id = APP_ID_NONE;
+ }
+
+ if ( asd.tp_app_id > APP_ID_NONE
+ && (!asd.get_session_flags(APPID_SESSION_APP_REINSPECT)
+ || asd.payload.get_id() > APP_ID_NONE) )
+ {
+ AppId snort_app_id;
+ AppIdHttpSession* hsession = asd.get_http_session();
+
+ // if the packet is HTTP, then search for via pattern
+ if ( asd.get_session_flags(APPID_SESSION_HTTP_SESSION) )
+ {
+ snort_app_id = APP_ID_HTTP;
+ //data should never be APP_ID_HTTP
+ if (asd.tp_app_id != APP_ID_HTTP)
+ asd.tp_payload_app_id = asd.tp_app_id;
+
+ asd.tp_app_id = APP_ID_HTTP;
+ // Handle HTTP tunneling and SSL possibly then being used in that tunnel
+ if (asd.tp_app_id == APP_ID_HTTP_TUNNEL)
+ asd.set_payload_appid_data(APP_ID_HTTP_TUNNEL, NULL);
+ if ((asd.payload.get_id() == APP_ID_HTTP_TUNNEL) && (asd.tp_app_id ==
+ APP_ID_SSL))
+ asd.set_payload_appid_data(APP_ID_HTTP_SSL_TUNNEL, NULL);
+
+ hsession->process_http_packet(direction);
+
+ // If SSL over HTTP tunnel, make sure Snort knows that it's encrypted.
+ if (asd.payload.get_id() == APP_ID_HTTP_SSL_TUNNEL)
+ snort_app_id = APP_ID_SSL;
+
+ if (asd.is_third_party_appid_available() && asd.tp_app_id ==
+ APP_ID_HTTP
+ && !asd.get_session_flags(APPID_SESSION_APP_REINSPECT))
+ {
+ asd.client_disco_state = APPID_DISCO_STATE_FINISHED;
+ asd.set_session_flags(APPID_SESSION_CLIENT_DETECTED |
+ APPID_SESSION_SERVICE_DETECTED);
+ asd.client_disco_state = APPID_DISCO_STATE_FINISHED;
+ asd.clear_session_flags(APPID_SESSION_CONTINUE);
+ if (direction == APP_ID_FROM_INITIATOR)
+ {
+ asd.service_ip = *p->ptrs.ip_api.get_dst();
+ asd.service_port = p->ptrs.dp;
+ }
+ else
+ {
+ asd.service_ip = *p->ptrs.ip_api.get_src();
+ asd.service_port = p->ptrs.sp;
+ }
+ }
+ }
+ else if (asd.get_session_flags(APPID_SESSION_SSL_SESSION) && asd.tsession)
+ {
+ asd.examine_ssl_metadata(p);
+ uint16_t serverPort;
+ AppId porAppId;
+ serverPort = (direction == APP_ID_FROM_INITIATOR) ? p->ptrs.dp : p->ptrs.sp;
+ porAppId = serverPort;
+ if (asd.tp_app_id == APP_ID_SSL)
+ {
+ asd.tp_app_id = porAppId;
+ //SSL policy determines IMAPS/POP3S etc before appId sees first server
+ // packet
+ asd.service.set_port_service_id(porAppId);
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s SSL is service %d, portServiceAppId %d\n",
+ appidDebug->get_debug_session(),
+ asd.tp_app_id, asd.service.get_port_service_id());
+ }
+ else
+ {
+ asd.tp_payload_app_id = asd.tp_app_id;
+ asd.tp_app_id = porAppId;
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s SSL is %d\n", appidDebug->get_debug_session(),
+ asd.tp_app_id);
+ }
+ snort_app_id = APP_ID_SSL;
+ }
+ else
+ {
+ //for non-http protocols, tp id is treated like serviceId
+ snort_app_id = asd.tp_app_id;
+ }
+
+ asd.sync_with_snort_protocol_id(snort_app_id, p);
+ }
+ else
+ {
+ if (protocol != IpProtocol::TCP ||
+ (p->packet_flags & (PKT_STREAM_ORDER_OK | PKT_STREAM_ORDER_BAD)))
+ {
+ if (direction == APP_ID_FROM_INITIATOR)
+ {
+ asd.init_tpPackets++;
+ check_terminate_tp_module(asd, asd.init_tpPackets);
+ }
+ else
+ {
+ asd.resp_tpPackets++;
+ check_terminate_tp_module(asd, asd.resp_tpPackets);
+ }
+ }
+ }
+ }
+ }
+
+ if ( asd.tp_reinspect_by_initiator && check_reinspect(p, asd) )
+ {
+ asd.clear_session_flags(APPID_SESSION_APP_REINSPECT);
+ if (direction == APP_ID_FROM_RESPONDER)
+ asd.tp_reinspect_by_initiator = false; //toggle at OK response
+ }
+
+ return isTpAppidDiscoveryDone;
+}
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2018-2018 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.
+//--------------------------------------------------------------------------
+
+// tp_lib_handler.cc author Silviu Minut <sminut@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <dlfcn.h>
+
+#include "appid_config.h"
+
+#include "main/snort_debug.h"
+#include "log/messages.h"
+
+#include "tp_lib_handler.h"
+
+using namespace std;
+using namespace snort;
+
+#define TP_APPID_MODULE_SYMBOL "create_third_party_appid_module"
+#define TP_APPID_SESSION_SYMBOL "create_third_party_appid_session"
+
+TPLibHandler* TPLibHandler::handler = nullptr;
+
+int TPLibHandler::LoadCallback(const char* const path, int /* indent */)
+{
+ void* handle = 0;
+ ThirdPartyAppIDModule* tp_module = 0;
+ const char* error = nullptr;
+
+ if (tp_appid_module != nullptr)
+ {
+ ErrorMessage("Ignoring additional 3rd party AppID module (%s)!\n", path);
+ return 0;
+ }
+
+ // Load the tp library and get function pointers to the module and
+ // session object factories.
+ dlerror();
+ handle = dlopen(path, RTLD_NOW | RTLD_LOCAL);
+ if (handle == nullptr)
+ {
+ ErrorMessage("Failed to load 3rd party AppID library: %s - %s\n", path, dlerror());
+ return 0;
+ }
+
+ CreateThirdPartyAppIDModule_t createThirdPartyAppIDModule=
+ (CreateThirdPartyAppIDModule_t)dlsym(handle, TP_APPID_MODULE_SYMBOL);
+ if ((error=dlerror()) != nullptr)
+ {
+ ErrorMessage(
+ "Failed to get 3rd party AppID module object factory: %s - %s\n",
+ TP_APPID_MODULE_SYMBOL, error);
+ dlclose(handle);
+ return 0;
+ }
+
+ createThirdPartyAppIDSession=(CreateThirdPartyAppIDSession_t)dlsym(
+ handle,TP_APPID_SESSION_SYMBOL);
+ if ((error=dlerror()) != nullptr)
+ {
+ ErrorMessage(
+ "Failed to get 3rd party AppID session object factory: %s - %s\n",
+ TP_APPID_SESSION_SYMBOL, error);
+ dlclose(handle);
+ return 0;
+ }
+
+ // The tp module object is a singleton and gets created here in main thread.
+ // TP session objects get created per worker thread.
+ tp_module=createThirdPartyAppIDModule();
+ if (tp_module == nullptr)
+ {
+ ErrorMessage("Failed to create third party appId module.\n");
+ dlclose(handle);
+ return 0;
+ }
+
+ if ( (tp_module->api_version() != THIRD_PARTY_APP_ID_API_VERSION)
+ || (tp_module->module_name().empty()) )
+ {
+ ErrorMessage("Ignoring incomplete 3rd party AppID module (%s, %d, %s)!\n",
+ path, tp_module->api_version(),
+ tp_module->module_name().empty() ? "empty" : tp_module->module_name().c_str());
+
+ dlclose(handle);
+ delete tp_module;
+ return 0;
+ }
+
+ this->tp_so_handle = handle;
+ tp_appid_module = tp_module;
+ return 0;
+}
+
+void TPLibHandler::pinit(const AppIdModuleConfig* config)
+{
+ int ret;
+
+ if (config->tp_appid_path.empty())
+ return;
+
+ tp_config.tp_appid_config=config->tp_appid_config;
+
+ LoadCallback(config->tp_appid_path.c_str(),1);
+
+ if (tp_appid_module == nullptr)
+ {
+ // FIXIT-H error message
+ return;
+ }
+
+ tp_config.chp_body_collection_max = config->chp_body_collection_max;
+ tp_config.ftp_userid_disabled = config->ftp_userid_disabled;
+ tp_config.chp_body_collection_disabled =
+ config->chp_body_collection_disabled;
+ tp_config.tp_allow_probes = config->tp_allow_probes;
+ if (config->http2_detection_enabled)
+ tp_config.http_upgrade_reporting_enabled = 1;
+ else
+ tp_config.http_upgrade_reporting_enabled = 0;
+ // FIXIT-H: Init http_response_version_enabled
+
+ ret = tp_appid_module->pinit(tp_config);
+ if (ret != 0)
+ {
+ ErrorMessage("Unable to initialize 3rd party AppID module (%d)!\n", ret);
+ delete tp_appid_module;
+ dlclose(tp_so_handle);
+ tp_so_handle = nullptr;
+ tp_appid_module = nullptr;
+ return;
+ }
+}
+
+void TPLibHandler::pfini(bool print_stats_flag)
+{
+ if (tp_appid_module != nullptr)
+ {
+ if (print_stats_flag)
+ tp_appid_module->print_stats();
+
+ int ret = tp_appid_module->pfini();
+
+ if (ret != 0)
+ ErrorMessage("Could not finalize 3rd party AppID module (%d)!\n", ret);
+
+ delete tp_appid_module;
+ tp_appid_module = nullptr;
+ dlclose(tp_so_handle); // after delete, otherwise tpam will be dangling
+ tp_so_handle = nullptr;
+ }
+}
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2018-2018 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.
+//--------------------------------------------------------------------------
+
+// tp_lib_handler.h author Silviu Minut <sminut@cisco.com>
+
+#ifndef TP_LIB_HANDLER_H
+#define TP_LIB_HANDLER_H
+
+#include "tp_appid_module_api.h"
+#include "tp_appid_session_api.h"
+
+class AppIdModuleConfig;
+
+// Class responsible for loading/reloading the thirdparty.so library and
+// for holding pointers to objects that live inside thirdparty.so.
+class TPLibHandler
+{
+public:
+
+ bool have_tp() const
+ {
+ return tp_appid_module != nullptr;
+ }
+
+ static TPLibHandler* get()
+ {
+ if (handler)
+ return handler;
+ else
+ return (handler=new TPLibHandler());
+ }
+
+ static void destroy(TPLibHandler* tph)
+ {
+ delete tph->handler;
+ tph->handler=nullptr;
+ }
+
+ // called from AppIdConfig::init_appid() and cleanup(), respectively.
+ void pinit(const AppIdModuleConfig* config);
+ void pfini(bool print_stats_flag=0);
+
+ // called from AppIdInspector tinit/tterm via
+ // AppIdConfig::tp_appid_module_tinit/tterm.
+ void tinit() { if ( tp_appid_module ) tp_appid_module->tinit(); }
+ void tterm() { if ( tp_appid_module ) tp_appid_module->tfini(); }
+
+ CreateThirdPartyAppIDSession_t tpsession_factory() const
+ {
+ return createThirdPartyAppIDSession;
+ }
+
+private:
+
+ TPLibHandler() { }
+ ~TPLibHandler() { }
+
+ static TPLibHandler* handler;
+ void* tp_so_handle = nullptr; // output of dlopen(thirdparty.so)
+ ThirdPartyAppIDModule* tp_appid_module = nullptr;
+ CreateThirdPartyAppIDSession_t createThirdPartyAppIDSession;
+
+ ThirdPartyConfig tp_config;
+
+ int LoadCallback(const char* path, int);
+};
+
+#endif
+