1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // Unit tests for the SafeBrowsing storage system.
7 #include "base/file_util.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/logging.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/sha1.h"
12 #include "base/time/time.h"
13 #include "chrome/browser/safe_browsing/safe_browsing_database.h"
14 #include "chrome/browser/safe_browsing/safe_browsing_store_file.h"
15 #include "chrome/browser/safe_browsing/safe_browsing_store_unittest_helper.h"
16 #include "content/public/test/test_browser_thread_bundle.h"
17 #include "crypto/sha2.h"
18 #include "net/base/net_util.h"
19 #include "sql/connection.h"
20 #include "sql/statement.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "testing/platform_test.h"
29 SBPrefix
Sha256Prefix(const std::string
& str
) {
31 crypto::SHA256HashString(str
, &prefix
, sizeof(prefix
));
35 SBFullHash
Sha256Hash(const std::string
& str
) {
37 crypto::SHA256HashString(str
, &hash
, sizeof(hash
));
41 std::string
HashedIpPrefix(const std::string
& ip_prefix
, size_t prefix_size
) {
42 net::IPAddressNumber ip_number
;
43 EXPECT_TRUE(net::ParseIPLiteralToNumber(ip_prefix
, &ip_number
));
44 EXPECT_EQ(net::kIPv6AddressSize
, ip_number
.size());
45 const std::string hashed_ip_prefix
= base::SHA1HashString(
46 net::IPAddressToPackedString(ip_number
));
47 std::string
hash(crypto::kSHA256Length
, '\0');
48 hash
.replace(0, hashed_ip_prefix
.size(), hashed_ip_prefix
);
49 hash
[base::kSHA1Length
] = static_cast<char>(prefix_size
);
53 // Same as InsertAddChunkHostPrefixUrl, but with pre-computed
55 void InsertAddChunkHostPrefixValue(SBChunk
* chunk
,
57 const SBPrefix
& host_prefix
,
58 const SBPrefix
& url_prefix
) {
59 chunk
->chunk_number
= chunk_number
;
62 host
.host
= host_prefix
;
63 host
.entry
= SBEntry::Create(SBEntry::ADD_PREFIX
, 1);
64 host
.entry
->set_chunk_id(chunk
->chunk_number
);
65 host
.entry
->SetPrefixAt(0, url_prefix
);
66 chunk
->hosts
.push_back(host
);
69 // A helper function that appends one AddChunkHost to chunk with
70 // one url for prefix.
71 void InsertAddChunkHostPrefixUrl(SBChunk
* chunk
,
73 const std::string
& host_name
,
74 const std::string
& url
) {
75 InsertAddChunkHostPrefixValue(chunk
, chunk_number
,
76 Sha256Prefix(host_name
),
80 // Same as InsertAddChunkHostPrefixUrl, but with full hashes.
81 void InsertAddChunkHostFullHashes(SBChunk
* chunk
,
83 const std::string
& host_name
,
84 const std::string
& url
) {
85 chunk
->chunk_number
= chunk_number
;
88 host
.host
= Sha256Prefix(host_name
);
89 host
.entry
= SBEntry::Create(SBEntry::ADD_FULL_HASH
, 1);
90 host
.entry
->set_chunk_id(chunk
->chunk_number
);
91 host
.entry
->SetFullHashAt(0, Sha256Hash(url
));
92 chunk
->hosts
.push_back(host
);
95 void InsertAddChunkFullHash(SBChunk
* chunk
,
97 const std::string
& ip_str
,
99 const std::string full_hash_str
= HashedIpPrefix(ip_str
, prefix_size
);
100 EXPECT_EQ(sizeof(SBFullHash
), full_hash_str
.size());
101 SBFullHash full_hash
;
102 std::memcpy(&(full_hash
.full_hash
), full_hash_str
.data(), sizeof(SBFullHash
));
104 chunk
->chunk_number
= chunk_number
;
105 chunk
->is_add
= true;
107 host
.host
= full_hash
.prefix
;
108 host
.entry
= SBEntry::Create(SBEntry::ADD_FULL_HASH
, 1);
109 host
.entry
->set_chunk_id(chunk
->chunk_number
);
110 host
.entry
->SetFullHashAt(0, full_hash
);
111 chunk
->hosts
.push_back(host
);
114 // Same as InsertAddChunkHostPrefixUrl, but with two urls for prefixes.
115 void InsertAddChunkHost2PrefixUrls(SBChunk
* chunk
,
117 const std::string
& host_name
,
118 const std::string
& url1
,
119 const std::string
& url2
) {
120 chunk
->chunk_number
= chunk_number
;
121 chunk
->is_add
= true;
123 host
.host
= Sha256Prefix(host_name
);
124 host
.entry
= SBEntry::Create(SBEntry::ADD_PREFIX
, 2);
125 host
.entry
->set_chunk_id(chunk
->chunk_number
);
126 host
.entry
->SetPrefixAt(0, Sha256Prefix(url1
));
127 host
.entry
->SetPrefixAt(1, Sha256Prefix(url2
));
128 chunk
->hosts
.push_back(host
);
131 // Same as InsertAddChunkHost2PrefixUrls, but with full hashes.
132 void InsertAddChunkHost2FullHashes(SBChunk
* chunk
,
134 const std::string
& host_name
,
135 const std::string
& url1
,
136 const std::string
& url2
) {
137 chunk
->chunk_number
= chunk_number
;
138 chunk
->is_add
= true;
140 host
.host
= Sha256Prefix(host_name
);
141 host
.entry
= SBEntry::Create(SBEntry::ADD_FULL_HASH
, 2);
142 host
.entry
->set_chunk_id(chunk
->chunk_number
);
143 host
.entry
->SetFullHashAt(0, Sha256Hash(url1
));
144 host
.entry
->SetFullHashAt(1, Sha256Hash(url2
));
145 chunk
->hosts
.push_back(host
);
148 // Same as InsertSubChunkHostPrefixUrl, but with pre-computed
150 void InsertSubChunkHostPrefixValue(SBChunk
* chunk
,
153 const SBPrefix
& host_prefix
,
154 const SBPrefix
& url_prefix
) {
155 chunk
->chunk_number
= chunk_number
;
156 chunk
->is_add
= false;
158 host
.host
= host_prefix
;
159 host
.entry
= SBEntry::Create(SBEntry::SUB_PREFIX
, 1);
160 host
.entry
->set_chunk_id(chunk
->chunk_number
);
161 host
.entry
->SetChunkIdAtPrefix(0, chunk_id_to_sub
);
162 host
.entry
->SetPrefixAt(0, url_prefix
);
163 chunk
->hosts
.push_back(host
);
166 // A helper function that adds one SubChunkHost to chunk with
167 // one url for prefix.
168 void InsertSubChunkHostPrefixUrl(SBChunk
* chunk
,
171 const std::string
& host_name
,
172 const std::string
& url
) {
173 InsertSubChunkHostPrefixValue(chunk
, chunk_number
,
175 Sha256Prefix(host_name
),
179 // Same as InsertSubChunkHostPrefixUrl, but with two urls for prefixes.
180 void InsertSubChunkHost2PrefixUrls(SBChunk
* chunk
,
183 const std::string
& host_name
,
184 const std::string
& url1
,
185 const std::string
& url2
) {
186 chunk
->chunk_number
= chunk_number
;
187 chunk
->is_add
= false;
189 host
.host
= Sha256Prefix(host_name
);
190 host
.entry
= SBEntry::Create(SBEntry::SUB_PREFIX
, 2);
191 host
.entry
->set_chunk_id(chunk
->chunk_number
);
192 host
.entry
->SetPrefixAt(0, Sha256Prefix(url1
));
193 host
.entry
->SetChunkIdAtPrefix(0, chunk_id_to_sub
);
194 host
.entry
->SetPrefixAt(1, Sha256Prefix(url2
));
195 host
.entry
->SetChunkIdAtPrefix(1, chunk_id_to_sub
);
196 chunk
->hosts
.push_back(host
);
199 // Same as InsertSubChunkHost2PrefixUrls, but with full hashes.
200 void InsertSubChunkHostFullHash(SBChunk
* chunk
,
203 const std::string
& host_name
,
204 const std::string
& url
) {
205 chunk
->chunk_number
= chunk_number
;
206 chunk
->is_add
= false;
208 host
.host
= Sha256Prefix(host_name
);
209 host
.entry
= SBEntry::Create(SBEntry::SUB_FULL_HASH
, 2);
210 host
.entry
->set_chunk_id(chunk
->chunk_number
);
211 host
.entry
->SetFullHashAt(0, Sha256Hash(url
));
212 host
.entry
->SetChunkIdAtPrefix(0, chunk_id_to_sub
);
213 chunk
->hosts
.push_back(host
);
216 // Prevent DCHECK from killing tests.
217 // TODO(shess): Pawel disputes the use of this, so the test which uses
218 // it is DISABLED. http://crbug.com/56448
219 class ScopedLogMessageIgnorer
{
221 ScopedLogMessageIgnorer() {
222 logging::SetLogMessageHandler(&LogMessageIgnorer
);
224 ~ScopedLogMessageIgnorer() {
225 // TODO(shess): Would be better to verify whether anyone else
226 // changed it, and then restore it to the previous value.
227 logging::SetLogMessageHandler(NULL
);
231 static bool LogMessageIgnorer(int severity
, const char* file
, int line
,
232 size_t message_start
, const std::string
& str
) {
233 // Intercept FATAL, strip the stack backtrace, and log it without
235 if (severity
== logging::LOG_FATAL
) {
236 size_t newline
= str
.find('\n');
237 if (newline
!= std::string::npos
) {
238 const std::string msg
= str
.substr(0, newline
+ 1);
239 fprintf(stderr
, "%s", msg
.c_str());
251 class SafeBrowsingDatabaseTest
: public PlatformTest
{
253 virtual void SetUp() {
254 PlatformTest::SetUp();
256 // Setup a database in a temporary directory.
257 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
258 database_
.reset(new SafeBrowsingDatabaseNew
);
260 temp_dir_
.path().AppendASCII("SafeBrowsingTestDatabase");
261 database_
->Init(database_filename_
);
264 virtual void TearDown() {
267 PlatformTest::TearDown();
270 void GetListsInfo(std::vector
<SBListChunkRanges
>* lists
) {
272 EXPECT_TRUE(database_
->UpdateStarted(lists
));
273 database_
->UpdateFinished(true);
276 // Helper function to do an AddDel or SubDel command.
277 void DelChunk(const std::string
& list
,
280 std::vector
<SBChunkDelete
> deletes
;
281 SBChunkDelete chunk_delete
;
282 chunk_delete
.list_name
= list
;
283 chunk_delete
.is_sub_del
= is_sub_del
;
284 chunk_delete
.chunk_del
.push_back(ChunkRange(chunk_id
));
285 deletes
.push_back(chunk_delete
);
286 database_
->DeleteChunks(deletes
);
289 void AddDelChunk(const std::string
& list
, int chunk_id
) {
290 DelChunk(list
, chunk_id
, false);
293 void SubDelChunk(const std::string
& list
, int chunk_id
) {
294 DelChunk(list
, chunk_id
, true);
297 // Utility function for setting up the database for the caching test.
298 void PopulateDatabaseForCacheTest();
300 scoped_ptr
<SafeBrowsingDatabaseNew
> database_
;
301 base::FilePath database_filename_
;
302 base::ScopedTempDir temp_dir_
;
305 // Tests retrieving list name information.
306 TEST_F(SafeBrowsingDatabaseTest
, ListNameForBrowse
) {
310 InsertAddChunkHostPrefixUrl(&chunk
, 1, "www.evil.com/",
311 "www.evil.com/malware.html");
313 chunks
.push_back(chunk
);
314 std::vector
<SBListChunkRanges
> lists
;
315 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
316 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
319 InsertAddChunkHostPrefixUrl(&chunk
, 2, "www.foo.com/",
320 "www.foo.com/malware.html");
322 chunks
.push_back(chunk
);
323 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
326 InsertAddChunkHostPrefixUrl(&chunk
, 3, "www.whatever.com/",
327 "www.whatever.com/malware.html");
329 chunks
.push_back(chunk
);
330 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
331 database_
->UpdateFinished(true);
333 GetListsInfo(&lists
);
334 EXPECT_TRUE(lists
[0].name
== safe_browsing_util::kMalwareList
);
335 EXPECT_EQ(lists
[0].adds
, "1-3");
336 EXPECT_TRUE(lists
[0].subs
.empty());
338 // Insert a malware sub chunk.
340 InsertSubChunkHostPrefixUrl(&chunk
, 7, 19, "www.subbed.com/",
341 "www.subbed.com/noteveil1.html");
343 chunks
.push_back(chunk
);
345 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
346 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
347 database_
->UpdateFinished(true);
349 GetListsInfo(&lists
);
350 EXPECT_TRUE(lists
[0].name
== safe_browsing_util::kMalwareList
);
351 EXPECT_EQ(lists
[0].adds
, "1-3");
352 EXPECT_EQ(lists
[0].subs
, "7");
353 if (lists
.size() == 2) {
354 // Old style database won't have the second entry since it creates the lists
355 // when it receives an update containing that list. The filter-based
356 // database has these values hard coded.
357 EXPECT_TRUE(lists
[1].name
== safe_browsing_util::kPhishingList
);
358 EXPECT_TRUE(lists
[1].adds
.empty());
359 EXPECT_TRUE(lists
[1].subs
.empty());
362 // Add a phishing add chunk.
364 InsertAddChunkHostPrefixUrl(&chunk
, 47, "www.evil.com/",
365 "www.evil.com/phishing.html");
367 chunks
.push_back(chunk
);
368 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
369 database_
->InsertChunks(safe_browsing_util::kPhishingList
, chunks
);
371 // Insert some phishing sub chunks.
373 InsertSubChunkHostPrefixUrl(&chunk
, 200, 1999, "www.phishy.com/",
374 "www.phishy.com/notevil1.html");
376 chunks
.push_back(chunk
);
377 database_
->InsertChunks(safe_browsing_util::kPhishingList
, chunks
);
380 InsertSubChunkHostPrefixUrl(&chunk
, 201, 1999, "www.phishy2.com/",
381 "www.phishy2.com/notevil1.html");
383 chunks
.push_back(chunk
);
384 database_
->InsertChunks(safe_browsing_util::kPhishingList
, chunks
);
385 database_
->UpdateFinished(true);
387 GetListsInfo(&lists
);
388 EXPECT_TRUE(lists
[0].name
== safe_browsing_util::kMalwareList
);
389 EXPECT_EQ(lists
[0].adds
, "1-3");
390 EXPECT_EQ(lists
[0].subs
, "7");
391 EXPECT_TRUE(lists
[1].name
== safe_browsing_util::kPhishingList
);
392 EXPECT_EQ(lists
[1].adds
, "47");
393 EXPECT_EQ(lists
[1].subs
, "200-201");
396 TEST_F(SafeBrowsingDatabaseTest
, ListNameForBrowseAndDownload
) {
398 base::MessageLoop loop
;
399 SafeBrowsingStoreFile
* browse_store
= new SafeBrowsingStoreFile();
400 SafeBrowsingStoreFile
* download_store
= new SafeBrowsingStoreFile();
401 SafeBrowsingStoreFile
* csd_whitelist_store
= new SafeBrowsingStoreFile();
402 SafeBrowsingStoreFile
* download_whitelist_store
= new SafeBrowsingStoreFile();
403 SafeBrowsingStoreFile
* extension_blacklist_store
=
404 new SafeBrowsingStoreFile();
405 SafeBrowsingStoreFile
* ip_blacklist_store
= new SafeBrowsingStoreFile();
406 database_
.reset(new SafeBrowsingDatabaseNew(browse_store
,
409 download_whitelist_store
,
410 extension_blacklist_store
,
412 ip_blacklist_store
));
413 database_
->Init(database_filename_
);
418 // Insert malware, phish, binurl and bindownload add chunks.
419 InsertAddChunkHostPrefixUrl(&chunk
, 1, "www.evil.com/",
420 "www.evil.com/malware.html");
421 chunks
.push_back(chunk
);
422 std::vector
<SBListChunkRanges
> lists
;
423 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
424 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
427 InsertAddChunkHostPrefixUrl(&chunk
, 2, "www.foo.com/",
428 "www.foo.com/malware.html");
430 chunks
.push_back(chunk
);
431 database_
->InsertChunks(safe_browsing_util::kPhishingList
, chunks
);
434 InsertAddChunkHostPrefixUrl(&chunk
, 3, "www.whatever.com/",
435 "www.whatever.com/download.html");
437 chunks
.push_back(chunk
);
438 database_
->InsertChunks(safe_browsing_util::kBinUrlList
, chunks
);
441 InsertAddChunkHostPrefixUrl(&chunk
, 4, "www.forhash.com/",
442 "www.forhash.com/download.html");
444 chunks
.push_back(chunk
);
445 database_
->InsertChunks(safe_browsing_util::kBinHashList
, chunks
);
448 InsertAddChunkHostFullHashes(&chunk
, 5, "www.forwhitelist.com/",
449 "www.forwhitelist.com/a.html");
451 chunks
.push_back(chunk
);
452 database_
->InsertChunks(safe_browsing_util::kCsdWhiteList
, chunks
);
455 InsertAddChunkHostFullHashes(&chunk
, 6, "www.download.com/",
456 "www.download.com/");
459 chunks
.push_back(chunk
);
460 database_
->InsertChunks(safe_browsing_util::kDownloadWhiteList
, chunks
);
463 InsertAddChunkHostFullHashes(&chunk
, 8,
464 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
465 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
468 chunks
.push_back(chunk
);
469 database_
->InsertChunks(safe_browsing_util::kExtensionBlacklist
, chunks
);
472 InsertAddChunkFullHash(&chunk
, 9, "::ffff:192.168.1.0", 120);
475 chunks
.push_back(chunk
);
476 database_
->InsertChunks(safe_browsing_util::kIPBlacklist
, chunks
);
478 database_
->UpdateFinished(true);
480 GetListsInfo(&lists
);
481 ASSERT_EQ(7U, lists
.size());
482 EXPECT_TRUE(lists
[0].name
== safe_browsing_util::kMalwareList
);
483 EXPECT_EQ(lists
[0].adds
, "1");
484 EXPECT_TRUE(lists
[0].subs
.empty());
485 EXPECT_TRUE(lists
[1].name
== safe_browsing_util::kPhishingList
);
486 EXPECT_EQ(lists
[1].adds
, "2");
487 EXPECT_TRUE(lists
[1].subs
.empty());
488 EXPECT_TRUE(lists
[2].name
== safe_browsing_util::kBinUrlList
);
489 EXPECT_EQ(lists
[2].adds
, "3");
490 EXPECT_TRUE(lists
[2].subs
.empty());
491 // kBinHashList is ignored. (http://crbug.com/108130)
492 EXPECT_TRUE(lists
[3].name
== safe_browsing_util::kCsdWhiteList
);
493 EXPECT_EQ(lists
[3].adds
, "5");
494 EXPECT_TRUE(lists
[3].subs
.empty());
495 EXPECT_TRUE(lists
[4].name
== safe_browsing_util::kDownloadWhiteList
);
496 EXPECT_EQ(lists
[4].adds
, "6");
497 EXPECT_TRUE(lists
[4].subs
.empty());
498 EXPECT_TRUE(lists
[5].name
== safe_browsing_util::kExtensionBlacklist
);
499 EXPECT_EQ(lists
[5].adds
, "8");
500 EXPECT_TRUE(lists
[5].subs
.empty());
501 EXPECT_TRUE(lists
[6].name
== safe_browsing_util::kIPBlacklist
);
502 EXPECT_EQ(lists
[6].adds
, "9");
503 EXPECT_TRUE(lists
[6].subs
.empty());
508 // Checks database reading and writing for browse.
509 TEST_F(SafeBrowsingDatabaseTest
, BrowseDatabase
) {
513 // Add a simple chunk with one hostkey.
514 InsertAddChunkHost2PrefixUrls(&chunk
, 1, "www.evil.com/",
515 "www.evil.com/phishing.html",
516 "www.evil.com/malware.html");
517 chunks
.push_back(chunk
);
518 std::vector
<SBListChunkRanges
> lists
;
519 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
520 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
523 InsertAddChunkHost2PrefixUrls(&chunk
, 2, "www.evil.com/",
524 "www.evil.com/notevil1.html",
525 "www.evil.com/notevil2.html");
526 InsertAddChunkHost2PrefixUrls(&chunk
, 2, "www.good.com/",
527 "www.good.com/good1.html",
528 "www.good.com/good2.html");
530 chunks
.push_back(chunk
);
531 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
533 // and a chunk with an IP-based host
535 InsertAddChunkHostPrefixUrl(&chunk
, 3, "192.168.0.1/",
536 "192.168.0.1/malware.html");
538 chunks
.push_back(chunk
);
539 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
540 database_
->UpdateFinished(true);
542 // Make sure they were added correctly.
543 GetListsInfo(&lists
);
544 EXPECT_TRUE(lists
[0].name
== safe_browsing_util::kMalwareList
);
545 EXPECT_EQ(lists
[0].adds
, "1-3");
546 EXPECT_TRUE(lists
[0].subs
.empty());
548 const Time now
= Time::Now();
549 std::vector
<SBFullHashResult
> full_hashes
;
550 std::vector
<SBPrefix
> prefix_hits
;
551 std::string matching_list
;
552 EXPECT_TRUE(database_
->ContainsBrowseUrl(
553 GURL("http://www.evil.com/phishing.html"),
554 &matching_list
, &prefix_hits
,
556 EXPECT_EQ(prefix_hits
[0], Sha256Prefix("www.evil.com/phishing.html"));
557 EXPECT_EQ(prefix_hits
.size(), 1U);
559 EXPECT_TRUE(database_
->ContainsBrowseUrl(
560 GURL("http://www.evil.com/malware.html"),
561 &matching_list
, &prefix_hits
,
564 EXPECT_TRUE(database_
->ContainsBrowseUrl(
565 GURL("http://www.evil.com/notevil1.html"),
566 &matching_list
, &prefix_hits
,
569 EXPECT_TRUE(database_
->ContainsBrowseUrl(
570 GURL("http://www.evil.com/notevil2.html"),
571 &matching_list
, &prefix_hits
,
574 EXPECT_TRUE(database_
->ContainsBrowseUrl(
575 GURL("http://www.good.com/good1.html"),
576 &matching_list
, &prefix_hits
,
579 EXPECT_TRUE(database_
->ContainsBrowseUrl(
580 GURL("http://www.good.com/good2.html"),
581 &matching_list
, &prefix_hits
,
584 EXPECT_TRUE(database_
->ContainsBrowseUrl(
585 GURL("http://192.168.0.1/malware.html"),
586 &matching_list
, &prefix_hits
,
589 EXPECT_FALSE(database_
->ContainsBrowseUrl(
590 GURL("http://www.evil.com/"),
591 &matching_list
, &prefix_hits
,
593 EXPECT_TRUE(prefix_hits
.empty());
595 EXPECT_FALSE(database_
->ContainsBrowseUrl(
596 GURL("http://www.evil.com/robots.txt"),
597 &matching_list
, &prefix_hits
,
600 // Attempt to re-add the first chunk (should be a no-op).
601 // see bug: http://code.google.com/p/chromium/issues/detail?id=4522
603 InsertAddChunkHost2PrefixUrls(&chunk
, 1, "www.evil.com/",
604 "www.evil.com/phishing.html",
605 "www.evil.com/malware.html");
607 chunks
.push_back(chunk
);
608 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
609 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
610 database_
->UpdateFinished(true);
612 GetListsInfo(&lists
);
613 EXPECT_TRUE(lists
[0].name
== safe_browsing_util::kMalwareList
);
614 EXPECT_EQ(lists
[0].adds
, "1-3");
615 EXPECT_TRUE(lists
[0].subs
.empty());
617 // Test removing a single prefix from the add chunk.
619 InsertSubChunkHostPrefixUrl(&chunk
, 4, 2, "www.evil.com/",
620 "www.evil.com/notevil1.html");
622 chunks
.push_back(chunk
);
623 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
624 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
626 database_
->UpdateFinished(true);
628 EXPECT_TRUE(database_
->ContainsBrowseUrl(
629 GURL("http://www.evil.com/phishing.html"),
630 &matching_list
, &prefix_hits
,
632 EXPECT_EQ(prefix_hits
[0], Sha256Prefix("www.evil.com/phishing.html"));
633 EXPECT_EQ(prefix_hits
.size(), 1U);
635 EXPECT_FALSE(database_
->ContainsBrowseUrl(
636 GURL("http://www.evil.com/notevil1.html"),
637 &matching_list
, &prefix_hits
,
639 EXPECT_TRUE(prefix_hits
.empty());
641 EXPECT_TRUE(database_
->ContainsBrowseUrl(
642 GURL("http://www.evil.com/notevil2.html"),
643 &matching_list
, &prefix_hits
,
646 EXPECT_TRUE(database_
->ContainsBrowseUrl(
647 GURL("http://www.good.com/good1.html"),
648 &matching_list
, &prefix_hits
,
651 EXPECT_TRUE(database_
->ContainsBrowseUrl(
652 GURL("http://www.good.com/good2.html"),
653 &matching_list
, &prefix_hits
,
656 GetListsInfo(&lists
);
657 EXPECT_TRUE(lists
[0].name
== safe_browsing_util::kMalwareList
);
658 EXPECT_EQ(lists
[0].subs
, "4");
660 // Test the same sub chunk again. This should be a no-op.
661 // see bug: http://code.google.com/p/chromium/issues/detail?id=4522
663 InsertSubChunkHostPrefixUrl(&chunk
, 4, 2, "www.evil.com/",
664 "www.evil.com/notevil1.html");
666 chunks
.push_back(chunk
);
668 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
669 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
670 database_
->UpdateFinished(true);
672 GetListsInfo(&lists
);
673 EXPECT_TRUE(lists
[0].name
== safe_browsing_util::kMalwareList
);
674 EXPECT_EQ(lists
[0].subs
, "4");
676 // Test removing all the prefixes from an add chunk.
677 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
678 AddDelChunk(safe_browsing_util::kMalwareList
, 2);
679 database_
->UpdateFinished(true);
681 EXPECT_FALSE(database_
->ContainsBrowseUrl(
682 GURL("http://www.evil.com/notevil2.html"),
683 &matching_list
, &prefix_hits
,
686 EXPECT_FALSE(database_
->ContainsBrowseUrl(
687 GURL("http://www.good.com/good1.html"),
688 &matching_list
, &prefix_hits
,
691 EXPECT_FALSE(database_
->ContainsBrowseUrl(
692 GURL("http://www.good.com/good2.html"),
693 &matching_list
, &prefix_hits
,
696 GetListsInfo(&lists
);
697 EXPECT_TRUE(lists
[0].name
== safe_browsing_util::kMalwareList
);
698 EXPECT_EQ(lists
[0].adds
, "1,3");
699 EXPECT_EQ(lists
[0].subs
, "4");
701 // The adddel command exposed a bug in the transaction code where any
702 // transaction after it would fail. Add a dummy entry and remove it to
703 // make sure the transcation works fine.
705 InsertAddChunkHostPrefixUrl(&chunk
, 44, "www.redherring.com/",
706 "www.redherring.com/index.html");
708 chunks
.push_back(chunk
);
709 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
710 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
712 // Now remove the dummy entry. If there are any problems with the
713 // transactions, asserts will fire.
714 AddDelChunk(safe_browsing_util::kMalwareList
, 44);
716 // Test the subdel command.
717 SubDelChunk(safe_browsing_util::kMalwareList
, 4);
718 database_
->UpdateFinished(true);
720 GetListsInfo(&lists
);
721 EXPECT_TRUE(lists
[0].name
== safe_browsing_util::kMalwareList
);
722 EXPECT_EQ(lists
[0].adds
, "1,3");
723 EXPECT_EQ(lists
[0].subs
, "");
725 // Test a sub command coming in before the add.
727 InsertSubChunkHost2PrefixUrls(&chunk
, 5, 10,
728 "www.notevilanymore.com/",
729 "www.notevilanymore.com/index.html",
730 "www.notevilanymore.com/good.html");
732 chunks
.push_back(chunk
);
733 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
734 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
735 database_
->UpdateFinished(true);
737 EXPECT_FALSE(database_
->ContainsBrowseUrl(
738 GURL("http://www.notevilanymore.com/index.html"),
739 &matching_list
, &prefix_hits
, &full_hashes
, now
));
741 // Now insert the tardy add chunk and we don't expect them to appear
742 // in database because of the previous sub chunk.
744 InsertAddChunkHost2PrefixUrls(&chunk
, 10, "www.notevilanymore.com/",
745 "www.notevilanymore.com/index.html",
746 "www.notevilanymore.com/good.html");
748 chunks
.push_back(chunk
);
749 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
750 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
751 database_
->UpdateFinished(true);
753 EXPECT_FALSE(database_
->ContainsBrowseUrl(
754 GURL("http://www.notevilanymore.com/index.html"),
755 &matching_list
, &prefix_hits
, &full_hashes
, now
));
757 EXPECT_FALSE(database_
->ContainsBrowseUrl(
758 GURL("http://www.notevilanymore.com/good.html"),
759 &matching_list
, &prefix_hits
, &full_hashes
, now
));
763 // Test adding zero length chunks to the database.
764 TEST_F(SafeBrowsingDatabaseTest
, ZeroSizeChunk
) {
768 // Populate with a couple of normal chunks.
769 InsertAddChunkHost2PrefixUrls(&chunk
, 1, "www.test.com/",
770 "www.test.com/test1.html",
771 "www.test.com/test2.html");
773 chunks
.push_back(chunk
);
776 InsertAddChunkHost2PrefixUrls(&chunk
, 10, "www.random.com/",
777 "www.random.com/random1.html",
778 "www.random.com/random2.html");
779 chunks
.push_back(chunk
);
781 std::vector
<SBListChunkRanges
> lists
;
782 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
783 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
784 database_
->UpdateFinished(true);
786 // Add an empty ADD and SUB chunk.
787 GetListsInfo(&lists
);
788 EXPECT_EQ(lists
[0].adds
, "1,10");
791 empty_chunk
.chunk_number
= 19;
792 empty_chunk
.is_add
= true;
794 chunks
.push_back(empty_chunk
);
795 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
796 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
798 empty_chunk
.chunk_number
= 7;
799 empty_chunk
.is_add
= false;
800 chunks
.push_back(empty_chunk
);
801 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
802 database_
->UpdateFinished(true);
804 GetListsInfo(&lists
);
805 EXPECT_EQ(lists
[0].adds
, "1,10,19");
806 EXPECT_EQ(lists
[0].subs
, "7");
808 // Add an empty chunk along with a couple that contain data. This should
809 // result in the chunk range being reduced in size.
810 empty_chunk
.hosts
.clear();
811 InsertAddChunkHostPrefixUrl(&empty_chunk
, 20, "www.notempy.com/",
812 "www.notempty.com/full1.html");
814 chunks
.push_back(empty_chunk
);
816 empty_chunk
.chunk_number
= 21;
817 empty_chunk
.is_add
= true;
818 empty_chunk
.hosts
.clear();
819 chunks
.push_back(empty_chunk
);
821 empty_chunk
.hosts
.clear();
822 InsertAddChunkHostPrefixUrl(&empty_chunk
, 22, "www.notempy.com/",
823 "www.notempty.com/full2.html");
824 chunks
.push_back(empty_chunk
);
826 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
827 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
828 database_
->UpdateFinished(true);
830 const Time now
= Time::Now();
831 std::vector
<SBFullHashResult
> full_hashes
;
832 std::vector
<SBPrefix
> prefix_hits
;
833 std::string matching_list
;
834 EXPECT_TRUE(database_
->ContainsBrowseUrl(
835 GURL("http://www.notempty.com/full1.html"),
836 &matching_list
, &prefix_hits
,
838 EXPECT_TRUE(database_
->ContainsBrowseUrl(
839 GURL("http://www.notempty.com/full2.html"),
840 &matching_list
, &prefix_hits
,
843 GetListsInfo(&lists
);
844 EXPECT_EQ(lists
[0].adds
, "1,10,19-22");
845 EXPECT_EQ(lists
[0].subs
, "7");
847 // Handle AddDel and SubDel commands for empty chunks.
848 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
849 AddDelChunk(safe_browsing_util::kMalwareList
, 21);
850 database_
->UpdateFinished(true);
852 GetListsInfo(&lists
);
853 EXPECT_EQ(lists
[0].adds
, "1,10,19-20,22");
854 EXPECT_EQ(lists
[0].subs
, "7");
856 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
857 SubDelChunk(safe_browsing_util::kMalwareList
, 7);
858 database_
->UpdateFinished(true);
860 GetListsInfo(&lists
);
861 EXPECT_EQ(lists
[0].adds
, "1,10,19-20,22");
862 EXPECT_EQ(lists
[0].subs
, "");
865 // Utility function for setting up the database for the caching test.
866 void SafeBrowsingDatabaseTest::PopulateDatabaseForCacheTest() {
869 // Add a simple chunk with one hostkey and cache it.
870 InsertAddChunkHost2PrefixUrls(&chunk
, 1, "www.evil.com/",
871 "www.evil.com/phishing.html",
872 "www.evil.com/malware.html");
873 chunks
.push_back(chunk
);
875 std::vector
<SBListChunkRanges
> lists
;
876 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
877 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
878 database_
->UpdateFinished(true);
880 // Add the GetHash results to the cache.
881 SBFullHashResult full_hash
;
882 full_hash
.hash
= Sha256Hash("www.evil.com/phishing.html");
883 full_hash
.list_name
= safe_browsing_util::kMalwareList
;
884 full_hash
.add_chunk_id
= 1;
886 std::vector
<SBFullHashResult
> results
;
887 results
.push_back(full_hash
);
889 full_hash
.hash
= Sha256Hash("www.evil.com/malware.html");
890 results
.push_back(full_hash
);
892 std::vector
<SBPrefix
> prefixes
;
893 database_
->CacheHashResults(prefixes
, results
);
896 TEST_F(SafeBrowsingDatabaseTest
, HashCaching
) {
897 PopulateDatabaseForCacheTest();
899 // We should have both full hashes in the cache.
900 EXPECT_EQ(database_
->pending_browse_hashes_
.size(), 2U);
902 // Test the cache lookup for the first prefix.
903 std::string listname
;
904 std::vector
<SBPrefix
> prefixes
;
905 std::vector
<SBFullHashResult
> full_hashes
;
906 database_
->ContainsBrowseUrl(
907 GURL("http://www.evil.com/phishing.html"),
908 &listname
, &prefixes
, &full_hashes
, Time::Now());
909 EXPECT_EQ(full_hashes
.size(), 1U);
910 EXPECT_TRUE(SBFullHashEq(full_hashes
[0].hash
,
911 Sha256Hash("www.evil.com/phishing.html")));
916 // Test the cache lookup for the second prefix.
917 database_
->ContainsBrowseUrl(
918 GURL("http://www.evil.com/malware.html"),
919 &listname
, &prefixes
, &full_hashes
, Time::Now());
920 EXPECT_EQ(full_hashes
.size(), 1U);
921 EXPECT_TRUE(SBFullHashEq(full_hashes
[0].hash
,
922 Sha256Hash("www.evil.com/malware.html")));
927 // Test removing a prefix via a sub chunk.
930 InsertSubChunkHostPrefixUrl(&chunk
, 2, 1, "www.evil.com/",
931 "www.evil.com/phishing.html");
932 chunks
.push_back(chunk
);
934 std::vector
<SBListChunkRanges
> lists
;
935 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
936 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
937 database_
->UpdateFinished(true);
939 // This prefix should still be there.
940 database_
->ContainsBrowseUrl(
941 GURL("http://www.evil.com/malware.html"),
942 &listname
, &prefixes
, &full_hashes
, Time::Now());
943 EXPECT_EQ(full_hashes
.size(), 1U);
944 EXPECT_TRUE(SBFullHashEq(full_hashes
[0].hash
,
945 Sha256Hash("www.evil.com/malware.html")));
949 // This prefix should be gone.
950 database_
->ContainsBrowseUrl(
951 GURL("http://www.evil.com/phishing.html"),
952 &listname
, &prefixes
, &full_hashes
, Time::Now());
953 EXPECT_TRUE(full_hashes
.empty());
958 // Test that an AddDel for the original chunk removes the last cached entry.
959 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
960 AddDelChunk(safe_browsing_util::kMalwareList
, 1);
961 database_
->UpdateFinished(true);
962 database_
->ContainsBrowseUrl(
963 GURL("http://www.evil.com/malware.html"),
964 &listname
, &prefixes
, &full_hashes
, Time::Now());
965 EXPECT_TRUE(full_hashes
.empty());
966 EXPECT_TRUE(database_
->full_browse_hashes_
.empty());
967 EXPECT_TRUE(database_
->pending_browse_hashes_
.empty());
972 // Test that the cache won't return expired values. First we have to adjust
973 // the cached entries' received time to make them older, since the database
974 // cache insert uses Time::Now(). First, store some entries.
975 PopulateDatabaseForCacheTest();
977 std::vector
<SBAddFullHash
>* hash_cache
= &database_
->pending_browse_hashes_
;
978 EXPECT_EQ(hash_cache
->size(), 2U);
980 // Now adjust one of the entries times to be in the past.
981 base::Time expired
= base::Time::Now() - base::TimeDelta::FromMinutes(60);
982 const SBPrefix key
= Sha256Prefix("www.evil.com/malware.html");
983 std::vector
<SBAddFullHash
>::iterator iter
;
984 for (iter
= hash_cache
->begin(); iter
!= hash_cache
->end(); ++iter
) {
985 if (iter
->full_hash
.prefix
== key
) {
986 iter
->received
= static_cast<int32
>(expired
.ToTimeT());
990 EXPECT_TRUE(iter
!= hash_cache
->end());
992 database_
->ContainsBrowseUrl(
993 GURL("http://www.evil.com/malware.html"),
994 &listname
, &prefixes
, &full_hashes
, expired
);
995 EXPECT_TRUE(full_hashes
.empty());
997 // This entry should still exist.
998 database_
->ContainsBrowseUrl(
999 GURL("http://www.evil.com/phishing.html"),
1000 &listname
, &prefixes
, &full_hashes
, expired
);
1001 EXPECT_EQ(full_hashes
.size(), 1U);
1004 // Testing prefix miss caching. First, we clear out the existing database,
1005 // Since PopulateDatabaseForCacheTest() doesn't handle adding duplicate
1007 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
1008 AddDelChunk(safe_browsing_util::kMalwareList
, 1);
1009 database_
->UpdateFinished(true);
1011 std::vector
<SBPrefix
> prefix_misses
;
1012 std::vector
<SBFullHashResult
> empty_full_hash
;
1013 prefix_misses
.push_back(Sha256Prefix("http://www.bad.com/malware.html"));
1014 prefix_misses
.push_back(Sha256Prefix("http://www.bad.com/phishing.html"));
1015 database_
->CacheHashResults(prefix_misses
, empty_full_hash
);
1017 // Prefixes with no full results are misses.
1018 EXPECT_EQ(database_
->prefix_miss_cache_
.size(), 2U);
1020 // Update the database.
1021 PopulateDatabaseForCacheTest();
1023 // Prefix miss cache should be cleared.
1024 EXPECT_TRUE(database_
->prefix_miss_cache_
.empty());
1026 // Cache a GetHash miss for a particular prefix, and even though the prefix is
1027 // in the database, it is flagged as a miss so looking up the associated URL
1028 // will not succeed.
1030 full_hashes
.clear();
1031 prefix_misses
.clear();
1032 empty_full_hash
.clear();
1033 prefix_misses
.push_back(Sha256Prefix("www.evil.com/phishing.html"));
1034 database_
->CacheHashResults(prefix_misses
, empty_full_hash
);
1035 EXPECT_FALSE(database_
->ContainsBrowseUrl(
1036 GURL("http://www.evil.com/phishing.html"),
1037 &listname
, &prefixes
,
1038 &full_hashes
, Time::Now()));
1041 full_hashes
.clear();
1043 // Test receiving a full add chunk.
1044 chunk
.hosts
.clear();
1045 InsertAddChunkHost2FullHashes(&chunk
, 20, "www.fullevil.com/",
1046 "www.fullevil.com/bad1.html",
1047 "www.fullevil.com/bad2.html");
1049 chunks
.push_back(chunk
);
1050 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
1051 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
1052 database_
->UpdateFinished(true);
1054 EXPECT_TRUE(database_
->ContainsBrowseUrl(
1055 GURL("http://www.fullevil.com/bad1.html"),
1056 &listname
, &prefixes
, &full_hashes
,
1058 EXPECT_EQ(full_hashes
.size(), 1U);
1059 EXPECT_TRUE(SBFullHashEq(full_hashes
[0].hash
,
1060 Sha256Hash("www.fullevil.com/bad1.html")));
1062 full_hashes
.clear();
1064 EXPECT_TRUE(database_
->ContainsBrowseUrl(
1065 GURL("http://www.fullevil.com/bad2.html"),
1066 &listname
, &prefixes
, &full_hashes
,
1068 EXPECT_EQ(full_hashes
.size(), 1U);
1069 EXPECT_TRUE(SBFullHashEq(full_hashes
[0].hash
,
1070 Sha256Hash("www.fullevil.com/bad2.html")));
1072 full_hashes
.clear();
1074 // Test receiving a full sub chunk, which will remove one of the full adds.
1075 chunk
.hosts
.clear();
1076 InsertSubChunkHostFullHash(&chunk
, 200, 20,
1077 "www.fullevil.com/",
1078 "www.fullevil.com/bad1.html");
1080 chunks
.push_back(chunk
);
1081 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
1082 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
1083 database_
->UpdateFinished(true);
1085 EXPECT_FALSE(database_
->ContainsBrowseUrl(
1086 GURL("http://www.fullevil.com/bad1.html"),
1087 &listname
, &prefixes
, &full_hashes
,
1089 EXPECT_TRUE(full_hashes
.empty());
1091 // There should be one remaining full add.
1092 EXPECT_TRUE(database_
->ContainsBrowseUrl(
1093 GURL("http://www.fullevil.com/bad2.html"),
1094 &listname
, &prefixes
, &full_hashes
,
1096 EXPECT_EQ(full_hashes
.size(), 1U);
1097 EXPECT_TRUE(SBFullHashEq(full_hashes
[0].hash
,
1098 Sha256Hash("www.fullevil.com/bad2.html")));
1100 full_hashes
.clear();
1102 // Now test an AddDel for the remaining full add.
1103 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
1104 AddDelChunk(safe_browsing_util::kMalwareList
, 20);
1105 database_
->UpdateFinished(true);
1107 EXPECT_FALSE(database_
->ContainsBrowseUrl(
1108 GURL("http://www.fullevil.com/bad1.html"),
1109 &listname
, &prefixes
, &full_hashes
,
1111 EXPECT_FALSE(database_
->ContainsBrowseUrl(
1112 GURL("http://www.fullevil.com/bad2.html"),
1113 &listname
, &prefixes
, &full_hashes
,
1117 // Test that corrupt databases are appropriately handled, even if the
1118 // corruption is detected in the midst of the update.
1119 // TODO(shess): Disabled until ScopedLogMessageIgnorer resolved.
1120 // http://crbug.com/56448
1121 TEST_F(SafeBrowsingDatabaseTest
, DISABLED_FileCorruptionHandling
) {
1122 // Re-create the database in a captive message loop so that we can
1123 // influence task-posting. Database specifically needs to the
1126 base::MessageLoop loop
;
1127 SafeBrowsingStoreFile
* store
= new SafeBrowsingStoreFile();
1128 database_
.reset(new SafeBrowsingDatabaseNew(store
, NULL
, NULL
, NULL
, NULL
,
1130 database_
->Init(database_filename_
);
1132 // This will cause an empty database to be created.
1133 std::vector
<SBListChunkRanges
> lists
;
1134 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
1135 database_
->UpdateFinished(true);
1137 // Create a sub chunk to insert.
1141 host
.host
= Sha256Prefix("www.subbed.com/");
1142 host
.entry
= SBEntry::Create(SBEntry::SUB_PREFIX
, 1);
1143 host
.entry
->set_chunk_id(7);
1144 host
.entry
->SetChunkIdAtPrefix(0, 19);
1145 host
.entry
->SetPrefixAt(0, Sha256Prefix("www.subbed.com/notevil1.html"));
1146 chunk
.chunk_number
= 7;
1147 chunk
.is_add
= false;
1148 chunk
.hosts
.clear();
1149 chunk
.hosts
.push_back(host
);
1151 chunks
.push_back(chunk
);
1153 // Corrupt the file by corrupting the checksum, which is not checked
1154 // until the entire table is read in |UpdateFinished()|.
1155 FILE* fp
= base::OpenFile(database_filename_
, "r+");
1157 ASSERT_NE(-1, fseek(fp
, -8, SEEK_END
));
1158 for (size_t i
= 0; i
< 8; ++i
) {
1164 // The following code will cause DCHECKs, so suppress the crashes.
1165 ScopedLogMessageIgnorer ignorer
;
1167 // Start an update. The insert will fail due to corruption.
1168 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
1169 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
1170 database_
->UpdateFinished(true);
1172 // Database file still exists until the corruption handler has run.
1173 EXPECT_TRUE(base::PathExists(database_filename_
));
1175 // Flush through the corruption-handler task.
1176 VLOG(1) << "Expect failed check on: SafeBrowsing database reset";
1177 base::MessageLoop::current()->RunUntilIdle();
1180 // Database file should not exist.
1181 EXPECT_FALSE(base::PathExists(database_filename_
));
1183 // Run the update again successfully.
1184 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
1185 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
1186 database_
->UpdateFinished(true);
1187 EXPECT_TRUE(base::PathExists(database_filename_
));
1192 // Checks database reading and writing.
1193 TEST_F(SafeBrowsingDatabaseTest
, ContainsDownloadUrl
) {
1195 base::MessageLoop loop
;
1196 SafeBrowsingStoreFile
* browse_store
= new SafeBrowsingStoreFile();
1197 SafeBrowsingStoreFile
* download_store
= new SafeBrowsingStoreFile();
1198 SafeBrowsingStoreFile
* csd_whitelist_store
= new SafeBrowsingStoreFile();
1199 database_
.reset(new SafeBrowsingDatabaseNew(browse_store
,
1201 csd_whitelist_store
,
1206 database_
->Init(database_filename_
);
1208 const char kEvil1Host
[] = "www.evil1.com/";
1209 const char kEvil1Url1
[] = "www.evil1.com/download1/";
1210 const char kEvil1Url2
[] = "www.evil1.com/download2.html";
1214 // Add a simple chunk with one hostkey for download url list.
1215 InsertAddChunkHost2PrefixUrls(&chunk
, 1, kEvil1Host
,
1216 kEvil1Url1
, kEvil1Url2
);
1217 chunks
.push_back(chunk
);
1218 std::vector
<SBListChunkRanges
> lists
;
1219 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
1220 database_
->InsertChunks(safe_browsing_util::kBinUrlList
, chunks
);
1221 database_
->UpdateFinished(true);
1223 std::vector
<SBPrefix
> prefix_hits
;
1224 std::vector
<GURL
> urls(1);
1226 urls
[0] = GURL(std::string("http://") + kEvil1Url1
);
1227 EXPECT_TRUE(database_
->ContainsDownloadUrl(urls
, &prefix_hits
));
1228 ASSERT_EQ(prefix_hits
.size(), 1U);
1229 EXPECT_EQ(prefix_hits
[0], Sha256Prefix(kEvil1Url1
));
1231 urls
[0] = GURL(std::string("http://") + kEvil1Url2
);
1232 EXPECT_TRUE(database_
->ContainsDownloadUrl(urls
, &prefix_hits
));
1233 ASSERT_EQ(prefix_hits
.size(), 1U);
1234 EXPECT_EQ(prefix_hits
[0], Sha256Prefix(kEvil1Url2
));
1236 urls
[0] = GURL(std::string("https://") + kEvil1Url2
);
1237 EXPECT_TRUE(database_
->ContainsDownloadUrl(urls
, &prefix_hits
));
1238 ASSERT_EQ(prefix_hits
.size(), 1U);
1239 EXPECT_EQ(prefix_hits
[0], Sha256Prefix(kEvil1Url2
));
1241 urls
[0] = GURL(std::string("ftp://") + kEvil1Url2
);
1242 EXPECT_TRUE(database_
->ContainsDownloadUrl(urls
, &prefix_hits
));
1243 ASSERT_EQ(prefix_hits
.size(), 1U);
1244 EXPECT_EQ(prefix_hits
[0], Sha256Prefix(kEvil1Url2
));
1246 urls
[0] = GURL("http://www.randomevil.com");
1247 EXPECT_FALSE(database_
->ContainsDownloadUrl(urls
, &prefix_hits
));
1249 // Should match with query args stripped.
1250 urls
[0] = GURL(std::string("http://") + kEvil1Url2
+ "?blah");
1251 EXPECT_TRUE(database_
->ContainsDownloadUrl(urls
, &prefix_hits
));
1252 ASSERT_EQ(prefix_hits
.size(), 1U);
1253 EXPECT_EQ(prefix_hits
[0], Sha256Prefix(kEvil1Url2
));
1255 // Should match with extra path stuff and query args stripped.
1256 urls
[0] = GURL(std::string("http://") + kEvil1Url1
+ "foo/bar?blah");
1257 EXPECT_TRUE(database_
->ContainsDownloadUrl(urls
, &prefix_hits
));
1258 ASSERT_EQ(prefix_hits
.size(), 1U);
1259 EXPECT_EQ(prefix_hits
[0], Sha256Prefix(kEvil1Url1
));
1261 // First hit in redirect chain is malware.
1263 urls
.push_back(GURL(std::string("http://") + kEvil1Url1
));
1264 urls
.push_back(GURL("http://www.randomevil.com"));
1265 EXPECT_TRUE(database_
->ContainsDownloadUrl(urls
, &prefix_hits
));
1266 ASSERT_EQ(prefix_hits
.size(), 1U);
1267 EXPECT_EQ(prefix_hits
[0], Sha256Prefix(kEvil1Url1
));
1269 // Middle hit in redirect chain is malware.
1271 urls
.push_back(GURL("http://www.randomevil.com"));
1272 urls
.push_back(GURL(std::string("http://") + kEvil1Url1
));
1273 urls
.push_back(GURL("http://www.randomevil2.com"));
1274 EXPECT_TRUE(database_
->ContainsDownloadUrl(urls
, &prefix_hits
));
1275 ASSERT_EQ(prefix_hits
.size(), 1U);
1276 EXPECT_EQ(prefix_hits
[0], Sha256Prefix(kEvil1Url1
));
1278 // Final hit in redirect chain is malware.
1280 urls
.push_back(GURL("http://www.randomevil.com"));
1281 urls
.push_back(GURL(std::string("http://") + kEvil1Url1
));
1282 EXPECT_TRUE(database_
->ContainsDownloadUrl(urls
, &prefix_hits
));
1283 ASSERT_EQ(prefix_hits
.size(), 1U);
1284 EXPECT_EQ(prefix_hits
[0], Sha256Prefix(kEvil1Url1
));
1286 // Multiple hits in redirect chain are in malware list.
1288 urls
.push_back(GURL(std::string("http://") + kEvil1Url1
));
1289 urls
.push_back(GURL(std::string("https://") + kEvil1Url2
));
1290 EXPECT_TRUE(database_
->ContainsDownloadUrl(urls
, &prefix_hits
));
1291 ASSERT_EQ(prefix_hits
.size(), 2U);
1292 EXPECT_EQ(prefix_hits
[0], Sha256Prefix(kEvil1Url1
));
1293 EXPECT_EQ(prefix_hits
[1], Sha256Prefix(kEvil1Url2
));
1297 // Checks that the whitelists are handled properly.
1298 TEST_F(SafeBrowsingDatabaseTest
, Whitelists
) {
1300 // We expect all calls to ContainsCsdWhitelistedUrl in particular to be made
1301 // from the IO thread. In general the whitelist lookups are thread-safe.
1302 content::TestBrowserThreadBundle thread_bundle_
;
1304 // If the whitelist is disabled everything should match the whitelist.
1305 database_
.reset(new SafeBrowsingDatabaseNew(new SafeBrowsingStoreFile(),
1306 NULL
, NULL
, NULL
, NULL
, NULL
,
1308 database_
->Init(database_filename_
);
1309 EXPECT_TRUE(database_
->ContainsDownloadWhitelistedUrl(
1310 GURL(std::string("http://www.phishing.com/"))));
1311 EXPECT_TRUE(database_
->ContainsDownloadWhitelistedUrl(
1312 GURL(std::string("http://www.phishing.com/"))));
1313 EXPECT_TRUE(database_
->ContainsDownloadWhitelistedString("asdf"));
1315 SafeBrowsingStoreFile
* browse_store
= new SafeBrowsingStoreFile();
1316 SafeBrowsingStoreFile
* csd_whitelist_store
= new SafeBrowsingStoreFile();
1317 SafeBrowsingStoreFile
* download_whitelist_store
= new SafeBrowsingStoreFile();
1318 SafeBrowsingStoreFile
* extension_blacklist_store
=
1319 new SafeBrowsingStoreFile();
1320 database_
.reset(new SafeBrowsingDatabaseNew(browse_store
, NULL
,
1321 csd_whitelist_store
,
1322 download_whitelist_store
,
1323 extension_blacklist_store
,
1325 database_
->Init(database_filename_
);
1327 const char kGood1Host
[] = "www.good1.com/";
1328 const char kGood1Url1
[] = "www.good1.com/a/b.html";
1329 const char kGood1Url2
[] = "www.good1.com/b/";
1331 const char kGood2Host
[] = "www.good2.com/";
1332 const char kGood2Url1
[] = "www.good2.com/c"; // Should match '/c/bla'.
1334 // good3.com/a/b/c/d/e/f/g/ should match because it's a whitelist.
1335 const char kGood3Host
[] = "good3.com/";
1336 const char kGood3Url1
[] = "good3.com/";
1338 const char kGoodString
[] = "good_string";
1340 SBChunkList download_chunks
, csd_chunks
;
1342 // Add two simple chunks to the csd whitelist.
1343 InsertAddChunkHost2FullHashes(&chunk
, 1, kGood1Host
,
1344 kGood1Url1
, kGood1Url2
);
1345 csd_chunks
.push_back(chunk
);
1347 chunk
.hosts
.clear();
1348 InsertAddChunkHostFullHashes(&chunk
, 2, kGood2Host
, kGood2Url1
);
1349 csd_chunks
.push_back(chunk
);
1351 chunk
.hosts
.clear();
1352 InsertAddChunkHostFullHashes(&chunk
, 2, kGood2Host
, kGood2Url1
);
1353 download_chunks
.push_back(chunk
);
1355 chunk
.hosts
.clear();
1356 InsertAddChunkHostFullHashes(&chunk
, 3, kGoodString
, kGoodString
);
1357 download_chunks
.push_back(chunk
);
1359 chunk
.hosts
.clear();
1360 InsertAddChunkHostFullHashes(&chunk
, 4, kGood3Host
, kGood3Url1
);
1361 download_chunks
.push_back(chunk
);
1363 std::vector
<SBListChunkRanges
> lists
;
1364 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
1365 database_
->InsertChunks(safe_browsing_util::kCsdWhiteList
,
1367 database_
->InsertChunks(safe_browsing_util::kDownloadWhiteList
,
1369 database_
->UpdateFinished(true);
1371 EXPECT_FALSE(database_
->ContainsCsdWhitelistedUrl(
1372 GURL(std::string("http://") + kGood1Host
)));
1374 EXPECT_TRUE(database_
->ContainsCsdWhitelistedUrl(
1375 GURL(std::string("http://") + kGood1Url1
)));
1376 EXPECT_TRUE(database_
->ContainsCsdWhitelistedUrl(
1377 GURL(std::string("http://") + kGood1Url1
+ "?a=b")));
1379 EXPECT_TRUE(database_
->ContainsCsdWhitelistedUrl(
1380 GURL(std::string("http://") + kGood1Url2
)));
1381 EXPECT_TRUE(database_
->ContainsCsdWhitelistedUrl(
1382 GURL(std::string("http://") + kGood1Url2
+ "/c.html")));
1384 EXPECT_TRUE(database_
->ContainsCsdWhitelistedUrl(
1385 GURL(std::string("https://") + kGood1Url2
+ "/c.html")));
1387 EXPECT_TRUE(database_
->ContainsCsdWhitelistedUrl(
1388 GURL(std::string("http://") + kGood2Url1
+ "/c")));
1389 EXPECT_TRUE(database_
->ContainsCsdWhitelistedUrl(
1390 GURL(std::string("http://") + kGood2Url1
+ "/c?bla")));
1391 EXPECT_TRUE(database_
->ContainsCsdWhitelistedUrl(
1392 GURL(std::string("http://") + kGood2Url1
+ "/c/bla")));
1394 EXPECT_FALSE(database_
->ContainsCsdWhitelistedUrl(
1395 GURL(std::string("http://www.google.com/"))));
1397 EXPECT_TRUE(database_
->ContainsDownloadWhitelistedUrl(
1398 GURL(std::string("http://") + kGood2Url1
+ "/c")));
1399 EXPECT_TRUE(database_
->ContainsDownloadWhitelistedUrl(
1400 GURL(std::string("http://") + kGood2Url1
+ "/c?bla")));
1401 EXPECT_TRUE(database_
->ContainsDownloadWhitelistedUrl(
1402 GURL(std::string("http://") + kGood2Url1
+ "/c/bla")));
1404 EXPECT_TRUE(database_
->ContainsDownloadWhitelistedUrl(
1405 GURL(std::string("http://good3.com/a/b/c/d/e/f/g/"))));
1406 EXPECT_TRUE(database_
->ContainsDownloadWhitelistedUrl(
1407 GURL(std::string("http://a.b.good3.com/"))));
1409 EXPECT_FALSE(database_
->ContainsDownloadWhitelistedString("asdf"));
1410 EXPECT_TRUE(database_
->ContainsDownloadWhitelistedString(kGoodString
));
1412 EXPECT_FALSE(database_
->ContainsDownloadWhitelistedUrl(
1413 GURL(std::string("http://www.google.com/"))));
1415 // Test only add the malware IP killswitch
1417 chunk
.hosts
.clear();
1418 InsertAddChunkHostFullHashes(
1419 &chunk
, 15, "sb-ssl.google.com/",
1420 "sb-ssl.google.com/safebrowsing/csd/killswitch_malware");
1421 csd_chunks
.push_back(chunk
);
1422 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
1423 database_
->InsertChunks(safe_browsing_util::kCsdWhiteList
, csd_chunks
);
1424 database_
->UpdateFinished(true);
1426 EXPECT_TRUE(database_
->IsMalwareIPMatchKillSwitchOn());
1428 // Test that the kill-switch works as intended.
1430 download_chunks
.clear();
1432 chunk
.hosts
.clear();
1433 InsertAddChunkHostFullHashes(&chunk
, 5, "sb-ssl.google.com/",
1434 "sb-ssl.google.com/safebrowsing/csd/killswitch");
1435 csd_chunks
.push_back(chunk
);
1436 chunk
.hosts
.clear();
1437 InsertAddChunkHostFullHashes(&chunk
, 5, "sb-ssl.google.com/",
1438 "sb-ssl.google.com/safebrowsing/csd/killswitch");
1439 download_chunks
.push_back(chunk
);
1441 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
1442 database_
->InsertChunks(safe_browsing_util::kCsdWhiteList
, csd_chunks
);
1443 database_
->InsertChunks(safe_browsing_util::kDownloadWhiteList
,
1445 database_
->UpdateFinished(true);
1447 EXPECT_TRUE(database_
->IsMalwareIPMatchKillSwitchOn());
1448 EXPECT_TRUE(database_
->ContainsCsdWhitelistedUrl(
1449 GURL(std::string("https://") + kGood1Url2
+ "/c.html")));
1450 EXPECT_TRUE(database_
->ContainsCsdWhitelistedUrl(
1451 GURL(std::string("http://www.google.com/"))));
1452 EXPECT_TRUE(database_
->ContainsCsdWhitelistedUrl(
1453 GURL(std::string("http://www.phishing_url.com/"))));
1455 EXPECT_TRUE(database_
->ContainsDownloadWhitelistedUrl(
1456 GURL(std::string("https://") + kGood1Url2
+ "/c.html")));
1457 EXPECT_TRUE(database_
->ContainsDownloadWhitelistedUrl(
1458 GURL(std::string("http://www.google.com/"))));
1459 EXPECT_TRUE(database_
->ContainsDownloadWhitelistedUrl(
1460 GURL(std::string("http://www.phishing_url.com/"))));
1462 EXPECT_TRUE(database_
->ContainsDownloadWhitelistedString("asdf"));
1463 EXPECT_TRUE(database_
->ContainsDownloadWhitelistedString(kGoodString
));
1465 // Remove the kill-switch and verify that we can recover.
1467 download_chunks
.clear();
1470 InsertSubChunkHostFullHash(&sub_chunk
, 1, 5,
1471 "sb-ssl.google.com/",
1472 "sb-ssl.google.com/safebrowsing/csd/killswitch");
1473 csd_chunks
.push_back(sub_chunk
);
1475 sub_chunk
.hosts
.clear();
1476 InsertSubChunkHostFullHash(
1477 &sub_chunk
, 10, 15, "sb-ssl.google.com/",
1478 "sb-ssl.google.com/safebrowsing/csd/killswitch_malware");
1479 csd_chunks
.push_back(sub_chunk
);
1481 sub_chunk
.hosts
.clear();
1482 InsertSubChunkHostFullHash(&sub_chunk
, 1, 5,
1483 "sb-ssl.google.com/",
1484 "sb-ssl.google.com/safebrowsing/csd/killswitch");
1485 download_chunks
.push_back(sub_chunk
);
1487 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
1488 database_
->InsertChunks(safe_browsing_util::kCsdWhiteList
, csd_chunks
);
1489 database_
->InsertChunks(safe_browsing_util::kDownloadWhiteList
,
1491 database_
->UpdateFinished(true);
1493 EXPECT_FALSE(database_
->IsMalwareIPMatchKillSwitchOn());
1494 EXPECT_TRUE(database_
->ContainsCsdWhitelistedUrl(
1495 GURL(std::string("https://") + kGood1Url2
+ "/c.html")));
1496 EXPECT_TRUE(database_
->ContainsCsdWhitelistedUrl(
1497 GURL(std::string("https://") + kGood2Url1
+ "/c/bla")));
1498 EXPECT_FALSE(database_
->ContainsCsdWhitelistedUrl(
1499 GURL(std::string("http://www.google.com/"))));
1500 EXPECT_FALSE(database_
->ContainsCsdWhitelistedUrl(
1501 GURL(std::string("http://www.phishing_url.com/"))));
1503 EXPECT_TRUE(database_
->ContainsDownloadWhitelistedUrl(
1504 GURL(std::string("https://") + kGood2Url1
+ "/c/bla")));
1505 EXPECT_TRUE(database_
->ContainsDownloadWhitelistedUrl(
1506 GURL(std::string("https://good3.com/"))));
1507 EXPECT_TRUE(database_
->ContainsDownloadWhitelistedString(kGoodString
));
1508 EXPECT_FALSE(database_
->ContainsDownloadWhitelistedUrl(
1509 GURL(std::string("http://www.google.com/"))));
1510 EXPECT_FALSE(database_
->ContainsDownloadWhitelistedUrl(
1511 GURL(std::string("http://www.phishing_url.com/"))));
1512 EXPECT_FALSE(database_
->ContainsDownloadWhitelistedString("asdf"));
1517 // Test to make sure we could insert chunk list that
1518 // contains entries for the same host.
1519 TEST_F(SafeBrowsingDatabaseTest
, SameHostEntriesOkay
) {
1522 // Add a malware add chunk with two entries of the same host.
1523 InsertAddChunkHostPrefixUrl(&chunk
, 1, "www.evil.com/",
1524 "www.evil.com/malware1.html");
1525 InsertAddChunkHostPrefixUrl(&chunk
, 1, "www.evil.com/",
1526 "www.evil.com/malware2.html");
1528 chunks
.push_back(chunk
);
1530 // Insert the testing chunks into database.
1531 std::vector
<SBListChunkRanges
> lists
;
1532 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
1533 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
1534 database_
->UpdateFinished(true);
1536 GetListsInfo(&lists
);
1537 EXPECT_EQ(std::string(safe_browsing_util::kMalwareList
), lists
[0].name
);
1538 EXPECT_EQ("1", lists
[0].adds
);
1539 EXPECT_TRUE(lists
[0].subs
.empty());
1541 // Add a phishing add chunk with two entries of the same host.
1542 chunk
.hosts
.clear();
1543 InsertAddChunkHostPrefixUrl(&chunk
, 47, "www.evil.com/",
1544 "www.evil.com/phishing1.html");
1545 InsertAddChunkHostPrefixUrl(&chunk
, 47, "www.evil.com/",
1546 "www.evil.com/phishing2.html");
1548 chunks
.push_back(chunk
);
1550 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
1551 database_
->InsertChunks(safe_browsing_util::kPhishingList
, chunks
);
1552 database_
->UpdateFinished(true);
1554 GetListsInfo(&lists
);
1555 EXPECT_EQ(std::string(safe_browsing_util::kMalwareList
), lists
[0].name
);
1556 EXPECT_EQ("1", lists
[0].adds
);
1557 EXPECT_EQ(std::string(safe_browsing_util::kPhishingList
), lists
[1].name
);
1558 EXPECT_EQ("47", lists
[1].adds
);
1560 const Time now
= Time::Now();
1561 std::vector
<SBPrefix
> prefixes
;
1562 std::vector
<SBFullHashResult
> full_hashes
;
1563 std::vector
<SBPrefix
> prefix_hits
;
1564 std::string matching_list
;
1565 std::string listname
;
1567 EXPECT_TRUE(database_
->ContainsBrowseUrl(
1568 GURL("http://www.evil.com/malware1.html"),
1569 &listname
, &prefixes
, &full_hashes
, now
));
1570 EXPECT_TRUE(database_
->ContainsBrowseUrl(
1571 GURL("http://www.evil.com/malware2.html"),
1572 &listname
, &prefixes
, &full_hashes
, now
));
1573 EXPECT_TRUE(database_
->ContainsBrowseUrl(
1574 GURL("http://www.evil.com/phishing1.html"),
1575 &listname
, &prefixes
, &full_hashes
, now
));
1576 EXPECT_TRUE(database_
->ContainsBrowseUrl(
1577 GURL("http://www.evil.com/phishing2.html"),
1578 &listname
, &prefixes
, &full_hashes
, now
));
1580 // Test removing a single prefix from the add chunk.
1581 // Remove the prefix that added first.
1582 chunk
.hosts
.clear();
1583 InsertSubChunkHostPrefixUrl(&chunk
, 4, 1, "www.evil.com/",
1584 "www.evil.com/malware1.html");
1586 chunks
.push_back(chunk
);
1587 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
1588 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
1589 database_
->UpdateFinished(true);
1591 // Remove the prefix that added last.
1592 chunk
.hosts
.clear();
1593 InsertSubChunkHostPrefixUrl(&chunk
, 5, 47, "www.evil.com/",
1594 "www.evil.com/phishing2.html");
1596 chunks
.push_back(chunk
);
1597 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
1598 database_
->InsertChunks(safe_browsing_util::kPhishingList
, chunks
);
1599 database_
->UpdateFinished(true);
1601 // Verify that the database contains urls expected.
1602 EXPECT_FALSE(database_
->ContainsBrowseUrl(
1603 GURL("http://www.evil.com/malware1.html"),
1604 &listname
, &prefixes
, &full_hashes
, now
));
1605 EXPECT_TRUE(database_
->ContainsBrowseUrl(
1606 GURL("http://www.evil.com/malware2.html"),
1607 &listname
, &prefixes
, &full_hashes
, now
));
1608 EXPECT_TRUE(database_
->ContainsBrowseUrl(
1609 GURL("http://www.evil.com/phishing1.html"),
1610 &listname
, &prefixes
, &full_hashes
, now
));
1611 EXPECT_FALSE(database_
->ContainsBrowseUrl(
1612 GURL("http://www.evil.com/phishing2.html"),
1613 &listname
, &prefixes
, &full_hashes
, now
));
1616 // Test that an empty update doesn't actually update the database.
1617 // This isn't a functionality requirement, but it is a useful
1619 TEST_F(SafeBrowsingDatabaseTest
, EmptyUpdate
) {
1623 base::FilePath filename
= database_
->BrowseDBFilename(database_filename_
);
1625 // Prime the database.
1626 std::vector
<SBListChunkRanges
> lists
;
1627 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
1629 InsertAddChunkHostPrefixUrl(&chunk
, 1, "www.evil.com/",
1630 "www.evil.com/malware.html");
1632 chunks
.push_back(chunk
);
1633 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
1634 database_
->UpdateFinished(true);
1636 // Get an older time to reset the lastmod time for detecting whether
1637 // the file has been updated.
1638 base::File::Info before_info
, after_info
;
1639 ASSERT_TRUE(base::GetFileInfo(filename
, &before_info
));
1640 const base::Time old_last_modified
=
1641 before_info
.last_modified
- base::TimeDelta::FromSeconds(10);
1643 // Inserting another chunk updates the database file. The sleep is
1644 // needed because otherwise the entire test can finish w/in the
1645 // resolution of the lastmod time.
1646 ASSERT_TRUE(base::TouchFile(filename
, old_last_modified
, old_last_modified
));
1647 ASSERT_TRUE(base::GetFileInfo(filename
, &before_info
));
1648 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
1649 chunk
.hosts
.clear();
1650 InsertAddChunkHostPrefixUrl(&chunk
, 2, "www.foo.com/",
1651 "www.foo.com/malware.html");
1653 chunks
.push_back(chunk
);
1654 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
1655 database_
->UpdateFinished(true);
1656 ASSERT_TRUE(base::GetFileInfo(filename
, &after_info
));
1657 EXPECT_LT(before_info
.last_modified
, after_info
.last_modified
);
1659 // Deleting a chunk updates the database file.
1660 ASSERT_TRUE(base::TouchFile(filename
, old_last_modified
, old_last_modified
));
1661 ASSERT_TRUE(base::GetFileInfo(filename
, &before_info
));
1662 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
1663 AddDelChunk(safe_browsing_util::kMalwareList
, chunk
.chunk_number
);
1664 database_
->UpdateFinished(true);
1665 ASSERT_TRUE(base::GetFileInfo(filename
, &after_info
));
1666 EXPECT_LT(before_info
.last_modified
, after_info
.last_modified
);
1668 // Simply calling |UpdateStarted()| then |UpdateFinished()| does not
1669 // update the database file.
1670 ASSERT_TRUE(base::TouchFile(filename
, old_last_modified
, old_last_modified
));
1671 ASSERT_TRUE(base::GetFileInfo(filename
, &before_info
));
1672 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
1673 database_
->UpdateFinished(true);
1674 ASSERT_TRUE(base::GetFileInfo(filename
, &after_info
));
1675 EXPECT_EQ(before_info
.last_modified
, after_info
.last_modified
);
1678 // Test that a filter file is written out during update and read back
1680 TEST_F(SafeBrowsingDatabaseTest
, FilterFile
) {
1681 // Create a database with trivial example data and write it out.
1686 // Prime the database.
1687 std::vector
<SBListChunkRanges
> lists
;
1688 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
1690 InsertAddChunkHostPrefixUrl(&chunk
, 1, "www.evil.com/",
1691 "www.evil.com/malware.html");
1693 chunks
.push_back(chunk
);
1694 database_
->InsertChunks(safe_browsing_util::kMalwareList
, chunks
);
1695 database_
->UpdateFinished(true);
1698 // Find the malware url in the database, don't find a good url.
1699 const Time now
= Time::Now();
1700 std::vector
<SBFullHashResult
> full_hashes
;
1701 std::vector
<SBPrefix
> prefix_hits
;
1702 std::string matching_list
;
1703 EXPECT_TRUE(database_
->ContainsBrowseUrl(
1704 GURL("http://www.evil.com/malware.html"),
1705 &matching_list
, &prefix_hits
, &full_hashes
, now
));
1706 EXPECT_FALSE(database_
->ContainsBrowseUrl(
1707 GURL("http://www.good.com/goodware.html"),
1708 &matching_list
, &prefix_hits
, &full_hashes
, now
));
1710 base::FilePath filter_file
= database_
->PrefixSetForFilename(
1711 database_
->BrowseDBFilename(database_filename_
));
1713 // After re-creating the database, it should have a filter read from
1714 // a file, so it should find the same results.
1715 ASSERT_TRUE(base::PathExists(filter_file
));
1716 database_
.reset(new SafeBrowsingDatabaseNew
);
1717 database_
->Init(database_filename_
);
1718 EXPECT_TRUE(database_
->ContainsBrowseUrl(
1719 GURL("http://www.evil.com/malware.html"),
1720 &matching_list
, &prefix_hits
, &full_hashes
, now
));
1721 EXPECT_FALSE(database_
->ContainsBrowseUrl(
1722 GURL("http://www.good.com/goodware.html"),
1723 &matching_list
, &prefix_hits
, &full_hashes
, now
));
1725 // If there is no filter file, the database cannot find malware urls.
1726 base::DeleteFile(filter_file
, false);
1727 ASSERT_FALSE(base::PathExists(filter_file
));
1728 database_
.reset(new SafeBrowsingDatabaseNew
);
1729 database_
->Init(database_filename_
);
1730 EXPECT_FALSE(database_
->ContainsBrowseUrl(
1731 GURL("http://www.evil.com/malware.html"),
1732 &matching_list
, &prefix_hits
, &full_hashes
, now
));
1733 EXPECT_FALSE(database_
->ContainsBrowseUrl(
1734 GURL("http://www.good.com/goodware.html"),
1735 &matching_list
, &prefix_hits
, &full_hashes
, now
));
1738 TEST_F(SafeBrowsingDatabaseTest
, MalwareIpBlacklist
) {
1740 SafeBrowsingStoreFile
* browse_store
= new SafeBrowsingStoreFile();
1741 SafeBrowsingStoreFile
* ip_blacklist_store
= new SafeBrowsingStoreFile();
1742 database_
.reset(new SafeBrowsingDatabaseNew(browse_store
,
1748 ip_blacklist_store
));
1749 database_
->Init(database_filename_
);
1750 std::vector
<SBListChunkRanges
> lists
;
1751 EXPECT_TRUE(database_
->UpdateStarted(&lists
));
1753 // IPv4 prefix match for ::ffff:192.168.1.0/120.
1756 InsertAddChunkFullHash(&chunk
, 1, "::ffff:192.168.1.0", 120);
1757 chunks
.push_back(chunk
);
1758 database_
->InsertChunks(safe_browsing_util::kIPBlacklist
, chunks
);
1760 // IPv4 exact match for ::ffff:192.1.1.1.
1762 chunk
.hosts
.clear();
1763 InsertAddChunkFullHash(&chunk
, 2, "::ffff:192.1.1.1", 128);
1764 chunks
.push_back(chunk
);
1765 database_
->InsertChunks(safe_browsing_util::kIPBlacklist
, chunks
);
1767 // IPv6 exact match for: fe80::31a:a0ff:fe10:786e/128.
1769 chunk
.hosts
.clear();
1770 InsertAddChunkFullHash(&chunk
, 3, "fe80::31a:a0ff:fe10:786e", 128);
1771 chunks
.push_back(chunk
);
1772 database_
->InsertChunks(safe_browsing_util::kIPBlacklist
, chunks
);
1774 // IPv6 prefix match for: 2620:0:1000:3103::/64.
1776 chunk
.hosts
.clear();
1777 InsertAddChunkFullHash(&chunk
, 4, "2620:0:1000:3103::", 64);
1778 chunks
.push_back(chunk
);
1779 database_
->InsertChunks(safe_browsing_util::kIPBlacklist
, chunks
);
1781 // IPv4 prefix match for ::ffff:192.1.122.0/119.
1783 chunk
.hosts
.clear();
1784 InsertAddChunkFullHash(&chunk
, 5, "::ffff:192.1.122.0", 119);
1785 chunks
.push_back(chunk
);
1786 database_
->InsertChunks(safe_browsing_util::kIPBlacklist
, chunks
);
1788 // IPv4 prefix match for ::ffff:192.1.128.0/113.
1790 chunk
.hosts
.clear();
1791 InsertAddChunkFullHash(&chunk
, 6, "::ffff:192.1.128.0", 113);
1792 chunks
.push_back(chunk
);
1793 database_
->InsertChunks(safe_browsing_util::kIPBlacklist
, chunks
);
1795 database_
->UpdateFinished(true);
1797 EXPECT_FALSE(database_
->ContainsMalwareIP("192.168.0.255"));
1798 EXPECT_TRUE(database_
->ContainsMalwareIP("192.168.1.0"));
1799 EXPECT_TRUE(database_
->ContainsMalwareIP("192.168.1.255"));
1800 EXPECT_TRUE(database_
->ContainsMalwareIP("192.168.1.10"));
1801 EXPECT_TRUE(database_
->ContainsMalwareIP("::ffff:192.168.1.2"));
1802 EXPECT_FALSE(database_
->ContainsMalwareIP("192.168.2.0"));
1804 EXPECT_FALSE(database_
->ContainsMalwareIP("192.1.1.0"));
1805 EXPECT_TRUE(database_
->ContainsMalwareIP("192.1.1.1"));
1806 EXPECT_FALSE(database_
->ContainsMalwareIP("192.1.1.2"));
1808 EXPECT_FALSE(database_
->ContainsMalwareIP(
1809 "2620:0:1000:3102:ffff:ffff:ffff:ffff"));
1810 EXPECT_TRUE(database_
->ContainsMalwareIP("2620:0:1000:3103::"));
1811 EXPECT_TRUE(database_
->ContainsMalwareIP(
1812 "2620:0:1000:3103:ffff:ffff:ffff:ffff"));
1813 EXPECT_FALSE(database_
->ContainsMalwareIP("2620:0:1000:3104::"));
1815 EXPECT_FALSE(database_
->ContainsMalwareIP("fe80::21a:a0ff:fe10:786d"));
1816 EXPECT_TRUE(database_
->ContainsMalwareIP("fe80::31a:a0ff:fe10:786e"));
1817 EXPECT_FALSE(database_
->ContainsMalwareIP("fe80::21a:a0ff:fe10:786f"));
1819 EXPECT_FALSE(database_
->ContainsMalwareIP("192.1.121.255"));
1820 EXPECT_TRUE(database_
->ContainsMalwareIP("192.1.122.0"));
1821 EXPECT_TRUE(database_
->ContainsMalwareIP("::ffff:192.1.122.1"));
1822 EXPECT_TRUE(database_
->ContainsMalwareIP("192.1.122.255"));
1823 EXPECT_TRUE(database_
->ContainsMalwareIP("192.1.123.0"));
1824 EXPECT_TRUE(database_
->ContainsMalwareIP("192.1.123.255"));
1825 EXPECT_FALSE(database_
->ContainsMalwareIP("192.1.124.0"));
1827 EXPECT_FALSE(database_
->ContainsMalwareIP("192.1.127.255"));
1828 EXPECT_TRUE(database_
->ContainsMalwareIP("192.1.128.0"));
1829 EXPECT_TRUE(database_
->ContainsMalwareIP("::ffff:192.1.128.1"));
1830 EXPECT_TRUE(database_
->ContainsMalwareIP("192.1.128.255"));
1831 EXPECT_TRUE(database_
->ContainsMalwareIP("192.1.255.0"));
1832 EXPECT_TRUE(database_
->ContainsMalwareIP("192.1.255.255"));
1833 EXPECT_FALSE(database_
->ContainsMalwareIP("192.2.0.0"));