blob: 77f22c006601ddf20259491a553ba15801d10fa1 [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
dchenge73d8520c2015-12-27 01:19:097#include <utility>
8
[email protected]289838c2011-09-29 22:12:279#include "base/bind.h"
[email protected]0fd776c42010-09-29 21:59:1710#include "base/i18n/time_formatting.h"
11#include "base/logging.h"
[email protected]135cb802013-06-09 16:44:2012#include "base/strings/utf_string_conversions.h"
avie4d7b6f2015-12-26 00:59:1813#include "build/build_config.h"
[email protected]3065a1f2014-01-22 08:56:3514#include "chrome/browser/net/nss_context.h"
[email protected]99e5e9522013-12-16 13:05:2715#include "chrome/browser/ui/crypto_module_password_dialog_nss.h"
[email protected]b1c2a5542010-10-08 12:44:4016#include "chrome/common/net/x509_certificate_model.h"
[email protected]af39f002014-08-22 10:18:1817#include "chrome/grit/generated_resources.h"
[email protected]3065a1f2014-01-22 08:56:3518#include "content/public/browser/browser_context.h"
19#include "content/public/browser/browser_thread.h"
20#include "content/public/browser/resource_context.h"
21#include "crypto/nss_util.h"
[email protected]4c4f7cd2011-03-05 02:20:4422#include "net/base/crypto_module.h"
[email protected]06dc3202010-10-06 21:18:0723#include "net/base/net_errors.h"
[email protected]6e7845ae2013-03-29 21:48:1124#include "net/cert/x509_certificate.h"
[email protected]1d77c3e2011-06-08 16:34:4725#include "ui/base/l10n/l10n_util.h"
[email protected]1d77c3e2011-06-08 16:34:4726
[email protected]3065a1f2014-01-22 08:56:3527using content::BrowserThread;
28
29// CertificateManagerModel is created on the UI thread. It needs a
30// NSSCertDatabase handle (and on ChromeOS it needs to get the TPM status) which
31// needs to be done on the IO thread.
32//
33// The initialization flow is roughly:
34//
35// UI thread IO Thread
36//
37// CertificateManagerModel::Create
38// \--------------------------------------v
39// CertificateManagerModel::GetCertDBOnIOThread
40// |
41// GetNSSCertDatabaseForResourceContext
42// |
43// CertificateManagerModel::DidGetCertDBOnIOThread
44// |
45// crypto::IsTPMTokenEnabledForNSS
46// v--------------------------------------/
47// CertificateManagerModel::DidGetCertDBOnUIThread
48// |
49// new CertificateManagerModel
50// |
51// callback
52
53// static
54void CertificateManagerModel::Create(
55 content::BrowserContext* browser_context,
56 CertificateManagerModel::Observer* observer,
57 const CreationCallback& callback) {
thestig00844cea2015-09-08 21:44:5258 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]3065a1f2014-01-22 08:56:3559 BrowserThread::PostTask(
60 BrowserThread::IO,
61 FROM_HERE,
62 base::Bind(&CertificateManagerModel::GetCertDBOnIOThread,
63 browser_context->GetResourceContext(),
64 observer,
65 callback));
66}
67
68CertificateManagerModel::CertificateManagerModel(
69 net::NSSCertDatabase* nss_cert_database,
[email protected]16dad0962014-03-18 01:29:1170 bool is_user_db_available,
[email protected]3065a1f2014-01-22 08:56:3571 bool is_tpm_available,
72 Observer* observer)
73 : cert_db_(nss_cert_database),
[email protected]16dad0962014-03-18 01:29:1174 is_user_db_available_(is_user_db_available),
[email protected]3065a1f2014-01-22 08:56:3575 is_tpm_available_(is_tpm_available),
[email protected]7fda9a402012-09-10 14:11:0776 observer_(observer) {
thestig00844cea2015-09-08 21:44:5277 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]0fd776c42010-09-29 21:59:1778}
79
80CertificateManagerModel::~CertificateManagerModel() {
81}
82
83void CertificateManagerModel::Refresh() {
[email protected]3f1719b2013-11-14 00:34:5484 DVLOG(1) << "refresh started";
[email protected]4c4f7cd2011-03-05 02:20:4485 net::CryptoModuleList modules;
[email protected]7fda9a402012-09-10 14:11:0786 cert_db_->ListModules(&modules, false);
[email protected]3f1719b2013-11-14 00:34:5487 DVLOG(1) << "refresh waiting for unlocking...";
[email protected]6246ac52012-09-24 01:55:2988 chrome::UnlockSlotsIfNecessary(
[email protected]4c4f7cd2011-03-05 02:20:4489 modules,
[email protected]6246ac52012-09-24 01:55:2990 chrome::kCryptoModulePasswordListCerts,
[email protected]791879c2013-12-17 07:22:4191 net::HostPortPair(), // unused.
[email protected]3f1719b2013-11-14 00:34:5492 NULL, // TODO(mattm): supply parent window.
[email protected]289838c2011-09-29 22:12:2793 base::Bind(&CertificateManagerModel::RefreshSlotsUnlocked,
94 base::Unretained(this)));
[email protected]4c4f7cd2011-03-05 02:20:4495}
96
97void CertificateManagerModel::RefreshSlotsUnlocked() {
[email protected]3f1719b2013-11-14 00:34:5498 DVLOG(1) << "refresh listing certs...";
[email protected]9e818932014-02-06 10:24:1199 // TODO(tbarzic): Use async |ListCerts|.
100 cert_db_->ListCertsSync(&cert_list_);
[email protected]06dc3202010-10-06 21:18:07101 observer_->CertificatesRefreshed();
[email protected]3f1719b2013-11-14 00:34:54102 DVLOG(1) << "refresh finished";
[email protected]0fd776c42010-09-29 21:59:17103}
104
105void CertificateManagerModel::FilterAndBuildOrgGroupingMap(
106 net::CertType filter_type,
107 CertificateManagerModel::OrgGroupingMap* map) const {
108 for (net::CertificateList::const_iterator i = cert_list_.begin();
109 i != cert_list_.end(); ++i) {
110 net::X509Certificate* cert = i->get();
[email protected]b1c2a5542010-10-08 12:44:40111 net::CertType type =
112 x509_certificate_model::GetType(cert->os_cert_handle());
[email protected]0fd776c42010-09-29 21:59:17113 if (type != filter_type)
114 continue;
115
116 std::string org;
117 if (!cert->subject().organization_names.empty())
118 org = cert->subject().organization_names[0];
119 if (org.empty())
120 org = cert->subject().GetDisplayName();
121
122 (*map)[org].push_back(cert);
123 }
124}
125
[email protected]96920152013-12-04 21:00:16126base::string16 CertificateManagerModel::GetColumnText(
[email protected]0fd776c42010-09-29 21:59:17127 const net::X509Certificate& cert,
128 Column column) const {
[email protected]96920152013-12-04 21:00:16129 base::string16 rv;
[email protected]0fd776c42010-09-29 21:59:17130 switch (column) {
131 case COL_SUBJECT_NAME:
[email protected]cc2a2a22013-12-24 23:12:15132 rv = base::UTF8ToUTF16(
[email protected]b1c2a5542010-10-08 12:44:40133 x509_certificate_model::GetCertNameOrNickname(cert.os_cert_handle()));
[email protected]1d77c3e2011-06-08 16:34:47134
[email protected]1d77c3e2011-06-08 16:34:47135 // TODO(xiyuan): Put this into a column when we have js tree-table.
[email protected]e0ad0892012-05-22 19:16:59136 if (IsHardwareBacked(&cert)) {
[email protected]1d77c3e2011-06-08 16:34:47137 rv = l10n_util::GetStringFUTF16(
138 IDS_CERT_MANAGER_HARDWARE_BACKED_KEY_FORMAT,
139 rv,
140 l10n_util::GetStringUTF16(IDS_CERT_MANAGER_HARDWARE_BACKED));
141 }
[email protected]0fd776c42010-09-29 21:59:17142 break;
143 case COL_CERTIFICATE_STORE:
[email protected]cc2a2a22013-12-24 23:12:15144 rv = base::UTF8ToUTF16(
[email protected]b1c2a5542010-10-08 12:44:40145 x509_certificate_model::GetTokenName(cert.os_cert_handle()));
[email protected]0fd776c42010-09-29 21:59:17146 break;
147 case COL_SERIAL_NUMBER:
[email protected]cc2a2a22013-12-24 23:12:15148 rv = base::ASCIIToUTF16(x509_certificate_model::GetSerialNumberHexified(
[email protected]007b3f82013-04-09 08:46:45149 cert.os_cert_handle(), std::string()));
[email protected]0fd776c42010-09-29 21:59:17150 break;
151 case COL_EXPIRES_ON:
[email protected]1b6dc3e2010-12-22 15:08:08152 if (!cert.valid_expiry().is_null())
153 rv = base::TimeFormatShortDateNumeric(cert.valid_expiry());
[email protected]0fd776c42010-09-29 21:59:17154 break;
[email protected]0fd776c42010-09-29 21:59:17155 default:
156 NOTREACHED();
157 }
158 return rv;
159}
[email protected]06dc3202010-10-06 21:18:07160
[email protected]88b9db72011-01-13 01:48:43161int CertificateManagerModel::ImportFromPKCS12(net::CryptoModule* module,
162 const std::string& data,
[email protected]96920152013-12-04 21:00:16163 const base::string16& password,
[email protected]6a18d072011-06-29 00:25:40164 bool is_extractable) {
[email protected]7fda9a402012-09-10 14:11:07165 int result = cert_db_->ImportFromPKCS12(module, data, password,
166 is_extractable, NULL);
[email protected]06dc3202010-10-06 21:18:07167 if (result == net::OK)
168 Refresh();
169 return result;
170}
171
svaldez3e98a712015-11-23 16:21:57172int CertificateManagerModel::ImportUserCert(const std::string& data) {
173 int result = cert_db_->ImportUserCert(data);
174 if (result == net::OK)
175 Refresh();
176 return result;
177}
178
[email protected]2feacc342010-10-12 22:52:52179bool CertificateManagerModel::ImportCACerts(
180 const net::CertificateList& certificates,
[email protected]7fda9a402012-09-10 14:11:07181 net::NSSCertDatabase::TrustBits trust_bits,
182 net::NSSCertDatabase::ImportCertFailureList* not_imported) {
183 bool result = cert_db_->ImportCACerts(certificates, trust_bits, not_imported);
[email protected]2feacc342010-10-12 22:52:52184 if (result && not_imported->size() != certificates.size())
185 Refresh();
186 return result;
[email protected]72a8d0d72010-10-08 00:36:57187}
188
[email protected]7a3a9652010-10-13 01:21:13189bool CertificateManagerModel::ImportServerCert(
190 const net::CertificateList& certificates,
[email protected]7fda9a402012-09-10 14:11:07191 net::NSSCertDatabase::TrustBits trust_bits,
192 net::NSSCertDatabase::ImportCertFailureList* not_imported) {
193 bool result = cert_db_->ImportServerCert(certificates, trust_bits,
194 not_imported);
[email protected]7a3a9652010-10-13 01:21:13195 if (result && not_imported->size() != certificates.size())
196 Refresh();
197 return result;
198}
199
[email protected]c79b784d12011-09-20 18:44:54200bool CertificateManagerModel::SetCertTrust(
201 const net::X509Certificate* cert,
202 net::CertType type,
[email protected]7fda9a402012-09-10 14:11:07203 net::NSSCertDatabase::TrustBits trust_bits) {
204 return cert_db_->SetCertTrust(cert, type, trust_bits);
[email protected]72a8d0d72010-10-08 00:36:57205}
206
[email protected]06dc3202010-10-06 21:18:07207bool CertificateManagerModel::Delete(net::X509Certificate* cert) {
[email protected]7fda9a402012-09-10 14:11:07208 bool result = cert_db_->DeleteCertAndKey(cert);
[email protected]06dc3202010-10-06 21:18:07209 if (result)
210 Refresh();
211 return result;
212}
[email protected]e0ad0892012-05-22 19:16:59213
214bool CertificateManagerModel::IsHardwareBacked(
215 const net::X509Certificate* cert) const {
[email protected]e764bea2013-11-20 05:07:01216 return cert_db_->IsHardwareBacked(cert);
[email protected]e0ad0892012-05-22 19:16:59217}
[email protected]3065a1f2014-01-22 08:56:35218
219// static
220void CertificateManagerModel::DidGetCertDBOnUIThread(
221 net::NSSCertDatabase* cert_db,
[email protected]16dad0962014-03-18 01:29:11222 bool is_user_db_available,
[email protected]3065a1f2014-01-22 08:56:35223 bool is_tpm_available,
224 CertificateManagerModel::Observer* observer,
225 const CreationCallback& callback) {
thestig00844cea2015-09-08 21:44:52226 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]3065a1f2014-01-22 08:56:35227
[email protected]16dad0962014-03-18 01:29:11228 scoped_ptr<CertificateManagerModel> model(new CertificateManagerModel(
229 cert_db, is_user_db_available, is_tpm_available, observer));
dchenge73d8520c2015-12-27 01:19:09230 callback.Run(std::move(model));
[email protected]3065a1f2014-01-22 08:56:35231}
232
233// static
234void CertificateManagerModel::DidGetCertDBOnIOThread(
235 CertificateManagerModel::Observer* observer,
236 const CreationCallback& callback,
237 net::NSSCertDatabase* cert_db) {
thestig00844cea2015-09-08 21:44:52238 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]3065a1f2014-01-22 08:56:35239
dcheng5d64b522016-01-20 01:41:02240 bool is_user_db_available = !!cert_db->GetPublicSlot();
[email protected]3065a1f2014-01-22 08:56:35241 bool is_tpm_available = false;
242#if defined(OS_CHROMEOS)
243 is_tpm_available = crypto::IsTPMTokenEnabledForNSS();
244#endif
245 BrowserThread::PostTask(
246 BrowserThread::UI,
247 FROM_HERE,
248 base::Bind(&CertificateManagerModel::DidGetCertDBOnUIThread,
249 cert_db,
[email protected]16dad0962014-03-18 01:29:11250 is_user_db_available,
[email protected]3065a1f2014-01-22 08:56:35251 is_tpm_available,
252 observer,
253 callback));
254}
255
256// static
257void CertificateManagerModel::GetCertDBOnIOThread(
258 content::ResourceContext* context,
259 CertificateManagerModel::Observer* observer,
260 const CreationCallback& callback) {
thestig00844cea2015-09-08 21:44:52261 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]3065a1f2014-01-22 08:56:35262 net::NSSCertDatabase* cert_db = GetNSSCertDatabaseForResourceContext(
263 context,
264 base::Bind(&CertificateManagerModel::DidGetCertDBOnIOThread,
265 observer,
266 callback));
267 if (cert_db)
268 DidGetCertDBOnIOThread(observer, callback, cert_db);
269}