GNUnet  0.20.0
plugin_rest_openid_connect.c File Reference
#include "platform.h"
#include <inttypes.h>
#include <jansson.h>
#include <jose/jose.h>
#include "gnunet_util_lib.h"
#include "gnunet_gns_service.h"
#include "gnunet_gnsrecord_lib.h"
#include "gnunet_identity_service.h"
#include "gnunet_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 49 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 54 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 59 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 64 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 69 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 74 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 79 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 84 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 89 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 94 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 99 of file plugin_rest_openid_connect.c.

◆ OIDC_CODE_KEY

#define OIDC_CODE_KEY   "code"

OIDC code key.

Definition at line 104 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 109 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 114 of file plugin_rest_openid_connect.c.

◆ OIDC_SCOPE_KEY

#define OIDC_SCOPE_KEY   "scope"

OIDC scope key.

Definition at line 119 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 124 of file plugin_rest_openid_connect.c.

◆ OIDC_STATE_KEY

#define OIDC_STATE_KEY   "state"

OIDC state key.

Definition at line 129 of file plugin_rest_openid_connect.c.

◆ OIDC_NONCE_KEY

#define OIDC_NONCE_KEY   "nonce"

OIDC nonce key.

Definition at line 134 of file plugin_rest_openid_connect.c.

◆ OIDC_CLAIMS_KEY

#define OIDC_CLAIMS_KEY   "claims"

OIDC claims key.

Definition at line 139 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 144 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 149 of file plugin_rest_openid_connect.c.

◆ OIDC_COOKIE_EXPIRATION

#define OIDC_COOKIE_EXPIRATION   3

OIDC cookie expiration (in seconds)

Definition at line 154 of file plugin_rest_openid_connect.c.

◆ OIDC_COOKIE_HEADER_KEY

#define OIDC_COOKIE_HEADER_KEY   "cookie"

OIDC cookie header key.

Definition at line 159 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 164 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 169 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 174 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 179 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 184 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 189 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 194 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 199 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 204 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 209 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 214 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 219 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 224 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 229 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 234 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 239 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:484

How long to wait for a consume in userinfo endpoint.

Definition at line 244 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 601 of file plugin_rest_openid_connect.c.

602 {
603 
604  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
605  if (NULL != handle->timeout_task)
606  GNUNET_SCHEDULER_cancel (handle->timeout_task);
607  if (NULL != handle->attr_it)
609  if (NULL != handle->cred_it)
611  if (NULL != handle->ticket_it)
613  if (NULL != handle->idp_op)
614  GNUNET_RECLAIM_cancel (handle->idp_op);
615  if (NULL != handle->consume_timeout_op)
616  GNUNET_SCHEDULER_cancel (handle->consume_timeout_op);
617  GNUNET_free (handle->url);
618  GNUNET_free (handle->tld);
619  GNUNET_free (handle->redirect_prefix);
620  GNUNET_free (handle->redirect_suffix);
621  GNUNET_free (handle->emsg);
622  GNUNET_free (handle->edesc);
623  if (NULL != handle->gns_op)
625  if (NULL != handle->oidc)
626  {
627  GNUNET_free (handle->oidc->client_id);
628  GNUNET_free (handle->oidc->login_identity);
629  GNUNET_free (handle->oidc->nonce);
630  GNUNET_free (handle->oidc->redirect_uri);
631  GNUNET_free (handle->oidc->response_type);
632  GNUNET_free (handle->oidc->scope);
633  GNUNET_free (handle->oidc->state);
634  if (NULL != handle->oidc->claims)
635  GNUNET_free (handle->oidc->claims);
636  if (NULL != handle->oidc->code_challenge)
637  GNUNET_free (handle->oidc->code_challenge);
638  GNUNET_free (handle->oidc);
639  }
640  if (NULL!=handle->attr_idtoken_list)
641  GNUNET_RECLAIM_attribute_list_destroy (handle->attr_idtoken_list);
642  if (NULL!=handle->attr_userinfo_list)
643  GNUNET_RECLAIM_attribute_list_destroy (handle->attr_userinfo_list);
644  if (NULL!=handle->credentials)
646  if (NULL!=handle->presentations)
650  handle);
651  if (NULL != handle->access_token)
652  GNUNET_free (handle->access_token);
654 }
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 credential 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:1128
void GNUNET_RECLAIM_get_attributes_stop(struct GNUNET_RECLAIM_AttributeIterator *it)
Stops iteration and releases the handle for further calls.
Definition: reclaim_api.c:1391
void GNUNET_RECLAIM_get_credentials_stop(struct GNUNET_RECLAIM_CredentialIterator *ait)
Stops iteration and releases the handle for further calls.
Definition: reclaim_api.c:1469
void GNUNET_RECLAIM_ticket_iteration_stop(struct GNUNET_RECLAIM_TicketIterator *it)
Stops iteration and releases the handle for further calls.
Definition: reclaim_api.c:1661
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975
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 663 of file plugin_rest_openid_connect.c.

664 {
665  struct RequestHandle *handle = cls;
666  struct MHD_Response *resp;
667  char *json_error;
668 
669  GNUNET_asprintf (&json_error,
670  "{ \"error\" : \"%s\", \"error_description\" : \"%s\"%s%s%s}",
671  handle->emsg,
672  (NULL != handle->edesc) ? handle->edesc : "",
673  (NULL != handle->oidc->state) ? ", \"state\":\"" : "",
674  (NULL != handle->oidc->state) ? handle->oidc->state : "",
675  (NULL != handle->oidc->state) ? "\"" : "");
676  if (0 == handle->response_code)
677  handle->response_code = MHD_HTTP_BAD_REQUEST;
678  resp = GNUNET_REST_create_response (json_error);
679  if (MHD_HTTP_UNAUTHORIZED == handle->response_code)
680  GNUNET_assert (MHD_NO !=
681  MHD_add_response_header (resp,
682  MHD_HTTP_HEADER_WWW_AUTHENTICATE,
683  "Basic"));
684  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
685  MHD_HTTP_HEADER_CONTENT_TYPE,
686  "application/json"));
687  handle->proc (handle->proc_cls, resp, handle->response_code);
689  GNUNET_free (json_error);
690 }
#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:44
@ MHD_HTTP_BAD_REQUEST
Bad Request [RFC7231, Section 6.5.1].
@ MHD_HTTP_UNAUTHORIZED
Unauthorized [RFC7235, Section 3.1].
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(), handle, MHD_HTTP_BAD_REQUEST, and MHD_HTTP_UNAUTHORIZED.

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

