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("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("Invalid value "
272  "for \"retval\" from LUA return table: '%s'",
273  v);
274  ret = 0;
275  }
276  else if (val == 1) {
277  ret = 1;
278  }
279  } else {
280  /* set flow var? */
281  }
282  }
283 
284  /* pop the table */
285  lua_pop(tlua->luastate, 1);
286  }
287  } else {
288  SCLogDebug("no stack");
289  }
290 
291  /* clear the stack */
292  while (lua_gettop(tlua->luastate) > 0) {
293  lua_pop(tlua->luastate, 1);
294  }
295 
296  if (lua->negated) {
297  if (ret == 1)
298  ret = 0;
299  else
300  ret = 1;
301  }
302 
303  SCReturnInt(ret);
304 }
305 
306 /**
307  * \brief match the specified lua script
308  *
309  * \param t thread local vars
310  * \param det_ctx pattern matcher thread local data
311  * \param p packet
312  * \param s signature being inspected
313  * \param m sigmatch that we will cast into DetectLuaData
314  *
315  * \retval 0 no match
316  * \retval 1 match
317  */
318 static int DetectLuaMatch (DetectEngineThreadCtx *det_ctx,
319  Packet *p, const Signature *s, const SigMatchCtx *ctx)
320 {
321  SCEnter();
322  int ret = 0;
323  DetectLuaData *lua = (DetectLuaData *)ctx;
324  if (lua == NULL)
325  SCReturnInt(0);
326 
327  DetectLuaThreadData *tlua = (DetectLuaThreadData *)DetectThreadCtxGetKeywordThreadCtx(det_ctx, lua->thread_ctx_id);
328  if (tlua == NULL)
329  SCReturnInt(0);
330 
331  /* setup extension data for use in lua c functions */
332  uint8_t flags = 0;
333  if (p->flowflags & FLOW_PKT_TOSERVER)
334  flags = STREAM_TOSERVER;
335  else if (p->flowflags & FLOW_PKT_TOCLIENT)
336  flags = STREAM_TOCLIENT;
337 
338  LuaStateSetThreadVars(tlua->luastate, det_ctx->tv);
339 
340  LuaExtensionsMatchSetup(tlua->luastate, lua, det_ctx, p->flow, p, s, flags);
341 
342  if ((tlua->flags & DATATYPE_PAYLOAD) && p->payload_len == 0)
343  SCReturnInt(0);
344  if ((tlua->flags & DATATYPE_PACKET) && GET_PKT_LEN(p) == 0)
345  SCReturnInt(0);
346  if (tlua->alproto != ALPROTO_UNKNOWN) {
347  if (p->flow == NULL)
348  SCReturnInt(0);
349 
350  AppProto alproto = p->flow->alproto;
351  if (tlua->alproto != alproto)
352  SCReturnInt(0);
353  }
354 
355  lua_getglobal(tlua->luastate, "match");
356  lua_newtable(tlua->luastate); /* stack at -1 */
357 
358  if ((tlua->flags & DATATYPE_PAYLOAD) && p->payload_len) {
359  lua_pushliteral(tlua->luastate, "payload"); /* stack at -2 */
360  LuaPushStringBuffer (tlua->luastate, (const uint8_t *)p->payload, (size_t)p->payload_len); /* stack at -3 */
361  lua_settable(tlua->luastate, -3);
362  }
363  if ((tlua->flags & DATATYPE_PACKET) && GET_PKT_LEN(p)) {
364  lua_pushliteral(tlua->luastate, "packet"); /* stack at -2 */
365  LuaPushStringBuffer (tlua->luastate, (const uint8_t *)GET_PKT_DATA(p), (size_t)GET_PKT_LEN(p)); /* stack at -3 */
366  lua_settable(tlua->luastate, -3);
367  }
368  if (tlua->alproto == ALPROTO_HTTP1) {
369  HtpState *htp_state = p->flow->alstate;
370  if (htp_state != NULL && htp_state->connp != NULL) {
371  htp_tx_t *tx = NULL;
373  STREAM_TOSERVER);
374  uint64_t total_txs= AppLayerParserGetTxCnt(p->flow, htp_state);
375  for ( ; idx < total_txs; idx++) {
376  tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, htp_state, idx);
377  if (tx == NULL)
378  continue;
379 
380  if ((tlua->flags & DATATYPE_HTTP_REQUEST_LINE) && tx->request_line != NULL &&
381  bstr_len(tx->request_line) > 0) {
382  lua_pushliteral(tlua->luastate, "http.request_line"); /* stack at -2 */
383  LuaPushStringBuffer(tlua->luastate,
384  (const uint8_t *)bstr_ptr(tx->request_line),
385  bstr_len(tx->request_line));
386  lua_settable(tlua->luastate, -3);
387  }
388  }
389  }
390  }
391 
392  int retval = lua_pcall(tlua->luastate, 1, 1, 0);
393  if (retval != 0) {
394  SCLogInfo("failed to run script: %s", lua_tostring(tlua->luastate, -1));
395  }
396 
397  /* process returns from script */
398  if (lua_gettop(tlua->luastate) > 0) {
399 
400  /* script returns a number (return 1 or return 0) */
401  if (lua_type(tlua->luastate, 1) == LUA_TNUMBER) {
402  double script_ret = lua_tonumber(tlua->luastate, 1);
403  SCLogDebug("script_ret %f", script_ret);
404  lua_pop(tlua->luastate, 1);
405 
406  if (script_ret == 1.0)
407  ret = 1;
408 
409  /* script returns a table */
410  } else if (lua_type(tlua->luastate, 1) == LUA_TTABLE) {
411  lua_pushnil(tlua->luastate);
412  const char *k, *v;
413  while (lua_next(tlua->luastate, -2)) {
414  v = lua_tostring(tlua->luastate, -1);
415  lua_pop(tlua->luastate, 1);
416  k = lua_tostring(tlua->luastate, -1);
417 
418  if (!k || !v)
419  continue;
420 
421  SCLogDebug("k='%s', v='%s'", k, v);
422 
423  if (strcmp(k, "retval") == 0) {
424  int val;
425  if (StringParseInt32(&val, 10, 0,
426  (const char *)v) < 0) {
427  SCLogError("Invalid value "
428  "for \"retval\" from LUA return table: '%s'",
429  v);
430  ret = 0;
431  }
432  else if (val == 1) {
433  ret = 1;
434  }
435  } else {
436  /* set flow var? */
437  }
438  }
439 
440  /* pop the table */
441  lua_pop(tlua->luastate, 1);
442  }
443  }
444  while (lua_gettop(tlua->luastate) > 0) {
445  lua_pop(tlua->luastate, 1);
446  }
447 
448  if (lua->negated) {
449  if (ret == 1)
450  ret = 0;
451  else
452  ret = 1;
453  }
454 
455  SCReturnInt(ret);
456 }
457 
458 static int DetectLuaAppMatchCommon (DetectEngineThreadCtx *det_ctx,
459  Flow *f, uint8_t flags, void *state,
460  const Signature *s, const SigMatchCtx *ctx)
461 {
462  SCEnter();
463  int ret = 0;
464  DetectLuaData *lua = (DetectLuaData *)ctx;
465  if (lua == NULL)
466  SCReturnInt(0);
467 
468  DetectLuaThreadData *tlua = (DetectLuaThreadData *)DetectThreadCtxGetKeywordThreadCtx(det_ctx, lua->thread_ctx_id);
469  if (tlua == NULL)
470  SCReturnInt(0);
471 
472  /* setup extension data for use in lua c functions */
473  LuaExtensionsMatchSetup(tlua->luastate, lua, det_ctx, f, NULL, s, flags);
474 
475  if (tlua->alproto != ALPROTO_UNKNOWN) {
476  int alproto = f->alproto;
477  if (tlua->alproto != alproto)
478  SCReturnInt(0);
479  }
480 
481  lua_getglobal(tlua->luastate, "match");
482  lua_newtable(tlua->luastate); /* stack at -1 */
483 
484  if (tlua->alproto == ALPROTO_HTTP1) {
485  HtpState *htp_state = state;
486  if (htp_state != NULL && htp_state->connp != NULL) {
487  htp_tx_t *tx = NULL;
488  tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, htp_state, det_ctx->tx_id);
489  if (tx != NULL) {
490  if ((tlua->flags & DATATYPE_HTTP_REQUEST_LINE) && tx->request_line != NULL &&
491  bstr_len(tx->request_line) > 0) {
492  lua_pushliteral(tlua->luastate, "http.request_line"); /* stack at -2 */
493  LuaPushStringBuffer(tlua->luastate,
494  (const uint8_t *)bstr_ptr(tx->request_line),
495  bstr_len(tx->request_line));
496  lua_settable(tlua->luastate, -3);
497  }
498  }
499  }
500  }
501 
502  int retval = lua_pcall(tlua->luastate, 1, 1, 0);
503  if (retval != 0) {
504  SCLogInfo("failed to run script: %s", lua_tostring(tlua->luastate, -1));
505  }
506 
507  /* process returns from script */
508  if (lua_gettop(tlua->luastate) > 0) {
509 
510  /* script returns a number (return 1 or return 0) */
511  if (lua_type(tlua->luastate, 1) == LUA_TNUMBER) {
512  double script_ret = lua_tonumber(tlua->luastate, 1);
513  SCLogDebug("script_ret %f", script_ret);
514  lua_pop(tlua->luastate, 1);
515 
516  if (script_ret == 1.0)
517  ret = 1;
518 
519  /* script returns a table */
520  } else if (lua_type(tlua->luastate, 1) == LUA_TTABLE) {
521  lua_pushnil(tlua->luastate);
522  const char *k, *v;
523  while (lua_next(tlua->luastate, -2)) {
524  v = lua_tostring(tlua->luastate, -1);
525  lua_pop(tlua->luastate, 1);
526  k = lua_tostring(tlua->luastate, -1);
527 
528  if (!k || !v)
529  continue;
530 
531  SCLogDebug("k='%s', v='%s'", k, v);
532 
533  if (strcmp(k, "retval") == 0) {
534  int val;
535  if (StringParseInt32(&val, 10, 0,
536  (const char *)v) < 0) {
537  SCLogError("Invalid value "
538  "for \"retval\" from LUA return table: '%s'",
539  v);
540  ret = 0;
541  }
542  else if (val == 1) {
543  ret = 1;
544  }
545  } else {
546  /* set flow var? */
547  }
548  }
549 
550  /* pop the table */
551  lua_pop(tlua->luastate, 1);
552  }
553  }
554  while (lua_gettop(tlua->luastate) > 0) {
555  lua_pop(tlua->luastate, 1);
556  }
557 
558  if (lua->negated) {
559  if (ret == 1)
560  ret = 0;
561  else
562  ret = 1;
563  }
564 
565  SCReturnInt(ret);
566 }
567 
568 /**
569  * \brief match the specified lua script in a list with a tx
570  *
571  * \param t thread local vars
572  * \param det_ctx pattern matcher thread local data
573  * \param s signature being inspected
574  * \param m sigmatch that we will cast into DetectLuaData
575  *
576  * \retval 0 no match
577  * \retval 1 match
578  */
579 static int DetectLuaAppTxMatch (DetectEngineThreadCtx *det_ctx,
580  Flow *f, uint8_t flags,
581  void *state, void *txv, const Signature *s,
582  const SigMatchCtx *ctx)
583 {
584  return DetectLuaAppMatchCommon(det_ctx, f, flags, state, s, ctx);
585 }
586 
587 #ifdef UNITTESTS
588 /* if this ptr is set the lua setup functions will use this buffer as the
589  * lua script instead of calling luaL_loadfile on the filename supplied. */
590 static const char *ut_script = NULL;
591 #endif
592 
593 static void *DetectLuaThreadInit(void *data)
594 {
595  int status;
596  DetectLuaData *lua = (DetectLuaData *)data;
597  BUG_ON(lua == NULL);
598 
599  DetectLuaThreadData *t = SCMalloc(sizeof(DetectLuaThreadData));
600  if (unlikely(t == NULL)) {
601  SCLogError("couldn't alloc ctx memory");
602  return NULL;
603  }
604  memset(t, 0x00, sizeof(DetectLuaThreadData));
605 
606  t->alproto = lua->alproto;
607  t->flags = lua->flags;
608 
609  t->luastate = LuaGetState();
610  if (t->luastate == NULL) {
611  SCLogError("luastate pool depleted");
612  goto error;
613  }
614 
615  luaL_openlibs(t->luastate);
616 
617  LuaRegisterExtensions(t->luastate);
618 
619  lua_pushinteger(t->luastate, (lua_Integer)(lua->sid));
620  lua_setglobal(t->luastate, "SCRuleSid");
621  lua_pushinteger(t->luastate, (lua_Integer)(lua->rev));
622  lua_setglobal(t->luastate, "SCRuleRev");
623  lua_pushinteger(t->luastate, (lua_Integer)(lua->gid));
624  lua_setglobal(t->luastate, "SCRuleGid");
625 
626  /* hackish, needed to allow unittests to pass buffers as scripts instead of files */
627 #ifdef UNITTESTS
628  if (ut_script != NULL) {
629  status = luaL_loadbuffer(t->luastate, ut_script, strlen(ut_script), "unittest");
630  if (status) {
631  SCLogError("couldn't load file: %s", lua_tostring(t->luastate, -1));
632  goto error;
633  }
634  } else {
635 #endif
636  status = luaL_loadfile(t->luastate, lua->filename);
637  if (status) {
638  SCLogError("couldn't load file: %s", lua_tostring(t->luastate, -1));
639  goto error;
640  }
641 #ifdef UNITTESTS
642  }
643 #endif
644 
645  /* prime the script (or something) */
646  if (lua_pcall(t->luastate, 0, 0, 0) != 0) {
647  SCLogError("couldn't prime file: %s", lua_tostring(t->luastate, -1));
648  goto error;
649  }
650 
651  return (void *)t;
652 
653 error:
654  if (t->luastate != NULL)
655  LuaReturnState(t->luastate);
656  SCFree(t);
657  return NULL;
658 }
659 
660 static void DetectLuaThreadFree(void *ctx)
661 {
662  if (ctx != NULL) {
663  DetectLuaThreadData *t = (DetectLuaThreadData *)ctx;
664  if (t->luastate != NULL)
665  LuaReturnState(t->luastate);
666  SCFree(t);
667  }
668 }
669 
670 /**
671  * \brief Parse the lua keyword
672  *
673  * \param de_ctx Pointer to the detection engine context
674  * \param str Pointer to the user provided option
675  *
676  * \retval lua pointer to DetectLuaData on success
677  * \retval NULL on failure
678  */
679 static DetectLuaData *DetectLuaParse (DetectEngineCtx *de_ctx, const char *str)
680 {
681  DetectLuaData *lua = NULL;
682 
683  /* We have a correct lua option */
684  lua = SCMalloc(sizeof(DetectLuaData));
685  if (unlikely(lua == NULL))
686  goto error;
687 
688  memset(lua, 0x00, sizeof(DetectLuaData));
689 
690  if (strlen(str) && str[0] == '!') {
691  lua->negated = 1;
692  str++;
693  }
694 
695  /* get full filename */
696  lua->filename = DetectLoadCompleteSigPath(de_ctx, str);
697  if (lua->filename == NULL) {
698  goto error;
699  }
700 
701  return lua;
702 
703 error:
704  if (lua != NULL)
705  DetectLuaFree(de_ctx, lua);
706  return NULL;
707 }
708 
709 static int DetectLuaSetupPrime(DetectEngineCtx *de_ctx, DetectLuaData *ld, const Signature *s)
710 {
711  int status;
712 
713  lua_State *luastate = luaL_newstate();
714  if (luastate == NULL)
715  return -1;
716  luaL_openlibs(luastate);
717 
718  /* hackish, needed to allow unittests to pass buffers as scripts instead of files */
719 #ifdef UNITTESTS
720  if (ut_script != NULL) {
721  status = luaL_loadbuffer(luastate, ut_script, strlen(ut_script), "unittest");
722  if (status) {
723  SCLogError("couldn't load file: %s", lua_tostring(luastate, -1));
724  goto error;
725  }
726  } else {
727 #endif
728  status = luaL_loadfile(luastate, ld->filename);
729  if (status) {
730  SCLogError("couldn't load file: %s", lua_tostring(luastate, -1));
731  goto error;
732  }
733 #ifdef UNITTESTS
734  }
735 #endif
736 
737  /* prime the script (or something) */
738  if (lua_pcall(luastate, 0, 0, 0) != 0) {
739  SCLogError("couldn't prime file: %s", lua_tostring(luastate, -1));
740  goto error;
741  }
742 
743  lua_getglobal(luastate, "init");
744  if (lua_type(luastate, -1) != LUA_TFUNCTION) {
745  SCLogError("no init function in script");
746  goto error;
747  }
748 
749  lua_newtable(luastate); /* stack at -1 */
750  if (lua_gettop(luastate) == 0 || lua_type(luastate, 2) != LUA_TTABLE) {
751  SCLogError("no table setup");
752  goto error;
753  }
754 
755  lua_pushliteral(luastate, "script_api_ver"); /* stack at -2 */
756  lua_pushnumber (luastate, 1); /* stack at -3 */
757  lua_settable(luastate, -3);
758 
759  if (lua_pcall(luastate, 1, 1, 0) != 0) {
760  SCLogError("couldn't run script 'init' function: %s", lua_tostring(luastate, -1));
761  goto error;
762  }
763 
764  /* process returns from script */
765  if (lua_gettop(luastate) == 0) {
766  SCLogError("init function in script should return table, nothing returned");
767  goto error;
768  }
769  if (lua_type(luastate, 1) != LUA_TTABLE) {
770  SCLogError("init function in script should return table, returned is not table");
771  goto error;
772  }
773 
774  lua_pushnil(luastate);
775  const char *k, *v;
776  while (lua_next(luastate, -2)) {
777  k = lua_tostring(luastate, -2);
778  if (k == NULL)
779  continue;
780 
781  /* handle flowvar and bytes separately as they have a table as value */
782  if (strcmp(k, "flowvar") == 0) {
783  if (lua_istable(luastate, -1)) {
784  lua_pushnil(luastate);
785  while (lua_next(luastate, -2) != 0) {
786  /* value at -1, key is at -2 which we ignore */
787  const char *value = lua_tostring(luastate, -1);
788  SCLogDebug("value %s", value);
789  /* removes 'value'; keeps 'key' for next iteration */
790  lua_pop(luastate, 1);
791 
792  if (ld->flowvars == DETECT_LUAJIT_MAX_FLOWVARS) {
793  SCLogError("too many flowvars registered");
794  goto error;
795  }
796 
797  uint32_t idx = VarNameStoreRegister(value, VAR_TYPE_FLOW_VAR);
798  ld->flowvar[ld->flowvars++] = idx;
799  SCLogDebug("script uses flowvar %u with script id %u", idx, ld->flowvars - 1);
800  }
801  }
802  lua_pop(luastate, 1);
803  continue;
804  } else if (strcmp(k, "flowint") == 0) {
805  if (lua_istable(luastate, -1)) {
806  lua_pushnil(luastate);
807  while (lua_next(luastate, -2) != 0) {
808  /* value at -1, key is at -2 which we ignore */
809  const char *value = lua_tostring(luastate, -1);
810  SCLogDebug("value %s", value);
811  /* removes 'value'; keeps 'key' for next iteration */
812  lua_pop(luastate, 1);
813 
814  if (ld->flowints == DETECT_LUAJIT_MAX_FLOWINTS) {
815  SCLogError("too many flowints registered");
816  goto error;
817  }
818 
819  uint32_t idx = VarNameStoreRegister(value, VAR_TYPE_FLOW_INT);
820  ld->flowint[ld->flowints++] = idx;
821  SCLogDebug("script uses flowint %u with script id %u", idx, ld->flowints - 1);
822  }
823  }
824  lua_pop(luastate, 1);
825  continue;
826  } else if (strcmp(k, "bytevar") == 0) {
827  if (lua_istable(luastate, -1)) {
828  lua_pushnil(luastate);
829  while (lua_next(luastate, -2) != 0) {
830  /* value at -1, key is at -2 which we ignore */
831  const char *value = lua_tostring(luastate, -1);
832  SCLogDebug("value %s", value);
833  /* removes 'value'; keeps 'key' for next iteration */
834  lua_pop(luastate, 1);
835 
836  if (ld->bytevars == DETECT_LUAJIT_MAX_BYTEVARS) {
837  SCLogError("too many bytevars registered");
838  goto error;
839  }
840 
842  if (!DetectByteRetrieveSMVar(value, s, &idx)) {
843  SCLogError("Unknown byte_extract or byte_math var "
844  "requested by lua script - %s",
845  value);
846  goto error;
847  }
848  ld->bytevar[ld->bytevars++] = idx;
849  SCLogDebug("script uses bytevar %u with script id %u", idx, ld->bytevars - 1);
850  }
851  }
852  lua_pop(luastate, 1);
853  continue;
854  }
855 
856  v = lua_tostring(luastate, -1);
857  lua_pop(luastate, 1);
858  if (v == NULL)
859  continue;
860 
861  SCLogDebug("k='%s', v='%s'", k, v);
862  if (strcmp(k, "packet") == 0 && strcmp(v, "true") == 0) {
863  ld->flags |= DATATYPE_PACKET;
864  } else if (strcmp(k, "payload") == 0 && strcmp(v, "true") == 0) {
865  ld->flags |= DATATYPE_PAYLOAD;
866  } else if (strcmp(k, "buffer") == 0 && strcmp(v, "true") == 0) {
867  ld->flags |= DATATYPE_BUFFER;
868 
869  ld->buffername = SCStrdup("buffer");
870  if (ld->buffername == NULL) {
871  SCLogError("alloc error");
872  goto error;
873  }
874  } else if (strcmp(k, "stream") == 0 && strcmp(v, "true") == 0) {
875  ld->flags |= DATATYPE_STREAM;
876 
877  ld->buffername = SCStrdup("stream");
878  if (ld->buffername == NULL) {
879  SCLogError("alloc error");
880  goto error;
881  }
882 
883  } else if (strncmp(k, "http", 4) == 0 && strcmp(v, "true") == 0) {
884  if (ld->alproto != ALPROTO_UNKNOWN && ld->alproto != ALPROTO_HTTP1) {
885  SCLogError(
886  "can just inspect script against one app layer proto like HTTP at a time");
887  goto error;
888  }
889  if (ld->flags != 0) {
890  SCLogError("when inspecting HTTP buffers only a single buffer can be inspected");
891  goto error;
892  }
893 
894  /* http types */
895  ld->alproto = ALPROTO_HTTP1;
896 
897  if (strcmp(k, "http.uri") == 0)
898  ld->flags |= DATATYPE_HTTP_URI;
899 
900  else if (strcmp(k, "http.uri.raw") == 0)
901  ld->flags |= DATATYPE_HTTP_URI_RAW;
902 
903  else if (strcmp(k, "http.request_line") == 0)
904  ld->flags |= DATATYPE_HTTP_REQUEST_LINE;
905 
906  else if (strcmp(k, "http.request_headers") == 0)
907  ld->flags |= DATATYPE_HTTP_REQUEST_HEADERS;
908 
909  else if (strcmp(k, "http.request_headers.raw") == 0)
910  ld->flags |= DATATYPE_HTTP_REQUEST_HEADERS_RAW;
911 
912  else if (strcmp(k, "http.request_cookie") == 0)
913  ld->flags |= DATATYPE_HTTP_REQUEST_COOKIE;
914 
915  else if (strcmp(k, "http.request_user_agent") == 0)
916  ld->flags |= DATATYPE_HTTP_REQUEST_UA;
917 
918  else if (strcmp(k, "http.request_body") == 0)
919  ld->flags |= DATATYPE_HTTP_REQUEST_BODY;
920 
921  else if (strcmp(k, "http.response_body") == 0)
922  ld->flags |= DATATYPE_HTTP_RESPONSE_BODY;
923 
924  else if (strcmp(k, "http.response_cookie") == 0)
925  ld->flags |= DATATYPE_HTTP_RESPONSE_COOKIE;
926 
927  else if (strcmp(k, "http.response_headers") == 0)
928  ld->flags |= DATATYPE_HTTP_RESPONSE_HEADERS;
929 
930  else if (strcmp(k, "http.response_headers.raw") == 0)
931  ld->flags |= DATATYPE_HTTP_RESPONSE_HEADERS_RAW;
932 
933  else {
934  SCLogError("unsupported http data type %s", k);
935  goto error;
936  }
937 
938  ld->buffername = SCStrdup(k);
939  if (ld->buffername == NULL) {
940  SCLogError("alloc error");
941  goto error;
942  }
943  } else if (strncmp(k, "dns", 3) == 0 && strcmp(v, "true") == 0) {
944 
945  ld->alproto = ALPROTO_DNS;
946 
947  if (strcmp(k, "dns.rrname") == 0)
948  ld->flags |= DATATYPE_DNS_RRNAME;
949  else if (strcmp(k, "dns.request") == 0)
950  ld->flags |= DATATYPE_DNS_REQUEST;
951  else if (strcmp(k, "dns.response") == 0)
952  ld->flags |= DATATYPE_DNS_RESPONSE;
953 
954  else {
955  SCLogError("unsupported dns data type %s", k);
956  goto error;
957  }
958  ld->buffername = SCStrdup(k);
959  if (ld->buffername == NULL) {
960  SCLogError("alloc error");
961  goto error;
962  }
963  } else if (strncmp(k, "tls", 3) == 0 && strcmp(v, "true") == 0) {
964 
965  ld->alproto = ALPROTO_TLS;
966 
967  ld->flags |= DATATYPE_TLS;
968 
969  } else if (strncmp(k, "ssh", 3) == 0 && strcmp(v, "true") == 0) {
970 
971  ld->alproto = ALPROTO_SSH;
972 
973  ld->flags |= DATATYPE_SSH;
974 
975  } else if (strncmp(k, "smtp", 4) == 0 && strcmp(v, "true") == 0) {
976 
977  ld->alproto = ALPROTO_SMTP;
978 
979  ld->flags |= DATATYPE_SMTP;
980 
981  } else if (strncmp(k, "dnp3", 4) == 0 && strcmp(v, "true") == 0) {
982 
983  ld->alproto = ALPROTO_DNP3;
984 
985  ld->flags |= DATATYPE_DNP3;
986 
987  } else {
988  SCLogError("unsupported data type %s", k);
989  goto error;
990  }
991  }
992 
993  /* pop the table */
994  lua_pop(luastate, 1);
995  lua_close(luastate);
996  return 0;
997 error:
998  lua_close(luastate);
999  return -1;
1000 }
1001 
1002 /**
1003  * \brief this function is used to parse lua options
1004  * \brief into the current signature
1005  *
1006  * \param de_ctx pointer to the Detection Engine Context
1007  * \param s pointer to the Current Signature
1008  * \param str pointer to the user provided "lua" option
1009  *
1010  * \retval 0 on Success
1011  * \retval -1 on Failure
1012  */
1013 static int DetectLuaSetup (DetectEngineCtx *de_ctx, Signature *s, const char *str)
1014 {
1015  DetectLuaData *lua = NULL;
1016  SigMatch *sm = NULL;
1017 
1018  /* First check if Lua rules are enabled, by default Lua in rules
1019  * is disabled. */
1020  int enabled = 0;
1021  (void)ConfGetBool("security.lua.allow-rules", &enabled);
1022  if (!enabled) {
1023  SCLogError("Lua rules disabled by security configuration: security.lua.allow-rules");
1024  goto error;
1025  }
1026 
1027  lua = DetectLuaParse(de_ctx, str);
1028  if (lua == NULL)
1029  goto error;
1030 
1031  if (DetectLuaSetupPrime(de_ctx, lua, s) == -1) {
1032  goto error;
1033  }
1034 
1035  lua->thread_ctx_id = DetectRegisterThreadCtxFuncs(de_ctx, "lua",
1036  DetectLuaThreadInit, (void *)lua,
1037  DetectLuaThreadFree, 0);
1038  if (lua->thread_ctx_id == -1)
1039  goto error;
1040 
1041  if (lua->alproto != ALPROTO_UNKNOWN) {
1042  if (s->alproto != ALPROTO_UNKNOWN && !AppProtoEquals(s->alproto, lua->alproto)) {
1043  goto error;
1044  }
1045  s->alproto = lua->alproto;
1046  }
1047 
1048  /* Okay so far so good, lets get this into a SigMatch
1049  * and put it in the Signature. */
1050  sm = SigMatchAlloc();
1051  if (sm == NULL)
1052  goto error;
1053 
1054  sm->type = DETECT_LUA;
1055  sm->ctx = (SigMatchCtx *)lua;
1056 
1057  int list = -1;
1058  if (lua->alproto == ALPROTO_UNKNOWN) {
1059  if (lua->flags & DATATYPE_STREAM)
1060  list = DETECT_SM_LIST_PMATCH;
1061  else {
1062  if (lua->flags & DATATYPE_BUFFER) {
1063  if (DetectBufferGetActiveList(de_ctx, s) != -1) {
1064  list = s->init_data->list;
1065  } else {
1066  SCLogError("Lua and sticky buffer failure");
1067  goto error;
1068  }
1069  } else
1070  list = DETECT_SM_LIST_MATCH;
1071  }
1072 
1073  } else if (lua->alproto == ALPROTO_HTTP1) {
1074  if (lua->flags & DATATYPE_HTTP_RESPONSE_BODY) {
1075  list = DetectBufferTypeGetByName("file_data");
1076  } else if (lua->flags & DATATYPE_HTTP_REQUEST_BODY) {
1077  list = DetectBufferTypeGetByName("http_client_body");
1078  } else if (lua->flags & DATATYPE_HTTP_URI) {
1079  list = DetectBufferTypeGetByName("http_uri");
1080  } else if (lua->flags & DATATYPE_HTTP_URI_RAW) {
1081  list = DetectBufferTypeGetByName("http_raw_uri");
1082  } else if (lua->flags & DATATYPE_HTTP_REQUEST_COOKIE ||
1083  lua->flags & DATATYPE_HTTP_RESPONSE_COOKIE)
1084  {
1085  list = DetectBufferTypeGetByName("http_cookie");
1086  } else if (lua->flags & DATATYPE_HTTP_REQUEST_UA) {
1087  list = DetectBufferTypeGetByName("http_user_agent");
1088  } else if (lua->flags & (DATATYPE_HTTP_REQUEST_HEADERS|DATATYPE_HTTP_RESPONSE_HEADERS)) {
1089  list = DetectBufferTypeGetByName("http_header");
1090  } else if (lua->flags & (DATATYPE_HTTP_REQUEST_HEADERS_RAW|DATATYPE_HTTP_RESPONSE_HEADERS_RAW)) {
1091  list = DetectBufferTypeGetByName("http_raw_header");
1092  } else {
1093  list = DetectBufferTypeGetByName("http_request_line");
1094  }
1095  } else if (lua->alproto == ALPROTO_DNS) {
1096  if (lua->flags & DATATYPE_DNS_RRNAME) {
1097  list = DetectBufferTypeGetByName("dns_query");
1098  } else if (lua->flags & DATATYPE_DNS_REQUEST) {
1099  list = DetectBufferTypeGetByName("dns_request");
1100  } else if (lua->flags & DATATYPE_DNS_RESPONSE) {
1101  list = DetectBufferTypeGetByName("dns_response");
1102  }
1103  } else if (lua->alproto == ALPROTO_TLS) {
1104  list = DetectBufferTypeGetByName("tls_generic");
1105  } else if (lua->alproto == ALPROTO_SSH) {
1106  list = DetectBufferTypeGetByName("ssh_banner");
1107  } else if (lua->alproto == ALPROTO_SMTP) {
1108  list = g_smtp_generic_list_id;
1109  } else if (lua->alproto == ALPROTO_DNP3) {
1110  list = DetectBufferTypeGetByName("dnp3");
1111  } else {
1112  SCLogError("lua can't be used with protocol %s", AppLayerGetProtoName(lua->alproto));
1113  goto error;
1114  }
1115 
1116  if (list == -1) {
1117  SCLogError("lua can't be used with protocol %s", AppLayerGetProtoName(lua->alproto));
1118  goto error;
1119  }
1120 
1121  SigMatchAppendSMToList(s, sm, list);
1122 
1123  return 0;
1124 
1125 error:
1126  if (lua != NULL)
1127  DetectLuaFree(de_ctx, lua);
1128  if (sm != NULL)
1129  SCFree(sm);
1130  return -1;
1131 }
1132 
1133 /** \brief post-sig parse function to set the sid,rev,gid into the
1134  * ctx, as this isn't available yet during parsing.
1135  */
1137 {
1138  int i;
1139  SigMatch *sm;
1140 
1141  for (i = 0; i < DETECT_SM_LIST_MAX; i++) {
1142  for (sm = s->init_data->smlists[i]; sm != NULL; sm = sm->next) {
1143  if (sm->type != DETECT_LUA)
1144  continue;
1145 
1146  DetectLuaData *ld = (DetectLuaData *)sm->ctx;
1147  ld->sid = s->id;
1148  ld->rev = s->rev;
1149  ld->gid = s->gid;
1150  }
1151  }
1152 }
1153 
1154 /**
1155  * \brief this function will free memory associated with DetectLuaData
1156  *
1157  * \param ptr pointer to DetectLuaData
1158  */
1159 static void DetectLuaFree(DetectEngineCtx *de_ctx, void *ptr)
1160 {
1161  if (ptr != NULL) {
1162  DetectLuaData *lua = (DetectLuaData *)ptr;
1163 
1164  if (lua->buffername)
1165  SCFree(lua->buffername);
1166  if (lua->filename)
1167  SCFree(lua->filename);
1168 
1169  for (uint16_t i = 0; i < lua->flowints; i++) {
1170  VarNameStoreUnregister(lua->flowint[i], VAR_TYPE_FLOW_INT);
1171  }
1172  for (uint16_t i = 0; i < lua->flowvars; i++) {
1173  VarNameStoreUnregister(lua->flowvar[i], VAR_TYPE_FLOW_VAR);
1174  }
1175 
1177 
1178  SCFree(lua);
1179  }
1180 }
1181 
1182 #ifdef UNITTESTS
1183 #include "detect-engine-alert.h"
1184 
1185 /** \test http buffer */
1186 static int LuaMatchTest01(void)
1187 {
1188  ConfSetFinal("security.lua.allow-rules", "true");
1189 
1190  const char script[] =
1191  "function init (args)\n"
1192  " local needs = {}\n"
1193  " needs[\"http.request_headers\"] = tostring(true)\n"
1194  " needs[\"flowvar\"] = {\"cnt\"}\n"
1195  " return needs\n"
1196  "end\n"
1197  "\n"
1198  "function match(args)\n"
1199  " a = ScFlowvarGet(0)\n"
1200  " if a then\n"
1201  " a = tostring(tonumber(a)+1)\n"
1202  " print (a)\n"
1203  " ScFlowvarSet(0, a, #a)\n"
1204  " else\n"
1205  " a = tostring(1)\n"
1206  " print (a)\n"
1207  " ScFlowvarSet(0, a, #a)\n"
1208  " end\n"
1209  " \n"
1210  " print (\"pre check: \" .. (a))\n"
1211  " if tonumber(a) == 2 then\n"
1212  " print \"match\"\n"
1213  " return 1\n"
1214  " end\n"
1215  " return 0\n"
1216  "end\n"
1217  "return 0\n";
1218  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1219  uint8_t httpbuf1[] =
1220  "POST / HTTP/1.1\r\n"
1221  "Host: www.emergingthreats.net\r\n\r\n";
1222  uint8_t httpbuf2[] =
1223  "POST / HTTP/1.1\r\n"
1224  "Host: www.openinfosecfoundation.org\r\n\r\n";
1225  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1226  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1227  TcpSession ssn;
1228  Flow f;
1229  ThreadVars th_v;
1230  DetectEngineThreadCtx *det_ctx;
1231 
1233 
1234  ut_script = script;
1235 
1236  memset(&th_v, 0, sizeof(th_v));
1237  memset(&f, 0, sizeof(f));
1238  memset(&ssn, 0, sizeof(ssn));
1239 
1240  Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1241  Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1242 
1243  FLOW_INITIALIZE(&f);
1244  f.protoctx = (void *)&ssn;
1245  f.proto = IPPROTO_TCP;
1246  f.flags |= FLOW_IPV4;
1247  f.alproto = ALPROTO_HTTP1;
1248 
1249  p1->flow = &f;
1253  p2->flow = &f;
1257 
1258  StreamTcpInitConfig(true);
1259 
1262  de_ctx->flags |= DE_QUIET;
1263 
1265  FAIL_IF_NULL(s);
1266 
1268  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1269 
1270  int r = AppLayerParserParse(
1271  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
1272  FAIL_IF(r != 0);
1273  HtpState *http_state = f.alstate;
1274  FAIL_IF_NULL(http_state);
1275 
1276  /* do detect for p1 */
1277  SCLogDebug("inspecting p1");
1278  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1279 
1280  FAIL_IF(PacketAlertCheck(p1, 1));
1281 
1282  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1283  FAIL_IF(r != 0);
1284 
1285  /* do detect for p2 */
1286  SCLogDebug("inspecting p2");
1287  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1288 
1289  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
1290 
1291  uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_VAR);
1292  FAIL_IF(id == 0);
1293 
1294  FlowVar *fv = FlowVarGet(&f, id);
1295  FAIL_IF_NULL(fv);
1296 
1297  FAIL_IF(fv->data.fv_str.value_len != 1);
1298 
1299  FAIL_IF(memcmp(fv->data.fv_str.value, "2", 1) != 0);
1300 
1303 
1304  StreamTcpFreeConfig(true);
1305  FLOW_DESTROY(&f);
1306  UTHFreePackets(&p1, 1);
1307  UTHFreePackets(&p2, 1);
1308  PASS;
1309 }
1310 
1311 static int LuaMatchTest01a(void)
1312 {
1313  const char script[] = "function init (args)\n"
1314  " local needs = {}\n"
1315  " needs[\"http.request_headers\"] = tostring(true)\n"
1316  " needs[\"flowvar\"] = {\"cnt\"}\n"
1317  " return needs\n"
1318  "end\n"
1319  "\n"
1320  "function match(args)\n"
1321  " a = SCFlowvarGet(0)\n"
1322  " if a then\n"
1323  " a = tostring(tonumber(a)+1)\n"
1324  " print (a)\n"
1325  " SCFlowvarSet(0, a, #a)\n"
1326  " else\n"
1327  " a = tostring(1)\n"
1328  " print (a)\n"
1329  " SCFlowvarSet(0, a, #a)\n"
1330  " end\n"
1331  " \n"
1332  " print (\"pre check: \" .. (a))\n"
1333  " if tonumber(a) == 2 then\n"
1334  " print \"match\"\n"
1335  " return 1\n"
1336  " end\n"
1337  " return 0\n"
1338  "end\n"
1339  "return 0\n";
1340  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1341  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1342  "Host: www.emergingthreats.net\r\n\r\n";
1343  uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1344  "Host: www.openinfosecfoundation.org\r\n\r\n";
1345  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1346  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1347  TcpSession ssn;
1348  Flow f;
1349  ThreadVars th_v;
1350  DetectEngineThreadCtx *det_ctx;
1351 
1353 
1354  ut_script = script;
1355 
1356  memset(&th_v, 0, sizeof(th_v));
1357  memset(&f, 0, sizeof(f));
1358  memset(&ssn, 0, sizeof(ssn));
1359 
1360  Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1361  Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1362 
1363  FLOW_INITIALIZE(&f);
1364  f.protoctx = (void *)&ssn;
1365  f.proto = IPPROTO_TCP;
1366  f.flags |= FLOW_IPV4;
1367  f.alproto = ALPROTO_HTTP1;
1368 
1369  p1->flow = &f;
1373  p2->flow = &f;
1377 
1378  StreamTcpInitConfig(true);
1379 
1382  de_ctx->flags |= DE_QUIET;
1383 
1385  FAIL_IF_NULL(s);
1386 
1388  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1389 
1390  int r = AppLayerParserParse(
1391  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
1392  FAIL_IF(r != 0);
1393 
1394  HtpState *http_state = f.alstate;
1395  FAIL_IF_NULL(http_state);
1396 
1397  /* do detect for p1 */
1398  SCLogDebug("inspecting p1");
1399  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1400 
1401  FAIL_IF(PacketAlertCheck(p1, 1));
1402 
1403  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1404  FAIL_IF(r != 0);
1405  /* do detect for p2 */
1406  SCLogDebug("inspecting p2");
1407  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1408 
1409  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
1410 
1411  uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_VAR);
1412  FAIL_IF(id == 0);
1413 
1414  FlowVar *fv = FlowVarGet(&f, id);
1415  FAIL_IF_NULL(fv);
1416 
1417  FAIL_IF(fv->data.fv_str.value_len != 1);
1418 
1419  FAIL_IF(memcmp(fv->data.fv_str.value, "2", 1) != 0);
1420 
1423 
1424  StreamTcpFreeConfig(true);
1425  FLOW_DESTROY(&f);
1426  UTHFreePackets(&p1, 1);
1427  UTHFreePackets(&p2, 1);
1428  PASS;
1429 }
1430 
1431 /** \test payload buffer */
1432 static int LuaMatchTest02(void)
1433 {
1434  const char script[] = "function init (args)\n"
1435  " local needs = {}\n"
1436  " needs[\"payload\"] = tostring(true)\n"
1437  " needs[\"flowvar\"] = {\"cnt\"}\n"
1438  " return needs\n"
1439  "end\n"
1440  "\n"
1441  "function match(args)\n"
1442  " a = ScFlowvarGet(0)\n"
1443  " if a then\n"
1444  " a = tostring(tonumber(a)+1)\n"
1445  " print (a)\n"
1446  " ScFlowvarSet(0, a, #a)\n"
1447  " else\n"
1448  " a = tostring(1)\n"
1449  " print (a)\n"
1450  " ScFlowvarSet(0, a, #a)\n"
1451  " end\n"
1452  " \n"
1453  " print (\"pre check: \" .. (a))\n"
1454  " if tonumber(a) == 2 then\n"
1455  " print \"match\"\n"
1456  " return 1\n"
1457  " end\n"
1458  " return 0\n"
1459  "end\n"
1460  "return 0\n";
1461  char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1462  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1463  "Host: www.emergingthreats.net\r\n\r\n";
1464  uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1465  "Host: www.openinfosecfoundation.org\r\n\r\n";
1466  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1467  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1468  TcpSession ssn;
1469  Flow f;
1470  ThreadVars th_v;
1471  DetectEngineThreadCtx *det_ctx;
1472 
1473  ut_script = script;
1474 
1475  memset(&th_v, 0, sizeof(th_v));
1476  memset(&f, 0, sizeof(f));
1477  memset(&ssn, 0, sizeof(ssn));
1478 
1479  Packet *p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP);
1480  Packet *p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP);
1481 
1482  FLOW_INITIALIZE(&f);
1483  f.protoctx = (void *)&ssn;
1484  f.proto = IPPROTO_TCP;
1485  f.flags |= FLOW_IPV4;
1486  f.alproto = ALPROTO_HTTP1;
1487 
1488  p1->flow = &f;
1492  p2->flow = &f;
1496 
1497  StreamTcpInitConfig(true);
1498 
1501  de_ctx->flags |= DE_QUIET;
1502 
1504  FAIL_IF_NULL(s);
1505 
1507  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1508 
1509  /* do detect for p1 */
1510  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1511 
1512  FAIL_IF(PacketAlertCheck(p1, 1));
1513 
1514  /* do detect for p2 */
1515  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1516 
1517  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
1518 
1519  uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_VAR);
1520  FAIL_IF(id == 0);
1521 
1522  FlowVar *fv = FlowVarGet(&f, id);
1523  FAIL_IF_NULL(fv);
1524 
1525  FAIL_IF(fv->data.fv_str.value_len != 1);
1526 
1527  FAIL_IF(memcmp(fv->data.fv_str.value, "2", 1) != 0);
1528 
1530 
1531  StreamTcpFreeConfig(true);
1532  FLOW_DESTROY(&f);
1533  UTHFreePackets(&p1, 1);
1534  UTHFreePackets(&p2, 1);
1535  PASS;
1536 }
1537 
1538 /** \test payload buffer */
1539 static int LuaMatchTest02a(void)
1540 {
1541  const char script[] = "function init (args)\n"
1542  " local needs = {}\n"
1543  " needs[\"payload\"] = tostring(true)\n"
1544  " needs[\"flowvar\"] = {\"cnt\"}\n"
1545  " return needs\n"
1546  "end\n"
1547  "\n"
1548  "function match(args)\n"
1549  " a = SCFlowvarGet(0)\n"
1550  " if a then\n"
1551  " a = tostring(tonumber(a)+1)\n"
1552  " print (a)\n"
1553  " SCFlowvarSet(0, a, #a)\n"
1554  " else\n"
1555  " a = tostring(1)\n"
1556  " print (a)\n"
1557  " SCFlowvarSet(0, a, #a)\n"
1558  " end\n"
1559  " \n"
1560  " print (\"pre check: \" .. (a))\n"
1561  " if tonumber(a) == 2 then\n"
1562  " print \"match\"\n"
1563  " return 1\n"
1564  " end\n"
1565  " return 0\n"
1566  "end\n"
1567  "return 0\n";
1568  char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1569  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1570  "Host: www.emergingthreats.net\r\n\r\n";
1571  uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1572  "Host: www.openinfosecfoundation.org\r\n\r\n";
1573  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1574  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1575  TcpSession ssn;
1576  Flow f;
1577  ThreadVars th_v;
1578  DetectEngineThreadCtx *det_ctx;
1579 
1580  ut_script = script;
1581 
1582  memset(&th_v, 0, sizeof(th_v));
1583  memset(&f, 0, sizeof(f));
1584  memset(&ssn, 0, sizeof(ssn));
1585 
1586  Packet *p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP);
1587  Packet *p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP);
1588 
1589  FLOW_INITIALIZE(&f);
1590  f.protoctx = (void *)&ssn;
1591  f.proto = IPPROTO_TCP;
1592  f.flags |= FLOW_IPV4;
1593  f.alproto = ALPROTO_HTTP1;
1594 
1595  p1->flow = &f;
1599  p2->flow = &f;
1603 
1604  StreamTcpInitConfig(true);
1605 
1608  de_ctx->flags |= DE_QUIET;
1609 
1611  FAIL_IF_NULL(s);
1612 
1614  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1615 
1616  /* do detect for p1 */
1617  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1618  FAIL_IF(PacketAlertCheck(p1, 1));
1619 
1620  /* do detect for p2 */
1621  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1622 
1623  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
1624 
1625  uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_VAR);
1626  FAIL_IF(id == 0);
1627 
1628  FlowVar *fv = FlowVarGet(&f, id);
1629  FAIL_IF_NULL(fv);
1630 
1631  FAIL_IF(fv->data.fv_str.value_len != 1);
1632 
1633  FAIL_IF(memcmp(fv->data.fv_str.value, "2", 1) != 0);
1634 
1636 
1637  StreamTcpFreeConfig(true);
1638  FLOW_DESTROY(&f);
1639  UTHFreePackets(&p1, 1);
1640  UTHFreePackets(&p2, 1);
1641  PASS;
1642 }
1643 
1644 /** \test packet buffer */
1645 static int LuaMatchTest03(void)
1646 {
1647  const char script[] = "function init (args)\n"
1648  " local needs = {}\n"
1649  " needs[\"packet\"] = tostring(true)\n"
1650  " needs[\"flowvar\"] = {\"cnt\"}\n"
1651  " return needs\n"
1652  "end\n"
1653  "\n"
1654  "function match(args)\n"
1655  " a = ScFlowvarGet(0)\n"
1656  " if a then\n"
1657  " a = tostring(tonumber(a)+1)\n"
1658  " print (a)\n"
1659  " ScFlowvarSet(0, a, #a)\n"
1660  " else\n"
1661  " a = tostring(1)\n"
1662  " print (a)\n"
1663  " ScFlowvarSet(0, a, #a)\n"
1664  " end\n"
1665  " \n"
1666  " print (\"pre check: \" .. (a))\n"
1667  " if tonumber(a) == 2 then\n"
1668  " print \"match\"\n"
1669  " return 1\n"
1670  " end\n"
1671  " return 0\n"
1672  "end\n"
1673  "return 0\n";
1674  char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1675  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1676  "Host: www.emergingthreats.net\r\n\r\n";
1677  uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1678  "Host: www.openinfosecfoundation.org\r\n\r\n";
1679  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1680  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1681  TcpSession ssn;
1682  Flow f;
1683  ThreadVars th_v;
1684  DetectEngineThreadCtx *det_ctx;
1685 
1686  ut_script = script;
1687 
1688  memset(&th_v, 0, sizeof(th_v));
1689  memset(&f, 0, sizeof(f));
1690  memset(&ssn, 0, sizeof(ssn));
1691 
1692  Packet *p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP);
1693  Packet *p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP);
1694 
1695  FLOW_INITIALIZE(&f);
1696  f.protoctx = (void *)&ssn;
1697  f.proto = IPPROTO_TCP;
1698  f.flags |= FLOW_IPV4;
1699  f.alproto = ALPROTO_HTTP1;
1700 
1701  p1->flow = &f;
1705  p2->flow = &f;
1709 
1710  StreamTcpInitConfig(true);
1711 
1714  de_ctx->flags |= DE_QUIET;
1715 
1717  FAIL_IF_NULL(s);
1718 
1720  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1721 
1722  /* do detect for p1 */
1723  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1724  FAIL_IF(PacketAlertCheck(p1, 1));
1725 
1726  /* do detect for p2 */
1727  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1728 
1729  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
1730 
1731  uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_VAR);
1732  FAIL_IF(id == 0);
1733 
1734  FlowVar *fv = FlowVarGet(&f, id);
1735  FAIL_IF_NULL(fv);
1736 
1737  FAIL_IF(fv->data.fv_str.value_len != 1);
1738 
1739  FAIL_IF(memcmp(fv->data.fv_str.value, "2", 1) != 0);
1740 
1742 
1743  StreamTcpFreeConfig(true);
1744  FLOW_DESTROY(&f);
1745  UTHFreePackets(&p1, 1);
1746  UTHFreePackets(&p2, 1);
1747  PASS;
1748 }
1749 
1750 /** \test packet buffer */
1751 static int LuaMatchTest03a(void)
1752 {
1753  const char script[] = "function init (args)\n"
1754  " local needs = {}\n"
1755  " needs[\"packet\"] = tostring(true)\n"
1756  " needs[\"flowvar\"] = {\"cnt\"}\n"
1757  " return needs\n"
1758  "end\n"
1759  "\n"
1760  "function match(args)\n"
1761  " a = SCFlowvarGet(0)\n"
1762  " if a then\n"
1763  " a = tostring(tonumber(a)+1)\n"
1764  " print (a)\n"
1765  " SCFlowvarSet(0, a, #a)\n"
1766  " else\n"
1767  " a = tostring(1)\n"
1768  " print (a)\n"
1769  " SCFlowvarSet(0, a, #a)\n"
1770  " end\n"
1771  " \n"
1772  " print (\"pre check: \" .. (a))\n"
1773  " if tonumber(a) == 2 then\n"
1774  " print \"match\"\n"
1775  " return 1\n"
1776  " end\n"
1777  " return 0\n"
1778  "end\n"
1779  "return 0\n";
1780  char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1781  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1782  "Host: www.emergingthreats.net\r\n\r\n";
1783  uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1784  "Host: www.openinfosecfoundation.org\r\n\r\n";
1785  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1786  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1787  TcpSession ssn;
1788  Flow f;
1789  ThreadVars th_v;
1790  DetectEngineThreadCtx *det_ctx;
1791 
1792  ut_script = script;
1793 
1794  memset(&th_v, 0, sizeof(th_v));
1795  memset(&f, 0, sizeof(f));
1796  memset(&ssn, 0, sizeof(ssn));
1797 
1798  Packet *p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP);
1799  Packet *p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP);
1800 
1801  FLOW_INITIALIZE(&f);
1802  f.protoctx = (void *)&ssn;
1803  f.proto = IPPROTO_TCP;
1804  f.flags |= FLOW_IPV4;
1805  f.alproto = ALPROTO_HTTP1;
1806 
1807  p1->flow = &f;
1811  p2->flow = &f;
1815 
1816  StreamTcpInitConfig(true);
1817 
1820  de_ctx->flags |= DE_QUIET;
1821 
1823  FAIL_IF_NULL(s);
1824 
1826  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1827 
1828  /* do detect for p1 */
1829  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1830  FAIL_IF(PacketAlertCheck(p1, 1));
1831 
1832  /* do detect for p2 */
1833  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1834  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
1835 
1836  uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_VAR);
1837  FAIL_IF(id == 0);
1838 
1839  FlowVar *fv = FlowVarGet(&f, id);
1840  FAIL_IF_NULL(fv);
1841 
1842  FAIL_IF(fv->data.fv_str.value_len != 1);
1843 
1844  FAIL_IF(memcmp(fv->data.fv_str.value, "2", 1) != 0);
1845 
1847 
1848  StreamTcpFreeConfig(true);
1849  FLOW_DESTROY(&f);
1850  UTHFreePackets(&p1, 1);
1851  UTHFreePackets(&p2, 1);
1852  PASS;
1853 }
1854 
1855 /** \test http buffer, flowints */
1856 static int LuaMatchTest04(void)
1857 {
1858  const char script[] = "function init (args)\n"
1859  " local needs = {}\n"
1860  " needs[\"http.request_headers\"] = tostring(true)\n"
1861  " needs[\"flowint\"] = {\"cnt\"}\n"
1862  " return needs\n"
1863  "end\n"
1864  "\n"
1865  "function match(args)\n"
1866  " print \"inspecting\""
1867  " a = ScFlowintGet(0)\n"
1868  " if a then\n"
1869  " ScFlowintSet(0, a + 1)\n"
1870  " else\n"
1871  " ScFlowintSet(0, 1)\n"
1872  " end\n"
1873  " \n"
1874  " a = ScFlowintGet(0)\n"
1875  " if a == 2 then\n"
1876  " print \"match\"\n"
1877  " return 1\n"
1878  " end\n"
1879  " return 0\n"
1880  "end\n"
1881  "return 0\n";
1882  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1883  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1884  "Host: www.emergingthreats.net\r\n\r\n";
1885  uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1886  "Host: www.openinfosecfoundation.org\r\n\r\n";
1887  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1888  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1889  TcpSession ssn;
1890  Flow f;
1891  ThreadVars th_v;
1892  DetectEngineThreadCtx *det_ctx;
1893 
1895 
1896  ut_script = script;
1897 
1898  memset(&th_v, 0, sizeof(th_v));
1899  memset(&f, 0, sizeof(f));
1900  memset(&ssn, 0, sizeof(ssn));
1901 
1902  Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1903  Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1904 
1905  FLOW_INITIALIZE(&f);
1906  f.protoctx = (void *)&ssn;
1907  f.proto = IPPROTO_TCP;
1908  f.flags |= FLOW_IPV4;
1909  f.alproto = ALPROTO_HTTP1;
1910 
1911  p1->flow = &f;
1915 
1916  p2->flow = &f;
1920 
1921  StreamTcpInitConfig(true);
1922 
1925  de_ctx->flags |= DE_QUIET;
1926 
1928  FAIL_IF_NULL(s);
1929 
1931  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1932 
1933  int r = AppLayerParserParse(
1934  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
1935  FAIL_IF(r != 0);
1936  HtpState *http_state = f.alstate;
1937  FAIL_IF_NULL(http_state);
1938 
1939  /* do detect for p1 */
1940  SCLogInfo("p1");
1941  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1942 
1943  FAIL_IF(PacketAlertCheck(p1, 1));
1944 
1945  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1946  FAIL_IF(r != 0);
1947  /* do detect for p2 */
1948  SCLogInfo("p2");
1949  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1950 
1951  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
1952 
1953  uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_INT);
1954  FAIL_IF(id == 0);
1955 
1956  FlowVar *fv = FlowVarGet(&f, id);
1957  FAIL_IF_NULL(fv);
1958 
1959  FAIL_IF(fv->data.fv_int.value != 2);
1960 
1963 
1964  StreamTcpFreeConfig(true);
1965  FLOW_DESTROY(&f);
1966  UTHFreePackets(&p1, 1);
1967  UTHFreePackets(&p2, 1);
1968  PASS;
1969 }
1970 
1971 /** \test http buffer, flowints */
1972 static int LuaMatchTest04a(void)
1973 {
1974  const char script[] = "function init (args)\n"
1975  " local needs = {}\n"
1976  " needs[\"http.request_headers\"] = tostring(true)\n"
1977  " needs[\"flowint\"] = {\"cnt\"}\n"
1978  " return needs\n"
1979  "end\n"
1980  "\n"
1981  "function match(args)\n"
1982  " print \"inspecting\""
1983  " a = SCFlowintGet(0)\n"
1984  " if a then\n"
1985  " SCFlowintSet(0, a + 1)\n"
1986  " else\n"
1987  " SCFlowintSet(0, 1)\n"
1988  " end\n"
1989  " \n"
1990  " a = SCFlowintGet(0)\n"
1991  " if a == 2 then\n"
1992  " print \"match\"\n"
1993  " return 1\n"
1994  " end\n"
1995  " return 0\n"
1996  "end\n"
1997  "return 0\n";
1998  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1999  uint8_t httpbuf1[] =
2000  "POST / HTTP/1.1\r\n"
2001  "Host: www.emergingthreats.net\r\n\r\n";
2002  uint8_t httpbuf2[] =
2003  "POST / HTTP/1.1\r\n"
2004  "Host: www.openinfosecfoundation.org\r\n\r\n";
2005  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2006  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2007  TcpSession ssn;
2008  Flow f;
2009  ThreadVars th_v;
2010  DetectEngineThreadCtx *det_ctx;
2011 
2013 
2014  ut_script = script;
2015 
2016  memset(&th_v, 0, sizeof(th_v));
2017  memset(&f, 0, sizeof(f));
2018  memset(&ssn, 0, sizeof(ssn));
2019 
2020  Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2021  Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2022 
2023  FLOW_INITIALIZE(&f);
2024  f.protoctx = (void *)&ssn;
2025  f.proto = IPPROTO_TCP;
2026  f.flags |= FLOW_IPV4;
2027  f.alproto = ALPROTO_HTTP1;
2028 
2029  p1->flow = &f;
2033 
2034  p2->flow = &f;
2038 
2039  StreamTcpInitConfig(true);
2040 
2043  de_ctx->flags |= DE_QUIET;
2044 
2046  FAIL_IF_NULL(s);
2047 
2049  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2050 
2051  int r = AppLayerParserParse(
2052  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
2053  FAIL_IF(r != 0);
2054  HtpState *http_state = f.alstate;
2055  FAIL_IF_NULL(http_state);
2056 
2057  /* do detect for p1 */
2058  SCLogInfo("p1");
2059  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
2060 
2061  FAIL_IF(PacketAlertCheck(p1, 1));
2062 
2063  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
2064  FAIL_IF(r != 0);
2065  /* do detect for p2 */
2066  SCLogInfo("p2");
2067  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
2068 
2069  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
2070 
2071  uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_INT);
2072  FAIL_IF(id == 0);
2073 
2074  FlowVar *fv = FlowVarGet(&f, id);
2075  FAIL_IF_NULL(fv);
2076 
2077  FAIL_IF(fv->data.fv_int.value != 2);
2078 
2081 
2082  StreamTcpFreeConfig(true);
2083  FLOW_DESTROY(&f);
2084  UTHFreePackets(&p1, 1);
2085  UTHFreePackets(&p2, 1);
2086  PASS;
2087 }
2088 
2089 /** \test http buffer, flowints */
2090 static int LuaMatchTest05(void)
2091 {
2092  const char script[] = "function init (args)\n"
2093  " local needs = {}\n"
2094  " needs[\"http.request_headers\"] = tostring(true)\n"
2095  " needs[\"flowint\"] = {\"cnt\"}\n"
2096  " return needs\n"
2097  "end\n"
2098  "\n"
2099  "function match(args)\n"
2100  " print \"inspecting\""
2101  " a = ScFlowintIncr(0)\n"
2102  " if a == 2 then\n"
2103  " print \"match\"\n"
2104  " return 1\n"
2105  " end\n"
2106  " return 0\n"
2107  "end\n"
2108  "return 0\n";
2109  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
2110  uint8_t httpbuf1[] =
2111  "POST / HTTP/1.1\r\n"
2112  "Host: www.emergingthreats.net\r\n\r\n";
2113  uint8_t httpbuf2[] =
2114  "POST / HTTP/1.1\r\n"
2115  "Host: www.openinfosecfoundation.org\r\n\r\n";
2116  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2117  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2118  TcpSession ssn;
2119  Flow f;
2120  ThreadVars th_v;
2121  DetectEngineThreadCtx *det_ctx;
2122 
2124 
2125  ut_script = script;
2126 
2127  memset(&th_v, 0, sizeof(th_v));
2128  memset(&f, 0, sizeof(f));
2129  memset(&ssn, 0, sizeof(ssn));
2130 
2131  Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2132  Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2133 
2134  FLOW_INITIALIZE(&f);
2135  f.protoctx = (void *)&ssn;
2136  f.proto = IPPROTO_TCP;
2137  f.flags |= FLOW_IPV4;
2138  f.alproto = ALPROTO_HTTP1;
2139 
2140  p1->flow = &f;
2144 
2145  p2->flow = &f;
2149 
2150  StreamTcpInitConfig(true);
2151 
2154  de_ctx->flags |= DE_QUIET;
2155 
2157  FAIL_IF_NULL(s);
2158 
2160  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2161 
2162  int r = AppLayerParserParse(
2163  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
2164  FAIL_IF(r != 0);
2165  HtpState *http_state = f.alstate;
2166  FAIL_IF_NULL(http_state);
2167 
2168  /* do detect for p1 */
2169  SCLogInfo("p1");
2170  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
2171 
2172  FAIL_IF(PacketAlertCheck(p1, 1));
2173 
2174  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
2175  FAIL_IF(r != 0);
2176  /* do detect for p2 */
2177  SCLogInfo("p2");
2178  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
2179 
2180  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
2181 
2182  uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_INT);
2183  FAIL_IF(id == 0);
2184 
2185  FlowVar *fv = FlowVarGet(&f, id);
2186  FAIL_IF_NULL(fv);
2187 
2188  FAIL_IF(fv->data.fv_int.value != 2);
2189 
2192 
2193  StreamTcpFreeConfig(true);
2194  FLOW_DESTROY(&f);
2195  UTHFreePackets(&p1, 1);
2196  UTHFreePackets(&p2, 1);
2197  PASS;
2198 }
2199 
2200 /** \test http buffer, flowints */
2201 static int LuaMatchTest05a(void)
2202 {
2203  const char script[] = "function init (args)\n"
2204  " local needs = {}\n"
2205  " needs[\"http.request_headers\"] = tostring(true)\n"
2206  " needs[\"flowint\"] = {\"cnt\"}\n"
2207  " return needs\n"
2208  "end\n"
2209  "\n"
2210  "function match(args)\n"
2211  " print \"inspecting\""
2212  " a = SCFlowintIncr(0)\n"
2213  " if a == 2 then\n"
2214  " print \"match\"\n"
2215  " return 1\n"
2216  " end\n"
2217  " return 0\n"
2218  "end\n"
2219  "return 0\n";
2220  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
2221  uint8_t httpbuf1[] =
2222  "POST / HTTP/1.1\r\n"
2223  "Host: www.emergingthreats.net\r\n\r\n";
2224  uint8_t httpbuf2[] =
2225  "POST / HTTP/1.1\r\n"
2226  "Host: www.openinfosecfoundation.org\r\n\r\n";
2227  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2228  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2229  TcpSession ssn;
2230  Flow f;
2231  ThreadVars th_v;
2232  DetectEngineThreadCtx *det_ctx;
2233 
2235 
2236  ut_script = script;
2237 
2238  memset(&th_v, 0, sizeof(th_v));
2239  memset(&f, 0, sizeof(f));
2240  memset(&ssn, 0, sizeof(ssn));
2241 
2242  Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2243  Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2244 
2245  FLOW_INITIALIZE(&f);
2246  f.protoctx = (void *)&ssn;
2247  f.proto = IPPROTO_TCP;
2248  f.flags |= FLOW_IPV4;
2249  f.alproto = ALPROTO_HTTP1;
2250 
2251  p1->flow = &f;
2255 
2256  p2->flow = &f;
2260 
2261  StreamTcpInitConfig(true);
2262 
2265  de_ctx->flags |= DE_QUIET;
2266 
2268  FAIL_IF_NULL(s);
2269 
2271  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2272 
2273  int r = AppLayerParserParse(
2274  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
2275  FAIL_IF(r != 0);
2276  HtpState *http_state = f.alstate;
2277  FAIL_IF_NULL(http_state);
2278 
2279  /* do detect for p1 */
2280  SCLogInfo("p1");
2281  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
2282 
2283  FAIL_IF(PacketAlertCheck(p1, 1));
2284 
2285  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
2286  FAIL_IF(r != 0);
2287  /* do detect for p2 */
2288  SCLogInfo("p2");
2289  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
2290 
2291  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
2292 
2293  uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_INT);
2294  FAIL_IF(id == 0);
2295 
2296  FlowVar *fv = FlowVarGet(&f, id);
2297  FAIL_IF_NULL(fv);
2298 
2299  FAIL_IF(fv->data.fv_int.value != 2);
2300 
2303 
2304  StreamTcpFreeConfig(true);
2305  FLOW_DESTROY(&f);
2306  UTHFreePackets(&p1, 1);
2307  UTHFreePackets(&p2, 1);
2308  PASS;
2309 }
2310 
2311 /** \test http buffer, flowints */
2312 static int LuaMatchTest06(void)
2313 {
2314  const char script[] = "function init (args)\n"
2315  " local needs = {}\n"
2316  " needs[\"http.request_headers\"] = tostring(true)\n"
2317  " needs[\"flowint\"] = {\"cnt\"}\n"
2318  " return needs\n"
2319  "end\n"
2320  "\n"
2321  "function match(args)\n"
2322  " print \"inspecting\""
2323  " a = ScFlowintGet(0)\n"
2324  " if a == nil then\n"
2325  " print \"new var set to 2\""
2326  " ScFlowintSet(0, 2)\n"
2327  " end\n"
2328  " a = ScFlowintDecr(0)\n"
2329  " if a == 0 then\n"
2330  " print \"match\"\n"
2331  " return 1\n"
2332  " end\n"
2333  " return 0\n"
2334  "end\n"
2335  "return 0\n";
2336  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
2337  uint8_t httpbuf1[] =
2338  "POST / HTTP/1.1\r\n"
2339  "Host: www.emergingthreats.net\r\n\r\n";
2340  uint8_t httpbuf2[] =
2341  "POST / HTTP/1.1\r\n"
2342  "Host: www.openinfosecfoundation.org\r\n\r\n";
2343  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2344  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2345  TcpSession ssn;
2346  Flow f;
2347  ThreadVars th_v;
2348  DetectEngineThreadCtx *det_ctx;
2349 
2351 
2352  ut_script = script;
2353 
2354  memset(&th_v, 0, sizeof(th_v));
2355  memset(&f, 0, sizeof(f));
2356  memset(&ssn, 0, sizeof(ssn));
2357 
2358  Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2359  Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2360 
2361  FLOW_INITIALIZE(&f);
2362  f.protoctx = (void *)&ssn;
2363  f.proto = IPPROTO_TCP;
2364  f.flags |= FLOW_IPV4;
2365  f.alproto = ALPROTO_HTTP1;
2366 
2367  p1->flow = &f;
2371 
2372  p2->flow = &f;
2376 
2377  StreamTcpInitConfig(true);
2378 
2381  de_ctx->flags |= DE_QUIET;
2382 
2384  FAIL_IF_NULL(s);
2385 
2387  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2388 
2389  int r = AppLayerParserParse(
2390  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
2391  FAIL_IF(r != 0);
2392  HtpState *http_state = f.alstate;
2393  FAIL_IF_NULL(http_state);
2394 
2395  /* do detect for p1 */
2396  SCLogInfo("p1");
2397  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
2398 
2399  FAIL_IF(PacketAlertCheck(p1, 1));
2400 
2401  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
2402  FAIL_IF(r != 0);
2403  /* do detect for p2 */
2404  SCLogInfo("p2");
2405  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
2406 
2407  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
2408 
2409  uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_INT);
2410  FAIL_IF(id == 0);
2411 
2412  FlowVar *fv = FlowVarGet(&f, id);
2413  FAIL_IF_NULL(fv);
2414 
2415  FAIL_IF(fv->data.fv_int.value != 0);
2416 
2419 
2420  StreamTcpFreeConfig(true);
2421  FLOW_DESTROY(&f);
2422  UTHFreePackets(&p1, 1);
2423  UTHFreePackets(&p2, 1);
2424  PASS;
2425 }
2426 
2427 /** \test http buffer, flowints */
2428 static int LuaMatchTest06a(void)
2429 {
2430  const char script[] = "function init (args)\n"
2431  " local needs = {}\n"
2432  " needs[\"http.request_headers\"] = tostring(true)\n"
2433  " needs[\"flowint\"] = {\"cnt\"}\n"
2434  " return needs\n"
2435  "end\n"
2436  "\n"
2437  "function match(args)\n"
2438  " print \"inspecting\""
2439  " a = SCFlowintGet(0)\n"
2440  " if a == nil then\n"
2441  " print \"new var set to 2\""
2442  " SCFlowintSet(0, 2)\n"
2443  " end\n"
2444  " a = SCFlowintDecr(0)\n"
2445  " if a == 0 then\n"
2446  " print \"match\"\n"
2447  " return 1\n"
2448  " end\n"
2449  " return 0\n"
2450  "end\n"
2451  "return 0\n";
2452  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
2453  uint8_t httpbuf1[] =
2454  "POST / HTTP/1.1\r\n"
2455  "Host: www.emergingthreats.net\r\n\r\n";
2456  uint8_t httpbuf2[] =
2457  "POST / HTTP/1.1\r\n"
2458  "Host: www.openinfosecfoundation.org\r\n\r\n";
2459  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2460  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2461  TcpSession ssn;
2462  Flow f;
2463  ThreadVars th_v;
2464  DetectEngineThreadCtx *det_ctx;
2465 
2467 
2468  ut_script = script;
2469 
2470  memset(&th_v, 0, sizeof(th_v));
2471  memset(&f, 0, sizeof(f));
2472  memset(&ssn, 0, sizeof(ssn));
2473 
2474  Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2475  Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2476 
2477  FLOW_INITIALIZE(&f);
2478  f.protoctx = (void *)&ssn;
2479  f.proto = IPPROTO_TCP;
2480  f.flags |= FLOW_IPV4;
2481  f.alproto = ALPROTO_HTTP1;
2482 
2483  p1->flow = &f;
2487 
2488  p2->flow = &f;
2492 
2493  StreamTcpInitConfig(true);
2494 
2497  de_ctx->flags |= DE_QUIET;
2498 
2500  FAIL_IF_NULL(s);
2501 
2503  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2504 
2505  int r = AppLayerParserParse(
2506  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
2507  FAIL_IF(r != 0);
2508  HtpState *http_state = f.alstate;
2509  FAIL_IF_NULL(http_state);
2510 
2511  /* do detect for p1 */
2512  SCLogInfo("p1");
2513  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
2514 
2515  FAIL_IF(PacketAlertCheck(p1, 1));
2516 
2517  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
2518  FAIL_IF(r != 0);
2519  /* do detect for p2 */
2520  SCLogInfo("p2");
2521  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
2522 
2523  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
2524 
2525  uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_INT);
2526  FAIL_IF(id == 0);
2527 
2528  FlowVar *fv = FlowVarGet(&f, id);
2529  FAIL_IF_NULL(fv);
2530 
2531  FAIL_IF(fv->data.fv_int.value != 0);
2532 
2535 
2536  StreamTcpFreeConfig(true);
2537  FLOW_DESTROY(&f);
2538  UTHFreePackets(&p1, 1);
2539  UTHFreePackets(&p2, 1);
2540  PASS;
2541 }
2542 
2543 void DetectLuaRegisterTests(void)
2544 {
2545  UtRegisterTest("LuaMatchTest01", LuaMatchTest01);
2546  UtRegisterTest("LuaMatchTest01a", LuaMatchTest01a);
2547  UtRegisterTest("LuaMatchTest02", LuaMatchTest02);
2548  UtRegisterTest("LuaMatchTest02a", LuaMatchTest02a);
2549  UtRegisterTest("LuaMatchTest03", LuaMatchTest03);
2550  UtRegisterTest("LuaMatchTest03a", LuaMatchTest03a);
2551  UtRegisterTest("LuaMatchTest04", LuaMatchTest04);
2552  UtRegisterTest("LuaMatchTest04a", LuaMatchTest04a);
2553  UtRegisterTest("LuaMatchTest05", LuaMatchTest05);
2554  UtRegisterTest("LuaMatchTest05a", LuaMatchTest05a);
2555  UtRegisterTest("LuaMatchTest06", LuaMatchTest06);
2556  UtRegisterTest("LuaMatchTest06a", LuaMatchTest06a);
2557 }
2558 #endif
2559 #endif /* HAVE_LUAJIT */
util-byte.h
SigTableElmt_::url
const char * url
Definition: detect.h:1287
detect-engine.h
DETECT_SM_LIST_PMATCH
@ DETECT_SM_LIST_PMATCH
Definition: detect.h:110
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
SigMatchAppendSMToList
void SigMatchAppendSMToList(Signature *s, SigMatch *new, const int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:437
SignatureInitData_::smlists
struct SigMatch_ * smlists[DETECT_SM_LIST_MAX]
Definition: detect.h:566
SigTableElmt_::desc
const char * desc
Definition: detect.h:1286
PKT_HAS_FLOW
#define PKT_HAS_FLOW
Definition: decode.h:1000
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1274
flow-util.h
ALPROTO_DNS
@ ALPROTO_DNS
Definition: app-layer-protos.h:41
SigTableElmt_::name
const char * name
Definition: detect.h:1284
ConfGetBool
int ConfGetBool(const char *name, int *val)
Retrieve a configuration value as a boolean.
Definition: conf.c:483
stream-tcp.h
DetectThreadCtxGetKeywordThreadCtx
void * DetectThreadCtxGetKeywordThreadCtx(DetectEngineThreadCtx *det_ctx, int id)
Retrieve thread local keyword ctx by id.
Definition: detect-engine.c:3656
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:586
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
Flow_::proto
uint8_t proto
Definition: flow.h:369
util-lua.h
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:80
Packet_::payload
uint8_t * payload
Definition: decode.h:577
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:1145
FlowVarTypeStr::value_len
uint16_t value_len
Definition: flow-var.h:39
SigMatchData_::ctx
SigMatchCtx * ctx
Definition: detect.h:352
Packet_::flags
uint32_t flags
Definition: decode.h:467
threads.h
Flow_
Flow data structure.
Definition: flow.h:347
SigTableElmt_::flags
uint16_t flags
Definition: detect.h:1278
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:826
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:2592
detect-lua.h
SigTableElmt_::AppLayerTxMatch
int(* AppLayerTxMatch)(DetectEngineThreadCtx *, Flow *, uint8_t flags, void *alstate, void *txv, const Signature *, const SigMatchCtx *)
Definition: detect.h:1255
AppLayerParserThreadCtxFree
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
Definition: app-layer-parser.c:314
FLOW_PKT_TOSERVER
#define FLOW_PKT_TOSERVER
Definition: flow.h:221
util-var-name.h
ConfSetFinal
int ConfSetFinal(const char *name, const char *val)
Set a final configuration value.
Definition: conf.c:303
DE_QUIET
#define DE_QUIET
Definition: detect.h:314
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:337
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1824
StringParseInt32
int StringParseInt32(int32_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:622
FlowVar_::data
union FlowVar_::@110 data
VarNameStoreRegister
uint32_t VarNameStoreRegister(const char *name, const enum VarTypes type)
Definition: util-var-name.c:155
ALPROTO_SSH
@ ALPROTO_SSH
Definition: app-layer-protos.h:34
DetectEngineAppendSig
Signature * DetectEngineAppendSig(DetectEngineCtx *, const char *)
Parse and append a Signature into the Detection Engine Context signature list.
Definition: detect-parse.c:2569
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:461
DetectBufferGetActiveList
int DetectBufferGetActiveList(DetectEngineCtx *de_ctx, Signature *s)
Definition: detect-engine.c:1453
SIG_FLAG_TOCLIENT
#define SIG_FLAG_TOCLIENT
Definition: detect.h:256
Flow_::protoctx
void * protoctx
Definition: flow.h:437
SigMatchData_
Data needed for Match()
Definition: detect.h:349
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1269
FLOW_IPV4
#define FLOW_IPV4
Definition: flow.h:96
Packet_::payload_len
uint16_t payload_len
Definition: decode.h:578
AppLayerParserGetTransactionInspectId
uint64_t AppLayerParserGetTransactionInspectId(AppLayerParserState *pstate, uint8_t direction)
Definition: app-layer-parser.c:729
DetectByteIndexType
uint8_t DetectByteIndexType
Definition: detect-byte.h:28
util-unittest.h
HtpState_
Definition: app-layer-htp.h:243
SIGMATCH_NOT_BUILT
#define SIGMATCH_NOT_BUILT
Definition: detect.h:1472
util-unittest-helper.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
DetectBufferTypeGetByName
int DetectBufferTypeGetByName(const char *name)
Definition: detect-engine.c:1124
Signature_::gid
uint32_t gid
Definition: detect.h:617
FlowVar_::fv_int
FlowVarTypeInt fv_int
Definition: flow-var.h:58
Flow_::alparser
AppLayerParserState * alparser
Definition: flow.h:471
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:359
FLOW_INITIALIZE
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:38
SIG_FLAG_TOSERVER
#define SIG_FLAG_TOSERVER
Definition: detect.h:255
app-layer-htp.h
VarNameStoreLookupByName
uint32_t VarNameStoreLookupByName(const char *name, const enum VarTypes type)
find name for id+type at packet time.
Definition: util-var-name.c:322
decode.h
util-debug.h
type
uint8_t type
Definition: decode-icmpv4.h:0
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
DetectEngineThreadCtx_
Definition: detect.h:1074
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:221
SignatureInitData_::list
int list
Definition: detect.h:550
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:271
GET_PKT_DATA
#define GET_PKT_DATA(p)
Definition: decode.h:220
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
VarNameStoreUnregister
void VarNameStoreUnregister(const uint32_t id, const enum VarTypes type)
Definition: util-var-name.c:201
SigMatch_::next
struct SigMatch_ * next
Definition: detect.h:344
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:108
app-layer-parser.h
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:343
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:295
Packet_
Definition: decode.h:430
detect-engine-build.h
GET_PKT_LEN
#define GET_PKT_LEN(p)
Definition: decode.h:219
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:216
detect-engine-alert.h
conf.h
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:653
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:1252
queue.h
detect-byte.h
FLOW_PKT_TOCLIENT
#define FLOW_PKT_TOCLIENT
Definition: flow.h:222
SigMatchAlloc
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:322
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:224
AppLayerParserGetTx
void * AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
Definition: app-layer-parser.c:1127
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:1973
AppLayerParserThreadCtxAlloc
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
Definition: app-layer-parser.c:293
SigMatchCtx_
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:335
FlowVarTypeStr::value
uint8_t * value
Definition: flow-var.h:38
Packet_::flow
struct Flow_ * flow
Definition: decode.h:469
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
Definition: detect-engine.c:3308
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
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:1060
StreamTcpFreeConfig
void StreamTcpFreeConfig(bool quiet)
Definition: stream-tcp.c:690
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:3586
SigTableElmt_::alias
const char * alias
Definition: detect.h:1285
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:1307
detect-lua-extensions.h
suricata-common.h
SigMatch_::type
uint16_t type
Definition: detect.h:341
ALPROTO_HTTP1
@ ALPROTO_HTTP1
Definition: app-layer-protos.h:30
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:129
HtpState_::connp
htp_connp_t * connp
Definition: app-layer-htp.h:245
lua_State
void lua_State
Definition: suricata-common.h:495
Signature_::rev
uint32_t rev
Definition: detect.h:618
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:2122
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
str
#define str(s)
Definition: suricata-common.h:286
DetectEngineThreadCtx_::tv
ThreadVars * tv
Definition: detect.h:1080
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
SCFree
#define SCFree(p)
Definition: util-mem.h:61
Flow_::alstate
void * alstate
Definition: flow.h:472
Signature_::id
uint32_t id
Definition: detect.h:616
Flow_::flags
uint32_t flags
Definition: flow.h:417
detect-parse.h
Signature_
Signature container.
Definition: detect.h:581
SigMatch_
a single match condition for a signature
Definition: detect.h:340
AppLayerGetProtoName
const char * AppLayerGetProtoName(AppProto alproto)
Given the internal protocol id, returns a string representation of the protocol.
Definition: app-layer.c:937
VAR_TYPE_FLOW_VAR
@ VAR_TYPE_FLOW_VAR
Definition: util-var.h:37
DETECT_SM_LIST_MAX
@ DETECT_SM_LIST_MAX
Definition: detect.h:126
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:223
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2553
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:828
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:66
DetectUnregisterThreadCtxFuncs
int DetectUnregisterThreadCtxFuncs(DetectEngineCtx *de_ctx, void *data, const char *name)
Remove Thread keyword context registration.
Definition: detect-engine.c:3638
TcpSession_
Definition: stream-tcp-private.h:283
flow.h
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:446
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:275
flow-var.h
AppLayerParserGetTxCnt
uint64_t AppLayerParserGetTxCnt(const Flow *f, void *alstate)
Definition: app-layer-parser.c:1120
FlowVar_
Definition: flow-var.h:48
FLOW_DESTROY
#define FLOW_DESTROY(f)
Definition: flow-util.h:127
PKT_STREAM_EST
#define PKT_STREAM_EST
Definition: decode.h:997
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1276
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:468