mirror of
https://github.com/zeek/zeek.git
synced 2025-10-04 07:38:19 +00:00

- FileAnalysis::Info is now just a record used for logging, the fa_file record type is defined in init-bare.bro as the analogue to a connection record. - Starting to transfer policy hook triggers and analyzer results to events.
185 lines
3.8 KiB
C++
185 lines
3.8 KiB
C++
#include "ActionSet.h"
|
|
#include "File.h"
|
|
#include "Action.h"
|
|
#include "Extract.h"
|
|
#include "DataEvent.h"
|
|
#include "Hash.h"
|
|
|
|
using namespace file_analysis;
|
|
|
|
// keep in order w/ declared enum values in file_analysis.bif
|
|
static ActionInstantiator action_factory[] = {
|
|
file_analysis::Extract::Instantiate,
|
|
file_analysis::MD5::Instantiate,
|
|
file_analysis::SHA1::Instantiate,
|
|
file_analysis::SHA256::Instantiate,
|
|
file_analysis::DataEvent::Instantiate,
|
|
};
|
|
|
|
static void action_del_func(void* v)
|
|
{
|
|
delete (Action*) v;
|
|
}
|
|
|
|
ActionSet::ActionSet(File* arg_file) : file(arg_file)
|
|
{
|
|
TypeList* t = new TypeList();
|
|
t->Append(BifType::Record::FileAnalysis::ActionArgs->Ref());
|
|
action_hash = new CompositeHash(t);
|
|
Unref(t);
|
|
action_map.SetDeleteFunc(action_del_func);
|
|
}
|
|
|
|
ActionSet::~ActionSet()
|
|
{
|
|
while ( ! mod_queue.empty() )
|
|
{
|
|
Modification* mod = mod_queue.front();
|
|
mod->Abort();
|
|
delete mod;
|
|
mod_queue.pop();
|
|
}
|
|
delete action_hash;
|
|
}
|
|
|
|
bool ActionSet::AddAction(RecordVal* args)
|
|
{
|
|
HashKey* key = GetKey(args);
|
|
|
|
if ( action_map.Lookup(key) )
|
|
{
|
|
DBG_LOG(DBG_FILE_ANALYSIS, "Instantiate action %d skipped for file id"
|
|
" %s: already exists", Action::ArgsTag(args),
|
|
file->GetID().c_str());
|
|
delete key;
|
|
return true;
|
|
}
|
|
|
|
Action* act = InstantiateAction(args);
|
|
|
|
if ( ! act )
|
|
{
|
|
delete key;
|
|
return false;
|
|
}
|
|
|
|
InsertAction(act, key);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ActionSet::QueueAddAction(RecordVal* args)
|
|
{
|
|
HashKey* key = GetKey(args);
|
|
Action* act = InstantiateAction(args);
|
|
|
|
if ( ! act )
|
|
{
|
|
delete key;
|
|
return false;
|
|
}
|
|
|
|
mod_queue.push(new Add(act, key));
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ActionSet::Add::Perform(ActionSet* set)
|
|
{
|
|
if ( set->action_map.Lookup(key) )
|
|
{
|
|
DBG_LOG(DBG_FILE_ANALYSIS, "Add action %d skipped for file id"
|
|
" %s: already exists", act->Tag(),
|
|
act->GetFile()->GetID().c_str());
|
|
Abort();
|
|
return true;
|
|
}
|
|
|
|
set->InsertAction(act, key);
|
|
return true;
|
|
}
|
|
|
|
bool ActionSet::RemoveAction(const RecordVal* args)
|
|
{
|
|
return RemoveAction(Action::ArgsTag(args), GetKey(args));
|
|
}
|
|
|
|
bool ActionSet::RemoveAction(ActionTag tag, HashKey* key)
|
|
{
|
|
Action* act = (Action*) action_map.Remove(key);
|
|
delete key;
|
|
|
|
if ( ! act )
|
|
{
|
|
DBG_LOG(DBG_FILE_ANALYSIS, "Skip remove action %d for file id %s",
|
|
tag, file->GetID().c_str());
|
|
return false;
|
|
}
|
|
|
|
DBG_LOG(DBG_FILE_ANALYSIS, "Remove action %d for file id %s", act->Tag(),
|
|
file->GetID().c_str());
|
|
delete act;
|
|
return true;
|
|
}
|
|
|
|
bool ActionSet::QueueRemoveAction(const RecordVal* args)
|
|
{
|
|
HashKey* key = GetKey(args);
|
|
ActionTag tag = Action::ArgsTag(args);
|
|
|
|
mod_queue.push(new Remove(tag, key));
|
|
|
|
return action_map.Lookup(key);
|
|
}
|
|
|
|
bool ActionSet::Remove::Perform(ActionSet* set)
|
|
{
|
|
return set->RemoveAction(tag, key);
|
|
}
|
|
|
|
HashKey* ActionSet::GetKey(const RecordVal* args) const
|
|
{
|
|
HashKey* key = action_hash->ComputeHash(args, 1);
|
|
if ( ! key )
|
|
reporter->InternalError("ActionArgs type mismatch");
|
|
return key;
|
|
}
|
|
|
|
Action* ActionSet::InstantiateAction(RecordVal* args) const
|
|
{
|
|
Action* act = action_factory[Action::ArgsTag(args)](args, file);
|
|
|
|
if ( ! act )
|
|
{
|
|
DBG_LOG(DBG_FILE_ANALYSIS, "Instantiate action %d failed for file id",
|
|
" %s", Action::ArgsTag(args), file->GetID().c_str());
|
|
return 0;
|
|
}
|
|
|
|
return act;
|
|
}
|
|
|
|
void ActionSet::InsertAction(Action* act, HashKey* key)
|
|
{
|
|
DBG_LOG(DBG_FILE_ANALYSIS, "Add action %d for file id %s", act->Tag(),
|
|
file->GetID().c_str());
|
|
action_map.Insert(key, act);
|
|
delete key;
|
|
}
|
|
|
|
void ActionSet::DrainModifications()
|
|
{
|
|
if ( mod_queue.empty() ) return;
|
|
|
|
DBG_LOG(DBG_FILE_ANALYSIS, "Start flushing action mod queue of file id %s",
|
|
file->GetID().c_str());
|
|
do
|
|
{
|
|
Modification* mod = mod_queue.front();
|
|
mod->Perform(this);
|
|
delete mod;
|
|
mod_queue.pop();
|
|
} while ( ! mod_queue.empty() );
|
|
DBG_LOG(DBG_FILE_ANALYSIS, "End flushing action mod queue of file id %s",
|
|
file->GetID().c_str());
|
|
}
|