701 {
702  struct RequestHandle *handle = cls;
703  struct MHD_Response *resp;
704  char *error;
705 
707  "Error: %s\n", handle->edesc);
708  GNUNET_asprintf (&error,
709  "error=\"%s\", error_description=\"%s\"",
710  handle->emsg,
711  (NULL != handle->edesc) ? handle->edesc : "");
712  resp = GNUNET_REST_create_response ("");
713  GNUNET_assert (MHD_NO !=
714  MHD_add_response_header (resp,
715  MHD_HTTP_HEADER_WWW_AUTHENTICATE,
716  "Bearer"));
717  handle->proc (handle->proc_cls, resp, handle->response_code);
719  GNUNET_free (error);
720 }
@ 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 729 of file plugin_rest_openid_connect.c.

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

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

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

758 {
759  struct RequestHandle *handle = cls;
760 
761  handle->timeout_task = NULL;
762  do_error (handle);
763 }
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 774 of file plugin_rest_openid_connect.c.

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

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

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

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

892 {
893  json_t *jwk;
894  json_error_t error;
895 
896  jwk = json_load_file (filename, JSON_DECODE_ANY, &error);
897 
898  if (! jwk)
899  {
901  ("Could not read OIDC RSA key from config file; %s\n"),
902  error.text);
903  }
904 
905  return jwk;
906 }
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 916 of file plugin_rest_openid_connect.c.

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

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

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

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

952 {
953  char *oidc_directory;
954  struct RequestHandle *handle = cls;
955 
956  // Read OIDC directory from config
958  "reclaim-rest-plugin",
959  "oidc_dir",
960  &oidc_directory))
961  {
962  // Could not read Config file
964  handle->edesc = GNUNET_strdup ("gnunet configuration failed");
965  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
967  return NULL;
968  }
969 
970  return oidc_directory;
971 }
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:1299
@ MHD_HTTP_INTERNAL_SERVER_ERROR
Internal Server Error [RFC7231, Section 6.6.1].
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, MHD_HTTP_INTERNAL_SERVER_ERROR, 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 979 of file plugin_rest_openid_connect.c.

980 {
981  char *oidc_directory;
982  char *oidc_jwk_path;
983 
984  oidc_directory = get_oidc_dir_path (cls);
985 
986  // Create path to file
987  GNUNET_asprintf (&oidc_jwk_path, "%s/%s", oidc_directory,
989 
990  return oidc_jwk_path;
991 }
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 998 of file plugin_rest_openid_connect.c.

999 {
1000  char *login_base_url;
1001  char *new_redirect;
1002  char *tmp;
1003  struct MHD_Response *resp;
1004  struct GNUNET_Buffer buf = { 0 };
1005  struct RequestHandle *handle = cls;
1006 
1008  "reclaim-rest-plugin",
1009  "address",
1010  &login_base_url))
1011  {
1012  GNUNET_buffer_write_str (&buf, login_base_url);
1014  "?%s=%s",
1016  handle->oidc->response_type);
1018  "&%s=%s",
1020  handle->oidc->client_id);
1021  GNUNET_STRINGS_urlencode (handle->oidc->redirect_uri,
1022  strlen (handle->oidc->redirect_uri),
1023  &tmp);
1025  "&%s=%s",
1027  tmp);
1028  GNUNET_free (tmp);
1029  GNUNET_STRINGS_urlencode (handle->oidc->scope,
1030  strlen (handle->oidc->scope),
1031  &tmp);
1033  "&%s=%s",
1035  tmp);
1036  GNUNET_free (tmp);
1037  if (NULL != handle->oidc->state)
1038  {
1039  GNUNET_STRINGS_urlencode (handle->oidc->state,
1040  strlen (handle->oidc->state),
1041  &tmp);
1043  "&%s=%s",
1045  handle->oidc->state);
1046  GNUNET_free (tmp);
1047  }
1048  if (NULL != handle->oidc->code_challenge)
1049  {
1051  "&%s=%s",
1053  handle->oidc->code_challenge);
1054  }
1055  if (NULL != handle->oidc->nonce)
1056  {
1058  "&%s=%s",
1060  handle->oidc->nonce);
1061  }
1062  if (NULL != handle->oidc->claims)
1063  {
1064  GNUNET_STRINGS_urlencode (handle->oidc->claims,
1065  strlen (handle->oidc->claims),
1066  &tmp);
1068  "&%s=%s",
1070  tmp);
1071  GNUNET_free (tmp);
1072  }
1073  new_redirect = GNUNET_buffer_reap_str (&buf);
1074  resp = GNUNET_REST_create_response ("");
1075  MHD_add_response_header (resp, "Location", new_redirect);
1076  GNUNET_free (login_base_url);
1077  }
1078  else
1079  {
1081  handle->edesc = GNUNET_strdup ("gnunet configuration failed");
1082  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1084  return;
1085  }
1086  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1087  GNUNET_free (new_redirect);
1089 }
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:1850
#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, MHD_HTTP_FOUND, MHD_HTTP_INTERNAL_SERVER_ERROR, 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 1096 of file plugin_rest_openid_connect.c.

1097 {
1098  struct RequestHandle *handle = cls;
1099 
1101  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1103 }

References do_error(), GNUNET_SCHEDULER_add_now(), GNUNET_strdup, handle, MHD_HTTP_INTERNAL_SERVER_ERROR, 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 1111 of file plugin_rest_openid_connect.c.

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

