| 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);
|
|
|