mirror of
https://github.com/zeek/zeek.git
synced 2025-10-06 08:38:20 +00:00
Make x509 certificates an opaque type
This commit is contained in:
parent
2b87499fd9
commit
2c7e7f962e
9 changed files with 114 additions and 117 deletions
|
@ -111,6 +111,7 @@ SERIAL_VAL(ENTROPY_VAL, 19)
|
||||||
SERIAL_VAL(TOPK_VAL, 20)
|
SERIAL_VAL(TOPK_VAL, 20)
|
||||||
SERIAL_VAL(BLOOMFILTER_VAL, 21)
|
SERIAL_VAL(BLOOMFILTER_VAL, 21)
|
||||||
SERIAL_VAL(CARDINALITY_VAL, 22)
|
SERIAL_VAL(CARDINALITY_VAL, 22)
|
||||||
|
SERIAL_VAL(X509_VAL, 23)
|
||||||
|
|
||||||
#define SERIAL_EXPR(name, val) SERIAL_CONST(name, val, EXPR)
|
#define SERIAL_EXPR(name, val) SERIAL_CONST(name, val, EXPR)
|
||||||
SERIAL_EXPR(EXPR, 1)
|
SERIAL_EXPR(EXPR, 1)
|
||||||
|
|
|
@ -616,6 +616,7 @@ extern OpaqueType* entropy_type;
|
||||||
extern OpaqueType* cardinality_type;
|
extern OpaqueType* cardinality_type;
|
||||||
extern OpaqueType* topk_type;
|
extern OpaqueType* topk_type;
|
||||||
extern OpaqueType* bloomfilter_type;
|
extern OpaqueType* bloomfilter_type;
|
||||||
|
extern OpaqueType* x509_opaque_type;
|
||||||
|
|
||||||
// Returns the BRO basic (non-parameterized) type with the given type.
|
// Returns the BRO basic (non-parameterized) type with the given type.
|
||||||
extern BroType* base_type(TypeTag tag);
|
extern BroType* base_type(TypeTag tag);
|
||||||
|
|
|
@ -22,8 +22,6 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
string orig_label(bool is_orig);
|
string orig_label(bool is_orig);
|
||||||
void free_X509(void *);
|
|
||||||
X509* d2i_X509_binpac(X509** px, const uint8** in, int len);
|
|
||||||
string handshake_type_label(int type);
|
string handshake_type_label(int type);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
@ -33,20 +31,6 @@ string orig_label(bool is_orig)
|
||||||
return string(is_orig ? "originator" :"responder");
|
return string(is_orig ? "originator" :"responder");
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_X509(void* cert)
|
|
||||||
{
|
|
||||||
X509_free((X509*) cert);
|
|
||||||
}
|
|
||||||
|
|
||||||
X509* d2i_X509_binpac(X509** px, const uint8** in, int len)
|
|
||||||
{
|
|
||||||
#ifdef OPENSSL_D2I_X509_USES_CONST_CHAR
|
|
||||||
return d2i_X509(px, in, len);
|
|
||||||
#else
|
|
||||||
return d2i_X509(px, (u_char**) in, len);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
string handshake_type_label(int type)
|
string handshake_type_label(int type)
|
||||||
{
|
{
|
||||||
switch ( type ) {
|
switch ( type ) {
|
||||||
|
|
|
@ -22,7 +22,6 @@ type uint24 = record {
|
||||||
};
|
};
|
||||||
|
|
||||||
string state_label(int state_nr);
|
string state_label(int state_nr);
|
||||||
double get_time_from_asn1(const ASN1_TIME * atime);
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
extern type to_int;
|
extern type to_int;
|
||||||
|
@ -146,105 +145,6 @@ enum AnalyzerState {
|
||||||
return string(fmt("UNKNOWN (%d)", state_nr));
|
return string(fmt("UNKNOWN (%d)", state_nr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
double get_time_from_asn1(const ASN1_TIME * atime)
|
|
||||||
{
|
|
||||||
time_t lResult = 0;
|
|
||||||
|
|
||||||
char lBuffer[24];
|
|
||||||
char * pBuffer = lBuffer;
|
|
||||||
|
|
||||||
size_t lTimeLength = atime->length;
|
|
||||||
char * pString = (char *) atime->data;
|
|
||||||
|
|
||||||
if ( atime->type == V_ASN1_UTCTIME )
|
|
||||||
{
|
|
||||||
if ( lTimeLength < 11 || lTimeLength > 17 )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
memcpy(pBuffer, pString, 10);
|
|
||||||
pBuffer += 10;
|
|
||||||
pString += 10;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ( lTimeLength < 13 )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
memcpy(pBuffer, pString, 12);
|
|
||||||
pBuffer += 12;
|
|
||||||
pString += 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((*pString == 'Z') || (*pString == '-') || (*pString == '+'))
|
|
||||||
{
|
|
||||||
*(pBuffer++) = '0';
|
|
||||||
*(pBuffer++) = '0';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*(pBuffer++) = *(pString++);
|
|
||||||
*(pBuffer++) = *(pString++);
|
|
||||||
|
|
||||||
// Skip any fractional seconds...
|
|
||||||
if (*pString == '.')
|
|
||||||
{
|
|
||||||
pString++;
|
|
||||||
while ((*pString >= '0') && (*pString <= '9'))
|
|
||||||
pString++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*(pBuffer++) = 'Z';
|
|
||||||
*(pBuffer++) = '\0';
|
|
||||||
|
|
||||||
time_t lSecondsFromUTC;
|
|
||||||
|
|
||||||
if ( *pString == 'Z' )
|
|
||||||
lSecondsFromUTC = 0;
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((*pString != '+') && (pString[5] != '-'))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
lSecondsFromUTC = ((pString[1]-'0') * 10 + (pString[2]-'0')) * 60;
|
|
||||||
lSecondsFromUTC += (pString[3]-'0') * 10 + (pString[4]-'0');
|
|
||||||
|
|
||||||
if (*pString == '-')
|
|
||||||
lSecondsFromUTC = -lSecondsFromUTC;
|
|
||||||
}
|
|
||||||
|
|
||||||
tm lTime;
|
|
||||||
lTime.tm_sec = ((lBuffer[10] - '0') * 10) + (lBuffer[11] - '0');
|
|
||||||
lTime.tm_min = ((lBuffer[8] - '0') * 10) + (lBuffer[9] - '0');
|
|
||||||
lTime.tm_hour = ((lBuffer[6] - '0') * 10) + (lBuffer[7] - '0');
|
|
||||||
lTime.tm_mday = ((lBuffer[4] - '0') * 10) + (lBuffer[5] - '0');
|
|
||||||
lTime.tm_mon = (((lBuffer[2] - '0') * 10) + (lBuffer[3] - '0')) - 1;
|
|
||||||
lTime.tm_year = ((lBuffer[0] - '0') * 10) + (lBuffer[1] - '0');
|
|
||||||
|
|
||||||
if ( lTime.tm_year < 50 )
|
|
||||||
lTime.tm_year += 100; // RFC 2459
|
|
||||||
|
|
||||||
lTime.tm_wday = 0;
|
|
||||||
lTime.tm_yday = 0;
|
|
||||||
lTime.tm_isdst = 0; // No DST adjustment requested
|
|
||||||
|
|
||||||
lResult = mktime(&lTime);
|
|
||||||
|
|
||||||
if ( lResult )
|
|
||||||
{
|
|
||||||
if ( 0 != lTime.tm_isdst )
|
|
||||||
lResult -= 3600; // mktime may adjust for DST (OS dependent)
|
|
||||||
|
|
||||||
lResult += lSecondsFromUTC;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
lResult = 0;
|
|
||||||
|
|
||||||
return lResult;
|
|
||||||
}
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
|
@ -6,5 +6,5 @@ include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
|
||||||
bro_plugin_begin(Bro X509)
|
bro_plugin_begin(Bro X509)
|
||||||
bro_plugin_cc(X509.cc Plugin.cc ../../Analyzer.cc)
|
bro_plugin_cc(X509.cc Plugin.cc ../../Analyzer.cc)
|
||||||
bro_plugin_bif(events.bif types.bif)
|
bro_plugin_bif(events.bif types.bif functions.bif)
|
||||||
bro_plugin_end()
|
bro_plugin_end()
|
||||||
|
|
|
@ -7,4 +7,5 @@ BRO_PLUGIN_BEGIN(Bro, X509)
|
||||||
BRO_PLUGIN_FILE_ANALYZER("X509", X509);
|
BRO_PLUGIN_FILE_ANALYZER("X509", X509);
|
||||||
BRO_PLUGIN_BIF_FILE(events);
|
BRO_PLUGIN_BIF_FILE(events);
|
||||||
BRO_PLUGIN_BIF_FILE(types);
|
BRO_PLUGIN_BIF_FILE(types);
|
||||||
|
BRO_PLUGIN_BIF_FILE(functions);
|
||||||
BRO_PLUGIN_END
|
BRO_PLUGIN_END
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
using namespace file_analysis;
|
using namespace file_analysis;
|
||||||
|
|
||||||
|
IMPLEMENT_SERIAL(X509Val, SER_X509_VAL);
|
||||||
|
|
||||||
file_analysis::X509::X509(RecordVal* args, file_analysis::File* file)
|
file_analysis::X509::X509(RecordVal* args, file_analysis::File* file)
|
||||||
: file_analysis::Analyzer(file_mgr->GetComponentTag("X509"), args, file)
|
: file_analysis::Analyzer(file_mgr->GetComponentTag("X509"), args, file)
|
||||||
{
|
{
|
||||||
|
@ -444,3 +446,65 @@ double file_analysis::X509::get_time_from_asn1(const ASN1_TIME * atime)
|
||||||
return lResult;
|
return lResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
X509Val::X509Val(::X509* arg_certificate) : OpaqueVal(x509_opaque_type)
|
||||||
|
{
|
||||||
|
certificate = arg_certificate;
|
||||||
|
}
|
||||||
|
|
||||||
|
X509Val::X509Val() : OpaqueVal(x509_opaque_type)
|
||||||
|
{
|
||||||
|
certificate = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
X509Val::~X509Val()
|
||||||
|
{
|
||||||
|
if ( certificate )
|
||||||
|
X509_free(certificate);
|
||||||
|
}
|
||||||
|
|
||||||
|
::X509* X509Val::GetCertificate() const
|
||||||
|
{
|
||||||
|
return certificate;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool X509Val::DoSerialize(SerialInfo* info) const
|
||||||
|
{
|
||||||
|
DO_SERIALIZE(SER_X509_VAL, X509Val);
|
||||||
|
|
||||||
|
unsigned char *buf = NULL;
|
||||||
|
|
||||||
|
int length = i2d_X509(certificate, &buf);
|
||||||
|
|
||||||
|
if ( length < 0 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool res = SERIALIZE_STR(reinterpret_cast<const char*>(buf), length);
|
||||||
|
|
||||||
|
OPENSSL_free(buf);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool X509Val::DoUnserialize(UnserialInfo* info)
|
||||||
|
{
|
||||||
|
DO_UNSERIALIZE(OpaqueVal)
|
||||||
|
|
||||||
|
int length;
|
||||||
|
unsigned char *certbuf, *opensslbuf;
|
||||||
|
|
||||||
|
if ( ! UNSERIALIZE_STR(reinterpret_cast<char **>(&certbuf), &length) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
opensslbuf = certbuf; // OpenSSL likes to shift pointers around. really.
|
||||||
|
certificate = d2i_X509(NULL, const_cast<const unsigned char**>(&opensslbuf), length);
|
||||||
|
delete[] certbuf;
|
||||||
|
|
||||||
|
if ( !certificate )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,50 @@ private:
|
||||||
std::string cert_data;
|
std::string cert_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class wraps an OpenSSL X509 data structure.
|
||||||
|
*
|
||||||
|
* We need these to be able to pass OpenSSL pointers around in Bro
|
||||||
|
* script-land. Otherwise, we cannot verify certificates from Bro
|
||||||
|
* scriptland
|
||||||
|
*/
|
||||||
|
class X509Val : public OpaqueVal {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Construct an X509Val.
|
||||||
|
*
|
||||||
|
* @param certificate specifies the wrapped OpenSSL certificate
|
||||||
|
*
|
||||||
|
* @return A newly initialized X509Val
|
||||||
|
*/
|
||||||
|
X509Val(::X509* certificate);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor.
|
||||||
|
*/
|
||||||
|
~X509Val();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the wrapped X509 certificate. Please take care, that the
|
||||||
|
* internal OpenSSL reference counting stays the same.
|
||||||
|
*
|
||||||
|
* @return The wrapped OpenSSL X509 certificate
|
||||||
|
*/
|
||||||
|
::X509* GetCertificate() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* Construct an empty X509Val. Only used for deserialization
|
||||||
|
*/
|
||||||
|
X509Val();
|
||||||
|
|
||||||
|
private:
|
||||||
|
::X509* certificate; // the wrapped certificate
|
||||||
|
|
||||||
|
DECLARE_SERIAL(X509Val);
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -131,6 +131,7 @@ OpaqueType* entropy_type = 0;
|
||||||
OpaqueType* cardinality_type = 0;
|
OpaqueType* cardinality_type = 0;
|
||||||
OpaqueType* topk_type = 0;
|
OpaqueType* topk_type = 0;
|
||||||
OpaqueType* bloomfilter_type = 0;
|
OpaqueType* bloomfilter_type = 0;
|
||||||
|
OpaqueType* x509_opaque_type = 0;
|
||||||
|
|
||||||
extern std::list<BroDoc*> docs_generated;
|
extern std::list<BroDoc*> docs_generated;
|
||||||
|
|
||||||
|
@ -860,6 +861,7 @@ int main(int argc, char** argv)
|
||||||
cardinality_type = new OpaqueType("cardinality");
|
cardinality_type = new OpaqueType("cardinality");
|
||||||
topk_type = new OpaqueType("topk");
|
topk_type = new OpaqueType("topk");
|
||||||
bloomfilter_type = new OpaqueType("bloomfilter");
|
bloomfilter_type = new OpaqueType("bloomfilter");
|
||||||
|
x509_opaque_type = new OpaqueType("x509");
|
||||||
|
|
||||||
// The leak-checker tends to produce some false
|
// The leak-checker tends to produce some false
|
||||||
// positives (memory which had already been
|
// positives (memory which had already been
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue