-various fixes; add attribute list API
authorSchanzenbach, Martin <mschanzenbach@posteo.de>
Sat, 16 Sep 2017 20:39:15 +0000 (22:39 +0200)
committerSchanzenbach, Martin <mschanzenbach@posteo.de>
Sat, 16 Sep 2017 20:39:15 +0000 (22:39 +0200)
13 files changed:
src/identity-provider/Makefile.am
src/identity-provider/gnunet-idp.c
src/identity-provider/gnunet-service-identity-provider.c
src/identity-provider/identity_attribute.c [new file with mode: 0644]
src/identity-provider/identity_attribute.h [new file with mode: 0644]
src/identity-provider/identity_provider.h
src/identity-provider/identity_provider_api.c
src/identity-provider/plugin_gnsrecord_identity_provider.c
src/identity-provider/test_idp.sh
src/include/gnunet_crypto_lib.h
src/include/gnunet_identity_provider_service.h
src/include/gnunet_protocols.h
src/util/crypto_abe.c

index ab0c2f67e320f76df2ba48abe62e34c3d3a68db6..106c8a92b7d23762177c06cc3cbd20f84d9e17e0 100644 (file)
@@ -43,7 +43,8 @@ libgnunet_plugin_gnsrecord_identity_provider_la_LDFLAGS = \
 
 gnunet_service_identity_provider_SOURCES = \
  gnunet-service-identity-provider.c \
- identity_token.c
+ identity_token.c \
+ identity_attribute.h
 gnunet_service_identity_provider_LDADD = \
  $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
  $(top_builddir)/src/util/libgnunetutil.la \
@@ -51,13 +52,15 @@ gnunet_service_identity_provider_LDADD = \
  $(top_builddir)/src/identity/libgnunetidentity.la \
  $(top_builddir)/src/statistics/libgnunetstatistics.la \
  $(top_builddir)/src/credential/libgnunetcredential.la \
+ $(top_builddir)/src/identity-provider/libgnunetidentityprovider.la \
  $(top_builddir)/src/gns/libgnunetgns.la \
  $(GN_LIBINTL) \
  -ljansson
 
 libgnunetidentityprovider_la_SOURCES = \
  identity_provider_api.c \
- identity_provider.h
+ identity_provider.h \
+ identity_attribute.c
 libgnunetidentityprovider_la_LIBADD = \
   $(top_builddir)/src/util/libgnunetutil.la \
        $(GN_LIBINTL) $(XLIB)
index b4785580a663e918a5e918a045a6756e7b207835..264d77ba2b644d5d974f605c5d3af697dab6b39f 100644 (file)
@@ -77,9 +77,9 @@ static struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op;
 static struct GNUNET_NAMESTORE_Handle *namestore_handle;
 
 /**
- * Namestore iterator
+ * Attribute iterator
  */
-static struct GNUNET_NAMESTORE_ZoneIterator *ns_iterator;
+static struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *attr_iterator;
 
 /**
  * Namestore queue
@@ -96,8 +96,10 @@ do_cleanup(void *cls)
 {
   if (NULL != ns_qe)
     GNUNET_NAMESTORE_cancel (ns_qe);
-  if (NULL != ns_iterator)
-    GNUNET_NAMESTORE_zone_iteration_stop (ns_iterator);
+  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)
@@ -152,7 +154,7 @@ store_abe_cont (void *cls,
 static void
 iter_error (void *cls)
 {
-  ns_iterator = NULL;
+  attr_iterator = NULL;
   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
               "Failed to iterate over attributes\n");
   GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
@@ -161,37 +163,19 @@ iter_error (void *cls)
 static void
 iter_finished (void *cls)
 {
-  ns_iterator = NULL;
+  attr_iterator = NULL;
   GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
 }
 
 static void
 iter_cb (void *cls,
-            const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-            const char *label,
-            unsigned int rd_count,
-            const struct GNUNET_GNSRECORD_Data *rd)
+         const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+         const struct GNUNET_IDENTITY_PROVIDER_Attribute *attr)
 {
-  struct GNUNET_CRYPTO_AbeKey *key;
-  int i;
-  char *attr_value;
-  char* attrs[2];
-  for (i=0;i<rd_count;i++) {
-    if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd[i].record_type)
-      continue;
-    attrs[0] = (char*)label;
-    attrs[1] = 0;
-    key = GNUNET_CRYPTO_cpabe_create_key (abe_key,
-                                          attrs);
-    GNUNET_CRYPTO_cpabe_decrypt (rd[i].data,
-                                 rd[i].data_size,
-                                 key,
-                                 (void**)&attr_value);
-    GNUNET_CRYPTO_cpabe_delete_key (key);
-    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
-                "%s: %s\n", label, attr_value);
-  }
-  GNUNET_NAMESTORE_zone_iterator_next (ns_iterator);
+  
+  GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+              "%s: %s\n", attr->name, (char*)attr->data);
+  GNUNET_IDENTITY_PROVIDER_get_attributes_next (attr_iterator);
 }
 
 static void
@@ -235,25 +219,23 @@ abe_lookup_cb (void *cls,
   }
 
   if (list) {
-    ns_iterator = GNUNET_NAMESTORE_zone_iteration_start (namestore_handle,
-                                                         zone,
-                                                         &iter_error,
-                                                         NULL,
-                                                         &iter_cb,
-                                                         NULL,
-                                                         &iter_finished,
-                                                         NULL);
+    attr_iterator = GNUNET_IDENTITY_PROVIDER_get_attributes_start (idp_handle,
+                                                                  zone,
+                                                                  &iter_error,
+                                                                  NULL,
+                                                                  &iter_cb,
+                                                                  NULL,
+                                                                  &iter_finished,
+                                                                  NULL);
     return;
   }
 
-  struct GNUNET_IDENTITY_PROVIDER_Attribute *attr;
-  attr = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_Attribute) + strlen (attr_value) + 1);
-  attr->attribute_type = GNUNET_IDENTITY_PROVIDER_AT_STRING;
-  attr->data = &attr[1];
-  attr->data_size = strlen (attr_value) + 1;
+  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_name,
                                                     attr,
                                                     &store_attr_cont,
                                                     NULL);
index 5663a76816582b6b3d66a964e4e5ff7b93376ee3..0ce70aed37b4314026fb5ebbf1b0fac3ebb91dee 100644 (file)
@@ -36,6 +36,7 @@
 #include "gnunet_signatures.h"
 #include "identity_provider.h"
 #include "identity_token.h"
+#include "identity_attribute.h"
 #include <inttypes.h>
 
 /**
@@ -129,13 +130,134 @@ static struct GNUNET_STATISTICS_Handle *stats;
  */
 static const struct GNUNET_CONFIGURATION_Handle *cfg;
 
