| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/safe_browsing/download_protection_service.h" | 5 #include "chrome/browser/safe_browsing/download_protection_service.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 | 10 |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 | 247 |
| 248 void CheckDone(SBThreatType threat_type) { | 248 void CheckDone(SBThreatType threat_type) { |
| 249 DownloadProtectionService::DownloadCheckResult result = | 249 DownloadProtectionService::DownloadCheckResult result = |
| 250 IsDangerous(threat_type) ? | 250 IsDangerous(threat_type) ? |
| 251 DownloadProtectionService::DANGEROUS : | 251 DownloadProtectionService::DANGEROUS : |
| 252 DownloadProtectionService::SAFE; | 252 DownloadProtectionService::SAFE; |
| 253 UpdateDownloadCheckStats(total_type_); | 253 UpdateDownloadCheckStats(total_type_); |
| 254 if (threat_type != SB_THREAT_TYPE_SAFE) { | 254 if (threat_type != SB_THREAT_TYPE_SAFE) { |
| 255 UpdateDownloadCheckStats(dangerous_type_); | 255 UpdateDownloadCheckStats(dangerous_type_); |
| 256 BrowserThread::PostTask( | 256 BrowserThread::PostTask( |
| 257 BrowserThread::UI, | 257 BrowserThread::UI, FROM_HERE, |
| 258 FROM_HERE, | 258 base::BindOnce(&DownloadUrlSBClient::ReportMalware, this, |
| 259 base::Bind(&DownloadUrlSBClient::ReportMalware, | 259 threat_type)); |
| 260 this, threat_type)); | |
| 261 } else if (download_attribution_enabled_) { | 260 } else if (download_attribution_enabled_) { |
| 262 // Identify download referrer chain, which will be used in | 261 // Identify download referrer chain, which will be used in |
| 263 // ClientDownloadRequest. | 262 // ClientDownloadRequest. |
| 264 BrowserThread::PostTask( | 263 BrowserThread::PostTask( |
| 265 BrowserThread::UI, | 264 BrowserThread::UI, FROM_HERE, |
| 266 FROM_HERE, | 265 base::BindOnce(&DownloadUrlSBClient::IdentifyReferrerChain, this)); |
| 267 base::Bind(&DownloadUrlSBClient::IdentifyReferrerChain, | |
| 268 this)); | |
| 269 } | 266 } |
| 270 BrowserThread::PostTask(BrowserThread::UI, | 267 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 271 FROM_HERE, | 268 base::BindOnce(callback_, result)); |
| 272 base::Bind(callback_, result)); | |
| 273 } | 269 } |
| 274 | 270 |
| 275 void ReportMalware(SBThreatType threat_type) { | 271 void ReportMalware(SBThreatType threat_type) { |
| 276 std::string post_data; | 272 std::string post_data; |
| 277 if (!sha256_hash_.empty()) { | 273 if (!sha256_hash_.empty()) { |
| 278 post_data += base::HexEncode(sha256_hash_.data(), | 274 post_data += base::HexEncode(sha256_hash_.data(), |
| 279 sha256_hash_.size()) + "\n"; | 275 sha256_hash_.size()) + "\n"; |
| 280 } | 276 } |
| 281 for (size_t i = 0; i < url_chain_.size(); ++i) { | 277 for (size_t i = 0; i < url_chain_.size(); ++i) { |
| 282 post_data += url_chain_[i].spec() + "\n"; | 278 post_data += url_chain_[i].spec() + "\n"; |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 485 // Start a timeout to cancel the request if it takes too long. | 481 // Start a timeout to cancel the request if it takes too long. |
| 486 // This should only be called after we have finished accessing the file. | 482 // This should only be called after we have finished accessing the file. |
| 487 void StartTimeout() { | 483 void StartTimeout() { |
| 488 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 484 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 489 if (!service_) { | 485 if (!service_) { |
| 490 // Request has already been cancelled. | 486 // Request has already been cancelled. |
| 491 return; | 487 return; |
| 492 } | 488 } |
| 493 timeout_start_time_ = base::TimeTicks::Now(); | 489 timeout_start_time_ = base::TimeTicks::Now(); |
| 494 BrowserThread::PostDelayedTask( | 490 BrowserThread::PostDelayedTask( |
| 495 BrowserThread::UI, | 491 BrowserThread::UI, FROM_HERE, |
| 496 FROM_HERE, | 492 base::BindOnce(&CheckClientDownloadRequest::Cancel, |
| 497 base::Bind(&CheckClientDownloadRequest::Cancel, | 493 weakptr_factory_.GetWeakPtr()), |
| 498 weakptr_factory_.GetWeakPtr()), | |
| 499 base::TimeDelta::FromMilliseconds( | 494 base::TimeDelta::FromMilliseconds( |
| 500 service_->download_request_timeout_ms())); | 495 service_->download_request_timeout_ms())); |
| 501 } | 496 } |
| 502 | 497 |
| 503 // Canceling a request will cause us to always report the result as UNKNOWN | 498 // Canceling a request will cause us to always report the result as UNKNOWN |
| 504 // unless a pending request is about to call FinishRequest. | 499 // unless a pending request is about to call FinishRequest. |
| 505 void Cancel() { | 500 void Cancel() { |
| 506 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 501 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 507 if (fetcher_.get()) { | 502 if (fetcher_.get()) { |
| 508 // The DownloadProtectionService is going to release its reference, so we | 503 // The DownloadProtectionService is going to release its reference, so we |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 655 DCHECK(item_ == NULL); | 650 DCHECK(item_ == NULL); |
| 656 } | 651 } |
| 657 | 652 |
| 658 void OnFileFeatureExtractionDone() { | 653 void OnFileFeatureExtractionDone() { |
| 659 // This can run in any thread, since it just posts more messages. | 654 // This can run in any thread, since it just posts more messages. |
| 660 | 655 |
| 661 // TODO(noelutz): DownloadInfo should also contain the IP address of | 656 // TODO(noelutz): DownloadInfo should also contain the IP address of |
| 662 // every URL in the redirect chain. We also should check whether the | 657 // every URL in the redirect chain. We also should check whether the |
| 663 // download URL is hosted on the internal network. | 658 // download URL is hosted on the internal network. |
| 664 BrowserThread::PostTask( | 659 BrowserThread::PostTask( |
| 665 BrowserThread::IO, | 660 BrowserThread::IO, FROM_HERE, |
| 666 FROM_HERE, | 661 base::BindOnce(&CheckClientDownloadRequest::CheckWhitelists, this)); |
| 667 base::Bind(&CheckClientDownloadRequest::CheckWhitelists, this)); | |
| 668 | 662 |
| 669 // We wait until after the file checks finish to start the timeout, as | 663 // We wait until after the file checks finish to start the timeout, as |
| 670 // windows can cause permissions errors if the timeout fired while we were | 664 // windows can cause permissions errors if the timeout fired while we were |
| 671 // checking the file signature and we tried to complete the download. | 665 // checking the file signature and we tried to complete the download. |
| 672 BrowserThread::PostTask( | 666 BrowserThread::PostTask( |
| 673 BrowserThread::UI, | 667 BrowserThread::UI, FROM_HERE, |
| 674 FROM_HERE, | 668 base::BindOnce(&CheckClientDownloadRequest::StartTimeout, this)); |
| 675 base::Bind(&CheckClientDownloadRequest::StartTimeout, this)); | |
| 676 } | 669 } |
| 677 | 670 |
| 678 void StartExtractFileFeatures() { | 671 void StartExtractFileFeatures() { |
| 679 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 672 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 680 DCHECK(item_); // Called directly from Start(), item should still exist. | 673 DCHECK(item_); // Called directly from Start(), item should still exist. |
| 681 // Since we do blocking I/O, offload this to a worker thread. | 674 // Since we do blocking I/O, offload this to a worker thread. |
| 682 // The task does not need to block shutdown. | 675 // The task does not need to block shutdown. |
| 683 base::PostTaskWithTraits( | 676 base::PostTaskWithTraits( |
| 684 FROM_HERE, base::TaskTraits() | 677 FROM_HERE, |
| 685 .MayBlock() | 678 base::TaskTraits() |
| 686 .WithPriority(base::TaskPriority::BACKGROUND) | 679 .MayBlock() |
| 687 .WithShutdownBehavior( | 680 .WithPriority(base::TaskPriority::BACKGROUND) |
| 688 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN), | 681 .WithShutdownBehavior( |
| 689 base::Bind(&CheckClientDownloadRequest::ExtractFileFeatures, this, | 682 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN), |
| 690 item_->GetFullPath())); | 683 base::BindOnce(&CheckClientDownloadRequest::ExtractFileFeatures, this, |
| 684 item_->GetFullPath())); |
| 691 } | 685 } |
| 692 | 686 |
| 693 void ExtractFileFeatures(const base::FilePath& file_path) { | 687 void ExtractFileFeatures(const base::FilePath& file_path) { |
| 694 base::TimeTicks start_time = base::TimeTicks::Now(); | 688 base::TimeTicks start_time = base::TimeTicks::Now(); |
| 695 binary_feature_extractor_->CheckSignature(file_path, &signature_info_); | 689 binary_feature_extractor_->CheckSignature(file_path, &signature_info_); |
| 696 bool is_signed = (signature_info_.certificate_chain_size() > 0); | 690 bool is_signed = (signature_info_.certificate_chain_size() > 0); |
| 697 if (is_signed) { | 691 if (is_signed) { |
| 698 DVLOG(2) << "Downloaded a signed binary: " << file_path.value(); | 692 DVLOG(2) << "Downloaded a signed binary: " << file_path.value(); |
| 699 } else { | 693 } else { |
| 700 DVLOG(2) << "Downloaded an unsigned binary: " | 694 DVLOG(2) << "Downloaded an unsigned binary: " |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 894 RecordCountOfWhitelistedDownload(NO_WHITELIST_MATCH); | 888 RecordCountOfWhitelistedDownload(NO_WHITELIST_MATCH); |
| 895 | 889 |
| 896 if (!pingback_enabled_) { | 890 if (!pingback_enabled_) { |
| 897 PostFinishTask(UNKNOWN, REASON_PING_DISABLED); | 891 PostFinishTask(UNKNOWN, REASON_PING_DISABLED); |
| 898 return; | 892 return; |
| 899 } | 893 } |
| 900 | 894 |
| 901 // The URLFetcher is owned by the UI thread, so post a message to | 895 // The URLFetcher is owned by the UI thread, so post a message to |
| 902 // start the pingback. | 896 // start the pingback. |
| 903 BrowserThread::PostTask( | 897 BrowserThread::PostTask( |
| 904 BrowserThread::UI, | 898 BrowserThread::UI, FROM_HERE, |
| 905 FROM_HERE, | 899 base::BindOnce(&CheckClientDownloadRequest::GetTabRedirects, this)); |
| 906 base::Bind(&CheckClientDownloadRequest::GetTabRedirects, this)); | |
| 907 } | 900 } |
| 908 | 901 |
| 909 void GetTabRedirects() { | 902 void GetTabRedirects() { |
| 910 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 903 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 911 if (!service_) | 904 if (!service_) |
| 912 return; | 905 return; |
| 913 | 906 |
| 914 if (!tab_url_.is_valid()) { | 907 if (!tab_url_.is_valid()) { |
| 915 SendRequest(); | 908 SendRequest(); |
| 916 return; | 909 return; |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1138 client_download_request_data_); | 1131 client_download_request_data_); |
| 1139 request_start_time_ = base::TimeTicks::Now(); | 1132 request_start_time_ = base::TimeTicks::Now(); |
| 1140 UMA_HISTOGRAM_COUNTS("SBClientDownload.DownloadRequestPayloadSize", | 1133 UMA_HISTOGRAM_COUNTS("SBClientDownload.DownloadRequestPayloadSize", |
| 1141 client_download_request_data_.size()); | 1134 client_download_request_data_.size()); |
| 1142 fetcher_->Start(); | 1135 fetcher_->Start(); |
| 1143 } | 1136 } |
| 1144 | 1137 |
| 1145 void PostFinishTask(DownloadCheckResult result, | 1138 void PostFinishTask(DownloadCheckResult result, |
| 1146 DownloadCheckResultReason reason) { | 1139 DownloadCheckResultReason reason) { |
| 1147 BrowserThread::PostTask( | 1140 BrowserThread::PostTask( |
| 1148 BrowserThread::UI, | 1141 BrowserThread::UI, FROM_HERE, |
| 1149 FROM_HERE, | 1142 base::BindOnce(&CheckClientDownloadRequest::FinishRequest, this, result, |
| 1150 base::Bind(&CheckClientDownloadRequest::FinishRequest, this, result, | 1143 reason)); |
| 1151 reason)); | |
| 1152 } | 1144 } |
| 1153 | 1145 |
| 1154 void FinishRequest(DownloadCheckResult result, | 1146 void FinishRequest(DownloadCheckResult result, |
| 1155 DownloadCheckResultReason reason) { | 1147 DownloadCheckResultReason reason) { |
| 1156 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1148 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 1157 if (finished_) { | 1149 if (finished_) { |
| 1158 return; | 1150 return; |
| 1159 } | 1151 } |
| 1160 finished_ = true; | 1152 finished_ = true; |
| 1161 | 1153 |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1381 Finish(RequestOutcome::UNSUPPORTED_FILE_TYPE, SAFE); | 1373 Finish(RequestOutcome::UNSUPPORTED_FILE_TYPE, SAFE); |
| 1382 return; | 1374 return; |
| 1383 } | 1375 } |
| 1384 | 1376 |
| 1385 // In case the request take too long, the check will abort with an UNKNOWN | 1377 // In case the request take too long, the check will abort with an UNKNOWN |
| 1386 // verdict. The weak pointer used for the timeout will be invalidated (and | 1378 // verdict. The weak pointer used for the timeout will be invalidated (and |
| 1387 // hence would prevent the timeout) if the check completes on time and | 1379 // hence would prevent the timeout) if the check completes on time and |
| 1388 // execution reaches Finish(). | 1380 // execution reaches Finish(). |
| 1389 BrowserThread::PostDelayedTask( | 1381 BrowserThread::PostDelayedTask( |
| 1390 BrowserThread::UI, FROM_HERE, | 1382 BrowserThread::UI, FROM_HERE, |
| 1391 base::Bind(&PPAPIDownloadRequest::OnRequestTimedOut, | 1383 base::BindOnce(&PPAPIDownloadRequest::OnRequestTimedOut, |
| 1392 weakptr_factory_.GetWeakPtr()), | 1384 weakptr_factory_.GetWeakPtr()), |
| 1393 base::TimeDelta::FromMilliseconds( | 1385 base::TimeDelta::FromMilliseconds( |
| 1394 service_->download_request_timeout_ms())); | 1386 service_->download_request_timeout_ms())); |
| 1395 | 1387 |
| 1396 BrowserThread::PostTask( | 1388 BrowserThread::PostTask( |
| 1397 BrowserThread::IO, FROM_HERE, | 1389 BrowserThread::IO, FROM_HERE, |
| 1398 base::Bind(&PPAPIDownloadRequest::CheckWhitelistsOnIOThread, | 1390 base::BindOnce(&PPAPIDownloadRequest::CheckWhitelistsOnIOThread, |
| 1399 requestor_url_, database_manager_, | 1391 requestor_url_, database_manager_, |
| 1400 weakptr_factory_.GetWeakPtr())); | 1392 weakptr_factory_.GetWeakPtr())); |
| 1401 } | 1393 } |
| 1402 | 1394 |
| 1403 private: | 1395 private: |
| 1404 // Whitelist checking needs to the done on the IO thread. | 1396 // Whitelist checking needs to the done on the IO thread. |
| 1405 static void CheckWhitelistsOnIOThread( | 1397 static void CheckWhitelistsOnIOThread( |
| 1406 const GURL& requestor_url, | 1398 const GURL& requestor_url, |
| 1407 scoped_refptr<SafeBrowsingDatabaseManager> database_manager, | 1399 scoped_refptr<SafeBrowsingDatabaseManager> database_manager, |
| 1408 base::WeakPtr<PPAPIDownloadRequest> download_request) { | 1400 base::WeakPtr<PPAPIDownloadRequest> download_request) { |
| 1409 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 1401 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 1410 DVLOG(2) << " checking whitelists for requestor URL:" << requestor_url; | 1402 DVLOG(2) << " checking whitelists for requestor URL:" << requestor_url; |
| 1411 | 1403 |
| 1412 bool url_was_whitelisted = | 1404 bool url_was_whitelisted = |
| 1413 requestor_url.is_valid() && database_manager && | 1405 requestor_url.is_valid() && database_manager && |
| 1414 database_manager->MatchDownloadWhitelistUrl(requestor_url); | 1406 database_manager->MatchDownloadWhitelistUrl(requestor_url); |
| 1415 BrowserThread::PostTask( | 1407 BrowserThread::PostTask( |
| 1416 BrowserThread::UI, FROM_HERE, | 1408 BrowserThread::UI, FROM_HERE, |
| 1417 base::Bind(&PPAPIDownloadRequest::WhitelistCheckComplete, | 1409 base::BindOnce(&PPAPIDownloadRequest::WhitelistCheckComplete, |
| 1418 download_request, url_was_whitelisted)); | 1410 download_request, url_was_whitelisted)); |
| 1419 } | 1411 } |
| 1420 | 1412 |
| 1421 void WhitelistCheckComplete(bool was_on_whitelist) { | 1413 void WhitelistCheckComplete(bool was_on_whitelist) { |
| 1422 DVLOG(2) << __func__ << " was_on_whitelist:" << was_on_whitelist; | 1414 DVLOG(2) << __func__ << " was_on_whitelist:" << was_on_whitelist; |
| 1423 if (was_on_whitelist) { | 1415 if (was_on_whitelist) { |
| 1424 RecordCountOfWhitelistedDownload(URL_WHITELIST); | 1416 RecordCountOfWhitelistedDownload(URL_WHITELIST); |
| 1425 // TODO(asanka): Should sample whitelisted downloads based on | 1417 // TODO(asanka): Should sample whitelisted downloads based on |
| 1426 // service_->whitelist_sample_rate(). http://crbug.com/610924 | 1418 // service_->whitelist_sample_rate(). http://crbug.com/610924 |
| 1427 Finish(RequestOutcome::WHITELIST_HIT, SAFE); | 1419 Finish(RequestOutcome::WHITELIST_HIT, SAFE); |
| 1428 return; | 1420 return; |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1745 | 1737 |
| 1746 void DownloadProtectionService::CheckDownloadUrl( | 1738 void DownloadProtectionService::CheckDownloadUrl( |
| 1747 content::DownloadItem* item, | 1739 content::DownloadItem* item, |
| 1748 const CheckDownloadCallback& callback) { | 1740 const CheckDownloadCallback& callback) { |
| 1749 DCHECK(!item->GetUrlChain().empty()); | 1741 DCHECK(!item->GetUrlChain().empty()); |
| 1750 scoped_refptr<DownloadUrlSBClient> client( | 1742 scoped_refptr<DownloadUrlSBClient> client( |
| 1751 new DownloadUrlSBClient(item, this, callback, ui_manager_, | 1743 new DownloadUrlSBClient(item, this, callback, ui_manager_, |
| 1752 database_manager_)); | 1744 database_manager_)); |
| 1753 // The client will release itself once it is done. | 1745 // The client will release itself once it is done. |
| 1754 BrowserThread::PostTask( | 1746 BrowserThread::PostTask( |
| 1755 BrowserThread::IO, | 1747 BrowserThread::IO, FROM_HERE, |
| 1756 FROM_HERE, | 1748 base::BindOnce(&DownloadUrlSBClient::StartCheck, client)); |
| 1757 base::Bind(&DownloadUrlSBClient::StartCheck, client)); | |
| 1758 } | 1749 } |
| 1759 | 1750 |
| 1760 bool DownloadProtectionService::IsSupportedDownload( | 1751 bool DownloadProtectionService::IsSupportedDownload( |
| 1761 const content::DownloadItem& item, | 1752 const content::DownloadItem& item, |
| 1762 const base::FilePath& target_path) const { | 1753 const base::FilePath& target_path) const { |
| 1763 DownloadCheckResultReason reason = REASON_MAX; | 1754 DownloadCheckResultReason reason = REASON_MAX; |
| 1764 ClientDownloadRequest::DownloadType type = | 1755 ClientDownloadRequest::DownloadType type = |
| 1765 ClientDownloadRequest::WIN_EXECUTABLE; | 1756 ClientDownloadRequest::WIN_EXECUTABLE; |
| 1766 // TODO(nparker): Remove the CRX check here once can support | 1757 // TODO(nparker): Remove the CRX check here once can support |
| 1767 // UNKNOWN types properly. http://crbug.com/581044 | 1758 // UNKNOWN types properly. http://crbug.com/581044 |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2010 UMA_HISTOGRAM_COUNTS_100( | 2001 UMA_HISTOGRAM_COUNTS_100( |
| 2011 "SafeBrowsing.ReferrerURLChainSize.PPAPIDownloadAttribution", | 2002 "SafeBrowsing.ReferrerURLChainSize.PPAPIDownloadAttribution", |
| 2012 out_request->referrer_chain_size()); | 2003 out_request->referrer_chain_size()); |
| 2013 UMA_HISTOGRAM_ENUMERATION( | 2004 UMA_HISTOGRAM_ENUMERATION( |
| 2014 "SafeBrowsing.ReferrerAttributionResult.PPAPIDownloadAttribution", result, | 2005 "SafeBrowsing.ReferrerAttributionResult.PPAPIDownloadAttribution", result, |
| 2015 SafeBrowsingNavigationObserverManager::ATTRIBUTION_FAILURE_TYPE_MAX); | 2006 SafeBrowsingNavigationObserverManager::ATTRIBUTION_FAILURE_TYPE_MAX); |
| 2016 out_request->set_download_attribution_finch_enabled(true); | 2007 out_request->set_download_attribution_finch_enabled(true); |
| 2017 } | 2008 } |
| 2018 | 2009 |
| 2019 } // namespace safe_browsing | 2010 } // namespace safe_browsing |
| OLD | NEW |