mirror of
https://github.com/zeek/zeek.git
synced 2025-10-04 15:48:19 +00:00
Reformat the world
This commit is contained in:
parent
194cb24547
commit
b2f171ec69
714 changed files with 35149 additions and 35203 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue