From e6eb523e12729ef1d6a6ee3f140671e5e51d8d1c Mon Sep 17 00:00:00 2001 From: Markus Voggenreiter Date: Wed, 9 Oct 2019 21:10:14 +0200 Subject: [PATCH] Adapted JSON Conversion and Serialization --- src/include/gnunet_reclaim_attribute_lib.h | 144 +++++++++++ src/include/gnunet_reclaim_attribute_plugin.h | 21 ++ .../plugin_reclaim_attribute_gnuid.c | 110 ++++++++ src/reclaim-attribute/reclaim_attribute.c | 242 ++++++++++++++++++ src/reclaim-attribute/reclaim_attribute.h | 33 +++ src/reclaim/json_reclaim.c | 110 ++++++++ src/reclaim/json_reclaim.h | 10 + 7 files changed, 670 insertions(+) diff --git a/src/include/gnunet_reclaim_attribute_lib.h b/src/include/gnunet_reclaim_attribute_lib.h index 4563a5f67..c23b39383 100644 --- a/src/include/gnunet_reclaim_attribute_lib.h +++ b/src/include/gnunet_reclaim_attribute_lib.h @@ -50,6 +50,15 @@ extern "C" { */ #define GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING 1 +/** +* No value attestation. +*/ +#define GNUNET_RECLAIM_ATTESTATION_TYPE_NONE 0 + +/** +* A JSON Web Token attestation. +*/ +#define GNUNET_RECLAIM_ATTESTATION_TYPE_JWT 1 /** * An attribute. @@ -89,6 +98,44 @@ struct GNUNET_RECLAIM_ATTRIBUTE_Claim const void *data; }; +/** + * An attestation. + */ +struct GNUNET_RECLAIM_ATTESTATION_Claim +{ + /** + * ID + */ + uint64_t id; + + /** + * Type/Format of Claim + */ + uint32_t type; + + /** + * Version + */ + uint32_t version; + + /** + * The name of the attribute. Note "name" must never be individually + * free'd + */ + const char *name; + + /** + * Number of bytes in @e data. + */ + size_t data_size; + + /** + * 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; +}; /** * A list of GNUNET_RECLAIM_ATTRIBUTE_Claim structures. @@ -299,6 +346,103 @@ GNUNET_RECLAIM_ATTRIBUTE_value_to_string (uint32_t type, const char * GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (uint32_t type); +/** + * Get required size for serialization buffer + * + * @param attr the attestation to serialize + * @return the required buffer size + */ +size_t +GNUNET_RECLAIM_ATTESTATION_serialize_get_size ( + const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr); + + +/** + * Serialize an attestation + * + * @param attr the attestation to serialize + * @param result the serialized attestation + * @return length of serialized data + */ +size_t +GNUNET_RECLAIM_ATTESTATION_serialize ( + const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr, + char *result); + + +/** + * Deserialize an attestation + * + * @param data the serialized attestation + * @param data_size the length of the serialized data + * + * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller + */ +struct GNUNET_RECLAIM_ATTESTATION_Claim * +GNUNET_RECLAIM_ATTESTATION_deserialize (const char *data, size_t data_size); + + +/** + * Create a new attestation. + * + * @param attr_name the attestation name + * @param type the attestation type + * @param data the attestation value + * @param data_size the attestation value size + * @return the new attestation + */ +struct GNUNET_RECLAIM_ATTESTATION_Claim * +GNUNET_RECLAIM_ATTESTATION_claim_new (const char *attr_name, + uint32_t type, + const void *data, + size_t data_size); + +/** + * Convert the 'claim' of an attestation to a string + * + * @param type the type of attestation + * @param data claim in binary encoding + * @param data_size number of bytes in @a data + * @return NULL on error, otherwise human-readable representation of the claim + */ +char * +GNUNET_RECLAIM_ATTESTATION_value_to_string (uint32_t type, + const void *data, + size_t data_size); + +/** + * Convert human-readable version of a 'claim' of an attestation to the binary + * representation + * + * @param type type of the claim + * @param s human-readable string + * @param data set to value in binary encoding (will be allocated) + * @param data_size set to number of bytes in @a data + * @return #GNUNET_OK on success + */ +int +GNUNET_RECLAIM_ATTESTATION_string_to_value (uint32_t type, + const char *s, + void **data, + size_t *data_size); + +/** + * Convert an attestation type number to the corresponding attestation type string + * + * @param type number of a type + * @return corresponding typestring, NULL on error + */ +const char * +GNUNET_RECLAIM_ATTESTATION_number_to_typename (uint32_t type); + +/** + * Convert an attestation type name to the corresponding number + * + * @param typename name to convert + * @return corresponding number, UINT32_MAX on error + */ +uint32_t +GNUNET_RECLAIM_ATTESTATION_typename_to_number (const char *typename); #if 0 /* keep Emacsens' auto-indent happy */ { diff --git a/src/include/gnunet_reclaim_attribute_plugin.h b/src/include/gnunet_reclaim_attribute_plugin.h index 26a4bb4f2..bdd815dcf 100644 --- a/src/include/gnunet_reclaim_attribute_plugin.h +++ b/src/include/gnunet_reclaim_attribute_plugin.h @@ -134,6 +134,27 @@ struct GNUNET_RECLAIM_ATTRIBUTE_PluginFunctions * Number to typename. */ GNUNET_RECLAIM_ATTRIBUTE_NumberToTypenameFunction number_to_typename; + + /** +* Attestation Conversion to string. +*/ + GNUNET_RECLAIM_ATTRIBUTE_ValueToStringFunction value_to_string_attest; + + /** + * Attestation Conversion to binary. + */ + GNUNET_RECLAIM_ATTRIBUTE_StringToValueFunction string_to_value_attest; + + /** + * Attestation Typename to number. + */ + GNUNET_RECLAIM_ATTRIBUTE_TypenameToNumberFunction typename_to_number_attest; + + /** + * Attestation Number to typename. + */ + GNUNET_RECLAIM_ATTRIBUTE_NumberToTypenameFunction number_to_typename_attest; + }; diff --git a/src/reclaim-attribute/plugin_reclaim_attribute_gnuid.c b/src/reclaim-attribute/plugin_reclaim_attribute_gnuid.c index bb60909d9..37610e2fb 100644 --- a/src/reclaim-attribute/plugin_reclaim_attribute_gnuid.c +++ b/src/reclaim-attribute/plugin_reclaim_attribute_gnuid.c @@ -90,6 +90,63 @@ gnuid_string_to_value (void *cls, } } +/** + * Convert the 'value' of an attestation to a string. + * + * @param cls closure, unused + * @param type type of the attestation + * @param data value in binary encoding + * @param data_size number of bytes in @a data + * @return NULL on error, otherwise human-readable representation of the value + */ +static char * +gnuid_value_to_string_attest (void *cls, + uint32_t type, + const void *data, + size_t data_size) +{ + switch (type) + { + case GNUNET_RECLAIM_ATTESTATION_TYPE_JWT: + return GNUNET_strndup (data, data_size); + + default: + return NULL; + } +} + + +/** + * Convert human-readable version of a 'value' of an attestation to the binary + * representation. + * + * @param cls closure, unused + * @param type type of the attestation + * @param s human-readable string + * @param data set to value in binary encoding (will be allocated) + * @param data_size set to number of bytes in @a data + * @return #GNUNET_OK on success + */ +static int +gnuid_string_to_value_attest (void *cls, + uint32_t type, + const char *s, + void **data, + size_t *data_size) +{ + if (NULL == s) + return GNUNET_SYSERR; + switch (type) + { + case GNUNET_RECLAIM_ATTESTATION_TYPE_JWT: + *data = GNUNET_strdup (s); + *data_size = strlen (s); + return GNUNET_OK; + + default: + return GNUNET_SYSERR; + } +} /** * Mapping of attribute type numbers to human-readable @@ -102,6 +159,17 @@ static struct } gnuid_name_map[] = { { "STRING", GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING }, { NULL, UINT32_MAX } }; +/** + * Mapping of attribute type numbers to human-readable + * attribute type names. + */ +static struct +{ + const char *name; + uint32_t number; +} gnuid_attest_name_map[] = { { "STRING", + GNUNET_RECLAIM_ATTRIBUTE_TYPE_STRING }, + { NULL, UINT32_MAX } }; /** * Convert a type name to the corresponding number. @@ -141,6 +209,44 @@ gnuid_number_to_typename (void *cls, uint32_t type) return gnuid_name_map[i].name; } +/** + * Convert a type name to the corresponding number. + * + * @param cls closure, unused + * @param gnuid_typename name to convert + * @return corresponding number, UINT32_MAX on error + */ +static uint32_t +gnuid_typename_to_number_attest (void *cls, const char *gnuid_typename) +{ + unsigned int i; + + i = 0; + while ((NULL != gnuid_attest_name_map[i].name) && + (0 != strcasecmp (gnuid_typename, gnuid_attest_name_map[i].name))) + i++; + return gnuid_attest_name_map[i].number; +} + +/** + * Convert a type number (i.e. 1) to the corresponding type string + * + * @param cls closure, unused + * @param type number of a type to convert + * @return corresponding typestring, NULL on error + */ +static const char * +gnuid_number_to_typename (void *cls, uint32_t type) +{ + unsigned int i; + + i = 0; + while ((NULL != gnuid_attest_name_map[i].name) && (type != + gnuid_attest_name_map[i]. + number)) + i++; + return gnuid_attest_name_map[i].name; +} /** * Entry point for the plugin. @@ -158,6 +264,10 @@ libgnunet_plugin_reclaim_attribute_gnuid_init (void *cls) api->string_to_value = &gnuid_string_to_value; api->typename_to_number = &gnuid_typename_to_number; api->number_to_typename = &gnuid_number_to_typename; + api->value_to_string_attest = &gnuid_value_to_string_attest; + api->string_to_value_attest = &gnuid_string_to_value_attest; + api->typename_to_number_attest = &gnuid_typename_to_number_attest; + api->number_to_typename_attest = &gnuid_number_to_typename_attest; return api; } diff --git a/src/reclaim-attribute/reclaim_attribute.c b/src/reclaim-attribute/reclaim_attribute.c index b81394ad2..6dd1632fd 100644 --- a/src/reclaim-attribute/reclaim_attribute.c +++ b/src/reclaim-attribute/reclaim_attribute.c @@ -217,6 +217,117 @@ GNUNET_RECLAIM_ATTRIBUTE_value_to_string (uint32_t type, return NULL; } +/** + * Convert an attestation type name to the corresponding number + * + * @param typename name to convert + * @return corresponding number, UINT32_MAX on error + */ +uint32_t +GNUNET_RECLAIM_ATTESTATION_typename_to_number (const char *typename) +{ + unsigned int i; + struct Plugin *plugin; + uint32_t ret; + + init (); + for (i = 0; i < num_plugins; i++) + { + plugin = attr_plugins[i]; + if (UINT32_MAX != + (ret = plugin->api->typename_to_number_attest (plugin->api->cls, + typename))) + return ret; + } + return UINT32_MAX; +} + +/** + * Convert an attestation type number to the corresponding attestation type string + * + * @param type number of a type + * @return corresponding typestring, NULL on error + */ +const char * +GNUNET_RECLAIM_ATTESTATION_number_to_typename (uint32_t type) +{ + unsigned int i; + struct Plugin *plugin; + const char *ret; + + init (); + for (i = 0; i < num_plugins; i++) + { + plugin = attr_plugins[i]; + if (NULL != + (ret = plugin->api->number_to_typename_attest (plugin->api->cls, type))) + return ret; + } + return NULL; +} +/** + * Convert human-readable version of a 'claim' of an attestation to the binary + * representation + * + * @param type type of the claim + * @param s human-readable string + * @param data set to value in binary encoding (will be allocated) + * @param data_size set to number of bytes in @a data + * @return #GNUNET_OK on success + */ +int +GNUNET_RECLAIM_ATTESTATION_string_to_value (uint32_t type, + const char *s, + void **data, + size_t *data_size) +{ + unsigned int i; + struct Plugin *plugin; + + init (); + for (i = 0; i < num_plugins; i++) + { + plugin = attr_plugins[i]; + if (GNUNET_OK == plugin->api->string_to_value_attest (plugin->api->cls, + type, + s, + data, + data_size)) + return GNUNET_OK; + } + return GNUNET_SYSERR; +} + + +/** + * Convert the 'claim' of an attestation to a string + * + * @param type the type of attestation + * @param data claim in binary encoding + * @param data_size number of bytes in @a data + * @return NULL on error, otherwise human-readable representation of the claim + */ +char * +GNUNET_RECLAIM_ATTESTATION_value_to_string (uint32_t type, + const void *data, + size_t data_size) +{ + unsigned int i; + struct Plugin *plugin; + char *ret; + + init (); + for (i = 0; i < num_plugins; i++) + { + plugin = attr_plugins[i]; + if (NULL != (ret = plugin->api->value_to_string_attest (plugin->api->cls, + type, + data, + data_size))) + return ret; + } + return NULL; +} /** * Create a new attribute. @@ -254,6 +365,41 @@ GNUNET_RECLAIM_ATTRIBUTE_claim_new (const char *attr_name, return attr; } +/** + * Create a new attestation. + * + * @param attr_name the attestation name + * @param type the attestation type + * @param data the attestation value + * @param data_size the attestation value size + * @return the new attestation + */ +struct GNUNET_RECLAIM_ATTESTATION_Claim * +GNUNET_RECLAIM_ATTESTATION_claim_new (const char *attr_name, + uint32_t type, + const void *data, + size_t data_size) +{ + struct GNUNET_RECLAIM_ATTESTATION_Claim *attr; + char *write_ptr; + char *attr_name_tmp = GNUNET_strdup (attr_name); + + GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp); + + attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTESTATION_Claim) + + strlen (attr_name_tmp) + 1 + data_size); + attr->type = type; + attr->data_size = data_size; + attr->version = 0; + write_ptr = (char *) &attr[1]; + GNUNET_memcpy (write_ptr, attr_name_tmp, strlen (attr_name_tmp) + 1); + attr->name = write_ptr; + write_ptr += strlen (attr->name) + 1; + GNUNET_memcpy (write_ptr, data, data_size); + attr->data = write_ptr; + GNUNET_free (attr_name_tmp); + return attr; +} /** * Add a new attribute to a claim list @@ -521,4 +667,100 @@ GNUNET_RECLAIM_ATTRIBUTE_deserialize (const char *data, size_t data_size) } +/** + * Get required size for serialization buffer + * + * @param attr the attestation to serialize + * @return the required buffer size + */ +size_t +GNUNET_RECLAIM_ATTESTATION_serialize_get_size ( + const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr) +{ + return sizeof(struct Attestation) + strlen (attr->name) + attr->data_size; +} + +/** + * Serialize an attestation + * + * @param attr the attestation to serialize + * @param result the serialized attestation + * @return length of serialized data + */ +size_t +GNUNET_RECLAIM_ATTESTATION_serialize ( + const struct GNUNET_RECLAIM_ATTESTATION_Claim *attr, + char *result) +{ + size_t data_len_ser; + size_t name_len; + struct Attestation *attr_ser; + char *write_ptr; + + attr_ser = (struct Attestation *) result; + attr_ser->attestation_type = htons (attr->type); + attr_ser->attestation_type = htonl (attr->version); + attr_ser->attestation_type = GNUNET_htonll (attr->id); + 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 sizeof(struct Attestation) + strlen (attr->name) + attr->data_size; +} + +/** + * Deserialize an attestation + * + * @param data the serialized attestation + * @param data_size the length of the serialized data + * + * @return a GNUNET_IDENTITY_PROVIDER_Attribute, must be free'd by caller + */ +struct GNUNET_RECLAIM_ATTESTATION_Claim * +GNUNET_RECLAIM_ATTESTATION_deserialize (const char *data, size_t data_size) +{ + struct GNUNET_RECLAIM_ATTESTATION_Claim *attr; + struct Attestation *attr_ser; + size_t data_len; + size_t name_len; + char *write_ptr; + + if (data_size < sizeof(struct Attestation)) + return NULL; + + attr_ser = (struct Attestation *) data; + data_len = ntohs (attr_ser->data_size); + name_len = ntohs (attr_ser->name_len); + if (data_size < sizeof(struct Attestation) + data_len + name_len) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Buffer too small to deserialize\n"); + return NULL; + } + attr = GNUNET_malloc (sizeof(struct GNUNET_RECLAIM_ATTESTATION_Claim) + + data_len + name_len + 1); + attr->type = ntohs (attr_ser->attestation_type); + attr->version = ntohl (attr_ser->attestation_version); + attr->id = GNUNET_ntohll (attr_ser->attestation_id); + attr->data_size = data_len; + + 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 reclaim_attribute.c */ diff --git a/src/reclaim-attribute/reclaim_attribute.h b/src/reclaim-attribute/reclaim_attribute.h index d7358847e..750afc479 100644 --- a/src/reclaim-attribute/reclaim_attribute.h +++ b/src/reclaim-attribute/reclaim_attribute.h @@ -61,4 +61,37 @@ struct Attribute // followed by data_size Attribute value data }; +/** + * Serialized attestation claim + */ +struct Attestation +{ + /** + * Attestation type + */ + uint32_t attestation_type; + + /** + * Attestation version + */ + uint32_t attestation_version; + + /** + * Attestation ID + */ + uint64_t attestation_id; + + /** + * Name length + */ + uint32_t name_len; + + /** + * Data size + */ + uint32_t data_size; + + // followed by data_size Attestation value data +}; + #endif diff --git a/src/reclaim/json_reclaim.c b/src/reclaim/json_reclaim.c index e029fdfb6..a0016bac8 100644 --- a/src/reclaim/json_reclaim.c +++ b/src/reclaim/json_reclaim.c @@ -264,3 +264,113 @@ GNUNET_RECLAIM_JSON_spec_ticket (struct GNUNET_RECLAIM_Ticket **ticket) *ticket = NULL; return ret; } + +/** + * Parse given JSON object to an attestation claim + * + * @param cls closure, NULL + * @param root the json object representing data + * @param spec where to write the data + * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error + */ +static int +parse_attest (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec) +{ + struct GNUNET_RECLAIM_ATTESTATION_Claim *attr; + const char *name_str = NULL; + const char *val_str = NULL; + const char *type_str = NULL; + const char *id_str = NULL; + char *data; + int unpack_state; + uint32_t type; + size_t data_size; + + GNUNET_assert (NULL != root); + + if (! json_is_object (root)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Error json is not array nor object!\n"); + return GNUNET_SYSERR; + } + // interpret single attribute + unpack_state = json_unpack (root, + "{s:s, s?s, s:s, s:s!}", + "name", + &name_str, + "id", + &id_str, + "type", + &type_str, + "value", + &val_str); + if ((0 != unpack_state) || (NULL == name_str) || (NULL == val_str) || + (NULL == type_str)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Error json object has a wrong format!\n"); + return GNUNET_SYSERR; + } + type = GNUNET_RECLAIM_ATTESTATION_typename_to_number (type_str); + if (GNUNET_SYSERR == + (GNUNET_RECLAIM_ATTESTATION_string_to_value (type, + val_str, + (void **) &data, + &data_size))) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Attribute value invalid!\n"); + return GNUNET_SYSERR; + } + attr = GNUNET_RECLAIM_ATTESTATION_claim_new (name_str, type, data, data_size); + if ((NULL == id_str) || (0 == strlen (id_str))) + attr->id = 0; + else + GNUNET_STRINGS_string_to_data (id_str, + strlen (id_str), + &attr->id, + sizeof(uint64_t)); + + *(struct GNUNET_RECLAIM_ATTESTATION_Claim **) spec->ptr = attr; + return GNUNET_OK; +} + +/** + * Cleanup data left from parsing RSA public key. + * + * @param cls closure, NULL + * @param[out] spec where to free the data + */ +static void +clean_attest (void *cls, struct GNUNET_JSON_Specification *spec) +{ + struct GNUNET_RECLAIM_ATTESTATION_Claim **attr; + + attr = (struct GNUNET_RECLAIM_ATTESTATION_Claim **) spec->ptr; + if (NULL != *attr) + { + GNUNET_free (*attr); + *attr = NULL; + } +} +/** + * JSON Specification for Reclaim attestation claims. + * + * @param ticket struct of GNUNET_RECLAIM_ATTESTATION_Claim to fill + * @return JSON Specification + */ +struct GNUNET_JSON_Specification +GNUNET_RECLAIM_JSON_spec_claim_attest (struct + GNUNET_RECLAIM_ATTESTATION_Claim **attr) +{ + struct GNUNET_JSON_Specification ret = { .parser = &parse_attest, + .cleaner = &clean_attest, + .cls = NULL, + .field = NULL, + .ptr = attr, + .ptr_size = 0, + .size_ptr = NULL }; + + *attr = NULL; + return ret; +} diff --git a/src/reclaim/json_reclaim.h b/src/reclaim/json_reclaim.h index 3fd26167f..4280cce48 100644 --- a/src/reclaim/json_reclaim.h +++ b/src/reclaim/json_reclaim.h @@ -46,3 +46,13 @@ GNUNET_RECLAIM_JSON_spec_claim (struct GNUNET_RECLAIM_ATTRIBUTE_Claim **attr); */ struct GNUNET_JSON_Specification GNUNET_RECLAIM_JSON_spec_ticket (struct GNUNET_RECLAIM_Ticket **ticket); + +/** + * JSON Specification for Reclaim attestation claims. + * + * @param ticket struct of GNUNET_RECLAIM_ATTESTATION_Claim to fill + * @return JSON Specification + */ +struct GNUNET_JSON_Specification +GNUNET_RECLAIM_JSON_spec_claim_attest (struct + GNUNET_RECLAIM_ATTESTATION_Claim **attr); -- 2.25.1