| 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 |