From 708f3b3ad64ea2f445ac975d9301db9304214d54 Mon Sep 17 00:00:00 2001 From: "sergeyu@chromium.org" Date: Thu, 28 Jul 2011 21:52:15 +0000 Subject: Revert 94553 - Provides in memory and persistent storage for origin bound certificates, which are specified at http://balfanz.github.com/tls-obc-spec/draft-balfanz-tls-obc-00.html. The code is based on cookie_monster.{cc,h} and sqlite_persistent_cookie_store.{cc,h}. BUG=88782 TEST=None Review URL: http://codereview.chromium.org/7342021 TBR=rkn@chromium.org Review URL: http://codereview.chromium.org/7523039 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@94555 0039d316-1c4b-4281-b951-d872f2087c98 --- net/base/default_origin_bound_cert_store.cc | 137 ----------------- net/base/default_origin_bound_cert_store.h | 163 --------------------- .../default_origin_bound_cert_store_unittest.cc | 112 -------------- net/base/origin_bound_cert_service.cc | 29 ++-- net/base/origin_bound_cert_service.h | 23 +-- net/base/origin_bound_cert_service_unittest.cc | 68 --------- net/base/origin_bound_cert_store.h | 25 +--- 7 files changed, 25 insertions(+), 532 deletions(-) delete mode 100644 net/base/default_origin_bound_cert_store.cc delete mode 100644 net/base/default_origin_bound_cert_store.h delete mode 100644 net/base/default_origin_bound_cert_store_unittest.cc delete mode 100644 net/base/origin_bound_cert_service_unittest.cc (limited to 'net/base') diff --git a/net/base/default_origin_bound_cert_store.cc b/net/base/default_origin_bound_cert_store.cc deleted file mode 100644 index e047af8..0000000 --- a/net/base/default_origin_bound_cert_store.cc +++ /dev/null @@ -1,137 +0,0 @@ -// 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/base/default_origin_bound_cert_store.h" - -#include "base/message_loop.h" - -namespace net { - -// static -const size_t DefaultOriginBoundCertStore::kMaxCerts = 3300; - -DefaultOriginBoundCertStore::DefaultOriginBoundCertStore( - PersistentStore* store) - : initialized_(false), - store_(store) {} - -void DefaultOriginBoundCertStore::FlushStore(Task* completion_task) { - base::AutoLock autolock(lock_); - - if (initialized_ && store_) - store_->Flush(completion_task); - else if (completion_task) - MessageLoop::current()->PostTask(FROM_HERE, completion_task); -} - -bool DefaultOriginBoundCertStore::GetOriginBoundCert( - const std::string& origin, - std::string* private_key_result, - std::string* cert_result) { - base::AutoLock autolock(lock_); - InitIfNecessary(); - - OriginBoundCertMap::iterator it = origin_bound_certs_.find(origin); - - if (it == origin_bound_certs_.end()) - return false; - - OriginBoundCert* cert = it->second; - *private_key_result = cert->private_key(); - *cert_result = cert->cert(); - - return true; -} - -bool DefaultOriginBoundCertStore::SetOriginBoundCert( - const std::string& origin, - const std::string& private_key, - const std::string& cert) { - base::AutoLock autolock(lock_); - InitIfNecessary(); - - InternalDeleteOriginBoundCert(origin); - InternalInsertOriginBoundCert(origin, - new OriginBoundCert(origin, private_key, cert)); - - return true; -} - -int DefaultOriginBoundCertStore::GetCertCount() { - base::AutoLock autolock(lock_); - InitIfNecessary(); - - return origin_bound_certs_.size(); -} - -DefaultOriginBoundCertStore::~DefaultOriginBoundCertStore() { - DeleteAll(); -} - -void DefaultOriginBoundCertStore::DeleteAll() { - base::AutoLock autolock(lock_); - - for (OriginBoundCertMap::iterator it = origin_bound_certs_.begin(); - it != origin_bound_certs_.end(); it++) { - delete it->second; - } - origin_bound_certs_.clear(); -} - -void DefaultOriginBoundCertStore::InitStore() { - lock_.AssertAcquired(); - - DCHECK(store_) << "Store must exist to initialize"; - - // Initialize the store and sync in any saved persistent certs. - std::vector certs; - // Reserve space for the maximum amount of certs a database should have. - // This prevents multiple vector growth / copies as we append certs. - certs.reserve(kMaxCerts); - store_->Load(&certs); - - for (std::vector::const_iterator it = certs.begin(); - it != certs.end(); ++it) { - origin_bound_certs_[(*it)->origin()] = *it; - } -} - -void DefaultOriginBoundCertStore::InternalDeleteOriginBoundCert( - const std::string& origin) { - lock_.AssertAcquired(); - - OriginBoundCertMap::iterator it = origin_bound_certs_.find(origin); - if (it == origin_bound_certs_.end()) - return; // There is nothing to delete. - - OriginBoundCert* cert = it->second; - if (store_) - store_->DeleteOriginBoundCert(*cert); - origin_bound_certs_.erase(it); - delete cert; -} - -void DefaultOriginBoundCertStore::InternalInsertOriginBoundCert( - const std::string& origin, - OriginBoundCert* cert) { - lock_.AssertAcquired(); - - if (store_) - store_->AddOriginBoundCert(*cert); - origin_bound_certs_[origin] = cert; -} - -DefaultOriginBoundCertStore::OriginBoundCert::OriginBoundCert() {} - -DefaultOriginBoundCertStore::OriginBoundCert::OriginBoundCert( - const std::string& origin, - const std::string& private_key, - const std::string& cert) - : origin_(origin), - private_key_(private_key), - cert_(cert) {} - -DefaultOriginBoundCertStore::PersistentStore::PersistentStore() {} - -} // namespace net diff --git a/net/base/default_origin_bound_cert_store.h b/net/base/default_origin_bound_cert_store.h deleted file mode 100644 index 4b8b8a9..0000000 --- a/net/base/default_origin_bound_cert_store.h +++ /dev/null @@ -1,163 +0,0 @@ -// 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. - -#ifndef NET_BASE_DEFAULT_ORIGIN_BOUND_CERT_STORE_H_ -#define NET_BASE_DEFAULT_ORIGIN_BOUND_CERT_STORE_H_ -#pragma once - -#include -#include -#include - -#include "base/compiler_specific.h" -#include "base/memory/ref_counted.h" -#include "base/synchronization/lock.h" -#include "net/base/origin_bound_cert_store.h" - -class Task; - -namespace net { - -// This class is the system for storing and retrieving origin bound certs. -// Modelled after the CookieMonster class, it has an in-memory cert store, -// and synchronizes origin bound certs to an optional permanent storage that -// implements the PersistentStore interface. The use case is described in -// http://balfanz.github.com/tls-obc-spec/draft-balfanz-tls-obc-00.html -// -// This class can be accessed by multiple threads. For example, it can be used -// by IO and origin bound cert management UI. -class DefaultOriginBoundCertStore : public OriginBoundCertStore { - public: - class OriginBoundCert; - class PersistentStore; - - // The key for each OriginBoundCert* in OriginBoundCertMap is the - // corresponding origin. - typedef std::map OriginBoundCertMap; - - // The store passed in should not have had Init() called on it yet. This - // class will take care of initializing it. The backing store is NOT owned by - // this class, but it must remain valid for the duration of the - // DefaultOriginBoundCertStore's existence. If |store| is NULL, then no - // backing store will be updated. - explicit DefaultOriginBoundCertStore(PersistentStore* store); - - virtual ~DefaultOriginBoundCertStore(); - - // Flush the backing store (if any) to disk and post the given task when done. - // WARNING: THE CALLBACK WILL RUN ON A RANDOM THREAD. IT MUST BE THREAD SAFE. - // It may be posted to the current thread, or it may run on the thread that - // actually does the flushing. Your Task should generally post a notification - // to the thread you actually want to be notified on. - void FlushStore(Task* completion_task); - - // OriginBoundCertStore implementation. - virtual bool GetOriginBoundCert(const std::string& origin, - std::string* private_key_result, - std::string* cert_result) OVERRIDE; - virtual bool SetOriginBoundCert(const std::string& origin, - const std::string& private_key, - const std::string& cert) OVERRIDE; - virtual int GetCertCount() OVERRIDE; - - private: - static const size_t kMaxCerts; - - // Deletes all of the certs. Does not delete them from |store_|. - void DeleteAll(); - - // Called by all non-static functions to ensure that the cert store has - // been initialized. This is not done during creating so it doesn't block - // the window showing. - // Note: this method should always be called with lock_ held. - void InitIfNecessary() { - if (!initialized_) { - if (store_) - InitStore(); - initialized_ = true; - } - } - - // Initializes the backing store and reads existing certs from it. - // Should only be called by InitIfNecessary(). - void InitStore(); - - // Deletes the cert for the specified origin, if such a cert exists, from the - // in-memory store. Deletes it from |store_| if |store_| is not NULL. - void InternalDeleteOriginBoundCert(const std::string& origin); - - // Takes ownership of *cert. - // Adds the cert for the specified origin to the in-memory store. Deletes it - // from |store_| if |store_| is not NULL. - void InternalInsertOriginBoundCert(const std::string& origin, - OriginBoundCert* cert); - - // Indicates whether the cert store has been initialized. This happens - // Lazily in InitStoreIfNecessary(). - bool initialized_; - - scoped_refptr store_; - - OriginBoundCertMap origin_bound_certs_; - - // Lock for thread-safety - base::Lock lock_; - - DISALLOW_COPY_AND_ASSIGN(DefaultOriginBoundCertStore); -}; - -// The OriginBoundCert class contains a private key in addition to the origin -// and the cert. -class DefaultOriginBoundCertStore::OriginBoundCert { - public: - OriginBoundCert(); - OriginBoundCert(const std::string& origin, - const std::string& privatekey, - const std::string& cert); - - const std::string& origin() const { return origin_; } - const std::string& private_key() const { return private_key_; } - const std::string& cert() const { return cert_; } - - private: - std::string origin_; - std::string private_key_; - std::string cert_; -}; - -typedef base::RefCountedThreadSafe - RefcountedPersistentStore; - -class DefaultOriginBoundCertStore::PersistentStore - : public RefcountedPersistentStore { - public: - virtual ~PersistentStore() {} - - // Initializes the store and retrieves the existing certs. This will be - // called only once at startup. Note that the certs are individually allocated - // and that ownership is transferred to the caller upon return. - virtual bool Load( - std::vector* certs) = 0; - - virtual void AddOriginBoundCert(const OriginBoundCert& cert) = 0; - - virtual void DeleteOriginBoundCert(const OriginBoundCert& cert) = 0; - - // Sets the value of the user preference whether the persistent storage - // must be deleted upon destruction. - virtual void SetClearLocalStateOnExit(bool clear_local_state) = 0; - - // Flush the store and post the given Task when complete. - virtual void Flush(Task* completion_task) = 0; - - protected: - PersistentStore(); - - private: - DISALLOW_COPY_AND_ASSIGN(PersistentStore); -}; - -} // namespace net - -#endif // NET_DEFAULT_ORIGIN_BOUND_CERT_STORE_H_ diff --git a/net/base/default_origin_bound_cert_store_unittest.cc b/net/base/default_origin_bound_cert_store_unittest.cc deleted file mode 100644 index 5fe77ef..0000000 --- a/net/base/default_origin_bound_cert_store_unittest.cc +++ /dev/null @@ -1,112 +0,0 @@ -// 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/base/default_origin_bound_cert_store.h" - -#include -#include -#include - -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace net { - -class MockPersistentStore - : public DefaultOriginBoundCertStore::PersistentStore { - public: - MockPersistentStore(); - virtual ~MockPersistentStore(); - - // DefaultOriginBoundCertStore::PersistentStore implementation. - virtual bool Load( - std::vector* certs) - OVERRIDE; - virtual void AddOriginBoundCert( - const DefaultOriginBoundCertStore::OriginBoundCert& cert) OVERRIDE; - virtual void DeleteOriginBoundCert( - const DefaultOriginBoundCertStore::OriginBoundCert& cert) OVERRIDE; - virtual void SetClearLocalStateOnExit(bool clear_local_state) OVERRIDE; - virtual void Flush(Task* completion_task) OVERRIDE; - - private: - typedef std::map - OriginBoundCertMap; - - OriginBoundCertMap origin_certs_; -}; - -MockPersistentStore::MockPersistentStore() {} - -MockPersistentStore::~MockPersistentStore() {} - -bool MockPersistentStore::Load( - std::vector* certs) { - OriginBoundCertMap::iterator it; - - for (it = origin_certs_.begin(); it != origin_certs_.end(); ++it) { - certs->push_back( - new DefaultOriginBoundCertStore::OriginBoundCert(it->second)); - } - - return true; -} - -void MockPersistentStore::AddOriginBoundCert( - const DefaultOriginBoundCertStore::OriginBoundCert& cert) { - origin_certs_[cert.origin()] = cert; -} - -void MockPersistentStore::DeleteOriginBoundCert( - const DefaultOriginBoundCertStore::OriginBoundCert& cert) { - origin_certs_.erase(cert.origin()); -} - -void MockPersistentStore::SetClearLocalStateOnExit(bool clear_local_state) {} - -void MockPersistentStore::Flush(Task* completion_task) { - NOTREACHED(); -} - -TEST(DefaultOriginBoundCertStoreTest, TestLoading) { - scoped_refptr persistent_store(new MockPersistentStore); - - persistent_store->AddOriginBoundCert( - DefaultOriginBoundCertStore::OriginBoundCert( - "https://encrypted.google.com/", "a", "b")); - persistent_store->AddOriginBoundCert( - DefaultOriginBoundCertStore::OriginBoundCert( - "https://www.verisign.com/", "c", "d")); - - // Make sure certs load properly. - scoped_ptr store( - new DefaultOriginBoundCertStore(persistent_store)); - EXPECT_EQ(2, store->GetCertCount()); - EXPECT_TRUE(store->SetOriginBoundCert("https://www.verisign.com/", "e", "f")); - EXPECT_EQ(2, store->GetCertCount()); - EXPECT_TRUE(store->SetOriginBoundCert("https://www.twitter.com/", "g", "h")); - EXPECT_EQ(3, store->GetCertCount()); -} - -TEST(DefaultOriginBoundCertStoreTest, TestSettingAndGetting) { - scoped_ptr store( - new DefaultOriginBoundCertStore(NULL)); - std::string private_key, cert; - EXPECT_EQ(0, store->GetCertCount()); - EXPECT_FALSE(store->GetOriginBoundCert("https://www.verisign.com/", - &private_key, - &cert)); - EXPECT_TRUE(private_key.empty()); - EXPECT_TRUE(cert.empty()); - EXPECT_TRUE(store->SetOriginBoundCert("https://www.verisign.com/", "i", "j")); - EXPECT_TRUE(store->GetOriginBoundCert("https://www.verisign.com/", - &private_key, - &cert)); - EXPECT_EQ("i", private_key); - EXPECT_EQ("j", cert); -} - -} // namespace net diff --git a/net/base/origin_bound_cert_service.cc b/net/base/origin_bound_cert_service.cc index 61a80eb..0d706bc 100644 --- a/net/base/origin_bound_cert_service.cc +++ b/net/base/origin_bound_cert_service.cc @@ -11,6 +11,7 @@ #include "base/memory/scoped_ptr.h" #include "base/rand_util.h" #include "crypto/rsa_private_key.h" +#include "googleurl/src/gurl.h" #include "net/base/origin_bound_cert_store.h" #include "net/base/x509_certificate.h" @@ -23,23 +24,19 @@ const int kValidityPeriodInDays = 365; } // namespace -OriginBoundCertService::OriginBoundCertService( - OriginBoundCertStore* origin_bound_cert_store) - : origin_bound_cert_store_(origin_bound_cert_store) {} - -OriginBoundCertService::~OriginBoundCertService() {} - -bool OriginBoundCertService::GetOriginBoundCert(const std::string& origin, +bool OriginBoundCertService::GetOriginBoundCert(const GURL& url, std::string* private_key_result, std::string* cert_result) { // Check if origin bound cert already exists for this origin. - if (origin_bound_cert_store_->GetOriginBoundCert(origin, - private_key_result, - cert_result)) - return true; + if (origin_bound_cert_store_->HasOriginBoundCert(url)) { + return origin_bound_cert_store_->GetOriginBoundCert(url, + private_key_result, + cert_result); + } // No origin bound cert exists, we have to create one. - std::string subject = "CN=OBC"; + std::string origin = url.GetOrigin().spec(); + std::string subject = "CN=origin-bound certificate for " + origin; scoped_ptr key( crypto::RSAPrivateKey::Create(kKeySizeInBits)); if (!key.get()) { @@ -71,9 +68,7 @@ bool OriginBoundCertService::GetOriginBoundCert(const std::string& origin, return false; } - if (!origin_bound_cert_store_->SetOriginBoundCert(origin, - key_out, - der_cert)) { + if (!origin_bound_cert_store_->SetOriginBoundCert(url, key_out, der_cert)) { LOG(WARNING) << "Unable to set origin bound certificate"; return false; } @@ -83,8 +78,4 @@ bool OriginBoundCertService::GetOriginBoundCert(const std::string& origin, return true; } -int OriginBoundCertService::GetCertCount() { - return origin_bound_cert_store_->GetCertCount(); -} - } // namespace net diff --git a/net/base/origin_bound_cert_service.h b/net/base/origin_bound_cert_service.h index 9f700b9..c1d65b9 100644 --- a/net/base/origin_bound_cert_service.h +++ b/net/base/origin_bound_cert_service.h @@ -8,39 +8,30 @@ #include -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" +class GURL; namespace net { class OriginBoundCertStore; // A class for creating and fetching origin bound certs. -class OriginBoundCertService - : public base::RefCountedThreadSafe { +class OriginBoundCertService { public: - // This object owns origin_bound_cert_store. - explicit OriginBoundCertService( - OriginBoundCertStore* origin_bound_cert_store); - - ~OriginBoundCertService(); + explicit OriginBoundCertService(OriginBoundCertStore* origin_bound_cert_store) + : origin_bound_cert_store_(origin_bound_cert_store) {} // TODO(rkn): Specify certificate type (RSA or DSA). // TODO(rkn): Key generation can be time consuming, so this should have an // asynchronous interface. // Fetches the origin bound cert for the specified origin if one exists // and creates one otherwise. On success, |private_key_result| stores a - // DER-encoded PrivateKeyInfo struct, and |cert_result| stores a DER-encoded - // certificate. - bool GetOriginBoundCert(const std::string& origin, + // PrivateKeyInfo struct, and |cert_result| stores a DER-encoded certificate. + bool GetOriginBoundCert(const GURL& url, std::string* private_key_result, std::string* cert_result); - // Public only for unit testing. - int GetCertCount(); - private: - scoped_ptr origin_bound_cert_store_; + OriginBoundCertStore* origin_bound_cert_store_; }; } // namespace net diff --git a/net/base/origin_bound_cert_service_unittest.cc b/net/base/origin_bound_cert_service_unittest.cc deleted file mode 100644 index 59be848..0000000 --- a/net/base/origin_bound_cert_service_unittest.cc +++ /dev/null @@ -1,68 +0,0 @@ -// 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/base/origin_bound_cert_service.h" - -#include -#include - -#include "base/memory/ref_counted.h" -#include "crypto/rsa_private_key.h" -#include "net/base/default_origin_bound_cert_store.h" -#include "net/base/x509_certificate.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace net { - -TEST(OriginBoundCertServiceTest, DuplicateCertTest) { - scoped_refptr service( - new OriginBoundCertService(new DefaultOriginBoundCertStore(NULL))); - std::string origin1("https://encrypted.google.com/"); - std::string origin2("https://www.verisign.com/"); - - // The store should start out empty and should increment appropriately. - std::string private_key_info_1a, der_cert_1a; - EXPECT_EQ(0, service->GetCertCount()); - EXPECT_TRUE(service->GetOriginBoundCert( - origin1, &private_key_info_1a, &der_cert_1a)); - EXPECT_EQ(1, service->GetCertCount()); - - // We should get the same cert and key for the same origin. - std::string private_key_info_1b, der_cert_1b; - EXPECT_TRUE(service->GetOriginBoundCert( - origin1, &private_key_info_1b, &der_cert_1b)); - EXPECT_EQ(1, service->GetCertCount()); - EXPECT_EQ(private_key_info_1a, private_key_info_1b); - EXPECT_EQ(der_cert_1a, der_cert_1b); - - // We should get a different cert and key for different origins. - std::string private_key_info_2, der_cert_2; - EXPECT_TRUE(service->GetOriginBoundCert( - origin2, &private_key_info_2, &der_cert_2)); - EXPECT_EQ(2, service->GetCertCount()); - EXPECT_NE(private_key_info_1a, private_key_info_2); - EXPECT_NE(der_cert_1a, der_cert_2); -} - -TEST(OriginBoundCertServiceTest, ExtractValuesFromBytes) { - scoped_refptr service( - new OriginBoundCertService(new DefaultOriginBoundCertStore(NULL))); - std::string origin("https://encrypted.google.com/"); - std::string private_key_info, der_cert; - EXPECT_TRUE(service->GetOriginBoundCert( - origin, &private_key_info, &der_cert)); - std::vector key_vec(private_key_info.begin(), private_key_info.end()); - - // Check that we can retrieve the key pair from the bytes. - scoped_ptr private_key( - crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_vec)); - EXPECT_TRUE(private_key != NULL); - - // Check that we can retrieve the cert from the bytes. - scoped_refptr x509cert( - X509Certificate::CreateFromBytes(der_cert.data(), der_cert.size())); - EXPECT_TRUE(x509cert != NULL); -} - -} // namespace net diff --git a/net/base/origin_bound_cert_store.h b/net/base/origin_bound_cert_store.h index 63989f5..8529fbd 100644 --- a/net/base/origin_bound_cert_store.h +++ b/net/base/origin_bound_cert_store.h @@ -8,38 +8,29 @@ #include +class GURL; + namespace net { // An interface for storing and retrieving origin bound certs. Origin bound // certificates are specified in // http://balfanz.github.com/tls-obc-spec/draft-balfanz-tls-obc-00.html. -// Owned only by a single OriginBoundCertService object, which is responsible -// for deleting it. - class OriginBoundCertStore { public: - virtual ~OriginBoundCertStore() {} + virtual bool HasOriginBoundCert(const GURL& url) = 0; // TODO(rkn): Specify certificate type (RSA or DSA). - // TODO(rkn): File I/O may be required, so this should have an asynchronous - // interface. - // Returns true on success. |private_key_result| stores a DER-encoded - // PrivateKeyInfo struct and |cert_result| stores a DER-encoded - // certificate. Returns false if no origin bound cert exists for the - // specified origin. - virtual bool GetOriginBoundCert(const std::string& origin, + // TODO(rkn): Key generation can be time consuming, so this should have an + // asynchronous interface. + // The output is stored in |private_key_result| and |cert_result|. + virtual bool GetOriginBoundCert(const GURL& url, std::string* private_key_result, std::string* cert_result) = 0; - // Adds an origin bound cert to the store. - virtual bool SetOriginBoundCert(const std::string& origin, + virtual bool SetOriginBoundCert(const GURL& url, const std::string& private_key, const std::string& cert) = 0; - - // Returns the number of certs in the store. - // Public only for unit testing. - virtual int GetCertCount() = 0; }; } // namespace net -- cgit v1.1