GNUnet 0.25.2-11-g84e94e98c
 
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_BlindablePublicKey *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_BlindablePublicKey *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_BlindablePublicKey *cid)
 
static const struct EgoEntryfind_ego (struct RequestHandle *handle, struct GNUNET_CRYPTO_BlindablePublicKey *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_BlindablePublicKey *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,
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,
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_BlindablePublicKey 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_BlindablePublicKey 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_BlindablePrivateKey *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 ))
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}
1868
1869
1877static void
1878login_cont (struct GNUNET_REST_RequestHandle *con_handle,
1879 const char *url,
1880 void *cls)
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}
1943
1944
1945static int
1947 char **client_id,
1948 char **client_secret)
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}
1998
1999
2000static int
2002 char **client_id,
2003 char **client_secret)
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}
2044
2045
2046static int
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
2087 GNUNET_free (received_cid);
2088 return GNUNET_OK;
2089
2090 }
2091
2092 // check client password
2094 "reclaim-rest-plugin",
2095 "OIDC_CLIENT_HMAC_SECRET",
2096 &expected_pass))
2097 {
2098 if (0 != strcmp (expected_pass, received_cpw))
2099 {
2100 GNUNET_free (expected_pass);
2102 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2103 GNUNET_free (received_cpw);
2104 GNUNET_free (received_cid);
2105 return GNUNET_SYSERR;
2106 }
2107 GNUNET_free (expected_pass);
2108 }
2109 else
2110 {
2111 GNUNET_free (received_cpw);
2112 GNUNET_free (received_cid);
2114 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
2115 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2116 return GNUNET_SYSERR;
2117 }
2118 // check client_id
2119 for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
2120 handle->ego_entry = handle->ego_entry->next)
2121 {
2122 if (0 == strcmp (handle->ego_entry->keystring, received_cid))
2123 break;
2124 }
2125 if (NULL == handle->ego_entry)
2126 {
2127 GNUNET_free (received_cpw);
2128 GNUNET_free (received_cid);
2130 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2131 return GNUNET_SYSERR;
2132 }
2133 GNUNET_STRINGS_string_to_data (received_cid,
2134 strlen (received_cid),
2135 cid,
2137 );
2138
2139 GNUNET_free (received_cpw);
2140 GNUNET_free (received_cid);
2141 return GNUNET_OK;
2142}
2143
2144
2145static const struct EgoEntry *
2147 struct GNUNET_CRYPTO_BlindablePublicKey *test_key)
2148{
2149 struct EgoEntry *ego_entry;
2150 struct GNUNET_CRYPTO_BlindablePublicKey pub_key;
2151
2152 for (ego_entry = ego_head; NULL != ego_entry;
2153 ego_entry = ego_entry->next)
2154 {
2155 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key);
2156 if (0 == GNUNET_memcmp (&pub_key, test_key))
2157 return ego_entry;
2158 }
2159 return NULL;
2160}
2161
2162
2170static void
2171token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2172 const char *url,
2173 void *cls)
2174{
2175 struct RequestHandle *handle = cls;
2176 const struct EgoEntry *ego_entry = NULL;
2177 struct GNUNET_TIME_Relative expiration_time;
2178 struct GNUNET_RECLAIM_AttributeList *cl = NULL;
2179 struct GNUNET_RECLAIM_PresentationList *pl = NULL;
2182 struct GNUNET_HashCode cache_key;
2183 struct MHD_Response *resp = NULL;
2185 char *grant_type = NULL;
2186 char *code = NULL;
2187 char *json_response = NULL;
2188 char *id_token = NULL;
2189 char *access_token = NULL;
2190 char *jwa = NULL;
2191 char *jwt_secret = NULL;
2192 char *nonce = NULL;
2193 char *code_verifier = NULL;
2194 json_t *oidc_jwk_tmp = NULL;
2195 char *oidc_jwk_path = NULL;
2196 char *oidc_directory = NULL;
2197 char *tmp_at = NULL;
2198 char *received_cid = NULL;
2199 char *emsg = NULL;
2200
2201 /*
2202 * Check Authorization
2203 */
2205 {
2207 "OIDC authorization for token endpoint failed\n");
2209 return;
2210 }
2212
2213 /*
2214 * Check parameter
2215 */
2216
2217 // TODO Do not allow multiple equal parameter names
2218 // REQUIRED grant_type
2220 strlen (OIDC_GRANT_TYPE_KEY),
2221 &cache_key);
2223 if (NULL == grant_type)
2224 {
2226 handle->edesc = GNUNET_strdup ("missing parameter grant_type");
2227 handle->response_code = MHD_HTTP_BAD_REQUEST;
2229 return;
2230 }
2231
2232 // Check parameter grant_type == "authorization_code"
2233 if (0 != strcmp (OIDC_GRANT_TYPE_VALUE, grant_type))
2234 {
2236 handle->response_code = MHD_HTTP_BAD_REQUEST;
2237 GNUNET_free (grant_type);
2239 return;
2240 }
2241 GNUNET_free (grant_type);
2242 // REQUIRED code
2244 if (NULL == code)
2245 {
2247 handle->edesc = GNUNET_strdup ("missing parameter code");
2248 handle->response_code = MHD_HTTP_BAD_REQUEST;
2250 return;
2251 }
2252 ego_entry = find_ego (handle, &cid);
2253 if (NULL == ego_entry)
2254 {
2256 handle->edesc = GNUNET_strdup ("Unknown client");
2257 handle->response_code = MHD_HTTP_BAD_REQUEST;
2258 GNUNET_free (code);
2260 return;
2261 }
2262
2263 // REQUIRED code verifier
2265 if (NULL == code_verifier)
2266 {
2268 "OAuth authorization request does not contain PKCE parameters!\n");
2269
2270 }
2271
2272 // decode code
2273 if (GNUNET_OK != OIDC_parse_authz_code (received_cid, &cid, code,
2274 code_verifier,
2275 &ticket,
2276 &cl, &pl, &nonce,
2278 &emsg))
2279 {
2281 handle->edesc = emsg;
2282 handle->response_code = MHD_HTTP_BAD_REQUEST;
2283 GNUNET_free (code);
2284 if (NULL != code_verifier)
2285 GNUNET_free (code_verifier);
2287 return;
2288 }
2289 if (NULL != code_verifier)
2290 GNUNET_free (code_verifier);
2291
2292 // create jwt
2294 "reclaim-rest-plugin",
2295 "expiration_time",
2296 &expiration_time))
2297 {
2299 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
2300 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2301 GNUNET_free (code);
2302 if (NULL != nonce)
2303 GNUNET_free (nonce);
2307 return;
2308 }
2309
2310 // Check if HMAC or RSA should be used
2312 "reclaim-rest-plugin",
2313 "oidc_json_web_algorithm",
2314 &jwa))
2315 {
2317 "Could not read OIDC JSON Web Algorithm config attribute."
2318 "Defaulting to RS256.");
2320 }
2321
2323
2324 if (! strcmp (jwa, JWT_ALG_VALUE_RSA))
2325 {
2326 // Replace for now
2327 oidc_jwk_path = get_oidc_jwk_path (cls);
2328 oidc_jwk_tmp = read_jwk_from_file (oidc_jwk_path);
2329
2330 // Check if secret JWK exists
2331 if (! oidc_jwk_tmp)
2332 {
2333 // Generate and save a new key
2334 oidc_jwk_tmp = generate_jwk ();
2335 oidc_directory = get_oidc_dir_path (cls);
2336
2337 // Create new oidc directory
2338 if (GNUNET_OK != GNUNET_DISK_directory_create (oidc_directory))
2339 {
2341 ("Failed to create directory `%s' for storing oidc data\n"),
2342 oidc_directory);
2343 }
2344 else
2345 {
2346 write_jwk_to_file (oidc_jwk_path, oidc_jwk_tmp);
2347 }
2348 }
2349
2350 // Generate oidc token
2351 id_token = OIDC_generate_id_token_rsa (received_cid,
2352 &issuer,
2353 cl,
2354 pl,
2355 &expiration_time,
2356 (NULL != nonce) ? nonce : NULL,
2357 oidc_jwk_tmp);
2358 }
2359 else if (! strcmp (jwa, JWT_ALG_VALUE_HMAC))
2360 {
2361 // TODO OPTIONAL acr,amr,azp
2363 "reclaim-rest-plugin",
2364 "jwt_secret",
2365 &jwt_secret))
2366 {
2368 handle->edesc = GNUNET_strdup ("No signing secret configured!");
2369 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2370 GNUNET_free (code);
2373 if (NULL != nonce)
2374 GNUNET_free (nonce);
2375 GNUNET_free (jwa);
2377 return;
2378 }
2379
2380 id_token = OIDC_generate_id_token_hmac (received_cid,
2381 &issuer,
2382 cl,
2383 pl,
2384 &expiration_time,
2385 (NULL != nonce) ? nonce : NULL,
2386 jwt_secret);
2387
2388 GNUNET_free (jwt_secret);
2389 }
2390 else
2391 {
2392 // TODO: OPTION NOT FOUND ERROR
2393 }
2394 GNUNET_free (jwa);
2395
2396 if (NULL != nonce)
2397 GNUNET_free (nonce);
2398 access_token = OIDC_access_token_new (&ticket, handle->oidc->redirect_uri);
2403 GNUNET_CRYPTO_hash (access_token,
2404 strlen (access_token),
2405 &cache_key);
2417 &cache_key);
2419 &cache_key,
2420 code,
2422 /* If there was a previous code in there, free the old value */
2423 if (NULL != tmp_at)
2424 {
2426 "OIDC access token already issued. Cleanup.\n");
2427 GNUNET_free (tmp_at);
2428 }
2429
2430 OIDC_build_token_response (access_token,
2431 id_token,
2432 &expiration_time,
2433 &json_response);
2434
2435 resp = GNUNET_REST_create_response (json_response);
2436 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2437 "Cache-Control",
2438 "no-store"));
2439 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2440 "Pragma", "no-cache"));
2441 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2442 "Content-Type",
2443 "application/json"));
2444 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2447 GNUNET_free (access_token);
2448 GNUNET_free (json_response);
2449 GNUNET_free (id_token);
2451}
2452
2453
2457static void
2458consume_ticket (void *cls,
2460 const struct GNUNET_RECLAIM_Attribute *attr,
2461 const struct GNUNET_RECLAIM_Presentation *presentation)
2462{
2463 struct RequestHandle *handle = cls;
2466 struct MHD_Response *resp;
2467 struct GNUNET_HashCode cache_key;
2468 char *result_str;
2469 char *cached_code;
2470
2471 if (NULL != handle->consume_timeout_op)
2472 GNUNET_SCHEDULER_cancel (handle->consume_timeout_op);
2473 handle->consume_timeout_op = NULL;
2474 handle->idp_op = NULL;
2475
2479 GNUNET_CRYPTO_hash (handle->access_token,
2480 strlen (handle->access_token),
2481 &cache_key);
2483 &cache_key);
2484 if (NULL != cached_code)
2485 {
2488 &cache_key,
2489 cached_code));
2490 GNUNET_free (cached_code);
2491 }
2492
2493
2494 if (NULL == identity)
2495 {
2497 char *key;
2498 char *tmp = GNUNET_strdup (handle->ticket.gns_name);
2499 GNUNET_assert (NULL != strtok (tmp, "."));
2500 key = strtok (NULL, ".");
2501 GNUNET_assert (NULL != key);
2504 );
2505 GNUNET_free (tmp);
2506 result_str = OIDC_generate_userinfo (&issuer,
2507 handle->attr_userinfo_list,
2508 handle->presentations);
2509 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2510 resp = GNUNET_REST_create_response (result_str);
2511 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2512 GNUNET_free (result_str);
2514 return;
2515 }
2518 &attr->credential,
2519 attr->type,
2520 attr->data,
2521 attr->data_size);
2522 ale->attribute->id = attr->id;
2523 ale->attribute->flag = attr->flag;
2524 ale->attribute->credential = attr->credential;
2525 GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
2526 handle->attr_userinfo_list->list_tail,
2527 ale);
2528 if (NULL == presentation)
2529 return;
2530 for (atle = handle->presentations->list_head;
2531 NULL != atle; atle = atle->next)
2532 {
2535 &presentation->credential_id))
2536 continue;
2537 break;
2538 }
2539 if (NULL == atle)
2540 {
2543 atle->presentation = GNUNET_RECLAIM_presentation_new (presentation->type,
2544 presentation->data,
2545 presentation->
2546 data_size);
2547 atle->presentation->credential_id = presentation->credential_id;
2548 GNUNET_CONTAINER_DLL_insert (handle->presentations->list_head,
2549 handle->presentations->list_tail,
2550 atle);
2551 }
2552}
2553
2554
2555static void
2556consume_fail (void *cls)
2557{
2558 struct RequestHandle *handle = cls;
2559 struct GNUNET_HashCode cache_key;
2560 struct GNUNET_RECLAIM_AttributeList *cl = NULL;
2561 struct GNUNET_RECLAIM_PresentationList *pl = NULL;
2564 struct MHD_Response *resp;
2566 char *nonce;
2567 char *cached_code;
2568 char *result_str;
2569 char *received_cid;
2570 char *emsg;
2571 char *tmp;
2572 char *key;
2573
2574 handle->consume_timeout_op = NULL;
2575 if (NULL != handle->idp_op)
2576 GNUNET_RECLAIM_cancel (handle->idp_op);
2577 handle->idp_op = NULL;
2578
2580 "Ticket consumptioned timed out. Using cache...\n");
2581 GNUNET_CRYPTO_hash (handle->access_token,
2582 strlen (handle->access_token),
2583 &cache_key);
2585 &cache_key);
2586 if (NULL == cached_code)
2587 {
2589 handle->edesc = GNUNET_strdup ("No Access Token in cache!");
2590 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2592 return;
2593 }
2599 &cache_key,
2600 cached_code));
2602 GNUNET_STRINGS_string_to_data (received_cid,
2603 strlen (received_cid),
2604 &cid,
2606 );
2607
2608 // decode code
2609 if (GNUNET_OK != OIDC_parse_authz_code (received_cid, &cid,
2610 cached_code, NULL, &ticket,
2611 &cl, &pl, &nonce,
2613 emsg))
2614 {
2616 handle->edesc = emsg;
2617 handle->response_code = MHD_HTTP_BAD_REQUEST;
2618 GNUNET_free (cached_code);
2619 if (NULL != nonce)
2620 GNUNET_free (nonce);
2622 return;
2623 }
2624
2625 GNUNET_free (cached_code);
2626
2627 tmp = GNUNET_strdup (handle->ticket.gns_name);
2628 GNUNET_assert (NULL != strtok (tmp, "."));
2629 key = strtok (NULL, ".");
2630 GNUNET_assert (NULL != key);
2633 GNUNET_free (tmp);
2634 result_str = OIDC_generate_userinfo (&issuer,
2635 cl,
2636 pl);
2637 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2638 resp = GNUNET_REST_create_response (result_str);
2639 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2640 GNUNET_free (result_str);
2641 GNUNET_free (nonce);
2645}
2646
2647
2655static void
2657 const char *url,
2658 void *cls)
2659{
2660 // TODO expiration time
2661 struct RequestHandle *handle = cls;
2663 char delimiter[] = " ";
2664 struct GNUNET_HashCode cache_key;
2665 char *authorization;
2666 char *authorization_type;
2667 char *authorization_access_token;
2668
2669 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting userinfo\n");
2672 &cache_key);
2674 ->header_param_map,
2675 &cache_key))
2676 {
2678 handle->edesc = GNUNET_strdup ("No Access Token");
2679 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2681 return;
2682 }
2683 authorization =
2684 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
2685 &cache_key);
2686
2687 // split header in "Bearer" and access_token
2688 authorization = GNUNET_strdup (authorization);
2689 authorization_type = strtok (authorization, delimiter);
2690 if ((NULL == authorization_type) ||
2691 (0 != strcmp ("Bearer", authorization_type)))
2692 {
2694 handle->edesc = GNUNET_strdup ("No Access Token");
2695 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2697 GNUNET_free (authorization);
2698 return;
2699 }
2700 authorization_access_token = strtok (NULL, delimiter);
2701 if (NULL == authorization_access_token)
2702 {
2704 handle->edesc = GNUNET_strdup ("Access token missing");
2705 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2707 GNUNET_free (authorization);
2708 return;
2709 }
2710
2711 {
2712 char *rp_uri;
2713 if (GNUNET_OK != OIDC_access_token_parse (authorization_access_token,
2714 &ticket, &rp_uri))
2715 {
2717 handle->edesc = GNUNET_strdup ("The access token is invalid");
2718 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2720 GNUNET_free (authorization);
2721 return;
2722
2723 }
2724 GNUNET_assert (NULL != ticket);
2725 handle->ticket = *ticket;
2727 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Consuming ticket\n");
2728 handle->attr_userinfo_list =
2730 handle->presentations =
2732
2733 /* If the consume takes too long, we use values from the cache */
2734 handle->access_token = GNUNET_strdup (authorization_access_token);
2736 &consume_fail,
2737 handle);
2739 &handle->ticket,
2740 rp_uri,
2742 handle);
2743 GNUNET_free (authorization);
2744 GNUNET_free (rp_uri);
2745 }
2746}
2747
2748
2756static void
2757jwks_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2758 const char *url,
2759 void *cls)
2760{
2761 char *oidc_directory;
2762 char *oidc_jwk_path;
2763 char *oidc_jwk_pub_str;
2764 json_t *oidc_jwk_tmp;
2765 struct MHD_Response *resp;
2766 struct RequestHandle *handle = cls;
2767
2768 oidc_jwk_path = get_oidc_jwk_path (cls);
2769 oidc_jwk_tmp = read_jwk_from_file (oidc_jwk_path);
2770
2771 // Check if secret JWK exists
2772 if (! oidc_jwk_tmp)
2773 {
2774 // Generate and save a new key
2775 oidc_jwk_tmp = generate_jwk ();
2776 oidc_directory = get_oidc_dir_path (cls);
2777
2778 // Create new oidc directory
2779 if (GNUNET_OK != GNUNET_DISK_directory_create (oidc_directory))
2780 {
2782 ("Failed to create directory `%s' for storing oidc data\n"),
2783 oidc_directory);
2784 }
2785 else
2786 {
2787 write_jwk_to_file (oidc_jwk_path, oidc_jwk_tmp);
2788 }
2789 }
2790
2791 // Convert secret JWK to public JWK
2792 jose_jwk_pub (NULL, oidc_jwk_tmp);
2793
2794 // Encode JWK as string and return to API endpoint
2795 oidc_jwk_pub_str = json_dumps (oidc_jwk_tmp, JSON_INDENT (1));
2796 resp = GNUNET_REST_create_response (oidc_jwk_pub_str);
2797 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2798 json_decref (oidc_jwk_tmp);
2799 GNUNET_free (oidc_jwk_pub_str);
2800 GNUNET_free (oidc_jwk_pub_str);
2802}
2803
2804
2837static void
2838list_ego (void *cls,
2839 struct GNUNET_IDENTITY_Ego *ego,
2840 void **ctx,
2841 const char *identifier)
2842{
2843 struct EgoEntry *ego_entry;
2845
2846 if (NULL == ego)
2847 {
2849 return;
2850 }
2852
2853 {
2854 ego_entry = GNUNET_new (struct EgoEntry);
2857 ego_entry->ego = ego;
2858 ego_entry->identifier = GNUNET_strdup (identifier);
2860 ego_tail,
2861 ego_entry);
2862 return;
2863 }
2864 /* Ego renamed or added */
2865 if (identifier != NULL)
2866 {
2867 for (ego_entry = ego_head; NULL != ego_entry;
2868 ego_entry = ego_entry->next)
2869 {
2870 if (ego_entry->ego == ego)
2871 {
2872 /* Rename */
2873 GNUNET_free (ego_entry->identifier);
2874 ego_entry->identifier = GNUNET_strdup (identifier);
2875 break;
2876 }
2877 }
2878 if (NULL == ego_entry)
2879 {
2880 /* Add */
2881 ego_entry = GNUNET_new (struct EgoEntry);
2884 ego_entry->ego = ego;
2885 ego_entry->identifier = GNUNET_strdup (identifier);
2887 ego_tail,
2888 ego_entry);
2889 }
2890 }
2891 else
2892 {
2893 /* Delete */
2894 for (ego_entry = ego_head; NULL != ego_entry;
2895 ego_entry = ego_entry->next)
2896 {
2897 if (ego_entry->ego == ego)
2898 break;
2899 }
2900 if (NULL == ego_entry)
2901 return; /* Not found */
2902
2904 ego_tail,
2905 ego_entry);
2906 GNUNET_free (ego_entry->identifier);
2907 GNUNET_free (ego_entry->keystring);
2908 GNUNET_free (ego_entry);
2909 return;
2910 }
2911}
2912
2913
2914static void
2916 const char *url,
2917 void *cls)
2918{
2919 json_t *oidc_config;
2920 json_t *auth_methods;
2921 json_t *sig_algs;
2922 json_t *scopes;
2923 json_t *response_types;
2924 json_t *sub_types;
2925 json_t *claim_types;
2926 char *oidc_config_str;
2927 struct MHD_Response *resp;
2928 struct RequestHandle *handle = cls;
2929
2930 oidc_config = json_object ();
2931 // FIXME get from config?
2932 json_object_set_new (oidc_config,
2933 "issuer", json_string ("http://localhost:7776"));
2934 json_object_set_new (oidc_config,
2935 "authorization_endpoint",
2936 json_string ("https://api.reclaim/openid/authorize"));
2937 json_object_set_new (oidc_config,
2938 "token_endpoint",
2939 json_string ("http://localhost:7776/openid/token"));
2940 auth_methods = json_array ();
2941 json_array_append_new (auth_methods,
2942 json_string ("client_secret_basic"));
2943 json_array_append_new (auth_methods,
2944 json_string ("client_secret_post"));
2945 json_object_set_new (oidc_config,
2946 "token_endpoint_auth_methods_supported",
2947 auth_methods);
2948 sig_algs = json_array ();
2949 json_array_append_new (sig_algs,
2950 json_string ("HS512"));
2951 json_array_append_new (sig_algs,
2952 json_string ("RS256"));
2953 json_object_set_new (oidc_config,
2954 "id_token_signing_alg_values_supported",
2955 sig_algs);
2956 json_object_set_new (oidc_config,
2957 "jwks_uri",
2958 json_string ("http://localhost:7776/jwks.json"));
2959 json_object_set_new (oidc_config,
2960 "userinfo_endpoint",
2961 json_string ("http://localhost:7776/openid/userinfo"));
2962 scopes = json_array ();
2963 json_array_append_new (scopes,
2964 json_string ("openid"));
2965 json_array_append_new (scopes,
2966 json_string ("profile"));
2967 json_array_append_new (scopes,
2968 json_string ("email"));
2969 json_array_append_new (scopes,
2970 json_string ("address"));
2971 json_array_append_new (scopes,
2972 json_string ("phone"));
2973 json_object_set_new (oidc_config,
2974 "scopes_supported",
2975 scopes);
2976 response_types = json_array ();
2977 json_array_append_new (response_types,
2978 json_string ("code"));
2979 json_object_set_new (oidc_config,
2980 "response_types_supported",
2981 response_types);
2982 sub_types = json_array ();
2983 json_array_append_new (sub_types,
2984 json_string ("public")); /* no pairwise support */
2985 json_object_set_new (oidc_config,
2986 "subject_types_supported",
2987 sub_types);
2988 claim_types = json_array ();
2989 json_array_append_new (claim_types,
2990 json_string ("normal"));
2991 json_array_append_new (claim_types,
2992 json_string ("aggregated"));
2993 json_object_set_new (oidc_config,
2994 "claim_types_supported",
2995 claim_types);
2996 json_object_set_new (oidc_config,
2997 "claims_parameter_supported",
2998 json_boolean (1));
2999 oidc_config_str = json_dumps (oidc_config, JSON_INDENT (1));
3000 resp = GNUNET_REST_create_response (oidc_config_str);
3001 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
3002 json_decref (oidc_config);
3003 GNUNET_free (oidc_config_str);
3005}
3006
3007
3015static void
3017 const char *url,
3018 void *cls)
3019{
3020 struct MHD_Response *resp;
3021 struct RequestHandle *handle = cls;
3022
3023 // For now, independent of path return all options
3024 resp = GNUNET_REST_create_response (NULL);
3025 GNUNET_assert (MHD_NO !=
3026 MHD_add_response_header (resp,
3027 "Access-Control-Allow-Methods",
3028 allow_methods));
3029 GNUNET_assert (MHD_NO !=
3030 MHD_add_response_header (resp,
3031 "Access-Control-Allow-Origin",
3032 "*"));
3033 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
3035 return;
3036}
3037
3038
3043 void *proc_cls)
3044{
3045 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
3047 static const struct GNUNET_REST_RequestHandler handlers[] =
3048 { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint },
3049 { MHD_HTTP_METHOD_POST,
3051 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont },
3052 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
3053 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
3054 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
3055 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_JWKS, &jwks_endpoint },
3056 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_OIDC_CONFIG,
3058 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC_CONFIG,
3060 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont },
3062
3063 handle->oidc = GNUNET_new (struct OIDC_Variables);
3064 if (NULL == OIDC_cookie_jar_map)
3066 GNUNET_NO);
3067 if (NULL == oidc_code_cache)
3069 GNUNET_NO);
3070
3071 handle->response_code = 0;
3073 handle->proc_cls = proc_cls;
3074 handle->proc = proc;
3075 handle->rest_handle = rest_handle;
3076 handle->url = GNUNET_strdup (rest_handle->url);
3077 handle->timeout_task =
3081 handle);
3082 if (handle->url[strlen (handle->url) - 1] == '/')
3083 handle->url[strlen (handle->url) - 1] = '\0';
3084 if (GNUNET_NO ==
3085 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
3086 return GNUNET_NO;
3087
3088 return GNUNET_YES;
3089}
3090
3091
3098void *
3100{
3101 static struct Plugin plugin;
3102 struct GNUNET_REST_Plugin *api;
3103
3104 oid_cfg = c;
3105 if (NULL != plugin.cfg)
3106 return NULL; /* can only initialize once! */
3107 memset (&plugin, 0, sizeof(struct Plugin));
3108 plugin.cfg = oid_cfg;
3109 api = GNUNET_new (struct GNUNET_REST_Plugin);
3110 api->cls = &plugin;
3116 "reclaim-rest-plugin",
3117 "OIDC_USERINFO_CONSUME_TIMEOUT",
3119 {
3121 }
3122
3123
3126 "%s, %s, %s, %s, %s",
3127 MHD_HTTP_METHOD_GET,
3128 MHD_HTTP_METHOD_POST,
3129 MHD_HTTP_METHOD_PUT,
3130 MHD_HTTP_METHOD_DELETE,
3131 MHD_HTTP_METHOD_OPTIONS);
3132
3134 _ ("OpenID Connect REST API initialized\n"));
3135 return api;
3136}
3137
3138
3139static int
3140cleanup_hashmap (void *cls, const struct GNUNET_HashCode *key, void *value)
3141{
3143 return GNUNET_YES;
3144}
3145
3146
3147void
3149{
3150 struct Plugin *plugin = api->cls;
3151 struct EgoEntry *ego_entry;
3152
3153 plugin->cfg = NULL;
3154 while (NULL != requests_head)
3156 if (NULL != OIDC_cookie_jar_map)
3157 {
3160 NULL);
3162 }
3163 if (NULL != oidc_code_cache)
3164 {
3167 NULL);
3169 }
3170
3172 if (NULL != gns_handle)
3174 if (NULL != identity_handle)
3176 if (NULL != idp)
3178 while (NULL != (ego_entry = ego_head))
3179 {
3181 ego_tail,
3182 ego_entry);
3183 GNUNET_free (ego_entry->identifier);
3184 GNUNET_free (ego_entry->keystring);
3185 GNUNET_free (ego_entry);
3186 }
3187 GNUNET_free (api);
3189 "OpenID Connect REST plugin is finished\n");
3190}
3191
3192
3193/* 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_BlindablePrivateKey pk
Private key from command line option, or NULL.
static struct GNUNET_CRYPTO_BlindablePublicKey pubkey
Public key of the zone to look in.
static char * pkey
Public key of the zone to look in, in ASCII.
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_BlindablePublicKey *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_BlindablePublicKey *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.
void GNUNET_IDENTITY_ego_get_public_key(struct GNUNET_IDENTITY_Ego *ego, struct GNUNET_CRYPTO_BlindablePublicKey *pk)
Get the identifier (public key) of an 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.
const struct GNUNET_CRYPTO_BlindablePrivateKey * GNUNET_IDENTITY_ego_get_private_key(const struct GNUNET_IDENTITY_Ego *ego)
Obtain the ECC key associated with a ego.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_blindable_key_get_public(const struct GNUNET_CRYPTO_BlindablePrivateKey *privkey, struct GNUNET_CRYPTO_BlindablePublicKey *key)
Retrieves the public key representation of a private key.
#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_blindable_public_key_to_string(const struct GNUNET_CRYPTO_BlindablePublicKey *key)
Creates a (Base32) string representation of the public key.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_blindable_public_key_from_string(const char *str, struct GNUNET_CRYPTO_BlindablePublicKey *key)
Parses a (Base32) string representation of the public 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.
@ 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.
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_CredentialIterator * GNUNET_RECLAIM_get_credentials_start(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_CRYPTO_BlindablePrivateKey *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.
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_BlindablePrivateKey *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.
struct GNUNET_RECLAIM_AttributeIterator * GNUNET_RECLAIM_get_attributes_start(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_CRYPTO_BlindablePrivateKey *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_ticket_iteration_stop(struct GNUNET_RECLAIM_TicketIterator *it)
Stops iteration and releases the handle for further calls.
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_userinfo(const struct GNUNET_CRYPTO_BlindablePublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations)
Generate userinfo JSON as string.
char * OIDC_build_authz_code(const struct GNUNET_CRYPTO_BlindablePrivateKey *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_rsa(const char *rp_uri, const struct GNUNET_CRYPTO_BlindablePublicKey *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_access_token_new(const struct GNUNET_RECLAIM_Ticket *ticket, const char *rp_uri)
Generate a new access token.
int OIDC_parse_authz_code(const char *rp_uri, const struct GNUNET_CRYPTO_BlindablePublicKey *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.
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?
char * OIDC_generate_id_token_hmac(const char *rp_uri, const struct GNUNET_CRYPTO_BlindablePublicKey *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.
#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.
#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.
#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.
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 const struct EgoEntry * find_ego(struct RequestHandle *handle, struct GNUNET_CRYPTO_BlindablePublicKey *test_key)
static int check_authorization(struct RequestHandle *handle, struct GNUNET_CRYPTO_BlindablePublicKey *cid)
static struct RequestHandle * requests_tail
DLL.
#define OIDC_COOKIE_HEADER_INFORMATION_KEY
OIDC cookie header information key.
static void oidc_attr_collect(void *cls, const struct GNUNET_CRYPTO_BlindablePublicKey *identity, const struct GNUNET_RECLAIM_Attribute *attr)
Collects all attributes for an ego if in scope parameter.
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.
#define OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE
OIDC expected response_type while authorizing.
static void oidc_cred_collect(void *cls, const struct GNUNET_CRYPTO_BlindablePublicKey *identity, const struct GNUNET_RECLAIM_Credential *cred)
Collects all attributes for an ego if in scope parameter.
#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.
char * scope
The list of oidc scopes.
char * code_verifier
The PKCE code_verifier.
char * nonce
The OIDC nonce.
struct GNUNET_CRYPTO_BlindablePublicKey client_pkey
The RP client public key.
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
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_CRYPTO_BlindablePrivateKey priv_key
Pointer to ego private key.
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_BlindablePublicKey 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_BlindablePublicKey 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_BlindablePublicKey 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_blindable_public_key_from_string(), GNUNET_CRYPTO_hash(), 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_BlindablePublicKey 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_blindable_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_BlindablePrivateKey *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 ))
1841 {
1843 handle->edesc = GNUNET_strdup ("The client is not authorized to request an "
1844 "authorization code using this method.");
1845 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1847 return;
1848 }
1849
1850 // If we know this identity, translated the corresponding TLD
1851 // TODO: We might want to have a reverse lookup functionality for TLDs?
1852 for (tmp_ego = ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next)
1853 {
1854 priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego);
1856 if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1857 {
1858 handle->tld = GNUNET_strdup (tmp_ego->identifier);
1859 handle->ego_entry = ego_tail;
1860 }
1861 }
1862 if (NULL == handle->tld)
1864 handle);
1865 if (NULL == handle->tld)
1866 handle->tld = GNUNET_strdup (handle->oidc->client_id);
1868}

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_blindable_key_get_public(), GNUNET_CRYPTO_blindable_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 1879 of file openid_plugin.c.

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

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 1947 of file openid_plugin.c.

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

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 2002 of file openid_plugin.c.

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

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_BlindablePublicKey cid 
)
static

Allow public clients with PKCE

Definition at line 2048 of file openid_plugin.c.

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

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_BlindablePublicKey test_key 
)
static

Definition at line 2147 of file openid_plugin.c.

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

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 2172 of file openid_plugin.c.

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

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_BlindablePublicKey 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 2459 of file openid_plugin.c.

2463{
2464 struct RequestHandle *handle = cls;
2467 struct MHD_Response *resp;
2468 struct GNUNET_HashCode cache_key;
2469 char *result_str;
2470 char *cached_code;
2471
2472 if (NULL != handle->consume_timeout_op)
2473 GNUNET_SCHEDULER_cancel (handle->consume_timeout_op);
2474 handle->consume_timeout_op = NULL;
2475 handle->idp_op = NULL;
2476
2480 GNUNET_CRYPTO_hash (handle->access_token,
2481 strlen (handle->access_token),
2482 &cache_key);
2484 &cache_key);
2485 if (NULL != cached_code)
2486 {
2489 &cache_key,
2490 cached_code));
2491 GNUNET_free (cached_code);
2492 }
2493
2494
2495 if (NULL == identity)
2496 {
2498 char *key;
2499 char *tmp = GNUNET_strdup (handle->ticket.gns_name);
2500 GNUNET_assert (NULL != strtok (tmp, "."));
2501 key = strtok (NULL, ".");
2502 GNUNET_assert (NULL != key);
2505 );
2506 GNUNET_free (tmp);
2507 result_str = OIDC_generate_userinfo (&issuer,
2508 handle->attr_userinfo_list,
2509 handle->presentations);
2510 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2511 resp = GNUNET_REST_create_response (result_str);
2512 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2513 GNUNET_free (result_str);
2515 return;
2516 }
2519 &attr->credential,
2520 attr->type,
2521 attr->data,
2522 attr->data_size);
2523 ale->attribute->id = attr->id;
2524 ale->attribute->flag = attr->flag;
2525 ale->attribute->credential = attr->credential;
2526 GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
2527 handle->attr_userinfo_list->list_tail,
2528 ale);
2529 if (NULL == presentation)
2530 return;
2531 for (atle = handle->presentations->list_head;
2532 NULL != atle; atle = atle->next)
2533 {
2536 &presentation->credential_id))
2537 continue;
2538 break;
2539 }
2540 if (NULL == atle)
2541 {
2544 atle->presentation = GNUNET_RECLAIM_presentation_new (presentation->type,
2545 presentation->data,
2546 presentation->
2547 data_size);
2548 atle->presentation->credential_id = presentation->credential_id;
2549 GNUNET_CONTAINER_DLL_insert (handle->presentations->list_head,
2550 handle->presentations->list_tail,
2551 atle);
2552 }
2553}

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_blindable_public_key_from_string(), GNUNET_CRYPTO_hash(), 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 2557 of file openid_plugin.c.

2558{
2559 struct RequestHandle *handle = cls;
2560 struct GNUNET_HashCode cache_key;
2561 struct GNUNET_RECLAIM_AttributeList *cl = NULL;
2562 struct GNUNET_RECLAIM_PresentationList *pl = NULL;
2565 struct MHD_Response *resp;
2567 char *nonce;
2568 char *cached_code;
2569 char *result_str;
2570 char *received_cid;
2571 char *emsg;
2572 char *tmp;
2573 char *key;
2574
2575 handle->consume_timeout_op = NULL;
2576 if (NULL != handle->idp_op)
2577 GNUNET_RECLAIM_cancel (handle->idp_op);
2578 handle->idp_op = NULL;
2579
2581 "Ticket consumptioned timed out. Using cache...\n");
2582 GNUNET_CRYPTO_hash (handle->access_token,
2583 strlen (handle->access_token),
2584 &cache_key);
2586 &cache_key);
2587 if (NULL == cached_code)
2588 {
2590 handle->edesc = GNUNET_strdup ("No Access Token in cache!");
2591 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2593 return;
2594 }
2600 &cache_key,
2601 cached_code));
2603 GNUNET_STRINGS_string_to_data (received_cid,
2604 strlen (received_cid),
2605 &cid,
2607 );
2608
2609 // decode code
2610 if (GNUNET_OK != OIDC_parse_authz_code (received_cid, &cid,
2611 cached_code, NULL, &ticket,
2612 &cl, &pl, &nonce,
2614 emsg))
2615 {
2617 handle->edesc = emsg;
2618 handle->response_code = MHD_HTTP_BAD_REQUEST;
2619 GNUNET_free (cached_code);
2620 if (NULL != nonce)
2621 GNUNET_free (nonce);
2623 return;
2624 }
2625
2626 GNUNET_free (cached_code);
2627
2628 tmp = GNUNET_strdup (handle->ticket.gns_name);
2629 GNUNET_assert (NULL != strtok (tmp, "."));
2630 key = strtok (NULL, ".");
2631 GNUNET_assert (NULL != key);
2634 GNUNET_free (tmp);
2635 result_str = OIDC_generate_userinfo (&issuer,
2636 cl,
2637 pl);
2638 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2639 resp = GNUNET_REST_create_response (result_str);
2640 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2641 GNUNET_free (result_str);
2642 GNUNET_free (nonce);
2646}

References cleanup_handle(), do_error(), do_userinfo_error(), get_url_parameter_copy(), GNUNET_assert, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_remove(), GNUNET_CRYPTO_blindable_public_key_from_string(), GNUNET_CRYPTO_hash(), 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 2657 of file openid_plugin.c.

2660{
2661 // TODO expiration time
2662 struct RequestHandle *handle = cls;
2664 char delimiter[] = " ";
2665 struct GNUNET_HashCode cache_key;
2666 char *authorization;
2667 char *authorization_type;
2668 char *authorization_access_token;
2669
2670 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting userinfo\n");
2673 &cache_key);
2675 ->header_param_map,
2676 &cache_key))
2677 {
2679 handle->edesc = GNUNET_strdup ("No Access Token");
2680 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2682 return;
2683 }
2684 authorization =
2685 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
2686 &cache_key);
2687
2688 // split header in "Bearer" and access_token
2689 authorization = GNUNET_strdup (authorization);
2690 authorization_type = strtok (authorization, delimiter);
2691 if ((NULL == authorization_type) ||
2692 (0 != strcmp ("Bearer", authorization_type)))
2693 {
2695 handle->edesc = GNUNET_strdup ("No Access Token");
2696 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2698 GNUNET_free (authorization);
2699 return;
2700 }
2701 authorization_access_token = strtok (NULL, delimiter);
2702 if (NULL == authorization_access_token)
2703 {
2705 handle->edesc = GNUNET_strdup ("Access token missing");
2706 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2708 GNUNET_free (authorization);
2709 return;
2710 }
2711
2712 {
2713 char *rp_uri;
2714 if (GNUNET_OK != OIDC_access_token_parse (authorization_access_token,
2715 &ticket, &rp_uri))
2716 {
2718 handle->edesc = GNUNET_strdup ("The access token is invalid");
2719 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2721 GNUNET_free (authorization);
2722 return;
2723
2724 }
2725 GNUNET_assert (NULL != ticket);
2726 handle->ticket = *ticket;
2728 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Consuming ticket\n");
2729 handle->attr_userinfo_list =
2731 handle->presentations =
2733
2734 /* If the consume takes too long, we use values from the cache */
2735 handle->access_token = GNUNET_strdup (authorization_access_token);
2737 &consume_fail,
2738 handle);
2740 &handle->ticket,
2741 rp_uri,
2743 handle);
2744 GNUNET_free (authorization);
2745 GNUNET_free (rp_uri);
2746 }
2747}

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 2758 of file openid_plugin.c.

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

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 2839 of file openid_plugin.c.

