GNUnet  0.17.6
Data Structures | Macros | Functions | Variables
plugin_rest_openid_connect.c File Reference
#include "platform.h"
#include <inttypes.h>
#include <jansson.h>
#include <jose/jose.h>
#include "gnunet_buffer_lib.h"
#include "gnunet_strings_lib.h"
#include "gnunet_gns_service.h"
#include "gnunet_gnsrecord_lib.h"
#include "gnunet_identity_service.h"
#include "gnunet_namestore_service.h"
#include "gnunet_reclaim_lib.h"
#include "gnunet_reclaim_service.h"
#include "gnunet_rest_lib.h"
#include "gnunet_rest_plugin.h"
#include "gnunet_signatures.h"
#include "microhttpd.h"
#include "oidc_helper.h"
Include dependency graph for plugin_rest_openid_connect.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 ego list. More...
 
struct  RequestHandle
 The request handle. More...
 

Macros

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

Functions

static void cleanup_handle (struct RequestHandle *handle)
 Cleanup lookup handle. More...
 
static void do_error (void *cls)
 Task run on error, sends error message. More...
 
static void do_userinfo_error (void *cls)
 Task run on error in userinfo endpoint, sends error header. More...
 
static void do_redirect_error (void *cls)
 Task run on error, sends error message and redirects. More...
 
static void do_timeout (void *cls)
 Task run on timeout, sends error message. More...
 
static void options_cont (struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
 Respond to OPTIONS request. More...
 
static void cookie_identity_interpretation (struct RequestHandle *handle)
 Interprets cookie header and pass its identity keystring to handle. More...
 
json_t * read_jwk_from_file (const char *filename)
 Read the the JSON Web Key in the given file and return it. More...
 
static int write_jwk_to_file (const char *filename, json_t *jwk)
 Write the JWK to file. More...
 
json_t * generate_jwk ()
 Generate a new RSA JSON Web Key. More...
 
char * get_oidc_dir_path (void *cls)
 Return the path to the oidc directory path. More...
 
char * get_oidc_jwk_path (void *cls)
 Return the path to the RSA JWK key file. More...
 
static void login_redirect (void *cls)
 Redirects to login page stored in configuration file. More...
 
static void oidc_iteration_error (void *cls)
 Does internal server error when iteration failed. More...
 
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. More...
 
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_IDENTITY_PublicKey *identity, const struct GNUNET_RECLAIM_Credential *cred)
 Collects all attributes for an ego if in scope parameter. More...
 
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_IDENTITY_PublicKey *identity, const struct GNUNET_RECLAIM_Attribute *attr)
 Collects all attributes for an ego if in scope parameter. More...
 
static void code_redirect (void *cls)
 Checks time and cookie and redirects accordingly. More...
 
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. More...
 
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. More...
 
static void tld_iter (void *cls, const char *section, const char *option, const char *value)
 Iterate over tlds in config. More...
 
static void authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
 Responds to authorization GET and url-encoded POST request. More...
 
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. More...
 
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_IDENTITY_PublicKey *cid)
 
const struct EgoEntryfind_ego (struct RequestHandle *handle, struct GNUNET_IDENTITY_PublicKey *test_key)
 
static void token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
 Responds to token url-encoded POST request. More...
 
static void consume_ticket (void *cls, const struct GNUNET_IDENTITY_PublicKey *identity, const struct GNUNET_RECLAIM_Attribute *attr, const struct GNUNET_RECLAIM_Presentation *presentation)
 Collects claims and stores them in handle. More...
 
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. More...
 
static void jwks_endpoint (struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
 Responds to /jwks.json. More...
 
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. More...
 
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. More...
 
static enum GNUNET_GenericReturnValue rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
 
void * libgnunet_plugin_rest_openid_connect_init (void *cls)
 Entry point for the plugin. More...
 
static int cleanup_hashmap (void *cls, const struct GNUNET_HashCode *key, void *value)
 
void * libgnunet_plugin_rest_openid_connect_done (void *cls)
 Exit point from the plugin. More...
 

Variables

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

Macro Definition Documentation

◆ GNUNET_REST_API_NS_OIDC

#define GNUNET_REST_API_NS_OIDC   "/openid"

REST root namespace.

Definition at line 50 of file plugin_rest_openid_connect.c.

◆ GNUNET_REST_API_NS_OIDC_CONFIG

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

OIDC config.

Definition at line 55 of file plugin_rest_openid_connect.c.

◆ GNUNET_REST_API_NS_AUTHORIZE

#define GNUNET_REST_API_NS_AUTHORIZE   "/openid/authorize"

Authorize endpoint.

Definition at line 60 of file plugin_rest_openid_connect.c.

◆ GNUNET_REST_API_NS_TOKEN

#define GNUNET_REST_API_NS_TOKEN   "/openid/token"

Token endpoint.

Definition at line 65 of file plugin_rest_openid_connect.c.

◆ GNUNET_REST_API_JWKS

#define GNUNET_REST_API_JWKS   "/jwks.json"

JSON Web Keys endpoint.

Definition at line 70 of file plugin_rest_openid_connect.c.

◆ GNUNET_REST_API_NS_USERINFO

#define GNUNET_REST_API_NS_USERINFO   "/openid/userinfo"

UserInfo endpoint.

Definition at line 75 of file plugin_rest_openid_connect.c.

◆ GNUNET_REST_API_NS_LOGIN

#define GNUNET_REST_API_NS_LOGIN   "/openid/login"

Login namespace.

Definition at line 80 of file plugin_rest_openid_connect.c.

◆ ID_REST_STATE_INIT

#define ID_REST_STATE_INIT   0

State while collecting all egos.

Definition at line 85 of file plugin_rest_openid_connect.c.

◆ ID_REST_STATE_POST_INIT

#define ID_REST_STATE_POST_INIT   1

Done collecting egos.

Definition at line 90 of file plugin_rest_openid_connect.c.

◆ OIDC_GRANT_TYPE_KEY

#define OIDC_GRANT_TYPE_KEY   "grant_type"

OIDC grant_type key.

Definition at line 95 of file plugin_rest_openid_connect.c.

◆ OIDC_GRANT_TYPE_VALUE

#define OIDC_GRANT_TYPE_VALUE   "authorization_code"

OIDC grant_type key.

Definition at line 100 of file plugin_rest_openid_connect.c.

◆ OIDC_CODE_KEY

#define OIDC_CODE_KEY   "code"

OIDC code key.

Definition at line 105 of file plugin_rest_openid_connect.c.

◆ OIDC_RESPONSE_TYPE_KEY

#define OIDC_RESPONSE_TYPE_KEY   "response_type"

OIDC response_type key.

Definition at line 110 of file plugin_rest_openid_connect.c.

◆ OIDC_CLIENT_ID_KEY

#define OIDC_CLIENT_ID_KEY   "client_id"

OIDC client_id key.

Definition at line 115 of file plugin_rest_openid_connect.c.

◆ OIDC_SCOPE_KEY

#define OIDC_SCOPE_KEY   "scope"

OIDC scope key.

Definition at line 120 of file plugin_rest_openid_connect.c.

◆ OIDC_REDIRECT_URI_KEY

#define OIDC_REDIRECT_URI_KEY   "redirect_uri"

OIDC redirect_uri key.

Definition at line 125 of file plugin_rest_openid_connect.c.

◆ OIDC_STATE_KEY

#define OIDC_STATE_KEY   "state"

OIDC state key.

Definition at line 130 of file plugin_rest_openid_connect.c.

◆ OIDC_NONCE_KEY

#define OIDC_NONCE_KEY   "nonce"

OIDC nonce key.

Definition at line 135 of file plugin_rest_openid_connect.c.

◆ OIDC_CLAIMS_KEY

#define OIDC_CLAIMS_KEY   "claims"

OIDC claims key.

Definition at line 140 of file plugin_rest_openid_connect.c.

◆ OIDC_CODE_CHALLENGE_KEY

#define OIDC_CODE_CHALLENGE_KEY   "code_challenge"

OIDC PKCE code challenge.

Definition at line 145 of file plugin_rest_openid_connect.c.

◆ OIDC_CODE_VERIFIER_KEY

#define OIDC_CODE_VERIFIER_KEY   "code_verifier"

OIDC PKCE code verifier.

Definition at line 150 of file plugin_rest_openid_connect.c.

◆ OIDC_COOKIE_EXPIRATION

#define OIDC_COOKIE_EXPIRATION   3

OIDC cookie expiration (in seconds)

Definition at line 155 of file plugin_rest_openid_connect.c.

◆ OIDC_COOKIE_HEADER_KEY

#define OIDC_COOKIE_HEADER_KEY   "cookie"

OIDC cookie header key.

Definition at line 160 of file plugin_rest_openid_connect.c.

◆ OIDC_AUTHORIZATION_HEADER_KEY

#define OIDC_AUTHORIZATION_HEADER_KEY   "authorization"

OIDC cookie header information key.

Definition at line 165 of file plugin_rest_openid_connect.c.

◆ OIDC_COOKIE_HEADER_INFORMATION_KEY

#define OIDC_COOKIE_HEADER_INFORMATION_KEY   "Identity="

OIDC cookie header information key.

Definition at line 170 of file plugin_rest_openid_connect.c.

◆ OIDC_COOKIE_HEADER_ACCESS_DENIED

#define OIDC_COOKIE_HEADER_ACCESS_DENIED   "Identity=Denied"

OIDC cookie header if user cancelled.

Definition at line 175 of file plugin_rest_openid_connect.c.

◆ OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE

#define OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE   "code"

OIDC expected response_type while authorizing.

Definition at line 180 of file plugin_rest_openid_connect.c.

◆ OIDC_EXPECTED_AUTHORIZATION_SCOPE

#define OIDC_EXPECTED_AUTHORIZATION_SCOPE   "openid"

OIDC expected scope part while authorizing.

Definition at line 185 of file plugin_rest_openid_connect.c.

◆ OIDC_ERROR_KEY_INVALID_CLIENT

#define OIDC_ERROR_KEY_INVALID_CLIENT   "invalid_client"

OIDC error key for invalid client.

Definition at line 190 of file plugin_rest_openid_connect.c.

◆ OIDC_ERROR_KEY_INVALID_SCOPE

#define OIDC_ERROR_KEY_INVALID_SCOPE   "invalid_scope"

OIDC error key for invalid scopes.

Definition at line 195 of file plugin_rest_openid_connect.c.

◆ OIDC_ERROR_KEY_INVALID_REQUEST

#define OIDC_ERROR_KEY_INVALID_REQUEST   "invalid_request"

OIDC error key for invalid requests.

Definition at line 200 of file plugin_rest_openid_connect.c.

◆ OIDC_ERROR_KEY_INVALID_TOKEN

#define OIDC_ERROR_KEY_INVALID_TOKEN   "invalid_token"

OIDC error key for invalid tokens.

Definition at line 205 of file plugin_rest_openid_connect.c.

◆ OIDC_ERROR_KEY_INVALID_COOKIE

#define OIDC_ERROR_KEY_INVALID_COOKIE   "invalid_cookie"

OIDC error key for invalid cookies.

Definition at line 210 of file plugin_rest_openid_connect.c.

◆ OIDC_ERROR_KEY_SERVER_ERROR

#define OIDC_ERROR_KEY_SERVER_ERROR   "server_error"

OIDC error key for generic server errors.

Definition at line 215 of file plugin_rest_openid_connect.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 220 of file plugin_rest_openid_connect.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 225 of file plugin_rest_openid_connect.c.

◆ OIDC_ERROR_KEY_UNAUTHORIZED_CLIENT

#define OIDC_ERROR_KEY_UNAUTHORIZED_CLIENT   "unauthorized_client"

OIDC error key for unauthorized clients.

Definition at line 230 of file plugin_rest_openid_connect.c.

◆ OIDC_ERROR_KEY_ACCESS_DENIED

#define OIDC_ERROR_KEY_ACCESS_DENIED   "access_denied"

OIDC error key for denied access.

Definition at line 235 of file plugin_rest_openid_connect.c.

◆ OIDC_JWK_RSA_FILENAME

#define OIDC_JWK_RSA_FILENAME   "jwk_rsa.json"

OIDC key store file name.

Definition at line 240 of file plugin_rest_openid_connect.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:483

How long to wait for a consume in userinfo endpoint.

Definition at line 245 of file plugin_rest_openid_connect.c.

Function Documentation

◆ cleanup_handle()

static void cleanup_handle ( struct RequestHandle handle)
static

Cleanup lookup handle.

Parameters
handleHandle to clean up

Definition at line 602 of file plugin_rest_openid_connect.c.

603 {
604 
605  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
606  if (NULL != handle->timeout_task)
607  GNUNET_SCHEDULER_cancel (handle->timeout_task);
608  if (NULL != handle->attr_it)
610  if (NULL != handle->cred_it)
612  if (NULL != handle->ticket_it)
614  if (NULL != handle->idp_op)
615  GNUNET_RECLAIM_cancel (handle->idp_op);
616  if (NULL != handle->consume_timeout_op)
617  GNUNET_SCHEDULER_cancel (handle->consume_timeout_op);
618  GNUNET_free (handle->url);
619  GNUNET_free (handle->tld);
620  GNUNET_free (handle->redirect_prefix);
621  GNUNET_free (handle->redirect_suffix);
622  GNUNET_free (handle->emsg);
623  GNUNET_free (handle->edesc);
624  if (NULL != handle->gns_op)
626  if (NULL != handle->oidc)
627  {
628  GNUNET_free (handle->oidc->client_id);
629  GNUNET_free (handle->oidc->login_identity);
630  GNUNET_free (handle->oidc->nonce);
631  GNUNET_free (handle->oidc->redirect_uri);
632  GNUNET_free (handle->oidc->response_type);
633  GNUNET_free (handle->oidc->scope);
634  GNUNET_free (handle->oidc->state);
635  if (NULL != handle->oidc->claims)
636  GNUNET_free (handle->oidc->claims);
637  if (NULL != handle->oidc->code_challenge)
638  GNUNET_free (handle->oidc->code_challenge);
639  GNUNET_free (handle->oidc);
640  }
641  if (NULL!=handle->attr_idtoken_list)
642  GNUNET_RECLAIM_attribute_list_destroy (handle->attr_idtoken_list);
643  if (NULL!=handle->attr_userinfo_list)
644  GNUNET_RECLAIM_attribute_list_destroy (handle->attr_userinfo_list);
645  if (NULL!=handle->credentials)
647  if (NULL!=handle->presentations)
651  handle);
652  if (NULL != handle->access_token)
653  GNUNET_free (handle->access_token);
655 }
static struct GNUNET_DNS_Handle * handle
Handle to transport service.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
void * GNUNET_GNS_lookup_cancel(struct GNUNET_GNS_LookupRequest *lr)
Cancel pending lookup request.
Definition: gns_api.c:314
#define GNUNET_log(kind,...)
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_free(ptr)
Wrapper around free.
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 claim list.
void GNUNET_RECLAIM_presentation_list_destroy(struct GNUNET_RECLAIM_PresentationList *presentations)
Destroy presentations list.
void GNUNET_RECLAIM_cancel(struct GNUNET_RECLAIM_Operation *op)
Cancel an identity provider operation.
Definition: reclaim_api.c:1088
void GNUNET_RECLAIM_get_attributes_stop(struct GNUNET_RECLAIM_AttributeIterator *it)
Stops iteration and releases the handle for further calls.
Definition: reclaim_api.c:1397
void GNUNET_RECLAIM_get_credentials_stop(struct GNUNET_RECLAIM_CredentialIterator *ait)
Stops iteration and releases the handle for further calls.
Definition: reclaim_api.c:1508
void GNUNET_RECLAIM_ticket_iteration_stop(struct GNUNET_RECLAIM_TicketIterator *it)
Stops iteration and releases the handle for further calls.
Definition: reclaim_api.c:1699
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:957
static struct RequestHandle * requests_head
DLL.
static struct RequestHandle * requests_tail
DLL.

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(), libgnunet_plugin_rest_openid_connect_done(), login_cont(), login_redirect(), oidc_config_cors(), oidc_config_endpoint(), oidc_ticket_issue_cb(), options_cont(), 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 664 of file plugin_rest_openid_connect.c.

