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

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

Issue 13532005: Added a PolicyCertVerifier that uses the trust anchors from the ONC policies. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: skip tests when NSS version is too old Created 7 years, 8 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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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.h" 5 #include "chromeos/network/onc/onc_certificate_importer.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
(...skipping 16 matching lines...) Expand all
27 // The PEM block header used for DER certificates 27 // The PEM block header used for DER certificates
28 const char kCertificateHeader[] = "CERTIFICATE"; 28 const char kCertificateHeader[] = "CERTIFICATE";
29 // This is an older PEM marker for DER certificates. 29 // This is an older PEM marker for DER certificates.
30 const char kX509CertificateHeader[] = "X509 CERTIFICATE"; 30 const char kX509CertificateHeader[] = "X509 CERTIFICATE";
31 31
32 } // namespace 32 } // namespace
33 33
34 namespace chromeos { 34 namespace chromeos {
35 namespace onc { 35 namespace onc {
36 36
37 CertificateImporter::CertificateImporter(bool allow_web_trust) 37 CertificateImporter::CertificateImporter(bool allow_trust_imports)
38 : allow_web_trust_(allow_web_trust) { 38 : allow_trust_imports_(allow_trust_imports) {
39 } 39 }
40 40
41 CertificateImporter::ParseResult CertificateImporter::ParseAndStoreCertificates( 41 CertificateImporter::ParseResult CertificateImporter::ParseAndStoreCertificates(
42 const base::ListValue& certificates) { 42 const base::ListValue& certificates,
43 net::CertificateList* onc_trusted_certificates) {
43 size_t successful_imports = 0; 44 size_t successful_imports = 0;
44 for (size_t i = 0; i < certificates.GetSize(); ++i) { 45 for (size_t i = 0; i < certificates.GetSize(); ++i) {
45 const base::DictionaryValue* certificate = NULL; 46 const base::DictionaryValue* certificate = NULL;
46 certificates.GetDictionary(i, &certificate); 47 certificates.GetDictionary(i, &certificate);
47 DCHECK(certificate != NULL); 48 DCHECK(certificate != NULL);
48 49
49 VLOG(2) << "Parsing certificate at index " << i << ": " << *certificate; 50 VLOG(2) << "Parsing certificate at index " << i << ": " << *certificate;
50 51
51 if (!ParseAndStoreCertificate(*certificate)) { 52 if (!ParseAndStoreCertificate(*certificate, onc_trusted_certificates)) {
52 ONC_LOG_ERROR( 53 ONC_LOG_ERROR(
53 base::StringPrintf("Cannot parse certificate at index %zu", i)); 54 base::StringPrintf("Cannot parse certificate at index %zu", i));
54 } else { 55 } else {
55 VLOG(2) << "Successfully imported certificate at index " << i; 56 VLOG(2) << "Successfully imported certificate at index " << i;
56 ++successful_imports; 57 ++successful_imports;
57 } 58 }
58 } 59 }
59 60
60 if (successful_imports == certificates.GetSize()) { 61 if (successful_imports == certificates.GetSize()) {
61 return IMPORT_OK; 62 return IMPORT_OK;
62 } else if (successful_imports == 0) { 63 } else if (successful_imports == 0) {
63 return IMPORT_FAILED; 64 return IMPORT_FAILED;
64 } else { 65 } else {
65 return IMPORT_INCOMPLETE; 66 return IMPORT_INCOMPLETE;
66 } 67 }
67 } 68 }
68 69
69 bool CertificateImporter::ParseAndStoreCertificate(
70 const base::DictionaryValue& certificate) {
71 // Get out the attributes of the given certificate.
72 std::string guid;
73 certificate.GetString(certificate::kGUID, &guid);
74 DCHECK(!guid.empty());
75
76 bool remove = false;
77 if (certificate.GetBoolean(kRemove, &remove) && remove) {
78 if (!DeleteCertAndKeyByNickname(guid)) {
79 ONC_LOG_ERROR("Unable to delete certificate");
80 return false;
81 } else {
82 return true;
83 }
84 }
85
86 // Not removing, so let's get the data we need to add this certificate.
87 std::string cert_type;
88 certificate.GetString(certificate::kType, &cert_type);
89 if (cert_type == certificate::kServer ||
90 cert_type == certificate::kAuthority) {
91 return ParseServerOrCaCertificate(cert_type, guid, certificate);
92 } else if (cert_type == certificate::kClient) {
93 return ParseClientCertificate(guid, certificate);
94 }
95
96 NOTREACHED();
97 return false;
98 }
99
100 // static 70 // static
101 void CertificateImporter::ListCertsWithNickname(const std::string& label, 71 void CertificateImporter::ListCertsWithNickname(const std::string& label,
102 net::CertificateList* result) { 72 net::CertificateList* result) {
103 net::CertificateList all_certs; 73 net::CertificateList all_certs;
104 net::NSSCertDatabase::GetInstance()->ListCerts(&all_certs); 74 net::NSSCertDatabase::GetInstance()->ListCerts(&all_certs);
105 result->clear(); 75 result->clear();
106 for (net::CertificateList::iterator iter = all_certs.begin(); 76 for (net::CertificateList::iterator iter = all_certs.begin();
107 iter != all_certs.end(); ++iter) { 77 iter != all_certs.end(); ++iter) {
108 if (iter->get()->os_cert_handle()->nickname) { 78 if (iter->get()->os_cert_handle()->nickname) {
109 // Separate the nickname stored in the certificate at the colon, since 79 // Separate the nickname stored in the certificate at the colon, since
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
148 // Luckily there should only be one cert with a particular 118 // Luckily there should only be one cert with a particular
149 // label, and the cert not being found is one of the few reasons the 119 // label, and the cert not being found is one of the few reasons the
150 // delete could fail, but still... The other choice is to return 120 // delete could fail, but still... The other choice is to return
151 // failure immediately, but that doesn't seem to do what is intended. 121 // failure immediately, but that doesn't seem to do what is intended.
152 if (!net::NSSCertDatabase::GetInstance()->DeleteCertAndKey(iter->get())) 122 if (!net::NSSCertDatabase::GetInstance()->DeleteCertAndKey(iter->get()))
153 result = false; 123 result = false;
154 } 124 }
155 return result; 125 return result;
156 } 126 }
157 127
128 bool CertificateImporter::ParseAndStoreCertificate(
129 const base::DictionaryValue& certificate,
130 net::CertificateList* onc_trusted_certificates) {
131 // Get out the attributes of the given certificate.
132 std::string guid;
133 certificate.GetString(certificate::kGUID, &guid);
134 DCHECK(!guid.empty());
135
136 bool remove = false;
137 if (certificate.GetBoolean(kRemove, &remove) && remove) {
138 if (!DeleteCertAndKeyByNickname(guid)) {
139 ONC_LOG_ERROR("Unable to delete certificate");
140 return false;
141 } else {
142 return true;
143 }
144 }
145
146 // Not removing, so let's get the data we need to add this certificate.
147 std::string cert_type;
148 certificate.GetString(certificate::kType, &cert_type);
149 if (cert_type == certificate::kServer ||
150 cert_type == certificate::kAuthority) {
151 return ParseServerOrCaCertificate(
152 cert_type, guid, certificate, onc_trusted_certificates);
153 } else if (cert_type == certificate::kClient) {
154 return ParseClientCertificate(guid, certificate);
155 }
156
157 NOTREACHED();
158 return false;
159 }
160
158 bool CertificateImporter::ParseServerOrCaCertificate( 161 bool CertificateImporter::ParseServerOrCaCertificate(
159 const std::string& cert_type, 162 const std::string& cert_type,
160 const std::string& guid, 163 const std::string& guid,
161 const base::DictionaryValue& certificate) { 164 const base::DictionaryValue& certificate,
162 bool web_trust = false; 165 net::CertificateList* onc_trusted_certificates) {
166 bool web_trust_flag = false;
163 const base::ListValue* trust_list = NULL; 167 const base::ListValue* trust_list = NULL;
164 if (certificate.GetList(certificate::kTrust, &trust_list)) { 168 if (certificate.GetList(certificate::kTrust, &trust_list)) {
165 for (size_t i = 0; i < trust_list->GetSize(); ++i) { 169 for (size_t i = 0; i < trust_list->GetSize(); ++i) {
166 std::string trust_type; 170 std::string trust_type;
167 if (!trust_list->GetString(i, &trust_type)) 171 if (!trust_list->GetString(i, &trust_type))
168 NOTREACHED(); 172 NOTREACHED();
169 173
170 if (trust_type == certificate::kWeb) { 174 if (trust_type == certificate::kWeb) {
171 // "Web" implies that the certificate is to be trusted for SSL 175 // "Web" implies that the certificate is to be trusted for SSL
172 // identification. 176 // identification.
173 web_trust = true; 177 web_trust_flag = true;
174 } else { 178 } else {
175 ONC_LOG_ERROR("Certificate contains unknown trust type " + trust_type); 179 ONC_LOG_ERROR("Certificate contains unknown trust type " + trust_type);
176 return false; 180 return false;
177 } 181 }
178 } 182 }
179 } 183 }
180 184
181 if (web_trust && !allow_web_trust_) { 185 bool import_with_ssl_trust = false;
182 LOG(WARNING) << "Web trust not granted for certificate: " << guid; 186 if (web_trust_flag) {
183 web_trust = false; 187 if (!allow_trust_imports_)
188 LOG(WARNING) << "Web trust not granted for certificate: " << guid;
189 else
190 import_with_ssl_trust = true;
184 } 191 }
185 192
186 std::string x509_data; 193 std::string x509_data;
187 if (!certificate.GetString(certificate::kX509, &x509_data) || 194 if (!certificate.GetString(certificate::kX509, &x509_data) ||
188 x509_data.empty()) { 195 x509_data.empty()) {
189 ONC_LOG_ERROR( 196 ONC_LOG_ERROR(
190 "Certificate missing appropriate certificate data for type: " + 197 "Certificate missing appropriate certificate data for type: " +
191 cert_type); 198 cert_type);
192 return false; 199 return false;
193 } 200 }
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
269 ListCertsWithNickname(guid, &certs); 276 ListCertsWithNickname(guid, &certs);
270 if (!certs.empty()) { 277 if (!certs.empty()) {
271 ONC_LOG_ERROR("Certificate GUID is already in use: " + guid); 278 ONC_LOG_ERROR("Certificate GUID is already in use: " + guid);
272 return false; 279 return false;
273 } 280 }
274 281
275 net::CertificateList cert_list; 282 net::CertificateList cert_list;
276 cert_list.push_back(x509_cert); 283 cert_list.push_back(x509_cert);
277 net::NSSCertDatabase::ImportCertFailureList failures; 284 net::NSSCertDatabase::ImportCertFailureList failures;
278 bool success = false; 285 bool success = false;
279 net::NSSCertDatabase::TrustBits trust = web_trust ? 286 net::NSSCertDatabase::TrustBits trust = import_with_ssl_trust ?
280 net::NSSCertDatabase::TRUSTED_SSL : 287 net::NSSCertDatabase::TRUSTED_SSL :
281 net::NSSCertDatabase::TRUST_DEFAULT; 288 net::NSSCertDatabase::TRUST_DEFAULT;
282 if (cert_type == certificate::kServer) { 289 if (cert_type == certificate::kServer) {
283 success = cert_database->ImportServerCert(cert_list, trust, &failures); 290 success = cert_database->ImportServerCert(cert_list, trust, &failures);
284 } else { // Authority cert 291 } else { // Authority cert
285 success = cert_database->ImportCACerts(cert_list, trust, &failures); 292 success = cert_database->ImportCACerts(cert_list, trust, &failures);
286 } 293 }
287 294
288 if (!failures.empty()) { 295 if (!failures.empty()) {
289 ONC_LOG_ERROR("Error (" + net::ErrorToString(failures[0].net_error) + 296 ONC_LOG_ERROR("Error (" + net::ErrorToString(failures[0].net_error) +
290 ") importing " + cert_type + " certificate"); 297 ") importing " + cert_type + " certificate");
291 return false; 298 return false;
292 } 299 }
293 if (!success) { 300 if (!success) {
294 ONC_LOG_ERROR("Unknown error importing " + cert_type + " certificate."); 301 ONC_LOG_ERROR("Unknown error importing " + cert_type + " certificate.");
295 return false; 302 return false;
296 } 303 }
297 304
305 if (web_trust_flag && onc_trusted_certificates)
306 onc_trusted_certificates->push_back(x509_cert);
307
298 return true; 308 return true;
299 } 309 }
300 310
301 bool CertificateImporter::ParseClientCertificate( 311 bool CertificateImporter::ParseClientCertificate(
302 const std::string& guid, 312 const std::string& guid,
303 const base::DictionaryValue& certificate) { 313 const base::DictionaryValue& certificate) {
304 std::string pkcs12_data; 314 std::string pkcs12_data;
305 if (!certificate.GetString(certificate::kPKCS12, &pkcs12_data) || 315 if (!certificate.GetString(certificate::kPKCS12, &pkcs12_data) ||
306 pkcs12_data.empty()) { 316 pkcs12_data.empty()) {
307 ONC_LOG_ERROR("PKCS12 data is missing for client certificate."); 317 ONC_LOG_ERROR("PKCS12 data is missing for client certificate.");
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
350 PK11_SetPrivateKeyNickname(private_key, const_cast<char*>(guid.c_str())); 360 PK11_SetPrivateKeyNickname(private_key, const_cast<char*>(guid.c_str()));
351 SECKEY_DestroyPrivateKey(private_key); 361 SECKEY_DestroyPrivateKey(private_key);
352 } else { 362 } else {
353 ONC_LOG_WARNING("Unable to find private key for certificate."); 363 ONC_LOG_WARNING("Unable to find private key for certificate.");
354 } 364 }
355 return true; 365 return true;
356 } 366 }
357 367
358 } // namespace onc 368 } // namespace onc
359 } // namespace chromeos 369 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698