From 9e6994a55e64aaf7b45fdad7277c27bf30e3c0f3 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Fri, 15 Sep 2017 18:53:10 +0200 Subject: - Add attribute store API to IdP service --- src/identity-provider/Makefile.am | 1 + src/identity-provider/gnunet-idp.c | 28 +- .../gnunet-service-identity-provider.c | 325 ++++++++++++++++++--- src/identity-provider/identity_provider.h | 60 ++++ src/identity-provider/identity_provider_api.c | 116 ++++++++ 5 files changed, 482 insertions(+), 48 deletions(-) (limited to 'src/identity-provider') diff --git a/src/identity-provider/Makefile.am b/src/identity-provider/Makefile.am index 5355b1221..4f5738692 100644 --- a/src/identity-provider/Makefile.am +++ b/src/identity-provider/Makefile.am @@ -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) diff --git a/src/identity-provider/gnunet-idp.c b/src/identity-provider/gnunet-idp.c index 6b2bdcc96..b4785580a 100644 --- a/src/identity-provider/gnunet-idp.c +++ b/src/identity-provider/gnunet-idp.c @@ -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, diff --git a/src/identity-provider/gnunet-service-identity-provider.c b/src/identity-provider/gnunet-service-identity-provider.c index 8746e39f7..5663a7681 100644 --- a/src/identity-provider/gnunet-service-identity-provider.c +++ b/src/identity-provider/gnunet-service-identity-provider.c @@ -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;iabe_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 */ diff --git a/src/identity-provider/identity_provider.h b/src/identity-provider/identity_provider.h index 9d2675c35..47d3f0945 100644 --- a/src/identity-provider/identity_provider.h +++ b/src/identity-provider/identity_provider.h @@ -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 diff --git a/src/identity-provider/identity_provider_api.c b/src/identity-provider/identity_provider_api.c index 9a3304334..bbc2bb70a 100644 --- a/src/identity-provider/identity_provider_api.c +++ b/src/identity-provider/identity_provider_api.c @@ -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; + +} + -- cgit v1.2.3