From: Schanzenbach, Martin Date: Sat, 16 Sep 2017 20:39:15 +0000 (+0200) Subject: -various fixes; add attribute list API X-Git-Tag: gnunet-0.11.0rc0~24^2~55 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=67e0d73709ef557b52ba0527291d68c17fd6c60a;p=oweals%2Fgnunet.git -various fixes; add attribute list API --- diff --git a/src/identity-provider/Makefile.am b/src/identity-provider/Makefile.am index ab0c2f67e..106c8a92b 100644 --- a/src/identity-provider/Makefile.am +++ b/src/identity-provider/Makefile.am @@ -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) diff --git a/src/identity-provider/gnunet-idp.c b/src/identity-provider/gnunet-idp.c index b4785580a..264d77ba2 100644 --- a/src/identity-provider/gnunet-idp.c +++ b/src/identity-provider/gnunet-idp.c @@ -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;iname, (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); diff --git a/src/identity-provider/gnunet-service-identity-provider.c b/src/identity-provider/gnunet-service-identity-provider.c index 5663a7681..0ce70aed3 100644 --- a/src/identity-provider/gnunet-service-identity-provider.c +++ b/src/identity-provider/gnunet-service-identity-provider.c @@ -36,6 +36,7 @@ #include "gnunet_signatures.h" #include "identity_provider.h" #include "identity_token.h" +#include "identity_attribute.h" #include /** @@ -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;iabe_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 index 000000000..3794010b2 --- /dev/null +++ b/src/identity-provider/identity_attribute.c @@ -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 index 000000000..0d4f2bb76 --- /dev/null +++ b/src/identity-provider/identity_attribute.h @@ -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 diff --git a/src/identity-provider/identity_provider.h b/src/identity-provider/identity_provider.h index 47d3f0945..588d6d39a 100644 --- a/src/identity-provider/identity_provider.h +++ b/src/identity-provider/identity_provider.h @@ -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 diff --git a/src/identity-provider/identity_provider_api.c b/src/identity-provider/identity_provider_api.c index bbc2bb70a..c806735f6 100644 --- a/src/identity-provider/identity_provider_api.c +++ b/src/identity-provider/identity_provider_api.c @@ -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 */ diff --git a/src/identity-provider/plugin_gnsrecord_identity_provider.c b/src/identity-provider/plugin_gnsrecord_identity_provider.c index c26c04074..1f1973783 100644 --- a/src/identity-provider/plugin_gnsrecord_identity_provider.c +++ b/src/identity-provider/plugin_gnsrecord_identity_provider.c @@ -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 } +}; /** diff --git a/src/identity-provider/test_idp.sh b/src/identity-provider/test_idp.sh index 2eeb27ce9..ce5c5ca69 100755 --- a/src/identity-provider/test_idp.sh +++ b/src/identity-provider/test_idp.sh @@ -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 diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h index 69f6ce5d4..78d31a9ec 100644 --- a/src/include/gnunet_crypto_lib.h +++ b/src/include/gnunet_crypto_lib.h @@ -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); diff --git a/src/include/gnunet_identity_provider_service.h b/src/include/gnunet_identity_provider_service.h index 2349e7012..aaa838a03 100644 --- a/src/include/gnunet_identity_provider_service.h +++ b/src/include/gnunet_identity_provider_service.h @@ -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); + /** diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index 5841bd4f8..e498af1f5 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h @@ -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 /************************************************** * diff --git a/src/util/crypto_abe.c b/src/util/crypto_abe.c index 25d04fba6..899965159 100644 --- a/src/util/crypto_abe.c +++ b/src/util/crypto_abe.c @@ -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);