mirror of https://github.com/OISF/suricata
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
4.5 KiB
C
135 lines
4.5 KiB
C
/*
|
|
* 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>
|
|
*
|
|
* Implements the Modbus function and access keywords
|
|
* You can specify a:
|
|
* - concrete function like Modbus:
|
|
* function 8, subfunction 4 (diagnostic: Force Listen Only Mode)
|
|
* - data (in primary table) register access (r/w) like Modbus:
|
|
* access read coils, address 1000 (.i.e Read coils: at address 1000)
|
|
* - write data value at specific address Modbus:
|
|
* access write, address 1500<>2000, value >2000 (Write multiple coils/register:
|
|
* at address between 1500 and 2000 value greater than 2000)
|
|
*/
|
|
|
|
#include "suricata-common.h"
|
|
|
|
#include "detect.h"
|
|
#include "detect-parse.h"
|
|
#include "detect-engine.h"
|
|
|
|
#include "detect-modbus.h"
|
|
|
|
#include "util-debug.h"
|
|
#include "util-byte.h"
|
|
|
|
#include "stream-tcp.h"
|
|
#include "rust.h"
|
|
|
|
static int g_modbus_buffer_id = 0;
|
|
|
|
/** \internal
|
|
*
|
|
* \brief this function will free memory associated with DetectModbus
|
|
*
|
|
* \param ptr pointer to DetectModbus
|
|
*/
|
|
static void DetectModbusFree(DetectEngineCtx *de_ctx, void *ptr) {
|
|
SCEnter();
|
|
if (ptr != NULL) {
|
|
rs_modbus_free(ptr);
|
|
}
|
|
SCReturn;
|
|
}
|
|
|
|
/** \internal
|
|
*
|
|
* \brief this function is used to add the parsed "id" option into the current signature
|
|
*
|
|
* \param de_ctx Pointer to the Detection Engine Context
|
|
* \param s Pointer to the Current Signature
|
|
* \param str Pointer to the user provided "id" option
|
|
*
|
|
* \retval 0 on Success or -1 on Failure
|
|
*/
|
|
static int DetectModbusSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
|
|
{
|
|
SCEnter();
|
|
DetectModbusRust *modbus = NULL;
|
|
|
|
if (DetectSignatureSetAppProto(s, ALPROTO_MODBUS) != 0)
|
|
return -1;
|
|
|
|
if ((modbus = rs_modbus_parse(str)) == NULL) {
|
|
SCLogError("invalid modbus option");
|
|
goto error;
|
|
}
|
|
|
|
/* Okay so far so good, lets get this into a SigMatch and put it in the Signature. */
|
|
if (SigMatchAppendSMToList(
|
|
de_ctx, s, DETECT_AL_MODBUS, (SigMatchCtx *)modbus, g_modbus_buffer_id) == NULL) {
|
|
goto error;
|
|
}
|
|
|
|
SCReturnInt(0);
|
|
|
|
error:
|
|
if (modbus != NULL)
|
|
DetectModbusFree(de_ctx, modbus);
|
|
SCReturnInt(-1);
|
|
}
|
|
|
|
static int DetectModbusMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, void *state,
|
|
void *txv, const Signature *s, const SigMatchCtx *ctx)
|
|
{
|
|
return rs_modbus_inspect(txv, (void *)ctx);
|
|
}
|
|
|
|
/**
|
|
* \brief Registration function for Modbus keyword
|
|
*/
|
|
void DetectModbusRegister(void)
|
|
{
|
|
sigmatch_table[DETECT_AL_MODBUS].name = "modbus";
|
|
sigmatch_table[DETECT_AL_MODBUS].desc = "match on various properties of Modbus requests";
|
|
sigmatch_table[DETECT_AL_MODBUS].url = "/rules/modbus-keyword.html#modbus-keyword";
|
|
sigmatch_table[DETECT_AL_MODBUS].Match = NULL;
|
|
sigmatch_table[DETECT_AL_MODBUS].Setup = DetectModbusSetup;
|
|
sigmatch_table[DETECT_AL_MODBUS].Free = DetectModbusFree;
|
|
sigmatch_table[DETECT_AL_MODBUS].AppLayerTxMatch = DetectModbusMatch;
|
|
|
|
DetectAppLayerInspectEngineRegister(
|
|
"modbus", ALPROTO_MODBUS, SIG_FLAG_TOSERVER, 0, DetectEngineInspectGenericList, NULL);
|
|
|
|
g_modbus_buffer_id = DetectBufferTypeGetByName("modbus");
|
|
}
|