Home | History | Annotate | Download | only in options
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/chromeos/options/wifi_config_model.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "base/utf_string_conversions.h"
     10 #include "chrome/browser/browser_process.h"  // g_browser_process
     11 #include "chrome/common/net/x509_certificate_model.h"
     12 #include "net/base/cert_database.h"
     13 #include "net/base/x509_certificate.h"
     14 #include "ui/base/l10n/l10n_util_collator.h"  // CompareString16WithCollator
     15 #include "unicode/coll.h"  // icu::Collator
     16 
     17 namespace chromeos {
     18 
     19 namespace {
     20 
     21 typedef scoped_refptr<net::X509Certificate> X509CertificateRefPtr;
     22 
     23 // Root CA certificates that are built into Chrome use this token name.
     24 const char* const kRootCertificateTokenName = "Builtin Object Token";
     25 
     26 // Returns a user-visible name for a given certificate.
     27 string16 GetCertDisplayString(const net::X509Certificate* cert) {
     28   DCHECK(cert);
     29   std::string name_or_nick =
     30       x509_certificate_model::GetCertNameOrNickname(cert->os_cert_handle());
     31   return UTF8ToUTF16(name_or_nick);
     32 }
     33 
     34 // Comparison functor for locale-sensitive sorting of certificates by name.
     35 class CertNameComparator {
     36  public:
     37   explicit CertNameComparator(icu::Collator* collator)
     38       : collator_(collator) {
     39   }
     40 
     41   bool operator()(const X509CertificateRefPtr& lhs,
     42                   const X509CertificateRefPtr& rhs) const {
     43     string16 lhs_name = GetCertDisplayString(lhs);
     44     string16 rhs_name = GetCertDisplayString(rhs);
     45     if (collator_ == NULL)
     46       return lhs_name < rhs_name;
     47     return l10n_util::CompareString16WithCollator(
     48         collator_, lhs_name, rhs_name) == UCOL_LESS;
     49   }
     50 
     51  private:
     52   icu::Collator* collator_;
     53 };
     54 
     55 }  // namespace
     56 
     57 WifiConfigModel::WifiConfigModel() {
     58 }
     59 
     60 WifiConfigModel::~WifiConfigModel() {
     61 }
     62 
     63 void WifiConfigModel::UpdateCertificates() {
     64   // CertDatabase and its wrappers do not have random access to certificates,
     65   // so build filtered lists once.
     66   net::CertificateList cert_list;
     67   cert_db_.ListCerts(&cert_list);
     68   for (net::CertificateList::const_iterator it = cert_list.begin();
     69        it != cert_list.end();
     70        ++it) {
     71     net::X509Certificate* cert = it->get();
     72     net::X509Certificate::OSCertHandle cert_handle = cert->os_cert_handle();
     73     net::CertType type = x509_certificate_model::GetType(cert_handle);
     74     switch (type) {
     75       case net::USER_CERT:
     76         user_certs_.push_back(*it);
     77         break;
     78       case net::CA_CERT: {
     79         // Exclude root CA certificates that are built into Chrome.
     80         std::string token_name =
     81             x509_certificate_model::GetTokenName(cert_handle);
     82         if (token_name != kRootCertificateTokenName)
     83           server_ca_certs_.push_back(*it);
     84         break;
     85       }
     86       default:
     87         // We only care about those two types.
     88         break;
     89     }
     90   }
     91 
     92   // Perform locale-sensitive sorting by certificate name.
     93   scoped_ptr<icu::Collator> collator;
     94   UErrorCode error = U_ZERO_ERROR;
     95   collator.reset(
     96       icu::Collator::createInstance(
     97           icu::Locale(g_browser_process->GetApplicationLocale().c_str()),
     98           error));
     99   if (U_FAILURE(error))
    100     collator.reset(NULL);
    101   CertNameComparator cert_name_comparator(collator.get());
    102   std::sort(user_certs_.begin(), user_certs_.end(), cert_name_comparator);
    103   std::sort(server_ca_certs_.begin(), server_ca_certs_.end(),
    104             cert_name_comparator);
    105 }
    106 
    107 int WifiConfigModel::GetUserCertCount() const {
    108   return static_cast<int>(user_certs_.size());
    109 }
    110 
    111 string16 WifiConfigModel::GetUserCertName(int cert_index) const {
    112   DCHECK(cert_index >= 0);
    113   DCHECK(cert_index < static_cast<int>(user_certs_.size()));
    114   net::X509Certificate* cert = user_certs_[cert_index].get();
    115   return GetCertDisplayString(cert);
    116 }
    117 
    118 std::string WifiConfigModel::GetUserCertPkcs11Id(int cert_index) const {
    119   DCHECK(cert_index >= 0);
    120   DCHECK(cert_index < static_cast<int>(user_certs_.size()));
    121   net::X509Certificate* cert = user_certs_[cert_index].get();
    122   net::X509Certificate::OSCertHandle cert_handle = cert->os_cert_handle();
    123   return x509_certificate_model::GetPkcs11Id(cert_handle);
    124 }
    125 
    126 int WifiConfigModel::GetUserCertIndex(const std::string& pkcs11_id) const {
    127   // The list of user certs is small, so just test each one.
    128   for (int index = 0; index < static_cast<int>(user_certs_.size()); ++index) {
    129     net::X509Certificate* cert = user_certs_[index].get();
    130     net::X509Certificate::OSCertHandle cert_handle = cert->os_cert_handle();
    131     std::string id = x509_certificate_model::GetPkcs11Id(cert_handle);
    132     if (id == pkcs11_id)
    133       return index;
    134   }
    135   // Not found.
    136   return -1;
    137 }
    138 
    139 int WifiConfigModel::GetServerCaCertCount() const {
    140   return static_cast<int>(server_ca_certs_.size());
    141 }
    142 
    143 string16 WifiConfigModel::GetServerCaCertName(int cert_index) const {
    144   DCHECK(cert_index >= 0);
    145   DCHECK(cert_index < static_cast<int>(server_ca_certs_.size()));
    146   net::X509Certificate* cert = server_ca_certs_[cert_index].get();
    147   return GetCertDisplayString(cert);
    148 }
    149 
    150 std::string WifiConfigModel::GetServerCaCertNssNickname(int cert_index) const {
    151   DCHECK(cert_index >= 0);
    152   DCHECK(cert_index < static_cast<int>(server_ca_certs_.size()));
    153   net::X509Certificate* cert = server_ca_certs_[cert_index].get();
    154   net::X509Certificate::OSCertHandle cert_handle = cert->os_cert_handle();
    155   return x509_certificate_model::GetNickname(cert_handle);
    156 }
    157 
    158 int WifiConfigModel::GetServerCaCertIndex(
    159     const std::string& nss_nickname) const {
    160   // List of server certs is small, so just test each one.
    161   for (int i = 0; i < static_cast<int>(server_ca_certs_.size()); ++i) {
    162     net::X509Certificate* cert = server_ca_certs_[i].get();
    163     net::X509Certificate::OSCertHandle cert_handle = cert->os_cert_handle();
    164     std::string nickname = x509_certificate_model::GetNickname(cert_handle);
    165     if (nickname == nss_nickname)
    166       return i;
    167   }
    168   // Not found.
    169   return -1;
    170 }
    171 
    172 }  // namespace chromeos
    173