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 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 257 for (size_t i = 0; i < decoded_chunks.size(); ++i) { | 257 for (size_t i = 0; i < decoded_chunks.size(); ++i) { |
| 258 ChunksToRangeString(decoded_chunks[i], &((*list_ranges)[i])); | 258 ChunksToRangeString(decoded_chunks[i], &((*list_ranges)[i])); |
| 259 } | 259 } |
| 260 } | 260 } |
| 261 | 261 |
| 262 // Helper function to create chunk range lists for Browse related | 262 // Helper function to create chunk range lists for Browse related |
| 263 // lists. | 263 // lists. |
| 264 void UpdateChunkRanges(SafeBrowsingStore* store, | 264 void UpdateChunkRanges(SafeBrowsingStore* store, |
| 265 const std::vector<std::string>& listnames, | 265 const std::vector<std::string>& listnames, |
| 266 std::vector<SBListChunkRanges>* lists) { | 266 std::vector<SBListChunkRanges>* lists) { |
| 267 if (!store) | |
| 268 return; | |
| 269 | |
| 267 DCHECK_GT(listnames.size(), 0U); | 270 DCHECK_GT(listnames.size(), 0U); |
| 268 DCHECK_LE(listnames.size(), 2U); | 271 DCHECK_LE(listnames.size(), 2U); |
| 269 std::vector<int> add_chunks; | 272 std::vector<int> add_chunks; |
| 270 std::vector<int> sub_chunks; | 273 std::vector<int> sub_chunks; |
| 271 store->GetAddChunks(&add_chunks); | 274 store->GetAddChunks(&add_chunks); |
| 272 store->GetSubChunks(&sub_chunks); | 275 store->GetSubChunks(&sub_chunks); |
| 273 | 276 |
| 274 // Always decode 2 ranges, even if only the first one is expected. | 277 // Always decode 2 ranges, even if only the first one is expected. |
| 275 // The loop below will only load as many into |lists| as |listnames| | 278 // The loop below will only load as many into |lists| as |listnames| |
| 276 // indicates. | 279 // indicates. |
| 277 std::vector<std::string> adds(2); | 280 std::vector<std::string> adds(2); |
| 278 std::vector<std::string> subs(2); | 281 std::vector<std::string> subs(2); |
| 279 GetChunkRanges(add_chunks, &adds); | 282 GetChunkRanges(add_chunks, &adds); |
| 280 GetChunkRanges(sub_chunks, &subs); | 283 GetChunkRanges(sub_chunks, &subs); |
| 281 | 284 |
| 282 for (size_t i = 0; i < listnames.size(); ++i) { | 285 for (size_t i = 0; i < listnames.size(); ++i) { |
| 283 const std::string& listname = listnames[i]; | 286 const std::string& listname = listnames[i]; |
| 284 DCHECK_EQ(safe_browsing_util::GetListId(listname) % 2, | 287 DCHECK_EQ(safe_browsing_util::GetListId(listname) % 2, |
| 285 static_cast<int>(i % 2)); | 288 static_cast<int>(i % 2)); |
| 286 DCHECK_NE(safe_browsing_util::GetListId(listname), | 289 DCHECK_NE(safe_browsing_util::GetListId(listname), |
| 287 safe_browsing_util::INVALID); | 290 safe_browsing_util::INVALID); |
| 288 lists->push_back(SBListChunkRanges(listname)); | 291 lists->push_back(SBListChunkRanges(listname)); |
| 289 lists->back().adds.swap(adds[i]); | 292 lists->back().adds.swap(adds[i]); |
| 290 lists->back().subs.swap(subs[i]); | 293 lists->back().subs.swap(subs[i]); |
| 291 } | 294 } |
| 292 } | 295 } |
| 293 | 296 |
| 294 // Helper for deleting chunks left over from obsolete lists. | 297 void UpdateChunkRangesForLists(SafeBrowsingStore* store, |
| 295 void DeleteChunksFromStore(SafeBrowsingStore* store, int listid){ | 298 const std::string& listname0, |
| 296 std::vector<int> add_chunks; | 299 const std::string& listname1, |
| 297 size_t adds_deleted = 0; | 300 std::vector<SBListChunkRanges>* lists) { |
| 298 store->GetAddChunks(&add_chunks); | 301 std::vector<std::string> listnames; |
| 299 for (std::vector<int>::const_iterator iter = add_chunks.begin(); | 302 listnames.push_back(listname0); |
| 300 iter != add_chunks.end(); ++iter) { | 303 listnames.push_back(listname1); |
| 301 if (GetListIdBit(*iter) == GetListIdBit(listid)) { | 304 UpdateChunkRanges(store, listnames, lists); |
| 302 adds_deleted++; | 305 } |
| 303 store->DeleteAddChunk(*iter); | |
| 304 } | |
| 305 } | |
| 306 if (adds_deleted > 0) | |
| 307 UMA_HISTOGRAM_COUNTS("SB2.DownloadBinhashAddsDeleted", adds_deleted); | |
| 308 | 306 |
| 309 std::vector<int> sub_chunks; | 307 void UpdateChunkRangesForList(SafeBrowsingStore* store, |
| 310 size_t subs_deleted = 0; | 308 const std::string& listname, |
| 311 store->GetSubChunks(&sub_chunks); | 309 std::vector<SBListChunkRanges>* lists) { |
| 312 for (std::vector<int>::const_iterator iter = sub_chunks.begin(); | 310 UpdateChunkRanges(store, std::vector<std::string>(1, listname), lists); |
| 313 iter != sub_chunks.end(); ++iter) { | |
| 314 if (GetListIdBit(*iter) == GetListIdBit(listid)) { | |
| 315 subs_deleted++; | |
| 316 store->DeleteSubChunk(*iter); | |
| 317 } | |
| 318 } | |
| 319 if (subs_deleted > 0) | |
| 320 UMA_HISTOGRAM_COUNTS("SB2.DownloadBinhashSubsDeleted", subs_deleted); | |
| 321 } | 311 } |
| 322 | 312 |
| 323 // Order |SBAddFullHash| on the prefix part. |SBAddPrefixLess()| from | 313 // Order |SBAddFullHash| on the prefix part. |SBAddPrefixLess()| from |
| 324 // safe_browsing_store.h orders on both chunk-id and prefix. | 314 // safe_browsing_store.h orders on both chunk-id and prefix. |
| 325 bool SBAddFullHashPrefixLess(const SBAddFullHash& a, const SBAddFullHash& b) { | 315 bool SBAddFullHashPrefixLess(const SBAddFullHash& a, const SBAddFullHash& b) { |
| 326 return a.full_hash.prefix < b.full_hash.prefix; | 316 return a.full_hash.prefix < b.full_hash.prefix; |
| 327 } | 317 } |
| 328 | 318 |
| 329 // This code always checks for non-zero file size. This helper makes | 319 // This code always checks for non-zero file size. This helper makes |
| 330 // that less verbose. | 320 // that less verbose. |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 443 // static | 433 // static |
| 444 base::FilePath SafeBrowsingDatabase::IpBlacklistDBFilename( | 434 base::FilePath SafeBrowsingDatabase::IpBlacklistDBFilename( |
| 445 const base::FilePath& db_filename) { | 435 const base::FilePath& db_filename) { |
| 446 return base::FilePath(db_filename.value() + kIPBlacklistDBFile); | 436 return base::FilePath(db_filename.value() + kIPBlacklistDBFile); |
| 447 } | 437 } |
| 448 | 438 |
| 449 SafeBrowsingStore* SafeBrowsingDatabaseNew::GetStore(const int list_id) { | 439 SafeBrowsingStore* SafeBrowsingDatabaseNew::GetStore(const int list_id) { |
| 450 if (list_id == safe_browsing_util::PHISH || | 440 if (list_id == safe_browsing_util::PHISH || |
| 451 list_id == safe_browsing_util::MALWARE) { | 441 list_id == safe_browsing_util::MALWARE) { |
| 452 return browse_store_.get(); | 442 return browse_store_.get(); |
| 453 } else if (list_id == safe_browsing_util::BINURL || | 443 } else if (list_id == safe_browsing_util::BINURL) { |
| 454 list_id == safe_browsing_util::BINHASH) { | |
| 455 return download_store_.get(); | 444 return download_store_.get(); |
| 456 } else if (list_id == safe_browsing_util::CSDWHITELIST) { | 445 } else if (list_id == safe_browsing_util::CSDWHITELIST) { |
| 457 return csd_whitelist_store_.get(); | 446 return csd_whitelist_store_.get(); |
| 458 } else if (list_id == safe_browsing_util::DOWNLOADWHITELIST) { | 447 } else if (list_id == safe_browsing_util::DOWNLOADWHITELIST) { |
| 459 return download_whitelist_store_.get(); | 448 return download_whitelist_store_.get(); |
| 460 } else if (list_id == safe_browsing_util::EXTENSIONBLACKLIST) { | 449 } else if (list_id == safe_browsing_util::EXTENSIONBLACKLIST) { |
| 461 return extension_blacklist_store_.get(); | 450 return extension_blacklist_store_.get(); |
| 462 } else if (list_id == safe_browsing_util::SIDEEFFECTFREEWHITELIST) { | 451 } else if (list_id == safe_browsing_util::SIDEEFFECTFREEWHITELIST) { |
| 463 return side_effect_free_whitelist_store_.get(); | 452 return side_effect_free_whitelist_store_.get(); |
| 464 } else if (list_id == safe_browsing_util::IPBLACKLIST) { | 453 } else if (list_id == safe_browsing_util::IPBLACKLIST) { |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 740 return false; | 729 return false; |
| 741 | 730 |
| 742 std::vector<SBPrefix> prefixes; | 731 std::vector<SBPrefix> prefixes; |
| 743 GetDownloadUrlPrefixes(urls, &prefixes); | 732 GetDownloadUrlPrefixes(urls, &prefixes); |
| 744 return MatchAddPrefixes(download_store_.get(), | 733 return MatchAddPrefixes(download_store_.get(), |
| 745 safe_browsing_util::BINURL % 2, | 734 safe_browsing_util::BINURL % 2, |
| 746 prefixes, | 735 prefixes, |
| 747 prefix_hits); | 736 prefix_hits); |
| 748 } | 737 } |
| 749 | 738 |
| 750 bool SafeBrowsingDatabaseNew::ContainsDownloadHashPrefix( | |
| 751 const SBPrefix& prefix) { | |
| 752 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); | |
| 753 | |
| 754 // Ignore this check when download store is not available. | |
| 755 if (!download_store_.get()) | |
| 756 return false; | |
| 757 | |
| 758 std::vector<SBPrefix> prefix_hits; | |
| 759 return MatchAddPrefixes(download_store_.get(), | |
| 760 safe_browsing_util::BINHASH % 2, | |
| 761 std::vector<SBPrefix>(1, prefix), | |
| 762 &prefix_hits); | |
| 763 } | |
| 764 | |
| 765 bool SafeBrowsingDatabaseNew::ContainsCsdWhitelistedUrl(const GURL& url) { | 739 bool SafeBrowsingDatabaseNew::ContainsCsdWhitelistedUrl(const GURL& url) { |
| 766 // This method is theoretically thread-safe but we expect all calls to | 740 // This method is theoretically thread-safe but we expect all calls to |
| 767 // originate from the IO thread. | 741 // originate from the IO thread. |
| 768 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 742 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 769 std::vector<SBFullHash> full_hashes; | 743 std::vector<SBFullHash> full_hashes; |
| 770 BrowseFullHashesToCheck(url, true, &full_hashes); | 744 BrowseFullHashesToCheck(url, true, &full_hashes); |
| 771 return ContainsWhitelistedHashes(csd_whitelist_, full_hashes); | 745 return ContainsWhitelistedHashes(csd_whitelist_, full_hashes); |
| 772 } | 746 } |
| 773 | 747 |
| 774 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedUrl(const GURL& url) { | 748 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedUrl(const GURL& url) { |
| (...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1156 HandleCorruptDatabase(); | 1130 HandleCorruptDatabase(); |
| 1157 return false; | 1131 return false; |
| 1158 } | 1132 } |
| 1159 | 1133 |
| 1160 if (ip_blacklist_store_ && !ip_blacklist_store_->BeginUpdate()) { | 1134 if (ip_blacklist_store_ && !ip_blacklist_store_->BeginUpdate()) { |
| 1161 RecordFailure(FAILURE_IP_BLACKLIST_UPDATE_BEGIN); | 1135 RecordFailure(FAILURE_IP_BLACKLIST_UPDATE_BEGIN); |
| 1162 HandleCorruptDatabase(); | 1136 HandleCorruptDatabase(); |
| 1163 return false; | 1137 return false; |
| 1164 } | 1138 } |
| 1165 | 1139 |
| 1166 std::vector<std::string> browse_listnames; | 1140 UpdateChunkRangesForLists(browse_store_.get(), |
| 1167 browse_listnames.push_back(safe_browsing_util::kMalwareList); | 1141 safe_browsing_util::kMalwareList, |
| 1168 browse_listnames.push_back(safe_browsing_util::kPhishingList); | 1142 safe_browsing_util::kPhishingList, |
| 1169 UpdateChunkRanges(browse_store_.get(), browse_listnames, lists); | 1143 lists); |
| 1170 | 1144 |
| 1171 if (download_store_.get()) { | 1145 // NOTE(shess): |download_store_| used to contain kBinHashList, which has been |
| 1172 // This store used to contain kBinHashList in addition to | 1146 // deprecated. Code to delete the list from the store shows no histogram hits |
| 1173 // kBinUrlList. Strip the stale data before generating the chunk | 1147 // at all, so it has been removed. Everything _should_ be resilient to extra |
|
mattm
2014/02/19 23:47:09
Looks like the histograms just don't show on the d
Scott Hess - ex-Googler
2014/02/20 19:13:20
I updated histograms.xml, and now the dashboard sh
| |
| 1174 // ranges to request. UpdateChunkRanges() will traverse the chunk | 1148 // data of that sort. |
| 1175 // list, so this is very cheap if there are no kBinHashList chunks. | 1149 UpdateChunkRangesForList(download_store_.get(), |
| 1176 const int listid = | 1150 safe_browsing_util::kBinUrlList, lists); |
| 1177 safe_browsing_util::GetListId(safe_browsing_util::kBinHashList); | |
| 1178 DeleteChunksFromStore(download_store_.get(), listid); | |
| 1179 | 1151 |
| 1180 // The above marks the chunks for deletion, but they are not | 1152 UpdateChunkRangesForList(csd_whitelist_store_.get(), |
| 1181 // actually deleted until the database is rewritten. The | 1153 safe_browsing_util::kCsdWhiteList, lists); |
| 1182 // following code removes the kBinHashList part of the request | |
| 1183 // before continuing so that UpdateChunkRanges() doesn't break. | |
| 1184 std::vector<std::string> download_listnames; | |
| 1185 download_listnames.push_back(safe_browsing_util::kBinUrlList); | |
| 1186 download_listnames.push_back(safe_browsing_util::kBinHashList); | |
| 1187 UpdateChunkRanges(download_store_.get(), download_listnames, lists); | |
| 1188 DCHECK_EQ(lists->back().name, | |
| 1189 std::string(safe_browsing_util::kBinHashList)); | |
| 1190 lists->pop_back(); | |
| 1191 | 1154 |
| 1192 // TODO(shess): This problem could also be handled in | 1155 UpdateChunkRangesForList(download_whitelist_store_.get(), |
| 1193 // BeginUpdate() by detecting the chunks to delete and rewriting | 1156 safe_browsing_util::kDownloadWhiteList, lists); |
| 1194 // the database before it's used. When I implemented that, it | |
| 1195 // felt brittle, it might be easier to just wait for some future | |
| 1196 // format change. | |
| 1197 } | |
| 1198 | 1157 |
| 1199 if (csd_whitelist_store_.get()) { | 1158 UpdateChunkRangesForList(extension_blacklist_store_.get(), |
| 1200 std::vector<std::string> csd_whitelist_listnames; | 1159 safe_browsing_util::kExtensionBlacklist, lists); |
| 1201 csd_whitelist_listnames.push_back(safe_browsing_util::kCsdWhiteList); | |
| 1202 UpdateChunkRanges(csd_whitelist_store_.get(), | |
| 1203 csd_whitelist_listnames, lists); | |
| 1204 } | |
| 1205 | 1160 |
| 1206 if (download_whitelist_store_.get()) { | 1161 UpdateChunkRangesForList(side_effect_free_whitelist_store_.get(), |
| 1207 std::vector<std::string> download_whitelist_listnames; | 1162 safe_browsing_util::kSideEffectFreeWhitelist, lists); |
| 1208 download_whitelist_listnames.push_back( | |
| 1209 safe_browsing_util::kDownloadWhiteList); | |
| 1210 UpdateChunkRanges(download_whitelist_store_.get(), | |
| 1211 download_whitelist_listnames, lists); | |
| 1212 } | |
| 1213 | 1163 |
| 1214 if (extension_blacklist_store_) { | 1164 UpdateChunkRangesForList(ip_blacklist_store_.get(), |
| 1215 UpdateChunkRanges( | 1165 safe_browsing_util::kIPBlacklist, lists); |
| 1216 extension_blacklist_store_.get(), | |
| 1217 std::vector<std::string>(1, safe_browsing_util::kExtensionBlacklist), | |
| 1218 lists); | |
| 1219 } | |
| 1220 | |
| 1221 if (side_effect_free_whitelist_store_) { | |
| 1222 UpdateChunkRanges( | |
| 1223 side_effect_free_whitelist_store_.get(), | |
| 1224 std::vector<std::string>( | |
| 1225 1, safe_browsing_util::kSideEffectFreeWhitelist), | |
| 1226 lists); | |
| 1227 } | |
| 1228 | |
| 1229 if (ip_blacklist_store_) { | |
| 1230 UpdateChunkRanges( | |
| 1231 ip_blacklist_store_.get(), | |
| 1232 std::vector<std::string>(1, safe_browsing_util::kIPBlacklist), | |
| 1233 lists); | |
| 1234 } | |
| 1235 | 1166 |
| 1236 corruption_detected_ = false; | 1167 corruption_detected_ = false; |
| 1237 change_detected_ = false; | 1168 change_detected_ = false; |
| 1238 return true; | 1169 return true; |
| 1239 } | 1170 } |
| 1240 | 1171 |
| 1241 void SafeBrowsingDatabaseNew::UpdateFinished(bool update_succeeded) { | 1172 void SafeBrowsingDatabaseNew::UpdateFinished(bool update_succeeded) { |
| 1242 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); | 1173 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 1243 | 1174 |
| 1244 // The update may have failed due to corrupt storage (for instance, | 1175 // The update may have failed due to corrupt storage (for instance, |
| (...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1784 } | 1715 } |
| 1785 | 1716 |
| 1786 bool SafeBrowsingDatabaseNew::IsMalwareIPMatchKillSwitchOn() { | 1717 bool SafeBrowsingDatabaseNew::IsMalwareIPMatchKillSwitchOn() { |
| 1787 SBFullHash malware_kill_switch; | 1718 SBFullHash malware_kill_switch; |
| 1788 crypto::SHA256HashString(kMalwareIPKillSwitchUrl, &malware_kill_switch, | 1719 crypto::SHA256HashString(kMalwareIPKillSwitchUrl, &malware_kill_switch, |
| 1789 sizeof(malware_kill_switch)); | 1720 sizeof(malware_kill_switch)); |
| 1790 std::vector<SBFullHash> full_hashes; | 1721 std::vector<SBFullHash> full_hashes; |
| 1791 full_hashes.push_back(malware_kill_switch); | 1722 full_hashes.push_back(malware_kill_switch); |
| 1792 return ContainsWhitelistedHashes(csd_whitelist_, full_hashes); | 1723 return ContainsWhitelistedHashes(csd_whitelist_, full_hashes); |
| 1793 } | 1724 } |
| OLD | NEW |