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