diff --git a/scripts/base/init-bare.zeek b/scripts/base/init-bare.zeek index 32ff925f13..82993bfb03 100644 --- a/scripts/base/init-bare.zeek +++ b/scripts/base/init-bare.zeek @@ -4684,6 +4684,18 @@ const dpd_buffer_size = 1024 &redef; ## only signatures used for dynamic protocol detection. const dpd_match_only_beginning = T &redef; +## If true, stops signature matching after a late match. A late match may occur +## in case the DPD buffer is exhausted but a protocol signature matched. To +## allow late matching, :zeek:see:`dpd_match_only_beginning` must be disabled. +## +## .. zeek:see:: dpd_reassemble_first_packets dpd_buffer_size +## dpd_match_only_beginning +## +## .. note:: Despite the name, this option stops *all* signature matching, not +## only signatures used for dynamic protocol detection but is triggered by +## DPD signatures only. +const dpd_late_match_stop = F &redef; + ## If true, don't consider any ports for deciding which protocol analyzer to ## use. ## diff --git a/src/NetVar.cc b/src/NetVar.cc index 981ca005ff..1ab99170bb 100644 --- a/src/NetVar.cc +++ b/src/NetVar.cc @@ -164,6 +164,7 @@ RecordType* irc_join_info; int dpd_reassemble_first_packets; int dpd_buffer_size; int dpd_match_only_beginning; +int dpd_late_match_stop; int dpd_ignore_ports; TableVal* likely_server_ports; @@ -406,6 +407,7 @@ void init_net_var() opt_internal_int("dpd_reassemble_first_packets"); dpd_buffer_size = opt_internal_int("dpd_buffer_size"); dpd_match_only_beginning = opt_internal_int("dpd_match_only_beginning"); + dpd_late_match_stop = opt_internal_int("dpd_late_match_stop"); dpd_ignore_ports = opt_internal_int("dpd_ignore_ports"); likely_server_ports = internal_val("likely_server_ports")->AsTableVal(); diff --git a/src/NetVar.h b/src/NetVar.h index 41b2028064..7c5f218cb6 100644 --- a/src/NetVar.h +++ b/src/NetVar.h @@ -166,6 +166,7 @@ extern RecordType* irc_join_info; extern int dpd_reassemble_first_packets; extern int dpd_buffer_size; extern int dpd_match_only_beginning; +extern int dpd_late_match_stop; extern int dpd_ignore_ports; extern TableVal* likely_server_ports; diff --git a/src/analyzer/protocol/pia/PIA.cc b/src/analyzer/protocol/pia/PIA.cc index bf9f27be7c..f035f942be 100644 --- a/src/analyzer/protocol/pia/PIA.cc +++ b/src/analyzer/protocol/pia/PIA.cc @@ -1,5 +1,6 @@ #include "PIA.h" #include "RuleMatcher.h" +#include "Event.h" #include "analyzer/protocol/tcp/TCP_Flags.h" #include "analyzer/protocol/tcp/TCP_Reassembler.h" @@ -144,6 +145,20 @@ void PIA_UDP::ActivateAnalyzer(analyzer::Tag tag, const Rule* rule) DBG_LOG(DBG_ANALYZER, "analyzer found but buffer already exceeded"); // FIXME: This is where to check whether an analyzer // supports partial connections once we get such. + + if ( protocol_late_match ) + { + // Queue late match event + EnumVal *tval = tag ? tag.AsEnumVal() : GetAnalyzerTag().AsEnumVal(); + Ref(tval); + + val_list *vl = new val_list; + vl->append(BuildConnVal()); + vl->append(tval); + mgr.QueueEvent(protocol_late_match, vl); + } + + pkt_buffer.state = dpd_late_match_stop ? SKIPPING : MATCHING_ONLY; return; } @@ -279,6 +294,20 @@ void PIA_TCP::ActivateAnalyzer(analyzer::Tag tag, const Rule* rule) DBG_LOG(DBG_ANALYZER, "analyzer found but buffer already exceeded"); // FIXME: This is where to check whether an analyzer supports // partial connections once we get such. + + if ( protocol_late_match ) + { + // Queue late match event + EnumVal *tval = tag ? tag.AsEnumVal() : GetAnalyzerTag().AsEnumVal(); + Ref(tval); + + val_list *vl = new val_list; + vl->append(BuildConnVal()); + vl->append(tval); + mgr.QueueEvent(protocol_late_match, vl); + } + + stream_buffer.state = dpd_late_match_stop ? SKIPPING : MATCHING_ONLY; return; } diff --git a/src/event.bif b/src/event.bif index 5222545ae5..62ab89f1c1 100644 --- a/src/event.bif +++ b/src/event.bif @@ -369,6 +369,20 @@ event content_gap%(c: connection, is_orig: bool, seq: count, length: count%); ## there (and thus in ``conn.log``). event protocol_confirmation%(c: connection, atype: Analyzer::Tag, aid: count%); +## Generated if a DPD signature matched but the DPD buffer is already exhausted +## and thus the analyzer could not be attached. While this does not confirm +## that a protocol is actually used, it allows to retain that information. +## +## c: The connection. +## +## atype: The type of the analyzer confirming that its protocol is in +## use. The value is one of the ``Analyzer::ANALYZER_*`` constants. For example, +## ``Analyzer::ANALYZER_HTTP`` means the HTTP analyzer determined that it's indeed +## parsing an HTTP connection. +## +## .. bro:see:: dpd_buffer_size +event protocol_late_match%(c: connection, atype: Analyzer::Tag%); + ## Generated when a protocol analyzer determines that a connection it is parsing ## is not conforming to the protocol it expects. Zeek's dynamic protocol ## detection heuristically activates analyzers as soon as it believes a