Index: net/base/x509_certificate_nss.cc |
=================================================================== |
--- net/base/x509_certificate_nss.cc (revision 49024) |
+++ net/base/x509_certificate_nss.cc (working copy) |
@@ -14,10 +14,13 @@ |
#include <sechash.h> |
#include <sslerr.h> |
+#include <limits> |
+ |
#include "base/logging.h" |
#include "base/pickle.h" |
#include "base/time.h" |
#include "base/nss_util.h" |
+#include "base/crypto/scoped_nss_types.h" |
#include "net/base/cert_status_flags.h" |
#include "net/base/cert_verify_result.h" |
#include "net/base/ev_root_ca_metadata.h" |
@@ -27,54 +30,11 @@ |
namespace { |
-class ScopedCERTCertificate { |
- public: |
- explicit ScopedCERTCertificate(CERTCertificate* cert) |
- : cert_(cert) {} |
+typedef scoped_ptr_malloc<CERTCertificatePolicies, |
+ base::NSSDestroyer<CERTCertificatePolicies, |
+ CERT_DestroyCertificatePoliciesExtension> > |
+ ScopedCERTCertificatePolicies; |
- ~ScopedCERTCertificate() { |
- if (cert_) |
- CERT_DestroyCertificate(cert_); |
- } |
- |
- private: |
- CERTCertificate* cert_; |
- |
- DISALLOW_COPY_AND_ASSIGN(ScopedCERTCertificate); |
-}; |
- |
-class ScopedCERTCertList { |
- public: |
- explicit ScopedCERTCertList(CERTCertList* cert_list) |
- : cert_list_(cert_list) {} |
- |
- ~ScopedCERTCertList() { |
- if (cert_list_) |
- CERT_DestroyCertList(cert_list_); |
- } |
- |
- private: |
- CERTCertList* cert_list_; |
- |
- DISALLOW_COPY_AND_ASSIGN(ScopedCERTCertList); |
-}; |
- |
-class ScopedCERTCertificatePolicies { |
- public: |
- explicit ScopedCERTCertificatePolicies(CERTCertificatePolicies* policies) |
- : policies_(policies) {} |
- |
- ~ScopedCERTCertificatePolicies() { |
- if (policies_) |
- CERT_DestroyCertificatePoliciesExtension(policies_); |
- } |
- |
- private: |
- CERTCertificatePolicies* policies_; |
- |
- DISALLOW_COPY_AND_ASSIGN(ScopedCERTCertificatePolicies); |
-}; |
- |
// ScopedCERTValOutParam manages destruction of values in the CERTValOutParam |
// array that cvout points to. cvout must be initialized as passed to |
// CERT_PKIXVerifyCert, so that the array must be terminated with |
@@ -571,6 +531,29 @@ |
return false; |
} |
+struct CollectCertsCallbackArgs { |
+ X509Certificate::OSCertHandle (*createFn)(const char* data, size_t length); |
+ X509Certificate::OSCertHandles* results; |
+}; |
+ |
+SECStatus PR_CALLBACK |
+CollectCertsCallback(void* arg, SECItem** certs, int numcerts) { |
+ if (numcerts < 0) |
+ return SECFailure; // In the event of wrapping |
+ |
+ CollectCertsCallbackArgs* args = |
+ reinterpret_cast<CollectCertsCallbackArgs*>(arg); |
+ |
+ for (int i = 0; i < numcerts; ++i) { |
+ X509Certificate::OSCertHandle handle = args->createFn( |
+ reinterpret_cast<char*>(certs[i]->data), certs[i]->len); |
+ if (handle) |
+ args->results->push_back(handle); |
+ } |
+ |
+ return SECSuccess; |
+} |
+ |
} // namespace |
void X509Certificate::Initialize() { |
@@ -591,7 +574,7 @@ |
if (!pickle.ReadData(pickle_iter, &data, &length)) |
return NULL; |
- return CreateFromBytes(data, length); |
+ return CreateFromBytes(data, length, FORMAT_DER); |
} |
void X509Certificate::Persist(Pickle* pickle) { |
@@ -720,25 +703,72 @@ |
// static |
X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( |
- const char* data, int length) { |
+ const char* data, size_t length) { |
+ if (length > static_cast<size_t>(std::numeric_limits<unsigned int>::max())) |
+ 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 = static_cast<unsigned int>(length); |
+ der_cert.type = siDERCertBuffer; |
// Parse into a certificate structure. |
- CERTCertificate* cert = CERT_DecodeCertFromPackage(data_copy, length); |
- delete [] data_copy; |
+ CERTCertificate* cert = |
+ CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &der_cert, NULL, |
+ PR_FALSE, PR_TRUE); |
if (!cert) |
- LOG(ERROR) << "Couldn't parse a certificate from " << length << " bytes"; |
+ return NULL; |
+ |
return cert; |
} |
// static |
+X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( |
+ const char* data, size_t length, CertificateFormat format) { |
+ OSCertHandles results; |
+ |
+ if (length > static_cast<size_t>(std::numeric_limits<int>::max())) |
+ return results; |
+ |
+ switch (format) { |
+ case FORMAT_DER: |
+ { |
+ OSCertHandle handle = CreateOSCertHandleFromBytes(data, length); |
+ if (handle) |
+ results.push_back(handle); |
+ } |
+ break; |
+ case FORMAT_LEGACY_NETSCAPE: |
+ case FORMAT_PKCS7: |
+ { |
+ // Make a copy since CERT_DecodeCertPackage may modify it |
+ scoped_array<char> data_copy(new char[length]); |
+ memcpy(data_copy.get(), data, length); |
+ |
+ CollectCertsCallbackArgs args; |
+ args.results = &results; |
+ args.createFn = &X509Certificate::CreateOSCertHandleFromBytes; |
+ |
+ SECStatus result = CERT_DecodeCertPackage(data_copy.get(), |
+ static_cast<int>(length), CollectCertsCallback, &args); |
+ if (result != SECSuccess) |
+ results.clear(); |
+ } |
+ break; |
+ default: |
+ NOTREACHED() << "Certificate format " << format << " unimplemented"; |
+ break; |
+ } |
+ |
+ return results; |
+} |
+ |
+// static |
X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( |
OSCertHandle cert_handle) { |
return CERT_DupCertificate(cert_handle); |