C++ Distributed Hash Table
securedht.h
1 /*
2  * Copyright (C) 2014-2017 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(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 
48  SecureDht() {}
49 
56  SecureDht(std::unique_ptr<DhtInterface> dht, Config config);
57 
58  virtual ~SecureDht();
59 
60  InfoHash getId() const {
61  return key_ ? key_->getPublicKey().getId() : InfoHash();
62  }
63  PkId getLongId() const {
64  return key_ ? key_->getPublicKey().getLongId() : PkId();
65  }
66 
67  ValueType secureType(ValueType&& type);
68 
69  ValueType secureType(const ValueType& type) {
70  ValueType tmp_type = type;
71  return secureType(std::move(tmp_type));
72  }
73 
74  void registerType(const ValueType& type) override {
75  if (dht_)
76  dht_->registerType(secureType(type));
77  }
78  void registerType(ValueType&& type) {
79  if (dht_)
80  dht_->registerType(secureType(std::forward<ValueType>(type)));
81  }
82  void registerInsecureType(const ValueType& type) {
83  if (dht_)
84  dht_->registerType(type);
85  }
86 
92  void get(const InfoHash& id, GetCallback cb, DoneCallback donecb={}, Value::Filter&& = {}, Where&& w = {}) override;
93  void get(const InfoHash& id, GetCallback cb, DoneCallbackSimple donecb={}, Value::Filter&& f = {}, Where&& w = {}) override {
94  get(id, cb, bindDoneCb(donecb), std::forward<Value::Filter>(f), std::forward<Where>(w));
95  }
96  void get(const InfoHash& key, GetCallbackSimple cb, DoneCallback donecb={}, Value::Filter&& f={}, Where&& w = {}) override {
97  get(key, bindGetCb(cb), donecb, std::forward<Value::Filter>(f), std::forward<Where>(w));
98  }
99  void get(const InfoHash& key, GetCallbackSimple cb, DoneCallbackSimple donecb, Value::Filter&& f={}, Where&& w = {}) override {
100  get(key, bindGetCb(cb), bindDoneCb(donecb), std::forward<Value::Filter>(f), std::forward<Where>(w));
101  }
102 
106  void putSigned(const InfoHash& hash, Sp<Value> val, DoneCallback callback, bool permanent = false);
107  void putSigned(const InfoHash& hash, Value&& v, DoneCallback callback, bool permanent = false) {
108  putSigned(hash, std::make_shared<Value>(std::move(v)), callback, permanent);
109  }
110 
116  void putEncrypted(const InfoHash& hash, const InfoHash& to, Sp<Value> val, DoneCallback callback, bool permanent = false);
117  void putEncrypted(const InfoHash& hash, const InfoHash& to, Value&& v, DoneCallback callback, bool permanent = false) {
118  putEncrypted(hash, to, std::make_shared<Value>(std::move(v)), callback, permanent);
119  }
120 
124  void sign(Value& v) const;
125 
126  Value encrypt(Value& v, const crypto::PublicKey& to) const;
127 
128  Value decrypt(const Value& v);
129 
130  void findCertificate(const InfoHash& node, std::function<void(const Sp<crypto::Certificate>)> cb);
131  void findPublicKey(const InfoHash& node, std::function<void(const Sp<const crypto::PublicKey>)> cb);
132 
133  const Sp<crypto::Certificate> registerCertificate(const InfoHash& node, const Blob& cert);
134  void registerCertificate(Sp<crypto::Certificate>& cert);
135 
136  const Sp<crypto::Certificate> getCertificate(const InfoHash& node) const;
137  const Sp<const crypto::PublicKey> getPublicKey(const InfoHash& node) const;
138 
144  void setLocalCertificateStore(CertificateStoreQuery&& query_method) {
145  localQueryMethod_ = std::move(query_method);
146  }
147 
151  void shutdown(ShutdownCallback cb) override {
152  dht_->shutdown(cb);
153  }
154  void dumpTables() const override {
155  dht_->dumpTables();
156  }
157  inline const InfoHash& getNodeId() const override { return dht_->getNodeId(); }
158 
159  std::pair<size_t, size_t> getStoreSize() const override {
160  return dht_->getStoreSize();
161  }
162  std::string getStorageLog() const override {
163  return dht_->getStorageLog();
164  }
165  std::string getStorageLog(const InfoHash& h) const override {
166  return dht_->getStorageLog(h);
167  }
168  void setStorageLimit(size_t limit = DEFAULT_STORAGE_LIMIT) override {
169  dht_->setStorageLimit(limit);
170  }
171  std::vector<NodeExport> exportNodes() override {
172  return dht_->exportNodes();
173  }
174  std::vector<ValuesExport> exportValues() const override {
175  return dht_->exportValues();
176  }
177  void importValues(const std::vector<ValuesExport>& v) override {
178  dht_->importValues(v);
179  }
180  NodeStats getNodesStats(sa_family_t af) const override {
181  return dht_->getNodesStats(af);
182  }
183  std::vector<unsigned> getNodeMessageStats(bool in = false) override {
184  return dht_->getNodeMessageStats(in);
185  }
186  std::string getRoutingTablesLog(sa_family_t af) const override {
187  return dht_->getRoutingTablesLog(af);
188  }
189  std::string getSearchesLog(sa_family_t af) const override {
190  return dht_->getSearchesLog(af);
191  }
192  std::string getSearchLog(const InfoHash& h, sa_family_t af = AF_UNSPEC) const override {
193  return dht_->getSearchLog(h, af);
194  }
195  std::vector<SockAddr> getPublicAddress(sa_family_t family = 0) override {
196  return dht_->getPublicAddress(family);
197  }
198  time_point periodic(const uint8_t *buf, size_t buflen, const SockAddr& sa) override {
199  return dht_->periodic(buf, buflen, sa);
200  }
201  time_point periodic(const uint8_t *buf, size_t buflen, const sockaddr* from, socklen_t fromlen) override {
202  return dht_->periodic(buf, buflen, from, fromlen);
203  }
204  NodeStatus getStatus(sa_family_t af) const override {
205  return dht_->getStatus(af);
206  }
207  NodeStatus getStatus() const override {
208  return dht_->getStatus();
209  }
210  bool isRunning(sa_family_t af = 0) const override {
211  return dht_->isRunning(af);
212  }
213  const ValueType& getType(ValueType::Id type_id) const override {
214  return dht_->getType(type_id);
215  }
216  void insertNode(const InfoHash& id, const SockAddr& sa) override {
217  dht_->insertNode(id, sa);
218  }
219  void insertNode(const InfoHash& id, const sockaddr* sa, socklen_t salen) override {
220  dht_->insertNode(id, sa, salen);
221  }
222  void insertNode(const NodeExport& n) override {
223  dht_->insertNode(n);
224  }
225  void pingNode(const sockaddr* sa, socklen_t salen, DoneCallbackSimple&& cb={}) override {
226  dht_->pingNode(sa, salen, std::move(cb));
227  }
228  void query(const InfoHash& key, QueryCallback cb, DoneCallback done_cb = {}, Query&& q = {}) override {
229  dht_->query(key, cb, done_cb, std::move(q));
230  }
231  void query(const InfoHash& key, QueryCallback cb, DoneCallbackSimple done_cb = {}, Query&& q = {}) override {
232  dht_->query(key, cb, done_cb, std::move(q));
233  }
234  std::vector<Sp<Value>> getLocal(const InfoHash& key, Value::Filter f = Value::AllFilter()) const override {
235  return dht_->getLocal(key, f);
236  }
237  Sp<Value> getLocalById(const InfoHash& key, Value::Id vid) const override {
238  return dht_->getLocalById(key, vid);
239  }
240  void put(const InfoHash& key,
241  Sp<Value> v,
242  DoneCallback cb=nullptr,
243  time_point created=time_point::max(),
244  bool permanent = false) override
245  {
246  dht_->put(key, v, cb, created, permanent);
247  }
248  void put(const InfoHash& key,
249  const Sp<Value>& v,
250  DoneCallbackSimple cb,
251  time_point created=time_point::max(),
252  bool permanent = false) override
253  {
254  dht_->put(key, v, cb, created, permanent);
255  }
256 
257  void put(const InfoHash& key,
258  Value&& v,
259  DoneCallback cb=nullptr,
260  time_point created=time_point::max(),
261  bool permanent = false) override
262  {
263  dht_->put(key, std::move(v), cb, created, permanent);
264  }
265  void put(const InfoHash& key,
266  Value&& v,
267  DoneCallbackSimple cb,
268  time_point created=time_point::max(),
269  bool permanent = false) override
270  {
271  dht_->put(key, std::move(v), cb, created, permanent);
272  }
273  std::vector<Sp<Value>> getPut(const InfoHash& h) override {
274  return dht_->getPut(h);
275  }
276  Sp<Value> getPut(const InfoHash& h, const Value::Id& vid) override {
277  return dht_->getPut(h, vid);
278  }
279  bool cancelPut(const InfoHash& h, const Value::Id& vid) override {
280  return dht_->cancelPut(h, vid);
281  }
282 
283  size_t listen(const InfoHash& key, ValueCallback, Value::Filter={}, Where={}) override;
284  size_t listen(const InfoHash& key, GetCallback cb, Value::Filter = {}, Where w = {}) override;
285  size_t listen(const InfoHash& key, GetCallbackSimple cb, Value::Filter f={}, Where w = {}) override {
286  return listen(key, bindGetCb(cb), f, w);
287  }
288  bool cancelListen(const InfoHash& h, size_t token) override {
289  return dht_->cancelListen(h, token);
290  }
291  void connectivityChanged(sa_family_t af) override {
292  dht_->connectivityChanged(af);
293  }
294  void connectivityChanged() override {
295  dht_->connectivityChanged();
296  }
297 
298  void forwardAllMessages(bool forward) {
299  forward_all_ = forward;
300  }
301 
302  void setPushNotificationToken(const std::string& token = "") override {
303  dht_->setPushNotificationToken(token);
304  }
305 
310  void pushNotificationReceived(const std::map<std::string, std::string>& notification) override {
311  dht_->pushNotificationReceived(notification);
312  }
313 
314  void setLoggers(LogMethod error = NOLOG, LogMethod warn = NOLOG, LogMethod debug = NOLOG) override
315  {
316  DhtInterface::setLoggers(error, warn, debug);
317  dht_->setLoggers(error, warn, debug);
318  }
319 
323  void setLogFilter(const InfoHash& f) override {
324  DHT_LOG.setFilter(f);
325  dht_->setLogFilter(f);
326  }
327 
328 private:
329  std::unique_ptr<DhtInterface> dht_;
330  // prevent copy
331  SecureDht(const SecureDht&) = delete;
332  SecureDht& operator=(const SecureDht&) = delete;
333 
334  Sp<Value> checkValue(const Sp<Value>& v);
335  ValueCallback getCallbackFilter(ValueCallback, Value::Filter&&);
336  GetCallback getCallbackFilter(GetCallback, Value::Filter&&);
337 
338  Sp<crypto::PrivateKey> key_ {};
339  Sp<crypto::Certificate> certificate_ {};
340 
341  // method to query the local certificate store
342  CertificateStoreQuery localQueryMethod_ {};
343 
344  // our certificate cache
345  std::map<InfoHash, Sp<crypto::Certificate>> nodesCertificates_ {};
346  std::map<InfoHash, Sp<const crypto::PublicKey>> nodesPubKeys_ {};
347 
348  std::atomic_bool forward_all_ {false};
349 };
350 
351 const ValueType CERTIFICATE_TYPE = {
352  8, "Certificate", std::chrono::hours(24 * 7),
353  // A certificate can only be stored at its public key ID.
354  [](InfoHash id, Sp<Value>& v, const InfoHash&, const SockAddr&) {
355  try {
356  crypto::Certificate crt(v->data);
357  // TODO check certificate signature
358  return crt.getPublicKey().getId() == id;
359  } catch (const std::exception& e) {}
360  return false;
361  },
362  [](InfoHash, const Sp<Value>& o, Sp<Value>& n, const InfoHash&, const SockAddr&) {
363  try {
364  return crypto::Certificate(o->data).getPublicKey().getId() == crypto::Certificate(n->data).getPublicKey().getId();
365  } catch (const std::exception& e) {}
366  return false;
367  }
368 };
369 
370 }
std::vector< Sp< Value > > getLocal(const InfoHash &key, Value::Filter f=Value::AllFilter()) const override
Definition: securedht.h:234
void NOLOG(char const *, va_list)
Definition: log_enable.h:38
const InfoHash & getNodeId() const override
Definition: securedht.h:157
std::vector< NodeExport > exportNodes() override
Definition: securedht.h:171
InfoHash node_id
Definition: callbacks.h:92
void connectivityChanged(sa_family_t af) override
Definition: securedht.h:291
void setLocalCertificateStore(CertificateStoreQuery &&query_method)
Definition: securedht.h:144
void insertNode(const InfoHash &id, const SockAddr &sa) override
Definition: securedht.h:216
void setLogFilter(const InfoHash &f) override
Definition: securedht.h:323
NodeStatus
Definition: callbacks.h:41
std::vector< Sp< Value > > getPut(const InfoHash &h) override
Definition: securedht.h:273
void shutdown(ShutdownCallback cb) override
Definition: securedht.h:151
std::vector< uint8_t > Blob
Definition: utils.h:114
Sp< Value > getPut(const InfoHash &h, const Value::Id &vid) override
Definition: securedht.h:276
std::pair< size_t, size_t > getStoreSize() const override
Definition: securedht.h:159
NodeStatus getStatus(sa_family_t af) const override
Definition: securedht.h:204
void setStorageLimit(size_t limit=DEFAULT_STORAGE_LIMIT) override
Definition: securedht.h:168
void pushNotificationReceived(const std::map< std::string, std::string > &notification) override
Definition: securedht.h:310
bool cancelPut(const InfoHash &h, const Value::Id &vid) override
Definition: securedht.h:279
Describes a query destined to another peer.
Definition: value.h:873
void query(const InfoHash &key, QueryCallback cb, DoneCallback done_cb={}, Query &&q={}) override
Definition: securedht.h:228
Serializable dht::Value filter.
Definition: value.h:749
void setLoggers(LogMethod error=NOLOG, LogMethod warn=NOLOG, LogMethod debug=NOLOG) override
Definition: securedht.h:314
Definition: callbacks.h:34
virtual void setLoggers(LogMethod error=NOLOG, LogMethod warn=NOLOG, LogMethod debug=NOLOG)
void put(const InfoHash &key, Sp< Value > v, DoneCallback cb=nullptr, time_point created=time_point::max(), bool permanent=false) override
Definition: securedht.h:240
Sp< Value > getLocalById(const InfoHash &key, Value::Id vid) const override
Definition: securedht.h:237
bool isRunning(sa_family_t af=0) const override
Definition: securedht.h:210