appid_discovery.cc
appid_discovery.h
appid_dns_session.h
+ appid_ha.cc
+ appid_ha.h
appid_http_session.cc
appid_http_session.h
appid_peg_counts.h
return ctxt.get_odp_ctxt().get_app_info_mgr().get_appid_by_name(appName);
}
-#define APPID_HA_FLAGS_APP ( 1 << 0 )
-#define APPID_HA_FLAGS_TP_DONE ( 1 << 1 )
-#define APPID_HA_FLAGS_SVC_DONE ( 1 << 2 )
-#define APPID_HA_FLAGS_HTTP ( 1 << 3 )
-
-uint32_t AppIdApi::produce_ha_state(const Flow& flow, uint8_t* buf)
-{
- assert(buf);
- AppIdSessionHA* appHA = (AppIdSessionHA*)buf;
- AppIdSession* asd = get_appid_session(flow);
- if (asd)
- {
- appHA->flags = APPID_HA_FLAGS_APP;
- if (asd->is_tp_appid_available())
- appHA->flags |= APPID_HA_FLAGS_TP_DONE;
- if (asd->is_service_detected())
- appHA->flags |= APPID_HA_FLAGS_SVC_DONE;
- if (asd->get_session_flags(APPID_SESSION_HTTP_SESSION))
- appHA->flags |= APPID_HA_FLAGS_HTTP;
- appHA->appId[0] = asd->get_tp_app_id();
- appHA->appId[1] = asd->get_service_id();
- appHA->appId[2] = asd->client_inferred_service_id;
- appHA->appId[3] = asd->get_port_service_id();
- const AppIdHttpSession* hsession = asd->get_http_session();
- if (hsession)
- appHA->appId[4] = hsession->payload.get_id();
- else
- appHA->appId[4] = asd->get_payload_id();
- appHA->appId[5] = asd->get_tp_payload_app_id();
- if (hsession)
- appHA->appId[6] = hsession->client.get_id();
- else
- appHA->appId[6] = asd->get_client_id();
- appHA->appId[7] = asd->misc_app_id;
- appHA->asid = asd->asid;
- }
- else
- memset(appHA, 0, sizeof(*appHA));
-
- return sizeof(*appHA);
-}
-
-uint32_t AppIdApi::consume_ha_state(Flow& flow, const uint8_t* buf, uint8_t, IpProtocol proto,
- SfIp* ip, uint16_t port)
-{
- const AppIdSessionHA* appHA = (const AppIdSessionHA*)buf;
- if (appHA->flags & APPID_HA_FLAGS_APP)
- {
- AppIdSession* asd =
- (AppIdSession*)(flow.get_flow_data(AppIdSession::inspector_id));
-
- if (!asd)
- {
- AppIdInspector* inspector = (AppIdInspector*) InspectorManager::get_inspector(MOD_NAME, true);
- if (inspector)
- {
- asd = new AppIdSession(proto, ip, port, *inspector,
- inspector->get_ctxt().get_odp_ctxt(), appHA->asid);
- flow.set_flow_data(asd);
- asd->set_service_id(appHA->appId[1], asd->get_odp_ctxt());
- if (asd->get_service_id() == APP_ID_FTP_CONTROL)
- {
- asd->set_session_flags(APPID_SESSION_CLIENT_DETECTED |
- APPID_SESSION_NOT_A_SERVICE | APPID_SESSION_SERVICE_DETECTED);
- if (!ServiceDiscovery::add_ftp_service_state(*asd))
- asd->set_session_flags(APPID_SESSION_CONTINUE);
-
- asd->service_disco_state = APPID_DISCO_STATE_STATEFUL;
- }
- else
- asd->service_disco_state = APPID_DISCO_STATE_FINISHED;
-
- asd->client_disco_state = APPID_DISCO_STATE_FINISHED;
- if (asd->tpsession)
- asd->tpsession->set_state(TP_STATE_HA);
- }
- }
-
- if (!asd)
- {
- return sizeof(*appHA);
- }
-
- if((appHA->flags & APPID_HA_FLAGS_TP_DONE) && asd->tpsession)
- {
- asd->tpsession->set_state(TP_STATE_TERMINATED);
- asd->set_session_flags(APPID_SESSION_NO_TPI);
- }
-
- if (appHA->flags & APPID_HA_FLAGS_SVC_DONE)
- asd->set_service_detected();
-
- if (appHA->flags & APPID_HA_FLAGS_HTTP)
- asd->set_session_flags(APPID_SESSION_HTTP_SESSION);
-
- asd->set_tp_app_id(appHA->appId[0]);
- asd->set_service_id(appHA->appId[1], asd->get_odp_ctxt());
- asd->client_inferred_service_id = appHA->appId[2];
- asd->set_port_service_id(appHA->appId[3]);
- AppIdHttpSession* hsession = nullptr;
- if (appHA->appId[1] == APP_ID_HTTP or appHA->appId[1] == APP_ID_RTMP)
- hsession = asd->create_http_session();
- if (hsession)
- hsession->payload.set_id(appHA->appId[4]);
- else
- asd->set_payload_id(appHA->appId[4]);
- asd->set_tp_payload_app_id(appHA->appId[5]);
- if (hsession)
- hsession->client.set_id(appHA->appId[6]);
- else
- asd->set_client_id(appHA->appId[6]);
- asd->misc_app_id = appHA->appId[7];
- }
- return sizeof(*appHA);
-}
-
bool AppIdApi::ssl_app_group_id_lookup(Flow* flow, const char* server_name,
const char* first_alt_name, const char* common_name, const char* org_unit,
bool sni_mismatch, AppId& service_id, AppId& client_id, AppId& payload_id)
namespace snort
{
-
-#define APPID_HA_SESSION_APP_NUM_MAX 8 // maximum number of appIds replicated for a flow/session
-
-struct AppIdSessionHA
-{
- uint16_t flags;
- uint16_t asid;
- AppId appId[APPID_HA_SESSION_APP_NUM_MAX];
-};
-
// -----------------------------------------------------------------------------
// AppId API
// -----------------------------------------------------------------------------
const char* get_application_name(AppId app_id, const Flow& flow);
const char* get_application_name(const Flow& flow, bool from_client);
AppId get_application_id(const char* appName, const AppIdContext& ctxt);
- uint32_t produce_ha_state(const Flow& flow, uint8_t* buf);
- uint32_t consume_ha_state(Flow& flow, const uint8_t* buf, uint8_t length, IpProtocol,
- SfIp*, uint16_t initiatorPort);
bool ssl_app_group_id_lookup(Flow* flow, const char*, const char*, const char*,
const char*, bool, AppId& service_id, AppId& client_id, AppId& payload_id);
const AppIdSessionApi* get_appid_session_api(const Flow& flow) const;
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2020-2020 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.
+//--------------------------------------------------------------------------
+
+// appid_ha.cc author Kani Murthi <kamurthi@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "appid_ha.h"
+
+#include "flow/flow_key.h"
+#include "managers/inspector_manager.h"
+
+#include "appid_debug.h"
+#include "appid_session.h"
+#include "tp_lib_handler.h"
+
+#define APPID_HA_FLAGS_TP_DONE ( 1 << 0 )
+#define APPID_HA_FLAGS_SVC_DONE ( 1 << 1 )
+#define APPID_HA_FLAGS_HTTP ( 1 << 2 )
+
+using namespace snort;
+
+THREAD_LOCAL AppIdHAAppsClient* AppIdHAManager::ha_apps_client = nullptr;
+THREAD_LOCAL AppIdHAHttpClient* AppIdHAManager::ha_http_client = nullptr;
+THREAD_LOCAL AppIdHATlsHostClient* AppIdHAManager::ha_tls_host_client = nullptr;
+
+static AppIdSession* create_appid_session(Flow& flow, const FlowKey* key)
+{
+ AppIdInspector* inspector = (AppIdInspector*) InspectorManager::get_inspector(MOD_NAME, true);
+ AppIdSession* asd = new AppIdSession(static_cast<IpProtocol>(key->ip_protocol),
+ flow.flags.client_initiated ? &flow.client_ip : &flow.server_ip,
+ flow.flags.client_initiated ? flow.client_port : flow.server_port, *inspector,
+ inspector->get_ctxt().get_odp_ctxt(), key->addressSpaceId);
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s high-avail - New AppId session created in consume\n",
+ appidDebug->get_debug_session());
+
+ flow.set_flow_data(asd);
+ asd->flow = &flow;
+
+ return asd;
+}
+
+bool AppIdHAAppsClient::consume(Flow*& flow, const FlowKey* key, HAMessage& msg,
+ uint8_t size)
+{
+ assert(key and flow);
+ if (size != sizeof(AppIdSessionHAApps))
+ return false;
+
+ AppIdInspector* inspector = (AppIdInspector*) InspectorManager::get_inspector(MOD_NAME, true);
+ if (!inspector)
+ return false;
+
+ AppIdSession* asd = (AppIdSession*)(flow->get_flow_data(AppIdSession::inspector_id));
+ const AppIdSessionHAApps* appHA = (const AppIdSessionHAApps*)msg.cursor;
+
+ if (appidDebug->is_enabled())
+ {
+ appidDebug->activate(flow, asd, inspector->get_ctxt().config.log_all_sessions);
+ LogMessage("AppIdDbg %s high-avail - Consuming app data - flags 0x%x, service %d, client %d, "
+ "payload %d, misc %d, referred %d, client_inferred_service %d, port_service %d, "
+ "tp_app %d, tp_payload %d\n",
+ appidDebug->get_debug_session(), appHA->flags, appHA->appId[APPID_HA_APP_SERVICE],
+ appHA->appId[APPID_HA_APP_CLIENT], appHA->appId[APPID_HA_APP_PAYLOAD],
+ appHA->appId[APPID_HA_APP_MISC], appHA->appId[APPID_HA_APP_REFERRED],
+ appHA->appId[APPID_HA_APP_CLIENT_INFERRED_SERVICE],
+ appHA->appId[APPID_HA_APP_PORT_SERVICE], appHA->appId[APPID_HA_APP_TP],
+ appHA->appId[APPID_HA_APP_TP_PAYLOAD]);
+ }
+
+ if (!asd)
+ {
+ asd = create_appid_session(*flow, key);
+ asd->set_service_id(appHA->appId[APPID_HA_APP_SERVICE], asd->get_odp_ctxt());
+ if (asd->get_service_id() == APP_ID_FTP_CONTROL)
+ {
+ asd->set_session_flags(APPID_SESSION_CLIENT_DETECTED |
+ APPID_SESSION_NOT_A_SERVICE | APPID_SESSION_SERVICE_DETECTED);
+ if (!ServiceDiscovery::add_ftp_service_state(*asd))
+ asd->set_session_flags(APPID_SESSION_CONTINUE);
+
+ asd->service_disco_state = APPID_DISCO_STATE_STATEFUL;
+ }
+ else
+ asd->service_disco_state = APPID_DISCO_STATE_FINISHED;
+
+ asd->client_disco_state = APPID_DISCO_STATE_FINISHED;
+ if (asd->get_tp_appid_ctxt())
+ {
+ const TPLibHandler* tph = TPLibHandler::get();
+ TpAppIdCreateSession tpsf = tph->tpsession_factory();
+ if ( !(asd->tpsession = tpsf(*asd->get_tp_appid_ctxt())) )
+ ErrorMessage("appid: Could not allocate asd.tpsession data in consume");
+ else
+ asd->tpsession->set_state(TP_STATE_HA);
+ }
+ }
+
+ if ((appHA->flags & APPID_HA_FLAGS_TP_DONE) and asd->tpsession)
+ {
+ asd->tpsession->set_state(TP_STATE_TERMINATED);
+ asd->set_session_flags(APPID_SESSION_NO_TPI);
+ }
+
+ if (appHA->flags & APPID_HA_FLAGS_SVC_DONE)
+ asd->set_service_detected();
+
+ if (appHA->flags & APPID_HA_FLAGS_HTTP)
+ asd->set_session_flags(APPID_SESSION_HTTP_SESSION);
+ asd->set_service_id(appHA->appId[APPID_HA_APP_SERVICE], asd->get_odp_ctxt());
+ AppIdHttpSession* hsession = nullptr;
+ if (appHA->appId[APPID_HA_APP_SERVICE] == APP_ID_HTTP or
+ appHA->appId[APPID_HA_APP_SERVICE] == APP_ID_RTMP)
+ hsession = asd->create_http_session();
+ if (hsession)
+ {
+ hsession->client.set_id(appHA->appId[APPID_HA_APP_CLIENT]);
+ hsession->payload.set_id(appHA->appId[APPID_HA_APP_PAYLOAD]);
+ hsession->misc_app_id = appHA->appId[APPID_HA_APP_MISC];
+ hsession->referred_payload_app_id = appHA->appId[APPID_HA_APP_REFERRED];
+ }
+ else
+ {
+ asd->set_client_id(appHA->appId[APPID_HA_APP_CLIENT]);
+ asd->set_payload_id(appHA->appId[APPID_HA_APP_PAYLOAD]);
+ asd->misc_app_id = appHA->appId[APPID_HA_APP_MISC];
+ }
+ asd->client_inferred_service_id = appHA->appId[APPID_HA_APP_CLIENT_INFERRED_SERVICE];
+ asd->set_port_service_id(appHA->appId[APPID_HA_APP_PORT_SERVICE]);
+ asd->set_tp_app_id(appHA->appId[APPID_HA_APP_TP]);
+ asd->set_tp_payload_app_id(appHA->appId[APPID_HA_APP_TP_PAYLOAD]);
+
+ asd->set_consumed_ha_data(true);
+
+ msg.advance_cursor(sizeof(AppIdSessionHAApps));
+ return true;
+}
+
+bool AppIdHAAppsClient::produce(Flow& flow, HAMessage& msg)
+{
+ if (!msg.fits(sizeof(AppIdSessionHAApps)))
+ return false;
+ assert(msg.cursor);
+
+ AppIdSession* asd = (AppIdSession*)flow.get_flow_data(AppIdSession::inspector_id);
+ if (!asd)
+ return false;
+
+ AppIdSessionHAApps* appHA = (AppIdSessionHAApps*)(msg.cursor);
+ if (asd->is_tp_appid_available())
+ appHA->flags |= APPID_HA_FLAGS_TP_DONE;
+ if (asd->is_service_detected())
+ appHA->flags |= APPID_HA_FLAGS_SVC_DONE;
+ if (asd->get_session_flags(APPID_SESSION_HTTP_SESSION))
+ appHA->flags |= APPID_HA_FLAGS_HTTP;
+ appHA->appId[APPID_HA_APP_SERVICE] = asd->get_service_id();
+ const AppIdHttpSession* hsession = asd->get_http_session(0);
+ if (hsession)
+ {
+ appHA->appId[APPID_HA_APP_CLIENT] = hsession->client.get_id();
+ appHA->appId[APPID_HA_APP_PAYLOAD] = hsession->payload.get_id();
+ appHA->appId[APPID_HA_APP_MISC] = hsession->misc_app_id;
+ appHA->appId[APPID_HA_APP_REFERRED] = hsession->referred_payload_app_id;
+ }
+ else
+ {
+ appHA->appId[APPID_HA_APP_CLIENT] = asd->get_client_id();
+ appHA->appId[APPID_HA_APP_PAYLOAD] = asd->get_payload_id();
+ appHA->appId[APPID_HA_APP_MISC] = asd->misc_app_id;
+ appHA->appId[APPID_HA_APP_REFERRED] = APP_ID_NONE;
+ }
+ appHA->appId[APPID_HA_APP_CLIENT_INFERRED_SERVICE] = asd->client_inferred_service_id;
+ appHA->appId[APPID_HA_APP_PORT_SERVICE] = asd->get_port_service_id();
+ appHA->appId[APPID_HA_APP_TP] = asd->get_tp_app_id();
+ appHA->appId[APPID_HA_APP_TP_PAYLOAD] = asd->get_tp_payload_app_id();
+
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s high-avail - Producing app data - flags 0x%x, service %d, client %d, "
+ "payload %d, misc %d, referred %d, client_inferred_service %d, port_service %d, "
+ "tp_app %d, tp_payload %d\n",
+ appidDebug->get_debug_session(), appHA->flags, appHA->appId[APPID_HA_APP_SERVICE],
+ appHA->appId[APPID_HA_APP_CLIENT], appHA->appId[APPID_HA_APP_PAYLOAD],
+ appHA->appId[APPID_HA_APP_MISC], appHA->appId[APPID_HA_APP_REFERRED],
+ appHA->appId[APPID_HA_APP_CLIENT_INFERRED_SERVICE],
+ appHA->appId[APPID_HA_APP_PORT_SERVICE], appHA->appId[APPID_HA_APP_TP],
+ appHA->appId[APPID_HA_APP_TP_PAYLOAD]);
+
+ msg.advance_cursor(sizeof(AppIdSessionHAApps));
+ return true;
+}
+
+bool AppIdHAHttpClient::consume(Flow*& flow, const FlowKey* key, HAMessage& msg,
+ uint8_t size)
+{
+ assert(key and flow);
+
+ if (size != sizeof(AppIdSessionHAHttp))
+ return false;
+
+ AppIdInspector* inspector = (AppIdInspector*) InspectorManager::get_inspector(MOD_NAME, true);
+ if (!inspector)
+ return false;
+
+ AppIdSession* asd = appid_api.get_appid_session(*flow);
+ AppIdSessionHAHttp* appHA = (AppIdSessionHAHttp*)msg.cursor;
+ if (appidDebug->is_enabled())
+ {
+ appidDebug->activate(flow, asd, inspector->get_ctxt().config.log_all_sessions);
+ LogMessage("AppIdDbg %s high-avail - Consuming HTTP data - URL %s, host %s\n",
+ appidDebug->get_debug_session(), appHA->url, appHA->host);
+ }
+
+ if (!asd)
+ asd = create_appid_session(*flow, key);
+
+ AppidChangeBits change_bits;
+ AppIdHttpSession* hsession = asd->get_http_session();
+ if (!hsession)
+ hsession = asd->create_http_session();
+
+ hsession->set_field(MISC_URL_FID, new std::string(appHA->url), change_bits);
+ hsession->set_field(REQ_HOST_FID, new std::string(appHA->host), change_bits);
+
+ asd->set_consumed_ha_data(true);
+
+ msg.advance_cursor(sizeof(AppIdSessionHAHttp));
+ return true;
+}
+
+bool AppIdHAHttpClient::produce(Flow& flow, HAMessage& msg)
+{
+ if (!msg.fits(sizeof(AppIdSessionHAHttp)))
+ return false;
+ assert(msg.cursor);
+
+ AppIdSession* asd = appid_api.get_appid_session(flow);
+ if (!asd)
+ return false;
+
+ const AppIdHttpSession* hsession = asd->get_http_session();
+ if (!hsession)
+ return false;
+
+ const char* url = hsession->get_cfield(MISC_URL_FID);
+ const char* host = hsession->get_cfield(REQ_HOST_FID);
+ if (!url and !host)
+ return false;
+
+ AppIdSessionHAHttp* appHA = (AppIdSessionHAHttp*)msg.cursor;
+
+ if (url)
+ {
+ auto length = strlen(url);
+ if (length >= APPID_HA_MAX_FIELD_LEN)
+ length = APPID_HA_MAX_FIELD_LEN - 1;
+ memcpy(appHA->url, (void *)url, length);
+ appHA->url[length] = '\0';
+ }
+ else
+ appHA->url[0] = '\0';
+
+ if (host)
+ {
+ auto length = strlen(host);
+ if (length >= APPID_HA_MAX_FIELD_LEN)
+ length = APPID_HA_MAX_FIELD_LEN - 1;
+ memcpy(appHA->host, (void *)host, length);
+ appHA->host[length] = '\0';
+ }
+ else
+ appHA->host[0] = '\0';
+
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s high-avail - Producing HTTP data - URL %s, host %s\n",
+ appidDebug->get_debug_session(), appHA->url, appHA->host);
+
+ msg.advance_cursor(sizeof(AppIdSessionHAHttp));
+ return true;
+}
+
+bool AppIdHATlsHostClient::consume(Flow*& flow, const FlowKey* key, HAMessage& msg,
+ uint8_t size)
+{
+ assert(key and flow);
+ if (size != sizeof(AppIdSessionHATlsHost))
+ return false;
+
+ AppIdInspector* inspector = (AppIdInspector*) InspectorManager::get_inspector(MOD_NAME, true);
+ if (!inspector)
+ return false;
+
+ AppIdSession* asd = appid_api.get_appid_session(*flow);
+ AppIdSessionHATlsHost* appHA = (AppIdSessionHATlsHost*)msg.cursor;
+ if (appidDebug->is_enabled())
+ {
+ appidDebug->activate(flow, asd, inspector->get_ctxt().config.log_all_sessions);
+ LogMessage("AppIdDbg %s high-avail - Consuming TLS host - %s\n",
+ appidDebug->get_debug_session(), appHA->tls_host);
+ }
+
+ if (!asd)
+ asd = create_appid_session(*flow, key);
+
+ asd->set_tls_host(appHA->tls_host);
+
+ asd->set_consumed_ha_data(true);
+
+ msg.advance_cursor(sizeof(AppIdSessionHATlsHost));
+ return true;
+}
+
+bool AppIdHATlsHostClient::produce(Flow& flow, HAMessage& msg)
+{
+ if (!msg.fits(sizeof(AppIdSessionHATlsHost)))
+ return false;
+ assert(msg.cursor);
+
+ AppIdSession* asd = appid_api.get_appid_session(flow);
+ if (!asd or !asd->get_api().get_tls_host())
+ return false;
+
+ AppIdSessionHATlsHost* appHA = (AppIdSessionHATlsHost*)msg.cursor;
+ const char* tls_host = asd->get_api().get_tls_host();
+ auto length = strlen(tls_host);
+ if (length >= APPID_HA_MAX_FIELD_LEN)
+ length = APPID_HA_MAX_FIELD_LEN - 1;
+ memcpy(appHA->tls_host, tls_host, length);
+ appHA->tls_host[length] = '\0';
+
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s high-avail - Producing TLS host - %s\n",
+ appidDebug->get_debug_session(), appHA->tls_host);
+
+ msg.advance_cursor(sizeof(AppIdSessionHATlsHost));
+ return true;
+}
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2020-2020 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.
+//--------------------------------------------------------------------------
+
+// appid_ha.h author Kani Murthi <kamurthi@cisco.com>
+
+#ifndef APPID_HA_H
+#define APPID_HA_H
+
+#include "flow/flow.h"
+#include "flow/ha.h"
+#include "appid_inspector.h"
+
+#define APPID_HA_MAX_FIELD_LEN 32
+
+enum AppIdHAAppType
+{
+ APPID_HA_APP_SERVICE = 0,
+ APPID_HA_APP_CLIENT,
+ APPID_HA_APP_PAYLOAD,
+ APPID_HA_APP_MISC,
+ APPID_HA_APP_REFERRED,
+ APPID_HA_APP_CLIENT_INFERRED_SERVICE,
+ APPID_HA_APP_PORT_SERVICE,
+ APPID_HA_APP_TP,
+ APPID_HA_APP_TP_PAYLOAD,
+ APPID_HA_APP_MAX
+};
+
+struct AppIdSessionHAApps
+{
+ uint16_t flags;
+ AppId appId[APPID_HA_APP_MAX];
+};
+
+struct AppIdSessionHAHttp
+{
+ char url[APPID_HA_MAX_FIELD_LEN];
+ char host[APPID_HA_MAX_FIELD_LEN];
+};
+
+struct AppIdSessionHATlsHost
+{
+ char tls_host[APPID_HA_MAX_FIELD_LEN];
+};
+
+class AppIdHAAppsClient : public snort::FlowHAClient
+{
+public:
+ AppIdHAAppsClient() : FlowHAClient(sizeof(AppIdSessionHAApps), false) { }
+ bool consume(snort::Flow*&, const snort::FlowKey*, snort::HAMessage&, uint8_t size) override;
+ bool produce(snort::Flow&, snort::HAMessage&) override;
+};
+
+class AppIdHAHttpClient : public snort::FlowHAClient
+{
+public:
+ AppIdHAHttpClient() : FlowHAClient(sizeof(AppIdSessionHAHttp), false) { }
+ bool consume(snort::Flow*&, const snort::FlowKey*, snort::HAMessage&, uint8_t size) override;
+ bool produce(snort::Flow&, snort::HAMessage&) override;
+};
+
+class AppIdHATlsHostClient : public snort::FlowHAClient
+{
+public:
+ AppIdHATlsHostClient() : FlowHAClient(sizeof(AppIdSessionHATlsHost), false) { }
+ bool consume(snort::Flow*&, const snort::FlowKey*, snort::HAMessage&, uint8_t size) override;
+ bool produce(snort::Flow&, snort::HAMessage&) override;
+};
+
+class AppIdHAManager
+{
+public:
+ static void tinit()
+ {
+ if ( snort::HighAvailabilityManager::active() )
+ {
+ ha_apps_client = new AppIdHAAppsClient;
+ ha_http_client = new AppIdHAHttpClient;
+ ha_tls_host_client = new AppIdHATlsHostClient;
+ }
+ }
+ static void tterm()
+ {
+ if ( snort::HighAvailabilityManager::active() )
+ {
+ delete ha_apps_client;
+ delete ha_http_client;
+ delete ha_tls_host_client;
+ }
+ }
+
+ static THREAD_LOCAL AppIdHAAppsClient* ha_apps_client;
+ static THREAD_LOCAL AppIdHAHttpClient* ha_http_client;
+ static THREAD_LOCAL AppIdHATlsHostClient* ha_tls_host_client;
+};
+
+#endif
#include "appid_http_session.h"
+#include "flow/ha.h"
#include "memory/memory_cap.h"
#include "profiler/profiler.h"
{
case REQ_HOST_FID:
change_bits.set(APPID_HOST_BIT);
+ assert(asd.flow);
+ if (asd.flow->ha_state)
+ asd.flow->ha_state->add(FlowHAState::MODIFIED | FlowHAState::MAJOR);
break;
case MISC_URL_FID:
change_bits.set(APPID_URL_BIT);
+ assert(asd.flow);
+ if (asd.flow->ha_state)
+ asd.flow->ha_state->add(FlowHAState::MODIFIED | FlowHAState::MAJOR);
break;
case REQ_AGENT_FID:
change_bits.set(APPID_USERAGENT_BIT);
}
}
-void AppIdHttpSession::set_client(AppId app_id, AppidChangeBits& change_bits, const char* type,
- const char* version)
+void AppIdHttpSession::set_client(AppId app_id, AppidChangeBits& change_bits,
+ const char* type, const char* version)
{
if (app_id <= APP_ID_NONE or (app_id == client.get_id()))
return;
client.set_id(app_id);
change_bits.set(APPID_CLIENT_BIT);
+ assert(asd.flow);
+ if (asd.flow->ha_state)
+ asd.flow->ha_state->add(FlowHAState::MODIFIED | FlowHAState::MAJOR);
if (version)
{
client.set_version(version);
}
}
-void AppIdHttpSession::set_payload(AppId app_id, AppidChangeBits& change_bits, const char* type,
- const char* version)
+void AppIdHttpSession::set_payload(AppId app_id, AppidChangeBits& change_bits,
+ const char* type, const char* version)
{
if (app_id == APP_ID_NONE or (app_id == payload.get_id()))
return;
payload.set_id(app_id);
change_bits.set(APPID_PAYLOAD_BIT);
+ assert(asd.flow);
+ if (asd.flow->ha_state)
+ asd.flow->ha_state->add(FlowHAState::MODIFIED | FlowHAState::MAJOR);
payload.set_version(version);
if (appidDebug->is_active())
void clear_all_fields();
void set_client(AppId, AppidChangeBits&, const char*, const char* version = nullptr);
- void set_payload(AppId, AppidChangeBits&, const char* type = nullptr, const char* version = nullptr);
+ void set_payload(AppId, AppidChangeBits&, const char* type = nullptr,
+ const char* version = nullptr);
void set_referred_payload(AppId, AppidChangeBits&);
uint32_t get_http2_stream_id() const
#include "appid_dcerpc_event_handler.h"
#include "appid_debug.h"
#include "appid_discovery.h"
+#include "appid_ha.h"
#include "appid_http_event_handler.h"
#include "appid_peg_counts.h"
#include "appid_session.h"
pkt_thread_tp_appid_ctxt->tinit();
if (ctxt->config.log_all_sessions)
appidDebug->set_enabled(true);
+ if ( snort::HighAvailabilityManager::active() )
+ AppIdHAManager::tinit();
}
void AppIdInspector::tterm()
odp_thread_local_ctxt = nullptr;
if (pkt_thread_tp_appid_ctxt)
pkt_thread_tp_appid_ctxt->tfini();
+ if ( snort::HighAvailabilityManager::active() )
+ AppIdHAManager::tterm();
}
void AppIdInspector::eval(Packet* p)
void AppIdSession::set_ss_application_ids(AppId service_id, AppId client_id, AppId payload_id,
AppId misc_id, AppId referred_id, AppidChangeBits& change_bits)
{
- api.set_ss_application_ids(service_id, client_id, payload_id, misc_id, referred_id, change_bits);
+ assert(flow);
+ api.set_ss_application_ids(service_id, client_id, payload_id, misc_id, referred_id, change_bits, *flow);
}
void AppIdSession::set_ss_application_ids(AppId client_id, AppId payload_id,
AppidChangeBits& change_bits)
{
- api.set_ss_application_ids(client_id, payload_id, change_bits);
+ assert(flow);
+ api.set_ss_application_ids(client_id, payload_id, change_bits, *flow);
}
void AppIdSession::set_application_ids_service(AppId service_id, AppidChangeBits& change_bits)
{
- api.set_application_ids_service(service_id, change_bits);
+ assert(flow);
+ api.set_application_ids_service(service_id, change_bits, *flow);
}
void AppIdSession::reset_session_data(AppidChangeBits& change_bits)
api.published = true;
}
+ if (consumed_ha_data)
+ {
+ AppIdHttpSession* hsession = get_http_session();
+ if (hsession)
+ {
+ if (hsession->get_field(MISC_URL_FID))
+ change_bits.set(APPID_URL_BIT);
+ if (hsession->get_field(REQ_HOST_FID))
+ change_bits.set(APPID_HOST_BIT);
+ }
+
+ if (api.get_tls_host())
+ change_bits.set(APPID_TLSHOST_BIT);
+
+ consumed_ha_data = false;
+ }
+
if (change_bits.none())
return;
api.set_tls_host(tsession->get_tls_host());
}
+ void set_tls_host(const char* tls_host)
+ {
+ api.set_tls_host(tls_host);
+ }
+
OdpContext& get_odp_ctxt() const
{
return odp_ctxt;
api.clear_user_logged_in();
}
+ void set_consumed_ha_data(bool val)
+ {
+ consumed_ha_data = val;
+ }
+
private:
uint16_t prev_http2_raw_packet = 0;
OdpContext& odp_ctxt;
uint32_t odp_ctxt_version;
ThirdPartyAppIdContext* tp_appid_ctxt = nullptr;
+ bool consumed_ha_data = false;
};
#endif
#include "appid_session_api.h"
+#include "flow/ha.h"
#include "managers/inspector_manager.h"
#include "appid_inspector.h"
#include "appid_session.h"
}
void AppIdSessionApi::set_ss_application_ids(AppId service_id, AppId client_id,
- AppId payload_id, AppId misc_id, AppId referred_id, AppidChangeBits& change_bits)
+ AppId payload_id, AppId misc_id, AppId referred_id, AppidChangeBits& change_bits, Flow& flow)
{
if (application_ids[APP_PROTOID_SERVICE] != service_id)
{
application_ids[APP_PROTOID_SERVICE] = service_id;
change_bits.set(APPID_SERVICE_BIT);
+ if (flow.ha_state)
+ flow.ha_state->add(FlowHAState::MODIFIED | FlowHAState::MAJOR);
}
if (application_ids[APP_PROTOID_CLIENT] != client_id)
{
application_ids[APP_PROTOID_CLIENT] = client_id;
change_bits.set(APPID_CLIENT_BIT);
+ if (flow.ha_state)
+ flow.ha_state->add(FlowHAState::MODIFIED | FlowHAState::MAJOR);
}
if (application_ids[APP_PROTOID_PAYLOAD] != payload_id)
{
application_ids[APP_PROTOID_PAYLOAD] = payload_id;
change_bits.set(APPID_PAYLOAD_BIT);
+ if (flow.ha_state)
+ flow.ha_state->add(FlowHAState::MODIFIED | FlowHAState::MAJOR);
}
if (application_ids[APP_PROTOID_MISC] != misc_id)
{
application_ids[APP_PROTOID_MISC] = misc_id;
change_bits.set(APPID_MISC_BIT);
+ if (flow.ha_state)
+ flow.ha_state->add(FlowHAState::MODIFIED | FlowHAState::MAJOR);
}
if (application_ids[APP_PROTOID_REFERRED] != referred_id)
{
}
void AppIdSessionApi::set_ss_application_ids(AppId client_id, AppId payload_id,
- AppidChangeBits& change_bits)
+ AppidChangeBits& change_bits, Flow& flow)
{
if (application_ids[APP_PROTOID_CLIENT] != client_id)
{
application_ids[APP_PROTOID_CLIENT] = client_id;
change_bits.set(APPID_CLIENT_BIT);
+ if (flow.ha_state)
+ flow.ha_state->add(FlowHAState::MODIFIED | FlowHAState::MAJOR);
}
if (application_ids[APP_PROTOID_PAYLOAD] != payload_id)
{
application_ids[APP_PROTOID_PAYLOAD] = payload_id;
change_bits.set(APPID_PAYLOAD_BIT);
+ if (flow.ha_state)
+ flow.ha_state->add(FlowHAState::MODIFIED | FlowHAState::MAJOR);
}
}
-void AppIdSessionApi::set_application_ids_service(AppId service_id, AppidChangeBits& change_bits)
+void AppIdSessionApi::set_application_ids_service(AppId service_id, AppidChangeBits& change_bits,
+ Flow& flow)
{
if (application_ids[APP_PROTOID_SERVICE] != service_id)
{
application_ids[APP_PROTOID_SERVICE] = service_id;
change_bits.set(APPID_SERVICE_BIT);
+ if (flow.ha_state)
+ flow.ha_state->add(FlowHAState::MODIFIED | FlowHAState::MAJOR);
}
}
static THREAD_LOCAL uint32_t appid_flow_data_id;
void set_ss_application_ids(AppId service, AppId client, AppId payload, AppId misc,
- AppId referred, AppidChangeBits& change_bits);
- void set_ss_application_ids(AppId client, AppId payload, AppidChangeBits& change_bits);
- void set_application_ids_service(AppId service_id, AppidChangeBits& change_bits);
+ AppId referred, AppidChangeBits& change_bits, Flow& flow);
+ void set_ss_application_ids(AppId client, AppId payload, AppidChangeBits& change_bits, Flow& flow);
+ void set_application_ids_service(AppId service_id, AppidChangeBits& change_bits, Flow& flow);
AppIdHttpSession* get_hsession(uint32_t stream_index = 0) const;
CHECK_EQUAL(id, 1492);
}
-TEST(appid_api, produce_ha_state)
-{
- AppIdSessionHA appHA, cmp_buf;
-
- memset((void*)&appHA, 0, sizeof(appHA));
- memset((void*)&cmp_buf, 0, sizeof(cmp_buf));
- mock_session->flags |= APPID_SESSION_SERVICE_DETECTED | APPID_SESSION_HTTP_SESSION;
-
- mock_session->set_tp_app_id(APPID_UT_ID);
- mock_session->set_service_id(APPID_UT_ID + 1, stub_odp_ctxt);
- mock_session->client_inferred_service_id = APPID_UT_ID + 2;
- mock_session->set_port_service_id(APPID_UT_ID + 3);
- mock_session->set_payload_id(APPID_UT_ID + 4);
- mock_session->set_tp_payload_app_id(APPID_UT_ID + 5);
- mock_session->set_client_id(APPID_UT_ID + 6);
- mock_session->misc_app_id = APPID_UT_ID + 7;
-
- uint32_t val = appid_api.produce_ha_state(*flow, (uint8_t*)&appHA);
- CHECK_TRUE(val == sizeof(appHA));
- CHECK_TRUE(appHA.appId[0] == APPID_UT_ID);
- CHECK_TRUE(appHA.appId[1] == APPID_UT_ID + 1);
- CHECK_TRUE(appHA.appId[2] == APPID_UT_ID + 2);
- CHECK_TRUE(appHA.appId[3] == APPID_UT_ID + 3);
- CHECK_TRUE(appHA.appId[4] == APPID_UT_ID + 4);
- CHECK_TRUE(appHA.appId[5] == APPID_UT_ID + 5);
- CHECK_TRUE(appHA.appId[6] == APPID_UT_ID + 6);
- CHECK_TRUE(appHA.appId[7] == APPID_UT_ID + 7);
- CHECK_TRUE(appHA.flags == (APPID_HA_FLAGS_APP | APPID_HA_FLAGS_TP_DONE
- | APPID_HA_FLAGS_SVC_DONE | APPID_HA_FLAGS_HTTP));
-
- mock_flow_data= nullptr;
- SfIp ip;
- ip.pton(AF_INET, "192.168.1.222");
- val = appid_api.consume_ha_state(*flow, (uint8_t*)&appHA, 0, IpProtocol::TCP, &ip, 1066);
- CHECK_TRUE(val == sizeof(appHA));
-
- AppIdSession* session = (AppIdSession*)flow->get_flow_data(AppIdSession::inspector_id);
- CHECK_TRUE(session);
- CHECK_TRUE(session->get_tp_app_id() == appHA.appId[0]);
- CHECK_TRUE(session->get_service_id() == appHA.appId[1]);
- CHECK_TRUE(session->client_inferred_service_id == appHA.appId[2]);
- CHECK_TRUE(session->get_port_service_id() == appHA.appId[3]);
- CHECK_TRUE(session->get_payload_id() == appHA.appId[4]);
- CHECK_TRUE(session->get_tp_payload_app_id() == appHA.appId[5]);
- CHECK_TRUE(session->get_client_id() == appHA.appId[6]);
- CHECK_TRUE(session->misc_app_id == appHA.appId[7]);
- CHECK_TRUE(session->service_disco_state == APPID_DISCO_STATE_FINISHED);
- CHECK_TRUE(session->client_disco_state == APPID_DISCO_STATE_FINISHED);
- delete &session->get_api();
- delete session;
-
- // test logic when service app is ftp control
- appHA.appId[1] = APP_ID_FTP_CONTROL;
- mock_flow_data= nullptr;
- val = appid_api.consume_ha_state(*flow, (uint8_t*)&appHA, 0, IpProtocol::TCP, &ip, 1066);
- CHECK_TRUE(val == sizeof(appHA));
-
- session = (AppIdSession*)flow->get_flow_data(AppIdSession::inspector_id);
- CHECK_TRUE(session);
- uint64_t flags = session->get_session_flags(APPID_SESSION_CLIENT_DETECTED |
- APPID_SESSION_NOT_A_SERVICE | APPID_SESSION_SERVICE_DETECTED);
- CHECK_TRUE(flags == (APPID_SESSION_CLIENT_DETECTED | APPID_SESSION_NOT_A_SERVICE
- | APPID_SESSION_SERVICE_DETECTED));
- CHECK_TRUE(session->get_service_id() == APP_ID_FTP_CONTROL);
- CHECK_TRUE(session->service_disco_state == APPID_DISCO_STATE_STATEFUL);
- CHECK_TRUE(session->client_disco_state == APPID_DISCO_STATE_FINISHED);
- delete &session->get_api();
- delete session;
-
- flow->set_flow_data(nullptr);
- uint32_t val1 = appid_api.produce_ha_state(*flow, (uint8_t*)&appHA);
- CHECK_TRUE(val1 == sizeof(appHA));
- CHECK_TRUE(appHA.flags == 0);
-
- val = appid_api.consume_ha_state(*flow, (uint8_t*)&appHA, 0, IpProtocol::TCP, &ip, 1066);
- CHECK_TRUE(val == sizeof(appHA));
- session = (AppIdSession*)flow->get_flow_data(AppIdSession::inspector_id);
- CHECK(session == nullptr);
-}
-
TEST(appid_api, ssl_app_group_id_lookup)
{
mock().expectNCalls(4, "publish");
StashGenericObject(STASH_GENERIC_OBJECT_APPID) {}
}
+void FlowHAState::add(uint8_t) { }
void ApplicationDescriptor::set_id(const Packet&, AppIdSession&, AppidSessionDirection, AppId, AppidChangeBits&) { }
const char* AppInfoManager::get_app_name(AppId)
{
static AppIdContext stub_ctxt(stub_config);
static OdpContext stub_odp_ctxt(stub_config, nullptr);
OdpContext* AppIdContext::odp_ctxt = &stub_odp_ctxt;
+static Flow flow;
// AppIdSession mock functions
AppIdSession::AppIdSession(IpProtocol, const SfIp* ip, uint16_t, AppIdInspector& inspector,
{
SfIp sfip;
session = new AppIdSession(IpProtocol::IP, &sfip, 0, dummy_appid_inspector, stub_odp_ctxt);
+ session->flow = &flow;
mock_hsession = new AppIdHttpSession(*session, 0);
appidDebug = new AppIdDebug();
}
// in appid_http_session.h.
AppidChangeBits change_bits;
- mock_hsession->set_field( (HttpFieldIds)0, new std::string("agent"), change_bits );
- mock_hsession->set_field( (HttpFieldIds)1, new std::string("host"), change_bits );
- mock_hsession->set_field( (HttpFieldIds)2, new std::string("referer"), change_bits );
- mock_hsession->set_field( (HttpFieldIds)3, new std::string("uri"), change_bits );
- mock_hsession->set_field( (HttpFieldIds)4, new std::string("cookie"), change_bits );
- mock_hsession->set_field( (HttpFieldIds)5, new std::string("req_body"), change_bits );
- mock_hsession->set_field( (HttpFieldIds)6, new std::string("content_type"), change_bits );
- mock_hsession->set_field( (HttpFieldIds)7, new std::string("location"), change_bits );
- mock_hsession->set_field( (HttpFieldIds)8, new std::string("rsp_body"), change_bits );
- mock_hsession->set_field( (HttpFieldIds)9, new std::string("via"), change_bits );
- mock_hsession->set_field( (HttpFieldIds)10, new std::string("response_code"), change_bits );
- mock_hsession->set_field( (HttpFieldIds)11, new std::string("server"), change_bits );
- mock_hsession->set_field( (HttpFieldIds)12, new std::string("xww"), change_bits );
- mock_hsession->set_field( (HttpFieldIds)13, new std::string("url"), change_bits );
+ mock_hsession->set_field( (HttpFieldIds)0, new std::string("agent"), change_bits);
+ mock_hsession->set_field( (HttpFieldIds)1, new std::string("host"), change_bits);
+ mock_hsession->set_field( (HttpFieldIds)2, new std::string("referer"), change_bits);
+ mock_hsession->set_field( (HttpFieldIds)3, new std::string("uri"), change_bits);
+ mock_hsession->set_field( (HttpFieldIds)4, new std::string("cookie"), change_bits);
+ mock_hsession->set_field( (HttpFieldIds)5, new std::string("req_body"), change_bits);
+ mock_hsession->set_field( (HttpFieldIds)6, new std::string("content_type"), change_bits);
+ mock_hsession->set_field( (HttpFieldIds)7, new std::string("location"), change_bits);
+ mock_hsession->set_field( (HttpFieldIds)8, new std::string("rsp_body"), change_bits);
+ mock_hsession->set_field( (HttpFieldIds)9, new std::string("via"), change_bits);
+ mock_hsession->set_field( (HttpFieldIds)10, new std::string("response_code"), change_bits);
+ mock_hsession->set_field( (HttpFieldIds)11, new std::string("server"), change_bits);
+ mock_hsession->set_field( (HttpFieldIds)12, new std::string("xww"), change_bits);
+ mock_hsession->set_field( (HttpFieldIds)13, new std::string("url"), change_bits);
const std::string* field;
field = mock_hsession->get_field(REQ_AGENT_FID);
session->set_service_id(APP_ID_HTTP, odp_ctxt);
session->scan_flags |= SCAN_HTTP_HOST_URL_FLAG;
mock_hsession->set_skip_simple_detect(false);
- mock_hsession->set_field( (HttpFieldIds)2, new std::string("referer"), change_bits );
+ mock_hsession->set_field( (HttpFieldIds)2, new std::string("referer"), change_bits);
mock_hsession->process_http_packet(APP_ID_FROM_INITIATOR, change_bits, odp_ctxt.get_http_matchers());
// Detect changes in referred appid
#ifndef APPID_MOCK_SESSION_H
#define APPID_MOCK_SESSION_H
+#include "flow/ha.h"
+
#include "appid_dns_session.h"
#include "appid_mock_flow.h"
#include "appid_mock_http_session.h"
OdpContext::OdpContext(const AppIdConfig&, snort::SnortConfig*) { }
OdpContext::~OdpContext() { }
+void FlowHAState::add(uint8_t) { }
+
static AppIdConfig stub_config;
static AppIdContext stub_ctxt(stub_config);
static OdpContext stub_odp_ctxt(stub_config, nullptr);
AppIdSessionApi* appid_session_api = nullptr;
static AppIdConfig config;
static OdpContext odpctxt(config, nullptr);
+static Flow flow;
void ApplicationDescriptor::set_id(const Packet&, AppIdSession&, AppidSessionDirection, AppId, AppidChangeBits&) { }
void AppIdSession::set_ss_application_ids(AppId service_id, AppId client_id, AppId payload_id,
AppId misc_id, AppId referred_id, AppidChangeBits& change_bits)
{
- api.set_ss_application_ids(service_id, client_id, payload_id, misc_id, referred_id, change_bits);
+ api.set_ss_application_ids(service_id, client_id, payload_id, misc_id, referred_id, change_bits, *flow);
}
void AppIdSession::set_application_ids_service(AppId service_id, AppidChangeBits& change_bits)
{
- api.set_application_ids_service(service_id, change_bits);
+ api.set_application_ids_service(service_id, change_bits, *flow);
}
TEST_GROUP(appid_session_api)
SfIp ip;
mock_session = new AppIdSession(IpProtocol::TCP, &ip, 1492, dummy_appid_inspector, odpctxt);
+ mock_session->flow = &flow;
pkt_thread_odp_ctxt = &mock_session->get_odp_ctxt();
mock_session->set_ss_application_ids(APPID_UT_ID, APPID_UT_ID, APPID_UT_ID,
APPID_UT_ID, APPID_UT_ID, change_bits);
{
SfIp ip;
AppIdSession asd(IpProtocol::TCP, &ip, 1492, dummy_appid_inspector, odpctxt);
+ asd.flow = &flow;
AppidChangeBits change_bits;
asd.set_application_ids_service(APP_ID_HTTP2, change_bits);