]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
output-lua: support File logging
authorVictor Julien <victor@inliniac.net>
Thu, 20 Feb 2014 16:51:47 +0000 (17:51 +0100)
committerVictor Julien <victor@inliniac.net>
Fri, 15 Aug 2014 11:58:25 +0000 (13:58 +0200)
Add file logger support. The script uses:

function init (args)
    local needs = {}
    needs['type'] = 'file'
    return needs
end

The type is set to file to make it a file logger.

src/output-lua.c

index e117f7bc746ccc12c2b99cc030ed059b7f45d77d..97cebb2c7ecbc0fc9303cd0a0e590ea6e2606e47 100644 (file)
@@ -186,6 +186,63 @@ static int LuaPacketConditionAlerts(ThreadVars *tv, const Packet *p)
     return FALSE;
 }
 
+/** \internal
+ *  \brief File API Logger function for Lua scripts
+ *
+ *  Executes a script once for one file.
+ *
+ * TODO non-http support
+ *
+ * NOTE p->flow is locked at this point
+ */
+static int LuaFileLogger(ThreadVars *tv, void *thread_data, const Packet *p, const File *ff)
+{
+    SCEnter();
+    LogLuaThreadCtx *td = (LogLuaThreadCtx *)thread_data;
+
+    if ((!(PKT_IS_IPV4(p))) && (!(PKT_IS_IPV6(p))))
+        return 0;
+
+    BUG_ON(ff->flags & FILE_LOGGED);
+
+    SCLogDebug("ff %p", ff);
+
+    /* Get the TX so the script can get more context about it.
+     * TODO hardcoded to HTTP currently */
+    void *txptr = NULL;
+    if (p && p->flow && p->flow->alstate)
+        txptr = AppLayerParserGetTx(p->proto, ALPROTO_HTTP, p->flow->alstate, ff->txid);
+
+    SCMutexLock(&td->lua_ctx->m);
+
+    /* we need the p in our callbacks */
+    lua_pushlightuserdata(td->lua_ctx->luastate, (void *)&lualog_ext_key_p);
+    lua_pushlightuserdata(td->lua_ctx->luastate, (void *)p);
+    lua_settable(td->lua_ctx->luastate, LUA_REGISTRYINDEX);
+    /* we need the tx in our callbacks */
+    lua_pushlightuserdata(td->lua_ctx->luastate, (void *)&lualog_ext_key_tx);
+    lua_pushlightuserdata(td->lua_ctx->luastate, (void *)txptr);
+    lua_settable(td->lua_ctx->luastate, LUA_REGISTRYINDEX);
+
+    /* get the lua function to call */
+    lua_getglobal(td->lua_ctx->luastate, "log");
+
+    /* prepare data to pass to script */
+    lua_newtable(td->lua_ctx->luastate);
+
+    LogLuaPushTableKeyValueArray(td->lua_ctx->luastate, "filename", ff->name, ff->name_len);
+    LogLuaPushTableKeyValueString(td->lua_ctx->luastate, "filemagic", ff->magic);
+    LogLuaPushTableKeyValueArray(td->lua_ctx->luastate, "filemd5", ff->md5, sizeof(ff->md5));
+
+    //LuaPrintStack(td->lua_ctx->luastate);
+    int retval = lua_pcall(td->lua_ctx->luastate, 1, 0, 0);
+    if (retval != 0) {
+        SCLogInfo("failed to run script: %s", lua_tostring(td->lua_ctx->luastate, -1));
+    }
+    SCMutexUnlock(&td->lua_ctx->m);
+    return 0;
+}
+
 typedef struct LogLuaScriptOptions_ {
     AppProto alproto;
     int packet;
@@ -283,10 +340,16 @@ static int LuaScriptInit(const char *filename, LogLuaScriptOptions *options) {
             options->packet = 1;
         else if (strcmp(k, "filter") == 0 && strcmp(v, "alerts") == 0)
             options->alerts = 1;
+        else if (strcmp(k, "type") == 0 && strcmp(v, "file") == 0)
+            options->file = 1;
         else
             SCLogInfo("unknown key and/or value: k='%s', v='%s'", k, v);
     }
-    //SCLogInfo("alproto %u", alproto);
+
+    if (options->alproto + options->packet + options->file > 1) {
+        SCLogError(SC_ERR_LUAJIT_ERROR, "invalid combination of 'needs' in the script");
+        goto error;
+    }
 
     lua_getglobal(luastate, "setup");
     if (lua_type(luastate, -1) != LUA_TFUNCTION) {
@@ -461,6 +524,8 @@ static OutputCtx *OutputLuaLogInit(ConfNode *conf)
         } else if (opts.packet && opts.alerts) {
             om->PacketLogFunc = LuaPacketLoggerAlerts;
             om->PacketConditionFunc = LuaPacketConditionAlerts;
+        } else if (opts.file) {
+            om->FileLogFunc = LuaFileLogger;
         }
 
         TAILQ_INSERT_TAIL(&output_ctx->submodules, om, entries);