Branch data Line data Source code
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(); 31 : : 32 : : /** Reply from Tor, can be single or multi-line */ 33 : : class TorControlReply 34 : : { 35 : : public: 36 [ # # ]: 0 : TorControlReply() { Clear(); } 37 : : 38 : : int code; 39 : : std::vector<std::string> lines; 40 : : 41 : 0 : void Clear() 42 : : { 43 : 0 : code = 0; 44 : 0 : lines.clear(); 45 : 0 : } 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 [ # # # # : 0 : TorController() : conn{nullptr} { # # # # ] 111 : : // Used for testing only. 112 : 0 : } 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 : 0 : 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