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