http_proxy_client_socket.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "net/http/http_proxy_client_socket.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/callback_helpers.h"
  9. #include "base/strings/string_util.h"
  10. #include "base/values.h"
  11. #include "net/base/auth.h"
  12. #include "net/base/host_port_pair.h"
  13. #include "net/base/io_buffer.h"
  14. #include "net/base/proxy_delegate.h"
  15. #include "net/base/proxy_server.h"
  16. #include "net/http/http_basic_stream.h"
  17. #include "net/http/http_log_util.h"
  18. #include "net/http/http_network_session.h"
  19. #include "net/http/http_request_info.h"
  20. #include "net/http/http_response_headers.h"
  21. #include "net/http/http_stream_parser.h"
  22. #include "net/log/net_log.h"
  23. #include "net/log/net_log_event_type.h"
  24. #include "net/socket/stream_socket.h"
  25. #include "url/gurl.h"
  26. namespace net {
  27. const int HttpProxyClientSocket::kDrainBodyBufferSize;
  28. HttpProxyClientSocket::HttpProxyClientSocket(
  29. std::unique_ptr<StreamSocket> socket,
  30. const std::string& user_agent,
  31. const HostPortPair& endpoint,
  32. const ProxyServer& proxy_server,
  33. scoped_refptr<HttpAuthController> http_auth_controller,
  34. ProxyDelegate* proxy_delegate,
  35. const NetworkTrafficAnnotationTag& traffic_annotation)
  36. : io_callback_(base::BindRepeating(&HttpProxyClientSocket::OnIOComplete,
  37. base::Unretained(this))),
  38. socket_(std::move(socket)),
  39. endpoint_(endpoint),
  40. auth_(std::move(http_auth_controller)),
  41. proxy_server_(proxy_server),
  42. proxy_delegate_(proxy_delegate),
  43. traffic_annotation_(traffic_annotation),
  44. net_log_(socket_->NetLog()) {
  45. // Synthesize the bits of a request that are actually used.
  46. request_.url = GURL("https://" + endpoint.ToString());
  47. request_.method = "CONNECT";
  48. if (!user_agent.empty())
  49. request_.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
  50. user_agent);
  51. }
  52. HttpProxyClientSocket::~HttpProxyClientSocket() {
  53. Disconnect();
  54. }
  55. int HttpProxyClientSocket::RestartWithAuth(CompletionOnceCallback callback) {
  56. DCHECK_EQ(STATE_NONE, next_state_);
  57. DCHECK(user_callback_.is_null());
  58. int rv = PrepareForAuthRestart();
  59. if (rv != OK)
  60. return rv;
  61. rv = DoLoop(OK);
  62. if (rv == ERR_IO_PENDING) {
  63. if (!callback.is_null())
  64. user_callback_ = std::move(callback);
  65. }
  66. return rv;
  67. }
  68. const scoped_refptr<HttpAuthController>&
  69. HttpProxyClientSocket::GetAuthController() const {
  70. return auth_;
  71. }
  72. const HttpResponseInfo* HttpProxyClientSocket::GetConnectResponseInfo() const {
  73. return response_.headers.get() ? &response_ : nullptr;
  74. }
  75. int HttpProxyClientSocket::Connect(CompletionOnceCallback callback) {
  76. DCHECK(socket_);
  77. DCHECK(user_callback_.is_null());
  78. if (next_state_ == STATE_DONE)
  79. return OK;
  80. DCHECK_EQ(STATE_NONE, next_state_);
  81. next_state_ = STATE_GENERATE_AUTH_TOKEN;
  82. int rv = DoLoop(OK);
  83. if (rv == ERR_IO_PENDING)
  84. user_callback_ = std::move(callback);
  85. return rv;
  86. }
  87. void HttpProxyClientSocket::Disconnect() {
  88. if (socket_)
  89. socket_->Disconnect();
  90. // Reset other states to make sure they aren't mistakenly used later.
  91. // These are the states initialized by Connect().
  92. next_state_ = STATE_NONE;
  93. user_callback_.Reset();
  94. }
  95. bool HttpProxyClientSocket::IsConnected() const {
  96. return next_state_ == STATE_DONE && socket_->IsConnected();
  97. }
  98. bool HttpProxyClientSocket::IsConnectedAndIdle() const {
  99. return next_state_ == STATE_DONE && socket_->IsConnectedAndIdle();
  100. }
  101. const NetLogWithSource& HttpProxyClientSocket::NetLog() const {
  102. return net_log_;
  103. }
  104. bool HttpProxyClientSocket::WasEverUsed() const {
  105. if (socket_)
  106. return socket_->WasEverUsed();
  107. NOTREACHED();
  108. return false;
  109. }
  110. bool HttpProxyClientSocket::WasAlpnNegotiated() const {
  111. // Do not delegate to `socket_`. While `socket_` may negotiate ALPN with the
  112. // proxy, this object represents the tunneled TCP connection to the origin.
  113. return false;
  114. }
  115. NextProto HttpProxyClientSocket::GetNegotiatedProtocol() const {
  116. // Do not delegate to `socket_`. While `socket_` may negotiate ALPN with the
  117. // proxy, this object represents the tunneled TCP connection to the origin.
  118. return kProtoUnknown;
  119. }
  120. bool HttpProxyClientSocket::GetSSLInfo(SSLInfo* ssl_info) {
  121. // Do not delegate to `socket_`. While `socket_` may connect to the proxy with
  122. // TLS, this object represents the tunneled TCP connection to the origin.
  123. return false;
  124. }
  125. int64_t HttpProxyClientSocket::GetTotalReceivedBytes() const {
  126. return socket_->GetTotalReceivedBytes();
  127. }
  128. void HttpProxyClientSocket::ApplySocketTag(const SocketTag& tag) {
  129. return socket_->ApplySocketTag(tag);
  130. }
  131. int HttpProxyClientSocket::Read(IOBuffer* buf,
  132. int buf_len,
  133. CompletionOnceCallback callback) {
  134. DCHECK(user_callback_.is_null());
  135. if (!CheckDone())
  136. return ERR_TUNNEL_CONNECTION_FAILED;
  137. return socket_->Read(buf, buf_len, std::move(callback));
  138. }
  139. int HttpProxyClientSocket::ReadIfReady(IOBuffer* buf,
  140. int buf_len,
  141. CompletionOnceCallback callback) {
  142. DCHECK(user_callback_.is_null());
  143. if (!CheckDone())
  144. return ERR_TUNNEL_CONNECTION_FAILED;
  145. return socket_->ReadIfReady(buf, buf_len, std::move(callback));
  146. }
  147. int HttpProxyClientSocket::CancelReadIfReady() {
  148. return socket_->CancelReadIfReady();
  149. }
  150. int HttpProxyClientSocket::Write(
  151. IOBuffer* buf,
  152. int buf_len,
  153. CompletionOnceCallback callback,
  154. const NetworkTrafficAnnotationTag& traffic_annotation) {
  155. DCHECK_EQ(STATE_DONE, next_state_);
  156. DCHECK(user_callback_.is_null());
  157. return socket_->Write(buf, buf_len, std::move(callback), traffic_annotation);
  158. }
  159. int HttpProxyClientSocket::SetReceiveBufferSize(int32_t size) {
  160. return socket_->SetReceiveBufferSize(size);
  161. }
  162. int HttpProxyClientSocket::SetSendBufferSize(int32_t size) {
  163. return socket_->SetSendBufferSize(size);
  164. }
  165. int HttpProxyClientSocket::GetPeerAddress(IPEndPoint* address) const {
  166. return socket_->GetPeerAddress(address);
  167. }
  168. int HttpProxyClientSocket::GetLocalAddress(IPEndPoint* address) const {
  169. return socket_->GetLocalAddress(address);
  170. }
  171. int HttpProxyClientSocket::PrepareForAuthRestart() {
  172. if (!response_.headers.get())
  173. return ERR_CONNECTION_RESET;
  174. // If the connection can't be reused, return
  175. // ERR_UNABLE_TO_REUSE_CONNECTION_FOR_PROXY_AUTH. The request will be retried
  176. // at a higher layer.
  177. if (!response_.headers->IsKeepAlive() ||
  178. !http_stream_parser_->CanFindEndOfResponse() || !socket_->IsConnected()) {
  179. socket_->Disconnect();
  180. return ERR_UNABLE_TO_REUSE_CONNECTION_FOR_PROXY_AUTH;
  181. }
  182. // If the auth request had a body, need to drain it before reusing the socket.
  183. if (!http_stream_parser_->IsResponseBodyComplete()) {
  184. next_state_ = STATE_DRAIN_BODY;
  185. drain_buf_ = base::MakeRefCounted<IOBuffer>(kDrainBodyBufferSize);
  186. return OK;
  187. }
  188. return DidDrainBodyForAuthRestart();
  189. }
  190. int HttpProxyClientSocket::DidDrainBodyForAuthRestart() {
  191. // Can't reuse the socket if there's still unread data on it.
  192. if (!socket_->IsConnectedAndIdle())
  193. return ERR_UNABLE_TO_REUSE_CONNECTION_FOR_PROXY_AUTH;
  194. next_state_ = STATE_GENERATE_AUTH_TOKEN;
  195. is_reused_ = true;
  196. // Reset the other member variables.
  197. drain_buf_ = nullptr;
  198. parser_buf_ = nullptr;
  199. http_stream_parser_.reset();
  200. request_line_.clear();
  201. request_headers_.Clear();
  202. response_ = HttpResponseInfo();
  203. return OK;
  204. }
  205. void HttpProxyClientSocket::DoCallback(int result) {
  206. DCHECK_NE(ERR_IO_PENDING, result);
  207. DCHECK(!user_callback_.is_null());
  208. // Since Run() may result in Read being called,
  209. // clear user_callback_ up front.
  210. std::move(user_callback_).Run(result);
  211. }
  212. void HttpProxyClientSocket::OnIOComplete(int result) {
  213. DCHECK_NE(STATE_NONE, next_state_);
  214. DCHECK_NE(STATE_DONE, next_state_);
  215. int rv = DoLoop(result);
  216. if (rv != ERR_IO_PENDING)
  217. DoCallback(rv);
  218. }
  219. int HttpProxyClientSocket::DoLoop(int last_io_result) {
  220. DCHECK_NE(next_state_, STATE_NONE);
  221. DCHECK_NE(next_state_, STATE_DONE);
  222. int rv = last_io_result;
  223. do {
  224. State state = next_state_;
  225. next_state_ = STATE_NONE;
  226. switch (state) {
  227. case STATE_GENERATE_AUTH_TOKEN:
  228. DCHECK_EQ(OK, rv);
  229. rv = DoGenerateAuthToken();
  230. break;
  231. case STATE_GENERATE_AUTH_TOKEN_COMPLETE:
  232. rv = DoGenerateAuthTokenComplete(rv);
  233. break;
  234. case STATE_SEND_REQUEST:
  235. DCHECK_EQ(OK, rv);
  236. net_log_.BeginEvent(
  237. NetLogEventType::HTTP_TRANSACTION_TUNNEL_SEND_REQUEST);
  238. rv = DoSendRequest();
  239. break;
  240. case STATE_SEND_REQUEST_COMPLETE:
  241. rv = DoSendRequestComplete(rv);
  242. net_log_.EndEventWithNetErrorCode(
  243. NetLogEventType::HTTP_TRANSACTION_TUNNEL_SEND_REQUEST, rv);
  244. break;
  245. case STATE_READ_HEADERS:
  246. DCHECK_EQ(OK, rv);
  247. net_log_.BeginEvent(
  248. NetLogEventType::HTTP_TRANSACTION_TUNNEL_READ_HEADERS);
  249. rv = DoReadHeaders();
  250. break;
  251. case STATE_READ_HEADERS_COMPLETE:
  252. rv = DoReadHeadersComplete(rv);
  253. net_log_.EndEventWithNetErrorCode(
  254. NetLogEventType::HTTP_TRANSACTION_TUNNEL_READ_HEADERS, rv);
  255. break;
  256. case STATE_DRAIN_BODY:
  257. DCHECK_EQ(OK, rv);
  258. rv = DoDrainBody();
  259. break;
  260. case STATE_DRAIN_BODY_COMPLETE:
  261. rv = DoDrainBodyComplete(rv);
  262. break;
  263. case STATE_DONE:
  264. break;
  265. default:
  266. NOTREACHED() << "bad state";
  267. rv = ERR_UNEXPECTED;
  268. break;
  269. }
  270. } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE &&
  271. next_state_ != STATE_DONE);
  272. return rv;
  273. }
  274. int HttpProxyClientSocket::DoGenerateAuthToken() {
  275. next_state_ = STATE_GENERATE_AUTH_TOKEN_COMPLETE;
  276. return auth_->MaybeGenerateAuthToken(&request_, io_callback_, net_log_);
  277. }
  278. int HttpProxyClientSocket::DoGenerateAuthTokenComplete(int result) {
  279. DCHECK_NE(ERR_IO_PENDING, result);
  280. if (result == OK)
  281. next_state_ = STATE_SEND_REQUEST;
  282. return result;
  283. }
  284. int HttpProxyClientSocket::DoSendRequest() {
  285. next_state_ = STATE_SEND_REQUEST_COMPLETE;
  286. // This is constructed lazily (instead of within our Start method), so that
  287. // we have proxy info available.
  288. if (request_line_.empty()) {
  289. DCHECK(request_headers_.IsEmpty());
  290. HttpRequestHeaders extra_headers;
  291. if (auth_->HaveAuth())
  292. auth_->AddAuthorizationHeader(&extra_headers);
  293. // AddAuthorizationHeader() might not have added the header even if
  294. // HaveAuth().
  295. response_.did_use_http_auth =
  296. extra_headers.HasHeader(HttpRequestHeaders::kProxyAuthorization);
  297. if (proxy_delegate_) {
  298. HttpRequestHeaders proxy_delegate_headers;
  299. proxy_delegate_->OnBeforeTunnelRequest(proxy_server_,
  300. &proxy_delegate_headers);
  301. extra_headers.MergeFrom(proxy_delegate_headers);
  302. }
  303. std::string user_agent;
  304. if (!request_.extra_headers.GetHeader(HttpRequestHeaders::kUserAgent,
  305. &user_agent)) {
  306. user_agent.clear();
  307. }
  308. BuildTunnelRequest(endpoint_, extra_headers, user_agent, &request_line_,
  309. &request_headers_);
  310. NetLogRequestHeaders(net_log_,
  311. NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
  312. request_line_, &request_headers_);
  313. }
  314. parser_buf_ = base::MakeRefCounted<GrowableIOBuffer>();
  315. http_stream_parser_ = std::make_unique<HttpStreamParser>(
  316. socket_.get(), is_reused_, &request_, parser_buf_.get(), net_log_);
  317. return http_stream_parser_->SendRequest(request_line_, request_headers_,
  318. traffic_annotation_, &response_,
  319. io_callback_);
  320. }
  321. int HttpProxyClientSocket::DoSendRequestComplete(int result) {
  322. if (result < 0)
  323. return result;
  324. next_state_ = STATE_READ_HEADERS;
  325. return OK;
  326. }
  327. int HttpProxyClientSocket::DoReadHeaders() {
  328. next_state_ = STATE_READ_HEADERS_COMPLETE;
  329. return http_stream_parser_->ReadResponseHeaders(io_callback_);
  330. }
  331. int HttpProxyClientSocket::DoReadHeadersComplete(int result) {
  332. if (result < 0)
  333. return result;
  334. // Require the "HTTP/1.x" status line for SSL CONNECT.
  335. if (response_.headers->GetHttpVersion() < HttpVersion(1, 0))
  336. return ERR_TUNNEL_CONNECTION_FAILED;
  337. NetLogResponseHeaders(
  338. net_log_, NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
  339. response_.headers.get());
  340. if (proxy_delegate_) {
  341. int rv = proxy_delegate_->OnTunnelHeadersReceived(proxy_server_,
  342. *response_.headers);
  343. if (rv != OK) {
  344. DCHECK_NE(ERR_IO_PENDING, rv);
  345. return rv;
  346. }
  347. }
  348. switch (response_.headers->response_code()) {
  349. case 200: // OK
  350. if (http_stream_parser_->IsMoreDataBuffered())
  351. // The proxy sent extraneous data after the headers.
  352. return ERR_TUNNEL_CONNECTION_FAILED;
  353. next_state_ = STATE_DONE;
  354. return OK;
  355. // We aren't able to CONNECT to the remote host through the proxy. We
  356. // need to be very suspicious about the response because an active network
  357. // attacker can force us into this state by masquerading as the proxy.
  358. // The only safe thing to do here is to fail the connection because our
  359. // client is expecting an SSL protected response.
  360. // See http://crbug.com/7338.
  361. case 407: // Proxy Authentication Required
  362. // We need this status code to allow proxy authentication. Our
  363. // authentication code is smart enough to avoid being tricked by an
  364. // active network attacker.
  365. // The next state is intentionally not set as it should be STATE_NONE;
  366. SanitizeProxyAuth(response_);
  367. return HandleProxyAuthChallenge(auth_.get(), &response_, net_log_);
  368. default:
  369. // Ignore response to avoid letting the proxy impersonate the target
  370. // server. (See http://crbug.com/137891.)
  371. // We lose something by doing this. We have seen proxy 403, 404, and
  372. // 501 response bodies that contain a useful error message. For
  373. // example, Squid uses a 404 response to report the DNS error: "The
  374. // domain name does not exist."
  375. return ERR_TUNNEL_CONNECTION_FAILED;
  376. }
  377. }
  378. int HttpProxyClientSocket::DoDrainBody() {
  379. DCHECK(drain_buf_.get());
  380. next_state_ = STATE_DRAIN_BODY_COMPLETE;
  381. return http_stream_parser_->ReadResponseBody(
  382. drain_buf_.get(), kDrainBodyBufferSize, io_callback_);
  383. }
  384. int HttpProxyClientSocket::DoDrainBodyComplete(int result) {
  385. if (result < 0)
  386. return ERR_UNABLE_TO_REUSE_CONNECTION_FOR_PROXY_AUTH;
  387. if (!http_stream_parser_->IsResponseBodyComplete()) {
  388. // Keep draining.
  389. next_state_ = STATE_DRAIN_BODY;
  390. return OK;
  391. }
  392. return DidDrainBodyForAuthRestart();
  393. }
  394. bool HttpProxyClientSocket::CheckDone() {
  395. if (next_state_ != STATE_DONE) {
  396. // We're trying to read the body of the response but we're still trying
  397. // to establish an SSL tunnel through the proxy. We can't read these
  398. // bytes when establishing a tunnel because they might be controlled by
  399. // an active network attacker. We don't worry about this for HTTP
  400. // because an active network attacker can already control HTTP sessions.
  401. // We reach this case when the user cancels a 407 proxy auth prompt.
  402. // See http://crbug.com/8473.
  403. DCHECK_EQ(407, response_.headers->response_code());
  404. return false;
  405. }
  406. return true;
  407. }
  408. //----------------------------------------------------------------
  409. } // namespace net