Feature #9363
openTask #7499: tracking: rust/plugins: first class support for rust plugins
detect/plugins: expose keyword setup accessors to plugins and Rust
Description
Keywords implemented in plugins or in Rust can't access the Signature, SigMatch and sigmatch_table internals that built-in keywords use when they are registered and when their rule options are set up, because those types are opaque to them and their layout changes with build options (for example --enable-profiling-rules). Three common things such a keyword needs are therefore impossible without calling unexported functions or mirroring struct offsets:
- Packet match callback:
SCDetectHelperKeywordRegister()takes anSCSigTableAppLiteElmt, which only has an app-layer transaction match callback. A packet keyword has to write itsMatchcallback intosigmatch_tabledirectly. - Negation: keywords registered with
SIGMATCH_HANDLE_NEGATIONget the leading!stripped by the rule parser, which records it inSignature::init_data. The flag is already exposed to Rust, but there is no way to read the result. - Earlier instances of the same keyword: keywords like
app-layer-protocolandipprotowalk the signature's packet match list to reject duplicate or conflicting options, reading each earlier instance's context.SCDetectGetLastSMFromLists()is not a substitute: it only returns the last match, gives no access to its context, and ignores the packet match list once a sticky buffer is active in the rule.
Proposal¶
Add functions to the detect API, exposed through the generated Rust bindings:
SCDetectHelperKeywordPacketMatchRegister(kwid, Match): install a packet match callback for a keyword registered withSCDetectHelperKeywordRegister(), without changing theSCSigTableAppLiteElmtlayoutSCDetectSignatureIsNegated(s): whether the option being set up was negatedSCDetectSignatureGetLastSMByType(s, list_id, type): last SigMatch of a keyword in one of the static lists (e.g.DETECT_SM_LIST_MATCH)SCSigMatchGetPrevByType(sm, type): previous SigMatch of the same keywordSCSigMatchGetCtx(sm): the keyword context of a SigMatch
The lookup is limited to the static lists from DetectSigmatchListEnum. That enum is moved to detect-engine-register.h and allowlisted in the Rust bindings, so Rust keywords can use DETECT_SM_LIST_MATCH instead of hardcoding it.
Users¶
- The in-tree nDPI plugin is converted to register its
ndpi-protocolandndpi-riskkeywords through the helpers, and to use the accessors for their negation and conflict checks, so it no longer touchessigmatch_table,SignatureorSigMatchinternals. - An external nDPI plugin written in Rust uses them in place of writing into
sigmatch_tablethrough a probed struct layout, calling the unexportedDetectGetLastSMByListId(), and walkingSigMatchthrough mirrored struct offsets. - The
flowbitsandipprotokeywords use the SigMatch lookup as in-tree examples, and unit tests insrc/tests/util-plugin.ccover the patterns from a keyword registered the way a plugin does it.