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