-improve revocation handling
authorSchanzenbach, Martin <mschanzenbach@posteo.de>
Mon, 9 Oct 2017 12:45:42 +0000 (14:45 +0200)
committerSchanzenbach, Martin <mschanzenbach@posteo.de>
Mon, 9 Oct 2017 12:45:42 +0000 (14:45 +0200)
src/identity-provider/gnunet-service-identity-provider.c
src/identity-provider/identity_attribute.c
src/identity-provider/identity_attribute.h
src/identity-provider/plugin_identity_provider_sqlite.c
src/identity-provider/test_idp_attribute.sh
src/identity-provider/test_idp_issue.sh
src/include/gnunet_identity_provider_plugin.h
src/include/gnunet_identity_provider_service.h

index 2f477370e7ee25c32866a2b5ab86efb7273514ed..364c097b53b2617e6c88fc054a727ea6a1256b61 100644 (file)
@@ -424,7 +424,8 @@ struct ConsumeTicketHandle
    * Attributes
    */
   struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs;
-
+  
   /**
    * request id
    */
@@ -671,9 +672,11 @@ bootstrap_store_task (void *cls)
 {
   struct AbeBootstrapHandle *abh = cls;
   struct GNUNET_GNSRECORD_Data rd[1];
+  char *key;
 
   rd[0].data_size = GNUNET_CRYPTO_cpabe_serialize_master_key (abh->abe_key,
-                                                              (void**)&rd[0].data);
+                                                              (void**)&key);
+  rd[0].data = key;
   rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER;
   rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE;
   rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
@@ -684,7 +687,7 @@ bootstrap_store_task (void *cls)
                                                rd,
                                                &bootstrap_store_cont,
                                                abh);
-  GNUNET_free ((void*)rd[0].data);
+  GNUNET_free (key);
 }
 
 /**
@@ -717,7 +720,7 @@ bootstrap_abe_result (void *cls,
   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,
+    abe_key = GNUNET_CRYPTO_cpabe_deserialize_master_key (rd[i].data,
                                                           rd[i].data_size);
     abh->proc (abh->proc_cls, abe_key);
     GNUNET_free (abh);
@@ -1125,12 +1128,12 @@ reissue_ticket_cont (void *cls,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Continue DB iteration\n");
   rh->offset++;
   GNUNET_assert (GNUNET_SYSERR != (ret =
-                 TKT_database->iterate_tickets (TKT_database->cls,
-                                                &rh->ticket.identity,
-                                                GNUNET_NO,
-                                                rh->offset,
-                                                &ticket_reissue_proc,
-                                                rh)));
+                                   TKT_database->iterate_tickets (TKT_database->cls,
+                                                                  &rh->ticket.identity,
+                                                                  GNUNET_NO,
+                                                                  rh->offset,
+                                                                  &ticket_reissue_proc,
+                                                                  rh)));
   if (GNUNET_NO == ret)
   {
     send_revocation_finished (rh, GNUNET_OK);
@@ -1138,6 +1141,8 @@ reissue_ticket_cont (void *cls,
   }
 }
 
+static void
+revocation_reissue_tickets (struct TicketRevocationHandle *rh);
 
 
 /**
@@ -1154,14 +1159,17 @@ ticket_reissue_proc (void *cls,
 {
   struct TicketRevocationHandle *rh = cls;
   struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
+  struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le_rollover;
   struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey;
   struct GNUNET_GNSRECORD_Data code_record[1];
   struct GNUNET_CRYPTO_AbeKey *rp_key;
   char *code_record_data;
   char **attr_arr;
   char *label;
+  char *policy;
   int attrs_len;
   int i;
+  int reissue_ticket;
   size_t code_record_len;
 
 
@@ -1173,6 +1181,37 @@ ticket_reissue_proc (void *cls,
     cleanup_revoke_ticket_handle (rh);
     return;
   }
+
+  /* 
+   * Check if any attribute of this ticket intersects with a rollover attribute
+   */
+  reissue_ticket = GNUNET_NO;
+  for (le = attrs->list_head; NULL != le; le = le->next)
+  {
+    for (le_rollover = rh->rvk_attrs->list_head;
+         NULL != le_rollover;
+         le_rollover = le_rollover->next)
+    {
+      if (0 == strcmp (le_rollover->attribute->name,
+                       le->attribute->name))
+      {
+        reissue_ticket = GNUNET_YES;
+        break;
+      }
+    }
+    if (GNUNET_YES == reissue_ticket)
+      break;
+  }
+
+  if (GNUNET_NO == reissue_ticket)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Skipping ticket.\n");
+    rh->offset++;
+    revocation_reissue_tickets (rh);
+    return;
+  }
+
   //Create new ABE key for RP
   attrs_len = 0;
 
