]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
lua: convert ja3 function into suricata.ja3 lib
authorPhilippe Antoine <pantoine@oisf.net>
Fri, 2 May 2025 12:34:09 +0000 (14:34 +0200)
committerVictor Julien <victor@inliniac.net>
Wed, 7 May 2025 11:59:57 +0000 (13:59 +0200)
Ticket: 7605

doc/userguide/lua/libs/index.rst
doc/userguide/lua/libs/ja3.rst [new file with mode: 0644]
doc/userguide/lua/lua-functions.rst
src/detect-lua-extensions.c
src/detect-lua.c
src/output-lua.c
src/util-lua-builtins.c
src/util-lua-ja3.c
src/util-lua-ja3.h

index ba7e6723600584b705fddc0fb9abbbd6df42a173..b6555bdfa7200881eb01ee89dfaf89618a0b6473 100644 (file)
@@ -18,3 +18,4 @@ environment without access to additional modules.
    packetlib
    rule
    ssh
+   ja3
diff --git a/doc/userguide/lua/libs/ja3.rst b/doc/userguide/lua/libs/ja3.rst
new file mode 100644 (file)
index 0000000..e025cbd
--- /dev/null
@@ -0,0 +1,90 @@
+JA3
+---
+
+JA3 details are exposes to Lua scripts with the
+``suricata.ja3`` library, For example::
+
+  local ja3 = require("suricata.ja3")
+
+If you want to use ja3, you can either set suricata.yaml option
+``app-layer.protocols.tls.ja3-fingerprints`` to true,
+or specify it in the ``init`` function of your lua script
+by calling ``ja3.enable_ja3()``::
+
+  function init (args)
+    ja3.enable_ja3()
+    return {}
+  end
+
+``ja3.enable_ja3()`` will not enable ja3 if they are explicitly
+disabled, so you should add ``requires: feature ja3;`` to your rule.
+
+For use in rule matching, the rule may **hook** into a TLS or QUIC
+transaction state if you want to match on only one of these protocols.
+Or you should use need ``ja3`` or ``ja3s`` in your init script::
+
+  function init (args)
+    ja3.enable_ja3()
+    local needs = {}
+    needs["ja3s"] = true
+    return needs
+  end
+
+Transaction
+~~~~~~~~~~~
+
+JA3 is transaction based, and the current transaction must be obtained before use::
+
+  local tx, err = ja3.get_tx()
+  if tx == err then
+      print(err)
+  end
+
+All other functions are methods on the transaction (either a QUIC or a TLS one).
+
+Transaction Methods
+~~~~~~~~~~~~~~~~~~~
+
+``ja3_get_hash()``
+^^^^^^^^^^^^^^^^^^
+
+Get the ja3 value as a hash.
+
+Example::
+
+  local tx = ja3.get_tx()
+  local h = tx:ja3_get_hash();
+  print (h)
+
+``ja3_get_string()``
+^^^^^^^^^^^^^^^^^^^^
+
+Get the ja3 value as a string.
+
+Example::
+
+  local tx = ja3.get_tx()
+  local s = tx:ja3_get_string();
+  print (s)
+
+``ja3s_get_hash()``
+^^^^^^^^^^^^^^^^^^^
+
+Get the ja3s value as a hash.
+
+Example::
+
+  local tx = ja3.get_tx()
+  local h = tx:ja3s_get_hash();
+  print (h)
+
+``ja3s_get_string()``
+^^^^^^^^^^^^^^^^^^^^^
+
+Get the ja3s value as a string.
+
+Example::
+
+  local tx = ja3.get_tx()
+  local s = tx:ja3s_get_string();
+  print (s)
\ No newline at end of file
index 9cecddf57c459da38ca23df6f4eeb6e89d55e479..f8c521937dffb6438883c82803e91a8abd35eeb8 100644 (file)
@@ -348,126 +348,6 @@ Example:
       end
   end
 
