along with this program. If not, see <http://www.gnu.org/licenses/>.
SPDX-License-Identifier: AGPL3.0-or-later
- */
+ */
/**
* @author Martin Schanzenbach
* @author Philippe Buschmann
#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"
*/
#define OIDC_NONCE_KEY "nonce"
+/**
+ * OIDC claims key
+ */
+#define OIDC_CLAIMS_KEY "claims"
+
+/**
+ * OIDC PKCE code challenge
+ */
+#define OIDC_CODE_CHALLENGE_KEY "code_challenge"
+
+/**
+ * OIDC PKCE code verifier
+ */
+#define OIDC_CODE_VERIFIER_KEY "code_verifier"
+
/**
* OIDC cookie expiration (in seconds)
*/
/**
* OIDC ignored parameter array
*/
-static char *OIDC_ignored_parameter_array[] = {"display",
- "prompt",
- "ui_locales",
- "response_mode",
- "id_token_hint",
- "login_hint",
- "acr_values"};
+static char *OIDC_ignored_parameter_array[] = { "display",
+ "prompt",
+ "ui_locales",
+ "response_mode",
+ "id_token_hint",
+ "login_hint",
+ "acr_values" };
/**
* OIDC Hash map that keeps track of issued cookies
*/
char *nonce;
+ /**
+ * The OIDC claims
+ */
+ char *claims;
+
/**
* The OIDC response type
*/
*/
int user_cancelled;
+ /**
+ * The PKCE code_challenge
+ */
+ char *code_challenge;
+
+ /**
+ * The PKCE code_verifier
+ */
+ char *code_verifier;
+
/**
* The response JSON
*/
/**
* 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
*/
struct GNUNET_RECLAIM_AttributeIterator *attr_it;
+ /**
+ * Attestation iterator
+ */
+ struct GNUNET_RECLAIM_AttestationIterator *attest_it;
+
+
/**
* Ticket iterator
*/
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)
GNUNET_SCHEDULER_cancel (handle->timeout_task);
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)
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);
- }
+ GNUNET_RECLAIM_attribute_list_destroy (handle->attr_list);
+ GNUNET_RECLAIM_attestation_list_destroy (handle->attests_list);
+
for (ego_entry = handle->ego_head; NULL != ego_entry;)
{
ego_tmp = ego_entry;
GNUNET_free (ego_tmp->keystring);
GNUNET_free (ego_tmp);
}
- GNUNET_free_non_null (handle->attr_it);
GNUNET_free (handle);
}
+
static void
cleanup_handle_delayed (void *cls)
{
struct RequestHandle *handle = cls;
struct MHD_Response *resp;
char *redirect;
+
GNUNET_asprintf (&redirect,
"%s?error=%s&error_description=%s%s%s",
handle->oidc->redirect_uri,
GNUNET_free (redirect);
}
+
/**
* Task run on timeout, sends error message. Cleans up everything.
*
do_error (handle);
}
+
/**
* Return attributes for claim
*
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);
GNUNET_CONTAINER_multihashmap_contains (OIDC_cookie_jar_map, &cache_key))
{
GNUNET_log (
- GNUNET_ERROR_TYPE_WARNING,
- "Found cookie `%s', but no corresponding expiration entry present...\n",
- token);
+ GNUNET_ERROR_TYPE_WARNING,
+ "Found cookie `%s', but no corresponding expiration entry present...\n",
+ token);
GNUNET_free (cookies);
return;
}
value = strtok (token, OIDC_COOKIE_HEADER_INFORMATION_KEY);
GNUNET_assert (NULL != value);
handle->oidc->login_identity = GNUNET_strdup (value);
+ GNUNET_free (cookies);
}
+
/**
* Redirects to login page stored in configuration file
*/
&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",
login_base_url,
OIDC_RESPONSE_TYPE_KEY,
handle->oidc->response_type,
handle->oidc->scope,
OIDC_STATE_KEY,
(NULL != handle->oidc->state) ? handle->oidc->state : "",
+ OIDC_CODE_CHALLENGE_KEY,
+ (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);
GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
}
+
/**
* Does internal server error when iteration failed.
*/
oidc_iteration_error (void *cls)
{
struct RequestHandle *handle = cls;
+
handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR);
handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
GNUNET_SCHEDULER_add_now (&do_error, handle);
char *code_string;
handle->idp_op = NULL;
- handle->ticket = *ticket;
if (NULL == ticket)
{
handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR);
GNUNET_SCHEDULER_add_now (&do_redirect_error, handle);
return;
}
+ handle->ticket = *ticket;
ticket_str =
GNUNET_STRINGS_data_to_string_alloc (&handle->ticket,
- sizeof (struct GNUNET_RECLAIM_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->oidc->nonce);
+ handle->attests_list,
+ handle->oidc->nonce,
+ handle->oidc->code_challenge);
if ((NULL != handle->redirect_prefix) && (NULL != handle->redirect_suffix) &&
(NULL != handle->tld))
{
-
GNUNET_asprintf (&redirect_uri,
"%s.%s/%s?%s=%s&state=%s",
handle->redirect_prefix,
GNUNET_free (code_string);
}
+
+static void
+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_collect_finished_cb (void *cls)
+oidc_attr_collect_finished_cb (void *cls)
{
struct RequestHandle *handle = cls;
+
handle->attr_it = NULL;
handle->ticket_it = NULL;
if (NULL == handle->attr_list->list_head)
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,
static void
oidc_attr_collect (void *cls,
const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
- const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
+ 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)
{
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);
GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->oidc
->login_identity,
strlen (
- handle->oidc
- ->login_identity),
+ handle->oidc
+ ->login_identity),
&pubkey))
{
handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_COOKIE);
*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,
handle,
&oidc_attr_collect,
handle,
- &oidc_collect_finished_cb,
+ &oidc_attr_collect_finished_cb,
handle);
return;
}
if (NULL == strstr (tmp, handle->oidc->client_id))
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Redirect uri %s does not contain client_id %s",
+ "Redirect uri %s does not contain client_id %s\n",
tmp,
handle->oidc->client_id);
}
else
{
-
pos = strrchr (tmp, (unsigned char) '.');
+ if (NULL == pos)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Redirect uri %s contains client_id but is malformed\n",
+ tmp);
+ GNUNET_free (tmp);
+ continue;
+ }
*pos = '\0';
handle->redirect_prefix = GNUNET_strdup (tmp);
tmp_key_str = pos + 1;
pos = strchr (tmp_key_str, (unsigned char) '/');
+ if (NULL == pos)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Redirect uri %s contains client_id but is malformed\n",
+ tmp);
+ GNUNET_free (tmp);
+ continue;
+ }
*pos = '\0';
handle->redirect_suffix = GNUNET_strdup (pos + 1);
GNUNET_STRINGS_string_to_data (tmp_key_str,
strlen (tmp_key_str),
&redirect_zone,
- sizeof (redirect_zone));
+ sizeof(redirect_zone));
}
GNUNET_SCHEDULER_add_now (&build_redirect, handle);
GNUNET_free (tmp);
handle);
}
+
static char *
get_url_parameter_copy (const struct RequestHandle *handle, const char *key)
{
struct GNUNET_HashCode hc;
char *value;
+
GNUNET_CRYPTO_hash (key, strlen (key), &hc);
if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle
->url_param_map,
// 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 *);
+ sizeof(OIDC_ignored_parameter_array) / sizeof(char *);
for (iterator = 0; iterator < number_of_ignored_parameter; iterator++)
{
GNUNET_CRYPTO_hash (OIDC_ignored_parameter_array[iterator],
GNUNET_SCHEDULER_add_now (&client_redirect, handle);
}
+
/**
* Iterate over tlds in config
*/
handle->tld = GNUNET_strdup (option + 1);
}
+
/**
* Responds to authorization GET and url-encoded POST request
*
return;
}
+ // OPTIONAL value: code_challenge
+ handle->oidc->code_challenge = get_url_parameter_copy (handle,
+ OIDC_CODE_CHALLENGE_KEY);
+ if (NULL == handle->oidc->code_challenge)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "OAuth authorization request does not contain PKCE parameters!\n");
+ }
+
if (GNUNET_OK !=
GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->oidc->client_id,
strlen (
- handle->oidc->client_id),
+ handle->oidc->client_id),
&handle->oidc->client_pkey))
{
handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_UNAUTHORIZED_CLIENT);
return;
}
- handle->ego_entry = handle->ego_head;
- handle->priv_key =
- *GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego);
// If we know this identity, translated the corresponding TLD
// TODO: We might want to have a reverse lookup functionality for TLDs?
for (tmp_ego = handle->ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next)
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",GNUNET_strdup (
+ handle->oidc->scope));
if (NULL == handle->tld)
GNUNET_CONFIGURATION_iterate_section_values (cfg, "gns", tld_iter, handle);
if (NULL == handle->tld)
GNUNET_SCHEDULER_add_now (&build_authz_response, handle);
}
+
/**
* Combines an identity with a login time and responds OK to login request
*
json_error_t error;
json_t *identity;
char term_data[handle->rest_handle->data_size + 1];
+
term_data[handle->rest_handle->data_size] = '\0';
GNUNET_memcpy (term_data,
handle->rest_handle->data,
{
current_time = GNUNET_new (struct GNUNET_TIME_Absolute);
*current_time = GNUNET_TIME_relative_to_absolute (
- GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_get_second_ (),
- OIDC_COOKIE_EXPIRATION));
+ GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_get_second_ (),
+ OIDC_COOKIE_EXPIRATION));
last_time =
GNUNET_CONTAINER_multihashmap_get (OIDC_cookie_jar_map, &cache_key);
GNUNET_free_non_null (last_time);
GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
}
+
static int
check_authorization (struct RequestHandle *handle,
struct GNUNET_CRYPTO_EcdsaPublicKey *cid)
// split header in "Basic" and [content]
credentials = strtok (authorization, " ");
- if (0 != strcmp ("Basic", credentials))
+ if ((NULL == credentials) || (0 != strcmp ("Basic", credentials)))
{
handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT);
handle->response_code = MHD_HTTP_UNAUTHORIZED;
}
// check client_id
- for (handle->ego_entry = handle->ego_head;
- NULL != handle->ego_entry;
+ for (handle->ego_entry = handle->ego_head; NULL != handle->ego_entry;
handle->ego_entry = handle->ego_entry->next)
{
if (0 == strcmp (handle->ego_entry->keystring, client_id))
GNUNET_STRINGS_string_to_data (client_id,
strlen (client_id),
cid,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
+ sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey));
GNUNET_free (basic_authorization);
return GNUNET_OK;
}
+
const struct EgoEntry *
find_ego (struct RequestHandle *handle,
struct GNUNET_CRYPTO_EcdsaPublicKey *test_key)
return NULL;
}
+
static void
persist_access_token (const struct RequestHandle *handle,
const char *access_token,
GNUNET_CRYPTO_hash (access_token, strlen (access_token), &hc);
ticketbuf = GNUNET_new (struct GNUNET_RECLAIM_Ticket);
*ticketbuf = *ticket;
- GNUNET_CONTAINER_multihashmap_put (
- OIDC_access_token_map,
- &hc,
- ticketbuf,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
+ GNUNET_assert (GNUNET_SYSERR !=
+ GNUNET_CONTAINER_multihashmap_put (
+ OIDC_access_token_map,
+ &hc,
+ ticketbuf,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
}
+
/**
* Responds to token url-encoded POST request
*
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;
+ struct GNUNET_RECLAIM_AttestationList *al;
struct GNUNET_RECLAIM_Ticket ticket;
struct GNUNET_CRYPTO_EcdsaPublicKey cid;
const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
char *access_token;
char *jwt_secret;
char *nonce;
+ char *code_verifier;
/*
* Check Authorization
{
handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_UNSUPPORTED_GRANT_TYPE);
handle->response_code = MHD_HTTP_BAD_REQUEST;
+ GNUNET_free (grant_type);
GNUNET_SCHEDULER_add_now (&do_error, handle);
return;
}
-
+ GNUNET_free (grant_type);
// REQUIRED code
code = get_url_parameter_copy (handle, OIDC_CODE_KEY);
if (NULL == code)
handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
handle->edesc = GNUNET_strdup ("Unknown client");
handle->response_code = MHD_HTTP_BAD_REQUEST;
+ GNUNET_free (code);
GNUNET_SCHEDULER_add_now (&do_error, handle);
+ return;
}
privkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
+
+ // REQUIRED code verifier
+ code_verifier = get_url_parameter_copy (handle, OIDC_CODE_VERIFIER_KEY);
+ if (NULL == code_verifier)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "OAuth authorization request does not contain PKCE parameters!\n");
+
+ }
+
// decode code
- if (GNUNET_OK != OIDC_parse_authz_code (privkey, code, &ticket, &cl, &nonce))
+ if (GNUNET_OK != OIDC_parse_authz_code (privkey, code, code_verifier, &ticket,
+ &cl, &al, &nonce))
{
handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST);
handle->edesc = GNUNET_strdup ("invalid code");
handle->response_code = MHD_HTTP_BAD_REQUEST;
+ GNUNET_free (code);
GNUNET_SCHEDULER_add_now (&do_error, handle);
return;
}
+ GNUNET_free (code);
// create jwt
if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg,
id_token = OIDC_id_token_new (&ticket.audience,
&ticket.identity,
cl,
+ al,
&expiration_time,
(NULL != nonce) ? nonce : NULL,
jwt_secret);
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);
GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
}
+
/**
* Collects claims and stores them in handle
*/
static void
consume_ticket (void *cls,
const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
- const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
+ const struct GNUNET_RECLAIM_Attribute *attr,
+ const struct GNUNET_RECLAIM_Attestation *attest)
{
struct RequestHandle *handle = cls;
- char *tmp_value;
- json_t *value;
-
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);
}
+
/**
* Responds to userinfo GET and url-encoded POST request
*
// split header in "Bearer" and access_token
authorization = GNUNET_strdup (authorization);
authorization_type = strtok (authorization, delimiter);
- if (0 != strcmp ("Bearer", authorization_type))
+ if ((NULL == authorization_type) ||
+ (0 != strcmp ("Bearer", authorization_type)))
{
handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN);
handle->edesc = GNUNET_strdup ("No Access Token");
{
struct GNUNET_REST_RequestHandlerError err;
static const struct GNUNET_REST_RequestHandler handlers[] =
- {{MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint},
- {MHD_HTTP_METHOD_POST,
+ { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint },
+ { MHD_HTTP_METHOD_POST,
GNUNET_REST_API_NS_AUTHORIZE,
- &authorize_endpoint}, // url-encoded
- {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont},
- {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint},
- {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint},
- {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint},
- {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont},
- GNUNET_REST_HANDLER_END};
+ &authorize_endpoint }, // url-encoded
+ { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont },
+ { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
+ { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
+ { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
+ { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont },
+ GNUNET_REST_HANDLER_END };
if (GNUNET_NO ==
GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
}
}
+
/**
* If listing is enabled, prints information about the egos.
*
init_cont (handle);
return;
}
+ GNUNET_assert (NULL != ego);
if (ID_REST_STATE_INIT == handle->state)
+
{
ego_entry = GNUNET_new (struct EgoEntry);
GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
}
}
+
static void
rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
GNUNET_REST_ResultProcessor proc,
void *proc_cls)
{
struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
+
handle->oidc = GNUNET_new (struct OIDC_Variables);
if (NULL == OIDC_cookie_jar_map)
OIDC_cookie_jar_map = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
}
+
/**
* Entry point for the plugin.
*
cfg = cls;
if (NULL != plugin.cfg)
return NULL; /* can only initialize once! */
- memset (&plugin, 0, sizeof (struct Plugin));
+ memset (&plugin, 0, sizeof(struct Plugin));
plugin.cfg = cfg;
api = GNUNET_new (struct GNUNET_REST_Plugin);
api->cls = &plugin;
{
struct GNUNET_REST_Plugin *api = cls;
struct Plugin *plugin = api->cls;
+
plugin->cfg = NULL;
struct GNUNET_CONTAINER_MultiHashMapIterator *hashmap_it;
while (GNUNET_YES ==
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);
hashmap_it =
return NULL;
}
+
/* end of plugin_rest_openid_connect.c */