]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
initial CAPWAP support
authorJosh <jrosenba@cisco.com>
Thu, 11 Dec 2014 18:17:51 +0000 (12:17 -0600)
committerJosh <jrosenba@cisco.com>
Thu, 11 Dec 2014 18:17:51 +0000 (12:17 -0600)
20 files changed:
src/codecs/codec_api.cc
src/codecs/codec_module.h
src/codecs/ip/cd_icmp4.cc
src/codecs/ip/cd_icmp6.cc
src/codecs/ip/cd_udp.cc
src/codecs/link/cd_vlan.cc
src/codecs/misc/CMakeLists.txt
src/codecs/misc/cd_gtp.cc
src/codecs/misc/cd_icmp4_ip.cc
src/codecs/misc/cd_icmp6_ip.cc
src/codecs/misc/cd_llc.cc
src/codecs/misc/cd_teredo.cc
src/codecs/root/cd_eth.cc
src/codecs/root/cd_wlan.cc
src/main/snort_config.cc
src/main/snort_config.h
src/protocols/layer.cc
src/protocols/packet_manager.cc
src/protocols/protocol_ids.h
src/protocols/udp.h

index 06e4fdad81b7e46cc30820567d6ee96ba28bec29..b81502ce9cf5f205db2376259307cd47819268a1 100644 (file)
@@ -39,6 +39,7 @@ extern const BaseApi* cd_tcp;  // static because only file that specific functio
 #ifdef STATIC_CODECS
 extern const BaseApi* cd_ah;
 extern const BaseApi* cd_arp;
+extern const BaseApi* cd_capwap;
 extern const BaseApi* cd_dstopts;
 extern const BaseApi* cd_erspan2;
 extern const BaseApi* cd_erspan3;
@@ -91,6 +92,7 @@ const BaseApi* codecs[] =
 #ifdef STATIC_CODECS
     cd_ah,
     cd_arp,
+    cd_capwap,
     cd_dstopts,
     cd_erspan2,
     cd_erspan3,
index 398bab648aff7b153c917d202c1283503577fe47..c7e20619fdce93ea5362848266daf2ee78ef6b4c 100644 (file)
@@ -203,7 +203,8 @@ enum CodecSid
     DECODE_AUTH_HDR_TRUNC,
     DECODE_AUTH_HDR_BAD_LEN,
     DECODE_TOO_MANY_LAYERS,
-    DECODE_INDEX_MAX // = 468
+    DECODE_CAPWAP_TRUNC,
+    DECODE_INDEX_MAX // = 469
 };
 
 
index 9f8fd6caeb7684b582397d47357361b56b4d0bb1..c6f962ea33a9c7fa01c7dbc2b28251869e3be93b 100644 (file)
@@ -247,7 +247,7 @@ bool Icmp4Codec::decode(const RawData& raw, CodecData& codec,DecodeData& snort)
         case icmp::IcmpType::PARAMETERPROB:
             /* account for extra 4 bytes in header */
             len += 4;
-            codec.next_prot_id = IP_EMBEDDED_IN_ICMP4;
+            codec.next_prot_id = PROTO_IP_EMBEDDED_IN_ICMP4;
             break;
 
         default:
index 9f23def7f5c021e6eb02c77bfe612d59f54b1b68..6d0d4e93139e7b2b973a7ed7c130aa9e5edffbe9 100644 (file)
@@ -195,7 +195,7 @@ bool Icmp6Codec::decode(const RawData& raw, CodecData& codec, DecodeData& snort)
                     codec_events::decoder_event(codec, DECODE_ICMPV6_TOO_BIG_BAD_MTU);
 
                 len = icmp::ICMP6_HEADER_NORMAL_LEN;
-                codec.next_prot_id = IP_EMBEDDED_IN_ICMP6;
+                codec.next_prot_id = PROTO_IP_EMBEDDED_IN_ICMP6;
             }
             else
             {
@@ -218,7 +218,7 @@ bool Icmp6Codec::decode(const RawData& raw, CodecData& codec, DecodeData& snort)
                         codec_events::decoder_event(codec, DECODE_ICMPV6_UNREACHABLE_NON_RFC_4443_CODE);
                 }
                 len = icmp::ICMP6_HEADER_NORMAL_LEN;
