mirror of
https://github.com/zeek/zeek.git
synced 2025-10-07 00:58:19 +00:00
Add component API to transparently remap one component to another one.
When a specific component is requested through its tag or name, one can now have the component manager transparently return a different one that has been registered to replace the original one. We limit this to disabled components to avoid unnecessary confusion. That also means that remappings are currently only supported for analyzers (because other types of components cannot be disabled for now, per the previous change).
This commit is contained in:
parent
ac1a7508ee
commit
5d0c61e68b
7 changed files with 123 additions and 32 deletions
|
@ -801,4 +801,30 @@ TEST_SUITE("Analyzer management") {
|
||||||
CHECK(conn->FindAnalyzer("IMAP"));
|
CHECK(conn->FindAnalyzer("IMAP"));
|
||||||
conn->Done();
|
conn->Done();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Analyzer mapping") {
|
||||||
|
REQUIRE(zeek::analyzer_mgr);
|
||||||
|
|
||||||
|
zeek::Packet p;
|
||||||
|
zeek::ConnTuple t;
|
||||||
|
auto conn = std::make_unique<zeek::Connection>(zeek::detail::ConnKey(t), 0, &t, 0, &p);
|
||||||
|
|
||||||
|
auto ssh = zeek::analyzer_mgr->InstantiateAnalyzer("SSH", conn.get());
|
||||||
|
REQUIRE(ssh);
|
||||||
|
auto imap = zeek::analyzer_mgr->InstantiateAnalyzer("IMAP", conn.get());
|
||||||
|
REQUIRE(imap);
|
||||||
|
|
||||||
|
zeek::analyzer_mgr->AddComponentMapping(ssh->GetAnalyzerTag(), imap->GetAnalyzerTag());
|
||||||
|
zeek::analyzer_mgr->DisableAnalyzer(ssh->GetAnalyzerTag()); // needs to be disabled for mapping to take effect
|
||||||
|
auto ssh_is_imap = zeek::analyzer_mgr->InstantiateAnalyzer("SSH", conn.get());
|
||||||
|
CHECK_EQ(ssh_is_imap->GetAnalyzerTag(), imap->GetAnalyzerTag()); // SSH is now IMAP
|
||||||
|
|
||||||
|
// orderly cleanup through connection
|
||||||
|
auto* tcp = new zeek::packet_analysis::TCP::TCPSessionAdapter(conn.get());
|
||||||
|
conn->SetSessionAdapter(tcp, nullptr);
|
||||||
|
tcp->AddChildAnalyzer(ssh);
|
||||||
|
tcp->AddChildAnalyzer(imap);
|
||||||
|
tcp->AddChildAnalyzer(ssh_is_imap);
|
||||||
|
conn->Done();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ void Manager::DumpDebug() {
|
||||||
void Manager::Done() {}
|
void Manager::Done() {}
|
||||||
|
|
||||||
bool Manager::EnableAnalyzer(const zeek::Tag& tag) {
|
bool Manager::EnableAnalyzer(const zeek::Tag& tag) {
|
||||||
Component* p = Lookup(tag);
|
Component* p = Lookup(tag, false);
|
||||||
|
|
||||||
if ( ! p )
|
if ( ! p )
|
||||||
return false;
|
return false;
|
||||||
|
@ -122,7 +122,7 @@ bool Manager::EnableAnalyzer(const zeek::Tag& tag) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Manager::EnableAnalyzer(EnumVal* val) {
|
bool Manager::EnableAnalyzer(EnumVal* val) {
|
||||||
Component* p = Lookup(val);
|
Component* p = Lookup(val, false);
|
||||||
|
|
||||||
if ( ! p )
|
if ( ! p )
|
||||||
return false;
|
return false;
|
||||||
|
@ -134,7 +134,7 @@ bool Manager::EnableAnalyzer(EnumVal* val) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Manager::DisableAnalyzer(const zeek::Tag& tag) {
|
bool Manager::DisableAnalyzer(const zeek::Tag& tag) {
|
||||||
Component* p = Lookup(tag);
|
Component* p = Lookup(tag, false);
|
||||||
|
|
||||||
if ( ! p )
|
if ( ! p )
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -41,7 +41,7 @@ function Files::__set_reassembly_buffer%(file_id: string, max: count%): bool
|
||||||
## :zeek:see:`Files::enable_analyzer`.
|
## :zeek:see:`Files::enable_analyzer`.
|
||||||
function Files::__enable_analyzer%(tag: Files::Tag%) : bool
|
function Files::__enable_analyzer%(tag: Files::Tag%) : bool
|
||||||
%{
|
%{
|
||||||
auto c = zeek::file_mgr->Lookup(tag->AsEnumVal());
|
auto c = zeek::file_mgr->Lookup(tag->AsEnumVal(), false);
|
||||||
|
|
||||||
if ( ! c )
|
if ( ! c )
|
||||||
return zeek::val_mgr->False();
|
return zeek::val_mgr->False();
|
||||||
|
@ -53,7 +53,7 @@ function Files::__enable_analyzer%(tag: Files::Tag%) : bool
|
||||||
## :zeek:see:`Files::disable_analyzer`.
|
## :zeek:see:`Files::disable_analyzer`.
|
||||||
function Files::__disable_analyzer%(tag: Files::Tag%) : bool
|
function Files::__disable_analyzer%(tag: Files::Tag%) : bool
|
||||||
%{
|
%{
|
||||||
auto c = zeek::file_mgr->Lookup(tag->AsEnumVal());
|
auto c = zeek::file_mgr->Lookup(tag->AsEnumVal(), false);
|
||||||
|
|
||||||
if ( ! c )
|
if ( ! c )
|
||||||
return zeek::val_mgr->False();
|
return zeek::val_mgr->False();
|
||||||
|
|
|
@ -21,7 +21,7 @@ void Component::SetEnabled(bool arg_enabled) {
|
||||||
plugin::Component::SetEnabled(arg_enabled);
|
plugin::Component::SetEnabled(arg_enabled);
|
||||||
|
|
||||||
// If we already have instantiated an analyzer, update its state.
|
// If we already have instantiated an analyzer, update its state.
|
||||||
if ( auto analyzer = packet_mgr->Lookup(Tag().AsVal().get()) )
|
if ( auto analyzer = packet_mgr->Lookup(Tag().AsVal().get(), false) )
|
||||||
analyzer->SetEnabled(arg_enabled);
|
analyzer->SetEnabled(arg_enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,14 +82,14 @@ AnalyzerPtr Manager::GetAnalyzer(const std::string& name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Manager::EnableAnalyzer(EnumVal* tag) {
|
bool Manager::EnableAnalyzer(EnumVal* tag) {
|
||||||
Component* c = Lookup(tag);
|
Component* c = Lookup(tag, false);
|
||||||
c->SetEnabled(true);
|
c->SetEnabled(true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Manager::DisableAnalyzer(EnumVal* tag) {
|
bool Manager::DisableAnalyzer(EnumVal* tag) {
|
||||||
Component* c = Lookup(tag);
|
Component* c = Lookup(tag, false);
|
||||||
c->SetEnabled(false);
|
c->SetEnabled(false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -119,24 +119,59 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param name The canonical name of a component.
|
* @param name The canonical name of a component.
|
||||||
|
* @param consider_remappings If true, component mappings will be honored
|
||||||
|
* if the original component is disabled.
|
||||||
* @return The component associated with the name or a null pointer if no
|
* @return The component associated with the name or a null pointer if no
|
||||||
* such component exists.
|
* such component exists.
|
||||||
*/
|
*/
|
||||||
C* Lookup(const std::string& name) const;
|
C* Lookup(const std::string& name, bool consider_remappings = true) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param name A component tag.
|
* @param name A component tag.
|
||||||
|
* @param consider_remappings If true, component mappings will be honored
|
||||||
|
* if the original component is disabled.
|
||||||
* @return The component associated with the tag or a null pointer if no
|
* @return The component associated with the tag or a null pointer if no
|
||||||
* such component exists.
|
* such component exists.
|
||||||
*/
|
*/
|
||||||
C* Lookup(const zeek::Tag& tag) const;
|
C* Lookup(const zeek::Tag& tag, bool consider_remappings = true) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param name A component's enum value.
|
* @param name A component's enum value.
|
||||||
|
* @param consider_remappings If true, component mappings will be honored
|
||||||
|
* if the original component is disabled.
|
||||||
* @return The component associated with the value or a null pointer if no
|
* @return The component associated with the value or a null pointer if no
|
||||||
* such component exists.
|
* such component exists.
|
||||||
*/
|
*/
|
||||||
C* Lookup(EnumVal* val) const;
|
C* Lookup(EnumVal* val, bool consider_remappings = true) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a mapping of a component to another one that will be honored
|
||||||
|
* by the `Lookup()` methods if (and only if) the original is currently
|
||||||
|
* disabled.
|
||||||
|
*
|
||||||
|
* @param old The original component tag.
|
||||||
|
* @param new_ The new component tag.
|
||||||
|
*/
|
||||||
|
void AddComponentMapping(const zeek::Tag& old, const zeek::Tag& new_) {
|
||||||
|
if ( old != new_ ) {
|
||||||
|
component_mapping_by_src[old] = new_;
|
||||||
|
component_mapping_by_dst[new_] = old;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if a given component has a mapping to different one in place.
|
||||||
|
*
|
||||||
|
* @param tag The component tag to check.
|
||||||
|
*/
|
||||||
|
auto HasComponentMapping(const zeek::Tag& tag) const { return component_mapping_by_src.count(tag); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if a given component is mapped to from a different one.
|
||||||
|
*
|
||||||
|
* @param tag The component tag to check.
|
||||||
|
*/
|
||||||
|
bool ProvidesComponentMapping(const zeek::Tag& tag) const { return component_mapping_by_dst.count(tag); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Script layer module in which component tags live. */
|
/** Script layer module in which component tags live. */
|
||||||
|
@ -150,6 +185,8 @@ private:
|
||||||
std::map<std::string, C*> components_by_name;
|
std::map<std::string, C*> components_by_name;
|
||||||
std::map<zeek::Tag, C*> components_by_tag;
|
std::map<zeek::Tag, C*> components_by_tag;
|
||||||
std::map<zeek_int_t, C*> components_by_val;
|
std::map<zeek_int_t, C*> components_by_val;
|
||||||
|
std::map<zeek::Tag, zeek::Tag> component_mapping_by_src;
|
||||||
|
std::map<zeek::Tag, zeek::Tag> component_mapping_by_dst;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class C>
|
template<class C>
|
||||||
|
@ -204,7 +241,7 @@ const std::string& ComponentManager<C>::GetComponentName(zeek::Tag tag) const {
|
||||||
if ( ! tag )
|
if ( ! tag )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
if ( C* c = Lookup(tag) )
|
if ( C* c = Lookup(tag, false) ) // use actual, not remapped name
|
||||||
return c->CanonicalName();
|
return c->CanonicalName();
|
||||||
|
|
||||||
reporter->InternalWarning("requested name of unknown component tag %s", tag.AsString().c_str());
|
reporter->InternalWarning("requested name of unknown component tag %s", tag.AsString().c_str());
|
||||||
|
@ -266,21 +303,48 @@ zeek::Tag ComponentManager<C>::GetComponentTag(Val* v) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class C>
|
template<class C>
|
||||||
C* ComponentManager<C>::Lookup(const std::string& name) const {
|
C* ComponentManager<C>::Lookup(const std::string& name, bool consider_remappings) const {
|
||||||
typename std::map<std::string, C*>::const_iterator i = components_by_name.find(util::to_upper(name));
|
if ( auto i = components_by_name.find(util::to_upper(name)); i != components_by_name.end() ) {
|
||||||
return i != components_by_name.end() ? i->second : nullptr;
|
auto c = (*i).second;
|
||||||
|
if ( consider_remappings && ! c->Enabled() ) {
|
||||||
|
if ( auto j = component_mapping_by_src.find(c->Tag()); j != component_mapping_by_src.end() )
|
||||||
|
return Lookup(j->second, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class C>
|
template<class C>
|
||||||
C* ComponentManager<C>::Lookup(const zeek::Tag& tag) const {
|
C* ComponentManager<C>::Lookup(const zeek::Tag& tag, bool consider_remappings) const {
|
||||||
typename std::map<zeek::Tag, C*>::const_iterator i = components_by_tag.find(tag);
|
if ( auto i = components_by_tag.find(tag); i != components_by_tag.end() ) {
|
||||||
return i != components_by_tag.end() ? i->second : nullptr;
|
auto c = (*i).second;
|
||||||
|
if ( consider_remappings && ! c->Enabled() ) {
|
||||||
|
if ( auto j = component_mapping_by_src.find(c->Tag()); j != component_mapping_by_src.end() )
|
||||||
|
return Lookup(j->second, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class C>
|
template<class C>
|
||||||
C* ComponentManager<C>::Lookup(EnumVal* val) const {
|
C* ComponentManager<C>::Lookup(EnumVal* val, bool consider_remappings) const {
|
||||||
typename std::map<zeek_int_t, C*>::const_iterator i = components_by_val.find(val->InternalInt());
|
if ( auto i = components_by_val.find(val->InternalInt()); i != components_by_val.end() ) {
|
||||||
return i != components_by_val.end() ? i->second : nullptr;
|
auto c = (*i).second;
|
||||||
|
if ( consider_remappings && ! c->Enabled() ) {
|
||||||
|
if ( auto j = component_mapping_by_src.find(c->Tag()); j != component_mapping_by_src.end() )
|
||||||
|
return Lookup(j->second, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class C>
|
template<class C>
|
||||||
|
|
|
@ -375,8 +375,9 @@ bool Manager::toggleFileAnalyzer(const Tag& tag, bool enable) {
|
||||||
// not set -> not ours
|
// not set -> not ours
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
file_analysis::Component* component = file_mgr->Lookup(tag);
|
file_analysis::Component* component = file_mgr->Lookup(tag, false);
|
||||||
file_analysis::Component* component_replaces = analyzer.replaces ? file_mgr->Lookup(analyzer.replaces) : nullptr;
|
file_analysis::Component* component_replaces =
|
||||||
|
analyzer.replaces ? file_mgr->Lookup(analyzer.replaces, false) : nullptr;
|
||||||
|
|
||||||
if ( ! component ) {
|
if ( ! component ) {
|
||||||
// Shouldn't really happen.
|
// Shouldn't really happen.
|
||||||
|
@ -418,9 +419,9 @@ bool Manager::togglePacketAnalyzer(const Tag& tag, bool enable) {
|
||||||
// not set -> not ours
|
// not set -> not ours
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
packet_analysis::Component* component = packet_mgr->Lookup(tag);
|
packet_analysis::Component* component = packet_mgr->Lookup(tag, false);
|
||||||
packet_analysis::Component* component_replaces =
|
packet_analysis::Component* component_replaces =
|
||||||
analyzer.replaces ? packet_mgr->Lookup(analyzer.replaces) : nullptr;
|
analyzer.replaces ? packet_mgr->Lookup(analyzer.replaces, false) : nullptr;
|
||||||
|
|
||||||
if ( ! component ) {
|
if ( ! component ) {
|
||||||
// Shouldn't really happen.
|
// Shouldn't really happen.
|
||||||
|
@ -452,21 +453,21 @@ bool Manager::togglePacketAnalyzer(const Tag& tag, bool enable) {
|
||||||
|
|
||||||
bool Manager::toggleAnalyzer(EnumVal* tag, bool enable) {
|
bool Manager::toggleAnalyzer(EnumVal* tag, bool enable) {
|
||||||
if ( tag->GetType() == analyzer_mgr->GetTagType() ) {
|
if ( tag->GetType() == analyzer_mgr->GetTagType() ) {
|
||||||
if ( auto analyzer = analyzer_mgr->Lookup(tag) )
|
if ( auto analyzer = analyzer_mgr->Lookup(tag, false) )
|
||||||
return toggleProtocolAnalyzer(analyzer->Tag(), enable);
|
return toggleProtocolAnalyzer(analyzer->Tag(), enable);
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( tag->GetType() == file_mgr->GetTagType() ) {
|
if ( tag->GetType() == file_mgr->GetTagType() ) {
|
||||||
if ( auto analyzer = file_mgr->Lookup(tag) )
|
if ( auto analyzer = file_mgr->Lookup(tag, false) )
|
||||||
return toggleFileAnalyzer(analyzer->Tag(), enable);
|
return toggleFileAnalyzer(analyzer->Tag(), enable);
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( tag->GetType() == packet_mgr->GetTagType() ) {
|
if ( tag->GetType() == packet_mgr->GetTagType() ) {
|
||||||
if ( auto analyzer = packet_mgr->Lookup(tag) )
|
if ( auto analyzer = packet_mgr->Lookup(tag, false) )
|
||||||
return togglePacketAnalyzer(analyzer->Tag(), enable);
|
return togglePacketAnalyzer(analyzer->Tag(), enable);
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
|
@ -893,7 +894,7 @@ void Manager::disableReplacedAnalyzers() {
|
||||||
|
|
||||||
auto replaces = info.name_replaces.c_str();
|
auto replaces = info.name_replaces.c_str();
|
||||||
|
|
||||||
if ( file_mgr->Lookup(replaces) || packet_mgr->Lookup(replaces) )
|
if ( file_mgr->Lookup(replaces, false) || packet_mgr->Lookup(replaces, false) )
|
||||||
reporter->FatalError("cannot replace '%s' analyzer with a protocol analyzer", replaces);
|
reporter->FatalError("cannot replace '%s' analyzer with a protocol analyzer", replaces);
|
||||||
|
|
||||||
auto tag = analyzer_mgr->GetAnalyzerTag(replaces);
|
auto tag = analyzer_mgr->GetAnalyzerTag(replaces);
|
||||||
|
@ -915,10 +916,10 @@ void Manager::disableReplacedAnalyzers() {
|
||||||
|
|
||||||
auto replaces = info.name_replaces.c_str();
|
auto replaces = info.name_replaces.c_str();
|
||||||
|
|
||||||
if ( analyzer_mgr->Lookup(replaces) || packet_mgr->Lookup(replaces) )
|
if ( analyzer_mgr->Lookup(replaces, false) || packet_mgr->Lookup(replaces, false) )
|
||||||
reporter->FatalError("cannot replace '%s' analyzer with a file analyzer", replaces);
|
reporter->FatalError("cannot replace '%s' analyzer with a file analyzer", replaces);
|
||||||
|
|
||||||
auto component = file_mgr->Lookup(replaces);
|
auto component = file_mgr->Lookup(replaces, false);
|
||||||
if ( ! component ) {
|
if ( ! component ) {
|
||||||
SPICY_DEBUG(hilti::rt::fmt("%s is supposed to replace file analyzer %s, but that does not exist",
|
SPICY_DEBUG(hilti::rt::fmt("%s is supposed to replace file analyzer %s, but that does not exist",
|
||||||
info.name_analyzer, replaces));
|
info.name_analyzer, replaces));
|
||||||
|
@ -937,7 +938,7 @@ void Manager::disableReplacedAnalyzers() {
|
||||||
|
|
||||||
auto replaces = info.name_replaces.c_str();
|
auto replaces = info.name_replaces.c_str();
|
||||||
|
|
||||||
auto component = packet_mgr->Lookup(replaces);
|
auto component = packet_mgr->Lookup(replaces, false);
|
||||||
if ( ! component ) {
|
if ( ! component ) {
|
||||||
SPICY_DEBUG(hilti::rt::fmt("%s is supposed to replace packet analyzer %s, but that does not exist",
|
SPICY_DEBUG(hilti::rt::fmt("%s is supposed to replace packet analyzer %s, but that does not exist",
|
||||||
info.name_analyzer, replaces));
|
info.name_analyzer, replaces));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue