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  SCMutexLock(&td->lua_ctx->m);
130  lua_State *luastate = td->lua_ctx->luastate;
131 
132  LuaStateSetThreadVars(luastate, tv);
134  LuaStateSetTX(luastate, txptr, tx_id);
135  LuaStateSetFlow(luastate, (Flow *)f);
136  LuaStateSetStreamingBuffer(luastate, &b);
137 
138  /* prepare data to pass to script */
139  lua_getglobal(luastate, "log");
140  lua_newtable(luastate);
141 
143  LuaPushTableKeyValueInt(luastate, "tx_id", (int)(tx_id));
144 
145  /* create the "stream" subtable */
146  lua_pushstring(luastate, "stream");
147  lua_newtable(luastate);
148 
149  LuaPushTableKeyValueLString(luastate, "data", (const char *)data, data_len);
154 
155  /* set the "stream" subtable into the main args table */
156  lua_settable(luastate, -3);
157 
158  int retval = lua_pcall(luastate, 1, 0, 0);
159  if (retval != 0) {
160  SCLogInfo("failed to run script: %s", lua_tostring(td->lua_ctx->luastate, -1));
161  }
162 
163  SCMutexUnlock(&td->lua_ctx->m);
164 
166 }
167 
168 /** \internal
169  * \brief Packet Logger for lua scripts, for alerts
170  *
171  * A single call to this function will run one script for a single
172  * packet. If it is called, it means that the registered condition
173  * function has returned true.
174  *
175  * The script is called once for each alert stored in the packet.
176  *
177  * NOTE: p->flow is UNlocked
178  */
179 static int LuaPacketLoggerAlerts(ThreadVars *tv, void *thread_data, const Packet *p)
180 {
181  LogLuaThreadCtx *td = (LogLuaThreadCtx *)thread_data;
182 
183  char timebuf[64];
184  CreateTimeString(p->ts, timebuf, sizeof(timebuf));
185 
186  if (!(PacketIsIPv4(p)) && !(PacketIsIPv6(p))) {
187  /* decoder event */
188  goto not_supported;
189  }
190 
191  /* loop through alerts stored in the packet */
192  SCMutexLock(&td->lua_ctx->m);
193  uint16_t cnt;
194  for (cnt = 0; cnt < p->alerts.cnt; cnt++) {
195  const PacketAlert *pa = &p->alerts.alerts[cnt];
196  if (unlikely(pa->s == NULL)) {
197  continue;
198  }
199 
200  lua_getglobal(td->lua_ctx->luastate, "log");
201 
202  void *txptr = NULL;
203  if (p->flow && p->flow->alstate && (pa->flags & PACKET_ALERT_FLAG_TX))
204  txptr = AppLayerParserGetTx(
205  p->flow->proto, p->flow->alproto, p->flow->alstate, pa->tx_id);
206 
209  LuaStateSetTX(td->lua_ctx->luastate, txptr, pa->tx_id);
212 
213  /* prepare data to pass to script */
214  //lua_newtable(td->lua_ctx->luastate);
215 
216  int retval = lua_pcall(td->lua_ctx->luastate, 0, 0, 0);
217  if (retval != 0) {
218  SCLogInfo("failed to run script: %s", lua_tostring(td->lua_ctx->luastate, -1));
219  }
220  }
221  SCMutexUnlock(&td->lua_ctx->m);
222 not_supported:
223  SCReturnInt(0);
224 }
225 
226 static bool LuaPacketConditionAlerts(ThreadVars *tv, void *data, const Packet *p)
227 {
228  return (p->alerts.cnt > 0);
229 }
230 
231 /** \internal
232  * \brief Packet Logger for lua scripts, for packets
233  *
234  * A single call to this function will run one script for a single
235  * packet. If it is called, it means that the registered condition
236  * function has returned true.
237  *
238  * The script is called once for each packet.
239  *
240  * NOTE: p->flow is UNlocked
241  */
242 static int LuaPacketLogger(ThreadVars *tv, void *thread_data, const Packet *p)
243 {
244  LogLuaThreadCtx *td = (LogLuaThreadCtx *)thread_data;
245 
246  char timebuf[64];
247 
248  if ((!(PacketIsIPv4(p))) && (!(PacketIsIPv6(p)))) {
249  goto not_supported;
250  }
251 
252  CreateTimeString(p->ts, timebuf, sizeof(timebuf));
253 
254  /* loop through alerts stored in the packet */
255  SCMutexLock(&td->lua_ctx->m);
256  lua_getglobal(td->lua_ctx->luastate, "log");
257 
261 
262  /* prepare data to pass to script */
263  lua_newtable(td->lua_ctx->luastate);
264 
265  int retval = lua_pcall(td->lua_ctx->luastate, 1, 0, 0);
266  if (retval != 0) {
267  SCLogInfo("failed to run script: %s", lua_tostring(td->lua_ctx->luastate, -1));
268  }
269  SCMutexUnlock(&td->lua_ctx->m);
270 not_supported:
271  SCReturnInt(0);
272 }
273 
274 static bool LuaPacketCondition(ThreadVars *tv, void *data, const Packet *p)
275 {
276  return true;
277 }
278 
279 /** \internal
280  * \brief File API Logger function for Lua scripts
281  *
282  * Executes a script once for one file.
283  *
284  * NOTE p->flow is locked at this point
285  */
286 static int LuaFileLogger(ThreadVars *tv, void *thread_data, const Packet *p, const File *ff,
287  void *tx, const uint64_t tx_id, uint8_t dir)
288 {
289  SCEnter();
290  LogLuaThreadCtx *td = (LogLuaThreadCtx *)thread_data;
291 
292  if ((!(PacketIsIPv4(p))) && (!(PacketIsIPv6(p))))
293  return 0;
294 
295  BUG_ON(ff->flags & FILE_LOGGED);
296 
297  SCLogDebug("ff %p", ff);
298 
299  SCMutexLock(&td->lua_ctx->m);
300 
303  LuaStateSetTX(td->lua_ctx->luastate, tx, tx_id);
305  LuaStateSetFile(td->lua_ctx->luastate, (File *)ff);
306 
307  /* get the lua function to call */
308  lua_getglobal(td->lua_ctx->luastate, "log");
309 
310  int retval = lua_pcall(td->lua_ctx->luastate, 0, 0, 0);
311  if (retval != 0) {
312  SCLogInfo("failed to run script: %s", lua_tostring(td->lua_ctx->luastate, -1));
313  }
314  SCMutexUnlock(&td->lua_ctx->m);
315  return 0;
316 }
317 
318 /** \internal
319  * \brief Flow API Logger function for Lua scripts
320  *
321  * Executes a script once for one flow
322  *
323  * Note: flow 'f' is locked
324  */
325 static int LuaFlowLogger(ThreadVars *tv, void *thread_data, Flow *f)
326 {
327  SCEnter();
328  LogLuaThreadCtx *td = (LogLuaThreadCtx *)thread_data;
329 
330  SCLogDebug("f %p", f);
331 
332  SCMutexLock(&td->lua_ctx->m);
333 
336 
337  /* get the lua function to call */
338  lua_getglobal(td->lua_ctx->luastate, "log");
339 
340  int retval = lua_pcall(td->lua_ctx->luastate, 0, 0, 0);
341  if (retval != 0) {
342  SCLogInfo("failed to run script: %s", lua_tostring(td->lua_ctx->luastate, -1));
343  }
344  SCMutexUnlock(&td->lua_ctx->m);
345  return 0;
346 }
347 
348 
349 
350 static int LuaStatsLogger(ThreadVars *tv, void *thread_data, const StatsTable *st)
351 {
352  SCEnter();
353  LogLuaThreadCtx *td = (LogLuaThreadCtx *)thread_data;
354 
355  SCMutexLock(&td->lua_ctx->m);
356 
357  lua_State *luastate = td->lua_ctx->luastate;
358  /* get the lua function to call */
359  lua_getglobal(td->lua_ctx->luastate, "log");
360 
361  /* create lua array, which is really just a table. The key is an int (1-x),
362  * the value another table with named fields: name, tm_name, value, pvalue.
363  * { 1, { name=<name>, tmname=<tm_name>, value=<value>, pvalue=<pvalue>}}
364  * { 2, { name=<name>, tmname=<tm_name>, value=<value>, pvalue=<pvalue>}}
365  * etc
366  */
367  lua_newtable(luastate);
368  uint32_t u = 0;
369  for (; u < st->nstats; u++) {
370  lua_pushinteger(luastate, u + 1);
371 
372  lua_newtable(luastate);
373 
374  lua_pushstring(luastate, "name");
375  lua_pushstring(luastate, st->stats[u].name);
376  lua_settable(luastate, -3);
377 
378  lua_pushstring(luastate, "tmname");
379  lua_pushstring(luastate, st->stats[u].tm_name);
380  lua_settable(luastate, -3);
381 
382  lua_pushstring(luastate, "value");
383  lua_pushinteger(luastate, st->stats[u].value);
384  lua_settable(luastate, -3);
385 
386  lua_pushstring(luastate, "pvalue");
387  lua_pushinteger(luastate, st->stats[u].pvalue);
388  lua_settable(luastate, -3);
389 
390  lua_settable(luastate, -3);
391  }
392 
393  int retval = lua_pcall(td->lua_ctx->luastate, 1, 0, 0);
394  if (retval != 0) {
395  SCLogInfo("failed to run script: %s", lua_tostring(td->lua_ctx->luastate, -1));
396  }
397  SCMutexUnlock(&td->lua_ctx->m);
398  return 0;
399 
400 }
401 
402 typedef struct LogLuaScriptOptions_ {
404  int packet;
405  int alerts;
406  int file;
408  int tcp_data;
410  int flow;
411  int stats;
413 
414 /** \brief Setup or clear Lua module search paths.
415  *
416  * If search paths are provided by the configuration, set them up,
417  * otherwise clear the default search paths.
418  */
419 static void LuaSetPaths(lua_State *L, LogLuaMasterCtx *ctx)
420 {
421  lua_getglobal(L, "package");
422 
423  if (strlen(ctx->path) > 0) {
424  lua_pushstring(L, ctx->path);
425  } else {
426  lua_pushstring(L, "");
427  }
428  lua_setfield(L, -2, "path");
429 
430  if (strlen(ctx->cpath) > 0) {
431  lua_pushstring(L, ctx->cpath);
432  } else {
433  lua_pushstring(L, "");
434  }
435  lua_setfield(L, -2, "cpath");
436 
437  /* Pop package. */
438  lua_pop(L, 1);
439 }
440 
441 /** \brief load and evaluate the script
442  *
443  * This function parses the script, checks if all the required functions
444  * are defined and runs the 'init' function. The init function will inform
445  * us what the scripts needs are.
446  *
447  * \param filename filename of lua script file
448  * \param options struct to pass script requirements/options back to caller
449  * \retval errcode 0 ok, -1 error
450  */
451 static int LuaScriptInit(const char *filename, LogLuaScriptOptions *options, LogLuaMasterCtx *ctx)
452 {
453  lua_State *luastate = LuaGetState();
454  if (luastate == NULL)
455  goto error;
456  luaL_openlibs(luastate);
457  SCLuaRequirefBuiltIns(luastate);
458  LuaSetPaths(luastate, ctx);
459 
460  int status = luaL_loadfile(luastate, filename);
461  if (status) {
462  SCLogError("couldn't load file: %s", lua_tostring(luastate, -1));
463  goto error;
464  }
465 
466  /* prime the script (or something) */
467  if (lua_pcall(luastate, 0, 0, 0) != 0) {
468  SCLogError("couldn't prime file: %s", lua_tostring(luastate, -1));
469  goto error;
470  }
471 
472  lua_getglobal(luastate, "init");
473  if (lua_type(luastate, -1) != LUA_TFUNCTION) {
474  SCLogError("no init function in script");
475  goto error;
476  }
477 
478  if (lua_pcall(luastate, 0, 1, 0) != 0) {
479  SCLogError("couldn't run script 'init' function: %s", lua_tostring(luastate, -1));
480  goto error;
481  }
482 
483  /* process returns from script */
484  if (lua_gettop(luastate) == 0) {
485  SCLogError("init function in script should return table, nothing returned");
486  goto error;
487  }
488  if (lua_type(luastate, 1) != LUA_TTABLE) {
489  SCLogError("init function in script should return table, returned is not table");
490  goto error;
491  }
492 
493  lua_pushnil(luastate);
494  const char *k, *v;
495  while (lua_next(luastate, -2)) {
496  k = lua_tostring(luastate, -2);
497  if (k == NULL)
498  continue;
499 
500  v = lua_tostring(luastate, -1);
501  lua_pop(luastate, 1);
502  if (v == NULL)
503  continue;
504 
505  SCLogDebug("k='%s', v='%s'", k, v);
506 
507  if (strcmp(k, "streaming") == 0) {
508  options->streaming = 1;
509  if (strcmp(v, "http") == 0) {
510  options->alproto = ALPROTO_HTTP1;
511  } else if (strcmp(v, "tcp") == 0) {
512  options->tcp_data = 1;
513  } else {
514  SCLogError("unsupported streaming argument: %s", v);
515  goto error;
516  }
517  } else if (strcmp(k, "protocol") == 0 && strcmp(v, "http") == 0)
518  options->alproto = ALPROTO_HTTP1;
519  else if (strcmp(k,"protocol") == 0 && strcmp(v, "dns") == 0)
520  options->alproto = ALPROTO_DNS;
521  else if (strcmp(k,"protocol") == 0 && strcmp(v, "tls") == 0)
522  options->alproto = ALPROTO_TLS;
523  else if (strcmp(k,"protocol") == 0 && strcmp(v, "ssh") == 0)
524  options->alproto = ALPROTO_SSH;
525  else if (strcmp(k,"protocol") == 0 && strcmp(v, "smtp") == 0)
526  options->alproto = ALPROTO_SMTP;
527  else if (strcmp(k, "type") == 0 && strcmp(v, "packet") == 0)
528  options->packet = 1;
529  else if (strcmp(k, "filter") == 0 && strcmp(v, "alerts") == 0)
530  options->alerts = 1;
531  else if (strcmp(k, "type") == 0 && strcmp(v, "file") == 0)
532  options->file = 1;
533  else if (strcmp(k, "type") == 0 && strcmp(v, "streaming") == 0)
534  options->streaming = 1;
535  else if (strcmp(k, "type") == 0 && strcmp(v, "flow") == 0)
536  options->flow = 1;
537  else if (strcmp(k, "filter") == 0 && strcmp(v, "tcp") == 0)
538  options->tcp_data = 1;
539  else if (strcmp(k, "type") == 0 && strcmp(v, "stats") == 0)
540  options->stats = 1;
541  else {
542  SCLogError("unknown key and/or value: k='%s', v='%s'", k, v);
543  goto error;
544  }
545  }
546 
547  if (((options->alproto != ALPROTO_UNKNOWN)) + options->packet + options->file > 1) {
548  SCLogError("invalid combination of 'needs' in the script");
549  goto error;
550  }
551 
552  lua_getglobal(luastate, "setup");
553  if (lua_type(luastate, -1) != LUA_TFUNCTION) {
554  SCLogError("no setup function in script");
555  goto error;
556  }
557 
558  lua_getglobal(luastate, "log");
559  if (lua_type(luastate, -1) != LUA_TFUNCTION) {
560  SCLogError("no log function in script");
561  goto error;
562  }
563 
564  lua_getglobal(luastate, "deinit");
565  if (lua_type(luastate, -1) != LUA_TFUNCTION) {
566  SCLogError("no deinit function in script");
567  goto error;
568  }
569 
570  LuaReturnState(luastate);
571  return 0;
572 error:
573  if (luastate)
574  LuaReturnState(luastate);
575  return -1;
576 }
577 
578 /** \brief setup a luastate for use at runtime
579  *
580  * This loads the script, primes it and then runs the 'setup' function.
581  *
582  * \retval state Returns the set up luastate on success, NULL on error
583  */
584 static lua_State *LuaScriptSetup(const char *filename, LogLuaMasterCtx *ctx)
585 {
586  lua_State *luastate = LuaGetState();
587  if (luastate == NULL) {
588  SCLogError("luaL_newstate failed");
589  goto error;
590  }
591 
592  luaL_openlibs(luastate);
593  SCLuaRequirefBuiltIns(luastate);
594  LuaSetPaths(luastate, ctx);
595 
596  int status = luaL_loadfile(luastate, filename);
597  if (status) {
598  SCLogError("couldn't load file: %s", lua_tostring(luastate, -1));
599  goto error;
600  }
601 
602  /* prime the script */
603  if (lua_pcall(luastate, 0, 0, 0) != 0) {
604  SCLogError("couldn't prime file: %s", lua_tostring(luastate, -1));
605  goto error;
606  }
607 
608  lua_getglobal(luastate, "setup");
609 
610  if (lua_pcall(luastate, 0, 0, 0) != 0) {
611  SCLogError("couldn't run script 'setup' function: %s", lua_tostring(luastate, -1));
612  goto error;
613  }
614 
615  SCLogDebug("lua_State %p is set up", luastate);
616  return luastate;
617 error:
618  if (luastate)
619  LuaReturnState(luastate);
620  return NULL;
621 }
622 
623 static void LogLuaSubFree(OutputCtx *oc) {
624  if (oc->data)
625  SCFree(oc->data);
626  SCFree(oc);
627 }
628 
629 /** \brief initialize output for a script instance
630  *
631  * Runs script 'setup' function.
632  */
633 static OutputInitResult OutputLuaLogInitSub(SCConfNode *conf, OutputCtx *parent_ctx)
634 {
635  OutputInitResult result = { NULL, false };
636  if (conf == NULL)
637  return result;
638 
639  LogLuaCtx *lua_ctx = SCCalloc(1, sizeof(LogLuaCtx));
640  if (unlikely(lua_ctx == NULL))
641  return result;
642 
643  OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
644  if (unlikely(output_ctx == NULL)) {
645  SCFree(lua_ctx);
646  return result;
647  }
648 
649  SCMutexInit(&lua_ctx->m, NULL);
650 
651  BUG_ON(parent_ctx == NULL);
652  LogLuaMasterCtx *mc = parent_ctx->data;
653  BUG_ON(mc == NULL);
654 
655  const char *dir = mc->script_dir;
656  char path[PATH_MAX] = "";
657  int ret = snprintf(path, sizeof(path),"%s%s%s", dir, strlen(dir) ? "/" : "", conf->val);
658  if (ret < 0 || ret == sizeof(path)) {
659  SCLogError("failed to construct lua script path");
660  goto error;
661  }
662  SCLogDebug("script full path %s", path);
663 
664  SCMutexLock(&lua_ctx->m);
665  lua_ctx->luastate = LuaScriptSetup(path, mc);
666  SCMutexUnlock(&lua_ctx->m);
667  if (lua_ctx->luastate == NULL)
668  goto error;
669 
670  SCLogDebug("lua_ctx %p", lua_ctx);
671 
672  output_ctx->data = lua_ctx;
673  output_ctx->DeInit = LogLuaSubFree;
674 
675  result.ctx = output_ctx;
676  result.ok = true;
677  return result;
678 error:
679  SCMutexDestroy(&lua_ctx->m);
680  SCFree(lua_ctx);
681  SCFree(output_ctx);
682  return result;
683 }
684 
685 static void LogLuaMasterFree(OutputCtx *oc)
686 {
687  if (oc->data)
688  SCFree(oc->data);
689 
690  OutputModule *om, *tom;
691  TAILQ_FOREACH_SAFE(om, &oc->submodules, entries, tom) {
692  SCFree(om);
693  }
694  SCFree(oc);
695 }
696 
697 /** \internal
698  * \brief initialize output instance for lua module
699  *
700  * Parses nested script list, primes them to find out what they
701  * inspect, then fills the OutputCtx::submodules list with the
702  * proper Logger function for the data type the script needs.
703  */
704 static OutputInitResult OutputLuaLogInit(SCConfNode *conf)
705 {
706  OutputInitResult result = { NULL, false };
707  const char *dir = SCConfNodeLookupChildValue(conf, "scripts-dir");
708  if (dir == NULL)
709  dir = "";
710 
711  SCConfNode *scripts = SCConfNodeLookupChild(conf, "scripts");
712  if (scripts == NULL) {
713  /* No "outputs" section in the configuration. */
714  SCLogInfo("scripts not defined");
715  return result;
716  }
717 
718  /* global output ctx setup */
719  OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
720  if (unlikely(output_ctx == NULL)) {
721  return result;
722  }
723  output_ctx->DeInit = LogLuaMasterFree;
724  output_ctx->data = SCCalloc(1, sizeof(LogLuaMasterCtx));
725  if (unlikely(output_ctx->data == NULL)) {
726  SCFree(output_ctx);
727  return result;
728  }
729  LogLuaMasterCtx *master_config = output_ctx->data;
730  strlcpy(master_config->script_dir, dir, sizeof(master_config->script_dir));
731 
732  const char *lua_path = SCConfNodeLookupChildValue(conf, "path");
733  if (lua_path && strlen(lua_path) > 0) {
734  strlcpy(master_config->path, lua_path, sizeof(master_config->path));
735  }
736 
737  const char *lua_cpath = SCConfNodeLookupChildValue(conf, "cpath");
738  if (lua_cpath && strlen(lua_cpath) > 0) {
739  strlcpy(master_config->cpath, lua_cpath, sizeof(master_config->cpath));
740  }
741 
742  TAILQ_INIT(&output_ctx->submodules);
743 
744  /* check the enables scripts and set them up as submodules */
745  SCConfNode *script;
746  TAILQ_FOREACH(script, &scripts->head, next) {
747  SCLogInfo("enabling script %s", script->val);
748  LogLuaScriptOptions opts;
749  memset(&opts, 0x00, sizeof(opts));
750 
751  char path[PATH_MAX] = "";
752  snprintf(path, sizeof(path),"%s%s%s", dir, strlen(dir) ? "/" : "", script->val);
753  SCLogDebug("script full path %s", path);
754 
755  int r = LuaScriptInit(path, &opts, master_config);
756  if (r != 0) {
757  SCLogError("couldn't initialize script");
758  goto error;
759  }
760 
761  /* create an OutputModule for this script, based
762  * on it's needs. */
763  OutputModule *om = SCCalloc(1, sizeof(*om));
764  if (om == NULL) {
765  SCLogError("calloc() failed");
766  goto error;
767  }
768 
769  om->name = MODULE_NAME;
770  om->conf_name = script->val;
771  om->InitSubFunc = OutputLuaLogInitSub;
772  om->ThreadInit = LuaLogThreadInit;
773  om->ThreadDeinit = LuaLogThreadDeinit;
774 
775  if (opts.alproto == ALPROTO_HTTP1 && opts.streaming) {
776  om->StreamingLogFunc = LuaStreamingLogger;
778  om->alproto = ALPROTO_HTTP1;
781  } else if (opts.alproto == ALPROTO_HTTP1) {
782  om->TxLogFunc = LuaTxLogger;
783  om->alproto = ALPROTO_HTTP1;
784  om->ts_log_progress = -1;
785  om->tc_log_progress = -1;
787  } else if (opts.alproto == ALPROTO_TLS) {
788  om->TxLogFunc = LuaTxLogger;
789  om->alproto = ALPROTO_TLS;
793  } else if (opts.alproto == ALPROTO_DNS) {
794  om->TxLogFunc = LuaTxLogger;
795  om->alproto = ALPROTO_DNS;
796  om->ts_log_progress = -1;
797  om->tc_log_progress = -1;
800  } else if (opts.alproto == ALPROTO_SSH) {
801  om->TxLogFunc = LuaTxLogger;
802  om->alproto = ALPROTO_SSH;
805  } else if (opts.alproto == ALPROTO_SMTP) {
806  om->TxLogFunc = LuaTxLogger;
807  om->alproto = ALPROTO_SMTP;
808  om->ts_log_progress = -1;
809  om->tc_log_progress = -1;
811  } else if (opts.packet && opts.alerts) {
812  om->PacketLogFunc = LuaPacketLoggerAlerts;
813  om->PacketConditionFunc = LuaPacketConditionAlerts;
814  } else if (opts.packet && opts.alerts == 0) {
815  om->PacketLogFunc = LuaPacketLogger;
816  om->PacketConditionFunc = LuaPacketCondition;
817  } else if (opts.file) {
818  om->FileLogFunc = LuaFileLogger;
820  } else if (opts.streaming && opts.tcp_data) {
821  om->StreamingLogFunc = LuaStreamingLogger;
823  } else if (opts.flow) {
824  om->FlowLogFunc = LuaFlowLogger;
825  } else if (opts.stats) {
826  om->StatsLogFunc = LuaStatsLogger;
827  } else {
828  SCLogError("failed to setup thread module");
829  SCFree(om);
830  goto error;
831  }
832 
833  TAILQ_INSERT_TAIL(&output_ctx->submodules, om, entries);
834  }
835 
836  result.ctx = output_ctx;
837  result.ok = true;
838  return result;
839 
840 error:
841  if (output_ctx->DeInit)
842  output_ctx->DeInit(output_ctx);
843 
844  int failure_fatal = 0;
845  if (SCConfGetBool("engine.init-failure-fatal", &failure_fatal) != 1) {
846  SCLogDebug("ConfGetBool could not load the value.");
847  }
848  if (failure_fatal) {
849  FatalError("Error during setup of lua output. Details should be "
850  "described in previous error messages. Shutting down...");
851  }
852 
853  return result;
854 }
855 
856 /** \internal
857  * \brief Run the scripts 'deinit' function
858  */
859 static void OutputLuaLogDoDeinit(LogLuaCtx *lua_ctx)
860 {
861  lua_State *luastate = lua_ctx->luastate;
862 
863  lua_getglobal(luastate, "deinit");
864  if (lua_type(luastate, -1) != LUA_TFUNCTION) {
865  SCLogError("no deinit function in script");
866  return;
867  }
868  //LuaPrintStack(luastate);
869 
870  if (lua_pcall(luastate, 0, 0, 0) != 0) {
871  SCLogError("couldn't run script 'deinit' function: %s", lua_tostring(luastate, -1));
872  return;
873  }
874  LuaReturnState(luastate);
875 }
876 
877 /** \internal
878  * \brief Initialize the thread storage for lua
879  *
880  * Currently only stores a pointer to the global LogLuaCtx
881  */
882 static TmEcode LuaLogThreadInit(ThreadVars *t, const void *initdata, void **data)
883 {
884  LogLuaThreadCtx *td = SCCalloc(1, sizeof(*td));
885  if (unlikely(td == NULL))
886  return TM_ECODE_FAILED;
887 
888  if (initdata == NULL) {
889  SCLogDebug("Error getting context for LuaLog. \"initdata\" argument NULL");
890  SCFree(td);
891  return TM_ECODE_FAILED;
892  }
893 
894  LogLuaCtx *lua_ctx = ((OutputCtx *)initdata)->data;
895  SCLogDebug("lua_ctx %p", lua_ctx);
896  td->lua_ctx = lua_ctx;
897  *data = (void *)td;
898  return TM_ECODE_OK;
899 }
900 
901 /** \internal
902  * \brief Deinit the thread storage for lua
903  *
904  * Calls OutputLuaLogDoDeinit if no-one else already did.
905  */
906 static TmEcode LuaLogThreadDeinit(ThreadVars *t, void *data)
907 {
908  LogLuaThreadCtx *td = (LogLuaThreadCtx *)data;
909  if (td == NULL) {
910  return TM_ECODE_OK;
911  }
912 
913  SCMutexLock(&td->lua_ctx->m);
914  if (td->lua_ctx->deinit_once == 0) {
915  OutputLuaLogDoDeinit(td->lua_ctx);
916  td->lua_ctx->deinit_once = 1;
917  }
918  SCMutexUnlock(&td->lua_ctx->m);
919 
920  /* clear memory */
921  memset(td, 0, sizeof(*td));
922 
923  SCFree(td);
924  return TM_ECODE_OK;
925 }
926 
927 void LuaLogRegister(void) {
928  /* register as separate module */
929  OutputRegisterModule(MODULE_NAME, "lua", OutputLuaLogInit);
930 }
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:575
LuaStateSetThreadVars
void LuaStateSetThreadVars(lua_State *luastate, ThreadVars *tv)
Definition: util-lua.c:110
PacketAlert_::s
const struct Signature_ * s
Definition: decode.h:252
STREAMING_TCP_DATA
@ STREAMING_TCP_DATA
Definition: output-streaming.h:36
LogLuaScriptOptions_::file
int file
Definition: output-lua.c:406
app-layer-ssh.h
LogLuaScriptOptions_::alproto
AppProto alproto
Definition: output-lua.c:403
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:275
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:287
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:408
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:290
SSHTxLogCondition
bool SSHTxLogCondition(ThreadVars *tv, const Packet *p, void *state, void *tx, uint64_t tx_id)
Definition: app-layer-ssh.c:74
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:620
OutputCtx_::data
void * data
Definition: tm-modules.h:91
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:81
PacketAlert_::tx_id
uint64_t tx_id
Definition: decode.h:253
OutputCtx_
Definition: tm-modules.h:88
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:402
OutputInitResult_::ctx
OutputCtx * ctx
Definition: output.h:47
OutputModule_::ThreadDeinit
ThreadDeinitFunc ThreadDeinit
Definition: output.h:66
SCAppLayerParserRegisterLogger
void SCAppLayerParserRegisterLogger(uint8_t ipproto, AppProto alproto)
Definition: app-layer-parser.c:491
Packet_::ts
SCTime_t ts
Definition: decode.h:555
LogLuaScriptOptions_::stats
int stats
Definition: output-lua.c:411
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:548
OutputRegisterModule
void OutputRegisterModule(const char *, const char *, OutputInitFunc)
SCEnter
#define SCEnter(...)
Definition: util-debug.h:277
LogLuaScriptOptions_::packet
int packet
Definition: output-lua.c:404
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:407
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:501
TmEcode
TmEcode
Definition: tm-threads-common.h:80
LogLuaScriptOptions_::http_body
int http_body
Definition: output-lua.c:409
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:561
LogLuaScriptOptions_::flow
int flow
Definition: output-lua.c:410
SCLuaRequirefBuiltIns
void SCLuaRequirefBuiltIns(lua_State *L)
Register Suricata built-in modules for loading in a non-sandboxed environment.
Definition: util-lua-builtins.c:85
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:1109
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:251
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:546
OutputModule_::TxLogCondition
TxLoggerCondition TxLogCondition
Definition: output.h:72
flags
uint8_t flags
Definition: decode-gre.h:0
suricata-common.h
OUTPUT_STREAMING_FLAG_OPEN
#define OUTPUT_STREAMING_FLAG_OPEN
Definition: output-streaming.h:29
OutputCtx_::DeInit
void(* DeInit)(struct OutputCtx_ *)
Definition: tm-modules.h:94
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:510
LuaLogRegister
void LuaLogRegister(void)
Definition: output-lua.c:927
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
OUTPUT_STREAMING_FLAG_TOSERVER
#define OUTPUT_STREAMING_FLAG_TOSERVER
Definition: output-streaming.h:31
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:267
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:272
ALPROTO_UNKNOWN
@ ALPROTO_UNKNOWN
Definition: app-layer-protos.h:29
output-lua.h
LuaPushTableKeyValueBoolean
void LuaPushTableKeyValueBoolean(lua_State *luastate, const char *key, bool value)
Definition: util-lua-common.c:66
OUTPUT_STREAMING_FLAG_CLOSE
#define OUTPUT_STREAMING_FLAG_CLOSE
Definition: output-streaming.h:30
OUTPUT_STREAMING_FLAG_TOCLIENT
#define OUTPUT_STREAMING_FLAG_TOCLIENT
Definition: output-streaming.h:32
LuaPushTableKeyValueLString
void LuaPushTableKeyValueLString(lua_State *luastate, const char *key, const char *value, size_t len)
Push a key plus string value with length to the stack.
Definition: util-lua-common.c:86
PacketAlert_
Definition: decode.h:248
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:405
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:281
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
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