-                codec.next_prot_id = IP_EMBEDDED_IN_ICMP6;
+                codec.next_prot_id = PROTO_IP_EMBEDDED_IN_ICMP6;
             }
             else
             {
index c453ce2339f960fc00a88234aaa5d361ae9f4bf3..986fa3468214bcbc9121e39cd5fd3ecbbd89f075 100644 (file)
@@ -77,6 +77,9 @@ static const Parameter udp_params[] =
     { "gtp_ports", Parameter::PT_BIT_LIST, "65535",
       "2152 3386", "set GTP ports" },
 
+    { "capwap_ports", Parameter::PT_BIT_LIST, "65535",
+      "5246 5247", "customize capwap_ports" },
+
     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
 };
 
@@ -138,6 +141,10 @@ public:
                 }
             }
         }
+        else if ( v.is("capwap_ports") )
+        {
+            v.get_bits(*(sc->capwap_ports));
+        }
         else
         {
             return false;
@@ -330,13 +337,18 @@ bool UdpCodec::decode(const RawData& raw, CodecData& codec, DecodeData& snort)
          (ScIsGTPPort(src_port)||ScIsGTPPort(dst_port)))
     {
         if ( !(snort.decode_flags & DECODE_FRAG) )
-            codec.next_prot_id = PROTOCOL_GTP;
+            codec.next_prot_id = PROTO_GTP;
     }
     else if (teredo::is_teredo_port(src_port) ||
         teredo::is_teredo_port(dst_port) ||
         ScDeepTeredoInspection())
     {
-        codec.next_prot_id = PROTOCOL_TEREDO;
+        codec.next_prot_id = PROTO_TEREDO;
+    }
+    else if (snort_conf->is_capwap_port(dst_port) ||
+        snort_conf->is_capwap_port(src_port))
+    {
+        codec.next_prot_id = PROTO_CAPWAP;
     }
 
     
index 63da35f92e4a69088aaf5dcb829e238a0c6821f7..c8b9089427a89f34fb01fa01c6177d2f6f3079c2 100644 (file)
@@ -100,7 +100,7 @@ bool VlanCodec::decode(const RawData& raw, CodecData& codec, DecodeData&)
      * http://www.geocities.com/billalexander/ethernet.html
      */
     if(proto <= ETHERNET_MAX_LEN_ENCAP)
-        codec.next_prot_id = ETHERNET_LLC;
+        codec.next_prot_id = PROTO_ETHERNET_LLC;
     else
         codec.next_prot_id = proto;
 
index 6425e338d5d97e2f7bf553fd87d99ff2ec586fd5..b709da2f80c4aedde14d0a16aa84e988c9afaa2b 100644 (file)
@@ -19,6 +19,7 @@ endif(STATIC_CODECS)
 
 add_library( misc_codecs STATIC
     cd_default.cc
+    cd_capwap.cc
     ${PLUGIN_LIST}
 )
 
