| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "net/ssl/ssl_client_session_cache.h" | 5 #include "net/ssl/ssl_client_session_cache.h" |
| 6 | 6 |
| 7 #include "base/memory/ptr_util.h" | 7 #include "base/memory/ptr_util.h" |
| 8 #include "base/run_loop.h" | 8 #include "base/run_loop.h" |
| 9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
| 10 #include "base/test/simple_test_clock.h" | 10 #include "base/test/simple_test_clock.h" |
| 11 #include "base/time/time.h" |
| 11 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
| 12 #include "third_party/boringssl/src/include/openssl/ssl.h" | 13 #include "third_party/boringssl/src/include/openssl/ssl.h" |
| 13 | 14 |
| 14 namespace net { | 15 namespace net { |
| 15 | 16 |
| 17 namespace { |
| 18 |
| 19 std::unique_ptr<base::SimpleTestClock> MakeTestClock() { |
| 20 std::unique_ptr<base::SimpleTestClock> clock = |
| 21 base::MakeUnique<base::SimpleTestClock>(); |
| 22 // SimpleTestClock starts at the null base::Time which converts to and from |
| 23 // time_t confusingly. |
| 24 clock->SetNow(base::Time::FromTimeT(1000000000)); |
| 25 return clock; |
| 26 } |
| 27 |
| 28 bssl::UniquePtr<SSL_SESSION> MakeTestSession(base::Time now, |
| 29 base::TimeDelta timeout) { |
| 30 bssl::UniquePtr<SSL_SESSION> session(SSL_SESSION_new()); |
| 31 SSL_SESSION_set_time(session.get(), now.ToTimeT()); |
| 32 SSL_SESSION_set_timeout(session.get(), timeout.InSeconds()); |
| 33 return session; |
| 34 } |
| 35 |
| 36 } // namespace |
| 37 |
| 16 // Test basic insertion and lookup operations. | 38 // Test basic insertion and lookup operations. |
| 17 TEST(SSLClientSessionCacheTest, Basic) { | 39 TEST(SSLClientSessionCacheTest, Basic) { |
| 18 SSLClientSessionCache::Config config; | 40 SSLClientSessionCache::Config config; |
| 19 SSLClientSessionCache cache(config); | 41 SSLClientSessionCache cache(config); |
| 20 | 42 |
| 21 bssl::UniquePtr<SSL_SESSION> session1(SSL_SESSION_new()); | 43 bssl::UniquePtr<SSL_SESSION> session1(SSL_SESSION_new()); |
| 22 bssl::UniquePtr<SSL_SESSION> session2(SSL_SESSION_new()); | 44 bssl::UniquePtr<SSL_SESSION> session2(SSL_SESSION_new()); |
| 23 bssl::UniquePtr<SSL_SESSION> session3(SSL_SESSION_new()); | 45 bssl::UniquePtr<SSL_SESSION> session3(SSL_SESSION_new()); |
| 24 EXPECT_EQ(1u, session1->references); | 46 EXPECT_EQ(1u, session1->references); |
| 25 EXPECT_EQ(1u, session2->references); | 47 EXPECT_EQ(1u, session2->references); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 } | 158 } |
| 137 | 159 |
| 138 // Tests that session expiration works properly. | 160 // Tests that session expiration works properly. |
| 139 TEST(SSLClientSessionCacheTest, Expiration) { | 161 TEST(SSLClientSessionCacheTest, Expiration) { |
| 140 const size_t kNumEntries = 20; | 162 const size_t kNumEntries = 20; |
| 141 const size_t kExpirationCheckCount = 10; | 163 const size_t kExpirationCheckCount = 10; |
| 142 const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(1000); | 164 const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(1000); |
| 143 | 165 |
| 144 SSLClientSessionCache::Config config; | 166 SSLClientSessionCache::Config config; |
| 145 config.expiration_check_count = kExpirationCheckCount; | 167 config.expiration_check_count = kExpirationCheckCount; |
| 146 config.timeout = kTimeout; | |
| 147 SSLClientSessionCache cache(config); | 168 SSLClientSessionCache cache(config); |
| 148 base::SimpleTestClock* clock = new base::SimpleTestClock; | 169 base::SimpleTestClock* clock = MakeTestClock().release(); |
| 149 cache.SetClockForTesting(base::WrapUnique(clock)); | 170 cache.SetClockForTesting(base::WrapUnique(clock)); |
| 150 | 171 |
| 151 // Add |kNumEntries - 1| entries. | 172 // Add |kNumEntries - 1| entries. |
| 152 for (size_t i = 0; i < kNumEntries - 1; i++) { | 173 for (size_t i = 0; i < kNumEntries - 1; i++) { |
| 153 bssl::UniquePtr<SSL_SESSION> session(SSL_SESSION_new()); | 174 bssl::UniquePtr<SSL_SESSION> session = |
| 175 MakeTestSession(clock->Now(), kTimeout); |
| 154 cache.Insert(base::SizeTToString(i), session.get()); | 176 cache.Insert(base::SizeTToString(i), session.get()); |
| 155 } | 177 } |
| 156 EXPECT_EQ(kNumEntries - 1, cache.size()); | 178 EXPECT_EQ(kNumEntries - 1, cache.size()); |
| 157 | 179 |
| 158 // Expire all the previous entries and insert one more entry. | 180 // Expire all the previous entries and insert one more entry. |
| 159 clock->Advance(kTimeout * 2); | 181 clock->Advance(kTimeout * 2); |
| 160 bssl::UniquePtr<SSL_SESSION> session(SSL_SESSION_new()); | 182 bssl::UniquePtr<SSL_SESSION> session = |
| 183 MakeTestSession(clock->Now(), kTimeout); |
| 161 cache.Insert("key", session.get()); | 184 cache.Insert("key", session.get()); |
| 162 | 185 |
| 163 // All entries are still in the cache. | 186 // All entries are still in the cache. |
| 164 EXPECT_EQ(kNumEntries, cache.size()); | 187 EXPECT_EQ(kNumEntries, cache.size()); |
| 165 | 188 |
| 166 // Perform one fewer lookup than needed to trigger the expiration check. This | 189 // Perform one fewer lookup than needed to trigger the expiration check. This |
| 167 // shall not expire any session. | 190 // shall not expire any session. |
| 168 for (size_t i = 0; i < kExpirationCheckCount - 1; i++) | 191 for (size_t i = 0; i < kExpirationCheckCount - 1; i++) |
| 169 cache.Lookup("key"); | 192 cache.Lookup("key"); |
| 170 | 193 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 184 // Tests that Lookup performs an expiration check before returning a cached | 207 // Tests that Lookup performs an expiration check before returning a cached |
| 185 // session. | 208 // session. |
| 186 TEST(SSLClientSessionCacheTest, LookupExpirationCheck) { | 209 TEST(SSLClientSessionCacheTest, LookupExpirationCheck) { |
| 187 // kExpirationCheckCount is set to a suitably large number so the automated | 210 // kExpirationCheckCount is set to a suitably large number so the automated |
| 188 // pruning never triggers. | 211 // pruning never triggers. |
| 189 const size_t kExpirationCheckCount = 1000; | 212 const size_t kExpirationCheckCount = 1000; |
| 190 const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(1000); | 213 const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(1000); |
| 191 | 214 |
| 192 SSLClientSessionCache::Config config; | 215 SSLClientSessionCache::Config config; |
| 193 config.expiration_check_count = kExpirationCheckCount; | 216 config.expiration_check_count = kExpirationCheckCount; |
| 194 config.timeout = kTimeout; | |
| 195 SSLClientSessionCache cache(config); | 217 SSLClientSessionCache cache(config); |
| 196 base::SimpleTestClock* clock = new base::SimpleTestClock; | 218 base::SimpleTestClock* clock = MakeTestClock().release(); |
| 197 cache.SetClockForTesting(base::WrapUnique(clock)); | 219 cache.SetClockForTesting(base::WrapUnique(clock)); |
| 198 | 220 |
| 199 // Insert an entry into the session cache. | 221 // Insert an entry into the session cache. |
| 200 bssl::UniquePtr<SSL_SESSION> session(SSL_SESSION_new()); | 222 bssl::UniquePtr<SSL_SESSION> session = |
| 223 MakeTestSession(clock->Now(), kTimeout); |
| 201 cache.Insert("key", session.get()); | 224 cache.Insert("key", session.get()); |
| 202 EXPECT_EQ(session.get(), cache.Lookup("key").get()); | 225 EXPECT_EQ(session.get(), cache.Lookup("key").get()); |
| 203 EXPECT_EQ(1u, cache.size()); | 226 EXPECT_EQ(1u, cache.size()); |
| 204 | 227 |
| 205 // Expire the session. | 228 // Expire the session. |
| 206 clock->Advance(kTimeout * 2); | 229 clock->Advance(kTimeout * 2); |
| 207 | 230 |
| 208 // The entry has not been removed yet. | 231 // The entry has not been removed yet. |
| 209 EXPECT_EQ(1u, cache.size()); | 232 EXPECT_EQ(1u, cache.size()); |
| 210 | 233 |
| 211 // But it will not be returned on lookup and gets pruned at that point. | 234 // But it will not be returned on lookup and gets pruned at that point. |
| 212 EXPECT_EQ(nullptr, cache.Lookup("key").get()); | 235 EXPECT_EQ(nullptr, cache.Lookup("key").get()); |
| 213 EXPECT_EQ(0u, cache.size()); | 236 EXPECT_EQ(0u, cache.size()); |
| 214 | 237 |
| 215 // Sessions also are treated as expired if the clock rewinds. | 238 // Re-inserting a session does not refresh the lifetime. The expiration |
| 239 // information in the session is used. |
| 240 cache.Insert("key", session.get()); |
| 241 EXPECT_EQ(nullptr, cache.Lookup("key").get()); |
| 242 EXPECT_EQ(0u, cache.size()); |
| 243 |
| 244 // Re-insert a fresh copy of the session. |
| 245 session = MakeTestSession(clock->Now(), kTimeout); |
| 216 cache.Insert("key", session.get()); | 246 cache.Insert("key", session.get()); |
| 217 EXPECT_EQ(session.get(), cache.Lookup("key").get()); | 247 EXPECT_EQ(session.get(), cache.Lookup("key").get()); |
| 218 EXPECT_EQ(1u, cache.size()); | 248 EXPECT_EQ(1u, cache.size()); |
| 219 | 249 |
| 220 clock->Advance(-kTimeout * 2); | 250 // Sessions also are treated as expired if the clock rewinds. |
| 221 | 251 clock->Advance(base::TimeDelta::FromSeconds(-1)); |
| 222 EXPECT_EQ(nullptr, cache.Lookup("key").get()); | 252 EXPECT_EQ(nullptr, cache.Lookup("key").get()); |
| 223 EXPECT_EQ(0u, cache.size()); | 253 EXPECT_EQ(0u, cache.size()); |
| 224 } | 254 } |
| 225 | 255 |
| 226 // Test that SSL cache is flushed on low memory notifications | 256 // Test that SSL cache is flushed on low memory notifications |
| 227 TEST(SSLClientSessionCacheTest, TestFlushOnMemoryNotifications) { | 257 TEST(SSLClientSessionCacheTest, TestFlushOnMemoryNotifications) { |
| 228 // kExpirationCheckCount is set to a suitably large number so the automated | 258 // kExpirationCheckCount is set to a suitably large number so the automated |
| 229 // pruning never triggers. | 259 // pruning never triggers. |
| 230 const size_t kExpirationCheckCount = 1000; | 260 const size_t kExpirationCheckCount = 1000; |
| 231 const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(1000); | 261 const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(1000); |
| 232 | 262 |
| 233 SSLClientSessionCache::Config config; | 263 SSLClientSessionCache::Config config; |
| 234 config.expiration_check_count = kExpirationCheckCount; | 264 config.expiration_check_count = kExpirationCheckCount; |
| 235 config.timeout = kTimeout; | |
| 236 SSLClientSessionCache cache(config); | 265 SSLClientSessionCache cache(config); |
| 237 base::SimpleTestClock* clock = new base::SimpleTestClock; | 266 base::SimpleTestClock* clock = MakeTestClock().release(); |
| 238 cache.SetClockForTesting(base::WrapUnique(clock)); | 267 cache.SetClockForTesting(base::WrapUnique(clock)); |
| 239 | 268 |
| 240 // Insert an entry into the session cache. | 269 // Insert an entry into the session cache. |
| 241 bssl::UniquePtr<SSL_SESSION> session1(SSL_SESSION_new()); | 270 bssl::UniquePtr<SSL_SESSION> session1 = |
| 271 MakeTestSession(clock->Now(), kTimeout); |
| 242 cache.Insert("key1", session1.get()); | 272 cache.Insert("key1", session1.get()); |
| 243 EXPECT_EQ(session1.get(), cache.Lookup("key1").get()); | 273 EXPECT_EQ(session1.get(), cache.Lookup("key1").get()); |
| 244 EXPECT_EQ(1u, cache.size()); | 274 EXPECT_EQ(1u, cache.size()); |
| 245 | 275 |
| 246 // Expire the session. | 276 // Expire the session. |
| 247 clock->Advance(kTimeout * 2); | 277 clock->Advance(kTimeout * 2); |
| 248 // Add one more session. | 278 // Add one more session. |
| 249 bssl::UniquePtr<SSL_SESSION> session2(SSL_SESSION_new()); | 279 bssl::UniquePtr<SSL_SESSION> session2 = |
| 280 MakeTestSession(clock->Now(), kTimeout); |
| 250 cache.Insert("key2", session2.get()); | 281 cache.Insert("key2", session2.get()); |
| 251 EXPECT_EQ(2u, cache.size()); | 282 EXPECT_EQ(2u, cache.size()); |
| 252 | 283 |
| 253 // Fire a notification that will flush expired sessions. | 284 // Fire a notification that will flush expired sessions. |
| 254 base::MemoryPressureListener::NotifyMemoryPressure( | 285 base::MemoryPressureListener::NotifyMemoryPressure( |
| 255 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE); | 286 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE); |
| 256 base::RunLoop().RunUntilIdle(); | 287 base::RunLoop().RunUntilIdle(); |
| 257 | 288 |
| 258 // Expired session's cache should be flushed. | 289 // Expired session's cache should be flushed. |
| 259 // Lookup returns nullptr, when cache entry not found. | 290 // Lookup returns nullptr, when cache entry not found. |
| 260 EXPECT_FALSE(cache.Lookup("key1")); | 291 EXPECT_FALSE(cache.Lookup("key1")); |
| 261 EXPECT_TRUE(cache.Lookup("key2")); | 292 EXPECT_TRUE(cache.Lookup("key2")); |
| 262 EXPECT_EQ(1u, cache.size()); | 293 EXPECT_EQ(1u, cache.size()); |
| 263 | 294 |
| 264 // Fire notification that will flush everything. | 295 // Fire notification that will flush everything. |
| 265 base::MemoryPressureListener::NotifyMemoryPressure( | 296 base::MemoryPressureListener::NotifyMemoryPressure( |
| 266 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL); | 297 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL); |
| 267 base::RunLoop().RunUntilIdle(); | 298 base::RunLoop().RunUntilIdle(); |
| 268 EXPECT_EQ(0u, cache.size()); | 299 EXPECT_EQ(0u, cache.size()); |
| 269 } | 300 } |
| 270 | 301 |
| 271 } // namespace net | 302 } // namespace net |
| OLD | NEW |