Branch data Line data Source code
# 1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto
# 2 : : // Copyright (c) 2009-2020 The Bitcoin Core developers
# 3 : : // Distributed under the MIT software license, see the accompanying
# 4 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
# 5 : :
# 6 : : #include <netbase.h>
# 7 : :
# 8 : : #include <compat.h>
# 9 : : #include <sync.h>
# 10 : : #include <tinyformat.h>
# 11 : : #include <util/sock.h>
# 12 : : #include <util/strencodings.h>
# 13 : : #include <util/string.h>
# 14 : : #include <util/system.h>
# 15 : : #include <util/time.h>
# 16 : :
# 17 : : #include <atomic>
# 18 : : #include <chrono>
# 19 : : #include <cstdint>
# 20 : : #include <functional>
# 21 : : #include <limits>
# 22 : : #include <memory>
# 23 : :
# 24 : : #ifndef WIN32
# 25 : : #include <fcntl.h>
# 26 : : #else
# 27 : : #include <codecvt>
# 28 : : #endif
# 29 : :
# 30 : : #ifdef USE_POLL
# 31 : : #include <poll.h>
# 32 : : #endif
# 33 : :
# 34 : : // Settings
# 35 : : static Mutex g_proxyinfo_mutex;
# 36 : : static proxyType proxyInfo[NET_MAX] GUARDED_BY(g_proxyinfo_mutex);
# 37 : : static proxyType nameProxy GUARDED_BY(g_proxyinfo_mutex);
# 38 : : int nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
# 39 : : bool fNameLookup = DEFAULT_NAME_LOOKUP;
# 40 : :
# 41 : : // Need ample time for negotiation for very slow proxies such as Tor (milliseconds)
# 42 : : int g_socks5_recv_timeout = 20 * 1000;
# 43 : : static std::atomic<bool> interruptSocks5Recv(false);
# 44 : :
# 45 : : std::vector<CNetAddr> WrappedGetAddrInfo(const std::string& name, bool allow_lookup)
# 46 : 385230 : {
# 47 : 385230 : addrinfo ai_hint{};
# 48 : : // We want a TCP port, which is a streaming socket type
# 49 : 385230 : ai_hint.ai_socktype = SOCK_STREAM;
# 50 : 385230 : ai_hint.ai_protocol = IPPROTO_TCP;
# 51 : : // We don't care which address family (IPv4 or IPv6) is returned
# 52 : 385230 : ai_hint.ai_family = AF_UNSPEC;
# 53 : : // If we allow lookups of hostnames, use the AI_ADDRCONFIG flag to only
# 54 : : // return addresses whose family we have an address configured for.
# 55 : : //
# 56 : : // If we don't allow lookups, then use the AI_NUMERICHOST flag for
# 57 : : // getaddrinfo to only decode numerical network addresses and suppress
# 58 : : // hostname lookups.
# 59 [ + + ]: 385230 : ai_hint.ai_flags = allow_lookup ? AI_ADDRCONFIG : AI_NUMERICHOST;
# 60 : :
# 61 : 385230 : addrinfo* ai_res{nullptr};
# 62 : 385230 : const int n_err{getaddrinfo(name.c_str(), nullptr, &ai_hint, &ai_res)};
# 63 [ + + ]: 385230 : if (n_err != 0) {
# 64 : 30 : return {};
# 65 : 30 : }
# 66 : :
# 67 : : // Traverse the linked list starting with ai_trav.
# 68 : 385200 : addrinfo* ai_trav{ai_res};
# 69 : 385200 : std::vector<CNetAddr> resolved_addresses;
# 70 [ + + ]: 770400 : while (ai_trav != nullptr) {
# 71 [ + + ]: 385200 : if (ai_trav->ai_family == AF_INET) {
# 72 : 383645 : assert(ai_trav->ai_addrlen >= sizeof(sockaddr_in));
# 73 : 383645 : resolved_addresses.emplace_back(reinterpret_cast<sockaddr_in*>(ai_trav->ai_addr)->sin_addr);
# 74 : 383645 : }
# 75 [ + + ]: 385200 : if (ai_trav->ai_family == AF_INET6) {
# 76 : 1555 : assert(ai_trav->ai_addrlen >= sizeof(sockaddr_in6));
# 77 : 1555 : const sockaddr_in6* s6{reinterpret_cast<sockaddr_in6*>(ai_trav->ai_addr)};
# 78 : 1555 : resolved_addresses.emplace_back(s6->sin6_addr, s6->sin6_scope_id);
# 79 : 1555 : }
# 80 : 385200 : ai_trav = ai_trav->ai_next;
# 81 : 385200 : }
# 82 : 385200 : freeaddrinfo(ai_res);
# 83 : :
# 84 : 385200 : return resolved_addresses;
# 85 : 385200 : }
# 86 : :
# 87 : : DNSLookupFn g_dns_lookup{WrappedGetAddrInfo};
# 88 : :
# 89 : 30 : enum Network ParseNetwork(const std::string& net_in) {
# 90 : 30 : std::string net = ToLower(net_in);
# 91 [ + + ]: 30 : if (net == "ipv4") return NET_IPV4;
# 92 [ + + ]: 24 : if (net == "ipv6") return NET_IPV6;
# 93 [ + + ]: 19 : if (net == "onion") return NET_ONION;
# 94 [ + + ]: 14 : if (net == "tor") {
# 95 : 4 : LogPrintf("Warning: net name 'tor' is deprecated and will be removed in the future. You should use 'onion' instead.\n");
# 96 : 4 : return NET_ONION;
# 97 : 4 : }
# 98 [ + + ]: 10 : if (net == "i2p") {
# 99 : 1 : return NET_I2P;
# 100 : 1 : }
# 101 : 9 : return NET_UNROUTABLE;
# 102 : 9 : }
# 103 : :
# 104 : : std::string GetNetworkName(enum Network net)
# 105 : 83346 : {
# 106 [ - + ]: 83346 : switch (net) {
# 107 [ + + ]: 16300 : case NET_UNROUTABLE: return "not_publicly_routable";
# 108 [ + + ]: 30005 : case NET_IPV4: return "ipv4";
# 109 [ + + ]: 12352 : case NET_IPV6: return "ipv6";
# 110 [ + + ]: 12347 : case NET_ONION: return "onion";
# 111 [ + + ]: 12342 : case NET_I2P: return "i2p";
# 112 [ - + ]: 0 : case NET_CJDNS: return "cjdns";
# 113 [ - + ]: 0 : case NET_INTERNAL: return "internal";
# 114 [ - + ]: 0 : case NET_MAX: assert(false);
# 115 : 83346 : } // no default case, so the compiler can warn about missing cases
# 116 : :
# 117 : 83346 : assert(false);
# 118 : 0 : }
# 119 : :
# 120 : : std::vector<std::string> GetNetworkNames(bool append_unroutable)
# 121 : 12283 : {
# 122 : 12283 : std::vector<std::string> names;
# 123 [ + + ]: 98264 : for (int n = 0; n < NET_MAX; ++n) {
# 124 : 85981 : const enum Network network{static_cast<Network>(n)};
# 125 [ + + ][ + + ]: 85981 : if (network == NET_UNROUTABLE || network == NET_CJDNS || network == NET_INTERNAL) continue;
# [ + + ]
# 126 : 49132 : names.emplace_back(GetNetworkName(network));
# 127 : 49132 : }
# 128 [ + + ]: 12283 : if (append_unroutable) {
# 129 : 6665 : names.emplace_back(GetNetworkName(NET_UNROUTABLE));
# 130 : 6665 : }
# 131 : 12283 : return names;
# 132 : 12283 : }
# 133 : :
# 134 : : static bool LookupIntern(const std::string& name, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup, DNSLookupFn dns_lookup_function)
# 135 : 385261 : {
# 136 : 385261 : vIP.clear();
# 137 : :
# 138 [ - + ]: 385261 : if (!ValidAsCString(name)) {
# 139 : 0 : return false;
# 140 : 0 : }
# 141 : :
# 142 : 385261 : {
# 143 : 385261 : CNetAddr addr;
# 144 : : // From our perspective, onion addresses are not hostnames but rather
# 145 : : // direct encodings of CNetAddr much like IPv4 dotted-decimal notation
# 146 : : // or IPv6 colon-separated hextet notation. Since we can't use
# 147 : : // getaddrinfo to decode them and it wouldn't make sense to resolve
# 148 : : // them, we return a network address representing it instead. See
# 149 : : // CNetAddr::SetSpecial(const std::string&) for more details.
# 150 [ + + ]: 385261 : if (addr.SetSpecial(name)) {
# 151 : 31 : vIP.push_back(addr);
# 152 : 31 : return true;
# 153 : 31 : }
# 154 : 385230 : }
# 155 : :
# 156 [ + + ]: 385230 : for (const CNetAddr& resolved : dns_lookup_function(name, fAllowLookup)) {
# 157 [ + - ][ - + ]: 385200 : if (nMaxSolutions > 0 && vIP.size() >= nMaxSolutions) {
# 158 : 0 : break;
# 159 : 0 : }
# 160 : : /* Never allow resolving to an internal address. Consider any such result invalid */
# 161 [ + + ]: 385200 : if (!resolved.IsInternal()) {
# 162 : 385198 : vIP.push_back(resolved);
# 163 : 385198 : }
# 164 : 385200 : }
# 165 : :
# 166 : 385230 : return (vIP.size() > 0);
# 167 : 385230 : }
# 168 : :
# 169 : : bool LookupHost(const std::string& name, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup, DNSLookupFn dns_lookup_function)
# 170 : 37121 : {
# 171 [ - + ]: 37121 : if (!ValidAsCString(name)) {
# 172 : 0 : return false;
# 173 : 0 : }
# 174 : 37121 : std::string strHost = name;
# 175 [ + + ]: 37121 : if (strHost.empty())
# 176 : 3 : return false;
# 177 [ - + ][ # # ]: 37118 : if (strHost.front() == '[' && strHost.back() == ']') {
# 178 : 0 : strHost = strHost.substr(1, strHost.size() - 2);
# 179 : 0 : }
# 180 : :
# 181 : 37118 : return LookupIntern(strHost, vIP, nMaxSolutions, fAllowLookup, dns_lookup_function);
# 182 : 37118 : }
# 183 : :
# 184 : : bool LookupHost(const std::string& name, CNetAddr& addr, bool fAllowLookup, DNSLookupFn dns_lookup_function)
# 185 : 36768 : {
# 186 [ + + ]: 36768 : if (!ValidAsCString(name)) {
# 187 : 6 : return false;
# 188 : 6 : }
# 189 : 36762 : std::vector<CNetAddr> vIP;
# 190 : 36762 : LookupHost(name, vIP, 1, fAllowLookup, dns_lookup_function);
# 191 [ + + ]: 36762 : if(vIP.empty())
# 192 : 7 : return false;
# 193 : 36755 : addr = vIP.front();
# 194 : 36755 : return true;
# 195 : 36755 : }
# 196 : :
# 197 : : bool Lookup(const std::string& name, std::vector<CService>& vAddr, uint16_t portDefault, bool fAllowLookup, unsigned int nMaxSolutions, DNSLookupFn dns_lookup_function)
# 198 : 348147 : {
# 199 [ + + ][ - + ]: 348147 : if (name.empty() || !ValidAsCString(name)) {
# 200 : 4 : return false;
# 201 : 4 : }
# 202 : 348143 : uint16_t port{portDefault};
# 203 : 348143 : std::string hostname;
# 204 : 348143 : SplitHostPort(name, port, hostname);
# 205 : :
# 206 : 348143 : std::vector<CNetAddr> vIP;
# 207 : 348143 : bool fRet = LookupIntern(hostname, vIP, nMaxSolutions, fAllowLookup, dns_lookup_function);
# 208 [ + + ]: 348143 : if (!fRet)
# 209 : 13 : return false;
# 210 : 348130 : vAddr.resize(vIP.size());
# 211 [ + + ]: 696260 : for (unsigned int i = 0; i < vIP.size(); i++)
# 212 : 348130 : vAddr[i] = CService(vIP[i], port);
# 213 : 348130 : return true;
# 214 : 348130 : }
# 215 : :
# 216 : : bool Lookup(const std::string& name, CService& addr, uint16_t portDefault, bool fAllowLookup, DNSLookupFn dns_lookup_function)
# 217 : 347780 : {
# 218 [ + + ]: 347780 : if (!ValidAsCString(name)) {
# 219 : 2 : return false;
# 220 : 2 : }
# 221 : 347778 : std::vector<CService> vService;
# 222 : 347778 : bool fRet = Lookup(name, vService, portDefault, fAllowLookup, 1, dns_lookup_function);
# 223 [ + + ]: 347778 : if (!fRet)
# 224 : 11 : return false;
# 225 : 347767 : addr = vService[0];
# 226 : 347767 : return true;
# 227 : 347767 : }
# 228 : :
# 229 : : CService LookupNumeric(const std::string& name, uint16_t portDefault, DNSLookupFn dns_lookup_function)
# 230 : 333832 : {
# 231 [ - + ]: 333832 : if (!ValidAsCString(name)) {
# 232 : 0 : return {};
# 233 : 0 : }
# 234 : 333832 : CService addr;
# 235 : : // "1.2:345" will fail to resolve the ip, but will still set the port.
# 236 : : // If the ip fails to resolve, re-init the result.
# 237 [ + + ]: 333832 : if(!Lookup(name, addr, portDefault, false, dns_lookup_function))
# 238 : 6 : addr = CService();
# 239 : 333832 : return addr;
# 240 : 333832 : }
# 241 : :
# 242 : : /** SOCKS version */
# 243 : : enum SOCKSVersion: uint8_t {
# 244 : : SOCKS4 = 0x04,
# 245 : : SOCKS5 = 0x05
# 246 : : };
# 247 : :
# 248 : : /** Values defined for METHOD in RFC1928 */
# 249 : : enum SOCKS5Method: uint8_t {
# 250 : : NOAUTH = 0x00, //!< No authentication required
# 251 : : GSSAPI = 0x01, //!< GSSAPI
# 252 : : USER_PASS = 0x02, //!< Username/password
# 253 : : NO_ACCEPTABLE = 0xff, //!< No acceptable methods
# 254 : : };
# 255 : :
# 256 : : /** Values defined for CMD in RFC1928 */
# 257 : : enum SOCKS5Command: uint8_t {
# 258 : : CONNECT = 0x01,
# 259 : : BIND = 0x02,
# 260 : : UDP_ASSOCIATE = 0x03
# 261 : : };
# 262 : :
# 263 : : /** Values defined for REP in RFC1928 */
# 264 : : enum SOCKS5Reply: uint8_t {
# 265 : : SUCCEEDED = 0x00, //!< Succeeded
# 266 : : GENFAILURE = 0x01, //!< General failure
# 267 : : NOTALLOWED = 0x02, //!< Connection not allowed by ruleset
# 268 : : NETUNREACHABLE = 0x03, //!< Network unreachable
# 269 : : HOSTUNREACHABLE = 0x04, //!< Network unreachable
# 270 : : CONNREFUSED = 0x05, //!< Connection refused
# 271 : : TTLEXPIRED = 0x06, //!< TTL expired
# 272 : : CMDUNSUPPORTED = 0x07, //!< Command not supported
# 273 : : ATYPEUNSUPPORTED = 0x08, //!< Address type not supported
# 274 : : };
# 275 : :
# 276 : : /** Values defined for ATYPE in RFC1928 */
# 277 : : enum SOCKS5Atyp: uint8_t {
# 278 : : IPV4 = 0x01,
# 279 : : DOMAINNAME = 0x03,
# 280 : : IPV6 = 0x04,
# 281 : : };
# 282 : :
# 283 : : /** Status codes that can be returned by InterruptibleRecv */
# 284 : : enum class IntrRecvError {
# 285 : : OK,
# 286 : : Timeout,
# 287 : : Disconnected,
# 288 : : NetworkError,
# 289 : : Interrupted
# 290 : : };
# 291 : :
# 292 : : /**
# 293 : : * Try to read a specified number of bytes from a socket. Please read the "see
# 294 : : * also" section for more detail.
# 295 : : *
# 296 : : * @param data The buffer where the read bytes should be stored.
# 297 : : * @param len The number of bytes to read into the specified buffer.
# 298 : : * @param timeout The total timeout in milliseconds for this read.
# 299 : : * @param sock The socket (has to be in non-blocking mode) from which to read bytes.
# 300 : : *
# 301 : : * @returns An IntrRecvError indicating the resulting status of this read.
# 302 : : * IntrRecvError::OK only if all of the specified number of bytes were
# 303 : : * read.
# 304 : : *
# 305 : : * @see This function can be interrupted by calling InterruptSocks5(bool).
# 306 : : * Sockets can be made non-blocking with SetSocketNonBlocking(const
# 307 : : * SOCKET&, bool).
# 308 : : */
# 309 : : static IntrRecvError InterruptibleRecv(uint8_t* data, size_t len, int timeout, const Sock& sock)
# 310 : 64 : {
# 311 : 64 : int64_t curTime = GetTimeMillis();
# 312 : 64 : int64_t endTime = curTime + timeout;
# 313 [ + + ][ + - ]: 158 : while (len > 0 && curTime < endTime) {
# 314 : 94 : ssize_t ret = sock.Recv(data, len, 0); // Optimistically try the recv first
# 315 [ + + ]: 94 : if (ret > 0) {
# 316 : 64 : len -= ret;
# 317 : 64 : data += ret;
# 318 [ - + ]: 64 : } else if (ret == 0) { // Unexpected disconnection
# 319 : 0 : return IntrRecvError::Disconnected;
# 320 : 30 : } else { // Other error or blocking
# 321 : 30 : int nErr = WSAGetLastError();
# 322 [ - + ][ + - ]: 30 : if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) {
# [ # # ]
# 323 : : // Only wait at most MAX_WAIT_FOR_IO at a time, unless
# 324 : : // we're approaching the end of the specified total timeout
# 325 : 30 : const auto remaining = std::chrono::milliseconds{endTime - curTime};
# 326 : 30 : const auto timeout = std::min(remaining, std::chrono::milliseconds{MAX_WAIT_FOR_IO});
# 327 [ - + ]: 30 : if (!sock.Wait(timeout, Sock::RECV)) {
# 328 : 0 : return IntrRecvError::NetworkError;
# 329 : 0 : }
# 330 : 0 : } else {
# 331 : 0 : return IntrRecvError::NetworkError;
# 332 : 0 : }
# 333 : 94 : }
# 334 [ - + ]: 94 : if (interruptSocks5Recv)
# 335 : 0 : return IntrRecvError::Interrupted;
# 336 : 94 : curTime = GetTimeMillis();
# 337 : 94 : }
# 338 [ + - ]: 64 : return len == 0 ? IntrRecvError::OK : IntrRecvError::Timeout;
# 339 : 64 : }
# 340 : :
# 341 : : /** Convert SOCKS5 reply to an error message */
# 342 : : static std::string Socks5ErrorString(uint8_t err)
# 343 : 0 : {
# 344 : 0 : switch(err) {
# 345 [ # # ]: 0 : case SOCKS5Reply::GENFAILURE:
# 346 : 0 : return "general failure";
# 347 [ # # ]: 0 : case SOCKS5Reply::NOTALLOWED:
# 348 : 0 : return "connection not allowed";
# 349 [ # # ]: 0 : case SOCKS5Reply::NETUNREACHABLE:
# 350 : 0 : return "network unreachable";
# 351 [ # # ]: 0 : case SOCKS5Reply::HOSTUNREACHABLE:
# 352 : 0 : return "host unreachable";
# 353 [ # # ]: 0 : case SOCKS5Reply::CONNREFUSED:
# 354 : 0 : return "connection refused";
# 355 [ # # ]: 0 : case SOCKS5Reply::TTLEXPIRED:
# 356 : 0 : return "TTL expired";
# 357 [ # # ]: 0 : case SOCKS5Reply::CMDUNSUPPORTED:
# 358 : 0 : return "protocol error";
# 359 [ # # ]: 0 : case SOCKS5Reply::ATYPEUNSUPPORTED:
# 360 : 0 : return "address type not supported";
# 361 [ # # ]: 0 : default:
# 362 : 0 : return "unknown";
# 363 : 0 : }
# 364 : 0 : }
# 365 : :
# 366 : : bool Socks5(const std::string& strDest, uint16_t port, const ProxyCredentials* auth, const Sock& sock)
# 367 : 15 : {
# 368 : 15 : IntrRecvError recvr;
# 369 [ + - ]: 15 : LogPrint(BCLog::NET, "SOCKS5 connecting %s\n", strDest);
# 370 [ - + ]: 15 : if (strDest.size() > 255) {
# 371 : 0 : return error("Hostname too long");
# 372 : 0 : }
# 373 : : // Construct the version identifier/method selection message
# 374 : 15 : std::vector<uint8_t> vSocks5Init;
# 375 : 15 : vSocks5Init.push_back(SOCKSVersion::SOCKS5); // We want the SOCK5 protocol
# 376 [ + + ]: 15 : if (auth) {
# 377 : 8 : vSocks5Init.push_back(0x02); // 2 method identifiers follow...
# 378 : 8 : vSocks5Init.push_back(SOCKS5Method::NOAUTH);
# 379 : 8 : vSocks5Init.push_back(SOCKS5Method::USER_PASS);
# 380 : 8 : } else {
# 381 : 7 : vSocks5Init.push_back(0x01); // 1 method identifier follows...
# 382 : 7 : vSocks5Init.push_back(SOCKS5Method::NOAUTH);
# 383 : 7 : }
# 384 : 15 : ssize_t ret = sock.Send(vSocks5Init.data(), vSocks5Init.size(), MSG_NOSIGNAL);
# 385 [ - + ]: 15 : if (ret != (ssize_t)vSocks5Init.size()) {
# 386 : 0 : return error("Error sending to proxy");
# 387 : 0 : }
# 388 : 15 : uint8_t pchRet1[2];
# 389 [ - + ]: 15 : if ((recvr = InterruptibleRecv(pchRet1, 2, g_socks5_recv_timeout, sock)) != IntrRecvError::OK) {
# 390 : 0 : LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port);
# 391 : 0 : return false;
# 392 : 0 : }
# 393 [ - + ]: 15 : if (pchRet1[0] != SOCKSVersion::SOCKS5) {
# 394 : 0 : return error("Proxy failed to initialize");
# 395 : 0 : }
# 396 [ + + ][ + - ]: 15 : if (pchRet1[1] == SOCKS5Method::USER_PASS && auth) {
# 397 : : // Perform username/password authentication (as described in RFC1929)
# 398 : 4 : std::vector<uint8_t> vAuth;
# 399 : 4 : vAuth.push_back(0x01); // Current (and only) version of user/pass subnegotiation
# 400 [ - + ][ - + ]: 4 : if (auth->username.size() > 255 || auth->password.size() > 255)
# 401 : 0 : return error("Proxy username or password too long");
# 402 : 4 : vAuth.push_back(auth->username.size());
# 403 : 4 : vAuth.insert(vAuth.end(), auth->username.begin(), auth->username.end());
# 404 : 4 : vAuth.push_back(auth->password.size());
# 405 : 4 : vAuth.insert(vAuth.end(), auth->password.begin(), auth->password.end());
# 406 : 4 : ret = sock.Send(vAuth.data(), vAuth.size(), MSG_NOSIGNAL);
# 407 [ - + ]: 4 : if (ret != (ssize_t)vAuth.size()) {
# 408 : 0 : return error("Error sending authentication to proxy");
# 409 : 0 : }
# 410 [ + - ]: 4 : LogPrint(BCLog::PROXY, "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password);
# 411 : 4 : uint8_t pchRetA[2];
# 412 [ - + ]: 4 : if ((recvr = InterruptibleRecv(pchRetA, 2, g_socks5_recv_timeout, sock)) != IntrRecvError::OK) {
# 413 : 0 : return error("Error reading proxy authentication response");
# 414 : 0 : }
# 415 [ - + ][ - + ]: 4 : if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) {
# 416 : 0 : return error("Proxy authentication unsuccessful");
# 417 : 0 : }
# 418 [ + - ]: 11 : } else if (pchRet1[1] == SOCKS5Method::NOAUTH) {
# 419 : : // Perform no authentication
# 420 : 11 : } else {
# 421 : 0 : return error("Proxy requested wrong authentication method %02x", pchRet1[1]);
# 422 : 0 : }
# 423 : 15 : std::vector<uint8_t> vSocks5;
# 424 : 15 : vSocks5.push_back(SOCKSVersion::SOCKS5); // VER protocol version
# 425 : 15 : vSocks5.push_back(SOCKS5Command::CONNECT); // CMD CONNECT
# 426 : 15 : vSocks5.push_back(0x00); // RSV Reserved must be 0
# 427 : 15 : vSocks5.push_back(SOCKS5Atyp::DOMAINNAME); // ATYP DOMAINNAME
# 428 : 15 : vSocks5.push_back(strDest.size()); // Length<=255 is checked at beginning of function
# 429 : 15 : vSocks5.insert(vSocks5.end(), strDest.begin(), strDest.end());
# 430 : 15 : vSocks5.push_back((port >> 8) & 0xFF);
# 431 : 15 : vSocks5.push_back((port >> 0) & 0xFF);
# 432 : 15 : ret = sock.Send(vSocks5.data(), vSocks5.size(), MSG_NOSIGNAL);
# 433 [ - + ]: 15 : if (ret != (ssize_t)vSocks5.size()) {
# 434 : 0 : return error("Error sending to proxy");
# 435 : 0 : }
# 436 : 15 : uint8_t pchRet2[4];
# 437 [ - + ]: 15 : if ((recvr = InterruptibleRecv(pchRet2, 4, g_socks5_recv_timeout, sock)) != IntrRecvError::OK) {
# 438 [ # # ]: 0 : if (recvr == IntrRecvError::Timeout) {
# 439 : : /* If a timeout happens here, this effectively means we timed out while connecting
# 440 : : * to the remote node. This is very common for Tor, so do not print an
# 441 : : * error message. */
# 442 : 0 : return false;
# 443 : 0 : } else {
# 444 : 0 : return error("Error while reading proxy response");
# 445 : 0 : }
# 446 : 15 : }
# 447 [ - + ]: 15 : if (pchRet2[0] != SOCKSVersion::SOCKS5) {
# 448 : 0 : return error("Proxy failed to accept request");
# 449 : 0 : }
# 450 [ - + ]: 15 : if (pchRet2[1] != SOCKS5Reply::SUCCEEDED) {
# 451 : : // Failures to connect to a peer that are not proxy errors
# 452 : 0 : LogPrintf("Socks5() connect to %s:%d failed: %s\n", strDest, port, Socks5ErrorString(pchRet2[1]));
# 453 : 0 : return false;
# 454 : 0 : }
# 455 [ - + ]: 15 : if (pchRet2[2] != 0x00) { // Reserved field must be 0
# 456 : 0 : return error("Error: malformed proxy response");
# 457 : 0 : }
# 458 : 15 : uint8_t pchRet3[256];
# 459 : 15 : switch (pchRet2[3])
# 460 : 15 : {
# 461 [ + - ]: 15 : case SOCKS5Atyp::IPV4: recvr = InterruptibleRecv(pchRet3, 4, g_socks5_recv_timeout, sock); break;
# 462 [ - + ]: 0 : case SOCKS5Atyp::IPV6: recvr = InterruptibleRecv(pchRet3, 16, g_socks5_recv_timeout, sock); break;
# 463 [ - + ]: 0 : case SOCKS5Atyp::DOMAINNAME:
# 464 : 0 : {
# 465 : 0 : recvr = InterruptibleRecv(pchRet3, 1, g_socks5_recv_timeout, sock);
# 466 [ # # ]: 0 : if (recvr != IntrRecvError::OK) {
# 467 : 0 : return error("Error reading from proxy");
# 468 : 0 : }
# 469 : 0 : int nRecv = pchRet3[0];
# 470 : 0 : recvr = InterruptibleRecv(pchRet3, nRecv, g_socks5_recv_timeout, sock);
# 471 : 0 : break;
# 472 : 0 : }
# 473 [ - + ]: 0 : default: return error("Error: malformed proxy response");
# 474 : 15 : }
# 475 [ - + ]: 15 : if (recvr != IntrRecvError::OK) {
# 476 : 0 : return error("Error reading from proxy");
# 477 : 0 : }
# 478 [ - + ]: 15 : if ((recvr = InterruptibleRecv(pchRet3, 2, g_socks5_recv_timeout, sock)) != IntrRecvError::OK) {
# 479 : 0 : return error("Error reading from proxy");
# 480 : 0 : }
# 481 [ + - ]: 15 : LogPrint(BCLog::NET, "SOCKS5 connected %s\n", strDest);
# 482 : 15 : return true;
# 483 : 15 : }
# 484 : :
# 485 : : std::unique_ptr<Sock> CreateSockTCP(const CService& address_family)
# 486 : 1786 : {
# 487 : : // Create a sockaddr from the specified service.
# 488 : 1786 : struct sockaddr_storage sockaddr;
# 489 : 1786 : socklen_t len = sizeof(sockaddr);
# 490 [ - + ]: 1786 : if (!address_family.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
# 491 : 0 : LogPrintf("Cannot create socket for %s: unsupported network\n", address_family.ToString());
# 492 : 0 : return nullptr;
# 493 : 0 : }
# 494 : :
# 495 : : // Create a TCP socket in the address family of the specified service.
# 496 : 1786 : SOCKET hSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
# 497 [ - + ]: 1786 : if (hSocket == INVALID_SOCKET) {
# 498 : 0 : return nullptr;
# 499 : 0 : }
# 500 : :
# 501 : : // Ensure that waiting for I/O on this socket won't result in undefined
# 502 : : // behavior.
# 503 [ - + ]: 1786 : if (!IsSelectableSocket(hSocket)) {
# 504 : 0 : CloseSocket(hSocket);
# 505 : 0 : LogPrintf("Cannot create connection: non-selectable socket created (fd >= FD_SETSIZE ?)\n");
# 506 : 0 : return nullptr;
# 507 : 0 : }
# 508 : :
# 509 : 1786 : #ifdef SO_NOSIGPIPE
# 510 : 1786 : int set = 1;
# 511 : : // Set the no-sigpipe option on the socket for BSD systems, other UNIXes
# 512 : : // should use the MSG_NOSIGNAL flag for every send.
# 513 : 1786 : setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
# 514 : 1786 : #endif
# 515 : :
# 516 : : // Set the no-delay option (disable Nagle's algorithm) on the TCP socket.
# 517 : 1786 : SetSocketNoDelay(hSocket);
# 518 : :
# 519 : : // Set the non-blocking option on the socket.
# 520 [ - + ]: 1786 : if (!SetSocketNonBlocking(hSocket, true)) {
# 521 : 0 : CloseSocket(hSocket);
# 522 : 0 : LogPrintf("Error setting socket to non-blocking: %s\n", NetworkErrorString(WSAGetLastError()));
# 523 : 0 : return nullptr;
# 524 : 0 : }
# 525 : 1786 : return std::make_unique<Sock>(hSocket);
# 526 : 1786 : }
# 527 : :
# 528 : : std::function<std::unique_ptr<Sock>(const CService&)> CreateSock = CreateSockTCP;
# 529 : :
# 530 : : template<typename... Args>
# 531 : 8 : static void LogConnectFailure(bool manual_connection, const char* fmt, const Args&... args) {
# 532 : 8 : std::string error_message = tfm::format(fmt, args...);
# 533 [ - + ]: 8 : if (manual_connection) {
# 534 : 0 : LogPrintf("%s\n", error_message);
# 535 : 8 : } else {
# 536 [ + - ]: 8 : LogPrint(BCLog::NET, "%s\n", error_message);
# 537 : 8 : }
# 538 : 8 : }
# 539 : :
# 540 : : bool ConnectSocketDirectly(const CService &addrConnect, const Sock& sock, int nTimeout, bool manual_connection)
# 541 : 551 : {
# 542 : : // Create a sockaddr from the specified service.
# 543 : 551 : struct sockaddr_storage sockaddr;
# 544 : 551 : socklen_t len = sizeof(sockaddr);
# 545 [ - + ]: 551 : if (sock.Get() == INVALID_SOCKET) {
# 546 : 0 : LogPrintf("Cannot connect to %s: invalid socket\n", addrConnect.ToString());
# 547 : 0 : return false;
# 548 : 0 : }
# 549 [ - + ]: 551 : if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
# 550 : 0 : LogPrintf("Cannot connect to %s: unsupported network\n", addrConnect.ToString());
# 551 : 0 : return false;
# 552 : 0 : }
# 553 : :
# 554 : : // Connect to the addrConnect service on the hSocket socket.
# 555 [ + + ]: 551 : if (sock.Connect(reinterpret_cast<struct sockaddr*>(&sockaddr), len) == SOCKET_ERROR) {
# 556 : 528 : int nErr = WSAGetLastError();
# 557 : : // WSAEINVAL is here because some legacy version of winsock uses it
# 558 [ + - ][ # # ]: 528 : if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL)
# [ # # ]
# 559 : 528 : {
# 560 : : // Connection didn't actually fail, but is being established
# 561 : : // asynchronously. Thus, use async I/O api (select/poll)
# 562 : : // synchronously to check for successful connection with a timeout.
# 563 : 528 : const Sock::Event requested = Sock::RECV | Sock::SEND;
# 564 : 528 : Sock::Event occurred;
# 565 [ - + ]: 528 : if (!sock.Wait(std::chrono::milliseconds{nTimeout}, requested, &occurred)) {
# 566 : 0 : LogPrintf("wait for connect to %s failed: %s\n",
# 567 : 0 : addrConnect.ToString(),
# 568 : 0 : NetworkErrorString(WSAGetLastError()));
# 569 : 0 : return false;
# 570 [ + + ]: 528 : } else if (occurred == 0) {
# 571 [ + - ]: 177 : LogPrint(BCLog::NET, "connection attempt to %s timed out\n", addrConnect.ToString());
# 572 : 177 : return false;
# 573 : 177 : }
# 574 : :
# 575 : : // Even if the wait was successful, the connect might not
# 576 : : // have been successful. The reason for this failure is hidden away
# 577 : : // in the SO_ERROR for the socket in modern systems. We read it into
# 578 : : // sockerr here.
# 579 : 351 : int sockerr;
# 580 : 351 : socklen_t sockerr_len = sizeof(sockerr);
# 581 [ - + ]: 351 : if (sock.GetSockOpt(SOL_SOCKET, SO_ERROR, (sockopt_arg_type)&sockerr, &sockerr_len) ==
# 582 : 351 : SOCKET_ERROR) {
# 583 : 0 : LogPrintf("getsockopt() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
# 584 : 0 : return false;
# 585 : 0 : }
# 586 [ + + ]: 351 : if (sockerr != 0) {
# 587 : 8 : LogConnectFailure(manual_connection,
# 588 : 8 : "connect() to %s failed after wait: %s",
# 589 : 8 : addrConnect.ToString(),
# 590 : 8 : NetworkErrorString(sockerr));
# 591 : 8 : return false;
# 592 : 8 : }
# 593 : 0 : }
# 594 : : #ifdef WIN32
# 595 : : else if (WSAGetLastError() != WSAEISCONN)
# 596 : : #else
# 597 : 0 : else
# 598 : 0 : #endif
# 599 : 0 : {
# 600 : 0 : LogConnectFailure(manual_connection, "connect() to %s failed: %s", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
# 601 : 0 : return false;
# 602 : 0 : }
# 603 : 366 : }
# 604 : 366 : return true;
# 605 : 366 : }
# 606 : :
# 607 : 15 : bool SetProxy(enum Network net, const proxyType &addrProxy) {
# 608 : 15 : assert(net >= 0 && net < NET_MAX);
# 609 [ - + ]: 15 : if (!addrProxy.IsValid())
# 610 : 0 : return false;
# 611 : 15 : LOCK(g_proxyinfo_mutex);
# 612 : 15 : proxyInfo[net] = addrProxy;
# 613 : 15 : return true;
# 614 : 15 : }
# 615 : :
# 616 : 1397 : bool GetProxy(enum Network net, proxyType &proxyInfoOut) {
# 617 : 1397 : assert(net >= 0 && net < NET_MAX);
# 618 : 1397 : LOCK(g_proxyinfo_mutex);
# 619 [ + + ]: 1397 : if (!proxyInfo[net].IsValid())
# 620 : 1371 : return false;
# 621 : 26 : proxyInfoOut = proxyInfo[net];
# 622 : 26 : return true;
# 623 : 26 : }
# 624 : :
# 625 : 4 : bool SetNameProxy(const proxyType &addrProxy) {
# 626 [ - + ]: 4 : if (!addrProxy.IsValid())
# 627 : 0 : return false;
# 628 : 4 : LOCK(g_proxyinfo_mutex);
# 629 : 4 : nameProxy = addrProxy;
# 630 : 4 : return true;
# 631 : 4 : }
# 632 : :
# 633 : 6 : bool GetNameProxy(proxyType &nameProxyOut) {
# 634 : 6 : LOCK(g_proxyinfo_mutex);
# 635 [ + + ]: 6 : if(!nameProxy.IsValid())
# 636 : 2 : return false;
# 637 : 4 : nameProxyOut = nameProxy;
# 638 : 4 : return true;
# 639 : 4 : }
# 640 : :
# 641 : 369 : bool HaveNameProxy() {
# 642 : 369 : LOCK(g_proxyinfo_mutex);
# 643 : 369 : return nameProxy.IsValid();
# 644 : 369 : }
# 645 : :
# 646 : 33 : bool IsProxy(const CNetAddr &addr) {
# 647 : 33 : LOCK(g_proxyinfo_mutex);
# 648 [ + + ]: 264 : for (int i = 0; i < NET_MAX; i++) {
# 649 [ - + ]: 231 : if (addr == static_cast<CNetAddr>(proxyInfo[i].proxy))
# 650 : 0 : return true;
# 651 : 231 : }
# 652 : 33 : return false;
# 653 : 33 : }
# 654 : :
# 655 : : bool ConnectThroughProxy(const proxyType& proxy, const std::string& strDest, uint16_t port, const Sock& sock, int nTimeout, bool& outProxyConnectionFailed)
# 656 : 15 : {
# 657 : : // first connect to proxy server
# 658 [ - + ]: 15 : if (!ConnectSocketDirectly(proxy.proxy, sock, nTimeout, true)) {
# 659 : 0 : outProxyConnectionFailed = true;
# 660 : 0 : return false;
# 661 : 0 : }
# 662 : : // do socks negotiation
# 663 [ + + ]: 15 : if (proxy.randomize_credentials) {
# 664 : 8 : ProxyCredentials random_auth;
# 665 : 8 : static std::atomic_int counter(0);
# 666 : 8 : random_auth.username = random_auth.password = strprintf("%i", counter++);
# 667 [ - + ]: 8 : if (!Socks5(strDest, port, &random_auth, sock)) {
# 668 : 0 : return false;
# 669 : 0 : }
# 670 : 7 : } else {
# 671 [ - + ]: 7 : if (!Socks5(strDest, port, 0, sock)) {
# 672 : 0 : return false;
# 673 : 0 : }
# 674 : 15 : }
# 675 : 15 : return true;
# 676 : 15 : }
# 677 : :
# 678 : : bool LookupSubNet(const std::string& strSubnet, CSubNet& ret, DNSLookupFn dns_lookup_function)
# 679 : 279 : {
# 680 [ + + ]: 279 : if (!ValidAsCString(strSubnet)) {
# 681 : 12 : return false;
# 682 : 12 : }
# 683 : 267 : size_t slash = strSubnet.find_last_of('/');
# 684 : 267 : std::vector<CNetAddr> vIP;
# 685 : :
# 686 : 267 : std::string strAddress = strSubnet.substr(0, slash);
# 687 : : // TODO: Use LookupHost(const std::string&, CNetAddr&, bool) instead to just get
# 688 : : // one CNetAddr.
# 689 [ + + ]: 267 : if (LookupHost(strAddress, vIP, 1, false, dns_lookup_function))
# 690 : 256 : {
# 691 : 256 : CNetAddr network = vIP[0];
# 692 [ + + ]: 256 : if (slash != strSubnet.npos)
# 693 : 160 : {
# 694 : 160 : std::string strNetmask = strSubnet.substr(slash + 1);
# 695 : 160 : uint8_t n;
# 696 [ + + ]: 160 : if (ParseUInt8(strNetmask, &n)) {
# 697 : : // If valid number, assume CIDR variable-length subnet masking
# 698 : 68 : ret = CSubNet(network, n);
# 699 : 68 : return ret.IsValid();
# 700 : 68 : }
# 701 : 92 : else // If not a valid number, try full netmask syntax
# 702 : 92 : {
# 703 : : // Never allow lookup for netmask
# 704 [ + + ]: 92 : if (LookupHost(strNetmask, vIP, 1, false, dns_lookup_function)) {
# 705 : 88 : ret = CSubNet(network, vIP[0]);
# 706 : 88 : return ret.IsValid();
# 707 : 88 : }
# 708 : 96 : }
# 709 : 96 : }
# 710 : 96 : else
# 711 : 96 : {
# 712 : 96 : ret = CSubNet(network);
# 713 : 96 : return ret.IsValid();
# 714 : 96 : }
# 715 : 15 : }
# 716 : 15 : return false;
# 717 : 15 : }
# 718 : :
# 719 : : bool SetSocketNonBlocking(const SOCKET& hSocket, bool fNonBlocking)
# 720 : 1786 : {
# 721 [ + - ]: 1786 : if (fNonBlocking) {
# 722 : : #ifdef WIN32
# 723 : : u_long nOne = 1;
# 724 : : if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR) {
# 725 : : #else
# 726 : 1786 : int fFlags = fcntl(hSocket, F_GETFL, 0);
# 727 [ - + ]: 1786 : if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == SOCKET_ERROR) {
# 728 : 0 : #endif
# 729 : 0 : return false;
# 730 : 0 : }
# 731 : 0 : } else {
# 732 : : #ifdef WIN32
# 733 : : u_long nZero = 0;
# 734 : : if (ioctlsocket(hSocket, FIONBIO, &nZero) == SOCKET_ERROR) {
# 735 : : #else
# 736 : 0 : int fFlags = fcntl(hSocket, F_GETFL, 0);
# 737 [ # # ]: 0 : if (fcntl(hSocket, F_SETFL, fFlags & ~O_NONBLOCK) == SOCKET_ERROR) {
# 738 : 0 : #endif
# 739 : 0 : return false;
# 740 : 0 : }
# 741 : 1786 : }
# 742 : :
# 743 : 1786 : return true;
# 744 : 1786 : }
# 745 : :
# 746 : : bool SetSocketNoDelay(const SOCKET& hSocket)
# 747 : 2399 : {
# 748 : 2399 : int set = 1;
# 749 : 2399 : int rc = setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&set, sizeof(int));
# 750 : 2399 : return rc == 0;
# 751 : 2399 : }
# 752 : :
# 753 : : void InterruptSocks5(bool interrupt)
# 754 : 2051 : {
# 755 : 2051 : interruptSocks5Recv = interrupt;
# 756 : 2051 : }
|