| 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
|
|
|