gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [gnunet] 116/171: - rework issue api


From: gnunet
Subject: [GNUnet-SVN] [gnunet] 116/171: - rework issue api
Date: Thu, 04 Jan 2018 16:10:24 +0100

This is an automated email from the git hooks/post-receive script.

martin-schanzenbach pushed a commit to branch master
in repository gnunet.

commit 0469377fd49450c1d7853c5ceecf08be9ce8df75
Author: Schanzenbach, Martin <address@hidden>
AuthorDate: Sun Sep 17 21:06:42 2017 +0200

    - rework issue api
---
 src/identity-provider/gnunet-idp.c                 | 274 +++++-----
 .../gnunet-service-identity-provider.c             | 571 ++++++++++++++++-----
 src/identity-provider/identity_attribute.c         |  68 ++-
 src/identity-provider/identity_attribute.h         |  41 +-
 src/identity-provider/identity_provider.h          |  50 +-
 src/identity-provider/identity_provider_api.c      | 118 ++++-
 src/identity-provider/test_idp.sh                  |   5 +-
 .../{test_idp.sh => test_idp_issue.sh}             |   5 +-
 src/include/gnunet_identity_provider_service.h     | 160 +++++-
 src/include/gnunet_protocols.h                     |  12 +-
 10 files changed, 1004 insertions(+), 300 deletions(-)

diff --git a/src/identity-provider/gnunet-idp.c 
b/src/identity-provider/gnunet-idp.c
index 264d77ba2..fdd4720e0 100644
--- a/src/identity-provider/gnunet-idp.c
+++ b/src/identity-provider/gnunet-idp.c
@@ -32,14 +32,14 @@
 #include "gnunet_signatures.h"
 
 /**
- * Init flag
+ * List attribute flag
  */
-static int init;
+static int list;
 
 /**
- * List attribute flag
+ * Relying party
  */
-static int list;
+static char* rp;
 
 /**
  * The attribute
@@ -52,6 +52,11 @@ static char* attr_name;
 static char* attr_value;
 
 /**
+ * Attributes to issue
+ */
+static char* issue_attrs;
+
+/**
  * Ego name
  */
 static char* ego_name;
@@ -72,81 +77,77 @@ static struct GNUNET_IDENTITY_PROVIDER_Handle *idp_handle;
 static struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op;
 
 /**
- * Namestore handle
+ * Attribute iterator
  */
-static struct GNUNET_NAMESTORE_Handle *namestore_handle;
+static struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *attr_iterator;
 
 /**
- * Attribute iterator
+ * Master ABE key
  */
-static struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *attr_iterator;
+static struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
 
 /**
- * Namestore queue
+ * ego private key
  */
-static struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
+static const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey;
 
 /**
- * Master ABE key
+ * rp public key
  */
-static struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
+static struct GNUNET_CRYPTO_EcdsaPublicKey rp_key;
+
+
+/**
+ * Attribute list
+ */
+static struct GNUNET_IDENTITY_PROVIDER_AttributeList *attr_list;
 
 static void
 do_cleanup(void *cls)
 {
-  if (NULL != ns_qe)
-    GNUNET_NAMESTORE_cancel (ns_qe);
   if (NULL != attr_iterator)
     GNUNET_IDENTITY_PROVIDER_get_attributes_stop (attr_iterator);
   if (NULL != idp_handle)
     GNUNET_IDENTITY_PROVIDER_disconnect (idp_handle);
-  if (NULL != namestore_handle)
-    GNUNET_NAMESTORE_disconnect (namestore_handle);
   if (NULL != identity_handle)
     GNUNET_IDENTITY_disconnect (identity_handle);
   if (NULL != abe_key)
     GNUNET_free (abe_key);
+  if (NULL != attr_list)
+    GNUNET_free (attr_list);
 }
 
 static void
-ns_error_cb (void *cls)
-{
-  ns_qe = NULL;
-  GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-              "Failed.");
-  do_cleanup(NULL);
-  return;
-}
-
-static void
-store_attr_cont (void *cls,
-                 int32_t success,
-                 const char*emsg)
+ticket_issue_cb (void* cls,
+                 const struct GNUNET_IDENTITY_PROVIDER_Ticket2 *ticket)
 {
-  ns_qe = NULL;
-  if (GNUNET_SYSERR == success) {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "%s\n", emsg);
-  } else {
+  char* ticket_str;
+  if (NULL != ticket) {
+    ticket_str = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd,
+                                    sizeof (uint64_t));
     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-                "Sucessfully added identity attribute %s=%s\n",
-                attr_name, attr_value);
+                "Got ticket, %s\n",
+                ticket_str);
+    GNUNET_free (ticket_str);
   }
   GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
 }
 
 static void
-store_abe_cont (void *cls,
+store_attr_cont (void *cls,
                  int32_t success,
                  const char*emsg)
 {
-  ns_qe = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+              "Store continuation\n");
+
   if (GNUNET_SYSERR == success) {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "%s\n", emsg);
   } else {
     GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-                "Bootstrapped ABE master key. Please run command again.\n");
+                "Sucessfully added identity attribute %s=%s\n",
+                attr_name, attr_value);
   }
   GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
 }
@@ -163,100 +164,75 @@ iter_error (void *cls)
 static void
 iter_finished (void *cls)
 {
-  attr_iterator = NULL;
-  GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
-}
+  struct GNUNET_IDENTITY_PROVIDER_Attribute *attr;
 
-static void
-iter_cb (void *cls,
-         const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
-         const struct GNUNET_IDENTITY_PROVIDER_Attribute *attr)
-{
-  
   GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-              "%s: %s\n", attr->name, (char*)attr->data);