665 {
666  struct RequestHandle *handle = cls;
667  struct MHD_Response *resp;
668  char *json_error;
669 
670  GNUNET_asprintf (&json_error,
671  "{ \"error\" : \"%s\", \"error_description\" : \"%s\"%s%s%s}",
672  handle->emsg,
673  (NULL != handle->edesc) ? handle->edesc : "",
674  (NULL != handle->oidc->state) ? ", \"state\":\"" : "",
675  (NULL != handle->oidc->state) ? handle->oidc->state : "",
676  (NULL != handle->oidc->state) ? "\"" : "");
677  if (0 == handle->response_code)
678  handle->response_code = MHD_HTTP_BAD_REQUEST;
679  resp = GNUNET_REST_create_response (json_error);
680  if (MHD_HTTP_UNAUTHORIZED == handle->response_code)
681  GNUNET_assert (MHD_NO !=
682  MHD_add_response_header (resp,
683  MHD_HTTP_HEADER_WWW_AUTHENTICATE,
684  "Basic"));
685  MHD_add_response_header (resp,
686  MHD_HTTP_HEADER_CONTENT_TYPE,
687  "application/json");
688  handle->proc (handle->proc_cls, resp, handle->response_code);
690  GNUNET_free (json_error);
691 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
struct MHD_Response * GNUNET_REST_create_response(const char *data)
Create REST MHD response.
Definition: rest.c:57
static void cleanup_handle(struct RequestHandle *handle)
Cleanup lookup handle.
The request handle.

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 701 of file plugin_rest_openid_connect.c.

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

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 730 of file plugin_rest_openid_connect.c.

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

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 758 of file plugin_rest_openid_connect.c.

759 {
760  struct RequestHandle *handle = cls;
761 
762  handle->timeout_task = NULL;
763  do_error (handle);
764 }
static void do_error(void *cls)
Task run on error, sends error message.

References do_error(), and handle.

Here is the call 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 775 of file plugin_rest_openid_connect.c.

778 {
779  struct MHD_Response *resp;
780  struct RequestHandle *handle = cls;
781 
782  // For now, independent of path return all options
783  resp = GNUNET_REST_create_response (NULL);
784  MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
785  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
787  return;
788 }
static char * allow_methods
HTTP methods allows for this plugin.

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

Here is the call 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 795 of file plugin_rest_openid_connect.c.

796 {
797  struct GNUNET_HashCode cache_key;
798  char *cookies;
799  struct GNUNET_TIME_Absolute current_time, *relog_time;
800  char delimiter[] = "; ";
801  char *tmp_cookies;
802  char *token;
803  char *value;
804 
805  // gets identity of login try with cookie
807  strlen (OIDC_COOKIE_HEADER_KEY),
808  &cache_key);
810  ->header_param_map,
811  &cache_key))
812  {
813  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No cookie found\n");
814  return;
815  }
816  // splits cookies and find 'Identity' cookie
817  tmp_cookies =
818  GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
819  &cache_key);
820  cookies = GNUNET_strdup (tmp_cookies);
821  token = strtok (cookies, delimiter);
822  handle->oidc->user_cancelled = GNUNET_NO;
823  handle->oidc->login_identity = NULL;
824  if (NULL == token)
825  {
827  "Unable to parse cookie: %s\n",
828  cookies);
829  GNUNET_free (cookies);
830  return;
831  }
832 
833  while (NULL != token)
834  {
835  if (0 == strcmp (token, OIDC_COOKIE_HEADER_ACCESS_DENIED))
836  {
837  handle->oidc->user_cancelled = GNUNET_YES;
838  GNUNET_free (cookies);
839  return;
840  }
841  if (NULL != strstr (token, OIDC_COOKIE_HEADER_INFORMATION_KEY))
842  break;
843  token = strtok (NULL, delimiter);
844  }
845  if (NULL == token)
846  {
848  "No cookie value to process: %s\n",
849  cookies);
850  GNUNET_free (cookies);
851  return;
852  }
853  GNUNET_CRYPTO_hash (token, strlen (token), &cache_key);
854  if (GNUNET_NO ==
856  {
857  GNUNET_log (
859  "Found cookie `%s', but no corresponding expiration entry present...\n",
860  token);
861  GNUNET_free (cookies);
862  return;
863  }
864  relog_time =
866  current_time = GNUNET_TIME_absolute_get ();
867  // 30 min after old login -> redirect to login
868  if (current_time.abs_value_us > relog_time->abs_value_us)
869  {
871  "Found cookie `%s', but it is expired.\n",
872  token);
873  GNUNET_free (cookies);
874  return;
875  }
876  value = strtok (token, OIDC_COOKIE_HEADER_INFORMATION_KEY);
877  GNUNET_assert (NULL != value);
878  handle->oidc->login_identity = GNUNET_strdup (value);
879  GNUNET_free (cookies);
880 }
static char * value
Value of the record to add/remove.
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).
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.
@ GNUNET_YES
@ GNUNET_NO
Definition: gnunet_common.h:98
@ GNUNET_ERROR_TYPE_WARNING
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:110
struct GNUNET_CONTAINER_MultiHashMap * OIDC_cookie_jar_map
OIDC hashmap that keeps track of issued cookies.
#define OIDC_COOKIE_HEADER_KEY
OIDC cookie header key.
#define OIDC_COOKIE_HEADER_ACCESS_DENIED
OIDC cookie header if user cancelled.
#define OIDC_COOKIE_HEADER_INFORMATION_KEY
OIDC cookie header information key.
A 512-bit hashcode.
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.

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

json_t* read_jwk_from_file ( const char *  filename)

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 892 of file plugin_rest_openid_connect.c.

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

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 writen to
jwkthe JWK that is going to be written
Returns
int Return GNUNET_OK if write is sucessfull

Definition at line 917 of file plugin_rest_openid_connect.c.

919 {
920  if (json_dump_file (jwk, filename, JSON_INDENT (2)))
921  {
923  ("Could not write OIDC RSA key to file %s\n"),
924  filename);
926  }
927  else
928  return GNUNET_OK;
929 }
@ GNUNET_OK
Definition: gnunet_common.h:99

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

json_t* generate_jwk ( )

Generate a new RSA JSON Web Key.

Returns
json_t* the generated JWK

Definition at line 937 of file plugin_rest_openid_connect.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()

char* get_oidc_dir_path ( void *  cls)

Return the path to the oidc directory path.

Parameters
clsthe RequestHandle

Definition at line 952 of file plugin_rest_openid_connect.c.

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 }
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.
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:1281
const struct GNUNET_CONFIGURATION_Handle * cfg
The configuration handle.
#define OIDC_ERROR_KEY_SERVER_ERROR
OIDC error key for generic server errors.

References cfg, do_error(), GNUNET_CONFIGURATION_get_value_filename(), GNUNET_OK, GNUNET_SCHEDULER_add_now(), GNUNET_strdup, handle, 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()

char* get_oidc_jwk_path ( void *  cls)

Return the path to the RSA JWK key file.

Parameters
clsthe RequestHandle

Definition at line 980 of file plugin_rest_openid_connect.c.

