| 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/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
| 9 #include "base/format_macros.h" | 9 #include "base/format_macros.h" |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 FILE_PATH_LITERAL(".mshxml"), | 113 FILE_PATH_LITERAL(".mshxml"), |
| 114 FILE_PATH_LITERAL(".ps1"), | 114 FILE_PATH_LITERAL(".ps1"), |
| 115 FILE_PATH_LITERAL(".ps1xml"), | 115 FILE_PATH_LITERAL(".ps1xml"), |
| 116 FILE_PATH_LITERAL(".ps2"), | 116 FILE_PATH_LITERAL(".ps2"), |
| 117 FILE_PATH_LITERAL(".ps2xml"), | 117 FILE_PATH_LITERAL(".ps2xml"), |
| 118 FILE_PATH_LITERAL(".psc1"), | 118 FILE_PATH_LITERAL(".psc1"), |
| 119 FILE_PATH_LITERAL(".psc2"), | 119 FILE_PATH_LITERAL(".psc2"), |
| 120 FILE_PATH_LITERAL(".scf"), | 120 FILE_PATH_LITERAL(".scf"), |
| 121 FILE_PATH_LITERAL(".sct"), | 121 FILE_PATH_LITERAL(".sct"), |
| 122 FILE_PATH_LITERAL(".wsf"), | 122 FILE_PATH_LITERAL(".wsf"), |
| 123 FILE_PATH_LITERAL(".7z"), |
| 124 FILE_PATH_LITERAL(".xz"), |
| 125 FILE_PATH_LITERAL(".gz"), |
| 126 FILE_PATH_LITERAL(".tgz"), |
| 127 FILE_PATH_LITERAL(".bz2"), |
| 128 FILE_PATH_LITERAL(".tar"), |
| 129 FILE_PATH_LITERAL(".arj"), |
| 130 FILE_PATH_LITERAL(".lzh"), |
| 131 FILE_PATH_LITERAL(".lha"), |
| 132 FILE_PATH_LITERAL(".wim"), |
| 133 FILE_PATH_LITERAL(".z"), |
| 134 FILE_PATH_LITERAL(".lzma"), |
| 135 FILE_PATH_LITERAL(".cpio"), |
| 123 }; | 136 }; |
| 124 | 137 |
| 125 // UMA enumeration value for unrecognized file types. This is the array index of | 138 // UMA enumeration value for unrecognized file types. This is the array index of |
| 126 // the "Other" bucket in kDangerousFileTypes. | 139 // the "Other" bucket in kDangerousFileTypes. |
| 127 const int EXTENSION_OTHER = 18; | 140 const int EXTENSION_OTHER = 18; |
| 128 | 141 |
| 129 void RecordFileExtensionType(const base::FilePath& file) { | 142 // Maximum extension ID returned by GetExtensionTypeForUMA() + 1. |
| 143 const int EXTENSION_MAX = arraysize(kDangerousFileTypes); |
| 144 |
| 145 int GetExtensionTypeForUMA(const base::FilePath::StringType& extension) { |
| 130 DCHECK_EQ(static_cast<base::FilePath::CharType*>(nullptr), | 146 DCHECK_EQ(static_cast<base::FilePath::CharType*>(nullptr), |
| 131 kDangerousFileTypes[EXTENSION_OTHER]); | 147 kDangerousFileTypes[EXTENSION_OTHER]); |
| 148 DCHECK(extension.find(base::FilePath::kExtensionSeparator) == 0 || |
| 149 extension.empty()); |
| 150 DCHECK_EQ(extension, base::FilePath(extension).FinalExtension()); |
| 132 | 151 |
| 133 int extension_type = EXTENSION_OTHER; | 152 for (const auto& dangerous_extension : kDangerousFileTypes) { |
| 134 for (const auto& extension : kDangerousFileTypes) { | 153 if (dangerous_extension && |
| 135 if (extension && file.MatchesExtension(extension)) { | 154 base::FilePath::CompareEqualIgnoreCase(dangerous_extension, extension)) |
| 136 extension_type = &extension - kDangerousFileTypes; | 155 return &dangerous_extension - kDangerousFileTypes; |
| 137 break; | |
| 138 } | |
| 139 } | 156 } |
| 157 return EXTENSION_OTHER; |
| 158 } |
| 140 | 159 |
| 160 void RecordFileExtensionType(const base::FilePath& file) { |
| 141 UMA_HISTOGRAM_ENUMERATION("SBClientDownload.DownloadExtensions", | 161 UMA_HISTOGRAM_ENUMERATION("SBClientDownload.DownloadExtensions", |
| 142 extension_type, arraysize(kDangerousFileTypes)); | 162 GetExtensionTypeForUMA(file.FinalExtension()), |
| 163 EXTENSION_MAX); |
| 164 } |
| 165 |
| 166 void RecordArchivedArchiveFileExtensionType( |
| 167 const base::FilePath::StringType& extension) { |
| 168 UMA_HISTOGRAM_ENUMERATION("SBClientDownload.ArchivedArchiveExtensions", |
| 169 GetExtensionTypeForUMA(extension), EXTENSION_MAX); |
| 143 } | 170 } |
| 144 | 171 |
| 145 // Enumerate for histogramming purposes. | 172 // Enumerate for histogramming purposes. |
| 146 // DO NOT CHANGE THE ORDERING OF THESE VALUES (different histogram data will | 173 // DO NOT CHANGE THE ORDERING OF THESE VALUES (different histogram data will |
| 147 // be mixed together based on their values). | 174 // be mixed together based on their values). |
| 148 enum SBStatsType { | 175 enum SBStatsType { |
| 149 DOWNLOAD_URL_CHECKS_TOTAL, | 176 DOWNLOAD_URL_CHECKS_TOTAL, |
| 150 DOWNLOAD_URL_CHECKS_CANCELED, | 177 DOWNLOAD_URL_CHECKS_CANCELED, |
| 151 DOWNLOAD_URL_CHECKS_MALWARE, | 178 DOWNLOAD_URL_CHECKS_MALWARE, |
| 152 | 179 |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 495 ClientDownloadRequest::DownloadType* type) { | 522 ClientDownloadRequest::DownloadType* type) { |
| 496 if (item.GetUrlChain().empty()) { | 523 if (item.GetUrlChain().empty()) { |
| 497 *reason = REASON_EMPTY_URL_CHAIN; | 524 *reason = REASON_EMPTY_URL_CHAIN; |
| 498 return false; | 525 return false; |
| 499 } | 526 } |
| 500 const GURL& final_url = item.GetUrlChain().back(); | 527 const GURL& final_url = item.GetUrlChain().back(); |
| 501 if (!final_url.is_valid() || final_url.is_empty()) { | 528 if (!final_url.is_valid() || final_url.is_empty()) { |
| 502 *reason = REASON_INVALID_URL; | 529 *reason = REASON_INVALID_URL; |
| 503 return false; | 530 return false; |
| 504 } | 531 } |
| 505 if (!download_protection_util::IsBinaryFile(target_path)) { | 532 if (!download_protection_util::IsSupportedBinaryFile(target_path)) { |
| 506 *reason = REASON_NOT_BINARY_FILE; | 533 *reason = REASON_NOT_BINARY_FILE; |
| 507 return false; | 534 return false; |
| 508 } | 535 } |
| 509 if ((!final_url.IsStandard() && !final_url.SchemeIsBlob() && | 536 if ((!final_url.IsStandard() && !final_url.SchemeIsBlob() && |
| 510 !final_url.SchemeIs(url::kDataScheme)) || | 537 !final_url.SchemeIs(url::kDataScheme)) || |
| 511 final_url.SchemeIsFile()) { | 538 final_url.SchemeIsFile()) { |
| 512 *reason = REASON_UNSUPPORTED_URL_SCHEME; | 539 *reason = REASON_UNSUPPORTED_URL_SCHEME; |
| 513 return false; | 540 return false; |
| 514 } | 541 } |
| 515 *type = download_protection_util::GetDownloadType(target_path); | 542 *type = download_protection_util::GetDownloadType(target_path); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 594 // analyzer is refcounted, it might outlive the request. | 621 // analyzer is refcounted, it might outlive the request. |
| 595 analyzer_ = new SandboxedZipAnalyzer( | 622 analyzer_ = new SandboxedZipAnalyzer( |
| 596 item_->GetFullPath(), | 623 item_->GetFullPath(), |
| 597 base::Bind(&CheckClientDownloadRequest::OnZipAnalysisFinished, | 624 base::Bind(&CheckClientDownloadRequest::OnZipAnalysisFinished, |
| 598 weakptr_factory_.GetWeakPtr())); | 625 weakptr_factory_.GetWeakPtr())); |
| 599 analyzer_->Start(); | 626 analyzer_->Start(); |
| 600 } | 627 } |
| 601 | 628 |
| 602 void OnZipAnalysisFinished(const zip_analyzer::Results& results) { | 629 void OnZipAnalysisFinished(const zip_analyzer::Results& results) { |
| 603 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 630 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 631 DCHECK_EQ(ClientDownloadRequest::ZIPPED_EXECUTABLE, type_); |
| 604 if (!service_) | 632 if (!service_) |
| 605 return; | 633 return; |
| 606 if (results.success) { | 634 if (results.success) { |
| 607 zipped_executable_ = results.has_executable; | 635 zipped_executable_ = results.has_executable; |
| 608 archived_binary_.CopyFrom(results.archived_binary); | 636 archived_binary_.CopyFrom(results.archived_binary); |
| 609 DVLOG(1) << "Zip analysis finished for " << item_->GetFullPath().value() | 637 DVLOG(1) << "Zip analysis finished for " << item_->GetFullPath().value() |
| 610 << ", has_executable=" << results.has_executable | 638 << ", has_executable=" << results.has_executable |
| 611 << " has_archive=" << results.has_archive; | 639 << " has_archive=" << results.has_archive; |
| 612 } else { | 640 } else { |
| 613 DVLOG(1) << "Zip analysis failed for " << item_->GetFullPath().value(); | 641 DVLOG(1) << "Zip analysis failed for " << item_->GetFullPath().value(); |
| 614 } | 642 } |
| 615 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileHasExecutable", | 643 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileHasExecutable", |
| 616 zipped_executable_); | 644 zipped_executable_); |
| 617 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileHasArchiveButNoExecutable", | 645 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileHasArchiveButNoExecutable", |
| 618 results.has_archive && !zipped_executable_); | 646 results.has_archive && !zipped_executable_); |
| 619 UMA_HISTOGRAM_TIMES("SBClientDownload.ExtractZipFeaturesTime", | 647 UMA_HISTOGRAM_TIMES("SBClientDownload.ExtractZipFeaturesTime", |
| 620 base::TimeTicks::Now() - zip_analysis_start_time_); | 648 base::TimeTicks::Now() - zip_analysis_start_time_); |
| 649 for (const auto& file_extension : results.archived_archive_filetypes) |
| 650 RecordArchivedArchiveFileExtensionType(file_extension); |
| 621 | 651 |
| 622 if (!zipped_executable_) { | 652 if (!zipped_executable_ && !results.has_archive) { |
| 623 PostFinishTask(UNKNOWN, REASON_ARCHIVE_WITHOUT_BINARIES); | 653 PostFinishTask(UNKNOWN, REASON_ARCHIVE_WITHOUT_BINARIES); |
| 624 return; | 654 return; |
| 625 } | 655 } |
| 656 |
| 657 if (!zipped_executable_ && results.has_archive) |
| 658 type_ = ClientDownloadRequest::ZIPPED_ARCHIVE; |
| 626 OnFileFeatureExtractionDone(); | 659 OnFileFeatureExtractionDone(); |
| 627 } | 660 } |
| 628 | 661 |
| 629 static void RecordCountOfSignedOrWhitelistedDownload() { | 662 static void RecordCountOfSignedOrWhitelistedDownload() { |
| 630 UMA_HISTOGRAM_COUNTS("SBClientDownload.SignedOrWhitelistedDownload", 1); | 663 UMA_HISTOGRAM_COUNTS("SBClientDownload.SignedOrWhitelistedDownload", 1); |
| 631 } | 664 } |
| 632 | 665 |
| 633 void CheckWhitelists() { | 666 void CheckWhitelists() { |
| 634 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 667 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 635 | 668 |
| (...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1136 GURL DownloadProtectionService::GetDownloadRequestUrl() { | 1169 GURL DownloadProtectionService::GetDownloadRequestUrl() { |
| 1137 GURL url(kDownloadRequestUrl); | 1170 GURL url(kDownloadRequestUrl); |
| 1138 std::string api_key = google_apis::GetAPIKey(); | 1171 std::string api_key = google_apis::GetAPIKey(); |
| 1139 if (!api_key.empty()) | 1172 if (!api_key.empty()) |
| 1140 url = url.Resolve("?key=" + net::EscapeQueryParamValue(api_key, true)); | 1173 url = url.Resolve("?key=" + net::EscapeQueryParamValue(api_key, true)); |
| 1141 | 1174 |
| 1142 return url; | 1175 return url; |
| 1143 } | 1176 } |
| 1144 | 1177 |
| 1145 } // namespace safe_browsing | 1178 } // namespace safe_browsing |
| OLD | NEW |