OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/file_util.h" | 5 #include "base/file_util.h" |
6 #include "base/memory/ref_counted.h" | 6 #include "base/memory/ref_counted.h" |
7 #include "base/message_loop.h" | 7 #include "base/message_loop.h" |
8 #include "base/scoped_temp_dir.h" | 8 #include "base/scoped_temp_dir.h" |
9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
10 #include "base/test/thread_test_helper.h" | 10 #include "base/test/thread_test_helper.h" |
11 #include "chrome/browser/net/sqlite_origin_bound_cert_store.h" | 11 #include "chrome/browser/net/sqlite_origin_bound_cert_store.h" |
12 #include "chrome/common/chrome_constants.h" | 12 #include "chrome/common/chrome_constants.h" |
13 #include "content/test/test_browser_thread.h" | 13 #include "content/test/test_browser_thread.h" |
| 14 #include "sql/statement.h" |
14 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
15 | 16 |
16 using content::BrowserThread; | 17 using content::BrowserThread; |
17 | 18 |
18 class SQLiteOriginBoundCertStoreTest : public testing::Test { | 19 class SQLiteOriginBoundCertStoreTest : public testing::Test { |
19 public: | 20 public: |
20 SQLiteOriginBoundCertStoreTest() | 21 SQLiteOriginBoundCertStoreTest() |
21 : db_thread_(BrowserThread::DB) { | 22 : db_thread_(BrowserThread::DB) { |
22 } | 23 } |
23 | 24 |
24 protected: | 25 protected: |
25 virtual void SetUp() { | 26 virtual void SetUp() { |
26 db_thread_.Start(); | 27 db_thread_.Start(); |
27 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | 28 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
28 store_ = new SQLiteOriginBoundCertStore( | 29 store_ = new SQLiteOriginBoundCertStore( |
29 temp_dir_.path().Append(chrome::kOBCertFilename)); | 30 temp_dir_.path().Append(chrome::kOBCertFilename)); |
30 std::vector<net::DefaultOriginBoundCertStore::OriginBoundCert*> certs; | 31 std::vector<net::DefaultOriginBoundCertStore::OriginBoundCert*> certs; |
31 ASSERT_TRUE(store_->Load(&certs)); | 32 ASSERT_TRUE(store_->Load(&certs)); |
32 ASSERT_EQ(0u, certs.size()); | 33 ASSERT_EQ(0u, certs.size()); |
33 // Make sure the store gets written at least once. | 34 // Make sure the store gets written at least once. |
34 store_->AddOriginBoundCert( | 35 store_->AddOriginBoundCert( |
35 net::DefaultOriginBoundCertStore::OriginBoundCert( | 36 net::DefaultOriginBoundCertStore::OriginBoundCert( |
36 "https://encrypted.google.com:8443", "a", "b")); | 37 "https://encrypted.google.com:8443", |
| 38 net::ORIGIN_BOUND_RSA_CERT, "a", "b")); |
37 } | 39 } |
38 | 40 |
39 content::TestBrowserThread db_thread_; | 41 content::TestBrowserThread db_thread_; |
40 ScopedTempDir temp_dir_; | 42 ScopedTempDir temp_dir_; |
41 scoped_refptr<SQLiteOriginBoundCertStore> store_; | 43 scoped_refptr<SQLiteOriginBoundCertStore> store_; |
42 }; | 44 }; |
43 | 45 |
44 TEST_F(SQLiteOriginBoundCertStoreTest, KeepOnDestruction) { | 46 TEST_F(SQLiteOriginBoundCertStoreTest, KeepOnDestruction) { |
45 store_->SetClearLocalStateOnExit(false); | 47 store_->SetClearLocalStateOnExit(false); |
46 store_ = NULL; | 48 store_ = NULL; |
(...skipping 20 matching lines...) Expand all Loading... |
67 new base::ThreadTestHelper( | 69 new base::ThreadTestHelper( |
68 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB))); | 70 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB))); |
69 ASSERT_TRUE(helper->Run()); | 71 ASSERT_TRUE(helper->Run()); |
70 | 72 |
71 ASSERT_FALSE(file_util::PathExists( | 73 ASSERT_FALSE(file_util::PathExists( |
72 temp_dir_.path().Append(chrome::kOBCertFilename))); | 74 temp_dir_.path().Append(chrome::kOBCertFilename))); |
73 } | 75 } |
74 | 76 |
75 // Test if data is stored as expected in the SQLite database. | 77 // Test if data is stored as expected in the SQLite database. |
76 TEST_F(SQLiteOriginBoundCertStoreTest, TestPersistence) { | 78 TEST_F(SQLiteOriginBoundCertStoreTest, TestPersistence) { |
| 79 store_->AddOriginBoundCert( |
| 80 net::DefaultOriginBoundCertStore::OriginBoundCert( |
| 81 "https://www.google.com/", net::ORIGIN_BOUND_EC_CERT, "c", "d")); |
| 82 |
77 std::vector<net::DefaultOriginBoundCertStore::OriginBoundCert*> certs; | 83 std::vector<net::DefaultOriginBoundCertStore::OriginBoundCert*> certs; |
78 // Replace the store effectively destroying the current one and forcing it | 84 // Replace the store effectively destroying the current one and forcing it |
79 // to write it's data to disk. Then we can see if after loading it again it | 85 // to write it's data to disk. Then we can see if after loading it again it |
80 // is still there. | 86 // is still there. |
81 store_ = NULL; | 87 store_ = NULL; |
82 scoped_refptr<base::ThreadTestHelper> helper( | 88 scoped_refptr<base::ThreadTestHelper> helper( |
83 new base::ThreadTestHelper( | 89 new base::ThreadTestHelper( |
84 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB))); | 90 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB))); |
85 // Make sure we wait until the destructor has run. | 91 // Make sure we wait until the destructor has run. |
86 ASSERT_TRUE(helper->Run()); | 92 ASSERT_TRUE(helper->Run()); |
87 store_ = new SQLiteOriginBoundCertStore( | 93 store_ = new SQLiteOriginBoundCertStore( |
88 temp_dir_.path().Append(chrome::kOBCertFilename)); | 94 temp_dir_.path().Append(chrome::kOBCertFilename)); |
89 | 95 |
90 // Reload and test for persistence | 96 // Reload and test for persistence |
91 ASSERT_TRUE(store_->Load(&certs)); | 97 ASSERT_TRUE(store_->Load(&certs)); |
92 ASSERT_EQ(1U, certs.size()); | 98 ASSERT_EQ(2U, certs.size()); |
93 ASSERT_STREQ("https://encrypted.google.com:8443", certs[0]->origin().c_str()); | 99 net::DefaultOriginBoundCertStore::OriginBoundCert* ec_cert; |
94 ASSERT_STREQ("a", certs[0]->private_key().c_str()); | 100 net::DefaultOriginBoundCertStore::OriginBoundCert* rsa_cert; |
95 ASSERT_STREQ("b", certs[0]->cert().c_str()); | 101 if (net::ORIGIN_BOUND_RSA_CERT == certs[0]->type()) { |
| 102 rsa_cert = certs[0]; |
| 103 ec_cert = certs[1]; |
| 104 } else { |
| 105 rsa_cert = certs[1]; |
| 106 ec_cert = certs[0]; |
| 107 } |
| 108 ASSERT_STREQ("https://encrypted.google.com:8443", rsa_cert->origin().c_str()); |
| 109 ASSERT_EQ(net::ORIGIN_BOUND_RSA_CERT, rsa_cert->type()); |
| 110 ASSERT_STREQ("a", rsa_cert->private_key().c_str()); |
| 111 ASSERT_STREQ("b", rsa_cert->cert().c_str()); |
| 112 ASSERT_STREQ("https://www.google.com/", ec_cert->origin().c_str()); |
| 113 ASSERT_EQ(net::ORIGIN_BOUND_EC_CERT, ec_cert->type()); |
| 114 ASSERT_STREQ("c", ec_cert->private_key().c_str()); |
| 115 ASSERT_STREQ("d", ec_cert->cert().c_str()); |
96 | 116 |
97 // Now delete the cert and check persistence again. | 117 // Now delete the cert and check persistence again. |
| 118 store_->DeleteOriginBoundCert(*certs[1]); |
98 store_->DeleteOriginBoundCert(*certs[0]); | 119 store_->DeleteOriginBoundCert(*certs[0]); |
99 store_ = NULL; | 120 store_ = NULL; |
100 // Make sure we wait until the destructor has run. | 121 // Make sure we wait until the destructor has run. |
101 ASSERT_TRUE(helper->Run()); | 122 ASSERT_TRUE(helper->Run()); |
102 STLDeleteContainerPointers(certs.begin(), certs.end()); | 123 STLDeleteContainerPointers(certs.begin(), certs.end()); |
103 certs.clear(); | 124 certs.clear(); |
104 store_ = new SQLiteOriginBoundCertStore( | 125 store_ = new SQLiteOriginBoundCertStore( |
105 temp_dir_.path().Append(chrome::kOBCertFilename)); | 126 temp_dir_.path().Append(chrome::kOBCertFilename)); |
106 | 127 |
107 // Reload and check if the cert has been removed. | 128 // Reload and check if the cert has been removed. |
108 ASSERT_TRUE(store_->Load(&certs)); | 129 ASSERT_TRUE(store_->Load(&certs)); |
109 ASSERT_EQ(0U, certs.size()); | 130 ASSERT_EQ(0U, certs.size()); |
110 } | 131 } |
111 | 132 |
| 133 TEST_F(SQLiteOriginBoundCertStoreTest, TestUpgrade) { |
| 134 // Reset the store. We'll be using a different database for this test. |
| 135 store_ = NULL; |
| 136 |
| 137 FilePath v1_db_path(temp_dir_.path().AppendASCII("v1db")); |
| 138 |
| 139 // Create a version 1 database. |
| 140 { |
| 141 sql::Connection db; |
| 142 ASSERT_TRUE(db.Open(v1_db_path)); |
| 143 ASSERT_TRUE(db.Execute( |
| 144 "CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY," |
| 145 "value LONGVARCHAR);" |
| 146 "INSERT INTO \"meta\" VALUES('version','1');" |
| 147 "INSERT INTO \"meta\" VALUES('last_compatible_version','1');" |
| 148 "CREATE TABLE origin_bound_certs (" |
| 149 "origin TEXT NOT NULL UNIQUE PRIMARY KEY," |
| 150 "private_key BLOB NOT NULL,cert BLOB NOT NULL);" |
| 151 "INSERT INTO \"origin_bound_certs\" VALUES(" |
| 152 "'https://google.com',X'AA',X'BB');" |
| 153 "INSERT INTO \"origin_bound_certs\" VALUES(" |
| 154 "'https://foo.com',X'CC',X'DD');" |
| 155 )); |
| 156 } |
| 157 |
| 158 std::vector<net::DefaultOriginBoundCertStore::OriginBoundCert*> certs; |
| 159 store_ = new SQLiteOriginBoundCertStore(v1_db_path); |
| 160 |
| 161 // Load the database and ensure the certs can be read and are marked as RSA. |
| 162 ASSERT_TRUE(store_->Load(&certs)); |
| 163 ASSERT_EQ(2U, certs.size()); |
| 164 ASSERT_STREQ("https://google.com", certs[0]->origin().c_str()); |
| 165 ASSERT_EQ(net::ORIGIN_BOUND_RSA_CERT, certs[0]->type()); |
| 166 ASSERT_STREQ("\xaa", certs[0]->private_key().c_str()); |
| 167 ASSERT_STREQ("\xbb", certs[0]->cert().c_str()); |
| 168 ASSERT_STREQ("https://foo.com", certs[1]->origin().c_str()); |
| 169 ASSERT_EQ(net::ORIGIN_BOUND_RSA_CERT, certs[1]->type()); |
| 170 ASSERT_STREQ("\xcc", certs[1]->private_key().c_str()); |
| 171 ASSERT_STREQ("\xdd", certs[1]->cert().c_str()); |
| 172 |
| 173 STLDeleteContainerPointers(certs.begin(), certs.end()); |
| 174 certs.clear(); |
| 175 |
| 176 store_ = NULL; |
| 177 // Make sure we wait until the destructor has run. |
| 178 scoped_refptr<base::ThreadTestHelper> helper( |
| 179 new base::ThreadTestHelper( |
| 180 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB))); |
| 181 ASSERT_TRUE(helper->Run()); |
| 182 |
| 183 // Verify the database version is updated. |
| 184 { |
| 185 sql::Connection db; |
| 186 ASSERT_TRUE(db.Open(v1_db_path)); |
| 187 sql::Statement smt(db.GetUniqueStatement( |
| 188 "SELECT value FROM meta WHERE key = \"version\"")); |
| 189 ASSERT_TRUE(smt); |
| 190 ASSERT_TRUE(smt.Step()); |
| 191 EXPECT_EQ(2, smt.ColumnInt(0)); |
| 192 EXPECT_FALSE(smt.Step()); |
| 193 } |
| 194 } |
| 195 |
112 // Test that we can force the database to be written by calling Flush(). | 196 // Test that we can force the database to be written by calling Flush(). |
113 TEST_F(SQLiteOriginBoundCertStoreTest, TestFlush) { | 197 TEST_F(SQLiteOriginBoundCertStoreTest, TestFlush) { |
114 // File timestamps don't work well on all platforms, so we'll determine | 198 // File timestamps don't work well on all platforms, so we'll determine |
115 // whether the DB file has been modified by checking its size. | 199 // whether the DB file has been modified by checking its size. |
116 FilePath path = temp_dir_.path().Append(chrome::kOBCertFilename); | 200 FilePath path = temp_dir_.path().Append(chrome::kOBCertFilename); |
117 base::PlatformFileInfo info; | 201 base::PlatformFileInfo info; |
118 ASSERT_TRUE(file_util::GetFileInfo(path, &info)); | 202 ASSERT_TRUE(file_util::GetFileInfo(path, &info)); |
119 int64 base_size = info.size; | 203 int64 base_size = info.size; |
120 | 204 |
121 // Write some certs, so the DB will have to expand by several KB. | 205 // Write some certs, so the DB will have to expand by several KB. |
122 for (char c = 'a'; c < 'z'; ++c) { | 206 for (char c = 'a'; c < 'z'; ++c) { |
123 std::string origin(1, c); | 207 std::string origin(1, c); |
124 std::string private_key(1000, c); | 208 std::string private_key(1000, c); |
125 std::string cert(1000, c); | 209 std::string cert(1000, c); |
126 store_->AddOriginBoundCert( | 210 store_->AddOriginBoundCert( |
127 net::DefaultOriginBoundCertStore::OriginBoundCert(origin, | 211 net::DefaultOriginBoundCertStore::OriginBoundCert( |
128 private_key, | 212 origin, |
129 cert)); | 213 net::ORIGIN_BOUND_RSA_CERT, |
| 214 private_key, |
| 215 cert)); |
130 } | 216 } |
131 | 217 |
132 // Call Flush() and wait until the DB thread is idle. | 218 // Call Flush() and wait until the DB thread is idle. |
133 store_->Flush(NULL); | 219 store_->Flush(NULL); |
134 scoped_refptr<base::ThreadTestHelper> helper( | 220 scoped_refptr<base::ThreadTestHelper> helper( |
135 new base::ThreadTestHelper( | 221 new base::ThreadTestHelper( |
136 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB))); | 222 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB))); |
137 ASSERT_TRUE(helper->Run()); | 223 ASSERT_TRUE(helper->Run()); |
138 | 224 |
139 // We forced a write, so now the file will be bigger. | 225 // We forced a write, so now the file will be bigger. |
(...skipping 28 matching lines...) Expand all Loading... |
168 | 254 |
169 store_->Flush(NewRunnableMethod(counter.get(), &CallbackCounter::Callback)); | 255 store_->Flush(NewRunnableMethod(counter.get(), &CallbackCounter::Callback)); |
170 | 256 |
171 scoped_refptr<base::ThreadTestHelper> helper( | 257 scoped_refptr<base::ThreadTestHelper> helper( |
172 new base::ThreadTestHelper( | 258 new base::ThreadTestHelper( |
173 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB))); | 259 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB))); |
174 ASSERT_TRUE(helper->Run()); | 260 ASSERT_TRUE(helper->Run()); |
175 | 261 |
176 ASSERT_EQ(1, counter->callback_count()); | 262 ASSERT_EQ(1, counter->callback_count()); |
177 } | 263 } |
OLD | NEW |