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

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

Issue 421113002: Use correct slot id for client certs in network config. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed comments. Created 6 years, 4 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 | Annotate | Revision Log
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 #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"
18 #include "base/task_runner.h" 17 #include "base/task_runner.h"
19 #include "base/threading/worker_pool.h" 18 #include "base/threading/worker_pool.h"
20 #include "base/time/time.h" 19 #include "base/time/time.h"
21 #include "chromeos/cert_loader.h" 20 #include "chromeos/cert_loader.h"
22 #include "chromeos/dbus/dbus_thread_manager.h" 21 #include "chromeos/dbus/dbus_thread_manager.h"
23 #include "chromeos/dbus/shill_service_client.h" 22 #include "chromeos/dbus/shill_service_client.h"
24 #include "chromeos/network/certificate_pattern.h"
25 #include "chromeos/network/client_cert_util.h"
26 #include "chromeos/network/managed_network_configuration_handler.h" 23 #include "chromeos/network/managed_network_configuration_handler.h"
27 #include "chromeos/network/network_state.h" 24 #include "chromeos/network/network_state.h"
28 #include "chromeos/tpm_token_loader.h"
29 #include "components/onc/onc_constants.h" 25 #include "components/onc/onc_constants.h"
30 #include "dbus/object_path.h" 26 #include "dbus/object_path.h"
31 #include "net/cert/scoped_nss_types.h" 27 #include "net/cert/scoped_nss_types.h"
32 #include "net/cert/x509_certificate.h" 28 #include "net/cert/x509_certificate.h"
33 29
34 namespace chromeos { 30 namespace chromeos {
35 31
36 // Describes a network |network_path| for which a matching certificate |cert_id| 32 // Describes a network |network_path| for which a matching certificate |cert_id|
37 // was found or for which no certificate was found (|cert_id| will be empty). 33 // was found or for which no certificate was found (|cert_id| will be empty).
38 struct ClientCertResolver::NetworkAndMatchingCert { 34 struct ClientCertResolver::NetworkAndMatchingCert {
39 NetworkAndMatchingCert(const std::string& network_path, 35 NetworkAndMatchingCert(const std::string& network_path,
40 client_cert::ConfigType config_type, 36 client_cert::ConfigType config_type,
41 const std::string& cert_id) 37 const std::string& cert_id,
38 int slot_id)
42 : service_path(network_path), 39 : service_path(network_path),
43 cert_config_type(config_type), 40 cert_config_type(config_type),
44 pkcs11_id(cert_id) {} 41 pkcs11_id(cert_id),
42 key_slot_id(slot_id) {}
45 43
46 std::string service_path; 44 std::string service_path;
47 client_cert::ConfigType cert_config_type; 45 client_cert::ConfigType cert_config_type;
48 46
49 // The id of the matching certificate or empty if no certificate was found. 47 // The id of the matching certificate or empty if no certificate was found.
50 std::string pkcs11_id; 48 std::string pkcs11_id;
49
50 // The id of the slot containing the certificate and the private key.
51 int key_slot_id;
51 }; 52 };
52 53
53 typedef std::vector<ClientCertResolver::NetworkAndMatchingCert> 54 typedef std::vector<ClientCertResolver::NetworkAndMatchingCert>
54 NetworkCertMatches; 55 NetworkCertMatches;
55 56
56 namespace { 57 namespace {
57 58
58 // Returns true if |vector| contains |value|. 59 // Returns true if |vector| contains |value|.
59 template <class T> 60 template <class T>
60 bool ContainsValue(const std::vector<T>& vector, const T& value) { 61 bool ContainsValue(const std::vector<T>& vector, const T& value) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 NetworkAndCertPattern(const std::string& network_path, 94 NetworkAndCertPattern(const std::string& network_path,
94 const client_cert::ClientCertConfig& client_cert_config) 95 const client_cert::ClientCertConfig& client_cert_config)
95 : service_path(network_path), 96 : service_path(network_path),
96 cert_config(client_cert_config) {} 97 cert_config(client_cert_config) {}
97 98
98 std::string service_path; 99 std::string service_path;
99 client_cert::ClientCertConfig cert_config; 100 client_cert::ClientCertConfig cert_config;
100 }; 101 };
101 102
102 // A unary predicate that returns true if the given CertAndIssuer matches the 103 // A unary predicate that returns true if the given CertAndIssuer matches the
103 // certificate pattern of the NetworkAndCertPattern. 104 // given certificate pattern.
104 struct MatchCertWithPattern { 105 struct MatchCertWithPattern {
105 explicit MatchCertWithPattern(const NetworkAndCertPattern& pattern) 106 explicit MatchCertWithPattern(const CertificatePattern& cert_pattern)
106 : net_and_pattern(pattern) {} 107 : pattern(cert_pattern) {}
107 108
108 bool operator()(const CertAndIssuer& cert_and_issuer) { 109 bool operator()(const CertAndIssuer& cert_and_issuer) {
109 const CertificatePattern& pattern = net_and_pattern.cert_config.pattern;
110 if (!pattern.issuer().Empty() && 110 if (!pattern.issuer().Empty() &&
111 !client_cert::CertPrincipalMatches(pattern.issuer(), 111 !client_cert::CertPrincipalMatches(pattern.issuer(),
112 cert_and_issuer.cert->issuer())) { 112 cert_and_issuer.cert->issuer())) {
113 return false; 113 return false;
114 } 114 }
115 if (!pattern.subject().Empty() && 115 if (!pattern.subject().Empty() &&
116 !client_cert::CertPrincipalMatches(pattern.subject(), 116 !client_cert::CertPrincipalMatches(pattern.subject(),
117 cert_and_issuer.cert->subject())) { 117 cert_and_issuer.cert->subject())) {
118 return false; 118 return false;
119 } 119 }
120 120
121 const std::vector<std::string>& issuer_ca_pems = pattern.issuer_ca_pems(); 121 const std::vector<std::string>& issuer_ca_pems = pattern.issuer_ca_pems();
122 if (!issuer_ca_pems.empty() && 122 if (!issuer_ca_pems.empty() &&
123 !ContainsValue(issuer_ca_pems, cert_and_issuer.pem_encoded_issuer)) { 123 !ContainsValue(issuer_ca_pems, cert_and_issuer.pem_encoded_issuer)) {
124 return false; 124 return false;
125 } 125 }
126 return true; 126 return true;
127 } 127 }
128 128
129 NetworkAndCertPattern net_and_pattern; 129 const CertificatePattern pattern;
130 }; 130 };
131 131
132 // Searches for matches between |networks| and |certs| and writes matches to 132 std::vector<CertAndIssuer> CreateSortedCertAndIssuerList(
133 // |matches|. Because this calls NSS functions and is potentially slow, it must 133 const net::CertificateList& certs) {
134 // be run on a worker thread.
135 void FindCertificateMatches(const net::CertificateList& certs,
136 std::vector<NetworkAndCertPattern>* networks,
137 NetworkCertMatches* matches) {
138 // Filter all client certs and determines each certificate's issuer, which is 134 // Filter all client certs and determines each certificate's issuer, which is
139 // required for the pattern matching. 135 // required for the pattern matching.
140 std::vector<CertAndIssuer> client_certs; 136 std::vector<CertAndIssuer> client_certs;
141 for (net::CertificateList::const_iterator it = certs.begin(); 137 for (net::CertificateList::const_iterator it = certs.begin();
142 it != certs.end(); ++it) { 138 it != certs.end(); ++it) {
143 const net::X509Certificate& cert = **it; 139 const net::X509Certificate& cert = **it;
144 if (cert.valid_expiry().is_null() || cert.HasExpired() || 140 if (cert.valid_expiry().is_null() || cert.HasExpired() ||
145 !HasPrivateKey(cert)) { 141 !HasPrivateKey(cert)) {
146 continue; 142 continue;
147 } 143 }
(...skipping 14 matching lines...) Expand all
162 std::string pem_encoded_issuer; 158 std::string pem_encoded_issuer;
163 if (!net::X509Certificate::GetPEMEncoded(issuer->os_cert_handle(), 159 if (!net::X509Certificate::GetPEMEncoded(issuer->os_cert_handle(),
164 &pem_encoded_issuer)) { 160 &pem_encoded_issuer)) {
165 LOG(ERROR) << "Couldn't PEM-encode certificate."; 161 LOG(ERROR) << "Couldn't PEM-encode certificate.";
166 continue; 162 continue;
167 } 163 }
168 client_certs.push_back(CertAndIssuer(*it, pem_encoded_issuer)); 164 client_certs.push_back(CertAndIssuer(*it, pem_encoded_issuer));
169 } 165 }
170 166
171 std::sort(client_certs.begin(), client_certs.end(), &CompareCertExpiration); 167 std::sort(client_certs.begin(), client_certs.end(), &CompareCertExpiration);
168 return client_certs;
169 }
170
171 // Searches for matches between |networks| and |certs| and writes matches to
172 // |matches|. Because this calls NSS functions and is potentially slow, it must
173 // be run on a worker thread.
174 void FindCertificateMatches(const net::CertificateList& certs,
175 std::vector<NetworkAndCertPattern>* networks,
176 NetworkCertMatches* matches) {
177 std::vector<CertAndIssuer> client_certs(CreateSortedCertAndIssuerList(certs));
172 178
173 for (std::vector<NetworkAndCertPattern>::const_iterator it = 179 for (std::vector<NetworkAndCertPattern>::const_iterator it =
174 networks->begin(); 180 networks->begin();
175 it != networks->end(); ++it) { 181 it != networks->end(); ++it) {
176 std::vector<CertAndIssuer>::iterator cert_it = std::find_if( 182 std::vector<CertAndIssuer>::iterator cert_it =
177 client_certs.begin(), client_certs.end(), MatchCertWithPattern(*it)); 183 std::find_if(client_certs.begin(),
184 client_certs.end(),
185 MatchCertWithPattern(it->cert_config.pattern));
178 std::string pkcs11_id; 186 std::string pkcs11_id;
187 int slot_id = -1;
179 if (cert_it == client_certs.end()) { 188 if (cert_it == client_certs.end()) {
180 VLOG(1) << "Couldn't find a matching client cert for network " 189 VLOG(1) << "Couldn't find a matching client cert for network "
181 << it->service_path; 190 << it->service_path;
182 // Leave |pkcs11_id empty| to indicate that no cert was found for this 191 // Leave |pkcs11_id| empty to indicate that no cert was found for this
183 // network. 192 // network.
184 } else { 193 } else {
185 pkcs11_id = CertLoader::GetPkcs11IdForCert(*cert_it->cert); 194 pkcs11_id =
195 CertLoader::GetPkcs11IdAndSlotForCert(*cert_it->cert, &slot_id);
186 if (pkcs11_id.empty()) { 196 if (pkcs11_id.empty()) {
187 LOG(ERROR) << "Couldn't determine PKCS#11 ID."; 197 LOG(ERROR) << "Couldn't determine PKCS#11 ID.";
188 // So far this error is not expected to happen. We can just continue, in 198 // So far this error is not expected to happen. We can just continue, in
189 // the worst case the user can remove the problematic cert. 199 // the worst case the user can remove the problematic cert.
190 continue; 200 continue;
191 } 201 }
192 } 202 }
193 matches->push_back(ClientCertResolver::NetworkAndMatchingCert( 203 matches->push_back(ClientCertResolver::NetworkAndMatchingCert(
194 it->service_path, it->cert_config.location, pkcs11_id)); 204 it->service_path, it->cert_config.location, pkcs11_id, slot_id));
195 } 205 }
196 } 206 }
197 207
198 void LogError(const std::string& service_path, 208 void LogError(const std::string& service_path,
199 const std::string& dbus_error_name, 209 const std::string& dbus_error_name,
200 const std::string& dbus_error_message) { 210 const std::string& dbus_error_message) {
201 network_handler::ShillErrorCallbackFunction( 211 network_handler::ShillErrorCallbackFunction(
202 "ClientCertResolver.SetProperties failed", 212 "ClientCertResolver.SetProperties failed",
203 service_path, 213 service_path,
204 network_handler::ErrorCallback(), 214 network_handler::ErrorCallback(),
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 managed_network_config_handler_->AddObserver(this); 257 managed_network_config_handler_->AddObserver(this);
248 258
249 CertLoader::Get()->AddObserver(this); 259 CertLoader::Get()->AddObserver(this);
250 } 260 }
251 261
252 void ClientCertResolver::SetSlowTaskRunnerForTest( 262 void ClientCertResolver::SetSlowTaskRunnerForTest(
253 const scoped_refptr<base::TaskRunner>& task_runner) { 263 const scoped_refptr<base::TaskRunner>& task_runner) {
254 slow_task_runner_for_test_ = task_runner; 264 slow_task_runner_for_test_ = task_runner;
255 } 265 }
256 266
267 // static
268 bool ClientCertResolver::ResolveCertificatePatternSync(
269 const client_cert::ConfigType client_cert_type,
270 const CertificatePattern& pattern,
271 base::DictionaryValue* shill_properties) {
272 // Prepare and sort the list of known client certs.
273 std::vector<CertAndIssuer> client_certs(
274 CreateSortedCertAndIssuerList(CertLoader::Get()->cert_list()));
275
276 // Search for a certificate matching the pattern.
277 std::vector<CertAndIssuer>::iterator cert_it = std::find_if(
278 client_certs.begin(), client_certs.end(), MatchCertWithPattern(pattern));
279
280 if (cert_it == client_certs.end()) {
281 VLOG(1) << "Couldn't find a matching client cert";
282 client_cert::SetEmptyShillProperties(client_cert_type, shill_properties);
283 return false;
284 }
285
286 int slot_id = -1;
287 std::string pkcs11_id =
288 CertLoader::GetPkcs11IdAndSlotForCert(*cert_it->cert, &slot_id);
289 if (pkcs11_id.empty()) {
290 LOG(ERROR) << "Couldn't determine PKCS#11 ID.";
291 // So far this error is not expected to happen. We can just continue, in
292 // the worst case the user can remove the problematic cert.
293 return false;
294 }
295 client_cert::SetShillProperties(
296 client_cert_type, slot_id, pkcs11_id, shill_properties);
297 return true;
298 }
299
257 void ClientCertResolver::NetworkListChanged() { 300 void ClientCertResolver::NetworkListChanged() {
258 VLOG(2) << "NetworkListChanged."; 301 VLOG(2) << "NetworkListChanged.";
259 if (!ClientCertificatesLoaded()) 302 if (!ClientCertificatesLoaded())
260 return; 303 return;
261 // Configure only networks that were not configured before. 304 // Configure only networks that were not configured before.
262 305
263 // We'll drop networks from |resolved_networks_|, which are not known anymore. 306 // We'll drop networks from |resolved_networks_|, which are not known anymore.
264 std::set<std::string> old_resolved_networks; 307 std::set<std::string> old_resolved_networks;
265 old_resolved_networks.swap(resolved_networks_); 308 old_resolved_networks.swap(resolved_networks_);
266 309
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 matches), 421 matches),
379 base::Bind(&ClientCertResolver::ConfigureCertificates, 422 base::Bind(&ClientCertResolver::ConfigureCertificates,
380 weak_ptr_factory_.GetWeakPtr(), 423 weak_ptr_factory_.GetWeakPtr(),
381 base::Owned(matches))); 424 base::Owned(matches)));
382 } 425 }
383 426
384 void ClientCertResolver::ConfigureCertificates(NetworkCertMatches* matches) { 427 void ClientCertResolver::ConfigureCertificates(NetworkCertMatches* matches) {
385 for (NetworkCertMatches::const_iterator it = matches->begin(); 428 for (NetworkCertMatches::const_iterator it = matches->begin();
386 it != matches->end(); ++it) { 429 it != matches->end(); ++it) {
387 VLOG(1) << "Configuring certificate of network " << it->service_path; 430 VLOG(1) << "Configuring certificate of network " << it->service_path;
388 CertLoader* cert_loader = CertLoader::Get();
389 base::DictionaryValue shill_properties; 431 base::DictionaryValue shill_properties;
390 // If pkcs11_id is empty, this will clear the key/cert properties of this 432 if (it->pkcs11_id.empty()) {
391 // network. 433 client_cert::SetEmptyShillProperties(it->cert_config_type,
392 client_cert::SetShillProperties( 434 &shill_properties);
393 it->cert_config_type, 435 } else {
394 base::IntToString(cert_loader->TPMTokenSlotID()), 436 client_cert::SetShillProperties(it->cert_config_type,
395 TPMTokenLoader::Get()->tpm_user_pin(), 437 it->key_slot_id,
396 &it->pkcs11_id, 438 it->pkcs11_id,
397 &shill_properties); 439 &shill_properties);
440 }
398 DBusThreadManager::Get()->GetShillServiceClient()-> 441 DBusThreadManager::Get()->GetShillServiceClient()->
399 SetProperties(dbus::ObjectPath(it->service_path), 442 SetProperties(dbus::ObjectPath(it->service_path),
400 shill_properties, 443 shill_properties,
401 base::Bind(&base::DoNothing), 444 base::Bind(&base::DoNothing),
402 base::Bind(&LogError, it->service_path)); 445 base::Bind(&LogError, it->service_path));
403 network_state_handler_->RequestUpdateForNetwork(it->service_path); 446 network_state_handler_->RequestUpdateForNetwork(it->service_path);
404 } 447 }
405 } 448 }
406 449
407 } // namespace chromeos 450 } // 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