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/local_database_manager.h" | 5 #include "chrome/browser/safe_browsing/local_database_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> |
8 | 9 |
9 #include "base/bind.h" | 10 #include "base/bind.h" |
10 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
11 #include "base/callback.h" | 12 #include "base/callback.h" |
12 #include "base/command_line.h" | 13 #include "base/command_line.h" |
13 #include "base/debug/leak_tracker.h" | 14 #include "base/debug/leak_tracker.h" |
14 #include "base/location.h" | 15 #include "base/location.h" |
15 #include "base/metrics/histogram_macros.h" | 16 #include "base/metrics/histogram_macros.h" |
16 #include "base/single_thread_task_runner.h" | 17 #include "base/single_thread_task_runner.h" |
17 #include "base/stl_util.h" | 18 #include "base/stl_util.h" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 } | 66 } |
66 | 67 |
67 bool IsExpectedThreat( | 68 bool IsExpectedThreat( |
68 const SBThreatType threat_type, | 69 const SBThreatType threat_type, |
69 const std::vector<SBThreatType>& expected_threats) { | 70 const std::vector<SBThreatType>& expected_threats) { |
70 return expected_threats.end() != std::find(expected_threats.begin(), | 71 return expected_threats.end() != std::find(expected_threats.begin(), |
71 expected_threats.end(), | 72 expected_threats.end(), |
72 threat_type); | 73 threat_type); |
73 } | 74 } |
74 | 75 |
| 76 // Returns threat level of the list. Lists with lower threat levels are more |
| 77 // severe than lists with higher threat levels. Zero is the severest threat |
| 78 // level possible. |
| 79 int GetThreatSeverity(ListType threat) { |
| 80 switch (threat) { |
| 81 case MALWARE: // Falls through. |
| 82 case PHISH: // Falls through. |
| 83 case BINURL: // Falls through. |
| 84 case CSDWHITELIST: // Falls through. |
| 85 case DOWNLOADWHITELIST: // Falls through. |
| 86 case INCLUSIONWHITELIST: // Falls through. |
| 87 case MODULEWHITELIST: // Falls through. |
| 88 case EXTENSIONBLACKLIST: // Falls through. |
| 89 case IPBLACKLIST: |
| 90 return 0; |
| 91 case UNWANTEDURL: |
| 92 // UNWANTEDURL is considered less severe than other threats. |
| 93 return 1; |
| 94 case RESOURCEBLACKLIST: |
| 95 // RESOURCEBLACKLIST is even less severe than UNWANTEDURL. |
| 96 return 2; |
| 97 case INVALID: |
| 98 return std::numeric_limits<int>::max(); |
| 99 } |
| 100 NOTREACHED(); |
| 101 return -1; |
| 102 } |
| 103 |
75 // Return the severest list id from the results in |full_hashes| which matches | 104 // Return the severest list id from the results in |full_hashes| which matches |
76 // |hash|, or INVALID if none match. | 105 // |hash|, or INVALID if none match. |
77 ListType GetHashSeverestThreatListType( | 106 ListType GetHashSeverestThreatListType( |
78 const SBFullHash& hash, | 107 const SBFullHash& hash, |
79 const std::vector<SBFullHashResult>& full_hashes, | 108 const std::vector<SBFullHashResult>& full_hashes, |
80 size_t* index) { | 109 size_t* index) { |
81 ListType pending_threat = INVALID; | 110 ListType pending_threat = INVALID; |
| 111 int pending_threat_severity = GetThreatSeverity(INVALID); |
82 for (size_t i = 0; i < full_hashes.size(); ++i) { | 112 for (size_t i = 0; i < full_hashes.size(); ++i) { |
83 if (SBFullHashEqual(hash, full_hashes[i].hash)) { | 113 if (SBFullHashEqual(hash, full_hashes[i].hash)) { |
84 const ListType threat = | 114 const ListType threat = |
85 static_cast<ListType>(full_hashes[i].list_id); | 115 static_cast<ListType>(full_hashes[i].list_id); |
86 switch (threat) { | 116 int threat_severity = GetThreatSeverity(threat); |
87 case INVALID: | 117 if (threat_severity < pending_threat_severity) { |
88 // |full_hashes| should never contain INVALID as a |list_id|. | 118 pending_threat = threat; |
89 NOTREACHED(); | 119 pending_threat_severity = threat_severity; |
90 break; | 120 if (index) |
91 case MALWARE: // Falls through. | 121 *index = i; |
92 case PHISH: // Falls through. | |
93 case BINURL: // Falls through. | |
94 case CSDWHITELIST: // Falls through. | |
95 case DOWNLOADWHITELIST: // Falls through. | |
96 case INCLUSIONWHITELIST: // Falls through. | |
97 case MODULEWHITELIST: // Falls through. | |
98 case EXTENSIONBLACKLIST: // Falls through. | |
99 case IPBLACKLIST: | |
100 if (index) | |
101 *index = i; | |
102 return threat; | |
103 case UNWANTEDURL: | |
104 // UNWANTEDURL is considered less severe than other threats, keep | |
105 // looking. | |
106 pending_threat = threat; | |
107 if (index) | |
108 *index = i; | |
109 break; | |
110 } | 122 } |
| 123 if (pending_threat_severity == 0) |
| 124 return pending_threat; |
111 } | 125 } |
112 } | 126 } |
113 return pending_threat; | 127 return pending_threat; |
114 } | 128 } |
115 | 129 |
116 // Given a URL, compare all the possible host + path full hashes to the set of | 130 // Given a URL, compare all the possible host + path full hashes to the set of |
117 // provided full hashes. Returns the list id of the severest matching result | 131 // provided full hashes. Returns the list id of the severest matching result |
118 // from |full_hashes|, or INVALID if none match. | 132 // from |full_hashes|, or INVALID if none match. |
119 ListType GetUrlSeverestThreatListType( | 133 ListType GetUrlSeverestThreatListType( |
120 const GURL& url, | 134 const GURL& url, |
121 const std::vector<SBFullHashResult>& full_hashes, | 135 const std::vector<SBFullHashResult>& full_hashes, |
122 size_t* index) { | 136 size_t* index) { |
123 if (full_hashes.empty()) | 137 if (full_hashes.empty()) |
124 return INVALID; | 138 return INVALID; |
125 | 139 |
126 std::vector<std::string> patterns; | 140 std::vector<std::string> patterns; |
127 GeneratePatternsToCheck(url, &patterns); | 141 GeneratePatternsToCheck(url, &patterns); |
128 | 142 |
129 ListType pending_threat = INVALID; | 143 ListType pending_threat = INVALID; |
| 144 int pending_threat_severity = GetThreatSeverity(INVALID); |
130 for (size_t i = 0; i < patterns.size(); ++i) { | 145 for (size_t i = 0; i < patterns.size(); ++i) { |
131 ListType threat = GetHashSeverestThreatListType( | 146 ListType threat = GetHashSeverestThreatListType( |
132 SBFullHashForString(patterns[i]), full_hashes, index); | 147 SBFullHashForString(patterns[i]), full_hashes, index); |
133 switch (threat) { | 148 int threat_severity = GetThreatSeverity(threat); |
134 case INVALID: | 149 if (threat_severity < pending_threat_severity) { |
135 // Ignore patterns with no matching threat. | 150 pending_threat = threat; |
136 break; | 151 pending_threat_severity = threat_severity; |
137 case MALWARE: // Falls through. | |
138 case PHISH: // Falls through. | |
139 case BINURL: // Falls through. | |
140 case CSDWHITELIST: // Falls through. | |
141 case DOWNLOADWHITELIST: // Falls through. | |
142 case INCLUSIONWHITELIST: // Falls through. | |
143 case MODULEWHITELIST: // Falls through. | |
144 case EXTENSIONBLACKLIST: // Falls through. | |
145 case IPBLACKLIST: | |
146 return threat; | |
147 case UNWANTEDURL: | |
148 // UNWANTEDURL is considered less severe than other threats, keep | |
149 // looking. | |
150 pending_threat = threat; | |
151 break; | |
152 } | 152 } |
| 153 if (pending_threat_severity == 0) |
| 154 return pending_threat; |
153 } | 155 } |
154 return pending_threat; | 156 return pending_threat; |
155 } | 157 } |
156 | 158 |
157 SBThreatType GetThreatTypeFromListType(ListType list_type) { | 159 SBThreatType GetThreatTypeFromListType(ListType list_type) { |
158 switch (list_type) { | 160 switch (list_type) { |
159 case PHISH: | 161 case PHISH: |
160 return SB_THREAT_TYPE_URL_PHISHING; | 162 return SB_THREAT_TYPE_URL_PHISHING; |
161 case MALWARE: | 163 case MALWARE: |
162 return SB_THREAT_TYPE_URL_MALWARE; | 164 return SB_THREAT_TYPE_URL_MALWARE; |
163 case UNWANTEDURL: | 165 case UNWANTEDURL: |
164 return SB_THREAT_TYPE_URL_UNWANTED; | 166 return SB_THREAT_TYPE_URL_UNWANTED; |
165 case BINURL: | 167 case BINURL: |
166 return SB_THREAT_TYPE_BINARY_MALWARE_URL; | 168 return SB_THREAT_TYPE_BINARY_MALWARE_URL; |
167 case EXTENSIONBLACKLIST: | 169 case EXTENSIONBLACKLIST: |
168 return SB_THREAT_TYPE_EXTENSION; | 170 return SB_THREAT_TYPE_EXTENSION; |
| 171 case RESOURCEBLACKLIST: |
| 172 return SB_THREAT_TYPE_BLACKLISTED_RESOURCE; |
169 default: | 173 default: |
170 DVLOG(1) << "Unknown safe browsing list id " << list_type; | 174 DVLOG(1) << "Unknown safe browsing list id " << list_type; |
171 return SB_THREAT_TYPE_SAFE; | 175 return SB_THREAT_TYPE_SAFE; |
172 } | 176 } |
173 } | 177 } |
174 | 178 |
175 } // namespace | 179 } // namespace |
176 | 180 |
177 // static | 181 // static |
178 SBThreatType LocalSafeBrowsingDatabaseManager::GetHashSeverestThreatType( | 182 SBThreatType LocalSafeBrowsingDatabaseManager::GetHashSeverestThreatType( |
(...skipping 14 matching lines...) Expand all Loading... |
193 | 197 |
194 LocalSafeBrowsingDatabaseManager::SafeBrowsingCheck::SafeBrowsingCheck( | 198 LocalSafeBrowsingDatabaseManager::SafeBrowsingCheck::SafeBrowsingCheck( |
195 const std::vector<GURL>& urls, | 199 const std::vector<GURL>& urls, |
196 const std::vector<SBFullHash>& full_hashes, | 200 const std::vector<SBFullHash>& full_hashes, |
197 Client* client, | 201 Client* client, |
198 ListType check_type, | 202 ListType check_type, |
199 const std::vector<SBThreatType>& expected_threats) | 203 const std::vector<SBThreatType>& expected_threats) |
200 : urls(urls), | 204 : urls(urls), |
201 url_results(urls.size(), SB_THREAT_TYPE_SAFE), | 205 url_results(urls.size(), SB_THREAT_TYPE_SAFE), |
202 url_metadata(urls.size()), | 206 url_metadata(urls.size()), |
| 207 url_hit_hash(urls.size()), |
203 full_hashes(full_hashes), | 208 full_hashes(full_hashes), |
204 full_hash_results(full_hashes.size(), SB_THREAT_TYPE_SAFE), | 209 full_hash_results(full_hashes.size(), SB_THREAT_TYPE_SAFE), |
205 client(client), | 210 client(client), |
206 need_get_hash(false), | 211 need_get_hash(false), |
207 check_type(check_type), | 212 check_type(check_type), |
208 expected_threats(expected_threats) { | 213 expected_threats(expected_threats) { |
209 DCHECK_EQ(urls.empty(), !full_hashes.empty()) | 214 DCHECK_EQ(urls.empty(), !full_hashes.empty()) |
210 << "Exactly one of urls and full_hashes must be set"; | 215 << "Exactly one of urls and full_hashes must be set"; |
211 } | 216 } |
212 | 217 |
(...skipping 15 matching lines...) Expand all Loading... |
228 case UNWANTEDURL: | 233 case UNWANTEDURL: |
229 DCHECK_EQ(1u, urls.size()); | 234 DCHECK_EQ(1u, urls.size()); |
230 client->OnCheckBrowseUrlResult(urls[0], url_results[0], | 235 client->OnCheckBrowseUrlResult(urls[0], url_results[0], |
231 url_metadata[0]); | 236 url_metadata[0]); |
232 break; | 237 break; |
233 case BINURL: | 238 case BINURL: |
234 DCHECK_EQ(urls.size(), url_results.size()); | 239 DCHECK_EQ(urls.size(), url_results.size()); |
235 client->OnCheckDownloadUrlResult( | 240 client->OnCheckDownloadUrlResult( |
236 urls, *std::max_element(url_results.begin(), url_results.end())); | 241 urls, *std::max_element(url_results.begin(), url_results.end())); |
237 break; | 242 break; |
| 243 case RESOURCEBLACKLIST: |
| 244 DCHECK_EQ(1u, urls.size()); |
| 245 client->OnCheckResourceUrlResult(urls[0], url_results[0], |
| 246 url_hit_hash[0]); |
| 247 break; |
238 default: | 248 default: |
239 NOTREACHED(); | 249 NOTREACHED(); |
240 } | 250 } |
241 } else if (!full_hashes.empty()) { | 251 } else if (!full_hashes.empty()) { |
242 switch (check_type) { | 252 switch (check_type) { |
243 case EXTENSIONBLACKLIST: { | 253 case EXTENSIONBLACKLIST: { |
244 std::set<std::string> unsafe_extension_ids; | 254 std::set<std::string> unsafe_extension_ids; |
245 for (size_t i = 0; i < full_hashes.size(); ++i) { | 255 for (size_t i = 0; i < full_hashes.size(); ++i) { |
246 std::string extension_id = | 256 std::string extension_id = |
247 SBFullHashToString(full_hashes[i]); | 257 SBFullHashToString(full_hashes[i]); |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 client, | 392 client, |
383 EXTENSIONBLACKLIST, | 393 EXTENSIONBLACKLIST, |
384 std::vector<SBThreatType>(1, SB_THREAT_TYPE_EXTENSION)); | 394 std::vector<SBThreatType>(1, SB_THREAT_TYPE_EXTENSION)); |
385 StartSafeBrowsingCheck( | 395 StartSafeBrowsingCheck( |
386 check, | 396 check, |
387 base::Bind(&LocalSafeBrowsingDatabaseManager::CheckExtensionIDsOnSBThread, | 397 base::Bind(&LocalSafeBrowsingDatabaseManager::CheckExtensionIDsOnSBThread, |
388 this, prefixes)); | 398 this, prefixes)); |
389 return false; | 399 return false; |
390 } | 400 } |
391 | 401 |
| 402 bool LocalSafeBrowsingDatabaseManager::CheckResourceUrl( |
| 403 const GURL& url, Client* client) { |
| 404 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 405 |
| 406 if (!enabled_ || !CanCheckUrl(url)) |
| 407 return true; |
| 408 |
| 409 std::vector<SBThreatType> expected_threats = |
| 410 {SB_THREAT_TYPE_BLACKLISTED_RESOURCE}; |
| 411 |
| 412 if (!MakeDatabaseAvailable()) { |
| 413 QueuedCheck queued_check(RESOURCEBLACKLIST, client, url, |
| 414 expected_threats, base::TimeTicks::Now()); |
| 415 queued_checks_.push_back(queued_check); |
| 416 return false; |
| 417 } |
| 418 |
| 419 SafeBrowsingCheck* check = |
| 420 new SafeBrowsingCheck({url}, std::vector<SBFullHash>(), client, |
| 421 RESOURCEBLACKLIST, expected_threats); |
| 422 |
| 423 std::vector<SBPrefix> prefixes; |
| 424 SafeBrowsingDatabase::GetDownloadUrlPrefixes(check->urls, &prefixes); |
| 425 StartSafeBrowsingCheck( |
| 426 check, |
| 427 base::Bind(&LocalSafeBrowsingDatabaseManager::CheckResourceUrlOnSBThread, |
| 428 this, prefixes)); |
| 429 return false; |
| 430 } |
| 431 |
392 bool LocalSafeBrowsingDatabaseManager::MatchMalwareIP( | 432 bool LocalSafeBrowsingDatabaseManager::MatchMalwareIP( |
393 const std::string& ip_address) { | 433 const std::string& ip_address) { |
394 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 434 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
395 if (!enabled_ || !enable_ip_blacklist_ || !MakeDatabaseAvailable()) { | 435 if (!enabled_ || !enable_ip_blacklist_ || !MakeDatabaseAvailable()) { |
396 return false; // Fail open. | 436 return false; // Fail open. |
397 } | 437 } |
398 return database_->ContainsMalwareIP(ip_address); | 438 return database_->ContainsMalwareIP(ip_address); |
399 } | 439 } |
400 | 440 |
401 bool LocalSafeBrowsingDatabaseManager::MatchCsdWhitelistUrl(const GURL& url) { | 441 bool LocalSafeBrowsingDatabaseManager::MatchCsdWhitelistUrl(const GURL& url) { |
(...skipping 701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1103 } | 1143 } |
1104 | 1144 |
1105 for (size_t i = 0; i < check->urls.size(); ++i) { | 1145 for (size_t i = 0; i < check->urls.size(); ++i) { |
1106 size_t threat_index; | 1146 size_t threat_index; |
1107 SBThreatType threat = GetUrlSeverestThreatType(check->urls[i], | 1147 SBThreatType threat = GetUrlSeverestThreatType(check->urls[i], |
1108 expected_full_hashes, | 1148 expected_full_hashes, |
1109 &threat_index); | 1149 &threat_index); |
1110 if (threat != SB_THREAT_TYPE_SAFE) { | 1150 if (threat != SB_THREAT_TYPE_SAFE) { |
1111 check->url_results[i] = threat; | 1151 check->url_results[i] = threat; |
1112 check->url_metadata[i] = expected_full_hashes[threat_index].metadata; | 1152 check->url_metadata[i] = expected_full_hashes[threat_index].metadata; |
| 1153 const SBFullHash& hash = expected_full_hashes[threat_index].hash; |
| 1154 check->url_hit_hash[i] = std::string(hash.full_hash, |
| 1155 arraysize(hash.full_hash)); |
1113 is_threat = true; | 1156 is_threat = true; |
1114 } | 1157 } |
1115 } | 1158 } |
1116 | 1159 |
1117 for (size_t i = 0; i < check->full_hashes.size(); ++i) { | 1160 for (size_t i = 0; i < check->full_hashes.size(); ++i) { |
1118 SBThreatType threat = | 1161 SBThreatType threat = |
1119 GetHashSeverestThreatType(check->full_hashes[i], expected_full_hashes); | 1162 GetHashSeverestThreatType(check->full_hashes[i], expected_full_hashes); |
1120 if (threat != SB_THREAT_TYPE_SAFE) { | 1163 if (threat != SB_THREAT_TYPE_SAFE) { |
1121 check->full_hash_results[i] = threat; | 1164 check->full_hash_results[i] = threat; |
1122 is_threat = true; | 1165 is_threat = true; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1160 const std::vector<SBPrefix>& prefixes) { | 1203 const std::vector<SBPrefix>& prefixes) { |
1161 DCHECK(safe_browsing_task_runner_->RunsTasksOnCurrentThread()); | 1204 DCHECK(safe_browsing_task_runner_->RunsTasksOnCurrentThread()); |
1162 | 1205 |
1163 std::vector<SBPrefix> prefix_hits; | 1206 std::vector<SBPrefix> prefix_hits; |
1164 const bool result = | 1207 const bool result = |
1165 database_->ContainsExtensionPrefixes(prefixes, &prefix_hits); | 1208 database_->ContainsExtensionPrefixes(prefixes, &prefix_hits); |
1166 DCHECK_EQ(result, !prefix_hits.empty()); | 1209 DCHECK_EQ(result, !prefix_hits.empty()); |
1167 return prefix_hits; | 1210 return prefix_hits; |
1168 } | 1211 } |
1169 | 1212 |
| 1213 std::vector<SBPrefix> |
| 1214 LocalSafeBrowsingDatabaseManager::CheckResourceUrlOnSBThread( |
| 1215 const std::vector<SBPrefix>& prefixes) { |
| 1216 DCHECK(safe_browsing_task_runner_->RunsTasksOnCurrentThread()); |
| 1217 |
| 1218 std::vector<SBPrefix> prefix_hits; |
| 1219 const bool result = |
| 1220 database_->ContainsResourceUrlPrefixes(prefixes, &prefix_hits); |
| 1221 DCHECK_EQ(result, !prefix_hits.empty()); |
| 1222 return prefix_hits; |
| 1223 } |
| 1224 |
1170 void LocalSafeBrowsingDatabaseManager::TimeoutCallback( | 1225 void LocalSafeBrowsingDatabaseManager::TimeoutCallback( |
1171 SafeBrowsingCheck* check) { | 1226 SafeBrowsingCheck* check) { |
1172 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 1227 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
1173 DCHECK(check); | 1228 DCHECK(check); |
1174 | 1229 |
1175 if (!enabled_) | 1230 if (!enabled_) |
1176 return; | 1231 return; |
1177 | 1232 |
1178 DCHECK(checks_.find(check) != checks_.end()); | 1233 DCHECK(checks_.find(check) != checks_.end()); |
1179 if (check->client) { | 1234 if (check->client) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1214 FROM_HERE, base::Bind(&LocalSafeBrowsingDatabaseManager::TimeoutCallback, | 1269 FROM_HERE, base::Bind(&LocalSafeBrowsingDatabaseManager::TimeoutCallback, |
1215 check->weak_ptr_factory_->GetWeakPtr(), check), | 1270 check->weak_ptr_factory_->GetWeakPtr(), check), |
1216 check_timeout_); | 1271 check_timeout_); |
1217 } | 1272 } |
1218 | 1273 |
1219 bool LocalSafeBrowsingDatabaseManager::download_protection_enabled() const { | 1274 bool LocalSafeBrowsingDatabaseManager::download_protection_enabled() const { |
1220 return enable_download_protection_; | 1275 return enable_download_protection_; |
1221 } | 1276 } |
1222 | 1277 |
1223 } // namespace safe_browsing | 1278 } // namespace safe_browsing |
OLD | NEW |