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

- Flip the flag for improved SafeBrowsing downoad protection.

- Send the binary sha256 hash.
- Cancel requests that timed out.

BUG=102540
TEST=Run DownloadProtectionServiceTest. Also, if you have SafeBrowsing enabled you should see a server request for every binary download that doesn't match our whitelist.


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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@110649 0039d316-1c4b-4281-b951-d872f2087c98
parent 409ac617
...@@ -5,8 +5,10 @@ ...@@ -5,8 +5,10 @@
#include "chrome/browser/safe_browsing/download_protection_service.h" #include "chrome/browser/safe_browsing/download_protection_service.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/format_macros.h" #include "base/format_macros.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/histogram.h" #include "base/metrics/histogram.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/string_number_conversions.h" #include "base/string_number_conversions.h"
...@@ -27,6 +29,10 @@ ...@@ -27,6 +29,10 @@
using content::BrowserThread; using content::BrowserThread;
namespace {
static const int64 kDownloadRequestTimeoutMs = 3000;
} // namespace
namespace safe_browsing { namespace safe_browsing {
const char DownloadProtectionService::kDownloadRequestUrl[] = const char DownloadProtectionService::kDownloadRequestUrl[] =
...@@ -144,7 +150,7 @@ DownloadProtectionService::DownloadInfo::FromDownloadItem( ...@@ -144,7 +150,7 @@ DownloadProtectionService::DownloadInfo::FromDownloadItem(
download_info.target_file = item.GetTargetFilePath(); download_info.target_file = item.GetTargetFilePath();
download_info.download_url_chain = item.url_chain(); download_info.download_url_chain = item.url_chain();
download_info.referrer_url = item.referrer_url(); download_info.referrer_url = item.referrer_url();
// TODO(bryner): Fill in the hash (we shouldn't compute it again) download_info.sha256_hash = item.hash();
download_info.total_bytes = item.total_bytes(); download_info.total_bytes = item.total_bytes();
// TODO(bryner): Populate user_initiated // TODO(bryner): Populate user_initiated
return download_info; return download_info;
...@@ -332,7 +338,9 @@ class DownloadProtectionService::CheckClientDownloadRequest ...@@ -332,7 +338,9 @@ class DownloadProtectionService::CheckClientDownloadRequest
service_(service), service_(service),
signature_util_(signature_util), signature_util_(signature_util),
sb_service_(sb_service), sb_service_(sb_service),
pingback_enabled_(service_->enabled()) { pingback_enabled_(service_->enabled()),
finished_(false),
ALLOW_THIS_IN_INITIALIZER_LIST(timeout_weakptr_factory_(this)) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
} }
...@@ -373,24 +381,35 @@ class DownloadProtectionService::CheckClientDownloadRequest ...@@ -373,24 +381,35 @@ class DownloadProtectionService::CheckClientDownloadRequest
BrowserThread::FILE, BrowserThread::FILE,
FROM_HERE, FROM_HERE,
base::Bind(&CheckClientDownloadRequest::ExtractFileFeatures, this)); base::Bind(&CheckClientDownloadRequest::ExtractFileFeatures, this));
// If the request takes too long we cancel it.
BrowserThread::PostDelayedTask(
BrowserThread::UI,
FROM_HERE,
base::Bind(&CheckClientDownloadRequest::Cancel,
timeout_weakptr_factory_.GetWeakPtr()),
service_->download_request_timeout_ms());
} }
// Canceling a request will cause us to always report the result as SAFE. // Canceling a request will cause us to always report the result as SAFE
// In addition, the DownloadProtectionService will not be notified when the // unless a pending request is about to call FinishRequest.
// request finishes, so it must drop its reference after calling Cancel.
void Cancel() { void Cancel() {
// Calling FinishRequest might delete this object if we don't keep a
// reference around until Cancel() is finished running.
scoped_refptr<CheckClientDownloadRequest> request(this);
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
service_ = NULL; FinishRequest(SAFE);
if (fetcher_.get()) { if (fetcher_.get()) {
// The DownloadProtectionService is going to release its reference, so we // The DownloadProtectionService is going to release its reference, so we
// might be destroyed before the URLFetcher completes. Cancel the // might be destroyed before the URLFetcher completes. Cancel the
// fetcher so it does not try to invoke OnURLFetchComplete. // fetcher so it does not try to invoke OnURLFetchComplete.
FinishRequest(SAFE);
fetcher_.reset(); fetcher_.reset();
} }
// Note: If there is no fetcher, then some callback is still holding a // Note: If there is no fetcher, then some callback is still holding a
// reference to this object. We'll eventually wind up in some method on // reference to this object. We'll eventually wind up in some method on
// the UI thread that will call FinishRequest() and run the callback. // the UI thread that will call FinishRequest() again. If FinishRequest()
// is called a second time, it will be a no-op.
service_ = NULL;
} }
// From the content::URLFetcherDelegate interface. // From the content::URLFetcherDelegate interface.
...@@ -552,6 +571,7 @@ class DownloadProtectionService::CheckClientDownloadRequest ...@@ -552,6 +571,7 @@ class DownloadProtectionService::CheckClientDownloadRequest
content::URLFetcher::POST, content::URLFetcher::POST,
this)); this));
fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE); fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE);
fetcher_->SetAutomaticallyRetryOn5xx(false); // Don't retry on error.
fetcher_->SetRequestContext(service_->request_context_getter_.get()); fetcher_->SetRequestContext(service_->request_context_getter_.get());
fetcher_->SetUploadData("application/octet-stream", request_data); fetcher_->SetUploadData("application/octet-stream", request_data);
fetcher_->Start(); fetcher_->Start();
...@@ -566,6 +586,10 @@ class DownloadProtectionService::CheckClientDownloadRequest ...@@ -566,6 +586,10 @@ class DownloadProtectionService::CheckClientDownloadRequest
void FinishRequest(DownloadCheckResult result) { void FinishRequest(DownloadCheckResult result) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (finished_) {
return;
}
finished_ = true;
if (service_) { if (service_) {
callback_.Run(result); callback_.Run(result);
service_->RequestFinished(this); service_->RequestFinished(this);
...@@ -591,6 +615,8 @@ class DownloadProtectionService::CheckClientDownloadRequest ...@@ -591,6 +615,8 @@ class DownloadProtectionService::CheckClientDownloadRequest
scoped_refptr<SafeBrowsingService> sb_service_; scoped_refptr<SafeBrowsingService> sb_service_;
const bool pingback_enabled_; const bool pingback_enabled_;
scoped_ptr<content::URLFetcher> fetcher_; scoped_ptr<content::URLFetcher> fetcher_;
bool finished_;
base::WeakPtrFactory<CheckClientDownloadRequest> timeout_weakptr_factory_;
DISALLOW_COPY_AND_ASSIGN(CheckClientDownloadRequest); DISALLOW_COPY_AND_ASSIGN(CheckClientDownloadRequest);
}; };
...@@ -601,7 +627,8 @@ DownloadProtectionService::DownloadProtectionService( ...@@ -601,7 +627,8 @@ DownloadProtectionService::DownloadProtectionService(
: sb_service_(sb_service), : sb_service_(sb_service),
request_context_getter_(request_context_getter), request_context_getter_(request_context_getter),
enabled_(false), enabled_(false),
signature_util_(new SignatureUtil()) {} signature_util_(new SignatureUtil()),
download_request_timeout_ms_(kDownloadRequestTimeoutMs) {}
DownloadProtectionService::~DownloadProtectionService() { DownloadProtectionService::~DownloadProtectionService() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
...@@ -651,10 +678,13 @@ void DownloadProtectionService::CancelPendingRequests() { ...@@ -651,10 +678,13 @@ void DownloadProtectionService::CancelPendingRequests() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
for (std::set<scoped_refptr<CheckClientDownloadRequest> >::iterator it = for (std::set<scoped_refptr<CheckClientDownloadRequest> >::iterator it =
download_requests_.begin(); download_requests_.begin();
it != download_requests_.end(); ++it) { it != download_requests_.end();) {
(*it)->Cancel(); // We need to advance the iterator before we cancel because canceling
// the request will invalidate it when RequestFinished is called below.
scoped_refptr<CheckClientDownloadRequest> tmp = *it++;
tmp->Cancel();
} }
download_requests_.clear(); DCHECK(download_requests_.empty());
} }
void DownloadProtectionService::RequestFinished( void DownloadProtectionService::RequestFinished(
......
...@@ -101,6 +101,11 @@ class DownloadProtectionService { ...@@ -101,6 +101,11 @@ class DownloadProtectionService {
return enabled_; return enabled_;
} }
// Returns the timeout that is used by CheckClientDownload().
int64 download_request_timeout_ms() const {
return download_request_timeout_ms_;
}
protected: protected:
// Enum to keep track why a particular download verdict was chosen. // Enum to keep track why a particular download verdict was chosen.
// This is used to keep some stats around. // This is used to keep some stats around.
...@@ -132,6 +137,8 @@ class DownloadProtectionService { ...@@ -132,6 +137,8 @@ class DownloadProtectionService {
CheckClientDownloadSuccess); CheckClientDownloadSuccess);
FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceTest, FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceTest,
CheckClientDownloadFetchFailed); CheckClientDownloadFetchFailed);
FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceTest,
TestDownloadRequestTimeout);
static const char kDownloadRequestUrl[]; static const char kDownloadRequestUrl[];
...@@ -164,6 +171,8 @@ class DownloadProtectionService { ...@@ -164,6 +171,8 @@ class DownloadProtectionService {
// SignatureUtil object, may be overridden for testing. // SignatureUtil object, may be overridden for testing.
scoped_refptr<SignatureUtil> signature_util_; scoped_refptr<SignatureUtil> signature_util_;
int64 download_request_timeout_ms_;
DISALLOW_COPY_AND_ASSIGN(DownloadProtectionService); DISALLOW_COPY_AND_ASSIGN(DownloadProtectionService);
}; };
} // namespace safe_browsing } // namespace safe_browsing
......
...@@ -1349,7 +1349,7 @@ void SafeBrowsingService::RefreshState() { ...@@ -1349,7 +1349,7 @@ void SafeBrowsingService::RefreshState() {
csd_service_->SetEnabledAndRefreshState(enable); csd_service_->SetEnabledAndRefreshState(enable);
if (download_service_.get()) { if (download_service_.get()) {
download_service_->SetEnabled( download_service_->SetEnabled(
enable && CommandLine::ForCurrentProcess()->HasSwitch( enable && !CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableImprovedDownloadProtection)); switches::kDisableImprovedDownloadProtection));
} }
} }
...@@ -262,6 +262,10 @@ const char kDisableHistoryQuickProvider[] = "disable-history-quick-provider"; ...@@ -262,6 +262,10 @@ const char kDisableHistoryQuickProvider[] = "disable-history-quick-provider";
// Disable the use of the HistoryURLProvider for autocomplete results. // Disable the use of the HistoryURLProvider for autocomplete results.
const char kDisableHistoryURLProvider[] = "disable-history-url-provider"; const char kDisableHistoryURLProvider[] = "disable-history-url-provider";
// Disables improved SafeBrowsing download protection.
const char kDisableImprovedDownloadProtection[] =
"disable-improved-download-protection";
// Disables HTML5 Forms interactive validation. // Disables HTML5 Forms interactive validation.
const char kDisableInteractiveFormValidation[] = const char kDisableInteractiveFormValidation[] =
"disable-interactive-form-validation"; "disable-interactive-form-validation";
...@@ -470,10 +474,6 @@ const char kEnableFileCookies[] = "enable-file-cookies"; ...@@ -470,10 +474,6 @@ const char kEnableFileCookies[] = "enable-file-cookies";
// Without this flag, pipelining will never be used. // Without this flag, pipelining will never be used.
const char kEnableHttpPipelining[] = "enable-http-pipelining"; const char kEnableHttpPipelining[] = "enable-http-pipelining";
// Enables improved SafeBrowsing download protection.
const char kEnableImprovedDownloadProtection[] =
"enable-improved-download-protection";
// Enables the in-browser thumbnailing, which is more efficient than the // Enables the in-browser thumbnailing, which is more efficient than the
// in-renderer thumbnailing, as we can use more information to determine if we // in-renderer thumbnailing, as we can use more information to determine if we
// need to update thumbnails. // need to update thumbnails.
......
...@@ -81,6 +81,7 @@ extern const char kDisableExtensions[]; ...@@ -81,6 +81,7 @@ extern const char kDisableExtensions[];
extern const char kDisableFlashSandbox[]; extern const char kDisableFlashSandbox[];
extern const char kDisableHistoryQuickProvider[]; extern const char kDisableHistoryQuickProvider[];
extern const char kDisableHistoryURLProvider[]; extern const char kDisableHistoryURLProvider[];
extern const char kDisableImprovedDownloadProtection[];
extern const char kDisableInteractiveFormValidation[]; extern const char kDisableInteractiveFormValidation[];
extern const char kDisableInternalFlash[]; extern const char kDisableInternalFlash[];
extern const char kDisableIPv6[]; extern const char kDisableIPv6[];
...@@ -137,7 +138,6 @@ extern const char kEnableExtensionTimelineApi[]; ...@@ -137,7 +138,6 @@ extern const char kEnableExtensionTimelineApi[];
extern const char kEnableFastback[]; extern const char kEnableFastback[];
extern const char kEnableFileCookies[]; extern const char kEnableFileCookies[];
extern const char kEnableHttpPipelining[]; extern const char kEnableHttpPipelining[];
extern const char kEnableImprovedDownloadProtection[];
extern const char kEnableInBrowserThumbnailing[]; extern const char kEnableInBrowserThumbnailing[];
extern const char kEnableIPv6[]; extern const char kEnableIPv6[];
extern const char kEnableIPCFuzzing[]; extern const char kEnableIPCFuzzing[];
......
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