diff --git a/doc/userguide/firewall/firewall-design.rst b/doc/userguide/firewall/firewall-design.rst index 9148065b79..d3f5cfb475 100644 --- a/doc/userguide/firewall/firewall-design.rst +++ b/doc/userguide/firewall/firewall-design.rst @@ -417,3 +417,6 @@ defining ``accept:tx`` as a global default policy will fail to start Suricata, because ``packet`` policies do not accept ``tx``. Cover such hooks with a more specific setting so the incompatible default never reaches them. + +A ``<`` hook rule at the protocol's first state (progress 0) is accepted and is +equivalent to the plain hook form, as there are no prior states to auto-accept. diff --git a/doc/userguide/rules/app-layer.rst b/doc/userguide/rules/app-layer.rst index 5d57471152..3ab87cecda 100644 --- a/doc/userguide/rules/app-layer.rst +++ b/doc/userguide/rules/app-layer.rst @@ -213,3 +213,12 @@ Examples:: app-layer-state:request_headers; app-layer-state:>request_body; + +A comparison that can never hold is rejected at rule load: + +* ``>`` with a state at or beyond the protocol's completion state; +* ``<`` with the protocol's first state (progress 0). + +.. note:: The keyword only resolves on protocols whose parser registers a + top-level state table (``get_state_id_by_name``). The ``http2`` and + ``doh2`` parsers do not, so ``app-layer-state`` cannot be used on them. diff --git a/doc/userguide/rules/intro.rst b/doc/userguide/rules/intro.rst index 8d36dd6c8f..c1d7d2fa1a 100644 --- a/doc/userguide/rules/intro.rst +++ b/doc/userguide/rules/intro.rst @@ -162,6 +162,12 @@ per protocol specific hooks. More details can be found in :ref:`rule-hooks`. +.. note:: + + A ``<`` hook at the protocol's first state (progress 0) is accepted and is + equivalent to the plain hook form: there are no prior states to auto-accept + (``http1:alproto, h, STREAM_TOSERVER); @@ -213,8 +214,24 @@ static int DetectAppLayerStateSetup(DetectEngineCtx *de_ctx, Signature *s, const } s->flags |= SIG_FLAG_TOCLIENT; progress = progress_tc; + dir_flag = STREAM_TOCLIENT; } + const uint8_t direction = dir_flag; + const uint8_t end_state = AppLayerParserGetStateProgressCompletionStatus(s->alproto, direction); + + /* the tx progress can never exceed the completion state */ + if (mode > 0 && progress >= end_state) { + SCLogError("app-layer-state: state '%s' is not below the completion state for mode '>'", h); + return -1; + } + /* the progress can never be below the starting state */ + if (mode < 0 && progress == 0) { + SCLogError("app-layer-state: state '%s' is the starting state, it can never match for " + "mode '<'", + h); + return -1; + } DetectAppLayerStateData *data = SCCalloc(1, sizeof(*data)); if (data == NULL) return -1;