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

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

Issue 20041002: Make CertificateHandler a proper interface of CertificateImporter. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed comments. Created 7 years, 4 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_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_constants.h" 15 #include "chromeos/network/onc/onc_constants.h"
16 #include "chromeos/network/onc/onc_utils.h" 16 #include "chromeos/network/onc/onc_utils.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 CertificateImporter::CertificateImporter(bool allow_trust_imports) 30 CertificateImporterImpl::CertificateImporterImpl() {
31 : allow_trust_imports_(allow_trust_imports) {
32 } 31 }
33 32
34 CertificateImporter::ParseResult CertificateImporter::ParseAndStoreCertificates( 33 bool CertificateImporterImpl::ImportCertificates(
34 const base::ListValue& certificates,
35 onc::ONCSource source,
36 net::CertificateList* onc_trusted_certificates) {
37 VLOG(2) << "ONC file has " << certificates.GetSize() << " certificates";
38
39 // Web trust is only granted to certificates imported by the user.
40 bool allow_trust_imports = source == onc::ONC_SOURCE_USER_IMPORT;
41 if (!ParseAndStoreCertificates(
42 allow_trust_imports, certificates, onc_trusted_certificates, NULL)) {
43 LOG(ERROR) << "Cannot parse some of the certificates in the ONC from "
44 << onc::GetSourceAsString(source);
45 return false;
46 }
47 return true;
48 }
49
50 bool CertificateImporterImpl::ParseAndStoreCertificates(
51 bool allow_trust_imports,
35 const base::ListValue& certificates, 52 const base::ListValue& certificates,
36 net::CertificateList* onc_trusted_certificates, 53 net::CertificateList* onc_trusted_certificates,
37 CertsByGUID* imported_server_and_ca_certs) { 54 CertsByGUID* imported_server_and_ca_certs) {
38 size_t successful_imports = 0; 55 bool success = true;
39 for (size_t i = 0; i < certificates.GetSize(); ++i) { 56 for (size_t i = 0; i < certificates.GetSize(); ++i) {
40 const base::DictionaryValue* certificate = NULL; 57 const base::DictionaryValue* certificate = NULL;
41 certificates.GetDictionary(i, &certificate); 58 certificates.GetDictionary(i, &certificate);
42 DCHECK(certificate != NULL); 59 DCHECK(certificate != NULL);
43 60
44 VLOG(2) << "Parsing certificate at index " << i << ": " << *certificate; 61 VLOG(2) << "Parsing certificate at index " << i << ": " << *certificate;
45 62
46 if (!ParseAndStoreCertificate(*certificate, onc_trusted_certificates, 63 if (!ParseAndStoreCertificate(allow_trust_imports,
64 *certificate,
65 onc_trusted_certificates,
47 imported_server_and_ca_certs)) { 66 imported_server_and_ca_certs)) {
67 success = false;
48 ONC_LOG_ERROR( 68 ONC_LOG_ERROR(
49 base::StringPrintf("Cannot parse certificate at index %zu", i)); 69 base::StringPrintf("Cannot parse certificate at index %zu", i));
50 } else { 70 } else {
51 VLOG(2) << "Successfully imported certificate at index " << i; 71 VLOG(2) << "Successfully imported certificate at index " << i;
52 ++successful_imports;
53 } 72 }
54 } 73 }
55 74 return success;
56 if (successful_imports == certificates.GetSize()) {
57 return IMPORT_OK;
58 } else if (successful_imports == 0) {
59 return IMPORT_FAILED;
60 } else {
61 return IMPORT_INCOMPLETE;
62 }
63 } 75 }
64 76
65 // static 77 // static
66 void CertificateImporter::ListCertsWithNickname(const std::string& label, 78 void CertificateImporterImpl::ListCertsWithNickname(const std::string& label,
67 net::CertificateList* result) { 79 net::CertificateList* result) {
68 net::CertificateList all_certs; 80 net::CertificateList all_certs;
69 net::NSSCertDatabase::GetInstance()->ListCerts(&all_certs); 81 net::NSSCertDatabase::GetInstance()->ListCerts(&all_certs);
70 result->clear(); 82 result->clear();
71 for (net::CertificateList::iterator iter = all_certs.begin(); 83 for (net::CertificateList::iterator iter = all_certs.begin();
72 iter != all_certs.end(); ++iter) { 84 iter != all_certs.end(); ++iter) {
73 if (iter->get()->os_cert_handle()->nickname) { 85 if (iter->get()->os_cert_handle()->nickname) {
74 // Separate the nickname stored in the certificate at the colon, since 86 // Separate the nickname stored in the certificate at the colon, since
75 // NSS likes to store it as token:nickname. 87 // NSS likes to store it as token:nickname.
76 const char* delimiter = 88 const char* delimiter =
(...skipping 17 matching lines...) Expand all
94 char* private_key_nickname = PK11_GetPrivateKeyNickname(private_key); 106 char* private_key_nickname = PK11_GetPrivateKeyNickname(private_key);
95 if (private_key_nickname && std::string(label) == private_key_nickname) 107 if (private_key_nickname && std::string(label) == private_key_nickname)
96 result->push_back(*iter); 108 result->push_back(*iter);
97 PORT_Free(private_key_nickname); 109 PORT_Free(private_key_nickname);
98 SECKEY_DestroyPrivateKey(private_key); 110 SECKEY_DestroyPrivateKey(private_key);
99 } 111 }
100 } 112 }
101 } 113 }
102 114
103 // static 115 // static
104 bool CertificateImporter::DeleteCertAndKeyByNickname(const std::string& label) { 116 bool CertificateImporterImpl::DeleteCertAndKeyByNickname(
117 const std::string& label) {
105 net::CertificateList cert_list; 118 net::CertificateList cert_list;
106 ListCertsWithNickname(label, &cert_list); 119 ListCertsWithNickname(label, &cert_list);
107 bool result = true; 120 bool result = true;
108 for (net::CertificateList::iterator iter = cert_list.begin(); 121 for (net::CertificateList::iterator iter = cert_list.begin();
109 iter != cert_list.end(); ++iter) { 122 iter != cert_list.end(); ++iter) {
110 // If we fail, we try and delete the rest still. 123 // If we fail, we try and delete the rest still.
111 // TODO(gspencer): this isn't very "transactional". If we fail on some, but 124 // TODO(gspencer): this isn't very "transactional". If we fail on some, but
112 // not all, then it's possible to leave things in a weird state. 125 // not all, then it's possible to leave things in a weird state.
113 // Luckily there should only be one cert with a particular 126 // Luckily there should only be one cert with a particular
114 // label, and the cert not being found is one of the few reasons the 127 // label, and the cert not being found is one of the few reasons the
115 // delete could fail, but still... The other choice is to return 128 // delete could fail, but still... The other choice is to return
116 // failure immediately, but that doesn't seem to do what is intended. 129 // failure immediately, but that doesn't seem to do what is intended.
117 if (!net::NSSCertDatabase::GetInstance()->DeleteCertAndKey(iter->get())) 130 if (!net::NSSCertDatabase::GetInstance()->DeleteCertAndKey(iter->get()))
118 result = false; 131 result = false;
119 } 132 }
120 return result; 133 return result;
121 } 134 }
122 135
123 bool CertificateImporter::ParseAndStoreCertificate( 136 bool CertificateImporterImpl::ParseAndStoreCertificate(
137 bool allow_trust_imports,
124 const base::DictionaryValue& certificate, 138 const base::DictionaryValue& certificate,
125 net::CertificateList* onc_trusted_certificates, 139 net::CertificateList* onc_trusted_certificates,
126 CertsByGUID* imported_server_and_ca_certs) { 140 CertsByGUID* imported_server_and_ca_certs) {
127 // Get out the attributes of the given certificate. 141 // Get out the attributes of the given certificate.
128 std::string guid; 142 std::string guid;
129 certificate.GetStringWithoutPathExpansion(certificate::kGUID, &guid); 143 certificate.GetStringWithoutPathExpansion(certificate::kGUID, &guid);
130 DCHECK(!guid.empty()); 144 DCHECK(!guid.empty());
131 145
132 bool remove = false; 146 bool remove = false;
133 if (certificate.GetBooleanWithoutPathExpansion(kRemove, &remove) && remove) { 147 if (certificate.GetBooleanWithoutPathExpansion(kRemove, &remove) && remove) {
134 if (!DeleteCertAndKeyByNickname(guid)) { 148 if (!DeleteCertAndKeyByNickname(guid)) {
135 ONC_LOG_ERROR("Unable to delete certificate"); 149 ONC_LOG_ERROR("Unable to delete certificate");
136 return false; 150 return false;
137 } else { 151 } else {
138 return true; 152 return true;
139 } 153 }
140 } 154 }
141 155
142 // Not removing, so let's get the data we need to add this certificate. 156 // Not removing, so let's get the data we need to add this certificate.
143 std::string cert_type; 157 std::string cert_type;
144 certificate.GetStringWithoutPathExpansion(certificate::kType, &cert_type); 158 certificate.GetStringWithoutPathExpansion(certificate::kType, &cert_type);
145 if (cert_type == certificate::kServer || 159 if (cert_type == certificate::kServer ||
146 cert_type == certificate::kAuthority) { 160 cert_type == certificate::kAuthority) {
147 return ParseServerOrCaCertificate(cert_type, guid, certificate, 161 return ParseServerOrCaCertificate(allow_trust_imports,
162 cert_type,
163 guid,
164 certificate,
148 onc_trusted_certificates, 165 onc_trusted_certificates,
149 imported_server_and_ca_certs); 166 imported_server_and_ca_certs);
150 } else if (cert_type == certificate::kClient) { 167 } else if (cert_type == certificate::kClient) {
151 return ParseClientCertificate(guid, certificate); 168 return ParseClientCertificate(guid, certificate);
152 } 169 }
153 170
154 NOTREACHED(); 171 NOTREACHED();
155 return false; 172 return false;
156 } 173 }
157 174
158 bool CertificateImporter::ParseServerOrCaCertificate( 175 bool CertificateImporterImpl::ParseServerOrCaCertificate(
176 bool allow_trust_imports,
159 const std::string& cert_type, 177 const std::string& cert_type,
160 const std::string& guid, 178 const std::string& guid,
161 const base::DictionaryValue& certificate, 179 const base::DictionaryValue& certificate,
162 net::CertificateList* onc_trusted_certificates, 180 net::CertificateList* onc_trusted_certificates,
163 CertsByGUID* imported_server_and_ca_certs) { 181 CertsByGUID* imported_server_and_ca_certs) {
164 bool web_trust_flag = false; 182 bool web_trust_flag = false;
165 const base::ListValue* trust_list = NULL; 183 const base::ListValue* trust_list = NULL;
166 if (certificate.GetListWithoutPathExpansion(certificate::kTrustBits, 184 if (certificate.GetListWithoutPathExpansion(certificate::kTrustBits,
167 &trust_list)) { 185 &trust_list)) {
168 for (base::ListValue::const_iterator it = trust_list->begin(); 186 for (base::ListValue::const_iterator it = trust_list->begin();
(...skipping 10 matching lines...) Expand all
179 // Trust bits should only increase trust and never restrict. Thus, 197 // Trust bits should only increase trust and never restrict. Thus,
180 // ignoring unknown bits should be safe. 198 // ignoring unknown bits should be safe.
181 ONC_LOG_WARNING("Certificate contains unknown trust type " + 199 ONC_LOG_WARNING("Certificate contains unknown trust type " +
182 trust_type); 200 trust_type);
183 } 201 }
184 } 202 }
185 } 203 }
186 204
187 bool import_with_ssl_trust = false; 205 bool import_with_ssl_trust = false;
188 if (web_trust_flag) { 206 if (web_trust_flag) {
189 if (!allow_trust_imports_) 207 if (!allow_trust_imports)
190 ONC_LOG_WARNING("Web trust not granted for certificate: " + guid); 208 ONC_LOG_WARNING("Web trust not granted for certificate: " + guid);
191 else 209 else
192 import_with_ssl_trust = true; 210 import_with_ssl_trust = true;
193 } 211 }
194 212
195 std::string x509_data; 213 std::string x509_data;
196 if (!certificate.GetStringWithoutPathExpansion(certificate::kX509, 214 if (!certificate.GetStringWithoutPathExpansion(certificate::kX509,
197 &x509_data) || 215 &x509_data) ||
198 x509_data.empty()) { 216 x509_data.empty()) {
199 ONC_LOG_ERROR( 217 ONC_LOG_ERROR(
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 281
264 if (web_trust_flag && onc_trusted_certificates) 282 if (web_trust_flag && onc_trusted_certificates)
265 onc_trusted_certificates->push_back(x509_cert); 283 onc_trusted_certificates->push_back(x509_cert);
266 284
267 if (imported_server_and_ca_certs) 285 if (imported_server_and_ca_certs)
268 (*imported_server_and_ca_certs)[guid] = x509_cert; 286 (*imported_server_and_ca_certs)[guid] = x509_cert;
269 287
270 return true; 288 return true;
271 } 289 }
272 290
273 bool CertificateImporter::ParseClientCertificate( 291 bool CertificateImporterImpl::ParseClientCertificate(
274 const std::string& guid, 292 const std::string& guid,
275 const base::DictionaryValue& certificate) { 293 const base::DictionaryValue& certificate) {
276 std::string pkcs12_data; 294 std::string pkcs12_data;
277 if (!certificate.GetStringWithoutPathExpansion(certificate::kPKCS12, 295 if (!certificate.GetStringWithoutPathExpansion(certificate::kPKCS12,
278 &pkcs12_data) || 296 &pkcs12_data) ||
279 pkcs12_data.empty()) { 297 pkcs12_data.empty()) {
280 ONC_LOG_ERROR("PKCS12 data is missing for client certificate."); 298 ONC_LOG_ERROR("PKCS12 data is missing for client certificate.");
281 return false; 299 return false;
282 } 300 }
283 301
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 PK11_SetPrivateKeyNickname(private_key, const_cast<char*>(guid.c_str())); 342 PK11_SetPrivateKeyNickname(private_key, const_cast<char*>(guid.c_str()));
325 SECKEY_DestroyPrivateKey(private_key); 343 SECKEY_DestroyPrivateKey(private_key);
326 } else { 344 } else {
327 ONC_LOG_WARNING("Unable to find private key for certificate."); 345 ONC_LOG_WARNING("Unable to find private key for certificate.");
328 } 346 }
329 return true; 347 return true;
330 } 348 }
331 349
332 } // namespace onc 350 } // namespace onc
333 } // namespace chromeos 351 } // 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