diff --git a/src/SerialTypes.h b/src/SerialTypes.h index 69927afb74..81ccbc030e 100644 --- a/src/SerialTypes.h +++ b/src/SerialTypes.h @@ -111,6 +111,7 @@ SERIAL_VAL(ENTROPY_VAL, 19) SERIAL_VAL(TOPK_VAL, 20) SERIAL_VAL(BLOOMFILTER_VAL, 21) SERIAL_VAL(CARDINALITY_VAL, 22) +SERIAL_VAL(X509_VAL, 23) #define SERIAL_EXPR(name, val) SERIAL_CONST(name, val, EXPR) SERIAL_EXPR(EXPR, 1) diff --git a/src/Type.h b/src/Type.h index a6163d5152..b880eac131 100644 --- a/src/Type.h +++ b/src/Type.h @@ -616,6 +616,7 @@ extern OpaqueType* entropy_type; extern OpaqueType* cardinality_type; extern OpaqueType* topk_type; extern OpaqueType* bloomfilter_type; +extern OpaqueType* x509_opaque_type; // Returns the BRO basic (non-parameterized) type with the given type. extern BroType* base_type(TypeTag tag); diff --git a/src/analyzer/protocol/ssl/ssl-analyzer.pac b/src/analyzer/protocol/ssl/ssl-analyzer.pac index 4bf1e27d64..f9de1a12a8 100644 --- a/src/analyzer/protocol/ssl/ssl-analyzer.pac +++ b/src/analyzer/protocol/ssl/ssl-analyzer.pac @@ -22,8 +22,6 @@ }; 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); %} @@ -33,20 +31,6 @@ string orig_label(bool is_orig) 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) { switch ( type ) { diff --git a/src/analyzer/protocol/ssl/ssl-protocol.pac b/src/analyzer/protocol/ssl/ssl-protocol.pac index b35d07f18b..4f24251a5c 100644 --- a/src/analyzer/protocol/ssl/ssl-protocol.pac +++ b/src/analyzer/protocol/ssl/ssl-protocol.pac @@ -22,7 +22,6 @@ type uint24 = record { }; string state_label(int state_nr); - double get_time_from_asn1(const ASN1_TIME * atime); %} extern type to_int; @@ -146,105 +145,6 @@ enum AnalyzerState { 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; - } %} ###################################################################### diff --git a/src/file_analysis/analyzer/x509/CMakeLists.txt b/src/file_analysis/analyzer/x509/CMakeLists.txt index 759a01b55c..b07ef278f7 100644 --- a/src/file_analysis/analyzer/x509/CMakeLists.txt +++ b/src/file_analysis/analyzer/x509/CMakeLists.txt @@ -6,5 +6,5 @@ include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} bro_plugin_begin(Bro X509) 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() diff --git a/src/file_analysis/analyzer/x509/Plugin.cc b/src/file_analysis/analyzer/x509/Plugin.cc index 1e76e3fdb7..5b0e5779c5 100644 --- a/src/file_analysis/analyzer/x509/Plugin.cc +++ b/src/file_analysis/analyzer/x509/Plugin.cc @@ -7,4 +7,5 @@ BRO_PLUGIN_BEGIN(Bro, X509) BRO_PLUGIN_FILE_ANALYZER("X509", X509); BRO_PLUGIN_BIF_FILE(events); BRO_PLUGIN_BIF_FILE(types); + BRO_PLUGIN_BIF_FILE(functions); BRO_PLUGIN_END diff --git a/src/file_analysis/analyzer/x509/X509.cc b/src/file_analysis/analyzer/x509/X509.cc index 3d7871be9a..59ab644634 100644 --- a/src/file_analysis/analyzer/x509/X509.cc +++ b/src/file_analysis/analyzer/x509/X509.cc @@ -17,6 +17,8 @@ using namespace file_analysis; +IMPLEMENT_SERIAL(X509Val, SER_X509_VAL); + file_analysis::X509::X509(RecordVal* args, file_analysis::File* 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; } +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(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(&certbuf), &length) ) + return false; + + opensslbuf = certbuf; // OpenSSL likes to shift pointers around. really. + certificate = d2i_X509(NULL, const_cast(&opensslbuf), length); + delete[] certbuf; + + if ( !certificate ) + return false; + + return true; + } + + + + + diff --git a/src/file_analysis/analyzer/x509/X509.h b/src/file_analysis/analyzer/x509/X509.h index cc0131afac..80bb68209e 100644 --- a/src/file_analysis/analyzer/x509/X509.h +++ b/src/file_analysis/analyzer/x509/X509.h @@ -39,6 +39,50 @@ private: 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 diff --git a/src/main.cc b/src/main.cc index 313e1a40b0..ffa7a85f29 100644 --- a/src/main.cc +++ b/src/main.cc @@ -131,6 +131,7 @@ OpaqueType* entropy_type = 0; OpaqueType* cardinality_type = 0; OpaqueType* topk_type = 0; OpaqueType* bloomfilter_type = 0; +OpaqueType* x509_opaque_type = 0; extern std::list docs_generated; @@ -860,6 +861,7 @@ int main(int argc, char** argv) cardinality_type = new OpaqueType("cardinality"); topk_type = new OpaqueType("topk"); bloomfilter_type = new OpaqueType("bloomfilter"); + x509_opaque_type = new OpaqueType("x509"); // The leak-checker tends to produce some false // positives (memory which had already been