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