981 {
982  char *oidc_directory;
983  char *oidc_jwk_path;
984 
985  oidc_directory = get_oidc_dir_path (cls);
986 
987  // Create path to file
988  GNUNET_asprintf (&oidc_jwk_path, "%s/%s", oidc_directory,
990 
991  return oidc_jwk_path;
992 }
char * get_oidc_dir_path(void *cls)
Return the path to the oidc directory path.
#define OIDC_JWK_RSA_FILENAME
OIDC key store file name.

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 999 of file plugin_rest_openid_connect.c.

1000 {
1001  char *login_base_url;
1002  char *new_redirect;
1003  char *tmp;
1004  struct MHD_Response *resp;
1005  struct GNUNET_Buffer buf = { 0 };
1006  struct RequestHandle *handle = cls;
1007 
1009  "reclaim-rest-plugin",
1010  "address",
1011  &login_base_url))
1012  {
1013  GNUNET_buffer_write_str (&buf, login_base_url);
1015  "?%s=%s",
1017  handle->oidc->response_type);
1019  "&%s=%s",
1021  handle->oidc->client_id);
1022  GNUNET_STRINGS_urlencode (handle->oidc->redirect_uri,
1023  strlen (handle->oidc->redirect_uri),
1024  &tmp);
1026  "&%s=%s",
1028  tmp);
1029  GNUNET_free (tmp);
1030  GNUNET_STRINGS_urlencode (handle->oidc->scope,
1031  strlen (handle->oidc->scope),
1032  &tmp);
1034  "&%s=%s",
1036  tmp);
1037  GNUNET_free (tmp);
1038  if (NULL != handle->oidc->state)
1039  {
1040  GNUNET_STRINGS_urlencode (handle->oidc->state,
1041  strlen (handle->oidc->state),
1042  &tmp);
1044  "&%s=%s",
1046  handle->oidc->state);
1047  GNUNET_free (tmp);
1048  }
1049  if (NULL != handle->oidc->code_challenge)
1050  {
1052  "&%s=%s",
1054  handle->oidc->code_challenge);
1055  }
1056  if (NULL != handle->oidc->nonce)
1057  {
1059  "&%s=%s",
1061  handle->oidc->nonce);
1062  }
1063  if (NULL != handle->oidc->claims)
1064  {
1065  GNUNET_STRINGS_urlencode (handle->oidc->claims,
1066  strlen (handle->oidc->claims),
1067  &tmp);
1069  "&%s=%s",
1071  tmp);
1072  GNUNET_free (tmp);
1073  }
1074  new_redirect = GNUNET_buffer_reap_str (&buf);
1075  resp = GNUNET_REST_create_response ("");
1076  MHD_add_response_header (resp, "Location", new_redirect);
1077  GNUNET_free (login_base_url);
1078  }
1079  else
1080  {
1082  handle->edesc = GNUNET_strdup ("gnunet configuration failed");
1083  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1085  return;
1086  }
1087  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1088  GNUNET_free (new_redirect);
1090 }
static char buf[2048]
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.
char * GNUNET_buffer_reap_str(struct GNUNET_Buffer *buf)
Clear the buffer and return the string it contained.
Definition: buffer.c:123
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.
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
size_t GNUNET_STRINGS_urlencode(const char *data, size_t len, char **out)
url/percent encode (RFC3986).
Definition: strings.c:1851
#define OIDC_SCOPE_KEY
OIDC scope key.
#define OIDC_CLAIMS_KEY
OIDC claims key.
#define OIDC_REDIRECT_URI_KEY
OIDC redirect_uri key.
#define OIDC_NONCE_KEY
OIDC nonce key.
#define OIDC_CODE_CHALLENGE_KEY
OIDC PKCE code challenge.
#define OIDC_RESPONSE_TYPE_KEY
OIDC response_type key.
#define OIDC_STATE_KEY
OIDC state key.
#define OIDC_CLIENT_ID_KEY
OIDC client_id key.
Dynamically growing buffer.

References buf, cfg, 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, 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 1097 of file plugin_rest_openid_connect.c.

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

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 1112 of file plugin_rest_openid_connect.c.

1116 {
1117  struct RequestHandle *handle = cls;
1118  struct MHD_Response *resp;
1119  char *ticket_str;
1120  char *redirect_uri;
1121  char *code_string;
1122 
1123  handle->idp_op = NULL;
1124  if (NULL == ticket)
1125  {
1127  handle->edesc = GNUNET_strdup ("Server cannot generate ticket.");
1129  return;
1130  }
1131  handle->ticket = *ticket;
1132  ticket_str =
1134  sizeof(struct GNUNET_RECLAIM_Ticket));
1135  code_string = OIDC_build_authz_code (&handle->priv_key,
1136  &handle->ticket,
1137  handle->attr_idtoken_list,
1138  presentation,
1139  handle->oidc->nonce,
1140  handle->oidc->code_challenge);
1141  if ((NULL != handle->redirect_prefix) && (NULL != handle->redirect_suffix) &&
1142  (NULL != handle->tld))
1143  {
1144  GNUNET_asprintf (&redirect_uri,
1145  "%s.%s/%s%s%s=%s&state=%s",
1146  handle->redirect_prefix,
1147  handle->tld,
1148  handle->redirect_suffix,
1149  (NULL == strchr (handle->redirect_suffix, '?') ? "?" :
1150  "&"),
1151  handle->oidc->response_type,
1152  code_string,
1153  handle->oidc->state);
1154  }
1155  else
1156  {
1157  GNUNET_asprintf (&redirect_uri,
1158  "%s%s%s=%s&state=%s",
1159  handle->oidc->redirect_uri,
1160  (NULL == strchr (handle->oidc->redirect_uri, '?') ? "?" :
1161  "&"),
1162  handle->oidc->response_type,
1163  code_string,
1164  handle->oidc->state);
1165  }
1166  resp = GNUNET_REST_create_response ("");
1167  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1168  "Location", redirect_uri));
1169  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1171  GNUNET_free (redirect_uri);
1172  GNUNET_free (ticket_str);
1173  GNUNET_free (code_string);
1174 }
static struct GNUNET_RECLAIM_Ticket ticket
Ticket to consume.
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
Definition: strings.c:764
char * OIDC_build_authz_code(const struct GNUNET_IDENTITY_PrivateKey *issuer, const struct GNUNET_RECLAIM_Ticket *ticket, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations, const char *nonce_str, const char *code_challenge)
Builds an OIDC authorization code including a reclaim ticket and nonce.
Definition: oidc_helper.c:595
static void do_redirect_error(void *cls)
Task run on error, sends error message and redirects.
The authorization ticket.

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 1178 of file plugin_rest_openid_connect.c.

1180 {
1181  struct GNUNET_RECLAIM_AttributeList *merged_list;
1182  struct GNUNET_RECLAIM_AttributeListEntry *le_a;
1183  struct GNUNET_RECLAIM_AttributeListEntry *le_b;
1184  struct GNUNET_RECLAIM_AttributeListEntry *le_m;
1185 
1186  merged_list = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
1187  for (le_a = list_a->list_head; NULL != le_a; le_a = le_a->next)
1188  {
1191  &le_a->attribute->
1192  credential,
1193  le_a->attribute->type,
1194  le_a->attribute->data,
1195  le_a->attribute->data_size);
1196  le_m->attribute->id = le_a->attribute->id;
1197  le_m->attribute->flag = le_a->attribute->flag;
1198  le_m->attribute->credential = le_a->attribute->credential;
1199  GNUNET_CONTAINER_DLL_insert (merged_list->list_head,
1200  merged_list->list_tail,
1201  le_m);
1202  }
1203  le_m = NULL;
1204  for (le_b = list_b->list_head; NULL != le_b; le_b = le_b->next)
1205  {
1206  for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1207  {
1209  &le_b->attribute->id))
1210  break;
1211  }
1212  if (NULL != le_m)
1213  continue;
1216  &le_b->attribute->
1217  credential,
1218  le_b->attribute->type,
1219  le_b->attribute->data,
1220  le_b->attribute->data_size);
1221  le_m->attribute->id = le_b->attribute->id;
1222  le_m->attribute->flag = le_b->attribute->flag;
1223  le_m->attribute->credential = le_b->attribute->credential;
1224  GNUNET_CONTAINER_DLL_insert (merged_list->list_head,
1225  merged_list->list_tail,
1226  le_m);
1227  }
1228  return merged_list;
1229 }
static struct GNUNET_RECLAIM_Identifier credential
Credential ID.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_RECLAIM_id_is_equal(a, b)
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_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.

References GNUNET_RECLAIM_AttributeListEntry::attribute, GNUNET_RECLAIM_Attribute::credential, 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 1233 of file plugin_rest_openid_connect.c.

1234 {
1235  struct RequestHandle *handle = cls;
1236  struct GNUNET_RECLAIM_AttributeList *merged_list;
1237  struct GNUNET_RECLAIM_AttributeListEntry *le_m;
1238 
1239  handle->cred_it = NULL;
1240  merged_list = attribute_list_merge (handle->attr_idtoken_list,
1241  handle->attr_userinfo_list);
1242  for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1244  "List Attribute in ticket to issue: %s\n",
1245  le_m->attribute->name);
1247  &handle->priv_key,
1248  &handle->oidc->client_pkey,
1249  merged_list,
1251  handle);
1253 }
struct GNUNET_RECLAIM_Operation * GNUNET_RECLAIM_ticket_issue(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_IDENTITY_PrivateKey *iss, const struct GNUNET_IDENTITY_PublicKey *rp, const struct GNUNET_RECLAIM_AttributeList *attrs, GNUNET_RECLAIM_IssueTicketCallback cb, void *cb_cls)
Issues a ticket to a relying party.
Definition: reclaim_api.c:1541
static struct GNUNET_RECLAIM_Handle * idp
Identity Provider.
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_AttributeList * attribute_list_merge(struct GNUNET_RECLAIM_AttributeList *list_a, struct GNUNET_RECLAIM_AttributeList *list_b)

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_IDENTITY_PublicKey identity,
const struct GNUNET_RECLAIM_Credential cred 
)
static

Collects all attributes for an ego if in scope parameter.

Credential already in list

Credential matches for attribute, add

Definition at line 1260 of file plugin_rest_openid_connect.c.

1263 {
1264  struct RequestHandle *handle = cls;
1267 
1268  for (ale = handle->credentials->list_head; NULL != ale; ale = ale->next)
1269  {
1271  &cred->id))
1272  continue;
1275  return;
1276  }
1277 
1278  for (le = handle->attr_idtoken_list->list_head; NULL != le; le = le->next)
1279  {
1281  &cred->id))
1282  continue;
1286  cred->type,
1287  cred->data,
1288  cred->data_size);
1289  GNUNET_CONTAINER_DLL_insert (handle->credentials->list_head,
1290  handle->credentials->list_tail,
1291  ale);
1292  }
1294 }
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_get_credentials_next(struct GNUNET_RECLAIM_CredentialIterator *ait)
Calls the record processor specified in GNUNET_RECLAIM_get_credentials_start for the next record.
Definition: reclaim_api.c:1486
struct GNUNET_RECLAIM_CredentialListEntry * next
DLL.
struct GNUNET_RECLAIM_Credential * credential
The credential.
uint32_t type
Type/Format of Claim.
const char * name
The name of the credential.
const void * data
Binary value stored as credential value.
size_t data_size
Number of bytes in data.
struct GNUNET_RECLAIM_Identifier id
ID.

References GNUNET_RECLAIM_AttributeListEntry::attribute, GNUNET_RECLAIM_Attribute::credential, GNUNET_RECLAIM_CredentialListEntry::credential, GNUNET_RECLAIM_Credential::data, GNUNET_RECLAIM_Credential::data_size, 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_Credential::id, GNUNET_RECLAIM_Credential::name, GNUNET_RECLAIM_AttributeListEntry::next, GNUNET_RECLAIM_CredentialListEntry::next, and GNUNET_RECLAIM_Credential::type.

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 1298 of file plugin_rest_openid_connect.c.

1299 {
1300  struct RequestHandle *handle = cls;
1301 
1302  handle->attr_it = NULL;
1303  handle->ticket_it = NULL;
1304  if (NULL == handle->attr_idtoken_list->list_head)
1305  {
1307  handle->edesc = GNUNET_strdup ("The requested scope is not available.");
1309  return;
1310  }
1311  handle->credentials = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
1312  handle->cred_it =
1314  &handle->priv_key,
1316  handle,
1318  handle,
1320  handle);
1321 
1322 }
struct GNUNET_RECLAIM_CredentialIterator * GNUNET_RECLAIM_get_credentials_start(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_IDENTITY_PrivateKey *identity, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_RECLAIM_CredentialResult proc, void *proc_cls, GNUNET_SCHEDULER_TaskCallback finish_cb, void *finish_cb_cls)
List all credentials for a local identity.
Definition: reclaim_api.c:1439
static void oidc_cred_collect(void *cls, const struct GNUNET_IDENTITY_PublicKey *identity, const struct GNUNET_RECLAIM_Credential *cred)
Collects all attributes for an ego if in scope parameter.
static void oidc_cred_collect_finished_cb(void *cls)
#define OIDC_ERROR_KEY_INVALID_SCOPE
OIDC error key for invalid scopes.
static void oidc_iteration_error(void *cls)
Does internal server error when iteration failed.
A list of GNUNET_RECLAIM_Credential structures.

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 1326 of file plugin_rest_openid_connect.c.

1329 {
1330  int ret = GNUNET_NO;
1331  json_t *root;
1332  json_error_t error;
1333  json_t *claims_j;
1334  const char *key;
1335  json_t *value;
1336 
1339  attr_name))
1340  return GNUNET_YES;
1341 
1343  if (NULL != handle->oidc->claims)
1344  {
1345  root = json_loads (handle->oidc->claims, JSON_DECODE_ANY, &error);
1346  claims_j = json_object_get (root, claims_parameter);
1347  /* obj is a JSON object */
1348  if (NULL != claims_j)
1349  {
1350  json_object_foreach (claims_j, key, value) {
1351  if (0 != strcmp (attr_name, key))
1352  continue;
1353  ret = GNUNET_YES;
1354  break;
1355  }
1356  }
1357  json_decref (root);
1358  }
1359  return ret;
1360 }
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
struct GNUNET_HashCode key
The key used in the DHT.
static char * attr_name
The attribute.
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...
Definition: oidc_helper.c:972

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 1364 of file plugin_rest_openid_connect.c.

