From: Russ Combs (rucombs) Date: Fri, 5 Aug 2016 20:22:10 +0000 (-0400) Subject: Merge pull request #580 in SNORT/snort3 from appid_ws2_rule_keyword2 to master X-Git-Tag: 3.0.0-233~312 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fc3a19db26dd5cf8229a2ad36ee3ff29b49f400b;p=thirdparty%2Fsnort3.git Merge pull request #580 in SNORT/snort3 from appid_ws2_rule_keyword2 to master Squashed commit of the following: commit fad89647036423353ff11e50750149e39e6f8d5b Author: Steve Chew Date: Wed Aug 3 14:06:23 2016 -0400 Implement Module and IpsOption subclasses for appid rule option. Add appid support to flow for caching application ids, implement eval function of appid rule option implement operator== for appid ips option fix hash & operator== methods to use appid option data correctly, add assert and change parameters to ref on stream api application id methods fix sort compare to only return true when lhsid mapping a helper function move get/set_application_ids methods from Stream to Flow use AppId type on get/set application ids parameters --- diff --git a/src/flow/flow.cc b/src/flow/flow.cc index 5a70c46f4..d83bf7337 100644 --- a/src/flow/flow.cc +++ b/src/flow/flow.cc @@ -412,3 +412,20 @@ void Flow::set_ttl(Packet* p, bool client) } } +void Flow::set_application_ids(AppId serviceAppId, AppId clientAppId, + AppId payloadAppId, AppId miscAppId) +{ + application_ids[APP_PROTOID_SERVICE] = serviceAppId; + application_ids[APP_PROTOID_CLIENT] = clientAppId; + application_ids[APP_PROTOID_PAYLOAD] = payloadAppId; + application_ids[APP_PROTOID_MISC] = miscAppId; +} + +void Flow::get_application_ids(AppId& serviceAppId, AppId& clientAppId, + AppId& payloadAppId, AppId& miscAppId) +{ + serviceAppId = application_ids[APP_PROTOID_SERVICE]; + clientAppId = application_ids[APP_PROTOID_CLIENT]; + payloadAppId = application_ids[APP_PROTOID_PAYLOAD]; + miscAppId = application_ids[APP_PROTOID_MISC]; +} diff --git a/src/flow/flow.h b/src/flow/flow.h index a808916d8..058e75f0f 100644 --- a/src/flow/flow.h +++ b/src/flow/flow.h @@ -84,6 +84,18 @@ #define STREAM_STATE_IGNORE 0x1000 #define STREAM_STATE_NO_PICKUP 0x2000 +// FIXIT-L: move to appid class if/when the application ids array +// is moved +typedef int32_t AppId; +enum AppProtoIdIndex +{ + APP_PROTOID_SERVICE, + APP_PROTOID_CLIENT, + APP_PROTOID_PAYLOAD, + APP_PROTOID_MISC, + APP_PROTOID_MAX +}; + struct Packet; typedef void (* StreamAppDataFree)(void*); @@ -152,17 +164,16 @@ public: void free_application_data(uint32_t proto); void free_application_data(FlowData*); void free_application_data(); - + void set_application_ids(AppId serviceAppId, AppId clientAppId, + AppId payloadAppId, AppId miscAppId); + void get_application_ids(AppId& serviceAppId, AppId& clientAppId, + AppId& payloadAppId, AppId& miscAppId); void call_handlers(Packet* p, bool eof = false); - void markup_packet_flags(Packet*); - void set_direction(Packet*); - void set_expire(const Packet*, uint32_t timeout); int get_expire(const Packet*); bool expired(const Packet*); - void set_ttl(Packet*, bool client); uint32_t update_session_flags( uint32_t flags ) @@ -326,6 +337,9 @@ public: // FIXIT-M privatize if possible uint8_t response_count; bool disable_inspect; + // FIXIT-L: if appid is only consumer of this move to appid + AppId application_ids[APP_PROTOID_MAX]; + public: LwState ssn_state; LwState previous_ssn_state; diff --git a/src/network_inspectors/appid/CMakeLists.txt b/src/network_inspectors/appid/CMakeLists.txt index c316def4b..a07d58b12 100644 --- a/src/network_inspectors/appid/CMakeLists.txt +++ b/src/network_inspectors/appid/CMakeLists.txt @@ -158,6 +158,7 @@ set ( APPID_SOURCES host_port_app_cache.cc host_port_app_cache.h http_common.h + ips_appid_option.cc length_app_cache.cc length_app_cache.h lua_detector_api.cc diff --git a/src/network_inspectors/appid/Makefile.am b/src/network_inspectors/appid/Makefile.am index dbc930cb0..52c28bdc2 100644 --- a/src/network_inspectors/appid/Makefile.am +++ b/src/network_inspectors/appid/Makefile.am @@ -154,6 +154,7 @@ fw_appid.h \ host_port_app_cache.cc \ host_port_app_cache.h \ http_common.h \ +ips_appid_option.cc \ length_app_cache.cc \ length_app_cache.h \ lua_detector_api.cc \ diff --git a/src/network_inspectors/appid/app_info_table.cc b/src/network_inspectors/appid/app_info_table.cc index 500691216..aec36c01f 100644 --- a/src/network_inspectors/appid/app_info_table.cc +++ b/src/network_inspectors/appid/app_info_table.cc @@ -231,11 +231,11 @@ void* appNameHashFind(SFGHASH* appNameHash, const char* appName) static void appIdConfLoad(const char* path); -static unsigned int getAppIdStaticIndex(AppId appid) +static AppId getAppIdStaticIndex(AppId appid) { if (appid > 0 && appid < SF_APPID_BUILDIN_MAX) return appid; - if (appid >= SF_APPID_CSD_MIN && appid < SF_APPID_CSD_MIN+(SF_APPID_MAX-SF_APPID_BUILDIN_MAX)) + if (appid >= SF_APPID_CSD_MIN && appid < SF_APPID_CSD_MIN + (SF_APPID_MAX - SF_APPID_BUILDIN_MAX)) return (SF_APPID_BUILDIN_MAX + appid - SF_APPID_CSD_MIN); return 0; } diff --git a/src/network_inspectors/appid/appid_api.cc b/src/network_inspectors/appid/appid_api.cc index d4dd79d72..f6e35852d 100644 --- a/src/network_inspectors/appid/appid_api.cc +++ b/src/network_inspectors/appid/appid_api.cc @@ -611,85 +611,3 @@ uint32_t getDNSTTL(AppIdData* appIdData) return 0; } -static AppIdApi appIdDispatchTable = -{ - appGetAppName, - appGetAppId, - - getServiceAppId, - getPorServiceAppId, - getOnlyServiceAppId, - getMiscAppId, - getClientAppId, - getPayloadAppId, - getReferredAppId, - getFwServiceAppId, - getFwMiscAppId, - getFwClientAppId, - getFwPayloadAppId, - getFwReferredAppId, - - isSessionSslDecrypted, - IsAppIdInspectingSession, - isAppIdAvailable, - - getUserName, - getClientVersion, - - getAppIdSessionAttribute, - - getFlowType, - getServiceInfo, - getServicePort, - getServiceIp, - getInitiatorIp, - - getHttpUserAgent, - getHttpHost, - getHttpUrl, - getHttpReferer, - getHttpNewUrl, - getHttpUri, - getHttpResponseCode, - getHttpCookie, - getHttpNewCookie, - getHttpContentType, - getHttpLocation, - getHttpBody, - getHttpReqBody, - getHttpUriOffset, - getHttpUriEndOffset, - getHttpCookieOffset, - getHttpCookieEndOffset, - getHttpSearch, - getHttpXffAddr, - - getTlsHost, - - getDhcpFpData, - freeDhcpFpData, - getDhcpInfo, - freeDhcpInfo, - getSmbFpData, - freeSmbFpData, - getNetbiosName, - produceHAState, - consumeHAState, - - getAppIdData, - - getDNSQuery, - getDNSQueryoffset, - getDNSRecordType, - getDNSResponseType, - getDNSTTL, - - getHttpNewField, - freeHttpNewField, -}; - -void appIdApiInit(struct AppIdApi* api) -{ - *api = appIdDispatchTable; -} - diff --git a/src/network_inspectors/appid/appid_api.h b/src/network_inspectors/appid/appid_api.h index 098680a45..be6f93ace 100644 --- a/src/network_inspectors/appid/appid_api.h +++ b/src/network_inspectors/appid/appid_api.h @@ -24,6 +24,8 @@ #include +#include "flow/flow.h" + enum class IpProtocol : uint8_t; #define APPID_SESSION_RESPONDER_MONITORED (1ULL << 0) @@ -38,24 +40,19 @@ enum class IpProtocol : uint8_t; #define APPID_SESSION_MID (1ULL << 9) #define APPID_SESSION_OOO (1ULL << 10) #define APPID_SESSION_SYN_RST (1ULL << 11) - /**Service missed the first UDP packet in a flow. This causes detectors to see traffic in reverse direction. * Detectors should set this flag by verifying that packet from initiator is indeed a packet from responder. * Setting this flag without this check will cause RNA to not try other detectors in some cases (see bug 77551).*/ #define APPID_SESSION_UDP_REVERSED (1ULL << 12) #define APPID_SESSION_HTTP_SESSION (1ULL << 13) - /**Service protocol was detected */ #define APPID_SESSION_SERVICE_DETECTED (1ULL << 14) - /**Finsihed with client app detection */ #define APPID_SESSION_CLIENT_DETECTED (1ULL << 15) /**Flow is a data connection not a service */ #define APPID_SESSION_NOT_A_SERVICE (1ULL << 16) - #define APPID_SESSION_DECRYPTED (1ULL << 17) #define APPID_SESSION_SERVICE_DELETED (1ULL << 18) - //The following attributes are references only with appId /**Continue calling the routine after the service has been identified. */ #define APPID_SESSION_CONTINUE (1ULL << 19) @@ -65,43 +62,33 @@ enum class IpProtocol : uint8_t; #define APPID_SESSION_INCOMPATIBLE (1ULL << 21) /**we are ready to see out of network Server packets */ #define APPID_SESSION_CLIENT_GETS_SERVER_PACKETS (1ULL << 22) - #define APPID_SESSION_DISCOVER_APP (1ULL << 23) - #define APPID_SESSION_PORT_SERVICE_DONE (1ULL << 24) #define APPID_SESSION_ADDITIONAL_PACKET (1ULL << 25) #define APPID_SESSION_RESPONDER_CHECKED (1ULL << 26) #define APPID_SESSION_INITIATOR_CHECKED (1ULL << 27) #define APPID_SESSION_SSL_SESSION (1ULL << 28) #define APPID_SESSION_LOGIN_SUCCEEDED (1ULL << 29) - #define APPID_SESSION_SPDY_SESSION (1ULL << 30) #define APPID_SESSION_ENCRYPTED (1ULL << 31) - #define APPID_SESSION_APP_REINSPECT (1ULL << 32) #define APPID_SESSION_RESPONSE_CODE_CHECKED (1ULL << 33) #define APPID_SESSION_REXEC_STDERR (1ULL << 34) #define APPID_SESSION_CHP_INSPECTING (1ULL << 35) #define APPID_SESSION_STICKY_SERVICE (1ULL << 36) #define APPID_SESSION_APP_REINSPECT_SSL (1ULL << 37) - #define APPID_SESSION_NO_TPI (1ULL << 38) #define APPID_SESSION_IGNORE_FLOW (1ULL << 39) #define APPID_SESSION_IGNORE_FLOW_LOGGED (1ULL << 40) - #define APPID_SESSION_OOO_LOGGED (1ULL << 41) #define APPID_SESSION_TPI_OOO_LOGGED (1ULL << 42) - #define APPID_SESSION_EXPECTED_EVALUATE (1ULL << 43) - #define APPID_SESSION_IGNORE_ID_FLAGS (APPID_SESSION_IGNORE_FLOW | \ APPID_SESSION_NOT_A_SERVICE | \ APPID_SESSION_NO_TPI | \ APPID_SESSION_SERVICE_DETECTED | \ APPID_SESSION_PORT_SERVICE_DONE) - -using AppId = int32_t; class AppIdData; enum APPID_FLOW_TYPE @@ -192,83 +179,71 @@ enum HTTP_FIELD_ID // ----------------------------------------------------------------------------- struct sfip_t; -// FIXIT-H J should be class with static methods -struct AppIdApi -{ - const char * (*geApplicationName)(int32_t appId); - AppId (*geApplicationId)(const char* appName); - - AppId (*geServiceAppId)(AppIdData*); - AppId (*getPorServiceAppId)(AppIdData*); - AppId (*getOnlyServiceAppId)(AppIdData*); - AppId (*getMiscAppId)(AppIdData*); - AppId (*getClientAppId)(AppIdData*); - AppId (*getPayloadAppId)(AppIdData*); - AppId (*getReferredAppId)(AppIdData*); - AppId (*getFwServiceAppId)(AppIdData*); - AppId (*getFwMiscAppId)(AppIdData*); - AppId (*getFwClientAppId)(AppIdData*); - AppId (*getFwPayloadAppId)(AppIdData*); - AppId (*getFwReferredAppId)(AppIdData*); - - bool (*isSessionSslDecrypted)(AppIdData*); - bool (*isAppIdInspectingSession)(AppIdData*); - bool (*isAppIdAvailable)(AppIdData*); - - char* (*getUserName)(AppIdData*, AppId* service, bool* isLoginSuccessful); - char* (*geClientVersion)(AppIdData*); - - uint64_t (*getAppIdSessionAttribute)(AppIdData*, uint64_t flag); - APPID_FLOW_TYPE (*getFlowType)(AppIdData*); - void (*geServiceInfo)(AppIdData*, char **serviceVendor, char** serviceVersion, RNAServiceSubtype** subtype); - short (*geServicePort)(AppIdData*); - sfip_t* (*geServiceIp)(AppIdData*); - sfip_t* (*getInitiatorIp)(AppIdData*); - - char* (*getHttpUserAgent)(AppIdData*); - char* (*getHttpHost)(AppIdData*); - char* (*getHttpUrl)(AppIdData*); - char* (*getHttpReferer)(AppIdData*); - char* (*getHttpNewUrl)(AppIdData*); - char* (*getHttpUri)(AppIdData*); - char* (*getHttpResponseCode)(AppIdData*); - char* (*getHttpCookie)(AppIdData*); - char* (*getHttpNewCookie)(AppIdData*); - char* (*getHttpContentType)(AppIdData*); - char* (*getHttpLocation)(AppIdData*); - char* (*getHttpBody)(AppIdData*); - char* (*getHttpReqBody)(AppIdData*); - uint16_t (*getHttpUriOffset)(AppIdData*); - uint16_t (*getHttpUriEndOffset)(AppIdData*); - uint16_t (*getHttpCookieOffset)(AppIdData*); - uint16_t (*getHttpCookieEndOffset)(AppIdData*); - SEARCH_SUPPORT_TYPE (*getHttpSearch)(AppIdData*); - sfip_t* (*getHttpXffAddr)(AppIdData*); - - char* (*getTlsHost)(AppIdData*); - - DhcpFPData* (*getDhcpFpData)(AppIdData*); - void (*freeDhcpFpData)(AppIdData*, DhcpFPData*); - DHCPInfo* (*getDhcpInfo)(AppIdData*); - void (*freeDhcpInfo)(AppIdData*, DHCPInfo*); - FpSMBData* (*getSmbFpData)(AppIdData*); - void (*freeSmbFpData)(AppIdData*, FpSMBData*); - char* (*getNetbiosName)(AppIdData*); - uint32_t (*produceHAState)(void* lwssn, uint8_t* buf); - uint32_t (*consumeHAState)(void* lwssn, const uint8_t* buf, uint8_t length, IpProtocol proto, sfip_t* ip); - AppIdData* (*getAppIdData)(void* lwssn); - - char* (*getDNSQuery)(AppIdData*, uint8_t* query_len); - uint16_t (*getDNSQueryoffset)(AppIdData*); - uint16_t (*getDNSRecordType)(AppIdData*); - uint8_t (*getDNSResponseType)(AppIdData*); - uint32_t (*getDNSTTL)(AppIdData*); - char* (*getHttpNewField)(AppIdData*, HTTP_FIELD_ID); - void (*freeHttpNewField)(AppIdData*, HTTP_FIELD_ID); +class AppIdApi +{ + const char* getApplicationName(int32_t appId); + AppId getApplicationId(const char* appName); + AppId getServiceAppId(AppIdData*); + AppId getPorServiceAppId(AppIdData*); + AppId getOnlyServiceAppId(AppIdData*); + AppId getMiscAppId(AppIdData*); + AppId getClientAppId(AppIdData*); + AppId getPayloadAppId(AppIdData*); + AppId getReferredAppId(AppIdData*); + AppId getFwServiceAppId(AppIdData*); + AppId getFwMiscAppId(AppIdData*); + AppId getFwClientAppId(AppIdData*); + AppId getFwPayloadAppId(AppIdData*); + AppId getFwReferredAppId(AppIdData*); + bool isSessionSslDecrypted(AppIdData*); + bool isAppIdInspectingSession(AppIdData*); + bool isAppIdAvailable(AppIdData*); + char* getUserName(AppIdData*, AppId* service, bool* isLoginSuccessful); + char* getClientVersion(AppIdData*); + uint64_t getAppIdSessionAttribute(AppIdData*, uint64_t flag); + APPID_FLOW_TYPE getFlowType(AppIdData*); + void getServiceInfo(AppIdData*, char **serviceVendor, char** serviceVersion, RNAServiceSubtype** subtype); + short getServicePort(AppIdData*); + sfip_t* getServiceIp(AppIdData*); + sfip_t* getInitiatorIp(AppIdData*); + char* getHttpUserAgent(AppIdData*); + char* getHttpHost(AppIdData*); + char* getHttpUrl(AppIdData*); + char* getHttpReferer(AppIdData*); + char* getHttpNewUrl(AppIdData*); + char* getHttpUri(AppIdData*); + char* getHttpResponseCode(AppIdData*); + char* getHttpCookie(AppIdData*); + char* getHttpNewCookie(AppIdData*); + char* getHttpContentType(AppIdData*); + char* getHttpLocation(AppIdData*); + char* getHttpBody(AppIdData*); + char* getHttpReqBody(AppIdData*); + uint16_t getHttpUriOffset(AppIdData*); + uint16_t getHttpUriEndOffset(AppIdData*); + uint16_t getHttpCookieOffset(AppIdData*); + uint16_t getHttpCookieEndOffset(AppIdData*); + SEARCH_SUPPORT_TYPE getHttpSearch(AppIdData*); + sfip_t* getHttpXffAddr(AppIdData*); + char* getTlsHost(AppIdData*); + DhcpFPData* getDhcpFpData(AppIdData*); + void freeDhcpFpData(AppIdData*, DhcpFPData*); + DHCPInfo* getDhcpInfo(AppIdData*); + void freeDhcpInfo(AppIdData*, DHCPInfo*); + FpSMBData* getSmbFpData(AppIdData*); + void freeSmbFpData(AppIdData*, FpSMBData*); + char* getNetbiosName(AppIdData*); + uint32_t produceHAState(void* lwssn, uint8_t* buf); + uint32_t consumeHAState(void* lwssn, const uint8_t* buf, uint8_t length, IpProtocol proto, sfip_t* ip); + AppIdData* getAppIdData(void* lwssn); + char* getDNSQuery(AppIdData*, uint8_t* query_len); + uint16_t getDNSQueryoffset(AppIdData*); + uint16_t getDNSRecordType(AppIdData*); + uint8_t getDNSResponseType(AppIdData*); + uint32_t getDNSTTL(AppIdData*); + char* getHttpNewField(AppIdData*, HTTP_FIELD_ID); + void freeHttpNewField(AppIdData*, HTTP_FIELD_ID); }; -// For access when including header -extern AppIdApi appIdApi; - #endif diff --git a/src/network_inspectors/appid/appid_inspector.cc b/src/network_inspectors/appid/appid_inspector.cc index 0a1256fd3..4d1a216f0 100644 --- a/src/network_inspectors/appid/appid_inspector.cc +++ b/src/network_inspectors/appid/appid_inspector.cc @@ -144,9 +144,12 @@ const InspectApi appid_inspector_api = }; #ifdef BUILDING_SO +extern const BaseApi* ips_appid; + SO_PUBLIC const BaseApi* snort_plugins[] = { &appid_inspector_api.base, + ips_appid, nullptr }; #else diff --git a/src/network_inspectors/appid/fw_appid.cc b/src/network_inspectors/appid/fw_appid.cc index b626c6105..a82cbb3cc 100644 --- a/src/network_inspectors/appid/fw_appid.cc +++ b/src/network_inspectors/appid/fw_appid.cc @@ -3066,11 +3066,8 @@ void fwAppIdSearch(Packet* p) #endif } -// FIXIT-M: Need to determine what api to use for this _dpd function -#ifdef REMOVED_WHILE_NOT_IN_USE - _dpd.streamAPI->set_application_id(p->flow, serviceAppId, pickClientAppId(session), + p->flow->set_application_ids(serviceAppId, pickClientAppId(session), payloadAppId, pickMiscAppId(session)); -#endif /* Set the field that the Firewall queries to see if we have a search engine. */ if (session->search_support_type == SEARCH_SUPPORT_TYPE_UNKNOWN && payloadAppId > APP_ID_NONE) diff --git a/src/network_inspectors/appid/ips_appid_option.cc b/src/network_inspectors/appid/ips_appid_option.cc new file mode 100644 index 000000000..44caaa4fe --- /dev/null +++ b/src/network_inspectors/appid/ips_appid_option.cc @@ -0,0 +1,304 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2014-2016 Cisco and/or its affiliates. All rights reserved. +// Copyright (C) 2011-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. +//-------------------------------------------------------------------------- + +// ips_appid_option.cc author: davis mcpherson + +#include // std::mismatch +#include // std::vector +#include // std::pair + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "app_info_table.h" + +#include "main/snort_debug.h" +#include "framework/ips_option.h" +#include "framework/module.h" +#include "framework/parameter.h" +#include "detection/detect.h" +#include "detection/detection_defines.h" +#include "hash/sfhashfcn.h" +#include "log/messages.h" +#include "profiler/profiler.h" +#include "utils/util.h" +#include "stream/stream_api.h" + +//------------------------------------------------------------------------- +// appid option +//------------------------------------------------------------------------- + +#define s_name "appids" +#define s_help \ + "detection option for application ids" + +// these defs are used during matching when the rule option eval function is called to +// control the order in which the different id types are checked +#define PAYLOAD 0 +#define MISC 1 +#define CP_CLIENT 2 +#define CP_SERVICE 3 +#define SP_CLIENT 3 +#define SP_SERVICE 2 +#define NUM_ID_TYPES 4 + +struct AppIdInfo +{ + char *appid_name; + AppId appid_ordinal; +}; + +struct AppIdRuleOptionData +{ + std::vector appid_table; + bool ids_mapped; +}; + +static THREAD_LOCAL ProfileStats appidRuleOptionPerfStats; + +class AppIdIpsOption : public IpsOption +{ +public: + AppIdIpsOption(const AppIdRuleOptionData& c) : + IpsOption(s_name) + { opt_data = c; } + + uint32_t hash() const override; + bool operator==(const IpsOption&) const override; + int eval(Cursor&, Packet*) override; + +private: + void map_names_to_ids(); + int match_id_against_rule( int16_t id ); + + AppIdRuleOptionData opt_data; +}; + +uint32_t AppIdIpsOption::hash() const +{ + uint32_t abc[3]; + + abc[0] = opt_data.appid_table.size(); + abc[1] = 0; + abc[2] = 0; + + mix(abc[0], abc[1], abc[2]); + + for ( auto& appid_info : opt_data.appid_table ) + mix_str(abc[0], abc[1], abc[2], + appid_info.appid_name, strlen(appid_info.appid_name) ); + + finalize(abc[0], abc[1], abc[2]); + + return abc[2]; +} + +bool AppIdIpsOption::operator==(const IpsOption& ips) const +{ + if ( !IpsOption::operator==(ips) ) + return false; + + const AppIdIpsOption& rhs = (AppIdIpsOption&)ips; + + if( opt_data.appid_table.size() != rhs.opt_data.appid_table.size() ) + return false; + + for(unsigned i = 0; i < opt_data.appid_table.size(); i++) + if( strcmp(opt_data.appid_table[i].appid_name, rhs.opt_data.appid_table[i].appid_name) != 0) + return false; + + return true; +} + +void AppIdIpsOption::map_names_to_ids() +{ + for (auto& appid_info : opt_data.appid_table) + appid_info.appid_ordinal = appGetAppId(appid_info.appid_name); + + opt_data.ids_mapped = true; +} + +int AppIdIpsOption::match_id_against_rule( int16_t id ) +{ + for ( auto& appid_info : opt_data.appid_table ) + if( id == appid_info.appid_ordinal ) + return id; + + return 0; +} + +// to determine if the application ids in the rule match the flow get the current +// ids for payload/misc/service/client and compare against ids defined on the rule +// first match wins... +int AppIdIpsOption::eval(Cursor&, Packet* p) +{ + AppId app_ids[NUM_ID_TYPES]; + + assert(p->flow); + Profile profile(appidRuleOptionPerfStats); + + if( !opt_data.ids_mapped ) + map_names_to_ids(); + + // id order on stream api call is: service, client, payload, misc + if ((p->packet_flags & PKT_FROM_CLIENT)) + p->flow->get_application_ids(app_ids[CP_SERVICE], app_ids[CP_CLIENT], + app_ids[PAYLOAD], app_ids[MISC] ); + else + p->flow->get_application_ids(app_ids[SP_SERVICE], app_ids[SP_CLIENT], + app_ids[PAYLOAD], app_ids[MISC] ); + + for( unsigned i = 0; i < NUM_ID_TYPES; i++ ) + if( match_id_against_rule(app_ids[i]) ) + return DETECTION_OPTION_MATCH; + + return DETECTION_OPTION_NO_MATCH; +} + +//------------------------------------------------------------------------- +// appid rule option module +//------------------------------------------------------------------------- + +static const Parameter s_params[] = +{ + { "~", Parameter::PT_STRING, nullptr, nullptr, "appid option" }, + { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } +}; + +bool compare_appid_names(const AppIdInfo& l, const AppIdInfo& r ) +{ + int rc = strcmp(l.appid_name, r.appid_name); + if( rc < 0 ) + return true; + else + return false; +} + +class AppIdOptionModule : public Module +{ +public: + AppIdOptionModule() : Module(s_name, s_help, s_params) { } + + bool begin(const char*, int, SnortConfig*) override; + bool set(const char*, Value&, SnortConfig*) override; + bool end(const char*, int, SnortConfig*) override; + + ProfileStats* get_profile() const override + { return &appidRuleOptionPerfStats; } + + AppIdRuleOptionData opt_data; +}; + +bool AppIdOptionModule::begin(const char*, int, SnortConfig*) +{ + opt_data.appid_table.clear(); + opt_data.ids_mapped = false; + return true; +} + +bool AppIdOptionModule::set(const char*, Value& v, SnortConfig*) +{ + if ( !v.is("~") ) + return false; + + v.set_first_token(); + std::string tok; + + while ( v.get_next_token(tok) ) + { + AppIdInfo appid_info; + + if ( tok[0] == '"' ) + tok.erase(0, 1); + + if ( tok[tok.length()-1] == '"' ) + tok.erase(tok.length()-1, 1); + + appid_info.appid_name = snort_strdup(tok.c_str()); + appid_info.appid_ordinal = 0; + opt_data.appid_table.push_back(appid_info); + } + + return true; +} + +bool AppIdOptionModule::end(const char*, int, SnortConfig*) +{ + std::sort( opt_data.appid_table.begin(), opt_data.appid_table.end(), compare_appid_names); + return true; +} + +//------------------------------------------------------------------------- +// appid option api methods +//------------------------------------------------------------------------- + +static Module* appid_option_mod_ctor() +{ + return new AppIdOptionModule; +} + +static void appid_option_mod_dtor(Module* m) +{ + delete m; +} + +static IpsOption* appid_option_ips_ctor(Module* p, OptTreeNode*) +{ + AppIdOptionModule* m = (AppIdOptionModule*)p; + return new AppIdIpsOption(m->opt_data); +} + +static void appid_option_ips_dtor(IpsOption* p) +{ + delete p; +} + +static const IpsApi appid_option_api = +{ + { + PT_IPS_OPTION, + sizeof(IpsApi), + IPSAPI_VERSION, + 0, + API_RESERVED, + API_OPTIONS, + s_name, + s_help, + appid_option_mod_ctor, + appid_option_mod_dtor + }, + OPT_TYPE_DETECTION, + 0, PROTO_BIT__TCP | PROTO_BIT__UDP, + nullptr, + nullptr, + nullptr, + nullptr, + appid_option_ips_ctor, + appid_option_ips_dtor, + nullptr +}; + +//------------------------------------------------------------------------- +// plugin +//------------------------------------------------------------------------- + +// added to snort_plugins in appid_inspector.cc +const BaseApi* ips_appid = &appid_option_api.base; + diff --git a/src/network_inspectors/appid/test/appid_tests.cc b/src/network_inspectors/appid/test/appid_tests.cc index 2719aaee2..03c3d613e 100644 --- a/src/network_inspectors/appid/test/appid_tests.cc +++ b/src/network_inspectors/appid/test/appid_tests.cc @@ -739,8 +739,6 @@ static void appIdTestSetup(void) _dpd.streamAPI = &streamAPI; _dpd.searchAPI = &searchAPI; - - appIdApiInit(&appIdApi); } static void sessionTcaseSetup(void) diff --git a/src/network_inspectors/appid/test/process_http_test.cc b/src/network_inspectors/appid/test/process_http_test.cc index 6d51fcdaa..fe67946c2 100644 --- a/src/network_inspectors/appid/test/process_http_test.cc +++ b/src/network_inspectors/appid/test/process_http_test.cc @@ -71,7 +71,6 @@ static void appIdTestSetup() _dpd.searchAPI = &searchAPI; #endif - appIdApiInit(&appIdApi); } #ifdef REMOVED_WHILE_NOT_IN_USE diff --git a/src/service_inspectors/service_inspectors.cc b/src/service_inspectors/service_inspectors.cc index 1f57bd50a..0b51f7b64 100644 --- a/src/service_inspectors/service_inspectors.cc +++ b/src/service_inspectors/service_inspectors.cc @@ -34,6 +34,7 @@ extern const BaseApi* ips_ssl_state; extern const BaseApi* ips_ssl_version; #ifdef STATIC_INSPECTORS +extern const BaseApi* ips_appid; extern const BaseApi* ips_dce_iface; extern const BaseApi* ips_dce_opnum; extern const BaseApi* ips_dce_stub_data; @@ -82,6 +83,7 @@ const BaseApi* service_inspectors[] = ips_ssl_version, #ifdef STATIC_INSPECTORS + ips_appid, ips_dce_iface, ips_dce_opnum, ips_dce_stub_data,