-  GNUNET_IDENTITY_PROVIDER_get_attributes_next (attr_iterator);
-}
-
-static void
-abe_lookup_cb (void *cls,
-               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-               const char *label,
-               unsigned int rd_count,
-               const struct GNUNET_GNSRECORD_Data *rd)
-{
-  struct GNUNET_GNSRECORD_Data new_record;
-  struct GNUNET_CRYPTO_AbeMasterKey *new_key;
-  int i;
-  ssize_t size;
-  ns_qe = NULL;
-  for (i=0;i<rd_count;i++) {
-    if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
-      continue;
-    abe_key = GNUNET_CRYPTO_cpabe_deserialize_master_key (rd[i].data,
-                                                          rd[i].data_size);
-  }
-  if (NULL == abe_key) {
-    new_key = GNUNET_CRYPTO_cpabe_create_master_key ();
-    size = GNUNET_CRYPTO_cpabe_serialize_master_key (new_key,
-                                                     (void**)&new_record.data);
-    new_record.data_size = size;
-    new_record.record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
-    new_record.expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
-    new_record.flags = GNUNET_GNSRECORD_RF_PRIVATE | 
GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
-    ns_qe = GNUNET_NAMESTORE_records_store (namestore_handle,
-                                            zone,
-                                            "+",
-                                            1,
-                                            &new_record,
-                                            &store_abe_cont,
-                                            NULL);
-    return;
-  }
-  if (init) {
+              "Attribute collection finished!\n");
+  attr_iterator = NULL;
+  if (list) {
     GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
     return;
   }
 
-  if (list) {
-    attr_iterator = GNUNET_IDENTITY_PROVIDER_get_attributes_start (idp_handle,
-                                                                  zone,
-                                                                  &iter_error,
-                                                                  NULL,
-                                                                  &iter_cb,
-                                                                  NULL,
-                                                                  
&iter_finished,
-                                                                  NULL);
+  if (issue_attrs) {
+    idp_op = GNUNET_IDENTITY_PROVIDER_idp_ticket_issue (idp_handle,
+                                                        pkey,
+                                                        &rp_key,
+                                                        attr_list,
+                                                        &ticket_issue_cb,
+                                                        NULL);
     return;
   }
+  attr = GNUNET_IDENTITY_PROVIDER_attribute_new (attr_name,
+                                                 
GNUNET_IDENTITY_PROVIDER_AT_STRING,
+                                                 attr_value,
+                                                 strlen (attr_value));
+  GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+              "Adding attribute\n");
 
-  struct GNUNET_IDENTITY_PROVIDER_Attribute *attr = 
GNUNET_IDENTITY_PROVIDER_attribute_new (attr_name,
-                                                                               
             GNUNET_IDENTITY_PROVIDER_AT_STRING,
-                                                                               
             attr_value,
-                                                                               
             strlen (attr_value));
   idp_op = GNUNET_IDENTITY_PROVIDER_attribute_store (idp_handle,
-                                                    zone,
-                                                    attr,
-                                                    &store_attr_cont,
-                                                    NULL);
-
-  /*size = GNUNET_CRYPTO_cpabe_encrypt (attr_value,
-                                      strlen (attr_value) + 1,
-                                      attr_name,
-                                      abe_key,
-                                      (void**)&new_record.data);
-  new_record.data_size = size;
-  new_record.record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
-  new_record.expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
-  new_record.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
-
-  ns_qe = GNUNET_NAMESTORE_records_store (namestore_handle,
-                                          zone,
-                                          attr_name,
-                                          1,
-                                          &new_record,
-                                          &store_attr_cont,
-                                          NULL);*/
+                                                     pkey,
+                                                     attr,
+                                                     &store_attr_cont,
+                                                     NULL);
+
+
+}
+
+static void
+iter_cb (void *cls,
+         const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+         const struct GNUNET_IDENTITY_PROVIDER_Attribute *attr)
+{
+  struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
+  char *attrs_tmp;
+  char *attr_str;
+
+  if (issue_attrs)
+  {
+    attrs_tmp = GNUNET_strdup (issue_attrs);
+    attr_str = strtok (attrs_tmp, ",");
+    while (NULL != attr_str) {
+      if (0 != strcmp (attr_str, attr->name)) {
+        attr_str = strtok (NULL, ",");
+        continue;
+      }
+      le = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry);
+      le->attribute = GNUNET_IDENTITY_PROVIDER_attribute_new (attr->name,
+                                                              
attr->attribute_type,
+                                                              attr->data,
+                                                              attr->data_size);
+      GNUNET_CONTAINER_DLL_insert (attr_list->list_head,
+                                   attr_list->list_tail,
+                                   le);
+      break;
+    }
+    GNUNET_free (attrs_tmp);
+  } else {
+    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+                "%s: %s\n", attr->name, (char*)attr->data);
+  }
+  GNUNET_IDENTITY_PROVIDER_get_attributes_next (attr_iterator);
 }
 
 static void
@@ -265,19 +241,29 @@ ego_cb (void *cls,
         void **ctx,
         const char *name)
 {
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey;
   if (NULL == name)
     return;
   if (0 != strcmp (name, ego_name))
     return;
   pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
-  ns_qe = GNUNET_NAMESTORE_records_lookup (namestore_handle,
-                                           pkey,
-                                           "+",
-                                           &ns_error_cb,
-                                           NULL,
-                                           &abe_lookup_cb,
-                                           NULL);
+
+  if (NULL != rp)
+    GNUNET_CRYPTO_ecdsa_public_key_from_string (rp,
+                                                strlen (rp),
+                                                &rp_key);
+
+  attr_list = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeList);
+
+  attr_iterator = GNUNET_IDENTITY_PROVIDER_get_attributes_start (idp_handle,
+                                                                 pkey,
+                                                                 &iter_error,
+                                                                 NULL,
+                                                                 &iter_cb,
+                                                                 NULL,
+                                                                 
&iter_finished,
+                                                                 NULL);
+
+
 }
 
 static void
@@ -294,18 +280,6 @@ run (void *cls,
     return;
   } 
 
-  if ((NULL == attr_name) && !list && !init)
-  {
-    return;
-  }
-  if ((NULL == attr_value) && !list && !init)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-                _("Value is required\n"));
-    return;
-  }
-
-  namestore_handle = GNUNET_NAMESTORE_connect (c);
   idp_handle = GNUNET_IDENTITY_PROVIDER_connect (c);
   //Get Ego
   identity_handle = GNUNET_IDENTITY_connect (c,
@@ -337,14 +311,20 @@ main(int argc, char *const argv[])
                                  NULL,
                                  gettext_noop ("Ego"),
                                  &ego_name),
+    GNUNET_GETOPT_option_string ('r',
+                                 "rp",
+                                 NULL,
+                                 gettext_noop ("Audience (relying party)"),
+                                 &rp),
     GNUNET_GETOPT_option_flag ('D',
                                "dump",
                                gettext_noop ("List attributes for Ego"),
                                &list),
-    GNUNET_GETOPT_option_flag ('i',
-                               "init",
-                               gettext_noop ("Initialize attribute store"),
-                               &init),
+    GNUNET_GETOPT_option_string ('i',
+                                 "issue",
+                                 NULL,
+                                 gettext_noop ("Issue a ticket"),
+                                 &issue_attrs),
     GNUNET_GETOPT_OPTION_END
   };
   return GNUNET_PROGRAM_run (argc, argv, "ct",
diff --git a/src/identity-provider/gnunet-service-identity-provider.c 
b/src/identity-provider/gnunet-service-identity-provider.c
index 0ce70aed3..b481c00c0 100644
--- a/src/identity-provider/gnunet-service-identity-provider.c
+++ b/src/identity-provider/gnunet-service-identity-provider.c
@@ -373,6 +373,45 @@ struct ParallelLookup
   char *label;
 };
 
