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