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

Side by Side Diff: net/base/x509_certificate.cc

Issue 3148034: Fix PEM parsing on Linux when using X509Certificate::FORMAT_AUTO (Closed)
Patch Set: Created 10 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
« no previous file with comments | « no previous file | net/base/x509_certificate_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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 "net/base/x509_certificate.h" 5 #include "net/base/x509_certificate.h"
6 6
7 #if defined(OS_MACOSX) 7 #if defined(OS_MACOSX)
8 #include <Security/Security.h> 8 #include <Security/Security.h>
9 #elif defined(USE_NSS) 9 #elif defined(USE_NSS)
10 #include <cert.h> 10 #include <cert.h>
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 SOURCE_LONE_CERT_IMPORT, 197 SOURCE_LONE_CERT_IMPORT,
198 OSCertHandles()); 198 OSCertHandles());
199 FreeOSCertHandle(cert_handle); 199 FreeOSCertHandle(cert_handle);
200 return cert; 200 return cert;
201 } 201 }
202 202
203 CertificateList X509Certificate::CreateCertificateListFromBytes( 203 CertificateList X509Certificate::CreateCertificateListFromBytes(
204 const char* data, int length, int format) { 204 const char* data, int length, int format) {
205 OSCertHandles certificates; 205 OSCertHandles certificates;
206 206
207 // Check to see if it is in a PEM-encoded form. This check is performed
208 // first, as both OS X and NSS will both try to convert if they detect
209 // PEM encoding, except they don't do it consistently between the two.
210 base::StringPiece data_string(data, length);
211 std::vector<std::string> pem_headers;
212
213 // To maintain compatibility with NSS/Firefox, CERTIFICATE is a universally
214 // valid PEM block header for any format.
215 pem_headers.push_back(kCertificateHeader);
216 if (format & FORMAT_PKCS7)
217 pem_headers.push_back(kPKCS7Header);
218
219 PEMTokenizer pem_tok(data_string, pem_headers);
220 while (pem_tok.GetNext()) {
221 std::string decoded(pem_tok.data());
222
223 OSCertHandle handle = NULL;
224 if (format & FORMAT_PEM_CERT_SEQUENCE)
225 handle = CreateOSCertHandleFromBytes(decoded.c_str(), decoded.size());
226 if (handle != NULL) {
227 // Parsed a DER encoded certificate. All PEM blocks that follow must
228 // also be DER encoded certificates wrapped inside of PEM blocks.
229 format = FORMAT_PEM_CERT_SEQUENCE;
230 certificates.push_back(handle);
231 continue;
232 }
233
234 // If the first block failed to parse as a DER certificate, and
235 // formats other than PEM are acceptable, check to see if the decoded
236 // data is one of the accepted formats.
237 if (format & ~FORMAT_PEM_CERT_SEQUENCE) {
238 for (size_t i = 0; certificates.empty() &&
239 i < arraysize(kFormatDecodePriority); ++i) {
240 if (format & kFormatDecodePriority[i]) {
241 certificates = CreateOSCertHandlesFromBytes(decoded.c_str(),
242 decoded.size(), kFormatDecodePriority[i]);
243 }
244 }
245 }
246
247 // Stop parsing after the first block for any format but a sequence of
248 // PEM-encoded DER certificates. The case of FORMAT_PEM_CERT_SEQUENCE
249 // is handled above, and continues processing until a certificate fails
250 // to parse.
251 break;
252 }
253
207 // Try each of the formats, in order of parse preference, to see if |data| 254 // Try each of the formats, in order of parse preference, to see if |data|
208 // contains the binary representation of a Format. 255 // contains the binary representation of a Format, if it failed to parse
256 // as a PEM certificate/chain.
209 for (size_t i = 0; certificates.empty() && 257 for (size_t i = 0; certificates.empty() &&
210 i < arraysize(kFormatDecodePriority); ++i) { 258 i < arraysize(kFormatDecodePriority); ++i) {
211 if (format & kFormatDecodePriority[i]) 259 if (format & kFormatDecodePriority[i])
212 certificates = CreateOSCertHandlesFromBytes(data, length, 260 certificates = CreateOSCertHandlesFromBytes(data, length,
213 kFormatDecodePriority[i]); 261 kFormatDecodePriority[i]);
214 } 262 }
215 263
216 // No certs were read. Check to see if it is in a PEM-encoded form.
217 if (certificates.empty()) {
218 base::StringPiece data_string(data, length);
219 std::vector<std::string> pem_headers;
220
221 // To maintain compatibility with NSS/Firefox, CERTIFICATE is a universally
222 // valid PEM block header for any format.
223 pem_headers.push_back(kCertificateHeader);
224 if (format & FORMAT_PKCS7)
225 pem_headers.push_back(kPKCS7Header);
226
227 PEMTokenizer pem_tok(data_string, pem_headers);
228 while (pem_tok.GetNext()) {
229 std::string decoded(pem_tok.data());
230
231 OSCertHandle handle = NULL;
232 if (format & FORMAT_PEM_CERT_SEQUENCE)
233 handle = CreateOSCertHandleFromBytes(decoded.c_str(), decoded.size());
234 if (handle != NULL) {
235 // Parsed a DER encoded certificate. All PEM blocks that follow must
236 // also be DER encoded certificates wrapped inside of PEM blocks.
237 format = FORMAT_PEM_CERT_SEQUENCE;
238 certificates.push_back(handle);
239 continue;
240 }
241
242 // If the first block failed to parse as a DER certificate, and
243 // formats other than PEM are acceptable, check to see if the decoded
244 // data is one of the accepted formats.
245 if (format & ~FORMAT_PEM_CERT_SEQUENCE) {
246 for (size_t i = 0; certificates.empty() &&
247 i < arraysize(kFormatDecodePriority); ++i) {
248 if (format & kFormatDecodePriority[i]) {
249 certificates = CreateOSCertHandlesFromBytes(decoded.c_str(),
250 decoded.size(), kFormatDecodePriority[i]);
251 }
252 }
253 }
254
255 // Stop parsing after the first block for any format but a sequence of
256 // PEM-encoded DER certificates. The case of FORMAT_PEM_CERT_SEQUENCE
257 // is handled above, and continues processing until a certificate fails
258 // to parse.
259 break;
260 }
261 }
262
263 CertificateList results; 264 CertificateList results;
264 // No certificates parsed. 265 // No certificates parsed.
265 if (certificates.empty()) 266 if (certificates.empty())
266 return results; 267 return results;
267 268
268 for (OSCertHandles::iterator it = certificates.begin(); 269 for (OSCertHandles::iterator it = certificates.begin();
269 it != certificates.end(); ++it) { 270 it != certificates.end(); ++it) {
270 X509Certificate* result = CreateFromHandle(*it, SOURCE_LONE_CERT_IMPORT, 271 X509Certificate* result = CreateFromHandle(*it, SOURCE_LONE_CERT_IMPORT,
271 OSCertHandles()); 272 OSCertHandles());
272 results.push_back(scoped_refptr<X509Certificate>(result)); 273 results.push_back(scoped_refptr<X509Certificate>(result));
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 333
333 bool X509Certificate::HasIntermediateCertificates(const OSCertHandles& certs) { 334 bool X509Certificate::HasIntermediateCertificates(const OSCertHandles& certs) {
334 for (size_t i = 0; i < certs.size(); ++i) { 335 for (size_t i = 0; i < certs.size(); ++i) {
335 if (!HasIntermediateCertificate(certs[i])) 336 if (!HasIntermediateCertificate(certs[i]))
336 return false; 337 return false;
337 } 338 }
338 return true; 339 return true;
339 } 340 }
340 341
341 } // namespace net 342 } // namespace net
OLDNEW
« no previous file with comments | « no previous file | net/base/x509_certificate_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698