suricata
detect-lua.c
Go to the documentation of this file.
1/* Copyright (C) 2007-2024 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 Victor Julien <victor@inliniac.net>
22 *
23 */
24
25#include "suricata-common.h"
26#include "conf.h"
27
28#include "decode.h"
29
30#include "detect.h"
31#include "detect-parse.h"
32
33#include "detect-engine.h"
35#include "detect-engine-mpm.h"
36#include "detect-engine-build.h"
37
38#include "detect-byte.h"
39
40#include "flow.h"
41#include "flow-var.h"
42#include "flow-util.h"
43
44#include "util-byte.h"
45
46#include "util-unittest.h"
48
49#include "app-layer.h"
50#include "app-layer-parser.h"
51#include "app-layer-htp.h"
52#include "app-layer-ssl.h"
53
54#include "stream-tcp.h"
55
56#include "detect-lua.h"
58
59#include "util-var-name.h"
60
61#include "util-lua.h"
62#include "util-lua-builtins.h"
63#include "util-lua-common.h"
64#include "util-lua-sandbox.h"
65
66static int DetectLuaMatch (DetectEngineThreadCtx *,
67 Packet *, const Signature *, const SigMatchCtx *);
68static int DetectLuaAppTxMatch (DetectEngineThreadCtx *det_ctx,
69 Flow *f, uint8_t flags,
70 void *state, void *txv, const Signature *s,
71 const SigMatchCtx *ctx);
72static int DetectLuaSetup (DetectEngineCtx *, Signature *, const char *);
73#ifdef UNITTESTS
74static void DetectLuaRegisterTests(void);
75#endif
76static void DetectLuaFree(DetectEngineCtx *, void *);
77static int g_lua_ja3_list_id = 0;
78static int g_lua_ja3s_list_id = 0;
79
80/**
81 * \brief Registration function for keyword: lua
82 */
84{
86 sigmatch_table[DETECT_LUA].desc = "match via a lua script";
87 sigmatch_table[DETECT_LUA].url = "/rules/rule-lua-scripting.html";
88 sigmatch_table[DETECT_LUA].Match = DetectLuaMatch;
89 sigmatch_table[DETECT_LUA].AppLayerTxMatch = DetectLuaAppTxMatch;
90 sigmatch_table[DETECT_LUA].Setup = DetectLuaSetup;
91 sigmatch_table[DETECT_LUA].Free = DetectLuaFree;
92#ifdef UNITTESTS
93 sigmatch_table[DETECT_LUA].RegisterTests = DetectLuaRegisterTests;
94#endif
95
96 g_lua_ja3_list_id = DetectBufferTypeRegister("ja3.lua");
101
102 g_lua_ja3s_list_id = DetectBufferTypeRegister("ja3s.lua");
107
108 SCLogDebug("registering lua rule option");
109}
110
111/* Flags for DetectLuaThreadData. */
112#define FLAG_DATATYPE_PACKET BIT_U32(0)
113#define FLAG_DATATYPE_PAYLOAD BIT_U32(1)
114#define FLAG_DATATYPE_STREAM BIT_U32(2)
115#define FLAG_LIST_JA3 BIT_U32(3)
116#define FLAG_LIST_JA3S BIT_U32(4)
117#define FLAG_DATATYPE_BUFFER BIT_U32(22)
118#define FLAG_ERROR_LOGGED BIT_U32(23)
119#define FLAG_BLOCKED_FUNCTION_LOGGED BIT_U32(24)
120#define FLAG_INSTRUCTION_LIMIT_LOGGED BIT_U32(25)
121#define FLAG_MEMORY_LIMIT_LOGGED BIT_U32(26)
122
123#define DEFAULT_LUA_ALLOC_LIMIT 500000
124#define DEFAULT_LUA_INSTRUCTION_LIMIT 500000
125
126/** \brief dump stack from lua state to screen */
127void LuaDumpStack(lua_State *state, const char *prefix)
128{
129 int size = lua_gettop(state);
130 printf("%s: size %d\n", prefix, size);
131
132 for (int i = 1; i <= size; i++) {
133 int type = lua_type(state, i);
134 printf("- %s: Stack size=%d, level=%d, type=%d, ", prefix, size, i, type);
135
136 switch (type) {
137 case LUA_TFUNCTION:
138 printf("function %s", lua_tostring(state, i));
139 break;
140 case LUA_TBOOLEAN:
141 printf("bool %s", lua_toboolean(state, i) ? "true" : "false");
142 break;
143 case LUA_TNUMBER:
144 printf("number %g", lua_tonumber(state, i));
145 break;
146 case LUA_TSTRING:
147 printf("string `%s'", lua_tostring(state, i));
148 break;
149 case LUA_TTABLE:
150 printf("table `%s'", lua_tostring(state, i));
151 break;
152 default:
153 printf("other %s", lua_typename(state, type));
154 break;
155
156 }
157 printf("\n");
158 }
159}
160
161static void LuaStateSetDetectLuaData(lua_State *state, DetectLuaData *data)
162{
163 lua_pushlightuserdata(state, (void *)&luaext_key_ld);
164 lua_pushlightuserdata(state, (void *)data);
165 lua_settable(state, LUA_REGISTRYINDEX);
166}
167
168/**
169 * \brief Common function to run the Lua match function and process
170 * the return value.
171 */
172static int DetectLuaRunMatch(
173 DetectEngineThreadCtx *det_ctx, const DetectLuaData *lua, DetectLuaThreadData *tlua)
174{
175 /* Reset instruction count. */
177
178 if (lua_pcall(tlua->luastate, 1, 1, 0) != 0) {
179 const char *reason = lua_tostring(tlua->luastate, -1);
180 SCLuaSbState *context = SCLuaSbGetContext(tlua->luastate);
181 uint32_t flag = 0;
182 if (context->blocked_function_error) {
183 StatsIncr(det_ctx->tv, det_ctx->lua_blocked_function_errors);
185 } else if (context->instruction_count_error) {
186 StatsIncr(det_ctx->tv, det_ctx->lua_instruction_limit_errors);
188 } else if (context->memory_limit_error) {
189 StatsIncr(det_ctx->tv, det_ctx->lua_memory_limit_errors);
190 reason = "memory limit exceeded";
192 } else {
193 flag = FLAG_ERROR_LOGGED;
194 }
195
196 /* Log once per thread per error type, the message from Lua
197 * will include the filename. */
198 if (!(tlua->flags & flag)) {
199 SCLogWarning("Lua script failed to run successfully: %s", reason);
200 tlua->flags |= flag;
201 }
202
203 StatsIncr(det_ctx->tv, det_ctx->lua_rule_errors);
204 while (lua_gettop(tlua->luastate) > 0) {
205 lua_pop(tlua->luastate, 1);
206 }
207 SCReturnInt(0);
208 }
209
210 int match = 0;
211
212 /* process returns from script */
213 if (lua_gettop(tlua->luastate) > 0) {
214 /* script returns a number (return 1 or return 0) */
215 if (lua_type(tlua->luastate, 1) == LUA_TNUMBER) {
216 lua_Integer script_ret = lua_tointeger(tlua->luastate, 1);
217 SCLogDebug("script_ret %lld", script_ret);
218 lua_pop(tlua->luastate, 1);
219 if (script_ret == 1)
220 match = 1;
221 } else {
222 SCLogDebug("Unsupported datatype returned from Lua script");
223 }
224 }
225
226 if (lua->negated) {
227 if (match == 1)
228 match = 0;
229 else
230 match = 1;
231 }
232
233 while (lua_gettop(tlua->luastate) > 0) {
234 lua_pop(tlua->luastate, 1);
235 }
236
237 SCReturnInt(match);
238}
239
241 const SigMatchData *smd, const uint8_t *buffer, uint32_t buffer_len, uint32_t offset,
242 Flow *f)
243{
244 SCEnter();
245
246 if (buffer == NULL || buffer_len == 0)
247 SCReturnInt(0);
248
249 DetectLuaData *lua = (DetectLuaData *)smd->ctx;
250 if (lua == NULL)
251 SCReturnInt(0);
252
253 DetectLuaThreadData *tlua =
255 if (tlua == NULL)
256 SCReturnInt(0);
257
258 LuaExtensionsMatchSetup(tlua->luastate, lua, det_ctx, f, /* no packet in the ctx */ NULL, s, 0);
259
260 /* prepare data to pass to script */
261 lua_getglobal(tlua->luastate, "match");
262 lua_newtable(tlua->luastate); /* stack at -1 */
263
264 lua_pushliteral(tlua->luastate, "offset"); /* stack at -2 */
265 lua_pushnumber(tlua->luastate, (int)(offset + 1));
266 lua_settable(tlua->luastate, -3);
267
268 lua_pushstring(tlua->luastate, lua->buffername); /* stack at -2 */
269 LuaPushStringBuffer(tlua->luastate, (const uint8_t *)buffer, (size_t)buffer_len);
270 lua_settable(tlua->luastate, -3);
271
272 SCReturnInt(DetectLuaRunMatch(det_ctx, lua, tlua));
273}
274
275/**
276 * \brief match the specified lua script
277 *
278 * \param t thread local vars
279 * \param det_ctx pattern matcher thread local data
280 * \param p packet
281 * \param s signature being inspected
282 * \param m sigmatch that we will cast into DetectLuaData
283 *
284 * \retval 0 no match
285 * \retval 1 match
286 */
287static int DetectLuaMatch (DetectEngineThreadCtx *det_ctx,
288 Packet *p, const Signature *s, const SigMatchCtx *ctx)
289{
290 SCEnter();
292 if (lua == NULL)
293 SCReturnInt(0);
294
296 if (tlua == NULL)
297 SCReturnInt(0);
298
299 /* setup extension data for use in lua c functions */
300 uint8_t flags = 0;
302 flags = STREAM_TOSERVER;
303 else if (p->flowflags & FLOW_PKT_TOCLIENT)
304 flags = STREAM_TOCLIENT;
305
306 LuaStateSetThreadVars(tlua->luastate, det_ctx->tv);
307
308 LuaExtensionsMatchSetup(tlua->luastate, lua, det_ctx, p->flow, p, s, flags);
309
310 if ((tlua->flags & FLAG_DATATYPE_PAYLOAD) && p->payload_len == 0)
311 SCReturnInt(0);
312 if ((tlua->flags & FLAG_DATATYPE_PACKET) && GET_PKT_LEN(p) == 0)
313 SCReturnInt(0);
314
315 lua_getglobal(tlua->luastate, "match");
316 lua_newtable(tlua->luastate); /* stack at -1 */
317
318 SCReturnInt(DetectLuaRunMatch(det_ctx, lua, tlua));
319}
320
321static int DetectLuaAppMatchCommon (DetectEngineThreadCtx *det_ctx,
322 Flow *f, uint8_t flags, void *state,
323 const Signature *s, const SigMatchCtx *ctx)
324{
325 SCEnter();
327 if (lua == NULL)
328 SCReturnInt(0);
329
331 if (tlua == NULL)
332 SCReturnInt(0);
333
334 /* setup extension data for use in lua c functions */
335 LuaExtensionsMatchSetup(tlua->luastate, lua, det_ctx, f, NULL, s, flags);
336
337 lua_getglobal(tlua->luastate, "match");
338 lua_newtable(tlua->luastate); /* stack at -1 */
339
340 SCReturnInt(DetectLuaRunMatch(det_ctx, lua, tlua));
341}
342
343/**
344 * \brief match the specified lua script in a list with a tx
345 *
346 * \param t thread local vars
347 * \param det_ctx pattern matcher thread local data
348 * \param s signature being inspected
349 * \param m sigmatch that we will cast into DetectLuaData
350 *
351 * \retval 0 no match
352 * \retval 1 match
353 */
354static int DetectLuaAppTxMatch (DetectEngineThreadCtx *det_ctx,
355 Flow *f, uint8_t flags,
356 void *state, void *txv, const Signature *s,
357 const SigMatchCtx *ctx)
358{
359 return DetectLuaAppMatchCommon(det_ctx, f, flags, state, s, ctx);
360}
361
362#ifdef UNITTESTS
363/* if this ptr is set the lua setup functions will use this buffer as the
364 * lua script instead of calling luaL_loadfile on the filename supplied. */
365static const char *ut_script = NULL;
366#endif
367
368static void *DetectLuaThreadInit(void *data)
369{
370 int status;
371 DetectLuaData *lua = (DetectLuaData *)data;
372 BUG_ON(lua == NULL);
373
375 if (unlikely(t == NULL)) {
376 SCLogError("couldn't alloc ctx memory");
377 return NULL;
378 }
379
380 t->flags = lua->flags;
381
383 if (t->luastate == NULL) {
384 SCLogError("luastate pool depleted");
385 goto error;
386 }
387
389 luaL_openlibs(t->luastate);
391 } else {
393 }
394
395 LuaStateSetDetectLuaData(t->luastate, lua);
396
397 /* hackish, needed to allow unittests to pass buffers as scripts instead of files */
398#ifdef UNITTESTS
399 if (ut_script != NULL) {
400 status = luaL_loadbuffer(t->luastate, ut_script, strlen(ut_script), "unittest");
401 if (status) {
402 SCLogError("couldn't load file: %s", lua_tostring(t->luastate, -1));
403 goto error;
404 }
405 } else {
406#endif
407 status = luaL_loadfile(t->luastate, lua->filename);
408 if (status) {
409 SCLogError("couldn't load file: %s", lua_tostring(t->luastate, -1));
410 goto error;
411 }
412#ifdef UNITTESTS
413 }
414#endif
415
416 /* prime the script (or something) */
417 if (lua_pcall(t->luastate, 0, 0, 0) != 0) {
418 SCLogError("couldn't prime file: %s", lua_tostring(t->luastate, -1));
419 goto error;
420 }
421
422 /* thread_init call */
423 lua_getglobal(t->luastate, "thread_init");
424 if (lua_isfunction(t->luastate, -1)) {
425 if (lua_pcall(t->luastate, 0, 0, 0) != 0) {
426 SCLogError("couldn't run script 'thread_init' function: %s",
427 lua_tostring(t->luastate, -1));
428 goto error;
429 }
430 } else {
431 lua_pop(t->luastate, 1);
432 }
433
434 return (void *)t;
435
436error:
437 if (t->luastate != NULL)
439 SCFree(t);
440 return NULL;
441}
442
443static void DetectLuaThreadFree(void *ctx)
444{
445 if (ctx != NULL) {
447 if (t->luastate != NULL)
449 SCFree(t);
450 }
451}
452
453/**
454 * \brief Parse the lua keyword
455 *
456 * \param de_ctx Pointer to the detection engine context
457 * \param str Pointer to the user provided option
458 *
459 * \retval lua pointer to DetectLuaData on success
460 * \retval NULL on failure
461 */
462static DetectLuaData *DetectLuaParse (DetectEngineCtx *de_ctx, const char *str)
463{
464 DetectLuaData *lua = NULL;
465
466 /* We have a correct lua option */
467 lua = SCCalloc(1, sizeof(DetectLuaData));
468 if (unlikely(lua == NULL))
469 goto error;
470
471 if (strlen(str) && str[0] == '!') {
472 lua->negated = 1;
473 str++;
474 }
475
476 /* get full filename */
478 if (lua->filename == NULL) {
479 goto error;
480 }
481
482 return lua;
483
484error:
485 if (lua != NULL)
486 DetectLuaFree(de_ctx, lua);
487 return NULL;
488}
489
490static int DetectLuaSetupPrime(DetectEngineCtx *de_ctx, DetectLuaData *ld, const Signature *s)
491{
492 int status;
493
495 if (luastate == NULL)
496 return -1;
498 luaL_openlibs(luastate);
499 SCLuaRequirefBuiltIns(luastate);
500 } else {
501 SCLuaSbLoadLibs(luastate);
502 }
503 LuaStateSetDetectLuaData(luastate, ld);
504
505 /* hackish, needed to allow unittests to pass buffers as scripts instead of files */
506#ifdef UNITTESTS
507 if (ut_script != NULL) {
508 status = luaL_loadbuffer(luastate, ut_script, strlen(ut_script), "unittest");
509 if (status) {
510 SCLogError("couldn't load file: %s", lua_tostring(luastate, -1));
511 goto error;
512 }
513 } else {
514#endif
515 status = luaL_loadfile(luastate, ld->filename);
516 if (status) {
517 SCLogError("couldn't load file: %s", lua_tostring(luastate, -1));
518 goto error;
519 }
520#ifdef UNITTESTS
521 }
522#endif
523
524 /* prime the script (or something) */
525 if (lua_pcall(luastate, 0, 0, 0) != 0) {
526 SCLogError("couldn't prime file: %s", lua_tostring(luastate, -1));
527 goto error;
528 }
529
530 lua_getglobal(luastate, "init");
531 if (lua_type(luastate, -1) != LUA_TFUNCTION) {
532 SCLogError("no init function in script");
533 goto error;
534 }
535
536 /* Pass the signature as the first argument, setting up bytevars depends on
537 * access to the signature. */
538 lua_pushlightuserdata(luastate, (void *)s);
539
540 if (lua_pcall(luastate, 1, 1, 0) != 0) {
541 SCLogError("couldn't run script 'init' function: %s", lua_tostring(luastate, -1));
542 goto error;
543 }
544
545 /* process returns from script */
546 if (lua_gettop(luastate) == 0) {
547 SCLogError("init function in script should return table, nothing returned");
548 goto error;
549 }
550 if (lua_type(luastate, 1) != LUA_TTABLE) {
551 SCLogError("init function in script should return table, returned is not table");
552 goto error;
553 }
554
555 lua_pushnil(luastate);
556 const char *k;
557 while (lua_next(luastate, -2)) {
558 k = lua_tostring(luastate, -2);
559 if (k == NULL)
560 continue;
561
562 /* handle flowvar and bytes separately as they have a table as value */
563 if (strcmp(k, "flowvar") == 0) {
564 if (lua_istable(luastate, -1)) {
565 lua_pushnil(luastate);
566 while (lua_next(luastate, -2) != 0) {
567 /* value at -1, key is at -2 which we ignore */
568 const char *value = lua_tostring(luastate, -1);
569 SCLogDebug("value %s", value);
570 /* removes 'value'; keeps 'key' for next iteration */
571 lua_pop(luastate, 1);
572
574 SCLogError("too many flowvars registered");
575 goto error;
576 }
577
578 uint32_t idx = VarNameStoreRegister(value, VAR_TYPE_FLOW_VAR);
579 ld->flowvar[ld->flowvars++] = idx;
580 SCLogDebug("script uses flowvar %u with script id %u", idx, ld->flowvars - 1);
581 }
582 }
583 lua_pop(luastate, 1);
584 continue;
585 } else if (strcmp(k, "flowint") == 0) {
586 if (lua_istable(luastate, -1)) {
587 lua_pushnil(luastate);
588 while (lua_next(luastate, -2) != 0) {
589 /* value at -1, key is at -2 which we ignore */
590 const char *value = lua_tostring(luastate, -1);
591 SCLogDebug("value %s", value);
592 /* removes 'value'; keeps 'key' for next iteration */
593 lua_pop(luastate, 1);
594
596 SCLogError("too many flowints registered");
597 goto error;
598 }
599
600 uint32_t idx = VarNameStoreRegister(value, VAR_TYPE_FLOW_INT);
601 ld->flowint[ld->flowints++] = idx;
602 SCLogDebug("script uses flowint %u with script id %u", idx, ld->flowints - 1);
603 }
604 }
605 lua_pop(luastate, 1);
606 continue;
607 }
608
609 bool required = lua_toboolean(luastate, -1);
610 lua_pop(luastate, 1);
611 if (!required) {
612 continue;
613 }
614
615 if (strcmp(k, "ja3") == 0) {
616 ld->flags |= FLAG_LIST_JA3;
617 } else if (strcmp(k, "ja3s") == 0) {
618 ld->flags |= FLAG_LIST_JA3S;
619 } else if (strcmp(k, "packet") == 0) {
621 } else if (strcmp(k, "payload") == 0) {
623 } else if (strcmp(k, "buffer") == 0) {
625
626 ld->buffername = SCStrdup("buffer");
627 if (ld->buffername == NULL) {
628 SCLogError("alloc error");
629 goto error;
630 }
631 } else if (strcmp(k, "stream") == 0) {
633
634 ld->buffername = SCStrdup("stream");
635 if (ld->buffername == NULL) {
636 SCLogError("alloc error");
637 goto error;
638 }
639 /* old options no longer supported */
640 } else if (strncmp(k, "http", 4) == 0 || strncmp(k, "dns", 3) == 0 ||
641 strncmp(k, "tls", 3) == 0 || strncmp(k, "ssh", 3) == 0 ||
642 strncmp(k, "smtp", 4) == 0 || strncmp(k, "dnp3", 4) == 0) {
643 SCLogError("data type %s no longer supported, use rule hooks", k);
644 goto error;
645
646 } else {
647 SCLogError("unsupported data type %s", k);
648 goto error;
649 }
650 }
651
652 /* pop the table */
653 lua_pop(luastate, 1);
654 SCLuaSbStateClose(luastate);
655 return 0;
656error:
657 SCLuaSbStateClose(luastate);
658 return -1;
659}
660
661/**
662 * \brief this function is used to parse lua options
663 * \brief into the current signature
664 *
665 * \param de_ctx pointer to the Detection Engine Context
666 * \param s pointer to the Current Signature
667 * \param str pointer to the user provided "lua" option
668 *
669 * \retval 0 on Success
670 * \retval -1 on Failure
671 */
672static int DetectLuaSetup (DetectEngineCtx *de_ctx, Signature *s, const char *str)
673{
674 /* First check if Lua rules are enabled, by default Lua in rules
675 * is disabled. */
676 int enabled = 0;
677 if (SCConfGetBool("security.lua.allow-rules", &enabled) == 1 && !enabled) {
678 SCLogError("Lua rules disabled by security configuration: security.lua.allow-rules");
679 return -1;
680 }
681
682 DetectLuaData *lua = DetectLuaParse(de_ctx, str);
683 if (lua == NULL)
684 return -1;
685
686 /* Load lua sandbox configurations */
687 intmax_t lua_alloc_limit = DEFAULT_LUA_ALLOC_LIMIT;
688 intmax_t lua_instruction_limit = DEFAULT_LUA_INSTRUCTION_LIMIT;
689 (void)SCConfGetInt("security.lua.max-bytes", &lua_alloc_limit);
690 (void)SCConfGetInt("security.lua.max-instructions", &lua_instruction_limit);
691 lua->alloc_limit = lua_alloc_limit;
692 lua->instruction_limit = lua_instruction_limit;
693
694 int allow_restricted_functions = 0;
695 (void)SCConfGetBool("security.lua.allow-restricted-functions", &allow_restricted_functions);
696 lua->allow_restricted_functions = allow_restricted_functions;
697
698 if (DetectLuaSetupPrime(de_ctx, lua, s) == -1) {
699 goto error;
700 }
701
703 DetectLuaThreadInit, (void *)lua,
704 DetectLuaThreadFree, 0);
705 if (lua->thread_ctx_id == -1)
706 goto error;
707
708 int list = DetectBufferGetActiveList(de_ctx, s);
709 SCLogDebug("buffer list %d -> %d", list, s->init_data->list);
710 if (list == -1 || (list == 0 && s->init_data->list == INT_MAX)) {
711 /* what needs to happen here is: we register to the rule hook, so e.g.
712 * http1.request_complete. This means we need a list.
713 *
714 * This includes each pkt, payload, stream, etc. */
715
717 list = s->init_data->hook.sm_list;
718 SCLogDebug("setting list %d", list);
719 }
720 }
721
722 if (list == -1) {
723 SCLogError("lua failed to set up");
724 goto error;
725 }
726 if (list == 0) {
727 if (lua->flags & FLAG_LIST_JA3) {
728 list = g_lua_ja3_list_id;
729 } else if (lua->flags & FLAG_LIST_JA3S) {
730 list = g_lua_ja3s_list_id;
731 }
732 }
733
734 if (SCSigMatchAppendSMToList(de_ctx, s, DETECT_LUA, (SigMatchCtx *)lua, list) == NULL) {
735 goto error;
736 }
737
738 return 0;
739
740error:
741 if (lua != NULL)
742 DetectLuaFree(de_ctx, lua);
743 return -1;
744}
745
746/**
747 * \brief this function will free memory associated with DetectLuaData
748 *
749 * \param ptr pointer to DetectLuaData
750 */
751static void DetectLuaFree(DetectEngineCtx *de_ctx, void *ptr)
752{
753 if (ptr != NULL) {
754 DetectLuaData *lua = (DetectLuaData *)ptr;
755
756 if (lua->buffername)
757 SCFree(lua->buffername);
758 if (lua->filename)
759 SCFree(lua->filename);
760
761 for (uint16_t i = 0; i < lua->flowints; i++) {
763 }
764 for (uint16_t i = 0; i < lua->flowvars; i++) {
766 }
767 for (uint16_t i = 0; i < lua->bytevars; i++) {
768 SCFree(lua->bytevar[i].name);
769 }
770
772
773 SCFree(lua);
774 }
775}
776
777#ifdef UNITTESTS
778#include "detect-engine-alert.h"
779
780/** \test http buffer */
781static int LuaMatchTest01(void)
782{
783 SCConfSetFinal("security.lua.allow-rules", "true");
784
785 const char script[] = "local flowvarlib = require(\"suricata.flowvar\")\n"
786 "function init (args)\n"
787 " flowvarlib.register(\"cnt\")\n"
788 " return {}\n"
789 "end\n"
790 "function thread_init (args)\n"
791 " cnt = flowvarlib.get(\"cnt\")\n"
792 "end\n"
793 "\n"
794 "function match(args)\n"
795 " a = cnt:value()\n"
796 " if a then\n"
797 " a = tostring(tonumber(a)+1)\n"
798 " print (a)\n"
799 " cnt:set(a, #a)\n"
800 " else\n"
801 " a = tostring(1)\n"
802 " print (a)\n"
803 " cnt:set(a, #a)\n"
804 " end\n"
805 " \n"
806 " print (\"pre check: \" .. (a))\n"
807 " if tonumber(a) == 2 then\n"
808 " print \"match\"\n"
809 " return 1\n"
810 " end\n"
811 " return 0\n"
812 "end\n"
813 "return 0\n";
814 char sig[] = "alert http1:request_complete any any -> any any (flow:to_server; lua:unittest; "
815 "sid:1;)";
816 uint8_t httpbuf1[] =
817 "POST / HTTP/1.1\r\n"
818 "Host: www.emergingthreats.net\r\n\r\n";
819 uint8_t httpbuf2[] =
820 "POST / HTTP/1.1\r\n"
821 "Host: www.openinfosecfoundation.org\r\n\r\n";
822 uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
823 uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
824 TcpSession ssn;
825 Flow f;
826 ThreadVars th_v;
827 DetectEngineThreadCtx *det_ctx;
828
830
831 ut_script = script;
832
833 memset(&th_v, 0, sizeof(th_v));
834 memset(&f, 0, sizeof(f));
835 memset(&ssn, 0, sizeof(ssn));
836
837 Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
838 Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
839
840 FLOW_INITIALIZE(&f);
841 f.protoctx = (void *)&ssn;
842 f.proto = IPPROTO_TCP;
843 f.flags |= FLOW_IPV4;
845
846 p1->flow = &f;
850 p2->flow = &f;
854
856
860
862 FAIL_IF_NULL(s);
863
865 DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
866
867 int r = AppLayerParserParse(
868 NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
869 FAIL_IF(r != 0);
870 HtpState *http_state = f.alstate;
871 FAIL_IF_NULL(http_state);
872
873 /* do detect for p1 */
874 SCLogDebug("inspecting p1");
875 SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
876
878
879 r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
880 FAIL_IF(r != 0);
881
882 /* do detect for p2 */
883 SCLogDebug("inspecting p2");
884 SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
885
887
888 uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_VAR);
889 FAIL_IF(id == 0);
890
891 FlowVar *fv = FlowVarGet(&f, id);
892 FAIL_IF_NULL(fv);
893
894 FAIL_IF(fv->data.fv_str.value_len != 1);
895
896 FAIL_IF(memcmp(fv->data.fv_str.value, "2", 1) != 0);
897
900
902 FLOW_DESTROY(&f);
903 UTHFreePackets(&p1, 1);
904 UTHFreePackets(&p2, 1);
905 PASS;
906}
907
908static int LuaMatchTest01a(void)
909{
910 const char script[] = "local flowvarlib = require(\"suricata.flowvar\")\n"
911 "function init (args)\n"
912 " flowvarlib.register(\"cnt\")\n"
913 " return {}\n"
914 "end\n"
915 "function thread_init (args)\n"
916 " cnt = flowvarlib.get(\"cnt\")\n"
917 "end\n"
918 "\n"
919 "function match(args)\n"
920 " a = cnt:value(0)\n"
921 " if a then\n"
922 " a = tostring(tonumber(a)+1)\n"
923 " print (a)\n"
924 " cnt:set(a, #a)\n"
925 " else\n"
926 " a = tostring(1)\n"
927 " print (a)\n"
928 " cnt:set(a, #a)\n"
929 " end\n"
930 " \n"
931 " print (\"pre check: \" .. (a))\n"
932 " if tonumber(a) == 2 then\n"
933 " print \"match\"\n"
934 " return 1\n"
935 " end\n"
936 " return 0\n"
937 "end\n"
938 "return 0\n";
939 char sig[] = "alert http1:request_complete any any -> any any (flow:to_server; lua:unittest; "
940 "sid:1;)";
941 uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
942 "Host: www.emergingthreats.net\r\n\r\n";
943 uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
944 "Host: www.openinfosecfoundation.org\r\n\r\n";
945 uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
946 uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
947 TcpSession ssn;
948 Flow f;
949 ThreadVars th_v;
950 DetectEngineThreadCtx *det_ctx;
951
953
954 ut_script = script;
955
956 memset(&th_v, 0, sizeof(th_v));
957 memset(&f, 0, sizeof(f));
958 memset(&ssn, 0, sizeof(ssn));
959
960 Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
961 Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
962
963 FLOW_INITIALIZE(&f);
964 f.protoctx = (void *)&ssn;
965 f.proto = IPPROTO_TCP;
966 f.flags |= FLOW_IPV4;
968
969 p1->flow = &f;
973 p2->flow = &f;
977
979
983
985 FAIL_IF_NULL(s);
986
988 DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
989
990 int r = AppLayerParserParse(
991 NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
992 FAIL_IF(r != 0);
993
994 HtpState *http_state = f.alstate;
995 FAIL_IF_NULL(http_state);
996
997 /* do detect for p1 */
998 SCLogDebug("inspecting p1");
999 SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1000
1001 FAIL_IF(PacketAlertCheck(p1, 1));
1002
1003 r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1004 FAIL_IF(r != 0);
1005 /* do detect for p2 */
1006 SCLogDebug("inspecting p2");
1007 SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1008
1010
1011 uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_VAR);
1012 FAIL_IF(id == 0);
1013
1014 FlowVar *fv = FlowVarGet(&f, id);
1015 FAIL_IF_NULL(fv);
1016
1017 FAIL_IF(fv->data.fv_str.value_len != 1);
1018
1019 FAIL_IF(memcmp(fv->data.fv_str.value, "2", 1) != 0);
1020
1023
1024 StreamTcpFreeConfig(true);
1025 FLOW_DESTROY(&f);
1026 UTHFreePackets(&p1, 1);
1027 UTHFreePackets(&p2, 1);
1028 PASS;
1029}
1030
1031/** \test payload buffer */
1032static int LuaMatchTest02(void)
1033{
1034 const char script[] = "local flowvarlib = require(\"suricata.flowvar\")\n"
1035 "function init (args)\n"
1036 " flowvarlib.register(\"cnt\")\n"
1037 " local needs = {}\n"
1038 " needs[\"payload\"] = tostring(true)\n"
1039 " return needs\n"
1040 "end\n"
1041 "function thread_init (args)\n"
1042 " cnt = flowvarlib.get(\"cnt\")\n"
1043 "end\n"
1044 "\n"
1045 "function match(args)\n"
1046 " a = cnt:value()\n"
1047 " if a then\n"
1048 " a = tostring(tonumber(a)+1)\n"
1049 " print (a)\n"
1050 " cnt:set(a, #a)\n"
1051 " else\n"
1052 " a = tostring(1)\n"
1053 " print (a)\n"
1054 " cnt:set(a, #a)\n"
1055 " end\n"
1056 " \n"
1057 " print (\"pre check: \" .. (a))\n"
1058 " if tonumber(a) == 2 then\n"
1059 " print \"match\"\n"
1060 " return 1\n"
1061 " end\n"
1062 " return 0\n"
1063 "end\n"
1064 "return 0\n";
1065 char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1066 uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1067 "Host: www.emergingthreats.net\r\n\r\n";
1068 uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1069 "Host: www.openinfosecfoundation.org\r\n\r\n";
1070 uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1071 uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1072 TcpSession ssn;
1073 Flow f;
1074 ThreadVars th_v;
1075 DetectEngineThreadCtx *det_ctx;
1076
1077 ut_script = script;
1078
1079 memset(&th_v, 0, sizeof(th_v));
1080 memset(&f, 0, sizeof(f));
1081 memset(&ssn, 0, sizeof(ssn));
1082
1083 Packet *p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP);
1084 Packet *p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP);
1085
1086 FLOW_INITIALIZE(&f);
1087 f.protoctx = (void *)&ssn;
1088 f.proto = IPPROTO_TCP;
1089 f.flags |= FLOW_IPV4;
1091
1092 p1->flow = &f;
1096 p2->flow = &f;
1100
1101 StreamTcpInitConfig(true);
1102
1105 de_ctx->flags |= DE_QUIET;
1106
1108 FAIL_IF_NULL(s);
1109
1111 DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1112
1113 /* do detect for p1 */
1114 SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1115
1116 FAIL_IF(PacketAlertCheck(p1, 1));
1117
1118 /* do detect for p2 */
1119 SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1120
1122
1123 uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_VAR);
1124 FAIL_IF(id == 0);
1125
1126 FlowVar *fv = FlowVarGet(&f, id);
1127 FAIL_IF_NULL(fv);
1128
1129 FAIL_IF(fv->data.fv_str.value_len != 1);
1130
1131 FAIL_IF(memcmp(fv->data.fv_str.value, "2", 1) != 0);
1132
1134
1135 StreamTcpFreeConfig(true);
1136 FLOW_DESTROY(&f);
1137 UTHFreePackets(&p1, 1);
1138 UTHFreePackets(&p2, 1);
1139 PASS;
1140}
1141
1142/** \test payload buffer */
1143static int LuaMatchTest02a(void)
1144{
1145 const char script[] = "local flowvarlib = require(\"suricata.flowvar\")\n"
1146 "function init (args)\n"
1147 " flowvarlib.register(\"cnt\")"
1148 " local needs = {}\n"
1149 " needs[\"payload\"] = tostring(true)\n"
1150 " return needs\n"
1151 "end\n"
1152 "function thread_init (args)\n"
1153 " cnt = flowvarlib.get(\"cnt\")"
1154 "end\n"
1155 "\n"
1156 "function match(args)\n"
1157 " a = cnt:value()\n"
1158 " if a then\n"
1159 " a = tostring(tonumber(a)+1)\n"
1160 " print (a)\n"
1161 " cnt:set(a, #a)\n"
1162 " else\n"
1163 " a = tostring(1)\n"
1164 " print (a)\n"
1165 " cnt:set(a, #a)\n"
1166 " end\n"
1167 " \n"
1168 " print (\"pre check: \" .. (a))\n"
1169 " if tonumber(a) == 2 then\n"
1170 " print \"match\"\n"
1171 " return 1\n"
1172 " end\n"
1173 " return 0\n"
1174 "end\n"
1175 "return 0\n";
1176 char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1177 uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1178 "Host: www.emergingthreats.net\r\n\r\n";
1179 uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1180 "Host: www.openinfosecfoundation.org\r\n\r\n";
1181 uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1182 uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1183 TcpSession ssn;
1184 Flow f;
1185 ThreadVars th_v;
1186 DetectEngineThreadCtx *det_ctx;
1187
1188 ut_script = script;
1189
1190 memset(&th_v, 0, sizeof(th_v));
1191 memset(&f, 0, sizeof(f));
1192 memset(&ssn, 0, sizeof(ssn));
1193
1194 Packet *p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP);
1195 Packet *p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP);
1196
1197 FLOW_INITIALIZE(&f);
1198 f.protoctx = (void *)&ssn;
1199 f.proto = IPPROTO_TCP;
1200 f.flags |= FLOW_IPV4;
1202
1203 p1->flow = &f;
1207 p2->flow = &f;
1211
1212 StreamTcpInitConfig(true);
1213
1216 de_ctx->flags |= DE_QUIET;
1217
1219 FAIL_IF_NULL(s);
1220
1222 DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1223
1224 /* do detect for p1 */
1225 SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1226 FAIL_IF(PacketAlertCheck(p1, 1));
1227
1228 /* do detect for p2 */
1229 SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1230
1232
1233 uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_VAR);
1234 FAIL_IF(id == 0);
1235
1236 FlowVar *fv = FlowVarGet(&f, id);
1237 FAIL_IF_NULL(fv);
1238
1239 FAIL_IF(fv->data.fv_str.value_len != 1);
1240
1241 FAIL_IF(memcmp(fv->data.fv_str.value, "2", 1) != 0);
1242
1244
1245 StreamTcpFreeConfig(true);
1246 FLOW_DESTROY(&f);
1247 UTHFreePackets(&p1, 1);
1248 UTHFreePackets(&p2, 1);
1249 PASS;
1250}
1251
1252/** \test packet buffer */
1253static int LuaMatchTest03(void)
1254{
1255 const char script[] = "local flowvarlib = require(\"suricata.flowvar\")\n"
1256 "function init (args)\n"
1257 " flowvarlib.register(\"cnt\")\n"
1258 " local needs = {}\n"
1259 " needs[\"packet\"] = tostring(true)\n"
1260 " return needs\n"
1261 "end\n"
1262 "\n"
1263 "function thread_init (args)\n"
1264 " cnt = flowvarlib.get(\"cnt\")\n"
1265 "end\n"
1266 "\n"
1267 "function match(args)\n"
1268 " a = cnt:value()\n"
1269 " if a then\n"
1270 " a = tostring(tonumber(a)+1)\n"
1271 " print (a)\n"
1272 " cnt:set(a, #a)\n"
1273 " else\n"
1274 " a = tostring(1)\n"
1275 " print (a)\n"
1276 " cnt:set(a, #a)\n"
1277 " end\n"
1278 " \n"
1279 " print (\"pre check: \" .. (a))\n"
1280 " if tonumber(a) == 2 then\n"
1281 " print \"match\"\n"
1282 " return 1\n"
1283 " end\n"
1284 " return 0\n"
1285 "end\n"
1286 "return 0\n";
1287 char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1288 uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1289 "Host: www.emergingthreats.net\r\n\r\n";
1290 uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1291 "Host: www.openinfosecfoundation.org\r\n\r\n";
1292 uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1293 uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1294 TcpSession ssn;
1295 Flow f;
1296 ThreadVars th_v;
1297 DetectEngineThreadCtx *det_ctx;
1298
1299 ut_script = script;
1300
1301 memset(&th_v, 0, sizeof(th_v));
1302 memset(&f, 0, sizeof(f));
1303 memset(&ssn, 0, sizeof(ssn));
1304
1305 Packet *p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP);
1306 Packet *p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP);
1307
1308 FLOW_INITIALIZE(&f);
1309 f.protoctx = (void *)&ssn;
1310 f.proto = IPPROTO_TCP;
1311 f.flags |= FLOW_IPV4;
1313
1314 p1->flow = &f;
1318 p2->flow = &f;
1322
1323 StreamTcpInitConfig(true);
1324
1327 de_ctx->flags |= DE_QUIET;
1328
1330 FAIL_IF_NULL(s);
1331
1333 DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1334
1335 /* do detect for p1 */
1336 SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1337 FAIL_IF(PacketAlertCheck(p1, 1));
1338
1339 /* do detect for p2 */
1340 SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1341
1343
1344 uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_VAR);
1345 FAIL_IF(id == 0);
1346
1347 FlowVar *fv = FlowVarGet(&f, id);
1348 FAIL_IF_NULL(fv);
1349
1350 FAIL_IF(fv->data.fv_str.value_len != 1);
1351
1352 FAIL_IF(memcmp(fv->data.fv_str.value, "2", 1) != 0);
1353
1355
1356 StreamTcpFreeConfig(true);
1357 FLOW_DESTROY(&f);
1358 UTHFreePackets(&p1, 1);
1359 UTHFreePackets(&p2, 1);
1360 PASS;
1361}
1362
1363/** \test packet buffer */
1364static int LuaMatchTest03a(void)
1365{
1366 const char script[] = "local flowvarlib = require(\"suricata.flowvar\")\n"
1367 "function init (args)\n"
1368 " flowvarlib.register(\"cnt\")\n"
1369 " local needs = {}\n"
1370 " needs[\"packet\"] = tostring(true)\n"
1371 " return needs\n"
1372 "end\n"
1373 "\n"
1374 "function thread_init (args)\n"
1375 " cnt = flowvarlib.get(\"cnt\")\n"
1376 "end\n"
1377 "\n"
1378 "function match(args)\n"
1379 " a = cnt:value()\n"
1380 " if a then\n"
1381 " a = tostring(tonumber(a)+1)\n"
1382 " print (a)\n"
1383 " cnt:set(a, #a)\n"
1384 " else\n"
1385 " a = tostring(1)\n"
1386 " print (a)\n"
1387 " cnt:set(a, #a)\n"
1388 " end\n"
1389 " \n"
1390 " print (\"pre check: \" .. (a))\n"
1391 " if tonumber(a) == 2 then\n"
1392 " print \"match\"\n"
1393 " return 1\n"
1394 " end\n"
1395 " return 0\n"
1396 "end\n"
1397 "return 0\n";
1398 char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1399 uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1400 "Host: www.emergingthreats.net\r\n\r\n";
1401 uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1402 "Host: www.openinfosecfoundation.org\r\n\r\n";
1403 uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1404 uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1405 TcpSession ssn;
1406 Flow f;
1407 ThreadVars th_v;
1408 DetectEngineThreadCtx *det_ctx;
1409
1410 ut_script = script;
1411
1412 memset(&th_v, 0, sizeof(th_v));
1413 memset(&f, 0, sizeof(f));
1414 memset(&ssn, 0, sizeof(ssn));
1415
1416 Packet *p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP);
1417 Packet *p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP);
1418
1419 FLOW_INITIALIZE(&f);
1420 f.protoctx = (void *)&ssn;
1421 f.proto = IPPROTO_TCP;
1422 f.flags |= FLOW_IPV4;
1424
1425 p1->flow = &f;
1429 p2->flow = &f;
1433
1434 StreamTcpInitConfig(true);
1435
1438 de_ctx->flags |= DE_QUIET;
1439
1441 FAIL_IF_NULL(s);
1442
1444 DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1445
1446 /* do detect for p1 */
1447 SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1448 FAIL_IF(PacketAlertCheck(p1, 1));
1449
1450 /* do detect for p2 */
1451 SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1453
1454 uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_VAR);
1455 FAIL_IF(id == 0);
1456
1457 FlowVar *fv = FlowVarGet(&f, id);
1458 FAIL_IF_NULL(fv);
1459
1460 FAIL_IF(fv->data.fv_str.value_len != 1);
1461
1462 FAIL_IF(memcmp(fv->data.fv_str.value, "2", 1) != 0);
1463
1465
1466 StreamTcpFreeConfig(true);
1467 FLOW_DESTROY(&f);
1468 UTHFreePackets(&p1, 1);
1469 UTHFreePackets(&p2, 1);
1470 PASS;
1471}
1472
1473/** \test http buffer, flowints */
1474static int LuaMatchTest04(void)
1475{
1476 const char script[] = "local flowintlib = require(\"suricata.flowint\")\n"
1477 "function init (args)\n"
1478 " flowintlib.register(\"cnt\")\n"
1479 " return {}\n"
1480 "end\n"
1481 "\n"
1482 "function thread_init (args)\n"
1483 " cnt = flowintlib.get(\"cnt\")\n"
1484 "end\n"
1485 "\n"
1486 "function match(args)\n"
1487 " print \"inspecting\""
1488 " a = cnt:value()\n"
1489 " if a then\n"
1490 " cnt:set(a + 1)\n"
1491 " else\n"
1492 " cnt:set(1)\n"
1493 " end\n"
1494 " \n"
1495 " a = cnt:value()\n"
1496 " if a == 2 then\n"
1497 " print \"match\"\n"
1498 " return 1\n"
1499 " end\n"
1500 " return 0\n"
1501 "end\n"
1502 "return 0\n";
1503 char sig[] = "alert http1:request_complete any any -> any any (flow:to_server; lua:unittest; "
1504 "sid:1;)";
1505 uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1506 "Host: www.emergingthreats.net\r\n\r\n";
1507 uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1508 "Host: www.openinfosecfoundation.org\r\n\r\n";
1509 uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1510 uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1511 TcpSession ssn;
1512 Flow f;
1513 ThreadVars th_v;
1514 DetectEngineThreadCtx *det_ctx;
1515
1517
1518 ut_script = script;
1519
1520 memset(&th_v, 0, sizeof(th_v));
1521 memset(&f, 0, sizeof(f));
1522 memset(&ssn, 0, sizeof(ssn));
1523
1524 Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1525 Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1526
1527 FLOW_INITIALIZE(&f);
1528 f.protoctx = (void *)&ssn;
1529 f.proto = IPPROTO_TCP;
1530 f.flags |= FLOW_IPV4;
1532
1533 p1->flow = &f;
1537
1538 p2->flow = &f;
1542
1543 StreamTcpInitConfig(true);
1544
1547 de_ctx->flags |= DE_QUIET;
1548
1550 FAIL_IF_NULL(s);
1551
1553 DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1554
1555 int r = AppLayerParserParse(
1556 NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
1557 FAIL_IF(r != 0);
1558 HtpState *http_state = f.alstate;
1559 FAIL_IF_NULL(http_state);
1560
1561 /* do detect for p1 */
1562 SCLogInfo("p1");
1563 SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1564
1565 FAIL_IF(PacketAlertCheck(p1, 1));
1566
1567 r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1568 FAIL_IF(r != 0);
1569 /* do detect for p2 */
1570 SCLogInfo("p2");
1571 SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1572
1574
1575 uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_INT);
1576 FAIL_IF(id == 0);
1577
1578 FlowVar *fv = FlowVarGet(&f, id);
1579 FAIL_IF_NULL(fv);
1580
1581 FAIL_IF(fv->data.fv_int.value != 2);
1582
1585
1586 StreamTcpFreeConfig(true);
1587 FLOW_DESTROY(&f);
1588 UTHFreePackets(&p1, 1);
1589 UTHFreePackets(&p2, 1);
1590 PASS;
1591}
1592
1593/** \test http buffer, flowints */
1594static int LuaMatchTest04a(void)
1595{
1596 const char script[] = "local flowintlib = require(\"suricata.flowint\")\n"
1597 "function init (args)\n"
1598 " flowintlib.register(\"cnt\")\n"
1599 " return {}\n"
1600 "end\n"
1601 "\n"
1602 "function thread_init (args)\n"
1603 " cnt = flowintlib.get(\"cnt\")\n"
1604 "end\n"
1605 "\n"
1606 "function match(args)\n"
1607 " print \"inspecting\""
1608 " a = cnt:value()\n"
1609 " if a then\n"
1610 " cnt:set(a + 1)\n"
1611 " else\n"
1612 " cnt:set(1)\n"
1613 " end\n"
1614 " \n"
1615 " a = cnt:value()\n"
1616 " if a == 2 then\n"
1617 " print \"match\"\n"
1618 " return 1\n"
1619 " end\n"
1620 " return 0\n"
1621 "end\n"
1622 "return 0\n";
1623 char sig[] = "alert http1:request_complete any any -> any any (flow:to_server; lua:unittest; "
1624 "sid:1;)";
1625 uint8_t httpbuf1[] =
1626 "POST / HTTP/1.1\r\n"
1627 "Host: www.emergingthreats.net\r\n\r\n";
1628 uint8_t httpbuf2[] =
1629 "POST / HTTP/1.1\r\n"
1630 "Host: www.openinfosecfoundation.org\r\n\r\n";
1631 uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1632 uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1633 TcpSession ssn;
1634 Flow f;
1635 ThreadVars th_v;
1636 DetectEngineThreadCtx *det_ctx;
1637
1639
1640 ut_script = script;
1641
1642 memset(&th_v, 0, sizeof(th_v));
1643 memset(&f, 0, sizeof(f));
1644 memset(&ssn, 0, sizeof(ssn));
1645
1646 Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1647 Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1648
1649 FLOW_INITIALIZE(&f);
1650 f.protoctx = (void *)&ssn;
1651 f.proto = IPPROTO_TCP;
1652 f.flags |= FLOW_IPV4;
1654
1655 p1->flow = &f;
1659
1660 p2->flow = &f;
1664
1665 StreamTcpInitConfig(true);
1666
1669 de_ctx->flags |= DE_QUIET;
1670
1672 FAIL_IF_NULL(s);
1673
1675 DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1676
1677 int r = AppLayerParserParse(
1678 NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
1679 FAIL_IF(r != 0);
1680 HtpState *http_state = f.alstate;
1681 FAIL_IF_NULL(http_state);
1682
1683 /* do detect for p1 */
1684 SCLogInfo("p1");
1685 SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1686
1687 FAIL_IF(PacketAlertCheck(p1, 1));
1688
1689 r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1690 FAIL_IF(r != 0);
1691 /* do detect for p2 */
1692 SCLogInfo("p2");
1693 SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1694
1696
1697 uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_INT);
1698 FAIL_IF(id == 0);
1699
1700 FlowVar *fv = FlowVarGet(&f, id);
1701 FAIL_IF_NULL(fv);
1702
1703 FAIL_IF(fv->data.fv_int.value != 2);
1704
1707
1708 StreamTcpFreeConfig(true);
1709 FLOW_DESTROY(&f);
1710 UTHFreePackets(&p1, 1);
1711 UTHFreePackets(&p2, 1);
1712 PASS;
1713}
1714
1715/** \test http buffer, flowints */
1716static int LuaMatchTest05(void)
1717{
1718 const char script[] = "local flowintlib = require(\"suricata.flowint\")\n"
1719 "function init (args)\n"
1720 " flowintlib.register(\"cnt\")\n"
1721 " return {}\n"
1722 "end\n"
1723 "\n"
1724 "function thread_init (args)\n"
1725 " cnt = flowintlib.get(\"cnt\")\n"
1726 "end\n"
1727 "\n"
1728 "function match(args)\n"
1729 " print \"inspecting\""
1730 " a = cnt:incr()\n"
1731 " if a == 2 then\n"
1732 " print \"match\"\n"
1733 " return 1\n"
1734 " end\n"
1735 " return 0\n"
1736 "end\n"
1737 "return 0\n";
1738 char sig[] = "alert http1:request_complete any any -> any any (flow:to_server; lua:unittest; "
1739 "sid:1;)";
1740 uint8_t httpbuf1[] =
1741 "POST / HTTP/1.1\r\n"
1742 "Host: www.emergingthreats.net\r\n\r\n";
1743 uint8_t httpbuf2[] =
1744 "POST / HTTP/1.1\r\n"
1745 "Host: www.openinfosecfoundation.org\r\n\r\n";
1746 uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1747 uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1748 TcpSession ssn;
1749 Flow f;
1750 ThreadVars th_v;
1751 DetectEngineThreadCtx *det_ctx;
1752
1754
1755 ut_script = script;
1756
1757 memset(&th_v, 0, sizeof(th_v));
1758 memset(&f, 0, sizeof(f));
1759 memset(&ssn, 0, sizeof(ssn));
1760
1761 Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1762 Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1763
1764 FLOW_INITIALIZE(&f);
1765 f.protoctx = (void *)&ssn;
1766 f.proto = IPPROTO_TCP;
1767 f.flags |= FLOW_IPV4;
1769
1770 p1->flow = &f;
1774
1775 p2->flow = &f;
1779
1780 StreamTcpInitConfig(true);
1781
1784 de_ctx->flags |= DE_QUIET;
1785
1787 FAIL_IF_NULL(s);
1788
1790 DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1791
1792 int r = AppLayerParserParse(
1793 NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
1794 FAIL_IF(r != 0);
1795 HtpState *http_state = f.alstate;
1796 FAIL_IF_NULL(http_state);
1797
1798 /* do detect for p1 */
1799 SCLogInfo("p1");
1800 SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1801
1802 FAIL_IF(PacketAlertCheck(p1, 1));
1803
1804 r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1805 FAIL_IF(r != 0);
1806 /* do detect for p2 */
1807 SCLogInfo("p2");
1808 SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1809
1811
1812 uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_INT);
1813 FAIL_IF(id == 0);
1814
1815 FlowVar *fv = FlowVarGet(&f, id);
1816 FAIL_IF_NULL(fv);
1817
1818 FAIL_IF(fv->data.fv_int.value != 2);
1819
1822
1823 StreamTcpFreeConfig(true);
1824 FLOW_DESTROY(&f);
1825 UTHFreePackets(&p1, 1);
1826 UTHFreePackets(&p2, 1);
1827 PASS;
1828}
1829
1830/** \test http buffer, flowints */
1831static int LuaMatchTest05a(void)
1832{
1833 const char script[] = "local flowintlib = require(\"suricata.flowint\")\n"
1834 "function init (args)\n"
1835 " flowintlib.register(\"cnt\")\n"
1836 " return {}\n"
1837 "end\n"
1838 "\n"
1839 "function thread_init (args)\n"
1840 " cnt = flowintlib.get(\"cnt\")\n"
1841 "end\n"
1842 "\n"
1843 "function match(args)\n"
1844 " print \"inspecting\""
1845 " a = cnt:incr()\n"
1846 " if a == 2 then\n"
1847 " print \"match\"\n"
1848 " return 1\n"
1849 " end\n"
1850 " return 0\n"
1851 "end\n"
1852 "return 0\n";
1853 char sig[] = "alert http1:request_complete any any -> any any (flow:to_server; lua:unittest; "
1854 "sid:1;)";
1855 uint8_t httpbuf1[] =
1856 "POST / HTTP/1.1\r\n"
1857 "Host: www.emergingthreats.net\r\n\r\n";
1858 uint8_t httpbuf2[] =
1859 "POST / HTTP/1.1\r\n"
1860 "Host: www.openinfosecfoundation.org\r\n\r\n";
1861 uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1862 uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1863 TcpSession ssn;
1864 Flow f;
1865 ThreadVars th_v;
1866 DetectEngineThreadCtx *det_ctx;
1867
1869
1870 ut_script = script;
1871
1872 memset(&th_v, 0, sizeof(th_v));
1873 memset(&f, 0, sizeof(f));
1874 memset(&ssn, 0, sizeof(ssn));
1875
1876 Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1877 Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1878
1879 FLOW_INITIALIZE(&f);
1880 f.protoctx = (void *)&ssn;
1881 f.proto = IPPROTO_TCP;
1882 f.flags |= FLOW_IPV4;
1884
1885 p1->flow = &f;
1889
1890 p2->flow = &f;
1894
1895 StreamTcpInitConfig(true);
1896
1899 de_ctx->flags |= DE_QUIET;
1900
1902 FAIL_IF_NULL(s);
1903
1905 DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1906
1907 int r = AppLayerParserParse(
1908 NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
1909 FAIL_IF(r != 0);
1910 HtpState *http_state = f.alstate;
1911 FAIL_IF_NULL(http_state);
1912
1913 /* do detect for p1 */
1914 SCLogInfo("p1");
1915 SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1916
1917 FAIL_IF(PacketAlertCheck(p1, 1));
1918
1919 r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1920 FAIL_IF(r != 0);
1921 /* do detect for p2 */
1922 SCLogInfo("p2");
1923 SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1924
1926
1927 uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_INT);
1928 FAIL_IF(id == 0);
1929
1930 FlowVar *fv = FlowVarGet(&f, id);
1931 FAIL_IF_NULL(fv);
1932
1933 FAIL_IF(fv->data.fv_int.value != 2);
1934
1937
1938 StreamTcpFreeConfig(true);
1939 FLOW_DESTROY(&f);
1940 UTHFreePackets(&p1, 1);
1941 UTHFreePackets(&p2, 1);
1942 PASS;
1943}
1944
1945/** \test http buffer, flowints */
1946static int LuaMatchTest06(void)
1947{
1948 const char script[] = "local flowintlib = require(\"suricata.flowint\")\n"
1949 "function init (args)\n"
1950 " flowintlib.register(\"cnt\")\n"
1951 " return {}\n"
1952 "end\n"
1953 "\n"
1954 "function thread_init (args)\n"
1955 " cnt = flowintlib.get(\"cnt\")\n"
1956 "end\n"
1957 "\n"
1958 "function match(args)\n"
1959 " print \"inspecting\""
1960 " a = cnt:value()\n"
1961 " if a == nil then\n"
1962 " print \"new var set to 2\""
1963 " cnt:set(2)\n"
1964 " end\n"
1965 " a = cnt:decr()\n"
1966 " if a == 0 then\n"
1967 " print \"match\"\n"
1968 " return 1\n"
1969 " end\n"
1970 " return 0\n"
1971 "end\n"
1972 "return 0\n";
1973 char sig[] = "alert http1:request_complete any any -> any any (flow:to_server; lua:unittest; "
1974 "sid:1;)";
1975 uint8_t httpbuf1[] =
1976 "POST / HTTP/1.1\r\n"
1977 "Host: www.emergingthreats.net\r\n\r\n";
1978 uint8_t httpbuf2[] =
1979 "POST / HTTP/1.1\r\n"
1980 "Host: www.openinfosecfoundation.org\r\n\r\n";
1981 uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1982 uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1983 TcpSession ssn;
1984 Flow f;
1985 ThreadVars th_v;
1986 DetectEngineThreadCtx *det_ctx;
1987
1989
1990 ut_script = script;
1991
1992 memset(&th_v, 0, sizeof(th_v));
1993 memset(&f, 0, sizeof(f));
1994 memset(&ssn, 0, sizeof(ssn));
1995
1996 Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1997 Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1998
1999 FLOW_INITIALIZE(&f);
2000 f.protoctx = (void *)&ssn;
2001 f.proto = IPPROTO_TCP;
2002 f.flags |= FLOW_IPV4;
2004
2005 p1->flow = &f;
2009
2010 p2->flow = &f;
2014
2015 StreamTcpInitConfig(true);
2016
2019 de_ctx->flags |= DE_QUIET;
2020
2022 FAIL_IF_NULL(s);
2023
2025 DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2026
2027 int r = AppLayerParserParse(
2028 NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
2029 FAIL_IF(r != 0);
2030 HtpState *http_state = f.alstate;
2031 FAIL_IF_NULL(http_state);
2032
2033 /* do detect for p1 */
2034 SCLogInfo("p1");
2035 SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
2036
2037 FAIL_IF(PacketAlertCheck(p1, 1));
2038
2039 r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
2040 FAIL_IF(r != 0);
2041 /* do detect for p2 */
2042 SCLogInfo("p2");
2043 SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
2044
2046
2047 uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_INT);
2048 FAIL_IF(id == 0);
2049
2050 FlowVar *fv = FlowVarGet(&f, id);
2051 FAIL_IF_NULL(fv);
2052
2053 FAIL_IF(fv->data.fv_int.value != 0);
2054
2057
2058 StreamTcpFreeConfig(true);
2059 FLOW_DESTROY(&f);
2060 UTHFreePackets(&p1, 1);
2061 UTHFreePackets(&p2, 1);
2062 PASS;
2063}
2064
2065/** \test http buffer, flowints */
2066static int LuaMatchTest06a(void)
2067{
2068 const char script[] = "local flowintlib = require(\"suricata.flowint\")\n"
2069 "function init (args)\n"
2070 " flowintlib.register(\"cnt\")\n"
2071 " return {}\n"
2072 "end\n"
2073 "\n"
2074 "function thread_init (args)\n"
2075 " cnt = flowintlib.get(\"cnt\")\n"
2076 "end\n"
2077 "\n"
2078 "function match(args)\n"
2079 " print \"inspecting\""
2080 " a = cnt:value()\n"
2081 " if a == nil then\n"
2082 " print \"new var set to 2\""
2083 " cnt:set(2)\n"
2084 " end\n"
2085 " a = cnt:decr()\n"
2086 " if a == 0 then\n"
2087 " print \"match\"\n"
2088 " return 1\n"
2089 " end\n"
2090 " return 0\n"
2091 "end\n"
2092 "return 0\n";
2093 char sig[] = "alert http1:request_complete any any -> any any (flow:to_server; lua:unittest; "
2094 "sid:1;)";
2095 uint8_t httpbuf1[] =
2096 "POST / HTTP/1.1\r\n"
2097 "Host: www.emergingthreats.net\r\n\r\n";
2098 uint8_t httpbuf2[] =
2099 "POST / HTTP/1.1\r\n"
2100 "Host: www.openinfosecfoundation.org\r\n\r\n";
2101 uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2102 uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2103 TcpSession ssn;
2104 Flow f;
2105 ThreadVars th_v;
2106 DetectEngineThreadCtx *det_ctx;
2107
2109
2110 ut_script = script;
2111
2112 memset(&th_v, 0, sizeof(th_v));
2113 memset(&f, 0, sizeof(f));
2114 memset(&ssn, 0, sizeof(ssn));
2115
2116 Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2117 Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2118
2119 FLOW_INITIALIZE(&f);
2120 f.protoctx = (void *)&ssn;
2121 f.proto = IPPROTO_TCP;
2122 f.flags |= FLOW_IPV4;
2124
2125 p1->flow = &f;
2129
2130 p2->flow = &f;
2134
2135 StreamTcpInitConfig(true);
2136
2139 de_ctx->flags |= DE_QUIET;
2140
2142 FAIL_IF_NULL(s);
2143
2145 DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2146
2147 int r = AppLayerParserParse(
2148 NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
2149 FAIL_IF(r != 0);
2150 HtpState *http_state = f.alstate;
2151 FAIL_IF_NULL(http_state);
2152
2153 /* do detect for p1 */
2154 SCLogInfo("p1");
2155 SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
2156
2157 FAIL_IF(PacketAlertCheck(p1, 1));
2158
2159 r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
2160 FAIL_IF(r != 0);
2161 /* do detect for p2 */
2162 SCLogInfo("p2");
2163 SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
2164
2166
2167 uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_INT);
2168 FAIL_IF(id == 0);
2169
2170 FlowVar *fv = FlowVarGet(&f, id);
2171 FAIL_IF_NULL(fv);
2172
2173 FAIL_IF(fv->data.fv_int.value != 0);
2174
2177
2178 StreamTcpFreeConfig(true);
2179 FLOW_DESTROY(&f);
2180 UTHFreePackets(&p1, 1);
2181 UTHFreePackets(&p2, 1);
2182 PASS;
2183}
2184
2185void DetectLuaRegisterTests(void)
2186{
2187 UtRegisterTest("LuaMatchTest01", LuaMatchTest01);
2188 UtRegisterTest("LuaMatchTest01a", LuaMatchTest01a);
2189 UtRegisterTest("LuaMatchTest02", LuaMatchTest02);
2190 UtRegisterTest("LuaMatchTest02a", LuaMatchTest02a);
2191 UtRegisterTest("LuaMatchTest03", LuaMatchTest03);
2192 UtRegisterTest("LuaMatchTest03a", LuaMatchTest03a);
2193 UtRegisterTest("LuaMatchTest04", LuaMatchTest04);
2194 UtRegisterTest("LuaMatchTest04a", LuaMatchTest04a);
2195 UtRegisterTest("LuaMatchTest05", LuaMatchTest05);
2196 UtRegisterTest("LuaMatchTest05a", LuaMatchTest05a);
2197 UtRegisterTest("LuaMatchTest06", LuaMatchTest06);
2198 UtRegisterTest("LuaMatchTest06a", LuaMatchTest06a);
2199}
2200#endif
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, const uint8_t *input, uint32_t input_len)
@ ALPROTO_TLS
@ ALPROTO_QUIC
@ ALPROTO_HTTP1
@ TLS_STATE_CLIENT_HELLO_DONE
@ TLS_STATE_SERVER_HELLO_DONE
int SCConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
Definition conf.c:414
int SCConfSetFinal(const char *name, const char *val)
Set a final configuration value.
Definition conf.c:318
int SCConfGetBool(const char *name, int *val)
Retrieve a configuration value as a boolean.
Definition conf.c:497
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition counters.c:166
uint8_t flags
Definition decode-gre.h:0
uint16_t type
#define PKT_HAS_FLOW
Definition decode.h:1266
#define GET_PKT_LEN(p)
Definition decode.h:208
#define PKT_STREAM_EST
Definition decode.h:1262
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
int DetectBufferGetActiveList(DetectEngineCtx *de_ctx, Signature *s)
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
char * DetectLoadCompleteSigPath(const DetectEngineCtx *de_ctx, const char *sig_file)
Create the path if default-rule-path was specified.
DetectEngineCtx * DetectEngineCtxInit(void)
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Signature * DetectEngineAppendSig(DetectEngineCtx *, const char *)
Parse and append a Signature into the Detection Engine Context signature list.
void * DetectThreadCtxGetKeywordThreadCtx(DetectEngineThreadCtx *det_ctx, int id)
Retrieve thread local keyword ctx by id.
int DetectBufferTypeRegister(const char *name)
int DetectRegisterThreadCtxFuncs(DetectEngineCtx *de_ctx, const char *name, void *(*InitFunc)(void *), void *data, void(*FreeFunc)(void *), int mode)
Register Thread keyword context Funcs.
int DetectUnregisterThreadCtxFuncs(DetectEngineCtx *de_ctx, void *data, const char *name)
Remove Thread keyword context registration.
void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uint32_t dir, int progress, InspectEngineFuncPtr Callback, InspectionBufferGetDataPtr GetData)
Registers an app inspection engine.
TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
initialize thread specific detection engine context
uint8_t DetectEngineInspectGenericList(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const struct DetectEngineAppInspectionEngine_ *engine, const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
Do the content inspection & validation for a signature.
const char luaext_key_ld[]
void LuaExtensionsMatchSetup(lua_State *lua_state, DetectLuaData *ld, DetectEngineThreadCtx *det_ctx, Flow *f, Packet *p, const Signature *s, uint8_t flags)
#define FLAG_ERROR_LOGGED
Definition detect-lua.c:118
#define FLAG_MEMORY_LIMIT_LOGGED
Definition detect-lua.c:121
#define FLAG_LIST_JA3S
Definition detect-lua.c:116
#define DEFAULT_LUA_INSTRUCTION_LIMIT
Definition detect-lua.c:124
#define FLAG_DATATYPE_STREAM
Definition detect-lua.c:114
#define FLAG_DATATYPE_PACKET
Definition detect-lua.c:112
#define FLAG_INSTRUCTION_LIMIT_LOGGED
Definition detect-lua.c:120
#define FLAG_BLOCKED_FUNCTION_LOGGED
Definition detect-lua.c:119
int DetectLuaMatchBuffer(DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, const uint8_t *buffer, uint32_t buffer_len, uint32_t offset, Flow *f)
Definition detect-lua.c:240
void LuaDumpStack(lua_State *state, const char *prefix)
dump stack from lua state to screen
Definition detect-lua.c:127
void DetectLuaRegister(void)
Registration function for keyword: lua.
Definition detect-lua.c:83
#define FLAG_DATATYPE_BUFFER
Definition detect-lua.c:117
#define FLAG_LIST_JA3
Definition detect-lua.c:115
#define FLAG_DATATYPE_PAYLOAD
Definition detect-lua.c:113
#define DEFAULT_LUA_ALLOC_LIMIT
Definition detect-lua.c:123
#define DETECT_LUA_MAX_FLOWINTS
Definition detect-lua.h:36
#define DETECT_LUA_MAX_FLOWVARS
Definition detect-lua.h:35
SigMatch * SCSigMatchAppendSMToList(DetectEngineCtx *de_ctx, Signature *s, uint16_t type, SigMatchCtx *ctx, const int list)
Append a SigMatch to the list type.
SigTableElmt * sigmatch_table
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition detect.c:2420
#define DE_QUIET
Definition detect.h:330
#define SIG_FLAG_TOCLIENT
Definition detect.h:272
#define SIG_FLAG_TOSERVER
Definition detect.h:271
@ SIGNATURE_HOOK_TYPE_NOT_SET
Definition detect.h:547
#define FLOW_INITIALIZE(f)
Definition flow-util.h:38
#define FLOW_DESTROY(f)
Definition flow-util.h:119
FlowVar * FlowVarGet(Flow *f, uint32_t idx)
get the flowvar with index 'idx' from the flow
Definition flow-var.c:84
#define FLOW_PKT_TOSERVER
Definition flow.h:233
#define FLOW_PKT_ESTABLISHED
Definition flow.h:235
#define FLOW_IPV4
Definition flow.h:100
#define FLOW_PKT_TOCLIENT
Definition flow.h:234
AppLayerParserThreadCtx * alp_tctx
DetectEngineCtx * de_ctx
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
#define PASS
Pass the test.
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
struct Thresholds ctx
void StreamTcpFreeConfig(bool quiet)
Definition stream-tcp.c:859
void StreamTcpInitConfig(bool)
To initialize the stream global configuration data.
Definition stream-tcp.c:488
main detection engine ctx
Definition detect.h:932
uint8_t flags
Definition detect.h:934
uint16_t lua_blocked_function_errors
Definition detect.h:1379
ThreadVars * tv
Definition detect.h:1252
uint16_t lua_memory_limit_errors
Definition detect.h:1385
uint16_t lua_rule_errors
Definition detect.h:1376
uint16_t lua_instruction_limit_errors
Definition detect.h:1382
uint32_t flags
Definition detect-lua.h:48
uint64_t alloc_limit
Definition detect-lua.h:56
uint16_t flowvars
Definition detect-lua.h:52
uint64_t instruction_limit
Definition detect-lua.h:57
uint32_t flowint[DETECT_LUA_MAX_FLOWINTS]
Definition detect-lua.h:50
int allow_restricted_functions
Definition detect-lua.h:58
uint32_t flowvar[DETECT_LUA_MAX_FLOWVARS]
Definition detect-lua.h:53
DetectLuaDataBytevarEntry bytevar[DETECT_LUA_MAX_BYTEVARS]
Definition detect-lua.h:55
char * filename
Definition detect-lua.h:47
uint16_t flowints
Definition detect-lua.h:51
char * buffername
Definition detect-lua.h:49
uint16_t bytevars
Definition detect-lua.h:54
lua_State * luastate
Definition detect-lua.h:31
uint32_t value
Definition flow-var.h:46
uint16_t value_len
Definition flow-var.h:41
uint8_t * value
Definition flow-var.h:40
FlowVarTypeInt fv_int
Definition flow-var.h:65
FlowVarTypeStr fv_str
Definition flow-var.h:64
union FlowVar_::@124 data
Flow data structure.
Definition flow.h:356
uint8_t proto
Definition flow.h:378
uint32_t flags
Definition flow.h:421
AppProto alproto
application level protocol
Definition flow.h:450
void * alstate
Definition flow.h:479
void * protoctx
Definition flow.h:441
uint8_t flowflags
Definition decode.h:532
struct Flow_ * flow
Definition decode.h:546
uint16_t payload_len
Definition decode.h:606
uint32_t flags
Definition decode.h:544
bool instruction_count_error
bool blocked_function_error
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition detect.h:351
Data needed for Match()
Definition detect.h:365
SigMatchCtx * ctx
Definition detect.h:368
const char * url
Definition detect.h:1462
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition detect.h:1441
void(* Free)(DetectEngineCtx *, void *)
Definition detect.h:1446
const char * desc
Definition detect.h:1461
int(* AppLayerTxMatch)(DetectEngineThreadCtx *, Flow *, uint8_t flags, void *alstate, void *txv, const Signature *, const SigMatchCtx *)
Definition detect.h:1424
void(* RegisterTests)(void)
Definition detect.h:1448
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition detect.h:1421
const char * name
Definition detect.h:1459
enum SignatureHookType type
Definition detect.h:572
SignatureHook hook
Definition detect.h:590
Signature container.
Definition detect.h:668
SignatureInitData * init_data
Definition detect.h:747
Per thread variable structure.
Definition threadvars.h:58
struct lua_State lua_State
#define BUG_ON(x)
#define str(s)
#define SCEnter(...)
Definition util-debug.h:277
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCReturnInt(x)
Definition util-debug.h:281
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition util-debug.h:255
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition util-debug.h:225
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267
void SCLuaRequirefBuiltIns(lua_State *L)
Register Suricata built-in modules for loading in a non-sandboxed environment.
void SCLuaSbStateClose(lua_State *L)
void SCLuaSbLoadLibs(lua_State *L)
lua_State * SCLuaSbStateNew(uint64_t alloclimit, uint64_t instructionlimit)
Allocate a new Lua sandbox.
SCLuaSbState * SCLuaSbGetContext(lua_State *L)
void SCLuaSbResetInstructionCounter(lua_State *L)
int LuaPushStringBuffer(lua_State *luastate, const uint8_t *input, size_t input_len)
Definition util-lua.c:319
void LuaStateSetThreadVars(lua_State *luastate, ThreadVars *tv)
Definition util-lua.c:110
#define SCFree(p)
Definition util-mem.h:61
#define SCCalloc(nm, sz)
Definition util-mem.h:53
#define SCStrdup(s)
Definition util-mem.h:56
#define unlikely(expr)
uint64_t offset
void UTHFreePackets(Packet **p, int numpkts)
UTHFreePackets: function to release the allocated data from UTHBuildPacket and the packet itself.
Packet * UTHBuildPacket(uint8_t *payload, uint16_t payload_len, uint8_t ipproto)
UTHBuildPacket is a wrapper that build packets with default ip and port fields.
void VarNameStoreUnregister(const uint32_t id, const enum VarTypes type)
uint32_t VarNameStoreRegister(const char *name, const enum VarTypes type)
uint32_t VarNameStoreLookupByName(const char *name, const enum VarTypes type)
find name for id+type at packet time. As the active store won't be modified, we don't need locks.
@ VAR_TYPE_FLOW_VAR
Definition util-var.h:39
@ VAR_TYPE_FLOW_INT
Definition util-var.h:37