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