OLD | NEW |
| (Empty) |
1 // Copyright 2016 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 #ifndef CHROME_BROWSER_SAFE_BROWSING_V4_PROTOCOL_MANAGER_H_ | |
6 #define CHROME_BROWSER_SAFE_BROWSING_V4_PROTOCOL_MANAGER_H_ | |
7 | |
8 // A class that implements Chrome's interface with the SafeBrowsing V4 protocol. | |
9 // | |
10 // The V4ProtocolManager handles formatting and making requests of, and handling | |
11 // responses from, Google's SafeBrowsing servers. | |
12 | |
13 #include <string> | |
14 #include <vector> | |
15 | |
16 #include "base/containers/hash_tables.h" | |
17 #include "base/gtest_prod_util.h" | |
18 #include "base/macros.h" | |
19 #include "base/memory/scoped_ptr.h" | |
20 #include "base/threading/non_thread_safe.h" | |
21 #include "base/time/time.h" | |
22 #include "base/timer/timer.h" | |
23 #include "components/safe_browsing_db/safebrowsing.pb.h" | |
24 #include "components/safe_browsing_db/util.h" | |
25 #include "net/url_request/url_fetcher_delegate.h" | |
26 #include "net/url_request/url_request_status.h" | |
27 #include "url/gurl.h" | |
28 | |
29 namespace net { | |
30 class URLFetcher; | |
31 class URLRequestContextGetter; | |
32 } // namespace net | |
33 | |
34 namespace safe_browsing { | |
35 | |
36 // Config passed to the constructor of a V4ProtocolManager. | |
37 struct V4ProtocolConfig { | |
38 std::string client_name; | |
39 std::string version; | |
40 std::string key_param; | |
41 }; | |
42 | |
43 class V4ProtocolManagerFactory; | |
44 | |
45 class V4ProtocolManager : public net::URLFetcherDelegate, | |
46 public base::NonThreadSafe { | |
47 public: | |
48 // FullHashCallback is invoked when GetFullHashes completes. | |
49 // Parameters: | |
50 // - The vector of full hash results. If empty, indicates that there | |
51 // were no matches, and that the resource is safe. | |
52 // - The negative cache duration of the result. | |
53 typedef base::Callback<void(const std::vector<SBFullHashResult>&, | |
54 const base::TimeDelta&)> | |
55 FullHashCallback; | |
56 | |
57 ~V4ProtocolManager() override; | |
58 | |
59 // Makes the passed |factory| the factory used to instantiate | |
60 // a V4ProtocolManager. Useful for tests. | |
61 static void RegisterFactory(V4ProtocolManagerFactory* factory) { | |
62 factory_ = factory; | |
63 } | |
64 | |
65 // Create an instance of the safe browsing v4 protocol manager. | |
66 static V4ProtocolManager* Create( | |
67 net::URLRequestContextGetter* request_context_getter, | |
68 const V4ProtocolConfig& config); | |
69 | |
70 // net::URLFetcherDelegate interface. | |
71 void OnURLFetchComplete(const net::URLFetcher* source) override; | |
72 | |
73 // Retrieve the full hash for a set of prefixes, and invoke the callback | |
74 // argument when the results are retrieved. The callback may be invoked | |
75 // synchronously. | |
76 virtual void GetFullHashes(const std::vector<SBPrefix>& prefixes, | |
77 const std::vector<PlatformType>& platforms, | |
78 ThreatType threat_type, | |
79 FullHashCallback callback); | |
80 | |
81 // Retrieve the full hash and API metadata for a set of prefixes, and invoke | |
82 // the callback argument when the results are retrieved. The callback may be | |
83 // invoked synchronously. | |
84 virtual void GetFullHashesWithApis(const std::vector<SBPrefix>& prefixes, | |
85 FullHashCallback callback); | |
86 | |
87 // Enumerate failures for histogramming purposes. DO NOT CHANGE THE | |
88 // ORDERING OF THESE VALUES. | |
89 // TODO(kcarattini): Use a custom v4 histogram set. | |
90 enum ResultType { | |
91 // 200 response code means that the server recognized the hash | |
92 // prefix, while 204 is an empty response indicating that the | |
93 // server did not recognize it. | |
94 GET_HASH_STATUS_200, | |
95 GET_HASH_STATUS_204, | |
96 | |
97 // Subset of successful responses which returned no full hashes. | |
98 // This includes the STATUS_204 case, and the *_ERROR cases. | |
99 GET_HASH_FULL_HASH_EMPTY, | |
100 | |
101 // Subset of successful responses for which one or more of the | |
102 // full hashes matched (should lead to an interstitial). | |
103 GET_HASH_FULL_HASH_HIT, | |
104 | |
105 // Subset of successful responses which weren't empty and have no | |
106 // matches. It means that there was a prefix collision which was | |
107 // cleared up by the full hashes. | |
108 GET_HASH_FULL_HASH_MISS, | |
109 | |
110 // Subset of successful responses where the response body wasn't parsable. | |
111 GET_HASH_PARSE_ERROR, | |
112 | |
113 // Gethash request failed (network error). | |
114 GET_HASH_NETWORK_ERROR, | |
115 | |
116 // Gethash request returned HTTP result code other than 200 or 204. | |
117 GET_HASH_HTTP_ERROR, | |
118 | |
119 // Gethash attempted during error backoff, no request sent. | |
120 GET_HASH_BACKOFF_ERROR, | |
121 | |
122 // Gethash attempted before min wait duration elapsed, no request sent. | |
123 GET_HASH_MIN_WAIT_DURATION_ERROR, | |
124 | |
125 // Memory space for histograms is determined by the max. ALWAYS | |
126 // ADD NEW VALUES BEFORE THIS ONE. | |
127 GET_HASH_RESULT_MAX | |
128 }; | |
129 | |
130 // Record a GetHash result. | |
131 static void RecordGetHashResult(ResultType result_type); | |
132 | |
133 // Record HTTP response code when there's no error in fetching an HTTP | |
134 // request, and the error code, when there is. | |
135 // |metric_name| is the name of the UMA metric to record the response code or | |
136 // error code against, |status| represents the status of the HTTP request, and | |
137 // |response code| represents the HTTP response code received from the server. | |
138 static void RecordHttpResponseOrErrorCode(const char* metric_name, | |
139 const net::URLRequestStatus& status, | |
140 int response_code); | |
141 | |
142 protected: | |
143 // Constructs a V4ProtocolManager that issues | |
144 // network requests using |request_context_getter|. | |
145 V4ProtocolManager(net::URLRequestContextGetter* request_context_getter, | |
146 const V4ProtocolConfig& config); | |
147 | |
148 private: | |
149 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4ProtocolManagerTest, TestGetHashUrl); | |
150 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4ProtocolManagerTest, | |
151 TestGetHashRequest); | |
152 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4ProtocolManagerTest, | |
153 TestParseHashResponse); | |
154 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4ProtocolManagerTest, | |
155 TestParseHashResponseWrongThreatEntryType); | |
156 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4ProtocolManagerTest, | |
157 TestParseHashResponseSocialEngineeringThreatType); | |
158 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4ProtocolManagerTest, | |
159 TestParseHashResponseNonPermissionMetadata); | |
160 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4ProtocolManagerTest, | |
161 TestParseHashResponseInconsistentThreatTypes); | |
162 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4ProtocolManagerTest, | |
163 TestGetHashBackOffTimes); | |
164 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4ProtocolManagerTest, | |
165 TestGetHashErrorHandlingOK); | |
166 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4ProtocolManagerTest, | |
167 TestGetHashErrorHandlingNetwork); | |
168 FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4ProtocolManagerTest, | |
169 TestGetHashErrorHandlingResponseCode); | |
170 friend class V4ProtocolManagerFactoryImpl; | |
171 | |
172 // Generates GetHashWithApis Pver4 request URL for retrieving full hashes. | |
173 // |request_base64| is the serialized FindFullHashesRequest protocol buffer | |
174 // encoded in base 64. | |
175 GURL GetHashUrl(const std::string& request_base64) const; | |
176 | |
177 // Fills a FindFullHashesRequest protocol buffer for a request. | |
178 // Returns the serialized and base 64 encoded request as a string. | |
179 std::string GetHashRequest(const std::vector<SBPrefix>& prefixes, | |
180 const std::vector<PlatformType>& platforms, | |
181 ThreatType threat_type); | |
182 | |
183 // Composes a URL using |prefix|, |method| (e.g.: encodedFullHashes). | |
184 // |request_base64|, |client_id|, |version| and |key_param|. |prefix| | |
185 // should contain the entire url prefix including scheme, host and path. | |
186 static std::string ComposePver4Url(const std::string& prefix, | |
187 const std::string& method, | |
188 const std::string& request_base64, | |
189 const std::string& client_id, | |
190 const std::string& version, | |
191 const std::string& key_param); | |
192 | |
193 // Parses a FindFullHashesResponse protocol buffer and fills the results in | |
194 // |full_hashes| and |negative_cache_duration|. |data| is a serialized | |
195 // FindFullHashes protocol buffer. |negative_cache_duration| is the duration | |
196 // to cache the response for entities that did not match the threat list. | |
197 // Returns true if parsing is successful, false otherwise. | |
198 bool ParseHashResponse(const std::string& data_base64, | |
199 std::vector<SBFullHashResult>* full_hashes, | |
200 base::TimeDelta* negative_cache_duration); | |
201 | |
202 // Worker function for calculating the GetHash backoff times. | |
203 // |multiplier| is doubled for each consecutive error after the | |
204 // first, and |error_count| is incremented with each call. | |
205 static base::TimeDelta GetNextBackOffInterval(size_t* error_count, | |
206 size_t* multiplier); | |
207 | |
208 // Resets the gethash error counter and multiplier. | |
209 void ResetGetHashErrors(); | |
210 | |
211 // Updates internal state for each GetHash response error, assuming that | |
212 // the current time is |now|. | |
213 void HandleGetHashError(const base::Time& now); | |
214 | |
215 private: | |
216 // Map of GetHash requests to parameters which created it. | |
217 typedef base::hash_map<const net::URLFetcher*, FullHashCallback> HashRequests; | |
218 | |
219 // The factory that controls the creation of V4ProtocolManager. | |
220 // This is used by tests. | |
221 static V4ProtocolManagerFactory* factory_; | |
222 | |
223 // Current active request (in case we need to cancel) for updates or chunks | |
224 // from the SafeBrowsing service. We can only have one of these outstanding | |
225 // at any given time unlike GetHash requests, which are tracked separately. | |
226 scoped_ptr<net::URLFetcher> request_; | |
227 | |
228 // The number of HTTP response errors since the the last successful HTTP | |
229 // response, used for request backoff timing. | |
230 size_t gethash_error_count_; | |
231 | |
232 // Multiplier for the backoff error after the second. | |
233 size_t gethash_back_off_mult_; | |
234 | |
235 HashRequests hash_requests_; | |
236 | |
237 // For v4, the next gethash time is set to the backoff time is the last | |
238 // response was an error, or the minimum wait time if the last response was | |
239 // successful. | |
240 base::Time next_gethash_time_; | |
241 | |
242 // Current product version sent in each request. | |
243 std::string version_; | |
244 | |
245 // The safe browsing client name sent in each request. | |
246 std::string client_name_; | |
247 | |
248 // The Google API key. | |
249 std::string key_param_; | |
250 | |
251 // The context we use to issue network requests. | |
252 scoped_refptr<net::URLRequestContextGetter> request_context_getter_; | |
253 | |
254 // ID for URLFetchers for testing. | |
255 int url_fetcher_id_; | |
256 | |
257 DISALLOW_COPY_AND_ASSIGN(V4ProtocolManager); | |
258 }; | |
259 | |
260 // Interface of a factory to create V4ProtocolManager. Useful for tests. | |
261 class V4ProtocolManagerFactory { | |
262 public: | |
263 V4ProtocolManagerFactory() {} | |
264 virtual ~V4ProtocolManagerFactory() {} | |
265 virtual V4ProtocolManager* CreateProtocolManager( | |
266 net::URLRequestContextGetter* request_context_getter, | |
267 const V4ProtocolConfig& config) = 0; | |
268 | |
269 private: | |
270 DISALLOW_COPY_AND_ASSIGN(V4ProtocolManagerFactory); | |
271 }; | |
272 | |
273 } // namespace safe_browsing | |
274 | |
275 #endif // CHROME_BROWSER_SAFE_BROWSING_V4_PROTOCOL_MANAGER_H_ | |
OLD | NEW |