+/**
+ * An idp client
+ */
+struct IdpClient;
+
+/**
+ * Callback after an ABE bootstrap
+ *
+ * @param cls closure
+ * @param abe_key the ABE key that exists or was created
+ */
+typedef void
+(*AbeBootstrapResult) (void *cls,
+                       struct GNUNET_CRYPTO_AbeMasterKey *abe_key);
+
+
+struct AbeBootstrapHandle
+{
+  /**
+   * Function to call when finished
+   */
+  AbeBootstrapResult proc;
+
+  /**
+   * Callback closure
+   */
+  char *proc_cls;
+
+  /**
+   * Key of the zone we are iterating over.
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+  /**
+   * Namestore Queue Entry
+   */
+  struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
+
+  /**
+   * The issuer egos ABE master key
+   */
+  struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
+};
+
+/**
+ * An attribute iteration operation.
+ */
+struct AttributeIterator
+{
+  /**
+   * Next element in the DLL
+   */
+  struct AttributeIterator *next;
+
+  /**
+   * Previous element in the DLL
+   */
+  struct AttributeIterator *prev;
+
+  /**
+   * IDP client which intiated this zone iteration
+   */
+  struct IdpClient *client;
+
+  /**
+   * Key of the zone we are iterating over.
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+  /**
+   * The issuer egos ABE master key
+   */
+  struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
+
+  /**
+   * Namestore iterator
+   */
+  struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
+
+  /**
+   * The operation id fot the zone iteration in the response for the client
+   */
+  uint32_t request_id;
+
+};
+
+
+
+/**
+ * An idp client
+ */
+struct IdpClient
+{
+
+  /**
+   * The client
+   */
+  struct GNUNET_SERVICE_Client *client;
+
+  /**
+   * Message queue for transmission to @e client
+   */
+  struct GNUNET_MQ_Handle *mq;
+  
+  /**
+   * Head of the DLL of
+   * Attribute iteration operations in 
+   * progress initiated by this client
+   */
+  struct AttributeIterator *op_head;
+
+  /**
+   * Tail of the DLL of
+   * Attribute iteration operations 
+   * in progress initiated by this client
+   */
+  struct AttributeIterator *op_tail;
+};
+
+
+
 struct AttributeStoreHandle
 {
 
   /**
    * Client connection
    */
-  struct GNUNET_SERVICE_Client *client;
+  struct IdpClient *client;
 
   /**
    * Identity
@@ -158,19 +280,9 @@ struct AttributeStoreHandle
   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
 
   /**
-   * The attribute name
+   * The attribute to store
    */
-  char *name;
-
-  /**
-   * The attribute value
-   */
-  char *attribute_value;
-
-  /**
-   * Size of the attribute value
-   */
-  size_t attribute_value_len;
+  struct GNUNET_IDENTITY_PROVIDER_Attribute *attribute;
 
   /**
    * request id
@@ -206,7 +318,7 @@ struct ExchangeHandle
   /**
    * Client connection
    */
-  struct GNUNET_SERVICE_Client *client;
+  struct IdpClient *client;
 
   /**
    * Ticket
@@ -267,7 +379,7 @@ struct IssueHandle
   /**
    * Client connection
    */
-  struct GNUNET_SERVICE_Client *client;
+  struct IdpClient *client;
 
   /**
    * Issuer Key
@@ -541,7 +653,7 @@ store_record_issue_cont (void *cls,
                                      ticket_str,
                                      token_str,
                                      handle->r_id);
-  GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(handle->client),
+  GNUNET_MQ_send (handle->client->mq,
                   env);
   cleanup_issue_handle (handle);
   GNUNET_free (ticket_str);
@@ -664,7 +776,7 @@ sign_and_return_token (void *cls)
                                         handle->label,
                                         handle->ticket->payload->nonce,
                                         handle->r_id);
-  GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(handle->client),
+  GNUNET_MQ_send (handle->client->mq,
                   env);
   cleanup_exchange_handle (handle);
   GNUNET_free (token_str);
@@ -1141,7 +1253,7 @@ handle_exchange_message (void *cls,
                          const struct ExchangeMessage *xm)
 {
   struct ExchangeHandle *xchange_handle;
-  struct GNUNET_SERVICE_Client *client = cls;
+  struct IdpClient *idp = cls;
   const char *ticket;
   char *lookup_query;
 
@@ -1157,7 +1269,7 @@ handle_exchange_message (void *cls,
                                      &xchange_handle->ticket))
   {
     GNUNET_free (xchange_handle);
-    GNUNET_SERVICE_client_drop (client);
+    GNUNET_SERVICE_client_drop (idp->client);
     return;
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for ABE key under %s\n",
@@ -1165,8 +1277,8 @@ handle_exchange_message (void *cls,
   GNUNET_asprintf (&lookup_query,
                    "%s.gnu",
                    xchange_handle->ticket->payload->label);
-  GNUNET_SERVICE_client_continue (client);
-  xchange_handle->client = client;
+  GNUNET_SERVICE_client_continue (idp->client);
+  xchange_handle->client = idp;
   xchange_handle->token = token_create (&xchange_handle->ticket->payload->identity_key,
                                         &xchange_handle->ticket->payload->identity_key);
   xchange_handle->lookup_request
@@ -1278,7 +1390,7 @@ handle_issue_message (void *cls,
   uint64_t rnd_key;
   struct GNUNET_HashCode key;
   struct IssueHandle *issue_handle;
-  struct GNUNET_SERVICE_Client *client = cls;
+  struct IdpClient *idp = cls;
 
   scopes = (const char *) &im[1];
   //v_attrs = (const char *) &im[1] + ntohl(im->scope_len);
@@ -1319,8 +1431,8 @@ handle_issue_message (void *cls,
                                       &issue_handle->iss_pkey);
   issue_handle->expiration = GNUNET_TIME_absolute_ntoh (im->expiration);
   issue_handle->nonce = ntohl (im->nonce);
-  GNUNET_SERVICE_client_continue (client);
-  issue_handle->client = client;
+  GNUNET_SERVICE_client_continue (idp->client);
+  issue_handle->client = idp;
   issue_handle->scopes = GNUNET_strdup (scopes);
   issue_handle->token = token_create (&issue_handle->iss_pkey,
                                       &issue_handle->aud_key);
@@ -1342,10 +1454,10 @@ handle_issue_message (void *cls,
 static void
 cleanup_as_handle (struct AttributeStoreHandle *handle)
 {
-  if (NULL != handle->name)
-    GNUNET_free (handle->name);
-  if (NULL != handle->attribute_value)
-    GNUNET_free (handle->attribute_value);
+  if (NULL != handle->attribute)
+    GNUNET_free (handle->attribute);
+  if (NULL != handle->abe_key)
+    GNUNET_free (handle->abe_key);
   GNUNET_free (handle);
 }
 
@@ -1375,104 +1487,154 @@ attr_store_cont (void *cls,
                       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 (GNUNET_SERVICE_client_get_mq(as_handle->client),
+  GNUNET_MQ_send (as_handle->client->mq,
                   env);
   cleanup_as_handle (as_handle);
 }
 
-void
+static void
 attr_store_task (void *cls)
 {
   struct AttributeStoreHandle *as_handle = cls;
   struct GNUNET_GNSRECORD_Data rd[1];
+  char* buf;
+  size_t buf_size;
+
+  buf_size = attribute_serialize_get_size (as_handle->attribute);
+  buf = GNUNET_malloc (buf_size);
+
+  attribute_serialize (as_handle->attribute,
+                       buf);
 
   /**
    * Encrypt the attribute value and store in namestore
    */
-  rd[0].data_size = GNUNET_CRYPTO_cpabe_encrypt (as_handle->attribute_value,
-                                                 as_handle->attribute_value_len,
-                                                 as_handle->name, //Policy
+  rd[0].data_size = GNUNET_CRYPTO_cpabe_encrypt (buf,
+                                                 buf_size,
+                                                 as_handle->attribute->name, //Policy
                                                  as_handle->abe_key,
                                                  (void**)&rd[0].data);
+  GNUNET_free (buf);
   rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
-  rd[0].flags = GNUNET_GNSRECORD_RF_NONE;
+  rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
   rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane?
   as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
                                                      &as_handle->identity,
-                                                     as_handle->name,
+                                                     as_handle->attribute->name,
                                                      1,
                                                      rd,
                                                      &attr_store_cont,
                                                      as_handle);
+  GNUNET_free ((void*)rd[0].data);
 
 }
 
