Reformat the world

This commit is contained in:
Tim Wojtulewicz 2021-09-16 15:35:39 -07:00
parent 194cb24547
commit b2f171ec69
714 changed files with 35149 additions and 35203 deletions

View file

@ -1,17 +1,18 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/file_analysis/Analyzer.h"
#include "zeek/file_analysis/Manager.h"
#include "zeek/Val.h"
namespace zeek::file_analysis {
#include "zeek/Val.h"
#include "zeek/file_analysis/Manager.h"
namespace zeek::file_analysis
{
ID Analyzer::id_counter = 0;
Analyzer::~Analyzer()
{
DBG_LOG(DBG_FILE_ANALYSIS, "Destroy file analyzer %s",
file_mgr->GetComponentName(tag).c_str());
DBG_LOG(DBG_FILE_ANALYSIS, "Destroy file analyzer %s", file_mgr->GetComponentName(tag).c_str());
}
void Analyzer::SetAnalyzerTag(const file_analysis::Tag& arg_tag)
@ -20,13 +21,8 @@ void Analyzer::SetAnalyzerTag(const file_analysis::Tag& arg_tag)
tag = arg_tag;
}
Analyzer::Analyzer(file_analysis::Tag arg_tag,
RecordValPtr arg_args,
File* arg_file)
: tag(arg_tag),
args(std::move(arg_args)),
file(arg_file),
got_stream_delivery(false),
Analyzer::Analyzer(file_analysis::Tag arg_tag, RecordValPtr arg_args, File* arg_file)
: tag(arg_tag), args(std::move(arg_args)), file(arg_file), got_stream_delivery(false),
skip(false)
{
id = ++id_counter;
@ -34,6 +30,7 @@ Analyzer::Analyzer(file_analysis::Tag arg_tag,
Analyzer::Analyzer(RecordValPtr arg_args, File* arg_file)
: Analyzer({}, std::move(arg_args), arg_file)
{}
{
}
} // namespace zeek::file_analysis
} // namespace zeek::file_analysis

View file

@ -6,12 +6,14 @@
#include "zeek/file_analysis/Tag.h"
namespace zeek {
namespace zeek
{
class RecordVal;
using RecordValPtr = IntrusivePtr<RecordVal>;
namespace file_analysis {
namespace file_analysis
{
class File;
using ID = uint32_t;
@ -19,9 +21,9 @@ using ID = uint32_t;
/**
* Base class for analyzers that can be attached to file_analysis::File objects.
*/
class Analyzer {
class Analyzer
{
public:
/**
* Destructor. Nothing special about it. Virtual since we definitely expect
* to delete instances of derived classes via pointers to this class.
@ -31,14 +33,12 @@ public:
/**
* Initializes the analyzer before input processing starts.
*/
virtual void Init()
{ }
virtual void Init() { }
/**
* Finishes the analyzer's operation after all input has been parsed.
*/
virtual void Done()
{ }
virtual void Done() { }
/**
* Subclasses may override this method to receive file data non-sequentially.
@ -48,8 +48,7 @@ public:
* @return true if the analyzer is still in a valid state to continue
* receiving data/events or false if it's essentially "done".
*/
virtual bool DeliverChunk(const u_char* data, uint64_t len, uint64_t offset)
{ return true; }
virtual bool DeliverChunk(const u_char* data, uint64_t len, uint64_t offset) { return true; }
/**
* Subclasses may override this method to receive file sequentially.
@ -58,8 +57,7 @@ public:
* @return true if the analyzer is still in a valid state to continue
* receiving data/events or false if it's essentially "done".
*/
virtual bool DeliverStream(const u_char* data, uint64_t len)
{ return true; }
virtual bool DeliverStream(const u_char* data, uint64_t len) { return true; }
/**
* Subclasses may override this method to specifically handle an EOF signal,
@ -68,8 +66,7 @@ public:
* @return true if the analyzer is still in a valid state to continue
* receiving data/events or false if it's essentially "done".
*/
virtual bool EndOfFile()
{ return true; }
virtual bool EndOfFile() { return true; }
/**
* Subclasses may override this method to handle missing data in a file.
@ -79,8 +76,7 @@ public:
* @return true if the analyzer is still in a valid state to continue
* receiving data/events or false if it's essentially "done".
*/
virtual bool Undelivered(uint64_t offset, uint64_t len)
{ return true; }
virtual bool Undelivered(uint64_t offset, uint64_t len) { return true; }
/**
* @return the analyzer type enum value.
@ -92,13 +88,12 @@ public:
* across all analyzers instantiated and can thus be used to
* indentify a specific instance.
*/
ID GetID() const { return id; }
ID GetID() const { return id; }
/**
* @return the AnalyzerArgs associated with the analyzer.
*/
const RecordValPtr& GetArgs() const
{ return args; }
const RecordValPtr& GetArgs() const { return args; }
/**
* @return the file_analysis::File object to which the analyzer is attached.
@ -116,14 +111,12 @@ public:
/**
* @return true if the analyzer has ever seen a stream-wise delivery.
*/
bool GotStreamDelivery() const
{ return got_stream_delivery; }
bool GotStreamDelivery() const { return got_stream_delivery; }
/**
* Flag the analyzer as having seen a stream-wise delivery.
*/
void SetGotStreamDelivery()
{ got_stream_delivery = true; }
void SetGotStreamDelivery() { got_stream_delivery = true; }
/**
* Signals that the analyzer is to skip all further input
@ -132,16 +125,15 @@ public:
*
* @param do_skip If true, further processing will be skipped.
*/
void SetSkip(bool do_skip) { skip = do_skip; }
void SetSkip(bool do_skip) { skip = do_skip; }
/**
* Returns true if the analyzer has been told to skip processing all
* further input.
*/
bool Skipping() const { return skip; }
bool Skipping() const { return skip; }
protected:
/**
* Constructor. Only derived classes are meant to be instantiated.
* @param arg_tag the tag definining the analyzer's type.
@ -163,16 +155,15 @@ protected:
Analyzer(RecordValPtr arg_args, File* arg_file);
private:
ID id; /**< Unique instance ID. */
file_analysis::Tag tag; /**< The particular type of the analyzer instance. */
RecordValPtr args; /**< \c AnalyzerArgs val gives tunable analyzer params. */
File* file; /**< The file to which the analyzer is attached. */
ID id; /**< Unique instance ID. */
file_analysis::Tag tag; /**< The particular type of the analyzer instance. */
RecordValPtr args; /**< \c AnalyzerArgs val gives tunable analyzer params. */
File* file; /**< The file to which the analyzer is attached. */
bool got_stream_delivery;
bool skip;
static ID id_counter;
};
};
} // namespace file_analysis
} // namespace zeek
} // namespace file_analysis
} // namespace zeek

View file

@ -1,15 +1,16 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/file_analysis/AnalyzerSet.h"
#include "zeek/file_analysis/File.h"
#include "zeek/file_analysis/Analyzer.h"
#include "zeek/file_analysis/Manager.h"
#include "zeek/CompHash.h"
#include "zeek/Val.h"
#include "zeek/file_analysis/Analyzer.h"
#include "zeek/file_analysis/File.h"
#include "zeek/file_analysis/Manager.h"
#include "zeek/file_analysis/file_analysis.bif.h"
namespace zeek::file_analysis::detail {
namespace zeek::file_analysis::detail
{
static void analyzer_del_func(void* v)
{
@ -41,8 +42,7 @@ AnalyzerSet::~AnalyzerSet()
delete analyzer_hash;
}
Analyzer* AnalyzerSet::Find(const file_analysis::Tag& tag,
RecordValPtr args)
Analyzer* AnalyzerSet::Find(const file_analysis::Tag& tag, RecordValPtr args)
{
auto key = GetKey(tag, std::move(args));
Analyzer* rval = analyzer_map.Lookup(key.get());
@ -56,8 +56,7 @@ bool AnalyzerSet::Add(const file_analysis::Tag& tag, RecordValPtr args)
if ( analyzer_map.Lookup(key.get()) )
{
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Instantiate analyzer %s skipped: already exists",
file->GetID().c_str(),
file_mgr->GetComponentName(tag).c_str());
file->GetID().c_str(), file_mgr->GetComponentName(tag).c_str());
return true;
}
@ -72,8 +71,7 @@ bool AnalyzerSet::Add(const file_analysis::Tag& tag, RecordValPtr args)
return true;
}
Analyzer* AnalyzerSet::QueueAdd(const file_analysis::Tag& tag,
RecordValPtr args)
Analyzer* AnalyzerSet::QueueAdd(const file_analysis::Tag& tag, RecordValPtr args)
{
auto key = GetKey(tag, args);
file_analysis::Analyzer* a = InstantiateAnalyzer(tag, std::move(args));
@ -91,8 +89,7 @@ bool AnalyzerSet::AddMod::Perform(AnalyzerSet* set)
if ( set->analyzer_map.Lookup(key.get()) )
{
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Add analyzer %s skipped: already exists",
a->GetFile()->GetID().c_str(),
file_mgr->GetComponentName(a->Tag()).c_str());
a->GetFile()->GetID().c_str(), file_mgr->GetComponentName(a->Tag()).c_str());
Abort();
return true;
@ -108,26 +105,23 @@ void AnalyzerSet::AddMod::Abort()
delete a;
}
bool AnalyzerSet::Remove(const file_analysis::Tag& tag,
RecordValPtr args)
bool AnalyzerSet::Remove(const file_analysis::Tag& tag, RecordValPtr args)
{
return Remove(tag, GetKey(tag, std::move(args)));
}
bool AnalyzerSet::Remove(const file_analysis::Tag& tag,
std::unique_ptr<zeek::detail::HashKey> key)
bool AnalyzerSet::Remove(const file_analysis::Tag& tag, std::unique_ptr<zeek::detail::HashKey> key)
{
auto a = (file_analysis::Analyzer*) analyzer_map.Remove(key.get());
auto a = (file_analysis::Analyzer*)analyzer_map.Remove(key.get());
if ( ! a )
{
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Skip remove analyzer %s",
file->GetID().c_str(), file_mgr->GetComponentName(tag).c_str());
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Skip remove analyzer %s", file->GetID().c_str(),
file_mgr->GetComponentName(tag).c_str());
return false;
}
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Remove analyzer %s",
file->GetID().c_str(),
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Remove analyzer %s", file->GetID().c_str(),
file_mgr->GetComponentName(tag).c_str());
a->Done();
@ -140,8 +134,7 @@ bool AnalyzerSet::Remove(const file_analysis::Tag& tag,
return true;
}
bool AnalyzerSet::QueueRemove(const file_analysis::Tag& tag,
RecordValPtr args)
bool AnalyzerSet::QueueRemove(const file_analysis::Tag& tag, RecordValPtr args)
{
auto key = GetKey(tag, std::move(args));
auto rval = analyzer_map.Lookup(key.get());
@ -168,10 +161,9 @@ std::unique_ptr<zeek::detail::HashKey> AnalyzerSet::GetKey(const file_analysis::
return key;
}
file_analysis::Analyzer* AnalyzerSet::InstantiateAnalyzer(const Tag& tag,
RecordValPtr args) const
file_analysis::Analyzer* AnalyzerSet::InstantiateAnalyzer(const Tag& tag, RecordValPtr args) const
{
auto a = file_mgr->InstantiateAnalyzer(tag, std::move(args), file);
auto a = file_mgr->InstantiateAnalyzer(tag, std::move(args), file);
if ( ! a )
{
@ -180,8 +172,7 @@ file_analysis::Analyzer* AnalyzerSet::InstantiateAnalyzer(const Tag& tag,
if ( c && ! c->Enabled() )
return nullptr;
reporter->Error("[%s] Failed file analyzer %s instantiation",
file->GetID().c_str(),
reporter->Error("[%s] Failed file analyzer %s instantiation", file->GetID().c_str(),
file_mgr->GetComponentName(tag).c_str());
return nullptr;
}
@ -189,11 +180,10 @@ file_analysis::Analyzer* AnalyzerSet::InstantiateAnalyzer(const Tag& tag,
return a;
}
void AnalyzerSet::Insert(file_analysis::Analyzer* a,
std::unique_ptr<zeek::detail::HashKey> key)
void AnalyzerSet::Insert(file_analysis::Analyzer* a, std::unique_ptr<zeek::detail::HashKey> key)
{
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Add analyzer %s",
file->GetID().c_str(), file_mgr->GetComponentName(a->Tag()).c_str());
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Add analyzer %s", file->GetID().c_str(),
file_mgr->GetComponentName(a->Tag()).c_str());
analyzer_map.Insert(key.get(), a);
a->Init();
@ -204,8 +194,7 @@ void AnalyzerSet::DrainModifications()
if ( mod_queue.empty() )
return;
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Start analyzer mod queue flush",
file->GetID().c_str());
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Start analyzer mod queue flush", file->GetID().c_str());
do
{
Modification* mod = mod_queue.front();
@ -213,8 +202,7 @@ void AnalyzerSet::DrainModifications()
delete mod;
mod_queue.pop();
} while ( ! mod_queue.empty() );
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] End flushing analyzer mod queue.",
file->GetID().c_str());
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] End flushing analyzer mod queue.", file->GetID().c_str());
}
} // namespace zeek::file_analysis::detail
} // namespace zeek::file_analysis::detail

View file

@ -2,25 +2,31 @@
#pragma once
#include <queue>
#include <memory>
#include <queue>
#include "zeek/Dict.h"
#include "zeek/file_analysis/Tag.h"
namespace zeek {
namespace zeek
{
class RecordVal;
using RecordValPtr = IntrusivePtr<RecordVal>;
namespace detail { class CompositeHash; }
namespace detail
{
class CompositeHash;
}
namespace file_analysis {
namespace file_analysis
{
class Analyzer;
class File;
namespace detail {
namespace detail
{
/**
* A set of file analysis analyzers indexed by an \c AnalyzerArgs (script-layer
@ -28,9 +34,9 @@ namespace detail {
* modifications can happen at well-defined times (e.g. to make sure a loop
* iterator isn't invalidated).
*/
class AnalyzerSet {
class AnalyzerSet
{
public:
/**
* Constructor. Nothing special.
* @param arg_file the file to which all analyzers in the set are attached.
@ -66,8 +72,7 @@ public:
* @return if successful, a pointer to a newly instantiated analyzer else
* a null pointer. The caller does *not* take ownership of the memory.
*/
file_analysis::Analyzer* QueueAdd(const file_analysis::Tag& tag,
RecordValPtr args);
file_analysis::Analyzer* QueueAdd(const file_analysis::Tag& tag, RecordValPtr args);
/**
* Remove an analyzer from #file immediately.
@ -95,8 +100,8 @@ public:
* @see Dictionary#InitForIteration
* @return an iterator that may be used to loop over analyzers in the set.
*/
[[deprecated("Remove in v5.1. Use standard-library compatible iteration.")]]
IterCookie* InitForIteration() const
[[deprecated("Remove in v5.1. Use standard-library compatible iteration.")]] IterCookie*
InitForIteration() const
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
@ -111,8 +116,9 @@ public:
* @return the next analyzer in the set or a null pointer if there is no
* more left (in that case the cookie is also deleted).
*/
[[deprecated("Remove in v5.1. Use standard-library compatible iteration.")]]
file_analysis::Analyzer* NextEntry(IterCookie* c)
[[deprecated(
"Remove in v5.1. Use standard-library compatible iteration.")]] file_analysis::Analyzer*
NextEntry(IterCookie* c)
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
@ -134,7 +140,6 @@ public:
const_iterator cend() { return analyzer_map.cend(); }
protected:
/**
* Get a hash key which represents an analyzer instance.
* @param tag the file analyzer tag.
@ -169,17 +174,17 @@ protected:
bool Remove(const file_analysis::Tag& tag, std::unique_ptr<zeek::detail::HashKey> key);
private:
File* file; /**< File which owns the set */
zeek::detail::CompositeHash* analyzer_hash; /**< AnalyzerArgs hashes. */
File* file; /**< File which owns the set */
zeek::detail::CompositeHash* analyzer_hash; /**< AnalyzerArgs hashes. */
PDict<file_analysis::Analyzer> analyzer_map; /**< Indexed by AnalyzerArgs. */
/**
* Abstract base class for analyzer set modifications.
*/
class Modification {
class Modification
{
public:
virtual ~Modification() {}
virtual ~Modification() { }
/**
* Perform the modification on an analyzer set.
@ -192,12 +197,13 @@ private:
* Don't perform the modification on the analyzer set and clean up.
*/
virtual void Abort() = 0;
};
};
/**
* Represents a request to add an analyzer to an analyzer set.
*/
class AddMod final : public Modification {
class AddMod final : public Modification
{
public:
/**
* Construct request which can add an analyzer to an analyzer set.
@ -205,20 +211,23 @@ private:
* @param arg_key hash key representing the analyzer's \c AnalyzerArgs.
*/
AddMod(file_analysis::Analyzer* arg_a, std::unique_ptr<zeek::detail::HashKey> arg_key)
: Modification(), a(arg_a), key(std::move(arg_key)) {}
~AddMod() override {}
: Modification(), a(arg_a), key(std::move(arg_key))
{
}
~AddMod() override { }
bool Perform(AnalyzerSet* set) override;
void Abort() override;
protected:
file_analysis::Analyzer* a;
std::unique_ptr<zeek::detail::HashKey> key;
};
};
/**
* Represents a request to remove an analyzer from an analyzer set.
*/
class RemoveMod final : public Modification {
class RemoveMod final : public Modification
{
public:
/**
* Construct request which can remove an analyzer from an analyzer set.
@ -226,20 +235,22 @@ private:
* @param arg_key hash key representing the analyzer's \c AnalyzerArgs.
*/
RemoveMod(const file_analysis::Tag& arg_tag, std::unique_ptr<zeek::detail::HashKey> arg_key)
: Modification(), tag(arg_tag), key(std::move(arg_key)) {}
~RemoveMod() override {}
: Modification(), tag(arg_tag), key(std::move(arg_key))
{
}
~RemoveMod() override { }
bool Perform(AnalyzerSet* set) override;
void Abort() override {}
void Abort() override { }
protected:
file_analysis::Tag tag;
std::unique_ptr<zeek::detail::HashKey> key;
};
};
using ModQueue = std::queue<Modification*>;
ModQueue mod_queue; /**< A queue of analyzer additions/removals requests. */
};
ModQueue mod_queue; /**< A queue of analyzer additions/removals requests. */
};
} // namespace detail
} // namespace file_analysis
} // namespace zeek
} // namespace detail
} // namespace file_analysis
} // namespace zeek

