diff --git a/src/detect-lua-extensions.c b/src/detect-lua-extensions.c index d03c022b70..28334038e5 100644 --- a/src/detect-lua-extensions.c +++ b/src/detect-lua-extensions.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2021 Open Information Security Foundation +/* Copyright (C) 2007-2022 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -481,6 +481,32 @@ static int LuaDecrFlowint(lua_State *luastate) } +static int LuaGetByteVar(lua_State *luastate) +{ + DetectLuaData *ld = NULL; + DetectEngineThreadCtx *det_ctx = LuaStateGetDetCtx(luastate); + + if (det_ctx == NULL) + return LuaCallbackError(luastate, "internal error: no ldet_ctx"); + + int ret = GetLuaData(luastate, &ld); + if (ret != 0) + return ret; + + if (!lua_isnumber(luastate, 1)) { + LUA_ERROR("bytevar id not a number"); + } + int id = lua_tonumber(luastate, 1); + if (id < 0 || id >= DETECT_LUAJIT_MAX_BYTEVARS) { + LUA_ERROR("bytevar id out of range"); + } + uint32_t idx = ld->bytevar[id]; + + lua_pushinteger(luastate, det_ctx->byte_values[idx]); + + return 1; +} + void LuaExtensionsMatchSetup(lua_State *lua_state, DetectLuaData *ld, DetectEngineThreadCtx *det_ctx, Flow *f, Packet *p, const Signature *s, uint8_t flags) { @@ -494,6 +520,7 @@ void LuaExtensionsMatchSetup(lua_State *lua_state, DetectLuaData *ld, LuaStateSetSignature(lua_state, s); LuaStateSetFlow(lua_state, f); + LuaStateSetDetCtx(lua_state, det_ctx); if (det_ctx->tx_id_set) { if (f && f->alstate) { @@ -551,6 +578,9 @@ int LuaRegisterExtensions(lua_State *lua_state) lua_pushcfunction(lua_state, LuaDecrFlowint); lua_setglobal(lua_state, "SCFlowintDecr"); + lua_pushcfunction(lua_state, LuaGetByteVar); + lua_setglobal(lua_state, "SCByteVarGet"); + LuaRegisterFunctions(lua_state); LuaRegisterHttpFunctions(lua_state); LuaRegisterDnsFunctions(lua_state); diff --git a/src/detect-lua.c b/src/detect-lua.c index e4765d0a5f..8e5f4a6b87 100644 --- a/src/detect-lua.c +++ b/src/detect-lua.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2014 Open Information Security Foundation +/* Copyright (C) 2007-2022 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -37,6 +37,8 @@ #include "detect-engine-state.h" #include "detect-engine-build.h" +#include "detect-byte.h" + #include "flow.h" #include "flow-var.h" #include "flow-util.h" @@ -702,7 +704,7 @@ error: return NULL; } -static int DetectLuaSetupPrime(DetectEngineCtx *de_ctx, DetectLuaData *ld) +static int DetectLuaSetupPrime(DetectEngineCtx *de_ctx, DetectLuaData *ld, const Signature *s) { int status; @@ -774,7 +776,7 @@ static int DetectLuaSetupPrime(DetectEngineCtx *de_ctx, DetectLuaData *ld) if (k == NULL) continue; - /* handle flowvar separately as it has a table as value */ + /* handle flowvar and bytes separately as they have a table as value */ if (strcmp(k, "flowvar") == 0) { if (lua_istable(luastate, -1)) { lua_pushnil(luastate); @@ -819,6 +821,35 @@ static int DetectLuaSetupPrime(DetectEngineCtx *de_ctx, DetectLuaData *ld) } lua_pop(luastate, 1); continue; + } else if (strcmp(k, "bytevar") == 0) { + if (lua_istable(luastate, -1)) { + lua_pushnil(luastate); + while (lua_next(luastate, -2) != 0) { + /* value at -1, key is at -2 which we ignore */ + const char *value = lua_tostring(luastate, -1); + SCLogDebug("value %s", value); + /* removes 'value'; keeps 'key' for next iteration */ + lua_pop(luastate, 1); + + if (ld->bytevars == DETECT_LUAJIT_MAX_BYTEVARS) { + SCLogError(SC_ERR_LUA_ERROR, "too many bytevars registered"); + goto error; + } + + DetectByteIndexType idx; + if (!DetectByteRetrieveSMVar(value, s, &idx)) { + SCLogError(SC_ERR_LUA_ERROR, + "Unknown byte_extract or byte_math var " + "requested by lua script - %s", + value); + goto error; + } + ld->bytevar[ld->bytevars++] = idx; + SCLogDebug("script uses bytevar %u with script id %u", idx, ld->bytevars - 1); + } + } + lua_pop(luastate, 1); + continue; } v = lua_tostring(luastate, -1); @@ -986,7 +1017,7 @@ static int DetectLuaSetup (DetectEngineCtx *de_ctx, Signature *s, const char *st if (lua == NULL) goto error; - if (DetectLuaSetupPrime(de_ctx, lua) == -1) { + if (DetectLuaSetupPrime(de_ctx, lua, s) == -1) { goto error; } diff --git a/src/detect-lua.h b/src/detect-lua.h index 5faa9241e6..dcf99b6c3f 100644 --- a/src/detect-lua.h +++ b/src/detect-lua.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2021 Open Information Security Foundation +/* Copyright (C) 2007-2022 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -36,6 +36,7 @@ typedef struct DetectLuaThreadData { #define DETECT_LUAJIT_MAX_FLOWVARS 15 #define DETECT_LUAJIT_MAX_FLOWINTS 15 +#define DETECT_LUAJIT_MAX_BYTEVARS 15 typedef struct DetectLuaData { int thread_ctx_id; @@ -48,6 +49,8 @@ typedef struct DetectLuaData { uint16_t flowints; uint16_t flowvars; uint32_t flowvar[DETECT_LUAJIT_MAX_FLOWVARS]; + uint16_t bytevars; + uint32_t bytevar[DETECT_LUAJIT_MAX_BYTEVARS]; uint32_t sid; uint32_t rev; uint32_t gid; diff --git a/src/util-lua.c b/src/util-lua.c index 084a3e132d..0eedd1e32c 100644 --- a/src/util-lua.c +++ b/src/util-lua.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014 Open Information Security Foundation +/* Copyright (C) 2014-2022 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -102,6 +102,8 @@ const char lua_ext_key_pa[] = "suricata:lua:pkt:alert:ptr"; const char lua_ext_key_s[] = "suricata:lua:signature:ptr"; /* key for file pointer */ const char lua_ext_key_file[] = "suricata:lua:file:ptr"; +/* key for DetectEngineThreadCtx pointer */ +const char lua_ext_key_det_ctx[] = "suricata:lua:det_ctx:ptr"; /* key for streaming buffer pointer */ const char lua_ext_key_streaming_buffer[] = "suricata:lua:streaming_buffer:ptr"; @@ -230,6 +232,22 @@ void LuaStateSetFile(lua_State *luastate, File *file) lua_settable(luastate, LUA_REGISTRYINDEX); } +/** \brief get DetectEngineThreadCtx pointer from the lua state */ +DetectEngineThreadCtx *LuaStateGetDetCtx(lua_State *luastate) +{ + lua_pushlightuserdata(luastate, (void *)&lua_ext_key_det_ctx); + lua_gettable(luastate, LUA_REGISTRYINDEX); + void *det_ctx = lua_touserdata(luastate, -1); + return (DetectEngineThreadCtx *)det_ctx; +} + +void LuaStateSetDetCtx(lua_State *luastate, DetectEngineThreadCtx *det_ctx) +{ + lua_pushlightuserdata(luastate, (void *)&lua_ext_key_det_ctx); + lua_pushlightuserdata(luastate, (void *)det_ctx); + lua_settable(luastate, LUA_REGISTRYINDEX); +} + LuaStreamingBuffer *LuaStateGetStreamingBuffer(lua_State *luastate) { lua_pushlightuserdata(luastate, (void *)&lua_ext_key_streaming_buffer); diff --git a/src/util-lua.h b/src/util-lua.h index fa47379555..ab571d8b29 100644 --- a/src/util-lua.h +++ b/src/util-lua.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2014 Open Information Security Foundation +/* Copyright (C) 2014-2022 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -67,6 +67,9 @@ Signature *LuaStateGetSignature(lua_State *luastate); /** \brief get file pointer from the lua state */ File *LuaStateGetFile(lua_State *luastate); +/** \brief get detect engine thread context pointer from the lua state */ +DetectEngineThreadCtx *LuaStateGetDetCtx(lua_State *luastate); + LuaStreamingBuffer *LuaStateGetStreamingBuffer(lua_State *luastate); int LuaStateGetDirection(lua_State *luastate); @@ -88,6 +91,8 @@ void LuaStateSetSignature(lua_State *luastate, const Signature *s); void LuaStateSetFile(lua_State *luastate, File *file); +void LuaStateSetDetCtx(lua_State *luastate, DetectEngineThreadCtx *det_ctx); + void LuaStateSetThreadVars(lua_State *luastate, ThreadVars *tv); void LuaStateSetStreamingBuffer(lua_State *luastate, LuaStreamingBuffer *b);