-void
-store_bootstrap_cont (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);
-    GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+    abh->proc (abh->proc_cls, NULL);
+    GNUNET_free (abh->abe_key);
+    GNUNET_free (abh);
     return;
   }
-  GNUNET_SCHEDULER_add_now (&attr_store_task, cls);
+  abh->proc (abh->proc_cls, abh->abe_key);
+  GNUNET_free (abh);
 }
 
-void
-store_bootstrap_task (void *cls)
+static void
+bootstrap_store_task (void *cls)
 {
-  struct AttributeStoreHandle *as_handle = cls;
+  struct AbeBootstrapHandle *abh = cls;
   struct GNUNET_GNSRECORD_Data rd[1];
 
-  rd[0].data_size = GNUNET_CRYPTO_cpabe_serialize_master_key (as_handle->abe_key,
+  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?
-  as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
-                                                     &as_handle->identity,
-                                                     "+",
-                                                     1,
-                                                     rd,
-                                                     &store_bootstrap_cont,
-                                                     as_handle);
+  abh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
+                                               &abh->identity,
+                                               "+",
+                                               1,
+                                               rd,
+                                               &bootstrap_store_cont,
+                                               abh);
 }
 
-void
-store_cont_abe_error (void *cls)
+static void
+bootstrap_abe_error (void *cls)
 {
-  GNUNET_SCHEDULER_add_now (&do_shutdown, cls);
+  struct AbeBootstrapHandle *abh = cls;
+  GNUNET_free (abh);
+  abh->proc (abh->proc_cls, NULL);
+  GNUNET_free (abh);
 }
 
-void
-store_cont_abe_result (void *cls,
-                       const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
-                       const char *label,
-                       unsigned int rd_count,
-                       const struct GNUNET_GNSRECORD_Data *rd)
+
+
+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 AttributeStoreHandle *handle = cls;
+  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;
-    handle->abe_key = GNUNET_CRYPTO_cpabe_deserialize_master_key ((void**)rd[i].data,
-                                                                  rd[i].data_size);
-    GNUNET_SCHEDULER_add_now (&attr_collect_task, handle);
+    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...
-  handle->abe_key = GNUNET_CRYPTO_cpabe_create_master_key ();
-  GNUNET_SCHEDULER_add_now (&store_bootstrap_task, handle);
+  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)
+{
+  struct AttributeStoreHandle *ash = cls;
+  ash->abe_key = abe_key;
+  GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
+}
 
 /**
  * Checks a store message
@@ -1486,7 +1648,6 @@ check_attribute_store_message(void *cls,
                               const struct AttributeStoreMessage *sam)
 {
   uint16_t size;
-  uint32_t name_len;
 
   size = ntohs (sam->header.size);
   if (size <= sizeof (struct AttributeStoreMessage))
@@ -1494,17 +1655,10 @@ check_attribute_store_message(void *cls,
     GNUNET_break (0);
     return GNUNET_SYSERR;
   }
-  name_len = ntohs (sam->name_len);
-  if (0 <= name_len)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Malformed store message received!\n");
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
   return GNUNET_OK;
 }
 
+
 /**
  *
  * Handler for store message
@@ -1518,40 +1672,224 @@ handle_attribute_store_message (void *cls,
                                 const struct AttributeStoreMessage *sam)
 {
   struct AttributeStoreHandle *as_handle;
-  struct GNUNET_SERVICE_Client *client = cls;
-  size_t name_len;
+  struct IdpClient *idp = cls;
   size_t data_len;
-  char *attribute_value;
 
-  name_len = ntohs (sam->name_len);
-  data_len = ntohs (sam->attr_value_len);
+  data_len = ntohs (sam->attr_len);
 
   as_handle = GNUNET_new (struct AttributeStoreHandle);
-  as_handle->name = GNUNET_strndup ((char*)&sam[1], name_len);
-  attribute_value = (char*)&sam[1] + name_len;
+  as_handle->attribute = attribute_deserialize ((char*)&sam[1],
+                                                data_len);
 
   as_handle->r_id = sam->id;
   as_handle->identity = sam->identity;
   GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity,
                                       &as_handle->identity_pkey);
-  as_handle->attribute_value = GNUNET_malloc (data_len);
-  GNUNET_memcpy (as_handle->attribute_value,
-                 attribute_value,
-                 data_len);
-  as_handle->attribute_value_len = data_len;
-
-  GNUNET_SERVICE_client_continue (client);
-  as_handle->client = client;
-  as_handle->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
-                                                      &as_handle->identity,
-                                                      "+",
-                                                      &store_cont_abe_error,
-                                                      as_handle,
-                                                      &store_cont_abe_result,
-                                                      as_handle);
+
+  GNUNET_SERVICE_client_continue (idp->client);
+  as_handle->client = idp;
+
+  bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle);
+}
+
+static void
+cleanup_iter_handle (struct AttributeIterator *ai)
+{
+  if (NULL != ai->abe_key)
+    GNUNET_free (ai->abe_key);
+  GNUNET_free (ai);
+}
+
+static void
+attr_iter_error (void *cls)
+{
+  //struct AttributeIterator *ai = cls;
+  //TODO
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+              "Failed to iterate over attributes\n");
+  GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+}
+
+static void
+attr_iter_finished (void *cls)
+{
+  struct AttributeIterator *ai = cls;
+  struct GNUNET_MQ_Envelope *env;
+  struct AttributeResultMessage *arm;
+
+  env = GNUNET_MQ_msg (arm,
+                       GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
+  arm->id = htonl (ai->request_id);
+  arm->attr_len = htons (0);
+  GNUNET_MQ_send (ai->client->mq, env);
+  cleanup_iter_handle (ai);
+}
+
+static void
+attr_iter_cb (void *cls,
+              const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+              const char *label,
+              unsigned int rd_count,
+              const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct AttributeIterator *ai = cls;
+  struct AttributeResultMessage *arm;
+  struct GNUNET_CRYPTO_AbeKey *key;
+  struct GNUNET_MQ_Envelope *env;
+  ssize_t msg_extra_len;
+  char* attr_ser;
+  char* attrs[2];
+  char* data_tmp;
+
+  if (rd_count != 1)
+  {
+    GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
+    return;
+  }
+
+  if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) {
+    GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it);
+    return;
+  }
+  attrs[0] = (char*)label;
+  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,
+                                               key,
+                                               (void**)&attr_ser);
+  GNUNET_CRYPTO_cpabe_delete_key (key);
+  GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+              "Found attribute: %s\n", label);
+  env = GNUNET_MQ_msg_extra (arm,
+                             msg_extra_len,
+                             GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT);
+  arm->id = htonl (ai->request_id);
+  arm->attr_len = htons (msg_extra_len);
+  arm->identity = *zone;
+  data_tmp = (char *) &arm[1];
+  GNUNET_memcpy (data_tmp,
+                 attr_ser,
+                 msg_extra_len);
+  GNUNET_MQ_send (ai->client->mq, env);
+  GNUNET_free (attr_ser);
+}
+
+
+void
+iterate_after_abe_bootstrap (void *cls,
+                             struct GNUNET_CRYPTO_AbeMasterKey *abe_key)
+{
+  struct AttributeIterator *ai = cls;
+  ai->abe_key = abe_key;
+  ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
+                                                     &ai->identity,
+                                                     &attr_iter_error,
+                                                     ai,
+                                                     &attr_iter_cb,
+                                                     ai,
+                                                     &attr_iter_finished,
+                                                     ai);
+}
+
+
+/**
+ * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_START message
+ *
+ * @param cls the client sending the message
+ * @param zis_msg message from the client
+ */
+static void
+handle_iteration_start (void *cls,
+                        const struct AttributeIterationStartMessage *ais_msg)
+{
+  struct IdpClient *idp = cls;
+  struct AttributeIterator *ai;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received ATTRIBUTE_ITERATION_START message\n");
+  ai = GNUNET_new (struct AttributeIterator);
+  ai->request_id = ntohl (ais_msg->id);
+  ai->client = idp;
+  ai->identity = ais_msg->identity;
+
+  GNUNET_CONTAINER_DLL_insert (idp->op_head,
+                               idp->op_tail,
+                               ai);
+  bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai);
+  GNUNET_SERVICE_client_continue (idp->client);
 }
 
 
