suricata
detect-lua.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2022 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 "threads.h"
29 #include "decode.h"
30 
31 #include "detect.h"
32 #include "detect-parse.h"
33 
34 #include "detect-engine.h"
35 #include "detect-engine-mpm.h"
36 #include "detect-engine-state.h"
37 #include "detect-engine-build.h"
38 
39 #include "detect-byte.h"
40 
41 #include "flow.h"
42 #include "flow-var.h"
43 #include "flow-util.h"
44 
45 #include "util-debug.h"
46 #include "util-spm-bm.h"
47 #include "util-print.h"
48 #include "util-byte.h"
49 
50 #include "util-unittest.h"
51 #include "util-unittest-helper.h"
52 
53 #include "app-layer.h"
54 #include "app-layer-parser.h"
55 #include "app-layer-htp.h"
56 
57 #include "stream-tcp.h"
58 
59 #include "detect-lua.h"
60 #include "detect-lua-extensions.h"
61 
62 #include "queue.h"
63 #include "util-cpu.h"
64 #include "util-var-name.h"
65 
66 #ifndef HAVE_LUA
67 
68 static int DetectLuaSetupNoSupport (DetectEngineCtx *a, Signature *b, const char *c)
69 {
70  SCLogError(SC_ERR_NO_LUA_SUPPORT, "no Lua support built in, needed for lua/luajit keyword");
71  return -1;
72 }
73 
74 /**
75  * \brief Registration function for keyword: lua
76  */
78 {
80  sigmatch_table[DETECT_LUA].alias = "luajit";
81  sigmatch_table[DETECT_LUA].desc = "support for lua scripting";
82  sigmatch_table[DETECT_LUA].url = "/rules/rule-lua-scripting.html";
83  sigmatch_table[DETECT_LUA].Setup = DetectLuaSetupNoSupport;
86 
87  SCLogDebug("registering lua rule option");
88  return;
89 }
90 
91 #else /* HAVE_LUA */
92 
93 #include "util-lua.h"
94 
95 static int DetectLuaMatch (DetectEngineThreadCtx *,
96  Packet *, const Signature *, const SigMatchCtx *);
97 static int DetectLuaAppTxMatch (DetectEngineThreadCtx *det_ctx,
98  Flow *f, uint8_t flags,
99  void *state, void *txv, const Signature *s,
100  const SigMatchCtx *ctx);
101 static int DetectLuaSetup (DetectEngineCtx *, Signature *, const char *);
102 #ifdef UNITTESTS
103 static void DetectLuaRegisterTests(void);
104 #endif
105 static void DetectLuaFree(DetectEngineCtx *, void *);
106 static int g_smtp_generic_list_id = 0;
107 
108 /**
109  * \brief Registration function for keyword: lua
110  */
111 void DetectLuaRegister(void)
112 {
113  sigmatch_table[DETECT_LUA].name = "lua";
114  sigmatch_table[DETECT_LUA].alias = "luajit";
115  sigmatch_table[DETECT_LUA].desc = "match via a lua script";
116  sigmatch_table[DETECT_LUA].url = "/rules/rule-lua-scripting.html";
117  sigmatch_table[DETECT_LUA].Match = DetectLuaMatch;
118  sigmatch_table[DETECT_LUA].AppLayerTxMatch = DetectLuaAppTxMatch;
119  sigmatch_table[DETECT_LUA].Setup = DetectLuaSetup;
120  sigmatch_table[DETECT_LUA].Free = DetectLuaFree;
121 #ifdef UNITTESTS
122  sigmatch_table[DETECT_LUA].RegisterTests = DetectLuaRegisterTests;
123 #endif
124  g_smtp_generic_list_id = DetectBufferTypeRegister("smtp_generic");
125 
130 
131  SCLogDebug("registering lua rule option");
132  return;
133 }
134 
135 #define DATATYPE_PACKET BIT_U32(0)
136 #define DATATYPE_PAYLOAD BIT_U32(1)
137 #define DATATYPE_STREAM BIT_U32(2)
138 
139 #define DATATYPE_HTTP_URI BIT_U32(3)
140 #define DATATYPE_HTTP_URI_RAW BIT_U32(4)
141 
142 #define DATATYPE_HTTP_REQUEST_HEADERS BIT_U32(5)
143 #define DATATYPE_HTTP_REQUEST_HEADERS_RAW BIT_U32(6)
144 #define DATATYPE_HTTP_REQUEST_COOKIE BIT_U32(7)
145 #define DATATYPE_HTTP_REQUEST_UA BIT_U32(8)
146 
147 #define DATATYPE_HTTP_REQUEST_LINE BIT_U32(9)
148 #define DATATYPE_HTTP_REQUEST_BODY BIT_U32(10)
149 
150 #define DATATYPE_HTTP_RESPONSE_COOKIE BIT_U32(11)
151 #define DATATYPE_HTTP_RESPONSE_BODY BIT_U32(12)
152 
153 #define DATATYPE_HTTP_RESPONSE_HEADERS BIT_U32(13)
154 #define DATATYPE_HTTP_RESPONSE_HEADERS_RAW BIT_U32(14)
155 
156 #define DATATYPE_DNS_RRNAME BIT_U32(15)
157 #define DATATYPE_DNS_REQUEST BIT_U32(16)
158 #define DATATYPE_DNS_RESPONSE BIT_U32(17)
159 
160 #define DATATYPE_TLS BIT_U32(18)
161 #define DATATYPE_SSH BIT_U32(19)
162 #define DATATYPE_SMTP BIT_U32(20)
163 
164 #define DATATYPE_DNP3 BIT_U32(21)
165 
166 #define DATATYPE_BUFFER BIT_U32(22)
167 
168 #if 0
169 /** \brief dump stack from lua state to screen */
170 void LuaDumpStack(lua_State *state)
171 {
172  int size = lua_gettop(state);
173  int i;
174 
175  for (i = 1; i <= size; i++) {
176  int type = lua_type(state, i);
177  printf("Stack size=%d, level=%d, type=%d, ", size, i, type);
178 
179  switch (type) {
180  case LUA_TFUNCTION:
181  printf("function %s", lua_tostring(state, i) ? "true" : "false");
182  break;
183  case LUA_TBOOLEAN:
184  printf("bool %s", lua_toboolean(state, i) ? "true" : "false");
185  break;
186  case LUA_TNUMBER:
187  printf("number %g", lua_tonumber(state, i));
188  break;
189  case LUA_TSTRING:
190  printf("string `%s'", lua_tostring(state, i));
191  break;
192  case LUA_TTABLE:
193  printf("table `%s'", lua_tostring(state, i));
194  break;
195  default:
196  printf("other %s", lua_typename(state, type));
197  break;
198 
199  }
200  printf("\n");
201  }
202 }
203 #endif
204 
206  const Signature *s, const SigMatchData *smd,
207  const uint8_t *buffer, uint32_t buffer_len, uint32_t offset,
208  Flow *f)
209 {
210  SCEnter();
211  int ret = 0;
212 
213  if (buffer == NULL || buffer_len == 0)
214  SCReturnInt(0);
215 
216  DetectLuaData *lua = (DetectLuaData *)smd->ctx;
217  if (lua == NULL)
218  SCReturnInt(0);
219 
220  DetectLuaThreadData *tlua = (DetectLuaThreadData *)DetectThreadCtxGetKeywordThreadCtx(det_ctx, lua->thread_ctx_id);
221  if (tlua == NULL)
222  SCReturnInt(0);
223 
224  LuaExtensionsMatchSetup(tlua->luastate, lua, det_ctx, f, /* no packet in the ctx */ NULL, s, 0);
225 
226  /* prepare data to pass to script */
227  lua_getglobal(tlua->luastate, "match");
228  lua_newtable(tlua->luastate); /* stack at -1 */
229 
230  lua_pushliteral (tlua->luastate, "offset"); /* stack at -2 */
231  lua_pushnumber (tlua->luastate, (int)(offset + 1));
232  lua_settable(tlua->luastate, -3);
233 
234  lua_pushstring (tlua->luastate, lua->buffername); /* stack at -2 */
235  LuaPushStringBuffer(tlua->luastate, (const uint8_t *)buffer, (size_t)buffer_len);
236  lua_settable(tlua->luastate, -3);
237 
238  int retval = lua_pcall(tlua->luastate, 1, 1, 0);
239  if (retval != 0) {
240  SCLogInfo("failed to run script: %s", lua_tostring(tlua->luastate, -1));
241  }
242 
243  /* process returns from script */
244  if (lua_gettop(tlua->luastate) > 0) {
245  /* script returns a number (return 1 or return 0) */
246  if (lua_type(tlua->luastate, 1) == LUA_TNUMBER) {
247  double script_ret = lua_tonumber(tlua->luastate, 1);
248  SCLogDebug("script_ret %f", script_ret);
249  lua_pop(tlua->luastate, 1);
250 
251  if (script_ret == 1.0)
252  ret = 1;
253 
254  /* script returns a table */
255  } else if (lua_type(tlua->luastate, 1) == LUA_TTABLE) {
256  lua_pushnil(tlua->luastate);
257  const char *k, *v;
258  while (lua_next(tlua->luastate, -2)) {
259  v = lua_tostring(tlua->luastate, -1);
260  lua_pop(tlua->luastate, 1);
261  k = lua_tostring(tlua->luastate, -1);
262 
263  if (!k || !v)
264  continue;
265 
266  SCLogDebug("k='%s', v='%s'", k, v);
267 
268  if (strcmp(k, "retval") == 0) {
269  int val;
270  if (StringParseInt32(&val, 10, 0, (const char *)v) < 0) {
271  SCLogError(SC_ERR_INVALID_VALUE, "Invalid value "
272  "for \"retval\" from LUA return table: '%s'", v);
273  ret = 0;
274  }
275  else if (val == 1) {
276  ret = 1;
277  }
278  } else {
279  /* set flow var? */
280  }
281  }
282 
283  /* pop the table */
284  lua_pop(tlua->luastate, 1);
285  }
286  } else {
287  SCLogDebug("no stack");
288  }
289 
290  /* clear the stack */
291  while (lua_gettop(tlua->luastate) > 0) {
292  lua_pop(tlua->luastate, 1);
293  }
294 
295  if (lua->negated) {
296  if (ret == 1)
297  ret = 0;
298  else
299  ret = 1;
300  }
301 
302  SCReturnInt(ret);
303 }
304 
305 /**
306  * \brief match the specified lua script
307  *
308  * \param t thread local vars
309  * \param det_ctx pattern matcher thread local data
310  * \param p packet
311  * \param s signature being inspected
312  * \param m sigmatch that we will cast into DetectLuaData
313  *
314  * \retval 0 no match
315  * \retval 1 match
316  */
317 static int DetectLuaMatch (DetectEngineThreadCtx *det_ctx,
318  Packet *p, const Signature *s, const SigMatchCtx *ctx)
319 {
320  SCEnter();
321  int ret = 0;
322  DetectLuaData *lua = (DetectLuaData *)ctx;
323  if (lua == NULL)
324  SCReturnInt(0);
325 
326  DetectLuaThreadData *tlua = (DetectLuaThreadData *)DetectThreadCtxGetKeywordThreadCtx(det_ctx, lua->thread_ctx_id);
327  if (tlua == NULL)
328  SCReturnInt(0);
329 
330  /* setup extension data for use in lua c functions */
331  uint8_t flags = 0;
332  if (p->flowflags & FLOW_PKT_TOSERVER)
333  flags = STREAM_TOSERVER;
334  else if (p->flowflags & FLOW_PKT_TOCLIENT)
335  flags = STREAM_TOCLIENT;
336 
337  LuaStateSetThreadVars(tlua->luastate, det_ctx->tv);
338 
339  LuaExtensionsMatchSetup(tlua->luastate, lua, det_ctx, p->flow, p, s, flags);
340 
341  if ((tlua->flags & DATATYPE_PAYLOAD) && p->payload_len == 0)
342  SCReturnInt(0);
343  if ((tlua->flags & DATATYPE_PACKET) && GET_PKT_LEN(p) == 0)
344  SCReturnInt(0);
345  if (tlua->alproto != ALPROTO_UNKNOWN) {
346  if (p->flow == NULL)
347  SCReturnInt(0);
348 
349  AppProto alproto = p->flow->alproto;
350  if (tlua->alproto != alproto)
351  SCReturnInt(0);
352  }
353 
354  lua_getglobal(tlua->luastate, "match");
355  lua_newtable(tlua->luastate); /* stack at -1 */
356 
357  if ((tlua->flags & DATATYPE_PAYLOAD) && p->payload_len) {
358  lua_pushliteral(tlua->luastate, "payload"); /* stack at -2 */
359  LuaPushStringBuffer (tlua->luastate, (const uint8_t *)p->payload, (size_t)p->payload_len); /* stack at -3 */
360  lua_settable(tlua->luastate, -3);
361  }
362  if ((tlua->flags & DATATYPE_PACKET) && GET_PKT_LEN(p)) {
363  lua_pushliteral(tlua->luastate, "packet"); /* stack at -2 */
364  LuaPushStringBuffer (tlua->luastate, (const uint8_t *)GET_PKT_DATA(p), (size_t)GET_PKT_LEN(p)); /* stack at -3 */
365  lua_settable(tlua->luastate, -3);
366  }
367  if (tlua->alproto == ALPROTO_HTTP1) {
368  HtpState *htp_state = p->flow->alstate;
369  if (htp_state != NULL && htp_state->connp != NULL) {
370  htp_tx_t *tx = NULL;
372  STREAM_TOSERVER);
373  uint64_t total_txs= AppLayerParserGetTxCnt(p->flow, htp_state);
374  for ( ; idx < total_txs; idx++) {
375  tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, htp_state, idx);
376  if (tx == NULL)
377  continue;
378 
379  if ((tlua->flags & DATATYPE_HTTP_REQUEST_LINE) && tx->request_line != NULL &&
380  bstr_len(tx->request_line) > 0) {
381  lua_pushliteral(tlua->luastate, "http.request_line"); /* stack at -2 */
382  LuaPushStringBuffer(tlua->luastate,
383  (const uint8_t *)bstr_ptr(tx->request_line),
384  bstr_len(tx->request_line));
385  lua_settable(tlua->luastate, -3);
386  }
387  }
388  }
389  }
390 
391  int retval = lua_pcall(tlua->luastate, 1, 1, 0);
392  if (retval != 0) {
393  SCLogInfo("failed to run script: %s", lua_tostring(tlua->luastate, -1));
394  }
395 
396  /* process returns from script */
397  if (lua_gettop(tlua->luastate) > 0) {
398 
399  /* script returns a number (return 1 or return 0) */
400  if (lua_type(tlua->luastate, 1) == LUA_TNUMBER) {
401  double script_ret = lua_tonumber(tlua->luastate, 1);
402  SCLogDebug("script_ret %f", script_ret);
403  lua_pop(tlua->luastate, 1);
404 
405  if (script_ret == 1.0)
406  ret = 1;
407 
408  /* script returns a table */
409  } else if (lua_type(tlua->luastate, 1) == LUA_TTABLE) {
410  lua_pushnil(tlua->luastate);
411  const char *k, *v;
412  while (lua_next(tlua->luastate, -2)) {
413  v = lua_tostring(tlua->luastate, -1);
414  lua_pop(tlua->luastate, 1);
415  k = lua_tostring(tlua->luastate, -1);
416 
417  if (!k || !v)
418  continue;
419 
420  SCLogDebug("k='%s', v='%s'", k, v);
421 
422  if (strcmp(k, "retval") == 0) {
423  int val;
424  if (StringParseInt32(&val, 10, 0,
425  (const char *)v) < 0) {
426  SCLogError(SC_ERR_INVALID_VALUE, "Invalid value "
427  "for \"retval\" from LUA return table: '%s'", v);
428  ret = 0;
429  }
430  else if (val == 1) {
431  ret = 1;
432  }
433  } else {
434  /* set flow var? */
435  }
436  }
437 
438  /* pop the table */
439  lua_pop(tlua->luastate, 1);
440  }
441  }
442  while (lua_gettop(tlua->luastate) > 0) {
443  lua_pop(tlua->luastate, 1);
444  }
445 
446  if (lua->negated) {
447  if (ret == 1)
448  ret = 0;
449  else
450  ret = 1;
451  }
452 
453  SCReturnInt(ret);
454 }
455 
456 static int DetectLuaAppMatchCommon (DetectEngineThreadCtx *det_ctx,
457  Flow *f, uint8_t flags, void *state,
458  const Signature *s, const SigMatchCtx *ctx)
459 {
460  SCEnter();
461  int ret = 0;
462  DetectLuaData *lua = (DetectLuaData *)ctx;
463  if (lua == NULL)
464  SCReturnInt(0);
465 
466  DetectLuaThreadData *tlua = (DetectLuaThreadData *)DetectThreadCtxGetKeywordThreadCtx(det_ctx, lua->thread_ctx_id);
467  if (tlua == NULL)
468  SCReturnInt(0);
469 
470  /* setup extension data for use in lua c functions */
471  LuaExtensionsMatchSetup(tlua->luastate, lua, det_ctx, f, NULL, s, flags);
472 
473  if (tlua->alproto != ALPROTO_UNKNOWN) {
474  int alproto = f->alproto;
475  if (tlua->alproto != alproto)
476  SCReturnInt(0);
477  }
478 
479  lua_getglobal(tlua->luastate, "match");
480  lua_newtable(tlua->luastate); /* stack at -1 */
481 
482  if (tlua->alproto == ALPROTO_HTTP1) {
483  HtpState *htp_state = state;
484  if (htp_state != NULL && htp_state->connp != NULL) {
485  htp_tx_t *tx = NULL;
486  tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, htp_state, det_ctx->tx_id);
487  if (tx != NULL) {
488  if ((tlua->flags & DATATYPE_HTTP_REQUEST_LINE) && tx->request_line != NULL &&
489  bstr_len(tx->request_line) > 0) {
490  lua_pushliteral(tlua->luastate, "http.request_line"); /* stack at -2 */
491  LuaPushStringBuffer(tlua->luastate,
492  (const uint8_t *)bstr_ptr(tx->request_line),
493  bstr_len(tx->request_line));
494  lua_settable(tlua->luastate, -3);
495  }
496  }
497  }
498  }
499 
500  int retval = lua_pcall(tlua->luastate, 1, 1, 0);
501  if (retval != 0) {
502  SCLogInfo("failed to run script: %s", lua_tostring(tlua->luastate, -1));
503  }
504 
505  /* process returns from script */
506  if (lua_gettop(tlua->luastate) > 0) {
507 
508  /* script returns a number (return 1 or return 0) */
509  if (lua_type(tlua->luastate, 1) == LUA_TNUMBER) {
510  double script_ret = lua_tonumber(tlua->luastate, 1);
511  SCLogDebug("script_ret %f", script_ret);
512  lua_pop(tlua->luastate, 1);
513 
514  if (script_ret == 1.0)
515  ret = 1;
516 
517  /* script returns a table */
518  } else if (lua_type(tlua->luastate, 1) == LUA_TTABLE) {
519  lua_pushnil(tlua->luastate);
520  const char *k, *v;
521  while (lua_next(tlua->luastate, -2)) {
522  v = lua_tostring(tlua->luastate, -1);
523  lua_pop(tlua->luastate, 1);
524  k = lua_tostring(tlua->luastate, -1);
525 
526  if (!k || !v)
527  continue;
528 
529  SCLogDebug("k='%s', v='%s'", k, v);
530 
531  if (strcmp(k, "retval") == 0) {
532  int val;
533  if (StringParseInt32(&val, 10, 0,
534  (const char *)v) < 0) {
535  SCLogError(SC_ERR_INVALID_VALUE, "Invalid value "
536  "for \"retval\" from LUA return table: '%s'", v);
537  ret = 0;
538  }
539  else if (val == 1) {
540  ret = 1;
541  }
542  } else {
543  /* set flow var? */
544  }
545  }
546 
547  /* pop the table */
548  lua_pop(tlua->luastate, 1);
549  }
550  }
551  while (lua_gettop(tlua->luastate) > 0) {
552  lua_pop(tlua->luastate, 1);
553  }
554 
555  if (lua->negated) {
556  if (ret == 1)
557  ret = 0;
558  else
559  ret = 1;
560  }
561 
562  SCReturnInt(ret);
563 }
564 
565 /**
566  * \brief match the specified lua script in a list with a tx
567  *
568  * \param t thread local vars
569  * \param det_ctx pattern matcher thread local data
570  * \param s signature being inspected
571  * \param m sigmatch that we will cast into DetectLuaData
572  *
573  * \retval 0 no match
574  * \retval 1 match
575  */
576 static int DetectLuaAppTxMatch (DetectEngineThreadCtx *det_ctx,
577  Flow *f, uint8_t flags,
578  void *state, void *txv, const Signature *s,
579  const SigMatchCtx *ctx)
580 {
581  return DetectLuaAppMatchCommon(det_ctx, f, flags, state, s, ctx);
582 }
583 
584 #ifdef UNITTESTS
585 /* if this ptr is set the lua setup functions will use this buffer as the
586  * lua script instead of calling luaL_loadfile on the filename supplied. */
587 static const char *ut_script = NULL;
588 #endif
589 
590 static void *DetectLuaThreadInit(void *data)
591 {
592  int status;
593  DetectLuaData *lua = (DetectLuaData *)data;
594  BUG_ON(lua == NULL);
595 
596  DetectLuaThreadData *t = SCMalloc(sizeof(DetectLuaThreadData));
597  if (unlikely(t == NULL)) {
598  SCLogError(SC_ERR_LUA_ERROR, "couldn't alloc ctx memory");
599  return NULL;
600  }
601  memset(t, 0x00, sizeof(DetectLuaThreadData));
602 
603  t->alproto = lua->alproto;
604  t->flags = lua->flags;
605 
606  t->luastate = LuaGetState();
607  if (t->luastate == NULL) {
608  SCLogError(SC_ERR_LUA_ERROR, "luastate pool depleted");
609  goto error;
610  }
611 
612  luaL_openlibs(t->luastate);
613 
614  LuaRegisterExtensions(t->luastate);
615 
616  lua_pushinteger(t->luastate, (lua_Integer)(lua->sid));
617  lua_setglobal(t->luastate, "SCRuleSid");
618  lua_pushinteger(t->luastate, (lua_Integer)(lua->rev));
619  lua_setglobal(t->luastate, "SCRuleRev");
620  lua_pushinteger(t->luastate, (lua_Integer)(lua->gid));
621  lua_setglobal(t->luastate, "SCRuleGid");
622 
623  /* hackish, needed to allow unittests to pass buffers as scripts instead of files */
624 #ifdef UNITTESTS
625  if (ut_script != NULL) {
626  status = luaL_loadbuffer(t->luastate, ut_script, strlen(ut_script), "unittest");
627  if (status) {
628  SCLogError(SC_ERR_LUA_ERROR, "couldn't load file: %s", lua_tostring(t->luastate, -1));
629  goto error;
630  }
631  } else {
632 #endif
633  status = luaL_loadfile(t->luastate, lua->filename);
634  if (status) {
635  SCLogError(SC_ERR_LUA_ERROR, "couldn't load file: %s", lua_tostring(t->luastate, -1));
636  goto error;
637  }
638 #ifdef UNITTESTS
639  }
640 #endif
641 
642  /* prime the script (or something) */
643  if (lua_pcall(t->luastate, 0, 0, 0) != 0) {
644  SCLogError(SC_ERR_LUA_ERROR, "couldn't prime file: %s", lua_tostring(t->luastate, -1));
645  goto error;
646  }
647 
648  return (void *)t;
649 
650 error:
651  if (t->luastate != NULL)
652  LuaReturnState(t->luastate);
653  SCFree(t);
654  return NULL;
655 }
656 
657 static void DetectLuaThreadFree(void *ctx)
658 {
659  if (ctx != NULL) {
660  DetectLuaThreadData *t = (DetectLuaThreadData *)ctx;
661  if (t->luastate != NULL)
662  LuaReturnState(t->luastate);
663  SCFree(t);
664  }
665 }
666 
667 /**
668  * \brief Parse the lua keyword
669  *
670  * \param de_ctx Pointer to the detection engine context
671  * \param str Pointer to the user provided option
672  *
673  * \retval lua pointer to DetectLuaData on success
674  * \retval NULL on failure
675  */
676 static DetectLuaData *DetectLuaParse (DetectEngineCtx *de_ctx, const char *str)
677 {
678  DetectLuaData *lua = NULL;
679 
680  /* We have a correct lua option */
681  lua = SCMalloc(sizeof(DetectLuaData));
682  if (unlikely(lua == NULL))
683  goto error;
684 
685  memset(lua, 0x00, sizeof(DetectLuaData));
686 
687  if (strlen(str) && str[0] == '!') {
688  lua->negated = 1;
689  str++;
690  }
691 
692  /* get full filename */
693  lua->filename = DetectLoadCompleteSigPath(de_ctx, str);
694  if (lua->filename == NULL) {
695  goto error;
696  }
697 
698  return lua;
699 
700 error:
701  if (lua != NULL)
702  DetectLuaFree(de_ctx, lua);
703  return NULL;
704 }
705 
706 static int DetectLuaSetupPrime(DetectEngineCtx *de_ctx, DetectLuaData *ld, const Signature *s)
707 {
708  int status;
709 
710  lua_State *luastate = luaL_newstate();
711  if (luastate == NULL)
712  return -1;
713  luaL_openlibs(luastate);
714 
715  /* hackish, needed to allow unittests to pass buffers as scripts instead of files */
716 #ifdef UNITTESTS
717  if (ut_script != NULL) {
718  status = luaL_loadbuffer(luastate, ut_script, strlen(ut_script), "unittest");
719  if (status) {
720  SCLogError(SC_ERR_LUA_ERROR, "couldn't load file: %s", lua_tostring(luastate, -1));
721  goto error;
722  }
723  } else {
724 #endif
725  status = luaL_loadfile(luastate, ld->filename);
726  if (status) {
727  SCLogError(SC_ERR_LUA_ERROR, "couldn't load file: %s", lua_tostring(luastate, -1));
728  goto error;
729  }
730 #ifdef UNITTESTS
731  }
732 #endif
733 
734  /* prime the script (or something) */
735  if (lua_pcall(luastate, 0, 0, 0) != 0) {
736  SCLogError(SC_ERR_LUA_ERROR, "couldn't prime file: %s", lua_tostring(luastate, -1));
737  goto error;
738  }
739 
740  lua_getglobal(luastate, "init");
741  if (lua_type(luastate, -1) != LUA_TFUNCTION) {
742  SCLogError(SC_ERR_LUA_ERROR, "no init function in script");
743  goto error;
744  }
745 
746  lua_newtable(luastate); /* stack at -1 */
747  if (lua_gettop(luastate) == 0 || lua_type(luastate, 2) != LUA_TTABLE) {
748  SCLogError(SC_ERR_LUA_ERROR, "no table setup");
749  goto error;
750  }
751 
752  lua_pushliteral(luastate, "script_api_ver"); /* stack at -2 */
753  lua_pushnumber (luastate, 1); /* stack at -3 */
754  lua_settable(luastate, -3);
755 
756  if (lua_pcall(luastate, 1, 1, 0) != 0) {
757  SCLogError(SC_ERR_LUA_ERROR, "couldn't run script 'init' function: %s", lua_tostring(luastate, -1));
758  goto error;
759  }
760 
761  /* process returns from script */
762  if (lua_gettop(luastate) == 0) {
763  SCLogError(SC_ERR_LUA_ERROR, "init function in script should return table, nothing returned");
764  goto error;
765  }
766  if (lua_type(luastate, 1) != LUA_TTABLE) {
767  SCLogError(SC_ERR_LUA_ERROR, "init function in script should return table, returned is not table");
768  goto error;
769  }
770 
771  lua_pushnil(luastate);
772  const char *k, *v;
773  while (lua_next(luastate, -2)) {
774  k = lua_tostring(luastate, -2);
775  if (k == NULL)
776  continue;
777 
778  /* handle flowvar and bytes separately as they have a table as value */
779  if (strcmp(k, "flowvar") == 0) {
780  if (lua_istable(luastate, -1)) {
781  lua_pushnil(luastate);
782  while (lua_next(luastate, -2) != 0) {
783  /* value at -1, key is at -2 which we ignore */
784  const char *value = lua_tostring(luastate, -1);
785  SCLogDebug("value %s", value);
786  /* removes 'value'; keeps 'key' for next iteration */
787  lua_pop(luastate, 1);
788 
789  if (ld->flowvars == DETECT_LUAJIT_MAX_FLOWVARS) {
790  SCLogError(SC_ERR_LUA_ERROR, "too many flowvars registered");
791  goto error;
792  }
793 
794  uint32_t idx = VarNameStoreSetupAdd((char *)value, VAR_TYPE_FLOW_VAR);
795  ld->flowvar[ld->flowvars++] = idx;
796  SCLogDebug("script uses flowvar %u with script id %u", idx, ld->flowvars - 1);
797  }
798  }
799  lua_pop(luastate, 1);
800  continue;
801  } else if (strcmp(k, "flowint") == 0) {
802  if (lua_istable(luastate, -1)) {
803  lua_pushnil(luastate);
804  while (lua_next(luastate, -2) != 0) {
805  /* value at -1, key is at -2 which we ignore */
806  const char *value = lua_tostring(luastate, -1);
807  SCLogDebug("value %s", value);
808  /* removes 'value'; keeps 'key' for next iteration */
809  lua_pop(luastate, 1);
810 
811  if (ld->flowints == DETECT_LUAJIT_MAX_FLOWINTS) {
812  SCLogError(SC_ERR_LUA_ERROR, "too many flowints registered");
813  goto error;
814  }
815 
816  uint32_t idx = VarNameStoreSetupAdd((char *)value, VAR_TYPE_FLOW_INT);
817  ld->flowint[ld->flowints++] = idx;
818  SCLogDebug("script uses flowint %u with script id %u", idx, ld->flowints - 1);
819  }
820  }
821  lua_pop(luastate, 1);
822  continue;
823  } else if (strcmp(k, "bytevar") == 0) {
824  if (lua_istable(luastate, -1)) {
825  lua_pushnil(luastate);
826  while (lua_next(luastate, -2) != 0) {
827  /* value at -1, key is at -2 which we ignore */
828  const char *value = lua_tostring(luastate, -1);
829  SCLogDebug("value %s", value);
830  /* removes 'value'; keeps 'key' for next iteration */
831  lua_pop(luastate, 1);
832 
833  if (ld->bytevars == DETECT_LUAJIT_MAX_BYTEVARS) {
834  SCLogError(SC_ERR_LUA_ERROR, "too many bytevars registered");
835  goto error;
836  }
837 
839  if (!DetectByteRetrieveSMVar(value, s, &idx)) {
841  "Unknown byte_extract or byte_math var "
842  "requested by lua script - %s",
843  value);
844  goto error;
845  }
846  ld->bytevar[ld->bytevars++] = idx;
847  SCLogDebug("script uses bytevar %u with script id %u", idx, ld->bytevars - 1);
848  }
849  }
850  lua_pop(luastate, 1);
851  continue;
852  }
853 
854  v = lua_tostring(luastate, -1);
855  lua_pop(luastate, 1);
856  if (v == NULL)
857  continue;
858 
859  SCLogDebug("k='%s', v='%s'", k, v);
860  if (strcmp(k, "packet") == 0 && strcmp(v, "true") == 0) {
861  ld->flags |= DATATYPE_PACKET;
862  } else if (strcmp(k, "payload") == 0 && strcmp(v, "true") == 0) {
863  ld->flags |= DATATYPE_PAYLOAD;
864  } else if (strcmp(k, "buffer") == 0 && strcmp(v, "true") == 0) {
865  ld->flags |= DATATYPE_BUFFER;
866 
867  ld->buffername = SCStrdup("buffer");
868  if (ld->buffername == NULL) {
869  SCLogError(SC_ERR_LUA_ERROR, "alloc error");
870  goto error;
871  }
872  } else if (strcmp(k, "stream") == 0 && strcmp(v, "true") == 0) {
873  ld->flags |= DATATYPE_STREAM;
874 
875  ld->buffername = SCStrdup("stream");
876  if (ld->buffername == NULL) {
877  SCLogError(SC_ERR_LUA_ERROR, "alloc error");
878  goto error;
879  }
880 
881  } else if (strncmp(k, "http", 4) == 0 && strcmp(v, "true") == 0) {
882  if (ld->alproto != ALPROTO_UNKNOWN && ld->alproto != ALPROTO_HTTP1) {
883  SCLogError(SC_ERR_LUA_ERROR, "can just inspect script against one app layer proto like HTTP at a time");
884  goto error;
885  }
886  if (ld->flags != 0) {
887  SCLogError(SC_ERR_LUA_ERROR, "when inspecting HTTP buffers only a single buffer can be inspected");
888  goto error;
889  }
890 
891  /* http types */
892  ld->alproto = ALPROTO_HTTP1;
893 
894  if (strcmp(k, "http.uri") == 0)
895  ld->flags |= DATATYPE_HTTP_URI;
896 
897  else if (strcmp(k, "http.uri.raw") == 0)
898  ld->flags |= DATATYPE_HTTP_URI_RAW;
899 
900  else if (strcmp(k, "http.request_line") == 0)
901  ld->flags |= DATATYPE_HTTP_REQUEST_LINE;
902 
903  else if (strcmp(k, "http.request_headers") == 0)
904  ld->flags |= DATATYPE_HTTP_REQUEST_HEADERS;
905 
906  else if (strcmp(k, "http.request_headers.raw") == 0)
907  ld->flags |= DATATYPE_HTTP_REQUEST_HEADERS_RAW;
908 
909  else if (strcmp(k, "http.request_cookie") == 0)
910  ld->flags |= DATATYPE_HTTP_REQUEST_COOKIE;
911 
912  else if (strcmp(k, "http.request_user_agent") == 0)
913  ld->flags |= DATATYPE_HTTP_REQUEST_UA;
914 
915  else if (strcmp(k, "http.request_body") == 0)
916  ld->flags |= DATATYPE_HTTP_REQUEST_BODY;
917 
918  else if (strcmp(k, "http.response_body") == 0)
919  ld->flags |= DATATYPE_HTTP_RESPONSE_BODY;
920 
921  else if (strcmp(k, "http.response_cookie") == 0)
922  ld->flags |= DATATYPE_HTTP_RESPONSE_COOKIE;
923 
924  else if (strcmp(k, "http.response_headers") == 0)
925  ld->flags |= DATATYPE_HTTP_RESPONSE_HEADERS;
926 
927  else if (strcmp(k, "http.response_headers.raw") == 0)
928  ld->flags |= DATATYPE_HTTP_RESPONSE_HEADERS_RAW;
929 
930  else {
931  SCLogError(SC_ERR_LUA_ERROR, "unsupported http data type %s", k);
932  goto error;
933  }
934 
935  ld->buffername = SCStrdup(k);
936  if (ld->buffername == NULL) {
937  SCLogError(SC_ERR_LUA_ERROR, "alloc error");
938  goto error;
939  }
940  } else if (strncmp(k, "dns", 3) == 0 && strcmp(v, "true") == 0) {
941 
942  ld->alproto = ALPROTO_DNS;
943 
944  if (strcmp(k, "dns.rrname") == 0)
945  ld->flags |= DATATYPE_DNS_RRNAME;
946  else if (strcmp(k, "dns.request") == 0)
947  ld->flags |= DATATYPE_DNS_REQUEST;
948  else if (strcmp(k, "dns.response") == 0)
949  ld->flags |= DATATYPE_DNS_RESPONSE;
950 
951  else {
952  SCLogError(SC_ERR_LUA_ERROR, "unsupported dns data type %s", k);
953  goto error;
954  }
955  ld->buffername = SCStrdup(k);
956  if (ld->buffername == NULL) {
957  SCLogError(SC_ERR_LUA_ERROR, "alloc error");
958  goto error;
959  }
960  } else if (strncmp(k, "tls", 3) == 0 && strcmp(v, "true") == 0) {
961 
962  ld->alproto = ALPROTO_TLS;
963 
964  ld->flags |= DATATYPE_TLS;
965 
966  } else if (strncmp(k, "ssh", 3) == 0 && strcmp(v, "true") == 0) {
967 
968  ld->alproto = ALPROTO_SSH;
969 
970  ld->flags |= DATATYPE_SSH;
971 
972  } else if (strncmp(k, "smtp", 4) == 0 && strcmp(v, "true") == 0) {
973 
974  ld->alproto = ALPROTO_SMTP;
975 
976  ld->flags |= DATATYPE_SMTP;
977 
978  } else if (strncmp(k, "dnp3", 4) == 0 && strcmp(v, "true") == 0) {
979 
980  ld->alproto = ALPROTO_DNP3;
981 
982  ld->flags |= DATATYPE_DNP3;
983 
984  } else {
985  SCLogError(SC_ERR_LUA_ERROR, "unsupported data type %s", k);
986  goto error;
987  }
988  }
989 
990  /* pop the table */
991  lua_pop(luastate, 1);
992  lua_close(luastate);
993  return 0;
994 error:
995  lua_close(luastate);
996  return -1;
997 }
998 
999 /**
1000  * \brief this function is used to parse lua options
1001  * \brief into the current signature
1002  *
1003  * \param de_ctx pointer to the Detection Engine Context
1004  * \param s pointer to the Current Signature
1005  * \param str pointer to the user provided "lua" option
1006  *
1007  * \retval 0 on Success
1008  * \retval -1 on Failure
1009  */
1010 static int DetectLuaSetup (DetectEngineCtx *de_ctx, Signature *s, const char *str)
1011 {
1012  DetectLuaData *lua = NULL;
1013  SigMatch *sm = NULL;
1014 
1015  lua = DetectLuaParse(de_ctx, str);
1016  if (lua == NULL)
1017  goto error;
1018 
1019  if (DetectLuaSetupPrime(de_ctx, lua, s) == -1) {
1020  goto error;
1021  }
1022 
1023  lua->thread_ctx_id = DetectRegisterThreadCtxFuncs(de_ctx, "lua",
1024  DetectLuaThreadInit, (void *)lua,
1025  DetectLuaThreadFree, 0);
1026  if (lua->thread_ctx_id == -1)
1027  goto error;
1028 
1029  if (lua->alproto != ALPROTO_UNKNOWN) {
1030  if (s->alproto != ALPROTO_UNKNOWN && !AppProtoEquals(s->alproto, lua->alproto)) {
1031  goto error;
1032  }
1033  s->alproto = lua->alproto;
1034  }
1035 
1036  /* Okay so far so good, lets get this into a SigMatch
1037  * and put it in the Signature. */
1038  sm = SigMatchAlloc();
1039  if (sm == NULL)
1040  goto error;
1041 
1042  sm->type = DETECT_LUA;
1043  sm->ctx = (SigMatchCtx *)lua;
1044 
1045  int list = -1;
1046  if (lua->alproto == ALPROTO_UNKNOWN) {
1047  if (lua->flags & DATATYPE_STREAM)
1048  list = DETECT_SM_LIST_PMATCH;
1049  else {
1050  if (lua->flags & DATATYPE_BUFFER) {
1051  if (DetectBufferGetActiveList(de_ctx, s) != -1) {
1052  list = s->init_data->list;
1053  } else {
1054  SCLogError(SC_ERR_LUA_ERROR, "Lua and sticky buffer failure");
1055  goto error;
1056  }
1057  } else
1058  list = DETECT_SM_LIST_MATCH;
1059  }
1060 
1061  } else if (lua->alproto == ALPROTO_HTTP1) {
1062  if (lua->flags & DATATYPE_HTTP_RESPONSE_BODY) {
1063  list = DetectBufferTypeGetByName("file_data");
1064  } else if (lua->flags & DATATYPE_HTTP_REQUEST_BODY) {
1065  list = DetectBufferTypeGetByName("http_client_body");
1066  } else if (lua->flags & DATATYPE_HTTP_URI) {
1067  list = DetectBufferTypeGetByName("http_uri");
1068  } else if (lua->flags & DATATYPE_HTTP_URI_RAW) {
1069  list = DetectBufferTypeGetByName("http_raw_uri");
1070  } else if (lua->flags & DATATYPE_HTTP_REQUEST_COOKIE ||
1071  lua->flags & DATATYPE_HTTP_RESPONSE_COOKIE)
1072  {
1073  list = DetectBufferTypeGetByName("http_cookie");
1074  } else if (lua->flags & DATATYPE_HTTP_REQUEST_UA) {
1075  list = DetectBufferTypeGetByName("http_user_agent");
1076  } else if (lua->flags & (DATATYPE_HTTP_REQUEST_HEADERS|DATATYPE_HTTP_RESPONSE_HEADERS)) {
1077  list = DetectBufferTypeGetByName("http_header");
1078  } else if (lua->flags & (DATATYPE_HTTP_REQUEST_HEADERS_RAW|DATATYPE_HTTP_RESPONSE_HEADERS_RAW)) {
1079  list = DetectBufferTypeGetByName("http_raw_header");
1080  } else {
1081  list = DetectBufferTypeGetByName("http_request_line");
1082  }
1083  } else if (lua->alproto == ALPROTO_DNS) {
1084  if (lua->flags & DATATYPE_DNS_RRNAME) {
1085  list = DetectBufferTypeGetByName("dns_query");
1086  } else if (lua->flags & DATATYPE_DNS_REQUEST) {
1087  list = DetectBufferTypeGetByName("dns_request");
1088  } else if (lua->flags & DATATYPE_DNS_RESPONSE) {
1089  list = DetectBufferTypeGetByName("dns_response");
1090  }
1091  } else if (lua->alproto == ALPROTO_TLS) {
1092  list = DetectBufferTypeGetByName("tls_generic");
1093  } else if (lua->alproto == ALPROTO_SSH) {
1094  list = DetectBufferTypeGetByName("ssh_banner");
1095  } else if (lua->alproto == ALPROTO_SMTP) {
1096  list = g_smtp_generic_list_id;
1097  } else if (lua->alproto == ALPROTO_DNP3) {
1098  list = DetectBufferTypeGetByName("dnp3");
1099  } else {
1100  SCLogError(SC_ERR_LUA_ERROR, "lua can't be used with protocol %s",
1101  AppLayerGetProtoName(lua->alproto));
1102  goto error;
1103  }
1104 
1105  if (list == -1) {
1106  SCLogError(SC_ERR_LUA_ERROR, "lua can't be used with protocol %s",
1107  AppLayerGetProtoName(lua->alproto));
1108  goto error;
1109  }
1110 
1111  SigMatchAppendSMToList(s, sm, list);
1112 
1113  return 0;
1114 
1115 error:
1116  if (lua != NULL)
1117  DetectLuaFree(de_ctx, lua);
1118  if (sm != NULL)
1119  SCFree(sm);
1120  return -1;
1121 }
1122 
1123 /** \brief post-sig parse function to set the sid,rev,gid into the
1124  * ctx, as this isn't available yet during parsing.
1125  */
1127 {
1128  int i;
1129  SigMatch *sm;
1130 
1131  for (i = 0; i < DETECT_SM_LIST_MAX; i++) {
1132  for (sm = s->init_data->smlists[i]; sm != NULL; sm = sm->next) {
1133  if (sm->type != DETECT_LUA)
1134  continue;
1135 
1136  DetectLuaData *ld = (DetectLuaData *)sm->ctx;
1137  ld->sid = s->id;
1138  ld->rev = s->rev;
1139  ld->gid = s->gid;
1140  }
1141  }
1142 }
1143 
1144 /**
1145  * \brief this function will free memory associated with DetectLuaData
1146  *
1147  * \param ptr pointer to DetectLuaData
1148  */
1149 static void DetectLuaFree(DetectEngineCtx *de_ctx, void *ptr)
1150 {
1151  if (ptr != NULL) {
1152  DetectLuaData *lua = (DetectLuaData *)ptr;
1153 
1154  if (lua->buffername)
1155  SCFree(lua->buffername);
1156  if (lua->filename)
1157  SCFree(lua->filename);
1158 
1160 
1161  SCFree(lua);
1162  }
1163 }
1164 
1165 #ifdef UNITTESTS
1166 #include "detect-engine-alert.h"
1167 
1168 /** \test http buffer */
1169 static int LuaMatchTest01(void)
1170 {
1171  const char script[] =
1172  "function init (args)\n"
1173  " local needs = {}\n"
1174  " needs[\"http.request_headers\"] = tostring(true)\n"
1175  " needs[\"flowvar\"] = {\"cnt\"}\n"
1176  " return needs\n"
1177  "end\n"
1178  "\n"
1179  "function match(args)\n"
1180  " a = ScFlowvarGet(0)\n"
1181  " if a then\n"
1182  " a = tostring(tonumber(a)+1)\n"
1183  " print (a)\n"
1184  " ScFlowvarSet(0, a, #a)\n"
1185  " else\n"
1186  " a = tostring(1)\n"
1187  " print (a)\n"
1188  " ScFlowvarSet(0, a, #a)\n"
1189  " end\n"
1190  " \n"
1191  " print (\"pre check: \" .. (a))\n"
1192  " if tonumber(a) == 2 then\n"
1193  " print \"match\"\n"
1194  " return 1\n"
1195  " end\n"
1196  " return 0\n"
1197  "end\n"
1198  "return 0\n";
1199  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1200  int result = 0;
1201  uint8_t httpbuf1[] =
1202  "POST / HTTP/1.1\r\n"
1203  "Host: www.emergingthreats.net\r\n\r\n";
1204  uint8_t httpbuf2[] =
1205  "POST / HTTP/1.1\r\n"
1206  "Host: www.openinfosecfoundation.org\r\n\r\n";
1207  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1208  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1209  TcpSession ssn;
1210  Packet *p1 = NULL;
1211  Packet *p2 = NULL;
1212  Flow f;
1213  Signature *s = NULL;
1214  ThreadVars th_v;
1215  DetectEngineThreadCtx *det_ctx;
1216 
1218 
1219  ut_script = script;
1220 
1221  memset(&th_v, 0, sizeof(th_v));
1222  memset(&f, 0, sizeof(f));
1223  memset(&ssn, 0, sizeof(ssn));
1224 
1225  p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1226  p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1227 
1228  FLOW_INITIALIZE(&f);
1229  f.protoctx = (void *)&ssn;
1230  f.proto = IPPROTO_TCP;
1231  f.flags |= FLOW_IPV4;
1232  f.alproto = ALPROTO_HTTP1;
1233 
1234  p1->flow = &f;
1238  p2->flow = &f;
1242 
1243  StreamTcpInitConfig(true);
1244 
1246  if (de_ctx == NULL) {
1247  goto end;
1248  }
1249  de_ctx->flags |= DE_QUIET;
1250 
1251  s = DetectEngineAppendSig(de_ctx, sig);
1252  if (s == NULL) {
1253  printf("sig parse failed: ");
1254  goto end;
1255  }
1256 
1258  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1259 
1260  int r = AppLayerParserParse(
1261  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
1262  if (r != 0) {
1263  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1264  goto end;
1265  }
1266  HtpState *http_state = f.alstate;
1267  if (http_state == NULL) {
1268  printf("no http state: ");
1269  goto end;
1270  }
1271 
1272  /* do detect for p1 */
1273  SCLogDebug("inspecting p1");
1274  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1275 
1276  if ((PacketAlertCheck(p1, 1))) {
1277  printf("sid 1 didn't match on p1 but should have: ");
1278  goto end;
1279  }
1280 
1281  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1282  if (r != 0) {
1283  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
1284  goto end;
1285  }
1286  /* do detect for p2 */
1287  SCLogDebug("inspecting p2");
1288  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1289 
1290  if (!(PacketAlertCheck(p2, 1))) {
1291  printf("sid 1 didn't match on p2 but should have: ");
1292  goto end;
1293  }
1294 
1295  FlowVar *fv = FlowVarGet(&f, 1);
1296  if (fv == NULL) {
1297  printf("no flowvar: ");
1298  goto end;
1299  }
1300 
1301  if (fv->data.fv_str.value_len != 1) {
1302  printf("%u != %u: ", fv->data.fv_str.value_len, 1);
1303  goto end;
1304  }
1305 
1306  if (memcmp(fv->data.fv_str.value, "2", 1) != 0) {
1307  PrintRawDataFp(stdout, fv->data.fv_str.value, fv->data.fv_str.value_len);
1308 
1309  printf("buffer mismatch: ");
1310  goto end;
1311  }
1312 
1313  result = 1;
1314 end:
1315  if (alp_tctx != NULL)
1317  if (de_ctx != NULL)
1319 
1320  StreamTcpFreeConfig(true);
1321  FLOW_DESTROY(&f);
1322  UTHFreePackets(&p1, 1);
1323  UTHFreePackets(&p2, 1);
1324  return result;
1325 }
1326 
1327 static int LuaMatchTest01a(void)
1328 {
1329  const char script[] = "function init (args)\n"
1330  " local needs = {}\n"
1331  " needs[\"http.request_headers\"] = tostring(true)\n"
1332  " needs[\"flowvar\"] = {\"cnt\"}\n"
1333  " return needs\n"
1334  "end\n"
1335  "\n"
1336  "function match(args)\n"
1337  " a = SCFlowvarGet(0)\n"
1338  " if a then\n"
1339  " a = tostring(tonumber(a)+1)\n"
1340  " print (a)\n"
1341  " SCFlowvarSet(0, a, #a)\n"
1342  " else\n"
1343  " a = tostring(1)\n"
1344  " print (a)\n"
1345  " SCFlowvarSet(0, a, #a)\n"
1346  " end\n"
1347  " \n"
1348  " print (\"pre check: \" .. (a))\n"
1349  " if tonumber(a) == 2 then\n"
1350  " print \"match\"\n"
1351  " return 1\n"
1352  " end\n"
1353  " return 0\n"
1354  "end\n"
1355  "return 0\n";
1356  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1357  int result = 0;
1358  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1359  "Host: www.emergingthreats.net\r\n\r\n";
1360  uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1361  "Host: www.openinfosecfoundation.org\r\n\r\n";
1362  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1363  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1364  TcpSession ssn;
1365  Packet *p1 = NULL;
1366  Packet *p2 = NULL;
1367  Flow f;
1368  Signature *s = NULL;
1369  ThreadVars th_v;
1370  DetectEngineThreadCtx *det_ctx;
1371 
1373 
1374  ut_script = script;
1375 
1376  memset(&th_v, 0, sizeof(th_v));
1377  memset(&f, 0, sizeof(f));
1378  memset(&ssn, 0, sizeof(ssn));
1379 
1380  p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1381  p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1382 
1383  FLOW_INITIALIZE(&f);
1384  f.protoctx = (void *)&ssn;
1385  f.proto = IPPROTO_TCP;
1386  f.flags |= FLOW_IPV4;
1387  f.alproto = ALPROTO_HTTP1;
1388 
1389  p1->flow = &f;
1393  p2->flow = &f;
1397 
1398  StreamTcpInitConfig(true);
1399 
1401  if (de_ctx == NULL) {
1402  goto end;
1403  }
1404  de_ctx->flags |= DE_QUIET;
1405 
1406  s = DetectEngineAppendSig(de_ctx, sig);
1407  if (s == NULL) {
1408  printf("sig parse failed: ");
1409  goto end;
1410  }
1411 
1413  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1414 
1415  int r = AppLayerParserParse(
1416  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
1417  if (r != 0) {
1418  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1419  goto end;
1420  }
1421  HtpState *http_state = f.alstate;
1422  if (http_state == NULL) {
1423  printf("no http state: ");
1424  goto end;
1425  }
1426 
1427  /* do detect for p1 */
1428  SCLogDebug("inspecting p1");
1429  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1430 
1431  if ((PacketAlertCheck(p1, 1))) {
1432  printf("sid 1 didn't match on p1 but should have: ");
1433  goto end;
1434  }
1435 
1436  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1437  if (r != 0) {
1438  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
1439  goto end;
1440  }
1441  /* do detect for p2 */
1442  SCLogDebug("inspecting p2");
1443  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1444 
1445  if (!(PacketAlertCheck(p2, 1))) {
1446  printf("sid 1 didn't match on p2 but should have: ");
1447  goto end;
1448  }
1449 
1450  FlowVar *fv = FlowVarGet(&f, 1);
1451  if (fv == NULL) {
1452  printf("no flowvar: ");
1453  goto end;
1454  }
1455 
1456  if (fv->data.fv_str.value_len != 1) {
1457  printf("%u != %u: ", fv->data.fv_str.value_len, 1);
1458  goto end;
1459  }
1460 
1461  if (memcmp(fv->data.fv_str.value, "2", 1) != 0) {
1462  PrintRawDataFp(stdout, fv->data.fv_str.value, fv->data.fv_str.value_len);
1463 
1464  printf("buffer mismatch: ");
1465  goto end;
1466  }
1467 
1468  result = 1;
1469 end:
1470  if (alp_tctx != NULL)
1472  if (de_ctx != NULL)
1474 
1475  StreamTcpFreeConfig(true);
1476  FLOW_DESTROY(&f);
1477  UTHFreePackets(&p1, 1);
1478  UTHFreePackets(&p2, 1);
1479  return result;
1480 }
1481 
1482 /** \test payload buffer */
1483 static int LuaMatchTest02(void)
1484 {
1485  const char script[] = "function init (args)\n"
1486  " local needs = {}\n"
1487  " needs[\"payload\"] = tostring(true)\n"
1488  " needs[\"flowvar\"] = {\"cnt\"}\n"
1489  " return needs\n"
1490  "end\n"
1491  "\n"
1492  "function match(args)\n"
1493  " a = ScFlowvarGet(0)\n"
1494  " if a then\n"
1495  " a = tostring(tonumber(a)+1)\n"
1496  " print (a)\n"
1497  " ScFlowvarSet(0, a, #a)\n"
1498  " else\n"
1499  " a = tostring(1)\n"
1500  " print (a)\n"
1501  " ScFlowvarSet(0, a, #a)\n"
1502  " end\n"
1503  " \n"
1504  " print (\"pre check: \" .. (a))\n"
1505  " if tonumber(a) == 2 then\n"
1506  " print \"match\"\n"
1507  " return 1\n"
1508  " end\n"
1509  " return 0\n"
1510  "end\n"
1511  "return 0\n";
1512  char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1513  int result = 0;
1514  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1515  "Host: www.emergingthreats.net\r\n\r\n";
1516  uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1517  "Host: www.openinfosecfoundation.org\r\n\r\n";
1518  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1519  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1520  TcpSession ssn;
1521  Packet *p1 = NULL;
1522  Packet *p2 = NULL;
1523  Flow f;
1524  Signature *s = NULL;
1525  ThreadVars th_v;
1526  DetectEngineThreadCtx *det_ctx;
1527 
1528  ut_script = script;
1529 
1530  memset(&th_v, 0, sizeof(th_v));
1531  memset(&f, 0, sizeof(f));
1532  memset(&ssn, 0, sizeof(ssn));
1533 
1534  p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP);
1535  p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP);
1536 
1537  FLOW_INITIALIZE(&f);
1538  f.protoctx = (void *)&ssn;
1539  f.proto = IPPROTO_TCP;
1540  f.flags |= FLOW_IPV4;
1541  f.alproto = ALPROTO_HTTP1;
1542 
1543  p1->flow = &f;
1547  p2->flow = &f;
1551 
1552  StreamTcpInitConfig(true);
1553 
1555  if (de_ctx == NULL) {
1556  goto end;
1557  }
1558  de_ctx->flags |= DE_QUIET;
1559 
1560  s = DetectEngineAppendSig(de_ctx, sig);
1561  if (s == NULL) {
1562  printf("sig parse failed: ");
1563  goto end;
1564  }
1565 
1567  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1568 
1569  /* do detect for p1 */
1570  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1571 
1572  if ((PacketAlertCheck(p1, 1))) {
1573  printf("sid 1 didn't match on p1 but should have: ");
1574  goto end;
1575  }
1576 
1577  /* do detect for p2 */
1578  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1579 
1580  if (!(PacketAlertCheck(p2, 1))) {
1581  printf("sid 1 didn't match on p2 but should have: ");
1582  goto end;
1583  }
1584 
1585  FlowVar *fv = FlowVarGet(&f, 1);
1586  if (fv == NULL) {
1587  printf("no flowvar: ");
1588  goto end;
1589  }
1590 
1591  if (fv->data.fv_str.value_len != 1) {
1592  printf("%u != %u: ", fv->data.fv_str.value_len, 1);
1593  goto end;
1594  }
1595 
1596  if (memcmp(fv->data.fv_str.value, "2", 1) != 0) {
1597  PrintRawDataFp(stdout, fv->data.fv_str.value, fv->data.fv_str.value_len);
1598 
1599  printf("buffer mismatch: ");
1600  goto end;
1601  }
1602 
1603  result = 1;
1604 end:
1605  if (de_ctx != NULL)
1607 
1608  StreamTcpFreeConfig(true);
1609  FLOW_DESTROY(&f);
1610  UTHFreePackets(&p1, 1);
1611  UTHFreePackets(&p2, 1);
1612  return result;
1613 }
1614 
1615 /** \test payload buffer */
1616 static int LuaMatchTest02a(void)
1617 {
1618  const char script[] = "function init (args)\n"
1619  " local needs = {}\n"
1620  " needs[\"payload\"] = tostring(true)\n"
1621  " needs[\"flowvar\"] = {\"cnt\"}\n"
1622  " return needs\n"
1623  "end\n"
1624  "\n"
1625  "function match(args)\n"
1626  " a = SCFlowvarGet(0)\n"
1627  " if a then\n"
1628  " a = tostring(tonumber(a)+1)\n"
1629  " print (a)\n"
1630  " SCFlowvarSet(0, a, #a)\n"
1631  " else\n"
1632  " a = tostring(1)\n"
1633  " print (a)\n"
1634  " SCFlowvarSet(0, a, #a)\n"
1635  " end\n"
1636  " \n"
1637  " print (\"pre check: \" .. (a))\n"
1638  " if tonumber(a) == 2 then\n"
1639  " print \"match\"\n"
1640  " return 1\n"
1641  " end\n"
1642  " return 0\n"
1643  "end\n"
1644  "return 0\n";
1645  char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1646  int result = 0;
1647  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1648  "Host: www.emergingthreats.net\r\n\r\n";
1649  uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1650  "Host: www.openinfosecfoundation.org\r\n\r\n";
1651  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1652  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1653  TcpSession ssn;
1654  Packet *p1 = NULL;
1655  Packet *p2 = NULL;
1656  Flow f;
1657  Signature *s = NULL;
1658  ThreadVars th_v;
1659  DetectEngineThreadCtx *det_ctx;
1660 
1661  ut_script = script;
1662 
1663  memset(&th_v, 0, sizeof(th_v));
1664  memset(&f, 0, sizeof(f));
1665  memset(&ssn, 0, sizeof(ssn));
1666 
1667  p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP);
1668  p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP);
1669 
1670  FLOW_INITIALIZE(&f);
1671  f.protoctx = (void *)&ssn;
1672  f.proto = IPPROTO_TCP;
1673  f.flags |= FLOW_IPV4;
1674  f.alproto = ALPROTO_HTTP1;
1675 
1676  p1->flow = &f;
1680  p2->flow = &f;
1684 
1685  StreamTcpInitConfig(true);
1686 
1688  if (de_ctx == NULL) {
1689  goto end;
1690  }
1691  de_ctx->flags |= DE_QUIET;
1692 
1693  s = DetectEngineAppendSig(de_ctx, sig);
1694  if (s == NULL) {
1695  printf("sig parse failed: ");
1696  goto end;
1697  }
1698 
1700  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1701 
1702  /* do detect for p1 */
1703  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1704 
1705  if ((PacketAlertCheck(p1, 1))) {
1706  printf("sid 1 didn't match on p1 but should have: ");
1707  goto end;
1708  }
1709 
1710  /* do detect for p2 */
1711  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1712 
1713  if (!(PacketAlertCheck(p2, 1))) {
1714  printf("sid 1 didn't match on p2 but should have: ");
1715  goto end;
1716  }
1717 
1718  FlowVar *fv = FlowVarGet(&f, 1);
1719  if (fv == NULL) {
1720  printf("no flowvar: ");
1721  goto end;
1722  }
1723 
1724  if (fv->data.fv_str.value_len != 1) {
1725  printf("%u != %u: ", fv->data.fv_str.value_len, 1);
1726  goto end;
1727  }
1728 
1729  if (memcmp(fv->data.fv_str.value, "2", 1) != 0) {
1730  PrintRawDataFp(stdout, fv->data.fv_str.value, fv->data.fv_str.value_len);
1731 
1732  printf("buffer mismatch: ");
1733  goto end;
1734  }
1735 
1736  result = 1;
1737 end:
1738  if (de_ctx != NULL)
1740 
1741  StreamTcpFreeConfig(true);
1742  FLOW_DESTROY(&f);
1743  UTHFreePackets(&p1, 1);
1744  UTHFreePackets(&p2, 1);
1745  return result;
1746 }
1747 
1748 /** \test packet buffer */
1749 static int LuaMatchTest03(void)
1750 {
1751  const char script[] = "function init (args)\n"
1752  " local needs = {}\n"
1753  " needs[\"packet\"] = tostring(true)\n"
1754  " needs[\"flowvar\"] = {\"cnt\"}\n"
1755  " return needs\n"
1756  "end\n"
1757  "\n"
1758  "function match(args)\n"
1759  " a = ScFlowvarGet(0)\n"
1760  " if a then\n"
1761  " a = tostring(tonumber(a)+1)\n"
1762  " print (a)\n"
1763  " ScFlowvarSet(0, a, #a)\n"
1764  " else\n"
1765  " a = tostring(1)\n"
1766  " print (a)\n"
1767  " ScFlowvarSet(0, a, #a)\n"
1768  " end\n"
1769  " \n"
1770  " print (\"pre check: \" .. (a))\n"
1771  " if tonumber(a) == 2 then\n"
1772  " print \"match\"\n"
1773  " return 1\n"
1774  " end\n"
1775  " return 0\n"
1776  "end\n"
1777  "return 0\n";
1778  char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1779  int result = 0;
1780  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1781  "Host: www.emergingthreats.net\r\n\r\n";
1782  uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1783  "Host: www.openinfosecfoundation.org\r\n\r\n";
1784  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1785  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1786  TcpSession ssn;
1787  Packet *p1 = NULL;
1788  Packet *p2 = NULL;
1789  Flow f;
1790  Signature *s = NULL;
1791  ThreadVars th_v;
1792  DetectEngineThreadCtx *det_ctx;
1793 
1794  ut_script = script;
1795 
1796  memset(&th_v, 0, sizeof(th_v));
1797  memset(&f, 0, sizeof(f));
1798  memset(&ssn, 0, sizeof(ssn));
1799 
1800  p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP);
1801  p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP);
1802 
1803  FLOW_INITIALIZE(&f);
1804  f.protoctx = (void *)&ssn;
1805  f.proto = IPPROTO_TCP;
1806  f.flags |= FLOW_IPV4;
1807  f.alproto = ALPROTO_HTTP1;
1808 
1809  p1->flow = &f;
1813  p2->flow = &f;
1817 
1818  StreamTcpInitConfig(true);
1819 
1821  if (de_ctx == NULL) {
1822  goto end;
1823  }
1824  de_ctx->flags |= DE_QUIET;
1825 
1826  s = DetectEngineAppendSig(de_ctx, sig);
1827  if (s == NULL) {
1828  printf("sig parse failed: ");
1829  goto end;
1830  }
1831 
1833  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1834 
1835  /* do detect for p1 */
1836  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1837 
1838  if ((PacketAlertCheck(p1, 1))) {
1839  printf("sid 1 didn't match on p1 but should have: ");
1840  goto end;
1841  }
1842 
1843  /* do detect for p2 */
1844  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1845 
1846  if (!(PacketAlertCheck(p2, 1))) {
1847  printf("sid 1 didn't match on p2 but should have: ");
1848  goto end;
1849  }
1850 
1851  FlowVar *fv = FlowVarGet(&f, 1);
1852  if (fv == NULL) {
1853  printf("no flowvar: ");
1854  goto end;
1855  }
1856 
1857  if (fv->data.fv_str.value_len != 1) {
1858  printf("%u != %u: ", fv->data.fv_str.value_len, 1);
1859  goto end;
1860  }
1861 
1862  if (memcmp(fv->data.fv_str.value, "2", 1) != 0) {
1863  PrintRawDataFp(stdout, fv->data.fv_str.value, fv->data.fv_str.value_len);
1864 
1865  printf("buffer mismatch: ");
1866  goto end;
1867  }
1868 
1869  result = 1;
1870 end:
1871  if (de_ctx != NULL)
1873 
1874  StreamTcpFreeConfig(true);
1875  FLOW_DESTROY(&f);
1876  UTHFreePackets(&p1, 1);
1877  UTHFreePackets(&p2, 1);
1878  return result;
1879 }
1880 
1881 /** \test packet buffer */
1882 static int LuaMatchTest03a(void)
1883 {
1884  const char script[] = "function init (args)\n"
1885  " local needs = {}\n"
1886  " needs[\"packet\"] = tostring(true)\n"
1887  " needs[\"flowvar\"] = {\"cnt\"}\n"
1888  " return needs\n"
1889  "end\n"
1890  "\n"
1891  "function match(args)\n"
1892  " a = SCFlowvarGet(0)\n"
1893  " if a then\n"
1894  " a = tostring(tonumber(a)+1)\n"
1895  " print (a)\n"
1896  " SCFlowvarSet(0, a, #a)\n"
1897  " else\n"
1898  " a = tostring(1)\n"
1899  " print (a)\n"
1900  " SCFlowvarSet(0, a, #a)\n"
1901  " end\n"
1902  " \n"
1903  " print (\"pre check: \" .. (a))\n"
1904  " if tonumber(a) == 2 then\n"
1905  " print \"match\"\n"
1906  " return 1\n"
1907  " end\n"
1908  " return 0\n"
1909  "end\n"
1910  "return 0\n";
1911  char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1912  int result = 0;
1913  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1914  "Host: www.emergingthreats.net\r\n\r\n";
1915  uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1916  "Host: www.openinfosecfoundation.org\r\n\r\n";
1917  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1918  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1919  TcpSession ssn;
1920  Packet *p1 = NULL;
1921  Packet *p2 = NULL;
1922  Flow f;
1923  Signature *s = NULL;
1924  ThreadVars th_v;
1925  DetectEngineThreadCtx *det_ctx;
1926 
1927  ut_script = script;
1928 
1929  memset(&th_v, 0, sizeof(th_v));
1930  memset(&f, 0, sizeof(f));
1931  memset(&ssn, 0, sizeof(ssn));
1932 
1933  p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP);
1934  p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP);
1935 
1936  FLOW_INITIALIZE(&f);
1937  f.protoctx = (void *)&ssn;
1938  f.proto = IPPROTO_TCP;
1939  f.flags |= FLOW_IPV4;
1940  f.alproto = ALPROTO_HTTP1;
1941 
1942  p1->flow = &f;
1946  p2->flow = &f;
1950 
1951  StreamTcpInitConfig(true);
1952 
1954  if (de_ctx == NULL) {
1955  goto end;
1956  }
1957  de_ctx->flags |= DE_QUIET;
1958 
1959  s = DetectEngineAppendSig(de_ctx, sig);
1960  if (s == NULL) {
1961  printf("sig parse failed: ");
1962  goto end;
1963  }
1964 
1966  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1967 
1968  /* do detect for p1 */
1969  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1970 
1971  if ((PacketAlertCheck(p1, 1))) {
1972  printf("sid 1 didn't match on p1 but should have: ");
1973  goto end;
1974  }
1975 
1976  /* do detect for p2 */
1977  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1978 
1979  if (!(PacketAlertCheck(p2, 1))) {
1980  printf("sid 1 didn't match on p2 but should have: ");
1981  goto end;
1982  }
1983 
1984  FlowVar *fv = FlowVarGet(&f, 1);
1985  if (fv == NULL) {
1986  printf("no flowvar: ");
1987  goto end;
1988  }
1989 
1990  if (fv->data.fv_str.value_len != 1) {
1991  printf("%u != %u: ", fv->data.fv_str.value_len, 1);
1992  goto end;
1993  }
1994 
1995  if (memcmp(fv->data.fv_str.value, "2", 1) != 0) {
1996  PrintRawDataFp(stdout, fv->data.fv_str.value, fv->data.fv_str.value_len);
1997 
1998  printf("buffer mismatch: ");
1999  goto end;
2000  }
2001 
2002  result = 1;
2003 end:
2004  if (de_ctx != NULL)
2006 
2007  StreamTcpFreeConfig(true);
2008  FLOW_DESTROY(&f);
2009  UTHFreePackets(&p1, 1);
2010  UTHFreePackets(&p2, 1);
2011  return result;
2012 }
2013 
2014 /** \test http buffer, flowints */
2015 static int LuaMatchTest04(void)
2016 {
2017  const char script[] = "function init (args)\n"
2018  " local needs = {}\n"
2019  " needs[\"http.request_headers\"] = tostring(true)\n"
2020  " needs[\"flowint\"] = {\"cnt\"}\n"
2021  " return needs\n"
2022  "end\n"
2023  "\n"
2024  "function match(args)\n"
2025  " print \"inspecting\""
2026  " a = ScFlowintGet(0)\n"
2027  " if a then\n"
2028  " ScFlowintSet(0, a + 1)\n"
2029  " else\n"
2030  " ScFlowintSet(0, 1)\n"
2031  " end\n"
2032  " \n"
2033  " a = ScFlowintGet(0)\n"
2034  " if a == 2 then\n"
2035  " print \"match\"\n"
2036  " return 1\n"
2037  " end\n"
2038  " return 0\n"
2039  "end\n"
2040  "return 0\n";
2041  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
2042  int result = 0;
2043  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
2044  "Host: www.emergingthreats.net\r\n\r\n";
2045  uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
2046  "Host: www.openinfosecfoundation.org\r\n\r\n";
2047  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2048  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2049  TcpSession ssn;
2050  Packet *p1 = NULL;
2051  Packet *p2 = NULL;
2052  Flow f;
2053  Signature *s = NULL;
2054  ThreadVars th_v;
2055  DetectEngineThreadCtx *det_ctx;
2056 
2058 
2059  ut_script = script;
2060 
2061  memset(&th_v, 0, sizeof(th_v));
2062  memset(&f, 0, sizeof(f));
2063  memset(&ssn, 0, sizeof(ssn));
2064 
2065  p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2066  p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2067 
2068  FLOW_INITIALIZE(&f);
2069  f.protoctx = (void *)&ssn;
2070  f.proto = IPPROTO_TCP;
2071  f.flags |= FLOW_IPV4;
2072  f.alproto = ALPROTO_HTTP1;
2073 
2074  p1->flow = &f;
2078 
2079  p2->flow = &f;
2083 
2084  StreamTcpInitConfig(true);
2085 
2087  if (de_ctx == NULL) {
2088  goto end;
2089  }
2090  de_ctx->flags |= DE_QUIET;
2091 
2092  s = DetectEngineAppendSig(de_ctx, sig);
2093  if (s == NULL) {
2094  printf("sig parse failed: ");
2095  goto end;
2096  }
2097 
2099  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2100 
2101  int r = AppLayerParserParse(
2102  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
2103  if (r != 0) {
2104  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
2105  goto end;
2106  }
2107  HtpState *http_state = f.alstate;
2108  if (http_state == NULL) {
2109  printf("no http state: ");
2110  goto end;
2111  }
2112 
2113  /* do detect for p1 */
2114  SCLogInfo("p1");
2115  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
2116 
2117  if (PacketAlertCheck(p1, 1)) {
2118  printf("sid 1 matched on p1 but should not have: ");
2119  goto end;
2120  }
2121 
2122  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
2123  if (r != 0) {
2124  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
2125  goto end;
2126  }
2127  /* do detect for p2 */
2128  SCLogInfo("p2");
2129  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
2130 
2131  if (!(PacketAlertCheck(p2, 1))) {
2132  printf("sid 1 didn't match on p2 but should have: ");
2133  goto end;
2134  }
2135 
2136  FlowVar *fv = FlowVarGet(&f, 1);
2137  if (fv == NULL) {
2138  printf("no flowvar: ");
2139  goto end;
2140  }
2141 
2142  if (fv->data.fv_int.value != 2) {
2143  printf("%u != %u: ", fv->data.fv_int.value, 2);
2144  goto end;
2145  }
2146 
2147  result = 1;
2148 end:
2149  if (alp_tctx != NULL)
2151  if (de_ctx != NULL)
2153 
2154  StreamTcpFreeConfig(true);
2155  FLOW_DESTROY(&f);
2156  UTHFreePackets(&p1, 1);
2157  UTHFreePackets(&p2, 1);
2158  return result;
2159 }
2160 
2161 /** \test http buffer, flowints */
2162 static int LuaMatchTest04a(void)
2163 {
2164  const char script[] = "function init (args)\n"
2165  " local needs = {}\n"
2166  " needs[\"http.request_headers\"] = tostring(true)\n"
2167  " needs[\"flowint\"] = {\"cnt\"}\n"
2168  " return needs\n"
2169  "end\n"
2170  "\n"
2171  "function match(args)\n"
2172  " print \"inspecting\""
2173  " a = SCFlowintGet(0)\n"
2174  " if a then\n"
2175  " SCFlowintSet(0, a + 1)\n"
2176  " else\n"
2177  " SCFlowintSet(0, 1)\n"
2178  " end\n"
2179  " \n"
2180  " a = SCFlowintGet(0)\n"
2181  " if a == 2 then\n"
2182  " print \"match\"\n"
2183  " return 1\n"
2184  " end\n"
2185  " return 0\n"
2186  "end\n"
2187  "return 0\n";
2188  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
2189  int result = 0;
2190  uint8_t httpbuf1[] =
2191  "POST / HTTP/1.1\r\n"
2192  "Host: www.emergingthreats.net\r\n\r\n";
2193  uint8_t httpbuf2[] =
2194  "POST / HTTP/1.1\r\n"
2195  "Host: www.openinfosecfoundation.org\r\n\r\n";
2196  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2197  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2198  TcpSession ssn;
2199  Packet *p1 = NULL;
2200  Packet *p2 = NULL;
2201  Flow f;
2202  Signature *s = NULL;
2203  ThreadVars th_v;
2204  DetectEngineThreadCtx *det_ctx;
2205 
2207 
2208  ut_script = script;
2209 
2210  memset(&th_v, 0, sizeof(th_v));
2211  memset(&f, 0, sizeof(f));
2212  memset(&ssn, 0, sizeof(ssn));
2213 
2214  p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2215  p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2216 
2217  FLOW_INITIALIZE(&f);
2218  f.protoctx = (void *)&ssn;
2219  f.proto = IPPROTO_TCP;
2220  f.flags |= FLOW_IPV4;
2221  f.alproto = ALPROTO_HTTP1;
2222 
2223  p1->flow = &f;
2227 
2228  p2->flow = &f;
2232 
2233  StreamTcpInitConfig(true);
2234 
2236  if (de_ctx == NULL) {
2237  goto end;
2238  }
2239  de_ctx->flags |= DE_QUIET;
2240 
2241  s = DetectEngineAppendSig(de_ctx, sig);
2242  if (s == NULL) {
2243  printf("sig parse failed: ");
2244  goto end;
2245  }
2246 
2248  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2249 
2250  int r = AppLayerParserParse(
2251  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
2252  if (r != 0) {
2253  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
2254  goto end;
2255  }
2256  HtpState *http_state = f.alstate;
2257  if (http_state == NULL) {
2258  printf("no http state: ");
2259  goto end;
2260  }
2261 
2262  /* do detect for p1 */
2263  SCLogInfo("p1");
2264  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
2265 
2266  if (PacketAlertCheck(p1, 1)) {
2267  printf("sid 1 matched on p1 but should not have: ");
2268  goto end;
2269  }
2270 
2271  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
2272  if (r != 0) {
2273  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
2274  goto end;
2275  }
2276  /* do detect for p2 */
2277  SCLogInfo("p2");
2278  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
2279 
2280  if (!(PacketAlertCheck(p2, 1))) {
2281  printf("sid 1 didn't match on p2 but should have: ");
2282  goto end;
2283  }
2284 
2285  FlowVar *fv = FlowVarGet(&f, 1);
2286  if (fv == NULL) {
2287  printf("no flowvar: ");
2288  goto end;
2289  }
2290 
2291  if (fv->data.fv_int.value != 2) {
2292  printf("%u != %u: ", fv->data.fv_int.value, 2);
2293  goto end;
2294  }
2295 
2296  result = 1;
2297 end:
2298  if (alp_tctx != NULL)
2300  if (de_ctx != NULL)
2302 
2303  StreamTcpFreeConfig(true);
2304  FLOW_DESTROY(&f);
2305  UTHFreePackets(&p1, 1);
2306  UTHFreePackets(&p2, 1);
2307  return result;
2308 }
2309 
2310 /** \test http buffer, flowints */
2311 static int LuaMatchTest05(void)
2312 {
2313  const char script[] = "function init (args)\n"
2314  " local needs = {}\n"
2315  " needs[\"http.request_headers\"] = tostring(true)\n"
2316  " needs[\"flowint\"] = {\"cnt\"}\n"
2317  " return needs\n"
2318  "end\n"
2319  "\n"
2320  "function match(args)\n"
2321  " print \"inspecting\""
2322  " a = ScFlowintIncr(0)\n"
2323  " if a == 2 then\n"
2324  " print \"match\"\n"
2325  " return 1\n"
2326  " end\n"
2327  " return 0\n"
2328  "end\n"
2329  "return 0\n";
2330  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
2331  int result = 0;
2332  uint8_t httpbuf1[] =
2333  "POST / HTTP/1.1\r\n"
2334  "Host: www.emergingthreats.net\r\n\r\n";
2335  uint8_t httpbuf2[] =
2336  "POST / HTTP/1.1\r\n"
2337  "Host: www.openinfosecfoundation.org\r\n\r\n";
2338  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2339  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2340  TcpSession ssn;
2341  Packet *p1 = NULL;
2342  Packet *p2 = NULL;
2343  Flow f;
2344  Signature *s = NULL;
2345  ThreadVars th_v;
2346  DetectEngineThreadCtx *det_ctx;
2347 
2349 
2350  ut_script = script;
2351 
2352  memset(&th_v, 0, sizeof(th_v));
2353  memset(&f, 0, sizeof(f));
2354  memset(&ssn, 0, sizeof(ssn));
2355 
2356  p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2357  p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2358 
2359  FLOW_INITIALIZE(&f);
2360  f.protoctx = (void *)&ssn;
2361  f.proto = IPPROTO_TCP;
2362  f.flags |= FLOW_IPV4;
2363  f.alproto = ALPROTO_HTTP1;
2364 
2365  p1->flow = &f;
2369 
2370  p2->flow = &f;
2374 
2375  StreamTcpInitConfig(true);
2376 
2378  if (de_ctx == NULL) {
2379  goto end;
2380  }
2381  de_ctx->flags |= DE_QUIET;
2382 
2383  s = DetectEngineAppendSig(de_ctx, sig);
2384  if (s == NULL) {
2385  printf("sig parse failed: ");
2386  goto end;
2387  }
2388 
2390  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2391 
2392  int r = AppLayerParserParse(
2393  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
2394  if (r != 0) {
2395  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
2396  goto end;
2397  }
2398  HtpState *http_state = f.alstate;
2399  if (http_state == NULL) {
2400  printf("no http state: ");
2401  goto end;
2402  }
2403 
2404  /* do detect for p1 */
2405  SCLogInfo("p1");
2406  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
2407 
2408  if (PacketAlertCheck(p1, 1)) {
2409  printf("sid 1 matched on p1 but should not have: ");
2410  goto end;
2411  }
2412 
2413  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
2414  if (r != 0) {
2415  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
2416  goto end;
2417  }
2418  /* do detect for p2 */
2419  SCLogInfo("p2");
2420  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
2421 
2422  if (!(PacketAlertCheck(p2, 1))) {
2423  printf("sid 1 didn't match on p2 but should have: ");
2424  goto end;
2425  }
2426 
2427  FlowVar *fv = FlowVarGet(&f, 1);
2428  if (fv == NULL) {
2429  printf("no flowvar: ");
2430  goto end;
2431  }
2432 
2433  if (fv->data.fv_int.value != 2) {
2434  printf("%u != %u: ", fv->data.fv_int.value, 2);
2435  goto end;
2436  }
2437 
2438  result = 1;
2439 end:
2440  if (alp_tctx != NULL)
2442  if (de_ctx != NULL)
2444 
2445  StreamTcpFreeConfig(true);
2446  FLOW_DESTROY(&f);
2447  UTHFreePackets(&p1, 1);
2448  UTHFreePackets(&p2, 1);
2449  return result;
2450 }
2451 
2452 /** \test http buffer, flowints */
2453 static int LuaMatchTest05a(void)
2454 {
2455  const char script[] = "function init (args)\n"
2456  " local needs = {}\n"
2457  " needs[\"http.request_headers\"] = tostring(true)\n"
2458  " needs[\"flowint\"] = {\"cnt\"}\n"
2459  " return needs\n"
2460  "end\n"
2461  "\n"
2462  "function match(args)\n"
2463  " print \"inspecting\""
2464  " a = SCFlowintIncr(0)\n"
2465  " if a == 2 then\n"
2466  " print \"match\"\n"
2467  " return 1\n"
2468  " end\n"
2469  " return 0\n"
2470  "end\n"
2471  "return 0\n";
2472  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
2473  int result = 0;
2474  uint8_t httpbuf1[] =
2475  "POST / HTTP/1.1\r\n"
2476  "Host: www.emergingthreats.net\r\n\r\n";
2477  uint8_t httpbuf2[] =
2478  "POST / HTTP/1.1\r\n"
2479  "Host: www.openinfosecfoundation.org\r\n\r\n";
2480  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2481  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2482  TcpSession ssn;
2483  Packet *p1 = NULL;
2484  Packet *p2 = NULL;
2485  Flow f;
2486  Signature *s = NULL;
2487  ThreadVars th_v;
2488  DetectEngineThreadCtx *det_ctx;
2489 
2491 
2492  ut_script = script;
2493 
2494  memset(&th_v, 0, sizeof(th_v));
2495  memset(&f, 0, sizeof(f));
2496  memset(&ssn, 0, sizeof(ssn));
2497 
2498  p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2499  p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2500 
2501  FLOW_INITIALIZE(&f);
2502  f.protoctx = (void *)&ssn;
2503  f.proto = IPPROTO_TCP;
2504  f.flags |= FLOW_IPV4;
2505  f.alproto = ALPROTO_HTTP1;
2506 
2507  p1->flow = &f;
2511 
2512  p2->flow = &f;
2516 
2517  StreamTcpInitConfig(true);
2518 
2520  if (de_ctx == NULL) {
2521  goto end;
2522  }
2523  de_ctx->flags |= DE_QUIET;
2524 
2525  s = DetectEngineAppendSig(de_ctx, sig);
2526  if (s == NULL) {
2527  printf("sig parse failed: ");
2528  goto end;
2529  }
2530 
2532  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2533 
2534  int r = AppLayerParserParse(
2535  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
2536  if (r != 0) {
2537  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
2538  goto end;
2539  }
2540  HtpState *http_state = f.alstate;
2541  if (http_state == NULL) {
2542  printf("no http state: ");
2543  goto end;
2544  }
2545 
2546  /* do detect for p1 */
2547  SCLogInfo("p1");
2548  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
2549 
2550  if (PacketAlertCheck(p1, 1)) {
2551  printf("sid 1 matched on p1 but should not have: ");
2552  goto end;
2553  }
2554 
2555  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
2556  if (r != 0) {
2557  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
2558  goto end;
2559  }
2560  /* do detect for p2 */
2561  SCLogInfo("p2");
2562  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
2563 
2564  if (!(PacketAlertCheck(p2, 1))) {
2565  printf("sid 1 didn't match on p2 but should have: ");
2566  goto end;
2567  }
2568 
2569  FlowVar *fv = FlowVarGet(&f, 1);
2570  if (fv == NULL) {
2571  printf("no flowvar: ");
2572  goto end;
2573  }
2574 
2575  if (fv->data.fv_int.value != 2) {
2576  printf("%u != %u: ", fv->data.fv_int.value, 2);
2577  goto end;
2578  }
2579 
2580  result = 1;
2581 end:
2582  if (alp_tctx != NULL)
2584  if (de_ctx != NULL)
2586 
2587  StreamTcpFreeConfig(true);
2588  FLOW_DESTROY(&f);
2589  UTHFreePackets(&p1, 1);
2590  UTHFreePackets(&p2, 1);
2591  return result;
2592 }
2593 
2594 /** \test http buffer, flowints */
2595 static int LuaMatchTest06(void)
2596 {
2597  const char script[] = "function init (args)\n"
2598  " local needs = {}\n"
2599  " needs[\"http.request_headers\"] = tostring(true)\n"
2600  " needs[\"flowint\"] = {\"cnt\"}\n"
2601  " return needs\n"
2602  "end\n"
2603  "\n"
2604  "function match(args)\n"
2605  " print \"inspecting\""
2606  " a = ScFlowintGet(0)\n"
2607  " if a == nil then\n"
2608  " print \"new var set to 2\""
2609  " ScFlowintSet(0, 2)\n"
2610  " end\n"
2611  " a = ScFlowintDecr(0)\n"
2612  " if a == 0 then\n"
2613  " print \"match\"\n"
2614  " return 1\n"
2615  " end\n"
2616  " return 0\n"
2617  "end\n"
2618  "return 0\n";
2619  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
2620  int result = 0;
2621  uint8_t httpbuf1[] =
2622  "POST / HTTP/1.1\r\n"
2623  "Host: www.emergingthreats.net\r\n\r\n";
2624  uint8_t httpbuf2[] =
2625  "POST / HTTP/1.1\r\n"
2626  "Host: www.openinfosecfoundation.org\r\n\r\n";
2627  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2628  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2629  TcpSession ssn;
2630  Packet *p1 = NULL;
2631  Packet *p2 = NULL;
2632  Flow f;
2633  Signature *s = NULL;
2634  ThreadVars th_v;
2635  DetectEngineThreadCtx *det_ctx;
2636 
2638 
2639  ut_script = script;
2640 
2641  memset(&th_v, 0, sizeof(th_v));
2642  memset(&f, 0, sizeof(f));
2643  memset(&ssn, 0, sizeof(ssn));
2644 
2645  p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2646  p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2647 
2648  FLOW_INITIALIZE(&f);
2649  f.protoctx = (void *)&ssn;
2650  f.proto = IPPROTO_TCP;
2651  f.flags |= FLOW_IPV4;
2652  f.alproto = ALPROTO_HTTP1;
2653 
2654  p1->flow = &f;
2658 
2659  p2->flow = &f;
2663 
2664  StreamTcpInitConfig(true);
2665 
2667  if (de_ctx == NULL) {
2668  goto end;
2669  }
2670  de_ctx->flags |= DE_QUIET;
2671 
2672  s = DetectEngineAppendSig(de_ctx, sig);
2673  if (s == NULL) {
2674  printf("sig parse failed: ");
2675  goto end;
2676  }
2677 
2679  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2680 
2681  int r = AppLayerParserParse(
2682  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
2683  if (r != 0) {
2684  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
2685  goto end;
2686  }
2687  HtpState *http_state = f.alstate;
2688  if (http_state == NULL) {
2689  printf("no http state: ");
2690  goto end;
2691  }
2692 
2693  /* do detect for p1 */
2694  SCLogInfo("p1");
2695  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
2696 
2697  if (PacketAlertCheck(p1, 1)) {
2698  printf("sid 1 matched on p1 but should not have: ");
2699  goto end;
2700  }
2701 
2702  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
2703  if (r != 0) {
2704  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
2705  goto end;
2706  }
2707  /* do detect for p2 */
2708  SCLogInfo("p2");
2709  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
2710 
2711  if (!(PacketAlertCheck(p2, 1))) {
2712  printf("sid 1 didn't match on p2 but should have: ");
2713  goto end;
2714  }
2715 
2716  FlowVar *fv = FlowVarGet(&f, 1);
2717  if (fv == NULL) {
2718  printf("no flowvar: ");
2719  goto end;
2720  }
2721 
2722  if (fv->data.fv_int.value != 0) {
2723  printf("%u != %u: ", fv->data.fv_int.value, 0);
2724  goto end;
2725  }
2726 
2727  result = 1;
2728 end:
2729  if (alp_tctx != NULL)
2731  if (de_ctx != NULL)
2733 
2734  StreamTcpFreeConfig(true);
2735  FLOW_DESTROY(&f);
2736  UTHFreePackets(&p1, 1);
2737  UTHFreePackets(&p2, 1);
2738  return result;
2739 }
2740 
2741 /** \test http buffer, flowints */
2742 static int LuaMatchTest06a(void)
2743 {
2744  const char script[] = "function init (args)\n"
2745  " local needs = {}\n"
2746  " needs[\"http.request_headers\"] = tostring(true)\n"
2747  " needs[\"flowint\"] = {\"cnt\"}\n"
2748  " return needs\n"
2749  "end\n"
2750  "\n"
2751  "function match(args)\n"
2752  " print \"inspecting\""
2753  " a = SCFlowintGet(0)\n"
2754  " if a == nil then\n"
2755  " print \"new var set to 2\""
2756  " SCFlowintSet(0, 2)\n"
2757  " end\n"
2758  " a = SCFlowintDecr(0)\n"
2759  " if a == 0 then\n"
2760  " print \"match\"\n"
2761  " return 1\n"
2762  " end\n"
2763  " return 0\n"
2764  "end\n"
2765  "return 0\n";
2766  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
2767  int result = 0;
2768  uint8_t httpbuf1[] =
2769  "POST / HTTP/1.1\r\n"
2770  "Host: www.emergingthreats.net\r\n\r\n";
2771  uint8_t httpbuf2[] =
2772  "POST / HTTP/1.1\r\n"
2773  "Host: www.openinfosecfoundation.org\r\n\r\n";
2774  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2775  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2776  TcpSession ssn;
2777  Packet *p1 = NULL;
2778  Packet *p2 = NULL;
2779  Flow f;
2780  Signature *s = NULL;
2781  ThreadVars th_v;
2782  DetectEngineThreadCtx *det_ctx;
2783 
2785 
2786  ut_script = script;
2787 
2788  memset(&th_v, 0, sizeof(th_v));
2789  memset(&f, 0, sizeof(f));
2790  memset(&ssn, 0, sizeof(ssn));
2791 
2792  p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2793  p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2794 
2795  FLOW_INITIALIZE(&f);
2796  f.protoctx = (void *)&ssn;
2797  f.proto = IPPROTO_TCP;
2798  f.flags |= FLOW_IPV4;
2799  f.alproto = ALPROTO_HTTP1;
2800 
2801  p1->flow = &f;
2805 
2806  p2->flow = &f;
2810 
2811  StreamTcpInitConfig(true);
2812 
2814  if (de_ctx == NULL) {
2815  goto end;
2816  }
2817  de_ctx->flags |= DE_QUIET;
2818 
2819  s = DetectEngineAppendSig(de_ctx, sig);
2820  if (s == NULL) {
2821  printf("sig parse failed: ");
2822  goto end;
2823  }
2824 
2826  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2827 
2828  int r = AppLayerParserParse(
2829  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
2830  if (r != 0) {
2831  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
2832  goto end;
2833  }
2834  HtpState *http_state = f.alstate;
2835  if (http_state == NULL) {
2836  printf("no http state: ");
2837  goto end;
2838  }
2839 
2840  /* do detect for p1 */
2841  SCLogInfo("p1");
2842  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
2843 
2844  if (PacketAlertCheck(p1, 1)) {
2845  printf("sid 1 matched on p1 but should not have: ");
2846  goto end;
2847  }
2848 
2849  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
2850  if (r != 0) {
2851  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
2852  goto end;
2853  }
2854  /* do detect for p2 */
2855  SCLogInfo("p2");
2856  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
2857 
2858  if (!(PacketAlertCheck(p2, 1))) {
2859  printf("sid 1 didn't match on p2 but should have: ");
2860  goto end;
2861  }
2862 
2863  FlowVar *fv = FlowVarGet(&f, 1);
2864  if (fv == NULL) {
2865  printf("no flowvar: ");
2866  goto end;
2867  }
2868 
2869  if (fv->data.fv_int.value != 0) {
2870  printf("%u != %u: ", fv->data.fv_int.value, 0);
2871  goto end;
2872  }
2873 
2874  result = 1;
2875 end:
2876  if (alp_tctx != NULL)
2878  if (de_ctx != NULL)
2880 
2881  StreamTcpFreeConfig(true);
2882  FLOW_DESTROY(&f);
2883  UTHFreePackets(&p1, 1);
2884  UTHFreePackets(&p2, 1);
2885  return result;
2886 }
2887 
2888 void DetectLuaRegisterTests(void)
2889 {
2890  UtRegisterTest("LuaMatchTest01", LuaMatchTest01);
2891  UtRegisterTest("LuaMatchTest01a", LuaMatchTest01a);
2892  UtRegisterTest("LuaMatchTest02", LuaMatchTest02);
2893  UtRegisterTest("LuaMatchTest02a", LuaMatchTest02a);
2894  UtRegisterTest("LuaMatchTest03", LuaMatchTest03);
2895  UtRegisterTest("LuaMatchTest03a", LuaMatchTest03a);
2896  UtRegisterTest("LuaMatchTest04", LuaMatchTest04);
2897  UtRegisterTest("LuaMatchTest04a", LuaMatchTest04a);
2898  UtRegisterTest("LuaMatchTest05", LuaMatchTest05);
2899  UtRegisterTest("LuaMatchTest05a", LuaMatchTest05a);
2900  UtRegisterTest("LuaMatchTest06", LuaMatchTest06);
2901  UtRegisterTest("LuaMatchTest06a", LuaMatchTest06a);
2902 }
2903 #endif
2904 #endif /* HAVE_LUAJIT */
util-byte.h
SigTableElmt_::url
const char * url
Definition: detect.h:1238
detect-engine.h
DETECT_SM_LIST_PMATCH
@ DETECT_SM_LIST_PMATCH
Definition: detect.h:79
SigTableElmt_::desc
const char * desc
Definition: detect.h:1237
PKT_HAS_FLOW
#define PKT_HAS_FLOW
Definition: decode.h:996
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
SC_ERR_INVALID_VALUE
@ SC_ERR_INVALID_VALUE
Definition: util-error.h:160
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1225
flow-util.h
ALPROTO_DNS
@ ALPROTO_DNS
Definition: app-layer-protos.h:41
SigTableElmt_::name
const char * name
Definition: detect.h:1235
stream-tcp.h
DetectThreadCtxGetKeywordThreadCtx
void * DetectThreadCtxGetKeywordThreadCtx(DetectEngineThreadCtx *det_ctx, int id)
Retrieve thread local keyword ctx by id.
Definition: detect-engine.c:3502
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
ALPROTO_TLS
@ ALPROTO_TLS
Definition: app-layer-protos.h:33
Signature_::alproto
AppProto alproto
Definition: detect.h:543
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:296
FlowVar_::data
union FlowVar_::@112 data
Flow_::proto
uint8_t proto
Definition: flow.h:378
util-lua.h
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:81
Packet_::payload
uint8_t * payload
Definition: decode.h:567
PacketAlertCheck
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
Definition: detect-engine-alert.c:141
DetectEngineThreadCtx_::tx_id
uint64_t tx_id
Definition: detect.h:1097
FlowVarTypeStr::value_len
uint16_t value_len
Definition: flow-var.h:39
SigMatchData_::ctx
SigMatchCtx * ctx
Definition: detect.h:325
Packet_::flags
uint32_t flags
Definition: decode.h:460
threads.h
Flow_
Flow data structure.
Definition: flow.h:356
SigTableElmt_::flags
uint16_t flags
Definition: detect.h:1229
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:784
Krb5PrincipalNameDataArgs::txv
void * txv
Definition: detect-krb5-cname.c:44
FlowVar_::fv_str
FlowVarTypeStr fv_str
Definition: flow-var.h:57
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2445
detect-lua.h
SigTableElmt_::AppLayerTxMatch
int(* AppLayerTxMatch)(DetectEngineThreadCtx *, Flow *, uint8_t flags, void *alstate, void *txv, const Signature *, const SigMatchCtx *)
Definition: detect.h:1206
AppLayerParserThreadCtxFree
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
Definition: app-layer-parser.c:316
FLOW_PKT_TOSERVER
#define FLOW_PKT_TOSERVER
Definition: flow.h:226
util-var-name.h
DE_QUIET
#define DE_QUIET
Definition: detect.h:287
DetectLuaPostSetup
void DetectLuaPostSetup(Signature *s)
UTHBuildPacket
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.
Definition: util-unittest-helper.c:339
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1788
StringParseInt32
int StringParseInt32(int32_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:613
ALPROTO_SSH
@ ALPROTO_SSH
Definition: app-layer-protos.h:34
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:456
DetectBufferGetActiveList
int DetectBufferGetActiveList(DetectEngineCtx *de_ctx, Signature *s)
Definition: detect-engine.c:1313
SIG_FLAG_TOCLIENT
#define SIG_FLAG_TOCLIENT
Definition: detect.h:229
Flow_::protoctx
void * protoctx
Definition: flow.h:454
SigMatchData_
Data needed for Match()
Definition: detect.h:322
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1220
FLOW_IPV4
#define FLOW_IPV4
Definition: flow.h:96
Packet_::payload_len
uint16_t payload_len
Definition: decode.h:568
AppLayerParserGetTransactionInspectId
uint64_t AppLayerParserGetTransactionInspectId(AppLayerParserState *pstate, uint8_t direction)
Definition: app-layer-parser.c:731
DetectByteIndexType
uint8_t DetectByteIndexType
Definition: detect-byte.h:28
util-unittest.h
HtpState_
Definition: app-layer-htp.h:245
SIGMATCH_NOT_BUILT
#define SIGMATCH_NOT_BUILT
Definition: detect.h:1427
util-unittest-helper.h
DetectBufferTypeGetByName
int DetectBufferTypeGetByName(const char *name)
Definition: detect-engine.c:1086
Signature_::gid
uint32_t gid
Definition: detect.h:574
FlowVar_::fv_int
FlowVarTypeInt fv_int
Definition: flow-var.h:58
Flow_::alparser
AppLayerParserState * alparser
Definition: flow.h:488
DetectLuaMatchBuffer
int DetectLuaMatchBuffer(DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, const uint8_t *buffer, uint32_t buffer_len, uint32_t offset, Flow *f)
StreamTcpInitConfig
void StreamTcpInitConfig(bool)
To initialize the stream global configuration data.
Definition: stream-tcp.c:361
FLOW_INITIALIZE
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:39
SIG_FLAG_TOSERVER
#define SIG_FLAG_TOSERVER
Definition: detect.h:228
app-layer-htp.h
decode.h
util-debug.h
type
uint8_t type
Definition: decode-icmpv4.h:0
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
DetectEngineThreadCtx_
Definition: detect.h:1024
util-cpu.h
ALPROTO_DNP3
@ ALPROTO_DNP3
Definition: app-layer-protos.h:44
ALPROTO_SMTP
@ ALPROTO_SMTP
Definition: app-layer-protos.h:32
alp_tctx
AppLayerParserThreadCtx * alp_tctx
Definition: fuzz_applayerparserparse.c:22
DETECT_LUA
@ DETECT_LUA
Definition: detect-engine-register.h:220
SignatureInitData_::list
int list
Definition: detect.h:516
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:298
GET_PKT_DATA
#define GET_PKT_DATA(p)
Definition: decode.h:216
detect-engine-mpm.h
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
DetectLuaRegister
void DetectLuaRegister(void)
Registration function for keyword: lua.
Definition: detect-lua.c:77
SigMatch_::next
struct SigMatch_ * next
Definition: detect.h:317
SC_ERR_LUA_ERROR
@ SC_ERR_LUA_ERROR
Definition: util-error.h:244
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:78
PrintRawDataFp
void PrintRawDataFp(FILE *fp, const uint8_t *buf, uint32_t buflen)
Definition: util-print.c:143
app-layer-parser.h
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:316
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:289
Packet_
Definition: decode.h:425
detect-engine-build.h
GET_PKT_LEN
#define GET_PKT_LEN(p)
Definition: decode.h:215
DetectAppLayerInspectEngineRegister2
void DetectAppLayerInspectEngineRegister2(const char *name, AppProto alproto, uint32_t dir, int progress, InspectEngineFuncPtr2 Callback2, InspectionBufferGetDataPtr GetData)
register inspect engine at start up time
Definition: detect-engine.c:228
detect-engine-alert.h
conf.h
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:610
detect-engine-state.h
Data structures and function prototypes for keeping state for the detection engine.
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1203
queue.h
detect-byte.h
SignatureInitData_::smlists
struct SigMatch_ ** smlists
Definition: detect.h:533
FLOW_PKT_TOCLIENT
#define FLOW_PKT_TOCLIENT
Definition: flow.h:227
SigMatchAlloc
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:238
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:215
AppLayerParserGetTx
void * AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
Definition: app-layer-parser.c:1148
FlowVarTypeInt_::value
uint32_t value
Definition: flow-var.h:44
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:1954
AppLayerParserThreadCtxAlloc
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
Definition: app-layer-parser.c:295
SigMatchCtx_
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:308
DetectEngineAppendSig
Signature * DetectEngineAppendSig(DetectEngineCtx *de_ctx, const char *sigstr)
Parse and append a Signature into the Detection Engine Context signature list.
Definition: detect-parse.c:2434
FlowVarTypeStr::value
uint8_t * value
Definition: flow-var.h:38
Packet_::flow
struct Flow_ * flow
Definition: decode.h:462
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
Definition: detect-engine.c:3154
DetectByteRetrieveSMVar
bool DetectByteRetrieveSMVar(const char *arg, const Signature *s, DetectByteIndexType *index)
Used to retrieve args from BM.
Definition: detect-byte.c:39
DetectBufferTypeRegister
int DetectBufferTypeRegister(const char *name)
Definition: detect-engine.c:1032
StreamTcpFreeConfig
void StreamTcpFreeConfig(bool quiet)
Definition: stream-tcp.c:669
flags
uint8_t flags
Definition: decode-gre.h:0
DetectRegisterThreadCtxFuncs
int DetectRegisterThreadCtxFuncs(DetectEngineCtx *de_ctx, const char *name, void *(*InitFunc)(void *), void *data, void(*FreeFunc)(void *), int mode)
Register Thread keyword context Funcs.
Definition: detect-engine.c:3432
SigTableElmt_::alias
const char * alias
Definition: detect.h:1236
AppLayerParserParse
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, const uint8_t *input, uint32_t input_len)
Definition: app-layer-parser.c:1280
detect-lua-extensions.h
suricata-common.h
SigMatch_::type
uint16_t type
Definition: detect.h:314
ALPROTO_HTTP1
@ ALPROTO_HTTP1
Definition: app-layer-protos.h:30
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:76
HtpState_::connp
htp_connp_t * connp
Definition: app-layer-htp.h:247
VarNameStoreSetupAdd
uint32_t VarNameStoreSetupAdd(const char *name, const enum VarTypes type)
add to staging or return existing id if already in there
Definition: util-var-name.c:323
SCLogError
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:255
lua_State
void lua_State
Definition: suricata-common.h:488
Signature_::rev
uint32_t rev
Definition: detect.h:575
util-spm-bm.h
SCStrdup
#define SCStrdup(s)
Definition: util-mem.h:56
DetectEngineInspectGenericList
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.
Definition: detect-engine.c:1951
SC_ERR_NO_LUA_SUPPORT
@ SC_ERR_NO_LUA_SUPPORT
Definition: util-error.h:243
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
str
#define str(s)
Definition: suricata-common.h:280
DetectEngineThreadCtx_::tv
ThreadVars * tv
Definition: detect.h:1030
SCFree
#define SCFree(p)
Definition: util-mem.h:61
Flow_::alstate
void * alstate
Definition: flow.h:489
Signature_::id
uint32_t id
Definition: detect.h:573
Flow_::flags
uint32_t flags
Definition: flow.h:434
detect-parse.h
Signature_
Signature container.
Definition: detect.h:539
SigMatch_
a single match condition for a signature
Definition: detect.h:313
AppLayerGetProtoName
const char * AppLayerGetProtoName(AppProto alproto)
Given the internal protocol id, returns a string representation of the protocol.
Definition: app-layer.c:934
VAR_TYPE_FLOW_VAR
@ VAR_TYPE_FLOW_VAR
Definition: util-var.h:37
DETECT_SM_LIST_MAX
@ DETECT_SM_LIST_MAX
Definition: detect.h:95
VAR_TYPE_FLOW_INT
@ VAR_TYPE_FLOW_INT
Definition: util-var.h:36
ALPROTO_UNKNOWN
@ ALPROTO_UNKNOWN
Definition: app-layer-protos.h:29
FLOW_PKT_ESTABLISHED
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:228
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2406
DetectLoadCompleteSigPath
char * DetectLoadCompleteSigPath(const DetectEngineCtx *de_ctx, const char *sig_file)
Create the path if default-rule-path was specified.
Definition: detect-engine-loader.c:61
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:785
FlowVarGet
FlowVar * FlowVarGet(Flow *f, uint32_t idx)
get the flowvar with index 'idx' from the flow
Definition: flow-var.c:78
AppLayerParserThreadCtx_
Definition: app-layer-parser.c:68
DetectUnregisterThreadCtxFuncs
int DetectUnregisterThreadCtxFuncs(DetectEngineCtx *de_ctx, void *data, const char *name)
Remove Thread keyword context registration.
Definition: detect-engine.c:3484
TcpSession_
Definition: stream-tcp-private.h:272
flow.h
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:463
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:302
flow-var.h
AppLayerParserGetTxCnt
uint64_t AppLayerParserGetTxCnt(const Flow *f, void *alstate)
Definition: app-layer-parser.c:1141
FlowVar_
Definition: flow-var.h:48
SigMatchAppendSMToList
void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:352
FLOW_DESTROY
#define FLOW_DESTROY(f)
Definition: flow-util.h:130
PKT_STREAM_EST
#define PKT_STREAM_EST
Definition: decode.h:993
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1227
app-layer.h
UTHFreePackets
void UTHFreePackets(Packet **p, int numpkts)
UTHFreePackets: function to release the allocated data from UTHBuildPacket and the packet itself.
Definition: util-unittest-helper.c:470