13345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Parse the data returned from the SafeBrowsing v2.1 protocol response. 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include <stdlib.h> 872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/safe_browsing/protocol_parser.h" 1072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/safe_browsing/safe_browsing_util.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "build/build_config.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <Winsock2.h> 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(OS_POSIX) 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <arpa/inet.h> 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/format_macros.h" 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h" 223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_split.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h" 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Helper function for quick scans of a line oriented protocol. Note that we use 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// std::string::assign(const charT* s, size_type n) 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// to copy data into 'line'. This form of 'assign' does not call strlen on 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 'input', which is binary data and is not NULL terminated. 'input' may also 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// contain valid NULL bytes in the payload, which a strlen based copy would 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// truncate. 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GetLine(const char* input, int input_len, std::string* line) { 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* pos = input; 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (pos && (pos - input < input_len)) { 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (*pos == '\n') { 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch line->assign(input, pos - input); 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++pos; 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------ 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// SafeBrowsingParser implementation 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSafeBrowsingProtocolParser::SafeBrowsingProtocolParser() { 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SafeBrowsingProtocolParser::ParseGetHash( 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* chunk_data, 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int chunk_len, 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& key, 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool* re_key, 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<SBFullHashResult>* full_hashes) { 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch full_hashes->clear(); 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int length = chunk_len; 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* data = chunk_data; 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int offset; 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string line; 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!key.empty()) { 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!GetLine(data, length, &line)) 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; // Error! Bad GetHash result. 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (line == "e:pleaserekey") { 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *re_key = true; 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch offset = static_cast<int>(line.size()) + 1; 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data += offset; 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch length -= offset; 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!safe_browsing_util::VerifyMAC(key, line, data, length)) 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (length > 0) { 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!GetLine(data, length, &line)) 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch offset = static_cast<int>(line.size()) + 1; 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data += offset; 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch length -= offset; 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<std::string> cmd_parts; 89731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick base::SplitString(line, ':', &cmd_parts); 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (cmd_parts.size() != 3) 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SBFullHashResult full_hash; 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch full_hash.list_name = cmd_parts[0]; 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch full_hash.add_chunk_id = atoi(cmd_parts[1].c_str()); 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int full_hash_len = atoi(cmd_parts[2].c_str()); 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Ignore hash results from lists we don't recognize. 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (safe_browsing_util::GetListId(full_hash.list_name) < 0) { 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data += full_hash_len; 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch length -= full_hash_len; 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (full_hash_len > 0) { 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(static_cast<size_t>(full_hash_len) >= sizeof(SBFullHash)); 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(&full_hash.hash, data, sizeof(SBFullHash)); 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch full_hashes->push_back(full_hash); 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data += sizeof(SBFullHash); 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch length -= sizeof(SBFullHash); 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch full_hash_len -= sizeof(SBFullHash); 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return length == 0; 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingProtocolParser::FormatGetHash( 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::vector<SBPrefix>& prefixes, std::string* request) { 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(request); 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Format the request for GetHash. 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->append(StringPrintf("%" PRIuS ":%" PRIuS "\n", 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sizeof(SBPrefix), 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sizeof(SBPrefix) * prefixes.size())); 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < prefixes.size(); ++i) { 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request->append(reinterpret_cast<const char*>(&prefixes[i]), 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sizeof(SBPrefix)); 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SafeBrowsingProtocolParser::ParseUpdate( 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* chunk_data, 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int chunk_len, 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& key, 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int* next_update_sec, 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool* re_key, 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool* reset, 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<SBChunkDelete>* deletes, 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<ChunkUrl>* chunk_urls) { 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(next_update_sec); 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(deletes); 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(chunk_urls); 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int length = chunk_len; 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* data = chunk_data; 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Populated below. 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string list_name; 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (length > 0) { 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string cmd_line; 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!GetLine(data, length, &cmd_line)) 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; // Error: bad list format! 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<std::string> cmd_parts; 157731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick base::SplitString(cmd_line, ':', &cmd_parts); 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (cmd_parts.empty()) 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& command = cmd_parts[0]; 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (cmd_parts.size() != 2 && command[0] != 'u') 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int consumed = static_cast<int>(cmd_line.size()) + 1; 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data += consumed; 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch length -= consumed; 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (length < 0) 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; // Parsing error. 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Differentiate on the first character of the command (which is usually 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // only one character, with the exception of the 'ad' and 'sd' commands). 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (command[0]) { 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case 'a': 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case 's': { 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Must be either an 'ad' (add-del) or 'sd' (sub-del) chunk. We must 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // have also parsed the list name before getting here, or the add-del 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // or sub-del will have no context. 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (command.size() != 2 || command[1] != 'd' || list_name.empty()) 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SBChunkDelete chunk_delete; 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chunk_delete.is_sub_del = command[0] == 's'; 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StringToRanges(cmd_parts[1], &chunk_delete.chunk_del); 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chunk_delete.list_name = list_name; 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch deletes->push_back(chunk_delete); 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case 'e': 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (cmd_parts[1] != "pleaserekey") 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *re_key = true; 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case 'i': 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The line providing the name of the list (i.e. 'goog-phish-shavar'). 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch list_name = cmd_parts[1]; 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case 'm': 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Verify that the MAC of the remainer of this chunk is what we expect. 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!key.empty() && 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !safe_browsing_util::VerifyMAC(key, cmd_parts[1], data, length)) 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case 'n': 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The line providing the next earliest time (in seconds) to re-query. 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *next_update_sec = atoi(cmd_parts[1].c_str()); 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case 'u': { 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The redirect command is of the form: u:<url>,<mac> where <url> can 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // contain multiple colons, commas or any valid URL characters. We scan 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // backwards in the string looking for the first ',' we encounter and 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // assume that everything before that is the URL and everything after 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // is the MAC (if the MAC was requested). 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string mac; 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string redirect_url(cmd_line, 2); // Skip the initial "u:". 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!key.empty()) { 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string::size_type mac_pos = redirect_url.rfind(','); 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (mac_pos == std::string::npos) 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mac = redirect_url.substr(mac_pos + 1); 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch redirect_url = redirect_url.substr(0, mac_pos); 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ChunkUrl chunk_url; 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chunk_url.url = redirect_url; 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chunk_url.list_name = list_name; 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!key.empty()) 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chunk_url.mac = mac; 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chunk_urls->push_back(chunk_url); 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case 'r': 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (cmd_parts[1] != "pleasereset") 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *reset = true; 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // According to the spec, we ignore commands we don't understand. 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 25172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool SafeBrowsingProtocolParser::ParseChunk(const std::string& list_name, 25272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const char* data, 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int length, 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& key, 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& mac, 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool* re_key, 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SBChunkList* chunks) { 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int remaining = length; 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* chunk_data = data; 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!key.empty() && 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !safe_browsing_util::VerifyMAC(key, mac, data, length)) { 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (remaining > 0) { 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string cmd_line; 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!GetLine(chunk_data, length, &cmd_line)) 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; // Error: bad chunk format! 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int line_len = static_cast<int>(cmd_line.length()) + 1; 27272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen chunk_data += line_len; 27372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen remaining -= line_len; 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<std::string> cmd_parts; 275731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick base::SplitString(cmd_line, ':', &cmd_parts); 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Handle a possible re-key command. 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (cmd_parts.size() != 4) { 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (cmd_parts.size() == 2 && 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cmd_parts[0] == "e" && 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cmd_parts[1] == "pleaserekey") { 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *re_key = true; 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Process the chunk data. 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int chunk_number = atoi(cmd_parts[1].c_str()); 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int hash_len = atoi(cmd_parts[2].c_str()); 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (hash_len != sizeof(SBPrefix) && hash_len != sizeof(SBFullHash)) { 292513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch VLOG(1) << "ParseChunk got unknown hashlen " << hash_len; 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int chunk_len = atoi(cmd_parts[3].c_str()); 29772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 29872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (remaining < chunk_len) 29972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; // parse error. 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chunks->push_back(SBChunk()); 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chunks->back().chunk_number = chunk_number; 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (cmd_parts[0] == "a") { 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chunks->back().is_add = true; 30672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!ParseAddChunk(list_name, chunk_data, chunk_len, hash_len, 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &chunks->back().hosts)) 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; // Parse error. 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (cmd_parts[0] == "s") { 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chunks->back().is_add = false; 31172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!ParseSubChunk(list_name, chunk_data, chunk_len, hash_len, 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &chunks->back().hosts)) 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; // Parse error. 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chunk_data += chunk_len; 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch remaining -= chunk_len; 32172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK_LE(0, remaining); 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(remaining == 0); 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 32972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool SafeBrowsingProtocolParser::ParseAddChunk(const std::string& list_name, 33072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const char* data, 33172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int data_len, 33272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int hash_len, 33372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::deque<SBChunkHost>* hosts) { 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* chunk_data = data; 33572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int remaining = data_len; 33672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int prefix_count; 33772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SBEntry::Type type = hash_len == sizeof(SBPrefix) ? 33872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SBEntry::ADD_PREFIX : SBEntry::ADD_FULL_HASH; 33972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 34072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (list_name == safe_browsing_util::kBinHashList) { 34172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // kBinHashList only contains prefixes, no HOSTKEY and COUNT. 34272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK_EQ(0, remaining % hash_len); 34372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen prefix_count = remaining / hash_len; 34472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SBChunkHost chunk_host; 34572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen chunk_host.host = 0; 34672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen chunk_host.entry = SBEntry::Create(type, prefix_count); 34772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen hosts->push_back(chunk_host); 34872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!ReadPrefixes(&chunk_data, &remaining, chunk_host.entry, prefix_count)) 34972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 35072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SBPrefix host; 35272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const int min_size = sizeof(SBPrefix) + 1; 35372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen while (remaining >= min_size) { 35472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ReadHostAndPrefixCount(&chunk_data, &remaining, &host, &prefix_count); 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SBChunkHost chunk_host; 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chunk_host.host = host; 35772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen chunk_host.entry = SBEntry::Create(type, prefix_count); 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hosts->push_back(chunk_host); 35972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!ReadPrefixes(&chunk_data, &remaining, chunk_host.entry, 36072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen prefix_count)) 36172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return remaining == 0; 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 36772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool SafeBrowsingProtocolParser::ParseSubChunk(const std::string& list_name, 36872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const char* data, 36972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int data_len, 37072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int hash_len, 37172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::deque<SBChunkHost>* hosts) { 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int remaining = data_len; 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* chunk_data = data; 37472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int prefix_count; 37572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SBEntry::Type type = hash_len == sizeof(SBPrefix) ? 37672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SBEntry::SUB_PREFIX : SBEntry::SUB_FULL_HASH; 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 37872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (list_name == safe_browsing_util::kBinHashList) { 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SBChunkHost chunk_host; 38072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Set host to 0 and it won't be used for kBinHashList. 38172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen chunk_host.host = 0; 38272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // kBinHashList only contains (add_chunk_number, prefix) pairs, no HOSTKEY 38372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // and COUNT. |add_chunk_number| is int32. 38472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen prefix_count = remaining / (sizeof(int32) + hash_len); 38572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen chunk_host.entry = SBEntry::Create(type, prefix_count); 38672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!ReadPrefixes(&chunk_data, &remaining, chunk_host.entry, prefix_count)) 38772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hosts->push_back(chunk_host); 38972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 39072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SBPrefix host; 39172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const int min_size = 2 * sizeof(SBPrefix) + 1; 39272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen while (remaining >= min_size) { 39372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ReadHostAndPrefixCount(&chunk_data, &remaining, &host, &prefix_count); 39472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SBChunkHost chunk_host; 39572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen chunk_host.host = host; 39672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen chunk_host.entry = SBEntry::Create(type, prefix_count); 39772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen hosts->push_back(chunk_host); 39872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (prefix_count == 0) { 39972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // There is only an add chunk number (no prefixes). 40072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen chunk_host.entry->set_chunk_id(ReadChunkId(&chunk_data, &remaining)); 40172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen continue; 40272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 40372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!ReadPrefixes(&chunk_data, &remaining, chunk_host.entry, 40472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen prefix_count)) 40572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return remaining == 0; 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SafeBrowsingProtocolParser::ReadHostAndPrefixCount( 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char** data, int* remaining, SBPrefix* host, int* count) { 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Next 4 bytes are the host prefix. 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(host, *data, sizeof(SBPrefix)); 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *data += sizeof(SBPrefix); 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *remaining -= sizeof(SBPrefix); 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Next 1 byte is the prefix count (could be zero, but never negative). 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *count = static_cast<unsigned char>(**data); 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *data += 1; 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *remaining -= 1; 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint SafeBrowsingProtocolParser::ReadChunkId( 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char** data, int* remaining) { 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int chunk_number; 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(&chunk_number, *data, sizeof(chunk_number)); 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *data += sizeof(chunk_number); 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *remaining -= sizeof(chunk_number); 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return htonl(chunk_number); 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SafeBrowsingProtocolParser::ReadPrefixes( 43472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const char** data, int* remaining, SBEntry* entry, int count) { 435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int hash_len = entry->HashLen(); 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < count; ++i) { 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (entry->IsSub()) { 43872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen entry->SetChunkIdAtPrefix(i, ReadChunkId(data, remaining)); 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (*remaining <= 0) 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (entry->IsPrefix()) { 44472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen entry->SetPrefixAt(i, *reinterpret_cast<const SBPrefix*>(*data)); 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 44672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen entry->SetFullHashAt(i, *reinterpret_cast<const SBFullHash*>(*data)); 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *data += hash_len; 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *remaining -= hash_len; 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (*remaining < 0) 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SafeBrowsingProtocolParser::ParseNewKey(const char* chunk_data, 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int chunk_length, 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string* client_key, 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string* wrapped_key) { 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(client_key && wrapped_key); 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch client_key->clear(); 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch wrapped_key->clear(); 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* data = chunk_data; 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int remaining = chunk_length; 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (remaining > 0) { 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string line; 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!GetLine(data, remaining, &line)) 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<std::string> cmd_parts; 474731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick base::SplitString(line, ':', &cmd_parts); 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (cmd_parts.size() != 3) 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (static_cast<int>(cmd_parts[2].size()) != atoi(cmd_parts[1].c_str())) 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (cmd_parts[0] == "clientkey") { 482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch client_key->assign(cmd_parts[2]); 483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (cmd_parts[0] == "wrappedkey") { 484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch wrapped_key->assign(cmd_parts[2]); 485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data += line.size() + 1; 490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch remaining -= static_cast<int>(line.size()) + 1; 491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (client_key->empty() || wrapped_key->empty()) 494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 498