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