detect: make the completion state final at the end state

eof is C > P, so an engine registered at a parser's completion state
never becomes complete: there is no next state to enter. A firewall
rule hooking such a state (e.g. tls:client_finished) stayed pending
forever and was optimistically accepted.

Treat progress == engine progress == tx end state as complete. This
also finalizes the buffer engines' eof on completion-state buffers, so
absent and bsize decisions now happen there, and it covers every parser
whose engine progress equals its completion state (dns, ntp, quic,
rdp-style two-state protocols), not only the firewall path that
motivated the change.

Ticket: #8944.
pull/16368/head
Victor Julien 1 month ago
parent 0e297d26ff
commit 59d08a717e

@ -2186,7 +2186,30 @@ static bool DetectTxCompleted(
// the DNS tx from DetectGetInnerTx is always complete
return true;
} // else
return AppLayerParserGetStateProgress(f->proto, f->alproto, txv, flags) > engine->progress;
const int progress = AppLayerParserGetStateProgress(f->proto, f->alproto, txv, flags);
if (progress < 0) {
return false;
}
if (progress > engine->progress) {
return true;
}
if (progress < engine->progress) {
return false;
}
/* An engine registered at the completion state has no P + 1; its data is
* final once the tx reached that state. For the buffer engines this is the
* engine's eof, so absent/bsize are decided; for the firewall checks it is
* the point where the verdict can no longer change.
* AppLayerParserGetStateProgress() returns the end progress for disrupted
* flows, so progress == end stays a valid finality signal there. */
const AppLayerTxData *txd = AppLayerParserGetTxData(f->proto, f->alproto, txv);
uint8_t tx_end_state;
if (txd != NULL && txd->tx_type != 0) {
tx_end_state = (flags & STREAM_TOSERVER) ? txd->tx_type_eop_ts : txd->tx_type_eop_tc;
} else {
tx_end_state = AppLayerParserGetStateProgressCompletionStatus(f->alproto, flags);
}
return progress == tx_end_state;
}
/**

Loading…
Cancel
Save