1366 {
1367  return attr_in_claims_request (handle, attr_name, "id_token");
1368 }
static int attr_in_claims_request(struct RequestHandle *handle, const char *attr_name, const char *claims_parameter)

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 1372 of file plugin_rest_openid_connect.c.

1374 {
1375  return attr_in_claims_request (handle, attr_name, "userinfo");
1376 }

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_IDENTITY_PublicKey identity,
const struct GNUNET_RECLAIM_Attribute attr 
)
static

Collects all attributes for an ego if in scope parameter.

Definition at line 1383 of file plugin_rest_openid_connect.c.

1386 {
1387  struct RequestHandle *handle = cls;
1390  {
1393  &attr->credential,
1394  attr->type,
1395  attr->data,
1396  attr->data_size);
1397  le->attribute->id = attr->id;
1398  le->attribute->flag = attr->flag;
1399  le->attribute->credential = attr->credential;
1400  GNUNET_CONTAINER_DLL_insert (handle->attr_idtoken_list->list_head,
1401  handle->attr_idtoken_list->list_tail,
1402  le);
1403  }
1405  {
1408  &attr->credential,
1409  attr->type,
1410  attr->data,
1411  attr->data_size);
1412  le->attribute->id = attr->id;
1413  le->attribute->flag = attr->flag;
1414  le->attribute->credential = attr->credential;
1415  GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
1416  handle->attr_userinfo_list->list_tail,
1417  le);
1418  }
1419 
1421 }
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.
Definition: reclaim_api.c:1376
static int attr_in_userinfo_request(struct RequestHandle *handle, const char *attr_name)
static int attr_in_idtoken_request(struct RequestHandle *handle, const char *attr_name)

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 1428 of file plugin_rest_openid_connect.c.

1429 {
1430  struct RequestHandle *handle = cls;
1431  struct GNUNET_TIME_Absolute current_time;
1432  struct GNUNET_TIME_Absolute *relog_time;
1434  struct GNUNET_IDENTITY_PublicKey ego_pkey;
1435  struct GNUNET_HashCode cache_key;
1436  char *identity_cookie;
1437 
1438  GNUNET_asprintf (&identity_cookie,
1439  "Identity=%s",
1440  handle->oidc->login_identity);
1441  GNUNET_CRYPTO_hash (identity_cookie, strlen (identity_cookie), &cache_key);
1442  GNUNET_free (identity_cookie);
1443  // No login time for identity -> redirect to login
1444  if (GNUNET_YES ==
1446  {
1447  relog_time =
1449  current_time = GNUNET_TIME_absolute_get ();
1450  // 30 min after old login -> redirect to login
1451  if (current_time.abs_value_us <= relog_time->abs_value_us)
1452  {
1453  if (GNUNET_OK !=
1455  ->login_identity,
1456  &pubkey))
1457  {
1459  handle->edesc =
1460  GNUNET_strdup ("The cookie of a login identity is not valid");
1462  return;
1463  }
1464  // iterate over egos and compare their public key
1465  for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
1466  handle->ego_entry = handle->ego_entry->next)
1467  {
1468  GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey);
1469  if (0 == GNUNET_memcmp (&ego_pkey, &pubkey))
1470  {
1471  handle->priv_key =
1472  *GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego);
1473  handle->attr_idtoken_list =
1475  handle->attr_userinfo_list =
1477  handle->attr_it =
1479  &handle->priv_key,
1481  handle,
1483  handle,
1485  handle);
1486  return;
1487  }
1488  }
1490  return;
1491  }
1492  }
1493 }
static struct GNUNET_IDENTITY_PublicKey pubkey
Public key of the zone to look in.
const struct GNUNET_IDENTITY_PrivateKey * GNUNET_IDENTITY_ego_get_private_key(const struct GNUNET_IDENTITY_Ego *ego)
Obtain the ECC key associated with a ego.
Definition: identity_api.c:639
enum GNUNET_GenericReturnValue GNUNET_IDENTITY_public_key_from_string(const char *str, struct GNUNET_IDENTITY_PublicKey *key)
Parses a (Base32) string representation of the public key.
void GNUNET_IDENTITY_ego_get_public_key(struct GNUNET_IDENTITY_Ego *ego, struct GNUNET_IDENTITY_PublicKey *pk)
Get the identifier (public key) of an ego.
Definition: identity_api.c:652
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
struct GNUNET_RECLAIM_AttributeIterator * GNUNET_RECLAIM_get_attributes_start(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_IDENTITY_PrivateKey *identity, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_RECLAIM_AttributeResult proc, void *proc_cls, GNUNET_SCHEDULER_TaskCallback finish_cb, void *finish_cb_cls)
List all attributes for a local identity.
Definition: reclaim_api.c:1330
static void oidc_attr_collect(void *cls, const struct GNUNET_IDENTITY_PublicKey *identity, const struct GNUNET_RECLAIM_Attribute *attr)
Collects all attributes for an ego if in scope parameter.
#define OIDC_ERROR_KEY_INVALID_COOKIE
OIDC error key for invalid cookies.
static struct EgoEntry * ego_head
Ego list.
static void oidc_attr_collect_finished_cb(void *cls)
static void login_redirect(void *cls)
Redirects to login page stored in configuration file.
An identity key as per LSD0001.

References GNUNET_TIME_Absolute::abs_value_us, do_redirect_error(), ego_head, GNUNET_asprintf(), GNUNET_CONTAINER_multihashmap_contains(), GNUNET_CONTAINER_multihashmap_get(), GNUNET_CRYPTO_hash(), GNUNET_free, GNUNET_IDENTITY_ego_get_private_key(), GNUNET_IDENTITY_ego_get_public_key(), GNUNET_IDENTITY_public_key_from_string(), 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 1497 of file plugin_rest_openid_connect.c.

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

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 1540 of file plugin_rest_openid_connect.c.

1543 {
1544  struct RequestHandle *handle = cls;
1545  char *tmp;
1546  char *tmp_key_str;
1547  char *pos;
1548  struct GNUNET_IDENTITY_PublicKey redirect_zone;
1549 
1550  handle->gns_op = NULL;
1551  if (0 == rd_count)
1552  {
1554  handle->edesc =
1555  GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1557  return;
1558  }
1559  for (int i = 0; i < rd_count; i++)
1560  {
1561  if (GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT != rd[i].record_type)
1562  continue;
1563  if (0 != strncmp (rd[i].data, handle->oidc->redirect_uri, rd[i].data_size))
1564  continue;
1565  tmp = GNUNET_strndup (rd[i].data, rd[i].data_size);
1566  if (NULL == strstr (tmp, handle->oidc->client_id))
1567  {
1569  "Redirect uri %s does not contain client_id %s\n",
1570  tmp,
1571  handle->oidc->client_id);
1572  }
1573  else
1574  {
1575  pos = strrchr (tmp, (unsigned char) '.');
1576  if (NULL == pos)
1577  {
1579  "Redirect uri %s contains client_id but is malformed\n",
1580  tmp);
1581  GNUNET_free (tmp);
1582  continue;
1583  }
1584  *pos = '\0';
1585  handle->redirect_prefix = GNUNET_strdup (tmp);
1586  tmp_key_str = pos + 1;
1587  pos = strchr (tmp_key_str, (unsigned char) '/');
1588  if (NULL == pos)
1589  {
1591  "Redirect uri %s contains client_id but is malformed\n",
1592  tmp);
1593  GNUNET_free (tmp);
1594  continue;
1595  }
1596  *pos = '\0';
1597  handle->redirect_suffix = GNUNET_strdup (pos + 1);
1598 
1599  GNUNET_STRINGS_string_to_data (tmp_key_str,
1600  strlen (tmp_key_str),
1601  &redirect_zone,
1602  sizeof(redirect_zone));
1603  }
1605  GNUNET_free (tmp);
1606  return;
1607  }
1609  handle->edesc =
1610  GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1612 }
#define GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT
Used reclaimID OIDC client redirect URIs.
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
uint32_t data
The data value.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
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:789
static void build_redirect(void *cls)

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, and OIDC_ERROR_KEY_SERVER_ERROR.

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 1619 of file plugin_rest_openid_connect.c.

1620 {
1621  struct RequestHandle *handle = cls;
1622 
1623  /* Lookup client redirect uri to verify request */
1624  handle->gns_op =
1627  &handle->oidc->client_pkey,
1631  handle);
1632 }
struct GNUNET_GNS_LookupRequest * GNUNET_GNS_lookup(struct GNUNET_GNS_Handle *handle, const char *name, const struct GNUNET_IDENTITY_PublicKey *zone, uint32_t type, enum GNUNET_GNS_LocalOptions options, GNUNET_GNS_LookupResultProcessor proc, void *proc_cls)
Perform an asynchronous lookup operation on the GNS.
Definition: gns_api.c:412
@ 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).
static struct GNUNET_GNS_Handle * gns_handle
GNS handle.
static void lookup_redirect_uri_result(void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd)

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 1636 of file plugin_rest_openid_connect.c.

1637 {
1638  struct GNUNET_HashCode hc;
1639  char *value;
1640  char *res;
1641 
1642  GNUNET_CRYPTO_hash (key, strlen (key), &hc);
1644  ->url_param_map,
1645  &hc))
1646  return NULL;
1647  value =
1648  GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, &hc);
1649  if (NULL == value)
1650  return NULL;
1651  GNUNET_STRINGS_urldecode (value, strlen (value), &res);
1652  return res;
1653 }
static int res
size_t GNUNET_STRINGS_urldecode(const char *data, size_t len, char **out)
url/percent encode (RFC3986).
Definition: strings.c:1807

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(), 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 1663 of file plugin_rest_openid_connect.c.

