My Project 1.7.4
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
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(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) {
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 = {});
93 void get(const InfoHash& id, GetCallback cb, DoneCallbackSimple donecb={}, Value::Filter&& f = {}, Where&& w = {}) {
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 = {}) {
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 = {}) {
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) {
152 dht_->shutdown(cb);
153 }
154 void dumpTables() const {
155 dht_->dumpTables();
156 }
157 inline const InfoHash& getNodeId() const { return dht_->getNodeId(); }
158 std::pair<size_t, size_t> getStoreSize() const {
159 return dht_->getStoreSize();
160 }
161 std::string getStorageLog() const {
162 return dht_->getStorageLog();
163 }
164 std::string getStorageLog(const InfoHash& h) const {
165 return dht_->getStorageLog(h);
166 }
167 void setStorageLimit(size_t limit = DEFAULT_STORAGE_LIMIT) {
168 dht_->setStorageLimit(limit);
169 }
170 std::vector<NodeExport> exportNodes() {
171 return dht_->exportNodes();
172 }
173 std::vector<ValuesExport> exportValues() const {
174 return dht_->exportValues();
175 }
176 void importValues(const std::vector<ValuesExport>& v) {
177 dht_->importValues(v);
178 }
179 NodeStats getNodesStats(sa_family_t af) const {
180 return dht_->getNodesStats(af);
181 }
182 std::vector<unsigned> getNodeMessageStats(bool in = false) {
183 return dht_->getNodeMessageStats(in);
184 }
185 std::string getRoutingTablesLog(sa_family_t af) const {
186 return dht_->getRoutingTablesLog(af);
187 }
188 std::string getSearchesLog(sa_family_t af) const {
189 return dht_->getSearchesLog(af);
190 }
191 std::string getSearchLog(const InfoHash& h, sa_family_t af = AF_UNSPEC) const {
192 return dht_->getSearchLog(h, af);
193 }
194 std::vector<SockAddr> getPublicAddress(sa_family_t family = 0) {
195 return dht_->getPublicAddress(family);
196 }
197 time_point periodic(const uint8_t *buf, size_t buflen, const SockAddr& sa) {
198 return dht_->periodic(buf, buflen, sa);
199 }
200 time_point periodic(const uint8_t *buf, size_t buflen, const sockaddr* from, socklen_t fromlen) {
201 return dht_->periodic(buf, buflen, from, fromlen);
202 }
203 NodeStatus getStatus(sa_family_t af) const {
204 return dht_->getStatus(af);
205 }
206 NodeStatus getStatus() const {
207 return dht_->getStatus();
208 }
209 bool isRunning(sa_family_t af = 0) const {
210 return dht_->isRunning(af);
211 }
212 const ValueType& getType(ValueType::Id type_id) const {
213 return dht_->getType(type_id);
214 }
215 void insertNode(const InfoHash& id, const SockAddr& sa) {
216 dht_->insertNode(id, sa);
217 }
218 void insertNode(const InfoHash& id, const sockaddr* sa, socklen_t salen) {
219 dht_->insertNode(id, sa, salen);
220 }
221 void insertNode(const NodeExport& n) {
222 dht_->insertNode(n);
223 }
224 void pingNode(const sockaddr* sa, socklen_t salen, DoneCallbackSimple&& cb={}) {
225 dht_->pingNode(sa, salen, std::move(cb));
226 }
227 void query(const InfoHash& key, QueryCallback cb, DoneCallback done_cb = {}, Query&& q = {}) {
228 dht_->query(key, cb, done_cb, std::move(q));
229 }
230 void query(const InfoHash& key, QueryCallback cb, DoneCallbackSimple done_cb = {}, Query&& q = {}) {
231 dht_->query(key, cb, done_cb, std::move(q));
232 }
233 std::vector<Sp<Value>> getLocal(const InfoHash& key, Value::Filter f = Value::AllFilter()) const {
234 return dht_->getLocal(key, f);
235 }
236 Sp<Value> getLocalById(const InfoHash& key, Value::Id vid) const {
237 return dht_->getLocalById(key, vid);
238 }
239 void put(const InfoHash& key,
240 Sp<Value> v,
241 DoneCallback cb=nullptr,
242 time_point created=time_point::max(),
243 bool permanent = false)
244 {
245 dht_->put(key, v, cb, created, permanent);
246 }
247 void put(const InfoHash& key,
248 const Sp<Value>& v,
249 DoneCallbackSimple cb,
250 time_point created=time_point::max(),
251 bool permanent = false)
252 {
253 dht_->put(key, v, cb, created, permanent);
254 }
255
256 void put(const InfoHash& key,
257 Value&& v,
258 DoneCallback cb=nullptr,
259 time_point created=time_point::max(),
260 bool permanent = false)
261 {
262 dht_->put(key, std::move(v), cb, created, permanent);
263 }
264 void put(const InfoHash& key,
265 Value&& v,
266 DoneCallbackSimple cb,
267 time_point created=time_point::max(),
268 bool permanent = false)
269 {
270 dht_->put(key, std::move(v), cb, created, permanent);
271 }
272 std::vector<Sp<Value>> getPut(const InfoHash& h) {
273 return dht_->getPut(h);
274 }
275 Sp<Value> getPut(const InfoHash& h, const Value::Id& vid) {
276 return dht_->getPut(h, vid);
277 }
278 bool cancelPut(const InfoHash& h, const Value::Id& vid) {
279 return dht_->cancelPut(h, vid);
280 }
281
282 size_t listen(const InfoHash& key, ValueCallback, Value::Filter={}, Where={});
283 size_t listen(const InfoHash& key, GetCallback cb, Value::Filter = {}, Where w = {});
284 size_t listen(const InfoHash& key, GetCallbackSimple cb, Value::Filter f={}, Where w = {}) {
285 return listen(key, bindGetCb(cb), f, w);
286 }
287 bool cancelListen(const InfoHash& h, size_t token) {
288 return dht_->cancelListen(h, token);
289 }
290 void connectivityChanged(sa_family_t af) {
291 dht_->connectivityChanged(af);
292 }
293 void connectivityChanged() {
294 dht_->connectivityChanged();
295 }
296
297 void forwardAllMessages(bool forward) {
298 forward_all_ = forward;
299 }
300
301 void setPushNotificationToken(const std::string& token = "") {
302 dht_->setPushNotificationToken(token);
303 }
304
309 void pushNotificationReceived(const std::map<std::string, std::string>& notification) {
310 dht_->pushNotificationReceived(notification);
311 }
312
313 void setLoggers(LogMethod error = NOLOG, LogMethod warn = NOLOG, LogMethod debug = NOLOG)
314 {
315 DHT_LOG.DEBUG = debug;
316 DHT_LOG.WARN = warn;
317 DHT_LOG.ERR = error;
318 dht_->setLoggers(error, warn, debug);
319 }
320
324 void setLogFilter(const InfoHash& f) {
325 DHT_LOG.setFilter(f);
326 dht_->setLogFilter(f);
327 }
328
329private:
330 std::unique_ptr<DhtInterface> dht_;
331 // prevent copy
332 SecureDht(const SecureDht&) = delete;
333 SecureDht& operator=(const SecureDht&) = delete;
334
335 Sp<Value> checkValue(const Sp<Value>& v);
336 ValueCallback getCallbackFilter(ValueCallback, Value::Filter&&);
337 GetCallback getCallbackFilter(GetCallback, Value::Filter&&);
338
339 Sp<crypto::PrivateKey> key_ {};
340 Sp<crypto::Certificate> certificate_ {};
341
342 // method to query the local certificate store
343 CertificateStoreQuery localQueryMethod_ {};
344
345 // our certificate cache
346 std::map<InfoHash, Sp<crypto::Certificate>> nodesCertificates_ {};
347 std::map<InfoHash, Sp<const crypto::PublicKey>> nodesPubKeys_ {};
348
349 std::atomic_bool forward_all_ {false};
350};
351
352const ValueType CERTIFICATE_TYPE = {
353 8, "Certificate", std::chrono::hours(24 * 7),
354 // A certificate can only be stored at its public key ID.
355 [](InfoHash id, Sp<Value>& v, const InfoHash&, const SockAddr&) {
356 try {
357 crypto::Certificate crt(v->data);
358 // TODO check certificate signature
359 return crt.getPublicKey().getId() == id;
360 } catch (const std::exception& e) {}
361 return false;
362 },
363 [](InfoHash, const Sp<Value>& o, Sp<Value>& n, const InfoHash&, const SockAddr&) {
364 try {
365 return crypto::Certificate(o->data).getPublicKey().getId() == crypto::Certificate(n->data).getPublicKey().getId();
366 } catch (const std::exception& e) {}
367 return false;
368 }
369};
370
371}
size_t listen(const InfoHash &key, GetCallback cb, Value::Filter={}, Where w={})
void setLoggers(LogMethod error=NOLOG, LogMethod warn=NOLOG, LogMethod debug=NOLOG)
Definition: securedht.h:313
void setStorageLimit(size_t limit=DEFAULT_STORAGE_LIMIT)
Definition: securedht.h:167
std::vector< Sp< Value > > getLocal(const InfoHash &key, Value::Filter f=Value::AllFilter()) const
Definition: securedht.h:233
void putSigned(const InfoHash &hash, Sp< Value > val, DoneCallback callback, bool permanent=false)
bool isRunning(sa_family_t af=0) const
Definition: securedht.h:209
void shutdown(ShutdownCallback cb)
Definition: securedht.h:151
SecureDht(std::unique_ptr< DhtInterface > dht, Config config)
std::pair< size_t, size_t > getStoreSize() const
Definition: securedht.h:158
void insertNode(const InfoHash &id, const SockAddr &sa)
Definition: securedht.h:215
void sign(Value &v) const
void connectivityChanged(sa_family_t af)
Definition: securedht.h:290
NodeStatus getStatus(sa_family_t af) const
Definition: securedht.h:203
Sp< Value > getLocalById(const InfoHash &key, Value::Id vid) const
Definition: securedht.h:236
std::vector< NodeExport > exportNodes()
Definition: securedht.h:170
void pushNotificationReceived(const std::map< std::string, std::string > &notification)
Definition: securedht.h:309
void setLogFilter(const InfoHash &f)
Definition: securedht.h:324
void put(const InfoHash &key, Sp< Value > v, DoneCallback cb=nullptr, time_point created=time_point::max(), bool permanent=false)
Definition: securedht.h:239
void get(const InfoHash &id, GetCallback cb, DoneCallback donecb={}, Value::Filter &&={}, Where &&w={})
void putEncrypted(const InfoHash &hash, const InfoHash &to, Sp< Value > val, DoneCallback callback, bool permanent=false)
void query(const InfoHash &key, QueryCallback cb, DoneCallback done_cb={}, Query &&q={})
Definition: securedht.h:227
Sp< Value > getPut(const InfoHash &h, const Value::Id &vid)
Definition: securedht.h:275
bool cancelPut(const InfoHash &h, const Value::Id &vid)
Definition: securedht.h:278
void setLocalCertificateStore(CertificateStoreQuery &&query_method)
Definition: securedht.h:144
const InfoHash & getNodeId() const
Definition: securedht.h:157
std::vector< Sp< Value > > getPut(const InfoHash &h)
Definition: securedht.h:272
Definition: callbacks.h:34
void NOLOG(char const *, va_list)
Definition: log_enable.h:38
std::vector< uint8_t > Blob
Definition: utils.h:114
NodeStatus
Definition: callbacks.h:41
InfoHash node_id
Definition: callbacks.h:91
Describes a query destined to another peer.
Definition: value.h:864
Serializable dht::Value filter.
Definition: value.h:740