OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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, ¤t_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 Loading... | |
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 |
OLD | NEW |