Chromium Code Reviews| Index: net/base/temporary_root_certs_nss.cc |
| diff --git a/net/base/temporary_root_certs_nss.cc b/net/base/temporary_root_certs_nss.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..3b4c52a189033fdc5f79f33c10126c47ad6c8561 |
| --- /dev/null |
| +++ b/net/base/temporary_root_certs_nss.cc |
| @@ -0,0 +1,122 @@ |
| +// Copyright (c) 2010 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/base/temporary_root_certs.h" |
| + |
| +#include <cert.h> |
| + |
| +#include "base/logging.h" |
| +#include "base/nss_util.h" |
| +#include "net/base/x509_certificate.h" |
| + |
| +namespace net { |
| + |
| +class TemporaryRootCerts::TrustEntry { |
| + public: |
| + TrustEntry(CERTCertificate* certificate, CERTCertTrust trust); |
| + TrustEntry(const TrustEntry& entry); |
| + ~TrustEntry(); |
| + |
| + TrustEntry& operator=(const TrustEntry& entry); |
| + |
| + CERTCertificate* certificate() const { return certificate_; } |
| + 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_; |
| +}; |
| + |
| +TemporaryRootCerts::TrustEntry::TrustEntry(CERTCertificate* certificate, |
| + CERTCertTrust trust) |
| + : certificate_(CERT_DupCertificate(certificate)), |
| + trust_(trust) {} |
| + |
| +TemporaryRootCerts::TrustEntry::TrustEntry(const TrustEntry& entry) |
|
wtc
2010/11/16 23:24:01
It seems that this is exactly what the compiler ca
Ryan Sleevi
2010/11/17 09:37:43
My understanding is that the implicitly generated
|
| + : certificate_(NULL) { |
| + *this = entry; |
| +} |
| + |
| +TemporaryRootCerts::TrustEntry::~TrustEntry() { |
| + CERT_DestroyCertificate(certificate_); |
| +} |
| + |
| +TemporaryRootCerts::TrustEntry& |
| +TemporaryRootCerts::TrustEntry::operator=(const TrustEntry& entry) { |
| + CERT_DestroyCertificate(certificate_); |
| + certificate_ = CERT_DupCertificate(entry.certificate_); |
| + trust_ = entry.trust_; |
| + return *this; |
| +} |
| + |
| +bool TemporaryRootCerts::Add(X509Certificate* certificate) { |
| + if (cert_trust_map_.find(certificate->fingerprint()) != |
| + cert_trust_map_.end()) |
| + return true; |
| + |
| + // Preserve the original trust bits so that they can be restored when |
| + // the certificate is removed. |
| + CERTCertTrust nss_trust; |
| + SECStatus rv = CERT_GetCertTrust(certificate->os_cert_handle(), |
| + &nss_trust); |
| + // TODO(rsleevi): Not checking rv because an untrusted (ephemeral) cert |
| + // will return SECFailure, rather than initializing an empty trust |
| + // structure. |
| + |
| + TrustEntry entry(certificate->os_cert_handle(), nss_trust); |
|
bulach
2010/11/09 16:21:09
could move this further down to 88
Ryan Sleevi
2010/11/17 09:37:43
No, this copies |nss_trust|, which is then modifie
|
| + |
| + // Change the trust bits to unconditionally trust this certificate. |
| + // TODO(port): remove this const_cast after NSS 3.12.3 is released. |
|
wtc
2010/11/16 23:24:01
Nit: you can remove this TODO comment and the cons
|
| + rv = CERT_DecodeTrustString(&nss_trust, const_cast<char*>("TCu,Cu,Tu")); |
| + if (rv != SECSuccess) { |
| + LOG(ERROR) << "Cannot decode certificate trust string."; |
| + return false; |
| + } |
| + |
| + rv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), |
| + certificate->os_cert_handle(), |
| + &nss_trust); |
| + if (rv != SECSuccess) { |
| + LOG(ERROR) << "Cannot change certificate trust."; |
| + return false; |
| + } |
| + |
| + cert_trust_map_.insert(std::make_pair(certificate->fingerprint(), entry)); |
|
wtc
2010/11/16 23:24:01
Isn't this equivalent to
cert_trust_map_[certifi
Ryan Sleevi
2010/11/17 09:37:43
Depends :) Using operator[] for a map<Key, T> forc
|
| + return true; |
| +} |
| + |
| +void TemporaryRootCerts::Remove(X509Certificate* certificate) { |
| + CertTrustMap::iterator it = |
| + cert_trust_map_.find(certificate->fingerprint()); |
| + if (it == cert_trust_map_.end()) |
| + return; |
| + |
| + CERTCertTrust original_trust = it->second.trust(); |
| + cert_trust_map_.erase(it); |
| + |
| + CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), |
| + certificate->os_cert_handle(), |
| + &original_trust); |
| +} |
| + |
| +TemporaryRootCerts::TemporaryRootCerts() { |
| + base::EnsureNSSInit(); |
| +} |
| + |
| +TemporaryRootCerts::~TemporaryRootCerts() { |
| + // Restore the certificate trusts to what they were originally. |
| + for (CertTrustMap::iterator it = cert_trust_map_.begin(); |
| + it != cert_trust_map_.end(); ++it) { |
| + CERTCertTrust original_trust = it->second.trust(); |
| + CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), |
| + it->second.certificate(), |
| + &original_trust); |
| + } |
| +} |
| + |
| +} // namespace net |