GNUnet debian-0.24.3-29-g453fda2cf
 
Loading...
Searching...
No Matches
openid_plugin.c File Reference
#include "platform.h"
#include <inttypes.h>
#include <jansson.h>
#include <jose/jose.h>
#include "gnunet_util_lib.h"
#include "gnunet_gns_service.h"
#include "gnunet_gnsrecord_lib.h"
#include "gnunet_identity_service.h"
#include "gnunet_reclaim_lib.h"
#include "gnunet_reclaim_service.h"
#include "gnunet_rest_lib.h"
#include "gnunet_rest_plugin.h"
#include "microhttpd.h"
#include "oidc_helper.h"
#include "openid_plugin.h"
Include dependency graph for openid_plugin.c:

Go to the source code of this file.

Data Structures

struct  Plugin
 Handle for a plugin. More...
 
struct  OIDC_Variables
 OIDC needed variables. More...
 
struct  EgoEntry
 The default namestore ego. More...
 
struct  RequestHandle
 The request handle. More...
 

Macros

#define GNUNET_REST_API_NS_OIDC   "/openid"
 REST root namespace.
 
#define GNUNET_REST_API_NS_OIDC_CONFIG   "/.well-known/openid-configuration"
 OIDC config.
 
#define GNUNET_REST_API_NS_AUTHORIZE   "/openid/authorize"
 Authorize endpoint.
 
#define GNUNET_REST_API_NS_TOKEN   "/openid/token"
 Token endpoint.
 
#define GNUNET_REST_API_JWKS   "/jwks.json"
 JSON Web Keys endpoint.
 
#define GNUNET_REST_API_NS_USERINFO   "/openid/userinfo"
 UserInfo endpoint.
 
#define GNUNET_REST_API_NS_LOGIN   "/openid/login"
 Login namespace.
 
#define ID_REST_STATE_INIT   0
 State while collecting all egos.
 
#define ID_REST_STATE_POST_INIT   1
 Done collecting egos.
 
#define OIDC_GRANT_TYPE_KEY   "grant_type"
 OIDC grant_type key.
 
#define OIDC_GRANT_TYPE_VALUE   "authorization_code"
 OIDC grant_type key.
 
#define OIDC_CODE_KEY   "code"
 OIDC code key.
 
#define OIDC_RESPONSE_TYPE_KEY   "response_type"
 OIDC response_type key.
 
#define OIDC_CLIENT_ID_KEY   "client_id"
 OIDC client_id key.
 
#define OIDC_SCOPE_KEY   "scope"
 OIDC scope key.
 
#define OIDC_REDIRECT_URI_KEY   "redirect_uri"
 OIDC redirect_uri key.
 
#define OIDC_STATE_KEY   "state"
 OIDC state key.
 
#define OIDC_NONCE_KEY   "nonce"
 OIDC nonce key.
 
#define OIDC_CLAIMS_KEY   "claims"
 OIDC claims key.
 
#define OIDC_CODE_CHALLENGE_KEY   "code_challenge"
 OIDC PKCE code challenge.
 
#define OIDC_CODE_VERIFIER_KEY   "code_verifier"
 OIDC PKCE code verifier.
 
#define OIDC_COOKIE_EXPIRATION   3
 OIDC cookie expiration (in seconds)
 
#define OIDC_COOKIE_HEADER_KEY   "cookie"
 OIDC cookie header key.
 
#define OIDC_AUTHORIZATION_HEADER_KEY   "authorization"
 OIDC cookie header information key.
 
#define OIDC_COOKIE_HEADER_INFORMATION_KEY   "Identity="
 OIDC cookie header information key.
 
#define OIDC_COOKIE_HEADER_ACCESS_DENIED   "Identity=Denied"
 OIDC cookie header if user cancelled.
 
#define OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE   "code"
 OIDC expected response_type while authorizing.
 
#define OIDC_EXPECTED_AUTHORIZATION_SCOPE   "openid"
 OIDC expected scope part while authorizing.
 
#define OIDC_ERROR_KEY_INVALID_CLIENT   "invalid_client"
 OIDC error key for invalid client.
 
#define OIDC_ERROR_KEY_INVALID_SCOPE   "invalid_scope"
 OIDC error key for invalid scopes.
 
#define OIDC_ERROR_KEY_INVALID_REQUEST   "invalid_request"
 OIDC error key for invalid requests.
 
#define OIDC_ERROR_KEY_INVALID_TOKEN   "invalid_token"
 OIDC error key for invalid tokens.
 
#define OIDC_ERROR_KEY_INVALID_COOKIE   "invalid_cookie"
 OIDC error key for invalid cookies.
 
#define OIDC_ERROR_KEY_SERVER_ERROR   "server_error"
 OIDC error key for generic server errors.
 
#define OIDC_ERROR_KEY_UNSUPPORTED_GRANT_TYPE   "unsupported_grant_type"
 OIDC error key for unsupported grants.
 
#define OIDC_ERROR_KEY_UNSUPPORTED_RESPONSE_TYPE   "unsupported_response_type"
 OIDC error key for unsupported response types.
 
#define OIDC_ERROR_KEY_UNAUTHORIZED_CLIENT   "unauthorized_client"
 OIDC error key for unauthorized clients.
 
#define OIDC_ERROR_KEY_ACCESS_DENIED   "access_denied"
 OIDC error key for denied access.
 
#define OIDC_JWK_RSA_FILENAME   "jwk_rsa.json"
 OIDC key store file name.
 
#define CONSUME_TIMEOUT
 How long to wait for a consume in userinfo endpoint.
 

Functions

static void cleanup_handle (struct RequestHandle *handle)
 Cleanup lookup handle.
 
static void do_error (void *cls)
 Task run on error, sends error message.
 
static void do_userinfo_error (void *cls)
 Task run on error in userinfo endpoint, sends error header.
 
static void do_redirect_error (void *cls)
 Task run on error, sends error message and redirects.
 
static void do_timeout (void *cls)
 Task run on timeout, sends error message.
 
static void options_cont (struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
 Respond to OPTIONS request.
 
static void cookie_identity_interpretation (struct RequestHandle *handle)
 Interprets cookie header and pass its identity keystring to handle.
 
static json_t * read_jwk_from_file (const char *filename)
 Read the the JSON Web Key in the given file and return it.
 
static int write_jwk_to_file (const char *filename, json_t *jwk)
 Write the JWK to file.
 
static json_t * generate_jwk ()
 Generate a new RSA JSON Web Key.
 
static char * get_oidc_dir_path (void *cls)
 Return the path to the oidc directory path.
 
static char * get_oidc_jwk_path (void *cls)
 Return the path to the RSA JWK key file.
 
static void login_redirect (void *cls)
 Redirects to login page stored in configuration file.
 
static void oidc_iteration_error (void *cls)
 Does internal server error when iteration failed.
 
static void oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket, const struct GNUNET_RECLAIM_PresentationList *presentation)
 Issues ticket and redirects to relying party with the authorization code as parameter.
 
static struct GNUNET_RECLAIM_AttributeListattribute_list_merge (struct GNUNET_RECLAIM_AttributeList *list_a, struct GNUNET_RECLAIM_AttributeList *list_b)
 
static void oidc_cred_collect_finished_cb (void *cls)
 
static void oidc_cred_collect (void *cls, const struct GNUNET_CRYPTO_PublicKey *identity, const struct GNUNET_RECLAIM_Credential *cred)
 Collects all attributes for an ego if in scope parameter.
 
static void oidc_attr_collect_finished_cb (void *cls)
 
static int attr_in_claims_request (struct RequestHandle *handle, const char *attr_name, const char *claims_parameter)
 
static int attr_in_idtoken_request (struct RequestHandle *handle, const char *attr_name)
 
static int attr_in_userinfo_request (struct RequestHandle *handle, const char *attr_name)
 
static void oidc_attr_collect (void *cls, const struct GNUNET_CRYPTO_PublicKey *identity, const struct GNUNET_RECLAIM_Attribute *attr)
 Collects all attributes for an ego if in scope parameter.
 
static void code_redirect (void *cls)
 Checks time and cookie and redirects accordingly.
 
static void build_redirect (void *cls)
 
static void lookup_redirect_uri_result (void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd)
 
static void client_redirect (void *cls)
 Initiate redirect back to client.
 
static char * get_url_parameter_copy (const struct RequestHandle *handle, const char *key)
 
static void build_authz_response (void *cls)
 Iteration over all results finished, build final response.
 
static void tld_iter (void *cls, const char *section, const char *option, const char *value)
 Iterate over tlds in config.
 
static void authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
 Responds to authorization GET and url-encoded POST request.
 
