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