16e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 26e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 36e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// found in the LICENSE file. 46e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 56e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/data_reduction_proxy/browser/data_reduction_proxy_tamper_detection.h" 66e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 76e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <algorithm> 86e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <cstring> 96e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/base64.h" 116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/md5.h" 126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/metrics/histogram.h" 136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/metrics/sparse_histogram.h" 146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/strings/string_util.h" 166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/data_reduction_proxy/common/data_reduction_proxy_headers.h" 176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "net/http/http_response_headers.h" 186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "net/http/http_util.h" 196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#if defined(OS_ANDROID) 216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "net/android/network_library.h" 226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#endif 236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Macro for UMA reporting. HTTP response first reports to histogram events 256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// |http_histogram| by |carrier_id|; then reports the total counts to 266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// |http_histogram|_Total. HTTPS response reports to histograms 276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// |https_histogram| and |https_histogram|_Total similarly. 286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#define REPORT_TAMPER_DETECTION_UMA( \ 296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scheme_is_https, https_histogram, http_histogram, carrier_id) \ 306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) do { \ 316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (scheme_is_https) { \ 326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) UMA_HISTOGRAM_SPARSE_SLOWLY(https_histogram, carrier_id); \ 336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) UMA_HISTOGRAM_COUNTS(https_histogram "_Total", 1); \ 346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else { \ 356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) UMA_HISTOGRAM_SPARSE_SLOWLY(http_histogram, carrier_id); \ 366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) UMA_HISTOGRAM_COUNTS(http_histogram "_Total", 1); \ 376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) }\ 386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } while (0) 396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)namespace data_reduction_proxy { 416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// static 436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool DataReductionProxyTamperDetection::DetectAndReport( 446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const net::HttpResponseHeaders* headers, 456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const bool scheme_is_https) { 466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(headers); 476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Abort tamper detection, if the fingerprint of the Chrome-Proxy header is 486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // absent. 496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string chrome_proxy_fingerprint; 506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!GetDataReductionProxyActionFingerprintChromeProxy( 516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) headers, &chrome_proxy_fingerprint)) { 526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return false; 536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Get carrier ID. 566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) unsigned carrier_id = 0; 576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#if defined(OS_ANDROID) 586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::StringToUint(net::android::GetTelephonyNetworkOperator(), &carrier_id); 596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#endif 606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DataReductionProxyTamperDetection tamper_detection( 626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) headers, scheme_is_https, carrier_id); 636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Checks if the Chrome-Proxy header has been tampered with. 656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (tamper_detection.ValidateChromeProxyHeader(chrome_proxy_fingerprint)) { 666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) tamper_detection.ReportUMAforChromeProxyHeaderValidation(); 676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return true; 686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Chrome-Proxy header has not been tampered with, and thus other 716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // fingerprints are valid. Reports the number of responses that other 726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // fingerprints will be checked. 736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) REPORT_TAMPER_DETECTION_UMA( 746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scheme_is_https, 756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "DataReductionProxy.HeaderTamperDetectionHTTPS", 766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "DataReductionProxy.HeaderTamperDetectionHTTP", 776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) carrier_id); 786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) bool tampered = false; 806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string fingerprint; 816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (GetDataReductionProxyActionFingerprintVia(headers, &fingerprint)) { 836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) bool has_chrome_proxy_via_header; 846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (tamper_detection.ValidateViaHeader( 856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) fingerprint, &has_chrome_proxy_via_header)) { 866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) tamper_detection.ReportUMAforViaHeaderValidation( 876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) has_chrome_proxy_via_header); 886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) tampered = true; 896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (GetDataReductionProxyActionFingerprintOtherHeaders( 936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) headers, &fingerprint)) { 946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (tamper_detection.ValidateOtherHeaders(fingerprint)) { 956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) tamper_detection.ReportUMAforOtherHeadersValidation(); 966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) tampered = true; 976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (GetDataReductionProxyActionFingerprintContentLength( 1016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) headers, &fingerprint)) { 1026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (tamper_detection.ValidateContentLengthHeader(fingerprint)) { 1036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) tamper_detection.ReportUMAforContentLengthHeaderValidation(); 1046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) tampered = true; 1056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!tampered) { 1096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) REPORT_TAMPER_DETECTION_UMA( 1106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scheme_is_https, 1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "DataReductionProxy.HeaderTamperDetectionPassHTTPS", 1126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "DataReductionProxy.HeaderTamperDetectionPassHTTP", 1136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) carrier_id); 1146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return tampered; 1176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Constructor initializes the map of fingerprint names to codes. 1206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)DataReductionProxyTamperDetection::DataReductionProxyTamperDetection( 1216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const net::HttpResponseHeaders* headers, 1226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const bool is_secure, 1236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const unsigned carrier_id) 1246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) : response_headers_(headers), 1256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scheme_is_https_(is_secure), 1266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) carrier_id_(carrier_id) { 1276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(headers); 1286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)DataReductionProxyTamperDetection::~DataReductionProxyTamperDetection() {}; 1316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// |fingerprint| is Base64 encoded. Decodes it first. Then calculates the 1336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// fingerprint of received Chrome-Proxy header, and compares the two to see 1346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// whether they are equal or not. 1356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool DataReductionProxyTamperDetection::ValidateChromeProxyHeader( 1366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const std::string& fingerprint) const { 1376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string received_fingerprint; 1386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!base::Base64Decode(fingerprint, &received_fingerprint)) 1396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return true; 1406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Gets the Chrome-Proxy header values with its fingerprint removed. 1426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::vector<std::string> chrome_proxy_header_values; 1436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) GetDataReductionProxyHeaderWithFingerprintRemoved( 1446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) response_headers_, &chrome_proxy_header_values); 1456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Calculates the MD5 hash value of Chrome-Proxy. 1476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string actual_fingerprint; 1486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) GetMD5(ValuesToSortedString(&chrome_proxy_header_values), 1496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) &actual_fingerprint); 1506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return received_fingerprint != actual_fingerprint; 1526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void DataReductionProxyTamperDetection:: 1556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ReportUMAforChromeProxyHeaderValidation() const { 1566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) REPORT_TAMPER_DETECTION_UMA( 1576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scheme_is_https_, 1586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "DataReductionProxy.HeaderTamperedHTTPS_ChromeProxy", 1596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "DataReductionProxy.HeaderTamperedHTTP_ChromeProxy", 1606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) carrier_id_); 1616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Checks whether there are other proxies/middleboxes' named after the data 1646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// reduction proxy's name in Via header. |has_chrome_proxy_via_header| marks 1656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// that whether the data reduction proxy's Via header occurs or not. 1666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool DataReductionProxyTamperDetection::ValidateViaHeader( 1676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const std::string& fingerprint, 1686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) bool* has_chrome_proxy_via_header) const { 1696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) bool has_intermediary; 1706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) *has_chrome_proxy_via_header = HasDataReductionProxyViaHeader( 1716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) response_headers_, 1726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) &has_intermediary); 1736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (*has_chrome_proxy_via_header) 1756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return !has_intermediary; 1766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return true; 1776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void DataReductionProxyTamperDetection::ReportUMAforViaHeaderValidation( 1806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) bool has_chrome_proxy) const { 1816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // The Via header of the data reduction proxy is missing. 1826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!has_chrome_proxy) { 1836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) REPORT_TAMPER_DETECTION_UMA( 1846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scheme_is_https_, 1856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "DataReductionProxy.HeaderTamperedHTTPS_Via_Missing", 1866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "DataReductionProxy.HeaderTamperedHTTP_Via_Missing", 1876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) carrier_id_); 1886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 1896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) REPORT_TAMPER_DETECTION_UMA( 1926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scheme_is_https_, 1936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "DataReductionProxy.HeaderTamperedHTTPS_Via", 1946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "DataReductionProxy.HeaderTamperedHTTP_Via", 1956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) carrier_id_); 1966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// The data reduction proxy constructs a canonical representation of values of 1996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// a list of headers. The fingerprint is constructed as follows: 2006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// 1) for each header, gets the string representation of its values (same as 2016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// ValuesToSortedString); 2026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// 2) concatenates all header's string representations using ";" as a delimiter; 2036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// 3) calculates the MD5 hash value of above concatenated string; 2046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// 4) appends the header names to the fingerprint, with a delimiter "|". 2056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// The constructed fingerprint looks like: 2066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// [hashed_fingerprint]|header_name1|header_namer2:... 2076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// 2086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// To check whether such a fingerprint matches the response that the Chromium 2096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// client receives, the client firstly extracts the header names. For 2106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// each header, gets its string representation (by ValuesToSortedString), 2116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// concatenates them and calculates the MD5 hash value. Compares the hash 2126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// value to the fingerprint received from the data reduction proxy. 2136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool DataReductionProxyTamperDetection::ValidateOtherHeaders( 2146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const std::string& fingerprint) const { 2156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(!fingerprint.empty()); 2166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // According to RFC 2616, "|" is not a valid character in a header name; and 2186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // it is not a valid base64 encoding character, so there is no ambituity in 2196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) //using it as a delimiter. 2206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) net::HttpUtil::ValuesIterator it( 2216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) fingerprint.begin(), fingerprint.end(), '|'); 2226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // The first value is the base64 encoded fingerprint. 2246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string received_fingerprint; 2256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!it.GetNext() || 2266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) !base::Base64Decode(it.value(), &received_fingerprint)) { 2276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) NOTREACHED(); 2286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return true; 2296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string header_values; 2326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // The following values are the header names included in the fingerprint 2336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // calculation. 2346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) while (it.GetNext()) { 2356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Gets values of one header. 2366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::vector<std::string> response_header_values = 2376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) GetHeaderValues(response_headers_, it.value()); 2386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Sorts the values and concatenate them, with delimiter ";". ";" can occur 2396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // in a header value and thus two different sets of header values could map 2406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // to the same string representation. This should be very rare. 2416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // TODO(xingx): find an unambiguous representation. 2426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) header_values += ValuesToSortedString(&response_header_values) + ";"; 2436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Calculates the MD5 hash of the concatenated string. 2466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string actual_fingerprint; 2476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) GetMD5(header_values, &actual_fingerprint); 2486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return received_fingerprint != actual_fingerprint; 2506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 2516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void DataReductionProxyTamperDetection:: 2536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ReportUMAforOtherHeadersValidation() const { 2546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) REPORT_TAMPER_DETECTION_UMA( 2556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scheme_is_https_, 2566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "DataReductionProxy.HeaderTamperedHTTPS_OtherHeaders", 2576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "DataReductionProxy.HeaderTamperedHTTP_OtherHeaders", 2586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) carrier_id_); 2596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 2606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// The Content-Length value will not be reported as different if at either side 2626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// (the data reduction proxy side and the client side), the Content-Length is 2636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// missing or it cannot be decoded as a valid integer. 2646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool DataReductionProxyTamperDetection::ValidateContentLengthHeader( 2656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const std::string& fingerprint) const { 2666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) int received_content_length_fingerprint, actual_content_length; 2676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Abort, if Content-Length value from the data reduction proxy does not 2686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // exist or it cannot be converted to an integer. 2696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!base::StringToInt(fingerprint, &received_content_length_fingerprint)) 2706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return false; 2716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string actual_content_length_string; 2736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Abort, if there is no Content-Length header received. 2746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!response_headers_->GetNormalizedHeader("Content-Length", 2756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) &actual_content_length_string)) { 2766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return false; 2776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Abort, if the Content-Length value cannot be converted to integer. 2806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!base::StringToInt(actual_content_length_string, 2816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) &actual_content_length)) { 2826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return false; 2836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 2846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return received_content_length_fingerprint != actual_content_length; 2866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 2876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void DataReductionProxyTamperDetection:: 2896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ReportUMAforContentLengthHeaderValidation() const { 2906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Gets MIME type of the response and reports to UMA histograms separately. 2916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Divides MIME types into 4 groups: JavaScript, CSS, Images, and others. 2926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) REPORT_TAMPER_DETECTION_UMA( 2936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scheme_is_https_, 2946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "DataReductionProxy.HeaderTamperedHTTPS_ContentLength", 2956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "DataReductionProxy.HeaderTamperedHTTP_ContentLength", 2966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) carrier_id_); 2976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Gets MIME type. 2996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string mime_type; 3006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) response_headers_->GetMimeType(&mime_type); 3016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string JS1 = "text/javascript"; 3036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string JS2 = "application/x-javascript"; 3046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string JS3 = "application/javascript"; 3056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string CSS = "text/css"; 3066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string IMAGE = "image/"; 3076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) size_t mime_type_size = mime_type.size(); 3096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if ((mime_type_size >= JS1.size() && LowerCaseEqualsASCII(mime_type.begin(), 3106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mime_type.begin() + JS1.size(), JS1.c_str())) || 3116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) (mime_type_size >= JS2.size() && LowerCaseEqualsASCII(mime_type.begin(), 3126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mime_type.begin() + JS2.size(), JS2.c_str())) || 3136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) (mime_type_size >= JS3.size() && LowerCaseEqualsASCII(mime_type.begin(), 3146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mime_type.begin() + JS3.size(), JS3.c_str()))) { 3156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) REPORT_TAMPER_DETECTION_UMA( 3166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scheme_is_https_, 3176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "DataReductionProxy.HeaderTamperedHTTPS_ContentLength_JS", 3186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "DataReductionProxy.HeaderTamperedHTTP_ContentLength_JS", 3196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) carrier_id_); 3206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else if (mime_type_size >= CSS.size() && 3216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) LowerCaseEqualsASCII(mime_type.begin(), 3226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mime_type.begin() + CSS.size(), CSS.c_str())) { 3236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) REPORT_TAMPER_DETECTION_UMA( 3246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scheme_is_https_, 3256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "DataReductionProxy.HeaderTamperedHTTPS_ContentLength_CSS", 3266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "DataReductionProxy.HeaderTamperedHTTP_ContentLength_CSS", 3276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) carrier_id_); 3286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else if (mime_type_size >= IMAGE.size() && 3296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) LowerCaseEqualsASCII(mime_type.begin(), 3306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) mime_type.begin() + IMAGE.size(), IMAGE.c_str())) { 3316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) REPORT_TAMPER_DETECTION_UMA( 3326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scheme_is_https_, 3336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "DataReductionProxy.HeaderTamperedHTTPS_ContentLength_Image", 3346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "DataReductionProxy.HeaderTamperedHTTP_ContentLength_Image", 3356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) carrier_id_); 3366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else { 3376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) REPORT_TAMPER_DETECTION_UMA( 3386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scheme_is_https_, 3396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "DataReductionProxy.HeaderTamperedHTTPS_ContentLength_Other", 3406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) "DataReductionProxy.HeaderTamperedHTTP_ContentLength_Other", 3416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) carrier_id_); 3426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 3436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 3446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// We construct a canonical representation of the header so that reordered 3466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// header values will produce the same fingerprint. The fingerprint is 3476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// constructed as follows: 3486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// 1) sort the values; 3496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// 2) concatenate sorted values with a "," delimiter. 3506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)std::string DataReductionProxyTamperDetection::ValuesToSortedString( 3516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::vector<std::string>* values) { 3526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string concatenated_values; 3536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(values); 3546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!values) return ""; 3556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::sort(values->begin(), values->end()); 3576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) for (size_t i = 0; i < values->size(); ++i) { 3586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Concatenates with delimiter ",". 3596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) concatenated_values += (*values)[i] + ","; 3606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 3616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return concatenated_values; 3626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 3636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void DataReductionProxyTamperDetection::GetMD5( 3656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const std::string& input, std::string* output) { 3666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::MD5Digest digest; 3676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::MD5Sum(input.c_str(), input.size(), &digest); 3686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) *output = std::string( 3696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) reinterpret_cast<char*>(digest.a), ARRAYSIZE_UNSAFE(digest.a)); 3706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 3716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)std::vector<std::string> DataReductionProxyTamperDetection::GetHeaderValues( 3736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const net::HttpResponseHeaders* headers, 3746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const std::string& header_name) { 3756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::vector<std::string> values; 3766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::string value; 3776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) void* iter = NULL; 3786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) while (headers->EnumerateHeader(&iter, header_name, &value)) { 3796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) values.push_back(value); 3806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 3816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return values; 3826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 3836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} // namespace data_reduction_proxy 385