Deletion of Reference Type
authorMarkus Voggenreiter <Markus.Voggenreiter@tum.de>
Sun, 27 Oct 2019 21:43:23 +0000 (22:43 +0100)
committerSchanzenbach, Martin <mschanzenbach@posteo.de>
Fri, 6 Dec 2019 08:35:21 +0000 (09:35 +0100)
src/include/gnunet_protocols.h
src/include/gnunet_reclaim_service.h
src/reclaim/gnunet-service-reclaim.c
src/reclaim/plugin_rest_reclaim.c
src/reclaim/reclaim_api.c

index f8d4243591ad30cb4b767eb48344d1efda8f8514..367f6fd80c4c74a41797ae79343610328f686ef4 100644 (file)
@@ -3309,6 +3309,7 @@ extern "C" {
 /**
  * Next available: 1500
  */
+#define GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_DELETE 1500
 
 
 /**
index eb6c1bc9e2d961b4032d6e457e97300d83699ffd..f839123e5f1701bd1e8b893b500944302ff6187d 100644 (file)
@@ -210,6 +210,25 @@ GNUNET_RECLAIM_attestation_delete (
   const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr,
   GNUNET_RECLAIM_ContinuationWithStatus cont,
   void *cont_cls);
+
+/**
+ * Delete an attestation reference. Tickets used to share this reference are updated
+ * accordingly.
+ *
+ * @param h handle to the re:claimID service
+ * @param pkey Private key of the identity to delete the reference from
+ * @param attr The reference
+ * @param cont Continuation to call when done
+ * @param cont_cls Closure for @a cont
+ * @return handle Used to to abort the request
+ */
+struct GNUNET_RECLAIM_Operation *
+GNUNET_RECLAIM_attestation_reference_delete (
+  struct GNUNET_RECLAIM_Handle *h,
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
+  const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr,
+  GNUNET_RECLAIM_ContinuationWithStatus cont,
+  void *cont_cls);
 /**
  * List all attributes for a local identity.
  * This MUST lock the `struct GNUNET_RECLAIM_Handle`
index aea96e61e37068d1e334f88cb2f8b0729d6756a9..1f320e19603db9040549e923c40da880c779e0bb 100644 (file)
@@ -270,6 +270,10 @@ struct AttributeDeleteHandle
    */
   struct GNUNET_RECLAIM_ATTESTATION_Claim *attest;
 
+  /**
+  * The reference to delete
+  */
+  struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *reference;
   /**
    * Tickets to update
    */
@@ -476,6 +480,8 @@ cleanup_adh (struct AttributeDeleteHandle *adh)
     GNUNET_free (adh->claim);
   if (NULL != adh->attest)
     GNUNET_free (adh->attest);
+  if (NULL != adh->reference)
+    GNUNET_free (adh->reference);
   while (NULL != (le = adh->tickets_to_update_head))
   {
     GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
@@ -1192,6 +1198,21 @@ ref_error (void *cls)
   return;
 }
 
+/**
+ * Error looking up potential reference value. Abort.
+ *
+ * @param cls our attribute delete handle
+ */
+static void
+ref_del_error (void *cls)
+{
+  struct AttributeDeleteHandle *adh = cls;
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+              "Failed to find Attestation entry for Attestation reference\n");
+  cleanup_adh (adh);
+  GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+  return;
+}
 /**
 * Reference store result handler
 *
@@ -1306,8 +1327,9 @@ reference_store_task (void *cls)
   {
     if (0 == ash->reference->id_attest)
     {
-      ash->reference->id = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG,
-                                                  UINT64_MAX);
+      ash->reference->id = GNUNET_CRYPTO_random_u64 (
+        GNUNET_CRYPTO_QUALITY_STRONG,
+        UINT64_MAX);
     }
     else
     {
@@ -1327,7 +1349,7 @@ reference_store_task (void *cls)
                                                 ash,
                                                 &ref_add_cb,
                                                 ash);
-               GNUNET_free (label);
+  GNUNET_free (label);
 }
 
 /**
@@ -1338,8 +1360,8 @@ reference_store_task (void *cls)
      */
 static int
 check_reference_store_message (void *cls,
-                                           const struct
-                                           AttributeStoreMessage *sam)
+                               const struct
+                               AttributeStoreMessage *sam)
 {
   uint16_t size;
 
@@ -1432,14 +1454,18 @@ ticket_iter (void *cls,
   for (int i = 0; i < rd_count; i++)
   {
     if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF != rd[i].record_type) &&
-        (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR != rd[i].record_type))
+        (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR != rd[i].record_type) &&
+        (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_REF != rd[i].record_type))
       continue;
     if (0 != memcmp (rd[i].data, &adh->claim->id, sizeof(uint64_t)))
       continue;
     if (0 != memcmp (rd[i].data, (&adh->attest->id), sizeof(uint64_t)))
       continue;
