-various fixes; add attribute list API
[oweals/gnunet.git] / src / identity-provider / gnunet-service-identity-provider.c
1 /*
2    This file is part of GNUnet.
3    Copyright (C) 2012-2015 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 License 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 License for more details.
14
15    You should have received a copy of the GNU General Public License
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  * @author Martin Schanzenbach
22  * @file src/identity-provider/gnunet-service-identity-provider.c
23  * @brief Identity Token Service
24  *
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_constants.h"
29 #include "gnunet_protocols.h"
30 #include "gnunet_identity_service.h"
31 #include "gnunet_gnsrecord_lib.h"
32 #include "gnunet_namestore_service.h"
33 #include "gnunet_credential_service.h"
34 #include "gnunet_statistics_service.h"
35 #include "gnunet_gns_service.h"
36 #include "gnunet_signatures.h"
37 #include "identity_provider.h"
38 #include "identity_token.h"
39 #include "identity_attribute.h"
40 #include <inttypes.h>
41
42 /**
43  * First pass state
44  */
45 #define STATE_INIT 0
46
47 /**
48  * Normal operation state
49  */
50 #define STATE_POST_INIT 1
51
52 /**
53  * Minimum interval between updates
54  */
55 #define MIN_WAIT_TIME GNUNET_TIME_UNIT_MINUTES
56
57 /**
58  * Standard token expiration time
59  */
60 #define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS
61
62 /**
63  * Identity handle
64  */
65 static struct GNUNET_IDENTITY_Handle *identity_handle;
66
67 /**
68  * Token expiration interval
69  */
70 static struct GNUNET_TIME_Relative token_expiration_interval;
71
72 /**
73  * Namestore handle
74  */
75 static struct GNUNET_NAMESTORE_Handle *ns_handle;
76
77 /**
78  * GNS handle
79  */
80 static struct GNUNET_GNS_Handle *gns_handle;
81
82 /**
83  * Credential handle
84  */
85 static struct GNUNET_CREDENTIAL_Handle *credential_handle;
86
87 /**
88  * Namestore qe
89  */
90 static struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
91
92 /**
93  * Namestore iterator
94  */
95 static struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
96
97 /**
98  * Timeout task
99  */
100 static struct GNUNET_SCHEDULER_Task *timeout_task;
101
102 /**
103  * Update task
104  */
105 static struct GNUNET_SCHEDULER_Task *update_task;
106
107
108 /**
109  * Currently processed token
110  */
111 static struct IdentityToken *token;
112
113 /**
114  * Label for currently processed token
115  */
116 static char* label;
117
118 /**
119  * Scopes for processed token
120  */
121 static char* scopes;
122
123 /**
124  * Handle to the statistics service.
125  */
126 static struct GNUNET_STATISTICS_Handle *stats;
127
128 /**
129  * Our configuration.
130  */
131 static const struct GNUNET_CONFIGURATION_Handle *cfg;
132
133 /**
134  * An idp client
135  */
136 struct IdpClient;
137
138 /**
139  * Callback after an ABE bootstrap
140  *
141  * @param cls closure
142  * @param abe_key the ABE key that exists or was created
143  */
144 typedef void
145 (*AbeBootstrapResult) (void *cls,
146                        struct GNUNET_CRYPTO_AbeMasterKey *abe_key);
147
148
149 struct AbeBootstrapHandle
150 {
151   /**
152    * Function to call when finished
153    */
154   AbeBootstrapResult proc;
155
156   /**
157    * Callback closure
158    */
159   char *proc_cls;
160
161   /**
162    * Key of the zone we are iterating over.
163    */
164   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
165
166   /**
167    * Namestore Queue Entry
168    */
169   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
170
171   /**
172    * The issuer egos ABE master key
173    */
174   struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
175 };
176
177 /**
178  * An attribute iteration operation.
179  */
180 struct AttributeIterator
181 {
182   /**
183    * Next element in the DLL
184    */
185   struct AttributeIterator *next;
186
187   /**
188    * Previous element in the DLL
189    */
190   struct AttributeIterator *prev;
191
192   /**
193    * IDP client which intiated this zone iteration
194    */
195   struct IdpClient *client;
196
197   /**
198    * Key of the zone we are iterating over.
199    */
200   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
201
202   /**
203    * The issuer egos ABE master key
204    */
205   struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
206
207   /**
208    * Namestore iterator
209    */
210   struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
211
212   /**
213    * The operation id fot the zone iteration in the response for the client
214    */
215   uint32_t request_id;
216
217 };
218
219
220
221 /**
222  * An idp client
223  */
224 struct IdpClient
225 {
226
227   /**
228    * The client
229    */
230   struct GNUNET_SERVICE_Client *client;
231
232   /**
233    * Message queue for transmission to @e client
234    */
235   struct GNUNET_MQ_Handle *mq;
236   
237   /**
238    * Head of the DLL of
239    * Attribute iteration operations in 
240    * progress initiated by this client
241    */
242   struct AttributeIterator *op_head;
243
244   /**
245    * Tail of the DLL of
246    * Attribute iteration operations 
247    * in progress initiated by this client
248    */
249   struct AttributeIterator *op_tail;
250 };
251
252
253
254 struct AttributeStoreHandle
255 {
256
257   /**
258    * Client connection
259    */
260   struct IdpClient *client;
261
262   /**
263    * Identity
264    */
265   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
266
267   /**
268    * Identity pubkey
269    */
270   struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
271
272   /**
273    * The issuer egos ABE master key
274    */
275   struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
276
277   /**
278    * QueueEntry
279    */
280   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
281
282   /**
283    * The attribute to store
284    */
285   struct GNUNET_IDENTITY_PROVIDER_Attribute *attribute;
286
287   /**
288    * request id
289    */
290   uint32_t r_id;
291 };
292
293
294
295 struct VerifiedAttributeEntry
296 {
297   /**
298    * DLL
299    */
300   struct VerifiedAttributeEntry *prev;
301
302   /**
303    * DLL
304    */
305   struct VerifiedAttributeEntry *next;
306
307   /**
308    * Attribute Name
309    */
310   char* name;
311 };
312
313 struct ParallelLookups;
314
315 struct ExchangeHandle
316 {
317
318   /**
319    * Client connection
320    */
321   struct IdpClient *client;
322
323   /**
324    * Ticket
325    */
326   struct TokenTicket *ticket;
327
328   /**
329    * Token returned
330    */
331   struct IdentityToken *token;
332
333   /**
334    * LookupRequest
335    */
336   struct GNUNET_GNS_LookupRequest *lookup_request;
337
338   /**
339    * Audience Key
340    */
341   struct GNUNET_CRYPTO_EcdsaPrivateKey aud_privkey;
342   
343   /**
344    * ParallelLookups DLL
345    */
346   struct ParallelLookup *parallel_lookups_head;
347   struct ParallelLookup *parallel_lookups_tail;
348   
349   struct GNUNET_SCHEDULER_Task *kill_task;
350   struct GNUNET_CRYPTO_AbeKey *key;
351
352   /**
353    * Label to return
354    */
355   char *label;
356
357   /**
358    * request id
359    */
360   uint32_t r_id;
361 };
362
363 struct ParallelLookup
364 {
365   struct ParallelLookup *next;
366
367   struct ParallelLookup *prev;
368
369   struct GNUNET_GNS_LookupRequest *lookup_request;
370
371   struct ExchangeHandle *handle;
372
373   char *label;
374 };
375
376 struct IssueHandle
377 {
378
379   /**
380    * Client connection
381    */
382   struct IdpClient *client;
383
384   /**
385    * Issuer Key
386    */
387   struct GNUNET_CRYPTO_EcdsaPrivateKey iss_key;
388
389   /**
390    * Issue pubkey
391    */
392   struct GNUNET_CRYPTO_EcdsaPublicKey iss_pkey;
393
394   /**
395    * Audience Key
396    */
397   struct GNUNET_CRYPTO_EcdsaPublicKey aud_key;
398
399   /**
400    * The issuer egos ABE master key
401    */
402   struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
403
404   /**
405    * Expiration
406    */
407   struct GNUNET_TIME_Absolute expiration;
408
409   /**
410    * Scopes
411    */
412   char *scopes;
413
414   /**
415    * DLL
416    */
417   struct VerifiedAttributeEntry *v_attr_head;
418
419   /**
420    * DLL
421    */
422   struct VerifiedAttributeEntry *v_attr_tail;
423
424   /**
425    * nonce
426    */
427   uint64_t nonce;
428
429   /**
430    * NS iterator
431    */
432   struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
433
434   /**
435    * Cred request
436    */
437   struct GNUNET_CREDENTIAL_Request *credential_request;
438
439   /**
440    * Attribute map
441    */
442   struct GNUNET_CONTAINER_MultiHashMap *attr_map;
443
444   /**
445    * Token
446    */
447   struct IdentityToken *token;
448
449   /**
450    * Ticket
451    */
452   struct TokenTicket *ticket;
453
454   /**
455    * QueueEntry
456    */
457   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
458
459   /**
460    * The label the token is stored under
461    */
462   char *label;
463
464   /**
465    * request id
466    */
467   uint32_t r_id;
468 };
469
470 /**
471  * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format
472  *
473  */
474 struct EgoEntry
475 {
476   /**
477    * DLL
478    */
479   struct EgoEntry *next;
480
481   /**
482    * DLL
483    */
484   struct EgoEntry *prev;
485
486   /**
487    * Ego handle
488    */
489   struct GNUNET_IDENTITY_Ego *ego;
490
491   /**
492    * Attribute map. Contains the attributes as json_t
493    */
494   struct GNUNET_CONTAINER_MultiHashMap *attr_map;
495
496 };
497
498 /**
499  * Cleanup task
500  */
501 static void
502 cleanup()
503 {
504   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
505               "Cleaning up\n");
506   if (NULL != stats)
507   {
508     GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
509     stats = NULL;
510   }
511
512   if (NULL != timeout_task)
513     GNUNET_SCHEDULER_cancel (timeout_task);
514   if (NULL != update_task)
515     GNUNET_SCHEDULER_cancel (update_task);
516   if (NULL != identity_handle)
517     GNUNET_IDENTITY_disconnect (identity_handle);
518   if (NULL != gns_handle)
519     GNUNET_GNS_disconnect (gns_handle);
520   if (NULL != credential_handle)
521     GNUNET_CREDENTIAL_disconnect (credential_handle);
522   if (NULL != ns_it)
523     GNUNET_NAMESTORE_zone_iteration_stop (ns_it);
524   if (NULL != ns_qe)
525     GNUNET_NAMESTORE_cancel (ns_qe);
526   if (NULL != ns_handle)
527     GNUNET_NAMESTORE_disconnect (ns_handle);
528   if (NULL != token)
529     GNUNET_free (token);
530   if (NULL != label)
531     GNUNET_free (label);
532
533 }
534
535 /**
536  * Shutdown task
537  *
538  * @param cls NULL
539  * @param tc task context
540  */
541 static void
542 do_shutdown (void *cls)
543 {
544   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
545               "Shutting down...\n");
546   cleanup();
547 }
548
549
550 static struct GNUNET_MQ_Envelope*
551 create_exchange_result_message (const char* token,
552                                 const char* label,
553                                 uint64_t ticket_nonce,
554                                 uint64_t id)
555 {
556   struct GNUNET_MQ_Envelope *env;
557   struct ExchangeResultMessage *erm;
558   uint16_t token_len = strlen (token) + 1;
559
560   env = GNUNET_MQ_msg_extra (erm,
561                              token_len,
562                              GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT);
563   erm->ticket_nonce = htonl (ticket_nonce);
564   erm->id = id;
565   GNUNET_memcpy (&erm[1], token, token_len);
566   return env;
567 }
568
569
570 static struct GNUNET_MQ_Envelope*
571 create_issue_result_message (const char* label,
572                              const char* ticket,
573                              const char* token,
574                              uint64_t id)
575 {
576   struct GNUNET_MQ_Envelope *env;
577   struct IssueResultMessage *irm;
578   char *tmp_str;
579   size_t len;
580
581   GNUNET_asprintf (&tmp_str, "%s,%s,%s", label, ticket, token);
582   len = strlen (tmp_str) + 1;
583   env = GNUNET_MQ_msg_extra (irm,
584                              len,
585                              GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT);
586   irm->id = id;
587   GNUNET_memcpy (&irm[1], tmp_str, strlen (tmp_str) + 1);
588   GNUNET_free (tmp_str);
589   return env;
590 }
591
592 static void
593 cleanup_issue_handle (struct IssueHandle *handle)
594 {
595   if (NULL != handle->attr_map)
596     GNUNET_CONTAINER_multihashmap_destroy (handle->attr_map);
597   if (NULL != handle->scopes)
598     GNUNET_free (handle->scopes);
599   if (NULL != handle->token)
600     token_destroy (handle->token);
601   if (NULL != handle->ticket)
602     ticket_destroy (handle->ticket);
603   if (NULL != handle->label)
604     GNUNET_free (handle->label);
605   if (NULL != handle->ns_it)
606     GNUNET_NAMESTORE_zone_iteration_stop (handle->ns_it);
607   if (NULL != handle->credential_request)
608     GNUNET_CREDENTIAL_request_cancel (handle->credential_request);
609   GNUNET_free (handle);
610 }
611
612 static void
613 store_record_issue_cont (void *cls,
614                         int32_t success,
615                         const char *emsg)
616 {
617   struct IssueHandle *handle = cls;
618   struct GNUNET_MQ_Envelope *env;
619   char *ticket_str;
620   char *token_str;
621
622   handle->ns_qe = NULL;
623   if (GNUNET_SYSERR == success)
624   {
625     cleanup_issue_handle (handle);
626     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
627                 "Unknown Error\n");
628     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
629     return;
630   }
631   if (GNUNET_OK != ticket_serialize (handle->ticket,
632                                      &handle->iss_key,
633                                      &ticket_str))
634   {
635     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
636                 "Error serializing ticket\n");
637     cleanup_issue_handle (handle);
638     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
639     return;
640   }
641   if (GNUNET_OK != token_to_string (handle->token,
642                                     &handle->iss_key,
643                                     &token_str))
644   {
645     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
646                 "Error serializing token\n");
647     GNUNET_free (ticket_str);
648     cleanup_issue_handle (handle);
649     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
650     return;
651   }
652   env = create_issue_result_message (handle->label,
653                                      ticket_str,
654                                      token_str,
655                                      handle->r_id);
656   GNUNET_MQ_send (handle->client->mq,
657                   env);
658   cleanup_issue_handle (handle);
659   GNUNET_free (ticket_str);
660   GNUNET_free (token_str);
661 }
662
663 static int
664 create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash,
665                          struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
666                          struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
667 {
668   struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str;
669
670   GNUNET_CRYPTO_hash_to_enc (new_key_hash,
671                              &new_key_hash_str);
672   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str);
673   static const char ctx_key[] = "gnuid-aes-ctx-key";
674   GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
675                      new_key_hash, sizeof (struct GNUNET_HashCode),
676                      ctx_key, strlen (ctx_key),
677                      NULL, 0);
678   static const char ctx_iv[] = "gnuid-aes-ctx-iv";
679   GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector),
680                      new_key_hash, sizeof (struct GNUNET_HashCode),
681                      ctx_iv, strlen (ctx_iv),
682                      NULL, 0);
683   return GNUNET_OK;
684 }
685
686 int
687 serialize_abe_keyinfo (const struct IssueHandle *handle,
688                  const struct GNUNET_CRYPTO_AbeKey *rp_key,
689                  struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
690                  char **result)
691 {
692   char *enc_keyinfo;
693   char *serialized_key;
694   char *buf;
695   struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
696   ssize_t size;
697   
698   struct GNUNET_CRYPTO_SymmetricSessionKey skey;
699   struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
700   struct GNUNET_HashCode new_key_hash;
701   ssize_t enc_size;
702   
703   size = GNUNET_CRYPTO_cpabe_serialize_key (rp_key,
704                                             (void**)&serialized_key);
705   buf = GNUNET_malloc (strlen (handle->scopes) + 1 + size);
706   GNUNET_memcpy (buf,
707                  handle->scopes,
708                  strlen (handle->scopes) + 1);
709   GNUNET_memcpy (buf + strlen (handle->scopes) + 1,
710                  serialized_key,
711                  size);
712   // ECDH keypair E = eG
713   *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
714   GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
715                                       &ecdh_pubkey);
716   enc_keyinfo = GNUNET_malloc (size + strlen (handle->scopes) + 1);
717   // Derived key K = H(eB)
718   GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
719                                                         &handle->aud_key,
720                                                         &new_key_hash));
721   create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
722   enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
723                                               size + strlen (handle->scopes) + 1,
724                                               &skey, &iv,
725                                               enc_keyinfo);
726   *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
727                            enc_size);
728   GNUNET_memcpy (*result,
729                  &ecdh_pubkey,
730                  sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
731   GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
732                  enc_keyinfo,
733                  enc_size);
734   GNUNET_free (enc_keyinfo);
735   return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
736 }
737
738 static void
739 cleanup_exchange_handle (struct ExchangeHandle *handle)
740 {
741   if (NULL != handle->ticket)
742     ticket_destroy (handle->ticket);
743   if (NULL != handle->token)
744     token_destroy (handle->token);
745   GNUNET_free (handle);
746 }
747
748
749 /**
750  * Build a token and store it
751  *
752  * @param cls the IssueHandle
753  */
754 static void
755 sign_and_return_token (void *cls)
756 {
757   struct ExchangeHandle *handle = cls;
758   struct GNUNET_MQ_Envelope *env;
759   char *token_str;
760   uint64_t time;
761   uint64_t exp_time;
762
763   time = GNUNET_TIME_absolute_get().abs_value_us;
764   exp_time = time + token_expiration_interval.rel_value_us;
765
766   token_add_attr_int (handle->token, "nbf", time);
767   token_add_attr_int (handle->token, "iat", time);
768   token_add_attr_int (handle->token, "exp", exp_time);
769   
770   //Readable
771   GNUNET_assert (GNUNET_OK == token_to_string (handle->token,
772                                                &handle->aud_privkey,
773                                                &token_str));
774
775   env = create_exchange_result_message (token_str,
776                                         handle->label,
777                                         handle->ticket->payload->nonce,
778                                         handle->r_id);
779   GNUNET_MQ_send (handle->client->mq,
780                   env);
781   cleanup_exchange_handle (handle);
782   GNUNET_free (token_str);
783
784 }
785
786 /**
787  * Build an ABE key and store it
788  *
789  * @param cls the IssueHandle
790  */
791 static void
792 issue_ticket (void *cls)
793 {
794   struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
795   struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
796   struct IssueHandle *handle = cls;
797   struct GNUNET_GNSRECORD_Data code_record[1];
798   struct GNUNET_CRYPTO_AbeKey *rp_key;
799   char *nonce_str;
800   char *code_record_data;
801   char **attrs;
802   char *scope;
803   char *scopes_tmp;
804   int attrs_len;
805   int i;
806   uint64_t time;
807   uint64_t exp_time;
808   size_t code_record_len;
809
810   //Remote nonce
811   nonce_str = NULL;
812   GNUNET_asprintf (&nonce_str, "%lu", handle->nonce);
813   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request nonce: %s\n", nonce_str);
814
815   GNUNET_CRYPTO_ecdsa_key_get_public (&handle->iss_key,
816                                       &pub_key);
817   handle->ticket = ticket_create (handle->nonce,
818                                   &pub_key,
819                                   handle->label,
820                                   &handle->aud_key);
821
822   time = GNUNET_TIME_absolute_get().abs_value_us;
823   exp_time = time + token_expiration_interval.rel_value_us;
824
825   token_add_attr_int (handle->token, "nbf", time);
826   token_add_attr_int (handle->token, "iat", time);
827   token_add_attr_int (handle->token, "exp", exp_time);
828   token_add_attr (handle->token, "nonce", nonce_str);
829
830   //Create new ABE key for RP
831   attrs_len = (GNUNET_CONTAINER_multihashmap_size (handle->attr_map) + 1) * sizeof (char*);
832   attrs = GNUNET_malloc (attrs_len);
833   i = 0;
834   scopes_tmp = GNUNET_strdup (handle->scopes);
835   for (scope = strtok (scopes_tmp, ","); NULL != scope; scope = strtok (NULL, ",")) {
836     attrs[i] = scope;
837     i++;
838   }
839   rp_key = GNUNET_CRYPTO_cpabe_create_key (handle->abe_key,
840                                            attrs);
841   code_record_len = serialize_abe_keyinfo (handle,
842                                            rp_key,
843                                            &ecdhe_privkey,
844                                            &code_record_data);
845   code_record[0].data = code_record_data;
846   code_record[0].data_size = code_record_len;
847   code_record[0].expiration_time = exp_time;
848   code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
849   code_record[0].flags = GNUNET_GNSRECORD_RF_NONE;
850
851
852   //Publish record
853   handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
854                                                   &handle->iss_key,
855                                                   handle->label,
856                                                   1,
857                                                   code_record,
858                                                   &store_record_issue_cont,
859                                                   handle);
860   GNUNET_free (ecdhe_privkey);
861   GNUNET_free (nonce_str);
862   GNUNET_free (code_record_data);
863 }
864
865 /**
866  * Credential to JSON
867  * @param cred the credential
868  * @return the resulting json, NULL if failed
869  */
870 static json_t*
871 credential_to_json (struct GNUNET_CREDENTIAL_Credential *cred)
872 {
873   char *issuer;
874   char *subject;
875   char *signature;
876   char attribute[cred->issuer_attribute_len + 1];
877   json_t *cred_obj;
878
879   issuer = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->issuer_key);
880   if (NULL == issuer)
881   {
882     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
883                 "Issuer in credential malformed\n");
884     return NULL;
885   }  
886   subject = GNUNET_CRYPTO_ecdsa_public_key_to_string (&cred->subject_key);
887   if (NULL == subject)
888   {
889     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
890                 "Subject in credential malformed\n");
891     GNUNET_free (issuer);
892     return NULL;
893   }
894   GNUNET_STRINGS_base64_encode ((char*)&cred->signature,
895                                 sizeof (struct GNUNET_CRYPTO_EcdsaSignature),
896                                 &signature);
897   memcpy (attribute,
898           cred->issuer_attribute,
899           cred->issuer_attribute_len);
900   attribute[cred->issuer_attribute_len] = '\0';
901   cred_obj = json_object ();
902   json_object_set_new (cred_obj, "issuer", json_string (issuer));
903   json_object_set_new (cred_obj, "subject", json_string (subject));
904   json_object_set_new (cred_obj, "attribute", json_string (attribute));
905   json_object_set_new (cred_obj, "signature", json_string (signature));
906   json_object_set_new (cred_obj, "expiration", json_integer (cred->expiration.abs_value_us));
907   GNUNET_free (issuer);
908   GNUNET_free (subject);
909   GNUNET_free (signature);
910   return cred_obj;
911 }
912
913
914 static void
915 handle_vattr_collection (void* cls,
916                          unsigned int d_count,
917                          struct GNUNET_CREDENTIAL_Delegation *dc,
918                          unsigned int c_count,
919                          struct GNUNET_CREDENTIAL_Credential *cred)
920 {
921   struct IssueHandle *handle = cls;
922   struct VerifiedAttributeEntry *vattr;
923   json_t *cred_json;
924   json_t *cred_array;
925   int i;
926   handle->credential_request = NULL;
927
928   if (NULL == cred)
929   {
930     GNUNET_SCHEDULER_add_now (&issue_ticket, handle);
931     return;
932   }
933   cred_array = json_array();
934   for (i=0;i<c_count;i++)
935   {
936     cred_json = credential_to_json (cred);
937     if (NULL == cred_json)
938       continue;
939     json_array_append (cred_array, cred_json);
940     token_add_attr_json (handle->token,
941                          handle->v_attr_head->name,
942                          cred_array);
943   }
944   json_decref (cred_array);
945   vattr = handle->v_attr_head;
946
947   GNUNET_CONTAINER_DLL_remove (handle->v_attr_head,
948                                handle->v_attr_tail,
949                                vattr);
950   GNUNET_free (vattr->name);
951   GNUNET_free (vattr);
952
953   if (NULL == handle->v_attr_head)
954   {
955     GNUNET_SCHEDULER_add_now (&issue_ticket, handle);
956     return;
957   }
958   handle->credential_request = GNUNET_CREDENTIAL_collect (credential_handle,
959                                                           &handle->aud_key,
960                                                           handle->v_attr_head->name,
961                                                           &handle->iss_key,
962                                                           &handle_vattr_collection,
963                                                           handle);
964
965 }
966
967
968 static void
969 attr_collect_error (void *cls)
970 {
971   struct IssueHandle *handle = cls;
972
973   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Adding attribute Error!\n");
974   handle->ns_it = NULL;
975   GNUNET_SCHEDULER_add_now (&issue_ticket, handle);
976 }
977
978
979 static void
980 attr_collect_finished (void *cls)
981 {
982   struct IssueHandle *handle = cls;
983
984   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute END: \n");
985   handle->ns_it = NULL;
986
987   if (NULL == handle->v_attr_head)
988   {
989     GNUNET_SCHEDULER_add_now (&issue_ticket, handle);
990     return;
991   }
992   handle->credential_request = GNUNET_CREDENTIAL_collect (credential_handle,
993                                                           &handle->aud_key,
994                                                           handle->v_attr_head->name,
995                                                           &handle->iss_key,
996                                                           &handle_vattr_collection,
997                                                           handle);
998 }
999 /**
1000  * Collect attributes for token
1001  */
1002 static void
1003 attr_collect (void *cls,
1004               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1005               const char *label,
1006               unsigned int rd_count,
1007               const struct GNUNET_GNSRECORD_Data *rd)
1008 {
1009   struct IssueHandle *handle = cls;
1010   int i;
1011   char* data;
1012   struct GNUNET_HashCode key;
1013
1014   GNUNET_CRYPTO_hash (label,
1015                       strlen (label),
1016                       &key);
1017
1018   if (0 == rd_count ||
1019       ( (NULL != handle->attr_map) &&
1020         (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->attr_map,
1021                                                                &key))
1022       )
1023      )
1024   {
1025     GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
1026     return;
1027   }
1028
1029   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", label);
1030
1031   if (1 == rd_count)
1032   {
1033     if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1034     {
1035       data = GNUNET_GNSRECORD_value_to_string (rd->record_type,
1036                                                rd->data,
1037                                                rd->data_size);
1038       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
1039       token_add_attr (handle->token,
1040                       label,
1041                       data);
1042       GNUNET_free (data);
1043     }
1044     GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
1045     return;
1046   }
1047
1048   i = 0;
1049   for (; i < rd_count; i++)
1050   {
1051     if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1052     {
1053       data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
1054                                                rd[i].data,
1055                                                rd[i].data_size);
1056       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding value: %s\n", data);
1057       token_add_attr (handle->token, label, data);
1058       GNUNET_free (data);
1059     }
1060   }
1061
1062   GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it);
1063 }
1064
1065 static void
1066 process_parallel_lookup (void *cls, uint32_t rd_count,
1067                          const struct GNUNET_GNSRECORD_Data *rd)
1068 {
1069   GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1070               "Parallel lookup finished (count=%u)\n", rd_count);
1071   struct ParallelLookup *parallel_lookup = cls;
1072   struct ExchangeHandle *handle = parallel_lookup->handle;
1073   char *data;
1074   int i;
1075
1076   GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1077                                handle->parallel_lookups_tail,
1078                                parallel_lookup);
1079   GNUNET_free (parallel_lookup);
1080   if (1 == rd_count)
1081   {
1082     if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1083     {
1084       GNUNET_CRYPTO_cpabe_decrypt (rd->data,
1085                                    rd->data_size,
1086                                    handle->key,
1087                                    (void**)&data);
1088       GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "Adding value: %s\n", data);
1089       token_add_attr (handle->token,
1090                       parallel_lookup->label,
1091                       data);
1092       GNUNET_free (data);
1093     }
1094   } else {
1095     i = 0;
1096     for (; i < rd_count; i++)
1097     {
1098       if (rd[i].record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
1099       {
1100         data = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
1101                                                  rd[i].data,
1102                                                  rd[i].data_size);
1103         GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "Adding value: %s\n", data);
1104         token_add_attr (handle->token, parallel_lookup->label, data);
1105         GNUNET_free (data);
1106       }
1107     }
1108   }
1109   if (NULL != handle->parallel_lookups_head)
1110     return; //Wait for more
1111   //Else we are done
1112   GNUNET_SCHEDULER_cancel (handle->kill_task);
1113   GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle);
1114 }
1115
1116 void
1117 abort_parallel_lookups (void *cls)
1118 {
1119   struct ExchangeHandle *handle = cls;
1120   struct ParallelLookup *lu;
1121   struct ParallelLookup *tmp;
1122
1123   for (lu = handle->parallel_lookups_head;
1124        NULL != lu;) {
1125     GNUNET_GNS_lookup_cancel (lu->lookup_request);
1126     GNUNET_free (lu->label);
1127     tmp = lu->next;
1128     GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head,
1129                                  handle->parallel_lookups_tail,
1130                                  lu);
1131       GNUNET_free (lu);
1132       lu = tmp;
1133   }
1134   GNUNET_SCHEDULER_add_now (&sign_and_return_token, handle);
1135
1136 }
1137
1138 static void
1139 process_lookup_result (void *cls, uint32_t rd_count,
1140                        const struct GNUNET_GNSRECORD_Data *rd)
1141 {
1142   struct ExchangeHandle *handle = cls;
1143   struct GNUNET_HashCode new_key_hash;
1144   struct GNUNET_CRYPTO_SymmetricSessionKey enc_key;
1145   struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv;
1146   struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key;
1147   struct ParallelLookup *parallel_lookup;
1148   size_t size;
1149   char *buf;
1150   char *scope;
1151   char *lookup_query;
1152
1153   handle->lookup_request = NULL;
1154   if (1 != rd_count)
1155   {
1156     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1157                 "Number of keys %d != 1.",
1158                 rd_count);
1159     cleanup_exchange_handle (handle);
1160     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1161     return;
1162   }
1163
1164   //Decrypt
1165   ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data;
1166
1167   buf = GNUNET_malloc (rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1168
1169   //Calculate symmetric key from ecdh parameters
1170   GNUNET_assert (GNUNET_OK == 
1171                  GNUNET_CRYPTO_ecdsa_ecdh (&handle->aud_privkey,
1172                                            ecdh_key,
1173                                            &new_key_hash));
1174   create_sym_key_from_ecdh (&new_key_hash,
1175                             &enc_key,
1176                             &enc_iv);
1177   size = GNUNET_CRYPTO_symmetric_decrypt (rd->data + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1178                                           rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
1179                                           &enc_key,
1180                                           &enc_iv,
1181                                           buf);
1182
1183   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1184               "Decrypted bytes: %zd Expected bytes: %zd\n",
1185               size, rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1186
1187   scopes = GNUNET_strdup (buf);
1188   GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1189               "Scopes %s\n", scopes);
1190   handle->key = GNUNET_CRYPTO_cpabe_deserialize_key ((void*)(buf + strlen (scopes) + 1),
1191                                          rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)
1192                                          - strlen (scopes) - 1);
1193
1194   for (scope = strtok (scopes, ","); NULL != scope; scope = strtok (NULL, ","))
1195   {
1196     GNUNET_asprintf (&lookup_query,
1197                      "%s.gnu",
1198                      scope);
1199     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1200                 "Looking up %s\n", lookup_query);
1201     parallel_lookup = GNUNET_new (struct ParallelLookup);
1202     parallel_lookup->handle = handle;
1203     parallel_lookup->label = GNUNET_strdup (scope);
1204     parallel_lookup->lookup_request
1205       = GNUNET_GNS_lookup (gns_handle,
1206                            lookup_query,
1207                            &handle->ticket->payload->identity_key,
1208                            GNUNET_GNSRECORD_TYPE_ID_ATTR,
1209                            GNUNET_GNS_LO_LOCAL_MASTER,
1210                            &process_parallel_lookup,
1211                            parallel_lookup);
1212     GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head,
1213                                  handle->parallel_lookups_tail,
1214                                  parallel_lookup);
1215   }
1216   handle->kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3),
1217                                 &abort_parallel_lookups,
1218                                 handle);
1219 }
1220
1221 /**
1222  * Checks a exchange message
1223  *
1224  * @param cls client sending the message
1225  * @param xm message of type `struct ExchangeMessage`
1226  * @return #GNUNET_OK if @a xm is well-formed
1227  */
1228 static int
1229 check_exchange_message (void *cls,
1230                         const struct ExchangeMessage *xm)
1231 {
1232   uint16_t size;
1233
1234   size = ntohs (xm->header.size);
1235   if (size <= sizeof (struct ExchangeMessage))
1236   {
1237     GNUNET_break (0);
1238     return GNUNET_SYSERR;
1239   }
1240   return GNUNET_OK;
1241 }
1242
1243 /**
1244  *
1245  * Handler for exchange message
1246  *
1247  * @param cls unused
1248  * @param client who sent the message
1249  * @param message the message
1250  */
1251 static void
1252 handle_exchange_message (void *cls,
1253                          const struct ExchangeMessage *xm)
1254 {
1255   struct ExchangeHandle *xchange_handle;
1256   struct IdpClient *idp = cls;
1257   const char *ticket;
1258   char *lookup_query;
1259
1260   ticket = (const char *) &xm[1];
1261   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1262               "Received EXCHANGE of `%s' from client\n",
1263               ticket);
1264   xchange_handle = GNUNET_malloc (sizeof (struct ExchangeHandle));
1265   xchange_handle->aud_privkey = xm->aud_privkey;
1266   xchange_handle->r_id = xm->id;
1267   if (GNUNET_SYSERR == ticket_parse (ticket,
1268                                      &xchange_handle->aud_privkey,
1269                                      &xchange_handle->ticket))
1270   {
1271     GNUNET_free (xchange_handle);
1272     GNUNET_SERVICE_client_drop (idp->client);
1273     return;
1274   }
1275   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for ABE key under %s\n",
1276               xchange_handle->ticket->payload->label);
1277   GNUNET_asprintf (&lookup_query,
1278                    "%s.gnu",
1279                    xchange_handle->ticket->payload->label);
1280   GNUNET_SERVICE_client_continue (idp->client);
1281   xchange_handle->client = idp;
1282   xchange_handle->token = token_create (&xchange_handle->ticket->payload->identity_key,
1283                                         &xchange_handle->ticket->payload->identity_key);
1284   xchange_handle->lookup_request
1285     = GNUNET_GNS_lookup (gns_handle,
1286                          lookup_query,
1287                          &xchange_handle->ticket->payload->identity_key,
1288                          GNUNET_GNSRECORD_TYPE_ABE_KEY,
1289                          GNUNET_GNS_LO_LOCAL_MASTER,
1290                          &process_lookup_result,
1291                          xchange_handle);
1292   GNUNET_free (lookup_query);
1293
1294 }
1295
1296 /**
1297  * Checks an issue message
1298  *
1299  * @param cls client sending the message
1300  * @param im message of type `struct IssueMessage`
1301  * @return #GNUNET_OK if @a im is well-formed
1302  */
1303 static int
1304 check_issue_message(void *cls,
1305                     const struct IssueMessage *im)
1306 {
1307   uint16_t size;
1308
1309   size = ntohs (im->header.size);
1310   if (size <= sizeof (struct IssueMessage))
1311   {
1312     GNUNET_break (0);
1313     return GNUNET_SYSERR;
1314   }
1315   scopes = (char *) &im[1];
1316   if ('\0' != scopes[size - sizeof (struct IssueMessage) - 1])
1317   {
1318     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1319                 "Malformed scopes received!\n");
1320     GNUNET_break (0);
1321     return GNUNET_SYSERR;
1322   }
1323   return GNUNET_OK;
1324 }
1325
1326 void
1327 attr_collect_task (void *cls)
1328 {
1329   struct IssueHandle *issue_handle = cls;
1330
1331   issue_handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
1332                                                                &issue_handle->iss_key,
1333                                                                &attr_collect_error,
1334                                                                issue_handle,
1335                                                                &attr_collect,
1336                                                                issue_handle,
1337                                                                &attr_collect_finished,
1338                                                                issue_handle);
1339 }
1340
1341
1342
1343 void
1344 abe_key_lookup_error (void *cls)
1345 {
1346   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1347               "Error looking for ABE master!\n");
1348   GNUNET_SCHEDULER_add_now (&do_shutdown, cls);
1349 }
1350
1351 void
1352 abe_key_lookup_result (void *cls,
1353                        const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1354                        const char *label,
1355                        unsigned int rd_count,
1356                        const struct GNUNET_GNSRECORD_Data *rd)
1357 {
1358   struct IssueHandle *handle = cls;
1359   int i;
1360
1361   for (i=0;i<rd_count;i++) {
1362     if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
1363       continue;
1364     handle->abe_key = GNUNET_CRYPTO_cpabe_deserialize_master_key ((void**)rd[i].data,
1365                                                                   rd[i].data_size);
1366     GNUNET_SCHEDULER_add_now (&attr_collect_task, handle);
1367     return;
1368   }
1369   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1370               "No ABE master found!\n");
1371   GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1372
1373 }
1374
1375 /**
1376  *
1377  * Handler for issue message
1378  *
1379  * @param cls unused
1380  * @param client who sent the message
1381  * @param message the message
1382  */
1383 static void
1384 handle_issue_message (void *cls,
1385                       const struct IssueMessage *im)
1386 {
1387   const char *scopes;
1388   char *scopes_tmp;
1389   char *scope;
1390   uint64_t rnd_key;
1391   struct GNUNET_HashCode key;
1392   struct IssueHandle *issue_handle;
1393   struct IdpClient *idp = cls;
1394
1395   scopes = (const char *) &im[1];
1396   //v_attrs = (const char *) &im[1] + ntohl(im->scope_len);
1397   issue_handle = GNUNET_malloc (sizeof (struct IssueHandle));
1398   issue_handle->attr_map = GNUNET_CONTAINER_multihashmap_create (5,
1399                                                                  GNUNET_NO);
1400   scopes_tmp = GNUNET_strdup (scopes);
1401
1402   for (scope = strtok (scopes_tmp, ","); NULL != scope; scope = strtok (NULL, ","))
1403   {
1404     GNUNET_CRYPTO_hash (scope,
1405                         strlen (scope),
1406                         &key);
1407     GNUNET_CONTAINER_multihashmap_put (issue_handle->attr_map,
1408                                        &key,
1409                                        scope,
1410                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
1411   }
1412   GNUNET_free (scopes_tmp);
1413   /*scopes_tmp = GNUNET_strdup (v_attrs);
1414
1415     for (scope = strtok (scopes_tmp, ","); NULL != scope; scope = strtok (NULL, ","))
1416     {
1417     vattr_entry = GNUNET_new (struct VerifiedAttributeEntry);
1418     vattr_entry->name = GNUNET_strdup (scope);
1419     GNUNET_CONTAINER_DLL_insert (issue_handle->v_attr_head,
1420     issue_handle->v_attr_tail,
1421     vattr_entry);
1422     }
1423     GNUNET_free (scopes_tmp);*/
1424
1425
1426
1427   issue_handle->r_id = im->id;
1428   issue_handle->aud_key = im->aud_key;
1429   issue_handle->iss_key = im->iss_key;
1430   GNUNET_CRYPTO_ecdsa_key_get_public (&im->iss_key,
1431                                       &issue_handle->iss_pkey);
1432   issue_handle->expiration = GNUNET_TIME_absolute_ntoh (im->expiration);
1433   issue_handle->nonce = ntohl (im->nonce);
1434   GNUNET_SERVICE_client_continue (idp->client);
1435   issue_handle->client = idp;
1436   issue_handle->scopes = GNUNET_strdup (scopes);
1437   issue_handle->token = token_create (&issue_handle->iss_pkey,
1438                                       &issue_handle->aud_key);
1439   rnd_key =
1440     GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
1441                               UINT64_MAX);
1442   GNUNET_STRINGS_base64_encode ((char*)&rnd_key,
1443                                 sizeof (uint64_t),
1444                                 &issue_handle->label);
1445   issue_handle->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
1446                                                          &issue_handle->iss_key,
1447                                                          "+",
1448                                                          &abe_key_lookup_error,
1449                                                          issue_handle,
1450                                                          &abe_key_lookup_result,
1451                                                          issue_handle);
1452 }
1453
1454 static void
1455 cleanup_as_handle (struct AttributeStoreHandle *handle)
1456 {
1457   if (NULL != handle->attribute)
1458     GNUNET_free (handle->attribute);
1459   if (NULL != handle->abe_key)
1460     GNUNET_free (handle->abe_key);
1461   GNUNET_free (handle);
1462 }
1463
1464
1465
1466 void
1467 attr_store_cont (void *cls,
1468                  int32_t success,
1469                  const char *emsg)
1470 {
1471   struct AttributeStoreHandle *as_handle = cls;
1472   struct GNUNET_MQ_Envelope *env;
1473   struct AttributeStoreResponseMessage *acr_msg;
1474
1475   if (GNUNET_SYSERR == success)
1476   {
1477     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1478                 "Failed to store attribute %s\n",
1479                 emsg);
1480     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1481     return;
1482   }
1483
1484   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1485               "Sending ATTRIBUTE_STORE_RESPONSE message\n");
1486   env = GNUNET_MQ_msg (acr_msg,
1487                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE);
1488   acr_msg->id = htonl (as_handle->r_id);
1489   acr_msg->op_result = htonl (GNUNET_OK);
1490   GNUNET_MQ_send (as_handle->client->mq,
1491                   env);
1492   cleanup_as_handle (as_handle);
1493 }
1494
1495 static void
1496 attr_store_task (void *cls)
1497 {
1498   struct AttributeStoreHandle *as_handle = cls;
1499   struct GNUNET_GNSRECORD_Data rd[1];
1500   char* buf;
1501   size_t buf_size;
1502
1503   buf_size = attribute_serialize_get_size (as_handle->attribute);
1504   buf = GNUNET_malloc (buf_size);
1505
1506   attribute_serialize (as_handle->attribute,
1507                        buf);
1508
1509   /**
1510    * Encrypt the attribute value and store in namestore
1511    */
1512   rd[0].data_size = GNUNET_CRYPTO_cpabe_encrypt (buf,
1513                                                  buf_size,
1514                                                  as_handle->attribute->name, //Policy
1515                                                  as_handle->abe_key,
1516                                                  (void**)&rd[0].data);
1517   GNUNET_free (buf);
1518   rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
1519   rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1520   rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1521   as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1522                                                      &as_handle->identity,
1523                                                      as_handle->attribute->name,
1524                                                      1,
1525                                                      rd,
1526                                                      &attr_store_cont,
1527                                                      as_handle);
1528   GNUNET_free ((void*)rd[0].data);
1529
1530 }
1531
1532 static void
1533 bootstrap_store_cont (void *cls,
1534                       int32_t success,
1535                       const char *emsg)
1536 {
1537   struct AbeBootstrapHandle *abh = cls;
1538   if (GNUNET_SYSERR == success)
1539   {
1540     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1541                 "Failed to bootstrap ABE master %s\n",
1542                 emsg);
1543     abh->proc (abh->proc_cls, NULL);
1544     GNUNET_free (abh->abe_key);
1545     GNUNET_free (abh);
1546     return;
1547   }
1548   abh->proc (abh->proc_cls, abh->abe_key);
1549   GNUNET_free (abh);
1550 }
1551
1552 static void
1553 bootstrap_store_task (void *cls)
1554 {
1555   struct AbeBootstrapHandle *abh = cls;
1556   struct GNUNET_GNSRECORD_Data rd[1];
1557
1558   rd[0].data_size = GNUNET_CRYPTO_cpabe_serialize_master_key (abh->abe_key,
1559                                                               (void**)&rd[0].data);
1560   rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
1561   rd[0].flags = GNUNET_GNSRECORD_RF_NONE | GNUNET_GNSRECORD_RF_PRIVATE;
1562   rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
1563   abh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
1564                                                &abh->identity,
1565                                                "+",
1566                                                1,
1567                                                rd,
1568                                                &bootstrap_store_cont,
1569                                                abh);
1570 }
1571
1572 static void
1573 bootstrap_abe_error (void *cls)
1574 {
1575   struct AbeBootstrapHandle *abh = cls;
1576   GNUNET_free (abh);
1577   abh->proc (abh->proc_cls, NULL);
1578   GNUNET_free (abh);
1579 }
1580
1581
1582
1583 static void
1584 bootstrap_abe_result (void *cls,
1585                       const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1586                       const char *label,
1587                       unsigned int rd_count,
1588                       const struct GNUNET_GNSRECORD_Data *rd)
1589 {
1590   struct AbeBootstrapHandle *abh = cls;
1591   struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
1592   int i;
1593
1594   for (i=0;i<rd_count;i++) {
1595     if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
1596       continue;
1597     abe_key = GNUNET_CRYPTO_cpabe_deserialize_master_key ((void**)rd[i].data,
1598                                                           rd[i].data_size);
1599     abh->proc (abh->proc_cls, abe_key);
1600     GNUNET_free (abh);
1601     return;
1602   }
1603
1604   //No ABE master found, bootstrapping...
1605   abh->abe_key = GNUNET_CRYPTO_cpabe_create_master_key ();
1606   GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
1607 }
1608
1609 static void
1610 bootstrap_abe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
1611                AbeBootstrapResult proc,
1612                void* cls)
1613 {
1614   struct AbeBootstrapHandle *abh;
1615
1616   abh = GNUNET_new (struct AbeBootstrapHandle);
1617   abh->proc = proc;
1618   abh->proc_cls = cls;
1619   abh->identity = *identity;
1620   abh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
1621                                                 identity,
1622                                                 "+",
1623                                                 &bootstrap_abe_error,
1624                                                 abh,
1625                                                 &bootstrap_abe_result,
1626                                                 abh);
1627
1628 }
1629
1630 static void
1631 store_after_abe_bootstrap (void *cls,
1632                            struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
1633 {
1634   struct AttributeStoreHandle *ash = cls;
1635   ash->abe_key = abe_key;
1636   GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1637 }
1638
1639 /**
1640  * Checks a store message
1641  *
1642  * @param cls client sending the message
1643  * @param sam message of type `struct AttributeStoreMessage`
1644  * @return #GNUNET_OK if @a im is well-formed
1645  */
1646 static int
1647 check_attribute_store_message(void *cls,
1648                               const struct AttributeStoreMessage *sam)
1649 {
1650   uint16_t size;
1651
1652   size = ntohs (sam->header.size);
1653   if (size <= sizeof (struct AttributeStoreMessage))
1654   {
1655     GNUNET_break (0);
1656     return GNUNET_SYSERR;
1657   }
1658   return GNUNET_OK;
1659 }
1660
1661
1662 /**
1663  *
1664  * Handler for store message
1665  *
1666  * @param cls unused
1667  * @param client who sent the message
1668  * @param message the message
1669  */
1670 static void
1671 handle_attribute_store_message (void *cls,
1672                                 const struct AttributeStoreMessage *sam)
1673 {
1674   struct AttributeStoreHandle *as_handle;
1675   struct IdpClient *idp = cls;
1676   size_t data_len;
1677
1678   data_len = ntohs (sam->attr_len);
1679
1680   as_handle = GNUNET_new (struct AttributeStoreHandle);
1681   as_handle->attribute = attribute_deserialize ((char*)&sam[1],
1682                                                 data_len);
1683
1684   as_handle->r_id = sam->id;
1685   as_handle->identity = sam->identity;
1686   GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity,
1687                                       &as_handle->identity_pkey);
1688
1689   GNUNET_SERVICE_client_continue (idp->client);
1690   as_handle->client = idp;
1691
1692   bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle);
1693 }
1694
1695 static void
1696 cleanup_iter_handle (struct AttributeIterator *ai)
1697 {
1698   if (NULL != ai->abe_key)
1699     GNUNET_free (ai->abe_key);
1700   GNUNET_free (ai);
1701 }
1702
1703 static void
1704 attr_iter_error (void *cls)
1705 {
1706   //struct AttributeIterator *ai = cls;
1707   //TODO
1708   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1709               "Failed to iterate over attributes\n");
1710   GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1711 }
1712
1713 static void
1714 attr_iter_finished (void *cls)
1715 {
1716   struct AttributeIterator *ai = cls;
1717   struct GNUNET_MQ_Envelope *env;
1718   struct AttributeResultMessage *arm;
1719
1720   env = GNUNET_MQ_msg (arm,
1721                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1722   arm->id = htonl (ai->request_id);
1723   arm->attr_len = htons (0);
1724   GNUNET_MQ_send (ai->client->mq, env);
1725   cleanup_iter_handle (ai);
1726 }
1727
1728 static void
1729 attr_iter_cb (void *cls,
1730               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1731               const char *label,
1732               unsigned int rd_count,
1733               const struct GNUNET_GNSRECORD_Data *rd)
1734 {
1735   struct AttributeIterator *ai = cls;
1736   struct AttributeResultMessage *arm;
1737   struct GNUNET_CRYPTO_AbeKey *key;
1738   struct GNUNET_MQ_Envelope *env;
1739   ssize_t msg_extra_len;
1740   char* attr_ser;
1741   char* attrs[2];
1742   char* data_tmp;
1743
1744   if (rd_count != 1)
1745   {
1746     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
1747     return;
1748   }
1749
1750   if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) {
1751     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
1752     return;
1753   }
1754   attrs[0] = (char*)label;
1755   attrs[1] = 0;
1756   key = GNUNET_CRYPTO_cpabe_create_key (ai->abe_key,
1757                                         attrs);
1758   msg_extra_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data,
1759                                                rd->data_size,
1760                                                key,
1761                                                (void**)&attr_ser);
1762   GNUNET_CRYPTO_cpabe_delete_key (key);
1763   GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1764               "Found attribute: %s\n", label);
1765   env = GNUNET_MQ_msg_extra (arm,
1766                              msg_extra_len,
1767                              GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
1768   arm->id = htonl (ai->request_id);
1769   arm->attr_len = htons (msg_extra_len);
1770   arm->identity = *zone;
1771   data_tmp = (char *) &arm[1];
1772   GNUNET_memcpy (data_tmp,
1773                  attr_ser,
1774                  msg_extra_len);
1775   GNUNET_MQ_send (ai->client->mq, env);
1776   GNUNET_free (attr_ser);
1777 }
1778
1779
1780 void
1781 iterate_after_abe_bootstrap (void *cls,
1782                              struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
1783 {
1784   struct AttributeIterator *ai = cls;
1785   ai->abe_key = abe_key;
1786   ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
1787                                                      &ai->identity,
1788                                                      &attr_iter_error,
1789                                                      ai,
1790                                                      &attr_iter_cb,
1791                                                      ai,
1792                                                      &attr_iter_finished,
1793                                                      ai);
1794 }
1795
1796
1797 /**
1798  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_START message
1799  *
1800  * @param cls the client sending the message
1801  * @param zis_msg message from the client
1802  */
1803 static void
1804 handle_iteration_start (void *cls,
1805                         const struct AttributeIterationStartMessage *ais_msg)
1806 {
1807   struct IdpClient *idp = cls;
1808   struct AttributeIterator *ai;
1809
1810   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1811               "Received ATTRIBUTE_ITERATION_START message\n");
1812   ai = GNUNET_new (struct AttributeIterator);
1813   ai->request_id = ntohl (ais_msg->id);
1814   ai->client = idp;
1815   ai->identity = ais_msg->identity;
1816
1817   GNUNET_CONTAINER_DLL_insert (idp->op_head,
1818                                idp->op_tail,
1819                                ai);
1820   bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai);
1821   GNUNET_SERVICE_client_continue (idp->client);
1822 }
1823
1824
1825 /**
1826  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_STOP message
1827  *
1828  * @param cls the client sending the message
1829  * @param ais_msg message from the client
1830  */
1831 static void
1832 handle_iteration_stop (void *cls,
1833                        const struct AttributeIterationStopMessage *ais_msg)
1834 {
1835   struct IdpClient *idp = cls;
1836   struct AttributeIterator *ai;
1837   uint32_t rid;
1838
1839   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1840               "Received `%s' message\n",
1841               "ATTRIBUTE_ITERATION_STOP");
1842   rid = ntohl (ais_msg->id);
1843   for (ai = idp->op_head; NULL != ai; ai = ai->next)
1844     if (ai->request_id == rid)
1845       break;
1846   if (NULL == ai)
1847   {
1848     GNUNET_break (0);
1849     GNUNET_SERVICE_client_drop (idp->client);
1850     return;
1851   }
1852   GNUNET_CONTAINER_DLL_remove (idp->op_head,
1853                                idp->op_tail,
1854                                ai);
1855   GNUNET_free (ai);
1856   GNUNET_SERVICE_client_continue (idp->client);
1857 }
1858
1859
1860 /**
1861  * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT message
1862  *
1863  * @param cls the client sending the message
1864  * @param message message from the client
1865  */
1866 static void
1867 handle_iteration_next (void *cls,
1868                        const struct AttributeIterationNextMessage *ais_msg)
1869 {
1870   struct IdpClient *idp = cls;
1871   struct AttributeIterator *ai;
1872   uint32_t rid;
1873
1874   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1875               "Received ATTRIBUTE_ITERATION_NEXT message\n");
1876   rid = ntohl (ais_msg->id);
1877   for (ai = idp->op_head; NULL != ai; ai = ai->next)
1878     if (ai->request_id == rid)
1879       break;
1880   if (NULL == ai)
1881   {
1882     GNUNET_break (0);
1883     GNUNET_SERVICE_client_drop (idp->client);
1884     return;
1885   }
1886   GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
1887   GNUNET_SERVICE_client_continue (idp->client);
1888 }
1889
1890
1891
1892
1893 /**
1894  * Main function that will be run
1895  *
1896  * @param cls closure
1897  * @param args remaining command-line arguments
1898  * @param cfgfile name of the configuration file used (for saving, can be NULL)
1899  * @param c configuration
1900  */
1901 static void
1902 run (void *cls,
1903      const struct GNUNET_CONFIGURATION_Handle *c,
1904      struct GNUNET_SERVICE_Handle *server)
1905 {
1906   cfg = c;
1907
1908   stats = GNUNET_STATISTICS_create ("identity-provider", cfg);
1909
1910   //Connect to identity and namestore services
1911   ns_handle = GNUNET_NAMESTORE_connect (cfg);
1912   if (NULL == ns_handle)
1913   {
1914     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to namestore");
1915   }
1916
1917   gns_handle = GNUNET_GNS_connect (cfg);
1918   if (NULL == gns_handle)
1919   {
1920     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns");
1921   }
1922   credential_handle = GNUNET_CREDENTIAL_connect (cfg);
1923   if (NULL == credential_handle)
1924   {
1925     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential");
1926   }
1927   identity_handle = GNUNET_IDENTITY_connect (cfg,
1928                                              NULL,
1929                                              NULL);
1930
1931   if (GNUNET_OK ==
1932       GNUNET_CONFIGURATION_get_value_time (cfg,
1933                                            "identity-provider",
1934                                            "TOKEN_EXPIRATION_INTERVAL",
1935                                            &token_expiration_interval))
1936   {
1937     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1938                 "Time window for zone iteration: %s\n",
1939                 GNUNET_STRINGS_relative_time_to_string (token_expiration_interval,
1940                                                         GNUNET_YES));
1941   } else {
1942     token_expiration_interval = DEFAULT_TOKEN_EXPIRATION_INTERVAL;
1943   }
1944
1945   GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1946 }
1947
1948 /**
1949  * Called whenever a client is disconnected.
1950  *
1951  * @param cls closure
1952  * @param client identification of the client
1953  * @param app_ctx @a client
1954  */
1955 static void
1956 client_disconnect_cb (void *cls,
1957                       struct GNUNET_SERVICE_Client *client,
1958                       void *app_ctx)
1959 {
1960   struct IdpClient *idp = app_ctx;
1961   struct AttributeIterator *ai;
1962
1963   //TODO other operations
1964
1965   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1966               "Client %p disconnected\n",
1967               client);
1968
1969   while (NULL != (ai = idp->op_head))
1970   {
1971     GNUNET_CONTAINER_DLL_remove (idp->op_head,
1972                                  idp->op_tail,
1973                                  ai);
1974     GNUNET_free (ai);
1975   }
1976   GNUNET_free (idp);
1977 }
1978
1979
1980 /**
1981  * Add a client to our list of active clients.
1982  *
1983  * @param cls NULL
1984  * @param client client to add
1985  * @param mq message queue for @a client
1986  * @return internal namestore client structure for this client
1987  */
1988 static void *
1989 client_connect_cb (void *cls,
1990                    struct GNUNET_SERVICE_Client *client,
1991                    struct GNUNET_MQ_Handle *mq)
1992 {
1993   struct IdpClient *idp;
1994   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1995               "Client %p connected\n",
1996               client);
1997   idp = GNUNET_new (struct IdpClient);
1998   idp->client = client;
1999   idp->mq = mq;
2000   return idp;
2001 }
2002
2003
2004
2005 /**
2006  * Define "main" method using service macro.
2007  */
2008 GNUNET_SERVICE_MAIN
2009 ("identity-provider",
2010  GNUNET_SERVICE_OPTION_NONE,
2011  &run,
2012  &client_connect_cb,
2013  &client_disconnect_cb,
2014  NULL,
2015  GNUNET_MQ_hd_var_size (issue_message,
2016                         GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE,
2017                         struct IssueMessage,
2018                         NULL),
2019  GNUNET_MQ_hd_var_size (exchange_message,
2020                         GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE,
2021                         struct ExchangeMessage,
2022                         NULL),
2023  GNUNET_MQ_hd_var_size (attribute_store_message,
2024                         GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE,
2025                         struct AttributeStoreMessage,
2026                         NULL),
2027  GNUNET_MQ_hd_fixed_size (iteration_start, 
2028                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START,
2029                           struct AttributeIterationStartMessage,
2030                           NULL),
2031  GNUNET_MQ_hd_fixed_size (iteration_next, 
2032                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT,
2033                           struct AttributeIterationNextMessage,
2034                           NULL),
2035  GNUNET_MQ_hd_fixed_size (iteration_stop, 
2036                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP,
2037                           struct AttributeIterationStopMessage,
2038                           NULL),
2039  GNUNET_MQ_handler_end());
2040 /* end of gnunet-service-identity-provider.c */