1664 {
1665  struct RequestHandle *handle = cls;
1666  struct GNUNET_HashCode cache_key;
1667 
1668  char *expected_scope;
1669  char delimiter[] = " ";
1670  int number_of_ignored_parameter, iterator;
1671 
1672 
1673  // REQUIRED value: redirect_uri
1674  handle->oidc->redirect_uri =
1676  if (NULL == handle->oidc->redirect_uri)
1677  {
1679  handle->edesc = GNUNET_strdup ("missing parameter redirect_uri");
1681  return;
1682  }
1683 
1684  // REQUIRED value: response_type
1685  handle->oidc->response_type =
1687  if (NULL == handle->oidc->response_type)
1688  {
1690  handle->edesc = GNUNET_strdup ("missing parameter response_type");
1692  return;
1693  }
1694 
1695  // REQUIRED value: scope
1697  if (NULL == handle->oidc->scope)
1698  {
1700  handle->edesc = GNUNET_strdup ("missing parameter scope");
1702  return;
1703  }
1704 
1705  // OPTIONAL value: nonce
1707 
1708  // OPTIONAL value: claims
1710 
1711  // TODO check other values if needed
1712  number_of_ignored_parameter =
1713  sizeof(OIDC_ignored_parameter_array) / sizeof(char *);
1714  for (iterator = 0; iterator < number_of_ignored_parameter; iterator++)
1715  {
1718  &cache_key);
1719  if (GNUNET_YES ==
1721  ->url_param_map,
1722  &cache_key))
1723  {
1725  GNUNET_asprintf (&handle->edesc,
1726  "Server will not handle parameter: %s",
1729  return;
1730  }
1731  }
1732 
1733  // We only support authorization code flows.
1734  if (0 != strcmp (handle->oidc->response_type,
1736  {
1738  handle->edesc = GNUNET_strdup ("The authorization server does not support "
1739  "obtaining this authorization code.");
1741  return;
1742  }
1743 
1744  // Checks if scope contains 'openid'
1745  expected_scope = GNUNET_strdup (handle->oidc->scope);
1746  char *test;
1747  test = strtok (expected_scope, delimiter);
1748  while (NULL != test)
1749  {
1750  if (0 == strcmp (OIDC_EXPECTED_AUTHORIZATION_SCOPE, expected_scope))
1751  break;
1752  test = strtok (NULL, delimiter);
1753  }
1754  if (NULL == test)
1755  {
1757  handle->edesc =
1758  GNUNET_strdup ("The requested scope is invalid, unknown, or malformed.");
1760  GNUNET_free (expected_scope);
1761  return;
1762  }
1763 
1764  GNUNET_free (expected_scope);
1765  if ((NULL == handle->oidc->login_identity) &&
1766  (GNUNET_NO == handle->oidc->user_cancelled))
1768  else
1770 }
static int iterator(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Iterator over hash map entries.
#define OIDC_ERROR_KEY_INVALID_REQUEST
OIDC error key for invalid requests.
static char * OIDC_ignored_parameter_array[]
OIDC ignored parameter array.
#define OIDC_ERROR_KEY_ACCESS_DENIED
OIDC error key for denied access.
#define OIDC_EXPECTED_AUTHORIZATION_SCOPE
OIDC expected scope part while authorizing.
static char * get_url_parameter_copy(const struct RequestHandle *handle, const char *key)
#define OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE
OIDC expected response_type while authorizing.
#define OIDC_ERROR_KEY_UNSUPPORTED_RESPONSE_TYPE
OIDC error key for unsupported response types.
static void client_redirect(void *cls)
Initiate redirect back to client.

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, iterator(), 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 1777 of file plugin_rest_openid_connect.c.

1778 {
1779  struct RequestHandle *handle = cls;
1781 
1782  if (GNUNET_OK !=
1784  {
1785  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Skipping non key %s\n", value);
1786  return;
1787  }
1788  if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1789  handle->tld = GNUNET_strdup (option + 1);
1790 }
static char * pkey
Public key of the zone to look in, in ASCII.

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_IDENTITY_public_key_from_string(), 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 1801 of file plugin_rest_openid_connect.c.

1804 {
1805  struct RequestHandle *handle = cls;
1806  struct EgoEntry *tmp_ego;
1807  const struct GNUNET_IDENTITY_PrivateKey *priv_key;
1809 
1811 
1812  // RECOMMENDED value: state - REQUIRED for answers
1814 
1815  // REQUIRED value: client_id
1817  if (NULL == handle->oidc->client_id)
1818  {
1820  handle->edesc = GNUNET_strdup ("missing parameter client_id");
1821  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1823  return;
1824  }
1825 
1826  // OPTIONAL value: code_challenge
1827  handle->oidc->code_challenge = get_url_parameter_copy (handle,
1829  if (NULL == handle->oidc->code_challenge)
1830  {
1832  "OAuth authorization request does not contain PKCE parameters!\n");
1833  }
1834 
1835  if (GNUNET_OK !=
1837  &handle->oidc->client_pkey))
1838  {
1840  handle->edesc = GNUNET_strdup ("The client is not authorized to request an "
1841  "authorization code using this method.");
1842  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1844  return;
1845  }
1846 
1847  // If we know this identity, translated the corresponding TLD
1848  // TODO: We might want to have a reverse lookup functionality for TLDs?
1849  for (tmp_ego = ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next)
1850  {
1851  priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego);
1852  GNUNET_IDENTITY_key_get_public (priv_key, &pkey);
1853  if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1854  {
1855  handle->tld = GNUNET_strdup (tmp_ego->identifier);
1856  handle->ego_entry = ego_tail;
1857  }
1858  }
1859  if (NULL == handle->tld)
1861  if (NULL == handle->tld)
1862  handle->tld = GNUNET_strdup (handle->oidc->client_id);
1864 }
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_IDENTITY_key_get_public(const struct GNUNET_IDENTITY_PrivateKey *privkey, struct GNUNET_IDENTITY_PublicKey *key)
Retrieves the public key representation of a private key.
Definition: identity_api.c:175
static struct EgoEntry * ego_tail
Ego list.
static void cookie_identity_interpretation(struct RequestHandle *handle)
Interprets cookie header and pass its identity keystring to handle.
#define OIDC_ERROR_KEY_UNAUTHORIZED_CLIENT
OIDC error key for unauthorized clients.
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.
The ego list.
char * identifier
Ego Identifier.
struct EgoEntry * next
DLL.
struct GNUNET_IDENTITY_Ego * ego
The Ego.
A private key for an identity as per LSD0001.

References build_authz_response(), cfg, cookie_identity_interpretation(), do_error(), EgoEntry::ego, ego_head, ego_tail, get_url_parameter_copy(), GNUNET_CONFIGURATION_iterate_section_values(), GNUNET_ERROR_TYPE_WARNING, GNUNET_IDENTITY_ego_get_private_key(), GNUNET_IDENTITY_key_get_public(), GNUNET_IDENTITY_public_key_from_string(), GNUNET_log, GNUNET_memcmp, GNUNET_OK, GNUNET_SCHEDULER_add_now(), GNUNET_strdup, handle, EgoEntry::identifier, EgoEntry::next, 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().

Here is the call 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 1875 of file plugin_rest_openid_connect.c.

1878 {
1879  struct MHD_Response *resp = GNUNET_REST_create_response ("");
1880  struct RequestHandle *handle = cls;
1881  struct GNUNET_HashCode cache_key;
1882  struct GNUNET_TIME_Absolute *current_time;
1883  struct GNUNET_TIME_Absolute *last_time;
1884  char *cookie;
1885  char *header_val;
1886  json_t *root;
1887  json_error_t error;
1888  json_t *identity;
1889  char term_data[handle->rest_handle->data_size + 1];
1890 
1891  term_data[handle->rest_handle->data_size] = '\0';
1892  GNUNET_memcpy (term_data,
1893  handle->rest_handle->data,
1894  handle->rest_handle->data_size);
1895  root = json_loads (term_data, JSON_DECODE_ANY, &error);
1896  identity = json_object_get (root, "identity");
1897  if (! json_is_string (identity))
1898  {
1900  "Error parsing json string from %s\n",
1901  term_data);
1902  handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
1903  json_decref (root);
1905  return;
1906  }
1907  GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity));
1908  GNUNET_asprintf (&header_val,
1909  "%s;Max-Age=%d",
1910  cookie,
1912  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1913  "Set-Cookie", header_val));
1914  GNUNET_assert (MHD_NO !=
1915  MHD_add_response_header (resp,
1916  "Access-Control-Allow-Methods",
1917  "POST"));
1918  GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key);
1919 
1920  if (0 != strcmp (json_string_value (identity), "Denied"))
1921  {
1922  current_time = GNUNET_new (struct GNUNET_TIME_Absolute);
1923  *current_time = GNUNET_TIME_relative_to_absolute (
1926  last_time =
1928  GNUNET_free (last_time);
1930  &cache_key,
1931  current_time,
1933  }
1934  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1935  GNUNET_free (cookie);
1936  GNUNET_free (header_val);
1937  json_decref (root);
1939 }
static struct GNUNET_IDENTITY_Handle * identity
Which namespace do we publish to? NULL if we do not publish to a namespace.
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.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE
If a value with the given key exists, replace it.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_get_second_(void)
Return relative time of 1s.
Definition: time.c:168
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:315
#define OIDC_COOKIE_EXPIRATION
OIDC cookie expiration (in seconds)

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.

Here is the call 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 1943 of file plugin_rest_openid_connect.c.

1946 {
1947  struct GNUNET_HashCode cache_key;
1948  char *authorization;
1949  char *credentials;
1950  char *basic_authorization;
1951  char *client_id_tmp;
1952  char *pass;
1953 
1956  &cache_key);
1958  ->header_param_map,
1959  &cache_key))
1960  return GNUNET_SYSERR;
1961  authorization =
1962  GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
1963  &cache_key);
1964 
1965  // split header in "Basic" and [content]
1966  credentials = strtok (authorization, " ");
1967  if ((NULL == credentials) || (0 != strcmp ("Basic", credentials)))
1968  return GNUNET_SYSERR;
1969  credentials = strtok (NULL, " ");
1970  if (NULL == credentials)
1971  return GNUNET_SYSERR;
1972  GNUNET_STRINGS_base64_decode (credentials,
1973  strlen (credentials),
1974  (void **) &basic_authorization);
1975 
1976  if (NULL == basic_authorization)
1977  return GNUNET_SYSERR;
1978  client_id_tmp = strtok (basic_authorization, ":");
1979  if (NULL == client_id_tmp)
1980  {
1981  GNUNET_free (basic_authorization);
1982  return GNUNET_SYSERR;
1983  }
1984  pass = strtok (NULL, ":");
1985  if (NULL == pass)
1986  {
1987  GNUNET_free (basic_authorization);
1988  return GNUNET_SYSERR;
1989  }
1990  *client_id = strdup (client_id_tmp);
1991  *client_secret = strdup (pass);
1992  GNUNET_free (basic_authorization);
1993  return GNUNET_OK;
1994 }
@ GNUNET_SYSERR
Definition: gnunet_common.h:97
size_t GNUNET_STRINGS_base64_decode(const char *data, size_t len, void **output)
Decode from Base64.
Definition: strings.c:1696
#define OIDC_AUTHORIZATION_HEADER_KEY
OIDC cookie header information key.

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 1998 of file plugin_rest_openid_connect.c.

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

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

Allow public clients with PKCE

Definition at line 2044 of file plugin_rest_openid_connect.c.

2046 {
2047  char *expected_pass;
2048  char *received_cid;
2049  char *received_cpw;
2050  char *pkce_cv;
2051 
2053  &received_cid,
2054  &received_cpw))
2055  {
2057  "Received client credentials in HTTP AuthZ header\n");
2058  }
2060  &received_cid,
2061  &received_cpw))
2062  {
2064  "Received client credentials in POST body\n");
2065  }
2066  else
2067  {
2070  if (NULL == pkce_cv)
2071  {
2073  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2074  return GNUNET_SYSERR;
2075  }
2076  handle->public_client = GNUNET_YES;
2077  GNUNET_free (pkce_cv);
2079  GNUNET_STRINGS_string_to_data (received_cid,
2080  strlen (received_cid),
2081  cid,
2082  sizeof(struct GNUNET_IDENTITY_PublicKey));
2083  GNUNET_free (received_cid);
2084  return GNUNET_OK;
2085 
2086  }
2087 
2088  // check client password
2090  "reclaim-rest-plugin",
2091  "OIDC_CLIENT_HMAC_SECRET",
2092  &expected_pass))
2093  {
2094  if (0 != strcmp (expected_pass, received_cpw))
2095  {
2096  GNUNET_free (expected_pass);
2098  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2099  GNUNET_free (received_cpw);
2100  GNUNET_free (received_cid);
2101  return GNUNET_SYSERR;
2102  }
2103  GNUNET_free (expected_pass);
2104  }
2105  else
2106  {
2107  GNUNET_free (received_cpw);
2108  GNUNET_free (received_cid);
2110  handle->edesc = GNUNET_strdup ("gnunet configuration failed");
2111  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2112  return GNUNET_SYSERR;
2113  }
2114  // check client_id
2115  for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
2116  handle->ego_entry = handle->ego_entry->next)
2117  {
2118  if (0 == strcmp (handle->ego_entry->keystring, received_cid))
2119  break;
2120  }
2121  if (NULL == handle->ego_entry)
2122  {
2123  GNUNET_free (received_cpw);
2124  GNUNET_free (received_cid);
2126  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2127  return GNUNET_SYSERR;
2128  }
2129  GNUNET_STRINGS_string_to_data (received_cid,
2130  strlen (received_cid),
2131  cid,
2132  sizeof(struct GNUNET_IDENTITY_PublicKey));
2133 
2134  GNUNET_free (received_cpw);
2135  GNUNET_free (received_cid);
2136  return GNUNET_OK;
2137 }
static int parse_credentials_post_body(struct RequestHandle *handle, char **client_id, char **client_secret)
#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_CODE_VERIFIER_KEY
OIDC PKCE code verifier.

References cfg, 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, 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()

const struct EgoEntry* find_ego ( struct RequestHandle handle,
struct GNUNET_IDENTITY_PublicKey test_key 
)

Definition at line 2141 of file plugin_rest_openid_connect.c.

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

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

Referenced by token_endpoint(), and userinfo_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 2166 of file plugin_rest_openid_connect.c.

