aboutsummaryrefslogtreecommitdiff
path: root/src/reclaim/gnunet-service-reclaim_tickets.c
diff options
context:
space:
mode:
authorSchanzenbach, Martin <mschanzenbach@posteo.de>2019-04-12 14:31:06 +0200
committerSchanzenbach, Martin <mschanzenbach@posteo.de>2019-04-14 10:01:23 +0200
commita12b8c2c4cbf952c8c305cde193bb25c13a0912b (patch)
tree0c7f27a870ce6fc8789e1b9672156758b1c1c2e6 /src/reclaim/gnunet-service-reclaim_tickets.c
parent947b84dcdee19d6a4b1fcad10618a2b4f505b3b9 (diff)
downloadgnunet-a12b8c2c4cbf952c8c305cde193bb25c13a0912b.tar.gz
gnunet-a12b8c2c4cbf952c8c305cde193bb25c13a0912b.zip
RECLAIM: refactoring; cleanup
Diffstat (limited to 'src/reclaim/gnunet-service-reclaim_tickets.c')
-rw-r--r--src/reclaim/gnunet-service-reclaim_tickets.c455
1 files changed, 455 insertions, 0 deletions
diff --git a/src/reclaim/gnunet-service-reclaim_tickets.c b/src/reclaim/gnunet-service-reclaim_tickets.c
new file mode 100644
index 000000000..f93e934ee
--- /dev/null
+++ b/src/reclaim/gnunet-service-reclaim_tickets.c
@@ -0,0 +1,455 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2015 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/**
22 * @author Martin Schanzenbach
23 * @file src/reclaim/gnunet-service-reclaim_tickets.c
24 * @brief reclaim tickets
25 *
26 */
27#include "gnunet-service-reclaim_tickets.h"
28
29/**
30 * A reference to a ticket stored in GNS
31 */
32struct TicketReference
33{
34 /**
35 * DLL
36 */
37 struct TicketReference *next;
38
39 /**
40 * DLL
41 */
42 struct TicketReference *prev;
43
44 /**
45 * Attributes
46 */
47 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
48
49 /**
50 * Tickets
51 */
52 struct GNUNET_RECLAIM_Ticket ticket;
53};
54
55
56/**
57 * Ticket issue request handle
58 */
59struct TicketIssueHandle
60{
61 /**
62 * Attributes to issue
63 */
64 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
65
66 /**
67 * Issuer Key
68 */
69 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
70
71 /**
72 * Ticket to issue
73 */
74 struct GNUNET_RECLAIM_Ticket ticket;
75
76 /**
77 * QueueEntry
78 */
79 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
80
81 /**
82 * Ticket reference list
83 */
84 struct TicketReference *ticket_refs_head;
85
86 /**
87 * Ticket reference list
88 */
89 struct TicketReference *ticket_refs_tail;
90
91 /**
92 * Number of references
93 */
94 uint32_t ticket_ref_num;
95
96 /**
97 * Callback
98 */
99 RECLAIM_TICKETS_TicketResult cb;
100
101 /**
102 * Callback cls
103 */
104 void *cb_cls;
105
106};
107
108static struct GNUNET_NAMESTORE_Handle *nsh;
109
110/**
111 * Cleanup ticket consume handle
112 * @param handle the handle to clean up
113 */
114static void
115cleanup_issue_handle (struct TicketIssueHandle *handle)
116{
117 struct TicketReference *tr;
118 struct TicketReference *tr_tmp;
119 if (NULL != handle->attrs)
120 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (handle->attrs);
121 if (NULL != handle->ns_qe)
122 GNUNET_NAMESTORE_cancel (handle->ns_qe);
123 for (tr = handle->ticket_refs_head; NULL != tr;)
124 {
125 if (NULL != tr->attrs)
126 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (tr->attrs);
127 tr_tmp = tr;
128 tr = tr->next;
129 GNUNET_free (tr_tmp);
130 }
131 GNUNET_free (handle);
132}
133
134
135
136static void
137store_ticket_refs_cont (void *cls,
138 int32_t success,
139 const char *emsg)
140{
141 struct TicketIssueHandle *handle = cls;
142 handle->ns_qe = NULL;
143 if (GNUNET_OK != success)
144 {
145 handle->cb (handle->cb_cls,
146 NULL,
147 GNUNET_SYSERR,
148 "Error storing updated ticket refs in GNS");
149 cleanup_issue_handle (handle);
150 return;
151 }
152 handle->cb (handle->cb_cls,
153 &handle->ticket,
154 GNUNET_OK,
155 NULL);
156 cleanup_issue_handle (handle);
157}
158
159
160
161static void
162update_ticket_refs (void* cls)
163{
164 struct TicketIssueHandle *handle = cls;
165 struct GNUNET_GNSRECORD_Data refs_rd[handle->ticket_ref_num];
166 struct TicketReference *tr;
167 char* buf;
168 size_t buf_size;
169
170 tr = handle->ticket_refs_head;
171 for (int i = 0; i < handle->ticket_ref_num; i++)
172 {
173 buf_size = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (tr->attrs);
174 buf_size += sizeof (struct GNUNET_RECLAIM_Ticket);
175 buf = GNUNET_malloc (buf_size);
176 memcpy (buf, &tr->ticket, sizeof (struct GNUNET_RECLAIM_Ticket));
177 GNUNET_RECLAIM_ATTRIBUTE_list_serialize (tr->attrs,
178 buf + sizeof (struct GNUNET_RECLAIM_Ticket));
179 refs_rd[i].data = buf;
180 refs_rd[i].data_size = buf_size;
181 refs_rd[i].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
182 refs_rd[i].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_TICKETREF;
183 refs_rd[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION |
184 GNUNET_GNSRECORD_RF_PRIVATE;
185 tr = tr->next;
186 }
187
188 handle->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
189 &handle->identity,
190 GNUNET_GNS_EMPTY_LABEL_AT,
191 handle->ticket_ref_num,
192 refs_rd,
193 &store_ticket_refs_cont,
194 handle);
195 for (int i = 0; i < handle->ticket_ref_num; i++)
196 GNUNET_free ((char*)refs_rd[i].data);
197}
198
199
200
201static void
202ticket_lookup_cb (void *cls,
203 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
204 const char *label,
205 unsigned int rd_count,
206 const struct GNUNET_GNSRECORD_Data *rd)
207{
208 struct TicketIssueHandle *handle = cls;
209 struct TicketReference *tr;
210 const char* attr_data;
211 size_t attr_data_len;
212 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
213 "Received tickets from local namestore.\n");
214 handle->ns_qe = NULL;
215 for (int i = 0; i < rd_count; i++)
216 {
217 if (GNUNET_GNSRECORD_TYPE_RECLAIM_TICKETREF != rd[i].record_type)
218 continue;
219 tr = GNUNET_new (struct TicketReference);
220 memcpy (&tr->ticket, rd[i].data,
221 sizeof (struct GNUNET_RECLAIM_Ticket));
222 if (0 != memcmp (&tr->ticket.identity,
223 &handle->ticket.identity,
224 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
225 {
226 //Not our ticket
227 GNUNET_free (tr);
228 continue;
229 }
230 attr_data = rd[i].data + sizeof (struct GNUNET_RECLAIM_Ticket);
231 attr_data_len = rd[i].data_size - sizeof (struct GNUNET_RECLAIM_Ticket);
232 tr->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (attr_data,
233 attr_data_len);
234 GNUNET_CONTAINER_DLL_insert (handle->ticket_refs_head,
235 handle->ticket_refs_tail,
236 tr);
237 handle->ticket_ref_num++;
238 }
239 tr = GNUNET_new (struct TicketReference);
240 tr->ticket = handle->ticket;
241 tr->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_dup (handle->attrs);
242 GNUNET_CONTAINER_DLL_insert (handle->ticket_refs_head,
243 handle->ticket_refs_tail,
244 tr);
245 handle->ticket_ref_num++;
246 GNUNET_SCHEDULER_add_now (&update_ticket_refs, handle);
247}
248
249static void
250ticket_lookup_error_cb (void *cls)
251{
252 struct TicketIssueHandle *handle = cls;
253 handle->ns_qe = NULL;
254 handle->cb (handle->cb_cls,
255 &handle->ticket,
256 GNUNET_SYSERR,
257 "Error checking for ticketsin GNS\n");
258 cleanup_issue_handle (handle);
259}
260
261static void
262store_ticket_issue_cont (void *cls,
263 int32_t success,
264 const char *emsg)
265{
266 struct TicketIssueHandle *handle = cls;
267
268 handle->ns_qe = NULL;
269 if (GNUNET_SYSERR == success)
270 {
271 handle->cb (handle->cb_cls,
272 &handle->ticket,
273 GNUNET_SYSERR,
274 "Error storing AuthZ ticket in GNS");
275 return;
276 }
277 /* First, local references to tickets */
278 handle->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
279 &handle->identity,
280 GNUNET_GNS_EMPTY_LABEL_AT,
281 &ticket_lookup_error_cb,
282 handle,
283 &ticket_lookup_cb,
284 handle);
285}
286
287static int
288create_sym_key_from_ecdh (const struct GNUNET_HashCode *new_key_hash,
289 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
290 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
291{
292 struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
293
294 GNUNET_CRYPTO_hash_to_enc (new_key_hash,
295 &new_key_hash_str);
296 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
297 static const char ctx_key[] = "gnuid-aes-ctx-key";
298 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
299 new_key_hash, sizeof (struct GNUNET_HashCode),
300 ctx_key, strlen (ctx_key),
301 NULL, 0);
302 static const char ctx_iv[] = "gnuid-aes-ctx-iv";
303 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
304 new_key_hash, sizeof (struct GNUNET_HashCode),
305 ctx_iv, strlen (ctx_iv),
306 NULL, 0);
307 return GNUNET_OK;
308}
309
310
311static int
312serialize_authz_record (const struct GNUNET_RECLAIM_Ticket *ticket,
313 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
314 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
315 char **result)
316{
317 struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
318 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
319 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
320 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
321 struct GNUNET_HashCode new_key_hash;
322 ssize_t enc_size;
323 char *enc_keyinfo;
324 char *buf;
325 char *write_ptr;
326 char attrs_str_len;
327 char* label;
328
329 GNUNET_assert (NULL != attrs->list_head);
330 attrs_str_len = 0;
331 for (le = attrs->list_head; NULL != le; le = le->next) {
332 attrs_str_len += 15 + 1; //TODO propery calculate
333 }
334 buf = GNUNET_malloc (attrs_str_len);
335 write_ptr = buf;
336 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
337 "Writing attributes\n");
338 for (le = attrs->list_head; NULL != le; le = le->next) {
339 label = GNUNET_STRINGS_data_to_string_alloc (&le->claim->id,
340 sizeof (uint64_t));
341 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
342 "Adding attribute to record: %s\n", label);
343
344 GNUNET_memcpy (write_ptr,
345 label,
346 strlen (label));
347 write_ptr[strlen (label)] = ',';
348 write_ptr += strlen (label) + 1;
349 GNUNET_free (label);
350 }
351 write_ptr--;
352 write_ptr[0] = '\0'; //replace last , with a 0-terminator
353 // ECDH keypair E = eG
354 *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
355 GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
356 &ecdh_pubkey);
357 enc_keyinfo = GNUNET_malloc (attrs_str_len);
358 // Derived key K = H(eB)
359 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
360 &ticket->audience,
361 &new_key_hash));
362 create_sym_key_from_ecdh (&new_key_hash, &skey, &iv);
363 enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
364 attrs_str_len,
365 &skey, &iv,
366 enc_keyinfo);
367 *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
368 enc_size);
369 GNUNET_memcpy (*result,
370 &ecdh_pubkey,
371 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
372 GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
373 enc_keyinfo,
374 enc_size);
375 GNUNET_free (enc_keyinfo);
376 GNUNET_free (buf);
377 return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
378}
379
380
381
382static void
383issue_ticket (struct TicketIssueHandle *ih)
384{
385 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
386 struct GNUNET_GNSRECORD_Data code_record[1];
387 char *authz_record_data;
388 size_t authz_record_len;
389 char *label;
390
391 //TODO rename function
392 authz_record_len = serialize_authz_record (&ih->ticket,
393 ih->attrs,
394 &ecdhe_privkey,
395 &authz_record_data);
396 code_record[0].data = authz_record_data;
397 code_record[0].data_size = authz_record_len;
398 code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
399 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_AUTHZ;
400 code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
401
402 label = GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd,
403 sizeof (uint64_t));
404 //Publish record
405 ih->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
406 &ih->identity,
407 label,
408 1,
409 code_record,
410 &store_ticket_issue_cont,
411 ih);
412 GNUNET_free (ecdhe_privkey);
413 GNUNET_free (label);
414 GNUNET_free (authz_record_data);
415}
416
417
418
419
420void
421RECLAIM_TICKETS_issue_ticket (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
422 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
423 const struct GNUNET_CRYPTO_EcdsaPublicKey *audience,
424 RECLAIM_TICKETS_TicketResult cb,
425 void* cb_cls)
426{
427 struct TicketIssueHandle *tih;
428 tih = GNUNET_new (struct TicketIssueHandle);
429 tih->cb = cb;
430 tih->cb_cls = cb_cls;
431 tih->attrs = GNUNET_RECLAIM_ATTRIBUTE_list_dup (attrs);
432 tih->identity = *identity;
433 GNUNET_CRYPTO_ecdsa_key_get_public (identity,
434 &tih->ticket.identity);
435 tih->ticket.rnd =
436 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
437 UINT64_MAX);
438 tih->ticket.audience = *audience;
439 issue_ticket (tih);
440}
441
442
443int
444RECLAIM_TICKETS_init (const struct GNUNET_CONFIGURATION_Handle *c)
445{
446 //Connect to identity and namestore services
447 nsh = GNUNET_NAMESTORE_connect (c);
448 if (NULL == nsh)
449 {
450 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
451 "Error connecting to namestore\n");
452 return GNUNET_SYSERR;
453 }
454 return GNUNET_OK;
455}