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