2169 {
2170  struct RequestHandle *handle = cls;
2171  const struct EgoEntry *ego_entry = NULL;
2172  struct GNUNET_TIME_Relative expiration_time;
2173  struct GNUNET_RECLAIM_AttributeList *cl = NULL;
2174  struct GNUNET_RECLAIM_PresentationList *pl = NULL;
2176  struct GNUNET_IDENTITY_PublicKey cid;
2177  struct GNUNET_HashCode cache_key;
2178  struct MHD_Response *resp = NULL;
2179  char *grant_type = NULL;
2180  char *code = NULL;
2181  char *json_response = NULL;
2182  char *id_token = NULL;
2183  char *access_token = NULL;
2184  char *jwa = NULL;
2185  char *jwt_secret = NULL;
2186  char *nonce = NULL;
2187  char *code_verifier = NULL;
2188  json_t *oidc_jwk = NULL;
2189  char *oidc_jwk_path = NULL;
2190  char *oidc_directory = NULL;
2191  char *tmp_at = NULL;
2192 
2193  /*
2194  * Check Authorization
2195  */
2196  if (GNUNET_SYSERR == check_authorization (handle, &cid))
2197  {
2199  "OIDC authorization for token endpoint failed\n");
2201  return;
2202  }
2203 
2204  /*
2205  * Check parameter
2206  */
2207 
2208  // TODO Do not allow multiple equal parameter names
2209  // REQUIRED grant_type
2211  strlen (OIDC_GRANT_TYPE_KEY),
2212  &cache_key);
2214  if (NULL == grant_type)
2215  {
2217  handle->edesc = GNUNET_strdup ("missing parameter grant_type");
2218  handle->response_code = MHD_HTTP_BAD_REQUEST;
2220  return;
2221  }
2222 
2223  // Check parameter grant_type == "authorization_code"
2224  if (0 != strcmp (OIDC_GRANT_TYPE_VALUE, grant_type))
2225  {
2227  handle->response_code = MHD_HTTP_BAD_REQUEST;
2228  GNUNET_free (grant_type);
2230  return;
2231  }
2232  GNUNET_free (grant_type);
2233  // REQUIRED code
2235  if (NULL == code)
2236  {
2238  handle->edesc = GNUNET_strdup ("missing parameter code");
2239  handle->response_code = MHD_HTTP_BAD_REQUEST;
2241  return;
2242  }
2243  ego_entry = find_ego (handle, &cid);
2244  if (NULL == ego_entry)
2245  {
2247  handle->edesc = GNUNET_strdup ("Unknown client");
2248  handle->response_code = MHD_HTTP_BAD_REQUEST;
2249  GNUNET_free (code);
2251  return;
2252  }
2253 
2254  // REQUIRED code verifier
2256  if (NULL == code_verifier)
2257  {
2259  "OAuth authorization request does not contain PKCE parameters!\n");
2260 
2261  }
2262 
2263  // decode code
2264  if (GNUNET_OK != OIDC_parse_authz_code (&cid, code, code_verifier, &ticket,
2265  &cl, &pl, &nonce,
2267  {
2269  handle->edesc = GNUNET_strdup ("invalid code");
2270  handle->response_code = MHD_HTTP_BAD_REQUEST;
2271  GNUNET_free (code);
2272  if (NULL != code_verifier)
2273  GNUNET_free (code_verifier);
2275  return;
2276  }
2277  if (NULL != code_verifier)
2278  GNUNET_free (code_verifier);
2279 
2280  // create jwt
2282  "reclaim-rest-plugin",
2283  "expiration_time",
2284  &expiration_time))
2285  {
2287  handle->edesc = GNUNET_strdup ("gnunet configuration failed");
2288  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2289  GNUNET_free (code);
2290  if (NULL != nonce)
2291  GNUNET_free (nonce);
2295  return;
2296  }
2297 
2298  // Check if HMAC or RSA should be used
2300  "reclaim-rest-plugin",
2301  "oidc_json_web_algorithm",
2302  &jwa))
2303  {
2305  "Could not read OIDC JSON Web Algorithm config attribute."
2306  "Defaulting to RS256.");
2307  jwa = JWT_ALG_VALUE_RSA;
2308  }
2309 
2310  if ( ! strcmp (jwa, JWT_ALG_VALUE_RSA))
2311  {
2312  // Replace for now
2313  oidc_jwk_path = get_oidc_jwk_path (cls);
2314  oidc_jwk = read_jwk_from_file (oidc_jwk_path);
2315 
2316  // Check if secret JWK exists
2317  if (! oidc_jwk)
2318  {
2319  // Generate and save a new key
2320  oidc_jwk = generate_jwk ();
2321  oidc_directory = get_oidc_dir_path (cls);
2322 
2323  // Create new oidc directory
2324  if (GNUNET_OK != GNUNET_DISK_directory_create (oidc_directory))
2325  {
2327  ("Failed to create directory `%s' for storing oidc data\n"),
2328  oidc_directory);
2329  }
2330  else
2331  {
2332  write_jwk_to_file (oidc_jwk_path, oidc_jwk);
2333  }
2334  }
2335 
2336  // Generate oidc token
2338  &ticket.identity,
2339  cl,
2340  pl,
2341  &expiration_time,
2342  (NULL != nonce) ? nonce : NULL,
2343  oidc_jwk);
2344  }
2345  else if ( ! strcmp (jwa, JWT_ALG_VALUE_HMAC))
2346  {
2347  // TODO OPTIONAL acr,amr,azp
2349  "reclaim-rest-plugin",
2350  "jwt_secret",
2351  &jwt_secret))
2352  {
2354  handle->edesc = GNUNET_strdup ("No signing secret configured!");
2355  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2356  GNUNET_free (code);
2359  if (NULL != nonce)
2360  GNUNET_free (nonce);
2362  return;
2363  }
2364 
2366  &ticket.identity,
2367  cl,
2368  pl,
2369  &expiration_time,
2370  (NULL != nonce) ? nonce : NULL,
2371  jwt_secret);
2372 
2373  GNUNET_free (jwt_secret);
2374  }
2375  else
2376  {
2377  // TODO: OPTION NOT FOUND ERROR
2378  }
2379 
2380  if (NULL != nonce)
2381  GNUNET_free (nonce);
2382  access_token = OIDC_access_token_new (&ticket);
2387  GNUNET_CRYPTO_hash (access_token,
2388  strlen (access_token),
2389  &cache_key);
2401  &cache_key);
2403  &cache_key,
2404  code,
2406  /* If there was a previous code in there, free the old value */
2407  if (NULL != tmp_at)
2408  {
2410  "OIDC access token already issued. Cleanup.\n");
2411  GNUNET_free (tmp_at);
2412  }
2413 
2414  OIDC_build_token_response (access_token,
2415  id_token,
2416  &expiration_time,
2417  &json_response);
2418 
2419  resp = GNUNET_REST_create_response (json_response);
2420  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2421  "Cache-Control",
2422  "no-store"));
2423  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2424  "Pragma", "no-cache"));
2425  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2426  "Content-Type",
2427  "application/json"));
2428  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2431  GNUNET_free (access_token);
2432  GNUNET_free (json_response);
2433  GNUNET_free (id_token);
2435 }
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_DISK_directory_create(const char *dir)
Implementation of "mkdir -p".
Definition: disk.c:496
char * OIDC_generate_id_token_hmac(const struct GNUNET_IDENTITY_PublicKey *aud_key, const struct GNUNET_IDENTITY_PublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations, const struct GNUNET_TIME_Relative *expiration_time, const char *nonce, const char *secret_key)
Create a JWT using HMAC (HS256) from attributes.
Definition: oidc_helper.c:501
char * OIDC_access_token_new(const struct GNUNET_RECLAIM_Ticket *ticket)
Generate a new access token.
Definition: oidc_helper.c:930
int OIDC_parse_authz_code(const struct GNUNET_IDENTITY_PublicKey *audience, 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)
Parse reclaim ticket and nonce from authorization code.
Definition: oidc_helper.c:781
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?
Definition: oidc_helper.c:902
char * OIDC_generate_id_token_rsa(const struct GNUNET_IDENTITY_PublicKey *aud_key, const struct GNUNET_IDENTITY_PublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations, const struct GNUNET_TIME_Relative *expiration_time, const char *nonce, const json_t *secret_rsa_key)
Create a JWT using RSA256 algorithm from attributes.
Definition: oidc_helper.c:439
#define JWT_ALG_VALUE_RSA
Definition: oidc_helper.h:35
@ OIDC_VERIFICATION_DEFAULT
Strict verification.
Definition: oidc_helper.h:44
#define JWT_ALG_VALUE_HMAC
Definition: oidc_helper.h:34
json_t * read_jwk_from_file(const char *filename)
Read the the JSON Web Key in the given file and return it.
char * get_oidc_jwk_path(void *cls)
Return the path to the RSA JWK key file.
struct GNUNET_CONTAINER_MultiHashMap * oidc_code_cache
OIDC hashmap for cached access tokens and codes.
json_t * generate_jwk()
Generate a new RSA JSON Web Key.
static int write_jwk_to_file(const char *filename, json_t *jwk)
Write the JWK to file.
#define OIDC_ERROR_KEY_UNSUPPORTED_GRANT_TYPE
OIDC error key for unsupported grants.
const struct EgoEntry * find_ego(struct RequestHandle *handle, struct GNUNET_IDENTITY_PublicKey *test_key)
#define OIDC_GRANT_TYPE_KEY
OIDC grant_type key.
static int check_authorization(struct RequestHandle *handle, struct GNUNET_IDENTITY_PublicKey *cid)
#define OIDC_CODE_KEY
OIDC code key.
#define OIDC_GRANT_TYPE_VALUE
OIDC grant_type key.
json_t * oidc_jwk
The RSA key used by the oidc enpoint.
A list of GNUNET_RECLAIM_Presentation structures.
struct GNUNET_IDENTITY_PublicKey audience
The ticket audience (= relying party)
struct GNUNET_IDENTITY_PublicKey identity
The ticket issuer (= the user)
Time for relative time used by GNUnet, in microseconds.

References GNUNET_RECLAIM_Ticket::audience, cfg, check_authorization(), cleanup_handle(), do_error(), find_ego(), generate_jwk(), get_oidc_dir_path(), get_oidc_jwk_path(), get_url_parameter_copy(), 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_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, GNUNET_RECLAIM_Ticket::identity, JWT_ALG_VALUE_HMAC, JWT_ALG_VALUE_RSA, OIDC_access_token_new(), OIDC_build_token_response(), 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_jwk, OIDC_parse_authz_code(), OIDC_VERIFICATION_DEFAULT, read_jwk_from_file(), ticket, and write_jwk_to_file().

Here is the call graph for this function:

◆ consume_ticket()

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

Collects claims and stores them in handle.

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

already in list

Credential matches for attribute, add

Definition at line 2442 of file plugin_rest_openid_connect.c.

2446 {
2447  struct RequestHandle *handle = cls;
2450  struct MHD_Response *resp;
2451  struct GNUNET_HashCode cache_key;
2452  char *result_str;
2453  char *cached_code;
2454 
2455  if (NULL != handle->consume_timeout_op)
2456  GNUNET_SCHEDULER_cancel (handle->consume_timeout_op);
2457  handle->consume_timeout_op = NULL;
2458  handle->idp_op = NULL;
2459 
2463  GNUNET_CRYPTO_hash (handle->access_token,
2464  strlen (handle->access_token),
2465  &cache_key);
2467  &cache_key);
2468  if (NULL != cached_code)
2469  {
2471  &cache_key,
2472  cached_code);
2473  GNUNET_free (cached_code);
2474  }
2475 
2476 
2477  if (NULL == identity)
2478  {
2479  result_str = OIDC_generate_userinfo (&handle->ticket.identity,
2480  handle->attr_userinfo_list,
2481  handle->presentations);
2482  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2483  resp = GNUNET_REST_create_response (result_str);
2484  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2485  GNUNET_free (result_str);
2487  return;
2488  }
2491  &attr->credential,
2492  attr->type,
2493  attr->data,
2494  attr->data_size);
2495  ale->attribute->id = attr->id;
2496  ale->attribute->flag = attr->flag;
2497  ale->attribute->credential = attr->credential;
2498  GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
2499  handle->attr_userinfo_list->list_tail,
2500  ale);
2501  if (NULL == presentation)
2502  return;
2503  for (atle = handle->presentations->list_head;
2504  NULL != atle; atle = atle->next)
2505  {
2507  &atle->presentation->credential_id,
2508  &presentation->credential_id))
2509  continue;
2510  break;
2511  }
2512  if (NULL == atle)
2513  {
2516  atle->presentation = GNUNET_RECLAIM_presentation_new (presentation->type,
2517  presentation->data,
2518  presentation->
2519  data_size);
2520  atle->presentation->credential_id = presentation->credential_id;
2521  GNUNET_CONTAINER_DLL_insert (handle->presentations->list_head,
2522  handle->presentations->list_tail,
2523  atle);
2524  }
2525 }
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.
struct GNUNET_RECLAIM_Presentation * GNUNET_RECLAIM_presentation_new(uint32_t type, const void *data, size_t data_size)
char * OIDC_generate_userinfo(const struct GNUNET_IDENTITY_PublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations)
Generate userinfo JSON as string.
Definition: oidc_helper.c:346
struct GNUNET_RECLAIM_Presentation * presentation
The credential.
struct GNUNET_RECLAIM_PresentationListEntry * next
DLL.
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.

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_CONTAINER_DLL_insert, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_remove(), GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_new, GNUNET_NO, GNUNET_RECLAIM_attribute_new(), GNUNET_RECLAIM_id_is_equal, GNUNET_RECLAIM_presentation_new(), GNUNET_REST_create_response(), GNUNET_SCHEDULER_cancel(), handle, GNUNET_RECLAIM_Attribute::id, identity, 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.

