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 = SCCalloc(1, sizeof(DetectLuaThreadData));
600  if (unlikely(t == NULL)) {
601  SCLogError("couldn't alloc ctx memory");
602  return NULL;
603  }
604 
605  t->alproto = lua->alproto;
606  t->flags = lua->flags;
607 
608  t->luastate = LuaGetState();
609  if (t->luastate == NULL) {
610  SCLogError("luastate pool depleted");
611  goto error;
612  }
613 
614  luaL_openlibs(t->luastate);
615 
616  LuaRegisterExtensions(t->luastate);
617 
618  lua_pushinteger(t->luastate, (lua_Integer)(lua->sid));
619  lua_setglobal(t->luastate, "SCRuleSid");
620  lua_pushinteger(t->luastate, (lua_Integer)(lua->rev));
621  lua_setglobal(t->luastate, "SCRuleRev");
622  lua_pushinteger(t->luastate, (lua_Integer)(lua->gid));
623  lua_setglobal(t->luastate, "SCRuleGid");
624 
625  /* hackish, needed to allow unittests to pass buffers as scripts instead of files */
626 #ifdef UNITTESTS
627  if (ut_script != NULL) {
628  status = luaL_loadbuffer(t->luastate, ut_script, strlen(ut_script), "unittest");
629  if (status) {
630  SCLogError("couldn't load file: %s", lua_tostring(t->luastate, -1));
631  goto error;
632  }
633  } else {
634 #endif
635  status = luaL_loadfile(t->luastate, lua->filename);
636  if (status) {
637  SCLogError("couldn't load file: %s", lua_tostring(t->luastate, -1));
638  goto error;
639  }
640 #ifdef UNITTESTS
641  }
642 #endif
643 
644  /* prime the script (or something) */
645  if (lua_pcall(t->luastate, 0, 0, 0) != 0) {
646  SCLogError("couldn't prime file: %s", lua_tostring(t->luastate, -1));
647  goto error;
648  }
649 
650  return (void *)t;
651 
652 error:
653  if (t->luastate != NULL)
654  LuaReturnState(t->luastate);
655  SCFree(t);
656  return NULL;
657 }
658 
659 static void DetectLuaThreadFree(void *ctx)
660 {
661  if (ctx != NULL) {
662  DetectLuaThreadData *t = (DetectLuaThreadData *)ctx;
663  if (t->luastate != NULL)
664  LuaReturnState(t->luastate);
665  SCFree(t);
666  }
667 }
668 
669 /**
670  * \brief Parse the lua keyword
671  *
672  * \param de_ctx Pointer to the detection engine context
673  * \param str Pointer to the user provided option
674  *
675  * \retval lua pointer to DetectLuaData on success
676  * \retval NULL on failure
677  */
678 static DetectLuaData *DetectLuaParse (DetectEngineCtx *de_ctx, const char *str)
679 {
680  DetectLuaData *lua = NULL;
681 
682  /* We have a correct lua option */
683  lua = SCCalloc(1, sizeof(DetectLuaData));
684  if (unlikely(lua == NULL))
685  goto error;
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("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("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("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("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("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("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("init function in script should return table, nothing returned");
764  goto error;
765  }
766  if (lua_type(luastate, 1) != LUA_TTABLE) {
767  SCLogError("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("too many flowvars registered");
791  goto error;
792  }
793 
794  uint32_t idx = VarNameStoreRegister(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("too many flowints registered");
813  goto error;
814  }
815 
816  uint32_t idx = VarNameStoreRegister(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("too many bytevars registered");
835  goto error;
836  }
837 
839  if (!DetectByteRetrieveSMVar(value, s, &idx)) {
840  SCLogError("Unknown byte_extract or byte_math var "
841  "requested by lua script - %s",
842  value);
843  goto error;
844  }
845  ld->bytevar[ld->bytevars++] = idx;
846  SCLogDebug("script uses bytevar %u with script id %u", idx, ld->bytevars - 1);
847  }
848  }
849  lua_pop(luastate, 1);
850  continue;
851  }
852 
853  v = lua_tostring(luastate, -1);
854  lua_pop(luastate, 1);
855  if (v == NULL)
856  continue;
857 
858  SCLogDebug("k='%s', v='%s'", k, v);
859  if (strcmp(k, "packet") == 0 && strcmp(v, "true") == 0) {
860  ld->flags |= DATATYPE_PACKET;
861  } else if (strcmp(k, "payload") == 0 && strcmp(v, "true") == 0) {
862  ld->flags |= DATATYPE_PAYLOAD;
863  } else if (strcmp(k, "buffer") == 0 && strcmp(v, "true") == 0) {
864  ld->flags |= DATATYPE_BUFFER;
865 
866  ld->buffername = SCStrdup("buffer");
867  if (ld->buffername == NULL) {
868  SCLogError("alloc error");
869  goto error;
870  }
871  } else if (strcmp(k, "stream") == 0 && strcmp(v, "true") == 0) {
872  ld->flags |= DATATYPE_STREAM;
873 
874  ld->buffername = SCStrdup("stream");
875  if (ld->buffername == NULL) {
876  SCLogError("alloc error");
877  goto error;
878  }
879 
880  } else if (strncmp(k, "http", 4) == 0 && strcmp(v, "true") == 0) {
881  if (ld->alproto != ALPROTO_UNKNOWN && ld->alproto != ALPROTO_HTTP1) {
882  SCLogError(
883  "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("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("unsupported http data type %s", k);
932  goto error;
933  }
934 
935  ld->buffername = SCStrdup(k);
936  if (ld->buffername == NULL) {
937  SCLogError("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("unsupported dns data type %s", k);
953  goto error;
954  }
955  ld->buffername = SCStrdup(k);
956  if (ld->buffername == NULL) {
957  SCLogError("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("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 
1014  /* First check if Lua rules are enabled, by default Lua in rules
1015  * is disabled. */
1016  int enabled = 0;
1017  (void)ConfGetBool("security.lua.allow-rules", &enabled);
1018  if (!enabled) {
1019  SCLogError("Lua rules disabled by security configuration: security.lua.allow-rules");
1020  goto error;
1021  }
1022 
1023  lua = DetectLuaParse(de_ctx, str);
1024  if (lua == NULL)
1025  goto error;
1026 
1027  if (DetectLuaSetupPrime(de_ctx, lua, s) == -1) {
1028  goto error;
1029  }
1030 
1031  lua->thread_ctx_id = DetectRegisterThreadCtxFuncs(de_ctx, "lua",
1032  DetectLuaThreadInit, (void *)lua,
1033  DetectLuaThreadFree, 0);
1034  if (lua->thread_ctx_id == -1)
1035  goto error;
1036 
1037  if (lua->alproto != ALPROTO_UNKNOWN) {
1038  if (s->alproto != ALPROTO_UNKNOWN && !AppProtoEquals(s->alproto, lua->alproto)) {
1039  goto error;
1040  }
1041  s->alproto = lua->alproto;
1042  }
1043 
1044  /* Okay so far so good, lets get this into a SigMatch
1045  * and put it in the Signature. */
1046 
1047  int list = -1;
1048  if (lua->alproto == ALPROTO_UNKNOWN) {
1049  if (lua->flags & DATATYPE_STREAM)
1050  list = DETECT_SM_LIST_PMATCH;
1051  else {
1052  if (lua->flags & DATATYPE_BUFFER) {
1053  if (DetectBufferGetActiveList(de_ctx, s) != -1) {
1054  list = s->init_data->list;
1055  } else {
1056  SCLogError("Lua and sticky buffer failure");
1057  goto error;
1058  }
1059  } else
1060  list = DETECT_SM_LIST_MATCH;
1061  }
1062 
1063  } else if (lua->alproto == ALPROTO_HTTP1) {
1064  if (lua->flags & DATATYPE_HTTP_RESPONSE_BODY) {
1065  list = DetectBufferTypeGetByName("file_data");
1066  } else if (lua->flags & DATATYPE_HTTP_REQUEST_BODY) {
1067  list = DetectBufferTypeGetByName("http_client_body");
1068  } else if (lua->flags & DATATYPE_HTTP_URI) {
1069  list = DetectBufferTypeGetByName("http_uri");
1070  } else if (lua->flags & DATATYPE_HTTP_URI_RAW) {
1071  list = DetectBufferTypeGetByName("http_raw_uri");
1072  } else if (lua->flags & DATATYPE_HTTP_REQUEST_COOKIE ||
1073  lua->flags & DATATYPE_HTTP_RESPONSE_COOKIE)
1074  {
1075  list = DetectBufferTypeGetByName("http_cookie");
1076  } else if (lua->flags & DATATYPE_HTTP_REQUEST_UA) {
1077  list = DetectBufferTypeGetByName("http_user_agent");
1078  } else if (lua->flags & (DATATYPE_HTTP_REQUEST_HEADERS|DATATYPE_HTTP_RESPONSE_HEADERS)) {
1079  list = DetectBufferTypeGetByName("http_header");
1080  } else if (lua->flags & (DATATYPE_HTTP_REQUEST_HEADERS_RAW|DATATYPE_HTTP_RESPONSE_HEADERS_RAW)) {
1081  list = DetectBufferTypeGetByName("http_raw_header");
1082  } else {
1083  list = DetectBufferTypeGetByName("http_request_line");
1084  }
1085  } else if (lua->alproto == ALPROTO_DNS) {
1086  if (lua->flags & DATATYPE_DNS_RRNAME) {
1087  list = DetectBufferTypeGetByName("dns_query");
1088  } else if (lua->flags & DATATYPE_DNS_REQUEST) {
1089  list = DetectBufferTypeGetByName("dns_request");
1090  } else if (lua->flags & DATATYPE_DNS_RESPONSE) {
1091  list = DetectBufferTypeGetByName("dns_response");
1092  }
1093  } else if (lua->alproto == ALPROTO_TLS) {
1094  list = DetectBufferTypeGetByName("tls_generic");
1095  } else if (lua->alproto == ALPROTO_SSH) {
1096  list = DetectBufferTypeGetByName("ssh_banner");
1097  } else if (lua->alproto == ALPROTO_SMTP) {
1098  list = g_smtp_generic_list_id;
1099  } else if (lua->alproto == ALPROTO_DNP3) {
1100  list = DetectBufferTypeGetByName("dnp3");
1101  } else {
1102  SCLogError("lua can't be used with protocol %s", AppLayerGetProtoName(lua->alproto));
1103  goto error;
1104  }
1105 
1106  if (list == -1) {
1107  SCLogError("lua can't be used with protocol %s", AppLayerGetProtoName(lua->alproto));
1108  goto error;
1109  }
1110 
1111  if (SigMatchAppendSMToList(de_ctx, s, DETECT_LUA, (SigMatchCtx *)lua, list) == NULL) {
1112  goto error;
1113  }
1114 
1115  return 0;
1116 
1117 error:
1118  if (lua != NULL)
1119  DetectLuaFree(de_ctx, lua);
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 
1159  for (uint16_t i = 0; i < lua->flowints; i++) {
1160  VarNameStoreUnregister(lua->flowint[i], VAR_TYPE_FLOW_INT);
1161  }
1162  for (uint16_t i = 0; i < lua->flowvars; i++) {
1163  VarNameStoreUnregister(lua->flowvar[i], VAR_TYPE_FLOW_VAR);
1164  }
1165 
1167 
1168  SCFree(lua);
1169  }
1170 }
1171 
1172 #ifdef UNITTESTS
1173 #include "detect-engine-alert.h"
1174 
1175 /** \test http buffer */
1176 static int LuaMatchTest01(void)
1177 {
1178  ConfSetFinal("security.lua.allow-rules", "true");
1179 
1180  const char script[] =
1181  "function init (args)\n"
1182  " local needs = {}\n"
1183  " needs[\"http.request_headers\"] = tostring(true)\n"
1184  " needs[\"flowvar\"] = {\"cnt\"}\n"
1185  " return needs\n"
1186  "end\n"
1187  "\n"
1188  "function match(args)\n"
1189  " a = ScFlowvarGet(0)\n"
1190  " if a then\n"
1191  " a = tostring(tonumber(a)+1)\n"
1192  " print (a)\n"
1193  " ScFlowvarSet(0, a, #a)\n"
1194  " else\n"
1195  " a = tostring(1)\n"
1196  " print (a)\n"
1197  " ScFlowvarSet(0, a, #a)\n"
1198  " end\n"
1199  " \n"
1200  " print (\"pre check: \" .. (a))\n"
1201  " if tonumber(a) == 2 then\n"
1202  " print \"match\"\n"
1203  " return 1\n"
1204  " end\n"
1205  " return 0\n"
1206  "end\n"
1207  "return 0\n";
1208  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1209  uint8_t httpbuf1[] =
1210  "POST / HTTP/1.1\r\n"
1211  "Host: www.emergingthreats.net\r\n\r\n";
1212  uint8_t httpbuf2[] =
1213  "POST / HTTP/1.1\r\n"
1214  "Host: www.openinfosecfoundation.org\r\n\r\n";
1215  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1216  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1217  TcpSession ssn;
1218  Flow f;
1219  ThreadVars th_v;
1220  DetectEngineThreadCtx *det_ctx;
1221 
1223 
1224  ut_script = script;
1225 
1226  memset(&th_v, 0, sizeof(th_v));
1227  memset(&f, 0, sizeof(f));
1228  memset(&ssn, 0, sizeof(ssn));
1229 
1230  Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1231  Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1232 
1233  FLOW_INITIALIZE(&f);
1234  f.protoctx = (void *)&ssn;
1235  f.proto = IPPROTO_TCP;
1236  f.flags |= FLOW_IPV4;
1237  f.alproto = ALPROTO_HTTP1;
1238 
1239  p1->flow = &f;
1243  p2->flow = &f;
1247 
1248  StreamTcpInitConfig(true);
1249 
1252  de_ctx->flags |= DE_QUIET;
1253 
1255  FAIL_IF_NULL(s);
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  FAIL_IF(r != 0);
1263  HtpState *http_state = f.alstate;
1264  FAIL_IF_NULL(http_state);
1265 
1266  /* do detect for p1 */
1267  SCLogDebug("inspecting p1");
1268  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1269 
1270  FAIL_IF(PacketAlertCheck(p1, 1));
1271 
1272  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1273  FAIL_IF(r != 0);
1274 
1275  /* do detect for p2 */
1276  SCLogDebug("inspecting p2");
1277  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1278 
1279  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
1280 
1281  uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_VAR);
1282  FAIL_IF(id == 0);
1283 
1284  FlowVar *fv = FlowVarGet(&f, id);
1285  FAIL_IF_NULL(fv);
1286 
1287  FAIL_IF(fv->data.fv_str.value_len != 1);
1288 
1289  FAIL_IF(memcmp(fv->data.fv_str.value, "2", 1) != 0);
1290 
1293 
1294  StreamTcpFreeConfig(true);
1295  FLOW_DESTROY(&f);
1296  UTHFreePackets(&p1, 1);
1297  UTHFreePackets(&p2, 1);
1298  PASS;
1299 }
1300 
1301 static int LuaMatchTest01a(void)
1302 {
1303  const char script[] = "function init (args)\n"
1304  " local needs = {}\n"
1305  " needs[\"http.request_headers\"] = tostring(true)\n"
1306  " needs[\"flowvar\"] = {\"cnt\"}\n"
1307  " return needs\n"
1308  "end\n"
1309  "\n"
1310  "function match(args)\n"
1311  " a = SCFlowvarGet(0)\n"
1312  " if a then\n"
1313  " a = tostring(tonumber(a)+1)\n"
1314  " print (a)\n"
1315  " SCFlowvarSet(0, a, #a)\n"
1316  " else\n"
1317  " a = tostring(1)\n"
1318  " print (a)\n"
1319  " SCFlowvarSet(0, a, #a)\n"
1320  " end\n"
1321  " \n"
1322  " print (\"pre check: \" .. (a))\n"
1323  " if tonumber(a) == 2 then\n"
1324  " print \"match\"\n"
1325  " return 1\n"
1326  " end\n"
1327  " return 0\n"
1328  "end\n"
1329  "return 0\n";
1330  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1331  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1332  "Host: www.emergingthreats.net\r\n\r\n";
1333  uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1334  "Host: www.openinfosecfoundation.org\r\n\r\n";
1335  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1336  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1337  TcpSession ssn;
1338  Flow f;
1339  ThreadVars th_v;
1340  DetectEngineThreadCtx *det_ctx;
1341 
1343 
1344  ut_script = script;
1345 
1346  memset(&th_v, 0, sizeof(th_v));
1347  memset(&f, 0, sizeof(f));
1348  memset(&ssn, 0, sizeof(ssn));
1349 
1350  Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1351  Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1352 
1353  FLOW_INITIALIZE(&f);
1354  f.protoctx = (void *)&ssn;
1355  f.proto = IPPROTO_TCP;
1356  f.flags |= FLOW_IPV4;
1357  f.alproto = ALPROTO_HTTP1;
1358 
1359  p1->flow = &f;
1363  p2->flow = &f;
1367 
1368  StreamTcpInitConfig(true);
1369 
1372  de_ctx->flags |= DE_QUIET;
1373 
1375  FAIL_IF_NULL(s);
1376 
1378  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1379 
1380  int r = AppLayerParserParse(
1381  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
1382  FAIL_IF(r != 0);
1383 
1384  HtpState *http_state = f.alstate;
1385  FAIL_IF_NULL(http_state);
1386 
1387  /* do detect for p1 */
1388  SCLogDebug("inspecting p1");
1389  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1390 
1391  FAIL_IF(PacketAlertCheck(p1, 1));
1392 
1393  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1394  FAIL_IF(r != 0);
1395  /* do detect for p2 */
1396  SCLogDebug("inspecting p2");
1397  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1398 
1399  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
1400 
1401  uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_VAR);
1402  FAIL_IF(id == 0);
1403 
1404  FlowVar *fv = FlowVarGet(&f, id);
1405  FAIL_IF_NULL(fv);
1406 
1407  FAIL_IF(fv->data.fv_str.value_len != 1);
1408 
1409  FAIL_IF(memcmp(fv->data.fv_str.value, "2", 1) != 0);
1410 
1413 
1414  StreamTcpFreeConfig(true);
1415  FLOW_DESTROY(&f);
1416  UTHFreePackets(&p1, 1);
1417  UTHFreePackets(&p2, 1);
1418  PASS;
1419 }
1420 
1421 /** \test payload buffer */
1422 static int LuaMatchTest02(void)
1423 {
1424  const char script[] = "function init (args)\n"
1425  " local needs = {}\n"
1426  " needs[\"payload\"] = tostring(true)\n"
1427  " needs[\"flowvar\"] = {\"cnt\"}\n"
1428  " return needs\n"
1429  "end\n"
1430  "\n"
1431  "function match(args)\n"
1432  " a = ScFlowvarGet(0)\n"
1433  " if a then\n"
1434  " a = tostring(tonumber(a)+1)\n"
1435  " print (a)\n"
1436  " ScFlowvarSet(0, a, #a)\n"
1437  " else\n"
1438  " a = tostring(1)\n"
1439  " print (a)\n"
1440  " ScFlowvarSet(0, a, #a)\n"
1441  " end\n"
1442  " \n"
1443  " print (\"pre check: \" .. (a))\n"
1444  " if tonumber(a) == 2 then\n"
1445  " print \"match\"\n"
1446  " return 1\n"
1447  " end\n"
1448  " return 0\n"
1449  "end\n"
1450  "return 0\n";
1451  char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1452  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1453  "Host: www.emergingthreats.net\r\n\r\n";
1454  uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1455  "Host: www.openinfosecfoundation.org\r\n\r\n";
1456  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1457  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1458  TcpSession ssn;
1459  Flow f;
1460  ThreadVars th_v;
1461  DetectEngineThreadCtx *det_ctx;
1462 
1463  ut_script = script;
1464 
1465  memset(&th_v, 0, sizeof(th_v));
1466  memset(&f, 0, sizeof(f));
1467  memset(&ssn, 0, sizeof(ssn));
1468 
1469  Packet *p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP);
1470  Packet *p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP);
1471 
1472  FLOW_INITIALIZE(&f);
1473  f.protoctx = (void *)&ssn;
1474  f.proto = IPPROTO_TCP;
1475  f.flags |= FLOW_IPV4;
1476  f.alproto = ALPROTO_HTTP1;
1477 
1478  p1->flow = &f;
1482  p2->flow = &f;
1486 
1487  StreamTcpInitConfig(true);
1488 
1491  de_ctx->flags |= DE_QUIET;
1492 
1494  FAIL_IF_NULL(s);
1495 
1497  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1498 
1499  /* do detect for p1 */
1500  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1501 
1502  FAIL_IF(PacketAlertCheck(p1, 1));
1503 
1504  /* do detect for p2 */
1505  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1506 
1507  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
1508 
1509  uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_VAR);
1510  FAIL_IF(id == 0);
1511 
1512  FlowVar *fv = FlowVarGet(&f, id);
1513  FAIL_IF_NULL(fv);
1514 
1515  FAIL_IF(fv->data.fv_str.value_len != 1);
1516 
1517  FAIL_IF(memcmp(fv->data.fv_str.value, "2", 1) != 0);
1518 
1520 
1521  StreamTcpFreeConfig(true);
1522  FLOW_DESTROY(&f);
1523  UTHFreePackets(&p1, 1);
1524  UTHFreePackets(&p2, 1);
1525  PASS;
1526 }
1527 
1528 /** \test payload buffer */
1529 static int LuaMatchTest02a(void)
1530 {
1531  const char script[] = "function init (args)\n"
1532  " local needs = {}\n"
1533  " needs[\"payload\"] = tostring(true)\n"
1534  " needs[\"flowvar\"] = {\"cnt\"}\n"
1535  " return needs\n"
1536  "end\n"
1537  "\n"
1538  "function match(args)\n"
1539  " a = SCFlowvarGet(0)\n"
1540  " if a then\n"
1541  " a = tostring(tonumber(a)+1)\n"
1542  " print (a)\n"
1543  " SCFlowvarSet(0, a, #a)\n"
1544  " else\n"
1545  " a = tostring(1)\n"
1546  " print (a)\n"
1547  " SCFlowvarSet(0, a, #a)\n"
1548  " end\n"
1549  " \n"
1550  " print (\"pre check: \" .. (a))\n"
1551  " if tonumber(a) == 2 then\n"
1552  " print \"match\"\n"
1553  " return 1\n"
1554  " end\n"
1555  " return 0\n"
1556  "end\n"
1557  "return 0\n";
1558  char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1559  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1560  "Host: www.emergingthreats.net\r\n\r\n";
1561  uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1562  "Host: www.openinfosecfoundation.org\r\n\r\n";
1563  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1564  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1565  TcpSession ssn;
1566  Flow f;
1567  ThreadVars th_v;
1568  DetectEngineThreadCtx *det_ctx;
1569 
1570  ut_script = script;
1571 
1572  memset(&th_v, 0, sizeof(th_v));
1573  memset(&f, 0, sizeof(f));
1574  memset(&ssn, 0, sizeof(ssn));
1575 
1576  Packet *p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP);
1577  Packet *p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP);
1578 
1579  FLOW_INITIALIZE(&f);
1580  f.protoctx = (void *)&ssn;
1581  f.proto = IPPROTO_TCP;
1582  f.flags |= FLOW_IPV4;
1583  f.alproto = ALPROTO_HTTP1;
1584 
1585  p1->flow = &f;
1589  p2->flow = &f;
1593 
1594  StreamTcpInitConfig(true);
1595 
1598  de_ctx->flags |= DE_QUIET;
1599 
1601  FAIL_IF_NULL(s);
1602 
1604  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1605 
1606  /* do detect for p1 */
1607  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1608  FAIL_IF(PacketAlertCheck(p1, 1));
1609 
1610  /* do detect for p2 */
1611  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1612 
1613  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
1614 
1615  uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_VAR);
1616  FAIL_IF(id == 0);
1617 
1618  FlowVar *fv = FlowVarGet(&f, id);
1619  FAIL_IF_NULL(fv);
1620 
1621  FAIL_IF(fv->data.fv_str.value_len != 1);
1622 
1623  FAIL_IF(memcmp(fv->data.fv_str.value, "2", 1) != 0);
1624 
1626 
1627  StreamTcpFreeConfig(true);
1628  FLOW_DESTROY(&f);
1629  UTHFreePackets(&p1, 1);
1630  UTHFreePackets(&p2, 1);
1631  PASS;
1632 }
1633 
1634 /** \test packet buffer */
1635 static int LuaMatchTest03(void)
1636 {
1637  const char script[] = "function init (args)\n"
1638  " local needs = {}\n"
1639  " needs[\"packet\"] = tostring(true)\n"
1640  " needs[\"flowvar\"] = {\"cnt\"}\n"
1641  " return needs\n"
1642  "end\n"
1643  "\n"
1644  "function match(args)\n"
1645  " a = ScFlowvarGet(0)\n"
1646  " if a then\n"
1647  " a = tostring(tonumber(a)+1)\n"
1648  " print (a)\n"
1649  " ScFlowvarSet(0, a, #a)\n"
1650  " else\n"
1651  " a = tostring(1)\n"
1652  " print (a)\n"
1653  " ScFlowvarSet(0, a, #a)\n"
1654  " end\n"
1655  " \n"
1656  " print (\"pre check: \" .. (a))\n"
1657  " if tonumber(a) == 2 then\n"
1658  " print \"match\"\n"
1659  " return 1\n"
1660  " end\n"
1661  " return 0\n"
1662  "end\n"
1663  "return 0\n";
1664  char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1665  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1666  "Host: www.emergingthreats.net\r\n\r\n";
1667  uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1668  "Host: www.openinfosecfoundation.org\r\n\r\n";
1669  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1670  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1671  TcpSession ssn;
1672  Flow f;
1673  ThreadVars th_v;
1674  DetectEngineThreadCtx *det_ctx;
1675 
1676  ut_script = script;
1677 
1678  memset(&th_v, 0, sizeof(th_v));
1679  memset(&f, 0, sizeof(f));
1680  memset(&ssn, 0, sizeof(ssn));
1681 
1682  Packet *p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP);
1683  Packet *p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP);
1684 
1685  FLOW_INITIALIZE(&f);
1686  f.protoctx = (void *)&ssn;
1687  f.proto = IPPROTO_TCP;
1688  f.flags |= FLOW_IPV4;
1689  f.alproto = ALPROTO_HTTP1;
1690 
1691  p1->flow = &f;
1695  p2->flow = &f;
1699 
1700  StreamTcpInitConfig(true);
1701 
1704  de_ctx->flags |= DE_QUIET;
1705 
1707  FAIL_IF_NULL(s);
1708 
1710  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1711 
1712  /* do detect for p1 */
1713  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1714  FAIL_IF(PacketAlertCheck(p1, 1));
1715 
1716  /* do detect for p2 */
1717  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1718 
1719  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
1720 
1721  uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_VAR);
1722  FAIL_IF(id == 0);
1723 
1724  FlowVar *fv = FlowVarGet(&f, id);
1725  FAIL_IF_NULL(fv);
1726 
1727  FAIL_IF(fv->data.fv_str.value_len != 1);
1728 
1729  FAIL_IF(memcmp(fv->data.fv_str.value, "2", 1) != 0);
1730 
1732 
1733  StreamTcpFreeConfig(true);
1734  FLOW_DESTROY(&f);
1735  UTHFreePackets(&p1, 1);
1736  UTHFreePackets(&p2, 1);
1737  PASS;
1738 }
1739 
1740 /** \test packet buffer */
1741 static int LuaMatchTest03a(void)
1742 {
1743  const char script[] = "function init (args)\n"
1744  " local needs = {}\n"
1745  " needs[\"packet\"] = tostring(true)\n"
1746  " needs[\"flowvar\"] = {\"cnt\"}\n"
1747  " return needs\n"
1748  "end\n"
1749  "\n"
1750  "function match(args)\n"
1751  " a = SCFlowvarGet(0)\n"
1752  " if a then\n"
1753  " a = tostring(tonumber(a)+1)\n"
1754  " print (a)\n"
1755  " SCFlowvarSet(0, a, #a)\n"
1756  " else\n"
1757  " a = tostring(1)\n"
1758  " print (a)\n"
1759  " SCFlowvarSet(0, a, #a)\n"
1760  " end\n"
1761  " \n"
1762  " print (\"pre check: \" .. (a))\n"
1763  " if tonumber(a) == 2 then\n"
1764  " print \"match\"\n"
1765  " return 1\n"
1766  " end\n"
1767  " return 0\n"
1768  "end\n"
1769  "return 0\n";
1770  char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1771  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1772  "Host: www.emergingthreats.net\r\n\r\n";
1773  uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1774  "Host: www.openinfosecfoundation.org\r\n\r\n";
1775  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1776  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1777  TcpSession ssn;
1778  Flow f;
1779  ThreadVars th_v;
1780  DetectEngineThreadCtx *det_ctx;
1781 
1782  ut_script = script;
1783 
1784  memset(&th_v, 0, sizeof(th_v));
1785  memset(&f, 0, sizeof(f));
1786  memset(&ssn, 0, sizeof(ssn));
1787 
1788  Packet *p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP);
1789  Packet *p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP);
1790 
1791  FLOW_INITIALIZE(&f);
1792  f.protoctx = (void *)&ssn;
1793  f.proto = IPPROTO_TCP;
1794  f.flags |= FLOW_IPV4;
1795  f.alproto = ALPROTO_HTTP1;
1796 
1797  p1->flow = &f;
1801  p2->flow = &f;
1805 
1806  StreamTcpInitConfig(true);
1807 
1810  de_ctx->flags |= DE_QUIET;
1811 
1813  FAIL_IF_NULL(s);
1814 
1816  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1817 
1818  /* do detect for p1 */
1819  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1820  FAIL_IF(PacketAlertCheck(p1, 1));
1821 
1822  /* do detect for p2 */
1823  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1824  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
1825 
1826  uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_VAR);
1827  FAIL_IF(id == 0);
1828 
1829  FlowVar *fv = FlowVarGet(&f, id);
1830  FAIL_IF_NULL(fv);
1831 
1832  FAIL_IF(fv->data.fv_str.value_len != 1);
1833 
1834  FAIL_IF(memcmp(fv->data.fv_str.value, "2", 1) != 0);
1835 
1837 
1838  StreamTcpFreeConfig(true);
1839  FLOW_DESTROY(&f);
1840  UTHFreePackets(&p1, 1);
1841  UTHFreePackets(&p2, 1);
1842  PASS;
1843 }
1844 
1845 /** \test http buffer, flowints */
1846 static int LuaMatchTest04(void)
1847 {
1848  const char script[] = "function init (args)\n"
1849  " local needs = {}\n"
1850  " needs[\"http.request_headers\"] = tostring(true)\n"
1851  " needs[\"flowint\"] = {\"cnt\"}\n"
1852  " return needs\n"
1853  "end\n"
1854  "\n"
1855  "function match(args)\n"
1856  " print \"inspecting\""
1857  " a = ScFlowintGet(0)\n"
1858  " if a then\n"
1859  " ScFlowintSet(0, a + 1)\n"
1860  " else\n"
1861  " ScFlowintSet(0, 1)\n"
1862  " end\n"
1863  " \n"
1864  " a = ScFlowintGet(0)\n"
1865  " if a == 2 then\n"
1866  " print \"match\"\n"
1867  " return 1\n"
1868  " end\n"
1869  " return 0\n"
1870  "end\n"
1871  "return 0\n";
1872  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1873  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1874  "Host: www.emergingthreats.net\r\n\r\n";
1875  uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1876  "Host: www.openinfosecfoundation.org\r\n\r\n";
1877  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1878  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1879  TcpSession ssn;
1880  Flow f;
1881  ThreadVars th_v;
1882  DetectEngineThreadCtx *det_ctx;
1883 
1885 
1886  ut_script = script;
1887 
1888  memset(&th_v, 0, sizeof(th_v));
1889  memset(&f, 0, sizeof(f));
1890  memset(&ssn, 0, sizeof(ssn));
1891 
1892  Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1893  Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1894 
1895  FLOW_INITIALIZE(&f);
1896  f.protoctx = (void *)&ssn;
1897  f.proto = IPPROTO_TCP;
1898  f.flags |= FLOW_IPV4;
1899  f.alproto = ALPROTO_HTTP1;
1900 
1901  p1->flow = &f;
1905 
1906  p2->flow = &f;
1910 
1911  StreamTcpInitConfig(true);
1912 
1915  de_ctx->flags |= DE_QUIET;
1916 
1918  FAIL_IF_NULL(s);
1919 
1921  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1922 
1923  int r = AppLayerParserParse(
1924  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
1925  FAIL_IF(r != 0);
1926  HtpState *http_state = f.alstate;
1927  FAIL_IF_NULL(http_state);
1928 
1929  /* do detect for p1 */
1930  SCLogInfo("p1");
1931  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1932 
1933  FAIL_IF(PacketAlertCheck(p1, 1));
1934 
1935  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1936  FAIL_IF(r != 0);
1937  /* do detect for p2 */
1938  SCLogInfo("p2");
1939  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1940 
1941  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
1942 
1943  uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_INT);
1944  FAIL_IF(id == 0);
1945 
1946  FlowVar *fv = FlowVarGet(&f, id);
1947  FAIL_IF_NULL(fv);
1948 
1949  FAIL_IF(fv->data.fv_int.value != 2);
1950 
1953 
1954  StreamTcpFreeConfig(true);
1955  FLOW_DESTROY(&f);
1956  UTHFreePackets(&p1, 1);
1957  UTHFreePackets(&p2, 1);
1958  PASS;
1959 }
1960 
1961 /** \test http buffer, flowints */
1962 static int LuaMatchTest04a(void)
1963 {
1964  const char script[] = "function init (args)\n"
1965  " local needs = {}\n"
1966  " needs[\"http.request_headers\"] = tostring(true)\n"
1967  " needs[\"flowint\"] = {\"cnt\"}\n"
1968  " return needs\n"
1969  "end\n"
1970  "\n"
1971  "function match(args)\n"
1972  " print \"inspecting\""
1973  " a = SCFlowintGet(0)\n"
1974  " if a then\n"
1975  " SCFlowintSet(0, a + 1)\n"
1976  " else\n"
1977  " SCFlowintSet(0, 1)\n"
1978  " end\n"
1979  " \n"
1980  " a = SCFlowintGet(0)\n"
1981  " if a == 2 then\n"
1982  " print \"match\"\n"
1983  " return 1\n"
1984  " end\n"
1985  " return 0\n"
1986  "end\n"
1987  "return 0\n";
1988  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1989  uint8_t httpbuf1[] =
1990  "POST / HTTP/1.1\r\n"
1991  "Host: www.emergingthreats.net\r\n\r\n";
1992  uint8_t httpbuf2[] =
1993  "POST / HTTP/1.1\r\n"
1994  "Host: www.openinfosecfoundation.org\r\n\r\n";
1995  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1996  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1997  TcpSession ssn;
1998  Flow f;
1999  ThreadVars th_v;
2000  DetectEngineThreadCtx *det_ctx;
2001 
2003 
2004  ut_script = script;
2005 
2006  memset(&th_v, 0, sizeof(th_v));
2007  memset(&f, 0, sizeof(f));
2008  memset(&ssn, 0, sizeof(ssn));
2009 
2010  Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2011  Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2012 
2013  FLOW_INITIALIZE(&f);
2014  f.protoctx = (void *)&ssn;
2015  f.proto = IPPROTO_TCP;
2016  f.flags |= FLOW_IPV4;
2017  f.alproto = ALPROTO_HTTP1;
2018 
2019  p1->flow = &f;
2023 
2024  p2->flow = &f;
2028 
2029  StreamTcpInitConfig(true);
2030 
2033  de_ctx->flags |= DE_QUIET;
2034 
2036  FAIL_IF_NULL(s);
2037 
2039  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2040 
2041  int r = AppLayerParserParse(
2042  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
2043  FAIL_IF(r != 0);
2044  HtpState *http_state = f.alstate;
2045  FAIL_IF_NULL(http_state);
2046 
2047  /* do detect for p1 */
2048  SCLogInfo("p1");
2049  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
2050 
2051  FAIL_IF(PacketAlertCheck(p1, 1));
2052 
2053  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
2054  FAIL_IF(r != 0);
2055  /* do detect for p2 */
2056  SCLogInfo("p2");
2057  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
2058 
2059  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
2060 
2061  uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_INT);
2062  FAIL_IF(id == 0);
2063 
2064  FlowVar *fv = FlowVarGet(&f, id);
2065  FAIL_IF_NULL(fv);
2066 
2067  FAIL_IF(fv->data.fv_int.value != 2);
2068 
2071 
2072  StreamTcpFreeConfig(true);
2073  FLOW_DESTROY(&f);
2074  UTHFreePackets(&p1, 1);
2075  UTHFreePackets(&p2, 1);
2076  PASS;
2077 }
2078 
2079 /** \test http buffer, flowints */
2080 static int LuaMatchTest05(void)
2081 {
2082  const char script[] = "function init (args)\n"
2083  " local needs = {}\n"
2084  " needs[\"http.request_headers\"] = tostring(true)\n"
2085  " needs[\"flowint\"] = {\"cnt\"}\n"
2086  " return needs\n"
2087  "end\n"
2088  "\n"
2089  "function match(args)\n"
2090  " print \"inspecting\""
2091  " a = ScFlowintIncr(0)\n"
2092  " if a == 2 then\n"
2093  " print \"match\"\n"
2094  " return 1\n"
2095  " end\n"
2096  " return 0\n"
2097  "end\n"
2098  "return 0\n";
2099  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
2100  uint8_t httpbuf1[] =
2101  "POST / HTTP/1.1\r\n"
2102  "Host: www.emergingthreats.net\r\n\r\n";
2103  uint8_t httpbuf2[] =
2104  "POST / HTTP/1.1\r\n"
2105  "Host: www.openinfosecfoundation.org\r\n\r\n";
2106  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2107  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2108  TcpSession ssn;
2109  Flow f;
2110  ThreadVars th_v;
2111  DetectEngineThreadCtx *det_ctx;
2112 
2114 
2115  ut_script = script;
2116 
2117  memset(&th_v, 0, sizeof(th_v));
2118  memset(&f, 0, sizeof(f));
2119  memset(&ssn, 0, sizeof(ssn));
2120 
2121  Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2122  Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2123 
2124  FLOW_INITIALIZE(&f);
2125  f.protoctx = (void *)&ssn;
2126  f.proto = IPPROTO_TCP;
2127  f.flags |= FLOW_IPV4;
2128  f.alproto = ALPROTO_HTTP1;
2129 
2130  p1->flow = &f;
2134 
2135  p2->flow = &f;
2139 
2140  StreamTcpInitConfig(true);
2141 
2144  de_ctx->flags |= DE_QUIET;
2145 
2147  FAIL_IF_NULL(s);
2148 
2150  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2151 
2152  int r = AppLayerParserParse(
2153  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
2154  FAIL_IF(r != 0);
2155  HtpState *http_state = f.alstate;
2156  FAIL_IF_NULL(http_state);
2157 
2158  /* do detect for p1 */
2159  SCLogInfo("p1");
2160  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
2161 
2162  FAIL_IF(PacketAlertCheck(p1, 1));
2163 
2164  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
2165  FAIL_IF(r != 0);
2166  /* do detect for p2 */
2167  SCLogInfo("p2");
2168  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
2169 
2170  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
2171 
2172  uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_INT);
2173  FAIL_IF(id == 0);
2174 
2175  FlowVar *fv = FlowVarGet(&f, id);
2176  FAIL_IF_NULL(fv);
2177 
2178  FAIL_IF(fv->data.fv_int.value != 2);
2179 
2182 
2183  StreamTcpFreeConfig(true);
2184  FLOW_DESTROY(&f);
2185  UTHFreePackets(&p1, 1);
2186  UTHFreePackets(&p2, 1);
2187  PASS;
2188 }
2189 
2190 /** \test http buffer, flowints */
2191 static int LuaMatchTest05a(void)
2192 {
2193  const char script[] = "function init (args)\n"
2194  " local needs = {}\n"
2195  " needs[\"http.request_headers\"] = tostring(true)\n"
2196  " needs[\"flowint\"] = {\"cnt\"}\n"
2197  " return needs\n"
2198  "end\n"
2199  "\n"
2200  "function match(args)\n"
2201  " print \"inspecting\""
2202  " a = SCFlowintIncr(0)\n"
2203  " if a == 2 then\n"
2204  " print \"match\"\n"
2205  " return 1\n"
2206  " end\n"
2207  " return 0\n"
2208  "end\n"
2209  "return 0\n";
2210  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
2211  uint8_t httpbuf1[] =
2212  "POST / HTTP/1.1\r\n"
2213  "Host: www.emergingthreats.net\r\n\r\n";
2214  uint8_t httpbuf2[] =
2215  "POST / HTTP/1.1\r\n"
2216  "Host: www.openinfosecfoundation.org\r\n\r\n";
2217  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2218  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2219  TcpSession ssn;
2220  Flow f;
2221  ThreadVars th_v;
2222  DetectEngineThreadCtx *det_ctx;
2223 
2225 
2226  ut_script = script;
2227 
2228  memset(&th_v, 0, sizeof(th_v));
2229  memset(&f, 0, sizeof(f));
2230  memset(&ssn, 0, sizeof(ssn));
2231 
2232  Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2233  Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2234 
2235  FLOW_INITIALIZE(&f);
2236  f.protoctx = (void *)&ssn;
2237  f.proto = IPPROTO_TCP;
2238  f.flags |= FLOW_IPV4;
2239  f.alproto = ALPROTO_HTTP1;
2240 
2241  p1->flow = &f;
2245 
2246  p2->flow = &f;
2250 
2251  StreamTcpInitConfig(true);
2252 
2255  de_ctx->flags |= DE_QUIET;
2256 
2258  FAIL_IF_NULL(s);
2259 
2261  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2262 
2263  int r = AppLayerParserParse(
2264  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
2265  FAIL_IF(r != 0);
2266  HtpState *http_state = f.alstate;
2267  FAIL_IF_NULL(http_state);
2268 
2269  /* do detect for p1 */
2270  SCLogInfo("p1");
2271  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
2272 
2273  FAIL_IF(PacketAlertCheck(p1, 1));
2274 
2275  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
2276  FAIL_IF(r != 0);
2277  /* do detect for p2 */
2278  SCLogInfo("p2");
2279  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
2280 
2281  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
2282 
2283  uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_INT);
2284  FAIL_IF(id == 0);
2285 
2286  FlowVar *fv = FlowVarGet(&f, id);
2287  FAIL_IF_NULL(fv);
2288 
2289  FAIL_IF(fv->data.fv_int.value != 2);
2290 
2293 
2294  StreamTcpFreeConfig(true);
2295  FLOW_DESTROY(&f);
2296  UTHFreePackets(&p1, 1);
2297  UTHFreePackets(&p2, 1);
2298  PASS;
2299 }
2300 
2301 /** \test http buffer, flowints */
2302 static int LuaMatchTest06(void)
2303 {
2304  const char script[] = "function init (args)\n"
2305  " local needs = {}\n"
2306  " needs[\"http.request_headers\"] = tostring(true)\n"
2307  " needs[\"flowint\"] = {\"cnt\"}\n"
2308  " return needs\n"
2309  "end\n"
2310  "\n"
2311  "function match(args)\n"
2312  " print \"inspecting\""
2313  " a = ScFlowintGet(0)\n"
2314  " if a == nil then\n"
2315  " print \"new var set to 2\""
2316  " ScFlowintSet(0, 2)\n"
2317  " end\n"
2318  " a = ScFlowintDecr(0)\n"
2319  " if a == 0 then\n"
2320  " print \"match\"\n"
2321  " return 1\n"
2322  " end\n"
2323  " return 0\n"
2324  "end\n"
2325  "return 0\n";
2326  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
2327  uint8_t httpbuf1[] =
2328  "POST / HTTP/1.1\r\n"
2329  "Host: www.emergingthreats.net\r\n\r\n";
2330  uint8_t httpbuf2[] =
2331  "POST / HTTP/1.1\r\n"
2332  "Host: www.openinfosecfoundation.org\r\n\r\n";
2333  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2334  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2335  TcpSession ssn;
2336  Flow f;
2337  ThreadVars th_v;
2338  DetectEngineThreadCtx *det_ctx;
2339 
2341 
2342  ut_script = script;
2343 
2344  memset(&th_v, 0, sizeof(th_v));
2345  memset(&f, 0, sizeof(f));
2346  memset(&ssn, 0, sizeof(ssn));
2347 
2348  Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2349  Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2350 
2351  FLOW_INITIALIZE(&f);
2352  f.protoctx = (void *)&ssn;
2353  f.proto = IPPROTO_TCP;
2354  f.flags |= FLOW_IPV4;
2355  f.alproto = ALPROTO_HTTP1;
2356 
2357  p1->flow = &f;
2361 
2362  p2->flow = &f;
2366 
2367  StreamTcpInitConfig(true);
2368 
2371  de_ctx->flags |= DE_QUIET;
2372 
2374  FAIL_IF_NULL(s);
2375 
2377  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2378 
2379  int r = AppLayerParserParse(
2380  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
2381  FAIL_IF(r != 0);
2382  HtpState *http_state = f.alstate;
2383  FAIL_IF_NULL(http_state);
2384 
2385  /* do detect for p1 */
2386  SCLogInfo("p1");
2387  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
2388 
2389  FAIL_IF(PacketAlertCheck(p1, 1));
2390 
2391  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
2392  FAIL_IF(r != 0);
2393  /* do detect for p2 */
2394  SCLogInfo("p2");
2395  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
2396 
2397  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
2398 
2399  uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_INT);
2400  FAIL_IF(id == 0);
2401 
2402  FlowVar *fv = FlowVarGet(&f, id);
2403  FAIL_IF_NULL(fv);
2404 
2405  FAIL_IF(fv->data.fv_int.value != 0);
2406 
2409 
2410  StreamTcpFreeConfig(true);
2411  FLOW_DESTROY(&f);
2412  UTHFreePackets(&p1, 1);
2413  UTHFreePackets(&p2, 1);
2414  PASS;
2415 }
2416 
2417 /** \test http buffer, flowints */
2418 static int LuaMatchTest06a(void)
2419 {
2420  const char script[] = "function init (args)\n"
2421  " local needs = {}\n"
2422  " needs[\"http.request_headers\"] = tostring(true)\n"
2423  " needs[\"flowint\"] = {\"cnt\"}\n"
2424  " return needs\n"
2425  "end\n"
2426  "\n"
2427  "function match(args)\n"
2428  " print \"inspecting\""
2429  " a = SCFlowintGet(0)\n"
2430  " if a == nil then\n"
2431  " print \"new var set to 2\""
2432  " SCFlowintSet(0, 2)\n"
2433  " end\n"
2434  " a = SCFlowintDecr(0)\n"
2435  " if a == 0 then\n"
2436  " print \"match\"\n"
2437  " return 1\n"
2438  " end\n"
2439  " return 0\n"
2440  "end\n"
2441  "return 0\n";
2442  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
2443  uint8_t httpbuf1[] =
2444  "POST / HTTP/1.1\r\n"
2445  "Host: www.emergingthreats.net\r\n\r\n";
2446  uint8_t httpbuf2[] =
2447  "POST / HTTP/1.1\r\n"
2448  "Host: www.openinfosecfoundation.org\r\n\r\n";
2449  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2450  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2451  TcpSession ssn;
2452  Flow f;
2453  ThreadVars th_v;
2454  DetectEngineThreadCtx *det_ctx;
2455 
2457 
2458  ut_script = script;
2459 
2460  memset(&th_v, 0, sizeof(th_v));
2461  memset(&f, 0, sizeof(f));
2462  memset(&ssn, 0, sizeof(ssn));
2463 
2464  Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2465  Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2466 
2467  FLOW_INITIALIZE(&f);
2468  f.protoctx = (void *)&ssn;
2469  f.proto = IPPROTO_TCP;
2470  f.flags |= FLOW_IPV4;
2471  f.alproto = ALPROTO_HTTP1;
2472 
2473  p1->flow = &f;
2477 
2478  p2->flow = &f;
2482 
2483  StreamTcpInitConfig(true);
2484 
2487  de_ctx->flags |= DE_QUIET;
2488 
2490  FAIL_IF_NULL(s);
2491 
2493  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2494 
2495  int r = AppLayerParserParse(
2496  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
2497  FAIL_IF(r != 0);
2498  HtpState *http_state = f.alstate;
2499  FAIL_IF_NULL(http_state);
2500 
2501  /* do detect for p1 */
2502  SCLogInfo("p1");
2503  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
2504 
2505  FAIL_IF(PacketAlertCheck(p1, 1));
2506 
2507  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
2508  FAIL_IF(r != 0);
2509  /* do detect for p2 */
2510  SCLogInfo("p2");
2511  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
2512 
2513  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
2514 
2515  uint32_t id = VarNameStoreLookupByName("cnt", VAR_TYPE_FLOW_INT);
2516  FAIL_IF(id == 0);
2517 
2518  FlowVar *fv = FlowVarGet(&f, id);
2519  FAIL_IF_NULL(fv);
2520 
2521  FAIL_IF(fv->data.fv_int.value != 0);
2522 
2525 
2526  StreamTcpFreeConfig(true);
2527  FLOW_DESTROY(&f);
2528  UTHFreePackets(&p1, 1);
2529  UTHFreePackets(&p2, 1);
2530  PASS;
2531 }
2532 
2533 void DetectLuaRegisterTests(void)
2534 {
2535  UtRegisterTest("LuaMatchTest01", LuaMatchTest01);
2536  UtRegisterTest("LuaMatchTest01a", LuaMatchTest01a);
2537  UtRegisterTest("LuaMatchTest02", LuaMatchTest02);
2538  UtRegisterTest("LuaMatchTest02a", LuaMatchTest02a);
2539  UtRegisterTest("LuaMatchTest03", LuaMatchTest03);
2540  UtRegisterTest("LuaMatchTest03a", LuaMatchTest03a);
2541  UtRegisterTest("LuaMatchTest04", LuaMatchTest04);
2542  UtRegisterTest("LuaMatchTest04a", LuaMatchTest04a);
2543  UtRegisterTest("LuaMatchTest05", LuaMatchTest05);
2544  UtRegisterTest("LuaMatchTest05a", LuaMatchTest05a);
2545  UtRegisterTest("LuaMatchTest06", LuaMatchTest06);
2546  UtRegisterTest("LuaMatchTest06a", LuaMatchTest06a);
2547 }
2548 #endif
2549 #endif /* HAVE_LUAJIT */
util-byte.h
SigTableElmt_::url
const char * url
Definition: detect.h:1299
detect-engine.h
DETECT_SM_LIST_PMATCH
@ DETECT_SM_LIST_PMATCH
Definition: detect.h:116
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
SignatureInitData_::smlists
struct SigMatch_ * smlists[DETECT_SM_LIST_MAX]
Definition: detect.h:581
SigTableElmt_::desc
const char * desc
Definition: detect.h:1298
PKT_HAS_FLOW
#define PKT_HAS_FLOW
Definition: decode.h:1022
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1286
flow-util.h
ALPROTO_DNS
@ ALPROTO_DNS
Definition: app-layer-protos.h:41
SigTableElmt_::name
const char * name
Definition: detect.h:1296
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:3581
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:601
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
FlowVar_::data
union FlowVar_::@112 data
Flow_::proto
uint8_t proto
Definition: flow.h:373
util-lua.h
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:81
Packet_::payload
uint8_t * payload
Definition: decode.h:586
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:1178
FlowVarTypeStr::value_len
uint16_t value_len
Definition: flow-var.h:39
SigMatchData_::ctx
SigMatchCtx * ctx
Definition: detect.h:362
Packet_::flags
uint32_t flags
Definition: decode.h:474
threads.h
Flow_
Flow data structure.
Definition: flow.h:351
SigTableElmt_::flags
uint16_t flags
Definition: detect.h:1290
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:839
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:2533
detect-lua.h
SigTableElmt_::AppLayerTxMatch
int(* AppLayerTxMatch)(DetectEngineThreadCtx *, Flow *, uint8_t flags, void *alstate, void *txv, const Signature *, const SigMatchCtx *)
Definition: detect.h:1267
AppLayerParserThreadCtxFree
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
Definition: app-layer-parser.c:312
FLOW_PKT_TOSERVER
#define FLOW_PKT_TOSERVER
Definition: flow.h:223
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:324
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:340
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1897
StringParseInt32
int StringParseInt32(int32_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:622
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:2620
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:468
DetectBufferGetActiveList
int DetectBufferGetActiveList(DetectEngineCtx *de_ctx, Signature *s)
Definition: detect-engine.c:1403
SIG_FLAG_TOCLIENT
#define SIG_FLAG_TOCLIENT
Definition: detect.h:267
Flow_::protoctx
void * protoctx
Definition: flow.h:441
SigMatchData_
Data needed for Match()
Definition: detect.h:359
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1281
FLOW_IPV4
#define FLOW_IPV4
Definition: flow.h:97
Packet_::payload_len
uint16_t payload_len
Definition: decode.h:587
AppLayerParserGetTransactionInspectId
uint64_t AppLayerParserGetTransactionInspectId(AppLayerParserState *pstate, uint8_t direction)
Definition: app-layer-parser.c:721
DetectByteIndexType
uint8_t DetectByteIndexType
Definition: detect-byte.h:28
util-unittest.h
HtpState_
Definition: app-layer-htp.h:244
SIGMATCH_NOT_BUILT
#define SIGMATCH_NOT_BUILT
Definition: detect.h:1482
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:1072
Signature_::gid
uint32_t gid
Definition: detect.h:632
FlowVar_::fv_int
FlowVarTypeInt fv_int
Definition: flow-var.h:58
Flow_::alparser
AppLayerParserState * alparser
Definition: flow.h:475
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:463
FLOW_INITIALIZE
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:38
SIG_FLAG_TOSERVER
#define SIG_FLAG_TOSERVER
Definition: detect.h:266
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
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:1095
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:228
SignatureInitData_::list
int list
Definition: detect.h:565
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:271
GET_PKT_DATA
#define GET_PKT_DATA(p)
Definition: decode.h:221
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:354
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:114
app-layer-parser.h
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:353
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:300
Packet_
Definition: decode.h:437
detect-engine-build.h
type
uint16_t type
Definition: decode-vlan.c:107
GET_PKT_LEN
#define GET_PKT_LEN(p)
Definition: decode.h:220
detect-engine-alert.h
conf.h
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:665
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:1264
queue.h
detect-byte.h
FLOW_PKT_TOCLIENT
#define FLOW_PKT_TOCLIENT
Definition: flow.h:224
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:1114
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:2149
AppLayerParserThreadCtxAlloc
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
Definition: app-layer-parser.c:291
SigMatchCtx_
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:345
FlowVarTypeStr::value
uint8_t * value
Definition: flow-var.h:38
Packet_::flow
struct Flow_ * flow
Definition: decode.h:476
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
Definition: detect-engine.c:3244
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:40
DetectBufferTypeRegister
int DetectBufferTypeRegister(const char *name)
Definition: detect-engine.c:1008
StreamTcpFreeConfig
void StreamTcpFreeConfig(bool quiet)
Definition: stream-tcp.c:794
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:3511
SigTableElmt_::alias
const char * alias
Definition: detect.h:1297
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:1292
detect-lua-extensions.h
suricata-common.h
SigMatch_::type
uint16_t type
Definition: detect.h:351
ALPROTO_HTTP1
@ ALPROTO_HTTP1
Definition: app-layer-protos.h:30
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:127
HtpState_::connp
htp_connp_t * connp
Definition: app-layer-htp.h:246
lua_State
void lua_State
Definition: suricata-common.h:500
Signature_::rev
uint32_t rev
Definition: detect.h:633
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:2079
str
#define str(s)
Definition: suricata-common.h:291
DetectEngineThreadCtx_::tv
ThreadVars * tv
Definition: detect.h:1103
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:476
Signature_::id
uint32_t id
Definition: detect.h:631
Flow_::flags
uint32_t flags
Definition: flow.h:421
detect-parse.h
Signature_
Signature container.
Definition: detect.h:596
SigMatch_
a single match condition for a signature
Definition: detect.h:350
AppLayerGetProtoName
const char * AppLayerGetProtoName(AppProto alproto)
Given the internal protocol id, returns a string representation of the protocol.
Definition: app-layer.c:1005
VAR_TYPE_FLOW_VAR
@ VAR_TYPE_FLOW_VAR
Definition: util-var.h:37
DETECT_SM_LIST_MAX
@ DETECT_SM_LIST_MAX
Definition: detect.h:132
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:225
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2494
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:63
DetectAppLayerInspectEngineRegister
void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uint32_t dir, int progress, InspectEngineFuncPtr Callback, InspectionBufferGetDataPtr GetData)
register inspect engine at start up time
Definition: detect-engine.c:169
SigMatchAppendSMToList
SigMatch * SigMatchAppendSMToList(DetectEngineCtx *de_ctx, Signature *s, uint16_t type, SigMatchCtx *ctx, const int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:447
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:841
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:65
DetectUnregisterThreadCtxFuncs
int DetectUnregisterThreadCtxFuncs(DetectEngineCtx *de_ctx, void *data, const char *name)
Remove Thread keyword context registration.
Definition: detect-engine.c:3563
TcpSession_
Definition: stream-tcp-private.h:283
flow.h
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:450
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
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:1107
FlowVar_
Definition: flow-var.h:48
FLOW_DESTROY
#define FLOW_DESTROY(f)
Definition: flow-util.h:121
PKT_STREAM_EST
#define PKT_STREAM_EST
Definition: decode.h:1019
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1288
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:431