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