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

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

Issue 1443043002: Execute ClientCertResolver on network disconnection. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Changed SimpleTestClock ownership Created 5 years, 1 month 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/stl_util.h" 16 #include "base/stl_util.h"
17 #include "base/task_runner.h" 17 #include "base/task_runner.h"
18 #include "base/threading/worker_pool.h" 18 #include "base/threading/worker_pool.h"
19 #include "base/time/clock.h"
19 #include "chromeos/dbus/dbus_thread_manager.h" 20 #include "chromeos/dbus/dbus_thread_manager.h"
20 #include "chromeos/dbus/shill_service_client.h" 21 #include "chromeos/dbus/shill_service_client.h"
21 #include "chromeos/network/managed_network_configuration_handler.h" 22 #include "chromeos/network/managed_network_configuration_handler.h"
22 #include "chromeos/network/network_state.h" 23 #include "chromeos/network/network_state.h"
23 #include "components/onc/onc_constants.h" 24 #include "components/onc/onc_constants.h"
24 #include "dbus/object_path.h" 25 #include "dbus/object_path.h"
25 #include "net/cert/scoped_nss_types.h" 26 #include "net/cert/scoped_nss_types.h"
26 #include "net/cert/x509_certificate.h" 27 #include "net/cert/x509_certificate.h"
27 28
28 namespace chromeos { 29 namespace chromeos {
(...skipping 26 matching lines...) Expand all
55 namespace { 56 namespace {
56 57
57 // Returns true if |vector| contains |value|. 58 // Returns true if |vector| contains |value|.
58 template <class T> 59 template <class T>
59 bool ContainsValue(const std::vector<T>& vector, const T& value) { 60 bool ContainsValue(const std::vector<T>& vector, const T& value) {
60 return find(vector.begin(), vector.end(), value) != vector.end(); 61 return find(vector.begin(), vector.end(), value) != vector.end();
61 } 62 }
62 63
63 // Returns true if a private key for certificate |cert| is installed. 64 // Returns true if a private key for certificate |cert| is installed.
64 bool HasPrivateKey(const net::X509Certificate& cert) { 65 bool HasPrivateKey(const net::X509Certificate& cert) {
65 PK11SlotInfo* slot = PK11_KeyForCertExists(cert.os_cert_handle(), NULL, NULL); 66 PK11SlotInfo* slot =
67 PK11_KeyForCertExists(cert.os_cert_handle(), nullptr, nullptr);
66 if (!slot) 68 if (!slot)
67 return false; 69 return false;
68 70
69 PK11_FreeSlot(slot); 71 PK11_FreeSlot(slot);
70 return true; 72 return true;
71 } 73 }
72 74
73 // Describes a certificate which is issued by |issuer| (encoded as PEM). 75 // Describes a certificate which is issued by |issuer| (encoded as PEM).
74 // |issuer| can be empty if no issuer certificate is found in the database. 76 // |issuer| can be empty if no issuer certificate is found in the database.
75 struct CertAndIssuer { 77 struct CertAndIssuer {
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 std::string pem_encoded_issuer; 151 std::string pem_encoded_issuer;
150 if (!net::X509Certificate::GetPEMEncoded(issuer->os_cert_handle(), 152 if (!net::X509Certificate::GetPEMEncoded(issuer->os_cert_handle(),
151 &pem_encoded_issuer)) { 153 &pem_encoded_issuer)) {
152 LOG(ERROR) << "Couldn't PEM-encode certificate."; 154 LOG(ERROR) << "Couldn't PEM-encode certificate.";
153 return std::string(); 155 return std::string();
154 } 156 }
155 return pem_encoded_issuer; 157 return pem_encoded_issuer;
156 } 158 }
157 159
158 std::vector<CertAndIssuer> CreateSortedCertAndIssuerList( 160 std::vector<CertAndIssuer> CreateSortedCertAndIssuerList(
159 const net::CertificateList& certs) { 161 const net::CertificateList& certs,
162 base::Time now) {
160 // Filter all client certs and determines each certificate's issuer, which is 163 // Filter all client certs and determines each certificate's issuer, which is
161 // required for the pattern matching. 164 // required for the pattern matching.
162 std::vector<CertAndIssuer> client_certs; 165 std::vector<CertAndIssuer> client_certs;
163 for (net::CertificateList::const_iterator it = certs.begin(); 166 for (net::CertificateList::const_iterator it = certs.begin();
164 it != certs.end(); ++it) { 167 it != certs.end(); ++it) {
165 const net::X509Certificate& cert = **it; 168 const net::X509Certificate& cert = **it;
166 if (cert.valid_expiry().is_null() || cert.HasExpired() || 169 if (cert.valid_expiry().is_null() || now > cert.valid_expiry() ||
167 !HasPrivateKey(cert) || 170 !HasPrivateKey(cert) ||
168 !CertLoader::IsCertificateHardwareBacked(&cert)) { 171 !CertLoader::IsCertificateHardwareBacked(&cert)) {
169 continue; 172 continue;
170 } 173 }
171 client_certs.push_back(CertAndIssuer(*it, GetPEMEncodedIssuer(cert))); 174 client_certs.push_back(CertAndIssuer(*it, GetPEMEncodedIssuer(cert)));
172 } 175 }
173 176
174 std::sort(client_certs.begin(), client_certs.end(), &CompareCertExpiration); 177 std::sort(client_certs.begin(), client_certs.end(), &CompareCertExpiration);
175 return client_certs; 178 return client_certs;
176 } 179 }
177 180
178 // Searches for matches between |networks| and |certs| and writes matches to 181 // Searches for matches between |networks| and |certs| and writes matches to
179 // |matches|. Because this calls NSS functions and is potentially slow, it must 182 // |matches|. Because this calls NSS functions and is potentially slow, it must
180 // be run on a worker thread. 183 // be run on a worker thread.
181 void FindCertificateMatches(const net::CertificateList& certs, 184 void FindCertificateMatches(const net::CertificateList& certs,
182 std::vector<NetworkAndCertPattern>* networks, 185 std::vector<NetworkAndCertPattern>* networks,
186 base::Time now,
183 NetworkCertMatches* matches) { 187 NetworkCertMatches* matches) {
184 std::vector<CertAndIssuer> client_certs(CreateSortedCertAndIssuerList(certs)); 188 std::vector<CertAndIssuer> client_certs(
189 CreateSortedCertAndIssuerList(certs, now));
185 190
186 for (std::vector<NetworkAndCertPattern>::const_iterator it = 191 for (std::vector<NetworkAndCertPattern>::const_iterator it =
187 networks->begin(); 192 networks->begin();
188 it != networks->end(); ++it) { 193 it != networks->end(); ++it) {
189 std::vector<CertAndIssuer>::iterator cert_it = 194 std::vector<CertAndIssuer>::iterator cert_it =
190 std::find_if(client_certs.begin(), 195 std::find_if(client_certs.begin(),
191 client_certs.end(), 196 client_certs.end(),
192 MatchCertWithPattern(it->cert_config.pattern)); 197 MatchCertWithPattern(it->cert_config.pattern));
193 std::string pkcs11_id; 198 std::string pkcs11_id;
194 int slot_id = -1; 199 int slot_id = -1;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 return false; 234 return false;
230 } 235 }
231 return true; 236 return true;
232 } 237 }
233 238
234 } // namespace 239 } // namespace
235 240
236 ClientCertResolver::ClientCertResolver() 241 ClientCertResolver::ClientCertResolver()
237 : resolve_task_running_(false), 242 : resolve_task_running_(false),
238 network_properties_changed_(false), 243 network_properties_changed_(false),
239 network_state_handler_(NULL), 244 network_state_handler_(nullptr),
240 managed_network_config_handler_(NULL), 245 managed_network_config_handler_(nullptr),
241 weak_ptr_factory_(this) { 246 testing_clock_(nullptr),
242 } 247 weak_ptr_factory_(this) {}
243 248
244 ClientCertResolver::~ClientCertResolver() { 249 ClientCertResolver::~ClientCertResolver() {
245 if (network_state_handler_) 250 if (network_state_handler_)
246 network_state_handler_->RemoveObserver(this, FROM_HERE); 251 network_state_handler_->RemoveObserver(this, FROM_HERE);
247 if (CertLoader::IsInitialized()) 252 if (CertLoader::IsInitialized())
248 CertLoader::Get()->RemoveObserver(this); 253 CertLoader::Get()->RemoveObserver(this);
249 if (managed_network_config_handler_) 254 if (managed_network_config_handler_)
250 managed_network_config_handler_->RemoveObserver(this); 255 managed_network_config_handler_->RemoveObserver(this);
251 } 256 }
252 257
(...skipping 27 matching lines...) Expand all
280 bool ClientCertResolver::IsAnyResolveTaskRunning() const { 285 bool ClientCertResolver::IsAnyResolveTaskRunning() const {
281 return resolve_task_running_; 286 return resolve_task_running_;
282 } 287 }
283 288
284 // static 289 // static
285 bool ClientCertResolver::ResolveCertificatePatternSync( 290 bool ClientCertResolver::ResolveCertificatePatternSync(
286 const client_cert::ConfigType client_cert_type, 291 const client_cert::ConfigType client_cert_type,
287 const CertificatePattern& pattern, 292 const CertificatePattern& pattern,
288 base::DictionaryValue* shill_properties) { 293 base::DictionaryValue* shill_properties) {
289 // Prepare and sort the list of known client certs. 294 // Prepare and sort the list of known client certs.
290 std::vector<CertAndIssuer> client_certs( 295 std::vector<CertAndIssuer> client_certs(CreateSortedCertAndIssuerList(
291 CreateSortedCertAndIssuerList(CertLoader::Get()->cert_list())); 296 CertLoader::Get()->cert_list(), base::Time::Now()));
292 297
293 // Search for a certificate matching the pattern. 298 // Search for a certificate matching the pattern.
294 std::vector<CertAndIssuer>::iterator cert_it = std::find_if( 299 std::vector<CertAndIssuer>::iterator cert_it = std::find_if(
295 client_certs.begin(), client_certs.end(), MatchCertWithPattern(pattern)); 300 client_certs.begin(), client_certs.end(), MatchCertWithPattern(pattern));
296 301
297 if (cert_it == client_certs.end()) { 302 if (cert_it == client_certs.end()) {
298 VLOG(1) << "Couldn't find a matching client cert"; 303 VLOG(1) << "Couldn't find a matching client cert";
299 client_cert::SetEmptyShillProperties(client_cert_type, shill_properties); 304 client_cert::SetEmptyShillProperties(client_cert_type, shill_properties);
300 return false; 305 return false;
301 } 306 }
302 307
303 int slot_id = -1; 308 int slot_id = -1;
304 std::string pkcs11_id = 309 std::string pkcs11_id =
305 CertLoader::GetPkcs11IdAndSlotForCert(*cert_it->cert, &slot_id); 310 CertLoader::GetPkcs11IdAndSlotForCert(*cert_it->cert, &slot_id);
306 if (pkcs11_id.empty()) { 311 if (pkcs11_id.empty()) {
307 LOG(ERROR) << "Couldn't determine PKCS#11 ID."; 312 LOG(ERROR) << "Couldn't determine PKCS#11 ID.";
308 // So far this error is not expected to happen. We can just continue, in 313 // So far this error is not expected to happen. We can just continue, in
309 // the worst case the user can remove the problematic cert. 314 // the worst case the user can remove the problematic cert.
310 return false; 315 return false;
311 } 316 }
312 client_cert::SetShillProperties( 317 client_cert::SetShillProperties(
313 client_cert_type, slot_id, pkcs11_id, shill_properties); 318 client_cert_type, slot_id, pkcs11_id, shill_properties);
314 return true; 319 return true;
315 } 320 }
316 321
322 void ClientCertResolver::SetClockForTesting(base::Clock* clock) {
323 testing_clock_ = clock;
324 }
325
317 void ClientCertResolver::NetworkListChanged() { 326 void ClientCertResolver::NetworkListChanged() {
318 VLOG(2) << "NetworkListChanged."; 327 VLOG(2) << "NetworkListChanged.";
319 if (!ClientCertificatesLoaded()) 328 if (!ClientCertificatesLoaded())
320 return; 329 return;
321 // Configure only networks that were not configured before. 330 // Configure only networks that were not configured before.
322 331
323 // We'll drop networks from |resolved_networks_|, which are not known anymore. 332 // We'll drop networks from |resolved_networks_|, which are not known anymore.
324 std::set<std::string> old_resolved_networks; 333 std::set<std::string> old_resolved_networks;
325 old_resolved_networks.swap(resolved_networks_); 334 old_resolved_networks.swap(resolved_networks_);
326 335
(...skipping 12 matching lines...) Expand all
339 if (ContainsKey(old_resolved_networks, service_path)) { 348 if (ContainsKey(old_resolved_networks, service_path)) {
340 resolved_networks_.insert(service_path); 349 resolved_networks_.insert(service_path);
341 continue; 350 continue;
342 } 351 }
343 networks_to_check.push_back(*it); 352 networks_to_check.push_back(*it);
344 } 353 }
345 354
346 ResolveNetworks(networks_to_check); 355 ResolveNetworks(networks_to_check);
347 } 356 }
348 357
358 void ClientCertResolver::NetworkConnectionStateChanged(
359 const NetworkState* network) {
360 if (!ClientCertificatesLoaded())
361 return;
362 if (!network->IsConnectedState() && !network->IsConnectingState())
363 ResolveNetworks(NetworkStateHandler::NetworkStateList(1, network));
364 }
365
349 void ClientCertResolver::OnCertificatesLoaded( 366 void ClientCertResolver::OnCertificatesLoaded(
350 const net::CertificateList& cert_list, 367 const net::CertificateList& cert_list,
351 bool initial_load) { 368 bool initial_load) {
352 VLOG(2) << "OnCertificatesLoaded."; 369 VLOG(2) << "OnCertificatesLoaded.";
353 if (!ClientCertificatesLoaded()) 370 if (!ClientCertificatesLoaded())
354 return; 371 return;
355 // Compare all networks with all certificates. 372 // Compare all networks with all certificates.
356 NetworkStateHandler::NetworkStateList networks; 373 NetworkStateHandler::NetworkStateList networks;
357 network_state_handler_->GetNetworkListByType( 374 network_state_handler_->GetNetworkListByType(
358 NetworkTypePattern::Default(), 375 NetworkTypePattern::Default(),
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
441 VLOG(2) << "Start task for resolving client cert patterns."; 458 VLOG(2) << "Start task for resolving client cert patterns.";
442 base::TaskRunner* task_runner = slow_task_runner_for_test_.get(); 459 base::TaskRunner* task_runner = slow_task_runner_for_test_.get();
443 if (!task_runner) 460 if (!task_runner)
444 task_runner = 461 task_runner =
445 base::WorkerPool::GetTaskRunner(true /* task is slow */).get(); 462 base::WorkerPool::GetTaskRunner(true /* task is slow */).get();
446 463
447 resolve_task_running_ = true; 464 resolve_task_running_ = true;
448 NetworkCertMatches* matches = new NetworkCertMatches; 465 NetworkCertMatches* matches = new NetworkCertMatches;
449 task_runner->PostTaskAndReply( 466 task_runner->PostTaskAndReply(
450 FROM_HERE, 467 FROM_HERE,
451 base::Bind(&FindCertificateMatches, 468 base::Bind(&FindCertificateMatches, CertLoader::Get()->cert_list(),
452 CertLoader::Get()->cert_list(), 469 base::Owned(networks_to_resolve.release()), Now(), matches),
453 base::Owned(networks_to_resolve.release()),
454 matches),
455 base::Bind(&ClientCertResolver::ConfigureCertificates, 470 base::Bind(&ClientCertResolver::ConfigureCertificates,
456 weak_ptr_factory_.GetWeakPtr(), 471 weak_ptr_factory_.GetWeakPtr(), base::Owned(matches)));
457 base::Owned(matches)));
458 } 472 }
459 473
460 void ClientCertResolver::ResolvePendingNetworks() { 474 void ClientCertResolver::ResolvePendingNetworks() {
461 NetworkStateHandler::NetworkStateList networks; 475 NetworkStateHandler::NetworkStateList networks;
462 network_state_handler_->GetNetworkListByType(NetworkTypePattern::Default(), 476 network_state_handler_->GetNetworkListByType(NetworkTypePattern::Default(),
463 true /* configured_only */, 477 true /* configured_only */,
464 false /* visible_only */, 478 false /* visible_only */,
465 0 /* no limit */, 479 0 /* no limit */,
466 &networks); 480 &networks);
467 481
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
505 519
506 void ClientCertResolver::NotifyResolveRequestCompleted() { 520 void ClientCertResolver::NotifyResolveRequestCompleted() {
507 VLOG(2) << "Notify observers: " << (network_properties_changed_ ? "" : "no ") 521 VLOG(2) << "Notify observers: " << (network_properties_changed_ ? "" : "no ")
508 << "networks changed."; 522 << "networks changed.";
509 resolve_task_running_ = false; 523 resolve_task_running_ = false;
510 const bool changed = network_properties_changed_; 524 const bool changed = network_properties_changed_;
511 network_properties_changed_ = false; 525 network_properties_changed_ = false;
512 FOR_EACH_OBSERVER(Observer, observers_, ResolveRequestCompleted(changed)); 526 FOR_EACH_OBSERVER(Observer, observers_, ResolveRequestCompleted(changed));
513 } 527 }
514 528
529 base::Time ClientCertResolver::Now() const {
530 if (testing_clock_)
531 return testing_clock_->Now();
532 return base::Time::Now();
533 }
534
515 } // namespace chromeos 535 } // 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