summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/chromeos/cros/network_library.cc8
-rw-r--r--chrome/browser/chromeos/cros/onc_network_parser.cc163
-rw-r--r--chrome/browser/chromeos/cros/onc_network_parser.h12
-rw-r--r--chrome/browser/chromeos/cros/onc_network_parser_unittest.cc198
-rw-r--r--crypto/nss_util.cc2
-rw-r--r--net/base/cert_database.h10
-rw-r--r--net/base/cert_database_nss.cc7
-rw-r--r--net/base/cert_database_nss_unittest.cc2
-rw-r--r--net/base/cert_database_openssl.cc7
9 files changed, 396 insertions, 13 deletions
diff --git a/chrome/browser/chromeos/cros/network_library.cc b/chrome/browser/chromeos/cros/network_library.cc
index 03ddeea..adfa8b9 100644
--- a/chrome/browser/chromeos/cros/network_library.cc
+++ b/chrome/browser/chromeos/cros/network_library.cc
@@ -2782,6 +2782,14 @@ void NetworkLibraryImplBase::SwitchToPreferredNetwork() {
bool NetworkLibraryImplBase::LoadOncNetworks(const std::string& onc_blob) {
OncNetworkParser parser(onc_blob);
+ for (int i = 0; i < parser.GetCertificatesSize(); i++) {
+ // Insert each of the available certs into the certificate DB.
+ if (!parser.ParseCertificate(i)) {
+ DLOG(WARNING) << "Cannot parse certificate in ONC file";
+ return false;
+ }
+ }
+
for (int i = 0; i < parser.GetNetworkConfigsSize(); i++) {
// Parse Open Network Configuration blob into a temporary Network object.
Network* network = parser.ParseNetwork(i);
diff --git a/chrome/browser/chromeos/cros/onc_network_parser.cc b/chrome/browser/chromeos/cros/onc_network_parser.cc
index b1cf7b6..2b0b8d0 100644
--- a/chrome/browser/chromeos/cros/onc_network_parser.cc
+++ b/chrome/browser/chromeos/cros/onc_network_parser.cc
@@ -4,12 +4,16 @@
#include "chrome/browser/chromeos/cros/onc_network_parser.h"
+#include "base/base64.h"
+#include "base/json/json_value_serializer.h"
#include "base/stringprintf.h"
#include "base/values.h"
#include "chrome/browser/chromeos/cros/native_network_constants.h"
#include "chrome/browser/chromeos/cros/network_library.h"
#include "chrome/browser/chromeos/login/user_manager.h"
-#include "base/json/json_value_serializer.h"
+#include "net/base/cert_database.h"
+#include "net/base/net_errors.h"
+#include "net/base/x509_certificate.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace chromeos {
@@ -75,15 +79,18 @@ OncNetworkParser::OncNetworkParser(const std::string& onc_blob)
LOG(WARNING) << "OncNetworkParser received bad ONC file: " << error_msg;
} else {
root_dict_.reset(static_cast<DictionaryValue*>(root.release()));
- if (!root_dict_->GetList("NetworkConfigurations", &network_configs_)) {
- LOG(WARNING) << "ONC file missing NetworkConfigurations";
+ // At least one of NetworkConfigurations or Certificates is required.
+ if (!root_dict_->GetList("NetworkConfigurations", &network_configs_) &&
+ !root_dict_->GetList("Certificates", &certificates_)) {
+ LOG(WARNING) << "ONC file has no NetworkConfigurations or Certificates.";
}
- // Certificates is optional
- root_dict_->GetList("Certificates", &certificates_);
}
}
-OncNetworkParser::OncNetworkParser() : NetworkParser(get_onc_mapper()) {
+OncNetworkParser::OncNetworkParser()
+ : NetworkParser(get_onc_mapper()),
+ network_configs_(NULL),
+ certificates_(NULL) {
}
OncNetworkParser::~OncNetworkParser() {
@@ -102,6 +109,45 @@ int OncNetworkParser::GetCertificatesSize() const {
return certificates_ ? certificates_->GetSize() : 0;
}
+bool OncNetworkParser::ParseCertificate(int cert_index) {
+ CHECK(certificates_);
+ CHECK(static_cast<size_t>(cert_index) < certificates_->GetSize());
+ CHECK(cert_index >= 0);
+ base::DictionaryValue* certificate = NULL;
+ certificates_->GetDictionary(cert_index, &certificate);
+ CHECK(certificate);
+
+ // Get out the attributes of the given cert.
+ std::string guid;
+ bool remove = false;
+ if (!certificate->GetString("GUID", &guid) || guid.empty()) {
+ LOG(WARNING) << "ONC File: certificate missing identifier at index"
+ << cert_index;
+ return false;
+ }
+
+ if (!certificate->GetBoolean("Remove", &remove))
+ remove = false;
+
+ net::CertDatabase cert_database;
+ if (remove)
+ return cert_database.DeleteCertAndKeyByLabel(guid);
+
+ // Not removing, so let's get the data we need to add this cert.
+ std::string cert_type;
+ certificate->GetString("Type", &cert_type);
+ if (cert_type == "Server" || cert_type == "Authority") {
+ return ParseServerOrCaCertificate(cert_index, cert_type, certificate);
+ }
+ if (cert_type == "Client") {
+ return ParseClientCertificate(cert_index, certificate);
+ }
+
+ LOG(WARNING) << "ONC File: certificate of unknown type: " << cert_type
+ << " at index " << cert_index;
+ return false;
+}
+
Network* OncNetworkParser::ParseNetwork(int n) {
// TODO(chocobo): Change this to parse network into a dictionary.
if (!network_configs_)
@@ -162,6 +208,111 @@ std::string OncNetworkParser::GetTypeFromDictionary(
return type_string;
}
+bool OncNetworkParser::ParseServerOrCaCertificate(
+ int cert_index,
+ const std::string& cert_type,
+ base::DictionaryValue* certificate) {
+ net::CertDatabase cert_database;
+ bool web_trust = false;
+ base::ListValue* trust_list = NULL;
+ if (certificate->GetList("Trust", &trust_list)) {
+ for (size_t i = 0; i < trust_list->GetSize(); ++i) {
+ std::string trust_type;
+ if (!trust_list->GetString(i, &trust_type)) {
+ LOG(WARNING) << "ONC File: certificate trust is invalid at index "
+ << cert_index;
+ return false;
+ }
+ if (trust_type == "Web") {
+ web_trust = true;
+ } else {
+ LOG(WARNING) << "ONC File: certificate contains unknown "
+ << "trust type: " << trust_type
+ << " at index " << cert_index;
+ return false;
+ }
+ }
+ }
+
+ std::string x509_data;
+ if (!certificate->GetString("X509", &x509_data) || x509_data.empty()) {
+ LOG(WARNING) << "ONC File: certificate missing appropriate "
+ << "certificate data for type: " << cert_type
+ << " at index " << cert_index;
+ return false;
+ }
+
+ std::string decoded_x509;
+ if (!base::Base64Decode(x509_data, &decoded_x509)) {
+ LOG(WARNING) << "Unable to base64 decode X509 data: \""
+ << x509_data << "\".";
+ return false;
+ }
+
+ scoped_refptr<net::X509Certificate> x509_cert(
+ net::X509Certificate::CreateFromBytes(decoded_x509.c_str(),
+ decoded_x509.size()));
+ if (!x509_cert.get()) {
+ LOG(WARNING) << "Unable to create X509 certificate from bytes.";
+ return false;
+ }
+ net::CertificateList cert_list;
+ cert_list.push_back(x509_cert);
+ net::CertDatabase::ImportCertFailureList failures;
+ bool success = false;
+ if (cert_type == "Server") {
+ success = cert_database.ImportServerCert(cert_list, &failures);
+ } else { // Authority cert
+ net::CertDatabase::TrustBits trust = web_trust ?
+ net::CertDatabase::TRUSTED_SSL :
+ net::CertDatabase::UNTRUSTED;
+ success = cert_database.ImportCACerts(cert_list, trust, &failures);
+ }
+ if (!failures.empty()) {
+ LOG(WARNING) << "ONC File: Error ("
+ << net::ErrorToString(failures[0].net_error)
+ << ") importing " << cert_type << " certificate at index "
+ << cert_index;
+ return false;
+ }
+ if (!success) {
+ LOG(WARNING) << "ONC File: Unknown error importing " << cert_type
+ << " certificate at index " << cert_index;
+ return false;
+ }
+ return true;
+}
+
+bool OncNetworkParser::ParseClientCertificate(
+ int cert_index,
+ base::DictionaryValue* certificate) {
+ net::CertDatabase cert_database;
+ std::string pkcs12_data;
+ if (!certificate->GetString("PKCS12", &pkcs12_data) ||
+ pkcs12_data.empty()) {
+ LOG(WARNING) << "ONC File: PKCS12 data is missing for Client "
+ << "certificate at index " << cert_index;
+ return false;
+ }
+
+ std::string decoded_pkcs12;
+ if (!base::Base64Decode(pkcs12_data, &decoded_pkcs12)) {
+ LOG(WARNING) << "Unable to base64 decode PKCS#12 data: \""
+ << pkcs12_data << "\".";
+ return false;
+ }
+
+ // Since this has a private key, always use the private module.
+ int result = cert_database.ImportFromPKCS12(
+ cert_database.GetPrivateModule(), decoded_pkcs12, string16(), false);
+ if (result != net::OK) {
+ LOG(WARNING) << "ONC File: Unable to import Client certificate at index "
+ << cert_index
+ << " (error " << net::ErrorToString(result) << ").";
+ return false;
+ }
+ return true;
+}
// -------------------- OncWirelessNetworkParser --------------------
diff --git a/chrome/browser/chromeos/cros/onc_network_parser.h b/chrome/browser/chromeos/cros/onc_network_parser.h
index cb624f3..4fd0126 100644
--- a/chrome/browser/chromeos/cros/onc_network_parser.h
+++ b/chrome/browser/chromeos/cros/onc_network_parser.h
@@ -42,6 +42,10 @@ class OncNetworkParser : public NetworkParser {
// (0-based). Returns NULL if there's a parse error or if n is out of range.
Network* ParseNetwork(int n);
+ // Call to parse and import the nth certificate in the certificate
+ // list. Returns false on failure.
+ bool ParseCertificate(int n);
+
virtual Network* CreateNetworkFromInfo(const std::string& service_path,
const base::DictionaryValue& info) OVERRIDE;
@@ -58,6 +62,14 @@ class OncNetworkParser : public NetworkParser {
std::string GetTypeFromDictionary(const base::DictionaryValue& info);
private:
+ bool ParseServerOrCaCertificate(
+ int cert_index,
+ const std::string& cert_type,
+ base::DictionaryValue* certificate);
+ bool ParseClientCertificate(
+ int cert_index,
+ base::DictionaryValue* certificate);
+
scoped_ptr<base::DictionaryValue> root_dict_;
base::ListValue* network_configs_;
base::ListValue* certificates_;
diff --git a/chrome/browser/chromeos/cros/onc_network_parser_unittest.cc b/chrome/browser/chromeos/cros/onc_network_parser_unittest.cc
index 3e2a313..25e9df8 100644
--- a/chrome/browser/chromeos/cros/onc_network_parser_unittest.cc
+++ b/chrome/browser/chromeos/cros/onc_network_parser_unittest.cc
@@ -4,13 +4,93 @@
#include "chrome/browser/chromeos/cros/onc_network_parser.h"
+#include <cert.h>
+#include <pk11pub.h>
+
+#include "base/lazy_instance.h"
+#include "base/scoped_temp_dir.h"
#include "base/values.h"
#include "chrome/browser/chromeos/cros/network_library.h"
+#include "crypto/nss_util.h"
+#include "net/base/cert_database.h"
+#include "net/base/crypto_module.h"
+#include "net/base/x509_certificate.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
-TEST(OncNetworkParserTest, TestCreateNetworkWifi1) {
+class OncNetworkParserTest : public testing::Test {
+ public:
+ static void SetUpTestCase() {
+ ASSERT_TRUE(temp_db_dir_.Get().CreateUniqueTempDir());
+ // Ideally, we'd open a test DB for each test case, and close it
+ // again, removing the temp dir, but unfortunately, there's a
+ // bug in NSS that prevents this from working, so we just open
+ // it once, and empty it for each test case. Here's the bug:
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=588269
+ ASSERT_TRUE(
+ crypto::OpenTestNSSDB(temp_db_dir_.Get().path(),
+ "OncNetworkParserTest db"));
+ }
+
+ static void TearDownTestCase() {
+ ASSERT_TRUE(temp_db_dir_.Get().Delete());
+ }
+
+ virtual void SetUp() {
+ slot_ = cert_db_.GetPublicModule();
+
+ // Don't run the test if the setup failed.
+ ASSERT_TRUE(slot_->os_module_handle());
+
+ // Test db should be empty at start of test.
+ EXPECT_EQ(0U, ListCertsInSlot(slot_->os_module_handle()).size());
+ }
+
+ virtual void TearDown() {
+ EXPECT_TRUE(CleanupSlotContents(slot_->os_module_handle()));
+ EXPECT_EQ(0U, ListCertsInSlot(slot_->os_module_handle()).size());
+ }
+
+ protected:
+ scoped_refptr<net::CryptoModule> slot_;
+ net::CertDatabase cert_db_;
+
+ private:
+ net::CertificateList ListCertsInSlot(PK11SlotInfo* slot) {
+ net::CertificateList result;
+ CERTCertList* cert_list = PK11_ListCertsInSlot(slot);
+ for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
+ !CERT_LIST_END(node, cert_list);
+ node = CERT_LIST_NEXT(node)) {
+ result.push_back(net::X509Certificate::CreateFromHandle(
+ node->cert, net::X509Certificate::OSCertHandles()));
+ }
+ CERT_DestroyCertList(cert_list);
+
+ // Sort the result so that test comparisons can be deterministic.
+ std::sort(result.begin(), result.end(), net::X509Certificate::LessThan());
+ return result;
+ }
+
+ bool CleanupSlotContents(PK11SlotInfo* slot) {
+ bool ok = true;
+ net::CertificateList certs = ListCertsInSlot(slot);
+ for (size_t i = 0; i < certs.size(); ++i) {
+ if (!cert_db_.DeleteCertAndKey(certs[i]))
+ ok = false;
+ }
+ return ok;
+ }
+
+ static base::LazyInstance<ScopedTempDir> temp_db_dir_;
+};
+
+// static
+base::LazyInstance<ScopedTempDir> OncNetworkParserTest::temp_db_dir_(
+ base::LINKER_INITIALIZED);
+
+TEST_F(OncNetworkParserTest, TestCreateNetworkWifi1) {
std::string test_blob(
"{"
" \"NetworkConfigurations\": [{"
@@ -39,7 +119,7 @@ TEST(OncNetworkParserTest, TestCreateNetworkWifi1) {
EXPECT_EQ(wifi->passphrase(), "pass");
}
-TEST(OncNetworkParserTest, TestCreateNetworkWifiEAP1) {
+TEST_F(OncNetworkParserTest, TestCreateNetworkWifiEAP1) {
std::string test_blob(
"{"
" \"NetworkConfigurations\": [{"
@@ -73,7 +153,7 @@ TEST(OncNetworkParserTest, TestCreateNetworkWifiEAP1) {
EXPECT_EQ(wifi->eap_use_system_cas(), false);
}
-TEST(OncNetworkParserTest, TestCreateNetworkWifiEAP2) {
+TEST_F(OncNetworkParserTest, TestCreateNetworkWifiEAP2) {
std::string test_blob(
"{"
" \"NetworkConfigurations\": [{"
@@ -112,4 +192,116 @@ TEST(OncNetworkParserTest, TestCreateNetworkWifiEAP2) {
EXPECT_EQ(wifi->eap_anonymous_identity(), "anon");
}
+TEST_F(OncNetworkParserTest, TestAddServerCertificate) {
+ std::string test_blob(
+ "{"
+ " \"Certificates\": ["
+ " {"
+ " \"GUID\": \"{f998f760-272b-6939-4c2beffe428697aa}\","
+ " \"Type\": \"Server\","
+ " \"X509\": \"MIICWDCCAcECAxAAATANBgkqhkiG9w0BAQQFADCBkzEVM"
+ "BMGA1UEChMMR29vZ2xlLCBJbmMuMREwDwYDVQQLEwhDaHJvbWVPUzEiMCAGCSqGSIb3DQ"
+ "EJARYTZ3NwZW5jZXJAZ29vZ2xlLmNvbTEaMBgGA1UEBxMRTW91bnRhaW4gVmlldywgQ0E"
+ "xCzAJBgNVBAgTAkNBMQswCQYDVQQGEwJVUzENMAsGA1UEAxMEbG1hbzAeFw0xMTAzMTYy"
+ "MzQ5MzhaFw0xMjAzMTUyMzQ5MzhaMFMxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEVM"
+ "BMGA1UEChMMR29vZ2xlLCBJbmMuMREwDwYDVQQLEwhDaHJvbWVPUzENMAsGA1UEAxMEbG"
+ "1hbzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA31WiJ9LvprrhKtDlW0RdLFAO7Qj"
+ "kvs+sG6j2Vp2aBSrlhALG/0BVHUhWi4F/HHJho+ncLHAg5AGO0sdAjYUdQG6tfPqjLsIA"
+ "LtoKEZZdFe/JhmqOEaxWsSdu2S2RdPgCQOsP79EH58gXwu2gejCkJDmU22WL4YLuqOc17"
+ "nxbDC8CAwEAATANBgkqhkiG9w0BAQQFAAOBgQCv4vMD+PMlfnftu4/6Yf/oMLE8yCOqZT"
+ "Q/dWCxB9PiJnOefiBeSzSZE6Uv3G7qnblZPVZaFeJMd+ostt0viCyPucFsFgLMyyoV1dM"
+ "VPVwJT5Iq1AHehWXnTBbxUK9wioA5jOEKdroKjuSSsg/Q8Wx6cpJmttQz5olGPgstmACR"
+ "WA==\""
+ " }"
+ " ],"
+ "}");
+ OncNetworkParser parser(test_blob);
+
+ EXPECT_EQ(1, parser.GetCertificatesSize());
+ EXPECT_TRUE(parser.ParseCertificate(0));
+}
+
+TEST_F(OncNetworkParserTest, TestAddAuthorityCertificate) {
+ const std::string test_blob("{"
+ " \"Certificates\": ["
+ " {"
+ " \"GUID\": \"{f998f760-272b-6939-4c2beffe428697ab}\","
+ " \"Type\": \"Authority\","
+ " \"Trust\": [\"Web\"],"
+ " \"X509\": \"MIIDojCCAwugAwIBAgIJAKGvi5ZgEWDVMA0GCSqGSIb3D"
+ "QEBBAUAMIGTMRUwEwYDVQQKEwxHb29nbGUsIEluYy4xETAPBgNVBAsTCENocm9tZU9TMS"
+ "IwIAYJKoZIhvcNAQkBFhNnc3BlbmNlckBnb29nbGUuY29tMRowGAYDVQQHExFNb3VudGF"
+ "pbiBWaWV3LCBDQTELMAkGA1UECBMCQ0ExCzAJBgNVBAYTAlVTMQ0wCwYDVQQDEwRsbWFv"
+ "MB4XDTExMDMxNjIzNDcxMFoXDTEyMDMxNTIzNDcxMFowgZMxFTATBgNVBAoTDEdvb2dsZ"
+ "SwgSW5jLjERMA8GA1UECxMIQ2hyb21lT1MxIjAgBgkqhkiG9w0BCQEWE2dzcGVuY2VyQG"
+ "dvb2dsZS5jb20xGjAYBgNVBAcTEU1vdW50YWluIFZpZXcsIENBMQswCQYDVQQIEwJDQTE"
+ "LMAkGA1UEBhMCVVMxDTALBgNVBAMTBGxtYW8wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ"
+ "AoGBAMDX6BQz2JUzIAVjetiXxDznd2wdqVqVHfNkbSRW+xBywgqUaIXmFEGUol7VzPfme"
+ "FV8o8ok/eFlQB0h6ycqgwwMd0KjtJs2ys/k0F5GuN0G7fsgr+NRnhVgxj21yF6gYTN/8a"
+ "9kscla/svdmp8ekexbALFnghbLBx3CgcqUxT+tAgMBAAGjgfswgfgwDAYDVR0TBAUwAwE"
+ "B/zAdBgNVHQ4EFgQUbYygbSkl4kpjCNuxoezFGupA97UwgcgGA1UdIwSBwDCBvYAUbYyg"
+ "bSkl4kpjCNuxoezFGupA97WhgZmkgZYwgZMxFTATBgNVBAoTDEdvb2dsZSwgSW5jLjERM"
+ "A8GA1UECxMIQ2hyb21lT1MxIjAgBgkqhkiG9w0BCQEWE2dzcGVuY2VyQGdvb2dsZS5jb2"
+ "0xGjAYBgNVBAcTEU1vdW50YWluIFZpZXcsIENBMQswCQYDVQQIEwJDQTELMAkGA1UEBhM"
+ "CVVMxDTALBgNVBAMTBGxtYW+CCQChr4uWYBFg1TANBgkqhkiG9w0BAQQFAAOBgQCDq9wi"
+ "Q4uVuf1CQU3sXfXCy1yqi5m8AsO9FxHvah5/SVFNwKllqTfedpCaWEswJ55YAojW9e+pY"
+ "2Fh3Fo/Y9YkF88KCtLuBjjqDKCRLxF4LycjHODKyQQ7mN/t5AtP9yKOsNvWF+M4IfReg5"
+ "1kohau6FauQx87by5NIRPdkNPvkQ==\""
+ " }"
+ " ],"
+ "}");
+ OncNetworkParser parser(test_blob);
+
+ EXPECT_EQ(1, parser.GetCertificatesSize());
+ EXPECT_TRUE(parser.ParseCertificate(0));
+}
+
+TEST_F(OncNetworkParserTest, TestAddClientCertificate) {
+ std::string test_blob(
+ "{"
+ " \"Certificates\": ["
+ " {"
+ " \"GUID\": \"{f998f760-272b-6939-4c2beffe428697ac}\","
+ " \"Type\": \"Client\","
+ " \"PKCS12\": \"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\""
+ " }"
+ " ],"
+ "}");
+ OncNetworkParser parser(test_blob);
+
+ EXPECT_EQ(1, parser.GetCertificatesSize());
+ EXPECT_TRUE(parser.ParseCertificate(0));
+}
+
} // namespace chromeos
diff --git a/crypto/nss_util.cc b/crypto/nss_util.cc
index 95afb54..803b01c 100644
--- a/crypto/nss_util.cc
+++ b/crypto/nss_util.cc
@@ -353,7 +353,7 @@ class NSSInitSingleton {
if (test_slot_) {
SECStatus status = SECMOD_CloseUserDB(test_slot_);
if (status != SECSuccess)
- LOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError();
+ PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError();
PK11_FreeSlot(test_slot_);
test_slot_ = NULL;
}
diff --git a/net/base/cert_database.h b/net/base/cert_database.h
index 4851a77..a735e693 100644
--- a/net/base/cert_database.h
+++ b/net/base/cert_database.h
@@ -174,10 +174,16 @@ class NET_EXPORT CertDatabase {
TrustBits trust_bits);
// Delete certificate and associated private key (if one exists).
- // Returns true on success or false on failure.
- // |cert| is still valid when this function returns.
+ // |cert| is still valid when this function returns. Returns true on
+ // success.
bool DeleteCertAndKey(const X509Certificate* cert);
+ // Delete the certificate and associated public and private key (if
+ // one exists) with the given label from the database. Returns true
+ // on success. ("label" here refers to the NSS Attribute CKA_LABEL,
+ // also referred to as a nickname or friendly name).
+ bool DeleteCertAndKeyByLabel(const std::string& label);
+
// Check whether cert is stored in a readonly slot.
bool IsReadOnly(const X509Certificate* cert) const;
#endif
diff --git a/net/base/cert_database_nss.cc b/net/base/cert_database_nss.cc
index 4fa877d..817372d 100644
--- a/net/base/cert_database_nss.cc
+++ b/net/base/cert_database_nss.cc
@@ -328,6 +328,13 @@ bool CertDatabase::DeleteCertAndKey(const X509Certificate* cert) {
return true;
}
+bool CertDatabase::DeleteCertAndKeyByLabel(const std::string& label) {
+ // TODO(gspencer):Find the certificate with the given CKA_LABEL
+ // (nickname), and delete it.
+ NOTIMPLEMENTED();
+ return false;
+}
+
bool CertDatabase::IsReadOnly(const X509Certificate* cert) const {
PK11SlotInfo* slot = cert->os_cert_handle()->slot;
return slot && PK11_IsReadOnly(slot);
diff --git a/net/base/cert_database_nss_unittest.cc b/net/base/cert_database_nss_unittest.cc
index a7301b8..7b1c3e2 100644
--- a/net/base/cert_database_nss_unittest.cc
+++ b/net/base/cert_database_nss_unittest.cc
@@ -174,7 +174,7 @@ TEST_F(CertDatabaseNSSTest, ImportFromPKCS12AsExtractableAndExportAgain) {
EXPECT_EQ("testusercert",
cert->subject().common_name);
- // TODO(mattm): move export test to seperate test case?
+ // TODO(mattm): move export test to separate test case?
std::string exported_data;
EXPECT_EQ(1, cert_db_.ExportToPKCS12(cert_list, ASCIIToUTF16("exportpw"),
&exported_data));
diff --git a/net/base/cert_database_openssl.cc b/net/base/cert_database_openssl.cc
index ca429c08..76bd3f8 100644
--- a/net/base/cert_database_openssl.cc
+++ b/net/base/cert_database_openssl.cc
@@ -82,6 +82,13 @@ bool CertDatabase::DeleteCertAndKey(const X509Certificate* cert) {
return false;
}
+bool CertDatabase::DeleteCertAndKeyByLabel(const std::string& label) {
+ // TODO(gspencer):Find the certificate with the given label
+ // (nickname), and delete it.
+ NOTIMPLEMENTED();
+ return false;
+}
+
CertDatabase::TrustBits CertDatabase::GetCertTrust(const X509Certificate* cert,
CertType type) const {
// TODO(bulach): implement me.