aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/suricata/src/output-lua.c
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/suricata/src/output-lua.c')
-rw-r--r--framework/src/suricata/src/output-lua.c176
1 files changed, 176 insertions, 0 deletions
diff --git a/framework/src/suricata/src/output-lua.c b/framework/src/suricata/src/output-lua.c
index fc5a5621..a8fcb246 100644
--- a/framework/src/suricata/src/output-lua.c
+++ b/framework/src/suricata/src/output-lua.c
@@ -40,6 +40,8 @@
#include "output.h"
#include "app-layer-htp.h"
#include "app-layer.h"
+#include "app-layer-ssl.h"
+#include "app-layer-ssh.h"
#include "app-layer-parser.h"
#include "util-privs.h"
#include "util-buffer.h"
@@ -57,6 +59,8 @@
#include "util-lua-common.h"
#include "util-lua-http.h"
#include "util-lua-dns.h"
+#include "util-lua-tls.h"
+#include "util-lua-ssh.h"
#define MODULE_NAME "LuaLog"
@@ -229,6 +233,166 @@ static int LuaPacketConditionAlerts(ThreadVars *tv, const Packet *p)
}
/** \internal
+ * \brief Packet Logger for lua scripts, for tls
+ *
+ * A single call to this function will run one script for a single
+ * packet. If it is called, it means that the registered condition
+ * function has returned TRUE.
+ *
+ * The script is called once for each packet.
+ */
+static int LuaPacketLoggerTls(ThreadVars *tv, void *thread_data, const Packet *p)
+{
+ LogLuaThreadCtx *td = (LogLuaThreadCtx *)thread_data;
+
+ char timebuf[64];
+ CreateTimeString(&p->ts, timebuf, sizeof(timebuf));
+
+ SCMutexLock(&td->lua_ctx->m);
+
+ lua_getglobal(td->lua_ctx->luastate, "log");
+
+ LuaStateSetThreadVars(td->lua_ctx->luastate, tv);
+ LuaStateSetPacket(td->lua_ctx->luastate, (Packet *)p);
+ LuaStateSetFlow(td->lua_ctx->luastate, p->flow, /* unlocked */LUA_FLOW_NOT_LOCKED_BY_PARENT);
+
+ int retval = lua_pcall(td->lua_ctx->luastate, 0, 0, 0);
+ if (retval != 0) {
+ SCLogInfo("failed to run script: %s", lua_tostring(td->lua_ctx->luastate, -1));
+ }
+
+ SCMutexUnlock(&td->lua_ctx->m);
+ FLOWLOCK_WRLOCK(p->flow);
+
+ SSLState *ssl_state = (SSLState *)FlowGetAppState(p->flow);
+ if (ssl_state != NULL)
+ ssl_state->flags |= SSL_AL_FLAG_STATE_LOGGED_LUA;
+
+ FLOWLOCK_UNLOCK(p->flow);
+ SCReturnInt(0);
+}
+
+static int LuaPacketConditionTls(ThreadVars *tv, const Packet *p)
+{
+ if (p->flow == NULL) {
+ return FALSE;
+ }
+
+ if (!(PKT_IS_IPV4(p)) && !(PKT_IS_IPV6(p))) {
+ return FALSE;
+ }
+
+ if (!(PKT_IS_TCP(p))) {
+ return FALSE;
+ }
+
+ FLOWLOCK_RDLOCK(p->flow);
+ uint16_t proto = FlowGetAppProtocol(p->flow);
+ if (proto != ALPROTO_TLS)
+ goto dontlog;
+
+ SSLState *ssl_state = (SSLState *)FlowGetAppState(p->flow);
+ if (ssl_state == NULL) {
+ SCLogDebug("no tls state, so no request logging");
+ goto dontlog;
+ }
+
+ if (ssl_state->server_connp.cert0_issuerdn == NULL ||
+ ssl_state->server_connp.cert0_subject == NULL)
+ goto dontlog;
+
+ /* We only log the state once */
+ if (ssl_state->flags & SSL_AL_FLAG_STATE_LOGGED_LUA)
+ goto dontlog;
+
+ FLOWLOCK_UNLOCK(p->flow);
+ return TRUE;
+dontlog:
+ FLOWLOCK_UNLOCK(p->flow);
+ return FALSE;
+}
+
+/** \internal
+ * \brief Packet Logger for lua scripts, for ssh
+ *
+ * A single call to this function will run one script for a single
+ * packet. If it is called, it means that the registered condition
+ * function has returned TRUE.
+ *
+ * The script is called once for each packet.
+ */
+static int LuaPacketLoggerSsh(ThreadVars *tv, void *thread_data, const Packet *p)
+{
+ LogLuaThreadCtx *td = (LogLuaThreadCtx *)thread_data;
+
+ char timebuf[64];
+ CreateTimeString(&p->ts, timebuf, sizeof(timebuf));
+
+ SCMutexLock(&td->lua_ctx->m);
+
+ lua_getglobal(td->lua_ctx->luastate, "log");
+
+ LuaStateSetThreadVars(td->lua_ctx->luastate, tv);
+ LuaStateSetPacket(td->lua_ctx->luastate, (Packet *)p);
+ LuaStateSetFlow(td->lua_ctx->luastate, p->flow, /* unlocked */LUA_FLOW_NOT_LOCKED_BY_PARENT);
+
+ int retval = lua_pcall(td->lua_ctx->luastate, 0, 0, 0);
+ if (retval != 0) {
+ SCLogInfo("failed to run script: %s", lua_tostring(td->lua_ctx->luastate, -1));
+ }
+
+ SCMutexUnlock(&td->lua_ctx->m);
+ FLOWLOCK_WRLOCK(p->flow);
+
+ SshState *ssh_state = (SshState *)FlowGetAppState(p->flow);
+ if (ssh_state != NULL)
+ ssh_state->cli_hdr.flags |= SSH_FLAG_STATE_LOGGED_LUA;
+
+ FLOWLOCK_UNLOCK(p->flow);
+ SCReturnInt(0);
+}
+
+static int LuaPacketConditionSsh(ThreadVars *tv, const Packet *p)
+{
+ if (p->flow == NULL) {
+ return FALSE;
+ }
+
+ if (!(PKT_IS_IPV4(p)) && !(PKT_IS_IPV6(p))) {
+ return FALSE;
+ }
+
+ if (!(PKT_IS_TCP(p))) {
+ return FALSE;
+ }
+
+ FLOWLOCK_RDLOCK(p->flow);
+ uint16_t proto = FlowGetAppProtocol(p->flow);
+ if (proto != ALPROTO_SSH)
+ goto dontlog;
+
+ SshState *ssh_state = (SshState *)FlowGetAppState(p->flow);
+ if (ssh_state == NULL) {
+ SCLogDebug("no ssh state, so no request logging");
+ goto dontlog;
+ }
+
+ if (ssh_state->cli_hdr.software_version == NULL ||
+ ssh_state->srv_hdr.software_version == NULL)
+ goto dontlog;
+
+ /* We only log the state once */
+ if (ssh_state->cli_hdr.flags & SSH_FLAG_STATE_LOGGED_LUA)
+ goto dontlog;
+
+ FLOWLOCK_UNLOCK(p->flow);
+ return TRUE;
+dontlog:
+ FLOWLOCK_UNLOCK(p->flow);
+ return FALSE;
+}
+
+/** \internal
* \brief Packet Logger for lua scripts, for packets
*
* A single call to this function will run one script for a single
@@ -517,6 +681,10 @@ static int LuaScriptInit(const char *filename, LogLuaScriptOptions *options) {
options->alproto = ALPROTO_HTTP;
else if (strcmp(k,"protocol") == 0 && strcmp(v, "dns") == 0)
options->alproto = ALPROTO_DNS;
+ else if (strcmp(k,"protocol") == 0 && strcmp(v, "tls") == 0)
+ options->alproto = ALPROTO_TLS;
+ else if (strcmp(k,"protocol") == 0 && strcmp(v, "ssh") == 0)
+ options->alproto = ALPROTO_SSH;
else if (strcmp(k, "type") == 0 && strcmp(v, "packet") == 0)
options->packet = 1;
else if (strcmp(k, "filter") == 0 && strcmp(v, "alerts") == 0)
@@ -617,6 +785,8 @@ static lua_State *LuaScriptSetup(const char *filename)
* if the tx is registered in the state at runtime though. */
LuaRegisterHttpFunctions(luastate);
LuaRegisterDnsFunctions(luastate);
+ LuaRegisterTlsFunctions(luastate);
+ LuaRegisterSshFunctions(luastate);
if (lua_pcall(luastate, 0, 0, 0) != 0) {
SCLogError(SC_ERR_LUA_ERROR, "couldn't run script 'setup' function: %s", lua_tostring(luastate, -1));
@@ -760,11 +930,17 @@ static OutputCtx *OutputLuaLogInit(ConfNode *conf)
om->TxLogFunc = LuaTxLogger;
om->alproto = ALPROTO_HTTP;
AppLayerParserRegisterLogger(IPPROTO_TCP, ALPROTO_HTTP);
+ } else if (opts.alproto == ALPROTO_TLS) {
+ om->PacketLogFunc = LuaPacketLoggerTls;
+ om->PacketConditionFunc = LuaPacketConditionTls;
} else if (opts.alproto == ALPROTO_DNS) {
om->TxLogFunc = LuaTxLogger;
om->alproto = ALPROTO_DNS;
AppLayerParserRegisterLogger(IPPROTO_TCP, ALPROTO_DNS);
AppLayerParserRegisterLogger(IPPROTO_UDP, ALPROTO_DNS);
+ } else if (opts.alproto == ALPROTO_SSH) {
+ om->PacketLogFunc = LuaPacketLoggerSsh;
+ om->PacketConditionFunc = LuaPacketConditionSsh;
} else if (opts.packet && opts.alerts) {
om->PacketLogFunc = LuaPacketLoggerAlerts;
om->PacketConditionFunc = LuaPacketConditionAlerts;