View file

@ -3,12 +3,14 @@
#include "zeek/file_analysis/Component.h"
#include "zeek/Desc.h"
#include "zeek/util.h"
#include "zeek/file_analysis/Manager.h"
#include "zeek/util.h"
namespace zeek::file_analysis {
namespace zeek::file_analysis
{
Component::Component(const std::string& name, factory_function arg_factory, Tag::subtype_t subtype, bool arg_enabled)
Component::Component(const std::string& name, factory_function arg_factory, Tag::subtype_t subtype,
bool arg_enabled)
: plugin::Component(plugin::component::FILE_ANALYZER, name),
plugin::TaggedComponent<file_analysis::Tag>(subtype)
{
@ -22,9 +24,7 @@ void Component::Initialize()
file_mgr->RegisterComponent(this, "ANALYZER_");
}
Component::~Component()
{
}
Component::~Component() { }
void Component::DoDescribe(ODesc* d) const
{
@ -38,4 +38,4 @@ void Component::DoDescribe(ODesc* d) const
d->Add(enabled ? "enabled" : "disabled");
}
} // namespace zeek::file_analysis
} // namespace zeek::file_analysis

View file

@ -2,18 +2,19 @@
#pragma once
#include "zeek/zeek-config.h"
#include "zeek/file_analysis/Tag.h"
#include "zeek/plugin/Component.h"
#include "zeek/plugin/TaggedComponent.h"
#include "zeek/zeek-config.h"
namespace zeek {
namespace zeek
{
class RecordVal;
using RecordValPtr = zeek::IntrusivePtr<RecordVal>;
namespace file_analysis {
namespace file_analysis
{
class File;
class Analyzer;
@ -25,8 +26,8 @@ class Manager;
* A plugin can provide a specific file analyzer by registering this
* analyzer component, describing the analyzer.
*/
class Component : public plugin::Component,
public plugin::TaggedComponent<file_analysis::Tag> {
class Component : public plugin::Component, public plugin::TaggedComponent<file_analysis::Tag>
{
public:
using factory_function = Analyzer* (*)(RecordValPtr args, File* file);
@ -53,7 +54,8 @@ public:
* hence won't be used. It can still be enabled later via the
* manager, including from script-land.
*/
Component(const std::string& name, factory_function factory, Tag::subtype_t subtype = 0, bool enabled = true);
Component(const std::string& name, factory_function factory, Tag::subtype_t subtype = 0,
bool enabled = true);
/**
* Destructor.
@ -70,14 +72,13 @@ public:
/**
* Returns the analyzer's factory function.
*/
factory_function FactoryFunction() const
{ return factory_func; }
factory_function FactoryFunction() const { return factory_func; }
/**
* Returns true if the analyzer is currently enabled and hence
* available for use.
*/
bool Enabled() const { return enabled; }
bool Enabled() const { return enabled; }
/**
* Enables or disables this analyzer.
@ -85,20 +86,20 @@ public:
* @param arg_enabled True to enabled, false to disable.
*
*/
void SetEnabled(bool arg_enabled) { enabled = arg_enabled; }
void SetEnabled(bool arg_enabled) { enabled = arg_enabled; }
protected:
/**
* Overriden from plugin::Component.
*/
* Overriden from plugin::Component.
*/
void DoDescribe(ODesc* d) const override;
private:
friend class Manager;
factory_function factory_func; // The analyzer's factory callback.
bool enabled; // True if the analyzer is enabled.
};
factory_function factory_func; // The analyzer's factory callback.
bool enabled; // True if the analyzer is enabled.
};
} // namespace file_analysis
} // namespace zeek
} // namespace file_analysis
} // namespace zeek

View file

@ -4,29 +4,27 @@
#include <utility>
#include "zeek/file_analysis/FileReassembler.h"
#include "zeek/file_analysis/FileTimer.h"
#include "zeek/file_analysis/Analyzer.h"
#include "zeek/file_analysis/Manager.h"
#include "zeek/Reporter.h"
#include "zeek/Val.h"
#include "zeek/Type.h"
#include "zeek/Event.h"
#include "zeek/Reporter.h"
#include "zeek/RuleMatcher.h"
#include "zeek/Type.h"
#include "zeek/Val.h"
#include "zeek/analyzer/Analyzer.h"
#include "zeek/analyzer/Manager.h"
#include "zeek/file_analysis/Analyzer.h"
#include "zeek/file_analysis/FileReassembler.h"
#include "zeek/file_analysis/FileTimer.h"
#include "zeek/file_analysis/Manager.h"
#include "zeek/file_analysis/analyzer/extract/Extract.h"
namespace zeek::file_analysis {
namespace zeek::file_analysis
{
static TableValPtr empty_connection_table()
{
auto tbl_index = make_intrusive<TypeList>(id::conn_id);
tbl_index->Append(id::conn_id);
auto tbl_type = make_intrusive<TableType>(std::move(tbl_index),
id::connection);
auto tbl_type = make_intrusive<TableType>(std::move(tbl_index), id::connection);
return make_intrusive<TableVal>(std::move(tbl_type));
}
@ -83,9 +81,8 @@ void File::StaticInit()
File::File(const std::string& file_id, const std::string& source_name, Connection* conn,
analyzer::Tag tag, bool is_orig)
: id(file_id), val(nullptr), file_reassembler(nullptr), stream_offset(0),
reassembly_max_buffer(0), did_metadata_inference(false),
reassembly_enabled(false), postpone_timeout(false), done(false),
analyzers(this)
reassembly_max_buffer(0), did_metadata_inference(false), reassembly_enabled(false),
postpone_timeout(false), done(false), analyzers(this)
{
StaticInit();
@ -151,10 +148,10 @@ void File::RaiseFileOverNewConnection(Connection* conn, bool is_orig)
if ( conn && FileEventAvailable(file_over_new_connection) )
{
FileEvent(file_over_new_connection, {
val,
conn->GetVal(),
val_mgr->Bool(is_orig),
});
val,
conn->GetVal(),
val_mgr->Bool(is_orig),
});
}
}
@ -175,8 +172,7 @@ int File::Idx(const std::string& field, const RecordType* type)
int rval = type->FieldOffset(field.c_str());
if ( rval < 0 )
reporter->InternalError("Unknown %s field: %s", type->GetName().c_str(),
field.c_str());
reporter->InternalError("Unknown %s field: %s", type->GetName().c_str(), field.c_str());
return rval;
}
@ -205,8 +201,7 @@ void File::SetTimeoutInterval(double interval)
bool File::SetExtractionLimit(RecordValPtr args, uint64_t bytes)
{
Analyzer* a = analyzers.Find(file_mgr->GetComponentTag("EXTRACT"),
std::move(args));
Analyzer* a = analyzers.Find(file_mgr->GetComponentTag("EXTRACT"), std::move(args));
if ( ! a )
return false;
@ -247,13 +242,14 @@ bool File::IsComplete() const
void File::ScheduleInactivityTimer() const
{
zeek::detail::timer_mgr->Add(new detail::FileTimer(run_state::network_time, id, GetTimeoutInterval()));
zeek::detail::timer_mgr->Add(
new detail::FileTimer(run_state::network_time, id, GetTimeoutInterval()));
}
bool File::AddAnalyzer(file_analysis::Tag tag, RecordValPtr args)
{
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Queuing addition of %s analyzer",
id.c_str(), file_mgr->GetComponentName(tag).c_str());
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Queuing addition of %s analyzer", id.c_str(),
file_mgr->GetComponentName(tag).c_str());
if ( done )
return false;
@ -263,8 +259,8 @@ bool File::AddAnalyzer(file_analysis::Tag tag, RecordValPtr args)
bool File::RemoveAnalyzer(file_analysis::Tag tag, RecordValPtr args)
{
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Queuing remove of %s analyzer",
id.c_str(), file_mgr->GetComponentName(tag).c_str());
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Queuing remove of %s analyzer", id.c_str(),
file_mgr->GetComponentName(tag).c_str());
return done ? false : analyzers.QueueRemove(tag, std::move(args));
}
@ -334,10 +330,8 @@ void File::InferMetadata()
if ( ! matches.empty() )
{
meta->Assign(meta_mime_type_idx,
*(matches.begin()->second.begin()));
meta->Assign(meta_mime_types_idx,
file_analysis::GenMIMEMatchesVal(matches));
meta->Assign(meta_mime_type_idx, *(matches.begin()->second.begin()));
meta->Assign(meta_mime_types_idx, file_analysis::GenMIMEMatchesVal(matches));
}
FileEvent(file_sniff, {val, std::move(meta)});
@ -377,21 +371,20 @@ void File::DeliverStream(const u_char* data, uint64_t len)
LookupFieldDefaultCount(missing_bytes_idx) == 0 )
InferMetadata();
DBG_LOG(DBG_FILE_ANALYSIS,
"[%s] %" PRIu64 " stream bytes in at offset %" PRIu64 "; %s [%s%s]",
id.c_str(), len, stream_offset,
IsComplete() ? "complete" : "incomplete",
util::fmt_bytes((const char*) data, std::min((uint64_t)40, len)),
len > 40 ? "..." : "");
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] %" PRIu64 " stream bytes in at offset %" PRIu64 "; %s [%s%s]",
id.c_str(), len, stream_offset, IsComplete() ? "complete" : "incomplete",
util::fmt_bytes((const char*)data, std::min((uint64_t)40, len)), len > 40 ? "..." : "");
for ( const auto& entry : analyzers )
{
auto* a = entry.GetValue<file_analysis::Analyzer*>();
DBG_LOG(DBG_FILE_ANALYSIS, "stream delivery to analyzer %s", file_mgr->GetComponentName(a->Tag()).c_str());
DBG_LOG(DBG_FILE_ANALYSIS, "stream delivery to analyzer %s",
file_mgr->GetComponentName(a->Tag()).c_str());
if ( ! a->GotStreamDelivery() )
{
DBG_LOG(DBG_FILE_ANALYSIS, "skipping stream delivery to analyzer %s", file_mgr->GetComponentName(a->Tag()).c_str());
DBG_LOG(DBG_FILE_ANALYSIS, "skipping stream delivery to analyzer %s",
file_mgr->GetComponentName(a->Tag()).c_str());
int num_bof_chunks_behind = bof_buffer.chunks.size();
if ( ! bof_was_full )
@ -407,7 +400,7 @@ void File::DeliverStream(const u_char* data, uint64_t len)
if ( ! a->Skipping() )
{
if ( ! a->DeliverStream(bof_buffer.chunks[i]->Bytes(),
bof_buffer.chunks[i]->Len()) )
bof_buffer.chunks[i]->Len()) )
{
a->SetSkip(true);
analyzers.QueueRemove(a->Tag(), a->GetArgs());
@ -441,8 +434,7 @@ void File::DeliverChunk(const u_char* data, uint64_t len, uint64_t offset)
// Potentially handle reassembly and deliver to the stream analyzers.
if ( file_reassembler )
{
if ( reassembly_max_buffer > 0 &&
reassembly_max_buffer < file_reassembler->TotalSize() )
if ( reassembly_max_buffer > 0 && reassembly_max_buffer < file_reassembler->TotalSize() )
{
uint64_t current_offset = stream_offset;
uint64_t gap_bytes = file_reassembler->Flush();
@ -450,11 +442,8 @@ void File::DeliverChunk(const u_char* data, uint64_t len, uint64_t offset)
if ( FileEventAvailable(file_reassembly_overflow) )
{
FileEvent(file_reassembly_overflow, {
val,
val_mgr->Count(current_offset),
val_mgr->Count(gap_bytes)
});
FileEvent(file_reassembly_overflow,
{val, val_mgr->Count(current_offset), val_mgr->Count(gap_bytes)});
}
}
@ -480,18 +469,16 @@ void File::DeliverChunk(const u_char* data, uint64_t len, uint64_t offset)
IncrementByteCount(len, overflow_bytes_idx);
}
DBG_LOG(DBG_FILE_ANALYSIS,
"[%s] %" PRIu64 " chunk bytes in at offset %" PRIu64 "; %s [%s%s]",
id.c_str(), len, offset,
IsComplete() ? "complete" : "incomplete",
util::fmt_bytes((const char*) data, std::min((uint64_t)40, len)),
len > 40 ? "..." : "");
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] %" PRIu64 " chunk bytes in at offset %" PRIu64 "; %s [%s%s]",
id.c_str(), len, offset, IsComplete() ? "complete" : "incomplete",
util::fmt_bytes((const char*)data, std::min((uint64_t)40, len)), len > 40 ? "..." : "");
for ( const auto& entry : analyzers )
{
auto* a = entry.GetValue<file_analysis::Analyzer*>();
DBG_LOG(DBG_FILE_ANALYSIS, "chunk delivery to analyzer %s", file_mgr->GetComponentName(a->Tag()).c_str());
DBG_LOG(DBG_FILE_ANALYSIS, "chunk delivery to analyzer %s",
file_mgr->GetComponentName(a->Tag()).c_str());
if ( ! a->Skipping() )
{
if ( ! a->DeliverChunk(data, len, offset) )
@ -544,7 +531,7 @@ void File::EndOfFile()
{
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] File over but bof_buffer not full.", id.c_str());
bof_buffer.full = true;
DeliverStream((const u_char*) "", 0);
DeliverStream((const u_char*)"", 0);
}
analyzers.DrainModifications();
@ -565,8 +552,8 @@ void File::EndOfFile()
void File::Gap(uint64_t offset, uint64_t len)
{
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Gap of size %" PRIu64 " at offset %" PRIu64,
id.c_str(), len, offset);
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Gap of size %" PRIu64 " at offset %" PRIu64, id.c_str(), len,
offset);
if ( file_reassembler && ! file_reassembler->IsCurrentlyFlushing() )
{
@ -577,9 +564,12 @@ void File::Gap(uint64_t offset, uint64_t len)
if ( ! bof_buffer.full )
{
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] File gap before bof_buffer filled, continued without attempting to fill bof_buffer.", id.c_str());
DBG_LOG(DBG_FILE_ANALYSIS,
"[%s] File gap before bof_buffer filled, continued without attempting to fill "
"bof_buffer.",
id.c_str());
bof_buffer.full = true;
DeliverStream((const u_char*) "", 0);
DeliverStream((const u_char*)"", 0);
}
for ( const auto& entry : analyzers )
@ -616,9 +606,8 @@ void File::FileEvent(EventHandlerPtr h, Args args)
{
event_mgr.Enqueue(h, std::move(args));
if ( h == file_new || h == file_over_new_connection ||
h == file_sniff ||
h == file_timeout || h == file_extraction_limit )
if ( h == file_new || h == file_over_new_connection || h == file_sniff || h == file_timeout ||
h == file_extraction_limit )
{
// immediate feedback is required for these events.
event_mgr.Drain();
@ -626,10 +615,9 @@ void File::FileEvent(EventHandlerPtr h, Args args)
}
}
bool File::PermitWeird(const char* name, uint64_t threshold, uint64_t rate,
double duration)
bool File::PermitWeird(const char* name, uint64_t threshold, uint64_t rate, double duration)
{
return zeek::detail::PermitWeird(weird_state, name, threshold, rate, duration);
}
} // namespace zeek::file_analysis
} // namespace zeek::file_analysis

View file

@ -6,14 +6,15 @@
#include <string>
#include <utility>
#include "zeek/WeirdState.h"
#include "zeek/ZeekArgs.h"
#include "zeek/ZeekList.h" // for ValPList
#include "zeek/ZeekString.h"
#include "zeek/analyzer/Tag.h"
#include "zeek/file_analysis/AnalyzerSet.h"
#include "zeek/ZeekString.h"
#include "zeek/ZeekList.h" // for ValPList
#include "zeek/ZeekArgs.h"
#include "zeek/WeirdState.h"
namespace zeek {
namespace zeek
{
class Connection;
class EventHandlerPtr;
@ -22,7 +23,8 @@ class RecordType;
using RecordValPtr = IntrusivePtr<RecordVal>;
using RecordTypePtr = IntrusivePtr<RecordType>;
namespace file_analysis {
namespace file_analysis
{
class FileReassembler;
class Tag;
@ -30,9 +32,9 @@ class Tag;
/**
* Wrapper class around \c fa_file record values from script layer.
*/
class File {
class File
{
public:
/**
* Destructor. Nothing fancy, releases a reference to the wrapped
* \c fa_file value.
@ -42,8 +44,7 @@ public:
/**
* @return the wrapped \c fa_file record value, #val.
*/
const RecordValPtr& ToVal() const
{ return val; }
const RecordValPtr& ToVal() const { return val; }
/**
* @return the value of the "source" field from #val record or an empty
@ -205,8 +206,7 @@ public:
* Whether to permit a weird to carry on through the full reporter/weird
* framework.
*/
bool PermitWeird(const char* name, uint64_t threshold, uint64_t rate,
double duration);
bool PermitWeird(const char* name, uint64_t threshold, uint64_t rate, double duration);
protected:
friend class Manager;
@ -313,7 +313,9 @@ protected:
*/
static int Idx(const std::string& field_name, const RecordType* type);
static int Idx(const std::string& field_name, const RecordTypePtr& type)
{ return Idx(field_name, type.get()); }
{
return Idx(field_name, type.get());
}
/**
* Initializes static member.
@ -321,27 +323,32 @@ protected:
static void StaticInit();
protected:
std::string id; /**< A pretty hash that likely identifies file */
RecordValPtr val; /**< \c fa_file from script layer. */
std::string id; /**< A pretty hash that likely identifies file */
RecordValPtr val; /**< \c fa_file from script layer. */
FileReassembler* file_reassembler; /**< A reassembler for the file if it's needed. */
uint64_t stream_offset; /**< The offset of the file which has been forwarded. */
uint64_t reassembly_max_buffer; /**< Maximum allowed buffer for reassembly. */
bool did_metadata_inference; /**< Whether the metadata inference has already been attempted. */
bool reassembly_enabled; /**< Whether file stream reassembly is needed. */
bool postpone_timeout; /**< Whether postponing timeout is requested. */
bool done; /**< If this object is about to be deleted. */
detail::AnalyzerSet analyzers; /**< A set of attached file analyzers. */
std::list<Analyzer *> done_analyzers; /**< Analyzers we're done with, remembered here until they can be safely deleted. */
uint64_t stream_offset; /**< The offset of the file which has been forwarded. */
uint64_t reassembly_max_buffer; /**< Maximum allowed buffer for reassembly. */
bool did_metadata_inference; /**< Whether the metadata inference has already been attempted. */
bool reassembly_enabled; /**< Whether file stream reassembly is needed. */
bool postpone_timeout; /**< Whether postponing timeout is requested. */
bool done; /**< If this object is about to be deleted. */
detail::AnalyzerSet analyzers; /**< A set of attached file analyzers. */
std::list<Analyzer*> done_analyzers; /**< Analyzers we're done with, remembered here until they
can be safely deleted. */
struct BOF_Buffer {
BOF_Buffer() : full(false), size(0) {}
struct BOF_Buffer
{
BOF_Buffer() : full(false), size(0) { }
~BOF_Buffer()
{ for ( size_t i = 0; i < chunks.size(); ++i ) delete chunks[i]; }
{
for ( size_t i = 0; i < chunks.size(); ++i )
delete chunks[i];
}
bool full;
uint64_t size;
String::CVec chunks;
} bof_buffer; /**< Beginning of file buffer. */
} bof_buffer; /**< Beginning of file buffer. */
zeek::detail::WeirdStateMap weird_state;
@ -364,7 +371,7 @@ protected:
static int meta_mime_type_idx;
static int meta_mime_types_idx;
};
};
} // namespace file_analysis
} // namespace zeek
} // namespace file_analysis
} // namespace zeek

