detect/krb5: move krb5_msg_type to rust

Makes it a generic u32 on the way

Unit tests are covered by SV tests

Ticket: 6723
pull/13892/head
Philippe Antoine 1 year ago committed by Victor Julien
parent 5a4d280461
commit 0553dfa814

@ -7,6 +7,8 @@ krb5_msg_type
This keyword allows to match the Kerberos messages by its type (integer). This keyword allows to match the Kerberos messages by its type (integer).
It is possible to specify the following values defined in RFC4120: It is possible to specify the following values defined in RFC4120:
krb5_msg_type uses :ref:`unsigned 32-bit integer <rules-integer-keywords>`.
* 10 (AS-REQ) * 10 (AS-REQ)
* 11 (AS-REP) * 11 (AS-REP)
* 12 (TGS-REQ) * 12 (TGS-REQ)
@ -15,15 +17,15 @@ It is possible to specify the following values defined in RFC4120:
Syntax:: Syntax::
krb5_msg_type:<number> krb5_msg_type:(mode) <number or string>
Signature examples:: Signature examples::
alert krb5 any any -> any any (msg:"Kerberos 5 AS-REQ message"; krb5_msg_type:10; sid:3; rev:1;) alert krb5 any any -> any any (msg:"Kerberos 5 AS-REQ message"; krb5_msg_type:10; sid:3; rev:1;)
alert krb5 any any -> any any (msg:"Kerberos 5 AS-REP message"; krb5_msg_type:11; sid:4; rev:1;) alert krb5 any any -> any any (msg:"Kerberos 5 AS-REP message"; krb5_msg_type:AS_REP; sid:4; rev:1;)
alert krb5 any any -> any any (msg:"Kerberos 5 TGS-REQ message"; krb5_msg_type:12; sid:5; rev:1;) alert krb5 any any -> any any (msg:"Kerberos 5 TGS-REQ message"; krb5_msg_type:12; sid:5; rev:1;)
alert krb5 any any -> any any (msg:"Kerberos 5 TGS-REP message"; krb5_msg_type:13; sid:6; rev:1;) alert krb5 any any -> any any (msg:"Kerberos 5 TGS-REP message"; krb5_msg_type:13; sid:6; rev:1;)
alert krb5 any any -> any any (msg:"Kerberos 5 ERROR message"; krb5_msg_type:30; sid:7; rev:1;) alert krb5 any any -> any any (msg:"Kerberos 5 not ERROR message"; krb5_msg_type:!30; sid:7; rev:1;)
.. note:: AP-REQ and AP-REP are not currently supported since those messages .. note:: AP-REQ and AP-REP are not currently supported since those messages

