policy_cert_verifier_browsertest.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/policy/policy_cert_verifier.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/memory/ref_counted.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/message_loop.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/run_loop.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/test/base/testing_browser_process.h"
13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/test/base/testing_profile.h"
14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/test/base/testing_profile_manager.h"
15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/public/browser/browser_thread.h"
16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/public/test/test_browser_thread.h"
17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "crypto/nss_util.h"
1868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "net/base/net_log.h"
19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/base/test_completion_callback.h"
20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/base/test_data_directory.h"
21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/cert/cert_trust_anchor_provider.h"
22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/cert/cert_verify_proc.h"
23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/cert/cert_verify_result.h"
24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/cert/nss_cert_database.h"
25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/cert/x509_certificate.h"
26116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/test/cert_test_util.h"
27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "testing/gmock/include/gmock/gmock.h"
28116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "testing/gtest/include/gtest/gtest.h"
29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
30116680a4aac90f2aa7413d9095a592090648e557Ben Murdochusing testing::Mock;
31116680a4aac90f2aa7413d9095a592090648e557Ben Murdochusing testing::ReturnRef;
32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
3368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace policy {
345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
35116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace {
36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
37116680a4aac90f2aa7413d9095a592090648e557Ben Murdochclass MockCertTrustAnchorProvider : public net::CertTrustAnchorProvider {
38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public:
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockCertTrustAnchorProvider() {}
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MockCertTrustAnchorProvider() {}
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MOCK_METHOD0(GetAdditionalTrustAnchors, const net::CertificateList&());
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is actually a unit test, but is linked with browser_tests because
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// importing a certificate into the NSS test database persists for the duration
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of a process; since each browser_test runs in a separate process then this
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// won't affect subsequent tests.
5168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// This can be moved to the unittests target once the TODO in ~ScopedTestNSSDB
5268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// is fixed.
5368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)class PolicyCertVerifierTest : public testing::Test {
5468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) public:
5568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  PolicyCertVerifierTest()
5668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      : cert_db_(NULL),
57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        ui_thread_(content::BrowserThread::UI, &loop_),
58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        io_thread_(content::BrowserThread::IO, &loop_),
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        profile_manager_(TestingBrowserProcess::GetGlobal()),
6068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        profile_(NULL) {}
6168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual ~PolicyCertVerifierTest() {}
63d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
64d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  virtual void SetUp() OVERRIDE {
65d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ASSERT_TRUE(test_nssdb_.is_open());
6668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    cert_db_ = net::NSSCertDatabase::GetInstance();
6768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(profile_manager_.SetUp());
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    profile_ = profile_manager_.CreateTestingProfile("profile");
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
71d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    cert_verifier_.reset(new PolicyCertVerifier(profile_, &trust_provider_));
72d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
73d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool SupportsAdditionalTrustAnchors() {
7568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    scoped_refptr<net::CertVerifyProc> proc =
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net::CertVerifyProc::CreateDefault();
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return proc->SupportsAdditionalTrustAnchors();
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<net::X509Certificate> LoadCertificate(const std::string& name,
8168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                                      net::CertType type) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<net::X509Certificate> cert =
83d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        net::ImportCertFromFile(net::GetTestCertsDirectory(), name);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // No certificate is trusted right after it's loaded.
8668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    net::NSSCertDatabase::TrustBits trust =
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cert_db_->GetCertTrust(cert.get(), type);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(net::NSSCertDatabase::TRUST_DEFAULT, trust);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return cert;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
92d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  crypto::ScopedTestNSSDB test_nssdb_;
9568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  net::NSSCertDatabase* cert_db_;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::MessageLoop loop_;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread ui_thread_;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread io_thread_;
9968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  TestingProfileManager profile_manager_;
10068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  TestingProfile* profile_;
10168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  MockCertTrustAnchorProvider trust_provider_;
10268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  scoped_ptr<PolicyCertVerifier> cert_verifier_;
10368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const net::CertificateList empty_cert_list_;
10468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)};
10568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
10668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)TEST_F(PolicyCertVerifierTest, VerifyUntrustedCert) {
10768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  scoped_refptr<net::X509Certificate> cert =
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LoadCertificate("ok_cert.pem", net::SERVER_CERT);
109d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_TRUE(cert.get());
11068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
11168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // |cert| is untrusted, so Verify() fails.
11268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  net::CertVerifyResult verify_result;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::TestCompletionCallback callback;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::CertVerifier::RequestHandle request_handle;
11568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_CALL(trust_provider_, GetAdditionalTrustAnchors())
11668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      .WillOnce(ReturnRef(empty_cert_list_));
11768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int error = cert_verifier_->Verify(cert.get(),
11868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                     "127.0.0.1",
11968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                     0,
12068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                     NULL,
12168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                     &verify_result,
12268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                     callback.callback(),
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     &request_handle,
12468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                     net::BoundNetLog());
12568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  Mock::VerifyAndClearExpectations(&trust_provider_);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(net::ERR_IO_PENDING, error);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(request_handle);
12868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  error = callback.WaitForResult();
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, error);
130d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Issuing the same request again hits the cache. This tests the synchronous
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // path.
13368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_CALL(trust_provider_, GetAdditionalTrustAnchors())
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .WillOnce(ReturnRef(empty_cert_list_));
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  error = cert_verifier_->Verify(cert.get(),
13668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                 "127.0.0.1",
13768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                 0,
13868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                 NULL,
13968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                 &verify_result,
14068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                 callback.callback(),
14168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                 &request_handle,
14268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                 net::BoundNetLog());
14368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  Mock::VerifyAndClearExpectations(&trust_provider_);
14468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, error);
14568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
14668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // The profile is not tainted.
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(
14968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      profile_->GetPrefs()->GetBoolean(prefs::kUsedPolicyCertificatesOnce));
15068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
15168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
15268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)TEST_F(PolicyCertVerifierTest, VerifyTrustedCert) {
15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // |ca_cert| is the issuer of |cert|.
15468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  scoped_refptr<net::X509Certificate> ca_cert =
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LoadCertificate("root_ca_cert.pem", net::CA_CERT);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(ca_cert.get());
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<net::X509Certificate> cert =
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LoadCertificate("ok_cert.pem", net::SERVER_CERT);
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(cert.get());
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make the database trust |ca_cert|.
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::CertificateList import_list;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  import_list.push_back(ca_cert);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::NSSCertDatabase::ImportCertFailureList failure_list;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(cert_db_->ImportCACerts(
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      import_list, net::NSSCertDatabase::TRUSTED_SSL, &failure_list));
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(failure_list.empty());
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that it is now trusted.
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::NSSCertDatabase::TrustBits trust =
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cert_db_->GetCertTrust(ca_cert.get(), net::CA_CERT);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(net::NSSCertDatabase::TRUSTED_SSL, trust);
173
174  // Verify() successfully verifies |cert| after it was imported.
175  net::CertVerifyResult verify_result;
176  net::TestCompletionCallback callback;
177  net::CertVerifier::RequestHandle request_handle;
178  EXPECT_CALL(trust_provider_, GetAdditionalTrustAnchors())
179      .WillOnce(ReturnRef(empty_cert_list_));
180  int error = cert_verifier_->Verify(cert.get(),
181                                     "127.0.0.1",
182                                     0,
183                                     NULL,
184                                     &verify_result,
185                                     callback.callback(),
186                                     &request_handle,
187                                     net::BoundNetLog());
188  Mock::VerifyAndClearExpectations(&trust_provider_);
189  ASSERT_EQ(net::ERR_IO_PENDING, error);
190  ASSERT_TRUE(request_handle);
191  error = callback.WaitForResult();
192  EXPECT_EQ(net::OK, error);
193
194  // The profile is not tainted, since the certificate is trusted from the
195  // database.
196  base::RunLoop().RunUntilIdle();
197  EXPECT_FALSE(
198      profile_->GetPrefs()->GetBoolean(prefs::kUsedPolicyCertificatesOnce));
199}
200
201TEST_F(PolicyCertVerifierTest, VerifyUsingAdditionalTrustAnchor) {
202  if (!SupportsAdditionalTrustAnchors()) {
203    LOG(INFO) << "Test skipped on this platform. NSS >= 3.14.2 required.";
204    return;
205  }
206
207  // |ca_cert| is the issuer of |cert|.
208  scoped_refptr<net::X509Certificate> ca_cert =
209      LoadCertificate("root_ca_cert.pem", net::CA_CERT);
210  ASSERT_TRUE(ca_cert.get());
211  scoped_refptr<net::X509Certificate> cert =
212      LoadCertificate("ok_cert.pem", net::SERVER_CERT);
213  ASSERT_TRUE(cert.get());
214
215  net::CertificateList additional_trust_anchors;
216  additional_trust_anchors.push_back(ca_cert);
217
218  // Verify() successfully verifies |cert|, using |ca_cert| from the list of
219  // |additional_trust_anchors|.
220  net::CertVerifyResult verify_result;
221  net::TestCompletionCallback callback;
222  net::CertVerifier::RequestHandle request_handle;
223  EXPECT_CALL(trust_provider_, GetAdditionalTrustAnchors())
224      .WillOnce(ReturnRef(additional_trust_anchors));
225  int error = cert_verifier_->Verify(cert.get(),
226                                     "127.0.0.1",
227                                     0,
228                                     NULL,
229                                     &verify_result,
230                                     callback.callback(),
231                                     &request_handle,
232                                     net::BoundNetLog());
233  Mock::VerifyAndClearExpectations(&trust_provider_);
234  ASSERT_EQ(net::ERR_IO_PENDING, error);
235  ASSERT_TRUE(request_handle);
236  error = callback.WaitForResult();
237  EXPECT_EQ(net::OK, error);
238
239  // The profile becomes tainted after using the trust anchors that came from
240  // the policy configuration.
241  base::RunLoop().RunUntilIdle();
242  EXPECT_TRUE(
243      profile_->GetPrefs()->GetBoolean(prefs::kUsedPolicyCertificatesOnce));
244}
245
246TEST_F(PolicyCertVerifierTest, ProfileRemainsTainted) {
247  if (!SupportsAdditionalTrustAnchors()) {
248    LOG(INFO) << "Test skipped on this platform. NSS >= 3.14.2 required.";
249    return;
250  }
251
252  // |ca_cert| is the issuer of |cert|.
253  scoped_refptr<net::X509Certificate> ca_cert =
254      LoadCertificate("root_ca_cert.pem", net::CA_CERT);
255  ASSERT_TRUE(ca_cert.get());
256  scoped_refptr<net::X509Certificate> cert =
257      LoadCertificate("ok_cert.pem", net::SERVER_CERT);
258  ASSERT_TRUE(cert.get());
259
260  net::CertificateList additional_trust_anchors;
261  additional_trust_anchors.push_back(ca_cert);
262
263  // |cert| is untrusted, so Verify() fails.
264  net::CertVerifyResult verify_result;
265  net::TestCompletionCallback callback;
266  net::CertVerifier::RequestHandle request_handle;
267  EXPECT_CALL(trust_provider_, GetAdditionalTrustAnchors())
268      .WillOnce(ReturnRef(empty_cert_list_));
269  int error = cert_verifier_->Verify(cert.get(),
270                                     "127.0.0.1",
271                                     0,
272                                     NULL,
273                                     &verify_result,
274                                     callback.callback(),
275                                     &request_handle,
276                                     net::BoundNetLog());
277  Mock::VerifyAndClearExpectations(&trust_provider_);
278  ASSERT_EQ(net::ERR_IO_PENDING, error);
279  ASSERT_TRUE(request_handle);
280  error = callback.WaitForResult();
281  EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, error);
282
283  // The profile is not tainted.
284  base::RunLoop().RunUntilIdle();
285  EXPECT_FALSE(
286      profile_->GetPrefs()->GetBoolean(prefs::kUsedPolicyCertificatesOnce));
287
288  // Verify() again with the additional trust anchors.
289  EXPECT_CALL(trust_provider_, GetAdditionalTrustAnchors())
290      .WillOnce(ReturnRef(additional_trust_anchors));
291  error = cert_verifier_->Verify(cert.get(),
292                                 "127.0.0.1",
293                                 0,
294                                 NULL,
295                                 &verify_result,
296                                 callback.callback(),
297                                 &request_handle,
298                                 net::BoundNetLog());
299  Mock::VerifyAndClearExpectations(&trust_provider_);
300  ASSERT_EQ(net::ERR_IO_PENDING, error);
301  ASSERT_TRUE(request_handle);
302  error = callback.WaitForResult();
303  EXPECT_EQ(net::OK, error);
304
305  // The profile becomes tainted after using the trust anchors that came from
306  // the policy configuration.
307  base::RunLoop().RunUntilIdle();
308  EXPECT_TRUE(
309      profile_->GetPrefs()->GetBoolean(prefs::kUsedPolicyCertificatesOnce));
310
311  // Verifying after removing the trust anchors should now fail.
312  EXPECT_CALL(trust_provider_, GetAdditionalTrustAnchors())
313      .WillOnce(ReturnRef(empty_cert_list_));
314  error = cert_verifier_->Verify(cert.get(),
315                                 "127.0.0.1",
316                                 0,
317                                 NULL,
318                                 &verify_result,
319                                 callback.callback(),
320                                 &request_handle,
321                                 net::BoundNetLog());
322  Mock::VerifyAndClearExpectations(&trust_provider_);
323  // Note: this hits the cached result from the first Verify() in this test.
324  EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, error);
325
326  // The profile is still tainted.
327  base::RunLoop().RunUntilIdle();
328  EXPECT_TRUE(
329      profile_->GetPrefs()->GetBoolean(prefs::kUsedPolicyCertificatesOnce));
330}
331
332}  // namespace policy
333