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.
5 // Helper class which handles communication with the SafeBrowsing backends for
6 // client-side phishing detection. This class is used to fetch the client-side
7 // model and send it to all renderers. This class is also used to send a ping
8 // back to Google to verify if a particular site is really phishing or not.
10 // This class is not thread-safe and expects all calls to be made on the UI
11 // thread. We also expect that the calling thread runs a message loop.
13 #ifndef CHROME_BROWSER_SAFE_BROWSING_CLIENT_SIDE_DETECTION_SERVICE_H_
14 #define CHROME_BROWSER_SAFE_BROWSING_CLIENT_SIDE_DETECTION_SERVICE_H_
23 #include "base/basictypes.h"
24 #include "base/callback_forward.h"
25 #include "base/gtest_prod_util.h"
26 #include "base/memory/linked_ptr.h"
27 #include "base/memory/ref_counted.h"
28 #include "base/memory/scoped_ptr.h"
29 #include "base/memory/weak_ptr.h"
30 #include "base/time/time.h"
31 #include "content/public/browser/notification_observer.h"
32 #include "content/public/browser/notification_registrar.h"
33 #include "net/base/net_util.h"
34 #include "net/url_request/url_fetcher_delegate.h"
37 class SafeBrowsingService
;
44 class RenderProcessHost
;
49 class URLRequestContextGetter
;
50 class URLRequestStatus
;
51 typedef std::vector
<std::string
> ResponseCookies
;
54 namespace safe_browsing
{
55 class ClientMalwareRequest
;
56 class ClientPhishingRequest
;
57 class ClientPhishingResponse
;
58 class ClientSideModel
;
60 class ClientSideDetectionService
: public net::URLFetcherDelegate
,
61 public content::NotificationObserver
{
63 // void(GURL phishing_url, bool is_phishing).
64 typedef base::Callback
<void(GURL
, bool)> ClientReportPhishingRequestCallback
;
65 // void(GURL original_url, GURL malware_url, bool is_malware).
66 typedef base::Callback
<void(GURL
, GURL
, bool)>
67 ClientReportMalwareRequestCallback
;
69 virtual ~ClientSideDetectionService();
71 // Creates a client-side detection service. The service is initially
72 // disabled, use SetEnabledAndRefreshState() to start it. The caller takes
73 // ownership of the object. This function may return NULL.
74 static ClientSideDetectionService
* Create(
75 net::URLRequestContextGetter
* request_context_getter
);
77 // Enables or disables the service, and refreshes the state of all renderers.
78 // This is usually called by the SafeBrowsingService, which tracks whether
79 // any profile uses these services at all. Disabling cancels any pending
80 // requests; existing ClientSideDetectionHosts will have their callbacks
81 // called with "false" verdicts. Enabling starts downloading the model after
82 // a delay. In all cases, each render process is updated to match the state
83 // of the SafeBrowsing preference for that profile.
84 void SetEnabledAndRefreshState(bool enabled
);
86 bool enabled() const {
90 // From the net::URLFetcherDelegate interface.
91 virtual void OnURLFetchComplete(const net::URLFetcher
* source
) OVERRIDE
;
93 // content::NotificationObserver overrides:
94 virtual void Observe(int type
,
95 const content::NotificationSource
& source
,
96 const content::NotificationDetails
& details
) OVERRIDE
;
98 // Sends a request to the SafeBrowsing servers with the ClientPhishingRequest.
99 // The URL scheme of the |url()| in the request should be HTTP. This method
100 // takes ownership of the |verdict| as well as the |callback| and calls the
101 // the callback once the result has come back from the server or if an error
102 // occurs during the fetch. If the service is disabled or an error occurs
103 // the phishing verdict will always be false. The callback is always called
104 // after SendClientReportPhishingRequest() returns and on the same thread as
105 // SendClientReportPhishingRequest() was called. You may set |callback| to
106 // NULL if you don't care about the server verdict.
107 virtual void SendClientReportPhishingRequest(
108 ClientPhishingRequest
* verdict
,
109 const ClientReportPhishingRequestCallback
& callback
);
111 // Similar to above one, instead send ClientMalwareRequest
112 virtual void SendClientReportMalwareRequest(
113 ClientMalwareRequest
* verdict
,
114 const ClientReportMalwareRequestCallback
& callback
);
116 // Returns true if the given IP address string falls within a private
117 // (unroutable) network block. Pages which are hosted on these IP addresses
118 // are exempt from client-side phishing detection. This is called by the
119 // ClientSideDetectionHost prior to sending the renderer a
120 // SafeBrowsingMsg_StartPhishingDetection IPC.
122 // ip_address should be a dotted IPv4 address, or an unbracketed IPv6
124 virtual bool IsPrivateIPAddress(const std::string
& ip_address
) const;
126 // Returns true and sets is_phishing if url is in the cache and valid.
127 virtual bool GetValidCachedResult(const GURL
& url
, bool* is_phishing
);
129 // Returns true if the url is in the cache.
130 virtual bool IsInCache(const GURL
& url
);
132 // Returns true if we have sent more than kMaxReportsPerInterval phishing
133 // reports in the last kReportsInterval.
134 virtual bool OverPhishingReportLimit();
136 // Returns true if we have sent more than kMaxReportsPerInterval malware
137 // reports in the last kReportsInterval.
138 virtual bool OverMalwareReportLimit();
141 // Use Create() method to create an instance of this object.
142 explicit ClientSideDetectionService(
143 net::URLRequestContextGetter
* request_context_getter
);
145 // Enum used to keep stats about why we fail to get the client model.
146 enum ClientModelStatus
{
153 MODEL_MISSING_FIELDS
,
154 MODEL_INVALID_VERSION_NUMBER
,
156 MODEL_STATUS_MAX
// Always add new values before this one.
159 // Starts fetching the model from the network or the cache. This method
160 // is called periodically to check whether a new client model is available
162 void StartFetchModel();
164 // Schedules the next fetch of the model.
165 virtual void ScheduleFetchModel(int64 delay_ms
); // Virtual for testing.
167 // This method is called when we're done fetching the model either because
168 // we hit an error somewhere or because we're actually done fetch and
169 // validating the model.
170 virtual void EndFetchModel(ClientModelStatus status
); // Virtual for testing.
173 friend class ClientSideDetectionServiceTest
;
174 FRIEND_TEST_ALL_PREFIXES(ClientSideDetectionServiceTest
, FetchModelTest
);
175 FRIEND_TEST_ALL_PREFIXES(ClientSideDetectionServiceTest
, SetBadSubnets
);
176 FRIEND_TEST_ALL_PREFIXES(ClientSideDetectionServiceTest
,
177 SetEnabledAndRefreshState
);
178 FRIEND_TEST_ALL_PREFIXES(ClientSideDetectionServiceTest
, IsBadIpAddress
);
179 FRIEND_TEST_ALL_PREFIXES(ClientSideDetectionServiceTest
,
180 ModelHasValidHashIds
);
182 // CacheState holds all information necessary to respond to a caller without
183 // actually making a HTTP request.
186 base::Time timestamp
;
188 CacheState(bool phish
, base::Time time
);
190 typedef std::map
<GURL
, linked_ptr
<CacheState
> > PhishingCache
;
192 // A tuple of (IP address block, prefix size) representing a private
194 typedef std::pair
<net::IPAddressNumber
, size_t> AddressRange
;
196 // Maps a IPv6 subnet mask to a set of hashed IPv6 subnets. The IPv6
197 // subnets are in network order and hashed with sha256.
198 typedef std::map
<std::string
/* subnet mask */,
199 std::set
<std::string
/* hashed subnet */> > BadSubnetMap
;
201 static const char kClientReportMalwareUrl
[];
202 static const char kClientReportPhishingUrl
[];
203 static const char kClientModelUrl
[];
204 static const size_t kMaxModelSizeBytes
;
205 static const int kMaxReportsPerInterval
;
206 static const int kClientModelFetchIntervalMs
;
207 static const int kInitialClientModelFetchDelayMs
;
208 static const int kReportsIntervalDays
;
209 static const int kNegativeCacheIntervalDays
;
210 static const int kPositiveCacheIntervalMinutes
;
212 // Starts sending the request to the client-side detection frontends.
213 // This method takes ownership of both pointers.
214 void StartClientReportPhishingRequest(
215 ClientPhishingRequest
* verdict
,
216 const ClientReportPhishingRequestCallback
& callback
);
218 void StartClientReportMalwareRequest(
219 ClientMalwareRequest
* verdict
,
220 const ClientReportMalwareRequestCallback
& callback
);
222 // Called by OnURLFetchComplete to handle the response from fetching the
224 void HandleModelResponse(const net::URLFetcher
* source
,
226 const net::URLRequestStatus
& status
,
228 const net::ResponseCookies
& cookies
,
229 const std::string
& data
);
231 // Called by OnURLFetchComplete to handle the server response from
232 // sending the client-side phishing request.
233 void HandlePhishingVerdict(const net::URLFetcher
* source
,
235 const net::URLRequestStatus
& status
,
237 const net::ResponseCookies
& cookies
,
238 const std::string
& data
);
240 // Called by OnURLFetchComplete to handle the server response from
241 // sending the client-side malware request.
242 void HandleMalwareVerdict(const net::URLFetcher
* source
,
244 const net::URLRequestStatus
& status
,
246 const net::ResponseCookies
& cookies
,
247 const std::string
& data
);
249 // Invalidate cache results which are no longer useful.
252 // Get the number of malware reports that we have sent over kReportsInterval.
253 int GetMalwareNumReports();
255 // Get the number of phishing reports that we have sent over kReportsInterval.
256 int GetPhishingNumReports();
258 // Get the number of reports that we have sent over kReportsInterval, and
259 // trims off the old elements.
260 int GetNumReports(std::queue
<base::Time
>* report_times
);
262 // Send the model to the given renderer.
263 void SendModelToProcess(content::RenderProcessHost
* process
);
265 // Same as above but sends the model to all rendereres.
266 void SendModelToRenderers();
268 // Reads the bad subnets from the client model and inserts them into
269 // |bad_subnets| for faster lookups. This method is static to simplify
271 static void SetBadSubnets(const ClientSideModel
& model
,
272 BadSubnetMap
* bad_subnets
);
275 // Returns true iff all the hash id's in the client-side model point to
276 // valid hashes in the model.
277 static bool ModelHasValidHashIds(const ClientSideModel
& model
);
279 // Returns the URL that will be used for phishing requests.
280 static GURL
GetClientReportUrl(const std::string
& report_url
);
282 // Whether the service is running or not. When the service is not running,
283 // it won't download the model nor report detected phishing URLs.
286 std::string model_str_
;
287 scoped_ptr
<ClientSideModel
> model_
;
288 scoped_ptr
<base::TimeDelta
> model_max_age_
;
289 scoped_ptr
<net::URLFetcher
> model_fetcher_
;
291 // Map of client report phishing request to the corresponding callback that
292 // has to be invoked when the request is done.
293 struct ClientReportInfo
;
294 std::map
<const net::URLFetcher
*, ClientReportInfo
*>
295 client_phishing_reports_
;
296 // Map of client malware ip request to the corresponding callback that
297 // has to be invoked when the request is done.
298 struct ClientMalwareReportInfo
;
299 std::map
<const net::URLFetcher
*, ClientMalwareReportInfo
*>
300 client_malware_reports_
;
302 // Cache of completed requests. Used to satisfy requests for the same urls
303 // as long as the next request falls within our caching window (which is
304 // determined by kNegativeCacheInterval and kPositiveCacheInterval). The
305 // size of this cache is limited by kMaxReportsPerDay *
306 // ceil(InDays(max(kNegativeCacheInterval, kPositiveCacheInterval))).
307 // TODO(gcasto): Serialize this so that it doesn't reset on browser restart.
308 PhishingCache cache_
;
310 // Timestamp of when we sent a phishing request. Used to limit the number
311 // of phishing requests that we send in a day.
312 // TODO(gcasto): Serialize this so that it doesn't reset on browser restart.
313 std::queue
<base::Time
> phishing_report_times_
;
315 // Timestamp of when we sent a malware request. Used to limit the number
316 // of malware requests that we send in a day.
317 std::queue
<base::Time
> malware_report_times_
;
319 // Used to asynchronously call the callbacks for
320 // SendClientReportPhishingRequest.
321 base::WeakPtrFactory
<ClientSideDetectionService
> weak_factory_
;
323 // The context we use to issue network requests.
324 scoped_refptr
<net::URLRequestContextGetter
> request_context_getter_
;
326 // Map of bad subnets which are copied from the client model and put into
327 // this map to speed up lookups.
328 BadSubnetMap bad_subnets_
;
330 content::NotificationRegistrar registrar_
;
332 DISALLOW_COPY_AND_ASSIGN(ClientSideDetectionService
);
334 } // namespace safe_browsing
336 #endif // CHROME_BROWSER_SAFE_BROWSING_CLIENT_SIDE_DETECTION_SERVICE_H_