From: Mats Klepsland Date: Fri, 2 Oct 2015 07:23:13 +0000 (+0200) Subject: lua: SSH output support X-Git-Tag: suricata-3.0RC1~67 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=70cc1ddbcd60fdb9373350e34aa276a98a9727e1;p=thirdparty%2Fsuricata.git lua: SSH output support Support SSH in lua output scripts (Feature #1569). --- diff --git a/src/app-layer-ssh.h b/src/app-layer-ssh.h index 7a6a9b7234..4fd59aa9e1 100644 --- a/src/app-layer-ssh.h +++ b/src/app-layer-ssh.h @@ -34,6 +34,8 @@ #define SSH_FLAG_STATE_LOGGED 0x04 +#define SSH_FLAG_STATE_LOGGED_LUA 0x08 + /* MSG_CODE */ #define SSH_MSG_NEWKEYS 21 diff --git a/src/output-lua.c b/src/output-lua.c index 0d6e4e8add..a8fcb246f7 100644 --- a/src/output-lua.c +++ b/src/output-lua.c @@ -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;