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 |