]> git.ipfire.org Git - people/ms/suricata.git/commitdiff
lua: TLS lua output support
authorMats Klepsland <mats.klepsland@gmail.com>
Wed, 30 Sep 2015 08:42:26 +0000 (10:42 +0200)
committerVictor Julien <victor@inliniac.net>
Thu, 8 Oct 2015 08:28:24 +0000 (10:28 +0200)
Support TLS in lua output scripts (Feature #1568).

function init (args)
    local needs = {}
    needs["protocol"] = "tls"
    return needs
end

function setup (args)
    filename = SCLogPath() .. "/" .. "lua_tls.log"
    file = assert(io.open(filename, "a"))
end

function log (args)
    ts = SCPacketTimeString()
    ipver, srcip, dstip, proto, sp, dp = SCFlowTuple()

    version, subject, issuer, fingerprint = TlsGetCertInfo();
    if version == nil then
        return 0
    end

    file:write(ts .. " " .. srcip .. ":" .. sp .. " -> " .. dstip  ..
               ":" .. dp .. "  TLS: " .. "Subject='" .. subject ..
               "' " .. "Issuerdn='" .. issuer .. "\n")
    file:flush()
end

function deinit (args)
    file:close(file)
end

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

index 5c6fe5b153b5962b6ac68bbf9e89d7b5e1223966..2fc1a9699bde52331a7262fafba647ba99e873e6 100644 (file)
@@ -81,6 +81,8 @@ enum {
 /* flags for file storage */
 #define SSL_AL_FLAG_STATE_STORED                0x40000
 
+#define SSL_AL_FLAG_STATE_LOGGED_LUA            0x80000
+
 /* config flags */
 #define SSL_TLS_LOG_PEM                         (1 << 0)
 
index fc5a562164fe8267ac979e19f75baa872477048c..0d6e4e8add500aa4dbb1182082f7ea62cb3eda06 100644 (file)
@@ -40,6 +40,7 @@
 #include "output.h"
 #include "app-layer-htp.h"
 #include "app-layer.h"
+#include "app-layer-ssl.h"
 #include "app-layer-parser.h"
 #include "util-privs.h"
 #include "util-buffer.h"
@@ -57,6 +58,7 @@
 #include "util-lua-common.h"
 #include "util-lua-http.h"
 #include "util-lua-dns.h"
+#include "util-lua-tls.h"
 
 #define MODULE_NAME "LuaLog"
 
@@ -228,6 +230,86 @@ static int LuaPacketConditionAlerts(ThreadVars *tv, const Packet *p)
     return FALSE;
 }
 
+/** \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 packets
  *
@@ -517,6 +599,8 @@ 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, "type") == 0 && strcmp(v, "packet") == 0)
             options->packet = 1;
         else if (strcmp(k, "filter") == 0 && strcmp(v, "alerts") == 0)
@@ -617,6 +701,7 @@ static lua_State *LuaScriptSetup(const char *filename)
      * if the tx is registered in the state at runtime though. */
     LuaRegisterHttpFunctions(luastate);
     LuaRegisterDnsFunctions(luastate);
+    LuaRegisterTlsFunctions(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,6 +845,9 @@ 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;