1179 {
1180  struct GNUNET_RECLAIM_AttributeList *merged_list;
1181  struct GNUNET_RECLAIM_AttributeListEntry *le_a;
1182  struct GNUNET_RECLAIM_AttributeListEntry *le_b;
1183  struct GNUNET_RECLAIM_AttributeListEntry *le_m;
1184 
1185  merged_list = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
1186  for (le_a = list_a->list_head; NULL != le_a; le_a = le_a->next)
1187  {
1190  &le_a->attribute->
1191  credential,
1192  le_a->attribute->type,
1193  le_a->attribute->data,
1194  le_a->attribute->data_size);
1195  le_m->attribute->id = le_a->attribute->id;
1196  le_m->attribute->flag = le_a->attribute->flag;
1197  le_m->attribute->credential = le_a->attribute->credential;
1198  GNUNET_CONTAINER_DLL_insert (merged_list->list_head,
1199  merged_list->list_tail,
1200  le_m);
1201  }
1202  le_m = NULL;
1203  for (le_b = list_b->list_head; NULL != le_b; le_b = le_b->next)
1204  {
1205  for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1206  {
1208  &le_b->attribute->id))
1209  break;
1210  }
1211  if (NULL != le_m)
1212  continue;
1215  &le_b->attribute->
1216  credential,
1217  le_b->attribute->type,
1218  le_b->attribute->data,
1219  le_b->attribute->data_size);
1220  le_m->attribute->id = le_b->attribute->id;
1221  le_m->attribute->flag = le_b->attribute->flag;
1222  le_m->attribute->credential = le_b->attribute->credential;
1223  GNUNET_CONTAINER_DLL_insert (merged_list->list_head,
1224  merged_list->list_tail,
1225  le_m);
1226  }
1227  return merged_list;
1228 }
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 1232 of file plugin_rest_openid_connect.c.

1233 {
1234  struct RequestHandle *handle = cls;
1235  struct GNUNET_RECLAIM_AttributeList *merged_list;
1236  struct GNUNET_RECLAIM_AttributeListEntry *le_m;
1237 
1238  handle->cred_it = NULL;
1239  merged_list = attribute_list_merge (handle->attr_idtoken_list,
1240  handle->attr_userinfo_list);
1241  for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1243  "List Attribute in ticket to issue: %s\n",
1244  le_m->attribute->name);
1246  &handle->priv_key,
1247  &handle->oidc->client_pkey,
1248  merged_list,
1250  handle);
1252 }
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:1489
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 1259 of file plugin_rest_openid_connect.c.

1262 {
1263  struct RequestHandle *handle = cls;
1266 
1267  for (ale = handle->credentials->list_head; NULL != ale; ale = ale->next)
1268  {
1270  &cred->id))
1271  continue;
1274  return;
1275  }
1276 
1277  for (le = handle->attr_idtoken_list->list_head; NULL != le; le = le->next)
1278  {
1280  &cred->id))
1281  continue;
1285  cred->type,
1286  cred->data,
1287  cred->data_size);
1288  GNUNET_CONTAINER_DLL_insert (handle->credentials->list_head,
1289  handle->credentials->list_tail,
1290  ale);
1291  }
1293 }
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:1454
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 1297 of file plugin_rest_openid_connect.c.

1298 {
1299  struct RequestHandle *handle = cls;
1300 
1301  handle->attr_it = NULL;
1302  handle->ticket_it = NULL;
1303  if (NULL == handle->attr_idtoken_list->list_head)
1304  {
1306  handle->edesc = GNUNET_strdup ("The requested scope is not available.");
1308  return;
1309  }
1310  handle->credentials = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
1311  handle->cred_it =
1313  &handle->priv_key,
1315  handle,
1317  handle,
1319  handle);
1320 
1321 }
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:1409
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 1325 of file plugin_rest_openid_connect.c.

1328 {
1329  int ret = GNUNET_NO;
1330  json_t *root;
1331  json_error_t error;
1332  json_t *claims_j;
1333  const char *key;
1334  json_t *value;
1335 
1338  attr_name))
1339  return GNUNET_YES;
1340 
1342  if (NULL != handle->oidc->claims)
1343  {
1344  root = json_loads (handle->oidc->claims, JSON_DECODE_ANY, &error);
1345  claims_j = json_object_get (root, claims_parameter);
1346  /* obj is a JSON object */
1347  if (NULL != claims_j)
1348  {
1349  json_object_foreach (claims_j, key, value) {
1350  if (0 != strcmp (attr_name, key))
1351  continue;
1352  ret = GNUNET_YES;
1353  break;
1354  }
1355  }
1356  json_decref (root);
1357  }
1358  return ret;
1359 }
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:958

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

1365 {
1366  return attr_in_claims_request (handle, attr_name, "id_token");
1367 }
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 1371 of file plugin_rest_openid_connect.c.

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

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

1385 {
1386  struct RequestHandle *handle = cls;
1389  {
1392  &attr->credential,
1393  attr->type,
1394  attr->data,
1395  attr->data_size);
1396  le->attribute->id = attr->id;
1397  le->attribute->flag = attr->flag;
1398  le->attribute->credential = attr->credential;
1399  GNUNET_CONTAINER_DLL_insert (handle->attr_idtoken_list->list_head,
1400  handle->attr_idtoken_list->list_tail,
1401  le);
1402  }
1404  {
1407  &attr->credential,
1408  attr->type,
1409  attr->data,
1410  attr->data_size);
1411  le->attribute->id = attr->id;
1412  le->attribute->flag = attr->flag;
1413  le->attribute->credential = attr->credential;
1414  GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
1415  handle->attr_userinfo_list->list_tail,
1416  le);
1417  }
1418 
1420 }
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:1377
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 1427 of file plugin_rest_openid_connect.c.

1428 {
1429  struct RequestHandle *handle = cls;
1430  struct GNUNET_TIME_Absolute current_time;
1431  struct GNUNET_TIME_Absolute *relog_time;
1433  struct GNUNET_IDENTITY_PublicKey ego_pkey;
1434  struct GNUNET_HashCode cache_key;
1435  char *identity_cookie;
1436 
1437  GNUNET_asprintf (&identity_cookie,
1438  "Identity=%s",
1439  handle->oidc->login_identity);
1440  GNUNET_CRYPTO_hash (identity_cookie, strlen (identity_cookie), &cache_key);
1441  GNUNET_free (identity_cookie);
1442  // No login time for identity -> redirect to login
1443  if (GNUNET_YES ==
1445  {
1446  relog_time =
1448  current_time = GNUNET_TIME_absolute_get ();
1449  // 30 min after old login -> redirect to login
1450  if (current_time.abs_value_us <= relog_time->abs_value_us)
1451  {
1452  if (GNUNET_OK !=
1454  ->login_identity,
1455  &pubkey))
1456  {
1458  handle->edesc =
1459  GNUNET_strdup ("The cookie of a login identity is not valid");
1461  return;
1462  }
1463  // iterate over egos and compare their public key
1464  for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
1465  handle->ego_entry = handle->ego_entry->next)
1466  {
1467  GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey);
1468  if (0 == GNUNET_memcmp (&ego_pkey, &pubkey))
1469  {
1470  handle->priv_key =
1471  *GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego);
1472  handle->attr_idtoken_list =
1474  handle->attr_userinfo_list =
1476  handle->attr_it =
1478  &handle->priv_key,
1480  handle,
1482  handle,
1484  handle);
1485  return;
1486  }
1487  }
1489  return;
1490  }
1491  }
1492 }
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:560
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:573
#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:1332
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 1496 of file plugin_rest_openid_connect.c.

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

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

