torcontrol.h
1 // Copyright (c) 2015-2021 The Bitcoin Core developers 2 // Distributed under the MIT software license, see the accompanying 3 // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 5 /** 6 * Functionality for communicating with Tor. 7 */ 8 #ifndef BITCOIN_TORCONTROL_H 9 #define BITCOIN_TORCONTROL_H 10 11 #include <netaddress.h> 12 #include <util/fs.h> 13 14 #include <event2/util.h> 15 16 #include <cstdint> 17 #include <deque> 18 #include <functional> 19 #include <string> 20 #include <vector> 21 22 constexpr uint16_t DEFAULT_TOR_SOCKS_PORT{9050}; 23 constexpr int DEFAULT_TOR_CONTROL_PORT = 9051; 24 extern const std::string DEFAULT_TOR_CONTROL; 25 static const bool DEFAULT_LISTEN_ONION = true; 26 27 void StartTorControl(CService onion_service_target); 28 void InterruptTorControl(); 29 void StopTorControl(); 30 31 CService DefaultOnionServiceTarget(uint16_t port); 32 33 /** Reply from Tor, can be single or multi-line */ 34 class TorControlReply 35 { 36 public: 37 TorControlReply() { Clear(); } 38 39 int code; 40 std::vector<std::string> lines; 41 42 void Clear() 43 { 44 code = 0; 45 lines.clear(); 46 } 47 }; 48 49 /** Low-level handling for Tor control connection. 50 * Speaks the SMTP-like protocol as defined in torspec/control-spec.txt 51 */ 52 class TorControlConnection 53 { 54 public: 55 typedef std::function<void(TorControlConnection&)> ConnectionCB; 56 typedef std::function<void(TorControlConnection &,const TorControlReply &)> ReplyHandlerCB; 57 58 /** Create a new TorControlConnection. 59 */ 60 explicit TorControlConnection(struct event_base *base); 61 ~TorControlConnection(); 62 63 /** 64 * Connect to a Tor control port. 65 * tor_control_center is address of the form host:port. 66 * connected is the handler that is called when connection is successfully established. 67 * disconnected is a handler that is called when the connection is broken. 68 * Return true on success. 69 */ 70 bool Connect(const std::string& tor_control_center, const ConnectionCB& connected, const ConnectionCB& disconnected); 71 72 /** 73 * Disconnect from Tor control port. 74 */ 75 void Disconnect(); 76 77 /** Send a command, register a handler for the reply. 78 * A trailing CRLF is automatically added. 79 * Return true on success. 80 */ 81 bool Command(const std::string &cmd, const ReplyHandlerCB& reply_handler); 82 83 private: 84 /** Callback when ready for use */ 85 std::function<void(TorControlConnection&)> connected; 86 /** Callback when connection lost */ 87 std::function<void(TorControlConnection&)> disconnected; 88 /** Libevent event base */ 89 struct event_base *base; 90 /** Connection to control socket */ 91 struct bufferevent* b_conn{nullptr}; 92 /** Message being received */ 93 TorControlReply message; 94 /** Response handlers */ 95 std::deque<ReplyHandlerCB> reply_handlers; 96 97 /** Libevent handlers: internal */ 98 static void readcb(struct bufferevent *bev, void *ctx); 99 static void eventcb(struct bufferevent *bev, short what, void *ctx); 100 }; 101 102 /****** Bitcoin specific TorController implementation ********/ 103 104 /** Controller that connects to Tor control socket, authenticate, then create 105 * and maintain an ephemeral onion service. 106 */ 107 class TorController 108 { 109 public: 110 TorController(struct event_base* base, const std::string& tor_control_center, const CService& target); 111 TorController() : conn{nullptr} { 112 // Used for testing only. 113 } 114 ~TorController(); 115 116 /** Get name of file to store private key in */ 117 fs::path GetPrivateKeyFile(); 118 119 /** Reconnect, after getting disconnected */ 120 void Reconnect(); 121 private: 122 struct event_base* base; 123 const std::string m_tor_control_center; 124 TorControlConnection conn; 125 std::string private_key; 126 std::string service_id; 127 bool reconnect; 128 struct event *reconnect_ev = nullptr; 129 float reconnect_timeout; 130 CService service; 131 const CService m_target; 132 /** Cookie for SAFECOOKIE auth */ 133 std::vector<uint8_t> cookie; 134 /** ClientNonce for SAFECOOKIE auth */ 135 std::vector<uint8_t> clientNonce; 136 137 public: 138 /** Callback for GETINFO net/listeners/socks result */ 139 void get_socks_cb(TorControlConnection& conn, const TorControlReply& reply); 140 /** Callback for ADD_ONION result */ 141 void add_onion_cb(TorControlConnection& conn, const TorControlReply& reply); 142 /** Callback for AUTHENTICATE result */ 143 void auth_cb(TorControlConnection& conn, const TorControlReply& reply); 144 /** Callback for AUTHCHALLENGE result */ 145 void authchallenge_cb(TorControlConnection& conn, const TorControlReply& reply); 146 /** Callback for PROTOCOLINFO result */ 147 void protocolinfo_cb(TorControlConnection& conn, const TorControlReply& reply); 148 /** Callback after successful connection */ 149 void connected_cb(TorControlConnection& conn); 150 /** Callback after connection lost or failed connection attempt */ 151 void disconnected_cb(TorControlConnection& conn); 152 153 /** Callback for reconnect timer */ 154 static void reconnect_cb(evutil_socket_t fd, short what, void *arg); 155 }; 156 157 #endif // BITCOIN_TORCONTROL_H