diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 9abc1fc032f..ffb783162ba 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -53,7 +53,7 @@ const std::string DEFAULT_TOR_CONTROL = "127.0.0.1:" + ToString(DEFAULT_TOR_CONT constexpr int TOR_COOKIE_SIZE = 32; /** Size of client/server nonce for SAFECOOKIE */ constexpr int TOR_NONCE_SIZE = 32; -/** For computing serverHash in SAFECOOKIE */ +/** For computing server_hash in SAFECOOKIE */ static const std::string TOR_SAFE_SERVERKEY = "Tor safe cookie authentication server-to-controller hash"; /** For computing clientHash in SAFECOOKIE */ static const std::string TOR_SAFE_CLIENTKEY = "Tor safe cookie authentication controller-to-server hash"; @@ -97,25 +97,25 @@ void TorControlConnection::readcb(struct bufferevent *bev, void *ctx) if (s.size() < 4) // Short line continue; // (-|+| ) - self->message.code = ToIntegral(s.substr(0, 3)).value_or(0); - self->message.lines.push_back(s.substr(4)); + self->m_message.code = ToIntegral(s.substr(0, 3)).value_or(0); + self->m_message.lines.push_back(s.substr(4)); char ch = s[3]; // '-','+' or ' ' if (ch == ' ') { // Final line, dispatch reply and clean up - if (self->message.code >= 600) { + if (self->m_message.code >= 600) { // (currently unused) // Dispatch async notifications to async handler // Synchronous and asynchronous messages are never interleaved } else { if (!self->reply_handlers.empty()) { // Invoke reply handler with message - self->reply_handlers.front()(*self, self->message); + self->reply_handlers.front()(*self, self->m_message); self->reply_handlers.pop_front(); } else { - LogDebug(BCLog::TOR, "Received unexpected sync reply %i\n", self->message.code); + LogDebug(BCLog::TOR, "Received unexpected sync reply %i\n", self->m_message.code); } } - self->message.Clear(); + self->m_message.Clear(); } } // Check for size of buffer - protect against memory exhaustion with very long lines @@ -322,14 +322,14 @@ std::map ParseTorReplyMapping(const std::string &s) TorController::TorController(struct event_base* _base, const std::string& tor_control_center, const CService& target): base(_base), - m_tor_control_center(tor_control_center), conn(base), reconnect(true), reconnect_timeout(RECONNECT_TIMEOUT_START), + m_tor_control_center(tor_control_center), m_conn(base), m_reconnect(true), m_reconnect_timeout(RECONNECT_TIMEOUT_START), m_target(target) { reconnect_ev = event_new(base, -1, 0, reconnect_cb, this); if (!reconnect_ev) LogWarning("tor: Failed to create event for reconnection: out of memory?"); // Start connection attempts immediately - if (!conn.Connect(m_tor_control_center, std::bind_front(&TorController::connected_cb, this), + if (!m_conn.Connect(m_tor_control_center, std::bind_front(&TorController::connected_cb, this), std::bind_front(&TorController::disconnected_cb, this) )) { LogWarning("tor: Initiating connection to Tor control port %s failed", m_tor_control_center); } @@ -337,7 +337,7 @@ TorController::TorController(struct event_base* _base, const std::string& tor_co std::pair pkf = ReadBinaryFile(GetPrivateKeyFile()); if (pkf.first) { LogDebug(BCLog::TOR, "Reading cached private key from %s\n", fs::PathToString(GetPrivateKeyFile())); - private_key = pkf.second; + m_private_key = pkf.second; } } @@ -347,8 +347,8 @@ TorController::~TorController() event_free(reconnect_ev); reconnect_ev = nullptr; } - if (service.IsValid()) { - RemoveLocal(service); + if (m_service.IsValid()) { + RemoveLocal(m_service); } } @@ -441,31 +441,31 @@ void TorController::add_onion_cb(TorControlConnection& _conn, const TorControlRe std::map m = ParseTorReplyMapping(s); std::map::iterator i; if ((i = m.find("ServiceID")) != m.end()) - service_id = i->second; + m_service_id = i->second; if ((i = m.find("PrivateKey")) != m.end()) - private_key = i->second; + m_private_key = i->second; } - if (service_id.empty()) { + if (m_service_id.empty()) { LogWarning("tor: Error parsing ADD_ONION parameters:"); for (const std::string &s : reply.lines) { LogWarning(" %s", SanitizeString(s)); } return; } - service = LookupNumeric(std::string(service_id+".onion"), Params().GetDefaultPort()); - LogInfo("Got tor service ID %s, advertising service %s\n", service_id, service.ToStringAddrPort()); - if (WriteBinaryFile(GetPrivateKeyFile(), private_key)) { + m_service = LookupNumeric(std::string(m_service_id+".onion"), Params().GetDefaultPort()); + LogInfo("Got tor service ID %s, advertising service %s\n", m_service_id, m_service.ToStringAddrPort()); + if (WriteBinaryFile(GetPrivateKeyFile(), m_private_key)) { LogDebug(BCLog::TOR, "Cached service private key to %s\n", fs::PathToString(GetPrivateKeyFile())); } else { LogWarning("tor: Error writing service private key to %s", fs::PathToString(GetPrivateKeyFile())); } - AddLocal(service, LOCAL_MANUAL); + AddLocal(m_service, LOCAL_MANUAL); // ... onion requested - keep connection open } else if (reply.code == TOR_REPLY_UNRECOGNIZED) { LogWarning("tor: Add onion failed with unrecognized command (You probably need to upgrade Tor)"); } else if (pow_was_enabled && reply.code == TOR_REPLY_SYNTAX_ERROR) { LogDebug(BCLog::TOR, "ADD_ONION failed with PoW defenses, retrying without"); - _conn.Command(MakeAddOnionCmd(private_key, m_target.ToStringAddrPort(), /*enable_pow=*/false), + _conn.Command(MakeAddOnionCmd(m_private_key, m_target.ToStringAddrPort(), /*enable_pow=*/false), [this](TorControlConnection& conn, const TorControlReply& reply) { add_onion_cb(conn, reply, /*pow_was_enabled=*/false); }); @@ -486,11 +486,11 @@ void TorController::auth_cb(TorControlConnection& _conn, const TorControlReply& } // Finally - now create the service - if (private_key.empty()) { // No private key, generate one - private_key = "NEW:ED25519-V3"; // Explicitly request key type - see issue #9214 + if (m_private_key.empty()) { // No private key, generate one + m_private_key = "NEW:ED25519-V3"; // Explicitly request key type - see issue #9214 } // Request onion service, redirect port. - _conn.Command(MakeAddOnionCmd(private_key, m_target.ToStringAddrPort(), /*enable_pow=*/true), + _conn.Command(MakeAddOnionCmd(m_private_key, m_target.ToStringAddrPort(), /*enable_pow=*/true), [this](TorControlConnection& conn, const TorControlReply& reply) { add_onion_cb(conn, reply, /*pow_was_enabled=*/true); }); @@ -515,13 +515,13 @@ void TorController::auth_cb(TorControlConnection& _conn, const TorControlReply& * CookieString | ClientNonce | ServerNonce) * */ -static std::vector ComputeResponse(const std::string &key, const std::vector &cookie, const std::vector &clientNonce, const std::vector &serverNonce) +static std::vector ComputeResponse(const std::string &key, const std::vector &cookie, const std::vector &client_nonce, const std::vector &server_nonce) { CHMAC_SHA256 computeHash((const uint8_t*)key.data(), key.size()); std::vector computedHash(CHMAC_SHA256::OUTPUT_SIZE, 0); computeHash.Write(cookie.data(), cookie.size()); - computeHash.Write(clientNonce.data(), clientNonce.size()); - computeHash.Write(serverNonce.data(), serverNonce.size()); + computeHash.Write(client_nonce.data(), client_nonce.size()); + computeHash.Write(server_nonce.data(), server_nonce.size()); computeHash.Finalize(computedHash.data()); return computedHash; } @@ -537,21 +537,21 @@ void TorController::authchallenge_cb(TorControlConnection& _conn, const TorContr LogWarning("tor: Error parsing AUTHCHALLENGE parameters: %s", SanitizeString(l.second)); return; } - std::vector serverHash = ParseHex(m["SERVERHASH"]); - std::vector serverNonce = ParseHex(m["SERVERNONCE"]); - LogDebug(BCLog::TOR, "AUTHCHALLENGE ServerHash %s ServerNonce %s\n", HexStr(serverHash), HexStr(serverNonce)); - if (serverNonce.size() != 32) { + std::vector server_hash = ParseHex(m["SERVERHASH"]); + std::vector server_nonce = ParseHex(m["SERVERNONCE"]); + LogDebug(BCLog::TOR, "AUTHCHALLENGE ServerHash %s ServerNonce %s\n", HexStr(server_hash), HexStr(server_nonce)); + if (server_nonce.size() != 32) { LogWarning("tor: ServerNonce is not 32 bytes, as required by spec"); return; } - std::vector computedServerHash = ComputeResponse(TOR_SAFE_SERVERKEY, cookie, clientNonce, serverNonce); - if (computedServerHash != serverHash) { - LogWarning("tor: ServerHash %s does not match expected ServerHash %s", HexStr(serverHash), HexStr(computedServerHash)); + std::vector computed_server_hash = ComputeResponse(TOR_SAFE_SERVERKEY, m_cookie, m_client_nonce, server_nonce); + if (computed_server_hash != server_hash) { + LogWarning("tor: ServerHash %s does not match expected ServerHash %s", HexStr(server_hash), HexStr(computed_server_hash)); return; } - std::vector computedClientHash = ComputeResponse(TOR_SAFE_CLIENTKEY, cookie, clientNonce, serverNonce); + std::vector computedClientHash = ComputeResponse(TOR_SAFE_CLIENTKEY, m_cookie, m_client_nonce, server_nonce); _conn.Command("AUTHENTICATE " + HexStr(computedClientHash), std::bind_front(&TorController::auth_cb, this)); } else { LogWarning("tor: Invalid reply to AUTHCHALLENGE"); @@ -616,10 +616,10 @@ void TorController::protocolinfo_cb(TorControlConnection& _conn, const TorContro std::pair status_cookie = ReadBinaryFile(fs::PathFromString(cookiefile), TOR_COOKIE_SIZE); if (status_cookie.first && status_cookie.second.size() == TOR_COOKIE_SIZE) { // _conn.Command("AUTHENTICATE " + HexStr(status_cookie.second), std::bind_front(&TorController::auth_cb, this)); - cookie = std::vector(status_cookie.second.begin(), status_cookie.second.end()); - clientNonce = std::vector(TOR_NONCE_SIZE, 0); - GetRandBytes(clientNonce); - _conn.Command("AUTHCHALLENGE SAFECOOKIE " + HexStr(clientNonce), std::bind_front(&TorController::authchallenge_cb, this)); + m_cookie = std::vector(status_cookie.second.begin(), status_cookie.second.end()); + m_client_nonce = std::vector(TOR_NONCE_SIZE, 0); + GetRandBytes(m_client_nonce); + _conn.Command("AUTHCHALLENGE SAFECOOKIE " + HexStr(m_client_nonce), std::bind_front(&TorController::authchallenge_cb, this)); } else { if (status_cookie.first) { LogWarning("tor: Authentication cookie %s is not exactly %i bytes, as is required by the spec", cookiefile, TOR_COOKIE_SIZE); @@ -639,7 +639,7 @@ void TorController::protocolinfo_cb(TorControlConnection& _conn, const TorContro void TorController::connected_cb(TorControlConnection& _conn) { - reconnect_timeout = RECONNECT_TIMEOUT_START; + m_reconnect_timeout = RECONNECT_TIMEOUT_START; // First send a PROTOCOLINFO command to figure out what authentication is expected if (!_conn.Command("PROTOCOLINFO 1", std::bind_front(&TorController::protocolinfo_cb, this))) LogWarning("tor: Error sending initial protocolinfo command"); @@ -648,21 +648,21 @@ void TorController::connected_cb(TorControlConnection& _conn) void TorController::disconnected_cb(TorControlConnection& _conn) { // Stop advertising service when disconnected - if (service.IsValid()) - RemoveLocal(service); - service = CService(); - if (!reconnect) + if (m_service.IsValid()) + RemoveLocal(m_service); + m_service = CService(); + if (!m_reconnect) return; LogDebug(BCLog::TOR, "Not connected to Tor control port %s, retrying in %.2f s\n", - m_tor_control_center, reconnect_timeout); + m_tor_control_center, m_reconnect_timeout); // Single-shot timer for reconnect. Use exponential backoff with a maximum. - struct timeval time = MillisToTimeval(int64_t(reconnect_timeout * 1000.0)); + struct timeval time = MillisToTimeval(int64_t(m_reconnect_timeout * 1000.0)); if (reconnect_ev) event_add(reconnect_ev, &time); - reconnect_timeout = std::min(reconnect_timeout * RECONNECT_TIMEOUT_EXP, RECONNECT_TIMEOUT_MAX); + m_reconnect_timeout = std::min(m_reconnect_timeout * RECONNECT_TIMEOUT_EXP, RECONNECT_TIMEOUT_MAX); } void TorController::Reconnect() @@ -670,7 +670,7 @@ void TorController::Reconnect() /* Try to reconnect and reestablish if we get booted - for example, Tor * may be restarting. */ - if (!conn.Connect(m_tor_control_center, std::bind_front(&TorController::connected_cb, this), + if (!m_conn.Connect(m_tor_control_center, std::bind_front(&TorController::connected_cb, this), std::bind_front(&TorController::disconnected_cb, this) )) { LogWarning("tor: Re-initiating connection to Tor control port %s failed", m_tor_control_center); } diff --git a/src/torcontrol.h b/src/torcontrol.h index b8a1d6540ba..9f4970296cc 100644 --- a/src/torcontrol.h +++ b/src/torcontrol.h @@ -95,7 +95,7 @@ private: /** Connection to control socket */ struct bufferevent* b_conn{nullptr}; /** Message being received */ - TorControlReply message; + TorControlReply m_message; /** Response handlers */ std::deque reply_handlers; @@ -113,7 +113,7 @@ class TorController { public: TorController(struct event_base* base, const std::string& tor_control_center, const CService& target); - TorController() : conn{nullptr} { + TorController() : m_conn{nullptr} { // Used for testing only. } ~TorController(); @@ -126,18 +126,18 @@ public: private: struct event_base* base; const std::string m_tor_control_center; - TorControlConnection conn; - std::string private_key; - std::string service_id; - bool reconnect; + TorControlConnection m_conn; + std::string m_private_key; + std::string m_service_id; + bool m_reconnect; struct event *reconnect_ev = nullptr; - float reconnect_timeout; - CService service; + float m_reconnect_timeout; + CService m_service; const CService m_target; /** Cookie for SAFECOOKIE auth */ - std::vector cookie; + std::vector m_cookie; /** ClientNonce for SAFECOOKIE auth */ - std::vector clientNonce; + std::vector m_client_nonce; public: /** Callback for GETINFO net/listeners/socks result */