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 
47 #include "util-unittest.h"
48 #include "util-unittest-helper.h"
49 
50 #include "app-layer.h"
51 #include "app-layer-parser.h"
52 #include "app-layer-htp.h"
53 
54 #include "stream-tcp.h"
55 
56 #include "detect-lua.h"
57 #include "detect-lua-extensions.h"
58 
59 #include "queue.h"
60 #include "util-cpu.h"
61 #include "util-var-name.h"
62 
63 #ifndef HAVE_LUA
64 
65 static int DetectLuaSetupNoSupport (DetectEngineCtx *a, Signature *b, const char *c)
66 {
67  SCLogError(SC_ERR_NO_LUA_SUPPORT, "no Lua support built in, needed for lua/luajit keyword");
68  return -1;
69 }
70 
71 /**
72  * \brief Registration function for keyword: lua
73  */
75 {
77  sigmatch_table[DETECT_LUA].alias = "luajit";
78  sigmatch_table[DETECT_LUA].Setup = DetectLuaSetupNoSupport;
82 
83  SCLogDebug("registering lua rule option");
84  return;
85 }
86 
87 #else /* HAVE_LUA */
88 
89 #include "util-lua.h"
90 
91 static int DetectLuaMatch (ThreadVars *, DetectEngineThreadCtx *,
92  Packet *, const Signature *, const SigMatchCtx *);
93 static int DetectLuaAppTxMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx,
94  Flow *f, uint8_t flags,
95  void *state, void *txv, const Signature *s,
96  const SigMatchCtx *ctx);
97 static int DetectLuaSetup (DetectEngineCtx *, Signature *, const char *);
98 static void DetectLuaRegisterTests(void);
99 static void DetectLuaFree(void *);
100 static int g_smtp_generic_list_id = 0;
101 
102 static int InspectSmtpGeneric(ThreadVars *tv,
103  DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
104  const Signature *s, const SigMatchData *smd,
105  Flow *f, uint8_t flags, void *alstate,
106  void *txv, uint64_t tx_id);
107 
108 /**
109  * \brief Registration function for keyword: lua
110  */
111 void DetectLuaRegister(void)
112 {
113  sigmatch_table[DETECT_LUA].name = "lua";
114  sigmatch_table[DETECT_LUA].alias = "luajit";
115  sigmatch_table[DETECT_LUA].desc = "match via a lua script";
116  sigmatch_table[DETECT_LUA].url = "https://suricata.readthedocs.io/en/latest/rules/rule-lua-scripting.html";
117  sigmatch_table[DETECT_LUA].Match = DetectLuaMatch;
118  sigmatch_table[DETECT_LUA].AppLayerTxMatch = DetectLuaAppTxMatch;
119  sigmatch_table[DETECT_LUA].Setup = DetectLuaSetup;
120  sigmatch_table[DETECT_LUA].Free = DetectLuaFree;
121  sigmatch_table[DETECT_LUA].RegisterTests = DetectLuaRegisterTests;
122 
123  g_smtp_generic_list_id = DetectBufferTypeRegister("smtp_generic");
124 
127  InspectSmtpGeneric);
130  InspectSmtpGeneric);
131 
132  SCLogDebug("registering lua rule option");
133  return;
134 }
135 
136 static int InspectSmtpGeneric(ThreadVars *tv,
137  DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
138  const Signature *s, const SigMatchData *smd,
139  Flow *f, uint8_t flags, void *alstate,
140  void *txv, uint64_t tx_id)
141 {
142  return DetectEngineInspectGenericList(tv, de_ctx, det_ctx, s, smd,
143  f, flags, alstate, txv, tx_id);
144 }
145 
146 #define DATATYPE_PACKET (1<<0)
147 #define DATATYPE_PAYLOAD (1<<1)
148 #define DATATYPE_STREAM (1<<2)
149 
150 #define DATATYPE_HTTP_URI (1<<3)
151 #define DATATYPE_HTTP_URI_RAW (1<<4)
152 
153 #define DATATYPE_HTTP_REQUEST_HEADERS (1<<5)
154 #define DATATYPE_HTTP_REQUEST_HEADERS_RAW (1<<6)
155 #define DATATYPE_HTTP_REQUEST_COOKIE (1<<7)
156 #define DATATYPE_HTTP_REQUEST_UA (1<<8)
157 
158 #define DATATYPE_HTTP_REQUEST_LINE (1<<9)
159 #define DATATYPE_HTTP_REQUEST_BODY (1<<10)
160 
161 #define DATATYPE_HTTP_RESPONSE_COOKIE (1<<11)
162 #define DATATYPE_HTTP_RESPONSE_BODY (1<<12)
163 
164 #define DATATYPE_HTTP_RESPONSE_HEADERS (1<<13)
165 #define DATATYPE_HTTP_RESPONSE_HEADERS_RAW (1<<14)
166 
167 #define DATATYPE_DNS_RRNAME (1<<15)
168 #define DATATYPE_DNS_REQUEST (1<<16)
169 #define DATATYPE_DNS_RESPONSE (1<<17)
170 
171 #define DATATYPE_TLS (1<<18)
172 #define DATATYPE_SSH (1<<19)
173 #define DATATYPE_SMTP (1<<20)
174 
175 #define DATATYPE_DNP3 (1<<20)
176 
177 #if 0
178 /** \brief dump stack from lua state to screen */
179 void LuaDumpStack(lua_State *state)
180 {
181  int size = lua_gettop(state);
182  int i;
183 
184  for (i = 1; i <= size; i++) {
185  int type = lua_type(state, i);
186  printf("Stack size=%d, level=%d, type=%d, ", size, i, type);
187 
188  switch (type) {
189  case LUA_TFUNCTION:
190  printf("function %s", lua_tostring(state, i) ? "true" : "false");
191  break;
192  case LUA_TBOOLEAN:
193  printf("bool %s", lua_toboolean(state, i) ? "true" : "false");
194  break;
195  case LUA_TNUMBER:
196  printf("number %g", lua_tonumber(state, i));
197  break;
198  case LUA_TSTRING:
199  printf("string `%s'", lua_tostring(state, i));
200  break;
201  case LUA_TTABLE:
202  printf("table `%s'", lua_tostring(state, i));
203  break;
204  default:
205  printf("other %s", lua_typename(state, type));
206  break;
207 
208  }
209  printf("\n");
210  }
211 }
212 #endif
213 
215  const Signature *s, const SigMatchData *smd,
216  uint8_t *buffer, uint32_t buffer_len, uint32_t offset,
217  Flow *f)
218 {
219  SCEnter();
220  int ret = 0;
221 
222  if (buffer == NULL || buffer_len == 0)
223  SCReturnInt(0);
224 
225  DetectLuaData *lua = (DetectLuaData *)smd->ctx;
226  if (lua == NULL)
227  SCReturnInt(0);
228 
229  DetectLuaThreadData *tlua = (DetectLuaThreadData *)DetectThreadCtxGetKeywordThreadCtx(det_ctx, lua->thread_ctx_id);
230  if (tlua == NULL)
231  SCReturnInt(0);
232 
233  LuaExtensionsMatchSetup(tlua->luastate, lua, det_ctx,
234  f, /* no packet in the ctx */NULL, 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  if (atoi(v) == 1)
280  ret = 1;
281  } else {
282  /* set flow var? */
283  }
284  }
285 
286  /* pop the table */
287  lua_pop(tlua->luastate, 1);
288  }
289  } else {
290  SCLogDebug("no stack");
291  }
292 
293  /* clear the stack */
294  while (lua_gettop(tlua->luastate) > 0) {
295  lua_pop(tlua->luastate, 1);
296  }
297 
298  if (lua->negated) {
299  if (ret == 1)
300  ret = 0;
301  else
302  ret = 1;
303  }
304 
305  SCReturnInt(ret);
306 }
307 
308 /**
309  * \brief match the specified lua script
310  *
311  * \param t thread local vars
312  * \param det_ctx pattern matcher thread local data
313  * \param p packet
314  * \param s signature being inspected
315  * \param m sigmatch that we will cast into DetectLuaData
316  *
317  * \retval 0 no match
318  * \retval 1 match
319  */
320 static int DetectLuaMatch (ThreadVars *tv, DetectEngineThreadCtx *det_ctx,
321  Packet *p, const Signature *s, const SigMatchCtx *ctx)
322 {
323  SCEnter();
324  int ret = 0;
325  DetectLuaData *lua = (DetectLuaData *)ctx;
326  if (lua == NULL)
327  SCReturnInt(0);
328 
329  DetectLuaThreadData *tlua = (DetectLuaThreadData *)DetectThreadCtxGetKeywordThreadCtx(det_ctx, lua->thread_ctx_id);
330  if (tlua == NULL)
331  SCReturnInt(0);
332 
333  /* setup extension data for use in lua c functions */
334  uint8_t flags = 0;
335  if (p->flowflags & FLOW_PKT_TOSERVER)
336  flags = STREAM_TOSERVER;
337  else if (p->flowflags & FLOW_PKT_TOCLIENT)
338  flags = STREAM_TOCLIENT;
339 
340  LuaStateSetThreadVars(tlua->luastate, tv);
341 
342  LuaExtensionsMatchSetup(tlua->luastate, lua, det_ctx,
343  p->flow, p, flags);
344 
345  if ((tlua->flags & DATATYPE_PAYLOAD) && p->payload_len == 0)
346  SCReturnInt(0);
347  if ((tlua->flags & DATATYPE_PACKET) && GET_PKT_LEN(p) == 0)
348  SCReturnInt(0);
349  if (tlua->alproto != ALPROTO_UNKNOWN) {
350  if (p->flow == NULL)
351  SCReturnInt(0);
352 
353  AppProto alproto = p->flow->alproto;
354  if (tlua->alproto != alproto)
355  SCReturnInt(0);
356  }
357 
358  lua_getglobal(tlua->luastate, "match");
359  lua_newtable(tlua->luastate); /* stack at -1 */
360 
361  if ((tlua->flags & DATATYPE_PAYLOAD) && p->payload_len) {
362  lua_pushliteral(tlua->luastate, "payload"); /* stack at -2 */
363  LuaPushStringBuffer (tlua->luastate, (const uint8_t *)p->payload, (size_t)p->payload_len); /* stack at -3 */
364  lua_settable(tlua->luastate, -3);
365  }
366  if ((tlua->flags & DATATYPE_PACKET) && GET_PKT_LEN(p)) {
367  lua_pushliteral(tlua->luastate, "packet"); /* stack at -2 */
368  LuaPushStringBuffer (tlua->luastate, (const uint8_t *)GET_PKT_DATA(p), (size_t)GET_PKT_LEN(p)); /* stack at -3 */
369  lua_settable(tlua->luastate, -3);
370  }
371  if (tlua->alproto == ALPROTO_HTTP) {
372  HtpState *htp_state = p->flow->alstate;
373  if (htp_state != NULL && htp_state->connp != NULL) {
374  htp_tx_t *tx = NULL;
377  uint64_t total_txs= AppLayerParserGetTxCnt(p->flow, htp_state);
378  for ( ; idx < total_txs; idx++) {
379  tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, htp_state, idx);
380  if (tx == NULL)
381  continue;
382 
383  if ((tlua->flags & DATATYPE_HTTP_REQUEST_LINE) && tx->request_line != NULL &&
384  bstr_len(tx->request_line) > 0) {
385  lua_pushliteral(tlua->luastate, "http.request_line"); /* stack at -2 */
386  LuaPushStringBuffer(tlua->luastate,
387  (const uint8_t *)bstr_ptr(tx->request_line),
388  bstr_len(tx->request_line));
389  lua_settable(tlua->luastate, -3);
390  }
391  }
392  }
393  }
394 
395  int retval = lua_pcall(tlua->luastate, 1, 1, 0);
396  if (retval != 0) {
397  SCLogInfo("failed to run script: %s", lua_tostring(tlua->luastate, -1));
398  }
399 
400  /* process returns from script */
401  if (lua_gettop(tlua->luastate) > 0) {
402 
403  /* script returns a number (return 1 or return 0) */
404  if (lua_type(tlua->luastate, 1) == LUA_TNUMBER) {
405  double script_ret = lua_tonumber(tlua->luastate, 1);
406  SCLogDebug("script_ret %f", script_ret);
407  lua_pop(tlua->luastate, 1);
408 
409  if (script_ret == 1.0)
410  ret = 1;
411 
412  /* script returns a table */
413  } else if (lua_type(tlua->luastate, 1) == LUA_TTABLE) {
414  lua_pushnil(tlua->luastate);
415  const char *k, *v;
416  while (lua_next(tlua->luastate, -2)) {
417  v = lua_tostring(tlua->luastate, -1);
418  lua_pop(tlua->luastate, 1);
419  k = lua_tostring(tlua->luastate, -1);
420 
421  if (!k || !v)
422  continue;
423 
424  SCLogDebug("k='%s', v='%s'", k, v);
425 
426  if (strcmp(k, "retval") == 0) {
427  if (atoi(v) == 1)
428  ret = 1;
429  } else {
430  /* set flow var? */
431  }
432  }
433 
434  /* pop the table */
435  lua_pop(tlua->luastate, 1);
436  }
437  }
438  while (lua_gettop(tlua->luastate) > 0) {
439  lua_pop(tlua->luastate, 1);
440  }
441 
442  if (lua->negated) {
443  if (ret == 1)
444  ret = 0;
445  else
446  ret = 1;
447  }
448 
449  SCReturnInt(ret);
450 }
451 
452 static int DetectLuaAppMatchCommon (ThreadVars *t, DetectEngineThreadCtx *det_ctx,
453  Flow *f, uint8_t flags, void *state,
454  const Signature *s, const SigMatchCtx *ctx)
455 {
456  SCEnter();
457  int ret = 0;
458  DetectLuaData *lua = (DetectLuaData *)ctx;
459  if (lua == NULL)
460  SCReturnInt(0);
461 
462  DetectLuaThreadData *tlua = (DetectLuaThreadData *)DetectThreadCtxGetKeywordThreadCtx(det_ctx, lua->thread_ctx_id);
463  if (tlua == NULL)
464  SCReturnInt(0);
465 
466  /* setup extension data for use in lua c functions */
467  LuaExtensionsMatchSetup(tlua->luastate, lua, det_ctx,
468  f, NULL, flags);
469 
470  if (tlua->alproto != ALPROTO_UNKNOWN) {
471  int alproto = f->alproto;
472  if (tlua->alproto != alproto)
473  SCReturnInt(0);
474  }
475 
476  lua_getglobal(tlua->luastate, "match");
477  lua_newtable(tlua->luastate); /* stack at -1 */
478 
479  if (tlua->alproto == ALPROTO_HTTP) {
480  HtpState *htp_state = state;
481  if (htp_state != NULL && htp_state->connp != NULL) {
482  htp_tx_t *tx = NULL;
483  tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, htp_state, det_ctx->tx_id);
484  if (tx != NULL) {
485  if ((tlua->flags & DATATYPE_HTTP_REQUEST_LINE) && tx->request_line != NULL &&
486  bstr_len(tx->request_line) > 0) {
487  lua_pushliteral(tlua->luastate, "http.request_line"); /* stack at -2 */
488  LuaPushStringBuffer(tlua->luastate,
489  (const uint8_t *)bstr_ptr(tx->request_line),
490  bstr_len(tx->request_line));
491  lua_settable(tlua->luastate, -3);
492  }
493  }
494  }
495  }
496 
497  int retval = lua_pcall(tlua->luastate, 1, 1, 0);
498  if (retval != 0) {
499  SCLogInfo("failed to run script: %s", lua_tostring(tlua->luastate, -1));
500  }
501 
502  /* process returns from script */
503  if (lua_gettop(tlua->luastate) > 0) {
504 
505  /* script returns a number (return 1 or return 0) */
506  if (lua_type(tlua->luastate, 1) == LUA_TNUMBER) {
507  double script_ret = lua_tonumber(tlua->luastate, 1);
508  SCLogDebug("script_ret %f", script_ret);
509  lua_pop(tlua->luastate, 1);
510 
511  if (script_ret == 1.0)
512  ret = 1;
513 
514  /* script returns a table */
515  } else if (lua_type(tlua->luastate, 1) == LUA_TTABLE) {
516  lua_pushnil(tlua->luastate);
517  const char *k, *v;
518  while (lua_next(tlua->luastate, -2)) {
519  v = lua_tostring(tlua->luastate, -1);
520  lua_pop(tlua->luastate, 1);
521  k = lua_tostring(tlua->luastate, -1);
522 
523  if (!k || !v)
524  continue;
525 
526  SCLogDebug("k='%s', v='%s'", k, v);
527 
528  if (strcmp(k, "retval") == 0) {
529  if (atoi(v) == 1)
530  ret = 1;
531  } else {
532  /* set flow var? */
533  }
534  }
535 
536  /* pop the table */
537  lua_pop(tlua->luastate, 1);
538  }
539  }
540  while (lua_gettop(tlua->luastate) > 0) {
541  lua_pop(tlua->luastate, 1);
542  }
543 
544  if (lua->negated) {
545  if (ret == 1)
546  ret = 0;
547  else
548  ret = 1;
549  }
550 
551  SCReturnInt(ret);
552 }
553 
554 /**
555  * \brief match the specified lua script in a list with a tx
556  *
557  * \param t thread local vars
558  * \param det_ctx pattern matcher thread local data
559  * \param s signature being inspected
560  * \param m sigmatch that we will cast into DetectLuaData
561  *
562  * \retval 0 no match
563  * \retval 1 match
564  */
565 static int DetectLuaAppTxMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx,
566  Flow *f, uint8_t flags,
567  void *state, void *txv, const Signature *s,
568  const SigMatchCtx *ctx)
569 {
570  return DetectLuaAppMatchCommon(t, det_ctx, f, flags, state, s, ctx);
571 }
572 
573 #ifdef UNITTESTS
574 /* if this ptr is set the lua setup functions will use this buffer as the
575  * lua script instead of calling luaL_loadfile on the filename supplied. */
576 static const char *ut_script = NULL;
577 #endif
578 
579 static void *DetectLuaThreadInit(void *data)
580 {
581  int status;
582  DetectLuaData *lua = (DetectLuaData *)data;
583  BUG_ON(lua == NULL);
584 
585  DetectLuaThreadData *t = SCMalloc(sizeof(DetectLuaThreadData));
586  if (unlikely(t == NULL)) {
587  SCLogError(SC_ERR_LUA_ERROR, "couldn't alloc ctx memory");
588  return NULL;
589  }
590  memset(t, 0x00, sizeof(DetectLuaThreadData));
591 
592  t->alproto = lua->alproto;
593  t->flags = lua->flags;
594 
595  t->luastate = LuaGetState();
596  if (t->luastate == NULL) {
597  SCLogError(SC_ERR_LUA_ERROR, "luastate pool depleted");
598  goto error;
599  }
600 
601  luaL_openlibs(t->luastate);
602 
603  LuaRegisterExtensions(t->luastate);
604 
605  lua_pushinteger(t->luastate, (lua_Integer)(lua->sid));
606  lua_setglobal(t->luastate, "SCRuleSid");
607  lua_pushinteger(t->luastate, (lua_Integer)(lua->rev));
608  lua_setglobal(t->luastate, "SCRuleRev");
609  lua_pushinteger(t->luastate, (lua_Integer)(lua->gid));
610  lua_setglobal(t->luastate, "SCRuleGid");
611 
612  /* hackish, needed to allow unittests to pass buffers as scripts instead of files */
613 #ifdef UNITTESTS
614  if (ut_script != NULL) {
615  status = luaL_loadbuffer(t->luastate, ut_script, strlen(ut_script), "unittest");
616  if (status) {
617  SCLogError(SC_ERR_LUA_ERROR, "couldn't load file: %s", lua_tostring(t->luastate, -1));
618  goto error;
619  }
620  } else {
621 #endif
622  status = luaL_loadfile(t->luastate, lua->filename);
623  if (status) {
624  SCLogError(SC_ERR_LUA_ERROR, "couldn't load file: %s", lua_tostring(t->luastate, -1));
625  goto error;
626  }
627 #ifdef UNITTESTS
628  }
629 #endif
630 
631  /* prime the script (or something) */
632  if (lua_pcall(t->luastate, 0, 0, 0) != 0) {
633  SCLogError(SC_ERR_LUA_ERROR, "couldn't prime file: %s", lua_tostring(t->luastate, -1));
634  goto error;
635  }
636 
637  return (void *)t;
638 
639 error:
640  if (t->luastate != NULL)
641  LuaReturnState(t->luastate);
642  SCFree(t);
643  return NULL;
644 }
645 
646 static void DetectLuaThreadFree(void *ctx)
647 {
648  if (ctx != NULL) {
649  DetectLuaThreadData *t = (DetectLuaThreadData *)ctx;
650  if (t->luastate != NULL)
651  LuaReturnState(t->luastate);
652  SCFree(t);
653  }
654 }
655 
656 /**
657  * \brief Parse the lua keyword
658  *
659  * \param str Pointer to the user provided option
660  *
661  * \retval lua pointer to DetectLuaData on success
662  * \retval NULL on failure
663  */
664 static DetectLuaData *DetectLuaParse (const DetectEngineCtx *de_ctx, const char *str)
665 {
666  DetectLuaData *lua = NULL;
667 
668  /* We have a correct lua option */
669  lua = SCMalloc(sizeof(DetectLuaData));
670  if (unlikely(lua == NULL))
671  goto error;
672 
673  memset(lua, 0x00, sizeof(DetectLuaData));
674 
675  if (strlen(str) && str[0] == '!') {
676  lua->negated = 1;
677  str++;
678  }
679 
680  /* get full filename */
681  lua->filename = DetectLoadCompleteSigPath(de_ctx, str);
682  if (lua->filename == NULL) {
683  goto error;
684  }
685 
686  return lua;
687 
688 error:
689  if (lua != NULL)
690  DetectLuaFree(lua);
691  return NULL;
692 }
693 
694 static int DetectLuaSetupPrime(DetectEngineCtx *de_ctx, DetectLuaData *ld)
695 {
696  int status;
697 
698  lua_State *luastate = luaL_newstate();
699  if (luastate == NULL)
700  return -1;
701  luaL_openlibs(luastate);
702 
703  /* hackish, needed to allow unittests to pass buffers as scripts instead of files */
704 #ifdef UNITTESTS
705  if (ut_script != NULL) {
706  status = luaL_loadbuffer(luastate, ut_script, strlen(ut_script), "unittest");
707  if (status) {
708  SCLogError(SC_ERR_LUA_ERROR, "couldn't load file: %s", lua_tostring(luastate, -1));
709  goto error;
710  }
711  } else {
712 #endif
713  status = luaL_loadfile(luastate, ld->filename);
714  if (status) {
715  SCLogError(SC_ERR_LUA_ERROR, "couldn't load file: %s", lua_tostring(luastate, -1));
716  goto error;
717  }
718 #ifdef UNITTESTS
719  }
720 #endif
721 
722  /* prime the script (or something) */
723  if (lua_pcall(luastate, 0, 0, 0) != 0) {
724  SCLogError(SC_ERR_LUA_ERROR, "couldn't prime file: %s", lua_tostring(luastate, -1));
725  goto error;
726  }
727 
728  lua_getglobal(luastate, "init");
729  if (lua_type(luastate, -1) != LUA_TFUNCTION) {
730  SCLogError(SC_ERR_LUA_ERROR, "no init function in script");
731  goto error;
732  }
733 
734  lua_newtable(luastate); /* stack at -1 */
735  if (lua_gettop(luastate) == 0 || lua_type(luastate, 2) != LUA_TTABLE) {
736  SCLogError(SC_ERR_LUA_ERROR, "no table setup");
737  goto error;
738  }
739 
740  lua_pushliteral(luastate, "script_api_ver"); /* stack at -2 */
741  lua_pushnumber (luastate, 1); /* stack at -3 */
742  lua_settable(luastate, -3);
743 
744  if (lua_pcall(luastate, 1, 1, 0) != 0) {
745  SCLogError(SC_ERR_LUA_ERROR, "couldn't run script 'init' function: %s", lua_tostring(luastate, -1));
746  goto error;
747  }
748 
749  /* process returns from script */
750  if (lua_gettop(luastate) == 0) {
751  SCLogError(SC_ERR_LUA_ERROR, "init function in script should return table, nothing returned");
752  goto error;
753  }
754  if (lua_type(luastate, 1) != LUA_TTABLE) {
755  SCLogError(SC_ERR_LUA_ERROR, "init function in script should return table, returned is not table");
756  goto error;
757  }
758 
759  lua_pushnil(luastate);
760  const char *k, *v;
761  while (lua_next(luastate, -2)) {
762  k = lua_tostring(luastate, -2);
763  if (k == NULL)
764  continue;
765 
766  /* handle flowvar separately as it has a table as value */
767  if (strcmp(k, "flowvar") == 0) {
768  if (lua_istable(luastate, -1)) {
769  lua_pushnil(luastate);
770  while (lua_next(luastate, -2) != 0) {
771  /* value at -1, key is at -2 which we ignore */
772  const char *value = lua_tostring(luastate, -1);
773  SCLogDebug("value %s", value);
774  /* removes 'value'; keeps 'key' for next iteration */
775  lua_pop(luastate, 1);
776 
777  if (ld->flowvars == DETECT_LUAJIT_MAX_FLOWVARS) {
778  SCLogError(SC_ERR_LUA_ERROR, "too many flowvars registered");
779  goto error;
780  }
781 
782  uint32_t idx = VarNameStoreSetupAdd((char *)value, VAR_TYPE_FLOW_VAR);
783  ld->flowvar[ld->flowvars++] = idx;
784  SCLogDebug("script uses flowvar %u with script id %u", idx, ld->flowvars - 1);
785  }
786  }
787  lua_pop(luastate, 1);
788  continue;
789  } else if (strcmp(k, "flowint") == 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->flowints == DETECT_LUAJIT_MAX_FLOWINTS) {
800  SCLogError(SC_ERR_LUA_ERROR, "too many flowints registered");
801  goto error;
802  }
803 
804  uint32_t idx = VarNameStoreSetupAdd((char *)value, VAR_TYPE_FLOW_INT);
805  ld->flowint[ld->flowints++] = idx;
806  SCLogDebug("script uses flowint %u with script id %u", idx, ld->flowints - 1);
807  }
808  }
809  lua_pop(luastate, 1);
810  continue;
811  }
812 
813  v = lua_tostring(luastate, -1);
814  lua_pop(luastate, 1);
815  if (v == NULL)
816  continue;
817 
818  SCLogDebug("k='%s', v='%s'", k, v);
819  if (strcmp(k, "packet") == 0 && strcmp(v, "true") == 0) {
820  ld->flags |= DATATYPE_PACKET;
821  } else if (strcmp(k, "payload") == 0 && strcmp(v, "true") == 0) {
822  ld->flags |= DATATYPE_PAYLOAD;
823  } else if (strcmp(k, "stream") == 0 && strcmp(v, "true") == 0) {
824  ld->flags |= DATATYPE_STREAM;
825 
826  ld->buffername = SCStrdup("stream");
827  if (ld->buffername == NULL) {
828  SCLogError(SC_ERR_LUA_ERROR, "alloc error");
829  goto error;
830  }
831 
832  } else if (strncmp(k, "http", 4) == 0 && strcmp(v, "true") == 0) {
833  if (ld->alproto != ALPROTO_UNKNOWN && ld->alproto != ALPROTO_HTTP) {
834  SCLogError(SC_ERR_LUA_ERROR, "can just inspect script against one app layer proto like HTTP at a time");
835  goto error;
836  }
837  if (ld->flags != 0) {
838  SCLogError(SC_ERR_LUA_ERROR, "when inspecting HTTP buffers only a single buffer can be inspected");
839  goto error;
840  }
841 
842  /* http types */
843  ld->alproto = ALPROTO_HTTP;
844 
845  if (strcmp(k, "http.uri") == 0)
846  ld->flags |= DATATYPE_HTTP_URI;
847 
848  else if (strcmp(k, "http.uri.raw") == 0)
849  ld->flags |= DATATYPE_HTTP_URI_RAW;
850 
851  else if (strcmp(k, "http.request_line") == 0)
852  ld->flags |= DATATYPE_HTTP_REQUEST_LINE;
853 
854  else if (strcmp(k, "http.request_headers") == 0)
855  ld->flags |= DATATYPE_HTTP_REQUEST_HEADERS;
856 
857  else if (strcmp(k, "http.request_headers.raw") == 0)
858  ld->flags |= DATATYPE_HTTP_REQUEST_HEADERS_RAW;
859 
860  else if (strcmp(k, "http.request_cookie") == 0)
861  ld->flags |= DATATYPE_HTTP_REQUEST_COOKIE;
862 
863  else if (strcmp(k, "http.request_user_agent") == 0)
864  ld->flags |= DATATYPE_HTTP_REQUEST_UA;
865 
866  else if (strcmp(k, "http.request_body") == 0)
867  ld->flags |= DATATYPE_HTTP_REQUEST_BODY;
868 
869  else if (strcmp(k, "http.response_body") == 0)
870  ld->flags |= DATATYPE_HTTP_RESPONSE_BODY;
871 
872  else if (strcmp(k, "http.response_cookie") == 0)
873  ld->flags |= DATATYPE_HTTP_RESPONSE_COOKIE;
874 
875  else if (strcmp(k, "http.response_headers") == 0)
876  ld->flags |= DATATYPE_HTTP_RESPONSE_HEADERS;
877 
878  else if (strcmp(k, "http.response_headers.raw") == 0)
879  ld->flags |= DATATYPE_HTTP_RESPONSE_HEADERS_RAW;
880 
881  else {
882  SCLogError(SC_ERR_LUA_ERROR, "unsupported http data type %s", k);
883  goto error;
884  }
885 
886  ld->buffername = SCStrdup(k);
887  if (ld->buffername == NULL) {
888  SCLogError(SC_ERR_LUA_ERROR, "alloc error");
889  goto error;
890  }
891  } else if (strncmp(k, "dns", 3) == 0 && strcmp(v, "true") == 0) {
892 
893  ld->alproto = ALPROTO_DNS;
894 
895  if (strcmp(k, "dns.rrname") == 0)
896  ld->flags |= DATATYPE_DNS_RRNAME;
897  else if (strcmp(k, "dns.request") == 0)
898  ld->flags |= DATATYPE_DNS_REQUEST;
899  else if (strcmp(k, "dns.response") == 0)
900  ld->flags |= DATATYPE_DNS_RESPONSE;
901 
902  else {
903  SCLogError(SC_ERR_LUA_ERROR, "unsupported dns data type %s", k);
904  goto error;
905  }
906  ld->buffername = SCStrdup(k);
907  if (ld->buffername == NULL) {
908  SCLogError(SC_ERR_LUA_ERROR, "alloc error");
909  goto error;
910  }
911  } else if (strncmp(k, "tls", 3) == 0 && strcmp(v, "true") == 0) {
912 
913  ld->alproto = ALPROTO_TLS;
914 
915  ld->flags |= DATATYPE_TLS;
916 
917  } else if (strncmp(k, "ssh", 3) == 0 && strcmp(v, "true") == 0) {
918 
919  ld->alproto = ALPROTO_SSH;
920 
921  ld->flags |= DATATYPE_SSH;
922 
923  } else if (strncmp(k, "smtp", 4) == 0 && strcmp(v, "true") == 0) {
924 
925  ld->alproto = ALPROTO_SMTP;
926 
927  ld->flags |= DATATYPE_SMTP;
928 
929  } else if (strncmp(k, "dnp3", 4) == 0 && strcmp(v, "true") == 0) {
930 
931  ld->alproto = ALPROTO_DNP3;
932 
933  ld->flags |= DATATYPE_DNP3;
934 
935  } else {
936  SCLogError(SC_ERR_LUA_ERROR, "unsupported data type %s", k);
937  goto error;
938  }
939  }
940 
941  /* pop the table */
942  lua_pop(luastate, 1);
943  lua_close(luastate);
944  return 0;
945 error:
946  lua_close(luastate);
947  return -1;
948 }
949 
950 /**
951  * \brief this function is used to parse lua options
952  * \brief into the current signature
953  *
954  * \param de_ctx pointer to the Detection Engine Context
955  * \param s pointer to the Current Signature
956  * \param str pointer to the user provided "lua" option
957  *
958  * \retval 0 on Success
959  * \retval -1 on Failure
960  */
961 static int DetectLuaSetup (DetectEngineCtx *de_ctx, Signature *s, const char *str)
962 {
963  DetectLuaData *lua = NULL;
964  SigMatch *sm = NULL;
965 
966  lua = DetectLuaParse(de_ctx, str);
967  if (lua == NULL)
968  goto error;
969 
970  if (DetectLuaSetupPrime(de_ctx, lua) == -1) {
971  goto error;
972  }
973 
974  lua->thread_ctx_id = DetectRegisterThreadCtxFuncs(de_ctx, "lua",
975  DetectLuaThreadInit, (void *)lua,
976  DetectLuaThreadFree, 0);
977  if (lua->thread_ctx_id == -1)
978  goto error;
979 
980  if (lua->alproto != ALPROTO_UNKNOWN) {
981  if (s->alproto != ALPROTO_UNKNOWN && lua->alproto != s->alproto) {
982  goto error;
983  }
984  s->alproto = lua->alproto;
985  }
986 
987  /* Okay so far so good, lets get this into a SigMatch
988  * and put it in the Signature. */
989  sm = SigMatchAlloc();
990  if (sm == NULL)
991  goto error;
992 
993  sm->type = DETECT_LUA;
994  sm->ctx = (SigMatchCtx *)lua;
995 
996  int list = -1;
997  if (lua->alproto == ALPROTO_UNKNOWN) {
998  if (lua->flags & DATATYPE_STREAM)
999  list = DETECT_SM_LIST_PMATCH;
1000  else
1001  list = DETECT_SM_LIST_MATCH;
1002 
1003  } else if (lua->alproto == ALPROTO_HTTP) {
1004  if (lua->flags & DATATYPE_HTTP_RESPONSE_BODY) {
1005  list = DetectBufferTypeGetByName("file_data");
1006  } else if (lua->flags & DATATYPE_HTTP_REQUEST_BODY) {
1007  list = DetectBufferTypeGetByName("http_client_body");
1008  } else if (lua->flags & DATATYPE_HTTP_URI) {
1009  list = DetectBufferTypeGetByName("http_uri");
1010  } else if (lua->flags & DATATYPE_HTTP_URI_RAW) {
1011  list = DetectBufferTypeGetByName("http_raw_uri");
1012  } else if (lua->flags & DATATYPE_HTTP_REQUEST_COOKIE ||
1013  lua->flags & DATATYPE_HTTP_RESPONSE_COOKIE)
1014  {
1015  list = DetectBufferTypeGetByName("http_cookie");
1016  } else if (lua->flags & DATATYPE_HTTP_REQUEST_UA) {
1017  list = DetectBufferTypeGetByName("http_user_agent");
1018  } else if (lua->flags & (DATATYPE_HTTP_REQUEST_HEADERS|DATATYPE_HTTP_RESPONSE_HEADERS)) {
1019  list = DetectBufferTypeGetByName("http_header");
1020  } else if (lua->flags & (DATATYPE_HTTP_REQUEST_HEADERS_RAW|DATATYPE_HTTP_RESPONSE_HEADERS_RAW)) {
1021  list = DetectBufferTypeGetByName("http_raw_header");
1022  } else {
1023  list = DetectBufferTypeGetByName("http_request_line");
1024  }
1025  } else if (lua->alproto == ALPROTO_DNS) {
1026  if (lua->flags & DATATYPE_DNS_RRNAME) {
1027  list = DetectBufferTypeGetByName("dns_query");
1028  } else if (lua->flags & DATATYPE_DNS_REQUEST) {
1029  list = DetectBufferTypeGetByName("dns_request");
1030  } else if (lua->flags & DATATYPE_DNS_RESPONSE) {
1031  list = DetectBufferTypeGetByName("dns_response");
1032  }
1033  } else if (lua->alproto == ALPROTO_TLS) {
1034  list = DetectBufferTypeGetByName("tls_generic");
1035  } else if (lua->alproto == ALPROTO_SSH) {
1036  list = DetectBufferTypeGetByName("ssh_banner");
1037  } else if (lua->alproto == ALPROTO_SMTP) {
1038  list = g_smtp_generic_list_id;
1039  } else if (lua->alproto == ALPROTO_DNP3) {
1040  list = DetectBufferTypeGetByName("dnp3");
1041  } else {
1042  SCLogError(SC_ERR_LUA_ERROR, "lua can't be used with protocol %s",
1043  AppLayerGetProtoName(lua->alproto));
1044  goto error;
1045  }
1046 
1047  if (list == -1) {
1048  SCLogError(SC_ERR_LUA_ERROR, "lua can't be used with protocol %s",
1049  AppLayerGetProtoName(lua->alproto));
1050  goto error;
1051  }
1052 
1053  SigMatchAppendSMToList(s, sm, list);
1054 
1055  return 0;
1056 
1057 error:
1058  if (lua != NULL)
1059  DetectLuaFree(lua);
1060  if (sm != NULL)
1061  SCFree(sm);
1062  return -1;
1063 }
1064 
1065 /** \brief post-sig parse function to set the sid,rev,gid into the
1066  * ctx, as this isn't available yet during parsing.
1067  */
1069 {
1070  int i;
1071  SigMatch *sm;
1072 
1073  for (i = 0; i < DETECT_SM_LIST_MAX; i++) {
1074  for (sm = s->init_data->smlists[i]; sm != NULL; sm = sm->next) {
1075  if (sm->type != DETECT_LUA)
1076  continue;
1077 
1078  DetectLuaData *ld = (DetectLuaData *)sm->ctx;
1079  ld->sid = s->id;
1080  ld->rev = s->rev;
1081  ld->gid = s->gid;
1082  }
1083  }
1084 }
1085 
1086 /**
1087  * \brief this function will free memory associated with DetectLuaData
1088  *
1089  * \param ptr pointer to DetectLuaData
1090  */
1091 static void DetectLuaFree(void *ptr)
1092 {
1093  if (ptr != NULL) {
1094  DetectLuaData *lua = (DetectLuaData *)ptr;
1095 
1096  if (lua->buffername)
1097  SCFree(lua->buffername);
1098  if (lua->filename)
1099  SCFree(lua->filename);
1100 
1101  SCFree(lua);
1102  }
1103 }
1104 
1105 #ifdef UNITTESTS
1106 /** \test http buffer */
1107 static int LuaMatchTest01(void)
1108 {
1109  const char script[] =
1110  "function init (args)\n"
1111  " local needs = {}\n"
1112  " needs[\"http.request_headers\"] = tostring(true)\n"
1113  " needs[\"flowvar\"] = {\"cnt\"}\n"
1114  " return needs\n"
1115  "end\n"
1116  "\n"
1117  "function match(args)\n"
1118  " a = ScFlowvarGet(0)\n"
1119  " if a then\n"
1120  " a = tostring(tonumber(a)+1)\n"
1121  " print (a)\n"
1122  " ScFlowvarSet(0, a, #a)\n"
1123  " else\n"
1124  " a = tostring(1)\n"
1125  " print (a)\n"
1126  " ScFlowvarSet(0, a, #a)\n"
1127  " end\n"
1128  " \n"
1129  " print (\"pre check: \" .. (a))\n"
1130  " if tonumber(a) == 2 then\n"
1131  " print \"match\"\n"
1132  " return 1\n"
1133  " end\n"
1134  " return 0\n"
1135  "end\n"
1136  "return 0\n";
1137  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1138  int result = 0;
1139  uint8_t httpbuf1[] =
1140  "POST / HTTP/1.1\r\n"
1141  "Host: www.emergingthreats.net\r\n\r\n";
1142  uint8_t httpbuf2[] =
1143  "POST / HTTP/1.1\r\n"
1144  "Host: www.openinfosecfoundation.org\r\n\r\n";
1145  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1146  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1147  TcpSession ssn;
1148  Packet *p1 = NULL;
1149  Packet *p2 = NULL;
1150  Flow f;
1151  Signature *s = NULL;
1152  ThreadVars th_v;
1153  DetectEngineThreadCtx *det_ctx;
1154 
1156 
1157  ut_script = script;
1158 
1159  memset(&th_v, 0, sizeof(th_v));
1160  memset(&f, 0, sizeof(f));
1161  memset(&ssn, 0, sizeof(ssn));
1162 
1163  p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1164  p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1165 
1166  FLOW_INITIALIZE(&f);
1167  f.protoctx = (void *)&ssn;
1168  f.proto = IPPROTO_TCP;
1169  f.flags |= FLOW_IPV4;
1170  f.alproto = ALPROTO_HTTP;
1171 
1172  p1->flow = &f;
1176  p2->flow = &f;
1180 
1182 
1184  if (de_ctx == NULL) {
1185  goto end;
1186  }
1187  de_ctx->flags |= DE_QUIET;
1188 
1189  s = DetectEngineAppendSig(de_ctx, sig);
1190  if (s == NULL) {
1191  printf("sig parse failed: ");
1192  goto end;
1193  }
1194 
1195  SigGroupBuild(de_ctx);
1196  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1197 
1198  FLOWLOCK_WRLOCK(&f);
1199  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1200  STREAM_TOSERVER, httpbuf1, httplen1);
1201  if (r != 0) {
1202  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1203  FLOWLOCK_UNLOCK(&f);
1204  goto end;
1205  }
1206  FLOWLOCK_UNLOCK(&f);
1207  HtpState *http_state = f.alstate;
1208  if (http_state == NULL) {
1209  printf("no http state: ");
1210  goto end;
1211  }
1212 
1213  /* do detect for p1 */
1214  SCLogDebug("inspecting p1");
1215  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1216 
1217  if ((PacketAlertCheck(p1, 1))) {
1218  printf("sid 1 didn't match on p1 but should have: ");
1219  goto end;
1220  }
1221 
1222  FLOWLOCK_WRLOCK(&f);
1223  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1224  STREAM_TOSERVER, httpbuf2, httplen2);
1225  if (r != 0) {
1226  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
1227  FLOWLOCK_UNLOCK(&f);
1228  goto end;
1229  }
1230  FLOWLOCK_UNLOCK(&f);
1231  /* do detect for p2 */
1232  SCLogDebug("inspecting p2");
1233  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1234 
1235  if (!(PacketAlertCheck(p2, 1))) {
1236  printf("sid 1 didn't match on p2 but should have: ");
1237  goto end;
1238  }
1239 
1240  FlowVar *fv = FlowVarGet(&f, 1);
1241  if (fv == NULL) {
1242  printf("no flowvar: ");
1243  goto end;
1244  }
1245 
1246  if (fv->data.fv_str.value_len != 1) {
1247  printf("%u != %u: ", fv->data.fv_str.value_len, 1);
1248  goto end;
1249  }
1250 
1251  if (memcmp(fv->data.fv_str.value, "2", 1) != 0) {
1252  PrintRawDataFp(stdout, fv->data.fv_str.value, fv->data.fv_str.value_len);
1253 
1254  printf("buffer mismatch: ");
1255  goto end;
1256  }
1257 
1258  result = 1;
1259 end:
1260  if (alp_tctx != NULL)
1261  AppLayerParserThreadCtxFree(alp_tctx);
1262  if (de_ctx != NULL)
1263  DetectEngineCtxFree(de_ctx);
1264 
1266  FLOW_DESTROY(&f);
1267  UTHFreePackets(&p1, 1);
1268  UTHFreePackets(&p2, 1);
1269  return result;
1270 }
1271 
1272 /** \test payload buffer */
1273 static int LuaMatchTest02(void)
1274 {
1275  const char script[] =
1276  "function init (args)\n"
1277  " local needs = {}\n"
1278  " needs[\"payload\"] = tostring(true)\n"
1279  " needs[\"flowvar\"] = {\"cnt\"}\n"
1280  " return needs\n"
1281  "end\n"
1282  "\n"
1283  "function match(args)\n"
1284  " a = ScFlowvarGet(0)\n"
1285  " if a then\n"
1286  " a = tostring(tonumber(a)+1)\n"
1287  " print (a)\n"
1288  " ScFlowvarSet(0, a, #a)\n"
1289  " else\n"
1290  " a = tostring(1)\n"
1291  " print (a)\n"
1292  " ScFlowvarSet(0, a, #a)\n"
1293  " end\n"
1294  " \n"
1295  " print (\"pre check: \" .. (a))\n"
1296  " if tonumber(a) == 2 then\n"
1297  " print \"match\"\n"
1298  " return 1\n"
1299  " end\n"
1300  " return 0\n"
1301  "end\n"
1302  "return 0\n";
1303  char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1304  int result = 0;
1305  uint8_t httpbuf1[] =
1306  "POST / HTTP/1.1\r\n"
1307  "Host: www.emergingthreats.net\r\n\r\n";
1308  uint8_t httpbuf2[] =
1309  "POST / HTTP/1.1\r\n"
1310  "Host: www.openinfosecfoundation.org\r\n\r\n";
1311  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1312  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1313  TcpSession ssn;
1314  Packet *p1 = NULL;
1315  Packet *p2 = NULL;
1316  Flow f;
1317  Signature *s = NULL;
1318  ThreadVars th_v;
1319  DetectEngineThreadCtx *det_ctx;
1320 
1321  ut_script = script;
1322 
1323  memset(&th_v, 0, sizeof(th_v));
1324  memset(&f, 0, sizeof(f));
1325  memset(&ssn, 0, sizeof(ssn));
1326 
1327  p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP);
1328  p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP);
1329 
1330  FLOW_INITIALIZE(&f);
1331  f.protoctx = (void *)&ssn;
1332  f.proto = IPPROTO_TCP;
1333  f.flags |= FLOW_IPV4;
1334  f.alproto = ALPROTO_HTTP;
1335 
1336  p1->flow = &f;
1340  p2->flow = &f;
1344 
1346 
1348  if (de_ctx == NULL) {
1349  goto end;
1350  }
1351  de_ctx->flags |= DE_QUIET;
1352 
1353  s = DetectEngineAppendSig(de_ctx, sig);
1354  if (s == NULL) {
1355  printf("sig parse failed: ");
1356  goto end;
1357  }
1358 
1359  SigGroupBuild(de_ctx);
1360  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1361 
1362  /* do detect for p1 */
1363  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1364 
1365  if ((PacketAlertCheck(p1, 1))) {
1366  printf("sid 1 didn't match on p1 but should have: ");
1367  goto end;
1368  }
1369 
1370  /* do detect for p2 */
1371  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1372 
1373  if (!(PacketAlertCheck(p2, 1))) {
1374  printf("sid 1 didn't match on p2 but should have: ");
1375  goto end;
1376  }
1377 
1378  FlowVar *fv = FlowVarGet(&f, 1);
1379  if (fv == NULL) {
1380  printf("no flowvar: ");
1381  goto end;
1382  }
1383 
1384  if (fv->data.fv_str.value_len != 1) {
1385  printf("%u != %u: ", fv->data.fv_str.value_len, 1);
1386  goto end;
1387  }
1388 
1389  if (memcmp(fv->data.fv_str.value, "2", 1) != 0) {
1390  PrintRawDataFp(stdout, fv->data.fv_str.value, fv->data.fv_str.value_len);
1391 
1392  printf("buffer mismatch: ");
1393  goto end;
1394  }
1395 
1396  result = 1;
1397 end:
1398  if (de_ctx != NULL)
1399  DetectEngineCtxFree(de_ctx);
1400 
1402  FLOW_DESTROY(&f);
1403  UTHFreePackets(&p1, 1);
1404  UTHFreePackets(&p2, 1);
1405  return result;
1406 }
1407 
1408 /** \test packet buffer */
1409 static int LuaMatchTest03(void)
1410 {
1411  const char script[] =
1412  "function init (args)\n"
1413  " local needs = {}\n"
1414  " needs[\"packet\"] = tostring(true)\n"
1415  " needs[\"flowvar\"] = {\"cnt\"}\n"
1416  " return needs\n"
1417  "end\n"
1418  "\n"
1419  "function match(args)\n"
1420  " a = ScFlowvarGet(0)\n"
1421  " if a then\n"
1422  " a = tostring(tonumber(a)+1)\n"
1423  " print (a)\n"
1424  " ScFlowvarSet(0, a, #a)\n"
1425  " else\n"
1426  " a = tostring(1)\n"
1427  " print (a)\n"
1428  " ScFlowvarSet(0, a, #a)\n"
1429  " end\n"
1430  " \n"
1431  " print (\"pre check: \" .. (a))\n"
1432  " if tonumber(a) == 2 then\n"
1433  " print \"match\"\n"
1434  " return 1\n"
1435  " end\n"
1436  " return 0\n"
1437  "end\n"
1438  "return 0\n";
1439  char sig[] = "alert tcp any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1440  int result = 0;
1441  uint8_t httpbuf1[] =
1442  "POST / HTTP/1.1\r\n"
1443  "Host: www.emergingthreats.net\r\n\r\n";
1444  uint8_t httpbuf2[] =
1445  "POST / HTTP/1.1\r\n"
1446  "Host: www.openinfosecfoundation.org\r\n\r\n";
1447  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1448  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1449  TcpSession ssn;
1450  Packet *p1 = NULL;
1451  Packet *p2 = NULL;
1452  Flow f;
1453  Signature *s = NULL;
1454  ThreadVars th_v;
1455  DetectEngineThreadCtx *det_ctx;
1456 
1457  ut_script = script;
1458 
1459  memset(&th_v, 0, sizeof(th_v));
1460  memset(&f, 0, sizeof(f));
1461  memset(&ssn, 0, sizeof(ssn));
1462 
1463  p1 = UTHBuildPacket(httpbuf1, httplen1, IPPROTO_TCP);
1464  p2 = UTHBuildPacket(httpbuf2, httplen2, IPPROTO_TCP);
1465 
1466  FLOW_INITIALIZE(&f);
1467  f.protoctx = (void *)&ssn;
1468  f.proto = IPPROTO_TCP;
1469  f.flags |= FLOW_IPV4;
1470  f.alproto = ALPROTO_HTTP;
1471 
1472  p1->flow = &f;
1476  p2->flow = &f;
1480 
1482 
1484  if (de_ctx == NULL) {
1485  goto end;
1486  }
1487  de_ctx->flags |= DE_QUIET;
1488 
1489  s = DetectEngineAppendSig(de_ctx, sig);
1490  if (s == NULL) {
1491  printf("sig parse failed: ");
1492  goto end;
1493  }
1494 
1495  SigGroupBuild(de_ctx);
1496  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1497 
1498  /* do detect for p1 */
1499  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1500 
1501  if ((PacketAlertCheck(p1, 1))) {
1502  printf("sid 1 didn't match on p1 but should have: ");
1503  goto end;
1504  }
1505 
1506  /* do detect for p2 */
1507  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1508 
1509  if (!(PacketAlertCheck(p2, 1))) {
1510  printf("sid 1 didn't match on p2 but should have: ");
1511  goto end;
1512  }
1513 
1514  FlowVar *fv = FlowVarGet(&f, 1);
1515  if (fv == NULL) {
1516  printf("no flowvar: ");
1517  goto end;
1518  }
1519 
1520  if (fv->data.fv_str.value_len != 1) {
1521  printf("%u != %u: ", fv->data.fv_str.value_len, 1);
1522  goto end;
1523  }
1524 
1525  if (memcmp(fv->data.fv_str.value, "2", 1) != 0) {
1526  PrintRawDataFp(stdout, fv->data.fv_str.value, fv->data.fv_str.value_len);
1527 
1528  printf("buffer mismatch: ");
1529  goto end;
1530  }
1531 
1532  result = 1;
1533 end:
1534  if (de_ctx != NULL)
1535  DetectEngineCtxFree(de_ctx);
1536 
1538  FLOW_DESTROY(&f);
1539  UTHFreePackets(&p1, 1);
1540  UTHFreePackets(&p2, 1);
1541  return result;
1542 }
1543 
1544 /** \test http buffer, flowints */
1545 static int LuaMatchTest04(void)
1546 {
1547  const char script[] =
1548  "function init (args)\n"
1549  " local needs = {}\n"
1550  " needs[\"http.request_headers\"] = tostring(true)\n"
1551  " needs[\"flowint\"] = {\"cnt\"}\n"
1552  " return needs\n"
1553  "end\n"
1554  "\n"
1555  "function match(args)\n"
1556  " print \"inspecting\""
1557  " a = ScFlowintGet(0)\n"
1558  " if a then\n"
1559  " ScFlowintSet(0, a + 1)\n"
1560  " else\n"
1561  " ScFlowintSet(0, 1)\n"
1562  " end\n"
1563  " \n"
1564  " a = ScFlowintGet(0)\n"
1565  " if a == 2 then\n"
1566  " print \"match\"\n"
1567  " return 1\n"
1568  " end\n"
1569  " return 0\n"
1570  "end\n"
1571  "return 0\n";
1572  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1573  int result = 0;
1574  uint8_t httpbuf1[] =
1575  "POST / HTTP/1.1\r\n"
1576  "Host: www.emergingthreats.net\r\n\r\n";
1577  uint8_t httpbuf2[] =
1578  "POST / HTTP/1.1\r\n"
1579  "Host: www.openinfosecfoundation.org\r\n\r\n";
1580  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1581  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1582  TcpSession ssn;
1583  Packet *p1 = NULL;
1584  Packet *p2 = NULL;
1585  Flow f;
1586  Signature *s = NULL;
1587  ThreadVars th_v;
1588  DetectEngineThreadCtx *det_ctx;
1589 
1591 
1592  ut_script = script;
1593 
1594  memset(&th_v, 0, sizeof(th_v));
1595  memset(&f, 0, sizeof(f));
1596  memset(&ssn, 0, sizeof(ssn));
1597 
1598  p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1599  p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1600 
1601  FLOW_INITIALIZE(&f);
1602  f.protoctx = (void *)&ssn;
1603  f.proto = IPPROTO_TCP;
1604  f.flags |= FLOW_IPV4;
1605  f.alproto = ALPROTO_HTTP;
1606 
1607  p1->flow = &f;
1611 
1612  p2->flow = &f;
1616 
1618 
1620  if (de_ctx == NULL) {
1621  goto end;
1622  }
1623  de_ctx->flags |= DE_QUIET;
1624 
1625  s = DetectEngineAppendSig(de_ctx, sig);
1626  if (s == NULL) {
1627  printf("sig parse failed: ");
1628  goto end;
1629  }
1630 
1631  SigGroupBuild(de_ctx);
1632  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1633 
1634  FLOWLOCK_WRLOCK(&f);
1635  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1636  STREAM_TOSERVER, httpbuf1, httplen1);
1637  if (r != 0) {
1638  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1639  FLOWLOCK_UNLOCK(&f);
1640  goto end;
1641  }
1642  FLOWLOCK_UNLOCK(&f);
1643  HtpState *http_state = f.alstate;
1644  if (http_state == NULL) {
1645  printf("no http state: ");
1646  goto end;
1647  }
1648 
1649  /* do detect for p1 */
1650  SCLogInfo("p1");
1651  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1652 
1653  if (PacketAlertCheck(p1, 1)) {
1654  printf("sid 1 matched on p1 but should not have: ");
1655  goto end;
1656  }
1657 
1658  FLOWLOCK_WRLOCK(&f);
1659  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1660  STREAM_TOSERVER, httpbuf2, httplen2);
1661  if (r != 0) {
1662  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
1663  FLOWLOCK_UNLOCK(&f);
1664  goto end;
1665  }
1666  FLOWLOCK_UNLOCK(&f);
1667  /* do detect for p2 */
1668  SCLogInfo("p2");
1669  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1670 
1671  if (!(PacketAlertCheck(p2, 1))) {
1672  printf("sid 1 didn't match on p2 but should have: ");
1673  goto end;
1674  }
1675 
1676  FlowVar *fv = FlowVarGet(&f, 1);
1677  if (fv == NULL) {
1678  printf("no flowvar: ");
1679  goto end;
1680  }
1681 
1682  if (fv->data.fv_int.value != 2) {
1683  printf("%u != %u: ", fv->data.fv_int.value, 2);
1684  goto end;
1685  }
1686 
1687  result = 1;
1688 end:
1689  if (alp_tctx != NULL)
1690  AppLayerParserThreadCtxFree(alp_tctx);
1691  if (de_ctx != NULL)
1692  DetectEngineCtxFree(de_ctx);
1693 
1695  FLOW_DESTROY(&f);
1696  UTHFreePackets(&p1, 1);
1697  UTHFreePackets(&p2, 1);
1698  return result;
1699 }
1700 
1701 /** \test http buffer, flowints */
1702 static int LuaMatchTest05(void)
1703 {
1704  const char script[] =
1705  "function init (args)\n"
1706  " local needs = {}\n"
1707  " needs[\"http.request_headers\"] = tostring(true)\n"
1708  " needs[\"flowint\"] = {\"cnt\"}\n"
1709  " return needs\n"
1710  "end\n"
1711  "\n"
1712  "function match(args)\n"
1713  " print \"inspecting\""
1714  " a = ScFlowintIncr(0)\n"
1715  " if a == 2 then\n"
1716  " print \"match\"\n"
1717  " return 1\n"
1718  " end\n"
1719  " return 0\n"
1720  "end\n"
1721  "return 0\n";
1722  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1723  int result = 0;
1724  uint8_t httpbuf1[] =
1725  "POST / HTTP/1.1\r\n"
1726  "Host: www.emergingthreats.net\r\n\r\n";
1727  uint8_t httpbuf2[] =
1728  "POST / HTTP/1.1\r\n"
1729  "Host: www.openinfosecfoundation.org\r\n\r\n";
1730  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1731  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1732  TcpSession ssn;
1733  Packet *p1 = NULL;
1734  Packet *p2 = NULL;
1735  Flow f;
1736  Signature *s = NULL;
1737  ThreadVars th_v;
1738  DetectEngineThreadCtx *det_ctx;
1739 
1741 
1742  ut_script = script;
1743 
1744  memset(&th_v, 0, sizeof(th_v));
1745  memset(&f, 0, sizeof(f));
1746  memset(&ssn, 0, sizeof(ssn));
1747 
1748  p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1749  p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1750 
1751  FLOW_INITIALIZE(&f);
1752  f.protoctx = (void *)&ssn;
1753  f.proto = IPPROTO_TCP;
1754  f.flags |= FLOW_IPV4;
1755  f.alproto = ALPROTO_HTTP;
1756 
1757  p1->flow = &f;
1761 
1762  p2->flow = &f;
1766 
1768 
1770  if (de_ctx == NULL) {
1771  goto end;
1772  }
1773  de_ctx->flags |= DE_QUIET;
1774 
1775  s = DetectEngineAppendSig(de_ctx, sig);
1776  if (s == NULL) {
1777  printf("sig parse failed: ");
1778  goto end;
1779  }
1780 
1781  SigGroupBuild(de_ctx);
1782  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1783 
1784  FLOWLOCK_WRLOCK(&f);
1785  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1786  STREAM_TOSERVER, httpbuf1, httplen1);
1787  if (r != 0) {
1788  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1789  FLOWLOCK_UNLOCK(&f);
1790  goto end;
1791  }
1792  FLOWLOCK_UNLOCK(&f);
1793  HtpState *http_state = f.alstate;
1794  if (http_state == NULL) {
1795  printf("no http state: ");
1796  goto end;
1797  }
1798 
1799  /* do detect for p1 */
1800  SCLogInfo("p1");
1801  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1802 
1803  if (PacketAlertCheck(p1, 1)) {
1804  printf("sid 1 matched on p1 but should not have: ");
1805  goto end;
1806  }
1807 
1808  FLOWLOCK_WRLOCK(&f);
1809  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1810  STREAM_TOSERVER, httpbuf2, httplen2);
1811  if (r != 0) {
1812  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
1813  FLOWLOCK_UNLOCK(&f);
1814  goto end;
1815  }
1816  FLOWLOCK_UNLOCK(&f);
1817  /* do detect for p2 */
1818  SCLogInfo("p2");
1819  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1820 
1821  if (!(PacketAlertCheck(p2, 1))) {
1822  printf("sid 1 didn't match on p2 but should have: ");
1823  goto end;
1824  }
1825 
1826  FlowVar *fv = FlowVarGet(&f, 1);
1827  if (fv == NULL) {
1828  printf("no flowvar: ");
1829  goto end;
1830  }
1831 
1832  if (fv->data.fv_int.value != 2) {
1833  printf("%u != %u: ", fv->data.fv_int.value, 2);
1834  goto end;
1835  }
1836 
1837  result = 1;
1838 end:
1839  if (alp_tctx != NULL)
1840  AppLayerParserThreadCtxFree(alp_tctx);
1841  if (de_ctx != NULL)
1842  DetectEngineCtxFree(de_ctx);
1843 
1845  FLOW_DESTROY(&f);
1846  UTHFreePackets(&p1, 1);
1847  UTHFreePackets(&p2, 1);
1848  return result;
1849 }
1850 
1851 /** \test http buffer, flowints */
1852 static int LuaMatchTest06(void)
1853 {
1854  const char script[] =
1855  "function init (args)\n"
1856  " local needs = {}\n"
1857  " needs[\"http.request_headers\"] = tostring(true)\n"
1858  " needs[\"flowint\"] = {\"cnt\"}\n"
1859  " return needs\n"
1860  "end\n"
1861  "\n"
1862  "function match(args)\n"
1863  " print \"inspecting\""
1864  " a = ScFlowintGet(0)\n"
1865  " if a == nil then\n"
1866  " print \"new var set to 2\""
1867  " ScFlowintSet(0, 2)\n"
1868  " end\n"
1869  " a = ScFlowintDecr(0)\n"
1870  " if a == 0 then\n"
1871  " print \"match\"\n"
1872  " return 1\n"
1873  " end\n"
1874  " return 0\n"
1875  "end\n"
1876  "return 0\n";
1877  char sig[] = "alert http any any -> any any (flow:to_server; lua:unittest; sid:1;)";
1878  int result = 0;
1879  uint8_t httpbuf1[] =
1880  "POST / HTTP/1.1\r\n"
1881  "Host: www.emergingthreats.net\r\n\r\n";
1882  uint8_t httpbuf2[] =
1883  "POST / HTTP/1.1\r\n"
1884  "Host: www.openinfosecfoundation.org\r\n\r\n";
1885  uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1886  uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1887  TcpSession ssn;
1888  Packet *p1 = NULL;
1889  Packet *p2 = NULL;
1890  Flow f;
1891  Signature *s = NULL;
1892  ThreadVars th_v;
1893  DetectEngineThreadCtx *det_ctx;
1894 
1896 
1897  ut_script = script;
1898 
1899  memset(&th_v, 0, sizeof(th_v));
1900  memset(&f, 0, sizeof(f));
1901  memset(&ssn, 0, sizeof(ssn));
1902 
1903  p1 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1904  p2 = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1905 
1906  FLOW_INITIALIZE(&f);
1907  f.protoctx = (void *)&ssn;
1908  f.proto = IPPROTO_TCP;
1909  f.flags |= FLOW_IPV4;
1910  f.alproto = ALPROTO_HTTP;
1911 
1912  p1->flow = &f;
1916 
1917  p2->flow = &f;
1921 
1923 
1925  if (de_ctx == NULL) {
1926  goto end;
1927  }
1928  de_ctx->flags |= DE_QUIET;
1929 
1930  s = DetectEngineAppendSig(de_ctx, sig);
1931  if (s == NULL) {
1932  printf("sig parse failed: ");
1933  goto end;
1934  }
1935 
1936  SigGroupBuild(de_ctx);
1937  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1938 
1939  FLOWLOCK_WRLOCK(&f);
1940  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1941  STREAM_TOSERVER, httpbuf1, httplen1);
1942  if (r != 0) {
1943  printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1944  FLOWLOCK_UNLOCK(&f);
1945  goto end;
1946  }
1947  FLOWLOCK_UNLOCK(&f);
1948  HtpState *http_state = f.alstate;
1949  if (http_state == NULL) {
1950  printf("no http state: ");
1951  goto end;
1952  }
1953 
1954  /* do detect for p1 */
1955  SCLogInfo("p1");
1956  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1957 
1958  if (PacketAlertCheck(p1, 1)) {
1959  printf("sid 1 matched on p1 but should not have: ");
1960  goto end;
1961  }
1962 
1963  FLOWLOCK_WRLOCK(&f);
1964  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
1965  STREAM_TOSERVER, httpbuf2, httplen2);
1966  if (r != 0) {
1967  printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
1968  FLOWLOCK_UNLOCK(&f);
1969  goto end;
1970  }
1971  FLOWLOCK_UNLOCK(&f);
1972  /* do detect for p2 */
1973  SCLogInfo("p2");
1974  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1975 
1976  if (!(PacketAlertCheck(p2, 1))) {
1977  printf("sid 1 didn't match on p2 but should have: ");
1978  goto end;
1979  }
1980 
1981  FlowVar *fv = FlowVarGet(&f, 1);
1982  if (fv == NULL) {
1983  printf("no flowvar: ");
1984  goto end;
1985  }
1986 
1987  if (fv->data.fv_int.value != 0) {
1988  printf("%u != %u: ", fv->data.fv_int.value, 0);
1989  goto end;
1990  }
1991 
1992  result = 1;
1993 end:
1994  if (alp_tctx != NULL)
1995  AppLayerParserThreadCtxFree(alp_tctx);
1996  if (de_ctx != NULL)
1997  DetectEngineCtxFree(de_ctx);
1998 
2000  FLOW_DESTROY(&f);
2001  UTHFreePackets(&p1, 1);
2002  UTHFreePackets(&p2, 1);
2003  return result;
2004 }
2005 
2006 #endif
2007 
2008 void DetectLuaRegisterTests(void)
2009 {
2010 #ifdef UNITTESTS
2011  UtRegisterTest("LuaMatchTest01", LuaMatchTest01);
2012  UtRegisterTest("LuaMatchTest02", LuaMatchTest02);
2013  UtRegisterTest("LuaMatchTest03", LuaMatchTest03);
2014  UtRegisterTest("LuaMatchTest04", LuaMatchTest04);
2015  UtRegisterTest("LuaMatchTest05", LuaMatchTest05);
2016  UtRegisterTest("LuaMatchTest06", LuaMatchTest06);
2017 #endif
2018 }
2019 
2020 #endif /* HAVE_LUAJIT */
Signature * DetectEngineAppendSig(DetectEngineCtx *de_ctx, const char *sigstr)
Parse and append a Signature into the Detection Engine Context signature list.
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect.h:1403
SignatureInitData * init_data
Definition: detect.h:560
uint16_t flags
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1146
int(* AppLayerTxMatch)(ThreadVars *, DetectEngineThreadCtx *, Flow *, uint8_t flags, void *alstate, void *txv, const Signature *, const SigMatchCtx *)
Definition: detect.h:1132
#define SCLogDebug(...)
Definition: util-debug.h:335
uint16_t value_len
Definition: flow-var.h:39
struct Flow_ * flow
Definition: decode.h:444
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
#define BUG_ON(x)
uint8_t proto
Definition: flow.h:346
uint32_t id
Definition: detect.h:525
#define FLOWLOCK_UNLOCK(fb)
Definition: flow.h:235
#define unlikely(expr)
Definition: util-optimize.h:35
uint64_t AppLayerParserGetTxCnt(const Flow *f, void *alstate)
void * DetectThreadCtxGetKeywordThreadCtx(DetectEngineThreadCtx *det_ctx, int id)
Retrieve thread local keyword ctx by id.
uint64_t offset
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:195
Data needed for Match()
Definition: detect.h:333
void StreamTcpFreeConfig(char quiet)
Definition: stream-tcp.c:669
#define FLOWLOCK_WRLOCK(fb)
Definition: flow.h:232
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
const char * name
Definition: detect.h:1160
uint16_t AppProto
int DetectEngineInspectGenericList(ThreadVars *tv, 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.
Signature container.
Definition: detect.h:492
#define TRUE
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:319
void * protoctx
Definition: flow.h:398
uint64_t AppLayerParserGetTransactionInspectId(AppLayerParserState *pstate, uint8_t direction)
struct SigMatch_ * next
Definition: detect.h:328
main detection engine ctx
Definition: detect.h:720
FlowVarTypeStr fv_str
Definition: flow-var.h:57
void * alstate
Definition: flow.h:436
void DetectLuaPostSetup(Signature *s)
#define DE_QUIET
Definition: detect.h:298
int DetectBufferTypeGetByName(const char *name)
#define str(s)
void * AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
union FlowVar_::@120 data
#define SIG_FLAG_TOCLIENT
Definition: detect.h:244
uint16_t type
uint8_t flags
Definition: detect.h:721
#define SIGMATCH_NOT_BUILT
Definition: detect.h:1334
Data structures and function prototypes for keeping state for the detection engine.
void(* Free)(void *)
Definition: detect.h:1151
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
#define FLOW_DESTROY(f)
Definition: flow-util.h:115
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
void SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1752
uint32_t value
Definition: flow-var.h:44
void DetectLuaRegister(void)
Registration function for keyword: lua.
Definition: detect-lua.c:74
#define SIG_FLAG_TOSERVER
Definition: detect.h:243
#define SCEnter(...)
Definition: util-debug.h:337
void StreamTcpInitConfig(char)
To initialize the stream global configuration data.
Definition: stream-tcp.c:365
uint8_t flowflags
Definition: decode.h:438
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.
#define STREAM_TOCLIENT
Definition: stream.h:32
#define FLOW_PKT_TOSERVER
Definition: flow.h:193
AppProto alproto
Definition: detect.h:496
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol&#39;s parser thread context.
uint32_t gid
Definition: detect.h:526
uint8_t type
Definition: detect.h:325
#define SCReturnInt(x)
Definition: util-debug.h:341
const char * desc
Definition: detect.h:1162
void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:282
struct SigMatch_ ** smlists
Definition: detect.h:486
FlowVarTypeInt fv_int
Definition: flow-var.h:58
int DetectBufferTypeRegister(const char *name)
char * DetectLoadCompleteSigPath(const DetectEngineCtx *de_ctx, const char *sig_file)
Create the path if default-rule-path was specified.
int DetectRegisterThreadCtxFuncs(DetectEngineCtx *de_ctx, const char *name, void *(*InitFunc)(void *), void *data, void(*FreeFunc)(void *), int mode)
Register Thread keyword context Funcs.
uint8_t * value
Definition: flow-var.h:38
SigMatchCtx * ctx
Definition: detect.h:327
const char * alias
Definition: detect.h:1161
#define SCMalloc(a)
Definition: util-mem.h:174
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
FlowVar * FlowVarGet(Flow *f, uint32_t idx)
get the flowvar with index &#39;idx&#39; from the flow
Definition: flow-var.c:78
void PrintRawDataFp(FILE *fp, const uint8_t *buf, uint32_t buflen)
Definition: util-print.c:141
#define SCFree(a)
Definition: util-mem.h:236
uint16_t tx_id
htp_connp_t * connp
int(* Match)(ThreadVars *, DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1129
uint32_t VarNameStoreSetupAdd(const char *name, const enum VarTypes type)
add to staging or return existing id if already in there
const char * url
Definition: detect.h:1163
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:39
#define STREAM_TOSERVER
Definition: stream.h:31
uint32_t rev
Definition: detect.h:527
#define GET_PKT_DATA(p)
Definition: decode.h:224
#define PKT_HAS_FLOW
Definition: decode.h:1101
#define SCStrdup(a)
Definition: util-mem.h:220
const char * AppLayerGetProtoName(AppProto alproto)
Given the internal protocol id, returns a string representation of the protocol.
Definition: app-layer.c:729
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:226
Per thread variable structure.
Definition: threadvars.h:57
#define FLOW_PKT_TOCLIENT
Definition: flow.h:194
AppProto alproto
application level protocol
Definition: flow.h:407
#define GET_PKT_LEN(p)
Definition: decode.h:223
int DetectLuaMatchBuffer(DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, uint8_t *buffer, uint32_t buffer_len, uint32_t offset, Flow *f)
uint32_t flags
Definition: decode.h:442
uint16_t payload_len
Definition: decode.h:546
uint16_t flags
Definition: detect.h:1154
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
void UTHFreePackets(Packet **p, int numpkts)
UTHFreePackets: function to release the allocated data from UTHBuildPacket and the packet itself...
Flow data structure.
Definition: flow.h:327
#define FLOW_IPV4
Definition: flow.h:93
uint8_t * payload
Definition: decode.h:545
uint32_t flags
Definition: flow.h:377
#define PKT_STREAM_EST
Definition: decode.h:1099
void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uint32_t dir, int progress, InspectEngineFuncPtr Callback)
register inspect engine at start up time
void(* RegisterTests)(void)
Definition: detect.h:1152
a single match condition for a signature
Definition: detect.h:324
AppLayerParserState * alparser
Definition: flow.h:435
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, uint8_t *input, uint32_t input_len)
SigMatchCtx * ctx
Definition: detect.h:336
DetectEngineCtx * DetectEngineCtxInit(void)