-
-JA3
----
-
-JA3 must be enabled in the Suricata config file (set 'app-layer.protocols.tls.ja3-fingerprints' to 'yes').
-
-For log output, initialize with:
-
-::
-
-  function init (args)
-      local needs = {}
-      needs["protocol"] = "tls"
-      return needs
-  end
-
-For detection, initialization is as follows:
-
-::
-
-  function init (args)
-      local needs = {}
-      needs["tls"] = tostring(true)
-      return needs
-  end
-
-Ja3GetHash
-~~~~~~~~~~
-
-Get the JA3 hash (md5sum of JA3 string) through Ja3GetHash.
-
-Example:
-
-::
-
-  function log (args)
-      hash = Ja3GetHash()
-      if hash == nil then
-          return
-      end
-  end
-
-Ja3GetString
-~~~~~~~~~~~~
-
-Get the JA3 string through Ja3GetString.
-
-Example:
-
-::
-
-  function log (args)
-      str = Ja3GetString()
-      if str == nil then
-          return
-      end
-  end
-
-Ja3SGetHash
-~~~~~~~~~~~
-
-Get the JA3S hash (md5sum of JA3S string) through JA3SGetHash.
-
-Examples:
-
-::
-
-  function log (args)
-      hash = Ja3SGetHash()
-      if hash == nil then
-          return
-      end
-  end
-
-Or, for detection:
-
-::
-
-  function match (args)
-      hash = Ja3SGetHash()
-      if hash == nil then
-        return 0
-      end
-
-      // matching code
-
-      return 0
-  end
-
-JA3SGetString
-~~~~~~~~~~~~~
-
-Get the JA3S string through Ja3SGetString.
-
-Examples:
-
-::
-
-  function log (args)
-      str = Ja3SGetString()
-      if str == nil then
-          return
-      end
-  end
-
-Or, for detection:
-
-::
-
-  function match (args)
-    str = Ja3SGetString()
-    if str == nil then
-      return 0
-    end
-
-    // matching code
-
-    return 0
-  end
-
 Files
 -----
 
index c793828de8c75159b65e6b889071e07f75c2ec85..c55511c52bf63e73d0e913e4de2e49b7827fb3a9 100644 (file)
@@ -38,7 +38,6 @@
 
 #include "util-lua.h"
 #include "util-lua-common.h"
-#include "util-lua-ja3.h"
 #include "util-lua-tls.h"
 #include "util-lua-smtp.h"
 #include "util-lua-dnp3.h"
@@ -121,7 +120,6 @@ int LuaRegisterExtensions(lua_State *lua_state)
     lua_setglobal(lua_state, "SCByteVarGet");
 
     LuaRegisterFunctions(lua_state);
-    LuaRegisterJa3Functions(lua_state);
     LuaRegisterTlsFunctions(lua_state);
     LuaRegisterSmtpFunctions(lua_state);
     return 0;
index 11c9fad7cfbca432518b8b18a1fffc91eee3fdef..b86a84de9585501e3e70fc1f41821c6fc11ff9a4 100644 (file)
@@ -49,6 +49,7 @@
 #include "app-layer.h"
 #include "app-layer-parser.h"
 #include "app-layer-htp.h"
+#include "app-layer-ssl.h"
 
 #include "stream-tcp.h"
 
@@ -72,6 +73,8 @@ static int DetectLuaSetup (DetectEngineCtx *, Signature *, const char *);
 static void DetectLuaRegisterTests(void);
 #endif
 static void DetectLuaFree(DetectEngineCtx *, void *);