1542 {
1543  struct RequestHandle *handle = cls;
1544  char *tmp;
1545  char *tmp_key_str;
1546  char *pos;
1547  struct GNUNET_IDENTITY_PublicKey redirect_zone;
1548 
1549  handle->gns_op = NULL;
1550  if (0 == rd_count)
1551  {
1553  handle->edesc =
1554  GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1556  return;
1557  }
1558  for (int i = 0; i < rd_count; i++)
1559  {
1560  if (GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT != rd[i].record_type)
1561  continue;
1562  if (0 != strncmp (rd[i].data, handle->oidc->redirect_uri, rd[i].data_size))
1563  continue;
1564  tmp = GNUNET_strndup (rd[i].data, rd[i].data_size);
1565  if (NULL == strstr (tmp, handle->oidc->client_id))
1566  {
1568  "Redirect uri %s does not contain client_id %s\n",
1569  tmp,
1570  handle->oidc->client_id);
1571  }
1572  else
1573  {
1574  pos = strrchr (tmp, (unsigned char) '.');
1575  if (NULL == pos)
1576  {
1578  "Redirect uri %s contains client_id but is malformed\n",
1579  tmp);
1580  GNUNET_free (tmp);
1581  continue;
1582  }
1583  *pos = '\0';
1584  handle->redirect_prefix = GNUNET_strdup (tmp);
1585  tmp_key_str = pos + 1;
1586  pos = strchr (tmp_key_str, (unsigned char) '/');
1587  if (NULL == pos)
1588  {
1590  "Redirect uri %s contains client_id but is malformed\n",
1591  tmp);
1592  GNUNET_free (tmp);
1593  continue;
1594  }
1595  *pos = '\0';
1596  handle->redirect_suffix = GNUNET_strdup (pos + 1);
1597 
1598  GNUNET_STRINGS_string_to_data (tmp_key_str,
1599  strlen (tmp_key_str),
1600  &redirect_zone,
1601  sizeof(redirect_zone));
1602  }
1604  GNUNET_free (tmp);
1605  return;
1606  }
1608  handle->edesc =
1609  GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1611 }
#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.
static unsigned int rd_count
Number of records for currently parsed set.
static struct GNUNET_GNSRECORD_Data rd[50]
The record data under a single label.
#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:788
static void build_redirect(void *cls)
size_t data_size
Number of bytes in data.

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

Referenced by client_redirect().

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

◆ client_redirect()

static void client_redirect ( void *  cls)
static

Initiate redirect back to client.

Definition at line 1618 of file plugin_rest_openid_connect.c.

1619 {
1620  struct RequestHandle *handle = cls;
1621 
1622  /* Lookup client redirect uri to verify request */
1623  handle->gns_op =
1626  &handle->oidc->client_pkey,
1630  handle);
1631 }
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:422
@ 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 1635 of file plugin_rest_openid_connect.c.

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

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

