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

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: 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 29 matching lines...) Expand all
54 : public base::RefCounted<MigrationTask> { 55 : public base::RefCounted<MigrationTask> {
55 public: 56 public:
56 MigrationTask(const net::CertificateList& certs, 57 MigrationTask(const net::CertificateList& certs,
57 const base::WeakPtr<NetworkCertMigrator>& cert_migrator) 58 const base::WeakPtr<NetworkCertMigrator>& cert_migrator)
58 : certs_(certs), 59 : certs_(certs),
59 cert_migrator_(cert_migrator) { 60 cert_migrator_(cert_migrator) {
60 } 61 }
61 62
62 void Run(const NetworkStateHandler::NetworkStateList& networks) { 63 void Run(const NetworkStateHandler::NetworkStateList& networks) {
63 // Request properties for each network that has a CaCertNssProperty set 64 // Request properties for each network that has a CaCertNssProperty set
64 // according to the NetworkStateHandler. 65 // or which could be configured with a client certificate.
65 for (NetworkStateHandler::NetworkStateList::const_iterator it = 66 for (NetworkStateHandler::NetworkStateList::const_iterator it =
66 networks.begin(); it != networks.end(); ++it) { 67 networks.begin(); it != networks.end(); ++it) {
67 if (!(*it)->HasCACertNSS()) 68 if (!(*it)->HasCACertNSS() &&
69 (*it)->security() != shill::kSecurity8021x &&
70 (*it)->type() != shill::kTypeVPN) {
Paul Stewart 2014/08/14 20:09:17 This is another place where you are opting out of
pneubeck (no reviews) 2014/08/14 23:06:00 Right, that one is ignored so far. I'll add the co
pneubeck (no reviews) 2014/08/15 13:15:21 Done.
68 continue; 71 continue;
72 }
69 const std::string& service_path = (*it)->path(); 73 const std::string& service_path = (*it)->path();
70 DBusThreadManager::Get()->GetShillServiceClient()->GetProperties( 74 DBusThreadManager::Get()->GetShillServiceClient()->GetProperties(
71 dbus::ObjectPath(service_path), 75 dbus::ObjectPath(service_path),
72 base::Bind(&network_handler::GetPropertiesCallback, 76 base::Bind(&network_handler::GetPropertiesCallback,
73 base::Bind(&MigrationTask::MigrateNetwork, this), 77 base::Bind(&MigrationTask::MigrateNetwork, this),
74 network_handler::ErrorCallback(), 78 network_handler::ErrorCallback(),
75 service_path)); 79 service_path));
76 } 80 }
77 } 81 }
78 82
79 void MigrateNetwork(const std::string& service_path, 83 void MigrateNetwork(const std::string& service_path,
80 const base::DictionaryValue& properties) { 84 const base::DictionaryValue& properties) {
81 if (!cert_migrator_) { 85 if (!cert_migrator_) {
82 VLOG(2) << "NetworkCertMigrator already destroyed. Aborting migration."; 86 VLOG(2) << "NetworkCertMigrator already destroyed. Aborting migration.";
83 return; 87 return;
84 } 88 }
85 89
90 base::DictionaryValue new_properties;
91 MigrateClientCertProperties(service_path, properties, &new_properties);
92 MigrateNssProperties(service_path, properties, &new_properties);
93
94 if (new_properties.empty())
95 return;
96 SendPropertiesToShill(service_path, new_properties);
97 }
98
99 void MigrateClientCertProperties(const std::string& service_path,
100 const base::DictionaryValue& properties,
101 base::DictionaryValue* new_properties) {
102 int configured_slot_id = -1;
103 std::string pkcs11_id;
104 chromeos::client_cert::ConfigType config_type =
105 chromeos::client_cert::CONFIG_TYPE_NONE;
106 chromeos::client_cert::GetShillProperties(
107 properties, &config_type, &configured_slot_id, &pkcs11_id);
108 if (config_type == chromeos::client_cert::CONFIG_TYPE_NONE ||
109 pkcs11_id.empty()) {
110 return;
111 }
112
113 // OpenVPN configuration doesn't have a slot id to migrate.
114 if (config_type == chromeos::client_cert::CONFIG_TYPE_OPENVPN)
115 return;
116
117 int real_slot_id = -1;
118 scoped_refptr<net::X509Certificate> cert =
119 FindCertificateWithPkcs11Id(pkcs11_id, &real_slot_id);
120 if (!cert) {
121 LOG(WARNING) << "No matching cert found, removing the certificate "
122 "configuration from network " << service_path;
123 chromeos::client_cert::SetEmptyShillProperties(config_type,
124 new_properties);
125 } else if (real_slot_id == -1) {
126 VLOG(1) << "Found a certificate without slot id.";
127 return;
128 }
129
130 if (cert && real_slot_id != configured_slot_id) {
131 VLOG(1) << "Network " << service_path
132 << " is configured with no or an incorrect slot id.";
133 chromeos::client_cert::SetShillProperties(
134 config_type, real_slot_id, pkcs11_id, new_properties);
135 }
136 }
137
138 void MigrateNssProperties(const std::string& service_path,
139 const base::DictionaryValue& properties,
140 base::DictionaryValue* new_properties) {
86 std::string nss_key, pem_key, nickname; 141 std::string nss_key, pem_key, nickname;
87 const base::ListValue* pem_property = NULL; 142 const base::ListValue* pem_property = NULL;
88 UMANetworkType uma_type = UMA_NETWORK_TYPE_SIZE; 143 UMANetworkType uma_type = UMA_NETWORK_TYPE_SIZE;
89 144
90 GetNssAndPemProperties( 145 GetNssAndPemProperties(
91 properties, &nss_key, &pem_key, &pem_property, &nickname, &uma_type); 146 properties, &nss_key, &pem_key, &pem_property, &nickname, &uma_type);
92 if (nickname.empty()) 147 if (nickname.empty())
93 return; // Didn't find any nickname. 148 return; // Didn't find any nickname.
94 149
95 VLOG(2) << "Found NSS nickname to migrate. Property: " << nss_key 150 VLOG(2) << "Found NSS nickname to migrate. Property: " << nss_key
96 << ", network: " << service_path; 151 << ", network: " << service_path;
97 UMA_HISTOGRAM_ENUMERATION( 152 UMA_HISTOGRAM_ENUMERATION(
98 "Network.MigrationNssToPem", uma_type, UMA_NETWORK_TYPE_SIZE); 153 "Network.MigrationNssToPem", uma_type, UMA_NETWORK_TYPE_SIZE);
99 154
100 if (pem_property && !pem_property->empty()) { 155 if (pem_property && !pem_property->empty()) {
101 VLOG(2) << "PEM already exists, clearing NSS property."; 156 VLOG(2) << "PEM already exists, clearing NSS property.";
102 ClearNssProperty(service_path, nss_key); 157 ClearNssProperty(nss_key, new_properties);
103 return; 158 return;
104 } 159 }
105 160
106 scoped_refptr<net::X509Certificate> cert = 161 scoped_refptr<net::X509Certificate> cert =
107 FindCertificateWithNickname(nickname); 162 FindCertificateWithNickname(nickname);
108 if (!cert) { 163 if (!cert) {
109 VLOG(2) << "No matching cert found."; 164 VLOG(2) << "No matching cert found.";
110 return; 165 return;
111 } 166 }
112 167
113 std::string pem_encoded; 168 std::string pem_encoded;
114 if (!net::X509Certificate::GetPEMEncoded(cert->os_cert_handle(), 169 if (!net::X509Certificate::GetPEMEncoded(cert->os_cert_handle(),
115 &pem_encoded)) { 170 &pem_encoded)) {
116 LOG(ERROR) << "PEM encoding failed."; 171 LOG(ERROR) << "PEM encoding failed.";
117 return; 172 return;
118 } 173 }
119 174
120 SetNssAndPemProperties(service_path, nss_key, pem_key, pem_encoded); 175 ClearNssProperty(nss_key, new_properties);
176 SetPemProperty(pem_key, pem_encoded, new_properties);
121 } 177 }
122 178
123 void GetNssAndPemProperties(const base::DictionaryValue& shill_properties, 179 void GetNssAndPemProperties(const base::DictionaryValue& shill_properties,
124 std::string* nss_key, 180 std::string* nss_key,
125 std::string* pem_key, 181 std::string* pem_key,
126 const base::ListValue** pem_property, 182 const base::ListValue** pem_property,
127 std::string* nickname, 183 std::string* nickname,
128 UMANetworkType* uma_type) { 184 UMANetworkType* uma_type) {
129 struct NssPem { 185 struct NssPem {
130 const char* read_prefix; 186 const char* read_prefix;
(...skipping 21 matching lines...) Expand all
152 if (!nickname->empty()) { 208 if (!nickname->empty()) {
153 *nss_key = kNssPemMap[i].nss_key; 209 *nss_key = kNssPemMap[i].nss_key;
154 *pem_key = kNssPemMap[i].pem_key; 210 *pem_key = kNssPemMap[i].pem_key;
155 *uma_type = kNssPemMap[i].uma_type; 211 *uma_type = kNssPemMap[i].uma_type;
156 dict->GetListWithoutPathExpansion(kNssPemMap[i].pem_key, pem_property); 212 dict->GetListWithoutPathExpansion(kNssPemMap[i].pem_key, pem_property);
157 return; 213 return;
158 } 214 }
159 } 215 }
160 } 216 }
161 217
162 void ClearNssProperty(const std::string& service_path, 218 void ClearNssProperty(const std::string& nss_key,
163 const std::string& nss_key) { 219 base::DictionaryValue* new_properties) {
164 DBusThreadManager::Get()->GetShillServiceClient()->SetProperty( 220 new_properties->SetStringWithoutPathExpansion(nss_key, std::string());
165 dbus::ObjectPath(service_path), 221 }
166 nss_key, 222
167 base::StringValue(std::string()), 223 scoped_refptr<net::X509Certificate> FindCertificateWithPkcs11Id(
168 base::Bind( 224 const std::string& pkcs11_id, int* slot_id) {
169 &MigrationTask::NotifyNetworkStateHandler, this, service_path), 225 *slot_id = -1;
170 base::Bind(&network_handler::ShillErrorCallbackFunction, 226 for (net::CertificateList::iterator it = certs_.begin(); it != certs_.end();
171 "MigrationTask.SetProperty failed", 227 ++it) {
172 service_path, 228 int current_slot_id = -1;
173 network_handler::ErrorCallback())); 229 std::string current_pkcs11_id =
230 CertLoader::GetPkcs11IdAndSlotForCert(**it, &current_slot_id);
231 if (current_pkcs11_id == pkcs11_id) {
232 *slot_id = current_slot_id;
233 return *it;
234 }
235 }
236 return NULL;
174 } 237 }
175 238
176 scoped_refptr<net::X509Certificate> FindCertificateWithNickname( 239 scoped_refptr<net::X509Certificate> FindCertificateWithNickname(
177 const std::string& nickname) { 240 const std::string& nickname) {
178 for (net::CertificateList::iterator it = certs_.begin(); it != certs_.end(); 241 for (net::CertificateList::iterator it = certs_.begin(); it != certs_.end();
179 ++it) { 242 ++it) {
180 if (nickname == GetNickname(**it)) 243 if (nickname == GetNickname(**it))
181 return *it; 244 return *it;
182 } 245 }
183 return NULL; 246 return NULL;
184 } 247 }
185 248 void SetPemProperty(const std::string& pem_key,
186 void SetNssAndPemProperties(const std::string& service_path, 249 const std::string& pem_encoded_cert,
187 const std::string& nss_key, 250 base::DictionaryValue* new_properties) {
188 const std::string& pem_key,
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); 251 scoped_ptr<base::ListValue> ca_cert_pems(new base::ListValue);
193 ca_cert_pems->AppendString(pem_encoded_cert); 252 ca_cert_pems->AppendString(pem_encoded_cert);
194 new_properties.SetWithoutPathExpansion(pem_key, ca_cert_pems.release()); 253 new_properties->SetWithoutPathExpansion(pem_key, ca_cert_pems.release());
254 }
195 255
256 void SendPropertiesToShill(const std::string& service_path,
257 const base::DictionaryValue& properties) {
196 DBusThreadManager::Get()->GetShillServiceClient()->SetProperties( 258 DBusThreadManager::Get()->GetShillServiceClient()->SetProperties(
197 dbus::ObjectPath(service_path), 259 dbus::ObjectPath(service_path),
198 new_properties, 260 properties,
199 base::Bind( 261 base::Bind(
200 &MigrationTask::NotifyNetworkStateHandler, this, service_path), 262 &MigrationTask::NotifyNetworkStateHandler, this, service_path),
201 base::Bind(&MigrationTask::LogErrorAndNotifyNetworkStateHandler, 263 base::Bind(&MigrationTask::LogErrorAndNotifyNetworkStateHandler,
202 this, 264 this,
203 service_path)); 265 service_path));
204 } 266 }
205 267
206 void LogErrorAndNotifyNetworkStateHandler(const std::string& service_path, 268 void LogErrorAndNotifyNetworkStateHandler(const std::string& service_path,
207 const std::string& error_name, 269 const std::string& error_name,
208 const std::string& error_message) { 270 const std::string& error_message) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 313
252 DCHECK(CertLoader::IsInitialized()); 314 DCHECK(CertLoader::IsInitialized());
253 CertLoader::Get()->AddObserver(this); 315 CertLoader::Get()->AddObserver(this);
254 } 316 }
255 317
256 void NetworkCertMigrator::NetworkListChanged() { 318 void NetworkCertMigrator::NetworkListChanged() {
257 if (!CertLoader::Get()->certificates_loaded()) { 319 if (!CertLoader::Get()->certificates_loaded()) {
258 VLOG(2) << "Certs not loaded yet."; 320 VLOG(2) << "Certs not loaded yet.";
259 return; 321 return;
260 } 322 }
261 // Run the migration process from deprecated CaCertNssProperties to CaCertPem. 323 // Run the migration process from deprecated CaCertNssProperties to CaCertPem
262 VLOG(2) << "Start NSS nickname to PEM migration."; 324 // and to fix missing or incorrect slot ids of client certificates.
325 VLOG(2) << "Start certificate migration of network configurations.";
263 scoped_refptr<MigrationTask> helper(new MigrationTask( 326 scoped_refptr<MigrationTask> helper(new MigrationTask(
264 CertLoader::Get()->cert_list(), weak_ptr_factory_.GetWeakPtr())); 327 CertLoader::Get()->cert_list(), weak_ptr_factory_.GetWeakPtr()));
265 NetworkStateHandler::NetworkStateList networks; 328 NetworkStateHandler::NetworkStateList networks;
266 network_state_handler_->GetVisibleNetworkList(&networks); 329 network_state_handler_->GetVisibleNetworkList(&networks);
267 helper->Run(networks); 330 helper->Run(networks);
268 } 331 }
269 332
270 void NetworkCertMigrator::OnCertificatesLoaded( 333 void NetworkCertMigrator::OnCertificatesLoaded(
271 const net::CertificateList& cert_list, 334 const net::CertificateList& cert_list,
272 bool initial_load) { 335 bool initial_load) {
273 // Maybe there are networks referring to certs (by NSS nickname) that were not 336 // Maybe there are networks referring to certs that were not loaded before but
274 // loaded before but are now. 337 // are now.
275 NetworkListChanged(); 338 NetworkListChanged();
276 } 339 }
277 340
278 } // namespace chromeos 341 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698