@ -18,8 +18,18 @@
// written by Pierre Chifflier <chifflier@wzdftpd.net> // written by Pierre Chifflier <chifflier@wzdftpd.net>
use crate::krb::krb5::{test_weak_encryption, KRB5Transaction}; use crate::krb::krb5::{test_weak_encryption, KRB5Transaction};
use suricata_sys::sys::DetectEngineThreadCtx; use suricata_sys::sys::AppProtoEnum::ALPROTO_KRB5;
use suricata_sys::sys::{
AppProto, DetectEngineCtx, DetectEngineThreadCtx, Flow, SCDetectHelperBufferRegister,
SCDetectHelperKeywordRegister, SCDetectSignatureSetAppProto, SCSigMatchAppendSMToList,
SCSigTableAppLiteElmt, SigMatchCtx, Signature,
};
use crate::core::{STREAM_TOCLIENT, STREAM_TOSERVER};
use crate::detect::uint::{
detect_parse_uint_enum, DetectUintData, SCDetectU32Free, SCDetectU32Match,
};
use crate::detect::{SIGMATCH_INFO_ENUM_UINT, SIGMATCH_INFO_MULTI_UINT};
use kerberos_parser::krb5::EncryptionType; use kerberos_parser::krb5::EncryptionType;
use nom7::branch::alt; use nom7::branch::alt;
@ -29,14 +39,9 @@ use nom7::combinator::{all_consuming, map_res, opt};
use nom7::multi::many1; use nom7::multi::many1;
use nom7::IResult; use nom7::IResult;
use std::ffi::CStr; use std::ffi::{c_int, CStr};
use std::os::raw::c_void; use std::os::raw::c_void;
#[no_mangle]
pub unsafe extern "C" fn SCKrb5TxGetMsgType(tx: &KRB5Transaction, ptr: *mut u32) {
*ptr = tx.msg_type.0;
}
/// Get error code, if present in transaction /// Get error code, if present in transaction
/// Return 0 if error code was filled, else 1 /// Return 0 if error code was filled, else 1
#[no_mangle] #[no_mangle]
@ -345,3 +350,97 @@ mod tests {
} }
} }
} }
static mut G_KRB5_MSG_TYPE_KW_ID: u16 = 0;
static mut G_KRB5_MSG_TYPE_BUFFER_ID: c_int = 0;
// We should apply the derive on the kerberos_parser MessageType
#[repr(u32)]
#[derive(EnumStringU32)]
#[allow(non_camel_case_types)]
pub enum Krb5MessageType {
AS_REQ = 10,
AS_REP = 11,
TGS_REQ = 12,
TGS_REP = 13,
AP_REQ = 14,
AP_REP = 15,
RESERVED16 = 16,
RESERVED17 = 17,
SAFE = 20,
PRIV = 21,
CRED = 22,
ERROR = 30,
}
unsafe extern "C" fn krb5_parse_msg_type(
ustr: *const std::os::raw::c_char,
) -> *mut DetectUintData<u32> {
let ft_name: &CStr = CStr::from_ptr(ustr); //unsafe
if let Ok(s) = ft_name.to_str() {
if let Some(ctx) = detect_parse_uint_enum::<u32, Krb5MessageType>(s) {
let boxed = Box::new(ctx);
return Box::into_raw(boxed) as *mut _;
}
}
return std::ptr::null_mut();
}
unsafe extern "C" fn krb5_msg_type_setup(
de: *mut DetectEngineCtx, s: *mut Signature, raw: *const libc::c_char,
) -> c_int {
if SCDetectSignatureSetAppProto(s, ALPROTO_KRB5 as AppProto) != 0 {
return -1;
}
let ctx = krb5_parse_msg_type(raw) as *mut c_void;
if ctx.is_null() {
return -1;
}
if SCSigMatchAppendSMToList(
de,
s,
G_KRB5_MSG_TYPE_KW_ID,
ctx as *mut SigMatchCtx,
G_KRB5_MSG_TYPE_BUFFER_ID,
)
.is_null()
{
krb5_msg_type_free(std::ptr::null_mut(), ctx);
return -1;
}
return 0;
}
unsafe extern "C" fn krb5_msg_type_match(
_de: *mut DetectEngineThreadCtx, _f: *mut Flow, _flags: u8, _state: *mut c_void,
tx: *mut c_void, _sig: *const Signature, ctx: *const SigMatchCtx,
) -> c_int {
let tx = cast_pointer!(tx, KRB5Transaction);
let ctx = cast_pointer!(ctx, DetectUintData<u32>);
// kerberos_parser crate defines MessageType as u32 and not u8...
return SCDetectU32Match(tx.msg_type.0, ctx);
}
unsafe extern "C" fn krb5_msg_type_free(_de: *mut DetectEngineCtx, ctx: *mut c_void) {
let ctx = cast_pointer!(ctx, DetectUintData<u32>);
SCDetectU32Free(ctx);
}
#[no_mangle]
pub unsafe extern "C" fn SCDetectKrb5MsgTypeRegister() {
let kw = SCSigTableAppLiteElmt {
name: b"krb5_msg_type\0".as_ptr() as *const libc::c_char,
desc: b"match Kerberos 5 message type\0".as_ptr() as *const libc::c_char,
url: b"/rules/kerberos-keywords.html#krb5-msg-type\0".as_ptr() as *const libc::c_char,
AppLayerTxMatch: Some(krb5_msg_type_match),
Setup: Some(krb5_msg_type_setup),
Free: Some(krb5_msg_type_free),
flags: SIGMATCH_INFO_MULTI_UINT | SIGMATCH_INFO_ENUM_UINT,
};
G_KRB5_MSG_TYPE_KW_ID = SCDetectHelperKeywordRegister(&kw);
G_KRB5_MSG_TYPE_BUFFER_ID = SCDetectHelperBufferRegister(
b"krb5_msg_type\0".as_ptr() as *const libc::c_char,
ALPROTO_KRB5 as AppProto,
STREAM_TOCLIENT | STREAM_TOSERVER,
);
}

