- Add attribute store API to IdP service
authorSchanzenbach, Martin <mschanzenbach@posteo.de>
Fri, 15 Sep 2017 16:53:10 +0000 (18:53 +0200)
committerSchanzenbach, Martin <mschanzenbach@posteo.de>
Fri, 15 Sep 2017 16:53:10 +0000 (18:53 +0200)
src/identity-provider/Makefile.am
src/identity-provider/gnunet-idp.c
src/identity-provider/gnunet-service-identity-provider.c
src/identity-provider/identity_provider.h
src/identity-provider/identity_provider_api.c
src/include/gnunet_identity_provider_service.h
src/include/gnunet_protocols.h

index 5355b1221af326b6d89395bd207bb8039d4e5e05..4f573869261b0a170624403ed803e28f45989329 100644 (file)
@@ -74,6 +74,7 @@ gnunet_idp_SOURCES = \
 gnunet_idp_LDADD = \
   $(top_builddir)/src/util/libgnunetutil.la \
        $(top_builddir)/src/namestore/libgnunetnamestore.la \
+       $(top_builddir)/src/identity-provider/libgnunetidentityprovider.la \
        $(top_builddir)/src/identity/libgnunetidentity.la \
   $(GN_LIBINTL)
 
index 6b2bdcc968b8500ac5c9b881248b59f92dbcf904..b4785580a663e918a5e918a045a6756e7b207835 100644 (file)
@@ -27,6 +27,7 @@
 #include "platform.h"
 #include "gnunet_util_lib.h"
 #include "gnunet_namestore_service.h"
+#include "gnunet_identity_provider_service.h"
 #include "gnunet_identity_service.h"
 #include "gnunet_signatures.h"
 
@@ -60,6 +61,16 @@ static char* ego_name;
  */
 static struct GNUNET_IDENTITY_Handle *identity_handle;
 
+/**
+ * IdP handle
+ */
+static struct GNUNET_IDENTITY_PROVIDER_Handle *idp_handle;
+
+/**
+ * IdP operation
+ */
+static struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op;
+
 /**
  * Namestore handle
  */
@@ -235,7 +246,19 @@ abe_lookup_cb (void *cls,
     return;
   }
 
-  size = GNUNET_CRYPTO_cpabe_encrypt (attr_value,
+  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;
+  idp_op = GNUNET_IDENTITY_PROVIDER_attribute_store (idp_handle,
+                                                    zone,
+                                                    attr_name,
+                                                    attr,
+                                                    &store_attr_cont,
+                                                    NULL);
+
+  /*size = GNUNET_CRYPTO_cpabe_encrypt (attr_value,
                                       strlen (attr_value) + 1,
                                       attr_name,
                                       abe_key,
@@ -251,7 +274,7 @@ abe_lookup_cb (void *cls,
                                           1,
                                           &new_record,
                                           &store_attr_cont,
-                                          NULL);
+                                          NULL);*/
 }
 
 static void
@@ -301,6 +324,7 @@ run (void *cls,
   }
 
   namestore_handle = GNUNET_NAMESTORE_connect (c);
