GH-532: improve disable_analyzer BIF

- Add an extra "prevent" parameter (default value of false), which
  helps prevent the same analyzer type from being attached in the
  future.  It's useful in situations where you want to disable early
  on, but a DPD signature may still trigger later and re-attach
  the same analyzer.  E.g. when not using this flag, but calling
  disable_analyzer() inside an http_request event, will remove the
  HTTP analyzer that was attached due to well-known-port, but a later
  DPD signature match from upon seeing the HTTP reply will end up
  attaching another HTTP analyzer.  More surprising is that upon
  re-attaching that analyzer, you'll get the same http_request as
  before since the DPD buffer will get replayed into the new analyzer.

- Fixes disable_analyzer() to work when called even earlier, like
  within the protocol_confirmation event.  At that time, the
  Analyzer tree may have not properly added the new analyzer into
  Analyzer::children yet, but rather the temporary waiting list,
  Analyzer::new_children.  Analyzer::RemoveChildAnalyzer previously
  did not inspect the later list.

- Fixes disable_analyzer() when called on an analyzer added to the
  tree via TCP_Analyzer::AddChildPacketAnalyzer.  TCP_Analyzer
  keeps track of such children in its own list,
  TCP_Analyzer::packet_children, which the previous
  Analyzer::RemoveChildAnalyzer implementation didn't inspect.
This commit is contained in:
Jon Siwek 2019-08-09 19:51:08 -07:00
parent bf9b983f00
commit a1c5eddb95
12 changed files with 247 additions and 58 deletions

View file

@ -205,6 +205,15 @@ analyzer::Analyzer* TCP_Analyzer::FindChild(Tag arg_tag)
return 0;
}
bool TCP_Analyzer::RemoveChildAnalyzer(ID id)
{
auto rval = analyzer::TransportLayerAnalyzer::RemoveChildAnalyzer(id);
if ( rval )
return rval;
return RemoveChild(packet_children, id);
}
void TCP_Analyzer::EnableReassembly()
{
@ -1209,8 +1218,28 @@ void TCP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig,
// Handle child_packet analyzers. Note: This happens *after* the
// packet has been processed and the TCP state updated.
LOOP_OVER_GIVEN_CHILDREN(i, packet_children)
(*i)->NextPacket(len, data, is_orig, rel_data_seq, ip, caplen);
analyzer_list::iterator next;
for ( auto i = packet_children.begin(); i != packet_children.end(); i = next )
{
auto child = *i;
next = ++i;
if ( child->IsFinished() || child->Removing() )
{
--i;
if ( child->Removing() )
child->Done();
DBG_LOG(DBG_ANALYZER, "%s deleted child %s",
fmt_analyzer(this).c_str(), fmt_analyzer(child).c_str());
packet_children.erase(i);
delete child;
}
else
child->NextPacket(len, data, is_orig, rel_data_seq, ip, caplen);
}
if ( ! reassembling )
ForwardPacket(len, data, is_orig, rel_data_seq, ip, caplen);