diff --git a/include/capi/cef_ssl_info_capi.h b/include/capi/cef_ssl_info_capi.h index dd0e6a9ff..d083b0de6 100644 --- a/include/capi/cef_ssl_info_capi.h +++ b/include/capi/cef_ssl_info_capi.h @@ -126,6 +126,24 @@ typedef struct _cef_sslinfo_t { /// cef_base_t base; + /// + // Returns a bitmask containing any and all problems verifying the server + // certificate. + /// + cef_cert_status_t (CEF_CALLBACK *get_cert_status)( + struct _cef_sslinfo_t* self); + + /// + // Returns true (1) if the certificate status has any error, major or minor. + /// + int (CEF_CALLBACK *is_cert_status_error)(struct _cef_sslinfo_t* self); + + /// + // Returns true (1) if the certificate status represents only minor errors + // (e.g. failure to verify certificate revocation). + /// + int (CEF_CALLBACK *is_cert_status_minor_error)(struct _cef_sslinfo_t* self); + /// // Returns the subject of the X.509 certificate. For HTTPS server certificates // this represents the web server. The common name of the subject should @@ -170,6 +188,28 @@ typedef struct _cef_sslinfo_t { /// struct _cef_binary_value_t* (CEF_CALLBACK *get_pemencoded)( struct _cef_sslinfo_t* self); + + /// + // Returns the number of certificates in the issuer chain. If 0, the + // certificate is self-signed. + /// + size_t (CEF_CALLBACK *get_issuer_chain_size)(struct _cef_sslinfo_t* self); + + /// + // Returns the DER encoded data for the certificate issuer chain. If we failed + // to encode a certificate in the chain it is still present in the array but + // is an NULL string. + /// + void (CEF_CALLBACK *get_derencoded_issuer_chain)(struct _cef_sslinfo_t* self, + size_t* chainCount, struct _cef_binary_value_t** chain); + + /// + // Returns the PEM encoded data for the certificate issuer chain. If we failed + // to encode a certificate in the chain it is still present in the array but + // is an NULL string. + /// + void (CEF_CALLBACK *get_pemencoded_issuer_chain)(struct _cef_sslinfo_t* self, + size_t* chainCount, struct _cef_binary_value_t** chain); } cef_sslinfo_t; diff --git a/include/cef_ssl_info.h b/include/cef_ssl_info.h index 213e1ee08..1ebc894ea 100644 --- a/include/cef_ssl_info.h +++ b/include/cef_ssl_info.h @@ -111,6 +111,28 @@ class CefSSLCertPrincipal : public virtual CefBase { /*--cef(source=library)--*/ class CefSSLInfo : public virtual CefBase { public: + typedef std::vector > IssuerChainBinaryList; + + /// + // Returns a bitmask containing any and all problems verifying the server + // certificate. + /// + /*--cef(default_retval=CERT_STATUS_NONE)--*/ + virtual cef_cert_status_t GetCertStatus() =0; + + /// + // Returns true if the certificate status has any error, major or minor. + /// + /*--cef()--*/ + virtual bool IsCertStatusError() =0; + + /// + // Returns true if the certificate status represents only minor errors + // (e.g. failure to verify certificate revocation). + /// + /*--cef()--*/ + virtual bool IsCertStatusMinorError() =0; + /// // Returns the subject of the X.509 certificate. For HTTPS server // certificates this represents the web server. The common name of the @@ -157,6 +179,29 @@ class CefSSLInfo : public virtual CefBase { /// /*--cef()--*/ virtual CefRefPtr GetPEMEncoded() =0; + + /// + // Returns the number of certificates in the issuer chain. + // If 0, the certificate is self-signed. + /// + /*--cef()--*/ + virtual size_t GetIssuerChainSize() =0; + + /// + // Returns the DER encoded data for the certificate issuer chain. + // If we failed to encode a certificate in the chain it is still + // present in the array but is an empty string. + /// + /*--cef(count_func=chain:GetIssuerChainSize)--*/ + virtual void GetDEREncodedIssuerChain(IssuerChainBinaryList& chain) =0; + + /// + // Returns the PEM encoded data for the certificate issuer chain. + // If we failed to encode a certificate in the chain it is still + // present in the array but is an empty string. + /// + /*--cef(count_func=chain:GetIssuerChainSize)--*/ + virtual void GetPEMEncodedIssuerChain(IssuerChainBinaryList& chain) =0; }; #endif // CEF_INCLUDE_CEF_SSL_INFO_H_ diff --git a/include/internal/cef_types.h b/include/internal/cef_types.h index 356b332a3..10a6b03f0 100644 --- a/include/internal/cef_types.h +++ b/include/internal/cef_types.h @@ -866,6 +866,7 @@ typedef enum { ERR_SSL_VERSION_OR_CIPHER_MISMATCH = -113, ERR_SSL_RENEGOTIATION_REQUESTED = -114, ERR_CERT_COMMON_NAME_INVALID = -200, + ERR_CERT_BEGIN = ERR_CERT_COMMON_NAME_INVALID, ERR_CERT_DATE_INVALID = -201, ERR_CERT_AUTHORITY_INVALID = -202, ERR_CERT_CONTAINS_ERRORS = -203, @@ -873,7 +874,13 @@ typedef enum { ERR_CERT_UNABLE_TO_CHECK_REVOCATION = -205, ERR_CERT_REVOKED = -206, ERR_CERT_INVALID = -207, - ERR_CERT_END = -208, + ERR_CERT_WEAK_SIGNATURE_ALGORITHM = -208, + // -209 is available: was ERR_CERT_NOT_IN_DNS. + ERR_CERT_NON_UNIQUE_NAME = -210, + ERR_CERT_WEAK_KEY = -211, + ERR_CERT_NAME_CONSTRAINT_VIOLATION = -212, + ERR_CERT_VALIDITY_TOO_LONG = -213, + ERR_CERT_END = ERR_CERT_VALIDITY_TOO_LONG, ERR_INVALID_URL = -300, ERR_DISALLOWED_URL_SCHEME = -301, ERR_UNKNOWN_URL_SCHEME = -302, @@ -890,6 +897,38 @@ typedef enum { ERR_INSECURE_RESPONSE = -501, } cef_errorcode_t; +/// +// Supported certificate status code values. See net\cert\cert_status_flags.h +// for more information. CERT_STATUS_NONE is new in CEF because we use an +// enum while cert_status_flags.h uses a typedef and static const variables. +/// +typedef enum { + CERT_STATUS_NONE = 0, + CERT_STATUS_COMMON_NAME_INVALID = 1 << 0, + CERT_STATUS_DATE_INVALID = 1 << 1, + CERT_STATUS_AUTHORITY_INVALID = 1 << 2, + // 1 << 3 is reserved for ERR_CERT_CONTAINS_ERRORS (not useful with WinHTTP). + CERT_STATUS_NO_REVOCATION_MECHANISM = 1 << 4, + CERT_STATUS_UNABLE_TO_CHECK_REVOCATION = 1 << 5, + CERT_STATUS_REVOKED = 1 << 6, + CERT_STATUS_INVALID = 1 << 7, + CERT_STATUS_WEAK_SIGNATURE_ALGORITHM = 1 << 8, + // 1 << 9 was used for CERT_STATUS_NOT_IN_DNS + CERT_STATUS_NON_UNIQUE_NAME = 1 << 10, + CERT_STATUS_WEAK_KEY = 1 << 11, + // 1 << 12 was used for CERT_STATUS_WEAK_DH_KEY + CERT_STATUS_PINNED_KEY_MISSING = 1 << 13, + CERT_STATUS_NAME_CONSTRAINT_VIOLATION = 1 << 14, + CERT_STATUS_VALIDITY_TOO_LONG = 1 << 15, + + // Bits 16 to 31 are for non-error statuses. + CERT_STATUS_IS_EV = 1 << 16, + CERT_STATUS_REV_CHECKING_ENABLED = 1 << 17, + // Bit 18 was CERT_STATUS_IS_DNSSEC + CERT_STATUS_SHA1_SIGNATURE_PRESENT = 1 << 19, + CERT_STATUS_CT_COMPLIANCE_FAILED = 1 << 20, +} cef_cert_status_t; + /// // The manner in which a link click should be opened. /// diff --git a/libcef/browser/ssl_info_impl.cc b/libcef/browser/ssl_info_impl.cc index aa38caec0..cfa31a205 100644 --- a/libcef/browser/ssl_info_impl.cc +++ b/libcef/browser/ssl_info_impl.cc @@ -6,10 +6,34 @@ #include "libcef/browser/ssl_cert_principal_impl.h" #include "libcef/common/time_util.h" +#include "net/cert/cert_status_flags.h" #include "net/cert/x509_certificate.h" -CefSSLInfoImpl::CefSSLInfoImpl(const net::SSLInfo& value) { +namespace { + +void EncodeCertificate( + const net::X509Certificate::OSCertHandle& os_handle, + CefRefPtr& der_encoded, + CefRefPtr& pem_encoded) { + std::string encoded; + if (net::X509Certificate::GetDEREncoded(os_handle, &encoded)) { + der_encoded = CefBinaryValue::Create(encoded.c_str(), + encoded.size()); + } + encoded.clear(); + if (net::X509Certificate::GetPEMEncoded(os_handle, &encoded)) { + pem_encoded = CefBinaryValue::Create(encoded.c_str(), + encoded.size()); + } +} + +} // namespace + +CefSSLInfoImpl::CefSSLInfoImpl(const net::SSLInfo& value) + : cert_status_(CERT_STATUS_NONE) { if (value.cert.get()) { + cert_status_ = static_cast(value.cert_status); + subject_ = new CefSSLCertPrincipalImpl(value.cert->subject()); issuer_ = new CefSSLCertPrincipalImpl(value.cert->issuer()); @@ -26,21 +50,36 @@ CefSSLInfoImpl::CefSSLInfoImpl(const net::SSLInfo& value) { cef_time_from_basetime(valid_expiry, valid_expiry_); net::X509Certificate::OSCertHandle os_handle = value.cert->os_cert_handle(); - if (os_handle) { - std::string encoded; - if (value.cert->GetDEREncoded(os_handle, &encoded)) { - der_encoded_ = CefBinaryValue::Create(encoded.c_str(), - encoded.size()); - } - encoded.clear(); - if (value.cert->GetPEMEncoded(os_handle, &encoded)) { - pem_encoded_ = CefBinaryValue::Create(encoded.c_str(), - encoded.size()); - } + if (os_handle) + EncodeCertificate(os_handle, der_encoded_, pem_encoded_); + + const net::X509Certificate::OSCertHandles& issuer_chain = + value.cert->GetIntermediateCertificates(); + for (net::X509Certificate::OSCertHandles::const_iterator it = + issuer_chain.begin(); it != issuer_chain.end(); it++) { + CefRefPtr der_encoded, pem_encoded; + EncodeCertificate(*it, der_encoded, pem_encoded); + + // Add each to the chain, even if one conversion unexpectedly failed. + // GetIssuerChainSize depends on these being the same length. + der_encoded_issuer_chain_.push_back(der_encoded); + pem_encoded_issuer_chain_.push_back(pem_encoded); } } } +cef_cert_status_t CefSSLInfoImpl::GetCertStatus() { + return cert_status_; +} + +bool CefSSLInfoImpl::IsCertStatusError() { + return net::IsCertStatusError(cert_status_); +} + +bool CefSSLInfoImpl::IsCertStatusMinorError() { + return net::IsCertStatusMinorError(cert_status_); +} + CefRefPtr CefSSLInfoImpl::GetSubject() { return subject_; } @@ -68,3 +107,17 @@ CefRefPtr CefSSLInfoImpl::GetDEREncoded() { CefRefPtr CefSSLInfoImpl::GetPEMEncoded() { return pem_encoded_; } + +size_t CefSSLInfoImpl::GetIssuerChainSize() { + return der_encoded_issuer_chain_.size(); +} + +void CefSSLInfoImpl::GetDEREncodedIssuerChain( + CefSSLInfo::IssuerChainBinaryList& chain) { + chain = der_encoded_issuer_chain_; +} + +void CefSSLInfoImpl::GetPEMEncodedIssuerChain( + CefSSLInfo::IssuerChainBinaryList& chain) { + chain = pem_encoded_issuer_chain_; +} diff --git a/libcef/browser/ssl_info_impl.h b/libcef/browser/ssl_info_impl.h index a16ca5e22..aa3a9c8fa 100644 --- a/libcef/browser/ssl_info_impl.h +++ b/libcef/browser/ssl_info_impl.h @@ -16,6 +16,9 @@ class CefSSLInfoImpl : public CefSSLInfo { explicit CefSSLInfoImpl(const net::SSLInfo& value); // CefSSLInfo methods. + cef_cert_status_t GetCertStatus() override; + bool IsCertStatusError() override; + bool IsCertStatusMinorError() override; CefRefPtr GetSubject() override; CefRefPtr GetIssuer() override; CefRefPtr GetSerialNumber() override; @@ -23,8 +26,12 @@ class CefSSLInfoImpl : public CefSSLInfo { CefTime GetValidExpiry() override; CefRefPtr GetDEREncoded() override; CefRefPtr GetPEMEncoded() override; + size_t GetIssuerChainSize() override; + void GetDEREncodedIssuerChain(IssuerChainBinaryList& chain) override; + void GetPEMEncodedIssuerChain(IssuerChainBinaryList& chain) override; private: + cef_cert_status_t cert_status_; CefRefPtr subject_; CefRefPtr issuer_; CefRefPtr serial_number_; @@ -32,6 +39,8 @@ class CefSSLInfoImpl : public CefSSLInfo { CefTime valid_expiry_; CefRefPtr der_encoded_; CefRefPtr pem_encoded_; + IssuerChainBinaryList der_encoded_issuer_chain_; + IssuerChainBinaryList pem_encoded_issuer_chain_; IMPLEMENT_REFCOUNTING(CefSSLInfoImpl); DISALLOW_COPY_AND_ASSIGN(CefSSLInfoImpl); diff --git a/libcef_dll/cpptoc/sslinfo_cpptoc.cc b/libcef_dll/cpptoc/sslinfo_cpptoc.cc index d808e6389..dce650387 100644 --- a/libcef_dll/cpptoc/sslinfo_cpptoc.cc +++ b/libcef_dll/cpptoc/sslinfo_cpptoc.cc @@ -10,6 +10,7 @@ // for more information. // +#include #include "libcef_dll/cpptoc/binary_value_cpptoc.h" #include "libcef_dll/cpptoc/sslcert_principal_cpptoc.h" #include "libcef_dll/cpptoc/sslinfo_cpptoc.h" @@ -19,6 +20,50 @@ namespace { // MEMBER FUNCTIONS - Body may be edited by hand. +cef_cert_status_t CEF_CALLBACK sslinfo_get_cert_status( + struct _cef_sslinfo_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return CERT_STATUS_NONE; + + // Execute + cef_cert_status_t _retval = CefSSLInfoCppToC::Get(self)->GetCertStatus(); + + // Return type: simple + return _retval; +} + +int CEF_CALLBACK sslinfo_is_cert_status_error(struct _cef_sslinfo_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefSSLInfoCppToC::Get(self)->IsCertStatusError(); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK sslinfo_is_cert_status_minor_error( + struct _cef_sslinfo_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefSSLInfoCppToC::Get(self)->IsCertStatusMinorError(); + + // Return type: bool + return _retval; +} + cef_sslcert_principal_t* CEF_CALLBACK sslinfo_get_subject( struct _cef_sslinfo_t* self) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING @@ -127,12 +172,101 @@ struct _cef_binary_value_t* CEF_CALLBACK sslinfo_get_pemencoded( return CefBinaryValueCppToC::Wrap(_retval); } +size_t CEF_CALLBACK sslinfo_get_issuer_chain_size(struct _cef_sslinfo_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + size_t _retval = CefSSLInfoCppToC::Get(self)->GetIssuerChainSize(); + + // Return type: simple + return _retval; +} + +void CEF_CALLBACK sslinfo_get_derencoded_issuer_chain( + struct _cef_sslinfo_t* self, size_t* chainCount, + struct _cef_binary_value_t** chain) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: chain; type: refptr_vec_same_byref + DCHECK(chainCount && (*chainCount == 0 || chain)); + if (!chainCount || (*chainCount > 0 && !chain)) + return; + + // Translate param: chain; type: refptr_vec_same_byref + std::vector > chainList; + if (chainCount && *chainCount > 0 && chain) { + for (size_t i = 0; i < *chainCount; ++i) { + chainList.push_back(CefBinaryValueCppToC::Unwrap(chain[i])); + } + } + + // Execute + CefSSLInfoCppToC::Get(self)->GetDEREncodedIssuerChain( + chainList); + + // Restore param: chain; type: refptr_vec_same_byref + if (chainCount && chain) { + *chainCount = std::min(chainList.size(), *chainCount); + if (*chainCount > 0) { + for (size_t i = 0; i < *chainCount; ++i) { + chain[i] = CefBinaryValueCppToC::Wrap(chainList[i]); + } + } + } +} + +void CEF_CALLBACK sslinfo_get_pemencoded_issuer_chain( + struct _cef_sslinfo_t* self, size_t* chainCount, + struct _cef_binary_value_t** chain) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: chain; type: refptr_vec_same_byref + DCHECK(chainCount && (*chainCount == 0 || chain)); + if (!chainCount || (*chainCount > 0 && !chain)) + return; + + // Translate param: chain; type: refptr_vec_same_byref + std::vector > chainList; + if (chainCount && *chainCount > 0 && chain) { + for (size_t i = 0; i < *chainCount; ++i) { + chainList.push_back(CefBinaryValueCppToC::Unwrap(chain[i])); + } + } + + // Execute + CefSSLInfoCppToC::Get(self)->GetPEMEncodedIssuerChain( + chainList); + + // Restore param: chain; type: refptr_vec_same_byref + if (chainCount && chain) { + *chainCount = std::min(chainList.size(), *chainCount); + if (*chainCount > 0) { + for (size_t i = 0; i < *chainCount; ++i) { + chain[i] = CefBinaryValueCppToC::Wrap(chainList[i]); + } + } + } +} + } // namespace // CONSTRUCTOR - Do not edit by hand. CefSSLInfoCppToC::CefSSLInfoCppToC() { + GetStruct()->get_cert_status = sslinfo_get_cert_status; + GetStruct()->is_cert_status_error = sslinfo_is_cert_status_error; + GetStruct()->is_cert_status_minor_error = sslinfo_is_cert_status_minor_error; GetStruct()->get_subject = sslinfo_get_subject; GetStruct()->get_issuer = sslinfo_get_issuer; GetStruct()->get_serial_number = sslinfo_get_serial_number; @@ -140,6 +274,11 @@ CefSSLInfoCppToC::CefSSLInfoCppToC() { GetStruct()->get_valid_expiry = sslinfo_get_valid_expiry; GetStruct()->get_derencoded = sslinfo_get_derencoded; GetStruct()->get_pemencoded = sslinfo_get_pemencoded; + GetStruct()->get_issuer_chain_size = sslinfo_get_issuer_chain_size; + GetStruct()->get_derencoded_issuer_chain = + sslinfo_get_derencoded_issuer_chain; + GetStruct()->get_pemencoded_issuer_chain = + sslinfo_get_pemencoded_issuer_chain; } template<> CefRefPtr CefCppToC #include "libcef_dll/ctocpp/binary_value_ctocpp.h" #include "libcef_dll/ctocpp/sslcert_principal_ctocpp.h" #include "libcef_dll/ctocpp/sslinfo_ctocpp.h" @@ -17,6 +18,48 @@ // VIRTUAL METHODS - Body may be edited by hand. +cef_cert_status_t CefSSLInfoCToCpp::GetCertStatus() { + cef_sslinfo_t* _struct = GetStruct(); + if (CEF_MEMBER_MISSING(_struct, get_cert_status)) + return CERT_STATUS_NONE; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_cert_status_t _retval = _struct->get_cert_status(_struct); + + // Return type: simple + return _retval; +} + +bool CefSSLInfoCToCpp::IsCertStatusError() { + cef_sslinfo_t* _struct = GetStruct(); + if (CEF_MEMBER_MISSING(_struct, is_cert_status_error)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = _struct->is_cert_status_error(_struct); + + // Return type: bool + return _retval?true:false; +} + +bool CefSSLInfoCToCpp::IsCertStatusMinorError() { + cef_sslinfo_t* _struct = GetStruct(); + if (CEF_MEMBER_MISSING(_struct, is_cert_status_minor_error)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = _struct->is_cert_status_minor_error(_struct); + + // Return type: bool + return _retval?true:false; +} + CefRefPtr CefSSLInfoCToCpp::GetSubject() { cef_sslinfo_t* _struct = GetStruct(); if (CEF_MEMBER_MISSING(_struct, get_subject)) @@ -115,6 +158,98 @@ CefRefPtr CefSSLInfoCToCpp::GetPEMEncoded() { return CefBinaryValueCToCpp::Wrap(_retval); } +size_t CefSSLInfoCToCpp::GetIssuerChainSize() { + cef_sslinfo_t* _struct = GetStruct(); + if (CEF_MEMBER_MISSING(_struct, get_issuer_chain_size)) + return 0; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + size_t _retval = _struct->get_issuer_chain_size(_struct); + + // Return type: simple + return _retval; +} + +void CefSSLInfoCToCpp::GetDEREncodedIssuerChain(IssuerChainBinaryList& chain) { + cef_sslinfo_t* _struct = GetStruct(); + if (CEF_MEMBER_MISSING(_struct, get_derencoded_issuer_chain)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Translate param: chain; type: refptr_vec_same_byref + size_t chainSize = chain.size(); + size_t chainCount = std::max(GetIssuerChainSize(), chainSize); + cef_binary_value_t** chainList = NULL; + if (chainCount > 0) { + chainList = new cef_binary_value_t*[chainCount]; + DCHECK(chainList); + if (chainList) { + memset(chainList, 0, sizeof(cef_binary_value_t*)*chainCount); + } + if (chainList && chainSize > 0) { + for (size_t i = 0; i < chainSize; ++i) { + chainList[i] = CefBinaryValueCToCpp::Unwrap(chain[i]); + } + } + } + + // Execute + _struct->get_derencoded_issuer_chain(_struct, + &chainCount, + chainList); + + // Restore param:chain; type: refptr_vec_same_byref + chain.clear(); + if (chainCount > 0 && chainList) { + for (size_t i = 0; i < chainCount; ++i) { + chain.push_back(CefBinaryValueCToCpp::Wrap(chainList[i])); + } + delete [] chainList; + } +} + +void CefSSLInfoCToCpp::GetPEMEncodedIssuerChain(IssuerChainBinaryList& chain) { + cef_sslinfo_t* _struct = GetStruct(); + if (CEF_MEMBER_MISSING(_struct, get_pemencoded_issuer_chain)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Translate param: chain; type: refptr_vec_same_byref + size_t chainSize = chain.size(); + size_t chainCount = std::max(GetIssuerChainSize(), chainSize); + cef_binary_value_t** chainList = NULL; + if (chainCount > 0) { + chainList = new cef_binary_value_t*[chainCount]; + DCHECK(chainList); + if (chainList) { + memset(chainList, 0, sizeof(cef_binary_value_t*)*chainCount); + } + if (chainList && chainSize > 0) { + for (size_t i = 0; i < chainSize; ++i) { + chainList[i] = CefBinaryValueCToCpp::Unwrap(chain[i]); + } + } + } + + // Execute + _struct->get_pemencoded_issuer_chain(_struct, + &chainCount, + chainList); + + // Restore param:chain; type: refptr_vec_same_byref + chain.clear(); + if (chainCount > 0 && chainList) { + for (size_t i = 0; i < chainCount; ++i) { + chain.push_back(CefBinaryValueCToCpp::Wrap(chainList[i])); + } + delete [] chainList; + } +} + // CONSTRUCTOR - Do not edit by hand. diff --git a/libcef_dll/ctocpp/sslinfo_ctocpp.h b/libcef_dll/ctocpp/sslinfo_ctocpp.h index 468257423..ebe758e7c 100644 --- a/libcef_dll/ctocpp/sslinfo_ctocpp.h +++ b/libcef_dll/ctocpp/sslinfo_ctocpp.h @@ -30,6 +30,9 @@ class CefSSLInfoCToCpp CefSSLInfoCToCpp(); // CefSSLInfo methods. + cef_cert_status_t GetCertStatus() OVERRIDE; + bool IsCertStatusError() OVERRIDE; + bool IsCertStatusMinorError() OVERRIDE; CefRefPtr GetSubject() OVERRIDE; CefRefPtr GetIssuer() OVERRIDE; CefRefPtr GetSerialNumber() OVERRIDE; @@ -37,6 +40,9 @@ class CefSSLInfoCToCpp CefTime GetValidExpiry() OVERRIDE; CefRefPtr GetDEREncoded() OVERRIDE; CefRefPtr GetPEMEncoded() OVERRIDE; + size_t GetIssuerChainSize() OVERRIDE; + void GetDEREncodedIssuerChain(IssuerChainBinaryList& chain) OVERRIDE; + void GetPEMEncodedIssuerChain(IssuerChainBinaryList& chain) OVERRIDE; }; #endif // USING_CEF_SHARED diff --git a/tests/cefclient/browser/client_handler.cc b/tests/cefclient/browser/client_handler.cc index 2938be5c8..42d25bd6a 100644 --- a/tests/cefclient/browser/client_handler.cc +++ b/tests/cefclient/browser/client_handler.cc @@ -82,6 +82,33 @@ std::string GetBinaryString(CefRefPtr value) { return CefBase64Encode(src.data(), src.size()); } +std::string GetCertStatusString(cef_cert_status_t status) { + #define FLAG(flag) if (status & flag) result += std::string(#flag) + "
" + std::string result; + + FLAG(CERT_STATUS_COMMON_NAME_INVALID); + FLAG(CERT_STATUS_DATE_INVALID); + FLAG(CERT_STATUS_AUTHORITY_INVALID); + FLAG(CERT_STATUS_NO_REVOCATION_MECHANISM); + FLAG(CERT_STATUS_UNABLE_TO_CHECK_REVOCATION); + FLAG(CERT_STATUS_REVOKED); + FLAG(CERT_STATUS_INVALID); + FLAG(CERT_STATUS_WEAK_SIGNATURE_ALGORITHM); + FLAG(CERT_STATUS_NON_UNIQUE_NAME); + FLAG(CERT_STATUS_WEAK_KEY); + FLAG(CERT_STATUS_PINNED_KEY_MISSING); + FLAG(CERT_STATUS_NAME_CONSTRAINT_VIOLATION); + FLAG(CERT_STATUS_VALIDITY_TOO_LONG); + FLAG(CERT_STATUS_IS_EV); + FLAG(CERT_STATUS_REV_CHECKING_ENABLED); + FLAG(CERT_STATUS_SHA1_SIGNATURE_PRESENT); + FLAG(CERT_STATUS_CT_COMPLIANCE_FAILED); + + if (result.empty()) + return " "; + return result; +} + // Load a data: URI containing the error message. void LoadErrorPage(CefRefPtr frame, const std::string& failed_url, @@ -539,7 +566,8 @@ bool ClientHandler::OnCertificateError( CefRefPtr subject = ssl_info->GetSubject(); CefRefPtr issuer = ssl_info->GetIssuer(); - // Build a table showing certificate information. + // Build a table showing certificate information. Various types of invalid + // certificates can be tested using https://badssl.com/. std::stringstream ss; ss << "X.509 Certificate Information:" "" << @@ -551,17 +579,32 @@ bool ClientHandler::OnCertificateError( "" "" + "" "" "" - "" - "" - "" - "" - "
FieldValue
Serial #*" << GetBinaryString(ssl_info->GetSerialNumber()) << "
Status" << + GetCertStatusString(ssl_info->GetCertStatus()) << "
Valid Start" << GetTimeString(ssl_info->GetValidStart()) << "
Valid Expiry" << - GetTimeString(ssl_info->GetValidExpiry()) << "
DER Encoded*" << - GetBinaryString(ssl_info->GetDEREncoded()) << "
PEM Encoded*" << - GetBinaryString(ssl_info->GetPEMEncoded()) << "
* Displayed value is base64 encoded."; + GetTimeString(ssl_info->GetValidExpiry()) << ""; + + CefSSLInfo::IssuerChainBinaryList der_chain_list; + CefSSLInfo::IssuerChainBinaryList pem_chain_list; + ssl_info->GetDEREncodedIssuerChain(der_chain_list); + ssl_info->GetPEMEncodedIssuerChain(pem_chain_list); + DCHECK_EQ(der_chain_list.size(), pem_chain_list.size()); + + der_chain_list.insert(der_chain_list.begin(), ssl_info->GetDEREncoded()); + pem_chain_list.insert(pem_chain_list.begin(), ssl_info->GetPEMEncoded()); + + for (size_t i = 0U; i < der_chain_list.size(); ++i) { + ss << "DER Encoded*" + "" << + GetBinaryString(der_chain_list[i]) << "" + "PEM Encoded*" + "" << + GetBinaryString(pem_chain_list[i]) << ""; + } + + ss << " * Displayed value is base64 encoded."; // Load the error page. LoadErrorPage(browser->GetMainFrame(), request_url, cert_error, ss.str());