summaryrefslogtreecommitdiffstats
path: root/net/base
diff options
context:
space:
mode:
Diffstat (limited to 'net/base')
-rw-r--r--net/base/x509_certificate.cc92
-rw-r--r--net/base/x509_certificate.h38
-rw-r--r--net/base/x509_certificate_mac.cc14
-rw-r--r--net/base/x509_certificate_nss.cc9
-rw-r--r--net/base/x509_certificate_unittest.cc70
-rw-r--r--net/base/x509_certificate_win.cc13
6 files changed, 42 insertions, 194 deletions
diff --git a/net/base/x509_certificate.cc b/net/base/x509_certificate.cc
index 700b254..24388d8 100644
--- a/net/base/x509_certificate.cc
+++ b/net/base/x509_certificate.cc
@@ -4,10 +4,6 @@
#include "net/base/x509_certificate.h"
-#if defined(USE_NSS)
-#include <cert.h>
-#endif
-
#include "base/histogram.h"
#include "base/logging.h"
#include "base/time.h"
@@ -28,33 +24,6 @@ bool IsNullFingerprint(const X509Certificate::Fingerprint& fingerprint) {
} // namespace
-// static
-bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a,
- X509Certificate::OSCertHandle b) {
- DCHECK(a && b);
- if (a == b)
- return true;
-#if defined(OS_WIN)
- return a->cbCertEncoded == b->cbCertEncoded &&
- memcmp(a->pbCertEncoded, b->pbCertEncoded, a->cbCertEncoded) == 0;
-#elif defined(OS_MACOSX)
- if (CFEqual(a, b))
- return true;
- CSSM_DATA a_data, b_data;
- return SecCertificateGetData(a, &a_data) == noErr &&
- SecCertificateGetData(b, &b_data) == noErr &&
- a_data.Length == b_data.Length &&
- memcmp(a_data.Data, b_data.Data, a_data.Length) == 0;
-#elif defined(USE_NSS)
- return a->derCert.len == b->derCert.len &&
- memcmp(a->derCert.data, b->derCert.data, a->derCert.len) == 0;
-#else
- // TODO(snej): not implemented
- UNREACHED();
- return false;
-#endif
-}
-
bool X509Certificate::FingerprintLessThan::operator()(
const Fingerprint& lhs,
const Fingerprint& rhs) const {
@@ -88,13 +57,14 @@ X509Certificate::Cache* X509Certificate::Cache::GetInstance() {
return Singleton<X509Certificate::Cache>::get();
}
-// Insert |cert| into the cache. The cache does NOT AddRef |cert|.
-// Any existing certificate with the same fingerprint will be replaced.
+// Insert |cert| into the cache. The cache does NOT AddRef |cert|. The cache
+// must not already contain a certificate with the same fingerprint.
void X509Certificate::Cache::Insert(X509Certificate* cert) {
AutoLock lock(lock_);
DCHECK(!IsNullFingerprint(cert->fingerprint())) <<
"Only insert certs with real fingerprints.";
+ DCHECK(cache_.find(cert->fingerprint()) == cache_.end());
cache_[cert->fingerprint()] = cert;
};
@@ -163,10 +133,8 @@ bool X509Certificate::Policy::HasDeniedCert() const {
}
// static
-X509Certificate* X509Certificate::CreateFromHandle(
- OSCertHandle cert_handle,
- Source source,
- const OSCertHandles& intermediates) {
+X509Certificate* X509Certificate::CreateFromHandle(OSCertHandle cert_handle,
+ Source source) {
DCHECK(cert_handle);
DCHECK(source != SOURCE_UNUSED);
@@ -176,20 +144,18 @@ X509Certificate* X509Certificate::CreateFromHandle(
cache->Find(CalculateFingerprint(cert_handle));
if (cached_cert) {
DCHECK(cached_cert->source_ != SOURCE_UNUSED);
- if (cached_cert->source_ > source ||
- (cached_cert->source_ == source &&
- cached_cert->HasIntermediateCertificates(intermediates))) {
- // Return the certificate with the same fingerprint from our cache.
- // But we own the input OSCertHandle, which makes it our job to free it.
+ if (cached_cert->source_ >= source) {
+ // We've found a certificate with the same fingerprint in our cache. We
+ // own the |cert_handle|, which makes it our job to free it.
FreeOSCertHandle(cert_handle);
DHISTOGRAM_COUNTS("X509CertificateReuseCount", 1);
return cached_cert;
}
- // Else the new cert is better and will replace the old one in the cache.
+ // Kick out the old certificate from our cache. The new one is better.
+ cache->Remove(cached_cert);
}
-
// Otherwise, allocate a new object.
- return new X509Certificate(cert_handle, source, intermediates);
+ return new X509Certificate(cert_handle, source);
}
// static
@@ -199,25 +165,13 @@ X509Certificate* X509Certificate::CreateFromBytes(const char* data,
if (!cert_handle)
return NULL;
- return CreateFromHandle(cert_handle,
- SOURCE_LONE_CERT_IMPORT,
- OSCertHandles());
+ return CreateFromHandle(cert_handle, SOURCE_LONE_CERT_IMPORT);
}
-X509Certificate::X509Certificate(OSCertHandle cert_handle,
- Source source,
- const OSCertHandles& intermediates)
+X509Certificate::X509Certificate(OSCertHandle cert_handle, Source source)
: cert_handle_(cert_handle),
source_(source) {
-#if defined(OS_MACOSX) || defined(OS_WIN)
- // Copy/retain the intermediate cert handles.
- for (size_t i = 0; i < intermediates.size(); ++i)
- intermediate_ca_certs_.push_back(DupOSCertHandle(intermediates[i]));
-#endif
- // Platform-specific initialization.
Initialize();
- // Store the certificate in the cache in case we need it later.
- X509Certificate::Cache::GetInstance()->Insert(this);
}
X509Certificate::X509Certificate(const std::string& subject,
@@ -248,24 +202,4 @@ bool X509Certificate::HasExpired() const {
return base::Time::Now() > valid_expiry();
}
-bool X509Certificate::HasIntermediateCertificate(OSCertHandle cert) {
-#if defined(OS_MACOSX) || defined(OS_WIN)
- for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) {
- if (IsSameOSCert(cert, intermediate_ca_certs_[i]))
- return true;
- }
- return false;
-#else
- return true;
-#endif
-}
-
-bool X509Certificate::HasIntermediateCertificates(const OSCertHandles& certs) {
- for (size_t i = 0; i < certs.size(); ++i) {
- if (!HasIntermediateCertificate(certs[i]))
- return false;
- }
- return true;
-}
-
} // namespace net
diff --git a/net/base/x509_certificate.h b/net/base/x509_certificate.h
index ec287ce..f3f3fea 100644
--- a/net/base/x509_certificate.h
+++ b/net/base/x509_certificate.h
@@ -72,8 +72,6 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
typedef void* OSCertHandle;
#endif
- typedef std::vector<OSCertHandle> OSCertHandles;
-
// Principal represent an X.509 principal.
struct Principal {
Principal() { }
@@ -154,11 +152,10 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
// prefers the handle from the network because our HTTP cache isn't
// caching the corresponding intermediate CA certificates yet
// (http://crbug.com/7065).
- // The list of intermediate certificates is ignored under NSS (i.e. Linux.)
+ //
// The returned pointer must be stored in a scoped_refptr<X509Certificate>.
static X509Certificate* CreateFromHandle(OSCertHandle cert_handle,
- Source source,
- const OSCertHandles& intermediates);
+ Source source);
// Create an X509Certificate from the BER-encoded representation.
// Returns NULL on failure.
@@ -213,20 +210,20 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
bool HasExpired() const;
#if defined(OS_MACOSX) || defined(OS_WIN)
+ // Adds an untrusted intermediate certificate that may be needed for
+ // chain building.
+ void AddIntermediateCertificate(OSCertHandle cert) {
+ intermediate_ca_certs_.push_back(cert);
+ }
+
// Returns intermediate certificates added via AddIntermediateCertificate().
// Ownership follows the "get" rule: it is the caller's responsibility to
// retain the elements of the result.
- const OSCertHandles& GetIntermediateCertificates() const {
+ const std::vector<OSCertHandle>& GetIntermediateCertificates() const {
return intermediate_ca_certs_;
}
#endif
- // Returns true if I already contain the given intermediate cert.
- bool HasIntermediateCertificate(OSCertHandle cert);
-
- // Returns true if I already contain all the given intermediate certs.
- bool HasIntermediateCertificates(const OSCertHandles& certs);
-
#if defined(OS_MACOSX)
// Does this certificate's usage allow SSL client authentication?
bool SupportsSSLClientAuth() const;
@@ -265,14 +262,9 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
OSCertHandle os_cert_handle() const { return cert_handle_; }
- // Returns true if two OSCertHandles refer to identical certificates.
- static bool IsSameOSCert(OSCertHandle a, OSCertHandle b);
-
-
private:
friend class base::RefCountedThreadSafe<X509Certificate>;
FRIEND_TEST(X509CertificateTest, Cache);
- FRIEND_TEST(X509CertificateTest, IntermediateCertificates);
// A cache of X509Certificate objects.
class Cache {
@@ -302,8 +294,7 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
// Construct an X509Certificate from a handle to the certificate object
// in the underlying crypto library.
- X509Certificate(OSCertHandle cert_handle, Source source,
- const OSCertHandles& intermediates);
+ X509Certificate(OSCertHandle cert_handle, Source source);
~X509Certificate();
@@ -317,10 +308,7 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
static OSCertHandle CreateOSCertHandleFromBytes(const char* data,
int length);
- // Duplicates (or adds a reference to) an OS certificate handle.
- static OSCertHandle DupOSCertHandle(OSCertHandle cert_handle);
-
- // Frees (or releases a reference to) an OS certificate handle.
+ // Frees an OS certificate handle.
static void FreeOSCertHandle(OSCertHandle cert_handle);
// Calculates the SHA-1 fingerprint of the certificate. Returns an empty
@@ -347,8 +335,8 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
#if defined(OS_MACOSX) || defined(OS_WIN)
// Untrusted intermediate certificates associated with this certificate
- // that may be needed for chain building. (NSS impl does not need these.)
- OSCertHandles intermediate_ca_certs_;
+ // that may be needed for chain building.
+ std::vector<OSCertHandle> intermediate_ca_certs_;
#endif
// Where the certificate comes from.
diff --git a/net/base/x509_certificate_mac.cc b/net/base/x509_certificate_mac.cc
index fa1c17e0..36fc65a 100644
--- a/net/base/x509_certificate_mac.cc
+++ b/net/base/x509_certificate_mac.cc
@@ -405,6 +405,9 @@ void X509Certificate::Initialize() {
&valid_expiry_);
fingerprint_ = CalculateFingerprint(cert_handle_);
+
+ // Store the certificate in the cache in case we need it later.
+ X509Certificate::Cache::GetInstance()->Insert(this);
}
// static
@@ -686,14 +689,6 @@ X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
}
// static
-X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle(
- OSCertHandle handle) {
- if (!handle)
- return NULL;
- return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle)));
-}
-
-// static
void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
CFRelease(cert_handle);
}
@@ -790,8 +785,7 @@ bool X509Certificate::GetSSLClientCertificates (
continue;
scoped_refptr<X509Certificate> cert(
- CreateFromHandle(cert_handle, SOURCE_LONE_CERT_IMPORT,
- OSCertHandles()));
+ CreateFromHandle(cert_handle, SOURCE_LONE_CERT_IMPORT));
// cert_handle is adoped by cert, so I don't need to release it myself.
if (cert->HasExpired() || !cert->SupportsSSLClientAuth())
continue;
diff --git a/net/base/x509_certificate_nss.cc b/net/base/x509_certificate_nss.cc
index 705690a..b25688e 100644
--- a/net/base/x509_certificate_nss.cc
+++ b/net/base/x509_certificate_nss.cc
@@ -472,6 +472,9 @@ void X509Certificate::Initialize() {
ParseDate(&cert_handle_->validity.notAfter, &valid_expiry_);
fingerprint_ = CalculateFingerprint(cert_handle_);
+
+ // Store the certificate in the cache in case we need it later.
+ X509Certificate::Cache::GetInstance()->Insert(this);
}
// static
@@ -627,12 +630,6 @@ X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
}
// static
-X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle(
- OSCertHandle cert_handle) {
- return CERT_DupCertificate(cert_handle);
-}
-
-// static
void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
CERT_DestroyCertificate(cert_handle);
}
diff --git a/net/base/x509_certificate_unittest.cc b/net/base/x509_certificate_unittest.cc
index 7081f1ad..7904cf0 100644
--- a/net/base/x509_certificate_unittest.cc
+++ b/net/base/x509_certificate_unittest.cc
@@ -309,16 +309,14 @@ TEST(X509CertificateTest, Cache) {
google_cert_handle = X509Certificate::CreateOSCertHandleFromBytes(
reinterpret_cast<const char*>(google_der), sizeof(google_der));
scoped_refptr<X509Certificate> cert1 = X509Certificate::CreateFromHandle(
- google_cert_handle, X509Certificate::SOURCE_LONE_CERT_IMPORT,
- X509Certificate::OSCertHandles());
+ google_cert_handle, X509Certificate::SOURCE_LONE_CERT_IMPORT);
// Add a certificate from the same source (SOURCE_LONE_CERT_IMPORT). This
// should return the cached certificate (cert1).
google_cert_handle = X509Certificate::CreateOSCertHandleFromBytes(
reinterpret_cast<const char*>(google_der), sizeof(google_der));
scoped_refptr<X509Certificate> cert2 = X509Certificate::CreateFromHandle(
- google_cert_handle, X509Certificate::SOURCE_LONE_CERT_IMPORT,
- X509Certificate::OSCertHandles());
+ google_cert_handle, X509Certificate::SOURCE_LONE_CERT_IMPORT);
EXPECT_EQ(cert1, cert2);
@@ -327,8 +325,7 @@ TEST(X509CertificateTest, Cache) {
google_cert_handle = X509Certificate::CreateOSCertHandleFromBytes(
reinterpret_cast<const char*>(google_der), sizeof(google_der));
scoped_refptr<X509Certificate> cert3 = X509Certificate::CreateFromHandle(
- google_cert_handle, X509Certificate::SOURCE_FROM_NETWORK,
- X509Certificate::OSCertHandles());
+ google_cert_handle, X509Certificate::SOURCE_FROM_NETWORK);
EXPECT_NE(cert1, cert3);
@@ -337,16 +334,14 @@ TEST(X509CertificateTest, Cache) {
google_cert_handle = X509Certificate::CreateOSCertHandleFromBytes(
reinterpret_cast<const char*>(google_der), sizeof(google_der));
scoped_refptr<X509Certificate> cert4 = X509Certificate::CreateFromHandle(
- google_cert_handle, X509Certificate::SOURCE_FROM_NETWORK,
- X509Certificate::OSCertHandles());
+ google_cert_handle, X509Certificate::SOURCE_FROM_NETWORK);
EXPECT_EQ(cert3, cert4);
google_cert_handle = X509Certificate::CreateOSCertHandleFromBytes(
reinterpret_cast<const char*>(google_der), sizeof(google_der));
scoped_refptr<X509Certificate> cert5 = X509Certificate::CreateFromHandle(
- google_cert_handle, X509Certificate::SOURCE_FROM_NETWORK,
- X509Certificate::OSCertHandles());
+ google_cert_handle, X509Certificate::SOURCE_FROM_NETWORK);
EXPECT_EQ(cert3, cert5);
}
@@ -401,59 +396,4 @@ TEST(X509CertificateTest, Policy) {
EXPECT_TRUE(policy.HasDeniedCert());
}
-#if defined(OS_MACOSX) || defined(OS_WIN)
-TEST(X509CertificateTest, IntermediateCertificates) {
- X509Certificate::OSCertHandle handle1, handle2, handle3, handle4;
-
- // Create object with no intermediates:
- handle1 = X509Certificate::CreateOSCertHandleFromBytes(
- reinterpret_cast<const char*>(google_der), sizeof(google_der));
- X509Certificate::OSCertHandles intermediates1;
- scoped_refptr<X509Certificate> cert1;
- cert1 = X509Certificate::CreateFromHandle(handle1,
- X509Certificate::SOURCE_FROM_NETWORK,
- intermediates1);
- EXPECT_TRUE(cert1->HasIntermediateCertificates(intermediates1));
- handle2 = X509Certificate::CreateOSCertHandleFromBytes(
- reinterpret_cast<const char*>(webkit_der), sizeof(webkit_der));
- EXPECT_FALSE(cert1->HasIntermediateCertificate(handle2));
-
- // Create object with 2 intermediates:
- handle1 = X509Certificate::CreateOSCertHandleFromBytes(
- reinterpret_cast<const char*>(google_der), sizeof(google_der));
- X509Certificate::OSCertHandles intermediates2;
- handle3 = X509Certificate::CreateOSCertHandleFromBytes(
- reinterpret_cast<const char*>(thawte_der), sizeof(thawte_der));
- intermediates2.push_back(handle2);
- intermediates2.push_back(handle3);
- scoped_refptr<X509Certificate> cert2;
- cert2 = X509Certificate::CreateFromHandle(handle1,
- X509Certificate::SOURCE_FROM_NETWORK,
- intermediates2);
-
- // The cache should have stored cert2 'cause it has more intermediates:
- EXPECT_NE(cert1, cert2);
-
- // Verify it has all the intermediates:
- EXPECT_TRUE(cert2->HasIntermediateCertificate(handle2));
- EXPECT_TRUE(cert2->HasIntermediateCertificate(handle3));
- handle4 = X509Certificate::CreateOSCertHandleFromBytes(
- reinterpret_cast<const char*>(paypal_null_der), sizeof(paypal_null_der));
- EXPECT_FALSE(cert2->HasIntermediateCertificate(handle4));
-
- // Create object with 1 intermediate:
- handle3 = X509Certificate::CreateOSCertHandleFromBytes(
- reinterpret_cast<const char*>(thawte_der), sizeof(thawte_der));
- X509Certificate::OSCertHandles intermediates3;
- intermediates2.push_back(handle3);
- scoped_refptr<X509Certificate> cert3;
- cert3 = X509Certificate::CreateFromHandle(handle1,
- X509Certificate::SOURCE_FROM_NETWORK,
- intermediates3);
-
- // The cache should have returned cert2 'cause it has more intermediates:
- EXPECT_EQ(cert3, cert2);
-}
-#endif
-
} // namespace net
diff --git a/net/base/x509_certificate_win.cc b/net/base/x509_certificate_win.cc
index 7f3f09e..df43814 100644
--- a/net/base/x509_certificate_win.cc
+++ b/net/base/x509_certificate_win.cc
@@ -463,6 +463,9 @@ void X509Certificate::Initialize() {
valid_expiry_ = Time::FromFileTime(cert_handle_->pCertInfo->NotAfter);
fingerprint_ = CalculateFingerprint(cert_handle_);
+
+ // Store the certificate in the cache in case we need it later.
+ X509Certificate::Cache::GetInstance()->Insert(this);
}
// static
@@ -481,8 +484,7 @@ X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle,
NULL, reinterpret_cast<const void **>(&cert_handle)))
return NULL;
- return CreateFromHandle(cert_handle, SOURCE_LONE_CERT_IMPORT,
- OSCertHandles());
+ return CreateFromHandle(cert_handle, SOURCE_LONE_CERT_IMPORT);
}
void X509Certificate::Persist(Pickle* pickle) {
@@ -744,13 +746,6 @@ X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
return cert_handle;
}
-
-// static
-X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle(
- OSCertHandle cert_handle) {
- return CertDuplicateCertificateContext(cert_handle);
-}
-
// static
void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
CertFreeCertificateContext(cert_handle);