]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
lua: SSH output support 1677/head
authorMats Klepsland <mats.klepsland@gmail.com>
Fri, 2 Oct 2015 07:23:13 +0000 (09:23 +0200)
committerMats Klepsland <mats.klepsland@gmail.com>
Fri, 9 Oct 2015 05:31:47 +0000 (07:31 +0200)
Support SSH in lua output scripts (Feature #1569).

src/app-layer-ssh.h
src/output-lua.c

index 7a6a9b723427b43d05d77571c1879b202ade7e8a..4fd59aa9e1d7f0b38f3d6c099e808824f4c99a04 100644 (file)
@@ -34,6 +34,8 @@
 
 #define SSH_FLAG_STATE_LOGGED                0x04
 
+#define SSH_FLAG_STATE_LOGGED_LUA            0x08
+
 /* MSG_CODE */
 #define SSH_MSG_NEWKEYS                      21
 
index 0d6e4e8add500aa4dbb1182082f7ea62cb3eda06..a8fcb246f7f8e73b89d1dad6e1b970a27d3bc690 100644 (file)
@@ -41,6 +41,7 @@
 #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"
@@ -59,6 +60,7 @@
 #include "util-lua-http.h"
 #include "util-lua-dns.h"
 #include "util-lua-tls.h"
+#include "util-lua-ssh.h"
 
 #define MODULE_NAME "LuaLog"
 
@@ -310,6 +312,86 @@ dontlog:
     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
  *
@@ -601,6 +683,8 @@ static int LuaScriptInit(const char *filename, LogLuaScriptOptions *options) {
             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)
@@ -702,6 +786,7 @@ static lua_State *LuaScriptSetup(const char *filename)
     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));
@@ -853,6 +938,9 @@ static OutputCtx *OutputLuaLogInit(ConfNode *conf)
             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;