View file

@ -1,13 +1,15 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/file_analysis/FileReassembler.h"
#include "zeek/file_analysis/File.h"
namespace zeek::file_analysis {
namespace zeek::file_analysis
{
class File;
FileReassembler::FileReassembler(File *f, uint64_t starting_offset)
FileReassembler::FileReassembler(File* f, uint64_t starting_offset)
: Reassembler(starting_offset, REASSEM_FILE), the_file(f), flushing(false)
{
}
@ -45,8 +47,7 @@ void FileReassembler::BlockInserted(DataBlockMap::const_iterator it)
{
const auto& start_block = it->second;
if ( start_block.seq > last_reassem_seq ||
start_block.upper <= last_reassem_seq )
if ( start_block.seq > last_reassem_seq || start_block.upper <= last_reassem_seq )
return;
while ( it != block_list.End() )
@ -111,4 +112,4 @@ void FileReassembler::Overlap(const u_char* b1, const u_char* b2, uint64_t n)
{
// Not doing anything here yet.
}
} // end file_analysis
} // end file_analysis

View file

@ -4,18 +4,20 @@
#include "zeek/Reassem.h"
namespace zeek {
namespace zeek
{
class Connection;
class File;
namespace file_analysis {
namespace file_analysis
{
class File;
class FileReassembler final : public Reassembler {
class FileReassembler final : public Reassembler
{
public:
FileReassembler(File* f, uint64_t starting_offset);
~FileReassembler() override = default;
@ -46,18 +48,16 @@ public:
* @return whether the reassembler is currently is the process of flushing
* out the contents of its buffer.
*/
bool IsCurrentlyFlushing() const
{ return flushing; }
bool IsCurrentlyFlushing() const { return flushing; }
protected:
void Undelivered(uint64_t up_to_seq) override;
void BlockInserted(DataBlockMap::const_iterator it) override;
void Overlap(const u_char* b1, const u_char* b2, uint64_t n) override;
File* the_file = nullptr;
bool flushing = false;
};
};
} // namespace file_analysis
} // namespace zeek
} // namespace file_analysis
} // namespace zeek

View file

@ -1,16 +1,17 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/file_analysis/FileTimer.h"
#include "zeek/file_analysis/File.h"
#include "zeek/file_analysis/Manager.h"
namespace zeek::file_analysis::detail {
namespace zeek::file_analysis::detail
{
FileTimer::FileTimer(double t, const std::string& id, double interval)
: zeek::detail::Timer(t + interval, zeek::detail::TIMER_FILE_ANALYSIS_INACTIVITY), file_id(id)
{
DBG_LOG(DBG_FILE_ANALYSIS, "New %f second timeout timer for %s",
interval, file_id.c_str());
DBG_LOG(DBG_FILE_ANALYSIS, "New %f second timeout timer for %s", interval, file_id.c_str());
}
void FileTimer::Dispatch(double t, bool is_expire)
@ -23,8 +24,10 @@ void FileTimer::Dispatch(double t, bool is_expire)
double last_active = file->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, "
"inactive for %f", file_id.c_str(), last_active, inactive_time);
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 )
{
@ -40,4 +43,4 @@ void FileTimer::Dispatch(double t, bool is_expire)
file->ScheduleInactivityTimer();
}
} // namespace zeek::file_analysis::detail
} // namespace zeek::file_analysis::detail

View file

@ -3,16 +3,18 @@
#pragma once
#include <string>
#include "zeek/Timer.h"
namespace zeek::file_analysis::detail {
namespace zeek::file_analysis::detail
{
/**
* Timer to periodically check if file analysis for a given file is inactive.
*/
class FileTimer final : public zeek::detail::Timer {
class FileTimer final : public zeek::detail::Timer
{
public:
/**
* Constructor, nothing interesting about it.
* @param t unix time at which the timer should start ticking.
@ -31,6 +33,6 @@ public:
private:
std::string file_id;
};
};
} // namespace zeek::file_analysis::detail
} // namespace zeek::file_analysis::detail

View file

@ -4,23 +4,22 @@
#include <openssl/md5.h>
#include "zeek/file_analysis/File.h"
#include "zeek/file_analysis/Analyzer.h"
#include "zeek/Event.h"
#include "zeek/UID.h"
#include "zeek/digest.h"
#include "zeek/plugin/Manager.h"
#include "zeek/analyzer/Manager.h"
#include "zeek/digest.h"
#include "zeek/file_analysis/Analyzer.h"
#include "zeek/file_analysis/File.h"
#include "zeek/file_analysis/file_analysis.bif.h"
#include "zeek/plugin/Manager.h"
using namespace std;
namespace zeek::file_analysis {
namespace zeek::file_analysis
{
Manager::Manager()
: plugin::ComponentManager<file_analysis::Tag,
file_analysis::Component>("Files", "Tag"),
: plugin::ComponentManager<file_analysis::Tag, file_analysis::Component>("Files", "Tag"),
current_file_id(), magic_state(), cumulative_files(0), max_files(0)
{
}
@ -38,13 +37,9 @@ Manager::~Manager()
delete magic_state;
}
void Manager::InitPreScript()
{
}
void Manager::InitPreScript() { }
void Manager::InitPostScript()
{
}
void Manager::InitPostScript() { }
void Manager::InitMagic()
{
@ -85,16 +80,16 @@ void Manager::SetHandle(const string& handle)
String tmp{handle};
auto rendered = tmp.Render();
DBG_LOG(DBG_FILE_ANALYSIS, "Set current handle to %s", rendered);
delete [] rendered;
delete[] rendered;
}
#endif
current_file_id = HashHandle(handle);
}
string Manager::DataIn(const u_char* data, uint64_t len, uint64_t offset,
const analyzer::Tag& tag, Connection* conn, bool is_orig,
const string& precomputed_id, const string& mime_type)
string Manager::DataIn(const u_char* data, uint64_t len, uint64_t offset, const analyzer::Tag& tag,
Connection* conn, bool is_orig, const string& precomputed_id,
const string& mime_type)
{
string id = precomputed_id.empty() ? GetFileID(tag, conn, is_orig) : precomputed_id;
File* file = GetFile(id, conn, tag, is_orig);
@ -122,9 +117,8 @@ string Manager::DataIn(const u_char* data, uint64_t len, uint64_t offset,
return id;
}
string Manager::DataIn(const u_char* data, uint64_t len, const analyzer::Tag& tag,
Connection* conn, bool is_orig, const string& precomputed_id,
const string& mime_type)
string Manager::DataIn(const u_char* data, uint64_t len, const analyzer::Tag& tag, Connection* conn,
bool is_orig, const string& precomputed_id, const string& mime_type)
{
string id = precomputed_id.empty() ? GetFileID(tag, conn, is_orig) : precomputed_id;
// Sequential data input shouldn't be going over multiple conns, so don't
@ -148,11 +142,10 @@ string Manager::DataIn(const u_char* data, uint64_t len, const analyzer::Tag& ta
return id;
}
void Manager::DataIn(const u_char* data, uint64_t len, const string& file_id,
const string& source, const string& mime_type)
void Manager::DataIn(const u_char* data, uint64_t len, const string& file_id, const string& source,
const string& mime_type)
{
File* file = GetFile(file_id, nullptr, analyzer::Tag::Error, false, false,
source.c_str());
File* file = GetFile(file_id, nullptr, analyzer::Tag::Error, false, false, source.c_str());
if ( ! file )
return;
@ -166,12 +159,10 @@ void Manager::DataIn(const u_char* data, uint64_t len, const string& file_id,
RemoveFile(file->GetID());
}
void Manager::DataIn(const u_char* data, uint64_t len, uint64_t offset,
const string& file_id, const string& source,
const string& mime_type)
void Manager::DataIn(const u_char* data, uint64_t len, uint64_t offset, const string& file_id,
const string& source, const string& mime_type)
{
File* file = GetFile(file_id, nullptr, analyzer::Tag::Error, false, false,
source.c_str());
File* file = GetFile(file_id, nullptr, analyzer::Tag::Error, false, false, source.c_str());
if ( ! file )
return;
@ -202,8 +193,8 @@ void Manager::EndOfFile(const string& file_id)
RemoveFile(file_id);
}
string Manager::Gap(uint64_t offset, uint64_t len, const analyzer::Tag& tag,
Connection* conn, bool is_orig, const string& precomputed_id)
string Manager::Gap(uint64_t offset, uint64_t len, const analyzer::Tag& tag, Connection* conn,
bool is_orig, const string& precomputed_id)
{
string id = precomputed_id.empty() ? GetFileID(tag, conn, is_orig) : precomputed_id;
File* file = GetFile(id, conn, tag, is_orig);
@ -215,8 +206,8 @@ string Manager::Gap(uint64_t offset, uint64_t len, const analyzer::Tag& tag,
return id;
}
string Manager::SetSize(uint64_t size, const analyzer::Tag& tag, Connection* conn,
bool is_orig, const string& precomputed_id)
string Manager::SetSize(uint64_t size, const analyzer::Tag& tag, Connection* conn, bool is_orig,
const string& precomputed_id)
{
string id = precomputed_id.empty() ? GetFileID(tag, conn, is_orig) : precomputed_id;
File* file = GetFile(id, conn, tag, is_orig);
@ -282,8 +273,7 @@ bool Manager::SetReassemblyBuffer(const string& file_id, uint64_t max)
return true;
}
bool Manager::SetExtractionLimit(const string& file_id,
RecordValPtr args, uint64_t n) const
bool Manager::SetExtractionLimit(const string& file_id, RecordValPtr args, uint64_t n) const
{
File* file = LookupFile(file_id);
@ -315,9 +305,8 @@ bool Manager::RemoveAnalyzer(const string& file_id, const file_analysis::Tag& ta
return file->RemoveAnalyzer(tag, std::move(args));
}
File* Manager::GetFile(const string& file_id, Connection* conn,
const analyzer::Tag& tag, bool is_orig, bool update_conn,
const char* source_name)
File* Manager::GetFile(const string& file_id, Connection* conn, const analyzer::Tag& tag,
bool is_orig, bool update_conn, const char* source_name)
{
if ( file_id.empty() )
return nullptr;
@ -329,9 +318,7 @@ File* Manager::GetFile(const string& file_id, Connection* conn,
if ( ! rval )
{
rval = new File(file_id,
source_name ? source_name
: analyzer_mgr->GetComponentName(tag),
rval = new File(file_id, source_name ? source_name : analyzer_mgr->GetComponentName(tag),
conn, tag, is_orig);
id_map[file_id] = rval;
@ -383,15 +370,13 @@ void Manager::Timeout(const string& file_id, bool is_terminating)
if ( file->postpone_timeout && ! is_terminating )
{
DBG_LOG(DBG_FILE_ANALYSIS, "Postpone file analysis timeout for %s",
file->GetID().c_str());
DBG_LOG(DBG_FILE_ANALYSIS, "Postpone file analysis timeout for %s", file->GetID().c_str());
file->UpdateLastActivityTime();
file->ScheduleInactivityTimer();
return;
}
DBG_LOG(DBG_FILE_ANALYSIS, "File analysis timeout for %s",
file->GetID().c_str());
DBG_LOG(DBG_FILE_ANALYSIS, "File analysis timeout for %s", file->GetID().c_str());
RemoveFile(file->GetID());
}
@ -466,29 +451,26 @@ bool Manager::IsDisabled(const analyzer::Tag& tag)
return yield->AsBool();
}
Analyzer* Manager::InstantiateAnalyzer(const Tag& tag,
RecordValPtr args,
File* f) const
Analyzer* Manager::InstantiateAnalyzer(const Tag& tag, RecordValPtr args, File* f) const
{
Component* c = Lookup(tag);
if ( ! c )
{
reporter->InternalWarning(
"unknown file analyzer instantiation request: %s",
tag.AsString().c_str());
reporter->InternalWarning("unknown file analyzer instantiation request: %s",
tag.AsString().c_str());
return nullptr;
}
if ( ! c->Enabled() )
{
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Skip instantiation of disabled analyzer %s",
f->id.c_str(), GetComponentName(tag).c_str());
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Skip instantiation of disabled analyzer %s", f->id.c_str(),
GetComponentName(tag).c_str());
return nullptr;
}
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Instantiate analyzer %s",
f->id.c_str(), GetComponentName(tag).c_str());
DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Instantiate analyzer %s", f->id.c_str(),
GetComponentName(tag).c_str());
Analyzer* a;
@ -497,7 +479,8 @@ Analyzer* Manager::InstantiateAnalyzer(const Tag& tag,
else
{
reporter->InternalWarning("file analyzer %s cannot be instantiated "
"dynamically", c->CanonicalName().c_str());
"dynamically",
c->CanonicalName().c_str());
return nullptr;
}
@ -509,9 +492,9 @@ Analyzer* Manager::InstantiateAnalyzer(const Tag& tag,
return a;
}
zeek::detail::RuleMatcher::MIME_Matches* Manager::DetectMIME(
const u_char* data, uint64_t len,
zeek::detail::RuleMatcher::MIME_Matches* rval) const
zeek::detail::RuleMatcher::MIME_Matches*
Manager::DetectMIME(const u_char* data, uint64_t len,
zeek::detail::RuleMatcher::MIME_Matches* rval) const
{
if ( ! magic_state )
reporter->InternalError("file magic signature state not initialized");
@ -538,13 +521,12 @@ VectorValPtr GenMIMEMatchesVal(const zeek::detail::RuleMatcher::MIME_Matches& m)
static auto mime_match = id::find_type<RecordType>("mime_match");
auto rval = make_intrusive<VectorVal>(mime_matches);
for ( zeek::detail::RuleMatcher::MIME_Matches::const_iterator it = m.begin();
it != m.end(); ++it )
for ( zeek::detail::RuleMatcher::MIME_Matches::const_iterator it = m.begin(); it != m.end();
++it )
{
auto element = make_intrusive<RecordVal>(mime_match);
for ( set<string>::const_iterator it2 = it->second.begin();
it2 != it->second.end(); ++it2 )
for ( set<string>::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 )
{
element->Assign(0, it->first);
element->Assign(1, *it2);
@ -556,4 +538,4 @@ VectorValPtr GenMIMEMatchesVal(const zeek::detail::RuleMatcher::MIME_Matches& m)
return rval;
}
} // namespace zeek::file_analysis
} // namespace zeek::file_analysis

View file

@ -2,31 +2,33 @@
#pragma once
#include <string>
#include <set>
#include <map>
#include <set>
#include <string>
#include "zeek/file_analysis/Component.h"
#include "zeek/RunState.h"
#include "zeek/RuleMatcher.h"
#include "zeek/plugin/ComponentManager.h"
#include "zeek/RunState.h"
#include "zeek/analyzer/Tag.h"
#include "zeek/file_analysis/Component.h"
#include "zeek/file_analysis/FileTimer.h"
#include "zeek/plugin/ComponentManager.h"
namespace zeek {
namespace zeek
{
class TableVal;
class VectorVal;
namespace analyzer {
namespace analyzer
{
class Analyzer;
class Tag;
} // namespace analyzer
} // namespace analyzer
namespace file_analysis {
namespace file_analysis
{
class File;
class Tag;
@ -34,9 +36,9 @@ class Tag;
/**
* Main entry point for interacting with file analysis.
*/
class Manager : public plugin::ComponentManager<Tag, Component> {
class Manager : public plugin::ComponentManager<Tag, Component>
{
public:
/**
* Constructor.
*/
@ -110,9 +112,8 @@ public:
* the \c get_file_handle script-layer event). An empty string
* indicates the associate file is not going to be analyzed further.
*/
std::string DataIn(const u_char* data, uint64_t len, uint64_t offset,
const analyzer::Tag& tag, Connection* conn, bool is_orig,
const std::string& precomputed_file_id = "",
std::string DataIn(const u_char* data, uint64_t len, uint64_t offset, const analyzer::Tag& tag,
Connection* conn, bool is_orig, const std::string& precomputed_file_id = "",
const std::string& mime_type = "");
/**
@ -137,9 +138,8 @@ public:
* the \c get_file_handle script-layer event). An empty string
* indicates the associated file is not going to be analyzed further.
*/
std::string DataIn(const u_char* data, uint64_t len, const analyzer::Tag& tag,
Connection* conn, bool is_orig,
const std::string& precomputed_file_id = "",
std::string DataIn(const u_char* data, uint64_t len, const analyzer::Tag& tag, Connection* conn,
bool is_orig, const std::string& precomputed_file_id = "",
const std::string& mime_type = "");
/**
@ -217,9 +217,8 @@ public:
* the \c get_file_handle script-layer event). An empty string
* indicates the associate file is not going to be analyzed further.
*/
std::string Gap(uint64_t offset, uint64_t len, const analyzer::Tag& tag,
Connection* conn, bool is_orig,
const std::string& precomputed_file_id = "");
std::string Gap(uint64_t offset, uint64_t len, const analyzer::Tag& tag, Connection* conn,
bool is_orig, const std::string& precomputed_file_id = "");
/**
* Provide the expected number of bytes that comprise a file.
@ -236,8 +235,8 @@ public:
* the \c get_file_handle script-layer event). An empty string
* indicates the associate file is not going to be analyzed further.
*/
std::string SetSize(uint64_t size, const analyzer::Tag& tag, Connection* conn,
bool is_orig, const std::string& precomputed_file_id = "");
std::string SetSize(uint64_t size, const analyzer::Tag& tag, Connection* conn, bool is_orig,
const std::string& precomputed_file_id = "");
/**
* Starts ignoring a file, which will finally be removed from internal
@ -282,8 +281,7 @@ public:
* @return false if file identifier and analyzer did not map to anything,
* else true.
*/
bool SetExtractionLimit(const std::string& file_id,
RecordValPtr args, uint64_t n) const;
bool SetExtractionLimit(const std::string& file_id, RecordValPtr args, uint64_t n) const;
/**
* Try to retrieve a file that's being analyzed, using its identifier/hash.
@ -329,8 +327,7 @@ public:
* @param f The file analzer is to be associated with.
* @return The new analyzer instance or null if tag is invalid.
*/
Analyzer* InstantiateAnalyzer(const Tag& tag, RecordValPtr args,
File* f) const;
Analyzer* InstantiateAnalyzer(const Tag& tag, RecordValPtr args, File* f) const;
/**
* Returns a set of all matching MIME magic signatures for a given
@ -343,9 +340,9 @@ public:
* @return Set of all matching file magic signatures, which may be
* an object allocated by the method if \a rval is a null pointer.
*/
zeek::detail::RuleMatcher::MIME_Matches* DetectMIME(
const u_char* data, uint64_t len,
zeek::detail::RuleMatcher::MIME_Matches* rval) const;
zeek::detail::RuleMatcher::MIME_Matches*
DetectMIME(const u_char* data, uint64_t len,
zeek::detail::RuleMatcher::MIME_Matches* rval) const;
/**
* Returns the strongest MIME magic signature match for a given data chunk.
@ -356,14 +353,11 @@ public:
*/
std::string DetectMIME(const u_char* data, uint64_t len) const;
uint64_t CurrentFiles()
{ return id_map.size(); }
uint64_t CurrentFiles() { return id_map.size(); }
uint64_t MaxFiles()
{ return max_files; }
uint64_t MaxFiles() { return max_files; }
uint64_t CumulativeFiles()
{ return cumulative_files; }
uint64_t CumulativeFiles() { return cumulative_files; }
protected:
friend class detail::FileTimer;
@ -387,9 +381,8 @@ protected:
* connection-related fields.
*/
File* GetFile(const std::string& file_id, Connection* conn = nullptr,
const analyzer::Tag& tag = analyzer::Tag::Error,
bool is_orig = false, bool update_conn = true,
const char* source_name = nullptr);
const analyzer::Tag& tag = analyzer::Tag::Error, bool is_orig = false,
bool update_conn = true, const char* source_name = nullptr);
/**
* Evaluate timeout policy for a file and remove the File object mapped to
@ -436,18 +429,18 @@ private:
TagSet* LookupMIMEType(const std::string& mtype, bool add_if_not_found);
std::map<std::string, File*> id_map; /**< Map file ID to file_analysis::File records. */
std::map<std::string, File*> id_map; /**< Map file ID to file_analysis::File records. */
std::set<std::string> ignored; /**< Ignored files. Will be finally removed on EOF. */
std::string current_file_id; /**< Hash of what get_file_handle event sets. */
zeek::detail::RuleFileMagicState* magic_state; /**< File magic signature match state. */
MIMEMap mime_types;/**< Mapping of MIME types to analyzers. */
std::string current_file_id; /**< Hash of what get_file_handle event sets. */
zeek::detail::RuleFileMagicState* magic_state; /**< File magic signature match state. */
MIMEMap mime_types; /**< Mapping of MIME types to analyzers. */
inline static TableVal* disabled = nullptr; /**< Table of disabled analyzers. */
inline static TableType* tag_set_type = nullptr; /**< Type for set[tag]. */
inline static TableVal* disabled = nullptr; /**< Table of disabled analyzers. */
inline static TableType* tag_set_type = nullptr; /**< Type for set[tag]. */
size_t cumulative_files;
size_t max_files;
};
};
/**
* Returns a script-layer value corresponding to the \c mime_matches type.
@ -455,8 +448,8 @@ private:
*/
VectorValPtr GenMIMEMatchesVal(const zeek::detail::RuleMatcher::MIME_Matches& m);
} // namespace file_analysis
} // namespace file_analysis
extern file_analysis::Manager* file_mgr;
} // namespace zeek
} // namespace zeek

