suricata
decode-gre.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2020 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \ingroup decode
20  *
21  * @{
22  */
23 
24 
25 /**
26  * \file
27  *
28  * \author Breno Silva <breno.silva@gmail.com>
29  *
30  * Decodes GRE
31  */
32 
33 #include "suricata-common.h"
34 #include "suricata.h"
35 #include "decode.h"
36 #include "decode-events.h"
37 #include "decode-gre.h"
38 
39 #include "util-unittest.h"
40 #include "util-debug.h"
41 
42 /**
43  * \brief Function to decode GRE packets
44  */
45 
46 int DecodeGRE(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
47 {
48  uint32_t header_len = GRE_HDR_LEN;
49  GRESreHdr *gsre = NULL;
50 
52 
53  if(len < GRE_HDR_LEN) {
55  return TM_ECODE_FAILED;
56  }
57 
58  p->greh = (GREHdr *)pkt;
59  if(p->greh == NULL)
60  return TM_ECODE_FAILED;
61 
62  SCLogDebug("p %p pkt %p GRE protocol %04x Len: %d GRE version %x",
63  p, pkt, GRE_GET_PROTO(p->greh), len,GRE_GET_VERSION(p->greh));
64 
65  switch (GRE_GET_VERSION(p->greh))
66  {
67  case GRE_VERSION_0:
68 
69  /* GRE version 0 doesn't support the fields below RFC 1701 */
70 
71  /**
72  * \todo We need to make sure this does not allow bypassing
73  * inspection. A server may just ignore these and
74  * continue processing the packet, but we will not look
75  * further into it.
76  */
77 
78  if (GRE_FLAG_ISSET_RECUR(p->greh)) {
80  return TM_ECODE_OK;
81  }
82 
83  if (GREV1_FLAG_ISSET_FLAGS(p->greh)) {
85  return TM_ECODE_OK;
86  }
87 
88  /* Adjust header length based on content */
89 
90  if (GRE_FLAG_ISSET_KY(p->greh))
91  header_len += GRE_KEY_LEN;
92 
93  if (GRE_FLAG_ISSET_SQ(p->greh))
94  header_len += GRE_SEQ_LEN;
95 
97  header_len += GRE_CHKSUM_LEN + GRE_OFFSET_LEN;
98 
99  if (header_len > len) {
101  return TM_ECODE_OK;
102  }
103 
104  if (GRE_FLAG_ISSET_ROUTE(p->greh))
105  {
106  while (1)
107  {
108  if ((header_len + GRE_SRE_HDR_LEN) > len) {
111  return TM_ECODE_OK;
112  }
113 
114  gsre = (GRESreHdr *)(pkt + header_len);
115 
116  header_len += GRE_SRE_HDR_LEN;
117 
118  if ((SCNtohs(gsre->af) == 0) && (gsre->sre_length == 0))
119  break;
120 
121  header_len += gsre->sre_length;
122  if (header_len > len) {
125  return TM_ECODE_OK;
126  }
127  }
128  }
129  break;
130 
131  case GRE_VERSION_1:
132 
133  /* GRE version 1 doesn't support the fields below RFC 1701 */
134 
135  /**
136  * \todo We need to make sure this does not allow bypassing
137  * inspection. A server may just ignore these and
138  * continue processing the packet, but we will not look
139  * further into it.
140  */
141 
142  if (GRE_FLAG_ISSET_CHKSUM(p->greh)) {
144  return TM_ECODE_OK;
145  }
146 
147  if (GRE_FLAG_ISSET_ROUTE(p->greh)) {
149  return TM_ECODE_OK;
150  }
151 
152  if (GRE_FLAG_ISSET_SSR(p->greh)) {
154  return TM_ECODE_OK;
155  }
156 
157  if (GRE_FLAG_ISSET_RECUR(p->greh)) {
159  return TM_ECODE_OK;
160  }
161 
162  if (GREV1_FLAG_ISSET_FLAGS(p->greh)) {
164  return TM_ECODE_OK;
165  }
166 
167  if (GRE_GET_PROTO(p->greh) != GRE_PROTO_PPP) {
169  return TM_ECODE_OK;
170  }
171 
172  if (!(GRE_FLAG_ISSET_KY(p->greh))) {
174  return TM_ECODE_OK;
175  }
176 
177  header_len += GRE_KEY_LEN;
178 
179  /* Adjust header length based on content */
180 
181  if (GRE_FLAG_ISSET_SQ(p->greh))
182  header_len += GRE_SEQ_LEN;
183 
184  if (GREV1_FLAG_ISSET_ACK(p->greh))
185  header_len += GREV1_ACK_LEN;
186 
187  if (header_len > len) {
189  return TM_ECODE_OK;
190  }
191 
192  break;
193  default:
195  return TM_ECODE_OK;
196  }
197 
198  switch (GRE_GET_PROTO(p->greh))
199  {
200  case ETHERNET_TYPE_IP:
201  {
202  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
203  len - header_len, DECODE_TUNNEL_IPV4);
204  if (tp != NULL) {
207  }
208  break;
209  }
210 
211  case GRE_PROTO_PPP:
212  {
213  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
214  len - header_len, DECODE_TUNNEL_PPP);
215  if (tp != NULL) {
218  }
219  break;
220  }
221 
222  case ETHERNET_TYPE_IPV6:
223  {
224  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
225  len - header_len, DECODE_TUNNEL_IPV6);
226  if (tp != NULL) {
229  }
230  break;
231  }
232 
233  case ETHERNET_TYPE_VLAN:
234  {
235  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
236  len - header_len, DECODE_TUNNEL_VLAN);
237  if (tp != NULL) {
240  }
241  break;
242  }
243 
245  {
246  // Determine if it's Type I or Type II based on the flags in the GRE header.
247  // Type I: 0|0|0|0|0|00000|000000000|00000
248  // Type II: 0|0|0|1|0|00000|000000000|00000
249  // Seq
250  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
251  len - header_len,
252  GRE_FLAG_ISSET_SQ(p->greh) == 0 ?
255  if (tp != NULL) {
258  }
259  break;
260  }
261 
263  {
264  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
265  len - header_len, DECODE_TUNNEL_ETHERNET);
266  if (tp != NULL) {
269  }
270  break;
271  }
272 
273  default:
274  return TM_ECODE_OK;
275  }
276  return TM_ECODE_OK;
277 }
278 
279 
280 #ifdef UNITTESTS
281 /**
282  * \test DecodeGRETest01 is a test for small gre packet
283  */
284 
285 static int DecodeGREtest01 (void)
286 {
287  uint8_t raw_gre[] = { 0x00 ,0x6e ,0x62 };
288  Packet *p = PacketGetFromAlloc();
289  if (unlikely(p == NULL))
290  return 0;
291  ThreadVars tv;
293 
294  memset(&tv, 0, sizeof(ThreadVars));
295  memset(&dtv, 0, sizeof(DecodeThreadVars));
296 
297  DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre));
298 
300  SCFree(p);
301  return 1;
302  }
303 
304  SCFree(p);
305  return 0;
306 }
307 
308 /**
309  * \test DecodeGRETest02 is a test for wrong gre version
310  */
311 
312 static int DecodeGREtest02 (void)
313 {
314  uint8_t raw_gre[] = {
315  0x00, 0x6e, 0x62, 0xac, 0x40, 0x00, 0x40, 0x2f,
316  0xc2, 0xc7, 0x0a, 0x00, 0x00, 0x64, 0x0a, 0x00,
317  0x00, 0x8a, 0x30, 0x01, 0x0b, 0x00, 0x4e, 0x00,
318  0x00, 0x00, 0x18, 0x4a, 0x50, 0xff, 0x03, 0x00,
319  0x21, 0x45, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x40,
320  0x00, 0x40, 0x11, 0x94, 0x22, 0x50, 0x7e, 0x2b,
321  0x2d, 0xc2, 0x6d, 0x68, 0x68, 0x80, 0x0e, 0x00,
322  0x35, 0x00, 0x36, 0x9f, 0x18, 0xdb, 0xc4, 0x01,
323  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
324  0x01, 0x03, 0x73, 0x31, 0x36, 0x09, 0x73, 0x69,
325  0x74, 0x65, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x03,
326  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
327  0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00, 0x00,
328  0x00, 0x00, 0x00 };
329  Packet *p = PacketGetFromAlloc();
330  if (unlikely(p == NULL))
331  return 0;
332  ThreadVars tv;
334 
335  memset(&tv, 0, sizeof(ThreadVars));
336  memset(&dtv, 0, sizeof(DecodeThreadVars));
337 
338  DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre));
339 
341  SCFree(p);
342  return 1;
343  }
344 
345  SCFree(p);
346  return 0;
347 }
348 
349 
350 /**
351  * \test DecodeGRETest03 is a test for valid gre packet
352  */
353 
354 static int DecodeGREtest03 (void)
355 {
356  uint8_t raw_gre[] = {
357  0x00, 0x6e, 0x62, 0xac, 0x40, 0x00, 0x40, 0x2f,
358  0xc2, 0xc7, 0x0a, 0x00, 0x00, 0x64, 0x0a, 0x00,
359  0x00, 0x8a, 0x30, 0x01, 0x88, 0x0b, 0x00, 0x4e,
360  0x00, 0x00, 0x00, 0x18, 0x4a, 0x50, 0xff, 0x03,
361  0x00, 0x21, 0x45, 0x00, 0x00, 0x4a, 0x00, 0x00,
362  0x40, 0x00, 0x40, 0x11, 0x94, 0x22, 0x50, 0x7e,
363  0x2b, 0x2d, 0xc2, 0x6d, 0x68, 0x68, 0x80, 0x0e,
364  0x00, 0x35, 0x00, 0x36, 0x9f, 0x18, 0xdb, 0xc4,
365  0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
366  0x00, 0x01, 0x03, 0x73, 0x31, 0x36, 0x09, 0x73,
367  0x69, 0x74, 0x65, 0x6d, 0x65, 0x74, 0x65, 0x72,
368  0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
369  0x01, 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00,
370  0x00, 0x00, 0x00, 0x00 };
371  Packet *p = PacketGetFromAlloc();
372  if (unlikely(p == NULL))
373  return 0;
374  ThreadVars tv;
376 
377  memset(&tv, 0, sizeof(ThreadVars));
378  memset(&dtv, 0, sizeof(DecodeThreadVars));
379 
380  DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre));
381 
382  if(p->greh == NULL) {
383  SCFree(p);
384  return 0;
385  }
386 
387 
388  SCFree(p);
389  return 1;
390 }
391 #endif /* UNITTESTS */
392 
393 /**
394  * \brief this function registers unit tests for GRE decoder
395  */
396 
398 {
399 #ifdef UNITTESTS
400  UtRegisterTest("DecodeGREtest01", DecodeGREtest01);
401  UtRegisterTest("DecodeGREtest02", DecodeGREtest02);
402  UtRegisterTest("DecodeGREtest03", DecodeGREtest03);
403 #endif /* UNITTESTS */
404 }
405 /**
406  * @}
407  */
GRE_VERSION0_HDR_TOO_BIG
@ GRE_VERSION0_HDR_TOO_BIG
Definition: decode-events.h:131
GRE_VERSION1_WRONG_PROTOCOL
@ GRE_VERSION1_WRONG_PROTOCOL
Definition: decode-events.h:139
Packet_::greh
GREHdr * greh
Definition: decode.h:545
ETHERNET_TYPE_BRIDGE
#define ETHERNET_TYPE_BRIDGE
Definition: decode-ethernet.h:36
GRE_FLAG_ISSET_CHKSUM
#define GRE_FLAG_ISSET_CHKSUM(r)
Definition: decode-gre.h:65
GRE_FLAG_ISSET_ROUTE
#define GRE_FLAG_ISSET_ROUTE(r)
Definition: decode-gre.h:66
len
uint8_t len
Definition: app-layer-dnp3.h:2
DECODE_TUNNEL_IPV6
@ DECODE_TUNNEL_IPV6
Definition: decode.h:908
StatsIncr
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition: counters.c:169
GREV1_ACK_LEN
#define GREV1_ACK_LEN
Definition: decode-gre.h:76
GRE_VERSION1_RECUR
@ GRE_VERSION1_RECUR
Definition: decode-events.h:136
GRE_VERSION0_RECUR
@ GRE_VERSION0_RECUR
Definition: decode-events.h:129
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
GRE_FLAG_ISSET_RECUR
#define GRE_FLAG_ISSET_RECUR(r)
Definition: decode-gre.h:70
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
ENGINE_ISSET_EVENT
#define ENGINE_ISSET_EVENT(p, e)
Definition: decode.h:1018
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
ETHERNET_TYPE_IPV6
#define ETHERNET_TYPE_IPV6
Definition: decode-ethernet.h:39
GRE_HDR_LEN
#define GRE_HDR_LEN
Definition: decode-gre.h:57
GRE_VERSION1_CHKSUM
@ GRE_VERSION1_CHKSUM
Definition: decode-events.h:133
DECODE_TUNNEL_ERSPANI
@ DECODE_TUNNEL_ERSPANI
Definition: decode.h:905
ETHERNET_TYPE_ERSPAN
#define ETHERNET_TYPE_ERSPAN
Definition: decode-ethernet.h:48
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:81
GRE_WRONG_VERSION
@ GRE_WRONG_VERSION
Definition: decode-events.h:128
util-unittest.h
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:80
PKT_SET_SRC
#define PKT_SET_SRC(p, src_val)
Definition: decode.h:1150
GREV1_FLAG_ISSET_FLAGS
#define GREV1_FLAG_ISSET_FLAGS(r)
Definition: decode-gre.h:77
decode-gre.h
DECODE_TUNNEL_ERSPANII
@ DECODE_TUNNEL_ERSPANII
Definition: decode.h:904
GRE_VERSION1_SSR
@ GRE_VERSION1_SSR
Definition: decode-events.h:135
decode.h
util-debug.h
GRE_FLAG_ISSET_SQ
#define GRE_FLAG_ISSET_SQ(r)
Definition: decode-gre.h:68
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
DECODE_TUNNEL_PPP
@ DECODE_TUNNEL_PPP
Definition: decode.h:910
DecodeGRE
int DecodeGRE(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Function to decode GRE packets.
Definition: decode-gre.c:46
GRE_VERSION_0
#define GRE_VERSION_0
Definition: decode-gre.h:54
GRE_VERSION0_FLAGS
@ GRE_VERSION0_FLAGS
Definition: decode-events.h:130
GRE_KEY_LEN
#define GRE_KEY_LEN
Definition: decode-gre.h:60
DECODE_TUNNEL_VLAN
@ DECODE_TUNNEL_VLAN
Definition: decode.h:906
Packet_
Definition: decode.h:414
DECODE_TUNNEL_IPV4
@ DECODE_TUNNEL_IPV4
Definition: decode.h:907
DECODE_TUNNEL_ETHERNET
@ DECODE_TUNNEL_ETHERNET
Definition: decode.h:903
GRE_OFFSET_LEN
#define GRE_OFFSET_LEN
Definition: decode-gre.h:59
decode-events.h
GRE_VERSION1_ROUTE
@ GRE_VERSION1_ROUTE
Definition: decode-events.h:134
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:30
GRE_CHKSUM_LEN
#define GRE_CHKSUM_LEN
Definition: decode-gre.h:58
PacketEnqueueNoLock
void PacketEnqueueNoLock(PacketQueueNoLock *qnl, Packet *p)
Definition: packet-queue.c:167
GRE_VERSION1_HDR_TOO_BIG
@ GRE_VERSION1_HDR_TOO_BIG
Definition: decode-events.h:141
SCNtohs
#define SCNtohs(x)
Definition: suricata-common.h:398
suricata-common.h
GRE_PKT_TOO_SMALL
@ GRE_PKT_TOO_SMALL
Definition: decode-events.h:127
GREV1_FLAG_ISSET_ACK
#define GREV1_FLAG_ISSET_ACK(r)
Definition: decode-gre.h:78
DecodeThreadVars_::counter_gre
uint16_t counter_gre
Definition: decode.h:660
GRE_SRE_HDR_LEN
#define GRE_SRE_HDR_LEN
Definition: decode-gre.h:62
GRE_PROTO_PPP
#define GRE_PROTO_PPP
Definition: decode-gre.h:63
GRE_VERSION1_NO_KEY
@ GRE_VERSION1_NO_KEY
Definition: decode-events.h:138
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:29
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:144
SCFree
#define SCFree(p)
Definition: util-mem.h:61
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:631
DecodeGRERegisterTests
void DecodeGRERegisterTests(void)
this function registers unit tests for GRE decoder
Definition: decode-gre.c:397
GRE_GET_PROTO
#define GRE_GET_PROTO(r)
Definition: decode-gre.h:73
ThreadVars_::decode_pq
PacketQueueNoLock decode_pq
Definition: threadvars.h:110
GRE_FLAG_ISSET_KY
#define GRE_FLAG_ISSET_KY(r)
Definition: decode-gre.h:67
GRE_FLAG_ISSET_SSR
#define GRE_FLAG_ISSET_SSR(r)
Definition: decode-gre.h:69
suricata.h
GRE_VERSION1_FLAGS
@ GRE_VERSION1_FLAGS
Definition: decode-events.h:137
PKT_SRC_DECODER_GRE
@ PKT_SRC_DECODER_GRE
Definition: decode.h:52
ENGINE_SET_INVALID_EVENT
#define ENGINE_SET_INVALID_EVENT(p, e)
Definition: decode.h:1011
GRE_VERSION0_MALFORMED_SRE_HDR
@ GRE_VERSION0_MALFORMED_SRE_HDR
Definition: decode-events.h:132
ETHERNET_TYPE_VLAN
#define ETHERNET_TYPE_VLAN
Definition: decode-vlan.h:31
GRE_SEQ_LEN
#define GRE_SEQ_LEN
Definition: decode-gre.h:61
GRE_GET_VERSION
#define GRE_GET_VERSION(r)
Definition: decode-gre.h:71
PacketTunnelPktSetup
Packet * PacketTunnelPktSetup(ThreadVars *tv, DecodeThreadVars *dtv, Packet *parent, const uint8_t *pkt, uint32_t len, enum DecodeTunnelProto proto)
Setup a pseudo packet (tunnel)
Definition: decode.c:278
GRE_VERSION_1
#define GRE_VERSION_1
Definition: decode-gre.h:55
ETHERNET_TYPE_IP
#define ETHERNET_TYPE_IP
Definition: decode-ethernet.h:34