@@ -1183,9 +1222,12 @@ ticket_reissue_proc (void *cls,
   attr_arr = GNUNET_malloc ((attrs_len + 1)*sizeof (char*));
   i = 0;
   for (le = attrs->list_head; NULL != le; le = le->next) {
+    GNUNET_asprintf (&policy, "%s:%lu",
+                     le->attribute->name,
+                     le->attribute->attribute_version);
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Recreating key with %s\n", (char*) le->attribute->name);
-    attr_arr[i] = (char*) le->attribute->name;
+                "Recreating key with %s\n", policy);
+    attr_arr[i] = policy;
     i++;
   }
   attr_arr[i] = NULL;
@@ -1214,6 +1256,8 @@ ticket_reissue_proc (void *cls,
                                               code_record,
                                               &reissue_ticket_cont,
                                               rh);
+  for (; i > 0; i--)
+    GNUNET_free (attr_arr[i]);
   GNUNET_free (ecdhe_privkey);
   GNUNET_free (label);
   GNUNET_free (attr_arr);
@@ -1262,30 +1306,43 @@ reenc_next_attribute (struct TicketRevocationHandle *rh)
   struct GNUNET_GNSRECORD_Data rd[1];
   char* buf;
   char* enc_buf;
+  size_t enc_size;
+  char* rd_buf;
   size_t buf_size;
+  char* policy;
+  uint32_t attr_ver;
 
   if (NULL == rh->attrs->list_head)
   {
     revocation_reissue_tickets (rh);
     return;
   }
-
   buf_size = attribute_serialize_get_size (rh->attrs->list_head->attribute);
   buf = GNUNET_malloc (buf_size);
-
   attribute_serialize (rh->attrs->list_head->attribute,
                        buf);
-
+  rh->attrs->list_head->attribute->attribute_version++;
+  GNUNET_asprintf (&policy, "%s:%lu", rh->attrs->list_head->attribute->name, rh->attrs->list_head->attribute->attribute_version);
   /**
    * Encrypt the attribute value and store in namestore
    */
-  rd[0].data_size = GNUNET_CRYPTO_cpabe_encrypt (buf,
-                                                 buf_size,
-                                                 rh->attrs->list_head->attribute->name, //Policy
-                                                 rh->abe_key,
-                                                 (void**)&enc_buf);
+  enc_size = GNUNET_CRYPTO_cpabe_encrypt (buf,
+                                          buf_size,
+                                          policy, //Policy
+                                          rh->abe_key,
+                                          (void**)&enc_buf);
   GNUNET_free (buf);
-  rd[0].data = enc_buf;
+  GNUNET_free (policy);
+  rd[0].data_size = enc_size + sizeof (uint32_t);
+  rd_buf = GNUNET_malloc (rd[0].data_size);
+  attr_ver = htonl (rh->attrs->list_head->attribute->attribute_version);
+  GNUNET_memcpy (rd_buf,
+                 &attr_ver,
+                 sizeof (uint32_t));
+  GNUNET_memcpy (rd_buf+sizeof (uint32_t),
+                 enc_buf,
+                 enc_size);
+  rd[0].data = rd_buf;
   rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
   rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
   rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
@@ -1297,7 +1354,7 @@ reenc_next_attribute (struct TicketRevocationHandle *rh)
                                               &attr_reenc_cont,
                                               rh);
   GNUNET_free (enc_buf);
-
+  GNUNET_free (rd_buf);
 }
 
 /**
@@ -1329,8 +1386,9 @@ attr_reenc_cont (void *cls,
   GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head,
                                rh->attrs->list_tail,
                                le);
-  GNUNET_free (le->attribute);
-  GNUNET_free (le);
+  GNUNET_CONTAINER_DLL_insert (rh->rvk_attrs->list_head,
+                               rh->rvk_attrs->list_tail,
+                               le);
 
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1339,18 +1397,17 @@ attr_reenc_cont (void *cls,
 }
 
 
-/**
- * Start reencryption with newly generated ABE master
- */
 static void