+
+struct TicketIssueHandle
+{
+
+  /**
+   * Client connection
+   */
+  struct IdpClient *client;
+
+  /**
+   * Attributes to issue
+   */
+  struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs;
+
+  /**
+   * Issuer Key
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+  /**
+   * Ticket to issue
+   */
+  struct GNUNET_IDENTITY_PROVIDER_Ticket2 ticket;
+
+  /**
+   * QueueEntry
+   */
+  struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
+
+  /**
+   * request id
+   */
+  uint32_t r_id;
+};
+
+
+/**
+ * DEPRECATED
+ */
 struct IssueHandle
 {
 
@@ -546,6 +585,120 @@ do_shutdown (void *cls)
   cleanup();
 }
 
+/**
+ * Finished storing newly bootstrapped ABE key
+ */
+static void
+bootstrap_store_cont (void *cls,
+                      int32_t success,
+                      const char *emsg)
+{
+  struct AbeBootstrapHandle *abh = cls;
+  if (GNUNET_SYSERR == success)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to bootstrap ABE master %s\n",
+                emsg);
+    abh->proc (abh->proc_cls, NULL);
+    GNUNET_free (abh->abe_key);
+    GNUNET_free (abh);
+    return;
+  }
+  abh->proc (abh->proc_cls, abh->abe_key);
+  GNUNET_free (abh);
+}
+
+/**
+ * Generates and stores a new ABE key
+ */
+static void
+bootstrap_store_task (void *cls)
+{
+  struct AbeBootstrapHandle *abh = cls;
+  struct GNUNET_GNSRECORD_Data rd[1];
+
+  rd[0].data_size = GNUNET_CRYPTO_cpabe_serialize_master_key (abh->abe_key,
+                                                              
(void**)&rd[0].data);
+  rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
+  rd[0].flags = GNUNET_GNSRECORD_RF_NONE | GNUNET_GNSRECORD_RF_PRIVATE;
+  rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
+  abh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
+                                               &abh->identity,
+                                               "+",
+                                               1,
+                                               rd,
+                                               &bootstrap_store_cont,
+                                               abh);
+}
+
+/**
+ * Error checking for ABE master
+ */
+static void
+bootstrap_abe_error (void *cls)
+{
+  struct AbeBootstrapHandle *abh = cls;
+  GNUNET_free (abh);
+  abh->proc (abh->proc_cls, NULL);
+  GNUNET_free (abh);
+}
+
+
+/**
+ * Handle ABE lookup in namestore
+ */
+static void
+bootstrap_abe_result (void *cls,
+                      const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+                      const char *label,
+                      unsigned int rd_count,
+                      const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct AbeBootstrapHandle *abh = cls;
+  struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
+  int i;
+
+  for (i=0;i<rd_count;i++) {
+    if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
+      continue;
+    abe_key = GNUNET_CRYPTO_cpabe_deserialize_master_key ((void**)rd[i].data,
+                                                          rd[i].data_size);
+    abh->proc (abh->proc_cls, abe_key);
+    GNUNET_free (abh);
+    return;
+  }
+
+  //No ABE master found, bootstrapping...
+  abh->abe_key = GNUNET_CRYPTO_cpabe_create_master_key ();
+  GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
+}
+
+/**
+ * Bootstrap ABE master if it does not yet exists.
+ * Will call the AbeBootstrapResult processor when done.
+ */
+static void
+bootstrap_abe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+               AbeBootstrapResult proc,
+               void* cls)
+{
+  struct AbeBootstrapHandle *abh;
+
+  abh = GNUNET_new (struct AbeBootstrapHandle);
+  abh->proc = proc;
+  abh->proc_cls = cls;
+  abh->identity = *identity;
+  abh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
+                                                identity,
+                                                "+",
+                                                &bootstrap_abe_error,
+                                                abh,
+                                                &bootstrap_abe_result,
+                                                abh);
+
+}
+
+
 
 static struct GNUNET_MQ_Envelope*
 create_exchange_result_message (const char* token,
@@ -996,6 +1149,7 @@ attr_collect_finished (void *cls)
                                                           
&handle_vattr_collection,
                                                           handle);
 }
+
 /**
  * Collect attributes for token
  */
@@ -1293,36 +1447,6 @@ handle_exchange_message (void *cls,
 
 }
 
-/**
- * Checks an issue message
- *
- * @param cls client sending the message
- * @param im message of type `struct IssueMessage`
- * @return #GNUNET_OK if @a im is well-formed
- */
-static int
-check_issue_message(void *cls,
-                    const struct IssueMessage *im)
-{
-  uint16_t size;
-
-  size = ntohs (im->header.size);
-  if (size <= sizeof (struct IssueMessage))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  scopes = (char *) &im[1];
-  if ('\0' != scopes[size - sizeof (struct IssueMessage) - 1])
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Malformed scopes received!\n");
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  return GNUNET_OK;
-}
-
 void
 attr_collect_task (void *cls)
 {
@@ -1338,8 +1462,6 @@ attr_collect_task (void *cls)
                                                                issue_handle);
 }
 
-
-
 void
 abe_key_lookup_error (void *cls)
 {
@@ -1372,6 +1494,38 @@ abe_key_lookup_result (void *cls,
 
 }
 
+
+/**
+ * Checks an issue message
+ *
+ * @param cls client sending the message
+ * @param im message of type `struct IssueMessage`
+ * @return #GNUNET_OK if @a im is well-formed
+ */
+static int
+check_issue_message(void *cls,
+                    const struct IssueMessage *im)
+{
+  uint16_t size;
+
+  size = ntohs (im->header.size);
+  if (size <= sizeof (struct IssueMessage))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  scopes = (char *) &im[1];
+  if ('\0' != scopes[size - sizeof (struct IssueMessage) - 1])
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Malformed scopes received!\n");
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
 /**
  *
  * Handler for issue message
@@ -1452,6 +1606,240 @@ handle_issue_message (void *cls,
 }
 
 static void
+cleanup_ticket_issue_handle (struct TicketIssueHandle *handle)
+{
+  struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
+  struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *tmp_le;
+
+  for (le = handle->attrs->list_head; NULL != le;)
+  {
+    GNUNET_free (le->attribute);
+    tmp_le = le;
+    le = le->next;
+    GNUNET_free (tmp_le);
+  }
+  GNUNET_free (handle->attrs);
+  if (NULL != handle->ns_qe)
+    GNUNET_NAMESTORE_cancel (handle->ns_qe);
+  GNUNET_free (handle);
+}
+
+static void
+store_ticket_issue_cont (void *cls,
+                        int32_t success,
+                        const char *emsg)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Ticket2 *ticket;
+  struct TicketIssueHandle *handle = cls;
+  struct TicketResultMessage *irm;
+  struct GNUNET_MQ_Envelope *env;
+
+  handle->ns_qe = NULL;
+  if (GNUNET_SYSERR == success)
+  {
+    cleanup_ticket_issue_handle (handle);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n",
+                "Unknown Error\n");
+    GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+    return;
+  }
+  env = GNUNET_MQ_msg_extra (irm,
+                             sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket2),
+                       GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT);
+  ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket2 *)&irm[1];
+  *ticket = handle->ticket;
+  irm->id = handle->r_id;
+
+  GNUNET_MQ_send (handle->client->mq,
+                  env);
+  cleanup_ticket_issue_handle (handle);
+}
+
+
+
+/**
+ * Checks a ticket issue message
+ *
+ * @param cls client sending the message
+ * @param im message of type `struct TicketIssueMessage`
+ * @return #GNUNET_OK if @a im is well-formed
+ */
+static int
+check_ticket_issue_message(void *cls,
+                           const struct TicketIssueMessage *im)
+{
+  uint16_t size;
+
+  size = ntohs (im->header.size);
+  if (size <= sizeof (struct IssueMessage))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+int
+serialize_abe_keyinfo2 (const struct TicketIssueHandle *handle,
+                 const struct GNUNET_CRYPTO_AbeKey *rp_key,
+                 struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey,
+                 char **result)
+{
+  struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey;
+  struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
+  char *enc_keyinfo;
+  char *serialized_key;
+  char *buf;
+  char *write_ptr;
+  char attrs_str_len;
+  ssize_t size;
+  
+  struct GNUNET_CRYPTO_SymmetricSessionKey skey;
+  struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
+  struct GNUNET_HashCode new_key_hash;
+  ssize_t enc_size;
+  
+  size = GNUNET_CRYPTO_cpabe_serialize_key (rp_key,
+                                            (void**)&serialized_key);
+  attrs_str_len = 0;
+  for (le = handle->attrs->list_head; NULL != le; le = le->next) {
+    attrs_str_len += strlen (le->attribute->name) + 1;
+  }
+  buf = GNUNET_malloc (attrs_str_len + size);
+  write_ptr = buf;
+  for (le = handle->attrs->list_head; NULL != le; le = le->next) {
+    GNUNET_memcpy (write_ptr,
+                   le->attribute->name,
+                   strlen (le->attribute->name));
+    write_ptr[strlen (le->attribute->name)] = ',';
+    write_ptr += strlen (le->attribute->name) + 1;
+  }
+  write_ptr--;
+  write_ptr[0] = '\0'; //replace last , with a 0-terminator
+  write_ptr++;
+  GNUNET_memcpy (write_ptr,
+                 serialized_key,
+                 size);
+  // ECDH keypair E = eG
+  *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create();
+  GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey,
+                                      &ecdh_pubkey);
+  enc_keyinfo = GNUNET_malloc (size + attrs_str_len);
+  // Derived key K = H(eB)
+  GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey,
+                                                        
&handle->ticket.audience,
+                                                        &new_key_hash));
+  create_sym_key_from_ecdh(&new_key_hash, &skey, &iv);
+  enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf,
+                                              size + attrs_str_len,
+                                              &skey, &iv,
+                                              enc_keyinfo);
+  *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+
+                           enc_size);
+  GNUNET_memcpy (*result,
+                 &ecdh_pubkey,
+                 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
+  GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey),
+                 enc_keyinfo,
+                 enc_size);
+  GNUNET_free (enc_keyinfo);
+  return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size;
+}
+
+
+
+static void
+issue_ticket_after_abe_bootstrap (void *cls,
+                           struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
+{
+  struct TicketIssueHandle *ih = cls;
+  struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
+  struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
+  struct GNUNET_GNSRECORD_Data code_record[1];
+  struct GNUNET_CRYPTO_AbeKey *rp_key;
+  char *code_record_data;
+  char **attrs;
+  char *label;
+  int attrs_len;
+  int i;
+  size_t code_record_len;
+
+  //Create new ABE key for RP
+  attrs_len = 0;
+  for (le = ih->attrs->list_head; NULL != le; le = le->next)
+    attrs_len++;
+  attrs = GNUNET_malloc (attrs_len);
+  i = 0;
+  for (le = ih->attrs->list_head; NULL != le; le = le->next) {
+    attrs[i] = (char*) le->attribute->name;
+    i++;
+  }
+  rp_key = GNUNET_CRYPTO_cpabe_create_key (abe_key,
+                                           attrs);
+  
+  //TODO review this wireformat
+  code_record_len = serialize_abe_keyinfo2 (ih,
+                                            rp_key,
+                                            &ecdhe_privkey,
+                                            &code_record_data);
+  code_record[0].data = code_record_data;
+  code_record[0].data_size = code_record_len;
+  code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us;
+  code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY;
+  code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
+
+  label = GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd,
+                                               sizeof (uint64_t));
+  //Publish record
+  ih->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
+                                              &ih->identity,
+                                              label,
+                                              1,
+                                              code_record,
+                                              &store_ticket_issue_cont,
+                                              ih);
+  GNUNET_free (ecdhe_privkey);
+  GNUNET_free (label);
+  GNUNET_free (code_record_data);
+}
+
+
+/**
+ *
+ * Handler for ticket issue message
+ *
+ * @param cls unused
+ * @param client who sent the message
+ * @param message the message
+ */
+static void
+handle_ticket_issue_message (void *cls,
+                             const struct TicketIssueMessage *im)
+{
+  struct TicketIssueHandle *ih;
+  struct IdpClient *idp = cls;
+  size_t attrs_len;
+
+  ih = GNUNET_new (struct TicketIssueHandle);
+  attrs_len = ntohs (im->attr_len);
+  ih->attrs = attribute_list_deserialize ((char*)&im[1], attrs_len);
+  ih->r_id = im->id;
+  ih->client = idp;
+  ih->identity = im->identity;
+  GNUNET_CRYPTO_ecdsa_key_get_public (&ih->identity,
+                                      &ih->ticket.identity);
+  ih->ticket.audience = im->rp;
+  ih->ticket.rnd =
+    GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
+                              UINT64_MAX);
+  bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih);
+  GNUNET_SERVICE_client_continue (idp->client);
+
+}
+
+
+
+static void
 cleanup_as_handle (struct AttributeStoreHandle *handle)
 {
   if (NULL != handle->attribute)
@@ -1481,10 +1869,10 @@ attr_store_cont (void *cls,
     return;
   }
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Sending ATTRIBUTE_STORE_RESPONSE message\n");
+  GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+              "Sending ATTRIBUTE_STORE_RESPONSE message\n");
   env = GNUNET_MQ_msg (acr_msg,
-                      
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE);
+                       
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE);
   acr_msg->id = htonl (as_handle->r_id);
   acr_msg->op_result = htonl (GNUNET_OK);
   GNUNET_MQ_send (as_handle->client->mq,
@@ -1500,6 +1888,8 @@ attr_store_task (void *cls)
   char* buf;
   size_t buf_size;
 
+  GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+              "Storing attribute\n");
   buf_size = attribute_serialize_get_size (as_handle->attribute);
   buf = GNUNET_malloc (buf_size);
 
@@ -1529,108 +1919,13 @@ attr_store_task (void *cls)
 
 }
 
-static void
-bootstrap_store_cont (void *cls,
-                      int32_t success,
-                      const char *emsg)
-{
-  struct AbeBootstrapHandle *abh = cls;
-  if (GNUNET_SYSERR == success)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed to bootstrap ABE master %s\n",
-                emsg);
-    abh->proc (abh->proc_cls, NULL);
-    GNUNET_free (abh->abe_key);
-    GNUNET_free (abh);
-    return;
-  }
-  abh->proc (abh->proc_cls, abh->abe_key);
-  GNUNET_free (abh);
-}
-
-static void
-bootstrap_store_task (void *cls)
-{
-  struct AbeBootstrapHandle *abh = cls;
-  struct GNUNET_GNSRECORD_Data rd[1];
-
-  rd[0].data_size = GNUNET_CRYPTO_cpabe_serialize_master_key (abh->abe_key,
-                                                              
(void**)&rd[0].data);
-  rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
-  rd[0].flags = GNUNET_GNSRECORD_RF_NONE | GNUNET_GNSRECORD_RF_PRIVATE;
-  rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
-  abh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
-                                               &abh->identity,
-                                               "+",
-                                               1,
-                                               rd,
-                                               &bootstrap_store_cont,
-                                               abh);
-}
-
-static void
-bootstrap_abe_error (void *cls)
-{
-  struct AbeBootstrapHandle *abh = cls;
-  GNUNET_free (abh);
-  abh->proc (abh->proc_cls, NULL);
-  GNUNET_free (abh);
-}
-
-
-
-static void
-bootstrap_abe_result (void *cls,
-                      const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-                      const char *label,
-                      unsigned int rd_count,
-                      const struct GNUNET_GNSRECORD_Data *rd)
-{
-  struct AbeBootstrapHandle *abh = cls;
-  struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
-  int i;
-
-  for (i=0;i<rd_count;i++) {
-    if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type)
-      continue;
-    abe_key = GNUNET_CRYPTO_cpabe_deserialize_master_key ((void**)rd[i].data,
-                                                          rd[i].data_size);
-    abh->proc (abh->proc_cls, abe_key);
-    GNUNET_free (abh);
-    return;
-  }
-
-  //No ABE master found, bootstrapping...
-  abh->abe_key = GNUNET_CRYPTO_cpabe_create_master_key ();
-  GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh);
-}
-
-static void
-bootstrap_abe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
-               AbeBootstrapResult proc,
-               void* cls)
-{
-  struct AbeBootstrapHandle *abh;
-
-  abh = GNUNET_new (struct AbeBootstrapHandle);
-  abh->proc = proc;
-  abh->proc_cls = cls;
-  abh->identity = *identity;
-  abh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
-                                                identity,
-                                                "+",
-                                                &bootstrap_abe_error,
-                                                abh,
-                                                &bootstrap_abe_result,
-                                                abh);
-
-}
 
 static void
 store_after_abe_bootstrap (void *cls,
                            struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
 {
+  GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+              "Finished ABE bootstrap\n");
   struct AttributeStoreHandle *ash = cls;
   ash->abe_key = abe_key;
   GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
@@ -1674,6 +1969,8 @@ handle_attribute_store_message (void *cls,
   struct AttributeStoreHandle *as_handle;
   struct IdpClient *idp = cls;
   size_t data_len;
+  GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+              "Received ATTRIBUTE_STORE message\n");
 
   data_len = ntohs (sam->attr_len);
 
@@ -1681,14 +1978,13 @@ handle_attribute_store_message (void *cls,
   as_handle->attribute = attribute_deserialize ((char*)&sam[1],
                                                 data_len);
 
-  as_handle->r_id = sam->id;
+  as_handle->r_id = ntohl (sam->id);
   as_handle->identity = sam->identity;
   GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity,
                                       &as_handle->identity_pkey);
 
   GNUNET_SERVICE_client_continue (idp->client);
   as_handle->client = idp;
-
   bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle);
 }
 
@@ -1697,6 +1993,9 @@ cleanup_iter_handle (struct AttributeIterator *ai)
 {
   if (NULL != ai->abe_key)
     GNUNET_free (ai->abe_key);
+  GNUNET_CONTAINER_DLL_remove (ai->client->op_head,
+                               ai->client->op_tail,
+                               ai);
   GNUNET_free (ai);
 }
 
@@ -2036,5 +2335,9 @@ GNUNET_SERVICE_MAIN
                           
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP,
                           struct AttributeIterationStopMessage,
                           NULL),
+ GNUNET_MQ_hd_var_size (ticket_issue_message,
+                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ISSUE,
+                        struct TicketIssueMessage,
+                        NULL),
  GNUNET_MQ_handler_end());
 /* end of gnunet-service-identity-provider.c */
diff --git a/src/identity-provider/identity_attribute.c 
b/src/identity-provider/identity_attribute.c
index 3794010b2..8cc94a731 100644
--- a/src/identity-provider/identity_attribute.c
+++ b/src/identity-provider/identity_attribute.c
@@ -63,17 +63,73 @@ attribute_new (const char* attr_name,
   return attr;
 }
 