+  idp_handle = GNUNET_IDENTITY_PROVIDER_connect (c);
   //Get Ego
   identity_handle = GNUNET_IDENTITY_connect (c,
                                              &ego_cb,
index 8746e39f76d13e7cd0cfe2d122b7623051be8a31..5663a76816582b6b3d66a964e4e5ff7b93376ee3 100644 (file)
@@ -129,6 +129,57 @@ static struct GNUNET_STATISTICS_Handle *stats;
  */
 static const struct GNUNET_CONFIGURATION_Handle *cfg;
 
+struct AttributeStoreHandle
+{
+
+  /**
+   * Client connection
+   */
+  struct GNUNET_SERVICE_Client *client;
+
+  /**
+   * Identity
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+  /**
+   * Identity pubkey
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
+
+  /**
+   * The issuer egos ABE master key
+   */
+  struct GNUNET_CRYPTO_AbeMasterKey *abe_key;
+
+  /**
+   * QueueEntry
+   */
+  struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
+
+  /**
+   * The attribute name
+   */
+  char *name;
+
+  /**
+   * The attribute value
+   */
+  char *attribute_value;
+
+  /**
+   * Size of the attribute value
+   */
+  size_t attribute_value_len;
+
+  /**
+   * request id
+   */
+  uint32_t r_id;
+};
+
+
+
 struct VerifiedAttributeEntry
 {
   /**
@@ -1175,45 +1226,13 @@ attr_collect_task (void *cls)
                                                                issue_handle);
 }
 
-void
-store_bootstrap_cont (void *cls,
-                      int32_t success,
-                      const char *emsg)
-{
-  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);
-    return;
-  }
-  GNUNET_SCHEDULER_add_now (&attr_collect_task, cls);
-}
-
-void
-store_bootstrap_task (void *cls)
-{
-  struct IssueHandle *issue_handle = cls;
-  struct GNUNET_GNSRECORD_Data rd[1];
 
-  rd[0].data_size = GNUNET_CRYPTO_cpabe_serialize_master_key (issue_handle->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?
-  issue_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
-                                                        &issue_handle->iss_key,
-                                                        "+",
-                                                        1,
-                                                        rd,
-                                                        &store_bootstrap_cont,
-                                                        issue_handle);
-}
 
 void
 abe_key_lookup_error (void *cls)
 {
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+              "Error looking for ABE master!\n");
   GNUNET_SCHEDULER_add_now (&do_shutdown, cls);
 }
 
@@ -1235,10 +1254,10 @@ abe_key_lookup_result (void *cls,
     GNUNET_SCHEDULER_add_now (&attr_collect_task, handle);
     return;
   }
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+              "No ABE master found!\n");
+  GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
 
-  //No ABE master found, bootstrapping...
-  handle->abe_key = GNUNET_CRYPTO_cpabe_create_master_key ();
-  GNUNET_SCHEDULER_add_now (&store_bootstrap_task, handle);
 }
 
 /**
@@ -1256,15 +1275,13 @@ handle_issue_message (void *cls,
   const char *scopes;
   char *scopes_tmp;
   char *scope;
-  const char *v_attrs;
   uint64_t rnd_key;
   struct GNUNET_HashCode key;
   struct IssueHandle *issue_handle;
-  struct VerifiedAttributeEntry *vattr_entry;
   struct GNUNET_SERVICE_Client *client = cls;
 
   scopes = (const char *) &im[1];
-  v_attrs = (const char *) &im[1] + ntohl(im->scope_len);
+  //v_attrs = (const char *) &im[1] + ntohl(im->scope_len);
   issue_handle = GNUNET_malloc (sizeof (struct IssueHandle));
   issue_handle->attr_map = GNUNET_CONTAINER_multihashmap_create (5,
                                                                  GNUNET_NO);
@@ -1283,15 +1300,15 @@ handle_issue_message (void *cls,
   GNUNET_free (scopes_tmp);
   /*scopes_tmp = GNUNET_strdup (v_attrs);
 
-  for (scope = strtok (scopes_tmp, ","); NULL != scope; scope = strtok (NULL, ","))
-  {
+    for (scope = strtok (scopes_tmp, ","); NULL != scope; scope = strtok (NULL, ","))
+    {
     vattr_entry = GNUNET_new (struct VerifiedAttributeEntry);
     vattr_entry->name = GNUNET_strdup (scope);
     GNUNET_CONTAINER_DLL_insert (issue_handle->v_attr_head,
-                                 issue_handle->v_attr_tail,
-                                 vattr_entry);
-  }
-  GNUNET_free (scopes_tmp);*/
+    issue_handle->v_attr_tail,
+    vattr_entry);
+    }
+    GNUNET_free (scopes_tmp);*/
 
 
 
@@ -1322,6 +1339,218 @@ handle_issue_message (void *cls,
                                                          issue_handle);
 }
 