index 041d7cb182f47b442de3fec2fbdbba03c0cba2de..7069bb3fce9cb9dcae0b16324c46ef16f8414245 100644 (file)
@@ -96,7 +96,7 @@ static const uint32_t GTP_V1_HEADER_LEN = 12;
 
 void GtpCodec::get_protocol_ids(std::vector<uint16_t>& v)
 {
-    v.push_back(PROTOCOL_GTP);
+    v.push_back(PROTO_GTP);
 }
 
 /* Function: DecodeGTP(uint8_t *, uint32_t, Packet *)
index 64b80425242da9ebfa007d223ac3e5387446694c..576cd7cec7a7c9c602f25c892aca62d8682e82eb 100644 (file)
@@ -59,7 +59,7 @@ public:
 
 
 void Icmp4IpCodec::get_protocol_ids(std::vector<uint16_t>& v)
-{ v.push_back(IP_EMBEDDED_IN_ICMP4); }
+{ v.push_back(PROTO_IP_EMBEDDED_IN_ICMP4); }
 
 bool Icmp4IpCodec::decode(const RawData& raw, CodecData& codec, DecodeData& snort)
 {
index 08a2e2ed627fa389e7789b527cff2d2e5c365bf3..fd5b4350e9b1ef2083e761075dda0af7d65a49c3 100644 (file)
@@ -59,7 +59,7 @@ public:
 } // namespace
 
 void Icmp6IpCodec::get_protocol_ids(std::vector<uint16_t>& v)
-{ v.push_back(IP_EMBEDDED_IN_ICMP6); }
+{ v.push_back(PROTO_IP_EMBEDDED_IN_ICMP6); }
 
 bool Icmp6IpCodec::decode(const RawData& raw, CodecData& codec, DecodeData&)
 {
index 11e8a3f9c0bfa0b625b8d976239aac7c58ac3291..7d14e26b9337d0ea6bba48dd1579da6b9ac159a2 100644 (file)
 #include "log/text_log.h"
 #include "protocols/packet_manager.h"
 
-// yes, macros are necessary. The API and class constructor require different strings.
-//
-// this macros is defined in the module to ensure identical names. However,
-// if you don't want a module, define the name here.
+
 #define LLC_NAME "llc"
 #define LLC_HELP "support for logical link control"
 
@@ -67,7 +64,10 @@ struct EthLlc
 struct EthLlcOther
 {
     uint8_t org_code[3];
-    uint16_t proto_id;
+    uint8_t proto_id[2];
+
+    uint16_t proto() const
+    { return ntohs(*((uint16_t*)(&proto_id[0]))); }
 };
 
 #define ETH_DSAP_SNA                  0x08    /* SNA */
@@ -84,9 +84,7 @@ struct EthLlcOther
 
 
 void LlcCodec::get_protocol_ids(std::vector<uint16_t>& v)
-{
-    v.push_back(ETHERNET_LLC);
-}
+{ v.push_back(PROTO_ETHERNET_LLC); }
 
 bool LlcCodec::decode(const RawData& raw, CodecData& codec, DecodeData&)
 {
@@ -117,7 +115,7 @@ bool LlcCodec::decode(const RawData& raw, CodecData& codec, DecodeData&)
             ehllcother->org_code[2] == 0)
         {
             codec.lyr_len = sizeof(EthLlc) + sizeof(EthLlcOther);
-            codec.next_prot_id = ntohs(ehllcother->proto_id);
+            codec.next_prot_id = ehllcother->proto();
         }
     }
 
