| Index: chrome/browser/net/spdyproxy/http_auth_handler_spdyproxy.cc
|
| diff --git a/chrome/browser/net/spdyproxy/http_auth_handler_spdyproxy.cc b/chrome/browser/net/spdyproxy/http_auth_handler_spdyproxy.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..183735e6f9e96bca206edcd966cf485c2c80be2a
|
| --- /dev/null
|
| +++ b/chrome/browser/net/spdyproxy/http_auth_handler_spdyproxy.cc
|
| @@ -0,0 +1,169 @@
|
| +// Copyright (c) 2012 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.
|
| +
|
| +#include "chrome/browser/net/spdyproxy/http_auth_handler_spdyproxy.h"
|
| +
|
| +#include <string>
|
| +
|
| +#include "base/i18n/icu_string_conversions.h"
|
| +#include "base/metrics/histogram.h"
|
| +#include "base/string_util.h"
|
| +#include "base/utf_string_conversions.h"
|
| +#include "net/base/net_errors.h"
|
| +#include "net/http/http_auth.h"
|
| +#include "net/http/http_request_info.h"
|
| +
|
| +
|
| +namespace spdyproxy {
|
| +
|
| +using net::AuthCredentials;
|
| +using net::BoundNetLog;
|
| +using net::CompletionCallback;
|
| +using net::HttpAuth;
|
| +using net::HttpAuthHandler;
|
| +using net::HttpAuthHandlerFactory;
|
| +using net::HttpRequestInfo;
|
| +using net::HttpUtil;
|
| +
|
| +HttpAuthHandlerSpdyProxy::Factory::Factory(
|
| + const GURL& authorized_spdyproxy_origin)
|
| + : authorized_spdyproxy_origin_(authorized_spdyproxy_origin) {
|
| +}
|
| +
|
| +HttpAuthHandlerSpdyProxy::Factory::~Factory() {
|
| +}
|
| +
|
| +int HttpAuthHandlerSpdyProxy::Factory::CreateAuthHandler(
|
| + HttpAuth::ChallengeTokenizer* challenge,
|
| + HttpAuth::Target target,
|
| + const GURL& origin,
|
| + CreateReason reason,
|
| + int digest_nonce_count,
|
| + const BoundNetLog& net_log,
|
| + scoped_ptr<HttpAuthHandler>* handler) {
|
| + // If a spdyproxy auth proxy has not been set, refuse all requests to use this
|
| + // auth handler.
|
| + if (authorized_spdyproxy_origin_.possibly_invalid_spec().empty()) {
|
| + VLOG(1) << "SpdyProxy auth without configuring authorized origin.";
|
| + return net::ERR_UNSUPPORTED_AUTH_SCHEME;
|
| + }
|
| +
|
| + // We ensure that this authentication handler is used only with an authorized
|
| + // SPDY proxy, since otherwise a user's authentication token can be
|
| + // sniffed by a malicious proxy that presents an appropriate challenge.
|
| + const GURL origin_origin = origin.GetOrigin();
|
| + if (!(target == HttpAuth::AUTH_PROXY &&
|
| + origin_origin == authorized_spdyproxy_origin_)) {
|
| + UMA_HISTOGRAM_COUNTS("Net.UnexpectedSpdyProxyAuth", 1);
|
| + VLOG(1) << "SpdyProxy auth request with an unexpected config."
|
| + << " origin: " << origin_origin.possibly_invalid_spec()
|
| + << " authorized_origin: "
|
| + << authorized_spdyproxy_origin_.possibly_invalid_spec();
|
| + return net::ERR_UNSUPPORTED_AUTH_SCHEME;
|
| + }
|
| +
|
| + scoped_ptr<HttpAuthHandler> tmp_handler(
|
| + new HttpAuthHandlerSpdyProxy(authorized_spdyproxy_origin_));
|
| + if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log))
|
| + return net::ERR_INVALID_RESPONSE;
|
| + handler->swap(tmp_handler);
|
| + return net::OK;
|
| +}
|
| +
|
| +HttpAuthHandlerSpdyProxy::HttpAuthHandlerSpdyProxy(
|
| + const GURL& authorized_spdyproxy_origin)
|
| + : HttpAuthHandler(),
|
| + authorized_spdyproxy_origin_(authorized_spdyproxy_origin) {
|
| +}
|
| +
|
| +HttpAuth::AuthorizationResult
|
| +HttpAuthHandlerSpdyProxy::HandleAnotherChallenge(
|
| + HttpAuth::ChallengeTokenizer* challenge) {
|
| + // SpdyProxy authentication is always a single round, so any responses
|
| + // should be treated as a rejection.
|
| + return HttpAuth::AUTHORIZATION_RESULT_REJECT;
|
| +}
|
| +
|
| +bool HttpAuthHandlerSpdyProxy::NeedsIdentity() {
|
| + return true;
|
| +}
|
| +
|
| +bool HttpAuthHandlerSpdyProxy::AllowsDefaultCredentials() {
|
| + return false;
|
| +}
|
| +
|
| +bool HttpAuthHandlerSpdyProxy::AllowsExplicitCredentials() {
|
| + return true;
|
| +}
|
| +
|
| +bool HttpAuthHandlerSpdyProxy::Init(
|
| + HttpAuth::ChallengeTokenizer* challenge) {
|
| + auth_scheme_ = HttpAuth::AUTH_SCHEME_SPDYPROXY;
|
| + score_ = 5;
|
| + properties_ = ENCRYPTS_IDENTITY;
|
| + return ParseChallenge(challenge);
|
| +}
|
| +
|
| +int HttpAuthHandlerSpdyProxy::GenerateAuthTokenImpl(
|
| + const AuthCredentials* credentials, const HttpRequestInfo* request,
|
| + const CompletionCallback&, std::string* auth_token) {
|
| + DCHECK(credentials);
|
| + if (credentials->password().length() == 0) {
|
| + DVLOG(1) << "Received a SpdyProxy auth token request without an "
|
| + << "available token.";
|
| + return -1;
|
| + }
|
| + *auth_token = "SpdyProxy ps=\"" + ps_token_ + "\", sid=\"" +
|
| + UTF16ToUTF8(credentials->password()) + "\"";
|
| + return net::OK;
|
| +}
|
| +
|
| +bool HttpAuthHandlerSpdyProxy::ParseChallenge(
|
| + HttpAuth::ChallengeTokenizer* challenge) {
|
| +
|
| + // Verify the challenge's auth-scheme.
|
| + if (!LowerCaseEqualsASCII(challenge->scheme(), "spdyproxy")) {
|
| + VLOG(1) << "Parsed challenge without SpdyProxy type";
|
| + return false;
|
| + }
|
| +
|
| + HttpUtil::NameValuePairsIterator parameters = challenge->param_pairs();
|
| +
|
| + // Loop through all the properties.
|
| + while (parameters.GetNext()) {
|
| + // FAIL -- couldn't parse a property.
|
| + if (!ParseChallengeProperty(parameters.name(),
|
| + parameters.value()))
|
| + return false;
|
| + }
|
| + // Check if tokenizer failed.
|
| + if (!parameters.valid())
|
| + return false;
|
| +
|
| + // Check that the required properties were provided.
|
| + if (realm_.empty())
|
| + return false;
|
| +
|
| + if (ps_token_.empty())
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool HttpAuthHandlerSpdyProxy::ParseChallengeProperty(
|
| + const std::string& name, const std::string& value) {
|
| + if (LowerCaseEqualsASCII(name, "realm")) {
|
| + std::string realm;
|
| + if (!base::ConvertToUtf8AndNormalize(value, base::kCodepageLatin1, &realm))
|
| + return false;
|
| + realm_ = realm;
|
| + } else if (LowerCaseEqualsASCII(name, "ps")) {
|
| + ps_token_ = value;
|
| + } else {
|
| + VLOG(1) << "Skipping unrecognized SpdyProxy auth property, " << name;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +} // namespace spdyproxy
|
|
|