+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);
+  GNUNET_free (handle);
+}
+
+
+
+void
+attr_store_cont (void *cls,
+                 int32_t success,
+                 const char *emsg)
+{
+  struct AttributeStoreHandle *as_handle = cls;
+  struct GNUNET_MQ_Envelope *env;
+  struct AttributeStoreResponseMessage *acr_msg;
+
+  if (GNUNET_SYSERR == success)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to store attribute %s\n",
+                emsg);
+    GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
+    return;
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Sending ATTRIBUTE_STORE_RESPONSE message\n");
+  env = GNUNET_MQ_msg (acr_msg,
+                      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),
+                  env);
+  cleanup_as_handle (as_handle);
+}
+
+void
+attr_store_task (void *cls)
+{
+  struct AttributeStoreHandle *as_handle = cls;
+  struct GNUNET_GNSRECORD_Data rd[1];
+
+  /**
+   * 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
+                                                 as_handle->abe_key,
+                                                 (void**)&rd[0].data);
+  rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR;
+  rd[0].flags = GNUNET_GNSRECORD_RF_NONE;
+  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,
+                                                     1,
+                                                     rd,
+                                                     &attr_store_cont,
+                                                     as_handle);
+
+}
+
+void
+store_bootstrap_cont (void *cls,
+                      int32_t success,
+                      const char *emsg)
+{
+  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);
+    return;
+  }
+  GNUNET_SCHEDULER_add_now (&attr_store_task, cls);
+}
+
+void
+store_bootstrap_task (void *cls)
+{
+  struct AttributeStoreHandle *as_handle = cls;
+  struct GNUNET_GNSRECORD_Data rd[1];
+
+  rd[0].data_size = GNUNET_CRYPTO_cpabe_serialize_master_key (as_handle->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);
+}
+
+void
+store_cont_abe_error (void *cls)
+{
+  GNUNET_SCHEDULER_add_now (&do_shutdown, cls);
+}
+
+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)
+{
+  struct AttributeStoreHandle *handle = cls;
+  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);
+    return;
+  }
+
+  //No ABE master found, bootstrapping...
+  handle->abe_key = GNUNET_CRYPTO_cpabe_create_master_key ();
+  GNUNET_SCHEDULER_add_now (&store_bootstrap_task, handle);
+}
+
+
+/**
+ * Checks a store message
+ *
+ * @param cls client sending the message
+ * @param sam message of type `struct AttributeStoreMessage`
+ * @return #GNUNET_OK if @a im is well-formed
+ */
+static int
+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))
+  {
+    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
+ *
+ * @param cls unused
+ * @param client who sent the message
+ * @param message the message
+ */
+static void
+handle_attribute_store_message (void *cls,
+                                const struct AttributeStoreMessage *sam)
+{
+  struct AttributeStoreHandle *as_handle;
+  struct GNUNET_SERVICE_Client *client = cls;
+  size_t name_len;
+  size_t data_len;
+  char *attribute_value;
+
+  name_len = ntohs (sam->name_len);
+  data_len = ntohs (sam->attr_value_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->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);
+}
+
 
 /**
  * Main function that will be run
@@ -1435,5 +1664,9 @@ GNUNET_SERVICE_MAIN
                         GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE,
                         struct ExchangeMessage,
                         NULL),
+ GNUNET_MQ_hd_var_size (attribute_store_message,
+                        GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE,
+                        struct AttributeStoreMessage,
+                        NULL),
  GNUNET_MQ_handler_end());
 /* end of gnunet-service-identity-provider.c */
index 9d2675c35af020a28f371550a6b9bff3c82f731e..47d3f0945cfc70cd3843e4ff673c498d076576c9 100644 (file)
@@ -173,6 +173,66 @@ struct ExchangeMessage
 
 };
 
+/**
+ * Use to store an identity attribute
+ */
+struct AttributeStoreMessage
+{
+  /**
+   * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+  /**
+   * The attribute type
+   */
+  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;
+
+  /**
+   * Identity
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
+
+  /* followed by the name of attribute as string and value data */
+
+};
+
+/**
+ * Attribute store response message
+ */
+struct AttributeStoreResponseMessage
+{
+  /**
+   * Message header
+   */
+  struct GNUNET_MessageHeader header;
+  
+  /**
+   * Unique identifier for this request (for key collisions).
+   */
+  uint32_t id GNUNET_PACKED;
+
+  /**
+   * #GNUNET_SYSERR on failure, #GNUNET_OK on success
+   */
+  int32_t op_result GNUNET_PACKED;
+
+};
 
 GNUNET_NETWORK_STRUCT_END
 
