suricata
util-lua-flowvarlib.c
Go to the documentation of this file.
1 /* Copyright (C) 2025 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 #include "suricata-common.h"
19 #include "app-layer-protos.h"
20 #include "flow-var.h"
21 #include "lauxlib.h"
22 #include "util-debug.h"
23 #include "util-lua-common.h"
24 #include "util-lua-flowvarlib.h"
25 #include "util-lua.h"
26 #include "util-var-name.h"
27 #include "detect-lua.h"
28 #include "detect-lua-extensions.h"
29 
30 static const char suricata_flowvar_mt[] = "suricata:flowvar:mt";
31 
32 static DetectLuaData *GetLuaData(lua_State *luastate)
33 {
34  return LuaStateGetDetectLuaData(luastate);
35 }
36 
37 /**
38  * \brief Register a flowvar.
39  *
40  * Ensures that a flowvar exists for the provided name, will be
41  * created if needed.
42  *
43  * The flowvar ID is returned, however as this is most likely to be
44  * used in the scripts "init" method, this ID is unlikely to be used.
45  */
46 static int LuaFlowvarRegister(lua_State *L)
47 {
48  DetectLuaData *ld = GetLuaData(L);
49  if (ld == NULL) {
50  return luaL_error(L, "flowvar API not available in this context");
51  }
52  if (!ld->register_in_init) {
53  return luaL_error(L, "flowvar.register() must be called from init()");
54  }
55  const char *name = luaL_checkstring(L, 1);
56  /* check the limit first: a failed over-limit registration must not
57  * leave a name store entry that nothing unregisters */
58  if (ld->flowvars >= DETECT_LUA_MAX_FLOWVARS) {
59  return luaL_error(L, "too many flowvars registered");
60  }
61  uint32_t *flowvar_id = SCLuaNewUserData(L, SCLUA_TUD_FLOWVAR, sizeof(*flowvar_id));
62  if (flowvar_id == NULL) {
63  return luaL_error(L, "failed to allocate flowvar");
64  }
66  if (*flowvar_id == 0) {
67  return luaL_error(L, "failed to register flowvar");
68  }
69  ld->flowvar[ld->flowvars++] = *flowvar_id;
70 
71  luaL_getmetatable(L, suricata_flowvar_mt);
72  lua_setmetatable(L, -2);
73 
74  return 1;
75 }
76 
77 static int LuaFlowvarGet(lua_State *L)
78 {
79  const char *name = luaL_checkstring(L, 1);
80  uint32_t *flowvar_id = SCLuaNewUserData(L, SCLUA_TUD_FLOWVAR, sizeof(*flowvar_id));
81  if (flowvar_id == NULL) {
82  return luaL_error(L, "failed to allocate flowvar");
83  }
85  if (*flowvar_id == 0) {
86  return luaL_error(L, "flowvar does not exist");
87  }
88 
89  luaL_getmetatable(L, suricata_flowvar_mt);
90  lua_setmetatable(L, -2);
91 
92  return 1;
93 }
94 
95 static int LuaFlowvarValue(lua_State *L)
96 {
97  uint32_t *flowvar_id = SCLuaCheckUserData(L, 1, suricata_flowvar_mt, SCLUA_TUD_FLOWVAR);
98  Flow *f = LuaStateGetFlow(L);
99  if (f == NULL) {
100  return LuaCallbackError(L, "flow is NULL");
101  }
102  FlowVar *fv = FlowVarGet(f, *flowvar_id);
103  if (fv == NULL) {
104  lua_pushnil(L);
105  } else {
107  L, (const uint8_t *)fv->data.fv_str.value, (size_t)fv->data.fv_str.value_len);
108  }
109  return 1;
110 }
111 
112 static int LuaFlowvarSet(lua_State *L)
113 {
114  size_t slen = 0;
115  const char *value = luaL_checklstring(L, 2, &slen);
116  lua_Integer req = luaL_optinteger(L, 3, (lua_Integer)slen);
117  if (req < 0 || ((size_t)req > slen) || (size_t)req > UINT16_MAX) {
118  return luaL_error(L, "length out of range");
119  }
120  const size_t len = (size_t)req;
121  uint32_t *flowvar_id = SCLuaCheckUserData(L, 1, suricata_flowvar_mt, SCLUA_TUD_FLOWVAR);
122  Flow *f = LuaStateGetFlow(L);
123  if (f == NULL) {
124  return luaL_error(L, "no flow");
125  }
126 
127  uint8_t *buf = SCMalloc(len + 1);
128  if (buf == NULL) {
129  return luaL_error(L, "alloc failure");
130  }
131  memcpy(buf, value, len);
132  buf[len] = '\0';
133  FlowVarAddIdValue(f, *flowvar_id, buf, (uint16_t)len);
134 
135  /* set() documents no result; claiming one hands back the last
136  * argument (or the flow lock hint left by LuaStateGetFlow) */
137  return 0;
138 }
139 
140 static const luaL_Reg flowvarlib[] = {
141  // clang-format off
142  { "register", LuaFlowvarRegister, },
143  { "get", LuaFlowvarGet },
144  { NULL, NULL, },
145  // clang-format on
146 };
147 
148 static const luaL_Reg flowvarmt[] = {
149  // clang-format off
150  { "value", LuaFlowvarValue, },
151  { "set", LuaFlowvarSet, },
152  { NULL, NULL, },
153  // clang-format on
154 };
155 
157 {
158  luaL_newmetatable(L, suricata_flowvar_mt);
159  lua_pushvalue(L, -1);
160  lua_setfield(L, -2, "__index");
161  luaL_setfuncs(L, flowvarmt, 0);
162 
163  luaL_newlib(L, flowvarlib);
164  return 1;
165 }
DetectLuaData
Definition: detect-lua.h:44
len
uint8_t len
Definition: app-layer-dnp3.h:2
util-lua-common.h
name
const char * name
Definition: detect-engine-proto.c:47
util-lua.h
LuaCallbackError
int LuaCallbackError(lua_State *luastate, const char *msg)
Definition: util-lua-common.c:218
FlowVarTypeStr::value_len
uint16_t value_len
Definition: flow-var.h:41
Flow_
Flow data structure.
Definition: flow.h:359
FlowVar_::fv_str
FlowVarTypeStr fv_str
Definition: flow-var.h:64
detect-lua.h
DETECT_LUA_MAX_FLOWVARS
#define DETECT_LUA_MAX_FLOWVARS
Definition: detect-lua.h:35
util-var-name.h
DetectLuaData::flowvar
uint32_t flowvar[DETECT_LUA_MAX_FLOWVARS]
Definition: detect-lua.h:55
VarNameStoreRegister
uint32_t VarNameStoreRegister(const char *name, const enum VarTypes type)
Definition: util-var-name.c:156
lua_State
struct lua_State lua_State
Definition: suricata-common.h:527
DetectLuaData::register_in_init
bool register_in_init
Definition: detect-lua.h:60
VarNameStoreLookupByName
uint32_t VarNameStoreLookupByName(const char *name, const enum VarTypes type)
find name for id+type at packet time. As the active store won't be modified, we don't need locks.
Definition: util-var-name.c:327
util-debug.h
SCLUA_TUD_FLOWVAR
@ SCLUA_TUD_FLOWVAR
Definition: util-lua-common.h:53
SCLuaCheckUserData
void * SCLuaCheckUserData(lua_State *L, int idx, const char *mt, uint32_t type_id)
Definition: util-lua-common.c:101
FlowVarAddIdValue
void FlowVarAddIdValue(Flow *f, uint32_t idx, uint8_t *value, uint16_t size)
Definition: flow-var.c:120
LuaStateGetDetectLuaData
DetectLuaData * LuaStateGetDetectLuaData(lua_State *luastate)
get the per-rule DetectLuaData
Definition: util-lua.c:319
SCLuaNewUserData
void * SCLuaNewUserData(lua_State *L, uint32_t type_id, size_t size)
Definition: util-lua-common.c:42
FlowVarTypeStr::value
uint8_t * value
Definition: flow-var.h:40
detect-lua-extensions.h
suricata-common.h
FlowVar_::data
union FlowVar_::@121 data
LuaLoadFlowvarLib
int LuaLoadFlowvarLib(lua_State *L)
Definition: util-lua-flowvarlib.c:156
DetectLuaData::flowvars
uint16_t flowvars
Definition: detect-lua.h:54
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
VAR_TYPE_FLOW_VAR
@ VAR_TYPE_FLOW_VAR
Definition: util-var.h:39
LuaStateGetFlow
Flow * LuaStateGetFlow(lua_State *luastate)
get flow pointer from lua state
Definition: util-lua.c:260
app-layer-protos.h
util-lua-flowvarlib.h
FlowVarGet
FlowVar * FlowVarGet(Flow *f, uint32_t idx)
get the flowvar with index 'idx' from the flow
Definition: flow-var.c:84
flow-var.h
FlowVar_
Definition: flow-var.h:55
LuaPushStringBuffer
int LuaPushStringBuffer(lua_State *luastate, const uint8_t *input, size_t input_len)
Definition: util-lua.c:380
f
Flow f
Definition: fuzz_dataset.c:32