diff options
Diffstat (limited to 'chromium/net/cert/nss_cert_database_chromeos_unittest.cc')
-rw-r--r-- | chromium/net/cert/nss_cert_database_chromeos_unittest.cc | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/chromium/net/cert/nss_cert_database_chromeos_unittest.cc b/chromium/net/cert/nss_cert_database_chromeos_unittest.cc new file mode 100644 index 00000000000..324575d0b1e --- /dev/null +++ b/chromium/net/cert/nss_cert_database_chromeos_unittest.cc @@ -0,0 +1,279 @@ +// Copyright 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 "net/cert/nss_cert_database_chromeos.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "base/message_loop/message_loop_proxy.h" +#include "base/run_loop.h" +#include "crypto/nss_util.h" +#include "crypto/nss_util_internal.h" +#include "net/base/test_data_directory.h" +#include "net/cert/cert_database.h" +#include "net/test/cert_test_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +namespace { + +bool IsCertInCertificateList(const X509Certificate* cert, + const CertificateList& cert_list) { + for (CertificateList::const_iterator it = cert_list.begin(); + it != cert_list.end(); + ++it) { + if (X509Certificate::IsSameOSCert((*it)->os_cert_handle(), + cert->os_cert_handle())) + return true; + } + return false; +} + +void SwapCertLists(CertificateList* destination, + scoped_ptr<CertificateList> source) { + ASSERT_TRUE(destination); + ASSERT_TRUE(source); + + destination->swap(*source); +} + +} // namespace + +class NSSCertDatabaseChromeOSTest : public testing::Test, + public CertDatabase::Observer { + public: + NSSCertDatabaseChromeOSTest() + : observer_added_(false), user_1_("user1"), user_2_("user2") {} + + virtual void SetUp() OVERRIDE { + // Initialize nss_util slots. + ASSERT_TRUE(user_1_.constructed_successfully()); + ASSERT_TRUE(user_2_.constructed_successfully()); + user_1_.FinishInit(); + user_2_.FinishInit(); + + // Create NSSCertDatabaseChromeOS for each user. + db_1_.reset(new NSSCertDatabaseChromeOS( + crypto::GetPublicSlotForChromeOSUser(user_1_.username_hash()), + crypto::GetPrivateSlotForChromeOSUser( + user_1_.username_hash(), + base::Callback<void(crypto::ScopedPK11Slot)>()))); + db_1_->SetSlowTaskRunnerForTest(base::MessageLoopProxy::current()); + db_2_.reset(new NSSCertDatabaseChromeOS( + crypto::GetPublicSlotForChromeOSUser(user_2_.username_hash()), + crypto::GetPrivateSlotForChromeOSUser( + user_2_.username_hash(), + base::Callback<void(crypto::ScopedPK11Slot)>()))); + db_2_->SetSlowTaskRunnerForTest(base::MessageLoopProxy::current()); + + // Add observer to CertDatabase for checking that notifications from + // NSSCertDatabaseChromeOS are proxied to the CertDatabase. + CertDatabase::GetInstance()->AddObserver(this); + observer_added_ = true; + } + + virtual void TearDown() OVERRIDE { + if (observer_added_) + CertDatabase::GetInstance()->RemoveObserver(this); + } + + // CertDatabase::Observer: + virtual void OnCertAdded(const X509Certificate* cert) OVERRIDE { + added_.push_back(cert ? cert->os_cert_handle() : NULL); + } + + virtual void OnCertRemoved(const X509Certificate* cert) OVERRIDE {} + + virtual void OnCACertChanged(const X509Certificate* cert) OVERRIDE { + added_ca_.push_back(cert ? cert->os_cert_handle() : NULL); + } + + protected: + bool observer_added_; + // Certificates that were passed to the CertDatabase observers. + std::vector<CERTCertificate*> added_ca_; + std::vector<CERTCertificate*> added_; + + crypto::ScopedTestNSSChromeOSUser user_1_; + crypto::ScopedTestNSSChromeOSUser user_2_; + scoped_ptr<NSSCertDatabaseChromeOS> db_1_; + scoped_ptr<NSSCertDatabaseChromeOS> db_2_; +}; + +// Test that ListModules() on each user includes that user's NSS software slot, +// and does not include the software slot of the other user. (Does not check the +// private slot, since it is the same as the public slot in tests.) +TEST_F(NSSCertDatabaseChromeOSTest, ListModules) { + CryptoModuleList modules_1; + CryptoModuleList modules_2; + + db_1_->ListModules(&modules_1, false /* need_rw */); + db_2_->ListModules(&modules_2, false /* need_rw */); + + bool found_1 = false; + for (CryptoModuleList::iterator it = modules_1.begin(); it != modules_1.end(); + ++it) { + EXPECT_NE(db_2_->GetPublicSlot().get(), (*it)->os_module_handle()); + if ((*it)->os_module_handle() == db_1_->GetPublicSlot().get()) + found_1 = true; + } + EXPECT_TRUE(found_1); + + bool found_2 = false; + for (CryptoModuleList::iterator it = modules_2.begin(); it != modules_2.end(); + ++it) { + EXPECT_NE(db_1_->GetPublicSlot().get(), (*it)->os_module_handle()); + if ((*it)->os_module_handle() == db_2_->GetPublicSlot().get()) + found_2 = true; + } + EXPECT_TRUE(found_2); +} + +// Test that ImportCACerts imports the cert to the correct slot, and that +// ListCerts includes the added cert for the correct user, and does not include +// it for the other user. +TEST_F(NSSCertDatabaseChromeOSTest, ImportCACerts) { + // Load test certs from disk. + CertificateList certs_1 = + CreateCertificateListFromFile(GetTestCertsDirectory(), + "root_ca_cert.pem", + X509Certificate::FORMAT_AUTO); + ASSERT_EQ(1U, certs_1.size()); + + CertificateList certs_2 = + CreateCertificateListFromFile(GetTestCertsDirectory(), + "2048-rsa-root.pem", + X509Certificate::FORMAT_AUTO); + ASSERT_EQ(1U, certs_2.size()); + + // Import one cert for each user. + NSSCertDatabase::ImportCertFailureList failed; + EXPECT_TRUE( + db_1_->ImportCACerts(certs_1, NSSCertDatabase::TRUSTED_SSL, &failed)); + EXPECT_EQ(0U, failed.size()); + failed.clear(); + EXPECT_TRUE( + db_2_->ImportCACerts(certs_2, NSSCertDatabase::TRUSTED_SSL, &failed)); + EXPECT_EQ(0U, failed.size()); + + // Get cert list for each user. + CertificateList user_1_certlist; + CertificateList user_2_certlist; + db_1_->ListCertsSync(&user_1_certlist); + db_2_->ListCertsSync(&user_2_certlist); + + // Check that the imported certs only shows up in the list for the user that + // imported them. + EXPECT_TRUE(IsCertInCertificateList(certs_1[0], user_1_certlist)); + EXPECT_FALSE(IsCertInCertificateList(certs_1[0], user_2_certlist)); + + EXPECT_TRUE(IsCertInCertificateList(certs_2[0], user_2_certlist)); + EXPECT_FALSE(IsCertInCertificateList(certs_2[0], user_1_certlist)); + + // Run the message loop so the observer notifications get processed. + base::RunLoop().RunUntilIdle(); + // Should have gotten two OnCACertChanged notifications. + ASSERT_EQ(2U, added_ca_.size()); + // TODO(mattm): make NSSCertDatabase actually pass the cert to the callback, + // and enable these checks: + // EXPECT_EQ(certs_1[0]->os_cert_handle(), added_ca_[0]); + // EXPECT_EQ(certs_2[0]->os_cert_handle(), added_ca_[1]); + EXPECT_EQ(0U, added_.size()); + + // Tests that the new certs are loaded by async ListCerts method. + CertificateList user_1_certlist_async; + CertificateList user_2_certlist_async; + db_1_->ListCerts( + base::Bind(&SwapCertLists, base::Unretained(&user_1_certlist_async))); + db_2_->ListCerts( + base::Bind(&SwapCertLists, base::Unretained(&user_2_certlist_async))); + + base::RunLoop().RunUntilIdle(); + + EXPECT_TRUE(IsCertInCertificateList(certs_1[0], user_1_certlist_async)); + EXPECT_FALSE(IsCertInCertificateList(certs_1[0], user_2_certlist_async)); + + EXPECT_TRUE(IsCertInCertificateList(certs_2[0], user_2_certlist_async)); + EXPECT_FALSE(IsCertInCertificateList(certs_2[0], user_1_certlist_async)); +} + +// Test that ImportServerCerts imports the cert to the correct slot, and that +// ListCerts includes the added cert for the correct user, and does not include +// it for the other user. +TEST_F(NSSCertDatabaseChromeOSTest, ImportServerCert) { + // Load test certs from disk. + CertificateList certs_1 = CreateCertificateListFromFile( + GetTestCertsDirectory(), "ok_cert.pem", X509Certificate::FORMAT_AUTO); + ASSERT_EQ(1U, certs_1.size()); + + CertificateList certs_2 = + CreateCertificateListFromFile(GetTestCertsDirectory(), + "2048-rsa-ee-by-2048-rsa-intermediate.pem", + X509Certificate::FORMAT_AUTO); + ASSERT_EQ(1U, certs_2.size()); + + // Import one cert for each user. + NSSCertDatabase::ImportCertFailureList failed; + EXPECT_TRUE( + db_1_->ImportServerCert(certs_1, NSSCertDatabase::TRUSTED_SSL, &failed)); + EXPECT_EQ(0U, failed.size()); + failed.clear(); + EXPECT_TRUE( + db_2_->ImportServerCert(certs_2, NSSCertDatabase::TRUSTED_SSL, &failed)); + EXPECT_EQ(0U, failed.size()); + + // Get cert list for each user. + CertificateList user_1_certlist; + CertificateList user_2_certlist; + db_1_->ListCertsSync(&user_1_certlist); + db_2_->ListCertsSync(&user_2_certlist); + + // Check that the imported certs only shows up in the list for the user that + // imported them. + EXPECT_TRUE(IsCertInCertificateList(certs_1[0], user_1_certlist)); + EXPECT_FALSE(IsCertInCertificateList(certs_1[0], user_2_certlist)); + + EXPECT_TRUE(IsCertInCertificateList(certs_2[0], user_2_certlist)); + EXPECT_FALSE(IsCertInCertificateList(certs_2[0], user_1_certlist)); + + // Run the message loop so the observer notifications get processed. + base::RunLoop().RunUntilIdle(); + // TODO(mattm): ImportServerCert doesn't actually cause any observers to + // fire. Is that correct? + EXPECT_EQ(0U, added_ca_.size()); + EXPECT_EQ(0U, added_.size()); + + // Tests that the new certs are loaded by async ListCerts method. + CertificateList user_1_certlist_async; + CertificateList user_2_certlist_async; + db_1_->ListCerts( + base::Bind(&SwapCertLists, base::Unretained(&user_1_certlist_async))); + db_2_->ListCerts( + base::Bind(&SwapCertLists, base::Unretained(&user_2_certlist_async))); + + base::RunLoop().RunUntilIdle(); + + EXPECT_TRUE(IsCertInCertificateList(certs_1[0], user_1_certlist_async)); + EXPECT_FALSE(IsCertInCertificateList(certs_1[0], user_2_certlist_async)); + + EXPECT_TRUE(IsCertInCertificateList(certs_2[0], user_2_certlist_async)); + EXPECT_FALSE(IsCertInCertificateList(certs_2[0], user_1_certlist_async)); +} + +// Tests that There is no crash if the database is deleted while ListCerts +// is being processed on the worker pool. +TEST_F(NSSCertDatabaseChromeOSTest, NoCrashIfShutdownBeforeDoneOnWorkerPool) { + CertificateList certlist; + db_1_->ListCerts(base::Bind(&SwapCertLists, base::Unretained(&certlist))); + EXPECT_EQ(0U, certlist.size()); + + db_1_.reset(); + + base::RunLoop().RunUntilIdle(); + + EXPECT_LT(0U, certlist.size()); +} + +} // namespace net |