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