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 "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
10 #include "base/format_macros.h" | 10 #include "base/format_macros.h" |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
271 const CheckDownloadCallback& callback, | 271 const CheckDownloadCallback& callback, |
272 DownloadProtectionService* service, | 272 DownloadProtectionService* service, |
273 const scoped_refptr<SafeBrowsingDatabaseManager>& database_manager, | 273 const scoped_refptr<SafeBrowsingDatabaseManager>& database_manager, |
274 BinaryFeatureExtractor* binary_feature_extractor) | 274 BinaryFeatureExtractor* binary_feature_extractor) |
275 : item_(item), | 275 : item_(item), |
276 url_chain_(item->GetUrlChain()), | 276 url_chain_(item->GetUrlChain()), |
277 referrer_url_(item->GetReferrerUrl()), | 277 referrer_url_(item->GetReferrerUrl()), |
278 tab_url_(item->GetTabUrl()), | 278 tab_url_(item->GetTabUrl()), |
279 tab_referrer_url_(item->GetTabReferrerUrl()), | 279 tab_referrer_url_(item->GetTabReferrerUrl()), |
280 archived_executable_(false), | 280 archived_executable_(false), |
281 archive_is_valid_(ArchiveValid::UNSET), | |
281 callback_(callback), | 282 callback_(callback), |
282 service_(service), | 283 service_(service), |
283 binary_feature_extractor_(binary_feature_extractor), | 284 binary_feature_extractor_(binary_feature_extractor), |
284 database_manager_(database_manager), | 285 database_manager_(database_manager), |
285 pingback_enabled_(service_->enabled()), | 286 pingback_enabled_(service_->enabled()), |
286 finished_(false), | 287 finished_(false), |
287 type_(ClientDownloadRequest::WIN_EXECUTABLE), | 288 type_(ClientDownloadRequest::WIN_EXECUTABLE), |
288 start_time_(base::TimeTicks::Now()), | 289 start_time_(base::TimeTicks::Now()), |
289 weakptr_factory_(this) { | 290 weakptr_factory_(this) { |
290 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 291 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
478 | 479 |
479 private: | 480 private: |
480 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; | 481 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; |
481 friend class base::DeleteHelper<CheckClientDownloadRequest>; | 482 friend class base::DeleteHelper<CheckClientDownloadRequest>; |
482 | 483 |
483 ~CheckClientDownloadRequest() override { | 484 ~CheckClientDownloadRequest() override { |
484 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 485 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
485 DCHECK(item_ == NULL); | 486 DCHECK(item_ == NULL); |
486 } | 487 } |
487 | 488 |
489 // .zip files that look invalid to Chrome can often be successfully unpacked | |
490 // by other archive tools, so they may be a real threat. For that reason, | |
491 // we send pings for them for some users. | |
492 bool CanReportInvalidArchives() { | |
493 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
494 const bool in_incognito = item_->GetBrowserContext()->IsOffTheRecord(); | |
asanka
2015/11/18 21:37:55
Nit: Maybe return early if in_incognito is true.
Nathan Parker
2015/11/20 06:22:16
We're sending pings here that weren't sent before,
asanka
2015/11/20 15:55:40
It does. I was just curious.
| |
495 | |
496 Profile* profile = Profile::FromBrowserContext(item_->GetBrowserContext()); | |
497 const bool is_extended_reporting = | |
498 profile && | |
499 profile->GetPrefs()->GetBoolean( | |
500 prefs::kSafeBrowsingExtendedReportingEnabled); | |
501 | |
502 return !in_incognito && is_extended_reporting; | |
503 } | |
504 | |
488 void OnFileFeatureExtractionDone() { | 505 void OnFileFeatureExtractionDone() { |
489 // This can run in any thread, since it just posts more messages. | 506 // This can run in any thread, since it just posts more messages. |
490 | 507 |
491 // TODO(noelutz): DownloadInfo should also contain the IP address of | 508 // TODO(noelutz): DownloadInfo should also contain the IP address of |
492 // every URL in the redirect chain. We also should check whether the | 509 // every URL in the redirect chain. We also should check whether the |
493 // download URL is hosted on the internal network. | 510 // download URL is hosted on the internal network. |
494 BrowserThread::PostTask( | 511 BrowserThread::PostTask( |
495 BrowserThread::IO, | 512 BrowserThread::IO, |
496 FROM_HERE, | 513 FROM_HERE, |
497 base::Bind(&CheckClientDownloadRequest::CheckWhitelists, this)); | 514 base::Bind(&CheckClientDownloadRequest::CheckWhitelists, this)); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
557 base::Bind(&CheckClientDownloadRequest::OnZipAnalysisFinished, | 574 base::Bind(&CheckClientDownloadRequest::OnZipAnalysisFinished, |
558 weakptr_factory_.GetWeakPtr())); | 575 weakptr_factory_.GetWeakPtr())); |
559 analyzer_->Start(); | 576 analyzer_->Start(); |
560 } | 577 } |
561 | 578 |
562 void OnZipAnalysisFinished(const zip_analyzer::Results& results) { | 579 void OnZipAnalysisFinished(const zip_analyzer::Results& results) { |
563 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 580 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
564 DCHECK_EQ(ClientDownloadRequest::ZIPPED_EXECUTABLE, type_); | 581 DCHECK_EQ(ClientDownloadRequest::ZIPPED_EXECUTABLE, type_); |
565 if (!service_) | 582 if (!service_) |
566 return; | 583 return; |
567 if (results.success) { | 584 |
568 archived_executable_ = results.has_executable; | 585 // Even if !results.success, some of the zip may have been parsed. |
569 archived_binary_.CopyFrom(results.archived_binary); | 586 // Some unzippers will successfully unpack archives that we cannot, |
570 DVLOG(1) << "Zip analysis finished for " << item_->GetFullPath().value() | 587 // so we're lenient here. |
571 << ", has_executable=" << results.has_executable | 588 archive_is_valid_ = |
asanka
2015/11/18 21:37:55
By the way, what happens if our utility process cr
Nathan Parker
2015/11/20 06:22:16
I suspect the download would never complete, since
asanka
2015/11/20 15:55:40
I pointed out one crash bug, though I didn't look
| |
572 << " has_archive=" << results.has_archive; | 589 (results.success ? ArchiveValid::VALID : ArchiveValid::INVALID); |
573 } else { | 590 archived_executable_ = results.has_executable; |
574 DVLOG(1) << "Zip analysis failed for " << item_->GetFullPath().value(); | 591 archived_binary_.CopyFrom(results.archived_binary); |
575 } | 592 DVLOG(1) << "Zip analysis finished for " << item_->GetFullPath().value() |
593 << ", has_executable=" << results.has_executable | |
594 << ", has_archive=" << results.has_archive | |
595 << ", success=" << results.success; | |
596 | |
576 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileSuccess", results.success); | 597 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileSuccess", results.success); |
577 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileHasExecutable", | 598 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileHasExecutable", |
578 archived_executable_); | 599 archived_executable_); |
579 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileHasArchiveButNoExecutable", | 600 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileHasArchiveButNoExecutable", |
580 results.has_archive && !archived_executable_); | 601 results.has_archive && !archived_executable_); |
581 UMA_HISTOGRAM_TIMES("SBClientDownload.ExtractZipFeaturesTime", | 602 UMA_HISTOGRAM_TIMES("SBClientDownload.ExtractZipFeaturesTime", |
582 base::TimeTicks::Now() - zip_analysis_start_time_); | 603 base::TimeTicks::Now() - zip_analysis_start_time_); |
583 for (const auto& file_name : results.archived_archive_filenames) | 604 for (const auto& file_name : results.archived_archive_filenames) |
584 RecordArchivedArchiveFileExtensionType(file_name); | 605 RecordArchivedArchiveFileExtensionType(file_name); |
585 | 606 |
586 if (!archived_executable_ && !results.has_archive) { | 607 if (!archived_executable_) { |
587 PostFinishTask(UNKNOWN, REASON_ARCHIVE_WITHOUT_BINARIES); | 608 if (results.has_archive) { |
588 return; | 609 type_ = ClientDownloadRequest::ZIPPED_ARCHIVE; |
610 } else if (!results.success && CanReportInvalidArchives()) { | |
611 type_ = ClientDownloadRequest::INVALID_ZIP; | |
612 } else { | |
613 // Normal zip w/o EXEs, or invalid zip and not extended-reporting. | |
614 PostFinishTask(UNKNOWN, REASON_ARCHIVE_WITHOUT_BINARIES); | |
615 return; | |
616 } | |
589 } | 617 } |
590 | 618 |
591 if (!archived_executable_ && results.has_archive) | |
592 type_ = ClientDownloadRequest::ZIPPED_ARCHIVE; | |
593 OnFileFeatureExtractionDone(); | 619 OnFileFeatureExtractionDone(); |
594 } | 620 } |
595 | 621 |
596 #if defined(OS_MACOSX) | 622 #if defined(OS_MACOSX) |
597 void StartExtractDmgFeatures() { | 623 void StartExtractDmgFeatures() { |
598 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 624 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
599 DCHECK(item_); | 625 DCHECK(item_); |
600 dmg_analyzer_ = new SandboxedDMGAnalyzer( | 626 dmg_analyzer_ = new SandboxedDMGAnalyzer( |
601 item_->GetFullPath(), | 627 item_->GetFullPath(), |
602 base::Bind(&CheckClientDownloadRequest::OnDmgAnalysisFinished, | 628 base::Bind(&CheckClientDownloadRequest::OnDmgAnalysisFinished, |
603 weakptr_factory_.GetWeakPtr())); | 629 weakptr_factory_.GetWeakPtr())); |
604 dmg_analyzer_->Start(); | 630 dmg_analyzer_->Start(); |
605 dmg_analysis_start_time_ = base::TimeTicks::Now(); | 631 dmg_analysis_start_time_ = base::TimeTicks::Now(); |
606 } | 632 } |
607 | 633 |
608 void OnDmgAnalysisFinished(const zip_analyzer::Results& results) { | 634 void OnDmgAnalysisFinished(const zip_analyzer::Results& results) { |
609 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 635 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
610 DCHECK_EQ(ClientDownloadRequest::MAC_EXECUTABLE, type_); | 636 DCHECK_EQ(ClientDownloadRequest::MAC_EXECUTABLE, type_); |
611 if (!service_) | 637 if (!service_) |
612 return; | 638 return; |
613 | 639 |
614 if (results.success) { | 640 // Even if !results.success, some of the DMG may have been parsed. |
615 archived_executable_ = results.has_executable; | 641 archive_is_valid_ = |
616 archived_binary_.CopyFrom(results.archived_binary); | 642 (results.success ? ArchiveValid::VALID : ArchiveValid::INVALID); |
617 DVLOG(1) << "DMG analysis has finished for " | 643 archived_executable_ = results.has_executable; |
618 << item_->GetFullPath().value() << ", has_executable=" | 644 archived_binary_.CopyFrom(results.archived_binary); |
619 << results.has_executable; | 645 DVLOG(1) << "DMG analysis has finished for " << item_->GetFullPath().value() |
620 } else { | 646 << ", has_executable=" << results.has_executable |
621 DVLOG(1) << "DMG analysis failed for "<< item_->GetFullPath().value(); | 647 << ", success=" << results.success; |
622 } | |
623 | 648 |
624 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.DmgFileSuccess", results.success); | 649 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.DmgFileSuccess", results.success); |
625 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.DmgFileHasExecutable", | 650 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.DmgFileHasExecutable", |
626 archived_executable_); | 651 archived_executable_); |
627 UMA_HISTOGRAM_TIMES("SBClientDownload.ExtractDmgFeaturesTime", | 652 UMA_HISTOGRAM_TIMES("SBClientDownload.ExtractDmgFeaturesTime", |
628 base::TimeTicks::Now() - dmg_analysis_start_time_); | 653 base::TimeTicks::Now() - dmg_analysis_start_time_); |
629 | 654 |
630 if (!archived_executable_) { | 655 if (!archived_executable_) { |
631 PostFinishTask(UNKNOWN, REASON_ARCHIVE_WITHOUT_BINARIES); | 656 if (!results.success && CanReportInvalidArchives()) { |
632 return; | 657 type_ = ClientDownloadRequest::INVALID_MAC_ARCHIVE; |
658 } else { | |
659 PostFinishTask(UNKNOWN, REASON_ARCHIVE_WITHOUT_BINARIES); | |
660 return; | |
661 } | |
633 } | 662 } |
634 | 663 |
635 OnFileFeatureExtractionDone(); | 664 OnFileFeatureExtractionDone(); |
636 } | 665 } |
637 #endif // defined(OS_MACOSX) | 666 #endif // defined(OS_MACOSX) |
638 | 667 |
639 static void RecordCountOfSignedOrWhitelistedDownload() { | 668 static void RecordCountOfSignedOrWhitelistedDownload() { |
640 UMA_HISTOGRAM_COUNTS("SBClientDownload.SignedOrWhitelistedDownload", 1); | 669 UMA_HISTOGRAM_COUNTS("SBClientDownload.SignedOrWhitelistedDownload", 1); |
641 } | 670 } |
642 | 671 |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
805 if (tab_referrer_url_.is_valid()) { | 834 if (tab_referrer_url_.is_valid()) { |
806 resource->set_referrer(SanitizeUrl(tab_referrer_url_)); | 835 resource->set_referrer(SanitizeUrl(tab_referrer_url_)); |
807 DVLOG(2) << "tab referrer " << resource->referrer(); | 836 DVLOG(2) << "tab referrer " << resource->referrer(); |
808 } | 837 } |
809 } | 838 } |
810 | 839 |
811 request.set_user_initiated(item_->HasUserGesture()); | 840 request.set_user_initiated(item_->HasUserGesture()); |
812 request.set_file_basename( | 841 request.set_file_basename( |
813 item_->GetTargetFilePath().BaseName().AsUTF8Unsafe()); | 842 item_->GetTargetFilePath().BaseName().AsUTF8Unsafe()); |
814 request.set_download_type(type_); | 843 request.set_download_type(type_); |
844 if (archive_is_valid_ != ArchiveValid::UNSET) | |
845 request.set_archive_valid(archive_is_valid_ == ArchiveValid::VALID); | |
815 request.mutable_signature()->CopyFrom(signature_info_); | 846 request.mutable_signature()->CopyFrom(signature_info_); |
816 if (image_headers_) | 847 if (image_headers_) |
817 request.set_allocated_image_headers(image_headers_.release()); | 848 request.set_allocated_image_headers(image_headers_.release()); |
818 if (archived_executable_) | 849 if (archived_executable_) |
819 request.mutable_archived_binary()->Swap(&archived_binary_); | 850 request.mutable_archived_binary()->Swap(&archived_binary_); |
820 if (!request.SerializeToString(&client_download_request_data_)) { | 851 if (!request.SerializeToString(&client_download_request_data_)) { |
821 FinishRequest(UNKNOWN, REASON_INVALID_REQUEST_PROTO); | 852 FinishRequest(UNKNOWN, REASON_INVALID_REQUEST_PROTO); |
822 return; | 853 return; |
823 } | 854 } |
824 service_->client_download_request_callbacks_.Notify(item_, &request); | 855 service_->client_download_request_callbacks_.Notify(item_, &request); |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
929 << cert->subject().GetDisplayName() | 960 << cert->subject().GetDisplayName() |
930 << " issuer=" << issuer->subject().GetDisplayName(); | 961 << " issuer=" << issuer->subject().GetDisplayName(); |
931 return true; | 962 return true; |
932 } | 963 } |
933 } | 964 } |
934 cert = issuer; | 965 cert = issuer; |
935 } | 966 } |
936 return false; | 967 return false; |
937 } | 968 } |
938 | 969 |
970 enum class ArchiveValid { UNSET, VALID, INVALID }; | |
971 | |
939 // The DownloadItem we are checking. Will be NULL if the request has been | 972 // The DownloadItem we are checking. Will be NULL if the request has been |
940 // canceled. Must be accessed only on UI thread. | 973 // canceled. Must be accessed only on UI thread. |
941 content::DownloadItem* item_; | 974 content::DownloadItem* item_; |
942 // Copies of data from |item_| for access on other threads. | 975 // Copies of data from |item_| for access on other threads. |
943 std::vector<GURL> url_chain_; | 976 std::vector<GURL> url_chain_; |
944 GURL referrer_url_; | 977 GURL referrer_url_; |
945 // URL chain of redirects leading to (but not including) |tab_url|. | 978 // URL chain of redirects leading to (but not including) |tab_url|. |
946 std::vector<GURL> tab_redirects_; | 979 std::vector<GURL> tab_redirects_; |
947 // URL and referrer of the window the download was started from. | 980 // URL and referrer of the window the download was started from. |
948 GURL tab_url_; | 981 GURL tab_url_; |
949 GURL tab_referrer_url_; | 982 GURL tab_referrer_url_; |
950 | 983 |
951 bool archived_executable_; | 984 bool archived_executable_; |
985 ArchiveValid archive_is_valid_; | |
986 | |
952 ClientDownloadRequest_SignatureInfo signature_info_; | 987 ClientDownloadRequest_SignatureInfo signature_info_; |
953 scoped_ptr<ClientDownloadRequest_ImageHeaders> image_headers_; | 988 scoped_ptr<ClientDownloadRequest_ImageHeaders> image_headers_; |
954 google::protobuf::RepeatedPtrField<ClientDownloadRequest_ArchivedBinary> | 989 google::protobuf::RepeatedPtrField<ClientDownloadRequest_ArchivedBinary> |
955 archived_binary_; | 990 archived_binary_; |
956 CheckDownloadCallback callback_; | 991 CheckDownloadCallback callback_; |
957 // Will be NULL if the request has been canceled. | 992 // Will be NULL if the request has been canceled. |
958 DownloadProtectionService* service_; | 993 DownloadProtectionService* service_; |
959 scoped_refptr<BinaryFeatureExtractor> binary_feature_extractor_; | 994 scoped_refptr<BinaryFeatureExtractor> binary_feature_extractor_; |
960 scoped_refptr<SafeBrowsingDatabaseManager> database_manager_; | 995 scoped_refptr<SafeBrowsingDatabaseManager> database_manager_; |
961 const bool pingback_enabled_; | 996 const bool pingback_enabled_; |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1203 GURL DownloadProtectionService::GetDownloadRequestUrl() { | 1238 GURL DownloadProtectionService::GetDownloadRequestUrl() { |
1204 GURL url(kDownloadRequestUrl); | 1239 GURL url(kDownloadRequestUrl); |
1205 std::string api_key = google_apis::GetAPIKey(); | 1240 std::string api_key = google_apis::GetAPIKey(); |
1206 if (!api_key.empty()) | 1241 if (!api_key.empty()) |
1207 url = url.Resolve("?key=" + net::EscapeQueryParamValue(api_key, true)); | 1242 url = url.Resolve("?key=" + net::EscapeQueryParamValue(api_key, true)); |
1208 | 1243 |
1209 return url; | 1244 return url; |
1210 } | 1245 } |
1211 | 1246 |
1212 } // namespace safe_browsing | 1247 } // namespace safe_browsing |
OLD | NEW |