+static int g_lua_ja3_list_id = 0;
+static int g_lua_ja3s_list_id = 0;
 
 /**
  * \brief Registration function for keyword: lua
@@ -89,6 +92,18 @@ void DetectLuaRegister(void)
     sigmatch_table[DETECT_LUA].RegisterTests = DetectLuaRegisterTests;
 #endif
 
+    g_lua_ja3_list_id = DetectBufferTypeRegister("ja3.lua");
+    DetectAppLayerInspectEngineRegister("ja3.lua", ALPROTO_TLS, SIG_FLAG_TOSERVER,
+            TLS_STATE_CLIENT_HELLO_DONE, DetectEngineInspectGenericList, NULL);
+    DetectAppLayerInspectEngineRegister(
+            "ja3.lua", ALPROTO_QUIC, SIG_FLAG_TOSERVER, 1, DetectEngineInspectGenericList, NULL);
+
+    g_lua_ja3s_list_id = DetectBufferTypeRegister("ja3s.lua");
+    DetectAppLayerInspectEngineRegister("ja3s.lua", ALPROTO_TLS, SIG_FLAG_TOCLIENT,
+            TLS_STATE_SERVER_HELLO_DONE, DetectEngineInspectGenericList, NULL);
+    DetectAppLayerInspectEngineRegister(
+            "ja3s.lua", ALPROTO_QUIC, SIG_FLAG_TOCLIENT, 1, DetectEngineInspectGenericList, NULL);
+
     SCLogDebug("registering lua rule option");
 }
 
@@ -96,6 +111,8 @@ void DetectLuaRegister(void)
 #define FLAG_DATATYPE_PACKET                    BIT_U32(0)
 #define FLAG_DATATYPE_PAYLOAD                   BIT_U32(1)
 #define FLAG_DATATYPE_STREAM                    BIT_U32(2)
+#define FLAG_LIST_JA3                           BIT_U32(3)
+#define FLAG_LIST_JA3S                          BIT_U32(4)
 #define FLAG_DATATYPE_BUFFER                    BIT_U32(22)
 #define FLAG_ERROR_LOGGED                       BIT_U32(23)
 #define FLAG_BLOCKED_FUNCTION_LOGGED            BIT_U32(24)
@@ -651,7 +668,11 @@ static int DetectLuaSetupPrime(DetectEngineCtx *de_ctx, DetectLuaData *ld, const
             continue;
         }
 
-        if (strcmp(k, "packet") == 0) {
+        if (strcmp(k, "ja3") == 0) {
+            ld->flags |= FLAG_LIST_JA3;
+        } else if (strcmp(k, "ja3s") == 0) {
+            ld->flags |= FLAG_LIST_JA3S;
+        } else if (strcmp(k, "packet") == 0) {
             ld->flags |= FLAG_DATATYPE_PACKET;
         } else if (strcmp(k, "payload") == 0) {
             ld->flags |= FLAG_DATATYPE_PAYLOAD;
@@ -758,6 +779,13 @@ static int DetectLuaSetup (DetectEngineCtx *de_ctx, Signature *s, const char *st
         SCLogError("lua failed to set up");
         goto error;
     }
+    if (list == 0) {
+        if (lua->flags & FLAG_LIST_JA3) {
+            list = g_lua_ja3_list_id;
+        } else if (lua->flags & FLAG_LIST_JA3S) {
+            list = g_lua_ja3s_list_id;
+        }
+    }
 
     if (SigMatchAppendSMToList(de_ctx, s, DETECT_LUA, (SigMatchCtx *)lua, list) == NULL) {
         goto error;
index 199c8fcc157f470b483d249168888a091adae94b..5c087044e13aa821d4c5b358d5852ada25b8b404 100644 (file)
@@ -36,7 +36,6 @@
 #include "util-lua.h"
 #include "util-lua-common.h"
 #include "util-lua-http.h"
-#include "util-lua-ja3.h"
 #include "util-lua-tls.h"
 #include "util-lua-smtp.h"
 
@@ -588,7 +587,6 @@ static lua_State *LuaScriptSetup(const char *filename, LogLuaMasterCtx *ctx)
 
     /* register functions common to all */
     LuaRegisterFunctions(luastate);
-    LuaRegisterJa3Functions(luastate);
     LuaRegisterTlsFunctions(luastate);
     LuaRegisterSmtpFunctions(luastate);
 
index c0898e28eafc2c204a9b9950bdcdbba273f4ee2d..1534b649397e30aac0020654c1dbc4f4a84cd5b4 100644 (file)
@@ -29,6 +29,7 @@
 #include "util-lua-hashlib.h"
 #include "util-lua-packetlib.h"
 #include "util-lua-rule.h"
+#include "util-lua-ja3.h"
 
 #include "lauxlib.h"
 
