Index: net/base/x509_certificate.cc |
diff --git a/net/base/x509_certificate.cc b/net/base/x509_certificate.cc |
index f5b28a6a2acadff141d70dcbe4521596035a1fec..9c69b4a4b4cd369b56da1abf01fd83620cf8be97 100644 |
--- a/net/base/x509_certificate.cc |
+++ b/net/base/x509_certificate.cc |
@@ -15,7 +15,9 @@ |
#include "base/histogram.h" |
#include "base/logging.h" |
#include "base/singleton.h" |
+#include "base/string_piece.h" |
#include "base/time.h" |
+#include "net/base/pem_tokenizer.h" |
namespace net { |
@@ -31,6 +33,18 @@ bool IsNullFingerprint(const SHA1Fingerprint& fingerprint) { |
return true; |
} |
+// Indicates the order to use when trying to decode binary data, which is |
+// based on (speculation) as to what will be most common -> least common |
+const X509Certificate::Format kFormatDecodePriority[] = { |
+ X509Certificate::FORMAT_SINGLE_CERTIFICATE, |
+ X509Certificate::FORMAT_PKCS7 |
+}; |
+ |
+// The PEM block header used for DER certificates |
+const char kCertificateHeader[] = "CERTIFICATE"; |
+// The PEM block header used for PKCS#7 data |
+const char kPKCS7Header[] = "PKCS7"; |
+ |
} // namespace |
// static |
@@ -186,6 +200,82 @@ X509Certificate* X509Certificate::CreateFromBytes(const char* data, |
return cert; |
} |
+CertificateList X509Certificate::CreateCertificateListFromBytes( |
+ const char* data, int length, int format) { |
+ OSCertHandles certificates; |
+ |
+ // Try each of the formats, in order of parse preference, to see if |data| |
+ // contains the binary representation of a Format. |
+ for (size_t i = 0; certificates.empty() && |
+ i < arraysize(kFormatDecodePriority); ++i) { |
+ if (format & kFormatDecodePriority[i]) |
+ certificates = CreateOSCertHandlesFromBytes(data, length, |
+ kFormatDecodePriority[i]); |
+ } |
+ |
+ // No certs were read. Check to see if it is in a PEM-encoded form. |
+ if (certificates.empty()) { |
+ base::StringPiece data_string(data, length); |
+ std::vector<std::string> pem_headers; |
+ |
+ // To maintain compatibility with NSS/Firefox, CERTIFICATE is a universally |
+ // valid PEM block header for any format. |
+ pem_headers.push_back(kCertificateHeader); |
+ if (format & FORMAT_PKCS7) |
+ pem_headers.push_back(kPKCS7Header); |
+ |
+ PEMTokenizer pem_tok(data_string, pem_headers); |
+ while (pem_tok.GetNext()) { |
+ std::string decoded(pem_tok.data()); |
+ |
+ OSCertHandle handle = NULL; |
+ if (format & FORMAT_PEM_CERT_SEQUENCE) |
+ handle = CreateOSCertHandleFromBytes(decoded.c_str(), decoded.size()); |
+ if (handle != NULL) { |
+ // Parsed a DER encoded certificate. All PEM blocks that follow must |
+ // also be DER encoded certificates wrapped inside of PEM blocks. |
+ format = FORMAT_PEM_CERT_SEQUENCE; |
+ certificates.push_back(handle); |
+ continue; |
+ } |
+ |
+ // If the first block failed to parse as a DER certificate, and |
+ // formats other than PEM are acceptable, check to see if the decoded |
+ // data is one of the accepted formats. |
+ if (format & ~FORMAT_PEM_CERT_SEQUENCE) { |
+ for (size_t i = 0; certificates.empty() && |
+ i < arraysize(kFormatDecodePriority); ++i) { |
+ if (format & kFormatDecodePriority[i]) { |
+ certificates = CreateOSCertHandlesFromBytes(decoded.c_str(), |
+ decoded.size(), kFormatDecodePriority[i]); |
+ } |
+ } |
+ } |
+ |
+ // Stop parsing after the first block for any format but a sequence of |
+ // PEM-encoded DER certificates. The case of FORMAT_PEM_CERT_SEQUENCE |
+ // is handled above, and continues processing until a certificate fails |
+ // to parse. |
+ break; |
+ } |
+ } |
+ |
+ CertificateList results; |
+ // No certificates parsed. |
+ if (certificates.empty()) |
+ return results; |
+ |
+ for (OSCertHandles::iterator it = certificates.begin(); |
+ it != certificates.end(); ++it) { |
+ X509Certificate* result = CreateFromHandle(*it, SOURCE_LONE_CERT_IMPORT, |
+ OSCertHandles()); |
+ results.push_back(scoped_refptr<X509Certificate>(result)); |
+ FreeOSCertHandle(*it); |
+ } |
+ |
+ return results; |
+} |
+ |
X509Certificate::X509Certificate(OSCertHandle cert_handle, |
Source source, |
const OSCertHandles& intermediates) |