Add net error code for self-signed certs on local network URLs
This adds (behind a new, default disabled feature flag) a new net error code (ERR_CERT_SELF_SIGNED_LOCAL_NETWORK), which is returned for certificate errors when the certificate is self-signed, and is being used on a local network URL (either an RFC 1918 IP, or a URL that ends in .local). This is step one towards implementing go/betterselfsigned, for now this only results in the regular SSL interstitial being triggered. Bug: 394119724 Change-Id: I62850128c250358071cc0693526b23c2677647cf Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6226147 Commit-Queue: Carlos IL <carlosil@chromium.org> Reviewed-by: Matt Mueller <mattm@chromium.org> Cr-Commit-Position: refs/heads/main@{#1424804}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
859865d196
commit
9f2a0256c7
components
net
@ -26,6 +26,7 @@ int IsCertErrorFatal(int cert_error) {
|
||||
case net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED:
|
||||
case net::ERR_CERT_SYMANTEC_LEGACY:
|
||||
case net::ERR_CERT_KNOWN_INTERCEPTION_BLOCKED:
|
||||
case net::ERR_CERT_SELF_SIGNED_LOCAL_NETWORK:
|
||||
return false;
|
||||
case net::ERR_CERT_CONTAINS_ERRORS:
|
||||
case net::ERR_CERT_REVOKED:
|
||||
|
@ -100,6 +100,7 @@ ErrorInfo ErrorInfo::CreateError(ErrorType error_type,
|
||||
case CERT_KNOWN_INTERCEPTION_BLOCKED:
|
||||
case CERT_AUTHORITY_INVALID:
|
||||
case CERT_SYMANTEC_LEGACY:
|
||||
case CERT_SELF_SIGNED_LOCAL_NETWORK:
|
||||
details =
|
||||
l10n_util::GetStringFUTF16(IDS_CERT_ERROR_AUTHORITY_INVALID_DETAILS,
|
||||
UTF8ToUTF16(request_url.host()));
|
||||
@ -235,6 +236,8 @@ ErrorInfo::ErrorType ErrorInfo::NetErrorToErrorType(int net_error) {
|
||||
return CERT_SYMANTEC_LEGACY;
|
||||
case net::ERR_CERT_KNOWN_INTERCEPTION_BLOCKED:
|
||||
return CERT_KNOWN_INTERCEPTION_BLOCKED;
|
||||
case net::ERR_CERT_SELF_SIGNED_LOCAL_NETWORK:
|
||||
return CERT_SELF_SIGNED_LOCAL_NETWORK;
|
||||
default:
|
||||
NOTREACHED();
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ class ErrorInfo {
|
||||
CERT_KNOWN_INTERCEPTION_BLOCKED = 17,
|
||||
LEGACY_TLS = 18,
|
||||
CERT_NON_UNIQUE_NAME = 19,
|
||||
CERT_SELF_SIGNED_LOCAL_NETWORK = 20,
|
||||
END_OF_ENUM
|
||||
};
|
||||
|
||||
|
@ -708,4 +708,8 @@ BASE_FEATURE(kUseCertTransparencyAwareApiForOsCertVerify,
|
||||
base::FEATURE_ENABLED_BY_DEFAULT);
|
||||
#endif // BUILDFLAG(IS_ANDROID)
|
||||
|
||||
BASE_FEATURE(kSelfSignedLocalNetworkInterstitial,
|
||||
"SelfSignedLocalNetworkInterstitial",
|
||||
base::FEATURE_DISABLED_BY_DEFAULT);
|
||||
|
||||
} // namespace net::features
|
||||
|
@ -725,6 +725,10 @@ NET_EXPORT BASE_DECLARE_FEATURE(kExcludeLargeBodyReports);
|
||||
NET_EXPORT BASE_DECLARE_FEATURE(kUseCertTransparencyAwareApiForOsCertVerify);
|
||||
#endif // BUILDFLAG(IS_ANDROID)
|
||||
|
||||
// Enables a special interstitial for self signed cert errors in local network
|
||||
// URLs.
|
||||
NET_EXPORT BASE_DECLARE_FEATURE(kSelfSignedLocalNetworkInterstitial);
|
||||
|
||||
} // namespace net::features
|
||||
|
||||
#endif // NET_BASE_FEATURES_H_
|
||||
|
@ -564,13 +564,17 @@ NET_ERROR(CERT_KNOWN_INTERCEPTION_BLOCKED, -217)
|
||||
// -218 was SSL_OBSOLETE_VERSION which is not longer used. TLS 1.0/1.1 instead
|
||||
// cause SSL_VERSION_OR_CIPHER_MISMATCH now.
|
||||
|
||||
// The certificate is self signed and it's being used for either an RFC1918 IP
|
||||
// literal URL, or a url ending in .local.
|
||||
NET_ERROR(CERT_SELF_SIGNED_LOCAL_NETWORK, -219)
|
||||
|
||||
// Add new certificate error codes here.
|
||||
//
|
||||
// Update the value of CERT_END whenever you add a new certificate error
|
||||
// code.
|
||||
|
||||
// The value immediately past the last certificate error code.
|
||||
NET_ERROR(CERT_END, -219)
|
||||
NET_ERROR(CERT_END, -220)
|
||||
|
||||
// The URL is invalid.
|
||||
NET_ERROR(INVALID_URL, -300)
|
||||
|
@ -29,6 +29,7 @@ TEST(NetErrorsTest, IsCertificateError) {
|
||||
EXPECT_TRUE(IsCertificateError(ERR_CERT_WEAK_SIGNATURE_ALGORITHM));
|
||||
EXPECT_TRUE(IsCertificateError(ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN));
|
||||
EXPECT_TRUE(IsCertificateError(ERR_CERT_KNOWN_INTERCEPTION_BLOCKED));
|
||||
EXPECT_TRUE(IsCertificateError(ERR_CERT_SELF_SIGNED_LOCAL_NETWORK));
|
||||
|
||||
// Negative tests.
|
||||
EXPECT_FALSE(IsCertificateError(ERR_SSL_PROTOCOL_ERROR));
|
||||
@ -42,7 +43,7 @@ TEST(NetErrorsTest, IsCertificateError) {
|
||||
|
||||
// Trigger a failure whenever ERR_CERT_END is changed, forcing developers to
|
||||
// update this test.
|
||||
EXPECT_EQ(ERR_CERT_END, -219)
|
||||
EXPECT_EQ(ERR_CERT_END, -220)
|
||||
<< "It looks like you added a new certificate error code ("
|
||||
<< ErrorToString(ERR_CERT_END + 1)
|
||||
<< ").\n"
|
||||
|
@ -353,6 +353,14 @@ std::string CanonicalizeHost(std::string_view host,
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::string CanonicalizeHostSupportsBareIPV6(std::string_view host,
|
||||
url::CanonHostInfo* host_info) {
|
||||
const std::string host_or_ip = host.find(':') != std::string::npos
|
||||
? base::StrCat({"[", host, "]"})
|
||||
: std::string(host);
|
||||
return CanonicalizeHost(host_or_ip, host_info);
|
||||
}
|
||||
|
||||
std::string CanonicalizeHost(std::string_view host,
|
||||
url::CanonHostInfo* host_info) {
|
||||
return CanonicalizeHost(host, /*is_file_scheme=*/false, host_info);
|
||||
|
@ -167,6 +167,12 @@ NET_EXPORT std::string GetSuperdomain(std::string_view domain);
|
||||
NET_EXPORT bool IsSubdomainOf(std::string_view subdomain,
|
||||
std::string_view superdomain);
|
||||
|
||||
// Wrapper for CanonicalizeHost that allows using a bare IPV6. If |host| is
|
||||
// not IPV6, this is equivalent to CanonicalizeHost.
|
||||
NET_EXPORT std::string CanonicalizeHostSupportsBareIPV6(
|
||||
std::string_view host,
|
||||
url::CanonHostInfo* host_info);
|
||||
|
||||
// Canonicalizes |host| and returns it. Also fills |host_info| with
|
||||
// IP address information. |host_info| must not be NULL.
|
||||
// Canonicalization will follow the host parsing rules for a non-file
|
||||
|
@ -25,10 +25,15 @@ int MapCertStatusToNetError(CertStatus cert_status) {
|
||||
return ERR_CERT_KNOWN_INTERCEPTION_BLOCKED;
|
||||
if (cert_status & CERT_STATUS_REVOKED)
|
||||
return ERR_CERT_REVOKED;
|
||||
if (cert_status & CERT_STATUS_AUTHORITY_INVALID)
|
||||
if (cert_status & CERT_STATUS_AUTHORITY_INVALID &&
|
||||
!(cert_status & CERT_STATUS_SELF_SIGNED_LOCAL_NETWORK)) {
|
||||
return ERR_CERT_AUTHORITY_INVALID;
|
||||
}
|
||||
if (cert_status & CERT_STATUS_COMMON_NAME_INVALID)
|
||||
return ERR_CERT_COMMON_NAME_INVALID;
|
||||
if (cert_status & CERT_STATUS_SELF_SIGNED_LOCAL_NETWORK) {
|
||||
return ERR_CERT_SELF_SIGNED_LOCAL_NETWORK;
|
||||
}
|
||||
if (cert_status & CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED)
|
||||
return ERR_CERTIFICATE_TRANSPARENCY_REQUIRED;
|
||||
if (cert_status & CERT_STATUS_SYMANTEC_LEGACY)
|
||||
|
@ -45,3 +45,4 @@ CERT_STATUS_FLAG(CERTIFICATE_TRANSPARENCY_REQUIRED, 1 << 24)
|
||||
CERT_STATUS_FLAG(SYMANTEC_LEGACY, 1 << 25)
|
||||
CERT_STATUS_FLAG(KNOWN_INTERCEPTION_BLOCKED, 1 << 26)
|
||||
// Bit 27 was CERT_STATUS_LEGACY_TLS.
|
||||
CERT_STATUS_FLAG(SELF_SIGNED_LOCAL_NETWORK, 1 << 28)
|
||||
|
@ -13,6 +13,8 @@
|
||||
#include "base/feature_list.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/strings/strcat.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/time/time.h"
|
||||
#include "base/values.h"
|
||||
#include "components/network_time/time_tracker/time_tracker.h"
|
||||
@ -20,6 +22,7 @@
|
||||
#include "net/base/features.h"
|
||||
#include "net/base/ip_address.h"
|
||||
#include "net/base/net_errors.h"
|
||||
#include "net/base/url_util.h"
|
||||
#include "net/cert/cert_net_fetcher.h"
|
||||
#include "net/cert/cert_status_flags.h"
|
||||
#include "net/cert/cert_verifier.h"
|
||||
@ -49,6 +52,7 @@
|
||||
#include "third_party/boringssl/src/pki/trust_store.h"
|
||||
#include "third_party/boringssl/src/pki/trust_store_collection.h"
|
||||
#include "third_party/boringssl/src/pki/trust_store_in_memory.h"
|
||||
#include "url/url_canon.h"
|
||||
|
||||
#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
|
||||
#include "base/version_info/version_info.h" // nogncheck
|
||||
@ -188,6 +192,37 @@ bool IsEVCandidate(const EVRootCAMetadata* ev_metadata,
|
||||
return !oids.empty();
|
||||
}
|
||||
|
||||
bool IsSelfSignedCertOnLocalNetwork(const X509Certificate* cert,
|
||||
const std::string& hostname) {
|
||||
if (!base::FeatureList::IsEnabled(
|
||||
features::kSelfSignedLocalNetworkInterstitial)) {
|
||||
return false;
|
||||
}
|
||||
url::CanonHostInfo host_info;
|
||||
std::string canonicalized_hostname =
|
||||
CanonicalizeHostSupportsBareIPV6(hostname, &host_info);
|
||||
if (canonicalized_hostname.empty()) {
|
||||
return false;
|
||||
}
|
||||
if (host_info.IsIPAddress()) {
|
||||
base::span<uint8_t> ip_span(host_info.address);
|
||||
// AddressLength() is always 0, 4, or 16, so it's safe to cast to unsigned.
|
||||
IPAddress ip(
|
||||
ip_span.first(static_cast<unsigned>(host_info.AddressLength())));
|
||||
if (ip.IsPubliclyRoutable()) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!base::EndsWith(canonicalized_hostname, ".local",
|
||||
base::CompareCase::INSENSITIVE_ASCII) &&
|
||||
!base::EndsWith(canonicalized_hostname, ".local.",
|
||||
base::CompareCase::INSENSITIVE_ASCII)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return X509Certificate::IsSelfSigned(cert->cert_buffer());
|
||||
}
|
||||
|
||||
// CertVerifyProcTrustStore wraps a SystemTrustStore with additional trust
|
||||
// anchors and TestRootCerts.
|
||||
class CertVerifyProcTrustStore {
|
||||
@ -1158,9 +1193,13 @@ int AssignVerifyResult(X509Certificate* input_cert,
|
||||
verify_result->policy_compliance = delegate_data->ct_policy_compliance;
|
||||
}
|
||||
|
||||
return IsCertStatusError(verify_result->cert_status)
|
||||
? MapCertStatusToNetError(verify_result->cert_status)
|
||||
: OK;
|
||||
if (IsCertStatusError(verify_result->cert_status)) {
|
||||
if (IsSelfSignedCertOnLocalNetwork(input_cert, hostname)) {
|
||||
verify_result->cert_status |= CERT_STATUS_SELF_SIGNED_LOCAL_NETWORK;
|
||||
}
|
||||
return MapCertStatusToNetError(verify_result->cert_status);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
// Returns true if retrying path building with a less stringent signature
|
||||
|
@ -20,8 +20,10 @@
|
||||
#include "base/time/time.h"
|
||||
#include "components/network_time/time_tracker/time_tracker.h"
|
||||
#include "net/base/features.h"
|
||||
#include "net/base/ip_address.h"
|
||||
#include "net/base/net_errors.h"
|
||||
#include "net/base/test_completion_callback.h"
|
||||
#include "net/cert/cert_status_flags.h"
|
||||
#include "net/cert/cert_verify_proc.h"
|
||||
#include "net/cert/crl_set.h"
|
||||
#include "net/cert/do_nothing_ct_verifier.h"
|
||||
@ -29,6 +31,7 @@
|
||||
#include "net/cert/internal/system_trust_store.h"
|
||||
#include "net/cert/sct_status_flags.h"
|
||||
#include "net/cert/time_conversions.h"
|
||||
#include "net/cert/x509_certificate.h"
|
||||
#include "net/cert/x509_util.h"
|
||||
#include "net/cert_net/cert_net_fetcher_url_request.h"
|
||||
#include "net/http/transport_security_state.h"
|
||||
@ -2111,4 +2114,211 @@ TEST_F(CertVerifyProcBuiltinTest, IterationLimit) {
|
||||
EXPECT_EQ(true, event->params.FindBool("exceeded_iteration_limit"));
|
||||
}
|
||||
|
||||
class CertVerifyProcBuiltinSelfSignedTest
|
||||
: public CertVerifyProcBuiltinTest,
|
||||
public testing::WithParamInterface<bool> {
|
||||
public:
|
||||
CertVerifyProcBuiltinSelfSignedTest() {
|
||||
if (GetParam()) {
|
||||
feature_list_.InitAndEnableFeature(
|
||||
features::kSelfSignedLocalNetworkInterstitial);
|
||||
} else {
|
||||
feature_list_.InitAndDisableFeature(
|
||||
features::kSelfSignedLocalNetworkInterstitial);
|
||||
}
|
||||
}
|
||||
|
||||
scoped_refptr<X509Certificate> CreateSelfSigned(
|
||||
std::string_view subject_dns_name) {
|
||||
// Create a chain of size 1, which will result in a self-signed certificate
|
||||
std::vector<std::unique_ptr<CertBuilder>> builders =
|
||||
CertBuilder::CreateSimpleChain(1);
|
||||
base::Time not_before = base::Time::Now() - base::Days(1);
|
||||
base::Time not_after = base::Time::Now() + base::Days(1);
|
||||
builders[0]->SetValidity(not_before, not_after);
|
||||
builders[0]->SetSubjectAltName(subject_dns_name);
|
||||
return builders[0]->GetX509Certificate();
|
||||
}
|
||||
|
||||
scoped_refptr<X509Certificate> CreateSelfSignedIPSubject(
|
||||
std::string_view ip_address) {
|
||||
// Create a chain of size 1, which will result in a self-signed certificate
|
||||
std::vector<std::unique_ptr<CertBuilder>> builders =
|
||||
CertBuilder::CreateSimpleChain(1);
|
||||
base::Time not_before = base::Time::Now() - base::Days(1);
|
||||
base::Time not_after = base::Time::Now() + base::Days(1);
|
||||
builders[0]->SetValidity(not_before, not_after);
|
||||
IPAddress ip;
|
||||
if (!ParseURLHostnameToAddress(ip_address, &ip)) {
|
||||
ADD_FAILURE() << "Failed to parse IP address";
|
||||
}
|
||||
|
||||
builders[0]->SetSubjectAltNames({}, {ip});
|
||||
return builders[0]->GetX509Certificate();
|
||||
}
|
||||
|
||||
private:
|
||||
base::test::ScopedFeatureList feature_list_;
|
||||
};
|
||||
|
||||
TEST_P(CertVerifyProcBuiltinSelfSignedTest,
|
||||
SelfSignedCertOnLocalNetworkHostname) {
|
||||
scoped_refptr<X509Certificate> cert = CreateSelfSigned("testurl.local");
|
||||
|
||||
CertVerifyResult verify_result;
|
||||
NetLogSource verify_net_log_source;
|
||||
TestCompletionCallback callback;
|
||||
Verify(cert, "testurl.local", 0, &verify_result, &verify_net_log_source,
|
||||
callback.callback());
|
||||
int error = callback.WaitForResult();
|
||||
|
||||
if (GetParam()) {
|
||||
EXPECT_TRUE(verify_result.cert_status &
|
||||
CERT_STATUS_SELF_SIGNED_LOCAL_NETWORK);
|
||||
EXPECT_THAT(error, IsError(ERR_CERT_SELF_SIGNED_LOCAL_NETWORK));
|
||||
} else {
|
||||
EXPECT_FALSE(verify_result.cert_status &
|
||||
CERT_STATUS_SELF_SIGNED_LOCAL_NETWORK);
|
||||
EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(CertVerifyProcBuiltinSelfSignedTest, SelfSignedCertOnLocalNetworkIP) {
|
||||
scoped_refptr<X509Certificate> cert =
|
||||
CreateSelfSignedIPSubject("192.168.0.1");
|
||||
|
||||
CertVerifyResult verify_result;
|
||||
NetLogSource verify_net_log_source;
|
||||
TestCompletionCallback callback;
|
||||
Verify(cert, "192.168.0.1", 0, &verify_result, &verify_net_log_source,
|
||||
callback.callback());
|
||||
int error = callback.WaitForResult();
|
||||
|
||||
if (GetParam()) {
|
||||
EXPECT_TRUE(verify_result.cert_status &
|
||||
CERT_STATUS_SELF_SIGNED_LOCAL_NETWORK);
|
||||
EXPECT_THAT(error, IsError(ERR_CERT_SELF_SIGNED_LOCAL_NETWORK));
|
||||
} else {
|
||||
EXPECT_FALSE(verify_result.cert_status &
|
||||
CERT_STATUS_SELF_SIGNED_LOCAL_NETWORK);
|
||||
EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(CertVerifyProcBuiltinSelfSignedTest, SelfSignedCertOnLocalNetworkIPv6) {
|
||||
scoped_refptr<X509Certificate> cert =
|
||||
CreateSelfSignedIPSubject("[fc00:0:0:0:0:0:0:0]");
|
||||
|
||||
CertVerifyResult verify_result;
|
||||
NetLogSource verify_net_log_source;
|
||||
TestCompletionCallback callback;
|
||||
Verify(cert, "fc00:0:0:0:0:0:0:0", 0, &verify_result, &verify_net_log_source,
|
||||
callback.callback());
|
||||
int error = callback.WaitForResult();
|
||||
|
||||
if (GetParam()) {
|
||||
EXPECT_TRUE(verify_result.cert_status &
|
||||
CERT_STATUS_SELF_SIGNED_LOCAL_NETWORK);
|
||||
EXPECT_THAT(error, IsError(ERR_CERT_SELF_SIGNED_LOCAL_NETWORK));
|
||||
} else {
|
||||
EXPECT_FALSE(verify_result.cert_status &
|
||||
CERT_STATUS_SELF_SIGNED_LOCAL_NETWORK);
|
||||
EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(CertVerifyProcBuiltinSelfSignedTest, NonSelfSignedCertOnLocalNetwork) {
|
||||
std::vector<std::unique_ptr<CertBuilder>> builders =
|
||||
CertBuilder::CreateSimpleChain(2);
|
||||
|
||||
base::Time not_before = base::Time::Now() - base::Days(2);
|
||||
base::Time not_after = base::Time::Now() - base::Days(2);
|
||||
builders[0]->SetValidity(not_before, not_after);
|
||||
builders[0]->SetSubjectAltName("testurl.local");
|
||||
|
||||
CertVerifyResult verify_result;
|
||||
NetLogSource verify_net_log_source;
|
||||
TestCompletionCallback callback;
|
||||
Verify(builders[0]->GetX509CertificateChain(), "testurl.local", 0,
|
||||
&verify_result, &verify_net_log_source, callback.callback());
|
||||
int error = callback.WaitForResult();
|
||||
|
||||
EXPECT_FALSE(verify_result.cert_status &
|
||||
CERT_STATUS_SELF_SIGNED_LOCAL_NETWORK);
|
||||
EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
|
||||
}
|
||||
|
||||
TEST_P(CertVerifyProcBuiltinSelfSignedTest,
|
||||
SelfSignedCertNotLocalNetworkHostname) {
|
||||
scoped_refptr<X509Certificate> cert = CreateSelfSigned("www.example.com");
|
||||
|
||||
CertVerifyResult verify_result;
|
||||
NetLogSource verify_net_log_source;
|
||||
TestCompletionCallback callback;
|
||||
Verify(cert, "www.example.com", 0, &verify_result, &verify_net_log_source,
|
||||
callback.callback());
|
||||
int error = callback.WaitForResult();
|
||||
|
||||
EXPECT_FALSE(verify_result.cert_status &
|
||||
CERT_STATUS_SELF_SIGNED_LOCAL_NETWORK);
|
||||
EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
|
||||
}
|
||||
|
||||
TEST_P(CertVerifyProcBuiltinSelfSignedTest, SelfSignedCertNotLocalNetworkIP) {
|
||||
scoped_refptr<X509Certificate> cert = CreateSelfSignedIPSubject("8.8.8.8");
|
||||
|
||||
CertVerifyResult verify_result;
|
||||
NetLogSource verify_net_log_source;
|
||||
TestCompletionCallback callback;
|
||||
Verify(cert, "8.8.8.8", 0, &verify_result, &verify_net_log_source,
|
||||
callback.callback());
|
||||
int error = callback.WaitForResult();
|
||||
|
||||
EXPECT_FALSE(verify_result.cert_status &
|
||||
CERT_STATUS_SELF_SIGNED_LOCAL_NETWORK);
|
||||
EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
|
||||
}
|
||||
|
||||
TEST_P(CertVerifyProcBuiltinSelfSignedTest, SelfSignedCertNotLocalNetworkIPv6) {
|
||||
scoped_refptr<X509Certificate> cert =
|
||||
CreateSelfSignedIPSubject("[2001:4860:4860::8888]");
|
||||
|
||||
CertVerifyResult verify_result;
|
||||
NetLogSource verify_net_log_source;
|
||||
TestCompletionCallback callback;
|
||||
Verify(cert, "2001:4860:4860::8888", 0, &verify_result,
|
||||
&verify_net_log_source, callback.callback());
|
||||
int error = callback.WaitForResult();
|
||||
|
||||
EXPECT_FALSE(verify_result.cert_status &
|
||||
CERT_STATUS_SELF_SIGNED_LOCAL_NETWORK);
|
||||
EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
|
||||
}
|
||||
|
||||
TEST_P(CertVerifyProcBuiltinSelfSignedTest,
|
||||
SelfSignedCertOnLocalNetworkHostnameNameMismatchTakesPrecedence) {
|
||||
scoped_refptr<X509Certificate> cert = CreateSelfSigned("nottesturl.local");
|
||||
|
||||
CertVerifyResult verify_result;
|
||||
NetLogSource verify_net_log_source;
|
||||
TestCompletionCallback callback;
|
||||
Verify(cert, "testurl.local", 0, &verify_result, &verify_net_log_source,
|
||||
callback.callback());
|
||||
int error = callback.WaitForResult();
|
||||
|
||||
if (GetParam()) {
|
||||
EXPECT_TRUE(verify_result.cert_status &
|
||||
CERT_STATUS_SELF_SIGNED_LOCAL_NETWORK);
|
||||
EXPECT_THAT(error, IsError(ERR_CERT_COMMON_NAME_INVALID));
|
||||
} else {
|
||||
EXPECT_FALSE(verify_result.cert_status &
|
||||
CERT_STATUS_SELF_SIGNED_LOCAL_NETWORK);
|
||||
EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID));
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(SelfSignedInterstitial,
|
||||
CertVerifyProcBuiltinSelfSignedTest,
|
||||
testing::Bool());
|
||||
|
||||
} // namespace net
|
||||
|
@ -452,12 +452,9 @@ bool X509Certificate::VerifyHostname(
|
||||
// access, i.e. the thing displayed in the URL bar.
|
||||
// Presented identifier(s) == name(s) the server knows itself as, in its cert.
|
||||
|
||||
// CanonicalizeHost requires surrounding brackets to parse an IPv6 address.
|
||||
const std::string host_or_ip = hostname.find(':') != std::string::npos
|
||||
? base::StrCat({"[", hostname, "]"})
|
||||
: std::string(hostname);
|
||||
url::CanonHostInfo host_info;
|
||||
std::string reference_name = CanonicalizeHost(host_or_ip, &host_info);
|
||||
std::string reference_name =
|
||||
CanonicalizeHostSupportsBareIPV6(hostname, &host_info);
|
||||
|
||||
// If the host cannot be canonicalized, fail fast.
|
||||
if (reference_name.empty())
|
||||
|
Reference in New Issue
Block a user