• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
GetCertDisplayString(const net::X509Certificate * cert)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:
CertNameComparator(icu::Collator * collator)37   explicit CertNameComparator(icu::Collator* collator)
38       : collator_(collator) {
39   }
40 
operator ()(const X509CertificateRefPtr & lhs,const X509CertificateRefPtr & rhs) const41   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 
WifiConfigModel()57 WifiConfigModel::WifiConfigModel() {
58 }
59 
~WifiConfigModel()60 WifiConfigModel::~WifiConfigModel() {
61 }
62 
UpdateCertificates()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 
GetUserCertCount() const107 int WifiConfigModel::GetUserCertCount() const {
108   return static_cast<int>(user_certs_.size());
109 }
110 
GetUserCertName(int cert_index) const111 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 
GetUserCertPkcs11Id(int cert_index) const118 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 
GetUserCertIndex(const std::string & pkcs11_id) const126 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 
GetServerCaCertCount() const139 int WifiConfigModel::GetServerCaCertCount() const {
140   return static_cast<int>(server_ca_certs_.size());
141 }
142 
GetServerCaCertName(int cert_index) const143 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 
GetServerCaCertNssNickname(int cert_index) const150 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 
GetServerCaCertIndex(const std::string & nss_nickname) const158 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