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
DecodeGRE(ThreadVars * tv,DecodeThreadVars * dtv,Packet * p,const uint8_t * pkt,uint32_t len)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
51 StatsIncr(tv, dtv->counter_gre);
52
53 if(len < GRE_HDR_LEN) {
54 ENGINE_SET_INVALID_EVENT(p, GRE_PKT_TOO_SMALL);
55 return TM_ECODE_FAILED;
56 }
57 if (!PacketIncreaseCheckLayers(p)) {
58 return TM_ECODE_FAILED;
59 }
60
61 p->greh = (GREHdr *)pkt;
62 if(p->greh == NULL)
63 return TM_ECODE_FAILED;
64
65 SCLogDebug("p %p pkt %p GRE protocol %04x Len: %d GRE version %x",
66 p, pkt, GRE_GET_PROTO(p->greh), len,GRE_GET_VERSION(p->greh));
67
68 switch (GRE_GET_VERSION(p->greh))
69 {
70 case GRE_VERSION_0:
71
72 /* GRE version 0 doesn't support the fields below RFC 1701 */
73
74 /**
75 * \todo We need to make sure this does not allow bypassing
76 * inspection. A server may just ignore these and
77 * continue processing the packet, but we will not look
78 * further into it.
79 */
80
81 if (GRE_FLAG_ISSET_RECUR(p->greh)) {
82 ENGINE_SET_INVALID_EVENT(p, GRE_VERSION0_RECUR);
83 return TM_ECODE_OK;
84 }
85
86 if (GREV1_FLAG_ISSET_FLAGS(p->greh)) {
87 ENGINE_SET_INVALID_EVENT(p, GRE_VERSION0_FLAGS);
88 return TM_ECODE_OK;
89 }
90
91 /* Adjust header length based on content */
92
93 if (GRE_FLAG_ISSET_KY(p->greh))
94 header_len += GRE_KEY_LEN;
95
96 if (GRE_FLAG_ISSET_SQ(p->greh))
97 header_len += GRE_SEQ_LEN;
98
99 if (GRE_FLAG_ISSET_CHKSUM(p->greh) || GRE_FLAG_ISSET_ROUTE(p->greh))
100 header_len += GRE_CHKSUM_LEN + GRE_OFFSET_LEN;
101
102 if (header_len > len) {
103 ENGINE_SET_INVALID_EVENT(p, GRE_VERSION0_HDR_TOO_BIG);
104 return TM_ECODE_OK;
105 }
106
107 if (GRE_FLAG_ISSET_ROUTE(p->greh))
108 {
109 while (1)
110 {
111 if ((header_len + GRE_SRE_HDR_LEN) > len) {
112 ENGINE_SET_INVALID_EVENT(p,
113 GRE_VERSION0_MALFORMED_SRE_HDR);
114 return TM_ECODE_OK;
115 }
116
117 gsre = (GRESreHdr *)(pkt + header_len);
118
119 header_len += GRE_SRE_HDR_LEN;
120
121 if ((SCNtohs(gsre->af) == 0) && (gsre->sre_length == 0))
122 break;
123
124 header_len += gsre->sre_length;
125 if (header_len > len) {
126 ENGINE_SET_INVALID_EVENT(p,
127 GRE_VERSION0_MALFORMED_SRE_HDR);
128 return TM_ECODE_OK;
129 }
130 }
131 }
132 break;
133
134 case GRE_VERSION_1:
135
136 /* GRE version 1 doesn't support the fields below RFC 1701 */
137
138 /**
139 * \todo We need to make sure this does not allow bypassing
140 * inspection. A server may just ignore these and
141 * continue processing the packet, but we will not look
142 * further into it.
143 */
144
145 if (GRE_FLAG_ISSET_CHKSUM(p->greh)) {
146 ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_CHKSUM);
147 return TM_ECODE_OK;
148 }
149
150 if (GRE_FLAG_ISSET_ROUTE(p->greh)) {
151 ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_ROUTE);
152 return TM_ECODE_OK;
153 }
154
155 if (GRE_FLAG_ISSET_SSR(p->greh)) {
156 ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_SSR);
157 return TM_ECODE_OK;
158 }
159
160 if (GRE_FLAG_ISSET_RECUR(p->greh)) {
161 ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_RECUR);
162 return TM_ECODE_OK;
163 }
164
165 if (GREV1_FLAG_ISSET_FLAGS(p->greh)) {
166 ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_FLAGS);
167 return TM_ECODE_OK;
168 }
169
170 if (GRE_GET_PROTO(p->greh) != GRE_PROTO_PPP) {
171 ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_WRONG_PROTOCOL);
172 return TM_ECODE_OK;
173 }
174
175 if (!(GRE_FLAG_ISSET_KY(p->greh))) {
176 ENGINE_SET_INVALID_EVENT(p,GRE_VERSION1_NO_KEY);
177 return TM_ECODE_OK;
178 }
179
180 header_len += GRE_KEY_LEN;
181
182 /* Adjust header length based on content */
183
184 if (GRE_FLAG_ISSET_SQ(p->greh))
185 header_len += GRE_SEQ_LEN;
186
187 if (GREV1_FLAG_ISSET_ACK(p->greh))
188 header_len += GREV1_ACK_LEN;
189
190 if (header_len > len) {
191 ENGINE_SET_INVALID_EVENT(p, GRE_VERSION1_HDR_TOO_BIG);
192 return TM_ECODE_OK;
193 }
194
195 break;
196 default:
197 ENGINE_SET_INVALID_EVENT(p, GRE_WRONG_VERSION);
198 return TM_ECODE_OK;
199 }
200
201 switch (GRE_GET_PROTO(p->greh))
202 {
203 case ETHERNET_TYPE_IP:
204 {
205 Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
206 len - header_len, DECODE_TUNNEL_IPV4);
207 if (tp != NULL) {
208 PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
209 PacketEnqueueNoLock(&tv->decode_pq,tp);
210 }
211 break;
212 }
213
214 case GRE_PROTO_PPP:
215 {
216 Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
217 len - header_len, DECODE_TUNNEL_PPP);
218 if (tp != NULL) {
219 PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
220 PacketEnqueueNoLock(&tv->decode_pq,tp);
221 }
222 break;
223 }
224
225 case ETHERNET_TYPE_IPV6:
226 {
227 Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
228 len - header_len, DECODE_TUNNEL_IPV6);
229 if (tp != NULL) {
230 PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
231 PacketEnqueueNoLock(&tv->decode_pq,tp);
232 }
233 break;
234 }
235
236 case ETHERNET_TYPE_VLAN:
237 {
238 Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
239 len - header_len, DECODE_TUNNEL_VLAN);
240 if (tp != NULL) {
241 PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
242 PacketEnqueueNoLock(&tv->decode_pq,tp);
243 }
244 break;
245 }
246
247 case ETHERNET_TYPE_ERSPAN:
248 {
249 // Determine if it's Type I or Type II based on the flags in the GRE header.
250 // Type I: 0|0|0|0|0|00000|000000000|00000
251 // Type II: 0|0|0|1|0|00000|000000000|00000
252 // Seq
253 Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
254 len - header_len,
255 GRE_FLAG_ISSET_SQ(p->greh) == 0 ?
256 DECODE_TUNNEL_ERSPANI :
257 DECODE_TUNNEL_ERSPANII);
258 if (tp != NULL) {
259 PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
260 PacketEnqueueNoLock(&tv->decode_pq,tp);
261 }
262 break;
263 }
264
265 case ETHERNET_TYPE_BRIDGE:
266 {
267 Packet *tp = PacketTunnelPktSetup(tv, dtv, p, pkt + header_len,
268 len - header_len, DECODE_TUNNEL_ETHERNET);
269 if (tp != NULL) {
270 PKT_SET_SRC(tp, PKT_SRC_DECODER_GRE);
271 PacketEnqueueNoLock(&tv->decode_pq,tp);
272 }
273 break;
274 }
275
276 default:
277 return TM_ECODE_OK;
278 }
279 return TM_ECODE_OK;
280 }
281
282
283 #ifdef UNITTESTS
284 /**
285 * \test DecodeGRETest01 is a test for small gre packet
286 */
287
DecodeGREtest01(void)288 static int DecodeGREtest01 (void)
289 {
290 uint8_t raw_gre[] = { 0x00 ,0x6e ,0x62 };
291 Packet *p = PacketGetFromAlloc();
292 if (unlikely(p == NULL))
293 return 0;
294 ThreadVars tv;
295 DecodeThreadVars dtv;
296
297 memset(&tv, 0, sizeof(ThreadVars));
298 memset(&dtv, 0, sizeof(DecodeThreadVars));
299
300 DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre));
301
302 if(ENGINE_ISSET_EVENT(p,GRE_PKT_TOO_SMALL)) {
303 SCFree(p);
304 return 1;
305 }
306
307 SCFree(p);
308 return 0;
309 }
310
311 /**
312 * \test DecodeGRETest02 is a test for wrong gre version
313 */
314
DecodeGREtest02(void)315 static int DecodeGREtest02 (void)
316 {
317 uint8_t raw_gre[] = {
318 0x00, 0x6e, 0x62, 0xac, 0x40, 0x00, 0x40, 0x2f,
319 0xc2, 0xc7, 0x0a, 0x00, 0x00, 0x64, 0x0a, 0x00,
320 0x00, 0x8a, 0x30, 0x01, 0x0b, 0x00, 0x4e, 0x00,
321 0x00, 0x00, 0x18, 0x4a, 0x50, 0xff, 0x03, 0x00,
322 0x21, 0x45, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x40,
323 0x00, 0x40, 0x11, 0x94, 0x22, 0x50, 0x7e, 0x2b,
324 0x2d, 0xc2, 0x6d, 0x68, 0x68, 0x80, 0x0e, 0x00,
325 0x35, 0x00, 0x36, 0x9f, 0x18, 0xdb, 0xc4, 0x01,
326 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
327 0x01, 0x03, 0x73, 0x31, 0x36, 0x09, 0x73, 0x69,
328 0x74, 0x65, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x03,
329 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
330 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00, 0x00,
331 0x00, 0x00, 0x00 };
332 Packet *p = PacketGetFromAlloc();
333 if (unlikely(p == NULL))
334 return 0;
335 ThreadVars tv;
336 DecodeThreadVars dtv;
337
338 memset(&tv, 0, sizeof(ThreadVars));
339 memset(&dtv, 0, sizeof(DecodeThreadVars));
340
341 DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre));
342
343 if(ENGINE_ISSET_EVENT(p,GRE_WRONG_VERSION)) {
344 SCFree(p);
345 return 1;
346 }
347
348 SCFree(p);
349 return 0;
350 }
351
352
353 /**
354 * \test DecodeGRETest03 is a test for valid gre packet
355 */
356
DecodeGREtest03(void)357 static int DecodeGREtest03 (void)
358 {
359 uint8_t raw_gre[] = {
360 0x00, 0x6e, 0x62, 0xac, 0x40, 0x00, 0x40, 0x2f,
361 0xc2, 0xc7, 0x0a, 0x00, 0x00, 0x64, 0x0a, 0x00,
362 0x00, 0x8a, 0x30, 0x01, 0x88, 0x0b, 0x00, 0x4e,
363 0x00, 0x00, 0x00, 0x18, 0x4a, 0x50, 0xff, 0x03,
364 0x00, 0x21, 0x45, 0x00, 0x00, 0x4a, 0x00, 0x00,
365 0x40, 0x00, 0x40, 0x11, 0x94, 0x22, 0x50, 0x7e,
366 0x2b, 0x2d, 0xc2, 0x6d, 0x68, 0x68, 0x80, 0x0e,
367 0x00, 0x35, 0x00, 0x36, 0x9f, 0x18, 0xdb, 0xc4,
368 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
369 0x00, 0x01, 0x03, 0x73, 0x31, 0x36, 0x09, 0x73,
370 0x69, 0x74, 0x65, 0x6d, 0x65, 0x74, 0x65, 0x72,
371 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
372 0x01, 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00,
373 0x00, 0x00, 0x00, 0x00 };
374 Packet *p = PacketGetFromAlloc();
375 if (unlikely(p == NULL))
376 return 0;
377 ThreadVars tv;
378 DecodeThreadVars dtv;
379
380 memset(&tv, 0, sizeof(ThreadVars));
381 memset(&dtv, 0, sizeof(DecodeThreadVars));
382
383 DecodeGRE(&tv, &dtv, p, raw_gre, sizeof(raw_gre));
384
385 if(p->greh == NULL) {
386 SCFree(p);
387 return 0;
388 }
389
390
391 SCFree(p);
392 return 1;
393 }
394 #endif /* UNITTESTS */
395
396 /**
397 * \brief this function registers unit tests for GRE decoder
398 */
399
DecodeGRERegisterTests(void)400 void DecodeGRERegisterTests(void)
401 {
402 #ifdef UNITTESTS
403 UtRegisterTest("DecodeGREtest01", DecodeGREtest01);
404 UtRegisterTest("DecodeGREtest02", DecodeGREtest02);
405 UtRegisterTest("DecodeGREtest03", DecodeGREtest03);
406 #endif /* UNITTESTS */
407 }
408 /**
409 * @}
410 */
411