static void login_cont (struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
 Combines an identity with a login time and responds OK to login request.
 
static int parse_credentials_basic_auth (struct RequestHandle *handle, char **client_id, char **client_secret)
 
static int parse_credentials_post_body (struct RequestHandle *handle, char **client_id, char **client_secret)
 
static int check_authorization (struct RequestHandle *handle, struct GNUNET_CRYPTO_PublicKey *cid)
 
static const struct EgoEntryfind_ego (struct RequestHandle *handle, struct GNUNET_CRYPTO_PublicKey *test_key)
 
static void token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
 Responds to token url-encoded POST request.
 
static void consume_ticket (void *cls, const struct GNUNET_CRYPTO_PublicKey *identity, const struct GNUNET_RECLAIM_Attribute *attr, const struct GNUNET_RECLAIM_Presentation *presentation)
 Collects claims and stores them in handle.
 
static void consume_fail (void *cls)
 
static void userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
 Responds to userinfo GET and url-encoded POST request.
 
static void jwks_endpoint (struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
 Responds to /jwks.json.
 
static void list_ego (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *identifier)
 If listing is enabled, prints information about the egos.
 
static void oidc_config_endpoint (struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
 
static void oidc_config_cors (struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
 Respond to OPTIONS request.
 
enum GNUNET_GenericReturnValue REST_openid_process_request (void *plugin, struct GNUNET_REST_RequestHandle *rest_handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
 Function processing the REST call.
 
void * REST_openid_init (const struct GNUNET_CONFIGURATION_Handle *c)
 Entry point for the plugin.
 
static int cleanup_hashmap (void *cls, const struct GNUNET_HashCode *key, void *value)
 
void REST_openid_done (struct GNUNET_REST_Plugin *api)
 Exit point from the plugin.
 

Variables

static const char * OIDC_ignored_parameter_array []
 OIDC ignored parameter array.
 
struct GNUNET_CONTAINER_MultiHashMapoidc_code_cache
 OIDC hashmap for cached access tokens and codes.
 
struct GNUNET_CONTAINER_MultiHashMapOIDC_cookie_jar_map
 OIDC hashmap that keeps track of issued cookies.
 
const struct GNUNET_CONFIGURATION_Handleoid_cfg
 The configuration handle.
 
static char * allow_methods
 HTTP methods allows for this plugin.
 
static struct EgoEntryego_head
 Ego list.
 
static struct EgoEntryego_tail
 Ego list.
 
static int state
 The processing state.
 
static struct GNUNET_IDENTITY_Handleidentity_handle
 Handle to Identity service.
 
static struct GNUNET_GNS_Handlegns_handle
 GNS handle.
 
static struct GNUNET_RECLAIM_Handleidp
 Identity Provider.
 
static struct GNUNET_TIME_Relative consume_timeout
 Timeout for consume call on userinfo.
 
json_t * oidc_jwk
 The RSA key used by the oidc endpoint.
 
static struct RequestHandlerequests_head
 DLL.
 
static struct RequestHandlerequests_tail
 DLL.
 

Macro Definition Documentation

◆ GNUNET_REST_API_NS_OIDC

#define GNUNET_REST_API_NS_OIDC   "/openid"

REST root namespace.

Definition at line 48 of file openid_plugin.c.

◆ GNUNET_REST_API_NS_OIDC_CONFIG

#define GNUNET_REST_API_NS_OIDC_CONFIG   "/.well-known/openid-configuration"

OIDC config.

Definition at line 53 of file openid_plugin.c.

◆ GNUNET_REST_API_NS_AUTHORIZE

#define GNUNET_REST_API_NS_AUTHORIZE   "/openid/authorize"

Authorize endpoint.

Definition at line 58 of file openid_plugin.c.

◆ GNUNET_REST_API_NS_TOKEN

#define GNUNET_REST_API_NS_TOKEN   "/openid/token"

Token endpoint.

Definition at line 63 of file openid_plugin.c.

◆ GNUNET_REST_API_JWKS

#define GNUNET_REST_API_JWKS   "/jwks.json"

JSON Web Keys endpoint.

Definition at line 68 of file openid_plugin.c.

◆ GNUNET_REST_API_NS_USERINFO

#define GNUNET_REST_API_NS_USERINFO   "/openid/userinfo"

UserInfo endpoint.

Definition at line 73 of file openid_plugin.c.

◆ GNUNET_REST_API_NS_LOGIN

#define GNUNET_REST_API_NS_LOGIN   "/openid/login"

Login namespace.

Definition at line 78 of file openid_plugin.c.

◆ ID_REST_STATE_INIT

#define ID_REST_STATE_INIT   0

State while collecting all egos.

Definition at line 83 of file openid_plugin.c.

◆ ID_REST_STATE_POST_INIT

#define ID_REST_STATE_POST_INIT   1

Done collecting egos.

Definition at line 88 of file openid_plugin.c.

◆ OIDC_GRANT_TYPE_KEY

#define OIDC_GRANT_TYPE_KEY   "grant_type"

OIDC grant_type key.

Definition at line 93 of file openid_plugin.c.

◆ OIDC_GRANT_TYPE_VALUE

#define OIDC_GRANT_TYPE_VALUE   "authorization_code"

OIDC grant_type key.

Definition at line 98 of file openid_plugin.c.

◆ OIDC_CODE_KEY

#define OIDC_CODE_KEY   "code"

OIDC code key.

Definition at line 103 of file openid_plugin.c.

◆ OIDC_RESPONSE_TYPE_KEY

#define OIDC_RESPONSE_TYPE_KEY   "response_type"

OIDC response_type key.

Definition at line 108 of file openid_plugin.c.

◆ OIDC_CLIENT_ID_KEY

#define OIDC_CLIENT_ID_KEY   "client_id"

OIDC client_id key.

Definition at line 113 of file openid_plugin.c.

◆ OIDC_SCOPE_KEY

#define OIDC_SCOPE_KEY   "scope"

OIDC scope key.

Definition at line 118 of file openid_plugin.c.

◆ OIDC_REDIRECT_URI_KEY

#define OIDC_REDIRECT_URI_KEY   "redirect_uri"

OIDC redirect_uri key.

Definition at line 123 of file openid_plugin.c.

◆ OIDC_STATE_KEY

#define OIDC_STATE_KEY   "state"

OIDC state key.

Definition at line 128 of file openid_plugin.c.

◆ OIDC_NONCE_KEY

#define OIDC_NONCE_KEY   "nonce"

OIDC nonce key.

Definition at line 133 of file openid_plugin.c.

◆ OIDC_CLAIMS_KEY

#define OIDC_CLAIMS_KEY   "claims"

OIDC claims key.

Definition at line 138 of file openid_plugin.c.

◆ OIDC_CODE_CHALLENGE_KEY

#define OIDC_CODE_CHALLENGE_KEY   "code_challenge"

OIDC PKCE code challenge.

Definition at line 143 of file openid_plugin.c.

◆ OIDC_CODE_VERIFIER_KEY

#define OIDC_CODE_VERIFIER_KEY   "code_verifier"

OIDC PKCE code verifier.

Definition at line 148 of file openid_plugin.c.

◆ OIDC_COOKIE_EXPIRATION

#define OIDC_COOKIE_EXPIRATION   3

OIDC cookie expiration (in seconds)

Definition at line 153 of file openid_plugin.c.

◆ OIDC_COOKIE_HEADER_KEY

#define OIDC_COOKIE_HEADER_KEY   "cookie"

OIDC cookie header key.

Definition at line 158 of file openid_plugin.c.

◆ OIDC_AUTHORIZATION_HEADER_KEY

#define OIDC_AUTHORIZATION_HEADER_KEY   "authorization"

OIDC cookie header information key.

Definition at line 163 of file openid_plugin.c.

◆ OIDC_COOKIE_HEADER_INFORMATION_KEY

#define OIDC_COOKIE_HEADER_INFORMATION_KEY   "Identity="

OIDC cookie header information key.

Definition at line 168 of file openid_plugin.c.

◆ OIDC_COOKIE_HEADER_ACCESS_DENIED

#define OIDC_COOKIE_HEADER_ACCESS_DENIED   "Identity=Denied"

OIDC cookie header if user cancelled.

Definition at line 173 of file openid_plugin.c.

◆ OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE

#define OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE   "code"

OIDC expected response_type while authorizing.

Definition at line 178 of file openid_plugin.c.

◆ OIDC_EXPECTED_AUTHORIZATION_SCOPE

#define OIDC_EXPECTED_AUTHORIZATION_SCOPE   "openid"

OIDC expected scope part while authorizing.

Definition at line 183 of file openid_plugin.c.

◆ OIDC_ERROR_KEY_INVALID_CLIENT

#define OIDC_ERROR_KEY_INVALID_CLIENT   "invalid_client"

OIDC error key for invalid client.

Definition at line 188 of file openid_plugin.c.

◆ OIDC_ERROR_KEY_INVALID_SCOPE

#define OIDC_ERROR_KEY_INVALID_SCOPE   "invalid_scope"

OIDC error key for invalid scopes.

Definition at line 193 of file openid_plugin.c.

◆ OIDC_ERROR_KEY_INVALID_REQUEST

#define OIDC_ERROR_KEY_INVALID_REQUEST   "invalid_request"

OIDC error key for invalid requests.

Definition at line 198 of file openid_plugin.c.

◆ OIDC_ERROR_KEY_INVALID_TOKEN

#define OIDC_ERROR_KEY_INVALID_TOKEN   "invalid_token"

OIDC error key for invalid tokens.

Definition at line 203 of file openid_plugin.c.

◆ OIDC_ERROR_KEY_INVALID_COOKIE

#define OIDC_ERROR_KEY_INVALID_COOKIE   "invalid_cookie"

OIDC error key for invalid cookies.

Definition at line 208 of file openid_plugin.c.

◆ OIDC_ERROR_KEY_SERVER_ERROR

#define OIDC_ERROR_KEY_SERVER_ERROR   "server_error"

OIDC error key for generic server errors.

Definition at line 213 of file openid_plugin.c.

◆ OIDC_ERROR_KEY_UNSUPPORTED_GRANT_TYPE

#define OIDC_ERROR_KEY_UNSUPPORTED_GRANT_TYPE   "unsupported_grant_type"

OIDC error key for unsupported grants.

Definition at line 218 of file openid_plugin.c.

◆ OIDC_ERROR_KEY_UNSUPPORTED_RESPONSE_TYPE

#define OIDC_ERROR_KEY_UNSUPPORTED_RESPONSE_TYPE   "unsupported_response_type"

OIDC error key for unsupported response types.

Definition at line 223 of file openid_plugin.c.

◆ OIDC_ERROR_KEY_UNAUTHORIZED_CLIENT

#define OIDC_ERROR_KEY_UNAUTHORIZED_CLIENT   "unauthorized_client"

OIDC error key for unauthorized clients.

Definition at line 228 of file openid_plugin.c.

◆ OIDC_ERROR_KEY_ACCESS_DENIED

#define OIDC_ERROR_KEY_ACCESS_DENIED   "access_denied"

OIDC error key for denied access.

Definition at line 233 of file openid_plugin.c.

◆ OIDC_JWK_RSA_FILENAME

#define OIDC_JWK_RSA_FILENAME   "jwk_rsa.json"

OIDC key store file name.

Definition at line 238 of file openid_plugin.c.

◆ CONSUME_TIMEOUT

#define CONSUME_TIMEOUT
Value:
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition time.c:486

How long to wait for a consume in userinfo endpoint.

Definition at line 243 of file openid_plugin.c.

248 { "display",
249 "prompt",
250 "ui_locales",
251 "response_mode",
252 "id_token_hint",
253 "login_hint",
254 "acr_values" };
255
260
265
270
274static char *allow_methods;
275
279static struct EgoEntry *ego_head;
280
284static struct EgoEntry *ego_tail;
285
289static int state;
290
295
299static struct GNUNET_GNS_Handle *gns_handle;
300
304static struct GNUNET_RECLAIM_Handle *idp;
305
310
314struct Plugin
315{
316 const struct GNUNET_CONFIGURATION_Handle *cfg;
317};
318
322json_t *oidc_jwk;
323
327struct OIDC_Variables
328{
333
337 char *client_id;
338
342 char *redirect_uri;
343
347 char *scope;
348
352 char *state;
353
357 char *nonce;
358
362 char *claims;
363
367 char *response_type;
368
372 char *login_identity;
373
377 int user_cancelled;
378
382 char *code_challenge;
383
387 char *code_verifier;
388
389};
390
394struct EgoEntry
395{
399 struct EgoEntry *next;
400
404 struct EgoEntry *prev;
405
409 char *identifier;
410
414 char *keystring;
415
419 struct GNUNET_IDENTITY_Ego *ego;
420};
421
422
423struct RequestHandle
424{
428 struct RequestHandle *next;
429
433 struct RequestHandle *prev;
434
438 struct EgoEntry *ego_entry;
439
444
448 struct OIDC_Variables *oidc;
449
454
459
464
469
474
479
484
485
490
495
500
505
506
511
516
521
526
531
535 void *proc_cls;
536
540 char *url;
541
545 char *access_token;
546
550 char *tld;
551
555 char *redirect_prefix;
556
560 char *redirect_suffix;
561
565 char *emsg;
566
570 char *edesc;
571
575 int response_code;
576
580 int public_client;
581};
582
586static struct RequestHandle *requests_head;
587
591static struct RequestHandle *requests_tail;
592
593
598static void
600{
601
602 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
603 if (NULL != handle->timeout_task)
604 GNUNET_SCHEDULER_cancel (handle->timeout_task);
605 if (NULL != handle->attr_it)
607 if (NULL != handle->cred_it)
609 if (NULL != handle->ticket_it)
611 if (NULL != handle->idp_op)
613 if (NULL != handle->consume_timeout_op)
614 GNUNET_SCHEDULER_cancel (handle->consume_timeout_op);
615 GNUNET_free (handle->url);
616 GNUNET_free (handle->tld);
617 GNUNET_free (handle->redirect_prefix);
618 GNUNET_free (handle->redirect_suffix);
619 GNUNET_free (handle->emsg);
620 GNUNET_free (handle->edesc);
621 if (NULL != handle->gns_op)
623 if (NULL != handle->oidc)
624 {
625 GNUNET_free (handle->oidc->client_id);
626 GNUNET_free (handle->oidc->login_identity);
627 GNUNET_free (handle->oidc->nonce);
628 GNUNET_free (handle->oidc->redirect_uri);
629 GNUNET_free (handle->oidc->response_type);
630 GNUNET_free (handle->oidc->scope);
631 GNUNET_free (handle->oidc->state);
632 if (NULL != handle->oidc->claims)
633 GNUNET_free (handle->oidc->claims);
634 if (NULL != handle->oidc->code_challenge)
635 GNUNET_free (handle->oidc->code_challenge);
636 GNUNET_free (handle->oidc);
637 }
638 if (NULL!=handle->attr_idtoken_list)
640 if (NULL!=handle->attr_userinfo_list)
641 GNUNET_RECLAIM_attribute_list_destroy (handle->attr_userinfo_list);
642 if (NULL!=handle->credentials)
644 if (NULL!=handle->presentations)
648 handle);
649 if (NULL != handle->access_token)
650 GNUNET_free (handle->access_token);
652}
653
654
660static void
661do_error (void *cls)
662{
663 struct RequestHandle *handle = cls;
664 struct MHD_Response *resp;
665 char *json_error;
666
667 GNUNET_asprintf (&json_error,
668 "{ \"error\" : \"%s\", \"error_description\" : \"%s\"%s%s%s}",
669 handle->emsg,
670 (NULL != handle->edesc) ? handle->edesc : "",
671 (NULL != handle->oidc->state) ? ", \"state\":\"" : "",
672 (NULL != handle->oidc->state) ? handle->oidc->state : "",
673 (NULL != handle->oidc->state) ? "\"" : "");
674 if (0 == handle->response_code)
675 handle->response_code = MHD_HTTP_BAD_REQUEST;
676 resp = GNUNET_REST_create_response (json_error);
677 if (MHD_HTTP_UNAUTHORIZED == handle->response_code)
678 GNUNET_assert (MHD_NO !=
679 MHD_add_response_header (resp,
680 MHD_HTTP_HEADER_WWW_AUTHENTICATE,
681 "Basic"));
682 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
683 MHD_HTTP_HEADER_CONTENT_TYPE,
684 "application/json"));
685 handle->proc (handle->proc_cls, resp, handle->response_code);
687 GNUNET_free (json_error);
688}
689
690
697static void
698do_userinfo_error (void *cls)
699{
700 struct RequestHandle *handle = cls;
701 struct MHD_Response *resp;
702 char *error;
703
705 "Error: %s\n", handle->edesc);
706 GNUNET_asprintf (&error,
707 "error=\"%s\", error_description=\"%s\"",
708 handle->emsg,
709 (NULL != handle->edesc) ? handle->edesc : "");
710 resp = GNUNET_REST_create_response ("");
711 GNUNET_assert (MHD_NO !=
712 MHD_add_response_header (resp,
713 MHD_HTTP_HEADER_WWW_AUTHENTICATE,
714 "Bearer"));
715 handle->proc (handle->proc_cls, resp, handle->response_code);
717 GNUNET_free (error);
718}
719
720
726static void
727do_redirect_error (void *cls)
728{
729 struct RequestHandle *handle = cls;
730 struct MHD_Response *resp;
731 char *redirect;
732
733 GNUNET_asprintf (&redirect,
734 "%s?error=%s&error_description=%s%s%s",
735 handle->oidc->redirect_uri,
736 handle->emsg,
737 handle->edesc,
738 (NULL != handle->oidc->state) ? "&state=" : "",
739 (NULL != handle->oidc->state) ? handle->oidc->state : "");
740 resp = GNUNET_REST_create_response ("");
741 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
742 "Location", redirect));
743 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
745 GNUNET_free (redirect);
746}
747
748
754static void
755do_timeout (void *cls)
756{
757 struct RequestHandle *handle = cls;
758
759 handle->timeout_task = NULL;
761}
762
763
771static void
772options_cont (struct GNUNET_REST_RequestHandle *con_handle,
773 const char *url,
774 void *cls)
775{
776 struct MHD_Response *resp;
777 struct RequestHandle *handle = cls;
778
779 // For now, independent of path return all options
780 resp = GNUNET_REST_create_response (NULL);
781 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
782 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
784 return;
785}
786
787
791static void
793{
794 struct GNUNET_HashCode cache_key;
795 char *cookies;
796 struct GNUNET_TIME_Absolute current_time, *relog_time;
797 char delimiter[] = "; ";
798 char *tmp_cookies;
799 char *token;
800 char *value;
801
802 // gets identity of login try with cookie
804 strlen (OIDC_COOKIE_HEADER_KEY),
805 &cache_key);
807 ->header_param_map,
808 &cache_key))
809 {
810 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No cookie found\n");
811 return;
812 }
813 // splits cookies and find 'Identity' cookie
814 tmp_cookies =
815 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
816 &cache_key);
817 cookies = GNUNET_strdup (tmp_cookies);
818 token = strtok (cookies, delimiter);
819 handle->oidc->user_cancelled = GNUNET_NO;
820 handle->oidc->login_identity = NULL;
821 if (NULL == token)
822 {
824 "Unable to parse cookie: %s\n",
825 cookies);
826 GNUNET_free (cookies);
827 return;
828 }
829
830 while (NULL != token)
831 {
832 if (0 == strcmp (token, OIDC_COOKIE_HEADER_ACCESS_DENIED))
833 {
834 handle->oidc->user_cancelled = GNUNET_YES;
835 GNUNET_free (cookies);
836 return;
837 }
838 if (NULL != strstr (token, OIDC_COOKIE_HEADER_INFORMATION_KEY))
839 break;
840 token = strtok (NULL, delimiter);
841 }
842 if (NULL == token)
843 {
845 "No cookie value to process: %s\n",
846 cookies);
847 GNUNET_free (cookies);
848 return;
849 }
850 GNUNET_CRYPTO_hash (token, strlen (token), &cache_key);
851 if (GNUNET_NO ==
853 {
854 GNUNET_log (
856 "Found cookie `%s', but no corresponding expiration entry present...\n",
857 token);
858 GNUNET_free (cookies);
859 return;
860 }
861 relog_time =
863 current_time = GNUNET_TIME_absolute_get ();
864 // 30 min after old login -> redirect to login
865 if (current_time.abs_value_us > relog_time->abs_value_us)
866 {
868 "Found cookie `%s', but it is expired.\n",
869 token);
870 GNUNET_free (cookies);
871 return;
872 }
874 GNUNET_assert (NULL != value);
875 handle->oidc->login_identity = GNUNET_strdup (value);
876 GNUNET_free (cookies);
877}
878
879
888static json_t *
889read_jwk_from_file (const char *filename)
890{
891 json_t *jwk;
892 json_error_t error;
893
894 jwk = json_load_file (filename, JSON_DECODE_ANY, &error);
895
896 if (! jwk)
897 {
899 ("Could not read OIDC RSA key from config file; %s\n"),
900 error.text);
901 }
902
903 return jwk;
904}
905
906
914static int
915write_jwk_to_file (const char *filename,
916 json_t *jwk)
917{
918 if (json_dump_file (jwk, filename, JSON_INDENT (2)))
919 {
921 ("Could not write OIDC RSA key to file %s\n"),
922 filename);
924 }
925 else
926 return GNUNET_OK;
927}
928
929
935static json_t *
937{
938 json_t *jwk;
939 jwk = json_pack ("{s:s,s:i}", "kty", "RSA", "bits", 2048);
940 jose_jwk_gen (NULL, jwk);
941 json_incref (jwk);
942 return jwk;
943}
944
945
951static char *
952get_oidc_dir_path (void *cls)
953{
954 char *oidc_directory;
955 struct RequestHandle *handle = cls;
956
957 // Read OIDC directory from config
959 "reclaim-rest-plugin",
960 "oidc_dir",
961 &oidc_directory))
962 {
963 // Could not read Config file
965 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
966 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
968 return NULL;
969 }
970
971 return oidc_directory;
972}
973
974
980static char *
981get_oidc_jwk_path (void *cls)
982{
983 char *oidc_directory;
984 char *oidc_jwk_path;
985
986 oidc_directory = get_oidc_dir_path (cls);
987
988 // Create path to file
989 GNUNET_asprintf (&oidc_jwk_path, "%s/%s", oidc_directory,
991
992 return oidc_jwk_path;
993}
994
995
999static void
1000login_redirect (void *cls)
1001{
1002 char *login_base_url;
1003 char *new_redirect;
1004 char *tmp;
1005 struct MHD_Response *resp;
1006 struct GNUNET_Buffer buf = { 0 };
1007 struct RequestHandle *handle = cls;
1008
1010 "reclaim-rest-plugin",
1011 "address",
1012 &login_base_url))
1013 {
1014 GNUNET_buffer_write_str (&buf, login_base_url);
1016 "?%s=%s",
1018 handle->oidc->response_type);
1020 "&%s=%s",
1022 handle->oidc->client_id);
1023 GNUNET_STRINGS_urlencode (strlen (handle->oidc->redirect_uri),
1024 handle->oidc->redirect_uri,
1025 &tmp);
1027 "&%s=%s",
1029 tmp);
1030 GNUNET_free (tmp);
1031 GNUNET_STRINGS_urlencode (strlen (handle->oidc->scope),
1032 handle->oidc->scope,
1033 &tmp);
1035 "&%s=%s",
1037 tmp);
1038 GNUNET_free (tmp);
1039 if (NULL != handle->oidc->state)
1040 {
1041 GNUNET_STRINGS_urlencode (strlen (handle->oidc->state),
1042 handle->oidc->state,
1043 &tmp);
1045 "&%s=%s",
1047 handle->oidc->state);
1048 GNUNET_free (tmp);
1049 }
1050 if (NULL != handle->oidc->code_challenge)
1051 {
1053 "&%s=%s",
1055 handle->oidc->code_challenge);
1056 }
1057 if (NULL != handle->oidc->nonce)
1058 {
1060 "&%s=%s",
1062 handle->oidc->nonce);
1063 }
1064 if (NULL != handle->oidc->claims)
1065 {
1066 GNUNET_STRINGS_urlencode (strlen (handle->oidc->claims),
1067 handle->oidc->claims,
1068 &tmp);
1070 "&%s=%s",
1072 tmp);
1073 GNUNET_free (tmp);
1074 }
1075 new_redirect = GNUNET_buffer_reap_str (&buf);
1076 resp = GNUNET_REST_create_response ("");
1077 MHD_add_response_header (resp, "Location", new_redirect);
1078 GNUNET_free (login_base_url);
1079 }
1080 else
1081 {
1083 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
1084 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1086 return;
1087 }
1088 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1089 GNUNET_free (new_redirect);
1091}
1092
1093
1097static void
1098oidc_iteration_error (void *cls)
1099{
1100 struct RequestHandle *handle = cls;
1101
1103 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1105}
1106
1107
1112static void
1113oidc_ticket_issue_cb (void *cls,
1114 const struct GNUNET_RECLAIM_Ticket *ticket,
1115 const struct
1116 GNUNET_RECLAIM_PresentationList *presentation)
1117{
1118 struct RequestHandle *handle = cls;
1119 struct MHD_Response *resp;
1120 char *ticket_str;
1121 char *redirect_uri;
1122 char *code_string;
1123
1124 handle->idp_op = NULL;
1125 if (NULL == ticket)
1126 {
1128 handle->edesc = GNUNET_strdup ("Server cannot generate ticket.");
1130 return;
1131 }
1132 handle->ticket = *ticket;
1133 ticket_str =
1135 sizeof(struct GNUNET_RECLAIM_Ticket));
1136 code_string = OIDC_build_authz_code (&handle->priv_key,
1137 &handle->ticket,
1138 handle->attr_idtoken_list,
1139 presentation,
1140 handle->oidc->nonce,
1141 handle->oidc->code_challenge);
1142 if ((NULL != handle->redirect_prefix) && (NULL != handle->redirect_suffix) &&
1143 (NULL != handle->tld))
1144 {
1145 GNUNET_asprintf (&redirect_uri,
1146 "%s.%s/%s%s%s=%s&state=%s",
1147 handle->redirect_prefix,
1148 handle->tld,
1149 handle->redirect_suffix,
1150 (NULL == strchr (handle->redirect_suffix, '?') ? "?" :
1151 "&"),
1152 handle->oidc->response_type,
1153 code_string,
1154 handle->oidc->state);
1155 }
1156 else
1157 {
1158 GNUNET_asprintf (&redirect_uri,
1159 "%s%s%s=%s&state=%s",
1160 handle->oidc->redirect_uri,
1161 (NULL == strchr (handle->oidc->redirect_uri, '?') ? "?" :
1162 "&"),
1163 handle->oidc->response_type,
1164 code_string,
1165 handle->oidc->state);
1166 }
1167 resp = GNUNET_REST_create_response ("");
1168 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1169 "Location", redirect_uri));
1170 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1172 GNUNET_free (redirect_uri);
1173 GNUNET_free (ticket_str);
1174 GNUNET_free (code_string);
1175}
1176
1177
1178static struct GNUNET_RECLAIM_AttributeList*
1180 struct GNUNET_RECLAIM_AttributeList *list_b)
1181{
1182 struct GNUNET_RECLAIM_AttributeList *merged_list;
1186
1187 merged_list = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
1188 for (le_a = list_a->list_head; NULL != le_a; le_a = le_a->next)
1189 {
1192 &le_a->attribute->
1193 credential,
1194 le_a->attribute->type,
1195 le_a->attribute->data,
1196 le_a->attribute->data_size);
1197 le_m->attribute->id = le_a->attribute->id;
1198 le_m->attribute->flag = le_a->attribute->flag;
1199 le_m->attribute->credential = le_a->attribute->credential;
1201 merged_list->list_tail,
1202 le_m);
1203 }
1204 le_m = NULL;
1205 for (le_b = list_b->list_head; NULL != le_b; le_b = le_b->next)
1206 {
1207 for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1208 {
1210 &le_b->attribute->id))
1211 break;
1212 }
1213 if (NULL != le_m)
1214 continue;
1217 &le_b->attribute->
1218 credential,
1219 le_b->attribute->type,
1220 le_b->attribute->data,
1221 le_b->attribute->data_size);
1222 le_m->attribute->id = le_b->attribute->id;
1223 le_m->attribute->flag = le_b->attribute->flag;
1224 le_m->attribute->credential = le_b->attribute->credential;
1226 merged_list->list_tail,
1227 le_m);
1228 }
1229 return merged_list;
1230}
1231
1232
1233static void
1235{
1236 struct RequestHandle *handle = cls;
1237 struct GNUNET_RECLAIM_AttributeList *merged_list;
1239
1240 handle->cred_it = NULL;
1241 merged_list = attribute_list_merge (handle->attr_idtoken_list,
1242 handle->attr_userinfo_list);
1243 for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1245 "List Attribute in ticket to issue: %s\n",
1246 le_m->attribute->name);
1248 &handle->priv_key,
1249 handle->oidc->client_id,
1250 merged_list,
1252 handle);
1254}
1255
1256
1260static void
1261oidc_cred_collect (void *cls,
1262 const struct GNUNET_CRYPTO_PublicKey *identity,
1263 const struct GNUNET_RECLAIM_Credential *cred)
1264{
1265 struct RequestHandle *handle = cls;
1268
1269 for (ale = handle->credentials->list_head; NULL != ale; ale = ale->next)
1270 {
1272 &cred->id))
1273 continue;
1276 return;
1277 }
1278
1279 for (le = handle->attr_idtoken_list->list_head; NULL != le; le = le->next)
1280 {
1282 &cred->id))
1283 continue;
1287 cred->type,
1288 cred->data,
1289 cred->data_size);
1290 GNUNET_CONTAINER_DLL_insert (handle->credentials->list_head,
1291 handle->credentials->list_tail,
1292 ale);
1293 }
1295}
1296
1297
1298static void
1300{
1301 struct RequestHandle *handle = cls;
1302
1303 handle->attr_it = NULL;
1304 handle->ticket_it = NULL;
1305 if (NULL == handle->attr_idtoken_list->list_head)
1306 {
1308 handle->edesc = GNUNET_strdup ("The requested scope is not available.");
1310 return;
1311 }
1312 handle->credentials = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
1313 handle->cred_it =
1315 &handle->priv_key,
1317 handle,
1319 handle,
1321 handle);
1322
1323}
1324
1325
1326static int
1328 const char *attr_name,
1329 const char *claims_parameter)
1330{
1331 int ret = GNUNET_NO;
1332 json_t *root;
1333 json_error_t error;
1334 json_t *claims_j;
1335 const char *key;
1336 json_t *value;
1337
1340 attr_name))
1341 return GNUNET_YES;
1342
1344 if (NULL != handle->oidc->claims)
1345 {
1346 root = json_loads (handle->oidc->claims, JSON_DECODE_ANY, &error);
1347 claims_j = json_object_get (root, claims_parameter);
1348 /* obj is a JSON object */
1349 if (NULL != claims_j)
1350 {
1351 json_object_foreach (claims_j, key, value) {
1352 if (0 != strcmp (attr_name, key))
1353 continue;
1354 ret = GNUNET_YES;
1355 break;
1356 }
1357 }
1358 json_decref (root);
1359 }
1360 return ret;
1361}
1362
1363
1364static int
1366 const char *attr_name)
1367{
1368 return attr_in_claims_request (handle, attr_name, "id_token");
1369}
1370
1371
1372static int
1374 const char *attr_name)
1375{
1376 return attr_in_claims_request (handle, attr_name, "userinfo");
1377}
1378
1379
1383static void
1384oidc_attr_collect (void *cls,
1385 const struct GNUNET_CRYPTO_PublicKey *identity,
1386 const struct GNUNET_RECLAIM_Attribute *attr)
1387{
1388 struct RequestHandle *handle = cls;
1391 {
1394 &attr->credential,
1395 attr->type,
1396 attr->data,
1397 attr->data_size);
1398 le->attribute->id = attr->id;
1399 le->attribute->flag = attr->flag;
1400 le->attribute->credential = attr->credential;
1401 GNUNET_CONTAINER_DLL_insert (handle->attr_idtoken_list->list_head,
1402 handle->attr_idtoken_list->list_tail,
1403 le);
1404 }
1406 {
1409 &attr->credential,
1410 attr->type,
1411 attr->data,
1412 attr->data_size);
1413 le->attribute->id = attr->id;
1414 le->attribute->flag = attr->flag;
1415 le->attribute->credential = attr->credential;
1416 GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
1417 handle->attr_userinfo_list->list_tail,
1418 le);
1419 }
1420
1422}
1423
1424
1428static void
1429code_redirect (void *cls)
1430{
1431 struct RequestHandle *handle = cls;
1432 struct GNUNET_TIME_Absolute current_time;
1433 struct GNUNET_TIME_Absolute *relog_time;
1435 struct GNUNET_CRYPTO_PublicKey ego_pkey;
1436 struct GNUNET_HashCode cache_key;
1437 char *identity_cookie;
1438
1439 GNUNET_asprintf (&identity_cookie,
1440 "Identity=%s",
1441 handle->oidc->login_identity);
1442 GNUNET_CRYPTO_hash (identity_cookie, strlen (identity_cookie), &cache_key);
1443 GNUNET_free (identity_cookie);
1444 // No login time for identity -> redirect to login
1445 if (GNUNET_YES ==
1447 {
1448 relog_time =
1450 current_time = GNUNET_TIME_absolute_get ();
1451 // 30 min after old login -> redirect to login
1452 if (current_time.abs_value_us <= relog_time->abs_value_us)
1453 {
1454 if (GNUNET_OK !=
1456 ->login_identity,
1457 &pubkey))
1458 {
1460 handle->edesc =
1461 GNUNET_strdup ("The cookie of a login identity is not valid");
1463 return;
1464 }
1465 // iterate over egos and compare their public key
1466 for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
1467 handle->ego_entry = handle->ego_entry->next)
1468 {
1469 GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey);
1470 if (0 == GNUNET_memcmp (&ego_pkey, &pubkey))
1471 {
1472 handle->priv_key =
1474 handle->attr_idtoken_list =
1476 handle->attr_userinfo_list =
1478 handle->attr_it =
1480 &handle->priv_key,
1482 handle,
1484 handle,
1486 handle);
1487 return;
1488 }
1489 }
1491 return;
1492 }
1493 }
1494}
1495
1496
1497static void
1498build_redirect (void *cls)
1499{
1500 struct RequestHandle *handle = cls;
1501 struct MHD_Response *resp;
1502 char *redirect_uri;
1503
1504 if (GNUNET_YES == handle->oidc->user_cancelled)
1505 {
1506 if ((NULL != handle->redirect_prefix) &&
1507 (NULL != handle->redirect_suffix) && (NULL != handle->tld))
1508 {
1509 GNUNET_asprintf (&redirect_uri,
1510 "%s.%s/%s?error=%s&error_description=%s&state=%s",
1511 handle->redirect_prefix,
1512 handle->tld,
1513 handle->redirect_suffix,
1514 "access_denied",
1515 "User denied access",
1516 handle->oidc->state);
1517 }
1518 else
1519 {
1520 GNUNET_asprintf (&redirect_uri,
1521 "%s?error=%s&error_description=%s&state=%s",
1522 handle->oidc->redirect_uri,
1523 "access_denied",
1524 "User denied access",
1525 handle->oidc->state);
1526 }
1527 resp = GNUNET_REST_create_response ("");
1528 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1529 "Location",
1530 redirect_uri));
1531 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1533 GNUNET_free (redirect_uri);
1534 return;
1535 }
1537}
1538
1539
1540static void
1542 uint32_t rd_count,
1543 const struct GNUNET_GNSRECORD_Data *rd)
1544{
1545 struct RequestHandle *handle = cls;
1546 char *tmp;
1547 char *tmp_key_str;
1548 char *pos;
1549 struct GNUNET_CRYPTO_PublicKey redirect_zone;
1550
1551 handle->gns_op = NULL;
1552 if (0 == rd_count)
1553 {
1555 handle->edesc =
1556 GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1558 return;
1559 }
1560 for (int i = 0; i < rd_count; i++)
1561 {
1562 if (GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT != rd[i].record_type)
1563 continue;
1564 if (0 != strncmp (rd[i].data, handle->oidc->redirect_uri, rd[i].data_size))
1565 continue;
1566 tmp = GNUNET_strndup (rd[i].data, rd[i].data_size);
1567 if (NULL == strstr (tmp, handle->oidc->client_id))
1568 {
1570 "Redirect uri %s does not contain client_id %s\n",
1571 tmp,
1572 handle->oidc->client_id);
1573 }
1574 else
1575 {
1576 pos = strrchr (tmp, (unsigned char) '.');
1577 if (NULL == pos)
1578 {
1580 "Redirect uri %s contains client_id but is malformed\n",
1581 tmp);
1582 GNUNET_free (tmp);
1583 continue;
1584 }
1585 *pos = '\0';
1586 handle->redirect_prefix = GNUNET_strdup (tmp);
1587 tmp_key_str = pos + 1;
1588 pos = strchr (tmp_key_str, (unsigned char) '/');
1589 if (NULL == pos)
1590 {
1592 "Redirect uri %s contains client_id but is malformed\n",
1593 tmp);
1594 GNUNET_free (tmp);
1595 continue;
1596 }
1597 *pos = '\0';
1598 handle->redirect_suffix = GNUNET_strdup (pos + 1);
1599
1600 GNUNET_STRINGS_string_to_data (tmp_key_str,
1601 strlen (tmp_key_str),
1602 &redirect_zone,
1603 sizeof(redirect_zone));
1604 }
1606 GNUNET_free (tmp);
1607 return;
1608 }
1610 handle->edesc =
1611 GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1613}
1614
1615
1619static void
1620client_redirect (void *cls)
1621{
1622 struct RequestHandle *handle = cls;
1623
1624 /* Lookup client redirect uri to verify request */
1625 handle->gns_op =
1628 &handle->oidc->client_pkey,
1632 handle);
1633}
1634
1635
1636static char *
1637get_url_parameter_copy (const struct RequestHandle *handle, const char *key)
1638{
1639 struct GNUNET_HashCode hc;
1640 char *value;
1641 char *res;
1642
1643 GNUNET_CRYPTO_hash (key, strlen (key), &hc);
1645 ->url_param_map,
1646 &hc))
1647 return NULL;
1648 value =
1649 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, &hc);
1650 if (NULL == value)
1651 return NULL;
1653 return res;
1654}
1655
1656
1663static void
1664build_authz_response (void *cls)
1665{
1666 struct RequestHandle *handle = cls;
1667 struct GNUNET_HashCode cache_key;
1668
1669 char *expected_scope;
1670 char delimiter[] = " ";
1671 char *test;
1672 int number_of_ignored_parameter, iterator;
1673
1674
1675 // REQUIRED value: redirect_uri
1676 handle->oidc->redirect_uri =
1678 if (NULL == handle->oidc->redirect_uri)
1679 {
1681 handle->edesc = GNUNET_strdup ("missing parameter redirect_uri");
1683 return;
1684 }
1685
1686 // REQUIRED value: response_type
1687 handle->oidc->response_type =
1689 if (NULL == handle->oidc->response_type)
1690 {
1692 handle->edesc = GNUNET_strdup ("missing parameter response_type");
1694 return;
1695 }
1696
1697 // REQUIRED value: scope
1699 if (NULL == handle->oidc->scope)
1700 {
1702 handle->edesc = GNUNET_strdup ("missing parameter scope");
1704 return;
1705 }
1706
1707 // OPTIONAL value: nonce
1709
1710 // OPTIONAL value: claims
1712
1713 // TODO check other values if needed
1714 number_of_ignored_parameter =
1715 sizeof(OIDC_ignored_parameter_array) / sizeof(char *);
1716 for (iterator = 0; iterator < number_of_ignored_parameter; iterator++)
1717 {
1719 strlen (OIDC_ignored_parameter_array[iterator]),
1720 &cache_key);
1721 if (GNUNET_YES ==
1723 ->url_param_map,
1724 &cache_key))
1725 {
1727 GNUNET_asprintf (&handle->edesc,
1728 "Server will not handle parameter: %s",
1731 return;
1732 }
1733 }
1734
1735 // We only support authorization code flows.
1736 if (0 != strcmp (handle->oidc->response_type,
1738 {
1740 handle->edesc = GNUNET_strdup ("The authorization server does not support "
1741 "obtaining this authorization code.");
1743 return;
1744 }
1745
1746 // Checks if scope contains 'openid'
1747 expected_scope = GNUNET_strdup (handle->oidc->scope);
1748 test = strtok (expected_scope, delimiter);
1749 while (NULL != test)
1750 {
1751 if (0 == strcmp (OIDC_EXPECTED_AUTHORIZATION_SCOPE, expected_scope))
1752 break;
1753 test = strtok (NULL, delimiter);
1754 }
1755 if (NULL == test)
1756 {
1758 handle->edesc =
1759 GNUNET_strdup ("The requested scope is invalid, unknown, or malformed.");
1761 GNUNET_free (expected_scope);
1762 return;
1763 }
1764
1765 GNUNET_free (expected_scope);
1766 if ((NULL == handle->oidc->login_identity) &&
1767 (GNUNET_NO == handle->oidc->user_cancelled))
1769 else
1771}
1772
1773
1777static void
1778tld_iter (void *cls, const char *section, const char *option, const char *value)
1779{
1780 struct RequestHandle *handle = cls;
1782
1783 if (GNUNET_OK !=
1785 {
1786 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Skipping non key %s\n", value);
1787 return;
1788 }
1789 if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1790 handle->tld = GNUNET_strdup (option + 1);
1791}
1792
1793
1801static void
1803 const char *url,
1804 void *cls)
1805{
1806 struct RequestHandle *handle = cls;
1807 struct EgoEntry *tmp_ego;
1808 const struct GNUNET_CRYPTO_PrivateKey *priv_key;
1810
1812
1813 // RECOMMENDED value: state - REQUIRED for answers
1815
1816 // REQUIRED value: client_id
1818 if (NULL == handle->oidc->client_id)
1819 {
1821 handle->edesc = GNUNET_strdup ("missing parameter client_id");
1822 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1824 return;
1825 }
1826
1827 // OPTIONAL value: code_challenge
1828 handle->oidc->code_challenge = get_url_parameter_copy (handle,
1830 if (NULL == handle->oidc->code_challenge)
1831 {
1833 "OAuth authorization request does not contain PKCE parameters!\n");
1834 }
1835
1836 if (GNUNET_OK !=
1838 &handle->oidc->client_pkey))
1839 {
1841 handle->edesc = GNUNET_strdup ("The client is not authorized to request an "
1842 "authorization code using this method.");
1843 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1845 return;
1846 }
1847
1848 // If we know this identity, translated the corresponding TLD
1849 // TODO: We might want to have a reverse lookup functionality for TLDs?
1850 for (tmp_ego = ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next)
1851 {
1852 priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego);
1854 if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1855 {
1856 handle->tld = GNUNET_strdup (tmp_ego->identifier);
1857 handle->ego_entry = ego_tail;
1858 }
1859 }
1860 if (NULL == handle->tld)
1862 handle);
1863 if (NULL == handle->tld)
1864 handle->tld = GNUNET_strdup (handle->oidc->client_id);
1866}
1867
1868
1876static void
1877login_cont (struct GNUNET_REST_RequestHandle *con_handle,
1878 const char *url,
1879 void *cls)
1880{
1881 struct MHD_Response *resp = GNUNET_REST_create_response ("");
1882 struct RequestHandle *handle = cls;
1883 struct GNUNET_HashCode cache_key;
1884 struct GNUNET_TIME_Absolute *current_time;
1885 struct GNUNET_TIME_Absolute *last_time;
1886 char *cookie;
1887 char *header_val;
1888 json_t *root;
1889 json_error_t error;
1890 json_t *identity;
1891 char term_data[handle->rest_handle->data_size + 1];
1892
1893 term_data[handle->rest_handle->data_size] = '\0';
1894 GNUNET_memcpy (term_data,
1895 handle->rest_handle->data,
1896 handle->rest_handle->data_size);
1897 root = json_loads (term_data, JSON_DECODE_ANY, &error);
1898 identity = json_object_get (root, "identity");
1899 if (! json_is_string (identity))
1900 {
1902 "Error parsing json string from %s\n",
1903 term_data);
1904 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
1905 json_decref (root);
1907 return;
1908 }
1909 GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity));
1910 GNUNET_asprintf (&header_val,
1911 "%s;Max-Age=%d",
1912 cookie,
1914 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1915 "Set-Cookie", header_val));
1916 GNUNET_assert (MHD_NO !=
1917 MHD_add_response_header (resp,
1918 "Access-Control-Allow-Methods",
1919 "POST"));
1920 GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key);
1921
1922 if (0 != strcmp (json_string_value (identity), "Denied"))
1923 {
1924 current_time = GNUNET_new (struct GNUNET_TIME_Absolute);
1925 *current_time = GNUNET_TIME_relative_to_absolute (
1928 last_time =
1930 GNUNET_free (last_time);
1932 &cache_key,
1933 current_time,
1935 }
1936 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1937 GNUNET_free (cookie);
1938 GNUNET_free (header_val);
1939 json_decref (root);
1941}
1942
1943
1944static int
1946 char **client_id,
1947 char **client_secret)
1948{
1949 struct GNUNET_HashCode cache_key;
1950 char *authorization;
1951 char *credentials;
1952 char *basic_authorization;
1953 char *client_id_tmp;
1954 char *pass;
1955
1958 &cache_key);
1960 ->header_param_map,
1961 &cache_key))
1962 return GNUNET_SYSERR;
1963 authorization =
1964 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
1965 &cache_key);
1966
1967 // split header in "Basic" and [content]
1968 credentials = strtok (authorization, " ");
1969 if ((NULL == credentials) || (0 != strcmp ("Basic", credentials)))
1970 return GNUNET_SYSERR;
1971 credentials = strtok (NULL, " ");
1972 if (NULL == credentials)
1973 return GNUNET_SYSERR;
1974 GNUNET_STRINGS_base64_decode (credentials,
1975 strlen (credentials),
1976 (void **) &basic_authorization);
1977
1978 if (NULL == basic_authorization)
1979 return GNUNET_SYSERR;
1980 client_id_tmp = strtok (basic_authorization, ":");
1981 if (NULL == client_id_tmp)
1982 {
1983 GNUNET_free (basic_authorization);
1984 return GNUNET_SYSERR;
1985 }
1986 pass = strtok (NULL, ":");
1987 if (NULL == pass)
1988 {
1989 GNUNET_free (basic_authorization);
1990 return GNUNET_SYSERR;
1991 }
1992 *client_id = strdup (client_id_tmp);
1993 *client_secret = strdup (pass);
1994 GNUNET_free (basic_authorization);
1995 return GNUNET_OK;
1996}
1997
1998
1999static int
2001 char **client_id,
2002 char **client_secret)
2003{
2004 struct GNUNET_HashCode cache_key;
2005 char *client_id_tmp;
2006 char *pass;
2007
2008 GNUNET_CRYPTO_hash ("client_id",
2009 strlen ("client_id"),
2010 &cache_key);
2012 ->url_param_map,
2013 &cache_key))
2014 return GNUNET_SYSERR;
2015 client_id_tmp = GNUNET_CONTAINER_multihashmap_get (
2016 handle->rest_handle->url_param_map,
2017 &cache_key);
2018 if (NULL == client_id_tmp)
2019 return GNUNET_SYSERR;
2020 *client_id = strdup (client_id_tmp);
2021 GNUNET_CRYPTO_hash ("client_secret",
2022 strlen ("client_secret"),
2023 &cache_key);
2025 ->url_param_map,
2026 &cache_key))
2027 {
2028 GNUNET_free (*client_id);
2029 *client_id = NULL;
2030 return GNUNET_SYSERR;
2031 }
2032 pass = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
2033 &cache_key);
2034 if (NULL == pass)
2035 {
2036 GNUNET_free (*client_id);
2037 *client_id = NULL;
2038 return GNUNET_SYSERR;
2039 }
2040 *client_secret = strdup (pass);
2041 return GNUNET_OK;
2042}
2043
2044
2045static int
2047 struct GNUNET_CRYPTO_PublicKey *cid)
2048{
2049 char *expected_pass;
2050 char *received_cid;
2051 char *received_cpw;
2052 char *pkce_cv;
2053
2055 &received_cid,
2056 &received_cpw))
2057 {
2059 "Received client credentials in HTTP AuthZ header\n");
2060 }
2062 &received_cid,
2063 &received_cpw))
2064 {
2066 "Received client credentials in POST body\n");
2067 }
2068 else
2069 {
2072 if (NULL == pkce_cv)
2073 {
2075 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2076 return GNUNET_SYSERR;
2077 }
2078 handle->public_client = GNUNET_YES;
2079 GNUNET_free (pkce_cv);
2081 GNUNET_STRINGS_string_to_data (received_cid,
2082 strlen (received_cid),
2083 cid,
2084 sizeof(struct GNUNET_CRYPTO_PublicKey));
2085 GNUNET_free (received_cid);
2086 return GNUNET_OK;
2087
2088 }
2089
2090 // check client password
2092 "reclaim-rest-plugin",
2093 "OIDC_CLIENT_HMAC_SECRET",
2094 &expected_pass))
2095 {
2096 if (0 != strcmp (expected_pass, received_cpw))
2097 {
2098 GNUNET_free (expected_pass);
2100 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2101 GNUNET_free (received_cpw);
2102 GNUNET_free (received_cid);
2103 return GNUNET_SYSERR;
2104 }
2105 GNUNET_free (expected_pass);
2106 }
2107 else
2108 {
2109 GNUNET_free (received_cpw);
2110 GNUNET_free (received_cid);
2112 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
2113 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2114 return GNUNET_SYSERR;
2115 }
2116 // check client_id
2117 for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
2118 handle->ego_entry = handle->ego_entry->next)
2119 {
2120 if (0 == strcmp (handle->ego_entry->keystring, received_cid))
2121 break;
2122 }
2123 if (NULL == handle->ego_entry)
2124 {
2125 GNUNET_free (received_cpw);
2126 GNUNET_free (received_cid);
2128 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2129 return GNUNET_SYSERR;
2130 }
2131 GNUNET_STRINGS_string_to_data (received_cid,
2132 strlen (received_cid),
2133 cid,
2134 sizeof(struct GNUNET_CRYPTO_PublicKey));
2135
2136 GNUNET_free (received_cpw);
2137 GNUNET_free (received_cid);
2138 return GNUNET_OK;
2139}
2140
2141
2142static const struct EgoEntry *
2144 struct GNUNET_CRYPTO_PublicKey *test_key)
2145{
2146 struct EgoEntry *ego_entry;
2147 struct GNUNET_CRYPTO_PublicKey pub_key;
2148
2149 for (ego_entry = ego_head; NULL != ego_entry;
2150 ego_entry = ego_entry->next)
2151 {
2152 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key);
2153 if (0 == GNUNET_memcmp (&pub_key, test_key))
2154 return ego_entry;
2155 }
2156 return NULL;
2157}
2158
2159
2167static void
2168token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2169 const char *url,
2170 void *cls)
2171{
2172 struct RequestHandle *handle = cls;
2173 const struct EgoEntry *ego_entry = NULL;
2174 struct GNUNET_TIME_Relative expiration_time;
2175 struct GNUNET_RECLAIM_AttributeList *cl = NULL;
2176 struct GNUNET_RECLAIM_PresentationList *pl = NULL;
2178 struct GNUNET_CRYPTO_PublicKey cid;
2179 struct GNUNET_HashCode cache_key;
2180 struct MHD_Response *resp = NULL;
2181 struct GNUNET_CRYPTO_PublicKey issuer;
2182 char *grant_type = NULL;
2183 char *code = NULL;
2184 char *json_response = NULL;
2185 char *id_token = NULL;
2186 char *access_token = NULL;
2187 char *jwa = NULL;
2188 char *jwt_secret = NULL;
2189 char *nonce = NULL;
2190 char *code_verifier = NULL;
2191 json_t *oidc_jwk_tmp = NULL;
2192 char *oidc_jwk_path = NULL;
2193 char *oidc_directory = NULL;
2194 char *tmp_at = NULL;
2195 char *received_cid = NULL;
2196 char *emsg = NULL;
2197
2198 /*
2199 * Check Authorization
2200 */
2202 {
2204 "OIDC authorization for token endpoint failed\n");
2206 return;
2207 }
2209
2210 /*
2211 * Check parameter
2212 */
2213
2214 // TODO Do not allow multiple equal parameter names
2215 // REQUIRED grant_type
2217 strlen (OIDC_GRANT_TYPE_KEY),
2218 &cache_key);
2220 if (NULL == grant_type)
2221 {
2223 handle->edesc = GNUNET_strdup ("missing parameter grant_type");
2224 handle->response_code = MHD_HTTP_BAD_REQUEST;
2226 return;
2227 }
2228
2229 // Check parameter grant_type == "authorization_code"
2230 if (0 != strcmp (OIDC_GRANT_TYPE_VALUE, grant_type))
2231 {
2233 handle->response_code = MHD_HTTP_BAD_REQUEST;
2234 GNUNET_free (grant_type);
2236 return;
2237 }
2238 GNUNET_free (grant_type);
2239 // REQUIRED code
2241 if (NULL == code)
2242 {
2244 handle->edesc = GNUNET_strdup ("missing parameter code");
2245 handle->response_code = MHD_HTTP_BAD_REQUEST;
2247 return;
2248 }
2249 ego_entry = find_ego (handle, &cid);
2250 if (NULL == ego_entry)
2251 {
2253 handle->edesc = GNUNET_strdup ("Unknown client");
2254 handle->response_code = MHD_HTTP_BAD_REQUEST;
2255 GNUNET_free (code);
2257 return;
2258 }
2259
2260 // REQUIRED code verifier
2262 if (NULL == code_verifier)
2263 {
2265 "OAuth authorization request does not contain PKCE parameters!\n");
2266
2267 }
2268
2269 // decode code
2270 if (GNUNET_OK != OIDC_parse_authz_code (received_cid, &cid, code,
2271 code_verifier,
2272 &ticket,
2273 &cl, &pl, &nonce,
2275 &emsg))
2276 {
2278 handle->edesc = emsg;
2279 handle->response_code = MHD_HTTP_BAD_REQUEST;
2280 GNUNET_free (code);
2281 if (NULL != code_verifier)
2282 GNUNET_free (code_verifier);
2284 return;
2285 }
2286 if (NULL != code_verifier)
2287 GNUNET_free (code_verifier);
2288
2289 // create jwt
2291 "reclaim-rest-plugin",
2292 "expiration_time",
2293 &expiration_time))
2294 {
2296 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
2297 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2298 GNUNET_free (code);
2299 if (NULL != nonce)
2300 GNUNET_free (nonce);
2304 return;
2305 }
2306
2307 // Check if HMAC or RSA should be used
2309 "reclaim-rest-plugin",
2310 "oidc_json_web_algorithm",
2311 &jwa))
2312 {
2314 "Could not read OIDC JSON Web Algorithm config attribute."
2315 "Defaulting to RS256.");
2317 }
2318
2320
2321 if (! strcmp (jwa, JWT_ALG_VALUE_RSA))
2322 {
2323 // Replace for now
2324 oidc_jwk_path = get_oidc_jwk_path (cls);
2325 oidc_jwk_tmp = read_jwk_from_file (oidc_jwk_path);
2326
2327 // Check if secret JWK exists
2328 if (! oidc_jwk_tmp)
2329 {
2330 // Generate and save a new key
2331 oidc_jwk_tmp = generate_jwk ();
2332 oidc_directory = get_oidc_dir_path (cls);
2333
2334 // Create new oidc directory
2335 if (GNUNET_OK != GNUNET_DISK_directory_create (oidc_directory))
2336 {
2338 ("Failed to create directory `%s' for storing oidc data\n"),
2339 oidc_directory);
2340 }
2341 else
2342 {
2343 write_jwk_to_file (oidc_jwk_path, oidc_jwk_tmp);
2344 }
2345 }
2346
2347 // Generate oidc token
2348 id_token = OIDC_generate_id_token_rsa (received_cid,
2349 &issuer,
2350 cl,
2351 pl,
2352 &expiration_time,
2353 (NULL != nonce) ? nonce : NULL,
2354 oidc_jwk_tmp);
2355 }
2356 else if (! strcmp (jwa, JWT_ALG_VALUE_HMAC))
2357 {
2358 // TODO OPTIONAL acr,amr,azp
2360 "reclaim-rest-plugin",
2361 "jwt_secret",
2362 &jwt_secret))
2363 {
2365 handle->edesc = GNUNET_strdup ("No signing secret configured!");
2366 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2367 GNUNET_free (code);
2370 if (NULL != nonce)
2371 GNUNET_free (nonce);
2372 GNUNET_free (jwa);
2374 return;
2375 }
2376
2377 id_token = OIDC_generate_id_token_hmac (received_cid,
2378 &issuer,
2379 cl,
2380 pl,
2381 &expiration_time,
2382 (NULL != nonce) ? nonce : NULL,
2383 jwt_secret);
2384
2385 GNUNET_free (jwt_secret);
2386 }
2387 else
2388 {
2389 // TODO: OPTION NOT FOUND ERROR
2390 }
2391 GNUNET_free (jwa);
2392
2393 if (NULL != nonce)
2394 GNUNET_free (nonce);
2395 access_token = OIDC_access_token_new (&ticket, handle->oidc->redirect_uri);
2400 GNUNET_CRYPTO_hash (access_token,
2401 strlen (access_token),
2402 &cache_key);
2414 &cache_key);
2416 &cache_key,
2417 code,
2419 /* If there was a previous code in there, free the old value */
2420 if (NULL != tmp_at)
2421 {
2423 "OIDC access token already issued. Cleanup.\n");
2424 GNUNET_free (tmp_at);
2425 }
2426
2427 OIDC_build_token_response (access_token,
2428 id_token,
2429 &expiration_time,
2430 &json_response);
2431
2432 resp = GNUNET_REST_create_response (json_response);
2433 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2434 "Cache-Control",
2435 "no-store"));
2436 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2437 "Pragma", "no-cache"));
2438 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2439 "Content-Type",
2440 "application/json"));
2441 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2444 GNUNET_free (access_token);
2445 GNUNET_free (json_response);
2446 GNUNET_free (id_token);
2448}
2449
2450
2454static void
2455consume_ticket (void *cls,
2456 const struct GNUNET_CRYPTO_PublicKey *identity,
2457 const struct GNUNET_RECLAIM_Attribute *attr,
2458 const struct GNUNET_RECLAIM_Presentation *presentation)
2459{
2460 struct RequestHandle *handle = cls;
2463 struct MHD_Response *resp;
2464 struct GNUNET_HashCode cache_key;
2465 char *result_str;
2466 char *cached_code;
2467
2468 if (NULL != handle->consume_timeout_op)
2469 GNUNET_SCHEDULER_cancel (handle->consume_timeout_op);
2470 handle->consume_timeout_op = NULL;
2471 handle->idp_op = NULL;
2472
2476 GNUNET_CRYPTO_hash (handle->access_token,
2477 strlen (handle->access_token),
2478 &cache_key);
2480 &cache_key);
2481 if (NULL != cached_code)
2482 {
2485 &cache_key,
2486 cached_code));
2487 GNUNET_free (cached_code);
2488 }
2489
2490
2491 if (NULL == identity)
2492 {
2493 struct GNUNET_CRYPTO_PublicKey issuer;
2494 char *key;
2495 char *tmp = GNUNET_strdup (handle->ticket.gns_name);
2496 GNUNET_assert (NULL != strtok (tmp, "."));
2497 key = strtok (NULL, ".");
2498 GNUNET_assert (NULL != key);
2501 GNUNET_free (tmp);
2502 result_str = OIDC_generate_userinfo (&issuer,
2503 handle->attr_userinfo_list,
2504 handle->presentations);
2505 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2506 resp = GNUNET_REST_create_response (result_str);
2507 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2508 GNUNET_free (result_str);
2510 return;
2511 }
2514 &attr->credential,
2515 attr->type,
2516 attr->data,
2517 attr->data_size);
2518 ale->attribute->id = attr->id;
2519 ale->attribute->flag = attr->flag;
2520 ale->attribute->credential = attr->credential;
2521 GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
2522 handle->attr_userinfo_list->list_tail,
2523 ale);
2524 if (NULL == presentation)
2525 return;
2526 for (atle = handle->presentations->list_head;
2527 NULL != atle; atle = atle->next)
2528 {
2531 &presentation->credential_id))
2532 continue;
2533 break;
2534 }
2535 if (NULL == atle)
2536 {
2539 atle->presentation = GNUNET_RECLAIM_presentation_new (presentation->type,
2540 presentation->data,
2541 presentation->
2542 data_size);
2543 atle->presentation->credential_id = presentation->credential_id;
2544 GNUNET_CONTAINER_DLL_insert (handle->presentations->list_head,
2545 handle->presentations->list_tail,
2546 atle);
2547 }
2548}
2549
2550
2551static void
2552consume_fail (void *cls)
2553{
2554 struct RequestHandle *handle = cls;
2555 struct GNUNET_HashCode cache_key;
2556 struct GNUNET_RECLAIM_AttributeList *cl = NULL;
2557 struct GNUNET_RECLAIM_PresentationList *pl = NULL;
2559 struct GNUNET_CRYPTO_PublicKey cid;
2560 struct MHD_Response *resp;
2561 struct GNUNET_CRYPTO_PublicKey issuer;
2562 char *nonce;
2563 char *cached_code;
2564 char *result_str;
2565 char *received_cid;
2566 char *emsg;
2567 char *tmp;
2568 char *key;
2569
2570 handle->consume_timeout_op = NULL;
2571 if (NULL != handle->idp_op)
2572 GNUNET_RECLAIM_cancel (handle->idp_op);
2573 handle->idp_op = NULL;
2574
2576 "Ticket consumptioned timed out. Using cache...\n");
2577 GNUNET_CRYPTO_hash (handle->access_token,
2578 strlen (handle->access_token),
2579 &cache_key);
2581 &cache_key);
2582 if (NULL == cached_code)
2583 {
2585 handle->edesc = GNUNET_strdup ("No Access Token in cache!");
2586 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2588 return;
2589 }
2595 &cache_key,
2596 cached_code));
2598 GNUNET_STRINGS_string_to_data (received_cid,
2599 strlen (received_cid),
2600 &cid,
2601 sizeof(struct GNUNET_CRYPTO_PublicKey));
2602
2603 // decode code
2604 if (GNUNET_OK != OIDC_parse_authz_code (received_cid, &cid,
2605 cached_code, NULL, &ticket,
2606 &cl, &pl, &nonce,
2608 emsg))
2609 {
2611 handle->edesc = emsg;
2612 handle->response_code = MHD_HTTP_BAD_REQUEST;
2613 GNUNET_free (cached_code);
2614 if (NULL != nonce)
2615 GNUNET_free (nonce);
2617 return;
2618 }
2619
2620 GNUNET_free (cached_code);
2621
2622 tmp = GNUNET_strdup (handle->ticket.gns_name);
2623 GNUNET_assert (NULL != strtok (tmp, "."));
2624 key = strtok (NULL, ".");
2625 GNUNET_assert (NULL != key);
2628 GNUNET_free (tmp);
2629 result_str = OIDC_generate_userinfo (&issuer,
2630 cl,
2631 pl);
2632 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2633 resp = GNUNET_REST_create_response (result_str);
2634 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2635 GNUNET_free (result_str);
2636 GNUNET_free (nonce);
2640}
2641
2642
2650static void
2652 const char *url,
2653 void *cls)
2654{
2655 // TODO expiration time
2656 struct RequestHandle *handle = cls;
2658 char delimiter[] = " ";
2659 struct GNUNET_HashCode cache_key;
2660 char *authorization;
2661 char *authorization_type;
2662 char *authorization_access_token;
2663
2664 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting userinfo\n");
2667 &cache_key);
2669 ->header_param_map,
2670 &cache_key))
2671 {
2673 handle->edesc = GNUNET_strdup ("No Access Token");
2674 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2676 return;
2677 }
2678 authorization =
2679 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
2680 &cache_key);
2681
2682 // split header in "Bearer" and access_token
2683 authorization = GNUNET_strdup (authorization);
2684 authorization_type = strtok (authorization, delimiter);
2685 if ((NULL == authorization_type) ||
2686 (0 != strcmp ("Bearer", authorization_type)))
2687 {
2689 handle->edesc = GNUNET_strdup ("No Access Token");
2690 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2692 GNUNET_free (authorization);
2693 return;
2694 }
2695 authorization_access_token = strtok (NULL, delimiter);
2696 if (NULL == authorization_access_token)
2697 {
2699 handle->edesc = GNUNET_strdup ("Access token missing");
2700 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2702 GNUNET_free (authorization);
2703 return;
2704 }
2705
2706 {
2707 char *rp_uri;
2708 if (GNUNET_OK != OIDC_access_token_parse (authorization_access_token,
2709 &ticket, &rp_uri))
2710 {
2712 handle->edesc = GNUNET_strdup ("The access token is invalid");
2713 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2715 GNUNET_free (authorization);
2716 return;
2717
2718 }
2719 GNUNET_assert (NULL != ticket);
2720 handle->ticket = *ticket;
2722 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Consuming ticket\n");
2723 handle->attr_userinfo_list =
2725 handle->presentations =
2727
2728 /* If the consume takes too long, we use values from the cache */
2729 handle->access_token = GNUNET_strdup (authorization_access_token);
2731 &consume_fail,
2732 handle);
2734 &handle->ticket,
2735 rp_uri,
2737 handle);
2738 GNUNET_free (authorization);
2739 GNUNET_free (rp_uri);
2740 }
2741}
2742
2743
2751static void
2752jwks_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2753 const char *url,
2754 void *cls)
2755{
2756 char *oidc_directory;
2757 char *oidc_jwk_path;
2758 char *oidc_jwk_pub_str;
2759 json_t *oidc_jwk_tmp;
2760 struct MHD_Response *resp;
2761 struct RequestHandle *handle = cls;
2762
2763 oidc_jwk_path = get_oidc_jwk_path (cls);
2764 oidc_jwk_tmp = read_jwk_from_file (oidc_jwk_path);
2765
2766 // Check if secret JWK exists
2767 if (! oidc_jwk_tmp)
2768 {
2769 // Generate and save a new key
2770 oidc_jwk_tmp = generate_jwk ();
2771 oidc_directory = get_oidc_dir_path (cls);
2772
2773 // Create new oidc directory
2774 if (GNUNET_OK != GNUNET_DISK_directory_create (oidc_directory))
2775 {
2777 ("Failed to create directory `%s' for storing oidc data\n"),
2778 oidc_directory);
2779 }
2780 else
2781 {
2782 write_jwk_to_file (oidc_jwk_path, oidc_jwk_tmp);
2783 }
2784 }
2785
2786 // Convert secret JWK to public JWK
2787 jose_jwk_pub (NULL, oidc_jwk_tmp);
2788
2789 // Encode JWK as string and return to API endpoint
2790 oidc_jwk_pub_str = json_dumps (oidc_jwk_tmp, JSON_INDENT (1));
2791 resp = GNUNET_REST_create_response (oidc_jwk_pub_str);
2792 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2793 json_decref (oidc_jwk_tmp);
2794 GNUNET_free (oidc_jwk_pub_str);
2795 GNUNET_free (oidc_jwk_pub_str);
2797}
2798
2799
2832static void
2833list_ego (void *cls,
2834 struct GNUNET_IDENTITY_Ego *ego,
2835 void **ctx,
2836 const char *identifier)
2837{
2838 struct EgoEntry *ego_entry;
2840
2841 if (NULL == ego)
2842 {
2844 return;
2845 }
2847
2848 {
2849 ego_entry = GNUNET_new (struct EgoEntry);
2852 ego_entry->ego = ego;
2853 ego_entry->identifier = GNUNET_strdup (identifier);
2855 ego_tail,
2856 ego_entry);
2857 return;
2858 }
2859 /* Ego renamed or added */
2860 if (identifier != NULL)
2861 {
2862 for (ego_entry = ego_head; NULL != ego_entry;
2863 ego_entry = ego_entry->next)
2864 {
2865 if (ego_entry->ego == ego)
2866 {
2867 /* Rename */
2868 GNUNET_free (ego_entry->identifier);
2869 ego_entry->identifier = GNUNET_strdup (identifier);
2870 break;
2871 }
2872 }
2873 if (NULL == ego_entry)
2874 {
2875 /* Add */
2876 ego_entry = GNUNET_new (struct EgoEntry);
2879 ego_entry->ego = ego;
2880 ego_entry->identifier = GNUNET_strdup (identifier);
2882 ego_tail,
2883 ego_entry);
2884 }
2885 }
2886 else
2887 {
2888 /* Delete */
2889 for (ego_entry = ego_head; NULL != ego_entry;
2890 ego_entry = ego_entry->next)
2891 {
2892 if (ego_entry->ego == ego)
2893 break;
2894 }
2895 if (NULL == ego_entry)
2896 return; /* Not found */
2897
2899 ego_tail,
2900 ego_entry);
2901 GNUNET_free (ego_entry->identifier);
2902 GNUNET_free (ego_entry->keystring);
2903 GNUNET_free (ego_entry);
2904 return;
2905 }
2906}
2907
2908
2909static void
2911 const char *url,
2912 void *cls)
2913{
2914 json_t *oidc_config;
2915 json_t *auth_methods;
2916 json_t *sig_algs;
2917 json_t *scopes;
2918 json_t *response_types;
2919 json_t *sub_types;
2920 json_t *claim_types;
2921 char *oidc_config_str;
2922 struct MHD_Response *resp;
2923 struct RequestHandle *handle = cls;
2924
2925 oidc_config = json_object ();
2926 // FIXME get from config?
2927 json_object_set_new (oidc_config,
2928 "issuer", json_string ("http://localhost:7776"));
2929 json_object_set_new (oidc_config,
2930 "authorization_endpoint",
2931 json_string ("https://api.reclaim/openid/authorize"));
2932 json_object_set_new (oidc_config,
2933 "token_endpoint",
2934 json_string ("http://localhost:7776/openid/token"));
2935 auth_methods = json_array ();
2936 json_array_append_new (auth_methods,
2937 json_string ("client_secret_basic"));
2938 json_array_append_new (auth_methods,
2939 json_string ("client_secret_post"));
2940 json_object_set_new (oidc_config,
2941 "token_endpoint_auth_methods_supported",
2942 auth_methods);
2943 sig_algs = json_array ();
2944 json_array_append_new (sig_algs,
2945 json_string ("HS512"));
2946 json_array_append_new (sig_algs,
2947 json_string ("RS256"));
2948 json_object_set_new (oidc_config,
2949 "id_token_signing_alg_values_supported",
2950 sig_algs);
2951 json_object_set_new (oidc_config,
2952 "jwks_uri",
2953 json_string ("http://localhost:7776/jwks.json"));
2954 json_object_set_new (oidc_config,
2955 "userinfo_endpoint",
2956 json_string ("http://localhost:7776/openid/userinfo"));
2957 scopes = json_array ();
2958 json_array_append_new (scopes,
2959 json_string ("openid"));
2960 json_array_append_new (scopes,
2961 json_string ("profile"));
2962 json_array_append_new (scopes,
2963 json_string ("email"));
2964 json_array_append_new (scopes,
2965 json_string ("address"));
2966 json_array_append_new (scopes,
2967 json_string ("phone"));
2968 json_object_set_new (oidc_config,
2969 "scopes_supported",
2970 scopes);
2971 response_types = json_array ();
2972 json_array_append_new (response_types,
2973 json_string ("code"));
2974 json_object_set_new (oidc_config,
2975 "response_types_supported",
2976 response_types);
2977 sub_types = json_array ();
2978 json_array_append_new (sub_types,
2979 json_string ("public")); /* no pairwise support */
2980 json_object_set_new (oidc_config,
2981 "subject_types_supported",
2982 sub_types);
2983 claim_types = json_array ();
2984 json_array_append_new (claim_types,
2985 json_string ("normal"));
2986 json_array_append_new (claim_types,
2987 json_string ("aggregated"));
2988 json_object_set_new (oidc_config,
2989 "claim_types_supported",
2990 claim_types);
2991 json_object_set_new (oidc_config,
2992 "claims_parameter_supported",
2993 json_boolean (1));
2994 oidc_config_str = json_dumps (oidc_config, JSON_INDENT (1));
2995 resp = GNUNET_REST_create_response (oidc_config_str);
2996 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2997 json_decref (oidc_config);
2998 GNUNET_free (oidc_config_str);
3000}
3001
3002
3010static void
3012 const char *url,
3013 void *cls)
3014{
3015 struct MHD_Response *resp;
3016 struct RequestHandle *handle = cls;
3017
3018 // For now, independent of path return all options
3019 resp = GNUNET_REST_create_response (NULL);
3020 GNUNET_assert (MHD_NO !=
3021 MHD_add_response_header (resp,
3022 "Access-Control-Allow-Methods",
3023 allow_methods));
3024 GNUNET_assert (MHD_NO !=
3025 MHD_add_response_header (resp,
3026 "Access-Control-Allow-Origin",
3027 "*"));
3028 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
3030 return;
3031}
3032
3033
3038 void *proc_cls)
3039{
3040 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
3042 static const struct GNUNET_REST_RequestHandler handlers[] =
3043 { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint },
3044 { MHD_HTTP_METHOD_POST,
3046 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont },
3047 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
3048 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
3049 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
3050 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_JWKS, &jwks_endpoint },
3051 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_OIDC_CONFIG,
3053 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC_CONFIG,
3055 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont },
3057
3058 handle->oidc = GNUNET_new (struct OIDC_Variables);
3059 if (NULL == OIDC_cookie_jar_map)
3061 GNUNET_NO);
3062 if (NULL == oidc_code_cache)
3064 GNUNET_NO);
3065
3066 handle->response_code = 0;
3068 handle->proc_cls = proc_cls;
3069 handle->proc = proc;
3070 handle->rest_handle = rest_handle;
3071 handle->url = GNUNET_strdup (rest_handle->url);
3072 handle->timeout_task =
3076 handle);
3077 if (handle->url[strlen (handle->url) - 1] == '/')
3078 handle->url[strlen (handle->url) - 1] = '\0';
3079 if (GNUNET_NO ==
3080 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
3081 return GNUNET_NO;
3082
3083 return GNUNET_YES;
3084}
3085
3086
3093void *
3095{
3096 static struct Plugin plugin;
3097 struct GNUNET_REST_Plugin *api;
3098
3099 oid_cfg = c;
3100 if (NULL != plugin.cfg)
3101 return NULL; /* can only initialize once! */
3102 memset (&plugin, 0, sizeof(struct Plugin));
3103 plugin.cfg = oid_cfg;
3104 api = GNUNET_new (struct GNUNET_REST_Plugin);
3105 api->cls = &plugin;
3111 "reclaim-rest-plugin",
3112 "OIDC_USERINFO_CONSUME_TIMEOUT",
3114 {
3116 }
3117
3118
3121 "%s, %s, %s, %s, %s",
3122 MHD_HTTP_METHOD_GET,
3123 MHD_HTTP_METHOD_POST,
3124 MHD_HTTP_METHOD_PUT,
3125 MHD_HTTP_METHOD_DELETE,
3126 MHD_HTTP_METHOD_OPTIONS);
3127
3129 _ ("OpenID Connect REST API initialized\n"));
3130 return api;
3131}
3132
3133
3134static int
3135cleanup_hashmap (void *cls, const struct GNUNET_HashCode *key, void *value)
3136{
3138 return GNUNET_YES;
3139}
3140
3141
3142void
3144{
3145 struct Plugin *plugin = api->cls;
3146 struct EgoEntry *ego_entry;
3147
3148 plugin->cfg = NULL;
3149 while (NULL != requests_head)
3151 if (NULL != OIDC_cookie_jar_map)
3152 {
3155 NULL);
3157 }
3158 if (NULL != oidc_code_cache)
3159 {
3162 NULL);
3164 }
3165
3167 if (NULL != gns_handle)
3169 if (NULL != identity_handle)
3171 if (NULL != idp)
3173 while (NULL != (ego_entry = ego_head))
3174 {
3176 ego_tail,
3177 ego_entry);
3178 GNUNET_free (ego_entry->identifier);
3179 GNUNET_free (ego_entry->keystring);
3180 GNUNET_free (ego_entry);
3181 }
3182 GNUNET_free (api);
3184 "OpenID Connect REST plugin is finished\n");
3185}
3186
3187
3188/* end of plugin_rest_openid_connect.c */
struct GNUNET_MQ_MessageHandlers handlers[]
Definition 003.c:1
#define GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT
Used reclaimID OIDC client redirect URIs.
static int ret
Final status code.
Definition gnunet-arm.c:93
static struct GNUNET_TESTING_PluginFunctions * plugin
Plugin to dynamically load a test case.
static gnutls_certificate_credentials_t cred
The credential.
static char * data
The data to insert into the dht.
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_FS_Handle * ctx
static char * filename
struct GNUNET_CRYPTO_PrivateKey pk
Private key from command line option, or NULL.
static char * pkey
Public key of the zone to look in, in ASCII.
static struct GNUNET_CRYPTO_PublicKey pubkey
Public key of the zone to look in.
static unsigned int rd_count
Number of records for currently parsed set.
static char * res
Currently read line or NULL on EOF.
static struct GNUNET_GNSRECORD_Data rd[50]
The record data under a single label.
static char * value
Value of the record to add/remove.
static size_t data_size
Number of bytes in data.
static struct GNUNET_IDENTITY_Handle * identity
Which namespace do we publish to? NULL if we do not publish to a namespace.
static char * attr_name
The attribute.
static struct GNUNET_RECLAIM_Ticket ticket
Ticket to consume.
static char * consume_ticket
Ticket to consume.
static struct GNUNET_RECLAIM_Identifier credential
Credential ID.
static struct GNUNET_VPN_Handle * handle
Handle to vpn service.
Definition gnunet-vpn.c:35
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_time(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time)
Get a configuration value that should be a relative time.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
void GNUNET_CONFIGURATION_iterate_section_values(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, GNUNET_CONFIGURATION_Iterator iter, void *iter_cls)
Iterate over values of a section in the configuration.
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create(const char *dir)
Implementation of "mkdir -p".
Definition disk.c:547
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
void GNUNET_GNS_disconnect(struct GNUNET_GNS_Handle *handle)
Shutdown connection with the GNS service.
Definition gns_api.c:289
struct GNUNET_GNS_LookupRequest * GNUNET_GNS_lookup(struct GNUNET_GNS_Handle *handle, const char *name, const struct GNUNET_CRYPTO_PublicKey *zone, uint32_t type, enum GNUNET_GNS_LocalOptions options, GNUNET_GNS_LookupResultProcessor proc, void *proc_cls)
Perform an asynchronous lookup operation on the GNS.
Definition gns_api.c:421
enum GNUNET_GenericReturnValue GNUNET_GNS_parse_ztld(const char *name, struct GNUNET_CRYPTO_PublicKey *ztld_key)
Try to parse the zTLD into a public key.
void * GNUNET_GNS_lookup_cancel(struct GNUNET_GNS_LookupRequest *lr)
Cancel pending lookup request.
Definition gns_api.c:313
struct GNUNET_GNS_Handle * GNUNET_GNS_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Initialize the connection with the GNS service.
Definition gns_api.c:267
@ GNUNET_GNS_LO_DEFAULT
Defaults, look in cache, then in DHT.
#define GNUNET_GNS_EMPTY_LABEL_AT
String we use to indicate an empty label (top-level entry in the zone).
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition crypto_hash.c:41
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_contains(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Check if the map contains any value under the given key (including values that are NULL).
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE
If a value with the given key exists, replace it.
const struct GNUNET_CRYPTO_PrivateKey * GNUNET_IDENTITY_ego_get_private_key(const struct GNUNET_IDENTITY_Ego *ego)
Obtain the ECC key associated with a ego.
struct GNUNET_IDENTITY_Handle * GNUNET_IDENTITY_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_IDENTITY_Callback cb, void *cb_cls)
Connect to the identity service.
void GNUNET_IDENTITY_disconnect(struct GNUNET_IDENTITY_Handle *h)
Disconnect from identity service.
void GNUNET_IDENTITY_ego_get_public_key(struct GNUNET_IDENTITY_Ego *ego, struct GNUNET_CRYPTO_PublicKey *pk)
Get the identifier (public key) of an ego.
#define GNUNET_log(kind,...)
char * GNUNET_buffer_reap_str(struct GNUNET_Buffer *buf)
Clear the buffer and return the string it contained.
Definition buffer.c:123
char * GNUNET_CRYPTO_public_key_to_string(const struct GNUNET_CRYPTO_PublicKey *key)
Creates a (Base32) string representation of the public key.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_key_get_public(const struct GNUNET_CRYPTO_PrivateKey *privkey, struct GNUNET_CRYPTO_PublicKey *key)
Retrieves the public key representation of a private key.
void GNUNET_buffer_write_fstr(struct GNUNET_Buffer *buf, const char *fmt,...) __attribute__((format(printf
Write a 0-terminated formatted string to a buffer, excluding the 0-terminator.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
void GNUNET_buffer_write_str(struct GNUNET_Buffer *buf, const char *str)
Write a 0-terminated string to a buffer, excluding the 0-terminator.
Definition buffer.c:103
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_public_key_from_string(const char *str, struct GNUNET_CRYPTO_PublicKey *key)
Parses a (Base32) string representation of the public key.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_RECLAIM_id_is_equal(a, b)
struct GNUNET_RECLAIM_Presentation * GNUNET_RECLAIM_presentation_new(uint32_t type, const void *data, size_t data_size)
void GNUNET_RECLAIM_attribute_list_destroy(struct GNUNET_RECLAIM_AttributeList *attrs)
Destroy claim list.
void GNUNET_RECLAIM_credential_list_destroy(struct GNUNET_RECLAIM_CredentialList *credentials)
Destroy credential list.
void GNUNET_RECLAIM_presentation_list_destroy(struct GNUNET_RECLAIM_PresentationList *presentations)
Destroy presentations list.
struct GNUNET_RECLAIM_Attribute * GNUNET_RECLAIM_attribute_new(const char *attr_name, const struct GNUNET_RECLAIM_Identifier *credential, uint32_t type, const void *data, size_t data_size)
Create a new attribute claim.
struct GNUNET_RECLAIM_Credential * GNUNET_RECLAIM_credential_new(const char *name, uint32_t type, const void *data, size_t data_size)
Create a new credential.
void GNUNET_RECLAIM_disconnect(struct GNUNET_RECLAIM_Handle *h)
Disconnect from identity provider service.
struct GNUNET_RECLAIM_Operation * GNUNET_RECLAIM_ticket_consume(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_RECLAIM_Ticket *ticket, const char *rp_uri, GNUNET_RECLAIM_AttributeTicketResult cb, void *cb_cls)
Consumes an issued ticket.
void GNUNET_RECLAIM_cancel(struct GNUNET_RECLAIM_Operation *op)
Cancel an identity provider operation.
void GNUNET_RECLAIM_get_attributes_stop(struct GNUNET_RECLAIM_AttributeIterator *it)
Stops iteration and releases the handle for further calls.
void GNUNET_RECLAIM_get_credentials_next(struct GNUNET_RECLAIM_CredentialIterator *ait)
Calls the record processor specified in GNUNET_RECLAIM_get_credentials_start for the next record.
struct GNUNET_RECLAIM_AttributeIterator * GNUNET_RECLAIM_get_attributes_start(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_CRYPTO_PrivateKey *identity, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_RECLAIM_AttributeResult proc, void *proc_cls, GNUNET_SCHEDULER_TaskCallback finish_cb, void *finish_cb_cls)
List all attributes for a local identity.
void GNUNET_RECLAIM_get_attributes_next(struct GNUNET_RECLAIM_AttributeIterator *it)
Calls the record processor specified in GNUNET_RECLAIM_get_attributes_start for the next record.
struct GNUNET_RECLAIM_Handle * GNUNET_RECLAIM_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the re:claimID service.
struct GNUNET_RECLAIM_Operation * GNUNET_RECLAIM_ticket_issue(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_CRYPTO_PrivateKey *iss, const char *rp_uri, const struct GNUNET_RECLAIM_AttributeList *attrs, GNUNET_RECLAIM_IssueTicketCallback cb, void *cb_cls)
Issues a ticket to a relying party.
void GNUNET_RECLAIM_get_credentials_stop(struct GNUNET_RECLAIM_CredentialIterator *ait)
Stops iteration and releases the handle for further calls.
void GNUNET_RECLAIM_ticket_iteration_stop(struct GNUNET_RECLAIM_TicketIterator *it)
Stops iteration and releases the handle for further calls.
struct GNUNET_RECLAIM_CredentialIterator * GNUNET_RECLAIM_get_credentials_start(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_CRYPTO_PrivateKey *identity, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_RECLAIM_CredentialResult proc, void *proc_cls, GNUNET_SCHEDULER_TaskCallback finish_cb, void *finish_cb_cls)
List all credentials for a local identity.
int GNUNET_REST_handle_request(struct GNUNET_REST_RequestHandle *conn, const struct GNUNET_REST_RequestHandler *handlers, struct GNUNET_REST_RequestHandlerError *err, void *cls)
Definition rest.c:64
void(* GNUNET_REST_ResultProcessor)(void *cls, struct MHD_Response *resp, int status)
Iterator called on obtained result for a REST result.
#define GNUNET_REST_HANDLER_END
struct MHD_Response * GNUNET_REST_create_response(const char *data)
Create REST MHD response.
Definition rest.c:44
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:980
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition scheduler.c:1304
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1277
size_t GNUNET_STRINGS_urlencode(size_t len, const char data[static len], char **out)
url/percent encode (RFC3986).
Definition strings.c:1882
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
Definition strings.c:807
size_t GNUNET_STRINGS_urldecode(const char *data, size_t len, char **out)
url/percent encode (RFC3986).
Definition strings.c:1827
enum GNUNET_GenericReturnValue GNUNET_STRINGS_string_to_data(const char *enc, size_t enclen, void *out, size_t out_size)
Convert CrockfordBase32 encoding back to data.
Definition strings.c:832
size_t GNUNET_STRINGS_base64_decode(const char *data, size_t len, void **output)
Decode from Base64.
Definition strings.c:1720
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition time.c:111
struct GNUNET_TIME_Relative GNUNET_TIME_relative_get_second_(void)
Return relative time of 1s.
Definition time.c:169
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition time.c:316
char * OIDC_generate_id_token_rsa(const char *rp_uri, const struct GNUNET_CRYPTO_PublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations, const struct GNUNET_TIME_Relative *expiration_time, const char *nonce, const json_t *secret_rsa_key)
Create a JWT using RSA256 algorithm from attributes.
char * OIDC_generate_userinfo(const struct GNUNET_CRYPTO_PublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations)
Generate userinfo JSON as string.
int OIDC_parse_authz_code(const char *rp_uri, const struct GNUNET_CRYPTO_PublicKey *cid, const char *code, const char *code_verifier, struct GNUNET_RECLAIM_Ticket *ticket, struct GNUNET_RECLAIM_AttributeList **attrs, struct GNUNET_RECLAIM_PresentationList **presentations, char **nonce_str, enum OIDC_VerificationOptions opts, char **emsg)
Parse reclaim ticket and nonce from authorization code.
char * OIDC_build_authz_code(const struct GNUNET_CRYPTO_PrivateKey *issuer, const struct GNUNET_RECLAIM_Ticket *ticket, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations, const char *nonce_str, const char *code_challenge)
Builds an OIDC authorization code including a reclaim ticket and nonce.
char * OIDC_generate_id_token_hmac(const char *rp_uri, const struct GNUNET_CRYPTO_PublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations, const struct GNUNET_TIME_Relative *expiration_time, const char *nonce, const char *secret_key)
Create a JWT using HMAC (HS256) from attributes.
char * OIDC_access_token_new(const struct GNUNET_RECLAIM_Ticket *ticket, const char *rp_uri)
Generate a new access token.
int OIDC_access_token_parse(const char *token, struct GNUNET_RECLAIM_Ticket **ticket, char **rp_uri)
Parse an access token.
enum GNUNET_GenericReturnValue OIDC_check_scopes_for_claim_request(const char *scopes, const char *attr)
Checks if a claim is implicitly requested through standard scope(s) or explicitly through non-standar...
void OIDC_build_token_response(const char *access_token, const char *id_token, const struct GNUNET_TIME_Relative *expiration_time, char **token_response)
Build a token response for a token request TODO: Maybe we should add the scope here?
#define JWT_ALG_VALUE_RSA
Definition oidc_helper.h:37
@ OIDC_VERIFICATION_NO_CODE_VERIFIER
Do not check code verifier even if expected.
Definition oidc_helper.h:51
@ OIDC_VERIFICATION_DEFAULT
Strict verification.
Definition oidc_helper.h:46
#define JWT_ALG_VALUE_HMAC
Definition oidc_helper.h:36
static struct EgoEntry * ego_tail
Ego list.
#define OIDC_SCOPE_KEY
OIDC scope key.
static void consume_fail(void *cls)
static int attr_in_userinfo_request(struct RequestHandle *handle, const char *attr_name)
#define OIDC_AUTHORIZATION_HEADER_KEY
OIDC cookie header information key.
#define GNUNET_REST_API_NS_OIDC_CONFIG
OIDC config.
static struct GNUNET_RECLAIM_Handle * idp
Identity Provider.
static const char * OIDC_ignored_parameter_array[]
OIDC ignored parameter array.
struct GNUNET_CONTAINER_MultiHashMap * oidc_code_cache
OIDC hashmap for cached access tokens and codes.
static void cookie_identity_interpretation(struct RequestHandle *handle)
Interprets cookie header and pass its identity keystring to handle.
static struct GNUNET_GNS_Handle * gns_handle
GNS handle.
static int write_jwk_to_file(const char *filename, json_t *jwk)
Write the JWK to file.
static char * get_oidc_dir_path(void *cls)
Return the path to the oidc directory path.
#define OIDC_ERROR_KEY_INVALID_REQUEST
OIDC error key for invalid requests.
static int attr_in_claims_request(struct RequestHandle *handle, const char *attr_name, const char *claims_parameter)
void REST_openid_done(struct GNUNET_REST_Plugin *api)
Exit point from the plugin.
static char * get_url_parameter_copy(const struct RequestHandle *handle, const char *key)
#define GNUNET_REST_API_NS_LOGIN
Login namespace.
#define OIDC_ERROR_KEY_UNAUTHORIZED_CLIENT
OIDC error key for unauthorized clients.
#define GNUNET_REST_API_NS_OIDC
REST root namespace.
static void do_timeout(void *cls)
Task run on timeout, sends error message.
static int parse_credentials_post_body(struct RequestHandle *handle, char **client_id, char **client_secret)
static void token_endpoint(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Responds to token url-encoded POST request.
static void userinfo_endpoint(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Responds to userinfo GET and url-encoded POST request.
static void jwks_endpoint(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Responds to /jwks.json.
#define OIDC_ERROR_KEY_UNSUPPORTED_GRANT_TYPE
OIDC error key for unsupported grants.
#define OIDC_ERROR_KEY_INVALID_TOKEN
OIDC error key for invalid tokens.
static struct GNUNET_TIME_Relative consume_timeout
Timeout for consume call on userinfo.
static void oidc_attr_collect(void *cls, const struct GNUNET_CRYPTO_PublicKey *identity, const struct GNUNET_RECLAIM_Attribute *attr)
Collects all attributes for an ego if in scope parameter.
#define OIDC_CLAIMS_KEY
OIDC claims key.
struct GNUNET_CONTAINER_MultiHashMap * OIDC_cookie_jar_map
OIDC hashmap that keeps track of issued cookies.
#define OIDC_ERROR_KEY_SERVER_ERROR
OIDC error key for generic server errors.
#define OIDC_COOKIE_EXPIRATION
OIDC cookie expiration (in seconds)
#define OIDC_ERROR_KEY_ACCESS_DENIED
OIDC error key for denied access.
static void login_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Combines an identity with a login time and responds OK to login request.
static void oidc_cred_collect(void *cls, const struct GNUNET_CRYPTO_PublicKey *identity, const struct GNUNET_RECLAIM_Credential *cred)
Collects all attributes for an ego if in scope parameter.
#define OIDC_COOKIE_HEADER_KEY
OIDC cookie header key.
enum GNUNET_GenericReturnValue REST_openid_process_request(void *plugin, struct GNUNET_REST_RequestHandle *rest_handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function processing the REST call.
#define GNUNET_REST_API_JWKS
JSON Web Keys endpoint.
void * REST_openid_init(const struct GNUNET_CONFIGURATION_Handle *c)
Entry point for the plugin.
#define OIDC_JWK_RSA_FILENAME
OIDC key store file name.
#define ID_REST_STATE_INIT
State while collecting all egos.
#define OIDC_REDIRECT_URI_KEY
OIDC redirect_uri key.
static void do_redirect_error(void *cls)
Task run on error, sends error message and redirects.
static void code_redirect(void *cls)
Checks time and cookie and redirects accordingly.
static struct RequestHandle * requests_head
DLL.
static void options_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Respond to OPTIONS request.
static json_t * read_jwk_from_file(const char *filename)
Read the the JSON Web Key in the given file and return it.
#define OIDC_NONCE_KEY
OIDC nonce key.
#define OIDC_ERROR_KEY_INVALID_CLIENT
OIDC error key for invalid client.
static int parse_credentials_basic_auth(struct RequestHandle *handle, char **client_id, char **client_secret)
#define OIDC_GRANT_TYPE_KEY
OIDC grant_type key.
static int state
The processing state.
#define OIDC_ERROR_KEY_INVALID_COOKIE
OIDC error key for invalid cookies.
static struct EgoEntry * ego_head
Ego list.
static void list_ego(void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *identifier)
If listing is enabled, prints information about the egos.
static void oidc_cred_collect_finished_cb(void *cls)
#define OIDC_CODE_CHALLENGE_KEY
OIDC PKCE code challenge.
static char * allow_methods
HTTP methods allows for this plugin.
static void oidc_config_endpoint(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
static void cleanup_handle(struct RequestHandle *handle)
Cleanup lookup handle.
static const struct EgoEntry * find_ego(struct RequestHandle *handle, struct GNUNET_CRYPTO_PublicKey *test_key)
const struct GNUNET_CONFIGURATION_Handle * oid_cfg
The configuration handle.
#define OIDC_COOKIE_HEADER_ACCESS_DENIED
OIDC cookie header if user cancelled.
#define GNUNET_REST_API_NS_TOKEN
Token endpoint.
#define CONSUME_TIMEOUT
How long to wait for a consume in userinfo endpoint.
#define OIDC_EXPECTED_AUTHORIZATION_SCOPE
OIDC expected scope part while authorizing.
static void build_authz_response(void *cls)
Iteration over all results finished, build final response.
static void do_userinfo_error(void *cls)
Task run on error in userinfo endpoint, sends error header.
static void oidc_ticket_issue_cb(void *cls, const struct GNUNET_RECLAIM_Ticket *ticket, const struct GNUNET_RECLAIM_PresentationList *presentation)
Issues ticket and redirects to relying party with the authorization code as parameter.
#define OIDC_RESPONSE_TYPE_KEY
OIDC response_type key.
static struct RequestHandle * requests_tail
DLL.
#define OIDC_COOKIE_HEADER_INFORMATION_KEY
OIDC cookie header information key.
static struct GNUNET_RECLAIM_AttributeList * attribute_list_merge(struct GNUNET_RECLAIM_AttributeList *list_a, struct GNUNET_RECLAIM_AttributeList *list_b)
#define OIDC_STATE_KEY
OIDC state key.
static struct GNUNET_IDENTITY_Handle * identity_handle
Handle to Identity service.
static void tld_iter(void *cls, const char *section, const char *option, const char *value)
Iterate over tlds in config.
static int check_authorization(struct RequestHandle *handle, struct GNUNET_CRYPTO_PublicKey *cid)
#define OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE
OIDC expected response_type while authorizing.
#define GNUNET_REST_API_NS_USERINFO
UserInfo endpoint.
#define GNUNET_REST_API_NS_AUTHORIZE
Authorize endpoint.
static void oidc_config_cors(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Respond to OPTIONS request.
#define OIDC_CODE_KEY
OIDC code key.
#define OIDC_CODE_VERIFIER_KEY
OIDC PKCE code verifier.
static void authorize_endpoint(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Responds to authorization GET and url-encoded POST request.
static json_t * generate_jwk()
Generate a new RSA JSON Web Key.
#define OIDC_CLIENT_ID_KEY
OIDC client_id key.
#define OIDC_GRANT_TYPE_VALUE
OIDC grant_type key.
json_t * oidc_jwk
The RSA key used by the oidc endpoint.
#define ID_REST_STATE_POST_INIT
Done collecting egos.
static int cleanup_hashmap(void *cls, const struct GNUNET_HashCode *key, void *value)
static void lookup_redirect_uri_result(void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd)
static void build_redirect(void *cls)
static void oidc_attr_collect_finished_cb(void *cls)
#define OIDC_ERROR_KEY_UNSUPPORTED_RESPONSE_TYPE
OIDC error key for unsupported response types.
#define OIDC_ERROR_KEY_INVALID_SCOPE
OIDC error key for invalid scopes.
static void do_error(void *cls)
Task run on error, sends error message.
static void oidc_iteration_error(void *cls)
Does internal server error when iteration failed.
static void client_redirect(void *cls)
Initiate redirect back to client.
static void login_redirect(void *cls)
Redirects to login page stored in configuration file.
static int attr_in_idtoken_request(struct RequestHandle *handle, const char *attr_name)
static char * get_oidc_jwk_path(void *cls)
Return the path to the RSA JWK key file.
#define _(String)
GNU gettext support macro.
Definition platform.h:179
The default namestore ego.
char * identifier
Ego Identifier.
struct EgoEntry * prev
DLL.
char * keystring
Public key string.
struct EgoEntry * next
DLL.
struct GNUNET_IDENTITY_Ego * ego
The Ego.
void * cls
Closure for all of the callbacks.
Dynamically growing buffer.
Internal representation of the hash map.
A private key for an identity as per LSD0001.
An identity key as per LSD0001.
size_t data_size
Number of bytes in data.
Connection to the GNS service.
Definition gns_api.h:36
Handle to a lookup request.
Definition gns_api.c:48
A 512-bit hashcode.
Handle for an ego.
Definition identity.h:37
Handle for the service.
Handle for an operation with the identity service.
Handle for a attribute iterator operation.
struct GNUNET_RECLAIM_Attribute * attribute
The attribute claim.
struct GNUNET_RECLAIM_AttributeListEntry * next
DLL.
A list of GNUNET_RECLAIM_Attribute structures.
struct GNUNET_RECLAIM_AttributeListEntry * list_tail
List tail.
struct GNUNET_RECLAIM_AttributeListEntry * list_head
List head.
const char * name
The name of the attribute.
struct GNUNET_RECLAIM_Identifier credential
Referenced ID of credential (may be GNUNET_RECLAIM_ID_ZERO if self-creded)
struct GNUNET_RECLAIM_Identifier id
ID.
uint32_t type
Type of Claim.
const void * data
Binary value stored as attribute value.
size_t data_size
Number of bytes in data.
Handle for a credential iterator operation.
struct GNUNET_RECLAIM_CredentialListEntry * next
DLL.
struct GNUNET_RECLAIM_Credential * credential
The credential.
A list of GNUNET_RECLAIM_Credential structures.
struct GNUNET_RECLAIM_Identifier id
ID.
Handle to the service.
Handle for an operation with the service.
Definition reclaim_api.c:40
struct GNUNET_RECLAIM_Presentation * presentation
The credential.
struct GNUNET_RECLAIM_PresentationListEntry * next
DLL.
A list of GNUNET_RECLAIM_Presentation structures.
A credential presentation.
const void * data
Binary value stored as presentation value.
uint32_t type
Type/Format of Claim.
struct GNUNET_RECLAIM_Identifier credential_id
The credential id of which this is a presentation.
Handle for a ticket iterator operation.
The authorization ticket.
char gns_name[63 *2+2]
The ticket.
struct returned by the initialization function of the plugin
void * cls
The closure of the plugin.
const char * name
Plugin name.
const char * url
The url as string.
void(* proc)(struct GNUNET_REST_RequestHandle *handle, const char *url, void *cls)
Namespace to handle.
Entry in list of pending tasks.
Definition scheduler.c:136
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds.
OIDC needed variables.
char * login_identity
The identity chosen by the user to login.
char * client_id
The OIDC client id of the RP.
char * response_type
The OIDC response type.
int user_cancelled
User cancelled authorization/login.
char * redirect_uri
The OIDC redirect uri.
char * claims
The OIDC claims.
char * code_challenge
The PKCE code_challenge.
struct GNUNET_CRYPTO_PublicKey client_pkey
The RP client public key.
char * scope
The list of oidc scopes.
char * code_verifier
The PKCE code_verifier.
char * nonce
The OIDC nonce.
char * state
The OIDC state.
Handle for a plugin.
Definition block.c:38
struct GNUNET_BLOCK_PluginFunctions * api
Plugin API.
Definition block.c:47
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
The request handle.
struct GNUNET_RECLAIM_TicketIterator * ticket_it
Ticket iterator.
struct GNUNET_RECLAIM_Ticket ticket
A ticket.
char * emsg
Error response message.
Definition gns_plugin.c:142
struct GNUNET_IDENTITY_Operation * op
IDENTITY Operation.
struct RequestHandle * prev
DLL.
struct GNUNET_RECLAIM_PresentationList * presentations
Presentations.
struct GNUNET_RECLAIM_Operation * idp_op
Idp Operation.
struct GNUNET_RECLAIM_AttributeList * attr_idtoken_list
Attribute claim list for id_token.
int response_code
HTTP response code.
struct EgoEntry * ego_entry
IDENTITY Operation.
struct GNUNET_SCHEDULER_Task * timeout_task
ID of a task associated with the resolution process.
Definition gns_plugin.c:122
struct GNUNET_CRYPTO_PrivateKey priv_key
Pointer to ego private key.
void * proc_cls
The closure of the result processor.
char * access_token
The passed access token.
char * redirect_prefix
The redirect prefix.
struct GNUNET_RECLAIM_AttributeIterator * attr_it
Attribute iterator.
GNUNET_REST_ResultProcessor proc
The plugin result processor.
char * redirect_suffix
The redirect suffix.
struct RequestHandle * next
DLL.
struct GNUNET_RECLAIM_CredentialIterator * cred_it
Credential iterator.
struct GNUNET_REST_RequestHandle * rest_handle
Handle to rest request.
char * url
The URL.
int public_client
Public client.
char * tld
The tld for redirect.
struct OIDC_Variables * oidc
OIDC variables.
struct GNUNET_RECLAIM_AttributeList * attr_userinfo_list
Attribute claim list for userinfo.
struct GNUNET_GNS_LookupRequest * gns_op
GNS lookup op.
struct GNUNET_RECLAIM_CredentialList * credentials
Credentials.
struct GNUNET_SCHEDULER_Task * consume_timeout_op
Timeout task for consume.
struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition gns_plugin.c:117
char * edesc
Error response description.

Function Documentation

◆ cleanup_handle()

static void cleanup_handle ( struct RequestHandle handle)
static

Cleanup lookup handle.

Parameters
handleHandle to clean up

Definition at line 600 of file openid_plugin.c.

601{
602
603 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
604 if (NULL != handle->timeout_task)
605 GNUNET_SCHEDULER_cancel (handle->timeout_task);
606 if (NULL != handle->attr_it)
608 if (NULL != handle->cred_it)
610 if (NULL != handle->ticket_it)
612 if (NULL != handle->idp_op)
614 if (NULL != handle->consume_timeout_op)
615 GNUNET_SCHEDULER_cancel (handle->consume_timeout_op);
616 GNUNET_free (handle->url);
617 GNUNET_free (handle->tld);
618 GNUNET_free (handle->redirect_prefix);
619 GNUNET_free (handle->redirect_suffix);
620 GNUNET_free (handle->emsg);
621 GNUNET_free (handle->edesc);
622 if (NULL != handle->gns_op)
624 if (NULL != handle->oidc)
625 {
626 GNUNET_free (handle->oidc->client_id);
627 GNUNET_free (handle->oidc->login_identity);
628 GNUNET_free (handle->oidc->nonce);
629 GNUNET_free (handle->oidc->redirect_uri);
630 GNUNET_free (handle->oidc->response_type);
631 GNUNET_free (handle->oidc->scope);
632 GNUNET_free (handle->oidc->state);
633 if (NULL != handle->oidc->claims)
634 GNUNET_free (handle->oidc->claims);
635 if (NULL != handle->oidc->code_challenge)
636 GNUNET_free (handle->oidc->code_challenge);
637 GNUNET_free (handle->oidc);
638 }
639 if (NULL!=handle->attr_idtoken_list)
641 if (NULL!=handle->attr_userinfo_list)
642 GNUNET_RECLAIM_attribute_list_destroy (handle->attr_userinfo_list);
643 if (NULL!=handle->credentials)
645 if (NULL!=handle->presentations)
649 handle);
650 if (NULL != handle->access_token)
651 GNUNET_free (handle->access_token);
653}

References GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_GNS_lookup_cancel(), GNUNET_log, GNUNET_RECLAIM_attribute_list_destroy(), GNUNET_RECLAIM_cancel(), GNUNET_RECLAIM_credential_list_destroy(), GNUNET_RECLAIM_get_attributes_stop(), GNUNET_RECLAIM_get_credentials_stop(), GNUNET_RECLAIM_presentation_list_destroy(), GNUNET_RECLAIM_ticket_iteration_stop(), GNUNET_SCHEDULER_cancel(), handle, requests_head, and requests_tail.

Referenced by build_redirect(), consume_fail(), consume_ticket(), do_error(), do_redirect_error(), do_userinfo_error(), jwks_endpoint(), login_cont(), login_redirect(), oidc_config_cors(), oidc_config_endpoint(), oidc_ticket_issue_cb(), options_cont(), REST_openid_done(), and token_endpoint().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_error()

static void do_error ( void *  cls)
static

Task run on error, sends error message.

Cleans up everything.

Parameters
clsthe struct RequestHandle

Definition at line 662 of file openid_plugin.c.

663{
664 struct RequestHandle *handle = cls;
665 struct MHD_Response *resp;
666 char *json_error;
667
668 GNUNET_asprintf (&json_error,
669 "{ \"error\" : \"%s\", \"error_description\" : \"%s\"%s%s%s}",
670 handle->emsg,
671 (NULL != handle->edesc) ? handle->edesc : "",
672 (NULL != handle->oidc->state) ? ", \"state\":\"" : "",
673 (NULL != handle->oidc->state) ? handle->oidc->state : "",
674 (NULL != handle->oidc->state) ? "\"" : "");
675 if (0 == handle->response_code)
676 handle->response_code = MHD_HTTP_BAD_REQUEST;
677 resp = GNUNET_REST_create_response (json_error);
678 if (MHD_HTTP_UNAUTHORIZED == handle->response_code)
679 GNUNET_assert (MHD_NO !=
680 MHD_add_response_header (resp,
681 MHD_HTTP_HEADER_WWW_AUTHENTICATE,
682 "Basic"));
683 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
684 MHD_HTTP_HEADER_CONTENT_TYPE,
685 "application/json"));
686 handle->proc (handle->proc_cls, resp, handle->response_code);
688 GNUNET_free (json_error);
689}

References cleanup_handle(), GNUNET_asprintf(), GNUNET_assert, GNUNET_free, GNUNET_REST_create_response(), and handle.

Referenced by authorize_endpoint(), build_authz_response(), consume_fail(), do_timeout(), get_oidc_dir_path(), login_redirect(), oidc_iteration_error(), and token_endpoint().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_userinfo_error()

static void do_userinfo_error ( void *  cls)
static

Task run on error in userinfo endpoint, sends error header.

Cleans up everything

Parameters
clsthe struct RequestHandle

Definition at line 699 of file openid_plugin.c.

700{
701 struct RequestHandle *handle = cls;
702 struct MHD_Response *resp;
703 char *error;
704
706 "Error: %s\n", handle->edesc);
707 GNUNET_asprintf (&error,
708 "error=\"%s\", error_description=\"%s\"",
709 handle->emsg,
710 (NULL != handle->edesc) ? handle->edesc : "");
711 resp = GNUNET_REST_create_response ("");
712 GNUNET_assert (MHD_NO !=
713 MHD_add_response_header (resp,
714 MHD_HTTP_HEADER_WWW_AUTHENTICATE,
715 "Bearer"));
716 handle->proc (handle->proc_cls, resp, handle->response_code);
718 GNUNET_free (error);
719}

References cleanup_handle(), GNUNET_asprintf(), GNUNET_assert, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_REST_create_response(), and handle.

Referenced by consume_fail(), and userinfo_endpoint().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_redirect_error()

static void do_redirect_error ( void *  cls)
static

Task run on error, sends error message and redirects.

Cleans up everything.

Parameters
clsthe struct RequestHandle

Definition at line 728 of file openid_plugin.c.

729{
730 struct RequestHandle *handle = cls;
731 struct MHD_Response *resp;
732 char *redirect;
733
734 GNUNET_asprintf (&redirect,
735 "%s?error=%s&error_description=%s%s%s",
736 handle->oidc->redirect_uri,
737 handle->emsg,
738 handle->edesc,
739 (NULL != handle->oidc->state) ? "&state=" : "",
740 (NULL != handle->oidc->state) ? handle->oidc->state : "");
741 resp = GNUNET_REST_create_response ("");
742 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
743 "Location", redirect));
744 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
746 GNUNET_free (redirect);
747}

References cleanup_handle(), GNUNET_asprintf(), GNUNET_assert, GNUNET_free, GNUNET_REST_create_response(), and handle.

Referenced by build_authz_response(), code_redirect(), lookup_redirect_uri_result(), oidc_attr_collect_finished_cb(), and oidc_ticket_issue_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_timeout()

static void do_timeout ( void *  cls)
static

Task run on timeout, sends error message.

Cleans up everything.

Parameters
clsthe struct RequestHandle

Definition at line 756 of file openid_plugin.c.

757{
758 struct RequestHandle *handle = cls;
759
760 handle->timeout_task = NULL;
762}

References do_error(), and handle.

Referenced by REST_openid_process_request().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ options_cont()

static void options_cont ( struct GNUNET_REST_RequestHandle con_handle,
const char *  url,
void *  cls 
)
static

Respond to OPTIONS request.

Parameters
con_handlethe connection handle
urlthe url
clsthe RequestHandle

Definition at line 773 of file openid_plugin.c.

776{
777 struct MHD_Response *resp;
778 struct RequestHandle *handle = cls;
779
780 // For now, independent of path return all options
781 resp = GNUNET_REST_create_response (NULL);
782 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
783 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
785 return;
786}

References allow_methods, cleanup_handle(), GNUNET_REST_create_response(), and handle.

Referenced by REST_openid_process_request().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cookie_identity_interpretation()

static void cookie_identity_interpretation ( struct RequestHandle handle)
static

Interprets cookie header and pass its identity keystring to handle.

Definition at line 793 of file openid_plugin.c.

794{
795 struct GNUNET_HashCode cache_key;
796 char *cookies;
797 struct GNUNET_TIME_Absolute current_time, *relog_time;
798 char delimiter[] = "; ";
799 char *tmp_cookies;
800 char *token;
801 char *value;
802
803 // gets identity of login try with cookie
805 strlen (OIDC_COOKIE_HEADER_KEY),
806 &cache_key);
808 ->header_param_map,
809 &cache_key))
810 {
811 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No cookie found\n");
812 return;
813 }
814 // splits cookies and find 'Identity' cookie
815 tmp_cookies =
816 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
817 &cache_key);
818 cookies = GNUNET_strdup (tmp_cookies);
819 token = strtok (cookies, delimiter);
820 handle->oidc->user_cancelled = GNUNET_NO;
821 handle->oidc->login_identity = NULL;
822 if (NULL == token)
823 {
825 "Unable to parse cookie: %s\n",
826 cookies);
827 GNUNET_free (cookies);
828 return;
829 }
830
831 while (NULL != token)
832 {
833 if (0 == strcmp (token, OIDC_COOKIE_HEADER_ACCESS_DENIED))
834 {
835 handle->oidc->user_cancelled = GNUNET_YES;
836 GNUNET_free (cookies);
837 return;
838 }
839 if (NULL != strstr (token, OIDC_COOKIE_HEADER_INFORMATION_KEY))
840 break;
841 token = strtok (NULL, delimiter);
842 }
843 if (NULL == token)
844 {
846 "No cookie value to process: %s\n",
847 cookies);
848 GNUNET_free (cookies);
849 return;
850 }
851 GNUNET_CRYPTO_hash (token, strlen (token), &cache_key);
852 if (GNUNET_NO ==
854 {
855 GNUNET_log (
857 "Found cookie `%s', but no corresponding expiration entry present...\n",
858 token);
859 GNUNET_free (cookies);
860 return;
861 }
862 relog_time =
864 current_time = GNUNET_TIME_absolute_get ();
865 // 30 min after old login -> redirect to login
866 if (current_time.abs_value_us > relog_time->abs_value_us)
867 {
869 "Found cookie `%s', but it is expired.\n",
870 token);
871 GNUNET_free (cookies);
872 return;
873 }
875 GNUNET_assert (NULL != value);
876 handle->oidc->login_identity = GNUNET_strdup (value);
877 GNUNET_free (cookies);
878}

