aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Schanzenbach <mschanzenbach@posteo.de>2015-11-20 13:59:10 +0000
committerMartin Schanzenbach <mschanzenbach@posteo.de>2015-11-20 13:59:10 +0000
commit05651b1889692c26533a9b30a9f7f79af2689675 (patch)
tree9184d53778bd47c3030e132d4362d41026bf2308 /src
parent1b41668499df4ced87b98c7b0727381456d39625 (diff)
downloadgnunet-05651b1889692c26533a9b30a9f7f79af2689675.tar.gz
gnunet-05651b1889692c26533a9b30a9f7f79af2689675.zip
- update; add attribute updates
Diffstat (limited to 'src')
-rw-r--r--src/identity-token/gnunet-service-identity-token.c317
1 files changed, 296 insertions, 21 deletions
diff --git a/src/identity-token/gnunet-service-identity-token.c b/src/identity-token/gnunet-service-identity-token.c
index 5e9376627..222b9d184 100644
--- a/src/identity-token/gnunet-service-identity-token.c
+++ b/src/identity-token/gnunet-service-identity-token.c
@@ -31,41 +31,113 @@
31#include <jansson.h> 31#include <jansson.h>
32#include "gnunet_signatures.h" 32#include "gnunet_signatures.h"
33 33
34/**
35 * First pass state
36 */
34#define STATE_INIT 0 37#define STATE_INIT 0
35 38
39/**
40 * Normal operation state
41 */
36#define STATE_POST_INIT 1 42#define STATE_POST_INIT 1
37 43
44/**
45 * Minimum interval between updates
46 */
38#define MIN_WAIT_TIME GNUNET_TIME_UNIT_MINUTES 47#define MIN_WAIT_TIME GNUNET_TIME_UNIT_MINUTES
39 48
49/**
50 * Service state (to detect initial update pass)
51 */
40static int state; 52static int state;
41 53
54/**
55 * Head of ego entry DLL
56 */
42static struct EgoEntry *ego_head; 57static struct EgoEntry *ego_head;
43 58
59/**
60 * Tail of ego entry DLL
61 */
44static struct EgoEntry *ego_tail; 62static struct EgoEntry *ego_tail;
45 63
64/**
65 * Identity handle
66 */
46static struct GNUNET_IDENTITY_Handle *identity_handle; 67static struct GNUNET_IDENTITY_Handle *identity_handle;
47 68
69/**
70 * Namestore handle
71 */
48static struct GNUNET_NAMESTORE_Handle *ns_handle; 72static struct GNUNET_NAMESTORE_Handle *ns_handle;
49 73
74/**
75 * Namestore qe
76 */
50static struct GNUNET_NAMESTORE_QueueEntry *ns_qe; 77static struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
51 78
79/**
80 * Namestore iterator
81 */
52static struct GNUNET_NAMESTORE_ZoneIterator *ns_it; 82static struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
53 83
84/**
85 * Timeout task
86 */
54static struct GNUNET_SCHEDULER_Task * timeout_task; 87static struct GNUNET_SCHEDULER_Task * timeout_task;
55 88
89
90/**
91 * Update task
92 */
56static struct GNUNET_SCHEDULER_Task * update_task; 93static struct GNUNET_SCHEDULER_Task * update_task;
57 94
95/**
96 * Timeout for next update pass
97 */
58static struct GNUNET_TIME_Relative min_rel_exp; 98static struct GNUNET_TIME_Relative min_rel_exp;
59 99
100
101/**
102 * Currently processed token
103 */
60static char* token; 104static char* token;
61 105
106/**
107 * Label for currently processed token
108 */
62static char* label; 109static char* label;
63 110
111/**
112 * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format
113 *
114 */
64struct EgoEntry 115struct EgoEntry
65{ 116{
117 /**
118 * DLL
119 */
66 struct EgoEntry *next; 120 struct EgoEntry *next;
121
122 /**
123 * DLL
124 */
67 struct EgoEntry *prev; 125 struct EgoEntry *prev;
126
127 /**
128 * Ego handle
129 */
68 struct GNUNET_IDENTITY_Ego *ego; 130 struct GNUNET_IDENTITY_Ego *ego;
131
132 /**
133 * Attribute map. Contains the attributes as json_t
134 */
135 struct GNUNET_CONTAINER_MultiHashMap *attr_map;
136
137 /**
138 * Attributes are old and should be updated if GNUNET_YES
139 */
140 int attributes_dirty;
69}; 141};
70 142
71/** 143/**
@@ -73,6 +145,14 @@ struct EgoEntry
73 */ 145 */
74static const struct GNUNET_CONFIGURATION_Handle *cfg; 146static const struct GNUNET_CONFIGURATION_Handle *cfg;
75 147
148
149/**
150 * Continuation for token store call
151 *
152 * @param cls NULL
153 * @param success error code
154 * @param emsg error message
155 */
76static void 156static void
77store_token_cont (void *cls, 157store_token_cont (void *cls,
78 int32_t success, 158 int32_t success,
@@ -86,10 +166,17 @@ store_token_cont (void *cls,
86 emsg); 166 emsg);
87 return; 167 return;
88 } 168 }
89 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, ">>> Next token\n");
90 GNUNET_NAMESTORE_zone_iterator_next (ns_it); 169 GNUNET_NAMESTORE_zone_iterator_next (ns_it);
91} 170}
92 171
172
173/**
174 * This function updates the old token with new attributes,
175 * removes deleted attributes and expiration times.
176 *
177 * @param cls the ego entry
178 * @param tc task context
179 */
93static void 180static void
94handle_token_update (void *cls, 181handle_token_update (void *cls,
95 const struct GNUNET_SCHEDULER_TaskContext *tc) 182 const struct GNUNET_SCHEDULER_TaskContext *tc)
@@ -108,6 +195,7 @@ handle_token_update (void *cls,
108 struct GNUNET_GNSRECORD_Data token_record; 195 struct GNUNET_GNSRECORD_Data token_record;
109 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; 196 struct GNUNET_CRYPTO_EccSignaturePurpose *purpose;
110 struct GNUNET_CRYPTO_EcdsaSignature sig; 197 struct GNUNET_CRYPTO_EcdsaSignature sig;
198 struct GNUNET_HashCode key_hash;
111 struct GNUNET_TIME_Relative token_rel_exp; 199 struct GNUNET_TIME_Relative token_rel_exp;
112 struct GNUNET_TIME_Relative token_ttl; 200 struct GNUNET_TIME_Relative token_ttl;
113 struct GNUNET_TIME_Absolute token_exp; 201 struct GNUNET_TIME_Absolute token_exp;
@@ -117,6 +205,7 @@ handle_token_update (void *cls,
117 struct GNUNET_TIME_Absolute new_nbf; 205 struct GNUNET_TIME_Absolute new_nbf;
118 json_t *payload_json; 206 json_t *payload_json;
119 json_t *value; 207 json_t *value;
208 json_t *cur_value;
120 json_t *new_payload_json; 209 json_t *new_payload_json;
121 json_t *token_nbf_json; 210 json_t *token_nbf_json;
122 json_t *token_exp_json; 211 json_t *token_exp_json;
@@ -141,8 +230,6 @@ handle_token_update (void *cls,
141 strlen (token_payload), 230 strlen (token_payload),
142 &token_payload_json); 231 &token_payload_json);
143 232
144 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Payload: %s\n",
145 token_payload_json);
146 payload_json = json_loads (token_payload_json, JSON_DECODE_ANY, &json_err); 233 payload_json = json_loads (token_payload_json, JSON_DECODE_ANY, &json_err);
147 GNUNET_free (token_payload_json); 234 GNUNET_free (token_payload_json);
148 235
@@ -168,7 +255,7 @@ handle_token_update (void *cls,
168 GNUNET_NAMESTORE_zone_iterator_next (ns_it); 255 GNUNET_NAMESTORE_zone_iterator_next (ns_it);
169 return; 256 return;
170 } 257 }
171 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 258 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
172 "Token is expired. Create a new one\n"); 259 "Token is expired. Create a new one\n");
173 new_exp = GNUNET_TIME_relative_to_absolute (token_rel_exp); 260 new_exp = GNUNET_TIME_relative_to_absolute (token_rel_exp);
174 new_nbf = GNUNET_TIME_absolute_get (); 261 new_nbf = GNUNET_TIME_absolute_get ();
@@ -187,9 +274,26 @@ handle_token_update (void *cls,
187 { 274 {
188 json_object_set_new (new_payload_json, key, json_integer (new_iat.abs_value_us)); 275 json_object_set_new (new_payload_json, key, json_integer (new_iat.abs_value_us));
189 } 276 }
190 else { 277 else if ((0 == strcmp (key, "iss"))
278 || (0 == strcmp (key, "aud"))
279 || (0 == strcmp (key, "sub"))
280 || (0 == strcmp (key, "rnl")))
281 {
191 json_object_set (new_payload_json, key, value); 282 json_object_set (new_payload_json, key, value);
192 } 283 }
284 else {
285 GNUNET_CRYPTO_hash (key,
286 strlen (key),
287 &key_hash);
288 //Check if attr still exists. omit of not
289 if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (ego_entry->attr_map,
290 &key_hash))
291 {
292 cur_value = GNUNET_CONTAINER_multihashmap_get (ego_entry->attr_map,
293 &key_hash);
294 json_object_set (new_payload_json, key, cur_value);
295 }
296 }
193 } 297 }
194 298
195 // reassemble and set 299 // reassemble and set
@@ -238,7 +342,7 @@ handle_token_update (void *cls,
238 &token_record, 342 &token_record,
239 &store_token_cont, 343 &store_token_cont,
240 ego_entry); 344 ego_entry);
241 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, ">>> Updating Token w/ %s\n", new_token); 345 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, ">>> Updating Token w/ %s\n", new_token);
242 GNUNET_free (new_token); 346 GNUNET_free (new_token);
243 GNUNET_free (token); 347 GNUNET_free (token);
244 token = NULL; 348 token = NULL;
@@ -250,6 +354,39 @@ static void
250update_identities(void *cls, 354update_identities(void *cls,
251 const struct GNUNET_SCHEDULER_TaskContext *tc); 355 const struct GNUNET_SCHEDULER_TaskContext *tc);
252 356
357/**
358 *
359 * Cleanup attr_map
360 *
361 * @param cls NULL
362 * @param key the key
363 * @param value the json_t attribute value
364 * @return GNUNET_YES
365 */
366static int
367clear_ego_attrs (void *cls,
368 const struct GNUNET_HashCode *key,
369 void *value)
370{
371 json_t *attr_value = value;
372
373 json_decref (attr_value);
374
375 return GNUNET_YES;
376}
377
378
379/**
380 *
381 * Update all ID_TOKEN records for an identity and store them
382 *
383 * @param cls the identity entry
384 * @param zone the identity
385 * @param lbl the name of the record
386 * @param rd_count number of records
387 * @param rd record data
388 *
389 */
253static void 390static void
254token_collect (void *cls, 391token_collect (void *cls,
255 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 392 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
@@ -262,14 +399,17 @@ token_collect (void *cls,
262 if (NULL == lbl) 399 if (NULL == lbl)
263 { 400 {
264 //Done 401 //Done
265 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 402 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
266 ">>> Updating Ego finished\n"); 403 ">>> Updating Ego finished\n");
404 //Clear attribute map for ego
405 GNUNET_CONTAINER_multihashmap_iterate (ego_entry->attr_map,
406 &clear_ego_attrs,
407 ego_entry);
408 GNUNET_CONTAINER_multihashmap_clear (ego_entry->attr_map);
267 GNUNET_SCHEDULER_add_now (&update_identities, ego_entry->next); 409 GNUNET_SCHEDULER_add_now (&update_identities, ego_entry->next);
268 return; 410 return;
269 } 411 }
270 412
271 //TODO autopurge expired tokens here if set in config
272 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, ">>> Found record\n");
273 //There should be only a single record for a token under a label 413 //There should be only a single record for a token under a label
274 if ((1 != rd_count) 414 if ((1 != rd_count)
275 || (rd->record_type != GNUNET_GNSRECORD_TYPE_ID_TOKEN) 415 || (rd->record_type != GNUNET_GNSRECORD_TYPE_ID_TOKEN)
@@ -282,13 +422,102 @@ token_collect (void *cls,
282 rd->data, 422 rd->data,
283 rd->data_size); 423 rd->data_size);
284 label = GNUNET_strdup (lbl); 424 label = GNUNET_strdup (lbl);
285 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Got token: %s\n", token);
286 425
287 GNUNET_SCHEDULER_add_now (&handle_token_update, ego_entry); 426 GNUNET_SCHEDULER_add_now (&handle_token_update, ego_entry);
288} 427}
289 428
290 429
430/**
431 *
432 * Collect all ID_ATTR records for an identity and store them
433 *
434 * @param cls the identity entry
435 * @param zone the identity
436 * @param lbl the name of the record
437 * @param rd_count number of records
438 * @param rd record data
439 *
440 */
441static void
442attribute_collect (void *cls,
443 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
444 const char *lbl,
445 unsigned int rd_count,
446 const struct GNUNET_GNSRECORD_Data *rd)
447{
448 struct EgoEntry *ego_entry = cls;
449 json_t *attr_value;
450 struct GNUNET_HashCode key;
451 char* attr;
452 int i;
291 453
454 if (NULL == lbl)
455 {
456 //Done
457 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
458 ">>> Updating Attributes finished\n");
459 ego_entry->attributes_dirty = GNUNET_NO;
460 GNUNET_SCHEDULER_add_now (&update_identities, ego_entry);
461 return;
462 }
463
464 if (0 == rd_count)
465 {
466 GNUNET_NAMESTORE_zone_iterator_next (ns_it);
467 return;
468 }
469 GNUNET_CRYPTO_hash (lbl,
470 strlen (lbl),
471 &key);
472 if (1 == rd_count)
473 {
474 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
475 {
476 attr = GNUNET_GNSRECORD_value_to_string (rd->record_type,
477 rd->data,
478 rd->data_size);
479 attr_value = json_string (attr);
480 GNUNET_CONTAINER_multihashmap_put (ego_entry->attr_map,
481 &key,
482 attr_value,
483 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
484 GNUNET_free (attr);
485 }
486
487 GNUNET_NAMESTORE_zone_iterator_next (ns_it);
488 return;
489 }
490
491 attr_value = json_array();
492 for (i = 0; i < rd_count; i++)
493 {
494 if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
495 {
496 attr = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
497 rd[i].data,
498 rd[i].data_size);
499 json_array_append_new (attr_value, json_string (attr));
500 GNUNET_free (attr);
501 }
502
503 }
504 GNUNET_CONTAINER_multihashmap_put (ego_entry->attr_map,
505 &key,
506 attr_value,
507 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
508 GNUNET_NAMESTORE_zone_iterator_next (ns_it);
509 return;
510}
511
512/**
513 *
514 * Update identity information for ego. If attribute map is
515 * dirty, first update the attributes.
516 *
517 * @param cls the ego to update
518 * param tc task context
519 *
520 */
292static void 521static void
293update_identities(void *cls, 522update_identities(void *cls,
294 const struct GNUNET_SCHEDULER_TaskContext *tc) 523 const struct GNUNET_SCHEDULER_TaskContext *tc)
@@ -299,33 +528,59 @@ update_identities(void *cls,
299 { 528 {
300 if (min_rel_exp.rel_value_us < MIN_WAIT_TIME.rel_value_us) 529 if (min_rel_exp.rel_value_us < MIN_WAIT_TIME.rel_value_us)
301 min_rel_exp = MIN_WAIT_TIME; 530 min_rel_exp = MIN_WAIT_TIME;
302 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, ">>> Finished. Rescheduling in %d\n", min_rel_exp.rel_value_us); 531 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
532 ">>> Finished. Rescheduling in %d\n",
533 min_rel_exp.rel_value_us);
303 ns_it = NULL; 534 ns_it = NULL;
304 //finished -> TODO reschedule 535 //finished -> TODO reschedule
305 update_task = GNUNET_SCHEDULER_add_delayed (min_rel_exp, 536 update_task = GNUNET_SCHEDULER_add_delayed (min_rel_exp,
306 &update_identities, 537 &update_identities,
307 ego_head); 538 ego_head);
539 min_rel_exp.rel_value_us = 0;
308 return; 540 return;
309 } 541 }
310 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, ">>> Updating Ego\n");
311 priv_key = GNUNET_IDENTITY_ego_get_private_key (next_ego->ego); 542 priv_key = GNUNET_IDENTITY_ego_get_private_key (next_ego->ego);
312 ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle, 543 if (GNUNET_YES == next_ego->attributes_dirty)
313 priv_key, 544 {
314 &token_collect, 545 //Starting over. We must update the Attributes for they might have changed.
315 next_ego); 546 ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
547 priv_key,
548 &attribute_collect,
549 next_ego);
550
551 }
552 else
553 {
554 //Ego will be dirty next time
555 next_ego->attributes_dirty = GNUNET_YES;
556 ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
557 priv_key,
558 &token_collect,
559 next_ego);
560 }
316} 561}
317 562
318 563
319/* ************************* Global helpers ********************* */
320 564
565/**
566 * Function called initially to start update task
567 */
321static void 568static void
322init_cont () 569init_cont ()
323{ 570{
324 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, ">>> Starting Service\n"); 571 GNUNET_log (GNUNET_ERROR_TYPE_INFO, ">>> Starting Service\n");
325 //Initially iterate all itenties and refresh all tokens 572 //Initially iterate all itenties and refresh all tokens
326 update_task = GNUNET_SCHEDULER_add_now (&update_identities, ego_head); 573 update_task = GNUNET_SCHEDULER_add_now (&update_identities, ego_head);
327} 574}
328 575
576/**
577 * Initial ego collection function.
578 *
579 * @param cls NULL
580 * @param ego ego
581 * @param ctx context
582 * @param identifier ego name
583 */
329static void 584static void
330list_ego (void *cls, 585list_ego (void *cls,
331 struct GNUNET_IDENTITY_Ego *ego, 586 struct GNUNET_IDENTITY_Ego *ego,
@@ -342,10 +597,16 @@ list_ego (void *cls,
342 if (STATE_INIT == state) { 597 if (STATE_INIT == state) {
343 new_entry = GNUNET_malloc (sizeof (struct EgoEntry)); 598 new_entry = GNUNET_malloc (sizeof (struct EgoEntry));
344 new_entry->ego = ego; 599 new_entry->ego = ego;
600 new_entry->attr_map = GNUNET_CONTAINER_multihashmap_create (5,
601 GNUNET_NO);
602 new_entry->attributes_dirty = GNUNET_YES;
345 GNUNET_CONTAINER_DLL_insert_tail(ego_head, ego_tail, new_entry); 603 GNUNET_CONTAINER_DLL_insert_tail(ego_head, ego_tail, new_entry);
346 } 604 }
347} 605}
348 606
607/**
608 * Cleanup task
609 */
349static void 610static void
350cleanup() 611cleanup()
351{ 612{
@@ -375,11 +636,25 @@ cleanup()
375 NULL != ego_entry;) 636 NULL != ego_entry;)
376 { 637 {
377 ego_tmp = ego_entry; 638 ego_tmp = ego_entry;
639 if (0 != GNUNET_CONTAINER_multihashmap_size (ego_tmp->attr_map))
640 {
641 GNUNET_CONTAINER_multihashmap_iterate (ego_tmp->attr_map,
642 &clear_ego_attrs,
643 ego_tmp);
644
645 }
646 GNUNET_CONTAINER_multihashmap_destroy (ego_tmp->attr_map);
378 ego_entry = ego_entry->next; 647 ego_entry = ego_entry->next;
379 GNUNET_free (ego_tmp); 648 GNUNET_free (ego_tmp);
380 } 649 }
381} 650}
382 651
652/**
653 * Shutdown task
654 *
655 * @param cls NULL
656 * @param tc task context
657 */
383static void 658static void
384do_shutdown (void *cls, 659do_shutdown (void *cls,
385 const struct GNUNET_SCHEDULER_TaskContext *tc) 660 const struct GNUNET_SCHEDULER_TaskContext *tc)
@@ -410,7 +685,7 @@ run (void *cls,
410 ns_handle = GNUNET_NAMESTORE_connect (cfg); 685 ns_handle = GNUNET_NAMESTORE_connect (cfg);
411 if (NULL == ns_handle) 686 if (NULL == ns_handle)
412 { 687 {
413 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connectin to namestore"); 688 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to namestore");
414 } 689 }
415 690
416 identity_handle = GNUNET_IDENTITY_connect (cfg, 691 identity_handle = GNUNET_IDENTITY_connect (cfg,