15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/safe_browsing/download_protection_service.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/format_macros.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 1358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "base/metrics/sparse_histogram.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sequenced_task_runner_helpers.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/sequenced_worker_pool.h" 20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 21effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/history/history_service.h" 22effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/history/history_service_factory.h" 23effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/safe_browsing/binary_feature_extractor.h" 247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "chrome/browser/safe_browsing/download_feedback_service.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/safe_browsing/safe_browsing_service.h" 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/safe_browsing/sandboxed_zip_analyzer.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_list.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/safe_browsing/csd.pb.h" 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/safe_browsing/download_protection_util.h" 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/safe_browsing/zip_analyzer.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/download_item.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/page_navigator.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/google_api_keys.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/escape.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/load_flags.h" 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_cert_types.h" 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_certificate.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_status_code.h" 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_fetcher.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_fetcher_delegate.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_context_getter.h" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_status.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)static const int64 kDownloadRequestTimeoutMs = 7000; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace safe_browsing { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char DownloadProtectionService::kDownloadRequestUrl[] = 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "https://sb-ssl.google.com/safebrowsing/clientreport/download"; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// List of extensions for which we track some UMA stats. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum MaliciousExtensionType { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_EXE, 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_MSI, 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_CAB, 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_SYS, 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_SCR, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_DRV, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_BAT, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_ZIP, 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_RAR, 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_DLL, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_PIF, 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_COM, 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_JAR, 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_CLASS, 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_PDF, 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_VB, 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_REG, 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_GRP, 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_OTHER, // Groups all other extensions into one bucket. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_CRX, 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_APK, 82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXTENSION_DMG, 83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXTENSION_PKG, 846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) EXTENSION_TORRENT, 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_MAX, 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MaliciousExtensionType GetExtensionType(const base::FilePath& f) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (f.MatchesExtension(FILE_PATH_LITERAL(".exe"))) return EXTENSION_EXE; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (f.MatchesExtension(FILE_PATH_LITERAL(".msi"))) return EXTENSION_MSI; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (f.MatchesExtension(FILE_PATH_LITERAL(".cab"))) return EXTENSION_CAB; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (f.MatchesExtension(FILE_PATH_LITERAL(".sys"))) return EXTENSION_SYS; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (f.MatchesExtension(FILE_PATH_LITERAL(".scr"))) return EXTENSION_SCR; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (f.MatchesExtension(FILE_PATH_LITERAL(".drv"))) return EXTENSION_DRV; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (f.MatchesExtension(FILE_PATH_LITERAL(".bat"))) return EXTENSION_BAT; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (f.MatchesExtension(FILE_PATH_LITERAL(".zip"))) return EXTENSION_ZIP; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (f.MatchesExtension(FILE_PATH_LITERAL(".rar"))) return EXTENSION_RAR; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (f.MatchesExtension(FILE_PATH_LITERAL(".dll"))) return EXTENSION_DLL; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (f.MatchesExtension(FILE_PATH_LITERAL(".pif"))) return EXTENSION_PIF; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (f.MatchesExtension(FILE_PATH_LITERAL(".com"))) return EXTENSION_COM; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (f.MatchesExtension(FILE_PATH_LITERAL(".jar"))) return EXTENSION_JAR; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (f.MatchesExtension(FILE_PATH_LITERAL(".class"))) return EXTENSION_CLASS; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (f.MatchesExtension(FILE_PATH_LITERAL(".pdf"))) return EXTENSION_PDF; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (f.MatchesExtension(FILE_PATH_LITERAL(".vb"))) return EXTENSION_VB; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (f.MatchesExtension(FILE_PATH_LITERAL(".reg"))) return EXTENSION_REG; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (f.MatchesExtension(FILE_PATH_LITERAL(".grp"))) return EXTENSION_GRP; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (f.MatchesExtension(FILE_PATH_LITERAL(".crx"))) return EXTENSION_CRX; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (f.MatchesExtension(FILE_PATH_LITERAL(".apk"))) return EXTENSION_APK; 109010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (f.MatchesExtension(FILE_PATH_LITERAL(".dmg"))) return EXTENSION_DMG; 110010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (f.MatchesExtension(FILE_PATH_LITERAL(".pkg"))) return EXTENSION_PKG; 1116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (f.MatchesExtension(FILE_PATH_LITERAL(".torrent"))) 1126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return EXTENSION_TORRENT; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return EXTENSION_OTHER; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RecordFileExtensionType(const base::FilePath& file) { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("SBClientDownload.DownloadExtensions", 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetExtensionType(file), 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_MAX); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Enumerate for histogramming purposes. 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DO NOT CHANGE THE ORDERING OF THESE VALUES (different histogram data will 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be mixed together based on their values). 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum SBStatsType { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DOWNLOAD_URL_CHECKS_TOTAL, 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DOWNLOAD_URL_CHECKS_CANCELED, 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DOWNLOAD_URL_CHECKS_MALWARE, 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DOWNLOAD_HASH_CHECKS_TOTAL, 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DOWNLOAD_HASH_CHECKS_MALWARE, 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Memory space for histograms is determined by the max. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ALWAYS ADD NEW VALUES BEFORE THIS ONE. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DOWNLOAD_CHECKS_MAX 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Parent SafeBrowsing::Client class used to lookup the bad binary 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// URL and digest list. There are two sub-classes (one for each list). 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DownloadSBClient 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : public SafeBrowsingDatabaseManager::Client, 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public base::RefCountedThreadSafe<DownloadSBClient> { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadSBClient( 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const content::DownloadItem& item, 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DownloadProtectionService::CheckDownloadCallback& callback, 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const scoped_refptr<SafeBrowsingUIManager>& ui_manager, 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SBStatsType total_type, 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SBStatsType dangerous_type) 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : sha256_hash_(item.GetHash()), 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_chain_(item.GetUrlChain()), 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) referrer_url_(item.GetReferrerUrl()), 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_(callback), 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui_manager_(ui_manager), 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_time_(base::TimeTicks::Now()), 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_type_(total_type), 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dangerous_type_(dangerous_type) {} 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void StartCheck() = 0; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool IsDangerous(SBThreatType threat_type) const = 0; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class base::RefCountedThreadSafe<DownloadSBClient>; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~DownloadSBClient() {} 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void CheckDone(SBThreatType threat_type) { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadProtectionService::DownloadCheckResult result = 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IsDangerous(threat_type) ? 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadProtectionService::DANGEROUS : 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadProtectionService::SAFE; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::UI, 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(callback_, result)); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateDownloadCheckStats(total_type_); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (threat_type != SB_THREAT_TYPE_SAFE) { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateDownloadCheckStats(dangerous_type_); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::UI, 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&DownloadSBClient::ReportMalware, 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, threat_type)); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ReportMalware(SBThreatType threat_type) { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string post_data; 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!sha256_hash_.empty()) 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) post_data += base::HexEncode(sha256_hash_.data(), 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sha256_hash_.size()) + "\n"; 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < url_chain_.size(); ++i) { 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) post_data += url_chain_[i].spec() + "\n"; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui_manager_->ReportSafeBrowsingHit( 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_chain_.back(), // malicious_url 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_chain_.front(), // page_url 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) referrer_url_, 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true, // is_subresource 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) threat_type, 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) post_data); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void UpdateDownloadCheckStats(SBStatsType stat_type) { 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("SB2.DownloadChecks", 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stat_type, 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DOWNLOAD_CHECKS_MAX); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string sha256_hash_; 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<GURL> url_chain_; 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL referrer_url_; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadProtectionService::CheckDownloadCallback callback_; 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<SafeBrowsingUIManager> ui_manager_; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks start_time_; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SBStatsType total_type_; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SBStatsType dangerous_type_; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(DownloadSBClient); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DownloadUrlSBClient : public DownloadSBClient { 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadUrlSBClient( 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const content::DownloadItem& item, 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DownloadProtectionService::CheckDownloadCallback& callback, 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const scoped_refptr<SafeBrowsingUIManager>& ui_manager, 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const scoped_refptr<SafeBrowsingDatabaseManager>& database_manager) 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : DownloadSBClient(item, callback, ui_manager, 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DOWNLOAD_URL_CHECKS_TOTAL, 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DOWNLOAD_URL_CHECKS_MALWARE), 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) database_manager_(database_manager) { } 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void StartCheck() OVERRIDE { 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!database_manager_.get() || 238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) database_manager_->CheckDownloadUrl(url_chain_, this)) { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckDone(SB_THREAT_TYPE_SAFE); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddRef(); // SafeBrowsingService takes a pointer not a scoped_refptr. 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool IsDangerous(SBThreatType threat_type) const OVERRIDE { 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return threat_type == SB_THREAT_TYPE_BINARY_MALWARE_URL; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnCheckDownloadUrlResult(const std::vector<GURL>& url_chain, 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SBThreatType threat_type) OVERRIDE { 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckDone(threat_type); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("SB2.DownloadUrlCheckDuration", 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks::Now() - start_time_); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Release(); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~DownloadUrlSBClient() {} 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<SafeBrowsingDatabaseManager> database_manager_; 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(DownloadUrlSBClient); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DownloadProtectionService::CheckClientDownloadRequest 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public base::RefCountedThreadSafe< 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadProtectionService::CheckClientDownloadRequest, 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::DeleteOnUIThread>, 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public net::URLFetcherDelegate, 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public content::DownloadItem::Observer { 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CheckClientDownloadRequest( 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::DownloadItem* item, 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CheckDownloadCallback& callback, 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DownloadProtectionService* service, 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const scoped_refptr<SafeBrowsingDatabaseManager>& database_manager, 278effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch BinaryFeatureExtractor* binary_feature_extractor) 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : item_(item), 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_chain_(item->GetUrlChain()), 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) referrer_url_(item->GetReferrerUrl()), 282effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch tab_url_(item->GetTabUrl()), 283effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch tab_referrer_url_(item->GetTabReferrerUrl()), 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) zipped_executable_(false), 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_(callback), 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service_(service), 287effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch binary_feature_extractor_(binary_feature_extractor), 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) database_manager_(database_manager), 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pingback_enabled_(service_->enabled()), 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) finished_(false), 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type_(ClientDownloadRequest::WIN_EXECUTABLE), 292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weakptr_factory_(this), 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_time_(base::TimeTicks::Now()) { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item_->AddObserver(this); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Start() { 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << "Starting SafeBrowsing download check for: " 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << item_->DebugString(true); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(noelutz): implement some cache to make sure we don't issue the same 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // request over and over again if a user downloads the same binary multiple 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // times. 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadCheckResultReason reason = REASON_MAX; 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!IsSupportedDownload( 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *item_, item_->GetTargetFilePath(), &reason, &type_)) { 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (reason) { 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case REASON_EMPTY_URL_CHAIN: 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case REASON_INVALID_URL: 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PostFinishTask(SAFE, reason); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case REASON_NOT_BINARY_FILE: 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RecordFileExtensionType(item_->GetTargetFilePath()); 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PostFinishTask(SAFE, reason); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We only expect the reasons explicitly handled above. 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RecordFileExtensionType(item_->GetTargetFilePath()); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compute features from the file contents. Note that we record histograms 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // based on the result, so this runs regardless of whether the pingbacks 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // are enabled. 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (item_->GetTargetFilePath().MatchesExtension( 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FILE_PATH_LITERAL(".zip"))) { 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StartExtractZipFeatures(); 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!download_protection_util::IsArchiveFile( 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item_->GetTargetFilePath())); 335effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch StartExtractFileFeatures(); 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start a timeout to cancel the request if it takes too long. 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This should only be called after we have finished accessing the file. 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StartTimeout() { 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!service_) { 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Request has already been cancelled. 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 34746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) timeout_start_time_ = base::TimeTicks::Now(); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostDelayedTask( 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::UI, 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CheckClientDownloadRequest::Cancel, 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) weakptr_factory_.GetWeakPtr()), 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds( 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service_->download_request_timeout_ms())); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Canceling a request will cause us to always report the result as SAFE 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unless a pending request is about to call FinishRequest. 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Cancel() { 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fetcher_.get()) { 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The DownloadProtectionService is going to release its reference, so we 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // might be destroyed before the URLFetcher completes. Cancel the 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fetcher so it does not try to invoke OnURLFetchComplete. 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: If there is no fetcher, then some callback is still holding a 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reference to this object. We'll eventually wind up in some method on 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the UI thread that will call FinishRequest() again. If FinishRequest() 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is called a second time, it will be a no-op. 37190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) FinishRequest(SAFE, REASON_REQUEST_CANCELED); 37290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Calling FinishRequest might delete this object, we may be deleted by 37390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // this point. 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // content::DownloadItem::Observer implementation. 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnDownloadDestroyed(content::DownloadItem* download) OVERRIDE { 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Cancel(); 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(item_ == NULL); 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // From the net::URLFetcherDelegate interface. 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE { 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(source, fetcher_.get()); 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << "Received a response for URL: " 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << item_->GetUrlChain().back() << ": success=" 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << source->GetStatus().is_success() << " response_code=" 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << source->GetResponseCode(); 39058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch if (source->GetStatus().is_success()) { 39158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch UMA_HISTOGRAM_SPARSE_SLOWLY( 39258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch "SBClientDownload.DownloadRequestResponseCode", 39358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch source->GetResponseCode()); 39458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch } 39558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch UMA_HISTOGRAM_SPARSE_SLOWLY( 39658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch "SBClientDownload.DownloadRequestNetError", 39758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch -source->GetStatus().error()); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadCheckResultReason reason = REASON_SERVER_PING_FAILED; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadCheckResult result = SAFE; 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (source->GetStatus().is_success() && 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::HTTP_OK == source->GetResponseCode()) { 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientDownloadResponse response; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string data; 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool got_data = source->GetResponseAsString(&data); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(got_data); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!response.ParseFromString(data)) { 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reason = REASON_INVALID_RESPONSE_PROTO; 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (response.verdict() == ClientDownloadResponse::SAFE) { 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reason = REASON_DOWNLOAD_SAFE; 4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (service_ && !service_->IsSupportedDownload( 4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *item_, item_->GetTargetFilePath())) { 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The client of the download protection service assumes that we don't 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // support this download so we cannot return any other verdict than 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SAFE even if the server says it's dangerous to download this file. 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: if service_ is NULL we already cancelled the request and 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // returned SAFE. 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reason = REASON_DOWNLOAD_NOT_SUPPORTED; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (response.verdict() == ClientDownloadResponse::DANGEROUS) { 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reason = REASON_DOWNLOAD_DANGEROUS; 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = DANGEROUS; 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (response.verdict() == ClientDownloadResponse::UNCOMMON) { 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reason = REASON_DOWNLOAD_UNCOMMON; 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = UNCOMMON; 4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (response.verdict() == ClientDownloadResponse::DANGEROUS_HOST) { 4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reason = REASON_DOWNLOAD_DANGEROUS_HOST; 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) result = DANGEROUS_HOST; 427a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch } else if ( 428a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch response.verdict() == ClientDownloadResponse::POTENTIALLY_UNWANTED) { 429a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch reason = REASON_DOWNLOAD_POTENTIALLY_UNWANTED; 430a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch result = POTENTIALLY_UNWANTED; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Unknown download response verdict: " 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << response.verdict(); 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reason = REASON_INVALID_RESPONSE_VERDICT; 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) DownloadFeedbackService::MaybeStorePingsForDownload( 4377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) result, item_, client_download_request_data_, data); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't need the fetcher anymore. 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("SBClientDownload.DownloadRequestDuration", 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks::Now() - start_time_); 44346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) UMA_HISTOGRAM_TIMES("SBClientDownload.DownloadRequestNetworkDuration", 44446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::TimeTicks::Now() - request_start_time_); 4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FinishRequest(result, reason); 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static bool IsSupportedDownload(const content::DownloadItem& item, 4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& target_path, 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadCheckResultReason* reason, 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientDownloadRequest::DownloadType* type) { 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (item.GetUrlChain().empty()) { 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *reason = REASON_EMPTY_URL_CHAIN; 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& final_url = item.GetUrlChain().back(); 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!final_url.is_valid() || final_url.is_empty() || 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !final_url.IsStandard() || final_url.SchemeIsFile()) { 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *reason = REASON_INVALID_URL; 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!download_protection_util::IsBinaryFile(target_path)) { 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *reason = REASON_NOT_BINARY_FILE; 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 466bee9932bab44713b74b422b4b759b49f5a222977Bo Liu *type = download_protection_util::GetDownloadType(target_path); 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class base::DeleteHelper<CheckClientDownloadRequest>; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~CheckClientDownloadRequest() { 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(item_ == NULL); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void OnFileFeatureExtractionDone() { 4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This can run in any thread, since it just posts more messages. 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(noelutz): DownloadInfo should also contain the IP address of 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // every URL in the redirect chain. We also should check whether the 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // download URL is hosted on the internal network. 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::IO, 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CheckClientDownloadRequest::CheckWhitelists, this)); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We wait until after the file checks finish to start the timeout, as 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // windows can cause permissions errors if the timeout fired while we were 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // checking the file signature and we tried to complete the download. 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::UI, 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CheckClientDownloadRequest::StartTimeout, this)); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 499effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch void StartExtractFileFeatures() { 5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(item_); // Called directly from Start(), item should still exist. 5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Since we do blocking I/O, offload this to a worker thread. 5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The task does not need to block shutdown. 5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::GetBlockingPool()->PostWorkerTaskWithShutdownBehavior( 5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 506effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::Bind(&CheckClientDownloadRequest::ExtractFileFeatures, 5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, item_->GetFullPath()), 5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); 5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 511effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch void ExtractFileFeatures(const base::FilePath& file_path) { 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks start_time = base::TimeTicks::Now(); 513effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch binary_feature_extractor_->CheckSignature(file_path, &signature_info_); 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_signed = (signature_info_.certificate_chain_size() > 0); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_signed) { 5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VLOG(2) << "Downloaded a signed binary: " << file_path.value(); 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VLOG(2) << "Downloaded an unsigned binary: " 5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << file_path.value(); 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("SBClientDownload.SignedBinaryDownload", is_signed); 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("SBClientDownload.ExtractSignatureFeaturesTime", 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks::Now() - start_time); 5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 525effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch start_time = base::TimeTicks::Now(); 526effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch binary_feature_extractor_->ExtractImageHeaders(file_path, &image_headers_); 527effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch UMA_HISTOGRAM_TIMES("SBClientDownload.ExtractImageHeadersTime", 528effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::TimeTicks::Now() - start_time); 529effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnFileFeatureExtractionDone(); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void StartExtractZipFeatures() { 5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(item_); // Called directly from Start(), item should still exist. 5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) zip_analysis_start_time_ = base::TimeTicks::Now(); 5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We give the zip analyzer a weak pointer to this object. Since the 5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // analyzer is refcounted, it might outlive the request. 5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) analyzer_ = new SandboxedZipAnalyzer( 5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item_->GetFullPath(), 5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&CheckClientDownloadRequest::OnZipAnalysisFinished, 5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) weakptr_factory_.GetWeakPtr())); 5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) analyzer_->Start(); 5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void OnZipAnalysisFinished(const zip_analyzer::Results& results) { 5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!service_) 5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (results.success) { 5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) zipped_executable_ = results.has_executable; 5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VLOG(1) << "Zip analysis finished for " << item_->GetFullPath().value() 5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << ", has_executable=" << results.has_executable 5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << " has_archive=" << results.has_archive; 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VLOG(1) << "Zip analysis failed for " << item_->GetFullPath().value(); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileHasExecutable", 5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) zipped_executable_); 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileHasArchiveButNoExecutable", 5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) results.has_archive && !zipped_executable_); 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("SBClientDownload.ExtractZipFeaturesTime", 5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks::Now() - zip_analysis_start_time_); 5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!zipped_executable_) { 5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PostFinishTask(SAFE, REASON_ARCHIVE_WITHOUT_BINARIES); 5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnFileFeatureExtractionDone(); 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void CheckWhitelists() { 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadCheckResultReason reason = REASON_MAX; 575868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!database_manager_.get()) { 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reason = REASON_SB_DISABLED; 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const GURL& url = url_chain_.back(); 5795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (url.is_valid() && database_manager_->MatchDownloadWhitelistUrl(url)) { 5805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VLOG(2) << url << " is on the download whitelist."; 5815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reason = REASON_WHITELISTED_URL; 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (reason != REASON_MAX || signature_info_.trusted()) { 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("SBClientDownload.SignedOrWhitelistedDownload", 1); 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (reason == REASON_MAX && signature_info_.trusted()) { 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < signature_info_.certificate_chain_size(); ++i) { 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CertificateChainIsWhitelisted( 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signature_info_.certificate_chain(i))) { 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reason = REASON_TRUSTED_EXECUTABLE; 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (reason != REASON_MAX) { 5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PostFinishTask(SAFE, reason); 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!pingback_enabled_) { 5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PostFinishTask(SAFE, REASON_PING_DISABLED); 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Currently, the UI only works on Windows so we don't even bother 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with pinging the server if we're not on Windows. TODO(noelutz): 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // change this code once the UI is done for Linux and Mac. 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The URLFetcher is owned by the UI thread, so post a message to 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // start the pingback. 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::UI, 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 610effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::Bind(&CheckClientDownloadRequest::GetTabRedirects, this)); 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PostFinishTask(SAFE, REASON_OS_NOT_SUPPORTED); 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 617effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch void GetTabRedirects() { 618effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 619effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!tab_url_.is_valid()) { 620effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch SendRequest(); 621effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 622effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 623effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 624effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch Profile* profile = Profile::FromBrowserContext(item_->GetBrowserContext()); 625effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch HistoryService* history = 626effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch HistoryServiceFactory::GetForProfile(profile, Profile::EXPLICIT_ACCESS); 627effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!history) { 628effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch SendRequest(); 629effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 630effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 631effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 632effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch history->QueryRedirectsTo( 633effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch tab_url_, 634effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch &request_consumer_, 635effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::Bind(&CheckClientDownloadRequest::OnGotTabRedirects, 636effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::Unretained(this))); 637effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 638effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 639effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch void OnGotTabRedirects(HistoryService::Handle handle, 640effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch GURL url, 641effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch bool success, 642effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch history::RedirectList* redirect_list) { 643effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 644effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_EQ(url, tab_url_); 645effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 646effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (success && redirect_list->size() > 0) { 647effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (history::RedirectList::reverse_iterator i = redirect_list->rbegin(); 648effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch i != redirect_list->rend(); 649effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ++i) { 650effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch tab_redirects_.push_back(*i); 651effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 652effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 653effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 654effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch SendRequest(); 655effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 656effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SendRequest() { 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is our last chance to check whether the request has been canceled 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // before sending it. 6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!service_) 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientDownloadRequest request; 6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request.set_url(item_->GetUrlChain().back().spec()); 6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request.mutable_digests()->set_sha256(item_->GetHash()); 6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request.set_length(item_->GetReceivedBytes()); 6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < item_->GetUrlChain().size(); ++i) { 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientDownloadRequest::Resource* resource = request.add_resources(); 6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) resource->set_url(item_->GetUrlChain()[i].spec()); 6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (i == item_->GetUrlChain().size() - 1) { 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The last URL in the chain is the download URL. 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resource->set_type(ClientDownloadRequest::DOWNLOAD_URL); 6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) resource->set_referrer(item_->GetReferrerUrl().spec()); 676effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DVLOG(2) << "dl url " << resource->url(); 6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!item_->GetRemoteAddress().empty()) { 6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) resource->set_remote_ip(item_->GetRemoteAddress()); 679effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DVLOG(2) << " dl url remote addr: " << resource->remote_ip(); 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 681effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DVLOG(2) << "dl referrer " << resource->referrer(); 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 683effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DVLOG(2) << "dl redirect " << i << " " << resource->url(); 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resource->set_type(ClientDownloadRequest::DOWNLOAD_REDIRECT); 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(noelutz): fill out the remote IP addresses. 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 688effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // TODO(mattm): fill out the remote IP addresses for tab resources. 689effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (size_t i = 0; i < tab_redirects_.size(); ++i) { 690effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ClientDownloadRequest::Resource* resource = request.add_resources(); 691effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DVLOG(2) << "tab redirect " << i << " " << tab_redirects_[i].spec(); 692effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch resource->set_url(tab_redirects_[i].spec()); 693effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch resource->set_type(ClientDownloadRequest::TAB_REDIRECT); 694effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 695effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (tab_url_.is_valid()) { 696effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ClientDownloadRequest::Resource* resource = request.add_resources(); 697effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch resource->set_url(tab_url_.spec()); 698effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DVLOG(2) << "tab url " << resource->url(); 699effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch resource->set_type(ClientDownloadRequest::TAB_URL); 700effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (tab_referrer_url_.is_valid()) { 701effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch resource->set_referrer(tab_referrer_url_.spec()); 702effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DVLOG(2) << "tab referrer " << resource->referrer(); 703effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 704effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 705effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request.set_user_initiated(item_->HasUserGesture()); 7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request.set_file_basename( 7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item_->GetTargetFilePath().BaseName().AsUTF8Unsafe()); 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.set_download_type(type_); 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.mutable_signature()->CopyFrom(signature_info_); 711effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch request.mutable_image_headers()->CopyFrom(image_headers_); 7127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!request.SerializeToString(&client_download_request_data_)) { 7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FinishRequest(SAFE, REASON_INVALID_REQUEST_PROTO); 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << "Sending a request for URL: " 7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << item_->GetUrlChain().back(); 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_.reset(net::URLFetcher::Create(0 /* ID used for testing */, 7204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) GetDownloadRequestUrl(), 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLFetcher::POST, 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE); 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->SetAutomaticallyRetryOn5xx(false); // Don't retry on error. 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->SetRequestContext(service_->request_context_getter_.get()); 7267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) fetcher_->SetUploadData("application/octet-stream", 7277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) client_download_request_data_); 72846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) request_start_time_ = base::TimeTicks::Now(); 729a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("SBClientDownload.DownloadRequestPayloadSize", 730a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) client_download_request_data_.size()); 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher_->Start(); 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void PostFinishTask(DownloadCheckResult result, 7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DownloadCheckResultReason reason) { 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::UI, 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&CheckClientDownloadRequest::FinishRequest, this, result, 7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reason)); 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void FinishRequest(DownloadCheckResult result, 7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DownloadCheckResultReason reason) { 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (finished_) { 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) finished_ = true; 75090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Ensure the timeout task is cancelled while we still have a non-zero 75190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // refcount. (crbug.com/240449) 75290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) weakptr_factory_.InvalidateWeakPtrs(); 75346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!request_start_time_.is_null()) { 75446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("SBClientDownload.DownloadRequestNetworkStats", 75546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) reason, 75646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) REASON_MAX); 75746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 75846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!timeout_start_time_.is_null()) { 75946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("SBClientDownload.DownloadRequestTimeoutStats", 76046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) reason, 76146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) REASON_MAX); 76246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (reason != REASON_REQUEST_CANCELED) { 76346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) UMA_HISTOGRAM_TIMES("SBClientDownload.DownloadRequestTimeoutDuration", 76446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::TimeTicks::Now() - timeout_start_time_); 76546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 76646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (service_) { 7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VLOG(2) << "SafeBrowsing download verdict for: " 7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << item_->DebugString(true) << " verdict:" << reason; 7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("SBClientDownload.CheckDownloadStats", 7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reason, 7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) REASON_MAX); 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_.Run(result); 7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item_->RemoveObserver(this); 7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) item_ = NULL; 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadProtectionService* service = service_; 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service_ = NULL; 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service->RequestFinished(this); 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DownloadProtectionService::RequestFinished will decrement our refcount, 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // so we may be deleted now. 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_.Run(SAFE); 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool CertificateChainIsWhitelisted( 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ClientDownloadRequest_CertificateChain& chain) { 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (chain.element_size() < 2) { 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need to have both a signing certificate and its issuer certificate 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // present to construct a whitelist entry. 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<net::X509Certificate> cert = 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::X509Certificate::CreateFromBytes( 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chain.element(0).certificate().data(), 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chain.element(0).certificate().size()); 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cert.get()) { 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 1; i < chain.element_size(); ++i) { 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<net::X509Certificate> issuer = 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::X509Certificate::CreateFromBytes( 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chain.element(i).certificate().data(), 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chain.element(i).certificate().size()); 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!issuer.get()) { 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string> whitelist_strings; 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadProtectionService::GetCertificateWhitelistStrings( 812868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *cert.get(), *issuer.get(), &whitelist_strings); 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t j = 0; j < whitelist_strings.size(); ++j) { 8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (database_manager_->MatchDownloadWhitelistString( 8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) whitelist_strings[j])) { 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << "Certificate matched whitelist, cert=" 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << cert->subject().GetDisplayName() 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " issuer=" << issuer->subject().GetDisplayName(); 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert = issuer; 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The DownloadItem we are checking. Will be NULL if the request has been 8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // canceled. Must be accessed only on UI thread. 8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::DownloadItem* item_; 8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Copies of data from |item_| for access on other threads. 8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<GURL> url_chain_; 8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL referrer_url_; 833effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // URL chain of redirects leading to (but not including) |tab_url|. 834effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::vector<GURL> tab_redirects_; 835effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // URL and referrer of the window the download was started from. 836effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch GURL tab_url_; 837effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch GURL tab_referrer_url_; 8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool zipped_executable_; 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientDownloadRequest_SignatureInfo signature_info_; 841effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ClientDownloadRequest_ImageHeaders image_headers_; 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckDownloadCallback callback_; 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Will be NULL if the request has been canceled. 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadProtectionService* service_; 845effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_refptr<BinaryFeatureExtractor> binary_feature_extractor_; 8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<SafeBrowsingDatabaseManager> database_manager_; 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool pingback_enabled_; 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<net::URLFetcher> fetcher_; 8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<SandboxedZipAnalyzer> analyzer_; 8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks zip_analysis_start_time_; 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool finished_; 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientDownloadRequest::DownloadType type_; 8537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) std::string client_download_request_data_; 854effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch CancelableRequestConsumer request_consumer_; // For HistoryService lookup. 8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::WeakPtrFactory<CheckClientDownloadRequest> weakptr_factory_; 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks start_time_; // Used for stats. 85746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::TimeTicks timeout_start_time_; 85846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::TimeTicks request_start_time_; 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(CheckClientDownloadRequest); 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DownloadProtectionService::DownloadProtectionService( 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SafeBrowsingService* sb_service, 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequestContextGetter* request_context_getter) 8662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : request_context_getter_(request_context_getter), 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enabled_(false), 868effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch binary_feature_extractor_(new BinaryFeatureExtractor()), 8697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) download_request_timeout_ms_(kDownloadRequestTimeoutMs), 8707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) feedback_service_(new DownloadFeedbackService( 8717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) request_context_getter, BrowserThread::GetBlockingPool())) { 8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (sb_service) { 8742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui_manager_ = sb_service->ui_manager(); 8752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) database_manager_ = sb_service->database_manager(); 8762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DownloadProtectionService::~DownloadProtectionService() { 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelPendingRequests(); 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadProtectionService::SetEnabled(bool enabled) { 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (enabled == enabled_) { 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enabled_ = enabled; 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!enabled_) { 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelPendingRequests(); 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadProtectionService::CheckClientDownload( 8962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::DownloadItem* item, 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CheckDownloadCallback& callback) { 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<CheckClientDownloadRequest> request( 8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new CheckClientDownloadRequest(item, callback, this, 900effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch database_manager_, 901effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch binary_feature_extractor_.get())); 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) download_requests_.insert(request); 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->Start(); 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadProtectionService::CheckDownloadUrl( 9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const content::DownloadItem& item, 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CheckDownloadCallback& callback) { 9092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!item.GetUrlChain().empty()); 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<DownloadUrlSBClient> client( 9112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new DownloadUrlSBClient(item, callback, ui_manager_, database_manager_)); 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The client will release itself once it is done. 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::IO, 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&DownloadUrlSBClient::StartCheck, client)); 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DownloadProtectionService::IsSupportedDownload( 9202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const content::DownloadItem& item, 9212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& target_path) const { 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Currently, the UI only works on Windows. On Linux and Mac we still 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // want to show the dangerous file type warning if the file is possibly 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dangerous which means we have to always return false here. 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadCheckResultReason reason = REASON_MAX; 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientDownloadRequest::DownloadType type = 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientDownloadRequest::WIN_EXECUTABLE; 9292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return (CheckClientDownloadRequest::IsSupportedDownload(item, target_path, 9302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &reason, &type) && 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (ClientDownloadRequest::ANDROID_APK == type || 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientDownloadRequest::WIN_EXECUTABLE == type || 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientDownloadRequest::ZIPPED_EXECUTABLE == type)); 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadProtectionService::CancelPendingRequests() { 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<scoped_refptr<CheckClientDownloadRequest> >::iterator it = 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) download_requests_.begin(); 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != download_requests_.end();) { 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need to advance the iterator before we cancel because canceling 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the request will invalidate it when RequestFinished is called below. 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<CheckClientDownloadRequest> tmp = *it++; 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tmp->Cancel(); 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(download_requests_.empty()); 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadProtectionService::RequestFinished( 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckClientDownloadRequest* request) { 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<scoped_refptr<CheckClientDownloadRequest> >::iterator it = 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) download_requests_.find(request); 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(it != download_requests_.end()); 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) download_requests_.erase(*it); 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadProtectionService::ShowDetailsForDownload( 9622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const content::DownloadItem& item, 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageNavigator* navigator) { 964a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch GURL learn_more_url(chrome::kDownloadScanningLearnMoreURL); 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) navigator->OpenURL( 966a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch content::OpenURLParams(learn_more_url, 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Referrer(), 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NEW_FOREGROUND_TAB, 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PAGE_TRANSITION_LINK, 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false)); 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Escapes a certificate attribute so that it can be used in a whitelist 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// entry. Currently, we only escape slashes, since they are used as a 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// separator between attributes. 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string EscapeCertAttribute(const std::string& attribute) { 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string escaped; 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < attribute.size(); ++i) { 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (attribute[i] == '%') { 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) escaped.append("%25"); 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (attribute[i] == '/') { 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) escaped.append("%2F"); 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) escaped.push_back(attribute[i]); 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return escaped; 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadProtectionService::GetCertificateWhitelistStrings( 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::X509Certificate& certificate, 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::X509Certificate& issuer, 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string>* whitelist_strings) { 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The whitelist paths are in the format: 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cert/<ascii issuer fingerprint>[/CN=common_name][/O=org][/OU=unit] 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Any of CN, O, or OU may be omitted from the whitelist entry, in which 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // case they match anything. However, the attributes that do appear will 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // always be in the order shown above. At least one attribute will always 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be present. 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::CertPrincipal& subject = certificate.subject(); 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string> ou_tokens; 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < subject.organization_unit_names.size(); ++i) { 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ou_tokens.push_back( 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "/OU=" + EscapeCertAttribute(subject.organization_unit_names[i])); 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string> o_tokens; 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < subject.organization_names.size(); ++i) { 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) o_tokens.push_back( 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "/O=" + EscapeCertAttribute(subject.organization_names[i])); 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string cn_token; 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!subject.common_name.empty()) { 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cn_token = "/CN=" + EscapeCertAttribute(subject.common_name); 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<std::string> paths_to_check; 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cn_token.empty()) { 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths_to_check.insert(cn_token); 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < o_tokens.size(); ++i) { 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths_to_check.insert(cn_token + o_tokens[i]); 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths_to_check.insert(o_tokens[i]); 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t j = 0; j < ou_tokens.size(); ++j) { 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths_to_check.insert(cn_token + o_tokens[i] + ou_tokens[j]); 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths_to_check.insert(o_tokens[i] + ou_tokens[j]); 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < ou_tokens.size(); ++i) { 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths_to_check.insert(cn_token + ou_tokens[i]); 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paths_to_check.insert(ou_tokens[i]); 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string issuer_fp = base::HexEncode(issuer.fingerprint().data, 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(issuer.fingerprint().data)); 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<std::string>::iterator it = paths_to_check.begin(); 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != paths_to_check.end(); ++it) { 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) whitelist_strings->push_back("cert/" + issuer_fp + *it); 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 10494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)GURL DownloadProtectionService::GetDownloadRequestUrl() { 10504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) GURL url(kDownloadRequestUrl); 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string api_key = google_apis::GetAPIKey(); 10524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!api_key.empty()) 10534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) url = url.Resolve("?key=" + net::EscapeQueryParamValue(api_key, true)); 10544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return url; 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace safe_browsing 1059