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
103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "base/location.h"
113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "base/metrics/histogram.h"
123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "chromeos/dbus/dbus_thread_manager.h"
133240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "chromeos/dbus/shill_service_client.h"
143240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "chromeos/network/network_handler_callbacks.h"
153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "chromeos/network/network_state.h"
163240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "chromeos/network/network_state_handler.h"
173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "dbus/object_path.h"
183240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "third_party/cros_system_api/dbus/service_constants.h"
193240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
203240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochnamespace chromeos {
213240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
223240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochnamespace {
233240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
243240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochenum UMANetworkType {
253240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  UMA_NETWORK_TYPE_EAP,
263240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  UMA_NETWORK_TYPE_OPENVPN,
273240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  UMA_NETWORK_TYPE_IPSEC,
283240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  UMA_NETWORK_TYPE_SIZE,
293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch};
303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
313240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// Copied from x509_certificate_model_nss.cc
323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochstd::string GetNickname(const net::X509Certificate& cert) {
333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (!cert.os_cert_handle()->nickname)
343240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    return std::string();
353240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  std::string name = cert.os_cert_handle()->nickname;
363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Hack copied from mozilla: Cut off text before first :, which seems to
373240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // just be the token name.
383240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  size_t colon_pos = name.find(':');
393240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (colon_pos != std::string::npos)
403240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    name = name.substr(colon_pos + 1);
413240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  return name;
423240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
433240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
443240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}  // namespace
453240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
463240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// Checks which of the given |networks| has one of the deprecated
473240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// CaCertNssProperties set. If such a network already has a CaCertPEM property,
483240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// then the NssProperty is cleared. Otherwise, the NssProperty is compared with
493240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// the nickname of each certificate of |certs|. If a match is found, then the
503240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// CaCertPemProperty is set and the NssProperty is cleared. Otherwise, the
513240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch// network is not modified.
523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochclass NetworkCertMigrator::MigrationTask
533240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    : public base::RefCounted<MigrationTask> {
543240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch public:
553240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  MigrationTask(const net::CertificateList& certs,
563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                const base::WeakPtr<NetworkCertMigrator>& cert_migrator)
573240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      : certs_(certs),
583240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        cert_migrator_(cert_migrator) {
593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
613240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  void Run(const NetworkStateHandler::NetworkStateList& networks) {
623240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // Request properties for each network that has a CaCertNssProperty set
633240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    // according to the NetworkStateHandler.
643240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    for (NetworkStateHandler::NetworkStateList::const_iterator it =
653240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch             networks.begin(); it != networks.end(); ++it) {
663240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      if (!(*it)->HasCACertNSS())
673240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        continue;
683240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      const std::string& service_path = (*it)->path();
693240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      DBusThreadManager::Get()->GetShillServiceClient()->GetProperties(
703240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch          dbus::ObjectPath(service_path),
713240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch          base::Bind(&network_handler::GetPropertiesCallback,
723240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                     base::Bind(&MigrationTask::MigrateNetwork, this),
733240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                     network_handler::ErrorCallback(),
743240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                     service_path));
753240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
763240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
773240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
783240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  void MigrateNetwork(const std::string& service_path,
793240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                      const base::DictionaryValue& properties) {
803240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (!cert_migrator_) {
813240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      VLOG(2) << "NetworkCertMigrator already destroyed. Aborting migration.";
823240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return;
833240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
843240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
853240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    std::string nss_key, pem_key, nickname;
863240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const base::ListValue* pem_property = NULL;
873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    UMANetworkType uma_type = UMA_NETWORK_TYPE_SIZE;
883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
893240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    GetNssAndPemProperties(
903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        properties, &nss_key, &pem_key, &pem_property, &nickname, &uma_type);
913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (nickname.empty())
923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return;  // Didn't find any nickname.
933240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
943240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    VLOG(2) << "Found NSS nickname to migrate. Property: " << nss_key
953240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch            << ", network: " << service_path;
963240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    UMA_HISTOGRAM_ENUMERATION(
973240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        "Network.MigrationNssToPem", uma_type, UMA_NETWORK_TYPE_SIZE);
983240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
993240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (pem_property && !pem_property->empty()) {
1003240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      VLOG(2) << "PEM already exists, clearing NSS property.";
1013240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      ClearNssProperty(service_path, nss_key);
1023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return;
1033240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
1043240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1053240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    scoped_refptr<net::X509Certificate> cert =
1063240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        FindCertificateWithNickname(nickname);
1073240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (!cert) {
1083240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      VLOG(2) << "No matching cert found.";
1093240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return;
1103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
1113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    std::string pem_encoded;
1133240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    if (!net::X509Certificate::GetPEMEncoded(cert->os_cert_handle(),
1143240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                                             &pem_encoded)) {
1153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      LOG(ERROR) << "PEM encoding failed.";
1163240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      return;
1173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
1183240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1193240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    SetNssAndPemProperties(service_path, nss_key, pem_key, pem_encoded);
1203240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
1213240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1223240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  void GetNssAndPemProperties(const base::DictionaryValue& shill_properties,
1233240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                              std::string* nss_key,
1243240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                              std::string* pem_key,
1253240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                              const base::ListValue** pem_property,
1263240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                              std::string* nickname,
1273240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                              UMANetworkType* uma_type) {
1283240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    struct NssPem {
1293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      const char* read_prefix;
1303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      const char* nss_key;
1313240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      const char* pem_key;
1323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      UMANetworkType uma_type;
1333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    } const kNssPemMap[] = {
13468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        { NULL, shill::kEapCaCertNssProperty, shill::kEapCaCertPemProperty,
1353240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch         UMA_NETWORK_TYPE_EAP },
13668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        { shill::kProviderProperty, shill::kL2tpIpsecCaCertNssProperty,
1373240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch         shill::kL2tpIpsecCaCertPemProperty, UMA_NETWORK_TYPE_IPSEC },
13868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        { shill::kProviderProperty, shill::kOpenVPNCaCertNSSProperty,
1393240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch         shill::kOpenVPNCaCertPemProperty, UMA_NETWORK_TYPE_OPENVPN },
1403240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    };
1413240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1423240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kNssPemMap); ++i) {
1433240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      const base::DictionaryValue* dict = &shill_properties;
1443240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      if (kNssPemMap[i].read_prefix) {
1453240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        shill_properties.GetDictionaryWithoutPathExpansion(
1463240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch            kNssPemMap[i].read_prefix, &dict);
1473240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        if (!dict)
1483240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch          continue;
1493240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      }
1503240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      dict->GetStringWithoutPathExpansion(kNssPemMap[i].nss_key, nickname);
1513240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      if (!nickname->empty()) {
1523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        *nss_key = kNssPemMap[i].nss_key;
1533240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        *pem_key = kNssPemMap[i].pem_key;
1543240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        *uma_type = kNssPemMap[i].uma_type;
1553240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        dict->GetListWithoutPathExpansion(kNssPemMap[i].pem_key, pem_property);
1563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        return;
1573240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      }
1583240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
1593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
1603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1613240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  void ClearNssProperty(const std::string& service_path,
1623240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                        const std::string& nss_key) {
1633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
1643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        dbus::ObjectPath(service_path),
1653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        nss_key,
1663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        base::StringValue(std::string()),
1673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        base::Bind(
1683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            &MigrationTask::NotifyNetworkStateHandler, this, service_path),
1693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        base::Bind(&network_handler::ShillErrorCallbackFunction,
1703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                   "MigrationTask.SetProperty failed",
1713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                   service_path,
1723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                   network_handler::ErrorCallback()));
1733240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
1743240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1753240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  scoped_refptr<net::X509Certificate> FindCertificateWithNickname(
1763240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      const std::string& nickname) {
1773240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    for (net::CertificateList::iterator it = certs_.begin(); it != certs_.end();
1783240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch         ++it) {
1793240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      if (nickname == GetNickname(**it))
1803240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        return *it;
1813240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
1823240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    return NULL;
1833240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
1843240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1853240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  void SetNssAndPemProperties(const std::string& service_path,
1863240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                              const std::string& nss_key,
1873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                              const std::string& pem_key,
1883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                              const std::string& pem_encoded_cert) {
1893240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    base::DictionaryValue new_properties;
1903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    new_properties.SetStringWithoutPathExpansion(nss_key, std::string());
1913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    scoped_ptr<base::ListValue> ca_cert_pems(new base::ListValue);
1923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    ca_cert_pems->AppendString(pem_encoded_cert);
1933240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    new_properties.SetWithoutPathExpansion(pem_key, ca_cert_pems.release());
1943240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
1953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    DBusThreadManager::Get()->GetShillServiceClient()->SetProperties(
1963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        dbus::ObjectPath(service_path),
1973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        new_properties,
1983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        base::Bind(
1993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            &MigrationTask::NotifyNetworkStateHandler, this, service_path),
2003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        base::Bind(&MigrationTask::LogErrorAndNotifyNetworkStateHandler,
2013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                   this,
2023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                   service_path));
2033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void LogErrorAndNotifyNetworkStateHandler(const std::string& service_path,
2063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                            const std::string& error_name,
2073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                            const std::string& error_message) {
2083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    network_handler::ShillErrorCallbackFunction(
2093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        "MigrationTask.SetProperties failed",
2103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        service_path,
2113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        network_handler::ErrorCallback(),
2123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        error_name,
2133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        error_message);
2143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    NotifyNetworkStateHandler(service_path);
2153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void NotifyNetworkStateHandler(const std::string& service_path) {
2183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (!cert_migrator_) {
2193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      VLOG(2) << "NetworkCertMigrator already destroyed. Aborting migration.";
2203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return;
2213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
2223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    cert_migrator_->network_state_handler_->RequestUpdateForNetwork(
2233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        service_path);
2243240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
2253240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2263240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch private:
2273240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  friend class base::RefCounted<MigrationTask>;
2283240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  virtual ~MigrationTask() {
2293240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
2303240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2313240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  net::CertificateList certs_;
2323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  base::WeakPtr<NetworkCertMigrator> cert_migrator_;
2333240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch};
2343240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2353240926e260ce088908e02ac07a6cf7b0c0cbf44Ben MurdochNetworkCertMigrator::NetworkCertMigrator()
2363240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    : network_state_handler_(NULL),
2373240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      weak_ptr_factory_(this) {
2383240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
2393240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2403240926e260ce088908e02ac07a6cf7b0c0cbf44Ben MurdochNetworkCertMigrator::~NetworkCertMigrator() {
2413240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  network_state_handler_->RemoveObserver(this, FROM_HERE);
2423240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (CertLoader::IsInitialized())
2433240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    CertLoader::Get()->RemoveObserver(this);
2443240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
2453240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2463240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid NetworkCertMigrator::Init(NetworkStateHandler* network_state_handler) {
2473240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  DCHECK(network_state_handler);
2483240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  network_state_handler_ = network_state_handler;
2493240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  network_state_handler_->AddObserver(this, FROM_HERE);
2503240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2513240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  DCHECK(CertLoader::IsInitialized());
2523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  CertLoader::Get()->AddObserver(this);
2533240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
2543240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2553240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid NetworkCertMigrator::NetworkListChanged() {
2563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  if (!CertLoader::Get()->certificates_loaded()) {
2573240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    VLOG(2) << "Certs not loaded yet.";
2583240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    return;
2593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  }
2603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Run the migration process from deprecated CaCertNssProperties to CaCertPem.
2613240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  VLOG(2) << "Start NSS nickname to PEM migration.";
2623240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  scoped_refptr<MigrationTask> helper(new MigrationTask(
2633240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      CertLoader::Get()->cert_list(), weak_ptr_factory_.GetWeakPtr()));
2643240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  NetworkStateHandler::NetworkStateList networks;
2653240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  network_state_handler_->GetNetworkList(&networks);
2663240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  helper->Run(networks);
2673240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
2683240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2693240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid NetworkCertMigrator::OnCertificatesLoaded(
2703240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const net::CertificateList& cert_list,
2713240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    bool initial_load) {
2723240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // Maybe there are networks referring to certs (by NSS nickname) that were not
2733240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  // loaded before but are now.
2743240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  NetworkListChanged();
2753240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
2763240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
2773240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}  // namespace chromeos
278