lua: convert ssh function into suricata.ssh lib

Ticket: 7607
pull/13092/head
Philippe Antoine 1 year ago committed by Victor Julien
parent fcac063cfe
commit 76d7ab5418

@ -15,3 +15,4 @@ environment without access to additional modules.
http
packetlib
rule
ssh

@ -0,0 +1,89 @@
SSH
---
SSH transaction details are exposes to Lua scripts with the
``suricata.ssh`` library, For example::
local ssh = require("suricata.ssh")
Setup
^^^^^
If your purpose is to create a logging script, initialize the buffer as:
::
function init (args)
local needs = {}
return needs
end
If you are going to use the script for rule matching, choose one of
the available SSH buffers listed in :ref:`lua-detection` and follow
the pattern:
::
function init (args)
local needs = {}
return needs
end
Transaction
~~~~~~~~~~~
SSH is transaction based, and the current transaction must be obtained before use::
local tx, err = ssh.get_tx()
if tx == err then
print(err)
end
All other functions are methods on the transaction table.
Transaction Methods
~~~~~~~~~~~~~~~~~~~
``server_proto()``
^^^^^^^^^^^^^^^^^^
Get the ``server_proto`` value as a string.
Example::
local tx = ssh.get_tx()
local proto = tx:server_proto();
print (proto)
``client_proto()``
^^^^^^^^^^^^^^^^^^
Get the ``client_proto`` value as a string.
Example::
local tx = ssh.get_tx()
local proto = tx:client_proto();
print (proto)
``server_software()``
^^^^^^^^^^^^^^^^^^^^^
Get the ``server_software`` value as a string.
Example::
local tx = ssh.get_tx()
local software = tx:server_software();
print (software)
``client_software()``
^^^^^^^^^^^^^^^^^^^^^
Get the ``client_software`` value as a string.
Example::
local tx = ssh.get_tx()
local software = tx:client_software();
print (software)

@ -481,71 +481,6 @@ Initialize with:
return needs
end
SshGetServerProtoVersion
~~~~~~~~~~~~~~~~~~~~~~~~
Get SSH protocol version used by the server through SshGetServerProtoVersion.
Example:
::
function log (args)
version = SshGetServerProtoVersion()
if version == nil then
return 0
end
end
SshGetServerSoftwareVersion
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Get SSH software used by the server through SshGetServerSoftwareVersion.
Example:
::
function log (args)
software = SshGetServerSoftwareVersion()
if software == nil then
return 0
end
end
SshGetClientProtoVersion
~~~~~~~~~~~~~~~~~~~~~~~~
Get SSH protocol version used by the client through SshGetClientProtoVersion.
Example:
::
function log (args)
version = SshGetClientProtoVersion()
if version == nil then
return 0
end
end
SshGetClientSoftwareVersion
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Get SSH software used by the client through SshGetClientSoftwareVersion.
Example:
::
function log (args)
software = SshGetClientSoftwareVersion()
if software == nil then
return 0
end
end
HasshGet
~~~~~~~~

@ -42,7 +42,6 @@
#include "util-lua-http.h"
#include "util-lua-ja3.h"
#include "util-lua-tls.h"
#include "util-lua-ssh.h"
#include "util-lua-hassh.h"
#include "util-lua-smtp.h"
#include "util-lua-dnp3.h"
@ -551,7 +550,6 @@ int LuaRegisterExtensions(lua_State *lua_state)
LuaRegisterFunctions(lua_state);
LuaRegisterJa3Functions(lua_state);
LuaRegisterTlsFunctions(lua_state);
LuaRegisterSshFunctions(lua_state);
LuaRegisterHasshFunctions(lua_state);
LuaRegisterSmtpFunctions(lua_state);
return 0;

@ -38,7 +38,6 @@
#include "util-lua-http.h"
#include "util-lua-ja3.h"
#include "util-lua-tls.h"
#include "util-lua-ssh.h"
#include "util-lua-hassh.h"
#include "util-lua-smtp.h"
@ -592,7 +591,6 @@ static lua_State *LuaScriptSetup(const char *filename, LogLuaMasterCtx *ctx)
LuaRegisterFunctions(luastate);
LuaRegisterJa3Functions(luastate);
LuaRegisterTlsFunctions(luastate);
LuaRegisterSshFunctions(luastate);
LuaRegisterHasshFunctions(luastate);
LuaRegisterSmtpFunctions(luastate);

