modbus: move tests from c to rust

Move tests in a seperate commit so that we can use the previous one for
regression testing. This also gets rid of the temporary glue that made
the C tests work with the rust implementation.
pull/6101/head
Simon Dugas 5 years ago committed by Victor Julien
parent a458a94dca
commit 8342641477

File diff suppressed because it is too large Load Diff

@ -143,7 +143,6 @@ noinst_HEADERS = \
detect-engine.h \
detect-engine-iponly.h \
detect-engine-loader.h \
detect-engine-modbus.h \
detect-engine-mpm.h \
detect-engine-payload.h \
detect-engine-port.h \
@ -722,7 +721,6 @@ libsuricata_c_a_SOURCES = \
detect-engine-file.c \
detect-engine-iponly.c \
detect-engine-loader.c \
detect-engine-modbus.c \
detect-engine-mpm.c \
detect-engine-payload.c \
detect-engine-port.c \

@ -34,32 +34,6 @@
#ifndef __APP_LAYER_MODBUS_H__
#define __APP_LAYER_MODBUS_H__
/* Modbus Function Code Categories. */
#define MODBUS_CAT_NONE 0x0
#define MODBUS_CAT_PUBLIC_ASSIGNED (1<<0)
#define MODBUS_CAT_PUBLIC_UNASSIGNED (1<<1)
#define MODBUS_CAT_USER_DEFINED (1<<2)
#define MODBUS_CAT_RESERVED (1<<3)
#define MODBUS_CAT_ALL 0xFF
/* Modbus Read/Write function and Access Types. */
#define MODBUS_TYP_NONE 0x0
#define MODBUS_TYP_ACCESS_MASK 0x03
#define MODBUS_TYP_READ (1<<0)
#define MODBUS_TYP_WRITE (1<<1)
#define MODBUS_TYP_ACCESS_FUNCTION_MASK 0x3C
#define MODBUS_TYP_BIT_ACCESS_MASK 0x0C
#define MODBUS_TYP_DISCRETES (1<<2)
#define MODBUS_TYP_COILS (1<<3)
#define MODBUS_TYP_WORD_ACCESS_MASK 0x30
#define MODBUS_TYP_INPUT (1<<4)
#define MODBUS_TYP_HOLDING (1<<5)
#define MODBUS_TYP_SINGLE (1<<6)
#define MODBUS_TYP_MULTIPLE (1<<7)
#define MODBUS_TYP_WRITE_SINGLE (MODBUS_TYP_WRITE | MODBUS_TYP_SINGLE)
#define MODBUS_TYP_WRITE_MULTIPLE (MODBUS_TYP_WRITE | MODBUS_TYP_MULTIPLE)
#define MODBUS_TYP_READ_WRITE_MULTIPLE (MODBUS_TYP_READ | MODBUS_TYP_WRITE | MODBUS_TYP_MULTIPLE)
void RegisterModbusParsers(void);
#endif /* __APP_LAYER_MODBUS_H__ */

File diff suppressed because it is too large Load Diff

@ -1,41 +0,0 @@
/*
* Copyright (C) 2014 ANSSI
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** \file
*
* \author David DIALLO <diallo@et.esiea.fr>
*/
#ifndef __DETECT_ENGINE_MODBUS_H__
#define __DETECT_ENGINE_MODBUS_H__
int DetectEngineInspectModbus(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *,
const struct DetectEngineAppInspectionEngine_ *engine, const Signature *, Flow *, uint8_t,
void *, void *, uint64_t);
void DetectEngineInspectModbusRegisterTests(void);
#endif /* __DETECT_ENGINE_MODBUS_H__ */

