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