2843{
2844 struct EgoEntry *ego_entry;
2846
2847 if (NULL == ego)
2848 {
2850 return;
2851 }
2853
2854 {
2855 ego_entry = GNUNET_new (struct EgoEntry);
2858 ego_entry->ego = ego;
2859 ego_entry->identifier = GNUNET_strdup (identifier);
2861 ego_tail,
2862 ego_entry);
2863 return;
2864 }
2865 /* Ego renamed or added */
2866 if (identifier != NULL)
2867 {
2868 for (ego_entry = ego_head; NULL != ego_entry;
2869 ego_entry = ego_entry->next)
2870 {
2871 if (ego_entry->ego == ego)
2872 {
2873 /* Rename */
2874 GNUNET_free (ego_entry->identifier);
2875 ego_entry->identifier = GNUNET_strdup (identifier);
2876 break;
2877 }
2878 }
2879 if (NULL == ego_entry)
2880 {
2881 /* Add */
2882 ego_entry = GNUNET_new (struct EgoEntry);
2885 ego_entry->ego = ego;
2886 ego_entry->identifier = GNUNET_strdup (identifier);
2888 ego_tail,
2889 ego_entry);
2890 }
2891 }
2892 else
2893 {
2894 /* Delete */
2895 for (ego_entry = ego_head; NULL != ego_entry;
2896 ego_entry = ego_entry->next)
2897 {
2898 if (ego_entry->ego == ego)
2899 break;
2900 }
2901 if (NULL == ego_entry)
2902 return; /* Not found */
2903
2905 ego_tail,
2906 ego_entry);
2907 GNUNET_free (ego_entry->identifier);
2908 GNUNET_free (ego_entry->keystring);
2909 GNUNET_free (ego_entry);
2910 return;
2911 }
2912}

