diff options
Diffstat (limited to 'src/messenger/gnunet-service-messenger_ego_store.c')
-rw-r--r-- | src/messenger/gnunet-service-messenger_ego_store.c | 295 |
1 files changed, 295 insertions, 0 deletions
diff --git a/src/messenger/gnunet-service-messenger_ego_store.c b/src/messenger/gnunet-service-messenger_ego_store.c new file mode 100644 index 000000000..3b069fcf5 --- /dev/null +++ b/src/messenger/gnunet-service-messenger_ego_store.c | |||
@@ -0,0 +1,295 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2020--2021 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 "gnunet-service-messenger_ego_store.h" | ||
27 | |||
28 | #include "gnunet-service-messenger_handle.h" | ||
29 | |||
30 | static void | ||
31 | callback_update_ego (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *identifier) | ||
32 | { | ||
33 | if ((!ego) || (!identifier)) | ||
34 | return; | ||
35 | |||
36 | struct GNUNET_MESSENGER_EgoStore *store = cls; | ||
37 | |||
38 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New ego in use: '%s'\n", identifier); | ||
39 | |||
40 | update_store_ego (store, identifier, GNUNET_IDENTITY_ego_get_private_key (ego)); | ||
41 | } | ||
42 | |||
43 | void | ||
44 | init_ego_store(struct GNUNET_MESSENGER_EgoStore *store, const struct GNUNET_CONFIGURATION_Handle *config) | ||
45 | { | ||
46 | GNUNET_assert ((store) && (config)); | ||
47 | |||
48 | store->cfg = config; | ||
49 | store->identity = GNUNET_IDENTITY_connect (config, &callback_update_ego, store); | ||
50 | store->egos = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); | ||
51 | |||
52 | store->lu_start = NULL; | ||
53 | store->lu_end = NULL; | ||
54 | |||
55 | store->op_start = NULL; | ||
56 | store->op_end = NULL; | ||
57 | } | ||
58 | |||
59 | |||
60 | static int | ||
61 | iterate_destroy_egos (void *cls, const struct GNUNET_HashCode *key, void *value) | ||
62 | { | ||
63 | struct GNUNET_MESSENGER_Ego *ego = value; | ||
64 | GNUNET_free(ego); | ||
65 | return GNUNET_YES; | ||
66 | } | ||
67 | |||
68 | void | ||
69 | clear_ego_store(struct GNUNET_MESSENGER_EgoStore *store) | ||
70 | { | ||
71 | GNUNET_assert (store); | ||
72 | |||
73 | struct GNUNET_MESSENGER_EgoOperation *op; | ||
74 | |||
75 | while (store->op_start) | ||
76 | { | ||
77 | op = store->op_start; | ||
78 | |||
79 | GNUNET_IDENTITY_cancel (op->operation); | ||
80 | GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, op); | ||
81 | |||
82 | if (op->identifier) | ||
83 | GNUNET_free (op->identifier); | ||
84 | |||
85 | GNUNET_free (op); | ||
86 | } | ||
87 | |||
88 | struct GNUNET_MESSENGER_EgoLookup *lu; | ||
89 | |||
90 | while (store->lu_start) | ||
91 | { | ||
92 | lu = store->lu_start; | ||
93 | |||
94 | GNUNET_IDENTITY_ego_lookup_cancel(lu->lookup); | ||
95 | GNUNET_CONTAINER_DLL_remove (store->lu_start, store->lu_end, lu); | ||
96 | |||
97 | if (lu->identifier) | ||
98 | GNUNET_free(lu->identifier); | ||
99 | |||
100 | GNUNET_free (lu); | ||
101 | } | ||
102 | |||
103 | GNUNET_CONTAINER_multihashmap_iterate (store->egos, iterate_destroy_egos, NULL); | ||
104 | GNUNET_CONTAINER_multihashmap_destroy (store->egos); | ||
105 | |||
106 | if (store->identity) | ||
107 | { | ||
108 | GNUNET_IDENTITY_disconnect (store->identity); | ||
109 | |||
110 | store->identity = NULL; | ||
111 | } | ||
112 | } | ||
113 | |||
114 | static void | ||
115 | callback_ego_create (void *cls, const struct GNUNET_IDENTITY_PrivateKey *key, const char *emsg) | ||
116 | { | ||
117 | struct GNUNET_MESSENGER_EgoOperation *element = cls; | ||
118 | struct GNUNET_MESSENGER_EgoStore *store = element->store; | ||
119 | |||
120 | GNUNET_assert(element->identifier); | ||
121 | |||
122 | if (emsg) | ||
123 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s\n", emsg); | ||
124 | |||
125 | if (key) | ||
126 | { | ||
127 | struct GNUNET_MESSENGER_SrvHandle *handle = element->handle; | ||
128 | |||
129 | struct GNUNET_MESSENGER_Ego *msg_ego = update_store_ego (store, element->identifier, key); | ||
130 | |||
131 | set_handle_ego (handle, msg_ego); | ||
132 | } | ||
133 | else | ||
134 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Creating ego failed!\n"); | ||
135 | |||
136 | GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, element); | ||
137 | GNUNET_free (element->identifier); | ||
138 | GNUNET_free (element); | ||
139 | } | ||
140 | |||
141 | void | ||
142 | create_store_ego (struct GNUNET_MESSENGER_EgoStore *store, const char *identifier, | ||
143 | void *handle) | ||
144 | { | ||
145 | GNUNET_assert ((store) && (identifier)); | ||
146 | |||
147 | struct GNUNET_MESSENGER_EgoOperation *element = GNUNET_new (struct GNUNET_MESSENGER_EgoOperation); | ||
148 | |||
149 | element->store = store; | ||
150 | element->handle = handle; | ||
151 | |||
152 | element->identifier = GNUNET_strdup (identifier); | ||
153 | |||
154 | element->operation = GNUNET_IDENTITY_create (store->identity, identifier, NULL, | ||
155 | GNUNET_IDENTITY_TYPE_ECDSA, callback_ego_create, element); | ||
156 | |||
157 | GNUNET_CONTAINER_DLL_insert (store->op_start, store->op_end, element); | ||
158 | } | ||
159 | |||
160 | static void | ||
161 | callback_ego_lookup (void *cls, struct GNUNET_IDENTITY_Ego *ego) | ||
162 | { | ||
163 | struct GNUNET_MESSENGER_EgoLookup *element = cls; | ||
164 | struct GNUNET_MESSENGER_EgoStore *store = element->store; | ||
165 | |||
166 | GNUNET_assert(element->identifier); | ||
167 | |||
168 | struct GNUNET_MESSENGER_Ego *msg_ego; | ||
169 | |||
170 | if (ego) | ||
171 | msg_ego = update_store_ego ( | ||
172 | store, element->identifier, GNUNET_IDENTITY_ego_get_private_key(ego) | ||
173 | ); | ||
174 | else | ||
175 | msg_ego = NULL; | ||
176 | |||
177 | if (element->cb) | ||
178 | element->cb(element->cls, element->identifier, msg_ego); | ||
179 | |||
180 | GNUNET_CONTAINER_DLL_remove (store->lu_start, store->lu_end, element); | ||
181 | GNUNET_free (element->identifier); | ||
182 | GNUNET_free (element); | ||
183 | } | ||
184 | |||
185 | void | ||
186 | lookup_store_ego(struct GNUNET_MESSENGER_EgoStore *store, const char *identifier, | ||
187 | GNUNET_MESSENGER_EgoLookupCallback lookup, void *cls) | ||
188 | { | ||
189 | GNUNET_assert (store); | ||
190 | |||
191 | if (!identifier) | ||
192 | { | ||
193 | lookup(cls, identifier, NULL); | ||
194 | return; | ||
195 | } | ||
196 | |||
197 | struct GNUNET_HashCode hash; | ||
198 | GNUNET_CRYPTO_hash (identifier, strlen (identifier), &hash); | ||
199 | |||
200 | struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (store->egos, &hash); | ||
201 | |||
202 | if (ego) | ||
203 | lookup(cls, identifier, ego); | ||
204 | else | ||
205 | { | ||
206 | struct GNUNET_MESSENGER_EgoLookup *element = GNUNET_new (struct GNUNET_MESSENGER_EgoLookup); | ||
207 | |||
208 | element->store = store; | ||
209 | |||
210 | element->cb = lookup; | ||
211 | element->cls = cls; | ||
212 | |||
213 | element->identifier = GNUNET_strdup (identifier); | ||
214 | |||
215 | element->lookup = GNUNET_IDENTITY_ego_lookup(store->cfg, identifier, callback_ego_lookup, element); | ||
216 | |||
217 | GNUNET_CONTAINER_DLL_insert (store->lu_start, store->lu_end, element); | ||
218 | } | ||
219 | } | ||
220 | |||
221 | struct GNUNET_MESSENGER_Ego* | ||
222 | update_store_ego(struct GNUNET_MESSENGER_EgoStore *store, const char *identifier, | ||
223 | const struct GNUNET_IDENTITY_PrivateKey *key) | ||
224 | { | ||
225 | GNUNET_assert ((store) && (identifier) && (key)); | ||
226 | |||
227 | struct GNUNET_HashCode hash; | ||
228 | GNUNET_CRYPTO_hash (identifier, strlen (identifier), &hash); | ||
229 | |||
230 | struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (store->egos, &hash); | ||
231 | |||
232 | if (!ego) | ||
233 | { | ||
234 | ego = GNUNET_new(struct GNUNET_MESSENGER_Ego); | ||
235 | GNUNET_CONTAINER_multihashmap_put (store->egos, &hash, ego, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
236 | } | ||
237 | |||
238 | GNUNET_memcpy(&(ego->priv), key, sizeof(*key)); | ||
239 | |||
240 | if (GNUNET_OK != GNUNET_IDENTITY_key_get_public (key, &(ego->pub))) | ||
241 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Updating invalid ego key failed!\n"); | ||
242 | |||
243 | return ego; | ||
244 | } | ||
245 | |||
246 | static void | ||
247 | callback_ego_rename (void *cls, const char *emsg) | ||
248 | { | ||
249 | struct GNUNET_MESSENGER_EgoOperation *element = cls; | ||
250 | struct GNUNET_MESSENGER_EgoStore *store = element->store; | ||
251 | |||
252 | GNUNET_assert(element->identifier); | ||
253 | |||
254 | if (emsg) | ||
255 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s\n", emsg); | ||
256 | |||
257 | struct GNUNET_HashCode hash; | ||
258 | GNUNET_CRYPTO_hash (element->identifier, strlen (element->identifier), &hash); | ||
259 | |||
260 | struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (store->egos, &hash); | ||
261 | |||
262 | if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (store->egos, &hash, ego)) | ||
263 | { | ||
264 | GNUNET_CRYPTO_hash ((char*) element->handle, strlen ((char*) element->handle), &hash); | ||
265 | |||
266 | GNUNET_CONTAINER_multihashmap_put (store->egos, &hash, ego, | ||
267 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
268 | } | ||
269 | else | ||
270 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Renaming ego failed!\n"); | ||
271 | |||
272 | GNUNET_free (element->handle); | ||
273 | |||
274 | GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, element); | ||
275 | GNUNET_free (element->identifier); | ||
276 | GNUNET_free (element); | ||
277 | } | ||
278 | |||
279 | void | ||
280 | rename_store_ego (struct GNUNET_MESSENGER_EgoStore *store, const char *old_identifier, | ||
281 | const char *new_identifier) | ||
282 | { | ||
283 | GNUNET_assert ((store) && (old_identifier) && (new_identifier)); | ||
284 | |||
285 | struct GNUNET_MESSENGER_EgoOperation *element = GNUNET_new (struct GNUNET_MESSENGER_EgoOperation); | ||
286 | |||
287 | element->store = store; | ||
288 | element->handle = GNUNET_strdup (new_identifier); | ||
289 | |||
290 | element->identifier = GNUNET_strdup (old_identifier); | ||
291 | |||
292 | element->operation = GNUNET_IDENTITY_rename (store->identity, old_identifier, new_identifier, callback_ego_rename, element); | ||
293 | |||
294 | GNUNET_CONTAINER_DLL_insert (store->op_start, store->op_end, element); | ||
295 | } | ||