set ( APPID_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR} )
set ( CP_APPID_SOURCES
- client_plugins/client_app_aim.cc
- client_plugins/client_app_aim.h
- client_plugins/client_app_bit.cc
- client_plugins/client_app_bit.h
- client_plugins/client_app_bit_tracker.cc
- client_plugins/client_app_bit_tracker.h
- client_plugins/client_detector.cc
- client_plugins/client_detector.h
- client_plugins/client_app_msn.cc
- client_plugins/client_app_msn.h
- client_plugins/client_app_rtp.cc
- client_plugins/client_app_rtp.h
- client_plugins/client_app_ssh.cc
- client_plugins/client_app_ssh.h
- client_plugins/client_app_timbuktu.cc
- client_plugins/client_app_timbuktu.h
- client_plugins/client_app_tns.cc
- client_plugins/client_app_tns.h
- client_plugins/client_app_vnc.cc
- client_plugins/client_app_vnc.h
- client_plugins/client_app_ym.cc
- client_plugins/client_app_ym.h
+ client_plugins/client_app_aim.cc
+ client_plugins/client_app_aim.h
+ client_plugins/client_app_bit.cc
+ client_plugins/client_app_bit.h
+ client_plugins/client_app_bit_tracker.cc
+ client_plugins/client_app_bit_tracker.h
+ client_plugins/client_detector.cc
+ client_plugins/client_detector.h
+ client_plugins/client_app_msn.cc
+ client_plugins/client_app_msn.h
+ client_plugins/client_app_rtp.cc
+ client_plugins/client_app_rtp.h
+ client_plugins/client_app_ssh.cc
+ client_plugins/client_app_ssh.h
+ client_plugins/client_app_timbuktu.cc
+ client_plugins/client_app_timbuktu.h
+ client_plugins/client_app_tns.cc
+ client_plugins/client_app_tns.h
+ client_plugins/client_app_vnc.cc
+ client_plugins/client_app_vnc.h
+ client_plugins/client_app_ym.cc
+ client_plugins/client_app_ym.h
client_plugins/client_detector.cc
client_plugins/client_detector.h
client_plugins/client_discovery.cc
)
set ( SP_APPID_SOURCES
- service_plugins/dcerpc.cc
- service_plugins/dcerpc.h
- service_plugins/service_battle_field.cc
- service_plugins/service_battle_field.h
- service_plugins/service_bgp.cc
- service_plugins/service_bgp.h
- service_plugins/service_bit.cc
- service_plugins/service_bit.h
- service_plugins/service_bootp.cc
- service_plugins/service_bootp.h
- service_plugins/service_dcerpc.cc
- service_plugins/service_dcerpc.h
+ service_plugins/dcerpc.cc
+ service_plugins/dcerpc.h
+ service_plugins/service_battle_field.cc
+ service_plugins/service_battle_field.h
+ service_plugins/service_bgp.cc
+ service_plugins/service_bgp.h
+ service_plugins/service_bit.cc
+ service_plugins/service_bit.h
+ service_plugins/service_bootp.cc
+ service_plugins/service_bootp.h
+ service_plugins/service_dcerpc.cc
+ service_plugins/service_dcerpc.h
service_plugins/service_detector.cc
service_plugins/service_detector.h
- service_plugins/service_direct_connect.cc
- service_plugins/service_direct_connect.h
+ service_plugins/service_direct_connect.cc
+ service_plugins/service_direct_connect.h
service_plugins/service_discovery.cc
service_plugins/service_discovery.h
- service_plugins/service_flap.cc
- service_plugins/service_flap.h
- service_plugins/service_ftp.cc
- service_plugins/service_ftp.h
- service_plugins/service_irc.cc
- service_plugins/service_irc.h
- service_plugins/service_lpr.cc
- service_plugins/service_lpr.h
- service_plugins/service_mdns.cc
- service_plugins/service_mdns.h
- service_plugins/service_mysql.cc
- service_plugins/service_mysql.h
- service_plugins/service_netbios.cc
- service_plugins/service_netbios.h
- service_plugins/service_nntp.cc
- service_plugins/service_nntp.h
- service_plugins/service_ntp.cc
- service_plugins/service_ntp.h
- service_plugins/service_radius.cc
- service_plugins/service_radius.h
- service_plugins/service_regtest.cc
- service_plugins/service_regtest.h
- service_plugins/service_rexec.cc
- service_plugins/service_rexec.h
- service_plugins/service_rfb.cc
- service_plugins/service_rfb.h
- service_plugins/service_rlogin.cc
- service_plugins/service_rlogin.h
- service_plugins/service_rpc.cc
- service_plugins/service_rpc.h
- service_plugins/service_rshell.cc
- service_plugins/service_rshell.h
- service_plugins/service_rsync.cc
- service_plugins/service_rsync.h
- service_plugins/service_rtmp.cc
- service_plugins/service_rtmp.h
- service_plugins/service_snmp.cc
- service_plugins/service_snmp.h
- service_plugins/service_ssh.cc
- service_plugins/service_ssh.h
- service_plugins/service_ssl.cc
- service_plugins/service_ssl.h
- service_plugins/service_telnet.cc
- service_plugins/service_telnet.h
- service_plugins/service_tftp.cc
- service_plugins/service_tftp.h
- service_plugins/service_timbuktu.cc
- service_plugins/service_timbuktu.h
- service_plugins/service_tns.cc
- service_plugins/service_tns.h
+ service_plugins/service_flap.cc
+ service_plugins/service_flap.h
+ service_plugins/service_ftp.cc
+ service_plugins/service_ftp.h
+ service_plugins/service_irc.cc
+ service_plugins/service_irc.h
+ service_plugins/service_lpr.cc
+ service_plugins/service_lpr.h
+ service_plugins/service_mdns.cc
+ service_plugins/service_mdns.h
+ service_plugins/service_mysql.cc
+ service_plugins/service_mysql.h
+ service_plugins/service_netbios.cc
+ service_plugins/service_netbios.h
+ service_plugins/service_nntp.cc
+ service_plugins/service_nntp.h
+ service_plugins/service_ntp.cc
+ service_plugins/service_ntp.h
+ service_plugins/service_radius.cc
+ service_plugins/service_radius.h
+ service_plugins/service_regtest.cc
+ service_plugins/service_regtest.h
+ service_plugins/service_rexec.cc
+ service_plugins/service_rexec.h
+ service_plugins/service_rfb.cc
+ service_plugins/service_rfb.h
+ service_plugins/service_rlogin.cc
+ service_plugins/service_rlogin.h
+ service_plugins/service_rpc.cc
+ service_plugins/service_rpc.h
+ service_plugins/service_rshell.cc
+ service_plugins/service_rshell.h
+ service_plugins/service_rsync.cc
+ service_plugins/service_rsync.h
+ service_plugins/service_rtmp.cc
+ service_plugins/service_rtmp.h
+ service_plugins/service_snmp.cc
+ service_plugins/service_snmp.h
+ service_plugins/service_ssh.cc
+ service_plugins/service_ssh.h
+ service_plugins/service_ssl.cc
+ service_plugins/service_ssl.h
+ service_plugins/service_telnet.cc
+ service_plugins/service_telnet.h
+ service_plugins/service_tftp.cc
+ service_plugins/service_tftp.h
+ service_plugins/service_timbuktu.cc
+ service_plugins/service_timbuktu.h
+ service_plugins/service_tns.cc
+ service_plugins/service_tns.h
)
set ( DP_APPID_SOURCES
- detector_plugins/detector_dns.cc
- detector_plugins/detector_dns.h
- detector_plugins/detector_http.cc
- detector_plugins/detector_http.h
- detector_plugins/detector_imap.cc
- detector_plugins/detector_imap.h
- detector_plugins/detector_kerberos.cc
- detector_plugins/detector_kerberos.h
- detector_plugins/detector_pattern.cc
- detector_plugins/detector_pattern.h
- detector_plugins/detector_pop3.cc
- detector_plugins/detector_pop3.h
- detector_plugins/detector_sip.cc
- detector_plugins/detector_sip.h
- detector_plugins/detector_smtp.cc
- detector_plugins/detector_smtp.h
- detector_plugins/http_url_patterns.cc
- detector_plugins/http_url_patterns.h
+ detector_plugins/detector_dns.cc
+ detector_plugins/detector_dns.h
+ detector_plugins/detector_http.cc
+ detector_plugins/detector_http.h
+ detector_plugins/detector_imap.cc
+ detector_plugins/detector_imap.h
+ detector_plugins/detector_kerberos.cc
+ detector_plugins/detector_kerberos.h
+ detector_plugins/detector_pattern.cc
+ detector_plugins/detector_pattern.h
+ detector_plugins/detector_pop3.cc
+ detector_plugins/detector_pop3.h
+ detector_plugins/detector_sip.cc
+ detector_plugins/detector_sip.h
+ detector_plugins/detector_smtp.cc
+ detector_plugins/detector_smtp.h
+ detector_plugins/http_url_patterns.cc
+ detector_plugins/http_url_patterns.h
)
set ( UTIL_APPID_SOURCES
- appid_utils/fw_avltree.cc
- appid_utils/fw_avltree.h
- appid_utils/ip_funcs.cc
- appid_utils/ip_funcs.h
- appid_utils/network_set.cc
- appid_utils/network_set.h
- appid_utils/sf_mlmp.cc
- appid_utils/sf_mlmp.h
- appid_utils/sf_multi_mpse.cc
- appid_utils/sf_multi_mpse.h
+ appid_utils/fw_avltree.cc
+ appid_utils/fw_avltree.h
+ appid_utils/ip_funcs.cc
+ appid_utils/ip_funcs.h
+ appid_utils/network_set.cc
+ appid_utils/network_set.h
+ appid_utils/sf_mlmp.cc
+ appid_utils/sf_mlmp.h
+ appid_utils/sf_multi_mpse.cc
+ appid_utils/sf_multi_mpse.h
)
if ( ENABLE_APPID_THIRD_PARTY )
app_forecast.h
appid_api.cc
appid_api.h
+ appid_app_descriptor.cc
appid_app_descriptor.h
appid_config.cc
appid_config.h
service_state.h
http_xff_fields.h
${APPID_TP_SOURCES}
- )
-
+)
#if (STATIC_INSPECTORS)
add_library(appid OBJECT
- ${APPID_SOURCES}
- ${CP_APPID_SOURCES}
- ${DP_APPID_SOURCES}
- ${SP_APPID_SOURCES}
- ${UTIL_APPID_SOURCES}
- )
+ ${APPID_SOURCES}
+ ${CP_APPID_SOURCES}
+ ${DP_APPID_SOURCES}
+ ${SP_APPID_SOURCES}
+ ${UTIL_APPID_SOURCES}
+)
#else (STATIC_INSPECTORS)
# add_dynamic_module(appid inspectors
-# ${APPID_SOURCES}
-# ${CP_APPID_SOURCES}
-# ${DP_APPID_SOURCES}
-# ${SP_APPID_SOURCES}
-# ${UTIL_APPID_SOURCES}
+# ${APPID_SOURCES}
+# ${CP_APPID_SOURCES}
+# ${DP_APPID_SOURCES}
+# ${SP_APPID_SOURCES}
+# ${UTIL_APPID_SOURCES}
# )
#endif (STATIC_INSPECTORS)
APPINFO_FLAG_TP_CLIENT = (1<<11),
APPINFO_FLAG_DEFER_PAYLOAD = (1<<12),
APPINFO_FLAG_SEARCH_ENGINE = (1<<13),
- APPINFO_FLAG_SUPPORTED_SEARCH = (1<<14)
+ APPINFO_FLAG_SUPPORTED_SEARCH = (1<<14),
+ APPINFO_FLAG_CLIENT_DETECTOR_CALLBACK = (1<<15),
+ APPINFO_FLAG_SERVICE_DETECTOR_CALLBACK = (1<<16)
};
class AppInfoTableEntry
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2019 Cisco and/or its affiliates. All rights reserved.
+//--------------------------------------------------------------------------
+
+// appid_app_descriptor.cc author Shravan Rangaraju <shrarang@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "appid_app_descriptor.h"
+#include "lua_detector_api.h"
+
+void ApplicationDescriptor::set_id(const snort::Packet& p, AppIdSession& asd,
+ AppidSessionDirection dir, AppId app_id, AppidChangeBits& change_bits)
+{
+ if ( my_id != app_id )
+ {
+ set_id(app_id);
+ check_detector_callback(p, asd, dir, app_id, change_bits);
+ }
+}
+
#include <string>
+#include "protocols/packet.h"
+#include "pub_sub/appid_events.h"
+
#include "app_info_table.h"
#include "appid_module.h"
#include "appid_peg_counts.h"
+#include "appid_types.h"
+
+class AppIdDetector;
+class AppIdSession;
class ApplicationDescriptor
{
my_version.clear();
}
- virtual void update(AppId id, char* vendor, char* version, AppidChangeBits& change_bits)
+ virtual void update(AppId id, AppidChangeBits& change_bits, char* version)
{
set_id(id);
- set_vendor(vendor);
set_version(version, change_bits);
}
}
}
+ virtual void set_id(const snort::Packet& p, AppIdSession& asd, AppidSessionDirection dir, AppId app_id, AppidChangeBits& change_bits);
+
const char* get_vendor() const
{
return my_vendor.empty() ? nullptr : my_vendor.c_str();
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// client_detector.h author Sourcefire Inc.
+// appid_detector.h author Sourcefire Inc.
#ifndef APPID_DETECTOR_H
#define APPID_DETECTOR_H
{
dns_host_scan_hostname((const uint8_t*)dsession->get_host(), dsession->get_host_len(),
&client_id, &payload_id);
- asd.set_client_appid_data(client_id, nullptr, change_bits);
+ asd.set_client_appid_data(client_id, change_bits);
}
else if (asd.service.get_id() == APP_ID_RTMP)
asd.examine_rtmp_metadata(change_bits);
: CHP_APPIDINSTANCE_TO_ID(chp_candidate);
if (app_type_flags & APP_TYPE_SERVICE)
- asd.set_service_appid_data(chp_final, nullptr, version, change_bits);
+ asd.set_service_appid_data(chp_final, change_bits, version);
if (app_type_flags & APP_TYPE_CLIENT)
- asd.set_client_appid_data(chp_final, version, change_bits);
+ asd.set_client_appid_data(chp_final, change_bits, version);
if ( app_type_flags & APP_TYPE_PAYLOAD )
- asd.set_payload_appid_data((AppId)chp_final, version, change_bits);
+ asd.set_payload_appid_data(chp_final, change_bits, version);
if ( version )
{
{
if (appidDebug->is_active() and asd.payload.get_id() != APP_ID_WEBDAV)
LogMessage("AppIdDbg %s Data is webdav\n", appidDebug->get_debug_session());
- asd.set_payload_appid_data(APP_ID_WEBDAV, nullptr, change_bits);
+ asd.set_payload_appid_data(APP_ID_WEBDAV, change_bits);
}
// Scan User-Agent for Browser types or Skype
appidDebug->get_debug_session(), app_name ? app_name : "unknown", client_id);
}
}
- asd.set_service_appid_data(service_id, nullptr, nullptr, change_bits);
- asd.set_client_appid_data(client_id, version, change_bits);
+ asd.set_service_appid_data(service_id, change_bits);
+ asd.set_client_appid_data(client_id, change_bits, version);
asd.scan_flags &= ~SCAN_HTTP_USER_AGENT_FLAG;
snort_free(version);
}
app_name ? app_name : "unknown",
payload_id);
}
- asd.set_payload_appid_data((AppId)payload_id, nullptr, change_bits);
+ asd.set_payload_appid_data(payload_id, change_bits);
asd.scan_flags &= ~SCAN_HTTP_VIA_FLAG;
}
}
LogMessage("AppIdDbg %s X is client %s (%d)\n", appidDebug->get_debug_session(),
app_name ? app_name : "unknown", appId);
}
- asd.set_client_appid_data(appId, version, change_bits);
+ asd.set_client_appid_data(appId, change_bits, version);
}
else
{
LogMessage("AppIdDbg %s X service %s (%d)\n", appidDebug->get_debug_session(),
app_name ? app_name : "unknown", appId);
}
- asd.set_service_appid_data(appId, nullptr, version, change_bits);
+ asd.set_service_appid_data(appId, change_bits, version);
}
asd.scan_flags &= ~SCAN_HTTP_XWORKINGWITH_FLAG;
}
app_name ? app_name : "unknown",
payload_id);
}
- asd.set_payload_appid_data((AppId)payload_id, nullptr, change_bits);
+ asd.set_payload_appid_data(payload_id, change_bits);
asd.scan_flags &= ~SCAN_HTTP_CONTENT_TYPE_FLAG;
}
app_name ? app_name : "unknown",
client_id);
}
- asd.set_client_appid_data(client_id, nullptr, change_bits);
+ asd.set_client_appid_data(client_id, change_bits);
}
if (asd.service.get_id() <= APP_ID_NONE)
app_name ? app_name : "unknown",
service_id);
}
- asd.set_service_appid_data(service_id, nullptr, nullptr, change_bits);
+ asd.set_service_appid_data(service_id, change_bits);
}
// DO overwrite a previously-set data
app_name ? app_name : "unknown",
payload_id);
}
- asd.set_payload_appid_data((AppId)payload_id, version, change_bits);
+ asd.set_payload_appid_data(payload_id, change_bits, version);
asd.set_referred_payload_app_id_data(referredPayloadAppId, change_bits);
}
#include "appid_inspector.h"
#include "appid_stats.h"
#include "appid_utils/ip_funcs.h"
+#include "lua_detector_api.h"
#include "service_plugins/service_ssl.h"
#ifdef ENABLE_APPID_THIRD_PARTY
#include "tp_lib_handler.h"
if ((ret = ssl_scan_hostname((const uint8_t*)tls_str, size,
client_id, payload_id)))
{
- set_client_appid_data(client_id, nullptr, change_bits);
- set_payload_appid_data((AppId)payload_id, nullptr, change_bits);
+ set_client_appid_data(client_id, change_bits);
+ set_payload_appid_data(payload_id, change_bits);
setSSLSquelch(p, ret, (ret == 1 ? payload_id : client_id));
}
scan_flags &= ~SCAN_SSL_HOST_FLAG;
if ((ret = ssl_scan_cname((const uint8_t*)tls_str, size,
client_id, payload_id)))
{
- set_client_appid_data(client_id, nullptr, change_bits);
- set_payload_appid_data((AppId)payload_id, nullptr, change_bits);
+ set_client_appid_data(client_id, change_bits);
+ set_payload_appid_data(payload_id, change_bits);
setSSLSquelch(p, ret, (ret == 1 ? payload_id : client_id));
}
tsession->set_tls_cname(nullptr, 0);
if ((ret = ssl_scan_cname((const uint8_t*)tls_str, size,
client_id, payload_id)))
{
- set_client_appid_data(client_id, nullptr, change_bits);
- set_payload_appid_data((AppId)payload_id, nullptr, change_bits);
+ set_client_appid_data(client_id, change_bits);
+ set_payload_appid_data(payload_id, change_bits);
setSSLSquelch(p, ret, (ret == 1 ? payload_id : client_id));
}
tsession->set_tls_org_unit(nullptr, 0);
{
/* do not overwrite a previously-set client or service */
if (client.get_id() <= APP_ID_NONE)
- set_client_appid_data(payload_id, nullptr, change_bits);
+ set_client_appid_data(payload_id, change_bits);
if (service.get_id() <= APP_ID_NONE)
- set_service_appid_data(service_id, nullptr, nullptr, change_bits);
+ set_service_appid_data(service_id, change_bits);
/* DO overwrite a previously-set data */
- set_payload_appid_data((AppId)payload.get_id(), nullptr, change_bits);
+ set_payload_appid_data((AppId)payload.get_id(), change_bits);
set_referred_payload_app_id_data(referred_payload_id, change_bits);
}
}
}
-void AppIdSession::set_client_appid_data(AppId id, char* version, AppidChangeBits& change_bits)
+void AppIdSession::set_client_appid_data(AppId id, AppidChangeBits& change_bits, char* version)
{
if ( id <= APP_ID_NONE || id == APP_ID_HTTP )
return;
}
}
-void AppIdSession::set_payload_appid_data(AppId id, char* version, AppidChangeBits& change_bits)
+void AppIdSession::set_payload_appid_data(AppId id, AppidChangeBits& change_bits, char* version)
{
if ( id <= APP_ID_NONE )
return;
payload.set_version(version, change_bits);
}
-void AppIdSession::set_service_appid_data(AppId id, char* vendor, char* version,
- AppidChangeBits& change_bits)
+void AppIdSession::set_service_appid_data(AppId id, AppidChangeBits& change_bits, char* version)
{
if (id <= APP_ID_NONE)
return;
return;
}
- service.update(id, vendor, version, change_bits);
+ service.update(id, change_bits, version);
}
void AppIdSession::free_tls_session_data()
return true;
}
+void AppIdSession::set_tp_app_id(Packet& p, AppidSessionDirection dir, AppId app_id, AppidChangeBits& change_bits)
+{
+ if (tp_app_id != app_id)
+ {
+ tp_app_id = app_id;
+ AppInfoTableEntry* entry = app_info_mgr->get_app_info_entry(tp_app_id);
+ if (entry)
+ {
+ tp_app_id_deferred = (entry->flags & APPINFO_FLAG_DEFER) ? true : false;
+ check_detector_callback(p, *this, dir, app_id, change_bits, entry);
+ }
+ }
+}
+
+void AppIdSession::set_tp_payload_app_id(Packet& p, AppidSessionDirection dir, AppId app_id, AppidChangeBits& change_bits)
+{
+ if (tp_payload_app_id != app_id)
+ {
+ tp_payload_app_id = app_id;
+ AppInfoTableEntry* entry = app_info_mgr->get_app_info_entry(tp_payload_app_id);
+ if (entry)
+ {
+ tp_payload_app_id_deferred = (entry->flags & APPINFO_FLAG_DEFER_PAYLOAD) ? true : false;
+ check_detector_callback(p, *this, dir, app_id, change_bits, entry);
+ }
+ }
+}
bool is_ssl_session_decrypted();
void examine_ssl_metadata(snort::Packet*, AppidChangeBits& change_bits);
- void set_client_appid_data(AppId, char*, AppidChangeBits& change_bits);
- void set_service_appid_data(AppId, char*, char*, AppidChangeBits& change_bits);
+ void set_client_appid_data(AppId, AppidChangeBits& change_bits, char* version = nullptr);
+ void set_service_appid_data(AppId, AppidChangeBits& change_bits, char* version = nullptr);
void set_referred_payload_app_id_data(AppId, AppidChangeBits& change_bits);
- void set_payload_appid_data(AppId, char*, AppidChangeBits& change_bits);
+ void set_payload_appid_data(AppId, AppidChangeBits& change_bits, char* version = nullptr);
void check_app_detection_restart(AppidChangeBits& change_bits);
void update_encrypted_app_id(AppId);
void examine_rtmp_metadata(AppidChangeBits& change_bits);
bool is_tp_processing_done() const;
bool is_tp_appid_available() const;
+ void set_tp_app_id(snort::Packet& p, AppidSessionDirection dir, AppId app_id, AppidChangeBits& change_bits);
+ void set_tp_payload_app_id(snort::Packet& p, AppidSessionDirection dir, AppId app_id, AppidChangeBits& change_bits);
+
inline void set_tp_app_id(AppId app_id) {
if(tp_app_id != app_id) {
tp_app_id = app_id;
static CHPAction my_match;
static void* my_chp_rewritten = nullptr;
+void ApplicationDescriptor::set_id(const snort::Packet&, AppIdSession&, AppidSessionDirection, AppId, AppidChangeBits&) { }
+
TEST_GROUP(http_url_patterns_tests)
{
void setup() override
#include "app_forecast.h"
#include "app_info_table.h"
+#include "appid_debug.h"
#include "appid_inspector.h"
#include "client_plugins/client_discovery.h"
#include "detector_plugins/detector_dns.h"
#include "host_tracker/host_cache.h"
using namespace snort;
+using namespace std;
#define OVECCOUNT 30 /* should be a multiple of 3 */
return 0;
}
+static int register_callback(lua_State* L, LuaObject& ud, AppInfoFlags flag)
+{
+ // Verify detector user data and that we are NOT in packet context
+ ud.validate_lua_state(false);
+
+ const char* callback = lua_tostring(L, 3);
+
+ if (!callback)
+ {
+ lua_pushnumber(L, -1);
+ return 1; // number of results
+ }
+
+ AppId app_id = lua_tonumber(L, 2);
+ if (init(L))
+ {
+ // in control thread, update app info table. app info table is shared across all threads
+ AppInfoTableEntry* entry = AppInfoManager::get_instance().get_app_info_entry(app_id);
+ if (entry)
+ {
+ if (entry->flags & flag)
+ {
+ ErrorMessage("AppId: detector callback already registered for app %d\n", app_id);
+ return 1;
+ }
+ entry->flags |= flag;
+ }
+ else
+ {
+ ErrorMessage("AppId: detector callback cannot be registered for invalid app %d\n",
+ app_id);
+ return 1;
+ }
+ }
+ else
+ {
+ // In packet thread, store Lua detectors objects with callback in a thread local list.
+ // Note that Lua detector objects are thread local
+ ud.set_cb_fn_name(callback);
+
+ assert(lua_detector_mgr);
+ if (!lua_detector_mgr->insert_cb_detector(app_id, &ud))
+ {
+ ErrorMessage("AppId: detector callback already registered for app %d\n", app_id);
+ return 1;
+ }
+ }
+
+ lua_pushnumber(L, 0);
+
+ return 1;
+}
+
+static int detector_register_client_callback(lua_State* L)
+{
+ auto& ud = *UserData<LuaClientObject>::check(L, DETECTOR, 1);
+
+ return register_callback(L, *ud, APPINFO_FLAG_CLIENT_DETECTOR_CALLBACK);
+}
+
+static int detector_register_service_callback(lua_State* L)
+{
+ auto& ud = *UserData<LuaServiceObject>::check(L, DETECTOR, 1);
+
+ return register_callback(L, *ud, APPINFO_FLAG_SERVICE_DETECTOR_CALLBACK);
+}
+
+static int detector_callback(const uint8_t* data, uint16_t size, AppidSessionDirection dir,
+ AppIdSession& asd, const Packet& p, LuaObject& ud, AppidChangeBits& change_bits)
+{
+ if (!data)
+ {
+ return -10;
+ }
+
+ auto my_lua_state = lua_detector_mgr->L;
+ const string& cb_fn_name = ud.get_cb_fn_name();
+ const char* detector_name = ud.get_detector()->get_name().c_str();
+
+ if ((cb_fn_name.empty()) || !(lua_checkstack(my_lua_state, 1)))
+ {
+ ErrorMessage("Detector %s: invalid LUA %s\n", detector_name, lua_tostring(my_lua_state, -1));
+ ud.lsd.ldp.pkt = nullptr;
+ return -10;
+ }
+
+ lua_getfield(my_lua_state, LUA_REGISTRYINDEX, ud.lsd.package_info.name.c_str());
+
+ ud.lsd.ldp.data = data;
+ ud.lsd.ldp.size = size;
+ ud.lsd.ldp.dir = dir;
+ ud.lsd.ldp.asd = &asd;
+ ud.lsd.ldp.pkt = &p;
+ ud.lsd.ldp.change_bits = &change_bits;
+
+ lua_getfield(my_lua_state, -1, cb_fn_name.c_str());
+ if (lua_pcall(my_lua_state, 0, 1, 0))
+ {
+ ErrorMessage("Detector %s: Error validating %s\n", detector_name, lua_tostring(my_lua_state, -1));
+ ud.lsd.ldp.pkt = nullptr;
+ return -10;
+ }
+
+ // detector flows must be destroyed after each packet is processed
+ LuaDetectorManager::free_detector_flows();
+
+ // retrieve result
+ if (!lua_isnumber(my_lua_state, -1))
+ {
+ ErrorMessage("Detector %s: Validator returned non-numeric value\n", detector_name);
+ ud.lsd.ldp.pkt = nullptr;
+ return -10;
+ }
+
+ int ret = lua_tonumber(my_lua_state, -1);
+ lua_pop(my_lua_state, 1); // pop returned value
+ ud.lsd.ldp.pkt = nullptr;
+
+ return ret;
+}
+
+void check_detector_callback(const Packet& p, AppIdSession& asd, AppidSessionDirection dir, AppId app_id, AppidChangeBits& change_bits, AppInfoTableEntry* entry)
+{
+ if (!entry)
+ entry = AppInfoManager::get_instance().get_app_info_entry(app_id);
+ if (!entry)
+ return;
+
+ if (entry->flags & APPINFO_FLAG_CLIENT_DETECTOR_CALLBACK or
+ entry->flags & APPINFO_FLAG_SERVICE_DETECTOR_CALLBACK)
+ {
+ assert(lua_detector_mgr);
+ LuaObject* ud = lua_detector_mgr->get_cb_detector(app_id);
+ assert(ud);
+
+ if (ud->is_running())
+ return;
+
+ ud->set_running(true);
+
+ int ret = detector_callback(p.data, p.dsize, dir, asd, p, *ud, change_bits);
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s %s detector callback returned %d\n", appidDebug->get_debug_session(),
+ ud->get_detector()->get_name().empty() ? "UKNOWN" : ud->get_detector()->get_name().c_str(), ret);
+ ud->set_running(false);
+ }
+}
+
static int create_chp_application(AppId appIdInstance, unsigned app_type_flags, int num_matches)
{
CHPApp* new_app = (CHPApp*)snort_calloc(sizeof(CHPApp));
{ "addHostPortApp", detector_add_host_port_application },
{ "addHostPortAppDynamic", detector_add_host_port_dynamic },
{ "addDNSHostPattern", detector_add_dns_host_pattern },
+ { "registerClientDetectorCallback", detector_register_client_callback },
+ { "registerServiceDetectorCallback", detector_register_service_callback },
/*Obsolete - new detectors should not use this API */
{ "init", service_init },
#include <cstdint>
#include <string>
+#include "appid_types.h"
#include "client_plugins/client_detector.h"
#include "service_plugins/service_detector.h"
}
struct lua_State;
class AppIdSession;
+class AppInfoTableEntry;
#define DETECTOR "Detector"
#define DETECTORFLOW "DetectorFlow"
AppidSessionDirection dir = APP_ID_FROM_INITIATOR;
AppIdSession* asd;
AppidChangeBits* change_bits = nullptr;
- snort::Packet* pkt = nullptr;
- uint8_t macAddress[6] = { 0 };
+ const snort::Packet* pkt = nullptr;
};
class LuaStateDescriptor
LuaStateDescriptor lsd;
virtual AppIdDetector* get_detector() = 0;
LuaStateDescriptor* validate_lua_state(bool packet_context);
+
+ const std::string& get_cb_fn_name()
+ { return cb_fn_name; }
+
+ void set_cb_fn_name(const char* name)
+ { cb_fn_name = name; }
+
+ bool is_running()
+ { return running; }
+
+ void set_running(bool is_running)
+ { running = is_running; }
+
+private:
+ std::string cb_fn_name;
+ bool running = false;
};
class LuaServiceObject: public LuaObject
int init(lua_State*, int result=0);
void free_chp_glossary();
+void check_detector_callback(const snort::Packet& p, AppIdSession& asd, AppidSessionDirection dir,
+ AppId app_id, AppidChangeBits& change_bits, AppInfoTableEntry* entry = nullptr);
+
#endif
{
sflist_init(&allocated_detector_flow_list);
allocated_objects.clear();
+ cb_detectors.clear();
L = create_lua_state(config.mod_config, is_control);
if (is_control == 1)
init_chp_glossary();
sflist_static_free_all(&allocated_detector_flow_list, free_detector_flow);
allocated_objects.clear();
+ cb_detectors.clear(); // do not free Lua objects in cb_detectors
}
void LuaDetectorManager::initialize(AppIdConfig& config, int is_control)
sflist_static_free_all(&allocated_detector_flow_list, free_detector_flow);
}
+bool LuaDetectorManager::insert_cb_detector(AppId app_id, LuaObject* cb_detector)
+{
+ if (cb_detectors.find(app_id) != cb_detectors.end())
+ return false;
+ else
+ cb_detectors[app_id] = cb_detector;
+
+ return true;
+}
+
+LuaObject* LuaDetectorManager::get_cb_detector(AppId app_id)
+{
+ auto it = cb_detectors.find(app_id);
+
+ if (it != cb_detectors.end())
+ return it->second;
+
+ return nullptr;
+}
+
/**calculates Number of flow and host tracker entries for Lua detectors, given amount
* of memory allocated to RNA (fraction of total system memory) and number of detectors
* loaded in database. Calculations are based on CAICCI detector and observing memory
#include <cstdint>
#include <list>
+#include <map>
#include <string>
#include <lua.hpp>
#include "main/thread.h"
#include "protocols/protocol_ids.h"
+#include "application_ids.h"
+
class AppIdConfig;
class AppIdDetector;
struct DetectorFlow;
static void free_detector_flows();
// FIXIT-M: RELOAD - When reload is supported, move this variable to a separate location
lua_State* L;
+ bool insert_cb_detector(AppId app_id, LuaObject* ud);
+ LuaObject* get_cb_detector(AppId app_id);
private:
void initialize_lua_detectors();
AppIdConfig& config;
std::list<LuaObject*> allocated_objects;
size_t num_odp_detectors = 0;
+ std::map<AppId, LuaObject*> cb_detectors;
};
extern THREAD_LOCAL LuaDetectorManager* lua_detector_mgr;
AppId payload_id = APP_ID_NONE;
dns_host_scan_hostname((const uint8_t*)(dsession->get_host()), dsession->get_host_len(),
&client_id, &payload_id);
- asd.set_client_appid_data(client_id, nullptr, change_bits);
+ asd.set_client_appid_data(client_id, change_bits);
}
else if (asd.service.get_id() == APP_ID_RTMP)
asd.examine_rtmp_metadata(change_bits);
}
+void ApplicationDescriptor::set_id(const snort::Packet&, AppIdSession&, AppidSessionDirection, AppId, AppidChangeBits&) { }
const char* AppInfoManager::get_app_name(AppId)
{
return test_app_name;
FlowData::~FlowData() = default;
}
+void ApplicationDescriptor::set_id(const snort::Packet&, AppIdSession&, AppidSessionDirection, AppId, AppidChangeBits&) { }
class AppIdInspector
{
public:
#include <CppUTest/CommandLineTestRunner.h>
#include <CppUTest/TestHarness.h>
+void ApplicationDescriptor::set_id(const snort::Packet&, AppIdSession&, AppidSessionDirection, AppId, AppidChangeBits&) { }
void AppIdHttpSession::set_http_change_bits(AppidChangeBits&, HttpFieldIds) {}
class TestDetector : public AppIdDetector
return http_matchers;
}
+void ApplicationDescriptor::set_id(const snort::Packet&, AppIdSession&, AppidSessionDirection, AppId, AppidChangeBits&) { }
+
// Stubs for AppIdModule
AppIdModule::AppIdModule(): snort::Module("appid_mock", "appid_mock_help") {}
AppIdModule::~AppIdModule() {}
// Stubs for AppIdSession
void AppIdSession::sync_with_snort_protocol_id(AppId, Packet*) {}
void AppIdSession::check_app_detection_restart(AppidChangeBits&) {}
-void AppIdSession::set_client_appid_data(AppId, char*, AppidChangeBits&) {}
+void AppIdSession::set_client_appid_data(AppId, AppidChangeBits&, char*) {}
void AppIdSession::examine_rtmp_metadata(AppidChangeBits&) {}
void AppIdSession::examine_ssl_metadata(Packet*, AppidChangeBits&) {}
void AppIdSession::update_encrypted_app_id(AppId) {}
#include <CppUTest/CommandLineTestRunner.h>
#include <CppUTest/TestHarness.h>
+void ApplicationDescriptor::set_id(const snort::Packet&, AppIdSession&, AppidSessionDirection, AppId, AppidChangeBits&) { }
void AppIdHttpSession::set_http_change_bits(AppidChangeBits&, HttpFieldIds) {}
class MockServiceDetector : public ServiceDetector
#include <CppUTest/TestHarness.h>
#include <CppUTestExt/MockSupport.h>
-// Stubs for AppIdDebug
THREAD_LOCAL AppIdDebug* appidDebug = nullptr;
void AppIdDebug::activate(const Flow*, const AppIdSession*, bool) { active = true; }
-
+void ApplicationDescriptor::set_id(const snort::Packet&, AppIdSession&, AppidSessionDirection, AppId, AppidChangeBits&) { }
using namespace snort;
namespace snort
using namespace snort;
+void ApplicationDescriptor::set_id(const snort::Packet&, AppIdSession&, AppidSessionDirection, AppId, AppidChangeBits&) { }
const char* AppInfoManager::get_app_name(AppId)
{
return "";
{
}
-void AppIdSession::set_client_appid_data(AppId, char*, AppidChangeBits&)
+void AppIdSession::set_client_appid_data(AppId, AppidChangeBits&, char*)
{
}
-void AppIdSession::set_service_appid_data(AppId, char*, char*, AppidChangeBits&)
+void AppIdSession::set_service_appid_data(AppId, AppidChangeBits&, char*)
{
}
-void AppIdSession::set_payload_appid_data(AppId, char*, AppidChangeBits&)
+void AppIdSession::set_payload_appid_data(AppId, AppidChangeBits&, char*)
{
}
#include <CppUTest/CommandLineTestRunner.h>
#include <CppUTest/TestHarness.h>
+void ApplicationDescriptor::set_id(const snort::Packet&, AppIdSession&, AppidSessionDirection, AppId, AppidChangeBits&) { }
void BootpServiceDetector::AppIdFreeDhcpData(DHCPData* data)
{
delete data;
void AppIdDebug::activate(const Flow*, const AppIdSession*, bool) { active = true; }
+void ApplicationDescriptor::set_id(const snort::Packet&, AppIdSession&, AppidSessionDirection, AppId, AppidChangeBits&) { }
AppIdSession::AppIdSession(IpProtocol, const SfIp*, uint16_t, AppIdInspector&)
: FlowData(0) {}
AppIdSession::~AppIdSession() = default;
http_matchers->identify_user_agent(field->c_str(), size, service_id,
client_id, &version);
- asd.set_client_appid_data(client_id, version, change_bits);
+ asd.set_client_appid_data(client_id, change_bits, version);
// do not overwrite a previously-set service
if ( service_id <= APP_ID_NONE )
- asd.set_service_appid_data(service_id, nullptr, nullptr, change_bits);
+ asd.set_service_appid_data(service_id, change_bits);
asd.scan_flags |= ~SCAN_HTTP_USER_AGENT_FLAG;
snort_free(version);
{
// do not overwrite a previously-set client or service
if ( client_id <= APP_ID_NONE )
- asd.set_client_appid_data(client_id, nullptr, change_bits);
+ asd.set_client_appid_data(client_id, change_bits);
if ( service_id <= APP_ID_NONE )
- asd.set_service_appid_data(service_id, nullptr, nullptr, change_bits);
+ asd.set_service_appid_data(service_id, change_bits);
// DO overwrite a previously-set data
- asd.set_payload_appid_data(payload_id, nullptr, change_bits);
+ asd.set_payload_appid_data(payload_id, change_bits);
asd.set_referred_payload_app_id_data(referred_payload_app_id, change_bits);
}
}
asd.tsession = (TlsSession*)snort_calloc(sizeof(TlsSession));
if (!asd.client.get_id())
- asd.set_client_appid_data(APP_ID_SSL_CLIENT, nullptr, change_bits);
+ asd.set_client_appid_data(APP_ID_SSL_CLIENT, change_bits);
if ( (field=attribute_data.tls_host(false)) != nullptr )
{
APPINFO_FLAG_TP_CLIENT | APPINFO_FLAG_IGNORE | APPINFO_FLAG_SSL_SQUELCH);
if ( app_info_flags & APPINFO_FLAG_TP_CLIENT )
- asd.client.set_id(tp_app_id);
+ asd.client.set_id(*p, asd, direction, tp_app_id, change_bits);
process_third_party_results(asd, tp_confidence, tp_proto_list, tp_attribute_data,
change_bits);
snort_app_id = APP_ID_HTTP;
//data should never be APP_ID_HTTP
if (tp_app_id != APP_ID_HTTP)
- asd.set_tp_payload_app_id(tp_app_id);
+ asd.set_tp_payload_app_id(*p, direction, tp_app_id, change_bits);
asd.set_tp_app_id(APP_ID_HTTP);
// Handle HTTP tunneling and SSL possibly then being used in that tunnel
if (tp_app_id == APP_ID_HTTP_TUNNEL)
- asd.set_payload_appid_data(APP_ID_HTTP_TUNNEL, NULL, change_bits);
+ asd.set_payload_appid_data(APP_ID_HTTP_TUNNEL, change_bits);
else if ((asd.payload.get_id() == APP_ID_HTTP_TUNNEL) &&
(tp_app_id == APP_ID_SSL))
- asd.set_payload_appid_data(APP_ID_HTTP_SSL_TUNNEL, NULL, change_bits);
+ asd.set_payload_appid_data(APP_ID_HTTP_SSL_TUNNEL, change_bits);
AppIdHttpSession* hsession = asd.get_http_session();
hsession->process_http_packet(direction, change_bits);
}
else
{
- asd.set_tp_payload_app_id(tp_app_id);
+ asd.set_tp_payload_app_id(*p, direction, tp_app_id, change_bits);
tp_app_id = portAppId;
if (appidDebug->is_active())
{
snort_app_id = tp_app_id;
}
- asd.set_tp_app_id(tp_app_id);
+ asd.set_tp_app_id(*p, direction, tp_app_id, change_bits);
asd.sync_with_snort_protocol_id(snort_app_id, p);
}
else