diff options
author | pneubeck@chromium.org <pneubeck@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-03 12:09:17 +0000 |
---|---|---|
committer | pneubeck@chromium.org <pneubeck@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-03 12:09:17 +0000 |
commit | 1e042d7f323cdae296abc8f541470554ea22270b (patch) | |
tree | 06f91a0e872fd97863b287d3164a05638c44bf88 /chromeos | |
parent | 54495f445387215519ea54816d27693e303a9c30 (diff) | |
download | chromium_src-1e042d7f323cdae296abc8f541470554ea22270b.zip chromium_src-1e042d7f323cdae296abc8f541470554ea22270b.tar.gz chromium_src-1e042d7f323cdae296abc8f541470554ea22270b.tar.bz2 |
Clear the CertID of a network if no valid cert exists.
The old behavior of the ClientCertResolver was that a non-empty Cert/KeyID is never cleared. However, this lead to other code handling as if the network was correctly configured even if that Cert/KeyID didn't point to a valid cert anymore.
If a cert is available, the behavior will not change: the resolver always writes the id of the best fitting certificate.
The new behavior is, that if no certificate matching the network's cert pattern is found, then the Cert/KeyID is cleared.
Accordingly, this leads to the Enrollment Dialog correctly popping up.
BUG=390914
Review URL: https://codereview.chromium.org/362323004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@281238 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chromeos')
-rw-r--r-- | chromeos/network/client_cert_resolver.cc | 27 | ||||
-rw-r--r-- | chromeos/network/client_cert_resolver_unittest.cc | 60 | ||||
-rw-r--r-- | chromeos/network/client_cert_util.cc | 14 |
3 files changed, 64 insertions, 37 deletions
diff --git a/chromeos/network/client_cert_resolver.cc b/chromeos/network/client_cert_resolver.cc index 96261dd..c4a03fa9 100644 --- a/chromeos/network/client_cert_resolver.cc +++ b/chromeos/network/client_cert_resolver.cc @@ -35,7 +35,7 @@ namespace chromeos { // Describes a network |network_path| for which a matching certificate |cert_id| -// was found. +// was found or for which no certificate was found (|cert_id| will be empty). struct ClientCertResolver::NetworkAndMatchingCert { NetworkAndMatchingCert(const std::string& network_path, client_cert::ConfigType config_type, @@ -46,7 +46,7 @@ struct ClientCertResolver::NetworkAndMatchingCert { std::string service_path; client_cert::ConfigType cert_config_type; - // The id of the matching certificate. + // The id of the matching certificate or empty if no certificate was found. std::string pkcs11_id; }; @@ -177,15 +177,20 @@ void FindCertificateMatches(const net::CertificateList& certs, it != networks->end(); ++it) { std::vector<CertAndIssuer>::iterator cert_it = std::find_if( client_certs.begin(), client_certs.end(), MatchCertWithPattern(*it)); + std::string pkcs11_id; if (cert_it == client_certs.end()) { - LOG(WARNING) << "Couldn't find a matching client cert for network " - << it->service_path; - continue; - } - std::string pkcs11_id = CertLoader::GetPkcs11IdForCert(*cert_it->cert); - if (pkcs11_id.empty()) { - LOG(ERROR) << "Couldn't determine PKCS#11 ID."; - continue; + VLOG(1) << "Couldn't find a matching client cert for network " + << it->service_path; + // Leave |pkcs11_id empty| to indicate that no cert was found for this + // network. + } else { + pkcs11_id = CertLoader::GetPkcs11IdForCert(*cert_it->cert); + if (pkcs11_id.empty()) { + LOG(ERROR) << "Couldn't determine PKCS#11 ID."; + // So far this error is not expected to happen. We can just continue, in + // the worst case the user can remove the problematic cert. + continue; + } } matches->push_back(ClientCertResolver::NetworkAndMatchingCert( it->service_path, it->cert_config_type, pkcs11_id)); @@ -447,6 +452,8 @@ void ClientCertResolver::ConfigureCertificates(NetworkCertMatches* matches) { VLOG(1) << "Configuring certificate of network " << it->service_path; CertLoader* cert_loader = CertLoader::Get(); base::DictionaryValue shill_properties; + // If pkcs11_id is empty, this will clear the key/cert properties of this + // network. client_cert::SetShillProperties( it->cert_config_type, base::IntToString(cert_loader->TPMTokenSlotID()), diff --git a/chromeos/network/client_cert_resolver_unittest.cc b/chromeos/network/client_cert_resolver_unittest.cc index 07bb43d..4ca251e 100644 --- a/chromeos/network/client_cert_resolver_unittest.cc +++ b/chromeos/network/client_cert_resolver_unittest.cc @@ -14,6 +14,7 @@ #include "base/values.h" #include "chromeos/cert_loader.h" #include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/shill_manager_client.h" #include "chromeos/dbus/shill_profile_client.h" #include "chromeos/dbus/shill_service_client.h" #include "chromeos/network/managed_network_configuration_handler_impl.h" @@ -82,7 +83,6 @@ class ClientCertResolverTest : public testing::Test { CertLoader::Initialize(); cert_loader_ = CertLoader::Get(); cert_loader_->force_hardware_backed_for_test(); - cert_loader_->StartWithNSSDB(test_nssdb_.get()); } virtual void TearDown() OVERRIDE { @@ -98,6 +98,17 @@ class ClientCertResolverTest : public testing::Test { } protected: + void StartCertLoader() { + cert_loader_->StartWithNSSDB(test_nssdb_.get()); + if (test_client_cert_) { + test_pkcs11_id_ = base::StringPrintf( + "%i:%s", + cert_loader_->TPMTokenSlotID(), + CertLoader::GetPkcs11IdForCert(*test_client_cert_).c_str()); + ASSERT_TRUE(!test_pkcs11_id_.empty()); + } + } + // Imports a CA cert (stored as PEM in test_ca_cert_pem_) and a client // certificate signed by that CA. Its PKCS#11 ID is stored in // |test_pkcs11_id_|. @@ -131,11 +142,7 @@ class ClientCertResolverTest : public testing::Test { test_nssdb_->ImportFromPKCS12( module, pkcs12_data, base::string16(), false, &client_cert_list)); ASSERT_TRUE(!client_cert_list.empty()); - test_pkcs11_id_ = base::StringPrintf( - "%i:%s", - cert_loader_->TPMTokenSlotID(), - CertLoader::GetPkcs11IdForCert(*client_cert_list[0]).c_str()); - ASSERT_TRUE(!test_pkcs11_id_.empty()); + test_client_cert_ = client_cert_list[0]; } void SetupNetworkHandlers() { @@ -160,16 +167,22 @@ class ClientCertResolverTest : public testing::Test { } void SetupWifi() { - const bool add_to_visible = true; - service_test_->AddService(kWifiStub, - kWifiSSID, - shill::kTypeWifi, - shill::kStateOnline, - add_to_visible); + service_test_->SetServiceProperties(kWifiStub, + kWifiStub, + kWifiSSID, + shill::kTypeWifi, + shill::kStateOnline, + true /* visible */); + // Set an arbitrary cert id, so that we can check afterwards whether we + // cleared the property or not. service_test_->SetServiceProperty( - kWifiStub, shill::kGuidProperty, base::StringValue(kWifiStub)); - + kWifiStub, shill::kEapCertIdProperty, base::StringValue("invalid id")); profile_test_->AddService(kUserProfilePath, kWifiStub); + + DBusThreadManager::Get() + ->GetShillManagerClient() + ->GetTestInterface() + ->AddManagerService(kWifiStub, true); } // Setup a policy with a certificate pattern that matches any client cert that @@ -242,6 +255,7 @@ class ClientCertResolverTest : public testing::Test { } CertLoader* cert_loader_; + scoped_refptr<net::X509Certificate> test_client_cert_; scoped_ptr<NetworkStateHandler> network_state_handler_; scoped_ptr<NetworkProfileHandler> network_profile_handler_; scoped_ptr<NetworkConfigurationHandler> network_config_handler_; @@ -256,25 +270,25 @@ class ClientCertResolverTest : public testing::Test { TEST_F(ClientCertResolverTest, NoMatchingCertificates) { SetupNetworkHandlers(); - SetupPolicy(); - base::RunLoop().RunUntilIdle(); - SetupWifi(); + StartCertLoader(); + SetupPolicy(); base::RunLoop().RunUntilIdle(); // Verify that no client certificate was configured. std::string pkcs11_id; GetClientCertProperties(&pkcs11_id); - EXPECT_TRUE(pkcs11_id.empty()); + EXPECT_EQ(std::string(), pkcs11_id); } -TEST_F(ClientCertResolverTest, ResolveOnInitialization) { - SetupTestCerts(); +TEST_F(ClientCertResolverTest, ResolveOnCertificatesLoaded) { SetupNetworkHandlers(); + SetupWifi(); + SetupTestCerts(); SetupPolicy(); base::RunLoop().RunUntilIdle(); - SetupWifi(); + StartCertLoader(); base::RunLoop().RunUntilIdle(); // Verify that the resolver positively matched the pattern in the policy with @@ -286,10 +300,12 @@ TEST_F(ClientCertResolverTest, ResolveOnInitialization) { TEST_F(ClientCertResolverTest, ResolveAfterPolicyApplication) { SetupTestCerts(); + StartCertLoader(); SetupNetworkHandlers(); + SetupWifi(); base::RunLoop().RunUntilIdle(); - // The policy will trigger the creation of a new wifi service. + // Policy application will trigger the ClientCertResolver. SetupPolicy(); base::RunLoop().RunUntilIdle(); diff --git a/chromeos/network/client_cert_util.cc b/chromeos/network/client_cert_util.cc index c77e286..536d578 100644 --- a/chromeos/network/client_cert_util.cc +++ b/chromeos/network/client_cert_util.cc @@ -233,11 +233,15 @@ void SetShillProperties(const client_cert::ConfigType cert_config_type, tpm_pin_property = shill::kEapPinProperty; if (pkcs11_id) { std::string key_id; - if (tpm_slot.empty()) - NET_LOG_ERROR("Missing TPM slot id", ""); - else - key_id = tpm_slot + ":"; - key_id.append(*pkcs11_id); + if (pkcs11_id->empty()) { + // An empty pkcs11_id means that we should clear the properties. + } else { + if (tpm_slot.empty()) + NET_LOG_ERROR("Missing TPM slot id", ""); + else + key_id = tpm_slot + ":"; + key_id.append(*pkcs11_id); + } // Shill requires both CertID and KeyID for TLS connections, despite the // fact that by convention they are the same ID, because one identifies // the certificate and the other the private key. |