1663 {
1664  struct RequestHandle *handle = cls;
1665  struct GNUNET_HashCode cache_key;
1666 
1667  char *expected_scope;
1668  char delimiter[] = " ";
1669  int number_of_ignored_parameter, iterator;
1670 
1671 
1672  // REQUIRED value: redirect_uri
1673  handle->oidc->redirect_uri =
1675  if (NULL == handle->oidc->redirect_uri)
1676  {
1678  handle->edesc = GNUNET_strdup ("missing parameter redirect_uri");
1680  return;
1681  }
1682 
1683  // REQUIRED value: response_type
1684  handle->oidc->response_type =
1686  if (NULL == handle->oidc->response_type)
1687  {
1689  handle->edesc = GNUNET_strdup ("missing parameter response_type");
1691  return;
1692  }
1693 
1694  // REQUIRED value: scope
1696  if (NULL == handle->oidc->scope)
1697  {
1699  handle->edesc = GNUNET_strdup ("missing parameter scope");
1701  return;
1702  }
1703 
1704  // OPTIONAL value: nonce
1706 
1707  // OPTIONAL value: claims
1709 
1710  // TODO check other values if needed
1711  number_of_ignored_parameter =
1712  sizeof(OIDC_ignored_parameter_array) / sizeof(char *);
1713  for (iterator = 0; iterator < number_of_ignored_parameter; iterator++)
1714  {
1717  &cache_key);
1718  if (GNUNET_YES ==
1720  ->url_param_map,
1721  &cache_key))
1722  {
1724  GNUNET_asprintf (&handle->edesc,
1725  "Server will not handle parameter: %s",
1728  return;
1729  }
1730  }
1731 
1732  // We only support authorization code flows.
1733  if (0 != strcmp (handle->oidc->response_type,
1735  {
1737  handle->edesc = GNUNET_strdup ("The authorization server does not support "
1738  "obtaining this authorization code.");
1740  return;
1741  }
1742 
1743  // Checks if scope contains 'openid'
1744  expected_scope = GNUNET_strdup (handle->oidc->scope);
1745  char *test;
1746  test = strtok (expected_scope, delimiter);
1747  while (NULL != test)
1748  {
1749  if (0 == strcmp (OIDC_EXPECTED_AUTHORIZATION_SCOPE, expected_scope))
1750  break;
1751  test = strtok (NULL, delimiter);
1752  }
1753  if (NULL == test)
1754  {
1756  handle->edesc =
1757  GNUNET_strdup ("The requested scope is invalid, unknown, or malformed.");
1759  GNUNET_free (expected_scope);
1760  return;
1761  }
1762 
1763  GNUNET_free (expected_scope);
1764  if ((NULL == handle->oidc->login_identity) &&
1765  (GNUNET_NO == handle->oidc->user_cancelled))
1767  else
1769 }
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 1776 of file plugin_rest_openid_connect.c.

1777 {
1778  struct RequestHandle *handle = cls;
1780 
1781  if (GNUNET_OK !=
1783  {
1784  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Skipping non key %s\n", value);
1785  return;
1786  }
1787  if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1788  handle->tld = GNUNET_strdup (option + 1);
1789 }
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 1800 of file plugin_rest_openid_connect.c.

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

1877 {
1878  struct MHD_Response *resp = GNUNET_REST_create_response ("");
1879  struct RequestHandle *handle = cls;
1880  struct GNUNET_HashCode cache_key;
1881  struct GNUNET_TIME_Absolute *current_time;
1882  struct GNUNET_TIME_Absolute *last_time;
1883  char *cookie;
1884  char *header_val;
1885  json_t *root;
1886  json_error_t error;
1887  json_t *identity;
1888  char term_data[handle->rest_handle->data_size + 1];
1889 
1890  term_data[handle->rest_handle->data_size] = '\0';
1891  GNUNET_memcpy (term_data,
1892  handle->rest_handle->data,
1893  handle->rest_handle->data_size);
1894  root = json_loads (term_data, JSON_DECODE_ANY, &error);
1895  identity = json_object_get (root, "identity");
1896  if (! json_is_string (identity))
1897  {
1899  "Error parsing json string from %s\n",
1900  term_data);
1901  handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
1902  json_decref (root);
1904  return;
1905  }
1906  GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity));
1907  GNUNET_asprintf (&header_val,
1908  "%s;Max-Age=%d",
1909  cookie,
1911  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1912  "Set-Cookie", header_val));
1913  GNUNET_assert (MHD_NO !=
1914  MHD_add_response_header (resp,
1915  "Access-Control-Allow-Methods",
1916  "POST"));
1917  GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key);
1918 
1919  if (0 != strcmp (json_string_value (identity), "Denied"))
1920  {
1921  current_time = GNUNET_new (struct GNUNET_TIME_Absolute);
1922  *current_time = GNUNET_TIME_relative_to_absolute (
1925  last_time =
1927  GNUNET_free (last_time);
1929  &cache_key,
1930  current_time,
1932  }
1933  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1934  GNUNET_free (cookie);
1935  GNUNET_free (header_val);
1936  json_decref (root);
1938 }
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:169
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:316
#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, MHD_HTTP_BAD_REQUEST, MHD_HTTP_OK, 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 1942 of file plugin_rest_openid_connect.c.

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

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

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

2045 {
2046  char *expected_pass;
2047  char *received_cid;
2048  char *received_cpw;
2049  char *pkce_cv;
2050 
2052  &received_cid,
2053  &received_cpw))
2054  {
2056  "Received client credentials in HTTP AuthZ header\n");
2057  }
2059  &received_cid,
2060  &received_cpw))
2061  {
2063  "Received client credentials in POST body\n");
2064  }
2065  else
2066  {
2069  if (NULL == pkce_cv)
2070  {
2072  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2073  return GNUNET_SYSERR;
2074  }
2075  handle->public_client = GNUNET_YES;
2076  GNUNET_free (pkce_cv);
2078  GNUNET_STRINGS_string_to_data (received_cid,
2079  strlen (received_cid),
2080  cid,
2081  sizeof(struct GNUNET_IDENTITY_PublicKey));
2082  GNUNET_free (received_cid);
2083  return GNUNET_OK;
2084 
2085  }
2086 
2087  // check client password
2089  "reclaim-rest-plugin",
2090  "OIDC_CLIENT_HMAC_SECRET",
2091  &expected_pass))
2092  {
2093  if (0 != strcmp (expected_pass, received_cpw))
2094  {
2095  GNUNET_free (expected_pass);
2097  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2098  GNUNET_free (received_cpw);
2099  GNUNET_free (received_cid);
2100  return GNUNET_SYSERR;
2101  }
2102  GNUNET_free (expected_pass);
2103  }
2104  else
2105  {
2106  GNUNET_free (received_cpw);
2107  GNUNET_free (received_cid);
2109  handle->edesc = GNUNET_strdup ("gnunet configuration failed");
2110  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2111  return GNUNET_SYSERR;
2112  }
2113  // check client_id
2114  for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
2115  handle->ego_entry = handle->ego_entry->next)
2116  {
2117  if (0 == strcmp (handle->ego_entry->keystring, received_cid))
2118  break;
2119  }
2120  if (NULL == handle->ego_entry)
2121  {
2122  GNUNET_free (received_cpw);
2123  GNUNET_free (received_cid);
2125  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2126  return GNUNET_SYSERR;
2127  }
2128  GNUNET_STRINGS_string_to_data (received_cid,
2129  strlen (received_cid),
2130  cid,
2131  sizeof(struct GNUNET_IDENTITY_PublicKey));
2132 
2133  GNUNET_free (received_cpw);
2134  GNUNET_free (received_cid);
2135  return GNUNET_OK;
2136 }
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, MHD_HTTP_INTERNAL_SERVER_ERROR, MHD_HTTP_UNAUTHORIZED, 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 2140 of file plugin_rest_openid_connect.c.

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

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

