Reformat the world

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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