@@ -138,7 +136,7 @@ void LlcCodec::log(TextLog* const text_log, const uint8_t* raw_pkt,
     {
 
         const EthLlcOther *other = reinterpret_cast<const EthLlcOther *>(raw_pkt + sizeof(EthLlc));
-        const uint16_t proto = ntohs(other->proto_id);
+        const uint16_t proto = other->proto();
 
         TextLog_Print(text_log, " ORG:0x%02X%02X%02X PROTO:0x%04X",
             other->org_code[0], other->org_code[1], other->org_code[2],
index a114dd6c93e50af5a76bc14159fadf349d59924f..e7a4a5f01472cfd81dd44ce4adf61e7a17099e95 100644 (file)
@@ -26,8 +26,6 @@
 #include "config.h"
 #endif
 
-//#include "prot_ipv6.h"
-
 #include "framework/codec.h"
 #include "packet_io/active.h"
 #include "snort_types.h"
@@ -58,7 +56,7 @@ public:
 
 void TeredoCodec::get_protocol_ids(std::vector<uint16_t>& v)
 {
-    v.push_back(PROTOCOL_TEREDO);
+    v.push_back(PROTO_TEREDO);
 }
 
 bool TeredoCodec::decode(const RawData& raw, CodecData& codec, DecodeData& snort)
index 56a11b9f70c21e721706f3c0434e5738051a0202..72fc0c571e4fe9c695c266123da485e6cb42cf0e 100644 (file)
@@ -88,7 +88,7 @@ void EthCodec::get_data_link_type(std::vector<int>&v)
 
 void EthCodec::get_protocol_ids(std::vector<uint16_t>&v)
 {
-    v.push_back(ETHERNET_802_3);
+    v.push_back(PROTO_ETHERNET_802_3);
 }
 
 
@@ -126,7 +126,7 @@ bool EthCodec::decode(const RawData& raw, CodecData& codec, DecodeData&)
     if (next_prot > eth::MIN_ETHERTYPE )
         codec.proto_bits |= PROTO_BIT__ETH;
     else
-        next_prot = ETHERNET_LLC;
+        next_prot = PROTO_ETHERNET_LLC;
 
     codec.next_prot_id = next_prot;
     codec.lyr_len = eth::ETH_HEADER_LEN;
index abf919f1ff5446867e457a8bef10d9f5d68ad702..ad78ee972be8569f4ab47af3f477e7f152efd87a 100644 (file)
 #include "main/snort.h"
 #include "log/text_log.h"
 
+#ifndef DLT_IEEE802_11
+#define DLT_IEEE802_11 105
+#endif
+
 #define CD_WLAN_NAME "wlan"
 #define CD_WLAN_HELP_STR "support for wireless local area network protocol"
 #define CD_WLAN_HELP ADD_DLT(CD_WLAN_HELP_STR, DLT_IEEE802_11)
@@ -66,6 +70,7 @@ public:
 
     bool decode(const RawData&, CodecData&, DecodeData&) override;
     void get_data_link_type(std::vector<int>&) override;
+    void get_protocol_ids(std::vector<uint16_t>&v) override;
     void log(TextLog* const, const uint8_t* /*raw_pkt*/,
                     const Packet* const) override;
 };
@@ -77,11 +82,10 @@ public:
 
 
 void WlanCodec::get_data_link_type(std::vector<int>&v)
-{
-#ifdef DLT_IEEE802_11
-    v.push_back(DLT_IEEE802_11);
-#endif
-}
+{ v.push_back(DLT_IEEE802_11); }
+
+void WlanCodec::get_protocol_ids(std::vector<uint16_t>&v)
+{ v.push_back(PROTO_ETHERNET_802_11); }
 
 bool WlanCodec::decode(const RawData& raw, CodecData& codec, DecodeData&)
 {
@@ -131,7 +135,7 @@ bool WlanCodec::decode(const RawData& raw, CodecData& codec, DecodeData&)
         case WLAN_TYPE_DATA_DATA:
         {
             codec.lyr_len = IEEE802_11_DATA_HDR_LEN;
-            codec.next_prot_id = ETHERNET_LLC;
+            codec.next_prot_id = PROTO_ETHERNET_LLC;
 
             break;
         }
index fa1f586efb48899e25f72e6487188800cc02f411..950a05283763d4c7f72a61756653578a02b8f9d8 100644 (file)
@@ -44,6 +44,7 @@
 #include "filters/detection_filter.h"
 #include "detection/fpcreate.h"
 #include "ips_options/ips_pcre.h"
+#include "protocols/udp.h"
 
 //-------------------------------------------------------------------------
 // private implementation
@@ -181,6 +182,9 @@ SnortConfig * SnortConfNew(void)
     sc->max_ip6_extensions = 0;
     sc->max_ip_layers = 0;
     sc->gtp_ports = nullptr;
+    sc->capwap_ports = new PortList;
+    sc->capwap_ports->set(udp::CAPWAP_CONTROL_CHANNEL_PORT);
+    sc->capwap_ports->set(udp::CAPWAP_DATA_CHANNEL_PORT);
 
     /*user_id and group_id should be initialized to -1 by default, because
      * chown() use this later, -1 means no change to user_id/group_id*/
@@ -356,6 +360,9 @@ void SnortConfFree(SnortConfig *sc)
     if (sc->gtp_ports)
         delete sc->gtp_ports;
 
+    if (sc->capwap_ports)
+        delete sc->capwap_ports;
+
     free(sc);
 }
 
index f538aea1638ec9badd1b5e24f8e8ab555b30f880..2bf22442ecf7b81f95b4a7de717c676ce2ca359b 100644 (file)
@@ -158,6 +158,7 @@ struct SnortConfig
     uint8_t enable_teredo;
     uint8_t enable_esp;
     PortList *gtp_ports;
+    PortList *capwap_ports;
 
     uint8_t num_layers;
     uint8_t max_ip6_extensions;
@@ -312,6 +313,9 @@ struct SnortConfig
     // curr_ip is the zero based ip layer
     inline bool hit_ip_maxlayers(uint8_t curr_ip) const
     { return max_ip_layers && (curr_ip >= max_ip_layers); }
+
+    inline bool is_capwap_port(uint16_t port) const
+    { return capwap_ports->test(port); }
 };
 
 SnortConfig* SnortConfNew(void);
index 024381749408f6036e2c998cb927d59440c26ed7..a96fa1181e87d87cf0abf45132079ee9aba5dd7d 100644 (file)
@@ -414,14 +414,14 @@ bool set_api_ip_embed_icmp(const Packet* p, ip::IpApi& api)
     {
         const Layer& lyr = p->layers[i];
 
-        if (lyr.prot_id == IP_EMBEDDED_IN_ICMP4)
+        if (lyr.prot_id == PROTO_IP_EMBEDDED_IN_ICMP4)
         {
             const ip::IP4Hdr* ip4h =
                 reinterpret_cast<const ip::IP4Hdr*>(lyr.start);
             api.set(ip4h);
             return true;
         }
-        else if (lyr.prot_id == IP_EMBEDDED_IN_ICMP6)
+        else if (lyr.prot_id == PROTO_IP_EMBEDDED_IN_ICMP6)
         {
             const ip::IP6Hdr* ip6h =
                 reinterpret_cast<const ip::IP6Hdr*>(lyr.start);
index 84078edb6a32f9c8fddea244d5c40283b5000e75..927170b3c4c836af20823c2694ef84e703d32292 100644 (file)
@@ -282,7 +282,7 @@ void PacketManager::decode(
                 p->ptrs.decode_flags |= DECODE_PKT_TRUST;
                 break;
 
-            case PROTOCOL_TEREDO:
+            case PROTO_TEREDO:
                 // if we just decoded teredo and the next
                 // layer fails, we made a mistake. Therefore,
                 // remove this bit.
index 485ecd692536485fab486504eba8bb9d7240c269..8eb7d8929ecf4131289bc995219c28b1ae93cf3f 100644 (file)
@@ -69,12 +69,14 @@ constexpr uint16_t IPPROTO_ID_RESERVED = 255; // == 0xFF
  */
 
 constexpr uint16_t FINISHED_DECODE = 0x0100;  // Indicates Codecs have succesfully decoded packet
-constexpr uint16_t PROTOCOL_TEREDO = 0x0101;
-constexpr uint16_t PROTOCOL_GTP = 0x0102;
-constexpr uint16_t IP_EMBEDDED_IN_ICMP4 = 0x0103;
-constexpr uint16_t IP_EMBEDDED_IN_ICMP6 = 0x0104;
-constexpr uint16_t ETHERNET_802_3 = 0x0105;  // CAPWAP sends data back to eth layer
-constexpr uint16_t ETHERNET_LLC = 0x0106;
+constexpr uint16_t PROTO_TEREDO = 0x0101;
+constexpr uint16_t PROTO_GTP = 0x0102;
+constexpr uint16_t PROTO_IP_EMBEDDED_IN_ICMP4 = 0x0103;
+constexpr uint16_t PROTO_IP_EMBEDDED_IN_ICMP6 = 0x0104;
+constexpr uint16_t PROTO_ETHERNET_802_3 = 0x0105;
+constexpr uint16_t PROTO_ETHERNET_802_11 = 0x0106;
+constexpr uint16_t PROTO_ETHERNET_LLC = 0x0107;
+constexpr uint16_t PROTO_CAPWAP = 0x0108;
 
 
 
index 116833ed27b129d49c883c127ef6b98f93c31e49..1cf5abbfaaf363a68632ab5b43a395dcda1066c4 100644 (file)
@@ -31,6 +31,9 @@ namespace udp
 
 constexpr uint8_t UDP_HEADER_LEN = 8;
 
+constexpr uint16_t CAPWAP_CONTROL_CHANNEL_PORT = 5246;
+constexpr uint16_t CAPWAP_DATA_CHANNEL_PORT = 5247;
+
 struct UDPHdr
 {
     uint16_t uh_sport;