1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2006-2008 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#ifndef CHROME_BROWSER_SAFE_BROWSING_PROTOCOL_PARSER_H_ 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define CHROME_BROWSER_SAFE_BROWSING_PROTOCOL_PARSER_H_ 73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Parse the data returned from the chunk response. 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Based on the SafeBrowsing v2.1 protocol: 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// http://code.google.com/p/google-safe-browsing/wiki/Protocolv2Spec 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Read the response from a SafeBrowsing request, and parse into useful pieces. 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The protocol is generally line oriented, but can contain binary data in the 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// actual chunk responses. The consumer of the protocol data should instantiate 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the parser and call the appropriate parsing function on the data. 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Examples of protocol responses: 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 1. List identification 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// i:goog-phish-shavar\n 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// <command>:<command_data>\n 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 2. Minimum time to wait (seconds) until the next download request can be made 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// n:1200\n 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// <command>:<time_in_seconds>\n 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 3. Redirect URL for retrieving a chunk 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// u:cache.googlevideo.com/safebrowsing/rd/goog-phish-shavar_a_1\n 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// <command>:<url>\n 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 4. Add and sub chunks 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// a:1:4:523\n... <-- Add chunk + binary data 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// s:13:4:17\n... <-- Sub chunk + binary data 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// <chunk_type>:<chunk_number>:<prefix_len>:<chunk_bytes>\n<binary_data> 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 5. Add-del and sub-del requests 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ad:1-4000,5001\n <-- Add-del 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// sd:1,3,5,7,903\n <-- Sub-del 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// <command>:<chunk_range>\n 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string> 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector> 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/basictypes.h" 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/safe_browsing/chunk_range.h" 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/safe_browsing/safe_browsing_util.h" 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SafeBrowsingProtocolParser { 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SafeBrowsingProtocolParser(); 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Parse the response of an update request. Results for chunk deletions (both 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // add-del and sub-del are returned in 'chunk_deletes', and new chunk URLs to 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // download are contained in 'chunk_urls'. The next time the client is allowed 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to request another update is returned in 'next_update_sec'. If the service 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // wants us to retrieve new MAC keys, 're_key' will be set to true. If we are 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // using MACs to verify responses, the 'key' must be set to the private key 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // returned from the SafeBrowsing servers. 'reset' will be set to true if the 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // SafeBrowsing service wants us to dump our database. 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Returns 'true'if it was able to decode the chunk properly, 'false' if not 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // decoded properly and the results should be ignored. 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool ParseUpdate(const char* chunk_data, 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int chunk_len, 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& key, 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int* next_update_sec, 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool* re_key, 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool* reset, 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<SBChunkDelete>* chunk_deletes, 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<ChunkUrl>* chunk_urls); 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Parse the response from a chunk URL request and returns the hosts/prefixes 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // for adds and subs in "chunks". Returns 'true' on successful parsing, 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 'false' otherwise. Any result should be ignored when a parse has failed. 7872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool ParseChunk(const std::string& list_name, 7972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const char* chunk_data, 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int chunk_len, 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& key, 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& mac, 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool* re_key, 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SBChunkList* chunks); 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Parse the result of a GetHash request, returning the list of full hashes. 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we are checking for valid MACs, the caller should populate 'key'. 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool ParseGetHash(const char* chunk_data, 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int chunk_len, 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& key, 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool* re_key, 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<SBFullHashResult>* full_hashes); 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Convert a list of partial hashes into a proper GetHash request. 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void FormatGetHash(const std::vector<SBPrefix>& prefixes, 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string* request); 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Parse the keys used for subsequent communications with the SafeBrowsing 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // servers. Returns true on successful parse, false on parse error. 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool ParseNewKey(const char* chunk_data, 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int chunk_length, 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string* client_key, 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string* wrapped_key); 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 10672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool ParseAddChunk(const std::string& list_name, 10772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const char* data, 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int data_len, 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int hash_len, 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::deque<SBChunkHost>* hosts); 11172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool ParseSubChunk(const std::string& list_name, 11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const char* data, 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int data_len, 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int hash_len, 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::deque<SBChunkHost>* hosts); 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Helper functions used by ParseAddChunk and ParseSubChunk. 11872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen static void ReadHostAndPrefixCount(const char** data, 11972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int* remaining, 12072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SBPrefix* host, 12172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int* count); 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static int ReadChunkId(const char** data, int* remaining); 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static bool ReadPrefixes( 12472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const char** data, int* remaining, SBEntry* entry, int count); 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The name of the current list 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string list_name_; 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(SafeBrowsingProtocolParser); 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif // CHROME_BROWSER_SAFE_BROWSING_PROTOCOL_PARSER_H_ 134