+    if (0 != memcmp (rd[i].data, &adh->reference->id, sizeof(uint64_t)))
+      continue;
+
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Attribute or Attestation to delete found (%s)\n",
+                "Attribute or Attestation/Reference to delete found (%s)\n",
                 adh->label);
     has_changed = GNUNET_YES;
     break;
@@ -1535,6 +1561,9 @@ update_tickets (void *cls)
     if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR == rd[i].record_type)
         && (0 == memcmp (rd[i].data, &adh->attest->id, sizeof(uint64_t))))
       continue;
+    if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_REF == rd[i].record_type)
+        && (0 == memcmp (rd[i].data, &adh->reference->id, sizeof(uint64_t))))
+      continue;
     rd_new[j] = rd[i];
     j++;
   }
@@ -1782,7 +1811,158 @@ handle_attestation_delete_message (void *cls,
 
 
 
+/**
+* Reference deleted callback
+*
+* @param cls our handle
+* @param success success status
+* @param emsg error message (NULL if success=GNUNET_OK)
+*/
+static void
+reference_delete_cont (void *cls, int32_t success, const char *emsg)
+{
+  struct AttributeDeleteHandle *adh = cls;
 
+  adh->ns_qe = NULL;
+  if (GNUNET_SYSERR == success)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Error deleting reference %s\n",
+                adh->label);
+    send_delete_response (adh, GNUNET_SYSERR);
+    cleanup_adh (adh);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating tickets...\n");
+  GNUNET_SCHEDULER_add_now (&start_ticket_update, adh);
+}
+
+static void
+ref_del_cb (void *cls,
+            const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+            const char *label,
+            unsigned int rd_count,
+            const struct GNUNET_GNSRECORD_Data *rd)
+{
+
+  struct AttributeDeleteHandle *adh = cls;
+  char *data_tmp;
+  struct GNUNET_GNSRECORD_Data rd_new[rd_count - 1];
+  struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *ref;
+  size_t attr_len;
+
+  if (0 == rd_count )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to find Attestation entry for Attestation reference\n");
+    cleanup_adh (adh);
+    GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+    return;
+  }
+  if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTEST_ATTR != rd[0].record_type)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Intended Reference location is not an attestation\n");
+    cleanup_adh (adh);
+    GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+    return;
+  }
+  rd_new[0] = rd[0];
+  int i;
+  int j = 1;
+  for (i = 1; i<rd_count; i++)
+  {
+    data_tmp = GNUNET_malloc (rd[i].data_size);
+    GNUNET_memcpy (data_tmp, rd[i].data, rd[i].data_size);
+    attr_len = htons (rd->data_size);
+    ref = GNUNET_RECLAIM_ATTESTATION_REF_deserialize (data_tmp, attr_len);
+    if (NULL == ref )
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Unable to parse attestation reference from %s\n",
+                  data_tmp);
+      rd_new[j] = rd[i];
+      j += 1;
+      continue;
+    }
+    if ((strcmp (adh->reference->name,ref->name) == 0)&&
+        (strcmp (adh->reference->reference_value,ref->reference_value)==0) )
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Found reference to delete.\n");
+    }
+    else
+    {
+      rd_new[j] = rd[i];
+      j += 1;
+    }
+    GNUNET_free (data_tmp);
+  }
+  adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
+                                               &adh->identity,
+                                               label,
+                                               j,
+                                               rd_new,
+                                               &reference_delete_cont,
+                                               adh);
+}
+
+/**
+ * Check an attestation reference delete message
+ *
+ * @param cls unused
+ * @param sam the message to check
+ */
+static int
+check_reference_delete_message (void *cls,
+                                const struct AttributeDeleteMessage *dam)
+{
+  uint16_t size;
+
+  size = ntohs (dam->header.size);
+  if (size <= sizeof(struct AttributeDeleteMessage))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+/**
+ * Handle reference deletion
+ *
+ * @param cls our client
+ * @param dam deletion message
+ */
+static void
+handle_reference_delete_message (void *cls,
+                                 const struct AttributeDeleteMessage *dam)
+{
+  struct AttributeDeleteHandle *adh;
+  struct IdpClient *idp = cls;
+  size_t data_len;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received REFERENCE_DELETE message\n");
+  data_len = ntohs (dam->attr_len);
+  adh = GNUNET_new (struct AttributeDeleteHandle);
+  adh->reference = GNUNET_RECLAIM_ATTESTATION_REF_deserialize ((char *) &dam[1],
+                                                               data_len);
+  adh->r_id = ntohl (dam->id);
+  adh->identity = dam->identity;
+  adh->label
+    = GNUNET_STRINGS_data_to_string_alloc (&adh->reference->id,
+                                           sizeof(uint64_t));
+  GNUNET_SERVICE_client_continue (idp->client);
+  adh->client = idp;
+  GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
+  adh->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
+                                                &adh->identity,
+                                                adh->label,
+                                                &ref_del_error,
+                                                adh,
+                                                &ref_del_cb,
+                                                adh);
+}
 
 
 
@@ -2238,6 +2418,10 @@ GNUNET_SERVICE_MAIN (
                          GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_STORE,
                          struct AttributeStoreMessage,
                          NULL),
+  GNUNET_MQ_hd_var_size (reference_delete_message,
+                         GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_DELETE,
+                         struct AttributeDeleteMessage,
+                         NULL),
   GNUNET_MQ_hd_fixed_size (
     iteration_start,
     GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START,
index b52cf9650d440ec8316fa3971df144919fd02712..5066eef5871c8dae8c53391000a4623ebe5a700e 100644 (file)
@@ -483,7 +483,8 @@ add_attestation_ref_cont (struct GNUNET_REST_RequestHandle *con_handle,
     return;
   }
   identity = handle->url + strlen (
-    GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + strlen ("reference/") + 1;
+    GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + strlen ("reference/")
+             + 1;
   for (ego_entry = handle->ego_head; NULL != ego_entry;
        ego_entry = ego_entry->next)
     if (0 == strcmp (identity, ego_entry->identifier))
@@ -733,6 +734,102 @@ list_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
                                                          handle);
 }
 
+/**
+ * Deletes reference from an identity
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+delete_attestation_ref_cont (struct GNUNET_REST_RequestHandle *con_handle,
+                             const char *url,
+                             void *cls)
+{
+  struct RequestHandle *handle = cls;
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
+  struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr;
+  struct EgoEntry *ego_entry;
+  char *identity;
+  char *identity_id_str;
+  char *id;
+  char term_data[handle->rest_handle->data_size + 1];
+  json_t *data_json;
+  json_error_t err;
+
+  struct GNUNET_JSON_Specification attrspec[] =
+  { GNUNET_RECLAIM_JSON_spec_claim_attest_ref (&attr),
+    GNUNET_JSON_spec_end () };
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Deleting attestation reference.\n");
+  if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) + strlen (
+        "reference/") + 1 >= strlen (
+        handle->url))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  identity_id_str = strdup (handle->url + strlen (
+                              GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE)
+                            + strlen ("reference/")
+                            + 1);
+  identity = strtok (identity_id_str, "/");
+  id = strtok (NULL, "/");
+
+  if ((NULL == identity) || (NULL == id))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Malformed request.\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  for (ego_entry = handle->ego_head; NULL != ego_entry;
+       ego_entry = ego_entry->next)
+    if (0 == strcmp (identity, ego_entry->identifier))
+      break;
+  handle->resp_object = json_array ();
+  if (NULL == ego_entry)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", identity);
+    GNUNET_SCHEDULER_add_now (&return_response, handle);
+    return;
+  }
+  priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+  if (0 >= handle->rest_handle->data_size)
+  {
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+
+  term_data[handle->rest_handle->data_size] = '\0';
+  GNUNET_memcpy (term_data,
+                 handle->rest_handle->data,
+                 handle->rest_handle->data_size);
+  data_json = json_loads (term_data, JSON_DECODE_ANY, &err);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_JSON_parse (data_json, attrspec, NULL, NULL));
+  json_decref (data_json);
+  if (NULL == attr)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unable to parse attestation reference from %s\n",
+                term_data);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  GNUNET_STRINGS_string_to_data (id, strlen (id), &attr->id, sizeof(uint64_t));
+
+  handle->idp = GNUNET_RECLAIM_connect (cfg);
+  handle->idp_op = GNUNET_RECLAIM_attestation_reference_delete (handle->idp,
+                                                                priv_key,
+                                                                attr,
+                                                                &
+                                                                delete_finished_cb,
+                                                                handle);
+  GNUNET_JSON_parse_free (attrspec);
+}
+
+
 /**
  * Deletes attestation from an identity
  *
@@ -745,8 +842,21 @@ delete_attestation_cont (struct GNUNET_REST_RequestHandle *con_handle,
                          const char *url,
                          void *cls)
 {
-  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
   struct RequestHandle *handle = cls;
+  /* Check for substring "reference" */
+  if (strlen (GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE) < strlen (
+        handle->url))
+  {
+    if ( strncmp ("reference", (handle->url + strlen (
+                                  GNUNET_REST_API_NS_RECLAIM_ATTESTATION_REFERENCE)
+                                + 1), strlen (
+                    "reference")) == 0)
+    {
+      delete_attestation_ref_cont (con_handle,url,cls);
+      return;
+    }
+  }
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
   struct GNUNET_RECLAIM_ATTESTATION_Claim attr;
   struct EgoEntry *ego_entry;
   char *identity_id_str;