Referenced by userinfo_endpoint().

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

◆ consume_fail()

static void consume_fail ( void *  cls)
static

Remove the cached item

Definition at line 2529 of file plugin_rest_openid_connect.c.

2530 {
2531  struct RequestHandle *handle = cls;
2532  struct GNUNET_HashCode cache_key;
2533  struct GNUNET_RECLAIM_AttributeList *cl = NULL;
2534  struct GNUNET_RECLAIM_PresentationList *pl = NULL;
2536  struct MHD_Response *resp;
2537  char *nonce;
2538  char *cached_code;
2539  char *result_str;
2540 
2541 
2542  handle->consume_timeout_op = NULL;
2543  if (NULL != handle->idp_op)
2544  GNUNET_RECLAIM_cancel (handle->idp_op);
2545  handle->idp_op = NULL;
2546 
2548  "Ticket consumptioned timed out. Using cache...\n");
2549  GNUNET_CRYPTO_hash (handle->access_token,
2550  strlen (handle->access_token),
2551  &cache_key);
2553  &cache_key);
2554  if (NULL == cached_code)
2555  {
2557  handle->edesc = GNUNET_strdup ("No Access Token in cache!");
2558  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2560  return;
2561  }
2566  &cache_key,
2567  cached_code);
2568 
2569  // decode code
2570  if (GNUNET_OK != OIDC_parse_authz_code (&handle->ticket.audience,
2571  cached_code, NULL, &ticket,
2572  &cl, &pl, &nonce,
2574  {
2576  handle->edesc = GNUNET_strdup ("invalid code");
2577  handle->response_code = MHD_HTTP_BAD_REQUEST;
2578  GNUNET_free (cached_code);
2579  if (NULL != nonce)
2580  GNUNET_free (nonce);
2582  return;
2583  }
2584 
2585  GNUNET_free (cached_code);
2586 
2587  result_str = OIDC_generate_userinfo (&handle->ticket.identity,
2588  cl,
2589  pl);
2590  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2591  resp = GNUNET_REST_create_response (result_str);
2592  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2593  GNUNET_free (result_str);
2594  GNUNET_free (nonce);
2598 }
@ OIDC_VERIFICATION_NO_CODE_VERIFIER
Do not check code verifier even if expected.
Definition: oidc_helper.h:49
#define OIDC_ERROR_KEY_INVALID_TOKEN
OIDC error key for invalid tokens.
static void do_userinfo_error(void *cls)
Task run on error in userinfo endpoint, sends error header.

References cleanup_handle(), do_error(), do_userinfo_error(), GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_remove(), 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, handle, 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 2609 of file plugin_rest_openid_connect.c.

2612 {
2613  // TODO expiration time
2614  struct RequestHandle *handle = cls;
2615  struct GNUNET_RECLAIM_Ticket *ticket;
2616  char delimiter[] = " ";
2617  struct GNUNET_HashCode cache_key;
2618  char *authorization;
2619  char *authorization_type;
2620  char *authorization_access_token;
2621  const struct EgoEntry *aud_ego;
2622  const struct GNUNET_IDENTITY_PrivateKey *privkey;
2623 
2624  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting userinfo\n");
2627  &cache_key);
2629  ->header_param_map,
2630  &cache_key))
2631  {
2633  handle->edesc = GNUNET_strdup ("No Access Token");
2634  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2636  return;
2637  }
2638  authorization =
2639  GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
2640  &cache_key);
2641 
2642  // split header in "Bearer" and access_token
2643  authorization = GNUNET_strdup (authorization);
2644  authorization_type = strtok (authorization, delimiter);
2645  if ((NULL == authorization_type) ||
2646  (0 != strcmp ("Bearer", authorization_type)))
2647  {
2649  handle->edesc = GNUNET_strdup ("No Access Token");
2650  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2652  GNUNET_free (authorization);
2653  return;
2654  }
2655  authorization_access_token = strtok (NULL, delimiter);
2656  if (NULL == authorization_access_token)
2657  {
2659  handle->edesc = GNUNET_strdup ("Access token missing");
2660  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2662  GNUNET_free (authorization);
2663  return;
2664  }
2665 
2666  if (GNUNET_OK != OIDC_access_token_parse (authorization_access_token,
2667  &ticket))
2668  {
2670  handle->edesc = GNUNET_strdup ("The access token is invalid");
2671  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2673  GNUNET_free (authorization);
2674  return;
2675 
2676  }
2677  GNUNET_assert (NULL != ticket);
2678  handle->ticket = *ticket;
2679  GNUNET_free (ticket);
2680  aud_ego = find_ego (handle, &handle->ticket.audience);
2681  if (NULL == aud_ego)
2682  {
2684  handle->edesc = GNUNET_strdup ("The access token expired");
2685  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2687  GNUNET_free (authorization);
2688  return;
2689  }
2690  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Consuming ticket\n");
2691  privkey = GNUNET_IDENTITY_ego_get_private_key (aud_ego->ego);
2692  handle->attr_userinfo_list =
2694  handle->presentations =
2696 
2697  /* If the consume takes too long, we use values from the cache */
2698  handle->access_token = GNUNET_strdup (authorization_access_token);
2699  handle->consume_timeout_op = GNUNET_SCHEDULER_add_delayed (consume_timeout,
2700  &consume_fail,
2701  handle);
2703  privkey,
2704  &handle->ticket,
2705  &consume_ticket,
2706  handle);
2707  GNUNET_free (authorization);
2708 }
struct GNUNET_RECLAIM_Operation * GNUNET_RECLAIM_ticket_consume(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_IDENTITY_PrivateKey *identity, const struct GNUNET_RECLAIM_Ticket *ticket, GNUNET_RECLAIM_AttributeTicketResult cb, void *cb_cls)
Consumes an issued ticket.
Definition: reclaim_api.c:1589
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:1254
int OIDC_access_token_parse(const char *token, struct GNUNET_RECLAIM_Ticket **ticket)
Parse an access token.
Definition: oidc_helper.c:945
static void consume_fail(void *cls)
static struct GNUNET_TIME_Relative consume_timeout
Timeout for consume call on userinfo.
static void consume_ticket(void *cls, const struct GNUNET_IDENTITY_PublicKey *identity, const struct GNUNET_RECLAIM_Attribute *attr, const struct GNUNET_RECLAIM_Presentation *presentation)
Collects claims and stores them in handle.

References consume_fail(), consume_ticket(), consume_timeout, do_userinfo_error(), EgoEntry::ego, find_ego(), GNUNET_assert, GNUNET_CONTAINER_multihashmap_contains(), GNUNET_CONTAINER_multihashmap_get(), GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_IDENTITY_ego_get_private_key(), 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.

Here is the call 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 2718 of file plugin_rest_openid_connect.c.

2721 {
2722  char *oidc_directory;
2723  char *oidc_jwk_path;
2724  char *oidc_jwk_pub_str;
2725  json_t *oidc_jwk;
2726  struct MHD_Response *resp;
2727  struct RequestHandle *handle = cls;
2728 
2729  oidc_jwk_path = get_oidc_jwk_path (cls);
2730  oidc_jwk = read_jwk_from_file (oidc_jwk_path);
2731 
2732  // Check if secret JWK exists
2733  if (! oidc_jwk)
2734  {
2735  // Generate and save a new key
2736  oidc_jwk = generate_jwk ();
2737  oidc_directory = get_oidc_dir_path (cls);
2738 
2739  // Create new oidc directory
2740  if (GNUNET_OK != GNUNET_DISK_directory_create (oidc_directory))
2741  {
2743  ("Failed to create directory `%s' for storing oidc data\n"),
2744  oidc_directory);
2745  }
2746  else
2747  {
2748  write_jwk_to_file (oidc_jwk_path, oidc_jwk);
2749  }
2750  }
2751 
2752  // Convert secret JWK to public JWK
2753  jose_jwk_pub (NULL, oidc_jwk);
2754 
2755  // Encode JWK as string and return to API endpoint
2756  oidc_jwk_pub_str = json_dumps (oidc_jwk, JSON_INDENT (1));
2757  resp = GNUNET_REST_create_response (oidc_jwk_pub_str);
2758  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2759  json_decref (oidc_jwk);
2760  GNUNET_free (oidc_jwk_pub_str);
2761  GNUNET_free (oidc_jwk_pub_str);
2763 }

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, oidc_jwk, read_jwk_from_file(), and write_jwk_to_file().

Here is the call 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' or 'GNUNET_IDENTITY_get', 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 2798 of file plugin_rest_openid_connect.c.

2802 {
2803  struct EgoEntry *ego_entry;
2805 
2806  if (NULL == ego)
2807  {
2809  return;
2810  }
2811  if (ID_REST_STATE_INIT == state)
2812 
2813  {
2814  ego_entry = GNUNET_new (struct EgoEntry);
2817  ego_entry->ego = ego;
2818  ego_entry->identifier = GNUNET_strdup (identifier);
2820  ego_tail,
2821  ego_entry);
2822  return;
2823  }
2824  /* Ego renamed or added */
2825  if (identifier != NULL)
2826  {
2827  for (ego_entry = ego_head; NULL != ego_entry;
2828  ego_entry = ego_entry->next)
2829  {
2830  if (ego_entry->ego == ego)
2831  {
2832  /* Rename */
2833  GNUNET_free (ego_entry->identifier);
2834  ego_entry->identifier = GNUNET_strdup (identifier);
2835  break;
2836  }
2837  }
2838  if (NULL == ego_entry)
2839  {
2840  /* Add */
2841  ego_entry = GNUNET_new (struct EgoEntry);
2844  ego_entry->ego = ego;
2845  ego_entry->identifier = GNUNET_strdup (identifier);
2847  ego_tail,
2848  ego_entry);
2849  }
2850  }
2851  else
2852  {
2853  /* Delete */
2854  for (ego_entry = ego_head; NULL != ego_entry;
2855  ego_entry = ego_entry->next)
2856  {
2857  if (ego_entry->ego == ego)
2858  break;
2859  }
2860  if (NULL == ego_entry)
2861  return; /* Not found */
2862 
2864  ego_tail,
2865  ego_entry);
2866  GNUNET_free (ego_entry->identifier);
2867  GNUNET_free (ego_entry->keystring);
2868  GNUNET_free (ego_entry);
2869  return;
2870  }
2871 }
struct GNUNET_IDENTITY_PrivateKey pk
Private key from command line option, or NULL.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
char * GNUNET_IDENTITY_public_key_to_string(const struct GNUNET_IDENTITY_PublicKey *key)
Creates a (Base32) string representation of the public key.
#define ID_REST_STATE_INIT
State while collecting all egos.
static int state
The processing state.
#define ID_REST_STATE_POST_INIT
Done collecting egos.
char * keystring
Public key string.

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

Referenced by libgnunet_plugin_rest_openid_connect_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 2875 of file plugin_rest_openid_connect.c.

