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 = VarNameStoreSetupAdd((char *)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 = VarNameStoreSetupAdd((char *)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  lua = DetectLuaParse(de_ctx, str);
1019  if (lua == NULL)
1020  goto error;
1021 
1022  if (DetectLuaSetupPrime(de_ctx, lua, s) == -1) {
1023  goto error;
1024  }
1025 
1026  lua->thread_ctx_id = DetectRegisterThreadCtxFuncs(de_ctx, "lua",
1027  DetectLuaThreadInit, (void *)lua,
1028  DetectLuaThreadFree, 0);
1029  if (lua->thread_ctx_id == -1)
1030  goto error;
1031 
1032  if (lua->alproto != ALPROTO_UNKNOWN) {
1033  if (s->alproto != ALPROTO_UNKNOWN && !AppProtoEquals(s->alproto, lua->alproto)) {
1034  goto error;
1035  }
1036  s->alproto = lua->alproto;
1037  }
1038 
1039  /* Okay so far so good, lets get this into a SigMatch
1040  * and put it in the Signature. */
1041  sm = SigMatchAlloc();
1042  if (sm == NULL)
1043  goto error;
1044 
1045  sm->type = DETECT_LUA;
1046  sm->ctx = (SigMatchCtx *)lua;
1047 
1048  int list = -1;
1049  if (lua->alproto == ALPROTO_UNKNOWN) {
1050  if (lua->flags & DATATYPE_STREAM)
1051  list = DETECT_SM_LIST_PMATCH;
1052  else {
1053  if (lua->flags & DATATYPE_BUFFER) {
1054  if (DetectBufferGetActiveList(de_ctx, s) != -1) {
1055  list = s->init_data->list;
1056  } else {
1057  SCLogError("Lua and sticky buffer failure");
1058  goto error;
1059  }
1060  } else
1061  list = DETECT_SM_LIST_MATCH;
1062  }
1063 
1064  } else if (lua->alproto == ALPROTO_HTTP1) {
1065  if (lua->flags & DATATYPE_HTTP_RESPONSE_BODY) {
1066  list = DetectBufferTypeGetByName("file_data");
1067  } else if (lua->flags & DATATYPE_HTTP_REQUEST_BODY) {
1068  list = DetectBufferTypeGetByName("http_client_body");
1069  } else if (lua->flags & DATATYPE_HTTP_URI) {
1070  list = DetectBufferTypeGetByName("http_uri");
1071  } else if (lua->flags & DATATYPE_HTTP_URI_RAW) {
1072  list = DetectBufferTypeGetByName("http_raw_uri");
1073  } else if (lua->flags & DATATYPE_HTTP_REQUEST_COOKIE ||
1074  lua->flags & DATATYPE_HTTP_RESPONSE_COOKIE)
1075  {
1076  list = DetectBufferTypeGetByName("http_cookie");
1077  } else if (lua->flags & DATATYPE_HTTP_REQUEST_UA) {
1078  list = DetectBufferTypeGetByName("http_user_agent");
1079  } else if (lua->flags & (DATATYPE_HTTP_REQUEST_HEADERS|DATATYPE_HTTP_RESPONSE_HEADERS)) {
1080  list = DetectBufferTypeGetByName("http_header");
1081  } else if (lua->flags & (DATATYPE_HTTP_REQUEST_HEADERS_RAW|DATATYPE_HTTP_RESPONSE_HEADERS_RAW)) {
1082  list = DetectBufferTypeGetByName("http_raw_header");
1083  } else {
1084  list = DetectBufferTypeGetByName("http_request_line");
1085  }
1086  } else if (lua->alproto == ALPROTO_DNS) {
1087  if (lua->flags & DATATYPE_DNS_RRNAME) {
1088  list = DetectBufferTypeGetByName("dns_query");
1089  } else if (lua->flags & DATATYPE_DNS_REQUEST) {
1090  list = DetectBufferTypeGetByName("dns_request");
1091  } else if (lua->flags & DATATYPE_DNS_RESPONSE) {
1092  list = DetectBufferTypeGetByName("dns_response");
1093  }
1094  } else if (lua->alproto == ALPROTO_TLS) {
1095  list = DetectBufferTypeGetByName("tls_generic");
1096  } else if (lua->alproto == ALPROTO_SSH) {
1097  list = DetectBufferTypeGetByName("ssh_banner");
1098  } else if (lua->alproto == ALPROTO_SMTP) {
1099  list = g_smtp_generic_list_id;
1100  } else if (lua->alproto == ALPROTO_DNP3) {
1101  list = DetectBufferTypeGetByName("dnp3");
1102  } else {
1103  SCLogError("lua can't be used with protocol %s", AppLayerGetProtoName(lua->alproto));
1104  goto error;
1105  }
1106 
1107  if (list == -1) {
1108  SCLogError("lua can't be used with protocol %s", AppLayerGetProtoName(lua->alproto));
1109  goto error;
1110  }
1111 
1112  SigMatchAppendSMToList(s, sm, list);
1113 
1114  return 0;
1115 
1116 error:
1117  if (lua != NULL)
1118  DetectLuaFree(de_ctx, lua);
1119  if (sm != NULL)
1120  SCFree(sm);
1121  return -1;
1122 }
1123 
1124 /** \brief post-sig parse function to set the sid,rev,gid into the
1125  * ctx, as this isn't available yet during parsing.
1126  */
1128 {
1129  int i;
1130  SigMatch *sm;
1131 
1132  for (i = 0; i < DETECT_SM_LIST_MAX; i++) {
1133  for (sm = s->init_data->smlists[i]; sm != NULL; sm = sm->next) {
1134  if (sm->type != DETECT_LUA)
1135  continue;
1136 
1137  DetectLuaData *ld = (DetectLuaData *)sm->ctx;
1138  ld->sid = s->id;
1139  ld->rev = s->rev;
1140  ld->gid = s->gid;
1141  }
1142  }
1143 }
1144 
1145 /**
1146  * \brief this function will free memory associated with DetectLuaData
1147  *
1148  * \param ptr pointer to DetectLuaData
1149  */
1150 static void DetectLuaFree(DetectEngineCtx *de_ctx, void *ptr)
1151 {
1152  if (ptr != NULL) {
1153  DetectLuaData *lua = (DetectLuaData *)ptr;
1154 
1155  if (lua->buffername)
1156  SCFree(lua->buffername);
1157  if (lua->filename)
1158  SCFree(lua->filename);
1159 
1161 
1162  SCFree(lua);
1163  }
1164 }
1165 
1166 #ifdef UNITTESTS
1167 #include "detect-engine-alert.h"
1168 
1169 /** \test http buffer */
1170 static int LuaMatchTest01(void)
1171 {
1172  const char script[] =
1173  "function init (args)\n"
1174  " local needs = {}\n"
1175  " needs[\"http.request_headers\"] = tostring(true)\n"
1176  " needs[\"flowvar\"] = {\"cnt\"}\n"
1177  " return needs\n"
1178  "end\n"
1179  "\n"
1180  "function match(args)\n"
1181  " a = ScFlowvarGet(0)\n"
1182  " if a then\n"
1183  " a = tostring(tonumber(a)+1)\n"
1184  " print (a)\n"
1185  " ScFlowvarSet(0, a, #a)\n"
1186  " else\n"
1187  " a = tostring(1)\n"
1188  " print (a)\n"
1189  " ScFlowvarSet(0, a, #a)\n"
1190  " end\n"
1191  " \n"
1192  " print (\"pre check: \" .. (a))\n"
1193  " if tonumber(a) == 2 then\n"
1194  " print \"match\"\n"
1195  " return 1\n"
1196  " end\n"
1197  " return 0\n"
1198  "end\n"
1199  "return 0\n";
1200  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1201  uint8_t httpbuf1[] =
1202  "POST / HTTP/1.1\r\n"
1203  "Host: www.emergingthreats.net\r\n\r\n";
1204  uint8_t httpbuf2[] =
1205  "POST / HTTP/1.1\r\n"
1206  "Host: www.openinfosecfoundation.org\r\n\r\n";
1207  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1208  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1209  TcpSession ssn;
1210  Flow f;
1211  ThreadVars th_v;
1212  DetectEngineThreadCtx *det_ctx;
1213 
1215 
1216  ut_script = script;
1217 
1218  memset(&th_v, 0, sizeof(th_v));
1219  memset(&f, 0, sizeof(f));
1220  memset(&ssn, 0, sizeof(ssn));
1221 
1222  Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1223  Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1224 
1225  FLOW_INITIALIZE(&f);
1226  f.protoctx = (void *)&ssn;
1227  f.proto = IPPROTO_TCP;
1228  f.flags |= FLOW_IPV4;
1229  f.alproto = ALPROTO_HTTP1;
1230 
1231  p1->flow = &f;
1235  p2->flow = &f;
1239 
1240  StreamTcpInitConfig(true);
1241 
1244  de_ctx->flags |= DE_QUIET;
1245 
1247  FAIL_IF_NULL(s);
1248 
1250  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1251 
1252  int r = AppLayerParserParse(
1253  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
1254  FAIL_IF(r != 0);
1255  HtpState *http_state = f.alstate;
1256  FAIL_IF_NULL(http_state);
1257 
1258  /* do detect for p1 */
1259  SCLogDebug("inspecting p1");
1260  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1261 
1262  FAIL_IF(PacketAlertCheck(p1, 1));
1263 
1264  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1265  FAIL_IF(r != 0);
1266 
1267  /* do detect for p2 */
1268  SCLogDebug("inspecting p2");
1269  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1270 
1271  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
1272 
1273  FlowVar *fv = FlowVarGet(&f, 1);
1274  FAIL_IF_NULL(fv);
1275 
1276  FAIL_IF(fv->data.fv_str.value_len != 1);
1277 
1278  FAIL_IF(memcmp(fv->data.fv_str.value, "2", 1) != 0);
1279 
1282 
1283  StreamTcpFreeConfig(true);
1284  FLOW_DESTROY(&f);
1285  UTHFreePackets(&p1, 1);
1286  UTHFreePackets(&p2, 1);
1287  PASS;
1288 }
1289 
1290 static int LuaMatchTest01a(void)
1291 {
1292  const char script[] = "function init (args)\n"
1293  " local needs = {}\n"
1294  " needs[\"http.request_headers\"] = tostring(true)\n"
1295  " needs[\"flowvar\"] = {\"cnt\"}\n"
1296  " return needs\n"
1297  "end\n"
1298  "\n"
1299  "function match(args)\n"
1300  " a = SCFlowvarGet(0)\n"
1301  " if a then\n"
1302  " a = tostring(tonumber(a)+1)\n"
1303  " print (a)\n"
1304  " SCFlowvarSet(0, a, #a)\n"
1305  " else\n"
1306  " a = tostring(1)\n"
1307  " print (a)\n"
1308  " SCFlowvarSet(0, a, #a)\n"
1309  " end\n"
1310  " \n"
1311  " print (\"pre check: \" .. (a))\n"
1312  " if tonumber(a) == 2 then\n"
1313  " print \"match\"\n"
1314  " return 1\n"
1315  " end\n"
1316  " return 0\n"
1317  "end\n"
1318  "return 0\n";
1319  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1320  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1321  "Host: www.emergingthreats.net\r\n\r\n";
1322  uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1323  "Host: www.openinfosecfoundation.org\r\n\r\n";
1324  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1325  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1326  TcpSession ssn;
1327  Flow f;
1328  ThreadVars th_v;
1329  DetectEngineThreadCtx *det_ctx;
1330 
1332 
1333  ut_script = script;
1334 
1335  memset(&th_v, 0, sizeof(th_v));
1336  memset(&f, 0, sizeof(f));
1337  memset(&ssn, 0, sizeof(ssn));
1338 
1339  Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1340  Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1341 
1342  FLOW_INITIALIZE(&f);
1343  f.protoctx = (void *)&ssn;
1344  f.proto = IPPROTO_TCP;
1345  f.flags |= FLOW_IPV4;
1346  f.alproto = ALPROTO_HTTP1;
1347 
1348  p1->flow = &f;
1352  p2->flow = &f;
1356 
1357  StreamTcpInitConfig(true);
1358 
1361  de_ctx->flags |= DE_QUIET;
1362 
1364  FAIL_IF_NULL(s);
1365 
1367  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1368 
1369  int r = AppLayerParserParse(
1370  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
1371  FAIL_IF(r != 0);
1372 
1373  HtpState *http_state = f.alstate;
1374  FAIL_IF_NULL(http_state);
1375 
1376  /* do detect for p1 */
1377  SCLogDebug("inspecting p1");
1378  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1379 
1380  FAIL_IF(PacketAlertCheck(p1, 1));
1381 
1382  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1383  FAIL_IF(r != 0);
1384  /* do detect for p2 */
1385  SCLogDebug("inspecting p2");
1386  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1387 
1388  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
1389 
1390  FlowVar *fv = FlowVarGet(&f, 1);
1391  FAIL_IF_NULL(fv);
1392 
1393  FAIL_IF(fv->data.fv_str.value_len != 1);
1394 
1395  FAIL_IF(memcmp(fv->data.fv_str.value, "2", 1) != 0);
1396 
1399 
1400  StreamTcpFreeConfig(true);
1401  FLOW_DESTROY(&f);
1402  UTHFreePackets(&p1, 1);
1403  UTHFreePackets(&p2, 1);
1404  PASS;
1405 }
1406 
1407 /** \test payload buffer */
1408 static int LuaMatchTest02(void)
1409 {
1410  const char script[] = "function init (args)\n"
1411  " local needs = {}\n"
1412  " needs[\"payload\"] = tostring(true)\n"
1413  " needs[\"flowvar\"] = {\"cnt\"}\n"
1414  " return needs\n"
1415  "end\n"
1416  "\n"
1417  "function match(args)\n"
1418  " a = ScFlowvarGet(0)\n"
1419  " if a then\n"
1420  " a = tostring(tonumber(a)+1)\n"
1421  " print (a)\n"
1422  " ScFlowvarSet(0, a, #a)\n"
1423  " else\n"
1424  " a = tostring(1)\n"
1425  " print (a)\n"
1426  " ScFlowvarSet(0, a, #a)\n"
1427  " end\n"
1428  " \n"
1429  " print (\"pre check: \" .. (a))\n"
1430  " if tonumber(a) == 2 then\n"
1431  " print \"match\"\n"
1432  " return 1\n"
1433  " end\n"
1434  " return 0\n"
1435  "end\n"
1436  "return 0\n";
1437  char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1438  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1439  "Host: www.emergingthreats.net\r\n\r\n";
1440  uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1441  "Host: www.openinfosecfoundation.org\r\n\r\n";
1442  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1443  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1444  TcpSession ssn;
1445  Flow f;
1446  ThreadVars th_v;
1447  DetectEngineThreadCtx *det_ctx;
1448 
1449  ut_script = script;
1450 
1451  memset(&th_v, 0, sizeof(th_v));
1452  memset(&f, 0, sizeof(f));
1453  memset(&ssn, 0, sizeof(ssn));
1454 
1455  Packet *p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP);
1456  Packet *p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP);
1457 
1458  FLOW_INITIALIZE(&f);
1459  f.protoctx = (void *)&ssn;
1460  f.proto = IPPROTO_TCP;
1461  f.flags |= FLOW_IPV4;
1462  f.alproto = ALPROTO_HTTP1;
1463 
1464  p1->flow = &f;
1468  p2->flow = &f;
1472 
1473  StreamTcpInitConfig(true);
1474 
1477  de_ctx->flags |= DE_QUIET;
1478 
1480  FAIL_IF_NULL(s);
1481 
1483  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1484 
1485  /* do detect for p1 */
1486  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1487 
1488  FAIL_IF(PacketAlertCheck(p1, 1));
1489 
1490  /* do detect for p2 */
1491  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1492 
1493  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
1494 
1495  FlowVar *fv = FlowVarGet(&f, 1);
1496  FAIL_IF_NULL(fv);
1497 
1498  FAIL_IF(fv->data.fv_str.value_len != 1);
1499 
1500  FAIL_IF(memcmp(fv->data.fv_str.value, "2", 1) != 0);
1501 
1503 
1504  StreamTcpFreeConfig(true);
1505  FLOW_DESTROY(&f);
1506  UTHFreePackets(&p1, 1);
1507  UTHFreePackets(&p2, 1);
1508  PASS;
1509 }
1510 
1511 /** \test payload buffer */
1512 static int LuaMatchTest02a(void)
1513 {
1514  const char script[] = "function init (args)\n"
1515  " local needs = {}\n"
1516  " needs[\"payload\"] = tostring(true)\n"
1517  " needs[\"flowvar\"] = {\"cnt\"}\n"
1518  " return needs\n"
1519  "end\n"
1520  "\n"
1521  "function match(args)\n"
1522  " a = SCFlowvarGet(0)\n"
1523  " if a then\n"
1524  " a = tostring(tonumber(a)+1)\n"
1525  " print (a)\n"
1526  " SCFlowvarSet(0, a, #a)\n"
1527  " else\n"
1528  " a = tostring(1)\n"
1529  " print (a)\n"
1530  " SCFlowvarSet(0, a, #a)\n"
1531  " end\n"
1532  " \n"
1533  " print (\"pre check: \" .. (a))\n"
1534  " if tonumber(a) == 2 then\n"
1535  " print \"match\"\n"
1536  " return 1\n"
1537  " end\n"
1538  " return 0\n"
1539  "end\n"
1540  "return 0\n";
1541  char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1542  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1543  "Host: www.emergingthreats.net\r\n\r\n";
1544  uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1545  "Host: www.openinfosecfoundation.org\r\n\r\n";
1546  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1547  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1548  TcpSession ssn;
1549  Flow f;
1550  ThreadVars th_v;
1551  DetectEngineThreadCtx *det_ctx;
1552 
1553  ut_script = script;
1554 
1555  memset(&th_v, 0, sizeof(th_v));
1556  memset(&f, 0, sizeof(f));
1557  memset(&ssn, 0, sizeof(ssn));
1558 
1559  Packet *p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP);
1560  Packet *p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP);
1561 
1562  FLOW_INITIALIZE(&f);
1563  f.protoctx = (void *)&ssn;
1564  f.proto = IPPROTO_TCP;
1565  f.flags |= FLOW_IPV4;
1566  f.alproto = ALPROTO_HTTP1;
1567 
1568  p1->flow = &f;
1572  p2->flow = &f;
1576 
1577  StreamTcpInitConfig(true);
1578 
1581  de_ctx->flags |= DE_QUIET;
1582 
1584  FAIL_IF_NULL(s);
1585 
1587  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1588 
1589  /* do detect for p1 */
1590  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1591  FAIL_IF(PacketAlertCheck(p1, 1));
1592 
1593  /* do detect for p2 */
1594  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1595 
1596  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
1597 
1598  FlowVar *fv = FlowVarGet(&f, 1);
1599  FAIL_IF_NULL(fv);
1600 
1601  FAIL_IF(fv->data.fv_str.value_len != 1);
1602 
1603  FAIL_IF(memcmp(fv->data.fv_str.value, "2", 1) != 0);
1604 
1606 
1607  StreamTcpFreeConfig(true);
1608  FLOW_DESTROY(&f);
1609  UTHFreePackets(&p1, 1);
1610  UTHFreePackets(&p2, 1);
1611  PASS;
1612 }
1613 
1614 /** \test packet buffer */
1615 static int LuaMatchTest03(void)
1616 {
1617  const char script[] = "function init (args)\n"
1618  " local needs = {}\n"
1619  " needs[\"packet\"] = tostring(true)\n"
1620  " needs[\"flowvar\"] = {\"cnt\"}\n"
1621  " return needs\n"
1622  "end\n"
1623  "\n"
1624  "function match(args)\n"
1625  " a = ScFlowvarGet(0)\n"
1626  " if a then\n"
1627  " a = tostring(tonumber(a)+1)\n"
1628  " print (a)\n"
1629  " ScFlowvarSet(0, a, #a)\n"
1630  " else\n"
1631  " a = tostring(1)\n"
1632  " print (a)\n"
1633  " ScFlowvarSet(0, a, #a)\n"
1634  " end\n"
1635  " \n"
1636  " print (\"pre check: \" .. (a))\n"
1637  " if tonumber(a) == 2 then\n"
1638  " print \"match\"\n"
1639  " return 1\n"
1640  " end\n"
1641  " return 0\n"
1642  "end\n"
1643  "return 0\n";
1644  char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1645  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1646  "Host: www.emergingthreats.net\r\n\r\n";
1647  uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1648  "Host: www.openinfosecfoundation.org\r\n\r\n";
1649  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1650  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1651  TcpSession ssn;
1652  Flow f;
1653  ThreadVars th_v;
1654  DetectEngineThreadCtx *det_ctx;
1655 
1656  ut_script = script;
1657 
1658  memset(&th_v, 0, sizeof(th_v));
1659  memset(&f, 0, sizeof(f));
1660  memset(&ssn, 0, sizeof(ssn));
1661 
1662  Packet *p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP);
1663  Packet *p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP);
1664 
1665  FLOW_INITIALIZE(&f);
1666  f.protoctx = (void *)&ssn;
1667  f.proto = IPPROTO_TCP;
1668  f.flags |= FLOW_IPV4;
1669  f.alproto = ALPROTO_HTTP1;
1670 
1671  p1->flow = &f;
1675  p2->flow = &f;
1679 
1680  StreamTcpInitConfig(true);
1681 
1684  de_ctx->flags |= DE_QUIET;
1685 
1687  FAIL_IF_NULL(s);
1688 
1690  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1691 
1692  /* do detect for p1 */
1693  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1694  FAIL_IF(PacketAlertCheck(p1, 1));
1695 
1696  /* do detect for p2 */
1697  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1698 
1699  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
1700 
1701  FlowVar *fv = FlowVarGet(&f, 1);
1702  FAIL_IF_NULL(fv);
1703 
1704  FAIL_IF(fv->data.fv_str.value_len != 1);
1705 
1706  FAIL_IF(memcmp(fv->data.fv_str.value, "2", 1) != 0);
1707 
1709 
1710  StreamTcpFreeConfig(true);
1711  FLOW_DESTROY(&f);
1712  UTHFreePackets(&p1, 1);
1713  UTHFreePackets(&p2, 1);
1714  PASS;
1715 }
1716 
1717 /** \test packet buffer */
1718 static int LuaMatchTest03a(void)
1719 {
1720  const char script[] = "function init (args)\n"
1721  " local needs = {}\n"
1722  " needs[\"packet\"] = tostring(true)\n"
1723  " needs[\"flowvar\"] = {\"cnt\"}\n"
1724  " return needs\n"
1725  "end\n"
1726  "\n"
1727  "function match(args)\n"
1728  " a = SCFlowvarGet(0)\n"
1729  " if a then\n"
1730  " a = tostring(tonumber(a)+1)\n"
1731  " print (a)\n"
1732  " SCFlowvarSet(0, a, #a)\n"
1733  " else\n"
1734  " a = tostring(1)\n"
1735  " print (a)\n"
1736  " SCFlowvarSet(0, a, #a)\n"
1737  " end\n"
1738  " \n"
1739  " print (\"pre check: \" .. (a))\n"
1740  " if tonumber(a) == 2 then\n"
1741  " print \"match\"\n"
1742  " return 1\n"
1743  " end\n"
1744  " return 0\n"
1745  "end\n"
1746  "return 0\n";
1747  char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1748  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1749  "Host: www.emergingthreats.net\r\n\r\n";
1750  uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1751  "Host: www.openinfosecfoundation.org\r\n\r\n";
1752  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1753  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1754  TcpSession ssn;
1755  Flow f;
1756  ThreadVars th_v;
1757  DetectEngineThreadCtx *det_ctx;
1758 
1759  ut_script = script;
1760 
1761  memset(&th_v, 0, sizeof(th_v));
1762  memset(&f, 0, sizeof(f));
1763  memset(&ssn, 0, sizeof(ssn));
1764 
1765  Packet *p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP);
1766  Packet *p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP);
1767 
1768  FLOW_INITIALIZE(&f);
1769  f.protoctx = (void *)&ssn;
1770  f.proto = IPPROTO_TCP;
1771  f.flags |= FLOW_IPV4;
1772  f.alproto = ALPROTO_HTTP1;
1773 
1774  p1->flow = &f;
1778  p2->flow = &f;
1782 
1783  StreamTcpInitConfig(true);
1784 
1787  de_ctx->flags |= DE_QUIET;
1788 
1790  FAIL_IF_NULL(s);
1791 
1793  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1794 
1795  /* do detect for p1 */
1796  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1797  FAIL_IF(PacketAlertCheck(p1, 1));
1798 
1799  /* do detect for p2 */
1800  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1801  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
1802 
1803  FlowVar *fv = FlowVarGet(&f, 1);
1804  FAIL_IF_NULL(fv);
1805 
1806  FAIL_IF(fv->data.fv_str.value_len != 1);
1807 
1808  FAIL_IF(memcmp(fv->data.fv_str.value, "2", 1) != 0);
1809 
1811 
1812  StreamTcpFreeConfig(true);
1813  FLOW_DESTROY(&f);
1814  UTHFreePackets(&p1, 1);
1815  UTHFreePackets(&p2, 1);
1816  PASS;
1817 }
1818 
1819 /** \test http buffer, flowints */
1820 static int LuaMatchTest04(void)
1821 {
1822  const char script[] = "function init (args)\n"
1823  " local needs = {}\n"
1824  " needs[\"http.request_headers\"] = tostring(true)\n"
1825  " needs[\"flowint\"] = {\"cnt\"}\n"
1826  " return needs\n"
1827  "end\n"
1828  "\n"
1829  "function match(args)\n"
1830  " print \"inspecting\""
1831  " a = ScFlowintGet(0)\n"
1832  " if a then\n"
1833  " ScFlowintSet(0, a + 1)\n"
1834  " else\n"
1835  " ScFlowintSet(0, 1)\n"
1836  " end\n"
1837  " \n"
1838  " a = ScFlowintGet(0)\n"
1839  " if a == 2 then\n"
1840  " print \"match\"\n"
1841  " return 1\n"
1842  " end\n"
1843  " return 0\n"
1844  "end\n"
1845  "return 0\n";
1846  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1847  uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n"
1848  "Host: www.emergingthreats.net\r\n\r\n";
1849  uint8_t httpbuf2[] = "POST / HTTP/1.1\r\n"
1850  "Host: www.openinfosecfoundation.org\r\n\r\n";
1851  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1852  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1853  TcpSession ssn;
1854  Flow f;
1855  ThreadVars th_v;
1856  DetectEngineThreadCtx *det_ctx;
1857 
1859 
1860  ut_script = script;
1861 
1862  memset(&th_v, 0, sizeof(th_v));
1863  memset(&f, 0, sizeof(f));
1864  memset(&ssn, 0, sizeof(ssn));
1865 
1866  Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1867  Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1868 
1869  FLOW_INITIALIZE(&f);
1870  f.protoctx = (void *)&ssn;
1871  f.proto = IPPROTO_TCP;
1872  f.flags |= FLOW_IPV4;
1873  f.alproto = ALPROTO_HTTP1;
1874 
1875  p1->flow = &f;
1879 
1880  p2->flow = &f;
1884 
1885  StreamTcpInitConfig(true);
1886 
1889  de_ctx->flags |= DE_QUIET;
1890 
1892  FAIL_IF_NULL(s);
1893 
1895  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1896 
1897  int r = AppLayerParserParse(
1898  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
1899  FAIL_IF(r != 0);
1900  HtpState *http_state = f.alstate;
1901  FAIL_IF_NULL(http_state);
1902 
1903  /* do detect for p1 */
1904  SCLogInfo("p1");
1905  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1906 
1907  FAIL_IF(PacketAlertCheck(p1, 1));
1908 
1909  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1910  FAIL_IF(r != 0);
1911  /* do detect for p2 */
1912  SCLogInfo("p2");
1913  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1914 
1915  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
1916 
1917  FlowVar *fv = FlowVarGet(&f, 1);
1918  FAIL_IF_NULL(fv);
1919 
1920  FAIL_IF(fv->data.fv_int.value != 2);
1921 
1924 
1925  StreamTcpFreeConfig(true);
1926  FLOW_DESTROY(&f);
1927  UTHFreePackets(&p1, 1);
1928  UTHFreePackets(&p2, 1);
1929  PASS;
1930 }
1931 
1932 /** \test http buffer, flowints */
1933 static int LuaMatchTest04a(void)
1934 {
1935  const char script[] = "function init (args)\n"
1936  " local needs = {}\n"
1937  " needs[\"http.request_headers\"] = tostring(true)\n"
1938  " needs[\"flowint\"] = {\"cnt\"}\n"
1939  " return needs\n"
1940  "end\n"
1941  "\n"
1942  "function match(args)\n"
1943  " print \"inspecting\""
1944  " a = SCFlowintGet(0)\n"
1945  " if a then\n"
1946  " SCFlowintSet(0, a + 1)\n"
1947  " else\n"
1948  " SCFlowintSet(0, 1)\n"
1949  " end\n"
1950  " \n"
1951  " a = SCFlowintGet(0)\n"
1952  " if a == 2 then\n"
1953  " print \"match\"\n"
1954  " return 1\n"
1955  " end\n"
1956  " return 0\n"
1957  "end\n"
1958  "return 0\n";
1959  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1960  uint8_t httpbuf1[] =
1961  "POST / HTTP/1.1\r\n"
1962  "Host: www.emergingthreats.net\r\n\r\n";
1963  uint8_t httpbuf2[] =
1964  "POST / HTTP/1.1\r\n"
1965  "Host: www.openinfosecfoundation.org\r\n\r\n";
1966  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1967  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1968  TcpSession ssn;
1969  Flow f;
1970  ThreadVars th_v;
1971  DetectEngineThreadCtx *det_ctx;
1972 
1974 
1975  ut_script = script;
1976 
1977  memset(&th_v, 0, sizeof(th_v));
1978  memset(&f, 0, sizeof(f));
1979  memset(&ssn, 0, sizeof(ssn));
1980 
1981  Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1982  Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1983 
1984  FLOW_INITIALIZE(&f);
1985  f.protoctx = (void *)&ssn;
1986  f.proto = IPPROTO_TCP;
1987  f.flags |= FLOW_IPV4;
1988  f.alproto = ALPROTO_HTTP1;
1989 
1990  p1->flow = &f;
1994 
1995  p2->flow = &f;
1999 
2000  StreamTcpInitConfig(true);
2001 
2004  de_ctx->flags |= DE_QUIET;
2005 
2007  FAIL_IF_NULL(s);
2008 
2010  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2011 
2012  int r = AppLayerParserParse(
2013  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
2014  FAIL_IF(r != 0);
2015  HtpState *http_state = f.alstate;
2016  FAIL_IF_NULL(http_state);
2017 
2018  /* do detect for p1 */
2019  SCLogInfo("p1");
2020  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
2021 
2022  FAIL_IF(PacketAlertCheck(p1, 1));
2023 
2024  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
2025  FAIL_IF(r != 0);
2026  /* do detect for p2 */
2027  SCLogInfo("p2");
2028  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
2029 
2030  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
2031 
2032  FlowVar *fv = FlowVarGet(&f, 1);
2033  FAIL_IF_NULL(fv);
2034 
2035  FAIL_IF(fv->data.fv_int.value != 2);
2036 
2039 
2040  StreamTcpFreeConfig(true);
2041  FLOW_DESTROY(&f);
2042  UTHFreePackets(&p1, 1);
2043  UTHFreePackets(&p2, 1);
2044  PASS;
2045 }
2046 
2047 /** \test http buffer, flowints */
2048 static int LuaMatchTest05(void)
2049 {
2050  const char script[] = "function init (args)\n"
2051  " local needs = {}\n"
2052  " needs[\"http.request_headers\"] = tostring(true)\n"
2053  " needs[\"flowint\"] = {\"cnt\"}\n"
2054  " return needs\n"
2055  "end\n"
2056  "\n"
2057  "function match(args)\n"
2058  " print \"inspecting\""
2059  " a = ScFlowintIncr(0)\n"
2060  " if a == 2 then\n"
2061  " print \"match\"\n"
2062  " return 1\n"
2063  " end\n"
2064  " return 0\n"
2065  "end\n"
2066  "return 0\n";
2067  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
2068  uint8_t httpbuf1[] =
2069  "POST / HTTP/1.1\r\n"
2070  "Host: www.emergingthreats.net\r\n\r\n";
2071  uint8_t httpbuf2[] =
2072  "POST / HTTP/1.1\r\n"
2073  "Host: www.openinfosecfoundation.org\r\n\r\n";
2074  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2075  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2076  TcpSession ssn;
2077  Flow f;
2078  ThreadVars th_v;
2079  DetectEngineThreadCtx *det_ctx;
2080 
2082 
2083  ut_script = script;
2084 
2085  memset(&th_v, 0, sizeof(th_v));
2086  memset(&f, 0, sizeof(f));
2087  memset(&ssn, 0, sizeof(ssn));
2088 
2089  Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2090  Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2091 
2092  FLOW_INITIALIZE(&f);
2093  f.protoctx = (void *)&ssn;
2094  f.proto = IPPROTO_TCP;
2095  f.flags |= FLOW_IPV4;
2096  f.alproto = ALPROTO_HTTP1;
2097 
2098  p1->flow = &f;
2102 
2103  p2->flow = &f;
2107 
2108  StreamTcpInitConfig(true);
2109 
2112  de_ctx->flags |= DE_QUIET;
2113 
2115  FAIL_IF_NULL(s);
2116 
2118  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2119 
2120  int r = AppLayerParserParse(
2121  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
2122  FAIL_IF(r != 0);
2123  HtpState *http_state = f.alstate;
2124  FAIL_IF_NULL(http_state);
2125 
2126  /* do detect for p1 */
2127  SCLogInfo("p1");
2128  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
2129 
2130  FAIL_IF(PacketAlertCheck(p1, 1));
2131 
2132  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
2133  FAIL_IF(r != 0);
2134  /* do detect for p2 */
2135  SCLogInfo("p2");
2136  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
2137 
2138  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
2139 
2140  FlowVar *fv = FlowVarGet(&f, 1);
2141  FAIL_IF_NULL(fv);
2142 
2143  FAIL_IF(fv->data.fv_int.value != 2);
2144 
2147 
2148  StreamTcpFreeConfig(true);
2149  FLOW_DESTROY(&f);
2150  UTHFreePackets(&p1, 1);
2151  UTHFreePackets(&p2, 1);
2152  PASS;
2153 }
2154 
2155 /** \test http buffer, flowints */
2156 static int LuaMatchTest05a(void)
2157 {
2158  const char script[] = "function init (args)\n"
2159  " local needs = {}\n"
2160  " needs[\"http.request_headers\"] = tostring(true)\n"
2161  " needs[\"flowint\"] = {\"cnt\"}\n"
2162  " return needs\n"
2163  "end\n"
2164  "\n"
2165  "function match(args)\n"
2166  " print \"inspecting\""
2167  " a = SCFlowintIncr(0)\n"
2168  " if a == 2 then\n"
2169  " print \"match\"\n"
2170  " return 1\n"
2171  " end\n"
2172  " return 0\n"
2173  "end\n"
2174  "return 0\n";
2175  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
2176  uint8_t httpbuf1[] =
2177  "POST / HTTP/1.1\r\n"
2178  "Host: www.emergingthreats.net\r\n\r\n";
2179  uint8_t httpbuf2[] =
2180  "POST / HTTP/1.1\r\n"
2181  "Host: www.openinfosecfoundation.org\r\n\r\n";
2182  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2183  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2184  TcpSession ssn;
2185  Flow f;
2186  ThreadVars th_v;
2187  DetectEngineThreadCtx *det_ctx;
2188 
2190 
2191  ut_script = script;
2192 
2193  memset(&th_v, 0, sizeof(th_v));
2194  memset(&f, 0, sizeof(f));
2195  memset(&ssn, 0, sizeof(ssn));
2196 
2197  Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2198  Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2199 
2200  FLOW_INITIALIZE(&f);
2201  f.protoctx = (void *)&ssn;
2202  f.proto = IPPROTO_TCP;
2203  f.flags |= FLOW_IPV4;
2204  f.alproto = ALPROTO_HTTP1;
2205 
2206  p1->flow = &f;
2210 
2211  p2->flow = &f;
2215 
2216  StreamTcpInitConfig(true);
2217 
2220  de_ctx->flags |= DE_QUIET;
2221 
2223  FAIL_IF_NULL(s);
2224 
2226  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2227 
2228  int r = AppLayerParserParse(
2229  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
2230  FAIL_IF(r != 0);
2231  HtpState *http_state = f.alstate;
2232  FAIL_IF_NULL(http_state);
2233 
2234  /* do detect for p1 */
2235  SCLogInfo("p1");
2236  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
2237 
2238  FAIL_IF(PacketAlertCheck(p1, 1));
2239 
2240  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
2241  FAIL_IF(r != 0);
2242  /* do detect for p2 */
2243  SCLogInfo("p2");
2244  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
2245 
2246  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
2247 
2248  FlowVar *fv = FlowVarGet(&f, 1);
2249  FAIL_IF_NULL(fv);
2250 
2251  FAIL_IF(fv->data.fv_int.value != 2);
2252 
2255 
2256  StreamTcpFreeConfig(true);
2257  FLOW_DESTROY(&f);
2258  UTHFreePackets(&p1, 1);
2259  UTHFreePackets(&p2, 1);
2260  PASS;
2261 }
2262 
2263 /** \test http buffer, flowints */
2264 static int LuaMatchTest06(void)
2265 {
2266  const char script[] = "function init (args)\n"
2267  " local needs = {}\n"
2268  " needs[\"http.request_headers\"] = tostring(true)\n"
2269  " needs[\"flowint\"] = {\"cnt\"}\n"
2270  " return needs\n"
2271  "end\n"
2272  "\n"
2273  "function match(args)\n"
2274  " print \"inspecting\""
2275  " a = ScFlowintGet(0)\n"
2276  " if a == nil then\n"
2277  " print \"new var set to 2\""
2278  " ScFlowintSet(0, 2)\n"
2279  " end\n"
2280  " a = ScFlowintDecr(0)\n"
2281  " if a == 0 then\n"
2282  " print \"match\"\n"
2283  " return 1\n"
2284  " end\n"
2285  " return 0\n"
2286  "end\n"
2287  "return 0\n";
2288  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
2289  uint8_t httpbuf1[] =
2290  "POST / HTTP/1.1\r\n"
2291  "Host: www.emergingthreats.net\r\n\r\n";
2292  uint8_t httpbuf2[] =
2293  "POST / HTTP/1.1\r\n"
2294  "Host: www.openinfosecfoundation.org\r\n\r\n";
2295  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2296  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2297  TcpSession ssn;
2298  Flow f;
2299  ThreadVars th_v;
2300  DetectEngineThreadCtx *det_ctx;
2301 
2303 
2304  ut_script = script;
2305 
2306  memset(&th_v, 0, sizeof(th_v));
2307  memset(&f, 0, sizeof(f));
2308  memset(&ssn, 0, sizeof(ssn));
2309 
2310  Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2311  Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2312 
2313  FLOW_INITIALIZE(&f);
2314  f.protoctx = (void *)&ssn;
2315  f.proto = IPPROTO_TCP;
2316  f.flags |= FLOW_IPV4;
2317  f.alproto = ALPROTO_HTTP1;
2318 
2319  p1->flow = &f;
2323 
2324  p2->flow = &f;
2328 
2329  StreamTcpInitConfig(true);
2330 
2333  de_ctx->flags |= DE_QUIET;
2334 
2336  FAIL_IF_NULL(s);
2337 
2339  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2340 
2341  int r = AppLayerParserParse(
2342  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
2343  FAIL_IF(r != 0);
2344  HtpState *http_state = f.alstate;
2345  FAIL_IF_NULL(http_state);
2346 
2347  /* do detect for p1 */
2348  SCLogInfo("p1");
2349  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
2350 
2351  FAIL_IF(PacketAlertCheck(p1, 1));
2352 
2353  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
2354  FAIL_IF(r != 0);
2355  /* do detect for p2 */
2356  SCLogInfo("p2");
2357  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
2358 
2359  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
2360 
2361  FlowVar *fv = FlowVarGet(&f, 1);
2362  FAIL_IF_NULL(fv);
2363 
2364  FAIL_IF(fv->data.fv_int.value != 0);
2365 
2368 
2369  StreamTcpFreeConfig(true);
2370  FLOW_DESTROY(&f);
2371  UTHFreePackets(&p1, 1);
2372  UTHFreePackets(&p2, 1);
2373  PASS;
2374 }
2375 
2376 /** \test http buffer, flowints */
2377 static int LuaMatchTest06a(void)
2378 {
2379  const char script[] = "function init (args)\n"
2380  " local needs = {}\n"
2381  " needs[\"http.request_headers\"] = tostring(true)\n"
2382  " needs[\"flowint\"] = {\"cnt\"}\n"
2383  " return needs\n"
2384  "end\n"
2385  "\n"
2386  "function match(args)\n"
2387  " print \"inspecting\""
2388  " a = SCFlowintGet(0)\n"
2389  " if a == nil then\n"
2390  " print \"new var set to 2\""
2391  " SCFlowintSet(0, 2)\n"
2392  " end\n"
2393  " a = SCFlowintDecr(0)\n"
2394  " if a == 0 then\n"
2395  " print \"match\"\n"
2396  " return 1\n"
2397  " end\n"
2398  " return 0\n"
2399  "end\n"
2400  "return 0\n";
2401  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
2402  uint8_t httpbuf1[] =
2403  "POST / HTTP/1.1\r\n"
2404  "Host: www.emergingthreats.net\r\n\r\n";
2405  uint8_t httpbuf2[] =
2406  "POST / HTTP/1.1\r\n"
2407  "Host: www.openinfosecfoundation.org\r\n\r\n";
2408  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
2409  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
2410  TcpSession ssn;
2411  Flow f;
2412  ThreadVars th_v;
2413  DetectEngineThreadCtx *det_ctx;
2414 
2416 
2417  ut_script = script;
2418 
2419  memset(&th_v, 0, sizeof(th_v));
2420  memset(&f, 0, sizeof(f));
2421  memset(&ssn, 0, sizeof(ssn));
2422 
2423  Packet *p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2424  Packet *p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
2425 
2426  FLOW_INITIALIZE(&f);
2427  f.protoctx = (void *)&ssn;
2428  f.proto = IPPROTO_TCP;
2429  f.flags |= FLOW_IPV4;
2430  f.alproto = ALPROTO_HTTP1;
2431 
2432  p1->flow = &f;
2436 
2437  p2->flow = &f;
2441 
2442  StreamTcpInitConfig(true);
2443 
2446  de_ctx->flags |= DE_QUIET;
2447 
2449  FAIL_IF_NULL(s);
2450 
2452  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2453 
2454  int r = AppLayerParserParse(
2455  NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
2456  FAIL_IF(r != 0);
2457  HtpState *http_state = f.alstate;
2458  FAIL_IF_NULL(http_state);
2459 
2460  /* do detect for p1 */
2461  SCLogInfo("p1");
2462  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
2463 
2464  FAIL_IF(PacketAlertCheck(p1, 1));
2465 
2466  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
2467  FAIL_IF(r != 0);
2468  /* do detect for p2 */
2469  SCLogInfo("p2");
2470  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
2471 
2472  FAIL_IF_NOT(PacketAlertCheck(p2, 1));
2473 
2474  FlowVar *fv = FlowVarGet(&f, 1);
2475  FAIL_IF_NULL(fv);
2476 
2477  FAIL_IF(fv->data.fv_int.value != 0);
2478 
2481 
2482  StreamTcpFreeConfig(true);
2483  FLOW_DESTROY(&f);
2484  UTHFreePackets(&p1, 1);
2485  UTHFreePackets(&p2, 1);
2486  PASS;
2487 }
2488 
2489 void DetectLuaRegisterTests(void)
2490 {
2491  UtRegisterTest("LuaMatchTest01", LuaMatchTest01);
2492  UtRegisterTest("LuaMatchTest01a", LuaMatchTest01a);
2493  UtRegisterTest("LuaMatchTest02", LuaMatchTest02);
2494  UtRegisterTest("LuaMatchTest02a", LuaMatchTest02a);
2495  UtRegisterTest("LuaMatchTest03", LuaMatchTest03);
2496  UtRegisterTest("LuaMatchTest03a", LuaMatchTest03a);
2497  UtRegisterTest("LuaMatchTest04", LuaMatchTest04);
2498  UtRegisterTest("LuaMatchTest04a", LuaMatchTest04a);
2499  UtRegisterTest("LuaMatchTest05", LuaMatchTest05);
2500  UtRegisterTest("LuaMatchTest05a", LuaMatchTest05a);
2501  UtRegisterTest("LuaMatchTest06", LuaMatchTest06);
2502  UtRegisterTest("LuaMatchTest06a", LuaMatchTest06a);
2503 }
2504 #endif
2505 #endif /* HAVE_LUAJIT */
util-byte.h
SigTableElmt_::url
const char * url
Definition: detect.h:1243
detect-engine.h
DETECT_SM_LIST_PMATCH
@ DETECT_SM_LIST_PMATCH
Definition: detect.h:81
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
SigTableElmt_::desc
const char * desc
Definition: detect.h:1242
PKT_HAS_FLOW
#define PKT_HAS_FLOW
Definition: decode.h:1003
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1230
flow-util.h
ALPROTO_DNS
@ ALPROTO_DNS
Definition: app-layer-protos.h:41
SigTableElmt_::name
const char * name
Definition: detect.h:1240
stream-tcp.h
DetectThreadCtxGetKeywordThreadCtx
void * DetectThreadCtxGetKeywordThreadCtx(DetectEngineThreadCtx *det_ctx, int id)
Retrieve thread local keyword ctx by id.
Definition: detect-engine.c:3514
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:546
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
Flow_::proto
uint8_t proto
Definition: flow.h:379
util-lua.h
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:80
Packet_::payload
uint8_t * payload
Definition: decode.h:573
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:1100
FlowVarTypeStr::value_len
uint16_t value_len
Definition: flow-var.h:39
SigMatchData_::ctx
SigMatchCtx * ctx
Definition: detect.h:327
Packet_::flags
uint32_t flags
Definition: decode.h:463
threads.h
Flow_
Flow data structure.
Definition: flow.h:357
SigTableElmt_::flags
uint16_t flags
Definition: detect.h:1234
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:787
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:2455
detect-lua.h
SigTableElmt_::AppLayerTxMatch
int(* AppLayerTxMatch)(DetectEngineThreadCtx *, Flow *, uint8_t flags, void *alstate, void *txv, const Signature *, const SigMatchCtx *)
Definition: detect.h:1211
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:227
util-var-name.h
DE_QUIET
#define DE_QUIET
Definition: detect.h:289
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:1809
StringParseInt32
int StringParseInt32(int32_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:622
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:2423
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:459
DetectBufferGetActiveList
int DetectBufferGetActiveList(DetectEngineCtx *de_ctx, Signature *s)
Definition: detect-engine.c:1306
SIG_FLAG_TOCLIENT
#define SIG_FLAG_TOCLIENT
Definition: detect.h:231
Flow_::protoctx
void * protoctx
Definition: flow.h:447
SigMatchData_
Data needed for Match()
Definition: detect.h:324
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1225
FLOW_IPV4
#define FLOW_IPV4
Definition: flow.h:97
Packet_::payload_len
uint16_t payload_len
Definition: decode.h:574
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:244
SIGMATCH_NOT_BUILT
#define SIGMATCH_NOT_BUILT
Definition: detect.h:1431
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:1079
Signature_::gid
uint32_t gid
Definition: detect.h:577
FlowVar_::fv_int
FlowVarTypeInt fv_int
Definition: flow-var.h:58
Flow_::alparser
AppLayerParserState * alparser
Definition: flow.h:481
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:40
SIG_FLAG_TOSERVER
#define SIG_FLAG_TOSERVER
Definition: detect.h:230
app-layer-htp.h
FlowVar_::data
union FlowVar_::@111 data
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:1027
util-cpu.h
ALPROTO_DNP3
@ ALPROTO_DNP3
Definition: app-layer-protos.h:44
ALPROTO_SMTP
@ ALPROTO_SMTP
Definition: app-layer-protos.h:32
alp_tctx
AppLayerParserThreadCtx * alp_tctx
Definition: fuzz_applayerparserparse.c:22
DETECT_LUA
@ DETECT_LUA
Definition: detect-engine-register.h:220
SignatureInitData_::list
int list
Definition: detect.h:519
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:271
GET_PKT_DATA
#define GET_PKT_DATA(p)
Definition: decode.h:219
detect-engine-mpm.h
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
DetectLuaRegister
void DetectLuaRegister(void)
Registration function for keyword: lua.
Definition: detect-lua.c:77
SigMatch_::next
struct SigMatch_ * next
Definition: detect.h:319
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:79
app-layer-parser.h
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:318
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:289
Packet_
Definition: decode.h:428
detect-engine-build.h
GET_PKT_LEN
#define GET_PKT_LEN(p)
Definition: decode.h:218
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:224
detect-engine-alert.h
conf.h
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:613
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:1208
queue.h
detect-byte.h
SignatureInitData_::smlists
struct SigMatch_ ** smlists
Definition: detect.h:536
FLOW_PKT_TOCLIENT
#define FLOW_PKT_TOCLIENT
Definition: flow.h:228
SigMatchAlloc
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:241
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:1143
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:1951
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:310
FlowVarTypeStr::value
uint8_t * value
Definition: flow-var.h:38
Packet_::flow
struct Flow_ * flow
Definition: decode.h:465
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
Definition: detect-engine.c:3166
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:1025
StreamTcpFreeConfig
void StreamTcpFreeConfig(bool quiet)
Definition: stream-tcp.c:695
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:3444
SigTableElmt_::alias
const char * alias
Definition: detect.h:1241
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:1323
detect-lua-extensions.h
suricata-common.h
SigMatch_::type
uint16_t type
Definition: detect.h:316
ALPROTO_HTTP1
@ ALPROTO_HTTP1
Definition: app-layer-protos.h:30
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:76
HtpState_::connp
htp_connp_t * connp
Definition: app-layer-htp.h:246
VarNameStoreSetupAdd
uint32_t VarNameStoreSetupAdd(const char *name, const enum VarTypes type)
add to staging or return existing id if already in there
Definition: util-var-name.c:323
lua_State
void lua_State
Definition: suricata-common.h:489
Signature_::rev
uint32_t rev
Definition: detect.h:578
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:1961
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
str
#define str(s)
Definition: suricata-common.h:280
DetectEngineThreadCtx_::tv
ThreadVars * tv
Definition: detect.h:1033
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:482
Signature_::id
uint32_t id
Definition: detect.h:576
Flow_::flags
uint32_t flags
Definition: flow.h:427
detect-parse.h
Signature_
Signature container.
Definition: detect.h:542
SigMatch_
a single match condition for a signature
Definition: detect.h:315
AppLayerGetProtoName
const char * AppLayerGetProtoName(AppProto alproto)
Given the internal protocol id, returns a string representation of the protocol.
Definition: app-layer.c:939
VAR_TYPE_FLOW_VAR
@ VAR_TYPE_FLOW_VAR
Definition: util-var.h:37
DETECT_SM_LIST_MAX
@ DETECT_SM_LIST_MAX
Definition: detect.h:97
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:229
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2416
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:788
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:3496
TcpSession_
Definition: stream-tcp-private.h:279
flow.h
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:456
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:1136
FlowVar_
Definition: flow-var.h:48
SigMatchAppendSMToList
void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:356
FLOW_DESTROY
#define FLOW_DESTROY(f)
Definition: flow-util.h:129
PKT_STREAM_EST
#define PKT_STREAM_EST
Definition: decode.h:1000
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1232
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