diff options
Diffstat (limited to 'src/service/messenger/gnunet-service-messenger_ego_store.c')
-rw-r--r-- | src/service/messenger/gnunet-service-messenger_ego_store.c | 527 |
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 | |||
31 | static void | ||
32 | callback_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 | |||
56 | void | ||
57 | init_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 | |||
76 | static int | ||
77 | iterate_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 | |||
87 | void | ||
88 | clear_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 | |||
137 | static int | ||
138 | iterate_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 | |||
148 | static void | ||
149 | callback_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 | |||
187 | void | ||
188 | create_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 | |||
216 | void | ||
217 | bind_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 | |||
240 | void | ||
241 | unbind_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 | |||
263 | static void | ||
264 | callback_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 | |||
307 | void | ||
308 | lookup_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 | |||
340 | struct GNUNET_MESSENGER_Ego* | ||
341 | update_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 | |||
372 | void | ||
373 | delete_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 | |||
403 | static void | ||
404 | callback_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 | |||
449 | void | ||
450 | rename_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 | |||
479 | static void | ||
480 | callback_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 | |||
503 | void | ||
504 | renew_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 | } | ||