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 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 : 0 : class TorControlReply
35 : : {
36 : : public:
37 : 0 : TorControlReply() { Clear(); }
38 : :
39 : : int code;
40 : : std::vector<std::string> lines;
41 : :
42 : 0 : void Clear()
43 : : {
44 : 0 : code = 0;
45 [ # # ]: 0 : lines.clear();
46 : 0 : }
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
|