Index: components/data_reduction_proxy/browser/data_reduction_proxy_tamper_detection.h |
diff --git a/components/data_reduction_proxy/browser/data_reduction_proxy_tamper_detection.h b/components/data_reduction_proxy/browser/data_reduction_proxy_tamper_detection.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b4021fcc8c025c83bbfccfb99a7a7ec7edfadef7 |
--- /dev/null |
+++ b/components/data_reduction_proxy/browser/data_reduction_proxy_tamper_detection.h |
@@ -0,0 +1,155 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+// This file implements the tamper detection logic, which detects whether |
+// there are middleboxes and whether they are tampering with the response |
+// which may break correct communication and data transfer between the Chromium |
+// client and the data reduction proxy. |
+// |
+// At a high level, the tamper detection process works in two steps: |
+// 1. The data reduction proxy selects a fraction of responses to analyze, |
+// generates a series of fingerprints for each, and appends them to the |
+// Chrome-Proxy response headers; |
+// 2. The client re-generate the fingerprints using the same method as the |
+// proxy, compares them to the fingerprints in the response, and generates |
+// UMA. A response is considered to have been tampered with if the |
+// fingerprints do not match. |
+// |
+// Four fingerprints are generated by the data reduction proxy: |
+// 1. Fingerprint of the Chrome-Proxy header, which is designed to check |
+// whether the Chrome-Proxy header has been modified or not; |
+// 2. Fingerprint of the Via header, which is designed to check whether there |
+// are middleboxes between the Chromium client and the data reduction proxy; |
+// 3. Fingerprint of a list of headers, which is designed to check whether the |
+// values of a list of headers (list is defined by the data reduction proxy) |
+// have been modified or deleted; |
+// 4. Fingerprint of the Content-Length header, which is designed to check |
+// whether the response body has been modified or not (the code assumes that |
+// different Content-Length values indicate different response bodies). |
+// |
+// On the client side, the fingerprint of the Chrome-Proxy header will be |
+// checked first. If the fingerprint indicates that the Chrome-Proxy header has |
+// not been modified, then the other fingerprints will be considered to be |
+// reliable and will be checked next; if not, then it's possible that the other |
+// fingerprints have been tampered with and thus they will not be checked. |
+// If middlebox removes all the fingerprints then such tampering will not be |
+// detected. |
+// |
+// Detected tampering information will be reported to UMA. In general, for each |
+// fingerprint, the client reports the number of responses that have been |
+// tampered with for different carriers. For the fingerprint of the |
+// Content-Length header, which indicates whether the response body has been |
+// modified or not, the reports of tampering are separated by MIME type of the |
+// response body. |
+ |
+#ifndef COMPONENTS_DATA_REDUCTION_PROXY_BROWSER_DATA_REDUCTION_PROXY_TAMPER_DETECTION_H_ |
+#define COMPONENTS_DATA_REDUCTION_PROXY_BROWSER_DATA_REDUCTION_PROXY_TAMPER_DETECTION_H_ |
+ |
+#include <map> |
+#include <string> |
+#include <vector> |
+ |
+#include "net/proxy/proxy_service.h" |
+ |
+namespace net { |
+class HttpResponseHeaders; |
+} |
+ |
+namespace data_reduction_proxy { |
+ |
+// Detects if the response sent by the data reduction proxy has been modified |
+// by intermediaries on the Web. |
+class DataReductionProxyTamperDetection { |
+ public: |
+ // Checks if the response contains tamper detection fingerprints added by the |
+ // data reduction proxy, and determines if the response had been tampered |
+ // with if so. Results are reported to UMA. HTTP and HTTPS traffic are |
+ // reported separately, specified by |scheme_is_https|. Returns true if |
+ // the response has been tampered with. |
+ static bool DetectAndReport(const net::HttpResponseHeaders* headers, |
+ bool scheme_is_https); |
+ |
+ // Tamper detection checks |response_headers|. Histogram events are reported |
+ // by |carrier_id|; |scheme_is_https| determines which histogram to report |
+ // (HTTP and HTTPS are reported separately). |
+ DataReductionProxyTamperDetection( |
+ const net::HttpResponseHeaders* response_headers, |
+ bool scheme_is_https, |
+ unsigned carrier_id); |
+ |
+ virtual ~DataReductionProxyTamperDetection(); |
+ |
+ private: |
+ FRIEND_TEST_ALL_PREFIXES(DataReductionProxyTamperDetectionTest, |
+ TestFingerprintCommon); |
+ FRIEND_TEST_ALL_PREFIXES(DataReductionProxyTamperDetectionTest, |
+ ChromeProxy); |
+ FRIEND_TEST_ALL_PREFIXES(DataReductionProxyTamperDetectionTest, |
+ Via); |
+ FRIEND_TEST_ALL_PREFIXES(DataReductionProxyTamperDetectionTest, |
+ OtherHeaders); |
+ FRIEND_TEST_ALL_PREFIXES(DataReductionProxyTamperDetectionTest, |
+ ContentLength); |
+ FRIEND_TEST_ALL_PREFIXES(DataReductionProxyTamperDetectionTest, |
+ HeaderRemoving); |
+ FRIEND_TEST_ALL_PREFIXES(DataReductionProxyTamperDetectionTest, |
+ ValuesToSortedString); |
+ FRIEND_TEST_ALL_PREFIXES(DataReductionProxyTamperDetectionTest, |
+ GetHeaderValues); |
+ FRIEND_TEST_ALL_PREFIXES(DataReductionProxyTamperDetectionTest, |
+ DetectAndReport); |
+ |
+ // Returns the result of validating Chrome-Proxy header. |
+ bool ValidateChromeProxyHeader(const std::string& fingerprint) const; |
+ |
+ // Reports UMA for tampering of the Chrome-Proxy header. |
+ void ReportUMAforChromeProxyHeaderValidation() const; |
+ |
+ // Returns the result of validating the Via header. |has_chrome_proxy| |
+ // indicates that the data reduction proxy's Via header occurs or not. |
+ bool ValidateViaHeader(const std::string& fingerprint, |
+ bool* has_chrome_proxy_via_header) const; |
+ |
+ // Reports UMA for tampering of the Via header. |
+ void ReportUMAforViaHeaderValidation(bool has_chrome_proxy_via_header) const; |
+ |
+ // Returns the result of validating a list of headers. |
+ bool ValidateOtherHeaders(const std::string& fingerprint) const; |
+ |
+ // Reports UMA for tampering of values of the list of headers. |
+ void ReportUMAforOtherHeadersValidation() const; |
+ |
+ // Returns the result of validating the Content-Length header. |
+ bool ValidateContentLengthHeader(const std::string& fingerprint) const; |
+ |
+ // Reports UMA for tampering of the Content-Length header. |
+ void ReportUMAforContentLengthHeaderValidation() const; |
+ |
+ // Returns a string representation of |values|. |
+ static std::string ValuesToSortedString(std::vector<std::string>* values); |
+ |
+ // Returns raw MD5 hash value for a given string |input|. It is different to |
+ // base::MD5String which is base16 encoded. |
+ static void GetMD5(const std::string& input, std::string* output); |
+ |
+ // Returns all the values of |header_name| of the response |headers| as a |
+ // vector. This function is used for values that need to be sorted later. |
+ static std::vector<std::string> GetHeaderValues( |
+ const net::HttpResponseHeaders* headers, |
+ const std::string& header_name); |
+ |
+ // Pointer to response headers. |
+ const net::HttpResponseHeaders* response_headers_; |
+ |
+ // If true, the connection to the data reduction proxy is over HTTPS; |
+ const bool scheme_is_https_; |
+ |
+ // Carrier ID: the numeric name of the current registered operator. |
+ const unsigned carrier_id_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(DataReductionProxyTamperDetection); |
+}; |
+ |
+} // namespace data_reduction_proxy |
+#endif // COMPONENTS_DATA_REDUCTION_PROXY_BROWSER_DATA_REDUCTION_PROXY_TAMPER_DETECTION_H_ |