suricata
output-lua.c
Go to the documentation of this file.
1 /* Copyright (C) 2014-2022 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  *
23  */
24 
25 #include "suricata-common.h"
26 #include "output-lua.h"
27 
28 #include "util-lua-builtins.h"
29 #include "util-debug.h"
30 #include "output.h"
31 #include "app-layer-htp.h"
32 #include "app-layer-ssl.h"
33 #include "app-layer-ssh.h"
34 #include "app-layer-parser.h"
35 #include "util-time.h"
36 #include "util-lua.h"
37 #include "util-lua-common.h"
38 #include "util-lua-http.h"
39 #include "util-lua-smtp.h"
40 
41 #define MODULE_NAME "LuaLog"
42 
43 /** \brief structure containing global config
44  * The OutputLuaLogInitSub which is run per script
45  * can access this to get global config info through
46  * it's parent_ctx->data ptr.
47  */
48 typedef struct LogLuaMasterCtx_ {
49  /** \brief Path to script directory. */
50  char script_dir[PATH_MAX];
51 
52  /** \brief Lua search path for Lua modules. */
53  char path[PATH_MAX];
54 
55  /** \brief Lua search path for C modules. */
56  char cpath[PATH_MAX];
58 
59 typedef struct LogLuaCtx_ {
64 
65 typedef struct LogLuaThreadCtx_ {
68 
69 static TmEcode LuaLogThreadInit(ThreadVars *t, const void *initdata, void **data);
70 static TmEcode LuaLogThreadDeinit(ThreadVars *t, void *data);
71 
72 /** \internal
73  * \brief TX logger for lua scripts
74  *
75  * A single call to this function will run one script on a single
76  * transaction.
77  *
78  * NOTE: The flow (f) also referenced by p->flow is locked.
79  */
80 static int LuaTxLogger(ThreadVars *tv, void *thread_data, const Packet *p, Flow *f, void *alstate, void *txptr, uint64_t tx_id)
81 {
82  SCEnter();
83 
84  LogLuaThreadCtx *td = (LogLuaThreadCtx *)thread_data;
85 
86  SCMutexLock(&td->lua_ctx->m);
87 
90  LuaStateSetTX(td->lua_ctx->luastate, txptr, tx_id);
92 
93  /* prepare data to pass to script */
94  lua_getglobal(td->lua_ctx->luastate, "log");
95  lua_newtable(td->lua_ctx->luastate);
96  LuaPushTableKeyValueInt(td->lua_ctx->luastate, "tx_id", (int)(tx_id));
97 
98  int retval = lua_pcall(td->lua_ctx->luastate, 1, 0, 0);
99  if (retval != 0) {
100  SCLogInfo("failed to run script: %s", lua_tostring(td->lua_ctx->luastate, -1));
101  }
102 
103  SCMutexUnlock(&td->lua_ctx->m);
104  SCReturnInt(0);
105 }
106 
107 /** \internal
108  * \brief Streaming logger for lua scripts
109  *
110  * Hooks into the Streaming Logger API. Gets called for each chunk of new
111  * streaming data.
112  */
113 static int LuaStreamingLogger(ThreadVars *tv, void *thread_data, const Flow *f,
114  const uint8_t *data, uint32_t data_len, uint64_t tx_id, uint8_t flags)
115 {
116  SCEnter();
117 
118  void *txptr = NULL;
119  LuaStreamingBuffer b = { data, data_len, flags };
120 
121  SCLogDebug("flags %02x", flags);
122 
124  if (f && f->alstate)
125  txptr = AppLayerParserGetTx(f->proto, f->alproto, f->alstate, tx_id);
126  }
127 
128  LogLuaThreadCtx *td = (LogLuaThreadCtx *)thread_data;
129 
130  SCMutexLock(&td->lua_ctx->m);
131 
134  LuaStateSetTX(td->lua_ctx->luastate, txptr, tx_id);
135  LuaStateSetFlow(td->lua_ctx->luastate, (Flow *)f);
137 
138  /* prepare data to pass to script */
139  lua_getglobal(td->lua_ctx->luastate, "log");
140  lua_newtable(td->lua_ctx->luastate);
141 
143  LuaPushTableKeyValueInt(td->lua_ctx->luastate, "tx_id", (int)(tx_id));
144 
145  int retval = lua_pcall(td->lua_ctx->luastate, 1, 0, 0);
146  if (retval != 0) {
147  SCLogInfo("failed to run script: %s", lua_tostring(td->lua_ctx->luastate, -1));
148  }
149 
150  SCMutexUnlock(&td->lua_ctx->m);
151 
153 }
154 
155 /** \internal
156  * \brief Packet Logger for lua scripts, for alerts
157  *
158  * A single call to this function will run one script for a single
159  * packet. If it is called, it means that the registered condition
160  * function has returned true.
161  *
162  * The script is called once for each alert stored in the packet.
163  *
164  * NOTE: p->flow is UNlocked
165  */
166 static int LuaPacketLoggerAlerts(ThreadVars *tv, void *thread_data, const Packet *p)
167 {
168  LogLuaThreadCtx *td = (LogLuaThreadCtx *)thread_data;
169 
170  char timebuf[64];
171  CreateTimeString(p->ts, timebuf, sizeof(timebuf));
172 
173  if (!(PacketIsIPv4(p)) && !(PacketIsIPv6(p))) {
174  /* decoder event */
175  goto not_supported;
176  }
177 
178  /* loop through alerts stored in the packet */
179  SCMutexLock(&td->lua_ctx->m);
180  uint16_t cnt;
181  for (cnt = 0; cnt < p->alerts.cnt; cnt++) {
182  const PacketAlert *pa = &p->alerts.alerts[cnt];
183  if (unlikely(pa->s == NULL)) {
184  continue;
185  }
186 
187  lua_getglobal(td->lua_ctx->luastate, "log");
188 
189  void *txptr = NULL;
190  if (p->flow && p->flow->alstate && (pa->flags & PACKET_ALERT_FLAG_TX))
191  txptr = AppLayerParserGetTx(
192  p->flow->proto, p->flow->alproto, p->flow->alstate, pa->tx_id);
193 
196  LuaStateSetTX(td->lua_ctx->luastate, txptr, pa->tx_id);
199 
200  /* prepare data to pass to script */
201  //lua_newtable(td->lua_ctx->luastate);
202 
203  int retval = lua_pcall(td->lua_ctx->luastate, 0, 0, 0);
204  if (retval != 0) {
205  SCLogInfo("failed to run script: %s", lua_tostring(td->lua_ctx->luastate, -1));
206  }
207  }
208  SCMutexUnlock(&td->lua_ctx->m);
209 not_supported:
210  SCReturnInt(0);
211 }
212 
213 static bool LuaPacketConditionAlerts(ThreadVars *tv, void *data, const Packet *p)
214 {
215  return (p->alerts.cnt > 0);
216 }
217 
218 /** \internal
219  * \brief Packet Logger for lua scripts, for packets
220  *
221  * A single call to this function will run one script for a single
222  * packet. If it is called, it means that the registered condition
223  * function has returned true.
224  *
225  * The script is called once for each packet.
226  *
227  * NOTE: p->flow is UNlocked
228  */
229 static int LuaPacketLogger(ThreadVars *tv, void *thread_data, const Packet *p)
230 {
231  LogLuaThreadCtx *td = (LogLuaThreadCtx *)thread_data;
232 
233  char timebuf[64];
234 
235  if ((!(PacketIsIPv4(p))) && (!(PacketIsIPv6(p)))) {
236  goto not_supported;
237  }
238 
239  CreateTimeString(p->ts, timebuf, sizeof(timebuf));
240 
241  /* loop through alerts stored in the packet */
242  SCMutexLock(&td->lua_ctx->m);
243  lua_getglobal(td->lua_ctx->luastate, "log");
244 
248 
249  /* prepare data to pass to script */
250  lua_newtable(td->lua_ctx->luastate);
251 
252  int retval = lua_pcall(td->lua_ctx->luastate, 1, 0, 0);
253  if (retval != 0) {
254  SCLogInfo("failed to run script: %s", lua_tostring(td->lua_ctx->luastate, -1));
255  }
256  SCMutexUnlock(&td->lua_ctx->m);
257 not_supported:
258  SCReturnInt(0);
259 }
260 
261 static bool LuaPacketCondition(ThreadVars *tv, void *data, const Packet *p)
262 {
263  return true;
264 }
265 
266 /** \internal
267  * \brief File API Logger function for Lua scripts
268  *
269  * Executes a script once for one file.
270  *
271  * NOTE p->flow is locked at this point
272  */
273 static int LuaFileLogger(ThreadVars *tv, void *thread_data, const Packet *p, const File *ff,
274  void *tx, const uint64_t tx_id, uint8_t dir)
275 {
276  SCEnter();
277  LogLuaThreadCtx *td = (LogLuaThreadCtx *)thread_data;
278 
279  if ((!(PacketIsIPv4(p))) && (!(PacketIsIPv6(p))))
280  return 0;
281 
282  BUG_ON(ff->flags & FILE_LOGGED);
283 
284  SCLogDebug("ff %p", ff);
285 
286  SCMutexLock(&td->lua_ctx->m);
287 
290  LuaStateSetTX(td->lua_ctx->luastate, tx, tx_id);
292  LuaStateSetFile(td->lua_ctx->luastate, (File *)ff);
293 
294  /* get the lua function to call */
295  lua_getglobal(td->lua_ctx->luastate, "log");
296 
297  int retval = lua_pcall(td->lua_ctx->luastate, 0, 0, 0);
298  if (retval != 0) {
299  SCLogInfo("failed to run script: %s", lua_tostring(td->lua_ctx->luastate, -1));
300  }
301  SCMutexUnlock(&td->lua_ctx->m);
302  return 0;
303 }
304 
305 /** \internal
306  * \brief Flow API Logger function for Lua scripts
307  *
308  * Executes a script once for one flow
309  *
310  * Note: flow 'f' is locked
311  */
312 static int LuaFlowLogger(ThreadVars *tv, void *thread_data, Flow *f)
313 {
314  SCEnter();
315  LogLuaThreadCtx *td = (LogLuaThreadCtx *)thread_data;
316 
317  SCLogDebug("f %p", f);
318 
319  SCMutexLock(&td->lua_ctx->m);
320 
323 
324  /* get the lua function to call */
325  lua_getglobal(td->lua_ctx->luastate, "log");
326 
327  int retval = lua_pcall(td->lua_ctx->luastate, 0, 0, 0);
328  if (retval != 0) {
329  SCLogInfo("failed to run script: %s", lua_tostring(td->lua_ctx->luastate, -1));
330  }
331  SCMutexUnlock(&td->lua_ctx->m);
332  return 0;
333 }
334 
335 
336 
337 static int LuaStatsLogger(ThreadVars *tv, void *thread_data, const StatsTable *st)
338 {
339  SCEnter();
340  LogLuaThreadCtx *td = (LogLuaThreadCtx *)thread_data;
341 
342  SCMutexLock(&td->lua_ctx->m);
343 
344  lua_State *luastate = td->lua_ctx->luastate;
345  /* get the lua function to call */
346  lua_getglobal(td->lua_ctx->luastate, "log");
347 
348  /* create lua array, which is really just a table. The key is an int (1-x),
349  * the value another table with named fields: name, tm_name, value, pvalue.
350  * { 1, { name=<name>, tmname=<tm_name>, value=<value>, pvalue=<pvalue>}}
351  * { 2, { name=<name>, tmname=<tm_name>, value=<value>, pvalue=<pvalue>}}
352  * etc
353  */
354  lua_newtable(luastate);
355  uint32_t u = 0;
356  for (; u < st->nstats; u++) {
357  lua_pushinteger(luastate, u + 1);
358 
359  lua_newtable(luastate);
360 
361  lua_pushstring(luastate, "name");
362  lua_pushstring(luastate, st->stats[u].name);
363  lua_settable(luastate, -3);
364 
365  lua_pushstring(luastate, "tmname");
366  lua_pushstring(luastate, st->stats[u].tm_name);
367  lua_settable(luastate, -3);
368 
369  lua_pushstring(luastate, "value");
370  lua_pushinteger(luastate, st->stats[u].value);
371  lua_settable(luastate, -3);
372 
373  lua_pushstring(luastate, "pvalue");
374  lua_pushinteger(luastate, st->stats[u].pvalue);
375  lua_settable(luastate, -3);
376 
377  lua_settable(luastate, -3);
378  }
379 
380  int retval = lua_pcall(td->lua_ctx->luastate, 1, 0, 0);
381  if (retval != 0) {
382  SCLogInfo("failed to run script: %s", lua_tostring(td->lua_ctx->luastate, -1));
383  }
384  SCMutexUnlock(&td->lua_ctx->m);
385  return 0;
386 
387 }
388 
389 typedef struct LogLuaScriptOptions_ {
391  int packet;
392  int alerts;
393  int file;
395  int tcp_data;
397  int flow;
398  int stats;
400 
401 /** \brief Setup or clear Lua module search paths.
402  *
403  * If search paths are provided by the configuration, set them up,
404  * otherwise clear the default search paths.
405  */
406 static void LuaSetPaths(lua_State *L, LogLuaMasterCtx *ctx)
407 {
408  lua_getglobal(L, "package");
409 
410  if (strlen(ctx->path) > 0) {
411  lua_pushstring(L, ctx->path);
412  } else {
413  lua_pushstring(L, "");
414  }
415  lua_setfield(L, -2, "path");
416 
417  if (strlen(ctx->cpath) > 0) {
418  lua_pushstring(L, ctx->cpath);
419  } else {
420  lua_pushstring(L, "");
421  }
422  lua_setfield(L, -2, "cpath");
423 
424  /* Pop package. */
425  lua_pop(L, 1);
426 }
427 
428 /** \brief load and evaluate the script
429  *
430  * This function parses the script, checks if all the required functions
431  * are defined and runs the 'init' function. The init function will inform
432  * us what the scripts needs are.
433  *
434  * \param filename filename of lua script file
435  * \param options struct to pass script requirements/options back to caller
436  * \retval errcode 0 ok, -1 error
437  */
438 static int LuaScriptInit(const char *filename, LogLuaScriptOptions *options, LogLuaMasterCtx *ctx)
439 {
440  lua_State *luastate = LuaGetState();
441  if (luastate == NULL)
442  goto error;
443  luaL_openlibs(luastate);
444  SCLuaRequirefBuiltIns(luastate);
445  LuaSetPaths(luastate, ctx);
446 
447  int status = luaL_loadfile(luastate, filename);
448  if (status) {
449  SCLogError("couldn't load file: %s", lua_tostring(luastate, -1));
450  goto error;
451  }
452 
453  /* prime the script (or something) */
454  if (lua_pcall(luastate, 0, 0, 0) != 0) {
455  SCLogError("couldn't prime file: %s", lua_tostring(luastate, -1));
456  goto error;
457  }
458 
459  lua_getglobal(luastate, "init");
460  if (lua_type(luastate, -1) != LUA_TFUNCTION) {
461  SCLogError("no init function in script");
462  goto error;
463  }
464 
465  if (lua_pcall(luastate, 0, 1, 0) != 0) {
466  SCLogError("couldn't run script 'init' function: %s", lua_tostring(luastate, -1));
467  goto error;
468  }
469 
470  /* process returns from script */
471  if (lua_gettop(luastate) == 0) {
472  SCLogError("init function in script should return table, nothing returned");
473  goto error;
474  }
475  if (lua_type(luastate, 1) != LUA_TTABLE) {
476  SCLogError("init function in script should return table, returned is not table");
477  goto error;
478  }
479 
480  lua_pushnil(luastate);
481  const char *k, *v;
482  while (lua_next(luastate, -2)) {
483  k = lua_tostring(luastate, -2);
484  if (k == NULL)
485  continue;
486 
487  v = lua_tostring(luastate, -1);
488  lua_pop(luastate, 1);
489  if (v == NULL)
490  continue;
491 
492  SCLogDebug("k='%s', v='%s'", k, v);
493 
494  if (strcmp(k,"protocol") == 0 && strcmp(v, "http") == 0)
495  options->alproto = ALPROTO_HTTP1;
496  else if (strcmp(k,"protocol") == 0 && strcmp(v, "dns") == 0)
497  options->alproto = ALPROTO_DNS;
498  else if (strcmp(k,"protocol") == 0 && strcmp(v, "tls") == 0)
499  options->alproto = ALPROTO_TLS;
500  else if (strcmp(k,"protocol") == 0 && strcmp(v, "ssh") == 0)
501  options->alproto = ALPROTO_SSH;
502  else if (strcmp(k,"protocol") == 0 && strcmp(v, "smtp") == 0)
503  options->alproto = ALPROTO_SMTP;
504  else if (strcmp(k, "type") == 0 && strcmp(v, "packet") == 0)
505  options->packet = 1;
506  else if (strcmp(k, "filter") == 0 && strcmp(v, "alerts") == 0)
507  options->alerts = 1;
508  else if (strcmp(k, "type") == 0 && strcmp(v, "file") == 0)
509  options->file = 1;
510  else if (strcmp(k, "type") == 0 && strcmp(v, "streaming") == 0)
511  options->streaming = 1;
512  else if (strcmp(k, "type") == 0 && strcmp(v, "flow") == 0)
513  options->flow = 1;
514  else if (strcmp(k, "filter") == 0 && strcmp(v, "tcp") == 0)
515  options->tcp_data = 1;
516  else if (strcmp(k, "type") == 0 && strcmp(v, "stats") == 0)
517  options->stats = 1;
518  else {
519  SCLogError("unknown key and/or value: k='%s', v='%s'", k, v);
520  goto error;
521  }
522  }
523 
524  if (((options->alproto != ALPROTO_UNKNOWN)) + options->packet + options->file > 1) {
525  SCLogError("invalid combination of 'needs' in the script");
526  goto error;
527  }
528 
529  lua_getglobal(luastate, "setup");
530  if (lua_type(luastate, -1) != LUA_TFUNCTION) {
531  SCLogError("no setup function in script");
532  goto error;
533  }
534 
535  lua_getglobal(luastate, "log");
536  if (lua_type(luastate, -1) != LUA_TFUNCTION) {
537  SCLogError("no log function in script");
538  goto error;
539  }
540 
541  lua_getglobal(luastate, "deinit");
542  if (lua_type(luastate, -1) != LUA_TFUNCTION) {
543  SCLogError("no deinit function in script");
544  goto error;
545  }
546 
547  LuaReturnState(luastate);
548  return 0;
549 error:
550  if (luastate)
551  LuaReturnState(luastate);
552  return -1;
553 }
554 
555 /** \brief setup a luastate for use at runtime
556  *
557  * This loads the script, primes it and then runs the 'setup' function.
558  *
559  * \retval state Returns the set up luastate on success, NULL on error
560  */
561 static lua_State *LuaScriptSetup(const char *filename, LogLuaMasterCtx *ctx)
562 {
563  lua_State *luastate = LuaGetState();
564  if (luastate == NULL) {
565  SCLogError("luaL_newstate failed");
566  goto error;
567  }
568 
569  luaL_openlibs(luastate);
570  SCLuaRequirefBuiltIns(luastate);
571  LuaSetPaths(luastate, ctx);
572 
573  int status = luaL_loadfile(luastate, filename);
574  if (status) {
575  SCLogError("couldn't load file: %s", lua_tostring(luastate, -1));
576  goto error;
577  }
578 
579  /* prime the script */
580  if (lua_pcall(luastate, 0, 0, 0) != 0) {
581  SCLogError("couldn't prime file: %s", lua_tostring(luastate, -1));
582  goto error;
583  }
584 
585  lua_getglobal(luastate, "setup");
586 
587  /* register functions common to all */
588  LuaRegisterFunctions(luastate);
589 
590  if (lua_pcall(luastate, 0, 0, 0) != 0) {
591  SCLogError("couldn't run script 'setup' function: %s", lua_tostring(luastate, -1));
592  goto error;
593  }
594 
595  SCLogDebug("lua_State %p is set up", luastate);
596  return luastate;
597 error:
598  if (luastate)
599  LuaReturnState(luastate);
600  return NULL;
601 }
602 
603 static void LogLuaSubFree(OutputCtx *oc) {
604  if (oc->data)
605  SCFree(oc->data);
606  SCFree(oc);
607 }
608 
609 /** \brief initialize output for a script instance
610  *
611  * Runs script 'setup' function.
612  */
613 static OutputInitResult OutputLuaLogInitSub(SCConfNode *conf, OutputCtx *parent_ctx)
614 {
615  OutputInitResult result = { NULL, false };
616  if (conf == NULL)
617  return result;
618 
619  LogLuaCtx *lua_ctx = SCCalloc(1, sizeof(LogLuaCtx));
620  if (unlikely(lua_ctx == NULL))
621  return result;
622 
623  OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
624  if (unlikely(output_ctx == NULL)) {
625  SCFree(lua_ctx);
626  return result;
627  }
628 
629  SCMutexInit(&lua_ctx->m, NULL);
630 
631  BUG_ON(parent_ctx == NULL);
632  LogLuaMasterCtx *mc = parent_ctx->data;
633  BUG_ON(mc == NULL);
634 
635  const char *dir = mc->script_dir;
636  char path[PATH_MAX] = "";
637  int ret = snprintf(path, sizeof(path),"%s%s%s", dir, strlen(dir) ? "/" : "", conf->val);
638  if (ret < 0 || ret == sizeof(path)) {
639  SCLogError("failed to construct lua script path");
640  goto error;
641  }
642  SCLogDebug("script full path %s", path);
643 
644  SCMutexLock(&lua_ctx->m);
645  lua_ctx->luastate = LuaScriptSetup(path, mc);
646  SCMutexUnlock(&lua_ctx->m);
647  if (lua_ctx->luastate == NULL)
648  goto error;
649 
650  SCLogDebug("lua_ctx %p", lua_ctx);
651 
652  output_ctx->data = lua_ctx;
653  output_ctx->DeInit = LogLuaSubFree;
654 
655  result.ctx = output_ctx;
656  result.ok = true;
657  return result;
658 error:
659  SCMutexDestroy(&lua_ctx->m);
660  SCFree(lua_ctx);
661  SCFree(output_ctx);
662  return result;
663 }
664 
665 static void LogLuaMasterFree(OutputCtx *oc)
666 {
667  if (oc->data)
668  SCFree(oc->data);
669 
670  OutputModule *om, *tom;
671  TAILQ_FOREACH_SAFE(om, &oc->submodules, entries, tom) {
672  SCFree(om);
673  }
674  SCFree(oc);
675 }
676 
677 /** \internal
678  * \brief initialize output instance for lua module
679  *
680  * Parses nested script list, primes them to find out what they
681  * inspect, then fills the OutputCtx::submodules list with the
682  * proper Logger function for the data type the script needs.
683  */
684 static OutputInitResult OutputLuaLogInit(SCConfNode *conf)
685 {
686  OutputInitResult result = { NULL, false };
687  const char *dir = SCConfNodeLookupChildValue(conf, "scripts-dir");
688  if (dir == NULL)
689  dir = "";
690 
691  SCConfNode *scripts = SCConfNodeLookupChild(conf, "scripts");
692  if (scripts == NULL) {
693  /* No "outputs" section in the configuration. */
694  SCLogInfo("scripts not defined");
695  return result;
696  }
697 
698  /* global output ctx setup */
699  OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
700  if (unlikely(output_ctx == NULL)) {
701  return result;
702  }
703  output_ctx->DeInit = LogLuaMasterFree;
704  output_ctx->data = SCCalloc(1, sizeof(LogLuaMasterCtx));
705  if (unlikely(output_ctx->data == NULL)) {
706  SCFree(output_ctx);
707  return result;
708  }
709  LogLuaMasterCtx *master_config = output_ctx->data;
710  strlcpy(master_config->script_dir, dir, sizeof(master_config->script_dir));
711 
712  const char *lua_path = SCConfNodeLookupChildValue(conf, "path");
713  if (lua_path && strlen(lua_path) > 0) {
714  strlcpy(master_config->path, lua_path, sizeof(master_config->path));
715  }
716 
717  const char *lua_cpath = SCConfNodeLookupChildValue(conf, "cpath");
718  if (lua_cpath && strlen(lua_cpath) > 0) {
719  strlcpy(master_config->cpath, lua_cpath, sizeof(master_config->cpath));
720  }
721 
722  TAILQ_INIT(&output_ctx->submodules);
723 
724  /* check the enables scripts and set them up as submodules */
725  SCConfNode *script;
726  TAILQ_FOREACH(script, &scripts->head, next) {
727  SCLogInfo("enabling script %s", script->val);
728  LogLuaScriptOptions opts;
729  memset(&opts, 0x00, sizeof(opts));
730 
731  char path[PATH_MAX] = "";
732  snprintf(path, sizeof(path),"%s%s%s", dir, strlen(dir) ? "/" : "", script->val);
733  SCLogDebug("script full path %s", path);
734 
735  int r = LuaScriptInit(path, &opts, master_config);
736  if (r != 0) {
737  SCLogError("couldn't initialize script");
738  goto error;
739  }
740 
741  /* create an OutputModule for this script, based
742  * on it's needs. */
743  OutputModule *om = SCCalloc(1, sizeof(*om));
744  if (om == NULL) {
745  SCLogError("calloc() failed");
746  goto error;
747  }
748 
749  om->name = MODULE_NAME;
750  om->conf_name = script->val;
751  om->InitSubFunc = OutputLuaLogInitSub;
752  om->ThreadInit = LuaLogThreadInit;
753  om->ThreadDeinit = LuaLogThreadDeinit;
754 
755  if (opts.alproto == ALPROTO_HTTP1 && opts.streaming) {
756  om->StreamingLogFunc = LuaStreamingLogger;
758  om->alproto = ALPROTO_HTTP1;
761  } else if (opts.alproto == ALPROTO_HTTP1) {
762  om->TxLogFunc = LuaTxLogger;
763  om->alproto = ALPROTO_HTTP1;
764  om->ts_log_progress = -1;
765  om->tc_log_progress = -1;
767  } else if (opts.alproto == ALPROTO_TLS) {
768  om->TxLogFunc = LuaTxLogger;
769  om->alproto = ALPROTO_TLS;
773  } else if (opts.alproto == ALPROTO_DNS) {
774  om->TxLogFunc = LuaTxLogger;
775  om->alproto = ALPROTO_DNS;
776  om->ts_log_progress = -1;
777  om->tc_log_progress = -1;
780  } else if (opts.alproto == ALPROTO_SSH) {
781  om->TxLogFunc = LuaTxLogger;
782  om->alproto = ALPROTO_SSH;
785  } else if (opts.alproto == ALPROTO_SMTP) {
786  om->TxLogFunc = LuaTxLogger;
787  om->alproto = ALPROTO_SMTP;
788  om->ts_log_progress = -1;
789  om->tc_log_progress = -1;
791  } else if (opts.packet && opts.alerts) {
792  om->PacketLogFunc = LuaPacketLoggerAlerts;
793  om->PacketConditionFunc = LuaPacketConditionAlerts;
794  } else if (opts.packet && opts.alerts == 0) {
795  om->PacketLogFunc = LuaPacketLogger;
796  om->PacketConditionFunc = LuaPacketCondition;
797  } else if (opts.file) {
798  om->FileLogFunc = LuaFileLogger;
800  } else if (opts.streaming && opts.tcp_data) {
801  om->StreamingLogFunc = LuaStreamingLogger;
803  } else if (opts.flow) {
804  om->FlowLogFunc = LuaFlowLogger;
805  } else if (opts.stats) {
806  om->StatsLogFunc = LuaStatsLogger;
807  } else {
808  SCLogError("failed to setup thread module");
809  SCFree(om);
810  goto error;
811  }
812 
813  TAILQ_INSERT_TAIL(&output_ctx->submodules, om, entries);
814  }
815 
816  result.ctx = output_ctx;
817  result.ok = true;
818  return result;
819 
820 error:
821  if (output_ctx->DeInit)
822  output_ctx->DeInit(output_ctx);
823 
824  int failure_fatal = 0;
825  if (SCConfGetBool("engine.init-failure-fatal", &failure_fatal) != 1) {
826  SCLogDebug("ConfGetBool could not load the value.");
827  }
828  if (failure_fatal) {
829  FatalError("Error during setup of lua output. Details should be "
830  "described in previous error messages. Shutting down...");
831  }
832 
833  return result;
834 }
835 
836 /** \internal
837  * \brief Run the scripts 'deinit' function
838  */
839 static void OutputLuaLogDoDeinit(LogLuaCtx *lua_ctx)
840 {
841  lua_State *luastate = lua_ctx->luastate;
842 
843  lua_getglobal(luastate, "deinit");
844  if (lua_type(luastate, -1) != LUA_TFUNCTION) {
845  SCLogError("no deinit function in script");
846  return;
847  }
848  //LuaPrintStack(luastate);
849 
850  if (lua_pcall(luastate, 0, 0, 0) != 0) {
851  SCLogError("couldn't run script 'deinit' function: %s", lua_tostring(luastate, -1));
852  return;
853  }
854  LuaReturnState(luastate);
855 }
856 
857 /** \internal
858  * \brief Initialize the thread storage for lua
859  *
860  * Currently only stores a pointer to the global LogLuaCtx
861  */
862 static TmEcode LuaLogThreadInit(ThreadVars *t, const void *initdata, void **data)
863 {
864  LogLuaThreadCtx *td = SCCalloc(1, sizeof(*td));
865  if (unlikely(td == NULL))
866  return TM_ECODE_FAILED;
867 
868  if (initdata == NULL) {
869  SCLogDebug("Error getting context for LuaLog. \"initdata\" argument NULL");
870  SCFree(td);
871  return TM_ECODE_FAILED;
872  }
873 
874  LogLuaCtx *lua_ctx = ((OutputCtx *)initdata)->data;
875  SCLogDebug("lua_ctx %p", lua_ctx);
876  td->lua_ctx = lua_ctx;
877  *data = (void *)td;
878  return TM_ECODE_OK;
879 }
880 
881 /** \internal
882  * \brief Deinit the thread storage for lua
883  *
884  * Calls OutputLuaLogDoDeinit if no-one else already did.
885  */
886 static TmEcode LuaLogThreadDeinit(ThreadVars *t, void *data)
887 {
888  LogLuaThreadCtx *td = (LogLuaThreadCtx *)data;
889  if (td == NULL) {
890  return TM_ECODE_OK;
891  }
892 
893  SCMutexLock(&td->lua_ctx->m);
894  if (td->lua_ctx->deinit_once == 0) {
895  OutputLuaLogDoDeinit(td->lua_ctx);
896  td->lua_ctx->deinit_once = 1;
897  }
898  SCMutexUnlock(&td->lua_ctx->m);
899 
900  /* clear memory */
901  memset(td, 0, sizeof(*td));
902 
903  SCFree(td);
904  return TM_ECODE_OK;
905 }
906 
907 void LuaLogRegister(void) {
908  /* register as separate module */
909  OutputRegisterModule(MODULE_NAME, "lua", OutputLuaLogInit);
910 }
LuaStateSetTX
void LuaStateSetTX(lua_State *luastate, void *txptr, const uint64_t tx_id)
Definition: util-lua.c:150
LogLuaThreadCtx
struct LogLuaThreadCtx_ LogLuaThreadCtx
LuaStateSetPacket
void LuaStateSetPacket(lua_State *luastate, Packet *p)
Definition: util-lua.c:126
OutputModule_::FileLogFunc
SCFileLogger FileLogFunc
Definition: output.h:73
LogLuaMasterCtx_
structure containing global config The OutputLuaLogInitSub which is run per script can access this to...
Definition: output-lua.c:48
AppLayerHtpNeedFileInspection
void AppLayerHtpNeedFileInspection(void)
Sets a flag that informs the HTP app layer that some module in the engine needs the http request file...
Definition: app-layer-htp.c:574
LuaStateSetThreadVars
void LuaStateSetThreadVars(lua_State *luastate, ThreadVars *tv)
Definition: util-lua.c:110
PacketAlert_::s
const struct Signature_ * s
Definition: decode.h:247
STREAMING_TCP_DATA
@ STREAMING_TCP_DATA
Definition: output-streaming.h:36
LogLuaScriptOptions_::file
int file
Definition: output-lua.c:393
app-layer-ssh.h
LogLuaScriptOptions_::alproto
AppProto alproto
Definition: output-lua.c:390
util-lua-common.h
TAILQ_INIT
#define TAILQ_INIT(head)
Definition: queue.h:262
LuaPushTableKeyValueInt
void LuaPushTableKeyValueInt(lua_State *luastate, const char *key, int value)
Definition: util-lua-common.c:59
ALPROTO_DNS
@ ALPROTO_DNS
Definition: app-layer-protos.h:47
LuaStreamingBuffer_
Definition: util-lua.h:34
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
ALPROTO_TLS
@ ALPROTO_TLS
Definition: app-layer-protos.h:39
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:270
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
Flow_::proto
uint8_t proto
Definition: flow.h:378
util-lua.h
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:86
LogLuaCtx_
Definition: output-lua.c:59
PacketAlerts_::cnt
uint16_t cnt
Definition: decode.h:281
LuaGetState
lua_State * LuaGetState(void)
Definition: util-lua.c:57
OutputModule_::name
const char * name
Definition: output.h:59
Flow_
Flow data structure.
Definition: flow.h:356
ctx
struct Thresholds ctx
LogLuaScriptOptions_::tcp_data
int tcp_data
Definition: output-lua.c:395
OutputModule_::ts_log_progress
int ts_log_progress
Definition: output.h:81
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:252
PacketAlerts_::alerts
PacketAlert * alerts
Definition: decode.h:284
SSHTxLogCondition
bool SSHTxLogCondition(ThreadVars *tv, const Packet *p, void *state, void *tx, uint64_t tx_id)
Definition: app-layer-ssh.c:76
OutputModule_::StatsLogFunc
StatsLogger StatsLogFunc
Definition: output.h:77
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
SCConfGetBool
int SCConfGetBool(const char *name, int *val)
Retrieve a configuration value as a boolean.
Definition: conf.c:497
LuaStateSetFlow
void LuaStateSetFlow(lua_State *luastate, Flow *f)
set a flow pointer in the lua state
Definition: util-lua.c:176
TAILQ_INSERT_TAIL
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:294
util-lua-builtins.h
LogLuaScriptOptions
struct LogLuaScriptOptions_ LogLuaScriptOptions
OutputModule_::InitSubFunc
OutputInitSubFunc InitSubFunc
Definition: output.h:63
SCConfNodeLookupChildValue
const char * SCConfNodeLookupChildValue(const SCConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition: conf.c:824
ALPROTO_SSH
@ ALPROTO_SSH
Definition: app-layer-protos.h:40
StatsRecord_::pvalue
int64_t pvalue
Definition: output-stats.h:36
LogLuaThreadCtx_
Definition: output-lua.c:65
OutputModule_::PacketLogFunc
PacketLogger PacketLogFunc
Definition: output.h:68
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:82
OUTPUT_STREAMING_FLAG_TRANSACTION
#define OUTPUT_STREAMING_FLAG_TRANSACTION
Definition: output-streaming.h:33
OutputModule_::alproto
AppProto alproto
Definition: output.h:78
LogLuaMasterCtx_::path
char path[PATH_MAX]
Lua search path for Lua modules.
Definition: output-lua.c:53
Packet_::alerts
PacketAlerts alerts
Definition: decode.h:611
OutputCtx_::data
void * data
Definition: tm-modules.h:87
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:81
PacketAlert_::tx_id
uint64_t tx_id
Definition: decode.h:248
OutputCtx_
Definition: tm-modules.h:84
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
lua_State
struct lua_State lua_State
Definition: suricata-common.h:523
LogLuaMasterCtx
struct LogLuaMasterCtx_ LogLuaMasterCtx
structure containing global config The OutputLuaLogInitSub which is run per script can access this to...
OutputModule_::stream_type
enum SCOutputStreamingType stream_type
Definition: output.h:79
app-layer-htp.h
OutputModule_::ThreadInit
ThreadInitFunc ThreadInit
Definition: output.h:65
util-debug.h
TLS_STATE_CLIENT_HANDSHAKE_DONE
@ TLS_STATE_CLIENT_HANDSHAKE_DONE
Definition: app-layer-ssl.h:81
LogLuaScriptOptions_
Definition: output-lua.c:389
OutputInitResult_::ctx
OutputCtx * ctx
Definition: output.h:47
OutputModule_::ThreadDeinit
ThreadDeinitFunc ThreadDeinit
Definition: output.h:66
Packet_::ts
SCTime_t ts
Definition: decode.h:546
LogLuaScriptOptions_::stats
int stats
Definition: output-lua.c:398
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:119
LuaStateSetFile
void LuaStateSetFile(lua_State *luastate, File *file)
Definition: util-lua.c:231
ALPROTO_SMTP
@ ALPROTO_SMTP
Definition: app-layer-protos.h:38
AppLayerHtpEnableRequestBodyCallback
void AppLayerHtpEnableRequestBodyCallback(void)
Sets a flag that informs the HTP app layer that some module in the engine needs the http request body...
Definition: app-layer-htp.c:547
AppLayerParserRegisterLogger
void AppLayerParserRegisterLogger(uint8_t ipproto, AppProto alproto)
Definition: app-layer-parser.c:490
OutputRegisterModule
void OutputRegisterModule(const char *, const char *, OutputInitFunc)
SCEnter
#define SCEnter(...)
Definition: util-debug.h:272
LogLuaScriptOptions_::packet
int packet
Definition: output-lua.c:391
StatsRecord_::name
const char * name
Definition: output-stats.h:32
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
LogLuaCtx_::luastate
lua_State * luastate
Definition: output-lua.c:61
OutputModule_::StreamingLogFunc
SCStreamingLogger StreamingLogFunc
Definition: output.h:76
LogLuaScriptOptions_::streaming
int streaming
Definition: output-lua.c:394
util-time.h
OutputInitResult_::ok
bool ok
Definition: output.h:48
app-layer-parser.h
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:317
StatsTable_
Definition: output-stats.h:39
StatsRecord_::value
int64_t value
Definition: output-stats.h:35
LogLuaCtx_::m
SCMutex m
Definition: output-lua.c:60
OutputModule_::conf_name
const char * conf_name
Definition: output.h:60
OutputModule_::FlowLogFunc
FlowLogger FlowLogFunc
Definition: output.h:75
Packet_
Definition: decode.h:492
TmEcode
TmEcode
Definition: tm-threads-common.h:80
LogLuaScriptOptions_::http_body
int http_body
Definition: output-lua.c:396
AppLayerHtpEnableResponseBodyCallback
void AppLayerHtpEnableResponseBodyCallback(void)
Sets a flag that informs the HTP app layer that some module in the engine needs the http request body...
Definition: app-layer-htp.c:560
LogLuaScriptOptions_::flow
int flow
Definition: output-lua.c:397
SCLuaRequirefBuiltIns
void SCLuaRequirefBuiltIns(lua_State *L)
Register Suricata built-in modules for loading in a non-sandboxed environment.
Definition: util-lua-builtins.c:79
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:225
TAILQ_FOREACH_SAFE
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:329
AppLayerParserGetTx
void * AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
Definition: app-layer-parser.c:1108
SCMutexInit
#define SCMutexInit(mut, mutattrs)
Definition: threads-debug.h:116
StatsTable_::stats
StatsRecord * stats
Definition: output-stats.h:40
util-lua-smtp.h
PacketAlert_::flags
uint8_t flags
Definition: decode.h:246
File_::flags
uint16_t flags
Definition: util-file.h:80
SCConfNodeLookupChild
SCConfNode * SCConfNodeLookupChild(const SCConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition: conf.c:796
File_
Definition: util-file.h:79
LogLuaMasterCtx_::cpath
char cpath[PATH_MAX]
Lua search path for C modules.
Definition: output-lua.c:56
cnt
uint32_t cnt
Definition: tmqh-packetpool.h:7
OutputInitResult_
Definition: output.h:46
Packet_::flow
struct Flow_ * flow
Definition: decode.h:537
OutputModule_::TxLogCondition
TxLoggerCondition TxLogCondition
Definition: output.h:72
flags
uint8_t flags
Definition: decode-gre.h:0
suricata-common.h
OutputCtx_::DeInit
void(* DeInit)(struct OutputCtx_ *)
Definition: tm-modules.h:90
ALPROTO_HTTP1
@ ALPROTO_HTTP1
Definition: app-layer-protos.h:36
LuaStateSetPacketAlert
void LuaStateSetPacketAlert(lua_State *luastate, PacketAlert *pa)
Definition: util-lua.c:199
StatsRecord_::tm_name
const char * tm_name
Definition: output-stats.h:34
FatalError
#define FatalError(...)
Definition: util-debug.h:503
LuaLogRegister
void LuaLogRegister(void)
Definition: output-lua.c:907
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
OutputModule_::PacketConditionFunc
PacketLogCondition PacketConditionFunc
Definition: output.h:70
FILE_LOGGED
#define FILE_LOGGED
Definition: util-file.h:53
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:262
LuaStateSetStreamingBuffer
void LuaStateSetStreamingBuffer(lua_State *luastate, LuaStreamingBuffer *b)
Definition: util-lua.c:262
SCFree
#define SCFree(p)
Definition: util-mem.h:61
Flow_::alstate
void * alstate
Definition: flow.h:479
OutputModule_::TxLogFunc
TxLogger TxLogFunc
Definition: output.h:71
OutputModule_::tc_log_progress
int tc_log_progress
Definition: output.h:80
STREAMING_HTTP_BODIES
@ STREAMING_HTTP_BODIES
Definition: output-streaming.h:37
PACKET_ALERT_FLAG_TX
#define PACKET_ALERT_FLAG_TX
Definition: decode.h:266
ALPROTO_UNKNOWN
@ ALPROTO_UNKNOWN
Definition: app-layer-protos.h:29
output-lua.h
PacketAlert_
Definition: decode.h:243
LogLuaCtx_::deinit_once
int deinit_once
Definition: output-lua.c:62
util-lua-http.h
LogLuaCtx
struct LogLuaCtx_ LogLuaCtx
LogLuaScriptOptions_::alerts
int alerts
Definition: output-lua.c:392
TLS_STATE_SERVER_HANDSHAKE_DONE
@ TLS_STATE_SERVER_HANDSHAKE_DONE
Definition: app-layer-ssl.h:90
OutputModule_
Definition: output.h:57
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:450
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:276
SCMutexDestroy
#define SCMutexDestroy
Definition: threads-debug.h:120
SCConfNode_
Definition: conf.h:37
LogLuaMasterCtx_::script_dir
char script_dir[PATH_MAX]
Path to script directory.
Definition: output-lua.c:50
SCConfNode_::val
char * val
Definition: conf.h:39
StatsTable_::nstats
uint32_t nstats
Definition: output-stats.h:42
LuaRegisterFunctions
int LuaRegisterFunctions(lua_State *luastate)
Definition: util-lua-common.c:155
SCMutex
#define SCMutex
Definition: threads-debug.h:114
app-layer-ssl.h
CreateTimeString
void CreateTimeString(const SCTime_t ts, char *str, size_t size)
Definition: util-time.c:272
LogLuaThreadCtx_::lua_ctx
LogLuaCtx * lua_ctx
Definition: output-lua.c:66
output.h
LuaReturnState
void LuaReturnState(lua_State *s)
Definition: util-lua.c:64
MODULE_NAME
#define MODULE_NAME
Definition: output-lua.c:41