mirror of
https://github.com/zeek/zeek.git
synced 2025-10-12 03:28: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,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