C++ Distributed Hash Table
securedht.h
1 /*
2  * Copyright (C) 2014-2022 Savoir-faire Linux Inc.
3  * Authors: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
4  * Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
5  * Sébastien Blin <sebastien.blin@savoirfairelinux.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <https://www.gnu.org/licenses/>.
19  */
20 
21 #pragma once
22 
23 #include "dht.h"
24 #include "crypto.h"
25 
26 #include <map>
27 #include <vector>
28 #include <memory>
29 #include <random>
30 
31 namespace dht {
32 
33 class OPENDHT_PUBLIC SecureDht final : public DhtInterface {
34 public:
35 
36  typedef std::function<void(bool)> SignatureCheckCallback;
37 
38  using Config = SecureDhtConfig;
39 
40  static dht::Config getConfig(const SecureDht::Config& conf)
41  {
42  auto c = conf.node_config;
43  if (not c.node_id and conf.id.second)
44  c.node_id = InfoHash::get("node:"+conf.id.second->getId().toString());
45  return c;
46  }
47 
54  SecureDht(std::unique_ptr<DhtInterface> dht, Config config, IdentityAnnouncedCb iacb = {}, const std::shared_ptr<Logger>& l = {});
55 
56  virtual ~SecureDht();
57 
58  InfoHash getId() const {
59  return key_ ? key_->getPublicKey().getId() : InfoHash();
60  }
61  PkId getLongId() const {
62  return key_ ? key_->getPublicKey().getLongId() : PkId();
63  }
64  Sp<crypto::PublicKey> getPublicKey() const {
65  return key_ ? key_->getSharedPublicKey() : Sp<crypto::PublicKey>{};
66  }
67 
68  ValueType secureType(ValueType&& type);
69 
70  ValueType secureType(const ValueType& type) {
71  ValueType tmp_type = type;
72  return secureType(std::move(tmp_type));
73  }
74 
75  void registerType(const ValueType& type) override {
76  if (dht_)
77  dht_->registerType(secureType(type));
78  }
79  void registerType(ValueType&& type) {
80  if (dht_)
81  dht_->registerType(secureType(std::forward<ValueType>(type)));
82  }
83  void registerInsecureType(const ValueType& type) {
84  if (dht_)
85  dht_->registerType(type);
86  }
87 
93  void get(const InfoHash& id, GetCallback cb, DoneCallback donecb={}, Value::Filter&& = {}, Where&& w = {}) override;
94  void get(const InfoHash& id, GetCallback cb, DoneCallbackSimple donecb={}, Value::Filter&& f = {}, Where&& w = {}) override {
95  get(id, cb, bindDoneCb(donecb), std::forward<Value::Filter>(f), std::forward<Where>(w));
96  }
97  void get(const InfoHash& key, GetCallbackSimple cb, DoneCallback donecb={}, Value::Filter&& f={}, Where&& w = {}) override {
98  get(key, bindGetCb(cb), donecb, std::forward<Value::Filter>(f), std::forward<Where>(w));
99  }
100  void get(const InfoHash& key, GetCallbackSimple cb, DoneCallbackSimple donecb, Value::Filter&& f={}, Where&& w = {}) override {
101  get(key, bindGetCb(cb), bindDoneCb(donecb), std::forward<Value::Filter>(f), std::forward<Where>(w));
102  }
103 
107  void putSigned(const InfoHash& hash, Sp<Value> val, DoneCallback callback, bool permanent = false);
108  void putSigned(const InfoHash& hash, Value&& v, DoneCallback callback, bool permanent = false) {
109  putSigned(hash, std::make_shared<Value>(std::move(v)), callback, permanent);
110  }
111 
117  void putEncrypted(const InfoHash& hash, const InfoHash& to, Sp<Value> val, DoneCallback callback, bool permanent = false);
118  void putEncrypted(const InfoHash& hash, const InfoHash& to, Value&& v, DoneCallback callback, bool permanent = false) {
119  putEncrypted(hash, to, std::make_shared<Value>(std::move(v)), callback, permanent);
120  }
121  void putEncrypted(const InfoHash& hash, const crypto::PublicKey& to, Sp<Value> val, DoneCallback callback, bool permanent = false);
122  void putEncrypted(const InfoHash& hash, const crypto::PublicKey& to, Value&& v, DoneCallback callback, bool permanent = false) {
123  putEncrypted(hash, to, std::make_shared<Value>(std::move(v)), callback, permanent);
124  }
125 
129  void sign(Value& v) const;
130 
131  Value encrypt(Value& v, const crypto::PublicKey& to) const;
132 
133  Value decrypt(const Value& v);
134 
135  void findCertificate(const InfoHash& node, const std::function<void(const Sp<crypto::Certificate>)>& cb);
136  void findPublicKey(const InfoHash& node, const std::function<void(const Sp<crypto::PublicKey>)>& cb);
137 
138  Sp<crypto::Certificate> registerCertificate(const InfoHash& node, const Blob& cert);
139  void registerCertificate(Sp<crypto::Certificate>& cert);
140 
141  Sp<crypto::Certificate> getCertificate(const InfoHash& node) const;
142  Sp<crypto::PublicKey> getPublicKey(const InfoHash& node) const;
143 
149  void setLocalCertificateStore(CertificateStoreQuery&& query_method) {
150  localQueryMethod_ = std::move(query_method);
151  }
152 
156  void shutdown(ShutdownCallback cb, bool stop = false) override {
157  dht_->shutdown(cb, stop);
158  }
159  void dumpTables() const override {
160  dht_->dumpTables();
161  }
162  inline const InfoHash& getNodeId() const override { return dht_->getNodeId(); }
163 
164  std::pair<size_t, size_t> getStoreSize() const override {
165  return dht_->getStoreSize();
166  }
167  std::string getStorageLog() const override {
168  return dht_->getStorageLog();
169  }
170  std::string getStorageLog(const InfoHash& h) const override {
171  return dht_->getStorageLog(h);
172  }
173  void setStorageLimit(size_t limit = DEFAULT_STORAGE_LIMIT) override {
174  dht_->setStorageLimit(limit);
175  }
176  size_t getStorageLimit() const override {
177  return dht_->getStorageLimit();
178  }
179 
180  std::vector<NodeExport> exportNodes() const override {
181  return dht_->exportNodes();
182  }
183  std::vector<ValuesExport> exportValues() const override {
184  return dht_->exportValues();
185  }
186  void importValues(const std::vector<ValuesExport>& v) override {
187  dht_->importValues(v);
188  }
189  NodeStats getNodesStats(sa_family_t af) const override {
190  return dht_->getNodesStats(af);
191  }
192  std::vector<unsigned> getNodeMessageStats(bool in = false) override {
193  return dht_->getNodeMessageStats(in);
194  }
195  std::string getRoutingTablesLog(sa_family_t af) const override {
196  return dht_->getRoutingTablesLog(af);
197  }
198  std::string getSearchesLog(sa_family_t af) const override {
199  return dht_->getSearchesLog(af);
200  }
201  std::string getSearchLog(const InfoHash& h, sa_family_t af = AF_UNSPEC) const override {
202  return dht_->getSearchLog(h, af);
203  }
204  std::vector<SockAddr> getPublicAddress(sa_family_t family = 0) override {
205  return dht_->getPublicAddress(family);
206  }
207  time_point periodic(const uint8_t *buf, size_t buflen, SockAddr sa, const time_point& now) override {
208  return dht_->periodic(buf, buflen, std::move(sa), now);
209  }
210  time_point periodic(const uint8_t *buf, size_t buflen, const sockaddr* from, socklen_t fromlen, const time_point& now) override {
211  return dht_->periodic(buf, buflen, from, fromlen, now);
212  }
213  NodeStatus updateStatus(sa_family_t af) override {
214  return dht_->updateStatus(af);
215  }
216  NodeStatus getStatus(sa_family_t af) const override {
217  return dht_->getStatus(af);
218  }
219  NodeStatus getStatus() const override {
220  return dht_->getStatus();
221  }
222  net::DatagramSocket* getSocket() const override {
223  return dht_->getSocket();
224  };
225  bool isRunning(sa_family_t af = 0) const override {
226  return dht_->isRunning(af);
227  }
228  const ValueType& getType(ValueType::Id type_id) const override {
229  return dht_->getType(type_id);
230  }
231  void addBootstrap(const std::string& host, const std::string& service) override {
232  dht_->addBootstrap(host, service);
233  }
234  void clearBootstrap() override {
235  dht_->clearBootstrap();
236  }
237  void insertNode(const InfoHash& id, const SockAddr& sa) override {
238  dht_->insertNode(id, sa);
239  }
240  void insertNode(const NodeExport& n) override {
241  dht_->insertNode(n);
242  }
243  void pingNode(SockAddr sa, DoneCallbackSimple&& cb={}) override {
244  dht_->pingNode(std::move(sa), std::move(cb));
245  }
246  void query(const InfoHash& key, QueryCallback cb, DoneCallback done_cb = {}, Query&& q = {}) override {
247  dht_->query(key, cb, done_cb, std::move(q));
248  }
249  void query(const InfoHash& key, QueryCallback cb, DoneCallbackSimple done_cb = {}, Query&& q = {}) override {
250  dht_->query(key, cb, done_cb, std::move(q));
251  }
252  std::vector<Sp<Value>> getLocal(const InfoHash& key, const Value::Filter& f = {}) const override {
253  return dht_->getLocal(key, f);
254  }
255  Sp<Value> getLocalById(const InfoHash& key, Value::Id vid) const override {
256  return dht_->getLocalById(key, vid);
257  }
258  void put(const InfoHash& key,
259  Sp<Value> v,
260  DoneCallback cb=nullptr,
261  time_point created=time_point::max(),
262  bool permanent = false) override
263  {
264  dht_->put(key, v, cb, created, permanent);
265  }
266  void put(const InfoHash& key,
267  const Sp<Value>& v,
268  DoneCallbackSimple cb,
269  time_point created=time_point::max(),
270  bool permanent = false) override
271  {
272  dht_->put(key, v, cb, created, permanent);
273  }
274 
275  void put(const InfoHash& key,
276  Value&& v,
277  DoneCallback cb=nullptr,
278  time_point created=time_point::max(),
279  bool permanent = false) override
280  {
281  dht_->put(key, std::move(v), cb, created, permanent);
282  }
283  void put(const InfoHash& key,
284  Value&& v,
285  DoneCallbackSimple cb,
286  time_point created=time_point::max(),
287  bool permanent = false) override
288  {
289  dht_->put(key, std::move(v), cb, created, permanent);
290  }
291  std::vector<Sp<Value>> getPut(const InfoHash& h) const override {
292  return dht_->getPut(h);
293  }
294  Sp<Value> getPut(const InfoHash& h, const Value::Id& vid) const override {
295  return dht_->getPut(h, vid);
296  }
297  bool cancelPut(const InfoHash& h, const Value::Id& vid) override {
298  return dht_->cancelPut(h, vid);
299  }
300 
301  size_t listen(const InfoHash& key, ValueCallback, Value::Filter={}, Where={}) override;
302  size_t listen(const InfoHash& key, GetCallback cb, Value::Filter = {}, Where w = {}) override;
303  size_t listen(const InfoHash& key, GetCallbackSimple cb, Value::Filter f={}, Where w = {}) override {
304  return listen(key, bindGetCb(cb), f, w);
305  }
306  bool cancelListen(const InfoHash& h, size_t token) override {
307  return dht_->cancelListen(h, token);
308  }
309  void connectivityChanged(sa_family_t af) override {
310  dht_->connectivityChanged(af);
311  }
312  void connectivityChanged() override {
313  dht_->connectivityChanged();
314  }
315 
316  void forwardAllMessages(bool forward) {
317  forward_all_ = forward;
318  }
319 
320  void setPushNotificationToken(const std::string& token = "") override {
321  dht_->setPushNotificationToken(token);
322  }
323 
328  void pushNotificationReceived(const std::map<std::string, std::string>& notification) override {
329  dht_->pushNotificationReceived(notification);
330  }
331 
332  void setLogger(const Logger& logger) override {
333  DhtInterface::setLogger(logger);
334  dht_->setLogger(logger);
335  }
336 
337  void setLogger(const std::shared_ptr<Logger>& logger) override {
338  DhtInterface::setLogger(logger);
339  dht_->setLogger(logger);
340  }
341 
345  void setLogFilter(const InfoHash& f) override {
347  dht_->setLogFilter(f);
348  }
349 
350 private:
351  std::unique_ptr<DhtInterface> dht_;
352  // prevent copy
353  SecureDht(const SecureDht&) = delete;
354  SecureDht& operator=(const SecureDht&) = delete;
355 
356  Sp<Value> checkValue(const Sp<Value>& v);
357  ValueCallback getCallbackFilter(const ValueCallback&, Value::Filter&&);
358  GetCallback getCallbackFilter(const GetCallback&, Value::Filter&&);
359 
360  Sp<crypto::PrivateKey> key_ {};
361  Sp<crypto::Certificate> certificate_ {};
362 
363  // method to query the local certificate store
364  CertificateStoreQuery localQueryMethod_ {};
365 
366  // our certificate cache
367  std::map<InfoHash, Sp<crypto::Certificate>> nodesCertificates_ {};
368  std::map<InfoHash, Sp<crypto::PublicKey>> nodesPubKeys_ {};
369 
370  std::atomic_bool forward_all_ {false};
371  bool enableCache_ {false};
372 };
373 
374 const ValueType CERTIFICATE_TYPE = {
375  8, "Certificate", std::chrono::hours(24 * 7),
376  // A certificate can only be stored at its public key ID.
377  [](InfoHash id, Sp<Value>& v, const InfoHash&, const SockAddr&) {
378  try {
379  crypto::Certificate crt(v->data);
380  // TODO check certificate signature
381  return crt.getPublicKey().getId() == id;
382  } catch (const std::exception& e) {}
383  return false;
384  },
385  [](InfoHash, const Sp<Value>& o, Sp<Value>& n, const InfoHash&, const SockAddr&) {
386  try {
387  return crypto::Certificate(o->data).getPublicKey().getId() == crypto::Certificate(n->data).getPublicKey().getId();
388  } catch (const std::exception& e) {}
389  return false;
390  }
391 };
392 
393 }
const InfoHash & getNodeId() const override
Definition: securedht.h:162
InfoHash node_id
Definition: callbacks.h:107
void connectivityChanged(sa_family_t af) override
Definition: securedht.h:309
void setLocalCertificateStore(CertificateStoreQuery &&query_method)
Definition: securedht.h:149
void insertNode(const InfoHash &id, const SockAddr &sa) override
Definition: securedht.h:237
std::vector< Sp< Value > > getLocal(const InfoHash &key, const Value::Filter &f={}) const override
Definition: securedht.h:252
NodeStatus updateStatus(sa_family_t af) override
Definition: securedht.h:213
void setLogFilter(const InfoHash &f) override
Definition: securedht.h:345
void shutdown(ShutdownCallback cb, bool stop=false) override
Definition: securedht.h:156
NodeStatus
Definition: callbacks.h:42
virtual void setLogFilter(const InfoHash &f)
std::vector< uint8_t > Blob
Definition: utils.h:151
std::pair< size_t, size_t > getStoreSize() const override
Definition: securedht.h:164
void setStorageLimit(size_t limit=DEFAULT_STORAGE_LIMIT) override
Definition: securedht.h:173
void pushNotificationReceived(const std::map< std::string, std::string > &notification) override
Definition: securedht.h:328
bool cancelPut(const InfoHash &h, const Value::Id &vid) override
Definition: securedht.h:297
std::vector< NodeExport > exportNodes() const override
Definition: securedht.h:180
Describes a query destined to another peer.
Definition: value.h:924
void query(const InfoHash &key, QueryCallback cb, DoneCallback done_cb={}, Query &&q={}) override
Definition: securedht.h:246
Serializable dht::Value filter.
Definition: value.h:800
std::vector< Sp< Value > > getPut(const InfoHash &h) const override
Definition: securedht.h:291
Sp< Value > getPut(const InfoHash &h, const Value::Id &vid) const override
Definition: securedht.h:294
Definition: callbacks.h:35
void put(const InfoHash &key, Sp< Value > v, DoneCallback cb=nullptr, time_point created=time_point::max(), bool permanent=false) override
Definition: securedht.h:258
Sp< Value > getLocalById(const InfoHash &key, Value::Id vid) const override
Definition: securedht.h:255
bool isRunning(sa_family_t af=0) const override
Definition: securedht.h:225