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 |