/src/suricata7/src/detect-rpc.c
Line | Count | Source (jump to first uncovered line) |
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 | | * \file |
20 | | * |
21 | | * \author Pablo Rincon <pablo.rincon.crespo@gmail.com> |
22 | | * |
23 | | * Implements RPC keyword |
24 | | */ |
25 | | |
26 | | #include "suricata-common.h" |
27 | | #include "decode.h" |
28 | | |
29 | | #include "detect.h" |
30 | | #include "detect-rpc.h" |
31 | | #include "detect-parse.h" |
32 | | #include "detect-engine.h" |
33 | | #include "detect-engine-mpm.h" |
34 | | #include "detect-engine-siggroup.h" |
35 | | #include "detect-engine-address.h" |
36 | | #include "detect-engine-build.h" |
37 | | |
38 | | #include "util-unittest.h" |
39 | | #include "util-unittest-helper.h" |
40 | | #include "util-debug.h" |
41 | | #include "util-byte.h" |
42 | | |
43 | | /** |
44 | | * \brief Regex for parsing our rpc options |
45 | | */ |
46 | 73 | #define PARSE_REGEX "^\\s*([0-9]{0,10})\\s*(?:,\\s*([0-9]{0,10}|[*])\\s*(?:,\\s*([0-9]{0,10}|[*]))?)?\\s*$" |
47 | | |
48 | | static DetectParseRegex parse_regex; |
49 | | |
50 | | static int DetectRpcMatch (DetectEngineThreadCtx *, Packet *, |
51 | | const Signature *, const SigMatchCtx *); |
52 | | static int DetectRpcSetup (DetectEngineCtx *, Signature *, const char *); |
53 | | #ifdef UNITTESTS |
54 | | static void DetectRpcRegisterTests(void); |
55 | | #endif |
56 | | void DetectRpcFree(DetectEngineCtx *, void *); |
57 | | |
58 | | /** |
59 | | * \brief Registration function for rpc keyword |
60 | | */ |
61 | | void DetectRpcRegister (void) |
62 | 73 | { |
63 | 73 | sigmatch_table[DETECT_RPC].name = "rpc"; |
64 | 73 | sigmatch_table[DETECT_RPC].desc = "match RPC procedure numbers and RPC version"; |
65 | 73 | sigmatch_table[DETECT_RPC].url = "/rules/payload-keywords.html#rpc"; |
66 | 73 | sigmatch_table[DETECT_RPC].Match = DetectRpcMatch; |
67 | 73 | sigmatch_table[DETECT_RPC].Setup = DetectRpcSetup; |
68 | 73 | sigmatch_table[DETECT_RPC].Free = DetectRpcFree; |
69 | | #ifdef UNITTESTS |
70 | | sigmatch_table[DETECT_RPC].RegisterTests = DetectRpcRegisterTests; |
71 | | #endif |
72 | 73 | DetectSetupParseRegexes(PARSE_REGEX, &parse_regex); |
73 | 73 | } |
74 | | |
75 | | /* |
76 | | * returns 0: no match |
77 | | * 1: match |
78 | | * -1: error |
79 | | */ |
80 | | |
81 | | /** |
82 | | * \brief This function is used to match rpc request set on a packet with those passed via rpc |
83 | | * |
84 | | * \param t pointer to thread vars |
85 | | * \param det_ctx pointer to the pattern matcher thread |
86 | | * \param p pointer to the current packet |
87 | | * \param m pointer to the sigmatch that we will cast into DetectRpcData |
88 | | * |
89 | | * \retval 0 no match |
90 | | * \retval 1 match |
91 | | */ |
92 | | static int DetectRpcMatch (DetectEngineThreadCtx *det_ctx, Packet *p, |
93 | | const Signature *s, const SigMatchCtx *ctx) |
94 | 23.8k | { |
95 | | /* PrintRawDataFp(stdout, p->payload, p->payload_len); */ |
96 | 23.8k | const DetectRpcData *rd = (const DetectRpcData *)ctx; |
97 | 23.8k | char *rpcmsg = (char *)p->payload; |
98 | | |
99 | 23.8k | if (PKT_IS_TCP(p)) { |
100 | | /* if Rpc msg too small */ |
101 | 19.2k | if (p->payload_len < 28) { |
102 | 12.6k | SCLogDebug("TCP packet to small for the rpc msg (%u)", p->payload_len); |
103 | 12.6k | return 0; |
104 | 12.6k | } |
105 | 6.65k | rpcmsg += 4; |
106 | 6.65k | } else if (PKT_IS_UDP(p)) { |
107 | | /* if Rpc msg too small */ |
108 | 1.25k | if (p->payload_len < 24) { |
109 | 2 | SCLogDebug("UDP packet to small for the rpc msg (%u)", p->payload_len); |
110 | 2 | return 0; |
111 | 2 | } |
112 | 3.31k | } else { |
113 | 3.31k | SCLogDebug("No valid proto for the rpc message"); |
114 | 3.31k | return 0; |
115 | 3.31k | } |
116 | | |
117 | | /* Point through the rpc msg structure. Use SCNtohl() to compare values */ |
118 | 7.90k | RpcMsg *msg = (RpcMsg *)rpcmsg; |
119 | | |
120 | | /* If its not a call, no match */ |
121 | 7.90k | if (SCNtohl(msg->type) != 0) { |
122 | 6.32k | SCLogDebug("RPC message type is not a call"); |
123 | 6.32k | return 0; |
124 | 6.32k | } |
125 | | |
126 | 1.58k | if (SCNtohl(msg->prog) != rd->program) |
127 | 1.56k | return 0; |
128 | | |
129 | 25 | if ((rd->flags & DETECT_RPC_CHECK_VERSION) && SCNtohl(msg->vers) != rd->program_version) |
130 | 0 | return 0; |
131 | | |
132 | 25 | if ((rd->flags & DETECT_RPC_CHECK_PROCEDURE) && SCNtohl(msg->proc) != rd->procedure) |
133 | 0 | return 0; |
134 | | |
135 | 25 | SCLogDebug("prog:%u pver:%u proc:%u matched", SCNtohl(msg->prog), SCNtohl(msg->vers), SCNtohl(msg->proc)); |
136 | 25 | return 1; |
137 | 25 | } |
138 | | |
139 | | /** |
140 | | * \brief This function is used to parse rpc options passed via rpc keyword |
141 | | * |
142 | | * \param de_ctx Pointer to the detection engine context |
143 | | * \param rpcstr Pointer to the user provided rpc options |
144 | | * |
145 | | * \retval rd pointer to DetectRpcData on success |
146 | | * \retval NULL on failure |
147 | | */ |
148 | | static DetectRpcData *DetectRpcParse (DetectEngineCtx *de_ctx, const char *rpcstr) |
149 | 6.32k | { |
150 | 6.32k | DetectRpcData *rd = NULL; |
151 | 6.32k | char *args[3] = {NULL,NULL,NULL}; |
152 | 6.32k | int res = 0; |
153 | 6.32k | size_t pcre2_len; |
154 | | |
155 | 6.32k | pcre2_match_data *match = NULL; |
156 | 6.32k | int ret = DetectParsePcreExec(&parse_regex, &match, rpcstr, 0, 0); |
157 | 6.32k | if (ret < 1 || ret > 4) { |
158 | 242 | SCLogError("parse error, ret %" PRId32 ", string %s", ret, rpcstr); |
159 | 242 | goto error; |
160 | 242 | } |
161 | | |
162 | 6.07k | if (ret > 1) { |
163 | 6.07k | const char *str_ptr; |
164 | 6.07k | res = pcre2_substring_get_bynumber(match, 1, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len); |
165 | 6.07k | if (res < 0) { |
166 | 0 | SCLogError("pcre2_substring_get_bynumber failed"); |
167 | 0 | goto error; |
168 | 0 | } |
169 | 6.07k | args[0] = (char *)str_ptr; |
170 | | |
171 | 6.07k | if (ret > 2) { |
172 | 4.84k | res = pcre2_substring_get_bynumber(match, 2, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len); |
173 | 4.84k | if (res < 0) { |
174 | 0 | SCLogError("pcre2_substring_get_bynumber failed"); |
175 | 0 | goto error; |
176 | 0 | } |
177 | 4.84k | args[1] = (char *)str_ptr; |
178 | 4.84k | } |
179 | 6.07k | if (ret > 3) { |
180 | 3.68k | res = pcre2_substring_get_bynumber(match, 3, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len); |
181 | 3.68k | if (res < 0) { |
182 | 0 | SCLogError("pcre2_substring_get_bynumber failed"); |
183 | 0 | goto error; |
184 | 0 | } |
185 | 3.68k | args[2] = (char *)str_ptr; |
186 | 3.68k | } |
187 | 6.07k | } |
188 | | |
189 | 6.07k | rd = SCMalloc(sizeof(DetectRpcData)); |
190 | 6.07k | if (unlikely(rd == NULL)) |
191 | 0 | goto error; |
192 | 6.07k | rd->flags = 0; |
193 | 6.07k | rd->program = 0; |
194 | 6.07k | rd->program_version = 0; |
195 | 6.07k | rd->procedure = 0; |
196 | | |
197 | 6.07k | int i; |
198 | 20.6k | for (i = 0; i < (ret - 1); i++) { |
199 | 14.6k | if (args[i]) { |
200 | 14.6k | switch (i) { |
201 | 6.07k | case 0: |
202 | 6.07k | if (StringParseUint32(&rd->program, 10, strlen(args[i]), args[i]) <= 0) { |
203 | 6 | SCLogError("Invalid size specified for the rpc program:\"%s\"", args[i]); |
204 | 6 | goto error; |
205 | 6 | } |
206 | 6.07k | rd->flags |= DETECT_RPC_CHECK_PROGRAM; |
207 | 6.07k | break; |
208 | 4.83k | case 1: |
209 | 4.83k | if (args[i][0] != '*') { |
210 | 2.86k | if (StringParseUint32(&rd->program_version, 10, strlen(args[i]), args[i]) <= 0) { |
211 | 5 | SCLogError( |
212 | 5 | "Invalid size specified for the rpc version:\"%s\"", args[i]); |
213 | 5 | goto error; |
214 | 5 | } |
215 | 2.85k | rd->flags |= DETECT_RPC_CHECK_VERSION; |
216 | 2.85k | } |
217 | 4.83k | break; |
218 | 4.83k | case 2: |
219 | 3.68k | if (args[i][0] != '*') { |
220 | 613 | if (StringParseUint32(&rd->procedure, 10, strlen(args[i]), args[i]) <= 0) { |
221 | 39 | SCLogError( |
222 | 39 | "Invalid size specified for the rpc procedure:\"%s\"", args[i]); |
223 | 39 | goto error; |
224 | 39 | } |
225 | 574 | rd->flags |= DETECT_RPC_CHECK_PROCEDURE; |
226 | 574 | } |
227 | 3.64k | break; |
228 | 14.6k | } |
229 | 14.6k | } else { |
230 | 0 | SCLogError("invalid rpc option %s", rpcstr); |
231 | 0 | goto error; |
232 | 0 | } |
233 | 14.6k | } |
234 | 20.4k | for (i = 0; i < (ret -1); i++){ |
235 | 14.4k | if (args[i] != NULL) |
236 | 14.4k | pcre2_substring_free((PCRE2_UCHAR8 *)args[i]); |
237 | 14.4k | } |
238 | 6.02k | pcre2_match_data_free(match); |
239 | 6.02k | return rd; |
240 | | |
241 | 292 | error: |
242 | 292 | if (match) { |
243 | 292 | pcre2_match_data_free(match); |
244 | 292 | } |
245 | 428 | for (i = 0; i < (ret -1) && i < 3; i++){ |
246 | 136 | if (args[i] != NULL) |
247 | 136 | pcre2_substring_free((PCRE2_UCHAR8 *)args[i]); |
248 | 136 | } |
249 | 292 | if (rd != NULL) |
250 | 50 | DetectRpcFree(de_ctx, rd); |
251 | 292 | return NULL; |
252 | | |
253 | 6.07k | } |
254 | | |
255 | | /** |
256 | | * \brief this function is used to add the parsed rpcdata into the current signature |
257 | | * |
258 | | * \param de_ctx pointer to the Detection Engine Context |
259 | | * \param s pointer to the Current Signature |
260 | | * \param m pointer to the Current SigMatch |
261 | | * \param rpcstr pointer to the user provided rpc options |
262 | | * |
263 | | * \retval 0 on Success |
264 | | * \retval -1 on Failure |
265 | | */ |
266 | | int DetectRpcSetup (DetectEngineCtx *de_ctx, Signature *s, const char *rpcstr) |
267 | 4.27k | { |
268 | 4.27k | DetectRpcData *rd = NULL; |
269 | 4.27k | SigMatch *sm = NULL; |
270 | | |
271 | 4.27k | rd = DetectRpcParse(de_ctx, rpcstr); |
272 | 4.27k | if (rd == NULL) goto error; |
273 | | |
274 | 4.20k | sm = SigMatchAlloc(); |
275 | 4.20k | if (sm == NULL) |
276 | 0 | goto error; |
277 | | |
278 | 4.20k | sm->type = DETECT_RPC; |
279 | 4.20k | sm->ctx = (SigMatchCtx *)rd; |
280 | | |
281 | 4.20k | SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH); |
282 | 4.20k | s->flags |= SIG_FLAG_REQUIRE_PACKET; |
283 | | |
284 | 4.20k | return 0; |
285 | | |
286 | 65 | error: |
287 | 65 | if (rd != NULL) DetectRpcFree(de_ctx, rd); |
288 | 65 | if (sm != NULL) SCFree(sm); |
289 | 65 | return -1; |
290 | | |
291 | 4.20k | } |
292 | | |
293 | | /** |
294 | | * \brief this function will free memory associated with DetectRpcData |
295 | | * |
296 | | * \param rd pointer to DetectRpcData |
297 | | */ |
298 | | void DetectRpcFree(DetectEngineCtx *de_ctx, void *ptr) |
299 | 6.07k | { |
300 | 6.07k | SCEnter(); |
301 | | |
302 | 6.07k | if (ptr == NULL) { |
303 | 0 | SCReturn; |
304 | 0 | } |
305 | | |
306 | 6.07k | DetectRpcData *rd = (DetectRpcData *)ptr; |
307 | 6.07k | SCFree(rd); |
308 | | |
309 | 6.07k | SCReturn; |
310 | 6.07k | } |
311 | | |
312 | | #ifdef UNITTESTS |
313 | | #include "detect-engine-alert.h" |
314 | | /** |
315 | | * \test DetectRpcTestParse01 is a test to make sure that we return "something" |
316 | | * when given valid rpc opt |
317 | | */ |
318 | | static int DetectRpcTestParse01 (void) |
319 | | { |
320 | | DetectRpcData *rd = DetectRpcParse(NULL, "123,444,555"); |
321 | | FAIL_IF_NULL(rd); |
322 | | |
323 | | DetectRpcFree(NULL, rd); |
324 | | PASS; |
325 | | } |
326 | | |
327 | | /** |
328 | | * \test DetectRpcTestParse02 is a test for setting the established rpc opt |
329 | | */ |
330 | | static int DetectRpcTestParse02 (void) |
331 | | { |
332 | | DetectRpcData *rd = NULL; |
333 | | rd = DetectRpcParse(NULL, "111,222,333"); |
334 | | FAIL_IF_NULL(rd); |
335 | | FAIL_IF_NOT(rd->flags & DETECT_RPC_CHECK_PROGRAM); |
336 | | FAIL_IF_NOT(rd->flags & DETECT_RPC_CHECK_VERSION); |
337 | | FAIL_IF_NOT(rd->flags & DETECT_RPC_CHECK_PROCEDURE); |
338 | | FAIL_IF_NOT(rd->program == 111); |
339 | | FAIL_IF_NOT(rd->program_version == 222); |
340 | | FAIL_IF_NOT(rd->procedure == 333); |
341 | | |
342 | | DetectRpcFree(NULL, rd); |
343 | | |
344 | | PASS; |
345 | | } |
346 | | |
347 | | /** |
348 | | * \test DetectRpcTestParse03 is a test for checking the wildcards |
349 | | * and not specified fields |
350 | | */ |
351 | | static int DetectRpcTestParse03 (void) |
352 | | { |
353 | | DetectRpcData *rd = NULL; |
354 | | |
355 | | rd = DetectRpcParse(NULL, "111,*,333"); |
356 | | FAIL_IF_NULL(rd); |
357 | | |
358 | | FAIL_IF_NOT(rd->flags & DETECT_RPC_CHECK_PROGRAM); |
359 | | FAIL_IF(rd->flags & DETECT_RPC_CHECK_VERSION); |
360 | | FAIL_IF_NOT(rd->flags & DETECT_RPC_CHECK_PROCEDURE); |
361 | | FAIL_IF_NOT(rd->program == 111); |
362 | | FAIL_IF_NOT(rd->program_version == 0); |
363 | | FAIL_IF_NOT(rd->procedure == 333); |
364 | | |
365 | | DetectRpcFree(NULL, rd); |
366 | | |
367 | | rd = DetectRpcParse(NULL, "111,222,*"); |
368 | | FAIL_IF_NULL(rd); |
369 | | |
370 | | FAIL_IF_NOT(rd->flags & DETECT_RPC_CHECK_PROGRAM); |
371 | | FAIL_IF_NOT(rd->flags & DETECT_RPC_CHECK_VERSION); |
372 | | FAIL_IF(rd->flags & DETECT_RPC_CHECK_PROCEDURE); |
373 | | FAIL_IF_NOT(rd->program == 111); |
374 | | FAIL_IF_NOT(rd->program_version == 222); |
375 | | FAIL_IF_NOT(rd->procedure == 0); |
376 | | |
377 | | DetectRpcFree(NULL, rd); |
378 | | |
379 | | rd = DetectRpcParse(NULL, "111,*,*"); |
380 | | FAIL_IF_NULL(rd); |
381 | | |
382 | | FAIL_IF_NOT(rd->flags & DETECT_RPC_CHECK_PROGRAM); |
383 | | FAIL_IF(rd->flags & DETECT_RPC_CHECK_VERSION); |
384 | | FAIL_IF(rd->flags & DETECT_RPC_CHECK_PROCEDURE); |
385 | | FAIL_IF_NOT(rd->program == 111); |
386 | | FAIL_IF_NOT(rd->program_version == 0); |
387 | | FAIL_IF_NOT(rd->procedure == 0); |
388 | | |
389 | | DetectRpcFree(NULL, rd); |
390 | | |
391 | | rd = DetectRpcParse(NULL, "111,222"); |
392 | | FAIL_IF_NULL(rd); |
393 | | |
394 | | FAIL_IF_NOT(rd->flags & DETECT_RPC_CHECK_PROGRAM); |
395 | | FAIL_IF_NOT(rd->flags & DETECT_RPC_CHECK_VERSION); |
396 | | FAIL_IF(rd->flags & DETECT_RPC_CHECK_PROCEDURE); |
397 | | FAIL_IF_NOT(rd->program == 111); |
398 | | FAIL_IF_NOT(rd->program_version == 222); |
399 | | FAIL_IF_NOT(rd->procedure == 0); |
400 | | |
401 | | DetectRpcFree(NULL, rd); |
402 | | |
403 | | rd = DetectRpcParse(NULL, "111"); |
404 | | FAIL_IF_NULL(rd); |
405 | | |
406 | | FAIL_IF_NOT(rd->flags & DETECT_RPC_CHECK_PROGRAM); |
407 | | FAIL_IF(rd->flags & DETECT_RPC_CHECK_VERSION); |
408 | | FAIL_IF(rd->flags & DETECT_RPC_CHECK_PROCEDURE); |
409 | | FAIL_IF_NOT(rd->program == 111); |
410 | | FAIL_IF_NOT(rd->program_version == 0); |
411 | | FAIL_IF_NOT(rd->procedure == 0); |
412 | | |
413 | | DetectRpcFree(NULL, rd); |
414 | | PASS; |
415 | | } |
416 | | |
417 | | /** |
418 | | * \test DetectRpcTestParse04 is a test for check the discarding of empty options |
419 | | */ |
420 | | static int DetectRpcTestParse04 (void) |
421 | | { |
422 | | DetectRpcData *rd = NULL; |
423 | | rd = DetectRpcParse(NULL, ""); |
424 | | |
425 | | FAIL_IF_NOT_NULL(rd); |
426 | | DetectRpcFree(NULL, rd); |
427 | | |
428 | | PASS; |
429 | | } |
430 | | |
431 | | /** |
432 | | * \test DetectRpcTestParse05 is a test for check invalid values |
433 | | */ |
434 | | static int DetectRpcTestParse05 (void) |
435 | | { |
436 | | DetectRpcData *rd = NULL; |
437 | | rd = DetectRpcParse(NULL, "111,aaa,*"); |
438 | | |
439 | | FAIL_IF_NOT_NULL(rd); |
440 | | DetectRpcFree(NULL, rd); |
441 | | |
442 | | PASS; |
443 | | } |
444 | | |
445 | | /** |
446 | | * \test DetectRpcTestParse05 is a test to check the match function |
447 | | */ |
448 | | static int DetectRpcTestSig01(void) |
449 | | { |
450 | | /* RPC Call */ |
451 | | uint8_t buf[] = { |
452 | | /* XID */ |
453 | | 0x64,0xb2,0xb3,0x75, |
454 | | /* Message type: Call (0) */ |
455 | | 0x00,0x00,0x00,0x00, |
456 | | /* RPC Version (2) */ |
457 | | 0x00,0x00,0x00,0x02, |
458 | | /* Program portmap (100000) */ |
459 | | 0x00,0x01,0x86,0xa0, |
460 | | /* Program version (2) */ |
461 | | 0x00,0x00,0x00,0x02, |
462 | | /* Program procedure (3) = GETPORT */ |
463 | | 0x00,0x00,0x00,0x03, |
464 | | /* AUTH_NULL */ |
465 | | 0x00,0x00,0x00,0x00, |
466 | | /* Length 0 */ |
467 | | 0x00,0x00,0x00,0x00, |
468 | | /* VERIFIER NULL */ |
469 | | 0x00,0x00,0x00,0x00, |
470 | | /* Length 0 */ |
471 | | 0x00,0x00,0x00,0x00, |
472 | | /* Program portmap */ |
473 | | 0x00,0x01,0x86,0xa2, |
474 | | /* Version 2 */ |
475 | | 0x00,0x00,0x00,0x02, |
476 | | /* Proto UDP */ |
477 | | 0x00,0x00,0x00,0x11, |
478 | | /* Port 0 */ |
479 | | 0x00,0x00,0x00,0x00 }; |
480 | | uint16_t buflen = sizeof(buf); |
481 | | Packet *p = NULL; |
482 | | Signature *s = NULL; |
483 | | ThreadVars th_v; |
484 | | DetectEngineThreadCtx *det_ctx; |
485 | | |
486 | | memset(&th_v, 0, sizeof(th_v)); |
487 | | |
488 | | p = UTHBuildPacket(buf, buflen, IPPROTO_UDP); |
489 | | |
490 | | DetectEngineCtx *de_ctx = DetectEngineCtxInit(); |
491 | | FAIL_IF_NULL(de_ctx); |
492 | | |
493 | | de_ctx->flags |= DE_QUIET; |
494 | | |
495 | | s = DetectEngineAppendSig(de_ctx, |
496 | | "alert udp any any -> any any (msg:\"RPC Get Port Call\"; rpc:100000, 2, 3; sid:1;)"); |
497 | | FAIL_IF_NULL(s); |
498 | | |
499 | | s = DetectEngineAppendSig(de_ctx, |
500 | | "alert udp any any -> any any (msg:\"RPC Get Port Call\"; rpc:100000, 2, *; sid:2;)"); |
501 | | FAIL_IF_NULL(s); |
502 | | |
503 | | s = DetectEngineAppendSig(de_ctx, |
504 | | "alert udp any any -> any any (msg:\"RPC Get Port Call\"; rpc:100000, *, 3; sid:3;)"); |
505 | | FAIL_IF_NULL(s); |
506 | | |
507 | | s = DetectEngineAppendSig(de_ctx, |
508 | | "alert udp any any -> any any (msg:\"RPC Get Port Call\"; rpc:100000, *, *; sid:4;)"); |
509 | | FAIL_IF_NULL(s); |
510 | | |
511 | | s = DetectEngineAppendSig(de_ctx, "alert udp any any -> any any (msg:\"RPC Get XXX Call.. no " |
512 | | "match\"; rpc:123456, *, 3; sid:5;)"); |
513 | | FAIL_IF_NULL(s); |
514 | | |
515 | | SigGroupBuild(de_ctx); |
516 | | DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); |
517 | | |
518 | | SigMatchSignatures(&th_v, de_ctx, det_ctx, p); |
519 | | FAIL_IF(PacketAlertCheck(p, 1) == 0); |
520 | | FAIL_IF(PacketAlertCheck(p, 2) == 0); |
521 | | FAIL_IF(PacketAlertCheck(p, 3) == 0); |
522 | | FAIL_IF(PacketAlertCheck(p, 4) == 0); |
523 | | FAIL_IF(PacketAlertCheck(p, 5) > 0); |
524 | | |
525 | | DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); |
526 | | DetectEngineCtxFree(de_ctx); |
527 | | |
528 | | UTHFreePackets(&p, 1); |
529 | | |
530 | | PASS; |
531 | | } |
532 | | |
533 | | /** |
534 | | * \brief this function registers unit tests for DetectRpc |
535 | | */ |
536 | | static void DetectRpcRegisterTests(void) |
537 | | { |
538 | | UtRegisterTest("DetectRpcTestParse01", DetectRpcTestParse01); |
539 | | UtRegisterTest("DetectRpcTestParse02", DetectRpcTestParse02); |
540 | | UtRegisterTest("DetectRpcTestParse03", DetectRpcTestParse03); |
541 | | UtRegisterTest("DetectRpcTestParse04", DetectRpcTestParse04); |
542 | | UtRegisterTest("DetectRpcTestParse05", DetectRpcTestParse05); |
543 | | UtRegisterTest("DetectRpcTestSig01", DetectRpcTestSig01); |
544 | | } |
545 | | #endif /* UNITTESTS */ |