References GNUNET_TIME_Absolute::abs_value_us, GNUNET_assert, GNUNET_CONTAINER_multihashmap_contains(), GNUNET_CONTAINER_multihashmap_get(), GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_NO, GNUNET_strdup, GNUNET_TIME_absolute_get(), GNUNET_YES, handle, OIDC_COOKIE_HEADER_ACCESS_DENIED, OIDC_COOKIE_HEADER_INFORMATION_KEY, OIDC_COOKIE_HEADER_KEY, OIDC_cookie_jar_map, and value.

Referenced by authorize_endpoint().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ read_jwk_from_file()

static json_t * read_jwk_from_file ( const char *  filename)
static

Read the the JSON Web Key in the given file and return it.

Return NULL and emit warning if JSON can not be decoded or the key is invalid

Parameters
filenamethe file to read the JWK from
Returns
json_t* the reed JWK

Definition at line 890 of file openid_plugin.c.

891{
892 json_t *jwk;
893 json_error_t error;
894
895 jwk = json_load_file (filename, JSON_DECODE_ANY, &error);
896
897 if (! jwk)
898 {
900 ("Could not read OIDC RSA key from config file; %s\n"),
901 error.text);
902 }
903
904 return jwk;
905}

References filename, GNUNET_ERROR_TYPE_WARNING, and GNUNET_log.

