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

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

Issue 471183002: Migrate Slot ID of client certs in network configuration. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix ethernet EAP. 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/network_cert_migrator.h" 5 #include "chromeos/network/network_cert_migrator.h"
6 6
7 #include <cert.h> 7 #include <cert.h>
8 #include <string> 8 #include <string>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/location.h" 11 #include "base/location.h"
12 #include "base/metrics/histogram.h" 12 #include "base/metrics/histogram.h"
13 #include "chromeos/dbus/dbus_thread_manager.h" 13 #include "chromeos/dbus/dbus_thread_manager.h"
14 #include "chromeos/dbus/shill_service_client.h" 14 #include "chromeos/dbus/shill_service_client.h"
15 #include "chromeos/network/client_cert_util.h"
15 #include "chromeos/network/network_handler_callbacks.h" 16 #include "chromeos/network/network_handler_callbacks.h"
16 #include "chromeos/network/network_state.h" 17 #include "chromeos/network/network_state.h"
17 #include "chromeos/network/network_state_handler.h" 18 #include "chromeos/network/network_state_handler.h"
18 #include "dbus/object_path.h" 19 #include "dbus/object_path.h"
19 #include "third_party/cros_system_api/dbus/service_constants.h" 20 #include "third_party/cros_system_api/dbus/service_constants.h"
20 21
21 namespace chromeos { 22 namespace chromeos {
22 23
23 namespace { 24 namespace {
24 25
(...skipping 12 matching lines...) Expand all
37 // Hack copied from mozilla: Cut off text before first :, which seems to 38 // Hack copied from mozilla: Cut off text before first :, which seems to
38 // just be the token name. 39 // just be the token name.
39 size_t colon_pos = name.find(':'); 40 size_t colon_pos = name.find(':');
40 if (colon_pos != std::string::npos) 41 if (colon_pos != std::string::npos)
41 name = name.substr(colon_pos + 1); 42 name = name.substr(colon_pos + 1);
42 return name; 43 return name;
43 } 44 }
44 45
45 } // namespace 46 } // namespace
46 47
47 // Checks which of the given |networks| has one of the deprecated 48 // Migrates each network of |networks| with a deprecated CaCertNss property to
48 // CaCertNssProperties set. If such a network already has a CaCertPEM property, 49 // the respective CaCertPEM property and fixes an invalid or missing slot ID of
49 // then the NssProperty is cleared. Otherwise, the NssProperty is compared with 50 // a client certificate configuration.
50 // the nickname of each certificate of |certs|. If a match is found, then the 51 //
51 // CaCertPemProperty is set and the NssProperty is cleared. Otherwise, the 52 // If a network already has a CaCertPEM property, then the NssProperty is
52 // network is not modified. 53 // cleared. Otherwise, the NssProperty is compared with
54 // the nickname of each certificate of |certs|. If a match is found, the
55 // CaCertPemProperty is set and the NssProperty is cleared.
56 //
57 // If a network with a client certificate configuration (i.e. a PKCS11 ID) is
58 // found, the configured client certificate is looked up.
59 // If the certificate is found, the currently configured slot ID (if any) is
60 // compared with the actual slot ID of the certificate and if required updated.
61 // If the certificate is not found, the client certificate configuration is
62 // removed.
63 //
64 // Only if necessary, a network will be notified.
53 class NetworkCertMigrator::MigrationTask 65 class NetworkCertMigrator::MigrationTask
54 : public base::RefCounted<MigrationTask> { 66 : public base::RefCounted<MigrationTask> {
55 public: 67 public:
56 MigrationTask(const net::CertificateList& certs, 68 MigrationTask(const net::CertificateList& certs,
57 const base::WeakPtr<NetworkCertMigrator>& cert_migrator) 69 const base::WeakPtr<NetworkCertMigrator>& cert_migrator)
58 : certs_(certs), 70 : certs_(certs),
59 cert_migrator_(cert_migrator) { 71 cert_migrator_(cert_migrator) {
60 } 72 }
61 73
62 void Run(const NetworkStateHandler::NetworkStateList& networks) { 74 void Run(const NetworkStateHandler::NetworkStateList& networks) {
63 // Request properties for each network that has a CaCertNssProperty set 75 // Request properties for each network that has a CaCertNssProperty set
64 // according to the NetworkStateHandler. 76 // or which could be configured with a client certificate.
65 for (NetworkStateHandler::NetworkStateList::const_iterator it = 77 for (NetworkStateHandler::NetworkStateList::const_iterator it =
66 networks.begin(); it != networks.end(); ++it) { 78 networks.begin(); it != networks.end(); ++it) {
67 if (!(*it)->HasCACertNSS()) 79 if (!(*it)->HasCACertNSS() &&
80 (*it)->security() != shill::kSecurity8021x &&
81 (*it)->type() != shill::kTypeVPN &&
82 (*it)->type() != shill::kTypeEthernetEap) {
68 continue; 83 continue;
84 }
69 const std::string& service_path = (*it)->path(); 85 const std::string& service_path = (*it)->path();
70 DBusThreadManager::Get()->GetShillServiceClient()->GetProperties( 86 DBusThreadManager::Get()->GetShillServiceClient()->GetProperties(
71 dbus::ObjectPath(service_path), 87 dbus::ObjectPath(service_path),
72 base::Bind(&network_handler::GetPropertiesCallback, 88 base::Bind(&network_handler::GetPropertiesCallback,
73 base::Bind(&MigrationTask::MigrateNetwork, this), 89 base::Bind(&MigrationTask::MigrateNetwork, this),
74 network_handler::ErrorCallback(), 90 network_handler::ErrorCallback(),
75 service_path)); 91 service_path));
76 } 92 }
77 } 93 }
78 94
79 void MigrateNetwork(const std::string& service_path, 95 void MigrateNetwork(const std::string& service_path,
80 const base::DictionaryValue& properties) { 96 const base::DictionaryValue& properties) {
81 if (!cert_migrator_) { 97 if (!cert_migrator_) {
82 VLOG(2) << "NetworkCertMigrator already destroyed. Aborting migration."; 98 VLOG(2) << "NetworkCertMigrator already destroyed. Aborting migration.";
83 return; 99 return;
84 } 100 }
85 101
102 base::DictionaryValue new_properties;
103 MigrateClientCertProperties(service_path, properties, &new_properties);
104 MigrateNssProperties(service_path, properties, &new_properties);
105
106 if (new_properties.empty())
107 return;
108 SendPropertiesToShill(service_path, new_properties);
109 }
110
111 void MigrateClientCertProperties(const std::string& service_path,
112 const base::DictionaryValue& properties,
113 base::DictionaryValue* new_properties) {
114 int configured_slot_id = -1;
115 std::string pkcs11_id;
116 chromeos::client_cert::ConfigType config_type =
117 chromeos::client_cert::CONFIG_TYPE_NONE;
118 chromeos::client_cert::GetClientCertFromShillProperties(
119 properties, &config_type, &configured_slot_id, &pkcs11_id);
120 if (config_type == chromeos::client_cert::CONFIG_TYPE_NONE ||
121 pkcs11_id.empty()) {
122 return;
123 }
124
125 // OpenVPN configuration doesn't have a slot id to migrate.
126 if (config_type == chromeos::client_cert::CONFIG_TYPE_OPENVPN)
127 return;
128
129 int real_slot_id = -1;
130 scoped_refptr<net::X509Certificate> cert =
131 FindCertificateWithPkcs11Id(pkcs11_id, &real_slot_id);
132 if (!cert) {
133 LOG(WARNING) << "No matching cert found, removing the certificate "
134 "configuration from network " << service_path;
135 chromeos::client_cert::SetEmptyShillProperties(config_type,
136 new_properties);
137 return;
138 }
139 if (real_slot_id == -1) {
140 LOG(WARNING) << "Found a certificate without slot id.";
141 return;
142 }
143
144 if (cert && real_slot_id != configured_slot_id) {
145 VLOG(1) << "Network " << service_path
146 << " is configured with no or an incorrect slot id.";
147 chromeos::client_cert::SetShillProperties(
148 config_type, real_slot_id, pkcs11_id, new_properties);
149 }
150 }
151
152 void MigrateNssProperties(const std::string& service_path,
153 const base::DictionaryValue& properties,
154 base::DictionaryValue* new_properties) {
86 std::string nss_key, pem_key, nickname; 155 std::string nss_key, pem_key, nickname;
87 const base::ListValue* pem_property = NULL; 156 const base::ListValue* pem_property = NULL;
88 UMANetworkType uma_type = UMA_NETWORK_TYPE_SIZE; 157 UMANetworkType uma_type = UMA_NETWORK_TYPE_SIZE;
89 158
90 GetNssAndPemProperties( 159 GetNssAndPemProperties(
91 properties, &nss_key, &pem_key, &pem_property, &nickname, &uma_type); 160 properties, &nss_key, &pem_key, &pem_property, &nickname, &uma_type);
92 if (nickname.empty()) 161 if (nickname.empty())
93 return; // Didn't find any nickname. 162 return; // Didn't find any nickname.
94 163
95 VLOG(2) << "Found NSS nickname to migrate. Property: " << nss_key 164 VLOG(2) << "Found NSS nickname to migrate. Property: " << nss_key
96 << ", network: " << service_path; 165 << ", network: " << service_path;
97 UMA_HISTOGRAM_ENUMERATION( 166 UMA_HISTOGRAM_ENUMERATION(
98 "Network.MigrationNssToPem", uma_type, UMA_NETWORK_TYPE_SIZE); 167 "Network.MigrationNssToPem", uma_type, UMA_NETWORK_TYPE_SIZE);
99 168
100 if (pem_property && !pem_property->empty()) { 169 if (pem_property && !pem_property->empty()) {
101 VLOG(2) << "PEM already exists, clearing NSS property."; 170 VLOG(2) << "PEM already exists, clearing NSS property.";
102 ClearNssProperty(service_path, nss_key); 171 ClearNssProperty(nss_key, new_properties);
103 return; 172 return;
104 } 173 }
105 174
106 scoped_refptr<net::X509Certificate> cert = 175 scoped_refptr<net::X509Certificate> cert =
107 FindCertificateWithNickname(nickname); 176 FindCertificateWithNickname(nickname);
108 if (!cert) { 177 if (!cert) {
109 VLOG(2) << "No matching cert found."; 178 VLOG(2) << "No matching cert found.";
110 return; 179 return;
111 } 180 }
112 181
113 std::string pem_encoded; 182 std::string pem_encoded;
114 if (!net::X509Certificate::GetPEMEncoded(cert->os_cert_handle(), 183 if (!net::X509Certificate::GetPEMEncoded(cert->os_cert_handle(),
115 &pem_encoded)) { 184 &pem_encoded)) {
116 LOG(ERROR) << "PEM encoding failed."; 185 LOG(ERROR) << "PEM encoding failed.";
117 return; 186 return;
118 } 187 }
119 188
120 SetNssAndPemProperties(service_path, nss_key, pem_key, pem_encoded); 189 ClearNssProperty(nss_key, new_properties);
190 SetPemProperty(pem_key, pem_encoded, new_properties);
121 } 191 }
122 192
123 void GetNssAndPemProperties(const base::DictionaryValue& shill_properties, 193 void GetNssAndPemProperties(const base::DictionaryValue& shill_properties,
124 std::string* nss_key, 194 std::string* nss_key,
125 std::string* pem_key, 195 std::string* pem_key,
126 const base::ListValue** pem_property, 196 const base::ListValue** pem_property,
127 std::string* nickname, 197 std::string* nickname,
128 UMANetworkType* uma_type) { 198 UMANetworkType* uma_type) {
129 struct NssPem { 199 struct NssPem {
130 const char* read_prefix; 200 const char* read_prefix;
(...skipping 21 matching lines...) Expand all
152 if (!nickname->empty()) { 222 if (!nickname->empty()) {
153 *nss_key = kNssPemMap[i].nss_key; 223 *nss_key = kNssPemMap[i].nss_key;
154 *pem_key = kNssPemMap[i].pem_key; 224 *pem_key = kNssPemMap[i].pem_key;
155 *uma_type = kNssPemMap[i].uma_type; 225 *uma_type = kNssPemMap[i].uma_type;
156 dict->GetListWithoutPathExpansion(kNssPemMap[i].pem_key, pem_property); 226 dict->GetListWithoutPathExpansion(kNssPemMap[i].pem_key, pem_property);
157 return; 227 return;
158 } 228 }
159 } 229 }
160 } 230 }
161 231
162 void ClearNssProperty(const std::string& service_path, 232 void ClearNssProperty(const std::string& nss_key,
163 const std::string& nss_key) { 233 base::DictionaryValue* new_properties) {
164 DBusThreadManager::Get()->GetShillServiceClient()->SetProperty( 234 new_properties->SetStringWithoutPathExpansion(nss_key, std::string());
165 dbus::ObjectPath(service_path), 235 }
166 nss_key, 236
167 base::StringValue(std::string()), 237 scoped_refptr<net::X509Certificate> FindCertificateWithPkcs11Id(
168 base::Bind( 238 const std::string& pkcs11_id, int* slot_id) {
169 &MigrationTask::NotifyNetworkStateHandler, this, service_path), 239 *slot_id = -1;
170 base::Bind(&network_handler::ShillErrorCallbackFunction, 240 for (net::CertificateList::iterator it = certs_.begin(); it != certs_.end();
171 "MigrationTask.SetProperty failed", 241 ++it) {
172 service_path, 242 int current_slot_id = -1;
173 network_handler::ErrorCallback())); 243 std::string current_pkcs11_id =
244 CertLoader::GetPkcs11IdAndSlotForCert(**it, &current_slot_id);
245 if (current_pkcs11_id == pkcs11_id) {
246 *slot_id = current_slot_id;
247 return *it;
248 }
249 }
250 return NULL;
174 } 251 }
175 252
176 scoped_refptr<net::X509Certificate> FindCertificateWithNickname( 253 scoped_refptr<net::X509Certificate> FindCertificateWithNickname(
177 const std::string& nickname) { 254 const std::string& nickname) {
178 for (net::CertificateList::iterator it = certs_.begin(); it != certs_.end(); 255 for (net::CertificateList::iterator it = certs_.begin(); it != certs_.end();
179 ++it) { 256 ++it) {
180 if (nickname == GetNickname(**it)) 257 if (nickname == GetNickname(**it))
181 return *it; 258 return *it;
182 } 259 }
183 return NULL; 260 return NULL;
184 } 261 }
185 262
186 void SetNssAndPemProperties(const std::string& service_path, 263 void SetPemProperty(const std::string& pem_key,
187 const std::string& nss_key, 264 const std::string& pem_encoded_cert,
188 const std::string& pem_key, 265 base::DictionaryValue* new_properties) {
189 const std::string& pem_encoded_cert) {
190 base::DictionaryValue new_properties;
191 new_properties.SetStringWithoutPathExpansion(nss_key, std::string());
192 scoped_ptr<base::ListValue> ca_cert_pems(new base::ListValue); 266 scoped_ptr<base::ListValue> ca_cert_pems(new base::ListValue);
193 ca_cert_pems->AppendString(pem_encoded_cert); 267 ca_cert_pems->AppendString(pem_encoded_cert);
194 new_properties.SetWithoutPathExpansion(pem_key, ca_cert_pems.release()); 268 new_properties->SetWithoutPathExpansion(pem_key, ca_cert_pems.release());
269 }
195 270
271 void SendPropertiesToShill(const std::string& service_path,
272 const base::DictionaryValue& properties) {
196 DBusThreadManager::Get()->GetShillServiceClient()->SetProperties( 273 DBusThreadManager::Get()->GetShillServiceClient()->SetProperties(
197 dbus::ObjectPath(service_path), 274 dbus::ObjectPath(service_path),
198 new_properties, 275 properties,
199 base::Bind( 276 base::Bind(
200 &MigrationTask::NotifyNetworkStateHandler, this, service_path), 277 &MigrationTask::NotifyNetworkStateHandler, this, service_path),
201 base::Bind(&MigrationTask::LogErrorAndNotifyNetworkStateHandler, 278 base::Bind(&MigrationTask::LogErrorAndNotifyNetworkStateHandler,
202 this, 279 this,
203 service_path)); 280 service_path));
204 } 281 }
205 282
206 void LogErrorAndNotifyNetworkStateHandler(const std::string& service_path, 283 void LogErrorAndNotifyNetworkStateHandler(const std::string& service_path,
207 const std::string& error_name, 284 const std::string& error_name,
208 const std::string& error_message) { 285 const std::string& error_message) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 328
252 DCHECK(CertLoader::IsInitialized()); 329 DCHECK(CertLoader::IsInitialized());
253 CertLoader::Get()->AddObserver(this); 330 CertLoader::Get()->AddObserver(this);
254 } 331 }
255 332
256 void NetworkCertMigrator::NetworkListChanged() { 333 void NetworkCertMigrator::NetworkListChanged() {
257 if (!CertLoader::Get()->certificates_loaded()) { 334 if (!CertLoader::Get()->certificates_loaded()) {
258 VLOG(2) << "Certs not loaded yet."; 335 VLOG(2) << "Certs not loaded yet.";
259 return; 336 return;
260 } 337 }
261 // Run the migration process from deprecated CaCertNssProperties to CaCertPem. 338 // Run the migration process from deprecated CaCertNssProperties to CaCertPem
262 VLOG(2) << "Start NSS nickname to PEM migration."; 339 // and to fix missing or incorrect slot ids of client certificates.
340 VLOG(2) << "Start certificate migration of network configurations.";
263 scoped_refptr<MigrationTask> helper(new MigrationTask( 341 scoped_refptr<MigrationTask> helper(new MigrationTask(
264 CertLoader::Get()->cert_list(), weak_ptr_factory_.GetWeakPtr())); 342 CertLoader::Get()->cert_list(), weak_ptr_factory_.GetWeakPtr()));
265 NetworkStateHandler::NetworkStateList networks; 343 NetworkStateHandler::NetworkStateList networks;
266 network_state_handler_->GetVisibleNetworkList(&networks); 344 network_state_handler_->GetNetworkListByType(
345 NetworkTypePattern::Default(),
346 true, // only configured networks
347 false, // visible and not visible networks
348 0, // no count limit
349 &networks);
267 helper->Run(networks); 350 helper->Run(networks);
268 } 351 }
269 352
270 void NetworkCertMigrator::OnCertificatesLoaded( 353 void NetworkCertMigrator::OnCertificatesLoaded(
271 const net::CertificateList& cert_list, 354 const net::CertificateList& cert_list,
272 bool initial_load) { 355 bool initial_load) {
273 // Maybe there are networks referring to certs (by NSS nickname) that were not 356 // Maybe there are networks referring to certs that were not loaded before but
274 // loaded before but are now. 357 // are now.
275 NetworkListChanged(); 358 NetworkListChanged();
276 } 359 }
277 360
278 } // namespace chromeos 361 } // namespace chromeos
OLDNEW
« no previous file with comments | « chromeos/network/network_cert_migrator.h ('k') | chromeos/network/network_cert_migrator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698