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