Referenced by jwks_endpoint(), and token_endpoint().

Here is the caller graph for this function:

◆ write_jwk_to_file()

static int write_jwk_to_file ( const char *  filename,
json_t *  jwk 
)
static

Write the JWK to file.

If unsuccessful emit warning

Parameters
filenamethe name of the file the JWK is written to
jwkthe JWK that is going to be written
Returns
int Return GNUNET_OK if write is successful

Definition at line 916 of file openid_plugin.c.

918{
919 if (json_dump_file (jwk, filename, JSON_INDENT (2)))
920 {
922 ("Could not write OIDC RSA key to file %s\n"),
923 filename);
925 }
926 else
927 return GNUNET_OK;
928}

References filename, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, and GNUNET_OK.

Referenced by jwks_endpoint(), and token_endpoint().

Here is the caller graph for this function:

◆ generate_jwk()

static json_t * generate_jwk ( )
static

Generate a new RSA JSON Web Key.

Returns
json_t* the generated JWK

Definition at line 937 of file openid_plugin.c.

938{
939 json_t *jwk;
940 jwk = json_pack ("{s:s,s:i}", "kty", "RSA", "bits", 2048);
941 jose_jwk_gen (NULL, jwk);
942 json_incref (jwk);
943 return jwk;
944}

Referenced by jwks_endpoint(), and token_endpoint().

