diff options
author | rsleevi@chromium.org <rsleevi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-22 02:31:04 +0000 |
---|---|---|
committer | rsleevi@chromium.org <rsleevi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-22 02:31:04 +0000 |
commit | e5a3eef63bed48a362ea5aa06b88559f7ad34d11 (patch) | |
tree | 137e336deffa52503326bfd77faa276523d2036e /net/base/x509_certificate_nss.cc | |
parent | 7349c6b146c267b7f634d518296f631642ef7095 (diff) | |
download | chromium_src-e5a3eef63bed48a362ea5aa06b88559f7ad34d11.zip chromium_src-e5a3eef63bed48a362ea5aa06b88559f7ad34d11.tar.gz chromium_src-e5a3eef63bed48a362ea5aa06b88559f7ad34d11.tar.bz2 |
Add support for parsing certificate formats other than raw, DER-encoded certificates - specifically formats that represent collections of certificates. The certificate format can now be specified as an explicit format, or as a bit-mask of formats that are acceptable/expected, with the first parsable format winning.
This is one half of a commit to address BUG #37142, with the second half involving connecting this through the X509UserCertHandler and the actual UI.
R=wtc
BUG=37142
TEST=X509CertificateParseTest* and PEMTokenizerTest.*
Review URL: http://codereview.chromium.org/2819018
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@53298 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base/x509_certificate_nss.cc')
-rw-r--r-- | net/base/x509_certificate_nss.cc | 71 |
1 files changed, 63 insertions, 8 deletions
diff --git a/net/base/x509_certificate_nss.cc b/net/base/x509_certificate_nss.cc index 8eb337f..07bfeb3 100644 --- a/net/base/x509_certificate_nss.cc +++ b/net/base/x509_certificate_nss.cc @@ -16,6 +16,7 @@ #include "base/logging.h" #include "base/pickle.h" +#include "base/scoped_ptr.h" #include "base/time.h" #include "base/nss_util.h" #include "net/base/cert_status_flags.h" @@ -571,6 +572,22 @@ bool CheckCertPolicies(X509Certificate::OSCertHandle cert_handle, return false; } +SECStatus PR_CALLBACK +CollectCertsCallback(void* arg, SECItem** certs, int num_certs) { + X509Certificate::OSCertHandles* results = + reinterpret_cast<X509Certificate::OSCertHandles*>(arg); + + for (int i = 0; i < num_certs; ++i) { + X509Certificate::OSCertHandle handle = + X509Certificate::CreateOSCertHandleFromBytes( + reinterpret_cast<char*>(certs[i]->data), certs[i]->len); + if (handle) + results->push_back(handle); + } + + return SECSuccess; +} + } // namespace void X509Certificate::Initialize() { @@ -721,21 +738,59 @@ bool X509Certificate::VerifyEV() const { // static X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( const char* data, int length) { + if (length < 0) + return NULL; + base::EnsureNSSInit(); if (!NSS_IsInitialized()) return NULL; - // Make a copy of |data| since CERT_DecodeCertPackage might modify it. - char* data_copy = new char[length]; - memcpy(data_copy, data, length); + SECItem der_cert; + der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(data)); + der_cert.len = length; + der_cert.type = siDERCertBuffer; // Parse into a certificate structure. - CERTCertificate* cert = CERT_DecodeCertFromPackage(data_copy, length); - delete [] data_copy; - if (!cert) - LOG(ERROR) << "Couldn't parse a certificate from " << length << " bytes"; - return cert; + return CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &der_cert, NULL, + PR_FALSE, PR_TRUE); +} + +// static +X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( + const char* data, int length, Format format) { + OSCertHandles results; + if (length < 0) + return results; + + base::EnsureNSSInit(); + + if (!NSS_IsInitialized()) + return results; + + switch (format) { + case FORMAT_SINGLE_CERTIFICATE: { + OSCertHandle handle = CreateOSCertHandleFromBytes(data, length); + if (handle) + results.push_back(handle); + break; + } + case FORMAT_PKCS7: { + // Make a copy since CERT_DecodeCertPackage may modify it + std::vector<char> data_copy(data, data + length); + + SECStatus result = CERT_DecodeCertPackage(&data_copy[0], + length, CollectCertsCallback, &results); + if (result != SECSuccess) + results.clear(); + break; + } + default: + NOTREACHED() << "Certificate format " << format << " unimplemented"; + break; + } + + return results; } // static |