diff options
Diffstat (limited to 'src/identity-provider/gnunet-service-identity-provider.c')
-rw-r--r-- | src/identity-provider/gnunet-service-identity-provider.c | 3064 |
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 | */ | ||
63 | static int state; | ||
64 | |||
65 | /** | ||
66 | * Head of ego entry DLL | ||
67 | */ | 64 | */ |
68 | static struct EgoEntry *ego_head; | 65 | static struct GNUNET_IDENTITY_Handle *identity_handle; |
69 | 66 | ||
70 | /** | 67 | /** |
71 | * Tail of ego entry DLL | 68 | * Database handle |
72 | */ | 69 | */ |
73 | static struct EgoEntry *ego_tail; | 70 | static struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *TKT_database; |
74 | 71 | ||
75 | /** | 72 | /** |
76 | * Identity handle | 73 | * Name of DB plugin |
77 | */ | 74 | */ |
78 | static struct GNUNET_IDENTITY_Handle *identity_handle; | 75 | static 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; | |||
93 | static struct GNUNET_GNS_Handle *gns_handle; | 90 | static struct GNUNET_GNS_Handle *gns_handle; |
94 | 91 | ||
95 | /** | 92 | /** |
93 | * Credential handle | ||
94 | */ | ||
95 | static struct GNUNET_CREDENTIAL_Handle *credential_handle; | ||
96 | |||
97 | /** | ||
98 | * Stats handle | ||
99 | */ | ||
100 | static struct GNUNET_STATISTICS_Handle *stats_handle; | ||
101 | |||
102 | /** | ||
96 | * Namestore qe | 103 | * Namestore qe |
97 | */ | 104 | */ |
98 | static struct GNUNET_NAMESTORE_QueueEntry *ns_qe; | 105 | static struct GNUNET_NAMESTORE_QueueEntry *ns_qe; |
@@ -112,11 +119,6 @@ static struct GNUNET_SCHEDULER_Task *timeout_task; | |||
112 | */ | 119 | */ |
113 | static struct GNUNET_SCHEDULER_Task *update_task; | 120 | static struct GNUNET_SCHEDULER_Task *update_task; |
114 | 121 | ||
115 | /** | ||
116 | * Timeout for next update pass | ||
117 | */ | ||
118 | static 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; | |||
134 | static char* scopes; | 136 | static char* scopes; |
135 | 137 | ||
136 | /** | 138 | /** |
137 | * Expiration for processed token | 139 | * Handle to the statistics service. |
138 | */ | 140 | */ |
139 | static uint64_t rd_exp; | 141 | static struct GNUNET_STATISTICS_Handle *stats; |
140 | 142 | ||
141 | /** | 143 | /** |
142 | * ECDHE Privkey for processed token metadata | 144 | * Our configuration. |
143 | */ | 145 | */ |
144 | static struct GNUNET_CRYPTO_EcdhePrivateKey ecdhe_privkey; | 146 | static const struct GNUNET_CONFIGURATION_Handle *cfg; |
145 | 147 | ||
146 | /** | 148 | /** |
147 | * Handle to the statistics service. | 149 | * An idp client |
148 | */ | 150 | */ |
149 | static struct GNUNET_STATISTICS_Handle *stats; | 151 | struct IdpClient; |
150 | 152 | ||
151 | /** | 153 | /** |
152 | * Our configuration. | 154 | * A ticket iteration operation. |
153 | */ | 155 | */ |
154 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | 156 | struct 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 | ||
157 | struct 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 | */ | ||
207 | typedef void | ||
208 | (*AbeBootstrapResult) (void *cls, | ||
209 | struct GNUNET_ABE_AbeMasterKey *abe_key); | ||
210 | |||
211 | |||
212 | struct 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 | */ | ||
243 | struct 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 | */ | ||
287 | struct 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 | |||
338 | struct 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 */ | ||
379 | struct ParallelLookup; | ||
380 | |||
381 | struct 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 | ||
196 | struct IssueHandle | 445 | /** |
446 | * Handle for a parallel GNS lookup job | ||
447 | */ | ||
448 | struct 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 | */ | ||
474 | struct 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 | */ | ||
542 | struct 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 | */ | ||
608 | static void | ||
609 | cleanup() | ||
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 | */ |
309 | static void | 650 | static void |
310 | store_token_cont (void *cls, | 651 | do_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 | */ | ||
661 | static void | ||
662 | bootstrap_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 | */ |
332 | static void | 684 | static void |
333 | handle_token_update (void *cls) | 685 | bootstrap_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, | 710 | static void |
457 | &enc_token_str)); | 711 | bootstrap_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 | */ | ||
502 | static void | 723 | static void |
503 | update_identities(void *cls); | 724 | bootstrap_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 | */ |
515 | static int | 753 | static void |
516 | clear_ego_attrs (void *cls, | 754 | bootstrap_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 | ||
540 | static void | ||
541 | token_collect_error_cb (void *cls) | ||
542 | { | ||
543 | struct EgoEntry *ego_entry = cls; | ||
544 | 781 | ||
545 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 782 | static int |
546 | ">>> Updating Ego failed!\n"); | 783 | create_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 | ||
805 | static void | ||
806 | cleanup_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 | ||
558 | static void | 816 | static void |
559 | token_collect_finished_cb (void *cls) | 817 | send_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 | */ | ||
585 | static void | 846 | static void |
586 | token_collect (void *cls, | 847 | store_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]; | 871 | int |
608 | token_record = &rd[1]; | 872 | serialize_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 | |||
949 | static void | ||
950 | issue_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 | |||
1020 | static int | ||
1021 | check_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, | 1036 | static void |
633 | &ecdhe_privkey, | 1037 | handle_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 | */ | ||
1070 | static void | ||
1071 | cleanup_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 | */ | ||
645 | static void | 1093 | static void |
646 | attribute_collect_error_cb (void *cls) | 1094 | send_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 | */ | ||
1119 | static void | ||
1120 | ticket_reissue_proc (void *cls, | ||
1121 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
1122 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs); | ||
1123 | |||
658 | static void | 1124 | static void |
659 | attribute_collect_finished_cb (void *cls) | 1125 | revocation_reissue_tickets (struct TicketRevocationHandle *rh); |
1126 | |||
1127 | |||
1128 | static 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"); | 1135 | static void |
665 | ego_entry->attributes_dirty = GNUNET_NO; | 1136 | reissue_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 | */ |
682 | static void | 1163 | static void |
683 | attribute_collect (void *cls, | 1164 | ticket_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 | */ | ||
759 | static void | ||
760 | update_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 */ | ||
1289 | static void | ||
1290 | attr_reenc_cont (void *cls, | ||
1291 | int32_t success, | ||
1292 | const char *emsg); | ||
1293 | |||
1294 | static void | ||
1295 | revocation_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 | */ |
814 | static void | 1322 | static void |
815 | init_cont () | 1323 | reenc_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 | */ |
832 | static void | 1387 | static void |
833 | list_ego (void *cls, | 1388 | attr_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 | */ | ||
858 | static void | 1424 | static void |
859 | cleanup() | 1425 | process_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); | 1451 | static void |
903 | ego_entry = ego_entry->next; | 1452 | get_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 | |||
1465 | static int | ||
1466 | check_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 | */ | ||
914 | static void | 1480 | static void |
915 | do_shutdown (void *cls) | 1481 | handle_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 | ||
923 | static struct GNUNET_MQ_Envelope* | 1506 | static void |
924 | create_exchange_result_message (const char* token, | 1507 | cleanup_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 | ||
943 | static struct GNUNET_MQ_Envelope* | 1518 | |
944 | create_issue_result_message (const char* label, | 1519 | static int |
945 | const char* ticket, | 1520 | check_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 | ||
965 | static void | 1534 | static void |
966 | cleanup_issue_handle (struct IssueHandle *handle) | 1535 | process_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 | ||
981 | static void | 1626 | void |
982 | store_token_issue_cont (void *cls, | 1627 | abort_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 | |||
1655 | static void | ||
1656 | process_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 | |||
1750 | static void | ||
1751 | handle_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 | |||
1788 | static void | ||
1789 | cleanup_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 | |||
1798 | static void | ||
1799 | attr_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 | */ | ||
1038 | static void | 1828 | static void |
1039 | sign_and_return_token (void *cls) | 1829 | attr_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 | ||
1119 | static void | 1890 | static void |
1120 | attr_collect_error (void *cls) | 1891 | store_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"); | 1901 | static int |
1125 | handle->ns_it = NULL; | 1902 | check_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 | ||
1130 | static void | 1917 | static void |
1131 | attr_collect_finished (void *cls) | 1918 | handle_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 | ||
1943 | static void | ||
1944 | cleanup_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 | |||
1954 | static void | ||
1955 | attr_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 | |||
1965 | static void | ||
1966 | attr_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 | */ | ||
1144 | static void | 1980 | static void |
1145 | attr_collect (void *cls, | 1981 | attr_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); | 2043 | void |
2044 | iterate_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 | ||
2059 | void | ||
2060 | iterate_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 | |||
1207 | static void | 2070 | static void |
1208 | cleanup_exchange_handle (struct ExchangeHandle *handle) | 2071 | handle_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 | |||
1217 | static void | 2092 | static void |
1218 | process_lookup_result (void *cls, uint32_t rd_count, | 2093 | handle_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 | 2121 | static void |
1265 | * | 2122 | handle_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 | */ | ||
1270 | static int | ||
1271 | check_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 | */ |
1293 | static void | 2151 | enum ZoneIterationResult |
1294 | handle_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 | ||
1337 | static void | 2171 | /** |
1338 | find_existing_token_error (void *cls) | 2172 | * Context for ticket iteration |
2173 | */ | ||
2174 | struct 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 | ||
1347 | static void | 2192 | static void |
1348 | find_existing_token_finished (void *cls) | 2193 | cleanup_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 | */ |
1384 | static void | 2205 | static void |
1385 | find_existing_token (void *cls, | 2206 | ticket_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! | 2232 | static void |
1430 | char *tmp = GNUNET_GNSRECORD_value_to_string (GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA, | 2233 | run_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 | /** | 2278 | static void |
1491 | * Checks an issue message | 2279 | handle_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 | */ | ||
1497 | static int | ||
1498 | check_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 | |||
2302 | static void | ||
2303 | handle_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 | */ | ||
1528 | static void | 2331 | static void |
1529 | handle_issue_message (void *cls, | 2332 | handle_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 | */ |
1588 | static void | 2365 | static void |
1589 | run (void *cls, | 2366 | run (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 */ |