My Project 3.2.0
C++ Distributed Hash Table
Loading...
Searching...
No Matches
securedht.h
1/*
2 * Copyright (C) 2014-2023 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
31namespace dht {
32
33class OPENDHT_PUBLIC SecureDht final : public DhtInterface {
34public:
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 void setOnPublicAddressChanged(PublicAddressChangedCb cb) override {
153 dht_->setOnPublicAddressChanged(cb);
154 }
155
159 void shutdown(ShutdownCallback cb, bool stop = false) override {
160 dht_->shutdown(cb, stop);
161 }
162 void dumpTables() const override {
163 dht_->dumpTables();
164 }
165 inline const InfoHash& getNodeId() const override { return dht_->getNodeId(); }
166
167 std::pair<size_t, size_t> getStoreSize() const override {
168 return dht_->getStoreSize();
169 }
170 std::string getStorageLog() const override {
171 return dht_->getStorageLog();
172 }
173 std::string getStorageLog(const InfoHash& h) const override {
174 return dht_->getStorageLog(h);
175 }
176 void setStorageLimit(size_t limit = DEFAULT_STORAGE_LIMIT) override {
177 dht_->setStorageLimit(limit);
178 }
179 size_t getStorageLimit() const override {
180 return dht_->getStorageLimit();
181 }
182
183 std::vector<NodeExport> exportNodes() const override {
184 return dht_->exportNodes();
185 }
186 std::vector<ValuesExport> exportValues() const override {
187 return dht_->exportValues();
188 }
189 void importValues(const std::vector<ValuesExport>& v) override {
190 dht_->importValues(v);
191 }
192 NodeStats getNodesStats(sa_family_t af) const override {
193 return dht_->getNodesStats(af);
194 }
195 std::vector<unsigned> getNodeMessageStats(bool in = false) override {
196 return dht_->getNodeMessageStats(in);
197 }
198 std::string getRoutingTablesLog(sa_family_t af) const override {
199 return dht_->getRoutingTablesLog(af);
200 }
201 std::string getSearchesLog(sa_family_t af) const override {
202 return dht_->getSearchesLog(af);
203 }
204 std::string getSearchLog(const InfoHash& h, sa_family_t af = AF_UNSPEC) const override {
205 return dht_->getSearchLog(h, af);
206 }
207 std::vector<SockAddr> getPublicAddress(sa_family_t family = 0) override {
208 return dht_->getPublicAddress(family);
209 }
210 time_point periodic(const uint8_t *buf, size_t buflen, SockAddr sa, const time_point& now) override {
211 return dht_->periodic(buf, buflen, std::move(sa), now);
212 }
213 time_point periodic(const uint8_t *buf, size_t buflen, const sockaddr* from, socklen_t fromlen, const time_point& now) override {
214 return dht_->periodic(buf, buflen, from, fromlen, now);
215 }
216 NodeStatus updateStatus(sa_family_t af) override {
217 return dht_->updateStatus(af);
218 }
219 NodeStatus getStatus(sa_family_t af) const override {
220 return dht_->getStatus(af);
221 }
222 NodeStatus getStatus() const override {
223 return dht_->getStatus();
224 }
225 net::DatagramSocket* getSocket() const override {
226 return dht_->getSocket();
227 };
228 bool isRunning(sa_family_t af = 0) const override {
229 return dht_->isRunning(af);
230 }
231 const ValueType& getType(ValueType::Id type_id) const override {
232 return dht_->getType(type_id);
233 }
234 void addBootstrap(const std::string& host, const std::string& service) override {
235 dht_->addBootstrap(host, service);
236 }
237 void clearBootstrap() override {
238 dht_->clearBootstrap();
239 }
240 void insertNode(const InfoHash& id, const SockAddr& sa) override {
241 dht_->insertNode(id, sa);
242 }
243 void insertNode(const NodeExport& n) override {
244 dht_->insertNode(n);
245 }
246 void pingNode(SockAddr sa, DoneCallbackSimple&& cb={}) override {
247 dht_->pingNode(std::move(sa), std::move(cb));
248 }
249 void query(const InfoHash& key, QueryCallback cb, DoneCallback done_cb = {}, Query&& q = {}) override {
250 dht_->query(key, cb, done_cb, std::move(q));
251 }
252 void query(const InfoHash& key, QueryCallback cb, DoneCallbackSimple done_cb = {}, Query&& q = {}) override {
253 dht_->query(key, cb, done_cb, std::move(q));
254 }
255 std::vector<Sp<Value>> getLocal(const InfoHash& key, const Value::Filter& f = {}) const override {
256 return dht_->getLocal(key, f);
257 }
258 Sp<Value> getLocalById(const InfoHash& key, Value::Id vid) const override {
259 return dht_->getLocalById(key, vid);
260 }
261 void put(const InfoHash& key,
262 Sp<Value> v,
263 DoneCallback cb=nullptr,
264 time_point created=time_point::max(),
265 bool permanent = false) override
266 {
267 dht_->put(key, v, cb, created, permanent);
268 }
269 void put(const InfoHash& key,
270 const Sp<Value>& v,
271 DoneCallbackSimple cb,
272 time_point created=time_point::max(),
273 bool permanent = false) override
274 {
275 dht_->put(key, v, cb, created, permanent);
276 }
277
278 void put(const InfoHash& key,
279 Value&& v,
280 DoneCallback cb=nullptr,
281 time_point created=time_point::max(),
282 bool permanent = false) override
283 {
284 dht_->put(key, std::move(v), cb, created, permanent);
285 }
286 void put(const InfoHash& key,
287 Value&& v,
288 DoneCallbackSimple cb,
289 time_point created=time_point::max(),
290 bool permanent = false) override
291 {
292 dht_->put(key, std::move(v), cb, created, permanent);
293 }
294 std::vector<Sp<Value>> getPut(const InfoHash& h) const override {
295 return dht_->getPut(h);
296 }
297 Sp<Value> getPut(const InfoHash& h, const Value::Id& vid) const override {
298 return dht_->getPut(h, vid);
299 }
300 bool cancelPut(const InfoHash& h, const Value::Id& vid) override {
301 return dht_->cancelPut(h, vid);
302 }
303
304 size_t listen(const InfoHash& key, ValueCallback, Value::Filter={}, Where={}) override;
305 size_t listen(const InfoHash& key, GetCallback cb, Value::Filter = {}, Where w = {}) override;
306 size_t listen(const InfoHash& key, GetCallbackSimple cb, Value::Filter f={}, Where w = {}) override {
307 return listen(key, bindGetCb(cb), f, w);
308 }
309 bool cancelListen(const InfoHash& h, size_t token) override {
310 return dht_->cancelListen(h, token);
311 }
312 void connectivityChanged(sa_family_t af) override {
313 dht_->connectivityChanged(af);
314 }
315 void connectivityChanged() override {
316 dht_->connectivityChanged();
317 }
318
319 void forwardAllMessages(bool forward) {
320 forward_all_ = forward;
321 }
322
323 void setPushNotificationToken(const std::string& token = "") override {
324 dht_->setPushNotificationToken(token);
325 }
326
331 void pushNotificationReceived(const std::map<std::string, std::string>& notification) override {
332 dht_->pushNotificationReceived(notification);
333 }
334
335 void setLogger(const Logger& logger) override {
336 DhtInterface::setLogger(logger);
337 dht_->setLogger(logger);
338 }
339
340 void setLogger(const std::shared_ptr<Logger>& logger) override {
341 DhtInterface::setLogger(logger);
342 dht_->setLogger(logger);
343 }
344
348 void setLogFilter(const InfoHash& f) override {
350 dht_->setLogFilter(f);
351 }
352
353private:
354 std::unique_ptr<DhtInterface> dht_;
355 // prevent copy
356 SecureDht(const SecureDht&) = delete;
357 SecureDht& operator=(const SecureDht&) = delete;
358
359 Sp<Value> checkValue(const Sp<Value>& v);
360 ValueCallback getCallbackFilter(const ValueCallback&, Value::Filter&&);
361 GetCallback getCallbackFilter(const GetCallback&, Value::Filter&&);
362
363 Sp<crypto::PrivateKey> key_ {};
364 Sp<crypto::Certificate> certificate_ {};
365
366 // method to query the local certificate store
367 CertificateStoreQuery localQueryMethod_ {};
368
369 // our certificate cache
370 std::map<InfoHash, Sp<crypto::Certificate>> nodesCertificates_ {};
371 std::map<InfoHash, Sp<crypto::PublicKey>> nodesPubKeys_ {};
372
373 std::atomic_bool forward_all_ {false};
374 bool enableCache_ {false};
375};
376
377const ValueType CERTIFICATE_TYPE = {
378 8, "Certificate", std::chrono::hours(24 * 7),
379 // A certificate can only be stored at its public key ID.
380 [](InfoHash id, Sp<Value>& v, const InfoHash&, const SockAddr&) {
381 try {
382 crypto::Certificate crt(v->data);
383 // TODO check certificate signature
384 return crt.getPublicKey().getId() == id || InfoHash::get(crt.getPublicKey().getLongId()) == id;
385 } catch (const std::exception& e) {}
386 return false;
387 },
388 [](InfoHash, const Sp<Value>& o, Sp<Value>& n, const InfoHash&, const SockAddr&) {
389 try {
390 return crypto::Certificate(o->data).getPublicKey().getId() == crypto::Certificate(n->data).getPublicKey().getId();
391 } catch (const std::exception& e) {}
392 return false;
393 }
394};
395
396}
virtual void setLogFilter(const InfoHash &f)
void putSigned(const InfoHash &hash, Sp< Value > val, DoneCallback callback, bool permanent=false)
size_t listen(const InfoHash &key, GetCallback cb, Value::Filter={}, Where w={}) override
bool isRunning(sa_family_t af=0) const override
Definition securedht.h:228
void insertNode(const InfoHash &id, const SockAddr &sa) override
Definition securedht.h:240
void query(const InfoHash &key, QueryCallback cb, DoneCallback done_cb={}, Query &&q={}) override
Definition securedht.h:249
void get(const InfoHash &id, GetCallback cb, DoneCallback donecb={}, Value::Filter &&={}, Where &&w={}) override
void sign(Value &v) const
SecureDht(std::unique_ptr< DhtInterface > dht, Config config, IdentityAnnouncedCb iacb={}, const std::shared_ptr< Logger > &l={})
void setLogFilter(const InfoHash &f) override
Definition securedht.h:348
void shutdown(ShutdownCallback cb, bool stop=false) override
Definition securedht.h:159
std::vector< NodeExport > exportNodes() const override
Definition securedht.h:183
std::vector< Sp< Value > > getLocal(const InfoHash &key, const Value::Filter &f={}) const override
Definition securedht.h:255
void pushNotificationReceived(const std::map< std::string, std::string > &notification) override
Definition securedht.h:331
bool cancelPut(const InfoHash &h, const Value::Id &vid) override
Definition securedht.h:300
std::vector< Sp< Value > > getPut(const InfoHash &h) const override
Definition securedht.h:294
void put(const InfoHash &key, Sp< Value > v, DoneCallback cb=nullptr, time_point created=time_point::max(), bool permanent=false) override
Definition securedht.h:261
std::pair< size_t, size_t > getStoreSize() const override
Definition securedht.h:167
Sp< Value > getLocalById(const InfoHash &key, Value::Id vid) const override
Definition securedht.h:258
void setStorageLimit(size_t limit=DEFAULT_STORAGE_LIMIT) override
Definition securedht.h:176
Sp< Value > getPut(const InfoHash &h, const Value::Id &vid) const override
Definition securedht.h:297
void putEncrypted(const InfoHash &hash, const InfoHash &to, Sp< Value > val, DoneCallback callback, bool permanent=false)
const InfoHash & getNodeId() const override
Definition securedht.h:165
NodeStatus updateStatus(sa_family_t af) override
Definition securedht.h:216
void setLocalCertificateStore(CertificateStoreQuery &&query_method)
Definition securedht.h:149
void connectivityChanged(sa_family_t af) override
Definition securedht.h:312
std::vector< uint8_t > Blob
Definition utils.h:151
NodeStatus
Definition callbacks.h:42
InfoHash node_id
Definition callbacks.h:107
Describes a query destined to another peer.
Definition value.h:924
Serializable dht::Value filter.
Definition value.h:797
const InfoHash & getId() const