From 307b1987004ad559ca3f98585030723e1cf1d1a7 Mon Sep 17 00:00:00 2001 From: Taylor `Riastradh' Campbell Date: Thu, 26 Jul 2018 18:14:45 +0000 Subject: [PATCH 1/2] Merge muon socks5 auth changes. --- chromium_src/net/base/host_port_pair_auth.cc | 50 ++++++ chromium_src/net/base/url_auth_util.cc | 92 +++++++++++ chromium_src/net/base/url_auth_util.h | 19 +++ .../net/socket/socks5_client_socket_auth.cc | 149 ++++++++++++++++++ .../net/socket/socks5_client_socket_auth.h | 46 ++++++ patches/net-BUILD.gn.patch | 14 ++ patches/net-base-host_port_pair.cc.patch | 31 ++++ patches/net-base-host_port_pair.h.patch | 48 ++++++ patches/net-base-proxy_server.cc.patch | 21 +++ .../net-log-net_log_event_type_list.h.patch | 17 ++ .../net-socket-socks5_client_socket.cc.patch | 73 +++++++++ .../net-socket-socks5_client_socket.h.patch | 42 +++++ ...t-socket-socks_client_socket_pool.cc.patch | 28 ++++ 13 files changed, 630 insertions(+) create mode 100644 chromium_src/net/base/host_port_pair_auth.cc create mode 100644 chromium_src/net/base/url_auth_util.cc create mode 100644 chromium_src/net/base/url_auth_util.h create mode 100644 chromium_src/net/socket/socks5_client_socket_auth.cc create mode 100644 chromium_src/net/socket/socks5_client_socket_auth.h create mode 100644 patches/net-BUILD.gn.patch create mode 100644 patches/net-base-host_port_pair.cc.patch create mode 100644 patches/net-base-host_port_pair.h.patch create mode 100644 patches/net-base-proxy_server.cc.patch create mode 100644 patches/net-log-net_log_event_type_list.h.patch create mode 100644 patches/net-socket-socks5_client_socket.cc.patch create mode 100644 patches/net-socket-socks5_client_socket.h.patch create mode 100644 patches/net-socket-socks_client_socket_pool.cc.patch diff --git a/chromium_src/net/base/host_port_pair_auth.cc b/chromium_src/net/base/host_port_pair_auth.cc new file mode 100644 index 000000000000..c63e993e6876 --- /dev/null +++ b/chromium_src/net/base/host_port_pair_auth.cc @@ -0,0 +1,50 @@ +// Copyright 2017 The Brave 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 "net/base/host_port_pair.h" + +#include "base/strings/string_number_conversions.h" + +namespace net { + +HostPortPair::HostPortPair(const std::string& username, + const std::string& password, + const std::string& in_host, uint16_t in_port) + : username_(username), password_(password), + host_(in_host), port_(in_port) { +} + +HostPortPair::HostPortPair(const std::string& up_host, uint16_t in_port) + : port_(in_port) { + std::string::const_iterator begin = up_host.begin(); + std::string::const_iterator end = up_host.end(); + std::string::const_iterator at = std::find(begin, end, '@'); + if (at == end) { + host_ = up_host; + } else { + std::string::const_iterator colon = std::find(begin, at, ':'); + username_ = std::string(begin, colon); + if (colon != at) + password_ = std::string(colon + 1, at); + host_ = std::string(at + 1, end); + } +} + +std::string HostPortPair::ToString() const { + std::string ret; + if (username_.size() != 0 || password_.size() != 0) { + ret += username_; + if (password_.size() != 0) { + ret += ':'; + ret += password_; + } + ret += '@'; + } + ret += HostForURL(); + ret += ':'; + ret += base::UintToString(port_); + return ret; +} + +} // namespace net diff --git a/chromium_src/net/base/url_auth_util.cc b/chromium_src/net/base/url_auth_util.cc new file mode 100644 index 000000000000..0da7a49c2a7f --- /dev/null +++ b/chromium_src/net/base/url_auth_util.cc @@ -0,0 +1,92 @@ +// Copyright 2013 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 +#include + +#include "base/strings/string_piece.h" +#include "net/base/url_auth_util.h" +#include "url/third_party/mozilla/url_parse.h" +#include "url/url_canon_ip.h" + +namespace net { + +// Copypasta of ParseHostAndPort that extracts the username and +// password instead of rejecting them. +bool ParseAuthHostAndPort(base::StringPiece input, + std::string* up_host_ret, + int* port) { + if (input.empty()) + return false; + + url::Component auth_component(0, input.size()); + url::Component username_component; + url::Component password_component; + url::Component hostname_component; + url::Component port_component; + + url::ParseAuthority(input.data(), auth_component, &username_component, + &password_component, &hostname_component, + &port_component); + + if (!hostname_component.is_nonempty()) + return false; // Failed parsing. + + int parsed_port_number = -1; + if (port_component.is_nonempty()) { + parsed_port_number = url::ParsePort(input.data(), port_component); + + // If parsing failed, port_number will be either PORT_INVALID or + // PORT_UNSPECIFIED, both of which are negative. + if (parsed_port_number < 0) + return false; // Failed parsing the port number. + } + + if (port_component.len == 0) + return false; // Reject inputs like "foo:" + + unsigned char tmp_ipv6_addr[16]; + + // If the hostname starts with a bracket, it is either an IPv6 literal or + // invalid. If it is an IPv6 literal then strip the brackets. + if (hostname_component.len > 0 && input[hostname_component.begin] == '[') { + if (input[hostname_component.end() - 1] == ']' && + url::IPv6AddressToNumber(input.data(), hostname_component, + tmp_ipv6_addr)) { + // Strip the brackets. + hostname_component.begin++; + hostname_component.len -= 2; + } else { + return false; + } + } + + // Reassemble user:pass@host as up_host. + std::string up_host; + if (username_component.is_valid() || password_component.is_valid()) { + if (username_component.is_valid()) { + std::string username(input.data() + username_component.begin, + username_component.len); + up_host += username; + } + if (password_component.is_valid()) { + std::string password(input.data() + password_component.begin, + password_component.len); + up_host += ":"; + up_host += password; + } + up_host += "@"; + } + std::string hostname(input.data() + hostname_component.begin, + hostname_component.len); + up_host += hostname; + + // Pass results back to caller. + *up_host_ret = up_host; + *port = parsed_port_number; + + return true; // Success. +} + +} diff --git a/chromium_src/net/base/url_auth_util.h b/chromium_src/net/base/url_auth_util.h new file mode 100644 index 000000000000..04052397165f --- /dev/null +++ b/chromium_src/net/base/url_auth_util.h @@ -0,0 +1,19 @@ +// Copyright 2013 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. + +#ifndef NET_BASE_URL_AUTH_UTIL_H_ +#define NET_BASE_URL_AUTH_UTIL_H_ + +#include "net/base/net_export.h" + +namespace net { + +NET_EXPORT bool ParseAuthHostAndPort( + base::StringPiece input, + std::string* up_host_ret, + int* port); + +} + +#endif // NET_BASE_URL_AUTH_UTIL_H_ diff --git a/chromium_src/net/socket/socks5_client_socket_auth.cc b/chromium_src/net/socket/socks5_client_socket_auth.cc new file mode 100644 index 000000000000..cd3b64e0843a --- /dev/null +++ b/chromium_src/net/socket/socks5_client_socket_auth.cc @@ -0,0 +1,149 @@ +// Copyright 2017 The Brave 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 "net/base/io_buffer.h" +#include "net/socket/socks5_client_socket_auth.h" + +namespace net { + +SOCKS5ClientSocketAuth::SOCKS5ClientSocketAuth( + std::unique_ptr transport_socket, + const HostResolver::RequestInfo& req_info, + const NetworkTrafficAnnotationTag& traffic_annotation, + const HostPortPair& proxy_host_port) + : SOCKS5ClientSocket(std::move(transport_socket), req_info, + traffic_annotation), + proxy_host_port_(proxy_host_port), + next_state_(STATE_INIT_WRITE) { +} + +SOCKS5ClientSocketAuth::~SOCKS5ClientSocketAuth() = default; + +const std::string& SOCKS5ClientSocketAuth::username() { + return proxy_host_port_.username(); +} + +const std::string& SOCKS5ClientSocketAuth::password() { + return proxy_host_port_.password(); +} + +bool SOCKS5ClientSocketAuth::do_auth() { + return username().size() != 0 || password().size() != 0; +} + +uint8_t SOCKS5ClientSocketAuth::auth_method() { + if (!do_auth()) + return 0x00; + return 0x02; +} + +static const size_t kSOCKSAuthUsernamePasswordResponseLen = 2; + +int SOCKS5ClientSocketAuth::Authenticate( + int rv, ClientSocketHandle& transport, NetLogWithSource& net_log, + CompletionCallback& callback) { + if (!do_auth()) { + DCHECK_EQ(OK, rv); + return OK; + } + do { + switch (next_state_) { + case STATE_INIT_WRITE: { + DCHECK_EQ(OK, rv); + // Initialize the buffer with  + // 0x01, usernamelen, username, passwordlen, password + size_t usernamelen = username().size(); + size_t passwordlen = password().size(); + buffer_ = std::string(1 + 1 + usernamelen + 1 + passwordlen, 0); + buffer_[0] = 0x01; + buffer_[1] = usernamelen; + buffer_.replace(2, usernamelen, username()); + buffer_[2 + usernamelen] = passwordlen; + buffer_.replace(2 + usernamelen + 1, passwordlen, password()); + DCHECK_EQ(buffer_.size(), 2 + usernamelen + 1 + passwordlen); + buffer_left_ = buffer_.size(); + next_state_ = STATE_WRITE; + rv = OK; + break; + } + case STATE_WRITE: + DCHECK_EQ(OK, rv); + DCHECK_LT(0u, buffer_left_); + iobuf_ = new IOBuffer(buffer_left_); + memcpy(iobuf_->data(), + &buffer_.data()[buffer_.size() - buffer_left_], + buffer_left_); + next_state_ = STATE_WRITE_COMPLETE; + net_log.BeginEvent(NetLogEventType::SOCKS5_AUTH_WRITE); + rv = transport.socket()->Write(iobuf_.get(), buffer_left_, callback, + traffic_annotation_); + break; + + case STATE_WRITE_COMPLETE: + // TODO(riastradh): Zero iobuf? Zero buffer? + net_log.EndEventWithNetErrorCode(NetLogEventType::SOCKS5_AUTH_WRITE, + std::max(rv, 0)); + if (rv < 0) { + next_state_ = STATE_BAD; + return rv; + } + DCHECK_LE(static_cast(rv), buffer_left_); + buffer_left_ -= rv; + next_state_ = (buffer_left_ == 0 ? STATE_INIT_READ : STATE_WRITE); + rv = OK; + break; + + case STATE_INIT_READ: + DCHECK_EQ(OK, rv); + buffer_.clear(); + buffer_left_ = kSOCKSAuthUsernamePasswordResponseLen; + iobuf_ = new IOBuffer(buffer_left_); + next_state_ = STATE_READ; + rv = OK; + break; + + case STATE_READ: + DCHECK_EQ(OK, rv); + iobuf_ = new IOBuffer(buffer_left_); + next_state_ = STATE_READ_COMPLETE; + net_log.BeginEvent(NetLogEventType::SOCKS5_AUTH_READ); + rv = transport.socket()->Read(iobuf_.get(), buffer_left_, callback); + break; + + case STATE_READ_COMPLETE: + net_log.EndEventWithNetErrorCode(NetLogEventType::SOCKS5_AUTH_READ, + std::max(rv, 0)); + if (rv < 0) { + next_state_ = STATE_BAD; + return rv; + } + DCHECK_LE(static_cast(rv), buffer_left_); + buffer_.append(iobuf_->data(), rv); + buffer_left_ -= rv; + next_state_ = (buffer_left_ == 0 ? STATE_DONE : STATE_READ); + rv = OK; + break; + + case STATE_DONE: { + DCHECK_EQ(OK, rv); + DCHECK_EQ(buffer_.size(), kSOCKSAuthUsernamePasswordResponseLen); + static_assert(kSOCKSAuthUsernamePasswordResponseLen == 2, "bad size"); + uint8_t ver = buffer_[0]; + uint8_t status = buffer_[1]; + next_state_ = STATE_BAD; // Caller had better stop here. + if (ver != 0x01 || status != 0x00) + return ERR_FAILED; + return OK; + } + + case STATE_BAD: + default: + NOTREACHED() << "bad state"; + return ERR_UNEXPECTED; + } + } while (rv != ERR_IO_PENDING); + return rv; +} + +} // namespace net diff --git a/chromium_src/net/socket/socks5_client_socket_auth.h b/chromium_src/net/socket/socks5_client_socket_auth.h new file mode 100644 index 000000000000..f1c176f7e8c3 --- /dev/null +++ b/chromium_src/net/socket/socks5_client_socket_auth.h @@ -0,0 +1,46 @@ +// Copyright 2017 The Brave Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_SOCKET_SOCKS5_CLIENT_SOCKET_AUTH_H_ +#define NET_SOCKET_SOCKS5_CLIENT_SOCKET_AUTH_H_ + +#include "net/socket/socks5_client_socket.h" + +namespace net { + +class NET_EXPORT_PRIVATE SOCKS5ClientSocketAuth : public SOCKS5ClientSocket { + public: + SOCKS5ClientSocketAuth(std::unique_ptr transport_socket, + const HostResolver::RequestInfo& req_info, + const NetworkTrafficAnnotationTag& traffic_annotation, + const HostPortPair& proxy_host_port); + ~SOCKS5ClientSocketAuth() override; + private: + bool do_auth(); + const std::string& username(); + const std::string& password(); + uint8_t auth_method() override; + int Authenticate(int rv, + ClientSocketHandle& transport, NetLogWithSource& net_log, + CompletionCallback& callback) override; + const HostPortPair proxy_host_port_; + enum { + STATE_INIT_WRITE = 0, + STATE_WRITE, + STATE_WRITE_COMPLETE, + STATE_INIT_READ, + STATE_READ, + STATE_READ_COMPLETE, + STATE_DONE, + STATE_BAD, + } next_state_; + scoped_refptr iobuf_; + std::string buffer_; + size_t buffer_left_; + DISALLOW_COPY_AND_ASSIGN(SOCKS5ClientSocketAuth); +}; + +} // namespace net + +#endif // NET_SOCKET_SOCKS5_CLIENT_SOCKET_AUTH_H_ diff --git a/patches/net-BUILD.gn.patch b/patches/net-BUILD.gn.patch new file mode 100644 index 000000000000..7f4c9289c90d --- /dev/null +++ b/patches/net-BUILD.gn.patch @@ -0,0 +1,14 @@ +diff --git a/net/BUILD.gn b/net/BUILD.gn +index 9d59189d80aea8f99b73020f36a578a96667af37..d5aa98b8f2f44f6acec58c124c262bd1ddcabe31 100644 +--- a/net/BUILD.gn ++++ b/net/BUILD.gn +@@ -355,6 +355,9 @@ component("net") { + "ssl/token_binding.h", + "third_party/quic/core/quic_error_codes.cc", + "third_party/quic/core/quic_error_codes.h", ++ "//brave/chromium_src/net/base/host_port_pair_auth.cc", ++ "//brave/chromium_src/net/base/url_auth_util.cc", ++ "//brave/chromium_src/net/socket/socks5_client_socket_auth.cc", + ] + net_unfiltered_sources = [] + diff --git a/patches/net-base-host_port_pair.cc.patch b/patches/net-base-host_port_pair.cc.patch new file mode 100644 index 000000000000..4ad0e33b154e --- /dev/null +++ b/patches/net-base-host_port_pair.cc.patch @@ -0,0 +1,31 @@ +diff --git a/net/base/host_port_pair.cc b/net/base/host_port_pair.cc +index ec8248449dbcd4156e361fcc8781ce0712f26a02..77f5a3653083625f8043147d42297dba05bb79a9 100644 +--- a/net/base/host_port_pair.cc ++++ b/net/base/host_port_pair.cc +@@ -18,9 +18,11 @@ + namespace net { + + HostPortPair::HostPortPair() : port_(0) {} ++#if 0 // brave override + HostPortPair::HostPortPair(const std::string& in_host, uint16_t in_port) + : host_(in_host), port_(in_port) { + } ++#endif + + // static + HostPortPair HostPortPair::FromURL(const GURL& url) { +@@ -50,12 +52,14 @@ HostPortPair HostPortPair::FromString(const std::string& str) { + return host_port_pair; + } + ++#if 0 // brave override + std::string HostPortPair::ToString() const { + std::string ret(HostForURL()); + ret += ':'; + ret += base::UintToString(port_); + return ret; + } ++#endif + + std::string HostPortPair::HostForURL() const { + // TODO(rtenneti): Add support for |host| to have '\0'. diff --git a/patches/net-base-host_port_pair.h.patch b/patches/net-base-host_port_pair.h.patch new file mode 100644 index 000000000000..ff97cfd6ac81 --- /dev/null +++ b/patches/net-base-host_port_pair.h.patch @@ -0,0 +1,48 @@ +diff --git a/net/base/host_port_pair.h b/net/base/host_port_pair.h +index a5ee6bda3ff542624b484b7a11811b708fec3e11..0d635e6dd1242382bd5845f6cb7674dc32c58b5d 100644 +--- a/net/base/host_port_pair.h ++++ b/net/base/host_port_pair.h +@@ -23,6 +23,8 @@ class NET_EXPORT HostPortPair { + HostPortPair(); + // If |in_host| represents an IPv6 address, it should not bracket the address. + HostPortPair(const std::string& in_host, uint16_t in_port); ++ HostPortPair(const std::string& username, const std::string& password, ++ const std::string& in_host, uint16_t in_port); + + // Creates a HostPortPair for the origin of |url|. + static HostPortPair FromURL(const GURL& url); +@@ -37,18 +39,23 @@ class NET_EXPORT HostPortPair { + // TODO(willchan): Define a functor instead. + // Comparator function so this can be placed in a std::map. + bool operator<(const HostPortPair& other) const { +- return std::tie(port_, host_) < std::tie(other.port_, other.host_); ++ return std::tie(port_, host_, username_, password_) < ++ std::tie(other.port_, other.host_, other.username_, other.password_); + } + + // Equality test of contents. (Probably another violation of style guide). + bool Equals(const HostPortPair& other) const { +- return host_ == other.host_ && port_ == other.port_; ++ return username_ == other.username_ && password_ == other.password_ && ++ host_ == other.host_ && port_ == other.port_; + } + + bool IsEmpty() const { + return host_.empty() && port_ == 0; + } + ++ const std::string& username() const { return username_; } ++ const std::string& password() const { return password_; } ++ + const std::string& host() const { + return host_; + } +@@ -72,6 +79,8 @@ class NET_EXPORT HostPortPair { + size_t EstimateMemoryUsage() const; + + private: ++ std::string username_; ++ std::string password_; + // If |host_| represents an IPv6 address, this string will not contain + // brackets around the address. + std::string host_; diff --git a/patches/net-base-proxy_server.cc.patch b/patches/net-base-proxy_server.cc.patch new file mode 100644 index 000000000000..6eeed424f4a1 --- /dev/null +++ b/patches/net-base-proxy_server.cc.patch @@ -0,0 +1,21 @@ +diff --git a/net/base/proxy_server.cc b/net/base/proxy_server.cc +index da31a40fbe8dc454dd24cb368c3af7d0b8c3506d..624d663b070e0eaf96a420c52a529525d7b7fed3 100644 +--- a/net/base/proxy_server.cc ++++ b/net/base/proxy_server.cc +@@ -8,6 +8,7 @@ + + #include "base/strings/string_util.h" + #include "base/trace_event/memory_usage_estimator.h" ++#include "net/base/url_auth_util.h" + #include "net/base/url_util.h" + #include "net/http/http_util.h" + +@@ -226,7 +227,7 @@ ProxyServer ProxyServer::FromSchemeHostAndPort( + std::string host; + int port = -1; + // If the scheme has a host/port, parse it. +- bool ok = ParseHostAndPort(host_and_port, &host, &port); ++ bool ok = ParseAuthHostAndPort(host_and_port, &host, &port); + if (!ok) + return ProxyServer(); // Invalid -- failed parsing [":"] + diff --git a/patches/net-log-net_log_event_type_list.h.patch b/patches/net-log-net_log_event_type_list.h.patch new file mode 100644 index 000000000000..a00613f2dd11 --- /dev/null +++ b/patches/net-log-net_log_event_type_list.h.patch @@ -0,0 +1,17 @@ +diff --git a/net/log/net_log_event_type_list.h b/net/log/net_log_event_type_list.h +index 79f3590df116ba98f0778a5a3f523d311952d86c..d700eb8572eba2361dee83fe0d097d0df2043a3e 100644 +--- a/net/log/net_log_event_type_list.h ++++ b/net/log/net_log_event_type_list.h +@@ -2113,6 +2113,12 @@ EVENT_TYPE(SOCKS5_GREET_WRITE) + // The time spent waiting for the "greeting" response from the SOCKS server. + EVENT_TYPE(SOCKS5_GREET_READ) + ++// The time spent sending authentication to the SOCKS server ++EVENT_TYPE(SOCKS5_AUTH_WRITE) ++ ++// The time spent waiting for the authentication response from the SOCKS server ++EVENT_TYPE(SOCKS5_AUTH_READ) ++ + // The time spent sending the CONNECT request to the SOCKS server. + EVENT_TYPE(SOCKS5_HANDSHAKE_WRITE) + diff --git a/patches/net-socket-socks5_client_socket.cc.patch b/patches/net-socket-socks5_client_socket.cc.patch new file mode 100644 index 000000000000..4845082df890 --- /dev/null +++ b/patches/net-socket-socks5_client_socket.cc.patch @@ -0,0 +1,73 @@ +diff --git a/net/socket/socks5_client_socket.cc b/net/socket/socks5_client_socket.cc +index 784bcef533288d1eced7daa5b470b8d99550cd98..490766ba173a5f15f618a8fcdd0de8bfa8c5328d 100644 +--- a/net/socket/socks5_client_socket.cc ++++ b/net/socket/socks5_client_socket.cc +@@ -241,6 +241,9 @@ int SOCKS5ClientSocket::DoLoop(int last_io_result) { + net_log_.EndEventWithNetErrorCode(NetLogEventType::SOCKS5_GREET_READ, + rv); + break; ++ case STATE_AUTH: ++ rv = DoAuth(rv); ++ break; + case STATE_HANDSHAKE_WRITE: + DCHECK_EQ(OK, rv); + net_log_.BeginEvent(NetLogEventType::SOCKS5_HANDSHAKE_WRITE); +@@ -270,8 +273,6 @@ int SOCKS5ClientSocket::DoLoop(int last_io_result) { + return rv; + } + +-const char kSOCKS5GreetWriteData[] = { 0x05, 0x01, 0x00 }; // no authentication +- + int SOCKS5ClientSocket::DoGreetWrite() { + // Since we only have 1 byte to send the hostname length in, if the + // URL has a hostname longer than 255 characters we can't send it. +@@ -281,8 +282,12 @@ int SOCKS5ClientSocket::DoGreetWrite() { + } + + if (buffer_.empty()) { +- buffer_ = std::string(kSOCKS5GreetWriteData, +- arraysize(kSOCKS5GreetWriteData)); ++ const char greeting[] = { ++ 0x05, // SOCKS version ++ 0x01, // number of authentication methods ++ auth_method(), ++ }; ++ buffer_ = std::string(greeting, sizeof(greeting)); + bytes_sent_ = 0; + } + +@@ -341,14 +346,32 @@ int SOCKS5ClientSocket::DoGreetReadComplete(int result) { + NetLog::IntCallback("version", buffer_[0])); + return ERR_SOCKS_CONNECTION_FAILED; + } +- if (buffer_[1] != 0x00) { ++ if (buffer_[1] != auth_method()) { + net_log_.AddEvent(NetLogEventType::SOCKS_UNEXPECTED_AUTH, + NetLog::IntCallback("method", buffer_[1])); + return ERR_SOCKS_CONNECTION_FAILED; + } + + buffer_.clear(); +- next_state_ = STATE_HANDSHAKE_WRITE; ++ next_state_ = STATE_AUTH; ++ return OK; ++} ++ ++int SOCKS5ClientSocket::DoAuth(int rv) { ++ rv = Authenticate(rv, *transport_, net_log_, io_callback_); ++ next_state_ = (rv == OK ? STATE_HANDSHAKE_WRITE : STATE_AUTH); ++ return rv; ++} ++ ++uint8_t SOCKS5ClientSocket::auth_method() { ++ return 0x00; ++} ++ ++int SOCKS5ClientSocket::Authenticate(int rv, ++ ClientSocketHandle& socket, ++ NetLogWithSource& net_log, ++ CompletionCallback& callback) { ++ DCHECK_EQ(OK, rv); + return OK; + } + diff --git a/patches/net-socket-socks5_client_socket.h.patch b/patches/net-socket-socks5_client_socket.h.patch new file mode 100644 index 000000000000..7a903ecdfbc2 --- /dev/null +++ b/patches/net-socket-socks5_client_socket.h.patch @@ -0,0 +1,42 @@ +diff --git a/net/socket/socks5_client_socket.h b/net/socket/socks5_client_socket.h +index b6e59ae6b07823087e44ffc40fb7d2d54c6a7c3e..98ee500609b2a72970387324a09da102b7230c14 100644 +--- a/net/socket/socks5_client_socket.h ++++ b/net/socket/socks5_client_socket.h +@@ -20,6 +20,7 @@ + #include "net/base/net_export.h" + #include "net/dns/host_resolver.h" + #include "net/log/net_log_with_source.h" ++#include "net/socket/socks_client_socket_pool.h" + #include "net/socket/stream_socket.h" + #include "net/traffic_annotation/network_traffic_annotation.h" + #include "url/gurl.h" +@@ -79,11 +80,14 @@ class NET_EXPORT_PRIVATE SOCKS5ClientSocket : public StreamSocket { + int GetLocalAddress(IPEndPoint* address) const override; + + private: ++ friend class SOCKS5ClientSocketAuth; + enum State { + STATE_GREET_WRITE, + STATE_GREET_WRITE_COMPLETE, + STATE_GREET_READ, + STATE_GREET_READ_COMPLETE, ++ STATE_AUTH, ++ STATE_AUTH_COMPLETE, + STATE_HANDSHAKE_WRITE, + STATE_HANDSHAKE_WRITE_COMPLETE, + STATE_HANDSHAKE_READ, +@@ -118,6 +122,14 @@ class NET_EXPORT_PRIVATE SOCKS5ClientSocket : public StreamSocket { + int DoGreetReadComplete(int result); + int DoGreetWrite(); + int DoGreetWriteComplete(int result); ++ int DoAuth(int result); ++ ++ // Authentication hooks. ++ virtual uint8_t auth_method(); ++ virtual int Authenticate(int result, ++ ClientSocketHandle& socket, ++ NetLogWithSource& net_log, ++ CompletionCallback& callback); + + // Writes the SOCKS handshake buffer into |handshake| + // and return OK on success. diff --git a/patches/net-socket-socks_client_socket_pool.cc.patch b/patches/net-socket-socks_client_socket_pool.cc.patch new file mode 100644 index 000000000000..4243af2e45a4 --- /dev/null +++ b/patches/net-socket-socks_client_socket_pool.cc.patch @@ -0,0 +1,28 @@ +diff --git a/net/socket/socks_client_socket_pool.cc b/net/socket/socks_client_socket_pool.cc +index 2dad2733466a194da7898919604ebf4dcb463d74..30cb9d1955a034d2a6bcec97a2a286589881f310 100644 +--- a/net/socket/socks_client_socket_pool.cc ++++ b/net/socket/socks_client_socket_pool.cc +@@ -16,7 +16,7 @@ + #include "net/socket/client_socket_factory.h" + #include "net/socket/client_socket_handle.h" + #include "net/socket/client_socket_pool_base.h" +-#include "net/socket/socks5_client_socket.h" ++#include "net/socket/socks5_client_socket_auth.h" + #include "net/socket/socks_client_socket.h" + #include "net/socket/transport_client_socket_pool.h" + +@@ -149,9 +149,11 @@ int SOCKSConnectJob::DoSOCKSConnect() { + + // Add a SOCKS connection on top of the tcp socket. + if (socks_params_->is_socks_v5()) { +- socket_.reset(new SOCKS5ClientSocket(std::move(transport_socket_handle_), +- socks_params_->destination(), +- socks_params_->traffic_annotation())); ++ socket_.reset(new SOCKS5ClientSocketAuth( ++ std::move(transport_socket_handle_), ++ socks_params_->destination(), ++ socks_params_->traffic_annotation(), ++ socks_params_->transport_params()->destination().host_port_pair())); + } else { + socket_.reset(new SOCKSClientSocket( + std::move(transport_socket_handle_), socks_params_->destination(), From 6d02981fc644bffe8b6aa3edd4f082b7385e6ed7 Mon Sep 17 00:00:00 2001 From: Taylor `Riastradh' Campbell Date: Thu, 26 Jul 2018 18:24:47 +0000 Subject: [PATCH 2/2] Rework socks5 authentication. - Work around Chromium's new in-line constructor size limits. - Get base::StringPiece forward declaration in url_auth_util.h. - Use `#if !defined(BRAVE_CHROMIUM_BUILD)', not #if 0. - Override and include, rather than patch, net_log_event_type_list.h. - Override and include host_port_pair.cc to reduce BUILD.gn diffs. - Override and include url_util.cc rather than add url_auth_util.cc. - Override and include socks5_client_socket.cc. - Don't patch HostPortPair(host, port) constructor. Instead, use a different constructor in proxy_server.cc. This adds another patch to our maintenance burden, but it avoids changing the semantics of (and adding parsing overhead to) the constructor that is used in a bazillion places all over Chromium. --- ...st_port_pair_auth.cc => host_port_pair.cc} | 23 +++--------- .../base/{url_auth_util.cc => url_util.cc} | 37 +++++++------------ .../net/base/{url_auth_util.h => url_util.h} | 13 +++++-- .../net/log/net_log_event_type_list.h | 11 ++++++ ...socket_auth.cc => socks5_client_socket.cc} | 6 ++- ...t_socket_auth.h => socks5_client_socket.h} | 10 ++--- patches/net-BUILD.gn.patch | 14 ------- patches/net-base-host_port_pair.cc.patch | 18 ++------- patches/net-base-host_port_pair.h.patch | 17 ++++++--- patches/net-base-proxy_server.cc.patch | 28 +++++++++----- .../net-log-net_log_event_type_list.h.patch | 17 --------- ...t-socket-socks_client_socket_pool.cc.patch | 11 +----- 12 files changed, 82 insertions(+), 123 deletions(-) rename chromium_src/net/base/{host_port_pair_auth.cc => host_port_pair.cc} (58%) rename chromium_src/net/base/{url_auth_util.cc => url_util.cc} (72%) rename chromium_src/net/base/{url_auth_util.h => url_util.h} (51%) create mode 100644 chromium_src/net/log/net_log_event_type_list.h rename chromium_src/net/socket/{socks5_client_socket_auth.cc => socks5_client_socket.cc} (96%) rename chromium_src/net/socket/{socks5_client_socket_auth.h => socks5_client_socket.h} (81%) delete mode 100644 patches/net-BUILD.gn.patch delete mode 100644 patches/net-log-net_log_event_type_list.h.patch diff --git a/chromium_src/net/base/host_port_pair_auth.cc b/chromium_src/net/base/host_port_pair.cc similarity index 58% rename from chromium_src/net/base/host_port_pair_auth.cc rename to chromium_src/net/base/host_port_pair.cc index c63e993e6876..fb56a11f3c0c 100644 --- a/chromium_src/net/base/host_port_pair_auth.cc +++ b/chromium_src/net/base/host_port_pair.cc @@ -1,13 +1,18 @@ -// Copyright 2017 The Brave Authors. All rights reserved. +// Copyright 2018 The Brave 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 "../../../../net/base/host_port_pair.cc" + #include "net/base/host_port_pair.h" #include "base/strings/string_number_conversions.h" namespace net { +HostPortPair::~HostPortPair() = default; +HostPortPair::HostPortPair(const HostPortPair& host_port) = default; + HostPortPair::HostPortPair(const std::string& username, const std::string& password, const std::string& in_host, uint16_t in_port) @@ -15,22 +20,6 @@ HostPortPair::HostPortPair(const std::string& username, host_(in_host), port_(in_port) { } -HostPortPair::HostPortPair(const std::string& up_host, uint16_t in_port) - : port_(in_port) { - std::string::const_iterator begin = up_host.begin(); - std::string::const_iterator end = up_host.end(); - std::string::const_iterator at = std::find(begin, end, '@'); - if (at == end) { - host_ = up_host; - } else { - std::string::const_iterator colon = std::find(begin, at, ':'); - username_ = std::string(begin, colon); - if (colon != at) - password_ = std::string(colon + 1, at); - host_ = std::string(at + 1, end); - } -} - std::string HostPortPair::ToString() const { std::string ret; if (username_.size() != 0 || password_.size() != 0) { diff --git a/chromium_src/net/base/url_auth_util.cc b/chromium_src/net/base/url_util.cc similarity index 72% rename from chromium_src/net/base/url_auth_util.cc rename to chromium_src/net/base/url_util.cc index 0da7a49c2a7f..bd7f498930d5 100644 --- a/chromium_src/net/base/url_auth_util.cc +++ b/chromium_src/net/base/url_util.cc @@ -2,11 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "../../../../net/base/url_util.cc" + #include #include #include "base/strings/string_piece.h" -#include "net/base/url_auth_util.h" #include "url/third_party/mozilla/url_parse.h" #include "url/url_canon_ip.h" @@ -15,7 +16,9 @@ namespace net { // Copypasta of ParseHostAndPort that extracts the username and // password instead of rejecting them. bool ParseAuthHostAndPort(base::StringPiece input, - std::string* up_host_ret, + std::string* username, + std::string* password, + std::string* host, int* port) { if (input.empty()) return false; @@ -62,28 +65,16 @@ bool ParseAuthHostAndPort(base::StringPiece input, } } - // Reassemble user:pass@host as up_host. - std::string up_host; - if (username_component.is_valid() || password_component.is_valid()) { - if (username_component.is_valid()) { - std::string username(input.data() + username_component.begin, - username_component.len); - up_host += username; - } - if (password_component.is_valid()) { - std::string password(input.data() + password_component.begin, - password_component.len); - up_host += ":"; - up_host += password; - } - up_host += "@"; - } - std::string hostname(input.data() + hostname_component.begin, - hostname_component.len); - up_host += hostname; - // Pass results back to caller. - *up_host_ret = up_host; + if (username_component.is_valid()) { + username->assign(input.data() + username_component.begin, + username_component.len); + } + if (password_component.is_valid()) { + password->assign(input.data() + password_component.begin, + password_component.len); + } + host->assign(input.data() + hostname_component.begin, hostname_component.len); *port = parsed_port_number; return true; // Success. diff --git a/chromium_src/net/base/url_auth_util.h b/chromium_src/net/base/url_util.h similarity index 51% rename from chromium_src/net/base/url_auth_util.h rename to chromium_src/net/base/url_util.h index 04052397165f..a120771b03ac 100644 --- a/chromium_src/net/base/url_auth_util.h +++ b/chromium_src/net/base/url_util.h @@ -2,18 +2,23 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef NET_BASE_URL_AUTH_UTIL_H_ -#define NET_BASE_URL_AUTH_UTIL_H_ +#ifndef BRAVE_NET_BASE_URL_AUTH_UTIL_H_ +#define BRAVE_NET_BASE_URL_AUTH_UTIL_H_ +#include "../../../../net/base/url_util.h" + +#include "base/strings/string_piece_forward.h" #include "net/base/net_export.h" namespace net { NET_EXPORT bool ParseAuthHostAndPort( base::StringPiece input, - std::string* up_host_ret, + std::string* username, + std::string* password, + std::string* host, int* port); } -#endif // NET_BASE_URL_AUTH_UTIL_H_ +#endif // BRAVE_NET_BASE_URL_AUTH_UTIL_H_ diff --git a/chromium_src/net/log/net_log_event_type_list.h b/chromium_src/net/log/net_log_event_type_list.h new file mode 100644 index 000000000000..eaefd4834fa5 --- /dev/null +++ b/chromium_src/net/log/net_log_event_type_list.h @@ -0,0 +1,11 @@ +// Copyright 2018 The Brave 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 "../../../../net/log/net_log_event_type_list.h" + +// The time spent sending authentication to the SOCKS server +EVENT_TYPE(SOCKS5_AUTH_WRITE) + +// The time spent waiting for the authentication response from the SOCKS server +EVENT_TYPE(SOCKS5_AUTH_READ) diff --git a/chromium_src/net/socket/socks5_client_socket_auth.cc b/chromium_src/net/socket/socks5_client_socket.cc similarity index 96% rename from chromium_src/net/socket/socks5_client_socket_auth.cc rename to chromium_src/net/socket/socks5_client_socket.cc index cd3b64e0843a..daafad6da40d 100644 --- a/chromium_src/net/socket/socks5_client_socket_auth.cc +++ b/chromium_src/net/socket/socks5_client_socket.cc @@ -1,9 +1,11 @@ -// Copyright 2017 The Brave Authors. All rights reserved. +// Copyright 2018 The Brave 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 "../../../../net/socket/socks5_client_socket.cc" + #include "net/base/io_buffer.h" -#include "net/socket/socks5_client_socket_auth.h" +#include "net/socket/socks5_client_socket.h" namespace net { diff --git a/chromium_src/net/socket/socks5_client_socket_auth.h b/chromium_src/net/socket/socks5_client_socket.h similarity index 81% rename from chromium_src/net/socket/socks5_client_socket_auth.h rename to chromium_src/net/socket/socks5_client_socket.h index f1c176f7e8c3..b2a6a0b4d3fa 100644 --- a/chromium_src/net/socket/socks5_client_socket_auth.h +++ b/chromium_src/net/socket/socks5_client_socket.h @@ -1,11 +1,11 @@ -// Copyright 2017 The Brave Authors. All rights reserved. +// Copyright 2018 The Brave Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef NET_SOCKET_SOCKS5_CLIENT_SOCKET_AUTH_H_ -#define NET_SOCKET_SOCKS5_CLIENT_SOCKET_AUTH_H_ +#ifndef BRAVE_NET_SOCKET_SOCKS5_CLIENT_SOCKET_AUTH_H_ +#define BRAVE_NET_SOCKET_SOCKS5_CLIENT_SOCKET_AUTH_H_ -#include "net/socket/socks5_client_socket.h" +#include "../../../../net/socket/socks5_client_socket.h" namespace net { @@ -43,4 +43,4 @@ class NET_EXPORT_PRIVATE SOCKS5ClientSocketAuth : public SOCKS5ClientSocket { } // namespace net -#endif // NET_SOCKET_SOCKS5_CLIENT_SOCKET_AUTH_H_ +#endif // BRAVE_NET_SOCKET_SOCKS5_CLIENT_SOCKET_AUTH_H_ diff --git a/patches/net-BUILD.gn.patch b/patches/net-BUILD.gn.patch deleted file mode 100644 index 7f4c9289c90d..000000000000 --- a/patches/net-BUILD.gn.patch +++ /dev/null @@ -1,14 +0,0 @@ -diff --git a/net/BUILD.gn b/net/BUILD.gn -index 9d59189d80aea8f99b73020f36a578a96667af37..d5aa98b8f2f44f6acec58c124c262bd1ddcabe31 100644 ---- a/net/BUILD.gn -+++ b/net/BUILD.gn -@@ -355,6 +355,9 @@ component("net") { - "ssl/token_binding.h", - "third_party/quic/core/quic_error_codes.cc", - "third_party/quic/core/quic_error_codes.h", -+ "//brave/chromium_src/net/base/host_port_pair_auth.cc", -+ "//brave/chromium_src/net/base/url_auth_util.cc", -+ "//brave/chromium_src/net/socket/socks5_client_socket_auth.cc", - ] - net_unfiltered_sources = [] - diff --git a/patches/net-base-host_port_pair.cc.patch b/patches/net-base-host_port_pair.cc.patch index 4ad0e33b154e..7af13cb02a1e 100644 --- a/patches/net-base-host_port_pair.cc.patch +++ b/patches/net-base-host_port_pair.cc.patch @@ -1,24 +1,12 @@ diff --git a/net/base/host_port_pair.cc b/net/base/host_port_pair.cc -index ec8248449dbcd4156e361fcc8781ce0712f26a02..77f5a3653083625f8043147d42297dba05bb79a9 100644 +index ec8248449dbcd4156e361fcc8781ce0712f26a02..fd8af49cfa6f41c56b7218a71048dd077e072f6e 100644 --- a/net/base/host_port_pair.cc +++ b/net/base/host_port_pair.cc -@@ -18,9 +18,11 @@ - namespace net { - - HostPortPair::HostPortPair() : port_(0) {} -+#if 0 // brave override - HostPortPair::HostPortPair(const std::string& in_host, uint16_t in_port) - : host_(in_host), port_(in_port) { - } -+#endif - - // static - HostPortPair HostPortPair::FromURL(const GURL& url) { -@@ -50,12 +52,14 @@ HostPortPair HostPortPair::FromString(const std::string& str) { +@@ -50,12 +50,14 @@ HostPortPair HostPortPair::FromString(const std::string& str) { return host_port_pair; } -+#if 0 // brave override ++#if !defined(BRAVE_CHROMIUM_BUILD) std::string HostPortPair::ToString() const { std::string ret(HostForURL()); ret += ':'; diff --git a/patches/net-base-host_port_pair.h.patch b/patches/net-base-host_port_pair.h.patch index ff97cfd6ac81..9210276beafb 100644 --- a/patches/net-base-host_port_pair.h.patch +++ b/patches/net-base-host_port_pair.h.patch @@ -1,17 +1,22 @@ diff --git a/net/base/host_port_pair.h b/net/base/host_port_pair.h -index a5ee6bda3ff542624b484b7a11811b708fec3e11..0d635e6dd1242382bd5845f6cb7674dc32c58b5d 100644 +index a5ee6bda3ff542624b484b7a11811b708fec3e11..084616da28ba3569cc75d1b0fef51a0b89a9f54e 100644 --- a/net/base/host_port_pair.h +++ b/net/base/host_port_pair.h -@@ -23,6 +23,8 @@ class NET_EXPORT HostPortPair { - HostPortPair(); +@@ -24,6 +24,13 @@ class NET_EXPORT HostPortPair { // If |in_host| represents an IPv6 address, it should not bracket the address. HostPortPair(const std::string& in_host, uint16_t in_port); + ++ // Brave addition. Nudges HostPortPair past Chromium's style ++ // threshold for in-line constructors and destructors. + HostPortPair(const std::string& username, const std::string& password, + const std::string& in_host, uint16_t in_port); - ++ ~HostPortPair(); ++ HostPortPair(const HostPortPair&); ++ // Creates a HostPortPair for the origin of |url|. static HostPortPair FromURL(const GURL& url); -@@ -37,18 +39,23 @@ class NET_EXPORT HostPortPair { + +@@ -37,18 +44,23 @@ class NET_EXPORT HostPortPair { // TODO(willchan): Define a functor instead. // Comparator function so this can be placed in a std::map. bool operator<(const HostPortPair& other) const { @@ -37,7 +42,7 @@ index a5ee6bda3ff542624b484b7a11811b708fec3e11..0d635e6dd1242382bd5845f6cb7674dc const std::string& host() const { return host_; } -@@ -72,6 +79,8 @@ class NET_EXPORT HostPortPair { +@@ -72,6 +84,8 @@ class NET_EXPORT HostPortPair { size_t EstimateMemoryUsage() const; private: diff --git a/patches/net-base-proxy_server.cc.patch b/patches/net-base-proxy_server.cc.patch index 6eeed424f4a1..01630cde231e 100644 --- a/patches/net-base-proxy_server.cc.patch +++ b/patches/net-base-proxy_server.cc.patch @@ -1,21 +1,29 @@ diff --git a/net/base/proxy_server.cc b/net/base/proxy_server.cc -index da31a40fbe8dc454dd24cb368c3af7d0b8c3506d..624d663b070e0eaf96a420c52a529525d7b7fed3 100644 +index da31a40fbe8dc454dd24cb368c3af7d0b8c3506d..85f8ee0367f949809e18bd7ec1eab0010975a87d 100644 --- a/net/base/proxy_server.cc +++ b/net/base/proxy_server.cc -@@ -8,6 +8,7 @@ +@@ -223,10 +223,13 @@ ProxyServer ProxyServer::FromSchemeHostAndPort( + HostPortPair host_port_pair; - #include "base/strings/string_util.h" - #include "base/trace_event/memory_usage_estimator.h" -+#include "net/base/url_auth_util.h" - #include "net/base/url_util.h" - #include "net/http/http_util.h" - -@@ -226,7 +227,7 @@ ProxyServer ProxyServer::FromSchemeHostAndPort( + if (scheme != SCHEME_INVALID && scheme != SCHEME_DIRECT) { ++ std::string username; ++ std::string password; std::string host; int port = -1; // If the scheme has a host/port, parse it. - bool ok = ParseHostAndPort(host_and_port, &host, &port); -+ bool ok = ParseAuthHostAndPort(host_and_port, &host, &port); ++ bool ok = ParseAuthHostAndPort(host_and_port, &username, &password, ++ &host, &port); if (!ok) return ProxyServer(); // Invalid -- failed parsing [":"] +@@ -234,7 +237,8 @@ ProxyServer ProxyServer::FromSchemeHostAndPort( + if (port == -1) + port = GetDefaultPortForScheme(scheme); + +- host_port_pair = HostPortPair(host, static_cast(port)); ++ host_port_pair = HostPortPair(username, password, host, ++ static_cast(port)); + } + + return ProxyServer(scheme, host_port_pair); diff --git a/patches/net-log-net_log_event_type_list.h.patch b/patches/net-log-net_log_event_type_list.h.patch deleted file mode 100644 index a00613f2dd11..000000000000 --- a/patches/net-log-net_log_event_type_list.h.patch +++ /dev/null @@ -1,17 +0,0 @@ -diff --git a/net/log/net_log_event_type_list.h b/net/log/net_log_event_type_list.h -index 79f3590df116ba98f0778a5a3f523d311952d86c..d700eb8572eba2361dee83fe0d097d0df2043a3e 100644 ---- a/net/log/net_log_event_type_list.h -+++ b/net/log/net_log_event_type_list.h -@@ -2113,6 +2113,12 @@ EVENT_TYPE(SOCKS5_GREET_WRITE) - // The time spent waiting for the "greeting" response from the SOCKS server. - EVENT_TYPE(SOCKS5_GREET_READ) - -+// The time spent sending authentication to the SOCKS server -+EVENT_TYPE(SOCKS5_AUTH_WRITE) -+ -+// The time spent waiting for the authentication response from the SOCKS server -+EVENT_TYPE(SOCKS5_AUTH_READ) -+ - // The time spent sending the CONNECT request to the SOCKS server. - EVENT_TYPE(SOCKS5_HANDSHAKE_WRITE) - diff --git a/patches/net-socket-socks_client_socket_pool.cc.patch b/patches/net-socket-socks_client_socket_pool.cc.patch index 4243af2e45a4..e0fe131d6c20 100644 --- a/patches/net-socket-socks_client_socket_pool.cc.patch +++ b/patches/net-socket-socks_client_socket_pool.cc.patch @@ -1,16 +1,7 @@ diff --git a/net/socket/socks_client_socket_pool.cc b/net/socket/socks_client_socket_pool.cc -index 2dad2733466a194da7898919604ebf4dcb463d74..30cb9d1955a034d2a6bcec97a2a286589881f310 100644 +index 2dad2733466a194da7898919604ebf4dcb463d74..c00c43c8febf0d78ca14e479cfe4f9af14146cb7 100644 --- a/net/socket/socks_client_socket_pool.cc +++ b/net/socket/socks_client_socket_pool.cc -@@ -16,7 +16,7 @@ - #include "net/socket/client_socket_factory.h" - #include "net/socket/client_socket_handle.h" - #include "net/socket/client_socket_pool_base.h" --#include "net/socket/socks5_client_socket.h" -+#include "net/socket/socks5_client_socket_auth.h" - #include "net/socket/socks_client_socket.h" - #include "net/socket/transport_client_socket_pool.h" - @@ -149,9 +149,11 @@ int SOCKSConnectJob::DoSOCKSConnect() { // Add a SOCKS connection on top of the tcp socket.