blob: 507b74811d906b8fcf44c8684ca4cf1653b881e9 [file] [log] [blame]
[email protected]e0ad0892012-05-22 19:16:591// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]0fd776c42010-09-29 21:59:172// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]4f242962011-05-13 22:25:225#include "chrome/browser/certificate_manager_model.h"
[email protected]0fd776c42010-09-29 21:59:176
[email protected]289838c2011-09-29 22:12:277#include "base/bind.h"
[email protected]0fd776c42010-09-29 21:59:178#include "base/i18n/time_formatting.h"
9#include "base/logging.h"
[email protected]135cb802013-06-09 16:44:2010#include "base/strings/utf_string_conversions.h"
[email protected]3065a1f2014-01-22 08:56:3511#include "chrome/browser/net/nss_context.h"
[email protected]99e5e9522013-12-16 13:05:2712#include "chrome/browser/ui/crypto_module_password_dialog_nss.h"
[email protected]b1c2a5542010-10-08 12:44:4013#include "chrome/common/net/x509_certificate_model.h"
[email protected]af39f002014-08-22 10:18:1814#include "chrome/grit/generated_resources.h"
[email protected]3065a1f2014-01-22 08:56:3515#include "content/public/browser/browser_context.h"
16#include "content/public/browser/browser_thread.h"
17#include "content/public/browser/resource_context.h"
18#include "crypto/nss_util.h"
[email protected]4c4f7cd2011-03-05 02:20:4419#include "net/base/crypto_module.h"
[email protected]06dc3202010-10-06 21:18:0720#include "net/base/net_errors.h"
[email protected]6e7845ae2013-03-29 21:48:1121#include "net/cert/x509_certificate.h"
[email protected]1d77c3e2011-06-08 16:34:4722#include "ui/base/l10n/l10n_util.h"
[email protected]1d77c3e2011-06-08 16:34:4723
[email protected]3065a1f2014-01-22 08:56:3524using content::BrowserThread;
25
26// CertificateManagerModel is created on the UI thread. It needs a
27// NSSCertDatabase handle (and on ChromeOS it needs to get the TPM status) which
28// needs to be done on the IO thread.
29//
30// The initialization flow is roughly:
31//
32// UI thread IO Thread
33//
34// CertificateManagerModel::Create
35// \--------------------------------------v
36// CertificateManagerModel::GetCertDBOnIOThread
37// |
38// GetNSSCertDatabaseForResourceContext
39// |
40// CertificateManagerModel::DidGetCertDBOnIOThread
41// |
42// crypto::IsTPMTokenEnabledForNSS
43// v--------------------------------------/
44// CertificateManagerModel::DidGetCertDBOnUIThread
45// |
46// new CertificateManagerModel
47// |
48// callback
49
50// static
51void CertificateManagerModel::Create(
52 content::BrowserContext* browser_context,
53 CertificateManagerModel::Observer* observer,
54 const CreationCallback& callback) {
thestig00844cea2015-09-08 21:44:5255 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]3065a1f2014-01-22 08:56:3556 BrowserThread::PostTask(
57 BrowserThread::IO,
58 FROM_HERE,
59 base::Bind(&CertificateManagerModel::GetCertDBOnIOThread,
60 browser_context->GetResourceContext(),
61 observer,
62 callback));
63}
64
65CertificateManagerModel::CertificateManagerModel(
66 net::NSSCertDatabase* nss_cert_database,
[email protected]16dad0962014-03-18 01:29:1167 bool is_user_db_available,
[email protected]3065a1f2014-01-22 08:56:3568 bool is_tpm_available,
69 Observer* observer)
70 : cert_db_(nss_cert_database),
[email protected]16dad0962014-03-18 01:29:1171 is_user_db_available_(is_user_db_available),
[email protected]3065a1f2014-01-22 08:56:3572 is_tpm_available_(is_tpm_available),
[email protected]7fda9a402012-09-10 14:11:0773 observer_(observer) {
thestig00844cea2015-09-08 21:44:5274 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]0fd776c42010-09-29 21:59:1775}
76
77CertificateManagerModel::~CertificateManagerModel() {
78}
79
80void CertificateManagerModel::Refresh() {
[email protected]3f1719b2013-11-14 00:34:5481 DVLOG(1) << "refresh started";
[email protected]4c4f7cd2011-03-05 02:20:4482 net::CryptoModuleList modules;
[email protected]7fda9a402012-09-10 14:11:0783 cert_db_->ListModules(&modules, false);
[email protected]3f1719b2013-11-14 00:34:5484 DVLOG(1) << "refresh waiting for unlocking...";
[email protected]6246ac52012-09-24 01:55:2985 chrome::UnlockSlotsIfNecessary(
[email protected]4c4f7cd2011-03-05 02:20:4486 modules,
[email protected]6246ac52012-09-24 01:55:2987 chrome::kCryptoModulePasswordListCerts,
[email protected]791879c2013-12-17 07:22:4188 net::HostPortPair(), // unused.
[email protected]3f1719b2013-11-14 00:34:5489 NULL, // TODO(mattm): supply parent window.
[email protected]289838c2011-09-29 22:12:2790 base::Bind(&CertificateManagerModel::RefreshSlotsUnlocked,
91 base::Unretained(this)));
[email protected]4c4f7cd2011-03-05 02:20:4492}
93
94void CertificateManagerModel::RefreshSlotsUnlocked() {
[email protected]3f1719b2013-11-14 00:34:5495 DVLOG(1) << "refresh listing certs...";
[email protected]9e818932014-02-06 10:24:1196 // TODO(tbarzic): Use async |ListCerts|.
97 cert_db_->ListCertsSync(&cert_list_);
[email protected]06dc3202010-10-06 21:18:0798 observer_->CertificatesRefreshed();
[email protected]3f1719b2013-11-14 00:34:5499 DVLOG(1) << "refresh finished";
[email protected]0fd776c42010-09-29 21:59:17100}
101
102void CertificateManagerModel::FilterAndBuildOrgGroupingMap(
103 net::CertType filter_type,
104 CertificateManagerModel::OrgGroupingMap* map) const {
105 for (net::CertificateList::const_iterator i = cert_list_.begin();
106 i != cert_list_.end(); ++i) {
107 net::X509Certificate* cert = i->get();
[email protected]b1c2a5542010-10-08 12:44:40108 net::CertType type =
109 x509_certificate_model::GetType(cert->os_cert_handle());
[email protected]0fd776c42010-09-29 21:59:17110 if (type != filter_type)
111 continue;
112
113 std::string org;
114 if (!cert->subject().organization_names.empty())
115 org = cert->subject().organization_names[0];
116 if (org.empty())
117 org = cert->subject().GetDisplayName();
118
119 (*map)[org].push_back(cert);
120 }
121}
122
[email protected]96920152013-12-04 21:00:16123base::string16 CertificateManagerModel::GetColumnText(
[email protected]0fd776c42010-09-29 21:59:17124 const net::X509Certificate& cert,
125 Column column) const {
[email protected]96920152013-12-04 21:00:16126 base::string16 rv;
[email protected]0fd776c42010-09-29 21:59:17127 switch (column) {
128 case COL_SUBJECT_NAME:
[email protected]cc2a2a22013-12-24 23:12:15129 rv = base::UTF8ToUTF16(
[email protected]b1c2a5542010-10-08 12:44:40130 x509_certificate_model::GetCertNameOrNickname(cert.os_cert_handle()));
[email protected]1d77c3e2011-06-08 16:34:47131
[email protected]1d77c3e2011-06-08 16:34:47132 // TODO(xiyuan): Put this into a column when we have js tree-table.
[email protected]e0ad0892012-05-22 19:16:59133 if (IsHardwareBacked(&cert)) {
[email protected]1d77c3e2011-06-08 16:34:47134 rv = l10n_util::GetStringFUTF16(
135 IDS_CERT_MANAGER_HARDWARE_BACKED_KEY_FORMAT,
136 rv,
137 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_HARDWARE_BACKED));
138 }
[email protected]0fd776c42010-09-29 21:59:17139 break;
140 case COL_CERTIFICATE_STORE:
[email protected]cc2a2a22013-12-24 23:12:15141 rv = base::UTF8ToUTF16(
[email protected]b1c2a5542010-10-08 12:44:40142 x509_certificate_model::GetTokenName(cert.os_cert_handle()));
[email protected]0fd776c42010-09-29 21:59:17143 break;
144 case COL_SERIAL_NUMBER:
[email protected]cc2a2a22013-12-24 23:12:15145 rv = base::ASCIIToUTF16(x509_certificate_model::GetSerialNumberHexified(
[email protected]007b3f82013-04-09 08:46:45146 cert.os_cert_handle(), std::string()));
[email protected]0fd776c42010-09-29 21:59:17147 break;
148 case COL_EXPIRES_ON:
[email protected]1b6dc3e2010-12-22 15:08:08149 if (!cert.valid_expiry().is_null())
150 rv = base::TimeFormatShortDateNumeric(cert.valid_expiry());
[email protected]0fd776c42010-09-29 21:59:17151 break;
[email protected]0fd776c42010-09-29 21:59:17152 default:
153 NOTREACHED();
154 }
155 return rv;
156}
[email protected]06dc3202010-10-06 21:18:07157
[email protected]88b9db72011-01-13 01:48:43158int CertificateManagerModel::ImportFromPKCS12(net::CryptoModule* module,
159 const std::string& data,
[email protected]96920152013-12-04 21:00:16160 const base::string16& password,
[email protected]6a18d072011-06-29 00:25:40161 bool is_extractable) {
[email protected]7fda9a402012-09-10 14:11:07162 int result = cert_db_->ImportFromPKCS12(module, data, password,
163 is_extractable, NULL);
[email protected]06dc3202010-10-06 21:18:07164 if (result == net::OK)
165 Refresh();
166 return result;
167}
168
svaldez3e98a712015-11-23 16:21:57169int CertificateManagerModel::ImportUserCert(const std::string& data) {
170 int result = cert_db_->ImportUserCert(data);
171 if (result == net::OK)
172 Refresh();
173 return result;
174}
175
[email protected]2feacc342010-10-12 22:52:52176bool CertificateManagerModel::ImportCACerts(
177 const net::CertificateList& certificates,
[email protected]7fda9a402012-09-10 14:11:07178 net::NSSCertDatabase::TrustBits trust_bits,
179 net::NSSCertDatabase::ImportCertFailureList* not_imported) {
180 bool result = cert_db_->ImportCACerts(certificates, trust_bits, not_imported);
[email protected]2feacc342010-10-12 22:52:52181 if (result && not_imported->size() != certificates.size())
182 Refresh();
183 return result;
[email protected]72a8d0d72010-10-08 00:36:57184}
185
[email protected]7a3a9652010-10-13 01:21:13186bool CertificateManagerModel::ImportServerCert(
187 const net::CertificateList& certificates,
[email protected]7fda9a402012-09-10 14:11:07188 net::NSSCertDatabase::TrustBits trust_bits,
189 net::NSSCertDatabase::ImportCertFailureList* not_imported) {
190 bool result = cert_db_->ImportServerCert(certificates, trust_bits,
191 not_imported);
[email protected]7a3a9652010-10-13 01:21:13192 if (result && not_imported->size() != certificates.size())
193 Refresh();
194 return result;
195}
196
[email protected]c79b784d12011-09-20 18:44:54197bool CertificateManagerModel::SetCertTrust(
198 const net::X509Certificate* cert,
199 net::CertType type,
[email protected]7fda9a402012-09-10 14:11:07200 net::NSSCertDatabase::TrustBits trust_bits) {
201 return cert_db_->SetCertTrust(cert, type, trust_bits);
[email protected]72a8d0d72010-10-08 00:36:57202}
203
[email protected]06dc3202010-10-06 21:18:07204bool CertificateManagerModel::Delete(net::X509Certificate* cert) {
[email protected]7fda9a402012-09-10 14:11:07205 bool result = cert_db_->DeleteCertAndKey(cert);
[email protected]06dc3202010-10-06 21:18:07206 if (result)
207 Refresh();
208 return result;
209}
[email protected]e0ad0892012-05-22 19:16:59210
211bool CertificateManagerModel::IsHardwareBacked(
212 const net::X509Certificate* cert) const {
[email protected]e764bea2013-11-20 05:07:01213 return cert_db_->IsHardwareBacked(cert);
[email protected]e0ad0892012-05-22 19:16:59214}
[email protected]3065a1f2014-01-22 08:56:35215
216// static
217void CertificateManagerModel::DidGetCertDBOnUIThread(
218 net::NSSCertDatabase* cert_db,
[email protected]16dad0962014-03-18 01:29:11219 bool is_user_db_available,
[email protected]3065a1f2014-01-22 08:56:35220 bool is_tpm_available,
221 CertificateManagerModel::Observer* observer,
222 const CreationCallback& callback) {
thestig00844cea2015-09-08 21:44:52223 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]3065a1f2014-01-22 08:56:35224
[email protected]16dad0962014-03-18 01:29:11225 scoped_ptr<CertificateManagerModel> model(new CertificateManagerModel(
226 cert_db, is_user_db_available, is_tpm_available, observer));
[email protected]3065a1f2014-01-22 08:56:35227 callback.Run(model.Pass());
228}
229
230// static
231void CertificateManagerModel::DidGetCertDBOnIOThread(
232 CertificateManagerModel::Observer* observer,
233 const CreationCallback& callback,
234 net::NSSCertDatabase* cert_db) {
thestig00844cea2015-09-08 21:44:52235 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]3065a1f2014-01-22 08:56:35236
[email protected]16dad0962014-03-18 01:29:11237 bool is_user_db_available = cert_db->GetPublicSlot();
[email protected]3065a1f2014-01-22 08:56:35238 bool is_tpm_available = false;
239#if defined(OS_CHROMEOS)
240 is_tpm_available = crypto::IsTPMTokenEnabledForNSS();
241#endif
242 BrowserThread::PostTask(
243 BrowserThread::UI,
244 FROM_HERE,
245 base::Bind(&CertificateManagerModel::DidGetCertDBOnUIThread,
246 cert_db,
[email protected]16dad0962014-03-18 01:29:11247 is_user_db_available,
[email protected]3065a1f2014-01-22 08:56:35248 is_tpm_available,
249 observer,
250 callback));
251}
252
253// static
254void CertificateManagerModel::GetCertDBOnIOThread(
255 content::ResourceContext* context,
256 CertificateManagerModel::Observer* observer,
257 const CreationCallback& callback) {
thestig00844cea2015-09-08 21:44:52258 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]3065a1f2014-01-22 08:56:35259 net::NSSCertDatabase* cert_db = GetNSSCertDatabaseForResourceContext(
260 context,
261 base::Bind(&CertificateManagerModel::DidGetCertDBOnIOThread,
262 observer,
263 callback));
264 if (cert_db)
265 DidGetCertDBOnIOThread(observer, callback, cert_db);
266}