From: Victor Julien Date: Thu, 20 Feb 2014 16:51:47 +0000 (+0100) Subject: output-lua: support File logging X-Git-Tag: suricata-2.1beta2~153 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0070aef3d12ee97fc7bc4bd9121a538c0dcaf00b;p=thirdparty%2Fsuricata.git output-lua: support File logging 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. --- diff --git a/src/output-lua.c b/src/output-lua.c index e117f7bc74..97cebb2c7e 100644 --- a/src/output-lua.c +++ b/src/output-lua.c @@ -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);