blob: 49ceaecc008eeab00319482175b27a59529e4cd2 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Helper class which handles communication with the SafeBrowsing servers for
// improved binary download protection.
#ifndef CHROME_BROWSER_SAFE_BROWSING_DOWNLOAD_PROTECTION_DOWNLOAD_PROTECTION_SERVICE_H_
#define CHROME_BROWSER_SAFE_BROWSING_DOWNLOAD_PROTECTION_DOWNLOAD_PROTECTION_SERVICE_H_
#include <stdint.h>
#include <memory>
#include <set>
#include <string>
#include <unordered_map>
#include <vector>
#include "base/callback.h"
#include "base/callback_list.h"
#include "base/files/file_path.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/supports_user_data.h"
#include "chrome/browser/safe_browsing/download_protection/download_protection_util.h"
#include "chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.h"
#include "chrome/browser/safe_browsing/ui_manager.h"
#include "components/safe_browsing_db/database_manager.h"
#include "net/url_request/url_request_context_getter.h"
#include "url/gurl.h"
namespace content {
class DownloadItem;
class PageNavigator;
} // namespace content
namespace net {
class X509Certificate;
} // namespace net
class Profile;
namespace safe_browsing {
class BinaryFeatureExtractor;
class ClientDownloadRequest;
class DownloadFeedbackService;
class CheckClientDownloadRequest;
class PPAPIDownloadRequest;
// This class provides an asynchronous API to check whether a particular
// client download is malicious or not.
class DownloadProtectionService {
public:
// Creates a download service. The service is initially disabled. You need
// to call SetEnabled() to start it. |sb_service| owns this object.
explicit DownloadProtectionService(SafeBrowsingService* sb_service);
virtual ~DownloadProtectionService();
// Parse a flag of blacklisted sha256 hashes to check at each download.
// This is used for testing, to hunt for safe-browsing by-pass bugs.
virtual void ParseManualBlacklistFlag();
// Return true if this hash value is blacklisted via flag (for testing).
virtual bool IsHashManuallyBlacklisted(const std::string& sha256_hash) const;
// Checks whether the given client download is likely to be malicious or not.
// The result is delivered asynchronously via the given callback. This
// method must be called on the UI thread, and the callback will also be
// invoked on the UI thread. This method must be called once the download
// is finished and written to disk.
virtual void CheckClientDownload(content::DownloadItem* item,
const CheckDownloadCallback& callback);
// Checks whether any of the URLs in the redirect chain of the
// download match the SafeBrowsing bad binary URL list. The result is
// delivered asynchronously via the given callback. This method must be
// called on the UI thread, and the callback will also be invoked on the UI
// thread. Pre-condition: !info.download_url_chain.empty().
virtual void CheckDownloadUrl(content::DownloadItem* item,
const CheckDownloadCallback& callback);
// Returns true iff the download specified by |info| should be scanned by
// CheckClientDownload() for malicious content.
virtual bool IsSupportedDownload(const content::DownloadItem& item,
const base::FilePath& target_path) const;
virtual void CheckPPAPIDownloadRequest(
const GURL& requestor_url,
const GURL& initiating_frame_url,
content::WebContents* web_contents,
const base::FilePath& default_file_path,
const std::vector<base::FilePath::StringType>& alternate_extensions,
Profile* profile,
const CheckDownloadCallback& callback);
// Display more information to the user regarding the download specified by
// |info|. This method is invoked when the user requests more information
// about a download that was marked as malicious.
void ShowDetailsForDownload(const content::DownloadItem& item,
content::PageNavigator* navigator);
// Enables or disables the service. This is usually called by the
// SafeBrowsingService, which tracks whether any profile uses these services
// at all. Disabling causes any pending and future requests to have their
// callbacks called with "UNKNOWN" results.
void SetEnabled(bool enabled);
bool enabled() const { return enabled_; }
// Returns the timeout that is used by CheckClientDownload().
int64_t download_request_timeout_ms() const {
return download_request_timeout_ms_;
}
DownloadFeedbackService* feedback_service() {
return feedback_service_.get();
}
// Registers a callback that will be run when a ClientDownloadRequest has
// been formed.
ClientDownloadRequestSubscription RegisterClientDownloadRequestCallback(
const ClientDownloadRequestCallback& callback);
// Registers a callback that will be run when a PPAPI ClientDownloadRequest
// has been formed.
PPAPIDownloadRequestSubscription RegisterPPAPIDownloadRequestCallback(
const PPAPIDownloadRequestCallback& callback);
double whitelist_sample_rate() const { return whitelist_sample_rate_; }
scoped_refptr<SafeBrowsingNavigationObserverManager>
navigation_observer_manager() {
return navigation_observer_manager_;
}
static void SetDownloadPingToken(content::DownloadItem* item,
const std::string& token);
static std::string GetDownloadPingToken(const content::DownloadItem* item);
// Sends dangerous download opened report when download is opened or
// shown in folder, and if the following conditions are met:
// (1) it is a dangerous download.
// (2) user is NOT in incognito mode.
// (3) user is opted-in for extended reporting.
void MaybeSendDangerousDownloadOpenedReport(const content::DownloadItem* item,
bool show_download_in_folder);
private:
// todo(jialiul): Remove the need for non-test friending.
friend class PPAPIDownloadRequest;
friend class DownloadUrlSBClient;
friend class DownloadProtectionServiceTest;
friend class DownloadDangerPromptTest;
friend class CheckClientDownloadRequest;
FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceTest,
CheckClientDownloadWhitelistedUrlWithoutSampling);
FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceTest,
CheckClientDownloadWhitelistedUrlWithSampling);
FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceTest,
CheckClientDownloadValidateRequest);
FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceTest,
CheckClientDownloadSuccess);
FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceTest,
CheckClientDownloadHTTPS);
FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceTest,
CheckClientDownloadBlob);
FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceTest,
CheckClientDownloadData);
FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceTest,
CheckClientDownloadZip);
FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceTest,
CheckClientDownloadFetchFailed);
FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceTest,
TestDownloadRequestTimeout);
FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceTest,
CheckClientCrxDownloadSuccess);
FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceTest,
PPAPIDownloadRequest_InvalidResponse);
FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceTest,
PPAPIDownloadRequest_Timeout);
FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceTest,
VerifyReferrerChainWithEmptyNavigationHistory);
FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceFlagTest,
CheckClientDownloadOverridenByFlag);
FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceTest,
VerifyMaybeSendDangerousDownloadOpenedReport);
static const void* const kDownloadPingTokenKey;
// Helper class for easy setting and getting token string.
class DownloadPingToken : public base::SupportsUserData::Data {
public:
explicit DownloadPingToken(const std::string& token)
: token_string_(token) {}
std::string token_string() { return token_string_; }
private:
std::string token_string_;
DISALLOW_COPY_AND_ASSIGN(DownloadPingToken);
};
// Cancels all requests in |download_requests_|, and empties it, releasing
// the references to the requests.
void CancelPendingRequests();
// Called by a CheckClientDownloadRequest instance when it finishes, to
// remove it from |download_requests_|.
void RequestFinished(CheckClientDownloadRequest* request);
void PPAPIDownloadCheckRequestFinished(PPAPIDownloadRequest* request);
// Given a certificate and its immediate issuer certificate, generates the
// list of strings that need to be checked against the download whitelist to
// determine whether the certificate is whitelisted.
static void GetCertificateWhitelistStrings(
const net::X509Certificate& certificate,
const net::X509Certificate& issuer,
std::vector<std::string>* whitelist_strings);
// If kDownloadAttribution feature is enabled, identify referrer chain info of
// a download. This function also records UMA stats of download attribution
// result.
std::unique_ptr<ReferrerChain> IdentifyReferrerChain(
const content::DownloadItem& item);
// If kDownloadAttribution feature is enabled, identify referrer chain of the
// PPAPI download based on the frame URL where the download is initiated.
// Then add referrer chain info to ClientDownloadRequest proto. This function
// also records UMA stats of download attribution result.
void AddReferrerChainToPPAPIClientDownloadRequest(
const GURL& initiating_frame_url,
const GURL& initiating_main_frame_url,
int tab_id,
bool has_user_gesture,
ClientDownloadRequest* out_request);
SafeBrowsingService* sb_service_;
// These pointers may be NULL if SafeBrowsing is disabled.
scoped_refptr<SafeBrowsingUIManager> ui_manager_;
scoped_refptr<SafeBrowsingDatabaseManager> database_manager_;
scoped_refptr<SafeBrowsingNavigationObserverManager>
navigation_observer_manager_;
// The context we use to issue network requests.
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
// Set of pending server requests for DownloadManager mediated downloads.
std::set<scoped_refptr<CheckClientDownloadRequest>> download_requests_;
// Set of pending server requests for PPAPI mediated downloads. Using a map
// because heterogeneous lookups aren't available yet in std::unordered_map.
std::unordered_map<PPAPIDownloadRequest*,
std::unique_ptr<PPAPIDownloadRequest>>
ppapi_download_requests_;
// Keeps track of the state of the service.
bool enabled_;
// BinaryFeatureExtractor object, may be overridden for testing.
scoped_refptr<BinaryFeatureExtractor> binary_feature_extractor_;
int64_t download_request_timeout_ms_;
std::unique_ptr<DownloadFeedbackService> feedback_service_;
// A list of callbacks to be run on the main thread when a
// ClientDownloadRequest has been formed.
ClientDownloadRequestCallbackList client_download_request_callbacks_;
// A list of callbacks to be run on the main thread when a
// PPAPIDownloadRequest has been formed.
PPAPIDownloadRequestCallbackList ppapi_download_request_callbacks_;
// List of 8-byte hashes that are blacklisted manually by flag.
// Normally empty.
std::set<std::string> manual_blacklist_hashes_;
// Rate of whitelisted downloads we sample to send out download ping.
double whitelist_sample_rate_;
DISALLOW_COPY_AND_ASSIGN(DownloadProtectionService);
};
} // namespace safe_browsing
#endif // CHROME_BROWSER_SAFE_BROWSING_DOWNLOAD_PROTECTION_DOWNLOAD_PROTECTION_SERVICE_H_