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