Here is the caller graph for this function:

◆ get_oidc_dir_path()

static char * get_oidc_dir_path ( void *  cls)
static

Return the path to the oidc directory path.

Parameters
clsthe RequestHandle

Definition at line 953 of file openid_plugin.c.

954{
955 char *oidc_directory;
956 struct RequestHandle *handle = cls;
957
958 // Read OIDC directory from config
960 "reclaim-rest-plugin",
961 "oidc_dir",
962 &oidc_directory))
963 {
964 // Could not read Config file
966 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
967 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
969 return NULL;
970 }
971
972 return oidc_directory;
973}

References do_error(), GNUNET_CONFIGURATION_get_value_filename(), GNUNET_OK, GNUNET_SCHEDULER_add_now(), GNUNET_strdup, handle, oid_cfg, and OIDC_ERROR_KEY_SERVER_ERROR.

Referenced by get_oidc_jwk_path(), jwks_endpoint(), and token_endpoint().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_oidc_jwk_path()

static char * get_oidc_jwk_path ( void *  cls)
static

Return the path to the RSA JWK key file.

Parameters
clsthe RequestHandle

Definition at line 982 of file openid_plugin.c.

983{
984 char *oidc_directory;
985 char *oidc_jwk_path;
986
987 oidc_directory = get_oidc_dir_path (cls);
988
989 // Create path to file
990 GNUNET_asprintf (&oidc_jwk_path, "%s/%s", oidc_directory,
992
993 return oidc_jwk_path;
994}

References get_oidc_dir_path(), GNUNET_asprintf(), and OIDC_JWK_RSA_FILENAME.

Referenced by jwks_endpoint(), and token_endpoint().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ login_redirect()

static void login_redirect ( void *  cls)
static

Redirects to login page stored in configuration file.

Definition at line 1001 of file openid_plugin.c.

1002{
1003 char *login_base_url;
1004 char *new_redirect;
1005 char *tmp;
1006 struct MHD_Response *resp;
1007 struct GNUNET_Buffer buf = { 0 };
1008 struct RequestHandle *handle = cls;
1009
1011 "reclaim-rest-plugin",
1012 "address",
1013 &login_base_url))
1014 {
1015 GNUNET_buffer_write_str (&buf, login_base_url);
1017 "?%s=%s",
1019 handle->oidc->response_type);
1021 "&%s=%s",
1023 handle->oidc->client_id);
1024 GNUNET_STRINGS_urlencode (strlen (handle->oidc->redirect_uri),
1025 handle->oidc->redirect_uri,
1026 &tmp);
1028 "&%s=%s",
1030 tmp);
1031 GNUNET_free (tmp);
1032 GNUNET_STRINGS_urlencode (strlen (handle->oidc->scope),
1033 handle->oidc->scope,
1034 &tmp);
1036 "&%s=%s",
1038 tmp);
1039 GNUNET_free (tmp);
1040 if (NULL != handle->oidc->state)
1041 {
1042 GNUNET_STRINGS_urlencode (strlen (handle->oidc->state),
1043 handle->oidc->state,
1044 &tmp);
1046 "&%s=%s",
1048 handle->oidc->state);
1049 GNUNET_free (tmp);
1050 }
1051 if (NULL != handle->oidc->code_challenge)
1052 {
1054 "&%s=%s",
1056 handle->oidc->code_challenge);
1057 }
1058 if (NULL != handle->oidc->nonce)
1059 {
1061 "&%s=%s",
1063 handle->oidc->nonce);
1064 }
1065 if (NULL != handle->oidc->claims)
1066 {
1067 GNUNET_STRINGS_urlencode (strlen (handle->oidc->claims),
1068 handle->oidc->claims,
1069 &tmp);
1071 "&%s=%s",
1073 tmp);
1074 GNUNET_free (tmp);
1075 }
1076 new_redirect = GNUNET_buffer_reap_str (&buf);
1077 resp = GNUNET_REST_create_response ("");
1078 MHD_add_response_header (resp, "Location", new_redirect);
1079 GNUNET_free (login_base_url);
1080 }
1081 else
1082 {
1084 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
1085 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1087 return;
1088 }
1089 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1090 GNUNET_free (new_redirect);
1092}

References cleanup_handle(), do_error(), GNUNET_buffer_reap_str(), GNUNET_buffer_write_fstr(), GNUNET_buffer_write_str(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_free, GNUNET_OK, GNUNET_REST_create_response(), GNUNET_SCHEDULER_add_now(), GNUNET_strdup, GNUNET_STRINGS_urlencode(), handle, oid_cfg, OIDC_CLAIMS_KEY, OIDC_CLIENT_ID_KEY, OIDC_CODE_CHALLENGE_KEY, OIDC_ERROR_KEY_SERVER_ERROR, OIDC_NONCE_KEY, OIDC_REDIRECT_URI_KEY, OIDC_RESPONSE_TYPE_KEY, OIDC_SCOPE_KEY, and OIDC_STATE_KEY.

Referenced by build_authz_response(), and code_redirect().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ oidc_iteration_error()

static void oidc_iteration_error ( void *  cls)
static

Does internal server error when iteration failed.

Definition at line 1099 of file openid_plugin.c.

1100{
1101 struct RequestHandle *handle = cls;
1102
1104 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1106}

References do_error(), GNUNET_SCHEDULER_add_now(), GNUNET_strdup, handle, and OIDC_ERROR_KEY_SERVER_ERROR.

Referenced by code_redirect(), and oidc_attr_collect_finished_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ oidc_ticket_issue_cb()

static void oidc_ticket_issue_cb ( void *  cls,
const struct GNUNET_RECLAIM_Ticket ticket,
const struct GNUNET_RECLAIM_PresentationList presentation 
)
static

Issues ticket and redirects to relying party with the authorization code as parameter.

Otherwise redirects with error

Definition at line 1114 of file openid_plugin.c.

1118{
1119 struct RequestHandle *handle = cls;
1120 struct MHD_Response *resp;
1121 char *ticket_str;
1122 char *redirect_uri;
1123 char *code_string;
1124
1125 handle->idp_op = NULL;
1126 if (NULL == ticket)
1127 {
1129 handle->edesc = GNUNET_strdup ("Server cannot generate ticket.");
1131 return;
1132 }
1133 handle->ticket = *ticket;
1134 ticket_str =
1136 sizeof(struct GNUNET_RECLAIM_Ticket));
1137 code_string = OIDC_build_authz_code (&handle->priv_key,
1138 &handle->ticket,
1139 handle->attr_idtoken_list,
1140 presentation,
1141 handle->oidc->nonce,
1142 handle->oidc->code_challenge);
1143 if ((NULL != handle->redirect_prefix) && (NULL != handle->redirect_suffix) &&
1144 (NULL != handle->tld))
1145 {
1146 GNUNET_asprintf (&redirect_uri,
1147 "%s.%s/%s%s%s=%s&state=%s",
1148 handle->redirect_prefix,
1149 handle->tld,
1150 handle->redirect_suffix,
1151 (NULL == strchr (handle->redirect_suffix, '?') ? "?" :
1152 "&"),
1153 handle->oidc->response_type,
1154 code_string,
1155 handle->oidc->state);
1156 }
1157 else
1158 {
1159 GNUNET_asprintf (&redirect_uri,
1160 "%s%s%s=%s&state=%s",
1161 handle->oidc->redirect_uri,
1162 (NULL == strchr (handle->oidc->redirect_uri, '?') ? "?" :
1163 "&"),
1164 handle->oidc->response_type,
1165 code_string,
1166 handle->oidc->state);
1167 }
1168 resp = GNUNET_REST_create_response ("");
1169 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1170 "Location", redirect_uri));
1171 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1173 GNUNET_free (redirect_uri);
1174 GNUNET_free (ticket_str);
1175 GNUNET_free (code_string);
1176}

