mirror of
https://github.com/zeek/zeek.git
synced 2025-10-04 07:38:19 +00:00
Add file analysis action to send data to script-land in chosen events.
This commit is contained in:
parent
85410a7657
commit
4b30cc2e24
10 changed files with 134 additions and 17 deletions
|
@ -33,8 +33,13 @@ export {
|
|||
## TODO: what's a reasonable default?
|
||||
const default_data_event_len: count = 1024*1024 &redef;
|
||||
|
||||
# Needed a forward declaration for event parameters...
|
||||
type Info: record {};
|
||||
|
||||
type ActionArgs: record {
|
||||
extract_filename: string &optional;
|
||||
chunk_event: event(info: Info, data: string, off: count) &optional;
|
||||
stream_event: event(info: Info, data: string) &optional;
|
||||
};
|
||||
|
||||
type ActionResults: record {
|
||||
|
|
|
@ -455,6 +455,7 @@ set(bro_SRCS
|
|||
file_analysis/Action.h
|
||||
file_analysis/Extract.cc
|
||||
file_analysis/Hash.cc
|
||||
file_analysis/DataEvent.cc
|
||||
|
||||
nb_dns.c
|
||||
digest.h
|
||||
|
|
|
@ -61,11 +61,12 @@ enum Action %{
|
|||
ACTION_MD5,
|
||||
ACTION_SHA1,
|
||||
ACTION_SHA256,
|
||||
ACTION_DATA_EVENT,
|
||||
%}
|
||||
|
||||
function FileAnalysis::postpone_timeout%(file_id: string%): bool
|
||||
%{
|
||||
using namespace file_analysis;
|
||||
using file_analysis::FileID;
|
||||
bool result = file_mgr->PostponeTimeout(FileID(file_id->CheckString()));
|
||||
return new Val(result, TYPE_BOOL);
|
||||
%}
|
||||
|
@ -74,9 +75,9 @@ function FileAnalysis::add_action%(file_id: string,
|
|||
action: FileAnalysis::Action,
|
||||
args: any%): bool
|
||||
%{
|
||||
using namespace file_analysis;
|
||||
RecordVal* rv = args->AsRecordVal()->CoerceTo(
|
||||
BifType::Record::FileAnalysis::ActionArgs);
|
||||
using file_analysis::FileID;
|
||||
using BifType::Record::FileAnalysis::ActionArgs;
|
||||
RecordVal* rv = args->AsRecordVal()->CoerceTo(ActionArgs);
|
||||
bool result = file_mgr->AddAction(FileID(file_id->CheckString()),
|
||||
action->AsEnumVal(), rv);
|
||||
Unref(rv);
|
||||
|
@ -86,7 +87,7 @@ function FileAnalysis::add_action%(file_id: string,
|
|||
function FileAnalysis::remove_action%(file_id: string,
|
||||
action: FileAnalysis::Action%): bool
|
||||
%{
|
||||
using namespace file_analysis;
|
||||
using file_analysis::FileID;
|
||||
bool result = file_mgr->RemoveAction(FileID(file_id->CheckString()),
|
||||
action->AsEnumVal());
|
||||
return new Val(result, TYPE_BOOL);
|
||||
|
@ -94,7 +95,7 @@ function FileAnalysis::remove_action%(file_id: string,
|
|||
|
||||
function FileAnalysis::stop%(file_id: string%): bool
|
||||
%{
|
||||
using namespace file_analysis;
|
||||
using file_analysis::FileID;
|
||||
bool result = file_mgr->RemoveFile(FileID(file_id->CheckString()));
|
||||
return new Val(result, TYPE_BOOL);
|
||||
%}
|
||||
|
|
69
src/file_analysis/DataEvent.cc
Normal file
69
src/file_analysis/DataEvent.cc
Normal file
|
@ -0,0 +1,69 @@
|
|||
#include <string>
|
||||
|
||||
#include "DataEvent.h"
|
||||
#include "EventRegistry.h"
|
||||
#include "Event.h"
|
||||
#include "util.h"
|
||||
|
||||
using namespace file_analysis;
|
||||
|
||||
DataEvent::DataEvent(Info* arg_info, EventHandlerPtr ce, EventHandlerPtr se)
|
||||
: Action(arg_info, BifEnum::FileAnalysis::ACTION_DATA_EVENT),
|
||||
chunk_event(ce), stream_event(se)
|
||||
{
|
||||
}
|
||||
|
||||
Action* DataEvent::Instantiate(const RecordVal* args, Info* info)
|
||||
{
|
||||
using BifType::Record::FileAnalysis::ActionArgs;
|
||||
|
||||
const char* chunk_field = "chunk_event";
|
||||
const char* stream_field = "stream_event";
|
||||
int chunk_off = ActionArgs->FieldOffset(chunk_field);
|
||||
int stream_off = ActionArgs->FieldOffset(stream_field);
|
||||
|
||||
Val* chunk_val = args->Lookup(chunk_off);
|
||||
Val* stream_val = args->Lookup(stream_off);
|
||||
|
||||
if ( ! chunk_val && ! stream_val ) return 0;
|
||||
|
||||
EventHandlerPtr chunk;
|
||||
EventHandlerPtr stream;
|
||||
|
||||
if ( chunk_val )
|
||||
chunk = event_registry->Lookup(chunk_val->AsFunc()->GetID()->Name());
|
||||
|
||||
if ( stream_val )
|
||||
stream = event_registry->Lookup(stream_val->AsFunc()->GetID()->Name());
|
||||
|
||||
return new DataEvent(info, chunk, stream);
|
||||
}
|
||||
|
||||
bool DataEvent::DeliverChunk(const u_char* data, uint64 len, uint64 offset)
|
||||
{
|
||||
Action::DeliverChunk(data, len, offset);
|
||||
|
||||
if ( ! chunk_event ) return true;
|
||||
|
||||
val_list* args = new val_list;
|
||||
args->append(info->GetVal()->Ref());
|
||||
args->append(new StringVal(new BroString(data, len, 0)));
|
||||
args->append(new Val(offset, TYPE_COUNT));
|
||||
mgr.QueueEvent(chunk_event, args);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DataEvent::DeliverStream(const u_char* data, uint64 len)
|
||||
{
|
||||
Action::DeliverStream(data, len);
|
||||
|
||||
if ( ! stream_event ) return true;
|
||||
|
||||
val_list* args = new val_list;
|
||||
args->append(info->GetVal()->Ref());
|
||||
args->append(new StringVal(new BroString(data, len, 0)));
|
||||
mgr.QueueEvent(stream_event, args);
|
||||
|
||||
return true;
|
||||
}
|
34
src/file_analysis/DataEvent.h
Normal file
34
src/file_analysis/DataEvent.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
#ifndef FILE_ANALYSIS_DATAEVENT_H
|
||||
#define FILE_ANALYSIS_DATAEVENT_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "Val.h"
|
||||
#include "Info.h"
|
||||
#include "Action.h"
|
||||
|
||||
namespace file_analysis {
|
||||
|
||||
/**
|
||||
* An action to send file data to script-layer events.
|
||||
*/
|
||||
class DataEvent : public Action {
|
||||
public:
|
||||
|
||||
static Action* Instantiate(const RecordVal* args, Info* info);
|
||||
|
||||
virtual bool DeliverChunk(const u_char* data, uint64 len, uint64 offset);
|
||||
|
||||
virtual bool DeliverStream(const u_char* data, uint64 len);
|
||||
|
||||
protected:
|
||||
|
||||
DataEvent(Info* arg_info, EventHandlerPtr ce, EventHandlerPtr se);
|
||||
|
||||
EventHandlerPtr chunk_event;
|
||||
EventHandlerPtr stream_event;
|
||||
};
|
||||
|
||||
} // namespace file_analysis
|
||||
|
||||
#endif
|
|
@ -50,5 +50,5 @@ void Hash::Finalize()
|
|||
if ( i < 0 )
|
||||
reporter->InternalError("Hash Action result field not found");
|
||||
|
||||
info->Results()->Assign(i, sv);
|
||||
info->GetResults()->Assign(i, sv);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "Action.h"
|
||||
#include "Extract.h"
|
||||
#include "Hash.h"
|
||||
#include "DataEvent.h"
|
||||
|
||||
using namespace file_analysis;
|
||||
|
||||
|
@ -18,6 +19,7 @@ static ActionInstantiator action_factory[] = {
|
|||
MD5::Instantiate,
|
||||
SHA1::Instantiate,
|
||||
SHA256::Instantiate,
|
||||
DataEvent::Instantiate,
|
||||
};
|
||||
|
||||
static TableVal* empty_conn_id_set()
|
||||
|
@ -150,12 +152,12 @@ int Info::Idx(const string& field)
|
|||
return rval;
|
||||
}
|
||||
|
||||
double Info::TimeoutInterval() const
|
||||
double Info::GetTimeoutInterval() const
|
||||
{
|
||||
return LookupFieldDefaultInterval(timeout_interval_idx);
|
||||
}
|
||||
|
||||
RecordVal* Info::Results() const
|
||||
RecordVal* Info::GetResults() const
|
||||
{
|
||||
return val->Lookup(action_results_idx)->AsRecordVal();
|
||||
}
|
||||
|
@ -182,7 +184,7 @@ bool Info::IsComplete() const
|
|||
|
||||
void Info::ScheduleInactivityTimer() const
|
||||
{
|
||||
timer_mgr->Add(new InfoTimer(network_time, file_id, TimeoutInterval()));
|
||||
timer_mgr->Add(new InfoTimer(network_time, file_id, GetTimeoutInterval()));
|
||||
}
|
||||
|
||||
bool Info::AddAction(ActionTag act, RecordVal* args)
|
||||
|
|
|
@ -19,10 +19,15 @@ public:
|
|||
|
||||
~Info();
|
||||
|
||||
/**
|
||||
* @return the #val record.
|
||||
*/
|
||||
RecordVal* GetVal() const { return val; }
|
||||
|
||||
/**
|
||||
* @return value (seconds) of the "timeout_interval" field from #val record.
|
||||
*/
|
||||
double TimeoutInterval() const;
|
||||
double GetTimeoutInterval() const;
|
||||
|
||||
/**
|
||||
* @return value of the "file_id" field from #val record.
|
||||
|
@ -32,17 +37,17 @@ public:
|
|||
/**
|
||||
* @return record val of the "action_results" field from #val record.
|
||||
*/
|
||||
RecordVal* Results() const;
|
||||
RecordVal* GetResults() const;
|
||||
|
||||
/**
|
||||
* @return the string which uniquely identifies the file.
|
||||
*/
|
||||
string Unique() const { return unique; }
|
||||
string GetUnique() const { return unique; }
|
||||
|
||||
/**
|
||||
* @return #last_activity_time
|
||||
*/
|
||||
double LastActivityTime() const { return last_activity_time; }
|
||||
double GetLastActivityTime() const { return last_activity_time; }
|
||||
|
||||
/**
|
||||
* Refreshes #last_activity_time with current network time.
|
||||
|
|
|
@ -9,7 +9,7 @@ void InfoTimer::Dispatch(double t, int is_expire)
|
|||
|
||||
if ( ! info ) return;
|
||||
|
||||
double last_active = info->LastActivityTime();
|
||||
double last_active = info->GetLastActivityTime();
|
||||
double inactive_time = t > last_active ? t - last_active : 0.0;
|
||||
|
||||
DBG_LOG(DBG_FILE_ANALYSIS, "Checking inactivity for %s, last active at %f, "
|
||||
|
@ -23,7 +23,7 @@ void InfoTimer::Dispatch(double t, int is_expire)
|
|||
return;
|
||||
}
|
||||
|
||||
if ( inactive_time >= info->TimeoutInterval() )
|
||||
if ( inactive_time >= info->GetTimeoutInterval() )
|
||||
file_mgr->Timeout(file_id);
|
||||
else if ( ! is_expire )
|
||||
info->ScheduleInactivityTimer();
|
||||
|
|
|
@ -185,7 +185,7 @@ bool Manager::RemoveFile(const FileID& file_id)
|
|||
|
||||
if ( it == id_map.end() ) return false;
|
||||
|
||||
if ( ! str_map.erase(it->second->Unique()) )
|
||||
if ( ! str_map.erase(it->second->GetUnique()) )
|
||||
reporter->Error("No string mapping for file ID %s", file_id.c_str());
|
||||
delete it->second;
|
||||
id_map.erase(it);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue