Index: extensions/browser/api/web_request/web_request_api_helpers.cc |
diff --git a/extensions/browser/api/web_request/web_request_api_helpers.cc b/extensions/browser/api/web_request/web_request_api_helpers.cc |
index 53dfc88655edc29f9a8cf5289df13da868f0d37e..348fe6e3b4f427484c4fccb6d09157e0c9add36d 100644 |
--- a/extensions/browser/api/web_request/web_request_api_helpers.cc |
+++ b/extensions/browser/api/web_request/web_request_api_helpers.cc |
@@ -28,10 +28,14 @@ |
#include "extensions/browser/runtime_data.h" |
#include "extensions/browser/warning_set.h" |
#include "extensions/common/extension_messages.h" |
+#include "net/cert/x509_certificate.h" |
#include "net/cookies/cookie_util.h" |
#include "net/cookies/parsed_cookie.h" |
#include "net/http/http_util.h" |
#include "net/log/net_log.h" |
+#include "net/ssl/ssl_cipher_suite_names.h" |
+#include "net/ssl/ssl_connection_status_flags.h" |
+#include "net/ssl/ssl_info.h" |
#include "net/url_request/url_request.h" |
#include "url/url_constants.h" |
@@ -1322,4 +1326,174 @@ bool ParseResourceType(const std::string& type_str, |
return found; |
} |
+static base::DictionaryValue* ExtractDN(const net::CertPrincipal& dn) { |
+ base::DictionaryValue* dn_dict = new base::DictionaryValue(); |
+ if (!dn.common_name.empty()) { |
+ dn_dict->SetString(keys::kCommonNameKey, dn.common_name); |
+ } |
+ if (!dn.locality_name.empty()) { |
+ dn_dict->SetString(keys::kLocalityNameKey, dn.locality_name); |
+ } |
+ if (!dn.state_or_province_name.empty()) { |
+ dn_dict->SetString(keys::kStateOrProvinceNameKey, |
+ dn.state_or_province_name); |
+ } |
+ if (!dn.country_name.empty()) { |
+ dn_dict->SetString(keys::kCountryNameKey, dn.country_name); |
+ } |
+ if (dn.street_addresses.size() > 0) { |
+ base::ListValue* addrs = new base::ListValue(); |
+ addrs->AppendStrings(dn.street_addresses); |
+ dn_dict->Set(keys::kStreetAddressesKey, addrs); |
+ } |
+ if (dn.organization_names.size() > 0) { |
+ base::ListValue* names = new base::ListValue(); |
+ names->AppendStrings(dn.organization_names); |
+ dn_dict->Set(keys::kOrganizationNamesKey, names); |
+ } |
+ if (dn.organization_unit_names.size() > 0) { |
+ base::ListValue* names = new base::ListValue(); |
+ names->AppendStrings(dn.organization_unit_names); |
+ dn_dict->Set(keys::kOrganizationUnitNamesKey, names); |
+ } |
+ if (dn.domain_components.size() > 0) { |
+ base::ListValue* components = new base::ListValue(); |
+ components->AppendStrings(dn.domain_components); |
+ dn_dict->Set(keys::kDomainComponentsKey, components); |
+ } |
+ return dn_dict; |
+} |
+ |
+static base::DictionaryValue* ExtractCertificateInfo( |
+ scoped_refptr<net::X509Certificate> cert) { |
+ base::DictionaryValue* info = new base::DictionaryValue(); |
+ info->SetString(keys::kSerialNumberKey, |
+ base::HexEncode(cert->serial_number().data(), |
+ cert->serial_number().size())); |
+ info->Set("subject", ExtractDN(cert->subject())); |
+ info->Set("issuer", ExtractDN(cert->issuer())); |
+ |
+ std::vector<std::string>* dns_names = new std::vector<std::string>; |
+ std::vector<std::string>* ip_addrs = new std::vector<std::string>; |
+ cert->GetSubjectAltName(dns_names, ip_addrs); |
+ if (dns_names->size() > 0) { |
+ base::ListValue* names = new base::ListValue(); |
+ names->AppendStrings(*dns_names); |
+ info->Set("DNSNames", names); |
+ } |
+ if (ip_addrs->size() > 0) { |
+ base::ListValue* addrs = new base::ListValue(); |
+ addrs->AppendStrings(*ip_addrs); |
+ info->Set("IPAddresses", addrs); |
+ } |
+ |
+ info->SetBoolean("expired", cert->HasExpired()); |
+ info->SetDouble("notBefore", cert->valid_start().ToJsTime()); |
+ info->SetDouble("notAfter", cert->valid_expiry().ToJsTime()); |
+ |
+ std::string der_holder; |
+ if (!cert->GetDEREncoded(cert->os_cert_handle(), &der_holder)) |
+ return info; |
+ info->Set("raw", base::BinaryValue::CreateWithCopiedBuffer( |
+ der_holder.c_str(), der_holder.size())); |
+ |
+ return info; |
+} |
+ |
+base::ListValue* ExtractCertificateChain( |
+ scoped_refptr<net::X509Certificate> cert) { |
+ base::ListValue* chain = new base::ListValue(); |
+ if (cert) { |
+ chain->Append(ExtractCertificateInfo(cert)); |
+ const net::X509Certificate::OSCertHandles cert_handles = |
+ cert->GetIntermediateCertificates(); |
+ const net::X509Certificate::OSCertHandles empty_handle; |
+ for (size_t i = 0; i < cert_handles.size(); i++) { |
+ scoped_refptr<net::X509Certificate> interCert; |
+ interCert = |
+ net::X509Certificate::CreateFromHandle(cert_handles[i], empty_handle); |
+ chain->Append(ExtractCertificateInfo(interCert)); |
+ } |
+ } |
+ return chain; |
+} |
+ |
+static std::unordered_map<net::CertStatus, int> status_to_error_map = { |
+ {net::CERT_STATUS_REVOKED, net::ERR_CERT_REVOKED}, |
+ {net::CERT_STATUS_INVALID, net::ERR_CERT_INVALID}, |
+ {net::CERT_STATUS_PINNED_KEY_MISSING, |
+ net::ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN}, |
+ {net::CERT_STATUS_AUTHORITY_INVALID, net::ERR_CERT_AUTHORITY_INVALID}, |
+ {net::CERT_STATUS_COMMON_NAME_INVALID, net::ERR_CERT_COMMON_NAME_INVALID}, |
+ {net::CERT_STATUS_NAME_CONSTRAINT_VIOLATION, |
+ net::ERR_CERT_NAME_CONSTRAINT_VIOLATION}, |
+ {net::CERT_STATUS_WEAK_SIGNATURE_ALGORITHM, |
+ net::ERR_CERT_WEAK_SIGNATURE_ALGORITHM}, |
+ {net::CERT_STATUS_WEAK_KEY, net::ERR_CERT_WEAK_KEY}, |
+ {net::CERT_STATUS_DATE_INVALID, net::ERR_CERT_DATE_INVALID}, |
+ {net::CERT_STATUS_VALIDITY_TOO_LONG, net::ERR_CERT_VALIDITY_TOO_LONG}, |
+ {net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION, |
+ net::ERR_CERT_UNABLE_TO_CHECK_REVOCATION}, |
+ {net::CERT_STATUS_NO_REVOCATION_MECHANISM, |
+ net::ERR_CERT_NO_REVOCATION_MECHANISM}, |
+ {net::CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED, |
+ net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED}, |
+}; |
+ |
+base::ListValue* ParseCertificateStatusErrors(net::CertStatus status) { |
+ base::ListValue* errors = new base::ListValue(); |
+ for (auto const& error : status_to_error_map) { |
+ if (status & error.first) |
+ errors->AppendString(net::ErrorToShortString(error.second)); |
+ } |
+ return errors; |
+} |
+ |
+base::DictionaryValue* ExtractConnectionInfo(net::SSLInfo ssl_info) { |
+ base::DictionaryValue* conn_info = new base::DictionaryValue(); |
+ |
+ conn_info->SetInteger(keys::kCipherStrengthKey, ssl_info.security_bits); |
+ conn_info->SetBoolean(keys::kClientCertSentKey, ssl_info.client_cert_sent); |
+ conn_info->SetBoolean(keys::kChannelIDSentKey, ssl_info.channel_id_sent); |
+ conn_info->SetBoolean(keys::kTokenBindingNegotiatedKey, |
+ ssl_info.token_binding_negotiated); |
+ |
+ const char* ssl_version; |
+ net::SSLVersionToString(&ssl_version, net::SSLConnectionStatusToVersion( |
+ ssl_info.connection_status)); |
+ if (strncmp(ssl_version, "?", 1) == 0) |
+ ssl_version = "UNKNOWN"; |
+ conn_info->SetString(keys::kSSLVersionKey, ssl_version); |
+ |
+ uint16_t cipher_suite = |
+ net::SSLConnectionStatusToCipherSuite(ssl_info.connection_status); |
+ const char *key_exchange, *cipher, *mac; |
+ bool is_aead; |
+ net::SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, |
+ cipher_suite); |
+ if (strncmp(key_exchange, "?", 1) == 0) |
+ key_exchange = "UNKNOWN"; |
+ if (strncmp(cipher, "?", 1) == 0) |
+ cipher = "UNKNOWN"; |
+ conn_info->SetString(keys::kCipherNameKey, cipher); |
+ conn_info->SetString(keys::kKeyExchangeNameKey, key_exchange); |
+ if (is_aead) |
+ conn_info->SetBoolean(keys::kAEDSuiteKey, true); |
+ else |
+ conn_info->SetString(keys::kMACNameKey, mac); |
+ |
+ int compression_type = |
+ (ssl_info.connection_status >> net::SSL_CONNECTION_COMPRESSION_SHIFT) & |
+ net::SSL_CONNECTION_COMPRESSION_MASK; |
+ if (compression_type == 1) |
+ conn_info->SetBoolean(keys::kDeflateCompressionKey, true); |
+ if ((ssl_info.connection_status & net::SSL_CONNECTION_VERSION_FALLBACK) != 0) |
+ conn_info->SetBoolean(keys::kVersionFallbackKey, true); |
+ if ((ssl_info.connection_status & |
+ net::SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION) != 0) |
+ conn_info->SetBoolean(keys::kNoRenegotiationExtensionKey, true); |
+ |
+ return conn_info; |
+} |
+ |
} // namespace extension_web_request_api_helpers |