OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/client_side_detection_service.h" | 5 #include "chrome/browser/safe_browsing/client_side_detection_service.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/time.h" | 9 #include "base/time.h" |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 NotificationService::AllSources()); | 69 NotificationService::AllSources()); |
70 } | 70 } |
71 | 71 |
72 ClientSideDetectionService::~ClientSideDetectionService() { | 72 ClientSideDetectionService::~ClientSideDetectionService() { |
73 method_factory_.RevokeAll(); | 73 method_factory_.RevokeAll(); |
74 STLDeleteContainerPairPointers(client_phishing_reports_.begin(), | 74 STLDeleteContainerPairPointers(client_phishing_reports_.begin(), |
75 client_phishing_reports_.end()); | 75 client_phishing_reports_.end()); |
76 client_phishing_reports_.clear(); | 76 client_phishing_reports_.clear(); |
77 } | 77 } |
78 | 78 |
79 /* static */ | 79 // static |
80 ClientSideDetectionService* ClientSideDetectionService::Create( | 80 ClientSideDetectionService* ClientSideDetectionService::Create( |
81 net::URLRequestContextGetter* request_context_getter) { | 81 net::URLRequestContextGetter* request_context_getter) { |
82 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 82 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
83 scoped_ptr<ClientSideDetectionService> service( | 83 scoped_ptr<ClientSideDetectionService> service( |
84 new ClientSideDetectionService(request_context_getter)); | 84 new ClientSideDetectionService(request_context_getter)); |
85 if (!service->InitializePrivateNetworks()) { | 85 if (!service->InitializePrivateNetworks()) { |
86 UMA_HISTOGRAM_COUNTS("SBClientPhishing.InitPrivateNetworksFailed", 1); | 86 UMA_HISTOGRAM_COUNTS("SBClientPhishing.InitPrivateNetworksFailed", 1); |
87 return NULL; | 87 return NULL; |
88 } | 88 } |
89 // We fetch the model at every browser restart. In a lot of cases the model | 89 // We fetch the model at every browser restart. In a lot of cases the model |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 if (!status.is_success() || RC_REQUEST_OK != response_code) { | 292 if (!status.is_success() || RC_REQUEST_OK != response_code) { |
293 model_status = MODEL_FETCH_FAILED; | 293 model_status = MODEL_FETCH_FAILED; |
294 } else if (data.empty()) { | 294 } else if (data.empty()) { |
295 model_status = MODEL_EMPTY; | 295 model_status = MODEL_EMPTY; |
296 } else if (data.size() > kMaxModelSizeBytes) { | 296 } else if (data.size() > kMaxModelSizeBytes) { |
297 model_status = MODEL_TOO_LARGE; | 297 model_status = MODEL_TOO_LARGE; |
298 } else if (!model->ParseFromString(data)) { | 298 } else if (!model->ParseFromString(data)) { |
299 model_status = MODEL_PARSE_ERROR; | 299 model_status = MODEL_PARSE_ERROR; |
300 } else if (!model->IsInitialized() || !model->has_version()) { | 300 } else if (!model->IsInitialized() || !model->has_version()) { |
301 model_status = MODEL_MISSING_FIELDS; | 301 model_status = MODEL_MISSING_FIELDS; |
| 302 } else if (!ModelHasValidHashIds(*model)) { |
| 303 model_status = MODEL_BAD_HASH_IDS; |
302 } else if (model->version() < 0 || | 304 } else if (model->version() < 0 || |
303 (model_.get() && model->version() < model_->version())) { | 305 (model_.get() && model->version() < model_->version())) { |
304 model_status = MODEL_INVALID_VERSION_NUMBER; | 306 model_status = MODEL_INVALID_VERSION_NUMBER; |
305 } else if (model_.get() && model->version() == model_->version()) { | 307 } else if (model_.get() && model->version() == model_->version()) { |
306 model_status = MODEL_NOT_CHANGED; | 308 model_status = MODEL_NOT_CHANGED; |
307 } else { | 309 } else { |
308 // The model is valid => replace the existing model with the new one. | 310 // The model is valid => replace the existing model with the new one. |
309 model_str_.assign(data); | 311 model_str_.assign(data); |
310 model_.swap(model); | 312 model_.swap(model); |
311 model_status = MODEL_SUCCESS; | 313 model_status = MODEL_SUCCESS; |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 private_networks_.push_back(std::make_pair(ip_number, prefix_length)); | 428 private_networks_.push_back(std::make_pair(ip_number, prefix_length)); |
427 } else { | 429 } else { |
428 DLOG(FATAL) << "Unable to parse IP address range: " | 430 DLOG(FATAL) << "Unable to parse IP address range: " |
429 << kPrivateNetworks[i]; | 431 << kPrivateNetworks[i]; |
430 return false; | 432 return false; |
431 } | 433 } |
432 } | 434 } |
433 return true; | 435 return true; |
434 } | 436 } |
435 | 437 |
436 /* static */ | 438 // static |
437 void ClientSideDetectionService::SetBadSubnets(const ClientSideModel& model, | 439 void ClientSideDetectionService::SetBadSubnets(const ClientSideModel& model, |
438 BadSubnetMap* bad_subnets) { | 440 BadSubnetMap* bad_subnets) { |
439 bad_subnets->clear(); | 441 bad_subnets->clear(); |
440 for (int i = 0; i < model.bad_subnet_size(); ++i) { | 442 for (int i = 0; i < model.bad_subnet_size(); ++i) { |
441 int size = model.bad_subnet(i).size(); | 443 int size = model.bad_subnet(i).size(); |
442 if (size < 0 || size > static_cast<int>(net::kIPv6AddressSize) * 8) { | 444 if (size < 0 || size > static_cast<int>(net::kIPv6AddressSize) * 8) { |
443 DLOG(ERROR) << "Invalid bad subnet size: " << size; | 445 DLOG(ERROR) << "Invalid bad subnet size: " << size; |
444 continue; | 446 continue; |
445 } | 447 } |
446 if (model.bad_subnet(i).prefix().size() != crypto::SHA256_LENGTH) { | 448 if (model.bad_subnet(i).prefix().size() != crypto::SHA256_LENGTH) { |
447 DLOG(ERROR) << "Invalid bad subnet prefix length: " | 449 DLOG(ERROR) << "Invalid bad subnet prefix length: " |
448 << model.bad_subnet(i).prefix().size(); | 450 << model.bad_subnet(i).prefix().size(); |
449 continue; | 451 continue; |
450 } | 452 } |
451 // We precompute the mask for the given subnet size to speed up lookups. | 453 // We precompute the mask for the given subnet size to speed up lookups. |
452 // Basically we need to create a 16B long string which has the highest | 454 // Basically we need to create a 16B long string which has the highest |
453 // |size| bits sets to one. | 455 // |size| bits sets to one. |
454 std::string mask(net::kIPv6AddressSize, '\x00'); | 456 std::string mask(net::kIPv6AddressSize, '\x00'); |
455 mask.replace(0, size / 8, size / 8, '\xFF'); | 457 mask.replace(0, size / 8, size / 8, '\xFF'); |
456 if (size % 8) { | 458 if (size % 8) { |
457 mask[size / 8] = 0xFF << (8 - (size % 8)); | 459 mask[size / 8] = 0xFF << (8 - (size % 8)); |
458 } | 460 } |
459 (*bad_subnets)[mask].insert(model.bad_subnet(i).prefix()); | 461 (*bad_subnets)[mask].insert(model.bad_subnet(i).prefix()); |
460 } | 462 } |
461 } | 463 } |
| 464 |
| 465 // static |
| 466 bool ClientSideDetectionService::ModelHasValidHashIds( |
| 467 const ClientSideModel& model) { |
| 468 const int max_index = model.hashes_size() - 1; |
| 469 for (int i = 0; i < model.rule_size(); ++i) { |
| 470 for (int j = 0; j < model.rule(i).feature_size(); ++j) { |
| 471 if (model.rule(i).feature(j) < 0 || |
| 472 model.rule(i).feature(j) > max_index) { |
| 473 return false; |
| 474 } |
| 475 } |
| 476 } |
| 477 for (int i = 0; i < model.page_term_size(); ++i) { |
| 478 if (model.page_term(i) < 0 || model.page_term(i) > max_index) { |
| 479 return false; |
| 480 } |
| 481 } |
| 482 for (int i = 0; i < model.page_word_size(); ++i) { |
| 483 if (model.page_word(i) < 0 || model.page_word(i) > max_index) { |
| 484 return false; |
| 485 } |
| 486 } |
| 487 return true; |
| 488 } |
462 } // namespace safe_browsing | 489 } // namespace safe_browsing |
OLD | NEW |