mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Add prototype file analysis interfaces.
Nothing connects to them yet and nothing would happen even if it did. Work on analyzers/actions for files coming soon.
This commit is contained in:
parent
564e27abb6
commit
390e4082c7
14 changed files with 635 additions and 2 deletions
1
scripts/base/frameworks/file-analysis/__load__.bro
Normal file
1
scripts/base/frameworks/file-analysis/__load__.bro
Normal file
|
@ -0,0 +1 @@
|
|||
@load ./main.bro
|
81
scripts/base/frameworks/file-analysis/main.bro
Normal file
81
scripts/base/frameworks/file-analysis/main.bro
Normal file
|
@ -0,0 +1,81 @@
|
|||
##! TODO add some comments here
|
||||
|
||||
@load base/file_analysis.bif
|
||||
|
||||
# TODO: do logging here?
|
||||
@load base/frameworks/logging
|
||||
|
||||
module FileAnalysis;
|
||||
|
||||
export {
|
||||
redef enum Log::ID += {
|
||||
## Logging stream for file analysis.
|
||||
LOG
|
||||
};
|
||||
|
||||
## The default buffer size used to reassemble files.
|
||||
# TODO: what's a reasonable default?
|
||||
const default_reassembly_buffer_size: count = 1024*1024 &redef;
|
||||
|
||||
## The default buffer size used for storing the beginning of files.
|
||||
# TODO: what's a reasonable default?
|
||||
const default_bof_buffer_size: count = 256 &redef;
|
||||
|
||||
## The default amount of time file analysis will wait for new file data
|
||||
## before giving up.
|
||||
## TODO: what's a reasonable default?
|
||||
#const default_timeout_interval: interval = 2 mins &redef;
|
||||
const default_timeout_interval: interval = 10 sec &redef;
|
||||
|
||||
## The default amount of data that a user is allowed to extract
|
||||
## from a file to an event with the
|
||||
## :bro:see:`FileAnalysis::ACTION_DATA_EVENT` action.
|
||||
## TODO: what's a reasonable default?
|
||||
const default_data_event_len: count = 1024*1024 &redef;
|
||||
|
||||
## Contains all metadata related to the analysis of a given file, some
|
||||
## of which is logged.
|
||||
type Info: record {
|
||||
## Unique identifier associated with a single file.
|
||||
file_id: string &log;
|
||||
## Unique identifier associated with the file if it was extracted
|
||||
## from a container file as part of the analysis.
|
||||
parent_file_id: string &log &optional;
|
||||
|
||||
## The network protocol over which the file was transferred.
|
||||
protocol: string &log &optional;
|
||||
|
||||
## The set of connections over which the file was transferred,
|
||||
## indicated by UID strings.
|
||||
conn_uids: set[string] &log &optional;
|
||||
## The set of connections over which the file was transferred,
|
||||
## indicated by 5-tuples.
|
||||
conn_ids: set[conn_id] &optional;
|
||||
|
||||
## Number of bytes provided to the file analysis engine for the file.
|
||||
seen_bytes: count &log &default=0;
|
||||
## Total number of bytes that are supposed to comprise the file content.
|
||||
total_bytes: count &log &optional;
|
||||
|
||||
## The number of not all-in-sequence bytes over the course of the
|
||||
## analysis that had to be discarded due to a reassembly buffer size
|
||||
## of *reassembly_buffer_size* being filled.
|
||||
undelivered: count &default=0;
|
||||
|
||||
## The amount of time between receiving new data for this file that
|
||||
## the analysis engine will wait before giving up on it.
|
||||
timeout_interval: interval &default=default_timeout_interval;
|
||||
|
||||
} &redef;
|
||||
|
||||
## TODO: document
|
||||
global policy: hook(trig: Trigger, info: Info);
|
||||
|
||||
## TODO: document
|
||||
global postpone_timeout: function(file_id: string): bool;
|
||||
}
|
||||
|
||||
function postpone_timeout(file_id: string): bool
|
||||
{
|
||||
return __postpone_timeout(file_id);
|
||||
}
|
|
@ -2866,3 +2866,4 @@ const snaplen = 8192 &redef;
|
|||
|
||||
@load base/frameworks/input
|
||||
|
||||
@load base/frameworks/file-analysis
|
||||
|
|
|
@ -145,6 +145,7 @@ set(BIF_SRCS
|
|||
logging.bif
|
||||
input.bif
|
||||
event.bif
|
||||
file_analysis.bif
|
||||
const.bif
|
||||
types.bif
|
||||
strings.bif
|
||||
|
@ -328,6 +329,7 @@ set(bro_SRCS
|
|||
FTP.cc
|
||||
File.cc
|
||||
FileAnalyzer.cc
|
||||
FileAnalysisManager.cc
|
||||
Finger.cc
|
||||
FlowSrc.cc
|
||||
Frag.cc
|
||||
|
|
|
@ -16,7 +16,7 @@ DebugLogger::Stream DebugLogger::streams[NUM_DBGS] = {
|
|||
{ "notifiers", 0, false }, { "main-loop", 0, false },
|
||||
{ "dpd", 0, false }, { "tm", 0, false },
|
||||
{ "logging", 0, false }, {"input", 0, false },
|
||||
{ "threading", 0, false }
|
||||
{ "threading", 0, false }, { "file_analysis", 0, false }
|
||||
};
|
||||
|
||||
DebugLogger::DebugLogger(const char* filename)
|
||||
|
|
|
@ -26,6 +26,7 @@ enum DebugStream {
|
|||
DBG_LOGGING, // Logging streams
|
||||
DBG_INPUT, // Input streams
|
||||
DBG_THREADING, // Threading system
|
||||
DBG_FILE_ANALYSIS, // File analysis
|
||||
|
||||
NUM_DBGS // Has to be last
|
||||
};
|
||||
|
|
276
src/FileAnalysisManager.cc
Normal file
276
src/FileAnalysisManager.cc
Normal file
|
@ -0,0 +1,276 @@
|
|||
#include <vector>
|
||||
|
||||
#include "FileAnalysisManager.h"
|
||||
#include "util.h"
|
||||
|
||||
using namespace file_analysis;
|
||||
|
||||
static TableVal* empty_conn_id_set()
|
||||
{
|
||||
TypeList* set_index = new TypeList(conn_id);
|
||||
set_index->Append(conn_id->Ref());
|
||||
return new TableVal(new SetType(set_index, 0));
|
||||
}
|
||||
|
||||
static StringVal* get_conn_uid_val(Connection* conn)
|
||||
{
|
||||
char tmp[20];
|
||||
if ( ! conn->GetUID() )
|
||||
conn->SetUID(calculate_unique_id());
|
||||
return new StringVal(uitoa_n(conn->GetUID(), tmp, sizeof(tmp), 62));
|
||||
}
|
||||
|
||||
static RecordVal* get_conn_id_val(const Connection* conn)
|
||||
{
|
||||
RecordVal* v = new RecordVal(conn_id);
|
||||
v->Assign(0, new AddrVal(conn->OrigAddr()));
|
||||
v->Assign(1, new PortVal(ntohs(conn->OrigPort()), conn->ConnTransport()));
|
||||
v->Assign(2, new AddrVal(conn->RespAddr()));
|
||||
v->Assign(3, new PortVal(ntohs(conn->RespPort()), conn->ConnTransport()));
|
||||
return v;
|
||||
}
|
||||
|
||||
int Info::file_id_idx = -1;
|
||||
int Info::parent_file_id_idx = -1;
|
||||
int Info::protocol_idx = -1;
|
||||
int Info::conn_uids_idx = -1;
|
||||
int Info::conn_ids_idx = -1;
|
||||
int Info::seen_bytes_idx = -1;
|
||||
int Info::total_bytes_idx = -1;
|
||||
int Info::undelivered_idx = -1;
|
||||
int Info::timeout_interval_idx = -1;
|
||||
|
||||
Info::Info(const string& file_id, Connection* conn, AnalyzerTag::Tag at)
|
||||
: val(0), last_activity_time(network_time), postpone_timeout(false)
|
||||
{
|
||||
DBG_LOG(DBG_FILE_ANALYSIS, "Creating new Info object %s", file_id.c_str());
|
||||
|
||||
if ( file_id_idx == -1 )
|
||||
{
|
||||
file_id_idx = Idx("file_id");
|
||||
parent_file_id_idx = Idx("parent_file_id");
|
||||
protocol_idx = Idx("protocol");
|
||||
conn_uids_idx = Idx("conn_uids");
|
||||
conn_ids_idx = Idx("conn_ids");
|
||||
seen_bytes_idx = Idx("seen_bytes");
|
||||
total_bytes_idx = Idx("total_bytes");
|
||||
undelivered_idx = Idx("undelivered");
|
||||
timeout_interval_idx = Idx("timeout_interval");
|
||||
}
|
||||
|
||||
val = new RecordVal(BifType::Record::FileAnalysis::Info);
|
||||
val->Assign(file_id_idx, new StringVal(file_id.c_str()));
|
||||
|
||||
UpdateConnectionFields(conn);
|
||||
|
||||
if ( at != AnalyzerTag::Error )
|
||||
val->Assign(protocol_idx, new StringVal(Analyzer::GetTagName(at)));
|
||||
|
||||
ScheduleInactivityTimer();
|
||||
Manager::EvaluatePolicy(BifEnum::FileAnalysis::TRIGGER_NEW, this);
|
||||
}
|
||||
|
||||
Info::~Info()
|
||||
{
|
||||
DBG_LOG(DBG_FILE_ANALYSIS, "Destroying Info object %s", FileID().c_str());
|
||||
Unref(val);
|
||||
}
|
||||
|
||||
void Info::UpdateConnectionFields(Connection* conn)
|
||||
{
|
||||
if ( ! conn ) return;
|
||||
|
||||
Val* conn_uids = val->Lookup(conn_uids_idx);
|
||||
Val* conn_ids = val->Lookup(conn_ids_idx);
|
||||
if ( ! conn_uids )
|
||||
val->Assign(conn_uids_idx, conn_uids = new TableVal(string_set));
|
||||
if ( ! conn_ids )
|
||||
val->Assign(conn_ids_idx, conn_ids = empty_conn_id_set());
|
||||
|
||||
conn_uids->AsTableVal()->Assign(get_conn_uid_val(conn), 0);
|
||||
conn_ids->AsTableVal()->Assign(get_conn_id_val(conn), 0);
|
||||
}
|
||||
|
||||
int Info::Idx(const string& field)
|
||||
{
|
||||
int rval = BifType::Record::FileAnalysis::Info->FieldOffset(field.c_str());
|
||||
if ( rval < 0 )
|
||||
reporter->InternalError("Unkown FileAnalysis::Info field: %s",
|
||||
field.c_str());
|
||||
return rval;
|
||||
}
|
||||
|
||||
double Info::TimeoutInterval() const
|
||||
{
|
||||
return val->LookupWithDefault(timeout_interval_idx)->AsInterval();
|
||||
}
|
||||
|
||||
string Info::FileID() const
|
||||
{
|
||||
return val->Lookup(file_id_idx)->AsString()->CheckString();
|
||||
}
|
||||
|
||||
void Info::SetTotalBytes(uint64 size)
|
||||
{
|
||||
val->Assign(total_bytes_idx, new Val(size, TYPE_COUNT));
|
||||
|
||||
if ( val->LookupWithDefault(seen_bytes_idx)->AsCount() >= size )
|
||||
{
|
||||
Manager::EvaluatePolicy(BifEnum::FileAnalysis::TRIGGER_DONE, this);
|
||||
file_mgr->Remove(FileID());
|
||||
}
|
||||
}
|
||||
|
||||
void Info::ScheduleInactivityTimer() const
|
||||
{
|
||||
timer_mgr->Add(new InfoTimer(network_time, FileID(), TimeoutInterval()));
|
||||
}
|
||||
|
||||
void InfoTimer::Dispatch(double t, int is_expire)
|
||||
{
|
||||
Info* info = file_mgr->Lookup(file_id);
|
||||
|
||||
if ( ! info ) return;
|
||||
|
||||
double last_active = info->LastActivityTime();
|
||||
double inactive_time = t > last_active ? t - last_active : 0.0;
|
||||
|
||||
DBG_LOG(DBG_FILE_ANALYSIS, "Checking inactivity for %s, last active at %f, "
|
||||
"inactive for %f", file_id.c_str(), last_active, inactive_time);
|
||||
|
||||
if ( last_active == 0.0 )
|
||||
{
|
||||
// was created when network_time was zero, so re-schedule w/ valid time
|
||||
info->UpdateLastActivityTime();
|
||||
info->ScheduleInactivityTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( inactive_time >= info->TimeoutInterval() )
|
||||
file_mgr->Timeout(file_id);
|
||||
else if ( ! is_expire )
|
||||
info->ScheduleInactivityTimer();
|
||||
}
|
||||
|
||||
Manager::Manager()
|
||||
{
|
||||
}
|
||||
|
||||
Manager::~Manager()
|
||||
{
|
||||
Terminate();
|
||||
}
|
||||
|
||||
void Manager::Terminate()
|
||||
{
|
||||
vector<string> keys;
|
||||
for ( FileMap::iterator it = file_map.begin(); it != file_map.end(); ++it )
|
||||
keys.push_back(it->first);
|
||||
for ( size_t i = 0; i < keys.size(); ++i )
|
||||
Timeout(keys[i], true);
|
||||
}
|
||||
|
||||
void Manager::DataIn(const string& file_id, const u_char* data, uint64 len,
|
||||
uint64 offset, Connection* conn, AnalyzerTag::Tag at)
|
||||
{
|
||||
Info* info = IDtoInfo(file_id, conn, at);
|
||||
info->UpdateLastActivityTime();
|
||||
info->UpdateConnectionFields(conn);
|
||||
// TODO: more stuff
|
||||
}
|
||||
|
||||
void Manager::DataIn(const string& file_id, const u_char* data, uint64 len,
|
||||
Connection* conn, AnalyzerTag::Tag at)
|
||||
{
|
||||
Info* info = IDtoInfo(file_id, conn, at);
|
||||
info->UpdateLastActivityTime();
|
||||
info->UpdateConnectionFields(conn);
|
||||
// TODO: more stuff
|
||||
}
|
||||
|
||||
void Manager::SetSize(const string& file_id, uint64 size,
|
||||
Connection* conn, AnalyzerTag::Tag at)
|
||||
{
|
||||
Info* info = IDtoInfo(file_id, conn, at);
|
||||
info->UpdateLastActivityTime();
|
||||
info->UpdateConnectionFields(conn);
|
||||
info->SetTotalBytes(size);
|
||||
}
|
||||
|
||||
void Manager::EvaluatePolicy(BifEnum::FileAnalysis::Trigger t, Info* info)
|
||||
{
|
||||
const ID* id = global_scope()->Lookup("FileAnalysis::policy");
|
||||
assert(id);
|
||||
const Func* hook = id->ID_Val()->AsFunc();
|
||||
|
||||
val_list vl(2);
|
||||
vl.append(new EnumVal(t, BifType::Enum::FileAnalysis::Trigger));
|
||||
vl.append(info->val->Ref());
|
||||
|
||||
info->postpone_timeout = false;
|
||||
|
||||
Val* result = hook->Call(&vl);
|
||||
Unref(result);
|
||||
}
|
||||
|
||||
bool Manager::PostponeTimeout(const string& file_id) const
|
||||
{
|
||||
Info* info = Lookup(file_id);
|
||||
|
||||
if ( ! info ) return false;
|
||||
|
||||
info->postpone_timeout = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
Info* Manager::IDtoInfo(const string& file_id, Connection* conn,
|
||||
AnalyzerTag::Tag at)
|
||||
{
|
||||
Info* rval = file_map[file_id];
|
||||
if ( ! rval )
|
||||
rval = file_map[file_id] = new Info(file_id, conn, at);
|
||||
return rval;
|
||||
}
|
||||
|
||||
Info* Manager::Lookup(const string& file_id) const
|
||||
{
|
||||
FileMap::const_iterator it = file_map.find(file_id);
|
||||
|
||||
if ( it == file_map.end() ) return 0;
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void Manager::Timeout(const string& file_id, bool is_terminating)
|
||||
{
|
||||
Info* info = Lookup(file_id);
|
||||
|
||||
if ( ! info ) return;
|
||||
|
||||
EvaluatePolicy(BifEnum::FileAnalysis::TRIGGER_TIMEOUT, info);
|
||||
|
||||
if ( info->postpone_timeout && ! is_terminating )
|
||||
{
|
||||
DBG_LOG(DBG_FILE_ANALYSIS, "Postpone file analysis timeout for %s",
|
||||
info->FileID().c_str());
|
||||
info->UpdateLastActivityTime();
|
||||
info->ScheduleInactivityTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
DBG_LOG(DBG_FILE_ANALYSIS, "File analysis timeout for %s",
|
||||
info->FileID().c_str());
|
||||
|
||||
file_map.erase(file_id);
|
||||
delete info;
|
||||
}
|
||||
|
||||
void Manager::Remove(const string& file_id)
|
||||
{
|
||||
FileMap::iterator it = file_map.find(file_id);
|
||||
|
||||
if ( it == file_map.end() ) return;
|
||||
|
||||
delete it->second;
|
||||
file_map.erase(it);
|
||||
}
|
199
src/FileAnalysisManager.h
Normal file
199
src/FileAnalysisManager.h
Normal file
|
@ -0,0 +1,199 @@
|
|||
#ifndef FILE_ANALYSIS_MANAGER_H
|
||||
#define FILE_ANALYSIS_MANAGER_H
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "Conn.h"
|
||||
#include "Analyzer.h"
|
||||
#include "AnalyzerTags.h"
|
||||
#include "Timer.h"
|
||||
#include "Val.h"
|
||||
#include "Reporter.h"
|
||||
|
||||
namespace file_analysis {
|
||||
|
||||
/**
|
||||
* Wrapper class around \c FileAnalysis::Info record values from script layer.
|
||||
*/
|
||||
class Info {
|
||||
public:
|
||||
|
||||
~Info();
|
||||
|
||||
/**
|
||||
* @return value (seconds) of the "timeout_interval" field from #val record.
|
||||
*/
|
||||
double TimeoutInterval() const;
|
||||
|
||||
/**
|
||||
* @return value of the "file_id" field from #val record.
|
||||
*/
|
||||
string FileID() const;
|
||||
|
||||
/**
|
||||
* @return #last_activity_time
|
||||
*/
|
||||
double LastActivityTime() const { return last_activity_time; }
|
||||
|
||||
/**
|
||||
* Refreshes #last_activity_time with current network time.
|
||||
*/
|
||||
void UpdateLastActivityTime() { last_activity_time = network_time; }
|
||||
|
||||
/**
|
||||
* Set "total_bytes" field of #val record to \a size, check if "seen_bytes"
|
||||
* is greater or equal to it, and evaluate \c FileAnalysis::policy if so.
|
||||
*/
|
||||
void SetTotalBytes(uint64 size);
|
||||
|
||||
/**
|
||||
* Create a timer to be dispatched after the amount of time indicated by
|
||||
* the "timeout_interval" field of the #val record in order to check if
|
||||
* #last_activity_time is old enough to timeout analysis of the file.
|
||||
*/
|
||||
void ScheduleInactivityTimer() const;
|
||||
|
||||
protected:
|
||||
|
||||
friend class Manager;
|
||||
|
||||
/**
|
||||
* Constructor; only file_analysis::Manager should be creating these.
|
||||
*/
|
||||
Info(const string& file_id, Connection* conn = 0,
|
||||
AnalyzerTag::Tag at = AnalyzerTag::Error);
|
||||
|
||||
/**
|
||||
* Updates the "conn_ids" and "conn_uids" fields in #val record with the
|
||||
* \c conn_id and UID taken from \a conn.
|
||||
*/
|
||||
void UpdateConnectionFields(Connection* conn);
|
||||
|
||||
RecordVal* val; /**< \c FileAnalysis::Info from script layer. */
|
||||
double last_activity_time; /**< Time of last activity. */
|
||||
bool postpone_timeout; /**< Whether postponing timeout is requested. */
|
||||
|
||||
/**
|
||||
* @return the field offset in #val record corresponding to \a field_name.
|
||||
*/
|
||||
static int Idx(const string& field_name);
|
||||
|
||||
static int file_id_idx;
|
||||
static int parent_file_id_idx;
|
||||
static int protocol_idx;
|
||||
static int conn_uids_idx;
|
||||
static int conn_ids_idx;
|
||||
static int seen_bytes_idx;
|
||||
static int total_bytes_idx;
|
||||
static int undelivered_idx;
|
||||
static int timeout_interval_idx;
|
||||
};
|
||||
|
||||
/**
|
||||
* Timer to periodically check if file analysis for a given file is inative.
|
||||
*/
|
||||
class InfoTimer : public Timer {
|
||||
public:
|
||||
|
||||
InfoTimer(double t, const string& id, double interval)
|
||||
: Timer(t + interval, TIMER_FILE_ANALYSIS_INACTIVITY), file_id(id) { }
|
||||
|
||||
~InfoTimer() { }
|
||||
|
||||
/**
|
||||
* Check inactivity of file_analysis::Info corresponding to #file_id,
|
||||
* reschedule if active, else call file_analysis::Manager::Timeout.
|
||||
*/
|
||||
void Dispatch(double t, int is_expire);
|
||||
|
||||
protected:
|
||||
|
||||
string file_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* Main entry point for interacting with file analysis.
|
||||
*/
|
||||
class Manager {
|
||||
public:
|
||||
|
||||
Manager();
|
||||
|
||||
~Manager();
|
||||
|
||||
/**
|
||||
* Times out any active file analysis to prepare for shutdown.
|
||||
*/
|
||||
void Terminate();
|
||||
|
||||
/**
|
||||
* Pass in non-sequential file data.
|
||||
*/
|
||||
void DataIn(const string& file_id, const u_char* data, uint64 len,
|
||||
uint64 offset, Connection* conn = 0,
|
||||
AnalyzerTag::Tag at = AnalyzerTag::Error);
|
||||
|
||||
/**
|
||||
* Pass in sequential file data.
|
||||
*/
|
||||
void DataIn(const string& file_id, const u_char* data, uint64 len,
|
||||
Connection* conn = 0,
|
||||
AnalyzerTag::Tag at = AnalyzerTag::Error);
|
||||
|
||||
/**
|
||||
* Provide the expected number of bytes that comprise a file.
|
||||
*/
|
||||
void SetSize(const string& file_id, uint64 size, Connection* conn = 0,
|
||||
AnalyzerTag::Tag at = AnalyzerTag::Error);
|
||||
|
||||
/**
|
||||
* Discard the file_analysis::Info object associated with \a file_id.
|
||||
*/
|
||||
void Remove(const string& file_id);
|
||||
|
||||
/**
|
||||
* If called during \c FileAnalysis::policy evaluation for a
|
||||
* \c FileAnalysis::TRIGGER_TIMEOUT, requests deferral of analysis timeout.
|
||||
*/
|
||||
bool PostponeTimeout(const string& file_id) const;
|
||||
|
||||
/**
|
||||
* Calls the \c FileAnalysis::policy hook.
|
||||
*/
|
||||
static void EvaluatePolicy(BifEnum::FileAnalysis::Trigger t, Info* info);
|
||||
|
||||
protected:
|
||||
|
||||
friend class InfoTimer;
|
||||
|
||||
typedef map<string, Info*> FileMap;
|
||||
|
||||
/**
|
||||
* @return the Info object mapped to \a file_id. One is created if mapping
|
||||
* doesn't exist.
|
||||
*/
|
||||
Info* IDtoInfo(const string& file_id, Connection* conn = 0,
|
||||
AnalyzerTag::Tag at = AnalyzerTag::Error);
|
||||
|
||||
/**
|
||||
* @return the Info object mapped to \a file_id, or a null pointer if no
|
||||
* mapping exists.
|
||||
*/
|
||||
|
||||
Info* Lookup(const string& file_id) const;
|
||||
|
||||
/**
|
||||
* Evaluate timeout policy for a file and remove the Info object mapped to
|
||||
* \a file_id if needed.
|
||||
*/
|
||||
void Timeout(const string& file_id, bool is_terminating = ::terminating);
|
||||
|
||||
FileMap file_map; /**< Map strings to \c FileAnalysis::Info records. */
|
||||
};
|
||||
|
||||
} // namespace file_analysis
|
||||
|
||||
extern file_analysis::Manager* file_mgr;
|
||||
|
||||
#endif
|
|
@ -557,12 +557,14 @@ void builtin_error(const char* msg, BroObj* arg)
|
|||
#include "input.bif.func_h"
|
||||
#include "reporter.bif.func_h"
|
||||
#include "strings.bif.func_h"
|
||||
#include "file_analysis.bif.func_h"
|
||||
|
||||
#include "bro.bif.func_def"
|
||||
#include "logging.bif.func_def"
|
||||
#include "input.bif.func_def"
|
||||
#include "reporter.bif.func_def"
|
||||
#include "strings.bif.func_def"
|
||||
#include "file_analysis.bif.func_def"
|
||||
|
||||
void init_builtin_funcs()
|
||||
{
|
||||
|
@ -578,6 +580,7 @@ void init_builtin_funcs()
|
|||
#include "input.bif.func_init"
|
||||
#include "reporter.bif.func_init"
|
||||
#include "strings.bif.func_init"
|
||||
#include "file_analysis.bif.func_init"
|
||||
|
||||
did_builtin_init = true;
|
||||
}
|
||||
|
|
|
@ -246,6 +246,7 @@ StringVal* cmd_line_bpf_filter;
|
|||
#include "logging.bif.netvar_def"
|
||||
#include "input.bif.netvar_def"
|
||||
#include "reporter.bif.netvar_def"
|
||||
#include "file_analysis.bif.netvar_def"
|
||||
|
||||
void init_event_handlers()
|
||||
{
|
||||
|
@ -308,6 +309,7 @@ void init_net_var()
|
|||
#include "logging.bif.netvar_init"
|
||||
#include "input.bif.netvar_init"
|
||||
#include "reporter.bif.netvar_init"
|
||||
#include "file_analysis.bif.netvar_init"
|
||||
|
||||
gtpv1_hdr_type = internal_type("gtpv1_hdr")->AsRecordType();
|
||||
conn_id = internal_type("conn_id")->AsRecordType();
|
||||
|
|
|
@ -256,5 +256,6 @@ extern void init_net_var();
|
|||
#include "logging.bif.netvar_h"
|
||||
#include "input.bif.netvar_h"
|
||||
#include "reporter.bif.netvar_h"
|
||||
#include "file_analysis.bif.netvar_h"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -22,6 +22,7 @@ enum TimerType {
|
|||
TIMER_CONN_INACTIVITY,
|
||||
TIMER_CONN_STATUS_UPDATE,
|
||||
TIMER_DNS_EXPIRE,
|
||||
TIMER_FILE_ANALYSIS_INACTIVITY,
|
||||
TIMER_FRAG,
|
||||
TIMER_INCREMENTAL_SEND,
|
||||
TIMER_INCREMENTAL_WRITE,
|
||||
|
|
59
src/file_analysis.bif
Normal file
59
src/file_analysis.bif
Normal file
|
@ -0,0 +1,59 @@
|
|||
##! Internal functions and types used by the logging framework.
|
||||
|
||||
module FileAnalysis;
|
||||
|
||||
%%{
|
||||
#include "FileAnalysisManager.h"
|
||||
%%}
|
||||
|
||||
type Info: record;
|
||||
|
||||
## An enumeration of possibly-interesting "events" that can occur over
|
||||
## the course of analyzing files. The :bro:see:`FileAnalysis::policy`
|
||||
## hook is called each time a trigger occurs.
|
||||
enum Trigger %{
|
||||
## Raised when any part of a new file is detected.
|
||||
TRIGGER_NEW,
|
||||
## Raised when file analysis has likely seen a complete file. That
|
||||
## is when a number of bytes indicated by the *total_bytes* field of
|
||||
## :bro:see:`FileAnalysis::Info` have been processed. Note that
|
||||
## the *undelivered* field does not have to be zero for this to have
|
||||
## occurred.
|
||||
TRIGGER_DONE,
|
||||
## Raised when file analysis for a given file is aborted due
|
||||
## to not seeing any data for it recently. Note that this doesn't
|
||||
## necessarily mean the full file wasn't seen (e.g. if the
|
||||
## :bro:see:`FileAnalysis::Info` record indicates the file *total_bytes*
|
||||
## isn't known). Use :bro:see:`FileAnalysis::postpone_timeout`
|
||||
## during a :bro:see:`FileAnalysis::policy` handler for this trigger to
|
||||
## defer the timeout until later.
|
||||
TRIGGER_TIMEOUT,
|
||||
## Raised when the beginning of a file is detected.
|
||||
TRIGGER_BOF,
|
||||
## Raised when the beginning of a file is available and that beginning
|
||||
## is at least the number of bytes indicated by the *bof_buffer_size*
|
||||
## field of :bro:see:`FileAnalysis::Info`.
|
||||
TRIGGER_BOF_BUFFER_AVAIL,
|
||||
## Raised when the mime type of a file is matched based on magic
|
||||
## numbers. TODO: re-purposing protocols/http/file-ident.sig for
|
||||
## doing this is tricky since the signature engine doesn't expect
|
||||
## to be decoupled from connections, so figure out what work needs
|
||||
## done there.
|
||||
TRIGGER_MIME_TYPE,
|
||||
## Raised when the end of a file is detected. If the file is not
|
||||
## being transferred linearly, then this doesn't have to mean the full
|
||||
## file has been transferred.
|
||||
TRIGGER_EOF,
|
||||
## The reassembly buffer for the file filled and had to be discarded.
|
||||
## The *undelivered* field of :bro:see:`FileAnalysis::Info` will
|
||||
## indicate the number of bytes, if any, that were not all-in-sequence.
|
||||
## TODO: Is it possible to extend the reassembly buffer when "handling"
|
||||
## this trigger?
|
||||
TRIGGER_REASSEMBLY_BUFFER_FULL,
|
||||
%}
|
||||
|
||||
function FileAnalysis::__postpone_timeout%(file_id: string%): bool
|
||||
%{
|
||||
bool result = file_mgr->PostponeTimeout(file_id->CheckString());
|
||||
return new Val(result, TYPE_BOOL);
|
||||
%}
|
|
@ -58,6 +58,8 @@ extern "C" void OPENSSL_add_all_algorithms_conf(void);
|
|||
#include "logging/Manager.h"
|
||||
#include "logging/writers/Ascii.h"
|
||||
|
||||
#include "FileAnalysisManager.h"
|
||||
|
||||
#include "binpac_bro.h"
|
||||
|
||||
Brofiler brofiler;
|
||||
|
@ -86,6 +88,7 @@ TimerMgr* timer_mgr;
|
|||
logging::Manager* log_mgr = 0;
|
||||
threading::Manager* thread_mgr = 0;
|
||||
input::Manager* input_mgr = 0;
|
||||
file_analysis::Manager* file_mgr = 0;
|
||||
Stmt* stmts;
|
||||
EventHandlerPtr net_done = 0;
|
||||
RuleMatcher* rule_matcher = 0;
|
||||
|
@ -319,6 +322,7 @@ void terminate_bro()
|
|||
|
||||
mgr.Drain();
|
||||
|
||||
file_mgr->Terminate();
|
||||
log_mgr->Terminate();
|
||||
thread_mgr->Terminate();
|
||||
|
||||
|
@ -336,6 +340,7 @@ void terminate_bro()
|
|||
delete dpm;
|
||||
delete log_mgr;
|
||||
delete thread_mgr;
|
||||
delete file_mgr;
|
||||
delete reporter;
|
||||
|
||||
reporter = 0;
|
||||
|
@ -776,6 +781,7 @@ int main(int argc, char** argv)
|
|||
event_registry = new EventRegistry();
|
||||
log_mgr = new logging::Manager();
|
||||
input_mgr = new input::Manager();
|
||||
file_mgr = new file_analysis::Manager();
|
||||
|
||||
if ( events_file )
|
||||
event_player = new EventPlayer(events_file);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue