suricata
detect-lua-extensions.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2013 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  * Functions to expose to the lua scripts.
24  */
25 
26 #include "suricata-common.h"
27 #include "conf.h"
28 
29 #include "threads.h"
30 #include "debug.h"
31 #include "decode.h"
32 
33 #include "detect.h"
34 #include "detect-parse.h"
35 #include "detect-flowvar.h"
36 
37 #include "detect-engine.h"
38 #include "detect-engine-mpm.h"
39 #include "detect-engine-state.h"
40 
41 #include "flow.h"
42 #include "flow-var.h"
43 #include "flow-util.h"
44 
45 #include "util-debug.h"
46 #include "util-spm-bm.h"
47 #include "util-print.h"
48 
49 #include "util-unittest.h"
50 #include "util-unittest-helper.h"
51 
52 #include "app-layer.h"
53 
54 #include "stream-tcp.h"
55 
56 #include "detect-lua.h"
57 
58 #include "queue.h"
59 #include "util-cpu.h"
60 
61 #include "app-layer-parser.h"
62 
63 #ifdef HAVE_LUA
64 
65 #include "util-lua.h"
66 #include "util-lua-common.h"
67 #include "util-lua-http.h"
68 #include "util-lua-dns.h"
69 #include "util-lua-ja3.h"
70 #include "util-lua-tls.h"
71 #include "util-lua-ssh.h"
72 #include "util-lua-smtp.h"
73 #include "util-lua-dnp3.h"
74 #include "detect-lua-extensions.h"
75 
76 static const char luaext_key_ld[] = "suricata:luadata";
77 
78 /* hack to please scan-build. Even though LuaCallbackError *always*
79  * returns 2, scan-build doesn't accept it and and generates false
80  * positives */
81 #define LUA_ERROR(msg) \
82  LuaCallbackError(luastate, (msg)); \
83  return 2
84 
85 static int GetLuaData(lua_State *luastate, DetectLuaData **ret_ld)
86 {
87  *ret_ld = NULL;
88 
89  DetectLuaData *ld;
90  lua_pushlightuserdata(luastate, (void *)&luaext_key_ld);
91  lua_gettable(luastate, LUA_REGISTRYINDEX);
92  ld = lua_touserdata(luastate, -1);
93  if (ld == NULL) {
94  LUA_ERROR("internal error: no ld");
95  }
96  *ret_ld = ld;
97  return 0;
98 }
99 
100 static int GetFlow(lua_State *luastate, Flow **ret_f)
101 {
102  Flow *f = LuaStateGetFlow(luastate);
103  if (f == NULL) {
104  LUA_ERROR("no flow");
105  }
106  *ret_f = f;
107  return 0;
108 }
109 
110 static int GetFlowVarById(lua_State *luastate, Flow *f,
111  FlowVar **ret_fv, _Bool fv_may_be_null, uint32_t *ret_idx)
112 {
113  DetectLuaData *ld = NULL;
114  if (ret_idx)
115  *ret_idx = 0;
116  *ret_fv = NULL;
117 
118  /* need lua data for id -> idx conversion */
119  int ret = GetLuaData(luastate, &ld);
120  if (ret != 0)
121  return ret;
122 
123  if (!lua_isnumber(luastate, 1)) {
124  LUA_ERROR("flowvar id not a number");
125  }
126  int id = lua_tonumber(luastate, 1);
127  if (id < 0 || id >= DETECT_LUAJIT_MAX_FLOWVARS) {
128  LUA_ERROR("flowvar id out of range");
129  }
130  uint32_t idx = ld->flowvar[id];
131  if (idx == 0) {
132  LUA_ERROR("flowvar id uninitialized");
133  }
134  FlowVar *fv = FlowVarGet(f, idx);
135  if (!fv_may_be_null && fv == NULL) {
136  LUA_ERROR("no flow var");
137  }
138  *ret_fv = fv;
139  if (ret_idx)
140  *ret_idx = idx;
141  return 0;
142 }
143 
144 static int GetFlowVarByKey(lua_State *luastate, Flow *f, FlowVar **ret_fv)
145 {
146  *ret_fv = NULL;
147 
148  if (!lua_isstring(luastate, 1)) {
149  LUA_ERROR("flowvar key not a string");
150  }
151  const char *keystr = lua_tostring(luastate, 1);
152  if (keystr == NULL) {
153  LUA_ERROR("key is null");
154  }
155  if (!lua_isnumber(luastate, 2)) {
156  LUA_ERROR("key length not specified");
157  }
158  int keylen = lua_tonumber(luastate, 2);
159  if (keylen < 0 || keylen > 0xff) {
160  LUA_ERROR("key len out of range: max 256");
161  }
162 
163  FlowVar *fv = FlowVarGetByKey(f, (const uint8_t *)keystr, keylen);
164  if (fv == NULL) {
165  LUA_ERROR("no flow var");
166  }
167  *ret_fv = fv;
168  return 0;
169 }
170 
171 static int GetFlowIntById(lua_State *luastate, Flow *f,
172  FlowVar **ret_fv, _Bool fv_may_be_null, uint32_t *ret_idx)
173 {
174  DetectLuaData *ld = NULL;
175  if (ret_idx)
176  *ret_idx = 0;
177  *ret_fv = NULL;
178 
179  /* need lua data for id -> idx conversion */
180  int ret = GetLuaData(luastate, &ld);
181  if (ret != 0)
182  return ret;
183 
184  if (!lua_isnumber(luastate, 1)) {
185  LUA_ERROR("flowvar id not a number");
186  }
187  int id = lua_tonumber(luastate, 1);
188  if (id < 0 || id >= DETECT_LUAJIT_MAX_FLOWVARS) {
189  LUA_ERROR("flowvar id out of range");
190  }
191  uint32_t idx = ld->flowint[id];
192  if (idx == 0) {
193  LUA_ERROR("flowvar id uninitialized");
194  }
195  FlowVar *fv = FlowVarGet(f, idx);
196  if (!fv_may_be_null && fv == NULL) {
197  LUA_ERROR("no flow var");
198  }
199  *ret_fv = fv;
200  if (ret_idx)
201  *ret_idx = idx;
202  return 0;
203 }
204 
205 static int LuaGetFlowvar(lua_State *luastate)
206 {
207  Flow *f;
208  FlowVar *fv;
209  int ret;
210 
211  /* need flow */
212  ret = GetFlow(luastate, &f);
213  if (ret != 0)
214  return ret;
215 
216  if (lua_isnumber(luastate, 1)) {
217  ret = GetFlowVarById(luastate, f, &fv, FALSE, NULL);
218  if (ret != 0 || fv == NULL)
219  return ret;
220  } else if (lua_isstring(luastate, 1)) {
221  ret = GetFlowVarByKey(luastate, f, &fv);
222  if (ret != 0 || fv == NULL)
223  return ret;
224  } else {
225  LUA_ERROR("invalid data type as first argument");
226  }
227 
228  LuaPushStringBuffer(luastate,
229  (const uint8_t *)fv->data.fv_str.value,
230  (size_t)fv->data.fv_str.value_len);
231  return 1;
232 }
233 
234 static int LuaSetFlowvarById(lua_State *luastate)
235 {
236  uint32_t idx = 0;
237  Flow *f;
238  const char *str;
239  int len;
240  uint8_t *buffer;
241  FlowVar *fv = NULL;
242 
243  /* need flow */
244  int ret = GetFlow(luastate, &f);
245  if (ret != 0)
246  return ret;
247 
248  ret = GetFlowVarById(luastate, f, &fv, TRUE, &idx);
249  if (ret != 0)
250  return ret;
251 
252  if (!lua_isstring(luastate, 2)) {
253  LUA_ERROR("buffer not a string");
254  }
255  str = lua_tostring(luastate, 2);
256  if (str == NULL) {
257  LUA_ERROR("buffer is null");
258  }
259 
260  if (!lua_isnumber(luastate, 3)) {
261  LUA_ERROR("buffer length not specified");
262  }
263  len = lua_tonumber(luastate, 3);
264  if (len < 0 || len > 0xffff) {
265  LUA_ERROR("len out of range: max 64k");
266  }
267 
268  buffer = SCMalloc(len+1);
269  if (unlikely(buffer == NULL)) {
270  LUA_ERROR("out of memory");
271  }
272  memcpy(buffer, str, len);
273  buffer[len] = '\0';
274 
275  FlowVarAddIdValue(f, idx, buffer, len);
276  return 0;
277 }
278 
279 static int LuaSetFlowvarByKey(lua_State *luastate)
280 {
281  Flow *f;
282  const char *str;
283  int len;
284  uint8_t *buffer;
285 
286  /* need flow */
287  int ret = GetFlow(luastate, &f);
288  if (ret != 0)
289  return ret;
290 
291  const char *keystr = NULL;
292  int keylen = 0;
293 
294  keystr = lua_tostring(luastate, 1);
295  if (keystr == NULL) {
296  LUA_ERROR("key is null");
297  }
298  if (!lua_isnumber(luastate, 2)) {
299  LUA_ERROR("key length not specified");
300  }
301  keylen = lua_tonumber(luastate, 2);
302  if (keylen < 0 || keylen > 0xff) {
303  LUA_ERROR("key len out of range: max 256");
304  }
305 
306  if (!lua_isstring(luastate, 3)) {
307  LUA_ERROR("buffer not a string");
308  }
309  str = lua_tostring(luastate, 3);
310  if (str == NULL) {
311  LUA_ERROR("buffer is null");
312  }
313 
314  if (!lua_isnumber(luastate, 4)) {
315  LUA_ERROR("buffer length not specified");
316  }
317  len = lua_tonumber(luastate, 4);
318  if (len < 0 || len > 0xffff) {
319  LUA_ERROR("len out of range: max 64k");
320  }
321 
322  buffer = SCMalloc(len+1);
323  if (unlikely(buffer == NULL)) {
324  LUA_ERROR("out of memory");
325  }
326  memcpy(buffer, str, len);
327  buffer[len] = '\0';
328 
329  uint8_t *keybuf = SCMalloc(keylen+1);
330  if (unlikely(keybuf == NULL)) {
331  SCFree(buffer);
332  LUA_ERROR("out of memory");
333  }
334  memcpy(keybuf, keystr, keylen);
335  keybuf[keylen] = '\0';
336  FlowVarAddKeyValue(f, keybuf, keylen, buffer, len);
337 
338  return 0;
339 }
340 
341 static int LuaSetFlowvar(lua_State *luastate)
342 {
343  if (lua_isnumber(luastate, 1)) {
344  return LuaSetFlowvarById(luastate);
345  } else {
346  return LuaSetFlowvarByKey(luastate);
347  }
348 }
349 
350 static int LuaGetFlowint(lua_State *luastate)
351 {
352  Flow *f;
353  FlowVar *fv;
354  uint32_t number;
355 
356  /* need flow */
357  int ret = GetFlow(luastate, &f);
358  if (ret != 0)
359  return ret;
360 
361  ret = GetFlowIntById(luastate, f, &fv, FALSE, NULL);
362  if (ret != 0)
363  return ret;
364 
365  number = fv->data.fv_int.value;
366 
367  /* return value through luastate, as a luanumber */
368  lua_pushnumber(luastate, (lua_Number)number);
369  return 1;
370 
371 }
372 
373 static int LuaSetFlowint(lua_State *luastate)
374 {
375  uint32_t idx;
376  Flow *f;
377  DetectLuaData *ld;
378 
379  /* need lua data for id -> idx conversion */
380  int ret = GetLuaData(luastate, &ld);
381  if (ret != 0)
382  return ret;
383 
384  /* need flow */
385  ret = GetFlow(luastate, &f);
386  if (ret != 0)
387  return ret;
388 
389  /* need flowint idx */
390  if (!lua_isnumber(luastate, 1)) {
391  LUA_ERROR("1st arg not a number");
392  }
393  int id = lua_tonumber(luastate, 1);
394  if (id < 0 || id >= DETECT_LUAJIT_MAX_FLOWVARS) {
395  LUA_ERROR("flowint id out of range");
396  }
397 
398  if (!lua_isnumber(luastate, 2)) {
399  LUA_ERROR("2nd arg not a number");
400  }
401  lua_Number luanumber = lua_tonumber(luastate, 2);
402  if (luanumber < 0 || id > (double)UINT_MAX) {
403  LUA_ERROR("value out of range, "
404  "value must be unsigned 32bit int");
405  }
406  uint32_t number = (uint32_t)luanumber;
407 
408  idx = ld->flowint[id];
409  if (idx == 0) {
410  LUA_ERROR("flowint id uninitialized");
411  }
412 
413  FlowVarAddInt(f, idx, number);
414 
415  SCLogDebug("stored flow:%p idx:%u value:%u", f, idx, number);
416  return 0;
417 }
418 
419 static int LuaIncrFlowint(lua_State *luastate)
420 {
421  uint32_t idx;
422  Flow *f;
423  FlowVar *fv;
424  uint32_t number;
425 
426  /* need flow */
427  int ret = GetFlow(luastate, &f);
428  if (ret != 0)
429  return ret;
430 
431  ret = GetFlowIntById(luastate, f, &fv, TRUE, &idx);
432  if (ret != 0)
433  return ret;
434 
435  if (fv == NULL) {
436  number = 1;
437  } else {
438  number = fv->data.fv_int.value;
439  if (number < UINT_MAX)
440  number++;
441  }
442  FlowVarAddIntNoLock(f, idx, number);
443 
444  /* return value through luastate, as a luanumber */
445  lua_pushnumber(luastate, (lua_Number)number);
446  SCLogDebug("incremented flow:%p idx:%u value:%u", f, idx, number);
447  return 1;
448 
449 }
450 
451 static int LuaDecrFlowint(lua_State *luastate)
452 {
453  uint32_t idx;
454  Flow *f;
455  FlowVar *fv;
456  uint32_t number;
457 
458  /* need flow */
459  int ret = GetFlow(luastate, &f);
460  if (ret != 0)
461  return ret;
462 
463  ret = GetFlowIntById(luastate, f, &fv, TRUE, &idx);
464  if (ret != 0)
465  return ret;
466 
467  if (fv == NULL) {
468  number = 0;
469  } else {
470  number = fv->data.fv_int.value;
471  if (number > 0)
472  number--;
473  }
474  FlowVarAddIntNoLock(f, idx, number);
475 
476  /* return value through luastate, as a luanumber */
477  lua_pushnumber(luastate, (lua_Number)number);
478  SCLogDebug("decremented flow:%p idx:%u value:%u", f, idx, number);
479  return 1;
480 
481 }
482 
483 void LuaExtensionsMatchSetup(lua_State *lua_state, DetectLuaData *ld, DetectEngineThreadCtx *det_ctx,
484  Flow *f, Packet *p, uint8_t flags)
485 {
486  SCLogDebug("det_ctx %p, f %p", det_ctx, f);
487 
488  /* lua keyword data */
489  lua_pushlightuserdata(lua_state, (void *)&luaext_key_ld);
490  lua_pushlightuserdata(lua_state, (void *)ld);
491  lua_settable(lua_state, LUA_REGISTRYINDEX);
492 
493  LuaStateSetFlow(lua_state, f);
494 
495  if (det_ctx->tx_id_set) {
496  if (f && f->alstate) {
497  void *txptr = AppLayerParserGetTx(f->proto, f->alproto, f->alstate, det_ctx->tx_id);
498  if (txptr) {
499  LuaStateSetTX(lua_state, txptr);
500  }
501  }
502  }
503 
504  if (p != NULL)
505  LuaStateSetPacket(lua_state, p);
506 
507  LuaStateSetDirection(lua_state, (flags & STREAM_TOSERVER));
508 }
509 
510 /**
511  * \brief Register Suricata Lua functions
512  */
513 int LuaRegisterExtensions(lua_State *lua_state)
514 {
515  lua_pushcfunction(lua_state, LuaGetFlowvar);
516  lua_setglobal(lua_state, "ScFlowvarGet");
517 
518  lua_pushcfunction(lua_state, LuaSetFlowvar);
519  lua_setglobal(lua_state, "ScFlowvarSet");
520 
521  lua_pushcfunction(lua_state, LuaGetFlowint);
522  lua_setglobal(lua_state, "ScFlowintGet");
523 
524  lua_pushcfunction(lua_state, LuaSetFlowint);
525  lua_setglobal(lua_state, "ScFlowintSet");
526 
527  lua_pushcfunction(lua_state, LuaIncrFlowint);
528  lua_setglobal(lua_state, "ScFlowintIncr");
529 
530  lua_pushcfunction(lua_state, LuaDecrFlowint);
531  lua_setglobal(lua_state, "ScFlowintDecr");
532 
533  LuaRegisterFunctions(lua_state);
534  LuaRegisterHttpFunctions(lua_state);
535  LuaRegisterDnsFunctions(lua_state);
536  LuaRegisterJa3Functions(lua_state);
537  LuaRegisterTlsFunctions(lua_state);
538  LuaRegisterSshFunctions(lua_state);
539  LuaRegisterSmtpFunctions(lua_state);
540  LuaRegisterDNP3Functions(lua_state);
541  return 0;
542 }
543 
544 #endif /* HAVE_LUA */
uint16_t flags
#define SCLogDebug(...)
Definition: util-debug.h:335
uint16_t value_len
Definition: flow-var.h:39
uint8_t proto
Definition: flow.h:344
#define FALSE
#define unlikely(expr)
Definition: util-optimize.h:35
void FlowVarAddInt(Flow *f, uint32_t idx, uint32_t value)
Definition: flow-var.c:156
FlowVar * FlowVarGetByKey(Flow *f, const uint8_t *key, uint16_t keylen)
get the flowvar with index &#39;idx&#39; from the flow
Definition: flow-var.c:54
#define TRUE
FlowVarTypeStr fv_str
Definition: flow-var.h:57
void * alstate
Definition: flow.h:438
#define str(s)
void * AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
Data structures and function prototypes for keeping state for the detection engine.
uint32_t value
Definition: flow-var.h:44
union FlowVar_::@112 data
FlowVarTypeInt fv_int
Definition: flow-var.h:58
uint8_t * value
Definition: flow-var.h:38
#define SCMalloc(a)
Definition: util-mem.h:166
FlowVar * FlowVarGet(Flow *f, uint32_t idx)
get the flowvar with index &#39;idx&#39; from the flow
Definition: flow-var.c:78
#define SCFree(a)
Definition: util-mem.h:228
void FlowVarAddIdValue(Flow *f, uint32_t idx, uint8_t *value, uint16_t size)
Definition: flow-var.c:113
#define STREAM_TOSERVER
Definition: stream.h:31
void FlowVarAddKeyValue(Flow *f, uint8_t *key, uint16_t keysize, uint8_t *value, uint16_t size)
Definition: flow-var.c:94
uint8_t len
AppProto alproto
application level protocol
Definition: flow.h:409
Flow data structure.
Definition: flow.h:325
void FlowVarAddIntNoLock(Flow *f, uint32_t idx, uint32_t value)
Definition: flow-var.c:135