2168 {
2169  struct RequestHandle *handle = cls;
2170  const struct EgoEntry *ego_entry = NULL;
2171  struct GNUNET_TIME_Relative expiration_time;
2172  struct GNUNET_RECLAIM_AttributeList *cl = NULL;
2173  struct GNUNET_RECLAIM_PresentationList *pl = NULL;
2175  struct GNUNET_IDENTITY_PublicKey cid;
2176  struct GNUNET_HashCode cache_key;
2177  struct MHD_Response *resp = NULL;
2178  char *grant_type = NULL;
2179  char *code = NULL;
2180  char *json_response = NULL;
2181  char *id_token = NULL;
2182  char *access_token = NULL;
2183  char *jwa = NULL;
2184  char *jwt_secret = NULL;
2185  char *nonce = NULL;
2186  char *code_verifier = NULL;
2187  json_t *oidc_jwk = NULL;
2188  char *oidc_jwk_path = NULL;
2189  char *oidc_directory = NULL;
2190  char *tmp_at = NULL;
2191 
2192  /*
2193  * Check Authorization
2194  */
2195  if (GNUNET_SYSERR == check_authorization (handle, &cid))
2196  {
2198  "OIDC authorization for token endpoint failed\n");
2200  return;
2201  }
2202 
2203  /*
2204  * Check parameter
2205  */
2206 
2207  // TODO Do not allow multiple equal parameter names
2208  // REQUIRED grant_type
2210  strlen (OIDC_GRANT_TYPE_KEY),
2211  &cache_key);
2213  if (NULL == grant_type)
2214  {
2216  handle->edesc = GNUNET_strdup ("missing parameter grant_type");
2217  handle->response_code = MHD_HTTP_BAD_REQUEST;
2219  return;
2220  }
2221 
2222  // Check parameter grant_type == "authorization_code"
2223  if (0 != strcmp (OIDC_GRANT_TYPE_VALUE, grant_type))
2224  {
2226  handle->response_code = MHD_HTTP_BAD_REQUEST;
2227  GNUNET_free (grant_type);
2229  return;
2230  }
2231  GNUNET_free (grant_type);
2232  // REQUIRED code
2234  if (NULL == code)
2235  {
2237  handle->edesc = GNUNET_strdup ("missing parameter code");
2238  handle->response_code = MHD_HTTP_BAD_REQUEST;
2240  return;
2241  }
2242  ego_entry = find_ego (handle, &cid);
2243  if (NULL == ego_entry)
2244  {
2246  handle->edesc = GNUNET_strdup ("Unknown client");
2247  handle->response_code = MHD_HTTP_BAD_REQUEST;
2248  GNUNET_free (code);
2250  return;
2251  }
2252 
2253  // REQUIRED code verifier
2255  if (NULL == code_verifier)
2256  {
2258  "OAuth authorization request does not contain PKCE parameters!\n");
2259 
2260  }
2261 
2262  // decode code
2263  if (GNUNET_OK != OIDC_parse_authz_code (&cid, code, code_verifier, &ticket,
2264  &cl, &pl, &nonce,
2266  {
2268  handle->edesc = GNUNET_strdup ("invalid code");
2269  handle->response_code = MHD_HTTP_BAD_REQUEST;
2270  GNUNET_free (code);
2271  if (NULL != code_verifier)
2272  GNUNET_free (code_verifier);
2274  return;
2275  }
2276  if (NULL != code_verifier)
2277  GNUNET_free (code_verifier);
2278 
2279  // create jwt
2281  "reclaim-rest-plugin",
2282  "expiration_time",
2283  &expiration_time))
2284  {
2286  handle->edesc = GNUNET_strdup ("gnunet configuration failed");
2287  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2288  GNUNET_free (code);
2289  if (NULL != nonce)
2290  GNUNET_free (nonce);
2294  return;
2295  }
2296 
2297  // Check if HMAC or RSA should be used
2299  "reclaim-rest-plugin",
2300  "oidc_json_web_algorithm",
2301  &jwa))
2302  {
2304  "Could not read OIDC JSON Web Algorithm config attribute."
2305  "Defaulting to RS256.");
2306  jwa = JWT_ALG_VALUE_RSA;
2307  }
2308 
2309  if ( ! strcmp (jwa, JWT_ALG_VALUE_RSA))
2310  {
2311  // Replace for now
2312  oidc_jwk_path = get_oidc_jwk_path (cls);
2313  oidc_jwk = read_jwk_from_file (oidc_jwk_path);
2314 
2315  // Check if secret JWK exists
2316  if (! oidc_jwk)
2317  {
2318  // Generate and save a new key
2319  oidc_jwk = generate_jwk ();
2320  oidc_directory = get_oidc_dir_path (cls);
2321 
2322  // Create new oidc directory
2323  if (GNUNET_OK != GNUNET_DISK_directory_create (oidc_directory))
2324  {
2326  ("Failed to create directory `%s' for storing oidc data\n"),
2327  oidc_directory);
2328  }
2329  else
2330  {
2331  write_jwk_to_file (oidc_jwk_path, oidc_jwk);
2332  }
2333  }
2334 
2335  // Generate oidc token
2337  &ticket.identity,
2338  cl,
2339  pl,
2340  &expiration_time,
2341  (NULL != nonce) ? nonce : NULL,
2342  oidc_jwk);
2343  }
2344  else if ( ! strcmp (jwa, JWT_ALG_VALUE_HMAC))
2345  {
2346  // TODO OPTIONAL acr,amr,azp
2348  "reclaim-rest-plugin",
2349  "jwt_secret",
2350  &jwt_secret))
2351  {
2353  handle->edesc = GNUNET_strdup ("No signing secret configured!");
2354  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2355  GNUNET_free (code);
2358  if (NULL != nonce)
2359  GNUNET_free (nonce);
2361  return;
2362  }
2363 
2365  &ticket.identity,
2366  cl,
2367  pl,
2368  &expiration_time,
2369  (NULL != nonce) ? nonce : NULL,
2370  jwt_secret);
2371 
2372  GNUNET_free (jwt_secret);
2373  }
2374  else
2375  {
2376  // TODO: OPTION NOT FOUND ERROR
2377  }
2378 
2379  if (NULL != nonce)
2380  GNUNET_free (nonce);
2381  access_token = OIDC_access_token_new (&ticket);
2386  GNUNET_CRYPTO_hash (access_token,
2387  strlen (access_token),
2388  &cache_key);
2400  &cache_key);
2402  &cache_key,
2403  code,
2405  /* If there was a previous code in there, free the old value */
2406  if (NULL != tmp_at)
2407  {
2409  "OIDC access token already issued. Cleanup.\n");
2410  GNUNET_free (tmp_at);
2411  }
2412 
2413  OIDC_build_token_response (access_token,
2414  id_token,
2415  &expiration_time,
2416  &json_response);
2417 
2418  resp = GNUNET_REST_create_response (json_response);
2419  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2420  "Cache-Control",
2421  "no-store"));
2422  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2423  "Pragma", "no-cache"));
2424  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2425  "Content-Type",
2426  "application/json"));
2427  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2430  GNUNET_free (access_token);
2431  GNUNET_free (json_response);
2432  GNUNET_free (id_token);
2434 }
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:489
char * OIDC_access_token_new(const struct GNUNET_RECLAIM_Ticket *ticket)
Generate a new access token.
Definition: oidc_helper.c:916
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:767
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:888
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:427
#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, MHD_HTTP_BAD_REQUEST, MHD_HTTP_INTERNAL_SERVER_ERROR, MHD_HTTP_OK, 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 2441 of file plugin_rest_openid_connect.c.

