hashlib
http
packetlib
+ rule
--- /dev/null
+Rule
+====
+
+Rule details for an alert are exposed to Lua scripts with the
+``suricata.rule`` library, for example::
+
+ local rule = require("suricata.rule")
+
+Rule Setup
+----------
+
+For use in Suricata Lua rules, no additional setup is required.
+
+Output Setup
+------------
+
+For use in Suricata Lua output scripts, some additional setup is
+required::
+
+ function init(args)
+ return {
+ type = "packet",
+ filter = "alerts",
+ }
+ end
+
+Getting a Rule Instance
+-----------------------
+
+To obtain a rule object, use the ``get_rule()`` function on the
+``rule`` library::
+
+ local sig = rule.get_rule()
+
+Rule Methods
+------------
+
+``action()``
+^^^^^^^^^^^^
+
+Returns the action of the rule, for example: `alert`, `pass`.
+
+``class_description()``
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Returns the classification description.
+
+``gid()``
+^^^^^^^^^
+
+Returns the generator ID of the rule.
+
+``rev()``
+^^^^^^^^^
+
+Returns the revision of the rule.
+
+``msg()``
+^^^^^^^^^
+
+Returns the rule message (``msg``).
+
+``priority``
+^^^^^^^^^^^^
+
+Returns the priority of the rule as a number.
+
+``sid()``
+^^^^^^^^^
+
+Returns the signature ID of the rule.
returns state (string), stored (bool)
-Alerts
-------
-
-Alerts are a subset of the 'packet' logger:
-
-::
-
- function init (args)
- local needs = {}
- needs["type"] = "packet"
- needs["filter"] = "alerts"
- return needs
- end
-
-SCRuleIds
-~~~~~~~~~
-
-::
-
- sid, rev, gid = SCRuleIds()
-
-SCRuleAction
-~~~~~~~~~~~~
-
-::
-
- action = SCRuleAction()
-
-returns one of 'pass', 'reject', 'drop' or 'alert'
-
-SCRuleMsg
-~~~~~~~~~
-
-::
-
- msg = SCRuleMsg()
-
-SCRuleClass
-~~~~~~~~~~~
-
-::
-
-
- class, prio = SCRuleClass()
-
Streaming Data
--------------
util-lua-http.h \
util-lua-ja3.h \
util-lua-packetlib.h \
+ util-lua-rule.h \
util-lua-sandbox.h \
util-lua-smtp.h \
util-lua-ssh.h \
util-lua-http.c \
util-lua-ja3.c \
util-lua-packetlib.c \
+ util-lua-rule.c \
util-lua-sandbox.c \
util-lua-smtp.c \
util-lua-ssh.c \
#include "util-lua-flowlib.h"
#include "util-lua-hashlib.h"
#include "util-lua-packetlib.h"
+#include "util-lua-rule.h"
#include "lauxlib.h"
{ "suricata.hashlib", SCLuaLoadHashlib },
{ "suricata.http", SCLuaLoadHttpLib },
{ "suricata.packet", LuaLoadPacketLib },
+ { "suricata.rule", SCLuaLoadRuleLib },
{ NULL, NULL },
};
return LuaCallbackStreamingBufferPushToStack(luastate, b);
}
-/** \internal
- * \brief fill lua stack with signature info
- * \param luastate the lua state
- * \param s pointer to signature struct
- * \retval cnt number of data items placed on the stack
- *
- * Places: sid (number), rev (number), gid (number)
- */
-static int LuaCallbackRuleIdsPushToStackFromSignature(lua_State *luastate, const Signature *s)
-{
- lua_pushinteger(luastate, s->id);
- lua_pushinteger(luastate, s->rev);
- lua_pushinteger(luastate, s->gid);
- return 3;
-}
-
-/** \internal
- * \brief Wrapper for getting tuple info into a lua script
- * \retval cnt number of items placed on the stack
- *
- * Info is pulled from PacketAlert if it exists in lua registry (true for logging scripts)
- * otherwise pulled from Signature in lua registry (for match scripts)
- */
-static int LuaCallbackRuleIds(lua_State *luastate)
-{
- const Signature *s = NULL;
- const PacketAlert *pa = LuaStateGetPacketAlert(luastate);
- if (pa != NULL) {
- s = pa->s;
- } else {
- s = LuaStateGetSignature(luastate);
- if (s == NULL)
- return LuaCallbackError(luastate, "internal error: no packet alert or signature");
- }
- return LuaCallbackRuleIdsPushToStackFromSignature(luastate, s);
-}
-
-/** \internal
- * \brief fill lua stack with signature info
- * \param luastate the lua state
- * \param s pointer to signature struct
- * \retval cnt number of data items placed on the stack
- *
- * Places: action (string)
- */
-static int LuaCallbackRuleActionPushToStackFromSignature(lua_State *luastate, const Signature *s)
-{
- const char *action = "";
- if (s->action & ACTION_PASS) {
- action = "pass";
- } else if ((s->action & ACTION_REJECT) || (s->action & ACTION_REJECT_BOTH) ||
- (s->action & ACTION_REJECT_DST)) {
- action = "reject";
- } else if (s->action & ACTION_DROP) {
- action = "drop";
- } else if (s->action & ACTION_ALERT) {
- action = "alert";
- }
- lua_pushstring(luastate, action);
- return 1;
-}
-
-/** \internal
- * \brief Wrapper for getting tuple info into a lua script
- * \retval cnt number of items placed on the stack
- *
- * Info is pulled from PacketAlert if it exists in lua registry (true for logging scripts)
- * otherwise pulled from Signature in lua registry (for match scripts)
- */
-static int LuaCallbackRuleAction(lua_State *luastate)
-{
- const Signature *s = NULL;
- const PacketAlert *pa = LuaStateGetPacketAlert(luastate);
- if (pa != NULL) {
- s = pa->s;
- } else {
- s = LuaStateGetSignature(luastate);
- if (s == NULL)
- return LuaCallbackError(luastate, "internal error: no packet alert or signature");
- }
- return LuaCallbackRuleActionPushToStackFromSignature(luastate, s);
-}
-
-/** \internal
- * \brief fill lua stack with signature info
- * \param luastate the lua state
- * \param s pointer to signature struct
- * \retval cnt number of data items placed on the stack
- *
- * Places: msg (string)
- */
-static int LuaCallbackRuleMsgPushToStackFromSignature(lua_State *luastate, const Signature *s)
-{
- lua_pushstring(luastate, s->msg);
- return 1;
-}
-
-/** \internal
- * \brief Wrapper for getting tuple info into a lua script
- * \retval cnt number of items placed on the stack
- *
- * Info is pulled from PacketAlert if it exists in lua registry (true for logging scripts)
- * otherwise pulled from Signature in lua registry (for match scripts)
- */
-static int LuaCallbackRuleMsg(lua_State *luastate)
-{
- const Signature *s = NULL;
- const PacketAlert *pa = LuaStateGetPacketAlert(luastate);
- if (pa != NULL) {
- s = pa->s;
- } else {
- s = LuaStateGetSignature(luastate);
- if (s == NULL)
- return LuaCallbackError(luastate, "internal error: no packet alert or signature");
- }
- return LuaCallbackRuleMsgPushToStackFromSignature(luastate, s);
-}
-
-/** \internal
- * \brief fill lua stack with signature info
- * \param luastate the lua state
- * \param s pointer to signature struct
- * \retval cnt number of data items placed on the stack
- *
- * Places: class (string), prio (number)
- */
-static int LuaCallbackRuleClassPushToStackFromSignature(lua_State *luastate, const Signature *s)
-{
- lua_pushstring(luastate, s->class_msg);
- lua_pushinteger(luastate, s->prio);
- return 2;
-}
-
-/** \internal
- * \brief Wrapper for getting tuple info into a lua script
- * \retval cnt number of items placed on the stack
- *
- * Info is pulled from PacketAlert if it exists in lua registry (true for logging scripts)
- * otherwise pulled from Signature in lua registry (for match scripts)
- */
-static int LuaCallbackRuleClass(lua_State *luastate)
-{
- const Signature *s = NULL;
- const PacketAlert *pa = LuaStateGetPacketAlert(luastate);
- if (pa != NULL) {
- s = pa->s;
- } else {
- s = LuaStateGetSignature(luastate);
- if (s == NULL)
- return LuaCallbackError(luastate, "internal error: no packet alert or signature");
- }
- return LuaCallbackRuleClassPushToStackFromSignature(luastate, s);
-}
-
static int LuaCallbackLogPath(lua_State *luastate)
{
const char *ld = SCConfigGetLogDirectory();
lua_pushcfunction(luastate, LuaCallbackLogError);
lua_setglobal(luastate, "SCLogError");
-
- lua_pushcfunction(luastate, LuaCallbackRuleIds);
- lua_setglobal(luastate, "SCRuleIds");
- lua_pushcfunction(luastate, LuaCallbackRuleAction);
- lua_setglobal(luastate, "SCRuleAction");
- lua_pushcfunction(luastate, LuaCallbackRuleMsg);
- lua_setglobal(luastate, "SCRuleMsg");
- lua_pushcfunction(luastate, LuaCallbackRuleClass);
- lua_setglobal(luastate, "SCRuleClass");
-
lua_pushcfunction(luastate, LuaCallbackFileInfo);
lua_setglobal(luastate, "SCFileInfo");
lua_pushcfunction(luastate, LuaCallbackFileState);
--- /dev/null
+/* Copyright (C) 2025 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
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include "suricata-common.h"
+#include "action-globals.h"
+#include "app-layer.h"
+#include "util-lua-rule.h"
+#include "util-lua-common.h"
+#include "util-lua.h"
+
+#include "lauxlib.h"
+
+static const char suricata_rule_mt[] = "suricata:rule:mt";
+
+static int LuaRuleGetRule(lua_State *L)
+{
+ const PacketAlert *pa = LuaStateGetPacketAlert(L);
+ const Signature *s = NULL;
+ if (pa != NULL) {
+ s = pa->s;
+ } else {
+ s = LuaStateGetSignature(L);
+ }
+ if (s == NULL) {
+ return LuaCallbackError(L, "internal error: no packet alert or signature");
+ }
+
+ void **p = lua_newuserdata(L, sizeof(*p));
+ if (p == NULL) {
+ return LuaCallbackError(L, "error: failed to allocate user data");
+ }
+ *p = (void *)s;
+
+ luaL_getmetatable(L, suricata_rule_mt);
+ lua_setmetatable(L, -2);
+
+ return 1;
+}
+
+static int LuaRuleGetSid(lua_State *L)
+{
+ void **data = luaL_testudata(L, 1, suricata_rule_mt);
+ if (data == NULL) {
+ lua_pushnil(L);
+ return 1;
+ }
+ const Signature *s = *data;
+ lua_pushinteger(L, s->id);
+ return 1;
+}
+
+static int LuaRuleGetGid(lua_State *L)
+{
+ void **data = luaL_testudata(L, 1, suricata_rule_mt);
+ if (data == NULL) {
+ lua_pushnil(L);
+ return 1;
+ }
+ const Signature *s = *data;
+ lua_pushinteger(L, s->gid);
+ return 1;
+}
+
+static int LuaRuleGetRev(lua_State *L)
+{
+ void **data = luaL_testudata(L, 1, suricata_rule_mt);
+ if (data == NULL) {
+ lua_pushnil(L);
+ return 1;
+ }
+ const Signature *s = *data;
+ lua_pushinteger(L, s->rev);
+ return 1;
+}
+
+static int LuaRuleGetAction(lua_State *L)
+{
+ void **data = luaL_testudata(L, 1, suricata_rule_mt);
+ if (data == NULL) {
+ lua_pushnil(L);
+ return 1;
+ }
+ const Signature *s = *data;
+
+ const char *action = "";
+ if (s->action & ACTION_PASS) {
+ action = "pass";
+ } else if ((s->action & ACTION_REJECT) || (s->action & ACTION_REJECT_BOTH) ||
+ (s->action & ACTION_REJECT_DST)) {
+ action = "reject";
+ } else if (s->action & ACTION_DROP) {
+ action = "drop";
+ } else if (s->action & ACTION_ALERT) {
+ action = "alert";
+ }
+ lua_pushstring(L, action);
+ return 1;
+}
+
+static int LuaRuleGetMsg(lua_State *L)
+{
+ void **data = luaL_testudata(L, 1, suricata_rule_mt);
+ if (data == NULL) {
+ lua_pushnil(L);
+ return 1;
+ }
+ const Signature *s = *data;
+ lua_pushstring(L, s->msg);
+ return 1;
+}
+
+static int LuaRuleGetClassDescription(lua_State *L)
+{
+ void **data = luaL_testudata(L, 1, suricata_rule_mt);
+ if (data == NULL) {
+ lua_pushnil(L);
+ return 1;
+ }
+ const Signature *s = *data;
+ lua_pushstring(L, s->class_msg);
+ return 1;
+}
+
+static int LuaRuleGetPriority(lua_State *L)
+{
+ void **data = luaL_testudata(L, 1, suricata_rule_mt);
+ if (data == NULL) {
+ lua_pushnil(L);
+ return 1;
+ }
+ const Signature *s = *data;
+ lua_pushinteger(L, s->prio);
+ return 1;
+}
+
+static const struct luaL_Reg rulemt[] = {
+ // clang-format off
+ { "action", LuaRuleGetAction },
+ { "class_description", LuaRuleGetClassDescription, },
+ { "gid", LuaRuleGetGid, },
+ { "msg", LuaRuleGetMsg },
+ { "priority", LuaRuleGetPriority },
+ { "rev", LuaRuleGetRev, },
+ { "sid", LuaRuleGetSid, },
+ { NULL, NULL },
+ // clang-format on
+};
+
+static const struct luaL_Reg rulelib[] = {
+ // clang-format off
+ { "get_rule", LuaRuleGetRule, },
+ { NULL, NULL, }
+ // clang-format on
+};
+
+int SCLuaLoadRuleLib(lua_State *L)
+{
+ luaL_newmetatable(L, suricata_rule_mt);
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -2, "__index");
+ luaL_setfuncs(L, rulemt, 0);
+
+ luaL_newlib(L, rulelib);
+
+ return 1;
+}
--- /dev/null
+/* Copyright (C) 2025 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
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef SURICATA_UTIL_LUA_RULE_H
+#define SURICATA_UTIL_LUA_RULE_H
+
+#include "lua.h"
+
+int SCLuaLoadRuleLib(lua_State *L);
+
+#endif /* SURICATA_UTIL_LUA_RULE_H */