/src/suricata7/src/detect-l3proto.c
Line | Count | Source |
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 "decode.h" |
29 | | #include "detect.h" |
30 | | |
31 | | #include "detect-ipproto.h" |
32 | | |
33 | | #include "detect-parse.h" |
34 | | #include "detect-engine.h" |
35 | | #include "detect-engine-mpm.h" |
36 | | #include "detect-engine-build.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 | | |
54 | | void DetectL3ProtoRegister(void) |
55 | 73 | { |
56 | 73 | sigmatch_table[DETECT_L3PROTO].name = "l3_proto"; |
57 | 73 | sigmatch_table[DETECT_L3PROTO].Match = NULL; |
58 | 73 | sigmatch_table[DETECT_L3PROTO].Setup = DetectL3ProtoSetup; |
59 | 73 | sigmatch_table[DETECT_L3PROTO].Free = NULL; |
60 | | #ifdef UNITTESTS |
61 | | sigmatch_table[DETECT_L3PROTO].RegisterTests = DetectL3protoRegisterTests; |
62 | | #endif |
63 | 73 | } |
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 | 531 | { |
76 | 531 | const char *str = optstr; |
77 | | |
78 | | /* reset possible any value */ |
79 | 531 | if (s->proto.flags & DETECT_PROTO_ANY) { |
80 | 224 | s->proto.flags &= ~DETECT_PROTO_ANY; |
81 | 224 | } |
82 | | |
83 | | /* authorized value, ip, any, ip4, ipv4, ip6, ipv6 */ |
84 | 531 | if (strcasecmp(str,"ipv4") == 0 || |
85 | 401 | strcasecmp(str,"ip4") == 0 ) { |
86 | 173 | if (s->proto.flags & DETECT_PROTO_IPV6) { |
87 | 2 | SCLogError("Conflicting l3 proto specified"); |
88 | 2 | goto error; |
89 | 2 | } |
90 | 171 | s->proto.flags |= DETECT_PROTO_IPV4; |
91 | 171 | SCLogDebug("IPv4 protocol detected"); |
92 | 358 | } else if (strcasecmp(str,"ipv6") == 0 || |
93 | 342 | strcasecmp(str,"ip6") == 0 ) { |
94 | 28 | if (s->proto.flags & DETECT_PROTO_IPV6) { |
95 | 2 | SCLogError("Conflicting l3 proto specified"); |
96 | 2 | goto error; |
97 | 2 | } |
98 | 26 | s->proto.flags |= DETECT_PROTO_IPV6; |
99 | 26 | SCLogDebug("IPv6 protocol detected"); |
100 | 330 | } else { |
101 | 330 | SCLogError("Invalid l3 proto: \"%s\"", str); |
102 | 330 | goto error; |
103 | 330 | } |
104 | | |
105 | 197 | return 0; |
106 | 334 | error: |
107 | 334 | return -1; |
108 | 531 | } |
109 | | |
110 | | #ifdef UNITTESTS |
111 | | #include "detect-engine-alert.h" |
112 | | |
113 | | /** |
114 | | * \test DetectL3protoTestSig01 is a test for checking the working of ttl keyword |
115 | | * by setting up the signature and later testing its working by matching |
116 | | * the received packet against the sig. |
117 | | */ |
118 | | |
119 | | static int DetectL3protoTestSig1(void) |
120 | | { |
121 | | |
122 | | Packet *p = PacketGetFromAlloc(); |
123 | | FAIL_IF_NULL(p); |
124 | | Signature *s = NULL; |
125 | | ThreadVars th_v; |
126 | | DetectEngineThreadCtx *det_ctx; |
127 | | IPV4Hdr ip4h; |
128 | | |
129 | | memset(&th_v, 0, sizeof(th_v)); |
130 | | |
131 | | p->src.family = AF_INET; |
132 | | p->dst.family = AF_INET; |
133 | | p->proto = IPPROTO_TCP; |
134 | | p->ip4h = &ip4h; |
135 | | |
136 | | DetectEngineCtx *de_ctx = DetectEngineCtxInit(); |
137 | | FAIL_IF_NULL(de_ctx); |
138 | | |
139 | | de_ctx->flags |= DE_QUIET; |
140 | | |
141 | | s = DetectEngineAppendSig( |
142 | | de_ctx, "alert ip any any -> any any (msg:\"l3proto ipv4\"; l3_proto:ipv4; sid:1;)"); |
143 | | FAIL_IF_NULL(s); |
144 | | |
145 | | s = DetectEngineAppendSig( |
146 | | de_ctx, "alert ip any any -> any any (msg:\"l3proto ipv6\"; l3_proto:ipv6; sid:2;)"); |
147 | | FAIL_IF_NULL(s); |
148 | | |
149 | | s = DetectEngineAppendSig( |
150 | | de_ctx, "alert ip any any -> any any (msg:\"l3proto ip4\"; l3_proto:ip4; sid:3;)"); |
151 | | FAIL_IF_NULL(s); |
152 | | |
153 | | s = DetectEngineAppendSig( |
154 | | de_ctx, "alert ip any any -> any any (msg:\"l3proto ip6\"; l3_proto:ip6; sid:4;)"); |
155 | | FAIL_IF_NULL(s); |
156 | | |
157 | | SigGroupBuild(de_ctx); |
158 | | DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); |
159 | | |
160 | | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); |
161 | | FAIL_IF_NOT(PacketAlertCheck(p, 1)); |
162 | | FAIL_IF(PacketAlertCheck(p, 2)); |
163 | | FAIL_IF_NOT(PacketAlertCheck(p, 3)); |
164 | | FAIL_IF(PacketAlertCheck(p, 4)); |
165 | | |
166 | | DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); |
167 | | DetectEngineCtxFree(de_ctx); |
168 | | |
169 | | SCFree(p); |
170 | | |
171 | | PASS; |
172 | | } |
173 | | |
174 | | /** |
175 | | * \test DetectL3protoTestSig02 is a test for checking the working of l3proto keyword |
176 | | * by setting up the signature and later testing its working by matching |
177 | | * the received IPv6 packet against the sig. |
178 | | */ |
179 | | |
180 | | static int DetectL3protoTestSig2(void) |
181 | | { |
182 | | |
183 | | Packet *p = PacketGetFromAlloc(); |
184 | | FAIL_IF_NULL(p); |
185 | | Signature *s = NULL; |
186 | | ThreadVars th_v; |
187 | | DetectEngineThreadCtx *det_ctx; |
188 | | IPV6Hdr ip6h; |
189 | | |
190 | | memset(&th_v, 0, sizeof(th_v)); |
191 | | |
192 | | p->src.family = AF_INET6; |
193 | | p->dst.family = AF_INET6; |
194 | | p->proto = IPPROTO_TCP; |
195 | | p->ip6h = &ip6h; |
196 | | |
197 | | DetectEngineCtx *de_ctx = DetectEngineCtxInit(); |
198 | | FAIL_IF_NULL(de_ctx); |
199 | | |
200 | | de_ctx->flags |= DE_QUIET; |
201 | | |
202 | | s = DetectEngineAppendSig( |
203 | | de_ctx, "alert ip any any -> any any (msg:\"l3proto ipv4\"; l3_proto:ipv4; sid:1;)"); |
204 | | FAIL_IF_NULL(s); |
205 | | |
206 | | s = DetectEngineAppendSig( |
207 | | de_ctx, "alert ip any any -> any any (msg:\"l3proto ipv6\"; l3_proto:ipv6; sid:2;)"); |
208 | | FAIL_IF_NULL(s); |
209 | | |
210 | | s = DetectEngineAppendSig( |
211 | | de_ctx, "alert ip any any -> any any (msg:\"l3proto ip4\"; l3_proto:ip4; sid:3;)"); |
212 | | FAIL_IF_NULL(s); |
213 | | |
214 | | s = DetectEngineAppendSig( |
215 | | de_ctx, "alert ip any any -> any any (msg:\"l3proto ip6\"; l3_proto:ip6; sid:4;)"); |
216 | | FAIL_IF_NULL(s); |
217 | | |
218 | | SigGroupBuild(de_ctx); |
219 | | DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); |
220 | | |
221 | | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); |
222 | | FAIL_IF(PacketAlertCheck(p, 1)); |
223 | | FAIL_IF_NOT(PacketAlertCheck(p, 2)); |
224 | | FAIL_IF(PacketAlertCheck(p, 3)); |
225 | | FAIL_IF_NOT(PacketAlertCheck(p, 4)); |
226 | | |
227 | | DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); |
228 | | DetectEngineCtxFree(de_ctx); |
229 | | |
230 | | SCFree(p); |
231 | | |
232 | | PASS; |
233 | | } |
234 | | |
235 | | /** |
236 | | * \test DetectL3protoTestSig03 is a test for checking the working of l3proto keyword |
237 | | * in conjunction with ip_proto keyword. |
238 | | */ |
239 | | |
240 | | static int DetectL3protoTestSig3(void) |
241 | | { |
242 | | |
243 | | Packet *p = PacketGetFromAlloc(); |
244 | | FAIL_IF_NULL(p); |
245 | | Signature *s = NULL; |
246 | | ThreadVars th_v; |
247 | | DetectEngineThreadCtx *det_ctx; |
248 | | IPV6Hdr ip6h; |
249 | | |
250 | | memset(&th_v, 0, sizeof(th_v)); |
251 | | |
252 | | p->src.family = AF_INET6; |
253 | | p->dst.family = AF_INET6; |
254 | | p->proto = IPPROTO_TCP; |
255 | | p->ip6h = &ip6h; |
256 | | |
257 | | DetectEngineCtx *de_ctx = DetectEngineCtxInit(); |
258 | | FAIL_IF_NULL(de_ctx); |
259 | | |
260 | | de_ctx->flags |= DE_QUIET; |
261 | | |
262 | | s = DetectEngineAppendSig(de_ctx, "alert ip any any -> any any (msg:\"l3proto ipv4 and " |
263 | | "ip_proto udp\"; l3_proto:ipv4; ip_proto:17; sid:1;)"); |
264 | | FAIL_IF_NULL(s); |
265 | | |
266 | | s = DetectEngineAppendSig(de_ctx, "alert ip any any -> any any (msg:\"l3proto ipv6 and " |
267 | | "ip_proto udp\"; l3_proto:ipv6; ip_proto:17; sid:2;)"); |
268 | | FAIL_IF_NULL(s); |
269 | | |
270 | | s = DetectEngineAppendSig(de_ctx, "alert ip any any -> any any (msg:\"l3proto ip4 and ip_proto " |
271 | | "tcp\"; l3_proto:ipv4; ip_proto:6; sid:3;)"); |
272 | | FAIL_IF_NULL(s); |
273 | | |
274 | | s = DetectEngineAppendSig(de_ctx, "alert ip any any -> any any (msg:\"l3proto ipv6 and " |
275 | | "ip_proto tcp\"; l3_proto:ipv6; ip_proto:6; sid:4;)"); |
276 | | FAIL_IF_NULL(s); |
277 | | |
278 | | SigGroupBuild(de_ctx); |
279 | | DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); |
280 | | |
281 | | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); |
282 | | FAIL_IF(PacketAlertCheck(p, 1)); |
283 | | FAIL_IF(PacketAlertCheck(p, 2)); |
284 | | FAIL_IF(PacketAlertCheck(p, 3)); |
285 | | FAIL_IF_NOT(PacketAlertCheck(p, 4)); |
286 | | |
287 | | DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); |
288 | | DetectEngineCtxFree(de_ctx); |
289 | | |
290 | | SCFree(p); |
291 | | |
292 | | PASS; |
293 | | } |
294 | | |
295 | | /** |
296 | | * \brief this function registers unit tests for DetectL3proto |
297 | | */ |
298 | | static void DetectL3protoRegisterTests(void) |
299 | | { |
300 | | UtRegisterTest("DetectL3protoTestSig1", DetectL3protoTestSig1); |
301 | | UtRegisterTest("DetectL3protoTestSig2", DetectL3protoTestSig2); |
302 | | UtRegisterTest("DetectL3protoTestSig3", DetectL3protoTestSig3); |
303 | | } |
304 | | #endif /* UNITTESTS */ |