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