Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(86)

Side by Side Diff: chromeos/cert_loader.cc

Issue 2828713002: Enable client certificate patterns in device ONC policy (Closed)
Patch Set: Use BindOnce, PostTaskWithTraitsAndReplyWithResult. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chromeos/cert_loader.h" 5 #include "chromeos/cert_loader.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/location.h" 11 #include "base/location.h"
12 #include "base/memory/ptr_util.h"
12 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/string_number_conversions.h"
13 #include "base/task_runner_util.h" 14 #include "base/task_scheduler/post_task.h"
14 #include "base/threading/worker_pool.h" 15 #include "base/threading/worker_pool.h"
15 #include "crypto/nss_util.h" 16 #include "crypto/nss_util.h"
16 #include "crypto/scoped_nss_types.h" 17 #include "crypto/scoped_nss_types.h"
17 #include "net/cert/nss_cert_database.h" 18 #include "net/cert/nss_cert_database.h"
18 #include "net/cert/nss_cert_database_chromeos.h" 19 #include "net/cert/nss_cert_database_chromeos.h"
19 #include "net/cert/x509_certificate.h" 20 #include "net/cert/x509_certificate.h"
20 21
21 namespace chromeos { 22 namespace chromeos {
22 23
23 static CertLoader* g_cert_loader = NULL; 24 namespace {
25
26 // Checks if |certificate| is on the given |slot|.
27 bool IsCertificateOnSlot(const net::X509Certificate* certificate,
28 PK11SlotInfo* slot) {
29 crypto::ScopedPK11SlotList slots_for_cert(
30 PK11_GetAllSlotsForCert(certificate->os_cert_handle(), nullptr));
31 if (!slots_for_cert)
32 return false;
33
34 for (PK11SlotListElement* slot_element =
35 PK11_GetFirstSafe(slots_for_cert.get());
36 slot_element; slot_element = PK11_GetNextSafe(slots_for_cert.get(),
37 slot_element, PR_FALSE)) {
38 if (slot_element->slot == slot) {
39 // All previously visited elements have been freed by PK11_GetNextSafe,
40 // but we're not calling that for the last one, so free it explicitly.
41 // The slots_for_cert list itself will be freed because ScopedPK11SlotList
42 // is a unique_ptr.
43 PK11_FreeSlotListElement(slots_for_cert.get(), slot_element);
44 return true;
45 }
46 }
47 return false;
48 }
49
50 // Goes through all certificates in |all_certs| and copies those certificates
51 // which are on |system_slot| to a new list.
52 std::unique_ptr<net::CertificateList> FilterSystemTokenCertificates(
53 const net::CertificateList* all_certs,
54 crypto::ScopedPK11Slot system_slot) {
55 VLOG(1) << "FilterSystemTokenCertificates";
56 std::unique_ptr<net::CertificateList> system_certs =
57 base::MakeUnique<net::CertificateList>();
58 if (!system_slot)
59 return system_certs;
60
61 // Extract certificates which are in the system token into the
62 // system_certs_ sublist.
fdoray 2017/04/26 13:11:36 |system_certs_|
pmarko 2017/04/27 08:51:56 Done.
63 for (auto cert : *all_certs) {
fdoray 2017/04/26 13:11:36 const auto& to avoid an unnecessary ref-count bump
pmarko 2017/04/27 08:51:56 Done.
64 if (IsCertificateOnSlot(cert.get(), system_slot.get())) {
65 system_certs->push_back(cert);
66 }
67 }
68 return system_certs;
69 }
70
71 } // namespace
72
73 static CertLoader* g_cert_loader = nullptr;
24 static bool g_force_hardware_backed_for_test = false; 74 static bool g_force_hardware_backed_for_test = false;
25 75
26 // static 76 // static
27 void CertLoader::Initialize() { 77 void CertLoader::Initialize() {
28 CHECK(!g_cert_loader); 78 CHECK(!g_cert_loader);
29 g_cert_loader = new CertLoader(); 79 g_cert_loader = new CertLoader();
30 } 80 }
31 81
32 // static 82 // static
33 void CertLoader::Shutdown() { 83 void CertLoader::Shutdown() {
34 CHECK(g_cert_loader); 84 CHECK(g_cert_loader);
35 delete g_cert_loader; 85 delete g_cert_loader;
36 g_cert_loader = NULL; 86 g_cert_loader = nullptr;
37 } 87 }
38 88
39 // static 89 // static
40 CertLoader* CertLoader::Get() { 90 CertLoader* CertLoader::Get() {
41 CHECK(g_cert_loader) << "CertLoader::Get() called before Initialize()"; 91 CHECK(g_cert_loader) << "CertLoader::Get() called before Initialize()";
42 return g_cert_loader; 92 return g_cert_loader;
43 } 93 }
44 94
45 // static 95 // static
46 bool CertLoader::IsInitialized() { 96 bool CertLoader::IsInitialized() {
47 return g_cert_loader; 97 return g_cert_loader;
48 } 98 }
49 99
50 CertLoader::CertLoader() 100 CertLoader::CertLoader()
51 : certificates_loaded_(false), 101 : certificates_loaded_(false),
52 certificates_update_required_(false), 102 certificates_update_required_(false),
53 certificates_update_running_(false), 103 certificates_update_running_(false),
54 database_(NULL), 104 database_(nullptr),
55 cert_list_(new net::CertificateList), 105 all_certs_(new net::CertificateList),
fdoray 2017/04/26 13:11:35 base::MakeUnique<net::CertificateList>()
pmarko 2017/04/27 08:51:55 Done.
56 weak_factory_(this) { 106 weak_factory_(this) {}
57 }
58 107
59 CertLoader::~CertLoader() { 108 CertLoader::~CertLoader() {
60 net::CertDatabase::GetInstance()->RemoveObserver(this); 109 net::CertDatabase::GetInstance()->RemoveObserver(this);
61 } 110 }
62 111
63 void CertLoader::StartWithNSSDB(net::NSSCertDatabase* database) { 112 void CertLoader::StartWithNSSDB(net::NSSCertDatabase* database) {
64 CHECK(!database_); 113 CHECK(!database_);
65 database_ = database; 114 database_ = database;
66 115
67 // Start observing cert database for changes. 116 // Start observing cert database for changes.
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 // NOTE: This function relies on the convention that the same PKCS#11 ID 158 // NOTE: This function relies on the convention that the same PKCS#11 ID
110 // is shared between a certificate and its associated private and public 159 // is shared between a certificate and its associated private and public
111 // keys. I tried to implement this with PK11_GetLowLevelKeyIDForCert(), 160 // keys. I tried to implement this with PK11_GetLowLevelKeyIDForCert(),
112 // but that always returns NULL on Chrome OS for me. 161 // but that always returns NULL on Chrome OS for me.
113 std::string CertLoader::GetPkcs11IdAndSlotForCert( 162 std::string CertLoader::GetPkcs11IdAndSlotForCert(
114 const net::X509Certificate& cert, 163 const net::X509Certificate& cert,
115 int* slot_id) { 164 int* slot_id) {
116 DCHECK(slot_id); 165 DCHECK(slot_id);
117 166
118 CERTCertificateStr* cert_handle = cert.os_cert_handle(); 167 CERTCertificateStr* cert_handle = cert.os_cert_handle();
119 SECKEYPrivateKey *priv_key = 168 SECKEYPrivateKey* priv_key =
120 PK11_FindKeyByAnyCert(cert_handle, NULL /* wincx */); 169 PK11_FindKeyByAnyCert(cert_handle, nullptr /* wincx */);
121 if (!priv_key) 170 if (!priv_key)
122 return std::string(); 171 return std::string();
123 172
124 *slot_id = static_cast<int>(PK11_GetSlotID(priv_key->pkcs11Slot)); 173 *slot_id = static_cast<int>(PK11_GetSlotID(priv_key->pkcs11Slot));
125 174
126 // Get the CKA_ID attribute for a key. 175 // Get the CKA_ID attribute for a key.
127 SECItem* sec_item = PK11_GetLowLevelKeyIDForPrivateKey(priv_key); 176 SECItem* sec_item = PK11_GetLowLevelKeyIDForPrivateKey(priv_key);
128 std::string pkcs11_id; 177 std::string pkcs11_id;
129 if (sec_item) { 178 if (sec_item) {
130 pkcs11_id = base::HexEncode(sec_item->data, sec_item->len); 179 pkcs11_id = base::HexEncode(sec_item->data, sec_item->len);
131 SECITEM_FreeItem(sec_item, PR_TRUE); 180 SECITEM_FreeItem(sec_item, PR_TRUE);
132 } 181 }
133 SECKEY_DestroyPrivateKey(priv_key); 182 SECKEY_DestroyPrivateKey(priv_key);
134 183
135 return pkcs11_id; 184 return pkcs11_id;
136 } 185 }
137 186
138 void CertLoader::LoadCertificates() { 187 void CertLoader::LoadCertificates() {
139 CHECK(thread_checker_.CalledOnValidThread()); 188 DCHECK(thread_checker_.CalledOnValidThread());
140 VLOG(1) << "LoadCertificates: " << certificates_update_running_; 189 VLOG(1) << "LoadCertificates: " << certificates_update_running_;
141 190
142 if (certificates_update_running_) { 191 if (certificates_update_running_) {
143 certificates_update_required_ = true; 192 certificates_update_required_ = true;
144 return; 193 return;
145 } 194 }
146 195
147 certificates_update_running_ = true; 196 certificates_update_running_ = true;
148 certificates_update_required_ = false; 197 certificates_update_required_ = false;
149 198
150 database_->ListCerts( 199 database_->ListCerts(
151 base::Bind(&CertLoader::UpdateCertificates, weak_factory_.GetWeakPtr())); 200 base::Bind(&CertLoader::CertificatesLoaded, weak_factory_.GetWeakPtr()));
201 }
202
203 void CertLoader::CertificatesLoaded(
204 std::unique_ptr<net::CertificateList> all_certs) {
205 DCHECK(thread_checker_.CalledOnValidThread());
206 VLOG(1) << "CertificatesLoaded: " << all_certs->size();
207
208 crypto::ScopedPK11Slot system_slot = database_->GetSystemSlot();
209 base::PostTaskWithTraitsAndReplyWithResult(
210 FROM_HERE,
211 base::TaskTraits()
212 .WithShutdownBehavior(
213 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)
214 .MayBlock(),
215 base::BindOnce(&FilterSystemTokenCertificates,
216 base::Unretained(all_certs.get()), std::move(system_slot)),
217 base::BindOnce(&CertLoader::UpdateCertificates,
218 weak_factory_.GetWeakPtr(), std::move(all_certs)));
152 } 219 }
153 220
154 void CertLoader::UpdateCertificates( 221 void CertLoader::UpdateCertificates(
155 std::unique_ptr<net::CertificateList> cert_list) { 222 std::unique_ptr<net::CertificateList> all_certs,
156 CHECK(thread_checker_.CalledOnValidThread()); 223 std::unique_ptr<net::CertificateList> system_certs) {
224 DCHECK(thread_checker_.CalledOnValidThread());
157 DCHECK(certificates_update_running_); 225 DCHECK(certificates_update_running_);
158 VLOG(1) << "UpdateCertificates: " << cert_list->size(); 226 VLOG(1) << "UpdateCertificates: " << all_certs->size() << " ("
227 << system_certs->size() << " on system slot)";
159 228
160 // Ignore any existing certificates. 229 // Ignore any existing certificates.
161 cert_list_ = std::move(cert_list); 230 all_certs_ = std::move(all_certs);
231 system_certs_ = std::move(system_certs);
162 232
163 bool initial_load = !certificates_loaded_; 233 bool initial_load = !certificates_loaded_;
164 certificates_loaded_ = true; 234 certificates_loaded_ = true;
165 NotifyCertificatesLoaded(initial_load); 235 NotifyCertificatesLoaded(initial_load);
166 236
167 certificates_update_running_ = false; 237 certificates_update_running_ = false;
168 if (certificates_update_required_) 238 if (certificates_update_required_)
169 LoadCertificates(); 239 LoadCertificates();
170 } 240 }
171 241
172 void CertLoader::NotifyCertificatesLoaded(bool initial_load) { 242 void CertLoader::NotifyCertificatesLoaded(bool initial_load) {
173 for (auto& observer : observers_) 243 for (auto& observer : observers_)
174 observer.OnCertificatesLoaded(*cert_list_, initial_load); 244 observer.OnCertificatesLoaded(*all_certs_, initial_load);
175 } 245 }
176 246
177 void CertLoader::OnCertDBChanged() { 247 void CertLoader::OnCertDBChanged() {
178 VLOG(1) << "OnCertDBChanged"; 248 VLOG(1) << "OnCertDBChanged";
179 LoadCertificates(); 249 LoadCertificates();
180 } 250 }
181 251
182 } // namespace chromeos 252 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698