]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
lua: Expose byte extract to lua match scripts
authorBenjamin Wilkins <benjamin.wilkins@uwaterloo.ca>
Tue, 26 Oct 2021 19:20:41 +0000 (15:20 -0400)
committerVictor Julien <vjulien@oisf.net>
Tue, 9 Aug 2022 08:52:37 +0000 (10:52 +0200)
Allow lua match scripts to access variables defined in rule by
byte_extract or byte_math

Issue: 2871

src/detect-lua-extensions.c
src/detect-lua.c
src/detect-lua.h
src/util-lua.c
src/util-lua.h

index d03c022b705aa2b1f392747b0434725a84bda185..28334038e5ea2953798a722ae453e645b205c848 100644 (file)
@@ -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);
index e4765d0a5f4993b7bb53a5d009302b0fc377cd81..8e5f4a6b8786f2cb6cca9db3f159a696c0316d3d 100644 (file)
@@ -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;
     }
 
index 5faa9241e608bc332fac9903a5d42b12568465df..dcf99b6c3f43fa726ae355c5b1ab830496c531cf 100644 (file)
@@ -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;
index 084a3e132dd2d89bc2b015fd7dbb15f8fd93c533..0eedd1e32c13f9316cd57d5807cec3708e943973 100644 (file)
@@ -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);
index fa4737955518eaba7d0d0402a7187dd7ca6cb9ff..ab571d8b29d00b0ce4db1dd051a76bce9aced52e 100644 (file)
@@ -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);