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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 60 // Maximum number of entries we allow in any of the whitelists. | 60 // Maximum number of entries we allow in any of the whitelists. |
| 61 // If a whitelist on disk contains more entries then all lookups to | 61 // If a whitelist on disk contains more entries then all lookups to |
| 62 // the whitelist will be considered a match. | 62 // the whitelist will be considered a match. |
| 63 const size_t kMaxWhitelistSize = 5000; | 63 const size_t kMaxWhitelistSize = 5000; |
| 64 | 64 |
| 65 // If the hash of this exact expression is on a whitelist then all | 65 // If the hash of this exact expression is on a whitelist then all |
| 66 // lookups to this whitelist will be considered a match. | 66 // lookups to this whitelist will be considered a match. |
| 67 const char kWhitelistKillSwitchUrl[] = | 67 const char kWhitelistKillSwitchUrl[] = |
| 68 "sb-ssl.google.com/safebrowsing/csd/killswitch"; // Don't change this! | 68 "sb-ssl.google.com/safebrowsing/csd/killswitch"; // Don't change this! |
| 69 | 69 |
| 70 // If the hash of this exact expression is on a whitelist then the | |
| 71 // malware IP blacklisting feature will be disabled in csd. | |
| 72 // Don't change this! | |
| 73 const char kMalwareIPKillSwitchUrl[] = | |
| 74 "sb-ssl.google.com/safebrowsing/csd/killswitch_malware"; | |
| 75 | |
| 70 // To save space, the incoming |chunk_id| and |list_id| are combined | 76 // To save space, the incoming |chunk_id| and |list_id| are combined |
| 71 // into an |encoded_chunk_id| for storage by shifting the |list_id| | 77 // into an |encoded_chunk_id| for storage by shifting the |list_id| |
| 72 // into the low-order bits. These functions decode that information. | 78 // into the low-order bits. These functions decode that information. |
| 73 // TODO(lzheng): It was reasonable when database is saved in sqlite, but | 79 // TODO(lzheng): It was reasonable when database is saved in sqlite, but |
| 74 // there should be better ways to save chunk_id and list_id after we use | 80 // there should be better ways to save chunk_id and list_id after we use |
| 75 // SafeBrowsingStoreFile. | 81 // SafeBrowsingStoreFile. |
| 76 int GetListIdBit(const int encoded_chunk_id) { | 82 int GetListIdBit(const int encoded_chunk_id) { |
| 77 return encoded_chunk_id & 1; | 83 return encoded_chunk_id & 1; |
| 78 } | 84 } |
| 79 int DecodeChunkId(int encoded_chunk_id) { | 85 int DecodeChunkId(int encoded_chunk_id) { |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 420 UMA_HISTOGRAM_ENUMERATION("SB2.DatabaseFailure", failure_type, | 426 UMA_HISTOGRAM_ENUMERATION("SB2.DatabaseFailure", failure_type, |
| 421 FAILURE_DATABASE_MAX); | 427 FAILURE_DATABASE_MAX); |
| 422 } | 428 } |
| 423 | 429 |
| 424 SafeBrowsingDatabaseNew::SafeBrowsingDatabaseNew() | 430 SafeBrowsingDatabaseNew::SafeBrowsingDatabaseNew() |
| 425 : creation_loop_(MessageLoop::current()), | 431 : creation_loop_(MessageLoop::current()), |
| 426 browse_store_(new SafeBrowsingStoreFile), | 432 browse_store_(new SafeBrowsingStoreFile), |
| 427 download_store_(NULL), | 433 download_store_(NULL), |
| 428 csd_whitelist_store_(NULL), | 434 csd_whitelist_store_(NULL), |
| 429 download_whitelist_store_(NULL), | 435 download_whitelist_store_(NULL), |
| 436 csd_malware_ipmatch_killswitch_on_(false), | |
| 430 reset_factory_(this), | 437 reset_factory_(this), |
| 431 corruption_detected_(false), | 438 corruption_detected_(false), |
| 432 change_detected_(false) { | 439 change_detected_(false) { |
| 433 DCHECK(browse_store_.get()); | 440 DCHECK(browse_store_.get()); |
| 434 DCHECK(!download_store_.get()); | 441 DCHECK(!download_store_.get()); |
| 435 DCHECK(!csd_whitelist_store_.get()); | 442 DCHECK(!csd_whitelist_store_.get()); |
| 436 DCHECK(!download_whitelist_store_.get()); | 443 DCHECK(!download_whitelist_store_.get()); |
| 437 DCHECK(!extension_blacklist_store_.get()); | 444 DCHECK(!extension_blacklist_store_.get()); |
| 438 } | 445 } |
| 439 | 446 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 498 | 505 |
| 499 if (csd_whitelist_store_.get()) { | 506 if (csd_whitelist_store_.get()) { |
| 500 csd_whitelist_filename_ = CsdWhitelistDBFilename(filename_base); | 507 csd_whitelist_filename_ = CsdWhitelistDBFilename(filename_base); |
| 501 csd_whitelist_store_->Init( | 508 csd_whitelist_store_->Init( |
| 502 csd_whitelist_filename_, | 509 csd_whitelist_filename_, |
| 503 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | 510 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, |
| 504 base::Unretained(this))); | 511 base::Unretained(this))); |
| 505 DVLOG(1) << "Init csd whitelist store: " << csd_whitelist_filename_.value(); | 512 DVLOG(1) << "Init csd whitelist store: " << csd_whitelist_filename_.value(); |
| 506 std::vector<SBAddFullHash> full_hashes; | 513 std::vector<SBAddFullHash> full_hashes; |
| 507 if (csd_whitelist_store_->GetAddFullHashes(&full_hashes)) { | 514 if (csd_whitelist_store_->GetAddFullHashes(&full_hashes)) { |
| 508 LoadWhitelist(full_hashes, &csd_whitelist_); | 515 LoadWhitelist(full_hashes, &csd_whitelist_, true); |
| 509 } else { | 516 } else { |
| 510 WhitelistEverything(&csd_whitelist_); | 517 WhitelistEverything(&csd_whitelist_); |
| 511 } | 518 } |
| 512 } else { | 519 } else { |
| 513 WhitelistEverything(&csd_whitelist_); // Just to be safe. | 520 WhitelistEverything(&csd_whitelist_); // Just to be safe. |
| 514 } | 521 } |
| 515 | 522 |
| 516 if (download_whitelist_store_.get()) { | 523 if (download_whitelist_store_.get()) { |
| 517 download_whitelist_filename_ = DownloadWhitelistDBFilename(filename_base); | 524 download_whitelist_filename_ = DownloadWhitelistDBFilename(filename_base); |
| 518 download_whitelist_store_->Init( | 525 download_whitelist_store_->Init( |
| 519 download_whitelist_filename_, | 526 download_whitelist_filename_, |
| 520 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | 527 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, |
| 521 base::Unretained(this))); | 528 base::Unretained(this))); |
| 522 DVLOG(1) << "Init download whitelist store: " | 529 DVLOG(1) << "Init download whitelist store: " |
| 523 << download_whitelist_filename_.value(); | 530 << download_whitelist_filename_.value(); |
| 524 std::vector<SBAddFullHash> full_hashes; | 531 std::vector<SBAddFullHash> full_hashes; |
| 525 if (download_whitelist_store_->GetAddFullHashes(&full_hashes)) { | 532 if (download_whitelist_store_->GetAddFullHashes(&full_hashes)) { |
| 526 LoadWhitelist(full_hashes, &download_whitelist_); | 533 LoadWhitelist(full_hashes, &download_whitelist_, false); |
| 527 } else { | 534 } else { |
| 528 WhitelistEverything(&download_whitelist_); | 535 WhitelistEverything(&download_whitelist_); |
| 529 } | 536 } |
| 530 } else { | 537 } else { |
| 531 WhitelistEverything(&download_whitelist_); // Just to be safe. | 538 WhitelistEverything(&download_whitelist_); // Just to be safe. |
| 532 } | 539 } |
| 533 | 540 |
| 534 if (extension_blacklist_store_.get()) { | 541 if (extension_blacklist_store_.get()) { |
| 535 extension_blacklist_filename_ = ExtensionBlacklistDBFilename(filename_base); | 542 extension_blacklist_filename_ = ExtensionBlacklistDBFilename(filename_base); |
| 536 extension_blacklist_store_->Init( | 543 extension_blacklist_store_->Init( |
| (...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1094 download_filename_, | 1101 download_filename_, |
| 1095 download_store_.get(), | 1102 download_store_.get(), |
| 1096 FAILURE_DOWNLOAD_DATABASE_UPDATE_FINISH); | 1103 FAILURE_DOWNLOAD_DATABASE_UPDATE_FINISH); |
| 1097 UMA_HISTOGRAM_COUNTS("SB2.DownloadDatabaseKilobytes", | 1104 UMA_HISTOGRAM_COUNTS("SB2.DownloadDatabaseKilobytes", |
| 1098 static_cast<int>(size_bytes / 1024)); | 1105 static_cast<int>(size_bytes / 1024)); |
| 1099 } | 1106 } |
| 1100 | 1107 |
| 1101 UpdateBrowseStore(); | 1108 UpdateBrowseStore(); |
| 1102 UpdateWhitelistStore(csd_whitelist_filename_, | 1109 UpdateWhitelistStore(csd_whitelist_filename_, |
| 1103 csd_whitelist_store_.get(), | 1110 csd_whitelist_store_.get(), |
| 1104 &csd_whitelist_); | 1111 &csd_whitelist_, true); |
| 1105 UpdateWhitelistStore(download_whitelist_filename_, | 1112 UpdateWhitelistStore(download_whitelist_filename_, |
| 1106 download_whitelist_store_.get(), | 1113 download_whitelist_store_.get(), |
| 1107 &download_whitelist_); | 1114 &download_whitelist_, false); |
| 1108 | 1115 |
| 1109 if (extension_blacklist_store_) { | 1116 if (extension_blacklist_store_) { |
| 1110 int64 size_bytes = UpdateHashPrefixStore( | 1117 int64 size_bytes = UpdateHashPrefixStore( |
| 1111 extension_blacklist_filename_, | 1118 extension_blacklist_filename_, |
| 1112 extension_blacklist_store_.get(), | 1119 extension_blacklist_store_.get(), |
| 1113 FAILURE_EXTENSION_BLACKLIST_UPDATE_FINISH); | 1120 FAILURE_EXTENSION_BLACKLIST_UPDATE_FINISH); |
| 1114 UMA_HISTOGRAM_COUNTS("SB2.ExtensionBlacklistKilobytes", | 1121 UMA_HISTOGRAM_COUNTS("SB2.ExtensionBlacklistKilobytes", |
| 1115 static_cast<int>(size_bytes / 1024)); | 1122 static_cast<int>(size_bytes / 1024)); |
| 1116 } | 1123 } |
| 1117 } | 1124 } |
| 1118 | 1125 |
| 1119 void SafeBrowsingDatabaseNew::UpdateWhitelistStore( | 1126 void SafeBrowsingDatabaseNew::UpdateWhitelistStore( |
| 1120 const base::FilePath& store_filename, | 1127 const base::FilePath& store_filename, |
| 1121 SafeBrowsingStore* store, | 1128 SafeBrowsingStore* store, |
| 1122 SBWhitelist* whitelist) { | 1129 SBWhitelist* whitelist, |
| 1130 bool check_malware_killswitch) { | |
| 1123 if (!store) | 1131 if (!store) |
| 1124 return; | 1132 return; |
| 1125 | 1133 |
| 1126 // For the whitelists, we don't cache and save full hashes since all | 1134 // For the whitelists, we don't cache and save full hashes since all |
| 1127 // hashes are already full. | 1135 // hashes are already full. |
| 1128 std::vector<SBAddFullHash> empty_add_hashes; | 1136 std::vector<SBAddFullHash> empty_add_hashes; |
| 1129 | 1137 |
| 1130 // Not needed for the whitelists. | 1138 // Not needed for the whitelists. |
| 1131 std::set<SBPrefix> empty_miss_cache; | 1139 std::set<SBPrefix> empty_miss_cache; |
| 1132 | 1140 |
| 1133 // Note: prefixes will not be empty. The current data store implementation | 1141 // Note: prefixes will not be empty. The current data store implementation |
| 1134 // stores all full-length hashes as both full and prefix hashes. | 1142 // stores all full-length hashes as both full and prefix hashes. |
| 1135 SBAddPrefixes prefixes; | 1143 SBAddPrefixes prefixes; |
| 1136 std::vector<SBAddFullHash> full_hashes; | 1144 std::vector<SBAddFullHash> full_hashes; |
| 1137 if (!store->FinishUpdate(empty_add_hashes, empty_miss_cache, &prefixes, | 1145 if (!store->FinishUpdate(empty_add_hashes, empty_miss_cache, &prefixes, |
| 1138 &full_hashes)) { | 1146 &full_hashes)) { |
| 1139 RecordFailure(FAILURE_WHITELIST_DATABASE_UPDATE_FINISH); | 1147 RecordFailure(FAILURE_WHITELIST_DATABASE_UPDATE_FINISH); |
| 1140 WhitelistEverything(whitelist); | 1148 WhitelistEverything(whitelist); |
| 1141 return; | 1149 return; |
| 1142 } | 1150 } |
| 1143 | 1151 |
| 1144 #if defined(OS_MACOSX) | 1152 #if defined(OS_MACOSX) |
| 1145 base::mac::SetFileBackupExclusion(store_filename); | 1153 base::mac::SetFileBackupExclusion(store_filename); |
| 1146 #endif | 1154 #endif |
| 1147 | 1155 |
| 1148 LoadWhitelist(full_hashes, whitelist); | 1156 LoadWhitelist(full_hashes, whitelist, check_malware_killswitch); |
| 1149 } | 1157 } |
| 1150 | 1158 |
| 1151 int64 SafeBrowsingDatabaseNew::UpdateHashPrefixStore( | 1159 int64 SafeBrowsingDatabaseNew::UpdateHashPrefixStore( |
| 1152 const base::FilePath& store_filename, | 1160 const base::FilePath& store_filename, |
| 1153 SafeBrowsingStore* store, | 1161 SafeBrowsingStore* store, |
| 1154 FailureType failure_type) { | 1162 FailureType failure_type) { |
| 1155 // We don't cache and save full hashes. | 1163 // We don't cache and save full hashes. |
| 1156 std::vector<SBAddFullHash> empty_add_hashes; | 1164 std::vector<SBAddFullHash> empty_add_hashes; |
| 1157 | 1165 |
| 1158 // Backend lookup happens only if a prefix is in add list. | 1166 // Backend lookup happens only if a prefix is in add list. |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1390 } | 1398 } |
| 1391 | 1399 |
| 1392 void SafeBrowsingDatabaseNew::WhitelistEverything(SBWhitelist* whitelist) { | 1400 void SafeBrowsingDatabaseNew::WhitelistEverything(SBWhitelist* whitelist) { |
| 1393 base::AutoLock locked(lookup_lock_); | 1401 base::AutoLock locked(lookup_lock_); |
| 1394 whitelist->second = true; | 1402 whitelist->second = true; |
| 1395 whitelist->first.clear(); | 1403 whitelist->first.clear(); |
| 1396 } | 1404 } |
| 1397 | 1405 |
| 1398 void SafeBrowsingDatabaseNew::LoadWhitelist( | 1406 void SafeBrowsingDatabaseNew::LoadWhitelist( |
| 1399 const std::vector<SBAddFullHash>& full_hashes, | 1407 const std::vector<SBAddFullHash>& full_hashes, |
| 1400 SBWhitelist* whitelist) { | 1408 SBWhitelist* whitelist, |
| 1409 bool check_malware_killswitch) { | |
| 1401 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 1410 DCHECK_EQ(creation_loop_, MessageLoop::current()); |
| 1402 if (full_hashes.size() > kMaxWhitelistSize) { | 1411 if (full_hashes.size() > kMaxWhitelistSize) { |
| 1403 WhitelistEverything(whitelist); | 1412 WhitelistEverything(whitelist); |
| 1404 return; | 1413 return; |
| 1405 } | 1414 } |
| 1406 | 1415 |
| 1407 std::vector<SBFullHash> new_whitelist; | 1416 std::vector<SBFullHash> new_whitelist; |
| 1408 new_whitelist.reserve(full_hashes.size()); | 1417 new_whitelist.reserve(full_hashes.size()); |
| 1409 for (std::vector<SBAddFullHash>::const_iterator it = full_hashes.begin(); | 1418 for (std::vector<SBAddFullHash>::const_iterator it = full_hashes.begin(); |
| 1410 it != full_hashes.end(); ++it) { | 1419 it != full_hashes.end(); ++it) { |
| 1411 new_whitelist.push_back(it->full_hash); | 1420 new_whitelist.push_back(it->full_hash); |
| 1412 } | 1421 } |
| 1413 std::sort(new_whitelist.begin(), new_whitelist.end()); | 1422 std::sort(new_whitelist.begin(), new_whitelist.end()); |
| 1414 | 1423 |
| 1415 SBFullHash kill_switch; | 1424 SBFullHash kill_switch; |
| 1416 crypto::SHA256HashString(kWhitelistKillSwitchUrl, &kill_switch, | 1425 crypto::SHA256HashString(kWhitelistKillSwitchUrl, &kill_switch, |
| 1417 sizeof(kill_switch)); | 1426 sizeof(kill_switch)); |
| 1418 if (std::binary_search(new_whitelist.begin(), new_whitelist.end(), | 1427 if (std::binary_search(new_whitelist.begin(), new_whitelist.end(), |
| 1419 kill_switch)) { | 1428 kill_switch)) { |
| 1420 // The kill switch is whitelisted hence we whitelist all URLs. | 1429 // The kill switch is whitelisted hence we whitelist all URLs. |
| 1421 WhitelistEverything(whitelist); | 1430 WhitelistEverything(whitelist); |
| 1422 } else { | 1431 } else { |
| 1423 base::AutoLock locked(lookup_lock_); | 1432 base::AutoLock locked(lookup_lock_); |
| 1424 whitelist->second = false; | 1433 whitelist->second = false; |
| 1425 whitelist->first.swap(new_whitelist); | 1434 whitelist->first.swap(new_whitelist); |
| 1426 } | 1435 } |
| 1436 | |
| 1437 // The killswitch is only in csd_whitelist, not download_whitelist | |
| 1438 if (!check_malware_killswitch) { | |
|
mattm
2013/05/21 02:14:09
I tihnk it would be clearer to move the check into
kewang
2013/05/22 10:14:00
I think this is a good idea. changed to call Conta
| |
| 1439 return; | |
| 1440 } | |
| 1441 | |
| 1442 SBFullHash malware_kill_switch; | |
| 1443 crypto::SHA256HashString(kMalwareIPKillSwitchUrl, &malware_kill_switch, | |
| 1444 sizeof(malware_kill_switch)); | |
| 1445 if (std::binary_search(new_whitelist.begin(), new_whitelist.end(), | |
|
mattm
2013/05/21 02:14:09
I think this is a bug, new_whitelist here will act
kewang
2013/05/22 10:14:00
removed this part totally.
| |
| 1446 malware_kill_switch)) { | |
| 1447 // Turn on the malware IP matching kill switch | |
| 1448 base::AutoLock locked(lookup_lock_); | |
| 1449 csd_malware_ipmatch_killswitch_on_ = true; | |
| 1450 } else { | |
| 1451 // Turn off the malware IP matching kill switch | |
| 1452 base::AutoLock locked(lookup_lock_); | |
| 1453 csd_malware_ipmatch_killswitch_on_ = false; | |
| 1454 } | |
| 1427 } | 1455 } |
| 1456 | |
| 1457 | |
| 1458 bool SafeBrowsingDatabaseNew::MalwareIPMatchKillSwitchOn() { | |
| 1459 base::AutoLock locked(lookup_lock_); | |
| 1460 return csd_malware_ipmatch_killswitch_on_; | |
| 1461 }; | |
| OLD | NEW |