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