diff --git a/src/detect-luajit.c b/src/detect-luajit.c index f17792eaf5..0f7ae63885 100644 --- a/src/detect-luajit.c +++ b/src/detect-luajit.c @@ -96,6 +96,43 @@ void DetectLuajitRegister(void) { return; } +#define DATATYPE_PACKET (1<<0) +#define DATATYPE_PAYLOAD (1<<1) + +/** \brief dump stack from lua state to screen */ +void LuaDumpStack(lua_State *state) { + int size = lua_gettop(state); + int i; + + for (i = 1; i <= size; i++) { + int type = lua_type(state, i); + printf("Stack size=%d, level=%d, type=%d, ", size, i, type); + + switch (type) { + case LUA_TFUNCTION: + printf("function %s", lua_tostring(state, i) ? "true" : "false"); + break; + case LUA_TBOOLEAN: + printf("bool %s", lua_toboolean(state, i) ? "true" : "false"); + break; + case LUA_TNUMBER: + printf("number %g", lua_tonumber(state, i)); + break; + case LUA_TSTRING: + printf("string `%s'", lua_tostring(state, i)); + break; + case LUA_TTABLE: + printf("table `%s'", lua_tostring(state, i)); + break; + default: + printf("other %s", lua_typename(state, type)); + break; + + } + printf("\n"); + } +} + /** * \brief match the specified luajit * @@ -121,15 +158,20 @@ static int DetectLuajitMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, if (tluajit == NULL) SCReturnInt(0); + if ((tluajit->flags & DATATYPE_PAYLOAD) && p->payload_len) + SCReturnInt(0); + if ((tluajit->flags & DATATYPE_PACKET) && GET_PKT_LEN(p)) + SCReturnInt(0); + lua_getglobal(tluajit->luastate, "match"); lua_newtable(tluajit->luastate); /* stack at -1 */ - if (p->payload_len) { + if ((tluajit->flags & DATATYPE_PAYLOAD) && p->payload_len) { lua_pushliteral(tluajit->luastate, "payload"); /* stack at -2 */ lua_pushlstring (tluajit->luastate, (const char *)p->payload, (size_t)p->payload_len); /* stack at -3 */ lua_settable(tluajit->luastate, -3); } - if (GET_PKT_LEN(p)) { + if ((tluajit->flags & DATATYPE_PACKET) && GET_PKT_LEN(p)) { lua_pushliteral(tluajit->luastate, "packet"); /* stack at -2 */ lua_pushlstring (tluajit->luastate, (const char *)GET_PKT_DATA(p), (size_t)GET_PKT_LEN(p)); /* stack at -3 */ lua_settable(tluajit->luastate, -3); @@ -140,12 +182,51 @@ static int DetectLuajitMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, SCLogInfo("failed to run script: %s", lua_tostring(tluajit->luastate, -1)); } - double script_ret = lua_tonumber(tluajit->luastate, 1); - SCLogDebug("script_ret %f", script_ret); - lua_pop(tluajit->luastate, 1); + /* process returns from script */ + if (lua_gettop(tluajit->luastate) > 0) { + + /* script returns a number (return 1 or return 0) */ + if (lua_type(tluajit->luastate, 1) == LUA_TNUMBER) { + double script_ret = lua_tonumber(tluajit->luastate, 1); + SCLogDebug("script_ret %f", script_ret); + lua_pop(tluajit->luastate, 1); + + if (script_ret == 1.0) + ret = 1; + + /* script returns a table */ + } else if (lua_type(tluajit->luastate, 1) == LUA_TTABLE) { + lua_pushnil(tluajit->luastate); + const char *k, *v; + while (lua_next(tluajit->luastate, -2)) { + v = lua_tostring(tluajit->luastate, -1); + lua_pop(tluajit->luastate, 1); + k = lua_tostring(tluajit->luastate, -1); + + if (!k || !v) + continue; + + SCLogDebug("k='%s', v='%s'", k, v); + + if (strcmp(k, "retval") == 0) { + if (atoi(v) == 1) + ret = 1; + } else { + /* set flow var? */ + } + } + + /* pop the table */ + lua_pop(tluajit->luastate, 1); + } + } - if (script_ret == 1.0) - ret = 1; + if (luajit->negated) { + if (ret == 1) + ret = 0; + else + ret = 1; + } SCReturnInt(ret); } @@ -170,8 +251,66 @@ static void *DetectLuajitThreadInit(void *data) { fprintf(stderr, "Couldn't prime file: %s\n", lua_tostring(t->luastate, -1)); BUG_ON(1); } - } + lua_getglobal(t->luastate, "init"); + if (lua_type(t->luastate, -1) != LUA_TFUNCTION) { + SCLogInfo("no init function in script"); + /** \todo proper cleanup */ + return NULL; + } + + lua_newtable(t->luastate); /* stack at -1 */ + if (lua_gettop(t->luastate) == 0 || lua_type(t->luastate, 2) != LUA_TTABLE) { + SCLogInfo("no table setup"); + /** \todo proper cleanup */ + return NULL; + } + + lua_pushliteral(t->luastate, "script_api_ver"); /* stack at -2 */ + lua_pushnumber (t->luastate, 1); /* stack at -3 */ + lua_settable(t->luastate, -3); + + if (lua_pcall(t->luastate, 1, 1, 0) != 0) { + fprintf(stderr, "Couldn't prime file: %s\n", lua_tostring(t->luastate, -1)); + BUG_ON(1); + } + + /* process returns from script */ + if (lua_gettop(t->luastate) == 0) { + SCLogInfo("init function in script should return table, nothing returned"); + /** \todo proper cleanup */ + return NULL; + } + if (lua_type(t->luastate, 1) != LUA_TTABLE) { + SCLogInfo("init function in script should return table, returned is not table"); + /** \todo proper cleanup */ + return NULL; + } + + lua_pushnil(t->luastate); + const char *k, *v; + while (lua_next(t->luastate, -2)) { + v = lua_tostring(t->luastate, -1); + lua_pop(t->luastate, 1); + k = lua_tostring(t->luastate, -1); + + if (!k || !v) + continue; + + SCLogDebug("k='%s', v='%s'", k, v); + if (strcmp(k, "packet") == 0 && strcmp(v, "true") == 0) { + t->flags |= DATATYPE_PACKET; + } else if (strcmp(k, "payload") == 0 && strcmp(v, "true") == 0) { + t->flags |= DATATYPE_PAYLOAD; + + } else { + SCLogInfo("unsupported data type %s", k); + } + } + + /* pop the table */ + lua_pop(t->luastate, 1); + } return (void *)t; } diff --git a/src/detect-luajit.h b/src/detect-luajit.h index a2d91c2336..a57f9a5040 100644 --- a/src/detect-luajit.h +++ b/src/detect-luajit.h @@ -32,6 +32,7 @@ typedef struct DetectLuajitThreadData { lua_State *luastate; + uint32_t flags; } DetectLuajitThreadData; typedef struct DetectLuajitData {