Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Side by Side Diff: chromeos/network/client_cert_resolver.cc

Issue 2828713002: Enable client certificate patterns in device ONC policy (Closed)
Patch Set: Addressed comments - more DCHECKs, use PostTask..WithReply in client_cert_resolver.cc. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 12
13 #include "base/bind.h" 13 #include "base/bind.h"
14 #include "base/location.h" 14 #include "base/location.h"
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "base/memory/ptr_util.h"
16 #include "base/stl_util.h" 17 #include "base/stl_util.h"
17 #include "base/strings/string_util.h" 18 #include "base/strings/string_util.h"
18 #include "base/task_scheduler/post_task.h" 19 #include "base/task_scheduler/post_task.h"
19 #include "base/time/clock.h" 20 #include "base/time/clock.h"
20 #include "chromeos/dbus/dbus_thread_manager.h" 21 #include "chromeos/dbus/dbus_thread_manager.h"
21 #include "chromeos/dbus/shill_service_client.h" 22 #include "chromeos/dbus/shill_service_client.h"
22 #include "chromeos/network/managed_network_configuration_handler.h" 23 #include "chromeos/network/managed_network_configuration_handler.h"
23 #include "chromeos/network/network_state.h" 24 #include "chromeos/network/network_state.h"
24 #include "components/onc/onc_constants.h" 25 #include "components/onc/onc_constants.h"
25 #include "dbus/object_path.h" 26 #include "dbus/object_path.h"
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 client_certs.push_back(CertAndIssuer(*it, GetPEMEncodedIssuer(cert))); 185 client_certs.push_back(CertAndIssuer(*it, GetPEMEncodedIssuer(cert)));
185 } 186 }
186 187
187 std::sort(client_certs.begin(), client_certs.end(), &CompareCertExpiration); 188 std::sort(client_certs.begin(), client_certs.end(), &CompareCertExpiration);
188 return client_certs; 189 return client_certs;
189 } 190 }
190 191
191 // Searches for matches between |networks| and |certs| and writes matches to 192 // Searches for matches between |networks| and |certs| and writes matches to
192 // |matches|. Because this calls NSS functions and is potentially slow, it must 193 // |matches|. Because this calls NSS functions and is potentially slow, it must
193 // be run on a worker thread. 194 // be run on a worker thread.
194 void FindCertificateMatches(const net::CertificateList& certs, 195 std::unique_ptr<NetworkCertMatches> FindCertificateMatches(
195 std::vector<NetworkAndCertPattern>* networks, 196 const net::CertificateList& all_certs,
196 base::Time now, 197 const net::CertificateList& system_certs,
197 NetworkCertMatches* matches) { 198 std::vector<NetworkAndCertPattern>* networks,
198 std::vector<CertAndIssuer> client_certs( 199 base::Time now) {
199 CreateSortedCertAndIssuerList(certs, now)); 200 std::unique_ptr<NetworkCertMatches> matches =
201 base::MakeUnique<NetworkCertMatches>();
202
203 std::vector<CertAndIssuer> all_client_certs(
204 CreateSortedCertAndIssuerList(all_certs, now));
205 std::vector<CertAndIssuer> system_client_certs(
206 CreateSortedCertAndIssuerList(system_certs, now));
200 207
201 for (std::vector<NetworkAndCertPattern>::const_iterator it = 208 for (std::vector<NetworkAndCertPattern>::const_iterator it =
202 networks->begin(); 209 networks->begin();
203 it != networks->end(); ++it) { 210 it != networks->end(); ++it) {
204 std::vector<CertAndIssuer>::iterator cert_it = 211 // Use only certs from the system token if the source of the client cert
205 std::find_if(client_certs.begin(), 212 // pattern is device policy.
206 client_certs.end(), 213 std::vector<CertAndIssuer>* client_certs =
207 MatchCertWithPattern(it->cert_config.pattern)); 214 it->cert_config.onc_source == ::onc::ONC_SOURCE_DEVICE_POLICY
215 ? &system_client_certs
216 : &all_client_certs;
217 auto cert_it = std::find_if(client_certs->begin(), client_certs->end(),
218 MatchCertWithPattern(it->cert_config.pattern));
208 std::string pkcs11_id; 219 std::string pkcs11_id;
209 int slot_id = -1; 220 int slot_id = -1;
210 std::string identity; 221 std::string identity;
211 222
212 if (cert_it == client_certs.end()) { 223 if (cert_it == client_certs->end()) {
213 VLOG(1) << "Couldn't find a matching client cert for network " 224 VLOG(1) << "Couldn't find a matching client cert for network "
214 << it->service_path; 225 << it->service_path;
215 // Leave |pkcs11_id| empty to indicate that no cert was found for this 226 // Leave |pkcs11_id| empty to indicate that no cert was found for this
216 // network. 227 // network.
217 } else { 228 } else {
218 pkcs11_id = 229 pkcs11_id =
219 CertLoader::GetPkcs11IdAndSlotForCert(*cert_it->cert, &slot_id); 230 CertLoader::GetPkcs11IdAndSlotForCert(*cert_it->cert, &slot_id);
220 if (pkcs11_id.empty()) { 231 if (pkcs11_id.empty()) {
221 LOG(ERROR) << "Couldn't determine PKCS#11 ID."; 232 LOG(ERROR) << "Couldn't determine PKCS#11 ID.";
222 // So far this error is not expected to happen. We can just continue, in 233 // So far this error is not expected to happen. We can just continue, in
(...skipping 26 matching lines...) Expand all
249 if (!names.empty()) { 260 if (!names.empty()) {
250 base::ReplaceSubstringsAfterOffset( 261 base::ReplaceSubstringsAfterOffset(
251 &identity, offset, onc::substitutes::kCertSANUPN, names[0]); 262 &identity, offset, onc::substitutes::kCertSANUPN, names[0]);
252 } 263 }
253 } 264 }
254 } 265 }
255 matches->push_back(ClientCertResolver::NetworkAndMatchingCert( 266 matches->push_back(ClientCertResolver::NetworkAndMatchingCert(
256 it->service_path, it->cert_config.location, pkcs11_id, slot_id, 267 it->service_path, it->cert_config.location, pkcs11_id, slot_id,
257 identity)); 268 identity));
258 } 269 }
270 return matches;
259 } 271 }
260 272
261 void LogError(const std::string& service_path, 273 void LogError(const std::string& service_path,
262 const std::string& dbus_error_name, 274 const std::string& dbus_error_name,
263 const std::string& dbus_error_message) { 275 const std::string& dbus_error_message) {
264 network_handler::ShillErrorCallbackFunction( 276 network_handler::ShillErrorCallbackFunction(
265 "ClientCertResolver.SetProperties failed", 277 "ClientCertResolver.SetProperties failed",
266 service_path, 278 service_path,
267 network_handler::ErrorCallback(), 279 network_handler::ErrorCallback(),
268 dbus_error_name, 280 dbus_error_name,
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 observers_.RemoveObserver(observer); 330 observers_.RemoveObserver(observer);
319 } 331 }
320 332
321 bool ClientCertResolver::IsAnyResolveTaskRunning() const { 333 bool ClientCertResolver::IsAnyResolveTaskRunning() const {
322 return resolve_task_running_; 334 return resolve_task_running_;
323 } 335 }
324 336
325 // static 337 // static
326 bool ClientCertResolver::ResolveCertificatePatternSync( 338 bool ClientCertResolver::ResolveCertificatePatternSync(
327 const client_cert::ConfigType client_cert_type, 339 const client_cert::ConfigType client_cert_type,
328 const CertificatePattern& pattern, 340 const client_cert::ClientCertConfig& client_cert_config,
329 base::DictionaryValue* shill_properties) { 341 base::DictionaryValue* shill_properties) {
330 // Prepare and sort the list of known client certs. 342 // Prepare and sort the list of known client certs. Use only certs from the
331 std::vector<CertAndIssuer> client_certs(CreateSortedCertAndIssuerList( 343 // system token if the source of the client cert pattern is device policy.
332 CertLoader::Get()->cert_list(), base::Time::Now())); 344 std::vector<CertAndIssuer> client_certs;
345 if (client_cert_config.onc_source == ::onc::ONC_SOURCE_DEVICE_POLICY) {
346 client_certs = CreateSortedCertAndIssuerList(
347 CertLoader::Get()->system_certs(), base::Time::Now());
348 } else {
349 client_certs = CreateSortedCertAndIssuerList(CertLoader::Get()->all_certs(),
350 base::Time::Now());
351 }
333 352
334 // Search for a certificate matching the pattern. 353 // Search for a certificate matching the pattern.
335 std::vector<CertAndIssuer>::iterator cert_it = std::find_if( 354 std::vector<CertAndIssuer>::iterator cert_it =
336 client_certs.begin(), client_certs.end(), MatchCertWithPattern(pattern)); 355 std::find_if(client_certs.begin(), client_certs.end(),
356 MatchCertWithPattern(client_cert_config.pattern));
337 357
338 if (cert_it == client_certs.end()) { 358 if (cert_it == client_certs.end()) {
339 VLOG(1) << "Couldn't find a matching client cert"; 359 VLOG(1) << "Couldn't find a matching client cert";
340 client_cert::SetEmptyShillProperties(client_cert_type, shill_properties); 360 client_cert::SetEmptyShillProperties(client_cert_type, shill_properties);
341 return false; 361 return false;
342 } 362 }
343 363
344 int slot_id = -1; 364 int slot_id = -1;
345 std::string pkcs11_id = 365 std::string pkcs11_id =
346 CertLoader::GetPkcs11IdAndSlotForCert(*cert_it->cert, &slot_id); 366 CertLoader::GetPkcs11IdAndSlotForCert(*cert_it->cert, &slot_id);
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 networks.begin(); it != networks.end(); ++it) { 465 networks.begin(); it != networks.end(); ++it) {
446 const NetworkState* network = *it; 466 const NetworkState* network = *it;
447 467
448 // In any case, don't check this network again in NetworkListChanged. 468 // In any case, don't check this network again in NetworkListChanged.
449 resolved_networks_.insert(network->path()); 469 resolved_networks_.insert(network->path());
450 470
451 // If this network is not configured, it cannot have a ClientCertPattern. 471 // If this network is not configured, it cannot have a ClientCertPattern.
452 if (network->profile_path().empty()) 472 if (network->profile_path().empty())
453 continue; 473 continue;
454 474
475 onc::ONCSource onc_source = onc::ONC_SOURCE_NONE;
455 const base::DictionaryValue* policy = 476 const base::DictionaryValue* policy =
456 managed_network_config_handler_->FindPolicyByGuidAndProfile( 477 managed_network_config_handler_->FindPolicyByGuidAndProfile(
457 network->guid(), network->profile_path()); 478 network->guid(), network->profile_path(), &onc_source);
458 479
459 if (!policy) { 480 if (!policy) {
460 VLOG(1) << "The policy for network " << network->path() << " with GUID " 481 VLOG(1) << "The policy for network " << network->path() << " with GUID "
461 << network->guid() << " is not available yet."; 482 << network->guid() << " is not available yet.";
462 // Skip this network for now. Once the policy is loaded, PolicyApplied() 483 // Skip this network for now. Once the policy is loaded, PolicyApplied()
463 // will retry. 484 // will retry.
464 continue; 485 continue;
465 } 486 }
466 487
467 VLOG(2) << "Inspecting network " << network->path(); 488 VLOG(2) << "Inspecting network " << network->path();
468 client_cert::ClientCertConfig cert_config; 489 client_cert::ClientCertConfig cert_config;
469 OncToClientCertConfig(*policy, &cert_config); 490 OncToClientCertConfig(onc_source, *policy, &cert_config);
470 491
471 // Skip networks that don't have a ClientCertPattern. 492 // Skip networks that don't have a ClientCertPattern.
472 if (cert_config.client_cert_type != ::onc::client_cert::kPattern) 493 if (cert_config.client_cert_type != ::onc::client_cert::kPattern)
473 continue; 494 continue;
474 495
475 networks_to_resolve->push_back( 496 networks_to_resolve->push_back(
476 NetworkAndCertPattern(network->path(), cert_config)); 497 NetworkAndCertPattern(network->path(), cert_config));
477 } 498 }
478 499
479 if (networks_to_resolve->empty()) { 500 if (networks_to_resolve->empty()) {
480 VLOG(1) << "No networks to resolve."; 501 VLOG(1) << "No networks to resolve.";
481 NotifyResolveRequestCompleted(); 502 NotifyResolveRequestCompleted();
482 return; 503 return;
483 } 504 }
484 505
485 if (resolve_task_running_) { 506 if (resolve_task_running_) {
486 VLOG(1) << "A resolve task is already running. Queue this request."; 507 VLOG(1) << "A resolve task is already running. Queue this request.";
487 for (const NetworkAndCertPattern& network_and_pattern : 508 for (const NetworkAndCertPattern& network_and_pattern :
488 *networks_to_resolve) { 509 *networks_to_resolve) {
489 queued_networks_to_resolve_.insert(network_and_pattern.service_path); 510 queued_networks_to_resolve_.insert(network_and_pattern.service_path);
490 } 511 }
491 return; 512 return;
492 } 513 }
493 514
494 VLOG(2) << "Start task for resolving client cert patterns."; 515 VLOG(2) << "Start task for resolving client cert patterns.";
495 resolve_task_running_ = true; 516 resolve_task_running_ = true;
496 NetworkCertMatches* matches = new NetworkCertMatches; 517 base::PostTaskWithTraitsAndReplyWithResult(
497 base::PostTaskWithTraitsAndReply( 518 FROM_HERE,
498 FROM_HERE, base::TaskTraits() 519 base::TaskTraits()
499 .WithShutdownBehavior( 520 .WithShutdownBehavior(
500 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) 521 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)
501 .MayBlock(), 522 .MayBlock(),
502 base::Bind(&FindCertificateMatches, CertLoader::Get()->cert_list(), 523 base::Bind(&FindCertificateMatches, CertLoader::Get()->all_certs(),
503 base::Owned(networks_to_resolve.release()), Now(), matches), 524 CertLoader::Get()->system_certs(),
525 base::Owned(networks_to_resolve.release()), Now()),
504 base::Bind(&ClientCertResolver::ConfigureCertificates, 526 base::Bind(&ClientCertResolver::ConfigureCertificates,
505 weak_ptr_factory_.GetWeakPtr(), base::Owned(matches))); 527 weak_ptr_factory_.GetWeakPtr()));
506 } 528 }
507 529
508 void ClientCertResolver::ResolvePendingNetworks() { 530 void ClientCertResolver::ResolvePendingNetworks() {
509 NetworkStateHandler::NetworkStateList networks; 531 NetworkStateHandler::NetworkStateList networks;
510 network_state_handler_->GetNetworkListByType(NetworkTypePattern::Default(), 532 network_state_handler_->GetNetworkListByType(NetworkTypePattern::Default(),
511 true /* configured_only */, 533 true /* configured_only */,
512 false /* visible_only */, 534 false /* visible_only */,
513 0 /* no limit */, 535 0 /* no limit */,
514 &networks); 536 &networks);
515 537
516 NetworkStateHandler::NetworkStateList networks_to_resolve; 538 NetworkStateHandler::NetworkStateList networks_to_resolve;
517 for (const NetworkState* network : networks) { 539 for (const NetworkState* network : networks) {
518 if (queued_networks_to_resolve_.count(network->path()) > 0) 540 if (queued_networks_to_resolve_.count(network->path()) > 0)
519 networks_to_resolve.push_back(network); 541 networks_to_resolve.push_back(network);
520 } 542 }
521 VLOG(1) << "Resolve pending " << networks_to_resolve.size() << " networks."; 543 VLOG(1) << "Resolve pending " << networks_to_resolve.size() << " networks.";
522 queued_networks_to_resolve_.clear(); 544 queued_networks_to_resolve_.clear();
523 ResolveNetworks(networks_to_resolve); 545 ResolveNetworks(networks_to_resolve);
524 } 546 }
525 547
526 void ClientCertResolver::ConfigureCertificates(NetworkCertMatches* matches) { 548 void ClientCertResolver::ConfigureCertificates(
549 std::unique_ptr<NetworkCertMatches> matches) {
527 for (NetworkCertMatches::const_iterator it = matches->begin(); 550 for (NetworkCertMatches::const_iterator it = matches->begin();
528 it != matches->end(); ++it) { 551 it != matches->end(); ++it) {
529 VLOG(1) << "Configuring certificate of network " << it->service_path; 552 VLOG(1) << "Configuring certificate of network " << it->service_path;
530 base::DictionaryValue shill_properties; 553 base::DictionaryValue shill_properties;
531 if (it->pkcs11_id.empty()) { 554 if (it->pkcs11_id.empty()) {
532 client_cert::SetEmptyShillProperties(it->cert_config_type, 555 client_cert::SetEmptyShillProperties(it->cert_config_type,
533 &shill_properties); 556 &shill_properties);
534 } else { 557 } else {
535 client_cert::SetShillProperties(it->cert_config_type, 558 client_cert::SetShillProperties(it->cert_config_type,
536 it->key_slot_id, 559 it->key_slot_id,
(...skipping 28 matching lines...) Expand all
565 observer.ResolveRequestCompleted(changed); 588 observer.ResolveRequestCompleted(changed);
566 } 589 }
567 590
568 base::Time ClientCertResolver::Now() const { 591 base::Time ClientCertResolver::Now() const {
569 if (testing_clock_) 592 if (testing_clock_)
570 return testing_clock_->Now(); 593 return testing_clock_->Now();
571 return base::Time::Now(); 594 return base::Time::Now();
572 } 595 }
573 596
574 } // namespace chromeos 597 } // namespace chromeos
OLDNEW
« no previous file with comments | « chromeos/network/client_cert_resolver.h ('k') | chromeos/network/client_cert_resolver_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698