View file

@ -1,16 +1,15 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/file_analysis/Tag.h"
#include "zeek/file_analysis/Manager.h"
namespace zeek::file_analysis {
namespace zeek::file_analysis
{
const Tag Tag::Error;
Tag::Tag(type_t type, subtype_t subtype)
: zeek::Tag(file_mgr->GetTagType(), type, subtype)
{
}
Tag::Tag(type_t type, subtype_t subtype) : zeek::Tag(file_mgr->GetTagType(), type, subtype) { }
Tag& Tag::operator=(const Tag& other)
{
@ -23,8 +22,6 @@ const EnumValPtr& Tag::AsVal() const
return zeek::Tag::AsVal(file_mgr->GetTagType());
}
Tag::Tag(EnumValPtr val)
: zeek::Tag(std::move(val))
{ }
Tag::Tag(EnumValPtr val) : zeek::Tag(std::move(val)) { }
} // namespace zeek::file_analysis
} // namespace zeek::file_analysis

View file

@ -2,19 +2,22 @@
#pragma once
#include "zeek/zeek-config.h"
#include "zeek/Tag.h"
#include "zeek/zeek-config.h"
namespace zeek::plugin {
template <class T> class TaggedComponent;
template <class T, class C> class ComponentManager;
}
namespace zeek::plugin
{
template <class T> class TaggedComponent;
template <class T, class C> class ComponentManager;
}
namespace zeek {
namespace zeek
{
class EnumVal;
namespace file_analysis {
namespace file_analysis
{
class Component;
@ -23,29 +26,30 @@ class Component;
*
* The script-layer analogue is Files::Tag.
*/
class Tag : public zeek::Tag {
class Tag : public zeek::Tag
{
public:
/*
* Copy constructor.
*/
Tag(const Tag& other) : zeek::Tag(other) {}
Tag(const Tag& other) : zeek::Tag(other) { }
/**
* Default constructor. This initializes the tag with an error value
* that will make \c operator \c bool return false.
*/
Tag() : zeek::Tag() {}
Tag() : zeek::Tag() { }
/**
* Destructor.
*/
~Tag() {}
~Tag() { }
/**
* Returns false if the tag represents an error value rather than a
* legal analyzer type.
*/
explicit operator bool() const { return *this != Error; }
explicit operator bool() const { return *this != Error; }
/**
* Assignment operator.
@ -55,26 +59,17 @@ public:
/**
* Compares two tags for equality.
*/
bool operator==(const Tag& other) const
{
return zeek::Tag::operator==(other);
}
bool operator==(const Tag& other) const { return zeek::Tag::operator==(other); }
/**
* Compares two tags for inequality.
*/
bool operator!=(const Tag& other) const
{
return zeek::Tag::operator!=(other);
}
bool operator!=(const Tag& other) const { return zeek::Tag::operator!=(other); }
/**
* Compares two tags for less-than relationship.
*/
bool operator<(const Tag& other) const
{
return zeek::Tag::operator<(other);
}
bool operator<(const Tag& other) const { return zeek::Tag::operator<(other); }
/**
* Returns the \c Files::Tag enum that corresponds to this tag.
@ -108,7 +103,7 @@ protected:
* @param val An enum value of script type \c Files::Tag.
*/
explicit Tag(EnumValPtr val);
};
};
} // namespace file_analysis
} // namespace zeek
} // namespace file_analysis
} // namespace zeek

View file