2878 {
2879  json_t *oidc_config;
2880  json_t *auth_methods;
2881  json_t *sig_algs;
2882  json_t *scopes;
2883  json_t *response_types;
2884  json_t *sub_types;
2885  json_t *claim_types;
2886  char *oidc_config_str;
2887  struct MHD_Response *resp;
2888  struct RequestHandle *handle = cls;
2889 
2890  oidc_config = json_object ();
2891  // FIXME get from config?
2892  json_object_set_new (oidc_config,
2893  "issuer", json_string ("http://localhost:7776"));
2894  json_object_set_new (oidc_config,
2895  "authorization_endpoint",
2896  json_string ("https://api.reclaim/openid/authorize"));
2897  json_object_set_new (oidc_config,
2898  "token_endpoint",
2899  json_string ("http://localhost:7776/openid/token"));
2900  auth_methods = json_array ();
2901  json_array_append_new (auth_methods,
2902  json_string ("client_secret_basic"));
2903  json_array_append_new (auth_methods,
2904  json_string ("client_secret_post"));
2905  json_object_set_new (oidc_config,
2906  "token_endpoint_auth_methods_supported",
2907  auth_methods);
2908  sig_algs = json_array ();
2909  json_array_append_new (sig_algs,
2910  json_string ("HS512"));
2911  json_array_append_new (sig_algs,
2912  json_string ("RS256"));
2913  json_object_set_new (oidc_config,
2914  "id_token_signing_alg_values_supported",
2915  sig_algs);
2916  json_object_set_new (oidc_config,
2917  "jwks_uri",
2918  json_string ("http://localhost:7776/jwks.json"));
2919  json_object_set_new (oidc_config,
2920  "userinfo_endpoint",
2921  json_string ("http://localhost:7776/openid/userinfo"));
2922  scopes = json_array ();
2923  json_array_append_new (scopes,
2924  json_string ("openid"));
2925  json_array_append_new (scopes,
2926  json_string ("profile"));
2927  json_array_append_new (scopes,
2928  json_string ("email"));
2929  json_array_append_new (scopes,
2930  json_string ("address"));
2931  json_array_append_new (scopes,
2932  json_string ("phone"));
2933  json_object_set_new (oidc_config,
2934  "scopes_supported",
2935  scopes);
2936  response_types = json_array ();
2937  json_array_append_new (response_types,
2938  json_string ("code"));
2939  json_object_set_new (oidc_config,
2940  "response_types_supported",
2941  response_types);
2942  sub_types = json_array ();
2943  json_array_append_new (sub_types,
2944  json_string ("public")); /* no pairwise support */
2945  json_object_set_new (oidc_config,
2946  "subject_types_supported",
2947  sub_types);
2948  claim_types = json_array ();
2949  json_array_append_new (claim_types,
2950  json_string ("normal"));
2951  json_array_append_new (claim_types,
2952  json_string ("aggregated"));
2953  json_object_set_new (oidc_config,
2954  "claim_types_supported",
2955  claim_types);
2956  json_object_set_new (oidc_config,
2957  "claims_parameter_supported",
2958  json_boolean (1));
2959  oidc_config_str = json_dumps (oidc_config, JSON_INDENT (1));
2960  resp = GNUNET_REST_create_response (oidc_config_str);
2961  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2962  json_decref (oidc_config);
2963  GNUNET_free (oidc_config_str);
2965 }

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

Here is the call 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 2976 of file plugin_rest_openid_connect.c.

2979 {
2980  struct MHD_Response *resp;
2981  struct RequestHandle *handle = cls;
2982 
2983  // For now, independent of path return all options
2984  resp = GNUNET_REST_create_response (NULL);
2985  GNUNET_assert (MHD_NO !=
2986  MHD_add_response_header (resp,
2987  "Access-Control-Allow-Methods",
2988  allow_methods));
2989  GNUNET_assert (MHD_NO !=
2990  MHD_add_response_header (resp,
2991  "Access-Control-Allow-Origin",
2992  "*"));
2993  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2995  return;
2996 }

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

Here is the call graph for this function:

◆ rest_identity_process_request()

static enum GNUNET_GenericReturnValue rest_identity_process_request ( struct GNUNET_REST_RequestHandle rest_handle,
GNUNET_REST_ResultProcessor  proc,
void *  proc_cls 
)
static

Definition at line 2976 of file plugin_rest_openid_connect.c.

3003 {
3004  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
3006  static const struct GNUNET_REST_RequestHandler handlers[] =
3007  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint },
3008  { MHD_HTTP_METHOD_POST,
3010  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont },
3011  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
3012  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
3013  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
3014  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_JWKS, &jwks_endpoint },
3015  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_OIDC_CONFIG,
3017  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC_CONFIG,
3018  &oidc_config_cors },
3019  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont },
3021 
3022  handle->oidc = GNUNET_new (struct OIDC_Variables);
3023  if (NULL == OIDC_cookie_jar_map)
3025  GNUNET_NO);
3026  if (NULL == oidc_code_cache)
3028  GNUNET_NO);
3029 
3030  handle->response_code = 0;
3032  handle->proc_cls = proc_cls;
3033  handle->proc = proc;
3034  handle->rest_handle = rest_handle;
3035  handle->url = GNUNET_strdup (rest_handle->url);
3036  handle->timeout_task =
3039  requests_tail,
3040  handle);
3041  if (handle->url[strlen (handle->url) - 1] == '/')
3042  handle->url[strlen (handle->url) - 1] = '\0';
3043  if (GNUNET_NO ==
3044  GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
3045  return GNUNET_NO;
3046 
3047  return GNUNET_YES;
3048 }
static struct GNUNET_CADET_MessageHandler handlers[]
Handlers, for diverse services.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
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:77
#define GNUNET_REST_HANDLER_END
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
#define GNUNET_REST_API_NS_OIDC_CONFIG
OIDC config.
#define GNUNET_REST_API_NS_LOGIN
Login namespace.
#define GNUNET_REST_API_NS_OIDC
REST root namespace.
static void do_timeout(void *cls)
Task run on timeout, sends error message.
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.
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 GNUNET_REST_API_JWKS
JSON Web Keys endpoint.
static void options_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Respond to OPTIONS request.
static void oidc_config_endpoint(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
#define GNUNET_REST_API_NS_TOKEN
Token endpoint.
#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.
static void authorize_endpoint(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Responds to authorization GET and url-encoded POST request.
const char * url
The url as string.
void(* proc)(struct GNUNET_REST_RequestHandle *handle, const char *url, void *cls)
Namespace to handle.
OIDC needed variables.

Referenced by libgnunet_plugin_rest_openid_connect_init().

Here is the caller graph for this function:

◆ libgnunet_plugin_rest_openid_connect_init()

void* libgnunet_plugin_rest_openid_connect_init ( void *  cls)

Entry point for the plugin.

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

Definition at line 3058 of file plugin_rest_openid_connect.c.

3059 {
3060  static struct Plugin plugin;
3061  struct GNUNET_REST_Plugin *api;
3062 
3063  cfg = cls;
3064  if (NULL != plugin.cfg)
3065  return NULL; /* can only initialize once! */
3066  memset (&plugin, 0, sizeof(struct Plugin));
3067  plugin.cfg = cfg;
3068  api = GNUNET_new (struct GNUNET_REST_Plugin);
3069  api->cls = &plugin;
3076  "reclaim-rest-plugin",
3077  "OIDC_USERINFO_CONSUME_TIMEOUT",
3078  &consume_timeout))
3079  {
3081  }
3082 
3083 
3086  "%s, %s, %s, %s, %s",
3087  MHD_HTTP_METHOD_GET,
3088  MHD_HTTP_METHOD_POST,
3089  MHD_HTTP_METHOD_PUT,
3090  MHD_HTTP_METHOD_DELETE,
3091  MHD_HTTP_METHOD_OPTIONS);
3092 
3094  _ ("OpenID Connect REST API initialized\n"));
3095  return api;
3096 }
struct Plugin * plugin
The process handle to the testbed service.
struct GNUNET_GNS_Handle * GNUNET_GNS_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Initialize the connection with the GNS service.
Definition: gns_api.c:268
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.
Definition: identity_api.c:610
struct GNUNET_RECLAIM_Handle * GNUNET_RECLAIM_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the re:claimID service.
Definition: reclaim_api.c:1063
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
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.
#define CONSUME_TIMEOUT
How long to wait for a consume in userinfo endpoint.
static struct GNUNET_IDENTITY_Handle * identity_handle
Handle to Identity service.
static enum GNUNET_GenericReturnValue rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
struct returned by the initialization function of the plugin
char * name
Plugin name.
void * cls
The closure of the plugin.
enum GNUNET_GenericReturnValue(* process_request)(struct GNUNET_REST_RequestHandle *handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function to process a REST call.
Handle for a plugin.
Definition: block.c:38
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.

References _, allow_methods, Plugin::cfg, cfg, 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, plugin, GNUNET_REST_Plugin::process_request, rest_identity_process_request(), and state.

Here is the call graph for this function:

◆ cleanup_hashmap()

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

Definition at line 3100 of file plugin_rest_openid_connect.c.

3101 {
3102  GNUNET_free (value);
3103  return GNUNET_YES;
3104 }

References GNUNET_free, GNUNET_YES, and value.

Referenced by libgnunet_plugin_rest_openid_connect_done().

Here is the caller graph for this function:

◆ libgnunet_plugin_rest_openid_connect_done()

void* libgnunet_plugin_rest_openid_connect_done ( void *  cls)

Exit point from the plugin.

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

Definition at line 3114 of file plugin_rest_openid_connect.c.

3115 {
3116  struct GNUNET_REST_Plugin *api = cls;
3117  struct Plugin *plugin = api->cls;
3118  struct EgoEntry *ego_entry;
3119 
3120  plugin->cfg = NULL;
3121  while (NULL != requests_head)
3123  if (NULL != OIDC_cookie_jar_map)
3124  {
3126  &cleanup_hashmap,
3127  NULL);
3129  }
3130  if (NULL != oidc_code_cache)
3131  {
3133  &cleanup_hashmap,
3134  NULL);
3136  }
3137 
3139  if (NULL != gns_handle)
3141  if (NULL != identity_handle)
3143  if (NULL != idp)
3145  while (NULL != (ego_entry = ego_head))
3146  {
3148  ego_tail,
3149  ego_entry);
3150  GNUNET_free (ego_entry->identifier);
3151  GNUNET_free (ego_entry->keystring);
3152  GNUNET_free (ego_entry);
3153  }
3154  GNUNET_free (api);
3156  "OpenID Connect REST plugin is finished\n");
3157  return NULL;
3158 }
void GNUNET_GNS_disconnect(struct GNUNET_GNS_Handle *handle)
Shutdown connection with the GNS service.
Definition: gns_api.c:290
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
void GNUNET_IDENTITY_disconnect(struct GNUNET_IDENTITY_Handle *h)
Disconnect from identity service.
Definition: identity_api.c:921
void GNUNET_RECLAIM_disconnect(struct GNUNET_RECLAIM_Handle *h)
Disconnect from identity provider service.
Definition: reclaim_api.c:1103
static int cleanup_hashmap(void *cls, const struct GNUNET_HashCode *key, void *value)
void * cls
Closure for all of the callbacks.
struct GNUNET_BLOCK_PluginFunctions * api
Plugin API.
Definition: block.c:47

References allow_methods, Plugin::api, Plugin::cfg, cleanup_handle(), cleanup_hashmap(), GNUNET_BLOCK_PluginFunctions::cls, GNUNET_REST_Plugin::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.

Here is the call graph for this function:

Variable Documentation

◆ OIDC_ignored_parameter_array

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 251 of file plugin_rest_openid_connect.c.

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 262 of file plugin_rest_openid_connect.c.

Referenced by consume_fail(), consume_ticket(), libgnunet_plugin_rest_openid_connect_done(), 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 267 of file plugin_rest_openid_connect.c.

Referenced by code_redirect(), cookie_identity_interpretation(), libgnunet_plugin_rest_openid_connect_done(), and login_cont().

◆ cfg

const struct GNUNET_CONFIGURATION_Handle* cfg

The configuration handle.

Handle to our configuration.

Definition at line 272 of file plugin_rest_openid_connect.c.

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

◆ allow_methods

char* allow_methods
static

◆ ego_head

struct EgoEntry* ego_head
static

◆ ego_tail

struct EgoEntry* ego_tail
static

◆ state

int state
static

The processing state.

Definition at line 292 of file plugin_rest_openid_connect.c.

Referenced by libgnunet_plugin_rest_openid_connect_init(), and list_ego().

◆ identity_handle

struct GNUNET_IDENTITY_Handle* identity_handle
static

Handle to Identity service.

Definition at line 297 of file plugin_rest_openid_connect.c.

Referenced by libgnunet_plugin_rest_openid_connect_done(), and libgnunet_plugin_rest_openid_connect_init().

◆ gns_handle

struct GNUNET_GNS_Handle* gns_handle
static

◆ idp

struct GNUNET_RECLAIM_Handle* idp
static

◆ consume_timeout

struct GNUNET_TIME_Relative consume_timeout
static

Timeout for consume call on userinfo.

Definition at line 307 of file plugin_rest_openid_connect.c.

Referenced by libgnunet_plugin_rest_openid_connect_init(), and userinfo_endpoint().

◆ oidc_jwk

json_t* oidc_jwk

The RSA key used by the oidc enpoint.

Definition at line 325 of file plugin_rest_openid_connect.c.

Referenced by jwks_endpoint(), and token_endpoint().

◆ requests_head

struct RequestHandle* requests_head
static

◆ requests_tail

struct RequestHandle* requests_tail
static

DLL.

Definition at line 594 of file plugin_rest_openid_connect.c.

Referenced by cleanup_handle().