]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #1005 in SNORT/snort3 from rule_dependencies to master
authorRuss Combs (rucombs) <rucombs@cisco.com>
Sat, 9 Sep 2017 15:00:00 +0000 (11:00 -0400)
committerRuss Combs (rucombs) <rucombs@cisco.com>
Sat, 9 Sep 2017 15:00:00 +0000 (11:00 -0400)
Squashed commit of the following:

commit acc68fe935fed33c263f355d08320c770bb06cdb
Author: Carter Waxman <cwaxman@cisco.com>
Date:   Fri Aug 25 16:21:58 2017 -0400

    sip: sip_method can use data from any sip inspector of any inspection policy

src/service_inspectors/sip/ips_sip_method.cc
src/service_inspectors/sip/sip.cc
src/service_inspectors/sip/sip_common.h
src/service_inspectors/sip/sip_config.h
src/service_inspectors/sip/sip_roptions.h

index d9c706cd6bbd6e2d51d39a372c2b88221307744c..8664e815149d7377dc47cbdeabb6ff9ae34bfd15 100644 (file)
@@ -26,6 +26,8 @@
 #include "config.h"
 #endif
 
+#include <unordered_map>
+
 #include "detection/detection_defines.h"
 #include "framework/ips_option.h"
 #include "framework/module.h"
@@ -44,6 +46,8 @@
 #define s_help \
     "detection option for sip stat code"
 
+typedef std::unordered_map<std::string, bool> MethodMap; //Method Name => Negated
+
 static THREAD_LOCAL ProfileStats sipMethodRuleOptionPerfStats;
 
 static inline bool IsRequest(SIP_Roptions* ropts)
@@ -57,28 +61,31 @@ static inline bool IsRequest(SIP_Roptions* ropts)
 class SipMethodOption : public IpsOption
 {
 public:
-    SipMethodOption(const SipMethodRuleOptData& c) :
-        IpsOption(s_name)
-    { smod = c; }
+    SipMethodOption(const MethodMap& m) :
+        IpsOption(s_name), methods(m) {}
 
     uint32_t hash() const override;
     bool operator==(const IpsOption&) const override;
     int eval(Cursor&, Packet*) override;
 
 private:
-    SipMethodRuleOptData smod;
+    MethodMap methods;
 };
 
 uint32_t SipMethodOption::hash() const
 {
     uint32_t a,b,c;
 
-    a = smod.flags;
-    b = smod.mask;
+    a = methods.size();
+    b = a ? methods.begin()->second : 0;
     c = 0;
 
-    mix_str(a,b,c,get_name());
-    finalize(a,b,c);
+    mix_str(a, b, c, get_name());
+
+    for ( auto& m : methods )
+        mix_str(a, b, c, m.first.c_str(), m.first.size());
+
+    finalize(a, b, c);
 
     return c;
 }
@@ -90,32 +97,40 @@ bool SipMethodOption::operator==(const IpsOption& ips) const
 
     const SipMethodOption& rhs = (SipMethodOption&)ips;
 
-    if ( (smod.flags == rhs.smod.flags) &&
-        (smod.mask == rhs.smod.mask) )
-        return true;
-
-    return false;
+    return methods == rhs.methods;
 }
 
 int SipMethodOption::eval(Cursor&, Packet* p)
 {
     Profile profile(sipMethodRuleOptionPerfStats);
 
-    if ((!p->is_tcp() && !p->is_udp()) || !p->flow || !p->dsize)
+    if ( !p->flow )
         return DETECTION_OPTION_NO_MATCH;
 
     SIPData* sd = get_sip_session_data(p->flow);
 
-    if (!sd)
+    if ( !sd )
         return DETECTION_OPTION_NO_MATCH;
 
     SIP_Roptions* ropts = &sd->ropts;
 
     // Not response
-    uint32_t methodFlag = 1 << (ropts->methodFlag - 1);
+    if ( IsRequest(ropts) && methods.size() )
+    {
+        if ( !ropts->method_data )
+            return DETECTION_OPTION_NO_MATCH;
+
+        //FIXIT-P This should really be evaluated once per request instead of once
+        //per rule option evaluation.
+        std::string method(ropts->method_data, ropts->method_len);
+        std::transform(method.begin(), method.end(), method.begin(), ::toupper);
 
-    if (IsRequest(ropts) && ((smod.flags & methodFlag) ^ smod.mask))
-        return DETECTION_OPTION_MATCH;
+        bool negated = methods.begin()->second;
+        bool match = methods.find(method) != methods.cend(); 
+
+        if ( negated ^ match )
+            return DETECTION_OPTION_MATCH;
+    }
 
     return DETECTION_OPTION_NO_MATCH;
 }
@@ -146,19 +161,16 @@ public:
     Usage get_usage() const override
     { return DETECT; }
 
-public:
-    SipMethodRuleOptData smod;
+    MethodMap methods;
 
 private:
