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 GetThreatLevel(ListType threat) { | |
Nathan Parker
2016/02/17 16:00:39
How about GetThreatSeverity?
veranika
2016/02/18 14:53:26
Done.
| |
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 EXTENSIONBLACKLIST: // Falls through. | |
88 case IPBLACKLIST: | |
89 return 0; | |
90 case UNWANTEDURL: | |
91 // UNWANTEDURL is considered less severe than other threats. | |
92 return 1; | |
93 case RESOURCEBLACKLIST: | |
94 // RESOURCEBLACKLIST is even less severe than UNWANTEDURL. | |
95 return 2; | |
96 default: | |
Nathan Parker
2016/02/17 16:00:39
Can we remove the default? That way new threats h
veranika
2016/02/18 14:53:25
Done.
| |
97 return std::numeric_limits<int>::max(); | |
98 } | |
99 } | |
100 | |
75 // Return the severest list id from the results in |full_hashes| which matches | 101 // Return the severest list id from the results in |full_hashes| which matches |
76 // |hash|, or INVALID if none match. | 102 // |hash|, or INVALID if none match. |
77 ListType GetHashSeverestThreatListType( | 103 ListType GetHashSeverestThreatListType( |
78 const SBFullHash& hash, | 104 const SBFullHash& hash, |
79 const std::vector<SBFullHashResult>& full_hashes, | 105 const std::vector<SBFullHashResult>& full_hashes, |
80 size_t* index) { | 106 size_t* index) { |
81 ListType pending_threat = INVALID; | 107 ListType pending_threat = INVALID; |
108 int pending_threat_level = GetThreatLevel(INVALID); | |
82 for (size_t i = 0; i < full_hashes.size(); ++i) { | 109 for (size_t i = 0; i < full_hashes.size(); ++i) { |
83 if (SBFullHashEqual(hash, full_hashes[i].hash)) { | 110 if (SBFullHashEqual(hash, full_hashes[i].hash)) { |
84 const ListType threat = | 111 const ListType threat = |
85 static_cast<ListType>(full_hashes[i].list_id); | 112 static_cast<ListType>(full_hashes[i].list_id); |
86 switch (threat) { | 113 int threat_level = GetThreatLevel(threat); |
Nathan Parker
2016/02/17 16:00:39
Cool, this is better. Thanks.
| |
87 case INVALID: | 114 if (threat_level < pending_threat_level) { |
88 // |full_hashes| should never contain INVALID as a |list_id|. | 115 pending_threat = threat; |
89 NOTREACHED(); | 116 pending_threat_level = threat_level; |
90 break; | 117 if (index) |
91 case MALWARE: // Falls through. | 118 *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 EXTENSIONBLACKLIST: // Falls through. | |
98 case IPBLACKLIST: | |
99 if (index) | |
100 *index = i; | |
101 return threat; | |
102 case UNWANTEDURL: | |
103 // UNWANTEDURL is considered less severe than other threats, keep | |
104 // looking. | |
105 pending_threat = threat; | |
106 if (index) | |
107 *index = i; | |
108 break; | |
109 } | 119 } |
120 if (pending_threat_level == 0) | |
121 return pending_threat; | |
110 } | 122 } |
111 } | 123 } |
112 return pending_threat; | 124 return pending_threat; |
113 } | 125 } |
114 | 126 |
115 // Given a URL, compare all the possible host + path full hashes to the set of | 127 // Given a URL, compare all the possible host + path full hashes to the set of |
116 // provided full hashes. Returns the list id of the severest matching result | 128 // provided full hashes. Returns the list id of the severest matching result |
117 // from |full_hashes|, or INVALID if none match. | 129 // from |full_hashes|, or INVALID if none match. |
118 ListType GetUrlSeverestThreatListType( | 130 ListType GetUrlSeverestThreatListType( |
119 const GURL& url, | 131 const GURL& url, |
120 const std::vector<SBFullHashResult>& full_hashes, | 132 const std::vector<SBFullHashResult>& full_hashes, |
121 size_t* index) { | 133 size_t* index) { |
122 if (full_hashes.empty()) | 134 if (full_hashes.empty()) |
123 return INVALID; | 135 return INVALID; |
124 | 136 |
125 std::vector<std::string> patterns; | 137 std::vector<std::string> patterns; |
126 GeneratePatternsToCheck(url, &patterns); | 138 GeneratePatternsToCheck(url, &patterns); |
127 | 139 |
128 ListType pending_threat = INVALID; | 140 ListType pending_threat = INVALID; |
141 int pending_threat_level = GetThreatLevel(INVALID); | |
129 for (size_t i = 0; i < patterns.size(); ++i) { | 142 for (size_t i = 0; i < patterns.size(); ++i) { |
130 ListType threat = GetHashSeverestThreatListType( | 143 ListType threat = GetHashSeverestThreatListType( |
131 SBFullHashForString(patterns[i]), full_hashes, index); | 144 SBFullHashForString(patterns[i]), full_hashes, index); |
132 switch (threat) { | 145 int threat_level = GetThreatLevel(threat); |
133 case INVALID: | 146 if (threat_level < pending_threat_level) { |
134 // Ignore patterns with no matching threat. | 147 pending_threat = threat; |
135 break; | 148 pending_threat_level = threat_level; |
136 case MALWARE: // Falls through. | |
137 case PHISH: // Falls through. | |
138 case BINURL: // Falls through. | |
139 case CSDWHITELIST: // Falls through. | |
140 case DOWNLOADWHITELIST: // Falls through. | |
141 case INCLUSIONWHITELIST: // Falls through. | |
142 case EXTENSIONBLACKLIST: // Falls through. | |
143 case IPBLACKLIST: | |
144 return threat; | |
145 case UNWANTEDURL: | |
146 // UNWANTEDURL is considered less severe than other threats, keep | |
147 // looking. | |
148 pending_threat = threat; | |
149 break; | |
150 } | 149 } |
150 if (pending_threat_level == 0) | |
151 return pending_threat; | |
151 } | 152 } |
152 return pending_threat; | 153 return pending_threat; |
153 } | 154 } |
154 | 155 |
155 SBThreatType GetThreatTypeFromListType(ListType list_type) { | 156 SBThreatType GetThreatTypeFromListType(ListType list_type) { |
156 switch (list_type) { | 157 switch (list_type) { |
157 case PHISH: | 158 case PHISH: |
158 return SB_THREAT_TYPE_URL_PHISHING; | 159 return SB_THREAT_TYPE_URL_PHISHING; |
159 case MALWARE: | 160 case MALWARE: |
160 return SB_THREAT_TYPE_URL_MALWARE; | 161 return SB_THREAT_TYPE_URL_MALWARE; |
161 case UNWANTEDURL: | 162 case UNWANTEDURL: |
162 return SB_THREAT_TYPE_URL_UNWANTED; | 163 return SB_THREAT_TYPE_URL_UNWANTED; |
163 case BINURL: | 164 case BINURL: |
164 return SB_THREAT_TYPE_BINARY_MALWARE_URL; | 165 return SB_THREAT_TYPE_BINARY_MALWARE_URL; |
165 case EXTENSIONBLACKLIST: | 166 case EXTENSIONBLACKLIST: |
166 return SB_THREAT_TYPE_EXTENSION; | 167 return SB_THREAT_TYPE_EXTENSION; |
168 case RESOURCEBLACKLIST: | |
169 return SB_THREAT_TYPE_BLACKLISTED_RESOURCE; | |
167 default: | 170 default: |
168 DVLOG(1) << "Unknown safe browsing list id " << list_type; | 171 DVLOG(1) << "Unknown safe browsing list id " << list_type; |
169 return SB_THREAT_TYPE_SAFE; | 172 return SB_THREAT_TYPE_SAFE; |
170 } | 173 } |
171 } | 174 } |
172 | 175 |
173 } // namespace | 176 } // namespace |
174 | 177 |
175 // static | 178 // static |
176 SBThreatType LocalSafeBrowsingDatabaseManager::GetHashSeverestThreatType( | 179 SBThreatType LocalSafeBrowsingDatabaseManager::GetHashSeverestThreatType( |
(...skipping 14 matching lines...) Expand all Loading... | |
191 | 194 |
192 LocalSafeBrowsingDatabaseManager::SafeBrowsingCheck::SafeBrowsingCheck( | 195 LocalSafeBrowsingDatabaseManager::SafeBrowsingCheck::SafeBrowsingCheck( |
193 const std::vector<GURL>& urls, | 196 const std::vector<GURL>& urls, |
194 const std::vector<SBFullHash>& full_hashes, | 197 const std::vector<SBFullHash>& full_hashes, |
195 Client* client, | 198 Client* client, |
196 ListType check_type, | 199 ListType check_type, |
197 const std::vector<SBThreatType>& expected_threats) | 200 const std::vector<SBThreatType>& expected_threats) |
198 : urls(urls), | 201 : urls(urls), |
199 url_results(urls.size(), SB_THREAT_TYPE_SAFE), | 202 url_results(urls.size(), SB_THREAT_TYPE_SAFE), |
200 url_metadata(urls.size()), | 203 url_metadata(urls.size()), |
204 url_hit_hash(urls.size()), | |
201 full_hashes(full_hashes), | 205 full_hashes(full_hashes), |
202 full_hash_results(full_hashes.size(), SB_THREAT_TYPE_SAFE), | 206 full_hash_results(full_hashes.size(), SB_THREAT_TYPE_SAFE), |
203 client(client), | 207 client(client), |
204 need_get_hash(false), | 208 need_get_hash(false), |
205 check_type(check_type), | 209 check_type(check_type), |
206 expected_threats(expected_threats) { | 210 expected_threats(expected_threats) { |
207 DCHECK_EQ(urls.empty(), !full_hashes.empty()) | 211 DCHECK_EQ(urls.empty(), !full_hashes.empty()) |
208 << "Exactly one of urls and full_hashes must be set"; | 212 << "Exactly one of urls and full_hashes must be set"; |
209 } | 213 } |
210 | 214 |
(...skipping 15 matching lines...) Expand all Loading... | |
226 case UNWANTEDURL: | 230 case UNWANTEDURL: |
227 DCHECK_EQ(1u, urls.size()); | 231 DCHECK_EQ(1u, urls.size()); |
228 client->OnCheckBrowseUrlResult(urls[0], url_results[0], | 232 client->OnCheckBrowseUrlResult(urls[0], url_results[0], |
229 url_metadata[0]); | 233 url_metadata[0]); |
230 break; | 234 break; |
231 case BINURL: | 235 case BINURL: |
232 DCHECK_EQ(urls.size(), url_results.size()); | 236 DCHECK_EQ(urls.size(), url_results.size()); |
233 client->OnCheckDownloadUrlResult( | 237 client->OnCheckDownloadUrlResult( |
234 urls, *std::max_element(url_results.begin(), url_results.end())); | 238 urls, *std::max_element(url_results.begin(), url_results.end())); |
235 break; | 239 break; |
240 case RESOURCEBLACKLIST: | |
241 DCHECK_EQ(1u, urls.size()); | |
242 client->OnCheckResourceUrlResult(urls[0], url_results[0], | |
243 url_hit_hash[0]); | |
244 break; | |
236 default: | 245 default: |
237 NOTREACHED(); | 246 NOTREACHED(); |
238 } | 247 } |
239 } else if (!full_hashes.empty()) { | 248 } else if (!full_hashes.empty()) { |
240 switch (check_type) { | 249 switch (check_type) { |
241 case EXTENSIONBLACKLIST: { | 250 case EXTENSIONBLACKLIST: { |
242 std::set<std::string> unsafe_extension_ids; | 251 std::set<std::string> unsafe_extension_ids; |
243 for (size_t i = 0; i < full_hashes.size(); ++i) { | 252 for (size_t i = 0; i < full_hashes.size(); ++i) { |
244 std::string extension_id = | 253 std::string extension_id = |
245 SBFullHashToString(full_hashes[i]); | 254 SBFullHashToString(full_hashes[i]); |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
379 client, | 388 client, |
380 EXTENSIONBLACKLIST, | 389 EXTENSIONBLACKLIST, |
381 std::vector<SBThreatType>(1, SB_THREAT_TYPE_EXTENSION)); | 390 std::vector<SBThreatType>(1, SB_THREAT_TYPE_EXTENSION)); |
382 StartSafeBrowsingCheck( | 391 StartSafeBrowsingCheck( |
383 check, | 392 check, |
384 base::Bind(&LocalSafeBrowsingDatabaseManager::CheckExtensionIDsOnSBThread, | 393 base::Bind(&LocalSafeBrowsingDatabaseManager::CheckExtensionIDsOnSBThread, |
385 this, prefixes)); | 394 this, prefixes)); |
386 return false; | 395 return false; |
387 } | 396 } |
388 | 397 |
398 bool LocalSafeBrowsingDatabaseManager::CheckResourceUrl( | |
399 const GURL& url, Client* client) { | |
400 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
401 | |
402 if (!enabled_ || !CanCheckUrl(url)) | |
403 return true; | |
404 | |
405 std::vector<SBThreatType> expected_threats = | |
406 {SB_THREAT_TYPE_BLACKLISTED_RESOURCE}; | |
407 | |
408 if (!MakeDatabaseAvailable()) { | |
409 QueuedCheck queued_check(RESOURCEBLACKLIST, client, url, | |
410 expected_threats, base::TimeTicks::Now()); | |
411 queued_checks_.push_back(queued_check); | |
412 return false; | |
413 } | |
414 | |
415 SafeBrowsingCheck* check = | |
416 new SafeBrowsingCheck({url}, std::vector<SBFullHash>(), client, | |
417 RESOURCEBLACKLIST, expected_threats); | |
418 | |
419 std::vector<SBPrefix> prefixes; | |
420 SafeBrowsingDatabase::GetDownloadUrlPrefixes(check->urls, &prefixes); | |
421 StartSafeBrowsingCheck( | |
422 check, | |
423 base::Bind(&LocalSafeBrowsingDatabaseManager::CheckResourceUrlOnSBThread, | |
424 this, prefixes)); | |
425 return false; | |
426 } | |
427 | |
389 bool LocalSafeBrowsingDatabaseManager::MatchMalwareIP( | 428 bool LocalSafeBrowsingDatabaseManager::MatchMalwareIP( |
390 const std::string& ip_address) { | 429 const std::string& ip_address) { |
391 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 430 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
392 if (!enabled_ || !enable_ip_blacklist_ || !MakeDatabaseAvailable()) { | 431 if (!enabled_ || !enable_ip_blacklist_ || !MakeDatabaseAvailable()) { |
393 return false; // Fail open. | 432 return false; // Fail open. |
394 } | 433 } |
395 return database_->ContainsMalwareIP(ip_address); | 434 return database_->ContainsMalwareIP(ip_address); |
396 } | 435 } |
397 | 436 |
398 bool LocalSafeBrowsingDatabaseManager::MatchCsdWhitelistUrl(const GURL& url) { | 437 bool LocalSafeBrowsingDatabaseManager::MatchCsdWhitelistUrl(const GURL& url) { |
(...skipping 692 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1091 } | 1130 } |
1092 | 1131 |
1093 for (size_t i = 0; i < check->urls.size(); ++i) { | 1132 for (size_t i = 0; i < check->urls.size(); ++i) { |
1094 size_t threat_index; | 1133 size_t threat_index; |
1095 SBThreatType threat = GetUrlSeverestThreatType(check->urls[i], | 1134 SBThreatType threat = GetUrlSeverestThreatType(check->urls[i], |
1096 expected_full_hashes, | 1135 expected_full_hashes, |
1097 &threat_index); | 1136 &threat_index); |
1098 if (threat != SB_THREAT_TYPE_SAFE) { | 1137 if (threat != SB_THREAT_TYPE_SAFE) { |
1099 check->url_results[i] = threat; | 1138 check->url_results[i] = threat; |
1100 check->url_metadata[i] = expected_full_hashes[threat_index].metadata; | 1139 check->url_metadata[i] = expected_full_hashes[threat_index].metadata; |
1140 const SBFullHash& hash = expected_full_hashes[threat_index].hash; | |
1141 check->url_hit_hash[i] = std::string(hash.full_hash, | |
1142 arraysize(hash.full_hash)); | |
1101 is_threat = true; | 1143 is_threat = true; |
1102 } | 1144 } |
1103 } | 1145 } |
1104 | 1146 |
1105 for (size_t i = 0; i < check->full_hashes.size(); ++i) { | 1147 for (size_t i = 0; i < check->full_hashes.size(); ++i) { |
1106 SBThreatType threat = | 1148 SBThreatType threat = |
1107 GetHashSeverestThreatType(check->full_hashes[i], expected_full_hashes); | 1149 GetHashSeverestThreatType(check->full_hashes[i], expected_full_hashes); |
1108 if (threat != SB_THREAT_TYPE_SAFE) { | 1150 if (threat != SB_THREAT_TYPE_SAFE) { |
1109 check->full_hash_results[i] = threat; | 1151 check->full_hash_results[i] = threat; |
1110 is_threat = true; | 1152 is_threat = true; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1148 const std::vector<SBPrefix>& prefixes) { | 1190 const std::vector<SBPrefix>& prefixes) { |
1149 DCHECK(safe_browsing_task_runner_->RunsTasksOnCurrentThread()); | 1191 DCHECK(safe_browsing_task_runner_->RunsTasksOnCurrentThread()); |
1150 | 1192 |
1151 std::vector<SBPrefix> prefix_hits; | 1193 std::vector<SBPrefix> prefix_hits; |
1152 const bool result = | 1194 const bool result = |
1153 database_->ContainsExtensionPrefixes(prefixes, &prefix_hits); | 1195 database_->ContainsExtensionPrefixes(prefixes, &prefix_hits); |
1154 DCHECK_EQ(result, !prefix_hits.empty()); | 1196 DCHECK_EQ(result, !prefix_hits.empty()); |
1155 return prefix_hits; | 1197 return prefix_hits; |
1156 } | 1198 } |
1157 | 1199 |
1200 std::vector<SBPrefix> | |
1201 LocalSafeBrowsingDatabaseManager::CheckResourceUrlOnSBThread( | |
1202 const std::vector<SBPrefix>& prefixes) { | |
1203 DCHECK(safe_browsing_task_runner_->RunsTasksOnCurrentThread()); | |
1204 | |
1205 std::vector<SBPrefix> prefix_hits; | |
1206 const bool result = | |
1207 database_->ContainsResourceUrlPrefixes(prefixes, &prefix_hits); | |
1208 DCHECK_EQ(result, !prefix_hits.empty()); | |
1209 return prefix_hits; | |
1210 } | |
1211 | |
1158 void LocalSafeBrowsingDatabaseManager::TimeoutCallback( | 1212 void LocalSafeBrowsingDatabaseManager::TimeoutCallback( |
1159 SafeBrowsingCheck* check) { | 1213 SafeBrowsingCheck* check) { |
1160 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 1214 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
1161 DCHECK(check); | 1215 DCHECK(check); |
1162 | 1216 |
1163 if (!enabled_) | 1217 if (!enabled_) |
1164 return; | 1218 return; |
1165 | 1219 |
1166 DCHECK(checks_.find(check) != checks_.end()); | 1220 DCHECK(checks_.find(check) != checks_.end()); |
1167 if (check->client) { | 1221 if (check->client) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1202 FROM_HERE, base::Bind(&LocalSafeBrowsingDatabaseManager::TimeoutCallback, | 1256 FROM_HERE, base::Bind(&LocalSafeBrowsingDatabaseManager::TimeoutCallback, |
1203 check->weak_ptr_factory_->GetWeakPtr(), check), | 1257 check->weak_ptr_factory_->GetWeakPtr(), check), |
1204 check_timeout_); | 1258 check_timeout_); |
1205 } | 1259 } |
1206 | 1260 |
1207 bool LocalSafeBrowsingDatabaseManager::download_protection_enabled() const { | 1261 bool LocalSafeBrowsingDatabaseManager::download_protection_enabled() const { |
1208 return enable_download_protection_; | 1262 return enable_download_protection_; |
1209 } | 1263 } |
1210 | 1264 |
1211 } // namespace safe_browsing | 1265 } // namespace safe_browsing |
OLD | NEW |