References EgoEntry::ego, ego_head, ego_tail, GNUNET_CONTAINER_DLL_insert_tail, GNUNET_CONTAINER_DLL_remove, GNUNET_CRYPTO_blindable_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 2916 of file openid_plugin.c.

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

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 3017 of file openid_plugin.c.

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

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 3041 of file openid_plugin.c.

3045{
3046 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
3048 static const struct GNUNET_REST_RequestHandler handlers[] =
3049 { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint },
3050 { MHD_HTTP_METHOD_POST,
3052 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont },
3053 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
3054 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
3055 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
3056 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_JWKS, &jwks_endpoint },
3057 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_OIDC_CONFIG,
3059 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC_CONFIG,
3061 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont },
3063
3064 handle->oidc = GNUNET_new (struct OIDC_Variables);
3065 if (NULL == OIDC_cookie_jar_map)
3067 GNUNET_NO);
3068 if (NULL == oidc_code_cache)
3070 GNUNET_NO);
3071
3072 handle->response_code = 0;
3074 handle->proc_cls = proc_cls;
3075 handle->proc = proc;
3076 handle->rest_handle = rest_handle;
3077 handle->url = GNUNET_strdup (rest_handle->url);
3078 handle->timeout_task =
3082 handle);
3083 if (handle->url[strlen (handle->url) - 1] == '/')
3084 handle->url[strlen (handle->url) - 1] = '\0';
3085 if (GNUNET_NO ==
3086 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
3087 return GNUNET_NO;
3088
3089 return GNUNET_YES;
3090}

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 3100 of file openid_plugin.c.

