From: Victor Julien Date: Wed, 12 Sep 2012 15:52:57 +0000 (+0200) Subject: luajit: support http.request_body (http_client_body) and http.response_body (file_dat... X-Git-Tag: suricata-1.4beta2~77 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b6834cb6b233343c41ddd9e86a2a48816c3b5bdc;p=thirdparty%2Fsuricata.git luajit: support http.request_body (http_client_body) and http.response_body (file_data/http_server_body). --- diff --git a/src/detect-engine-content-inspection.c b/src/detect-engine-content-inspection.c index f887b14140..f90c2e27e2 100644 --- a/src/detect-engine-content-inspection.c +++ b/src/detect-engine-content-inspection.c @@ -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 diff --git a/src/detect-luajit.c b/src/detect-luajit.c index 572fce8343..e65b820835 100644 --- a/src/detect-luajit.c +++ b/src/detect-luajit.c @@ -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); } } diff --git a/src/detect-luajit.h b/src/detect-luajit.h index 3cca94ec5d..09669c9328 100644 --- a/src/detect-luajit.h +++ b/src/detect-luajit.h @@ -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