suricata
detect-lua-extensions.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-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  * 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 "decode.h"
31 
32 #include "detect.h"
33 #include "detect-parse.h"
34 #include "detect-flowvar.h"
35 
36 #include "detect-engine.h"
37 #include "detect-engine-mpm.h"
38 #include "detect-engine-state.h"
39 
40 #include "flow.h"
41 #include "flow-var.h"
42 #include "flow-util.h"
43 
44 #include "util-debug.h"
45 #include "util-spm-bm.h"
46 #include "util-print.h"
47 
48 #include "util-unittest.h"
49 #include "util-unittest-helper.h"
50 
51 #include "app-layer.h"
52 
53 #include "stream-tcp.h"
54 
55 #include "detect-lua.h"
56 
57 #include "queue.h"
58 #include "util-cpu.h"
59 
60 #include "app-layer-parser.h"
61 
62 #ifdef HAVE_LUA
63 
64 #include "util-lua.h"
65 #include "util-lua-common.h"
66 #include "util-lua-http.h"
67 #include "util-lua-dns.h"
68 #include "util-lua-ja3.h"
69 #include "util-lua-tls.h"
70 #include "util-lua-ssh.h"
71 #include "util-lua-hassh.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 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 static int LuaGetByteVar(lua_State *luastate)
484 {
485  DetectLuaData *ld = NULL;
486  DetectEngineThreadCtx *det_ctx = LuaStateGetDetCtx(luastate);
487 
488  if (det_ctx == NULL)
489  return LuaCallbackError(luastate, "internal error: no ldet_ctx");
490 
491  int ret = GetLuaData(luastate, &ld);
492  if (ret != 0)
493  return ret;
494 
495  if (!lua_isnumber(luastate, 1)) {
496  LUA_ERROR("bytevar id not a number");
497  }
498  int id = lua_tonumber(luastate, 1);
499  if (id < 0 || id >= DETECT_LUAJIT_MAX_BYTEVARS) {
500  LUA_ERROR("bytevar id out of range");
501  }
502  uint32_t idx = ld->bytevar[id];
503 
504  lua_pushinteger(luastate, det_ctx->byte_values[idx]);
505 
506  return 1;
507 }
508 
509 void LuaExtensionsMatchSetup(lua_State *lua_state, DetectLuaData *ld,
510  DetectEngineThreadCtx *det_ctx, Flow *f, Packet *p, const Signature *s, uint8_t flags)
511 {
512  SCLogDebug("det_ctx %p, f %p", det_ctx, f);
513 
514  /* lua keyword data */
515  lua_pushlightuserdata(lua_state, (void *)&luaext_key_ld);
516  lua_pushlightuserdata(lua_state, (void *)ld);
517  lua_settable(lua_state, LUA_REGISTRYINDEX);
518 
519  LuaStateSetSignature(lua_state, s);
520 
521  LuaStateSetFlow(lua_state, f);
522  LuaStateSetDetCtx(lua_state, det_ctx);
523 
524  if (det_ctx->tx_id_set) {
525  if (f && f->alstate) {
526  void *txptr = AppLayerParserGetTx(f->proto, f->alproto, f->alstate, det_ctx->tx_id);
527  if (txptr) {
528  LuaStateSetTX(lua_state, txptr, det_ctx->tx_id);
529  }
530  }
531  }
532 
533  if (p != NULL)
534  LuaStateSetPacket(lua_state, p);
535 
536  LuaStateSetDirection(lua_state, (flags & STREAM_TOSERVER));
537 }
538 
539 /**
540  * \brief Register Suricata Lua functions
541  */
542 int LuaRegisterExtensions(lua_State *lua_state)
543 {
544  lua_pushcfunction(lua_state, LuaGetFlowvar);
545  lua_setglobal(lua_state, "ScFlowvarGet");
546 
547  lua_pushcfunction(lua_state, LuaGetFlowvar);
548  lua_setglobal(lua_state, "SCFlowvarGet");
549 
550  lua_pushcfunction(lua_state, LuaSetFlowvar);
551  lua_setglobal(lua_state, "ScFlowvarSet");
552 
553  lua_pushcfunction(lua_state, LuaSetFlowvar);
554  lua_setglobal(lua_state, "SCFlowvarSet");
555 
556  lua_pushcfunction(lua_state, LuaGetFlowint);
557  lua_setglobal(lua_state, "ScFlowintGet");
558 
559  lua_pushcfunction(lua_state, LuaGetFlowint);
560  lua_setglobal(lua_state, "SCFlowintGet");
561 
562  lua_pushcfunction(lua_state, LuaSetFlowint);
563  lua_setglobal(lua_state, "ScFlowintSet");
564 
565  lua_pushcfunction(lua_state, LuaSetFlowint);
566  lua_setglobal(lua_state, "SCFlowintSet");
567 
568  lua_pushcfunction(lua_state, LuaIncrFlowint);
569  lua_setglobal(lua_state, "ScFlowintIncr");
570 
571  lua_pushcfunction(lua_state, LuaIncrFlowint);
572  lua_setglobal(lua_state, "SCFlowintIncr");
573 
574  lua_pushcfunction(lua_state, LuaDecrFlowint);
575  lua_setglobal(lua_state, "ScFlowintDecr");
576 
577  lua_pushcfunction(lua_state, LuaDecrFlowint);
578  lua_setglobal(lua_state, "SCFlowintDecr");
579 
580  lua_pushcfunction(lua_state, LuaGetByteVar);
581  lua_setglobal(lua_state, "SCByteVarGet");
582 
583  LuaRegisterFunctions(lua_state);
584  LuaRegisterHttpFunctions(lua_state);
585  LuaRegisterDnsFunctions(lua_state);
586  LuaRegisterJa3Functions(lua_state);
587  LuaRegisterTlsFunctions(lua_state);
588  LuaRegisterSshFunctions(lua_state);
589  LuaRegisterHasshFunctions(lua_state);
590  LuaRegisterSmtpFunctions(lua_state);
591  LuaRegisterDNP3Functions(lua_state);
592  return 0;
593 }
594 
595 #endif /* HAVE_LUA */
DetectEngineThreadCtx_::byte_values
uint64_t * byte_values
Definition: detect.h:1135
len
uint8_t len
Definition: app-layer-dnp3.h:2
detect-engine.h
util-lua-ssh.h
util-lua-hassh.h
util-lua-common.h
flow-util.h
FlowVarAddKeyValue
void FlowVarAddKeyValue(Flow *f, uint8_t *key, uint16_t keysize, uint8_t *value, uint16_t size)
Definition: flow-var.c:94
stream-tcp.h
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
FlowVar_::data
union FlowVar_::@112 data
Flow_::proto
uint8_t proto
Definition: flow.h:373
util-lua.h
DetectEngineThreadCtx_::tx_id
uint64_t tx_id
Definition: detect.h:1178
FlowVarTypeStr::value_len
uint16_t value_len
Definition: flow-var.h:39
threads.h
Flow_
Flow data structure.
Definition: flow.h:351
util-lua-ja3.h
FlowVar_::fv_str
FlowVarTypeStr fv_str
Definition: flow-var.h:57
detect-lua.h
util-unittest.h
util-unittest-helper.h
detect-flowvar.h
FlowVar_::fv_int
FlowVarTypeInt fv_int
Definition: flow-var.h:58
decode.h
util-debug.h
FlowVarGetByKey
FlowVar * FlowVarGetByKey(Flow *f, const uint8_t *key, uint16_t keylen)
get the flowvar with index 'idx' from the flow
Definition: flow-var.c:54
DetectEngineThreadCtx_
Definition: detect.h:1095
util-cpu.h
util-print.h
detect-engine-mpm.h
detect.h
app-layer-parser.h
Packet_
Definition: decode.h:437
conf.h
util-lua-dnp3.h
FlowVarAddIdValue
void FlowVarAddIdValue(Flow *f, uint32_t idx, uint8_t *value, uint16_t size)
Definition: flow-var.c:113
detect-engine-state.h
Data structures and function prototypes for keeping state for the detection engine.
queue.h
AppLayerParserGetTx
void * AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
Definition: app-layer-parser.c:1108
FlowVarTypeInt_::value
uint32_t value
Definition: flow-var.h:44
util-lua-smtp.h
FlowVarTypeStr::value
uint8_t * value
Definition: flow-var.h:38
flags
uint8_t flags
Definition: decode-gre.h:0
detect-lua-extensions.h
suricata-common.h
lua_State
void lua_State
Definition: suricata-common.h:500
util-lua-dns.h
util-spm-bm.h
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
str
#define str(s)
Definition: suricata-common.h:291
SCFree
#define SCFree(p)
Definition: util-mem.h:61
Flow_::alstate
void * alstate
Definition: flow.h:476
FlowVarAddInt
void FlowVarAddInt(Flow *f, uint32_t idx, uint32_t value)
Definition: flow-var.c:156
detect-parse.h
Signature_
Signature container.
Definition: detect.h:596
FlowVarAddIntNoLock
void FlowVarAddIntNoLock(Flow *f, uint32_t idx, uint32_t value)
Definition: flow-var.c:135
util-lua-tls.h
DetectEngineThreadCtx_::tx_id_set
bool tx_id_set
Definition: detect.h:1176
util-lua-http.h
FlowVarGet
FlowVar * FlowVarGet(Flow *f, uint32_t idx)
get the flowvar with index 'idx' from the flow
Definition: flow-var.c:78
flow.h
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:450
flow-var.h
FlowVar_
Definition: flow-var.h:48
app-layer.h