suricata
util-lua-common.c
Go to the documentation of this file.
1 /* Copyright (C) 2014-2021 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  * Common function for Lua Output
24  */
25 
26 #include "suricata-common.h"
27 #include "detect.h"
28 #include "pkt-var.h"
29 #include "conf.h"
30 
31 #include "threads.h"
32 #include "threadvars.h"
33 #include "tm-threads.h"
34 
35 #include "util-print.h"
36 #include "util-unittest.h"
37 
38 #include "util-debug.h"
39 
40 #include "output.h"
41 #include "app-layer-htp.h"
42 #include "app-layer.h"
43 #include "app-layer-parser.h"
44 #include "util-privs.h"
45 #include "util-buffer.h"
46 #include "util-proto-name.h"
47 #include "util-logopenfile.h"
48 #include "util-time.h"
49 #include "util-conf.h"
50 
51 #include "lua.h"
52 #include "lualib.h"
53 #include "lauxlib.h"
54 
55 #include "util-lua.h"
56 #include "util-lua-common.h"
57 #include "action-globals.h"
58 
59 int LuaCallbackError(lua_State *luastate, const char *msg)
60 {
61  lua_pushnil(luastate);
62  lua_pushstring(luastate, msg);
63  return 2;
64 }
65 
66 const char *LuaGetStringArgument(lua_State *luastate, int idx)
67 {
68  /* get argument */
69  if (!lua_isstring(luastate, idx))
70  return NULL;
71  const char *str = lua_tostring(luastate, idx);
72  if (str == NULL)
73  return NULL;
74  if (strlen(str) == 0)
75  return NULL;
76  return str;
77 }
78 
79 void LuaPushTableKeyValueInt(lua_State *luastate, const char *key, int value)
80 {
81  lua_pushstring(luastate, key);
82  lua_pushnumber(luastate, value);
83  lua_settable(luastate, -3);
84 }
85 
86 /** \brief Push a key plus string value to the stack
87  *
88  * If value is NULL, string "(null")" will be put on the stack.
89  */
90 void LuaPushTableKeyValueString(lua_State *luastate, const char *key, const char *value)
91 {
92  lua_pushstring(luastate, key);
93  lua_pushstring(luastate, value ? value : "(null)");
94  lua_settable(luastate, -3);
95 }
96 
97 void LuaPushTableKeyValueArray(lua_State *luastate, const char *key, const uint8_t *value, size_t len)
98 {
99  lua_pushstring(luastate, key);
100  LuaPushStringBuffer(luastate, value, len);
101  lua_settable(luastate, -3);
102 }
103 
104 /** \internal
105  * \brief fill lua stack with payload
106  * \param luastate the lua state
107  * \param p packet
108  * \retval cnt number of data items placed on the stack
109  *
110  * Places: payload (string), open (bool), close (bool), toserver (bool), toclient (bool)
111  */
112 static int LuaCallbackStreamingBufferPushToStack(lua_State *luastate, const LuaStreamingBuffer *b)
113 {
114  //PrintRawDataFp(stdout, (uint8_t *)b->data, b->data_len);
115  lua_pushlstring (luastate, (const char *)b->data, b->data_len);
116  lua_pushboolean (luastate, (b->flags & OUTPUT_STREAMING_FLAG_OPEN));
117  lua_pushboolean (luastate, (b->flags & OUTPUT_STREAMING_FLAG_CLOSE));
118  lua_pushboolean (luastate, (b->flags & OUTPUT_STREAMING_FLAG_TOSERVER));
119  lua_pushboolean (luastate, (b->flags & OUTPUT_STREAMING_FLAG_TOCLIENT));
120  return 5;
121 }
122 
123 /** \internal
124  * \brief Wrapper for getting payload into a lua script
125  * \retval cnt number of items placed on the stack
126  */
127 static int LuaCallbackStreamingBuffer(lua_State *luastate)
128 {
129  const LuaStreamingBuffer *b = LuaStateGetStreamingBuffer(luastate);
130  if (b == NULL)
131  return LuaCallbackError(luastate, "internal error: no buffer");
132 
133  return LuaCallbackStreamingBufferPushToStack(luastate, b);
134 }
135 
136 static int LuaCallbackLogPath(lua_State *luastate)
137 {
138  const char *ld = SCConfigGetLogDirectory();
139  if (ld == NULL)
140  return LuaCallbackError(luastate, "internal error: no log dir");
141 
142  return LuaPushStringBuffer(luastate, (const uint8_t *)ld, strlen(ld));
143 }
144 
145 static int LuaCallbackLogDebug(lua_State *luastate)
146 {
147  const char *msg = LuaGetStringArgument(luastate, 1);
148  if (msg == NULL)
149  return LuaCallbackError(luastate, "1st argument missing, empty or wrong type");
150  SCLogDebug("%s", msg);
151  return 0;
152 }
153 
154 static int LuaCallbackLogInfo(lua_State *luastate)
155 {
156  const char *msg = LuaGetStringArgument(luastate, 1);
157  if (msg == NULL)
158  return LuaCallbackError(luastate, "1st argument missing, empty or wrong type");
159 
160  lua_Debug ar;
161  lua_getstack(luastate, 1, &ar);
162  lua_getinfo(luastate, "nSl", &ar);
163  const char *funcname = ar.name ? ar.name : ar.what;
164  SCLogInfoRaw(ar.short_src, funcname, ar.currentline, "%s", msg);
165  return 0;
166 }
167 
168 static int LuaCallbackLogNotice(lua_State *luastate)
169 {
170  const char *msg = LuaGetStringArgument(luastate, 1);
171  if (msg == NULL)
172  return LuaCallbackError(luastate, "1st argument missing, empty or wrong type");
173 
174  lua_Debug ar;
175  lua_getstack(luastate, 1, &ar);
176  lua_getinfo(luastate, "nSl", &ar);
177  const char *funcname = ar.name ? ar.name : ar.what;
178  SCLogNoticeRaw(ar.short_src, funcname, ar.currentline, "%s", msg);
179  return 0;
180 }
181 
182 static int LuaCallbackLogWarning(lua_State *luastate)
183 {
184  const char *msg = LuaGetStringArgument(luastate, 1);
185  if (msg == NULL)
186  return LuaCallbackError(luastate, "1st argument missing, empty or wrong type");
187 
188  lua_Debug ar;
189  lua_getstack(luastate, 1, &ar);
190  lua_getinfo(luastate, "nSl", &ar);
191  const char *funcname = ar.name ? ar.name : ar.what;
192  SCLogWarningRaw(ar.short_src, funcname, ar.currentline, "%s", msg);
193  return 0;
194 }
195 
196 static int LuaCallbackLogError(lua_State *luastate)
197 {
198  const char *msg = LuaGetStringArgument(luastate, 1);
199  if (msg == NULL)
200  return LuaCallbackError(luastate, "1st argument missing, empty or wrong type");
201  lua_Debug ar;
202  lua_getstack(luastate, 1, &ar);
203  lua_getinfo(luastate, "nSl", &ar);
204  const char *funcname = ar.name ? ar.name : ar.what;
205  SCLogErrorRaw(ar.short_src, funcname, ar.currentline, "%s", msg);
206  return 0;
207 }
208 
209 /** \internal
210  * \brief fill lua stack with file info
211  * \param luastate the lua state
212  * \param pa pointer to packet alert struct
213  * \retval cnt number of data items placed on the stack
214  *
215  * Places: fileid (number), txid (number), name (string),
216  * size (number), magic (string), md5 in hex (string),
217  * sha1 (string), sha256 (string)
218  */
219 static int LuaCallbackFileInfoPushToStackFromFile(lua_State *luastate, const File *file)
220 {
221  char *md5ptr = NULL;
222  char *sha1ptr = NULL;
223  char *sha256ptr = NULL;
224 
225  char md5[33] = "";
226  md5ptr = md5;
227  if (file->flags & FILE_MD5) {
228  size_t x;
229  for (x = 0; x < sizeof(file->md5); x++) {
230  char one[3] = "";
231  snprintf(one, sizeof(one), "%02x", file->md5[x]);
232  strlcat(md5, one, sizeof(md5));
233  }
234  }
235  char sha1[41] = "";
236  sha1ptr = sha1;
237  if (file->flags & FILE_SHA1) {
238  size_t x;
239  for (x = 0; x < sizeof(file->sha1); x++) {
240  char one[3] = "";
241  snprintf(one, sizeof(one), "%02x", file->sha1[x]);
242  strlcat(sha1, one, sizeof(sha1));
243  }
244  }
245  char sha256[65] = "";
246  sha256ptr = sha256;
247  if (file->flags & FILE_SHA256) {
248  size_t x;
249  for (x = 0; x < sizeof(file->sha256); x++) {
250  char one[3] = "";
251  snprintf(one, sizeof(one), "%02x", file->sha256[x]);
252  strlcat(sha256, one, sizeof(sha256));
253  }
254  }
255 
256  lua_Integer tx_id = LuaStateGetTxId(luastate);
257  lua_pushinteger(luastate, file->file_store_id);
258  lua_pushinteger(luastate, tx_id);
259  lua_pushlstring(luastate, (char *)file->name, file->name_len);
260  lua_pushinteger(luastate, FileTrackedSize(file));
261  lua_pushstring (luastate,
262 #ifdef HAVE_MAGIC
263  file->magic
264 #else
265  "nomagic"
266 #endif
267  );
268  lua_pushstring(luastate, md5ptr);
269  lua_pushstring(luastate, sha1ptr);
270  lua_pushstring(luastate, sha256ptr);
271  return 8;
272 }
273 
274 /** \internal
275  * \brief Wrapper for getting tuple info into a lua script
276  * \retval cnt number of items placed on the stack
277  */
278 static int LuaCallbackFileInfo(lua_State *luastate)
279 {
280  const File *file = LuaStateGetFile(luastate);
281  if (file == NULL)
282  return LuaCallbackError(luastate, "internal error: no file");
283 
284  return LuaCallbackFileInfoPushToStackFromFile(luastate, file);
285 }
286 
287 /** \internal
288  * \brief fill lua stack with file info
289  * \param luastate the lua state
290  * \param pa pointer to packet alert struct
291  * \retval cnt number of data items placed on the stack
292  *
293  * Places: state (string), stored (bool)
294  */
295 static int LuaCallbackFileStatePushToStackFromFile(lua_State *luastate, const File *file)
296 {
297  const char *state = "UNKNOWN";
298  switch (file->state) {
299  case FILE_STATE_CLOSED:
300  state = "CLOSED";
301  break;
303  state = "TRUNCATED";
304  break;
305  case FILE_STATE_ERROR:
306  state = "ERROR";
307  break;
308  case FILE_STATE_OPENED:
309  state = "OPENED";
310  break;
311  case FILE_STATE_NONE:
312  state = "NONE";
313  break;
314  case FILE_STATE_MAX:
315  break;
316  }
317 
318  lua_pushstring (luastate, state);
319  lua_pushboolean (luastate, file->flags & FILE_STORED);
320  return 2;
321 }
322 
323 /** \internal
324  * \brief Wrapper for getting tuple info into a lua script
325  * \retval cnt number of items placed on the stack
326  */
327 static int LuaCallbackFileState(lua_State *luastate)
328 {
329  const File *file = LuaStateGetFile(luastate);
330  if (file == NULL)
331  return LuaCallbackError(luastate, "internal error: no file");
332 
333  return LuaCallbackFileStatePushToStackFromFile(luastate, file);
334 }
335 
336 /** \internal
337  * \brief fill lua stack with thread info
338  * \param luastate the lua state
339  * \param pa pointer to packet alert struct
340  * \retval cnt number of data items placed on the stack
341  *
342  * Places: thread id (number), thread name (string, thread group name (string)
343  */
344 static int LuaCallbackThreadInfoPushToStackFromThreadVars(lua_State *luastate, const ThreadVars *tv)
345 {
346  unsigned long tid = SCGetThreadIdLong();
347  lua_pushinteger (luastate, (lua_Integer)tid);
348  lua_pushstring (luastate, tv->name);
349  lua_pushstring (luastate, tv->thread_group_name);
350  return 3;
351 }
352 
353 /** \internal
354  * \brief Wrapper for getting tuple info into a lua script
355  * \retval cnt number of items placed on the stack
356  */
357 static int LuaCallbackThreadInfo(lua_State *luastate)
358 {
359  const ThreadVars *tv = LuaStateGetThreadVars(luastate);
360  if (tv == NULL)
361  return LuaCallbackError(luastate, "internal error: no tv");
362 
363  return LuaCallbackThreadInfoPushToStackFromThreadVars(luastate, tv);
364 }
365 
367 {
368  /* registration of the callbacks */
369  lua_pushcfunction(luastate, LuaCallbackStreamingBuffer);
370  lua_setglobal(luastate, "SCStreamingBuffer");
371 
372  lua_pushcfunction(luastate, LuaCallbackLogPath);
373  lua_setglobal(luastate, "SCLogPath");
374 
375  lua_pushcfunction(luastate, LuaCallbackLogDebug);
376  lua_setglobal(luastate, "SCLogDebug");
377  lua_pushcfunction(luastate, LuaCallbackLogInfo);
378  lua_setglobal(luastate, "SCLogInfo");
379  lua_pushcfunction(luastate, LuaCallbackLogNotice);
380  lua_setglobal(luastate, "SCLogNotice");
381  lua_pushcfunction(luastate, LuaCallbackLogWarning);
382  lua_setglobal(luastate, "SCLogWarning");
383  lua_pushcfunction(luastate, LuaCallbackLogError);
384  lua_setglobal(luastate, "SCLogError");
385 
386  lua_pushcfunction(luastate, LuaCallbackFileInfo);
387  lua_setglobal(luastate, "SCFileInfo");
388  lua_pushcfunction(luastate, LuaCallbackFileState);
389  lua_setglobal(luastate, "SCFileState");
390 
391  lua_pushcfunction(luastate, LuaCallbackThreadInfo);
392  lua_setglobal(luastate, "SCThreadInfo");
393  return 0;
394 }
395 
396 int LuaStateNeedProto(lua_State *luastate, AppProto alproto)
397 {
398  AppProto flow_alproto = 0;
399  Flow *flow = LuaStateGetFlow(luastate);
400  if (flow == NULL)
401  return LuaCallbackError(luastate, "internal error: no flow");
402 
403  flow_alproto = flow->alproto;
404 
405  return (alproto == flow_alproto);
406 }
tm-threads.h
len
uint8_t len
Definition: app-layer-dnp3.h:2
LuaStateGetStreamingBuffer
LuaStreamingBuffer * LuaStateGetStreamingBuffer(lua_State *luastate)
Definition: util-lua.c:254
ThreadVars_::name
char name[16]
Definition: threadvars.h:65
util-lua-common.h
LuaPushTableKeyValueInt
void LuaPushTableKeyValueInt(lua_State *luastate, const char *key, int value)
Definition: util-lua-common.c:79
LuaStreamingBuffer_
Definition: util-lua.h:34
SCLogWarningRaw
#define SCLogWarningRaw(file, func, line,...)
Definition: util-debug.h:251
FILE_SHA256
#define FILE_SHA256
Definition: util-file.h:52
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
util-lua.h
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:85
LuaCallbackError
int LuaCallbackError(lua_State *luastate, const char *msg)
Definition: util-lua-common.c:59
action-globals.h
threads.h
FILE_STATE_OPENED
@ FILE_STATE_OPENED
Definition: util-file.h:70
Flow_
Flow data structure.
Definition: flow.h:356
File_::state
FileState state
Definition: util-file.h:82
File_::file_store_id
uint32_t file_store_id
Definition: util-file.h:85
util-privs.h
FILE_STATE_TRUNCATED
@ FILE_STATE_TRUNCATED
Definition: util-file.h:73
LuaGetStringArgument
const char * LuaGetStringArgument(lua_State *luastate, int idx)
Definition: util-lua-common.c:66
File_::sha1
uint8_t sha1[SC_SHA1_LEN]
Definition: util-file.h:96
util-unittest.h
lua_State
struct lua_State lua_State
Definition: suricata-common.h:523
File_::name_len
uint16_t name_len
Definition: util-file.h:81
LuaStateGetThreadVars
ThreadVars * LuaStateGetThreadVars(lua_State *luastate)
get tv pointer from the lua state
Definition: util-lua.c:102
app-layer-htp.h
File_::md5
uint8_t md5[SC_MD5_LEN]
Definition: util-file.h:94
util-debug.h
strlcat
size_t strlcat(char *, const char *src, size_t siz)
Definition: util-strlcatu.c:45
util-print.h
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
pkt-var.h
FileTrackedSize
uint64_t FileTrackedSize(const File *file)
get the size of the file
Definition: util-file.c:343
util-time.h
app-layer-parser.h
SCConfigGetLogDirectory
const char * SCConfigGetLogDirectory(void)
Definition: util-conf.c:38
conf.h
ThreadVars_::thread_group_name
char * thread_group_name
Definition: threadvars.h:67
FILE_STATE_MAX
@ FILE_STATE_MAX
Definition: util-file.h:76
File_::name
uint8_t * name
Definition: util-file.h:88
util-proto-name.h
SCGetThreadIdLong
#define SCGetThreadIdLong(...)
Definition: threads.h:255
File_::flags
uint16_t flags
Definition: util-file.h:80
FILE_STATE_CLOSED
@ FILE_STATE_CLOSED
Definition: util-file.h:71
File_
Definition: util-file.h:79
LuaPushTableKeyValueArray
void LuaPushTableKeyValueArray(lua_State *luastate, const char *key, const uint8_t *value, size_t len)
Definition: util-lua-common.c:97
util-conf.h
LuaStateGetTxId
uint64_t LuaStateGetTxId(lua_State *luastate)
get tx id from the lua state
Definition: util-lua.c:143
suricata-common.h
OUTPUT_STREAMING_FLAG_OPEN
#define OUTPUT_STREAMING_FLAG_OPEN
Definition: output-streaming.h:29
LuaStreamingBuffer_::data_len
uint32_t data_len
Definition: util-lua.h:36
LuaStreamingBuffer_::data
const uint8_t * data
Definition: util-lua.h:35
FILE_STORED
#define FILE_STORED
Definition: util-file.h:56
FILE_MD5
#define FILE_MD5
Definition: util-file.h:48
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
File_::sha256
uint8_t sha256[SC_SHA256_LEN]
Definition: util-file.h:98
threadvars.h
OUTPUT_STREAMING_FLAG_TOSERVER
#define OUTPUT_STREAMING_FLAG_TOSERVER
Definition: output-streaming.h:31
str
#define str(s)
Definition: suricata-common.h:308
SCLogNoticeRaw
#define SCLogNoticeRaw(file, func, line,...)
Definition: util-debug.h:239
util-logopenfile.h
LuaStateGetFile
File * LuaStateGetFile(lua_State *luastate)
get file pointer from the lua state
Definition: util-lua.c:223
util-buffer.h
LuaStateGetFlow
Flow * LuaStateGetFlow(lua_State *luastate)
get flow pointer from lua state
Definition: util-lua.c:161
OUTPUT_STREAMING_FLAG_CLOSE
#define OUTPUT_STREAMING_FLAG_CLOSE
Definition: output-streaming.h:30
FILE_SHA1
#define FILE_SHA1
Definition: util-file.h:50
OUTPUT_STREAMING_FLAG_TOCLIENT
#define OUTPUT_STREAMING_FLAG_TOCLIENT
Definition: output-streaming.h:32
SCLogInfoRaw
#define SCLogInfoRaw(file, func, line,...)
Definition: util-debug.h:225
LuaPushTableKeyValueString
void LuaPushTableKeyValueString(lua_State *luastate, const char *key, const char *value)
Push a key plus string value to the stack.
Definition: util-lua-common.c:90
SCLogErrorRaw
#define SCLogErrorRaw(file, func, line,...)
Definition: util-debug.h:263
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:450
FILE_STATE_ERROR
@ FILE_STATE_ERROR
Definition: util-file.h:75
LuaRegisterFunctions
int LuaRegisterFunctions(lua_State *luastate)
Definition: util-lua-common.c:366
LuaStateNeedProto
int LuaStateNeedProto(lua_State *luastate, AppProto alproto)
Definition: util-lua-common.c:396
LuaStreamingBuffer_::flags
uint8_t flags
Definition: util-lua.h:37
output.h
FILE_STATE_NONE
@ FILE_STATE_NONE
Definition: util-file.h:69
LuaPushStringBuffer
int LuaPushStringBuffer(lua_State *luastate, const uint8_t *input, size_t input_len)
Definition: util-lua.c:319
app-layer.h