diff --git a/scripts/base/files/x509/main.bro b/scripts/base/files/x509/main.bro index 458a389934..d19327f07c 100644 --- a/scripts/base/files/x509/main.bro +++ b/scripts/base/files/x509/main.bro @@ -12,17 +12,17 @@ event x509_cert(f: fa_file, cert: X509::Certificate) print cert; } -event x509_extension(f: fa_file, ext: X509::Extension) +event x509_extension(f: fa_file, cert: X509::Certificate, ext: X509::Extension) { print ext; } -event x509_ext_basic_constraints(f: fa_file, ext: X509::BasicConstraints) +event x509_ext_basic_constraints(f: fa_file, cert: X509::Certificate, ext: X509::BasicConstraints) { print ext; } -event x509_ext_subject_alternative_name(f: fa_file, ext: X509::SubjectAlternativeName) +event x509_ext_subject_alternative_name(f: fa_file, cert: X509::Certificate, ext: X509::SubjectAlternativeName) { print ext; } diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index 8573fc2876..e4c1803fcb 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -2420,29 +2420,6 @@ global dns_skip_all_addl = T &redef; ## traffic and do not process it. Set to 0 to turn off this functionality. global dns_max_queries = 5; -## An X509 certificate. -## -## .. bro:see:: x509_certificate -type X509: record { - version: count; ##< Version number. - serial: string; ##< Serial number. - subject: string; ##< Subject. - issuer: string; ##< Issuer. - not_valid_before: time; ##< Timestamp before when certificate is not valid. - not_valid_after: time; ##< Timestamp after when certificate is not valid. -}; - -## An X509 extension. -## -## .. bro:see:: x509_extension -type X509_extension_info: record { - name: string; ##< Long name of extension; oid if name not known. - short_name: string &optional; ##< Short name of extension if known. - oid: string; ##< Oid of extension. - critical: bool; ##< True if extension is critical. - value: string; ##< Extension content parsed to string for known extensions. Raw data otherwise. -}; - ## HTTP session statistics. ## ## .. bro:see:: http_stats @@ -2767,6 +2744,7 @@ export { module X509; export { type X509::Certificate: record { + certificate: opaque of x509; ##< OpenSSL certificate reference version: count; ##< Version number. serial: string; ##< Serial number. subject: string; ##< Subject. @@ -2799,7 +2777,6 @@ export { type X509::SubjectAlternativeName: record { names: vector of string; }; - } module SOCKS; diff --git a/src/NetVar.cc b/src/NetVar.cc index 05a4e16b47..2883adcf9f 100644 --- a/src/NetVar.cc +++ b/src/NetVar.cc @@ -47,9 +47,6 @@ int tcp_max_initial_window; int tcp_max_above_hole_without_any_acks; int tcp_excessive_data_without_further_acks; -RecordType* x509_type; -RecordType* x509_extension_type; - RecordType* socks_address; double non_analyzed_lifetime; @@ -356,9 +353,6 @@ void init_net_var() tcp_excessive_data_without_further_acks = opt_internal_int("tcp_excessive_data_without_further_acks"); - x509_type = internal_type("X509")->AsRecordType(); - x509_extension_type = internal_type("X509_extension_info")->AsRecordType(); - socks_address = internal_type("SOCKS::Address")->AsRecordType(); non_analyzed_lifetime = opt_internal_double("non_analyzed_lifetime"); diff --git a/src/NetVar.h b/src/NetVar.h index 8ef6571313..55f3955fa4 100644 --- a/src/NetVar.h +++ b/src/NetVar.h @@ -50,9 +50,6 @@ extern int tcp_max_initial_window; extern int tcp_max_above_hole_without_any_acks; extern int tcp_excessive_data_without_further_acks; -extern RecordType* x509_type; -extern RecordType* x509_extension_type; - extern RecordType* socks_address; extern double non_analyzed_lifetime; diff --git a/src/file_analysis/analyzer/x509/X509.cc b/src/file_analysis/analyzer/x509/X509.cc index c2c2a0b8bc..684f4f54ba 100644 --- a/src/file_analysis/analyzer/x509/X509.cc +++ b/src/file_analysis/analyzer/x509/X509.cc @@ -49,7 +49,7 @@ bool file_analysis::X509::EndOfFile() return false; } - ParseCertificate(ssl_cert); + RecordVal* cert_record = ParseCertificate(ssl_cert); // cert_record takes ownership of ssl_cert // after parsing the certificate - parse the extensions... @@ -60,37 +60,43 @@ bool file_analysis::X509::EndOfFile() if ( !ex ) continue; - ParseExtension(ex); + ParseExtension(ex, cert_record); } - X509_free(ssl_cert); + // X509_free(ssl_cert); We do _not_ free the certificate here. It is refcounted + // inside the X509Val that is sent on in the cert record to scriptland. + // + // The certificate will be freed when the last X509Val is Unref'd. + + Unref(cert_record); // Unref the RecordVal that we kept around from ParseCertificate return false; } -void file_analysis::X509::ParseCertificate(::X509* ssl_cert) +RecordVal* file_analysis::X509::ParseCertificate(::X509* ssl_cert) { char buf[256]; // we need a buffer for some of the openssl functions - memset(buf, 0, 256); + memset(buf, 0, 256); RecordVal* pX509Cert = new RecordVal(BifType::Record::X509::Certificate); BIO *bio = BIO_new(BIO_s_mem()); - pX509Cert->Assign(0, new Val((uint64) X509_get_version(ssl_cert), TYPE_COUNT)); + pX509Cert->Assign(0, new X509Val(ssl_cert)); // take ownership for cleanup + pX509Cert->Assign(1, new Val((uint64) X509_get_version(ssl_cert), TYPE_COUNT)); i2a_ASN1_INTEGER(bio, X509_get_serialNumber(ssl_cert)); int len = BIO_read(bio, &(*buf), sizeof buf); - pX509Cert->Assign(1, new StringVal(len, buf)); + pX509Cert->Assign(2, new StringVal(len, buf)); X509_NAME_print_ex(bio, X509_get_subject_name(ssl_cert), 0, XN_FLAG_RFC2253); len = BIO_gets(bio, &(*buf), sizeof buf); - pX509Cert->Assign(2, new StringVal(len, buf)); + pX509Cert->Assign(3, new StringVal(len, buf)); X509_NAME_print_ex(bio, X509_get_issuer_name(ssl_cert), 0, XN_FLAG_RFC2253); len = BIO_gets(bio, &(*buf), sizeof buf); - pX509Cert->Assign(3, new StringVal(len, buf)); + pX509Cert->Assign(4, new StringVal(len, buf)); BIO_free(bio); - pX509Cert->Assign(4, new Val(get_time_from_asn1(X509_get_notBefore(ssl_cert)), TYPE_TIME)); - pX509Cert->Assign(5, new Val(get_time_from_asn1(X509_get_notAfter(ssl_cert)), TYPE_TIME)); + pX509Cert->Assign(5, new Val(get_time_from_asn1(X509_get_notBefore(ssl_cert)), TYPE_TIME)); + pX509Cert->Assign(6, new Val(get_time_from_asn1(X509_get_notAfter(ssl_cert)), TYPE_TIME)); // we only read 255 bytes because byte 256 is always 0. // if the string is longer than 255, that will be our null-termination, @@ -137,12 +143,14 @@ void file_analysis::X509::ParseCertificate(::X509* ssl_cert) val_list* vl = new val_list(); vl->append(GetFile()->GetVal()->Ref()); - vl->append(pX509Cert); + vl->append(pX509Cert->Ref()); // we Ref it here, because we want to keep a copy around for now... mgr.QueueEvent(x509_cert, vl); + + return pX509Cert; } -void file_analysis::X509::ParseExtension(X509_EXTENSION* ex) +void file_analysis::X509::ParseExtension(X509_EXTENSION* ex, RecordVal* r) { char name[256]; char oid[256]; @@ -188,18 +196,19 @@ void file_analysis::X509::ParseExtension(X509_EXTENSION* ex) // but I am not sure if there is a better way to do it... val_list* vl = new val_list(); vl->append(GetFile()->GetVal()->Ref()); + vl->append(r->Ref()); vl->append(pX509Ext); mgr.QueueEvent(x509_extension, vl); // look if we have a specialized handler for this event... if ( OBJ_obj2nid(ext_asn) == NID_basic_constraints ) - ParseBasicConstraints(ex); + ParseBasicConstraints(ex, r); else if ( OBJ_obj2nid(ext_asn) == NID_subject_alt_name ) - ParseSAN(ex); + ParseSAN(ex, r); } -void file_analysis::X509::ParseBasicConstraints(X509_EXTENSION* ex) +void file_analysis::X509::ParseBasicConstraints(X509_EXTENSION* ex, RecordVal* r) { assert(OBJ_obj2nid(X509_EXTENSION_get_object(ex)) == NID_basic_constraints); @@ -217,6 +226,7 @@ void file_analysis::X509::ParseBasicConstraints(X509_EXTENSION* ex) } val_list* vl = new val_list(); vl->append(GetFile()->GetVal()->Ref()); + vl->append(r->Ref()); vl->append(pBasicConstraint); mgr.QueueEvent(x509_ext_basic_constraints, vl); @@ -224,7 +234,7 @@ void file_analysis::X509::ParseBasicConstraints(X509_EXTENSION* ex) } } -void file_analysis::X509::ParseSAN(X509_EXTENSION* ext) +void file_analysis::X509::ParseSAN(X509_EXTENSION* ext, RecordVal* r) { assert(OBJ_obj2nid(X509_EXTENSION_get_object(ext)) == NID_subject_alt_name); @@ -268,6 +278,7 @@ void file_analysis::X509::ParseSAN(X509_EXTENSION* ext) val_list* vl = new val_list(); vl->append(GetFile()->GetVal()->Ref()); + vl->append(r->Ref()); vl->append(pSan); mgr.QueueEvent(x509_ext_basic_constraints, vl); diff --git a/src/file_analysis/analyzer/x509/X509.h b/src/file_analysis/analyzer/x509/X509.h index 80bb68209e..f64aa3eb58 100644 --- a/src/file_analysis/analyzer/x509/X509.h +++ b/src/file_analysis/analyzer/x509/X509.h @@ -31,10 +31,10 @@ private: static StringVal* key_curve(EVP_PKEY *key); static unsigned int key_length(EVP_PKEY *key); - void ParseCertificate(::X509* ssl_cert); - void ParseExtension(X509_EXTENSION* ex); - void ParseBasicConstraints(X509_EXTENSION* ex); - void ParseSAN(X509_EXTENSION* ex); + RecordVal* ParseCertificate(::X509* ssl_cert); + void ParseExtension(X509_EXTENSION* ex, RecordVal* r); + void ParseBasicConstraints(X509_EXTENSION* ex, RecordVal* r); + void ParseSAN(X509_EXTENSION* ex, RecordVal* r); std::string cert_data; }; @@ -55,7 +55,7 @@ public: * * @return A newly initialized X509Val */ - X509Val(::X509* certificate); + explicit X509Val(::X509* certificate); /** * Destructor. @@ -84,5 +84,4 @@ private: } - #endif diff --git a/src/file_analysis/analyzer/x509/events.bif b/src/file_analysis/analyzer/x509/events.bif index 148d09ec00..2787746e0c 100644 --- a/src/file_analysis/analyzer/x509/events.bif +++ b/src/file_analysis/analyzer/x509/events.bif @@ -1,4 +1,4 @@ event x509_cert%(f: fa_file, cert: X509::Certificate%); -event x509_extension%(f: fa_file, ext: X509::Extension%); -event x509_ext_basic_constraints%(f: fa_file, ext: X509::BasicConstraints%); -event x509_ext_subject_alternative_name%(f: fa_file, ext: X509::SubjectAlternativeName%); +event x509_extension%(f: fa_file, cert: X509::Certificate, ext: X509::Extension%); +event x509_ext_basic_constraints%(f: fa_file, cert: X509::Certificate, ext: X509::BasicConstraints%); +event x509_ext_subject_alternative_name%(f: fa_file, cert: X509::Certificate, ext: X509::SubjectAlternativeName%);