| Index: chromeos/network/client_cert_resolver.cc
|
| diff --git a/chromeos/network/client_cert_resolver.cc b/chromeos/network/client_cert_resolver.cc
|
| index 20de5f82f020733ac7c3993183b526f875db49d2..d345317176fe45fdb5529cc37899bc32d1511f05 100644
|
| --- a/chromeos/network/client_cert_resolver.cc
|
| +++ b/chromeos/network/client_cert_resolver.cc
|
| @@ -14,18 +14,14 @@
|
| #include "base/bind.h"
|
| #include "base/location.h"
|
| #include "base/stl_util.h"
|
| -#include "base/strings/string_number_conversions.h"
|
| #include "base/task_runner.h"
|
| #include "base/threading/worker_pool.h"
|
| #include "base/time/time.h"
|
| #include "chromeos/cert_loader.h"
|
| #include "chromeos/dbus/dbus_thread_manager.h"
|
| #include "chromeos/dbus/shill_service_client.h"
|
| -#include "chromeos/network/certificate_pattern.h"
|
| -#include "chromeos/network/client_cert_util.h"
|
| #include "chromeos/network/managed_network_configuration_handler.h"
|
| #include "chromeos/network/network_state.h"
|
| -#include "chromeos/tpm_token_loader.h"
|
| #include "components/onc/onc_constants.h"
|
| #include "dbus/object_path.h"
|
| #include "net/cert/scoped_nss_types.h"
|
| @@ -38,16 +34,21 @@ namespace chromeos {
|
| struct ClientCertResolver::NetworkAndMatchingCert {
|
| NetworkAndMatchingCert(const std::string& network_path,
|
| client_cert::ConfigType config_type,
|
| - const std::string& cert_id)
|
| + const std::string& cert_id,
|
| + int slot_id)
|
| : service_path(network_path),
|
| cert_config_type(config_type),
|
| - pkcs11_id(cert_id) {}
|
| + pkcs11_id(cert_id),
|
| + key_slot_id(slot_id) {}
|
|
|
| std::string service_path;
|
| client_cert::ConfigType cert_config_type;
|
|
|
| // The id of the matching certificate or empty if no certificate was found.
|
| std::string pkcs11_id;
|
| +
|
| + // The id of the slot containing the certificate and the private key.
|
| + int key_slot_id;
|
| };
|
|
|
| typedef std::vector<ClientCertResolver::NetworkAndMatchingCert>
|
| @@ -100,13 +101,12 @@ struct NetworkAndCertPattern {
|
| };
|
|
|
| // A unary predicate that returns true if the given CertAndIssuer matches the
|
| -// certificate pattern of the NetworkAndCertPattern.
|
| +// given certificate pattern.
|
| struct MatchCertWithPattern {
|
| - explicit MatchCertWithPattern(const NetworkAndCertPattern& pattern)
|
| - : net_and_pattern(pattern) {}
|
| + explicit MatchCertWithPattern(const CertificatePattern& cert_pattern)
|
| + : pattern(cert_pattern) {}
|
|
|
| bool operator()(const CertAndIssuer& cert_and_issuer) {
|
| - const CertificatePattern& pattern = net_and_pattern.cert_config.pattern;
|
| if (!pattern.issuer().Empty() &&
|
| !client_cert::CertPrincipalMatches(pattern.issuer(),
|
| cert_and_issuer.cert->issuer())) {
|
| @@ -126,15 +126,11 @@ struct MatchCertWithPattern {
|
| return true;
|
| }
|
|
|
| - NetworkAndCertPattern net_and_pattern;
|
| + const CertificatePattern pattern;
|
| };
|
|
|
| -// Searches for matches between |networks| and |certs| and writes matches to
|
| -// |matches|. Because this calls NSS functions and is potentially slow, it must
|
| -// be run on a worker thread.
|
| -void FindCertificateMatches(const net::CertificateList& certs,
|
| - std::vector<NetworkAndCertPattern>* networks,
|
| - NetworkCertMatches* matches) {
|
| +std::vector<CertAndIssuer> CreateSortedCertAndIssuerList(
|
| + const net::CertificateList& certs) {
|
| // Filter all client certs and determines each certificate's issuer, which is
|
| // required for the pattern matching.
|
| std::vector<CertAndIssuer> client_certs;
|
| @@ -169,20 +165,34 @@ void FindCertificateMatches(const net::CertificateList& certs,
|
| }
|
|
|
| std::sort(client_certs.begin(), client_certs.end(), &CompareCertExpiration);
|
| + return client_certs;
|
| +}
|
| +
|
| +// Searches for matches between |networks| and |certs| and writes matches to
|
| +// |matches|. Because this calls NSS functions and is potentially slow, it must
|
| +// be run on a worker thread.
|
| +void FindCertificateMatches(const net::CertificateList& certs,
|
| + std::vector<NetworkAndCertPattern>* networks,
|
| + NetworkCertMatches* matches) {
|
| + std::vector<CertAndIssuer> client_certs(CreateSortedCertAndIssuerList(certs));
|
|
|
| for (std::vector<NetworkAndCertPattern>::const_iterator it =
|
| networks->begin();
|
| it != networks->end(); ++it) {
|
| - std::vector<CertAndIssuer>::iterator cert_it = std::find_if(
|
| - client_certs.begin(), client_certs.end(), MatchCertWithPattern(*it));
|
| + std::vector<CertAndIssuer>::iterator cert_it =
|
| + std::find_if(client_certs.begin(),
|
| + client_certs.end(),
|
| + MatchCertWithPattern(it->cert_config.pattern));
|
| std::string pkcs11_id;
|
| + int slot_id = -1;
|
| if (cert_it == client_certs.end()) {
|
| 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
|
| + // Leave |pkcs11_id| empty to indicate that no cert was found for this
|
| // network.
|
| } else {
|
| - pkcs11_id = CertLoader::GetPkcs11IdForCert(*cert_it->cert);
|
| + pkcs11_id =
|
| + CertLoader::GetPkcs11IdAndSlotForCert(*cert_it->cert, &slot_id);
|
| 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
|
| @@ -191,7 +201,7 @@ void FindCertificateMatches(const net::CertificateList& certs,
|
| }
|
| }
|
| matches->push_back(ClientCertResolver::NetworkAndMatchingCert(
|
| - it->service_path, it->cert_config.location, pkcs11_id));
|
| + it->service_path, it->cert_config.location, pkcs11_id, slot_id));
|
| }
|
| }
|
|
|
| @@ -254,6 +264,39 @@ void ClientCertResolver::SetSlowTaskRunnerForTest(
|
| slow_task_runner_for_test_ = task_runner;
|
| }
|
|
|
| +// static
|
| +bool ClientCertResolver::ResolveCertificatePatternSync(
|
| + const client_cert::ConfigType client_cert_type,
|
| + const CertificatePattern& pattern,
|
| + base::DictionaryValue* shill_properties) {
|
| + // Prepare and sort the list of known client certs.
|
| + std::vector<CertAndIssuer> client_certs(
|
| + CreateSortedCertAndIssuerList(CertLoader::Get()->cert_list()));
|
| +
|
| + // Search for a certificate matching the pattern.
|
| + std::vector<CertAndIssuer>::iterator cert_it = std::find_if(
|
| + client_certs.begin(), client_certs.end(), MatchCertWithPattern(pattern));
|
| +
|
| + if (cert_it == client_certs.end()) {
|
| + VLOG(1) << "Couldn't find a matching client cert";
|
| + client_cert::SetEmptyShillProperties(client_cert_type, shill_properties);
|
| + return false;
|
| + }
|
| +
|
| + int slot_id = -1;
|
| + std::string pkcs11_id =
|
| + CertLoader::GetPkcs11IdAndSlotForCert(*cert_it->cert, &slot_id);
|
| + 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.
|
| + return false;
|
| + }
|
| + client_cert::SetShillProperties(
|
| + client_cert_type, slot_id, pkcs11_id, shill_properties);
|
| + return true;
|
| +}
|
| +
|
| void ClientCertResolver::NetworkListChanged() {
|
| VLOG(2) << "NetworkListChanged.";
|
| if (!ClientCertificatesLoaded())
|
| @@ -385,16 +428,16 @@ void ClientCertResolver::ConfigureCertificates(NetworkCertMatches* matches) {
|
| for (NetworkCertMatches::const_iterator it = matches->begin();
|
| it != matches->end(); ++it) {
|
| 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()),
|
| - TPMTokenLoader::Get()->tpm_user_pin(),
|
| - &it->pkcs11_id,
|
| - &shill_properties);
|
| + if (it->pkcs11_id.empty()) {
|
| + client_cert::SetEmptyShillProperties(it->cert_config_type,
|
| + &shill_properties);
|
| + } else {
|
| + client_cert::SetShillProperties(it->cert_config_type,
|
| + it->key_slot_id,
|
| + it->pkcs11_id,
|
| + &shill_properties);
|
| + }
|
| DBusThreadManager::Get()->GetShillServiceClient()->
|
| SetProperties(dbus::ObjectPath(it->service_path),
|
| shill_properties,
|
|
|