index a6ff0237d938f874e264c90d7e93fc9186446dc2..7c7261522ef7b238741dc1507a66b5a3ddea2815 100644 (file)
@@ -1163,6 +1163,49 @@ GNUNET_RECLAIM_attestation_reference_store (
   return op;
 }
 
+/**
+ * Delete an attestation reference. Tickets used to share this reference are updated
+ * accordingly.
+ *
+ * @param h handle to the re:claimID service
+ * @param pkey Private key of the identity to delete the reference from
+ * @param attr The reference
+ * @param cont Continuation to call when done
+ * @param cont_cls Closure for @a cont
+ * @return handle Used to to abort the request
+ */
+struct GNUNET_RECLAIM_Operation *
+GNUNET_RECLAIM_attestation_reference_delete (
+  struct GNUNET_RECLAIM_Handle *h,
+  const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
+  const struct GNUNET_RECLAIM_ATTESTATION_REFERENCE *attr,
+  GNUNET_RECLAIM_ContinuationWithStatus cont,
+  void *cont_cls)
+{
+
+  struct GNUNET_RECLAIM_Operation *op;
+  struct AttributeDeleteMessage *dam;
+  size_t attr_len;
+
+  op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
+  op->h = h;
+  op->as_cb = cont;
+  op->cls = cont_cls;
+  op->r_id = h->r_id_gen++;
+  GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
+  attr_len = GNUNET_RECLAIM_ATTESTATION_REF_serialize_get_size (attr);
+  op->env = GNUNET_MQ_msg_extra (dam,
+                                 attr_len,
+                                 GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_DELETE);
+  dam->identity = *pkey;
+  dam->id = htonl (op->r_id);
+  GNUNET_RECLAIM_ATTESTATION_REF_serialize (attr, (char *) &dam[1]);
+
+  dam->attr_len = htons (attr_len);
+  if (NULL != h->mq)
+    GNUNET_MQ_send_copy (h->mq, op->env);
+  return op;
+}
 
 /**
  * List all attributes for a local identity.