Chromium Code Reviews| OLD | NEW |
|---|---|
| 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/safe_browsing_database.h" | 5 #include "chrome/browser/safe_browsing/safe_browsing_database.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <iterator> | 8 #include <iterator> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 498 DCHECK(side_effect_free_whitelist_filename_.empty()); | 498 DCHECK(side_effect_free_whitelist_filename_.empty()); |
| 499 DCHECK(ip_blacklist_filename_.empty()); | 499 DCHECK(ip_blacklist_filename_.empty()); |
| 500 | 500 |
| 501 browse_filename_ = BrowseDBFilename(filename_base); | 501 browse_filename_ = BrowseDBFilename(filename_base); |
| 502 browse_prefix_set_filename_ = PrefixSetForFilename(browse_filename_); | 502 browse_prefix_set_filename_ = PrefixSetForFilename(browse_filename_); |
| 503 | 503 |
| 504 browse_store_->Init( | 504 browse_store_->Init( |
| 505 browse_filename_, | 505 browse_filename_, |
| 506 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | 506 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, |
| 507 base::Unretained(this))); | 507 base::Unretained(this))); |
| 508 DVLOG(1) << "Init browse store: " << browse_filename_.value(); | |
| 509 | 508 |
| 510 { | 509 { |
| 511 // NOTE: There is no need to grab the lock in this function, since | 510 // NOTE: There is no need to grab the lock in this function, since |
| 512 // until it returns, there are no pointers to this class on other | 511 // until it returns, there are no pointers to this class on other |
| 513 // threads. Then again, that means there is no possibility of | 512 // threads. Then again, that means there is no possibility of |
| 514 // contention on the lock... | 513 // contention on the lock... |
| 515 base::AutoLock locked(lookup_lock_); | 514 base::AutoLock locked(lookup_lock_); |
| 516 cached_browse_hashes_.clear(); | 515 cached_browse_hashes_.clear(); |
| 517 LoadPrefixSet(); | 516 LoadPrefixSet(); |
| 518 } | 517 } |
| 519 | 518 |
| 520 if (download_store_.get()) { | 519 if (download_store_.get()) { |
| 521 download_filename_ = DownloadDBFilename(filename_base); | 520 download_filename_ = DownloadDBFilename(filename_base); |
| 522 download_store_->Init( | 521 download_store_->Init( |
| 523 download_filename_, | 522 download_filename_, |
| 524 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | 523 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, |
| 525 base::Unretained(this))); | 524 base::Unretained(this))); |
| 526 DVLOG(1) << "Init download store: " << download_filename_.value(); | |
| 527 } | 525 } |
| 528 | 526 |
| 529 if (csd_whitelist_store_.get()) { | 527 if (csd_whitelist_store_.get()) { |
| 530 csd_whitelist_filename_ = CsdWhitelistDBFilename(filename_base); | 528 csd_whitelist_filename_ = CsdWhitelistDBFilename(filename_base); |
| 531 csd_whitelist_store_->Init( | 529 csd_whitelist_store_->Init( |
| 532 csd_whitelist_filename_, | 530 csd_whitelist_filename_, |
| 533 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | 531 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, |
| 534 base::Unretained(this))); | 532 base::Unretained(this))); |
| 535 DVLOG(1) << "Init csd whitelist store: " << csd_whitelist_filename_.value(); | 533 |
| 536 std::vector<SBAddFullHash> full_hashes; | 534 std::vector<SBAddFullHash> full_hashes; |
| 537 if (csd_whitelist_store_->GetAddFullHashes(&full_hashes)) { | 535 if (csd_whitelist_store_->GetAddFullHashes(&full_hashes)) { |
| 538 LoadWhitelist(full_hashes, &csd_whitelist_); | 536 LoadWhitelist(full_hashes, &csd_whitelist_); |
| 539 } else { | 537 } else { |
| 540 WhitelistEverything(&csd_whitelist_); | 538 WhitelistEverything(&csd_whitelist_); |
| 541 } | 539 } |
| 542 } else { | 540 } else { |
| 543 WhitelistEverything(&csd_whitelist_); // Just to be safe. | 541 WhitelistEverything(&csd_whitelist_); // Just to be safe. |
| 544 } | 542 } |
| 545 | 543 |
| 546 if (download_whitelist_store_.get()) { | 544 if (download_whitelist_store_.get()) { |
| 547 download_whitelist_filename_ = DownloadWhitelistDBFilename(filename_base); | 545 download_whitelist_filename_ = DownloadWhitelistDBFilename(filename_base); |
| 548 download_whitelist_store_->Init( | 546 download_whitelist_store_->Init( |
| 549 download_whitelist_filename_, | 547 download_whitelist_filename_, |
| 550 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | 548 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, |
| 551 base::Unretained(this))); | 549 base::Unretained(this))); |
| 552 DVLOG(1) << "Init download whitelist store: " | 550 |
| 553 << download_whitelist_filename_.value(); | |
| 554 std::vector<SBAddFullHash> full_hashes; | 551 std::vector<SBAddFullHash> full_hashes; |
| 555 if (download_whitelist_store_->GetAddFullHashes(&full_hashes)) { | 552 if (download_whitelist_store_->GetAddFullHashes(&full_hashes)) { |
| 556 LoadWhitelist(full_hashes, &download_whitelist_); | 553 LoadWhitelist(full_hashes, &download_whitelist_); |
| 557 } else { | 554 } else { |
| 558 WhitelistEverything(&download_whitelist_); | 555 WhitelistEverything(&download_whitelist_); |
| 559 } | 556 } |
| 560 } else { | 557 } else { |
| 561 WhitelistEverything(&download_whitelist_); // Just to be safe. | 558 WhitelistEverything(&download_whitelist_); // Just to be safe. |
| 562 } | 559 } |
| 563 | 560 |
| 564 if (extension_blacklist_store_.get()) { | 561 if (extension_blacklist_store_.get()) { |
| 565 extension_blacklist_filename_ = ExtensionBlacklistDBFilename(filename_base); | 562 extension_blacklist_filename_ = ExtensionBlacklistDBFilename(filename_base); |
| 566 extension_blacklist_store_->Init( | 563 extension_blacklist_store_->Init( |
| 567 extension_blacklist_filename_, | 564 extension_blacklist_filename_, |
| 568 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | 565 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, |
| 569 base::Unretained(this))); | 566 base::Unretained(this))); |
| 570 DVLOG(1) << "Init extension blacklist store: " | |
| 571 << extension_blacklist_filename_.value(); | |
| 572 } | 567 } |
| 573 | 568 |
| 574 if (side_effect_free_whitelist_store_.get()) { | 569 if (side_effect_free_whitelist_store_.get()) { |
| 575 side_effect_free_whitelist_filename_ = | 570 side_effect_free_whitelist_filename_ = |
| 576 SideEffectFreeWhitelistDBFilename(filename_base); | 571 SideEffectFreeWhitelistDBFilename(filename_base); |
| 577 side_effect_free_whitelist_prefix_set_filename_ = | 572 side_effect_free_whitelist_prefix_set_filename_ = |
| 578 PrefixSetForFilename(side_effect_free_whitelist_filename_); | 573 PrefixSetForFilename(side_effect_free_whitelist_filename_); |
| 579 side_effect_free_whitelist_store_->Init( | 574 side_effect_free_whitelist_store_->Init( |
| 580 side_effect_free_whitelist_filename_, | 575 side_effect_free_whitelist_filename_, |
| 581 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | 576 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, |
| 582 base::Unretained(this))); | 577 base::Unretained(this))); |
| 583 DVLOG(1) << "Init side-effect free whitelist store: " | |
| 584 << side_effect_free_whitelist_filename_.value(); | |
| 585 | 578 |
| 586 // If there is no database, the filter cannot be used. | 579 // If there is no database, the filter cannot be used. |
| 587 base::File::Info db_info; | 580 base::File::Info db_info; |
| 588 if (base::GetFileInfo(side_effect_free_whitelist_filename_, &db_info) | 581 if (base::GetFileInfo(side_effect_free_whitelist_filename_, &db_info) |
| 589 && db_info.size != 0) { | 582 && db_info.size != 0) { |
| 590 const base::TimeTicks before = base::TimeTicks::Now(); | 583 const base::TimeTicks before = base::TimeTicks::Now(); |
| 591 side_effect_free_whitelist_prefix_set_ = | 584 side_effect_free_whitelist_prefix_set_ = |
| 592 safe_browsing::PrefixSet::LoadFile( | 585 safe_browsing::PrefixSet::LoadFile( |
| 593 side_effect_free_whitelist_prefix_set_filename_); | 586 side_effect_free_whitelist_prefix_set_filename_); |
| 594 DVLOG(1) << "SafeBrowsingDatabaseNew read side-effect free whitelist " | |
| 595 << "prefix set in " | |
| 596 << (base::TimeTicks::Now() - before).InMilliseconds() << " ms"; | |
| 597 UMA_HISTOGRAM_TIMES("SB2.SideEffectFreeWhitelistPrefixSetLoad", | 587 UMA_HISTOGRAM_TIMES("SB2.SideEffectFreeWhitelistPrefixSetLoad", |
| 598 base::TimeTicks::Now() - before); | 588 base::TimeTicks::Now() - before); |
| 599 if (!side_effect_free_whitelist_prefix_set_.get()) | 589 if (!side_effect_free_whitelist_prefix_set_.get()) |
| 600 RecordFailure(FAILURE_SIDE_EFFECT_FREE_WHITELIST_PREFIX_SET_READ); | 590 RecordFailure(FAILURE_SIDE_EFFECT_FREE_WHITELIST_PREFIX_SET_READ); |
| 601 } | 591 } |
| 602 } else { | 592 } else { |
| 603 // Delete any files of the side-effect free sidelist that may be around | 593 // Delete any files of the side-effect free sidelist that may be around |
| 604 // from when it was previously enabled. | 594 // from when it was previously enabled. |
| 605 SafeBrowsingStoreFile::DeleteStore( | 595 SafeBrowsingStoreFile::DeleteStore( |
| 606 SideEffectFreeWhitelistDBFilename(filename_base)); | 596 SideEffectFreeWhitelistDBFilename(filename_base)); |
| 607 } | 597 } |
| 608 | 598 |
| 609 if (ip_blacklist_store_.get()) { | 599 if (ip_blacklist_store_.get()) { |
| 610 ip_blacklist_filename_ = IpBlacklistDBFilename(filename_base); | 600 ip_blacklist_filename_ = IpBlacklistDBFilename(filename_base); |
| 611 ip_blacklist_store_->Init( | 601 ip_blacklist_store_->Init( |
| 612 ip_blacklist_filename_, | 602 ip_blacklist_filename_, |
| 613 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | 603 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, |
| 614 base::Unretained(this))); | 604 base::Unretained(this))); |
| 615 DVLOG(1) << "SafeBrowsingDatabaseNew read ip blacklist: " | 605 |
| 616 << ip_blacklist_filename_.value(); | |
| 617 std::vector<SBAddFullHash> full_hashes; | 606 std::vector<SBAddFullHash> full_hashes; |
| 618 if (ip_blacklist_store_->GetAddFullHashes(&full_hashes)) { | 607 if (ip_blacklist_store_->GetAddFullHashes(&full_hashes)) { |
| 619 LoadIpBlacklist(full_hashes); | 608 LoadIpBlacklist(full_hashes); |
| 620 } else { | 609 } else { |
| 621 DVLOG(1) << "Unable to load full hashes from the IP blacklist."; | |
| 622 LoadIpBlacklist(std::vector<SBAddFullHash>()); // Clear the list. | 610 LoadIpBlacklist(std::vector<SBAddFullHash>()); // Clear the list. |
| 623 } | 611 } |
| 624 } | 612 } |
| 625 } | 613 } |
| 626 | 614 |
| 627 bool SafeBrowsingDatabaseNew::ResetDatabase() { | 615 bool SafeBrowsingDatabaseNew::ResetDatabase() { |
| 628 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); | 616 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 629 | 617 |
| 630 // Delete files on disk. | 618 // Delete files on disk. |
| 631 // TODO(shess): Hard to see where one might want to delete without a | 619 // TODO(shess): Hard to see where one might want to delete without a |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 755 // from disk, or the first update populates it. Bail out without a hit if | 743 // from disk, or the first update populates it. Bail out without a hit if |
| 756 // not yet available. | 744 // not yet available. |
| 757 if (!side_effect_free_whitelist_prefix_set_.get()) | 745 if (!side_effect_free_whitelist_prefix_set_.get()) |
| 758 return false; | 746 return false; |
| 759 | 747 |
| 760 return side_effect_free_whitelist_prefix_set_->Exists(full_hash); | 748 return side_effect_free_whitelist_prefix_set_->Exists(full_hash); |
| 761 } | 749 } |
| 762 | 750 |
| 763 bool SafeBrowsingDatabaseNew::ContainsMalwareIP(const std::string& ip_address) { | 751 bool SafeBrowsingDatabaseNew::ContainsMalwareIP(const std::string& ip_address) { |
| 764 net::IPAddressNumber ip_number; | 752 net::IPAddressNumber ip_number; |
| 765 if (!net::ParseIPLiteralToNumber(ip_address, &ip_number)) { | 753 if (!net::ParseIPLiteralToNumber(ip_address, &ip_number)) |
| 766 DVLOG(2) << "Unable to parse IP address: '" << ip_address << "'"; | |
| 767 return false; | 754 return false; |
| 768 } | 755 if (ip_number.size() == net::kIPv4AddressSize) |
| 769 if (ip_number.size() == net::kIPv4AddressSize) { | |
| 770 ip_number = net::ConvertIPv4NumberToIPv6Number(ip_number); | 756 ip_number = net::ConvertIPv4NumberToIPv6Number(ip_number); |
| 771 } | 757 if (ip_number.size() != net::kIPv6AddressSize) |
| 772 if (ip_number.size() != net::kIPv6AddressSize) { | |
| 773 DVLOG(2) << "Unable to convert IPv4 address to IPv6: '" | |
| 774 << ip_address << "'"; | |
| 775 return false; // better safe than sorry. | 758 return false; // better safe than sorry. |
| 776 } | 759 |
| 777 // This function can be called from any thread. | 760 // This function can be called from any thread. |
| 778 base::AutoLock locked(lookup_lock_); | 761 base::AutoLock locked(lookup_lock_); |
| 779 for (IPBlacklist::const_iterator it = ip_blacklist_.begin(); | 762 for (IPBlacklist::const_iterator it = ip_blacklist_.begin(); |
| 780 it != ip_blacklist_.end(); | 763 it != ip_blacklist_.end(); |
| 781 ++it) { | 764 ++it) { |
| 782 const std::string& mask = it->first; | 765 const std::string& mask = it->first; |
| 783 DCHECK_EQ(mask.size(), ip_number.size()); | 766 DCHECK_EQ(mask.size(), ip_number.size()); |
| 784 std::string subnet(net::kIPv6AddressSize, '\0'); | 767 std::string subnet(net::kIPv6AddressSize, '\0'); |
| 785 for (size_t i = 0; i < net::kIPv6AddressSize; ++i) { | 768 for (size_t i = 0; i < net::kIPv6AddressSize; ++i) { |
| 786 subnet[i] = ip_number[i] & mask[i]; | 769 subnet[i] = ip_number[i] & mask[i]; |
| 787 } | 770 } |
| 788 const std::string hash = base::SHA1HashString(subnet); | 771 const std::string hash = base::SHA1HashString(subnet); |
| 789 DVLOG(2) << "Lookup Malware IP: " | 772 DVLOG(2) << "Lookup Malware IP: " |
| 790 << " ip:" << ip_address | 773 << " ip:" << ip_address |
| 791 << " mask:" << base::HexEncode(mask.data(), mask.size()) | 774 << " mask:" << base::HexEncode(mask.data(), mask.size()) |
| 792 << " subnet:" << base::HexEncode(subnet.data(), subnet.size()) | 775 << " subnet:" << base::HexEncode(subnet.data(), subnet.size()) |
| 793 << " hash:" << base::HexEncode(hash.data(), hash.size()); | 776 << " hash:" << base::HexEncode(hash.data(), hash.size()); |
|
Scott Hess - ex-Googler
2014/06/18 00:08:41
I did not remove this one because it looks complic
| |
| 794 if (it->second.count(hash) > 0) { | 777 if (it->second.count(hash) > 0) { |
| 795 return true; | 778 return true; |
| 796 } | 779 } |
| 797 } | 780 } |
| 798 return false; | 781 return false; |
| 799 } | 782 } |
| 800 | 783 |
| 801 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedString( | 784 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedString( |
| 802 const std::string& str) { | 785 const std::string& str) { |
| 803 std::vector<SBFullHash> hashes; | 786 std::vector<SBFullHash> hashes; |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 895 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); | 878 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 896 | 879 |
| 897 if (corruption_detected_ || chunks.empty()) | 880 if (corruption_detected_ || chunks.empty()) |
| 898 return; | 881 return; |
| 899 | 882 |
| 900 const base::TimeTicks before = base::TimeTicks::Now(); | 883 const base::TimeTicks before = base::TimeTicks::Now(); |
| 901 | 884 |
| 902 // TODO(shess): The caller should just pass list_id. | 885 // TODO(shess): The caller should just pass list_id. |
| 903 const safe_browsing_util::ListType list_id = | 886 const safe_browsing_util::ListType list_id = |
| 904 safe_browsing_util::GetListId(list_name); | 887 safe_browsing_util::GetListId(list_name); |
| 905 DVLOG(2) << list_name << ": " << list_id; | |
| 906 | 888 |
| 907 SafeBrowsingStore* store = GetStore(list_id); | 889 SafeBrowsingStore* store = GetStore(list_id); |
| 908 if (!store) return; | 890 if (!store) return; |
| 909 | 891 |
| 910 change_detected_ = true; | 892 change_detected_ = true; |
| 911 | 893 |
| 912 // TODO(shess): I believe that the list is always add or sub. Can this use | 894 // TODO(shess): I believe that the list is always add or sub. Can this use |
| 913 // that productively? | 895 // that productively? |
| 914 store->BeginChunk(); | 896 store->BeginChunk(); |
| 915 for (size_t i = 0; i < chunks.size(); ++i) { | 897 for (size_t i = 0; i < chunks.size(); ++i) { |
| (...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1261 // TODO(shess): If |CacheHashResults()| is posted between the | 1243 // TODO(shess): If |CacheHashResults()| is posted between the |
| 1262 // earlier lock and this clear, those pending hashes will be lost. | 1244 // earlier lock and this clear, those pending hashes will be lost. |
| 1263 // It could be fixed by only removing hashes which were collected | 1245 // It could be fixed by only removing hashes which were collected |
| 1264 // at the earlier point. I believe that is fail-safe as-is (the | 1246 // at the earlier point. I believe that is fail-safe as-is (the |
| 1265 // hash will be fetched again). | 1247 // hash will be fetched again). |
| 1266 cached_browse_hashes_.clear(); | 1248 cached_browse_hashes_.clear(); |
| 1267 prefix_miss_cache_.clear(); | 1249 prefix_miss_cache_.clear(); |
| 1268 browse_prefix_set_.swap(prefix_set); | 1250 browse_prefix_set_.swap(prefix_set); |
| 1269 } | 1251 } |
| 1270 | 1252 |
| 1271 DVLOG(1) << "SafeBrowsingDatabaseImpl built prefix set in " | |
| 1272 << (base::TimeTicks::Now() - before).InMilliseconds() | |
| 1273 << " ms total."; | |
| 1274 UMA_HISTOGRAM_LONG_TIMES("SB2.BuildFilter", base::TimeTicks::Now() - before); | 1253 UMA_HISTOGRAM_LONG_TIMES("SB2.BuildFilter", base::TimeTicks::Now() - before); |
| 1275 | 1254 |
| 1276 // Persist the prefix set to disk. Since only this thread changes | 1255 // Persist the prefix set to disk. Since only this thread changes |
| 1277 // |browse_prefix_set_|, there is no need to lock. | 1256 // |browse_prefix_set_|, there is no need to lock. |
| 1278 WritePrefixSet(); | 1257 WritePrefixSet(); |
| 1279 | 1258 |
| 1280 // Gather statistics. | 1259 // Gather statistics. |
| 1281 if (got_counters && metric->GetIOCounters(&io_after)) { | 1260 if (got_counters && metric->GetIOCounters(&io_after)) { |
| 1282 UMA_HISTOGRAM_COUNTS("SB2.BuildReadKilobytes", | 1261 UMA_HISTOGRAM_COUNTS("SB2.BuildReadKilobytes", |
| 1283 static_cast<int>(io_after.ReadTransferCount - | 1262 static_cast<int>(io_after.ReadTransferCount - |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1319 | 1298 |
| 1320 // Swap in the newly built prefix set. | 1299 // Swap in the newly built prefix set. |
| 1321 { | 1300 { |
| 1322 base::AutoLock locked(lookup_lock_); | 1301 base::AutoLock locked(lookup_lock_); |
| 1323 side_effect_free_whitelist_prefix_set_.swap(prefix_set); | 1302 side_effect_free_whitelist_prefix_set_.swap(prefix_set); |
| 1324 } | 1303 } |
| 1325 | 1304 |
| 1326 const base::TimeTicks before = base::TimeTicks::Now(); | 1305 const base::TimeTicks before = base::TimeTicks::Now(); |
| 1327 const bool write_ok = side_effect_free_whitelist_prefix_set_->WriteFile( | 1306 const bool write_ok = side_effect_free_whitelist_prefix_set_->WriteFile( |
| 1328 side_effect_free_whitelist_prefix_set_filename_); | 1307 side_effect_free_whitelist_prefix_set_filename_); |
| 1329 DVLOG(1) << "SafeBrowsingDatabaseNew wrote side-effect free whitelist prefix " | |
| 1330 << "set in " << (base::TimeTicks::Now() - before).InMilliseconds() | |
| 1331 << " ms"; | |
| 1332 UMA_HISTOGRAM_TIMES("SB2.SideEffectFreePrefixSetWrite", | 1308 UMA_HISTOGRAM_TIMES("SB2.SideEffectFreePrefixSetWrite", |
| 1333 base::TimeTicks::Now() - before); | 1309 base::TimeTicks::Now() - before); |
| 1334 | 1310 |
| 1335 if (!write_ok) | 1311 if (!write_ok) |
| 1336 RecordFailure(FAILURE_SIDE_EFFECT_FREE_WHITELIST_PREFIX_SET_WRITE); | 1312 RecordFailure(FAILURE_SIDE_EFFECT_FREE_WHITELIST_PREFIX_SET_WRITE); |
| 1337 | 1313 |
| 1338 // Gather statistics. | 1314 // Gather statistics. |
| 1339 int64 file_size = GetFileSizeOrZero( | 1315 int64 file_size = GetFileSizeOrZero( |
| 1340 side_effect_free_whitelist_prefix_set_filename_); | 1316 side_effect_free_whitelist_prefix_set_filename_); |
| 1341 UMA_HISTOGRAM_COUNTS("SB2.SideEffectFreeWhitelistPrefixSetKilobytes", | 1317 UMA_HISTOGRAM_COUNTS("SB2.SideEffectFreeWhitelistPrefixSetKilobytes", |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1377 base::MessageLoop::current()->PostTask(FROM_HERE, | 1353 base::MessageLoop::current()->PostTask(FROM_HERE, |
| 1378 base::Bind(&SafeBrowsingDatabaseNew::OnHandleCorruptDatabase, | 1354 base::Bind(&SafeBrowsingDatabaseNew::OnHandleCorruptDatabase, |
| 1379 reset_factory_.GetWeakPtr())); | 1355 reset_factory_.GetWeakPtr())); |
| 1380 } | 1356 } |
| 1381 } | 1357 } |
| 1382 | 1358 |
| 1383 void SafeBrowsingDatabaseNew::OnHandleCorruptDatabase() { | 1359 void SafeBrowsingDatabaseNew::OnHandleCorruptDatabase() { |
| 1384 RecordFailure(FAILURE_DATABASE_CORRUPT_HANDLER); | 1360 RecordFailure(FAILURE_DATABASE_CORRUPT_HANDLER); |
| 1385 corruption_detected_ = true; // Stop updating the database. | 1361 corruption_detected_ = true; // Stop updating the database. |
| 1386 ResetDatabase(); | 1362 ResetDatabase(); |
| 1363 | |
| 1364 // NOTE(shess): ResetDatabase() should remove the corruption, so this should | |
| 1365 // only happen once. If you are here because you are hitting this after a | |
| 1366 // restart, then I would be very interested in working with you to figure out | |
| 1367 // what is happening, since it may affect real users. | |
| 1387 DLOG(FATAL) << "SafeBrowsing database was corrupt and reset"; | 1368 DLOG(FATAL) << "SafeBrowsing database was corrupt and reset"; |
| 1388 } | 1369 } |
| 1389 | 1370 |
| 1390 // TODO(shess): I'm not clear why this code doesn't have any | 1371 // TODO(shess): I'm not clear why this code doesn't have any |
| 1391 // real error-handling. | 1372 // real error-handling. |
| 1392 void SafeBrowsingDatabaseNew::LoadPrefixSet() { | 1373 void SafeBrowsingDatabaseNew::LoadPrefixSet() { |
| 1393 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); | 1374 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 1394 DCHECK(!browse_prefix_set_filename_.empty()); | 1375 DCHECK(!browse_prefix_set_filename_.empty()); |
| 1395 | 1376 |
| 1396 // If there is no database, the filter cannot be used. | 1377 // If there is no database, the filter cannot be used. |
| 1397 base::File::Info db_info; | 1378 base::File::Info db_info; |
| 1398 if (!base::GetFileInfo(browse_filename_, &db_info) || db_info.size == 0) | 1379 if (!base::GetFileInfo(browse_filename_, &db_info) || db_info.size == 0) |
| 1399 return; | 1380 return; |
| 1400 | 1381 |
| 1401 // Cleanup any stale bloom filter (no longer used). | 1382 // Cleanup any stale bloom filter (no longer used). |
| 1402 // TODO(shess): Track failure to delete? | 1383 // TODO(shess): Track failure to delete? |
| 1403 base::FilePath bloom_filter_filename = | 1384 base::FilePath bloom_filter_filename = |
| 1404 BloomFilterForFilename(browse_filename_); | 1385 BloomFilterForFilename(browse_filename_); |
| 1405 base::DeleteFile(bloom_filter_filename, false); | 1386 base::DeleteFile(bloom_filter_filename, false); |
| 1406 | 1387 |
| 1407 const base::TimeTicks before = base::TimeTicks::Now(); | 1388 const base::TimeTicks before = base::TimeTicks::Now(); |
| 1408 browse_prefix_set_ = safe_browsing::PrefixSet::LoadFile( | 1389 browse_prefix_set_ = safe_browsing::PrefixSet::LoadFile( |
| 1409 browse_prefix_set_filename_); | 1390 browse_prefix_set_filename_); |
| 1410 DVLOG(1) << "SafeBrowsingDatabaseNew read prefix set in " | |
| 1411 << (base::TimeTicks::Now() - before).InMilliseconds() << " ms"; | |
| 1412 UMA_HISTOGRAM_TIMES("SB2.PrefixSetLoad", base::TimeTicks::Now() - before); | 1391 UMA_HISTOGRAM_TIMES("SB2.PrefixSetLoad", base::TimeTicks::Now() - before); |
| 1413 | 1392 |
| 1414 if (!browse_prefix_set_.get()) | 1393 if (!browse_prefix_set_.get()) |
| 1415 RecordFailure(FAILURE_BROWSE_PREFIX_SET_READ); | 1394 RecordFailure(FAILURE_BROWSE_PREFIX_SET_READ); |
| 1416 } | 1395 } |
| 1417 | 1396 |
| 1418 bool SafeBrowsingDatabaseNew::Delete() { | 1397 bool SafeBrowsingDatabaseNew::Delete() { |
| 1419 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); | 1398 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 1420 | 1399 |
| 1421 const bool r1 = browse_store_->Delete(); | 1400 const bool r1 = browse_store_->Delete(); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1470 | 1449 |
| 1471 void SafeBrowsingDatabaseNew::WritePrefixSet() { | 1450 void SafeBrowsingDatabaseNew::WritePrefixSet() { |
| 1472 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); | 1451 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 1473 | 1452 |
| 1474 if (!browse_prefix_set_.get()) | 1453 if (!browse_prefix_set_.get()) |
| 1475 return; | 1454 return; |
| 1476 | 1455 |
| 1477 const base::TimeTicks before = base::TimeTicks::Now(); | 1456 const base::TimeTicks before = base::TimeTicks::Now(); |
| 1478 const bool write_ok = browse_prefix_set_->WriteFile( | 1457 const bool write_ok = browse_prefix_set_->WriteFile( |
| 1479 browse_prefix_set_filename_); | 1458 browse_prefix_set_filename_); |
| 1480 DVLOG(1) << "SafeBrowsingDatabaseNew wrote prefix set in " | |
| 1481 << (base::TimeTicks::Now() - before).InMilliseconds() << " ms"; | |
| 1482 UMA_HISTOGRAM_TIMES("SB2.PrefixSetWrite", base::TimeTicks::Now() - before); | 1459 UMA_HISTOGRAM_TIMES("SB2.PrefixSetWrite", base::TimeTicks::Now() - before); |
| 1483 | 1460 |
| 1484 if (!write_ok) | 1461 if (!write_ok) |
| 1485 RecordFailure(FAILURE_BROWSE_PREFIX_SET_WRITE); | 1462 RecordFailure(FAILURE_BROWSE_PREFIX_SET_WRITE); |
| 1486 | 1463 |
| 1487 #if defined(OS_MACOSX) | 1464 #if defined(OS_MACOSX) |
| 1488 base::mac::SetFileBackupExclusion(browse_prefix_set_filename_); | 1465 base::mac::SetFileBackupExclusion(browse_prefix_set_filename_); |
| 1489 #endif | 1466 #endif |
| 1490 } | 1467 } |
| 1491 | 1468 |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 1521 base::AutoLock locked(lookup_lock_); | 1498 base::AutoLock locked(lookup_lock_); |
| 1522 whitelist->second = false; | 1499 whitelist->second = false; |
| 1523 whitelist->first.swap(new_whitelist); | 1500 whitelist->first.swap(new_whitelist); |
| 1524 } | 1501 } |
| 1525 } | 1502 } |
| 1526 | 1503 |
| 1527 void SafeBrowsingDatabaseNew::LoadIpBlacklist( | 1504 void SafeBrowsingDatabaseNew::LoadIpBlacklist( |
| 1528 const std::vector<SBAddFullHash>& full_hashes) { | 1505 const std::vector<SBAddFullHash>& full_hashes) { |
| 1529 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); | 1506 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 1530 IPBlacklist new_blacklist; | 1507 IPBlacklist new_blacklist; |
| 1531 DVLOG(2) << "Writing IP blacklist of size: " << full_hashes.size(); | |
| 1532 for (std::vector<SBAddFullHash>::const_iterator it = full_hashes.begin(); | 1508 for (std::vector<SBAddFullHash>::const_iterator it = full_hashes.begin(); |
| 1533 it != full_hashes.end(); | 1509 it != full_hashes.end(); |
| 1534 ++it) { | 1510 ++it) { |
| 1535 const char* full_hash = it->full_hash.full_hash; | 1511 const char* full_hash = it->full_hash.full_hash; |
| 1536 DCHECK_EQ(crypto::kSHA256Length, arraysize(it->full_hash.full_hash)); | 1512 DCHECK_EQ(crypto::kSHA256Length, arraysize(it->full_hash.full_hash)); |
| 1537 // The format of the IP blacklist is: | 1513 // The format of the IP blacklist is: |
| 1538 // SHA-1(IPv6 prefix) + uint8(prefix size) + 11 unused bytes. | 1514 // SHA-1(IPv6 prefix) + uint8(prefix size) + 11 unused bytes. |
| 1539 std::string hashed_ip_prefix(full_hash, base::kSHA1Length); | 1515 std::string hashed_ip_prefix(full_hash, base::kSHA1Length); |
| 1540 size_t prefix_size = static_cast<uint8>(full_hash[base::kSHA1Length]); | 1516 size_t prefix_size = static_cast<uint8>(full_hash[base::kSHA1Length]); |
| 1541 if (prefix_size > kMaxIpPrefixSize || prefix_size < kMinIpPrefixSize) { | 1517 if (prefix_size > kMaxIpPrefixSize || prefix_size < kMinIpPrefixSize) { |
| 1542 DVLOG(2) << "Invalid IP prefix size in IP blacklist: " << prefix_size; | |
| 1543 RecordFailure(FAILURE_IP_BLACKLIST_UPDATE_INVALID); | 1518 RecordFailure(FAILURE_IP_BLACKLIST_UPDATE_INVALID); |
| 1544 new_blacklist.clear(); // Load empty blacklist. | 1519 new_blacklist.clear(); // Load empty blacklist. |
| 1545 break; | 1520 break; |
| 1546 } | 1521 } |
| 1547 | 1522 |
| 1548 // We precompute the mask for the given subnet size to speed up lookups. | 1523 // We precompute the mask for the given subnet size to speed up lookups. |
| 1549 // Basically we need to create a 16B long string which has the highest | 1524 // Basically we need to create a 16B long string which has the highest |
| 1550 // |size| bits sets to one. | 1525 // |size| bits sets to one. |
| 1551 std::string mask(net::kIPv6AddressSize, '\0'); | 1526 std::string mask(net::kIPv6AddressSize, '\0'); |
| 1552 mask.replace(0, prefix_size / 8, prefix_size / 8, '\xFF'); | 1527 mask.replace(0, prefix_size / 8, prefix_size / 8, '\xFF'); |
| 1553 if ((prefix_size % 8) != 0) { | 1528 if ((prefix_size % 8) != 0) { |
| 1554 mask[prefix_size / 8] = 0xFF << (8 - (prefix_size % 8)); | 1529 mask[prefix_size / 8] = 0xFF << (8 - (prefix_size % 8)); |
| 1555 } | 1530 } |
| 1556 DVLOG(2) << "Inserting malicious IP: " | 1531 DVLOG(2) << "Inserting malicious IP: " |
| 1557 << " raw:" << base::HexEncode(full_hash, crypto::kSHA256Length) | 1532 << " raw:" << base::HexEncode(full_hash, crypto::kSHA256Length) |
| 1558 << " mask:" << base::HexEncode(mask.data(), mask.size()) | 1533 << " mask:" << base::HexEncode(mask.data(), mask.size()) |
| 1559 << " prefix_size:" << prefix_size | 1534 << " prefix_size:" << prefix_size |
| 1560 << " hashed_ip:" << base::HexEncode(hashed_ip_prefix.data(), | 1535 << " hashed_ip:" << base::HexEncode(hashed_ip_prefix.data(), |
|
Scott Hess - ex-Googler
2014/06/18 00:08:41
Likewise this one.
| |
| 1561 hashed_ip_prefix.size()); | 1536 hashed_ip_prefix.size()); |
| 1562 new_blacklist[mask].insert(hashed_ip_prefix); | 1537 new_blacklist[mask].insert(hashed_ip_prefix); |
| 1563 } | 1538 } |
| 1564 | 1539 |
| 1565 base::AutoLock locked(lookup_lock_); | 1540 base::AutoLock locked(lookup_lock_); |
| 1566 ip_blacklist_.swap(new_blacklist); | 1541 ip_blacklist_.swap(new_blacklist); |
| 1567 } | 1542 } |
| 1568 | 1543 |
| 1569 bool SafeBrowsingDatabaseNew::IsMalwareIPMatchKillSwitchOn() { | 1544 bool SafeBrowsingDatabaseNew::IsMalwareIPMatchKillSwitchOn() { |
| 1570 SBFullHash malware_kill_switch = SBFullHashForString(kMalwareIPKillSwitchUrl); | 1545 SBFullHash malware_kill_switch = SBFullHashForString(kMalwareIPKillSwitchUrl); |
| 1571 std::vector<SBFullHash> full_hashes; | 1546 std::vector<SBFullHash> full_hashes; |
| 1572 full_hashes.push_back(malware_kill_switch); | 1547 full_hashes.push_back(malware_kill_switch); |
| 1573 return ContainsWhitelistedHashes(csd_whitelist_, full_hashes); | 1548 return ContainsWhitelistedHashes(csd_whitelist_, full_hashes); |
| 1574 } | 1549 } |
| 1575 | 1550 |
| 1576 bool SafeBrowsingDatabaseNew::IsCsdWhitelistKillSwitchOn() { | 1551 bool SafeBrowsingDatabaseNew::IsCsdWhitelistKillSwitchOn() { |
| 1577 return csd_whitelist_.second; | 1552 return csd_whitelist_.second; |
| 1578 } | 1553 } |
| OLD | NEW |