torcontrol.cpp
1 // Copyright (c) 2015-2022 The Bitcoin Core developers 2 // Copyright (c) 2017 The Zcash 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 <torcontrol.h> 7 8 #include <chainparams.h> 9 #include <chainparamsbase.h> 10 #include <common/args.h> 11 #include <compat/compat.h> 12 #include <crypto/hmac_sha256.h> 13 #include <logging.h> 14 #include <net.h> 15 #include <netaddress.h> 16 #include <netbase.h> 17 #include <random.h> 18 #include <tinyformat.h> 19 #include <util/check.h> 20 #include <util/fs.h> 21 #include <util/readwritefile.h> 22 #include <util/strencodings.h> 23 #include <util/string.h> 24 #include <util/thread.h> 25 #include <util/time.h> 26 27 #include <algorithm> 28 #include <cassert> 29 #include <cstdlib> 30 #include <deque> 31 #include <functional> 32 #include <map> 33 #include <optional> 34 #include <set> 35 #include <thread> 36 #include <utility> 37 #include <vector> 38 39 #include <event2/buffer.h> 40 #include <event2/bufferevent.h> 41 #include <event2/event.h> 42 #include <event2/thread.h> 43 #include <event2/util.h> 44 45 /** Default control ip and port */ 46 const std::string DEFAULT_TOR_CONTROL = "127.0.0.1:" + ToString(DEFAULT_TOR_CONTROL_PORT); 47 /** Tor cookie size (from control-spec.txt) */ 48 static const int TOR_COOKIE_SIZE = 32; 49 /** Size of client/server nonce for SAFECOOKIE */ 50 static const int TOR_NONCE_SIZE = 32; 51 /** For computing serverHash in SAFECOOKIE */ 52 static const std::string TOR_SAFE_SERVERKEY = "Tor safe cookie authentication server-to-controller hash"; 53 /** For computing clientHash in SAFECOOKIE */ 54 static const std::string TOR_SAFE_CLIENTKEY = "Tor safe cookie authentication controller-to-server hash"; 55 /** Exponential backoff configuration - initial timeout in seconds */ 56 static const float RECONNECT_TIMEOUT_START = 1.0; 57 /** Exponential backoff configuration - growth factor */ 58 static const float RECONNECT_TIMEOUT_EXP = 1.5; 59 /** Maximum length for lines received on TorControlConnection. 60 * tor-control-spec.txt mentions that there is explicitly no limit defined to line length, 61 * this is belt-and-suspenders sanity limit to prevent memory exhaustion. 62 */ 63 static const int MAX_LINE_LENGTH = 100000; 64 static const uint16_t DEFAULT_TOR_SOCKS_PORT = 9050; 65 66 /****** Low-level TorControlConnection ********/ 67 68 TorControlConnection::TorControlConnection(struct event_base* _base) 69 : base(_base) 70 { 71 } 72 73 TorControlConnection::~TorControlConnection() 74 { 75 if (b_conn) 76 bufferevent_free(b_conn); 77 } 78 79 void TorControlConnection::readcb(struct bufferevent *bev, void *ctx) 80 { 81 TorControlConnection *self = static_cast<TorControlConnection*>(ctx); 82 struct evbuffer *input = bufferevent_get_input(bev); 83 size_t n_read_out = 0; 84 char *line; 85 assert(input); 86 // If there is not a whole line to read, evbuffer_readln returns nullptr 87 while((line = evbuffer_readln(input, &n_read_out, EVBUFFER_EOL_CRLF)) != nullptr) 88 { 89 std::string s(line, n_read_out); 90 free(line); 91 if (s.size() < 4) // Short line 92 continue; 93 // <status>(-|+| )<data><CRLF> 94 self->message.code = ToIntegral<int>(s.substr(0, 3)).value_or(0); 95 self->message.lines.push_back(s.substr(4)); 96 char ch = s[3]; // '-','+' or ' ' 97 if (ch == ' ') { 98 // Final line, dispatch reply and clean up 99 if (self->message.code >= 600) { 100 // (currently unused) 101 // Dispatch async notifications to async handler 102 // Synchronous and asynchronous messages are never interleaved 103 } else { 104 if (!self->reply_handlers.empty()) { 105 // Invoke reply handler with message 106 self->reply_handlers.front()(*self, self->message); 107 self->reply_handlers.pop_front(); 108 } else { 109 LogPrint(BCLog::TOR, "Received unexpected sync reply %i\n", self->message.code); 110 } 111 } 112 self->message.Clear(); 113 } 114 } 115 // Check for size of buffer - protect against memory exhaustion with very long lines 116 // Do this after evbuffer_readln to make sure all full lines have been 117 // removed from the buffer. Everything left is an incomplete line. 118 if (evbuffer_get_length(input) > MAX_LINE_LENGTH) { 119 LogPrintf("tor: Disconnecting because MAX_LINE_LENGTH exceeded\n"); 120 self->Disconnect(); 121 } 122 } 123 124 void TorControlConnection::eventcb(struct bufferevent *bev, short what, void *ctx) 125 { 126 TorControlConnection *self = static_cast<TorControlConnection*>(ctx); 127 if (what & BEV_EVENT_CONNECTED) { 128 LogPrint(BCLog::TOR, "Successfully connected!\n"); 129 self->connected(*self); 130 } else if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) { 131 if (what & BEV_EVENT_ERROR) { 132 LogPrint(BCLog::TOR, "Error connecting to Tor control socket\n"); 133 } else { 134 LogPrint(BCLog::TOR, "End of stream\n"); 135 } 136 self->Disconnect(); 137 self->disconnected(*self); 138 } 139 } 140 141 bool TorControlConnection::Connect(const std::string& tor_control_center, const ConnectionCB& _connected, const ConnectionCB& _disconnected) 142 { 143 if (b_conn) { 144 Disconnect(); 145 } 146 147 const std::optional<CService> control_service{Lookup(tor_control_center, DEFAULT_TOR_CONTROL_PORT, fNameLookup)}; 148 if (!control_service.has_value()) { 149 LogPrintf("tor: Failed to look up control center %s\n", tor_control_center); 150 return false; 151 } 152 153 struct sockaddr_storage control_address; 154 socklen_t control_address_len = sizeof(control_address); 155 if (!control_service.value().GetSockAddr(reinterpret_cast<struct sockaddr*>(&control_address), &control_address_len)) { 156 LogPrintf("tor: Error parsing socket address %s\n", tor_control_center); 157 return false; 158 } 159 160 // Create a new socket, set up callbacks and enable notification bits 161 b_conn = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE); 162 if (!b_conn) { 163 return false; 164 } 165 bufferevent_setcb(b_conn, TorControlConnection::readcb, nullptr, TorControlConnection::eventcb, this); 166 bufferevent_enable(b_conn, EV_READ|EV_WRITE); 167 this->connected = _connected; 168 this->disconnected = _disconnected; 169 170 // Finally, connect to tor_control_center 171 if (bufferevent_socket_connect(b_conn, reinterpret_cast<struct sockaddr*>(&control_address), control_address_len) < 0) { 172 LogPrintf("tor: Error connecting to address %s\n", tor_control_center); 173 return false; 174 } 175 return true; 176 } 177 178 void TorControlConnection::Disconnect() 179 { 180 if (b_conn) 181 bufferevent_free(b_conn); 182 b_conn = nullptr; 183 } 184 185 bool TorControlConnection::Command(const std::string &cmd, const ReplyHandlerCB& reply_handler) 186 { 187 if (!b_conn) 188 return false; 189 struct evbuffer *buf = bufferevent_get_output(b_conn); 190 if (!buf) 191 return false; 192 evbuffer_add(buf, cmd.data(), cmd.size()); 193 evbuffer_add(buf, "\r\n", 2); 194 reply_handlers.push_back(reply_handler); 195 return true; 196 } 197 198 /****** General parsing utilities ********/ 199 200 /* Split reply line in the form 'AUTH METHODS=...' into a type 201 * 'AUTH' and arguments 'METHODS=...'. 202 * Grammar is implicitly defined in https://spec.torproject.org/control-spec by 203 * the server reply formats for PROTOCOLINFO (S3.21) and AUTHCHALLENGE (S3.24). 204 */ 205 std::pair<std::string,std::string> SplitTorReplyLine(const std::string &s) 206 { 207 size_t ptr=0; 208 std::string type; 209 while (ptr < s.size() && s[ptr] != ' ') { 210 type.push_back(s[ptr]); 211 ++ptr; 212 } 213 if (ptr < s.size()) 214 ++ptr; // skip ' ' 215 return make_pair(type, s.substr(ptr)); 216 } 217 218 /** Parse reply arguments in the form 'METHODS=COOKIE,SAFECOOKIE COOKIEFILE=".../control_auth_cookie"'. 219 * Returns a map of keys to values, or an empty map if there was an error. 220 * Grammar is implicitly defined in https://spec.torproject.org/control-spec by 221 * the server reply formats for PROTOCOLINFO (S3.21), AUTHCHALLENGE (S3.24), 222 * and ADD_ONION (S3.27). See also sections 2.1 and 2.3. 223 */ 224 std::map<std::string,std::string> ParseTorReplyMapping(const std::string &s) 225 { 226 std::map<std::string,std::string> mapping; 227 size_t ptr=0; 228 while (ptr < s.size()) { 229 std::string key, value; 230 while (ptr < s.size() && s[ptr] != '=' && s[ptr] != ' ') { 231 key.push_back(s[ptr]); 232 ++ptr; 233 } 234 if (ptr == s.size()) // unexpected end of line 235 return std::map<std::string,std::string>(); 236 if (s[ptr] == ' ') // The remaining string is an OptArguments 237 break; 238 ++ptr; // skip '=' 239 if (ptr < s.size() && s[ptr] == '"') { // Quoted string 240 ++ptr; // skip opening '"' 241 bool escape_next = false; 242 while (ptr < s.size() && (escape_next || s[ptr] != '"')) { 243 // Repeated backslashes must be interpreted as pairs 244 escape_next = (s[ptr] == '\\' && !escape_next); 245 value.push_back(s[ptr]); 246 ++ptr; 247 } 248 if (ptr == s.size()) // unexpected end of line 249 return std::map<std::string,std::string>(); 250 ++ptr; // skip closing '"' 251 /** 252 * Unescape value. Per https://spec.torproject.org/control-spec section 2.1.1: 253 * 254 * For future-proofing, controller implementers MAY use the following 255 * rules to be compatible with buggy Tor implementations and with 256 * future ones that implement the spec as intended: 257 * 258 * Read \n \t \r and \0 ... \377 as C escapes. 259 * Treat a backslash followed by any other character as that character. 260 */ 261 std::string escaped_value; 262 for (size_t i = 0; i < value.size(); ++i) { 263 if (value[i] == '\\') { 264 // This will always be valid, because if the QuotedString 265 // ended in an odd number of backslashes, then the parser 266 // would already have returned above, due to a missing 267 // terminating double-quote. 268 ++i; 269 if (value[i] == 'n') { 270 escaped_value.push_back('\n'); 271 } else if (value[i] == 't') { 272 escaped_value.push_back('\t'); 273 } else if (value[i] == 'r') { 274 escaped_value.push_back('\r'); 275 } else if ('0' <= value[i] && value[i] <= '7') { 276 size_t j; 277 // Octal escape sequences have a limit of three octal digits, 278 // but terminate at the first character that is not a valid 279 // octal digit if encountered sooner. 280 for (j = 1; j < 3 && (i+j) < value.size() && '0' <= value[i+j] && value[i+j] <= '7'; ++j) {} 281 // Tor restricts first digit to 0-3 for three-digit octals. 282 // A leading digit of 4-7 would therefore be interpreted as 283 // a two-digit octal. 284 if (j == 3 && value[i] > '3') { 285 j--; 286 } 287 const auto end{i + j}; 288 uint8_t val{0}; 289 while (i < end) { 290 val *= 8; 291 val += value[i++] - '0'; 292 } 293 escaped_value.push_back(char(val)); 294 // Account for automatic incrementing at loop end 295 --i; 296 } else { 297 escaped_value.push_back(value[i]); 298 } 299 } else { 300 escaped_value.push_back(value[i]); 301 } 302 } 303 value = escaped_value; 304 } else { // Unquoted value. Note that values can contain '=' at will, just no spaces 305 while (ptr < s.size() && s[ptr] != ' ') { 306 value.push_back(s[ptr]); 307 ++ptr; 308 } 309 } 310 if (ptr < s.size() && s[ptr] == ' ') 311 ++ptr; // skip ' ' after key=value 312 mapping[key] = value; 313 } 314 return mapping; 315 } 316 317 TorController::TorController(struct event_base* _base, const std::string& tor_control_center, const CService& target): 318 base(_base), 319 m_tor_control_center(tor_control_center), conn(base), reconnect(true), reconnect_timeout(RECONNECT_TIMEOUT_START), 320 m_target(target) 321 { 322 reconnect_ev = event_new(base, -1, 0, reconnect_cb, this); 323 if (!reconnect_ev) 324 LogPrintf("tor: Failed to create event for reconnection: out of memory?\n"); 325 // Start connection attempts immediately 326 if (!conn.Connect(m_tor_control_center, std::bind(&TorController::connected_cb, this, std::placeholders::_1), 327 std::bind(&TorController::disconnected_cb, this, std::placeholders::_1) )) { 328 LogPrintf("tor: Initiating connection to Tor control port %s failed\n", m_tor_control_center); 329 } 330 // Read service private key if cached 331 std::pair<bool,std::string> pkf = ReadBinaryFile(GetPrivateKeyFile()); 332 if (pkf.first) { 333 LogPrint(BCLog::TOR, "Reading cached private key from %s\n", fs::PathToString(GetPrivateKeyFile())); 334 private_key = pkf.second; 335 } 336 } 337 338 TorController::~TorController() 339 { 340 if (reconnect_ev) { 341 event_free(reconnect_ev); 342 reconnect_ev = nullptr; 343 } 344 if (service.IsValid()) { 345 RemoveLocal(service); 346 } 347 } 348 349 void TorController::get_socks_cb(TorControlConnection& _conn, const TorControlReply& reply) 350 { 351 // NOTE: We can only get here if -onion is unset 352 std::string socks_location; 353 if (reply.code == 250) { 354 for (const auto& line : reply.lines) { 355 if (0 == line.compare(0, 20, "net/listeners/socks=")) { 356 const std::string port_list_str = line.substr(20); 357 std::vector<std::string> port_list = SplitString(port_list_str, ' '); 358 359 for (auto& portstr : port_list) { 360 if (portstr.empty()) continue; 361 if ((portstr[0] == '"' || portstr[0] == '\'') && portstr.size() >= 2 && (*portstr.rbegin() == portstr[0])) { 362 portstr = portstr.substr(1, portstr.size() - 2); 363 if (portstr.empty()) continue; 364 } 365 socks_location = portstr; 366 if (0 == portstr.compare(0, 10, "127.0.0.1:")) { 367 // Prefer localhost - ignore other ports 368 break; 369 } 370 } 371 } 372 } 373 if (!socks_location.empty()) { 374 LogPrint(BCLog::TOR, "Get SOCKS port command yielded %s\n", socks_location); 375 } else { 376 LogPrintf("tor: Get SOCKS port command returned nothing\n"); 377 } 378 } else if (reply.code == 510) { // 510 Unrecognized command 379 LogPrintf("tor: Get SOCKS port command failed with unrecognized command (You probably should upgrade Tor)\n"); 380 } else { 381 LogPrintf("tor: Get SOCKS port command failed; error code %d\n", reply.code); 382 } 383 384 CService resolved; 385 Assume(!resolved.IsValid()); 386 if (!socks_location.empty()) { 387 resolved = LookupNumeric(socks_location, DEFAULT_TOR_SOCKS_PORT); 388 } 389 if (!resolved.IsValid()) { 390 // Fallback to old behaviour 391 resolved = LookupNumeric("127.0.0.1", DEFAULT_TOR_SOCKS_PORT); 392 } 393 394 Assume(resolved.IsValid()); 395 LogPrint(BCLog::TOR, "Configuring onion proxy for %s\n", resolved.ToStringAddrPort()); 396 Proxy addrOnion = Proxy(resolved, true); 397 SetProxy(NET_ONION, addrOnion); 398 399 const auto onlynets = gArgs.GetArgs("-onlynet"); 400 401 const bool onion_allowed_by_onlynet{ 402 !gArgs.IsArgSet("-onlynet") || 403 std::any_of(onlynets.begin(), onlynets.end(), [](const auto& n) { 404 return ParseNetwork(n) == NET_ONION; 405 })}; 406 407 if (onion_allowed_by_onlynet) { 408 // If NET_ONION is reachable, then the below is a noop. 409 // 410 // If NET_ONION is not reachable, then none of -proxy or -onion was given. 411 // Since we are here, then -torcontrol and -torpassword were given. 412 g_reachable_nets.Add(NET_ONION); 413 } 414 } 415 416 void TorController::add_onion_cb(TorControlConnection& _conn, const TorControlReply& reply) 417 { 418 if (reply.code == 250) { 419 LogPrint(BCLog::TOR, "ADD_ONION successful\n"); 420 for (const std::string &s : reply.lines) { 421 std::map<std::string,std::string> m = ParseTorReplyMapping(s); 422 std::map<std::string,std::string>::iterator i; 423 if ((i = m.find("ServiceID")) != m.end()) 424 service_id = i->second; 425 if ((i = m.find("PrivateKey")) != m.end()) 426 private_key = i->second; 427 } 428 if (service_id.empty()) { 429 LogPrintf("tor: Error parsing ADD_ONION parameters:\n"); 430 for (const std::string &s : reply.lines) { 431 LogPrintf(" %s\n", SanitizeString(s)); 432 } 433 return; 434 } 435 service = LookupNumeric(std::string(service_id+".onion"), Params().GetDefaultPort()); 436 LogInfo("Got tor service ID %s, advertising service %s\n", service_id, service.ToStringAddrPort()); 437 if (WriteBinaryFile(GetPrivateKeyFile(), private_key)) { 438 LogPrint(BCLog::TOR, "Cached service private key to %s\n", fs::PathToString(GetPrivateKeyFile())); 439 } else { 440 LogPrintf("tor: Error writing service private key to %s\n", fs::PathToString(GetPrivateKeyFile())); 441 } 442 AddLocal(service, LOCAL_MANUAL); 443 // ... onion requested - keep connection open 444 } else if (reply.code == 510) { // 510 Unrecognized command 445 LogPrintf("tor: Add onion failed with unrecognized command (You probably need to upgrade Tor)\n"); 446 } else { 447 LogPrintf("tor: Add onion failed; error code %d\n", reply.code); 448 } 449 } 450 451 void TorController::auth_cb(TorControlConnection& _conn, const TorControlReply& reply) 452 { 453 if (reply.code == 250) { 454 LogPrint(BCLog::TOR, "Authentication successful\n"); 455 456 // Now that we know Tor is running setup the proxy for onion addresses 457 // if -onion isn't set to something else. 458 if (gArgs.GetArg("-onion", "") == "") { 459 _conn.Command("GETINFO net/listeners/socks", std::bind(&TorController::get_socks_cb, this, std::placeholders::_1, std::placeholders::_2)); 460 } 461 462 // Finally - now create the service 463 if (private_key.empty()) { // No private key, generate one 464 private_key = "NEW:ED25519-V3"; // Explicitly request key type - see issue #9214 465 } 466 // Request onion service, redirect port. 467 // Note that the 'virtual' port is always the default port to avoid decloaking nodes using other ports. 468 _conn.Command(strprintf("ADD_ONION %s Port=%i,%s", private_key, Params().GetDefaultPort(), m_target.ToStringAddrPort()), 469 std::bind(&TorController::add_onion_cb, this, std::placeholders::_1, std::placeholders::_2)); 470 } else { 471 LogPrintf("tor: Authentication failed\n"); 472 } 473 } 474 475 /** Compute Tor SAFECOOKIE response. 476 * 477 * ServerHash is computed as: 478 * HMAC-SHA256("Tor safe cookie authentication server-to-controller hash", 479 * CookieString | ClientNonce | ServerNonce) 480 * (with the HMAC key as its first argument) 481 * 482 * After a controller sends a successful AUTHCHALLENGE command, the 483 * next command sent on the connection must be an AUTHENTICATE command, 484 * and the only authentication string which that AUTHENTICATE command 485 * will accept is: 486 * 487 * HMAC-SHA256("Tor safe cookie authentication controller-to-server hash", 488 * CookieString | ClientNonce | ServerNonce) 489 * 490 */ 491 static std::vector<uint8_t> ComputeResponse(const std::string &key, const std::vector<uint8_t> &cookie, const std::vector<uint8_t> &clientNonce, const std::vector<uint8_t> &serverNonce) 492 { 493 CHMAC_SHA256 computeHash((const uint8_t*)key.data(), key.size()); 494 std::vector<uint8_t> computedHash(CHMAC_SHA256::OUTPUT_SIZE, 0); 495 computeHash.Write(cookie.data(), cookie.size()); 496 computeHash.Write(clientNonce.data(), clientNonce.size()); 497 computeHash.Write(serverNonce.data(), serverNonce.size()); 498 computeHash.Finalize(computedHash.data()); 499 return computedHash; 500 } 501 502 void TorController::authchallenge_cb(TorControlConnection& _conn, const TorControlReply& reply) 503 { 504 if (reply.code == 250) { 505 LogPrint(BCLog::TOR, "SAFECOOKIE authentication challenge successful\n"); 506 std::pair<std::string,std::string> l = SplitTorReplyLine(reply.lines[0]); 507 if (l.first == "AUTHCHALLENGE") { 508 std::map<std::string,std::string> m = ParseTorReplyMapping(l.second); 509 if (m.empty()) { 510 LogPrintf("tor: Error parsing AUTHCHALLENGE parameters: %s\n", SanitizeString(l.second)); 511 return; 512 } 513 std::vector<uint8_t> serverHash = ParseHex(m["SERVERHASH"]); 514 std::vector<uint8_t> serverNonce = ParseHex(m["SERVERNONCE"]); 515 LogPrint(BCLog::TOR, "AUTHCHALLENGE ServerHash %s ServerNonce %s\n", HexStr(serverHash), HexStr(serverNonce)); 516 if (serverNonce.size() != 32) { 517 LogPrintf("tor: ServerNonce is not 32 bytes, as required by spec\n"); 518 return; 519 } 520 521 std::vector<uint8_t> computedServerHash = ComputeResponse(TOR_SAFE_SERVERKEY, cookie, clientNonce, serverNonce); 522 if (computedServerHash != serverHash) { 523 LogPrintf("tor: ServerHash %s does not match expected ServerHash %s\n", HexStr(serverHash), HexStr(computedServerHash)); 524 return; 525 } 526 527 std::vector<uint8_t> computedClientHash = ComputeResponse(TOR_SAFE_CLIENTKEY, cookie, clientNonce, serverNonce); 528 _conn.Command("AUTHENTICATE " + HexStr(computedClientHash), std::bind(&TorController::auth_cb, this, std::placeholders::_1, std::placeholders::_2)); 529 } else { 530 LogPrintf("tor: Invalid reply to AUTHCHALLENGE\n"); 531 } 532 } else { 533 LogPrintf("tor: SAFECOOKIE authentication challenge failed\n"); 534 } 535 } 536 537 void TorController::protocolinfo_cb(TorControlConnection& _conn, const TorControlReply& reply) 538 { 539 if (reply.code == 250) { 540 std::set<std::string> methods; 541 std::string cookiefile; 542 /* 543 * 250-AUTH METHODS=COOKIE,SAFECOOKIE COOKIEFILE="/home/x/.tor/control_auth_cookie" 544 * 250-AUTH METHODS=NULL 545 * 250-AUTH METHODS=HASHEDPASSWORD 546 */ 547 for (const std::string &s : reply.lines) { 548 std::pair<std::string,std::string> l = SplitTorReplyLine(s); 549 if (l.first == "AUTH") { 550 std::map<std::string,std::string> m = ParseTorReplyMapping(l.second); 551 std::map<std::string,std::string>::iterator i; 552 if ((i = m.find("METHODS")) != m.end()) { 553 std::vector<std::string> m_vec = SplitString(i->second, ','); 554 methods = std::set<std::string>(m_vec.begin(), m_vec.end()); 555 } 556 if ((i = m.find("COOKIEFILE")) != m.end()) 557 cookiefile = i->second; 558 } else if (l.first == "VERSION") { 559 std::map<std::string,std::string> m = ParseTorReplyMapping(l.second); 560 std::map<std::string,std::string>::iterator i; 561 if ((i = m.find("Tor")) != m.end()) { 562 LogPrint(BCLog::TOR, "Connected to Tor version %s\n", i->second); 563 } 564 } 565 } 566 for (const std::string &s : methods) { 567 LogPrint(BCLog::TOR, "Supported authentication method: %s\n", s); 568 } 569 // Prefer NULL, otherwise SAFECOOKIE. If a password is provided, use HASHEDPASSWORD 570 /* Authentication: 571 * cookie: hex-encoded ~/.tor/control_auth_cookie 572 * password: "password" 573 */ 574 std::string torpassword = gArgs.GetArg("-torpassword", ""); 575 if (!torpassword.empty()) { 576 if (methods.count("HASHEDPASSWORD")) { 577 LogPrint(BCLog::TOR, "Using HASHEDPASSWORD authentication\n"); 578 ReplaceAll(torpassword, "\"", "\\\""); 579 _conn.Command("AUTHENTICATE \"" + torpassword + "\"", std::bind(&TorController::auth_cb, this, std::placeholders::_1, std::placeholders::_2)); 580 } else { 581 LogPrintf("tor: Password provided with -torpassword, but HASHEDPASSWORD authentication is not available\n"); 582 } 583 } else if (methods.count("NULL")) { 584 LogPrint(BCLog::TOR, "Using NULL authentication\n"); 585 _conn.Command("AUTHENTICATE", std::bind(&TorController::auth_cb, this, std::placeholders::_1, std::placeholders::_2)); 586 } else if (methods.count("SAFECOOKIE")) { 587 // Cookie: hexdump -e '32/1 "%02x""\n"' ~/.tor/control_auth_cookie 588 LogPrint(BCLog::TOR, "Using SAFECOOKIE authentication, reading cookie authentication from %s\n", cookiefile); 589 std::pair<bool,std::string> status_cookie = ReadBinaryFile(fs::PathFromString(cookiefile), TOR_COOKIE_SIZE); 590 if (status_cookie.first && status_cookie.second.size() == TOR_COOKIE_SIZE) { 591 // _conn.Command("AUTHENTICATE " + HexStr(status_cookie.second), std::bind(&TorController::auth_cb, this, std::placeholders::_1, std::placeholders::_2)); 592 cookie = std::vector<uint8_t>(status_cookie.second.begin(), status_cookie.second.end()); 593 clientNonce = std::vector<uint8_t>(TOR_NONCE_SIZE, 0); 594 GetRandBytes(clientNonce); 595 _conn.Command("AUTHCHALLENGE SAFECOOKIE " + HexStr(clientNonce), std::bind(&TorController::authchallenge_cb, this, std::placeholders::_1, std::placeholders::_2)); 596 } else { 597 if (status_cookie.first) { 598 LogPrintf("tor: Authentication cookie %s is not exactly %i bytes, as is required by the spec\n", cookiefile, TOR_COOKIE_SIZE); 599 } else { 600 LogPrintf("tor: Authentication cookie %s could not be opened (check permissions)\n", cookiefile); 601 } 602 } 603 } else if (methods.count("HASHEDPASSWORD")) { 604 LogPrintf("tor: The only supported authentication mechanism left is password, but no password provided with -torpassword\n"); 605 } else { 606 LogPrintf("tor: No supported authentication method\n"); 607 } 608 } else { 609 LogPrintf("tor: Requesting protocol info failed\n"); 610 } 611 } 612 613 void TorController::connected_cb(TorControlConnection& _conn) 614 { 615 reconnect_timeout = RECONNECT_TIMEOUT_START; 616 // First send a PROTOCOLINFO command to figure out what authentication is expected 617 if (!_conn.Command("PROTOCOLINFO 1", std::bind(&TorController::protocolinfo_cb, this, std::placeholders::_1, std::placeholders::_2))) 618 LogPrintf("tor: Error sending initial protocolinfo command\n"); 619 } 620 621 void TorController::disconnected_cb(TorControlConnection& _conn) 622 { 623 // Stop advertising service when disconnected 624 if (service.IsValid()) 625 RemoveLocal(service); 626 service = CService(); 627 if (!reconnect) 628 return; 629 630 LogPrint(BCLog::TOR, "Not connected to Tor control port %s, trying to reconnect\n", m_tor_control_center); 631 632 // Single-shot timer for reconnect. Use exponential backoff. 633 struct timeval time = MillisToTimeval(int64_t(reconnect_timeout * 1000.0)); 634 if (reconnect_ev) 635 event_add(reconnect_ev, &time); 636 reconnect_timeout *= RECONNECT_TIMEOUT_EXP; 637 } 638 639 void TorController::Reconnect() 640 { 641 /* Try to reconnect and reestablish if we get booted - for example, Tor 642 * may be restarting. 643 */ 644 if (!conn.Connect(m_tor_control_center, std::bind(&TorController::connected_cb, this, std::placeholders::_1), 645 std::bind(&TorController::disconnected_cb, this, std::placeholders::_1) )) { 646 LogPrintf("tor: Re-initiating connection to Tor control port %s failed\n", m_tor_control_center); 647 } 648 } 649 650 fs::path TorController::GetPrivateKeyFile() 651 { 652 return gArgs.GetDataDirNet() / "onion_v3_private_key"; 653 } 654 655 void TorController::reconnect_cb(evutil_socket_t fd, short what, void *arg) 656 { 657 TorController *self = static_cast<TorController*>(arg); 658 self->Reconnect(); 659 } 660 661 /****** Thread ********/ 662 static struct event_base *gBase; 663 static std::thread torControlThread; 664 665 static void TorControlThread(CService onion_service_target) 666 { 667 TorController ctrl(gBase, gArgs.GetArg("-torcontrol", DEFAULT_TOR_CONTROL), onion_service_target); 668 669 event_base_dispatch(gBase); 670 } 671 672 void StartTorControl(CService onion_service_target) 673 { 674 assert(!gBase); 675 #ifdef WIN32 676 evthread_use_windows_threads(); 677 #else 678 evthread_use_pthreads(); 679 #endif 680 gBase = event_base_new(); 681 if (!gBase) { 682 LogPrintf("tor: Unable to create event_base\n"); 683 return; 684 } 685 686 torControlThread = std::thread(&util::TraceThread, "torcontrol", [onion_service_target] { 687 TorControlThread(onion_service_target); 688 }); 689 } 690 691 void InterruptTorControl() 692 { 693 if (gBase) { 694 LogPrintf("tor: Thread interrupt\n"); 695 event_base_once(gBase, -1, EV_TIMEOUT, [](evutil_socket_t, short, void*) { 696 event_base_loopbreak(gBase); 697 }, nullptr, nullptr); 698 } 699 } 700 701 void StopTorControl() 702 { 703 if (gBase) { 704 torControlThread.join(); 705 event_base_free(gBase); 706 gBase = nullptr; 707 } 708 } 709 710 CService DefaultOnionServiceTarget() 711 { 712 struct in_addr onion_service_target; 713 onion_service_target.s_addr = htonl(INADDR_LOOPBACK); 714 return {onion_service_target, BaseParams().OnionServiceTargetPort()}; 715 }