@ -244,7 +244,6 @@ noinst_HEADERS = \
detect-ja4-hash.h \ detect-ja4-hash.h \
detect-krb5-cname.h \ detect-krb5-cname.h \
detect-krb5-errcode.h \ detect-krb5-errcode.h \
detect-krb5-msgtype.h \
detect-krb5-sname.h \ detect-krb5-sname.h \
detect-krb5-ticket-encryption.h \ detect-krb5-ticket-encryption.h \
detect-l3proto.h \ detect-l3proto.h \
@ -845,7 +844,6 @@ libsuricata_c_a_SOURCES = \
detect-ja4-hash.c \ detect-ja4-hash.c \
detect-krb5-cname.c \ detect-krb5-cname.c \
detect-krb5-errcode.c \ detect-krb5-errcode.c \
detect-krb5-msgtype.c \
detect-krb5-sname.c \ detect-krb5-sname.c \
detect-krb5-ticket-encryption.c \ detect-krb5-ticket-encryption.c \
detect-l3proto.c \ detect-l3proto.c \

@ -198,7 +198,6 @@
#include "detect-ipv6hdr.h" #include "detect-ipv6hdr.h"
#include "detect-krb5-cname.h" #include "detect-krb5-cname.h"
#include "detect-krb5-errcode.h" #include "detect-krb5-errcode.h"
#include "detect-krb5-msgtype.h"
#include "detect-krb5-sname.h" #include "detect-krb5-sname.h"
#include "detect-krb5-ticket-encryption.h" #include "detect-krb5-ticket-encryption.h"
#include "detect-sip-method.h" #include "detect-sip-method.h"
@ -742,7 +741,7 @@ void SigTableSetup(void)
DetectIpv6hdrRegister(); DetectIpv6hdrRegister();
DetectKrb5CNameRegister(); DetectKrb5CNameRegister();
DetectKrb5ErrCodeRegister(); DetectKrb5ErrCodeRegister();
DetectKrb5MsgTypeRegister(); SCDetectKrb5MsgTypeRegister();
DetectKrb5SNameRegister(); DetectKrb5SNameRegister();
DetectKrb5TicketEncryptionRegister(); DetectKrb5TicketEncryptionRegister();
DetectSipMethodRegister(); DetectSipMethodRegister();

