suricata
detect-l3proto.c
Go to the documentation of this file.
1 /* Copyright (C) 2012-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  * \file
20  *
21  * \author Eric Leblond <eric@regit.org>
22  *
23  *
24  * Implements the l3_proto keyword
25  */
26 
27 #include "suricata-common.h"
28 #include "debug.h"
29 #include "decode.h"
30 #include "detect.h"
31 
32 #include "detect-ipproto.h"
33 
34 #include "detect-parse.h"
35 #include "detect-engine.h"
36 #include "detect-engine-mpm.h"
37 
38 #include "detect-engine-siggroup.h"
39 #include "detect-engine-address.h"
40 
41 #include "detect-l3proto.h"
42 
43 #include "util-byte.h"
44 #include "util-unittest.h"
45 #include "util-unittest-helper.h"
46 
47 #include "util-debug.h"
48 
49 static int DetectL3ProtoSetup(DetectEngineCtx *, Signature *, const char *);
50 #ifdef UNITTESTS
51 static void DetectL3protoRegisterTests(void);
52 #endif
53 
55 {
56  sigmatch_table[DETECT_L3PROTO].name = "l3_proto";
58  sigmatch_table[DETECT_L3PROTO].Setup = DetectL3ProtoSetup;
60 #ifdef UNITTESTS
61  sigmatch_table[DETECT_L3PROTO].RegisterTests = DetectL3protoRegisterTests;
62 #endif
63 }
64 /**
65  * \internal
66  * \brief Setup l3_proto keyword.
67  *
68  * \param de_ctx Detection engine context
69  * \param s Signature
70  * \param optstr Options string
71  *
72  * \return Non-zero on error
73  */
74 static int DetectL3ProtoSetup(DetectEngineCtx *de_ctx, Signature *s, const char *optstr)
75 {
76  const char *str = optstr;
77 
78  /* reset possible any value */
79  if (s->proto.flags & DETECT_PROTO_ANY) {
81  }
82 
83  /* authorized value, ip, any, ip4, ipv4, ip6, ipv6 */
84  if (strcasecmp(str,"ipv4") == 0 ||
85  strcasecmp(str,"ip4") == 0 ) {
86  if (s->proto.flags & DETECT_PROTO_IPV6) {
87  SCLogError(SC_ERR_INVALID_SIGNATURE, "Conflicting l3 proto specified");
88  goto error;
89  }
91  SCLogDebug("IPv4 protocol detected");
92  } else if (strcasecmp(str,"ipv6") == 0 ||
93  strcasecmp(str,"ip6") == 0 ) {
94  if (s->proto.flags & DETECT_PROTO_IPV6) {
95  SCLogError(SC_ERR_INVALID_SIGNATURE, "Conflicting l3 proto specified");
96  goto error;
97  }
99  SCLogDebug("IPv6 protocol detected");
100  } else {
101  SCLogError(SC_ERR_INVALID_SIGNATURE, "Invalid l3 proto: \"%s\"", str);
102  goto error;
103  }
104 
105  return 0;
106 error:
107  return -1;
108 }
109 
110 #ifdef UNITTESTS
111 
112 /**
113  * \test DetectL3protoTestSig01 is a test for checking the working of ttl keyword
114  * by setting up the signature and later testing its working by matching
115  * the received packet against the sig.
116  */
117 
118 static int DetectL3protoTestSig1(void)
119 {
120 
121  Packet *p = PacketGetFromAlloc();
122  if (unlikely(p == NULL))
123  return 0;
124  Signature *s = NULL;
125  ThreadVars th_v;
126  DetectEngineThreadCtx *det_ctx;
127  int result = 0;
128  IPV4Hdr ip4h;
129 
130  memset(&th_v, 0, sizeof(th_v));
131 
132  p->src.family = AF_INET;
133  p->dst.family = AF_INET;
134  p->proto = IPPROTO_TCP;
135  p->ip4h = &ip4h;
136 
138  if (de_ctx == NULL) {
139  goto end;
140  }
141 
142  de_ctx->flags |= DE_QUIET;
143 
144  s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"l3proto ipv4\"; l3_proto:ipv4; sid:1;)");
145  if (s == NULL) {
146  goto end;
147  }
148 
149  s = s->next = SigInit(de_ctx,"alert ip any any -> any any (msg:\"l3proto ipv6\"; l3_proto:ipv6; sid:2;)");
150  if (s == NULL) {
151  goto end;
152  }
153 
154  s = s->next = SigInit(de_ctx,"alert ip any any -> any any (msg:\"l3proto ip4\"; l3_proto:ip4; sid:3;)");
155  if (s == NULL) {
156  goto end;
157  }
158 
159  s = s->next = SigInit(de_ctx,"alert ip any any -> any any (msg:\"l3proto ip6\"; l3_proto:ip6; sid:2;)");
160  if (s == NULL) {
161  goto end;
162  }
163 
165  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
166 
167  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
168  if (PacketAlertCheck(p, 1) == 0) {
169  printf("sid 1 did not alert, but should have: ");
170  goto cleanup;
171  } else if (PacketAlertCheck(p, 2)) {
172  printf("sid 2 alerted, but should not have: ");
173  goto cleanup;
174  } else if (PacketAlertCheck(p, 3) == 0) {
175  printf("sid 3 did not alert, but should have: ");
176  goto cleanup;
177  } else if (PacketAlertCheck(p, 4)) {
178  printf("sid 4 alerted, but should not have: ");
179  goto cleanup;
180  }
181 
182  result = 1;
183 
184 cleanup:
187 
188  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
190 
191 end:
192  SCFree(p);
193  return result;
194 }
195 
196 /**
197  * \test DetectL3protoTestSig02 is a test for checking the working of l3proto keyword
198  * by setting up the signature and later testing its working by matching
199  * the received IPv6 packet against the sig.
200  */
201 
202 static int DetectL3protoTestSig2(void)
203 {
204 
205  Packet *p = PacketGetFromAlloc();
206  if (unlikely(p == NULL))
207  return 0;
208  Signature *s = NULL;
209  ThreadVars th_v;
210  DetectEngineThreadCtx *det_ctx;
211  int result = 0;
212  IPV6Hdr ip6h;
213 
214  memset(&th_v, 0, sizeof(th_v));
215 
216  p->src.family = AF_INET6;
217  p->dst.family = AF_INET6;
218  p->proto = IPPROTO_TCP;
219  p->ip6h = &ip6h;
220 
222  if (de_ctx == NULL) {
223  goto end;
224  }
225 
226  de_ctx->flags |= DE_QUIET;
227 
228  s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"l3proto ipv4\"; l3_proto:ipv4; sid:1;)");
229  if (s == NULL) {
230  goto end;
231  }
232 
233  s = s->next = SigInit(de_ctx,"alert ip any any -> any any (msg:\"l3proto ipv6\"; l3_proto:ipv6; sid:2;)");
234  if (s == NULL) {
235  goto end;
236  }
237 
238  s = s->next = SigInit(de_ctx,"alert ip any any -> any any (msg:\"l3proto ip4\"; l3_proto:ip4; sid:3;)");
239  if (s == NULL) {
240  goto end;
241  }
242 
243  s = s->next = SigInit(de_ctx,"alert ip any any -> any any (msg:\"l3proto ip6\"; l3_proto:ip6; sid:4;)");
244  if (s == NULL) {
245  goto end;
246  }
247 
249  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
250 
251  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
252  if (PacketAlertCheck(p, 1)) {
253  printf("sid 1 alerted, but should not have: ");
254  goto cleanup;
255  } else if (PacketAlertCheck(p, 2) == 0) {
256  printf("sid 2 did not alert, but should have: ");
257  goto cleanup;
258  } else if (PacketAlertCheck(p, 3)) {
259  printf("sid 3 alerted, but should not have: ");
260  goto cleanup;
261  } else if (PacketAlertCheck(p, 4) == 0) {
262  printf("sid 4 did not alert, but should have: ");
263  goto cleanup;
264  }
265 
266  result = 1;
267 
268 cleanup:
271 
272  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
274 
275 end:
276  SCFree(p);
277  return result;
278 }
279 
280 /**
281  * \test DetectL3protoTestSig03 is a test for checking the working of l3proto keyword
282  * in conjonction with ip_proto keyword.
283  */
284 
285 static int DetectL3protoTestSig3(void)
286 {
287 
288  Packet *p = PacketGetFromAlloc();
289  if (unlikely(p == NULL))
290  return 0;
291  Signature *s = NULL;
292  ThreadVars th_v;
293  DetectEngineThreadCtx *det_ctx;
294  int result = 0;
295  IPV6Hdr ip6h;
296 
297  memset(&th_v, 0, sizeof(th_v));
298 
299  p->src.family = AF_INET6;
300  p->dst.family = AF_INET6;
301  p->proto = IPPROTO_TCP;
302  p->ip6h = &ip6h;
303 
305  if (de_ctx == NULL) {
306  goto end;
307  }
308 
309  de_ctx->flags |= DE_QUIET;
310 
311  s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"l3proto ipv4 and ip_proto udp\"; l3_proto:ipv4; ip_proto:17; sid:1;)");
312  if (s == NULL) {
313  goto end;
314  }
315 
316  s = s->next = SigInit(de_ctx,"alert ip any any -> any any (msg:\"l3proto ipv6 and ip_proto udp\"; l3_proto:ipv6; ip_proto:17; sid:2;)");
317  if (s == NULL) {
318  goto end;
319  }
320 
321  s = s->next = SigInit(de_ctx,"alert ip any any -> any any (msg:\"l3proto ip4 and ip_proto tcp\"; l3_proto:ipv4; ip_proto:6; sid:3;)");
322  if (s == NULL) {
323  goto end;
324  }
325 
326  s = s->next = SigInit(de_ctx,"alert ip any any -> any any (msg:\"l3proto ipv6 and ip_proto tcp\"; l3_proto:ipv6; ip_proto:6; sid:4;)");
327  if (s == NULL) {
328  goto end;
329  }
330 
332  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
333 
334  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
335  if (PacketAlertCheck(p, 1)) {
336  printf("sid 1 alerted, but should not have: ");
337  goto cleanup;
338  } else if (PacketAlertCheck(p, 2)) {
339  printf("sid 2 alerted, but should not have: ");
340  goto cleanup;
341  } else if (PacketAlertCheck(p, 3)) {
342  printf("sid 3 alerted, but should not have: ");
343  goto cleanup;
344  } else if (PacketAlertCheck(p, 4) == 0) {
345  printf("sid 4 did not alert, but should have: ");
346  goto cleanup;
347  }
348 
349  result = 1;
350 
351 cleanup:
354 
355  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
357 
358 end:
359  SCFree(p);
360  return result;
361 }
362 
363 /**
364  * \brief this function registers unit tests for DetectL3proto
365  */
366 static void DetectL3protoRegisterTests(void)
367 {
368  UtRegisterTest("DetectL3protoTestSig1", DetectL3protoTestSig1);
369  UtRegisterTest("DetectL3protoTestSig2", DetectL3protoTestSig2);
370  UtRegisterTest("DetectL3protoTestSig3", DetectL3protoTestSig3);
371 }
372 #endif /* UNITTESTS */
util-byte.h
Packet_::proto
uint8_t proto
Definition: decode.h:436
detect-engine.h
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1201
DETECT_PROTO_IPV6
#define DETECT_PROTO_IPV6
Definition: detect-engine-proto.h:34
detect-engine-siggroup.h
SigTableElmt_::name
const char * name
Definition: detect.h:1211
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
PacketAlertCheck
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
Definition: detect-engine-alert.c:138
SigInit
Signature * SigInit(DetectEngineCtx *, const char *)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:2056
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:767
DETECT_PROTO_ANY
#define DETECT_PROTO_ANY
Definition: detect-engine-proto.h:27
SC_ERR_INVALID_SIGNATURE
@ SC_ERR_INVALID_SIGNATURE
Definition: util-error.h:69
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2093
DE_QUIET
#define DE_QUIET
Definition: detect.h:294
SigCleanSignatures
void SigCleanSignatures(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:39
detect-l3proto.h
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1196
util-unittest.h
DETECT_L3PROTO
@ DETECT_L3PROTO
Definition: detect-engine-register.h:209
util-unittest-helper.h
Signature_::next
struct Signature_ * next
Definition: detect.h:600
decode.h
util-debug.h
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
DetectL3ProtoRegister
void DetectL3ProtoRegister(void)
Registration function for ip_proto keyword.
Definition: detect-l3proto.c:54
DetectEngineThreadCtx_
Definition: detect.h:1010
detect-engine-mpm.h
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
SigMatchSignatures
void SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1688
SigGroupCleanup
int SigGroupCleanup(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:1953
IPV6Hdr_
Definition: decode-ipv6.h:32
Packet_
Definition: decode.h:414
Packet_::ip4h
IPV4Hdr * ip4h
Definition: decode.h:509
detect-ipproto.h
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1179
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:1888
IPV4Hdr_
Definition: decode-ipv4.h:71
DetectProto_::flags
uint8_t flags
Definition: detect-engine-proto.h:38
DETECT_PROTO_IPV4
#define DETECT_PROTO_IPV4
Definition: detect-engine-proto.h:33
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
Definition: detect-engine.c:2797
Signature_::proto
DetectProto proto
Definition: detect.h:545
suricata-common.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
Definition: detect-engine.c:3005
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:73
SCLogError
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:257
DetectEngineCtx_::sig_list
Signature * sig_list
Definition: detect.h:773
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:144
str
#define str(s)
Definition: suricata-common.h:273
SCFree
#define SCFree(p)
Definition: util-mem.h:61
detect-parse.h
Signature_
Signature container.
Definition: detect.h:528
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2048
Address_::family
char family
Definition: decode.h:117
Packet_::dst
Address dst
Definition: decode.h:419
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:768
Packet_::ip6h
IPV6Hdr * ip6h
Definition: decode.h:511
detect-engine-address.h
Packet_::src
Address src
Definition: decode.h:418
debug.h
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1203