1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/safe_browsing/ping_manager.h" 6 7 #include "base/logging.h" 8 #include "base/stl_util.h" 9 #include "base/strings/string_util.h" 10 #include "base/strings/stringprintf.h" 11 #include "chrome/common/env_vars.h" 12 #include "content/public/browser/browser_thread.h" 13 #include "google_apis/google_api_keys.h" 14 #include "net/base/escape.h" 15 #include "net/base/load_flags.h" 16 #include "net/url_request/url_fetcher.h" 17 #include "net/url_request/url_request_context_getter.h" 18 #include "net/url_request/url_request_status.h" 19 20 using content::BrowserThread; 21 22 // SafeBrowsingPingManager implementation ---------------------------------- 23 24 // static 25 SafeBrowsingPingManager* SafeBrowsingPingManager::Create( 26 net::URLRequestContextGetter* request_context_getter, 27 const SafeBrowsingProtocolConfig& config) { 28 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 29 return new SafeBrowsingPingManager(request_context_getter, config); 30 } 31 32 SafeBrowsingPingManager::SafeBrowsingPingManager( 33 net::URLRequestContextGetter* request_context_getter, 34 const SafeBrowsingProtocolConfig& config) 35 : client_name_(config.client_name), 36 request_context_getter_(request_context_getter), 37 url_prefix_(config.url_prefix) { 38 DCHECK(!url_prefix_.empty()); 39 40 version_ = SafeBrowsingProtocolManagerHelper::Version(); 41 } 42 43 SafeBrowsingPingManager::~SafeBrowsingPingManager() { 44 // Delete in-progress safebrowsing reports (hits and details). 45 STLDeleteContainerPointers(safebrowsing_reports_.begin(), 46 safebrowsing_reports_.end()); 47 } 48 49 // net::URLFetcherDelegate implementation ---------------------------------- 50 51 // All SafeBrowsing request responses are handled here. 52 void SafeBrowsingPingManager::OnURLFetchComplete( 53 const net::URLFetcher* source) { 54 Reports::iterator sit = safebrowsing_reports_.find(source); 55 DCHECK(sit != safebrowsing_reports_.end()); 56 delete *sit; 57 safebrowsing_reports_.erase(sit); 58 } 59 60 // Sends a SafeBrowsing "hit" for UMA users. 61 void SafeBrowsingPingManager::ReportSafeBrowsingHit( 62 const GURL& malicious_url, 63 const GURL& page_url, 64 const GURL& referrer_url, 65 bool is_subresource, 66 SBThreatType threat_type, 67 const std::string& post_data) { 68 GURL report_url = SafeBrowsingHitUrl(malicious_url, page_url, 69 referrer_url, is_subresource, 70 threat_type); 71 net::URLFetcher* report = net::URLFetcher::Create( 72 report_url, 73 post_data.empty() ? net::URLFetcher::GET : net::URLFetcher::POST, 74 this); 75 report->SetLoadFlags(net::LOAD_DISABLE_CACHE); 76 report->SetRequestContext(request_context_getter_.get()); 77 if (!post_data.empty()) 78 report->SetUploadData("text/plain", post_data); 79 safebrowsing_reports_.insert(report); 80 report->Start(); 81 } 82 83 // Sends malware details for users who opt-in. 84 void SafeBrowsingPingManager::ReportMalwareDetails( 85 const std::string& report) { 86 GURL report_url = MalwareDetailsUrl(); 87 net::URLFetcher* fetcher = net::URLFetcher::Create( 88 report_url, net::URLFetcher::POST, this); 89 fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE); 90 fetcher->SetRequestContext(request_context_getter_.get()); 91 fetcher->SetUploadData("application/octet-stream", report); 92 // Don't try too hard to send reports on failures. 93 fetcher->SetAutomaticallyRetryOn5xx(false); 94 fetcher->Start(); 95 safebrowsing_reports_.insert(fetcher); 96 } 97 98 GURL SafeBrowsingPingManager::SafeBrowsingHitUrl( 99 const GURL& malicious_url, const GURL& page_url, 100 const GURL& referrer_url, bool is_subresource, 101 SBThreatType threat_type) const { 102 DCHECK(threat_type == SB_THREAT_TYPE_URL_MALWARE || 103 threat_type == SB_THREAT_TYPE_URL_PHISHING || 104 threat_type == SB_THREAT_TYPE_BINARY_MALWARE_URL || 105 threat_type == SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL || 106 threat_type == SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL); 107 std::string url = SafeBrowsingProtocolManagerHelper::ComposeUrl( 108 url_prefix_, "report", client_name_, version_, std::string()); 109 std::string threat_list = "none"; 110 switch (threat_type) { 111 case SB_THREAT_TYPE_URL_MALWARE: 112 threat_list = "malblhit"; 113 break; 114 case SB_THREAT_TYPE_URL_PHISHING: 115 threat_list = "phishblhit"; 116 break; 117 case SB_THREAT_TYPE_BINARY_MALWARE_URL: 118 threat_list = "binurlhit"; 119 break; 120 case SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL: 121 threat_list = "phishcsdhit"; 122 break; 123 case SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL: 124 threat_list = "malcsdhit"; 125 break; 126 default: 127 NOTREACHED(); 128 } 129 return GURL(base::StringPrintf("%s&evts=%s&evtd=%s&evtr=%s&evhr=%s&evtb=%d", 130 url.c_str(), threat_list.c_str(), 131 net::EscapeQueryParamValue(malicious_url.spec(), true).c_str(), 132 net::EscapeQueryParamValue(page_url.spec(), true).c_str(), 133 net::EscapeQueryParamValue(referrer_url.spec(), true).c_str(), 134 is_subresource)); 135 } 136 137 GURL SafeBrowsingPingManager::MalwareDetailsUrl() const { 138 std::string url = base::StringPrintf( 139 "%s/clientreport/malware?client=%s&appver=%s&pver=1.0", 140 url_prefix_.c_str(), 141 client_name_.c_str(), 142 version_.c_str()); 143 std::string api_key = google_apis::GetAPIKey(); 144 if (!api_key.empty()) { 145 base::StringAppendF(&url, "&key=%s", 146 net::EscapeQueryParamValue(api_key, true).c_str()); 147 } 148 return GURL(url); 149 } 150