]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
luajit: force scripts to have 'init' function that returns a table of 'needs' such...
authorVictor Julien <victor@inliniac.net>
Fri, 7 Sep 2012 13:04:34 +0000 (15:04 +0200)
committerVictor Julien <victor@inliniac.net>
Fri, 7 Sep 2012 13:04:34 +0000 (15:04 +0200)
src/detect-luajit.c
src/detect-luajit.h

index f17792eaf5485ce8408563ab0477eb3c4f47ee30..0f7ae6388541bb037bb5ff8ea13a9efbbce5a9fe 100644 (file)
@@ -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;
 }
 
index a2d91c233664addb55cf25e5c19153fae6438b3d..a57f9a504091f46e11808dd75bd4718e740f31db 100644 (file)
@@ -32,6 +32,7 @@
 
 typedef struct DetectLuajitThreadData {
     lua_State *luastate;
+    uint32_t flags;
 } DetectLuajitThreadData;
 
 typedef struct DetectLuajitData {