detect: expose opaque SigMatch lookup to plugins and Rust

Add accessors so a keyword Setup callback can inspect earlier instances
of its keyword in the signature being set up without depending on the
Signature or SigMatch layout:

- SCDetectSignatureGetLastSMByType: last SigMatch of a keyword in a list
- SCSigMatchGetPrevByType: previous SigMatch of the same keyword
- SCSigMatchGetCtx: the keyword context of a SigMatch

This is what keywords like app-layer-protocol do to reject duplicate or
conflicting options, by walking the match list directly. Plugins, and
keywords implemented in Rust, can't do that as these types are opaque
to them. The existing SCDetectGetLastSMFromLists is not a substitute as
it ignores the packet match list once a sticky buffer is active in the
rule, and gives no access to the context.

The lookup is limited to the static lists from DetectSigmatchListEnum.
A dynamic buffer list can have several instances in a signature, each
with its own SigMatch chain, so the previous-SigMatch walk could not
cover it, and DetectGetLastSMByListId would search every buffer rather
than the requested one.

Expose the new functions through the generated Rust bindings.

Related to ticket: 7499
pull/16454/head
Jason Ish 1 week ago
parent c92af11867
commit c2d192db92

@ -1040,6 +1040,17 @@ extern "C" {
extern "C" {
pub fn SCDetectGetLastSMFromLists(s: *const Signature, ...) -> *mut SigMatch;
}
extern "C" {
pub fn SCDetectSignatureGetLastSMByType(
s: *const Signature, list_id: ::std::os::raw::c_int, type_: u16,
) -> *const SigMatch;
}
extern "C" {
pub fn SCSigMatchGetPrevByType(sm: *const SigMatch, type_: u16) -> *const SigMatch;
}
extern "C" {
pub fn SCSigMatchGetCtx(sm: *const SigMatch) -> *const SigMatchCtx;
}
extern "C" {
pub fn SCDetectSignatureSetAppProto(
s: *mut Signature, alproto: AppProto,

@ -737,6 +737,57 @@ SigMatch *DetectGetLastSMByListId(const Signature *s, int list_id, ...)
return sm_last;
}
/**
* \brief Get the last SigMatch of keyword \a type in list \a list_id.
*
* Lets a keyword Setup callback inspect earlier instances of a keyword in
* the signature being set up, together with SCSigMatchGetPrevByType() and
* SCSigMatchGetCtx(), without depending on the SigMatch layout.
*
* Only the static lists from DetectSigmatchListEnum are supported. A dynamic
* buffer list can have several instances in a signature, each with its own
* SigMatch chain, so there is no single list to walk.
*
* \param s signature being set up
* \param list_id static list to search, e.g. DETECT_SM_LIST_MATCH
* \param type keyword id, as returned by SCDetectHelperKeywordRegister()
*
* \retval sm last SigMatch of \a type in the list, or NULL if there is none
* or \a list_id is not a static list
*/
const SigMatch *SCDetectSignatureGetLastSMByType(const Signature *s, int list_id, uint16_t type)
{
DEBUG_VALIDATE_BUG_ON(list_id < 0 || list_id >= DETECT_SM_LIST_MAX);
if (list_id < 0 || list_id >= DETECT_SM_LIST_MAX)
return NULL;
return DetectGetLastSMByListId(s, list_id, type, -1);
}
/**
* \brief Get the previous SigMatch of keyword \a type before \a sm.
*
* \param sm SigMatch to search before, must not be NULL
* \param type keyword id
*
* \retval sm previous SigMatch of \a type in the same list, or NULL if there
* is none
*/
const SigMatch *SCSigMatchGetPrevByType(const SigMatch *sm, uint16_t type)
{
return SigMatchGetLastSMByType(sm->prev, type);
}
/**
* \brief Get the keyword context of \a sm, as passed to
* SCSigMatchAppendSMToList() by the keyword's Setup callback.
*
* \param sm SigMatch, must not be NULL
*/
const SigMatchCtx *SCSigMatchGetCtx(const SigMatch *sm)
{
return sm->ctx;
}
/**
* \brief Returns the sm with the largest index (added latest) from this sig
*

@ -84,6 +84,9 @@ SigMatch *DetectGetLastSMFromMpmLists(const DetectEngineCtx *de_ctx, const Signa
SigMatch *SCDetectGetLastSMFromLists(const Signature *s, ...);
SigMatch *DetectGetLastSMByListPtr(const Signature *s, SigMatch *sm_list, ...);
SigMatch *DetectGetLastSMByListId(const Signature *s, int list_id, ...);
const SigMatch *SCDetectSignatureGetLastSMByType(const Signature *s, int list_id, uint16_t type);
const SigMatch *SCSigMatchGetPrevByType(const SigMatch *sm, uint16_t type);
const SigMatchCtx *SCSigMatchGetCtx(const SigMatch *sm);
int WARN_UNUSED SCDetectSignatureSetAppProto(Signature *s, AppProto alproto);
bool SCDetectSignatureIsNegated(const Signature *s);

Loading…
Cancel
Save