index 9a330433473a37bbbd82c7b52ccf10dd960b470b..bbc2bb70a6c3af6391293ed01c8a6af977ab34cf 100644 (file)
@@ -74,6 +74,11 @@ struct GNUNET_IDENTITY_PROVIDER_Operation
    */
   GNUNET_IDENTITY_PROVIDER_IssueCallback iss_cb;
 
+  /**
+   * Continuation to invoke after attribute store call
+   */
+  GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus as_cb;
+
   /**
    * Envelope with the message for this queue entry.
    */
@@ -355,6 +360,53 @@ handle_result (void *cls,
 
 }
 
+
+
+/**
+ * Handle an incoming message of type
+ * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE
+ *
+ * @param cls
+ * @param msg the message we received
+ */
+static void
+handle_attribute_store_response (void *cls,
+                             const struct AttributeStoreResponseMessage *msg)
+{
+  struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls;
+  struct GNUNET_IDENTITY_PROVIDER_Operation *op;
+  uint32_t r_id = ntohl (msg->id);
+  int res;
+  const char *emsg;
+
+  for (op = h->op_head; NULL != op; op = op->next)
+    if (op->r_id == r_id)
+      break;
+  if (NULL == op)
+    return;
+
+  res = ntohl (msg->op_result);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Received ATTRIBUTE_STORE_RESPONSE with result %d\n",
+       res);
+
+  /* TODO: add actual error message to response... */
+  if (GNUNET_SYSERR == res)
+    emsg = _("failed to store record\n");
+  else
+    emsg = NULL;
+  if (NULL != op->as_cb)
+    op->as_cb (op->cls,
+              res,
+              emsg);
+  GNUNET_CONTAINER_DLL_remove (h->op_head,
+                               h->op_tail,
+                               op);
+  GNUNET_free (op);
+
+}
+
+
 /**
  * Try again to connect to the service.
  *
@@ -364,6 +416,10 @@ static void
 reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h)
 {
   struct GNUNET_MQ_MessageHandler handlers[] = {
+    GNUNET_MQ_hd_fixed_size (attribute_store_response,
+                             GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE,
+                             struct AttributeStoreResponseMessage,
+                             h),
     GNUNET_MQ_hd_var_size (result,
                            GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT,
                            struct IssueResultMessage,
@@ -372,6 +428,7 @@ reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h)
                            GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT,
                            struct ExchangeResultMessage,
                            h),
+
     GNUNET_MQ_handler_end ()
   };
   struct GNUNET_IDENTITY_PROVIDER_Operation *op;
@@ -645,6 +702,65 @@ GNUNET_IDENTITY_PROVIDER_ticket_destroy(struct GNUNET_IDENTITY_PROVIDER_Ticket *
   GNUNET_free (ticket);
 }
 
+/**
+ * Store an attribute.  If the attribute is already present,
+ * it is replaced with the new attribute.
+ *
+ * @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 cont continuation to call when done
+ * @param cont_cls closure for @a cont
+ * @return handle to abort the request
+ */
+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,
+                                          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;
+
+
+  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;
+  op->cls = cont_cls;
+  op->r_id = h->r_id_gen++;
+  GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
+                                    h->op_tail,
+                                    op);
+  op->env = GNUNET_MQ_msg_extra (sam,
+                                 name_len + value->data_size,
+                                 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);
+  if (NULL != h->mq)
+    GNUNET_MQ_send_copy (h->mq,
+                         op->env);
+  return op;
+
+}
+
 
 
 
index ba727eb9261ae267e35e22f9bdd7509101ef231e..2349e7012bc69de9dd0900ffc9fd820e028dd424 100644 (file)
@@ -66,6 +66,53 @@ struct GNUNET_IDENTITY_PROVIDER_Ticket;
  */
 struct GNUNET_IDENTITY_PROVIDER_Operation;
 
