Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(500)

Side by Side Diff: chrome/browser/safe_browsing/protocol_manager.cc

Issue 1556613002: Adds SB V4 response handler to Protocol Manager. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@osb-pm-1
Patch Set: Review Comments Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/safe_browsing/protocol_manager.h" 5 #include "chrome/browser/safe_browsing/protocol_manager.h"
6 6
7 #include "base/base64.h" 7 #include "base/base64.h"
8 #include "base/environment.h" 8 #include "base/environment.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/metrics/histogram_macros.h" 10 #include "base/metrics/histogram_macros.h"
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 const std::string get_hash = FormatGetHash(prefixes); 231 const std::string get_hash = FormatGetHash(prefixes);
232 232
233 fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE); 233 fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE);
234 fetcher->SetRequestContext(request_context_getter_.get()); 234 fetcher->SetRequestContext(request_context_getter_.get());
235 fetcher->SetUploadData("text/plain", get_hash); 235 fetcher->SetUploadData("text/plain", get_hash);
236 fetcher->Start(); 236 fetcher->Start();
237 } 237 }
238 238
239 std::string SafeBrowsingProtocolManager::GetV4HashRequest( 239 std::string SafeBrowsingProtocolManager::GetV4HashRequest(
240 const std::vector<SBPrefix>& prefixes, 240 const std::vector<SBPrefix>& prefixes,
241 const std::vector<PlatformType>& platforms,
241 ThreatType threat_type) { 242 ThreatType threat_type) {
242 // Build the request. Client info and client states are not added to the 243 // Build the request. Client info and client states are not added to the
243 // request protocol buffer. Client info is passed as params in the url. 244 // request protocol buffer. Client info is passed as params in the url.
244 FindFullHashesRequest req; 245 FindFullHashesRequest req;
245 ThreatInfo* info = req.mutable_threat_info(); 246 ThreatInfo* info = req.mutable_threat_info();
246 info->add_threat_types(threat_type); 247 info->add_threat_types(threat_type);
247 info->add_platform_types(CHROME_PLATFORM);
248 info->add_threat_entry_types(URL_EXPRESSION); 248 info->add_threat_entry_types(URL_EXPRESSION);
249 for (const PlatformType p : platforms) {
250 info->add_platform_types(p);
251 }
249 for (const SBPrefix& prefix : prefixes) { 252 for (const SBPrefix& prefix : prefixes) {
250 std::string hash; 253 std::string hash;
251 hash.append(reinterpret_cast<const char*>(&prefix), sizeof(SBPrefix)); 254 hash.append(reinterpret_cast<const char*>(&prefix), sizeof(SBPrefix));
252 info->add_threat_entries()->set_hash(hash); 255 info->add_threat_entries()->set_hash(hash);
253 } 256 }
254 257
255 // Serialize and Base64 encode. 258 // Serialize and Base64 encode.
256 std::string req_data, req_base64; 259 std::string req_data, req_base64;
257 req.SerializeToString(&req_data); 260 req.SerializeToString(&req_data);
258 base::Base64Encode(req_data, &req_base64); 261 base::Base64Encode(req_data, &req_base64);
259 262
260 return req_base64; 263 return req_base64;
261 } 264 }
262 265
266 bool SafeBrowsingProtocolManager::ParseV4HashResponse(
267 const std::string& data,
268 std::vector<SBFullHashResult>* full_hashes,
269 base::TimeDelta* negative_cache_duration) {
270 FindFullHashesResponse response;
271
272 if (!response.ParseFromString(data))
273 return false;
274
275 if (response.has_negative_cache_duration()) {
276 // Seconds resolution is good enough so we ignore the nanos field.
277 *negative_cache_duration = base::TimeDelta::FromSeconds(
278 response.negative_cache_duration().seconds());
279 }
280
281 // Loop over the threat matches and fill in full_hashes.
282 for (const ThreatMatch& match : response.matches()) {
283 // Make sure the platform and threat entry type match.
284 if (!(match.has_threat_entry_type() &&
285 match.threat_entry_type() == URL_EXPRESSION &&
286 match.has_threat())) {
287 continue;
288 }
289
290 // Fill in the full hash.
291 SBFullHashResult result;
292 result.hash = StringToSBFullHash(match.threat().hash());
awoz 2016/01/05 17:20:10 Should the threat type also be passed back?
awoz 2016/01/12 22:55:04 This is irrelevant since only one threat type is b
293
294 if (match.has_cache_duration()) {
295 // Seconds resolution is good enough so we ignore the nanos field.
296 result.cache_duration = base::TimeDelta::FromSeconds(
297 match.cache_duration().seconds());
298 }
299
300 // Different threat types will handle the metadata differently.
301 if (match.has_threat_type() && match.threat_type() == API_ABUSE &&
302 match.has_platform_type() &&
303 match.platform_type() == CHROME_PLATFORM &&
304 match.has_threat_entry_metadata()) {
305 // For API Abuse, store a csv of the returned permissions.
306 for (const ThreatEntryMetadata::MetadataEntry& m :
307 match.threat_entry_metadata().entries()) {
308 if (m.key() == "permission") {
309 result.metadata += m.value() + ",";
310 }
311 }
312 }
313
314 full_hashes->push_back(result);
315 }
316 return true;
317 }
318
263 void SafeBrowsingProtocolManager::GetV4FullHashes( 319 void SafeBrowsingProtocolManager::GetV4FullHashes(
264 const std::vector<SBPrefix>& prefixes, 320 const std::vector<SBPrefix>& prefixes,
321 const std::vector<PlatformType>& platforms,
265 ThreatType threat_type, 322 ThreatType threat_type,
266 FullHashCallback callback) { 323 FullHashCallback callback) {
267 DCHECK(CalledOnValidThread()); 324 DCHECK(CalledOnValidThread());
268 // TODO(kcarattini): Implement backoff behavior. 325 // TODO(kcarattini): Implement backoff behavior.
269 326
270 std::string req_base64 = GetV4HashRequest(prefixes, threat_type); 327 std::string req_base64 = GetV4HashRequest(prefixes, platforms, threat_type);
271 GURL gethash_url = GetV4HashUrl(req_base64); 328 GURL gethash_url = GetV4HashUrl(req_base64);
272 329
273 net::URLFetcher* fetcher = 330 net::URLFetcher* fetcher =
274 net::URLFetcher::Create(url_fetcher_id_++, gethash_url, 331 net::URLFetcher::Create(url_fetcher_id_++, gethash_url,
275 net::URLFetcher::GET, this) 332 net::URLFetcher::GET, this)
276 .release(); 333 .release();
277 // TODO(kcarattini): Implement a new response processor.
278 v4_hash_requests_[fetcher] = FullHashDetails(callback, 334 v4_hash_requests_[fetcher] = FullHashDetails(callback,
279 false /* is_download */); 335 false /* is_download */);
280 336
281 fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE); 337 fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE);
282 fetcher->SetRequestContext(request_context_getter_.get()); 338 fetcher->SetRequestContext(request_context_getter_.get());
283 fetcher->Start(); 339 fetcher->Start();
284 } 340 }
285 341
286 void SafeBrowsingProtocolManager::GetFullHashesWithApis( 342 void SafeBrowsingProtocolManager::GetFullHashesWithApis(
287 const std::vector<SBPrefix>& prefixes, 343 const std::vector<SBPrefix>& prefixes,
288 FullHashCallback callback) { 344 FullHashCallback callback) {
289 GetV4FullHashes(prefixes, API_ABUSE, callback); 345 std::vector<PlatformType> platform;
346 platform.push_back(CHROME_PLATFORM);
347 GetV4FullHashes(prefixes, platform, API_ABUSE, callback);
290 } 348 }
291 349
292 void SafeBrowsingProtocolManager::GetNextUpdate() { 350 void SafeBrowsingProtocolManager::GetNextUpdate() {
293 DCHECK(CalledOnValidThread()); 351 DCHECK(CalledOnValidThread());
294 if (request_.get() || request_type_ != NO_REQUEST) 352 if (request_.get() || request_type_ != NO_REQUEST)
295 return; 353 return;
296 354
297 IssueUpdateRequest(); 355 IssueUpdateRequest();
298 } 356 }
299 357
300 // net::URLFetcherDelegate implementation ---------------------------------- 358 // net::URLFetcherDelegate implementation ----------------------------------
301 359
302 // All SafeBrowsing request responses are handled here. 360 // All SafeBrowsing request responses are handled here.
303 // TODO(paulg): Clarify with the SafeBrowsing team whether a failed parse of a 361 // TODO(paulg): Clarify with the SafeBrowsing team whether a failed parse of a
304 // chunk should retry the download and parse of that chunk (and 362 // chunk should retry the download and parse of that chunk (and
305 // what back off / how many times to try), and if that effects the 363 // what back off / how many times to try), and if that effects the
306 // update back off. For now, a failed parse of the chunk means we 364 // update back off. For now, a failed parse of the chunk means we
307 // drop it. This isn't so bad because the next UPDATE_REQUEST we 365 // drop it. This isn't so bad because the next UPDATE_REQUEST we
308 // do will report all the chunks we have. If that chunk is still 366 // do will report all the chunks we have. If that chunk is still
309 // required, the SafeBrowsing servers will tell us to get it again. 367 // required, the SafeBrowsing servers will tell us to get it again.
310 void SafeBrowsingProtocolManager::OnURLFetchComplete( 368 void SafeBrowsingProtocolManager::OnURLFetchComplete(
311 const net::URLFetcher* source) { 369 const net::URLFetcher* source) {
312 DCHECK(CalledOnValidThread()); 370 DCHECK(CalledOnValidThread());
313 scoped_ptr<const net::URLFetcher> fetcher; 371 scoped_ptr<const net::URLFetcher> fetcher;
314 372
315 HashRequests::iterator it = hash_requests_.find(source); 373 HashRequests::iterator it = hash_requests_.find(source);
374 HashRequests::iterator v4_it = v4_hash_requests_.find(source);
316 int response_code = source->GetResponseCode(); 375 int response_code = source->GetResponseCode();
317 net::URLRequestStatus status = source->GetStatus(); 376 net::URLRequestStatus status = source->GetStatus();
318 RecordHttpResponseOrErrorCode(kUmaHashResponseMetricName, status, 377 RecordHttpResponseOrErrorCode(kUmaHashResponseMetricName, status,
319 response_code); 378 response_code);
320 if (it != hash_requests_.end()) { 379 if (it != hash_requests_.end()) {
321 // GetHash response. 380 // GetHash response.
322 fetcher.reset(it->first); 381 fetcher.reset(it->first);
323 const FullHashDetails& details = it->second; 382 const FullHashDetails& details = it->second;
324 std::vector<SBFullHashResult> full_hashes; 383 std::vector<SBFullHashResult> full_hashes;
325 base::TimeDelta cache_lifetime; 384 base::TimeDelta cache_lifetime;
(...skipping 29 matching lines...) Expand all
355 << " failed with error: " << response_code; 414 << " failed with error: " << response_code;
356 } 415 }
357 } 416 }
358 417
359 // Invoke the callback with full_hashes, even if there was a parse error or 418 // Invoke the callback with full_hashes, even if there was a parse error or
360 // an error response code (in which case full_hashes will be empty). The 419 // an error response code (in which case full_hashes will be empty). The
361 // caller can't be blocked indefinitely. 420 // caller can't be blocked indefinitely.
362 details.callback.Run(full_hashes, cache_lifetime); 421 details.callback.Run(full_hashes, cache_lifetime);
363 422
364 hash_requests_.erase(it); 423 hash_requests_.erase(it);
424 } else if (v4_it != v4_hash_requests_.end()) {
425 // V4 FindFullHashes response.
426 fetcher.reset(v4_it->first);
427 const FullHashDetails& details = v4_it->second;
428 std::vector<SBFullHashResult> full_hashes;
429 base::TimeDelta negative_cache_duration;
430 if (status.is_success() && response_code == net::HTTP_OK) {
431 // TODO(kcarattini): Add UMA reporting.
432 // TODO(kcarattini): Implement backoff and minimum waiting duration
433 // compliance.
434 std::string data;
435 source->GetResponseAsString(&data);
436 if (!ParseV4HashResponse(data, &full_hashes, &negative_cache_duration)) {
437 full_hashes.clear();
438 // TODO(kcarattini): Add UMA reporting.
439 }
440 } else {
441 // TODO(kcarattini): Handle error by setting backoff interval.
442 // TODO(kcarattini): Add UMA reporting.
443 if (status.status() == net::URLRequestStatus::FAILED) {
444 DVLOG(1) << "SafeBrowsing GetEncodedFullHashes request for: " <<
445 source->GetURL() << " failed with error: " << status.error();
446 } else {
447 DVLOG(1) << "SafeBrowsing GetEncodedFullHashes request for: " <<
448 source->GetURL() << " failed with error: " << response_code;
449 }
450 }
451
452 // Invoke the callback with full_hashes, even if there was a parse error or
453 // an error response code (in which case full_hashes will be empty). The
454 // caller can't be blocked indefinitely.
455 details.callback.Run(full_hashes, negative_cache_duration);
456
457 v4_hash_requests_.erase(it);
365 } else { 458 } else {
366 // Update or chunk response. 459 // Update or chunk response.
367 fetcher.reset(request_.release()); 460 fetcher.reset(request_.release());
368 461
369 if (request_type_ == UPDATE_REQUEST || 462 if (request_type_ == UPDATE_REQUEST ||
370 request_type_ == BACKUP_UPDATE_REQUEST) { 463 request_type_ == BACKUP_UPDATE_REQUEST) {
371 if (!fetcher.get()) { 464 if (!fetcher.get()) {
372 // We've timed out waiting for an update response, so we've cancelled 465 // We've timed out waiting for an update response, so we've cancelled
373 // the update request and scheduled a new one. Ignore this response. 466 // the update request and scheduled a new one. Ignore this response.
374 return; 467 return;
(...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after
861 SafeBrowsingProtocolManager::FullHashDetails::FullHashDetails( 954 SafeBrowsingProtocolManager::FullHashDetails::FullHashDetails(
862 FullHashCallback callback, 955 FullHashCallback callback,
863 bool is_download) 956 bool is_download)
864 : callback(callback), is_download(is_download) {} 957 : callback(callback), is_download(is_download) {}
865 958
866 SafeBrowsingProtocolManager::FullHashDetails::~FullHashDetails() {} 959 SafeBrowsingProtocolManager::FullHashDetails::~FullHashDetails() {}
867 960
868 SafeBrowsingProtocolManagerDelegate::~SafeBrowsingProtocolManagerDelegate() {} 961 SafeBrowsingProtocolManagerDelegate::~SafeBrowsingProtocolManagerDelegate() {}
869 962
870 } // namespace safe_browsing 963 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698