X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Freclaim%2Fplugin_rest_openid_connect.c;h=09b3c8248a2de75894e3c494f51a292a09069f30;hb=0ecd5d693d2a7fa3e2897c77ed1f5f9566c9bebd;hp=2dde8995095e52d495ef1d79e2f683ec57526164;hpb=483bc7e3095dff908fe8c032ea96995d44304868;p=oweals%2Fgnunet.git diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c index 2dde89950..09b3c8248 100644 --- a/src/reclaim/plugin_rest_openid_connect.c +++ b/src/reclaim/plugin_rest_openid_connect.c @@ -32,7 +32,7 @@ #include "gnunet_gnsrecord_lib.h" #include "gnunet_identity_service.h" #include "gnunet_namestore_service.h" -#include "gnunet_reclaim_attribute_lib.h" +#include "gnunet_reclaim_lib.h" #include "gnunet_reclaim_service.h" #include "gnunet_rest_lib.h" #include "gnunet_rest_plugin.h" @@ -119,6 +119,11 @@ */ #define OIDC_NONCE_KEY "nonce" +/** + * OIDC claims key + */ +#define OIDC_CLAIMS_KEY "claims" + /** * OIDC PKCE code challenge */ @@ -290,6 +295,11 @@ struct OIDC_Variables */ char *nonce; + /** + * The OIDC claims + */ + char *claims; + /** * The OIDC response type */ @@ -418,7 +428,13 @@ struct RequestHandle /** * Attribute claim list */ - struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attr_list; + struct GNUNET_RECLAIM_AttributeList *attr_list; + + /** + * Attestation list + */ + struct GNUNET_RECLAIM_AttestationList *attests_list; + /** * IDENTITY Operation @@ -440,6 +456,12 @@ struct RequestHandle */ struct GNUNET_RECLAIM_AttributeIterator *attr_it; + /** + * Attestation iterator + */ + struct GNUNET_RECLAIM_AttestationIterator *attest_it; + + /** * Ticket iterator */ @@ -513,10 +535,7 @@ struct RequestHandle static void cleanup_handle (struct RequestHandle *handle) { - struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *claim_entry; - struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *claim_tmp; struct EgoEntry *ego_entry; - struct EgoEntry *ego_tmp; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); if (NULL != handle->timeout_task) @@ -525,8 +544,12 @@ cleanup_handle (struct RequestHandle *handle) GNUNET_IDENTITY_disconnect (handle->identity_handle); if (NULL != handle->attr_it) GNUNET_RECLAIM_get_attributes_stop (handle->attr_it); + if (NULL != handle->attest_it) + GNUNET_RECLAIM_get_attestations_stop (handle->attest_it); if (NULL != handle->ticket_it) GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it); + if (NULL != handle->idp_op) + GNUNET_RECLAIM_cancel (handle->idp_op); if (NULL != handle->idp) GNUNET_RECLAIM_disconnect (handle->idp); GNUNET_free_non_null (handle->url); @@ -554,24 +577,19 @@ cleanup_handle (struct RequestHandle *handle) json_decref (handle->oidc->response); GNUNET_free (handle->oidc); } - if (NULL != handle->attr_list) - { - for (claim_entry = handle->attr_list->list_head; NULL != claim_entry;) - { - claim_tmp = claim_entry; - claim_entry = claim_entry->next; - GNUNET_free (claim_tmp->claim); - GNUNET_free (claim_tmp); - } - GNUNET_free (handle->attr_list); - } - for (ego_entry = handle->ego_head; NULL != ego_entry;) + if (NULL!=handle->attr_list) + GNUNET_RECLAIM_attribute_list_destroy (handle->attr_list); + if (NULL!=handle->attests_list) + GNUNET_RECLAIM_attestation_list_destroy (handle->attests_list); + + while (NULL != (ego_entry = handle->ego_head)) { - ego_tmp = ego_entry; - ego_entry = ego_entry->next; - GNUNET_free (ego_tmp->identifier); - GNUNET_free (ego_tmp->keystring); - GNUNET_free (ego_tmp); + GNUNET_CONTAINER_DLL_remove (handle->ego_head, + handle->ego_tail, + ego_entry); + GNUNET_free_non_null (ego_entry->identifier); + GNUNET_free_non_null (ego_entry->keystring); + GNUNET_free (ego_entry); } GNUNET_free (handle); } @@ -697,7 +715,7 @@ return_userinfo_response (void *cls) struct MHD_Response *resp; result_str = json_dumps (handle->oidc->response, 0); - + GNUNET_log (GNUNET_ERROR_TYPE_ERROR,"ID-Token: %s\n",result_str); resp = GNUNET_REST_create_response (result_str); handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); GNUNET_free (result_str); @@ -838,7 +856,7 @@ login_redirect (void *cls) &login_base_url)) { GNUNET_asprintf (&new_redirect, - "%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s", + "%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s", login_base_url, OIDC_RESPONSE_TYPE_KEY, handle->oidc->response_type, @@ -854,7 +872,10 @@ login_redirect (void *cls) (NULL != handle->oidc->code_challenge) ? handle->oidc->code_challenge : "", OIDC_NONCE_KEY, - (NULL != handle->oidc->nonce) ? handle->oidc->nonce : ""); + (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "", + OIDC_CLAIMS_KEY, + (NULL != handle->oidc->claims) ? handle->oidc->claims : + ""); resp = GNUNET_REST_create_response (""); MHD_add_response_header (resp, "Location", new_redirect); GNUNET_free (login_base_url); @@ -912,10 +933,10 @@ oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket) ticket_str = GNUNET_STRINGS_data_to_string_alloc (&handle->ticket, sizeof(struct GNUNET_RECLAIM_Ticket)); - // TODO change if more attributes are needed (see max_age) code_string = OIDC_build_authz_code (&handle->priv_key, &handle->ticket, handle->attr_list, + handle->attests_list, handle->oidc->nonce, handle->oidc->code_challenge); if ((NULL != handle->redirect_prefix) && (NULL != handle->redirect_suffix) && @@ -950,7 +971,53 @@ oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket) static void -oidc_collect_finished_cb (void *cls) +oidc_attest_collect_finished_cb (void *cls) +{ + struct RequestHandle *handle = cls; + + handle->attest_it = NULL; + handle->idp_op = GNUNET_RECLAIM_ticket_issue (handle->idp, + &handle->priv_key, + &handle->oidc->client_pkey, + handle->attr_list, + &oidc_ticket_issue_cb, + handle); +} + + +/** + * Collects all attributes for an ego if in scope parameter + */ +static void +oidc_attest_collect (void *cls, + const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, + const struct GNUNET_RECLAIM_Attestation *attest) +{ + struct RequestHandle *handle = cls; + struct GNUNET_RECLAIM_AttributeListEntry *le; + + for (le = handle->attr_list->list_head; NULL != le; le = le->next) + { + if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&le->attribute->attestation, + &attest->id)) + { + struct GNUNET_RECLAIM_AttestationListEntry *ale; + ale = GNUNET_new (struct GNUNET_RECLAIM_AttestationListEntry); + ale->attestation = GNUNET_RECLAIM_attestation_new (attest->name, + attest->type, + attest->data, + attest->data_size); + GNUNET_CONTAINER_DLL_insert (handle->attests_list->list_head, + handle->attests_list->list_tail, + ale); + } + } + GNUNET_RECLAIM_get_attestations_next (handle->attest_it); +} + + +static void +oidc_attr_collect_finished_cb (void *cls) { struct RequestHandle *handle = cls; @@ -963,6 +1030,17 @@ oidc_collect_finished_cb (void *cls) GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); return; } + handle->attests_list = GNUNET_new (struct GNUNET_RECLAIM_AttestationList); + handle->attest_it = + GNUNET_RECLAIM_get_attestations_start (handle->idp, + &handle->priv_key, + &oidc_iteration_error, + handle, + &oidc_attest_collect, + handle, + &oidc_attest_collect_finished_cb, + handle); + handle->idp_op = GNUNET_RECLAIM_ticket_issue (handle->idp, &handle->priv_key, &handle->oidc->client_pkey, @@ -978,21 +1056,14 @@ oidc_collect_finished_cb (void *cls) static void oidc_attr_collect (void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, - const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr, - const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest) + const struct GNUNET_RECLAIM_Attribute *attr) { struct RequestHandle *handle = cls; - struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le; + struct GNUNET_RECLAIM_AttributeListEntry *le; char *scope_variables; char *scope_variable; char delimiter[] = " "; - if ((NULL == attr->name) || (NULL == attr->data)) - { - GNUNET_RECLAIM_get_attributes_next (handle->attr_it); - return; - } - scope_variables = GNUNET_strdup (handle->oidc->scope); scope_variable = strtok (scope_variables, delimiter); while (NULL != scope_variable) @@ -1005,17 +1076,19 @@ oidc_attr_collect (void *cls, { GNUNET_RECLAIM_get_attributes_next (handle->attr_it); GNUNET_free (scope_variables); + // We can ignore this return; } GNUNET_free (scope_variables); - - le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry); - le->claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr->name, - attr->type, - attr->data, - attr->data_size); - le->claim->id = attr->id; - le->claim->version = attr->version; + le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry); + le->attribute = GNUNET_RECLAIM_attribute_new (attr->name, + &attr->attestation, + attr->type, + attr->data, + attr->data_size); + le->attribute->id = attr->id; + le->attribute->flag = attr->flag; + le->attribute->attestation = attr->attestation; GNUNET_CONTAINER_DLL_insert (handle->attr_list->list_head, handle->attr_list->list_tail, le); @@ -1077,7 +1150,7 @@ code_redirect (void *cls) *GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego); handle->idp = GNUNET_RECLAIM_connect (cfg); handle->attr_list = - GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList); + GNUNET_new (struct GNUNET_RECLAIM_AttributeList); handle->attr_it = GNUNET_RECLAIM_get_attributes_start (handle->idp, &handle->priv_key, @@ -1085,7 +1158,7 @@ code_redirect (void *cls) handle, &oidc_attr_collect, handle, - &oidc_collect_finished_cb, + &oidc_attr_collect_finished_cb, handle); return; } @@ -1305,6 +1378,9 @@ build_authz_response (void *cls) // OPTIONAL value: nonce handle->oidc->nonce = get_url_parameter_copy (handle, OIDC_NONCE_KEY); + // OPTIONAL value: claims + handle->oidc->claims = get_url_parameter_copy (handle, OIDC_CLAIMS_KEY); + // TODO check other values if needed number_of_ignored_parameter = sizeof(OIDC_ignored_parameter_array) / sizeof(char *); @@ -1455,6 +1531,8 @@ authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle, handle->ego_entry = handle->ego_tail; } } + handle->oidc->scope = get_url_parameter_copy (handle, OIDC_SCOPE_KEY); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Scope: %s\n", handle->oidc->scope); if (NULL == handle->tld) GNUNET_CONFIGURATION_iterate_section_values (cfg, "gns", tld_iter, handle); if (NULL == handle->tld) @@ -1706,7 +1784,8 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, struct RequestHandle *handle = cls; const struct EgoEntry *ego_entry; struct GNUNET_TIME_Relative expiration_time; - struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *cl; + struct GNUNET_RECLAIM_AttributeList *cl = NULL; + struct GNUNET_RECLAIM_AttestationList *al = NULL; struct GNUNET_RECLAIM_Ticket ticket; struct GNUNET_CRYPTO_EcdsaPublicKey cid; const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey; @@ -1794,7 +1873,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, // decode code if (GNUNET_OK != OIDC_parse_authz_code (privkey, code, code_verifier, &ticket, - &cl, &nonce)) + &cl, &al, &nonce)) { handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST); handle->edesc = GNUNET_strdup ("invalid code"); @@ -1834,6 +1913,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, id_token = OIDC_id_token_new (&ticket.audience, &ticket.identity, cl, + al, &expiration_time, (NULL != nonce) ? nonce : NULL, jwt_secret); @@ -1849,7 +1929,8 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, MHD_add_response_header (resp, "Pragma", "no-cache"); MHD_add_response_header (resp, "Content-Type", "application/json"); handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); - GNUNET_RECLAIM_ATTRIBUTE_list_destroy (cl); + GNUNET_RECLAIM_attribute_list_destroy (cl); + GNUNET_RECLAIM_attestation_list_destroy (al); GNUNET_free (access_token); GNUNET_free (json_response); GNUNET_free (id_token); @@ -1863,24 +1944,87 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, static void consume_ticket (void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, - const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr, - const struct GNUNET_RECLAIM_ATTESTATION_Claim *attest) + const struct GNUNET_RECLAIM_Attribute *attr, + const struct GNUNET_RECLAIM_Attestation *attest) { struct RequestHandle *handle = cls; - char *tmp_value; - json_t *value; + handle->idp_op = NULL; if (NULL == identity) { GNUNET_SCHEDULER_add_now (&return_userinfo_response, handle); return; } - tmp_value = GNUNET_RECLAIM_ATTRIBUTE_value_to_string (attr->type, - attr->data, - attr->data_size); - value = json_string (tmp_value); - json_object_set_new (handle->oidc->response, attr->name, value); - GNUNET_free (tmp_value); + if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attr->attestation)) + { + char *tmp_value; + json_t *value; + tmp_value = GNUNET_RECLAIM_attribute_value_to_string (attr->type, + attr->data, + attr->data_size); + value = json_string (tmp_value); + json_object_set_new (handle->oidc->response, attr->name, value); + GNUNET_free (tmp_value); + return; + } + json_t *claim_sources; + json_t *claim_sources_jwt; + json_t *claim_names; + char *attest_val_str; + claim_sources = json_object_get (handle->oidc->response,"_claim_sources"); + claim_names = json_object_get (handle->oidc->response,"_claim_names"); + attest_val_str = + GNUNET_RECLAIM_attestation_value_to_string (attest->type, + attest->data, + attest->data_size); + if ((NULL == claim_sources) && (NULL == claim_names) ) + { + claim_sources = json_object (); + claim_names = json_object (); + } + char *source_name; + int i = 0; + GNUNET_asprintf (&source_name, "src%d", i); + while (NULL != (claim_sources_jwt = json_object_get (claim_sources, + source_name))) + { + if (0 == strcmp (json_string_value (json_object_get (claim_sources_jwt, + "JWT")), + attest_val_str)) + { + // Adapt only the claim names + json_object_set_new (claim_names, attr->data, + json_string (source_name)); + json_object_set (handle->oidc->response, + "_claim_names", claim_names); + break; + } + i++; + GNUNET_free (source_name); + GNUNET_asprintf (&source_name, "src%d", i); + } + + // Create new one + if (NULL == claim_sources_jwt) + { + claim_sources_jwt = json_object (); + // Set the JWT for names + json_object_set_new (claim_names, attr->data, + json_string (source_name)); + // Set the JWT for the inner source + json_object_set_new (claim_sources_jwt, "JWT", + json_string (attest_val_str)); + // Set the JWT for the source + json_object_set_new (claim_sources, source_name, claim_sources_jwt); + // Set as claims + json_object_set (handle->oidc->response, "_claim_names", claim_names); + json_object_set (handle->oidc->response, "_claim_sources",claim_sources); + } + + json_decref (claim_sources); + json_decref (claim_names); + json_decref (claim_sources_jwt); + GNUNET_free (attest_val_str); } @@ -2117,13 +2261,16 @@ list_ego (void *cls, for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next) { - if (ego_entry->ego == ego) - break; - } - if (NULL != ego_entry) + if (ego_entry->ego != ego) + continue; GNUNET_CONTAINER_DLL_remove (handle->ego_head, handle->ego_tail, ego_entry); + GNUNET_free (ego_entry->identifier); + GNUNET_free (ego_entry->keystring); + GNUNET_free (ego_entry); + return; + } } } @@ -2137,7 +2284,8 @@ rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle, handle->oidc = GNUNET_new (struct OIDC_Variables); if (NULL == OIDC_cookie_jar_map) - OIDC_cookie_jar_map = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO); + OIDC_cookie_jar_map = GNUNET_CONTAINER_multihashmap_create (10, + GNUNET_NO); if (NULL == OIDC_access_token_map) OIDC_access_token_map = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO); @@ -2162,11 +2310,11 @@ rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle, /** - * Entry point for the plugin. - * - * @param cls Config info - * @return NULL on error, otherwise the plugin context - */ + * Entry point for the plugin. + * + * @param cls Config info + * @return NULL on error, otherwise the plugin context + */ void * libgnunet_plugin_rest_openid_connect_init (void *cls) { @@ -2175,7 +2323,7 @@ libgnunet_plugin_rest_openid_connect_init (void *cls) cfg = cls; if (NULL != plugin.cfg) - return NULL; /* can only initialize once! */ + return NULL; /* can only initialize once! */ memset (&plugin, 0, sizeof(struct Plugin)); plugin.cfg = cfg; api = GNUNET_new (struct GNUNET_REST_Plugin); @@ -2197,11 +2345,11 @@ libgnunet_plugin_rest_openid_connect_init (void *cls) /** - * Exit point from the plugin. - * - * @param cls the plugin context (as returned by "init") - * @return always NULL - */ + * Exit point from the plugin. + * + * @param cls the plugin context (as returned by "init") + * @return always NULL + */ void * libgnunet_plugin_rest_openid_connect_done (void *cls) { @@ -2215,7 +2363,8 @@ libgnunet_plugin_rest_openid_connect_done (void *cls) hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_cookie_jar_map); while (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value)) + GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, + value)) GNUNET_free_non_null (value); GNUNET_CONTAINER_multihashmap_iterator_destroy (hashmap_it); GNUNET_CONTAINER_multihashmap_destroy (OIDC_cookie_jar_map); @@ -2223,7 +2372,8 @@ libgnunet_plugin_rest_openid_connect_done (void *cls) hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_access_token_map); while (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value)) + GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, + value)) GNUNET_free_non_null (value); GNUNET_CONTAINER_multihashmap_destroy (OIDC_access_token_map); GNUNET_CONTAINER_multihashmap_iterator_destroy (hashmap_it);