/ src / torcontrol.h
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