OLD | NEW |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |