diff options
Diffstat (limited to 'src/identity-provider/identity_provider_api.c')
-rw-r--r-- | src/identity-provider/identity_provider_api.c | 1213 |
1 files changed, 969 insertions, 244 deletions
diff --git a/src/identity-provider/identity_provider_api.c b/src/identity-provider/identity_provider_api.c index 845d1f753..d0ece80fe 100644 --- a/src/identity-provider/identity_provider_api.c +++ b/src/identity-provider/identity_provider_api.c | |||
@@ -29,12 +29,12 @@ | |||
29 | #include "gnunet_protocols.h" | 29 | #include "gnunet_protocols.h" |
30 | #include "gnunet_mq_lib.h" | 30 | #include "gnunet_mq_lib.h" |
31 | #include "gnunet_identity_provider_service.h" | 31 | #include "gnunet_identity_provider_service.h" |
32 | #include "gnunet_identity_attribute_lib.h" | ||
32 | #include "identity_provider.h" | 33 | #include "identity_provider.h" |
33 | 34 | ||
34 | #define LOG(kind,...) GNUNET_log_from (kind, "identity-api",__VA_ARGS__) | 35 | #define LOG(kind,...) GNUNET_log_from (kind, "identity-api",__VA_ARGS__) |
35 | 36 | ||
36 | 37 | ||
37 | |||
38 | /** | 38 | /** |
39 | * Handle for an operation with the service. | 39 | * Handle for an operation with the service. |
40 | */ | 40 | */ |
@@ -63,16 +63,24 @@ struct GNUNET_IDENTITY_PROVIDER_Operation | |||
63 | const struct GNUNET_MessageHeader *msg; | 63 | const struct GNUNET_MessageHeader *msg; |
64 | 64 | ||
65 | /** | 65 | /** |
66 | * Continuation to invoke with the result of the transmission; @e cb | 66 | * Continuation to invoke after attribute store call |
67 | * will be NULL in this case. | 67 | */ |
68 | GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus as_cb; | ||
69 | |||
70 | /** | ||
71 | * Attribute result callback | ||
72 | */ | ||
73 | GNUNET_IDENTITY_PROVIDER_AttributeResult ar_cb; | ||
74 | |||
75 | /** | ||
76 | * Revocation result callback | ||
68 | */ | 77 | */ |
69 | GNUNET_IDENTITY_PROVIDER_ExchangeCallback ex_cb; | 78 | GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus rvk_cb; |
70 | 79 | ||
71 | /** | 80 | /** |
72 | * Continuation to invoke with the result of the transmission for | 81 | * Ticket result callback |
73 | * 'issue' operations (@e cont will be NULL in this case). | ||
74 | */ | 82 | */ |
75 | GNUNET_IDENTITY_PROVIDER_IssueCallback iss_cb; | 83 | GNUNET_IDENTITY_PROVIDER_TicketCallback tr_cb; |
76 | 84 | ||
77 | /** | 85 | /** |
78 | * Envelope with the message for this queue entry. | 86 | * Envelope with the message for this queue entry. |
@@ -91,6 +99,140 @@ struct GNUNET_IDENTITY_PROVIDER_Operation | |||
91 | 99 | ||
92 | }; | 100 | }; |
93 | 101 | ||
102 | /** | ||
103 | * Handle for a ticket iterator operation | ||
104 | */ | ||
105 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator | ||
106 | { | ||
107 | |||
108 | /** | ||
109 | * Kept in a DLL. | ||
110 | */ | ||
111 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator *next; | ||
112 | |||
113 | /** | ||
114 | * Kept in a DLL. | ||
115 | */ | ||
116 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator *prev; | ||
117 | |||
118 | /** | ||
119 | * Main handle to access the idp. | ||
120 | */ | ||
121 | struct GNUNET_IDENTITY_PROVIDER_Handle *h; | ||
122 | |||
123 | /** | ||
124 | * Function to call on completion. | ||
125 | */ | ||
126 | GNUNET_SCHEDULER_TaskCallback finish_cb; | ||
127 | |||
128 | /** | ||
129 | * Closure for @e error_cb. | ||
130 | */ | ||
131 | void *finish_cb_cls; | ||
132 | |||
133 | /** | ||
134 | * The continuation to call with the results | ||
135 | */ | ||
136 | GNUNET_IDENTITY_PROVIDER_TicketCallback tr_cb; | ||
137 | |||
138 | /** | ||
139 | * Closure for @e tr_cb. | ||
140 | */ | ||
141 | void *cls; | ||
142 | |||
143 | /** | ||
144 | * Function to call on errors. | ||
145 | */ | ||
146 | GNUNET_SCHEDULER_TaskCallback error_cb; | ||
147 | |||
148 | /** | ||
149 | * Closure for @e error_cb. | ||
150 | */ | ||
151 | void *error_cb_cls; | ||
152 | |||
153 | /** | ||
154 | * Envelope of the message to send to the service, if not yet | ||
155 | * sent. | ||
156 | */ | ||
157 | struct GNUNET_MQ_Envelope *env; | ||
158 | |||
159 | /** | ||
160 | * The operation id this zone iteration operation has | ||
161 | */ | ||
162 | uint32_t r_id; | ||
163 | |||
164 | }; | ||
165 | |||
166 | |||
167 | /** | ||
168 | * Handle for a attribute iterator operation | ||
169 | */ | ||
170 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator | ||
171 | { | ||
172 | |||
173 | /** | ||
174 | * Kept in a DLL. | ||
175 | */ | ||
176 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *next; | ||
177 | |||
178 | /** | ||
179 | * Kept in a DLL. | ||
180 | */ | ||
181 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *prev; | ||
182 | |||
183 | /** | ||
184 | * Main handle to access the idp. | ||
185 | */ | ||
186 | struct GNUNET_IDENTITY_PROVIDER_Handle *h; | ||
187 | |||
188 | /** | ||
189 | * Function to call on completion. | ||
190 | */ | ||
191 | GNUNET_SCHEDULER_TaskCallback finish_cb; | ||
192 | |||
193 | /** | ||
194 | * Closure for @e error_cb. | ||
195 | */ | ||
196 | void *finish_cb_cls; | ||
197 | |||
198 | /** | ||
199 | * The continuation to call with the results | ||
200 | */ | ||
201 | GNUNET_IDENTITY_PROVIDER_AttributeResult proc; | ||
202 | |||
203 | /** | ||
204 | * Closure for @e proc. | ||
205 | */ | ||
206 | void *proc_cls; | ||
207 | |||
208 | /** | ||
209 | * Function to call on errors. | ||
210 | */ | ||
211 | GNUNET_SCHEDULER_TaskCallback error_cb; | ||
212 | |||
213 | /** | ||
214 | * Closure for @e error_cb. | ||
215 | */ | ||
216 | void *error_cb_cls; | ||
217 | |||
218 | /** | ||
219 | * Envelope of the message to send to the service, if not yet | ||
220 | * sent. | ||
221 | */ | ||
222 | struct GNUNET_MQ_Envelope *env; | ||
223 | |||
224 | /** | ||
225 | * Private key of the zone. | ||
226 | */ | ||
227 | struct GNUNET_CRYPTO_EcdsaPrivateKey identity; | ||
228 | |||
229 | /** | ||
230 | * The operation id this zone iteration operation has | ||
231 | */ | ||
232 | uint32_t r_id; | ||
233 | |||
234 | }; | ||
235 | |||
94 | 236 | ||
95 | /** | 237 | /** |
96 | * Handle for the service. | 238 | * Handle for the service. |
@@ -123,6 +265,27 @@ struct GNUNET_IDENTITY_PROVIDER_Handle | |||
123 | struct GNUNET_IDENTITY_PROVIDER_Operation *op_tail; | 265 | struct GNUNET_IDENTITY_PROVIDER_Operation *op_tail; |
124 | 266 | ||
125 | /** | 267 | /** |
268 | * Head of active iterations | ||
269 | */ | ||
270 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it_head; | ||
271 | |||
272 | /** | ||
273 | * Tail of active iterations | ||
274 | */ | ||
275 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it_tail; | ||
276 | |||
277 | /** | ||
278 | * Head of active iterations | ||
279 | */ | ||
280 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it_head; | ||
281 | |||
282 | /** | ||
283 | * Tail of active iterations | ||
284 | */ | ||
285 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it_tail; | ||
286 | |||
287 | |||
288 | /** | ||
126 | * Currently pending transmission request, or NULL for none. | 289 | * Currently pending transmission request, or NULL for none. |
127 | */ | 290 | */ |
128 | struct GNUNET_CLIENT_TransmitHandle *th; | 291 | struct GNUNET_CLIENT_TransmitHandle *th; |
@@ -154,14 +317,13 @@ struct GNUNET_IDENTITY_PROVIDER_Handle | |||
154 | 317 | ||
155 | }; | 318 | }; |
156 | 319 | ||
157 | |||
158 | /** | 320 | /** |
159 | * Try again to connect to the service. | 321 | * Try again to connect to the service. |
160 | * | 322 | * |
161 | * @param cls handle to the service. | 323 | * @param h handle to the identity provider service. |
162 | */ | 324 | */ |
163 | static void | 325 | static void |
164 | reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *handle); | 326 | reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h); |
165 | 327 | ||
166 | /** | 328 | /** |
167 | * Reconnect | 329 | * Reconnect |
@@ -181,7 +343,7 @@ reconnect_task (void *cls) | |||
181 | /** | 343 | /** |
182 | * Disconnect from service and then reconnect. | 344 | * Disconnect from service and then reconnect. |
183 | * | 345 | * |
184 | * @param handle our handle | 346 | * @param handle our service |
185 | */ | 347 | */ |
186 | static void | 348 | static void |
187 | force_reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *handle) | 349 | force_reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *handle) |
@@ -197,6 +359,26 @@ force_reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *handle) | |||
197 | } | 359 | } |
198 | 360 | ||
199 | /** | 361 | /** |
362 | * Free @a it. | ||
363 | * | ||
364 | * @param it entry to free | ||
365 | */ | ||
366 | static void | ||
367 | free_it (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it) | ||
368 | { | ||
369 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h; | ||
370 | |||
371 | GNUNET_CONTAINER_DLL_remove (h->it_head, | ||
372 | h->it_tail, | ||
373 | it); | ||
374 | if (NULL != it->env) | ||
375 | GNUNET_MQ_discard (it->env); | ||
376 | GNUNET_free (it); | ||
377 | } | ||
378 | |||
379 | |||
380 | |||
381 | /** | ||
200 | * Generic error handler, called with the appropriate error code and | 382 | * Generic error handler, called with the appropriate error code and |
201 | * the same closure specified at the creation of the message queue. | 383 | * the same closure specified at the creation of the message queue. |
202 | * Not every message queue implementation supports an error handler. | 384 | * Not every message queue implementation supports an error handler. |
@@ -213,22 +395,68 @@ mq_error_handler (void *cls, | |||
213 | } | 395 | } |
214 | 396 | ||
215 | /** | 397 | /** |
216 | * Check validity of message received from the service | 398 | * Handle an incoming message of type |
399 | * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE | ||
400 | * | ||
401 | * @param cls | ||
402 | * @param msg the message we received | ||
403 | */ | ||
404 | static void | ||
405 | handle_attribute_store_response (void *cls, | ||
406 | const struct AttributeStoreResultMessage *msg) | ||
407 | { | ||
408 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls; | ||
409 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
410 | uint32_t r_id = ntohl (msg->id); | ||
411 | int res; | ||
412 | const char *emsg; | ||
413 | |||
414 | for (op = h->op_head; NULL != op; op = op->next) | ||
415 | if (op->r_id == r_id) | ||
416 | break; | ||
417 | if (NULL == op) | ||
418 | return; | ||
419 | |||
420 | res = ntohl (msg->op_result); | ||
421 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
422 | "Received ATTRIBUTE_STORE_RESPONSE with result %d\n", | ||
423 | res); | ||
424 | |||
425 | /* TODO: add actual error message to response... */ | ||
426 | if (GNUNET_SYSERR == res) | ||
427 | emsg = _("failed to store record\n"); | ||
428 | else | ||
429 | emsg = NULL; | ||
430 | if (NULL != op->as_cb) | ||
431 | op->as_cb (op->cls, | ||
432 | res, | ||
433 | emsg); | ||
434 | GNUNET_CONTAINER_DLL_remove (h->op_head, | ||
435 | h->op_tail, | ||
436 | op); | ||
437 | GNUNET_free (op); | ||
438 | |||
439 | } | ||
440 | |||
441 | |||
442 | /** | ||
443 | * Handle an incoming message of type | ||
444 | * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT | ||
217 | * | 445 | * |
218 | * @param cls the `struct GNUNET_IDENTITY_PROVIDER_Handle *` | 446 | * @param cls |
219 | * @param result_msg the incoming message | 447 | * @param msg the message we received |
448 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | ||
220 | */ | 449 | */ |
221 | static int | 450 | static int |
222 | check_exchange_result (void *cls, | 451 | check_consume_ticket_result (void *cls, |
223 | const struct ExchangeResultMessage *erm) | 452 | const struct ConsumeTicketResultMessage *msg) |
224 | { | 453 | { |
225 | char *str; | 454 | size_t msg_len; |
226 | size_t size = ntohs (erm->header.size) - sizeof (*erm); | 455 | size_t attrs_len; |
227 | |||
228 | 456 | ||
229 | str = (char *) &erm[1]; | 457 | msg_len = ntohs (msg->header.size); |
230 | if ( (size > sizeof (struct ExchangeResultMessage)) && | 458 | attrs_len = ntohs (msg->attrs_len); |
231 | ('\0' != str[size - sizeof (struct ExchangeResultMessage) - 1]) ) | 459 | if (msg_len != sizeof (struct ConsumeTicketResultMessage) + attrs_len) |
232 | { | 460 | { |
233 | GNUNET_break (0); | 461 | GNUNET_break (0); |
234 | return GNUNET_SYSERR; | 462 | return GNUNET_SYSERR; |
@@ -238,20 +466,85 @@ check_exchange_result (void *cls, | |||
238 | 466 | ||
239 | 467 | ||
240 | /** | 468 | /** |
241 | * Check validity of message received from the service | 469 | * Handle an incoming message of type |
470 | * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT | ||
471 | * | ||
472 | * @param cls | ||
473 | * @param msg the message we received | ||
474 | */ | ||
475 | static void | ||
476 | handle_consume_ticket_result (void *cls, | ||
477 | const struct ConsumeTicketResultMessage *msg) | ||
478 | { | ||
479 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls; | ||
480 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
481 | size_t attrs_len; | ||
482 | uint32_t r_id = ntohl (msg->id); | ||
483 | |||
484 | attrs_len = ntohs (msg->attrs_len); | ||
485 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
486 | "Processing attribute result.\n"); | ||
487 | |||
488 | |||
489 | for (op = h->op_head; NULL != op; op = op->next) | ||
490 | if (op->r_id == r_id) | ||
491 | break; | ||
492 | if (NULL == op) | ||
493 | return; | ||
494 | |||
495 | { | ||
496 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs; | ||
497 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le; | ||
498 | attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize ((char*)&msg[1], | ||
499 | attrs_len); | ||
500 | if (NULL != op->ar_cb) | ||
501 | { | ||
502 | if (NULL == attrs) | ||
503 | { | ||
504 | op->ar_cb (op->cls, | ||
505 | &msg->identity, | ||
506 | NULL); | ||
507 | } | ||
508 | else | ||
509 | { | ||
510 | for (le = attrs->list_head; NULL != le; le = le->next) | ||
511 | op->ar_cb (op->cls, | ||
512 | &msg->identity, | ||
513 | le->claim); | ||
514 | GNUNET_IDENTITY_ATTRIBUTE_list_destroy (attrs); | ||
515 | } | ||
516 | } | ||
517 | op->ar_cb (op->cls, | ||
518 | NULL, | ||
519 | NULL); | ||
520 | GNUNET_CONTAINER_DLL_remove (h->op_head, | ||
521 | h->op_tail, | ||
522 | op); | ||
523 | GNUNET_free (op); | ||
524 | return; | ||
525 | } | ||
526 | GNUNET_assert (0); | ||
527 | } | ||
528 | |||
529 | |||
530 | /** | ||
531 | * Handle an incoming message of type | ||
532 | * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT | ||
242 | * | 533 | * |
243 | * @param cls the `struct GNUNET_IDENTITY_PROVIDER_Handle *` | 534 | * @param cls |
244 | * @param result_msg the incoming message | 535 | * @param msg the message we received |
536 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | ||
245 | */ | 537 | */ |
246 | static int | 538 | static int |
247 | check_result (void *cls, | 539 | check_attribute_result (void *cls, |
248 | const struct IssueResultMessage *irm) | 540 | const struct AttributeResultMessage *msg) |
249 | { | 541 | { |
250 | char *str; | 542 | size_t msg_len; |
251 | size_t size = ntohs (irm->header.size) - sizeof (*irm); | 543 | size_t attr_len; |
252 | str = (char*) &irm[1]; | 544 | |
253 | if ( (size > sizeof (struct IssueResultMessage)) && | 545 | msg_len = ntohs (msg->header.size); |
254 | ('\0' != str[size - sizeof (struct IssueResultMessage) - 1]) ) | 546 | attr_len = ntohs (msg->attr_len); |
547 | if (msg_len != sizeof (struct AttributeResultMessage) + attr_len) | ||
255 | { | 548 | { |
256 | GNUNET_break (0); | 549 | GNUNET_break (0); |
257 | return GNUNET_SYSERR; | 550 | return GNUNET_SYSERR; |
@@ -259,119 +552,254 @@ check_result (void *cls, | |||
259 | return GNUNET_OK; | 552 | return GNUNET_OK; |
260 | } | 553 | } |
261 | 554 | ||
555 | |||
262 | /** | 556 | /** |
263 | * Handler for messages received from the GNS service | 557 | * Handle an incoming message of type |
558 | * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT | ||
264 | * | 559 | * |
265 | * @param cls the `struct GNUNET_GNS_Handle *` | 560 | * @param cls |
266 | * @param loookup_msg the incoming message | 561 | * @param msg the message we received |
267 | */ | 562 | */ |
268 | static void | 563 | static void |
269 | handle_exchange_result (void *cls, | 564 | handle_attribute_result (void *cls, |
270 | const struct ExchangeResultMessage *erm) | 565 | const struct AttributeResultMessage *msg) |
271 | { | 566 | { |
272 | struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls; | 567 | static struct GNUNET_CRYPTO_EcdsaPrivateKey identity_dummy; |
568 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls; | ||
569 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it; | ||
273 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | 570 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; |
274 | struct GNUNET_IDENTITY_PROVIDER_Token token; | 571 | size_t attr_len; |
275 | uint64_t ticket_nonce; | 572 | uint32_t r_id = ntohl (msg->id); |
276 | uint32_t r_id = ntohl (erm->id); | 573 | |
277 | char *str; | 574 | attr_len = ntohs (msg->attr_len); |
278 | 575 | LOG (GNUNET_ERROR_TYPE_DEBUG, | |
279 | for (op = handle->op_head; NULL != op; op = op->next) | 576 | "Processing attribute result.\n"); |
577 | |||
578 | |||
579 | for (it = h->it_head; NULL != it; it = it->next) | ||
580 | if (it->r_id == r_id) | ||
581 | break; | ||
582 | for (op = h->op_head; NULL != op; op = op->next) | ||
280 | if (op->r_id == r_id) | 583 | if (op->r_id == r_id) |
281 | break; | 584 | break; |
282 | if (NULL == op) | 585 | if ((NULL == it) && (NULL == op)) |
283 | return; | 586 | return; |
284 | str = GNUNET_strdup ((char*)&erm[1]); | ||
285 | op = handle->op_head; | ||
286 | GNUNET_CONTAINER_DLL_remove (handle->op_head, | ||
287 | handle->op_tail, | ||
288 | op); | ||
289 | token.data = str; | ||
290 | ticket_nonce = ntohl (erm->ticket_nonce); | ||
291 | if (NULL != op->ex_cb) | ||
292 | op->ex_cb (op->cls, &token, ticket_nonce); | ||
293 | GNUNET_free (str); | ||
294 | GNUNET_free (op); | ||
295 | 587 | ||
588 | if ( (0 == (memcmp (&msg->identity, | ||
589 | &identity_dummy, | ||
590 | sizeof (identity_dummy)))) ) | ||
591 | { | ||
592 | if ((NULL == it) && (NULL == op)) | ||
593 | { | ||
594 | GNUNET_break (0); | ||
595 | force_reconnect (h); | ||
596 | return; | ||
597 | } | ||
598 | if (NULL != it) | ||
599 | { | ||
600 | if (NULL != it->finish_cb) | ||
601 | it->finish_cb (it->finish_cb_cls); | ||
602 | free_it (it); | ||
603 | } | ||
604 | if (NULL != op) | ||
605 | { | ||
606 | if (NULL != op->ar_cb) | ||
607 | op->ar_cb (op->cls, | ||
608 | NULL, | ||
609 | NULL); | ||
610 | GNUNET_CONTAINER_DLL_remove (h->op_head, | ||
611 | h->op_tail, | ||
612 | op); | ||
613 | GNUNET_free (op); | ||
614 | |||
615 | } | ||
616 | return; | ||
617 | } | ||
618 | |||
619 | { | ||
620 | struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr; | ||
621 | attr = GNUNET_IDENTITY_ATTRIBUTE_deserialize ((char*)&msg[1], | ||
622 | attr_len); | ||
623 | if (NULL != it) | ||
624 | { | ||
625 | if (NULL != it->proc) | ||
626 | it->proc (it->proc_cls, | ||
627 | &msg->identity, | ||
628 | attr); | ||
629 | } else if (NULL != op) | ||
630 | { | ||
631 | if (NULL != op->ar_cb) | ||
632 | op->ar_cb (op->cls, | ||
633 | &msg->identity, | ||
634 | attr); | ||
635 | |||
636 | } | ||
637 | GNUNET_free (attr); | ||
638 | return; | ||
639 | } | ||
640 | GNUNET_assert (0); | ||
641 | } | ||
642 | |||
643 | /** | ||
644 | * Handle an incoming message of type | ||
645 | * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT | ||
646 | * | ||
647 | * @param cls | ||
648 | * @param msg the message we received | ||
649 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | ||
650 | */ | ||
651 | static int | ||
652 | check_ticket_result (void *cls, | ||
653 | const struct TicketResultMessage *msg) | ||
654 | { | ||
655 | size_t msg_len; | ||
656 | |||
657 | msg_len = ntohs (msg->header.size); | ||
658 | if (msg_len < sizeof (struct TicketResultMessage)) | ||
659 | { | ||
660 | GNUNET_break (0); | ||
661 | return GNUNET_SYSERR; | ||
662 | } | ||
663 | return GNUNET_OK; | ||
296 | } | 664 | } |
297 | 665 | ||
666 | |||
667 | |||
298 | /** | 668 | /** |
299 | * Handler for messages received from the GNS service | 669 | * Handle an incoming message of type |
670 | * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT | ||
300 | * | 671 | * |
301 | * @param cls the `struct GNUNET_GNS_Handle *` | 672 | * @param cls |
302 | * @param loookup_msg the incoming message | 673 | * @param msg the message we received |
303 | */ | 674 | */ |
304 | static void | 675 | static void |
305 | handle_result (void *cls, | 676 | handle_ticket_result (void *cls, |
306 | const struct IssueResultMessage *irm) | 677 | const struct TicketResultMessage *msg) |
307 | { | 678 | { |
308 | struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls; | 679 | struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls; |
309 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | 680 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; |
310 | struct GNUNET_IDENTITY_PROVIDER_Token token; | 681 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it; |
311 | struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; | 682 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket; |
312 | uint32_t r_id = ntohl (irm->id); | 683 | uint32_t r_id = ntohl (msg->id); |
313 | char *str; | 684 | size_t msg_len; |
314 | char *label_str; | ||
315 | char *ticket_str; | ||
316 | char *token_str; | ||
317 | 685 | ||
318 | for (op = handle->op_head; NULL != op; op = op->next) | 686 | for (op = handle->op_head; NULL != op; op = op->next) |
319 | if (op->r_id == r_id) | 687 | if (op->r_id == r_id) |
320 | break; | 688 | break; |
321 | if (NULL == op) | 689 | for (it = handle->ticket_it_head; NULL != it; it = it->next) |
690 | if (it->r_id == r_id) | ||
691 | break; | ||
692 | if ((NULL == op) && (NULL == it)) | ||
322 | return; | 693 | return; |
323 | str = GNUNET_strdup ((char*)&irm[1]); | 694 | msg_len = ntohs (msg->header.size); |
324 | label_str = strtok (str, ","); | 695 | if (NULL != op) |
325 | |||
326 | if (NULL == label_str) | ||
327 | { | 696 | { |
328 | GNUNET_free (str); | 697 | GNUNET_CONTAINER_DLL_remove (handle->op_head, |
329 | GNUNET_break (0); | 698 | handle->op_tail, |
699 | op); | ||
700 | if (msg_len == sizeof (struct TicketResultMessage)) | ||
701 | { | ||
702 | if (NULL != op->tr_cb) | ||
703 | op->tr_cb (op->cls, NULL); | ||
704 | } else { | ||
705 | ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&msg[1]; | ||
706 | if (NULL != op->tr_cb) | ||
707 | op->tr_cb (op->cls, ticket); | ||
708 | } | ||
709 | GNUNET_free (op); | ||
330 | return; | 710 | return; |
331 | } | 711 | } else if (NULL != it) { |
332 | ticket_str = strtok (NULL, ","); | 712 | if (msg_len == sizeof (struct TicketResultMessage)) |
333 | if (NULL == ticket_str) | 713 | { |
334 | { | 714 | if (NULL != it->tr_cb) |
335 | GNUNET_free (str); | 715 | GNUNET_CONTAINER_DLL_remove (handle->ticket_it_head, |
336 | GNUNET_break (0); | 716 | handle->ticket_it_tail, |
717 | it); | ||
718 | it->finish_cb (it->finish_cb_cls); | ||
719 | GNUNET_free (it); | ||
720 | } else { | ||
721 | ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&msg[1]; | ||
722 | if (NULL != it->tr_cb) | ||
723 | it->tr_cb (it->cls, ticket); | ||
724 | } | ||
337 | return; | 725 | return; |
338 | } | 726 | } |
339 | token_str = strtok (NULL, ","); | 727 | GNUNET_break (0); |
340 | if (NULL == token_str) | 728 | } |
729 | |||
730 | /** | ||
731 | * Handle an incoming message of type | ||
732 | * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT | ||
733 | * | ||
734 | * @param cls | ||
735 | * @param msg the message we received | ||
736 | */ | ||
737 | static void | ||
738 | handle_revoke_ticket_result (void *cls, | ||
739 | const struct RevokeTicketResultMessage *msg) | ||
740 | { | ||
741 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls; | ||
742 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
743 | uint32_t r_id = ntohl (msg->id); | ||
744 | int32_t success; | ||
745 | |||
746 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
747 | "Processing revocation result.\n"); | ||
748 | |||
749 | |||
750 | for (op = h->op_head; NULL != op; op = op->next) | ||
751 | if (op->r_id == r_id) | ||
752 | break; | ||
753 | if (NULL == op) | ||
754 | return; | ||
755 | success = ntohl (msg->success); | ||
341 | { | 756 | { |
342 | GNUNET_free (str); | 757 | if (NULL != op->rvk_cb) |
343 | GNUNET_break (0); | 758 | { |
759 | op->rvk_cb (op->cls, | ||
760 | success, | ||
761 | NULL); | ||
762 | } | ||
763 | GNUNET_CONTAINER_DLL_remove (h->op_head, | ||
764 | h->op_tail, | ||
765 | op); | ||
766 | GNUNET_free (op); | ||
344 | return; | 767 | return; |
345 | } | 768 | } |
346 | GNUNET_CONTAINER_DLL_remove (handle->op_head, | 769 | GNUNET_assert (0); |
347 | handle->op_tail, | ||
348 | op); | ||
349 | ticket.data = ticket_str; | ||
350 | token.data = token_str; | ||
351 | if (NULL != op->iss_cb) | ||
352 | op->iss_cb (op->cls, label_str, &ticket, &token); | ||
353 | GNUNET_free (str); | ||
354 | GNUNET_free (op); | ||
355 | |||
356 | } | 770 | } |
357 | 771 | ||
772 | |||
773 | |||
358 | /** | 774 | /** |
359 | * Try again to connect to the service. | 775 | * Try again to connect to the service. |
360 | * | 776 | * |
361 | * @param cls handle to the identity provider service. | 777 | * @param h handle to the identity provider service. |
362 | */ | 778 | */ |
363 | static void | 779 | static void |
364 | reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h) | 780 | reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h) |
365 | { | 781 | { |
366 | struct GNUNET_MQ_MessageHandler handlers[] = { | 782 | struct GNUNET_MQ_MessageHandler handlers[] = { |
367 | GNUNET_MQ_hd_var_size (result, | 783 | GNUNET_MQ_hd_fixed_size (attribute_store_response, |
368 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT, | 784 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE, |
369 | struct IssueResultMessage, | 785 | struct AttributeStoreResultMessage, |
786 | h), | ||
787 | GNUNET_MQ_hd_var_size (attribute_result, | ||
788 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT, | ||
789 | struct AttributeResultMessage, | ||
370 | h), | 790 | h), |
371 | GNUNET_MQ_hd_var_size (exchange_result, | 791 | GNUNET_MQ_hd_var_size (ticket_result, |
372 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT, | 792 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT, |
373 | struct ExchangeResultMessage, | 793 | struct TicketResultMessage, |
374 | h), | 794 | h), |
795 | GNUNET_MQ_hd_var_size (consume_ticket_result, | ||
796 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT, | ||
797 | struct ConsumeTicketResultMessage, | ||
798 | h), | ||
799 | GNUNET_MQ_hd_fixed_size (revoke_ticket_result, | ||
800 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT, | ||
801 | struct RevokeTicketResultMessage, | ||
802 | h), | ||
375 | GNUNET_MQ_handler_end () | 803 | GNUNET_MQ_handler_end () |
376 | }; | 804 | }; |
377 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | 805 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; |
@@ -417,111 +845,6 @@ GNUNET_IDENTITY_PROVIDER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) | |||
417 | 845 | ||
418 | 846 | ||
419 | /** | 847 | /** |
420 | * Issue an identity token | ||
421 | * | ||
422 | * @param id identity service to query | ||
423 | * @param service_name for which service is an identity wanted | ||
424 | * @param cb function to call with the result (will only be called once) | ||
425 | * @param cb_cls closure for @a cb | ||
426 | * @return handle to abort the operation | ||
427 | */ | ||
428 | struct GNUNET_IDENTITY_PROVIDER_Operation * | ||
429 | GNUNET_IDENTITY_PROVIDER_issue_token (struct GNUNET_IDENTITY_PROVIDER_Handle *id, | ||
430 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss_key, | ||
431 | const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, | ||
432 | const char* scopes, | ||
433 | struct GNUNET_TIME_Absolute expiration, | ||
434 | uint64_t nonce, | ||
435 | GNUNET_IDENTITY_PROVIDER_IssueCallback cb, | ||
436 | void *cb_cls) | ||
437 | { | ||
438 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
439 | struct IssueMessage *im; | ||
440 | size_t slen; | ||
441 | |||
442 | slen = strlen (scopes) + 1; | ||
443 | if (slen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (struct IssueMessage)) | ||
444 | { | ||
445 | GNUNET_break (0); | ||
446 | return NULL; | ||
447 | } | ||
448 | op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation); | ||
449 | op->h = id; | ||
450 | op->iss_cb = cb; | ||
451 | op->cls = cb_cls; | ||
452 | op->r_id = id->r_id_gen++; | ||
453 | op->env = GNUNET_MQ_msg_extra (im, | ||
454 | slen, | ||
455 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE); | ||
456 | im->id = op->r_id; | ||
457 | im->iss_key = *iss_key; | ||
458 | im->aud_key = *aud_key; | ||
459 | im->nonce = htonl (nonce); | ||
460 | im->expiration = GNUNET_TIME_absolute_hton (expiration); | ||
461 | GNUNET_memcpy (&im[1], scopes, slen); | ||
462 | GNUNET_CONTAINER_DLL_insert_tail (id->op_head, | ||
463 | id->op_tail, | ||
464 | op); | ||
465 | if (NULL != id->mq) | ||
466 | GNUNET_MQ_send_copy (id->mq, | ||
467 | op->env); | ||
468 | return op; | ||
469 | } | ||
470 | |||
471 | |||
472 | /** | ||
473 | * Exchange a token ticket for a token | ||
474 | * | ||
475 | * @param id identity provider service | ||
476 | * @param ticket ticket to exchange | ||
477 | * @param cont function to call once the operation finished | ||
478 | * @param cont_cls closure for @a cont | ||
479 | * @return handle to abort the operation | ||
480 | */ | ||
481 | struct GNUNET_IDENTITY_PROVIDER_Operation * | ||
482 | GNUNET_IDENTITY_PROVIDER_exchange_ticket (struct GNUNET_IDENTITY_PROVIDER_Handle *id, | ||
483 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
484 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *aud_privkey, | ||
485 | GNUNET_IDENTITY_PROVIDER_ExchangeCallback cont, | ||
486 | void *cont_cls) | ||
487 | { | ||
488 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
489 | struct ExchangeMessage *em; | ||
490 | size_t slen; | ||
491 | char *ticket_str; | ||
492 | |||
493 | ticket_str = GNUNET_IDENTITY_PROVIDER_ticket_to_string (ticket); | ||
494 | |||
495 | slen = strlen (ticket_str) + 1; | ||
496 | if (slen >= GNUNET_MAX_MESSAGE_SIZE - sizeof (struct ExchangeMessage)) | ||
497 | { | ||
498 | GNUNET_free (ticket_str); | ||
499 | GNUNET_break (0); | ||
500 | return NULL; | ||
501 | } | ||
502 | op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation); | ||
503 | op->h = id; | ||
504 | op->ex_cb = cont; | ||
505 | op->cls = cont_cls; | ||
506 | op->r_id = id->r_id_gen++; | ||
507 | op->env = GNUNET_MQ_msg_extra (em, | ||
508 | slen, | ||
509 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE); | ||
510 | em->aud_privkey = *aud_privkey; | ||
511 | em->id = htonl (op->r_id); | ||
512 | GNUNET_memcpy (&em[1], ticket_str, slen); | ||
513 | GNUNET_free (ticket_str); | ||
514 | GNUNET_CONTAINER_DLL_insert_tail (id->op_head, | ||
515 | id->op_tail, | ||
516 | op); | ||
517 | if (NULL != id->mq) | ||
518 | GNUNET_MQ_send_copy (id->mq, | ||
519 | op->env); | ||
520 | return op; | ||
521 | } | ||
522 | |||
523 | |||
524 | /** | ||
525 | * Cancel an operation. Note that the operation MAY still | 848 | * Cancel an operation. Note that the operation MAY still |
526 | * be executed; this merely cancels the continuation; if the request | 849 | * be executed; this merely cancels the continuation; if the request |
527 | * was already transmitted, the service may still choose to complete | 850 | * was already transmitted, the service may still choose to complete |
@@ -566,80 +889,482 @@ GNUNET_IDENTITY_PROVIDER_disconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h) | |||
566 | } | 889 | } |
567 | 890 | ||
568 | /** | 891 | /** |
569 | * Convenience API | 892 | * Store an attribute. If the attribute is already present, |
893 | * it is replaced with the new attribute. | ||
894 | * | ||
895 | * @param h handle to the identity provider | ||
896 | * @param pkey private key of the identity | ||
897 | * @param attr the attribute value | ||
898 | * @param cont continuation to call when done | ||
899 | * @param cont_cls closure for @a cont | ||
900 | * @return handle to abort the request | ||
570 | */ | 901 | */ |
902 | struct GNUNET_IDENTITY_PROVIDER_Operation * | ||
903 | GNUNET_IDENTITY_PROVIDER_attribute_store (struct GNUNET_IDENTITY_PROVIDER_Handle *h, | ||
904 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey, | ||
905 | const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr, | ||
906 | GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cont, | ||
907 | void *cont_cls) | ||
908 | { | ||
909 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
910 | struct AttributeStoreMessage *sam; | ||
911 | size_t attr_len; | ||
912 | |||
913 | op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation); | ||
914 | op->h = h; | ||
915 | op->as_cb = cont; | ||
916 | op->cls = cont_cls; | ||
917 | op->r_id = h->r_id_gen++; | ||
918 | GNUNET_CONTAINER_DLL_insert_tail (h->op_head, | ||
919 | h->op_tail, | ||
920 | op); | ||
921 | attr_len = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (attr); | ||
922 | op->env = GNUNET_MQ_msg_extra (sam, | ||
923 | attr_len, | ||
924 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE); | ||
925 | sam->identity = *pkey; | ||
926 | sam->id = htonl (op->r_id); | ||
927 | |||
928 | GNUNET_IDENTITY_ATTRIBUTE_serialize (attr, | ||
929 | (char*)&sam[1]); | ||
930 | |||
931 | sam->attr_len = htons (attr_len); | ||
932 | if (NULL != h->mq) | ||
933 | GNUNET_MQ_send_copy (h->mq, | ||
934 | op->env); | ||
935 | return op; | ||
936 | |||
937 | } | ||
938 | |||
939 | |||
940 | /** | ||
941 | * List all attributes for a local identity. | ||
942 | * This MUST lock the `struct GNUNET_IDENTITY_PROVIDER_Handle` | ||
943 | * for any other calls than #GNUNET_IDENTITY_PROVIDER_get_attributes_next() and | ||
944 | * #GNUNET_IDENTITY_PROVIDER_get_attributes_stop. @a proc will be called once | ||
945 | * immediately, and then again after | ||
946 | * #GNUNET_IDENTITY_PROVIDER_get_attributes_next() is invoked. | ||
947 | * | ||
948 | * On error (disconnect), @a error_cb will be invoked. | ||
949 | * On normal completion, @a finish_cb proc will be | ||
950 | * invoked. | ||
951 | * | ||
952 | * @param h handle to the idp | ||
953 | * @param identity identity to access | ||
954 | * @param error_cb function to call on error (i.e. disconnect), | ||
955 | * the handle is afterwards invalid | ||
956 | * @param error_cb_cls closure for @a error_cb | ||
957 | * @param proc function to call on each attribute; it | ||
958 | * will be called repeatedly with a value (if available) | ||
959 | * @param proc_cls closure for @a proc | ||
960 | * @param finish_cb function to call on completion | ||
961 | * the handle is afterwards invalid | ||
962 | * @param finish_cb_cls closure for @a finish_cb | ||
963 | * @return an iterator handle to use for iteration | ||
964 | */ | ||
965 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator * | ||
966 | GNUNET_IDENTITY_PROVIDER_get_attributes_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h, | ||
967 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, | ||
968 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
969 | void *error_cb_cls, | ||
970 | GNUNET_IDENTITY_PROVIDER_AttributeResult proc, | ||
971 | void *proc_cls, | ||
972 | GNUNET_SCHEDULER_TaskCallback finish_cb, | ||
973 | void *finish_cb_cls) | ||
974 | { | ||
975 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it; | ||
976 | struct GNUNET_MQ_Envelope *env; | ||
977 | struct AttributeIterationStartMessage *msg; | ||
978 | uint32_t rid; | ||
979 | |||
980 | rid = h->r_id_gen++; | ||
981 | it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator); | ||
982 | it->h = h; | ||
983 | it->error_cb = error_cb; | ||
984 | it->error_cb_cls = error_cb_cls; | ||
985 | it->finish_cb = finish_cb; | ||
986 | it->finish_cb_cls = finish_cb_cls; | ||
987 | it->proc = proc; | ||
988 | it->proc_cls = proc_cls; | ||
989 | it->r_id = rid; | ||
990 | it->identity = *identity; | ||
991 | GNUNET_CONTAINER_DLL_insert_tail (h->it_head, | ||
992 | h->it_tail, | ||
993 | it); | ||
994 | env = GNUNET_MQ_msg (msg, | ||
995 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START); | ||
996 | msg->id = htonl (rid); | ||
997 | msg->identity = *identity; | ||
998 | if (NULL == h->mq) | ||
999 | it->env = env; | ||
1000 | else | ||
1001 | GNUNET_MQ_send (h->mq, | ||
1002 | env); | ||
1003 | return it; | ||
1004 | } | ||
571 | 1005 | ||
572 | 1006 | ||
573 | /** | 1007 | /** |
574 | * Destroy token | 1008 | * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_get_attributes_start |
1009 | * for the next record. | ||
575 | * | 1010 | * |
576 | * @param token the token | 1011 | * @param it the iterator |
577 | */ | 1012 | */ |
578 | void | 1013 | void |
579 | GNUNET_IDENTITY_PROVIDER_token_destroy(struct GNUNET_IDENTITY_PROVIDER_Token *token) | 1014 | GNUNET_IDENTITY_PROVIDER_get_attributes_next (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it) |
1015 | { | ||
1016 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h; | ||
1017 | struct AttributeIterationNextMessage *msg; | ||
1018 | struct GNUNET_MQ_Envelope *env; | ||
1019 | |||
1020 | env = GNUNET_MQ_msg (msg, | ||
1021 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT); | ||
1022 | msg->id = htonl (it->r_id); | ||
1023 | GNUNET_MQ_send (h->mq, | ||
1024 | env); | ||
1025 | } | ||
1026 | |||
1027 | |||
1028 | /** | ||
1029 | * Stops iteration and releases the idp handle for further calls. Must | ||
1030 | * be called on any iteration that has not yet completed prior to calling | ||
1031 | * #GNUNET_IDENTITY_PROVIDER_disconnect. | ||
1032 | * | ||
1033 | * @param it the iterator | ||
1034 | */ | ||
1035 | void | ||
1036 | GNUNET_IDENTITY_PROVIDER_get_attributes_stop (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it) | ||
1037 | { | ||
1038 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h; | ||
1039 | struct GNUNET_MQ_Envelope *env; | ||
1040 | struct AttributeIterationStopMessage *msg; | ||
1041 | |||
1042 | if (NULL != h->mq) | ||
1043 | { | ||
1044 | env = GNUNET_MQ_msg (msg, | ||
1045 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP); | ||
1046 | msg->id = htonl (it->r_id); | ||
1047 | GNUNET_MQ_send (h->mq, | ||
1048 | env); | ||
1049 | } | ||
1050 | free_it (it); | ||
1051 | } | ||
1052 | |||
1053 | |||
1054 | /** TODO | ||
1055 | * Issues a ticket to another identity. The identity may use | ||
1056 | * @GNUNET_IDENTITY_PROVIDER_authorization_ticket_consume to consume the ticket | ||
1057 | * and retrieve the attributes specified in the AttributeList. | ||
1058 | * | ||
1059 | * @param h the identity provider to use | ||
1060 | * @param iss the issuing identity | ||
1061 | * @param rp the subject of the ticket (the relying party) | ||
1062 | * @param attrs the attributes that the relying party is given access to | ||
1063 | * @param cb the callback | ||
1064 | * @param cb_cls the callback closure | ||
1065 | * @return handle to abort the operation | ||
1066 | */ | ||
1067 | struct GNUNET_IDENTITY_PROVIDER_Operation * | ||
1068 | GNUNET_IDENTITY_PROVIDER_ticket_issue (struct GNUNET_IDENTITY_PROVIDER_Handle *h, | ||
1069 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss, | ||
1070 | const struct GNUNET_CRYPTO_EcdsaPublicKey *rp, | ||
1071 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs, | ||
1072 | GNUNET_IDENTITY_PROVIDER_TicketCallback cb, | ||
1073 | void *cb_cls) | ||
1074 | { | ||
1075 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
1076 | struct IssueTicketMessage *tim; | ||
1077 | size_t attr_len; | ||
1078 | |||
1079 | op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation); | ||
1080 | op->h = h; | ||
1081 | op->tr_cb = cb; | ||
1082 | op->cls = cb_cls; | ||
1083 | op->r_id = h->r_id_gen++; | ||
1084 | GNUNET_CONTAINER_DLL_insert_tail (h->op_head, | ||
1085 | h->op_tail, | ||
1086 | op); | ||
1087 | attr_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (attrs); | ||
1088 | op->env = GNUNET_MQ_msg_extra (tim, | ||
1089 | attr_len, | ||
1090 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET); | ||
1091 | tim->identity = *iss; | ||
1092 | tim->rp = *rp; | ||
1093 | tim->id = htonl (op->r_id); | ||
1094 | |||
1095 | GNUNET_IDENTITY_ATTRIBUTE_list_serialize (attrs, | ||
1096 | (char*)&tim[1]); | ||
1097 | |||
1098 | tim->attr_len = htons (attr_len); | ||
1099 | if (NULL != h->mq) | ||
1100 | GNUNET_MQ_send_copy (h->mq, | ||
1101 | op->env); | ||
1102 | return op; | ||
1103 | } | ||
1104 | |||
1105 | /** | ||
1106 | * Consumes an issued ticket. The ticket is persisted | ||
1107 | * and used to retrieve identity information from the issuer | ||
1108 | * | ||
1109 | * @param h the identity provider to use | ||
1110 | * @param identity the identity that is the subject of the issued ticket (the relying party) | ||
1111 | * @param ticket the issued ticket to consume | ||
1112 | * @param cb the callback to call | ||
1113 | * @param cb_cls the callback closure | ||
1114 | * @return handle to abort the operation | ||
1115 | */ | ||
1116 | struct GNUNET_IDENTITY_PROVIDER_Operation * | ||
1117 | GNUNET_IDENTITY_PROVIDER_ticket_consume (struct GNUNET_IDENTITY_PROVIDER_Handle *h, | ||
1118 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, | ||
1119 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
1120 | GNUNET_IDENTITY_PROVIDER_AttributeResult cb, | ||
1121 | void *cb_cls) | ||
580 | { | 1122 | { |
581 | GNUNET_assert (NULL != token); | 1123 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; |
582 | if (NULL != token->data) | 1124 | struct ConsumeTicketMessage *ctm; |
583 | GNUNET_free (token->data); | 1125 | |
584 | GNUNET_free (token); | 1126 | op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation); |
1127 | op->h = h; | ||
1128 | op->ar_cb = cb; | ||
1129 | op->cls = cb_cls; | ||
1130 | op->r_id = h->r_id_gen++; | ||
1131 | GNUNET_CONTAINER_DLL_insert_tail (h->op_head, | ||
1132 | h->op_tail, | ||
1133 | op); | ||
1134 | op->env = GNUNET_MQ_msg_extra (ctm, | ||
1135 | sizeof (const struct GNUNET_IDENTITY_PROVIDER_Ticket), | ||
1136 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET); | ||
1137 | ctm->identity = *identity; | ||
1138 | ctm->id = htonl (op->r_id); | ||
1139 | |||
1140 | GNUNET_memcpy ((char*)&ctm[1], | ||
1141 | ticket, | ||
1142 | sizeof (const struct GNUNET_IDENTITY_PROVIDER_Ticket)); | ||
1143 | |||
1144 | if (NULL != h->mq) | ||
1145 | GNUNET_MQ_send_copy (h->mq, | ||
1146 | op->env); | ||
1147 | return op; | ||
1148 | |||
585 | } | 1149 | } |
586 | 1150 | ||
1151 | |||
587 | /** | 1152 | /** |
588 | * Returns string representation of token. A JSON-Web-Token. | 1153 | * Lists all tickets that have been issued to remote |
1154 | * identites (relying parties) | ||
589 | * | 1155 | * |
590 | * @param token the token | 1156 | * @param h the identity provider to use |
591 | * @return The JWT (must be freed) | 1157 | * @param identity the issuing identity |
1158 | * @param error_cb function to call on error (i.e. disconnect), | ||
1159 | * the handle is afterwards invalid | ||
1160 | * @param error_cb_cls closure for @a error_cb | ||
1161 | * @param proc function to call on each ticket; it | ||
1162 | * will be called repeatedly with a value (if available) | ||
1163 | * @param proc_cls closure for @a proc | ||
1164 | * @param finish_cb function to call on completion | ||
1165 | * the handle is afterwards invalid | ||
1166 | * @param finish_cb_cls closure for @a finish_cb | ||
1167 | * @return an iterator handle to use for iteration | ||
592 | */ | 1168 | */ |
593 | char * | 1169 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator * |
594 | GNUNET_IDENTITY_PROVIDER_token_to_string (const struct GNUNET_IDENTITY_PROVIDER_Token *token) | 1170 | GNUNET_IDENTITY_PROVIDER_ticket_iteration_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h, |
1171 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, | ||
1172 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
1173 | void *error_cb_cls, | ||
1174 | GNUNET_IDENTITY_PROVIDER_TicketCallback proc, | ||
1175 | void *proc_cls, | ||
1176 | GNUNET_SCHEDULER_TaskCallback finish_cb, | ||
1177 | void *finish_cb_cls) | ||
595 | { | 1178 | { |
596 | return GNUNET_strdup (token->data); | 1179 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it; |
1180 | struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub; | ||
1181 | struct GNUNET_MQ_Envelope *env; | ||
1182 | struct TicketIterationStartMessage *msg; | ||
1183 | uint32_t rid; | ||
1184 | |||
1185 | GNUNET_CRYPTO_ecdsa_key_get_public (identity, | ||
1186 | &identity_pub); | ||
1187 | rid = h->r_id_gen++; | ||
1188 | it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_TicketIterator); | ||
1189 | it->h = h; | ||
1190 | it->error_cb = error_cb; | ||
1191 | it->error_cb_cls = error_cb_cls; | ||
1192 | it->finish_cb = finish_cb; | ||
1193 | it->finish_cb_cls = finish_cb_cls; | ||
1194 | it->tr_cb = proc; | ||
1195 | it->cls = proc_cls; | ||
1196 | it->r_id = rid; | ||
1197 | GNUNET_CONTAINER_DLL_insert_tail (h->ticket_it_head, | ||
1198 | h->ticket_it_tail, | ||
1199 | it); | ||
1200 | env = GNUNET_MQ_msg (msg, | ||
1201 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START); | ||
1202 | msg->id = htonl (rid); | ||
1203 | msg->identity = identity_pub; | ||
1204 | msg->is_audience = htonl (GNUNET_NO); | ||
1205 | if (NULL == h->mq) | ||
1206 | it->env = env; | ||
1207 | else | ||
1208 | GNUNET_MQ_send (h->mq, | ||
1209 | env); | ||
1210 | return it; | ||
1211 | |||
597 | } | 1212 | } |
598 | 1213 | ||
1214 | |||
599 | /** | 1215 | /** |
600 | * Returns string representation of ticket. Base64-Encoded | 1216 | * Lists all tickets that have been issued to remote |
1217 | * identites (relying parties) | ||
601 | * | 1218 | * |
602 | * @param ticket the ticket | 1219 | * @param h the identity provider to use |
603 | * @return the Base64-Encoded ticket | 1220 | * @param identity the issuing identity |
1221 | * @param error_cb function to call on error (i.e. disconnect), | ||
1222 | * the handle is afterwards invalid | ||
1223 | * @param error_cb_cls closure for @a error_cb | ||
1224 | * @param proc function to call on each ticket; it | ||
1225 | * will be called repeatedly with a value (if available) | ||
1226 | * @param proc_cls closure for @a proc | ||
1227 | * @param finish_cb function to call on completion | ||
1228 | * the handle is afterwards invalid | ||
1229 | * @param finish_cb_cls closure for @a finish_cb | ||
1230 | * @return an iterator handle to use for iteration | ||
604 | */ | 1231 | */ |
605 | char * | 1232 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator * |
606 | GNUNET_IDENTITY_PROVIDER_ticket_to_string (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket) | 1233 | GNUNET_IDENTITY_PROVIDER_ticket_iteration_start_rp (struct GNUNET_IDENTITY_PROVIDER_Handle *h, |
1234 | const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, | ||
1235 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
1236 | void *error_cb_cls, | ||
1237 | GNUNET_IDENTITY_PROVIDER_TicketCallback proc, | ||
1238 | void *proc_cls, | ||
1239 | GNUNET_SCHEDULER_TaskCallback finish_cb, | ||
1240 | void *finish_cb_cls) | ||
607 | { | 1241 | { |
608 | return GNUNET_strdup (ticket->data); | 1242 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it; |
1243 | struct GNUNET_MQ_Envelope *env; | ||
1244 | struct TicketIterationStartMessage *msg; | ||
1245 | uint32_t rid; | ||
1246 | |||
1247 | rid = h->r_id_gen++; | ||
1248 | it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_TicketIterator); | ||
1249 | it->h = h; | ||
1250 | it->error_cb = error_cb; | ||
1251 | it->error_cb_cls = error_cb_cls; | ||
1252 | it->finish_cb = finish_cb; | ||
1253 | it->finish_cb_cls = finish_cb_cls; | ||
1254 | it->tr_cb = proc; | ||
1255 | it->cls = proc_cls; | ||
1256 | it->r_id = rid; | ||
1257 | GNUNET_CONTAINER_DLL_insert_tail (h->ticket_it_head, | ||
1258 | h->ticket_it_tail, | ||
1259 | it); | ||
1260 | env = GNUNET_MQ_msg (msg, | ||
1261 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START); | ||
1262 | msg->id = htonl (rid); | ||
1263 | msg->identity = *identity; | ||
1264 | msg->is_audience = htonl (GNUNET_YES); | ||
1265 | if (NULL == h->mq) | ||
1266 | it->env = env; | ||
1267 | else | ||
1268 | GNUNET_MQ_send (h->mq, | ||
1269 | env); | ||
1270 | return it; | ||
1271 | |||
1272 | |||
609 | } | 1273 | } |
610 | 1274 | ||
611 | /** | 1275 | /** |
612 | * Created a ticket from a string (Base64 encoded ticket) | 1276 | * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_ticket_iteration_start |
1277 | * for the next record. | ||
613 | * | 1278 | * |
614 | * @param input Base64 encoded ticket | 1279 | * @param it the iterator |
615 | * @param ticket pointer where the ticket is stored | ||
616 | * @return GNUNET_OK | ||
617 | */ | 1280 | */ |
618 | int | 1281 | void |
619 | GNUNET_IDENTITY_PROVIDER_string_to_ticket (const char* input, | 1282 | GNUNET_IDENTITY_PROVIDER_ticket_iteration_next (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it) |
620 | struct GNUNET_IDENTITY_PROVIDER_Ticket **ticket) | ||
621 | { | 1283 | { |
622 | *ticket = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket)); | 1284 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h; |
623 | (*ticket)->data = GNUNET_strdup (input); | 1285 | struct TicketIterationNextMessage *msg; |
624 | return GNUNET_OK; | 1286 | struct GNUNET_MQ_Envelope *env; |
1287 | |||
1288 | env = GNUNET_MQ_msg (msg, | ||
1289 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT); | ||
1290 | msg->id = htonl (it->r_id); | ||
1291 | GNUNET_MQ_send (h->mq, | ||
1292 | env); | ||
625 | } | 1293 | } |
626 | 1294 | ||
627 | 1295 | ||
628 | /** | 1296 | /** |
629 | * Destroys a ticket | 1297 | * Stops iteration and releases the idp handle for further calls. Must |
1298 | * be called on any iteration that has not yet completed prior to calling | ||
1299 | * #GNUNET_IDENTITY_PROVIDER_disconnect. | ||
630 | * | 1300 | * |
631 | * @param ticket the ticket to destroy | 1301 | * @param it the iterator |
632 | */ | 1302 | */ |
633 | void | 1303 | void |
634 | GNUNET_IDENTITY_PROVIDER_ticket_destroy(struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket) | 1304 | GNUNET_IDENTITY_PROVIDER_ticket_iteration_stop (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it) |
635 | { | 1305 | { |
636 | GNUNET_assert (NULL != ticket); | 1306 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h; |
637 | if (NULL != ticket->data) | 1307 | struct GNUNET_MQ_Envelope *env; |
638 | GNUNET_free (ticket->data); | 1308 | struct TicketIterationStopMessage *msg; |
639 | GNUNET_free (ticket); | 1309 | |
1310 | if (NULL != h->mq) | ||
1311 | { | ||
1312 | env = GNUNET_MQ_msg (msg, | ||
1313 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP); | ||
1314 | msg->id = htonl (it->r_id); | ||
1315 | GNUNET_MQ_send (h->mq, | ||
1316 | env); | ||
1317 | } | ||
1318 | GNUNET_free (it); | ||
640 | } | 1319 | } |
641 | 1320 | ||
1321 | /** | ||
1322 | * Revoked an issued ticket. The relying party will be unable to retrieve | ||
1323 | * updated attributes. | ||
1324 | * | ||
1325 | * @param h the identity provider to use | ||
1326 | * @param identity the issuing identity | ||
1327 | * @param ticket the ticket to revoke | ||
1328 | * @param cb the callback | ||
1329 | * @param cb_cls the callback closure | ||
1330 | * @return handle to abort the operation | ||
1331 | */ | ||
1332 | struct GNUNET_IDENTITY_PROVIDER_Operation * | ||
1333 | GNUNET_IDENTITY_PROVIDER_ticket_revoke (struct GNUNET_IDENTITY_PROVIDER_Handle *h, | ||
1334 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, | ||
1335 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
1336 | GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cb, | ||
1337 | void *cb_cls) | ||
1338 | { | ||
1339 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
1340 | struct GNUNET_MQ_Envelope *env; | ||
1341 | struct RevokeTicketMessage *msg; | ||
1342 | uint32_t rid; | ||
642 | 1343 | ||
1344 | rid = h->r_id_gen++; | ||
1345 | op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation); | ||
1346 | op->h = h; | ||
1347 | op->rvk_cb = cb; | ||
1348 | op->cls = cb_cls; | ||
1349 | op->r_id = rid; | ||
1350 | GNUNET_CONTAINER_DLL_insert_tail (h->op_head, | ||
1351 | h->op_tail, | ||
1352 | op); | ||
1353 | env = GNUNET_MQ_msg_extra (msg, | ||
1354 | sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket), | ||
1355 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET); | ||
1356 | msg->id = htonl (rid); | ||
1357 | msg->identity = *identity; | ||
1358 | memcpy (&msg[1], | ||
1359 | ticket, | ||
1360 | sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket)); | ||
1361 | if (NULL == h->mq) | ||
1362 | op->env = env; | ||
1363 | else | ||
1364 | GNUNET_MQ_send (h->mq, | ||
1365 | env); | ||
1366 | return op; | ||
1367 | } | ||
643 | 1368 | ||
644 | 1369 | ||
645 | 1370 | ||