summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-12 02:17:08 +0000
committermattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-12 02:17:08 +0000
commit8405da12256819349baf47280fcd495bb796a723 (patch)
tree83f1b318ee853e10985a47a70dcd00d8049b2803
parente1751fb1116682ffba80cbc127b9da66c6d72a3c (diff)
downloadchromium_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.h11
-rw-r--r--net/base/cert_database_nss.cc5
-rw-r--r--net/base/cert_database_nss_unittest.cc71
-rw-r--r--net/base/net_error_list.h3
-rw-r--r--net/third_party/mozilla_security_manager/nsNSSCertificateDB.cpp36
-rw-r--r--net/third_party/mozilla_security_manager/nsNSSCertificateDB.h3
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);