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