Skip to content

Commit 50434f8

Browse files
committed
ntp: expose logged fields to lua
This includes: - version - mode - stratum - reference_id Ticket: OISF#8533 (cherry picked from commit 899e9f0)
1 parent 207f33e commit 50434f8

9 files changed

Lines changed: 274 additions & 0 deletions

File tree

doc/userguide/lua/libs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ environment without access to additional modules.
2020
hashlib
2121
http
2222
log
23+
ntp
2324
packetlib
2425
rule
2526
smtp

doc/userguide/lua/libs/ntp.rst

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
NTP
2+
###
3+
4+
NTP transaction details are exposed to Lua scripts with the
5+
``suricata.ntp`` library, for example::
6+
7+
local ntp = require("suricata.ntp")
8+
9+
Setup
10+
*****
11+
12+
If your purpose is to create a logging script, initialize the buffer as:
13+
14+
::
15+
16+
function init (args)
17+
local needs = {}
18+
needs["protocol"] = "ntp"
19+
return needs
20+
end
21+
22+
Transaction
23+
***********
24+
25+
NTP is transaction based, and the current transaction must be obtained
26+
before use::
27+
28+
local tx, err = ntp.get_tx()
29+
if tx == nil then
30+
print(err)
31+
end
32+
33+
All other functions are methods on the transaction table.
34+
35+
Transaction Methods
36+
*******************
37+
38+
``version()``
39+
=============
40+
41+
Get the NTP version as an integer.
42+
43+
``mode()``
44+
==========
45+
46+
Get the NTP mode as an integer.
47+
48+
``stratum()``
49+
=============
50+
51+
Get the NTP stratum as an integer.
52+
53+
``reference_id()``
54+
==================
55+
56+
Get the NTP reference ID as a raw 4-byte binary string.
57+
58+
Example::
59+
60+
local tx, err = ntp.get_tx()
61+
local ref_id = tx:reference_id()
62+
if ref_id == "\x4c\x4f\x43\x4c" then
63+
-- ref_id matches "LOCL"
64+
end
65+
66+
-- If looking for a specific printable string, this is also valid
67+
if ref_id == "LOCL" then
68+
...
69+
end

