Index: chrome/browser/net/spdyproxy/data_reduction_proxy_settings.cc |
diff --git a/chrome/browser/net/spdyproxy/data_reduction_proxy_settings.cc b/chrome/browser/net/spdyproxy/data_reduction_proxy_settings.cc |
index 4318d770545b5b7eb7818aaf49d33ad3db4b43d6..fe86a08257e5b895c50dde524a3158ce1413022c 100644 |
--- a/chrome/browser/net/spdyproxy/data_reduction_proxy_settings.cc |
+++ b/chrome/browser/net/spdyproxy/data_reduction_proxy_settings.cc |
@@ -21,9 +21,13 @@ |
#include "chrome/browser/profiles/profile_manager.h" |
#include "chrome/common/chrome_switches.h" |
#include "chrome/common/pref_names.h" |
+#include "crypto/random.h" |
+#include "net/base/auth.h" |
#include "net/base/host_port_pair.h" |
#include "net/base/load_flags.h" |
#include "net/base/net_errors.h" |
+#include "net/http/http_auth.h" |
+#include "net/http/http_network_session.h" |
#include "net/url_request/url_fetcher.h" |
#include "net/url_request/url_fetcher_delegate.h" |
#include "net/url_request/url_request_status.h" |
@@ -47,6 +51,10 @@ enum ProxyStartupState { |
const char kEnabled[] = "Enabled"; |
+// TODO(marq): factor this string out into a constant here and in |
bengr
2013/10/22 17:49:30
Factor
marq (ping after 24h)
2013/10/22 21:18:01
Done.
|
+// http_auth_handler_spdyproxy. |
+const char kAuthenticationRealmName[] = "SpdyProxy"; |
+ |
int64 GetInt64PrefValue(const ListValue& list_value, size_t index) { |
int64 val = 0; |
std::string pref_value; |
@@ -107,6 +115,42 @@ void DataReductionProxySettings::InitDataReductionProxySettings() { |
} |
} |
+void DataReductionProxySettings::InitDataReductionProxySession( |
+ net::HttpNetworkSession* session) { |
bengr
2013/10/22 17:49:30
indent +2
marq (ping after 24h)
2013/10/22 21:18:01
Done.
|
+// This is a no-op unless the authentication params are compiled in. |
bengr
2013/10/22 17:49:30
parameters
marq (ping after 24h)
2013/10/22 21:18:01
Done.
|
+// (even though values for them may be specified on the command line). |
bengr
2013/10/22 17:49:30
It's probably worth saying that when specified in
marq (ping after 24h)
2013/10/22 21:18:01
Done.
|
+#if defined(SPDY_PROXY_AUTH_ORIGIN) && defined(SPDY_PROXY_AUTH_VALUE) |
+ DCHECK(session); |
+ int64 timestamp = |
+ (base::Time::Now() - base::Time::UnixEpoch()).InMilliseconds() / 1000; |
bengr
2013/10/22 17:49:30
indent -1
marq (ping after 24h)
2013/10/22 21:18:01
Done.
|
+ |
+ DataReductionProxyList proxies = GetDataReductionProxies(); |
+ for (DataReductionProxyList::iterator it = proxies.begin(); |
+ it != proxies.end(); ++it) { |
+ net::HostPortPair auth_origin = *it; |
bengr
2013/10/22 17:49:30
const ref?
marq (ping after 24h)
2013/10/22 21:18:01
Yes, but the code's changed slightly.
|
+ int32 rand1, rand2, rand3; |
+ crypto::RandBytes(&rand1, sizeof(rand1)); |
+ crypto::RandBytes(&rand2, sizeof(rand2)); |
+ crypto::RandBytes(&rand3, sizeof(rand3)); |
+ |
+ std::string realm = |
+ base::StringPrintf("%s%lld", kAuthenticationRealmName, timestamp); |
+ std::string challenge = base::StringPrintf( |
+ "%s realm=\"%s\", ps=\"%lld-%u-%u-%u\"", |
+ kAuthenticationRealmName, realm.data(), timestamp, rand1, rand2, rand3); |
+ base::string16 password = AuthHashForSalt(timestamp); |
+ |
+ DVLOG(1) << "origin: [" << auth_origin.ToString() << "] realm: [" << realm |
+ << "] challenge: [" << challenge << "] password: [" << password << "]"; |
+ |
+ net::AuthCredentials credentials(base::string16(), password); |
+ session->http_auth_cache()->Add(GURL(auth_origin.ToString()), realm, |
+ net::HttpAuth::AUTH_SCHEME_SPDYPROXY, |
+ challenge, credentials, std::string("/")); |
+ } |
+#endif // defined(SPDY_PROXY_AUTH_ORIGIN) && defined(SPDY_PROXY_AUTH_VALUE) |
+} |
+ |
void DataReductionProxySettings::AddHostPatternToBypass( |
const std::string& pattern) { |
bypass_rules_.push_back(pattern); |
@@ -143,31 +187,55 @@ std::string DataReductionProxySettings::GetDataReductionProxyOrigin() { |
const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
if (command_line.HasSwitch(switches::kSpdyProxyAuthOrigin)) |
return command_line.GetSwitchValueASCII(switches::kSpdyProxyAuthOrigin); |
-#if defined(SPDY_PROXY_AUTH_ORIGIN) |
- return SPDY_PROXY_AUTH_ORIGIN; |
-#else |
- return std::string(); |
-#endif |
+ return GetDefaultProxyHost(); |
} |
-std::string DataReductionProxySettings::GetDataReductionProxyAuth() { |
- if (!IsDataReductionProxyAllowed()) |
+std::string DataReductionProxySettings::GetDataReductionProxyFallback() { |
+ // Regardless of what else is defined, only return a value if the main proxy |
+ // origin is defined. |
+ if (GetDataReductionProxyOrigin().empty()) |
return std::string(); |
const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
- if (command_line.HasSwitch(switches::kSpdyProxyAuthOrigin)) { |
- // If an origin is provided via a switch, then only consider the value |
- // that is provided by a switch. Do not use the preprocessor constant. |
- // Don't expose SPDY_PROXY_AUTH_VALUE to a proxy passed in via the command |
- // line. |
- if (command_line.HasSwitch(switches::kSpdyProxyAuthValue)) |
- return command_line.GetSwitchValueASCII(switches::kSpdyProxyAuthValue); |
- return std::string(); |
+ if (command_line.HasSwitch(switches::kSpdyProxyAuthFallback)) |
+ return command_line.GetSwitchValueASCII(switches::kSpdyProxyAuthFallback); |
+ return GetDefaultFallbackProxyHost(); |
+} |
+ |
+bool DataReductionProxySettings::IsAcceptableAuthChallenge( |
+ net::AuthChallengeInfo* auth_info) { |
+ // Challenge realm must start with the authentication realm name. |
+ std::string realm_prefix = |
+ auth_info->realm.substr(0, strlen(kAuthenticationRealmName)); |
+ if (realm_prefix != kAuthenticationRealmName) |
+ return false; |
+ |
+ // The challenger must be one of the configured proxies. |
+ DataReductionProxyList proxies = GetDataReductionProxies(); |
+ for (DataReductionProxyList::iterator it = proxies.begin(); |
+ it != proxies.end(); ++it) { |
+ net::HostPortPair origin_host = *it; |
+ if (origin_host.Equals(auth_info->challenger)) |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+base::string16 DataReductionProxySettings::GetTokenForAuthChallenge( |
+ net::AuthChallengeInfo* auth_info) { |
+ if (auth_info->realm.length() > strlen(kAuthenticationRealmName)) { |
+ int64 salt; |
+ std::string realm_suffix = |
+ auth_info->realm.substr(strlen(kAuthenticationRealmName)); |
+ if (base::StringToInt64(realm_suffix, &salt)) { |
+ return AuthHashForSalt(salt); |
+ } else { |
+ DVLOG(1) << "Unable to parse realm name " << auth_info->realm |
+ << "into an int for salting."; |
+ return base::string16(); |
+ } |
+ } else { |
+ return base::string16(); |
} |
-#if defined(SPDY_PROXY_AUTH_VALUE) |
- return SPDY_PROXY_AUTH_VALUE; |
-#else |
- return std::string(); |
-#endif |
} |
bool DataReductionProxySettings::IsDataReductionProxyEnabled() { |
@@ -178,6 +246,24 @@ bool DataReductionProxySettings::IsDataReductionProxyManaged() { |
return spdy_proxy_auth_enabled_.IsManaged(); |
} |
+DataReductionProxySettings::DataReductionProxyList |
+DataReductionProxySettings::GetDataReductionProxies() { |
+ DataReductionProxyList proxies; |
+ std::string proxy = GetDataReductionProxyOrigin(); |
+ std::string fallback = GetDataReductionProxyFallback(); |
+ |
+ if (!proxy.empty()) |
+ proxies.push_back(net::HostPortPair::FromURL(GURL(proxy))); |
+ |
+ if (!fallback.empty()) { |
+ // Sanity check: fallback isn't the only proxy. |
+ DCHECK(!proxies.empty()); |
+ proxies.push_back(net::HostPortPair::FromURL(GURL(fallback))); |
+ } |
+ |
+ return proxies; |
+} |
+ |
void DataReductionProxySettings::SetDataReductionProxyEnabled(bool enabled) { |
// Prevent configuring the proxy when it is not allowed to be used. |
if (!IsDataReductionProxyAllowed()) |
@@ -195,12 +281,12 @@ int64 DataReductionProxySettings::GetDataReductionLastUpdateTime() { |
return static_cast<int64>(last_update.ToJsTime()); |
} |
-std::vector<long long> |
+DataReductionProxySettings::ContentLengthList |
DataReductionProxySettings::GetDailyOriginalContentLengths() { |
return GetDailyContentLengths(prefs::kDailyHttpOriginalContentLength); |
} |
-std::vector<long long> |
+DataReductionProxySettings::ContentLengthList |
DataReductionProxySettings::GetDailyReceivedContentLengths() { |
return GetDailyContentLengths(prefs::kDailyHttpReceivedContentLength); |
} |
@@ -237,17 +323,6 @@ void DataReductionProxySettings::OnURLFetchComplete( |
disabled_by_carrier_ = true; |
} |
-std::string DataReductionProxySettings::GetDataReductionProxyOriginHostPort() { |
- std::string spdy_proxy = GetDataReductionProxyOrigin(); |
- if (spdy_proxy.empty()) { |
- DLOG(ERROR) << "A SPDY proxy has not been set."; |
- return spdy_proxy; |
- } |
- // Remove a trailing slash from the proxy string if one exists as well as |
- // leading HTTPS scheme. |
- return net::HostPortPair::FromURL(GURL(spdy_proxy)).ToString(); |
-} |
- |
void DataReductionProxySettings::OnIPAddressChanged() { |
if (enabled_by_user_) { |
DCHECK(IsDataReductionProxyAllowed()); |
@@ -284,6 +359,22 @@ void DataReductionProxySettings::LogProxyState(bool enabled, bool at_startup) { |
<< " " << (at_startup ? kAtStartup : kByUser); |
} |
+std::string DataReductionProxySettings::GetDefaultProxyHost() { |
bengr
2013/10/22 17:49:30
Why isn't the handling of command line switch valu
marq (ping after 24h)
2013/10/22 21:18:01
These two methods are used so that unit tests can
|
+#if defined(SPDY_PROXY_AUTH_ORIGIN) |
+ return SPDY_PROXY_AUTH_ORIGIN; |
+#else |
+ return std::string(); |
+#endif |
+} |
+ |
+std::string DataReductionProxySettings::GetDefaultFallbackProxyHost() { |
+#if defined(DATA_REDUCTION_FALLBACK_HOST) |
+ return DATA_REDUCTION_FALLBACK_HOST; |
bengr
2013/10/22 17:49:30
why not check in this function if GetDefaultProxyH
marq (ping after 24h)
2013/10/22 21:18:01
I don't think the default value here is of necessi
|
+#else |
+ return std::string(); |
+#endif |
+} |
+ |
PrefService* DataReductionProxySettings::GetOriginalProfilePrefs() { |
return g_browser_process->profile_manager()->GetLastUsedProfile()-> |
GetOriginalProfile()->GetPrefs(); |
@@ -324,12 +415,10 @@ void DataReductionProxySettings::MaybeActivateDataReductionProxy( |
ResetDataReductionStatistics(); |
} |
- std::string spdy_proxy_origin = GetDataReductionProxyOriginHostPort(); |
- |
+ std::string proxy = GetDataReductionProxyOrigin(); |
// Configure use of the data reduction proxy if it is enabled and the proxy |
// origin is non-empty. |
- enabled_by_user_= |
- spdy_proxy_auth_enabled_.GetValue() && !spdy_proxy_origin.empty(); |
+ enabled_by_user_= spdy_proxy_auth_enabled_.GetValue() && !proxy.empty(); |
SetProxyConfigs(enabled_by_user_ && !disabled_by_carrier_, at_startup); |
// Check if the proxy has been disabled explicitly by the carrier. |
@@ -345,8 +434,11 @@ void DataReductionProxySettings::SetProxyConfigs(bool enabled, |
DictionaryPrefUpdate update(prefs, prefs::kProxy); |
base::DictionaryValue* dict = update.Get(); |
if (enabled) { |
+ std::string fallback = GetDataReductionProxyFallback(); |
std::string proxy_server_config = |
- "http=" + GetDataReductionProxyOrigin() + ",direct://;"; |
+ "http=" + GetDataReductionProxyOrigin() + |
+ (fallback.empty() ? "" : "," + fallback) + |
+ ",direct://;"; |
dict->SetString("server", proxy_server_config); |
dict->SetString("mode", |
ProxyModeToString(ProxyPrefs::MODE_FIXED_SERVERS)); |
@@ -436,6 +528,36 @@ std::string DataReductionProxySettings::GetProxyCheckURL() { |
#endif |
} |
+base::string16 DataReductionProxySettings::AuthHashForSalt(int64 salt) { |
+ if (!IsDataReductionProxyAllowed()) |
+ return base::string16(); |
+ |
+ std::string key; |
+ |
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
+ if (command_line.HasSwitch(switches::kSpdyProxyAuthOrigin)) { |
+ // If an origin is provided via a switch, then only consider the value |
+ // that is provided by a switch. Do not use the preprocessor constant. |
+ // Don't expose SPDY_PROXY_AUTH_VALUE to a proxy passed in via the command |
+ // line. |
+ if (!command_line.HasSwitch(switches::kSpdyProxyAuthValue)) |
+ return base::string16(); |
+ key = command_line.GetSwitchValueASCII(switches::kSpdyProxyAuthValue); |
+ } else { |
+#if defined(SPDY_PROXY_AUTH_VALUE) |
+ key = SPDY_PROXY_AUTH_VALUE; |
+#else |
+ return base::string16(); |
+#endif |
+ } |
+ |
+ DCHECK(!key.empty()); |
+ |
+ std::string salted_key = |
+ base::StringPrintf("%lld%s%lld", salt, key.c_str(), salt); |
+ return UTF8ToUTF16(base::MD5String(salted_key)); |
+} |
+ |
net::URLFetcher* DataReductionProxySettings::GetURLFetcher() { |
std::string url = GetProxyCheckURL(); |
if (url.empty()) |