aboutsummaryrefslogtreecommitdiff
path: root/src/identity-provider/gnunet-service-identity-provider.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/identity-provider/gnunet-service-identity-provider.c')
-rw-r--r--src/identity-provider/gnunet-service-identity-provider.c3064
1 files changed, 1968 insertions, 1096 deletions
diff --git a/src/identity-provider/gnunet-service-identity-provider.c b/src/identity-provider/gnunet-service-identity-provider.c
index 53fd02c9f..4e1de36cd 100644
--- a/src/identity-provider/gnunet-service-identity-provider.c
+++ b/src/identity-provider/gnunet-service-identity-provider.c
@@ -30,12 +30,14 @@
30#include "gnunet_identity_service.h" 30#include "gnunet_identity_service.h"
31#include "gnunet_gnsrecord_lib.h" 31#include "gnunet_gnsrecord_lib.h"
32#include "gnunet_namestore_service.h" 32#include "gnunet_namestore_service.h"
33#include "gnunet_abe_lib.h"
34#include "gnunet_credential_service.h"
33#include "gnunet_statistics_service.h" 35#include "gnunet_statistics_service.h"
34#include "gnunet_gns_service.h" 36#include "gnunet_gns_service.h"
37#include "gnunet_identity_provider_plugin.h"
38#include "gnunet_identity_attribute_lib.h"
35#include "gnunet_signatures.h" 39#include "gnunet_signatures.h"
36#include "identity_provider.h" 40#include "identity_provider.h"
37#include "identity_token.h"
38#include <inttypes.h>
39 41
40/** 42/**
41 * First pass state 43 * First pass state
@@ -58,24 +60,19 @@
58#define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS 60#define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS
59 61
60/** 62/**
61 * Service state (to detect initial update pass) 63 * Identity handle
62 */
63static int state;
64
65/**
66 * Head of ego entry DLL
67 */ 64 */
68static struct EgoEntry *ego_head; 65static struct GNUNET_IDENTITY_Handle *identity_handle;
69 66
70/** 67/**
71 * Tail of ego entry DLL 68 * Database handle
72 */ 69 */
73static struct EgoEntry *ego_tail; 70static struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *TKT_database;
74 71
75/** 72/**
76 * Identity handle 73 * Name of DB plugin
77 */ 74 */
78static struct GNUNET_IDENTITY_Handle *identity_handle; 75static char *db_lib_name;
79 76
80/** 77/**
81 * Token expiration interval 78 * Token expiration interval
@@ -93,6 +90,16 @@ static struct GNUNET_NAMESTORE_Handle *ns_handle;
93static struct GNUNET_GNS_Handle *gns_handle; 90static struct GNUNET_GNS_Handle *gns_handle;
94 91
95/** 92/**
93 * Credential handle
94 */
95static struct GNUNET_CREDENTIAL_Handle *credential_handle;
96
97/**
98 * Stats handle
99 */
100static struct GNUNET_STATISTICS_Handle *stats_handle;
101
102/**
96 * Namestore qe 103 * Namestore qe
97 */ 104 */
98static struct GNUNET_NAMESTORE_QueueEntry *ns_qe; 105static struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
@@ -112,11 +119,6 @@ static struct GNUNET_SCHEDULER_Task *timeout_task;
112 */ 119 */
113static struct GNUNET_SCHEDULER_Task *update_task; 120static struct GNUNET_SCHEDULER_Task *update_task;
114 121
115/**
116 * Timeout for next update pass
117 */
118static struct GNUNET_TIME_Relative min_rel_exp;
119
120 122
121/** 123/**
122 * Currently processed token 124 * Currently processed token
@@ -134,43 +136,260 @@ static char* label;
134static char* scopes; 136static char* scopes;
135 137
136/** 138/**
137 * Expiration for processed token 139 * Handle to the statistics service.
138 */ 140 */
139static uint64_t rd_exp; 141static struct GNUNET_STATISTICS_Handle *stats;
140 142
141/** 143/**
142 * ECDHE Privkey for processed token metadata 144 * Our configuration.
143 */ 145 */
144static struct GNUNET_CRYPTO_EcdhePrivateKey ecdhe_privkey; 146static const struct GNUNET_CONFIGURATION_Handle *cfg;
145 147
146/** 148/**
147 * Handle to the statistics service. 149 * An idp client
148 */ 150 */
149static struct GNUNET_STATISTICS_Handle *stats; 151struct IdpClient;
150 152
151/** 153/**
152 * Our configuration. 154 * A ticket iteration operation.
153 */ 155 */
154static const struct GNUNET_CONFIGURATION_Handle *cfg; 156struct TicketIteration
157{
158 /**
159 * DLL
160 */
161 struct TicketIteration *next;
162
163 /**
164 * DLL
165 */
166 struct TicketIteration *prev;
167
168 /**
169 * Client which intiated this zone iteration
170 */
171 struct IdpClient *client;
155 172
173 /**
174 * Key of the identity we are iterating over.
175 */
176 struct GNUNET_CRYPTO_EcdsaPublicKey identity;
156 177
157struct ExchangeHandle 178 /**
179 * Identity is audience
180 */
181 uint32_t is_audience;
182
183 /**
184 * The operation id fot the iteration in the response for the client
185 */
186 uint32_t r_id;
187
188 /**
189 * Offset of the iteration used to address next result of the
190 * iteration in the store
191 *
192 * Initialy set to 0 in handle_iteration_start
193 * Incremented with by every call to handle_iteration_next
194 */
195 uint32_t offset;
196
197};
198
199
200
201/**
202 * Callback after an ABE bootstrap
203 *
204 * @param cls closure
205 * @param abe_key the ABE key that exists or was created
206 */
207typedef void
208(*AbeBootstrapResult) (void *cls,
209 struct GNUNET_ABE_AbeMasterKey *abe_key);
210
211
212struct AbeBootstrapHandle
158{ 213{
214 /**
215 * Function to call when finished
216 */
217 AbeBootstrapResult proc;
159 218
160 /** 219 /**
161 * Client connection 220 * Callback closure
221 */
222 char *proc_cls;
223
224 /**
225 * Key of the zone we are iterating over.
226 */
227 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
228
229 /**
230 * Namestore Queue Entry
231 */
232 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
233
234 /**
235 * The issuer egos ABE master key
236 */
237 struct GNUNET_ABE_AbeMasterKey *abe_key;
238};
239
240/**
241 * An attribute iteration operation.
242 */
243struct AttributeIterator
244{
245 /**
246 * Next element in the DLL
247 */
248 struct AttributeIterator *next;
249
250 /**
251 * Previous element in the DLL
252 */
253 struct AttributeIterator *prev;
254
255 /**
256 * IDP client which intiated this zone iteration
257 */
258 struct IdpClient *client;
259
260 /**
261 * Key of the zone we are iterating over.
262 */
263 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
264
265 /**
266 * The issuer egos ABE master key
267 */
268 struct GNUNET_ABE_AbeMasterKey *abe_key;
269
270 /**
271 * Namestore iterator
272 */
273 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
274
275 /**
276 * The operation id fot the zone iteration in the response for the client
277 */
278 uint32_t request_id;
279
280};
281
282
283
284/**
285 * An idp client
286 */
287struct IdpClient
288{
289
290 /**
291 * The client
162 */ 292 */
163 struct GNUNET_SERVICE_Client *client; 293 struct GNUNET_SERVICE_Client *client;
164 294
165 /** 295 /**
166 * Ticket 296 * Message queue for transmission to @e client
297 */
298 struct GNUNET_MQ_Handle *mq;
299
300 /**
301 * Head of the DLL of
302 * Attribute iteration operations in
303 * progress initiated by this client
304 */
305 struct AttributeIterator *op_head;
306
307 /**
308 * Tail of the DLL of
309 * Attribute iteration operations
310 * in progress initiated by this client
311 */
312 struct AttributeIterator *op_tail;
313
314 /**
315 * Head of DLL of ticket iteration ops
316 */
317 struct TicketIteration *ticket_iter_head;
318
319 /**
320 * Tail of DLL of ticket iteration ops
321 */
322 struct TicketIteration *ticket_iter_tail;
323
324
325 /**
326 * Head of DLL of ticket revocation ops
327 */
328 struct TicketRevocationHandle *revocation_list_head;
329
330 /**
331 * Tail of DLL of ticket revocation ops
332 */
333 struct TicketRevocationHandle *revocation_list_tail;
334};
335
336
337
338struct AttributeStoreHandle
339{
340
341 /**
342 * Client connection
343 */
344 struct IdpClient *client;
345
346 /**
347 * Identity
348 */
349 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
350
351 /**
352 * Identity pubkey
353 */
354 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
355
356 /**
357 * The issuer egos ABE master key
358 */
359 struct GNUNET_ABE_AbeMasterKey *abe_key;
360
361 /**
362 * QueueEntry
363 */
364 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
365
366 /**
367 * The attribute to store
368 */
369 struct GNUNET_IDENTITY_ATTRIBUTE_Claim *claim;
370
371 /**
372 * request id
373 */
374 uint32_t r_id;
375};
376
377
378/* Prototype */
379struct ParallelLookup;
380
381struct ConsumeTicketHandle
382{
383
384 /**
385 * Client connection
167 */ 386 */
168 struct TokenTicket *ticket; 387 struct IdpClient *client;
169 388
170 /** 389 /**
171 * Token returned 390 * Ticket
172 */ 391 */
173 struct IdentityToken *token; 392 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
174 393
175 /** 394 /**
176 * LookupRequest 395 * LookupRequest
@@ -180,86 +399,173 @@ struct ExchangeHandle
180 /** 399 /**
181 * Audience Key 400 * Audience Key
182 */ 401 */
183 struct GNUNET_CRYPTO_EcdsaPrivateKey aud_privkey; 402 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
184 403
185 /** 404 /**
186 * Label to return 405 * Audience Key
187 */ 406 */
188 char *label; 407 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub;
189 408
190 /** 409 /**
410 * Lookup DLL
411 */
412 struct ParallelLookup *parallel_lookups_head;
413
414 /**
415 * Lookup DLL
416 */
417 struct ParallelLookup *parallel_lookups_tail;
418
419 /**
420 * Kill task
421 */
422 struct GNUNET_SCHEDULER_Task *kill_task;
423
424 /**
425 * The ABE key
426 */
427 struct GNUNET_ABE_AbeKey *key;
428
429 /**
430 * Attributes
431 */
432 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
433
434 /**
435 * Lookup time
436 */
437 struct GNUNET_TIME_Absolute lookup_start_time;
438
439 /**
191 * request id 440 * request id
192 */ 441 */
193 uint32_t r_id; 442 uint32_t r_id;
194}; 443};
195 444
196struct IssueHandle 445/**
446 * Handle for a parallel GNS lookup job
447 */
448struct ParallelLookup
197{ 449{
450 /* DLL */
451 struct ParallelLookup *next;
452
453 /* DLL */
454 struct ParallelLookup *prev;
455
456 /* The GNS request */
457 struct GNUNET_GNS_LookupRequest *lookup_request;
458
459 /* The handle the return to */
460 struct ConsumeTicketHandle *handle;
461
462 /**
463 * Lookup time
464 */
465 struct GNUNET_TIME_Absolute lookup_start_time;
466
467 /* The label to look up */
468 char *label;
469};
470
471/**
472 * Ticket revocation request handle
473 */
474struct TicketRevocationHandle
475{
476 /**
477 * DLL
478 */
479 struct TicketRevocationHandle *next;
480
481 /**
482 * DLL
483 */
484 struct TicketRevocationHandle *prev;
198 485
199 /** 486 /**
200 * Client connection 487 * Client connection
201 */ 488 */
202 struct GNUNET_SERVICE_Client *client; 489 struct IdpClient *client;
490
491 /**
492 * Attributes to reissue
493 */
494 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
495
496 /**
497 * Attributes to revoke
498 */
499 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *rvk_attrs;
203 500
204 /** 501 /**
205 * Issuer Key 502 * Issuer Key
206 */ 503 */
207 struct GNUNET_CRYPTO_EcdsaPrivateKey iss_key; 504 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
208 505
209 /** 506 /**
210 * Issue pubkey 507 * Ticket to issue
211 */ 508 */
212 struct GNUNET_CRYPTO_EcdsaPublicKey iss_pkey; 509 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
213 510
214 /** 511 /**
215 * Audience Key 512 * QueueEntry
216 */ 513 */
217 struct GNUNET_CRYPTO_EcdsaPublicKey aud_key; 514 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
218 515
219 /** 516 /**
220 * Expiration 517 * Namestore iterator
221 */ 518 */
222 struct GNUNET_TIME_Absolute expiration; 519 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
223 520
224 /** 521 /**
225 * Scopes 522 * The ABE master key
226 */ 523 */
227 char *scopes; 524 struct GNUNET_ABE_AbeMasterKey *abe_key;
228 525
229 /** 526 /**
230 * nonce 527 * Offset
231 */ 528 */
232 uint64_t nonce; 529 uint32_t offset;
233 530
234 /** 531 /**
235 * NS iterator 532 * request id
236 */ 533 */
237 struct GNUNET_NAMESTORE_ZoneIterator *ns_it; 534 uint32_t r_id;
535};
536
537
538
539/**
540 * Ticket issue request handle
541 */
542struct TicketIssueHandle
543{
238 544
239 /** 545 /**
240 * Attribute map 546 * Client connection
241 */ 547 */
242 struct GNUNET_CONTAINER_MultiHashMap *attr_map; 548 struct IdpClient *client;
243 549
244 /** 550 /**
245 * Token 551 * Attributes to issue
246 */ 552 */
247 struct IdentityToken *token; 553 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs;
248 554
249 /** 555 /**
250 * Ticket 556 * Issuer Key
251 */ 557 */
252 struct TokenTicket *ticket; 558 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
253 559
254 /** 560 /**
255 * QueueEntry 561 * Ticket to issue
256 */ 562 */
257 struct GNUNET_NAMESTORE_QueueEntry *ns_qe; 563 struct GNUNET_IDENTITY_PROVIDER_Ticket ticket;
258 564
259 /** 565 /**
260 * The label the token is stored under 566 * QueueEntry
261 */ 567 */
262 char *label; 568 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
263 569
264 /** 570 /**
265 * request id 571 * request id
@@ -267,6 +573,7 @@ struct IssueHandle
267 uint32_t r_id; 573 uint32_t r_id;
268}; 574};
269 575
576
270/** 577/**
271 * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format 578 * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format
272 * 579 *
@@ -293,1303 +600,1774 @@ struct EgoEntry
293 */ 600 */
294 struct GNUNET_CONTAINER_MultiHashMap *attr_map; 601 struct GNUNET_CONTAINER_MultiHashMap *attr_map;
295 602
296 /**
297 * Attributes are old and should be updated if GNUNET_YES
298 */
299 int attributes_dirty;
300}; 603};
301 604
302/** 605/**
303 * Continuation for token store call 606 * Cleanup task
607 */
608static void
609cleanup()
610{
611 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
612 "Cleaning up\n");
613 if (NULL != stats)
614 {
615 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
616 stats = NULL;
617 }
618 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name,
619 TKT_database));
620 GNUNET_free (db_lib_name);
621 db_lib_name = NULL;
622 if (NULL != timeout_task)
623 GNUNET_SCHEDULER_cancel (timeout_task);
624 if (NULL != update_task)
625 GNUNET_SCHEDULER_cancel (update_task);
626 if (NULL != identity_handle)
627 GNUNET_IDENTITY_disconnect (identity_handle);
628 if (NULL != gns_handle)
629 GNUNET_GNS_disconnect (gns_handle);
630 if (NULL != credential_handle)
631 GNUNET_CREDENTIAL_disconnect (credential_handle);
632 if (NULL != ns_it)
633 GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
634 if (NULL != ns_qe)
635 GNUNET_NAMESTORE_cancel (ns_qe);
636 if (NULL != ns_handle)
637 GNUNET_NAMESTORE_disconnect (ns_handle);
638 if (NULL != stats_handle)
639 GNUNET_STATISTICS_destroy (stats_handle, GNUNET_NO);
640 GNUNET_free_non_null (token);
641 GNUNET_free_non_null (label);
642
643}
644
645/**
646 * Shutdown task
304 * 647 *
305 * @param cls NULL 648 * @param cls NULL
306 * @param success error code
307 * @param emsg error message
308 */ 649 */
309static void 650static void
310store_token_cont (void *cls, 651do_shutdown (void *cls)
311 int32_t success, 652{
312 const char *emsg) 653 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
654 "Shutting down...\n");
655 cleanup();
656}
657
658/**
659 * Finished storing newly bootstrapped ABE key
660 */
661static void
662bootstrap_store_cont (void *cls,
663 int32_t success,
664 const char *emsg)
313{ 665{
314 ns_qe = NULL; 666 struct AbeBootstrapHandle *abh = cls;
315 if (GNUNET_SYSERR == success) 667 if (GNUNET_SYSERR == success)
316 { 668 {
317 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 669 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
318 "Failed to update token: %s\n", 670 "Failed to bootstrap ABE master %s\n",
319 emsg); 671 emsg);
672 abh->proc (abh->proc_cls, NULL);
673 GNUNET_free (abh->abe_key);
674 GNUNET_free (abh);
320 return; 675 return;
321 } 676 }
322 GNUNET_NAMESTORE_zone_iterator_next (ns_it); 677 abh->proc (abh->proc_cls, abh->abe_key);
678 GNUNET_free (abh);
323} 679}
324 680
325
326/** 681/**
327 * This function updates the old token with new attributes, 682 * Generates and stores a new ABE key
328 * removes deleted attributes and expiration times.
329 *
330 * @param cls the ego entry
331 */ 683 */
332static void 684static void
333handle_token_update (void *cls) 685bootstrap_store_task (void *cls)
334{ 686{
335 char *token_metadata; 687 struct AbeBootstrapHandle *abh = cls;
336 char *write_ptr; 688 struct GNUNET_GNSRECORD_Data rd[1];
337 char *enc_token_str; 689 char *key;
338 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; 690
339 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; 691 rd[0].data_size = GNUNET_ABE_cpabe_serialize_master_key (abh->abe_key,
340 struct GNUNET_CRYPTO_EcdhePrivateKey *new_ecdhe_privkey; 692 (void**)&key);
341 struct EgoEntry *ego_entry = cls; 693 rd[0].data = key;
342 struct GNUNET_GNSRECORD_Data token_record[2]; 694 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
343 struct GNUNET_HashCode key_hash; 695 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE;
344 struct GNUNET_TIME_Relative token_rel_exp; 696 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
345 struct GNUNET_TIME_Relative token_ttl; 697 abh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
346 struct GNUNET_TIME_Absolute token_exp; 698 &abh->identity,
347 struct GNUNET_TIME_Absolute token_nbf; 699 "+",
348 struct GNUNET_TIME_Absolute new_exp; 700 1,
349 struct GNUNET_TIME_Absolute new_iat; 701 rd,
350 struct GNUNET_TIME_Absolute new_nbf; 702 &bootstrap_store_cont,
351 struct IdentityToken *new_token; 703 abh);
352 struct TokenAttr *cur_value; 704 GNUNET_free (key);
353 struct TokenAttr *attr; 705}
354 size_t token_metadata_len;
355
356 priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
357 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego,
358 &pub_key);
359
360 //Note: We need the token expiration time here. Not the record expiration
361 //time.
362 //There are two types of tokens: Token that expire on GNS level with
363 //an absolute expiration time. Those are basically tokens that will
364 //be automatically revoked on (record)expiration.
365 //Tokens stored with relative expiration times will expire on the token level (token expiration)
366 //but this service will reissue new tokens that can be retrieved from GNS
367 //automatically.
368
369 for (attr = token->attr_head; NULL != attr; attr = attr->next)
370 {
371 if (0 == strcmp (attr->name, "exp"))
372 {
373 GNUNET_assert (1 == sscanf (attr->val_head->value,
374 "%"SCNu64,
375 &token_exp.abs_value_us));
376 } else if (0 == strcmp (attr->name, "nbf")) {
377 GNUNET_assert (1 == sscanf (attr->val_head->value,
378 "%"SCNu64,
379 &token_nbf.abs_value_us));
380 }
381 }
382 token_rel_exp = GNUNET_TIME_absolute_get_difference (token_nbf, token_exp);
383
384 token_ttl = GNUNET_TIME_absolute_get_remaining (token_exp);
385 if (0 != GNUNET_TIME_absolute_get_remaining (token_exp).rel_value_us)
386 {
387 //This token is not yet expired! Save and skip
388 if (min_rel_exp.rel_value_us > token_ttl.rel_value_us)
389 {
390 min_rel_exp = token_ttl;
391 }
392 GNUNET_free (token);
393 token = NULL;
394 GNUNET_free (label);
395 label = NULL;
396 GNUNET_free (scopes);
397 scopes = NULL;
398 GNUNET_NAMESTORE_zone_iterator_next (ns_it);
399 return;
400 }
401 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
402 "Token is expired. Create a new one\n");
403 new_token = token_create (&pub_key,
404 &token->aud_key);
405 new_exp = GNUNET_TIME_relative_to_absolute (token_rel_exp);
406 new_nbf = GNUNET_TIME_absolute_get ();
407 new_iat = new_nbf;
408 for (attr = token->attr_head; NULL != attr; attr = attr->next)
409 {
410 if (0 == strcmp (attr->name, "exp"))
411 {
412 token_add_attr_int (new_token, attr->name, new_exp.abs_value_us);
413 }
414 else if (0 == strcmp (attr->name, "nbf"))
415 {
416 token_add_attr_int (new_token, attr->name, new_nbf.abs_value_us);
417 }
418 else if (0 == strcmp (attr->name, "iat"))
419 {
420 token_add_attr_int (new_token, attr->name, new_iat.abs_value_us);
421 }
422 else if ((0 == strcmp (attr->name, "iss"))
423 || (0 == strcmp (attr->name, "aud")))
424 {
425 //Omit
426 }
427 else if (0 == strcmp (attr->name, "sub"))
428 {
429 token_add_attr (new_token,
430 attr->name,
431 attr->val_head->value);
432 }
433 else
434 {
435 GNUNET_CRYPTO_hash (attr->name,
436 strlen (attr->name),
437 &key_hash);
438 //Check if attr still exists. omit of not
439 if (GNUNET_NO !=
440 GNUNET_CONTAINER_multihashmap_contains (ego_entry->attr_map,
441 &key_hash))
442 {
443 cur_value = GNUNET_CONTAINER_multihashmap_get (ego_entry->attr_map,
444 &key_hash);
445 GNUNET_assert (NULL != cur_value);
446 GNUNET_CONTAINER_DLL_insert (new_token->attr_head,
447 new_token->attr_tail,
448 cur_value);
449 }
450 }
451 }
452 706
453 // reassemble and set 707/**
454 GNUNET_assert (token_serialize (new_token, 708 * Error checking for ABE master
455 priv_key, 709 */
456 &new_ecdhe_privkey, 710static void
457 &enc_token_str)); 711bootstrap_abe_error (void *cls)
458 712{
459 token_record[0].data = enc_token_str; 713 struct AbeBootstrapHandle *abh = cls;
460 token_record[0].data_size = strlen (enc_token_str) + 1; 714 GNUNET_free (abh);
461 token_record[0].expiration_time = rd_exp; //Old expiration time 715 abh->proc (abh->proc_cls, NULL);
462 token_record[0].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN; 716 GNUNET_free (abh);
463 token_record[0].flags = GNUNET_GNSRECORD_RF_NONE;
464
465 //Meta
466 token_metadata_len = sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)
467 + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)
468 + strlen (scopes) + 1; //With 0-Terminator
469 token_metadata = GNUNET_malloc (token_metadata_len);
470 write_ptr = token_metadata;
471 GNUNET_memcpy (token_metadata, new_ecdhe_privkey, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
472 write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey);
473 GNUNET_memcpy (write_ptr, &token->aud_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
474 write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
475 GNUNET_memcpy (write_ptr, scopes, strlen (scopes) + 1); //with 0-Terminator;
476
477 token_record[1].data = token_metadata;
478 token_record[1].data_size = token_metadata_len;
479 token_record[1].expiration_time = rd_exp;
480 token_record[1].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA;
481 token_record[1].flags = GNUNET_GNSRECORD_RF_PRIVATE;
482
483 ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
484 priv_key,
485 label,
486 2,
487 token_record,
488 &store_token_cont,
489 ego_entry);
490 token_destroy (new_token);
491 token_destroy (token);
492 GNUNET_free (new_ecdhe_privkey);
493 GNUNET_free (enc_token_str);
494 token = NULL;
495 GNUNET_free (label);
496 label = NULL;
497 GNUNET_free (scopes);
498 scopes = NULL;
499} 717}
500 718
501 719
720/**
721 * Handle ABE lookup in namestore
722 */
502static void 723static void
503update_identities(void *cls); 724bootstrap_abe_result (void *cls,
725 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
726 const char *label,
727 unsigned int rd_count,
728 const struct GNUNET_GNSRECORD_Data *rd)
729{
730 struct AbeBootstrapHandle *abh = cls;
731 struct GNUNET_ABE_AbeMasterKey *abe_key;
732
733 for (uint32_t i=0;i<rd_count;i++) {
734 if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
735 continue;
736 abe_key = GNUNET_ABE_cpabe_deserialize_master_key (rd[i].data,
737 rd[i].data_size);
738 abh->proc (abh->proc_cls, abe_key);
739 GNUNET_free (abh);
740 return;
741 }
504 742
743 //No ABE master found, bootstrapping...
744 abh->abe_key = GNUNET_ABE_cpabe_create_master_key ();
745 GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
746}
505 747
506/** 748/**
507 * 749 * Bootstrap ABE master if it does not yet exists.
508 * Cleanup attr_map 750 * Will call the AbeBootstrapResult processor when done.
509 * 751 * will always recreate the ABE key of GNUNET_YES == recreate
510 * @param cls NULL
511 * @param key the key
512 * @param value the json_t attribute value
513 * @return #GNUNET_YES
514 */ 752 */
515static int 753static void
516clear_ego_attrs (void *cls, 754bootstrap_abe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
517 const struct GNUNET_HashCode *key, 755 AbeBootstrapResult proc,
518 void *value) 756 void* cls,
519{ 757 int recreate)
520 struct TokenAttr *attr = value; 758{
521 struct TokenAttrValue *val; 759 struct AbeBootstrapHandle *abh;
522 struct TokenAttrValue *tmp_val; 760
523 for (val = attr->val_head; NULL != val;) 761 abh = GNUNET_new (struct AbeBootstrapHandle);
762 abh->proc = proc;
763 abh->proc_cls = cls;
764 abh->identity = *identity;
765 if (GNUNET_YES == recreate)
524 { 766 {
525 tmp_val = val->next; 767 abh->abe_key = GNUNET_ABE_cpabe_create_master_key ();
526 GNUNET_CONTAINER_DLL_remove (attr->val_head, 768 GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
527 attr->val_tail, 769 } else {
528 val); 770 abh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
529 GNUNET_free (val->value); 771 identity,
530 GNUNET_free (val); 772 "+",
531 val = tmp_val; 773 &bootstrap_abe_error,
774 abh,
775 &bootstrap_abe_result,
776 abh);
532 } 777 }
533 GNUNET_free (attr->name);
534 GNUNET_free (attr);
535
536 return GNUNET_YES;
537} 778}
538 779
539 780
540static void
541token_collect_error_cb (void *cls)
542{
543 struct EgoEntry *ego_entry = cls;
544 781
545 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 782static int
546 ">>> Updating Ego failed!\n"); 783create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
547 //Clear attribute map for ego 784 struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
548 GNUNET_CONTAINER_multihashmap_iterate (ego_entry->attr_map, 785 struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
549 &clear_ego_attrs, 786{
550 ego_entry); 787 struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
551 GNUNET_CONTAINER_multihashmap_clear (ego_entry->attr_map); 788
552 update_task = GNUNET_SCHEDULER_add_now (&update_identities, 789 GNUNET_CRYPTO_hash_to_enc (new_key_hash,
553 ego_entry->next); 790 &new_key_hash_str);
791 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
792 static const char ctx_key[] = "gnuid-aes-ctx-key";
793 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
794 new_key_hash, sizeof (struct GNUNET_HashCode),
795 ctx_key, strlen (ctx_key),
796 NULL, 0);
797 static const char ctx_iv[] = "gnuid-aes-ctx-iv";
798 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
799 new_key_hash, sizeof (struct GNUNET_HashCode),
800 ctx_iv, strlen (ctx_iv),
801 NULL, 0);
802 return GNUNET_OK;
803}
554 804
805static void
806cleanup_ticket_issue_handle (struct TicketIssueHandle *handle)
807{
808 if (NULL != handle->attrs)
809 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->attrs);
810 if (NULL != handle->ns_qe)
811 GNUNET_NAMESTORE_cancel (handle->ns_qe);
812 GNUNET_free (handle);
555} 813}
556 814
557 815
558static void 816static void
559token_collect_finished_cb (void *cls) 817send_ticket_result (struct IdpClient *client,
818 uint32_t r_id,
819 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
820 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
560{ 821{
561 struct EgoEntry *ego_entry = cls; 822 struct TicketResultMessage *irm;
823 struct GNUNET_MQ_Envelope *env;
824 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket_buf;
562 825
563 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 826 /* store ticket in DB */
564 ">>> Updating Ego finished\n"); 827 if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
565 //Clear attribute map for ego 828 ticket,
566 GNUNET_CONTAINER_multihashmap_iterate (ego_entry->attr_map, 829 attrs))
567 &clear_ego_attrs, 830 {
568 ego_entry); 831 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
569 GNUNET_CONTAINER_multihashmap_clear (ego_entry->attr_map); 832 "Unable to store ticket after issue\n");
570 update_task = GNUNET_SCHEDULER_add_now (&update_identities, 833 GNUNET_break (0);
571 ego_entry->next); 834 }
572}
573 835
836 env = GNUNET_MQ_msg_extra (irm,
837 sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket),
838 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
839 ticket_buf = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&irm[1];
840 *ticket_buf = *ticket;
841 irm->id = htonl (r_id);
842 GNUNET_MQ_send (client->mq,
843 env);
844}
574 845
575/**
576 *
577 * Update all ID_TOKEN records for an identity and store them
578 *
579 * @param cls the identity entry
580 * @param zone the identity
581 * @param lbl the name of the record
582 * @param rd_count number of records
583 * @param rd record data
584 */
585static void 846static void
586token_collect (void *cls, 847store_ticket_issue_cont (void *cls,
587 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 848 int32_t success,
588 const char *lbl, 849 const char *emsg)
589 unsigned int rd_count, 850{
590 const struct GNUNET_GNSRECORD_Data *rd) 851 struct TicketIssueHandle *handle = cls;
591{ 852
592 struct EgoEntry *ego_entry = cls; 853 handle->ns_qe = NULL;
593 const struct GNUNET_GNSRECORD_Data *token_record; 854 if (GNUNET_SYSERR == success)
594 const struct GNUNET_GNSRECORD_Data *token_metadata_record;
595 struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key;
596 struct GNUNET_CRYPTO_EcdhePrivateKey *priv_key;
597
598 //There should be only a single record for a token under a label
599 if (2 != rd_count)
600 { 855 {
601 GNUNET_NAMESTORE_zone_iterator_next (ns_it); 856 cleanup_ticket_issue_handle (handle);
857 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
858 "Unknown Error\n");
859 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
602 return; 860 return;
603 } 861 }
862 send_ticket_result (handle->client,
863 handle->r_id,
864 &handle->ticket,
865 handle->attrs);
866 cleanup_ticket_issue_handle (handle);
867}
604 868
605 if (rd[0].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA) 869
606 { 870
607 token_metadata_record = &rd[0]; 871int
608 token_record = &rd[1]; 872serialize_abe_keyinfo2 (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
873 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs,
874 const struct GNUNET_ABE_AbeKey *rp_key,
875 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
876 char **result)
877{
878 struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
879 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
880 char *enc_keyinfo;
881 char *serialized_key;
882 char *buf;
883 char *write_ptr;
884 char attrs_str_len;
885 ssize_t size;
886
887 struct GNUNET_CRYPTO_SymmetricSessionKey skey;
888 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
889 struct GNUNET_HashCode new_key_hash;
890 ssize_t enc_size;
891
892 size = GNUNET_ABE_cpabe_serialize_key (rp_key,
893 (void**)&serialized_key);
894 attrs_str_len = 0;
895 for (le = attrs->list_head; NULL != le; le = le->next) {
896 attrs_str_len += strlen (le->claim->name) + 1;
609 } 897 }
610 else 898 buf = GNUNET_malloc (attrs_str_len + size);
611 { 899 write_ptr = buf;
612 token_record = &rd[0]; 900 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
613 token_metadata_record = &rd[1]; 901 "Writing attributes\n");
902 for (le = attrs->list_head; NULL != le; le = le->next) {
903 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
904 "%s\n", le->claim->name);
905
906
907 GNUNET_memcpy (write_ptr,
908 le->claim->name,
909 strlen (le->claim->name));
910 write_ptr[strlen (le->claim->name)] = ',';
911 write_ptr += strlen (le->claim->name) + 1;
614 } 912 }
615 if (token_metadata_record->record_type != GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA) 913 write_ptr--;
616 { 914 write_ptr[0] = '\0'; //replace last , with a 0-terminator
617 GNUNET_NAMESTORE_zone_iterator_next (ns_it); 915 write_ptr++;
618 return; 916 GNUNET_memcpy (write_ptr,
917 serialized_key,
918 size);
919 GNUNET_free (serialized_key);
920 // ECDH keypair E = eG
921 *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
922 GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
923 &ecdh_pubkey);
924 enc_keyinfo = GNUNET_malloc (size + attrs_str_len);
925 // Derived key K = H(eB)
926 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
927 &ticket->audience,
928 &new_key_hash));
929 create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
930 enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
931 size + attrs_str_len,
932 &skey, &iv,
933 enc_keyinfo);
934 *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
935 enc_size);
936 GNUNET_memcpy (*result,
937 &ecdh_pubkey,
938 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
939 GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
940 enc_keyinfo,
941 enc_size);
942 GNUNET_free (enc_keyinfo);
943 GNUNET_free (buf);
944 return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
945}
946
947
948
949static void
950issue_ticket_after_abe_bootstrap (void *cls,
951 struct GNUNET_ABE_AbeMasterKey *abe_key)
952{
953 struct TicketIssueHandle *ih = cls;
954 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
955 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
956 struct GNUNET_GNSRECORD_Data code_record[1];
957 struct GNUNET_ABE_AbeKey *rp_key;
958 char *code_record_data;
959 char **attrs;
960 char *label;
961 char *policy;
962 int attrs_len;
963 uint32_t i;
964 size_t code_record_len;
965
966 //Create new ABE key for RP
967 attrs_len = 0;
968 for (le = ih->attrs->list_head; NULL != le; le = le->next)
969 attrs_len++;
970 attrs = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
971 i = 0;
972 for (le = ih->attrs->list_head; NULL != le; le = le->next) {
973 GNUNET_asprintf (&policy, "%s_%lu",
974 le->claim->name,
975 le->claim->version);
976 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
977 "Adding attribute to key: %s\n",
978 policy);
979 attrs[i] = policy;
980 i++;
619 } 981 }
620 if (token_record->record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN) 982 attrs[i] = NULL;
983 rp_key = GNUNET_ABE_cpabe_create_key (abe_key,
984 attrs);
985
986 //TODO review this wireformat
987 code_record_len = serialize_abe_keyinfo2 (&ih->ticket,
988 ih->attrs,
989 rp_key,
990 &ecdhe_privkey,
991 &code_record_data);
992 code_record[0].data = code_record_data;
993 code_record[0].data_size = code_record_len;
994 code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
995 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
996 code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
997
998 label = GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd,
999 sizeof (uint64_t));
1000 //Publish record
1001 ih->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1002 &ih->identity,
1003 label,
1004 1,
1005 code_record,
1006 &store_ticket_issue_cont,
1007 ih);
1008 //for (; i > 0; i--)
1009 // GNUNET_free (attrs[i-1]);
1010 GNUNET_free (ecdhe_privkey);
1011 GNUNET_free (label);
1012 GNUNET_free (attrs);
1013 GNUNET_free (code_record_data);
1014 GNUNET_ABE_cpabe_delete_key (rp_key,
1015 GNUNET_YES);
1016 GNUNET_ABE_cpabe_delete_master_key (abe_key);
1017}
1018
1019
1020static int
1021check_issue_ticket_message(void *cls,
1022 const struct IssueTicketMessage *im)
1023{
1024 uint16_t size;
1025
1026 size = ntohs (im->header.size);
1027 if (size <= sizeof (struct IssueTicketMessage))
621 { 1028 {
622 GNUNET_NAMESTORE_zone_iterator_next (ns_it); 1029 GNUNET_break (0);
623 return; 1030 return GNUNET_SYSERR;
624 } 1031 }
1032 return GNUNET_OK;
1033}
625 1034
626 //Get metadata and decrypt token
627 priv_key = (struct GNUNET_CRYPTO_EcdhePrivateKey *)token_metadata_record->data;
628 ecdhe_privkey = *priv_key;
629 aud_key = (struct GNUNET_CRYPTO_EcdsaPublicKey *)&priv_key[1];
630 scopes = GNUNET_strdup ((char*) aud_key+sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
631 1035
632 token_parse2 (token_record->data, 1036static void
633 &ecdhe_privkey, 1037handle_issue_ticket_message (void *cls,
634 aud_key, 1038 const struct IssueTicketMessage *im)
635 &token); 1039{
1040 struct TicketIssueHandle *ih;
1041 struct IdpClient *idp = cls;
1042 size_t attrs_len;
1043
1044 ih = GNUNET_new (struct TicketIssueHandle);
1045 attrs_len = ntohs (im->attr_len);
1046 ih->attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize ((char*)&im[1], attrs_len);
1047 ih->r_id = ntohl (im->id);
1048 ih->client = idp;
1049 ih->identity = im->identity;
1050 GNUNET_CRYPTO_ecdsa_key_get_public (&ih->identity,
1051 &ih->ticket.identity);
1052 ih->ticket.audience = im->rp;
1053 ih->ticket.rnd =
1054 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
1055 UINT64_MAX);
1056 bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih, GNUNET_NO);
1057 GNUNET_SERVICE_client_continue (idp->client);
636 1058
637 label = GNUNET_strdup (lbl); 1059}
638 rd_exp = token_record->expiration_time;
639 1060
640 GNUNET_SCHEDULER_add_now (&handle_token_update, 1061/**********************************************************
641 ego_entry); 1062 * Revocation
1063 **********************************************************/
1064
1065/**
1066 * Cleanup revoke handle
1067 *
1068 * @param rh the ticket revocation handle
1069 */
1070static void
1071cleanup_revoke_ticket_handle (struct TicketRevocationHandle *rh)
1072{
1073 if (NULL != rh->attrs)
1074 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (rh->attrs);
1075 if (NULL != rh->rvk_attrs)
1076 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (rh->rvk_attrs);
1077 if (NULL != rh->abe_key)
1078 GNUNET_ABE_cpabe_delete_master_key (rh->abe_key);
1079 if (NULL != rh->ns_qe)
1080 GNUNET_NAMESTORE_cancel (rh->ns_qe);
1081 if (NULL != rh->ns_it)
1082 GNUNET_NAMESTORE_zone_iteration_stop (rh->ns_it);
1083 GNUNET_free (rh);
642} 1084}
643 1085
644 1086
1087/**
1088 * Send revocation result
1089 *
1090 * @param rh ticket revocation handle
1091 * @param success GNUNET_OK if successful result
1092 */
645static void 1093static void
646attribute_collect_error_cb (void *cls) 1094send_revocation_finished (struct TicketRevocationHandle *rh,
1095 uint32_t success)
647{ 1096{
648 struct EgoEntry *ego_entry = cls; 1097 struct GNUNET_MQ_Envelope *env;
1098 struct RevokeTicketResultMessage *trm;
649 1099
650 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1100 env = GNUNET_MQ_msg (trm,
651 ">>> Updating Attributes failed!\n"); 1101 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT);
652 ego_entry->attributes_dirty = GNUNET_NO; 1102 trm->id = htonl (rh->r_id);
653 update_task = GNUNET_SCHEDULER_add_now (&update_identities, 1103 trm->success = htonl (success);
654 ego_entry); 1104 GNUNET_MQ_send (rh->client->mq,
1105 env);
1106 GNUNET_CONTAINER_DLL_remove (rh->client->revocation_list_head,
1107 rh->client->revocation_list_tail,
1108 rh);
655} 1109}
656 1110
657 1111
1112/**
1113 * Process ticket from database
1114 *
1115 * @param cls struct TicketIterationProcResult
1116 * @param ticket the ticket
1117 * @param attrs the attributes
1118 */
1119static void
1120ticket_reissue_proc (void *cls,
1121 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1122 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs);
1123
658static void 1124static void
659attribute_collect_finished_cb (void *cls) 1125revocation_reissue_tickets (struct TicketRevocationHandle *rh);
1126
1127
1128static void reissue_next (void *cls)
660{ 1129{
661 struct EgoEntry *ego_entry = cls; 1130 struct TicketRevocationHandle *rh = cls;
1131 revocation_reissue_tickets (rh);
1132}
662 1133
663 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1134
664 ">>> Updating Attributes finished\n"); 1135static void
665 ego_entry->attributes_dirty = GNUNET_NO; 1136reissue_ticket_cont (void *cls,
666 update_task = GNUNET_SCHEDULER_add_now (&update_identities, 1137 int32_t success,
667 ego_entry); 1138 const char *emsg)
1139{
1140 struct TicketRevocationHandle *rh = cls;
1141
1142 rh->ns_qe = NULL;
1143 if (GNUNET_SYSERR == success)
1144 {
1145 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
1146 "Unknown Error\n");
1147 send_revocation_finished (rh, GNUNET_SYSERR);
1148 cleanup_revoke_ticket_handle (rh);
1149 return;
1150 }
1151 rh->offset++;
1152 GNUNET_SCHEDULER_add_now (&reissue_next, rh);
668} 1153}
669 1154
670 1155
671/** 1156/**
1157 * Process ticket from database
672 * 1158 *
673 * Collect all ID_ATTR records for an identity and store them 1159 * @param cls struct TicketIterationProcResult
674 * 1160 * @param ticket the ticket
675 * @param cls the identity entry 1161 * @param attrs the attributes
676 * @param zone the identity
677 * @param lbl the name of the record
678 * @param rd_count number of records
679 * @param rd record data
680 *
681 */ 1162 */
682static void 1163static void
683attribute_collect (void *cls, 1164ticket_reissue_proc (void *cls,
684 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 1165 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
685 const char *lbl, 1166 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
686 unsigned int rd_count, 1167{
687 const struct GNUNET_GNSRECORD_Data *rd) 1168 struct TicketRevocationHandle *rh = cls;
688{ 1169 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
689 struct EgoEntry *ego_entry = cls; 1170 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le_rollover;
690 struct GNUNET_HashCode key; 1171 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
691 struct TokenAttr *attr; 1172 struct GNUNET_GNSRECORD_Data code_record[1];
692 struct TokenAttrValue *val; 1173 struct GNUNET_ABE_AbeKey *rp_key;
693 char *val_str; 1174 char *code_record_data;
694 int i; 1175 char **attr_arr;
695 1176 char *label;
696 if (0 == rd_count) 1177 char *policy;
1178 int attrs_len;
1179 uint32_t i;
1180 int reissue_ticket;
1181 size_t code_record_len;
1182
1183
1184 if (NULL == ticket)
697 { 1185 {
698 GNUNET_NAMESTORE_zone_iterator_next (ns_it); 1186 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1187 "Iteration done\n");
699 return; 1188 return;
700 } 1189 }
701 GNUNET_CRYPTO_hash (lbl, 1190
702 strlen (lbl), 1191 if (0 == memcmp (&ticket->audience,
703 &key); 1192 &rh->ticket.audience,
704 if (1 == rd_count) 1193 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
705 { 1194 {
706 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR) 1195 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
707 { 1196 "Do not reissue for this identity.!\n");
708 val_str = GNUNET_GNSRECORD_value_to_string (rd->record_type,
709 rd->data,
710 rd->data_size);
711 attr = GNUNET_malloc (sizeof (struct TokenAttr));
712 attr->name = GNUNET_strdup (lbl);
713 val = GNUNET_malloc (sizeof (struct TokenAttrValue));
714 val->value = val_str;
715 GNUNET_CONTAINER_DLL_insert (attr->val_head,
716 attr->val_tail,
717 val);
718 GNUNET_assert (GNUNET_OK ==
719 GNUNET_CONTAINER_multihashmap_put (ego_entry->attr_map,
720 &key,
721 attr,
722 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
723 }
724 1197
725 GNUNET_NAMESTORE_zone_iterator_next (ns_it); 1198 rh->offset++;
1199 GNUNET_SCHEDULER_add_now (&reissue_next, rh);
726 return; 1200 return;
727 } 1201 }
728 1202
729 attr = GNUNET_malloc (sizeof (struct TokenAttr)); 1203 /*
730 attr->name = GNUNET_strdup (lbl); 1204 * Check if any attribute of this ticket intersects with a rollover attribute
731 for (i = 0; i < rd_count; i++) 1205 */
1206 reissue_ticket = GNUNET_NO;
1207 for (le = attrs->list_head; NULL != le; le = le->next)
732 { 1208 {
733 if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR) 1209 for (le_rollover = rh->rvk_attrs->list_head;
1210 NULL != le_rollover;
1211 le_rollover = le_rollover->next)
734 { 1212 {
735 val_str = GNUNET_GNSRECORD_value_to_string (rd[i].record_type, 1213 if (0 == strcmp (le_rollover->claim->name,
736 rd[i].data, 1214 le->claim->name))
737 rd[i].data_size); 1215 {
738 val = GNUNET_malloc (sizeof (struct TokenAttrValue)); 1216 reissue_ticket = GNUNET_YES;
739 val->value = val_str; 1217 le->claim->version = le_rollover->claim->version;
740 GNUNET_CONTAINER_DLL_insert (attr->val_head, 1218 }
741 attr->val_tail,
742 val);
743 } 1219 }
744 } 1220 }
745 GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (ego_entry->attr_map,
746 &key,
747 attr,
748 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
749 GNUNET_NAMESTORE_zone_iterator_next (ns_it);
750}
751
752/**
753 *
754 * Update identity information for ego. If attribute map is
755 * dirty, first update the attributes.
756 *
757 * @param cls the ego to update
758 */
759static void
760update_identities(void *cls)
761{
762 struct EgoEntry *next_ego = cls;
763 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
764 1221
765 update_task = NULL; 1222 if (GNUNET_NO == reissue_ticket)
766 if (NULL == next_ego)
767 { 1223 {
768 if (min_rel_exp.rel_value_us < MIN_WAIT_TIME.rel_value_us)
769 min_rel_exp = MIN_WAIT_TIME;
770 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1224 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
771 ">>> Finished. Rescheduling in %"SCNu64"\n", 1225 "Skipping ticket.\n");
772 min_rel_exp.rel_value_us); 1226
773 ns_it = NULL; 1227 rh->offset++;
774 //finished -> reschedule 1228 GNUNET_SCHEDULER_add_now (&reissue_next, rh);
775 update_task = GNUNET_SCHEDULER_add_delayed (min_rel_exp, 1229
776 &update_identities, 1230
777 ego_head);
778 min_rel_exp.rel_value_us = 0;
779 return; 1231 return;
780 } 1232 }
781 priv_key = GNUNET_IDENTITY_ego_get_private_key (next_ego->ego);
782 if (GNUNET_YES == next_ego->attributes_dirty)
783 {
784 //Starting over. We must update the Attributes for they might have changed.
785 ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
786 priv_key,
787 &attribute_collect_error_cb,
788 next_ego,
789 &attribute_collect,
790 next_ego,
791 &attribute_collect_finished_cb,
792 next_ego);
793 1233
1234 //Create new ABE key for RP
1235 attrs_len = 0;
1236
1237 /* If this is the RP we want to revoke attributes of, the do so */
1238
1239 for (le = attrs->list_head; NULL != le; le = le->next)
1240 attrs_len++;
1241 attr_arr = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
1242 i = 0;
1243 for (le = attrs->list_head; NULL != le; le = le->next) {
1244 GNUNET_asprintf (&policy, "%s_%lu",
1245 le->claim->name,
1246 le->claim->version);
1247 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1248 "Recreating key with %s\n", policy);
1249 attr_arr[i] = policy;
1250 i++;
794 } 1251 }
795 else 1252 attr_arr[i] = NULL;
1253 rp_key = GNUNET_ABE_cpabe_create_key (rh->abe_key,
1254 attr_arr);
1255
1256 //TODO review this wireformat
1257 code_record_len = serialize_abe_keyinfo2 (ticket,
1258 attrs,
1259 rp_key,
1260 &ecdhe_privkey,
1261 &code_record_data);
1262 code_record[0].data = code_record_data;
1263 code_record[0].data_size = code_record_len;
1264 code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
1265 code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
1266 code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1267
1268 label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
1269 sizeof (uint64_t));
1270 //Publish record
1271 rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1272 &rh->identity,
1273 label,
1274 1,
1275 code_record,
1276 &reissue_ticket_cont,
1277 rh);
1278 //for (; i > 0; i--)
1279 // GNUNET_free (attr_arr[i-1]);
1280 GNUNET_free (ecdhe_privkey);
1281 GNUNET_free (label);
1282 GNUNET_free (attr_arr);
1283 GNUNET_free (code_record_data);
1284 GNUNET_ABE_cpabe_delete_key (rp_key, GNUNET_YES);
1285}
1286
1287
1288/* Prototype for below function */
1289static void
1290attr_reenc_cont (void *cls,
1291 int32_t success,
1292 const char *emsg);
1293
1294static void
1295revocation_reissue_tickets (struct TicketRevocationHandle *rh)
1296{
1297 int ret;
1298 /* Done, issue new keys */
1299 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1300 "Revocation Phase III: Reissuing Tickets\n");
1301 if (GNUNET_SYSERR == (ret = TKT_database->iterate_tickets (TKT_database->cls,
1302 &rh->ticket.identity,
1303 GNUNET_NO,
1304 rh->offset,
1305 &ticket_reissue_proc,
1306 rh)))
796 { 1307 {
797 //Ego will be dirty next time 1308 GNUNET_break (0);
798 next_ego->attributes_dirty = GNUNET_YES; 1309 }
799 ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle, 1310 if (GNUNET_NO == ret)
800 priv_key, 1311 {
801 &token_collect_error_cb, 1312 send_revocation_finished (rh, GNUNET_OK);
802 next_ego, 1313 cleanup_revoke_ticket_handle (rh);
803 &token_collect, 1314 return;
804 next_ego,
805 &token_collect_finished_cb,
806 next_ego);
807 } 1315 }
808} 1316}
809 1317
810
811/** 1318/**
812 * Function called initially to start update task 1319 * Revoke next attribte by reencryption with
1320 * new ABE master
813 */ 1321 */
814static void 1322static void
815init_cont () 1323reenc_next_attribute (struct TicketRevocationHandle *rh)
816{ 1324{
817 GNUNET_log (GNUNET_ERROR_TYPE_INFO, ">>> Starting Service\n"); 1325 struct GNUNET_GNSRECORD_Data rd[1];
818 //Initially iterate all itenties and refresh all tokens 1326 char* buf;
819 update_task = GNUNET_SCHEDULER_add_now (&update_identities, 1327 char* enc_buf;
820 ego_head); 1328 size_t enc_size;
1329 char* rd_buf;
1330 size_t buf_size;
1331 char* policy;
1332 uint32_t attr_ver;
1333
1334 if (NULL == rh->attrs->list_head)
1335 {
1336 revocation_reissue_tickets (rh);
1337 return;
1338 }
1339 buf_size = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (rh->attrs->list_head->claim);
1340 buf = GNUNET_malloc (buf_size);
1341 GNUNET_IDENTITY_ATTRIBUTE_serialize (rh->attrs->list_head->claim,
1342 buf);
1343 rh->attrs->list_head->claim->version++;
1344 GNUNET_asprintf (&policy, "%s_%lu",
1345 rh->attrs->list_head->claim->name,
1346 rh->attrs->list_head->claim->version);
1347 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1348 "Encrypting with policy %s\n", policy);
1349 /**
1350 * Encrypt the attribute value and store in namestore
1351 */
1352 enc_size = GNUNET_ABE_cpabe_encrypt (buf,
1353 buf_size,
1354 policy, //Policy
1355 rh->abe_key,
1356 (void**)&enc_buf);
1357 GNUNET_free (buf);
1358 GNUNET_free (policy);
1359 rd[0].data_size = enc_size + sizeof (uint32_t);
1360 rd_buf = GNUNET_malloc (rd[0].data_size);
1361 attr_ver = htonl (rh->attrs->list_head->claim->version);
1362 GNUNET_memcpy (rd_buf,
1363 &attr_ver,
1364 sizeof (uint32_t));
1365 GNUNET_memcpy (rd_buf+sizeof (uint32_t),
1366 enc_buf,
1367 enc_size);
1368 rd[0].data = rd_buf;
1369 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1370 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1371 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1372 rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1373 &rh->identity,
1374 rh->attrs->list_head->claim->name,
1375 1,
1376 rd,
1377 &attr_reenc_cont,
1378 rh);
1379 GNUNET_free (enc_buf);
1380 GNUNET_free (rd_buf);
821} 1381}
822 1382
823
824/** 1383/**
825 * Initial ego collection function. 1384 * Namestore callback after revoked attribute
826 * 1385 * is stored
827 * @param cls NULL
828 * @param ego ego
829 * @param ctx context
830 * @param identifier ego name
831 */ 1386 */
832static void 1387static void
833list_ego (void *cls, 1388attr_reenc_cont (void *cls,
834 struct GNUNET_IDENTITY_Ego *ego, 1389 int32_t success,
835 void **ctx, 1390 const char *emsg)
836 const char *identifier)
837{ 1391{
838 struct EgoEntry *new_entry; 1392 struct TicketRevocationHandle *rh = cls;
839 if ((NULL == ego) && (STATE_INIT == state)) 1393 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le;
1394
1395 if (GNUNET_SYSERR == success)
840 { 1396 {
841 state = STATE_POST_INIT; 1397 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
842 init_cont (); 1398 "Failed to reencrypt attribute %s\n",
1399 emsg);
1400 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
843 return; 1401 return;
844 } 1402 }
845 if (STATE_INIT == state) { 1403 if (NULL == rh->attrs->list_head)
846 new_entry = GNUNET_malloc (sizeof (struct EgoEntry)); 1404 {
847 new_entry->ego = ego; 1405 revocation_reissue_tickets (rh);
848 new_entry->attr_map = GNUNET_CONTAINER_multihashmap_create (5, 1406 return;
849 GNUNET_NO);
850 new_entry->attributes_dirty = GNUNET_YES;
851 GNUNET_CONTAINER_DLL_insert_tail(ego_head, ego_tail, new_entry);
852 } 1407 }
1408 le = rh->attrs->list_head;
1409 GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head,
1410 rh->attrs->list_tail,
1411 le);
1412 GNUNET_assert (NULL != rh->rvk_attrs);
1413 GNUNET_CONTAINER_DLL_insert (rh->rvk_attrs->list_head,
1414 rh->rvk_attrs->list_tail,
1415 le);
1416
1417
1418 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1419 "Re-encrypting next attribute\n");
1420 reenc_next_attribute (rh);
853} 1421}
854 1422
855/** 1423
856 * Cleanup task
857 */
858static void 1424static void
859cleanup() 1425process_attributes_to_update (void *cls,
1426 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1427 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
860{ 1428{
861 struct EgoEntry *ego_entry; 1429 struct TicketRevocationHandle *rh = cls;
862 struct EgoEntry *ego_tmp;
863 1430
1431 rh->attrs = GNUNET_IDENTITY_ATTRIBUTE_list_dup (attrs);
864 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1432 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
865 "Cleaning up\n"); 1433 "Revocation Phase I: Collecting attributes\n");
866 if (NULL != stats) 1434 /* Reencrypt all attributes with new key */
1435 if (NULL == rh->attrs->list_head)
867 { 1436 {
868 GNUNET_STATISTICS_destroy (stats, GNUNET_NO); 1437 /* No attributes to reencrypt */
869 stats = NULL; 1438 send_revocation_finished (rh, GNUNET_OK);
1439 cleanup_revoke_ticket_handle (rh);
1440 return;
1441 } else {
1442 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1443 "Revocation Phase II: Re-encrypting attributes\n");
1444 reenc_next_attribute (rh);
870 } 1445 }
871 1446
872 if (NULL != timeout_task) 1447}
873 GNUNET_SCHEDULER_cancel (timeout_task);
874 if (NULL != update_task)
875 GNUNET_SCHEDULER_cancel (update_task);
876 if (NULL != identity_handle)
877 GNUNET_IDENTITY_disconnect (identity_handle);
878 if (NULL != gns_handle)
879 GNUNET_GNS_disconnect (gns_handle);
880 if (NULL != ns_it)
881 GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
882 if (NULL != ns_qe)
883 GNUNET_NAMESTORE_cancel (ns_qe);
884 if (NULL != ns_handle)
885 GNUNET_NAMESTORE_disconnect (ns_handle);
886 if (NULL != token)
887 GNUNET_free (token);
888 if (NULL != label)
889 GNUNET_free (label);
890 1448
891 for (ego_entry = ego_head;
892 NULL != ego_entry;)
893 {
894 ego_tmp = ego_entry;
895 if (0 != GNUNET_CONTAINER_multihashmap_size (ego_tmp->attr_map))
896 {
897 GNUNET_CONTAINER_multihashmap_iterate (ego_tmp->attr_map,
898 &clear_ego_attrs,
899 ego_tmp);
900 1449
901 } 1450
902 GNUNET_CONTAINER_multihashmap_destroy (ego_tmp->attr_map); 1451static void
903 ego_entry = ego_entry->next; 1452get_ticket_after_abe_bootstrap (void *cls,
904 GNUNET_free (ego_tmp); 1453 struct GNUNET_ABE_AbeMasterKey *abe_key)
1454{
1455 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1456 "Finished ABE bootstrap\n");
1457 struct TicketRevocationHandle *rh = cls;
1458 rh->abe_key = abe_key;
1459 TKT_database->get_ticket_attributes (TKT_database->cls,
1460 &rh->ticket,
1461 &process_attributes_to_update,
1462 rh);
1463}
1464
1465static int
1466check_revoke_ticket_message(void *cls,
1467 const struct RevokeTicketMessage *im)
1468{
1469 uint16_t size;
1470
1471 size = ntohs (im->header.size);
1472 if (size <= sizeof (struct RevokeTicketMessage))
1473 {
1474 GNUNET_break (0);
1475 return GNUNET_SYSERR;
905 } 1476 }
1477 return GNUNET_OK;
906} 1478}
907 1479
908/**
909 * Shutdown task
910 *
911 * @param cls NULL
912 * @param tc task context
913 */
914static void 1480static void
915do_shutdown (void *cls) 1481handle_revoke_ticket_message (void *cls,
1482 const struct RevokeTicketMessage *rm)
916{ 1483{
917 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1484 struct TicketRevocationHandle *rh;
918 "Shutting down...\n"); 1485 struct IdpClient *idp = cls;
919 cleanup(); 1486 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
1487
1488 rh = GNUNET_new (struct TicketRevocationHandle);
1489 ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket*)&rm[1];
1490 rh->rvk_attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
1491 rh->ticket = *ticket;
1492 rh->r_id = ntohl (rm->id);
1493 rh->client = idp;
1494 rh->identity = rm->identity;
1495 GNUNET_CRYPTO_ecdsa_key_get_public (&rh->identity,
1496 &rh->ticket.identity);
1497 GNUNET_CONTAINER_DLL_insert (idp->revocation_list_head,
1498 idp->revocation_list_tail,
1499 rh);
1500 bootstrap_abe (&rh->identity, &get_ticket_after_abe_bootstrap, rh, GNUNET_NO);
1501 GNUNET_SERVICE_client_continue (idp->client);
1502
920} 1503}
921 1504
922 1505
923static struct GNUNET_MQ_Envelope* 1506static void
924create_exchange_result_message (const char* token, 1507cleanup_consume_ticket_handle (struct ConsumeTicketHandle *handle)
925 const char* label,
926 uint64_t ticket_nonce,
927 uint64_t id)
928{ 1508{
929 struct GNUNET_MQ_Envelope *env; 1509 if (NULL != handle->key)
930 struct ExchangeResultMessage *erm; 1510 GNUNET_ABE_cpabe_delete_key (handle->key,
931 uint16_t token_len = strlen (token) + 1; 1511 GNUNET_YES);
932 1512 if (NULL != handle->attrs)
933 env = GNUNET_MQ_msg_extra (erm, 1513 GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->attrs);
934 token_len, 1514 GNUNET_free (handle);
935 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT);
936 erm->ticket_nonce = htonl (ticket_nonce);
937 erm->id = id;
938 GNUNET_memcpy (&erm[1], token, token_len);
939 return env;
940} 1515}
941 1516
942 1517
943static struct GNUNET_MQ_Envelope* 1518
944create_issue_result_message (const char* label, 1519static int
945 const char* ticket, 1520check_consume_ticket_message(void *cls,
946 const char* token, 1521 const struct ConsumeTicketMessage *cm)
947 uint64_t id)
948{ 1522{
949 struct GNUNET_MQ_Envelope *env; 1523 uint16_t size;
950 struct IssueResultMessage *irm;
951 char *tmp_str;
952 size_t len;
953 1524
954 GNUNET_asprintf (&tmp_str, "%s,%s,%s", label, ticket, token); 1525 size = ntohs (cm->header.size);
955 len = strlen (tmp_str) + 1; 1526 if (size <= sizeof (struct ConsumeTicketMessage))
956 env = GNUNET_MQ_msg_extra (irm, 1527 {
957 len, 1528 GNUNET_break (0);
958 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT); 1529 return GNUNET_SYSERR;
959 irm->id = id; 1530 }
960 GNUNET_memcpy (&irm[1], tmp_str, strlen (tmp_str) + 1); 1531 return GNUNET_OK;
961 GNUNET_free (tmp_str);
962 return env;
963} 1532}
964 1533
965static void 1534static void
966cleanup_issue_handle (struct IssueHandle *handle) 1535process_parallel_lookup2 (void *cls, uint32_t rd_count,
967{ 1536 const struct GNUNET_GNSRECORD_Data *rd)
968 if (NULL != handle->attr_map) 1537{
969 GNUNET_CONTAINER_multihashmap_destroy (handle->attr_map); 1538 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
970 if (NULL != handle->scopes) 1539 "Parallel lookup finished (count=%u)\n", rd_count);
971 GNUNET_free (handle->scopes); 1540 struct ParallelLookup *parallel_lookup = cls;
972 if (NULL != handle->token) 1541 struct ConsumeTicketHandle *handle = parallel_lookup->handle;
973 token_destroy (handle->token); 1542 struct ConsumeTicketResultMessage *crm;
974 if (NULL != handle->ticket) 1543 struct GNUNET_MQ_Envelope *env;
975 ticket_destroy (handle->ticket); 1544 struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *attr_le;
976 if (NULL != handle->label) 1545 struct GNUNET_TIME_Absolute decrypt_duration;
977 GNUNET_free (handle->label); 1546 char *data;
978 GNUNET_free (handle); 1547 char *data_tmp;
1548 ssize_t attr_len;
1549 size_t attrs_len;
1550
1551 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1552 handle->parallel_lookups_tail,
1553 parallel_lookup);
1554 GNUNET_free (parallel_lookup->label);
1555
1556 GNUNET_STATISTICS_update (stats_handle,
1557 "attribute_lookup_time_total",
1558 GNUNET_TIME_absolute_get_duration (parallel_lookup->lookup_start_time).rel_value_us,
1559 GNUNET_YES);
1560 GNUNET_STATISTICS_update (stats_handle,
1561 "attribute_lookups_count",
1562 1,
1563 GNUNET_YES);
1564
1565
1566 GNUNET_free (parallel_lookup);
1567 if (1 != rd_count)
1568 GNUNET_break(0);//TODO
1569 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1570 {
1571 decrypt_duration = GNUNET_TIME_absolute_get ();
1572 attr_len = GNUNET_ABE_cpabe_decrypt (rd->data + sizeof (uint32_t),
1573 rd->data_size - sizeof (uint32_t),
1574 handle->key,
1575 (void**)&data);
1576 if (GNUNET_SYSERR != attr_len)
1577 {
1578 GNUNET_STATISTICS_update (stats_handle,
1579 "abe_decrypt_time_total",
1580 GNUNET_TIME_absolute_get_duration (decrypt_duration).rel_value_us,
1581 GNUNET_YES);
1582 GNUNET_STATISTICS_update (stats_handle,
1583 "abe_decrypt_count",
1584 1,
1585 GNUNET_YES);
1586
1587 attr_le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry);
1588 attr_le->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize (data,
1589 attr_len);
1590 attr_le->claim->version = ntohl(*(uint32_t*)rd->data);
1591 GNUNET_CONTAINER_DLL_insert (handle->attrs->list_head,
1592 handle->attrs->list_tail,
1593 attr_le);
1594 GNUNET_free (data);
1595 }
1596 }
1597 if (NULL != handle->parallel_lookups_head)
1598 return; //Wait for more
1599 /* Else we are done */
1600
1601 /* Store ticket in DB */
1602 if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls,
1603 &handle->ticket,
1604 handle->attrs))
1605 {
1606 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1607 "Unable to store ticket after consume\n");
1608 GNUNET_break (0);
1609 }
1610
1611 GNUNET_SCHEDULER_cancel (handle->kill_task);
1612 attrs_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (handle->attrs);
1613 env = GNUNET_MQ_msg_extra (crm,
1614 attrs_len,
1615 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT);
1616 crm->id = htonl (handle->r_id);
1617 crm->attrs_len = htons (attrs_len);
1618 crm->identity = handle->ticket.identity;
1619 data_tmp = (char *) &crm[1];
1620 GNUNET_IDENTITY_ATTRIBUTE_list_serialize (handle->attrs,
1621 data_tmp);
1622 GNUNET_MQ_send (handle->client->mq, env);
1623 cleanup_consume_ticket_handle (handle);
979} 1624}
980 1625
981static void 1626void
982store_token_issue_cont (void *cls, 1627abort_parallel_lookups2 (void *cls)
983 int32_t success,
984 const char *emsg)
985{ 1628{
986 struct IssueHandle *handle = cls; 1629 struct ConsumeTicketHandle *handle = cls;
1630 struct ParallelLookup *lu;
1631 struct ParallelLookup *tmp;
1632 struct AttributeResultMessage *arm;
987 struct GNUNET_MQ_Envelope *env; 1633 struct GNUNET_MQ_Envelope *env;
988 char *ticket_str;
989 char *token_str;
990 1634
991 handle->ns_qe = NULL; 1635 for (lu = handle->parallel_lookups_head;
992 if (GNUNET_SYSERR == success) 1636 NULL != lu;) {
1637 GNUNET_GNS_lookup_cancel (lu->lookup_request);
1638 GNUNET_free (lu->label);
1639 tmp = lu->next;
1640 GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1641 handle->parallel_lookups_tail,
1642 lu);
1643 GNUNET_free (lu);
1644 lu = tmp;
1645 }
1646 env = GNUNET_MQ_msg (arm,
1647 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1648 arm->id = htonl (handle->r_id);
1649 arm->attr_len = htons (0);
1650 GNUNET_MQ_send (handle->client->mq, env);
1651
1652}
1653
1654
1655static void
1656process_consume_abe_key (void *cls, uint32_t rd_count,
1657 const struct GNUNET_GNSRECORD_Data *rd)
1658{
1659 struct ConsumeTicketHandle *handle = cls;
1660 struct GNUNET_HashCode new_key_hash;
1661 struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
1662 struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
1663 struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key;
1664 struct ParallelLookup *parallel_lookup;
1665 size_t size;
1666 char *buf;
1667 char *scope;
1668 char *lookup_query;
1669
1670 handle->lookup_request = NULL;
1671 if (1 != rd_count)
993 { 1672 {
994 cleanup_issue_handle (handle); 1673 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
995 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", 1674 "Number of keys %d != 1.",
996 "Unknown Error\n"); 1675 rd_count);
1676 cleanup_consume_ticket_handle (handle);
997 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); 1677 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
998 return; 1678 return;
999 } 1679 }
1000 if (GNUNET_OK != ticket_serialize (handle->ticket, 1680
1001 &handle->iss_key, 1681 //Decrypt
1002 &ticket_str)) 1682 ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data;
1683
1684 buf = GNUNET_malloc (rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1685
1686 //Calculate symmetric key from ecdh parameters
1687 GNUNET_assert (GNUNET_OK ==
1688 GNUNET_CRYPTO_ecdsa_ecdh (&handle->identity,
1689 ecdh_key,
1690 &new_key_hash));
1691 create_sym_key_from_ecdh (&new_key_hash,
1692 &enc_key,
1693 &enc_iv);
1694 size = GNUNET_CRYPTO_symmetric_decrypt (rd->data + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1695 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1696 &enc_key,
1697 &enc_iv,
1698 buf);
1699
1700 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1701 "Decrypted bytes: %zd Expected bytes: %zd\n",
1702 size, rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1703 GNUNET_STATISTICS_update (stats_handle,
1704 "abe_key_lookup_time_total",
1705 GNUNET_TIME_absolute_get_duration (handle->lookup_start_time).rel_value_us,
1706 GNUNET_YES);
1707 GNUNET_STATISTICS_update (stats_handle,
1708 "abe_key_lookups_count",
1709 1,
1710 GNUNET_YES);
1711 scopes = GNUNET_strdup (buf);
1712 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1713 "Scopes %s\n", scopes);
1714 handle->key = GNUNET_ABE_cpabe_deserialize_key ((void*)(buf + strlen (scopes) + 1),
1715 rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)
1716 - strlen (scopes) - 1);
1717
1718 for (scope = strtok (scopes, ","); NULL != scope; scope = strtok (NULL, ","))
1003 { 1719 {
1004 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", 1720 GNUNET_asprintf (&lookup_query,
1005 "Error serializing ticket\n"); 1721 "%s.gnu",
1006 cleanup_issue_handle (handle); 1722 scope);
1007 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); 1723 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1008 return; 1724 "Looking up %s\n", lookup_query);
1725 parallel_lookup = GNUNET_new (struct ParallelLookup);
1726 parallel_lookup->handle = handle;
1727 parallel_lookup->label = GNUNET_strdup (scope);
1728 parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get();
1729 parallel_lookup->lookup_request
1730 = GNUNET_GNS_lookup (gns_handle,
1731 lookup_query,
1732 &handle->ticket.identity,
1733 GNUNET_GNSRECORD_TYPE_ID_ATTR,
1734 GNUNET_GNS_LO_DEFAULT,
1735 &process_parallel_lookup2,
1736 parallel_lookup);
1737 GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head,
1738 handle->parallel_lookups_tail,
1739 parallel_lookup);
1740 GNUNET_free (lookup_query);
1009 } 1741 }
1010 if (GNUNET_OK != token_to_string (handle->token, 1742 GNUNET_free (scopes);
1011 &handle->iss_key, 1743 GNUNET_free (buf);
1012 &token_str)) 1744 handle->kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3),
1745 &abort_parallel_lookups2,
1746 handle);
1747}
1748
1749
1750static void
1751handle_consume_ticket_message (void *cls,
1752 const struct ConsumeTicketMessage *cm)
1753{
1754 struct ConsumeTicketHandle *ch;
1755 struct IdpClient *idp = cls;
1756 char* lookup_query;
1757 char* rnd_label;
1758
1759 ch = GNUNET_new (struct ConsumeTicketHandle);
1760 ch->r_id = ntohl (cm->id);
1761 ch->client = idp;
1762 ch->identity = cm->identity;
1763 ch->attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList);
1764 GNUNET_CRYPTO_ecdsa_key_get_public (&ch->identity,
1765 &ch->identity_pub);
1766 ch->ticket = *((struct GNUNET_IDENTITY_PROVIDER_Ticket*)&cm[1]);
1767 rnd_label = GNUNET_STRINGS_data_to_string_alloc (&ch->ticket.rnd,
1768 sizeof (uint64_t));
1769 GNUNET_asprintf (&lookup_query,
1770 "%s.gnu",
1771 rnd_label);
1772 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1773 "Looking for ABE key under %s\n", lookup_query);
1774 ch->lookup_start_time = GNUNET_TIME_absolute_get ();
1775 ch->lookup_request
1776 = GNUNET_GNS_lookup (gns_handle,
1777 lookup_query,
1778 &ch->ticket.identity,
1779 GNUNET_GNSRECORD_TYPE_ABE_KEY,
1780 GNUNET_GNS_LO_DEFAULT,
1781 &process_consume_abe_key,
1782 ch);
1783 GNUNET_free (rnd_label);
1784 GNUNET_free (lookup_query);
1785 GNUNET_SERVICE_client_continue (idp->client);
1786}
1787
1788static void
1789cleanup_as_handle (struct AttributeStoreHandle *handle)
1790{
1791 if (NULL != handle->claim)
1792 GNUNET_free (handle->claim);
1793 if (NULL != handle->abe_key)
1794 GNUNET_ABE_cpabe_delete_master_key (handle->abe_key);
1795 GNUNET_free (handle);
1796}
1797
1798static void
1799attr_store_cont (void *cls,
1800 int32_t success,
1801 const char *emsg)
1802{
1803 struct AttributeStoreHandle *as_handle = cls;
1804 struct GNUNET_MQ_Envelope *env;
1805 struct AttributeStoreResultMessage *acr_msg;
1806
1807 if (GNUNET_SYSERR == success)
1013 { 1808 {
1014 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", 1809 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1015 "Error serializing token\n"); 1810 "Failed to store attribute %s\n",
1016 GNUNET_free (ticket_str); 1811 emsg);
1017 cleanup_issue_handle (handle); 1812 cleanup_as_handle (as_handle);
1018 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); 1813 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1019 return; 1814 return;
1020 } 1815 }
1021 env = create_issue_result_message (handle->label, 1816
1022 ticket_str, 1817 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1023 token_str, 1818 "Sending ATTRIBUTE_STORE_RESPONSE message\n");
1024 handle->r_id); 1819 env = GNUNET_MQ_msg (acr_msg,
1025 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(handle->client), 1820 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE);
1821 acr_msg->id = htonl (as_handle->r_id);
1822 acr_msg->op_result = htonl (GNUNET_OK);
1823 GNUNET_MQ_send (as_handle->client->mq,
1026 env); 1824 env);
1027 cleanup_issue_handle (handle); 1825 cleanup_as_handle (as_handle);
1028 GNUNET_free (ticket_str);
1029 GNUNET_free (token_str);
1030} 1826}
1031 1827
1032
1033/**
1034 * Build a token and store it
1035 *
1036 * @param cls the IssueHandle
1037 */
1038static void 1828static void
1039sign_and_return_token (void *cls) 1829attr_store_task (void *cls)
1040{ 1830{
1041 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; 1831 struct AttributeStoreHandle *as_handle = cls;
1042 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey; 1832 struct GNUNET_GNSRECORD_Data rd[1];
1043 struct IssueHandle *handle = cls; 1833 char* buf;
1044 struct GNUNET_GNSRECORD_Data token_record[2]; 1834 char* policy;
1045 char *nonce_str; 1835 char* enc_buf;
1046 char *enc_token_str; 1836 char* rd_buf;
1047 char *token_metadata; 1837 size_t enc_size;
1048 char* write_ptr; 1838 size_t buf_size;
1049 uint64_t time; 1839 uint32_t attr_ver;
1050 uint64_t exp_time; 1840
1051 size_t token_metadata_len; 1841 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1052 1842 "Storing attribute\n");
1053 //Remote nonce 1843 buf_size = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (as_handle->claim);
1054 nonce_str = NULL; 1844 buf = GNUNET_malloc (buf_size);
1055 GNUNET_asprintf (&nonce_str, "%lu", handle->nonce); 1845
1056 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request nonce: %s\n", nonce_str); 1846 GNUNET_IDENTITY_ATTRIBUTE_serialize (as_handle->claim,
1057 1847 buf);
1058 GNUNET_CRYPTO_ecdsa_key_get_public (&handle->iss_key, 1848
1059 &pub_key); 1849 GNUNET_asprintf (&policy,
1060 handle->ticket = ticket_create (handle->nonce, 1850 "%s_%lu",
1061 &pub_key, 1851 as_handle->claim->name,
1062 handle->label, 1852 as_handle->claim->version);
1063 &handle->aud_key); 1853 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1064 1854 "Encrypting with policy %s\n", policy);
1065 time = GNUNET_TIME_absolute_get().abs_value_us; 1855 /**
1066 exp_time = time + token_expiration_interval.rel_value_us; 1856 * Encrypt the attribute value and store in namestore
1067 1857 */
1068 token_add_attr_int (handle->token, "nbf", time); 1858 enc_size = GNUNET_ABE_cpabe_encrypt (buf,
1069 token_add_attr_int (handle->token, "iat", time); 1859 buf_size,
1070 token_add_attr_int (handle->token, "exp", exp_time); 1860 policy, //Policy
1071 token_add_attr (handle->token, "nonce", nonce_str); 1861 as_handle->abe_key,
1072 1862 (void**)&enc_buf);
1073 //Token in a serialized encrypted format 1863 GNUNET_free (buf);
1074 GNUNET_assert (token_serialize (handle->token, 1864 GNUNET_free (policy);
1075 &handle->iss_key, 1865 rd[0].data_size = enc_size + sizeof (uint32_t);
1076 &ecdhe_privkey, 1866 rd_buf = GNUNET_malloc (rd[0].data_size);
1077 &enc_token_str)); 1867 attr_ver = htonl (as_handle->claim->version);
1078 1868 GNUNET_memcpy (rd_buf,
1079 //Token record E,E_K (Token) 1869 &attr_ver,
1080 token_record[0].data = enc_token_str; 1870 sizeof (uint32_t));
1081 token_record[0].data_size = strlen (enc_token_str) + 1; 1871 GNUNET_memcpy (rd_buf+sizeof (uint32_t),
1082 token_record[0].expiration_time = exp_time; 1872 enc_buf,
1083 token_record[0].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN; 1873 enc_size);
1084 token_record[0].flags = GNUNET_GNSRECORD_RF_NONE; 1874 rd[0].data = rd_buf;
1085 1875 rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1086 1876 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1087 token_metadata_len = sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey) 1877 rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1088 + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) 1878 as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1089 + strlen (handle->scopes) + 1; //With 0-Terminator 1879 &as_handle->identity,
1090 token_metadata = GNUNET_malloc (token_metadata_len); 1880 as_handle->claim->name,
1091 write_ptr = token_metadata; 1881 1,
1092 GNUNET_memcpy (token_metadata, ecdhe_privkey, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)); 1882 rd,
1093 write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey); 1883 &attr_store_cont,
1094 GNUNET_memcpy (write_ptr, &handle->aud_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); 1884 as_handle);
1095 write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); 1885 GNUNET_free (enc_buf);
1096 GNUNET_memcpy (write_ptr, handle->scopes, strlen (handle->scopes) + 1); //with 0-Terminator; 1886 GNUNET_free (rd_buf);
1097
1098 token_record[1].data = token_metadata;
1099 token_record[1].data_size = token_metadata_len;
1100 token_record[1].expiration_time = exp_time;
1101 token_record[1].record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA;
1102 token_record[1].flags = GNUNET_GNSRECORD_RF_PRIVATE;
1103
1104 //Persist token
1105 handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1106 &handle->iss_key,
1107 handle->label,
1108 2,
1109 token_record,
1110 &store_token_issue_cont,
1111 handle);
1112 GNUNET_free (ecdhe_privkey);
1113 GNUNET_free (nonce_str);
1114 GNUNET_free (enc_token_str);
1115 GNUNET_free (token_metadata);
1116} 1887}
1117 1888
1118 1889
1119static void 1890static void
1120attr_collect_error (void *cls) 1891store_after_abe_bootstrap (void *cls,
1892 struct GNUNET_ABE_AbeMasterKey *abe_key)
1121{ 1893{
1122 struct IssueHandle *handle = cls; 1894 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1895 "Finished ABE bootstrap\n");
1896 struct AttributeStoreHandle *ash = cls;
1897 ash->abe_key = abe_key;
1898 GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1899}
1123 1900
1124 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Adding attribute Error!\n"); 1901static int
1125 handle->ns_it = NULL; 1902check_attribute_store_message(void *cls,
1126 GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle); 1903 const struct AttributeStoreMessage *sam)
1904{
1905 uint16_t size;
1906
1907 size = ntohs (sam->header.size);
1908 if (size <= sizeof (struct AttributeStoreMessage))
1909 {
1910 GNUNET_break (0);
1911 return GNUNET_SYSERR;
1912 }
1913 return GNUNET_OK;
1127} 1914}
1128 1915
1129 1916
1130static void 1917static void
1131attr_collect_finished (void *cls) 1918handle_attribute_store_message (void *cls,
1919 const struct AttributeStoreMessage *sam)
1132{ 1920{
1133 struct IssueHandle *handle = cls; 1921 struct AttributeStoreHandle *as_handle;
1922 struct IdpClient *idp = cls;
1923 size_t data_len;
1924 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1925 "Received ATTRIBUTE_STORE message\n");
1926
1927 data_len = ntohs (sam->attr_len);
1928
1929 as_handle = GNUNET_new (struct AttributeStoreHandle);
1930 as_handle->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize ((char*)&sam[1],
1931 data_len);
1932
1933 as_handle->r_id = ntohl (sam->id);
1934 as_handle->identity = sam->identity;
1935 GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity,
1936 &as_handle->identity_pkey);
1134 1937
1135 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute END: \n"); 1938 GNUNET_SERVICE_client_continue (idp->client);
1136 handle->ns_it = NULL; 1939 as_handle->client = idp;
1137 GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle); 1940 bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle, GNUNET_NO);
1138} 1941}
1139 1942
1943static void
1944cleanup_iter_handle (struct AttributeIterator *ai)
1945{
1946 if (NULL != ai->abe_key)
1947 GNUNET_ABE_cpabe_delete_master_key (ai->abe_key);
1948 GNUNET_CONTAINER_DLL_remove (ai->client->op_head,
1949 ai->client->op_tail,
1950 ai);
1951 GNUNET_free (ai);
1952}
1953
1954static void
1955attr_iter_error (void *cls)
1956{
1957 struct AttributeIterator *ai = cls;
1958 //TODO
1959 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1960 "Failed to iterate over attributes\n");
1961 cleanup_iter_handle (ai);
1962 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1963}
1964
1965static void
1966attr_iter_finished (void *cls)
1967{
1968 struct AttributeIterator *ai = cls;
1969 struct GNUNET_MQ_Envelope *env;
1970 struct AttributeResultMessage *arm;
1971
1972 env = GNUNET_MQ_msg (arm,
1973 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1974 arm->id = htonl (ai->request_id);
1975 arm->attr_len = htons (0);
1976 GNUNET_MQ_send (ai->client->mq, env);
1977 cleanup_iter_handle (ai);
1978}
1140 1979
1141/**
1142 * Collect attributes for token
1143 */
1144static void 1980static void
1145attr_collect (void *cls, 1981attr_iter_cb (void *cls,
1146 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 1982 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1147 const char *label, 1983 const char *label,
1148 unsigned int rd_count, 1984 unsigned int rd_count,
1149 const struct GNUNET_GNSRECORD_Data *rd) 1985 const struct GNUNET_GNSRECORD_Data *rd)
1150{ 1986{
1151 struct IssueHandle *handle = cls; 1987 struct AttributeIterator *ai = cls;
1152 int i; 1988 struct AttributeResultMessage *arm;
1153 char* data; 1989 struct GNUNET_ABE_AbeKey *key;
1154 struct GNUNET_HashCode key; 1990 struct GNUNET_MQ_Envelope *env;
1155 1991 ssize_t msg_extra_len;
1156 GNUNET_CRYPTO_hash (label, 1992 char* attr_ser;
1157 strlen (label), 1993 char* attrs[2];
1158 &key); 1994 char* data_tmp;
1159 1995 char* policy;
1160 if (0 == rd_count || 1996 uint32_t attr_ver;
1161 ( (NULL != handle->attr_map) && 1997
1162 (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->attr_map, 1998 if (rd_count != 1)
1163 &key))
1164 )
1165 )
1166 { 1999 {
1167 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); 2000 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
1168 return; 2001 return;
1169 } 2002 }
1170 2003
1171 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", label); 2004 if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) {
1172 2005 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
1173 if (1 == rd_count)
1174 {
1175 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1176 {
1177 data = GNUNET_GNSRECORD_value_to_string (rd->record_type,
1178 rd->data,
1179 rd->data_size);
1180 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
1181 token_add_attr (handle->token,
1182 label,
1183 data);
1184 GNUNET_free (data);
1185 }
1186 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
1187 return; 2006 return;
1188 } 2007 }
2008 attr_ver = ntohl(*((uint32_t*)rd->data));
2009 GNUNET_asprintf (&policy, "%s_%lu",
2010 label, attr_ver);
2011 attrs[0] = policy;
2012 attrs[1] = 0;
2013 key = GNUNET_ABE_cpabe_create_key (ai->abe_key,
2014 attrs);
2015 msg_extra_len = GNUNET_ABE_cpabe_decrypt (rd->data+sizeof (uint32_t),
2016 rd->data_size-sizeof (uint32_t),
2017 key,
2018 (void**)&attr_ser);
2019
2020 GNUNET_ABE_cpabe_delete_key (key,
2021 GNUNET_YES);
2022 //GNUNET_free (policy);
2023 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2024 "Found attribute: %s\n", label);
2025 env = GNUNET_MQ_msg_extra (arm,
2026 msg_extra_len,
2027 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
2028 arm->id = htonl (ai->request_id);
2029 arm->attr_len = htons (msg_extra_len);
2030 GNUNET_CRYPTO_ecdsa_key_get_public (zone,
2031 &arm->identity);
2032 data_tmp = (char *) &arm[1];
2033 GNUNET_memcpy (data_tmp,
2034 attr_ser,
2035 msg_extra_len);
2036 GNUNET_MQ_send (ai->client->mq, env);
2037 GNUNET_free (attr_ser);
2038 GNUNET_ABE_cpabe_delete_master_key (ai->abe_key);
2039 ai->abe_key = NULL;
2040}
1189 2041
1190 i = 0;
1191 for (; i < rd_count; i++)
1192 {
1193 if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1194 {
1195 data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
1196 rd[i].data,
1197 rd[i].data_size);
1198 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
1199 token_add_attr (handle->token, label, data);
1200 GNUNET_free (data);
1201 }
1202 }
1203 2042
1204 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); 2043void
2044iterate_after_abe_bootstrap (void *cls,
2045 struct GNUNET_ABE_AbeMasterKey *abe_key)
2046{
2047 struct AttributeIterator *ai = cls;
2048 ai->abe_key = abe_key;
2049 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
2050 &ai->identity,
2051 &attr_iter_error,
2052 ai,
2053 &attr_iter_cb,
2054 ai,
2055 &attr_iter_finished,
2056 ai);
1205} 2057}
1206 2058
2059void
2060iterate_next_after_abe_bootstrap (void *cls,
2061 struct GNUNET_ABE_AbeMasterKey *abe_key)
2062{
2063 struct AttributeIterator *ai = cls;
2064 ai->abe_key = abe_key;
2065 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
2066}
2067
2068
2069
1207static void 2070static void
1208cleanup_exchange_handle (struct ExchangeHandle *handle) 2071handle_iteration_start (void *cls,
2072 const struct AttributeIterationStartMessage *ais_msg)
1209{ 2073{
1210 if (NULL != handle->ticket) 2074 struct IdpClient *idp = cls;
1211 ticket_destroy (handle->ticket); 2075 struct AttributeIterator *ai;
1212 if (NULL != handle->token) 2076
1213 token_destroy (handle->token); 2077 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1214 GNUNET_free (handle); 2078 "Received ATTRIBUTE_ITERATION_START message\n");
2079 ai = GNUNET_new (struct AttributeIterator);
2080 ai->request_id = ntohl (ais_msg->id);
2081 ai->client = idp;
2082 ai->identity = ais_msg->identity;
2083
2084 GNUNET_CONTAINER_DLL_insert (idp->op_head,
2085 idp->op_tail,
2086 ai);
2087 bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai, GNUNET_NO);
2088 GNUNET_SERVICE_client_continue (idp->client);
1215} 2089}
1216 2090
2091
1217static void 2092static void
1218process_lookup_result (void *cls, uint32_t rd_count, 2093handle_iteration_stop (void *cls,
1219 const struct GNUNET_GNSRECORD_Data *rd) 2094 const struct AttributeIterationStopMessage *ais_msg)
1220{ 2095{
1221 struct ExchangeHandle *handle = cls; 2096 struct IdpClient *idp = cls;
1222 struct GNUNET_MQ_Envelope *env; 2097 struct AttributeIterator *ai;
1223 char* token_str; 2098 uint32_t rid;
1224 char* record_str;
1225 2099
1226 handle->lookup_request = NULL; 2100 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1227 if (2 != rd_count) 2101 "Received `%s' message\n",
2102 "ATTRIBUTE_ITERATION_STOP");
2103 rid = ntohl (ais_msg->id);
2104 for (ai = idp->op_head; NULL != ai; ai = ai->next)
2105 if (ai->request_id == rid)
2106 break;
2107 if (NULL == ai)
1228 { 2108 {
1229 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2109 GNUNET_break (0);
1230 "Number of tokens %d != 2.", 2110 GNUNET_SERVICE_client_drop (idp->client);
1231 rd_count);
1232 cleanup_exchange_handle (handle);
1233 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1234 return; 2111 return;
1235 } 2112 }
1236 2113 GNUNET_CONTAINER_DLL_remove (idp->op_head,
1237 record_str = 2114 idp->op_tail,
1238 GNUNET_GNSRECORD_value_to_string (GNUNET_GNSRECORD_TYPE_ID_TOKEN, 2115 ai);
1239 rd->data, 2116 GNUNET_free (ai);
1240 rd->data_size); 2117 GNUNET_SERVICE_client_continue (idp->client);
1241
1242 //Decrypt and parse
1243 GNUNET_assert (GNUNET_OK == token_parse (record_str,
1244 &handle->aud_privkey,
1245 &handle->token));
1246
1247 //Readable
1248 GNUNET_assert (GNUNET_OK == token_to_string (handle->token,
1249 &handle->aud_privkey,
1250 &token_str));
1251
1252 env = create_exchange_result_message (token_str,
1253 handle->label,
1254 handle->ticket->payload->nonce,
1255 handle->r_id);
1256 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(handle->client),
1257 env);
1258 cleanup_exchange_handle (handle);
1259 GNUNET_free (record_str);
1260 GNUNET_free (token_str);
1261} 2118}
1262 2119
1263/** 2120
1264 * Checks a exchange message 2121static void
1265 * 2122handle_iteration_next (void *cls,
1266 * @param cls client sending the message 2123 const struct AttributeIterationNextMessage *ais_msg)
1267 * @param xm message of type `struct ExchangeMessage`
1268 * @return #GNUNET_OK if @a xm is well-formed
1269 */
1270static int
1271check_exchange_message (void *cls,
1272 const struct ExchangeMessage *xm)
1273{ 2124{
1274 uint16_t size; 2125 struct IdpClient *idp = cls;
2126 struct AttributeIterator *ai;
2127 uint32_t rid;
1275 2128
1276 size = ntohs (xm->header.size); 2129 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1277 if (size <= sizeof (struct ExchangeMessage)) 2130 "Received ATTRIBUTE_ITERATION_NEXT message\n");
2131 rid = ntohl (ais_msg->id);
2132 for (ai = idp->op_head; NULL != ai; ai = ai->next)
2133 if (ai->request_id == rid)
2134 break;
2135 if (NULL == ai)
1278 { 2136 {
1279 GNUNET_break (0); 2137 GNUNET_break (0);
1280 return GNUNET_SYSERR; 2138 GNUNET_SERVICE_client_drop (idp->client);
2139 return;
1281 } 2140 }
1282 return GNUNET_OK; 2141 bootstrap_abe (&ai->identity,
2142 &iterate_next_after_abe_bootstrap,
2143 ai,
2144 GNUNET_NO);
2145 GNUNET_SERVICE_client_continue (idp->client);
1283} 2146}
1284 2147
1285/** 2148/**
1286 * 2149 * Ticket iteration processor result
1287 * Handler for exchange message
1288 *
1289 * @param cls unused
1290 * @param client who sent the message
1291 * @param message the message
1292 */ 2150 */
1293static void 2151enum ZoneIterationResult
1294handle_exchange_message (void *cls,
1295 const struct ExchangeMessage *xm)
1296{ 2152{
1297 struct ExchangeHandle *xchange_handle; 2153 /**
1298 struct GNUNET_SERVICE_Client *client = cls; 2154 * Iteration start.
1299 const char *ticket; 2155 */
1300 char *lookup_query; 2156 IT_START = 0,
1301 2157
1302 ticket = (const char *) &xm[1]; 2158 /**
1303 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2159 * Found tickets,
1304 "Received EXCHANGE of `%s' from client\n", 2160 * Continue to iterate with next iteration_next call
1305 ticket); 2161 */
1306 xchange_handle = GNUNET_malloc (sizeof (struct ExchangeHandle)); 2162 IT_SUCCESS_MORE_AVAILABLE = 1,
1307 xchange_handle->aud_privkey = xm->aud_privkey;
1308 xchange_handle->r_id = xm->id;
1309 if (GNUNET_SYSERR == ticket_parse (ticket,
1310 &xchange_handle->aud_privkey,
1311 &xchange_handle->ticket))
1312 {
1313 GNUNET_free (xchange_handle);
1314 GNUNET_SERVICE_client_drop (client);
1315 return;
1316 }
1317 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for token under %s\n",
1318 xchange_handle->ticket->payload->label);
1319 GNUNET_asprintf (&lookup_query,
1320 "%s.gnu",
1321 xchange_handle->ticket->payload->label);
1322 GNUNET_SERVICE_client_continue (client);
1323 xchange_handle->client = client;
1324 xchange_handle->lookup_request
1325 = GNUNET_GNS_lookup (gns_handle,
1326 lookup_query,
1327 &xchange_handle->ticket->payload->identity_key,
1328 GNUNET_GNSRECORD_TYPE_ID_TOKEN,
1329 GNUNET_GNS_LO_LOCAL_MASTER,
1330 &process_lookup_result,
1331 xchange_handle);
1332 GNUNET_free (lookup_query);
1333 2163
1334} 2164 /**
2165 * Iteration complete
2166 */
2167 IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 2
2168};
1335 2169
1336 2170
1337static void 2171/**
1338find_existing_token_error (void *cls) 2172 * Context for ticket iteration
2173 */
2174struct TicketIterationProcResult
1339{ 2175{
1340 struct IssueHandle *handle = cls; 2176 /**
1341 cleanup_issue_handle (handle); 2177 * The ticket iteration handle
1342 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error looking for existing token\n"); 2178 */
1343 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); 2179 struct TicketIteration *ti;
1344}
1345 2180
2181 /**
2182 * Iteration result: iteration done?
2183 * #IT_SUCCESS_MORE_AVAILABLE: if there may be more results overall but
2184 * we got one for now and have sent it to the client
2185 * #IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results,
2186 * #IT_START: if we are still trying to find a result.
2187 */
2188 int res_iteration_finished;
2189
2190};
1346 2191
1347static void 2192static void
1348find_existing_token_finished (void *cls) 2193cleanup_ticket_iter_handle (struct TicketIteration *ti)
1349{ 2194{
1350 struct IssueHandle *handle = cls; 2195 GNUNET_free (ti);
1351 uint64_t rnd_key;
1352
1353 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1354 ">>> No existing token found\n");
1355 rnd_key =
1356 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
1357 UINT64_MAX);
1358 GNUNET_STRINGS_base64_encode ((char*)&rnd_key,
1359 sizeof (uint64_t),
1360 &handle->label);
1361 handle->ns_it = NULL;
1362 handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
1363 &handle->iss_key,
1364 &attr_collect_error,
1365 handle,
1366 &attr_collect,
1367 handle,
1368 &attr_collect_finished,
1369 handle);
1370} 2196}
1371 2197
1372
1373/** 2198/**
2199 * Process ticket from database
1374 * 2200 *
1375 * Look for existing token 2201 * @param cls struct TicketIterationProcResult
1376 * 2202 * @param ticket the ticket
1377 * @param cls the identity entry 2203 * @param attrs the attributes
1378 * @param zone the identity
1379 * @param lbl the name of the record
1380 * @param rd_count number of records
1381 * @param rd record data
1382 *
1383 */ 2204 */
1384static void 2205static void
1385find_existing_token (void *cls, 2206ticket_iterate_proc (void *cls,
1386 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, 2207 const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
1387 const char *lbl, 2208 const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs)
1388 unsigned int rd_count, 2209{
1389 const struct GNUNET_GNSRECORD_Data *rd) 2210 struct TicketIterationProcResult *proc = cls;
1390{
1391 struct IssueHandle *handle = cls;
1392 const struct GNUNET_GNSRECORD_Data *token_metadata_record;
1393 struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key;
1394 struct GNUNET_HashCode key;
1395 int scope_count_token;
1396 char *scope;
1397 char *tmp_scopes;
1398 2211
1399 //There should be only a single record for a token under a label 2212 if (NULL == ticket)
1400 if (2 != rd_count)
1401 { 2213 {
1402 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); 2214 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2215 "Iteration done\n");
2216 proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
1403 return; 2217 return;
1404 } 2218 }
2219 proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
2220 send_ticket_result (proc->ti->client,
2221 proc->ti->r_id,
2222 ticket,
2223 attrs);
1405 2224
1406 if (rd[0].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA) 2225}
1407 {
1408 token_metadata_record = &rd[0];
1409 }
1410 else
1411 {
1412 token_metadata_record = &rd[1];
1413 }
1414 if (token_metadata_record->record_type != GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA)
1415 {
1416 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
1417 return;
1418 }
1419 ecdhe_privkey = *((struct GNUNET_CRYPTO_EcdhePrivateKey *)token_metadata_record->data);
1420 aud_key =
1421 (struct GNUNET_CRYPTO_EcdsaPublicKey *)(token_metadata_record->data+sizeof(struct GNUNET_CRYPTO_EcdhePrivateKey));
1422 tmp_scopes = GNUNET_strdup ((char*) aud_key+sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
1423 2226
1424 if (0 != memcmp (aud_key, &handle->aud_key, 2227/**
1425 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) 2228 * Perform ticket iteration step
1426 { 2229 *
1427 char *tmp2 = GNUNET_STRINGS_data_to_string_alloc (aud_key, 2230 * @param ti ticket iterator to process
1428 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); 2231 */
1429 //Audience does not match! 2232static void
1430 char *tmp = GNUNET_GNSRECORD_value_to_string (GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA, 2233run_ticket_iteration_round (struct TicketIteration *ti)
1431 token_metadata_record->data, 2234{
1432 token_metadata_record->data_size); 2235 struct TicketIterationProcResult proc;
1433 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2236 struct GNUNET_MQ_Envelope *env;
1434 "Token does not match audience %s vs %s. Moving on\n", 2237 struct TicketResultMessage *trm;
1435 tmp2, 2238 int ret;
1436 tmp);
1437 GNUNET_free (tmp_scopes);
1438 GNUNET_free (tmp2);
1439 GNUNET_free (tmp);
1440 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
1441 return;
1442 }
1443 2239
1444 scope = strtok (tmp_scopes, ","); 2240 memset (&proc, 0, sizeof (proc));
1445 scope_count_token = 0; 2241 proc.ti = ti;
1446 while (NULL != scope) 2242 proc.res_iteration_finished = IT_START;
2243 while (IT_START == proc.res_iteration_finished)
1447 { 2244 {
1448 GNUNET_CRYPTO_hash (scope, 2245 if (GNUNET_SYSERR ==
1449 strlen (scope), 2246 (ret = TKT_database->iterate_tickets (TKT_database->cls,
1450 &key); 2247 &ti->identity,
1451 2248 ti->is_audience,
1452 if ((NULL != handle->attr_map) && 2249 ti->offset,
1453 (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->attr_map, &key))) 2250 &ticket_iterate_proc,
2251 &proc)))
1454 { 2252 {
1455 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2253 GNUNET_break (0);
1456 "Issued token does not include `%s'. Moving on\n", scope); 2254 break;
1457 GNUNET_free (tmp_scopes);
1458 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
1459 return;
1460 } 2255 }
1461 scope_count_token++; 2256 if (GNUNET_NO == ret)
1462 scope = strtok (NULL, ","); 2257 proc.res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
2258 ti->offset++;
1463 } 2259 }
1464 GNUNET_free (tmp_scopes); 2260 if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished)
1465 //All scopes in token are also in request. Now
1466 //Check length
1467 if ((NULL != handle->attr_map) &&
1468 (GNUNET_CONTAINER_multihashmap_size (handle->attr_map) == scope_count_token))
1469 { 2261 {
1470 //We have an existing token 2262 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1471 handle->label = GNUNET_strdup (lbl); 2263 "More results available\n");
1472 handle->ns_it = NULL; 2264 return; /* more later */
1473 handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
1474 &handle->iss_key,
1475 &attr_collect_error,
1476 handle,
1477 &attr_collect,
1478 handle,
1479 &attr_collect_finished,
1480 handle);
1481
1482 return;
1483 } 2265 }
1484 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2266 /* send empty response to indicate end of list */
1485 "Nuber of attributes in token do not match request\n"); 2267 env = GNUNET_MQ_msg (trm,
1486 //No luck 2268 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
1487 GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); 2269 trm->id = htonl (ti->r_id);
2270 GNUNET_MQ_send (ti->client->mq,
2271 env);
2272 GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
2273 ti->client->ticket_iter_tail,
2274 ti);
2275 cleanup_ticket_iter_handle (ti);
1488} 2276}
1489 2277
1490/** 2278static void
1491 * Checks an issue message 2279handle_ticket_iteration_start (void *cls,
1492 * 2280 const struct TicketIterationStartMessage *tis_msg)
1493 * @param cls client sending the message
1494 * @param im message of type `struct IssueMessage`
1495 * @return #GNUNET_OK if @a im is well-formed
1496 */
1497static int
1498check_issue_message(void *cls,
1499 const struct IssueMessage *im)
1500{ 2281{
1501 uint16_t size; 2282 struct IdpClient *client = cls;
2283 struct TicketIteration *ti;
1502 2284
1503 size = ntohs (im->header.size); 2285 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1504 if (size <= sizeof (struct IssueMessage)) 2286 "Received TICKET_ITERATION_START message\n");
1505 { 2287 ti = GNUNET_new (struct TicketIteration);
1506 GNUNET_break (0); 2288 ti->r_id = ntohl (tis_msg->id);
1507 return GNUNET_SYSERR; 2289 ti->offset = 0;
1508 } 2290 ti->client = client;
1509 scopes = (char *) &im[1]; 2291 ti->identity = tis_msg->identity;
1510 if ('\0' != scopes[size - sizeof (struct IssueMessage) - 1]) 2292 ti->is_audience = ntohl (tis_msg->is_audience);
2293
2294 GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
2295 client->ticket_iter_tail,
2296 ti);
2297 run_ticket_iteration_round (ti);
2298 GNUNET_SERVICE_client_continue (client->client);
2299}
2300
2301
2302static void
2303handle_ticket_iteration_stop (void *cls,
2304 const struct TicketIterationStopMessage *tis_msg)
2305{
2306 struct IdpClient *client = cls;
2307 struct TicketIteration *ti;
2308 uint32_t rid;
2309
2310 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2311 "Received `%s' message\n",
2312 "TICKET_ITERATION_STOP");
2313 rid = ntohl (tis_msg->id);
2314 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2315 if (ti->r_id == rid)
2316 break;
2317 if (NULL == ti)
1511 { 2318 {
1512 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1513 "Malformed scopes received!\n");
1514 GNUNET_break (0); 2319 GNUNET_break (0);
1515 return GNUNET_SYSERR; 2320 GNUNET_SERVICE_client_drop (client->client);
2321 return;
1516 } 2322 }
1517 return GNUNET_OK; 2323 GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
2324 client->ticket_iter_tail,
2325 ti);
2326 cleanup_ticket_iter_handle (ti);
2327 GNUNET_SERVICE_client_continue (client->client);
1518} 2328}
1519 2329
1520/** 2330
1521 *
1522 * Handler for issue message
1523 *
1524 * @param cls unused
1525 * @param client who sent the message
1526 * @param message the message
1527 */
1528static void 2331static void
1529handle_issue_message (void *cls, 2332handle_ticket_iteration_next (void *cls,
1530 const struct IssueMessage *im) 2333 const struct TicketIterationNextMessage *tis_msg)
1531{ 2334{
1532 const char *scopes; 2335 struct IdpClient *client = cls;
1533 char *scopes_tmp; 2336 struct TicketIteration *ti;
1534 char *scope; 2337 uint32_t rid;
1535 struct GNUNET_HashCode key;
1536 struct IssueHandle *issue_handle;
1537 struct GNUNET_SERVICE_Client *client = cls;
1538
1539 scopes = (const char *) &im[1];
1540 issue_handle = GNUNET_malloc (sizeof (struct IssueHandle));
1541 issue_handle->attr_map = GNUNET_CONTAINER_multihashmap_create (5,
1542 GNUNET_NO);
1543 scopes_tmp = GNUNET_strdup (scopes);
1544 2338
1545 for (scope = strtok (scopes_tmp, ","); NULL != scope; scope = strtok (NULL, ",")) 2339 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2340 "Received TICKET_ITERATION_NEXT message\n");
2341 rid = ntohl (tis_msg->id);
2342 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2343 if (ti->r_id == rid)
2344 break;
2345 if (NULL == ti)
1546 { 2346 {
1547 GNUNET_CRYPTO_hash (scope, 2347 GNUNET_break (0);
1548 strlen (scope), 2348 GNUNET_SERVICE_client_drop (client->client);
1549 &key); 2349 return;
1550 GNUNET_CONTAINER_multihashmap_put (issue_handle->attr_map,
1551 &key,
1552 scope,
1553 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
1554 } 2350 }
1555 GNUNET_free (scopes_tmp); 2351 run_ticket_iteration_round (ti);
1556 issue_handle->r_id = im->id; 2352 GNUNET_SERVICE_client_continue (client->client);
1557 issue_handle->aud_key = im->aud_key;
1558 issue_handle->iss_key = im->iss_key;
1559 GNUNET_CRYPTO_ecdsa_key_get_public (&im->iss_key,
1560 &issue_handle->iss_pkey);
1561 issue_handle->expiration = GNUNET_TIME_absolute_ntoh (im->expiration);
1562 issue_handle->nonce = ntohl (im->nonce);
1563 GNUNET_SERVICE_client_continue (client);
1564 issue_handle->client = client;
1565 issue_handle->scopes = GNUNET_strdup (scopes);
1566 issue_handle->token = token_create (&issue_handle->iss_pkey,
1567 &issue_handle->aud_key);
1568
1569 issue_handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
1570 &im->iss_key,
1571 &find_existing_token_error,
1572 issue_handle,
1573 &find_existing_token,
1574 issue_handle,
1575 &find_existing_token_finished,
1576 issue_handle);
1577} 2353}
1578 2354
1579 2355
2356
2357
1580/** 2358/**
1581 * Main function that will be run 2359 * Main function that will be run
1582 * 2360 *
1583 * @param cls closure 2361 * @param cls closure
1584 * @param args remaining command-line arguments 2362 * @param c the configuration used
1585 * @param cfgfile name of the configuration file used (for saving, can be NULL) 2363 * @param server the service handle
1586 * @param c configuration
1587 */ 2364 */
1588static void 2365static void
1589run (void *cls, 2366run (void *cls,
1590 const struct GNUNET_CONFIGURATION_Handle *c, 2367 const struct GNUNET_CONFIGURATION_Handle *c,
1591 struct GNUNET_SERVICE_Handle *server) 2368 struct GNUNET_SERVICE_Handle *server)
1592{ 2369{
2370 char *database;
1593 cfg = c; 2371 cfg = c;
1594 2372
1595 stats = GNUNET_STATISTICS_create ("identity-provider", cfg); 2373 stats = GNUNET_STATISTICS_create ("identity-provider", cfg);
@@ -1606,10 +2384,38 @@ run (void *cls,
1606 { 2384 {
1607 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns"); 2385 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
1608 } 2386 }
1609 2387 credential_handle = GNUNET_CREDENTIAL_connect (cfg);
2388 if (NULL == credential_handle)
2389 {
2390 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential");
2391 }
1610 identity_handle = GNUNET_IDENTITY_connect (cfg, 2392 identity_handle = GNUNET_IDENTITY_connect (cfg,
1611 &list_ego, 2393 NULL,
1612 NULL); 2394 NULL);
2395 stats_handle = GNUNET_STATISTICS_create ("identity-provider",
2396 cfg);
2397 /* Loading DB plugin */
2398 if (GNUNET_OK !=
2399 GNUNET_CONFIGURATION_get_value_string (cfg,
2400 "identity-provider",
2401 "database",
2402 &database))
2403 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2404 "No database backend configured\n");
2405 GNUNET_asprintf (&db_lib_name,
2406 "libgnunet_plugin_identity_provider_%s",
2407 database);
2408 TKT_database = GNUNET_PLUGIN_load (db_lib_name,
2409 (void *) cfg);
2410 GNUNET_free (database);
2411 if (NULL == TKT_database)
2412 {
2413 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2414 "Could not load database backend `%s'\n",
2415 db_lib_name);
2416 GNUNET_SCHEDULER_shutdown ();
2417 return;
2418 }
1613 2419
1614 if (GNUNET_OK == 2420 if (GNUNET_OK ==
1615 GNUNET_CONFIGURATION_get_value_time (cfg, 2421 GNUNET_CONFIGURATION_get_value_time (cfg,
@@ -1640,9 +2446,39 @@ client_disconnect_cb (void *cls,
1640 struct GNUNET_SERVICE_Client *client, 2446 struct GNUNET_SERVICE_Client *client,
1641 void *app_ctx) 2447 void *app_ctx)
1642{ 2448{
2449 struct IdpClient *idp = app_ctx;
2450 struct AttributeIterator *ai;
2451 struct TicketIteration *ti;
2452 struct TicketRevocationHandle *rh;
2453
2454 //TODO other operations
2455
1643 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2456 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1644 "Client %p disconnected\n", 2457 "Client %p disconnected\n",
1645 client); 2458 client);
2459
2460 while (NULL != (ai = idp->op_head))
2461 {
2462 GNUNET_CONTAINER_DLL_remove (idp->op_head,
2463 idp->op_tail,
2464 ai);
2465 GNUNET_free (ai);
2466 }
2467 while (NULL != (rh = idp->revocation_list_head))
2468 {
2469 GNUNET_CONTAINER_DLL_remove (idp->revocation_list_head,
2470 idp->revocation_list_tail,
2471 rh);
2472 cleanup_revoke_ticket_handle (rh);
2473 }
2474 while (NULL != (ti = idp->ticket_iter_head))
2475 {
2476 GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
2477 idp->ticket_iter_tail,
2478 ti);
2479 cleanup_ticket_iter_handle (ti);
2480 }
2481 GNUNET_free (idp);
1646} 2482}
1647 2483
1648 2484
@@ -1659,10 +2495,14 @@ client_connect_cb (void *cls,
1659 struct GNUNET_SERVICE_Client *client, 2495 struct GNUNET_SERVICE_Client *client,
1660 struct GNUNET_MQ_Handle *mq) 2496 struct GNUNET_MQ_Handle *mq)
1661{ 2497{
2498 struct IdpClient *idp;
1662 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2499 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1663 "Client %p connected\n", 2500 "Client %p connected\n",
1664 client); 2501 client);
1665 return client; 2502 idp = GNUNET_new (struct IdpClient);
2503 idp->client = client;
2504 idp->mq = mq;
2505 return idp;
1666} 2506}
1667 2507
1668 2508
@@ -1677,13 +2517,45 @@ GNUNET_SERVICE_MAIN
1677 &client_connect_cb, 2517 &client_connect_cb,
1678 &client_disconnect_cb, 2518 &client_disconnect_cb,
1679 NULL, 2519 NULL,
1680 GNUNET_MQ_hd_var_size (issue_message, 2520 GNUNET_MQ_hd_var_size (attribute_store_message,
1681 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE, 2521 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE,
1682 struct IssueMessage, 2522 struct AttributeStoreMessage,
2523 NULL),
2524 GNUNET_MQ_hd_fixed_size (iteration_start,
2525 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START,
2526 struct AttributeIterationStartMessage,
2527 NULL),
2528 GNUNET_MQ_hd_fixed_size (iteration_next,
2529 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT,
2530 struct AttributeIterationNextMessage,
2531 NULL),
2532 GNUNET_MQ_hd_fixed_size (iteration_stop,
2533 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP,
2534 struct AttributeIterationStopMessage,
2535 NULL),
2536 GNUNET_MQ_hd_var_size (issue_ticket_message,
2537 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET,
2538 struct IssueTicketMessage,
2539 NULL),
2540 GNUNET_MQ_hd_var_size (consume_ticket_message,
2541 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET,
2542 struct ConsumeTicketMessage,
1683 NULL), 2543 NULL),
1684 GNUNET_MQ_hd_var_size (exchange_message, 2544 GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
1685 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE, 2545 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START,
1686 struct ExchangeMessage, 2546 struct TicketIterationStartMessage,
2547 NULL),
2548 GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
2549 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT,
2550 struct TicketIterationNextMessage,
2551 NULL),
2552 GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
2553 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP,
2554 struct TicketIterationStopMessage,
2555 NULL),
2556 GNUNET_MQ_hd_var_size (revoke_ticket_message,
2557 GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET,
2558 struct RevokeTicketMessage,
1687 NULL), 2559 NULL),
1688 GNUNET_MQ_handler_end()); 2560 GNUNET_MQ_handler_end());
1689/* end of gnunet-service-identity-provider.c */ 2561/* end of gnunet-service-identity-provider.c */