Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1727)

Side by Side Diff: components/safe_browsing_db/safe_browsing_db_util.cc

Issue 1420053005: Move code in components/safe_browsing_db and chrome/browser/s_b/ under the safe_browsing namespace. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@02_components_move
Patch Set: Remove '// namespace safe_browsing' for a small fwd decl block. Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/safe_browsing_db/safe_browsing_db_util.h"
6
7 #include "crypto/sha2.h"
8
9 // Utility functions -----------------------------------------------------------
10
11 namespace {
12 bool IsKnownList(const std::string& name) {
13 for (size_t i = 0; i < arraysize(kAllLists); ++i) {
14 if (!strcmp(kAllLists[i], name.c_str())) {
15 return true;
16 }
17 }
18 return false;
19 }
20 } // namespace
21
22
23 namespace safe_browsing {
24
25 // Listnames that browser can process.
26 // TODO(shess): This shouldn't be OS-driven <http://crbug.com/394379>
27 #if defined(OS_ANDROID)
28 // NOTE(shess): This difference is also reflected in the store name in
29 // safe_browsing_database.cc.
30 const char kMalwareList[] = "goog-mobilemalware-shavar";
31 const char kPhishingList[] = "goog-mobilephish-shavar";
32 #else
33 const char kMalwareList[] = "goog-malware-shavar";
34 const char kPhishingList[] = "goog-phish-shavar";
35 #endif
36 const char kBinUrlList[] = "goog-badbinurl-shavar";
37 const char kCsdWhiteList[] = "goog-csdwhite-sha256";
38 const char kDownloadWhiteList[] = "goog-downloadwhite-digest256";
39 const char kExtensionBlacklist[] = "goog-badcrxids-digestvar";
40 const char kIPBlacklist[] = "goog-badip-digest256";
41 const char kUnwantedUrlList[] = "goog-unwanted-shavar";
42 const char kInclusionWhitelist[] = "goog-csdinclusionwhite-sha256";
43
44 const char* kAllLists[9] = {
45 kMalwareList,
46 kPhishingList,
47 kBinUrlList,
48 kCsdWhiteList,
49 kDownloadWhiteList,
50 kExtensionBlacklist,
51 kIPBlacklist,
52 kUnwantedUrlList,
53 kInclusionWhitelist,
54 };
55
56 ListType GetListId(const base::StringPiece& name) {
57 ListType id;
58 if (name == kMalwareList) {
59 id = MALWARE;
60 } else if (name == kPhishingList) {
61 id = PHISH;
62 } else if (name == kBinUrlList) {
63 id = BINURL;
64 } else if (name == kCsdWhiteList) {
65 id = CSDWHITELIST;
66 } else if (name == kDownloadWhiteList) {
67 id = DOWNLOADWHITELIST;
68 } else if (name == kExtensionBlacklist) {
69 id = EXTENSIONBLACKLIST;
70 } else if (name == kIPBlacklist) {
71 id = IPBLACKLIST;
72 } else if (name == kUnwantedUrlList) {
73 id = UNWANTEDURL;
74 } else if (name == kInclusionWhitelist) {
75 id = INCLUSIONWHITELIST;
76 } else {
77 id = INVALID;
78 }
79 return id;
80 }
81
82 bool GetListName(ListType list_id, std::string* list) {
83 switch (list_id) {
84 case MALWARE:
85 *list = kMalwareList;
86 break;
87 case PHISH:
88 *list = kPhishingList;
89 break;
90 case BINURL:
91 *list = kBinUrlList;
92 break;
93 case CSDWHITELIST:
94 *list = kCsdWhiteList;
95 break;
96 case DOWNLOADWHITELIST:
97 *list = kDownloadWhiteList;
98 break;
99 case EXTENSIONBLACKLIST:
100 *list = kExtensionBlacklist;
101 break;
102 case IPBLACKLIST:
103 *list = kIPBlacklist;
104 break;
105 case UNWANTEDURL:
106 *list = kUnwantedUrlList;
107 break;
108 case INCLUSIONWHITELIST:
109 *list = kInclusionWhitelist;
110 break;
111 default:
112 return false;
113 }
114 DCHECK(IsKnownList(*list));
115 return true;
116 }
117
118
119 SBFullHash SBFullHashForString(const base::StringPiece& str) {
120 SBFullHash h;
121 crypto::SHA256HashString(str, &h.full_hash, sizeof(h.full_hash));
122 return h;
123 }
124
125 SBFullHash StringToSBFullHash(const std::string& hash_in) {
126 DCHECK_EQ(crypto::kSHA256Length, hash_in.size());
127 SBFullHash hash_out;
128 memcpy(hash_out.full_hash, hash_in.data(), crypto::kSHA256Length);
129 return hash_out;
130 }
131
132 std::string SBFullHashToString(const SBFullHash& hash) {
133 DCHECK_EQ(crypto::kSHA256Length, sizeof(hash.full_hash));
134 return std::string(hash.full_hash, sizeof(hash.full_hash));
135 }
136
137
138 std::string Unescape(const std::string& url) {
139 std::string unescaped_str(url);
140 std::string old_unescaped_str;
141 const int kMaxLoopIterations = 1024;
142 int loop_var = 0;
143 do {
144 old_unescaped_str = unescaped_str;
145 unescaped_str = net::UnescapeURLComponent(
146 old_unescaped_str, net::UnescapeRule::SPOOFING_AND_CONTROL_CHARS |
147 net::UnescapeRule::SPACES |
148 net::UnescapeRule::URL_SPECIAL_CHARS);
149 } while (unescaped_str != old_unescaped_str && ++loop_var <=
150 kMaxLoopIterations);
151
152 return unescaped_str;
153 }
154
155 std::string Escape(const std::string& url) {
156 std::string escaped_str;
157 const char* kHexString = "0123456789ABCDEF";
158 for (size_t i = 0; i < url.length(); i++) {
159 unsigned char c = static_cast<unsigned char>(url[i]);
160 if (c <= ' ' || c > '~' || c == '#' || c == '%') {
161 escaped_str.push_back('%');
162 escaped_str.push_back(kHexString[c >> 4]);
163 escaped_str.push_back(kHexString[c & 0xf]);
164 } else {
165 escaped_str.push_back(c);
166 }
167 }
168
169 return escaped_str;
170 }
171
172 std::string RemoveConsecutiveChars(const std::string& str, const char c) {
173 std::string output(str);
174 std::string string_to_find;
175 std::string::size_type loc = 0;
176 string_to_find.append(2, c);
177 while ((loc = output.find(string_to_find, loc)) != std::string::npos) {
178 output.erase(loc, 1);
179 }
180
181 return output;
182 }
183
184 // Canonicalizes url as per Google Safe Browsing Specification.
185 // See section 6.1 in
186 // http://code.google.com/p/google-safe-browsing/wiki/Protocolv2Spec.
187 void CanonicalizeUrl(const GURL& url,
188 std::string* canonicalized_hostname,
189 std::string* canonicalized_path,
190 std::string* canonicalized_query) {
191 DCHECK(url.is_valid());
192
193 // We only canonicalize "normal" URLs.
194 if (!url.IsStandard())
195 return;
196
197 // Following canonicalization steps are excluded since url parsing takes care
198 // of those :-
199 // 1. Remove any tab (0x09), CR (0x0d), and LF (0x0a) chars from url.
200 // (Exclude escaped version of these chars).
201 // 2. Normalize hostname to 4 dot-seperated decimal values.
202 // 3. Lowercase hostname.
203 // 4. Resolve path sequences "/../" and "/./".
204
205 // That leaves us with the following :-
206 // 1. Remove fragment in URL.
207 GURL url_without_fragment;
208 GURL::Replacements f_replacements;
209 f_replacements.ClearRef();
210 f_replacements.ClearUsername();
211 f_replacements.ClearPassword();
212 url_without_fragment = url.ReplaceComponents(f_replacements);
213
214 // 2. Do URL unescaping until no more hex encoded characters exist.
215 std::string url_unescaped_str(Unescape(url_without_fragment.spec()));
216 url::Parsed parsed;
217 url::ParseStandardURL(url_unescaped_str.data(), url_unescaped_str.length(),
218 &parsed);
219
220 // 3. In hostname, remove all leading and trailing dots.
221 const std::string host =
222 (parsed.host.len > 0)
223 ? url_unescaped_str.substr(parsed.host.begin, parsed.host.len)
224 : std::string();
225 std::string host_without_end_dots;
226 base::TrimString(host, ".", &host_without_end_dots);
227
228 // 4. In hostname, replace consecutive dots with a single dot.
229 std::string host_without_consecutive_dots(RemoveConsecutiveChars(
230 host_without_end_dots, '.'));
231
232 // 5. In path, replace runs of consecutive slashes with a single slash.
233 std::string path =
234 (parsed.path.len > 0)
235 ? url_unescaped_str.substr(parsed.path.begin, parsed.path.len)
236 : std::string();
237 std::string path_without_consecutive_slash(RemoveConsecutiveChars(path, '/'));
238
239 url::Replacements<char> hp_replacements;
240 hp_replacements.SetHost(
241 host_without_consecutive_dots.data(),
242 url::Component(0, host_without_consecutive_dots.length()));
243 hp_replacements.SetPath(
244 path_without_consecutive_slash.data(),
245 url::Component(0, path_without_consecutive_slash.length()));
246
247 std::string url_unescaped_with_can_hostpath;
248 url::StdStringCanonOutput output(&url_unescaped_with_can_hostpath);
249 url::Parsed temp_parsed;
250 url::ReplaceComponents(url_unescaped_str.data(),
251 url_unescaped_str.length(),
252 parsed,
253 hp_replacements,
254 NULL,
255 &output,
256 &temp_parsed);
257 output.Complete();
258
259 // 6. Step needed to revert escaping done in url::ReplaceComponents.
260 url_unescaped_with_can_hostpath = Unescape(url_unescaped_with_can_hostpath);
261
262 // 7. After performing all above steps, percent-escape all chars in url which
263 // are <= ASCII 32, >= 127, #, %. Escapes must be uppercase hex characters.
264 std::string escaped_canon_url_str(Escape(url_unescaped_with_can_hostpath));
265 url::Parsed final_parsed;
266 url::ParseStandardURL(escaped_canon_url_str.data(),
267 escaped_canon_url_str.length(),
268 &final_parsed);
269
270 if (canonicalized_hostname && final_parsed.host.len > 0) {
271 *canonicalized_hostname =
272 escaped_canon_url_str.substr(final_parsed.host.begin,
273 final_parsed.host.len);
274 }
275 if (canonicalized_path && final_parsed.path.len > 0) {
276 *canonicalized_path = escaped_canon_url_str.substr(final_parsed.path.begin,
277 final_parsed.path.len);
278 }
279 if (canonicalized_query && final_parsed.query.len > 0) {
280 *canonicalized_query = escaped_canon_url_str.substr(
281 final_parsed.query.begin, final_parsed.query.len);
282 }
283 }
284
285 void GenerateHostsToCheck(const GURL& url, std::vector<std::string>* hosts) {
286 hosts->clear();
287
288 std::string canon_host;
289 CanonicalizeUrl(url, &canon_host, NULL, NULL);
290
291 const std::string host = canon_host; // const sidesteps GCC bugs below!
292 if (host.empty())
293 return;
294
295 // Per the Safe Browsing Protocol v2 spec, we try the host, and also up to 4
296 // hostnames formed by starting with the last 5 components and successively
297 // removing the leading component. The last component isn't examined alone,
298 // since it's the TLD or a subcomponent thereof.
299 //
300 // Note that we don't need to be clever about stopping at the "real" eTLD --
301 // the data on the server side has been filtered to ensure it will not
302 // blacklist a whole TLD, and it's not significantly slower on our side to
303 // just check too much.
304 //
305 // Also note that because we have a simple blacklist, not some sort of complex
306 // whitelist-in-blacklist or vice versa, it doesn't matter what order we check
307 // these in.
308 const size_t kMaxHostsToCheck = 4;
309 bool skipped_last_component = false;
310 for (std::string::const_reverse_iterator i(host.rbegin());
311 i != host.rend() && hosts->size() < kMaxHostsToCheck; ++i) {
312 if (*i == '.') {
313 if (skipped_last_component)
314 hosts->push_back(std::string(i.base(), host.end()));
315 else
316 skipped_last_component = true;
317 }
318 }
319 hosts->push_back(host);
320 }
321
322 void GeneratePathsToCheck(const GURL& url, std::vector<std::string>* paths) {
323 paths->clear();
324
325 std::string canon_path;
326 std::string canon_query;
327 CanonicalizeUrl(url, NULL, &canon_path, &canon_query);
328
329 const std::string path = canon_path; // const sidesteps GCC bugs below!
330 const std::string query = canon_query;
331 if (path.empty())
332 return;
333
334 // Per the Safe Browsing Protocol v2 spec, we try the exact path with/without
335 // the query parameters, and also up to 4 paths formed by starting at the root
336 // and adding more path components.
337 //
338 // As with the hosts above, it doesn't matter what order we check these in.
339 const size_t kMaxPathsToCheck = 4;
340 for (std::string::const_iterator i(path.begin());
341 i != path.end() && paths->size() < kMaxPathsToCheck; ++i) {
342 if (*i == '/')
343 paths->push_back(std::string(path.begin(), i + 1));
344 }
345
346 if (!paths->empty() && paths->back() != path)
347 paths->push_back(path);
348
349 if (!query.empty())
350 paths->push_back(path + "?" + query);
351 }
352
353 void GeneratePatternsToCheck(const GURL& url, std::vector<std::string>* urls) {
354 std::vector<std::string> hosts, paths;
355 GenerateHostsToCheck(url, &hosts);
356 GeneratePathsToCheck(url, &paths);
357 for (size_t h = 0; h < hosts.size(); ++h) {
358 for (size_t p = 0; p < paths.size(); ++p) {
359 urls->push_back(hosts[h] + paths[p]);
360 }
361 }
362 }
363
364 } // namespace safe_browsing
OLDNEW
« no previous file with comments | « components/safe_browsing_db/safe_browsing_db_util.h ('k') | components/safe_browsing_db/safe_browsing_db_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698