@ -1,31 +1,32 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/file_analysis/analyzer/data_event/DataEvent.h"
#include <string>
#include "zeek/file_analysis/analyzer/data_event/DataEvent.h"
#include "zeek/EventRegistry.h"
#include "zeek/Event.h"
#include "zeek/EventRegistry.h"
#include "zeek/Func.h"
#include "zeek/util.h"
#include "zeek/file_analysis/Manager.h"
#include "zeek/util.h"
namespace zeek::file_analysis::detail {
namespace zeek::file_analysis::detail
{
DataEvent::DataEvent(RecordValPtr args, file_analysis::File* file,
EventHandlerPtr ce, EventHandlerPtr se)
: file_analysis::Analyzer(file_mgr->GetComponentTag("DATA_EVENT"),
std::move(args), file),
chunk_event(ce), stream_event(se)
DataEvent::DataEvent(RecordValPtr args, file_analysis::File* file, EventHandlerPtr ce,
EventHandlerPtr se)
: file_analysis::Analyzer(file_mgr->GetComponentTag("DATA_EVENT"), std::move(args), file),
chunk_event(ce), stream_event(se)
{
}
file_analysis::Analyzer* DataEvent::Instantiate(RecordValPtr args,
file_analysis::File* file)
file_analysis::Analyzer* DataEvent::Instantiate(RecordValPtr args, file_analysis::File* file)
{
const auto& chunk_val = args->GetField("chunk_event");
const auto& stream_val = args->GetField("stream_event");
if ( ! chunk_val && ! stream_val ) return nullptr;
if ( ! chunk_val && ! stream_val )
return nullptr;
EventHandlerPtr chunk;
EventHandlerPtr stream;
@ -41,27 +42,25 @@ file_analysis::Analyzer* DataEvent::Instantiate(RecordValPtr args,
bool DataEvent::DeliverChunk(const u_char* data, uint64_t len, uint64_t offset)
{
if ( ! chunk_event ) return true;
if ( ! chunk_event )
return true;
event_mgr.Enqueue(chunk_event,
GetFile()->ToVal(),
event_mgr.Enqueue(chunk_event, GetFile()->ToVal(),
make_intrusive<StringVal>(new String(data, len, false)),
val_mgr->Count(offset)
);
val_mgr->Count(offset));
return true;
}
bool DataEvent::DeliverStream(const u_char* data, uint64_t len)
{
if ( ! stream_event ) return true;
if ( ! stream_event )
return true;
event_mgr.Enqueue(stream_event,
GetFile()->ToVal(),
make_intrusive<StringVal>(new String(data, len, false))
);
event_mgr.Enqueue(stream_event, GetFile()->ToVal(),
make_intrusive<StringVal>(new String(data, len, false)));
return true;
}
} // namespace zeek::file_analysis::detail
} // namespace zeek::file_analysis::detail

View file

@ -4,19 +4,20 @@
#include <string>
#include "zeek/Val.h"
#include "zeek/file_analysis/File.h"
#include "zeek/file_analysis/Analyzer.h"
#include "zeek/EventHandler.h"
#include "zeek/Val.h"
#include "zeek/file_analysis/Analyzer.h"
#include "zeek/file_analysis/File.h"
namespace zeek::file_analysis::detail {
namespace zeek::file_analysis::detail
{
/**
* An analyzer to send file data to script-layer via events.
*/
class DataEvent : public file_analysis::Analyzer {
class DataEvent : public file_analysis::Analyzer
{
public:
/**
* Generates the event, if any, specified by the "chunk_event" field of this
* analyzer's \c AnalyzerArgs. This is for non-sequential file data input.
@ -43,11 +44,9 @@ public:
* @return the new DataEvent analyzer instance or a null pointer if
* no "chunk_event" or "stream_event" field was specfied in \a args.
*/
static file_analysis::Analyzer* Instantiate(RecordValPtr args,
file_analysis::File* file);
static file_analysis::Analyzer* Instantiate(RecordValPtr args, file_analysis::File* file);
protected:
/**
* Constructor.
* @param args the \c AnalyzerArgs value which represents the analyzer.
@ -57,12 +56,11 @@ protected:
* @param se pointer to event handler which will be called to receive
* sequential file data.
*/
DataEvent(RecordValPtr args, file_analysis::File* file,
EventHandlerPtr ce, EventHandlerPtr se);
DataEvent(RecordValPtr args, file_analysis::File* file, EventHandlerPtr ce, EventHandlerPtr se);
private:
EventHandlerPtr chunk_event;
EventHandlerPtr stream_event;
};
};
} // namespace zeek::file_analysis::detail
} // namespace zeek::file_analysis::detail

View file

@ -1,22 +1,26 @@
// See the file in the main distribution directory for copyright.
#include "zeek/plugin/Plugin.h"
#include "zeek/file_analysis/Component.h"
#include "zeek/file_analysis/analyzer/data_event/DataEvent.h"
namespace zeek::plugin::detail::Zeek_FileDataEvent {
namespace zeek::plugin::detail::Zeek_FileDataEvent
{
class Plugin : public zeek::plugin::Plugin {
class Plugin : public zeek::plugin::Plugin
{
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::file_analysis::Component("DATA_EVENT", zeek::file_analysis::detail::DataEvent::Instantiate));
AddComponent(new zeek::file_analysis::Component(
"DATA_EVENT", zeek::file_analysis::detail::DataEvent::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::FileDataEvent";
config.description = "Delivers file content";
return config;
}
} plugin;
} plugin;
} // namespace zeek::plugin::detail::Zeek_FileDataEvent
} // namespace zeek::plugin::detail::Zeek_FileDataEvent

View file

@ -4,15 +4,15 @@
#include <string>
#include "zeek/util.h"
#include "zeek/Event.h"
#include "zeek/file_analysis/Manager.h"
#include "zeek/util.h"
namespace zeek::file_analysis::detail {
namespace zeek::file_analysis::detail
{
Entropy::Entropy(RecordValPtr args, file_analysis::File* file)
: file_analysis::Analyzer(file_mgr->GetComponentTag("ENTROPY"),
std::move(args), file)
: file_analysis::Analyzer(file_mgr->GetComponentTag("ENTROPY"), std::move(args), file)
{
entropy = new EntropyVal;
fed = false;
@ -23,8 +23,7 @@ Entropy::~Entropy()
Unref(entropy);
}
file_analysis::Analyzer* Entropy::Instantiate(RecordValPtr args,
file_analysis::File* file)
file_analysis::Analyzer* Entropy::Instantiate(RecordValPtr args, file_analysis::File* file)
{
return new Entropy(std::move(args), file);
}
@ -69,10 +68,7 @@ void Entropy::Finalize()
ent_result->Assign(3, montepi);
ent_result->Assign(4, scc);
event_mgr.Enqueue(file_entropy,
GetFile()->ToVal(),
std::move(ent_result)
);
event_mgr.Enqueue(file_entropy, GetFile()->ToVal(), std::move(ent_result));
}
} // namespace zeek::file_analysis::detail
} // namespace zeek::file_analysis::detail

View file

@ -4,21 +4,21 @@
#include <string>
#include "zeek/Val.h"
#include "zeek/OpaqueVal.h"
#include "zeek/file_analysis/File.h"
#include "zeek/Val.h"
#include "zeek/file_analysis/Analyzer.h"
#include "zeek/file_analysis/File.h"
#include "zeek/file_analysis/analyzer/entropy/events.bif.h"
namespace zeek::file_analysis::detail {
namespace zeek::file_analysis::detail
{
/**
* An analyzer to produce entropy of file contents.
*/
class Entropy : public file_analysis::Analyzer {
class Entropy : public file_analysis::Analyzer
{
public:
/**
* Destructor.
*/
@ -31,8 +31,7 @@ public:
* @return the new Entropy analyzer instance or a null pointer if the
* the "extraction_file" field of \a args wasn't set.
*/
static file_analysis::Analyzer* Instantiate(RecordValPtr args,
file_analysis::File* file);
static file_analysis::Analyzer* Instantiate(RecordValPtr args, file_analysis::File* file);
/**
* Calculate entropy of next chunk of file contents.
@ -58,7 +57,6 @@ public:
bool Undelivered(uint64_t offset, uint64_t len) override;
protected:
/**
* Constructor.
* @param args the \c AnalyzerArgs value which represents the analyzer.
@ -77,6 +75,6 @@ protected:
private:
EntropyVal* entropy;
bool fed;
};
};
} // namespace zeek::file_analysis::detail
} // namespace zeek::file_analysis::detail

View file

@ -1,22 +1,26 @@
// See the file in the main distribution directory for copyright.
#include "zeek/plugin/Plugin.h"
#include "zeek/file_analysis/Component.h"
#include "zeek/file_analysis/analyzer/entropy/Entropy.h"
namespace zeek::plugin::detail::Zeek_FileEntropy {
namespace zeek::plugin::detail::Zeek_FileEntropy
{
class Plugin : public zeek::plugin::Plugin {
class Plugin : public zeek::plugin::Plugin
{
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::file_analysis::Component("ENTROPY", zeek::file_analysis::detail::Entropy::Instantiate));
AddComponent(new zeek::file_analysis::Component(
"ENTROPY", zeek::file_analysis::detail::Entropy::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::FileEntropy";
config.description = "Entropy test file content";
return config;
}
} plugin;
} plugin;
} // namespace zeek::plugin::detail::Zeek_FileEntropy
} // namespace zeek::plugin::detail::Zeek_FileEntropy

View file

@ -5,17 +5,17 @@
#include <fcntl.h>
#include <string>
#include "zeek/util.h"
#include "zeek/Event.h"
#include "zeek/file_analysis/Manager.h"
#include "zeek/util.h"
namespace zeek::file_analysis::detail {
namespace zeek::file_analysis::detail
{
Extract::Extract(RecordValPtr args, file_analysis::File* file,
const std::string& arg_filename, uint64_t arg_limit)
: file_analysis::Analyzer(file_mgr->GetComponentTag("EXTRACT"),
std::move(args), file),
filename(arg_filename), limit(arg_limit), depth(0)
Extract::Extract(RecordValPtr args, file_analysis::File* file, const std::string& arg_filename,
uint64_t arg_limit)
: file_analysis::Analyzer(file_mgr->GetComponentTag("EXTRACT"), std::move(args), file),
filename(arg_filename), limit(arg_limit), depth(0)
{
char buf[128];
file_stream = fopen(filename.data(), "w");
@ -26,8 +26,7 @@ Extract::Extract(RecordValPtr args, file_analysis::File* file,
if ( setvbuf(file_stream, nullptr, _IOFBF, BUFSIZ) )
{
util::zeek_strerror_r(errno, buf, sizeof(buf));
reporter->Warning("cannot set buffering mode for %s: %s",
filename.data(), buf);
reporter->Warning("cannot set buffering mode for %s: %s", filename.data(), buf);
}
}
else
@ -47,8 +46,7 @@ Extract::~Extract()
}
}
static ValPtr get_extract_field_val(const RecordValPtr& args,
const char* name)
static ValPtr get_extract_field_val(const RecordValPtr& args, const char* name)
{
const auto& rval = args->GetField(name);
@ -58,8 +56,7 @@ static ValPtr get_extract_field_val(const RecordValPtr& args,
return rval;
}
file_analysis::Analyzer* Extract::Instantiate(RecordValPtr args,
file_analysis::File* file)
file_analysis::Analyzer* Extract::Instantiate(RecordValPtr args, file_analysis::File* file)
{
const auto& fname = get_extract_field_val(args, "extract_filename");
const auto& limit = get_extract_field_val(args, "extract_limit");
@ -67,8 +64,7 @@ file_analysis::Analyzer* Extract::Instantiate(RecordValPtr args,
if ( ! fname || ! limit )
return nullptr;
return new Extract(std::move(args), file, fname->AsString()->CheckString(),
limit->AsCount());
return new Extract(std::move(args), file, fname->AsString()->CheckString(), limit->AsCount());
}
static bool check_limit_exceeded(uint64_t lim, uint64_t depth, uint64_t len, uint64_t* n)
@ -108,12 +104,8 @@ bool Extract::DeliverStream(const u_char* data, uint64_t len)
if ( limit_exceeded && file_extraction_limit )
{
file_analysis::File* f = GetFile();
f->FileEvent(file_extraction_limit, {
f->ToVal(),
GetArgs(),
val_mgr->Count(limit),
val_mgr->Count(len)
});
f->FileEvent(file_extraction_limit,
{f->ToVal(), GetArgs(), val_mgr->Count(limit), val_mgr->Count(len)});
// Limit may have been modified by a BIF, re-check it.
limit_exceeded = check_limit_exceeded(limit, depth, len, &towrite);
@ -126,8 +118,7 @@ bool Extract::DeliverStream(const u_char* data, uint64_t len)
if ( fwrite(data, towrite, 1, file_stream) != 1 )
{
util::zeek_strerror_r(errno, buf, sizeof(buf));
reporter->Error("failed to write to extracted file %s: %s",
filename.data(), buf);
reporter->Error("failed to write to extracted file %s: %s", filename.data(), buf);
fclose(file_stream);
file_stream = nullptr;
return false;
@ -143,11 +134,10 @@ bool Extract::DeliverStream(const u_char* data, uint64_t len)
if ( limit_exceeded && fflush(file_stream) )
{
util::zeek_strerror_r(errno, buf, sizeof(buf));
reporter->Warning("cannot fflush extracted file %s: %s",
filename.data(), buf);
reporter->Warning("cannot fflush extracted file %s: %s", filename.data(), buf);
}
return ( ! limit_exceeded );
return (! limit_exceeded);
}
bool Extract::Undelivered(uint64_t offset, uint64_t len)
@ -163,19 +153,18 @@ bool Extract::Undelivered(uint64_t offset, uint64_t len)
{
char buf[128];
util::zeek_strerror_r(errno, buf, sizeof(buf));
reporter->Error("failed to write to extracted file %s: %s",
filename.data(), buf);
reporter->Error("failed to write to extracted file %s: %s", filename.data(), buf);
fclose(file_stream);
file_stream = nullptr;
delete [] tmp;
delete[] tmp;
return false;
}
delete [] tmp;
delete[] tmp;
depth += len;
}
return true;
}
} // namespace zeek::file_analysis::detail
} // namespace zeek::file_analysis::detail

View file

@ -2,23 +2,23 @@
#pragma once
#include <string>
#include <cstdio>
#include <string>
#include "zeek/Val.h"
#include "zeek/file_analysis/File.h"
#include "zeek/file_analysis/Analyzer.h"
#include "zeek/file_analysis/File.h"
#include "zeek/file_analysis/analyzer/extract/events.bif.h"
namespace zeek::file_analysis::detail {
namespace zeek::file_analysis::detail
{
/**
* An analyzer to extract content of files to local disk.
*/
class Extract : public file_analysis::Analyzer {
class Extract : public file_analysis::Analyzer
{
public:
/**
* Destructor. Will close the file that was used for data extraction.
*/
@ -48,8 +48,7 @@ public:
* @return the new Extract analyzer instance or a null pointer if the
* the "extraction_file" field of \a args wasn't set.
*/
static file_analysis::Analyzer* Instantiate(RecordValPtr args,
file_analysis::File* file);
static file_analysis::Analyzer* Instantiate(RecordValPtr args, file_analysis::File* file);
/**
* Sets the maximum allowed extracted file size. A value of zero means
@ -59,7 +58,6 @@ public:
void SetLimit(uint64_t bytes) { limit = bytes; }
protected:
/**
* Constructor.
* @param args the \c AnalyzerArgs value which represents the analyzer.
@ -68,14 +66,14 @@ protected:
* to which the contents of the file will be extracted/written.
* @param arg_limit the maximum allowed file size.
*/
Extract(RecordValPtr args, file_analysis::File* file,
const std::string& arg_filename, uint64_t arg_limit);
Extract(RecordValPtr args, file_analysis::File* file, const std::string& arg_filename,
uint64_t arg_limit);
private:
std::string filename;
FILE* file_stream;
uint64_t limit;
uint64_t depth;
};
};
} // namespace zeek::file_analysis::detail
} // namespace zeek::file_analysis::detail

View file

@ -1,22 +1,26 @@
// See the file in the main distribution directory for copyright.
#include "zeek/plugin/Plugin.h"
#include "zeek/file_analysis/Component.h"
#include "zeek/file_analysis/analyzer/extract/Extract.h"
namespace zeek::plugin::detail::Zeek_FileExtract {
namespace zeek::plugin::detail::Zeek_FileExtract
{
class Plugin : public zeek::plugin::Plugin {
class Plugin : public zeek::plugin::Plugin
{
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::file_analysis::Component("EXTRACT", zeek::file_analysis::detail::Extract::Instantiate));
AddComponent(new zeek::file_analysis::Component(
"EXTRACT", zeek::file_analysis::detail::Extract::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::FileExtract";
config.description = "Extract file content";
return config;
}
} plugin;
} plugin;
} // namespace zeek::plugin::detail::Zeek_FileExtract
} // namespace zeek::plugin::detail::Zeek_FileExtract

View file

@ -4,16 +4,16 @@
#include <string>
#include "zeek/util.h"
#include "zeek/Event.h"
#include "zeek/file_analysis/Manager.h"
#include "zeek/util.h"
namespace zeek::file_analysis::detail {
namespace zeek::file_analysis::detail
{
Hash::Hash(RecordValPtr args, file_analysis::File* file,
HashVal* hv, const char* arg_kind)
Hash::Hash(RecordValPtr args, file_analysis::File* file, HashVal* hv, const char* arg_kind)
: file_analysis::Analyzer(file_mgr->GetComponentTag(util::to_upper(arg_kind).c_str()),
std::move(args), file),
std::move(args), file),
hash(hv), fed(false), kind(arg_kind)
{
hash->Init();
@ -55,11 +55,7 @@ void Hash::Finalize()
if ( ! file_hash )
return;
event_mgr.Enqueue(file_hash,
GetFile()->ToVal(),
make_intrusive<StringVal>(kind),
hash->Get()
);
event_mgr.Enqueue(file_hash, GetFile()->ToVal(), make_intrusive<StringVal>(kind), hash->Get());
}
} // namespace zeek::file_analysis::detail
} // namespace zeek::file_analysis::detail

View file

@ -4,21 +4,21 @@
#include <string>
#include "zeek/Val.h"
#include "zeek/OpaqueVal.h"
#include "zeek/file_analysis/File.h"
#include "zeek/Val.h"
#include "zeek/file_analysis/Analyzer.h"
#include "zeek/file_analysis/File.h"
#include "zeek/file_analysis/analyzer/hash/events.bif.h"
namespace zeek::file_analysis::detail {
namespace zeek::file_analysis::detail
{
/**
* An analyzer to produce a hash of file contents.
*/
class Hash : public file_analysis::Analyzer {
class Hash : public file_analysis::Analyzer
{
public:
/**
* Destructor.
*/
@ -48,7 +48,6 @@ public:
bool Undelivered(uint64_t offset, uint64_t len) override;
protected:
/**
* Constructor.
* @param args the \c AnalyzerArgs value which represents the analyzer.
@ -68,14 +67,14 @@ private:
HashVal* hash;
bool fed;
const char* kind;
};
};
/**
* An analyzer to produce an MD5 hash of file contents.
*/
class MD5 : public Hash {
class MD5 : public Hash
{
public:
/**
* Create a new instance of the MD5 hashing file analyzer.
* @param args the \c AnalyzerArgs value which represents the analyzer.
@ -83,12 +82,12 @@ public:
* @return the new MD5 analyzer instance or a null pointer if there's no
* handler for the "file_hash" event.
*/
static file_analysis::Analyzer* Instantiate(RecordValPtr args,
file_analysis::File* file)
{ return file_hash ? new MD5(std::move(args), file) : nullptr; }
static file_analysis::Analyzer* Instantiate(RecordValPtr args, file_analysis::File* file)
{
return file_hash ? new MD5(std::move(args), file) : nullptr;
}
protected:
/**
* Constructor.
* @param args the \c AnalyzerArgs value which represents the analyzer.
@ -96,15 +95,16 @@ protected:
*/
MD5(RecordValPtr args, file_analysis::File* file)
: Hash(std::move(args), file, new MD5Val(), "md5")
{}
};
{
}
};
/**
* An analyzer to produce a SHA1 hash of file contents.
*/
class SHA1 : public Hash {
class SHA1 : public Hash
{
public:
/**
* Create a new instance of the SHA1 hashing file analyzer.
* @param args the \c AnalyzerArgs value which represents the analyzer.
@ -112,12 +112,12 @@ public:
* @return the new MD5 analyzer instance or a null pointer if there's no
* handler for the "file_hash" event.
*/
static file_analysis::Analyzer* Instantiate(RecordValPtr args,
file_analysis::File* file)
{ return file_hash ? new SHA1(std::move(args), file) : nullptr; }
static file_analysis::Analyzer* Instantiate(RecordValPtr args, file_analysis::File* file)
{
return file_hash ? new SHA1(std::move(args), file) : nullptr;
}
protected:
/**
* Constructor.
* @param args the \c AnalyzerArgs value which represents the analyzer.
@ -125,15 +125,16 @@ protected:
*/
SHA1(RecordValPtr args, file_analysis::File* file)
: Hash(std::move(args), file, new SHA1Val(), "sha1")
{}
};
{
}
};
/**
* An analyzer to produce a SHA256 hash of file contents.
*/
class SHA256 : public Hash {
class SHA256 : public Hash
{
public:
/**
* Create a new instance of the SHA256 hashing file analyzer.
* @param args the \c AnalyzerArgs value which represents the analyzer.
@ -141,12 +142,12 @@ public:
* @return the new MD5 analyzer instance or a null pointer if there's no
* handler for the "file_hash" event.
*/
static file_analysis::Analyzer* Instantiate(RecordValPtr args,
file_analysis::File* file)
{ return file_hash ? new SHA256(std::move(args), file) : nullptr; }
static file_analysis::Analyzer* Instantiate(RecordValPtr args, file_analysis::File* file)
{
return file_hash ? new SHA256(std::move(args), file) : nullptr;
}
protected:
/**
* Constructor.
* @param args the \c AnalyzerArgs value which represents the analyzer.
@ -154,7 +155,8 @@ protected:
*/
SHA256(RecordValPtr args, file_analysis::File* file)
: Hash(std::move(args), file, new SHA256Val(), "sha256")
{}
};
{
}
};
} // namespace zeek::file_analysis
} // namespace zeek::file_analysis

View file

@ -1,24 +1,30 @@
// See the file in the main distribution directory for copyright.
#include "zeek/plugin/Plugin.h"
#include "zeek/file_analysis/Component.h"
#include "zeek/file_analysis/analyzer/hash/Hash.h"
namespace zeek::plugin::detail::Zeek_FileHash {
namespace zeek::plugin::detail::Zeek_FileHash
{
class Plugin : public zeek::plugin::Plugin {
class Plugin : public zeek::plugin::Plugin
{
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::file_analysis::Component("MD5", zeek::file_analysis::detail::MD5::Instantiate));
AddComponent(new zeek::file_analysis::Component("SHA1", zeek::file_analysis::detail::SHA1::Instantiate));
AddComponent(new zeek::file_analysis::Component("SHA256", zeek::file_analysis::detail::SHA256::Instantiate));
AddComponent(new zeek::file_analysis::Component(
"MD5", zeek::file_analysis::detail::MD5::Instantiate));
AddComponent(new zeek::file_analysis::Component(
"SHA1", zeek::file_analysis::detail::SHA1::Instantiate));
AddComponent(new zeek::file_analysis::Component(
"SHA256", zeek::file_analysis::detail::SHA256::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::FileHash";
config.description = "Hash file content";
return config;
}
} plugin;
} plugin;
} // namespace zeek::plugin::detail::Zeek_FileHash
} // namespace zeek::plugin::detail::Zeek_FileHash

View file

@ -1,12 +1,12 @@
#include "zeek/file_analysis/analyzer/pe/PE.h"
#include "zeek/file_analysis/Manager.h"
namespace zeek::file_analysis::detail {
namespace zeek::file_analysis::detail
{
PE::PE(RecordValPtr args, file_analysis::File* file)
: file_analysis::Analyzer(file_mgr->GetComponentTag("PE"),
std::move(args),
file)
: file_analysis::Analyzer(file_mgr->GetComponentTag("PE"), std::move(args), file)
{
conn = new binpac::PE::MockConnection(this);
interp = new binpac::PE::File(conn);
@ -41,4 +41,4 @@ bool PE::EndOfFile()
return false;
}
} // namespace zeek::file_analysis::detail
} // namespace zeek::file_analysis::detail

View file

@ -2,22 +2,26 @@
#include <string>
#include "zeek/Val.h"
#include "zeek/File.h"
#include "zeek/Val.h"
#include "file_analysis/analyzer/pe/pe_pac.h"
namespace zeek::file_analysis::detail {
namespace zeek::file_analysis::detail
{
/**
* Analyze Portable Executable files
*/
class PE : public file_analysis::Analyzer {
class PE : public file_analysis::Analyzer
{
public:
~PE();
static file_analysis::Analyzer* Instantiate(RecordValPtr args,
file_analysis::File* file)
{ return new PE(std::move(args), file); }
static file_analysis::Analyzer* Instantiate(RecordValPtr args, file_analysis::File* file)
{
return new PE(std::move(args), file);
}
virtual bool DeliverStream(const u_char* data, uint64_t len);
@ -28,6 +32,6 @@ protected:
binpac::PE::File* interp;
binpac::PE::MockConnection* conn;
bool done;
};
};
} // namespace zeek::file_analysis::detail
} // namespace zeek::file_analysis::detail

View file

@ -1,22 +1,26 @@
// See the file in the main distribution directory for copyright.
#include "zeek/plugin/Plugin.h"
#include "zeek/file_analysis/Component.h"
#include "zeek/file_analysis/analyzer/pe/PE.h"
namespace zeek::plugin::detail::Zeek_PE {
namespace zeek::plugin::detail::Zeek_PE
{
class Plugin : public zeek::plugin::Plugin {
class Plugin : public zeek::plugin::Plugin
{
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::file_analysis::Component("PE", zeek::file_analysis::detail::PE::Instantiate));
AddComponent(
new zeek::file_analysis::Component("PE", zeek::file_analysis::detail::PE::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::PE";
config.description = "Portable Executable analyzer";
return config;
}
} plugin;
} plugin;
} // namespace zeek::plugin::detail::Zeek_PE
} // namespace zeek::plugin::detail::Zeek_PE

View file

@ -3,22 +3,26 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/plugin/Plugin.h"
#include "zeek/file_analysis/Component.h"
#include "zeek/file_analysis/analyzer/unified2/Unified2.h"
namespace zeek::plugin::detail::Zeek_Unified2 {
namespace zeek::plugin::detail::Zeek_Unified2
{
class Plugin : public zeek::plugin::Plugin {
class Plugin : public zeek::plugin::Plugin
{
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::file_analysis::Component("UNIFIED2", zeek::file_analysis::detail::Unified2::Instantiate));
AddComponent(new zeek::file_analysis::Component(
"UNIFIED2", zeek::file_analysis::detail::Unified2::Instantiate));
zeek::plugin::Configuration config;
config.name = "Zeek::Unified2";
config.description = "Analyze Unified2 alert files.";
return config;
}
} plugin;
} plugin;
} // namespace zeek::plugin::detail::Zeek_Unified2
} // namespace zeek::plugin::detail::Zeek_Unified2

View file

@ -1,13 +1,14 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/file_analysis/analyzer/unified2/Unified2.h"
#include "zeek/file_analysis/Manager.h"
namespace zeek::file_analysis::detail {
namespace zeek::file_analysis::detail
{
Unified2::Unified2(RecordValPtr args, file_analysis::File* file)
: file_analysis::Analyzer(file_mgr->GetComponentTag("UNIFIED2"),
std::move(args), file)
: file_analysis::Analyzer(file_mgr->GetComponentTag("UNIFIED2"), std::move(args), file)
{
interp = new binpac::Unified2::Unified2_Analyzer(this);
}
@ -17,8 +18,7 @@ Unified2::~Unified2()
delete interp;
}
file_analysis::Analyzer* Unified2::Instantiate(RecordValPtr args,
file_analysis::File* file)
file_analysis::Analyzer* Unified2::Instantiate(RecordValPtr args, file_analysis::File* file)
{
return new Unified2(std::move(args), file);
}
@ -38,4 +38,4 @@ bool Unified2::DeliverStream(const u_char* data, uint64_t len)
return true;
}
} // namespace zeek::file_analysis::detail
} // namespace zeek::file_analysis::detail