@ -22,6 +22,7 @@
#include "util-lua-dnp3.h"
#include "util-lua-http.h"
#include "util-lua-dns.h"
#include "util-lua-ssh.h"
#include "util-lua-flowlib.h"
#include "util-lua-hashlib.h"
#include "util-lua-packetlib.h"
@ -39,6 +40,7 @@ static const luaL_Reg builtins[] = {
{ "suricata.http", SCLuaLoadHttpLib },
{ "suricata.packet", LuaLoadPacketLib },
{ "suricata.rule", SCLuaLoadRuleLib },
{ "suricata.ssh", SCLuaLoadSshLib },
{ NULL, NULL },
};

@ -24,192 +24,115 @@
*/
#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-ssh.h"
#include "util-privs.h"
#include "util-buffer.h"
#include "util-proto-name.h"
#include "util-logopenfile.h"
#include "util-time.h"
#include "rust.h"
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include "util-lua-ssh.h"
#include "util-lua.h"
#include "util-lua-common.h"
#include "util-lua-ssh.h"
static int GetServerProtoVersion(lua_State *luastate, const Flow *f)
{
void *state = FlowGetAppState(f);
if (state == NULL)
return LuaCallbackError(luastate, "error: no app layer state");
const uint8_t *protocol = NULL;
uint32_t b_len = 0;
#include "rust.h"
void *tx = SCSshStateGetTx(state, 0);
if (SCSshTxGetProtocol(tx, &protocol, &b_len, STREAM_TOCLIENT) != 1)
return LuaCallbackError(luastate, "error: no server proto version");
if (protocol == NULL || b_len == 0) {
return LuaCallbackError(luastate, "error: no server proto version");
}
// #define SSH_MT "suricata:ssh:tx"
static const char ssh_tx[] = "suricata:ssh:tx";
return LuaPushStringBuffer(luastate, protocol, b_len);
}
struct LuaTx {
void *tx; // SSHTransaction
};
static int SshGetServerProtoVersion(lua_State *luastate)
static int LuaSshGetTx(lua_State *L)
{
int r;
if (!(LuaStateNeedProto(luastate, ALPROTO_SSH)))
return LuaCallbackError(luastate, "error: protocol not ssh");
Flow *f = LuaStateGetFlow(luastate);
if (f == NULL)
return LuaCallbackError(luastate, "internal error: no flow");
if (!(LuaStateNeedProto(L, ALPROTO_SSH))) {
return LuaCallbackError(L, "error: protocol not ssh");
}
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;
r = GetServerProtoVersion(luastate, f);
luaL_getmetatable(L, ssh_tx);
lua_setmetatable(L, -2);
return r;
return 1;
}
static int GetServerSoftwareVersion(lua_State *luastate, const Flow *f)
static int LuaSshTxGetProto(lua_State *L, uint8_t flags)
{
void *state = FlowGetAppState(f);
if (state == NULL)
return LuaCallbackError(luastate, "error: no app layer state");
const uint8_t *software = NULL;
const uint8_t *buf = NULL;
uint32_t b_len = 0;
void *tx = SCSshStateGetTx(state, 0);
if (SCSshTxGetSoftware(tx, &software, &b_len, STREAM_TOCLIENT) != 1)
return LuaCallbackError(luastate, "error: no server software version");
if (software == NULL || b_len == 0) {
return LuaCallbackError(luastate, "error: no server software version");
struct LuaTx *ltx = luaL_testudata(L, 1, ssh_tx);
if (ltx == NULL) {
lua_pushnil(L);
return 1;
}
return LuaPushStringBuffer(luastate, software, b_len);
}
static int SshGetServerSoftwareVersion(lua_State *luastate)
{
int r;
if (!(LuaStateNeedProto(luastate, ALPROTO_SSH)))
return LuaCallbackError(luastate, "error: protocol not ssh");
Flow *f = LuaStateGetFlow(luastate);
if (f == NULL)
return LuaCallbackError(luastate, "internal error: no flow");
r = GetServerSoftwareVersion(luastate, f);
return r;
if (SCSshTxGetProtocol(ltx->tx, &buf, &b_len, flags) != 1) {
lua_pushnil(L);
return 1;
}
return LuaPushStringBuffer(L, buf, b_len);
}
static int GetClientProtoVersion(lua_State *luastate, const Flow *f)
static int LuaSshTxGetServerProto(lua_State *L)
{
void *state = FlowGetAppState(f);
if (state == NULL)
return LuaCallbackError(luastate, "error: no app layer state");
const uint8_t *protocol = NULL;
uint32_t b_len = 0;
void *tx = SCSshStateGetTx(state, 0);
if (SCSshTxGetProtocol(tx, &protocol, &b_len, STREAM_TOSERVER) != 1)
return LuaCallbackError(luastate, "error: no client proto version");
if (protocol == NULL || b_len == 0) {
return LuaCallbackError(luastate, "error: no client proto version");
}
return LuaPushStringBuffer(luastate, protocol, b_len);
return LuaSshTxGetProto(L, STREAM_TOCLIENT);
}
static int SshGetClientProtoVersion(lua_State *luastate)
static int LuaSshTxGetClientProto(lua_State *L)
{
int r;
if (!(LuaStateNeedProto(luastate, ALPROTO_SSH)))
return LuaCallbackError(luastate, "error: protocol not ssh");
Flow *f = LuaStateGetFlow(luastate);
if (f == NULL)
return LuaCallbackError(luastate, "internal error: no flow");
r = GetClientProtoVersion(luastate, f);
return r;
return LuaSshTxGetProto(L, STREAM_TOSERVER);
}
static int GetClientSoftwareVersion(lua_State *luastate, const Flow *f)
static int LuaSshTxGetSoftware(lua_State *L, uint8_t flags)
{
void *state = FlowGetAppState(f);
if (state == NULL)
return LuaCallbackError(luastate, "error: no app layer state");
const uint8_t *software = NULL;
const uint8_t *buf = NULL;
uint32_t b_len = 0;
void *tx = SCSshStateGetTx(state, 0);
if (SCSshTxGetSoftware(tx, &software, &b_len, STREAM_TOSERVER) != 1)
return LuaCallbackError(luastate, "error: no client software version");
if (software == NULL || b_len == 0) {
return LuaCallbackError(luastate, "error: no client software version");
struct LuaTx *ltx = luaL_testudata(L, 1, ssh_tx);
if (ltx == NULL) {
lua_pushnil(L);
return 1;
}
return LuaPushStringBuffer(luastate, software, b_len);
if (SCSshTxGetSoftware(ltx->tx, &buf, &b_len, flags) != 1) {
lua_pushnil(L);
return 1;
}
return LuaPushStringBuffer(L, buf, b_len);
}
static int SshGetClientSoftwareVersion(lua_State *luastate)
static int LuaSshTxGetServerSoftware(lua_State *L)
{
int r;
if (!(LuaStateNeedProto(luastate, ALPROTO_SSH)))
return LuaCallbackError(luastate, "error: protocol not ssh");
Flow *f = LuaStateGetFlow(luastate);
if (f == NULL)
return LuaCallbackError(luastate, "internal error: no flow");
r = GetClientSoftwareVersion(luastate, f);
return r;
return LuaSshTxGetSoftware(L, STREAM_TOCLIENT);
}
/** \brief register ssh lua extensions in a luastate */
int LuaRegisterSshFunctions(lua_State *luastate)
static int LuaSshTxGetClientSoftware(lua_State *L)
{
/* registration of the callbacks */
lua_pushcfunction(luastate, SshGetServerProtoVersion);
lua_setglobal(luastate, "SshGetServerProtoVersion");
lua_pushcfunction(luastate, SshGetServerSoftwareVersion);
lua_setglobal(luastate, "SshGetServerSoftwareVersion");
lua_pushcfunction(luastate, SshGetClientProtoVersion);
lua_setglobal(luastate, "SshGetClientProtoVersion");
return LuaSshTxGetSoftware(L, STREAM_TOSERVER);
}
lua_pushcfunction(luastate, SshGetClientSoftwareVersion);
lua_setglobal(luastate, "SshGetClientSoftwareVersion");
static const struct luaL_Reg txlib[] = {
// clang-format off
{ "server_proto", LuaSshTxGetServerProto },
{ "server_software", LuaSshTxGetServerSoftware },
{ "client_proto", LuaSshTxGetClientProto },
{ "client_software", LuaSshTxGetClientSoftware },
{ NULL, NULL, }
// clang-format on
};
static const struct luaL_Reg sshlib[] = {
// clang-format off
{ "get_tx", LuaSshGetTx },
{ NULL, NULL,},
// clang-format on
};
int SCLuaLoadSshLib(lua_State *L)
{
luaL_newmetatable(L, ssh_tx);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
luaL_setfuncs(L, txlib, 0);
return 0;
luaL_newlib(L, sshlib);
return 1;
}

@ -24,6 +24,8 @@
#ifndef SURICATA_UTIL_LUA_SSH_H
#define SURICATA_UTIL_LUA_SSH_H
int LuaRegisterSshFunctions(lua_State *luastate);
#include "lua.h"
int SCLuaLoadSshLib(lua_State *L);
#endif /* SURICATA_UTIL_LUA_SSH_H */

Loading…
Cancel
Save