Commit adb84582 authored by noelutz@google.com's avatar noelutz@google.com

Measure how often downloaded executables match the download whitelist.

This CL also tells all Chrome users who have SafeBrowsing turned on to
download this new whitelist.

BUG=
TEST=SafeBrowsingProtocolParsingTest


Review URL: http://codereview.chromium.org/8417040

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@107885 0039d316-1c4b-4281-b951-d872f2087c98
parent af34d3df
...@@ -67,7 +67,8 @@ class DownloadProtectionService::CheckClientDownloadRequest ...@@ -67,7 +67,8 @@ class DownloadProtectionService::CheckClientDownloadRequest
callback_(callback), callback_(callback),
service_(service), service_(service),
sb_service_(sb_service), sb_service_(sb_service),
pingback_enabled_(service_->enabled()) { pingback_enabled_(service_->enabled()),
is_signed_(false) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
} }
...@@ -162,15 +163,14 @@ class DownloadProtectionService::CheckClientDownloadRequest ...@@ -162,15 +163,14 @@ class DownloadProtectionService::CheckClientDownloadRequest
void ExtractFileFeatures() { void ExtractFileFeatures() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
bool is_signed;
if (safe_browsing::signature_util::IsSigned(info_.local_file)) { if (safe_browsing::signature_util::IsSigned(info_.local_file)) {
VLOG(2) << "Downloaded a signed binary: " << info_.local_file.value(); VLOG(2) << "Downloaded a signed binary: " << info_.local_file.value();
is_signed = true; is_signed_ = true;
} else { } else {
VLOG(2) << "Downloaded an unsigned binary: " << info_.local_file.value(); VLOG(2) << "Downloaded an unsigned binary: " << info_.local_file.value();
is_signed = false; is_signed_ = false;
} }
UMA_HISTOGRAM_BOOLEAN("SBClientDownload.SignedBinaryDownload", is_signed); UMA_HISTOGRAM_BOOLEAN("SBClientDownload.SignedBinaryDownload", is_signed_);
// TODO(noelutz): DownloadInfo should also contain the IP address of every // TODO(noelutz): DownloadInfo should also contain the IP address of every
// URL in the redirect chain. We also should check whether the download // URL in the redirect chain. We also should check whether the download
...@@ -184,7 +184,7 @@ class DownloadProtectionService::CheckClientDownloadRequest ...@@ -184,7 +184,7 @@ class DownloadProtectionService::CheckClientDownloadRequest
void CheckWhitelists() { void CheckWhitelists() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DownloadCheckResultReason reason = REASON_MAX; DownloadCheckResultReason reason = REASON_MAX;
if (!pingback_enabled_ || !sb_service_.get()) { if (!sb_service_.get()) {
reason = REASON_SB_DISABLED; reason = REASON_SB_DISABLED;
} else { } else {
for (size_t i = 0; i < info_.download_url_chain.size(); ++i) { for (size_t i = 0; i < info_.download_url_chain.size(); ++i) {
...@@ -194,25 +194,30 @@ class DownloadProtectionService::CheckClientDownloadRequest ...@@ -194,25 +194,30 @@ class DownloadProtectionService::CheckClientDownloadRequest
break; break;
} }
} }
if (info_.referrer_url.is_valid() && if (info_.referrer_url.is_valid() && reason == REASON_MAX &&
sb_service_->MatchDownloadWhitelistUrl(info_.referrer_url)) { sb_service_->MatchDownloadWhitelistUrl(info_.referrer_url)) {
reason = REASON_WHITELISTED_REFERRER; reason = REASON_WHITELISTED_REFERRER;
} }
if (reason != REASON_MAX || is_signed_) {
UMA_HISTOGRAM_COUNTS("SBClientDownload.SignedOrWhitelistedDownload", 1);
}
} }
if (reason != REASON_MAX) { if (reason != REASON_MAX) {
RecordStats(reason); RecordStats(reason);
PostFinishTask(SAFE); PostFinishTask(SAFE);
return; } else if (!pingback_enabled_) {
RecordStats(REASON_SB_DISABLED);
PostFinishTask(SAFE);
} else {
// TODO(noelutz): check signature and CA against whitelist.
// The URLFetcher is owned by the UI thread, so post a message to
// start the pingback.
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
base::Bind(&CheckClientDownloadRequest::SendRequest, this));
} }
// TODO(noelutz): check signature and CA against whitelist.
// The URLFetcher is owned by the UI thread, so post a message to
// start the pingback.
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
base::Bind(&CheckClientDownloadRequest::SendRequest, this));
} }
void SendRequest() { void SendRequest() {
...@@ -221,6 +226,7 @@ class DownloadProtectionService::CheckClientDownloadRequest ...@@ -221,6 +226,7 @@ class DownloadProtectionService::CheckClientDownloadRequest
// This is our last chance to check whether the request has been canceled // This is our last chance to check whether the request has been canceled
// before sending it. // before sending it.
if (!service_) { if (!service_) {
RecordStats(REASON_REQUEST_CANCELED);
FinishRequest(SAFE); FinishRequest(SAFE);
return; return;
} }
...@@ -289,7 +295,8 @@ class DownloadProtectionService::CheckClientDownloadRequest ...@@ -289,7 +295,8 @@ class DownloadProtectionService::CheckClientDownloadRequest
// Will be NULL if the request has been canceled. // Will be NULL if the request has been canceled.
DownloadProtectionService* service_; DownloadProtectionService* service_;
scoped_refptr<SafeBrowsingService> sb_service_; scoped_refptr<SafeBrowsingService> sb_service_;
bool pingback_enabled_; const bool pingback_enabled_;
bool is_signed_;
scoped_ptr<content::URLFetcher> fetcher_; scoped_ptr<content::URLFetcher> fetcher_;
DISALLOW_COPY_AND_ASSIGN(CheckClientDownloadRequest); DISALLOW_COPY_AND_ASSIGN(CheckClientDownloadRequest);
......
...@@ -97,6 +97,7 @@ class DownloadProtectionService { ...@@ -97,6 +97,7 @@ class DownloadProtectionService {
REASON_SERVER_PING_FAILED, REASON_SERVER_PING_FAILED,
REASON_INVALID_RESPONSE_PROTO, REASON_INVALID_RESPONSE_PROTO,
REASON_NOT_BINARY_FILE, REASON_NOT_BINARY_FILE,
REASON_REQUEST_CANCELED,
REASON_MAX // Always add new values before this one. REASON_MAX // Always add new values before this one.
}; };
......
...@@ -432,7 +432,7 @@ bool SafeBrowsingProtocolManager::HandleServiceResponse(const GURL& url, ...@@ -432,7 +432,7 @@ bool SafeBrowsingProtocolManager::HandleServiceResponse(const GURL& url,
std::string data_str; std::string data_str;
data_str.assign(data, length); data_str.assign(data, length);
std::string encoded_chunk; std::string encoded_chunk;
base::Base64Encode(data, &encoded_chunk); base::Base64Encode(data_str, &encoded_chunk);
VLOG(1) << "ParseChunk error for chunk: " << chunk_url.url VLOG(1) << "ParseChunk error for chunk: " << chunk_url.url
<< ", client_key: " << client_key_ << ", client_key: " << client_key_
<< ", wrapped_key: " << wrapped_key_ << ", wrapped_key: " << wrapped_key_
......
// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
...@@ -335,8 +335,9 @@ bool SafeBrowsingProtocolParser::ParseAddChunk(const std::string& list_name, ...@@ -335,8 +335,9 @@ bool SafeBrowsingProtocolParser::ParseAddChunk(const std::string& list_name,
SBEntry::Type type = hash_len == sizeof(SBPrefix) ? SBEntry::Type type = hash_len == sizeof(SBPrefix) ?
SBEntry::ADD_PREFIX : SBEntry::ADD_FULL_HASH; SBEntry::ADD_PREFIX : SBEntry::ADD_FULL_HASH;
if (list_name == safe_browsing_util::kBinHashList) { if (list_name == safe_browsing_util::kBinHashList ||
// kBinHashList only contains prefixes, no HOSTKEY and COUNT. list_name == safe_browsing_util::kDownloadWhiteList) {
// These lists only contain prefixes, no HOSTKEY and COUNT.
DCHECK_EQ(0, remaining % hash_len); DCHECK_EQ(0, remaining % hash_len);
prefix_count = remaining / hash_len; prefix_count = remaining / hash_len;
SBChunkHost chunk_host; SBChunkHost chunk_host;
......
...@@ -924,3 +924,43 @@ TEST(SafeBrowsingProtocolParsingTest, TestSubBinHashChunk) { ...@@ -924,3 +924,43 @@ TEST(SafeBrowsingProtocolParsingTest, TestSubBinHashChunk) {
EXPECT_EQ(entry->ChunkIdAtPrefix(1), 0x32323232); EXPECT_EQ(entry->ChunkIdAtPrefix(1), 0x32323232);
EXPECT_EQ(entry->PrefixAt(1), 0x6e6e6e6e); EXPECT_EQ(entry->PrefixAt(1), 0x6e6e6e6e);
} }
TEST(SafeBrowsingProtocolParsingTest, TestAddDownloadWhitelistChunk) {
std::string add_chunk("a:1:32:32\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"a:2:32:64\nyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"
"zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz");
// Run the parse.
SafeBrowsingProtocolParser parser;
bool re_key = false;
SBChunkList chunks;
bool result = parser.ParseChunk(
safe_browsing_util::kDownloadWhiteList,
add_chunk.data(),
static_cast<int>(add_chunk.length()),
"", "", &re_key, &chunks);
EXPECT_TRUE(result);
EXPECT_FALSE(re_key);
EXPECT_EQ(chunks.size(), 2U);
EXPECT_EQ(chunks[0].chunk_number, 1);
EXPECT_EQ(chunks[0].hosts.size(), 1U);
EXPECT_EQ(chunks[0].hosts[0].host, 0);
SBEntry* entry = chunks[0].hosts[0].entry;
EXPECT_TRUE(entry->IsAdd());
EXPECT_FALSE(entry->IsPrefix());
EXPECT_EQ(entry->prefix_count(), 1);
SBFullHash full;
memcpy(full.full_hash, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 32);
EXPECT_TRUE(entry->FullHashAt(0) == full);
EXPECT_EQ(chunks[1].chunk_number, 2);
EXPECT_EQ(chunks[1].hosts.size(), 1U);
EXPECT_EQ(chunks[1].hosts[0].host, 0);
entry = chunks[1].hosts[0].entry;
EXPECT_TRUE(entry->IsAdd());
EXPECT_FALSE(entry->IsPrefix());
EXPECT_EQ(entry->prefix_count(), 2);
memcpy(full.full_hash, "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy", 32);
EXPECT_TRUE(entry->FullHashAt(0) == full);
memcpy(full.full_hash, "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", 32);
EXPECT_TRUE(entry->FullHashAt(1) == full);
}
...@@ -913,8 +913,11 @@ void SafeBrowsingService::Start() { ...@@ -913,8 +913,11 @@ void SafeBrowsingService::Start() {
!cmdline->HasSwitch(switches::kDisableClientSidePhishingDetection); !cmdline->HasSwitch(switches::kDisableClientSidePhishingDetection);
#endif #endif
enable_download_whitelist_ = cmdline->HasSwitch( // TODO(noelutz): remove this boolean variable since it should always be true
switches::kEnableImprovedDownloadProtection); // if SafeBrowsing is enabled. Unfortunately, we have no test data for this
// list right now. This means that we need to be able to disable this list
// for the SafeBrowsing test to pass.
enable_download_whitelist_ = enable_csd_whitelist_;
BrowserThread::PostTask( BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE, BrowserThread::IO, FROM_HERE,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment