add attestation API
authorSchanzenbach, Martin <mschanzenbach@posteo.de>
Tue, 4 Feb 2020 20:15:59 +0000 (21:15 +0100)
committerSchanzenbach, Martin <mschanzenbach@posteo.de>
Tue, 4 Feb 2020 20:15:59 +0000 (21:15 +0100)
src/include/gnunet_protocols.h
src/include/gnunet_reclaim_service.h
src/reclaim/gnunet-reclaim.c
src/reclaim/gnunet-service-reclaim.c
src/reclaim/plugin_rest_openid_connect.c
src/reclaim/plugin_rest_reclaim.c
src/reclaim/reclaim.h
src/reclaim/reclaim_api.c

index 8091fb3671af8ba01503ba119d19614cd3566b64..d92015787728abee666571855d35f09f363d1e04 100644 (file)
@@ -2720,21 +2720,26 @@ extern "C" {
 
 #define GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT 979
 
-#define GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_STORE 980
+#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_START 963
+
+#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_STOP 964
+
+#define GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_NEXT 965
+
 
 /**************************************************
  *
  * ABD MESSAGE TYPES
  */
-#define GNUNET_MESSAGE_TYPE_ABD_VERIFY 981
+#define GNUNET_MESSAGE_TYPE_ABD_VERIFY 991
 
-#define GNUNET_MESSAGE_TYPE_ABD_VERIFY_RESULT 982
+#define GNUNET_MESSAGE_TYPE_ABD_VERIFY_RESULT 992
 
-#define GNUNET_MESSAGE_TYPE_ABD_COLLECT 983
+#define GNUNET_MESSAGE_TYPE_ABD_COLLECT 993
 
-#define GNUNET_MESSAGE_TYPE_ABD_COLLECT_RESULT 984
+#define GNUNET_MESSAGE_TYPE_ABD_COLLECT_RESULT 994
 
-#define GNUNET_MESSAGE_TYPE_ABD_INTERMEDIATE_RESULT 985
+#define GNUNET_MESSAGE_TYPE_ABD_INTERMEDIATE_RESULT 995
 
 /******************************************************************************/
 
index 4ead87003e00ac869a2ad9854c6f863515d65db2..c9c4fa5d151c0575605f37d40f88e5a06df2486b 100644 (file)
@@ -107,7 +107,6 @@ typedef void (*GNUNET_RECLAIM_ContinuationWithStatus) (void *cls,
                                                        int32_t success,
                                                        const char *emsg);
 
-
 /**
  * Callback used to notify the client of attribute results.
  *
@@ -117,6 +116,18 @@ typedef void (*GNUNET_RECLAIM_ContinuationWithStatus) (void *cls,
  * @param attestation The attestation for the attribute (may be NULL)
  */
 typedef void (*GNUNET_RECLAIM_AttributeResult) (
+  void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+  const struct GNUNET_RECLAIM_Attribute *attr);
+
+/**
+ * Callback used to notify the client of attribute results.
+ *
+ * @param cls The callback closure
+ * @param identity The identity authoritative over the attributes
+ * @param attr The attribute
+ * @param attestation The attestation for the attribute (may be NULL)
+ */
+typedef void (*GNUNET_RECLAIM_AttributeTicketResult) (
   void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
   const struct GNUNET_RECLAIM_Attribute *attr,
   const struct GNUNET_RECLAIM_Attestation *attestation);
@@ -280,6 +291,63 @@ GNUNET_RECLAIM_get_attributes_stop (
   struct GNUNET_RECLAIM_AttributeIterator *it);
 
 
+/**
+ * List all attestations for a local identity.
+ * This MUST lock the `struct GNUNET_RECLAIM_Handle`
+ * for any other calls than #GNUNET_RECLAIM_get_attestations_next() and
+ * #GNUNET_RECLAIM_get_attestations_stop. @a proc will be called once
+ * immediately, and then again after
+ * #GNUNET_RECLAIM_get_attestations_next() is invoked.
+ *
+ * On error (disconnect), @a error_cb will be invoked.
+ * On normal completion, @a finish_cb proc will be
+ * invoked.
+ *
+ * @param h Handle to the re:claimID service
+ * @param identity Identity to iterate over
+ * @param error_cb Function to call on error (i.e. disconnect),
+ *        the handle is afterwards invalid
+ * @param error_cb_cls Closure for @a error_cb
+ * @param proc Function to call on each attestation
+ * @param proc_cls Closure for @a proc
+ * @param finish_cb Function to call on completion
+ *        the handle is afterwards invalid
+ * @param finish_cb_cls Closure for @a finish_cb
+ * @return an iterator Handle to use for iteration
+ */
+struct GNUNET_RECLAIM_AttestationIterator *
+GNUNET_RECLAIM_get_attestations_start (
+  struct GNUNET_RECLAIM_Handle *h,
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+  GNUNET_SCHEDULER_TaskCallback error_cb,
+  void *error_cb_cls,
+  GNUNET_RECLAIM_AttestationResult proc,
+  void *proc_cls,
+  GNUNET_SCHEDULER_TaskCallback finish_cb,
+  void *finish_cb_cls);
+
+
+/**
+ * Calls the record processor specified in #GNUNET_RECLAIM_get_attestation_start
+ * for the next record.
+ *
+ * @param it the iterator
+ */
+void
+GNUNET_RECLAIM_get_attestations_next (struct GNUNET_RECLAIM_AttestationIterator *ait);
+
+
+/**
+ * Stops iteration and releases the handle for further calls. Must
+ * be called on any iteration that has not yet completed prior to calling
+ * #GNUNET_RECLAIM_disconnect.
+ *
+ * @param it the iterator
+ */
+void
+GNUNET_RECLAIM_get_attestations_stop (struct GNUNET_RECLAIM_AttestationIterator *ait);
+
+
 /**
  * Issues a ticket to a relying party. The identity may use
  * GNUNET_RECLAIM_ticket_consume to consume the ticket
@@ -340,7 +408,7 @@ GNUNET_RECLAIM_ticket_consume (
   struct GNUNET_RECLAIM_Handle *h,
   const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
   const struct GNUNET_RECLAIM_Ticket *ticket,
-  GNUNET_RECLAIM_AttributeResult cb, void *cb_cls);
+  GNUNET_RECLAIM_AttributeTicketResult cb, void *cb_cls);
 
 
 /**
index b72336907b0e361f1e2234e41ca03c54b89db7f1..93d9ee3df4d0515fedd0334d0aa6afd54c43002d 100644 (file)
@@ -447,8 +447,7 @@ iter_finished (void *cls)
 static void
 iter_cb (void *cls,
          const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
-         const struct GNUNET_RECLAIM_Attribute *attr,
-         const struct GNUNET_RECLAIM_Attestation *attest)
+         const struct GNUNET_RECLAIM_Attribute *attr)
 {
   struct GNUNET_RECLAIM_AttributeListEntry *le;
   char *attrs_tmp;
index 15f9a8385946ca14b4d4a6b21163ddf998710718..f6fd04eeb24da8ede3cadba0d0b2739f051ed42c 100644 (file)
@@ -90,17 +90,17 @@ struct TicketIteration
 /**
  * An attribute iteration operation.
  */
-struct AttributeIterator
+struct Iterator
 {
   /**
    * Next element in the DLL
    */
-  struct AttributeIterator *next;
+  struct Iterator *next;
 
   /**
    * Previous element in the DLL
    */
-  struct AttributeIterator *prev;
+  struct Iterator *prev;
 
   /**
    * IDP client which intiated this zone iteration
@@ -121,6 +121,11 @@ struct AttributeIterator
    * The operation id fot the zone iteration in the response for the client
    */
   uint32_t request_id;
+
+  /**
+   * Context
+   */
+  void *ctx;
 };
 
 
@@ -154,14 +159,28 @@ struct IdpClient
    * Attribute iteration operations in
    * progress initiated by this client
    */
-  struct AttributeIterator *attr_iter_head;
+  struct Iterator *attr_iter_head;
+
+  /**
+   * Tail of the DLL of
+   * Attribute iteration operations
+   * in progress initiated by this client
+   */
+  struct Iterator *attr_iter_tail;
+
+  /**
+   * Head of the DLL of
+   * Attribute iteration operations in
+   * progress initiated by this client
+   */
+  struct Iterator *attest_iter_head;
 
   /**
    * Tail of the DLL of
    * Attribute iteration operations
    * in progress initiated by this client
    */
-  struct AttributeIterator *attr_iter_tail;
+  struct Iterator *attest_iter_tail;
 
   /**
    * Head of DLL of ticket iteration ops
@@ -512,7 +531,7 @@ cleanup_as_handle (struct AttributeStoreHandle *ash)
 static void
 cleanup_client (struct IdpClient *idp)
 {
-  struct AttributeIterator *ai;
+  struct Iterator *ai;
   struct TicketIteration *ti;
   struct TicketRevocationOperation *rop;
   struct TicketIssueOperation *iss;
@@ -550,6 +569,13 @@ cleanup_client (struct IdpClient *idp)
     GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
     GNUNET_free (ai);
   }
+  while (NULL != (ai = idp->attest_iter_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (idp->attest_iter_head, idp->attest_iter_tail,
+                                 ai);
+    GNUNET_free (ai);
+  }
+
   while (NULL != (rop = idp->revoke_op_head))
   {
     GNUNET_CONTAINER_DLL_remove (idp->revoke_op_head, idp->revoke_op_tail, rop);
@@ -1641,7 +1667,7 @@ handle_attestation_delete_message (void *cls,
 static void
 attr_iter_finished (void *cls)
 {
-  struct AttributeIterator *ai = cls;
+  struct Iterator *ai = cls;
   struct GNUNET_MQ_Envelope *env;
   struct AttributeResultMessage *arm;
 
@@ -1665,7 +1691,7 @@ attr_iter_finished (void *cls)
 static void
 attr_iter_error (void *cls)
 {
-  struct AttributeIterator *ai = cls;
+  struct Iterator *ai = cls;
 
   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over attributes\n");
   attr_iter_finished (ai);
@@ -1688,7 +1714,7 @@ attr_iter_cb (void *cls,
               unsigned int rd_count,
               const struct GNUNET_GNSRECORD_Data *rd)
 {
-  struct AttributeIterator *ai = cls;
+  struct Iterator *ai = cls;
   struct GNUNET_MQ_Envelope *env;
   char *data_tmp;
 
@@ -1697,71 +1723,25 @@ attr_iter_cb (void *cls,
     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
     return;
   }
-  if (rd_count > 1)
-  {
-    if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF == rd[0].record_type)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Found Ticket. Ignoring.\n");
-      GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
-      return;
-    }
-    else if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION != rd[0].record_type)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Non-Attestation record with multiple entries found: %u\n",
-                  rd[0].record_type);
-      GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
-      return;
-    }
-  }
 
   for (int i = 0; i<rd_count; i++)
   {
-    if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE != rd[i].record_type) &&
-        (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION != rd[i].record_type))
-    {
-      GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
-      return;
-    }
-    // FIXME Send attribute TOGETHER with respective attestation if applicable
-    if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE == rd[i].record_type)
-    {
-      struct AttributeResultMessage *arm;
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attribute under: %s\n",
-                  label);
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Sending ATTRIBUTE_RESULT message\n");
-      env = GNUNET_MQ_msg_extra (arm,
-                                 rd[i].data_size,
-                                 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
-      arm->id = htonl (ai->request_id);
-      arm->attr_len = htons (rd[i].data_size);
-      GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
-      data_tmp = (char *) &arm[1];
-      GNUNET_memcpy (data_tmp, rd[i].data, rd[i].data_size);
-      GNUNET_MQ_send (ai->client->mq, env);
-    }
-    else
-    {
-      if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION == rd[i].record_type)
-      {
-        struct AttributeResultMessage *arm;
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attestation under: %s\n",
-                    label);
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "Sending ATTESTATION_RESULT message\n");
-        env = GNUNET_MQ_msg_extra (arm,
-                                   rd[i].data_size,
-                                   GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT);
-        arm->id = htonl (ai->request_id);
-        arm->attr_len = htons (rd[i].data_size);
-        GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
-        data_tmp = (char *) &arm[1];
-        GNUNET_memcpy (data_tmp, rd[i].data, rd[i].data_size);
-        GNUNET_MQ_send (ai->client->mq, env);
-      }
-    }
+    if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE != rd[i].record_type)
+      continue;
+    struct AttributeResultMessage *arm;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attribute under: %s\n",
+                label);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Sending ATTRIBUTE_RESULT message\n");
+    env = GNUNET_MQ_msg_extra (arm,
+                               rd[i].data_size,
+                               GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
+    arm->id = htonl (ai->request_id);
+    arm->attr_len = htons (rd[i].data_size);
+    GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
+    data_tmp = (char *) &arm[1];
+    GNUNET_memcpy (data_tmp, rd[i].data, rd[i].data_size);
+    GNUNET_MQ_send (ai->client->mq, env);
   }
 }
 
@@ -1777,11 +1757,11 @@ handle_iteration_start (void *cls,
                         const struct AttributeIterationStartMessage *ais_msg)
 {
   struct IdpClient *idp = cls;
-  struct AttributeIterator *ai;
+  struct Iterator *ai;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Received ATTRIBUTE_ITERATION_START message\n");
-  ai = GNUNET_new (struct AttributeIterator);
+  ai = GNUNET_new (struct Iterator);
   ai->request_id = ntohl (ais_msg->id);
   ai->client = idp;
   ai->identity = ais_msg->identity;
@@ -1810,7 +1790,7 @@ handle_iteration_stop (void *cls,
                        const struct AttributeIterationStopMessage *ais_msg)
 {
   struct IdpClient *idp = cls;
-  struct AttributeIterator *ai;
+  struct Iterator *ai;
   uint32_t rid;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1843,7 +1823,7 @@ handle_iteration_next (void *cls,
                        const struct AttributeIterationNextMessage *ais_msg)
 {
   struct IdpClient *idp = cls;
-  struct AttributeIterator *ai;
+  struct Iterator *ai;
   uint32_t rid;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1863,6 +1843,200 @@ handle_iteration_next (void *cls,
 }
 
 
+/*************************************************
+* Attestation iteration
+*************************************************/
+
+
+/**
+ * Done iterating over attestations
+ *
+ * @param cls our iterator handle
+ */
+static void
+attest_iter_finished (void *cls)
+{
+  struct Iterator *ai = cls;
+  struct GNUNET_MQ_Envelope *env;
+  struct AttestationResultMessage *arm;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ATTESTATION_RESULT message\n");
+  env = GNUNET_MQ_msg (arm, GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT);
+  arm->id = htonl (ai->request_id);
+  arm->attestation_len = htons (0);
+  GNUNET_MQ_send (ai->client->mq, env);
+  GNUNET_CONTAINER_DLL_remove (ai->client->attest_iter_head,
+                               ai->client->attest_iter_tail,
+                               ai);
+  GNUNET_free (ai);
+}
+
+
+/**
+ * Error iterating over attestations. Abort.
+ *
+ * @param cls our attribute iteration handle
+ */
+static void
+attest_iter_error (void *cls)
+{
+  struct Iterator *ai = cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over attestations\n");
+  attest_iter_finished (ai);
+}
+
+
+/**
+ * Got record. Return attestation.
+ *
+ * @param cls our attribute iterator
+ * @param zone zone we are iterating
+ * @param label label of the records
+ * @param rd_count record count
+ * @param rd records
+ */
+static void
+attest_iter_cb (void *cls,
+                const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+                const char *label,
+                unsigned int rd_count,
+                const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct Iterator *ai = cls;
+  struct GNUNET_MQ_Envelope *env;
+  char *data_tmp;
+
+  if (rd_count == 0)
+  {
+    GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
+    return;
+  }
+
+  for (int i = 0; i<rd_count; i++)
+  {
+    if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION != rd[i].record_type)
+      continue;
+    struct AttestationResultMessage *arm;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attestation under: %s\n",
+                label);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Sending ATTESTATION_RESULT message\n");
+    env = GNUNET_MQ_msg_extra (arm,
+                               rd[i].data_size,
+                               GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT);
+    arm->id = htonl (ai->request_id);
+    arm->attestation_len = htons (rd[i].data_size);
+    GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
+    data_tmp = (char *) &arm[1];
+    GNUNET_memcpy (data_tmp, rd[i].data, rd[i].data_size);
+    GNUNET_MQ_send (ai->client->mq, env);
+  }
+}
+
+
+/**
+ * Iterate over zone to get attributes
+ *
+ * @param cls our client
+ * @param ais_msg the iteration message to start
+ */
+static void
+handle_attestation_iteration_start (void *cls,
+                                    const struct
+                                    AttestationIterationStartMessage *ais_msg)
+{
+  struct IdpClient *idp = cls;
+  struct Iterator *ai;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received ATTESTATION_ITERATION_START message\n");
+  ai = GNUNET_new (struct Iterator);
+  ai->request_id = ntohl (ais_msg->id);
+  ai->client = idp;
+  ai->identity = ais_msg->identity;
+
+  GNUNET_CONTAINER_DLL_insert (idp->attest_iter_head, idp->attest_iter_tail,
+                               ai);
+  ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
+                                                     &ai->identity,
+                                                     &attest_iter_error,
+                                                     ai,
+                                                     &attest_iter_cb,
+                                                     ai,
+                                                     &attest_iter_finished,
+                                                     ai);
+  GNUNET_SERVICE_client_continue (idp->client);
+}
+
+
+/**
+ * Handle iteration stop message from client
+ *
+ * @param cls the client
+ * @param ais_msg the stop message
+ */
+static void
+handle_attestation_iteration_stop (void *cls,
+                                   const struct
+                                   AttestationIterationStopMessage *ais_msg)
+{
+  struct IdpClient *idp = cls;
+  struct Iterator *ai;
+  uint32_t rid;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received `%s' message\n",
+              "ATTESTATION_ITERATION_STOP");
+  rid = ntohl (ais_msg->id);
+  for (ai = idp->attest_iter_head; NULL != ai; ai = ai->next)
+    if (ai->request_id == rid)
+      break;
+  if (NULL == ai)
+  {
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (idp->client);
+    return;
+  }
+  GNUNET_CONTAINER_DLL_remove (idp->attest_iter_head, idp->attest_iter_tail,
+                               ai);
+  GNUNET_free (ai);
+  GNUNET_SERVICE_client_continue (idp->client);
+}
+
+
+/**
+ * Client requests next attestation from iterator
+ *
+ * @param cls the client
+ * @param ais_msg the message
+ */
+static void
+handle_attestation_iteration_next (void *cls,
+                                   const struct
+                                   AttestationIterationNextMessage *ais_msg)
+{
+  struct IdpClient *idp = cls;
+  struct Iterator *ai;
+  uint32_t rid;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received ATTESTATION_ITERATION_NEXT message\n");
+  rid = ntohl (ais_msg->id);
+  for (ai = idp->attest_iter_head; NULL != ai; ai = ai->next)
+    if (ai->request_id == rid)
+      break;
+  if (NULL == ai)
+  {
+    GNUNET_break (0);
+    GNUNET_SERVICE_client_drop (idp->client);
+    return;
+  }
+  GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
+  GNUNET_SERVICE_client_continue (idp->client);
+}
+
+
 /******************************************************
 * Ticket iteration
 ******************************************************/
@@ -2115,6 +2289,19 @@ GNUNET_SERVICE_MAIN (
                            GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP,
                            struct AttributeIterationStopMessage,
                            NULL),
+  GNUNET_MQ_hd_fixed_size (attestation_iteration_start,
+                           GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_START,
+                           struct AttestationIterationStartMessage,
+                           NULL),
+  GNUNET_MQ_hd_fixed_size (attestation_iteration_next,
+                           GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_NEXT,
+                           struct AttestationIterationNextMessage,
+                           NULL),
+  GNUNET_MQ_hd_fixed_size (attestation_iteration_stop,
+                           GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_STOP,
+                           struct AttestationIterationStopMessage,
+                           NULL),
+
   GNUNET_MQ_hd_var_size (issue_ticket_message,
                          GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET,
                          struct IssueTicketMessage,
index 610f93dbed97c515c3424cfa5ab383b4775222e2..345dbeed6323d2b7bfd83b11e40364db94d492d7 100644 (file)
@@ -456,6 +456,12 @@ struct RequestHandle
    */
   struct GNUNET_RECLAIM_AttributeIterator *attr_it;
 
+  /**
+   * Attestation iterator
+   */
+  struct GNUNET_RECLAIM_AttestationIterator *attest_it;
+
+
   /**
    * Ticket iterator
    */
@@ -529,7 +535,6 @@ struct RequestHandle
 static void
 cleanup_handle (struct RequestHandle *handle)
 {
-  struct GNUNET_RECLAIM_AttributeListEntry *claim_entry;
   struct EgoEntry *ego_entry;
   struct EgoEntry *ego_tmp;
 
@@ -540,6 +545,8 @@ cleanup_handle (struct RequestHandle *handle)
     GNUNET_IDENTITY_disconnect (handle->identity_handle);
   if (NULL != handle->attr_it)
     GNUNET_RECLAIM_get_attributes_stop (handle->attr_it);
+  if (NULL != handle->attest_it)
+    GNUNET_RECLAIM_get_attestations_stop (handle->attest_it);
   if (NULL != handle->ticket_it)
     GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it);
   if (NULL != handle->idp)
@@ -961,7 +968,53 @@ oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
 
 
 static void
-oidc_collect_finished_cb (void *cls)
+oidc_attest_collect_finished_cb (void *cls)
+{
+  struct RequestHandle *handle = cls;
+
+  handle->attest_it = NULL;
+  handle->idp_op = GNUNET_RECLAIM_ticket_issue (handle->idp,
+                                                &handle->priv_key,
+                                                &handle->oidc->client_pkey,
+                                                handle->attr_list,
+                                                &oidc_ticket_issue_cb,
+                                                handle);
+}
+
+
+/**
+ * Collects all attributes for an ego if in scope parameter
+ */
+static void
+oidc_attest_collect (void *cls,
+                     const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
+                     const struct GNUNET_RECLAIM_Attestation *attest)
+{
+  struct RequestHandle *handle = cls;
+  struct GNUNET_RECLAIM_AttributeListEntry *le;
+
+  for (le = handle->attr_list->list_head; NULL != le; le = le->next)
+  {
+    if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&le->attribute->attestation,
+                                                 &attest->id))
+    {
+      struct GNUNET_RECLAIM_AttestationListEntry *ale;
+      ale = GNUNET_new (struct GNUNET_RECLAIM_AttestationListEntry);
+      ale->attestation = GNUNET_RECLAIM_attestation_new (attest->name,
+                                                         attest->type,
+                                                         attest->data,
+                                                         attest->data_size);
+      GNUNET_CONTAINER_DLL_insert (handle->attests_list->list_head,
+                                   handle->attests_list->list_tail,
+                                   ale);
+    }
+  }
+  GNUNET_RECLAIM_get_attestations_next (handle->attest_it);
+}
+
+
+static void
+oidc_attr_collect_finished_cb (void *cls)
 {
   struct RequestHandle *handle = cls;
 
@@ -974,6 +1027,17 @@ oidc_collect_finished_cb (void *cls)
     GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
     return;
   }
+  handle->attests_list = GNUNET_new (struct GNUNET_RECLAIM_AttestationList);
+  handle->attest_it =
+    GNUNET_RECLAIM_get_attestations_start (handle->idp,
+                                           &handle->priv_key,
+                                           &oidc_iteration_error,
+                                           handle,
+                                           &oidc_attest_collect,
+                                           handle,
+                                           &oidc_attest_collect_finished_cb,
+                                           handle);
+
   handle->idp_op = GNUNET_RECLAIM_ticket_issue (handle->idp,
                                                 &handle->priv_key,
                                                 &handle->oidc->client_pkey,
@@ -989,8 +1053,7 @@ oidc_collect_finished_cb (void *cls)
 static void
 oidc_attr_collect (void *cls,
                    const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
-                   const struct GNUNET_RECLAIM_Attribute *attr,
-                   const struct GNUNET_RECLAIM_Attestation *attest)
+                   const struct GNUNET_RECLAIM_Attribute *attr)
 {
   struct RequestHandle *handle = cls;
   struct GNUNET_RECLAIM_AttributeListEntry *le;
@@ -1026,18 +1089,6 @@ oidc_attr_collect (void *cls,
   GNUNET_CONTAINER_DLL_insert (handle->attr_list->list_head,
                                handle->attr_list->list_tail,
                                le);
-  if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&attr->attestation))
-  {
-    struct GNUNET_RECLAIM_AttestationListEntry *ale;
-    ale = GNUNET_new (struct GNUNET_RECLAIM_AttestationListEntry);
-    ale->attestation = GNUNET_RECLAIM_attestation_new (attest->name,
-                                                       attest->type,
-                                                       attest->data,
-                                                       attest->data_size);
-    GNUNET_CONTAINER_DLL_insert (handle->attests_list->list_head,
-                                 handle->attests_list->list_tail,
-                                 ale);
-  }
   GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
 }
 
@@ -1104,7 +1155,7 @@ code_redirect (void *cls)
                                                  handle,
                                                  &oidc_attr_collect,
                                                  handle,
-                                                 &oidc_collect_finished_cb,
+                                                 &oidc_attr_collect_finished_cb,
                                                  handle);
           return;
         }
index fcb34e11a0da636dd5041aac1eab0d5bd7e4330b..6f7a5987b4b111a154045e39f65eecd02f3fd14c 100644 (file)
@@ -712,13 +712,14 @@ list_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
   priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
   handle->idp = GNUNET_RECLAIM_connect (cfg);
   handle->attest_it = GNUNET_RECLAIM_get_attestations_start (handle->idp,
-                                                           priv_key,
-                                                           &collect_error_cb,
-                                                           handle,
-                                                           &attest_collect,
-                                                           handle,
-                                                           &collect_finished_cb,
-                                                           handle);
+                                                             priv_key,
+                                                             &collect_error_cb,
+                                                             handle,
+                                                             &attest_collect,
+                                                             handle,
+                                                             &
+                                                             collect_finished_cb,
+                                                             handle);
 }
 
 
@@ -1000,67 +1001,33 @@ parse_jwt (const struct GNUNET_RECLAIM_Attestation *attest,
 static void
 attr_collect (void *cls,
               const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
-              const struct GNUNET_RECLAIM_Attribute *attr,
-              const struct GNUNET_RECLAIM_Attestation *attest)
+              const struct GNUNET_RECLAIM_Attribute *attr)
 {
   struct RequestHandle *handle = cls;
   json_t *attr_obj;
   const char *type;
   char *id_str;
 
-  if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&attr->attestation))
-  {
-    struct GNUNET_RECLAIM_Attribute *attr2;
-    attr2 = parse_jwt (attest, attr->data);
-    if (NULL == attr2)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Attribute Collection with unparsed Attestation\n");
-      return;
-    }
-    attr2->name = attr->name;
-    char *tmp_value;
-    tmp_value = GNUNET_RECLAIM_attribute_value_to_string (attr2->type,
-                                                          attr2->data,
-                                                          attr2->data_size);
-    attr_obj = json_object ();
-    json_object_set_new (attr_obj, "value", json_string (tmp_value));
-    json_object_set_new (attr_obj, "name", json_string (attr2->name));
-    json_object_set_new (attr_obj, "flag", json_string ("1"));
-    type = GNUNET_RECLAIM_attribute_number_to_typename (attr2->type);
-    json_object_set_new (attr_obj, "type", json_string (type));
-    id_str = GNUNET_STRINGS_data_to_string_alloc (&attr2->id,
-                                                  sizeof(attr2->id));
-    json_object_set_new (attr_obj, "id", json_string (id_str));
-    json_array_append (handle->resp_object, attr_obj);
-    json_decref (attr_obj);
-    GNUNET_free (tmp_value);
-  }
-  else
-  {
-    char *tmp_value;
-    char *flag_str;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", attr->name);
-
-    tmp_value = GNUNET_RECLAIM_attribute_value_to_string (attr->type,
-                                                          attr->data,
-                                                          attr->data_size);
-
-    attr_obj = json_object ();
-    json_object_set_new (attr_obj, "value", json_string (tmp_value));
-    json_object_set_new (attr_obj, "name", json_string (attr->name));
-    GNUNET_asprintf (&flag_str,"%d",attr->flag);
-    json_object_set_new (attr_obj, "flag", json_string (flag_str));
-    type = GNUNET_RECLAIM_attribute_number_to_typename (attr->type);
-    json_object_set_new (attr_obj, "type", json_string (type));
-    id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->id,
-                                                  sizeof(attr->id));
-    json_object_set_new (attr_obj, "id", json_string (id_str));
-    json_array_append (handle->resp_object, attr_obj);
-    json_decref (attr_obj);
-    GNUNET_free (tmp_value);
-    GNUNET_RECLAIM_get_attributes_next (handle->attr_it);
-  }
+  char *tmp_value;
+  tmp_value = GNUNET_RECLAIM_attribute_value_to_string (attr->type,
+                                                        attr->data,
+                                                        attr->data_size);
+  attr_obj = json_object ();
+  json_object_set_new (attr_obj, "value", json_string (tmp_value));
+  json_object_set_new (attr_obj, "name", json_string (attr->name));
+
+  json_object_set_new (attr_obj, "flag", json_string ("1"));
+  type = GNUNET_RECLAIM_attribute_number_to_typename (attr->type);
+  json_object_set_new (attr_obj, "type", json_string (type));
+  id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->id,
+                                                sizeof(attr->id));
+  json_object_set_new (attr_obj, "id", json_string (id_str));
+  id_str = GNUNET_STRINGS_data_to_string_alloc (&attr->attestation,
+                                                sizeof(attr->attestation));
+  json_object_set_new (attr_obj, "attestation", json_string (id_str));
+  json_array_append (handle->resp_object, attr_obj);
+  json_decref (attr_obj);
+  GNUNET_free (tmp_value);
 }
 
 
index 3da49fe7a3796cd51d4828fe7ba11adb84f90164..7b5d7ab194a211e41ccf7eefa2a3cf7bb0547296 100644 (file)
@@ -195,12 +195,12 @@ struct AttestationResultMessage
 
 
 /**
- * Reference plus Attestation is returned from the idp.
+ * Start a attribute iteration for the given identity
  */
-struct ReferenceResultMessage
+struct AttributeIterationStartMessage
 {
   /**
-   * Message header
+   * Message
    */
   struct GNUNET_MessageHeader header;
 
@@ -210,34 +210,33 @@ struct ReferenceResultMessage
   uint32_t id GNUNET_PACKED;
 
   /**
-   * Length of serialized attestation data
+   * Identity.
    */
-  uint16_t attest_len GNUNET_PACKED;
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+};
 
-  /**
-   * Length of serialized reference data
-   */
-  uint16_t ref_len GNUNET_PACKED;
 
+/**
+ * Ask for next result of attribute iteration for the given operation
+ */
+struct AttributeIterationNextMessage
+{
   /**
-   * always zero (for alignment)
+   * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT
    */
-  uint16_t reserved GNUNET_PACKED;
+  struct GNUNET_MessageHeader header;
 
   /**
-   * The public key of the identity.
-   */
-  struct GNUNET_CRYPTO_EcdsaPublicKey identity;
-
-  /* followed by:
-   * serialized reference data + attestation data
+   * Unique identifier for this request (for key collisions).
    */
+  uint32_t id GNUNET_PACKED;
 };
 
+
 /**
- * Start a attribute iteration for the given identity
+ * Start a attestation iteration for the given identity
  */
-struct AttributeIterationStartMessage
+struct AttestationIterationStartMessage
 {
   /**
    * Message
@@ -257,9 +256,9 @@ struct AttributeIterationStartMessage
 
 
 /**
- * Ask for next result of attribute iteration for the given operation
+ * Ask for next result of attestation iteration for the given operation
  */
-struct AttributeIterationNextMessage
+struct AttestationIterationNextMessage
 {
   /**
    * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT
@@ -273,6 +272,23 @@ struct AttributeIterationNextMessage
 };
 
 
+/**
+ * Stop attestation iteration for the given operation
+ */
+struct AttestationIterationStopMessage
+{
+  /**
+   * Type will be #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+};
+
+
 /**
  * Stop attribute iteration for the given operation
  */
index 0fcf95ee360157635277547a5005705f159b0455..89b9ea0f75502b9b7b4ae69dc58e07fe57970036 100644 (file)
@@ -71,6 +71,11 @@ struct GNUNET_RECLAIM_Operation
    */
   GNUNET_RECLAIM_AttributeResult ar_cb;
 
+  /**
+   * Attribute result callback
+   */
+  GNUNET_RECLAIM_AttributeTicketResult atr_cb;
+
   /**
    * Attestation result callback
    */
@@ -607,11 +612,11 @@ handle_consume_ticket_result (void *cls,
     read_ptr = ((char *) &msg[1]) + attrs_len;
     attests =
       GNUNET_RECLAIM_attestation_list_deserialize (read_ptr, attests_len);
-    if (NULL != op->ar_cb)
+    if (NULL != op->atr_cb)
     {
       if (NULL == attrs)
       {
-        op->ar_cb (op->cls, &msg->identity, NULL, NULL);
+        op->atr_cb (op->cls, &msg->identity, NULL, NULL);
       }
       else
       {
@@ -626,7 +631,7 @@ handle_consume_ticket_result (void *cls,
                   GNUNET_RECLAIM_id_is_equal (&le->attribute->id,
                                               &ale->attestation->id))
               {
-                op->ar_cb (op->cls, &msg->identity,
+                op->atr_cb (op->cls, &msg->identity,
                            le->attribute, ale->attestation);
                 break;
               }
@@ -635,7 +640,7 @@ handle_consume_ticket_result (void *cls,
           }
           else     // No attestations
           {
-            op->ar_cb (op->cls, &msg->identity,
+            op->atr_cb (op->cls, &msg->identity,
                        le->attribute, NULL);
           }
         }
@@ -644,7 +649,7 @@ handle_consume_ticket_result (void *cls,
         attrs = NULL;
         attests = NULL;
       }
-      op->ar_cb (op->cls, NULL, NULL, NULL);
+      op->atr_cb (op->cls, NULL, NULL, NULL);
     }
     GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
     free_op (op);
@@ -730,7 +735,7 @@ handle_attribute_result (void *cls, const struct AttributeResultMessage *msg)
     if (NULL != op)
     {
       if (NULL != op->ar_cb)
-        op->ar_cb (op->cls, NULL, NULL, NULL);
+        op->ar_cb (op->cls, NULL, NULL);
       GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
       free_op (op);
     }
@@ -739,20 +744,16 @@ handle_attribute_result (void *cls, const struct AttributeResultMessage *msg)
 
   {
     struct GNUNET_RECLAIM_Attribute *attr;
-    struct GNUNET_RECLAIM_Attestation *attest;
-    char *read_ptr;
     attr = GNUNET_RECLAIM_attribute_deserialize ((char *) &msg[1], attr_len);
-    read_ptr = ((char *) &msg[1]) + attr_len;
-    attest = GNUNET_RECLAIM_attestation_deserialize (read_ptr, attest_len);
     if (NULL != it)
     {
       if (NULL != it->proc)
-        it->proc (it->proc_cls, &msg->identity, attr, attest);
+        it->proc (it->proc_cls, &msg->identity, attr);
     }
     else if (NULL != op)
     {
       if (NULL != op->ar_cb)
-        op->ar_cb (op->cls, &msg->identity, attr, attest);
+        op->ar_cb (op->cls, &msg->identity, attr);
     }
     GNUNET_free (attr);
     return;
@@ -1369,6 +1370,116 @@ GNUNET_RECLAIM_get_attributes_stop (struct GNUNET_RECLAIM_AttributeIterator *it)
 }
 
 
+/**
+ * List all attestations for a local identity.
+ * This MUST lock the `struct GNUNET_RECLAIM_Handle`
+ * for any other calls than #GNUNET_RECLAIM_get_attestations_next() and
+ * #GNUNET_RECLAIM_get_attestations_stop. @a proc will be called once
+ * immediately, and then again after
+ * #GNUNET_RECLAIM_get_attestations_next() is invoked.
+ *
+ * On error (disconnect), @a error_cb will be invoked.
+ * On normal completion, @a finish_cb proc will be
+ * invoked.
+ *
+ * @param h Handle to the re:claimID service
+ * @param identity Identity to iterate over
+ * @param error_cb Function to call on error (i.e. disconnect),
+ *        the handle is afterwards invalid
+ * @param error_cb_cls Closure for @a error_cb
+ * @param proc Function to call on each attestation
+ * @param proc_cls Closure for @a proc
+ * @param finish_cb Function to call on completion
+ *        the handle is afterwards invalid
+ * @param finish_cb_cls Closure for @a finish_cb
+ * @return an iterator Handle to use for iteration
+ */
+struct GNUNET_RECLAIM_AttestationIterator *
+GNUNET_RECLAIM_get_attestations_start (
+  struct GNUNET_RECLAIM_Handle *h,
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+  GNUNET_SCHEDULER_TaskCallback error_cb,
+  void *error_cb_cls,
+  GNUNET_RECLAIM_AttestationResult proc,
+  void *proc_cls,
+  GNUNET_SCHEDULER_TaskCallback finish_cb,
+  void *finish_cb_cls)
+{
+  struct GNUNET_RECLAIM_AttestationIterator *ait;
+  struct GNUNET_MQ_Envelope *env;
+  struct AttestationIterationStartMessage *msg;
+  uint32_t rid;
+
+  rid = h->r_id_gen++;
+  ait = GNUNET_new (struct GNUNET_RECLAIM_AttestationIterator);
+  ait->h = h;
+  ait->error_cb = error_cb;
+  ait->error_cb_cls = error_cb_cls;
+  ait->finish_cb = finish_cb;
+  ait->finish_cb_cls = finish_cb_cls;
+  ait->proc = proc;
+  ait->proc_cls = proc_cls;
+  ait->r_id = rid;
+  ait->identity = *identity;
+  GNUNET_CONTAINER_DLL_insert_tail (h->ait_head, h->ait_tail, ait);
+  env =
+    GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START);
+  msg->id = htonl (rid);
+  msg->identity = *identity;
+  if (NULL == h->mq)
+    ait->env = env;
+  else
+    GNUNET_MQ_send (h->mq, env);
+  return ait;
+}
+
+
+/**
+ * Calls the record processor specified in #GNUNET_RECLAIM_get_attestation_start
+ * for the next record.
+ *
+ * @param it the iterator
+ */
+void
+GNUNET_RECLAIM_get_attestations_next (struct GNUNET_RECLAIM_AttestationIterator *ait)
+{
+  struct GNUNET_RECLAIM_Handle *h = ait->h;
+  struct AttestationIterationNextMessage *msg;
+  struct GNUNET_MQ_Envelope *env;
+
+  env =
+    GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_NEXT);
+  msg->id = htonl (ait->r_id);
+  GNUNET_MQ_send (h->mq, env);
+}
+
+
+/**
+ * Stops iteration and releases the handle for further calls. Must
+ * be called on any iteration that has not yet completed prior to calling
+ * #GNUNET_RECLAIM_disconnect.
+ *
+ * @param it the iterator
+ */
+void
+GNUNET_RECLAIM_get_attestations_stop (struct GNUNET_RECLAIM_AttestationIterator *ait)
+{
+  struct GNUNET_RECLAIM_Handle *h = ait->h;
+  struct GNUNET_MQ_Envelope *env;
+  struct AttestationIterationStopMessage *msg;
+
+  if (NULL != h->mq)
+  {
+    env =
+      GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_STOP);
+    msg->id = htonl (ait->r_id);
+    GNUNET_MQ_send (h->mq, env);
+  }
+  free_ait (ait);
+}
+
+
+
 /**
  * Issues a ticket to another relying party. The identity may use
  * @GNUNET_RECLAIM_ticket_consume to consume the ticket
@@ -1436,7 +1547,7 @@ GNUNET_RECLAIM_ticket_consume (
   struct GNUNET_RECLAIM_Handle *h,
   const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
   const struct GNUNET_RECLAIM_Ticket *ticket,
-  GNUNET_RECLAIM_AttributeResult cb,
+  GNUNET_RECLAIM_AttributeTicketResult cb,
   void *cb_cls)
 {
   struct GNUNET_RECLAIM_Operation *op;
@@ -1444,7 +1555,7 @@ GNUNET_RECLAIM_ticket_consume (
 
   op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
   op->h = h;
-  op->ar_cb = cb;
+  op->atr_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);