13240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved. 23240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 33240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// found in the LICENSE file. 43240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 53240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "chromeos/network/network_cert_migrator.h" 63240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 73240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include <cert.h> 83240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include <string> 93240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/bind.h" 113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "base/location.h" 123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "base/metrics/histogram.h" 133240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "chromeos/dbus/dbus_thread_manager.h" 143240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "chromeos/dbus/shill_service_client.h" 1503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chromeos/network/client_cert_util.h" 163240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "chromeos/network/network_handler_callbacks.h" 173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "chromeos/network/network_state.h" 183240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "chromeos/network/network_state_handler.h" 193240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "dbus/object_path.h" 203240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "third_party/cros_system_api/dbus/service_constants.h" 213240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 223240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochnamespace chromeos { 233240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 243240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochnamespace { 253240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 263240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochenum UMANetworkType { 273240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch UMA_NETWORK_TYPE_EAP, 283240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch UMA_NETWORK_TYPE_OPENVPN, 293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch UMA_NETWORK_TYPE_IPSEC, 303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch UMA_NETWORK_TYPE_SIZE, 313240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}; 323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// Copied from x509_certificate_model_nss.cc 343240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochstd::string GetNickname(const net::X509Certificate& cert) { 353240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (!cert.os_cert_handle()->nickname) 363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return std::string(); 373240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch std::string name = cert.os_cert_handle()->nickname; 383240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // Hack copied from mozilla: Cut off text before first :, which seems to 393240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // just be the token name. 403240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch size_t colon_pos = name.find(':'); 413240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (colon_pos != std::string::npos) 423240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch name = name.substr(colon_pos + 1); 433240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return name; 443240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch} 453240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 463240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch} // namespace 473240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Migrates each network of |networks| with a deprecated CaCertNss property to 4903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// the respective CaCertPEM property and fixes an invalid or missing slot ID of 5003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// a client certificate configuration. 5103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// 5203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// If a network already has a CaCertPEM property, then the NssProperty is 5303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// cleared. Otherwise, the NssProperty is compared with 5403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// the nickname of each certificate of |certs|. If a match is found, the 5503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// CaCertPemProperty is set and the NssProperty is cleared. 5603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// 5703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// If a network with a client certificate configuration (i.e. a PKCS11 ID) is 5803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// found, the configured client certificate is looked up. 5903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// If the certificate is found, the currently configured slot ID (if any) is 6003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// compared with the actual slot ID of the certificate and if required updated. 6103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// If the certificate is not found, the client certificate configuration is 6203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// removed. 6303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// 6403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Only if necessary, a network will be notified. 653240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochclass NetworkCertMigrator::MigrationTask 663240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch : public base::RefCounted<MigrationTask> { 673240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch public: 683240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch MigrationTask(const net::CertificateList& certs, 693240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch const base::WeakPtr<NetworkCertMigrator>& cert_migrator) 703240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch : certs_(certs), 713240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch cert_migrator_(cert_migrator) { 723240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 733240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 743240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch void Run(const NetworkStateHandler::NetworkStateList& networks) { 753240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // Request properties for each network that has a CaCertNssProperty set 7603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // or which could be configured with a client certificate. 773240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch for (NetworkStateHandler::NetworkStateList::const_iterator it = 783240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch networks.begin(); it != networks.end(); ++it) { 7903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!(*it)->HasCACertNSS() && 8003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) (*it)->security() != shill::kSecurity8021x && 8103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) (*it)->type() != shill::kTypeVPN && 8203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) (*it)->type() != shill::kTypeEthernetEap) { 833240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch continue; 8403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 853240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch const std::string& service_path = (*it)->path(); 863240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch DBusThreadManager::Get()->GetShillServiceClient()->GetProperties( 873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch dbus::ObjectPath(service_path), 883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch base::Bind(&network_handler::GetPropertiesCallback, 893240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch base::Bind(&MigrationTask::MigrateNetwork, this), 903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch network_handler::ErrorCallback(), 913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch service_path)); 923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 933240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 943240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 953240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch void MigrateNetwork(const std::string& service_path, 963240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch const base::DictionaryValue& properties) { 973240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (!cert_migrator_) { 983240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch VLOG(2) << "NetworkCertMigrator already destroyed. Aborting migration."; 993240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return; 1003240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 1013240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 10203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::DictionaryValue new_properties; 10303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) MigrateClientCertProperties(service_path, properties, &new_properties); 10403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) MigrateNssProperties(service_path, properties, &new_properties); 10503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 10603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (new_properties.empty()) 10703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 10803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) SendPropertiesToShill(service_path, new_properties); 10903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 11003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 11103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) void MigrateClientCertProperties(const std::string& service_path, 11203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const base::DictionaryValue& properties, 11303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::DictionaryValue* new_properties) { 11403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int configured_slot_id = -1; 11503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::string pkcs11_id; 11603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) chromeos::client_cert::ConfigType config_type = 11703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) chromeos::client_cert::CONFIG_TYPE_NONE; 11803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) chromeos::client_cert::GetClientCertFromShillProperties( 11903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) properties, &config_type, &configured_slot_id, &pkcs11_id); 12003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (config_type == chromeos::client_cert::CONFIG_TYPE_NONE || 12103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) pkcs11_id.empty()) { 12203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 12303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 12403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 12503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // OpenVPN configuration doesn't have a slot id to migrate. 12603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (config_type == chromeos::client_cert::CONFIG_TYPE_OPENVPN) 12703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 12803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 12903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int real_slot_id = -1; 13003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_refptr<net::X509Certificate> cert = 13103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) FindCertificateWithPkcs11Id(pkcs11_id, &real_slot_id); 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!cert.get()) { 13303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LOG(WARNING) << "No matching cert found, removing the certificate " 13403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) "configuration from network " << service_path; 13503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) chromeos::client_cert::SetEmptyShillProperties(config_type, 13603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) new_properties); 13703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 13803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 13903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (real_slot_id == -1) { 14003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) LOG(WARNING) << "Found a certificate without slot id."; 14103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 14203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 14303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (cert.get() && real_slot_id != configured_slot_id) { 14503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) VLOG(1) << "Network " << service_path 14603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) << " is configured with no or an incorrect slot id."; 14703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) chromeos::client_cert::SetShillProperties( 14803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) config_type, real_slot_id, pkcs11_id, new_properties); 14903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 15003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 15103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 15203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) void MigrateNssProperties(const std::string& service_path, 15303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const base::DictionaryValue& properties, 15403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::DictionaryValue* new_properties) { 1553240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch std::string nss_key, pem_key, nickname; 1563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch const base::ListValue* pem_property = NULL; 1573240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch UMANetworkType uma_type = UMA_NETWORK_TYPE_SIZE; 1583240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 1593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch GetNssAndPemProperties( 1603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch properties, &nss_key, &pem_key, &pem_property, &nickname, &uma_type); 1613240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (nickname.empty()) 1623240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return; // Didn't find any nickname. 1633240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 1643240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch VLOG(2) << "Found NSS nickname to migrate. Property: " << nss_key 1653240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch << ", network: " << service_path; 1663240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch UMA_HISTOGRAM_ENUMERATION( 1673240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch "Network.MigrationNssToPem", uma_type, UMA_NETWORK_TYPE_SIZE); 1683240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 1693240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (pem_property && !pem_property->empty()) { 1703240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch VLOG(2) << "PEM already exists, clearing NSS property."; 17103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ClearNssProperty(nss_key, new_properties); 1723240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return; 1733240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 1743240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 1753240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch scoped_refptr<net::X509Certificate> cert = 1763240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch FindCertificateWithNickname(nickname); 1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!cert.get()) { 1783240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch VLOG(2) << "No matching cert found."; 1793240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return; 1803240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 1813240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 1823240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch std::string pem_encoded; 1833240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (!net::X509Certificate::GetPEMEncoded(cert->os_cert_handle(), 1843240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch &pem_encoded)) { 1853240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch LOG(ERROR) << "PEM encoding failed."; 1863240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return; 1873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 1883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 18903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ClearNssProperty(nss_key, new_properties); 19003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) SetPemProperty(pem_key, pem_encoded, new_properties); 1913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 1923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 1933240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch void GetNssAndPemProperties(const base::DictionaryValue& shill_properties, 1943240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch std::string* nss_key, 1953240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch std::string* pem_key, 1963240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch const base::ListValue** pem_property, 1973240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch std::string* nickname, 1983240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch UMANetworkType* uma_type) { 1993240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch struct NssPem { 2003240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch const char* read_prefix; 2013240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch const char* nss_key; 2023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch const char* pem_key; 2033240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch UMANetworkType uma_type; 2043240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } const kNssPemMap[] = { 20568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) { NULL, shill::kEapCaCertNssProperty, shill::kEapCaCertPemProperty, 2063240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch UMA_NETWORK_TYPE_EAP }, 20768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) { shill::kProviderProperty, shill::kL2tpIpsecCaCertNssProperty, 2083240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch shill::kL2tpIpsecCaCertPemProperty, UMA_NETWORK_TYPE_IPSEC }, 20968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) { shill::kProviderProperty, shill::kOpenVPNCaCertNSSProperty, 2103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch shill::kOpenVPNCaCertPemProperty, UMA_NETWORK_TYPE_OPENVPN }, 2113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch }; 2123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 2133240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kNssPemMap); ++i) { 2143240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch const base::DictionaryValue* dict = &shill_properties; 2153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (kNssPemMap[i].read_prefix) { 2163240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch shill_properties.GetDictionaryWithoutPathExpansion( 2173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch kNssPemMap[i].read_prefix, &dict); 2183240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (!dict) 2193240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch continue; 2203240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 2213240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch dict->GetStringWithoutPathExpansion(kNssPemMap[i].nss_key, nickname); 2223240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (!nickname->empty()) { 2233240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch *nss_key = kNssPemMap[i].nss_key; 2243240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch *pem_key = kNssPemMap[i].pem_key; 2253240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch *uma_type = kNssPemMap[i].uma_type; 2263240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch dict->GetListWithoutPathExpansion(kNssPemMap[i].pem_key, pem_property); 2273240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return; 2283240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 2293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 2303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 2313240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 23203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) void ClearNssProperty(const std::string& nss_key, 23303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::DictionaryValue* new_properties) { 23403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) new_properties->SetStringWithoutPathExpansion(nss_key, std::string()); 23503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 23603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 23703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) scoped_refptr<net::X509Certificate> FindCertificateWithPkcs11Id( 23803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const std::string& pkcs11_id, int* slot_id) { 23903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) *slot_id = -1; 24003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) for (net::CertificateList::iterator it = certs_.begin(); it != certs_.end(); 24103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ++it) { 24203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int current_slot_id = -1; 24303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::string current_pkcs11_id = 24403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) CertLoader::GetPkcs11IdAndSlotForCert(**it, ¤t_slot_id); 24503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (current_pkcs11_id == pkcs11_id) { 24603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) *slot_id = current_slot_id; 24703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return *it; 24803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 24903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 25003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return NULL; 2513240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 2523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 2533240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch scoped_refptr<net::X509Certificate> FindCertificateWithNickname( 2543240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch const std::string& nickname) { 2553240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch for (net::CertificateList::iterator it = certs_.begin(); it != certs_.end(); 2563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch ++it) { 2573240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (nickname == GetNickname(**it)) 2583240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return *it; 2593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 2603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return NULL; 2613240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 2623240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 26303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) void SetPemProperty(const std::string& pem_key, 26403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const std::string& pem_encoded_cert, 26503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::DictionaryValue* new_properties) { 2663240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch scoped_ptr<base::ListValue> ca_cert_pems(new base::ListValue); 2673240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch ca_cert_pems->AppendString(pem_encoded_cert); 26803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) new_properties->SetWithoutPathExpansion(pem_key, ca_cert_pems.release()); 26903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 2703240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 27103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) void SendPropertiesToShill(const std::string& service_path, 27203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const base::DictionaryValue& properties) { 2733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DBusThreadManager::Get()->GetShillServiceClient()->SetProperties( 2743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) dbus::ObjectPath(service_path), 27503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) properties, 2763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::Bind( 2773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) &MigrationTask::NotifyNetworkStateHandler, this, service_path), 2783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::Bind(&MigrationTask::LogErrorAndNotifyNetworkStateHandler, 2793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) this, 2803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) service_path)); 2813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 2823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) void LogErrorAndNotifyNetworkStateHandler(const std::string& service_path, 2843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& error_name, 2853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& error_message) { 2863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) network_handler::ShillErrorCallbackFunction( 2873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "MigrationTask.SetProperties failed", 2883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) service_path, 2893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) network_handler::ErrorCallback(), 2903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) error_name, 2913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) error_message); 2923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) NotifyNetworkStateHandler(service_path); 2933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 2943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) void NotifyNetworkStateHandler(const std::string& service_path) { 2963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!cert_migrator_) { 2973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) VLOG(2) << "NetworkCertMigrator already destroyed. Aborting migration."; 2983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return; 2993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 3003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) cert_migrator_->network_state_handler_->RequestUpdateForNetwork( 3013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) service_path); 3023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 3033240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 3043240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch private: 3053240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch friend class base::RefCounted<MigrationTask>; 3063240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch virtual ~MigrationTask() { 3073240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 3083240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 3093240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch net::CertificateList certs_; 3103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch base::WeakPtr<NetworkCertMigrator> cert_migrator_; 3113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}; 3123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 3133240926e260ce088908e02ac07a6cf7b0c0cbf44Ben MurdochNetworkCertMigrator::NetworkCertMigrator() 3143240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch : network_state_handler_(NULL), 3153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch weak_ptr_factory_(this) { 3163240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch} 3173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 3183240926e260ce088908e02ac07a6cf7b0c0cbf44Ben MurdochNetworkCertMigrator::~NetworkCertMigrator() { 3193240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch network_state_handler_->RemoveObserver(this, FROM_HERE); 3203240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (CertLoader::IsInitialized()) 3213240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch CertLoader::Get()->RemoveObserver(this); 3223240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch} 3233240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 3243240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid NetworkCertMigrator::Init(NetworkStateHandler* network_state_handler) { 3253240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch DCHECK(network_state_handler); 3263240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch network_state_handler_ = network_state_handler; 3273240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch network_state_handler_->AddObserver(this, FROM_HERE); 3283240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 3293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch DCHECK(CertLoader::IsInitialized()); 3303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch CertLoader::Get()->AddObserver(this); 3313240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch} 3323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 3333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid NetworkCertMigrator::NetworkListChanged() { 3343240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (!CertLoader::Get()->certificates_loaded()) { 3353240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch VLOG(2) << "Certs not loaded yet."; 3363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return; 3373240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 33803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Run the migration process from deprecated CaCertNssProperties to CaCertPem 33903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // and to fix missing or incorrect slot ids of client certificates. 34003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) VLOG(2) << "Start certificate migration of network configurations."; 3413240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch scoped_refptr<MigrationTask> helper(new MigrationTask( 3423240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch CertLoader::Get()->cert_list(), weak_ptr_factory_.GetWeakPtr())); 3433240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch NetworkStateHandler::NetworkStateList networks; 34403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) network_state_handler_->GetNetworkListByType( 34503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) NetworkTypePattern::Default(), 34603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) true, // only configured networks 34703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) false, // visible and not visible networks 34803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 0, // no count limit 34903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) &networks); 3503240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch helper->Run(networks); 3513240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch} 3523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 3533240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid NetworkCertMigrator::OnCertificatesLoaded( 3543240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch const net::CertificateList& cert_list, 3553240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch bool initial_load) { 35603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Maybe there are networks referring to certs that were not loaded before but 35703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // are now. 3583240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch NetworkListChanged(); 3593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch} 3603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 3613240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch} // namespace chromeos 362