OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 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 // This file implements the tamper detection logic, which detects whether |
| 6 // there are middleboxes and whether they are tampering with the response |
| 7 // which maybe break correct communication and data transfer between the |
| 8 // Chromium client and the data reduction proxy. |
| 9 // |
| 10 // A high-level description of the tamper detection process works in two steps: |
| 11 // 1. The data reduction proxy selects a fraction of responses to analyze; |
| 12 // for the selected ones, the data reduction proxy generates a series of |
| 13 // fingerprints for the responses, and appends them to the Chrome-Proxy |
| 14 // header; |
| 15 // 2. At the Chromium client side, when the Chromium client sees such |
| 16 // fingerprints, it uses the same method as the data reduction proxy to |
| 17 // re-generate the fingerprints, and compares them to the fingerprints in |
| 18 // the response, to see if the response has been tampered with and report to |
| 19 // UMA. |
| 20 // |
| 21 // Four fingerprints are generated at the data reduction proxy side: |
| 22 // 1. Fingerprint of the Chrome-Proxy header, which is designed to check |
| 23 // whether the Chrome-Proxy header has been modified or not; |
| 24 // 2. Fingerprint of the Via header, which is designed to check whether there |
| 25 // are middleboxes between the Chromium client and the data reduction proxy; |
| 26 // 3. Fingerprint of a list of headers, which is designed to check whether the |
| 27 // values of a list of headers (list is defined by the data reduction proxy) |
| 28 // have been modified or deleted; |
| 29 // 4. Fingerprint of the Content-Length header, which is designed to check |
| 30 // whether the response body has been modified or not (assume that different |
| 31 // Content-Length value indicates different response body). |
| 32 // |
| 33 // At the Chromium client side, the fingerprint of the Chrome-Proxy header will |
| 34 // be checked first. If the fingerprint indicates that the Chrome-Proxy header |
| 35 // has not been modified, then the other fingerprints will be considered to be |
| 36 // reliable and will be checked next; if not, then it's possible that the other |
| 37 // fingerprints have been tampered with and thus they will not be checked. |
| 38 // |
| 39 // Detected tampering information will be reported to UMA. In general, for each |
| 40 // fingerprint, the Chromium client reports the number of responses that have |
| 41 // been tampered with for different carriers. For the fingerprint of the |
| 42 // Content-Length header, which indicates whether the response body has been |
| 43 // modified or not, the reports of tampering are separated by MIME type of the |
| 44 // response body. |
| 45 |
| 46 #ifndef COMPONENTS_DATA_REDUCTION_PROXY_BROWSER_DATA_REDUCTION_PROXY_TAMPER_DETE
CTION_H_ |
| 47 #define COMPONENTS_DATA_REDUCTION_PROXY_BROWSER_DATA_REDUCTION_PROXY_TAMPER_DETE
CTION_H_ |
| 48 |
| 49 #include <map> |
| 50 #include <string> |
| 51 #include <vector> |
| 52 |
| 53 #include "net/proxy/proxy_service.h" |
| 54 |
| 55 namespace net { |
| 56 class HttpResponseHeaders; |
| 57 } |
| 58 |
| 59 namespace data_reduction_proxy { |
| 60 |
| 61 // This class detects if the response sent by the data reduction proxy has been |
| 62 // modified by the intermediaries on the Web. |
| 63 class DataReductionProxyTamperDetection { |
| 64 public: |
| 65 // Checks if the response contains tamper detection fingerprints added by the |
| 66 // data reduction proxy, and determines if the response had been tampered |
| 67 // with if so. Results are reported to UMA. HTTP and HTTPS traffic are |
| 68 // reported separately, specified by |is_secure_scheme|. |
| 69 static void DetectAndReport(const net::HttpResponseHeaders* header, |
| 70 bool is_secure_scheme); |
| 71 |
| 72 // Tamper detection checks |response_headers|. Histogram events are reported |
| 73 // by |carrier_id|; |is_secure_scheme| determines which histogram to report |
| 74 // (HTTP and HTTPS are reported separately). |chrome_proxy_header_values| |
| 75 // points to the vector contains the values of the Chrome-Proxy header, but |
| 76 // with the Chrome-Proxy header's fingerprint removed, which is a temporary |
| 77 // result saved to use later to avoid parsing the header again. |
| 78 DataReductionProxyTamperDetection( |
| 79 const net::HttpResponseHeaders* response_headers, |
| 80 bool is_secure_scheme, |
| 81 unsigned carrier_id, |
| 82 std::vector<std::string>* chrome_proxy_header_values); |
| 83 |
| 84 virtual ~DataReductionProxyTamperDetection(); |
| 85 |
| 86 private: |
| 87 friend class DataReductionProxyTamperDetectionTest; |
| 88 FRIEND_TEST_ALL_PREFIXES(DataReductionProxyTamperDetectionTest, |
| 89 TestFingerprintCommon); |
| 90 FRIEND_TEST_ALL_PREFIXES(DataReductionProxyTamperDetectionTest, |
| 91 ChromeProxy); |
| 92 FRIEND_TEST_ALL_PREFIXES(DataReductionProxyTamperDetectionTest, |
| 93 Via); |
| 94 FRIEND_TEST_ALL_PREFIXES(DataReductionProxyTamperDetectionTest, |
| 95 OtherHeaders); |
| 96 FRIEND_TEST_ALL_PREFIXES(DataReductionProxyTamperDetectionTest, |
| 97 ContentLength); |
| 98 FRIEND_TEST_ALL_PREFIXES(DataReductionProxyTamperDetectionTest, |
| 99 HeaderRemoving); |
| 100 FRIEND_TEST_ALL_PREFIXES(DataReductionProxyTamperDetectionTest, |
| 101 ValuesToSortedString); |
| 102 FRIEND_TEST_ALL_PREFIXES(DataReductionProxyTamperDetectionTest, |
| 103 GetHeaderValues); |
| 104 FRIEND_TEST_ALL_PREFIXES(DataReductionProxyTamperDetectionTest, |
| 105 Completed); |
| 106 |
| 107 // Enum for fingerprint type. |
| 108 enum FingerprintCode { |
| 109 CHROMEPROXY = 1, /* Code of fingerprint of the Chrome-Proxy header */ |
| 110 VIA = 2, /* Code of fingerprint of the Via header */ |
| 111 OTHERHEADERS = 3, /* Code of fingerprint of a list of headers */ |
| 112 CONTENTLENGTH = 4, /* Code of fingerprint of the Content-Length header */ |
| 113 NONEXIST = 5, |
| 114 }; |
| 115 |
| 116 // Returns true if the Chrome-Proxy header has been tampered with. |
| 117 bool IsChromeProxyHeaderTampered(const std::string& fingerprint) const; |
| 118 // Reports UMA for tampering of the Chrome-Proxy header. |
| 119 void ReportChromeProxyHeaderTamperedUMA() const; |
| 120 |
| 121 // Returns true if the Via header has been tampered with. |has_chrome_proxy| |
| 122 // indicates that the data reduction proxy's Via header occurs or not. |
| 123 bool IsViaHeaderTampered(const std::string& fingerprint, |
| 124 bool* has_chrome_proxy_via_header) const; |
| 125 // Reports UMA for tampering of the Via header. |
| 126 void ReportViaHeaderTamperedUMA(bool has_chrome_proxy_via_header) const; |
| 127 |
| 128 // Returns true if a list of headers have been tampered with. |
| 129 bool AreOtherHeadersTampered(const std::string& fingerprint) const; |
| 130 // Reports UMA for tampering of values of the list of headers. |
| 131 void ReportOtherHeadersTamperedUMA() const; |
| 132 |
| 133 // Returns true if the Content-Length header has been tampered with. |
| 134 bool IsContentLengthHeaderTampered(const std::string& fingerprint) const; |
| 135 // Reports UMA for tampering of the Content-Length header. |
| 136 void ReportContentLengthHeaderTamperedUMA() const; |
| 137 |
| 138 // Returns the fingerprint code (enum) for the given fingerprint name. |
| 139 FingerprintCode GetFingerprintCode(const std::string& fingerprint_name); |
| 140 |
| 141 // Removes the fingerprint of the Chrome-Proxy header from the Chrome-Proxy |
| 142 // header's |values| vector. The data reduction proxy calculates the |
| 143 // fingerprint for the Chrome-Proxy header and then appends calculated |
| 144 // fingerprint to the Chrome-Proxy header, so at the Chromium client side, |
| 145 // to re-generate the fingerprint, the Chrome-Proxy header's fingerprint value |
| 146 // needs to be removed from the Chrome-Proxy header first. |
| 147 static void RemoveChromeProxyFingerprint(std::vector<std::string>* values); |
| 148 |
| 149 // Returns a string representation of |values|. |
| 150 static std::string ValuesToSortedString(std::vector<std::string>* values); |
| 151 |
| 152 // Returns raw MD5 hash value for a given string |input|. It is different to |
| 153 // base::MD5String which is base16 encoded. |
| 154 static std::string GetMD5(const std::string& input); |
| 155 |
| 156 // Returns all the values of |header_name| of the response |headers| as a |
| 157 // vector. This function is used for values that need to be sorted later. |
| 158 static std::vector<std::string> GetHeaderValues( |
| 159 const net::HttpResponseHeaders* headers, |
| 160 const std::string& header_name); |
| 161 |
| 162 // Pointer to response headers. |
| 163 const net::HttpResponseHeaders* response_headers_; |
| 164 |
| 165 // If true, the connection to the data reduction proxy is over HTTPS; |
| 166 const bool is_secure_scheme_; |
| 167 |
| 168 // Carrier ID. |
| 169 const unsigned carrier_id_; |
| 170 |
| 171 // Values of the Chrome-Proxy header, with fingerprint of the Chrome-Proxy |
| 172 // header value removed. Save it as a temporary result to avoid parsing the |
| 173 // Chrome-Proxy header again. |
| 174 std::vector<std::string>* clean_chrome_proxy_header_values_; |
| 175 |
| 176 // Maps a fingerprint name (string) to a fingerprint code (enum). |
| 177 std::map<std::string, FingerprintCode> fingerprint_name_code_map_; |
| 178 }; |
| 179 |
| 180 } // namespace data_reduction_proxy |
| 181 #endif // COMPONENTS_DATA_REDUCTION_PROXY_BROWSER_DATA_REDUCTION_PROXY_TAMPER_D
ETECTION_H_ |
OLD | NEW |