diff options
-rw-r--r-- | src/identity-provider/gnunet-service-identity-provider.c | 190 | ||||
-rw-r--r-- | src/identity-provider/identity_token.c | 64 | ||||
-rw-r--r-- | src/identity-provider/identity_token.h | 62 | ||||
-rw-r--r-- | src/identity/plugin_gnsrecord_identity.c | 2 | ||||
-rw-r--r-- | src/namestore/plugin_rest_namestore.c | 3 |
5 files changed, 255 insertions, 66 deletions
diff --git a/src/identity-provider/gnunet-service-identity-provider.c b/src/identity-provider/gnunet-service-identity-provider.c index 10ecf95380..a8a8b7f161 100644 --- a/src/identity-provider/gnunet-service-identity-provider.c +++ b/src/identity-provider/gnunet-service-identity-provider.c @@ -255,6 +255,11 @@ struct IssueHandle * QueueEntry */ struct GNUNET_NAMESTORE_QueueEntry *ns_qe; + + /** + * The label the token is stored under + */ + char *label; }; /** @@ -327,7 +332,6 @@ handle_token_update (void *cls, char *token_metadata; char *write_ptr; char *enc_token_str; - char *val_str; const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; struct GNUNET_CRYPTO_EcdhePrivateKey *new_ecdhe_privkey; @@ -402,21 +406,15 @@ handle_token_update (void *cls, { if (0 == strcmp (attr->name, "exp")) { - GNUNET_asprintf (&val_str, "%ul", new_exp.abs_value_us); - token_add_attr (new_token, attr->name, val_str); - GNUNET_free (val_str); + token_add_attr_int (new_token, attr->name, new_exp.abs_value_us); } else if (0 == strcmp (attr->name, "nbf")) { - GNUNET_asprintf (&val_str, "%ul", new_nbf.abs_value_us); - token_add_attr (new_token, attr->name, val_str); - GNUNET_free (val_str); + token_add_attr_int (new_token, attr->name, new_nbf.abs_value_us); } else if (0 == strcmp (attr->name, "iat")) { - GNUNET_asprintf (&val_str, "%ul", new_iat.abs_value_us); - token_add_attr (new_token, attr->name, val_str); - GNUNET_free (val_str); + token_add_attr_int (new_token, attr->name, new_iat.abs_value_us); } else if ((0 == strcmp (attr->name, "iss")) || (0 == strcmp (attr->name, "aud"))) @@ -534,7 +532,6 @@ clear_ego_attrs (void *cls, return GNUNET_YES; } - /** * * Update all ID_TOKEN records for an identity and store them @@ -913,9 +910,11 @@ cleanup_issue_handle (struct IssueHandle *handle) if (NULL != handle->scopes) GNUNET_free (handle->scopes); if (NULL != handle->token) - token_destroy (handle->token); + token_destroy (handle->token); if (NULL != handle->ticket) ticket_destroy (handle->ticket); + if (NULL != handle->label) + GNUNET_free (handle->label); GNUNET_free (handle); } @@ -974,15 +973,12 @@ sign_and_return_token (void *cls, struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey; struct IssueHandle *handle = cls; struct GNUNET_GNSRECORD_Data token_record[2]; - char *lbl_str; char *nonce_str; char *enc_token_str; char *token_metadata; char* write_ptr; - char* attr_val; uint64_t time; uint64_t exp_time; - uint64_t rnd_key; size_t token_metadata_len; //Remote nonce @@ -990,29 +986,19 @@ sign_and_return_token (void *cls, GNUNET_asprintf (&nonce_str, "%d", handle->nonce); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request nonce: %s\n", nonce_str); - //Label - rnd_key = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, - UINT64_MAX); - GNUNET_STRINGS_base64_encode ((char*)&rnd_key, - sizeof (uint64_t), - &lbl_str); GNUNET_CRYPTO_ecdsa_key_get_public (&handle->iss_key, &pub_key); handle->ticket = ticket_create (nonce_str, &pub_key, - lbl_str, + handle->label, &handle->aud_key); time = GNUNET_TIME_absolute_get().abs_value_us; exp_time = time + token_expiration_interval.rel_value_us; - GNUNET_asprintf (&attr_val, "%ul", time); - token_add_attr (handle->token, "nbf", attr_val); - token_add_attr (handle->token, "iat", attr_val); - GNUNET_free (attr_val); - GNUNET_asprintf (&attr_val, "%ul", exp_time); - token_add_attr (handle->token, "exp", attr_val); - GNUNET_free (attr_val); + token_add_attr_int (handle->token, "nbf", time); + token_add_attr_int (handle->token, "iat", time); + token_add_attr_int (handle->token, "exp", exp_time); token_add_attr (handle->token, "nonce", nonce_str); //Token in a serialized encrypted format @@ -1049,13 +1035,12 @@ sign_and_return_token (void *cls, //Persist token handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, &handle->iss_key, - lbl_str, + handle->label, 2, token_record, &store_token_issue_cont, handle); GNUNET_free (ecdhe_privkey); - GNUNET_free (lbl_str); GNUNET_free (nonce_str); GNUNET_free (enc_token_str); GNUNET_free (token_metadata); @@ -1195,6 +1180,8 @@ process_lookup_result (void *cls, uint32_t rd_count, } + + /** * * Handler for exchange message @@ -1258,6 +1245,137 @@ handle_exchange_message (void *cls, } + +/** + * + * Look for existing token + * + * @param cls the identity entry + * @param zone the identity + * @param lbl the name of the record + * @param rd_count number of records + * @param rd record data + * + */ +static void +find_existing_token (void *cls, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, + const char *lbl, + unsigned int rd_count, + const struct GNUNET_GNSRECORD_Data *rd) +{ + struct IssueHandle *handle = cls; + const struct GNUNET_GNSRECORD_Data *token_metadata_record; + struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key; + struct GNUNET_HashCode key; + int scope_count_token; + uint64_t rnd_key; + char *scope; + char *tmp_scopes; + + if (NULL == lbl) + { + //Done + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + ">>> No existing token found\n"); + //Label + rnd_key = + GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, + UINT64_MAX); + GNUNET_STRINGS_base64_encode ((char*)&rnd_key, + sizeof (uint64_t), + &handle->label); + handle->ns_it = NULL; + handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle, + &handle->iss_key, + &attr_collect, + handle); + return; + } + + //There should be only a single record for a token under a label + if (2 != rd_count) + { + GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); + return; + } + + if (rd[0].record_type == GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA) + { + token_metadata_record = &rd[0]; + } else { + token_metadata_record = &rd[1]; + } + if (token_metadata_record->record_type != GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA) + { + GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); + return; + } + ecdhe_privkey = *((struct GNUNET_CRYPTO_EcdhePrivateKey *)token_metadata_record->data); + aud_key = + (struct GNUNET_CRYPTO_EcdsaPublicKey *)(token_metadata_record->data+sizeof(struct GNUNET_CRYPTO_EcdhePrivateKey)); + tmp_scopes = GNUNET_strdup ((char*) aud_key+sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); + + if (0 != memcmp (aud_key, &handle->aud_key, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) + { + char *tmp2 = GNUNET_STRINGS_data_to_string_alloc (aud_key, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); + //Audience does not match! + char *tmp = GNUNET_GNSRECORD_value_to_string (GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA, + token_metadata_record->data, + token_metadata_record->data_size); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Token does not match audience %s vs %s. Moving on\n", + tmp2, + tmp); + GNUNET_free (tmp_scopes); + GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); + return; + } + + scope = strtok (tmp_scopes, ","); + scope_count_token = 0; + while (NULL != scope) + { + GNUNET_CRYPTO_hash (scope, + strlen (scope), + &key); + + if ((NULL != handle->attr_map) && + (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->attr_map, &key))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Issued token does not include `%s'. Moving on\n", scope); + GNUNET_free (tmp_scopes); + GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); + return; + } + scope_count_token++; + scope = strtok (NULL, ","); + } + GNUNET_free (tmp_scopes); + //All scopes in token are also in request. Now + //Check length + if (GNUNET_CONTAINER_multihashmap_size (handle->attr_map) == scope_count_token) + { + //We have an existing token + handle->label = GNUNET_strdup (lbl); + handle->ns_it = NULL; + handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle, + &handle->iss_key, + &attr_collect, + handle); + + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Nuber of attributes in token do not match request\n"); + //No luck + GNUNET_NAMESTORE_zone_iterator_next (handle->ns_it); +} + + /** * * Handler for issue message @@ -1311,21 +1429,21 @@ handle_issue_message (void *cls, issue_handle->aud_key = im->aud_key; issue_handle->iss_key = im->iss_key; + GNUNET_CRYPTO_ecdsa_key_get_public (&im->iss_key, + &issue_handle->iss_pkey); issue_handle->expiration = GNUNET_TIME_absolute_ntoh (im->expiration); - issue_handle->nonce = im->nonce; + issue_handle->nonce = ntohl (im->nonce); GNUNET_SERVER_receive_done (client, GNUNET_OK); GNUNET_SERVER_notification_context_add (nc, client); GNUNET_SERVER_client_set_user_context (client, issue_handle); issue_handle->client = client; issue_handle->scopes = GNUNET_strdup (scopes); - GNUNET_CRYPTO_ecdsa_key_get_public (&im->iss_key, - &issue_handle->iss_pkey); issue_handle->token = token_create (&issue_handle->iss_pkey, - &im->aud_key); + &issue_handle->aud_key); issue_handle->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle, &im->iss_key, - &attr_collect, + &find_existing_token, issue_handle); } diff --git a/src/identity-provider/identity_token.c b/src/identity-provider/identity_token.c index caf1a78481..1974df6a57 100644 --- a/src/identity-provider/identity_token.c +++ b/src/identity-provider/identity_token.c @@ -238,7 +238,8 @@ token_destroy (struct IdentityToken *token) GNUNET_CONTAINER_DLL_remove (attr->val_head, attr->val_tail, val); - GNUNET_free (val->value); + if (NULL != val->value) + GNUNET_free (val->value); GNUNET_free (val); val = tmp_val; } @@ -282,6 +283,37 @@ token_add_attr (struct IdentityToken *token, new_val); } +void +token_add_attr_int (struct IdentityToken *token, + const char* key, + uint64_t value) +{ + struct TokenAttr *attr; + struct TokenAttrValue *new_val; + GNUNET_assert (NULL != token); + + new_val = GNUNET_malloc (sizeof (struct TokenAttrValue)); + new_val->int_value = value; + for (attr = token->attr_head; NULL != attr; attr = attr->next) + { + if (0 == strcmp (key, attr->name)) + break; + } + + if (NULL == attr) + { + attr = GNUNET_malloc (sizeof (struct TokenAttr)); + attr->name = GNUNET_strdup (key); + GNUNET_CONTAINER_DLL_insert (token->attr_head, + token->attr_tail, + attr); + } + + GNUNET_CONTAINER_DLL_insert (attr->val_head, + attr->val_tail, + new_val); +} + static void parse_json_payload(const char* payload_base64, struct IdentityToken *token) @@ -306,15 +338,24 @@ parse_json_payload(const char* payload_base64, { json_array_foreach (value, idx, arr_value) { - token_add_attr (token, - key, - json_string_value (arr_value)); + if (json_is_integer (arr_value)) + token_add_attr_int (token, key, + json_integer_value (arr_value)); + else + token_add_attr (token, + key, + json_string_value (arr_value)); } } else { - token_add_attr (token, key, json_string_value (value)); + if (json_is_integer (value)) + token_add_attr_int (token, key, + json_integer_value (value)); + else + token_add_attr (token, key, json_string_value (value)); } } + json_decref (payload_json); GNUNET_free (payload); } @@ -423,9 +464,16 @@ create_json_payload (const struct IdentityToken *token) { for (val = attr->val_head; NULL != val; val = val->next) { - json_object_set_new (root, - attr->name, - json_string (val->value)); + if (NULL != val->value) + { + json_object_set_new (root, + attr->name, + json_string (val->value)); + } else { + json_object_set_new (root, + attr->name, + json_integer (val->int_value)); + } } } json_str = json_dumps (root, JSON_INDENT(1)); diff --git a/src/identity-provider/identity_token.h b/src/identity-provider/identity_token.h index 3eeaf9ae2f..5d5634111f 100644 --- a/src/identity-provider/identity_token.h +++ b/src/identity-provider/identity_token.h @@ -97,6 +97,12 @@ struct TokenAttrValue * Attribute value */ char *value; + + /** + * Attribute int value + * used if NULL == value + */ + uint64_t int_value; }; struct TokenTicketPayload @@ -176,6 +182,20 @@ token_add_attr (struct IdentityToken *token, const char* value); /** + * Add a new key value pair to the token + * + * @param token the token to modify + * @param key the key + * @param value the value + */ +void +token_add_attr_int (struct IdentityToken *token, + const char* key, + uint64_t value); + + + +/** * Add a value to a TokenAttribute * * @param attr the token attribute @@ -193,10 +213,10 @@ token_add_attr (struct IdentityToken *token, * @param value the value * */ -void -token_add_json (const struct IdentityToken *token, - const char* key, - json_t* value); + void + token_add_json (const struct IdentityToken *token, + const char* key, + json_t* value); /** * Serialize a token. The token will be signed and base64 according to the @@ -214,11 +234,11 @@ token_add_json (const struct IdentityToken *token, * * @return GNUNET_OK on success */ -int -token_serialize (const struct IdentityToken*token, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key, - struct GNUNET_CRYPTO_EcdhePrivateKey **ecdhe_privkey, - char **result); + int + token_serialize (const struct IdentityToken*token, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key, + struct GNUNET_CRYPTO_EcdhePrivateKey **ecdhe_privkey, + char **result); /** * Parses the serialized token and returns a token @@ -229,10 +249,10 @@ token_serialize (const struct IdentityToken*token, * * @return GNUNET_OK on success */ - int - token_parse (const char* data, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key, - struct IdentityToken **result); + int + token_parse (const char* data, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key, + struct IdentityToken **result); /** * Parses the serialized token and returns a token @@ -263,10 +283,10 @@ token_parse2 (const char* data, * * @return GNUNET_OK on success */ -int -token_to_string (const struct IdentityToken *token, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key, - char **result); + int + token_to_string (const struct IdentityToken *token, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key, + char **result); /** * @@ -296,10 +316,10 @@ ticket_create (const char* nonce_str, * * @return GNUNET_OK on success */ -int -ticket_serialize (struct TokenTicket *ticket, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key, - char **result); + int + ticket_serialize (struct TokenTicket *ticket, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key, + char **result); /** * Destroys a ticket diff --git a/src/identity/plugin_gnsrecord_identity.c b/src/identity/plugin_gnsrecord_identity.c index fd689490a0..d2f87d235a 100644 --- a/src/identity/plugin_gnsrecord_identity.c +++ b/src/identity/plugin_gnsrecord_identity.c @@ -67,6 +67,8 @@ value_to_string (void *cls, GNUNET_asprintf (&result, "%s;%s;%s", ecdhe_str, aud_str, scopes); + GNUNET_free (aud_str); + GNUNET_free (ecdhe_str); return result; default: diff --git a/src/namestore/plugin_rest_namestore.c b/src/namestore/plugin_rest_namestore.c index 42a9f63560..dfad24d3cf 100644 --- a/src/namestore/plugin_rest_namestore.c +++ b/src/namestore/plugin_rest_namestore.c @@ -561,7 +561,7 @@ del_cont (void *cls, const struct GNUNET_GNSRECORD_Data *rd) { struct RequestHandle *handle = cls; - + handle->add_qe = NULL; if (0 == rd_count) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -828,6 +828,7 @@ namestore_zkey_response (void *cls, } resp = GNUNET_REST_create_json_response (result); handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); + GNUNET_REST_jsonapi_object_delete (json_obj); GNUNET_free (result); GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); return; |