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

Side by Side Diff: chrome/browser/safe_browsing/protocol_parser.cc

Issue 10069031: Replace SafeBrowsing MAC with downloads over SSL. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 8 months 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 | Annotate | Revision Log
OLDNEW
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 // Parse the data returned from the SafeBrowsing v2.1 protocol response. 5 // Parse the data returned from the SafeBrowsing v2.1 protocol response.
6 6
7 #include <stdlib.h> 7 #include <stdlib.h>
8 8
9 #include "base/format_macros.h" 9 #include "base/format_macros.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 26 matching lines...) Expand all
37 37
38 //------------------------------------------------------------------------------ 38 //------------------------------------------------------------------------------
39 // SafeBrowsingParser implementation 39 // SafeBrowsingParser implementation
40 40
41 SafeBrowsingProtocolParser::SafeBrowsingProtocolParser() { 41 SafeBrowsingProtocolParser::SafeBrowsingProtocolParser() {
42 } 42 }
43 43
44 bool SafeBrowsingProtocolParser::ParseGetHash( 44 bool SafeBrowsingProtocolParser::ParseGetHash(
45 const char* chunk_data, 45 const char* chunk_data,
46 int chunk_len, 46 int chunk_len,
47 const std::string& key,
48 bool* re_key,
49 std::vector<SBFullHashResult>* full_hashes) { 47 std::vector<SBFullHashResult>* full_hashes) {
50 full_hashes->clear(); 48 full_hashes->clear();
51 int length = chunk_len; 49 int length = chunk_len;
52 const char* data = chunk_data; 50 const char* data = chunk_data;
53 51
54 int offset; 52 int offset;
55 std::string line; 53 std::string line;
56 if (!key.empty()) {
57 if (!GetLine(data, length, &line))
58 return false; // Error! Bad GetHash result.
59
60 if (line == "e:pleaserekey") {
61 *re_key = true;
62 return true;
63 }
64
65 offset = static_cast<int>(line.size()) + 1;
66 data += offset;
67 length -= offset;
68
69 if (!safe_browsing_util::VerifyMAC(key, line, data, length))
70 return false;
71 }
72
73 while (length > 0) { 54 while (length > 0) {
74 if (!GetLine(data, length, &line)) 55 if (!GetLine(data, length, &line))
75 return false; 56 return false;
76 57
77 offset = static_cast<int>(line.size()) + 1; 58 offset = static_cast<int>(line.size()) + 1;
78 data += offset; 59 data += offset;
79 length -= offset; 60 length -= offset;
80 61
81 std::vector<std::string> cmd_parts; 62 std::vector<std::string> cmd_parts;
82 base::SplitString(line, ':', &cmd_parts); 63 base::SplitString(line, ':', &cmd_parts);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 sizeof(SBPrefix) * prefixes.size())); 99 sizeof(SBPrefix) * prefixes.size()));
119 for (size_t i = 0; i < prefixes.size(); ++i) { 100 for (size_t i = 0; i < prefixes.size(); ++i) {
120 request->append(reinterpret_cast<const char*>(&prefixes[i]), 101 request->append(reinterpret_cast<const char*>(&prefixes[i]),
121 sizeof(SBPrefix)); 102 sizeof(SBPrefix));
122 } 103 }
123 } 104 }
124 105
125 bool SafeBrowsingProtocolParser::ParseUpdate( 106 bool SafeBrowsingProtocolParser::ParseUpdate(
126 const char* chunk_data, 107 const char* chunk_data,
127 int chunk_len, 108 int chunk_len,
128 const std::string& key,
129 int* next_update_sec, 109 int* next_update_sec,
130 bool* re_key,
131 bool* reset, 110 bool* reset,
132 std::vector<SBChunkDelete>* deletes, 111 std::vector<SBChunkDelete>* deletes,
133 std::vector<ChunkUrl>* chunk_urls) { 112 std::vector<ChunkUrl>* chunk_urls) {
134 DCHECK(next_update_sec); 113 DCHECK(next_update_sec);
135 DCHECK(deletes); 114 DCHECK(deletes);
136 DCHECK(chunk_urls); 115 DCHECK(chunk_urls);
137 116
138 int length = chunk_len; 117 int length = chunk_len;
139 const char* data = chunk_data; 118 const char* data = chunk_data;
140 119
141 // Populated below. 120 // Populated below.
142 std::string list_name; 121 std::string list_name;
143 122
144 // If we requested the MAC, the response must start with a MAC command.
145 // This test ensures it is present, the value will be verified in the
146 // switch statement below.
147 if (!key.empty() && (length < 1 || data[0] != 'm'))
148 return false;
149
150 while (length > 0) { 123 while (length > 0) {
151 std::string cmd_line; 124 std::string cmd_line;
152 if (!GetLine(data, length, &cmd_line)) 125 if (!GetLine(data, length, &cmd_line))
153 return false; // Error: bad list format! 126 return false; // Error: bad list format!
154 127
155 std::vector<std::string> cmd_parts; 128 std::vector<std::string> cmd_parts;
156 base::SplitString(cmd_line, ':', &cmd_parts); 129 base::SplitString(cmd_line, ':', &cmd_parts);
157 if (cmd_parts.empty()) 130 if (cmd_parts.empty())
158 return false; 131 return false;
159 const std::string& command = cmd_parts[0]; 132 const std::string& command = cmd_parts[0];
(...skipping 17 matching lines...) Expand all
177 if (command.size() != 2 || command[1] != 'd' || list_name.empty()) 150 if (command.size() != 2 || command[1] != 'd' || list_name.empty())
178 return false; 151 return false;
179 SBChunkDelete chunk_delete; 152 SBChunkDelete chunk_delete;
180 chunk_delete.is_sub_del = command[0] == 's'; 153 chunk_delete.is_sub_del = command[0] == 's';
181 StringToRanges(cmd_parts[1], &chunk_delete.chunk_del); 154 StringToRanges(cmd_parts[1], &chunk_delete.chunk_del);
182 chunk_delete.list_name = list_name; 155 chunk_delete.list_name = list_name;
183 deletes->push_back(chunk_delete); 156 deletes->push_back(chunk_delete);
184 break; 157 break;
185 } 158 }
186 159
187 case 'e':
188 if (cmd_parts[1] != "pleaserekey")
189 return false;
190 *re_key = true;
191 break;
192
193 case 'i': 160 case 'i':
194 // The line providing the name of the list (i.e. 'goog-phish-shavar'). 161 // The line providing the name of the list (i.e. 'goog-phish-shavar').
195 list_name = cmd_parts[1]; 162 list_name = cmd_parts[1];
196 break; 163 break;
197 164
198 case 'm':
199 // Verify that the MAC of the remainer of this chunk is what we expect.
200 if (!key.empty() &&
201 !safe_browsing_util::VerifyMAC(key, cmd_parts[1], data, length))
202 return false;
203 break;
204
205 case 'n': 165 case 'n':
206 // The line providing the next earliest time (in seconds) to re-query. 166 // The line providing the next earliest time (in seconds) to re-query.
207 *next_update_sec = atoi(cmd_parts[1].c_str()); 167 *next_update_sec = atoi(cmd_parts[1].c_str());
208 break; 168 break;
209 169
210 case 'u': { 170 case 'u': {
211 // The redirect command is of the form: u:<url>,<mac> where <url> can
212 // contain multiple colons, commas or any valid URL characters. We scan
213 // backwards in the string looking for the first ',' we encounter and
214 // assume that everything before that is the URL and everything after
215 // is the MAC (if the MAC was requested).
216 std::string mac;
217 std::string redirect_url(cmd_line, 2); // Skip the initial "u:".
218 if (!key.empty()) {
219 std::string::size_type mac_pos = redirect_url.rfind(',');
220 if (mac_pos == std::string::npos)
221 return false;
222 mac = redirect_url.substr(mac_pos + 1);
223 redirect_url = redirect_url.substr(0, mac_pos);
224 }
225
226 ChunkUrl chunk_url; 171 ChunkUrl chunk_url;
227 chunk_url.url = redirect_url; 172 chunk_url.url = cmd_line.substr(2); // Skip the initial "u:".
228 chunk_url.list_name = list_name; 173 chunk_url.list_name = list_name;
229 if (!key.empty())
230 chunk_url.mac = mac;
231 chunk_urls->push_back(chunk_url); 174 chunk_urls->push_back(chunk_url);
232 break; 175 break;
233 } 176 }
234 177
235 case 'r': 178 case 'r':
236 if (cmd_parts[1] != "pleasereset") 179 if (cmd_parts[1] != "pleasereset")
237 return false; 180 return false;
238 *reset = true; 181 *reset = true;
239 break; 182 break;
240 183
241 default: 184 default:
242 // According to the spec, we ignore commands we don't understand. 185 // According to the spec, we ignore commands we don't understand.
243 break; 186 break;
244 } 187 }
245 } 188 }
246 189
247 return true; 190 return true;
248 } 191 }
249 192
250 bool SafeBrowsingProtocolParser::ParseChunk(const std::string& list_name, 193 bool SafeBrowsingProtocolParser::ParseChunk(const std::string& list_name,
251 const char* data, 194 const char* data,
252 int length, 195 int length,
253 const std::string& key,
254 const std::string& mac,
255 bool* re_key,
256 SBChunkList* chunks) { 196 SBChunkList* chunks) {
257 int remaining = length; 197 int remaining = length;
258 const char* chunk_data = data; 198 const char* chunk_data = data;
259 199
260 if (!key.empty() &&
261 !safe_browsing_util::VerifyMAC(key, mac, data, length)) {
262 return false;
263 }
264
265 while (remaining > 0) { 200 while (remaining > 0) {
266 std::string cmd_line; 201 std::string cmd_line;
267 if (!GetLine(chunk_data, length, &cmd_line)) 202 if (!GetLine(chunk_data, length, &cmd_line))
268 return false; // Error: bad chunk format! 203 return false; // Error: bad chunk format!
269 204
270 const int line_len = static_cast<int>(cmd_line.length()) + 1; 205 const int line_len = static_cast<int>(cmd_line.length()) + 1;
271 chunk_data += line_len; 206 chunk_data += line_len;
272 remaining -= line_len; 207 remaining -= line_len;
273 std::vector<std::string> cmd_parts; 208 std::vector<std::string> cmd_parts;
274 base::SplitString(cmd_line, ':', &cmd_parts); 209 base::SplitString(cmd_line, ':', &cmd_parts);
275
276 // Handle a possible re-key command.
277 if (cmd_parts.size() != 4) { 210 if (cmd_parts.size() != 4) {
278 if (cmd_parts.size() == 2 &&
279 cmd_parts[0] == "e" &&
280 cmd_parts[1] == "pleaserekey") {
281 *re_key = true;
282 continue;
283 }
284 return false; 211 return false;
285 } 212 }
286 213
287 // Process the chunk data. 214 // Process the chunk data.
288 const int chunk_number = atoi(cmd_parts[1].c_str()); 215 const int chunk_number = atoi(cmd_parts[1].c_str());
289 const int hash_len = atoi(cmd_parts[2].c_str()); 216 const int hash_len = atoi(cmd_parts[2].c_str());
290 if (hash_len != sizeof(SBPrefix) && hash_len != sizeof(SBFullHash)) { 217 if (hash_len != sizeof(SBPrefix) && hash_len != sizeof(SBFullHash)) {
291 VLOG(1) << "ParseChunk got unknown hashlen " << hash_len; 218 VLOG(1) << "ParseChunk got unknown hashlen " << hash_len;
292 return false; 219 return false;
293 } 220 }
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 DCHECK_EQ(hash_len, (int)sizeof(SBFullHash)); 405 DCHECK_EQ(hash_len, (int)sizeof(SBFullHash));
479 entry->SetFullHashAt(i, *reinterpret_cast<const SBFullHash*>(*data)); 406 entry->SetFullHashAt(i, *reinterpret_cast<const SBFullHash*>(*data));
480 } 407 }
481 *data += hash_len; 408 *data += hash_len;
482 *remaining -= hash_len; 409 *remaining -= hash_len;
483 DCHECK_GE(*remaining, 0); 410 DCHECK_GE(*remaining, 0);
484 } 411 }
485 412
486 return true; 413 return true;
487 } 414 }
488
489 bool SafeBrowsingProtocolParser::ParseNewKey(const char* chunk_data,
490 int chunk_length,
491 std::string* client_key,
492 std::string* wrapped_key) {
493 DCHECK(client_key && wrapped_key);
494 client_key->clear();
495 wrapped_key->clear();
496
497 const char* data = chunk_data;
498 int remaining = chunk_length;
499
500 while (remaining > 0) {
501 std::string line;
502 if (!GetLine(data, remaining, &line))
503 return false;
504
505 std::vector<std::string> cmd_parts;
506 base::SplitString(line, ':', &cmd_parts);
507 if (cmd_parts.size() != 3)
508 return false;
509
510 if (static_cast<int>(cmd_parts[2].size()) != atoi(cmd_parts[1].c_str()))
511 return false;
512
513 if (cmd_parts[0] == "clientkey") {
514 client_key->assign(cmd_parts[2]);
515 } else if (cmd_parts[0] == "wrappedkey") {
516 wrapped_key->assign(cmd_parts[2]);
517 } else {
518 return false;
519 }
520
521 data += line.size() + 1;
522 remaining -= static_cast<int>(line.size()) + 1;
523 }
524
525 if (client_key->empty() || wrapped_key->empty())
526 return false;
527
528 return true;
529 }
OLDNEW
« no previous file with comments | « chrome/browser/safe_browsing/protocol_parser.h ('k') | chrome/browser/safe_browsing/protocol_parser_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698