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 |