2445 {
2446  struct RequestHandle *handle = cls;
2449  struct MHD_Response *resp;
2450  struct GNUNET_HashCode cache_key;
2451  char *result_str;
2452  char *cached_code;
2453 
2454  if (NULL != handle->consume_timeout_op)
2455  GNUNET_SCHEDULER_cancel (handle->consume_timeout_op);
2456  handle->consume_timeout_op = NULL;
2457  handle->idp_op = NULL;
2458 
2462  GNUNET_CRYPTO_hash (handle->access_token,
2463  strlen (handle->access_token),
2464  &cache_key);
2466  &cache_key);
2467  if (NULL != cached_code)
2468  {
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_assert, 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(), GNUNET_YES, handle, GNUNET_RECLAIM_Attribute::id, identity, MHD_HTTP_OK, 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  }
2567  &cache_key,
2568  cached_code));
2569 
2570  // decode code
2571  if (GNUNET_OK != OIDC_parse_authz_code (&handle->ticket.audience,
2572  cached_code, NULL, &ticket,
2573  &cl, &pl, &nonce,
2575  {
2577  handle->edesc = GNUNET_strdup ("invalid code");
2578  handle->response_code = MHD_HTTP_BAD_REQUEST;
2579  GNUNET_free (cached_code);
2580  if (NULL != nonce)
2581  GNUNET_free (nonce);
2583  return;
2584  }
2585 
2586  GNUNET_free (cached_code);
2587 
2588  result_str = OIDC_generate_userinfo (&handle->ticket.identity,
2589  cl,
2590  pl);
2591  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2592  resp = GNUNET_REST_create_response (result_str);
2593  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2594  GNUNET_free (result_str);
2595  GNUNET_free (nonce);
2599 }
@ 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_assert, 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, GNUNET_YES, handle, MHD_HTTP_BAD_REQUEST, MHD_HTTP_OK, MHD_HTTP_UNAUTHORIZED, 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 2610 of file plugin_rest_openid_connect.c.

2613 {
2614  // TODO expiration time
2615  struct RequestHandle *handle = cls;
2616  struct GNUNET_RECLAIM_Ticket *ticket;
2617  char delimiter[] = " ";
2618  struct GNUNET_HashCode cache_key;
2619  char *authorization;
2620  char *authorization_type;
2621  char *authorization_access_token;
2622  const struct EgoEntry *aud_ego;
2623  const struct GNUNET_IDENTITY_PrivateKey *privkey;
2624 
2625  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting userinfo\n");
2628  &cache_key);
2630  ->header_param_map,
2631  &cache_key))
2632  {
2634  handle->edesc = GNUNET_strdup ("No Access Token");
2635  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2637  return;
2638  }
2639  authorization =
2640  GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
2641  &cache_key);
2642 
2643  // split header in "Bearer" and access_token
2644  authorization = GNUNET_strdup (authorization);
2645  authorization_type = strtok (authorization, delimiter);
2646  if ((NULL == authorization_type) ||
2647  (0 != strcmp ("Bearer", authorization_type)))
2648  {
2650  handle->edesc = GNUNET_strdup ("No Access Token");
2651  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2653  GNUNET_free (authorization);
2654  return;
2655  }
2656  authorization_access_token = strtok (NULL, delimiter);
2657  if (NULL == authorization_access_token)
2658  {
2660  handle->edesc = GNUNET_strdup ("Access token missing");
2661  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2663  GNUNET_free (authorization);
2664  return;
2665  }
2666 
2667  if (GNUNET_OK != OIDC_access_token_parse (authorization_access_token,
2668  &ticket))
2669  {
2671  handle->edesc = GNUNET_strdup ("The access token is invalid");
2672  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2674  GNUNET_free (authorization);
2675  return;
2676 
2677  }
2678  GNUNET_assert (NULL != ticket);
2679  handle->ticket = *ticket;
2680  GNUNET_free (ticket);
2681  aud_ego = find_ego (handle, &handle->ticket.audience);
2682  if (NULL == aud_ego)
2683  {
2685  handle->edesc = GNUNET_strdup ("The access token expired");
2686  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2688  GNUNET_free (authorization);
2689  return;
2690  }
2691  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Consuming ticket\n");
2692  privkey = GNUNET_IDENTITY_ego_get_private_key (aud_ego->ego);
2693  handle->attr_userinfo_list =
2695  handle->presentations =
2697 
2698  /* If the consume takes too long, we use values from the cache */
2699  handle->access_token = GNUNET_strdup (authorization_access_token);
2700  handle->consume_timeout_op = GNUNET_SCHEDULER_add_delayed (consume_timeout,
2701  &consume_fail,
2702  handle);
2704  privkey,
2705  &handle->ticket,
2706  &consume_ticket,
2707  handle);
2708  GNUNET_free (authorization);
2709 }
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:1549
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:1272
int OIDC_access_token_parse(const char *token, struct GNUNET_RECLAIM_Ticket **ticket)
Parse an access token.
Definition: oidc_helper.c:931
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, MHD_HTTP_UNAUTHORIZED, 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 2719 of file plugin_rest_openid_connect.c.

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

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, MHD_HTTP_OK, 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 2799 of file plugin_rest_openid_connect.c.

2803 {
2804  struct EgoEntry *ego_entry;
2806 
2807  if (NULL == ego)
2808  {
2810  return;
2811  }
2812  if (ID_REST_STATE_INIT == state)
2813 
2814  {
2815  ego_entry = GNUNET_new (struct EgoEntry);
2818  ego_entry->ego = ego;
2819  ego_entry->identifier = GNUNET_strdup (identifier);
2821  ego_tail,
2822  ego_entry);
2823  return;
2824  }
2825  /* Ego renamed or added */
2826  if (identifier != NULL)
2827  {
2828  for (ego_entry = ego_head; NULL != ego_entry;
2829  ego_entry = ego_entry->next)
2830  {
2831  if (ego_entry->ego == ego)
2832  {
2833  /* Rename */
2834  GNUNET_free (ego_entry->identifier);
2835  ego_entry->identifier = GNUNET_strdup (identifier);
2836  break;
2837  }
2838  }
2839  if (NULL == ego_entry)
2840  {
2841  /* Add */
2842  ego_entry = GNUNET_new (struct EgoEntry);
2845  ego_entry->ego = ego;
2846  ego_entry->identifier = GNUNET_strdup (identifier);
2848  ego_tail,
2849  ego_entry);
2850  }
2851  }
2852  else
2853  {
2854  /* Delete */
2855  for (ego_entry = ego_head; NULL != ego_entry;
2856  ego_entry = ego_entry->next)
2857  {
2858  if (ego_entry->ego == ego)
2859  break;
2860  }
2861  if (NULL == ego_entry)
2862  return; /* Not found */
2863 
2865  ego_tail,
2866  ego_entry);
2867  GNUNET_free (ego_entry->identifier);
2868  GNUNET_free (ego_entry->keystring);
2869  GNUNET_free (ego_entry);
2870  return;
2871  }
2872 }
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 2876 of file plugin_rest_openid_connect.c.

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

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

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

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

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

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

3004 {
3005  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
3007  static const struct GNUNET_REST_RequestHandler handlers[] =
3008  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint },
3009  { MHD_HTTP_METHOD_POST,
3011  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont },
3012  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
3013  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
3014  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
3015  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_JWKS, &jwks_endpoint },
3016  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_OIDC_CONFIG,
3018  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC_CONFIG,
3019  &oidc_config_cors },
3020  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont },
3022 
3023  handle->oidc = GNUNET_new (struct OIDC_Variables);
3024  if (NULL == OIDC_cookie_jar_map)
3026  GNUNET_NO);
3027  if (NULL == oidc_code_cache)
3029  GNUNET_NO);
3030 
3031  handle->response_code = 0;
3033  handle->proc_cls = proc_cls;
3034  handle->proc = proc;
3035  handle->rest_handle = rest_handle;
3036  handle->url = GNUNET_strdup (rest_handle->url);
3037  handle->timeout_task =
3040  requests_tail,
3041  handle);
3042  if (handle->url[strlen (handle->url) - 1] == '/')
3043  handle->url[strlen (handle->url) - 1] = '\0';
3044  if (GNUNET_NO ==
3045  GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
3046  return GNUNET_NO;
3047 
3048  return GNUNET_YES;
3049 }
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:64
#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 3059 of file plugin_rest_openid_connect.c.

3060 {
3061  static struct Plugin plugin;
3062  struct GNUNET_REST_Plugin *api;
3063 
3064  cfg = cls;
3065  if (NULL != plugin.cfg)
3066  return NULL; /* can only initialize once! */
3067  memset (&plugin, 0, sizeof(struct Plugin));
3068  plugin.cfg = cfg;
3069  api = GNUNET_new (struct GNUNET_REST_Plugin);
3070  api->cls = &plugin;
3077  "reclaim-rest-plugin",
3078  "OIDC_USERINFO_CONSUME_TIMEOUT",
3079  &consume_timeout))
3080  {
3082  }
3083 
3084 
3087  "%s, %s, %s, %s, %s",
3088  MHD_HTTP_METHOD_GET,
3089  MHD_HTTP_METHOD_POST,
3090  MHD_HTTP_METHOD_PUT,
3091  MHD_HTTP_METHOD_DELETE,
3092  MHD_HTTP_METHOD_OPTIONS);
3093 
3095  _ ("OpenID Connect REST API initialized\n"));
3096  return api;
3097 }
struct TestcasePlugin * 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:531
struct GNUNET_RECLAIM_Handle * GNUNET_RECLAIM_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the re:claimID service.
Definition: reclaim_api.c:1111
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
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

References _, allow_methods, 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 3101 of file plugin_rest_openid_connect.c.

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

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

3116 {
3117  struct GNUNET_REST_Plugin *api = cls;
3118  struct Plugin *plugin = api->cls;
3119  struct EgoEntry *ego_entry;
3120 
3121  plugin->cfg = NULL;
3122  while (NULL != requests_head)
3124  if (NULL != OIDC_cookie_jar_map)
3125  {
3127  &cleanup_hashmap,
3128  NULL);
3130  }
3131  if (NULL != oidc_code_cache)
3132  {
3134  &cleanup_hashmap,
3135  NULL);
3137  }
3138 
3140  if (NULL != gns_handle)
3142  if (NULL != identity_handle)
3144  if (NULL != idp)
3146  while (NULL != (ego_entry = ego_head))
3147  {
3149  ego_tail,
3150  ego_entry);
3151  GNUNET_free (ego_entry->identifier);
3152  GNUNET_free (ego_entry->keystring);
3153  GNUNET_free (ego_entry);
3154  }
3155  GNUNET_free (api);
3157  "OpenID Connect REST plugin is finished\n");
3158  return NULL;
3159 }
void GNUNET_GNS_disconnect(struct GNUNET_GNS_Handle *handle)
Shutdown connection with the GNS service.
Definition: gns_api.c:290
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
void GNUNET_IDENTITY_disconnect(struct GNUNET_IDENTITY_Handle *h)
Disconnect from identity service.
Definition: identity_api.c:757
void GNUNET_RECLAIM_disconnect(struct GNUNET_RECLAIM_Handle *h)
Disconnect from identity provider service.
Definition: reclaim_api.c:1143
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, 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 250 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 261 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 266 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 271 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

◆ ego_tail

struct EgoEntry* ego_tail
static

◆ state

int state
static

The processing state.

Definition at line 291 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 296 of file plugin_rest_openid_connect.c.

Referenced by libgnunet_plugin_rest_openid_connect_done(), and libgnunet_plugin_rest_openid_connect_init().

◆ gns_handle

◆ idp

◆ consume_timeout

struct GNUNET_TIME_Relative consume_timeout
static

Timeout for consume call on userinfo.

Definition at line 306 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 324 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 593 of file plugin_rest_openid_connect.c.

Referenced by cleanup_handle().