-reenc_after_abe_bootstrap (void *cls,
-                           struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
+process_attributes_to_update (void *cls,
+                              const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+                              const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs)
 {
   struct TicketRevocationHandle *rh = cls;
-  GNUNET_free (rh->abe_key);
-  GNUNET_assert (NULL != abe_key);
-  rh->abe_key = abe_key;
 
+  rh->attrs = attribute_list_dup (attrs);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Revocation Phase I: Collecting attributes\n");
+  /* Reencrypt all attributes with new key */
   if (NULL == rh->attrs->list_head)
   {
     /* No attributes to reencrypt */
@@ -1359,111 +1416,9 @@ reenc_after_abe_bootstrap (void *cls,
     return;
   } else {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Revocation Phase III: Re-encrypting attributes\n");
+                "Revocation Phase II: Re-encrypting attributes\n");
     reenc_next_attribute (rh);
   }
-}
-
-
-/**
- * Collecting attributes failed... abort.
- */
-static void
-revoke_collect_iter_error (void *cls)
-{
-  struct TicketRevocationHandle *rh = cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-              "Failed to iterate over attributes\n");
-  rh->ns_it = NULL;
-  send_revocation_finished (rh, GNUNET_SYSERR);
-  cleanup_revoke_ticket_handle (rh);
-}
-
-/**
- * Done decrypting existing attributes.
- */
-static void
-revoke_collect_iter_finished (void *cls)
-{
-  struct TicketRevocationHandle *rh = cls;
-  rh->ns_it = NULL;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Revocation Phase II: Invalidating old ABE Master\n");
-  /* Bootstrap new abe key */
-  bootstrap_abe (&rh->identity, &reenc_after_abe_bootstrap, rh, GNUNET_YES);
-}
-
-/**
- * Decrypt existing attribute and store it
- * We will revoke it by reencrypting it with a new ABE master key.
- */
-static void
-revoke_collect_iter_cb (void *cls,
-                        const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-                        const char *label,
-                        unsigned int rd_count,
-                        const struct GNUNET_GNSRECORD_Data *rd)
-{
-  struct TicketRevocationHandle *rh = cls;
-  struct GNUNET_CRYPTO_AbeKey *key;
-  struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
-  ssize_t attr_len;
-  char* attr_ser;
-  char* attrs[2];
-
-  if (rd_count != 1)
-  {
-    GNUNET_NAMESTORE_zone_iterator_next (rh->ns_it);
-    return;
-  }
-
-  if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) {
-    GNUNET_NAMESTORE_zone_iterator_next (rh->ns_it);
-    return;
-  }
-  attrs[0] = (char*)label;
-  attrs[1] = 0;
-  key = GNUNET_CRYPTO_cpabe_create_key (rh->abe_key,
-                                        attrs);
-  attr_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data,
-                                          rd->data_size,
-                                          key,
-                                          (void**)&attr_ser);
-  GNUNET_CRYPTO_cpabe_delete_key (key);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Attribute to reencrypt: %s\n", label);
-  le = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry);
-  le->attribute = attribute_deserialize (attr_ser, attr_len);
-  GNUNET_free (attr_ser);
-  GNUNET_CONTAINER_DLL_insert_tail (rh->attrs->list_head,
-                                    rh->attrs->list_tail,
-                                    le);
-  GNUNET_NAMESTORE_zone_iterator_next (rh->ns_it);
-}
-
-/**
- * Start attribute collection for revocation
- */
-static void
-collect_after_abe_bootstrap (void *cls,
-                             struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
-{
-  struct TicketRevocationHandle *rh = cls;
-
-  rh->abe_key = abe_key;
-  GNUNET_assert (NULL != abe_key);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Revocation Phase I: Collecting attributes\n");
-  /* Reencrypt all attributes with new key */
-  rh->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
-                                                     &rh->identity,
-                                                     &revoke_collect_iter_error,
-                                                     rh,
-                                                     &revoke_collect_iter_cb,
-                                                     rh,
-                                                     &revoke_collect_iter_finished,
-                                                     rh);
 
 }
 
@@ -1490,7 +1445,6 @@ check_revoke_ticket_message(void *cls,
   return GNUNET_OK;
 }
 
-
 /**
  *
  * Handler for ticket revocation message
@@ -1513,7 +1467,7 @@ handle_revoke_ticket_message (void *cls,
   ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket*)&rm[1];
   if (0 < attrs_len)
     rh->rvk_attrs = attribute_list_deserialize ((char*)&ticket[1], attrs_len);
-  rh->attrs = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeList);
+  rh->rvk_attrs = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeList);
   rh->ticket = *ticket;
   rh->r_id = ntohl (rm->id);
   rh->client = idp;
@@ -1523,7 +1477,11 @@ handle_revoke_ticket_message (void *cls,
   GNUNET_CONTAINER_DLL_insert (idp->revocation_list_head,
                                idp->revocation_list_tail,
                                rh);
-  bootstrap_abe (&rh->identity, &collect_after_abe_bootstrap, rh, GNUNET_NO);
+  TKT_database->get_ticket_attributes (TKT_database->cls,
+                                       &rh->ticket,
+                                       &process_attributes_to_update,
+                                       rh);
+  //bootstrap_abe (&rh->identity, &collect_after_abe_bootstrap, rh, GNUNET_NO);
   GNUNET_SERVICE_client_continue (idp->client);
 
 }
@@ -1586,13 +1544,14 @@ process_parallel_lookup2 (void *cls, uint32_t rd_count,
     GNUNET_break(0);//TODO
   if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR)
   {
-    attr_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data,
-                                            rd->data_size,
+    attr_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data + sizeof (uint32_t),
+                                            rd->data_size - sizeof (uint32_t),
                                             handle->key,
                                             (void**)&data);
     attr_le = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry);
     attr_le->attribute = attribute_deserialize (data,
                                                 attr_len);
+    attr_le->attribute->attribute_version = ntohl(*(uint32_t*)rd->data);
     GNUNET_CONTAINER_DLL_insert (handle->attrs->list_head,
                                  handle->attrs->list_tail,
                                  attr_le);
@@ -1829,7 +1788,12 @@ attr_store_task (void *cls)
   struct AttributeStoreHandle *as_handle = cls;
   struct GNUNET_GNSRECORD_Data rd[1];
   char* buf;
+  char* policy;
+  char* enc_buf;
+  char* rd_buf;
+  size_t enc_size;
   size_t buf_size;
+  uint32_t attr_ver;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Storing attribute\n");
@@ -1839,15 +1803,30 @@ attr_store_task (void *cls)
   attribute_serialize (as_handle->attribute,
                        buf);
 
+  GNUNET_asprintf (&policy,
+                   "%s:%lu",
+                   as_handle->attribute->name,
+                   as_handle->attribute->attribute_version);
   /**
    * Encrypt the attribute value and store in namestore
    */
-  rd[0].data_size = GNUNET_CRYPTO_cpabe_encrypt (buf,
-                                                 buf_size,
-                                                 as_handle->attribute->name, //Policy
-                                                 as_handle->abe_key,
-                                                 (void**)&rd[0].data);
+  enc_size = GNUNET_CRYPTO_cpabe_encrypt (buf,
+                                          buf_size,
+                                          policy, //Policy
+                                          as_handle->abe_key,
+                                          (void**)&enc_buf);
   GNUNET_free (buf);
+  GNUNET_free (policy);
+  rd[0].data_size = enc_size + sizeof (uint32_t);
+  rd_buf = GNUNET_malloc (rd[0].data_size);
+  attr_ver = htonl (as_handle->attribute->attribute_version);
+  GNUNET_memcpy (rd_buf,
+                 &attr_ver,
+                 sizeof (uint32_t));
+  GNUNET_memcpy (rd_buf+sizeof (uint32_t),
+                 enc_buf,
+                 enc_size);
+  rd[0].data = rd_buf;
   rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
   rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
   rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
@@ -1858,8 +1837,8 @@ attr_store_task (void *cls)
                                                      rd,
                                                      &attr_store_cont,
                                                      as_handle);
-  GNUNET_free ((void*)rd[0].data);
-
+  GNUNET_free (enc_buf);
+  GNUNET_free (rd_buf);
 }
 
 
@@ -1982,6 +1961,7 @@ attr_iter_cb (void *cls,
   char* attr_ser;
   char* attrs[2];
   char* data_tmp;
+  char* policy;
 
   if (rd_count != 1)
   {
@@ -1993,15 +1973,18 @@ attr_iter_cb (void *cls,
     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
     return;
   }
-  attrs[0] = (char*)label;
+  GNUNET_asprintf (&policy, "%s:%lu",
+                   label, *(uint32_t*)rd->data);
+  attrs[0] = policy;
   attrs[1] = 0;
   key = GNUNET_CRYPTO_cpabe_create_key (ai->abe_key,
                                         attrs);
-  msg_extra_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data,
-                                               rd->data_size,
+  msg_extra_len = GNUNET_CRYPTO_cpabe_decrypt (rd->data+sizeof (uint32_t),
+                                               rd->data_size-sizeof (uint32_t),
                                                key,
                                                (void**)&attr_ser);
   GNUNET_CRYPTO_cpabe_delete_key (key);
+  GNUNET_free (policy);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Found attribute: %s\n", label);
   env = GNUNET_MQ_msg_extra (arm,
index b90a08e3e67708eb8d2ec68aa953d8b32e51f44b..a8d2b27e6935a7111db1092b58d8601e9cb2784f 100644 (file)
@@ -125,6 +125,31 @@ attribute_list_deserialize (const char* data,
   return attrs;
 }
 
+struct GNUNET_IDENTITY_PROVIDER_AttributeList*
+attribute_list_dup (const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs)
+{
+  struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *le;
+  struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry *result_le;
+  struct GNUNET_IDENTITY_PROVIDER_AttributeList *result;
+  size_t len;
+
+  result = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeList);
+  for (le = attrs->list_head; NULL != le; le = le->next)
+  {
+    result_le = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeListEntry);
+    len = sizeof (struct GNUNET_IDENTITY_PROVIDER_Attribute) + le->attribute->data_size;
+    result_le->attribute = GNUNET_malloc (len);
+    GNUNET_memcpy (result_le->attribute,
+                   le->attribute,
+                   len);
+    GNUNET_CONTAINER_DLL_insert (result->list_head,
+                                 result->list_tail,
+                                 result_le);
+  }
+  return result;
+}
+
+
 void
 attribute_list_destroy (struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs)
 {
index d44f4c17f6ecc29518c321917a561e3a2a0451e0..8a8da12f1897994e220d36e219491c03052f6314 100644 (file)
@@ -138,5 +138,7 @@ attribute_new (const char* attr_name,
                const void* data,
                size_t data_size);
 
+struct GNUNET_IDENTITY_PROVIDER_AttributeList*
+attribute_list_dup (const struct GNUNET_IDENTITY_PROVIDER_AttributeList *attrs);
 
 #endif
index c55366214a32dd89a262b8c666df88b2d25e6a65..c87f30e1caf73f067d01ebecf933e9e02d5075a8 100644 (file)
@@ -87,6 +87,11 @@ struct Plugin
    */
   sqlite3_stmt *iterate_tickets;
 
+  /**
+   * Precompiled SQL to get ticket attributes.
+   */
+  sqlite3_stmt *get_ticket_attrs;
+  
   /**
    * Precompiled SQL to iterate tickets by audience.
    */
@@ -276,6 +281,11 @@ database_setup (struct Plugin *plugin)
         sq_prepare (plugin->dbh,
                     "DELETE FROM identity001tickets WHERE identity=? AND rnd=?",
                     &plugin->delete_ticket)) ||
+       (SQLITE_OK !=
+        sq_prepare (plugin->dbh,
+                    "SELECT identity,audience,rnd,attributes"
+                    " FROM identity001tickets WHERE identity=? AND rnd=?",
+                    &plugin->get_ticket_attrs)) ||
        (SQLITE_OK !=
         sq_prepare (plugin->dbh,
                     "SELECT identity,audience,rnd,attributes"
@@ -317,6 +327,8 @@ database_shutdown (struct Plugin *plugin)
     sqlite3_finalize (plugin->iterate_tickets);
   if (NULL != plugin->iterate_tickets_by_audience)
     sqlite3_finalize (plugin->iterate_tickets_by_audience);
+  if (NULL != plugin->get_ticket_attrs)
+    sqlite3_finalize (plugin->get_ticket_attrs);
   result = sqlite3_close (plugin->dbh);
   if (result == SQLITE_BUSY)
   {
@@ -564,6 +576,47 @@ get_ticket_and_call_iterator (struct Plugin *plugin,
   return ret;
 }
 
+
+/**
+ * Lookup tickets in the datastore.
+ *
+ * @param cls closure (internal context for the plugin)
+ * @param zone private key of the zone
+ * @param label name of the record in the zone
+ * @param iter function to call with the result
+ * @param iter_cls closure for @a iter
+ * @return #GNUNET_OK on success, else #GNUNET_SYSERR
+ */
+static int
+identity_provider_sqlite_ticket_get_attrs (void *cls,
+                                           const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+                                           GNUNET_IDENTITY_PROVIDER_TicketIterator iter,
+                                           void *iter_cls)
+{
+  struct Plugin *plugin = cls;
+  struct GNUNET_SQ_QueryParam params[] = {
+    GNUNET_SQ_query_param_auto_from_type (&ticket->identity),
+    GNUNET_SQ_query_param_uint64 (&ticket->rnd),
+    GNUNET_SQ_query_param_end
+  };
+
+  if (GNUNET_OK !=
+      GNUNET_SQ_bind (plugin->get_ticket_attrs,
+                      params))
+  {
+    LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+                "sqlite3_bind_XXXX");
+    GNUNET_SQ_reset (plugin->dbh,
+                     plugin->get_ticket_attrs);
+    return GNUNET_SYSERR;
+  }
+  return get_ticket_and_call_iterator (plugin,
+                                       plugin->get_ticket_attrs,
+                                       iter,
+                                       iter_cls);
+}
+
+
 /**
  * Iterate over the results for a particular key and zone in the
  * datastore.  Will return at most one result to the iterator.
@@ -653,6 +706,7 @@ libgnunet_plugin_identity_provider_sqlite_init (void *cls)
   api->store_ticket = &identity_provider_sqlite_store_ticket;
   api->delete_ticket = &identity_provider_sqlite_delete_ticket;
   api->iterate_tickets = &identity_provider_sqlite_iterate_tickets;
+  api->get_ticket_attributes = &identity_provider_sqlite_ticket_get_attrs;
   LOG (GNUNET_ERROR_TYPE_INFO,
        _("Sqlite database running\n"));
   return api;
index 0b0436ede21b79e477008e3d25d0a86440e6f94d..7e86ae532e8f7a3bd1907279ad9ab169d1270b90 100755 (executable)
@@ -24,11 +24,12 @@ which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
 
 TEST_ATTR="test"
 gnunet-arm -s -c test_idp.conf
-gnunet-arm -i rest -c test_idp.conf
+#gnunet-arm -i rest -c test_idp.conf
 gnunet-identity -C testego -c test_idp.conf
 gnunet-identity -C rpego -c test_idp.conf
 TEST_KEY=$(gnunet-identity -d -c test_idp.conf | grep testego | awk '{print $3}')
 gnunet-idp -e testego -a email -V john@doe.gnu -c test_idp.conf
 gnunet-idp -e testego -a name -V John -c test_idp.conf
-curl localhost:7776/idp/attributes/testego
+gnunet-idp -e testego -D -c test_idp.conf
+#curl localhost:7776/idp/attributes/testego
 gnunet-arm -e -c test_idp.conf
index bf5783c9ddc4505066e100c2d4b826946571c706..26c490c76c0cec5fea488e34a46ab4f52cf9bc73 100755 (executable)
@@ -24,7 +24,7 @@ which timeout &> /dev/null && DO_TIMEOUT="timeout 30"
 
 TEST_ATTR="test"
 gnunet-arm -s -c test_idp.conf
-#gnunet-arm -i rest -c test_idp.conf
+gnunet-arm -i rest -c test_idp.conf
 gnunet-identity -C testego -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}')
@@ -35,4 +35,4 @@ gnunet-idp -e testego -a name -V John -c test_idp.conf > /dev/null 2>&1
 TICKET=$(gnunet-idp -e testego -i "email,name" -r $SUBJECT_KEY -c test_idp.conf | awk '{print $1}')
 #curl http://localhost:7776/idp/attributes/testego
 echo "Ticket: $TICKET"
-gnunet-arm -e -c test_idp.conf
+#gnunet-arm -e -c test_idp.conf
index e34ed3f1a03a32c7fa1235471a95ecdb6d99e138..c0a258ab633a1c80196c1b664afba805017e0c59 100644 (file)
@@ -105,7 +105,10 @@ struct GNUNET_IDENTITY_PROVIDER_PluginFunctions
                          uint64_t offset,
                          GNUNET_IDENTITY_PROVIDER_TicketIterator iter, void *iter_cls);
 
-
+  int (*get_ticket_attributes) (void* cls,
+                                const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+                                GNUNET_IDENTITY_PROVIDER_TicketIterator iter,
+                                void *iter_cls);
 };
 
 
index fa4d4536c3493b53f6e2b930af0f6405d2df6cd6..d17a1cc9caee4ab48b5c5c9a35566e8964822d76 100644 (file)
@@ -113,6 +113,11 @@ struct GNUNET_IDENTITY_PROVIDER_Attribute
    */
   uint32_t attribute_type;
 
+  /**
+   * Attribute version
+   */
+  uint32_t attribute_version;
+
   /**
    * Number of bytes in @e data.
    */