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

Side by Side Diff: chromeos/network/onc/onc_certificate_importer_impl.cc

Issue 148183013: Use per-user nssdb in onc certificate importer (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix browser_tests compile Created 6 years, 10 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 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/network/onc/onc_certificate_importer_impl.h" 5 #include "chromeos/network/onc/onc_certificate_importer_impl.h"
6 6
7 #include <cert.h> 7 #include <cert.h>
8 #include <keyhi.h> 8 #include <keyhi.h>
9 #include <pk11pub.h> 9 #include <pk11pub.h>
10 10
11 #include "base/base64.h" 11 #include "base/base64.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/values.h" 13 #include "base/values.h"
14 #include "chromeos/network/network_event_log.h" 14 #include "chromeos/network/network_event_log.h"
15 #include "chromeos/network/onc/onc_utils.h" 15 #include "chromeos/network/onc/onc_utils.h"
16 #include "components/onc/onc_constants.h" 16 #include "components/onc/onc_constants.h"
17 #include "net/base/crypto_module.h" 17 #include "net/base/crypto_module.h"
18 #include "net/base/net_errors.h" 18 #include "net/base/net_errors.h"
19 #include "net/cert/nss_cert_database.h" 19 #include "net/cert/nss_cert_database.h"
20 #include "net/cert/x509_certificate.h" 20 #include "net/cert/x509_certificate.h"
21 21
22 #define ONC_LOG_WARNING(message) \ 22 #define ONC_LOG_WARNING(message) \
23 NET_LOG_DEBUG("ONC Certificate Import Warning", message) 23 NET_LOG_DEBUG("ONC Certificate Import Warning", message)
24 #define ONC_LOG_ERROR(message) \ 24 #define ONC_LOG_ERROR(message) \
25 NET_LOG_ERROR("ONC Certificate Import Error", message) 25 NET_LOG_ERROR("ONC Certificate Import Error", message)
26 26
27 namespace chromeos { 27 namespace chromeos {
28 namespace onc { 28 namespace onc {
29 29
30 CertificateImporterImpl::CertificateImporterImpl() { 30 CertificateImporterImpl::CertificateImporterImpl(
31 net::NSSCertDatabase* target_nssdb)
32 : target_nssdb_(target_nssdb) {
33 CHECK(target_nssdb);
31 } 34 }
32 35
33 bool CertificateImporterImpl::ImportCertificates( 36 bool CertificateImporterImpl::ImportCertificates(
34 const base::ListValue& certificates, 37 const base::ListValue& certificates,
35 ::onc::ONCSource source, 38 ::onc::ONCSource source,
36 net::CertificateList* onc_trusted_certificates) { 39 net::CertificateList* onc_trusted_certificates) {
37 VLOG(2) << "ONC file has " << certificates.GetSize() << " certificates"; 40 VLOG(2) << "ONC file has " << certificates.GetSize() << " certificates";
38 41
39 // Web trust is only granted to certificates imported by the user. 42 // Web trust is only granted to certificates imported by the user.
40 bool allow_trust_imports = source == ::onc::ONC_SOURCE_USER_IMPORT; 43 bool allow_trust_imports = source == ::onc::ONC_SOURCE_USER_IMPORT;
41 if (!ParseAndStoreCertificates( 44 if (!ParseAndStoreCertificates(allow_trust_imports,
42 allow_trust_imports, certificates, onc_trusted_certificates, NULL)) { 45 certificates,
46 onc_trusted_certificates,
47 NULL)) {
43 LOG(ERROR) << "Cannot parse some of the certificates in the ONC from " 48 LOG(ERROR) << "Cannot parse some of the certificates in the ONC from "
44 << onc::GetSourceAsString(source); 49 << onc::GetSourceAsString(source);
45 return false; 50 return false;
46 } 51 }
47 return true; 52 return true;
48 } 53 }
49 54
50 bool CertificateImporterImpl::ParseAndStoreCertificates( 55 bool CertificateImporterImpl::ParseAndStoreCertificates(
51 bool allow_trust_imports, 56 bool allow_trust_imports,
52 const base::ListValue& certificates, 57 const base::ListValue& certificates,
(...skipping 15 matching lines...) Expand all
68 ONC_LOG_ERROR( 73 ONC_LOG_ERROR(
69 base::StringPrintf("Cannot parse certificate at index %zu", i)); 74 base::StringPrintf("Cannot parse certificate at index %zu", i));
70 } else { 75 } else {
71 VLOG(2) << "Successfully imported certificate at index " << i; 76 VLOG(2) << "Successfully imported certificate at index " << i;
72 } 77 }
73 } 78 }
74 return success; 79 return success;
75 } 80 }
76 81
77 // static 82 // static
78 void CertificateImporterImpl::ListCertsWithNickname(const std::string& label, 83 void CertificateImporterImpl::ListCertsWithNickname(
79 net::CertificateList* result) { 84 const std::string& label,
85 net::CertificateList* result,
86 net::NSSCertDatabase* target_nssdb) {
80 net::CertificateList all_certs; 87 net::CertificateList all_certs;
81 // TODO(tbarzic): Use async |ListCerts|. 88 // TODO(tbarzic): Use async |ListCerts|.
82 net::NSSCertDatabase::GetInstance()->ListCertsSync(&all_certs); 89 target_nssdb->ListCertsSync(&all_certs);
83 result->clear(); 90 result->clear();
84 for (net::CertificateList::iterator iter = all_certs.begin(); 91 for (net::CertificateList::iterator iter = all_certs.begin();
85 iter != all_certs.end(); ++iter) { 92 iter != all_certs.end(); ++iter) {
86 if (iter->get()->os_cert_handle()->nickname) { 93 if (iter->get()->os_cert_handle()->nickname) {
87 // Separate the nickname stored in the certificate at the colon, since 94 // Separate the nickname stored in the certificate at the colon, since
88 // NSS likes to store it as token:nickname. 95 // NSS likes to store it as token:nickname.
89 const char* delimiter = 96 const char* delimiter =
90 ::strchr(iter->get()->os_cert_handle()->nickname, ':'); 97 ::strchr(iter->get()->os_cert_handle()->nickname, ':');
91 if (delimiter) { 98 if (delimiter) {
92 ++delimiter; // move past the colon. 99 ++delimiter; // move past the colon.
(...skipping 15 matching lines...) Expand all
108 if (private_key_nickname && std::string(label) == private_key_nickname) 115 if (private_key_nickname && std::string(label) == private_key_nickname)
109 result->push_back(*iter); 116 result->push_back(*iter);
110 PORT_Free(private_key_nickname); 117 PORT_Free(private_key_nickname);
111 SECKEY_DestroyPrivateKey(private_key); 118 SECKEY_DestroyPrivateKey(private_key);
112 } 119 }
113 } 120 }
114 } 121 }
115 122
116 // static 123 // static
117 bool CertificateImporterImpl::DeleteCertAndKeyByNickname( 124 bool CertificateImporterImpl::DeleteCertAndKeyByNickname(
118 const std::string& label) { 125 const std::string& label,
126 net::NSSCertDatabase* target_nssdb) {
119 net::CertificateList cert_list; 127 net::CertificateList cert_list;
120 ListCertsWithNickname(label, &cert_list); 128 ListCertsWithNickname(label, &cert_list, target_nssdb);
121 bool result = true; 129 bool result = true;
122 for (net::CertificateList::iterator iter = cert_list.begin(); 130 for (net::CertificateList::iterator iter = cert_list.begin();
123 iter != cert_list.end(); ++iter) { 131 iter != cert_list.end(); ++iter) {
124 // If we fail, we try and delete the rest still. 132 // If we fail, we try and delete the rest still.
125 // TODO(gspencer): this isn't very "transactional". If we fail on some, but 133 // TODO(gspencer): this isn't very "transactional". If we fail on some, but
126 // not all, then it's possible to leave things in a weird state. 134 // not all, then it's possible to leave things in a weird state.
127 // Luckily there should only be one cert with a particular 135 // Luckily there should only be one cert with a particular
128 // label, and the cert not being found is one of the few reasons the 136 // label, and the cert not being found is one of the few reasons the
129 // delete could fail, but still... The other choice is to return 137 // delete could fail, but still... The other choice is to return
130 // failure immediately, but that doesn't seem to do what is intended. 138 // failure immediately, but that doesn't seem to do what is intended.
131 if (!net::NSSCertDatabase::GetInstance()->DeleteCertAndKey(iter->get())) 139 if (!target_nssdb->DeleteCertAndKey(iter->get()))
132 result = false; 140 result = false;
133 } 141 }
134 return result; 142 return result;
135 } 143 }
136 144
137 bool CertificateImporterImpl::ParseAndStoreCertificate( 145 bool CertificateImporterImpl::ParseAndStoreCertificate(
138 bool allow_trust_imports, 146 bool allow_trust_imports,
139 const base::DictionaryValue& certificate, 147 const base::DictionaryValue& certificate,
140 net::CertificateList* onc_trusted_certificates, 148 net::CertificateList* onc_trusted_certificates,
141 CertsByGUID* imported_server_and_ca_certs) { 149 CertsByGUID* imported_server_and_ca_certs) {
142 // Get out the attributes of the given certificate. 150 // Get out the attributes of the given certificate.
143 std::string guid; 151 std::string guid;
144 certificate.GetStringWithoutPathExpansion(::onc::certificate::kGUID, &guid); 152 certificate.GetStringWithoutPathExpansion(::onc::certificate::kGUID, &guid);
145 DCHECK(!guid.empty()); 153 DCHECK(!guid.empty());
146 154
147 bool remove = false; 155 bool remove = false;
148 if (certificate.GetBooleanWithoutPathExpansion(::onc::kRemove, &remove) && 156 if (certificate.GetBooleanWithoutPathExpansion(::onc::kRemove, &remove) &&
149 remove) { 157 remove) {
150 if (!DeleteCertAndKeyByNickname(guid)) { 158 if (!DeleteCertAndKeyByNickname(guid, target_nssdb_)) {
151 ONC_LOG_ERROR("Unable to delete certificate"); 159 ONC_LOG_ERROR("Unable to delete certificate");
152 return false; 160 return false;
153 } else { 161 } else {
154 return true; 162 return true;
155 } 163 }
156 } 164 }
157 165
158 // Not removing, so let's get the data we need to add this certificate. 166 // Not removing, so let's get the data we need to add this certificate.
159 std::string cert_type; 167 std::string cert_type;
160 certificate.GetStringWithoutPathExpansion(::onc::certificate::kType, 168 certificate.GetStringWithoutPathExpansion(::onc::certificate::kType,
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 if (!x509_cert.get()) { 236 if (!x509_cert.get()) {
229 ONC_LOG_ERROR("Unable to create certificate from PEM encoding, type: " + 237 ONC_LOG_ERROR("Unable to create certificate from PEM encoding, type: " +
230 cert_type); 238 cert_type);
231 return false; 239 return false;
232 } 240 }
233 241
234 net::NSSCertDatabase::TrustBits trust = (import_with_ssl_trust ? 242 net::NSSCertDatabase::TrustBits trust = (import_with_ssl_trust ?
235 net::NSSCertDatabase::TRUSTED_SSL : 243 net::NSSCertDatabase::TRUSTED_SSL :
236 net::NSSCertDatabase::TRUST_DEFAULT); 244 net::NSSCertDatabase::TRUST_DEFAULT);
237 245
238 net::NSSCertDatabase* cert_database = net::NSSCertDatabase::GetInstance();
239 if (x509_cert->os_cert_handle()->isperm) { 246 if (x509_cert->os_cert_handle()->isperm) {
240 net::CertType net_cert_type = 247 net::CertType net_cert_type =
241 cert_type == ::onc::certificate::kServer ? net::SERVER_CERT 248 cert_type == ::onc::certificate::kServer ? net::SERVER_CERT
242 : net::CA_CERT; 249 : net::CA_CERT;
243 VLOG(1) << "Certificate is already installed."; 250 VLOG(1) << "Certificate is already installed.";
244 net::NSSCertDatabase::TrustBits missing_trust_bits = 251 net::NSSCertDatabase::TrustBits missing_trust_bits =
245 trust & ~cert_database->GetCertTrust(x509_cert.get(), net_cert_type); 252 trust & ~target_nssdb_->GetCertTrust(x509_cert.get(), net_cert_type);
246 if (missing_trust_bits) { 253 if (missing_trust_bits) {
247 std::string error_reason; 254 std::string error_reason;
248 bool success = false; 255 bool success = false;
249 if (cert_database->IsReadOnly(x509_cert.get())) { 256 if (target_nssdb_->IsReadOnly(x509_cert.get())) {
250 error_reason = " Certificate is stored read-only."; 257 error_reason = " Certificate is stored read-only.";
251 } else { 258 } else {
252 success = cert_database->SetCertTrust(x509_cert.get(), 259 success = target_nssdb_->SetCertTrust(x509_cert.get(),
253 net_cert_type, 260 net_cert_type,
254 trust); 261 trust);
255 } 262 }
256 if (!success) { 263 if (!success) {
257 ONC_LOG_ERROR("Certificate of type " + cert_type + 264 ONC_LOG_ERROR("Certificate of type " + cert_type +
258 " was already present, but trust couldn't be set." + 265 " was already present, but trust couldn't be set." +
259 error_reason); 266 error_reason);
260 } 267 }
261 } 268 }
262 } else { 269 } else {
263 net::CertificateList cert_list; 270 net::CertificateList cert_list;
264 cert_list.push_back(x509_cert); 271 cert_list.push_back(x509_cert);
265 net::NSSCertDatabase::ImportCertFailureList failures; 272 net::NSSCertDatabase::ImportCertFailureList failures;
266 bool success = false; 273 bool success = false;
267 if (cert_type == ::onc::certificate::kServer) 274 if (cert_type == ::onc::certificate::kServer)
268 success = cert_database->ImportServerCert(cert_list, trust, &failures); 275 success = target_nssdb_->ImportServerCert(cert_list, trust, &failures);
269 else // Authority cert 276 else // Authority cert
270 success = cert_database->ImportCACerts(cert_list, trust, &failures); 277 success = target_nssdb_->ImportCACerts(cert_list, trust, &failures);
271 278
272 if (!failures.empty()) { 279 if (!failures.empty()) {
273 ONC_LOG_ERROR( 280 ONC_LOG_ERROR(
274 base::StringPrintf("Error ( %s ) importing %s certificate", 281 base::StringPrintf("Error ( %s ) importing %s certificate",
275 net::ErrorToString(failures[0].net_error), 282 net::ErrorToString(failures[0].net_error),
276 cert_type.c_str())); 283 cert_type.c_str()));
277 return false; 284 return false;
278 } 285 }
279 286
280 if (!success) { 287 if (!success) {
(...skipping 23 matching lines...) Expand all
304 } 311 }
305 312
306 std::string decoded_pkcs12; 313 std::string decoded_pkcs12;
307 if (!base::Base64Decode(pkcs12_data, &decoded_pkcs12)) { 314 if (!base::Base64Decode(pkcs12_data, &decoded_pkcs12)) {
308 ONC_LOG_ERROR( 315 ONC_LOG_ERROR(
309 "Unable to base64 decode PKCS#12 data: \"" + pkcs12_data + "\"."); 316 "Unable to base64 decode PKCS#12 data: \"" + pkcs12_data + "\".");
310 return false; 317 return false;
311 } 318 }
312 319
313 // Since this has a private key, always use the private module. 320 // Since this has a private key, always use the private module.
314 net::NSSCertDatabase* cert_database = net::NSSCertDatabase::GetInstance(); 321 scoped_refptr<net::CryptoModule> module(net::CryptoModule::CreateFromHandle(
315 scoped_refptr<net::CryptoModule> module(cert_database->GetPrivateModule()); 322 target_nssdb_->GetPrivateSlot().get()));
316 net::CertificateList imported_certs; 323 net::CertificateList imported_certs;
317 324
318 int import_result = cert_database->ImportFromPKCS12( 325 int import_result = target_nssdb_->ImportFromPKCS12(
319 module.get(), decoded_pkcs12, base::string16(), false, &imported_certs); 326 module.get(), decoded_pkcs12, base::string16(), false, &imported_certs);
320 if (import_result != net::OK) { 327 if (import_result != net::OK) {
321 ONC_LOG_ERROR( 328 ONC_LOG_ERROR(
322 base::StringPrintf("Unable to import client certificate (error %s)", 329 base::StringPrintf("Unable to import client certificate (error %s)",
323 net::ErrorToString(import_result))); 330 net::ErrorToString(import_result)));
324 return false; 331 return false;
325 } 332 }
326 333
327 if (imported_certs.size() == 0) { 334 if (imported_certs.size() == 0) {
328 ONC_LOG_WARNING("PKCS12 data contains no importable certificates."); 335 ONC_LOG_WARNING("PKCS12 data contains no importable certificates.");
(...skipping 17 matching lines...) Expand all
346 PK11_SetPrivateKeyNickname(private_key, const_cast<char*>(guid.c_str())); 353 PK11_SetPrivateKeyNickname(private_key, const_cast<char*>(guid.c_str()));
347 SECKEY_DestroyPrivateKey(private_key); 354 SECKEY_DestroyPrivateKey(private_key);
348 } else { 355 } else {
349 ONC_LOG_WARNING("Unable to find private key for certificate."); 356 ONC_LOG_WARNING("Unable to find private key for certificate.");
350 } 357 }
351 return true; 358 return true;
352 } 359 }
353 360
354 } // namespace onc 361 } // namespace onc
355 } // namespace chromeos 362 } // namespace chromeos
OLDNEW
« no previous file with comments | « chromeos/network/onc/onc_certificate_importer_impl.h ('k') | chromeos/network/onc/onc_certificate_importer_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698