1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/http/proxy_client_socket.h"
6
7 #include <unordered_set>
8
9 #include "base/metrics/histogram_macros.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/stringprintf.h"
12 #include "net/base/host_port_pair.h"
13 #include "net/base/net_errors.h"
14 #include "net/http/http_auth_controller.h"
15 #include "net/http/http_request_info.h"
16 #include "net/http/http_response_headers.h"
17 #include "net/http/http_response_info.h"
18 #include "url/gurl.h"
19
20 namespace net {
21
SetStreamPriority(RequestPriority priority)22 void ProxyClientSocket::SetStreamPriority(RequestPriority priority) {}
23
24 // static
BuildTunnelRequest(const HostPortPair & endpoint,const HttpRequestHeaders & extra_headers,const std::string & user_agent,std::string * request_line,HttpRequestHeaders * request_headers)25 void ProxyClientSocket::BuildTunnelRequest(
26 const HostPortPair& endpoint,
27 const HttpRequestHeaders& extra_headers,
28 const std::string& user_agent,
29 std::string* request_line,
30 HttpRequestHeaders* request_headers) {
31 // RFC 7230 Section 5.4 says a client MUST send a Host header field in all
32 // HTTP/1.1 request messages, and Host SHOULD be the first header field
33 // following the request-line. Add "Proxy-Connection: keep-alive" for compat
34 // with HTTP/1.0 proxies such as Squid (required for NTLM authentication).
35 std::string host_and_port = endpoint.ToString();
36 *request_line =
37 base::StringPrintf("CONNECT %s HTTP/1.1\r\n", host_and_port.c_str());
38 request_headers->SetHeader(HttpRequestHeaders::kHost, host_and_port);
39 request_headers->SetHeader(HttpRequestHeaders::kProxyConnection,
40 "keep-alive");
41 if (!user_agent.empty())
42 request_headers->SetHeader(HttpRequestHeaders::kUserAgent, user_agent);
43
44 request_headers->MergeFrom(extra_headers);
45 }
46
47 // static
HandleProxyAuthChallenge(HttpAuthController * auth,HttpResponseInfo * response,const NetLogWithSource & net_log)48 int ProxyClientSocket::HandleProxyAuthChallenge(
49 HttpAuthController* auth,
50 HttpResponseInfo* response,
51 const NetLogWithSource& net_log) {
52 DCHECK(response->headers.get());
53 int rv = auth->HandleAuthChallenge(response->headers, response->ssl_info,
54 false, true, net_log);
55 auth->TakeAuthInfo(&response->auth_challenge);
56 if (rv == OK)
57 return ERR_PROXY_AUTH_REQUESTED;
58 return rv;
59 }
60
61 // static
SanitizeProxyAuth(HttpResponseInfo & response)62 void ProxyClientSocket::SanitizeProxyAuth(HttpResponseInfo& response) {
63 DCHECK(response.headers);
64
65 // Copy status line and all hop-by-hop headers to preserve keep-alive
66 // behavior.
67 const char* kHeadersToKeep[] = {
68 "connection", "proxy-connection", "keep-alive", "trailer",
69 "transfer-encoding", "upgrade",
70
71 "content-length",
72
73 "proxy-authenticate",
74 };
75
76 // Create a list of all present header not in |kHeadersToKeep|, and then
77 // remove them.
78 size_t iter = 0;
79 std::string header_name;
80 std::string header_value;
81 std::unordered_set<std::string> headers_to_remove;
82 while (response.headers->EnumerateHeaderLines(&iter, &header_name,
83 &header_value)) {
84 bool remove = true;
85 for (const char* header : kHeadersToKeep) {
86 if (base::EqualsCaseInsensitiveASCII(header, header_name)) {
87 remove = false;
88 break;
89 }
90 }
91 if (remove)
92 headers_to_remove.insert(header_name);
93 }
94
95 response.headers->RemoveHeaders(headers_to_remove);
96 }
97
98 } // namespace net
99