diff options
18 files changed, 460 insertions, 75 deletions
diff --git a/chrome/browser/browsing_data_remover.cc b/chrome/browser/browsing_data_remover.cc index 25ef011..9273f01 100644 --- a/chrome/browser/browsing_data_remover.cc +++ b/chrome/browser/browsing_data_remover.cc @@ -49,6 +49,8 @@ #include "content/public/browser/user_metrics.h" #include "net/base/cookie_store.h" #include "net/base/net_errors.h" +#include "net/base/origin_bound_cert_service.h" +#include "net/base/origin_bound_cert_store.h" #include "net/base/transport_security_state.h" #include "net/disk_cache/disk_cache.h" #include "net/http/http_cache.h" @@ -95,12 +97,13 @@ BrowsingDataRemover::BrowsingDataRemover(Profile* profile, cache_(NULL), main_context_getter_(profile->GetRequestContext()), media_context_getter_(profile->GetRequestContextForMedia()), + waiting_for_clear_cache_(false), + waiting_for_clear_cookies_(false), waiting_for_clear_history_(false), - waiting_for_clear_quota_managed_data_(false), waiting_for_clear_networking_history_(false), - waiting_for_clear_cookies_(false), - waiting_for_clear_cache_(false), + waiting_for_clear_origin_bound_certs_(false), waiting_for_clear_plugin_data_(false), + waiting_for_clear_quota_managed_data_(false), remove_mask_(0) { DCHECK(profile); } @@ -117,12 +120,13 @@ BrowsingDataRemover::BrowsingDataRemover(Profile* profile, cache_(NULL), main_context_getter_(profile->GetRequestContext()), media_context_getter_(profile->GetRequestContextForMedia()), + waiting_for_clear_cache_(false), + waiting_for_clear_cookies_(false), waiting_for_clear_history_(false), - waiting_for_clear_quota_managed_data_(false), waiting_for_clear_networking_history_(false), - waiting_for_clear_cookies_(false), - waiting_for_clear_cache_(false), + waiting_for_clear_origin_bound_certs_(false), waiting_for_clear_plugin_data_(false), + waiting_for_clear_quota_managed_data_(false), remove_mask_(0) { DCHECK(profile); } @@ -225,6 +229,20 @@ void BrowsingDataRemover::Remove(int remove_mask) { } } + if (remove_mask & REMOVE_ORIGIN_BOUND_CERTS) { + content::RecordAction( + UserMetricsAction("ClearBrowsingData_OriginBoundCerts")); + // Since we are running on the UI thread don't call GetURLRequestContext(). + net::URLRequestContextGetter* rq_context = profile_->GetRequestContext(); + if (rq_context) { + waiting_for_clear_origin_bound_certs_ = true; + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&BrowsingDataRemover::ClearOriginBoundCertsOnIOThread, + base::Unretained(this), base::Unretained(rq_context))); + } + } + if (remove_mask & REMOVE_LOCAL_STORAGE) { // Remove data such as local databases, STS state, etc. These only can // be removed if a WEBKIT thread exists, so check that first: @@ -620,3 +638,22 @@ void BrowsingDataRemover::ClearCookiesOnIOThread( base::Bind(&BrowsingDataRemover::OnClearedCookies, base::Unretained(this))); } + +void BrowsingDataRemover::ClearOriginBoundCertsOnIOThread( + net::URLRequestContextGetter* rq_context) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + net::OriginBoundCertService* origin_bound_cert_service = + rq_context->GetURLRequestContext()->origin_bound_cert_service(); + origin_bound_cert_service->GetCertStore()->DeleteAllCreatedBetween( + delete_begin_, delete_end_); + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&BrowsingDataRemover::OnClearedOriginBoundCerts, + base::Unretained(this))); +} + +void BrowsingDataRemover::OnClearedOriginBoundCerts() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + waiting_for_clear_origin_bound_certs_ = false; + NotifyAndDeleteIfDone(); +} diff --git a/chrome/browser/browsing_data_remover.h b/chrome/browser/browsing_data_remover.h index 9bc68d9..7f47002 100644 --- a/chrome/browser/browsing_data_remover.h +++ b/chrome/browser/browsing_data_remover.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -70,12 +70,14 @@ class BrowsingDataRemover : public content::NotificationObserver, REMOVE_PLUGIN_DATA = 1 << 9, REMOVE_PASSWORDS = 1 << 10, REMOVE_WEBSQL = 1 << 11, + REMOVE_ORIGIN_BOUND_CERTS = 1 << 12, // "Site data" includes cookies, appcache, file systems, indexedDBs, local // storage, webSQL, and plugin data. REMOVE_SITE_DATA = REMOVE_APPCACHE | REMOVE_COOKIES | REMOVE_FILE_SYSTEMS | REMOVE_INDEXEDDB | REMOVE_LOCAL_STORAGE | - REMOVE_PLUGIN_DATA | REMOVE_WEBSQL + REMOVE_PLUGIN_DATA | REMOVE_WEBSQL | + REMOVE_ORIGIN_BOUND_CERTS }; // When BrowsingDataRemover successfully removes data, a notification of type @@ -208,6 +210,14 @@ class BrowsingDataRemover : public content::NotificationObserver, // Invoked on the IO thread to delete cookies. void ClearCookiesOnIOThread(net::URLRequestContextGetter* rq_context); + // Invoked on the IO thread to delete origin bound certs. + void ClearOriginBoundCertsOnIOThread( + net::URLRequestContextGetter* rq_context); + + // Callback when origin bound certs have been deleted. Invokes + // NotifyAndDeleteIfDone. + void OnClearedOriginBoundCerts(); + // Calculate the begin time for the deletion range specified by |time_period|. base::Time CalculateBeginDeleteTime(TimePeriod time_period); @@ -216,9 +226,10 @@ class BrowsingDataRemover : public content::NotificationObserver, return registrar_.IsEmpty() && !waiting_for_clear_cache_ && !waiting_for_clear_cookies_&& !waiting_for_clear_history_ && - !waiting_for_clear_quota_managed_data_ && !waiting_for_clear_networking_history_ && - !waiting_for_clear_plugin_data_; + !waiting_for_clear_origin_bound_certs_ && + !waiting_for_clear_plugin_data_ && + !waiting_for_clear_quota_managed_data_; } // Setter for removing_; DCHECKs that we can only start removing if we're not @@ -259,12 +270,13 @@ class BrowsingDataRemover : public content::NotificationObserver, // True if we're waiting for various data to be deleted. // These may only be accessed from UI thread in order to avoid races! + bool waiting_for_clear_cache_; + bool waiting_for_clear_cookies_; bool waiting_for_clear_history_; - bool waiting_for_clear_quota_managed_data_; bool waiting_for_clear_networking_history_; - bool waiting_for_clear_cookies_; - bool waiting_for_clear_cache_; + bool waiting_for_clear_origin_bound_certs_; bool waiting_for_clear_plugin_data_; + bool waiting_for_clear_quota_managed_data_; // Tracking how many origins need to be deleted, and whether we're finished // gathering origins. diff --git a/chrome/browser/browsing_data_remover_unittest.cc b/chrome/browser/browsing_data_remover_unittest.cc index 97a5c8e..6c88aa3 100644 --- a/chrome/browser/browsing_data_remover_unittest.cc +++ b/chrome/browser/browsing_data_remover_unittest.cc @@ -5,6 +5,7 @@ #include "chrome/browser/browsing_data_remover.h" #include <set> +#include <vector> #include "base/bind.h" #include "base/bind_helpers.h" @@ -19,6 +20,9 @@ #include "content/public/browser/notification_service.h" #include "content/test/test_browser_thread.h" #include "net/base/cookie_monster.h" +#include "net/base/origin_bound_cert_service.h" +#include "net/base/origin_bound_cert_store.h" +#include "net/base/ssl_client_cert_type.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" #include "testing/gtest/include/gtest/gtest.h" @@ -139,6 +143,51 @@ class RemoveCookieTester : public BrowsingDataRemoverTester { DISALLOW_COPY_AND_ASSIGN(RemoveCookieTester); }; +class RemoveOriginBoundCertTester : public BrowsingDataRemoverTester { + public: + explicit RemoveOriginBoundCertTester(TestingProfile* profile) { + profile->CreateRequestContext(); + ob_cert_service_ = profile->GetRequestContext()->GetURLRequestContext()-> + origin_bound_cert_service(); + } + + int OriginBoundCertCount() { + return ob_cert_service_->cert_count(); + } + + // Add an origin bound cert for |origin| with specific creation and expiry + // times. The cert and key data will be filled with dummy values. + void AddOriginBoundCertWithTimes(const std::string& origin, + base::Time creation_time, + base::Time expiration_time) { + GetCertStore()->SetOriginBoundCert(origin, net::CLIENT_CERT_RSA_SIGN, + creation_time, expiration_time, + "a", "b"); + } + + // Add an origin bound cert for |origin|, with the current time as the + // creation time. The cert and key data will be filled with dummy values. + void AddOriginBoundCert(const std::string& origin) { + base::Time now = base::Time::Now(); + AddOriginBoundCertWithTimes(origin, + now, + now + base::TimeDelta::FromDays(1)); + } + + net::OriginBoundCertStore* GetCertStore() { + return ob_cert_service_->GetCertStore(); + } + + private: + net::OriginBoundCertService* ob_cert_service_; + + net::SSLClientCertType type_; + std::string key_; + std::string cert_; + + DISALLOW_COPY_AND_ASSIGN(RemoveOriginBoundCertTester); +}; + class RemoveHistoryTester : public BrowsingDataRemoverTester { public: explicit RemoveHistoryTester(TestingProfile* profile) @@ -349,6 +398,41 @@ TEST_F(BrowsingDataRemoverTest, RemoveCookieForever) { EXPECT_FALSE(tester->ContainsCookie()); } +TEST_F(BrowsingDataRemoverTest, RemoveOriginBoundCertForever) { + scoped_ptr<RemoveOriginBoundCertTester> tester( + new RemoveOriginBoundCertTester(GetProfile())); + + tester->AddOriginBoundCert(kTestkOrigin1); + EXPECT_EQ(1, tester->OriginBoundCertCount()); + + BlockUntilBrowsingDataRemoved(BrowsingDataRemover::EVERYTHING, + BrowsingDataRemover::REMOVE_ORIGIN_BOUND_CERTS, tester.get()); + + EXPECT_EQ(BrowsingDataRemover::REMOVE_ORIGIN_BOUND_CERTS, GetRemovalMask()); + EXPECT_EQ(0, tester->OriginBoundCertCount()); +} + +TEST_F(BrowsingDataRemoverTest, RemoveOriginBoundCertLastHour) { + scoped_ptr<RemoveOriginBoundCertTester> tester( + new RemoveOriginBoundCertTester(GetProfile())); + + base::Time now = base::Time::Now(); + tester->AddOriginBoundCert(kTestkOrigin1); + tester->AddOriginBoundCertWithTimes(kTestkOrigin2, + now - base::TimeDelta::FromHours(2), + now); + EXPECT_EQ(2, tester->OriginBoundCertCount()); + + BlockUntilBrowsingDataRemoved(BrowsingDataRemover::LAST_HOUR, + BrowsingDataRemover::REMOVE_ORIGIN_BOUND_CERTS, tester.get()); + + EXPECT_EQ(BrowsingDataRemover::REMOVE_ORIGIN_BOUND_CERTS, GetRemovalMask()); + EXPECT_EQ(1, tester->OriginBoundCertCount()); + std::vector<net::OriginBoundCertStore::OriginBoundCert> certs; + tester->GetCertStore()->GetAllOriginBoundCerts(&certs); + EXPECT_EQ(kTestkOrigin2, certs[0].origin()); +} + TEST_F(BrowsingDataRemoverTest, RemoveHistoryForever) { scoped_ptr<RemoveHistoryTester> tester( new RemoveHistoryTester(GetProfile())); diff --git a/chrome/browser/extensions/extension_clear_api.cc b/chrome/browser/extensions/extension_clear_api.cc index d1251cb..05d23e3 100644 --- a/chrome/browser/extensions/extension_clear_api.cc +++ b/chrome/browser/extensions/extension_clear_api.cc @@ -34,6 +34,7 @@ const char kFormDataKey[] = "formData"; const char kHistoryKey[] = "history"; const char kIndexedDBKey[] = "indexedDB"; const char kLocalStorageKey[] = "localStorage"; +const char kOriginBoundCertsKey[] = "originBoundCerts"; const char kPasswordsKey[] = "passwords"; const char kPluginDataKey[] = "pluginData"; const char kWebSQLKey[] = "webSQL"; @@ -84,6 +85,9 @@ int ParseRemovalMask(base::DictionaryValue* value) { if (DataRemovalRequested(value, extension_clear_api_constants::kLocalStorageKey)) GetRemovalMask |= BrowsingDataRemover::REMOVE_LOCAL_STORAGE; + if (DataRemovalRequested(value, + extension_clear_api_constants::kOriginBoundCertsKey)) + GetRemovalMask |= BrowsingDataRemover::REMOVE_ORIGIN_BOUND_CERTS; if (DataRemovalRequested(value, extension_clear_api_constants::kPasswordsKey)) GetRemovalMask |= BrowsingDataRemover::REMOVE_PASSWORDS; if (DataRemovalRequested(value, @@ -209,6 +213,10 @@ int ClearLocalStorageFunction::GetRemovalMask() const { return BrowsingDataRemover::REMOVE_LOCAL_STORAGE; } +int ClearOriginBoundCertsFunction::GetRemovalMask() const { + return BrowsingDataRemover::REMOVE_ORIGIN_BOUND_CERTS; +} + int ClearPluginDataFunction::GetRemovalMask() const { return BrowsingDataRemover::REMOVE_PLUGIN_DATA; } diff --git a/chrome/browser/extensions/extension_clear_api.h b/chrome/browser/extensions/extension_clear_api.h index bd58aae..387486b 100644 --- a/chrome/browser/extensions/extension_clear_api.h +++ b/chrome/browser/extensions/extension_clear_api.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -192,6 +192,18 @@ class ClearLocalStorageFunction : public BrowsingDataExtensionFunction { DECLARE_EXTENSION_FUNCTION_NAME("experimental.clear.localStorage") }; +class ClearOriginBoundCertsFunction : public BrowsingDataExtensionFunction { + public: + ClearOriginBoundCertsFunction() {} + virtual ~ClearOriginBoundCertsFunction() {} + + protected: + // BrowsingDataTypeExtensionFunction interface method. + virtual int GetRemovalMask() const OVERRIDE; + + DECLARE_EXTENSION_FUNCTION_NAME("experimental.clear.originBoundCerts") +}; + class ClearPluginDataFunction : public BrowsingDataExtensionFunction { public: ClearPluginDataFunction() {} diff --git a/chrome/browser/extensions/extension_clear_test.cc b/chrome/browser/extensions/extension_clear_test.cc index ac038da..1f050f2 100644 --- a/chrome/browser/extensions/extension_clear_test.cc +++ b/chrome/browser/extensions/extension_clear_test.cc @@ -27,7 +27,8 @@ const char kClearEverythingArguments[] = "[1000, {" "\"appcache\": true, \"cache\": true, \"cookies\": true, " "\"downloads\": true, \"fileSystems\": true, \"formData\": true, " "\"history\": true, \"indexedDB\": true, \"localStorage\": true, " - "\"pluginData\": true, \"passwords\": true, \"webSQL\": true" + "\"originBoundCerts\": true, \"passwords\": true, \"pluginData\": true, " + "\"webSQL\": true" "}]"; class ExtensionClearTest : public InProcessBrowserTest, @@ -129,6 +130,8 @@ IN_PROC_BROWSER_TEST_F(ExtensionClearTest, ClearBrowsingDataMask) { RunClearBrowsingDataFunctionAndCompareMask( "localStorage", BrowsingDataRemover::REMOVE_LOCAL_STORAGE); RunClearBrowsingDataFunctionAndCompareMask( + "originBoundCerts", BrowsingDataRemover::REMOVE_ORIGIN_BOUND_CERTS); + RunClearBrowsingDataFunctionAndCompareMask( "passwords", BrowsingDataRemover::REMOVE_PASSWORDS); // We can't remove plugin data inside a test profile. RunClearBrowsingDataFunctionAndCompareMask( diff --git a/chrome/browser/net/sqlite_origin_bound_cert_store.cc b/chrome/browser/net/sqlite_origin_bound_cert_store.cc index 90a9ddd..9c6538e 100644 --- a/chrome/browser/net/sqlite_origin_bound_cert_store.cc +++ b/chrome/browser/net/sqlite_origin_bound_cert_store.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -118,7 +118,7 @@ class SQLiteOriginBoundCertStore::Backend }; // Version number of the database. -static const int kCurrentVersionNumber = 3; +static const int kCurrentVersionNumber = 4; static const int kCompatibleVersionNumber = 1; namespace { @@ -131,7 +131,8 @@ bool InitTable(sql::Connection* db) { "private_key BLOB NOT NULL," "cert BLOB NOT NULL," "cert_type INTEGER," - "expiration_time INTEGER)")) + "expiration_time INTEGER," + "creation_time INTEGER)")) return false; } @@ -173,8 +174,8 @@ bool SQLiteOriginBoundCertStore::Backend::Load( // Slurp all the certs into the out-vector. sql::Statement smt(db_->GetUniqueStatement( - "SELECT origin, private_key, cert, cert_type, expiration_time " - "FROM origin_bound_certs")); + "SELECT origin, private_key, cert, cert_type, expiration_time, " + "creation_time FROM origin_bound_certs")); if (!smt) { NOTREACHED() << "select statement prep failed"; db_.reset(); @@ -189,6 +190,7 @@ bool SQLiteOriginBoundCertStore::Backend::Load( new net::DefaultOriginBoundCertStore::OriginBoundCert( smt.ColumnString(0), // origin static_cast<net::SSLClientCertType>(smt.ColumnInt(3)), + base::Time::FromInternalValue(smt.ColumnInt64(5)), base::Time::FromInternalValue(smt.ColumnInt64(4)), private_key_from_db, cert_from_db)); @@ -234,29 +236,36 @@ bool SQLiteOriginBoundCertStore::Backend::EnsureDatabaseVersion() { transaction.Commit(); } - if (cur_version == 2) { + if (cur_version <= 3) { sql::Transaction transaction(db_.get()); if (!transaction.Begin()) return false; + + if (cur_version == 2) { + if (!db_->Execute("ALTER TABLE origin_bound_certs ADD COLUMN " + "expiration_time INTEGER")) { + LOG(WARNING) << "Unable to update origin bound cert database to " + << "version 4."; + return false; + } + } + if (!db_->Execute("ALTER TABLE origin_bound_certs ADD COLUMN " - "expiration_time INTEGER")) { + "creation_time INTEGER")) { LOG(WARNING) << "Unable to update origin bound cert database to " - << "version 3."; + << "version 4."; return false; } sql::Statement smt(db_->GetUniqueStatement( "SELECT origin, cert FROM origin_bound_certs")); - if (!smt) { - LOG(WARNING) << "Unable to update origin bound cert database to " - << "version 3."; - return false; - } sql::Statement update_expires_smt(db_->GetUniqueStatement( "UPDATE origin_bound_certs SET expiration_time = ? WHERE origin = ?")); - if (!update_expires_smt) { + sql::Statement update_creation_smt(db_->GetUniqueStatement( + "UPDATE origin_bound_certs SET creation_time = ? WHERE origin = ?")); + if (!smt || !update_expires_smt || !update_creation_smt) { LOG(WARNING) << "Unable to update origin bound cert database to " - << "version 3."; + << "version 4."; return false; } while (smt.Step()) { @@ -268,12 +277,24 @@ bool SQLiteOriginBoundCertStore::Backend::EnsureDatabaseVersion() { net::X509Certificate::CreateFromBytes( cert_from_db.data(), cert_from_db.size())); if (cert) { - update_expires_smt.Reset(); - update_expires_smt.BindInt64(0, cert->valid_expiry().ToInternalValue()); - update_expires_smt.BindString(1, origin); - if (!update_expires_smt.Run()) { + if (cur_version == 2) { + update_expires_smt.Reset(); + update_expires_smt.BindInt64(0, + cert->valid_expiry().ToInternalValue()); + update_expires_smt.BindString(1, origin); + if (!update_expires_smt.Run()) { + LOG(WARNING) << "Unable to update origin bound cert database to " + << "version 4."; + return false; + } + } + + update_creation_smt.Reset(); + update_creation_smt.BindInt64(0, cert->valid_start().ToInternalValue()); + update_creation_smt.BindString(1, origin); + if (!update_creation_smt.Run()) { LOG(WARNING) << "Unable to update origin bound cert database to " - << "version 3."; + << "version 4."; return false; } } else { @@ -284,7 +305,7 @@ bool SQLiteOriginBoundCertStore::Backend::EnsureDatabaseVersion() { } } - ++cur_version; + cur_version = 4; meta_table_.SetVersionNumber(cur_version); meta_table_.SetCompatibleVersionNumber( std::min(cur_version, kCompatibleVersionNumber)); diff --git a/chrome/browser/net/sqlite_origin_bound_cert_store_unittest.cc b/chrome/browser/net/sqlite_origin_bound_cert_store_unittest.cc index 5ee226e..c1715e0 100644 --- a/chrome/browser/net/sqlite_origin_bound_cert_store_unittest.cc +++ b/chrome/browser/net/sqlite_origin_bound_cert_store_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -43,6 +43,20 @@ class SQLiteOriginBoundCertStoreTest : public testing::Test { return base::Time::FromInternalValue(GG_INT64_C(16121816625000000)); } + static base::Time GetTestCertCreationTime() { + // UTCTime 13/12/2011 02:23:45 GMT + base::Time::Exploded exploded_time; + exploded_time.year = 2011; + exploded_time.month = 12; + exploded_time.day_of_week = 0; // Unused. + exploded_time.day_of_month = 13; + exploded_time.hour = 2; + exploded_time.minute = 23; + exploded_time.second = 45; + exploded_time.millisecond = 0; + return base::Time::FromUTCExploded(exploded_time); + } + virtual void SetUp() { db_thread_.Start(); ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); @@ -57,6 +71,7 @@ class SQLiteOriginBoundCertStoreTest : public testing::Test { "https://encrypted.google.com:8443", net::CLIENT_CERT_RSA_SIGN, base::Time(), + base::Time(), "a", "b")); } @@ -103,6 +118,7 @@ TEST_F(SQLiteOriginBoundCertStoreTest, TestPersistence) { "https://www.google.com/", net::CLIENT_CERT_ECDSA_SIGN, base::Time(), + base::Time(), "c", "d")); ScopedVector<net::DefaultOriginBoundCertStore::OriginBoundCert> certs; @@ -233,7 +249,7 @@ TEST_F(SQLiteOriginBoundCertStoreTest, TestUpgradeV1) { "SELECT value FROM meta WHERE key = \"version\"")); ASSERT_TRUE(smt); ASSERT_TRUE(smt.Step()); - EXPECT_EQ(3, smt.ColumnInt(0)); + EXPECT_EQ(4, smt.ColumnInt(0)); EXPECT_FALSE(smt.Step()); } } @@ -322,7 +338,100 @@ TEST_F(SQLiteOriginBoundCertStoreTest, TestUpgradeV2) { "SELECT value FROM meta WHERE key = \"version\"")); ASSERT_TRUE(smt); ASSERT_TRUE(smt.Step()); - EXPECT_EQ(3, smt.ColumnInt(0)); + EXPECT_EQ(4, smt.ColumnInt(0)); + EXPECT_FALSE(smt.Step()); + } + } +} + +TEST_F(SQLiteOriginBoundCertStoreTest, TestUpgradeV3) { + // Reset the store. We'll be using a different database for this test. + store_ = NULL; + + FilePath v3_db_path(temp_dir_.path().AppendASCII("v3db")); + + std::string key_data; + std::string cert_data; + ReadTestKeyAndCert(&key_data, &cert_data); + + // Create a version 3 database. + { + sql::Connection db; + ASSERT_TRUE(db.Open(v3_db_path)); + ASSERT_TRUE(db.Execute( + "CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY," + "value LONGVARCHAR);" + "INSERT INTO \"meta\" VALUES('version','3');" + "INSERT INTO \"meta\" VALUES('last_compatible_version','1');" + "CREATE TABLE origin_bound_certs (" + "origin TEXT NOT NULL UNIQUE PRIMARY KEY," + "private_key BLOB NOT NULL," + "cert BLOB NOT NULL," + "cert_type INTEGER," + "expiration_time INTEGER);" + )); + + sql::Statement add_smt(db.GetUniqueStatement( + "INSERT INTO origin_bound_certs (origin, private_key, cert, cert_type, " + "expiration_time) VALUES (?,?,?,?,?)")); + add_smt.BindString(0, "https://www.google.com:443"); + add_smt.BindBlob(1, key_data.data(), key_data.size()); + add_smt.BindBlob(2, cert_data.data(), cert_data.size()); + add_smt.BindInt64(3, 1); + add_smt.BindInt64(4, 1000); + ASSERT_TRUE(add_smt.Run()); + + ASSERT_TRUE(db.Execute( + "INSERT INTO \"origin_bound_certs\" VALUES(" + "'https://foo.com',X'AA',X'BB',64,2000);" + )); + } + + // Load and test the DB contents twice. First time ensures that we can use + // the updated values immediately. Second time ensures that the updated + // values are saved and read correctly on next load. + for (int i = 0; i < 2; ++i) { + SCOPED_TRACE(i); + + ScopedVector<net::DefaultOriginBoundCertStore::OriginBoundCert> certs; + store_ = new SQLiteOriginBoundCertStore(v3_db_path); + + // Load the database and ensure the certs can be read and are marked as RSA. + ASSERT_TRUE(store_->Load(&certs.get())); + ASSERT_EQ(2U, certs.size()); + + ASSERT_STREQ("https://www.google.com:443", certs[0]->origin().c_str()); + ASSERT_EQ(net::CLIENT_CERT_RSA_SIGN, certs[0]->type()); + ASSERT_EQ(1000, certs[0]->expiration_time().ToInternalValue()); + ASSERT_EQ(GetTestCertCreationTime(), + certs[0]->creation_time()); + ASSERT_EQ(key_data, certs[0]->private_key()); + ASSERT_EQ(cert_data, certs[0]->cert()); + + ASSERT_STREQ("https://foo.com", certs[1]->origin().c_str()); + ASSERT_EQ(net::CLIENT_CERT_ECDSA_SIGN, certs[1]->type()); + ASSERT_EQ(2000, certs[1]->expiration_time().ToInternalValue()); + // Undecodable cert, creation time will be uninitialized. + ASSERT_EQ(base::Time(), certs[1]->creation_time()); + ASSERT_STREQ("\xaa", certs[1]->private_key().c_str()); + ASSERT_STREQ("\xbb", certs[1]->cert().c_str()); + + store_ = NULL; + // Make sure we wait until the destructor has run. + scoped_refptr<base::ThreadTestHelper> helper( + new base::ThreadTestHelper( + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB))); + ASSERT_TRUE(helper->Run()); + + // Verify the database version is updated. + { + sql::Connection db; + ASSERT_TRUE(db.Open(v3_db_path)); + sql::Statement smt(db.GetUniqueStatement( + "SELECT value FROM meta WHERE key = \"version\"")); + ASSERT_TRUE(smt); + ASSERT_TRUE(smt.Step()); + EXPECT_EQ(4, smt.ColumnInt(0)); EXPECT_FALSE(smt.Step()); } } @@ -347,6 +456,7 @@ TEST_F(SQLiteOriginBoundCertStoreTest, TestFlush) { origin, net::CLIENT_CERT_RSA_SIGN, base::Time(), + base::Time(), private_key, cert)); } diff --git a/chrome/tools/chromeactions.txt b/chrome/tools/chromeactions.txt index 92c228b..b1e73be 100644 --- a/chrome/tools/chromeactions.txt +++ b/chrome/tools/chromeactions.txt @@ -8,6 +8,7 @@ 0xc5ec36aaa32ceff4 AboutFlags_confirm-to-quit 0x4e8fe1c674de45dd AboutFlags_conflicting-modules-check 0xe9d2339d6b9225c7 AboutFlags_disable-outdated-plugins +0xf73b5212b48e2a75 AboutFlags_disable-print-preview 0xdddbf34cee2c636c AboutFlags_dns-server 0x3add7fc42803849e AboutFlags_downloads-new-ui 0x4eae5ccc2900dffa AboutFlags_enable-nacl @@ -180,6 +181,7 @@ 0xea9b835bf0310f85 ClearBrowsingData_Downloads 0xe3c9686626019346 ClearBrowsingData_History 0x86678d0ede469c46 ClearBrowsingData_LSOData +0x82601d6a3aca0eb1 ClearBrowsingData_OriginBoundCerts 0x511e8366cdda3890 ClearBrowsingData_Passwords 0x6d69a061f7adf595 ClearBrowsingData_ShowDlg 0x9fd631c62234969a ClearSelection @@ -252,6 +254,7 @@ 0x4f07c158c8047ab9 Extensions.ExtensionUninstalled 0x08566bf746b7f665 Extensions.IDChangedError 0xa295e3ad39bbacc0 Extensions.WebStoreLaunch +0xbea4c2c8eb82d058 Feedback 0x4268aeb48d5c0d1e FileBrowser.CreateNewFolder 0x604a1468d08b7c7b FileBrowser.PhotoEditor.Edit 0xca74d47b273dd801 FileBrowser.PhotoEditor.View @@ -870,6 +873,7 @@ 0x9372bb835cd720fb MoveWordForward 0x002e07cb5223cd33 MoveWordLeft 0xd55f7c4e520b18a4 MoveWordRight +0xfc8e40d96ab33f1b NTPPromoClosed 0x0cdd043c5d63d234 NTPPromoShown 0xdcf1af37de1d8dd0 NativeUI_Applications 0x3c6e0d9310ba3a20 NewIncognitoWindow @@ -957,6 +961,8 @@ 0x84502179f3e2ae8c Options_ManagerCerts 0x540bea8eaba24835 Options_MetricsReportingCheckbox_Disable 0x4aa2c70a745dbb49 Options_MetricsReportingCheckbox_Enable +0x224b0bf60dccdeda Options_MousePrimaryRight_Disable +0xb23cd3cde814d929 Options_MousePrimaryRight_Enable 0xc5fbe9d9b3a165dd Options_PasswordManager_Disable 0x59b4f208d9d9f648 Options_PasswordManager_Enable 0x6149925370ef4f47 Options_PluginsCheckbox_Disable @@ -994,6 +1000,8 @@ 0x6f37e83ce98b3082 Options_TapToClickCheckbox_Enable 0x73defd4825af2700 Options_ThemesGallery 0x60d52658d42b1593 Options_ThemesReset +0x4a469294c73f23e4 Options_TouchpadTapToClick_Disable +0x61a29472d343cf72 Options_TouchpadTapToClick_Enable 0xa35806253d8d8b30 Options_Translate_Disable 0x280bb55487be6eb4 Options_Translate_Enable 0x6f40a6712a19568a Options_UseSuggestCheckbox_Disable @@ -1059,6 +1067,8 @@ 0x6cc1116fbd900ebf PasswordManager_Enabled 0x36bb6559696dc912 Paste 0x5d0e6942f354a06c PasteAndMatchStyle +0xca471265efb33961 PluginContextMenu_RotateClockwise +0xa260d9dde6e550c4 PluginContextMenu_RotateCounterclockwise 0x6f2cd84fa374c281 Plugin_Blocked 0xcecb82fcd8e64529 Plugin_ClickToPlay 0xc52b281d793adc6b Plugin_Hide_Click @@ -1142,6 +1152,7 @@ 0xfd243b004d004e00 ShowSections_RecentSitesDisabled 0x3b86156dcf560cdb ShowSections_RecentSitesEnabled 0x5118181c3ece5e84 ShowSessions +0x1a4ebb180ba59b06 Shutdown 0x26f93e6e68e28a69 Star 0x2fbe99005588ef01 StartupTick 0x11a755d598c0c417 Stop diff --git a/net/base/default_origin_bound_cert_store.cc b/net/base/default_origin_bound_cert_store.cc index 3c311ca..8e721ae 100644 --- a/net/base/default_origin_bound_cert_store.cc +++ b/net/base/default_origin_bound_cert_store.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -30,6 +30,7 @@ void DefaultOriginBoundCertStore::FlushStore( bool DefaultOriginBoundCertStore::GetOriginBoundCert( const std::string& origin, SSLClientCertType* type, + base::Time* creation_time, base::Time* expiration_time, std::string* private_key_result, std::string* cert_result) { @@ -43,6 +44,7 @@ bool DefaultOriginBoundCertStore::GetOriginBoundCert( OriginBoundCert* cert = it->second; *type = cert->type(); + *creation_time = cert->creation_time(); *expiration_time = cert->expiration_time(); *private_key_result = cert->private_key(); *cert_result = cert->cert(); @@ -53,6 +55,7 @@ bool DefaultOriginBoundCertStore::GetOriginBoundCert( void DefaultOriginBoundCertStore::SetOriginBoundCert( const std::string& origin, SSLClientCertType type, + base::Time creation_time, base::Time expiration_time, const std::string& private_key, const std::string& cert) { @@ -62,7 +65,8 @@ void DefaultOriginBoundCertStore::SetOriginBoundCert( InternalDeleteOriginBoundCert(origin); InternalInsertOriginBoundCert( origin, - new OriginBoundCert(origin, type, expiration_time, private_key, cert)); + new OriginBoundCert( + origin, type, creation_time, expiration_time, private_key, cert)); } void DefaultOriginBoundCertStore::DeleteOriginBoundCert( @@ -72,17 +76,28 @@ void DefaultOriginBoundCertStore::DeleteOriginBoundCert( InternalDeleteOriginBoundCert(origin); } -void DefaultOriginBoundCertStore::DeleteAll() { +void DefaultOriginBoundCertStore::DeleteAllCreatedBetween( + base::Time delete_begin, + base::Time delete_end) { base::AutoLock autolock(lock_); InitIfNecessary(); for (OriginBoundCertMap::iterator it = origin_bound_certs_.begin(); - it != origin_bound_certs_.end(); ++it) { - OriginBoundCert* cert = it->second; - if (store_) - store_->DeleteOriginBoundCert(*cert); - delete cert; + it != origin_bound_certs_.end();) { + OriginBoundCertMap::iterator cur = it; + ++it; + OriginBoundCert* cert = cur->second; + if ((delete_begin.is_null() || cert->creation_time() >= delete_begin) && + (delete_end.is_null() || cert->creation_time() < delete_end)) { + if (store_) + store_->DeleteOriginBoundCert(*cert); + delete cert; + origin_bound_certs_.erase(cur); + } } - origin_bound_certs_.clear(); +} + +void DefaultOriginBoundCertStore::DeleteAll() { + DeleteAllCreatedBetween(base::Time(), base::Time()); } void DefaultOriginBoundCertStore::GetAllOriginBoundCerts( diff --git a/net/base/default_origin_bound_cert_store.h b/net/base/default_origin_bound_cert_store.h index 1714248..e717d38 100644 --- a/net/base/default_origin_bound_cert_store.h +++ b/net/base/default_origin_bound_cert_store.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -57,16 +57,20 @@ class NET_EXPORT DefaultOriginBoundCertStore : public OriginBoundCertStore { virtual bool GetOriginBoundCert( const std::string& origin, SSLClientCertType* type, + base::Time* creation_time, base::Time* expiration_time, std::string* private_key_result, std::string* cert_result) OVERRIDE; virtual void SetOriginBoundCert( const std::string& origin, SSLClientCertType type, + base::Time creation_time, base::Time expiration_time, const std::string& private_key, const std::string& cert) OVERRIDE; virtual void DeleteOriginBoundCert(const std::string& origin) OVERRIDE; + virtual void DeleteAllCreatedBetween(base::Time delete_begin, + base::Time delete_end) OVERRIDE; virtual void DeleteAll() OVERRIDE; virtual void GetAllOriginBoundCerts( std::vector<OriginBoundCert>* origin_bound_certs) OVERRIDE; diff --git a/net/base/default_origin_bound_cert_store_unittest.cc b/net/base/default_origin_bound_cert_store_unittest.cc index a62191a..ec55716 100644 --- a/net/base/default_origin_bound_cert_store_unittest.cc +++ b/net/base/default_origin_bound_cert_store_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -80,12 +80,14 @@ TEST(DefaultOriginBoundCertStoreTest, TestLoading) { "https://encrypted.google.com/", CLIENT_CERT_RSA_SIGN, base::Time(), + base::Time(), "a", "b")); persistent_store->AddOriginBoundCert( DefaultOriginBoundCertStore::OriginBoundCert( "https://www.verisign.com/", CLIENT_CERT_ECDSA_SIGN, base::Time(), + base::Time(), "c", "d")); // Make sure certs load properly. @@ -94,13 +96,15 @@ TEST(DefaultOriginBoundCertStoreTest, TestLoading) { store.SetOriginBoundCert( "https://www.verisign.com/", CLIENT_CERT_RSA_SIGN, - base::Time(), + base::Time(), + base::Time(), "e", "f"); EXPECT_EQ(2, store.GetCertCount()); store.SetOriginBoundCert( "https://www.twitter.com/", CLIENT_CERT_RSA_SIGN, base::Time(), + base::Time(), "g", "h"); EXPECT_EQ(3, store.GetCertCount()); } @@ -108,11 +112,13 @@ TEST(DefaultOriginBoundCertStoreTest, TestLoading) { TEST(DefaultOriginBoundCertStoreTest, TestSettingAndGetting) { DefaultOriginBoundCertStore store(NULL); SSLClientCertType type; + base::Time creation_time; base::Time expiration_time; std::string private_key, cert; EXPECT_EQ(0, store.GetCertCount()); EXPECT_FALSE(store.GetOriginBoundCert("https://www.verisign.com/", &type, + &creation_time, &expiration_time, &private_key, &cert)); @@ -122,14 +128,17 @@ TEST(DefaultOriginBoundCertStoreTest, TestSettingAndGetting) { "https://www.verisign.com/", CLIENT_CERT_RSA_SIGN, base::Time::FromInternalValue(123), + base::Time::FromInternalValue(456), "i", "j"); EXPECT_TRUE(store.GetOriginBoundCert("https://www.verisign.com/", &type, + &creation_time, &expiration_time, &private_key, &cert)); EXPECT_EQ(CLIENT_CERT_RSA_SIGN, type); - EXPECT_EQ(123, expiration_time.ToInternalValue()); + EXPECT_EQ(123, creation_time.ToInternalValue()); + EXPECT_EQ(456, expiration_time.ToInternalValue()); EXPECT_EQ("i", private_key); EXPECT_EQ("j", cert); } @@ -139,6 +148,7 @@ TEST(DefaultOriginBoundCertStoreTest, TestDuplicateCerts) { DefaultOriginBoundCertStore store(persistent_store.get()); SSLClientCertType type; + base::Time creation_time; base::Time expiration_time; std::string private_key, cert; EXPECT_EQ(0, store.GetCertCount()); @@ -146,21 +156,25 @@ TEST(DefaultOriginBoundCertStoreTest, TestDuplicateCerts) { "https://www.verisign.com/", CLIENT_CERT_RSA_SIGN, base::Time::FromInternalValue(123), + base::Time::FromInternalValue(1234), "a", "b"); store.SetOriginBoundCert( "https://www.verisign.com/", CLIENT_CERT_ECDSA_SIGN, base::Time::FromInternalValue(456), + base::Time::FromInternalValue(4567), "c", "d"); EXPECT_EQ(1, store.GetCertCount()); EXPECT_TRUE(store.GetOriginBoundCert("https://www.verisign.com/", &type, + &creation_time, &expiration_time, &private_key, &cert)); EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type); - EXPECT_EQ(456, expiration_time.ToInternalValue()); + EXPECT_EQ(456, creation_time.ToInternalValue()); + EXPECT_EQ(4567, expiration_time.ToInternalValue()); EXPECT_EQ("c", private_key); EXPECT_EQ("d", cert); } @@ -174,16 +188,19 @@ TEST(DefaultOriginBoundCertStoreTest, TestDeleteAll) { "https://www.verisign.com/", CLIENT_CERT_RSA_SIGN, base::Time(), + base::Time(), "a", "b"); store.SetOriginBoundCert( "https://www.google.com/", CLIENT_CERT_RSA_SIGN, base::Time(), + base::Time(), "c", "d"); store.SetOriginBoundCert( "https://www.harvard.com/", CLIENT_CERT_RSA_SIGN, base::Time(), + base::Time(), "e", "f"); EXPECT_EQ(3, store.GetCertCount()); @@ -196,6 +213,7 @@ TEST(DefaultOriginBoundCertStoreTest, TestDelete) { DefaultOriginBoundCertStore store(persistent_store.get()); SSLClientCertType type; + base::Time creation_time; base::Time expiration_time; std::string private_key, cert; EXPECT_EQ(0, store.GetCertCount()); @@ -203,11 +221,13 @@ TEST(DefaultOriginBoundCertStoreTest, TestDelete) { "https://www.verisign.com/", CLIENT_CERT_RSA_SIGN, base::Time(), + base::Time(), "a", "b"); store.SetOriginBoundCert( "https://www.google.com/", CLIENT_CERT_ECDSA_SIGN, base::Time(), + base::Time(), "c", "d"); EXPECT_EQ(2, store.GetCertCount()); @@ -215,11 +235,13 @@ TEST(DefaultOriginBoundCertStoreTest, TestDelete) { EXPECT_EQ(1, store.GetCertCount()); EXPECT_FALSE(store.GetOriginBoundCert("https://www.verisign.com/", &type, + &creation_time, &expiration_time, &private_key, &cert)); EXPECT_TRUE(store.GetOriginBoundCert("https://www.google.com/", &type, + &creation_time, &expiration_time, &private_key, &cert)); @@ -227,6 +249,7 @@ TEST(DefaultOriginBoundCertStoreTest, TestDelete) { EXPECT_EQ(0, store.GetCertCount()); EXPECT_FALSE(store.GetOriginBoundCert("https://www.google.com/", &type, + &creation_time, &expiration_time, &private_key, &cert)); @@ -241,21 +264,25 @@ TEST(DefaultOriginBoundCertStoreTest, TestGetAll) { "https://www.verisign.com/", CLIENT_CERT_RSA_SIGN, base::Time(), + base::Time(), "a", "b"); store.SetOriginBoundCert( "https://www.google.com/", CLIENT_CERT_ECDSA_SIGN, base::Time(), + base::Time(), "c", "d"); store.SetOriginBoundCert( "https://www.harvard.com/", CLIENT_CERT_RSA_SIGN, base::Time(), + base::Time(), "e", "f"); store.SetOriginBoundCert( "https://www.mit.com/", CLIENT_CERT_RSA_SIGN, base::Time(), + base::Time(), "g", "h"); EXPECT_EQ(4, store.GetCertCount()); diff --git a/net/base/origin_bound_cert_service.cc b/net/base/origin_bound_cert_service.cc index 246383e..1edf9c0 100644 --- a/net/base/origin_bound_cert_service.cc +++ b/net/base/origin_bound_cert_service.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -134,6 +134,7 @@ class OriginBoundCertServiceWorker { error_ = OriginBoundCertService::GenerateCert(origin_, type_, serial_number_, + &creation_time_, &expiration_time_, &private_key_, &cert_); @@ -161,7 +162,8 @@ class OriginBoundCertServiceWorker { base::AutoLock locked(lock_); if (!canceled_) { origin_bound_cert_service_->HandleResult( - origin_, error_, type_, expiration_time_, private_key_, cert_); + origin_, error_, type_, creation_time_, expiration_time_, + private_key_, cert_); } } delete this; @@ -209,6 +211,7 @@ class OriginBoundCertServiceWorker { bool canceled_; int error_; + base::Time creation_time_; base::Time expiration_time_; std::string private_key_; std::string cert_; @@ -302,9 +305,10 @@ int OriginBoundCertService::GetOriginBoundCert( RequestHandle* out_req) { DCHECK(CalledOnValidThread()); + *out_req = NULL; + if (callback.is_null() || !private_key || !cert || origin.empty() || requested_types.empty()) { - *out_req = NULL; return ERR_INVALID_ARGUMENT; } @@ -317,7 +321,6 @@ int OriginBoundCertService::GetOriginBoundCert( } if (preferred_type == CLIENT_CERT_INVALID_TYPE) { // None of the requested types are supported. - *out_req = NULL; return ERR_CLIENT_AUTH_CERT_TYPE_UNSUPPORTED; } @@ -326,9 +329,11 @@ int OriginBoundCertService::GetOriginBoundCert( // Check if an origin bound cert of an acceptable type already exists for this // origin, and that it has not expired. base::Time now = base::Time::Now(); + base::Time creation_time; base::Time expiration_time; if (origin_bound_cert_store_->GetOriginBoundCert(origin, type, + &creation_time, &expiration_time, private_key, cert)) { @@ -341,7 +346,6 @@ int OriginBoundCertService::GetOriginBoundCert( << origin; } else { cert_store_hits_++; - *out_req = NULL; return OK; } } @@ -360,7 +364,6 @@ int OriginBoundCertService::GetOriginBoundCert( == requested_types.end()) { DVLOG(1) << "Found inflight job of wrong type " << job->type() << " for " << origin; - *out_req = NULL; // If we get here, the server is asking for different types of certs in // short succession. This probably means the server is broken or // misconfigured. Since we only store one type of cert per origin, we @@ -379,7 +382,6 @@ int OriginBoundCertService::GetOriginBoundCert( if (!worker->Start()) { delete job; delete worker; - *out_req = NULL; // TODO(rkn): Log to the NetLog. LOG(ERROR) << "OriginBoundCertServiceWorker couldn't be started."; return ERR_INSUFFICIENT_RESOURCES; // Just a guess. @@ -394,10 +396,15 @@ int OriginBoundCertService::GetOriginBoundCert( return ERR_IO_PENDING; } +OriginBoundCertStore* OriginBoundCertService::GetCertStore() { + return origin_bound_cert_store_.get(); +} + // static int OriginBoundCertService::GenerateCert(const std::string& origin, SSLClientCertType type, uint32 serial_number, + base::Time* creation_time, base::Time* expiration_time, std::string* private_key, std::string* cert) { @@ -466,6 +473,7 @@ int OriginBoundCertService::GenerateCert(const std::string& origin, private_key->swap(key_out); cert->swap(der_cert); + *creation_time = now; *expiration_time = not_valid_after; return OK; } @@ -482,13 +490,14 @@ void OriginBoundCertService::CancelRequest(RequestHandle req) { void OriginBoundCertService::HandleResult(const std::string& origin, int error, SSLClientCertType type, + base::Time creation_time, base::Time expiration_time, const std::string& private_key, const std::string& cert) { DCHECK(CalledOnValidThread()); origin_bound_cert_store_->SetOriginBoundCert( - origin, type, expiration_time, private_key, cert); + origin, type, creation_time, expiration_time, private_key, cert); std::map<std::string, OriginBoundCertServiceJob*>::iterator j; j = inflight_.find(origin); diff --git a/net/base/origin_bound_cert_service.h b/net/base/origin_bound_cert_service.h index 0f78260..298c3e9 100644 --- a/net/base/origin_bound_cert_service.h +++ b/net/base/origin_bound_cert_service.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -60,9 +60,8 @@ class NET_EXPORT OriginBoundCertService // could not be completed immediately, in which case the result code will // be passed to the callback when available. // - // If |out_req| is non-NULL, then |*out_req| will be filled with a handle to - // the async request. This handle is not valid after the request has - // completed. + // |*out_req| will be filled with a handle to the async request. This handle + // is not valid after the request has completed. int GetOriginBoundCert( const std::string& origin, const std::vector<uint8>& requested_types, @@ -77,6 +76,9 @@ class NET_EXPORT OriginBoundCertService // callback will not be called. void CancelRequest(RequestHandle req); + // Returns the backing OriginBoundCertStore. + OriginBoundCertStore* GetCertStore(); + // Public only for unit testing. int cert_count(); uint64 requests() const { return requests_; } @@ -87,15 +89,17 @@ class NET_EXPORT OriginBoundCertService friend class OriginBoundCertServiceWorker; // Calls HandleResult. // On success, |private_key| stores a DER-encoded PrivateKeyInfo - // struct, |cert| stores a DER-encoded certificate, and |expiration_time| - // stores the expiration time of the certificate. Returns - // OK if successful and an error code otherwise. + // struct, |cert| stores a DER-encoded certificate, |creation_time| stores the + // start of the validity period of the certificate and |expiration_time| + // stores the expiration time of the certificate. Returns OK if successful and + // an error code otherwise. // |serial_number| is passed in because it is created with the function // base::RandInt, which opens the file /dev/urandom. /dev/urandom is opened // with a LazyInstance, which is not allowed on a worker thread. static int GenerateCert(const std::string& origin, SSLClientCertType type, uint32 serial_number, + base::Time* creation_time, base::Time* expiration_time, std::string* private_key, std::string* cert); @@ -103,6 +107,7 @@ class NET_EXPORT OriginBoundCertService void HandleResult(const std::string& origin, int error, SSLClientCertType type, + base::Time creation_time, base::Time expiration_time, const std::string& private_key, const std::string& cert); diff --git a/net/base/origin_bound_cert_service_unittest.cc b/net/base/origin_bound_cert_service_unittest.cc index 65f40a5..6c0d264 100644 --- a/net/base/origin_bound_cert_service_unittest.cc +++ b/net/base/origin_bound_cert_service_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -459,14 +459,17 @@ TEST(OriginBoundCertServiceTest, CancelRequest) { TEST(OriginBoundCertServiceTest, Expiration) { OriginBoundCertStore* store = new DefaultOriginBoundCertStore(NULL); + base::Time now = base::Time::Now(); store->SetOriginBoundCert("https://good", CLIENT_CERT_RSA_SIGN, - base::Time::Now() + base::TimeDelta::FromDays(1), + now, + now + base::TimeDelta::FromDays(1), "a", "b"); store->SetOriginBoundCert("https://expired", CLIENT_CERT_RSA_SIGN, - base::Time::Now() - base::TimeDelta::FromDays(1), + now - base::TimeDelta::FromDays(2), + now - base::TimeDelta::FromDays(1), "c", "d"); OriginBoundCertService service(store); diff --git a/net/base/origin_bound_cert_store.cc b/net/base/origin_bound_cert_store.cc index 6a31a7e..af2acce 100644 --- a/net/base/origin_bound_cert_store.cc +++ b/net/base/origin_bound_cert_store.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -13,11 +13,13 @@ OriginBoundCertStore::OriginBoundCert::OriginBoundCert() OriginBoundCertStore::OriginBoundCert::OriginBoundCert( const std::string& origin, SSLClientCertType type, + base::Time creation_time, base::Time expiration_time, const std::string& private_key, const std::string& cert) : origin_(origin), type_(type), + creation_time_(creation_time), expiration_time_(expiration_time), private_key_(private_key), cert_(cert) {} diff --git a/net/base/origin_bound_cert_store.h b/net/base/origin_bound_cert_store.h index 1eb8382..1101a01 100644 --- a/net/base/origin_bound_cert_store.h +++ b/net/base/origin_bound_cert_store.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -31,6 +31,7 @@ class NET_EXPORT OriginBoundCertStore { OriginBoundCert(); OriginBoundCert(const std::string& origin, SSLClientCertType type, + base::Time creation_time, base::Time expiration_time, const std::string& private_key, const std::string& cert); @@ -40,6 +41,9 @@ class NET_EXPORT OriginBoundCertStore { const std::string& origin() const { return origin_; } // TLS ClientCertificateType. SSLClientCertType type() const { return type_; } + // The time the certificate was created, also the start of the certificate + // validity period. + base::Time creation_time() const { return creation_time_; } // The time after which this certificate is no longer valid. base::Time expiration_time() const { return expiration_time_; } // The encoding of the private key depends on the type. @@ -52,6 +56,7 @@ class NET_EXPORT OriginBoundCertStore { private: std::string origin_; SSLClientCertType type_; + base::Time creation_time_; base::Time expiration_time_; std::string private_key_; std::string cert_; @@ -63,12 +68,14 @@ class NET_EXPORT OriginBoundCertStore { // interface. // Returns true on success. |private_key_result| stores a DER-encoded // PrivateKeyInfo struct, |cert_result| stores a DER-encoded certificate, - // |type| is the ClientCertificateType of the returned certificate, and - // |expiration_time| is the expiration time of the certificate. + // |type| is the ClientCertificateType of the returned certificate, + // |creation_time| stores the start of the validity period of the certificate + // and |expiration_time| is the expiration time of the certificate. // Returns false if no origin bound cert exists for the specified origin. virtual bool GetOriginBoundCert( const std::string& origin, SSLClientCertType* type, + base::Time* creation_time, base::Time* expiration_time, std::string* private_key_result, std::string* cert_result) = 0; @@ -77,6 +84,7 @@ class NET_EXPORT OriginBoundCertStore { virtual void SetOriginBoundCert( const std::string& origin, SSLClientCertType type, + base::Time creation_time, base::Time expiration_time, const std::string& private_key, const std::string& cert) = 0; @@ -85,6 +93,12 @@ class NET_EXPORT OriginBoundCertStore { // store. virtual void DeleteOriginBoundCert(const std::string& origin) = 0; + // Deletes all of the origin bound certs that have a creation_date greater + // than or equal to |delete_begin| and less than |delete_end|. If a + // base::Time value is_null, that side of the comparison is unbounded. + virtual void DeleteAllCreatedBetween(base::Time delete_begin, + base::Time delete_end) = 0; + // Removes all origin bound certs and the corresponding private keys from // the store. virtual void DeleteAll() = 0; diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc index d9544ab..c296745 100644 --- a/net/url_request/url_request_test_util.cc +++ b/net/url_request/url_request_test_util.cc @@ -8,7 +8,9 @@ #include "base/logging.h" #include "base/message_loop.h" #include "base/threading/thread.h" +#include "net/base/default_origin_bound_cert_store.h" #include "net/base/host_port_pair.h" +#include "net/base/origin_bound_cert_service.h" #include "net/http/http_network_session.h" #include "net/http/http_server_properties_impl.h" #include "net/url_request/url_request_job_factory.h" @@ -140,6 +142,12 @@ void TestURLRequestContext::Init() { // In-memory cookie store. if (!cookie_store()) context_storage_.set_cookie_store(new net::CookieMonster(NULL, NULL)); + // In-memory origin bound cert service. + if (!origin_bound_cert_service()) { + context_storage_.set_origin_bound_cert_service( + new net::OriginBoundCertService( + new net::DefaultOriginBoundCertStore(NULL))); + } if (accept_language().empty()) set_accept_language("en-us,fr"); if (accept_charset().empty()) |