View file

@ -5,23 +5,25 @@
#include <string>
#include "zeek/Val.h"
#include "zeek/file_analysis/File.h"
#include "zeek/file_analysis/Analyzer.h"
#include "zeek/file_analysis/File.h"
#include "file_analysis/analyzer/unified2/unified2_pac.h"
namespace zeek::file_analysis::detail {
namespace zeek::file_analysis::detail
{
/**
* An analyzer to extract content of files from local disk.
*/
class Unified2 : public file_analysis::Analyzer {
class Unified2 : public file_analysis::Analyzer
{
public:
~Unified2() override;
bool DeliverStream(const u_char* data, uint64_t len) override;
static file_analysis::Analyzer* Instantiate(RecordValPtr args,
file_analysis::File* file);
static file_analysis::Analyzer* Instantiate(RecordValPtr args, file_analysis::File* file);
protected:
Unified2(RecordValPtr args, file_analysis::File* file);
@ -30,6 +32,6 @@ private:
binpac::Unified2::Unified2_Analyzer* interp;
string filename;
};
};
} // namespace zeek::file_analysis::detail
} // namespace zeek::file_analysis::detail

View file

@ -3,39 +3,38 @@
#include "zeek/file_analysis/analyzer/x509/OCSP.h"
#include <string>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/asn1.h>
#include <openssl/opensslconf.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <string>
#include "zeek/file_analysis/analyzer/x509/X509.h"
#include "zeek/Event.h"
#include "zeek/Reporter.h"
#include "zeek/file_analysis/File.h"
#include "zeek/file_analysis/Manager.h"
#include "zeek/file_analysis/analyzer/x509/types.bif.h"
#include "zeek/file_analysis/analyzer/x509/X509.h"
#include "zeek/file_analysis/analyzer/x509/ocsp_events.bif.h"
#include "zeek/file_analysis/analyzer/x509/types.bif.h"
// helper function of sk_X509_value to avoid namespace problem
// sk_X509_value(X,Y) = > SKM_sk_value(X509,X,Y)
// X509 => file_analysis::X509
X509* helper_sk_X509_value(const STACK_OF(X509)* certs, int i)
X509* helper_sk_X509_value(const STACK_OF(X509) * certs, int i)
{
return sk_X509_value(certs, i);
}
namespace zeek::file_analysis::detail {
namespace zeek::file_analysis::detail
{
#define OCSP_STRING_BUF_SIZE 2048
static bool OCSP_RESPID_bio(OCSP_BASICRESP* basic_resp, BIO* bio)
{
#if ( OPENSSL_VERSION_NUMBER < 0x10100000L ) || defined(LIBRESSL_VERSION_NUMBER)
ASN1_OCTET_STRING* key = nullptr;
X509_NAME* name = nullptr;
ASN1_OCTET_STRING* key = nullptr;
X509_NAME* name = nullptr;
if ( ! basic_resp->tbsResponseData )
return false;
@ -49,8 +48,8 @@ static bool OCSP_RESPID_bio(OCSP_BASICRESP* basic_resp, BIO* bio)
else
return false;
#else
const ASN1_OCTET_STRING* key = nullptr;
const X509_NAME* name = nullptr;
const ASN1_OCTET_STRING* key = nullptr;
const X509_NAME* name = nullptr;
if ( ! OCSP_resp_get0_id(basic_resp, &key, &name) )
return false;
@ -66,13 +65,12 @@ static bool OCSP_RESPID_bio(OCSP_BASICRESP* basic_resp, BIO* bio)
static bool ocsp_add_cert_id(const OCSP_CERTID* cert_id, zeek::Args* vl, BIO* bio)
{
ASN1_OBJECT* hash_alg = nullptr;
ASN1_OBJECT* hash_alg = nullptr;
ASN1_OCTET_STRING* issuer_name_hash = nullptr;
ASN1_OCTET_STRING* issuer_key_hash = nullptr;
ASN1_INTEGER* serial_number = nullptr;
ASN1_OCTET_STRING* issuer_key_hash = nullptr;
ASN1_INTEGER* serial_number = nullptr;
auto res = OCSP_id_get0_info(&issuer_name_hash, &hash_alg,
&issuer_key_hash, &serial_number,
auto res = OCSP_id_get0_info(&issuer_name_hash, &hash_alg, &issuer_key_hash, &serial_number,
const_cast<OCSP_CERTID*>(cert_id));
if ( ! res )
@ -111,22 +109,18 @@ static bool ocsp_add_cert_id(const OCSP_CERTID* cert_id, zeek::Args* vl, BIO* bi
return true;
}
file_analysis::Analyzer* OCSP::InstantiateRequest(RecordValPtr args,
file_analysis::File* file)
file_analysis::Analyzer* OCSP::InstantiateRequest(RecordValPtr args, file_analysis::File* file)
{
return new OCSP(std::move(args), file, true);
}
file_analysis::Analyzer* OCSP::InstantiateReply(RecordValPtr args,
file_analysis::File* file)
file_analysis::Analyzer* OCSP::InstantiateReply(RecordValPtr args, file_analysis::File* file)
{
return new OCSP(std::move(args), file, false);
}
OCSP::OCSP(RecordValPtr args, file_analysis::File* file,
bool arg_request)
: X509Common::X509Common(file_mgr->GetComponentTag("OCSP"),
std::move(args), file),
OCSP::OCSP(RecordValPtr args, file_analysis::File* file, bool arg_request)
: X509Common::X509Common(file_mgr->GetComponentTag("OCSP"), std::move(args), file),
request(arg_request)
{
}
@ -150,9 +144,9 @@ bool OCSP::EndOfFile()
if ( request )
{
OCSP_REQUEST *req = d2i_OCSP_REQUEST(NULL, &ocsp_char, ocsp_data.size());
OCSP_REQUEST* req = d2i_OCSP_REQUEST(NULL, &ocsp_char, ocsp_data.size());
if (!req)
if ( ! req )
{
reporter->Weird(GetFile(), "openssl_ocsp_request_parse_error");
return false;
@ -163,9 +157,9 @@ bool OCSP::EndOfFile()
}
else
{
OCSP_RESPONSE *resp = d2i_OCSP_RESPONSE(NULL, &ocsp_char, ocsp_data.size());
OCSP_RESPONSE* resp = d2i_OCSP_RESPONSE(NULL, &ocsp_char, ocsp_data.size());
if (!resp)
if ( ! resp )
{
reporter->Weird(GetFile(), "openssl_ocsp_response_parse_error");
return false;
@ -176,25 +170,25 @@ bool OCSP::EndOfFile()
}
return true;
}
}
#if ( OPENSSL_VERSION_NUMBER >= 0x10100000L )
struct ASN1Seq {
struct ASN1Seq
{
ASN1Seq(const unsigned char** der_in, long length)
{ decoded = d2i_ASN1_SEQUENCE_ANY(nullptr, der_in, length); }
{
decoded = d2i_ASN1_SEQUENCE_ANY(nullptr, der_in, length);
}
~ASN1Seq()
{ sk_ASN1_TYPE_pop_free(decoded, ASN1_TYPE_free); }
~ASN1Seq() { sk_ASN1_TYPE_pop_free(decoded, ASN1_TYPE_free); }
explicit operator bool() const
{ return decoded; }
explicit operator bool() const { return decoded; }
operator ASN1_SEQUENCE_ANY*() const
{ return decoded; }
operator ASN1_SEQUENCE_ANY*() const { return decoded; }
ASN1_SEQUENCE_ANY* decoded;
};
};
// Re-encode and then parse out ASN1 structures to get at what we need...
/*- BasicOCSPResponse ::= SEQUENCE {
@ -209,9 +203,8 @@ typedef struct ocsp_basic_response_st {
STACK_OF(X509) *certs;
} OCSP_BASICRESP;
*/
static StringValPtr parse_basic_resp_sig_alg(OCSP_BASICRESP* basic_resp,
BIO* bio, char* buf,
size_t buf_len)
static StringValPtr parse_basic_resp_sig_alg(OCSP_BASICRESP* basic_resp, BIO* bio, char* buf,
size_t buf_len)
{
int der_basic_resp_len = 0;
unsigned char* der_basic_resp_dat = nullptr;
@ -336,13 +329,13 @@ static ValPtr parse_basic_resp_data_version(OCSP_BASICRESP* basic_resp)
return val_mgr->Count(-1);
}
/*- ResponseData ::= SEQUENCE {
* version [0] EXPLICIT Version DEFAULT v1,
* responderID ResponderID,
* producedAt GeneralizedTime,
* responses SEQUENCE OF SingleResponse,
* responseExtensions [1] EXPLICIT Extensions OPTIONAL }
*/
/*- ResponseData ::= SEQUENCE {
* version [0] EXPLICIT Version DEFAULT v1,
* responderID ResponderID,
* producedAt GeneralizedTime,
* responses SEQUENCE OF SingleResponse,
* responseExtensions [1] EXPLICIT Extensions OPTIONAL }
*/
auto constexpr version_idx = 0u;
auto version_type = sk_ASN1_TYPE_value(dseq, version_idx);
@ -415,22 +408,19 @@ void OCSP::ParseRequest(OCSP_REQUEST* req)
#endif
if ( ocsp_request )
event_mgr.Enqueue(ocsp_request,
GetFile()->ToVal(),
val_mgr->Count(version)
);
event_mgr.Enqueue(ocsp_request, GetFile()->ToVal(), val_mgr->Count(version));
BIO *bio = BIO_new(BIO_s_mem());
BIO* bio = BIO_new(BIO_s_mem());
int req_count = OCSP_request_onereq_count(req);
for ( int i=0; i<req_count; i++ )
for ( int i = 0; i < req_count; i++ )
{
zeek::Args rvl;
rvl.reserve(5);
rvl.emplace_back(GetFile()->ToVal());
OCSP_ONEREQ *one_req = OCSP_request_onereq_get0(req, i);
OCSP_CERTID *cert_id = OCSP_onereq_get0_id(one_req);
OCSP_ONEREQ* one_req = OCSP_request_onereq_get0(req, i);
OCSP_CERTID* cert_id = OCSP_onereq_get0_id(one_req);
ocsp_add_cert_id(cert_id, &rvl, bio);
@ -439,52 +429,52 @@ void OCSP::ParseRequest(OCSP_REQUEST* req)
}
BIO_free(bio);
}
}
void OCSP::ParseResponse(OCSP_RESPONSE *resp)
void OCSP::ParseResponse(OCSP_RESPONSE* resp)
{
//OCSP_RESPBYTES *resp_bytes = resp->responseBytes;
OCSP_BASICRESP *basic_resp = nullptr;
OCSP_RESPDATA *resp_data = nullptr;
OCSP_RESPID *resp_id = nullptr;
// OCSP_RESPBYTES *resp_bytes = resp->responseBytes;
OCSP_BASICRESP* basic_resp = nullptr;
OCSP_RESPDATA* resp_data = nullptr;
OCSP_RESPID* resp_id = nullptr;
const ASN1_GENERALIZEDTIME* produced_at = nullptr;
const STACK_OF(X509)* certs = nullptr;
int resp_count, num_ext = 0;
VectorVal *certs_vector = nullptr;
VectorVal* certs_vector = nullptr;
int len = 0;
char buf[OCSP_STRING_BUF_SIZE];
char buf[OCSP_STRING_BUF_SIZE];
memset(buf, 0, sizeof(buf));
const char *status_str = OCSP_response_status_str(OCSP_response_status(resp));
const char* status_str = OCSP_response_status_str(OCSP_response_status(resp));
auto status_val = make_intrusive<StringVal>(strlen(status_str), status_str);
if ( ocsp_response_status )
event_mgr.Enqueue(ocsp_response_status, GetFile()->ToVal(), status_val);
//if (!resp_bytes)
// if (!resp_bytes)
// {
// Unref(status_val);
// return;
// }
BIO *bio = BIO_new(BIO_s_mem());
//i2a_ASN1_OBJECT(bio, resp_bytes->responseType);
//int len = BIO_read(bio, buf, sizeof(buf));
//BIO_reset(bio);
BIO* bio = BIO_new(BIO_s_mem());
// i2a_ASN1_OBJECT(bio, resp_bytes->responseType);
// int len = BIO_read(bio, buf, sizeof(buf));
// BIO_reset(bio);
zeek::Args vl;
vl.reserve(8);
// get the basic response
basic_resp = OCSP_response_get1_basic(resp);
if ( !basic_resp )
if ( ! basic_resp )
goto clean_up;
#if ( OPENSSL_VERSION_NUMBER < 0x10100000L ) || defined(LIBRESSL_VERSION_NUMBER)
resp_data = basic_resp->tbsResponseData;
if ( !resp_data )
if ( ! resp_data )
goto clean_up;
#endif
@ -523,11 +513,11 @@ void OCSP::ParseResponse(OCSP_RESPONSE *resp)
resp_count = OCSP_resp_count(basic_resp);
for ( int i=0; i<resp_count; i++ )
for ( int i = 0; i < resp_count; i++ )
{
OCSP_SINGLERESP* single_resp = OCSP_resp_get0(basic_resp, i);
if ( !single_resp )
if ( ! single_resp )
continue;
zeek::Args rvl;
@ -553,10 +543,8 @@ void OCSP::ParseResponse(OCSP_RESPONSE *resp)
ASN1_GENERALIZEDTIME* this_update = nullptr;
ASN1_GENERALIZEDTIME* next_update = nullptr;
if ( ! OCSP_resp_find_status(basic_resp,
const_cast<OCSP_CERTID*>(cert_id),
&status, &reason, &revoke_time,
&this_update, &next_update) )
if ( ! OCSP_resp_find_status(basic_resp, const_cast<OCSP_CERTID*>(cert_id), &status,
&reason, &revoke_time, &this_update, &next_update) )
reporter->Weird("OpenSSL failed to find status of OCSP response");
const char* cert_status_str = OCSP_cert_status_str(status);
@ -565,7 +553,8 @@ void OCSP::ParseResponse(OCSP_RESPONSE *resp)
// revocation time and reason if revoked
if ( status == V_OCSP_CERTSTATUS_REVOKED )
{
rvl.emplace_back(make_intrusive<TimeVal>(GetTimeFromAsn1(revoke_time, GetFile(), reporter)));
rvl.emplace_back(
make_intrusive<TimeVal>(GetTimeFromAsn1(revoke_time, GetFile(), reporter)));
if ( reason != OCSP_REVOKED_STATUS_NOSTATUS )
{
@ -582,12 +571,14 @@ void OCSP::ParseResponse(OCSP_RESPONSE *resp)
}
if ( this_update )
rvl.emplace_back(make_intrusive<TimeVal>(GetTimeFromAsn1(this_update, GetFile(), reporter)));
rvl.emplace_back(
make_intrusive<TimeVal>(GetTimeFromAsn1(this_update, GetFile(), reporter)));
else
rvl.emplace_back(make_intrusive<TimeVal>(0.0));
if ( next_update )
rvl.emplace_back(make_intrusive<TimeVal>(GetTimeFromAsn1(next_update, GetFile(), reporter)));
rvl.emplace_back(
make_intrusive<TimeVal>(GetTimeFromAsn1(next_update, GetFile(), reporter)));
else
rvl.emplace_back(make_intrusive<TimeVal>(0.0));
@ -614,10 +605,10 @@ void OCSP::ParseResponse(OCSP_RESPONSE *resp)
vl.emplace_back(parse_basic_resp_sig_alg(basic_resp, bio, buf, sizeof(buf)));
#endif
//i2a_ASN1_OBJECT(bio, basic_resp->signature);
//len = BIO_read(bio, buf, sizeof(buf));
//ocsp_resp_record->Assign(7, make_intrusive<StringVal>(len, buf));
//BIO_reset(bio);
// i2a_ASN1_OBJECT(bio, basic_resp->signature);
// len = BIO_read(bio, buf, sizeof(buf));
// ocsp_resp_record->Assign(7, make_intrusive<StringVal>(len, buf));
// BIO_reset(bio);
certs_vector = new VectorVal(id::find_type<VectorType>("x509_opaque_vector"));
vl.emplace_back(AdoptRef{}, certs_vector);
@ -631,16 +622,16 @@ void OCSP::ParseResponse(OCSP_RESPONSE *resp)
if ( certs )
{
int num_certs = sk_X509_num(certs);
for ( int i=0; i<num_certs; i++ )
for ( int i = 0; i < num_certs; i++ )
{
::X509 *this_cert = X509_dup(helper_sk_X509_value(certs, i));
::X509* this_cert = X509_dup(helper_sk_X509_value(certs, i));
//::X509 *this_cert = X509_dup(sk_X509_value(certs, i));
if (this_cert)
if ( this_cert )
certs_vector->Assign(i, make_intrusive<X509Val>(this_cert));
else
reporter->Weird("OpenSSL returned null certificate");
}
}
}
if ( ocsp_response_bytes )
event_mgr.Enqueue(ocsp_response_bytes, std::move(vl));
@ -657,16 +648,17 @@ void OCSP::ParseResponse(OCSP_RESPONSE *resp)
}
clean_up:
if (basic_resp)
if ( basic_resp )
OCSP_BASICRESP_free(basic_resp);
BIO_free(bio);
}
}
void OCSP::ParseExtensionsSpecific(X509_EXTENSION* ex, bool global, ASN1_OBJECT* ext_asn, const char* oid)
void OCSP::ParseExtensionsSpecific(X509_EXTENSION* ex, bool global, ASN1_OBJECT* ext_asn,
const char* oid)
{
// In OpenSSL 1.0.2+, we can get the extension by using NID_ct_cert_scts.
// In OpenSSL <= 1.0.1, this is not yet defined yet, so we have to manually
// look it up by performing a string comparison on the oid.
// In OpenSSL 1.0.2+, we can get the extension by using NID_ct_cert_scts.
// In OpenSSL <= 1.0.1, this is not yet defined yet, so we have to manually
// look it up by performing a string comparison on the oid.
#ifdef NID_ct_cert_scts
if ( OBJ_obj2nid(ext_asn) == NID_ct_cert_scts )
#else
@ -675,4 +667,4 @@ void OCSP::ParseExtensionsSpecific(X509_EXTENSION* ex, bool global, ASN1_OBJECT*
ParseSignedCertificateTimestamps(ex);
}
} // namespace zeek::file_analysis::detail
} // namespace zeek::file_analysis::detail

View file

@ -2,18 +2,21 @@
#pragma once
#include <string>
#include <openssl/ocsp.h>
#include <string>
#include "zeek/file_analysis/analyzer/x509/X509Common.h"
namespace zeek::file_analysis {
namespace zeek::file_analysis
{
class File;
namespace detail {
namespace detail
{
class OCSP : public file_analysis::detail::X509Common {
class OCSP : public file_analysis::detail::X509Common
{
public:
bool DeliverStream(const u_char* data, uint64_t len) override;
bool Undelivered(uint64_t offset, uint64_t len) override;
@ -21,8 +24,7 @@ public:
static file_analysis::Analyzer* InstantiateRequest(RecordValPtr args,
file_analysis::File* file);
static file_analysis::Analyzer* InstantiateReply(RecordValPtr args,
file_analysis::File* file);
static file_analysis::Analyzer* InstantiateReply(RecordValPtr args, file_analysis::File* file);
protected:
OCSP(RecordValPtr args, file_analysis::File* file, bool request);
@ -34,7 +36,7 @@ private:
std::string ocsp_data;
bool request = false; // true if ocsp request, false if reply
};
};
} // namespace detail
} // namespace zeek::file_analysis
} // namespace detail
} // namespace zeek::file_analysis

View file

@ -1,19 +1,25 @@
// See the file in the main distribution directory for copyright.
#include "zeek/plugin/Plugin.h"
#include "zeek/file_analysis/Component.h"
#include "zeek/file_analysis/analyzer/x509/X509.h"
#include "zeek/file_analysis/analyzer/x509/OCSP.h"
#include "zeek/file_analysis/analyzer/x509/X509.h"
namespace zeek::plugin::detail::Zeek_X509 {
namespace zeek::plugin::detail::Zeek_X509
{
class Plugin : public zeek::plugin::Plugin {
class Plugin : public zeek::plugin::Plugin
{
public:
zeek::plugin::Configuration Configure() override
{
AddComponent(new zeek::file_analysis::Component("X509", zeek::file_analysis::detail::X509::Instantiate));
AddComponent(new zeek::file_analysis::Component("OCSP_REQUEST", zeek::file_analysis::detail::OCSP::InstantiateRequest));
AddComponent(new zeek::file_analysis::Component("OCSP_REPLY", zeek::file_analysis::detail::OCSP::InstantiateReply));
AddComponent(new zeek::file_analysis::Component(
"X509", zeek::file_analysis::detail::X509::Instantiate));
AddComponent(new zeek::file_analysis::Component(
"OCSP_REQUEST", zeek::file_analysis::detail::OCSP::InstantiateRequest));
AddComponent(new zeek::file_analysis::Component(
"OCSP_REPLY", zeek::file_analysis::detail::OCSP::InstantiateReply));
zeek::plugin::Configuration config;
config.name = "Zeek::X509";
@ -26,6 +32,6 @@ public:
zeek::plugin::Plugin::Done();
zeek::file_analysis::detail::X509::FreeRootStore();
}
} plugin;
} plugin;
} // namespace zeek::plugin::detail::Zeek_X509
} // namespace zeek::plugin::detail::Zeek_X509

View file

@ -2,30 +2,27 @@
#include "zeek/file_analysis/analyzer/x509/X509.h"
#include <string>
#include <broker/data.hh>
#include <broker/error.hh>
#include <broker/expected.hh>
#include <broker/data.hh>
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/opensslconf.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/asn1.h>
#include <openssl/opensslconf.h>
#include <openssl/err.h>
#include <string>
#include "zeek/Event.h"
#include "zeek/file_analysis/File.h"
#include "zeek/file_analysis/Manager.h"
#include "zeek/file_analysis/analyzer/x509/events.bif.h"
#include "zeek/file_analysis/analyzer/x509/types.bif.h"
namespace zeek::file_analysis::detail {
namespace zeek::file_analysis::detail
{
X509::X509(RecordValPtr args, file_analysis::File* file)
: X509Common::X509Common(file_mgr->GetComponentTag("X509"),
std::move(args), file)
: X509Common::X509Common(file_mgr->GetComponentTag("X509"), std::move(args), file)
{
cert_data.clear();
}
@ -86,9 +83,7 @@ bool X509::EndOfFile()
// and send the record on to scriptland
if ( x509_certificate )
event_mgr.Enqueue(x509_certificate,
GetFile()->ToVal(),
IntrusivePtr{NewRef{}, cert_val},
event_mgr.Enqueue(x509_certificate, GetFile()->ToVal(), IntrusivePtr{NewRef{}, cert_val},
cert_record);
// after parsing the certificate - parse the extensions...
@ -113,8 +108,7 @@ bool X509::EndOfFile()
return false;
}
RecordValPtr X509::ParseCertificate(X509Val* cert_val,
file_analysis::File* f)
RecordValPtr X509::ParseCertificate(X509Val* cert_val, file_analysis::File* f)
{
::X509* ssl_cert = cert_val->GetCertificate();
@ -122,7 +116,7 @@ RecordValPtr X509::ParseCertificate(X509Val* cert_val,
memset(buf, 0, sizeof(buf));
auto pX509Cert = make_intrusive<RecordVal>(BifType::Record::X509::Certificate);
BIO *bio = BIO_new(BIO_s_mem());
BIO* bio = BIO_new(BIO_s_mem());
pX509Cert->Assign(0, static_cast<uint64_t>(X509_get_version(ssl_cert) + 1));
i2a_ASN1_INTEGER(bio, X509_get_serialNumber(ssl_cert));
@ -135,7 +129,7 @@ RecordValPtr X509::ParseCertificate(X509Val* cert_val,
pX509Cert->Assign(2, make_intrusive<StringVal>(len, buf));
BIO_reset(bio);
X509_NAME *subject_name = X509_get_subject_name(ssl_cert);
X509_NAME* subject_name = X509_get_subject_name(ssl_cert);
// extract the most specific (last) common name from the subject
int namepos = -1;
for ( ;; )
@ -150,7 +144,8 @@ RecordValPtr X509::ParseCertificate(X509Val* cert_val,
if ( namepos != -1 )
{
// we found a common name
ASN1_STRING_print(bio, X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject_name, namepos)));
ASN1_STRING_print(bio,
X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject_name, namepos)));
len = BIO_gets(bio, buf, sizeof(buf));
pX509Cert->Assign(4, make_intrusive<StringVal>(len, buf));
BIO_reset(bio);
@ -167,7 +162,7 @@ RecordValPtr X509::ParseCertificate(X509Val* cert_val,
// we only read 255 bytes because byte 256 is always 0.
// if the string is longer than 255, that will be our null-termination,
// otherwhise i2t does null-terminate.
ASN1_OBJECT *algorithm;
ASN1_OBJECT* algorithm;
X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(ssl_cert));
if ( ! i2t_ASN1_OBJECT(buf, 255, algorithm) )
buf[0] = 0;
@ -182,11 +177,13 @@ RecordValPtr X509::ParseCertificate(X509Val* cert_val,
if ( OBJ_obj2nid(algorithm) == NID_md5WithRSAEncryption )
{
ASN1_OBJECT *copy = OBJ_dup(algorithm); // the next line will destroy the original algorithm.
X509_PUBKEY_set0_param(X509_get_X509_PUBKEY(ssl_cert), OBJ_nid2obj(NID_rsaEncryption), 0, NULL, NULL, 0);
ASN1_OBJECT* copy =
OBJ_dup(algorithm); // the next line will destroy the original algorithm.
X509_PUBKEY_set0_param(X509_get_X509_PUBKEY(ssl_cert), OBJ_nid2obj(NID_rsaEncryption), 0,
NULL, NULL, 0);
algorithm = copy;
// we do not have to worry about freeing algorithm in that case - since it will be re-assigned using
// set0_param and the cert will take ownership.
// we do not have to worry about freeing algorithm in that case - since it will be
// re-assigned using set0_param and the cert will take ownership.
}
else
algorithm = 0;
@ -197,7 +194,7 @@ RecordValPtr X509::ParseCertificate(X509Val* cert_val,
pX509Cert->Assign(8, buf);
// Things we can do when we have the key...
EVP_PKEY *pkey = X509_extract_key(ssl_cert);
EVP_PKEY* pkey = X509_extract_key(ssl_cert);
if ( pkey != NULL )
{
if ( EVP_PKEY_base_id(pkey) == EVP_PKEY_DSA )
@ -207,9 +204,9 @@ RecordValPtr X509::ParseCertificate(X509Val* cert_val,
{
pX509Cert->Assign(9, "rsa");
const BIGNUM *e;
const BIGNUM* e;
RSA_get0_key(EVP_PKEY_get0_RSA(pkey), NULL, &e, NULL);
char *exponent = BN_bn2dec(e);
char* exponent = BN_bn2dec(e);
if ( exponent != NULL )
{
pX509Cert->Assign(11, exponent);
@ -225,8 +222,8 @@ RecordValPtr X509::ParseCertificate(X509Val* cert_val,
}
#endif
// set key algorithm back. We do not have to free the value that we created because (I think) it
// comes out of a static array from OpenSSL memory.
// set key algorithm back. We do not have to free the value that we created because (I
// think) it comes out of a static array from OpenSSL memory.
if ( algorithm )
X509_PUBKEY_set0_param(X509_get_X509_PUBKEY(ssl_cert), algorithm, 0, NULL, NULL, 0);
@ -237,7 +234,6 @@ RecordValPtr X509::ParseCertificate(X509Val* cert_val,
EVP_PKEY_free(pkey);
}
return pX509Cert;
}
@ -261,7 +257,8 @@ X509_STORE* X509::GetRootStore(TableVal* root_certs)
::X509* x = d2i_X509(NULL, &data, sv->Len());
if ( ! x )
{
emit_builtin_error(util::fmt("Root CA error: %s", ERR_error_string(ERR_get_error(), NULL)));
emit_builtin_error(
util::fmt("Root CA error: %s", ERR_error_string(ERR_get_error(), NULL)));
return nullptr;
}
@ -285,22 +282,22 @@ void X509::ParseBasicConstraints(X509_EXTENSION* ex)
{
assert(OBJ_obj2nid(X509_EXTENSION_get_object(ex)) == NID_basic_constraints);
BASIC_CONSTRAINTS *constr = (BASIC_CONSTRAINTS *) X509V3_EXT_d2i(ex);
BASIC_CONSTRAINTS* constr = (BASIC_CONSTRAINTS*)X509V3_EXT_d2i(ex);
if ( constr )
{
if ( x509_ext_basic_constraints )
{
auto pBasicConstraint = make_intrusive<RecordVal>(BifType::Record::X509::BasicConstraints);
auto pBasicConstraint =
make_intrusive<RecordVal>(BifType::Record::X509::BasicConstraints);
pBasicConstraint->Assign(0, constr->ca);
if ( constr->pathlen )
pBasicConstraint->Assign(1, static_cast<int32_t>(ASN1_INTEGER_get(constr->pathlen)));
pBasicConstraint->Assign(1,
static_cast<int32_t>(ASN1_INTEGER_get(constr->pathlen)));
event_mgr.Enqueue(x509_ext_basic_constraints,
GetFile()->ToVal(),
std::move(pBasicConstraint)
);
event_mgr.Enqueue(x509_ext_basic_constraints, GetFile()->ToVal(),
std::move(pBasicConstraint));
}
BASIC_CONSTRAINTS_free(constr);
@ -310,7 +307,8 @@ void X509::ParseBasicConstraints(X509_EXTENSION* ex)
reporter->Weird(GetFile(), "x509_invalid_basic_constraint");
}
void X509::ParseExtensionsSpecific(X509_EXTENSION* ex, bool global, ASN1_OBJECT* ext_asn, const char* oid)
void X509::ParseExtensionsSpecific(X509_EXTENSION* ex, bool global, ASN1_OBJECT* ext_asn,
const char* oid)
{
// look if we have a specialized handler for this event...
if ( OBJ_obj2nid(ext_asn) == NID_basic_constraints )
@ -319,9 +317,9 @@ void X509::ParseExtensionsSpecific(X509_EXTENSION* ex, bool global, ASN1_OBJECT*
else if ( OBJ_obj2nid(ext_asn) == NID_subject_alt_name )
ParseSAN(ex);
// In OpenSSL 1.0.2+, we can get the extension by using NID_ct_precert_scts.
// In OpenSSL <= 1.0.1, this is not yet defined yet, so we have to manually
// look it up by performing a string comparison on the oid.
// In OpenSSL 1.0.2+, we can get the extension by using NID_ct_precert_scts.
// In OpenSSL <= 1.0.1, this is not yet defined yet, so we have to manually
// look it up by performing a string comparison on the oid.
#ifdef NID_ct_precert_scts
else if ( OBJ_obj2nid(ext_asn) == NID_ct_precert_scts )
#else
@ -334,7 +332,7 @@ void X509::ParseSAN(X509_EXTENSION* ext)
{
assert(OBJ_obj2nid(X509_EXTENSION_get_object(ext)) == NID_subject_alt_name);
GENERAL_NAMES *altname = (GENERAL_NAMES*)X509V3_EXT_d2i(ext);
GENERAL_NAMES* altname = (GENERAL_NAMES*)X509V3_EXT_d2i(ext);
if ( ! altname )
{
reporter->Weird(GetFile(), "x509_san_parse_error");
@ -350,7 +348,7 @@ void X509::ParseSAN(X509_EXTENSION* ext)
for ( int i = 0; i < sk_GENERAL_NAME_num(altname); i++ )
{
GENERAL_NAME *gen = sk_GENERAL_NAME_value(altname, i);
GENERAL_NAME* gen = sk_GENERAL_NAME_value(altname, i);
assert(gen);
if ( gen->type == GEN_DNS || gen->type == GEN_URI || gen->type == GEN_EMAIL )
@ -363,9 +361,9 @@ void X509::ParseSAN(X509_EXTENSION* ext)
auto len = ASN1_STRING_length(gen->d.ia5);
#if ( OPENSSL_VERSION_NUMBER < 0x10100000L ) || defined(LIBRESSL_VERSION_NUMBER)
const char* name = (const char*) ASN1_STRING_data(gen->d.ia5);
const char* name = (const char*)ASN1_STRING_data(gen->d.ia5);
#else
const char* name = (const char*) ASN1_STRING_get0_data(gen->d.ia5);
const char* name = (const char*)ASN1_STRING_get0_data(gen->d.ia5);
#endif
auto bs = make_intrusive<StringVal>(len, name);
@ -396,52 +394,51 @@ void X509::ParseSAN(X509_EXTENSION* ext)
else if ( gen->type == GEN_IPADD )
{
if ( ips == nullptr )
ips = make_intrusive<VectorVal>(id::find_type<VectorType>("addr_vec"));
if ( ips == nullptr )
ips = make_intrusive<VectorVal>(id::find_type<VectorType>("addr_vec"));
uint32_t* addr = (uint32_t*) gen->d.ip->data;
uint32_t* addr = (uint32_t*)gen->d.ip->data;
if( gen->d.ip->length == 4 )
ips->Assign(ips->Size(), make_intrusive<AddrVal>(*addr));
if ( gen->d.ip->length == 4 )
ips->Assign(ips->Size(), make_intrusive<AddrVal>(*addr));
else if ( gen->d.ip->length == 16 )
ips->Assign(ips->Size(), make_intrusive<AddrVal>(addr));
else if ( gen->d.ip->length == 16 )
ips->Assign(ips->Size(), make_intrusive<AddrVal>(addr));
else
{
reporter->Weird(GetFile(), "x509_san_ip_length", util::fmt("%d", gen->d.ip->length));
continue;
}
else
{
reporter->Weird(GetFile(), "x509_san_ip_length",
util::fmt("%d", gen->d.ip->length));
continue;
}
}
else
{
// reporter->Error("Subject alternative name contained unsupported fields. fuid %s", GetFile()->GetID().c_str());
// This happens quite often - just mark it
// reporter->Error("Subject alternative name contained unsupported fields. fuid %s",
// GetFile()->GetID().c_str()); This happens quite often - just mark it
otherfields = true;
continue;
}
}
auto sanExt = make_intrusive<RecordVal>(BifType::Record::X509::SubjectAlternativeName);
auto sanExt = make_intrusive<RecordVal>(BifType::Record::X509::SubjectAlternativeName);
if ( names != nullptr )
sanExt->Assign(0, names);
if ( names != nullptr )
sanExt->Assign(0, names);
if ( uris != nullptr )
sanExt->Assign(1, uris);
if ( uris != nullptr )
sanExt->Assign(1, uris);
if ( emails != nullptr )
sanExt->Assign(2, emails);
if ( emails != nullptr )
sanExt->Assign(2, emails);
if ( ips != nullptr )
sanExt->Assign(3, ips);
if ( ips != nullptr )
sanExt->Assign(3, ips);
sanExt->Assign(4, otherfields);
sanExt->Assign(4, otherfields);
event_mgr.Enqueue(x509_ext_subject_alternative_name,
GetFile()->ToVal(),
std::move(sanExt));
event_mgr.Enqueue(x509_ext_subject_alternative_name, GetFile()->ToVal(), std::move(sanExt));
GENERAL_NAMES_free(altname);
}
@ -459,7 +456,7 @@ StringValPtr X509::KeyCurve(EVP_PKEY* key)
return nullptr;
}
const EC_GROUP *group;
const EC_GROUP* group;
int nid;
if ( (group = EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(key))) == NULL )
// I guess we could not parse this
@ -470,7 +467,7 @@ StringValPtr X509::KeyCurve(EVP_PKEY* key)
// and an invalid nid...
return nullptr;
const char * curve_name = OBJ_nid2sn(nid);
const char* curve_name = OBJ_nid2sn(nid);
if ( curve_name == nullptr )
return nullptr;
@ -478,53 +475,54 @@ StringValPtr X509::KeyCurve(EVP_PKEY* key)
#endif
}
unsigned int X509::KeyLength(EVP_PKEY *key)
unsigned int X509::KeyLength(EVP_PKEY* key)
{
assert(key != NULL);
switch(EVP_PKEY_base_id(key)) {
case EVP_PKEY_RSA:
const BIGNUM *n;
RSA_get0_key(EVP_PKEY_get0_RSA(key), &n, NULL, NULL);
return BN_num_bits(n);
switch ( EVP_PKEY_base_id(key) )
{
case EVP_PKEY_RSA:
const BIGNUM* n;
RSA_get0_key(EVP_PKEY_get0_RSA(key), &n, NULL, NULL);
return BN_num_bits(n);
case EVP_PKEY_DSA:
const BIGNUM *p;
DSA_get0_pqg(EVP_PKEY_get0_DSA(key), &p, NULL, NULL);
return BN_num_bits(p);
case EVP_PKEY_DSA:
const BIGNUM* p;
DSA_get0_pqg(EVP_PKEY_get0_DSA(key), &p, NULL, NULL);
return BN_num_bits(p);
#ifndef OPENSSL_NO_EC
case EVP_PKEY_EC:
{
BIGNUM* ec_order = BN_new();
if ( ! ec_order )
// could not malloc bignum?
return 0;
case EVP_PKEY_EC:
{
BIGNUM* ec_order = BN_new();
if ( ! ec_order )
// could not malloc bignum?
return 0;
const EC_GROUP *group = EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(key));
const EC_GROUP* group = EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(key));
if ( ! group )
{
// unknown ex-group
BN_free(ec_order);
return 0;
}
if ( ! group )
{
// unknown ex-group
BN_free(ec_order);
return 0;
}
if ( ! EC_GROUP_get_order(group, ec_order, NULL) )
{
// could not get ec-group-order
BN_free(ec_order);
return 0;
}
if ( ! EC_GROUP_get_order(group, ec_order, NULL) )
{
// could not get ec-group-order
BN_free(ec_order);
return 0;
}
unsigned int length = BN_num_bits(ec_order);
BN_free(ec_order);
return length;
}
unsigned int length = BN_num_bits(ec_order);
BN_free(ec_order);
return length;
}
#endif
default:
return 0; // unknown public key type
}
default:
return 0; // unknown public key type
}
reporter->InternalError("cannot be reached");
}
@ -563,7 +561,7 @@ IMPLEMENT_OPAQUE_VALUE(X509Val)
broker::expected<broker::data> X509Val::DoSerialize() const
{
unsigned char *buf = nullptr;
unsigned char* buf = nullptr;
int length = i2d_X509(certificate, &buf);
if ( length < 0 )
@ -586,4 +584,4 @@ bool X509Val::DoUnserialize(const broker::data& data)
return (certificate != nullptr);
}
} // namespace zeek::file_analysis::detail
} // namespace zeek::file_analysis::detail

View file

@ -2,12 +2,12 @@
#pragma once
#include <string>
#include <map>
#include <string>
#include "zeek/Func.h"
#include "zeek/OpaqueVal.h"
#include "zeek/file_analysis/analyzer/x509/X509Common.h"
#include "zeek/Func.h"
#if ( OPENSSL_VERSION_NUMBER < 0x10002000L ) || defined(LIBRESSL_VERSION_NUMBER)
@ -17,57 +17,57 @@
#if ( OPENSSL_VERSION_NUMBER < 0x1010000fL ) || defined(LIBRESSL_VERSION_NUMBER)
#define X509_OBJECT_new() (X509_OBJECT*)malloc(sizeof(X509_OBJECT))
#define X509_OBJECT_new() (X509_OBJECT*)malloc(sizeof(X509_OBJECT))
#define X509_OBJECT_free(a) free(a)
#define OCSP_resp_get0_certs(x) (x)->certs
#define OCSP_resp_get0_certs(x) (x)->certs
#define EVP_PKEY_get0_DSA(p) ((p)->pkey.dsa)
#define EVP_PKEY_get0_DSA(p) ((p)->pkey.dsa)
#define EVP_PKEY_get0_EC_KEY(p) ((p)->pkey.ec)
#define EVP_PKEY_get0_RSA(p) ((p)->pkey.rsa)
#define EVP_PKEY_get0_RSA(p) ((p)->pkey.rsa)
#if !defined(LIBRESSL_VERSION_NUMBER) || ( LIBRESSL_VERSION_NUMBER < 0x2070000fL )
#if ! defined(LIBRESSL_VERSION_NUMBER) || (LIBRESSL_VERSION_NUMBER < 0x2070000fL)
#define OCSP_SINGLERESP_get0_id(s) (s)->certId
static X509 *X509_OBJECT_get0_X509(const X509_OBJECT *a)
{
static X509* X509_OBJECT_get0_X509(const X509_OBJECT* a)
{
if ( a == nullptr || a->type != X509_LU_X509 )
return nullptr;
return a->data.x509;
}
}
static void DSA_get0_pqg(const DSA *d,
const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
{
static void DSA_get0_pqg(const DSA* d, const BIGNUM** p, const BIGNUM** q, const BIGNUM** g)
{
if ( p != nullptr )
*p = d->p;
if ( q != nullptr )
*q = d->q;
if ( g != nullptr )
*g = d->g;
}
}
static void RSA_get0_key(const RSA *r,
const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
{
static void RSA_get0_key(const RSA* r, const BIGNUM** n, const BIGNUM** e, const BIGNUM** d)
{
if ( n != nullptr )
*n = r->n;
if ( e != nullptr )
*e = r->e;
if ( d != nullptr )
*d = r->d;
}
}
#endif
#endif
namespace zeek::file_analysis::detail {
namespace zeek::file_analysis::detail
{
class X509Val;
class X509 : public file_analysis::detail::X509Common {
class X509 : public file_analysis::detail::X509Common
{
public:
bool DeliverStream(const u_char* data, uint64_t len) override;
bool Undelivered(uint64_t offset, uint64_t len) override;
@ -88,9 +88,10 @@ public:
*/
static RecordValPtr ParseCertificate(X509Val* cert_val, file_analysis::File* file = nullptr);
static file_analysis::Analyzer* Instantiate(RecordValPtr args,
file_analysis::File* file)
{ return new X509(std::move(args), file); }
static file_analysis::Analyzer* Instantiate(RecordValPtr args, file_analysis::File* file)
{
return new X509(std::move(args), file);
}
/**
* Retrieves OpenSSL's representation of an X509 certificate store
@ -117,14 +118,15 @@ public:
/**
* Sets the table[string] that used as the certificate cache inside of Zeek.
*/
static void SetCertificateCache(TableValPtr cache)
{ certificate_cache = std::move(cache); }
static void SetCertificateCache(TableValPtr cache) { certificate_cache = std::move(cache); }
/**
* Sets the callback when a certificate cache hit is encountered
*/
static void SetCertificateCacheHitCallback(FuncPtr func)
{ cache_hit_callback = std::move(func); }
{
cache_hit_callback = std::move(func);
}
protected:
X509(RecordValPtr args, file_analysis::File* file);
@ -138,12 +140,12 @@ private:
// Helpers for ParseCertificate.
static StringValPtr KeyCurve(EVP_PKEY* key);
static unsigned int KeyLength(EVP_PKEY *key);
static unsigned int KeyLength(EVP_PKEY* key);
/** X509 stores associated with global script-layer values */
inline static std::map<Val*, X509_STORE*> x509_stores = std::map<Val*, X509_STORE*>();
inline static TableValPtr certificate_cache = nullptr;
inline static FuncPtr cache_hit_callback = nullptr;
};
};
/**
* This class wraps an OpenSSL X509 data structure.
@ -152,7 +154,8 @@ private:
* script-land. Otherwise, we cannot verify certificates from Bro
* scriptland
*/
class X509Val : public OpaqueVal {
class X509Val : public OpaqueVal
{
public:
/**
* Construct an X509Val.
@ -194,6 +197,6 @@ protected:
DECLARE_OPAQUE_VALUE(X509Val)
private:
::X509* certificate; // the wrapped certificate
};
};
} // namespace zeek::file_analysis::detail
} // namespace zeek::file_analysis::detail

View file

@ -2,23 +2,22 @@
#include "zeek/file_analysis/analyzer/x509/X509Common.h"
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/opensslconf.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/asn1.h>
#include <openssl/opensslconf.h>
#include <openssl/err.h>
#include "zeek/Reporter.h"
#include "zeek/file_analysis/analyzer/x509/x509-extension_pac.h"
#include "zeek/file_analysis/analyzer/x509/events.bif.h"
#include "zeek/file_analysis/analyzer/x509/ocsp_events.bif.h"
#include "zeek/file_analysis/analyzer/x509/types.bif.h"
#include "zeek/file_analysis/analyzer/x509/x509-extension_pac.h"
namespace zeek::file_analysis::detail {
namespace zeek::file_analysis::detail
{
X509Common::X509Common(const file_analysis::Tag& arg_tag,
RecordValPtr arg_args,
X509Common::X509Common(const file_analysis::Tag& arg_tag, RecordValPtr arg_args,
file_analysis::File* arg_file)
: file_analysis::Analyzer(arg_tag, std::move(arg_args), arg_file)
{
@ -32,14 +31,15 @@ static void EmitWeird(const char* name, file_analysis::File* file, const char* a
reporter->Weird(name);
}
double X509Common::GetTimeFromAsn1(const ASN1_TIME* atime, file_analysis::File* f, Reporter* reporter)
double X509Common::GetTimeFromAsn1(const ASN1_TIME* atime, file_analysis::File* f,
Reporter* reporter)
{
time_t lResult = 0;
char lBuffer[26];
char* pBuffer = lBuffer;
const char *pString = (const char *) atime->data;
const char* pString = (const char*)atime->data;
unsigned int remaining = atime->length;
if ( atime->type == V_ASN1_UTCTIME )
@ -50,7 +50,7 @@ double X509Common::GetTimeFromAsn1(const ASN1_TIME* atime, file_analysis::File*
return 0;
}
if ( pString[remaining-1] != 'Z' )
if ( pString[remaining - 1] != 'Z' )
{
// not valid according to RFC 2459 4.1.2.5.1
EmitWeird("x509_utc_format", f);
@ -145,7 +145,7 @@ double X509Common::GetTimeFromAsn1(const ASN1_TIME* atime, file_analysis::File*
return 0;
}
if ((*pString != '+') && (*pString != '-'))
if ( (*pString != '+') && (*pString != '-') )
{
EmitWeird("x509_time_offset_type", f);
return 0;
@ -154,31 +154,32 @@ double X509Common::GetTimeFromAsn1(const ASN1_TIME* atime, file_analysis::File*
lSecondsFromUTC = ((pString[1] - '0') * 10 + (pString[2] - '0')) * 60;
lSecondsFromUTC += (pString[3] - '0') * 10 + (pString[4] - '0');
if (*pString == '-')
if ( *pString == '-' )
lSecondsFromUTC = -lSecondsFromUTC;
}
tm lTime;
lTime.tm_sec = ((lBuffer[12] - '0') * 10) + (lBuffer[13] - '0');
lTime.tm_min = ((lBuffer[10] - '0') * 10) + (lBuffer[11] - '0');
lTime.tm_sec = ((lBuffer[12] - '0') * 10) + (lBuffer[13] - '0');
lTime.tm_min = ((lBuffer[10] - '0') * 10) + (lBuffer[11] - '0');
lTime.tm_hour = ((lBuffer[8] - '0') * 10) + (lBuffer[9] - '0');
lTime.tm_mday = ((lBuffer[6] - '0') * 10) + (lBuffer[7] - '0');
lTime.tm_mon = (((lBuffer[4] - '0') * 10) + (lBuffer[5] - '0')) - 1;
lTime.tm_year = (lBuffer[0] - '0') * 1000 + (lBuffer[1] - '0') * 100 + ((lBuffer[2] - '0') * 10) + (lBuffer[3] - '0');
lTime.tm_mon = (((lBuffer[4] - '0') * 10) + (lBuffer[5] - '0')) - 1;
lTime.tm_year = (lBuffer[0] - '0') * 1000 + (lBuffer[1] - '0') * 100 +
((lBuffer[2] - '0') * 10) + (lBuffer[3] - '0');
if ( lTime.tm_year > 1900)
if ( lTime.tm_year > 1900 )
lTime.tm_year -= 1900;
lTime.tm_wday = 0;
lTime.tm_yday = 0;
lTime.tm_isdst = 0; // No DST adjustment requested
lTime.tm_isdst = 0; // No DST adjustment requested
lResult = mktime(&lTime);
if ( lResult )
{
if ( lTime.tm_isdst != 0 )
lResult -= 3600; // mktime may adjust for DST (OS dependent)
if ( lTime.tm_isdst != 0 )
lResult -= 3600; // mktime may adjust for DST (OS dependent)
lResult += lSecondsFromUTC;
}
@ -187,7 +188,7 @@ double X509Common::GetTimeFromAsn1(const ASN1_TIME* atime, file_analysis::File*
lResult = 0;
return lResult;
}
}
void X509Common::ParseSignedCertificateTimestamps(X509_EXTENSION* ext)
{
@ -200,25 +201,28 @@ void X509Common::ParseSignedCertificateTimestamps(X509_EXTENSION* ext)
// the octet string of the extension contains the octet string which in turn
// contains the SCT. Obviously.
unsigned char* ext_val_copy = (unsigned char*) OPENSSL_malloc(ext_val->length);
unsigned char* ext_val_copy = (unsigned char*)OPENSSL_malloc(ext_val->length);
unsigned char* ext_val_second_pointer = ext_val_copy;
memcpy(ext_val_copy, ext_val->data, ext_val->length);
ASN1_OCTET_STRING* inner = d2i_ASN1_OCTET_STRING(NULL, (const unsigned char**) &ext_val_copy, ext_val->length);
if ( !inner )
ASN1_OCTET_STRING* inner =
d2i_ASN1_OCTET_STRING(NULL, (const unsigned char**)&ext_val_copy, ext_val->length);
if ( ! inner )
{
reporter->Error("X509::ParseSignedCertificateTimestamps could not parse inner octet string");
reporter->Error(
"X509::ParseSignedCertificateTimestamps could not parse inner octet string");
return;
}
binpac::X509Extension::MockConnection* conn = new binpac::X509Extension::MockConnection(this);
binpac::X509Extension::SignedCertTimestampExt* interp = new binpac::X509Extension::SignedCertTimestampExt(conn);
binpac::X509Extension::SignedCertTimestampExt* interp =
new binpac::X509Extension::SignedCertTimestampExt(conn);
try
{
interp->NewData(inner->data, inner->data + inner->length);
}
catch( const binpac::Exception& e )
catch ( const binpac::Exception& e )
{
// throw a warning or sth
reporter->Error("X509::ParseSignedCertificateTimestamps could not parse SCT");
@ -248,12 +252,12 @@ void X509Common::ParseExtension(X509_EXTENSION* ex, const EventHandlerPtr& h, bo
if ( X509_EXTENSION_get_critical(ex) != 0 )
critical = 1;
BIO *bio = BIO_new(BIO_s_mem());
if( ! X509V3_EXT_print(bio, ex, 0, 0))
BIO* bio = BIO_new(BIO_s_mem());
if ( ! X509V3_EXT_print(bio, ex, 0, 0) )
{
unsigned char *buf = nullptr;
unsigned char* buf = nullptr;
int len = i2d_ASN1_OCTET_STRING(X509_EXTENSION_get_data(ex), &buf);
if ( len >=0 )
if ( len >= 0 )
{
BIO_write(bio, buf, len);
OPENSSL_free(buf);
@ -290,9 +294,7 @@ void X509Common::ParseExtension(X509_EXTENSION* ex, const EventHandlerPtr& h, bo
// but I am not sure if there is a better way to do it...
if ( h == ocsp_extension )
event_mgr.Enqueue(h, GetFile()->ToVal(),
std::move(pX509Ext),
val_mgr->Bool(global));
event_mgr.Enqueue(h, GetFile()->ToVal(), std::move(pX509Ext), val_mgr->Bool(global));
else
event_mgr.Enqueue(h, GetFile()->ToVal(), std::move(pX509Ext));
@ -321,7 +323,7 @@ StringValPtr X509Common::GetExtensionFromBIO(BIO* bio, file_analysis::File* f)
return val_mgr->EmptyString();
}
char* buffer = (char*) malloc(length);
char* buffer = (char*)malloc(length);
if ( ! buffer )
{
@ -332,7 +334,7 @@ StringValPtr X509Common::GetExtensionFromBIO(BIO* bio, file_analysis::File* f)
return nullptr;
}
BIO_read(bio, (void*) buffer, length);
BIO_read(bio, (void*)buffer, length);
auto ext_val = make_intrusive<StringVal>(length, buffer);
free(buffer);
@ -341,4 +343,4 @@ StringValPtr X509Common::GetExtensionFromBIO(BIO* bio, file_analysis::File* f)
return ext_val;
}
} // namespace zeek::file_analysis::detail
} // namespace zeek::file_analysis::detail

View file

@ -5,12 +5,13 @@
#pragma once
#include <openssl/x509.h>
#include <openssl/asn1.h>
#include <openssl/x509.h>
#include "zeek/file_analysis/Analyzer.h"
namespace zeek {
namespace zeek
{
class EventHandlerPtr;
class Reporter;
@ -18,16 +19,19 @@ class StringVal;
template <class T> class IntrusivePtr;
using StringValPtr = IntrusivePtr<StringVal>;
namespace file_analysis {
namespace file_analysis
{
class File;
class Tag;
namespace detail {
namespace detail
{
class X509Common : public file_analysis::Analyzer {
class X509Common : public file_analysis::Analyzer
{
public:
~X509Common() override {};
~X509Common() override{};
/**
* Retrieve an X509 extension value from an OpenSSL BIO to which it was
@ -46,15 +50,14 @@ public:
Reporter* reporter);
protected:
X509Common(const file_analysis::Tag& arg_tag,
RecordValPtr arg_args,
X509Common(const file_analysis::Tag& arg_tag, RecordValPtr arg_args,
file_analysis::File* arg_file);
void ParseExtension(X509_EXTENSION* ex, const EventHandlerPtr& h, bool global);
void ParseSignedCertificateTimestamps(X509_EXTENSION* ext);
virtual void ParseExtensionsSpecific(X509_EXTENSION* ex, bool, ASN1_OBJECT*, const char*) = 0;
};
};
} // namespace detail
} // namespace file_analysis
} // namespace zeek
} // namespace detail
} // namespace file_analysis
} // namespace zeek