@ -52,8 +52,6 @@
#include "util-debug.h"
#include "util-byte.h"
#include "app-layer-modbus.h"
#include "stream-tcp.h"
#include "rust.h"
@ -170,502 +168,170 @@ void DetectModbusRegister(void)
}
#ifdef UNITTESTS /* UNITTESTS */
#include "util-unittest.h"
/** Convert rust structure to C for regression tests.
*
* Note: Newly allocated `DetectModbus` structure must be freed.
*
* TODO: remove this after regression testing commit.
*/
static DetectModbusValue *DetectModbusValueRustToC(uint16_t min, uint16_t max)
{
DetectModbusValue *value = SCMalloc(sizeof(*value));
FAIL_IF_NULL(value);
value->min = min;
value->max = max;
if (min == max) {
value->mode = DETECT_MODBUS_EQ;
} else if (min == 0) {
value->mode = DETECT_MODBUS_LT;
} else if (max == UINT16_MAX) {
value->mode = DETECT_MODBUS_GT;
} else {
value->mode = DETECT_MODBUS_RA;
}
return value;
}
static DetectModbus *DetectModbusRustToC(DetectModbusRust *ctx)
{
DetectModbus *modbus = SCMalloc(sizeof(*modbus));
FAIL_IF_NULL(modbus);
modbus->category = rs_modbus_get_category(ctx);
modbus->function = rs_modbus_get_function(ctx);
modbus->subfunction = rs_modbus_get_subfunction(ctx);
modbus->has_subfunction = rs_modbus_get_has_subfunction(ctx);
modbus->type = rs_modbus_get_access_type(ctx);
modbus->unit_id = DetectModbusValueRustToC(
rs_modbus_get_unit_id_min(ctx), rs_modbus_get_unit_id_max(ctx));
modbus->address = DetectModbusValueRustToC(
rs_modbus_get_address_min(ctx), rs_modbus_get_address_max(ctx));
modbus->data =
DetectModbusValueRustToC(rs_modbus_get_data_min(ctx), rs_modbus_get_data_max(ctx));
return modbus;
}
static void DetectModbusCFree(DetectModbus *modbus)
{
if (modbus) {
if (modbus->unit_id)
SCFree(modbus->unit_id);
if (modbus->address)
SCFree(modbus->address);
if (modbus->data)
SCFree(modbus->data);
SCFree(modbus);
}
}
/** \test Signature containing a function. */
static int DetectModbusTest01(void)
{
DetectEngineCtx *de_ctx = NULL;
DetectModbus *modbus = NULL;
de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
"(msg:\"Testing modbus function\"; "
"modbus: function 1; sid:1;)");
FAIL_IF_NULL(de_ctx->sig_list);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
modbus = DetectModbusRustToC(
(DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
FAIL_IF_NOT(modbus->function == 1);
DetectModbusCFree(modbus);
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
PASS;
}
/** \test Signature containing a function and a subfunction. */
static int DetectModbusTest02(void)
{
DetectEngineCtx *de_ctx = NULL;
DetectModbus *modbus = NULL;
de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
#include "app-layer-parser.h"
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
"(msg:\"Testing modbus function and subfunction\"; "
"modbus: function 8, subfunction 4; sid:1;)");
FAIL_IF_NULL(de_ctx->sig_list);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
modbus = DetectModbusRustToC(
(DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
FAIL_IF_NOT(modbus->function == 8);
FAIL_IF_NOT(modbus->subfunction == 4);
DetectModbusCFree(modbus);
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
PASS;
}
/** \test Signature containing a function category. */
static int DetectModbusTest03(void)
{
DetectEngineCtx *de_ctx = NULL;
DetectModbus *modbus = NULL;
de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
"(msg:\"Testing modbus.function\"; "
"modbus: function reserved; sid:1;)");
FAIL_IF_NULL(de_ctx->sig_list);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
modbus = DetectModbusRustToC(
(DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
FAIL_IF_NOT(modbus->category == MODBUS_CAT_RESERVED);
DetectModbusCFree(modbus);
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
PASS;
}
/** \test Signature containing a negative function category. */
static int DetectModbusTest04(void)
{
DetectEngineCtx *de_ctx = NULL;
DetectModbus *modbus = NULL;
de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
"(msg:\"Testing modbus function\"; "
"modbus: function !assigned; sid:1;)");
FAIL_IF_NULL(de_ctx->sig_list);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
modbus = DetectModbusRustToC(
(DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
FAIL_IF(modbus->category & MODBUS_CAT_PUBLIC_ASSIGNED);
FAIL_IF_NOT(modbus->category & MODBUS_CAT_PUBLIC_UNASSIGNED);
FAIL_IF_NOT(modbus->category & MODBUS_CAT_USER_DEFINED);
FAIL_IF_NOT(modbus->category & MODBUS_CAT_RESERVED);
#include "flow-util.h"
DetectModbusCFree(modbus);
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
PASS;
}
/** \test Signature containing a access type. */
static int DetectModbusTest05(void)
{
DetectEngineCtx *de_ctx = NULL;
DetectModbus *modbus = NULL;
de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
"(msg:\"Testing modbus.access\"; "
"modbus: access read; sid:1;)");
FAIL_IF_NULL(de_ctx->sig_list);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
modbus = DetectModbusRustToC(
(DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
FAIL_IF_NOT(modbus->type == MODBUS_TYP_READ);
DetectModbusCFree(modbus);
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
PASS;
}
#include "util-unittest.h"
#include "util-unittest-helper.h"
/** \test Signature containing a access function. */
static int DetectModbusTest06(void)
/**
* Sample data for tests derived from
* https://github.com/bro/bro/blob/master/testing/btest/Traces/modbus/modbus.trace
*/
static uint8_t writeSingleCoil[] = {
/* Transaction ID */ 0x00, 0x01,
/* Protocol ID */ 0x00, 0x00,
/* Length */ 0x00, 0x06,
/* Unit ID */ 0x0a,
/* Function code */ 0x05,
/* Read Starting Address */ 0x00, 0x02,
/* Data */ 0x00, 0x00
};
static uint8_t restartCommOption[] = {
/* Transaction ID */ 0x00, 0x00,
/* Protocol ID */ 0x00, 0x00,
/* Length */ 0x00, 0x06,
/* Unit ID */ 0x0a,
/* Function code */ 0x08,
/* Diagnostic Code */ 0x00, 0x01,
/* Data */ 0x00, 0x00
};
/** \test Signature containing an access type. */
static int DetectModbusTestAccess(void)
{
AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
DetectEngineThreadCtx *det_ctx = NULL;
DetectEngineCtx *de_ctx = NULL;
DetectModbus *modbus = NULL;
uint8_t type = (MODBUS_TYP_READ | MODBUS_TYP_DISCRETES);
Flow f;
Packet *p = NULL;
Signature *s = NULL;
TcpSession ssn;
ThreadVars tv;
de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
"(msg:\"Testing modbus.access\"; "
"modbus: access read discretes; sid:1;)");
FAIL_IF_NULL(de_ctx->sig_list);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
FAIL_IF_NULL(alp_tctx);
modbus = DetectModbusRustToC(
(DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
memset(&tv, 0, sizeof(ThreadVars));
memset(&f, 0, sizeof(Flow));
memset(&ssn, 0, sizeof(TcpSession));
FAIL_IF_NOT(modbus->type == type);
p = UTHBuildPacket(restartCommOption, sizeof(restartCommOption), IPPROTO_TCP);
DetectModbusCFree(modbus);
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
PASS;
}
FLOW_INITIALIZE(&f);
f.alproto = ALPROTO_MODBUS;
f.protoctx = (void *)&ssn;
f.proto = IPPROTO_TCP;
f.flags |= FLOW_IPV4;
/** \test Signature containing a read access at an address. */
static int DetectModbusTest07(void)
{
DetectEngineCtx *de_ctx = NULL;
DetectModbus *modbus = NULL;
DetectModbusMode mode = DETECT_MODBUS_EQ;
p->flow = &f;
p->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
p->flowflags |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
uint8_t type = MODBUS_TYP_READ;
StreamTcpInitConfig(TRUE);
de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
de_ctx->flags |= DE_QUIET;
s = de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
"(msg:\"Testing modbus code function\"; "
"modbus: access write; sid:1;)");
FAIL_IF_NULL(s);
de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
"(msg:\"Testing modbus.access\"; "
"modbus: access read, address 1000; sid:1;)");
FAIL_IF_NULL(de_ctx->sig_list);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
modbus = DetectModbusRustToC(
(DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
FAIL_IF_NOT(modbus->type == type);
FAIL_IF_NOT((*modbus->address).mode == mode);
FAIL_IF_NOT((*modbus->address).min == 1000);
FLOWLOCK_WRLOCK(&f);
int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOSERVER,
writeSingleCoil, sizeof(writeSingleCoil));
FAIL_IF_NOT(r == 0);
FLOWLOCK_UNLOCK(&f);
DetectModbusCFree(modbus);
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
PASS;
}
/** \test Signature containing a write access at a range of address. */
static int DetectModbusTest08(void)
{
DetectEngineCtx *de_ctx = NULL;
DetectModbus *modbus = NULL;
DetectModbusMode mode = DETECT_MODBUS_GT;
uint8_t type = (MODBUS_TYP_WRITE | MODBUS_TYP_COILS);
de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
"(msg:\"Testing modbus.access\"; "
"modbus: access write coils, address >500; sid:1;)");
FAIL_IF_NULL(de_ctx->sig_list);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
FAIL_IF_NULL(f.alstate);
modbus = DetectModbusRustToC(
(DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
/* do detect */
SigMatchSignatures(&tv, de_ctx, det_ctx, p);
FAIL_IF_NOT(modbus->type == type);
FAIL_IF_NOT((*modbus->address).mode == mode);
FAIL_IF_NOT((*modbus->address).min == 500);
FAIL_IF_NOT(PacketAlertCheck(p, 1));
DetectModbusCFree(modbus);
AppLayerParserThreadCtxFree(alp_tctx);
DetectEngineThreadCtxDeinit(&tv, det_ctx);
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
PASS;
}
/** \test Signature containing a write access at a address a range of value. */
static int DetectModbusTest09(void)
{
DetectEngineCtx *de_ctx = NULL;
DetectModbus *modbus = NULL;
DetectModbusMode addressMode = DETECT_MODBUS_EQ;
DetectModbusMode valueMode = DETECT_MODBUS_RA;
uint8_t type = (MODBUS_TYP_WRITE | MODBUS_TYP_HOLDING);
de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
"(msg:\"Testing modbus.access\"; "
"modbus: access write holding, address 100, value 500<>1000; sid:1;)");
FAIL_IF_NULL(de_ctx->sig_list);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
modbus = DetectModbusRustToC(
(DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
FAIL_IF_NOT(modbus->type == type);
FAIL_IF_NOT((*modbus->address).mode == addressMode);
FAIL_IF_NOT((*modbus->address).min == 100);
FAIL_IF_NOT((*modbus->data).mode == valueMode);
FAIL_IF_NOT((*modbus->data).min == 500);
FAIL_IF_NOT((*modbus->data).max == 1000);
DetectModbusCFree(modbus);
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
StreamTcpFreeConfig(TRUE);
FLOW_DESTROY(&f);
UTHFreePacket(p);
PASS;
}
/** \test Signature containing a unit_id. */
static int DetectModbusTest10(void)
/** \test Signature containing a function. */
static int DetectModbusTestFunction(void)
{
AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
DetectEngineThreadCtx *det_ctx = NULL;
DetectEngineCtx *de_ctx = NULL;
DetectModbus *modbus = NULL;
DetectModbusMode mode = DETECT_MODBUS_EQ;
de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
Flow f;
Packet *p = NULL;
Signature *s = NULL;
TcpSession ssn;
ThreadVars tv;
de_ctx->flags |= DE_QUIET;
FAIL_IF_NULL(alp_tctx);
de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
"(msg:\"Testing modbus unit_id\"; "
"modbus: unit 10; sid:1;)");
FAIL_IF_NULL(de_ctx->sig_list);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
memset(&tv, 0, sizeof(ThreadVars));
memset(&f, 0, sizeof(Flow));
memset(&ssn, 0, sizeof(TcpSession));
modbus = DetectModbusRustToC(
(DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
p = UTHBuildPacket(writeSingleCoil, sizeof(writeSingleCoil), IPPROTO_TCP);
FAIL_IF_NOT((*modbus->unit_id).min == 10);
FAIL_IF_NOT((*modbus->unit_id).mode == mode);
FLOW_INITIALIZE(&f);
f.alproto = ALPROTO_MODBUS;
f.protoctx = (void *)&ssn;
f.proto = IPPROTO_TCP;
f.flags |= FLOW_IPV4;
DetectModbusCFree(modbus);
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
PASS;
}
p->flow = &f;
p->flags |= PKT_HAS_FLOW | PKT_STREAM_EST;
p->flowflags |= FLOW_PKT_TOSERVER | FLOW_PKT_ESTABLISHED;
/** \test Signature containing a unit_id, a function and a subfunction. */
static int DetectModbusTest11(void)
{
DetectEngineCtx *de_ctx = NULL;
DetectModbus *modbus = NULL;
DetectModbusMode mode = DETECT_MODBUS_EQ;
StreamTcpInitConfig(TRUE);
de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
de_ctx->flags |= DE_QUIET;
s = de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
"(msg:\"Testing modbus code function\"; "
"modbus: function 8; sid:1;)");
FAIL_IF_NULL(s);
de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
"(msg:\"Testing modbus function and subfunction\"; "
"modbus: unit 10, function 8, subfunction 4; sid:1;)");
FAIL_IF_NULL(de_ctx->sig_list);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
modbus = DetectModbusRustToC(
(DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
FAIL_IF_NOT((*modbus->unit_id).min == 10);
FAIL_IF_NOT((*modbus->unit_id).mode == mode);
FAIL_IF_NOT(modbus->function == 8);
FAIL_IF_NOT(modbus->subfunction == 4);
FLOWLOCK_WRLOCK(&f);
int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_MODBUS, STREAM_TOSERVER,
restartCommOption, sizeof(restartCommOption));
FAIL_IF_NOT(r == 0);
FLOWLOCK_UNLOCK(&f);
DetectModbusCFree(modbus);
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
PASS;
}
FAIL_IF_NULL(f.alstate);
/** \test Signature containing an unit_id and a read access at an address. */
static int DetectModbusTest12(void)
{
DetectEngineCtx *de_ctx = NULL;
DetectModbus *modbus = NULL;
DetectModbusMode mode = DETECT_MODBUS_EQ;
/* do detect */
SigMatchSignatures(&tv, de_ctx, det_ctx, p);
uint8_t type = MODBUS_TYP_READ;
FAIL_IF_NOT(PacketAlertCheck(p, 1));
de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
"(msg:\"Testing modbus.access\"; "
"modbus: unit 10, access read, address 1000; sid:1;)");
FAIL_IF_NULL(de_ctx->sig_list);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
modbus = DetectModbusRustToC(
(DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
FAIL_IF_NOT((*modbus->unit_id).min == 10);
FAIL_IF_NOT((*modbus->unit_id).mode == mode);
FAIL_IF_NOT(modbus->type == type);
FAIL_IF_NOT((*modbus->address).mode == mode);
FAIL_IF_NOT((*modbus->address).min == 1000);
DetectModbusCFree(modbus);
AppLayerParserThreadCtxFree(alp_tctx);
DetectEngineThreadCtxDeinit(&tv, det_ctx);
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
PASS;
}
/** \test Signature containing a range of unit_id. */
static int DetectModbusTest13(void)
{
DetectEngineCtx *de_ctx = NULL;
DetectModbus *modbus = NULL;
DetectModbusMode mode = DETECT_MODBUS_RA;
de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
de_ctx->flags |= DE_QUIET;
de_ctx->sig_list = SigInit(de_ctx, "alert modbus any any -> any any "
"(msg:\"Testing modbus.access\"; "
"modbus: unit 10<>500; sid:1;)");
FAIL_IF_NULL(de_ctx->sig_list);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]);
FAIL_IF_NULL(de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
modbus = DetectModbusRustToC(
(DetectModbusRust *)de_ctx->sig_list->sm_lists_tail[g_modbus_buffer_id]->ctx);
FAIL_IF_NOT((*modbus->unit_id).min == 10);
FAIL_IF_NOT((*modbus->unit_id).max == 500);
FAIL_IF_NOT((*modbus->unit_id).mode == mode);
DetectModbusCFree(modbus);
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
StreamTcpFreeConfig(TRUE);
FLOW_DESTROY(&f);
UTHFreePacket(p);
PASS;
}
@ -674,31 +340,7 @@ static int DetectModbusTest13(void)
*/
void DetectModbusRegisterTests(void)
{
UtRegisterTest("DetectModbusTest01 - Testing function",
DetectModbusTest01);
UtRegisterTest("DetectModbusTest02 - Testing function and subfunction",
DetectModbusTest02);
UtRegisterTest("DetectModbusTest03 - Testing category function",
DetectModbusTest03);
UtRegisterTest("DetectModbusTest04 - Testing category function in negative",
DetectModbusTest04);
UtRegisterTest("DetectModbusTest05 - Testing access type",
DetectModbusTest05);
UtRegisterTest("DetectModbusTest06 - Testing access function",
DetectModbusTest06);
UtRegisterTest("DetectModbusTest07 - Testing access at address",
DetectModbusTest07);
UtRegisterTest("DetectModbusTest08 - Testing a range of address",
DetectModbusTest08);
UtRegisterTest("DetectModbusTest09 - Testing write a range of value",
DetectModbusTest09);
UtRegisterTest("DetectModbusTest10 - Testing unit_id",
DetectModbusTest10);
UtRegisterTest("DetectModbusTest11 - Testing unit_id, function and subfunction",
DetectModbusTest11);
UtRegisterTest("DetectModbusTest12 - Testing unit_id and access at address",
DetectModbusTest12);
UtRegisterTest("DetectModbusTest13 - Testing a range of unit_id",
DetectModbusTest13);
UtRegisterTest("DetectModbusTestAccess", DetectModbusTestAccess);
UtRegisterTest("DetectModbusTestFunction", DetectModbusTestFunction);
}
#endif /* UNITTESTS */

@ -34,32 +34,6 @@
#ifndef __DETECT_MODBUS_H__
#define __DETECT_MODBUS_H__
#include "app-layer-modbus.h"
typedef enum {
DETECT_MODBUS_EQ = 0, /** < EQual operator */
DETECT_MODBUS_LT, /** < "Less Than" operator */
DETECT_MODBUS_GT, /** < "Greater Than" operator */
DETECT_MODBUS_RA, /** < RAnge operator */
} DetectModbusMode;
typedef struct DetectModbusValue_ {
uint16_t min; /** < Modbus minimum [range] or equal value to match */
uint16_t max; /** < Modbus maximum value [range] to match */
DetectModbusMode mode; /** < Modbus operator used in the address/data signature */
} DetectModbusValue;
typedef struct DetectModbus_ {
uint8_t category; /** < Modbus function code category to match */
uint8_t function; /** < Modbus function code to match */
uint16_t subfunction; /** < Modbus subfunction to match */
bool has_subfunction; /** < Modbus subfunction indicator */
uint8_t type; /** < Modbus access type to match */
DetectModbusValue *unit_id; /** < Modbus unit id to match */
DetectModbusValue *address; /** < Modbus address to match */
DetectModbusValue *data; /** < Modbus data to match */
} DetectModbus;
/* prototypes */
void DetectModbusRegister(void);

@ -37,7 +37,6 @@
#include "detect-engine-dcepayload.h"
#include "detect-engine-state.h"
#include "detect-engine-tag.h"
#include "detect-engine-modbus.h"
#include "detect-fast-pattern.h"
#include "flow.h"
#include "flow-timeout.h"
@ -184,7 +183,6 @@ static void RegisterUnittests(void)
#endif
DeStateRegisterTests();
MemcmpRegisterTests();
DetectEngineInspectModbusRegisterTests();
DetectEngineRegisterTests();
SCLogRegisterTests();
MagicRegisterTests();

Loading…
Cancel
Save