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

Side by Side Diff: chromeos/cert_loader.cc

Issue 2828713002: Enable client certificate patterns in device ONC policy (Closed)
Patch Set: Addressed comments. 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.
emaxx 2017/04/25 15:15:58 nit: My understanding was that the issue is not on
pmarko 2017/04/25 16:59:57 Actually: - Each element in the list starts out wi
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 |system_certs|.
52 void FilterSystemTokenCertificates(const net::CertificateList* all_certs,
53 net::CertificateList* system_certs,
54 crypto::ScopedPK11Slot system_slot) {
55 VLOG(1) << "FilterSystemTokenCertificates";
56 if (!system_slot)
57 return;
58 // Extract certificates which are in the system token into the
59 // system_certs_ sublist.
60 for (auto cert : *all_certs) {
61 if (IsCertificateOnSlot(cert.get(), system_slot.get())) {
62 system_certs->push_back(cert);
63 }
64 }
65 }
66
67 } // namespace
68
69 static CertLoader* g_cert_loader = nullptr;
24 static bool g_force_hardware_backed_for_test = false; 70 static bool g_force_hardware_backed_for_test = false;
25 71
26 // static 72 // static
27 void CertLoader::Initialize() { 73 void CertLoader::Initialize() {
28 CHECK(!g_cert_loader); 74 CHECK(!g_cert_loader);
29 g_cert_loader = new CertLoader(); 75 g_cert_loader = new CertLoader();
30 } 76 }
31 77
32 // static 78 // static
33 void CertLoader::Shutdown() { 79 void CertLoader::Shutdown() {
34 CHECK(g_cert_loader); 80 CHECK(g_cert_loader);
35 delete g_cert_loader; 81 delete g_cert_loader;
36 g_cert_loader = NULL; 82 g_cert_loader = nullptr;
37 } 83 }
38 84
39 // static 85 // static
40 CertLoader* CertLoader::Get() { 86 CertLoader* CertLoader::Get() {
41 CHECK(g_cert_loader) << "CertLoader::Get() called before Initialize()"; 87 CHECK(g_cert_loader) << "CertLoader::Get() called before Initialize()";
42 return g_cert_loader; 88 return g_cert_loader;
43 } 89 }
44 90
45 // static 91 // static
46 bool CertLoader::IsInitialized() { 92 bool CertLoader::IsInitialized() {
47 return g_cert_loader; 93 return g_cert_loader;
48 } 94 }
49 95
50 CertLoader::CertLoader() 96 CertLoader::CertLoader()
51 : certificates_loaded_(false), 97 : certificates_loaded_(false),
52 certificates_update_required_(false), 98 certificates_update_required_(false),
53 certificates_update_running_(false), 99 certificates_update_running_(false),
54 database_(NULL), 100 database_(nullptr),
55 cert_list_(new net::CertificateList), 101 all_certs_(new net::CertificateList),
56 weak_factory_(this) { 102 weak_factory_(this) {}
57 }
58 103
59 CertLoader::~CertLoader() { 104 CertLoader::~CertLoader() {
60 net::CertDatabase::GetInstance()->RemoveObserver(this); 105 net::CertDatabase::GetInstance()->RemoveObserver(this);
61 } 106 }
62 107
63 void CertLoader::StartWithNSSDB(net::NSSCertDatabase* database) { 108 void CertLoader::StartWithNSSDB(net::NSSCertDatabase* database) {
64 CHECK(!database_); 109 CHECK(!database_);
65 database_ = database; 110 database_ = database;
66 111
67 // Start observing cert database for changes. 112 // 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 154 // 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 155 // is shared between a certificate and its associated private and public
111 // keys. I tried to implement this with PK11_GetLowLevelKeyIDForCert(), 156 // keys. I tried to implement this with PK11_GetLowLevelKeyIDForCert(),
112 // but that always returns NULL on Chrome OS for me. 157 // but that always returns NULL on Chrome OS for me.
113 std::string CertLoader::GetPkcs11IdAndSlotForCert( 158 std::string CertLoader::GetPkcs11IdAndSlotForCert(
114 const net::X509Certificate& cert, 159 const net::X509Certificate& cert,
115 int* slot_id) { 160 int* slot_id) {
116 DCHECK(slot_id); 161 DCHECK(slot_id);
117 162
118 CERTCertificateStr* cert_handle = cert.os_cert_handle(); 163 CERTCertificateStr* cert_handle = cert.os_cert_handle();
119 SECKEYPrivateKey *priv_key = 164 SECKEYPrivateKey* priv_key =
120 PK11_FindKeyByAnyCert(cert_handle, NULL /* wincx */); 165 PK11_FindKeyByAnyCert(cert_handle, nullptr /* wincx */);
121 if (!priv_key) 166 if (!priv_key)
122 return std::string(); 167 return std::string();
123 168
124 *slot_id = static_cast<int>(PK11_GetSlotID(priv_key->pkcs11Slot)); 169 *slot_id = static_cast<int>(PK11_GetSlotID(priv_key->pkcs11Slot));
125 170
126 // Get the CKA_ID attribute for a key. 171 // Get the CKA_ID attribute for a key.
127 SECItem* sec_item = PK11_GetLowLevelKeyIDForPrivateKey(priv_key); 172 SECItem* sec_item = PK11_GetLowLevelKeyIDForPrivateKey(priv_key);
128 std::string pkcs11_id; 173 std::string pkcs11_id;
129 if (sec_item) { 174 if (sec_item) {
130 pkcs11_id = base::HexEncode(sec_item->data, sec_item->len); 175 pkcs11_id = base::HexEncode(sec_item->data, sec_item->len);
(...skipping 10 matching lines...) Expand all
141 186
142 if (certificates_update_running_) { 187 if (certificates_update_running_) {
143 certificates_update_required_ = true; 188 certificates_update_required_ = true;
144 return; 189 return;
145 } 190 }
146 191
147 certificates_update_running_ = true; 192 certificates_update_running_ = true;
148 certificates_update_required_ = false; 193 certificates_update_required_ = false;
149 194
150 database_->ListCerts( 195 database_->ListCerts(
151 base::Bind(&CertLoader::UpdateCertificates, weak_factory_.GetWeakPtr())); 196 base::Bind(&CertLoader::CertificatesLoaded, weak_factory_.GetWeakPtr()));
197 }
198
199 void CertLoader::CertificatesLoaded(
200 std::unique_ptr<net::CertificateList> all_certs) {
201 CHECK(thread_checker_.CalledOnValidThread());
202 VLOG(1) << "CertificatesLoaded: " << all_certs->size();
203
204 crypto::ScopedPK11Slot system_slot = database_->GetSystemSlot();
205 std::unique_ptr<net::CertificateList> system_certs =
206 base::MakeUnique<net::CertificateList>();
207 base::PostTaskWithTraitsAndReply(
208 FROM_HERE,
209 base::TaskTraits()
210 .WithShutdownBehavior(
pmarko 2017/04/25 12:10:03 I've used the same traits that were used in the re
emaxx 2017/04/25 15:15:58 Maybe you're right; to me the difference between t
pmarko 2017/04/25 16:59:57 @fdoray: Could you give advice here? We have a tas
211 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)
212 .MayBlock(),
213 base::Bind(
214 &FilterSystemTokenCertificates, base::Unretained(all_certs.get()),
215 base::Unretained(system_certs.get()), base::Passed(&system_slot)),
216 base::Bind(&CertLoader::UpdateCertificates, weak_factory_.GetWeakPtr(),
217 base::Passed(&all_certs), base::Passed(&system_certs)));
152 } 218 }
153 219
154 void CertLoader::UpdateCertificates( 220 void CertLoader::UpdateCertificates(
155 std::unique_ptr<net::CertificateList> cert_list) { 221 std::unique_ptr<net::CertificateList> all_certs,
222 std::unique_ptr<net::CertificateList> system_certs) {
156 CHECK(thread_checker_.CalledOnValidThread()); 223 CHECK(thread_checker_.CalledOnValidThread());
157 DCHECK(certificates_update_running_); 224 DCHECK(certificates_update_running_);
158 VLOG(1) << "UpdateCertificates: " << cert_list->size(); 225 VLOG(1) << "UpdateCertificates: " << all_certs->size() << " ("
226 << system_certs->size() << " on system slot)";
159 227
160 // Ignore any existing certificates. 228 // Ignore any existing certificates.
161 cert_list_ = std::move(cert_list); 229 all_certs_ = std::move(all_certs);
230 system_certs_ = std::move(system_certs);
162 231
163 bool initial_load = !certificates_loaded_; 232 bool initial_load = !certificates_loaded_;
164 certificates_loaded_ = true; 233 certificates_loaded_ = true;
165 NotifyCertificatesLoaded(initial_load); 234 NotifyCertificatesLoaded(initial_load);
166 235
167 certificates_update_running_ = false; 236 certificates_update_running_ = false;
168 if (certificates_update_required_) 237 if (certificates_update_required_)
169 LoadCertificates(); 238 LoadCertificates();
170 } 239 }
171 240
172 void CertLoader::NotifyCertificatesLoaded(bool initial_load) { 241 void CertLoader::NotifyCertificatesLoaded(bool initial_load) {
173 for (auto& observer : observers_) 242 for (auto& observer : observers_)
174 observer.OnCertificatesLoaded(*cert_list_, initial_load); 243 observer.OnCertificatesLoaded(*all_certs_, initial_load);
175 } 244 }
176 245
177 void CertLoader::OnCertDBChanged() { 246 void CertLoader::OnCertDBChanged() {
178 VLOG(1) << "OnCertDBChanged"; 247 VLOG(1) << "OnCertDBChanged";
179 LoadCertificates(); 248 LoadCertificates();
180 } 249 }
181 250
182 } // namespace chromeos 251 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698