References cleanup_handle(), do_redirect_error(), GNUNET_asprintf(), GNUNET_assert, GNUNET_free, GNUNET_REST_create_response(), GNUNET_SCHEDULER_add_now(), GNUNET_strdup, GNUNET_STRINGS_data_to_string_alloc(), handle, OIDC_build_authz_code(), OIDC_ERROR_KEY_SERVER_ERROR, and ticket.

Referenced by oidc_cred_collect_finished_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ attribute_list_merge()

static struct GNUNET_RECLAIM_AttributeList * attribute_list_merge ( struct GNUNET_RECLAIM_AttributeList list_a,
struct GNUNET_RECLAIM_AttributeList list_b 
)
static

Attribute already in list

Attribute already in list

Definition at line 1180 of file openid_plugin.c.

1182{
1183 struct GNUNET_RECLAIM_AttributeList *merged_list;
1187
1188 merged_list = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
1189 for (le_a = list_a->list_head; NULL != le_a; le_a = le_a->next)
1190 {
1193 &le_a->attribute->
1194 credential,
1195 le_a->attribute->type,
1196 le_a->attribute->data,
1197 le_a->attribute->data_size);
1198 le_m->attribute->id = le_a->attribute->id;
1199 le_m->attribute->flag = le_a->attribute->flag;
1200 le_m->attribute->credential = le_a->attribute->credential;
1202 merged_list->list_tail,
1203 le_m);
1204 }
1205 le_m = NULL;
1206 for (le_b = list_b->list_head; NULL != le_b; le_b = le_b->next)
1207 {
1208 for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1209 {
1211 &le_b->attribute->id))
1212 break;
1213 }
1214 if (NULL != le_m)
1215 continue;
1218 &le_b->attribute->
1219 credential,
1220 le_b->attribute->type,
1221 le_b->attribute->data,
1222 le_b->attribute->data_size);
1223 le_m->attribute->id = le_b->attribute->id;
1224 le_m->attribute->flag = le_b->attribute->flag;
1225 le_m->attribute->credential = le_b->attribute->credential;
1227 merged_list->list_tail,
1228 le_m);
1229 }
1230 return merged_list;
1231}

References GNUNET_RECLAIM_AttributeListEntry::attribute, credential, GNUNET_RECLAIM_Attribute::credential, GNUNET_RECLAIM_Attribute::data, GNUNET_RECLAIM_Attribute::data_size, GNUNET_RECLAIM_Attribute::flag, GNUNET_CONTAINER_DLL_insert, GNUNET_new, GNUNET_RECLAIM_attribute_new(), GNUNET_RECLAIM_id_is_equal, GNUNET_YES, GNUNET_RECLAIM_Attribute::id, GNUNET_RECLAIM_AttributeList::list_head, GNUNET_RECLAIM_AttributeList::list_tail, GNUNET_RECLAIM_Attribute::name, GNUNET_RECLAIM_AttributeListEntry::next, and GNUNET_RECLAIM_Attribute::type.

Referenced by oidc_cred_collect_finished_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ oidc_cred_collect_finished_cb()

static void oidc_cred_collect_finished_cb ( void *  cls)
static

Definition at line 1235 of file openid_plugin.c.

1236{
1237 struct RequestHandle *handle = cls;
1238 struct GNUNET_RECLAIM_AttributeList *merged_list;
1240
1241 handle->cred_it = NULL;
1242 merged_list = attribute_list_merge (handle->attr_idtoken_list,
1243 handle->attr_userinfo_list);
1244 for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1246 "List Attribute in ticket to issue: %s\n",
1247 le_m->attribute->name);
1249 &handle->priv_key,
1250 handle->oidc->client_id,
1251 merged_list,
1253 handle);
1255}

References GNUNET_RECLAIM_AttributeListEntry::attribute, attribute_list_merge(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_RECLAIM_attribute_list_destroy(), GNUNET_RECLAIM_ticket_issue(), handle, idp, GNUNET_RECLAIM_AttributeList::list_head, GNUNET_RECLAIM_Attribute::name, GNUNET_RECLAIM_AttributeListEntry::next, and oidc_ticket_issue_cb().

Referenced by oidc_attr_collect_finished_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ oidc_cred_collect()

static void oidc_cred_collect ( void *  cls,
const struct GNUNET_CRYPTO_PublicKey identity,
const struct GNUNET_RECLAIM_Credential cred 
)
static

Collects all attributes for an ego if in scope parameter.

Credential already in list

Credential matches for attribute, add

Definition at line 1262 of file openid_plugin.c.

1265{
1266 struct RequestHandle *handle = cls;
1269
1270 for (ale = handle->credentials->list_head; NULL != ale; ale = ale->next)
1271 {
1273 &cred->id))
1274 continue;
1277 return;
1278 }
1279
1280 for (le = handle->attr_idtoken_list->list_head; NULL != le; le = le->next)
1281 {
1283 &cred->id))
1284 continue;
1288 cred->type,
1289 cred->data,
1290 cred->data_size);
1291 GNUNET_CONTAINER_DLL_insert (handle->credentials->list_head,
1292 handle->credentials->list_tail,
1293 ale);
1294 }
1296}

References GNUNET_RECLAIM_AttributeListEntry::attribute, cred, GNUNET_RECLAIM_Attribute::credential, GNUNET_RECLAIM_CredentialListEntry::credential, GNUNET_CONTAINER_DLL_insert, GNUNET_new, GNUNET_NO, GNUNET_RECLAIM_credential_new(), GNUNET_RECLAIM_get_credentials_next(), GNUNET_RECLAIM_id_is_equal, handle, GNUNET_RECLAIM_Identifier::id, GNUNET_RECLAIM_Credential::id, GNUNET_RECLAIM_AttributeListEntry::next, and GNUNET_RECLAIM_CredentialListEntry::next.

Referenced by oidc_attr_collect_finished_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ oidc_attr_collect_finished_cb()

static void oidc_attr_collect_finished_cb ( void *  cls)
static

Definition at line 1300 of file openid_plugin.c.

1301{
1302 struct RequestHandle *handle = cls;
1303
1304 handle->attr_it = NULL;
1305 handle->ticket_it = NULL;
1306 if (NULL == handle->attr_idtoken_list->list_head)
1307 {
1309 handle->edesc = GNUNET_strdup ("The requested scope is not available.");
1311 return;
1312 }
1313 handle->credentials = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
1314 handle->cred_it =
1316 &handle->priv_key,
1318 handle,
1320 handle,
1322 handle);
1323
1324}

References do_redirect_error(), GNUNET_new, GNUNET_RECLAIM_get_credentials_start(), GNUNET_SCHEDULER_add_now(), GNUNET_strdup, handle, idp, oidc_cred_collect(), oidc_cred_collect_finished_cb(), OIDC_ERROR_KEY_INVALID_SCOPE, and oidc_iteration_error().

Referenced by code_redirect().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ attr_in_claims_request()

static int attr_in_claims_request ( struct RequestHandle handle,
const char *  attr_name,
const char *  claims_parameter 
)
static

Check if attribute is requested through a scope

Try claims parameter if not in scope

Definition at line 1328 of file openid_plugin.c.

1331{
1332 int ret = GNUNET_NO;
1333 json_t *root;
1334 json_error_t error;
1335 json_t *claims_j;
1336 const char *key;
1337 json_t *value;
1338
1341 attr_name))
1342 return GNUNET_YES;
1343
1345 if (NULL != handle->oidc->claims)
1346 {
1347 root = json_loads (handle->oidc->claims, JSON_DECODE_ANY, &error);
1348 claims_j = json_object_get (root, claims_parameter);
1349 /* obj is a JSON object */
1350 if (NULL != claims_j)
1351 {
1352 json_object_foreach (claims_j, key, value) {
1353 if (0 != strcmp (attr_name, key))
1354 continue;
1355 ret = GNUNET_YES;
1356 break;
1357 }
1358 }
1359 json_decref (root);
1360 }
1361 return ret;
1362}

References attr_name, GNUNET_NO, GNUNET_YES, handle, key, OIDC_check_scopes_for_claim_request(), ret, and value.

Referenced by attr_in_idtoken_request(), and attr_in_userinfo_request().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ attr_in_idtoken_request()

static int attr_in_idtoken_request ( struct RequestHandle handle,
const char *  attr_name 
)
static

Definition at line 1366 of file openid_plugin.c.

1368{
1369 return attr_in_claims_request (handle, attr_name, "id_token");
1370}

References attr_in_claims_request(), attr_name, and handle.

Referenced by oidc_attr_collect().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ attr_in_userinfo_request()

static int attr_in_userinfo_request ( struct RequestHandle handle,
const char *  attr_name 
)
static

Definition at line 1374 of file openid_plugin.c.

1376{
1377 return attr_in_claims_request (handle, attr_name, "userinfo");
1378}

References attr_in_claims_request(), attr_name, and handle.

Referenced by oidc_attr_collect().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ oidc_attr_collect()

static void oidc_attr_collect ( void *  cls,
const struct GNUNET_CRYPTO_PublicKey identity,
const struct GNUNET_RECLAIM_Attribute attr 
)
static

Collects all attributes for an ego if in scope parameter.

Definition at line 1385 of file openid_plugin.c.

1388{
1389 struct RequestHandle *handle = cls;
1392 {
1395 &attr->credential,
1396 attr->type,
1397 attr->data,
1398 attr->data_size);
1399 le->attribute->id = attr->id;
1400 le->attribute->flag = attr->flag;
1401 le->attribute->credential = attr->credential;
1402 GNUNET_CONTAINER_DLL_insert (handle->attr_idtoken_list->list_head,
1403 handle->attr_idtoken_list->list_tail,
1404 le);
1405 }
1407 {
1410 &attr->credential,
1411 attr->type,
1412 attr->data,
1413 attr->data_size);
1414 le->attribute->id = attr->id;
1415 le->attribute->flag = attr->flag;
1416 le->attribute->credential = attr->credential;
1417 GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
1418 handle->attr_userinfo_list->list_tail,
1419 le);
1420 }
1421
1423}

References attr_in_idtoken_request(), attr_in_userinfo_request(), GNUNET_RECLAIM_AttributeListEntry::attribute, GNUNET_RECLAIM_Attribute::credential, GNUNET_RECLAIM_Attribute::data, GNUNET_RECLAIM_Attribute::data_size, GNUNET_RECLAIM_Attribute::flag, GNUNET_CONTAINER_DLL_insert, GNUNET_new, GNUNET_RECLAIM_attribute_new(), GNUNET_RECLAIM_get_attributes_next(), GNUNET_YES, handle, GNUNET_RECLAIM_Attribute::id, GNUNET_RECLAIM_Attribute::name, and GNUNET_RECLAIM_Attribute::type.

Referenced by code_redirect().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ code_redirect()

static void code_redirect ( void *  cls)
static

Checks time and cookie and redirects accordingly.

Definition at line 1430 of file openid_plugin.c.

1431{
1432 struct RequestHandle *handle = cls;
1433 struct GNUNET_TIME_Absolute current_time;
1434 struct GNUNET_TIME_Absolute *relog_time;
1436 struct GNUNET_CRYPTO_PublicKey ego_pkey;
1437 struct GNUNET_HashCode cache_key;
1438 char *identity_cookie;
1439
1440 GNUNET_asprintf (&identity_cookie,
1441 "Identity=%s",
1442 handle->oidc->login_identity);
1443 GNUNET_CRYPTO_hash (identity_cookie, strlen (identity_cookie), &cache_key);
1444 GNUNET_free (identity_cookie);
1445 // No login time for identity -> redirect to login
1446 if (GNUNET_YES ==
1448 {
1449 relog_time =
1451 current_time = GNUNET_TIME_absolute_get ();
1452 // 30 min after old login -> redirect to login
1453 if (current_time.abs_value_us <= relog_time->abs_value_us)
1454 {
1455 if (GNUNET_OK !=
1457 ->login_identity,
1458 &pubkey))
1459 {
1461 handle->edesc =
1462 GNUNET_strdup ("The cookie of a login identity is not valid");
1464 return;
1465 }
1466 // iterate over egos and compare their public key
1467 for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
1468 handle->ego_entry = handle->ego_entry->next)
1469 {
1470 GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey);
1471 if (0 == GNUNET_memcmp (&ego_pkey, &pubkey))
1472 {
1473 handle->priv_key =
1475 handle->attr_idtoken_list =
1477 handle->attr_userinfo_list =
1479 handle->attr_it =
1481 &handle->priv_key,
1483 handle,
1485 handle,
1487 handle);
1488 return;
1489 }
1490 }
1492 return;
1493 }
1494 }
1495}

References GNUNET_TIME_Absolute::abs_value_us, do_redirect_error(), ego_head, GNUNET_asprintf(), GNUNET_CONTAINER_multihashmap_contains(), GNUNET_CONTAINER_multihashmap_get(), GNUNET_CRYPTO_hash(), GNUNET_CRYPTO_public_key_from_string(), GNUNET_free, GNUNET_IDENTITY_ego_get_private_key(), GNUNET_IDENTITY_ego_get_public_key(), GNUNET_memcmp, GNUNET_new, GNUNET_OK, GNUNET_RECLAIM_get_attributes_start(), GNUNET_SCHEDULER_add_now(), GNUNET_strdup, GNUNET_TIME_absolute_get(), GNUNET_YES, handle, idp, login_redirect(), oidc_attr_collect(), oidc_attr_collect_finished_cb(), OIDC_cookie_jar_map, OIDC_ERROR_KEY_INVALID_COOKIE, oidc_iteration_error(), and pubkey.

Referenced by build_redirect().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ build_redirect()

static void build_redirect ( void *  cls)
static

Definition at line 1499 of file openid_plugin.c.

1500{
1501 struct RequestHandle *handle = cls;
1502 struct MHD_Response *resp;
1503 char *redirect_uri;
1504
1505 if (GNUNET_YES == handle->oidc->user_cancelled)
1506 {
1507 if ((NULL != handle->redirect_prefix) &&
1508 (NULL != handle->redirect_suffix) && (NULL != handle->tld))
1509 {
1510 GNUNET_asprintf (&redirect_uri,
1511 "%s.%s/%s?error=%s&error_description=%s&state=%s",
1512 handle->redirect_prefix,
1513 handle->tld,
1514 handle->redirect_suffix,
1515 "access_denied",
1516 "User denied access",
1517 handle->oidc->state);
1518 }
1519 else
1520 {
1521 GNUNET_asprintf (&redirect_uri,
1522 "%s?error=%s&error_description=%s&state=%s",
1523 handle->oidc->redirect_uri,
1524 "access_denied",
1525 "User denied access",
1526 handle->oidc->state);
1527 }
1528 resp = GNUNET_REST_create_response ("");
1529 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1530 "Location",
1531 redirect_uri));
1532 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1534 GNUNET_free (redirect_uri);
1535 return;
1536 }
1538}

References cleanup_handle(), code_redirect(), GNUNET_asprintf(), GNUNET_assert, GNUNET_free, GNUNET_REST_create_response(), GNUNET_SCHEDULER_add_now(), GNUNET_YES, and handle.

Referenced by lookup_redirect_uri_result().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ lookup_redirect_uri_result()

static void lookup_redirect_uri_result ( void *  cls,
uint32_t  rd_count,
const struct GNUNET_GNSRECORD_Data rd 
)
static

Definition at line 1542 of file openid_plugin.c.

1545{
1546 struct RequestHandle *handle = cls;
1547 char *tmp;
1548 char *tmp_key_str;
1549 char *pos;
1550 struct GNUNET_CRYPTO_PublicKey redirect_zone;
1551
1552 handle->gns_op = NULL;
1553 if (0 == rd_count)
1554 {
1556 handle->edesc =
1557 GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1559 return;
1560 }
1561 for (int i = 0; i < rd_count; i++)
1562 {
1563 if (GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT != rd[i].record_type)
1564 continue;
1565 if (0 != strncmp (rd[i].data, handle->oidc->redirect_uri, rd[i].data_size))
1566 continue;
1567 tmp = GNUNET_strndup (rd[i].data, rd[i].data_size);
1568 if (NULL == strstr (tmp, handle->oidc->client_id))
1569 {
1571 "Redirect uri %s does not contain client_id %s\n",
1572 tmp,
1573 handle->oidc->client_id);
1574 }
1575 else
1576 {
1577 pos = strrchr (tmp, (unsigned char) '.');
1578 if (NULL == pos)
1579 {
1581 "Redirect uri %s contains client_id but is malformed\n",
1582 tmp);
1583 GNUNET_free (tmp);
1584 continue;
1585 }
1586 *pos = '\0';
1587 handle->redirect_prefix = GNUNET_strdup (tmp);
1588 tmp_key_str = pos + 1;
1589 pos = strchr (tmp_key_str, (unsigned char) '/');
1590 if (NULL == pos)
1591 {
1593 "Redirect uri %s contains client_id but is malformed\n",
1594 tmp);
1595 GNUNET_free (tmp);
1596 continue;
1597 }
1598 *pos = '\0';
1599 handle->redirect_suffix = GNUNET_strdup (pos + 1);
1600
1601 GNUNET_STRINGS_string_to_data (tmp_key_str,
1602 strlen (tmp_key_str),
1603 &redirect_zone,
1604 sizeof(redirect_zone));
1605 }
1607 GNUNET_free (tmp);
1608 return;
1609 }
1611 handle->edesc =
1612 GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1614}

References build_redirect(), data, data_size, GNUNET_GNSRECORD_Data::data_size, do_redirect_error(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT, GNUNET_log, GNUNET_SCHEDULER_add_now(), GNUNET_strdup, GNUNET_STRINGS_string_to_data(), GNUNET_strndup, handle, OIDC_ERROR_KEY_SERVER_ERROR, rd, and rd_count.

Referenced by client_redirect().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ client_redirect()

static void client_redirect ( void *  cls)
static

Initiate redirect back to client.

Definition at line 1621 of file openid_plugin.c.

1622{
1623 struct RequestHandle *handle = cls;
1624
1625 /* Lookup client redirect uri to verify request */
1626 handle->gns_op =
1629 &handle->oidc->client_pkey,
1633 handle);
1634}

References gns_handle, GNUNET_GNS_EMPTY_LABEL_AT, GNUNET_GNS_LO_DEFAULT, GNUNET_GNS_lookup(), GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT, handle, and lookup_redirect_uri_result().

Referenced by build_authz_response().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_url_parameter_copy()

static char * get_url_parameter_copy ( const struct RequestHandle handle,
const char *  key 
)
static

Definition at line 1638 of file openid_plugin.c.

1639{
1640 struct GNUNET_HashCode hc;
1641 char *value;
1642 char *res;
1643
1644 GNUNET_CRYPTO_hash (key, strlen (key), &hc);
1646 ->url_param_map,
1647 &hc))
1648 return NULL;
1649 value =
1650 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, &hc);
1651 if (NULL == value)
1652 return NULL;
1654 return res;
1655}

References GNUNET_CONTAINER_multihashmap_contains(), GNUNET_CONTAINER_multihashmap_get(), GNUNET_CRYPTO_hash(), GNUNET_STRINGS_urldecode(), GNUNET_YES, handle, key, res, and value.

Referenced by authorize_endpoint(), build_authz_response(), check_authorization(), consume_fail(), and token_endpoint().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ build_authz_response()

static void build_authz_response ( void *  cls)
static

Iteration over all results finished, build final response.

Parameters
clsthe struct RequestHandle

Definition at line 1665 of file openid_plugin.c.

1666{
1667 struct RequestHandle *handle = cls;
1668 struct GNUNET_HashCode cache_key;
1669
1670 char *expected_scope;
1671 char delimiter[] = " ";
1672 char *test;
1673 int number_of_ignored_parameter, iterator;
1674
1675
1676 // REQUIRED value: redirect_uri
1677 handle->oidc->redirect_uri =
1679 if (NULL == handle->oidc->redirect_uri)
1680 {
1682 handle->edesc = GNUNET_strdup ("missing parameter redirect_uri");
1684 return;
1685 }
1686
1687 // REQUIRED value: response_type
1688 handle->oidc->response_type =
1690 if (NULL == handle->oidc->response_type)
1691 {
1693 handle->edesc = GNUNET_strdup ("missing parameter response_type");
1695 return;
1696 }
1697
1698 // REQUIRED value: scope
1700 if (NULL == handle->oidc->scope)
1701 {
1703 handle->edesc = GNUNET_strdup ("missing parameter scope");
1705 return;
1706 }
1707
1708 // OPTIONAL value: nonce
1710
1711 // OPTIONAL value: claims
1713
1714 // TODO check other values if needed
1715 number_of_ignored_parameter =
1716 sizeof(OIDC_ignored_parameter_array) / sizeof(char *);
1717 for (iterator = 0; iterator < number_of_ignored_parameter; iterator++)
1718 {
1720 strlen (OIDC_ignored_parameter_array[iterator]),
1721 &cache_key);
1722 if (GNUNET_YES ==
1724 ->url_param_map,
1725 &cache_key))
1726 {
1728 GNUNET_asprintf (&handle->edesc,
1729 "Server will not handle parameter: %s",
1732 return;
1733 }
1734 }
1735
1736 // We only support authorization code flows.
1737 if (0 != strcmp (handle->oidc->response_type,
1739 {
1741 handle->edesc = GNUNET_strdup ("The authorization server does not support "
1742 "obtaining this authorization code.");
1744 return;
1745 }
1746
1747 // Checks if scope contains 'openid'
1748 expected_scope = GNUNET_strdup (handle->oidc->scope);
1749 test = strtok (expected_scope, delimiter);
1750 while (NULL != test)
1751 {
1752 if (0 == strcmp (OIDC_EXPECTED_AUTHORIZATION_SCOPE, expected_scope))
1753 break;
1754 test = strtok (NULL, delimiter);
1755 }
1756 if (NULL == test)
1757 {
1759 handle->edesc =
1760 GNUNET_strdup ("The requested scope is invalid, unknown, or malformed.");
1762 GNUNET_free (expected_scope);
1763 return;
1764 }
1765
1766 GNUNET_free (expected_scope);
1767 if ((NULL == handle->oidc->login_identity) &&
1768 (GNUNET_NO == handle->oidc->user_cancelled))
1770 else
1772}

References client_redirect(), do_error(), do_redirect_error(), get_url_parameter_copy(), GNUNET_asprintf(), GNUNET_CONTAINER_multihashmap_contains(), GNUNET_CRYPTO_hash(), GNUNET_free, GNUNET_NO, GNUNET_SCHEDULER_add_now(), GNUNET_strdup, GNUNET_YES, handle, login_redirect(), OIDC_CLAIMS_KEY, OIDC_ERROR_KEY_ACCESS_DENIED, OIDC_ERROR_KEY_INVALID_REQUEST, OIDC_ERROR_KEY_INVALID_SCOPE, OIDC_ERROR_KEY_UNSUPPORTED_RESPONSE_TYPE, OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE, OIDC_EXPECTED_AUTHORIZATION_SCOPE, OIDC_ignored_parameter_array, OIDC_NONCE_KEY, OIDC_REDIRECT_URI_KEY, OIDC_RESPONSE_TYPE_KEY, and OIDC_SCOPE_KEY.

Referenced by authorize_endpoint().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ tld_iter()

static void tld_iter ( void *  cls,
const char *  section,
const char *  option,
const char *  value 
)
static

Iterate over tlds in config.

Definition at line 1779 of file openid_plugin.c.

1780{
1781 struct RequestHandle *handle = cls;
1783
1784 if (GNUNET_OK !=
1786 {
1787 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Skipping non key %s\n", value);
1788 return;
1789 }
1790 if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1791 handle->tld = GNUNET_strdup (option + 1);
1792}

References GNUNET_CRYPTO_public_key_from_string(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_memcmp, GNUNET_OK, GNUNET_strdup, handle, pkey, and value.

Referenced by authorize_endpoint().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ authorize_endpoint()

static void authorize_endpoint ( struct GNUNET_REST_RequestHandle con_handle,
const char *  url,
void *  cls 
)
static

Responds to authorization GET and url-encoded POST request.

Parameters
con_handlethe connection handle
urlthe url
clsthe RequestHandle

Definition at line 1803 of file openid_plugin.c.

1806{
1807 struct RequestHandle *handle = cls;
1808 struct EgoEntry *tmp_ego;
1809 const struct GNUNET_CRYPTO_PrivateKey *priv_key;
1811
1813
1814 // RECOMMENDED value: state - REQUIRED for answers
1816
1817 // REQUIRED value: client_id
1819 if (NULL == handle->oidc->client_id)
1820 {
1822 handle->edesc = GNUNET_strdup ("missing parameter client_id");
1823 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1825 return;
1826 }
1827
1828 // OPTIONAL value: code_challenge
1829 handle->oidc->code_challenge = get_url_parameter_copy (handle,
1831 if (NULL == handle->oidc->code_challenge)
1832 {
1834 "OAuth authorization request does not contain PKCE parameters!\n");
1835 }
1836
1837 if (GNUNET_OK !=
1839 &handle->oidc->client_pkey))
1840 {
1842 handle->edesc = GNUNET_strdup ("The client is not authorized to request an "
1843 "authorization code using this method.");
1844 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1846 return;
1847 }
1848
1849 // If we know this identity, translated the corresponding TLD
1850 // TODO: We might want to have a reverse lookup functionality for TLDs?
1851 for (tmp_ego = ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next)
1852 {
1853 priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego);
1855 if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1856 {
1857 handle->tld = GNUNET_strdup (tmp_ego->identifier);
1858 handle->ego_entry = ego_tail;
1859 }
1860 }
1861 if (NULL == handle->tld)
1863 handle);
1864 if (NULL == handle->tld)
1865 handle->tld = GNUNET_strdup (handle->oidc->client_id);
1867}

References build_authz_response(), cookie_identity_interpretation(), do_error(), EgoEntry::ego, ego_head, ego_tail, get_url_parameter_copy(), GNUNET_CONFIGURATION_iterate_section_values(), GNUNET_CRYPTO_key_get_public(), GNUNET_CRYPTO_public_key_from_string(), GNUNET_ERROR_TYPE_WARNING, GNUNET_IDENTITY_ego_get_private_key(), GNUNET_log, GNUNET_memcmp, GNUNET_OK, GNUNET_SCHEDULER_add_now(), GNUNET_strdup, handle, EgoEntry::identifier, EgoEntry::next, oid_cfg, OIDC_CLIENT_ID_KEY, OIDC_CODE_CHALLENGE_KEY, OIDC_ERROR_KEY_INVALID_REQUEST, OIDC_ERROR_KEY_UNAUTHORIZED_CLIENT, OIDC_STATE_KEY, pkey, and tld_iter().

Referenced by REST_openid_process_request().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ login_cont()

static void login_cont ( struct GNUNET_REST_RequestHandle con_handle,
const char *  url,
void *  cls 
)
static

Combines an identity with a login time and responds OK to login request.

Parameters
con_handlethe connection handle
urlthe url
clsthe RequestHandle

Definition at line 1878 of file openid_plugin.c.

1881{
1882 struct MHD_Response *resp = GNUNET_REST_create_response ("");
1883 struct RequestHandle *handle = cls;
1884 struct GNUNET_HashCode cache_key;
1885 struct GNUNET_TIME_Absolute *current_time;
1886 struct GNUNET_TIME_Absolute *last_time;
1887 char *cookie;
1888 char *header_val;
1889 json_t *root;
1890 json_error_t error;
1891 json_t *identity;
1892 char term_data[handle->rest_handle->data_size + 1];
1893
1894 term_data[handle->rest_handle->data_size] = '\0';
1895 GNUNET_memcpy (term_data,
1896 handle->rest_handle->data,
1897 handle->rest_handle->data_size);
1898 root = json_loads (term_data, JSON_DECODE_ANY, &error);
1899 identity = json_object_get (root, "identity");
1900 if (! json_is_string (identity))
1901 {
1903 "Error parsing json string from %s\n",
1904 term_data);
1905 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
1906 json_decref (root);
1908 return;
1909 }
1910 GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity));
1911 GNUNET_asprintf (&header_val,
1912 "%s;Max-Age=%d",
1913 cookie,
1915 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1916 "Set-Cookie", header_val));
1917 GNUNET_assert (MHD_NO !=
1918 MHD_add_response_header (resp,
1919 "Access-Control-Allow-Methods",
1920 "POST"));
1921 GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key);
1922
1923 if (0 != strcmp (json_string_value (identity), "Denied"))
1924 {
1925 current_time = GNUNET_new (struct GNUNET_TIME_Absolute);
1926 *current_time = GNUNET_TIME_relative_to_absolute (
1929 last_time =
1931 GNUNET_free (last_time);
1933 &cache_key,
1934 current_time,
1936 }
1937 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1938 GNUNET_free (cookie);
1939 GNUNET_free (header_val);
1940 json_decref (root);
1942}

References cleanup_handle(), GNUNET_asprintf(), GNUNET_assert, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE, GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_memcpy, GNUNET_new, GNUNET_REST_create_response(), GNUNET_TIME_relative_get_second_(), GNUNET_TIME_relative_multiply(), GNUNET_TIME_relative_to_absolute(), handle, identity, OIDC_COOKIE_EXPIRATION, and OIDC_cookie_jar_map.

Referenced by REST_openid_process_request().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse_credentials_basic_auth()

static int parse_credentials_basic_auth ( struct RequestHandle handle,
char **  client_id,
char **  client_secret 
)
static

Definition at line 1946 of file openid_plugin.c.

1949{
1950 struct GNUNET_HashCode cache_key;
1951 char *authorization;
1952 char *credentials;
1953 char *basic_authorization;
1954 char *client_id_tmp;
1955 char *pass;
1956
1959 &cache_key);
1961 ->header_param_map,
1962 &cache_key))
1963 return GNUNET_SYSERR;
1964 authorization =
1965 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
1966 &cache_key);
1967
1968 // split header in "Basic" and [content]
1969 credentials = strtok (authorization, " ");
1970 if ((NULL == credentials) || (0 != strcmp ("Basic", credentials)))
1971 return GNUNET_SYSERR;
1972 credentials = strtok (NULL, " ");
1973 if (NULL == credentials)
1974 return GNUNET_SYSERR;
1975 GNUNET_STRINGS_base64_decode (credentials,
1976 strlen (credentials),
1977 (void **) &basic_authorization);
1978
1979 if (NULL == basic_authorization)
1980 return GNUNET_SYSERR;
1981 client_id_tmp = strtok (basic_authorization, ":");
1982 if (NULL == client_id_tmp)
1983 {
1984 GNUNET_free (basic_authorization);
1985 return GNUNET_SYSERR;
1986 }
1987 pass = strtok (NULL, ":");
1988 if (NULL == pass)
1989 {
1990 GNUNET_free (basic_authorization);
1991 return GNUNET_SYSERR;
1992 }
1993 *client_id = strdup (client_id_tmp);
1994 *client_secret = strdup (pass);
1995 GNUNET_free (basic_authorization);
1996 return GNUNET_OK;
1997}

References GNUNET_CONTAINER_multihashmap_contains(), GNUNET_CONTAINER_multihashmap_get(), GNUNET_CRYPTO_hash(), GNUNET_free, GNUNET_NO, GNUNET_OK, GNUNET_STRINGS_base64_decode(), GNUNET_SYSERR, handle, and OIDC_AUTHORIZATION_HEADER_KEY.

Referenced by check_authorization().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse_credentials_post_body()

static int parse_credentials_post_body ( struct RequestHandle handle,
char **  client_id,
char **  client_secret 
)
static

Definition at line 2001 of file openid_plugin.c.

2004{
2005 struct GNUNET_HashCode cache_key;
2006 char *client_id_tmp;
2007 char *pass;
2008
2009 GNUNET_CRYPTO_hash ("client_id",
2010 strlen ("client_id"),
2011 &cache_key);
2013 ->url_param_map,
2014 &cache_key))
2015 return GNUNET_SYSERR;
2016 client_id_tmp = GNUNET_CONTAINER_multihashmap_get (
2017 handle->rest_handle->url_param_map,
2018 &cache_key);
2019 if (NULL == client_id_tmp)
2020 return GNUNET_SYSERR;
2021 *client_id = strdup (client_id_tmp);
2022 GNUNET_CRYPTO_hash ("client_secret",
2023 strlen ("client_secret"),
2024 &cache_key);
2026 ->url_param_map,
2027 &cache_key))
2028 {
2029 GNUNET_free (*client_id);
2030 *client_id = NULL;
2031 return GNUNET_SYSERR;
2032 }
2033 pass = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
2034 &cache_key);
2035 if (NULL == pass)
2036 {
2037 GNUNET_free (*client_id);
2038 *client_id = NULL;
2039 return GNUNET_SYSERR;
2040 }
2041 *client_secret = strdup (pass);
2042 return GNUNET_OK;
2043}

References GNUNET_CONTAINER_multihashmap_contains(), GNUNET_CONTAINER_multihashmap_get(), GNUNET_CRYPTO_hash(), GNUNET_free, GNUNET_NO, GNUNET_OK, GNUNET_SYSERR, and handle.

Referenced by check_authorization().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_authorization()

static int check_authorization ( struct RequestHandle handle,
struct GNUNET_CRYPTO_PublicKey cid 
)
static

Allow public clients with PKCE

Definition at line 2047 of file openid_plugin.c.

2049{
2050 char *expected_pass;
2051 char *received_cid;
2052 char *received_cpw;
2053 char *pkce_cv;
2054
2056 &received_cid,
2057 &received_cpw))
2058 {
2060 "Received client credentials in HTTP AuthZ header\n");
2061 }
2063 &received_cid,
2064 &received_cpw))
2065 {
2067 "Received client credentials in POST body\n");
2068 }
2069 else
2070 {
2073 if (NULL == pkce_cv)
2074 {
2076 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2077 return GNUNET_SYSERR;
2078 }
2079 handle->public_client = GNUNET_YES;
2080 GNUNET_free (pkce_cv);
2082 GNUNET_STRINGS_string_to_data (received_cid,
2083 strlen (received_cid),
2084 cid,
2085 sizeof(struct GNUNET_CRYPTO_PublicKey));
2086 GNUNET_free (received_cid);
2087 return GNUNET_OK;
2088
2089 }
2090
2091 // check client password
2093 "reclaim-rest-plugin",
2094 "OIDC_CLIENT_HMAC_SECRET",
2095 &expected_pass))
2096 {
2097 if (0 != strcmp (expected_pass, received_cpw))
2098 {
2099 GNUNET_free (expected_pass);
2101 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2102 GNUNET_free (received_cpw);
2103 GNUNET_free (received_cid);
2104 return GNUNET_SYSERR;
2105 }
2106 GNUNET_free (expected_pass);
2107 }
2108 else
2109 {
2110 GNUNET_free (received_cpw);
2111 GNUNET_free (received_cid);
2113 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
2114 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2115 return GNUNET_SYSERR;
2116 }
2117 // check client_id
2118 for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
2119 handle->ego_entry = handle->ego_entry->next)
2120 {
2121 if (0 == strcmp (handle->ego_entry->keystring, received_cid))
2122 break;
2123 }
2124 if (NULL == handle->ego_entry)
2125 {
2126 GNUNET_free (received_cpw);
2127 GNUNET_free (received_cid);
2129 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2130 return GNUNET_SYSERR;
2131 }
2132 GNUNET_STRINGS_string_to_data (received_cid,
2133 strlen (received_cid),
2134 cid,
2135 sizeof(struct GNUNET_CRYPTO_PublicKey));
2136
2137 GNUNET_free (received_cpw);
2138 GNUNET_free (received_cid);
2139 return GNUNET_OK;
2140}

References ego_head, get_url_parameter_copy(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_OK, GNUNET_strdup, GNUNET_STRINGS_string_to_data(), GNUNET_SYSERR, GNUNET_YES, handle, oid_cfg, OIDC_CLIENT_ID_KEY, OIDC_CODE_VERIFIER_KEY, OIDC_ERROR_KEY_INVALID_CLIENT, OIDC_ERROR_KEY_SERVER_ERROR, parse_credentials_basic_auth(), and parse_credentials_post_body().

Referenced by token_endpoint().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_ego()

static const struct EgoEntry * find_ego ( struct RequestHandle handle,
struct GNUNET_CRYPTO_PublicKey test_key 
)
static

Definition at line 2144 of file openid_plugin.c.

2146{
2147 struct EgoEntry *ego_entry;
2148 struct GNUNET_CRYPTO_PublicKey pub_key;
2149
2150 for (ego_entry = ego_head; NULL != ego_entry;
2151 ego_entry = ego_entry->next)
2152 {
2153 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key);
2154 if (0 == GNUNET_memcmp (&pub_key, test_key))
2155 return ego_entry;
2156 }
2157 return NULL;
2158}

References EgoEntry::ego, ego_head, GNUNET_IDENTITY_ego_get_public_key(), GNUNET_memcmp, and EgoEntry::next.

Referenced by token_endpoint().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ token_endpoint()

static void token_endpoint ( struct GNUNET_REST_RequestHandle con_handle,
const char *  url,
void *  cls 
)
static

Responds to token url-encoded POST request.

Parameters
con_handlethe connection handle
urlthe url
clsthe RequestHandle

Store mapping from access token to code so we can later fall back on the provided attributes in userinfo one time.

Note to future self: This cache has the following purpose: Some OIDC plugins call the userendpoint right after receiving an ID token and access token. There are reasons why this would make sense. Others not so much. In any case, in order to smoothen out the user experience upon login (authorization), we speculatively cache the next userinfo response in case the actual resolution through reclaim/GNS takes too long.

Definition at line 2169 of file openid_plugin.c.

2172{
2173 struct RequestHandle *handle = cls;
2174 const struct EgoEntry *ego_entry = NULL;
2175 struct GNUNET_TIME_Relative expiration_time;
2176 struct GNUNET_RECLAIM_AttributeList *cl = NULL;
2177 struct GNUNET_RECLAIM_PresentationList *pl = NULL;
2179 struct GNUNET_CRYPTO_PublicKey cid;
2180 struct GNUNET_HashCode cache_key;
2181 struct MHD_Response *resp = NULL;
2182 struct GNUNET_CRYPTO_PublicKey issuer;
2183 char *grant_type = NULL;
2184 char *code = NULL;
2185 char *json_response = NULL;
2186 char *id_token = NULL;
2187 char *access_token = NULL;
2188 char *jwa = NULL;
2189 char *jwt_secret = NULL;
2190 char *nonce = NULL;
2191 char *code_verifier = NULL;
2192 json_t *oidc_jwk_tmp = NULL;
2193 char *oidc_jwk_path = NULL;
2194 char *oidc_directory = NULL;
2195 char *tmp_at = NULL;
2196 char *received_cid = NULL;
2197 char *emsg = NULL;
2198
2199 /*
2200 * Check Authorization
2201 */
2203 {
2205 "OIDC authorization for token endpoint failed\n");
2207 return;
2208 }
2210
2211 /*
2212 * Check parameter
2213 */
2214
2215 // TODO Do not allow multiple equal parameter names
2216 // REQUIRED grant_type
2218 strlen (OIDC_GRANT_TYPE_KEY),
2219 &cache_key);
2221 if (NULL == grant_type)
2222 {
2224 handle->edesc = GNUNET_strdup ("missing parameter grant_type");
2225 handle->response_code = MHD_HTTP_BAD_REQUEST;
2227 return;
2228 }
2229
2230 // Check parameter grant_type == "authorization_code"
2231 if (0 != strcmp (OIDC_GRANT_TYPE_VALUE, grant_type))
2232 {
2234 handle->response_code = MHD_HTTP_BAD_REQUEST;
2235 GNUNET_free (grant_type);
2237 return;
2238 }
2239 GNUNET_free (grant_type);
2240 // REQUIRED code
2242 if (NULL == code)
2243 {
2245 handle->edesc = GNUNET_strdup ("missing parameter code");
2246 handle->response_code = MHD_HTTP_BAD_REQUEST;
2248 return;
2249 }
2250 ego_entry = find_ego (handle, &cid);
2251 if (NULL == ego_entry)
2252 {
2254 handle->edesc = GNUNET_strdup ("Unknown client");
2255 handle->response_code = MHD_HTTP_BAD_REQUEST;
2256 GNUNET_free (code);
2258 return;
2259 }
2260
2261 // REQUIRED code verifier
2263 if (NULL == code_verifier)
2264 {
2266 "OAuth authorization request does not contain PKCE parameters!\n");
2267
2268 }
2269
2270 // decode code
2271 if (GNUNET_OK != OIDC_parse_authz_code (received_cid, &cid, code,
2272 code_verifier,
2273 &ticket,
2274 &cl, &pl, &nonce,
2276 &emsg))
2277 {
2279 handle->edesc = emsg;
2280 handle->response_code = MHD_HTTP_BAD_REQUEST;
2281 GNUNET_free (code);
2282 if (NULL != code_verifier)
2283 GNUNET_free (code_verifier);
2285 return;
2286 }
2287 if (NULL != code_verifier)
2288 GNUNET_free (code_verifier);
2289
2290 // create jwt
2292 "reclaim-rest-plugin",
2293 "expiration_time",
2294 &expiration_time))
2295 {
2297 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
2298 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2299 GNUNET_free (code);
2300 if (NULL != nonce)
2301 GNUNET_free (nonce);
2305 return;
2306 }
2307
2308 // Check if HMAC or RSA should be used
2310 "reclaim-rest-plugin",
2311 "oidc_json_web_algorithm",
2312 &jwa))
2313 {
2315 "Could not read OIDC JSON Web Algorithm config attribute."
2316 "Defaulting to RS256.");
2318 }
2319
2321
2322 if (! strcmp (jwa, JWT_ALG_VALUE_RSA))
2323 {
2324 // Replace for now
2325 oidc_jwk_path = get_oidc_jwk_path (cls);
2326 oidc_jwk_tmp = read_jwk_from_file (oidc_jwk_path);
2327
2328 // Check if secret JWK exists
2329 if (! oidc_jwk_tmp)
2330 {
2331 // Generate and save a new key
2332 oidc_jwk_tmp = generate_jwk ();
2333 oidc_directory = get_oidc_dir_path (cls);
2334
2335 // Create new oidc directory
2336 if (GNUNET_OK != GNUNET_DISK_directory_create (oidc_directory))
2337 {
2339 ("Failed to create directory `%s' for storing oidc data\n"),
2340 oidc_directory);
2341 }
2342 else
2343 {
2344 write_jwk_to_file (oidc_jwk_path, oidc_jwk_tmp);
2345 }
2346 }
2347
2348 // Generate oidc token
2349 id_token = OIDC_generate_id_token_rsa (received_cid,
2350 &issuer,
2351 cl,
2352 pl,
2353 &expiration_time,
2354 (NULL != nonce) ? nonce : NULL,
2355 oidc_jwk_tmp);
2356 }
2357 else if (! strcmp (jwa, JWT_ALG_VALUE_HMAC))
2358 {
2359 // TODO OPTIONAL acr,amr,azp
2361 "reclaim-rest-plugin",
2362 "jwt_secret",
2363 &jwt_secret))
2364 {
2366 handle->edesc = GNUNET_strdup ("No signing secret configured!");
2367 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2368 GNUNET_free (code);
2371 if (NULL != nonce)
2372 GNUNET_free (nonce);
2373 GNUNET_free (jwa);
2375 return;
2376 }
2377
2378 id_token = OIDC_generate_id_token_hmac (received_cid,
2379 &issuer,
2380 cl,
2381 pl,
2382 &expiration_time,
2383 (NULL != nonce) ? nonce : NULL,
2384 jwt_secret);
2385
2386 GNUNET_free (jwt_secret);
2387 }
2388 else
2389 {
2390 // TODO: OPTION NOT FOUND ERROR
2391 }
2392 GNUNET_free (jwa);
2393
2394 if (NULL != nonce)
2395 GNUNET_free (nonce);
2396 access_token = OIDC_access_token_new (&ticket, handle->oidc->redirect_uri);
2401 GNUNET_CRYPTO_hash (access_token,
2402 strlen (access_token),
2403 &cache_key);
2415 &cache_key);
2417 &cache_key,
2418 code,
2420 /* If there was a previous code in there, free the old value */
2421 if (NULL != tmp_at)
2422 {
2424 "OIDC access token already issued. Cleanup.\n");
2425 GNUNET_free (tmp_at);
2426 }
2427
2428 OIDC_build_token_response (access_token,
2429 id_token,
2430 &expiration_time,
2431 &json_response);
2432
2433 resp = GNUNET_REST_create_response (json_response);
2434 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2435 "Cache-Control",
2436 "no-store"));
2437 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2438 "Pragma", "no-cache"));
2439 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2440 "Content-Type",
2441 "application/json"));
2442 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2445 GNUNET_free (access_token);
2446 GNUNET_free (json_response);
2447 GNUNET_free (id_token);
2449}

References check_authorization(), cleanup_handle(), do_error(), find_ego(), generate_jwk(), get_oidc_dir_path(), get_oidc_jwk_path(), get_url_parameter_copy(), GNUNET_RECLAIM_Ticket::gns_name, GNUNET_assert, GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_get_value_time(), GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE, GNUNET_CRYPTO_hash(), GNUNET_DISK_directory_create(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_GNS_parse_ztld(), GNUNET_log, GNUNET_OK, GNUNET_RECLAIM_attribute_list_destroy(), GNUNET_RECLAIM_presentation_list_destroy(), GNUNET_REST_create_response(), GNUNET_SCHEDULER_add_now(), GNUNET_strdup, GNUNET_SYSERR, handle, JWT_ALG_VALUE_HMAC, JWT_ALG_VALUE_RSA, oid_cfg, OIDC_access_token_new(), OIDC_build_token_response(), OIDC_CLIENT_ID_KEY, oidc_code_cache, OIDC_CODE_KEY, OIDC_CODE_VERIFIER_KEY, OIDC_ERROR_KEY_INVALID_REQUEST, OIDC_ERROR_KEY_SERVER_ERROR, OIDC_ERROR_KEY_UNSUPPORTED_GRANT_TYPE, OIDC_generate_id_token_hmac(), OIDC_generate_id_token_rsa(), OIDC_GRANT_TYPE_KEY, OIDC_GRANT_TYPE_VALUE, OIDC_parse_authz_code(), OIDC_VERIFICATION_DEFAULT, read_jwk_from_file(), ticket, and write_jwk_to_file().

Referenced by REST_openid_process_request().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ consume_ticket()

static void consume_ticket ( void *  cls,
const struct GNUNET_CRYPTO_PublicKey identity,
const struct GNUNET_RECLAIM_Attribute attr,
const struct GNUNET_RECLAIM_Presentation presentation 
)
static

Collects claims and stores them in handle.

We received a reply. In any case clear the cache.

already in list

Credential matches for attribute, add

Definition at line 2456 of file openid_plugin.c.

2460{
2461 struct RequestHandle *handle = cls;
2464 struct MHD_Response *resp;
2465 struct GNUNET_HashCode cache_key;
2466 char *result_str;
2467 char *cached_code;
2468
2469 if (NULL != handle->consume_timeout_op)
2470 GNUNET_SCHEDULER_cancel (handle->consume_timeout_op);
2471 handle->consume_timeout_op = NULL;
2472 handle->idp_op = NULL;
2473
2477 GNUNET_CRYPTO_hash (handle->access_token,
2478 strlen (handle->access_token),
2479 &cache_key);
2481 &cache_key);
2482 if (NULL != cached_code)
2483 {
2486 &cache_key,
2487 cached_code));
2488 GNUNET_free (cached_code);
2489 }
2490
2491
2492 if (NULL == identity)
2493 {
2494 struct GNUNET_CRYPTO_PublicKey issuer;
2495 char *key;
2496 char *tmp = GNUNET_strdup (handle->ticket.gns_name);
2497 GNUNET_assert (NULL != strtok (tmp, "."));
2498 key = strtok (NULL, ".");
2499 GNUNET_assert (NULL != key);
2502 GNUNET_free (tmp);
2503 result_str = OIDC_generate_userinfo (&issuer,
2504 handle->attr_userinfo_list,
2505 handle->presentations);
2506 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2507 resp = GNUNET_REST_create_response (result_str);
2508 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2509 GNUNET_free (result_str);
2511 return;
2512 }
2515 &attr->credential,
2516 attr->type,
2517 attr->data,
2518 attr->data_size);
2519 ale->attribute->id = attr->id;
2520 ale->attribute->flag = attr->flag;
2521 ale->attribute->credential = attr->credential;
2522 GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
2523 handle->attr_userinfo_list->list_tail,
2524 ale);
2525 if (NULL == presentation)
2526 return;
2527 for (atle = handle->presentations->list_head;
2528 NULL != atle; atle = atle->next)
2529 {
2532 &presentation->credential_id))
2533 continue;
2534 break;
2535 }
2536 if (NULL == atle)
2537 {
2540 atle->presentation = GNUNET_RECLAIM_presentation_new (presentation->type,
2541 presentation->data,
2542 presentation->
2543 data_size);
2544 atle->presentation->credential_id = presentation->credential_id;
2545 GNUNET_CONTAINER_DLL_insert (handle->presentations->list_head,
2546 handle->presentations->list_tail,
2547 atle);
2548 }
2549}

References GNUNET_RECLAIM_AttributeListEntry::attribute, cleanup_handle(), GNUNET_RECLAIM_Attribute::credential, GNUNET_RECLAIM_Presentation::credential_id, GNUNET_RECLAIM_Attribute::data, GNUNET_RECLAIM_Presentation::data, data_size, GNUNET_RECLAIM_Attribute::data_size, GNUNET_RECLAIM_Attribute::flag, GNUNET_assert, GNUNET_CONTAINER_DLL_insert, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_remove(), GNUNET_CRYPTO_hash(), GNUNET_CRYPTO_public_key_from_string(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_RECLAIM_attribute_new(), GNUNET_RECLAIM_id_is_equal, GNUNET_RECLAIM_presentation_new(), GNUNET_REST_create_response(), GNUNET_SCHEDULER_cancel(), GNUNET_strdup, GNUNET_YES, handle, GNUNET_RECLAIM_Attribute::id, identity, key, GNUNET_RECLAIM_Attribute::name, GNUNET_RECLAIM_PresentationListEntry::next, oidc_code_cache, OIDC_generate_userinfo(), GNUNET_RECLAIM_PresentationListEntry::presentation, GNUNET_RECLAIM_Attribute::type, and GNUNET_RECLAIM_Presentation::type.

Here is the call graph for this function:

◆ consume_fail()

static void consume_fail ( void *  cls)
static

Remove the cached item

Definition at line 2553 of file openid_plugin.c.

2554{
2555 struct RequestHandle *handle = cls;
2556 struct GNUNET_HashCode cache_key;
2557 struct GNUNET_RECLAIM_AttributeList *cl = NULL;
2558 struct GNUNET_RECLAIM_PresentationList *pl = NULL;
2560 struct GNUNET_CRYPTO_PublicKey cid;
2561 struct MHD_Response *resp;
2562 struct GNUNET_CRYPTO_PublicKey issuer;
2563 char *nonce;
2564 char *cached_code;
2565 char *result_str;
2566 char *received_cid;
2567 char *emsg;
2568 char *tmp;
2569 char *key;
2570
2571 handle->consume_timeout_op = NULL;
2572 if (NULL != handle->idp_op)
2573 GNUNET_RECLAIM_cancel (handle->idp_op);
2574 handle->idp_op = NULL;
2575
2577 "Ticket consumptioned timed out. Using cache...\n");
2578 GNUNET_CRYPTO_hash (handle->access_token,
2579 strlen (handle->access_token),
2580 &cache_key);
2582 &cache_key);
2583 if (NULL == cached_code)
2584 {
2586 handle->edesc = GNUNET_strdup ("No Access Token in cache!");
2587 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2589 return;
2590 }
2596 &cache_key,
2597 cached_code));
2599 GNUNET_STRINGS_string_to_data (received_cid,
2600 strlen (received_cid),
2601 &cid,
2602 sizeof(struct GNUNET_CRYPTO_PublicKey));
2603
2604 // decode code
2605 if (GNUNET_OK != OIDC_parse_authz_code (received_cid, &cid,
2606 cached_code, NULL, &ticket,
2607 &cl, &pl, &nonce,
2609 emsg))
2610 {
2612 handle->edesc = emsg;
2613 handle->response_code = MHD_HTTP_BAD_REQUEST;
2614 GNUNET_free (cached_code);
2615 if (NULL != nonce)
2616 GNUNET_free (nonce);
2618 return;
2619 }
2620
2621 GNUNET_free (cached_code);
2622
2623 tmp = GNUNET_strdup (handle->ticket.gns_name);
2624 GNUNET_assert (NULL != strtok (tmp, "."));
2625 key = strtok (NULL, ".");
2626 GNUNET_assert (NULL != key);
2629 GNUNET_free (tmp);
2630 result_str = OIDC_generate_userinfo (&issuer,
2631 cl,
2632 pl);
2633 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2634 resp = GNUNET_REST_create_response (result_str);
2635 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2636 GNUNET_free (result_str);
2637 GNUNET_free (nonce);
2641}

