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

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

Issue 845533002: Remove CACert NSS nickname to PEM migration. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 11 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/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/client_cert_util.h"
16 #include "chromeos/network/network_handler_callbacks.h" 16 #include "chromeos/network/network_handler_callbacks.h"
17 #include "chromeos/network/network_state.h" 17 #include "chromeos/network/network_state.h"
18 #include "chromeos/network/network_state_handler.h" 18 #include "chromeos/network/network_state_handler.h"
19 #include "dbus/object_path.h" 19 #include "dbus/object_path.h"
20 #include "third_party/cros_system_api/dbus/service_constants.h" 20 #include "third_party/cros_system_api/dbus/service_constants.h"
21 21
22 namespace chromeos { 22 namespace chromeos {
23 23
24 namespace { 24 // Migrates each network of |networks| with an invalid or missing slot ID in
25 25 // their client certificate configuration.
26 enum UMANetworkType {
27 UMA_NETWORK_TYPE_EAP,
28 UMA_NETWORK_TYPE_OPENVPN,
29 UMA_NETWORK_TYPE_IPSEC,
30 UMA_NETWORK_TYPE_SIZE,
31 };
32
33 // Copied from x509_certificate_model_nss.cc
34 std::string GetNickname(const net::X509Certificate& cert) {
35 if (!cert.os_cert_handle()->nickname)
36 return std::string();
37 std::string name = cert.os_cert_handle()->nickname;
38 // Hack copied from mozilla: Cut off text before first :, which seems to
39 // just be the token name.
40 size_t colon_pos = name.find(':');
41 if (colon_pos != std::string::npos)
42 name = name.substr(colon_pos + 1);
43 return name;
44 }
45
46 } // namespace
47
48 // Migrates each network of |networks| with a deprecated CaCertNss property to
49 // the respective CaCertPEM property and fixes an invalid or missing slot ID of
50 // a client certificate configuration.
51 //
52 // If a network already has a CaCertPEM property, then the NssProperty is
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 // 26 //
57 // If a network with a client certificate configuration (i.e. a PKCS11 ID) is 27 // If a network with a client certificate configuration (i.e. a PKCS11 ID) is
58 // found, the configured client certificate is looked up. 28 // found, the configured client certificate is looked up.
59 // If the certificate is found, the currently configured slot ID (if any) is 29 // 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. 30 // 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 31 // If the certificate is not found, the client certificate configuration is
62 // removed. 32 // removed.
63 // 33 //
64 // Only if necessary, a network will be notified. 34 // Only if necessary, a network will be notified.
65 class NetworkCertMigrator::MigrationTask 35 class NetworkCertMigrator::MigrationTask
66 : public base::RefCounted<MigrationTask> { 36 : public base::RefCounted<MigrationTask> {
67 public: 37 public:
68 MigrationTask(const net::CertificateList& certs, 38 MigrationTask(const net::CertificateList& certs,
69 const base::WeakPtr<NetworkCertMigrator>& cert_migrator) 39 const base::WeakPtr<NetworkCertMigrator>& cert_migrator)
70 : certs_(certs), 40 : certs_(certs),
71 cert_migrator_(cert_migrator) { 41 cert_migrator_(cert_migrator) {
72 } 42 }
73 43
74 void Run(const NetworkStateHandler::NetworkStateList& networks) { 44 void Run(const NetworkStateHandler::NetworkStateList& networks) {
75 // Request properties for each network that has a CaCertNssProperty set 45 // Request properties for each network that could be configured with a
76 // or which could be configured with a client certificate. 46 // client certificate.
77 for (NetworkStateHandler::NetworkStateList::const_iterator it = 47 for (const NetworkState* network : networks) {
78 networks.begin(); it != networks.end(); ++it) { 48 if (network->security() != shill::kSecurity8021x &&
79 if (!(*it)->HasCACertNSS() && 49 network->type() != shill::kTypeVPN &&
80 (*it)->security() != shill::kSecurity8021x && 50 network->type() != shill::kTypeEthernetEap) {
81 (*it)->type() != shill::kTypeVPN &&
82 (*it)->type() != shill::kTypeEthernetEap) {
83 continue; 51 continue;
84 } 52 }
85 const std::string& service_path = (*it)->path(); 53 const std::string& service_path = network->path();
86 DBusThreadManager::Get()->GetShillServiceClient()->GetProperties( 54 DBusThreadManager::Get()->GetShillServiceClient()->GetProperties(
87 dbus::ObjectPath(service_path), 55 dbus::ObjectPath(service_path),
88 base::Bind(&network_handler::GetPropertiesCallback, 56 base::Bind(&network_handler::GetPropertiesCallback,
89 base::Bind(&MigrationTask::MigrateNetwork, this), 57 base::Bind(&MigrationTask::MigrateNetwork, this),
90 network_handler::ErrorCallback(), 58 network_handler::ErrorCallback(),
91 service_path)); 59 service_path));
92 } 60 }
93 } 61 }
94 62
95 void MigrateNetwork(const std::string& service_path, 63 void MigrateNetwork(const std::string& service_path,
96 const base::DictionaryValue& properties) { 64 const base::DictionaryValue& properties) {
97 if (!cert_migrator_) { 65 if (!cert_migrator_) {
98 VLOG(2) << "NetworkCertMigrator already destroyed. Aborting migration."; 66 VLOG(2) << "NetworkCertMigrator already destroyed. Aborting migration.";
99 return; 67 return;
100 } 68 }
101 69
102 base::DictionaryValue new_properties; 70 base::DictionaryValue new_properties;
103 MigrateClientCertProperties(service_path, properties, &new_properties); 71 MigrateClientCertProperties(service_path, properties, &new_properties);
104 MigrateNssProperties(service_path, properties, &new_properties);
105 72
106 if (new_properties.empty()) 73 if (new_properties.empty())
107 return; 74 return;
108 SendPropertiesToShill(service_path, new_properties); 75 SendPropertiesToShill(service_path, new_properties);
109 } 76 }
110 77
111 void MigrateClientCertProperties(const std::string& service_path, 78 void MigrateClientCertProperties(const std::string& service_path,
112 const base::DictionaryValue& properties, 79 const base::DictionaryValue& properties,
113 base::DictionaryValue* new_properties) { 80 base::DictionaryValue* new_properties) {
114 int configured_slot_id = -1; 81 int configured_slot_id = -1;
(...skipping 27 matching lines...) Expand all
142 } 109 }
143 110
144 if (cert.get() && real_slot_id != configured_slot_id) { 111 if (cert.get() && real_slot_id != configured_slot_id) {
145 VLOG(1) << "Network " << service_path 112 VLOG(1) << "Network " << service_path
146 << " is configured with no or an incorrect slot id."; 113 << " is configured with no or an incorrect slot id.";
147 chromeos::client_cert::SetShillProperties( 114 chromeos::client_cert::SetShillProperties(
148 config_type, real_slot_id, pkcs11_id, new_properties); 115 config_type, real_slot_id, pkcs11_id, new_properties);
149 } 116 }
150 } 117 }
151 118
152 void MigrateNssProperties(const std::string& service_path,
153 const base::DictionaryValue& properties,
154 base::DictionaryValue* new_properties) {
155 std::string nss_key, pem_key, nickname;
156 const base::ListValue* pem_property = NULL;
157 UMANetworkType uma_type = UMA_NETWORK_TYPE_SIZE;
158
159 GetNssAndPemProperties(
160 properties, &nss_key, &pem_key, &pem_property, &nickname, &uma_type);
161 if (nickname.empty())
162 return; // Didn't find any nickname.
163
164 VLOG(2) << "Found NSS nickname to migrate. Property: " << nss_key
165 << ", network: " << service_path;
166 UMA_HISTOGRAM_ENUMERATION(
167 "Network.MigrationNssToPem", uma_type, UMA_NETWORK_TYPE_SIZE);
168
169 if (pem_property && !pem_property->empty()) {
170 VLOG(2) << "PEM already exists, clearing NSS property.";
171 ClearNssProperty(nss_key, new_properties);
172 return;
173 }
174
175 scoped_refptr<net::X509Certificate> cert =
176 FindCertificateWithNickname(nickname);
177 if (!cert.get()) {
178 VLOG(2) << "No matching cert found.";
179 return;
180 }
181
182 std::string pem_encoded;
183 if (!net::X509Certificate::GetPEMEncoded(cert->os_cert_handle(),
184 &pem_encoded)) {
185 LOG(ERROR) << "PEM encoding failed.";
186 return;
187 }
188
189 ClearNssProperty(nss_key, new_properties);
190 SetPemProperty(pem_key, pem_encoded, new_properties);
191 }
192
193 void GetNssAndPemProperties(const base::DictionaryValue& shill_properties,
194 std::string* nss_key,
195 std::string* pem_key,
196 const base::ListValue** pem_property,
197 std::string* nickname,
198 UMANetworkType* uma_type) {
199 struct NssPem {
200 const char* read_prefix;
201 const char* nss_key;
202 const char* pem_key;
203 UMANetworkType uma_type;
204 } const kNssPemMap[] = {
205 { NULL, shill::kEapCaCertNssProperty, shill::kEapCaCertPemProperty,
206 UMA_NETWORK_TYPE_EAP },
207 { shill::kProviderProperty, shill::kL2tpIpsecCaCertNssProperty,
208 shill::kL2tpIpsecCaCertPemProperty, UMA_NETWORK_TYPE_IPSEC },
209 { shill::kProviderProperty, shill::kOpenVPNCaCertNSSProperty,
210 shill::kOpenVPNCaCertPemProperty, UMA_NETWORK_TYPE_OPENVPN },
211 };
212
213 for (size_t i = 0; i < arraysize(kNssPemMap); ++i) {
214 const base::DictionaryValue* dict = &shill_properties;
215 if (kNssPemMap[i].read_prefix) {
216 shill_properties.GetDictionaryWithoutPathExpansion(
217 kNssPemMap[i].read_prefix, &dict);
218 if (!dict)
219 continue;
220 }
221 dict->GetStringWithoutPathExpansion(kNssPemMap[i].nss_key, nickname);
222 if (!nickname->empty()) {
223 *nss_key = kNssPemMap[i].nss_key;
224 *pem_key = kNssPemMap[i].pem_key;
225 *uma_type = kNssPemMap[i].uma_type;
226 dict->GetListWithoutPathExpansion(kNssPemMap[i].pem_key, pem_property);
227 return;
228 }
229 }
230 }
231
232 void ClearNssProperty(const std::string& nss_key,
233 base::DictionaryValue* new_properties) {
234 new_properties->SetStringWithoutPathExpansion(nss_key, std::string());
235 }
236
237 scoped_refptr<net::X509Certificate> FindCertificateWithPkcs11Id( 119 scoped_refptr<net::X509Certificate> FindCertificateWithPkcs11Id(
238 const std::string& pkcs11_id, int* slot_id) { 120 const std::string& pkcs11_id, int* slot_id) {
239 *slot_id = -1; 121 *slot_id = -1;
240 for (net::CertificateList::iterator it = certs_.begin(); it != certs_.end(); 122 for (scoped_refptr<net::X509Certificate> cert : certs_) {
241 ++it) {
242 int current_slot_id = -1; 123 int current_slot_id = -1;
243 std::string current_pkcs11_id = 124 std::string current_pkcs11_id =
244 CertLoader::GetPkcs11IdAndSlotForCert(**it, &current_slot_id); 125 CertLoader::GetPkcs11IdAndSlotForCert(*cert, &current_slot_id);
245 if (current_pkcs11_id == pkcs11_id) { 126 if (current_pkcs11_id == pkcs11_id) {
246 *slot_id = current_slot_id; 127 *slot_id = current_slot_id;
247 return *it; 128 return cert;
248 } 129 }
249 } 130 }
250 return NULL; 131 return nullptr;
251 }
252
253 scoped_refptr<net::X509Certificate> FindCertificateWithNickname(
254 const std::string& nickname) {
255 for (net::CertificateList::iterator it = certs_.begin(); it != certs_.end();
256 ++it) {
257 if (nickname == GetNickname(**it))
258 return *it;
259 }
260 return NULL;
261 }
262
263 void SetPemProperty(const std::string& pem_key,
264 const std::string& pem_encoded_cert,
265 base::DictionaryValue* new_properties) {
266 scoped_ptr<base::ListValue> ca_cert_pems(new base::ListValue);
267 ca_cert_pems->AppendString(pem_encoded_cert);
268 new_properties->SetWithoutPathExpansion(pem_key, ca_cert_pems.release());
269 } 132 }
270 133
271 void SendPropertiesToShill(const std::string& service_path, 134 void SendPropertiesToShill(const std::string& service_path,
272 const base::DictionaryValue& properties) { 135 const base::DictionaryValue& properties) {
273 DBusThreadManager::Get()->GetShillServiceClient()->SetProperties( 136 DBusThreadManager::Get()->GetShillServiceClient()->SetProperties(
274 dbus::ObjectPath(service_path), 137 dbus::ObjectPath(service_path), properties,
275 properties, 138 base::Bind(&base::DoNothing), base::Bind(&LogError, service_path));
276 base::Bind(
277 &MigrationTask::NotifyNetworkStateHandler, this, service_path),
278 base::Bind(&MigrationTask::LogErrorAndNotifyNetworkStateHandler,
279 this,
280 service_path));
281 } 139 }
282 140
283 void LogErrorAndNotifyNetworkStateHandler(const std::string& service_path, 141 static void LogError(const std::string& service_path,
284 const std::string& error_name, 142 const std::string& error_name,
285 const std::string& error_message) { 143 const std::string& error_message) {
286 network_handler::ShillErrorCallbackFunction( 144 network_handler::ShillErrorCallbackFunction(
287 "MigrationTask.SetProperties failed", 145 "MigrationTask.SetProperties failed",
288 service_path, 146 service_path,
289 network_handler::ErrorCallback(), 147 network_handler::ErrorCallback(),
290 error_name, 148 error_name,
291 error_message); 149 error_message);
292 NotifyNetworkStateHandler(service_path);
293 }
294
295 void NotifyNetworkStateHandler(const std::string& service_path) {
296 if (!cert_migrator_) {
297 VLOG(2) << "NetworkCertMigrator already destroyed. Aborting migration.";
298 return;
299 }
300 cert_migrator_->network_state_handler_->RequestUpdateForNetwork(
301 service_path);
302 } 150 }
303 151
304 private: 152 private:
305 friend class base::RefCounted<MigrationTask>; 153 friend class base::RefCounted<MigrationTask>;
306 virtual ~MigrationTask() { 154 virtual ~MigrationTask() {
307 } 155 }
308 156
309 net::CertificateList certs_; 157 net::CertificateList certs_;
310 base::WeakPtr<NetworkCertMigrator> cert_migrator_; 158 base::WeakPtr<NetworkCertMigrator> cert_migrator_;
311 }; 159 };
312 160
313 NetworkCertMigrator::NetworkCertMigrator() 161 NetworkCertMigrator::NetworkCertMigrator()
314 : network_state_handler_(NULL), 162 : network_state_handler_(nullptr),
315 weak_ptr_factory_(this) { 163 weak_ptr_factory_(this) {
316 } 164 }
317 165
318 NetworkCertMigrator::~NetworkCertMigrator() { 166 NetworkCertMigrator::~NetworkCertMigrator() {
319 network_state_handler_->RemoveObserver(this, FROM_HERE); 167 network_state_handler_->RemoveObserver(this, FROM_HERE);
320 if (CertLoader::IsInitialized()) 168 if (CertLoader::IsInitialized())
321 CertLoader::Get()->RemoveObserver(this); 169 CertLoader::Get()->RemoveObserver(this);
322 } 170 }
323 171
324 void NetworkCertMigrator::Init(NetworkStateHandler* network_state_handler) { 172 void NetworkCertMigrator::Init(NetworkStateHandler* network_state_handler) {
325 DCHECK(network_state_handler); 173 DCHECK(network_state_handler);
326 network_state_handler_ = network_state_handler; 174 network_state_handler_ = network_state_handler;
327 network_state_handler_->AddObserver(this, FROM_HERE); 175 network_state_handler_->AddObserver(this, FROM_HERE);
328 176
329 DCHECK(CertLoader::IsInitialized()); 177 DCHECK(CertLoader::IsInitialized());
330 CertLoader::Get()->AddObserver(this); 178 CertLoader::Get()->AddObserver(this);
331 } 179 }
332 180
333 void NetworkCertMigrator::NetworkListChanged() { 181 void NetworkCertMigrator::NetworkListChanged() {
334 if (!CertLoader::Get()->certificates_loaded()) { 182 if (!CertLoader::Get()->certificates_loaded()) {
335 VLOG(2) << "Certs not loaded yet."; 183 VLOG(2) << "Certs not loaded yet.";
336 return; 184 return;
337 } 185 }
338 // Run the migration process from deprecated CaCertNssProperties to CaCertPem 186 // Run the migration process to fix missing or incorrect slot ids of client
339 // and to fix missing or incorrect slot ids of client certificates. 187 // certificates.
340 VLOG(2) << "Start certificate migration of network configurations."; 188 VLOG(2) << "Start certificate migration of network configurations.";
341 scoped_refptr<MigrationTask> helper(new MigrationTask( 189 scoped_refptr<MigrationTask> helper(new MigrationTask(
342 CertLoader::Get()->cert_list(), weak_ptr_factory_.GetWeakPtr())); 190 CertLoader::Get()->cert_list(), weak_ptr_factory_.GetWeakPtr()));
343 NetworkStateHandler::NetworkStateList networks; 191 NetworkStateHandler::NetworkStateList networks;
344 network_state_handler_->GetNetworkListByType( 192 network_state_handler_->GetNetworkListByType(
345 NetworkTypePattern::Default(), 193 NetworkTypePattern::Default(),
346 true, // only configured networks 194 true, // only configured networks
347 false, // visible and not visible networks 195 false, // visible and not visible networks
348 0, // no count limit 196 0, // no count limit
349 &networks); 197 &networks);
350 helper->Run(networks); 198 helper->Run(networks);
351 } 199 }
352 200
353 void NetworkCertMigrator::OnCertificatesLoaded( 201 void NetworkCertMigrator::OnCertificatesLoaded(
354 const net::CertificateList& cert_list, 202 const net::CertificateList& cert_list,
355 bool initial_load) { 203 bool initial_load) {
356 // Maybe there are networks referring to certs that were not loaded before but 204 if (initial_load)
357 // are now. 205 NetworkListChanged();
358 NetworkListChanged();
359 } 206 }
360 207
361 } // namespace chromeos 208 } // 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