Chromium Code Reviews| 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 |