#include "net/cert/cert_verify_proc_android.h"
#include <memory>
#include <vector>
#include "net/cert/cert_net_fetcher.h"
#include "net/cert/cert_verify_proc_android.h"
#include "net/cert/cert_verify_result.h"
#include "net/cert/crl_set.h"
#include "net/cert/internal/test_helpers.h"
#include "net/cert/mock_cert_net_fetcher.h"
#include "net/cert/test_root_certs.h"
#include "net/cert/x509_certificate.h"
#include "net/cert/x509_util.h"
#include "net/log/net_log_with_source.h"
#include "net/test/cert_builder.h"
#include "net/test/cert_test_util.h"
#include "net/test/test_certificate_data.h"
#include "net/test/test_data_directory.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
using ::testing::ByMove;
using ::testing::Return;
using ::testing::_;
namespace net {
namespace {
const char kHostname[] = "example.com";
const GURL kRootURL("http://aia.test/root");
const GURL kIntermediateURL("http://aia.test/intermediate");
std::unique_ptr<CertNetFetcher::Request>
CreateMockRequestWithInvalidCertificate() {
return MockCertNetFetcherRequest::Create(std::vector<uint8_t>({1, 2, 3}));
}
class CertVerifyProcAndroidTestWithAIAFetching : public testing::Test {
public:
void SetUp() override {
fetcher_ = base::MakeRefCounted<MockCertNetFetcher>();
std::tie(leaf_, intermediate_, root_) = CertBuilder::CreateSimpleChain3();
root_->SetCaIssuersUrl(kRootURL);
intermediate_->SetCaIssuersUrl(kRootURL);
leaf_->SetCaIssuersUrl(kIntermediateURL);
leaf_->SetSubjectAltName(kHostname);
}
void TearDown() override {
ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(fetcher_.get()));
}
scoped_refptr<X509Certificate> LeafOnly() {
return leaf_->GetX509Certificate();
}
scoped_refptr<X509Certificate> LeafWithIntermediate() {
return leaf_->GetX509CertificateChain();
}
protected:
void TrustTestRoot() {
scoped_test_root_.Reset({root_->GetX509Certificate()});
}
scoped_refptr<MockCertNetFetcher> fetcher_;
std::unique_ptr<CertBuilder> root_;
std::unique_ptr<CertBuilder> intermediate_;
std::unique_ptr<CertBuilder> leaf_;
private:
ScopedTestRoot scoped_test_root_;
};
}
TEST_F(CertVerifyProcAndroidTestWithAIAFetching,
NoFetchIfProperIntermediatesSupplied) {
TrustTestRoot();
scoped_refptr<CertVerifyProcAndroid> proc =
base::MakeRefCounted<CertVerifyProcAndroid>(fetcher_,
CRLSet::BuiltinCRLSet());
CertVerifyResult verify_result;
EXPECT_EQ(OK, proc->Verify(LeafWithIntermediate().get(), kHostname,
std::string(),
std::string(), 0, &verify_result,
NetLogWithSource()));
}
TEST_F(CertVerifyProcAndroidTestWithAIAFetching, NoAIAURL) {
leaf_->SetCaIssuersAndOCSPUrls(std::vector<GURL>(),
std::vector<GURL>());
TrustTestRoot();
scoped_refptr<CertVerifyProcAndroid> proc =
base::MakeRefCounted<CertVerifyProcAndroid>(fetcher_,
CRLSet::BuiltinCRLSet());
CertVerifyResult verify_result;
EXPECT_EQ(
ERR_CERT_AUTHORITY_INVALID,
proc->Verify(LeafOnly().get(), kHostname, std::string(),
std::string(), 0, &verify_result,
NetLogWithSource()));
}
TEST_F(CertVerifyProcAndroidTestWithAIAFetching, OneFileAndOneHTTPURL) {
const GURL kFileURL("file:///dev/null");
leaf_->SetCaIssuersAndOCSPUrls(
{kFileURL, kIntermediateURL},
{});
TrustTestRoot();
scoped_refptr<CertVerifyProcAndroid> proc =
base::MakeRefCounted<CertVerifyProcAndroid>(fetcher_,
CRLSet::BuiltinCRLSet());
EXPECT_CALL(*fetcher_, FetchCaIssuers(kFileURL, _, _))
.WillOnce(Return(ByMove(
MockCertNetFetcherRequest::Create(ERR_DISALLOWED_URL_SCHEME))));
EXPECT_CALL(*fetcher_, FetchCaIssuers(kIntermediateURL, _, _))
.WillOnce(Return(ByMove(
MockCertNetFetcherRequest::Create(intermediate_->GetCertBuffer()))));
CertVerifyResult verify_result;
EXPECT_EQ(OK, proc->Verify(LeafOnly().get(), kHostname,
std::string(),
std::string(), 0, &verify_result,
NetLogWithSource()));
}
TEST_F(CertVerifyProcAndroidTestWithAIAFetching,
UnsuccessfulVerificationWithLeafOnly) {
TrustTestRoot();
scoped_refptr<CertVerifyProcAndroid> proc =
base::MakeRefCounted<CertVerifyProcAndroid>(fetcher_,
CRLSet::BuiltinCRLSet());
const scoped_refptr<X509Certificate> bad_intermediate =
ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
EXPECT_CALL(*fetcher_, FetchCaIssuers(kIntermediateURL, _, _))
.WillOnce(Return(ByMove(
MockCertNetFetcherRequest::Create(bad_intermediate->cert_buffer()))));
CertVerifyResult verify_result;
EXPECT_EQ(
ERR_CERT_AUTHORITY_INVALID,
proc->Verify(LeafOnly().get(), kHostname, std::string(),
std::string(), 0, &verify_result,
NetLogWithSource()));
}
TEST_F(CertVerifyProcAndroidTestWithAIAFetching,
UnsuccessfulVerificationWithLeafOnlyAndErrorOnFetch) {
TrustTestRoot();
scoped_refptr<CertVerifyProcAndroid> proc =
base::MakeRefCounted<CertVerifyProcAndroid>(fetcher_,
CRLSet::BuiltinCRLSet());
EXPECT_CALL(*fetcher_, FetchCaIssuers(kIntermediateURL, _, _))
.WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(ERR_FAILED))));
CertVerifyResult verify_result;
EXPECT_EQ(
ERR_CERT_AUTHORITY_INVALID,
proc->Verify(LeafOnly().get(), kHostname, std::string(),
std::string(), 0, &verify_result,
NetLogWithSource()));
}
TEST_F(CertVerifyProcAndroidTestWithAIAFetching,
UnsuccessfulVerificationWithLeafOnlyAndUnparseableFetch) {
TrustTestRoot();
scoped_refptr<CertVerifyProcAndroid> proc =
base::MakeRefCounted<CertVerifyProcAndroid>(fetcher_,
CRLSet::BuiltinCRLSet());
EXPECT_CALL(*fetcher_, FetchCaIssuers(kIntermediateURL, _, _))
.WillOnce(Return(ByMove(CreateMockRequestWithInvalidCertificate())));
CertVerifyResult verify_result;
EXPECT_EQ(
ERR_CERT_AUTHORITY_INVALID,
proc->Verify(LeafOnly().get(), kHostname, std::string(),
std::string(), 0, &verify_result,
NetLogWithSource()));
}
TEST_F(CertVerifyProcAndroidTestWithAIAFetching, TwoHTTPURLs) {
const GURL kUnrelatedURL("http://aia.test/unrelated");
leaf_->SetCaIssuersAndOCSPUrls(
{kUnrelatedURL, kIntermediateURL},
{});
scoped_refptr<X509Certificate> unrelated =
ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
ASSERT_TRUE(unrelated);
TrustTestRoot();
scoped_refptr<CertVerifyProcAndroid> proc =
base::MakeRefCounted<CertVerifyProcAndroid>(fetcher_,
CRLSet::BuiltinCRLSet());
EXPECT_CALL(*fetcher_, FetchCaIssuers(kUnrelatedURL, _, _))
.WillOnce(Return(
ByMove(MockCertNetFetcherRequest::Create(unrelated->cert_buffer()))));
EXPECT_CALL(*fetcher_, FetchCaIssuers(kIntermediateURL, _, _))
.WillOnce(Return(ByMove(
MockCertNetFetcherRequest::Create(intermediate_->GetCertBuffer()))));
CertVerifyResult verify_result;
EXPECT_EQ(OK, proc->Verify(LeafOnly().get(), kHostname,
std::string(),
std::string(), 0, &verify_result,
NetLogWithSource()));
}
TEST_F(CertVerifyProcAndroidTestWithAIAFetching,
AIAFetchForFetchedIntermediate) {
scoped_refptr<CertVerifyProcAndroid> proc =
base::MakeRefCounted<CertVerifyProcAndroid>(fetcher_,
CRLSet::BuiltinCRLSet());
EXPECT_CALL(*fetcher_, FetchCaIssuers(kIntermediateURL, _, _))
.WillOnce(Return(ByMove(
MockCertNetFetcherRequest::Create(intermediate_->GetCertBuffer()))));
EXPECT_CALL(*fetcher_, FetchCaIssuers(kRootURL, _, _))
.WillOnce(Return(
ByMove(MockCertNetFetcherRequest::Create(root_->GetCertBuffer()))));
CertVerifyResult verify_result;
EXPECT_EQ(
ERR_CERT_AUTHORITY_INVALID,
proc->Verify(LeafOnly().get(), kHostname, std::string(),
std::string(), 0, &verify_result,
NetLogWithSource()));
}
TEST_F(CertVerifyProcAndroidTestWithAIAFetching, MaxAIAFetches) {
leaf_->SetCaIssuersAndOCSPUrls(
{GURL("http://aia.test/1"), GURL("http://aia.test/2"),
GURL("http://aia.test/3"), GURL("http://aia.test/4"),
GURL("http://aia.test/5"),
GURL("http://aia.test/6")},
{});
TrustTestRoot();
scoped_refptr<CertVerifyProcAndroid> proc =
base::MakeRefCounted<CertVerifyProcAndroid>(fetcher_,
CRLSet::BuiltinCRLSet());
EXPECT_CALL(*fetcher_, FetchCaIssuers(_, _, _))
.WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(ERR_FAILED))))
.WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(ERR_FAILED))))
.WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(ERR_FAILED))))
.WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(ERR_FAILED))))
.WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(ERR_FAILED))));
CertVerifyResult verify_result;
EXPECT_EQ(
ERR_CERT_AUTHORITY_INVALID,
proc->Verify(LeafOnly().get(), kHostname, std::string(),
std::string(), 0, &verify_result,
NetLogWithSource()));
}
TEST_F(CertVerifyProcAndroidTestWithAIAFetching, FetchForSuppliedIntermediate) {
scoped_refptr<CertVerifyProcAndroid> proc =
base::MakeRefCounted<CertVerifyProcAndroid>(fetcher_,
CRLSet::BuiltinCRLSet());
EXPECT_CALL(*fetcher_, FetchCaIssuers(kRootURL, _, _))
.WillOnce(Return(
ByMove(MockCertNetFetcherRequest::Create(root_->GetCertBuffer()))));
CertVerifyResult verify_result;
EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID,
proc->Verify(LeafWithIntermediate().get(), kHostname,
std::string(),
std::string(), 0, &verify_result,
NetLogWithSource()));
}
}