@ -268,7 +268,6 @@ enum DetectKeywordId {
DETECT_DNP3OBJ, DETECT_DNP3OBJ,
DETECT_KRB5_ERRCODE, DETECT_KRB5_ERRCODE,
DETECT_KRB5_MSGTYPE,
DETECT_KRB5_CNAME, DETECT_KRB5_CNAME,
DETECT_KRB5_SNAME, DETECT_KRB5_SNAME,
DETECT_KRB5_TICKET_ENCRYPTION, DETECT_KRB5_TICKET_ENCRYPTION,

@ -1,243 +0,0 @@
/* Copyright (C) 2018-2020 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.
*/
/**
* \file
*
* \author Pierre Chifflier <chifflier@wzdftpd.net>
*/
#include "suricata-common.h"
#include "util-unittest.h"
#include "util-byte.h"
#include "detect-parse.h"
#include "detect-engine.h"
#include "detect-krb5-msgtype.h"
#include "rust.h"
/**
* \brief Regex for parsing our keyword options
*/
#define PARSE_REGEX "^\\s*([A-z0-9\\.]+|\"[A-z0-9_\\.]+\")\\s*$"
static DetectParseRegex parse_regex;
/* Prototypes of functions registered in DetectKrb5MsgTypeRegister below */
static int DetectKrb5MsgTypeMatch (DetectEngineThreadCtx *, Flow *,
uint8_t, void *, void *, const Signature *,
const SigMatchCtx *);
static int DetectKrb5MsgTypeSetup (DetectEngineCtx *, Signature *, const char *);
static void DetectKrb5MsgTypeFree (DetectEngineCtx *, void *);
#ifdef UNITTESTS
static void DetectKrb5MsgTypeRegisterTests (void);
#endif
static int g_krb5_msg_type_list_id = 0;
/**
* \brief Registration function for krb5_msg_type: keyword
*
* This function is called once in the 'lifetime' of the engine.
*/
void DetectKrb5MsgTypeRegister(void)
{
sigmatch_table[DETECT_KRB5_MSGTYPE].name = "krb5_msg_type";
sigmatch_table[DETECT_KRB5_MSGTYPE].desc = "match Kerberos 5 message type";
sigmatch_table[DETECT_KRB5_MSGTYPE].url = "/rules/kerberos-keywords.html#krb5-msg-type";
sigmatch_table[DETECT_KRB5_MSGTYPE].Match = NULL;
sigmatch_table[DETECT_KRB5_MSGTYPE].AppLayerTxMatch = DetectKrb5MsgTypeMatch;
sigmatch_table[DETECT_KRB5_MSGTYPE].Setup = DetectKrb5MsgTypeSetup;
sigmatch_table[DETECT_KRB5_MSGTYPE].Free = DetectKrb5MsgTypeFree;
#ifdef UNITTESTS
sigmatch_table[DETECT_KRB5_MSGTYPE].RegisterTests = DetectKrb5MsgTypeRegisterTests;
#endif
DetectAppLayerInspectEngineRegister("krb5_msg_type", ALPROTO_KRB5, SIG_FLAG_TOSERVER, 0,
DetectEngineInspectGenericList, NULL);
DetectAppLayerInspectEngineRegister("krb5_msg_type", ALPROTO_KRB5, SIG_FLAG_TOCLIENT, 0,
DetectEngineInspectGenericList, NULL);
/* set up the PCRE for keyword parsing */
DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
g_krb5_msg_type_list_id = DetectBufferTypeRegister("krb5_msg_type");
SCLogDebug("g_krb5_msg_type_list_id %d", g_krb5_msg_type_list_id);
}
/**
* \brief This function is used to match KRB5 rule option on a packet
*
* \param t pointer to thread vars
* \param det_ctx pointer to the pattern matcher thread
* \param p pointer to the current packet
* \param m pointer to the sigmatch with context that we will cast into DetectKrb5Data
*
* \retval 0 no match
* \retval 1 match
*/
static int DetectKrb5MsgTypeMatch (DetectEngineThreadCtx *det_ctx,
Flow *f, uint8_t flags, void *state,
void *txv, const Signature *s,
const SigMatchCtx *ctx)
{
uint32_t msg_type;
const DetectKrb5MsgTypeData *dd = (const DetectKrb5MsgTypeData *)ctx;
SCEnter();
SCKrb5TxGetMsgType(txv, &msg_type);
if (dd->msg_type == msg_type)
SCReturnInt(1);
SCReturnInt(0);
}
/**
* \brief This function is used to parse options passed via krb5_msgtype: keyword
*
* \param krb5str Pointer to the user provided krb5_msg_type options
*
* \retval krb5d pointer to DetectKrb5Data on success
* \retval NULL on failure
*/
static DetectKrb5MsgTypeData *DetectKrb5MsgTypeParse (const char *krb5str)
{
DetectKrb5MsgTypeData *krb5d = NULL;
char arg1[4] = "";
int res = 0;
size_t pcre2len;
pcre2_match_data *match = NULL;
int ret = DetectParsePcreExec(&parse_regex, &match, krb5str, 0, 0);
if (ret != 2) {
SCLogError("parse error, ret %" PRId32 "", ret);
goto error;
}
pcre2len = sizeof(arg1);
res = pcre2_substring_copy_bynumber(match, 1, (PCRE2_UCHAR8 *)arg1, &pcre2len);
if (res < 0) {
SCLogError("pcre2_substring_copy_bynumber failed");
goto error;
}
krb5d = SCMalloc(sizeof (DetectKrb5MsgTypeData));
if (unlikely(krb5d == NULL))
goto error;
if (StringParseUint8(&krb5d->msg_type, 10, 0,
(const char *)arg1) < 0) {
goto error;
}
pcre2_match_data_free(match);
return krb5d;
error:
if (match) {
pcre2_match_data_free(match);
}
if (krb5d)
SCFree(krb5d);
return NULL;
}
/**
* \brief parse the options from the 'krb5_msg_type' keyword in the rule into
* the Signature data structure.
*
* \param de_ctx pointer to the Detection Engine Context
* \param s pointer to the Current Signature
* \param krb5str pointer to the user provided options
*
* \retval 0 on Success
* \retval -1 on Failure
*/
static int DetectKrb5MsgTypeSetup (DetectEngineCtx *de_ctx, Signature *s, const char *krb5str)
{
DetectKrb5MsgTypeData *krb5d = NULL;
if (SCDetectSignatureSetAppProto(s, ALPROTO_KRB5) != 0)
return -1;
krb5d = DetectKrb5MsgTypeParse(krb5str);
if (krb5d == NULL)
goto error;
if (SCSigMatchAppendSMToList(de_ctx, s, DETECT_KRB5_MSGTYPE, (SigMatchCtx *)krb5d,
g_krb5_msg_type_list_id) == NULL) {
goto error;
}
return 0;
error:
if (krb5d != NULL)
DetectKrb5MsgTypeFree(de_ctx, krb5d);
return -1;
}
/**
* \brief this function will free memory associated with DetectKrb5Data
*
* \param ptr pointer to DetectKrb5Data
*/
static void DetectKrb5MsgTypeFree(DetectEngineCtx *de_ctx, void *ptr) {
DetectKrb5MsgTypeData *krb5d = (DetectKrb5MsgTypeData *)ptr;
SCFree(krb5d);
}
#ifdef UNITTESTS
/**
* \test description of the test
*/
static int DetectKrb5MsgTypeParseTest01 (void)
{
DetectKrb5MsgTypeData *krb5d = DetectKrb5MsgTypeParse("10");
FAIL_IF_NULL(krb5d);
FAIL_IF(!(krb5d->msg_type == 10));
DetectKrb5MsgTypeFree(NULL, krb5d);
PASS;
}
static int DetectKrb5MsgTypeSignatureTest01 (void)
{
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
Signature *sig = DetectEngineAppendSig(de_ctx, "alert krb5 any any -> any any (krb5_msg_type:10; sid:1; rev:1;)");
FAIL_IF_NULL(sig);
DetectEngineCtxFree(de_ctx);
PASS;
}
/**
* \brief this function registers unit tests for DetectKrb5MsgType
*/
static void DetectKrb5MsgTypeRegisterTests(void)
{
UtRegisterTest("DetectKrb5MsgTypeParseTest01", DetectKrb5MsgTypeParseTest01);
UtRegisterTest("DetectKrb5MsgTypeSignatureTest01",
DetectKrb5MsgTypeSignatureTest01);
}
#endif /* UNITTESTS */

@ -1,33 +0,0 @@
/* Copyright (C) 2015-2017 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.
*/
/**
* \file
*
* \author Pierre Chifflier <chifflier@wzdftpd.net>
*/
#ifndef SURICATA_DETECT_KRB5_MSGTYPE_H
#define SURICATA_DETECT_KRB5_MSGTYPE_H
typedef struct DetectKrb5MsgTypeData_ {
uint8_t msg_type;
} DetectKrb5MsgTypeData;
void DetectKrb5MsgTypeRegister(void);
#endif /* SURICATA_DETECT_KRB5_MSGTYPE_H */
Loading…
Cancel
Save