Home | History | Annotate | Download | only in safe_browsing
      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_BINARY_MALWARE_HASH ||
    106          threat_type == SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL ||
    107          threat_type == SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL);
    108   std::string url = SafeBrowsingProtocolManagerHelper::ComposeUrl(
    109       url_prefix_, "report", client_name_, version_, std::string());
    110   std::string threat_list = "none";
    111   switch (threat_type) {
    112     case SB_THREAT_TYPE_URL_MALWARE:
    113       threat_list = "malblhit";
    114       break;
    115     case SB_THREAT_TYPE_URL_PHISHING:
    116       threat_list = "phishblhit";
    117       break;
    118     case SB_THREAT_TYPE_BINARY_MALWARE_URL:
    119       threat_list = "binurlhit";
    120       break;
    121     case SB_THREAT_TYPE_BINARY_MALWARE_HASH:
    122       threat_list = "binhashhit";
    123       break;
    124     case SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL:
    125       threat_list = "phishcsdhit";
    126       break;
    127     case SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL:
    128       threat_list = "malcsdhit";
    129       break;
    130     default:
    131       NOTREACHED();
    132   }
    133   return GURL(base::StringPrintf("%s&evts=%s&evtd=%s&evtr=%s&evhr=%s&evtb=%d",
    134       url.c_str(), threat_list.c_str(),
    135       net::EscapeQueryParamValue(malicious_url.spec(), true).c_str(),
    136       net::EscapeQueryParamValue(page_url.spec(), true).c_str(),
    137       net::EscapeQueryParamValue(referrer_url.spec(), true).c_str(),
    138       is_subresource));
    139 }
    140 
    141 GURL SafeBrowsingPingManager::MalwareDetailsUrl() const {
    142   std::string url = base::StringPrintf(
    143           "%s/clientreport/malware?client=%s&appver=%s&pver=1.0",
    144           url_prefix_.c_str(),
    145           client_name_.c_str(),
    146           version_.c_str());
    147   std::string api_key = google_apis::GetAPIKey();
    148   if (!api_key.empty()) {
    149     base::StringAppendF(&url, "&key=%s",
    150                         net::EscapeQueryParamValue(api_key, true).c_str());
    151   }
    152   return GURL(url);
    153 }
    154