@@ -42,6 +43,7 @@ static const luaL_Reg builtins[] = {
     { "suricata.flowvar", LuaLoadFlowvarLib },
     { "suricata.hashlib", SCLuaLoadHashlib },
     { "suricata.http", SCLuaLoadHttpLib },
+    { "suricata.ja3", SCLuaLoadJa3Lib },
     { "suricata.packet", LuaLoadPacketLib },
     { "suricata.rule", SCLuaLoadRuleLib },
     { "suricata.ssh", SCLuaLoadSshLib },
index b7074ac1c682102043de6cda0624c57eac1749fe..33b0c5bc0be5894f83b4d67597abd78f6a0a0f2a 100644 (file)
  */
 
 #include "suricata-common.h"
-#include "detect.h"
-#include "pkt-var.h"
-#include "conf.h"
-
-#include "threads.h"
-#include "threadvars.h"
-#include "tm-threads.h"
-
-#include "util-print.h"
-#include "util-unittest.h"
-
-#include "util-debug.h"
-
-#include "output.h"
-#include "app-layer.h"
-#include "app-layer-parser.h"
-#include "app-layer-ssl.h"
-#include "util-privs.h"
-#include "util-buffer.h"
-#include "util-proto-name.h"
-#include "util-logopenfile.h"
-#include "util-time.h"
-
-#include "lua.h"
-#include "lualib.h"
-#include "lauxlib.h"
-
+#include "util-lua-ja3.h"
 #include "util-lua.h"
 #include "util-lua-common.h"
-#include "util-lua-ja3.h"
-
-static int Ja3GetHash(lua_State *luastate)
-{
-    if (!(LuaStateNeedProto(luastate, ALPROTO_TLS)))
-        return LuaCallbackError(luastate, "error: protocol is not tls");
-
-    Flow *f = LuaStateGetFlow(luastate);
-    if (f == NULL)
-        return LuaCallbackError(luastate, "internal error: no flow");
-
-    void *state = FlowGetAppState(f);
-    if (state == NULL)
-        return LuaCallbackError(luastate, "error: no app layer state");
+#include "app-layer-ssl.h"
+#include "rust.h"
 
-    SSLState *ssl_state = (SSLState *)state;
+static const char ja3_tx[] = "suricata:ja3:tx";
 
-    if (ssl_state->client_connp.ja3_hash == NULL)
-        return LuaCallbackError(luastate, "error: no JA3 hash");
+struct LuaTx {
+    void *tx; // Quic or TLS Transaction
+    AppProto alproto;
+};
 
-    return LuaPushStringBuffer(luastate,
-                               (uint8_t *)ssl_state->client_connp.ja3_hash,
-                               strlen(ssl_state->client_connp.ja3_hash));
+static int LuaJa3GetTx(lua_State *L)
+{
+    AppProto alproto = ALPROTO_QUIC;
+    if (LuaStateNeedProto(L, ALPROTO_TLS)) {
+        alproto = ALPROTO_TLS;
+    } else if (!(LuaStateNeedProto(L, ALPROTO_QUIC))) {
+        return LuaCallbackError(L, "error: protocol nor tls neither quic");
+    }
+    void *tx = LuaStateGetTX(L);
+    if (tx == NULL) {
+        return LuaCallbackError(L, "error: no tx available");
+    }
+    struct LuaTx *ltx = (struct LuaTx *)lua_newuserdata(L, sizeof(*ltx));
+    if (ltx == NULL) {
+        return LuaCallbackError(L, "error: fail to allocate user data");
+    }
+    ltx->tx = tx;
+    ltx->alproto = alproto;
+
+    luaL_getmetatable(L, ja3_tx);
+    lua_setmetatable(L, -2);
+
+    return 1;
 }
 
-static int Ja3GetString(lua_State *luastate)
+static int LuaJa3TxGetHash(lua_State *L)
 {
-    if (!(LuaStateNeedProto(luastate, ALPROTO_TLS)))
-        return LuaCallbackError(luastate, "error: protocol is not tls");
-
-    Flow *f = LuaStateGetFlow(luastate);
-    if (f == NULL)
-        return LuaCallbackError(luastate, "internal error: no flow");
-
-    void *state = FlowGetAppState(f);
-    if (state == NULL)
-        return LuaCallbackError(luastate, "error: no app layer state");
-
-    SSLState *ssl_state = (SSLState *)state;
-
-    if (ssl_state->client_connp.ja3_str == NULL ||
-            ssl_state->client_connp.ja3_str->data == NULL)
-        return LuaCallbackError(luastate, "error: no JA3 str");
-
-    return LuaPushStringBuffer(luastate,
-                               (uint8_t *)ssl_state->client_connp.ja3_str->data,
-                               ssl_state->client_connp.ja3_str->used);
+    struct LuaTx *ltx = luaL_testudata(L, 1, ja3_tx);
+    if (ltx == NULL) {
+        lua_pushnil(L);
+        return 1;
+    }
+    if (ltx->alproto == ALPROTO_TLS) {
+        SSLState *ssl_state = (SSLState *)ltx->tx;
+        if (ssl_state->client_connp.ja3_hash == NULL) {
+            lua_pushnil(L);
+            return 1;
+        }
+        return LuaPushStringBuffer(L, (uint8_t *)ssl_state->client_connp.ja3_hash,
+                strlen(ssl_state->client_connp.ja3_hash));
+    } // else QUIC {
+    const uint8_t *buf = NULL;
+    uint32_t b_len = 0;
+    if (!SCQuicTxGetJa3(ltx->tx, STREAM_TOSERVER, &buf, &b_len)) {
+        lua_pushnil(L);
+        return 1;
+    }
+    uint8_t ja3_hash[SC_MD5_HEX_LEN + 1];
+    // this adds a final zero
+    SCMd5HashBufferToHex(buf, b_len, (char *)ja3_hash, SC_MD5_HEX_LEN + 1);
+    return LuaPushStringBuffer(L, ja3_hash, SC_MD5_HEX_LEN);
 }
 
-static int Ja3SGetHash(lua_State *luastate)
+static int LuaJa3TxGetString(lua_State *L)
 {
-    if (!(LuaStateNeedProto(luastate, ALPROTO_TLS)))
-        return LuaCallbackError(luastate, "error: protocol is not tls");
-
-    Flow *f = LuaStateGetFlow(luastate);
-    if (f == NULL)
-        return LuaCallbackError(luastate, "internal error: no flow");
-
-    void *state = FlowGetAppState(f);
-    if (state == NULL)
-        return LuaCallbackError(luastate, "error: no app layer state");
-
-    SSLState *ssl_state = (SSLState *)state;
-
-    if (ssl_state->server_connp.ja3_hash == NULL)
-        return LuaCallbackError(luastate, "error: no JA3S hash");
-
-    return LuaPushStringBuffer(luastate,
-                               (uint8_t *)ssl_state->server_connp.ja3_hash,
-                               strlen(ssl_state->server_connp.ja3_hash));
+    struct LuaTx *ltx = luaL_testudata(L, 1, ja3_tx);
+    if (ltx == NULL) {
+        lua_pushnil(L);
+        return 1;
+    }
+    if (ltx->alproto == ALPROTO_TLS) {
+        SSLState *ssl_state = (SSLState *)ltx->tx;
+        if (ssl_state->client_connp.ja3_str == NULL ||
+                ssl_state->client_connp.ja3_str->data == NULL) {
+            lua_pushnil(L);
+            return 1;
+        }
+        return LuaPushStringBuffer(L, (uint8_t *)ssl_state->client_connp.ja3_str->data,
+                ssl_state->client_connp.ja3_str->used);
+    } // else QUIC {
+    const uint8_t *buf = NULL;
+    uint32_t b_len = 0;
+    if (!SCQuicTxGetJa3(ltx->tx, STREAM_TOSERVER, &buf, &b_len)) {
+        lua_pushnil(L);
+        return 1;
+    }
+    return LuaPushStringBuffer(L, buf, b_len);
 }
 
-static int Ja3SGetString(lua_State *luastate)
+static int LuaJa3TxGetServerHash(lua_State *L)
 {
-    if (!(LuaStateNeedProto(luastate, ALPROTO_TLS)))
-        return LuaCallbackError(luastate, "error: protocol is not tls");
-
-    Flow *f = LuaStateGetFlow(luastate);
-    if (f == NULL)
-        return LuaCallbackError(luastate, "internal error: no flow");
-
-    void *state = FlowGetAppState(f);
-    if (state == NULL)
-        return LuaCallbackError(luastate, "error: no app layer state");
-
-    SSLState *ssl_state = (SSLState *)state;
-
-    if (ssl_state->server_connp.ja3_str == NULL ||
-            ssl_state->server_connp.ja3_str->data == NULL)
-        return LuaCallbackError(luastate, "error: no JA3S str");
-
-    return LuaPushStringBuffer(luastate,
-                               (uint8_t *)ssl_state->server_connp.ja3_str->data,
-                               ssl_state->server_connp.ja3_str->used);
+    struct LuaTx *ltx = luaL_testudata(L, 1, ja3_tx);
+    if (ltx == NULL) {
+        lua_pushnil(L);
+        return 1;
+    }
+    if (ltx->alproto == ALPROTO_TLS) {
+        SSLState *ssl_state = (SSLState *)ltx->tx;
+        if (ssl_state->server_connp.ja3_hash == NULL) {
+            lua_pushnil(L);
+            return 1;
+        }
+        return LuaPushStringBuffer(L, (uint8_t *)ssl_state->server_connp.ja3_hash,
+                strlen(ssl_state->server_connp.ja3_hash));
+    } // else QUIC {
+    const uint8_t *buf = NULL;
+    uint32_t b_len = 0;
+    if (!SCQuicTxGetJa3(ltx->tx, STREAM_TOCLIENT, &buf, &b_len)) {
+        lua_pushnil(L);
+        return 1;
+    }
+    uint8_t ja3_hash[SC_MD5_HEX_LEN + 1];
+    // this adds a final zero
+    SCMd5HashBufferToHex(buf, b_len, (char *)ja3_hash, SC_MD5_HEX_LEN + 1);
+    return LuaPushStringBuffer(L, ja3_hash, SC_MD5_HEX_LEN);
 }
 
-/** *\brief Register JA3 Lua extensions */
-int LuaRegisterJa3Functions(lua_State *luastate)
+static int LuaJa3TxGetServerString(lua_State *L)
 {
-    lua_pushcfunction(luastate, Ja3GetHash);
-    lua_setglobal(luastate, "Ja3GetHash");
+    struct LuaTx *ltx = luaL_testudata(L, 1, ja3_tx);
+    if (ltx == NULL) {
+        lua_pushnil(L);
+        return 1;
+    }
+    if (ltx->alproto == ALPROTO_TLS) {
+        SSLState *ssl_state = (SSLState *)ltx->tx;
+        if (ssl_state->server_connp.ja3_str == NULL ||
+                ssl_state->server_connp.ja3_str->data == NULL) {
+            lua_pushnil(L);
+            return 1;
+        }
+        return LuaPushStringBuffer(L, (uint8_t *)ssl_state->server_connp.ja3_str->data,
+                ssl_state->server_connp.ja3_str->used);
+    } // else QUIC {
+    const uint8_t *buf = NULL;
+    uint32_t b_len = 0;
+    if (!SCQuicTxGetJa3(ltx->tx, STREAM_TOCLIENT, &buf, &b_len)) {
+        lua_pushnil(L);
+        return 1;
+    }
+    return LuaPushStringBuffer(L, buf, b_len);
+}
 
-    lua_pushcfunction(luastate, Ja3GetString);
-    lua_setglobal(luastate, "Ja3GetString");
+static const struct luaL_Reg txlib[] = {
+    // clang-format off
+    { "ja3_get_hash", LuaJa3TxGetHash },
+    { "ja3_get_string", LuaJa3TxGetString },
+    { "ja3s_get_hash", LuaJa3TxGetServerHash },
+    { "ja3s_get_string", LuaJa3TxGetServerString },
+    { NULL, NULL, }
+    // clang-format on
+};
+
+static int LuaJa3Enable(lua_State *L)
+{
+    SSLEnableJA3();
+    return 1;
+}
 
-    lua_pushcfunction(luastate, Ja3SGetHash);
-    lua_setglobal(luastate, "Ja3SGetHash");
+static const struct luaL_Reg ja3lib[] = {
+    // clang-format off
+    { "get_tx", LuaJa3GetTx },
+    { "enable_ja3", LuaJa3Enable },
+    { NULL, NULL,},
+    // clang-format on
+};
 
-    lua_pushcfunction(luastate, Ja3SGetString);
-    lua_setglobal(luastate, "Ja3SGetString");
+int SCLuaLoadJa3Lib(lua_State *L)
+{
+    luaL_newmetatable(L, ja3_tx);
+    lua_pushvalue(L, -1);
+    lua_setfield(L, -2, "__index");
+    luaL_setfuncs(L, txlib, 0);
 
-    return 0;
+    luaL_newlib(L, ja3lib);
+    return 1;
 }
index 0bbbb666b2b781ba52f50fb032e17485bfd7d832..a5b6cbe8d62c356f685eb45a7f866765adb537fb 100644 (file)
@@ -24,6 +24,8 @@
 #ifndef SURICATA_UTIL_LUA_JA3_H
 #define SURICATA_UTIL_LUA_JA3_H
 
-int LuaRegisterJa3Functions(lua_State *luastate);
+#include "lua.h"
+
+int SCLuaLoadJa3Lib(lua_State *L);
 
 #endif /* SURICATA_UTIL_LUA_JA3_H */