DNP3: Lua detect support.

Adds support for access the DNP3 transaction in Lua rules.
pull/2391/head
Jason Ish 10 years ago committed by Victor Julien
parent 44a69f6355
commit a59f31a99f

@ -379,6 +379,8 @@ util-logopenfile.h util-logopenfile.c \
util-logopenfile-tile.h util-logopenfile-tile.c \
util-lua.c util-lua.h \
util-lua-common.c util-lua-common.h \
util-lua-dnp3.c util-lua-dnp3.h \
util-lua-dnp3-objects.c util-lua-dnp3-objects.h \
util-lua-dns.c util-lua-dns.h \
util-lua-http.c util-lua-http.h \
util-lua-tls.c util-lua-tls.h \

@ -17,12 +17,16 @@
#include "suricata-common.h"
#include "stream.h"
#include "detect.h"
#include "detect-parse.h"
#include "detect-dnp3.h"
#include "detect-engine.h"
#include "detect-engine-content-inspection.h"
#include "app-layer-dnp3.h"
/**
* The detection struct.
*/
@ -213,7 +217,6 @@ static int DetectDNP3FuncSetup(DetectEngineCtx *de_ctx, Signature *s, char *str)
if (unlikely(dnp3 == NULL)) {
goto error;
}
dnp3->detect_type = DNP3_DETECT_TYPE_FC;
dnp3->function_code = function_code;
sm = SigMatchAlloc();
@ -301,7 +304,6 @@ static int DetectDNP3IndSetup(DetectEngineCtx *de_ctx, Signature *s, char *str)
if (unlikely(detect == NULL)) {
goto error;
}
detect->detect_type = DNP3_DETECT_TYPE_IND;
detect->ind_flags = flags;
sm = SigMatchAlloc();
@ -384,7 +386,6 @@ static int DetectDNP3ObjSetup(DetectEngineCtx *de_ctx, Signature *s, char *str)
if (unlikely(detect == NULL)) {
goto fail;
}
detect->detect_type = DNP3_DETECT_TYPE_OBJ;
detect->obj_group = group;
detect->obj_variation = variation;
@ -489,6 +490,7 @@ static void DetectDNP3FuncRegister(void)
sigmatch_table[DETECT_AL_DNP3FUNC].alias = "dnp3_func";
sigmatch_table[DETECT_AL_DNP3FUNC].Match = NULL;
sigmatch_table[DETECT_AL_DNP3FUNC].AppLayerMatch = NULL;
sigmatch_table[DETECT_AL_DNP3FUNC].AppLayerTxMatch = DetectDNP3FuncMatch;
sigmatch_table[DETECT_AL_DNP3FUNC].Setup = DetectDNP3FuncSetup;
sigmatch_table[DETECT_AL_DNP3FUNC].Free = DetectDNP3Free;
sigmatch_table[DETECT_AL_DNP3FUNC].RegisterTests =
@ -505,6 +507,7 @@ static void DetectDNP3IndRegister(void)
sigmatch_table[DETECT_AL_DNP3IND].alias = "dnp3_ind";
sigmatch_table[DETECT_AL_DNP3IND].Match = NULL;
sigmatch_table[DETECT_AL_DNP3IND].AppLayerMatch = NULL;
sigmatch_table[DETECT_AL_DNP3IND].AppLayerTxMatch = DetectDNP3IndMatch;
sigmatch_table[DETECT_AL_DNP3IND].Setup = DetectDNP3IndSetup;
sigmatch_table[DETECT_AL_DNP3IND].Free = DetectDNP3Free;
sigmatch_table[DETECT_AL_DNP3IND].RegisterTests =
@ -521,6 +524,7 @@ static void DetectDNP3ObjRegister(void)
sigmatch_table[DETECT_AL_DNP3OBJ].alias = "dnp3_obj";
sigmatch_table[DETECT_AL_DNP3OBJ].Match = NULL;
sigmatch_table[DETECT_AL_DNP3OBJ].AppLayerMatch = NULL;
sigmatch_table[DETECT_AL_DNP3OBJ].AppLayerTxMatch = DetectDNP3ObjMatch;
sigmatch_table[DETECT_AL_DNP3OBJ].Setup = DetectDNP3ObjSetup;
sigmatch_table[DETECT_AL_DNP3OBJ].Free = DetectDNP3Free;
sigmatch_table[DETECT_AL_DNP3OBJ].RegisterTests =

