*/
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
{
/**
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);
}
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);
}
/**
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);
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);*/
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
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 */
*/
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.
*/
}
+
+
+/**
+ * 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.
*
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,
GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT,
struct ExchangeResultMessage,
h),
+
GNUNET_MQ_handler_end ()
};
struct GNUNET_IDENTITY_PROVIDER_Operation *op;
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;
+
+}
+
*/
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
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.
*/
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);
/**
*/
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);
/**