From 6cc4218f3320d1ed11553c4a89a360a8db143ca7 Mon Sep 17 00:00:00 2001 From: "cbentzel@chromium.org" Date: Mon, 2 Aug 2010 11:27:02 +0000 Subject: Digest authentication uses a uri field to prevent replay attacks. When authenticating to an HTTP proxy to establish a secure tunnel (via CONNECT), the uri should be the hostname of the server and the destination port, such as "www.example.com:443". When authenticating to an HTTP proxy for a non-secure content, the uri should be the path at the server, i.e. "/index.html". If the site we are trying to connect to previously advertised "Alternate-Protocol: 443:spdy-npn/1" a request to "http://www.example.com" will be attempted on a secure port. However, the URL passed into the digest authenticator was an unsecure one, and it decided to have a uri in the form "/index.html" rather than the correct "www.example.com:443". This causes persistent failure with the password and many password prompts. BUG=49865 TEST=Run with --use-spdy=npn, force connection through a digest authenticating proxy, and browse a site which advertises Alternate-Protocol through http URLs. Review URL: http://codereview.chromium.org/3028021 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@54528 0039d316-1c4b-4281-b951-d872f2087c98 --- net/http/http_network_transaction.cc | 39 +++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 10 deletions(-) (limited to 'net/http/http_network_transaction.cc') diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index aa557db..a3624f3 100644 --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc @@ -194,6 +194,17 @@ void ProcessAlternateProtocol(const HttpResponseHeaders& headers, alternate_protocols->SetAlternateProtocolFor(host_port, port, protocol); } +GURL UpgradeUrlToHttps(const GURL& original_url) { + GURL::Replacements replacements; + // new_sheme and new_port need to be in scope here because GURL::Replacements + // references the memory contained by them directly. + const std::string new_scheme = "https"; + const std::string new_port = IntToString(443); + replacements.SetSchemeStr(new_scheme); + replacements.SetPortStr(new_port); + return original_url.ReplaceComponents(replacements); +} + } // namespace //----------------------------------------------------------------------------- @@ -682,15 +693,7 @@ int HttpNetworkTransaction::DoResolveProxy() { endpoint_.set_port(alternate.port); alternate_protocol_ = alternate.protocol; alternate_protocol_mode_ = kUsingAlternateProtocol; - - url_canon::Replacements replacements; - replacements.SetScheme("https", - url_parse::Component(0, strlen("https"))); - const std::string port_str = base::IntToString(endpoint_.port()); - replacements.SetPort(port_str.c_str(), - url_parse::Component(0, port_str.size())); - alternate_endpoint_url = - curr_endpoint_url->ReplaceComponents(replacements); + alternate_endpoint_url = UpgradeUrlToHttps(*curr_endpoint_url); curr_endpoint_url = &alternate_endpoint_url; } } @@ -779,9 +782,25 @@ int HttpNetworkTransaction::DoInitConnection() { request_->referrer, disable_resolver_cache); if (proxy_info_.is_http()) { + GURL authentication_url = request_->url; + if (using_ssl_) { + if (!authentication_url.SchemeIs("https")) { + // If a proxy tunnel connection needs to be established due to + // an Alternate-Protocol, the URL needs to be changed to indicate + // https or digest authentication attempts will fail. + // For example, suppose the initial request was for + // "http://www.example.com/index.html". If this is an SSL + // upgrade due to alternate protocol, the digest authorization + // should have a uri="www.example.com:443" field rather than a + // "/index.html" entry, even though the original request URL has not + // changed. + authentication_url = UpgradeUrlToHttps(authentication_url); + } + } establishing_tunnel_ = using_ssl_; http_proxy_params = new HttpProxySocketParams(proxy_tcp_params, - request_->url, endpoint_, + authentication_url, + endpoint_, session_, using_ssl_); } else { DCHECK(proxy_info_.is_socks()); -- cgit v1.1