suricata
decode-gre.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2021 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-validate.h"
40 #include "util-unittest.h"
41 #include "util-debug.h"
42 
43 /**
44  * \brief Function to decode GRE packets
45  */
46 
47 int DecodeGRE(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
48 {
49  DEBUG_VALIDATE_BUG_ON(pkt == NULL);
50 
51  uint32_t header_len = GRE_HDR_LEN;
52  GRESreHdr *gsre = NULL;
53  GREPPtPHd *gre_pptp_h = NULL;
54 
56 
57  if(len < GRE_HDR_LEN) {
59  return TM_ECODE_FAILED;
60  }
61  if (!PacketIncreaseCheckLayers(p)) {
62  return TM_ECODE_FAILED;
63  }
64 
65  p->greh = (GREHdr *)pkt;
66 
67  SCLogDebug("p %p pkt %p GRE protocol %04x Len: %d GRE version %x",
68  p, pkt, GRE_GET_PROTO(p->greh), len,GRE_GET_VERSION(p->greh));
69 
70  switch (GRE_GET_VERSION(p->greh))
71  {
72  case GRE_VERSION_0:
73 
74  /* GRE version 0 doesn't support the fields below RFC 1701 */
75 
76  /**
77  * \todo We need to make sure this does not allow bypassing
78  * inspection. A server may just ignore these and
79  * continue processing the packet, but we will not look
80  * further into it.
81  */
82 
83  if (GRE_FLAG_ISSET_RECUR(p->greh)) {
85  return TM_ECODE_OK;
86  }
87 
88  if (GREV1_FLAG_ISSET_FLAGS(p->greh)) {
90  return TM_ECODE_OK;
91  }
92 
93  /* Adjust header length based on content */
94 
95  if (GRE_FLAG_ISSET_KY(p->greh))
96  header_len += GRE_KEY_LEN;
97 
98  if (GRE_FLAG_ISSET_SQ(p->greh))
99  header_len += GRE_SEQ_LEN;
100 
102  header_len += GRE_CHKSUM_LEN + GRE_OFFSET_LEN;
103 
104  if (header_len > len) {
106  return TM_ECODE_OK;
107  }
108 
109  if (GRE_FLAG_ISSET_ROUTE(p->greh))
110  {
111  while (1)
112  {
113  if ((header_len + GRE_SRE_HDR_LEN) > len) {
116  return TM_ECODE_OK;
117  }
118 
119  gsre = (GRESreHdr *)(pkt + header_len);
120 
121  header_len += GRE_SRE_HDR_LEN;
122 
123  if ((SCNtohs(gsre->af) == 0) && (gsre->sre_length == 0))
124  break;
125 
126  header_len += gsre->sre_length;
127  if (header_len > len) {
130  return TM_ECODE_OK;
131  }
132  }
133  }
134  break;
135 
136  case GRE_VERSION_1:
137 
138  /* GRE version 1 doesn't support the fields below RFC 1701 */
139 
140  /**
141  * \todo We need to make sure this does not allow bypassing
142  * inspection. A server may just ignore these and
143  * continue processing the packet, but we will not look
144  * further into it.
145  */
146 
147  if (GRE_FLAG_ISSET_CHKSUM(p->greh)) {
149  return TM_ECODE_OK;
150  }
151 
152  if (GRE_FLAG_ISSET_ROUTE(p->greh)) {
154  return TM_ECODE_OK;
155  }
156 
157  if (GRE_FLAG_ISSET_SSR(p->greh)) {
159  return TM_ECODE_OK;
160  }
161 
162  if (GRE_FLAG_ISSET_RECUR(p->greh)) {
164  return TM_ECODE_OK;
165  }
166 
167  if (GREV1_FLAG_ISSET_FLAGS(p->greh)) {
169  return TM_ECODE_OK;
170  }
171 
172  if (GRE_GET_PROTO(p->greh) != GRE_PROTO_PPP) {
174  return TM_ECODE_OK;
175  }
176 
177  if (!(GRE_FLAG_ISSET_KY(p->greh))) {
179  return TM_ECODE_OK;
180  }
181 
182  header_len += GRE_KEY_LEN;
183  /* key is set and proto == PPP */
184  gre_pptp_h = (GREPPtPHd *)pkt;
185 
186  /* Adjust header length based on content */
187 
188  if (GRE_FLAG_ISSET_SQ(p->greh))
189  header_len += GRE_SEQ_LEN;
190 
191  if (GREV1_FLAG_ISSET_ACK(p->greh))
192  header_len += GREV1_ACK_LEN;
193 
194  if (header_len > len) {
196  return TM_ECODE_OK;
197  }
198 
199  break;
200  default:
202  return TM_ECODE_OK;
203  }
204 
205  switch (GRE_GET_PROTO(p->greh))
206  {
207  case ETHERNET_TYPE_IP:
208  {
209  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
210  len - header_len, DECODE_TUNNEL_IPV4);
211  if (tp != NULL) {
214  }
215  break;
216  }
217 
218  case GRE_PROTO_PPP:
219  {
220  if (gre_pptp_h && !gre_pptp_h->payload_length)
221  return TM_ECODE_OK;
222 
223  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
224  len - header_len, DECODE_TUNNEL_PPP);
225  if (tp != NULL) {
228  }
229  break;
230  }
231 
232  case ETHERNET_TYPE_IPV6:
233  {
234  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
235  len - header_len, DECODE_TUNNEL_IPV6);
236  if (tp != NULL) {
239  }
240  break;
241  }
242 
243  case ETHERNET_TYPE_VLAN:
244  {
245  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
246  len - header_len, DECODE_TUNNEL_VLAN);
247  if (tp != NULL) {
250  }
251  break;
252  }
253 
255  {
256  // Determine if it's Type I or Type II based on the flags in the GRE header.
257  // Type I: 0|0|0|0|0|00000|000000000|00000
258  // Type II: 0|0|0|1|0|00000|000000000|00000
259  // Seq
260  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
261  len - header_len,
262  GRE_FLAG_ISSET_SQ(p->greh) == 0 ?
265  if (tp != NULL) {
268  }
269  break;
270  }
271 
273  {
274  Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
275  len - header_len, DECODE_TUNNEL_ETHERNET);
276  if (tp != NULL) {
279  }
280  break;
281  }
282 
283  default:
284  return TM_ECODE_OK;
285  }
286  return TM_ECODE_OK;
287 }
288 
289 
290 #ifdef UNITTESTS
291 /**
292  * \test DecodeGRETest01 is a test for small gre packet
293  */
294 
295 static int DecodeGREtest01 (void)
296 {
297  uint8_t raw_gre[] = { 0x00 ,0x6e ,0x62 };
298  Packet *p = PacketGetFromAlloc();
299  FAIL_IF_NULL(p);
300  ThreadVars tv;
302 
303  memset(&tv, 0, sizeof(ThreadVars));
304  memset(&dtv, 0, sizeof(DecodeThreadVars));
305 
306  DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre));
308 
309  SCFree(p);
310  PASS;
311 }
312 
313 /**
314  * \test DecodeGRETest02 is a test for wrong gre version
315  */
316 
317 static int DecodeGREtest02 (void)
318 {
319  uint8_t raw_gre[] = {
320  0x00, 0x6e, 0x62, 0xac, 0x40, 0x00, 0x40, 0x2f,
321  0xc2, 0xc7, 0x0a, 0x00, 0x00, 0x64, 0x0a, 0x00,
322  0x00, 0x8a, 0x30, 0x01, 0x0b, 0x00, 0x4e, 0x00,
323  0x00, 0x00, 0x18, 0x4a, 0x50, 0xff, 0x03, 0x00,
324  0x21, 0x45, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x40,
325  0x00, 0x40, 0x11, 0x94, 0x22, 0x50, 0x7e, 0x2b,
326  0x2d, 0xc2, 0x6d, 0x68, 0x68, 0x80, 0x0e, 0x00,
327  0x35, 0x00, 0x36, 0x9f, 0x18, 0xdb, 0xc4, 0x01,
328  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
329  0x01, 0x03, 0x73, 0x31, 0x36, 0x09, 0x73, 0x69,
330  0x74, 0x65, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x03,
331  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
332  0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00, 0x00,
333  0x00, 0x00, 0x00 };
334  Packet *p = PacketGetFromAlloc();
335  FAIL_IF_NULL(p);
336  ThreadVars tv;
338 
339  memset(&tv, 0, sizeof(ThreadVars));
340  memset(&dtv, 0, sizeof(DecodeThreadVars));
341 
342  DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre));
344 
345  SCFree(p);
346  PASS;
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  FAIL_IF_NULL(p);
373  ThreadVars tv;
375 
376  memset(&tv, 0, sizeof(ThreadVars));
377  memset(&dtv, 0, sizeof(DecodeThreadVars));
378 
379  DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre));
380  FAIL_IF_NULL(p->greh);
381 
382  SCFree(p);
383  PASS;
384 }
385 #endif /* UNITTESTS */
386 
387 /**
388  * \brief this function registers unit tests for GRE decoder
389  */
390 
392 {
393 #ifdef UNITTESTS
394  UtRegisterTest("DecodeGREtest01", DecodeGREtest01);
395  UtRegisterTest("DecodeGREtest02", DecodeGREtest02);
396  UtRegisterTest("DecodeGREtest03", DecodeGREtest03);
397 #endif /* UNITTESTS */
398 }
399 /**
400  * @}
401  */
Packet_::greh
GREHdr * greh
Definition: decode.h:547
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:72
GRE_FLAG_ISSET_ROUTE
#define GRE_FLAG_ISSET_ROUTE(r)
Definition: decode-gre.h:73
len
uint8_t len
Definition: app-layer-dnp3.h:2
DECODE_TUNNEL_IPV6
@ DECODE_TUNNEL_IPV6
Definition: decode.h:938
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
StatsIncr
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition: counters.c:169
GRE_VERSION1_NO_KEY
@ GRE_VERSION1_NO_KEY
Definition: decode-events.h:138
GREV1_ACK_LEN
#define GREV1_ACK_LEN
Definition: decode-gre.h:83
GRE_VERSION0_HDR_TOO_BIG
@ GRE_VERSION0_HDR_TOO_BIG
Definition: decode-events.h:131
GRE_FLAG_ISSET_RECUR
#define GRE_FLAG_ISSET_RECUR(r)
Definition: decode-gre.h:77
GRE_VERSION1_SSR
@ GRE_VERSION1_SSR
Definition: decode-events.h:135
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:1051
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
GRE_WRONG_VERSION
@ GRE_WRONG_VERSION
Definition: decode-events.h:128
ETHERNET_TYPE_IPV6
#define ETHERNET_TYPE_IPV6
Definition: decode-ethernet.h:39
GRE_HDR_LEN
#define GRE_HDR_LEN
Definition: decode-gre.h:64
DECODE_TUNNEL_ERSPANI
@ DECODE_TUNNEL_ERSPANI
Definition: decode.h:935
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_VERSION1_CHKSUM
@ GRE_VERSION1_CHKSUM
Definition: decode-events.h:133
util-unittest.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
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:1204
GREV1_FLAG_ISSET_FLAGS
#define GREV1_FLAG_ISSET_FLAGS(r)
Definition: decode-gre.h:84
decode-gre.h
DECODE_TUNNEL_ERSPANII
@ DECODE_TUNNEL_ERSPANII
Definition: decode.h:934
decode.h
util-debug.h
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
GRE_FLAG_ISSET_SQ
#define GRE_FLAG_ISSET_SQ(r)
Definition: decode-gre.h:75
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
DECODE_TUNNEL_PPP
@ DECODE_TUNNEL_PPP
Definition: decode.h:940
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:47
GRE_VERSION_0
#define GRE_VERSION_0
Definition: decode-gre.h:61
GRE_KEY_LEN
#define GRE_KEY_LEN
Definition: decode-gre.h:67
DECODE_TUNNEL_VLAN
@ DECODE_TUNNEL_VLAN
Definition: decode.h:936
Packet_
Definition: decode.h:414
DECODE_TUNNEL_IPV4
@ DECODE_TUNNEL_IPV4
Definition: decode.h:937
GRE_VERSION1_WRONG_PROTOCOL
@ GRE_VERSION1_WRONG_PROTOCOL
Definition: decode-events.h:139
GRE_VERSION0_MALFORMED_SRE_HDR
@ GRE_VERSION0_MALFORMED_SRE_HDR
Definition: decode-events.h:132
GRE_VERSION1_FLAGS
@ GRE_VERSION1_FLAGS
Definition: decode-events.h:137
DECODE_TUNNEL_ETHERNET
@ DECODE_TUNNEL_ETHERNET
Definition: decode.h:933
GRE_VERSION0_FLAGS
@ GRE_VERSION0_FLAGS
Definition: decode-events.h:130
GRE_OFFSET_LEN
#define GRE_OFFSET_LEN
Definition: decode-gre.h:66
decode-events.h
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:30
GRE_CHKSUM_LEN
#define GRE_CHKSUM_LEN
Definition: decode-gre.h:65
PacketEnqueueNoLock
void PacketEnqueueNoLock(PacketQueueNoLock *qnl, Packet *p)
Definition: packet-queue.c:167
SCNtohs
#define SCNtohs(x)
Definition: suricata-common.h:395
suricata-common.h
GREV1_FLAG_ISSET_ACK
#define GREV1_FLAG_ISSET_ACK(r)
Definition: decode-gre.h:85
DecodeThreadVars_::counter_gre
uint16_t counter_gre
Definition: decode.h:668
GRE_SRE_HDR_LEN
#define GRE_SRE_HDR_LEN
Definition: decode-gre.h:69
GRE_PROTO_PPP
#define GRE_PROTO_PPP
Definition: decode-gre.h:70
GRE_VERSION1_RECUR
@ GRE_VERSION1_RECUR
Definition: decode-events.h:136
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:29
util-validate.h
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:151
GRE_PKT_TOO_SMALL
@ GRE_PKT_TOO_SMALL
Definition: decode-events.h:127
SCFree
#define SCFree(p)
Definition: util-mem.h:61
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:638
DecodeGRERegisterTests
void DecodeGRERegisterTests(void)
this function registers unit tests for GRE decoder
Definition: decode-gre.c:391
GRE_GET_PROTO
#define GRE_GET_PROTO(r)
Definition: decode-gre.h:80
GRE_VERSION0_RECUR
@ GRE_VERSION0_RECUR
Definition: decode-events.h:129
ThreadVars_::decode_pq
PacketQueueNoLock decode_pq
Definition: threadvars.h:110
GRE_FLAG_ISSET_KY
#define GRE_FLAG_ISSET_KY(r)
Definition: decode-gre.h:74
GRE_FLAG_ISSET_SSR
#define GRE_FLAG_ISSET_SSR(r)
Definition: decode-gre.h:76
suricata.h
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:1044
ETHERNET_TYPE_VLAN
#define ETHERNET_TYPE_VLAN
Definition: decode-vlan.h:31
GRE_SEQ_LEN
#define GRE_SEQ_LEN
Definition: decode-gre.h:68
GRE_GET_VERSION
#define GRE_GET_VERSION(r)
Definition: decode-gre.h:78
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:289
GRE_VERSION1_HDR_TOO_BIG
@ GRE_VERSION1_HDR_TOO_BIG
Definition: decode-events.h:141
GRE_VERSION_1
#define GRE_VERSION_1
Definition: decode-gre.h:62
ETHERNET_TYPE_IP
#define ETHERNET_TYPE_IP
Definition: decode-ethernet.h:34
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:111
GRE_VERSION1_ROUTE
@ GRE_VERSION1_ROUTE
Definition: decode-events.h:134