Chromium Code Reviews| Index: chromeos/network/client_cert_resolver.cc |
| diff --git a/chromeos/network/client_cert_resolver.cc b/chromeos/network/client_cert_resolver.cc |
| index 3d438d8843c018caac5ec1a9018a0ce0ec639532..66e3dc3e5d8ed55ba8b9f09ed8dcc3bdec66a5b3 100644 |
| --- a/chromeos/network/client_cert_resolver.cc |
| +++ b/chromeos/network/client_cert_resolver.cc |
| @@ -14,6 +14,7 @@ |
| #include "base/location.h" |
| #include "base/logging.h" |
| #include "base/stl_util.h" |
| +#include "base/strings/string_util.h" |
| #include "base/task_runner.h" |
| #include "base/threading/worker_pool.h" |
| #include "base/time/clock.h" |
| @@ -25,6 +26,8 @@ |
| #include "dbus/object_path.h" |
| #include "net/cert/scoped_nss_types.h" |
| #include "net/cert/x509_certificate.h" |
| +#include "net/cert/x509_util_nss.h" |
| +#include "third_party/cros_system_api/dbus/service_constants.h" |
| namespace chromeos { |
| @@ -34,11 +37,13 @@ struct ClientCertResolver::NetworkAndMatchingCert { |
| NetworkAndMatchingCert(const std::string& network_path, |
| client_cert::ConfigType config_type, |
| const std::string& cert_id, |
| - int slot_id) |
| + int slot_id, |
| + const std::string& configured_identity) |
| : service_path(network_path), |
| cert_config_type(config_type), |
| pkcs11_id(cert_id), |
| - key_slot_id(slot_id) {} |
| + key_slot_id(slot_id), |
| + identity(configured_identity) {} |
| std::string service_path; |
| client_cert::ConfigType cert_config_type; |
| @@ -48,6 +53,10 @@ struct ClientCertResolver::NetworkAndMatchingCert { |
| // The id of the slot containing the certificate and the private key. |
| int key_slot_id; |
| + |
| + // The EAP-TLS Identity field, if it is configured through a policy |
| + // substitution. |
| + std::string identity; |
| }; |
| typedef std::vector<ClientCertResolver::NetworkAndMatchingCert> |
| @@ -178,6 +187,21 @@ std::vector<CertAndIssuer> CreateSortedCertAndIssuerList( |
| return client_certs; |
| } |
| +// Looks up subjectAlternativeName fields in |cert| that match |type|, |
| +// then searches for |var_name| in |identity| and replaces any occurrences |
| +// with the SAN. |
| +void ReplaceSAN(std::string* identity, |
|
stevenjb
2016/02/29 19:04:20
Output parameters should be passed in last.
Kevin Cernekee
2016/02/29 21:50:29
Done.
|
| + const std::string& var_name, |
| + const net::X509Certificate& cert, |
| + net::x509_util::SubjectAltNameType type) { |
| + if (identity->find(var_name, 0) != std::string::npos) { |
|
stevenjb
2016/02/29 19:04:20
invert and early exit
Kevin Cernekee
2016/02/29 21:50:29
Done.
|
| + std::vector<std::string> names; |
| + GetSubjectAltName(cert.os_cert_handle(), type, &names); |
|
stevenjb
2016/02/29 19:04:20
Is this intended to be x509_util::GetSubjectAltNam
Kevin Cernekee
2016/02/29 21:50:29
Yes, I added another variant in crrev.com/17206530
stevenjb
2016/02/29 22:06:21
It looks like this should still be in the x509_uti
Kevin Cernekee
2016/02/29 22:53:49
Switched to new name, and added the net::x509_util
|
| + if (!names.empty()) |
| + base::ReplaceSubstringsAfterOffset(identity, 0, var_name, names.at(0)); |
| + } |
| +} |
| + |
| // 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. |
| @@ -197,6 +221,8 @@ void FindCertificateMatches(const net::CertificateList& certs, |
| MatchCertWithPattern(it->cert_config.pattern)); |
| std::string pkcs11_id; |
| int slot_id = -1; |
| + std::string identity; |
| + |
| if (cert_it == client_certs.end()) { |
| VLOG(1) << "Couldn't find a matching client cert for network " |
| << it->service_path; |
| @@ -211,9 +237,20 @@ void FindCertificateMatches(const net::CertificateList& certs, |
| // the worst case the user can remove the problematic cert. |
| continue; |
| } |
| + |
| + // If the policy specifies an identity containing ${CERT_SAN_xxx}, |
| + // see if the cert contains a suitable subjectAltName that we can |
| + // stuff into the shill properties. |
| + identity = it->cert_config.policy_identity; |
| + ReplaceSAN(&identity, ::onc::substitutes::kCertSANEmail, *cert_it->cert, |
| + net::x509_util::SAN_RFC822_NAME); |
| + ReplaceSAN(&identity, ::onc::substitutes::kCertSANUPN, *cert_it->cert, |
| + net::x509_util::SAN_UPN); |
| } |
| + |
| matches->push_back(ClientCertResolver::NetworkAndMatchingCert( |
| - it->service_path, it->cert_config.location, pkcs11_id, slot_id)); |
| + it->service_path, it->cert_config.location, pkcs11_id, slot_id, |
| + identity)); |
| } |
| } |
| @@ -502,6 +539,9 @@ void ClientCertResolver::ConfigureCertificates(NetworkCertMatches* matches) { |
| it->key_slot_id, |
| it->pkcs11_id, |
| &shill_properties); |
| + if (!it->identity.empty()) |
| + shill_properties.SetStringWithoutPathExpansion( |
| + shill::kEapIdentityProperty, it->identity); |
|
stevenjb
2016/02/29 19:04:20
{}
Kevin Cernekee
2016/02/29 21:50:29
Done.
|
| } |
| network_properties_changed_ = true; |
| DBusThreadManager::Get()->GetShillServiceClient()-> |