+/**
+ * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ITERATION_STOP message
+ *
+ * @param cls the client sending the message
+ * @param ais_msg message from the client
+ */
+static void
+handle_iteration_stop (void *cls,
+                       const struct AttributeIterationStopMessage *ais_msg)
+{
+  struct IdpClient *idp = cls;
+  struct AttributeIterator *ai;
+  uint32_t rid;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received `%s' message\n",
+              "ATTRIBUTE_ITERATION_STOP");
+  rid = ntohl (ais_msg->id);
+  for (ai = idp->op_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->op_head,
+                               idp->op_tail,
+                               ai);
+  GNUNET_free (ai);
+  GNUNET_SERVICE_client_continue (idp->client);
+}
+
+
+/**
+ * Handles a #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT message
+ *
+ * @param cls the client sending the message
+ * @param message message from the client
+ */
+static void
+handle_iteration_next (void *cls,
+                       const struct AttributeIterationNextMessage *ais_msg)
+{
+  struct IdpClient *idp = cls;
+  struct AttributeIterator *ai;
+  uint32_t rid;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received ATTRIBUTE_ITERATION_NEXT message\n");
+  rid = ntohl (ais_msg->id);
+  for (ai = idp->op_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);
+  GNUNET_SERVICE_client_continue (idp->client);
+}
+
+
+
+
 /**
  * Main function that will be run
  *
@@ -1619,9 +1957,23 @@ client_disconnect_cb (void *cls,
                       struct GNUNET_SERVICE_Client *client,
                       void *app_ctx)
 {
+  struct IdpClient *idp = app_ctx;
+  struct AttributeIterator *ai;
+
+  //TODO other operations
+
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Client %p disconnected\n",
               client);
+
+  while (NULL != (ai = idp->op_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (idp->op_head,
+                                 idp->op_tail,
+                                 ai);
+    GNUNET_free (ai);
+  }
+  GNUNET_free (idp);
 }
 
 
@@ -1638,10 +1990,14 @@ client_connect_cb (void *cls,
                    struct GNUNET_SERVICE_Client *client,
                    struct GNUNET_MQ_Handle *mq)
 {
+  struct IdpClient *idp;
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Client %p connected\n",
               client);
-  return client;
+  idp = GNUNET_new (struct IdpClient);
+  idp->client = client;
+  idp->mq = mq;
+  return idp;
 }
 
 
@@ -1668,5 +2024,17 @@ GNUNET_SERVICE_MAIN
                         GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE,
                         struct AttributeStoreMessage,
                         NULL),
+ GNUNET_MQ_hd_fixed_size (iteration_start, 
+                          GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START,
+                          struct AttributeIterationStartMessage,
+                          NULL),
+ GNUNET_MQ_hd_fixed_size (iteration_next, 
+                          GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT,
+                          struct AttributeIterationNextMessage,
+                          NULL),
+ GNUNET_MQ_hd_fixed_size (iteration_stop, 
+                          GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP,
+                          struct AttributeIterationStopMessage,
+                          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
new file mode 100644 (file)
index 0000000..3794010
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+      This file is part of GNUnet
+      Copyright (C) 2010-2015 GNUnet e.V.
+
+      GNUnet is free software; you can redistribute it and/or modify
+      it under the terms of the GNU General Public License as published
+      by the Free Software Foundation; either version 3, or (at your
+      option) any later version.
+
+      GNUnet is distributed in the hope that it will be useful, but
+      WITHOUT ANY WARRANTY; without even the implied warranty of
+      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+      General Public License for more details.
+
+      You should have received a copy of the GNU General Public License
+      along with GNUnet; see the file COPYING.  If not, write to the
+      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+      Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * @file identity-provider/identity_attribute.c
+ * @brief helper library to manage identity attributes
+ * @author Martin Schanzenbach
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "identity_attribute.h"
+
+/**
+ * Create a new attribute.
+ *
+ * @param name the attribute name
+ * @param type the attribute type
+ * @param data the attribute value
+ * @param data_size the attribute value size
+ * @return the new attribute
+ */
+struct GNUNET_IDENTITY_PROVIDER_Attribute *
+attribute_new (const char* attr_name,
+               uint32_t attr_type,
+               const void* data,
+               size_t data_size)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Attribute *attr;
+  char *write_ptr;
+
+  attr = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_Attribute) +
+                        strlen (attr_name) + 1 +
+                        data_size);
+  attr->attribute_type = attr_type;
+  attr->data_size = data_size;
+  write_ptr = (char*)&attr[1];
+  GNUNET_memcpy (write_ptr,
+                 attr_name,
+                 strlen (attr_name) + 1);
+  attr->name = write_ptr;
+  write_ptr += strlen (attr->name) + 1;
+  GNUNET_memcpy (write_ptr,
+                 data,
+                 data_size);
+  attr->data = write_ptr;
+  return attr;
+}
+
+
+
+size_t
+attribute_serialize_get_size (const struct GNUNET_IDENTITY_PROVIDER_Attribute *attr)
+{
+  return sizeof (struct Attribute) 
+    + strlen (attr->name) + 1
+    + attr->data_size; //TODO get data_size from plugin
+}
+
+int
+attribute_serialize (const struct GNUNET_IDENTITY_PROVIDER_Attribute *attr,
+                     char *result)
+{
+  size_t data_len_ser;
+  size_t name_len;
+  struct Attribute *attr_ser;
+  char* write_ptr;
+
+  attr_ser = (struct Attribute*)result;
+  attr_ser->attribute_type = htons (attr->attribute_type);
+  name_len = strlen (attr->name);
+  attr_ser->name_len = htons (name_len);
+  write_ptr = (char*)&attr_ser[1];
+  GNUNET_memcpy (write_ptr, attr->name, name_len);
+  write_ptr += name_len;
+  //TODO plugin-ize
+  //data_len_ser = plugin->serialize_attribute_value (attr,
+  //                                                  &attr_ser[1]);
+  data_len_ser = attr->data_size;
+  GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
+  attr_ser->data_size = htons (data_len_ser);
+
+  return GNUNET_OK;
+}
+
+struct GNUNET_IDENTITY_PROVIDER_Attribute *
+attribute_deserialize (const char* data,
+                       size_t data_size)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Attribute *attr;
+  struct Attribute *attr_ser;
+  size_t data_len;
+  size_t name_len;
+  char* write_ptr;
+  
+  if (data_size < sizeof (struct Attribute))
+    return NULL;
+
+  attr_ser = (struct Attribute*)data;
+  //TODO use plugin. 
+  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);
+  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],
+                 name_len);
+  write_ptr[name_len] = '\0';
+  attr->name = write_ptr;
+
+  write_ptr += name_len + 1;
+  GNUNET_memcpy (write_ptr,
+                 (char*)&attr_ser[1] + name_len,
+                 attr->data_size);
+  attr->data = write_ptr;
+  return attr;
+
+}
+
+/* end of identity_attribute.c */
diff --git a/src/identity-provider/identity_attribute.h b/src/identity-provider/identity_attribute.h
new file mode 100644 (file)
index 0000000..0d4f2bb
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2012-2015 GNUnet e.V.
+
+   GNUnet is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNUnet; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+   */
+/**
+ * @author Martin Schanzenbach
+ * @file identity-provider/identity_attribute.h
+ * @brief GNUnet Identity Provider library
+ *
+ */
+#ifndef IDENTITY_ATTRIBUTE_H
+#define IDENTITY_ATTRIBUTE_H
+
+#include "gnunet_identity_provider_service.h"
+
+struct Attribute
+{
+  /**
+   * Attribute type
+   */
+  uint32_t attribute_type;
+
+  /**
+   * Name length
+   */
+  uint32_t name_len;
+  
+  /**
+   * Data size
+   */
+  uint32_t data_size;
+
+  //followed by data_size Attribute value data
+};
+
+/**
+ * Get required size for serialization buffer
+ *
+ * @param attr the attribute to serialize
+ *
+ * @return the required buffer size
+ */
+size_t
+attribute_serialize_get_size (const struct GNUNET_IDENTITY_PROVIDER_Attribute *attr);
+
+
+
+/**
+ * Serialize an attribute
+ *
+ * @param attr the attribute to serialize
+ * @param result the serialized attribute
+ *
+ * @return GNUNET_OK on success
+ */
+int 
+attribute_serialize (const struct GNUNET_IDENTITY_PROVIDER_Attribute *attr,
+                     char *result);
+
+/**
+ * Deserialize an attribute
+ *
+ * @param data the serialized attribute
+ * @param data_size the length of the serialized data
+ *
+ * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller
+ */
+struct GNUNET_IDENTITY_PROVIDER_Attribute *
+attribute_deserialize (const char* data,
+                       size_t data_size);
+
+/**
+ * Create a new attribute.
+ *
+ * @param name the attribute name
+ * @param type the attribute type
+ * @param data the attribute value
+ * @param data_size the attribute value size
+ * @return the new attribute
+ */
+struct GNUNET_IDENTITY_PROVIDER_Attribute *
+attribute_new (const char* attr_name,
+               uint32_t attr_type,
+               const void* data,
+               size_t data_size);
+
+
+#endif
index 47d3f0945cfc70cd3843e4ff673c498d076576c9..588d6d39a983812c9ffefd67a38c2e9d79986112 100644 (file)
@@ -189,26 +189,16 @@ struct AttributeStoreMessage
   uint32_t id GNUNET_PACKED;
 
   /**
-   * The attribute type
+   * The length of the attribute
    */
-  uint32_t attribute_type GNUNET_PACKED;
-
-  /**
-   * The length of the attribute name
-   */
-  uint32_t name_len GNUNET_PACKED;
-
-  /**
-   * The length of the attribute value
-   */
-  uint32_t attr_value_len GNUNET_PACKED;
+  uint32_t attr_len GNUNET_PACKED;
 
   /**
    * Identity
    */
   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
 
-  /* followed by the name of attribute as string and value data */
+  /* followed by the serialized attribute */
 
 };
 
@@ -234,6 +224,101 @@ struct AttributeStoreResponseMessage
 
 };
 
+/**
+ * Attribute is returned from the idp.
+ */
+struct AttributeResultMessage
+{
+  /**
+   * Message header
+   */
+  struct GNUNET_MessageHeader header;
+
+   /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+  /**
+   * Length of serialized attribute data
+   */
+  uint16_t attr_len GNUNET_PACKED;
+
+  /**
+   * always zero (for alignment)
+   */
+  uint16_t reserved GNUNET_PACKED;
+
+  /**
+   * The private key of the identity.
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+  /* followed by:
+   * serialized attribute data
+   */
+};
+
+
+/**
+ * Start a attribute iteration for the given identity
+ */
+struct AttributeIterationStartMessage
+{
+  /**
+   * Message
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+  /**
+   * Identity.
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+};
+
+
+/**
+ * Ask for next result of attribute iteration for the given operation
+ */
+struct AttributeIterationNextMessage
+{
+  /**
+   * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+};
+
+
+/**
+ * Stop attribute iteration for the given operation
+ */
+struct AttributeIterationStopMessage
+{
+  /**
+   * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+};
+
+
 GNUNET_NETWORK_STRUCT_END
 
 #endif
index bbc2bb70a6c3af6391293ed01c8a6af977ab34cf..c806735f65409dc0378c2c22f4fdbb4572897098 100644 (file)
@@ -30,6 +30,7 @@
 #include "gnunet_mq_lib.h"
 #include "gnunet_identity_provider_service.h"
 #include "identity_provider.h"
+#include "identity_attribute.h"
 
 #define LOG(kind,...) GNUNET_log_from (kind, "identity-api",__VA_ARGS__)
 
@@ -96,6 +97,75 @@ struct GNUNET_IDENTITY_PROVIDER_Operation
 
 };
 
+/**
+ * Handle for a attribute iterator operation
+ */
+struct GNUNET_IDENTITY_PROVIDER_AttributeIterator
+{
+
+  /**
+   * Kept in a DLL.
+   */
+  struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *next;
+
+  /**
+   * Kept in a DLL.
+   */
+  struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *prev;
+
+  /**
+   * Main handle to access the idp.
+   */
+  struct GNUNET_IDENTITY_PROVIDER_Handle *h;
+
+  /**
+   * Function to call on completion.
+   */
+  GNUNET_SCHEDULER_TaskCallback finish_cb;
+
+  /**
+   * Closure for @e error_cb.
+   */
+  void *finish_cb_cls;
+
+  /**
+   * The continuation to call with the results
+   */
+  GNUNET_IDENTITY_PROVIDER_AttributeResult proc;
+
+  /**
+   * Closure for @e proc.
+   */
+  void *proc_cls;
+
+  /**
+   * Function to call on errors.
+   */
+  GNUNET_SCHEDULER_TaskCallback error_cb;
+
+  /**
+   * Closure for @e error_cb.
+   */
+  void *error_cb_cls;
+
+  /**
+   * Envelope of the message to send to the service, if not yet
+   * sent.
+   */
+  struct GNUNET_MQ_Envelope *env;
+
+  /**
+   * Private key of the zone.
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+  /**
+   * The operation id this zone iteration operation has
+   */
+  uint32_t r_id;
+
+};
+
 
 /**
  * Handle for the service.
@@ -127,6 +197,16 @@ struct GNUNET_IDENTITY_PROVIDER_Handle
    */
   struct GNUNET_IDENTITY_PROVIDER_Operation *op_tail;
 
+  /**
+   * Head of active iterations
+   */
+  struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it_head;
+
+  /**
+   * Tail of active iterations
+   */
+  struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it_tail;
+
   /**
    * Currently pending transmission request, or NULL for none.
    */
@@ -201,6 +281,26 @@ force_reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *handle)
                                     handle);
 }
 
+/**
+ * Free @a it.
+ *
+ * @param it entry to free
+ */
+static void
+free_it (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
+
+  GNUNET_CONTAINER_DLL_remove (h->it_head,
+                               h->it_tail,
+                               it);
+  if (NULL != it->env)
+    GNUNET_MQ_discard (it->env);
+  GNUNET_free (it);
+}
+
+
+
 /**
  * Generic error handler, called with the appropriate error code and
  * the same closure specified at the creation of the message queue.
@@ -406,6 +506,91 @@ handle_attribute_store_response (void *cls,
 
 }
 
+/**
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT
+ *
+ * @param cls
+ * @param msg the message we received
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+static int
+check_attribute_result (void *cls,
+                        const struct AttributeResultMessage *msg)
+{
+  size_t msg_len;
+  size_t attr_len;
+
+  msg_len = ntohs (msg->header.size);
+  attr_len = ntohs (msg->attr_len);
+  if (msg_len != sizeof (struct AttributeResultMessage) + attr_len)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT
+ *
+ * @param cls
+ * @param msg the message we received
+ */
+static void
+handle_attribute_result (void *cls,
+                     const struct AttributeResultMessage *msg)
+{
+  static struct GNUNET_CRYPTO_EcdsaPrivateKey identity_dummy;
+  struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
+  struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it;
+  size_t attr_len;
+  uint32_t r_id = ntohl (msg->id);
+
+  attr_len = ntohs (msg->attr_len);
+  
+ for (it = h->it_head; NULL != it; it = it->next)
+    if (it->r_id == r_id)
+      break;
+  if (NULL == it)
+    return;
+
+  if ( (0 == (memcmp (&msg->identity,
+                     &identity_dummy,
+                     sizeof (identity_dummy)))) )
+  {
+    if (NULL == it)
+    {
+      GNUNET_break (0);
+      force_reconnect (h);
+      return;
+    }
+    if (NULL != it->finish_cb)
+      it->finish_cb (it->finish_cb_cls);
+    free_it (it);
+    return;
+  }
+
+  {
+    struct GNUNET_IDENTITY_PROVIDER_Attribute *attr;
+    attr = attribute_deserialize ((char*)&msg[1],
+                                  attr_len);
+    if (NULL != it)
+    {
+      if (NULL != it->proc)
+        it->proc (it->proc_cls,
+                  &msg->identity,
+                  attr);
+      GNUNET_free (attr);
+      return;
+    }
+  }
+  GNUNET_assert (0);
+}
+
+
 
 /**
  * Try again to connect to the service.
@@ -428,7 +613,10 @@ reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h)
                            GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT,
                            struct ExchangeResultMessage,
                            h),
-
+    GNUNET_MQ_hd_var_size (attribute_result,
+                           GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT,
+                           struct AttributeResultMessage,
+                           h),
     GNUNET_MQ_handler_end ()
   };
   struct GNUNET_IDENTITY_PROVIDER_Operation *op;
@@ -717,24 +905,14 @@ GNUNET_IDENTITY_PROVIDER_ticket_destroy(struct GNUNET_IDENTITY_PROVIDER_Ticket *
 struct GNUNET_IDENTITY_PROVIDER_Operation *
 GNUNET_IDENTITY_PROVIDER_attribute_store (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
                                           const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
-                                          const char* name,
-                                          const struct GNUNET_IDENTITY_PROVIDER_Attribute *value,
+                                          const struct GNUNET_IDENTITY_PROVIDER_Attribute *attr,
                                           GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cont,
                                           void *cont_cls)
 {
   struct GNUNET_IDENTITY_PROVIDER_Operation *op;
   struct AttributeStoreMessage *sam;
-  size_t name_len;
-  char *name_tmp;
-  char *attr_ser;
+  size_t attr_len;
 
-
-  name_len = strlen (name) + 1;
-  if (name_len >= GNUNET_MAX_MESSAGE_SIZE - sizeof (struct AttributeStoreMessage))
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
   op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation);
   op->h = h;
   op->as_cb = cont;
@@ -743,17 +921,17 @@ GNUNET_IDENTITY_PROVIDER_attribute_store (struct GNUNET_IDENTITY_PROVIDER_Handle
   GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
                                     h->op_tail,
                                     op);
+  attr_len = attribute_serialize_get_size (attr);
   op->env = GNUNET_MQ_msg_extra (sam,
-                                 name_len + value->data_size,
+                                 attr_len,
                                  GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE);
   sam->identity = *pkey;
   sam->id = htonl (op->r_id);
-  sam->attr_value_len = htons (value->data_size);
-  sam->name_len = htons (name_len);
-  name_tmp = (char *) &sam[1];
-  GNUNET_memcpy (name_tmp, name, name_len);
-  attr_ser = &name_tmp[name_len];
-  GNUNET_memcpy (attr_ser, value->data, value->data_size);
+
+  attribute_serialize (attr,
+                       (char*)&sam[1]);
+
+  sam->attr_len = htons (attr_len);
   if (NULL != h->mq)
     GNUNET_MQ_send_copy (h->mq,
                          op->env);
@@ -762,7 +940,139 @@ GNUNET_IDENTITY_PROVIDER_attribute_store (struct GNUNET_IDENTITY_PROVIDER_Handle
 }
 
 
+/**
+ * Create a new attribute.
+ *
+ * @param name the attribute name
+ * @param type the attribute type
+ * @param data the attribute value
+ * @param data_size the attribute value size
+ * @return the new attribute
+ */
+struct GNUNET_IDENTITY_PROVIDER_Attribute *
+GNUNET_IDENTITY_PROVIDER_attribute_new (const char* attr_name,
+                                        uint32_t attr_type,
+                                        const void* data,
+                                        size_t data_size)
+{
+  return attribute_new (attr_name, attr_type, data, data_size);
+}
+
+/**
+ * List all attributes for a local identity. 
+ * This MUST lock the `struct GNUNET_IDENTITY_PROVIDER_Handle`
+ * for any other calls than #GNUNET_IDENTITY_PROVIDER_get_attributes_next() and
+ * #GNUNET_IDENTITY_PROVIDER_get_attributes_stop. @a proc will be called once
+ * immediately, and then again after
+ * #GNUNET_IDENTITY_PROVIDER_get_attributes_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 idp
+ * @param identity identity to access
+ * @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 attribute; it
+ *        will be called repeatedly with a value (if available)
+ * @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_IDENTITY_PROVIDER_AttributeIterator *
+GNUNET_IDENTITY_PROVIDER_get_attributes_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
+                                               const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+                                               GNUNET_SCHEDULER_TaskCallback error_cb,
+                                               void *error_cb_cls,
+                                               GNUNET_IDENTITY_PROVIDER_AttributeResult proc,
+                                               void *proc_cls,
+                                               GNUNET_SCHEDULER_TaskCallback finish_cb,
+                                               void *finish_cb_cls)
+{
+  struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it;
+  struct GNUNET_MQ_Envelope *env;
+  struct AttributeIterationStartMessage *msg;
+  uint32_t rid;
+
+  rid = h->r_id_gen++;
+  it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator);
+  it->h = h;
+  it->error_cb = error_cb;
+  it->error_cb_cls = error_cb_cls;
+  it->finish_cb = finish_cb;
+  it->finish_cb_cls = finish_cb_cls;
+  it->proc = proc;
+  it->proc_cls = proc_cls;
+  it->r_id = rid;
+  it->identity = *identity;
+  GNUNET_CONTAINER_DLL_insert_tail (h->it_head,
+                                    h->it_tail,
+                                    it);
+  env = GNUNET_MQ_msg (msg,
+                       GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START);
+  msg->id = htonl (rid);
+  msg->identity = *identity;
+  if (NULL == h->mq)
+    it->env = env;
+  else
+    GNUNET_MQ_send (h->mq,
+                    env);
+  return it;
+}
+
+
+/**
+ * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_get_attributes_start
+ * for the next record.
+ *
+ * @param it the iterator
+ */
+void
+GNUNET_IDENTITY_PROVIDER_get_attributes_next (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
+  struct AttributeIterationNextMessage *msg;
+  struct GNUNET_MQ_Envelope *env;
+
+  env = GNUNET_MQ_msg (msg,
+                       GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT);
+  msg->id = htonl (it->r_id);
+  GNUNET_MQ_send (h->mq,
+                  env);
+}
+
+
+/**
+ * Stops iteration and releases the idp handle for further calls.  Must
+ * be called on any iteration that has not yet completed prior to calling
+ * #GNUNET_IDENTITY_PROVIDER_disconnect.
+ *
+ * @param it the iterator
+ */
+void
+GNUNET_IDENTITY_PROVIDER_get_attributes_stop (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h;
+  struct GNUNET_MQ_Envelope *env;
+  struct AttributeIterationStopMessage *msg;
+
+  if (NULL != h->mq)
+  {
+    env = GNUNET_MQ_msg (msg,
+                         GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP);
+    msg->id = htonl (it->r_id);
+    GNUNET_MQ_send (h->mq,
+                    env);
+  }
+  free_it (it);
+}
+
+
 
 
 
-/* end of identity_provider_api.c */
+  /* end of identity_provider_api.c */
index c26c040746120ebbeb239ecf36a17bb36e651c82..1f197378345569fbcef7c1cddaa2a924264cff27 100644 (file)
@@ -56,6 +56,9 @@ value_to_string (void *cls,
     case GNUNET_GNSRECORD_TYPE_ID_ATTR:
     case GNUNET_GNSRECORD_TYPE_ID_TOKEN:
       return GNUNET_strndup (data, data_size);
+    case GNUNET_GNSRECORD_TYPE_ABE_KEY:
+    case GNUNET_GNSRECORD_TYPE_ABE_MASTER:
+      return GNUNET_STRINGS_data_to_string_alloc (data, data_size); 
     case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA:
         ecdhe_privkey = data;
         audience_pubkey = data+sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey);
@@ -110,8 +113,14 @@ string_to_value (void *cls,
       *data = GNUNET_strdup (s);
       *data_size = strlen (s);
       return GNUNET_OK;
+    case GNUNET_GNSRECORD_TYPE_ABE_KEY:
+    case GNUNET_GNSRECORD_TYPE_ABE_MASTER:
+      return GNUNET_STRINGS_string_to_data (s,
+                                            strlen (s),
+                                            *data,
+                                            *data_size);
     case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA:
-            tmp_tok = GNUNET_strdup (s);
+      tmp_tok = GNUNET_strdup (s);
       ecdhe_str = strtok (tmp_tok, ";");
       if (NULL == ecdhe_str)
       {
@@ -160,15 +169,15 @@ string_to_value (void *cls,
  * Mapping of record type numbers to human-readable
  * record type names.
  */
-        static struct {
-          const char *name;
-          uint32_t number;
-        } name_map[] = {
-          { "ID_ATTR", GNUNET_GNSRECORD_TYPE_ID_ATTR },
-          { "ID_TOKEN", GNUNET_GNSRECORD_TYPE_ID_TOKEN },
-          { "ID_TOKEN_METADATA", GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA },
-          { NULL, UINT32_MAX }
-        };
+static struct {
+  const char *name;
+  uint32_t number;
+} name_map[] = {
+  { "ID_ATTR", GNUNET_GNSRECORD_TYPE_ID_ATTR },
+  { "ID_TOKEN", GNUNET_GNSRECORD_TYPE_ID_TOKEN },
+  { "ID_TOKEN_METADATA", GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA },
+  { NULL, UINT32_MAX }
+};
 
 
 /**
index 2eeb27ce92032fff1a136f9a0b43a963ee8650a4..ce5c5ca69c331be6ca3f0e3e1937e62a4c2c3500 100755 (executable)
@@ -27,5 +27,6 @@ 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 john@doe.gnu -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
index 69f6ce5d4842e5c94baefbeb12e9fea51dd73eed..78d31a9ece42628a49d0d6890de589d6bf257437 100644 (file)
@@ -2168,7 +2168,7 @@ GNUNET_CRYPTO_cpabe_delete_key (struct GNUNET_CRYPTO_AbeKey *key);
 ssize_t
 GNUNET_CRYPTO_cpabe_encrypt (const void *block,
                              size_t size,
-                             char *policy,
+                             const char *policy,
                              const struct GNUNET_CRYPTO_AbeMasterKey *key,
                              void **result);
 
index 2349e7012bc69de9dd0900ffc9fd820e028dd424..aaa838a03146315d7ee61eff6ef38bb0987866a6 100644 (file)
@@ -93,11 +93,9 @@ struct GNUNET_IDENTITY_PROVIDER_Attribute
 {
 
   /**
-   * Binary value stored as attribute value.  Note: "data" must never
-   * be individually 'malloc'ed, but instead always points into some
-   * existing data area.
+   * Type of Attribute.
    */
-  const void *data;
+  uint32_t attribute_type;
 
   /**
    * Number of bytes in @e data.
@@ -105,9 +103,17 @@ struct GNUNET_IDENTITY_PROVIDER_Attribute
   size_t data_size;
 
   /**
-   * Type of Attribute.
+   * The name of the attribute. Note "name" must never be individually
+   * free'd
    */
-  uint32_t attribute_type;
+  const char* name;
+
+  /**
+   * Binary value stored as attribute value.  Note: "data" must never
+   * be individually 'malloc'ed, but instead always points into some
+   * existing data area.
+   */
+  const void *data;
 
 };
 
@@ -176,8 +182,7 @@ typedef void
  *
  * @param h handle to the identity provider
  * @param pkey private key of the identity
- * @param name the attribute name
- * @param value the attribute value
+ * @param attr the attribute
  * @param cont continuation to call when done
  * @param cont_cls closure for @a cont
  * @return handle to abort the request
@@ -185,12 +190,95 @@ typedef void
 struct GNUNET_IDENTITY_PROVIDER_Operation *
 GNUNET_IDENTITY_PROVIDER_attribute_store (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
                                           const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
-                                          const char* name,
-                                          const struct GNUNET_IDENTITY_PROVIDER_Attribute *value,
+                                          const struct GNUNET_IDENTITY_PROVIDER_Attribute *attr,
                                           GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cont,
                                           void *cont_cls);
 
 
+/**
+ * Create a new attribute.
+ *
+ * @param name the attribute name
+ * @param type the attribute type
+ * @param data the attribute value
+ * @param data_size the attribute value size
+ * @return the new attribute
+ */
+struct GNUNET_IDENTITY_PROVIDER_Attribute *
+GNUNET_IDENTITY_PROVIDER_attribute_new (const char* attr_name,
+                                        uint32_t attr_type,
+                                        const void* data,
+                                        size_t data_size);
+
+/**
+ * Process an attribute that was stored in the idp.
+ *
+ * @param cls closure
+ * @param attr the attribute
+ */
+typedef void
+(*GNUNET_IDENTITY_PROVIDER_AttributeResult) (void *cls,
+                                   const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+                                   const struct GNUNET_IDENTITY_PROVIDER_Attribute *attr);
+
+
+
+/**
+ * List all attributes for a local identity. 
+ * This MUST lock the `struct GNUNET_IDENTITY_PROVIDER_Handle`
+ * for any other calls than #GNUNET_IDENTITY_PROVIDER_get_attributes_next() and
+ * #GNUNET_IDENTITY_PROVIDER_get_attributes_stop. @a proc will be called once
+ * immediately, and then again after
+ * #GNUNET_IDENTITY_PROVIDER_get_attributes_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 idp
+ * @param identity identity to access
+ * @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 attribute; it
+ *        will be called repeatedly with a value (if available)
+ * @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_IDENTITY_PROVIDER_AttributeIterator *
+GNUNET_IDENTITY_PROVIDER_get_attributes_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h,
+                                               const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
+                                               GNUNET_SCHEDULER_TaskCallback error_cb,
+                                               void *error_cb_cls,
+                                               GNUNET_IDENTITY_PROVIDER_AttributeResult proc,
+                                               void *proc_cls,
+                                               GNUNET_SCHEDULER_TaskCallback finish_cb,
+                                               void *finish_cb_cls);
+
+
+/**
+ * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_get_attributes_start
+ * for the next record.
+ *
+ * @param it the iterator
+ */
+void
+GNUNET_IDENTITY_PROVIDER_get_attributes_next (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it);
+
+
+/**
+ * Stops iteration and releases the idp handle for further calls.  Must
+ * be called on any iteration that has not yet completed prior to calling
+ * #GNUNET_IDENTITY_PROVIDER_disconnect.
+ *
+ * @param it the iterator
+ */
+void
+GNUNET_IDENTITY_PROVIDER_get_attributes_stop (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it);
+
 
 
 /**
index 5841bd4f80cbe2dee4841fdddc881acc3e387ff7..e498af1f51cc6c4ad1ddcc525020be4720997a41 100644 (file)
@@ -2632,6 +2632,13 @@ extern "C"
 
 #define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE 966
 
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START 967
+
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP 968
+
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT 969
+
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT 970
 
 /**************************************************
  *
index 25d04fba61b900efaf26f7e673eee4b780186caf..899965159932c3532d346c76faa8f34d3e5ec8cd 100644 (file)
@@ -168,7 +168,6 @@ GNUNET_CRYPTO_cpabe_create_key (struct GNUNET_CRYPTO_AbeMasterKey *key,
                              char **attrs)
 {
   struct GNUNET_CRYPTO_AbeKey *prv_key;
-  prv_key = GNUNET_new (struct GNUNET_CRYPTO_AbeKey);
   int size;
   char *tmp;
   
@@ -249,7 +248,7 @@ read_cpabe (const void *data,
 ssize_t
 GNUNET_CRYPTO_cpabe_encrypt (const void *block,
                              size_t size,
-                             char *policy,
+                             const char *policy,
                              const struct GNUNET_CRYPTO_AbeMasterKey *key,
                              void **result)
 {
@@ -262,7 +261,7 @@ GNUNET_CRYPTO_cpabe_encrypt (const void *block,
   int aes_buf_len;
   ssize_t result_len;
 
-  if( !(cph = gabe_enc(key->pub, m, policy)) )
+  if( !(cph = gabe_enc(key->pub, m, (char*)policy)) )
     return GNUNET_SYSERR;
   cph_buf_len = gabe_cph_serialize(cph,
                                 &cph_buf);