+size_t
+attribute_list_serialize_get_size (const struct 
GNUNET_IDENTITY_PROVIDER_AttributeList *attrs)
+{
+  struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
+  size_t len = 0;
+  for (le = attrs->list_head; NULL != le; le = le->next)
+    len += attribute_serialize_get_size (le->attribute);
+  return len; 
+}
+
+size_t
+attribute_list_serialize (const struct GNUNET_IDENTITY_PROVIDER_AttributeList 
*attrs,
+                          char *result)
+{
+  struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
+  size_t len;
+  size_t total_len;
+  char* write_ptr;
+
+  write_ptr = result;
+  total_len = 0;
+  for (le = attrs->list_head; NULL != le; le = le->next)
+  {
+    len = attribute_serialize (le->attribute,
+                               write_ptr);
+    total_len += len;
+    write_ptr += len;
+  }
+  return total_len;
+}
+
+struct GNUNET_IDENTITY_PROVIDER_AttributeList *
+attribute_list_deserialize (const char* data,
+                       size_t data_size)
+{
+  struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs;
+  struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
+  size_t attr_len;
+  const char* read_ptr;
+
+  if (data_size < sizeof (struct Attribute))
+    return NULL;
+  
+  attrs = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeList);
+  read_ptr = data;
+  while (((data + data_size) - read_ptr) >= sizeof (struct Attribute))
+  {
+    le = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry);
+    le->attribute = attribute_deserialize (read_ptr,
+                                           data_size - (read_ptr - data));
+    attr_len = attribute_serialize_get_size (le->attribute);
+    read_ptr += attr_len;
+  }
+  return attrs;
+}
+
 
 
 size_t
 attribute_serialize_get_size (const struct GNUNET_IDENTITY_PROVIDER_Attribute 
*attr)
 {
   return sizeof (struct Attribute) 
-    + strlen (attr->name) + 1
+    + strlen (attr->name)
     + attr->data_size; //TODO get data_size from plugin
 }
 
-int
+size_t
 attribute_serialize (const struct GNUNET_IDENTITY_PROVIDER_Attribute *attr,
                      char *result)
 {
@@ -96,7 +152,7 @@ attribute_serialize (const struct 
GNUNET_IDENTITY_PROVIDER_Attribute *attr,
   GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
   attr_ser->data_size = htons (data_len_ser);
 
-  return GNUNET_OK;
+  return sizeof (struct Attribute) + strlen (attr->name) + attr->data_size;
 }
 
 struct GNUNET_IDENTITY_PROVIDER_Attribute *
@@ -108,7 +164,7 @@ attribute_deserialize (const char* data,
   size_t data_len;
   size_t name_len;
   char* write_ptr;
-  
+
   if (data_size < sizeof (struct Attribute))
     return NULL;
 
@@ -117,10 +173,10 @@ attribute_deserialize (const char* data,
   data_len = ntohs (attr_ser->data_size);
   name_len = ntohs (attr_ser->name_len);
   attr = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_Attribute)
-    + data_len + name_len + 1);
+                        + data_len + name_len + 1);
   attr->attribute_type = ntohs (attr_ser->attribute_type);
   attr->data_size = ntohs (attr_ser->data_size);
-  
+
   write_ptr =  (char*)&attr[1];
   GNUNET_memcpy (write_ptr,
                  &attr_ser[1],
diff --git a/src/identity-provider/identity_attribute.h 
b/src/identity-provider/identity_attribute.h
index 0d4f2bb76..00e520a38 100644
--- a/src/identity-provider/identity_attribute.h
+++ b/src/identity-provider/identity_attribute.h
@@ -51,6 +51,43 @@ struct Attribute
 /**
  * Get required size for serialization buffer
  *
+ * @param attrs the attribute list to serialize
+ *
+ * @return the required buffer size
+ */
+size_t
+attribute_list_serialize_get_size (const struct 
GNUNET_IDENTITY_PROVIDER_AttributeList *attrs);
+
+
+
+/**
+ * Serialize an attribute list
+ *
+ * @param attrs the attribute list to serialize
+ * @param result the serialized attribute
+ *
+ * @return length of serialized data
+ */
+size_t
+attribute_list_serialize (const struct GNUNET_IDENTITY_PROVIDER_AttributeList 
*attrs,
+                     char *result);
+
+/**
+ * Deserialize an attribute list
+ *
+ * @param data the serialized attribute list
+ * @param data_size the length of the serialized data
+ *
+ * @return a GNUNET_IDENTITY_PROVIDER_AttributeList, must be free'd by caller
+ */
+struct GNUNET_IDENTITY_PROVIDER_AttributeList *
+attribute_list_deserialize (const char* data,
+                            size_t data_size);
+
+
+/**
+ * Get required size for serialization buffer
+ *
  * @param attr the attribute to serialize
  *
  * @return the required buffer size
@@ -66,9 +103,9 @@ attribute_serialize_get_size (const struct 
GNUNET_IDENTITY_PROVIDER_Attribute *a
  * @param attr the attribute to serialize
  * @param result the serialized attribute
  *
- * @return GNUNET_OK on success
+ * @return length of serialized data
  */
-int 
+size_t
 attribute_serialize (const struct GNUNET_IDENTITY_PROVIDER_Attribute *attr,
                      char *result);
 
diff --git a/src/identity-provider/identity_provider.h 
b/src/identity-provider/identity_provider.h
index 588d6d39a..098885e3c 100644
--- a/src/identity-provider/identity_provider.h
+++ b/src/identity-provider/identity_provider.h
@@ -45,7 +45,7 @@ struct GNUNET_IDENTITY_PROVIDER_Token
 };
 
 /**
- * The ticket
+ * The ticket DEPRECATED
  */
 struct GNUNET_IDENTITY_PROVIDER_Ticket
 {
@@ -318,7 +318,55 @@ struct AttributeIterationStopMessage
 
 };
 