3101{
3102 static struct Plugin plugin;
3103 struct GNUNET_REST_Plugin *api;
3104
3105 oid_cfg = c;
3106 if (NULL != plugin.cfg)
3107 return NULL; /* can only initialize once! */
3108 memset (&plugin, 0, sizeof(struct Plugin));
3109 plugin.cfg = oid_cfg;
3110 api = GNUNET_new (struct GNUNET_REST_Plugin);
3111 api->cls = &plugin;
3117 "reclaim-rest-plugin",
3118 "OIDC_USERINFO_CONSUME_TIMEOUT",
3120 {
3122 }
3123
3124
3127 "%s, %s, %s, %s, %s",
3128 MHD_HTTP_METHOD_GET,
3129 MHD_HTTP_METHOD_POST,
3130 MHD_HTTP_METHOD_PUT,
3131 MHD_HTTP_METHOD_DELETE,
3132 MHD_HTTP_METHOD_OPTIONS);
3133
3135 _ ("OpenID Connect REST API initialized\n"));
3136 return api;
3137}

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 3141 of file openid_plugin.c.

3142{
3144 return GNUNET_YES;
3145}

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 3149 of file openid_plugin.c.

3150{
3151 struct Plugin *plugin = api->cls;
3152 struct EgoEntry *ego_entry;
3153
3154 plugin->cfg = NULL;
3155 while (NULL != requests_head)
3157 if (NULL != OIDC_cookie_jar_map)
3158 {
3161 NULL);
3163 }
3164 if (NULL != oidc_code_cache)
3165 {
3168 NULL);
3170 }
3171
3173 if (NULL != gns_handle)
3175 if (NULL != identity_handle)
3177 if (NULL != idp)
3179 while (NULL != (ego_entry = ego_head))
3180 {
3182 ego_tail,
3183 ego_entry);
3184 GNUNET_free (ego_entry->identifier);
3185 GNUNET_free (ego_entry->keystring);
3186 GNUNET_free (ego_entry);
3187 }
3188 GNUNET_free (api);
3190 "OpenID Connect REST plugin is finished\n");
3191}

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().