| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chromeos/network/client_cert_resolver.h" | 5 #include "chromeos/network/client_cert_resolver.h" |
| 6 | 6 |
| 7 #include <cert.h> | 7 #include <cert.h> |
| 8 #include <certt.h> // for (SECCertUsageEnum) certUsageAnyCA | 8 #include <certt.h> // for (SECCertUsageEnum) certUsageAnyCA |
| 9 #include <pk11pub.h> | 9 #include <pk11pub.h> |
| 10 | 10 |
| 11 #include <algorithm> | 11 #include <algorithm> |
| 12 #include <string> | 12 #include <string> |
| 13 | 13 |
| 14 #include "base/bind.h" | 14 #include "base/bind.h" |
| 15 #include "base/location.h" | 15 #include "base/location.h" |
| 16 #include "base/stl_util.h" | 16 #include "base/stl_util.h" |
| 17 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
| 18 #include "base/task_runner.h" | 18 #include "base/task_runner.h" |
| 19 #include "base/threading/worker_pool.h" | 19 #include "base/threading/worker_pool.h" |
| 20 #include "base/time/time.h" | 20 #include "base/time/time.h" |
| 21 #include "chromeos/cert_loader.h" | 21 #include "chromeos/cert_loader.h" |
| 22 #include "chromeos/dbus/dbus_thread_manager.h" | 22 #include "chromeos/dbus/dbus_thread_manager.h" |
| 23 #include "chromeos/dbus/shill_service_client.h" | 23 #include "chromeos/dbus/shill_service_client.h" |
| 24 #include "chromeos/network/certificate_pattern.h" | 24 #include "chromeos/network/certificate_pattern.h" |
| 25 #include "chromeos/network/client_cert_util.h" | 25 #include "chromeos/network/client_cert_util.h" |
| 26 #include "chromeos/network/managed_network_configuration_handler.h" | 26 #include "chromeos/network/managed_network_configuration_handler.h" |
| 27 #include "chromeos/network/network_state.h" | 27 #include "chromeos/network/network_state.h" |
| 28 #include "chromeos/network/network_ui_data.h" | |
| 29 #include "chromeos/tpm_token_loader.h" | 28 #include "chromeos/tpm_token_loader.h" |
| 30 #include "components/onc/onc_constants.h" | 29 #include "components/onc/onc_constants.h" |
| 31 #include "dbus/object_path.h" | 30 #include "dbus/object_path.h" |
| 32 #include "net/cert/scoped_nss_types.h" | 31 #include "net/cert/scoped_nss_types.h" |
| 33 #include "net/cert/x509_certificate.h" | 32 #include "net/cert/x509_certificate.h" |
| 34 | 33 |
| 35 namespace chromeos { | 34 namespace chromeos { |
| 36 | 35 |
| 37 // Describes a network |network_path| for which a matching certificate |cert_id| | 36 // Describes a network |network_path| for which a matching certificate |cert_id| |
| 38 // was found or for which no certificate was found (|cert_id| will be empty). | 37 // was found or for which no certificate was found (|cert_id| will be empty). |
| 39 struct ClientCertResolver::NetworkAndMatchingCert { | 38 struct ClientCertResolver::NetworkAndMatchingCert { |
| 40 NetworkAndMatchingCert(const std::string& network_path, | 39 NetworkAndMatchingCert(const std::string& network_path, |
| 41 client_cert::ConfigType config_type, | 40 client_cert::ConfigType config_type, |
| 42 const std::string& cert_id) | 41 const std::string& cert_id) |
| 43 : service_path(network_path), | 42 : service_path(network_path), |
| 44 cert_config_type(config_type), | 43 cert_config_type(config_type), |
| 45 pkcs11_id(cert_id) {} | 44 pkcs11_id(cert_id) {} |
| 46 | 45 |
| 47 std::string service_path; | 46 std::string service_path; |
| 48 client_cert::ConfigType cert_config_type; | 47 client_cert::ConfigType cert_config_type; |
| 48 |
| 49 // The id of the matching certificate or empty if no certificate was found. | 49 // The id of the matching certificate or empty if no certificate was found. |
| 50 std::string pkcs11_id; | 50 std::string pkcs11_id; |
| 51 }; | 51 }; |
| 52 | 52 |
| 53 typedef std::vector<ClientCertResolver::NetworkAndMatchingCert> | 53 typedef std::vector<ClientCertResolver::NetworkAndMatchingCert> |
| 54 NetworkCertMatches; | 54 NetworkCertMatches; |
| 55 | 55 |
| 56 namespace { | 56 namespace { |
| 57 | 57 |
| 58 // Returns true if |vector| contains |value|. | 58 // Returns true if |vector| contains |value|. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 84 | 84 |
| 85 bool CompareCertExpiration(const CertAndIssuer& a, | 85 bool CompareCertExpiration(const CertAndIssuer& a, |
| 86 const CertAndIssuer& b) { | 86 const CertAndIssuer& b) { |
| 87 return (a.cert->valid_expiry() > b.cert->valid_expiry()); | 87 return (a.cert->valid_expiry() > b.cert->valid_expiry()); |
| 88 } | 88 } |
| 89 | 89 |
| 90 // Describes a network that is configured with the certificate pattern | 90 // Describes a network that is configured with the certificate pattern |
| 91 // |client_cert_pattern|. | 91 // |client_cert_pattern|. |
| 92 struct NetworkAndCertPattern { | 92 struct NetworkAndCertPattern { |
| 93 NetworkAndCertPattern(const std::string& network_path, | 93 NetworkAndCertPattern(const std::string& network_path, |
| 94 client_cert::ConfigType config_type, | 94 const client_cert::ClientCertConfig& client_cert_config) |
| 95 const CertificatePattern& pattern) | |
| 96 : service_path(network_path), | 95 : service_path(network_path), |
| 97 cert_config_type(config_type), | 96 cert_config(client_cert_config) {} |
| 98 client_cert_pattern(pattern) {} | 97 |
| 99 std::string service_path; | 98 std::string service_path; |
| 100 client_cert::ConfigType cert_config_type; | 99 client_cert::ClientCertConfig cert_config; |
| 101 CertificatePattern client_cert_pattern; | |
| 102 }; | 100 }; |
| 103 | 101 |
| 104 // A unary predicate that returns true if the given CertAndIssuer matches the | 102 // A unary predicate that returns true if the given CertAndIssuer matches the |
| 105 // certificate pattern of the NetworkAndCertPattern. | 103 // certificate pattern of the NetworkAndCertPattern. |
| 106 struct MatchCertWithPattern { | 104 struct MatchCertWithPattern { |
| 107 explicit MatchCertWithPattern(const NetworkAndCertPattern& pattern) | 105 explicit MatchCertWithPattern(const NetworkAndCertPattern& pattern) |
| 108 : net_and_pattern(pattern) {} | 106 : net_and_pattern(pattern) {} |
| 109 | 107 |
| 110 bool operator()(const CertAndIssuer& cert_and_issuer) { | 108 bool operator()(const CertAndIssuer& cert_and_issuer) { |
| 111 const CertificatePattern& pattern = net_and_pattern.client_cert_pattern; | 109 const CertificatePattern& pattern = net_and_pattern.cert_config.pattern; |
| 112 if (!pattern.issuer().Empty() && | 110 if (!pattern.issuer().Empty() && |
| 113 !client_cert::CertPrincipalMatches(pattern.issuer(), | 111 !client_cert::CertPrincipalMatches(pattern.issuer(), |
| 114 cert_and_issuer.cert->issuer())) { | 112 cert_and_issuer.cert->issuer())) { |
| 115 return false; | 113 return false; |
| 116 } | 114 } |
| 117 if (!pattern.subject().Empty() && | 115 if (!pattern.subject().Empty() && |
| 118 !client_cert::CertPrincipalMatches(pattern.subject(), | 116 !client_cert::CertPrincipalMatches(pattern.subject(), |
| 119 cert_and_issuer.cert->subject())) { | 117 cert_and_issuer.cert->subject())) { |
| 120 return false; | 118 return false; |
| 121 } | 119 } |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 } else { | 184 } else { |
| 187 pkcs11_id = CertLoader::GetPkcs11IdForCert(*cert_it->cert); | 185 pkcs11_id = CertLoader::GetPkcs11IdForCert(*cert_it->cert); |
| 188 if (pkcs11_id.empty()) { | 186 if (pkcs11_id.empty()) { |
| 189 LOG(ERROR) << "Couldn't determine PKCS#11 ID."; | 187 LOG(ERROR) << "Couldn't determine PKCS#11 ID."; |
| 190 // So far this error is not expected to happen. We can just continue, in | 188 // So far this error is not expected to happen. We can just continue, in |
| 191 // the worst case the user can remove the problematic cert. | 189 // the worst case the user can remove the problematic cert. |
| 192 continue; | 190 continue; |
| 193 } | 191 } |
| 194 } | 192 } |
| 195 matches->push_back(ClientCertResolver::NetworkAndMatchingCert( | 193 matches->push_back(ClientCertResolver::NetworkAndMatchingCert( |
| 196 it->service_path, it->cert_config_type, pkcs11_id)); | 194 it->service_path, it->cert_config.location, pkcs11_id)); |
| 197 } | 195 } |
| 198 } | 196 } |
| 199 | 197 |
| 200 // Determines the type of the CertificatePattern configuration, i.e. is it a | |
| 201 // pattern within an EAP, IPsec or OpenVPN configuration. | |
| 202 client_cert::ConfigType OncToClientCertConfigurationType( | |
| 203 const base::DictionaryValue& network_config) { | |
| 204 using namespace ::onc; | |
| 205 | |
| 206 const base::DictionaryValue* wifi = NULL; | |
| 207 network_config.GetDictionaryWithoutPathExpansion(network_config::kWiFi, | |
| 208 &wifi); | |
| 209 if (wifi) { | |
| 210 const base::DictionaryValue* eap = NULL; | |
| 211 wifi->GetDictionaryWithoutPathExpansion(wifi::kEAP, &eap); | |
| 212 if (!eap) | |
| 213 return client_cert::CONFIG_TYPE_NONE; | |
| 214 return client_cert::CONFIG_TYPE_EAP; | |
| 215 } | |
| 216 | |
| 217 const base::DictionaryValue* vpn = NULL; | |
| 218 network_config.GetDictionaryWithoutPathExpansion(network_config::kVPN, &vpn); | |
| 219 if (vpn) { | |
| 220 const base::DictionaryValue* openvpn = NULL; | |
| 221 vpn->GetDictionaryWithoutPathExpansion(vpn::kOpenVPN, &openvpn); | |
| 222 if (openvpn) | |
| 223 return client_cert::CONFIG_TYPE_OPENVPN; | |
| 224 | |
| 225 const base::DictionaryValue* ipsec = NULL; | |
| 226 vpn->GetDictionaryWithoutPathExpansion(vpn::kIPsec, &ipsec); | |
| 227 if (ipsec) | |
| 228 return client_cert::CONFIG_TYPE_IPSEC; | |
| 229 | |
| 230 return client_cert::CONFIG_TYPE_NONE; | |
| 231 } | |
| 232 | |
| 233 const base::DictionaryValue* ethernet = NULL; | |
| 234 network_config.GetDictionaryWithoutPathExpansion(network_config::kEthernet, | |
| 235 ðernet); | |
| 236 if (ethernet) { | |
| 237 const base::DictionaryValue* eap = NULL; | |
| 238 ethernet->GetDictionaryWithoutPathExpansion(wifi::kEAP, &eap); | |
| 239 if (eap) | |
| 240 return client_cert::CONFIG_TYPE_EAP; | |
| 241 return client_cert::CONFIG_TYPE_NONE; | |
| 242 } | |
| 243 | |
| 244 return client_cert::CONFIG_TYPE_NONE; | |
| 245 } | |
| 246 | |
| 247 void LogError(const std::string& service_path, | 198 void LogError(const std::string& service_path, |
| 248 const std::string& dbus_error_name, | 199 const std::string& dbus_error_name, |
| 249 const std::string& dbus_error_message) { | 200 const std::string& dbus_error_message) { |
| 250 network_handler::ShillErrorCallbackFunction( | 201 network_handler::ShillErrorCallbackFunction( |
| 251 "ClientCertResolver.SetProperties failed", | 202 "ClientCertResolver.SetProperties failed", |
| 252 service_path, | 203 service_path, |
| 253 network_handler::ErrorCallback(), | 204 network_handler::ErrorCallback(), |
| 254 dbus_error_name, | 205 dbus_error_name, |
| 255 dbus_error_message); | 206 dbus_error_message); |
| 256 } | 207 } |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 | 349 |
| 399 if (!policy) { | 350 if (!policy) { |
| 400 VLOG(1) << "The policy for network " << network->path() << " with GUID " | 351 VLOG(1) << "The policy for network " << network->path() << " with GUID " |
| 401 << network->guid() << " is not available yet."; | 352 << network->guid() << " is not available yet."; |
| 402 // Skip this network for now. Once the policy is loaded, PolicyApplied() | 353 // Skip this network for now. Once the policy is loaded, PolicyApplied() |
| 403 // will retry. | 354 // will retry. |
| 404 continue; | 355 continue; |
| 405 } | 356 } |
| 406 | 357 |
| 407 VLOG(2) << "Inspecting network " << network->path(); | 358 VLOG(2) << "Inspecting network " << network->path(); |
| 408 // TODO(pneubeck): Access the ClientCertPattern without relying on | 359 client_cert::ClientCertConfig cert_config; |
| 409 // NetworkUIData, which also parses other things that we don't need here. | 360 OncToClientCertConfig(*policy, &cert_config); |
| 410 // The ONCSource is irrelevant here. | |
| 411 scoped_ptr<NetworkUIData> ui_data( | |
| 412 NetworkUIData::CreateFromONC(onc::ONC_SOURCE_NONE, *policy)); | |
| 413 | 361 |
| 414 // Skip networks that don't have a ClientCertPattern. | 362 // Skip networks that don't have a ClientCertPattern. |
| 415 if (ui_data->certificate_type() != CLIENT_CERT_TYPE_PATTERN) | 363 if (cert_config.client_cert_type != ::onc::client_cert::kPattern) |
| 416 continue; | 364 continue; |
| 417 | 365 |
| 418 client_cert::ConfigType config_type = | 366 networks_with_pattern->push_back( |
| 419 OncToClientCertConfigurationType(*policy); | 367 NetworkAndCertPattern(network->path(), cert_config)); |
| 420 if (config_type == client_cert::CONFIG_TYPE_NONE) { | |
| 421 LOG(ERROR) << "UIData contains a CertificatePattern, but the policy " | |
| 422 << "doesn't. Network: " << network->path(); | |
| 423 continue; | |
| 424 } | |
| 425 | |
| 426 networks_with_pattern->push_back(NetworkAndCertPattern( | |
| 427 network->path(), config_type, ui_data->certificate_pattern())); | |
| 428 } | 368 } |
| 429 if (networks_with_pattern->empty()) | 369 if (networks_with_pattern->empty()) |
| 430 return; | 370 return; |
| 431 | 371 |
| 432 VLOG(2) << "Start task for resolving client cert patterns."; | 372 VLOG(2) << "Start task for resolving client cert patterns."; |
| 433 base::TaskRunner* task_runner = slow_task_runner_for_test_.get(); | 373 base::TaskRunner* task_runner = slow_task_runner_for_test_.get(); |
| 434 if (!task_runner) | 374 if (!task_runner) |
| 435 task_runner = base::WorkerPool::GetTaskRunner(true /* task is slow */); | 375 task_runner = base::WorkerPool::GetTaskRunner(true /* task is slow */); |
| 436 | 376 |
| 437 NetworkCertMatches* matches = new NetworkCertMatches; | 377 NetworkCertMatches* matches = new NetworkCertMatches; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 463 DBusThreadManager::Get()->GetShillServiceClient()-> | 403 DBusThreadManager::Get()->GetShillServiceClient()-> |
| 464 SetProperties(dbus::ObjectPath(it->service_path), | 404 SetProperties(dbus::ObjectPath(it->service_path), |
| 465 shill_properties, | 405 shill_properties, |
| 466 base::Bind(&base::DoNothing), | 406 base::Bind(&base::DoNothing), |
| 467 base::Bind(&LogError, it->service_path)); | 407 base::Bind(&LogError, it->service_path)); |
| 468 network_state_handler_->RequestUpdateForNetwork(it->service_path); | 408 network_state_handler_->RequestUpdateForNetwork(it->service_path); |
| 469 } | 409 } |
| 470 } | 410 } |
| 471 | 411 |
| 472 } // namespace chromeos | 412 } // namespace chromeos |
| OLD | NEW |