Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4935)

Unified Diff: chrome/browser/chromeos/policy/policy_cert_verifier_browsertest.cc

Issue 13532005: Added a PolicyCertVerifier that uses the trust anchors from the ONC policies. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: skip tests when NSS version is too old Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/policy/policy_cert_verifier_browsertest.cc
diff --git a/chrome/browser/chromeos/policy/policy_cert_verifier_browsertest.cc b/chrome/browser/chromeos/policy/policy_cert_verifier_browsertest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c39c460d718353e548446f3ca9a6402d6366ba97
--- /dev/null
+++ b/chrome/browser/chromeos/policy/policy_cert_verifier_browsertest.cc
@@ -0,0 +1,297 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/policy/policy_cert_verifier.h"
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop.h"
+#include "base/run_loop.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chrome/test/base/testing_profile_manager.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/test_browser_thread.h"
+#include "crypto/nss_util.h"
+#include "net/base/net_log.h"
+#include "net/base/test_completion_callback.h"
+#include "net/base/test_data_directory.h"
+#include "net/cert/cert_trust_anchor_provider.h"
+#include "net/cert/cert_verify_proc.h"
+#include "net/cert/cert_verify_result.h"
+#include "net/cert/nss_cert_database.h"
+#include "net/cert/x509_certificate.h"
+#include "net/test/cert_test_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::Mock;
+using testing::ReturnRef;
+
+namespace policy {
+
+namespace {
+
+class MockCertTrustAnchorProvider : public net::CertTrustAnchorProvider {
+ public:
+ MockCertTrustAnchorProvider() {}
+ virtual ~MockCertTrustAnchorProvider() {}
+
+ MOCK_METHOD0(GetAdditionalTrustAnchors, const net::CertificateList&());
+};
+
+} // namespace
+
+// This is actually a unit test, but is linked with browser_tests because
+// importing a certificate into the NSS test database persists for the duration
+// of a process; since each browser_test runs in a separate process then this
+// won't affect subsequent tests.
+// This can be moved to the unittests target once the TODO in ~ScopedTestNSSDB
+// is fixed.
+class PolicyCertVerifierTest : public testing::Test {
+ public:
+ PolicyCertVerifierTest()
+ : cert_db_(NULL),
+ ui_thread_(content::BrowserThread::UI, &loop_),
+ io_thread_(content::BrowserThread::IO, &loop_),
+ profile_manager_(TestingBrowserProcess::GetGlobal()),
+ profile_(NULL) {}
+
+ virtual ~PolicyCertVerifierTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ ASSERT_TRUE(test_nssdb_.is_open());
+ cert_db_ = net::NSSCertDatabase::GetInstance();
+
+ ASSERT_TRUE(profile_manager_.SetUp());
+ profile_ = profile_manager_.CreateTestingProfile("profile");
+
+ cert_verifier_.reset(new PolicyCertVerifier(profile_, &trust_provider_));
+ }
+
+ bool SupportsAdditionalTrustAnchors() {
+ scoped_refptr<net::CertVerifyProc> proc =
pneubeck (no reviews) 2013/04/04 11:22:22 nit: you might drop the local variable.
Joao da Silva 2013/04/04 11:25:35 RefCounted objects have 0 refcounts when they are
+ net::CertVerifyProc::CreateDefault();
+ return proc->SupportsAdditionalTrustAnchors();
+ }
+
+ scoped_refptr<net::X509Certificate> LoadCertificate(const std::string& name,
+ net::CertType type) {
+ scoped_refptr<net::X509Certificate> cert =
+ net::ImportCertFromFile(net::GetTestCertsDirectory(), name);
+
+ // No certificate is trusted right after it's loaded.
+ net::NSSCertDatabase::TrustBits trust =
+ cert_db_->GetCertTrust(cert.get(), type);
+ EXPECT_EQ(net::NSSCertDatabase::TRUST_DEFAULT, trust);
+
+ return cert;
+ }
+
+ protected:
+ crypto::ScopedTestNSSDB test_nssdb_;
+ net::NSSCertDatabase* cert_db_;
+ MessageLoop loop_;
+ content::TestBrowserThread ui_thread_;
+ content::TestBrowserThread io_thread_;
+ TestingProfileManager profile_manager_;
+ TestingProfile* profile_;
+ MockCertTrustAnchorProvider trust_provider_;
+ scoped_ptr<PolicyCertVerifier> cert_verifier_;
+ const net::CertificateList empty_cert_list_;
+};
+
+TEST_F(PolicyCertVerifierTest, VerifyUntrustedCert) {
+ scoped_refptr<net::X509Certificate> cert =
+ LoadCertificate("ok_cert.pem", net::SERVER_CERT);
+ ASSERT_TRUE(cert);
+
+ // |cert| is untrusted, so Verify() fails.
+ net::CertVerifyResult verify_result;
+ net::TestCompletionCallback callback;
+ net::CertVerifier::RequestHandle request_handle;
+ EXPECT_CALL(trust_provider_, GetAdditionalTrustAnchors())
+ .WillOnce(ReturnRef(empty_cert_list_));
+ int error = cert_verifier_->Verify(cert, "127.0.0.1", 0, NULL,
+ &verify_result, callback.callback(),
+ &request_handle, net::BoundNetLog());
+ Mock::VerifyAndClearExpectations(&trust_provider_);
+ ASSERT_EQ(net::ERR_IO_PENDING, error);
+ ASSERT_TRUE(request_handle);
+ error = callback.WaitForResult();
+ EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, error);
+
+ // Issuing the same request again hits the cache. This tests the synchronous
+ // path.
+ EXPECT_CALL(trust_provider_, GetAdditionalTrustAnchors())
+ .WillOnce(ReturnRef(empty_cert_list_));
+ error = cert_verifier_->Verify(cert, "127.0.0.1", 0, NULL,
+ &verify_result, callback.callback(),
+ &request_handle, net::BoundNetLog());
+ Mock::VerifyAndClearExpectations(&trust_provider_);
+ EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, error);
+
+ // The profile is not tainted.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(
+ profile_->GetPrefs()->GetBoolean(prefs::kUsedPolicyCertificatesOnce));
+}
+
+TEST_F(PolicyCertVerifierTest, VerifyTrustedCert) {
+ // |ca_cert| is the issuer of |cert|.
+ scoped_refptr<net::X509Certificate> ca_cert =
+ LoadCertificate("root_ca_cert.crt", net::CA_CERT);
+ ASSERT_TRUE(ca_cert);
+ scoped_refptr<net::X509Certificate> cert =
+ LoadCertificate("ok_cert.pem", net::SERVER_CERT);
+ ASSERT_TRUE(cert);
+
+ // Make the database trust |ca_cert|.
+ net::CertificateList import_list;
+ import_list.push_back(ca_cert);
+ net::NSSCertDatabase::ImportCertFailureList failure_list;
+ ASSERT_TRUE(cert_db_->ImportCACerts(
+ import_list, net::NSSCertDatabase::TRUSTED_SSL, &failure_list));
+ ASSERT_TRUE(failure_list.empty());
+
+ // Verify that it is now trusted.
+ net::NSSCertDatabase::TrustBits trust =
+ cert_db_->GetCertTrust(ca_cert.get(), net::CA_CERT);
+ EXPECT_EQ(net::NSSCertDatabase::TRUSTED_SSL, trust);
+
+ // Verify() successfully verifies |cert| after it was imported.
+ net::CertVerifyResult verify_result;
+ net::TestCompletionCallback callback;
+ net::CertVerifier::RequestHandle request_handle;
+ EXPECT_CALL(trust_provider_, GetAdditionalTrustAnchors())
+ .WillOnce(ReturnRef(empty_cert_list_));
+ int error = cert_verifier_->Verify(cert, "127.0.0.1", 0, NULL,
+ &verify_result, callback.callback(),
+ &request_handle, net::BoundNetLog());
+ Mock::VerifyAndClearExpectations(&trust_provider_);
+ ASSERT_EQ(net::ERR_IO_PENDING, error);
+ ASSERT_TRUE(request_handle);
+ error = callback.WaitForResult();
+ EXPECT_EQ(net::OK, error);
+
+ // The profile is not tainted, since the certificate is trusted from the
+ // database.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(
+ profile_->GetPrefs()->GetBoolean(prefs::kUsedPolicyCertificatesOnce));
+}
+
+TEST_F(PolicyCertVerifierTest, VerifyUsingAdditionalTrustAnchor) {
+ if (!SupportsAdditionalTrustAnchors()) {
+ LOG(INFO) << "Test skipped on this platform. NSS >= 3.14.2 required.";
+ return;
+ }
+
+ // |ca_cert| is the issuer of |cert|.
+ scoped_refptr<net::X509Certificate> ca_cert =
+ LoadCertificate("root_ca_cert.crt", net::CA_CERT);
+ ASSERT_TRUE(ca_cert);
+ scoped_refptr<net::X509Certificate> cert =
+ LoadCertificate("ok_cert.pem", net::SERVER_CERT);
+ ASSERT_TRUE(cert);
+
+ net::CertificateList additional_trust_anchors;
+ additional_trust_anchors.push_back(ca_cert);
+
+ // Verify() successfully verifies |cert|, using |ca_cert| from the list of
+ // |additional_trust_anchors|.
+ net::CertVerifyResult verify_result;
+ net::TestCompletionCallback callback;
+ net::CertVerifier::RequestHandle request_handle;
+ EXPECT_CALL(trust_provider_, GetAdditionalTrustAnchors())
+ .WillOnce(ReturnRef(additional_trust_anchors));
+ int error = cert_verifier_->Verify(cert, "127.0.0.1", 0, NULL,
+ &verify_result, callback.callback(),
+ &request_handle, net::BoundNetLog());
+ Mock::VerifyAndClearExpectations(&trust_provider_);
+ ASSERT_EQ(net::ERR_IO_PENDING, error);
+ ASSERT_TRUE(request_handle);
+ error = callback.WaitForResult();
+ EXPECT_EQ(net::OK, error);
+
+ // The profile becomes tainted after using the trust anchors that came from
+ // the policy configuration.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(
+ profile_->GetPrefs()->GetBoolean(prefs::kUsedPolicyCertificatesOnce));
+}
+
+TEST_F(PolicyCertVerifierTest, ProfileRemainsTainted) {
+ if (!SupportsAdditionalTrustAnchors()) {
+ LOG(INFO) << "Test skipped on this platform. NSS >= 3.14.2 required.";
+ return;
+ }
+
+ // |ca_cert| is the issuer of |cert|.
+ scoped_refptr<net::X509Certificate> ca_cert =
+ LoadCertificate("root_ca_cert.crt", net::CA_CERT);
+ ASSERT_TRUE(ca_cert);
+ scoped_refptr<net::X509Certificate> cert =
+ LoadCertificate("ok_cert.pem", net::SERVER_CERT);
+ ASSERT_TRUE(cert);
+
+ net::CertificateList additional_trust_anchors;
+ additional_trust_anchors.push_back(ca_cert);
+
+ // |cert| is untrusted, so Verify() fails.
+ net::CertVerifyResult verify_result;
+ net::TestCompletionCallback callback;
+ net::CertVerifier::RequestHandle request_handle;
+ EXPECT_CALL(trust_provider_, GetAdditionalTrustAnchors())
+ .WillOnce(ReturnRef(empty_cert_list_));
+ int error = cert_verifier_->Verify(cert, "127.0.0.1", 0, NULL,
+ &verify_result, callback.callback(),
+ &request_handle, net::BoundNetLog());
+ Mock::VerifyAndClearExpectations(&trust_provider_);
+ ASSERT_EQ(net::ERR_IO_PENDING, error);
+ ASSERT_TRUE(request_handle);
+ error = callback.WaitForResult();
+ EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, error);
+
+ // The profile is not tainted.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(
+ profile_->GetPrefs()->GetBoolean(prefs::kUsedPolicyCertificatesOnce));
+
+ // Verify() again with the additional trust anchors.
+ EXPECT_CALL(trust_provider_, GetAdditionalTrustAnchors())
+ .WillOnce(ReturnRef(additional_trust_anchors));
+ error = cert_verifier_->Verify(cert, "127.0.0.1", 0, NULL,
+ &verify_result, callback.callback(),
+ &request_handle, net::BoundNetLog());
+ Mock::VerifyAndClearExpectations(&trust_provider_);
+ ASSERT_EQ(net::ERR_IO_PENDING, error);
+ ASSERT_TRUE(request_handle);
+ error = callback.WaitForResult();
+ EXPECT_EQ(net::OK, error);
+
+ // The profile becomes tainted after using the trust anchors that came from
+ // the policy configuration.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(
+ profile_->GetPrefs()->GetBoolean(prefs::kUsedPolicyCertificatesOnce));
+
+ // Verifying after removing the trust anchors should now fail.
+ EXPECT_CALL(trust_provider_, GetAdditionalTrustAnchors())
+ .WillOnce(ReturnRef(empty_cert_list_));
+ error = cert_verifier_->Verify(cert, "127.0.0.1", 0, NULL,
+ &verify_result, callback.callback(),
+ &request_handle, net::BoundNetLog());
+ Mock::VerifyAndClearExpectations(&trust_provider_);
+ // Note: this hits the cached result from the first Verify() in this test.
+ EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, error);
+
+ // The profile is still tainted.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(
+ profile_->GetPrefs()->GetBoolean(prefs::kUsedPolicyCertificatesOnce));
+}
+
+} // namespace policy
« no previous file with comments | « chrome/browser/chromeos/policy/policy_cert_verifier.cc ('k') | chrome/browser/policy/browser_policy_connector.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698