]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #580 in SNORT/snort3 from appid_ws2_rule_keyword2 to master
authorRuss Combs (rucombs) <rucombs@cisco.com>
Fri, 5 Aug 2016 20:22:10 +0000 (16:22 -0400)
committerRuss Combs (rucombs) <rucombs@cisco.com>
Fri, 5 Aug 2016 20:22:10 +0000 (16:22 -0400)
Squashed commit of the following:

commit fad89647036423353ff11e50750149e39e6f8d5b
Author: Steve Chew <stechew@cisco.com>
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 lhs<rhs, refactor appids option eval function to streamline matching algorithm, make name->id mapping a helper function

    move get/set_application_ids methods from Stream to Flow

    use AppId type on get/set application ids parameters

13 files changed:
src/flow/flow.cc
src/flow/flow.h
src/network_inspectors/appid/CMakeLists.txt
src/network_inspectors/appid/Makefile.am
src/network_inspectors/appid/app_info_table.cc
src/network_inspectors/appid/appid_api.cc
src/network_inspectors/appid/appid_api.h
src/network_inspectors/appid/appid_inspector.cc
src/network_inspectors/appid/fw_appid.cc
src/network_inspectors/appid/ips_appid_option.cc [new file with mode: 0644]
src/network_inspectors/appid/test/appid_tests.cc
src/network_inspectors/appid/test/process_http_test.cc
src/service_inspectors/service_inspectors.cc

index 5a70c46f43feb8d29df7ce2ee392fe1289a357e4..d83bf73371d3e24958ca8762cf9ac3f4f719f65a 100644 (file)
@@ -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];
+}
index a808916d82ac1ec0b8c9ef6ed22081d53e09a8c3..058e75f0fdfad82e29947500a87046bdd0316959 100644 (file)
 #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;
index c316def4bab6fb08658d3318edd2d89933af2524..a07d58b12dd6ea3d3d7392c757d590b4e064fc48 100644 (file)
@@ -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
index dbc930cb0c3e8dec1814e8503f43e26118a9e424..52c28bdc29a0b5514142219161dd42d4669f4151 100644 (file)
@@ -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 \
index 500691216f86ff68040887a3ef102c96f0e65f83..aec36c01ffbcf6a25cecc52bf995c892a14e5792 100644 (file)
@@ -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;
 }
index d4dd79d7241033a1b38309dca1f25da93683077b..f6e35852d4e3f54c16996554d47feabde59160ee 100644 (file)
@@ -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;
-}
-
index 098680a45d78202287d517c808a2dc794dae75dc..be6f93acef155a426233ec9154af305abd2637b0 100644 (file)
@@ -24,6 +24,8 @@
 
 #include <cstdint>
 
+#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
index 0a1256fd38829613925e5283d88a0e6c6d20d81c..4d1a216f09ae5f9d075dec3617ffc59c093ffa3b 100644 (file)
@@ -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
index b626c61056413fe8a6eba05b0b90a3027f41a440..a82cbb3ccaee466dc0c233ca7f329f200ab282b5 100644 (file)
@@ -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 (file)
index 0000000..44caaa4
--- /dev/null
@@ -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 <davmcphe@cisco.com>
+
+#include <algorithm>    // std::mismatch
+#include <vector>       // std::vector
+#include <utility>      // 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<AppIdInfo> 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;
+
index 2719aaee247407d8d7aeb7fb63a3ebebbc64e746..03c3d613ea95dc23e361434eb2e6a9b4b45e2cad 100644 (file)
@@ -739,8 +739,6 @@ static void appIdTestSetup(void)
     _dpd.streamAPI = &streamAPI;
 
     _dpd.searchAPI = &searchAPI;
-
-    appIdApiInit(&appIdApi);
 }
 
 static void sessionTcaseSetup(void)
index 6d51fcdaa05bea6ea42e78023cfed2341ba47956..fe67946c2e70525b7f84bc97bdd97fefb4bc4c78 100644 (file)
@@ -71,7 +71,6 @@ static void appIdTestSetup()
     _dpd.searchAPI = &searchAPI;
 #endif
 
-    appIdApiInit(&appIdApi);
 }
 
 #ifdef REMOVED_WHILE_NOT_IN_USE
index 1f57bd50ad10addad3bb0c5072e18c89757d7081..0b51f7b64dd9881c1569b7c370e8185e17d9d541 100644 (file)
@@ -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,