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