diff options
author | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-29 21:48:11 +0000 |
---|---|---|
committer | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-29 21:48:11 +0000 |
commit | 6e7845aed4759ab35d722ce0551b5a90d21e7640 (patch) | |
tree | f29a3f007f7ded842d2096446ff7ecaf186cb362 /net/cert/test_root_certs_nss.cc | |
parent | a6b4f91d970aa2b71b0f3552dbc11e94f7650fd5 (diff) | |
download | chromium_src-6e7845aed4759ab35d722ce0551b5a90d21e7640.zip chromium_src-6e7845aed4759ab35d722ce0551b5a90d21e7640.tar.gz chromium_src-6e7845aed4759ab35d722ce0551b5a90d21e7640.tar.bz2 |
net: extract net/cert out of net/base
This introduces the following dependency of net/base on things outside:
net/base/openssl_client_key_store.cc:#include "net/cert/x509_certificate.h"
BUG=70818
Review URL: https://codereview.chromium.org/13006020
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@191450 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/cert/test_root_certs_nss.cc')
-rw-r--r-- | net/cert/test_root_certs_nss.cc | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/net/cert/test_root_certs_nss.cc b/net/cert/test_root_certs_nss.cc new file mode 100644 index 0000000..3a2f88a --- /dev/null +++ b/net/cert/test_root_certs_nss.cc @@ -0,0 +1,125 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/cert/test_root_certs.h" + +#include <cert.h> + +#include "base/logging.h" +#include "base/stl_util.h" +#include "crypto/nss_util.h" +#include "net/cert/x509_certificate.h" + +#if defined(OS_IOS) +#include "net/cert/x509_util_ios.h" +#endif + +namespace net { + +// TrustEntry is used to store the original CERTCertificate and CERTCertTrust +// for a certificate whose trust status has been changed by the +// TestRootCerts. +class TestRootCerts::TrustEntry { + public: + // Creates a new TrustEntry by incrementing the reference to |certificate| + // and copying |trust|. + TrustEntry(CERTCertificate* certificate, const CERTCertTrust& trust); + ~TrustEntry(); + + CERTCertificate* certificate() const { return certificate_; } + const CERTCertTrust& trust() const { return trust_; } + + private: + // The temporary root certificate. + CERTCertificate* certificate_; + + // The original trust settings, before |certificate_| was manipulated to + // be a temporarily trusted root. + CERTCertTrust trust_; + + DISALLOW_COPY_AND_ASSIGN(TrustEntry); +}; + +TestRootCerts::TrustEntry::TrustEntry(CERTCertificate* certificate, + const CERTCertTrust& trust) + : certificate_(CERT_DupCertificate(certificate)), + trust_(trust) { +} + +TestRootCerts::TrustEntry::~TrustEntry() { + CERT_DestroyCertificate(certificate_); +} + +bool TestRootCerts::Add(X509Certificate* certificate) { +#if defined(OS_IOS) + x509_util_ios::NSSCertificate nss_certificate(certificate->os_cert_handle()); + CERTCertificate* cert_handle = nss_certificate.cert_handle(); +#else + CERTCertificate* cert_handle = certificate->os_cert_handle(); +#endif + // Preserve the original trust bits so that they can be restored when + // the certificate is removed. + CERTCertTrust original_trust; + SECStatus rv = CERT_GetCertTrust(cert_handle, &original_trust); + if (rv != SECSuccess) { + // CERT_GetCertTrust will fail if the certificate does not have any + // particular trust settings associated with it, and attempts to use + // |original_trust| later to restore the original trust settings will not + // cause the trust settings to be revoked. If the certificate has no + // particular trust settings associated with it, mark the certificate as + // a valid CA certificate with no specific trust. + rv = CERT_DecodeTrustString(&original_trust, "c,c,c"); + } + + // Change the trust bits to unconditionally trust this certificate. + CERTCertTrust new_trust; + rv = CERT_DecodeTrustString(&new_trust, "TCu,Cu,Tu"); + if (rv != SECSuccess) { + LOG(ERROR) << "Cannot decode certificate trust string."; + return false; + } + + rv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert_handle, &new_trust); + if (rv != SECSuccess) { + LOG(ERROR) << "Cannot change certificate trust."; + return false; + } + + trust_cache_.push_back(new TrustEntry(cert_handle, original_trust)); + return true; +} + +void TestRootCerts::Clear() { + // Restore the certificate trusts to what they were originally, before + // Add() was called. Work from the rear first, since if a certificate was + // added twice, the second entry's original trust status will be that of + // the first entry, while the first entry contains the desired resultant + // status. + for (std::list<TrustEntry*>::reverse_iterator it = trust_cache_.rbegin(); + it != trust_cache_.rend(); ++it) { + CERTCertTrust original_trust = (*it)->trust(); + SECStatus rv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), + (*it)->certificate(), + &original_trust); + // DCHECK(), rather than LOG(), as a failure to restore the original + // trust can cause flake or hard-to-trace errors in any unit tests that + // occur after Clear() has been called. + DCHECK_EQ(SECSuccess, rv) << "Cannot restore certificate trust."; + } + STLDeleteElements(&trust_cache_); +} + +bool TestRootCerts::IsEmpty() const { + return trust_cache_.empty(); +} + +TestRootCerts::~TestRootCerts() { + Clear(); +} + +void TestRootCerts::Init() { + crypto::EnsureNSSInit(); +} + +} // namespace net |