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 |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
184 client_certs.push_back(CertAndIssuer(*it, GetPEMEncodedIssuer(cert))); | 184 client_certs.push_back(CertAndIssuer(*it, GetPEMEncodedIssuer(cert))); |
185 } | 185 } |
186 | 186 |
187 std::sort(client_certs.begin(), client_certs.end(), &CompareCertExpiration); | 187 std::sort(client_certs.begin(), client_certs.end(), &CompareCertExpiration); |
188 return client_certs; | 188 return client_certs; |
189 } | 189 } |
190 | 190 |
191 // Searches for matches between |networks| and |certs| and writes matches to | 191 // Searches for matches between |networks| and |certs| and writes matches to |
192 // |matches|. Because this calls NSS functions and is potentially slow, it must | 192 // |matches|. Because this calls NSS functions and is potentially slow, it must |
193 // be run on a worker thread. | 193 // be run on a worker thread. |
194 void FindCertificateMatches(const net::CertificateList& certs, | 194 void FindCertificateMatches(const net::CertificateList& all_certs, |
195 const net::CertificateList& system_certs, | |
195 std::vector<NetworkAndCertPattern>* networks, | 196 std::vector<NetworkAndCertPattern>* networks, |
196 base::Time now, | 197 base::Time now, |
197 NetworkCertMatches* matches) { | 198 NetworkCertMatches* matches) { |
198 std::vector<CertAndIssuer> client_certs( | 199 std::vector<CertAndIssuer> all_client_certs( |
199 CreateSortedCertAndIssuerList(certs, now)); | 200 CreateSortedCertAndIssuerList(all_certs, now)); |
201 std::vector<CertAndIssuer> system_client_certs( | |
202 CreateSortedCertAndIssuerList(system_certs, now)); | |
200 | 203 |
201 for (std::vector<NetworkAndCertPattern>::const_iterator it = | 204 for (std::vector<NetworkAndCertPattern>::const_iterator it = |
202 networks->begin(); | 205 networks->begin(); |
203 it != networks->end(); ++it) { | 206 it != networks->end(); ++it) { |
204 std::vector<CertAndIssuer>::iterator cert_it = | 207 // Use only certs from the system token if the source of the client cert |
205 std::find_if(client_certs.begin(), | 208 // pattern is device policy. |
206 client_certs.end(), | 209 std::vector<CertAndIssuer>* client_certs = |
207 MatchCertWithPattern(it->cert_config.pattern)); | 210 it->cert_config.onc_source == ::onc::ONC_SOURCE_DEVICE_POLICY |
211 ? &system_client_certs | |
212 : &all_client_certs; | |
213 auto cert_it = std::find_if(client_certs->begin(), client_certs->end(), | |
214 MatchCertWithPattern(it->cert_config.pattern)); | |
208 std::string pkcs11_id; | 215 std::string pkcs11_id; |
209 int slot_id = -1; | 216 int slot_id = -1; |
210 std::string identity; | 217 std::string identity; |
211 | 218 |
212 if (cert_it == client_certs.end()) { | 219 if (cert_it == client_certs->end()) { |
213 VLOG(1) << "Couldn't find a matching client cert for network " | 220 VLOG(1) << "Couldn't find a matching client cert for network " |
214 << it->service_path; | 221 << it->service_path; |
215 // Leave |pkcs11_id| empty to indicate that no cert was found for this | 222 // Leave |pkcs11_id| empty to indicate that no cert was found for this |
216 // network. | 223 // network. |
217 } else { | 224 } else { |
218 pkcs11_id = | 225 pkcs11_id = |
219 CertLoader::GetPkcs11IdAndSlotForCert(*cert_it->cert, &slot_id); | 226 CertLoader::GetPkcs11IdAndSlotForCert(*cert_it->cert, &slot_id); |
220 if (pkcs11_id.empty()) { | 227 if (pkcs11_id.empty()) { |
221 LOG(ERROR) << "Couldn't determine PKCS#11 ID."; | 228 LOG(ERROR) << "Couldn't determine PKCS#11 ID."; |
222 // So far this error is not expected to happen. We can just continue, in | 229 // So far this error is not expected to happen. We can just continue, in |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
318 observers_.RemoveObserver(observer); | 325 observers_.RemoveObserver(observer); |
319 } | 326 } |
320 | 327 |
321 bool ClientCertResolver::IsAnyResolveTaskRunning() const { | 328 bool ClientCertResolver::IsAnyResolveTaskRunning() const { |
322 return resolve_task_running_; | 329 return resolve_task_running_; |
323 } | 330 } |
324 | 331 |
325 // static | 332 // static |
326 bool ClientCertResolver::ResolveCertificatePatternSync( | 333 bool ClientCertResolver::ResolveCertificatePatternSync( |
327 const client_cert::ConfigType client_cert_type, | 334 const client_cert::ConfigType client_cert_type, |
328 const CertificatePattern& pattern, | 335 const client_cert::ClientCertConfig& client_cert_config, |
329 base::DictionaryValue* shill_properties) { | 336 base::DictionaryValue* shill_properties) { |
330 // Prepare and sort the list of known client certs. | 337 // Prepare and sort the list of known client certs. Use only certs from the |
331 std::vector<CertAndIssuer> client_certs(CreateSortedCertAndIssuerList( | 338 // system token if the source of the client cert pattern is device policy. |
332 CertLoader::Get()->cert_list(), base::Time::Now())); | 339 std::vector<CertAndIssuer> client_certs; |
340 if (client_cert_config.onc_source == ::onc::ONC_SOURCE_DEVICE_POLICY) { | |
341 client_certs = CreateSortedCertAndIssuerList( | |
342 CertLoader::Get()->system_certs(), base::Time::Now()); | |
343 } else { | |
344 client_certs = CreateSortedCertAndIssuerList(CertLoader::Get()->all_certs(), | |
345 base::Time::Now()); | |
346 } | |
333 | 347 |
334 // Search for a certificate matching the pattern. | 348 // Search for a certificate matching the pattern. |
335 std::vector<CertAndIssuer>::iterator cert_it = std::find_if( | 349 std::vector<CertAndIssuer>::iterator cert_it = |
336 client_certs.begin(), client_certs.end(), MatchCertWithPattern(pattern)); | 350 std::find_if(client_certs.begin(), client_certs.end(), |
351 MatchCertWithPattern(client_cert_config.pattern)); | |
337 | 352 |
338 if (cert_it == client_certs.end()) { | 353 if (cert_it == client_certs.end()) { |
339 VLOG(1) << "Couldn't find a matching client cert"; | 354 VLOG(1) << "Couldn't find a matching client cert"; |
340 client_cert::SetEmptyShillProperties(client_cert_type, shill_properties); | 355 client_cert::SetEmptyShillProperties(client_cert_type, shill_properties); |
341 return false; | 356 return false; |
342 } | 357 } |
343 | 358 |
344 int slot_id = -1; | 359 int slot_id = -1; |
345 std::string pkcs11_id = | 360 std::string pkcs11_id = |
346 CertLoader::GetPkcs11IdAndSlotForCert(*cert_it->cert, &slot_id); | 361 CertLoader::GetPkcs11IdAndSlotForCert(*cert_it->cert, &slot_id); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
445 networks.begin(); it != networks.end(); ++it) { | 460 networks.begin(); it != networks.end(); ++it) { |
446 const NetworkState* network = *it; | 461 const NetworkState* network = *it; |
447 | 462 |
448 // In any case, don't check this network again in NetworkListChanged. | 463 // In any case, don't check this network again in NetworkListChanged. |
449 resolved_networks_.insert(network->path()); | 464 resolved_networks_.insert(network->path()); |
450 | 465 |
451 // If this network is not configured, it cannot have a ClientCertPattern. | 466 // If this network is not configured, it cannot have a ClientCertPattern. |
452 if (network->profile_path().empty()) | 467 if (network->profile_path().empty()) |
453 continue; | 468 continue; |
454 | 469 |
470 onc::ONCSource onc_source = onc::ONC_SOURCE_NONE; | |
455 const base::DictionaryValue* policy = | 471 const base::DictionaryValue* policy = |
456 managed_network_config_handler_->FindPolicyByGuidAndProfile( | 472 managed_network_config_handler_->FindPolicyByGuidAndProfile( |
457 network->guid(), network->profile_path()); | 473 network->guid(), network->profile_path(), &onc_source); |
458 | 474 |
459 if (!policy) { | 475 if (!policy) { |
460 VLOG(1) << "The policy for network " << network->path() << " with GUID " | 476 VLOG(1) << "The policy for network " << network->path() << " with GUID " |
461 << network->guid() << " is not available yet."; | 477 << network->guid() << " is not available yet."; |
462 // Skip this network for now. Once the policy is loaded, PolicyApplied() | 478 // Skip this network for now. Once the policy is loaded, PolicyApplied() |
463 // will retry. | 479 // will retry. |
464 continue; | 480 continue; |
465 } | 481 } |
466 | 482 |
467 VLOG(2) << "Inspecting network " << network->path(); | 483 VLOG(2) << "Inspecting network " << network->path(); |
468 client_cert::ClientCertConfig cert_config; | 484 client_cert::ClientCertConfig cert_config; |
469 OncToClientCertConfig(*policy, &cert_config); | 485 OncToClientCertConfig(onc_source, *policy, &cert_config); |
470 | 486 |
471 // Skip networks that don't have a ClientCertPattern. | 487 // Skip networks that don't have a ClientCertPattern. |
472 if (cert_config.client_cert_type != ::onc::client_cert::kPattern) | 488 if (cert_config.client_cert_type != ::onc::client_cert::kPattern) |
473 continue; | 489 continue; |
474 | 490 |
475 networks_to_resolve->push_back( | 491 networks_to_resolve->push_back( |
476 NetworkAndCertPattern(network->path(), cert_config)); | 492 NetworkAndCertPattern(network->path(), cert_config)); |
477 } | 493 } |
478 | 494 |
479 if (networks_to_resolve->empty()) { | 495 if (networks_to_resolve->empty()) { |
480 VLOG(1) << "No networks to resolve."; | 496 VLOG(1) << "No networks to resolve."; |
481 NotifyResolveRequestCompleted(); | 497 NotifyResolveRequestCompleted(); |
482 return; | 498 return; |
483 } | 499 } |
484 | 500 |
485 if (resolve_task_running_) { | 501 if (resolve_task_running_) { |
486 VLOG(1) << "A resolve task is already running. Queue this request."; | 502 VLOG(1) << "A resolve task is already running. Queue this request."; |
487 for (const NetworkAndCertPattern& network_and_pattern : | 503 for (const NetworkAndCertPattern& network_and_pattern : |
488 *networks_to_resolve) { | 504 *networks_to_resolve) { |
489 queued_networks_to_resolve_.insert(network_and_pattern.service_path); | 505 queued_networks_to_resolve_.insert(network_and_pattern.service_path); |
490 } | 506 } |
491 return; | 507 return; |
492 } | 508 } |
493 | 509 |
494 VLOG(2) << "Start task for resolving client cert patterns."; | 510 VLOG(2) << "Start task for resolving client cert patterns."; |
495 resolve_task_running_ = true; | 511 resolve_task_running_ = true; |
496 NetworkCertMatches* matches = new NetworkCertMatches; | 512 NetworkCertMatches* matches = new NetworkCertMatches; |
497 base::PostTaskWithTraitsAndReply( | 513 base::PostTaskWithTraitsAndReply( |
fdoray
2017/04/26 13:11:36
PostTaskWithTraitsAndReplyWithResult() could be us
pmarko
2017/04/27 08:51:56
Done.
| |
498 FROM_HERE, base::TaskTraits() | 514 FROM_HERE, |
499 .WithShutdownBehavior( | 515 base::TaskTraits() |
500 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) | 516 .WithShutdownBehavior( |
501 .MayBlock(), | 517 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) |
502 base::Bind(&FindCertificateMatches, CertLoader::Get()->cert_list(), | 518 .MayBlock(), |
519 base::Bind(&FindCertificateMatches, CertLoader::Get()->all_certs(), | |
520 CertLoader::Get()->system_certs(), | |
503 base::Owned(networks_to_resolve.release()), Now(), matches), | 521 base::Owned(networks_to_resolve.release()), Now(), matches), |
504 base::Bind(&ClientCertResolver::ConfigureCertificates, | 522 base::Bind(&ClientCertResolver::ConfigureCertificates, |
505 weak_ptr_factory_.GetWeakPtr(), base::Owned(matches))); | 523 weak_ptr_factory_.GetWeakPtr(), base::Owned(matches))); |
506 } | 524 } |
507 | 525 |
508 void ClientCertResolver::ResolvePendingNetworks() { | 526 void ClientCertResolver::ResolvePendingNetworks() { |
509 NetworkStateHandler::NetworkStateList networks; | 527 NetworkStateHandler::NetworkStateList networks; |
510 network_state_handler_->GetNetworkListByType(NetworkTypePattern::Default(), | 528 network_state_handler_->GetNetworkListByType(NetworkTypePattern::Default(), |
511 true /* configured_only */, | 529 true /* configured_only */, |
512 false /* visible_only */, | 530 false /* visible_only */, |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
565 observer.ResolveRequestCompleted(changed); | 583 observer.ResolveRequestCompleted(changed); |
566 } | 584 } |
567 | 585 |
568 base::Time ClientCertResolver::Now() const { | 586 base::Time ClientCertResolver::Now() const { |
569 if (testing_clock_) | 587 if (testing_clock_) |
570 return testing_clock_->Now(); | 588 return testing_clock_->Now(); |
571 return base::Time::Now(); | 589 return base::Time::Now(); |
572 } | 590 } |
573 | 591 |
574 } // namespace chromeos | 592 } // namespace chromeos |
OLD | NEW |