| 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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 FILE_PATH_LITERAL(" IP Blacklist"); | 59 FILE_PATH_LITERAL(" IP Blacklist"); |
| 60 | 60 |
| 61 // Filename suffix for browse store. | 61 // Filename suffix for browse store. |
| 62 // TODO(shess): "Safe Browsing Bloom Prefix Set" is full of win. | 62 // TODO(shess): "Safe Browsing Bloom Prefix Set" is full of win. |
| 63 // Unfortunately, to change the name implies lots of transition code | 63 // Unfortunately, to change the name implies lots of transition code |
| 64 // for little benefit. If/when file formats change (say to put all | 64 // for little benefit. If/when file formats change (say to put all |
| 65 // the data in one file), that would be a convenient point to rectify | 65 // the data in one file), that would be a convenient point to rectify |
| 66 // this. | 66 // this. |
| 67 const base::FilePath::CharType kBrowseDBFile[] = FILE_PATH_LITERAL(" Bloom"); | 67 const base::FilePath::CharType kBrowseDBFile[] = FILE_PATH_LITERAL(" Bloom"); |
| 68 | 68 |
| 69 // The maximum staleness for a cached entry. | |
| 70 const int kMaxStalenessMinutes = 45; | |
| 71 | |
| 72 // Maximum number of entries we allow in any of the whitelists. | 69 // Maximum number of entries we allow in any of the whitelists. |
| 73 // If a whitelist on disk contains more entries then all lookups to | 70 // If a whitelist on disk contains more entries then all lookups to |
| 74 // the whitelist will be considered a match. | 71 // the whitelist will be considered a match. |
| 75 const size_t kMaxWhitelistSize = 5000; | 72 const size_t kMaxWhitelistSize = 5000; |
| 76 | 73 |
| 77 // If the hash of this exact expression is on a whitelist then all | 74 // If the hash of this exact expression is on a whitelist then all |
| 78 // lookups to this whitelist will be considered a match. | 75 // lookups to this whitelist will be considered a match. |
| 79 const char kWhitelistKillSwitchUrl[] = | 76 const char kWhitelistKillSwitchUrl[] = |
| 80 "sb-ssl.google.com/safebrowsing/csd/killswitch"; // Don't change this! | 77 "sb-ssl.google.com/safebrowsing/csd/killswitch"; // Don't change this! |
| 81 | 78 |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 // add them to |full_hits| if not expired. "Not expired" is when | 186 // add them to |full_hits| if not expired. "Not expired" is when |
| 190 // either |last_update| was recent enough, or the item has been | 187 // either |last_update| was recent enough, or the item has been |
| 191 // received recently enough. Expired items are not deleted because a | 188 // received recently enough. Expired items are not deleted because a |
| 192 // future update may make them acceptable again. | 189 // future update may make them acceptable again. |
| 193 // | 190 // |
| 194 // For efficiency reasons the code walks |prefix_hits| and | 191 // For efficiency reasons the code walks |prefix_hits| and |
| 195 // |full_hashes| in parallel, so they must be sorted by prefix. | 192 // |full_hashes| in parallel, so they must be sorted by prefix. |
| 196 void GetCachedFullHashesForBrowse( | 193 void GetCachedFullHashesForBrowse( |
| 197 const std::vector<SBPrefix>& prefix_hits, | 194 const std::vector<SBPrefix>& prefix_hits, |
| 198 const std::vector<SBFullHashCached>& full_hashes, | 195 const std::vector<SBFullHashCached>& full_hashes, |
| 199 std::vector<SBFullHashResult>* full_hits, | 196 std::vector<SBFullHashResult>* full_hits) { |
| 200 base::Time last_update) { | 197 const base::Time now = base::Time::Now(); |
| 201 const base::Time expire_time = | |
| 202 base::Time::Now() - base::TimeDelta::FromMinutes(kMaxStalenessMinutes); | |
| 203 | 198 |
| 204 std::vector<SBPrefix>::const_iterator piter = prefix_hits.begin(); | 199 std::vector<SBPrefix>::const_iterator piter = prefix_hits.begin(); |
| 205 std::vector<SBFullHashCached>::const_iterator hiter = full_hashes.begin(); | 200 std::vector<SBFullHashCached>::const_iterator hiter = full_hashes.begin(); |
| 206 | 201 |
| 207 while (piter != prefix_hits.end() && hiter != full_hashes.end()) { | 202 while (piter != prefix_hits.end() && hiter != full_hashes.end()) { |
| 208 if (*piter < hiter->hash.prefix) { | 203 if (*piter < hiter->hash.prefix) { |
| 209 ++piter; | 204 ++piter; |
| 210 } else if (hiter->hash.prefix < *piter) { | 205 } else if (hiter->hash.prefix < *piter) { |
| 211 ++hiter; | 206 ++hiter; |
| 212 } else { | 207 } else { |
| 213 if (expire_time < last_update || | 208 if (now <= hiter->expire_after) { |
| 214 expire_time.ToTimeT() < hiter->received) { | |
| 215 SBFullHashResult result; | 209 SBFullHashResult result; |
| 216 result.list_id = hiter->list_id; | 210 result.list_id = hiter->list_id; |
| 217 result.hash = hiter->hash; | 211 result.hash = hiter->hash; |
| 218 full_hits->push_back(result); | 212 full_hits->push_back(result); |
| 219 } | 213 } |
| 220 | 214 |
| 221 // Only increment |hiter|, |piter| might have multiple hits. | 215 // Only increment |hiter|, |piter| might have multiple hits. |
| 222 ++hiter; | 216 ++hiter; |
| 223 } | 217 } |
| 224 } | 218 } |
| (...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 650 } | 644 } |
| 651 // Wants to acquire the lock itself. | 645 // Wants to acquire the lock itself. |
| 652 WhitelistEverything(&csd_whitelist_); | 646 WhitelistEverything(&csd_whitelist_); |
| 653 WhitelistEverything(&download_whitelist_); | 647 WhitelistEverything(&download_whitelist_); |
| 654 return true; | 648 return true; |
| 655 } | 649 } |
| 656 | 650 |
| 657 bool SafeBrowsingDatabaseNew::ContainsBrowseUrl( | 651 bool SafeBrowsingDatabaseNew::ContainsBrowseUrl( |
| 658 const GURL& url, | 652 const GURL& url, |
| 659 std::vector<SBPrefix>* prefix_hits, | 653 std::vector<SBPrefix>* prefix_hits, |
| 660 std::vector<SBFullHashResult>* cached_hits, | 654 std::vector<SBFullHashResult>* cached_hits) { |
| 661 base::Time last_update) { | |
| 662 // Clear the results first. | 655 // Clear the results first. |
| 663 prefix_hits->clear(); | 656 prefix_hits->clear(); |
| 664 cached_hits->clear(); | 657 cached_hits->clear(); |
| 665 | 658 |
| 666 std::vector<SBFullHash> full_hashes; | 659 std::vector<SBFullHash> full_hashes; |
| 667 BrowseFullHashesToCheck(url, false, &full_hashes); | 660 BrowseFullHashesToCheck(url, false, &full_hashes); |
| 668 if (full_hashes.empty()) | 661 if (full_hashes.empty()) |
| 669 return false; | 662 return false; |
| 670 | 663 |
| 671 // This function is called on the I/O thread, prevent changes to | 664 // This function is called on the I/O thread, prevent changes to |
| (...skipping 16 matching lines...) Expand all Loading... |
| 688 } | 681 } |
| 689 } | 682 } |
| 690 | 683 |
| 691 // If all the prefixes are cached as 'misses', don't issue a GetHash. | 684 // If all the prefixes are cached as 'misses', don't issue a GetHash. |
| 692 if (miss_count == prefix_hits->size()) | 685 if (miss_count == prefix_hits->size()) |
| 693 return false; | 686 return false; |
| 694 | 687 |
| 695 // Find matching cached gethash responses. | 688 // Find matching cached gethash responses. |
| 696 std::sort(prefix_hits->begin(), prefix_hits->end()); | 689 std::sort(prefix_hits->begin(), prefix_hits->end()); |
| 697 GetCachedFullHashesForBrowse(*prefix_hits, cached_browse_hashes_, | 690 GetCachedFullHashesForBrowse(*prefix_hits, cached_browse_hashes_, |
| 698 cached_hits, last_update); | 691 cached_hits); |
| 699 | 692 |
| 700 return true; | 693 return true; |
| 701 } | 694 } |
| 702 | 695 |
| 703 bool SafeBrowsingDatabaseNew::ContainsDownloadUrl( | 696 bool SafeBrowsingDatabaseNew::ContainsDownloadUrl( |
| 704 const std::vector<GURL>& urls, | 697 const std::vector<GURL>& urls, |
| 705 std::vector<SBPrefix>* prefix_hits) { | 698 std::vector<SBPrefix>* prefix_hits) { |
| 706 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); | 699 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 707 | 700 |
| 708 // Ignore this check when download checking is not enabled. | 701 // Ignore this check when download checking is not enabled. |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1018 if (chunk_deletes[i].is_sub_del) | 1011 if (chunk_deletes[i].is_sub_del) |
| 1019 store->DeleteSubChunk(encoded_chunk_id); | 1012 store->DeleteSubChunk(encoded_chunk_id); |
| 1020 else | 1013 else |
| 1021 store->DeleteAddChunk(encoded_chunk_id); | 1014 store->DeleteAddChunk(encoded_chunk_id); |
| 1022 } | 1015 } |
| 1023 } | 1016 } |
| 1024 } | 1017 } |
| 1025 | 1018 |
| 1026 void SafeBrowsingDatabaseNew::CacheHashResults( | 1019 void SafeBrowsingDatabaseNew::CacheHashResults( |
| 1027 const std::vector<SBPrefix>& prefixes, | 1020 const std::vector<SBPrefix>& prefixes, |
| 1028 const std::vector<SBFullHashResult>& full_hits) { | 1021 const std::vector<SBFullHashResult>& full_hits, |
| 1022 const base::TimeDelta& cache_lifetime) { |
| 1023 const base::Time expire_after = base::Time::Now() + cache_lifetime; |
| 1024 |
| 1029 // This is called on the I/O thread, lock against updates. | 1025 // This is called on the I/O thread, lock against updates. |
| 1030 base::AutoLock locked(lookup_lock_); | 1026 base::AutoLock locked(lookup_lock_); |
| 1031 | 1027 |
| 1032 if (full_hits.empty()) { | 1028 if (full_hits.empty()) { |
| 1033 prefix_miss_cache_.insert(prefixes.begin(), prefixes.end()); | 1029 prefix_miss_cache_.insert(prefixes.begin(), prefixes.end()); |
| 1034 return; | 1030 return; |
| 1035 } | 1031 } |
| 1036 | 1032 |
| 1037 const base::Time now = base::Time::Now(); | |
| 1038 const size_t orig_size = cached_browse_hashes_.size(); | 1033 const size_t orig_size = cached_browse_hashes_.size(); |
| 1039 for (std::vector<SBFullHashResult>::const_iterator iter = full_hits.begin(); | 1034 for (std::vector<SBFullHashResult>::const_iterator iter = full_hits.begin(); |
| 1040 iter != full_hits.end(); ++iter) { | 1035 iter != full_hits.end(); ++iter) { |
| 1041 if (iter->list_id == safe_browsing_util::MALWARE || | 1036 if (iter->list_id == safe_browsing_util::MALWARE || |
| 1042 iter->list_id == safe_browsing_util::PHISH) { | 1037 iter->list_id == safe_browsing_util::PHISH) { |
| 1043 SBFullHashCached cached_hash; | 1038 SBFullHashCached cached_hash; |
| 1044 cached_hash.hash = iter->hash; | 1039 cached_hash.hash = iter->hash; |
| 1045 cached_hash.list_id = iter->list_id; | 1040 cached_hash.list_id = iter->list_id; |
| 1046 cached_hash.received = static_cast<int>(now.ToTimeT()); | 1041 cached_hash.expire_after = expire_after; |
| 1047 cached_browse_hashes_.push_back(cached_hash); | 1042 cached_browse_hashes_.push_back(cached_hash); |
| 1048 } | 1043 } |
| 1049 } | 1044 } |
| 1050 | 1045 |
| 1051 // Sort new entries then merge with the previously-sorted entries. | 1046 // Sort new entries then merge with the previously-sorted entries. |
| 1052 std::vector<SBFullHashCached>::iterator | 1047 std::vector<SBFullHashCached>::iterator |
| 1053 orig_end = cached_browse_hashes_.begin() + orig_size; | 1048 orig_end = cached_browse_hashes_.begin() + orig_size; |
| 1054 std::sort(orig_end, cached_browse_hashes_.end(), SBFullHashCachedPrefixLess); | 1049 std::sort(orig_end, cached_browse_hashes_.end(), SBFullHashCachedPrefixLess); |
| 1055 std::inplace_merge(cached_browse_hashes_.begin(), | 1050 std::inplace_merge(cached_browse_hashes_.begin(), |
| 1056 orig_end, cached_browse_hashes_.end(), | 1051 orig_end, cached_browse_hashes_.end(), |
| (...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1631 base::AutoLock locked(lookup_lock_); | 1626 base::AutoLock locked(lookup_lock_); |
| 1632 ip_blacklist_.swap(new_blacklist); | 1627 ip_blacklist_.swap(new_blacklist); |
| 1633 } | 1628 } |
| 1634 | 1629 |
| 1635 bool SafeBrowsingDatabaseNew::IsMalwareIPMatchKillSwitchOn() { | 1630 bool SafeBrowsingDatabaseNew::IsMalwareIPMatchKillSwitchOn() { |
| 1636 SBFullHash malware_kill_switch = SBFullHashForString(kMalwareIPKillSwitchUrl); | 1631 SBFullHash malware_kill_switch = SBFullHashForString(kMalwareIPKillSwitchUrl); |
| 1637 std::vector<SBFullHash> full_hashes; | 1632 std::vector<SBFullHash> full_hashes; |
| 1638 full_hashes.push_back(malware_kill_switch); | 1633 full_hashes.push_back(malware_kill_switch); |
| 1639 return ContainsWhitelistedHashes(csd_whitelist_, full_hashes); | 1634 return ContainsWhitelistedHashes(csd_whitelist_, full_hashes); |
| 1640 } | 1635 } |
| OLD | NEW |