diff options
author | mattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-12 02:17:08 +0000 |
---|---|---|
committer | mattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-12 02:17:08 +0000 |
commit | 8405da12256819349baf47280fcd495bb796a723 (patch) | |
tree | 83f1b318ee853e10985a47a70dcd00d8049b2803 | |
parent | e1751fb1116682ffba80cbc127b9da66c6d72a3c (diff) | |
download | chromium_src-8405da12256819349baf47280fcd495bb796a723.zip chromium_src-8405da12256819349baf47280fcd495bb796a723.tar.gz chromium_src-8405da12256819349baf47280fcd495bb796a723.tar.bz2 |
CertDatabase: Add ImportServerCerts method.
BUG=19991
TEST=net_unittests
Review URL: http://codereview.chromium.org/3576016
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@62228 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | net/base/cert_database.h | 11 | ||||
-rw-r--r-- | net/base/cert_database_nss.cc | 5 | ||||
-rw-r--r-- | net/base/cert_database_nss_unittest.cc | 71 | ||||
-rw-r--r-- | net/base/net_error_list.h | 3 | ||||
-rw-r--r-- | net/third_party/mozilla_security_manager/nsNSSCertificateDB.cpp | 36 | ||||
-rw-r--r-- | net/third_party/mozilla_security_manager/nsNSSCertificateDB.h | 3 |
6 files changed, 129 insertions, 0 deletions
diff --git a/net/base/cert_database.h b/net/base/cert_database.h index 113a658..a40a56f 100644 --- a/net/base/cert_database.h +++ b/net/base/cert_database.h @@ -100,6 +100,17 @@ class CertDatabase { unsigned int trust_bits, ImportCertFailureList* not_imported); + // Import server certificate. The first cert should be the server cert. Any + // additional certs should be intermediate/CA certs and will be imported but + // not given any trust. + // Any certificates that could not be imported will be listed in + // |not_imported|. + // Returns false if there is an internal error, otherwise true is returned and + // |not_imported| should be checked for any certificates that were not + // imported. + bool ImportServerCert(const CertificateList& certificates, + ImportCertFailureList* not_imported); + // Get trust bits for certificate. unsigned int GetCertTrust(const X509Certificate* cert, CertType type) const; diff --git a/net/base/cert_database_nss.cc b/net/base/cert_database_nss.cc index 45b2e66..2c1ad92 100644 --- a/net/base/cert_database_nss.cc +++ b/net/base/cert_database_nss.cc @@ -148,6 +148,11 @@ bool CertDatabase::ImportCACerts(const CertificateList& certificates, return psm::ImportCACerts(certificates, root, trust_bits, not_imported); } +bool CertDatabase::ImportServerCert(const CertificateList& certificates, + ImportCertFailureList* not_imported) { + return psm::ImportServerCert(certificates, not_imported); +} + unsigned int CertDatabase::GetCertTrust( const X509Certificate* cert, CertType type) const { CERTCertTrust nsstrust; diff --git a/net/base/cert_database_nss_unittest.cc b/net/base/cert_database_nss_unittest.cc index 40754d8..c68b6fd 100644 --- a/net/base/cert_database_nss_unittest.cc +++ b/net/base/cert_database_nss_unittest.cc @@ -17,6 +17,8 @@ #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "net/base/cert_database.h" +#include "net/base/cert_status_flags.h" +#include "net/base/cert_verify_result.h" #include "net/base/net_errors.h" #include "net/base/x509_certificate.h" #include "net/third_party/mozilla_security_manager/nsNSSCertificateDB.h" @@ -426,5 +428,74 @@ TEST_F(CertDatabaseNSSTest, ImportCACertNotHierarchy) { EXPECT_EQ("Test CA", cert_list[0]->subject().common_name); } +TEST_F(CertDatabaseNSSTest, ImportServerCert) { + // Need to import intermediate cert for the verify of google cert, otherwise + // it will try to fetch it automatically with cert_pi_useAIACertFetch, which + // will cause OCSPCreateSession on the main thread, which is not allowed. + std::string cert_data = ReadTestFile("google.chain.pem"); + CertificateList certs = + X509Certificate::CreateCertificateListFromBytes( + cert_data.data(), cert_data.size(), X509Certificate::FORMAT_AUTO); + ASSERT_EQ(2U, certs.size()); + + CertDatabase::ImportCertFailureList failed; + EXPECT_EQ(true, cert_db_.ImportServerCert(certs, &failed)); + + EXPECT_EQ(0U, failed.size()); + + CertificateList cert_list = ListCertsInSlot(slot_.get()); + ASSERT_EQ(2U, cert_list.size()); + scoped_refptr<X509Certificate> goog_cert(cert_list[0]); + scoped_refptr<X509Certificate> thawte_cert(cert_list[1]); + EXPECT_EQ("www.google.com", goog_cert->subject().common_name); + EXPECT_EQ("Thawte SGC CA", thawte_cert->subject().common_name); + + EXPECT_EQ(CertDatabase::UNTRUSTED, + cert_db_.GetCertTrust(goog_cert.get(), SERVER_CERT)); + psm::nsNSSCertTrust goog_trust(goog_cert->os_cert_handle()->trust); + EXPECT_TRUE(goog_trust.HasPeer(PR_TRUE, PR_TRUE, PR_TRUE)); + + int flags = 0; + CertVerifyResult verify_result; + int error = goog_cert->Verify("www.google.com", flags, &verify_result); + EXPECT_EQ(OK, error); + EXPECT_EQ(0, verify_result.cert_status); +} + +TEST_F(CertDatabaseNSSTest, ImportServerCert_SelfSigned) { + CertificateList certs; + ASSERT_TRUE(ReadCertIntoList("punycodetest.der", &certs)); + + CertDatabase::ImportCertFailureList failed; + EXPECT_EQ(true, cert_db_.ImportServerCert(certs, &failed)); + + EXPECT_EQ(0U, failed.size()); + + CertificateList cert_list = ListCertsInSlot(slot_.get()); + ASSERT_EQ(1U, cert_list.size()); + scoped_refptr<X509Certificate> puny_cert(cert_list[0]); + + EXPECT_EQ(CertDatabase::UNTRUSTED, + cert_db_.GetCertTrust(puny_cert.get(), SERVER_CERT)); + psm::nsNSSCertTrust puny_trust(puny_cert->os_cert_handle()->trust); + EXPECT_TRUE(puny_trust.HasPeer(PR_TRUE, PR_TRUE, PR_TRUE)); + + int flags = 0; + CertVerifyResult verify_result; + int error = puny_cert->Verify("xn--wgv71a119e.com", flags, &verify_result); + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, error); + EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, verify_result.cert_status); + + // TODO(mattm): this should be SERVER_CERT, not CA_CERT, but that does not + // work due to NSS bug: https://bugzilla.mozilla.org/show_bug.cgi?id=531160 + EXPECT_TRUE(cert_db_.SetCertTrust( + puny_cert.get(), CA_CERT, + CertDatabase::TRUSTED_SSL | CertDatabase::TRUSTED_EMAIL)); + + verify_result.Reset(); + error = puny_cert->Verify("xn--wgv71a119e.com", flags, &verify_result); + EXPECT_EQ(OK, error); + EXPECT_EQ(0, verify_result.cert_status); +} } // namespace net diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h index bd5e71e..7c533f3 100644 --- a/net/base/net_error_list.h +++ b/net/base/net_error_list.h @@ -489,3 +489,6 @@ NET_ERROR(IMPORT_CERT_ALREADY_EXISTS, -704) // CA import failed due to some other error. NET_ERROR(IMPORT_CA_CERT_FAILED, -705) + +// Server certificate import failed due to some internal error. +NET_ERROR(IMPORT_SERVER_CERT_FAILED, -706) diff --git a/net/third_party/mozilla_security_manager/nsNSSCertificateDB.cpp b/net/third_party/mozilla_security_manager/nsNSSCertificateDB.cpp index b32458d..e0876f77 100644 --- a/net/third_party/mozilla_security_manager/nsNSSCertificateDB.cpp +++ b/net/third_party/mozilla_security_manager/nsNSSCertificateDB.cpp @@ -160,6 +160,42 @@ bool ImportCACerts(const net::CertificateList& certificates, return true; } +// Based on nsNSSCertificateDB::ImportServerCertificate. +bool ImportServerCert(const net::CertificateList& certificates, + net::CertDatabase::ImportCertFailureList* not_imported) { + base::ScopedPK11Slot slot(base::GetDefaultNSSKeySlot()); + if (!slot.get()) { + LOG(ERROR) << "Couldn't get internal key slot!"; + return false; + } + + for (size_t i = 0; i < certificates.size(); ++i) { + const scoped_refptr<net::X509Certificate>& cert = certificates[i]; + + // Mozilla uses CERT_ImportCerts, which doesn't take a slot arg. We use + // PK11_ImportCert instead. + SECStatus srv = PK11_ImportCert(slot.get(), cert->os_cert_handle(), + CK_INVALID_HANDLE, + cert->subject().GetDisplayName().c_str(), + PR_FALSE /* includeTrust (unused) */); + if (srv != SECSuccess) { + LOG(ERROR) << "PK11_ImportCert failed with error " << PORT_GetError(); + not_imported->push_back(net::CertDatabase::ImportCertFailure( + cert, net::ERR_IMPORT_SERVER_CERT_FAILED)); + continue; + } + } + + // Set as valid peer, but without any extra trust. + SetCertTrust(certificates[0].get(), net::SERVER_CERT, + net::CertDatabase::UNTRUSTED); + // TODO(mattm): Report SetCertTrust result? Putting in not_imported + // wouldn't quite match up since it was imported... + + // Any errors importing individual certs will be in listed in |not_imported|. + return true; +} + // Based on nsNSSCertificateDB::SetCertTrust. bool SetCertTrust(const net::X509Certificate* cert, diff --git a/net/third_party/mozilla_security_manager/nsNSSCertificateDB.h b/net/third_party/mozilla_security_manager/nsNSSCertificateDB.h index 58c1a2b..ea02bf8 100644 --- a/net/third_party/mozilla_security_manager/nsNSSCertificateDB.h +++ b/net/third_party/mozilla_security_manager/nsNSSCertificateDB.h @@ -57,6 +57,9 @@ bool ImportCACerts(const net::CertificateList& certificates, unsigned int trustBits, net::CertDatabase::ImportCertFailureList* not_imported); +bool ImportServerCert(const net::CertificateList& certificates, + net::CertDatabase::ImportCertFailureList* not_imported); + bool SetCertTrust(const net::X509Certificate* cert, net::CertType type, unsigned int trusted); |