1 //-------------------------------------------------------------------------- 2 // Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved. 3 // 4 // This program is free software; you can redistribute it and/or modify it 5 // under the terms of the GNU General Public License Version 2 as published 6 // by the Free Software Foundation. You may not use, modify or distribute 7 // this program under any other version of the GNU General Public License. 8 // 9 // This program is distributed in the hope that it will be useful, but 10 // WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 // General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License along 15 // with this program; if not, write to the Free Software Foundation, Inc., 16 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 //-------------------------------------------------------------------------- 18 // codec.h author Josh Rosenbaum <jrosenba@cisco.com> 19 20 #ifndef FRAMEWORK_CODEC_H 21 #define FRAMEWORK_CODEC_H 22 23 // Codec is a type of plugin that provides protocol-specific encoding and 24 // decoding. 25 26 #include <cstdint> 27 #include <vector> 28 29 #include "framework/base_api.h" 30 #include "framework/decode_data.h" 31 #include "protocols/layer.h" 32 #include "utils/cpp_macros.h" 33 34 struct TextLog; 35 struct _daq_msg; 36 37 namespace snort 38 { 39 enum CodecSid : uint32_t; 40 41 namespace ip 42 { 43 class IpApi; 44 } 45 namespace tcp 46 { 47 struct TCPHdr; 48 } 49 namespace udp 50 { 51 struct UDPHdr; 52 } 53 namespace icmp 54 { 55 struct ICMPHdr; 56 } 57 58 class Flow; 59 60 // Used by root codecs to add their DLT to their HELP string 61 #define ADD_DLT(help, x) help " (DLT " STRINGIFY_MX(x) ")" 62 63 constexpr uint8_t MIN_TTL = 64; 64 constexpr uint8_t MAX_TTL = 255; 65 66 struct RawData 67 { 68 const struct _daq_msg* daq_msg; 69 const uint8_t* data; 70 uint32_t len; 71 RawDataRawData72 RawData(const struct _daq_msg* daq_msg, const uint8_t* data, uint32_t len) : 73 daq_msg(daq_msg), data(data), len(len) { } 74 }; 75 76 /* Decode Flags */ 77 constexpr uint16_t CODEC_DF = 0x0001; /* don't fragment flag */ 78 79 // packet may have incorrect encapsulation layer. don't alert if "next 80 // layer" is invalid. If decode fails with this bit set, PacketManager 81 // will back out to the previous layer. IMPORTANT: This bit can ONLY be 82 // set if the DECODE_ENCAP_LAYER flag was was previously set. 83 constexpr uint16_t CODEC_UNSURE_ENCAP = 0x0002; 84 85 // DO NOT USE THIS LAYER!! -- use DECODE_ENCAP_LAYER 86 constexpr uint16_t CODEC_SAVE_LAYER = 0x0004; 87 88 // If encapsulation decode fails, back out to this layer This will be 89 // cleared by PacketManager between decodes This flag automatically sets 90 // DECODE_ENCAP_LAYER for the next layer (and only the next layer). 91 constexpr uint16_t CODEC_ENCAP_LAYER = (CODEC_SAVE_LAYER | CODEC_UNSURE_ENCAP ); 92 93 // used to check ip6 extension order 94 constexpr uint16_t CODEC_ROUTING_SEEN = 0x0008; 95 96 // used by icmp4 for alerting 97 constexpr uint16_t CODEC_IPOPT_RR_SEEN = 0x0010; 98 99 // used by IGMP for alerting 100 constexpr uint16_t CODEC_IPOPT_RTRALT_SEEN = 0x0020; 101 102 // used by IGMP for alerting 103 constexpr uint16_t CODEC_IPOPT_LEN_THREE = 0x0040; 104 105 // used in IPv6 Codec 106 constexpr uint16_t CODEC_TEREDO_SEEN = 0x0080; 107 108 constexpr uint16_t CODEC_STREAM_REBUILT = 0x0100; 109 constexpr uint16_t CODEC_NON_IP_TUNNEL = 0x0200; 110 111 constexpr uint16_t CODEC_IP6_EXT_OOO = 0x0400; 112 constexpr uint16_t CODEC_IP6_BAD_OPT = 0x0800; 113 114 constexpr uint16_t CODEC_ETHER_NEXT = 0x1000; 115 constexpr uint16_t CODEC_COMPOUND = 0x2000; 116 constexpr uint16_t CODEC_LAYERS_EXCEEDED = 0x400; 117 118 constexpr uint16_t CODEC_IPOPT_FLAGS = (CODEC_IPOPT_RR_SEEN | 119 CODEC_IPOPT_RTRALT_SEEN | CODEC_IPOPT_LEN_THREE); 120 121 struct SnortConfig; 122 123 constexpr uint8_t COMPOUND_LAYERS_MAX = 8; 124 125 struct CompoundLayer 126 { 127 Layer layer; 128 uint32_t proto_bits; 129 }; 130 131 struct CodecData 132 { 133 const SnortConfig* conf; 134 135 /* This section will get reset before every decode() function call */ 136 ProtocolId next_prot_id; /* protocol type of the next layer */ 137 uint16_t lyr_len = 0; /* length of the valid portion of this layer */ 138 uint16_t invalid_bytes = 0; /* length of the INVALID part of this layer */ 139 uint32_t proto_bits = 0; /* protocols contained within this packet 140 -- will be propogated to Snort++ Packet struct*/ 141 142 /* Reset before each decode of packet begins */ 143 144 /* Codec specific fields. These fields are only relevant to codecs. */ 145 uint16_t codec_flags = 0; /* flags used while decoding */ 146 uint8_t ip_layer_cnt = 0; 147 148 uint8_t ip6_extension_count = 0; 149 uint8_t curr_ip6_extension = 0; 150 IpProtocol ip6_csum_proto = IpProtocol::IP; /* Used for IPv6 checksums */ 151 bool tunnel_bypass = false; 152 153 CompoundLayer compound_layers[COMPOUND_LAYERS_MAX]{}; 154 uint8_t compound_layer_cnt = 0; 155 CodecDataCodecData156 CodecData(const SnortConfig* sc, ProtocolId init_prot) : conf(sc), next_prot_id(init_prot) 157 { } 158 is_cookedCodecData159 bool inline is_cooked() const 160 { return codec_flags & CODEC_STREAM_REBUILT; } 161 }; 162 163 typedef uint64_t EncodeFlags; 164 constexpr EncodeFlags ENC_FLAG_FWD = 0x8000000000000000; // send in forward direction 165 constexpr EncodeFlags ENC_FLAG_SEQ = 0x4000000000000000; // VAL bits contain seq adj 166 constexpr EncodeFlags ENC_FLAG_ID = 0x2000000000000000; // use randomized IP ID 167 constexpr EncodeFlags ENC_FLAG_NET = 0x1000000000000000; // stop after innermost network (ip4/6) 168 // layer 169 constexpr EncodeFlags ENC_FLAG_DEF = 0x0800000000000000; // stop before innermost ip4 opts or ip6 170 // frag header 171 constexpr EncodeFlags ENC_FLAG_RAW = 0x0400000000000000; // don't encode outer eth header (this is 172 // raw ip) 173 constexpr EncodeFlags ENC_FLAG_PAY = 0x0200000000000000; // set to when a TCP payload is attached 174 constexpr EncodeFlags ENC_FLAG_PSH = 0x0100000000000000; // set by PacketManager when TCP should 175 // set PUSH flag 176 constexpr EncodeFlags ENC_FLAG_FIN = 0x0080000000000000; // set by PacketManager when TCP should 177 // set FIN flag 178 constexpr EncodeFlags ENC_FLAG_TTL = 0x0040000000000000; // set by PacketManager when TCP should 179 // set FIN flag 180 constexpr EncodeFlags ENC_FLAG_INLINE = 0x0020000000000000; // set by PacketManager when TCP 181 // should set FIN flag 182 constexpr EncodeFlags ENC_FLAG_RST_CLNT = 0x0010000000000000; // finish with a client RST packet 183 constexpr EncodeFlags ENC_FLAG_RST_SRVR = 0x0008000000000000; // finish with a server RST packet 184 constexpr EncodeFlags ENC_FLAG_VAL = 0x00000000FFFFFFFF; // bits for adjusting seq and/or ack 185 186 constexpr uint8_t ENC_PROTO_UNSET = 0xFF; 187 188 struct SO_PUBLIC EncState 189 { 190 const ip::IpApi& ip_api; /* IP related information. Good for checksums */ 191 EncodeFlags flags; 192 const uint16_t dsize; /* for non-inline, TCP sequence numbers */ 193 ProtocolId next_ethertype; /* set the next encoder 'proto' field to this value. */ 194 IpProtocol next_proto; /* set the next encoder 'proto' field to this value. */ 195 const uint8_t ttl; 196 197 EncState(const ip::IpApi& api, EncodeFlags f, IpProtocol pr, 198 uint8_t t, uint16_t data_size); 199 next_proto_setEncState200 inline bool next_proto_set() const 201 { return (next_proto != IpProtocol::PROTO_NOT_SET); } 202 ethertype_setEncState203 inline bool ethertype_set() const 204 { return next_ethertype != ProtocolId::ETHERTYPE_NOT_SET; } 205 forwardEncState206 inline bool forward() const 207 { return flags & ENC_FLAG_FWD; } 208 209 uint8_t get_ttl(uint8_t lyr_ttl) const; 210 }; 211 212 struct SO_PUBLIC Buffer 213 { 214 public: 215 Buffer(uint8_t* buf, uint32_t size); 216 dataBuffer217 inline uint8_t* data() const 218 { return base; } 219 sizeBuffer220 uint32_t size() const 221 { return end; } 222 allocateBuffer223 inline bool allocate(uint32_t len) 224 { 225 if ( (end + len) > max_len ) 226 return false; 227 228 end += len; 229 base -= len; 230 return true; 231 } 232 clearBuffer233 inline void clear() 234 { base = base + end; end = 0; off = 0; } 235 236 private: 237 uint8_t* base; /* start of data */ 238 uint32_t end; /* end of data */ 239 const uint32_t max_len; /* size of allocation */ 240 241 public: 242 uint32_t off; /* offset into data */ 243 }; 244 245 typedef uint8_t UpdateFlags; 246 constexpr UpdateFlags UPD_COOKED = 0x01; 247 constexpr UpdateFlags UPD_MODIFIED = 0x02; 248 constexpr UpdateFlags UPD_RESIZED = 0x04; 249 constexpr UpdateFlags UPD_REBUILT_FRAG = 0x08; 250 251 /* Codec Class */ 252 253 class SO_PUBLIC Codec 254 { 255 public: 256 virtual ~Codec() = default; 257 258 // PKT_MAX = ETHERNET_HEADER_LEN + VLAN_HEADER + ETHERNET_MTU + IP_MAXPACKET 259 260 /* PKT_MAX is sized to ensure that any reassembled packet 261 * can accommodate a full datagram at innermost layer 262 * 263 * ETHERNET_HEADER_LEN == 14 264 * VLAN_HEADER == 4 265 * ETHERNET_MTU == 1500 266 * IP_MAXPACKET == 65535 FIXIT-L use Packet::max_dsize 267 */ 268 static const uint32_t PKT_MAX = 14 + 4 + 1500 + 65535; 269 270 /* Codec Initialization */ 271 272 // Get the codec's name get_name()273 inline const char* get_name() const 274 { return name; } 275 // Registers this Codec's data link type (as defined by libpcap) get_data_link_type(std::vector<int> &)276 virtual void get_data_link_type(std::vector<int>&) // FIXIT-M return a vector == efficient in 277 // c++11 278 { } 279 // Register the code's protocol ID's and Ethertypes get_protocol_ids(std::vector<ProtocolId> &)280 virtual void get_protocol_ids(std::vector<ProtocolId>&) // FIXIT-M return a vector == 281 // efficient in c++11 282 { } 283 284 /* 285 * Main decoding function! Will get called when decoding a packet. 286 * 287 * PARAMS: 288 * const RawData& = struct containing information about the 289 * current packet's raw data 290 * 291 * CodecData& = Pass information the PacketManager and other 292 * codecs. IMPORTANT FIELDS TO SET IN YOUR CODEC - 293 * next_prot_id = protocol type of the next layer 294 * lyr_len = The length of the valid part layer 295 * invalid bytes = number of invalid bytes between the end of 296 * the this layer's valid length and the next 297 * layer. For instance, 298 * when decoding IP, if there are 20 bytes of 299 * options but only 12 bytes are valid. 300 * 301 * data.lyr_len = MIN_IP_HEADER_LEN + 12; 302 * data.invalid_bytes = 8 === 20 - 12 303 * 304 * DecodeData& = Data which will be sent to the rest of Snort++. 305 * contains convenience pointers and information 306 * about this packet. 307 **/ 308 virtual bool decode(const RawData&, CodecData&, DecodeData&)=0; 309 310 /* 311 * Log this layer's information 312 * PARAMS: 313 * TextLog* = the logger. Defined in "text_log.h" 314 * const uint8_t *raw_pkt = the same data seen during decode 315 * const uint16_t lyr_len = This layer's validated length == 316 * lyr_len set during decode. 317 */ log(TextLog * const,const uint8_t *,const uint16_t)318 virtual void log(TextLog* const, const uint8_t* /*raw_pkt*/, const uint16_t /*lyr_len*/) 319 { } 320 321 /* 322 * Encoding -- active response!! 323 * 324 * Encode the current packet. Encoding starts with the innermost 325 * layer and working outwards. All encoders MUST call the 326 * Buffer.allocate() function before writing to output buffer. 327 * PARAMS: 328 * uint8_t* raw_in = A pointer to the raw input which was decoded. 329 * This is the same pointer which was given to decode(). 330 * uint16_t len == the value to which '(CodecData&).lyr_len' was set during decode. 331 * I.e., the validated length of this layer. Some protocols, 332 * like IPv4 (original ipv4 header may contain invalid options 333 * which we don't want to copy) and GTP have dynamic lengths. 334 * So, this parameter ensure the encode() function doesn't 335 * need to revalidate and recalculate the length. 336 * EncState& = The current EncState struct 337 * Buffer& = the packet which will be sent. All inward layers will already 338 * be set. 339 * 340 * NOTE: all functions MUST call the Buffer.allocate() function before 341 * manipulating memory. 342 */ encode(const uint8_t * const,const uint16_t,EncState &,Buffer &,Flow *)343 virtual bool encode(const uint8_t* const /*raw_in */, 344 const uint16_t /*raw_len*/, 345 EncState&, 346 Buffer&, Flow*) 347 { return true; } 348 349 /* 350 * Update this layers checksums and length fields. Used 351 * when rebuilding packets and Snort is in inline mode. 352 * 353 * updated_len MUST be set to this layers updated length. 354 */ update(const ip::IpApi &,const EncodeFlags,uint8_t *,uint16_t lyr_len,uint32_t & updated_len)355 virtual void update( 356 const ip::IpApi&, 357 const EncodeFlags /*flags*/, 358 uint8_t* /*raw_pkt*/, /* The data associated with the current layer */ 359 uint16_t lyr_len, /* This layers previously calculated length */ 360 uint32_t& updated_len) /* Update! The length to end of packet */ 361 { updated_len += lyr_len; } 362 363 // formatter format(bool,uint8_t *,DecodeData &)364 virtual void format(bool /*reverse*/, uint8_t* /*raw_pkt*/, DecodeData&) 365 { } 366 367 protected: Codec(const char * s)368 Codec(const char* s) 369 { name = s; } 370 371 // Create an event with the Codec GID 372 void codec_event(const CodecData &, CodecSid); 373 // Check the Hop and DST IPv6 extension 374 bool CheckIPV6HopOptions(const RawData&, CodecData&); 375 // NOTE:: data.next_prot_id MUST be set before calling this!! 376 void CheckIPv6ExtensionOrder(CodecData&, const IpProtocol); 377 378 private: 379 const char* name; 380 }; 381 382 //------------------------------------------------------------------------- 383 // api 384 //------------------------------------------------------------------------- 385 386 // this is the current version of the api 387 #define CDAPI_VERSION ((BASE_API_VERSION << 16) | 1) 388 389 typedef Codec* (* CdNewFunc)(Module*); 390 typedef void (* CdDelFunc)(Codec*); 391 typedef void (* CdAuxFunc)(); 392 393 struct CodecApi 394 { 395 BaseApi base; 396 397 // these may be nullptr 398 CdAuxFunc pinit; // initialize global plugin data 399 CdAuxFunc pterm; // clean-up pinit() 400 401 CdAuxFunc tinit; // initialize thread-local plugin data 402 CdAuxFunc tterm; // clean-up tinit() 403 404 // these must be set 405 CdNewFunc ctor; // get eval optional instance data 406 CdDelFunc dtor; // clean up instance data 407 }; 408 } 409 #endif /* FRAMEWORK_CODEC_H */ 410 411