+/**
+ * Ticket issue message
+ */
+struct TicketIssueMessage
+{
+  /**
+   * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ISSUE
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+  /**
+   * Identity.
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+  /**
+   * Requesting party.
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey rp;
 
+  /**
+   * length of serialized attribute list
+   */
+  uint32_t attr_len GNUNET_PACKED;
+
+  //Followed by a serialized attribute list
+};
+
+/**
+ * Ticket result message
+ */
+struct TicketResultMessage
+{
+  /**
+   * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+};
 GNUNET_NETWORK_STRUCT_END
 
 #endif
diff --git a/src/identity-provider/identity_provider_api.c 
b/src/identity-provider/identity_provider_api.c
index c806735f6..74d15bbe0 100644
--- a/src/identity-provider/identity_provider_api.c
+++ b/src/identity-provider/identity_provider_api.c
@@ -81,6 +81,11 @@ struct GNUNET_IDENTITY_PROVIDER_Operation
   GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus as_cb;
 
   /**
+   * Ticket result callback
+   */
+  GNUNET_IDENTITY_PROVIDER_TicketCallback tr_cb;
+
+  /**
    * Envelope with the message for this queue entry.
    */
   struct GNUNET_MQ_Envelope *env;
@@ -590,6 +595,62 @@ handle_attribute_result (void *cls,
   GNUNET_assert (0);
 }
 
+/**
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT
+ *
+ * @param cls
+ * @param msg the message we received
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+static int
+check_ticket_result (void *cls,
+                        const struct TicketResultMessage *msg)
+{
+  size_t msg_len;
+
+  msg_len = ntohs (msg->header.size);
+  if (msg_len < sizeof (struct TicketResultMessage))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+
+/**
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT
+ *
+ * @param cls
+ * @param msg the message we received
+ */
+static void
+handle_ticket_result (void *cls,
+                     const struct TicketResultMessage *msg)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls;
+  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
+  const struct GNUNET_IDENTITY_PROVIDER_Ticket2 *ticket;
+  uint32_t r_id = ntohl (msg->id);
+
+  for (op = handle->op_head; NULL != op; op = op->next)
+    if (op->r_id == r_id)
+      break;
+  if (NULL == op)
+    return;
+  GNUNET_CONTAINER_DLL_remove (handle->op_head,
+                               handle->op_tail,
+                               op);
+  ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket2 *)&msg[1];
+  if (NULL != op->tr_cb)
+    op->tr_cb (op->cls, ticket);
+  GNUNET_free (op);
+
+}
+
 
 
 /**
@@ -617,6 +678,10 @@ reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h)
                            
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT,
                            struct AttributeResultMessage,
                            h),
+    GNUNET_MQ_hd_var_size (ticket_result,
+                             
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT,
+                             struct TicketResultMessage,
+                             h),
     GNUNET_MQ_handler_end ()
   };
   struct GNUNET_IDENTITY_PROVIDER_Operation *op;
@@ -1072,7 +1137,58 @@ GNUNET_IDENTITY_PROVIDER_get_attributes_stop (struct 
GNUNET_IDENTITY_PROVIDER_At
 }
 
 
+/** TODO
+ * Issues a ticket to another identity. The identity may use
+ * @GNUNET_IDENTITY_PROVIDER_authorization_ticket_consume to consume the ticket
+ * and retrieve the attributes specified in the AttributeList.
+ *
+ * @param h the identity provider to use
+ * @param iss the issuing identity
+ * @param rp the subject of the ticket (the relying party)
+ * @param attr the attributes that the relying party is given access to
+ * @param cb the callback
+ * @param cb_cls the callback closure
+ * @return handle to abort the operation
+ */
+struct GNUNET_IDENTITY_PROVIDER_Operation *
+GNUNET_IDENTITY_PROVIDER_idp_ticket_issue (struct 
GNUNET_IDENTITY_PROVIDER_Handle *h,
+                                           const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *iss,
+                                           const struct 
GNUNET_CRYPTO_EcdsaPublicKey *rp,
+                                           const struct 
GNUNET_IDENTITY_PROVIDER_AttributeList *attrs,
+                                           
GNUNET_IDENTITY_PROVIDER_TicketCallback cb,
+                                           void *cb_cls)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
+  struct TicketIssueMessage *tim;
+  size_t attr_len;
+
+  op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
+  op->h = h;
+  op->tr_cb = cb;
+  op->cls = cb_cls;
+  op->r_id = h->r_id_gen++;
+  GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
+                                    h->op_tail,
+                                    op);
+  attr_len = attribute_list_serialize_get_size (attrs);
+  op->env = GNUNET_MQ_msg_extra (tim,
+                                 attr_len,
+                                 
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ISSUE);
+  tim->identity = *iss;
+  tim->rp = *rp;
+  tim->id = htonl (op->r_id);
+
+  attribute_list_serialize (attrs,
+                            (char*)&tim[1]);
+
+  tim->attr_len = htons (attr_len);
+  if (NULL != h->mq)
+    GNUNET_MQ_send_copy (h->mq,
+                         op->env);
+  return op;
+}
+
 
 
 
-  /* end of identity_provider_api.c */
+/* end of identity_provider_api.c */
diff --git a/src/identity-provider/test_idp.sh 
b/src/identity-provider/test_idp.sh
index ce5c5ca69..598d1008c 100755
--- a/src/identity-provider/test_idp.sh
+++ b/src/identity-provider/test_idp.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-trap "gnunet-arm -e -c test_idp_lookup.conf" SIGINT
+#trap "gnunet-arm -e -c test_idp_lookup.conf" SIGINT
 
 LOCATION=$(which gnunet-config)
 if [ -z $LOCATION ]
@@ -25,8 +25,7 @@ which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
 TEST_ATTR="test"
 gnunet-arm -s -c test_idp.conf
 gnunet-identity -C testego -c test_idp.conf
-gnunet-idp -e testego --init -c test_idp.conf
-gnunet-idp -e testego -a email -V address@hidden -c test_idp.conf
+valgrind gnunet-idp -e testego -a email -V address@hidden -c test_idp.conf
 gnunet-idp -e testego -a name -V John -c test_idp.conf
 gnunet-idp -e testego -D -c test_idp.conf
 gnunet-arm -e -c test_idp.conf
diff --git a/src/identity-provider/test_idp.sh 
b/src/identity-provider/test_idp_issue.sh
similarity index 77%
copy from src/identity-provider/test_idp.sh
copy to src/identity-provider/test_idp_issue.sh
index ce5c5ca69..306f238d9 100755
--- a/src/identity-provider/test_idp.sh
+++ b/src/identity-provider/test_idp_issue.sh
@@ -25,8 +25,11 @@ which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
 TEST_ATTR="test"
 gnunet-arm -s -c test_idp.conf
 gnunet-identity -C testego -c test_idp.conf
-gnunet-idp -e testego --init -c test_idp.conf
+gnunet-identity -C rpego -c test_idp.conf
+SUBJECT_KEY=$(gnunet-identity -d -c test_idp.conf | grep rpego | awk '{print 
$3}')
 gnunet-idp -e testego -a email -V address@hidden -c test_idp.conf
 gnunet-idp -e testego -a name -V John -c test_idp.conf
 gnunet-idp -e testego -D -c test_idp.conf
+gnunet-idp -e testego -i "email,name" -r $SUBJECT_KEY -c test_idp.conf
+gnunet-namestore -z testego -D -c test_idp.conf
 gnunet-arm -e -c test_idp.conf
diff --git a/src/include/gnunet_identity_provider_service.h 
b/src/include/gnunet_identity_provider_service.h
index aaa838a03..cc71646bc 100644
--- a/src/include/gnunet_identity_provider_service.h
+++ b/src/include/gnunet_identity_provider_service.h
@@ -57,11 +57,32 @@ struct GNUNET_IDENTITY_PROVIDER_Handle;
 struct GNUNET_IDENTITY_PROVIDER_Token;
 
 /**
- * Handle for a ticket
+ * Handle for a ticket DEPRECATED
  */
 struct GNUNET_IDENTITY_PROVIDER_Ticket;
 
 /**
+ * The ticket
+ */
+struct GNUNET_IDENTITY_PROVIDER_Ticket2
+{
+  /**
+   * The ticket issuer
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey identity;
+
+  /**
+   * The ticket audience
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey audience;
+
+  /**
+   * The ticket random (NBO)
+   */
+  uint64_t rnd;
+};
+
+/**
  * Handle for an operation with the identity provider service.
  */
 struct GNUNET_IDENTITY_PROVIDER_Operation;
