aboutsummaryrefslogtreecommitdiff
path: root/src/service/messenger/gnunet-service-messenger_ego_store.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/messenger/gnunet-service-messenger_ego_store.c')
-rw-r--r--src/service/messenger/gnunet-service-messenger_ego_store.c527
1 files changed, 527 insertions, 0 deletions
diff --git a/src/service/messenger/gnunet-service-messenger_ego_store.c b/src/service/messenger/gnunet-service-messenger_ego_store.c
new file mode 100644
index 000000000..e7faa9eed
--- /dev/null
+++ b/src/service/messenger/gnunet-service-messenger_ego_store.c
@@ -0,0 +1,527 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2023 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_ego_store.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "platform.h"
27#include "gnunet-service-messenger_ego_store.h"
28
29#include "gnunet-service-messenger_handle.h"
30
31static void
32callback_update_ego (void *cls,
33 struct GNUNET_IDENTITY_Ego *ego,
34 void **ctx,
35 const char *identifier)
36{
37 if ((! ctx) || (! identifier))
38 return;
39
40 struct GNUNET_MESSENGER_EgoStore *store = cls;
41
42 if (ego)
43 {
44 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New ego in use: '%s'\n", identifier);
45 update_store_ego (store, identifier,
46 GNUNET_IDENTITY_ego_get_private_key (ego));
47 }
48 else
49 {
50 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego got deleted: '%s'\n", identifier);
51 delete_store_ego (store, identifier);
52 }
53}
54
55
56void
57init_ego_store (struct GNUNET_MESSENGER_EgoStore *store,
58 const struct GNUNET_CONFIGURATION_Handle *config)
59{
60 GNUNET_assert ((store) && (config));
61
62 store->cfg = config;
63 store->identity = GNUNET_IDENTITY_connect (config, &callback_update_ego,
64 store);
65 store->egos = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
66 store->handles = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
67
68 store->lu_start = NULL;
69 store->lu_end = NULL;
70
71 store->op_start = NULL;
72 store->op_end = NULL;
73}
74
75
76static int
77iterate_destroy_egos (void *cls,
78 const struct GNUNET_HashCode *key,
79 void *value)
80{
81 struct GNUNET_MESSENGER_Ego *ego = value;
82 GNUNET_free (ego);
83 return GNUNET_YES;
84}
85
86
87void
88clear_ego_store (struct GNUNET_MESSENGER_EgoStore *store)
89{
90 GNUNET_assert (store);
91
92 struct GNUNET_MESSENGER_EgoOperation *op;
93
94 while (store->op_start)
95 {
96 op = store->op_start;
97
98 GNUNET_IDENTITY_cancel (op->operation);
99 GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, op);
100
101 if (op->identifier)
102 GNUNET_free (op->identifier);
103
104 GNUNET_free (op);
105 }
106
107 struct GNUNET_MESSENGER_EgoLookup *lu;
108
109 while (store->lu_start)
110 {
111 lu = store->lu_start;
112
113 GNUNET_IDENTITY_ego_lookup_cancel (lu->lookup);
114 GNUNET_CONTAINER_DLL_remove (store->lu_start, store->lu_end, lu);
115
116 if (lu->identifier)
117 GNUNET_free (lu->identifier);
118
119 GNUNET_free (lu);
120 }
121
122 GNUNET_CONTAINER_multihashmap_iterate (store->egos,
123 iterate_destroy_egos,
124 NULL);
125 GNUNET_CONTAINER_multihashmap_destroy (store->egos);
126 GNUNET_CONTAINER_multihashmap_destroy (store->handles);
127
128 if (store->identity)
129 {
130 GNUNET_IDENTITY_disconnect (store->identity);
131
132 store->identity = NULL;
133 }
134}
135
136
137static int
138iterate_create_ego (void *cls,
139 const struct GNUNET_HashCode *key,
140 void *value)
141{
142 struct GNUNET_MESSENGER_SrvHandle *handle = value;
143 set_srv_handle_ego (handle, (struct GNUNET_MESSENGER_Ego*) cls);
144 return GNUNET_YES;
145}
146
147
148static void
149callback_ego_create (void *cls,
150 const struct GNUNET_CRYPTO_PrivateKey *key,
151 enum GNUNET_ErrorCode ec)
152{
153 struct GNUNET_MESSENGER_EgoOperation *element = cls;
154 struct GNUNET_MESSENGER_EgoStore *store = element->store;
155
156 GNUNET_assert (element->identifier);
157
158 /**
159 * FIXME: This is dangerous, please handle errors
160 */
161 if (GNUNET_EC_NONE != ec)
162 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%s\n",
163 GNUNET_ErrorCode_get_hint (ec));
164
165 if (key)
166 {
167 struct GNUNET_MESSENGER_Ego *msg_ego = update_store_ego (store,
168 element->identifier,
169 key);
170
171 struct GNUNET_HashCode hash;
172 GNUNET_CRYPTO_hash (element->identifier, strlen (element->identifier),
173 &hash);
174
175 GNUNET_CONTAINER_multihashmap_get_multiple (store->handles, &hash,
176 iterate_create_ego, msg_ego);
177 }
178 else
179 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Creating ego failed!\n");
180
181 GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, element);
182 GNUNET_free (element->identifier);
183 GNUNET_free (element);
184}
185
186
187void
188create_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
189 const char *identifier)
190{
191 GNUNET_assert ((store) && (identifier));
192
193 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Store create ego: %s\n", identifier);
194
195 struct GNUNET_MESSENGER_EgoOperation *element = GNUNET_new (struct
196 GNUNET_MESSENGER_EgoOperation);
197
198 element->store = store;
199 element->cls = NULL;
200
201 element->identifier = GNUNET_strdup (identifier);
202
203 element->operation = GNUNET_IDENTITY_create (
204 store->identity,
205 identifier,
206 NULL,
207 GNUNET_PUBLIC_KEY_TYPE_ECDSA,
208 callback_ego_create,
209 element
210 );
211
212 GNUNET_CONTAINER_DLL_insert (store->op_start, store->op_end, element);
213}
214
215
216void
217bind_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
218 const char *identifier,
219 void *handle)
220{
221 GNUNET_assert ((store) && (identifier) && (handle));
222
223 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Store bind ego: %s\n", identifier);
224
225 struct GNUNET_HashCode hash;
226 GNUNET_CRYPTO_hash (identifier, strlen (identifier), &hash);
227
228 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains_value (
229 store->handles, &hash, handle))
230 return;
231
232 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (store->handles, &hash,
233 handle,
234 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE))
235 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
236 "Putting handle binding to ego store failed!\n");
237}
238
239
240void
241unbind_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
242 const char *identifier,
243 void *handle)
244{
245 GNUNET_assert ((store) && (identifier) && (handle));
246
247 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Store unbind ego: %s\n", identifier);
248
249 struct GNUNET_HashCode hash;
250 GNUNET_CRYPTO_hash (identifier, strlen (identifier), &hash);
251
252 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains_value (
253 store->handles, &hash, handle))
254 return;
255
256 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (store->handles, &hash,
257 handle))
258 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
259 "Removing handle binding from ego store failed!\n");
260}
261
262
263static void
264callback_ego_lookup (void *cls,
265 struct GNUNET_IDENTITY_Ego *ego)
266{
267 struct GNUNET_MESSENGER_EgoLookup *element = cls;
268 struct GNUNET_MESSENGER_EgoStore *store = element->store;
269
270 GNUNET_assert (element->identifier);
271
272 struct GNUNET_MESSENGER_Ego *msg_ego = NULL;
273
274 if (ego)
275 {
276 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New ego looked up: '%s'\n",
277 element->identifier);
278 msg_ego = update_store_ego (
279 store,
280 element->identifier,
281 GNUNET_IDENTITY_ego_get_private_key (ego)
282 );
283 }
284 else
285 {
286 struct GNUNET_HashCode hash;
287 GNUNET_CRYPTO_hash (element->identifier, strlen (element->identifier),
288 &hash);
289
290 if (GNUNET_CONTAINER_multihashmap_get (store->egos, &hash))
291 {
292 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looked up ego got deleted: '%s'\n",
293 element->identifier);
294 delete_store_ego (store, element->identifier);
295 }
296 }
297
298 if (element->cb)
299 element->cb (element->cls, element->identifier, msg_ego);
300
301 GNUNET_CONTAINER_DLL_remove (store->lu_start, store->lu_end, element);
302 GNUNET_free (element->identifier);
303 GNUNET_free (element);
304}
305
306
307void
308lookup_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
309 const char *identifier,
310 GNUNET_MESSENGER_EgoLookupCallback lookup,
311 void *cls)
312{
313 GNUNET_assert (store);
314
315 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Store lookup ego: %s\n", identifier);
316
317 if (! identifier)
318 {
319 lookup (cls, identifier, NULL);
320 return;
321 }
322
323 struct GNUNET_MESSENGER_EgoLookup *element = GNUNET_new (struct
324 GNUNET_MESSENGER_EgoLookup);
325
326 element->store = store;
327
328 element->cb = lookup;
329 element->cls = cls;
330
331 element->identifier = GNUNET_strdup (identifier);
332
333 element->lookup = GNUNET_IDENTITY_ego_lookup (store->cfg, identifier,
334 callback_ego_lookup, element);
335
336 GNUNET_CONTAINER_DLL_insert (store->lu_start, store->lu_end, element);
337}
338
339
340struct GNUNET_MESSENGER_Ego*
341update_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
342 const char *identifier,
343 const struct GNUNET_CRYPTO_PrivateKey *key)
344{
345 GNUNET_assert ((store) && (identifier) && (key));
346
347 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Store update ego: %s\n", identifier);
348
349 struct GNUNET_HashCode hash;
350 GNUNET_CRYPTO_hash (identifier, strlen (identifier), &hash);
351
352 struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (
353 store->egos, &hash);
354
355 if (! ego)
356 {
357 ego = GNUNET_new (struct GNUNET_MESSENGER_Ego);
358 GNUNET_CONTAINER_multihashmap_put (store->egos, &hash, ego,
359 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
360 }
361
362 GNUNET_memcpy (&(ego->priv), key, sizeof(*key));
363
364 if (GNUNET_OK != GNUNET_CRYPTO_key_get_public (key, &(ego->pub)))
365 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
366 "Updating invalid ego key failed!\n");
367
368 return ego;
369}
370
371
372void
373delete_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
374 const char *identifier)
375{
376 GNUNET_assert ((store) && (identifier));
377
378 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Store delete ego: %s\n", identifier);
379
380 struct GNUNET_HashCode hash;
381 GNUNET_CRYPTO_hash (identifier, strlen (identifier), &hash);
382
383 struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (
384 store->egos, &hash);
385
386 if (ego)
387 {
388 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Ego is not stored!\n");
389 return;
390 }
391
392 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (store->egos, &hash,
393 ego))
394 {
395 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Removing ego from store failed!\n");
396 return;
397 }
398
399 GNUNET_free (ego);
400}
401
402
403static void
404callback_ego_rename (void *cls,
405 enum GNUNET_ErrorCode ec)
406{
407 struct GNUNET_MESSENGER_EgoOperation *element = cls;
408 struct GNUNET_MESSENGER_EgoStore *store = element->store;
409
410 GNUNET_assert (element->identifier);
411
412 /**
413 * FIXME: Dangerous, handle error
414 */
415 if (GNUNET_EC_NONE != ec)
416 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%s\n",
417 GNUNET_ErrorCode_get_hint (ec));
418
419 struct GNUNET_HashCode hash;
420 GNUNET_CRYPTO_hash (element->identifier, strlen (element->identifier), &hash);
421
422 struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (
423 store->egos, &hash);
424
425 if (! ego)
426 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Ego is not stored!\n");
427
428 char *identifier = (char*) element->cls;
429
430 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (store->egos, &hash,
431 ego))
432 {
433 GNUNET_CRYPTO_hash (identifier, strlen (identifier), &hash);
434
435 GNUNET_CONTAINER_multihashmap_put (store->egos, &hash, ego,
436 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
437 }
438 else
439 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Renaming ego failed!\n");
440
441 GNUNET_free (identifier);
442
443 GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, element);
444 GNUNET_free (element->identifier);
445 GNUNET_free (element);
446}
447
448
449void
450rename_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
451 const char *old_identifier,
452 const char *new_identifier)
453{
454 GNUNET_assert ((store) && (old_identifier) && (new_identifier));
455
456 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Store rename ego: %s -> %s\n",
457 old_identifier, new_identifier);
458
459 struct GNUNET_MESSENGER_EgoOperation *element = GNUNET_new (struct
460 GNUNET_MESSENGER_EgoOperation);
461
462 element->store = store;
463 element->cls = GNUNET_strdup (new_identifier);
464
465 element->identifier = GNUNET_strdup (old_identifier);
466
467 element->operation = GNUNET_IDENTITY_rename (
468 store->identity,
469 old_identifier,
470 new_identifier,
471 callback_ego_rename,
472 element
473 );
474
475 GNUNET_CONTAINER_DLL_insert (store->op_start, store->op_end, element);
476}
477
478
479static void
480callback_ego_delete (void *cls,
481 enum GNUNET_ErrorCode ec)
482{
483 struct GNUNET_MESSENGER_EgoOperation *element = cls;
484 struct GNUNET_MESSENGER_EgoStore *store = element->store;
485
486 GNUNET_assert (element->identifier);
487
488 /**
489 * FIXME: Dangerous, handle error
490 */
491 if (GNUNET_EC_NONE != ec)
492 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%s\n",
493 GNUNET_ErrorCode_get_hint (ec));
494
495 create_store_ego (store, element->identifier);
496
497 GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, element);
498 GNUNET_free (element->identifier);
499 GNUNET_free (element);
500}
501
502
503void
504renew_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
505 const char *identifier)
506{
507 GNUNET_assert ((store) && (identifier));
508
509 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Store renew ego: %s\n", identifier);
510
511 struct GNUNET_MESSENGER_EgoOperation *element = GNUNET_new (struct
512 GNUNET_MESSENGER_EgoOperation);
513
514 element->store = store;
515 element->cls = NULL;
516
517 element->identifier = GNUNET_strdup (identifier);
518
519 element->operation = GNUNET_IDENTITY_delete (
520 store->identity,
521 identifier,
522 callback_ego_delete,
523 element
524 );
525
526 GNUNET_CONTAINER_DLL_insert (store->op_start, store->op_end, element);
527}