-    int num_tokens;
     bool negated;
 };
 
 bool SipMethodModule::begin(const char*, int, SnortConfig*)
 {
-    num_tokens = 0;
     negated = false;
-    smod.flags = smod.mask = 0;
+    methods.clear();
     return true;
 }
 
@@ -178,21 +190,12 @@ bool SipMethodModule::set(const char*, Value& v, SnortConfig*)
             negated = false;
 
         /*Only one method is allowed with !*/
-        if (negated && (++num_tokens > 1))
+        if ( negated && (!methods.empty()) )
             ParseError("Only one method is allowed with ! for sip_method");
 
-        method = add_sip_method(tok);
-
-        if(!method)
-        {
-            ParseError("Failed to add a new method to sip_method");
-            return false;
-        }
-
-        smod.flags |= 1 << (method->methodFlag - 1);
-
-        if (negated)
-            smod.mask |= 1 << (method->methodFlag - 1);
+        std::string key = tok;
+        std::transform(key.begin(), key.end(), key.begin(), ::toupper);
+        methods[key] = negated;
     }
     else
         return false;
@@ -217,7 +220,7 @@ static void mod_dtor(Module* m)
 static IpsOption* sip_method_ctor(Module* p, OptTreeNode*)
 {
     SipMethodModule* m = (SipMethodModule*)p;
-    return new SipMethodOption(m->smod);
+    return new SipMethodOption(m->methods);
 }
 
 static void opt_dtor(IpsOption* p)
index 1b000b4aca68e5c8f229d0f6af279c60c802a3f0..1344a1599403c2cfce79146960db45e75118a1d2 100644 (file)
@@ -183,7 +183,8 @@ static inline int SIP_Process(Packet* p, SIPData* sessp, SIP_PROTO_CONF* config)
     }
     /*Update the session data*/
     pRopts = &(sessp->ropts);
-    pRopts->methodFlag = sipMsg.methodFlag;
+    pRopts->method_data = sipMsg.method;
+    pRopts->method_len = sipMsg.methodLen;
     pRopts->header_data = sipMsg.header;
     pRopts->header_len = sipMsg.headerLen;
     pRopts->body_len = sipMsg.bodyLen;
@@ -255,8 +256,6 @@ public:
     void eval(Packet*) override;
     bool get_buf(InspectionBuffer::Type, Packet*, InspectionBuffer&) override;
 
-    SIPMethodNode* add_method(const char*);
-
 private:
     SIP_PROTO_CONF* config;
 };
@@ -280,17 +279,6 @@ void Sip::show(SnortConfig*)
     PrintSipConf(config);
 }
 
-SIPMethodNode* Sip::add_method(const char* tok)
-{
-    SIPMethodNode *method;
-    method = SIP_FindMethod(config->methods, tok, strlen(tok));
-
-    if ( !method )
-        method = SIP_AddUserDefinedMethod(tok, &config->methodsConfig, &config->methods);
-
-    return method;
-}
-
 void Sip::eval(Packet* p)
 {
     // precondition - what we registered for
@@ -368,12 +356,6 @@ static void sip_dtor(Inspector* p)
     delete p;
 }
 
-SIPMethodNode* add_sip_method(const char* tok)
-{
-    Sip* sip = (Sip*)InspectorManager::get_inspector("sip");
-    return sip ? sip->add_method(tok) : nullptr;
-}
-
 const InspectApi sip_api =
 {
     {
index cab85d2ee1bf71738d8873ab8c0eb1fce9303a70..2719de8d170a79ffbb10752f4314205dfa2bc753 100644 (file)
@@ -24,7 +24,7 @@
 
 #include "sfip/sf_ip.h"
 
-// Header containing datatypes/definitions shared by SSL inspector files.
+// Header containing datatypes/definitions shared by SIP inspector files.
 
 enum SIPMethodsFlag
 {
index 1c6e91c3b94d96b68bed86573b5c37ae0ddb08f2..b905c6278cccbf99483ad8597d3181dad5169bfb 100644 (file)
@@ -113,9 +113,6 @@ void SIP_ParseMethods(
 // Sets the Default method lists
 void SIP_SetDefaultMethods(SIP_PROTO_CONF* config);
 
-// API to find a method
-int SIP_findMethod(char* token, SIPMethod* methods);
-
 // API to add a user defined method to SIP config
 SIPMethodNode* SIP_AddUserDefinedMethod(
     const char* methodName, uint32_t* methodsConfig, SIPMethodlist* pmethods);
index 4043be2a459d679c12b09c351f73b9197d9454aa..a5800a49346ec10bab24a5be45d82e1c2f894db4 100644 (file)
@@ -30,7 +30,9 @@
 
 struct SIP_Roptions
 {
-    SIPMethodsFlag methodFlag;  // sip_method data
+    const char* method_data;
+    uint16_t method_len;
+
     uint16_t status_code;       // sip_stat_code data
 
     const uint8_t* header_data; // Set to NULL if not applicable