detect/krb5: move krb5_err_code to rust

Ticket: 8648

Make it a generic integer on the way
pull/15726/head
Philippe Antoine 2 months ago committed by Victor Julien
parent e560db9d1f
commit 3327cf42f0

@ -88,6 +88,8 @@ Kerberos error code (integer). This field is matched in Kerberos error messages
For a list of error codes, refer to RFC4120 section 7.5.9.
krb5_err_code uses :ref:`unsigned 32-bit integer <rules-integer-keywords>`.
Syntax::
krb5_err_code:<number>

@ -27,7 +27,7 @@ use suricata_sys::sys::{
use crate::core::{STREAM_TOCLIENT, STREAM_TOSERVER};
use crate::detect::uint::{
detect_parse_uint_enum, DetectUintData, SCDetectU32Free, SCDetectU32Match,
detect_parse_uint, detect_parse_uint_enum, DetectUintData, SCDetectU32Free, SCDetectU32Match,
};
use crate::detect::{SIGMATCH_INFO_ENUM_UINT, SIGMATCH_INFO_MULTI_UINT, SIGMATCH_INFO_UINT32};
use kerberos_parser::krb5::EncryptionType;
@ -43,19 +43,6 @@ use nom8::Parser;
use std::ffi::{c_int, CStr};
use std::os::raw::c_void;
/// Get error code, if present in transaction
/// Return 0 if error code was filled, else 1
#[no_mangle]
pub unsafe extern "C" fn SCKrb5TxGetErrorCode(tx: &KRB5Transaction, ptr: *mut i32) -> u32 {
match tx.error_code {
Some(ref e) => {
*ptr = e.0;
0
}
None => 1,
}
}
#[no_mangle]
pub unsafe extern "C" fn SCKrb5TxGetCname(
_de: *mut DetectEngineThreadCtx, tx: *const c_void, _flags: u8, i: u32, buffer: *mut *const u8,
@ -354,7 +341,8 @@ mod tests {
}
static mut G_KRB5_MSG_TYPE_KW_ID: u16 = 0;
static mut G_KRB5_MSG_TYPE_BUFFER_ID: c_int = 0;
static mut G_KRB5_GENERIC_BUFFER_ID: c_int = 0;
static mut G_KRB5_ERR_CODE_KW_ID: u16 = 0;
// We should apply the derive on the kerberos_parser MessageType
#[repr(u32)]
@ -403,7 +391,7 @@ unsafe extern "C" fn krb5_msg_type_setup(
s,
G_KRB5_MSG_TYPE_KW_ID,
ctx as *mut SigMatchCtx,
G_KRB5_MSG_TYPE_BUFFER_ID,
G_KRB5_GENERIC_BUFFER_ID,
)
.is_null()
{
@ -428,8 +416,66 @@ unsafe extern "C" fn krb5_msg_type_free(_de: *mut DetectEngineCtx, ctx: *mut c_v
SCDetectU32Free(ctx);
}
unsafe extern "C" fn krb5_parse_err_code(
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() {
// maybe we should own enumeration
if let Ok((_, ctx)) = detect_parse_uint::<u32>(s) {
let boxed = Box::new(ctx);
return Box::into_raw(boxed) as *mut _;
}
}
return std::ptr::null_mut();
}
unsafe extern "C" fn krb5_err_code_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_err_code(raw) as *mut c_void;
if ctx.is_null() {
return -1;
}
if SCSigMatchAppendSMToList(
de,
s,
G_KRB5_ERR_CODE_KW_ID,
ctx as *mut SigMatchCtx,
G_KRB5_GENERIC_BUFFER_ID,
)
.is_null()
{
krb5_err_code_free(std::ptr::null_mut(), ctx);
return -1;
}
return 0;
}
unsafe extern "C" fn krb5_err_code_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>);
match tx.error_code {
Some(ref e) => {
SCDetectU32Match(e.0 as u32, ctx)
}
None => 0,
}
}
unsafe extern "C" fn krb5_err_code_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() {
pub unsafe extern "C" fn SCDetectKrb5Register() {
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,
@ -440,10 +486,21 @@ pub unsafe extern "C" fn SCDetectKrb5MsgTypeRegister() {
flags: SIGMATCH_INFO_MULTI_UINT | SIGMATCH_INFO_ENUM_UINT | SIGMATCH_INFO_UINT32,
};
G_KRB5_MSG_TYPE_KW_ID = SCDetectHelperKeywordRegister(&kw);
G_KRB5_MSG_TYPE_BUFFER_ID = SCDetectHelperBufferProgressRegister(
b"krb5_msg_type\0".as_ptr() as *const libc::c_char,
G_KRB5_GENERIC_BUFFER_ID = SCDetectHelperBufferProgressRegister(
b"krb5_generic\0".as_ptr() as *const libc::c_char,
ALPROTO_KRB5 as AppProto,
STREAM_TOCLIENT | STREAM_TOSERVER,
1,
);
let kw = SCSigTableAppLiteElmt {
name: b"krb5_err_code\0".as_ptr() as *const libc::c_char,
desc: b"match Kerberos 5 error code\0".as_ptr() as *const libc::c_char,
url: b"/rules/kerberos-keywords.html#krb5-err-code\0".as_ptr() as *const libc::c_char,
AppLayerTxMatch: Some(krb5_err_code_match),
Setup: Some(krb5_err_code_setup),
Free: Some(krb5_err_code_free),
flags: SIGMATCH_INFO_UINT32,
};
G_KRB5_ERR_CODE_KW_ID = SCDetectHelperKeywordRegister(&kw);
}

@ -243,7 +243,6 @@ noinst_HEADERS = \
detect-itype.h \
detect-ja4-hash.h \
detect-krb5-cname.h \
detect-krb5-errcode.h \
detect-krb5-sname.h \
detect-krb5-ticket-encryption.h \
detect-l3proto.h \
@ -824,7 +823,6 @@ libsuricata_c_a_SOURCES = \
detect-itype.c \
detect-ja4-hash.c \
detect-krb5-cname.c \
detect-krb5-errcode.c \
detect-krb5-sname.c \
detect-krb5-ticket-encryption.c \
detect-l3proto.c \

@ -197,7 +197,6 @@
#include "detect-ipv4hdr.h"
#include "detect-ipv6hdr.h"
#include "detect-krb5-cname.h"
#include "detect-krb5-errcode.h"
#include "detect-krb5-sname.h"
#include "detect-krb5-ticket-encryption.h"
#include "detect-sip-method.h"
@ -717,8 +716,6 @@ void SigTableSetup(void)
DetectIpv4hdrRegister();
DetectIpv6hdrRegister();
DetectKrb5CNameRegister();
DetectKrb5ErrCodeRegister();
SCDetectKrb5MsgTypeRegister();
DetectKrb5SNameRegister();
DetectKrb5TicketEncryptionRegister();
DetectSipMethodRegister();
@ -779,6 +776,7 @@ void SigTableSetup(void)
SCDetectSmbRegister();
SCDetectIkeRegister();
SCDetectDcerpcRegister();
SCDetectKrb5Register();
for (size_t i = 0; i < preregistered_callbacks_nb; i++) {
PreregisteredCallbacks[i]();

@ -258,7 +258,6 @@ enum DetectKeywordId {
DETECT_DNP3IND,
DETECT_DNP3OBJ,
DETECT_KRB5_ERRCODE,
DETECT_KRB5_CNAME,
DETECT_KRB5_SNAME,
DETECT_KRB5_TICKET_ENCRYPTION,

@ -1,245 +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-errcode.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 DetectKrb5ErrCodeRegister below */
static int DetectKrb5ErrCodeMatch (DetectEngineThreadCtx *, Flow *,
uint8_t, void *, void *, const Signature *,
const SigMatchCtx *);
static int DetectKrb5ErrCodeSetup (DetectEngineCtx *, Signature *, const char *);
static void DetectKrb5ErrCodeFree (DetectEngineCtx *, void *);
#ifdef UNITTESTS
static void DetectKrb5ErrCodeRegisterTests (void);
#endif
static int g_krb5_err_code_list_id = 0;
/**
* \brief Registration function for krb5_err_code: keyword
*
* This function is called once in the 'lifetime' of the engine.
*/
void DetectKrb5ErrCodeRegister(void)
{
sigmatch_table[DETECT_KRB5_ERRCODE].name = "krb5_err_code";
sigmatch_table[DETECT_KRB5_ERRCODE].desc = "match Kerberos 5 error code";
sigmatch_table[DETECT_KRB5_ERRCODE].url = "/rules/kerberos-keywords.html#krb5-err-code";
sigmatch_table[DETECT_KRB5_ERRCODE].Match = NULL;
sigmatch_table[DETECT_KRB5_ERRCODE].AppLayerTxMatch = DetectKrb5ErrCodeMatch;
sigmatch_table[DETECT_KRB5_ERRCODE].Setup = DetectKrb5ErrCodeSetup;
sigmatch_table[DETECT_KRB5_ERRCODE].Free = DetectKrb5ErrCodeFree;
#ifdef UNITTESTS
sigmatch_table[DETECT_KRB5_ERRCODE].RegisterTests = DetectKrb5ErrCodeRegisterTests;
#endif
DetectAppLayerInspectEngineRegister("krb5_err_code", ALPROTO_KRB5, SIG_FLAG_TOSERVER, 0,
DetectEngineInspectGenericList, NULL);
DetectAppLayerInspectEngineRegister("krb5_err_code", ALPROTO_KRB5, SIG_FLAG_TOCLIENT, 0,
DetectEngineInspectGenericList, NULL);
/* set up the PCRE for keyword parsing */
DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
g_krb5_err_code_list_id = DetectBufferTypeRegister("krb5_err_code");
SCLogDebug("g_krb5_err_code_list_id %d", g_krb5_err_code_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 DetectKrb5ErrCodeMatch (DetectEngineThreadCtx *det_ctx,
Flow *f, uint8_t flags, void *state,
void *txv, const Signature *s,
const SigMatchCtx *ctx)
{
int32_t err_code;
int ret;
const DetectKrb5ErrCodeData *dd = (const DetectKrb5ErrCodeData *)ctx;
SCEnter();
ret = SCKrb5TxGetErrorCode(txv, &err_code);
if (ret != 0)
SCReturnInt(0);
if (dd->err_code == err_code)
SCReturnInt(1);
SCReturnInt(0);
}
/**
* \brief This function is used to parse options passed via krb5_errcode: keyword
*
* \param krb5str Pointer to the user provided krb5_err_code options
*
* \retval krb5d pointer to DetectKrb5Data on success
* \retval NULL on failure
*/
static DetectKrb5ErrCodeData *DetectKrb5ErrCodeParse (const char *krb5str)
{
DetectKrb5ErrCodeData *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 (DetectKrb5ErrCodeData));
if (unlikely(krb5d == NULL))
goto error;
if (StringParseInt32(&krb5d->err_code, 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_err_code' 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 DetectKrb5ErrCodeSetup (DetectEngineCtx *de_ctx, Signature *s, const char *krb5str)
{
DetectKrb5ErrCodeData *krb5d = NULL;
if (SCDetectSignatureSetAppProto(s, ALPROTO_KRB5) != 0)
return -1;
krb5d = DetectKrb5ErrCodeParse(krb5str);
if (krb5d == NULL)
goto error;
if (SCSigMatchAppendSMToList(de_ctx, s, DETECT_KRB5_ERRCODE, (SigMatchCtx *)krb5d,
g_krb5_err_code_list_id) == NULL) {
goto error;
}
return 0;
error:
if (krb5d != NULL)
DetectKrb5ErrCodeFree(de_ctx, krb5d);
return -1;
}
/**
* \brief this function will free memory associated with DetectKrb5Data
*
* \param ptr pointer to DetectKrb5Data
*/
static void DetectKrb5ErrCodeFree(DetectEngineCtx *de_ctx, void *ptr) {
DetectKrb5ErrCodeData *krb5d = (DetectKrb5ErrCodeData *)ptr;
SCFree(krb5d);
}
#ifdef UNITTESTS
/**
* \test description of the test
*/
static int DetectKrb5ErrCodeParseTest01 (void)
{
DetectKrb5ErrCodeData *krb5d = DetectKrb5ErrCodeParse("10");
FAIL_IF_NULL(krb5d);
FAIL_IF(!(krb5d->err_code == 10));
DetectKrb5ErrCodeFree(NULL, krb5d);
PASS;
}
static int DetectKrb5ErrCodeSignatureTest01 (void)
{
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
FAIL_IF_NULL(de_ctx);
Signature *sig = DetectEngineAppendSig(de_ctx, "alert krb5 any any -> any any (krb5_err_code:10; sid:1; rev:1;)");
FAIL_IF_NULL(sig);
DetectEngineCtxFree(de_ctx);
PASS;
}
/**
* \brief this function registers unit tests for DetectKrb5ErrCode
*/
static void DetectKrb5ErrCodeRegisterTests(void)
{
UtRegisterTest("DetectKrb5ErrCodeParseTest01", DetectKrb5ErrCodeParseTest01);
UtRegisterTest("DetectKrb5ErrCodeSignatureTest01",
DetectKrb5ErrCodeSignatureTest01);
}
#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_ERRCODE_H
#define SURICATA_DETECT_KRB5_ERRCODE_H
typedef struct DetectKrb5ErrCodeData_ {
int32_t err_code;
} DetectKrb5ErrCodeData;
void DetectKrb5ErrCodeRegister(void);
#endif /* SURICATA_DETECT_KRB5_ERRCODE_H */
Loading…
Cancel
Save