@@ -117,7 +138,36 @@ struct GNUNET_IDENTITY_PROVIDER_Attribute
 
 };
 
+struct GNUNET_IDENTITY_PROVIDER_AttributeList
+{
+  /**
+   * List head
+   */
+  struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *list_head;
 
+  /**
+   * List tail
+   */
+  struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *list_tail;
+};
+
+struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry
+{
+  /**
+   * DLL
+   */
+  struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *prev;
+
+  /**
+   * DLL
+   */
+  struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *next;
+
+  /**
+   * The attribute
+   */
+  struct GNUNET_IDENTITY_PROVIDER_Attribute *attribute;
+};
 
 /**
  * Method called when a token has been exchanged for a ticket.
@@ -280,6 +330,114 @@ void
 GNUNET_IDENTITY_PROVIDER_get_attributes_stop (struct 
GNUNET_IDENTITY_PROVIDER_AttributeIterator *it);
 
 
+/**
+ * Method called when a token has been issued.
+ * On success returns a ticket that can be given to the audience to retrive the
+ * token
+ *
+ * @param cls closure
+ * @param grant the label in GNS pointing to the token
+ * @param ticket the ticket
+ * @param token the issued token
+ * @param name name assigned by the user for this ego,
+ *                   NULL if the user just deleted the ego and it
+ *                   must thus no longer be used
+ */
+typedef void
+(*GNUNET_IDENTITY_PROVIDER_TicketCallback)(void *cls,
+                            const struct GNUNET_IDENTITY_PROVIDER_Ticket2 
*ticket);
+
+
+/** TODO
+ * Issues a ticket to another identity. The identity may use
+ * @GNUNET_IDENTITY_PROVIDER_authorization_ticket_consume to consume the ticket
+ * and retrieve the attributes specified in the AttributeList.
+ *
+ * @param id the identity provider to use
+ * @param iss the issuing identity
+ * @param rp the subject of the ticket (the relying party)
+ * @param attr the attributes that the relying party is given access to
+ * @param cb the callback
+ * @param cb_cls the callback closure
+ * @return handle to abort the operation
+ */
+struct GNUNET_IDENTITY_PROVIDER_Operation *
+GNUNET_IDENTITY_PROVIDER_idp_ticket_issue (struct 
GNUNET_IDENTITY_PROVIDER_Handle *id,
+                                           const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *iss,
+                                           const struct 
GNUNET_CRYPTO_EcdsaPublicKey *rp,
+                                           const struct 
GNUNET_IDENTITY_PROVIDER_AttributeList *attrs,
+                                           
GNUNET_IDENTITY_PROVIDER_TicketCallback cb,
+                                           void *cb_cls);
+
+/** TODO
+ * Revoked an issued ticket. The relying party will be unable to retrieve
+ * updated attributes.
+ *
+ * @param id the identity provider to use
+ * @param identity the issuing identity
+ * @param ticket the ticket to revoke
+ * @param cb the callback
+ * @param cb_cls the callback closure
+ * @return handle to abort the operation
+ */
+struct GNUNET_IDENTITY_PROVIDER_Operation *
+GNUNET_IDENTITY_PROVIDER_idp_ticket_revoke (struct 
GNUNET_IDENTITY_PROVIDER_Handle *id,
+                                            const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+                                            const struct 
GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+                                            
GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cb,
+                                            void *cb_cls);
+
+
+
+/** TODO
+ * Consumes an issued ticket. The ticket is persisted
+ * and used to retrieve identity information from the issuer
+ *
+ * @param id the identity provider to use
+ * @param identity the identity that is the subject of the issued ticket (the 
relying party)
+ * @param ticket the issued ticket to consume
+ * @param cb the callback to call
+ * @param cb_cls the callback closure
+ * @return handle to abort the operation
+ */
+struct GNUNET_IDENTITY_PROVIDER_Operation *
+GNUNET_IDENTITY_PROVIDER_rp_ticket_consume (struct 
GNUNET_IDENTITY_PROVIDER_Handle *id,
+                                            const struct 
GNUNET_CRYPTO_EcdsaPrivateKey * identity,
+                                            const struct 
GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+                                            
GNUNET_IDENTITY_PROVIDER_AttributeResult cb,
+                                            void *cb_cls);
+
+/** TODO
+ * Lists all tickets that have been issued to remote
+ * identites (relying parties)
+ *
+ * @param id the identity provider to use
+ * @param identity the issuing identity
+ * @param cb the callback to use
+ * @param cb_cls the callback closure
+ * @return handle to abort the operation
+ */
+struct GNUNET_IDENTITY_PROVIDER_Operation *
+GNUNET_IDENTITY_PROVIDER_idp_tickets_list (struct 
GNUNET_IDENTITY_PROVIDER_Handle *id,
+                                           const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+                                           
GNUNET_IDENTITY_PROVIDER_TicketCallback *cb,
+                                           void *cb_cls);
+
+/** TODO
+ * Lists all attributes that are shared with this identity
+ * by remote parties
+ *
+ * @param id identity provider service to use
+ * @param identity the identity (relying party)
+ * @param cb the result callback
+ * @param cb_cls the result callback closure
+ * @return handle to abort the operation
+ */
+struct GNUNET_IDENTITY_PROVIDER_Operation *
+GNUNET_IDENTITY_PROVIDER_rp_attributes_list (struct 
GNUNET_IDENTITY_PROVIDER_Handle *id,
+                                             const struct 
GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+                                             
GNUNET_IDENTITY_PROVIDER_AttributeResult *cb,
+                                             void *cb_cls);
 
 /**
  * Issue a token for a specific audience.
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index e498af1f5..1a7df377c 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -2640,17 +2640,21 @@ extern "C"
 
 #define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT 970
 
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ISSUE 971
+
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT 972
+
 /**************************************************
  *
  * CREDENTIAL MESSAGE TYPES
  */
-#define GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY     971
+#define GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY     981
 
-#define GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT 972
+#define GNUNET_MESSAGE_TYPE_CREDENTIAL_VERIFY_RESULT 982
 
-#define GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT 973
+#define GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT 983
 
-#define GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT_RESULT 974
+#define GNUNET_MESSAGE_TYPE_CREDENTIAL_COLLECT_RESULT 984
 
 
/******************************************************************************/
 

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]