suricata
util-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  * Common function for Lua
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 #include "util-luajit.h"
38 
39 #include "util-debug.h"
40 
41 #include "output.h"
42 #include "app-layer-htp.h"
43 #include "app-layer.h"
44 #include "app-layer-parser.h"
45 #include "util-privs.h"
46 #include "util-buffer.h"
47 #include "util-proto-name.h"
48 #include "util-logopenfile.h"
49 #include "util-time.h"
50 
51 #ifdef HAVE_LUA
52 
53 #include <lua.h>
54 #include <lualib.h>
55 #include <lauxlib.h>
56 
57 #include "util-lua.h"
58 
59 lua_State *LuaGetState(void)
60 {
61  lua_State *s = NULL;
62 #ifdef HAVE_LUAJIT
63  s = LuajitGetState();
64 #else
65  s = luaL_newstate();
66 #endif
67  return s;
68 }
69 
70 void LuaReturnState(lua_State *s)
71 {
72  if (s != NULL) {
73  /* clear the stack */
74  while (lua_gettop(s) > 0) {
75  lua_pop(s, 1);
76  }
77 #ifdef HAVE_LUAJIT
78  LuajitReturnState(s);
79 #else
80  lua_close(s);
81 #endif
82  }
83 }
84 
85 /* key for tv (threadvars) pointer */
86 const char lua_ext_key_tv[] = "suricata:lua:tv:ptr";
87 /* key for tx pointer */
88 const char lua_ext_key_tx[] = "suricata:lua:tx:ptr";
89 /* key for tx id */
90 const char lua_ext_key_tx_id[] = "suricata:lua:tx_id";
91 /* key for p (packet) pointer */
92 const char lua_ext_key_p[] = "suricata:lua:pkt:ptr";
93 /* key for f (flow) pointer */
94 const char lua_ext_key_flow[] = "suricata:lua:flow:ptr";
95 /* key for flow lock hint bool */
96 const char lua_ext_key_flow_lock_hint[] = "suricata:lua:flow:lock_hint";
97 /* key for direction */
98 const char lua_ext_key_direction[] = "suricata:lua:direction";
99 
100 /* key for pa (packet alert) pointer */
101 const char lua_ext_key_pa[] = "suricata:lua:pkt:alert:ptr";
102 /* key for s (signature) pointer */
103 const char lua_ext_key_s[] = "suricata:lua:signature:ptr";
104 /* key for file pointer */
105 const char lua_ext_key_file[] = "suricata:lua:file:ptr";
106 /* key for DetectEngineThreadCtx pointer */
107 const char lua_ext_key_det_ctx[] = "suricata:lua:det_ctx:ptr";
108 /* key for streaming buffer pointer */
109 const char lua_ext_key_streaming_buffer[] = "suricata:lua:streaming_buffer:ptr";
110 
111 /** \brief get tv pointer from the lua state */
112 ThreadVars *LuaStateGetThreadVars(lua_State *luastate)
113 {
114  lua_pushlightuserdata(luastate, (void *)&lua_ext_key_tv);
115  lua_gettable(luastate, LUA_REGISTRYINDEX);
116  void *tv = lua_touserdata(luastate, -1);
117  return (ThreadVars *)tv;
118 }
119 
120 void LuaStateSetThreadVars(lua_State *luastate, ThreadVars *tv)
121 {
122  lua_pushlightuserdata(luastate, (void *)&lua_ext_key_tv);
123  lua_pushlightuserdata(luastate, (void *)tv);
124  lua_settable(luastate, LUA_REGISTRYINDEX);
125 }
126 
127 /** \brief get packet pointer from the lua state */
128 Packet *LuaStateGetPacket(lua_State *luastate)
129 {
130  lua_pushlightuserdata(luastate, (void *)&lua_ext_key_p);
131  lua_gettable(luastate, LUA_REGISTRYINDEX);
132  void *p = lua_touserdata(luastate, -1);
133  return (Packet *)p;
134 }
135 
136 void LuaStateSetPacket(lua_State *luastate, Packet *p)
137 {
138  lua_pushlightuserdata(luastate, (void *)&lua_ext_key_p);
139  lua_pushlightuserdata(luastate, (void *)p);
140  lua_settable(luastate, LUA_REGISTRYINDEX);
141 }
142 
143 /** \brief get tx pointer from the lua state */
144 void *LuaStateGetTX(lua_State *luastate)
145 {
146  lua_pushlightuserdata(luastate, (void *)&lua_ext_key_tx);
147  lua_gettable(luastate, LUA_REGISTRYINDEX);
148  void *tx = lua_touserdata(luastate, -1);
149  return tx;
150 }
151 
152 /** \brief get tx id from the lua state */
153 uint64_t LuaStateGetTxId(lua_State *luastate)
154 {
155  lua_pushlightuserdata(luastate, (void *)&lua_ext_key_tx_id);
156  lua_gettable(luastate, LUA_REGISTRYINDEX);
157  uint64_t tx_id = lua_tointeger(luastate, -1);
158  return tx_id;
159 }
160 void LuaStateSetTX(lua_State *luastate, void *txptr, const uint64_t tx_id)
161 {
162  lua_pushlightuserdata(luastate, (void *)&lua_ext_key_tx);
163  lua_pushlightuserdata(luastate, (void *)txptr);
164  lua_settable(luastate, LUA_REGISTRYINDEX);
165 
166  lua_pushlightuserdata(luastate, (void *)&lua_ext_key_tx_id);
167  lua_pushinteger(luastate, tx_id);
168  lua_settable(luastate, LUA_REGISTRYINDEX);
169 }
170 
171 Flow *LuaStateGetFlow(lua_State *luastate)
172 {
173  Flow *f = NULL;
174 
175  lua_pushlightuserdata(luastate, (void *)&lua_ext_key_flow);
176  lua_gettable(luastate, LUA_REGISTRYINDEX);
177  f = lua_touserdata(luastate, -1);
178 
179  /* need flow lock hint */
180  lua_pushlightuserdata(luastate, (void *)&lua_ext_key_flow_lock_hint);
181  lua_gettable(luastate, LUA_REGISTRYINDEX);
182 
183  return f;
184 }
185 
186 void LuaStateSetFlow(lua_State *luastate, Flow *f)
187 {
188  /* flow */
189  lua_pushlightuserdata(luastate, (void *)&lua_ext_key_flow);
190  lua_pushlightuserdata(luastate, (void *)f);
191  lua_settable(luastate, LUA_REGISTRYINDEX);
192 
193  /* flow lock status hint */
194  lua_pushlightuserdata(luastate, (void *)&lua_ext_key_flow_lock_hint);
195  /* locking is not required, set to 0 for backwards compatibility */
196  lua_pushboolean(luastate, 0);
197  lua_settable(luastate, LUA_REGISTRYINDEX);
198 }
199 
200 /** \brief get packet alert pointer from the lua state */
201 PacketAlert *LuaStateGetPacketAlert(lua_State *luastate)
202 {
203  lua_pushlightuserdata(luastate, (void *)&lua_ext_key_pa);
204  lua_gettable(luastate, LUA_REGISTRYINDEX);
205  void *pa = lua_touserdata(luastate, -1);
206  return (PacketAlert *)pa;
207 }
208 
209 void LuaStateSetPacketAlert(lua_State *luastate, PacketAlert *pa)
210 {
211  lua_pushlightuserdata(luastate, (void *)&lua_ext_key_pa);
212  lua_pushlightuserdata(luastate, (void *)pa);
213  lua_settable(luastate, LUA_REGISTRYINDEX);
214 }
215 
216 /** \brief get signature pointer from the lua state */
217 Signature *LuaStateGetSignature(lua_State *luastate)
218 {
219  lua_pushlightuserdata(luastate, (void *)&lua_ext_key_s);
220  lua_gettable(luastate, LUA_REGISTRYINDEX);
221  void *s = lua_touserdata(luastate, -1);
222  return (Signature *)s;
223 }
224 
225 void LuaStateSetSignature(lua_State *luastate, const Signature *s)
226 {
227  lua_pushlightuserdata(luastate, (void *)&lua_ext_key_s);
228  lua_pushlightuserdata(luastate, (void *)s);
229  lua_settable(luastate, LUA_REGISTRYINDEX);
230 }
231 
232 /** \brief get file pointer from the lua state */
233 File *LuaStateGetFile(lua_State *luastate)
234 {
235  lua_pushlightuserdata(luastate, (void *)&lua_ext_key_file);
236  lua_gettable(luastate, LUA_REGISTRYINDEX);
237  void *file = lua_touserdata(luastate, -1);
238  return (File *)file;
239 }
240 
241 void LuaStateSetFile(lua_State *luastate, File *file)
242 {
243  lua_pushlightuserdata(luastate, (void *)&lua_ext_key_file);
244  lua_pushlightuserdata(luastate, (void *)file);
245  lua_settable(luastate, LUA_REGISTRYINDEX);
246 }
247 
248 /** \brief get DetectEngineThreadCtx pointer from the lua state */
249 DetectEngineThreadCtx *LuaStateGetDetCtx(lua_State *luastate)
250 {
251  lua_pushlightuserdata(luastate, (void *)&lua_ext_key_det_ctx);
252  lua_gettable(luastate, LUA_REGISTRYINDEX);
253  void *det_ctx = lua_touserdata(luastate, -1);
254  return (DetectEngineThreadCtx *)det_ctx;
255 }
256 
257 void LuaStateSetDetCtx(lua_State *luastate, DetectEngineThreadCtx *det_ctx)
258 {
259  lua_pushlightuserdata(luastate, (void *)&lua_ext_key_det_ctx);
260  lua_pushlightuserdata(luastate, (void *)det_ctx);
261  lua_settable(luastate, LUA_REGISTRYINDEX);
262 }
263 
264 LuaStreamingBuffer *LuaStateGetStreamingBuffer(lua_State *luastate)
265 {
266  lua_pushlightuserdata(luastate, (void *)&lua_ext_key_streaming_buffer);
267  lua_gettable(luastate, LUA_REGISTRYINDEX);
268  void *b = lua_touserdata(luastate, -1);
269  return (LuaStreamingBuffer *)b;
270 }
271 
272 void LuaStateSetStreamingBuffer(lua_State *luastate, LuaStreamingBuffer *b)
273 {
274  lua_pushlightuserdata(luastate, (void *)&lua_ext_key_streaming_buffer);
275  lua_pushlightuserdata(luastate, (void *)b);
276  lua_settable(luastate, LUA_REGISTRYINDEX);
277 }
278 
279 /** \brief get packet pointer from the lua state */
280 int LuaStateGetDirection(lua_State *luastate)
281 {
282  lua_pushlightuserdata(luastate, (void *)&lua_ext_key_direction);
283  lua_gettable(luastate, LUA_REGISTRYINDEX);
284  int dir = lua_toboolean(luastate, -1);
285  return dir;
286 }
287 
288 void LuaStateSetDirection(lua_State *luastate, int direction)
289 {
290  lua_pushlightuserdata(luastate, (void *)&lua_ext_key_direction);
291  lua_pushboolean(luastate, direction);
292  lua_settable(luastate, LUA_REGISTRYINDEX);
293 }
294 
295 /** \brief dump stack from lua state to screen */
296 void LuaPrintStack(lua_State *state) {
297  int size = lua_gettop(state);
298  int i;
299 
300  for (i = 1; i <= size; i++) {
301  int type = lua_type(state, i);
302  printf("Stack size=%d, level=%d, type=%d, ", size, i, type);
303 
304  switch (type) {
305  case LUA_TFUNCTION:
306  printf("function %s", lua_tostring(state, i) ? "true" : "false");
307  break;
308  case LUA_TBOOLEAN:
309  printf("bool %s", lua_toboolean(state, i) ? "true" : "false");
310  break;
311  case LUA_TNUMBER:
312  printf("number %g", lua_tonumber(state, i));
313  break;
314  case LUA_TSTRING:
315  printf("string `%s'", lua_tostring(state, i));
316  break;
317  case LUA_TTABLE:
318  printf("table `%s'", lua_tostring(state, i));
319  break;
320  default:
321  printf("other %s", lua_typename(state, type));
322  break;
323 
324  }
325  printf("\n");
326  }
327 }
328 
329 int LuaPushStringBuffer(lua_State *luastate, const uint8_t *input, size_t input_len)
330 {
331  if (input_len % 4 != 0) {
332  /* we're using a buffer sized at a multiple of 4 as lua_pushlstring generates
333  * invalid read errors in valgrind otherwise. Adding in a nul to be sure.
334  *
335  * Buffer size = len + 1 (for nul) + whatever makes it a multiple of 4 */
336  size_t buflen = input_len + 1 + ((input_len + 1) % 4);
337  uint8_t buf[buflen];
338  memset(buf, 0x00, buflen);
339  memcpy(buf, input, input_len);
340  buf[input_len] = '\0';
341 
342  /* return value through luastate, as a luastring */
343  lua_pushlstring(luastate, (char *)buf, input_len);
344  } else {
345  lua_pushlstring(luastate, (char *)input, input_len);
346  }
347  return 1;
348 }
349 
350 int LuaPushInteger(lua_State *luastate, lua_Integer n)
351 {
352  lua_pushinteger(luastate, n);
353  return 1;
354 }
355 
356 #endif /* HAVE_LUA */
tm-threads.h
util-lua.h
threads.h
Flow_
Flow data structure.
Definition: flow.h:351
util-privs.h
util-unittest.h
app-layer-htp.h
util-debug.h
DetectEngineThreadCtx_
Definition: detect.h:1095
util-print.h
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
pkt-var.h
util-time.h
app-layer-parser.h
Packet_
Definition: decode.h:437
type
uint16_t type
Definition: decode-vlan.c:107
conf.h
util-proto-name.h
File_
Definition: util-file.h:79
suricata-common.h
lua_State
void lua_State
Definition: suricata-common.h:500
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
threadvars.h
util-logopenfile.h
util-buffer.h
Signature_
Signature container.
Definition: detect.h:596
PacketAlert_
Definition: decode.h:264
util-luajit.h
output.h
app-layer.h