Chromium Code Reviews| Index: components/data_reduction_proxy/browser/data_reduction_proxy_auth_request_handler.cc |
| diff --git a/components/data_reduction_proxy/browser/data_reduction_proxy_auth_request_handler.cc b/components/data_reduction_proxy/browser/data_reduction_proxy_auth_request_handler.cc |
| index 590598ae34ef5f0008f8ca99aaaa3fb23d9f51f7..ba7e2b071c2fe05207d475017b6a50be27943c00 100644 |
| --- a/components/data_reduction_proxy/browser/data_reduction_proxy_auth_request_handler.cc |
| +++ b/components/data_reduction_proxy/browser/data_reduction_proxy_auth_request_handler.cc |
| @@ -4,118 +4,155 @@ |
| #include "components/data_reduction_proxy/browser/data_reduction_proxy_auth_request_handler.h" |
| +#include "base/command_line.h" |
| +#include "base/strings/stringprintf.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/time/time.h" |
| +#include "components/data_reduction_proxy/browser/data_reduction_proxy_params.h" |
| +#include "components/data_reduction_proxy/browser/data_reduction_proxy_protocol.h" |
| #include "components/data_reduction_proxy/browser/data_reduction_proxy_settings.h" |
| -#include "net/base/auth.h" |
| +#include "components/data_reduction_proxy/common/data_reduction_proxy_headers.h" |
| +#include "components/data_reduction_proxy/common/data_reduction_proxy_switches.h" |
| +#include "crypto/random.h" |
| +#include "net/proxy/proxy_server.h" |
| +#include "net/url_request/url_request.h" |
| +#include "url/gurl.h" |
| -namespace { |
| -// The minimum interval allowed, in milliseconds, between data reduction proxy |
| -// auth requests. |
| -const int64 kMinAuthRequestIntervalMs = 500; |
| +namespace data_reduction_proxy { |
| + |
| +// The version of the authentication protocol. |
| +const char kProtocolVersion[] = "0"; |
| -// The minimum interval allowed, in milliseconds, between data reduction proxy |
| -// auth token invalidation. |
| -const int64 kMinTokenInvalidationIntervalMs = 60 * 60 * 1000; |
| +// The clients supported by the data reduction proxy. |
| +const char kClientAndroidWebview[] = "webview"; |
| +const char kClientChromeAndroid[] = "android"; |
| +const char kClientChromeIOS[] = "ios"; |
| -// The maximum number of data reduction proxy authentication failures to |
| -// accept before giving up. |
| -const int kMaxBackToBackFailures = 5; |
| +// static |
| +bool DataReductionProxyAuthRequestHandler::IsKeySetOnCommandLine() { |
| + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
| + return command_line.HasSwitch( |
| + data_reduction_proxy::switches::kDataReductionProxyKey); |
| } |
| -namespace data_reduction_proxy { |
| +DataReductionProxyAuthRequestHandler::DataReductionProxyAuthRequestHandler( |
| + DataReductionProxyParams* params) |
| + : data_reduction_proxy_params_(params) { |
| + version_ = kProtocolVersion; |
| +#if defined(OS_ANDROID) |
| + client_ = kClientChromeAndroid; |
| +#elif defined(OS_IOS) |
| + client_ = kClientChromeIOS; |
| +#endif |
| + Init(); |
| +} |
| -int64 DataReductionProxyAuthRequestHandler::auth_request_timestamp_ = 0; |
| +void DataReductionProxyAuthRequestHandler::Init() { |
| + InitAuthentication(GetDefaultKey()); |
| +} |
| -int DataReductionProxyAuthRequestHandler::back_to_back_failure_count_ = 0; |
| -int64 |
| -DataReductionProxyAuthRequestHandler::auth_token_invalidation_timestamp_ = 0; |
| +DataReductionProxyAuthRequestHandler::~DataReductionProxyAuthRequestHandler() { |
| +} |
| +// static |
| +base::string16 DataReductionProxyAuthRequestHandler::AuthHashForSalt( |
| + int64 salt, |
| + const std::string& key) { |
| + std::string salted_key = |
| + base::StringPrintf("%lld%s%lld", |
| + static_cast<long long>(salt), |
| + key.c_str(), |
| + static_cast<long long>(salt)); |
| + return base::UTF8ToUTF16(base::MD5String(salted_key)); |
| +} |
| -DataReductionProxyAuthRequestHandler::DataReductionProxyAuthRequestHandler( |
| - DataReductionProxySettings* settings) : settings_(settings) { |
| - DCHECK(settings); |
| + |
| + |
| +base::Time DataReductionProxyAuthRequestHandler::Now() const { |
|
marq (ping after 24h)
2014/06/25 16:39:26
Why wrap base::Time::Now() like this?
bengr
2014/06/25 17:15:19
This facilitates testing. There's a comment in the
|
| + return base::Time::Now(); |
| } |
| -DataReductionProxyAuthRequestHandler::~DataReductionProxyAuthRequestHandler() { |
| +void DataReductionProxyAuthRequestHandler::RandBytes( |
|
marq (ping after 24h)
2014/06/25 16:39:27
Why wrap RandBytes like this?
bengr
2014/06/25 17:15:19
This facilitates testing also.
|
| + void* output, size_t length) { |
| + crypto::RandBytes(output, length); |
| } |
| -DataReductionProxyAuthRequestHandler::TryHandleResult |
| -DataReductionProxyAuthRequestHandler::TryHandleAuthentication( |
| - net::AuthChallengeInfo* auth_info, |
| - base::string16* user, |
| - base::string16* password) { |
| - if (!auth_info) { |
| - return TRY_HANDLE_RESULT_IGNORE; |
| +void DataReductionProxyAuthRequestHandler::MaybeAddRequestHeader( |
| + net::URLRequest* request, |
| + const net::ProxyServer& proxy_server, |
| + net::HttpRequestHeaders* request_headers) { |
| + if (!proxy_server.is_valid()) { |
| + LOG(WARNING) << "Invalid proxy"; |
|
marq (ping after 24h)
2014/06/25 16:39:26
Clean up the logging -- this looks like debugging
bengr
2014/06/25 17:15:18
Aargh. Sorry. Done.
|
| + return; |
| + } else { |
| + LOG(WARNING) << "Valid proxy"; |
| } |
| - DCHECK(user); |
| - DCHECK(password); |
| - |
| - if (!IsAcceptableAuthChallenge(auth_info)) { |
| - *user = base::string16(); |
| - *password = base::string16(); |
| - return TRY_HANDLE_RESULT_IGNORE; |
| + if (data_reduction_proxy_params_ && |
| + data_reduction_proxy_params_->IsDataReductionProxy( |
| + proxy_server.host_port_pair(), NULL)) { |
| + LOG(WARNING) << "DRP"; |
| + AddAuthorizationHeader(request_headers); |
| } |
| - |
| - base::TimeTicks auth_request = |
| - base::TimeTicks::FromInternalValue(auth_request_timestamp_); |
| - base::TimeTicks auth_token_invalidation = |
| - base::TimeTicks::FromInternalValue(auth_token_invalidation_timestamp_); |
| - |
| - |
| - base::TimeTicks now = Now(); |
| - if ((now - auth_request).InMilliseconds() < kMinAuthRequestIntervalMs) { |
| - // We've received back-to-back failures. There are two possibilities: |
| - // 1) Our auth token has expired and we should invalidate it, or |
| - // 2) We're receiving spurious failures from the service. |
| - // |
| - // If we haven't recently invalidated our token, we do that here |
| - // and make several attempts to authenticate. Otherwise, we fail. |
| - back_to_back_failure_count_++; |
| - if ((now - auth_token_invalidation).InMilliseconds() < |
| - kMinTokenInvalidationIntervalMs) { |
| - auth_token_invalidation_timestamp_ = now.ToInternalValue(); |
| - back_to_back_failure_count_ = 0; |
| - } else { |
| - if (back_to_back_failure_count_ > kMaxBackToBackFailures) { |
| - DLOG(WARNING) << "Interpreting frequent data reduction proxy auth " |
| - << "requests as an authorization failure."; |
| - back_to_back_failure_count_ = 0; |
| - *user = base::string16(); |
| - *password = base::string16(); |
| - return TRY_HANDLE_RESULT_CANCEL; |
| - } |
| - } |
| - } else { |
| - back_to_back_failure_count_ = 0; |
| + else { |
|
marq (ping after 24h)
2014/06/25 16:39:27
} else {
bengr
2014/06/25 17:15:19
Done.
|
| + LOG(WARNING) << "Not DRP"; |
| } |
| - auth_request_timestamp_ = now.ToInternalValue(); |
| - |
| - *password = GetTokenForAuthChallenge(auth_info); |
| +} |
| - if (*password == base::string16()) { |
| - *user = base::string16(); |
| - DLOG(WARNING) << "Data reduction proxy auth produced null token."; |
| - return TRY_HANDLE_RESULT_CANCEL; |
| +void DataReductionProxyAuthRequestHandler::AddAuthorizationHeader( |
| + net::HttpRequestHeaders* headers) { |
| + const char kChromeProxyHeader[] = "Chrome-Proxy"; |
| + std::string header_value; |
| + if (headers->HasHeader(kChromeProxyHeader)) { |
| + headers->GetHeader(kChromeProxyHeader, &header_value); |
| + headers->RemoveHeader(kChromeProxyHeader); |
| + header_value += ", "; |
| } |
| - *user = base::UTF8ToUTF16("fw-cookie"); |
| - return TRY_HANDLE_RESULT_PROCEED; |
| + header_value += |
| + "ps=" + session_ + ", sid=" + credentials_ + ", v=" + version_; |
| + if (!client_.empty()) |
| + header_value += ", c=" + client_; |
| + headers->SetHeader(kChromeProxyHeader, header_value); |
| } |
| -bool DataReductionProxyAuthRequestHandler::IsAcceptableAuthChallenge( |
| - net::AuthChallengeInfo* auth_info) { |
| - return settings_->IsAcceptableAuthChallenge(auth_info); |
| +void DataReductionProxyAuthRequestHandler::InitAuthentication( |
| + const std::string& key) { |
| + key_ = key; |
| + int64 timestamp = |
| + (Now() - base::Time::UnixEpoch()).InMilliseconds() / 1000; |
| + |
| + int32 rand[3]; |
| + RandBytes(rand, 3 * sizeof(rand[0])); |
| + session_ = base::StringPrintf("%lld-%u-%u-%u", |
| + static_cast<long long>(timestamp), |
| + rand[0], |
| + rand[1], |
| + rand[2]); |
| + credentials_ = UTF16ToUTF8(AuthHashForSalt(timestamp, key_)); |
| + |
| + DVLOG(1) << "session: [" << session_ << "] password: [" << credentials_ |
| + << "]"; |
|
marq (ping after 24h)
2014/06/25 16:39:27
Align << for continued log lines.
bengr
2014/06/25 17:15:19
Done.
|
| } |
| -base::string16 DataReductionProxyAuthRequestHandler::GetTokenForAuthChallenge( |
| - net::AuthChallengeInfo* auth_info) { |
| - DCHECK(settings_); |
| - return settings_->GetTokenForAuthChallenge(auth_info); |
| +void DataReductionProxyAuthRequestHandler::SetKey(const std::string& key, |
| + const std::string& client, |
| + const std::string& version) { |
| + client_ = client; |
| + version_ = version; |
| + if (!key.empty()) |
| + InitAuthentication(key); |
| } |
| -base::TimeTicks DataReductionProxyAuthRequestHandler::Now() { |
| - return base::TimeTicks::Now(); |
| + |
| +std::string DataReductionProxyAuthRequestHandler::GetDefaultKey() const { |
| + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
|
marq (ping after 24h)
2014/06/25 16:39:26
Why doesn't this get the key from a data_reduction
bengr
2014/06/25 17:15:19
Key has been pulled out of params, bucause it is m
|
| + std::string key = |
| + command_line.GetSwitchValueASCII(switches::kDataReductionProxyKey); |
| +#if defined(SPDY_PROXY_AUTH_VALUE) |
| + if (key.empty()) |
| + key = SPDY_PROXY_AUTH_VALUE; |
| +#endif |
| + return key; |
| } |
| } // namespace data_reduction_proxy |