References cleanup_handle(), do_error(), do_userinfo_error(), get_url_parameter_copy(), GNUNET_assert, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_remove(), GNUNET_CRYPTO_hash(), GNUNET_CRYPTO_public_key_from_string(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_OK, GNUNET_RECLAIM_attribute_list_destroy(), GNUNET_RECLAIM_cancel(), GNUNET_RECLAIM_presentation_list_destroy(), GNUNET_REST_create_response(), GNUNET_SCHEDULER_add_now(), GNUNET_strdup, GNUNET_STRINGS_string_to_data(), GNUNET_YES, handle, key, OIDC_CLIENT_ID_KEY, oidc_code_cache, OIDC_ERROR_KEY_INVALID_REQUEST, OIDC_ERROR_KEY_INVALID_TOKEN, OIDC_generate_userinfo(), OIDC_parse_authz_code(), OIDC_VERIFICATION_NO_CODE_VERIFIER, and ticket.

Referenced by userinfo_endpoint().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ userinfo_endpoint()

static void userinfo_endpoint ( struct GNUNET_REST_RequestHandle con_handle,
const char *  url,
void *  cls 
)
static

Responds to userinfo GET and url-encoded POST request.

Parameters
con_handlethe connection handle
urlthe url
clsthe RequestHandle

Definition at line 2652 of file openid_plugin.c.

2655{
2656 // TODO expiration time
2657 struct RequestHandle *handle = cls;
2659 char delimiter[] = " ";
2660 struct GNUNET_HashCode cache_key;
2661 char *authorization;
2662 char *authorization_type;
2663 char *authorization_access_token;
2664
2665 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting userinfo\n");
2668 &cache_key);
2670 ->header_param_map,
2671 &cache_key))
2672 {
2674 handle->edesc = GNUNET_strdup ("No Access Token");
2675 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2677 return;
2678 }
2679 authorization =
2680 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
2681 &cache_key);
2682
2683 // split header in "Bearer" and access_token
2684 authorization = GNUNET_strdup (authorization);
2685 authorization_type = strtok (authorization, delimiter);
2686 if ((NULL == authorization_type) ||
2687 (0 != strcmp ("Bearer", authorization_type)))
2688 {
2690 handle->edesc = GNUNET_strdup ("No Access Token");
2691 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2693 GNUNET_free (authorization);
2694 return;
2695 }
2696 authorization_access_token = strtok (NULL, delimiter);
2697 if (NULL == authorization_access_token)
2698 {
2700 handle->edesc = GNUNET_strdup ("Access token missing");
2701 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2703 GNUNET_free (authorization);
2704 return;
2705 }
2706
2707 {
2708 char *rp_uri;
2709 if (GNUNET_OK != OIDC_access_token_parse (authorization_access_token,
2710 &ticket, &rp_uri))
2711 {
2713 handle->edesc = GNUNET_strdup ("The access token is invalid");
2714 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2716 GNUNET_free (authorization);
2717 return;
2718
2719 }
2720 GNUNET_assert (NULL != ticket);
2721 handle->ticket = *ticket;
2723 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Consuming ticket\n");
2724 handle->attr_userinfo_list =
2726 handle->presentations =
2728
2729 /* If the consume takes too long, we use values from the cache */
2730 handle->access_token = GNUNET_strdup (authorization_access_token);
2732 &consume_fail,
2733 handle);
2735 &handle->ticket,
2736 rp_uri,
2738 handle);
2739 GNUNET_free (authorization);
2740 GNUNET_free (rp_uri);
2741 }
2742}

References consume_fail(), consume_ticket, consume_timeout, do_userinfo_error(), GNUNET_assert, GNUNET_CONTAINER_multihashmap_contains(), GNUNET_CONTAINER_multihashmap_get(), GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_RECLAIM_ticket_consume(), GNUNET_SCHEDULER_add_delayed(), GNUNET_SCHEDULER_add_now(), GNUNET_strdup, handle, idp, OIDC_access_token_parse(), OIDC_AUTHORIZATION_HEADER_KEY, OIDC_ERROR_KEY_INVALID_TOKEN, and ticket.

Referenced by REST_openid_process_request().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ jwks_endpoint()

static void jwks_endpoint ( struct GNUNET_REST_RequestHandle con_handle,
const char *  url,
void *  cls 
)
static

Responds to /jwks.json.

Parameters
con_handlethe connection handle
urlthe url
clsthe RequestHandle

Definition at line 2753 of file openid_plugin.c.

2756{
2757 char *oidc_directory;
2758 char *oidc_jwk_path;
2759 char *oidc_jwk_pub_str;
2760 json_t *oidc_jwk_tmp;
2761 struct MHD_Response *resp;
2762 struct RequestHandle *handle = cls;
2763
2764 oidc_jwk_path = get_oidc_jwk_path (cls);
2765 oidc_jwk_tmp = read_jwk_from_file (oidc_jwk_path);
2766
2767 // Check if secret JWK exists
2768 if (! oidc_jwk_tmp)
2769 {
2770 // Generate and save a new key
2771 oidc_jwk_tmp = generate_jwk ();
2772 oidc_directory = get_oidc_dir_path (cls);
2773
2774 // Create new oidc directory
2775 if (GNUNET_OK != GNUNET_DISK_directory_create (oidc_directory))
2776 {
2778 ("Failed to create directory `%s' for storing oidc data\n"),
2779 oidc_directory);
2780 }
2781 else
2782 {
2783 write_jwk_to_file (oidc_jwk_path, oidc_jwk_tmp);
2784 }
2785 }
2786
2787 // Convert secret JWK to public JWK
2788 jose_jwk_pub (NULL, oidc_jwk_tmp);
2789
2790 // Encode JWK as string and return to API endpoint
2791 oidc_jwk_pub_str = json_dumps (oidc_jwk_tmp, JSON_INDENT (1));
2792 resp = GNUNET_REST_create_response (oidc_jwk_pub_str);
2793 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2794 json_decref (oidc_jwk_tmp);
2795 GNUNET_free (oidc_jwk_pub_str);
2796 GNUNET_free (oidc_jwk_pub_str);
2798}

References cleanup_handle(), generate_jwk(), get_oidc_dir_path(), get_oidc_jwk_path(), GNUNET_DISK_directory_create(), GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_OK, GNUNET_REST_create_response(), handle, read_jwk_from_file(), and write_jwk_to_file().

Referenced by REST_openid_process_request().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ list_ego()

static void list_ego ( void *  cls,
struct GNUNET_IDENTITY_Ego ego,
void **  ctx,
const char *  identifier 
)
static

If listing is enabled, prints information about the egos.

This function is initially called for all egos and then again whenever a ego's identifier changes or if it is deleted. At the end of the initial pass over all egos, the function is once called with 'NULL' for 'ego'. That does NOT mean that the callback won't be invoked in the future or that there was an error.

When used with 'GNUNET_IDENTITY_create', this function is only called ONCE, and 'NULL' being passed in 'ego' does indicate an error (for example because name is taken or no default value is known). If 'ego' is non-NULL and if '*ctx' is set in those callbacks, the value WILL be passed to a subsequent call to the identity callback of 'GNUNET_IDENTITY_connect' (if that one was not NULL).

When an identity is renamed, this function is called with the (known) ego but the NEW identifier.

When an identity is deleted, this function is called with the (known) ego and "NULL" for the 'identifier'. In this case, the 'ego' is henceforth invalid (and the 'ctx' should also be cleaned up).

Parameters
clsclosure
egoego handle
ctxcontext for application to store data for this ego (during the lifetime of this process, initially NULL)
identifieridentifier assigned by the user for this ego, NULL if the user just deleted the ego and it must thus no longer be used

Definition at line 2834 of file openid_plugin.c.

2838{
2839 struct EgoEntry *ego_entry;
2841
2842 if (NULL == ego)
2843 {
2845 return;
2846 }
2848
2849 {
2850 ego_entry = GNUNET_new (struct EgoEntry);
2853 ego_entry->ego = ego;
2854 ego_entry->identifier = GNUNET_strdup (identifier);
2856 ego_tail,
2857 ego_entry);
2858 return;
2859 }
2860 /* Ego renamed or added */
2861 if (identifier != NULL)
2862 {
2863 for (ego_entry = ego_head; NULL != ego_entry;
2864 ego_entry = ego_entry->next)
2865 {
2866 if (ego_entry->ego == ego)
2867 {
2868 /* Rename */
2869 GNUNET_free (ego_entry->identifier);
2870 ego_entry->identifier = GNUNET_strdup (identifier);
2871 break;
2872 }
2873 }
2874 if (NULL == ego_entry)
2875 {
2876 /* Add */
2877 ego_entry = GNUNET_new (struct EgoEntry);
2880 ego_entry->ego = ego;
2881 ego_entry->identifier = GNUNET_strdup (identifier);
2883 ego_tail,
2884 ego_entry);
2885 }
2886 }
2887 else
2888 {
2889 /* Delete */
2890 for (ego_entry = ego_head; NULL != ego_entry;
2891 ego_entry = ego_entry->next)
2892 {
2893 if (ego_entry->ego == ego)
2894 break;
2895 }
2896 if (NULL == ego_entry)
2897 return; /* Not found */
2898
2900 ego_tail,
2901 ego_entry);
2902 GNUNET_free (ego_entry->identifier);
2903 GNUNET_free (ego_entry->keystring);
2904 GNUNET_free (ego_entry);
2905 return;
2906 }
2907}

References EgoEntry::ego, ego_head, ego_tail, GNUNET_CONTAINER_DLL_insert_tail, GNUNET_CONTAINER_DLL_remove, GNUNET_CRYPTO_public_key_to_string(), GNUNET_free, GNUNET_IDENTITY_ego_get_public_key(), GNUNET_new, GNUNET_strdup, ID_REST_STATE_INIT, ID_REST_STATE_POST_INIT, EgoEntry::identifier, EgoEntry::keystring, EgoEntry::next, pk, and state.

Referenced by REST_openid_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ oidc_config_endpoint()

static void oidc_config_endpoint ( struct GNUNET_REST_RequestHandle con_handle,
const char *  url,
void *  cls 
)
static

Definition at line 2911 of file openid_plugin.c.

2914{
2915 json_t *oidc_config;
2916 json_t *auth_methods;
2917 json_t *sig_algs;
2918 json_t *scopes;
2919 json_t *response_types;
2920 json_t *sub_types;
2921 json_t *claim_types;
2922 char *oidc_config_str;
2923 struct MHD_Response *resp;
2924 struct RequestHandle *handle = cls;
2925
2926 oidc_config = json_object ();
2927 // FIXME get from config?
2928 json_object_set_new (oidc_config,
2929 "issuer", json_string ("http://localhost:7776"));
2930 json_object_set_new (oidc_config,
2931 "authorization_endpoint",
2932 json_string ("https://api.reclaim/openid/authorize"));
2933 json_object_set_new (oidc_config,
2934 "token_endpoint",
2935 json_string ("http://localhost:7776/openid/token"));
2936 auth_methods = json_array ();
2937 json_array_append_new (auth_methods,
2938 json_string ("client_secret_basic"));
2939 json_array_append_new (auth_methods,
2940 json_string ("client_secret_post"));
2941 json_object_set_new (oidc_config,
2942 "token_endpoint_auth_methods_supported",
2943 auth_methods);
2944 sig_algs = json_array ();
2945 json_array_append_new (sig_algs,
2946 json_string ("HS512"));
2947 json_array_append_new (sig_algs,
2948 json_string ("RS256"));
2949 json_object_set_new (oidc_config,
2950 "id_token_signing_alg_values_supported",
2951 sig_algs);
2952 json_object_set_new (oidc_config,
2953 "jwks_uri",
2954 json_string ("http://localhost:7776/jwks.json"));
2955 json_object_set_new (oidc_config,
2956 "userinfo_endpoint",
2957 json_string ("http://localhost:7776/openid/userinfo"));
2958 scopes = json_array ();
2959 json_array_append_new (scopes,
2960 json_string ("openid"));
2961 json_array_append_new (scopes,
2962 json_string ("profile"));
2963 json_array_append_new (scopes,
2964 json_string ("email"));
2965 json_array_append_new (scopes,
2966 json_string ("address"));
2967 json_array_append_new (scopes,
2968 json_string ("phone"));
2969 json_object_set_new (oidc_config,
2970 "scopes_supported",
2971 scopes);
2972 response_types = json_array ();
2973 json_array_append_new (response_types,
2974 json_string ("code"));
2975 json_object_set_new (oidc_config,
2976 "response_types_supported",
2977 response_types);
2978 sub_types = json_array ();
2979 json_array_append_new (sub_types,
2980 json_string ("public")); /* no pairwise support */
2981 json_object_set_new (oidc_config,
2982 "subject_types_supported",
2983 sub_types);
2984 claim_types = json_array ();
2985 json_array_append_new (claim_types,
2986 json_string ("normal"));
2987 json_array_append_new (claim_types,
2988 json_string ("aggregated"));
2989 json_object_set_new (oidc_config,
2990 "claim_types_supported",
2991 claim_types);
2992 json_object_set_new (oidc_config,
2993 "claims_parameter_supported",
2994 json_boolean (1));
2995 oidc_config_str = json_dumps (oidc_config, JSON_INDENT (1));
2996 resp = GNUNET_REST_create_response (oidc_config_str);
2997 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2998 json_decref (oidc_config);
2999 GNUNET_free (oidc_config_str);
3001}

References cleanup_handle(), GNUNET_free, GNUNET_REST_create_response(), and handle.

Referenced by REST_openid_process_request().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ oidc_config_cors()

static void oidc_config_cors ( struct GNUNET_REST_RequestHandle con_handle,
const char *  url,
void *  cls 
)
static

Respond to OPTIONS request.

Parameters
con_handlethe connection handle
urlthe url
clsthe RequestHandle

Definition at line 3012 of file openid_plugin.c.

3015{
3016 struct MHD_Response *resp;
3017 struct RequestHandle *handle = cls;
3018
3019 // For now, independent of path return all options
3020 resp = GNUNET_REST_create_response (NULL);
3021 GNUNET_assert (MHD_NO !=
3022 MHD_add_response_header (resp,
3023 "Access-Control-Allow-Methods",
3024 allow_methods));
3025 GNUNET_assert (MHD_NO !=
3026 MHD_add_response_header (resp,
3027 "Access-Control-Allow-Origin",
3028 "*"));
3029 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
3031 return;
3032}

References allow_methods, cleanup_handle(), GNUNET_assert, GNUNET_REST_create_response(), and handle.

Referenced by REST_openid_process_request().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ REST_openid_process_request()

enum GNUNET_GenericReturnValue REST_openid_process_request ( void *  plugin,
struct GNUNET_REST_RequestHandle conndata_handle,
GNUNET_REST_ResultProcessor  proc,
void *  proc_cls 
)

Function processing the REST call.

Parameters
methodHTTP method
urlURL of the HTTP request
databody of the HTTP request (optional)
data_sizelength of the body
proccallback function for the result
proc_clsclosure for proc
Returns
GNUNET_OK if request accepted

Definition at line 3036 of file openid_plugin.c.

3040{
3041 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
3043 static const struct GNUNET_REST_RequestHandler handlers[] =
3044 { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint },
3045 { MHD_HTTP_METHOD_POST,
3047 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont },
3048 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
3049 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
3050 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
3051 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_JWKS, &jwks_endpoint },
3052 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_OIDC_CONFIG,
3054 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC_CONFIG,
3056 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont },
3058
3059 handle->oidc = GNUNET_new (struct OIDC_Variables);
3060 if (NULL == OIDC_cookie_jar_map)
3062 GNUNET_NO);
3063 if (NULL == oidc_code_cache)
3065 GNUNET_NO);
3066
3067 handle->response_code = 0;
3069 handle->proc_cls = proc_cls;
3070 handle->proc = proc;
3071 handle->rest_handle = rest_handle;
3072 handle->url = GNUNET_strdup (rest_handle->url);
3073 handle->timeout_task =
3077 handle);
3078 if (handle->url[strlen (handle->url) - 1] == '/')
3079 handle->url[strlen (handle->url) - 1] = '\0';
3080 if (GNUNET_NO ==
3081 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
3082 return GNUNET_NO;
3083
3084 return GNUNET_YES;
3085}

References authorize_endpoint(), do_timeout(), GNUNET_CONTAINER_DLL_insert, GNUNET_CONTAINER_multihashmap_create(), GNUNET_new, GNUNET_NO, GNUNET_REST_API_JWKS, GNUNET_REST_API_NS_AUTHORIZE, GNUNET_REST_API_NS_LOGIN, GNUNET_REST_API_NS_OIDC, GNUNET_REST_API_NS_OIDC_CONFIG, GNUNET_REST_API_NS_TOKEN, GNUNET_REST_API_NS_USERINFO, GNUNET_REST_handle_request(), GNUNET_REST_HANDLER_END, GNUNET_SCHEDULER_add_delayed(), GNUNET_strdup, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, handle, handlers, jwks_endpoint(), login_cont(), oidc_code_cache, oidc_config_cors(), oidc_config_endpoint(), OIDC_cookie_jar_map, options_cont(), GNUNET_REST_RequestHandler::proc, requests_head, requests_tail, token_endpoint(), GNUNET_REST_RequestHandle::url, and userinfo_endpoint().

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ REST_openid_init()

void * REST_openid_init ( const struct GNUNET_CONFIGURATION_Handle c)

Entry point for the plugin.

Parameters
clsConfig info
Returns
NULL on error, otherwise the plugin context

Definition at line 3095 of file openid_plugin.c.

3096{
3097 static struct Plugin plugin;
3098 struct GNUNET_REST_Plugin *api;
3099
3100 oid_cfg = c;
3101 if (NULL != plugin.cfg)
3102 return NULL; /* can only initialize once! */
3103 memset (&plugin, 0, sizeof(struct Plugin));
3104 plugin.cfg = oid_cfg;
3105 api = GNUNET_new (struct GNUNET_REST_Plugin);
3106 api->cls = &plugin;
3112 "reclaim-rest-plugin",
3113 "OIDC_USERINFO_CONSUME_TIMEOUT",
3115 {
3117 }
3118
3119
3122 "%s, %s, %s, %s, %s",
3123 MHD_HTTP_METHOD_GET,
3124 MHD_HTTP_METHOD_POST,
3125 MHD_HTTP_METHOD_PUT,
3126 MHD_HTTP_METHOD_DELETE,
3127 MHD_HTTP_METHOD_OPTIONS);
3128
3130 _ ("OpenID Connect REST API initialized\n"));
3131 return api;
3132}

References _, allow_methods, GNUNET_REST_Plugin::cls, CONSUME_TIMEOUT, consume_timeout, gns_handle, GNUNET_asprintf(), GNUNET_CONFIGURATION_get_value_time(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_GNS_connect(), GNUNET_IDENTITY_connect(), GNUNET_log, GNUNET_new, GNUNET_OK, GNUNET_RECLAIM_connect(), GNUNET_REST_API_NS_OIDC, ID_REST_STATE_INIT, identity_handle, idp, list_ego(), GNUNET_REST_Plugin::name, oid_cfg, plugin, and state.

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cleanup_hashmap()

static int cleanup_hashmap ( void *  cls,
const struct GNUNET_HashCode key,
void *  value 
)
static

Definition at line 3136 of file openid_plugin.c.

3137{
3139 return GNUNET_YES;
3140}

References GNUNET_free, GNUNET_YES, and value.

Referenced by REST_openid_done().

Here is the caller graph for this function:

◆ REST_openid_done()

void REST_openid_done ( struct GNUNET_REST_Plugin api)

Exit point from the plugin.

Parameters
clsthe plugin context (as returned by "init")
Returns
always NULL

Definition at line 3144 of file openid_plugin.c.

3145{
3146 struct Plugin *plugin = api->cls;
3147 struct EgoEntry *ego_entry;
3148
3149 plugin->cfg = NULL;
3150 while (NULL != requests_head)
3152 if (NULL != OIDC_cookie_jar_map)
3153 {
3156 NULL);
3158 }
3159 if (NULL != oidc_code_cache)
3160 {
3163 NULL);
3165 }
3166
3168 if (NULL != gns_handle)
3170 if (NULL != identity_handle)
3172 if (NULL != idp)
3174 while (NULL != (ego_entry = ego_head))
3175 {
3177 ego_tail,
3178 ego_entry);
3179 GNUNET_free (ego_entry->identifier);
3180 GNUNET_free (ego_entry->keystring);
3181 GNUNET_free (ego_entry);
3182 }
3183 GNUNET_free (api);
3185 "OpenID Connect REST plugin is finished\n");
3186}

References allow_methods, Plugin::api, cleanup_handle(), cleanup_hashmap(), GNUNET_BLOCK_PluginFunctions::cls, ego_head, ego_tail, gns_handle, GNUNET_CONTAINER_DLL_remove, GNUNET_CONTAINER_multihashmap_destroy(), GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_GNS_disconnect(), GNUNET_IDENTITY_disconnect(), GNUNET_log, GNUNET_RECLAIM_disconnect(), EgoEntry::identifier, identity_handle, idp, EgoEntry::keystring, oidc_code_cache, OIDC_cookie_jar_map, plugin, and requests_head.

Referenced by do_shutdown().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ OIDC_ignored_parameter_array

const char* OIDC_ignored_parameter_array[]
static
Initial value:
= { "display",
"prompt",
"ui_locales",
"response_mode",
"id_token_hint",
"login_hint",
"acr_values" }

OIDC ignored parameter array.

Definition at line 249 of file openid_plugin.c.

249 { "display",
250 "prompt",
251 "ui_locales",
252 "response_mode",
253 "id_token_hint",
254 "login_hint",
255 "acr_values" };

Referenced by build_authz_response().

◆ oidc_code_cache

struct GNUNET_CONTAINER_MultiHashMap* oidc_code_cache

OIDC hashmap for cached access tokens and codes.

Definition at line 260 of file openid_plugin.c.

Referenced by consume_fail(), consume_ticket(), REST_openid_done(), REST_openid_process_request(), and token_endpoint().

◆ OIDC_cookie_jar_map

struct GNUNET_CONTAINER_MultiHashMap* OIDC_cookie_jar_map

OIDC hashmap that keeps track of issued cookies.

Definition at line 265 of file openid_plugin.c.

Referenced by code_redirect(), cookie_identity_interpretation(), login_cont(), REST_openid_done(), and REST_openid_process_request().

◆ oid_cfg

const struct GNUNET_CONFIGURATION_Handle* oid_cfg

The configuration handle.

Definition at line 270 of file openid_plugin.c.

Referenced by authorize_endpoint(), check_authorization(), get_oidc_dir_path(), login_redirect(), REST_openid_init(), and token_endpoint().

◆ allow_methods

char* allow_methods
static

HTTP methods allows for this plugin.

Definition at line 275 of file openid_plugin.c.

Referenced by oidc_config_cors(), options_cont(), REST_openid_done(), and REST_openid_init().

◆ ego_head

struct EgoEntry* ego_head
static

◆ ego_tail

struct EgoEntry* ego_tail
static

Ego list.

Definition at line 285 of file openid_plugin.c.

Referenced by authorize_endpoint(), list_ego(), and REST_openid_done().

◆ state

int state
static

The processing state.

Definition at line 290 of file openid_plugin.c.

Referenced by list_ego(), and REST_openid_init().

◆ identity_handle

struct GNUNET_IDENTITY_Handle* identity_handle
static

Handle to Identity service.

Definition at line 295 of file openid_plugin.c.

Referenced by REST_openid_done(), and REST_openid_init().

◆ gns_handle

struct GNUNET_GNS_Handle* gns_handle
static

GNS handle.

Definition at line 300 of file openid_plugin.c.

Referenced by client_redirect(), REST_openid_done(), and REST_openid_init().

◆ idp

◆ consume_timeout

struct GNUNET_TIME_Relative consume_timeout
static

Timeout for consume call on userinfo.

Definition at line 310 of file openid_plugin.c.

Referenced by REST_openid_init(), and userinfo_endpoint().

◆ oidc_jwk

json_t* oidc_jwk

The RSA key used by the oidc endpoint.

Definition at line 323 of file openid_plugin.c.

◆ requests_head

struct RequestHandle* requests_head
static

DLL.

Definition at line 587 of file openid_plugin.c.

Referenced by cleanup_handle(), REST_openid_done(), and REST_openid_process_request().

◆ requests_tail

struct RequestHandle* requests_tail
static

DLL.

Definition at line 592 of file openid_plugin.c.

Referenced by cleanup_handle(), and REST_openid_process_request().