1 /* Copyright (C) 2007-2013 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 Pinto <breno.silva@gmail.com>
29  *
30  * Decode PPP
31  */
32 
33 #include "suricata-common.h"
34 #include "decode.h"
35 #include "decode-ppp.h"
36 #include "decode-events.h"
37 
38 #include "flow.h"
39 
40 #include "util-unittest.h"
41 #include "util-debug.h"
42 
DecodePPP(ThreadVars * tv,DecodeThreadVars * dtv,Packet * p,const uint8_t * pkt,uint32_t len)43 int DecodePPP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
44         const uint8_t *pkt, uint32_t len)
45 {
46     StatsIncr(tv, dtv->counter_ppp);
47 
48     if (unlikely(len < PPP_HEADER_LEN)) {
49         ENGINE_SET_INVALID_EVENT(p, PPP_PKT_TOO_SMALL);
50         return TM_ECODE_FAILED;
51     }
52     if (!PacketIncreaseCheckLayers(p)) {
53         return TM_ECODE_FAILED;
54     }
55 
56     p->ppph = (PPPHdr *)pkt;
57     if (unlikely(p->ppph == NULL))
58         return TM_ECODE_FAILED;
59 
60     SCLogDebug("p %p pkt %p PPP protocol %04x Len: %" PRIu32 "",
61         p, pkt, SCNtohs(p->ppph->protocol), len);
62 
63     switch (SCNtohs(p->ppph->protocol))
64     {
65         case PPP_VJ_UCOMP:
66             if (unlikely(len < (PPP_HEADER_LEN + IPV4_HEADER_LEN))) {
67                 ENGINE_SET_INVALID_EVENT(p,PPPVJU_PKT_TOO_SMALL);
68                 p->ppph = NULL;
69                 return TM_ECODE_FAILED;
70             }
71 
72             if (unlikely(len > PPP_HEADER_LEN + USHRT_MAX)) {
73                 return TM_ECODE_FAILED;
74             }
75 
76             if (likely(IPV4_GET_RAW_VER((IPV4Hdr *)(pkt + PPP_HEADER_LEN)) == 4)) {
77                 return DecodeIPV4(tv, dtv, p, pkt + PPP_HEADER_LEN, len - PPP_HEADER_LEN);
78             } else
79                 return TM_ECODE_FAILED;
80             break;
81 
82         case PPP_IP:
83             if (unlikely(len < (PPP_HEADER_LEN + IPV4_HEADER_LEN))) {
84                 ENGINE_SET_INVALID_EVENT(p,PPPIPV4_PKT_TOO_SMALL);
85                 p->ppph = NULL;
86                 return TM_ECODE_FAILED;
87             }
88             if (unlikely(len > PPP_HEADER_LEN + USHRT_MAX)) {
89                 return TM_ECODE_FAILED;
90             }
91 
92             return DecodeIPV4(tv, dtv, p, pkt + PPP_HEADER_LEN, len - PPP_HEADER_LEN);
93 
94             /* PPP IPv6 was not tested */
95         case PPP_IPV6:
96             if (unlikely(len < (PPP_HEADER_LEN + IPV6_HEADER_LEN))) {
97                 ENGINE_SET_INVALID_EVENT(p,PPPIPV6_PKT_TOO_SMALL);
98                 p->ppph = NULL;
99                 return TM_ECODE_FAILED;
100             }
101             if (unlikely(len > PPP_HEADER_LEN + USHRT_MAX)) {
102                 return TM_ECODE_FAILED;
103             }
104 
105             return DecodeIPV6(tv, dtv, p, pkt + PPP_HEADER_LEN, len - PPP_HEADER_LEN);
106 
107         case PPP_VJ_COMP:
108         case PPP_IPX:
109         case PPP_OSI:
110         case PPP_NS:
111         case PPP_DECNET:
112         case PPP_APPLE:
113         case PPP_BRPDU:
114         case PPP_STII:
115         case PPP_VINES:
116         case PPP_HELLO:
117         case PPP_LUXCOM:
118         case PPP_SNS:
119         case PPP_MPLS_UCAST:
120         case PPP_MPLS_MCAST:
121         case PPP_IPCP:
122         case PPP_OSICP:
123         case PPP_NSCP:
124         case PPP_DECNETCP:
125         case PPP_APPLECP:
126         case PPP_IPXCP:
127         case PPP_STIICP:
128         case PPP_VINESCP:
129         case PPP_IPV6CP:
130         case PPP_MPLSCP:
131         case PPP_LCP:
132         case PPP_PAP:
133         case PPP_LQM:
134         case PPP_CHAP:
135             ENGINE_SET_EVENT(p,PPP_UNSUP_PROTO);
136             return TM_ECODE_OK;
137 
138         default:
139             SCLogDebug("unknown PPP protocol: %" PRIx32 "",SCNtohs(p->ppph->protocol));
140             ENGINE_SET_INVALID_EVENT(p, PPP_WRONG_TYPE);
141             return TM_ECODE_OK;
142     }
143 
144 }
145 
146 /* TESTS BELOW */
147 #ifdef UNITTESTS
148 
149 /*  DecodePPPtest01
150  *  Decode malformed ip layer PPP packet
151  *  Expected test value: 1
152  */
DecodePPPtest01(void)153 static int DecodePPPtest01 (void)
154 {
155     uint8_t raw_ppp[] = { 0xff, 0x03, 0x00, 0x21, 0x45, 0xc0, 0x00 };
156     Packet *p = PacketGetFromAlloc();
157     if (unlikely(p == NULL))
158         return 0;
159     ThreadVars tv;
160     DecodeThreadVars dtv;
161 
162     memset(&tv, 0, sizeof(ThreadVars));
163     memset(&dtv, 0, sizeof(DecodeThreadVars));
164 
165     DecodePPP(&tv, &dtv, p, raw_ppp, sizeof(raw_ppp));
166 
167     /* Function my returns here with expected value */
168 
169     if(ENGINE_ISSET_EVENT(p,PPPIPV4_PKT_TOO_SMALL))  {
170         SCFree(p);
171         return 1;
172     }
173 
174     SCFree(p);
175     return 0;
176 }
177 
178 /*  DecodePPPtest02
179  *  Decode malformed ppp layer packet
180  *  Expected test value: 1
181  */
DecodePPPtest02(void)182 static int DecodePPPtest02 (void)
183 {
184     uint8_t raw_ppp[] = { 0xff, 0x03, 0x00, 0xff, 0x45, 0xc0, 0x00, 0x2c, 0x4d,
185                            0xed, 0x00, 0x00, 0xff, 0x06, 0xd5, 0x17, 0xbf, 0x01,
186                            0x0d, 0x01, 0xbf, 0x01, 0x0d, 0x03, 0xea, 0x37, 0x00,
187                            0x17, 0x6d, 0x0b, 0xba, 0xc3, 0x00, 0x00, 0x00, 0x00,
188                            0x60, 0x02, 0x10, 0x20, 0xdd, 0xe1, 0x00, 0x00 };
189     Packet *p = PacketGetFromAlloc();
190     if (unlikely(p == NULL))
191         return 0;
192     ThreadVars tv;
193     DecodeThreadVars dtv;
194 
195     memset(&tv, 0, sizeof(ThreadVars));
196     memset(&dtv, 0, sizeof(DecodeThreadVars));
197 
198     DecodePPP(&tv, &dtv, p, raw_ppp, sizeof(raw_ppp));
199 
200     /* Function must returns here */
201 
202     if(ENGINE_ISSET_EVENT(p,PPP_WRONG_TYPE))  {
203         SCFree(p);
204         return 1;
205     }
206 
207     SCFree(p);
208     return 0;
209 }
210 
211 /** DecodePPPtest03
212  *  \brief Decode good PPP packet, additionally the IPv4 packet inside is
213  *         4 bytes short.
214  *  \retval 0 Test failed
215  *  \retval 1 Test succeeded
216  */
DecodePPPtest03(void)217 static int DecodePPPtest03 (void)
218 {
219     uint8_t raw_ppp[] = { 0xff, 0x03, 0x00, 0x21, 0x45, 0xc0, 0x00, 0x2c, 0x4d,
220                            0xed, 0x00, 0x00, 0xff, 0x06, 0xd5, 0x17, 0xbf, 0x01,
221                            0x0d, 0x01, 0xbf, 0x01, 0x0d, 0x03, 0xea, 0x37, 0x00,
222                            0x17, 0x6d, 0x0b, 0xba, 0xc3, 0x00, 0x00, 0x00, 0x00,
223                            0x60, 0x02, 0x10, 0x20, 0xdd, 0xe1, 0x00, 0x00 };
224     Packet *p = PacketGetFromAlloc();
225     if (unlikely(p == NULL))
226         return 0;
227     ThreadVars tv;
228     DecodeThreadVars dtv;
229 
230     memset(&tv, 0, sizeof(ThreadVars));
231     memset(&dtv, 0, sizeof(DecodeThreadVars));
232 
233     FlowInitConfig(FLOW_QUIET);
234 
235     DecodePPP(&tv, &dtv, p, raw_ppp, sizeof(raw_ppp));
236 
237     FlowShutdown();
238 
239     if(p->ppph == NULL) {
240         SCFree(p);
241         return 0;
242     }
243 
244     if(ENGINE_ISSET_EVENT(p,PPP_PKT_TOO_SMALL))  {
245         SCFree(p);
246         return 0;
247     }
248 
249     if(ENGINE_ISSET_EVENT(p,PPPIPV4_PKT_TOO_SMALL))  {
250         SCFree(p);
251         return 0;
252     }
253 
254     if(ENGINE_ISSET_EVENT(p,PPP_WRONG_TYPE))  {
255         SCFree(p);
256         return 0;
257     }
258 
259     if (!(ENGINE_ISSET_EVENT(p,IPV4_TRUNC_PKT))) {
260         SCFree(p);
261         return 0;
262     }
263     /* Function must return here */
264 
265     SCFree(p);
266     return 1;
267 }
268 
269 
270 /*  DecodePPPtest04
271  *  Check if ppp header is null
272  *  Expected test value: 1
273  */
274 
DecodePPPtest04(void)275 static int DecodePPPtest04 (void)
276 {
277     uint8_t raw_ppp[] = { 0xff, 0x03, 0x00, 0x21, 0x45, 0xc0, 0x00, 0x2c, 0x4d,
278                            0xed, 0x00, 0x00, 0xff, 0x06, 0xd5, 0x17, 0xbf, 0x01,
279                            0x0d, 0x01, 0xbf, 0x01, 0x0d, 0x03, 0xea, 0x37, 0x00,
280                            0x17, 0x6d, 0x0b, 0xba, 0xc3, 0x00, 0x00, 0x00, 0x00,
281                            0x60, 0x02, 0x10, 0x20, 0xdd, 0xe1, 0x00, 0x00 };
282     Packet *p = PacketGetFromAlloc();
283     if (unlikely(p == NULL))
284         return 0;
285     ThreadVars tv;
286     DecodeThreadVars dtv;
287 
288     memset(&tv, 0, sizeof(ThreadVars));
289     memset(&dtv, 0, sizeof(DecodeThreadVars));
290 
291     FlowInitConfig(FLOW_QUIET);
292 
293     DecodePPP(&tv, &dtv, p, raw_ppp, sizeof(raw_ppp));
294 
295     FlowShutdown();
296 
297     if(p->ppph == NULL) {
298         SCFree(p);
299         return 0;
300     }
301 
302     if (!(ENGINE_ISSET_EVENT(p,IPV4_TRUNC_PKT))) {
303         SCFree(p);
304         return 0;
305     }
306 
307     /* Function must returns here */
308 
309     SCFree(p);
310     return 1;
311 }
312 #endif /* UNITTESTS */
313 
DecodePPPRegisterTests(void)314 void DecodePPPRegisterTests(void)
315 {
316 #ifdef UNITTESTS
317     UtRegisterTest("DecodePPPtest01", DecodePPPtest01);
318     UtRegisterTest("DecodePPPtest02", DecodePPPtest02);
319     UtRegisterTest("DecodePPPtest03", DecodePPPtest03);
320     UtRegisterTest("DecodePPPtest04", DecodePPPtest04);
321 #endif /* UNITTESTS */
322 }
323 
324 /**
325  * @}
326  */
327