]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
luajit: support http.request_body (http_client_body) and http.response_body (file_dat...
authorVictor Julien <victor@inliniac.net>
Wed, 12 Sep 2012 15:52:57 +0000 (17:52 +0200)
committerVictor Julien <victor@inliniac.net>
Wed, 12 Sep 2012 15:53:02 +0000 (17:53 +0200)
src/detect-engine-content-inspection.c
src/detect-luajit.c
src/detect-luajit.h

index f887b1414050bf5b162e0be5d8813b84c3183d91..f90c2e27e21df3101270279e9ba71384994f8073 100644 (file)
@@ -497,6 +497,13 @@ int DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx
         }
 
         SCReturnInt(0);
+    } else if (sm->type == DETECT_LUAJIT) {
+        if (DetectLuajitMatchBuffer(det_ctx, s, sm, buffer, buffer_len, det_ctx->buffer_offset) != 1) {
+            SCReturnInt(0);
+        }
+
+        goto match;
+
     } else {
         SCLogDebug("sm->type %u", sm->type);
 #ifdef DEBUG
index 572fce834339714f1a57f32528f05e157fc2b33f..e65b8208350a4ea0effaf77684e65d44ef4c9ff6 100644 (file)
@@ -102,6 +102,8 @@ void DetectLuajitRegister(void) {
 #define DATATYPE_HTTP_URI           (1<<3)
 #define DATATYPE_HTTP_URI_RAW       (1<<4)
 #define DATATYPE_HTTP_REQUEST_LINE  (1<<5)
+#define DATATYPE_HTTP_REQUEST_BODY  (1<<6)
+#define DATATYPE_HTTP_RESPONSE_BODY (1<<7)
 
 
 /** \brief dump stack from lua state to screen */
@@ -138,6 +140,88 @@ void LuaDumpStack(lua_State *state) {
     }
 }
 
+int DetectLuajitMatchBuffer(DetectEngineThreadCtx *det_ctx, Signature *s, SigMatch *sm, uint8_t *buffer, uint32_t buffer_len, uint32_t offset) {
+    SCEnter();
+    int ret = 0;
+
+    if (buffer == NULL || buffer_len == 0)
+        SCReturnInt(0);
+
+    DetectLuajitData *luajit = (DetectLuajitData *)sm->ctx;
+    if (luajit == NULL)
+        SCReturnInt(0);
+
+    DetectLuajitThreadData *tluajit = (DetectLuajitThreadData *)DetectThreadCtxGetKeywordThreadCtx(det_ctx, luajit->thread_ctx_id);
+    if (tluajit == NULL)
+        SCReturnInt(0);
+
+    lua_getglobal(tluajit->luastate, "match");
+    lua_newtable(tluajit->luastate); /* stack at -1 */
+
+    lua_pushliteral (tluajit->luastate, "offset"); /* stack at -2 */
+    lua_pushnumber (tluajit->luastate, (int)offset);
+    lua_settable(tluajit->luastate, -3);
+
+    lua_pushstring (tluajit->luastate, luajit->buffername); /* stack at -2 */
+    lua_pushlstring (tluajit->luastate, (const char *)buffer, (size_t)buffer_len);
+    lua_settable(tluajit->luastate, -3);
+
+    int retval = lua_pcall(tluajit->luastate, 1, 1, 0);
+    if (retval != 0) {
+        SCLogInfo("failed to run script: %s", lua_tostring(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);
+        }
+    } else {
+        SCLogDebug("no stack");
+    }
+
+    if (luajit->negated) {
+        if (ret == 1)
+            ret = 0;
+        else
+            ret = 1;
+    }
+
+    SCReturnInt(ret);
+
+}
+
 /**
  * \brief match the specified luajit
  *
@@ -207,15 +291,6 @@ static int DetectLuajitMatch (ThreadVars *tv, DetectEngineThreadCtx *det_ctx,
                     if (tx == NULL)
                         continue;
 
-                    if ((tluajit->flags & DATATYPE_HTTP_URI) && tx->request_uri_normalized != NULL &&
-                            bstr_len(tx->request_uri_normalized) > 0)
-                    {
-                        lua_pushliteral(tluajit->luastate, "http.uri"); /* stack at -2 */
-                        lua_pushlstring (tluajit->luastate,
-                                (const char *)bstr_ptr(tx->request_uri_normalized),
-                                bstr_len(tx->request_uri_normalized));
-                        lua_settable(tluajit->luastate, -3);
-                    }
                     if ((tluajit->flags & DATATYPE_HTTP_REQUEST_LINE) && tx->request_line != NULL &&
                             bstr_len(tx->request_line) > 0) {
                         lua_pushliteral(tluajit->luastate, "http.request_line"); /* stack at -2 */
@@ -318,8 +393,6 @@ static void *DetectLuajitThreadInit(void *data) {
         goto error;
     }
 
-    /* pop the table */
-    lua_pop(t->luastate, 1);
     return (void *)t;
 
 error:
@@ -439,8 +512,12 @@ static int DetectLuaSetupPrime(DetectLuajitData *ld) {
         } else if (strcmp(k, "payload") == 0 && strcmp(v, "true") == 0) {
             ld->flags |= DATATYPE_PAYLOAD;
         } else if (strncmp(k, "http", 4) == 0 && strcmp(v, "true") == 0) {
-            if (ld->alproto != ALPROTO_UNKNOWN) {
-                SCLogError(SC_ERR_LUAJIT_ERROR, "can just inspect script against one alproto %s", k);
+            if (ld->alproto != ALPROTO_UNKNOWN && ld->alproto != ALPROTO_HTTP) {
+                SCLogError(SC_ERR_LUAJIT_ERROR, "can just inspect script against one app layer proto like HTTP at a time");
+                goto error;
+            }
+            if (ld->flags != 0) {
+                SCLogError(SC_ERR_LUAJIT_ERROR, "when inspecting HTTP buffers only a single buffer can be inspected");
                 goto error;
             }
 
@@ -451,11 +528,22 @@ static int DetectLuaSetupPrime(DetectLuajitData *ld) {
                 ld->flags |= DATATYPE_HTTP_URI;
             else if (strcmp(k, "http.request_line") == 0)
                 ld->flags |= DATATYPE_HTTP_REQUEST_LINE;
-            else {
+            else if (strcmp(k, "http.request_body") == 0)
+                ld->flags |= DATATYPE_HTTP_REQUEST_BODY;
+            else if (strcmp(k, "http.response_body") == 0) {
+                ld->flags |= DATATYPE_HTTP_RESPONSE_BODY;
+
+            } else {
                 SCLogError(SC_ERR_LUAJIT_ERROR, "unsupported http data type %s", k);
                 goto error;
             }
 
+            ld->buffername = SCStrdup(k);
+            if (ld->buffername == NULL) {
+                SCLogError(SC_ERR_LUAJIT_ERROR, "alloc error");
+                goto error;
+            }
+
         } else {
             SCLogError(SC_ERR_LUAJIT_ERROR, "unsupported data type %s", k);
             goto error;
@@ -491,16 +579,16 @@ static int DetectLuajitSetup (DetectEngineCtx *de_ctx, Signature *s, char *str)
     if (luajit == NULL)
         goto error;
 
+    if (DetectLuaSetupPrime(luajit) == -1) {
+        goto error;
+    }
+
     luajit->thread_ctx_id = DetectRegisterThreadCtxFuncs(de_ctx, "luajit",
             DetectLuajitThreadInit, (void *)luajit,
             DetectLuajitThreadFree);
     if (luajit->thread_ctx_id == -1)
         goto error;
 
-    if (DetectLuaSetupPrime(luajit) == -1) {
-        goto error;
-    }
-
     if (luajit->alproto != ALPROTO_UNKNOWN) {
         if (s->alproto != ALPROTO_UNKNOWN && luajit->alproto != s->alproto) {
             goto error;
@@ -517,8 +605,18 @@ static int DetectLuajitSetup (DetectEngineCtx *de_ctx, Signature *s, char *str)
     sm->type = DETECT_LUAJIT;
     sm->ctx = (void *)luajit;
 
-    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
-
+    if (luajit->alproto == ALPROTO_UNKNOWN)
+        SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
+    else if (luajit->alproto == ALPROTO_HTTP) {
+        if (luajit->flags & DATATYPE_HTTP_RESPONSE_BODY)
+            SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_HSBDMATCH);
+        else if (luajit->flags & DATATYPE_HTTP_REQUEST_BODY)
+            SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_HCBDMATCH);
+        else if (luajit->flags & DATATYPE_HTTP_URI)
+            SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_UMATCH);
+        else
+            SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_AMATCH);
+    }
     return 0;
 
 error:
@@ -537,6 +635,10 @@ error:
 static void DetectLuajitFree(void *ptr) {
     if (ptr != NULL) {
         DetectLuajitData *luajit = (DetectLuajitData *)ptr;
+
+        if (luajit->buffername)
+            SCFree(luajit->buffername);
+
         SCFree(luajit);
     }
 }
index 3cca94ec5d4ace63e9fe684d69de74119afde6e8..09669c9328af536617cdfc5f521ff5aecfa8212a 100644 (file)
@@ -42,6 +42,7 @@ typedef struct DetectLuajitData {
     char *filename;
     uint32_t flags;
     int alproto;
+    char *buffername; /* buffer name in case of a single buffer */
 } DetectLuajitData;
 #endif