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