+/**
+ * Flags that can be set for an attribute.
+ */
+enum GNUNET_IDENTITY_PROVIDER_AttributeType
+{
+
+  /**
+   * No value attribute.
+   */
+  GNUNET_IDENTITY_PROVIDER_AT_NULL = 0,
+
+  /**
+   * String attribute.
+   */
+  GNUNET_IDENTITY_PROVIDER_AT_STRING = 1,
+
+};
+
+
+
+/**
+ * An attribute.
+ */
+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.
+   */
+  const void *data;
+
+  /**
+   * Number of bytes in @e data.
+   */
+  size_t data_size;
+
+  /**
+   * Type of Attribute.
+   */
+  uint32_t attribute_type;
+
+};
+
+
+
 /**
  * Method called when a token has been exchanged for a ticket.
  * On success returns a token
@@ -107,6 +154,44 @@ typedef void
 struct GNUNET_IDENTITY_PROVIDER_Handle *
 GNUNET_IDENTITY_PROVIDER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg);
 
+/**
+ * Continuation called to notify client about result of the
+ * operation.
+ *
+ * @param cls closure
+ * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate)
+ *                #GNUNET_NO if content was already there or not found
+ *                #GNUNET_YES (or other positive value) on success
+ * @param emsg NULL on success, otherwise an error message
+ */
+typedef void
+(*GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus) (void *cls,
+                                            int32_t success,
+                                            const char *emsg);
+
+
+/**
+ * Store an attribute.  If the attribute is already present,
+ * it is replaced with the new attribute.
+ *
+ * @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 cont continuation to call when done
+ * @param cont_cls closure for @a cont
+ * @return handle to abort the request
+ */
+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,
+                                          GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cont,
+                                          void *cont_cls);
+
+
+
 
 /**
  * Issue a token for a specific audience.
@@ -123,14 +208,14 @@ GNUNET_IDENTITY_PROVIDER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
  */
 struct GNUNET_IDENTITY_PROVIDER_Operation *
 GNUNET_IDENTITY_PROVIDER_issue_token (struct GNUNET_IDENTITY_PROVIDER_Handle *id,
-                    const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss_key,
-         const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
-         const char* scope,
-         const char* vattr,
-         struct GNUNET_TIME_Absolute expiration,
-         uint64_t nonce,
-                    GNUNET_IDENTITY_PROVIDER_IssueCallback cb,
-                    void *cb_cls);
+                                      const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss_key,
+                                      const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key,
+                                      const char* scope,
+                                      const char* vattr,
+                                      struct GNUNET_TIME_Absolute expiration,
+                                      uint64_t nonce,
+                                      GNUNET_IDENTITY_PROVIDER_IssueCallback cb,
+                                      void *cb_cls);
 
 
 /**
@@ -146,10 +231,10 @@ GNUNET_IDENTITY_PROVIDER_issue_token (struct GNUNET_IDENTITY_PROVIDER_Handle *id
  */
 struct GNUNET_IDENTITY_PROVIDER_Operation *
 GNUNET_IDENTITY_PROVIDER_exchange_ticket (struct GNUNET_IDENTITY_PROVIDER_Handle *id,
-                    const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
-         const struct GNUNET_CRYPTO_EcdsaPrivateKey *aud_privkey,
-                    GNUNET_IDENTITY_PROVIDER_ExchangeCallback cont,
-                    void *cont_cls);
+                                          const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket,
+                                          const struct GNUNET_CRYPTO_EcdsaPrivateKey *aud_privkey,
+                                          GNUNET_IDENTITY_PROVIDER_ExchangeCallback cont,
+                                          void *cont_cls);
 
 
 /**
index 455a8292b0de80db1eec8ffede0b848d89f0aeec..5841bd4f80cbe2dee4841fdddc881acc3e387ff7 100644 (file)
@@ -2628,6 +2628,10 @@ extern "C"
 
 #define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT  964
 
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE 965
+
+#define GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE 966
+
 
 /**************************************************
  *