#include "base/file_util.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/scoped_temp_dir.h"
#include "base/time.h"
#include "chrome/browser/safe_browsing/bloom_filter.h"
#include "chrome/browser/safe_browsing/safe_browsing_database.h"
#include "chrome/browser/safe_browsing/safe_browsing_store_file.h"
#include "chrome/browser/safe_browsing/safe_browsing_store_unittest_helper.h"
#include "content/public/test/test_browser_thread.h"
#include "crypto/sha2.h"
#include "googleurl/src/gurl.h"
#include "sql/connection.h"
#include "sql/statement.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
using base::Time;
using content::BrowserThread;
namespace {
SBPrefix Sha256Prefix(const std::string& str) {
SBPrefix prefix;
crypto::SHA256HashString(str, &prefix, sizeof(prefix));
return prefix;
}
SBFullHash Sha256Hash(const std::string& str) {
SBFullHash hash;
crypto::SHA256HashString(str, &hash, sizeof(hash));
return hash;
}
void InsertAddChunkHostPrefixValue(SBChunk* chunk,
int chunk_number,
const SBPrefix& host_prefix,
const SBPrefix& url_prefix) {
chunk->chunk_number = chunk_number;
chunk->is_add = true;
SBChunkHost host;
host.host = host_prefix;
host.entry = SBEntry::Create(SBEntry::ADD_PREFIX, 1);
host.entry->set_chunk_id(chunk->chunk_number);
host.entry->SetPrefixAt(0, url_prefix);
chunk->hosts.push_back(host);
}
void InsertAddChunkHostPrefixUrl(SBChunk* chunk,
int chunk_number,
const std::string& host_name,
const std::string& url) {
InsertAddChunkHostPrefixValue(chunk, chunk_number,
Sha256Prefix(host_name),
Sha256Prefix(url));
}
void InsertAddChunkHostFullHashes(SBChunk* chunk,
int chunk_number,
const std::string& host_name,
const std::string& url) {
chunk->chunk_number = chunk_number;
chunk->is_add = true;
SBChunkHost host;
host.host = Sha256Prefix(host_name);
host.entry = SBEntry::Create(SBEntry::ADD_FULL_HASH, 1);
host.entry->set_chunk_id(chunk->chunk_number);
host.entry->SetFullHashAt(0, Sha256Hash(url));
chunk->hosts.push_back(host);
}
void InsertAddChunkHost2PrefixUrls(SBChunk* chunk,
int chunk_number,
const std::string& host_name,
const std::string& url1,
const std::string& url2) {
chunk->chunk_number = chunk_number;
chunk->is_add = true;
SBChunkHost host;
host.host = Sha256Prefix(host_name);
host.entry = SBEntry::Create(SBEntry::ADD_PREFIX, 2);
host.entry->set_chunk_id(chunk->chunk_number);
host.entry->SetPrefixAt(0, Sha256Prefix(url1));
host.entry->SetPrefixAt(1, Sha256Prefix(url2));
chunk->hosts.push_back(host);
}
void InsertAddChunkHost2FullHashes(SBChunk* chunk,
int chunk_number,
const std::string& host_name,
const std::string& url1,
const std::string& url2) {
chunk->chunk_number = chunk_number;
chunk->is_add = true;
SBChunkHost host;
host.host = Sha256Prefix(host_name);
host.entry = SBEntry::Create(SBEntry::ADD_FULL_HASH, 2);
host.entry->set_chunk_id(chunk->chunk_number);
host.entry->SetFullHashAt(0, Sha256Hash(url1));
host.entry->SetFullHashAt(1, Sha256Hash(url2));
chunk->hosts.push_back(host);
}
void InsertSubChunkHostPrefixValue(SBChunk* chunk,
int chunk_number,
int chunk_id_to_sub,
const SBPrefix& host_prefix,
const SBPrefix& url_prefix) {
chunk->chunk_number = chunk_number;
chunk->is_add = false;
SBChunkHost host;
host.host = host_prefix;
host.entry = SBEntry::Create(SBEntry::SUB_PREFIX, 1);
host.entry->set_chunk_id(chunk->chunk_number);
host.entry->SetChunkIdAtPrefix(0, chunk_id_to_sub);
host.entry->SetPrefixAt(0, url_prefix);
chunk->hosts.push_back(host);
}
void InsertSubChunkHostPrefixUrl(SBChunk* chunk,
int chunk_number,
int chunk_id_to_sub,
const std::string& host_name,
const std::string& url) {
InsertSubChunkHostPrefixValue(chunk, chunk_number,
chunk_id_to_sub,
Sha256Prefix(host_name),
Sha256Prefix(url));
}
void InsertSubChunkHost2PrefixUrls(SBChunk* chunk,
int chunk_number,
int chunk_id_to_sub,
const std::string& host_name,
const std::string& url1,
const std::string& url2) {
chunk->chunk_number = chunk_number;
chunk->is_add = false;
SBChunkHost host;
host.host = Sha256Prefix(host_name);
host.entry = SBEntry::Create(SBEntry::SUB_PREFIX, 2);
host.entry->set_chunk_id(chunk->chunk_number);
host.entry->SetPrefixAt(0, Sha256Prefix(url1));
host.entry->SetChunkIdAtPrefix(0, chunk_id_to_sub);
host.entry->SetPrefixAt(1, Sha256Prefix(url2));
host.entry->SetChunkIdAtPrefix(1, chunk_id_to_sub);
chunk->hosts.push_back(host);
}
void InsertSubChunkHostFullHash(SBChunk* chunk,
int chunk_number,
int chunk_id_to_sub,
const std::string& host_name,
const std::string& url) {
chunk->chunk_number = chunk_number;
chunk->is_add = false;
SBChunkHost host;
host.host = Sha256Prefix(host_name);
host.entry = SBEntry::Create(SBEntry::SUB_FULL_HASH, 2);
host.entry->set_chunk_id(chunk->chunk_number);
host.entry->SetFullHashAt(0, Sha256Hash(url));
host.entry->SetChunkIdAtPrefix(0, chunk_id_to_sub);
chunk->hosts.push_back(host);
}
class ScopedLogMessageIgnorer {
public:
ScopedLogMessageIgnorer() {
logging::SetLogMessageHandler(&LogMessageIgnorer);
}
~ScopedLogMessageIgnorer() {
logging::SetLogMessageHandler(NULL);
}
private:
static bool LogMessageIgnorer(int severity, const char* file, int line,
size_t message_start, const std::string& str) {
if (severity == logging::LOG_FATAL) {
size_t newline = str.find('\n');
if (newline != std::string::npos) {
const std::string msg = str.substr(0, newline + 1);
fprintf(stderr, "%s", msg.c_str());
fflush(stderr);
}
return true;
}
return false;
}
};
}
class SafeBrowsingDatabaseTest : public PlatformTest {
public:
virtual void SetUp() {
PlatformTest::SetUp();
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
database_.reset(new SafeBrowsingDatabaseNew);
database_filename_ =
temp_dir_.path().AppendASCII("SafeBrowsingTestDatabase");
database_->Init(database_filename_);
}
virtual void TearDown() {
database_.reset();
PlatformTest::TearDown();
}
void GetListsInfo(std::vector<SBListChunkRanges>* lists) {
lists->clear();
EXPECT_TRUE(database_->UpdateStarted(lists));
database_->UpdateFinished(true);
}
void DelChunk(const std::string& list,
int chunk_id,
bool is_sub_del) {
std::vector<SBChunkDelete> deletes;
SBChunkDelete chunk_delete;
chunk_delete.list_name = list;
chunk_delete.is_sub_del = is_sub_del;
chunk_delete.chunk_del.push_back(ChunkRange(chunk_id));
deletes.push_back(chunk_delete);
database_->DeleteChunks(deletes);
}
void AddDelChunk(const std::string& list, int chunk_id) {
DelChunk(list, chunk_id, false);
}
void SubDelChunk(const std::string& list, int chunk_id) {
DelChunk(list, chunk_id, true);
}
void PopulateDatabaseForCacheTest();
scoped_ptr<SafeBrowsingDatabaseNew> database_;
FilePath database_filename_;
ScopedTempDir temp_dir_;
};
TEST_F(SafeBrowsingDatabaseTest, ListNameForBrowse) {
SBChunkList chunks;
SBChunk chunk;
InsertAddChunkHostPrefixUrl(&chunk, 1, "www.evil.com/",
"www.evil.com/malware.html");
chunks.clear();
chunks.push_back(chunk);
std::vector<SBListChunkRanges> lists;
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
chunk.hosts.clear();
InsertAddChunkHostPrefixUrl(&chunk, 2, "www.foo.com/",
"www.foo.com/malware.html");
chunks.clear();
chunks.push_back(chunk);
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
chunk.hosts.clear();
InsertAddChunkHostPrefixUrl(&chunk, 3, "www.whatever.com/",
"www.whatever.com/malware.html");
chunks.clear();
chunks.push_back(chunk);
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
database_->UpdateFinished(true);
GetListsInfo(&lists);
EXPECT_TRUE(lists[0].name == safe_browsing_util::kMalwareList);
EXPECT_EQ(lists[0].adds, "1-3");
EXPECT_TRUE(lists[0].subs.empty());
chunk.hosts.clear();
InsertSubChunkHostPrefixUrl(&chunk, 7, 19, "www.subbed.com/",
"www.subbed.com/noteveil1.html");
chunks.clear();
chunks.push_back(chunk);
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
database_->UpdateFinished(true);
GetListsInfo(&lists);
EXPECT_TRUE(lists[0].name == safe_browsing_util::kMalwareList);
EXPECT_EQ(lists[0].adds, "1-3");
EXPECT_EQ(lists[0].subs, "7");
if (lists.size() == 2) {
EXPECT_TRUE(lists[1].name == safe_browsing_util::kPhishingList);
EXPECT_TRUE(lists[1].adds.empty());
EXPECT_TRUE(lists[1].subs.empty());
}
chunk.hosts.clear();
InsertAddChunkHostPrefixUrl(&chunk, 47, "www.evil.com/",
"www.evil.com/phishing.html");
chunks.clear();
chunks.push_back(chunk);
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kPhishingList, chunks);
chunk.hosts.clear();
InsertSubChunkHostPrefixUrl(&chunk, 200, 1999, "www.phishy.com/",
"www.phishy.com/notevil1.html");
chunks.clear();
chunks.push_back(chunk);
database_->InsertChunks(safe_browsing_util::kPhishingList, chunks);
chunk.hosts.clear();
InsertSubChunkHostPrefixUrl(&chunk, 201, 1999, "www.phishy2.com/",
"www.phishy2.com/notevil1.html");
chunks.clear();
chunks.push_back(chunk);
database_->InsertChunks(safe_browsing_util::kPhishingList, chunks);
database_->UpdateFinished(true);
GetListsInfo(&lists);
EXPECT_TRUE(lists[0].name == safe_browsing_util::kMalwareList);
EXPECT_EQ(lists[0].adds, "1-3");
EXPECT_EQ(lists[0].subs, "7");
EXPECT_TRUE(lists[1].name == safe_browsing_util::kPhishingList);
EXPECT_EQ(lists[1].adds, "47");
EXPECT_EQ(lists[1].subs, "200-201");
}
TEST_F(SafeBrowsingDatabaseTest, ListNameForBrowseAndDownload) {
database_.reset();
MessageLoop loop(MessageLoop::TYPE_DEFAULT);
SafeBrowsingStoreFile* browse_store = new SafeBrowsingStoreFile();
SafeBrowsingStoreFile* download_store = new SafeBrowsingStoreFile();
SafeBrowsingStoreFile* csd_whitelist_store = new SafeBrowsingStoreFile();
SafeBrowsingStoreFile* download_whitelist_store = new SafeBrowsingStoreFile();
database_.reset(new SafeBrowsingDatabaseNew(browse_store,
download_store,
csd_whitelist_store,
download_whitelist_store));
database_->Init(database_filename_);
SBChunkList chunks;
SBChunk chunk;
InsertAddChunkHostPrefixUrl(&chunk, 1, "www.evil.com/",
"www.evil.com/malware.html");
chunks.push_back(chunk);
std::vector<SBListChunkRanges> lists;
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
chunk.hosts.clear();
InsertAddChunkHostPrefixUrl(&chunk, 2, "www.foo.com/",
"www.foo.com/malware.html");
chunks.clear();
chunks.push_back(chunk);
database_->InsertChunks(safe_browsing_util::kPhishingList, chunks);
chunk.hosts.clear();
InsertAddChunkHostPrefixUrl(&chunk, 3, "www.whatever.com/",
"www.whatever.com/download.html");
chunks.clear();
chunks.push_back(chunk);
database_->InsertChunks(safe_browsing_util::kBinUrlList, chunks);
chunk.hosts.clear();
InsertAddChunkHostPrefixUrl(&chunk, 4, "www.forhash.com/",
"www.forhash.com/download.html");
chunks.clear();
chunks.push_back(chunk);
database_->InsertChunks(safe_browsing_util::kBinHashList, chunks);
chunk.hosts.clear();
InsertAddChunkHostFullHashes(&chunk, 5, "www.forwhitelist.com/",
"www.forwhitelist.com/a.html");
chunks.clear();
chunks.push_back(chunk);
database_->InsertChunks(safe_browsing_util::kCsdWhiteList, chunks);
chunk.hosts.clear();
InsertAddChunkHostFullHashes(&chunk, 6, "www.download.com/",
"www.download.com/");
chunks.clear();
chunks.push_back(chunk);
database_->InsertChunks(safe_browsing_util::kDownloadWhiteList, chunks);
database_->UpdateFinished(true);
GetListsInfo(&lists);
ASSERT_EQ(5U, lists.size());
EXPECT_TRUE(lists[0].name == safe_browsing_util::kMalwareList);
EXPECT_EQ(lists[0].adds, "1");
EXPECT_TRUE(lists[0].subs.empty());
EXPECT_TRUE(lists[1].name == safe_browsing_util::kPhishingList);
EXPECT_EQ(lists[1].adds, "2");
EXPECT_TRUE(lists[1].subs.empty());
EXPECT_TRUE(lists[2].name == safe_browsing_util::kBinUrlList);
EXPECT_EQ(lists[2].adds, "3");
EXPECT_TRUE(lists[2].subs.empty());
EXPECT_TRUE(lists[3].name == safe_browsing_util::kCsdWhiteList);
EXPECT_EQ(lists[3].adds, "5");
EXPECT_TRUE(lists[3].subs.empty());
EXPECT_TRUE(lists[4].name == safe_browsing_util::kDownloadWhiteList);
EXPECT_EQ(lists[4].adds, "6");
EXPECT_TRUE(lists[4].subs.empty());
database_.reset();
}
TEST_F(SafeBrowsingDatabaseTest, BrowseDatabase) {
SBChunkList chunks;
SBChunk chunk;
InsertAddChunkHost2PrefixUrls(&chunk, 1, "www.evil.com/",
"www.evil.com/phishing.html",
"www.evil.com/malware.html");
chunks.push_back(chunk);
std::vector<SBListChunkRanges> lists;
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
chunk.hosts.clear();
InsertAddChunkHost2PrefixUrls(&chunk, 2, "www.evil.com/",
"www.evil.com/notevil1.html",
"www.evil.com/notevil2.html");
InsertAddChunkHost2PrefixUrls(&chunk, 2, "www.good.com/",
"www.good.com/good1.html",
"www.good.com/good2.html");
chunks.clear();
chunks.push_back(chunk);
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
chunk.hosts.clear();
InsertAddChunkHostPrefixUrl(&chunk, 3, "192.168.0.1/",
"192.168.0.1/malware.html");
chunks.clear();
chunks.push_back(chunk);
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
database_->UpdateFinished(true);
GetListsInfo(&lists);
EXPECT_TRUE(lists[0].name == safe_browsing_util::kMalwareList);
EXPECT_EQ(lists[0].adds, "1-3");
EXPECT_TRUE(lists[0].subs.empty());
const Time now = Time::Now();
std::vector<SBFullHashResult> full_hashes;
std::vector<SBPrefix> prefix_hits;
std::string matching_list;
EXPECT_TRUE(database_->ContainsBrowseUrl(
GURL("http://www.evil.com/phishing.html"),
&matching_list, &prefix_hits,
&full_hashes, now));
EXPECT_EQ(prefix_hits[0], Sha256Prefix("www.evil.com/phishing.html"));
EXPECT_EQ(prefix_hits.size(), 1U);
EXPECT_TRUE(database_->ContainsBrowseUrl(
GURL("http://www.evil.com/malware.html"),
&matching_list, &prefix_hits,
&full_hashes, now));
EXPECT_TRUE(database_->ContainsBrowseUrl(
GURL("http://www.evil.com/notevil1.html"),
&matching_list, &prefix_hits,
&full_hashes, now));
EXPECT_TRUE(database_->ContainsBrowseUrl(
GURL("http://www.evil.com/notevil2.html"),
&matching_list, &prefix_hits,
&full_hashes, now));
EXPECT_TRUE(database_->ContainsBrowseUrl(
GURL("http://www.good.com/good1.html"),
&matching_list, &prefix_hits,
&full_hashes, now));
EXPECT_TRUE(database_->ContainsBrowseUrl(
GURL("http://www.good.com/good2.html"),
&matching_list, &prefix_hits,
&full_hashes, now));
EXPECT_TRUE(database_->ContainsBrowseUrl(
GURL("http://192.168.0.1/malware.html"),
&matching_list, &prefix_hits,
&full_hashes, now));
EXPECT_FALSE(database_->ContainsBrowseUrl(
GURL("http://www.evil.com/"),
&matching_list, &prefix_hits,
&full_hashes, now));
EXPECT_TRUE(prefix_hits.empty());
EXPECT_FALSE(database_->ContainsBrowseUrl(
GURL("http://www.evil.com/robots.txt"),
&matching_list, &prefix_hits,
&full_hashes, now));
chunk.hosts.clear();
InsertAddChunkHost2PrefixUrls(&chunk, 1, "www.evil.com/",
"www.evil.com/phishing.html",
"www.evil.com/malware.html");
chunks.clear();
chunks.push_back(chunk);
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
database_->UpdateFinished(true);
GetListsInfo(&lists);
EXPECT_TRUE(lists[0].name == safe_browsing_util::kMalwareList);
EXPECT_EQ(lists[0].adds, "1-3");
EXPECT_TRUE(lists[0].subs.empty());
chunk.hosts.clear();
InsertSubChunkHostPrefixUrl(&chunk, 4, 2, "www.evil.com/",
"www.evil.com/notevil1.html");
chunks.clear();
chunks.push_back(chunk);
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
database_->UpdateFinished(true);
EXPECT_TRUE(database_->ContainsBrowseUrl(
GURL("http://www.evil.com/phishing.html"),
&matching_list, &prefix_hits,
&full_hashes, now));
EXPECT_EQ(prefix_hits[0], Sha256Prefix("www.evil.com/phishing.html"));
EXPECT_EQ(prefix_hits.size(), 1U);
EXPECT_FALSE(database_->ContainsBrowseUrl(
GURL("http://www.evil.com/notevil1.html"),
&matching_list, &prefix_hits,
&full_hashes, now));
EXPECT_TRUE(prefix_hits.empty());
EXPECT_TRUE(database_->ContainsBrowseUrl(
GURL("http://www.evil.com/notevil2.html"),
&matching_list, &prefix_hits,
&full_hashes, now));
EXPECT_TRUE(database_->ContainsBrowseUrl(
GURL("http://www.good.com/good1.html"),
&matching_list, &prefix_hits,
&full_hashes, now));
EXPECT_TRUE(database_->ContainsBrowseUrl(
GURL("http://www.good.com/good2.html"),
&matching_list, &prefix_hits,
&full_hashes, now));
GetListsInfo(&lists);
EXPECT_TRUE(lists[0].name == safe_browsing_util::kMalwareList);
EXPECT_EQ(lists[0].subs, "4");
chunk.hosts.clear();
InsertSubChunkHostPrefixUrl(&chunk, 4, 2, "www.evil.com/",
"www.evil.com/notevil1.html");
chunks.clear();
chunks.push_back(chunk);
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
database_->UpdateFinished(true);
GetListsInfo(&lists);
EXPECT_TRUE(lists[0].name == safe_browsing_util::kMalwareList);
EXPECT_EQ(lists[0].subs, "4");
EXPECT_TRUE(database_->UpdateStarted(&lists));
AddDelChunk(safe_browsing_util::kMalwareList, 2);
database_->UpdateFinished(true);
EXPECT_FALSE(database_->ContainsBrowseUrl(
GURL("http://www.evil.com/notevil2.html"),
&matching_list, &prefix_hits,
&full_hashes, now));
EXPECT_FALSE(database_->ContainsBrowseUrl(
GURL("http://www.good.com/good1.html"),
&matching_list, &prefix_hits,
&full_hashes, now));
EXPECT_FALSE(database_->ContainsBrowseUrl(
GURL("http://www.good.com/good2.html"),
&matching_list, &prefix_hits,
&full_hashes, now));
GetListsInfo(&lists);
EXPECT_TRUE(lists[0].name == safe_browsing_util::kMalwareList);
EXPECT_EQ(lists[0].adds, "1,3");
EXPECT_EQ(lists[0].subs, "4");
chunk.hosts.clear();
InsertAddChunkHostPrefixUrl(&chunk, 44, "www.redherring.com/",
"www.redherring.com/index.html");
chunks.clear();
chunks.push_back(chunk);
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
AddDelChunk(safe_browsing_util::kMalwareList, 44);
SubDelChunk(safe_browsing_util::kMalwareList, 4);
database_->UpdateFinished(true);
GetListsInfo(&lists);
EXPECT_TRUE(lists[0].name == safe_browsing_util::kMalwareList);
EXPECT_EQ(lists[0].adds, "1,3");
EXPECT_EQ(lists[0].subs, "");
chunk.hosts.clear();
InsertSubChunkHost2PrefixUrls(&chunk, 5, 10,
"www.notevilanymore.com/",
"www.notevilanymore.com/index.html",
"www.notevilanymore.com/good.html");
chunks.clear();
chunks.push_back(chunk);
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
database_->UpdateFinished(true);
EXPECT_FALSE(database_->ContainsBrowseUrl(
GURL("http://www.notevilanymore.com/index.html"),
&matching_list, &prefix_hits, &full_hashes, now));
chunk.hosts.clear();
InsertAddChunkHost2PrefixUrls(&chunk, 10, "www.notevilanymore.com/",
"www.notevilanymore.com/index.html",
"www.notevilanymore.com/good.html");
chunks.clear();
chunks.push_back(chunk);
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
database_->UpdateFinished(true);
EXPECT_FALSE(database_->ContainsBrowseUrl(
GURL("http://www.notevilanymore.com/index.html"),
&matching_list, &prefix_hits, &full_hashes, now));
EXPECT_FALSE(database_->ContainsBrowseUrl(
GURL("http://www.notevilanymore.com/good.html"),
&matching_list, &prefix_hits, &full_hashes, now));
}
TEST_F(SafeBrowsingDatabaseTest, ZeroSizeChunk) {
SBChunkList chunks;
SBChunk chunk;
InsertAddChunkHost2PrefixUrls(&chunk, 1, "www.test.com/",
"www.test.com/test1.html",
"www.test.com/test2.html");
chunks.clear();
chunks.push_back(chunk);
chunk.hosts.clear();
InsertAddChunkHost2PrefixUrls(&chunk, 10, "www.random.com/",
"www.random.com/random1.html",
"www.random.com/random2.html");
chunks.push_back(chunk);
std::vector<SBListChunkRanges> lists;
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
database_->UpdateFinished(true);
GetListsInfo(&lists);
EXPECT_EQ(lists[0].adds, "1,10");
SBChunk empty_chunk;
empty_chunk.chunk_number = 19;
empty_chunk.is_add = true;
chunks.clear();
chunks.push_back(empty_chunk);
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
chunks.clear();
empty_chunk.chunk_number = 7;
empty_chunk.is_add = false;
chunks.push_back(empty_chunk);
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
database_->UpdateFinished(true);
GetListsInfo(&lists);
EXPECT_EQ(lists[0].adds, "1,10,19");
EXPECT_EQ(lists[0].subs, "7");
empty_chunk.hosts.clear();
InsertAddChunkHostPrefixUrl(&empty_chunk, 20, "www.notempy.com/",
"www.notempty.com/full1.html");
chunks.clear();
chunks.push_back(empty_chunk);
empty_chunk.chunk_number = 21;
empty_chunk.is_add = true;
empty_chunk.hosts.clear();
chunks.push_back(empty_chunk);
empty_chunk.hosts.clear();
InsertAddChunkHostPrefixUrl(&empty_chunk, 22, "www.notempy.com/",
"www.notempty.com/full2.html");
chunks.push_back(empty_chunk);
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
database_->UpdateFinished(true);
const Time now = Time::Now();
std::vector<SBFullHashResult> full_hashes;
std::vector<SBPrefix> prefix_hits;
std::string matching_list;
EXPECT_TRUE(database_->ContainsBrowseUrl(
GURL("http://www.notempty.com/full1.html"),
&matching_list, &prefix_hits,
&full_hashes, now));
EXPECT_TRUE(database_->ContainsBrowseUrl(
GURL("http://www.notempty.com/full2.html"),
&matching_list, &prefix_hits,
&full_hashes, now));
GetListsInfo(&lists);
EXPECT_EQ(lists[0].adds, "1,10,19-22");
EXPECT_EQ(lists[0].subs, "7");
EXPECT_TRUE(database_->UpdateStarted(&lists));
AddDelChunk(safe_browsing_util::kMalwareList, 21);
database_->UpdateFinished(true);
GetListsInfo(&lists);
EXPECT_EQ(lists[0].adds, "1,10,19-20,22");
EXPECT_EQ(lists[0].subs, "7");
EXPECT_TRUE(database_->UpdateStarted(&lists));
SubDelChunk(safe_browsing_util::kMalwareList, 7);
database_->UpdateFinished(true);
GetListsInfo(&lists);
EXPECT_EQ(lists[0].adds, "1,10,19-20,22");
EXPECT_EQ(lists[0].subs, "");
}
void SafeBrowsingDatabaseTest::PopulateDatabaseForCacheTest() {
SBChunkList chunks;
SBChunk chunk;
InsertAddChunkHost2PrefixUrls(&chunk, 1, "www.evil.com/",
"www.evil.com/phishing.html",
"www.evil.com/malware.html");
chunks.push_back(chunk);
std::vector<SBListChunkRanges> lists;
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
database_->UpdateFinished(true);
SBFullHashResult full_hash;
full_hash.hash = Sha256Hash("www.evil.com/phishing.html");
full_hash.list_name = safe_browsing_util::kMalwareList;
full_hash.add_chunk_id = 1;
std::vector<SBFullHashResult> results;
results.push_back(full_hash);
full_hash.hash = Sha256Hash("www.evil.com/malware.html");
results.push_back(full_hash);
std::vector<SBPrefix> prefixes;
database_->CacheHashResults(prefixes, results);
}
TEST_F(SafeBrowsingDatabaseTest, HashCaching) {
PopulateDatabaseForCacheTest();
EXPECT_EQ(database_->pending_browse_hashes_.size(), 2U);
std::string listname;
std::vector<SBPrefix> prefixes;
std::vector<SBFullHashResult> full_hashes;
database_->ContainsBrowseUrl(
GURL("http://www.evil.com/phishing.html"),
&listname, &prefixes, &full_hashes, Time::Now());
EXPECT_EQ(full_hashes.size(), 1U);
EXPECT_TRUE(SBFullHashEq(full_hashes[0].hash,
Sha256Hash("www.evil.com/phishing.html")));
prefixes.clear();
full_hashes.clear();
database_->ContainsBrowseUrl(
GURL("http://www.evil.com/malware.html"),
&listname, &prefixes, &full_hashes, Time::Now());
EXPECT_EQ(full_hashes.size(), 1U);
EXPECT_TRUE(SBFullHashEq(full_hashes[0].hash,
Sha256Hash("www.evil.com/malware.html")));
prefixes.clear();
full_hashes.clear();
SBChunk chunk;
SBChunkList chunks;
InsertSubChunkHostPrefixUrl(&chunk, 2, 1, "www.evil.com/",
"www.evil.com/phishing.html");
chunks.push_back(chunk);
std::vector<SBListChunkRanges> lists;
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
database_->UpdateFinished(true);
database_->ContainsBrowseUrl(
GURL("http://www.evil.com/malware.html"),
&listname, &prefixes, &full_hashes, Time::Now());
EXPECT_EQ(full_hashes.size(), 1U);
EXPECT_TRUE(SBFullHashEq(full_hashes[0].hash,
Sha256Hash("www.evil.com/malware.html")));
prefixes.clear();
full_hashes.clear();
database_->ContainsBrowseUrl(
GURL("http://www.evil.com/phishing.html"),
&listname, &prefixes, &full_hashes, Time::Now());
EXPECT_TRUE(full_hashes.empty());
prefixes.clear();
full_hashes.clear();
EXPECT_TRUE(database_->UpdateStarted(&lists));
AddDelChunk(safe_browsing_util::kMalwareList, 1);
database_->UpdateFinished(true);
database_->ContainsBrowseUrl(
GURL("http://www.evil.com/malware.html"),
&listname, &prefixes, &full_hashes, Time::Now());
EXPECT_TRUE(full_hashes.empty());
EXPECT_TRUE(database_->full_browse_hashes_.empty());
EXPECT_TRUE(database_->pending_browse_hashes_.empty());
prefixes.clear();
full_hashes.clear();
PopulateDatabaseForCacheTest();
std::vector<SBAddFullHash>* hash_cache = &database_->pending_browse_hashes_;
EXPECT_EQ(hash_cache->size(), 2U);
base::Time expired = base::Time::Now() - base::TimeDelta::FromMinutes(60);
const SBPrefix key = Sha256Prefix("www.evil.com/malware.html");
std::vector<SBAddFullHash>::iterator iter;
for (iter = hash_cache->begin(); iter != hash_cache->end(); ++iter) {
if (iter->full_hash.prefix == key) {
iter->received = static_cast<int32>(expired.ToTimeT());
break;
}
}
EXPECT_TRUE(iter != hash_cache->end());
database_->ContainsBrowseUrl(
GURL("http://www.evil.com/malware.html"),
&listname, &prefixes, &full_hashes, expired);
EXPECT_TRUE(full_hashes.empty());
database_->ContainsBrowseUrl(
GURL("http://www.evil.com/phishing.html"),
&listname, &prefixes, &full_hashes, expired);
EXPECT_EQ(full_hashes.size(), 1U);
EXPECT_TRUE(database_->UpdateStarted(&lists));
AddDelChunk(safe_browsing_util::kMalwareList, 1);
database_->UpdateFinished(true);
std::vector<SBPrefix> prefix_misses;
std::vector<SBFullHashResult> empty_full_hash;
prefix_misses.push_back(Sha256Prefix("http://www.bad.com/malware.html"));
prefix_misses.push_back(Sha256Prefix("http://www.bad.com/phishing.html"));
database_->CacheHashResults(prefix_misses, empty_full_hash);
EXPECT_EQ(database_->prefix_miss_cache_.size(), 2U);
PopulateDatabaseForCacheTest();
EXPECT_TRUE(database_->prefix_miss_cache_.empty());
prefixes.clear();
full_hashes.clear();
prefix_misses.clear();
empty_full_hash.clear();
prefix_misses.push_back(Sha256Prefix("www.evil.com/phishing.html"));
database_->CacheHashResults(prefix_misses, empty_full_hash);
EXPECT_FALSE(database_->ContainsBrowseUrl(
GURL("http://www.evil.com/phishing.html"),
&listname, &prefixes,
&full_hashes, Time::Now()));
prefixes.clear();
full_hashes.clear();
chunk.hosts.clear();
InsertAddChunkHost2FullHashes(&chunk, 20, "www.fullevil.com/",
"www.fullevil.com/bad1.html",
"www.fullevil.com/bad2.html");
chunks.clear();
chunks.push_back(chunk);
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
database_->UpdateFinished(true);
EXPECT_TRUE(database_->ContainsBrowseUrl(
GURL("http://www.fullevil.com/bad1.html"),
&listname, &prefixes, &full_hashes,
Time::Now()));
EXPECT_EQ(full_hashes.size(), 1U);
EXPECT_TRUE(SBFullHashEq(full_hashes[0].hash,
Sha256Hash("www.fullevil.com/bad1.html")));
prefixes.clear();
full_hashes.clear();
EXPECT_TRUE(database_->ContainsBrowseUrl(
GURL("http://www.fullevil.com/bad2.html"),
&listname, &prefixes, &full_hashes,
Time::Now()));
EXPECT_EQ(full_hashes.size(), 1U);
EXPECT_TRUE(SBFullHashEq(full_hashes[0].hash,
Sha256Hash("www.fullevil.com/bad2.html")));
prefixes.clear();
full_hashes.clear();
chunk.hosts.clear();
InsertSubChunkHostFullHash(&chunk, 200, 20,
"www.fullevil.com/",
"www.fullevil.com/bad1.html");
chunks.clear();
chunks.push_back(chunk);
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
database_->UpdateFinished(true);
EXPECT_FALSE(database_->ContainsBrowseUrl(
GURL("http://www.fullevil.com/bad1.html"),
&listname, &prefixes, &full_hashes,
Time::Now()));
EXPECT_TRUE(full_hashes.empty());
EXPECT_TRUE(database_->ContainsBrowseUrl(
GURL("http://www.fullevil.com/bad2.html"),
&listname, &prefixes, &full_hashes,
Time::Now()));
EXPECT_EQ(full_hashes.size(), 1U);
EXPECT_TRUE(SBFullHashEq(full_hashes[0].hash,
Sha256Hash("www.fullevil.com/bad2.html")));
prefixes.clear();
full_hashes.clear();
EXPECT_TRUE(database_->UpdateStarted(&lists));
AddDelChunk(safe_browsing_util::kMalwareList, 20);
database_->UpdateFinished(true);
EXPECT_FALSE(database_->ContainsBrowseUrl(
GURL("http://www.fullevil.com/bad1.html"),
&listname, &prefixes, &full_hashes,
Time::Now()));
EXPECT_FALSE(database_->ContainsBrowseUrl(
GURL("http://www.fullevil.com/bad2.html"),
&listname, &prefixes, &full_hashes,
Time::Now()));
}
TEST_F(SafeBrowsingDatabaseTest, DISABLED_FileCorruptionHandling) {
database_.reset();
MessageLoop loop(MessageLoop::TYPE_DEFAULT);
SafeBrowsingStoreFile* store = new SafeBrowsingStoreFile();
database_.reset(new SafeBrowsingDatabaseNew(store, NULL, NULL, NULL));
database_->Init(database_filename_);
std::vector<SBListChunkRanges> lists;
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->UpdateFinished(true);
SBChunkList chunks;
SBChunk chunk;
SBChunkHost host;
host.host = Sha256Prefix("www.subbed.com/");
host.entry = SBEntry::Create(SBEntry::SUB_PREFIX, 1);
host.entry->set_chunk_id(7);
host.entry->SetChunkIdAtPrefix(0, 19);
host.entry->SetPrefixAt(0, Sha256Prefix("www.subbed.com/notevil1.html"));
chunk.chunk_number = 7;
chunk.is_add = false;
chunk.hosts.clear();
chunk.hosts.push_back(host);
chunks.clear();
chunks.push_back(chunk);
FILE* fp = file_util::OpenFile(database_filename_, "r+");
ASSERT_TRUE(fp);
ASSERT_NE(-1, fseek(fp, -8, SEEK_END));
for (size_t i = 0; i < 8; ++i) {
fputc('!', fp);
}
fclose(fp);
{
ScopedLogMessageIgnorer ignorer;
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
database_->UpdateFinished(true);
EXPECT_TRUE(file_util::PathExists(database_filename_));
VLOG(1) << "Expect failed check on: SafeBrowsing database reset";
MessageLoop::current()->RunAllPending();
}
EXPECT_FALSE(file_util::PathExists(database_filename_));
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
database_->UpdateFinished(true);
EXPECT_TRUE(file_util::PathExists(database_filename_));
database_.reset();
}
TEST_F(SafeBrowsingDatabaseTest, ContainsDownloadUrl) {
database_.reset();
MessageLoop loop(MessageLoop::TYPE_DEFAULT);
SafeBrowsingStoreFile* browse_store = new SafeBrowsingStoreFile();
SafeBrowsingStoreFile* download_store = new SafeBrowsingStoreFile();
SafeBrowsingStoreFile* csd_whitelist_store = new SafeBrowsingStoreFile();
database_.reset(new SafeBrowsingDatabaseNew(browse_store,
download_store,
csd_whitelist_store,
NULL));
database_->Init(database_filename_);
const char kEvil1Host[] = "www.evil1.com/";
const char kEvil1Url1[] = "www.evil1.com/download1/";
const char kEvil1Url2[] = "www.evil1.com/download2.html";
SBChunkList chunks;
SBChunk chunk;
InsertAddChunkHost2PrefixUrls(&chunk, 1, kEvil1Host,
kEvil1Url1, kEvil1Url2);
chunks.push_back(chunk);
std::vector<SBListChunkRanges> lists;
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kBinUrlList, chunks);
database_->UpdateFinished(true);
std::vector<SBPrefix> prefix_hits;
std::vector<GURL> urls(1);
urls[0] = GURL(std::string("http://") + kEvil1Url1);
EXPECT_TRUE(database_->ContainsDownloadUrl(urls, &prefix_hits));
ASSERT_EQ(prefix_hits.size(), 1U);
EXPECT_EQ(prefix_hits[0], Sha256Prefix(kEvil1Url1));
urls[0] = GURL(std::string("http://") + kEvil1Url2);
EXPECT_TRUE(database_->ContainsDownloadUrl(urls, &prefix_hits));
ASSERT_EQ(prefix_hits.size(), 1U);
EXPECT_EQ(prefix_hits[0], Sha256Prefix(kEvil1Url2));
urls[0] = GURL(std::string("https://") + kEvil1Url2);
EXPECT_TRUE(database_->ContainsDownloadUrl(urls, &prefix_hits));
ASSERT_EQ(prefix_hits.size(), 1U);
EXPECT_EQ(prefix_hits[0], Sha256Prefix(kEvil1Url2));
urls[0] = GURL(std::string("ftp://") + kEvil1Url2);
EXPECT_TRUE(database_->ContainsDownloadUrl(urls, &prefix_hits));
ASSERT_EQ(prefix_hits.size(), 1U);
EXPECT_EQ(prefix_hits[0], Sha256Prefix(kEvil1Url2));
urls[0] = GURL("http://www.randomevil.com");
EXPECT_FALSE(database_->ContainsDownloadUrl(urls, &prefix_hits));
urls[0] = GURL(std::string("http://") + kEvil1Url2 + "?blah");
EXPECT_TRUE(database_->ContainsDownloadUrl(urls, &prefix_hits));
ASSERT_EQ(prefix_hits.size(), 1U);
EXPECT_EQ(prefix_hits[0], Sha256Prefix(kEvil1Url2));
urls[0] = GURL(std::string("http://") + kEvil1Url1 + "foo/bar?blah");
EXPECT_TRUE(database_->ContainsDownloadUrl(urls, &prefix_hits));
ASSERT_EQ(prefix_hits.size(), 1U);
EXPECT_EQ(prefix_hits[0], Sha256Prefix(kEvil1Url1));
urls.clear();
urls.push_back(GURL(std::string("http://") + kEvil1Url1));
urls.push_back(GURL("http://www.randomevil.com"));
EXPECT_TRUE(database_->ContainsDownloadUrl(urls, &prefix_hits));
ASSERT_EQ(prefix_hits.size(), 1U);
EXPECT_EQ(prefix_hits[0], Sha256Prefix(kEvil1Url1));
urls.clear();
urls.push_back(GURL("http://www.randomevil.com"));
urls.push_back(GURL(std::string("http://") + kEvil1Url1));
urls.push_back(GURL("http://www.randomevil2.com"));
EXPECT_TRUE(database_->ContainsDownloadUrl(urls, &prefix_hits));
ASSERT_EQ(prefix_hits.size(), 1U);
EXPECT_EQ(prefix_hits[0], Sha256Prefix(kEvil1Url1));
urls.clear();
urls.push_back(GURL("http://www.randomevil.com"));
urls.push_back(GURL(std::string("http://") + kEvil1Url1));
EXPECT_TRUE(database_->ContainsDownloadUrl(urls, &prefix_hits));
ASSERT_EQ(prefix_hits.size(), 1U);
EXPECT_EQ(prefix_hits[0], Sha256Prefix(kEvil1Url1));
urls.clear();
urls.push_back(GURL(std::string("http://") + kEvil1Url1));
urls.push_back(GURL(std::string("https://") + kEvil1Url2));
EXPECT_TRUE(database_->ContainsDownloadUrl(urls, &prefix_hits));
ASSERT_EQ(prefix_hits.size(), 2U);
EXPECT_EQ(prefix_hits[0], Sha256Prefix(kEvil1Url1));
EXPECT_EQ(prefix_hits[1], Sha256Prefix(kEvil1Url2));
database_.reset();
}
TEST_F(SafeBrowsingDatabaseTest, Whitelists) {
database_.reset();
MessageLoop loop(MessageLoop::TYPE_DEFAULT);
content::TestBrowserThread io_thread(BrowserThread::IO, &loop);
database_.reset(new SafeBrowsingDatabaseNew(new SafeBrowsingStoreFile(),
NULL, NULL, NULL));
database_->Init(database_filename_);
EXPECT_TRUE(database_->ContainsDownloadWhitelistedUrl(
GURL(std::string("http://www.phishing.com/"))));
EXPECT_TRUE(database_->ContainsDownloadWhitelistedUrl(
GURL(std::string("http://www.phishing.com/"))));
EXPECT_TRUE(database_->ContainsDownloadWhitelistedString("asdf"));
SafeBrowsingStoreFile* browse_store = new SafeBrowsingStoreFile();
SafeBrowsingStoreFile* csd_whitelist_store = new SafeBrowsingStoreFile();
SafeBrowsingStoreFile* download_whitelist_store = new SafeBrowsingStoreFile();
database_.reset(new SafeBrowsingDatabaseNew(browse_store, NULL,
csd_whitelist_store,
download_whitelist_store));
database_->Init(database_filename_);
const char kGood1Host[] = "www.good1.com/";
const char kGood1Url1[] = "www.good1.com/a/b.html";
const char kGood1Url2[] = "www.good1.com/b/";
const char kGood2Host[] = "www.good2.com/";
const char kGood2Url1[] = "www.good2.com/c";
const char kGood3Host[] = "good3.com/";
const char kGood3Url1[] = "good3.com/";
const char kGoodString[] = "good_string";
SBChunkList download_chunks, csd_chunks;
SBChunk chunk;
InsertAddChunkHost2FullHashes(&chunk, 1, kGood1Host,
kGood1Url1, kGood1Url2);
csd_chunks.push_back(chunk);
chunk.hosts.clear();
InsertAddChunkHostFullHashes(&chunk, 2, kGood2Host, kGood2Url1);
csd_chunks.push_back(chunk);
chunk.hosts.clear();
InsertAddChunkHostFullHashes(&chunk, 2, kGood2Host, kGood2Url1);
download_chunks.push_back(chunk);
chunk.hosts.clear();
InsertAddChunkHostFullHashes(&chunk, 3, kGoodString, kGoodString);
download_chunks.push_back(chunk);
chunk.hosts.clear();
InsertAddChunkHostFullHashes(&chunk, 4, kGood3Host, kGood3Url1);
download_chunks.push_back(chunk);
std::vector<SBListChunkRanges> lists;
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kCsdWhiteList,
csd_chunks);
database_->InsertChunks(safe_browsing_util::kDownloadWhiteList,
download_chunks);
database_->UpdateFinished(true);
EXPECT_FALSE(database_->ContainsCsdWhitelistedUrl(
GURL(std::string("http://") + kGood1Host)));
EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
GURL(std::string("http://") + kGood1Url1)));
EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
GURL(std::string("http://") + kGood1Url1 + "?a=b")));
EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
GURL(std::string("http://") + kGood1Url2)));
EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
GURL(std::string("http://") + kGood1Url2 + "/c.html")));
EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
GURL(std::string("https://") + kGood1Url2 + "/c.html")));
EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
GURL(std::string("http://") + kGood2Url1 + "/c")));
EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
GURL(std::string("http://") + kGood2Url1 + "/c?bla")));
EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
GURL(std::string("http://") + kGood2Url1 + "/c/bla")));
EXPECT_FALSE(database_->ContainsCsdWhitelistedUrl(
GURL(std::string("http://www.google.com/"))));
EXPECT_TRUE(database_->ContainsDownloadWhitelistedUrl(
GURL(std::string("http://") + kGood2Url1 + "/c")));
EXPECT_TRUE(database_->ContainsDownloadWhitelistedUrl(
GURL(std::string("http://") + kGood2Url1 + "/c?bla")));
EXPECT_TRUE(database_->ContainsDownloadWhitelistedUrl(
GURL(std::string("http://") + kGood2Url1 + "/c/bla")));
EXPECT_TRUE(database_->ContainsDownloadWhitelistedUrl(
GURL(std::string("http://good3.com/a/b/c/d/e/f/g/"))));
EXPECT_TRUE(database_->ContainsDownloadWhitelistedUrl(
GURL(std::string("http://a.b.good3.com/"))));
EXPECT_FALSE(database_->ContainsDownloadWhitelistedString("asdf"));
EXPECT_TRUE(database_->ContainsDownloadWhitelistedString(kGoodString));
EXPECT_FALSE(database_->ContainsDownloadWhitelistedUrl(
GURL(std::string("http://www.google.com/"))));
csd_chunks.clear();
download_chunks.clear();
lists.clear();
chunk.hosts.clear();
InsertAddChunkHostFullHashes(&chunk, 5, "sb-ssl.google.com/",
"sb-ssl.google.com/safebrowsing/csd/killswitch");
csd_chunks.push_back(chunk);
chunk.hosts.clear();
InsertAddChunkHostFullHashes(&chunk, 5, "sb-ssl.google.com/",
"sb-ssl.google.com/safebrowsing/csd/killswitch");
download_chunks.push_back(chunk);
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kCsdWhiteList, csd_chunks);
database_->InsertChunks(safe_browsing_util::kDownloadWhiteList,
download_chunks);
database_->UpdateFinished(true);
EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
GURL(std::string("https://") + kGood1Url2 + "/c.html")));
EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
GURL(std::string("http://www.google.com/"))));
EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
GURL(std::string("http://www.phishing_url.com/"))));
EXPECT_TRUE(database_->ContainsDownloadWhitelistedUrl(
GURL(std::string("https://") + kGood1Url2 + "/c.html")));
EXPECT_TRUE(database_->ContainsDownloadWhitelistedUrl(
GURL(std::string("http://www.google.com/"))));
EXPECT_TRUE(database_->ContainsDownloadWhitelistedUrl(
GURL(std::string("http://www.phishing_url.com/"))));
EXPECT_TRUE(database_->ContainsDownloadWhitelistedString("asdf"));
EXPECT_TRUE(database_->ContainsDownloadWhitelistedString(kGoodString));
csd_chunks.clear();
download_chunks.clear();
lists.clear();
SBChunk sub_chunk;
InsertSubChunkHostFullHash(&sub_chunk, 1, 5,
"sb-ssl.google.com/",
"sb-ssl.google.com/safebrowsing/csd/killswitch");
csd_chunks.push_back(sub_chunk);
sub_chunk.hosts.clear();
InsertSubChunkHostFullHash(&sub_chunk, 1, 5,
"sb-ssl.google.com/",
"sb-ssl.google.com/safebrowsing/csd/killswitch");
download_chunks.push_back(sub_chunk);
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kCsdWhiteList, csd_chunks);
database_->InsertChunks(safe_browsing_util::kDownloadWhiteList,
download_chunks);
database_->UpdateFinished(true);
EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
GURL(std::string("https://") + kGood1Url2 + "/c.html")));
EXPECT_TRUE(database_->ContainsCsdWhitelistedUrl(
GURL(std::string("https://") + kGood2Url1 + "/c/bla")));
EXPECT_FALSE(database_->ContainsCsdWhitelistedUrl(
GURL(std::string("http://www.google.com/"))));
EXPECT_FALSE(database_->ContainsCsdWhitelistedUrl(
GURL(std::string("http://www.phishing_url.com/"))));
EXPECT_TRUE(database_->ContainsDownloadWhitelistedUrl(
GURL(std::string("https://") + kGood2Url1 + "/c/bla")));
EXPECT_TRUE(database_->ContainsDownloadWhitelistedUrl(
GURL(std::string("https://good3.com/"))));
EXPECT_TRUE(database_->ContainsDownloadWhitelistedString(kGoodString));
EXPECT_FALSE(database_->ContainsDownloadWhitelistedUrl(
GURL(std::string("http://www.google.com/"))));
EXPECT_FALSE(database_->ContainsDownloadWhitelistedUrl(
GURL(std::string("http://www.phishing_url.com/"))));
EXPECT_FALSE(database_->ContainsDownloadWhitelistedString("asdf"));
database_.reset();
}
TEST_F(SafeBrowsingDatabaseTest, SameHostEntriesOkay) {
SBChunk chunk;
InsertAddChunkHostPrefixUrl(&chunk, 1, "www.evil.com/",
"www.evil.com/malware1.html");
InsertAddChunkHostPrefixUrl(&chunk, 1, "www.evil.com/",
"www.evil.com/malware2.html");
SBChunkList chunks;
chunks.push_back(chunk);
std::vector<SBListChunkRanges> lists;
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
database_->UpdateFinished(true);
GetListsInfo(&lists);
EXPECT_EQ(std::string(safe_browsing_util::kMalwareList), lists[0].name);
EXPECT_EQ("1", lists[0].adds);
EXPECT_TRUE(lists[0].subs.empty());
chunk.hosts.clear();
InsertAddChunkHostPrefixUrl(&chunk, 47, "www.evil.com/",
"www.evil.com/phishing1.html");
InsertAddChunkHostPrefixUrl(&chunk, 47, "www.evil.com/",
"www.evil.com/phishing2.html");
chunks.clear();
chunks.push_back(chunk);
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kPhishingList, chunks);
database_->UpdateFinished(true);
GetListsInfo(&lists);
EXPECT_EQ(std::string(safe_browsing_util::kMalwareList), lists[0].name);
EXPECT_EQ("1", lists[0].adds);
EXPECT_EQ(std::string(safe_browsing_util::kPhishingList), lists[1].name);
EXPECT_EQ("47", lists[1].adds);
const Time now = Time::Now();
std::vector<SBPrefix> prefixes;
std::vector<SBFullHashResult> full_hashes;
std::vector<SBPrefix> prefix_hits;
std::string matching_list;
std::string listname;
EXPECT_TRUE(database_->ContainsBrowseUrl(
GURL("http://www.evil.com/malware1.html"),
&listname, &prefixes, &full_hashes, now));
EXPECT_TRUE(database_->ContainsBrowseUrl(
GURL("http://www.evil.com/malware2.html"),
&listname, &prefixes, &full_hashes, now));
EXPECT_TRUE(database_->ContainsBrowseUrl(
GURL("http://www.evil.com/phishing1.html"),
&listname, &prefixes, &full_hashes, now));
EXPECT_TRUE(database_->ContainsBrowseUrl(
GURL("http://www.evil.com/phishing2.html"),
&listname, &prefixes, &full_hashes, now));
chunk.hosts.clear();
InsertSubChunkHostPrefixUrl(&chunk, 4, 1, "www.evil.com/",
"www.evil.com/malware1.html");
chunks.clear();
chunks.push_back(chunk);
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
database_->UpdateFinished(true);
chunk.hosts.clear();
InsertSubChunkHostPrefixUrl(&chunk, 5, 47, "www.evil.com/",
"www.evil.com/phishing2.html");
chunks.clear();
chunks.push_back(chunk);
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->InsertChunks(safe_browsing_util::kPhishingList, chunks);
database_->UpdateFinished(true);
EXPECT_FALSE(database_->ContainsBrowseUrl(
GURL("http://www.evil.com/malware1.html"),
&listname, &prefixes, &full_hashes, now));
EXPECT_TRUE(database_->ContainsBrowseUrl(
GURL("http://www.evil.com/malware2.html"),
&listname, &prefixes, &full_hashes, now));
EXPECT_TRUE(database_->ContainsBrowseUrl(
GURL("http://www.evil.com/phishing1.html"),
&listname, &prefixes, &full_hashes, now));
EXPECT_FALSE(database_->ContainsBrowseUrl(
GURL("http://www.evil.com/phishing2.html"),
&listname, &prefixes, &full_hashes, now));
}
TEST_F(SafeBrowsingDatabaseTest, EmptyUpdate) {
SBChunkList chunks;
SBChunk chunk;
FilePath filename = database_->BrowseDBFilename(database_filename_);
std::vector<SBListChunkRanges> lists;
EXPECT_TRUE(database_->UpdateStarted(&lists));
InsertAddChunkHostPrefixUrl(&chunk, 1, "www.evil.com/",
"www.evil.com/malware.html");
chunks.clear();
chunks.push_back(chunk);
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
database_->UpdateFinished(true);
base::PlatformFileInfo before_info, after_info;
ASSERT_TRUE(file_util::GetFileInfo(filename, &before_info));
const base::Time old_last_modified =
before_info.last_modified - base::TimeDelta::FromSeconds(10);
ASSERT_TRUE(file_util::SetLastModifiedTime(filename, old_last_modified));
ASSERT_TRUE(file_util::GetFileInfo(filename, &before_info));
EXPECT_TRUE(database_->UpdateStarted(&lists));
chunk.hosts.clear();
InsertAddChunkHostPrefixUrl(&chunk, 2, "www.foo.com/",
"www.foo.com/malware.html");
chunks.clear();
chunks.push_back(chunk);
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
database_->UpdateFinished(true);
ASSERT_TRUE(file_util::GetFileInfo(filename, &after_info));
EXPECT_LT(before_info.last_modified, after_info.last_modified);
ASSERT_TRUE(file_util::SetLastModifiedTime(filename, old_last_modified));
ASSERT_TRUE(file_util::GetFileInfo(filename, &before_info));
EXPECT_TRUE(database_->UpdateStarted(&lists));
AddDelChunk(safe_browsing_util::kMalwareList, chunk.chunk_number);
database_->UpdateFinished(true);
ASSERT_TRUE(file_util::GetFileInfo(filename, &after_info));
EXPECT_LT(before_info.last_modified, after_info.last_modified);
ASSERT_TRUE(file_util::SetLastModifiedTime(filename, old_last_modified));
ASSERT_TRUE(file_util::GetFileInfo(filename, &before_info));
EXPECT_TRUE(database_->UpdateStarted(&lists));
database_->UpdateFinished(true);
ASSERT_TRUE(file_util::GetFileInfo(filename, &after_info));
EXPECT_EQ(before_info.last_modified, after_info.last_modified);
}
TEST_F(SafeBrowsingDatabaseTest, FilterFile) {
{
SBChunkList chunks;
SBChunk chunk;
std::vector<SBListChunkRanges> lists;
EXPECT_TRUE(database_->UpdateStarted(&lists));
InsertAddChunkHostPrefixUrl(&chunk, 1, "www.evil.com/",
"www.evil.com/malware.html");
chunks.clear();
chunks.push_back(chunk);
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
database_->UpdateFinished(true);
}
const Time now = Time::Now();
std::vector<SBFullHashResult> full_hashes;
std::vector<SBPrefix> prefix_hits;
std::string matching_list;
EXPECT_TRUE(database_->ContainsBrowseUrl(
GURL("http://www.evil.com/malware.html"),
&matching_list, &prefix_hits, &full_hashes, now));
EXPECT_FALSE(database_->ContainsBrowseUrl(
GURL("http://www.good.com/goodware.html"),
&matching_list, &prefix_hits, &full_hashes, now));
FilePath filter_file = database_->PrefixSetForFilename(
database_->BrowseDBFilename(database_filename_));
ASSERT_TRUE(file_util::PathExists(filter_file));
database_.reset(new SafeBrowsingDatabaseNew);
database_->Init(database_filename_);
EXPECT_TRUE(database_->ContainsBrowseUrl(
GURL("http://www.evil.com/malware.html"),
&matching_list, &prefix_hits, &full_hashes, now));
EXPECT_FALSE(database_->ContainsBrowseUrl(
GURL("http://www.good.com/goodware.html"),
&matching_list, &prefix_hits, &full_hashes, now));
file_util::Delete(filter_file, false);
ASSERT_FALSE(file_util::PathExists(filter_file));
database_.reset(new SafeBrowsingDatabaseNew);
database_->Init(database_filename_);
EXPECT_FALSE(database_->ContainsBrowseUrl(
GURL("http://www.evil.com/malware.html"),
&matching_list, &prefix_hits, &full_hashes, now));
EXPECT_FALSE(database_->ContainsBrowseUrl(
GURL("http://www.good.com/goodware.html"),
&matching_list, &prefix_hits, &full_hashes, now));
}
TEST_F(SafeBrowsingDatabaseTest, PrefixSetTransition) {
{
SBChunkList chunks;
SBChunk chunk;
std::vector<SBListChunkRanges> lists;
EXPECT_TRUE(database_->UpdateStarted(&lists));
InsertAddChunkHostPrefixUrl(&chunk, 1, "www.evil.com/",
"www.evil.com/malware.html");
chunks.clear();
chunks.push_back(chunk);
database_->InsertChunks(safe_browsing_util::kMalwareList, chunks);
database_->UpdateFinished(true);
}
FilePath prefix_set_file = database_->PrefixSetForFilename(
database_->BrowseDBFilename(database_filename_));
FilePath bloom_filter_file = database_->BloomFilterForFilename(
database_->BrowseDBFilename(database_filename_));
{
scoped_refptr<BloomFilter> filter(
new BloomFilter(BloomFilter::kBloomFilterSizeRatio *
BloomFilter::kBloomFilterMinSize));
filter->Insert(Sha256Prefix("www.evil.com/"));
filter->Insert(Sha256Prefix("www.evil.com/malware.html"));
ASSERT_TRUE(filter->WriteFile(bloom_filter_file));
}
file_util::Delete(prefix_set_file, false);
ASSERT_FALSE(file_util::PathExists(prefix_set_file));
ASSERT_TRUE(file_util::PathExists(bloom_filter_file));
database_.reset(new SafeBrowsingDatabaseNew);
database_->Init(database_filename_);
const Time now = Time::Now();
std::vector<SBFullHashResult> full_hashes;
std::vector<SBPrefix> prefix_hits;
std::string matching_list;
EXPECT_TRUE(database_->ContainsBrowseUrl(
GURL("http://www.evil.com/malware.html"),
&matching_list, &prefix_hits, &full_hashes, now));
EXPECT_FALSE(database_->ContainsBrowseUrl(
GURL("http://www.good.com/goodware.html"),
&matching_list, &prefix_hits, &full_hashes, now));
}