@ -69,6 +69,7 @@
#include "util-lua-tls.h"
#include "util-lua-ssh.h"
#include "util-lua-smtp.h"
#include "util-lua-dnp3.h"
static const char luaext_key_ld[] = "suricata:luajitdata";
static const char luaext_key_det_ctx[] = "suricata:det_ctx";
@ -580,6 +581,7 @@ int LuaRegisterExtensions(lua_State *lua_state)
LuaRegisterTlsFunctions(lua_state);
LuaRegisterSshFunctions(lua_state);
LuaRegisterSmtpFunctions(lua_state);
LuaRegisterDNP3Functions(lua_state);
return 0;
}

@ -168,6 +168,8 @@ void DetectLuaRegister(void)
#define DATATYPE_SSH (1<<19)
#define DATATYPE_SMTP (1<<20)
#define DATATYPE_DNP3 (1<<20)
#ifdef HAVE_LUAJIT
static void *LuaStatePoolAlloc(void)
{
@ -1023,6 +1025,12 @@ static int DetectLuaSetupPrime(DetectEngineCtx *de_ctx, DetectLuaData *ld)
ld->flags |= DATATYPE_SMTP;
} else if (strncmp(k, "dnp3", 4) == 0 && strcmp(v, "true") == 0) {
ld->alproto = ALPROTO_DNP3;
ld->flags |= DATATYPE_DNP3;
} else {
SCLogError(SC_ERR_LUA_ERROR, "unsupported data type %s", k);
goto error;
@ -1124,6 +1132,8 @@ static int DetectLuaSetup (DetectEngineCtx *de_ctx, Signature *s, char *str)
SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_AMATCH);
} else if (luajit->alproto == ALPROTO_SMTP) {
SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_AMATCH);
} else if (luajit->alproto == ALPROTO_DNP3) {
SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_DNP3_MATCH);
} else {
SCLogError(SC_ERR_LUA_ERROR, "luajit can't be used with protocol %s",
AppLayerGetProtoName(luajit->alproto));

@ -1604,6 +1604,9 @@ static Signature *SigInitHelper(DetectEngineCtx *de_ctx, char *sigstr,
if (sig->sm_lists[DETECT_SM_LIST_DNP3_DATA_MATCH]) {
sig->flags |= SIG_FLAG_STATE_MATCH;
}
if (sig->sm_lists[DETECT_SM_LIST_DNP3_MATCH]) {
sig->flags |= SIG_FLAG_STATE_MATCH;
}
/* Template. */
if (sig->sm_lists[DETECT_SM_LIST_TEMPLATE_BUFFER_MATCH]) {

@ -415,32 +415,19 @@ static TmEcode JsonDNP3LogThreadDeinit(ThreadVars *t, void *data)
return TM_ECODE_OK;
}
void TmModuleJsonDNP3LogRegister(void)
void JsonDNP3LogRegister(void)
{
tmm_modules[TMM_JSONDNP3LOG].name = "JsonDNP3Log";
tmm_modules[TMM_JSONDNP3LOG].ThreadInit = JsonDNP3LogThreadInit;
tmm_modules[TMM_JSONDNP3LOG].ThreadDeinit = JsonDNP3LogThreadDeinit;
tmm_modules[TMM_JSONDNP3LOG].RegisterTests = NULL;
tmm_modules[TMM_JSONDNP3LOG].cap_flags = 0;
tmm_modules[TMM_JSONDNP3LOG].flags = TM_FLAG_LOGAPI_TM;
/* Register as en eve sub-module. */
OutputRegisterTxSubModule("eve-log", "JsonDNP3Log", "eve-log.dnp3",
OutputDNP3LogInitSub, ALPROTO_DNP3, JsonDNP3Logger);
OutputRegisterTxSubModule(LOGGER_JSON_DNP3, "eve-log", "JsonDNP3Log",
"eve-log.dnp3", OutputDNP3LogInitSub, ALPROTO_DNP3, JsonDNP3Logger,
JsonDNP3LogThreadInit, JsonDNP3LogThreadDeinit, NULL);
}
#else
static TmEcode OutputJsonThreadInit(ThreadVars *t, void *initdata, void **data)
void JsonDNP3LogRegister (void)
{
SCLogInfo("Can't init JSON output - JSON support was disabled during build.");
return TM_ECODE_FAILED;
}
void TmModuleJsonDNP3LogRegister (void)
{
tmm_modules[TMM_JSONDNP3LOG].name = "JsonDNP3Log";
tmm_modules[TMM_JSONDNP3LOG].ThreadInit = OutputJsonThreadInit;
}
#endif

@ -69,6 +69,7 @@
#include "output-json.h"
#include "output-json-template.h"
#include "output-lua.h"
#include "output-json-dnp3.h"
typedef struct RootLogger_ {
ThreadInitFunc ThreadInit;
@ -1087,6 +1088,9 @@ void OutputRegisterLoggers(void)
/* json stats */
JsonStatsLogRegister();
/* DNP3. */
JsonDNP3LogRegister();
/* Template JSON logger. */
JsonTemplateLogRegister();
}

@ -361,6 +361,7 @@ typedef enum {
LOGGER_JSON_STATS,
LOGGER_PRELUDE,
LOGGER_PCAP,
LOGGER_JSON_DNP3,
LOGGER_SIZE,
} LoggerId;

@ -841,9 +841,6 @@ void RegisterAllModules()
/* nflog */
TmModuleReceiveNFLOGRegister();
TmModuleDecodeNFLOGRegister();
/* dnp3 */
TmModuleJsonDNP3LogRegister();
}
static TmEcode LoadYamlConfig(SCInstance *suri)

File diff suppressed because it is too large Load Diff

@ -0,0 +1,24 @@
/* Copyright (C) 2015 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef __UTIL_LUA_DNP3_OBJECTS_H__
#define __UTIL_LUA_DNP3_OBJECTS_H__
void DNP3PushPoint(lua_State *luastate, DNP3Object *object,
DNP3Point *item);
#endif /* ! __UTIL_LUA_DNP3_OBJECTS_H__ */

@ -0,0 +1,201 @@
/* Copyright (C) 2015 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include "suricata-common.h"
#include "app-layer-dnp3.h"
#include "app-layer-dnp3-objects.h"
#ifdef HAVE_LUA
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include "util-lua.h"
#include "util-lua-common.h"
#include "util-lua-dnp3-objects.h"
/**
* \brief Helper macro to push key and integer value onto a table.
*/
#define LUA_PUSHT_INT(l, k, v) do { \
lua_pushliteral(luastate, k); \
lua_pushinteger(luastate, v); \
lua_settable(luastate, -3); \
} while (0);
static void DNP3PushPoints(lua_State *luastate, DNP3Object *object)
{
DNP3Point *point;
int i = 1;
TAILQ_FOREACH(point, object->points, next) {
lua_pushinteger(luastate, i++);
lua_newtable(luastate);
lua_pushliteral(luastate, "index");
lua_pushinteger(luastate, point->index);
lua_settable(luastate, -3);
DNP3PushPoint(luastate, object, point);
lua_settable(luastate, -3);
}
}
static void DNP3PushObjects(lua_State *luastate, DNP3ObjectList *objects)
{
DNP3Object *object = NULL;
int i = 1;
TAILQ_FOREACH(object, objects, next) {
lua_pushinteger(luastate, i++);
lua_newtable(luastate);
lua_pushliteral(luastate, "group");
lua_pushinteger(luastate, object->group);
lua_settable(luastate, -3);
lua_pushliteral(luastate, "variation");
lua_pushinteger(luastate, object->variation);
lua_settable(luastate, -3);
lua_pushliteral(luastate, "points");
lua_newtable(luastate);
DNP3PushPoints(luastate, object);
lua_settable(luastate, -3);
lua_settable(luastate, -3);
}
}
static void DNP3PushLinkHeader(lua_State *luastate, DNP3LinkHeader *header)
{
LUA_PUSHT_INT(luastate, "len", header->len);
LUA_PUSHT_INT(luastate, "control", header->control);
LUA_PUSHT_INT(luastate, "dst", header->dst);
LUA_PUSHT_INT(luastate, "src", header->src);
LUA_PUSHT_INT(luastate, "crc", header->crc);
}
static void DNP3PushApplicationHeader(lua_State *luastate,
DNP3ApplicationHeader *header)
{
LUA_PUSHT_INT(luastate, "control", header->control);
LUA_PUSHT_INT(luastate, "function_code", header->function_code);
}
static void DNP3PushRequest(lua_State *luastate, DNP3Transaction *tx)
{
/* Link header. */
lua_pushliteral(luastate, "link_header");
lua_newtable(luastate);
DNP3PushLinkHeader(luastate, &tx->request_lh);
lua_settable(luastate, -3);
/* Transport header. */
LUA_PUSHT_INT(luastate, "transport_header", tx->request_th);
/* Application header. */
lua_pushliteral(luastate, "application_header");
lua_newtable(luastate);
DNP3PushApplicationHeader(luastate, &tx->request_ah);
lua_settable(luastate, -3);
lua_pushliteral(luastate, "objects");
lua_newtable(luastate);
DNP3PushObjects(luastate, &tx->request_objects);
lua_settable(luastate, -3);
}
static void DNP3PushResponse(lua_State *luastate, DNP3Transaction *tx)
{
/* Link header. */
lua_pushliteral(luastate, "link_header");
lua_newtable(luastate);
DNP3PushLinkHeader(luastate, &tx->response_lh);
lua_settable(luastate, -3);
/* Transport header. */
LUA_PUSHT_INT(luastate, "transport_header", tx->response_th);
/* Application header. */
lua_pushliteral(luastate, "application_header");
lua_newtable(luastate);
DNP3PushApplicationHeader(luastate, &tx->response_ah);
lua_settable(luastate, -3);
/* Internal indicators. */
LUA_PUSHT_INT(luastate, "indicators",
tx->response_iin.iin1 << 8 | tx->response_iin.iin2);
lua_pushliteral(luastate, "objects");
lua_newtable(luastate);
DNP3PushObjects(luastate, &tx->response_objects);
lua_settable(luastate, -3);
}
static int DNP3GetTx(lua_State *luastate)
{
if (!LuaStateNeedProto(luastate, ALPROTO_DNP3)) {
return LuaCallbackError(luastate, "error: protocol not dnp3");
}
DNP3Transaction *tx = LuaStateGetTX(luastate);
if (tx == NULL) {
return LuaCallbackError(luastate, "error: no tx");
}
lua_newtable(luastate);
lua_pushliteral(luastate, "tx_num");
lua_pushinteger(luastate, tx->tx_num);
lua_settable(luastate, -3);
LUA_PUSHT_INT(luastate, "has_request", tx->has_request);
if (tx->has_request) {
lua_pushliteral(luastate, "request");
lua_newtable(luastate);
LUA_PUSHT_INT(luastate, "done", tx->request_done);
LUA_PUSHT_INT(luastate, "complete", tx->request_complete);
DNP3PushRequest(luastate, tx);
lua_settable(luastate, -3);
}
LUA_PUSHT_INT(luastate, "has_response", tx->has_response);
if (tx->has_response) {
lua_pushliteral(luastate, "response");
lua_newtable(luastate);
LUA_PUSHT_INT(luastate, "done", tx->response_done);
LUA_PUSHT_INT(luastate, "complete", tx->response_complete);
DNP3PushResponse(luastate, tx);
lua_settable(luastate, -3);
}
return 1;
}
int LuaRegisterDNP3Functions(lua_State *luastate)
{
lua_pushcfunction(luastate, DNP3GetTx);
lua_setglobal(luastate, "DNP3GetTx");
return 0;
}
#endif /* HAVE_LUA */

@ -0,0 +1,27 @@
/* Copyright (C) 2015 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef __UTIL_LUA_DNP3_H__
#define __UTIL_LUA_DNP3_H__
#ifdef HAVE_LUA
int LuaRegisterDNP3Functions(lua_State *);
#endif /* HAVE_LUA */
#endif /* !__UTIL_LUA_DNP3_H__ */
Loading…
Cancel
Save