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" |
11 #include "base/message_loop.h" | 11 #include "base/message_loop.h" |
12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
13 #include "base/string_util.h" | |
14 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
15 #include "base/task.h" | 14 #include "base/task.h" |
16 #include "base/time.h" | 15 #include "base/time.h" |
17 #include "chrome/browser/browser_process.h" | |
18 #include "chrome/browser/safe_browsing/browser_features.h" | |
19 #include "chrome/browser/safe_browsing/safe_browsing_service.h" | |
20 #include "chrome/common/net/http_return.h" | 16 #include "chrome/common/net/http_return.h" |
21 #include "chrome/common/safe_browsing/client_model.pb.h" | 17 #include "chrome/common/safe_browsing/client_model.pb.h" |
22 #include "chrome/common/safe_browsing/csd.pb.h" | 18 #include "chrome/common/safe_browsing/csd.pb.h" |
23 #include "chrome/common/safe_browsing/safebrowsing_messages.h" | 19 #include "chrome/common/safe_browsing/safebrowsing_messages.h" |
24 #include "chrome/renderer/safe_browsing/features.h" | |
25 #include "content/browser/browser_thread.h" | 20 #include "content/browser/browser_thread.h" |
26 #include "content/browser/renderer_host/render_process_host.h" | 21 #include "content/browser/renderer_host/render_process_host.h" |
27 #include "content/common/notification_service.h" | 22 #include "content/common/notification_service.h" |
28 #include "content/common/url_fetcher.h" | 23 #include "content/common/url_fetcher.h" |
29 #include "crypto/sha2.h" | 24 #include "crypto/sha2.h" |
30 #include "googleurl/src/gurl.h" | 25 #include "googleurl/src/gurl.h" |
31 #include "net/base/load_flags.h" | 26 #include "net/base/load_flags.h" |
32 #include "net/http/http_response_headers.h" | 27 #include "net/http/http_response_headers.h" |
33 #include "net/url_request/url_request_context_getter.h" | 28 #include "net/url_request/url_request_context_getter.h" |
34 #include "net/url_request/url_request_status.h" | 29 #include "net/url_request/url_request_status.h" |
(...skipping 27 matching lines...) Expand all Loading... |
62 GURL phishing_url; | 57 GURL phishing_url; |
63 }; | 58 }; |
64 | 59 |
65 ClientSideDetectionService::CacheState::CacheState(bool phish, base::Time time) | 60 ClientSideDetectionService::CacheState::CacheState(bool phish, base::Time time) |
66 : is_phishing(phish), | 61 : is_phishing(phish), |
67 timestamp(time) {} | 62 timestamp(time) {} |
68 | 63 |
69 ClientSideDetectionService::ClientSideDetectionService( | 64 ClientSideDetectionService::ClientSideDetectionService( |
70 net::URLRequestContextGetter* request_context_getter) | 65 net::URLRequestContextGetter* request_context_getter) |
71 : enabled_(false), | 66 : enabled_(false), |
72 sb_service_(g_browser_process->safe_browsing_service()), | |
73 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), | 67 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), |
74 request_context_getter_(request_context_getter) { | 68 request_context_getter_(request_context_getter) { |
75 InitializeAllowedFeatures(); | |
76 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED, | 69 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED, |
77 NotificationService::AllSources()); | 70 NotificationService::AllSources()); |
78 } | 71 } |
79 | 72 |
80 ClientSideDetectionService::~ClientSideDetectionService() { | 73 ClientSideDetectionService::~ClientSideDetectionService() { |
81 method_factory_.RevokeAll(); | 74 method_factory_.RevokeAll(); |
82 STLDeleteContainerPairPointers(client_phishing_reports_.begin(), | 75 STLDeleteContainerPairPointers(client_phishing_reports_.begin(), |
83 client_phishing_reports_.end()); | 76 client_phishing_reports_.end()); |
84 client_phishing_reports_.clear(); | 77 client_phishing_reports_.clear(); |
85 } | 78 } |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 // the model's age. | 259 // the model's age. |
267 *model_max_age_ += base::TimeDelta::FromMinutes(1); | 260 *model_max_age_ += base::TimeDelta::FromMinutes(1); |
268 delay_ms = model_max_age_->InMilliseconds(); | 261 delay_ms = model_max_age_->InMilliseconds(); |
269 } | 262 } |
270 model_max_age_.reset(); | 263 model_max_age_.reset(); |
271 | 264 |
272 // Schedule the next model reload. | 265 // Schedule the next model reload. |
273 ScheduleFetchModel(delay_ms); | 266 ScheduleFetchModel(delay_ms); |
274 } | 267 } |
275 | 268 |
276 void ClientSideDetectionService::SanitizeRequestForPingback( | |
277 const ClientPhishingRequest& full_request, | |
278 ClientPhishingRequest* sanitized_request) { | |
279 DCHECK(full_request.IsInitialized()); | |
280 sanitized_request->Clear(); | |
281 if (full_request.has_suffix_prefix_hash()) { | |
282 sanitized_request->set_suffix_prefix_hash( | |
283 full_request.suffix_prefix_hash()); | |
284 } | |
285 sanitized_request->set_client_score(full_request.client_score()); | |
286 if (full_request.has_is_phishing()) { | |
287 sanitized_request->set_is_phishing(full_request.is_phishing()); | |
288 } | |
289 | |
290 for (int i = 0; i < full_request.feature_map_size(); ++i) { | |
291 const ClientPhishingRequest_Feature& feature = full_request.feature_map(i); | |
292 if (allowed_features_.find(feature.name()) != allowed_features_.end()) { | |
293 sanitized_request->add_feature_map()->CopyFrom(feature); | |
294 } | |
295 } | |
296 | |
297 if (full_request.has_model_version()) { | |
298 sanitized_request->set_model_version(full_request.model_version()); | |
299 } | |
300 | |
301 for (int i = 0; i < full_request.non_model_feature_map_size(); ++i) { | |
302 const ClientPhishingRequest_Feature& feature = | |
303 full_request.non_model_feature_map(i); | |
304 if (allowed_features_.find(feature.name()) != allowed_features_.end()) { | |
305 sanitized_request->add_non_model_feature_map()->CopyFrom(feature); | |
306 } | |
307 } | |
308 } | |
309 | |
310 void ClientSideDetectionService::StartClientReportPhishingRequest( | 269 void ClientSideDetectionService::StartClientReportPhishingRequest( |
311 ClientPhishingRequest* verdict, | 270 ClientPhishingRequest* verdict, |
312 ClientReportPhishingRequestCallback* callback) { | 271 ClientReportPhishingRequestCallback* callback) { |
313 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 272 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
314 scoped_ptr<ClientPhishingRequest> request(verdict); | 273 scoped_ptr<ClientPhishingRequest> request(verdict); |
315 scoped_ptr<ClientReportPhishingRequestCallback> cb(callback); | 274 scoped_ptr<ClientReportPhishingRequestCallback> cb(callback); |
316 | 275 |
317 if (!enabled_) { | 276 if (!enabled_) { |
318 if (cb.get()) | 277 if (cb.get()) |
319 cb->Run(GURL(request->url()), false); | 278 cb->Run(GURL(request->url()), false); |
320 return; | 279 return; |
321 } | 280 } |
322 | 281 |
323 // Create the version of the request proto that we'll send over the network. | |
324 ClientPhishingRequest request_to_send; | |
325 if (sb_service_ && sb_service_->CanReportStats()) { | |
326 request_to_send.CopyFrom(*request); | |
327 } else { | |
328 SanitizeRequestForPingback(*request, &request_to_send); | |
329 } | |
330 | |
331 std::string request_data; | 282 std::string request_data; |
332 if (!request_to_send.SerializeToString(&request_data)) { | 283 if (!request->SerializeToString(&request_data)) { |
333 UMA_HISTOGRAM_COUNTS("SBClientPhishing.RequestNotSerialized", 1); | 284 UMA_HISTOGRAM_COUNTS("SBClientPhishing.RequestNotSerialized", 1); |
334 VLOG(1) << "Unable to serialize the CSD request. Proto file changed?"; | 285 VLOG(1) << "Unable to serialize the CSD request. Proto file changed?"; |
335 if (cb.get()) { | 286 if (cb.get()) { |
336 cb->Run(GURL(request->url()), false); | 287 cb->Run(GURL(request->url()), false); |
337 } | 288 } |
338 return; | 289 return; |
339 } | 290 } |
340 | 291 |
341 URLFetcher* fetcher = URLFetcher::Create(0 /* ID is not used */, | 292 URLFetcher* fetcher = URLFetcher::Create(0 /* ID is not used */, |
342 GURL(kClientReportPhishingUrl), | 293 GURL(kClientReportPhishingUrl), |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
512 private_networks_.push_back(std::make_pair(ip_number, prefix_length)); | 463 private_networks_.push_back(std::make_pair(ip_number, prefix_length)); |
513 } else { | 464 } else { |
514 DLOG(FATAL) << "Unable to parse IP address range: " | 465 DLOG(FATAL) << "Unable to parse IP address range: " |
515 << kPrivateNetworks[i]; | 466 << kPrivateNetworks[i]; |
516 return false; | 467 return false; |
517 } | 468 } |
518 } | 469 } |
519 return true; | 470 return true; |
520 } | 471 } |
521 | 472 |
522 void ClientSideDetectionService::InitializeAllowedFeatures() { | |
523 static const char* const kAllowedFeatures[] = { | |
524 // Renderer (model) features. | |
525 features::kUrlHostIsIpAddress, | |
526 features::kUrlNumOtherHostTokensGTOne, | |
527 features::kUrlNumOtherHostTokensGTThree, | |
528 features::kPageHasForms, | |
529 features::kPageActionOtherDomainFreq, | |
530 features::kPageHasTextInputs, | |
531 features::kPageHasPswdInputs, | |
532 features::kPageHasRadioInputs, | |
533 features::kPageHasCheckInputs, | |
534 features::kPageExternalLinksFreq, | |
535 features::kPageSecureLinksFreq, | |
536 features::kPageNumScriptTagsGTOne, | |
537 features::kPageNumScriptTagsGTSix, | |
538 features::kPageImgOtherDomainFreq, | |
539 // Browser (non-model) features. | |
540 features::kUrlHistoryVisitCount, | |
541 features::kUrlHistoryTypedCount, | |
542 features::kUrlHistoryLinkCount, | |
543 features::kUrlHistoryVisitCountMoreThan24hAgo, | |
544 features::kHttpHostVisitCount, | |
545 features::kHttpsHostVisitCount, | |
546 features::kFirstHttpHostVisitMoreThan24hAgo, | |
547 features::kFirstHttpsHostVisitMoreThan24hAgo, | |
548 features::kHasSSLReferrer, | |
549 features::kPageTransitionType, | |
550 features::kIsFirstNavigation, | |
551 features::kSafeBrowsingIsSubresource, | |
552 features::kSafeBrowsingThreatType, | |
553 }; | |
554 | |
555 for (size_t i = 0; i < arraysize(kAllowedFeatures); ++i) { | |
556 allowed_features_.insert(kAllowedFeatures[i]); | |
557 } | |
558 } | |
559 | |
560 // static | 473 // static |
561 void ClientSideDetectionService::SetBadSubnets(const ClientSideModel& model, | 474 void ClientSideDetectionService::SetBadSubnets(const ClientSideModel& model, |
562 BadSubnetMap* bad_subnets) { | 475 BadSubnetMap* bad_subnets) { |
563 bad_subnets->clear(); | 476 bad_subnets->clear(); |
564 for (int i = 0; i < model.bad_subnet_size(); ++i) { | 477 for (int i = 0; i < model.bad_subnet_size(); ++i) { |
565 int size = model.bad_subnet(i).size(); | 478 int size = model.bad_subnet(i).size(); |
566 if (size < 0 || size > static_cast<int>(net::kIPv6AddressSize) * 8) { | 479 if (size < 0 || size > static_cast<int>(net::kIPv6AddressSize) * 8) { |
567 DLOG(ERROR) << "Invalid bad subnet size: " << size; | 480 DLOG(ERROR) << "Invalid bad subnet size: " << size; |
568 continue; | 481 continue; |
569 } | 482 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
602 } | 515 } |
603 } | 516 } |
604 for (int i = 0; i < model.page_word_size(); ++i) { | 517 for (int i = 0; i < model.page_word_size(); ++i) { |
605 if (model.page_word(i) < 0 || model.page_word(i) > max_index) { | 518 if (model.page_word(i) < 0 || model.page_word(i) > max_index) { |
606 return false; | 519 return false; |
607 } | 520 } |
608 } | 521 } |
609 return true; | 522 return true; |
610 } | 523 } |
611 } // namespace safe_browsing | 524 } // namespace safe_browsing |
OLD | NEW |