rust/src/ntp/lua.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/* Copyright (C) 2026 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+
use std::os::raw::c_int;
19+
20+
use super::ntp::NTPTransaction;
21+
use crate::lua::*;
22+
23+
#[no_mangle]
24+
pub extern "C" fn SCNtpLuaGetVersion(clua: &mut CLuaState, tx: &mut NTPTransaction) -> c_int {
25+
let lua = LuaState { lua: clua };
26+
lua.pushinteger(tx.version as i64);
27+
1
28+
}
29+
30+
#[no_mangle]
31+
pub extern "C" fn SCNtpLuaGetMode(clua: &mut CLuaState, tx: &mut NTPTransaction) -> c_int {
32+
let lua = LuaState { lua: clua };
33+
lua.pushinteger(tx.mode as i64);
34+
1
35+
}
36+
37+
#[no_mangle]
38+
pub extern "C" fn SCNtpLuaGetStratum(clua: &mut CLuaState, tx: &mut NTPTransaction) -> c_int {
39+
let lua = LuaState { lua: clua };
40+
lua.pushinteger(tx.stratum as i64);
41+
1
42+
}
43+
44+
#[no_mangle]
45+
pub extern "C" fn SCNtpLuaGetReferenceId(clua: &mut CLuaState, tx: &mut NTPTransaction) -> c_int {
46+
let lua = LuaState { lua: clua };
47+
lua.pushbytes(&tx.reference_id);
48+
1
49+
}

rust/src/ntp/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@
2121

2222
pub mod detect;
2323
pub mod log;
24+
pub mod lua;
2425
pub mod ntp;

src/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,7 @@ noinst_HEADERS = \
551551
util-lua-http.h \
552552
util-lua-ja3.h \
553553
util-lua-log.h \
554+
util-lua-ntp.h \
554555
util-lua-packetlib.h \
555556
util-lua-rule.h \
556557
util-lua-sandbox.h \
@@ -1134,6 +1135,7 @@ libsuricata_c_a_SOURCES = \
11341135
util-lua-http.c \
11351136
util-lua-ja3.c \
11361137
util-lua-log.c \
1138+
util-lua-ntp.c \
11371139
util-lua-packetlib.c \
11381140
util-lua-rule.c \
11391141
util-lua-sandbox.c \

src/output-lua.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,8 @@ static int LuaScriptInit(const char *filename, LogLuaScriptOptions *options, Log
524524
options->alproto = ALPROTO_SSH;
525525
else if (strcmp(k,"protocol") == 0 && strcmp(v, "smtp") == 0)
526526
options->alproto = ALPROTO_SMTP;
527+
else if (strcmp(k, "protocol") == 0 && strcmp(v, "ntp") == 0)
528+
options->alproto = ALPROTO_NTP;
527529
else if (strcmp(k, "type") == 0 && strcmp(v, "packet") == 0)
528530
options->packet = 1;
529531
else if (strcmp(k, "filter") == 0 && strcmp(v, "alerts") == 0)
@@ -808,6 +810,12 @@ static OutputInitResult OutputLuaLogInit(SCConfNode *conf)
808810
om->ts_log_progress = -1;
809811
om->tc_log_progress = -1;
810812
SCAppLayerParserRegisterLogger(IPPROTO_TCP, ALPROTO_SMTP);
813+
} else if (opts.alproto == ALPROTO_NTP) {
814+
om->TxLogFunc = LuaTxLogger;
815+
om->alproto = ALPROTO_NTP;
816+
om->ts_log_progress = -1;
817+
om->tc_log_progress = -1;
818+
SCAppLayerParserRegisterLogger(IPPROTO_UDP, ALPROTO_NTP);
811819
} else if (opts.packet && opts.alerts) {
812820
om->PacketLogFunc = LuaPacketLoggerAlerts;
813821
om->PacketConditionFunc = LuaPacketConditionAlerts;

src/util-lua-builtins.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "util-lua-ja3.h"
3737
#include "util-lua-filelib.h"
3838
#include "util-lua-log.h"
39+
#include "util-lua-ntp.h"
3940
#include "util-lua-util.h"
4041

4142
#include "lauxlib.h"
@@ -55,6 +56,7 @@ static const luaL_Reg builtins[] = {
5556
{ "suricata.http", SCLuaLoadHttpLib },
5657
{ "suricata.ja3", SCLuaLoadJa3Lib },
5758
{ "suricata.log", SCLuaLoadLogLib },
59+
{ "suricata.ntp", SCLuaLoadNtpLib },
5860
{ "suricata.packet", LuaLoadPacketLib },
5961
{ "suricata.rule", SCLuaLoadRuleLib },
6062
{ "suricata.smtp", SCLuaLoadSmtpLib },

src/util-lua-ntp.c

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/* Copyright (C) 2026 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 "util-lua-ntp.h"
20+
#include "util-lua.h"
21+
#include "util-lua-common.h"
22+
#include "rust.h"
23+
24+
static const char ntp_tx[] = "suricata:ntp:tx";
25+
26+
struct LuaTx {
27+
NTPTransaction *tx;
28+
};
29+
30+
static int LuaNtpGetTx(lua_State *L)
31+
{
32+
if (!(LuaStateNeedProto(L, ALPROTO_NTP))) {
33+
return LuaCallbackError(L, "error: protocol not ntp");
34+
}
35+
NTPTransaction *tx = LuaStateGetTX(L);
36+
if (tx == NULL) {
37+
return LuaCallbackError(L, "error: no tx available");
38+
}
39+
struct LuaTx *ltx = (struct LuaTx *)lua_newuserdata(L, sizeof(*ltx));
40+
if (ltx == NULL) {
41+
return LuaCallbackError(L, "error: fail to allocate user data");
42+
}
43+
ltx->tx = tx;
44+
45+
luaL_getmetatable(L, ntp_tx);
46+
lua_setmetatable(L, -2);
47+
48+
return 1;
49+
}
50+
51+
static int LuaNtpTxGetVersion(lua_State *L)
52+
{
53+
struct LuaTx *tx = luaL_testudata(L, 1, ntp_tx);
54+
if (tx == NULL) {
55+
lua_pushnil(L);
56+
return 1;
57+
}
58+
return SCNtpLuaGetVersion(L, tx->tx);
59+
}
60+
61+
static int LuaNtpTxGetMode(lua_State *L)
62+
{
63+
struct LuaTx *tx = luaL_testudata(L, 1, ntp_tx);
64+
if (tx == NULL) {
65+
lua_pushnil(L);
66+
return 1;
67+
}
68+
return SCNtpLuaGetMode(L, tx->tx);
69+
}
70+
71+
static int LuaNtpTxGetStratum(lua_State *L)
72+
{
73+
struct LuaTx *tx = luaL_testudata(L, 1, ntp_tx);
74+
if (tx == NULL) {
75+
lua_pushnil(L);
76+
return 1;
77+
}
78+
return SCNtpLuaGetStratum(L, tx->tx);
79+
}
80+
81+
static int LuaNtpTxGetReferenceId(lua_State *L)
82+
{
83+
struct LuaTx *tx = luaL_testudata(L, 1, ntp_tx);
84+
if (tx == NULL) {
85+
lua_pushnil(L);
86+
return 1;
87+
}
88+
return SCNtpLuaGetReferenceId(L, tx->tx);
89+
}
90+
91+
static const struct luaL_Reg txlib[] = {
92+
// clang-format off
93+
{ "mode", LuaNtpTxGetMode },
94+
{ "reference_id", LuaNtpTxGetReferenceId },
95+
{ "stratum", LuaNtpTxGetStratum },
96+
{ "version", LuaNtpTxGetVersion },
97+
{ NULL, NULL, }
98+
// clang-format on
99+
};
100+
101+
static const struct luaL_Reg ntplib[] = {
102+
// clang-format off
103+
{ "get_tx", LuaNtpGetTx },
104+
{ NULL, NULL,}
105+
// clang-format on
106+
};
107+
108+
int SCLuaLoadNtpLib(lua_State *L)
109+
{
110+
luaL_newmetatable(L, ntp_tx);
111+
lua_pushvalue(L, -1);
112+
lua_setfield(L, -2, "__index");
113+
luaL_setfuncs(L, txlib, 0);
114+
115+
luaL_newlib(L, ntplib);
116+
return 1;
117+
}

src/util-lua-ntp.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/* Copyright (C) 2026 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+
#ifndef SURICATA_UTIL_LUA_NTP_H
19+
#define SURICATA_UTIL_LUA_NTP_H
20+
21+
#include "lua.h"
22+
23+
int SCLuaLoadNtpLib(lua_State *L);
24+
25+
#endif /* SURICATA_UTIL_LUA_NTP_H */

0 commit comments

Comments
 (0)