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