diff options
Diffstat (limited to 'src/reclaim/plugin_rest_openid_connect.c')
-rw-r--r-- | src/reclaim/plugin_rest_openid_connect.c | 823 |
1 files changed, 467 insertions, 356 deletions
diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c index 36ae937c1..06e1b0061 100644 --- a/src/reclaim/plugin_rest_openid_connect.c +++ b/src/reclaim/plugin_rest_openid_connect.c | |||
@@ -28,6 +28,8 @@ | |||
28 | #include <inttypes.h> | 28 | #include <inttypes.h> |
29 | #include <jansson.h> | 29 | #include <jansson.h> |
30 | 30 | ||
31 | #include "gnunet_buffer_lib.h" | ||
32 | #include "gnunet_strings_lib.h" | ||
31 | #include "gnunet_gns_service.h" | 33 | #include "gnunet_gns_service.h" |
32 | #include "gnunet_gnsrecord_lib.h" | 34 | #include "gnunet_gnsrecord_lib.h" |
33 | #include "gnunet_identity_service.h" | 35 | #include "gnunet_identity_service.h" |
@@ -39,12 +41,18 @@ | |||
39 | #include "gnunet_signatures.h" | 41 | #include "gnunet_signatures.h" |
40 | #include "microhttpd.h" | 42 | #include "microhttpd.h" |
41 | #include "oidc_helper.h" | 43 | #include "oidc_helper.h" |
44 | |||
42 | /** | 45 | /** |
43 | * REST root namespace | 46 | * REST root namespace |
44 | */ | 47 | */ |
45 | #define GNUNET_REST_API_NS_OIDC "/openid" | 48 | #define GNUNET_REST_API_NS_OIDC "/openid" |
46 | 49 | ||
47 | /** | 50 | /** |
51 | * OIDC config | ||
52 | */ | ||
53 | #define GNUNET_REST_API_NS_OIDC_CONFIG "/.well-known/openid-configuration" | ||
54 | |||
55 | /** | ||
48 | * Authorize endpoint | 56 | * Authorize endpoint |
49 | */ | 57 | */ |
50 | #define GNUNET_REST_API_NS_AUTHORIZE "/openid/authorize" | 58 | #define GNUNET_REST_API_NS_AUTHORIZE "/openid/authorize" |
@@ -237,12 +245,6 @@ static char *OIDC_ignored_parameter_array[] = { "display", | |||
237 | struct GNUNET_CONTAINER_MultiHashMap *OIDC_cookie_jar_map; | 245 | struct GNUNET_CONTAINER_MultiHashMap *OIDC_cookie_jar_map; |
238 | 246 | ||
239 | /** | 247 | /** |
240 | * Hash map that links the issued access token to the corresponding ticket and | ||
241 | * ego | ||
242 | */ | ||
243 | struct GNUNET_CONTAINER_MultiHashMap *OIDC_access_token_map; | ||
244 | |||
245 | /** | ||
246 | * The configuration handle | 248 | * The configuration handle |
247 | */ | 249 | */ |
248 | const struct GNUNET_CONFIGURATION_Handle *cfg; | 250 | const struct GNUNET_CONFIGURATION_Handle *cfg; |
@@ -253,6 +255,36 @@ const struct GNUNET_CONFIGURATION_Handle *cfg; | |||
253 | static char *allow_methods; | 255 | static char *allow_methods; |
254 | 256 | ||
255 | /** | 257 | /** |
258 | * Ego list | ||
259 | */ | ||
260 | static struct EgoEntry *ego_head; | ||
261 | |||
262 | /** | ||
263 | * Ego list | ||
264 | */ | ||
265 | static struct EgoEntry *ego_tail; | ||
266 | |||
267 | /** | ||
268 | * The processing state | ||
269 | */ | ||
270 | static int state; | ||
271 | |||
272 | /** | ||
273 | * Handle to Identity service. | ||
274 | */ | ||
275 | static struct GNUNET_IDENTITY_Handle *identity_handle; | ||
276 | |||
277 | /** | ||
278 | * GNS handle | ||
279 | */ | ||
280 | static struct GNUNET_GNS_Handle *gns_handle; | ||
281 | |||
282 | /** | ||
283 | * Identity Provider | ||
284 | */ | ||
285 | static struct GNUNET_RECLAIM_Handle *idp; | ||
286 | |||
287 | /** | ||
256 | * @brief struct returned by the initialization function of the plugin | 288 | * @brief struct returned by the initialization function of the plugin |
257 | */ | 289 | */ |
258 | struct Plugin | 290 | struct Plugin |
@@ -325,10 +357,6 @@ struct OIDC_Variables | |||
325 | */ | 357 | */ |
326 | char *code_verifier; | 358 | char *code_verifier; |
327 | 359 | ||
328 | /** | ||
329 | * The response JSON | ||
330 | */ | ||
331 | json_t *response; | ||
332 | }; | 360 | }; |
333 | 361 | ||
334 | /** | 362 | /** |
@@ -365,15 +393,6 @@ struct EgoEntry | |||
365 | 393 | ||
366 | struct RequestHandle | 394 | struct RequestHandle |
367 | { | 395 | { |
368 | /** | ||
369 | * Ego list | ||
370 | */ | ||
371 | struct EgoEntry *ego_head; | ||
372 | |||
373 | /** | ||
374 | * Ego list | ||
375 | */ | ||
376 | struct EgoEntry *ego_tail; | ||
377 | 396 | ||
378 | /** | 397 | /** |
379 | * Selected ego | 398 | * Selected ego |
@@ -391,39 +410,14 @@ struct RequestHandle | |||
391 | struct OIDC_Variables *oidc; | 410 | struct OIDC_Variables *oidc; |
392 | 411 | ||
393 | /** | 412 | /** |
394 | * The processing state | ||
395 | */ | ||
396 | int state; | ||
397 | |||
398 | /** | ||
399 | * Handle to Identity service. | ||
400 | */ | ||
401 | struct GNUNET_IDENTITY_Handle *identity_handle; | ||
402 | |||
403 | /** | ||
404 | * Rest connection | ||
405 | */ | ||
406 | struct GNUNET_REST_RequestHandle *rest_handle; | ||
407 | |||
408 | /** | ||
409 | * GNS handle | ||
410 | */ | ||
411 | struct GNUNET_GNS_Handle *gns_handle; | ||
412 | |||
413 | /** | ||
414 | * GNS lookup op | 413 | * GNS lookup op |
415 | */ | 414 | */ |
416 | struct GNUNET_GNS_LookupRequest *gns_op; | 415 | struct GNUNET_GNS_LookupRequest *gns_op; |
417 | 416 | ||
418 | /** | 417 | /** |
419 | * Handle to NAMESTORE | 418 | * Rest connection |
420 | */ | ||
421 | struct GNUNET_NAMESTORE_Handle *namestore_handle; | ||
422 | |||
423 | /** | ||
424 | * Iterator for NAMESTORE | ||
425 | */ | 419 | */ |
426 | struct GNUNET_NAMESTORE_ZoneIterator *namestore_handle_it; | 420 | struct GNUNET_REST_RequestHandle *rest_handle; |
427 | 421 | ||
428 | /** | 422 | /** |
429 | * Attribute claim list for id_token | 423 | * Attribute claim list for id_token |
@@ -446,10 +440,6 @@ struct RequestHandle | |||
446 | */ | 440 | */ |
447 | struct GNUNET_IDENTITY_Operation *op; | 441 | struct GNUNET_IDENTITY_Operation *op; |
448 | 442 | ||
449 | /** | ||
450 | * Identity Provider | ||
451 | */ | ||
452 | struct GNUNET_RECLAIM_Handle *idp; | ||
453 | 443 | ||
454 | /** | 444 | /** |
455 | * Idp Operation | 445 | * Idp Operation |
@@ -531,8 +521,14 @@ struct RequestHandle | |||
531 | * Reponse code | 521 | * Reponse code |
532 | */ | 522 | */ |
533 | int response_code; | 523 | int response_code; |
524 | |||
525 | /** | ||
526 | * Public client | ||
527 | */ | ||
528 | int public_client; | ||
534 | }; | 529 | }; |
535 | 530 | ||
531 | |||
536 | /** | 532 | /** |
537 | * Cleanup lookup handle | 533 | * Cleanup lookup handle |
538 | * @param handle Handle to clean up | 534 | * @param handle Handle to clean up |
@@ -540,13 +536,10 @@ struct RequestHandle | |||
540 | static void | 536 | static void |
541 | cleanup_handle (struct RequestHandle *handle) | 537 | cleanup_handle (struct RequestHandle *handle) |
542 | { | 538 | { |
543 | struct EgoEntry *ego_entry; | ||
544 | 539 | ||
545 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); | 540 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); |
546 | if (NULL != handle->timeout_task) | 541 | if (NULL != handle->timeout_task) |
547 | GNUNET_SCHEDULER_cancel (handle->timeout_task); | 542 | GNUNET_SCHEDULER_cancel (handle->timeout_task); |
548 | if (NULL != handle->identity_handle) | ||
549 | GNUNET_IDENTITY_disconnect (handle->identity_handle); | ||
550 | if (NULL != handle->attr_it) | 543 | if (NULL != handle->attr_it) |
551 | GNUNET_RECLAIM_get_attributes_stop (handle->attr_it); | 544 | GNUNET_RECLAIM_get_attributes_stop (handle->attr_it); |
552 | if (NULL != handle->attest_it) | 545 | if (NULL != handle->attest_it) |
@@ -555,8 +548,6 @@ cleanup_handle (struct RequestHandle *handle) | |||
555 | GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it); | 548 | GNUNET_RECLAIM_ticket_iteration_stop (handle->ticket_it); |
556 | if (NULL != handle->idp_op) | 549 | if (NULL != handle->idp_op) |
557 | GNUNET_RECLAIM_cancel (handle->idp_op); | 550 | GNUNET_RECLAIM_cancel (handle->idp_op); |
558 | if (NULL != handle->idp) | ||
559 | GNUNET_RECLAIM_disconnect (handle->idp); | ||
560 | GNUNET_free (handle->url); | 551 | GNUNET_free (handle->url); |
561 | GNUNET_free (handle->tld); | 552 | GNUNET_free (handle->tld); |
562 | GNUNET_free (handle->redirect_prefix); | 553 | GNUNET_free (handle->redirect_prefix); |
@@ -565,11 +556,6 @@ cleanup_handle (struct RequestHandle *handle) | |||
565 | GNUNET_free (handle->edesc); | 556 | GNUNET_free (handle->edesc); |
566 | if (NULL != handle->gns_op) | 557 | if (NULL != handle->gns_op) |
567 | GNUNET_GNS_lookup_cancel (handle->gns_op); | 558 | GNUNET_GNS_lookup_cancel (handle->gns_op); |
568 | if (NULL != handle->gns_handle) | ||
569 | GNUNET_GNS_disconnect (handle->gns_handle); | ||
570 | |||
571 | if (NULL != handle->namestore_handle) | ||
572 | GNUNET_NAMESTORE_disconnect (handle->namestore_handle); | ||
573 | if (NULL != handle->oidc) | 559 | if (NULL != handle->oidc) |
574 | { | 560 | { |
575 | GNUNET_free (handle->oidc->client_id); | 561 | GNUNET_free (handle->oidc->client_id); |
@@ -579,7 +565,6 @@ cleanup_handle (struct RequestHandle *handle) | |||
579 | GNUNET_free (handle->oidc->response_type); | 565 | GNUNET_free (handle->oidc->response_type); |
580 | GNUNET_free (handle->oidc->scope); | 566 | GNUNET_free (handle->oidc->scope); |
581 | GNUNET_free (handle->oidc->state); | 567 | GNUNET_free (handle->oidc->state); |
582 | json_decref (handle->oidc->response); | ||
583 | GNUNET_free (handle->oidc); | 568 | GNUNET_free (handle->oidc); |
584 | } | 569 | } |
585 | if (NULL!=handle->attr_idtoken_list) | 570 | if (NULL!=handle->attr_idtoken_list) |
@@ -589,15 +574,6 @@ cleanup_handle (struct RequestHandle *handle) | |||
589 | if (NULL!=handle->attests_list) | 574 | if (NULL!=handle->attests_list) |
590 | GNUNET_RECLAIM_attestation_list_destroy (handle->attests_list); | 575 | GNUNET_RECLAIM_attestation_list_destroy (handle->attests_list); |
591 | 576 | ||
592 | while (NULL != (ego_entry = handle->ego_head)) | ||
593 | { | ||
594 | GNUNET_CONTAINER_DLL_remove (handle->ego_head, | ||
595 | handle->ego_tail, | ||
596 | ego_entry); | ||
597 | GNUNET_free (ego_entry->identifier); | ||
598 | GNUNET_free (ego_entry->keystring); | ||
599 | GNUNET_free (ego_entry); | ||
600 | } | ||
601 | GNUNET_free (handle); | 577 | GNUNET_free (handle); |
602 | } | 578 | } |
603 | 579 | ||
@@ -655,6 +631,8 @@ do_userinfo_error (void *cls) | |||
655 | struct MHD_Response *resp; | 631 | struct MHD_Response *resp; |
656 | char *error; | 632 | char *error; |
657 | 633 | ||
634 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
635 | "Error: %s\n", handle->edesc); | ||
658 | GNUNET_asprintf (&error, | 636 | GNUNET_asprintf (&error, |
659 | "error=\"%s\", error_description=\"%s\"", | 637 | "error=\"%s\", error_description=\"%s\"", |
660 | handle->emsg, | 638 | handle->emsg, |
@@ -710,27 +688,6 @@ do_timeout (void *cls) | |||
710 | 688 | ||
711 | 689 | ||
712 | /** | 690 | /** |
713 | * Return attributes for claim | ||
714 | * | ||
715 | * @param cls the request handle | ||
716 | */ | ||
717 | static void | ||
718 | return_userinfo_response (void *cls) | ||
719 | { | ||
720 | char *result_str; | ||
721 | struct RequestHandle *handle = cls; | ||
722 | struct MHD_Response *resp; | ||
723 | |||
724 | result_str = json_dumps (handle->oidc->response, 0); | ||
725 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR,"ID-Token: %s\n",result_str); | ||
726 | resp = GNUNET_REST_create_response (result_str); | ||
727 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
728 | GNUNET_free (result_str); | ||
729 | cleanup_handle (handle); | ||
730 | } | ||
731 | |||
732 | |||
733 | /** | ||
734 | * Respond to OPTIONS request | 691 | * Respond to OPTIONS request |
735 | * | 692 | * |
736 | * @param con_handle the connection handle | 693 | * @param con_handle the connection handle |
@@ -854,7 +811,9 @@ login_redirect (void *cls) | |||
854 | { | 811 | { |
855 | char *login_base_url; | 812 | char *login_base_url; |
856 | char *new_redirect; | 813 | char *new_redirect; |
814 | char *tmp; | ||
857 | struct MHD_Response *resp; | 815 | struct MHD_Response *resp; |
816 | struct GNUNET_Buffer buf = { 0 }; | ||
858 | struct RequestHandle *handle = cls; | 817 | struct RequestHandle *handle = cls; |
859 | 818 | ||
860 | if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, | 819 | if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, |
@@ -862,27 +821,68 @@ login_redirect (void *cls) | |||
862 | "address", | 821 | "address", |
863 | &login_base_url)) | 822 | &login_base_url)) |
864 | { | 823 | { |
865 | GNUNET_asprintf (&new_redirect, | 824 | GNUNET_buffer_write_str (&buf, login_base_url); |
866 | "%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s", | 825 | GNUNET_buffer_write_fstr (&buf, |
867 | login_base_url, | 826 | "?%s=%s", |
868 | OIDC_RESPONSE_TYPE_KEY, | 827 | OIDC_RESPONSE_TYPE_KEY, |
869 | handle->oidc->response_type, | 828 | handle->oidc->response_type); |
870 | OIDC_CLIENT_ID_KEY, | 829 | GNUNET_buffer_write_fstr (&buf, |
871 | handle->oidc->client_id, | 830 | "&%s=%s", |
872 | OIDC_REDIRECT_URI_KEY, | 831 | OIDC_CLIENT_ID_KEY, |
873 | handle->oidc->redirect_uri, | 832 | handle->oidc->client_id); |
874 | OIDC_SCOPE_KEY, | 833 | GNUNET_STRINGS_urlencode (handle->oidc->redirect_uri, |
875 | handle->oidc->scope, | 834 | strlen (handle->oidc->redirect_uri), |
876 | OIDC_STATE_KEY, | 835 | &tmp); |
877 | (NULL != handle->oidc->state) ? handle->oidc->state : "", | 836 | GNUNET_buffer_write_fstr (&buf, |
878 | OIDC_CODE_CHALLENGE_KEY, | 837 | "&%s=%s", |
879 | (NULL != handle->oidc->code_challenge) ? | 838 | OIDC_REDIRECT_URI_KEY, |
880 | handle->oidc->code_challenge : "", | 839 | tmp); |
881 | OIDC_NONCE_KEY, | 840 | GNUNET_free (tmp); |
882 | (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "", | 841 | GNUNET_STRINGS_urlencode (handle->oidc->scope, |
883 | OIDC_CLAIMS_KEY, | 842 | strlen (handle->oidc->scope), |
884 | (NULL != handle->oidc->claims) ? handle->oidc->claims : | 843 | &tmp); |
885 | ""); | 844 | GNUNET_buffer_write_fstr (&buf, |
845 | "&%s=%s", | ||
846 | OIDC_SCOPE_KEY, | ||
847 | tmp); | ||
848 | GNUNET_free (tmp); | ||
849 | if (NULL != handle->oidc->state) | ||
850 | { | ||
851 | GNUNET_STRINGS_urlencode (handle->oidc->state, | ||
852 | strlen (handle->oidc->state), | ||
853 | &tmp); | ||
854 | GNUNET_buffer_write_fstr (&buf, | ||
855 | "&%s=%s", | ||
856 | OIDC_STATE_KEY, | ||
857 | handle->oidc->state); | ||
858 | GNUNET_free (tmp); | ||
859 | } | ||
860 | if (NULL != handle->oidc->code_challenge) | ||
861 | { | ||
862 | GNUNET_buffer_write_fstr (&buf, | ||
863 | "&%s=%s", | ||
864 | OIDC_CODE_CHALLENGE_KEY, | ||
865 | handle->oidc->code_challenge); | ||
866 | } | ||
867 | if (NULL != handle->oidc->nonce) | ||
868 | { | ||
869 | GNUNET_buffer_write_fstr (&buf, | ||
870 | "&%s=%s", | ||
871 | OIDC_NONCE_KEY, | ||
872 | handle->oidc->nonce); | ||
873 | } | ||
874 | if (NULL != handle->oidc->claims) | ||
875 | { | ||
876 | GNUNET_STRINGS_urlencode (handle->oidc->claims, | ||
877 | strlen (handle->oidc->claims), | ||
878 | &tmp); | ||
879 | GNUNET_buffer_write_fstr (&buf, | ||
880 | "&%s=%s", | ||
881 | OIDC_CLAIMS_KEY, | ||
882 | tmp); | ||
883 | GNUNET_free (tmp); | ||
884 | } | ||
885 | new_redirect = GNUNET_buffer_reap_str (&buf); | ||
886 | resp = GNUNET_REST_create_response (""); | 886 | resp = GNUNET_REST_create_response (""); |
887 | MHD_add_response_header (resp, "Location", new_redirect); | 887 | MHD_add_response_header (resp, "Location", new_redirect); |
888 | GNUNET_free (login_base_url); | 888 | GNUNET_free (login_base_url); |
@@ -954,6 +954,8 @@ oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket) | |||
954 | handle->redirect_prefix, | 954 | handle->redirect_prefix, |
955 | handle->tld, | 955 | handle->tld, |
956 | handle->redirect_suffix, | 956 | handle->redirect_suffix, |
957 | (NULL == strchr (handle->redirect_suffix, '?') ? "?" : | ||
958 | "&"), | ||
957 | handle->oidc->response_type, | 959 | handle->oidc->response_type, |
958 | code_string, | 960 | code_string, |
959 | handle->oidc->state); | 961 | handle->oidc->state); |
@@ -961,8 +963,10 @@ oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket) | |||
961 | else | 963 | else |
962 | { | 964 | { |
963 | GNUNET_asprintf (&redirect_uri, | 965 | GNUNET_asprintf (&redirect_uri, |
964 | "%s?%s=%s&state=%s", | 966 | "%s%s%s=%s&state=%s", |
965 | handle->oidc->redirect_uri, | 967 | handle->oidc->redirect_uri, |
968 | (NULL == strchr (handle->oidc->redirect_uri, '?') ? "?" : | ||
969 | "&"), | ||
966 | handle->oidc->response_type, | 970 | handle->oidc->response_type, |
967 | code_string, | 971 | code_string, |
968 | handle->oidc->state); | 972 | handle->oidc->state); |
@@ -1041,7 +1045,7 @@ oidc_attest_collect_finished_cb (void *cls) | |||
1041 | handle->attest_it = NULL; | 1045 | handle->attest_it = NULL; |
1042 | merged_list = attribute_list_merge (handle->attr_idtoken_list, | 1046 | merged_list = attribute_list_merge (handle->attr_idtoken_list, |
1043 | handle->attr_userinfo_list); | 1047 | handle->attr_userinfo_list); |
1044 | handle->idp_op = GNUNET_RECLAIM_ticket_issue (handle->idp, | 1048 | handle->idp_op = GNUNET_RECLAIM_ticket_issue (idp, |
1045 | &handle->priv_key, | 1049 | &handle->priv_key, |
1046 | &handle->oidc->client_pkey, | 1050 | &handle->oidc->client_pkey, |
1047 | merged_list, | 1051 | merged_list, |
@@ -1108,7 +1112,7 @@ oidc_attr_collect_finished_cb (void *cls) | |||
1108 | } | 1112 | } |
1109 | handle->attests_list = GNUNET_new (struct GNUNET_RECLAIM_AttestationList); | 1113 | handle->attests_list = GNUNET_new (struct GNUNET_RECLAIM_AttestationList); |
1110 | handle->attest_it = | 1114 | handle->attest_it = |
1111 | GNUNET_RECLAIM_get_attestations_start (handle->idp, | 1115 | GNUNET_RECLAIM_get_attestations_start (idp, |
1112 | &handle->priv_key, | 1116 | &handle->priv_key, |
1113 | &oidc_iteration_error, | 1117 | &oidc_iteration_error, |
1114 | handle, | 1118 | handle, |
@@ -1125,9 +1129,6 @@ attr_in_claims_request (struct RequestHandle *handle, | |||
1125 | const char *attr_name, | 1129 | const char *attr_name, |
1126 | const char *claims_parameter) | 1130 | const char *claims_parameter) |
1127 | { | 1131 | { |
1128 | char *scope_variables; | ||
1129 | char *scope_variable; | ||
1130 | char delimiter[] = " "; | ||
1131 | int ret = GNUNET_NO; | 1132 | int ret = GNUNET_NO; |
1132 | json_t *root; | 1133 | json_t *root; |
1133 | json_error_t error; | 1134 | json_error_t error; |
@@ -1135,19 +1136,12 @@ attr_in_claims_request (struct RequestHandle *handle, | |||
1135 | const char *key; | 1136 | const char *key; |
1136 | json_t *value; | 1137 | json_t *value; |
1137 | 1138 | ||
1138 | scope_variables = GNUNET_strdup (handle->oidc->scope); | 1139 | /** Check if attribute is requested through standard scope **/ |
1139 | scope_variable = strtok (scope_variables, delimiter); | 1140 | if (GNUNET_YES == OIDC_check_scopes_for_claim_request (handle->oidc->scope, |
1140 | while (NULL != scope_variable) | 1141 | attr_name)) |
1141 | { | 1142 | return GNUNET_YES; |
1142 | if (0 == strcmp (attr_name, scope_variable)) | ||
1143 | break; | ||
1144 | scope_variable = strtok (NULL, delimiter); | ||
1145 | } | ||
1146 | if (NULL != scope_variable) | ||
1147 | ret = GNUNET_YES; | ||
1148 | GNUNET_free (scope_variables); | ||
1149 | 1143 | ||
1150 | /** Try claims parameter if no in scope */ | 1144 | /** Try claims parameter if not in scope */ |
1151 | if ((NULL != handle->oidc->claims) && | 1145 | if ((NULL != handle->oidc->claims) && |
1152 | (GNUNET_YES != ret)) | 1146 | (GNUNET_YES != ret)) |
1153 | { | 1147 | { |
@@ -1274,7 +1268,7 @@ code_redirect (void *cls) | |||
1274 | return; | 1268 | return; |
1275 | } | 1269 | } |
1276 | // iterate over egos and compare their public key | 1270 | // iterate over egos and compare their public key |
1277 | for (handle->ego_entry = handle->ego_head; NULL != handle->ego_entry; | 1271 | for (handle->ego_entry = ego_head; NULL != handle->ego_entry; |
1278 | handle->ego_entry = handle->ego_entry->next) | 1272 | handle->ego_entry = handle->ego_entry->next) |
1279 | { | 1273 | { |
1280 | GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey); | 1274 | GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey); |
@@ -1282,13 +1276,12 @@ code_redirect (void *cls) | |||
1282 | { | 1276 | { |
1283 | handle->priv_key = | 1277 | handle->priv_key = |
1284 | *GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego); | 1278 | *GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego); |
1285 | handle->idp = GNUNET_RECLAIM_connect (cfg); | ||
1286 | handle->attr_idtoken_list = | 1279 | handle->attr_idtoken_list = |
1287 | GNUNET_new (struct GNUNET_RECLAIM_AttributeList); | 1280 | GNUNET_new (struct GNUNET_RECLAIM_AttributeList); |
1288 | handle->attr_userinfo_list = | 1281 | handle->attr_userinfo_list = |
1289 | GNUNET_new (struct GNUNET_RECLAIM_AttributeList); | 1282 | GNUNET_new (struct GNUNET_RECLAIM_AttributeList); |
1290 | handle->attr_it = | 1283 | handle->attr_it = |
1291 | GNUNET_RECLAIM_get_attributes_start (handle->idp, | 1284 | GNUNET_RECLAIM_get_attributes_start (idp, |
1292 | &handle->priv_key, | 1285 | &handle->priv_key, |
1293 | &oidc_iteration_error, | 1286 | &oidc_iteration_error, |
1294 | handle, | 1287 | handle, |
@@ -1433,7 +1426,7 @@ client_redirect (void *cls) | |||
1433 | 1426 | ||
1434 | /* Lookup client redirect uri to verify request */ | 1427 | /* Lookup client redirect uri to verify request */ |
1435 | handle->gns_op = | 1428 | handle->gns_op = |
1436 | GNUNET_GNS_lookup (handle->gns_handle, | 1429 | GNUNET_GNS_lookup (gns_handle, |
1437 | GNUNET_GNS_EMPTY_LABEL_AT, | 1430 | GNUNET_GNS_EMPTY_LABEL_AT, |
1438 | &handle->oidc->client_pkey, | 1431 | &handle->oidc->client_pkey, |
1439 | GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT, | 1432 | GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT, |
@@ -1448,6 +1441,7 @@ get_url_parameter_copy (const struct RequestHandle *handle, const char *key) | |||
1448 | { | 1441 | { |
1449 | struct GNUNET_HashCode hc; | 1442 | struct GNUNET_HashCode hc; |
1450 | char *value; | 1443 | char *value; |
1444 | char *res; | ||
1451 | 1445 | ||
1452 | GNUNET_CRYPTO_hash (key, strlen (key), &hc); | 1446 | GNUNET_CRYPTO_hash (key, strlen (key), &hc); |
1453 | if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle | 1447 | if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle |
@@ -1458,7 +1452,8 @@ get_url_parameter_copy (const struct RequestHandle *handle, const char *key) | |||
1458 | GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, &hc); | 1452 | GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, &hc); |
1459 | if (NULL == value) | 1453 | if (NULL == value) |
1460 | return NULL; | 1454 | return NULL; |
1461 | return GNUNET_strdup (value); | 1455 | GNUNET_STRINGS_urldecode (value, strlen (value), &res); |
1456 | return res; | ||
1462 | } | 1457 | } |
1463 | 1458 | ||
1464 | 1459 | ||
@@ -1657,14 +1652,14 @@ authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
1657 | 1652 | ||
1658 | // If we know this identity, translated the corresponding TLD | 1653 | // If we know this identity, translated the corresponding TLD |
1659 | // TODO: We might want to have a reverse lookup functionality for TLDs? | 1654 | // TODO: We might want to have a reverse lookup functionality for TLDs? |
1660 | for (tmp_ego = handle->ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next) | 1655 | for (tmp_ego = ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next) |
1661 | { | 1656 | { |
1662 | priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego); | 1657 | priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego); |
1663 | GNUNET_CRYPTO_ecdsa_key_get_public (priv_key, &pkey); | 1658 | GNUNET_CRYPTO_ecdsa_key_get_public (priv_key, &pkey); |
1664 | if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey)) | 1659 | if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey)) |
1665 | { | 1660 | { |
1666 | handle->tld = GNUNET_strdup (tmp_ego->identifier); | 1661 | handle->tld = GNUNET_strdup (tmp_ego->identifier); |
1667 | handle->ego_entry = handle->ego_tail; | 1662 | handle->ego_entry = ego_tail; |
1668 | } | 1663 | } |
1669 | } | 1664 | } |
1670 | handle->oidc->scope = get_url_parameter_copy (handle, OIDC_SCOPE_KEY); | 1665 | handle->oidc->scope = get_url_parameter_copy (handle, OIDC_SCOPE_KEY); |
@@ -1749,16 +1744,16 @@ login_cont (struct GNUNET_REST_RequestHandle *con_handle, | |||
1749 | 1744 | ||
1750 | 1745 | ||
1751 | static int | 1746 | static int |
1752 | check_authorization (struct RequestHandle *handle, | 1747 | parse_credentials_basic_auth (struct RequestHandle *handle, |
1753 | struct GNUNET_CRYPTO_EcdsaPublicKey *cid) | 1748 | char **client_id, |
1749 | char **client_secret) | ||
1754 | { | 1750 | { |
1755 | struct GNUNET_HashCode cache_key; | 1751 | struct GNUNET_HashCode cache_key; |
1756 | char *authorization; | 1752 | char *authorization; |
1757 | char *credentials; | 1753 | char *credentials; |
1758 | char *basic_authorization; | 1754 | char *basic_authorization; |
1759 | char *client_id; | 1755 | char *client_id_tmp; |
1760 | char *pass; | 1756 | char *pass; |
1761 | char *expected_pass; | ||
1762 | 1757 | ||
1763 | GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY, | 1758 | GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY, |
1764 | strlen (OIDC_AUTHORIZATION_HEADER_KEY), | 1759 | strlen (OIDC_AUTHORIZATION_HEADER_KEY), |
@@ -1766,12 +1761,7 @@ check_authorization (struct RequestHandle *handle, | |||
1766 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle | 1761 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle |
1767 | ->header_param_map, | 1762 | ->header_param_map, |
1768 | &cache_key)) | 1763 | &cache_key)) |
1769 | { | ||
1770 | handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT); | ||
1771 | handle->edesc = GNUNET_strdup ("missing authorization"); | ||
1772 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | ||
1773 | return GNUNET_SYSERR; | 1764 | return GNUNET_SYSERR; |
1774 | } | ||
1775 | authorization = | 1765 | authorization = |
1776 | GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map, | 1766 | GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map, |
1777 | &cache_key); | 1767 | &cache_key); |
@@ -1779,44 +1769,117 @@ check_authorization (struct RequestHandle *handle, | |||
1779 | // split header in "Basic" and [content] | 1769 | // split header in "Basic" and [content] |
1780 | credentials = strtok (authorization, " "); | 1770 | credentials = strtok (authorization, " "); |
1781 | if ((NULL == credentials) || (0 != strcmp ("Basic", credentials))) | 1771 | if ((NULL == credentials) || (0 != strcmp ("Basic", credentials))) |
1782 | { | ||
1783 | handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT); | ||
1784 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | ||
1785 | return GNUNET_SYSERR; | 1772 | return GNUNET_SYSERR; |
1786 | } | ||
1787 | credentials = strtok (NULL, " "); | 1773 | credentials = strtok (NULL, " "); |
1788 | if (NULL == credentials) | 1774 | if (NULL == credentials) |
1789 | { | ||
1790 | handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT); | ||
1791 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | ||
1792 | return GNUNET_SYSERR; | 1775 | return GNUNET_SYSERR; |
1793 | } | ||
1794 | GNUNET_STRINGS_base64_decode (credentials, | 1776 | GNUNET_STRINGS_base64_decode (credentials, |
1795 | strlen (credentials), | 1777 | strlen (credentials), |
1796 | (void **) &basic_authorization); | 1778 | (void **) &basic_authorization); |
1797 | 1779 | ||
1798 | if (NULL == basic_authorization) | 1780 | if (NULL == basic_authorization) |
1799 | { | ||
1800 | handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT); | ||
1801 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | ||
1802 | return GNUNET_SYSERR; | 1781 | return GNUNET_SYSERR; |
1803 | } | 1782 | client_id_tmp = strtok (basic_authorization, ":"); |
1804 | client_id = strtok (basic_authorization, ":"); | 1783 | if (NULL == client_id_tmp) |
1805 | if (NULL == client_id) | ||
1806 | { | 1784 | { |
1807 | GNUNET_free (basic_authorization); | 1785 | GNUNET_free (basic_authorization); |
1808 | handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT); | ||
1809 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | ||
1810 | return GNUNET_SYSERR; | 1786 | return GNUNET_SYSERR; |
1811 | } | 1787 | } |
1812 | pass = strtok (NULL, ":"); | 1788 | pass = strtok (NULL, ":"); |
1813 | if (NULL == pass) | 1789 | if (NULL == pass) |
1814 | { | 1790 | { |
1815 | GNUNET_free (basic_authorization); | 1791 | GNUNET_free (basic_authorization); |
1816 | handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT); | ||
1817 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | ||
1818 | return GNUNET_SYSERR; | 1792 | return GNUNET_SYSERR; |
1819 | } | 1793 | } |
1794 | *client_id = strdup (client_id_tmp); | ||
1795 | *client_secret = strdup (pass); | ||
1796 | GNUNET_free (basic_authorization); | ||
1797 | return GNUNET_OK; | ||
1798 | } | ||
1799 | |||
1800 | |||
1801 | static int | ||
1802 | parse_credentials_post_body (struct RequestHandle *handle, | ||
1803 | char **client_id, | ||
1804 | char **client_secret) | ||
1805 | { | ||
1806 | struct GNUNET_HashCode cache_key; | ||
1807 | char *client_id_tmp; | ||
1808 | char *pass; | ||
1809 | |||
1810 | GNUNET_CRYPTO_hash ("client_id", | ||
1811 | strlen ("client_id"), | ||
1812 | &cache_key); | ||
1813 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle | ||
1814 | ->url_param_map, | ||
1815 | &cache_key)) | ||
1816 | return GNUNET_SYSERR; | ||
1817 | client_id_tmp = GNUNET_CONTAINER_multihashmap_get ( | ||
1818 | handle->rest_handle->url_param_map, | ||
1819 | &cache_key); | ||
1820 | if (NULL == client_id_tmp) | ||
1821 | return GNUNET_SYSERR; | ||
1822 | *client_id = strdup (client_id_tmp); | ||
1823 | GNUNET_CRYPTO_hash ("client_secret", | ||
1824 | strlen ("client_secret"), | ||
1825 | &cache_key); | ||
1826 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle | ||
1827 | ->url_param_map, | ||
1828 | &cache_key)) | ||
1829 | return GNUNET_SYSERR; | ||
1830 | pass = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, | ||
1831 | &cache_key); | ||
1832 | if (NULL == pass) | ||
1833 | return GNUNET_SYSERR; | ||
1834 | *client_secret = strdup (pass); | ||
1835 | return GNUNET_OK; | ||
1836 | } | ||
1837 | |||
1838 | |||
1839 | static int | ||
1840 | check_authorization (struct RequestHandle *handle, | ||
1841 | struct GNUNET_CRYPTO_EcdsaPublicKey *cid) | ||
1842 | { | ||
1843 | char *expected_pass; | ||
1844 | char *received_cid; | ||
1845 | char *received_cpw; | ||
1846 | char *pkce_cv; | ||
1847 | |||
1848 | if (GNUNET_OK == parse_credentials_basic_auth (handle, | ||
1849 | &received_cid, | ||
1850 | &received_cpw)) | ||
1851 | { | ||
1852 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1853 | "Received client credentials in HTTP AuthZ header\n"); | ||
1854 | } | ||
1855 | else if (GNUNET_OK == parse_credentials_post_body (handle, | ||
1856 | &received_cid, | ||
1857 | &received_cpw)) | ||
1858 | { | ||
1859 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1860 | "Received client credentials in POST body\n"); | ||
1861 | } | ||
1862 | else | ||
1863 | { | ||
1864 | /** Allow public clients with PKCE **/ | ||
1865 | pkce_cv = get_url_parameter_copy (handle, OIDC_CODE_VERIFIER_KEY); | ||
1866 | if (NULL == pkce_cv) | ||
1867 | { | ||
1868 | handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT); | ||
1869 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | ||
1870 | return GNUNET_SYSERR; | ||
1871 | } | ||
1872 | handle->public_client = GNUNET_YES; | ||
1873 | GNUNET_free (pkce_cv); | ||
1874 | received_cid = get_url_parameter_copy (handle, OIDC_CLIENT_ID_KEY); | ||
1875 | GNUNET_STRINGS_string_to_data (received_cid, | ||
1876 | strlen (received_cid), | ||
1877 | cid, | ||
1878 | sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
1879 | GNUNET_free (received_cid); | ||
1880 | return GNUNET_OK; | ||
1881 | |||
1882 | } | ||
1820 | 1883 | ||
1821 | // check client password | 1884 | // check client password |
1822 | if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, | 1885 | if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, |
@@ -1824,9 +1887,8 @@ check_authorization (struct RequestHandle *handle, | |||
1824 | "OIDC_CLIENT_SECRET", | 1887 | "OIDC_CLIENT_SECRET", |
1825 | &expected_pass)) | 1888 | &expected_pass)) |
1826 | { | 1889 | { |
1827 | if (0 != strcmp (expected_pass, pass)) | 1890 | if (0 != strcmp (expected_pass, received_cpw)) |
1828 | { | 1891 | { |
1829 | GNUNET_free (basic_authorization); | ||
1830 | GNUNET_free (expected_pass); | 1892 | GNUNET_free (expected_pass); |
1831 | handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT); | 1893 | handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT); |
1832 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | 1894 | handle->response_code = MHD_HTTP_UNAUTHORIZED; |
@@ -1836,33 +1898,33 @@ check_authorization (struct RequestHandle *handle, | |||
1836 | } | 1898 | } |
1837 | else | 1899 | else |
1838 | { | 1900 | { |
1839 | GNUNET_free (basic_authorization); | ||
1840 | handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR); | 1901 | handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_SERVER_ERROR); |
1841 | handle->edesc = GNUNET_strdup ("gnunet configuration failed"); | 1902 | handle->edesc = GNUNET_strdup ("gnunet configuration failed"); |
1842 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | 1903 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; |
1843 | return GNUNET_SYSERR; | 1904 | return GNUNET_SYSERR; |
1844 | } | 1905 | } |
1845 | |||
1846 | // check client_id | 1906 | // check client_id |
1847 | for (handle->ego_entry = handle->ego_head; NULL != handle->ego_entry; | 1907 | for (handle->ego_entry = ego_head; NULL != handle->ego_entry; |
1848 | handle->ego_entry = handle->ego_entry->next) | 1908 | handle->ego_entry = handle->ego_entry->next) |
1849 | { | 1909 | { |
1850 | if (0 == strcmp (handle->ego_entry->keystring, client_id)) | 1910 | if (0 == strcmp (handle->ego_entry->keystring, received_cid)) |
1851 | break; | 1911 | break; |
1852 | } | 1912 | } |
1853 | if (NULL == handle->ego_entry) | 1913 | if (NULL == handle->ego_entry) |
1854 | { | 1914 | { |
1855 | GNUNET_free (basic_authorization); | 1915 | GNUNET_free (received_cpw); |
1916 | GNUNET_free (received_cid); | ||
1856 | handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT); | 1917 | handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_CLIENT); |
1857 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | 1918 | handle->response_code = MHD_HTTP_UNAUTHORIZED; |
1858 | return GNUNET_SYSERR; | 1919 | return GNUNET_SYSERR; |
1859 | } | 1920 | } |
1860 | GNUNET_STRINGS_string_to_data (client_id, | 1921 | GNUNET_STRINGS_string_to_data (received_cid, |
1861 | strlen (client_id), | 1922 | strlen (received_cid), |
1862 | cid, | 1923 | cid, |
1863 | sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)); | 1924 | sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)); |
1864 | 1925 | ||
1865 | GNUNET_free (basic_authorization); | 1926 | GNUNET_free (received_cpw); |
1927 | GNUNET_free (received_cid); | ||
1866 | return GNUNET_OK; | 1928 | return GNUNET_OK; |
1867 | } | 1929 | } |
1868 | 1930 | ||
@@ -1874,7 +1936,7 @@ find_ego (struct RequestHandle *handle, | |||
1874 | struct EgoEntry *ego_entry; | 1936 | struct EgoEntry *ego_entry; |
1875 | struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; | 1937 | struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; |
1876 | 1938 | ||
1877 | for (ego_entry = handle->ego_head; NULL != ego_entry; | 1939 | for (ego_entry = ego_head; NULL != ego_entry; |
1878 | ego_entry = ego_entry->next) | 1940 | ego_entry = ego_entry->next) |
1879 | { | 1941 | { |
1880 | GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key); | 1942 | GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key); |
@@ -1885,26 +1947,6 @@ find_ego (struct RequestHandle *handle, | |||
1885 | } | 1947 | } |
1886 | 1948 | ||
1887 | 1949 | ||
1888 | static void | ||
1889 | persist_access_token (const struct RequestHandle *handle, | ||
1890 | const char *access_token, | ||
1891 | const struct GNUNET_RECLAIM_Ticket *ticket) | ||
1892 | { | ||
1893 | struct GNUNET_HashCode hc; | ||
1894 | struct GNUNET_RECLAIM_Ticket *ticketbuf; | ||
1895 | |||
1896 | GNUNET_CRYPTO_hash (access_token, strlen (access_token), &hc); | ||
1897 | ticketbuf = GNUNET_new (struct GNUNET_RECLAIM_Ticket); | ||
1898 | *ticketbuf = *ticket; | ||
1899 | GNUNET_assert (GNUNET_SYSERR != | ||
1900 | GNUNET_CONTAINER_multihashmap_put ( | ||
1901 | OIDC_access_token_map, | ||
1902 | &hc, | ||
1903 | ticketbuf, | ||
1904 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
1905 | } | ||
1906 | |||
1907 | |||
1908 | /** | 1950 | /** |
1909 | * Responds to token url-encoded POST request | 1951 | * Responds to token url-encoded POST request |
1910 | * | 1952 | * |
@@ -2008,7 +2050,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
2008 | } | 2050 | } |
2009 | 2051 | ||
2010 | // decode code | 2052 | // decode code |
2011 | if (GNUNET_OK != OIDC_parse_authz_code (privkey, code, code_verifier, &ticket, | 2053 | if (GNUNET_OK != OIDC_parse_authz_code (&cid, code, code_verifier, &ticket, |
2012 | &cl, &al, &nonce)) | 2054 | &cl, &al, &nonce)) |
2013 | { | 2055 | { |
2014 | handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST); | 2056 | handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST); |
@@ -2046,20 +2088,19 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
2046 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 2088 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
2047 | return; | 2089 | return; |
2048 | } | 2090 | } |
2049 | id_token = OIDC_id_token_new (&ticket.audience, | 2091 | id_token = OIDC_generate_id_token (&ticket.audience, |
2050 | &ticket.identity, | 2092 | &ticket.identity, |
2051 | cl, | 2093 | cl, |
2052 | al, | 2094 | al, |
2053 | &expiration_time, | 2095 | &expiration_time, |
2054 | (NULL != nonce) ? nonce : NULL, | 2096 | (NULL != nonce) ? nonce : NULL, |
2055 | jwt_secret); | 2097 | jwt_secret); |
2056 | access_token = OIDC_access_token_new (); | 2098 | access_token = OIDC_access_token_new (&ticket); |
2057 | OIDC_build_token_response (access_token, | 2099 | OIDC_build_token_response (access_token, |
2058 | id_token, | 2100 | id_token, |
2059 | &expiration_time, | 2101 | &expiration_time, |
2060 | &json_response); | 2102 | &json_response); |
2061 | 2103 | ||
2062 | persist_access_token (handle, access_token, &ticket); | ||
2063 | resp = GNUNET_REST_create_response (json_response); | 2104 | resp = GNUNET_REST_create_response (json_response); |
2064 | MHD_add_response_header (resp, "Cache-Control", "no-store"); | 2105 | MHD_add_response_header (resp, "Cache-Control", "no-store"); |
2065 | MHD_add_response_header (resp, "Pragma", "no-cache"); | 2106 | MHD_add_response_header (resp, "Pragma", "no-cache"); |
@@ -2084,83 +2125,56 @@ consume_ticket (void *cls, | |||
2084 | const struct GNUNET_RECLAIM_Attestation *attest) | 2125 | const struct GNUNET_RECLAIM_Attestation *attest) |
2085 | { | 2126 | { |
2086 | struct RequestHandle *handle = cls; | 2127 | struct RequestHandle *handle = cls; |
2128 | struct GNUNET_RECLAIM_AttributeListEntry *ale; | ||
2129 | struct GNUNET_RECLAIM_AttestationListEntry *atle; | ||
2130 | struct MHD_Response *resp; | ||
2131 | char *result_str; | ||
2087 | handle->idp_op = NULL; | 2132 | handle->idp_op = NULL; |
2088 | 2133 | ||
2134 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Attr: %s\n", attr->name); | ||
2089 | if (NULL == identity) | 2135 | if (NULL == identity) |
2090 | { | 2136 | { |
2091 | GNUNET_SCHEDULER_add_now (&return_userinfo_response, handle); | 2137 | result_str = OIDC_generate_userinfo (&handle->ticket.identity, |
2138 | handle->attr_userinfo_list, | ||
2139 | handle->attests_list); | ||
2140 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Userinfo: %s\n", result_str); | ||
2141 | resp = GNUNET_REST_create_response (result_str); | ||
2142 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
2143 | GNUNET_free (result_str); | ||
2144 | cleanup_handle (handle); | ||
2092 | return; | 2145 | return; |
2093 | } | 2146 | } |
2094 | if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&attr->attestation)) | 2147 | ale = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry); |
2148 | ale->attribute = GNUNET_RECLAIM_attribute_new (attr->name, | ||
2149 | &attr->attestation, | ||
2150 | attr->type, | ||
2151 | attr->data, | ||
2152 | attr->data_size); | ||
2153 | ale->attribute->id = attr->id; | ||
2154 | ale->attribute->flag = attr->flag; | ||
2155 | ale->attribute->attestation = attr->attestation; | ||
2156 | GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head, | ||
2157 | handle->attr_userinfo_list->list_tail, | ||
2158 | ale); | ||
2159 | for (atle = handle->attests_list->list_head; NULL != atle; atle = atle->next) | ||
2160 | { | ||
2161 | if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&atle->attestation->id, | ||
2162 | &attest->id)) | ||
2163 | continue; | ||
2164 | break; /** already in list **/ | ||
2165 | } | ||
2166 | if (NULL == atle) | ||
2095 | { | 2167 | { |
2096 | char *tmp_value; | 2168 | /** Attestation matches for attribute, add **/ |
2097 | json_t *value; | 2169 | atle = GNUNET_new (struct GNUNET_RECLAIM_AttestationListEntry); |
2098 | tmp_value = GNUNET_RECLAIM_attribute_value_to_string (attr->type, | 2170 | atle->attestation = GNUNET_RECLAIM_attestation_new (attest->name, |
2099 | attr->data, | 2171 | attest->type, |
2100 | attr->data_size); | 2172 | attest->data, |
2101 | value = json_string (tmp_value); | 2173 | attest->data_size); |
2102 | json_object_set_new (handle->oidc->response, attr->name, value); | 2174 | GNUNET_CONTAINER_DLL_insert (handle->attests_list->list_head, |
2103 | GNUNET_free (tmp_value); | 2175 | handle->attests_list->list_tail, |
2104 | return; | 2176 | atle); |
2105 | } | 2177 | } |
2106 | json_t *claim_sources; | ||
2107 | json_t *claim_sources_jwt; | ||
2108 | json_t *claim_names; | ||
2109 | char *attest_val_str; | ||
2110 | claim_sources = json_object_get (handle->oidc->response,"_claim_sources"); | ||
2111 | claim_names = json_object_get (handle->oidc->response,"_claim_names"); | ||
2112 | attest_val_str = | ||
2113 | GNUNET_RECLAIM_attestation_value_to_string (attest->type, | ||
2114 | attest->data, | ||
2115 | attest->data_size); | ||
2116 | if ((NULL == claim_sources) && (NULL == claim_names) ) | ||
2117 | { | ||
2118 | claim_sources = json_object (); | ||
2119 | claim_names = json_object (); | ||
2120 | } | ||
2121 | char *source_name; | ||
2122 | int i = 0; | ||
2123 | GNUNET_asprintf (&source_name, "src%d", i); | ||
2124 | while (NULL != (claim_sources_jwt = json_object_get (claim_sources, | ||
2125 | source_name))) | ||
2126 | { | ||
2127 | if (0 == strcmp (json_string_value (json_object_get (claim_sources_jwt, | ||
2128 | "JWT")), | ||
2129 | attest_val_str)) | ||
2130 | { | ||
2131 | // Adapt only the claim names | ||
2132 | json_object_set_new (claim_names, attr->data, | ||
2133 | json_string (source_name)); | ||
2134 | json_object_set (handle->oidc->response, | ||
2135 | "_claim_names", claim_names); | ||
2136 | break; | ||
2137 | } | ||
2138 | i++; | ||
2139 | GNUNET_free (source_name); | ||
2140 | GNUNET_asprintf (&source_name, "src%d", i); | ||
2141 | } | ||
2142 | |||
2143 | // Create new one | ||
2144 | if (NULL == claim_sources_jwt) | ||
2145 | { | ||
2146 | claim_sources_jwt = json_object (); | ||
2147 | // Set the JWT for names | ||
2148 | json_object_set_new (claim_names, attr->data, | ||
2149 | json_string (source_name)); | ||
2150 | // Set the JWT for the inner source | ||
2151 | json_object_set_new (claim_sources_jwt, "JWT", | ||
2152 | json_string (attest_val_str)); | ||
2153 | // Set the JWT for the source | ||
2154 | json_object_set_new (claim_sources, source_name, claim_sources_jwt); | ||
2155 | // Set as claims | ||
2156 | json_object_set (handle->oidc->response, "_claim_names", claim_names); | ||
2157 | json_object_set (handle->oidc->response, "_claim_sources",claim_sources); | ||
2158 | } | ||
2159 | |||
2160 | json_decref (claim_sources); | ||
2161 | json_decref (claim_names); | ||
2162 | json_decref (claim_sources_jwt); | ||
2163 | GNUNET_free (attest_val_str); | ||
2164 | } | 2178 | } |
2165 | 2179 | ||
2166 | 2180 | ||
@@ -2178,15 +2192,16 @@ userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
2178 | { | 2192 | { |
2179 | // TODO expiration time | 2193 | // TODO expiration time |
2180 | struct RequestHandle *handle = cls; | 2194 | struct RequestHandle *handle = cls; |
2195 | struct GNUNET_RECLAIM_Ticket *ticket; | ||
2181 | char delimiter[] = " "; | 2196 | char delimiter[] = " "; |
2182 | struct GNUNET_HashCode cache_key; | 2197 | struct GNUNET_HashCode cache_key; |
2183 | char *authorization; | 2198 | char *authorization; |
2184 | char *authorization_type; | 2199 | char *authorization_type; |
2185 | char *authorization_access_token; | 2200 | char *authorization_access_token; |
2186 | struct GNUNET_RECLAIM_Ticket *ticket; | 2201 | const struct EgoEntry *aud_ego; |
2187 | const struct EgoEntry *ego_entry; | ||
2188 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey; | 2202 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey; |
2189 | 2203 | ||
2204 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Getting userinfo\n"); | ||
2190 | GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY, | 2205 | GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY, |
2191 | strlen (OIDC_AUTHORIZATION_HEADER_KEY), | 2206 | strlen (OIDC_AUTHORIZATION_HEADER_KEY), |
2192 | &cache_key); | 2207 | &cache_key); |
@@ -2228,25 +2243,22 @@ userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
2228 | return; | 2243 | return; |
2229 | } | 2244 | } |
2230 | 2245 | ||
2231 | GNUNET_CRYPTO_hash (authorization_access_token, | 2246 | if (GNUNET_OK != OIDC_access_token_parse (authorization_access_token, |
2232 | strlen (authorization_access_token), | 2247 | &ticket)) |
2233 | &cache_key); | ||
2234 | if (GNUNET_NO == | ||
2235 | GNUNET_CONTAINER_multihashmap_contains (OIDC_access_token_map, | ||
2236 | &cache_key)) | ||
2237 | { | 2248 | { |
2238 | handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN); | 2249 | handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN); |
2239 | handle->edesc = GNUNET_strdup ("The access token expired"); | 2250 | handle->edesc = GNUNET_strdup ("The access token is invalid"); |
2240 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | 2251 | handle->response_code = MHD_HTTP_UNAUTHORIZED; |
2241 | GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); | 2252 | GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); |
2242 | GNUNET_free (authorization); | 2253 | GNUNET_free (authorization); |
2243 | return; | 2254 | return; |
2255 | |||
2244 | } | 2256 | } |
2245 | ticket = | ||
2246 | GNUNET_CONTAINER_multihashmap_get (OIDC_access_token_map, &cache_key); | ||
2247 | GNUNET_assert (NULL != ticket); | 2257 | GNUNET_assert (NULL != ticket); |
2248 | ego_entry = find_ego (handle, &ticket->audience); | 2258 | handle->ticket = *ticket; |
2249 | if (NULL == ego_entry) | 2259 | GNUNET_free (ticket); |
2260 | aud_ego = find_ego (handle, &handle->ticket.audience); | ||
2261 | if (NULL == aud_ego) | ||
2250 | { | 2262 | { |
2251 | handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN); | 2263 | handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_TOKEN); |
2252 | handle->edesc = GNUNET_strdup ("The access token expired"); | 2264 | handle->edesc = GNUNET_strdup ("The access token expired"); |
@@ -2255,53 +2267,23 @@ userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
2255 | GNUNET_free (authorization); | 2267 | GNUNET_free (authorization); |
2256 | return; | 2268 | return; |
2257 | } | 2269 | } |
2270 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Consuming ticket\n"); | ||
2271 | privkey = GNUNET_IDENTITY_ego_get_private_key (aud_ego->ego); | ||
2272 | handle->attr_userinfo_list = | ||
2273 | GNUNET_new (struct GNUNET_RECLAIM_AttributeList); | ||
2274 | handle->attests_list = | ||
2275 | GNUNET_new (struct GNUNET_RECLAIM_AttestationList); | ||
2258 | 2276 | ||
2259 | handle->idp = GNUNET_RECLAIM_connect (cfg); | 2277 | handle->idp_op = GNUNET_RECLAIM_ticket_consume (idp, |
2260 | handle->oidc->response = json_object (); | ||
2261 | json_object_set_new (handle->oidc->response, | ||
2262 | "sub", | ||
2263 | json_string (ego_entry->keystring)); | ||
2264 | privkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); | ||
2265 | handle->idp_op = GNUNET_RECLAIM_ticket_consume (handle->idp, | ||
2266 | privkey, | 2278 | privkey, |
2267 | ticket, | 2279 | &handle->ticket, |
2268 | consume_ticket, | 2280 | &consume_ticket, |
2269 | handle); | 2281 | handle); |
2270 | GNUNET_free (authorization); | 2282 | GNUNET_free (authorization); |
2271 | } | 2283 | } |
2272 | 2284 | ||
2273 | 2285 | ||
2274 | /** | 2286 | /** |
2275 | * Handle rest request | ||
2276 | * | ||
2277 | * @param handle the request handle | ||
2278 | */ | ||
2279 | static void | ||
2280 | init_cont (struct RequestHandle *handle) | ||
2281 | { | ||
2282 | struct GNUNET_REST_RequestHandlerError err; | ||
2283 | static const struct GNUNET_REST_RequestHandler handlers[] = | ||
2284 | { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint }, | ||
2285 | { MHD_HTTP_METHOD_POST, | ||
2286 | GNUNET_REST_API_NS_AUTHORIZE, | ||
2287 | &authorize_endpoint }, // url-encoded | ||
2288 | { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont }, | ||
2289 | { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint }, | ||
2290 | { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint }, | ||
2291 | { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint }, | ||
2292 | { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont }, | ||
2293 | GNUNET_REST_HANDLER_END }; | ||
2294 | |||
2295 | if (GNUNET_NO == | ||
2296 | GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle)) | ||
2297 | { | ||
2298 | handle->response_code = err.error_code; | ||
2299 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
2300 | } | ||
2301 | } | ||
2302 | |||
2303 | |||
2304 | /** | ||
2305 | * If listing is enabled, prints information about the egos. | 2287 | * If listing is enabled, prints information about the egos. |
2306 | * | 2288 | * |
2307 | * This function is initially called for all egos and then again | 2289 | * This function is initially called for all egos and then again |
@@ -2340,18 +2322,16 @@ list_ego (void *cls, | |||
2340 | void **ctx, | 2322 | void **ctx, |
2341 | const char *identifier) | 2323 | const char *identifier) |
2342 | { | 2324 | { |
2343 | struct RequestHandle *handle = cls; | ||
2344 | struct EgoEntry *ego_entry; | 2325 | struct EgoEntry *ego_entry; |
2345 | struct GNUNET_CRYPTO_EcdsaPublicKey pk; | 2326 | struct GNUNET_CRYPTO_EcdsaPublicKey pk; |
2346 | 2327 | ||
2347 | if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state)) | 2328 | if ((NULL == ego) && (ID_REST_STATE_INIT == state)) |
2348 | { | 2329 | { |
2349 | handle->state = ID_REST_STATE_POST_INIT; | 2330 | state = ID_REST_STATE_POST_INIT; |
2350 | init_cont (handle); | ||
2351 | return; | 2331 | return; |
2352 | } | 2332 | } |
2353 | GNUNET_assert (NULL != ego); | 2333 | GNUNET_assert (NULL != ego); |
2354 | if (ID_REST_STATE_INIT == handle->state) | 2334 | if (ID_REST_STATE_INIT == state) |
2355 | 2335 | ||
2356 | { | 2336 | { |
2357 | ego_entry = GNUNET_new (struct EgoEntry); | 2337 | ego_entry = GNUNET_new (struct EgoEntry); |
@@ -2359,15 +2339,15 @@ list_ego (void *cls, | |||
2359 | ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); | 2339 | ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); |
2360 | ego_entry->ego = ego; | 2340 | ego_entry->ego = ego; |
2361 | ego_entry->identifier = GNUNET_strdup (identifier); | 2341 | ego_entry->identifier = GNUNET_strdup (identifier); |
2362 | GNUNET_CONTAINER_DLL_insert_tail (handle->ego_head, | 2342 | GNUNET_CONTAINER_DLL_insert_tail (ego_head, |
2363 | handle->ego_tail, | 2343 | ego_tail, |
2364 | ego_entry); | 2344 | ego_entry); |
2365 | return; | 2345 | return; |
2366 | } | 2346 | } |
2367 | /* Ego renamed or added */ | 2347 | /* Ego renamed or added */ |
2368 | if (identifier != NULL) | 2348 | if (identifier != NULL) |
2369 | { | 2349 | { |
2370 | for (ego_entry = handle->ego_head; NULL != ego_entry; | 2350 | for (ego_entry = ego_head; NULL != ego_entry; |
2371 | ego_entry = ego_entry->next) | 2351 | ego_entry = ego_entry->next) |
2372 | { | 2352 | { |
2373 | if (ego_entry->ego == ego) | 2353 | if (ego_entry->ego == ego) |
@@ -2386,15 +2366,15 @@ list_ego (void *cls, | |||
2386 | ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); | 2366 | ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); |
2387 | ego_entry->ego = ego; | 2367 | ego_entry->ego = ego; |
2388 | ego_entry->identifier = GNUNET_strdup (identifier); | 2368 | ego_entry->identifier = GNUNET_strdup (identifier); |
2389 | GNUNET_CONTAINER_DLL_insert_tail (handle->ego_head, | 2369 | GNUNET_CONTAINER_DLL_insert_tail (ego_head, |
2390 | handle->ego_tail, | 2370 | ego_tail, |
2391 | ego_entry); | 2371 | ego_entry); |
2392 | } | 2372 | } |
2393 | } | 2373 | } |
2394 | else | 2374 | else |
2395 | { | 2375 | { |
2396 | /* Delete */ | 2376 | /* Delete */ |
2397 | for (ego_entry = handle->ego_head; NULL != ego_entry; | 2377 | for (ego_entry = ego_head; NULL != ego_entry; |
2398 | ego_entry = ego_entry->next) | 2378 | ego_entry = ego_entry->next) |
2399 | { | 2379 | { |
2400 | if (ego_entry->ego == ego) | 2380 | if (ego_entry->ego == ego) |
@@ -2403,8 +2383,8 @@ list_ego (void *cls, | |||
2403 | if (NULL == ego_entry) | 2383 | if (NULL == ego_entry) |
2404 | return; /* Not found */ | 2384 | return; /* Not found */ |
2405 | 2385 | ||
2406 | GNUNET_CONTAINER_DLL_remove (handle->ego_head, | 2386 | GNUNET_CONTAINER_DLL_remove (ego_head, |
2407 | handle->ego_tail, | 2387 | ego_tail, |
2408 | ego_entry); | 2388 | ego_entry); |
2409 | GNUNET_free (ego_entry->identifier); | 2389 | GNUNET_free (ego_entry->identifier); |
2410 | GNUNET_free (ego_entry->keystring); | 2390 | GNUNET_free (ego_entry->keystring); |
@@ -2415,36 +2395,153 @@ list_ego (void *cls, | |||
2415 | 2395 | ||
2416 | 2396 | ||
2417 | static void | 2397 | static void |
2398 | oidc_config_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | ||
2399 | const char *url, | ||
2400 | void *cls) | ||
2401 | { | ||
2402 | json_t *oidc_config; | ||
2403 | json_t *auth_methods; | ||
2404 | json_t *sig_algs; | ||
2405 | json_t *scopes; | ||
2406 | json_t *response_types; | ||
2407 | json_t *sub_types; | ||
2408 | json_t *claim_types; | ||
2409 | char *oidc_config_str; | ||
2410 | struct MHD_Response *resp; | ||
2411 | struct RequestHandle *handle = cls; | ||
2412 | |||
2413 | oidc_config = json_object (); | ||
2414 | // FIXME get from config? | ||
2415 | json_object_set_new (oidc_config, | ||
2416 | "issuer", json_string ("http://localhost:7776")); | ||
2417 | json_object_set_new (oidc_config, | ||
2418 | "authorization_endpoint", | ||
2419 | json_string ("https://api.reclaim/openid/authorize")); | ||
2420 | json_object_set_new (oidc_config, | ||
2421 | "token_endpoint", | ||
2422 | json_string ("http://localhost:7776/openid/token")); | ||
2423 | auth_methods = json_array (); | ||
2424 | json_array_append_new (auth_methods, | ||
2425 | json_string ("client_secret_basic")); | ||
2426 | json_array_append_new (auth_methods, | ||
2427 | json_string ("client_secret_post")); | ||
2428 | json_object_set_new (oidc_config, | ||
2429 | "token_endpoint_auth_methods_supported", | ||
2430 | auth_methods); | ||
2431 | sig_algs = json_array (); | ||
2432 | json_array_append_new (sig_algs, | ||
2433 | json_string ("HS512")); | ||
2434 | json_object_set_new (oidc_config, | ||
2435 | "id_token_signing_alg_values_supported", | ||
2436 | sig_algs); | ||
2437 | json_object_set_new (oidc_config, | ||
2438 | "userinfo_endpoint", | ||
2439 | json_string ("http://localhost:7776/openid/userinfo")); | ||
2440 | scopes = json_array (); | ||
2441 | json_array_append_new (scopes, | ||
2442 | json_string ("openid")); | ||
2443 | json_array_append_new (scopes, | ||
2444 | json_string ("profile")); | ||
2445 | json_object_set_new (oidc_config, | ||
2446 | "scopes_supported", | ||
2447 | scopes); | ||
2448 | response_types = json_array (); | ||
2449 | json_array_append_new (response_types, | ||
2450 | json_string ("code")); | ||
2451 | json_object_set_new (oidc_config, | ||
2452 | "response_types_supported", | ||
2453 | response_types); | ||
2454 | sub_types = json_array (); | ||
2455 | json_array_append_new (sub_types, | ||
2456 | json_string ("public")); /* no pairwise suppport */ | ||
2457 | json_object_set_new (oidc_config, | ||
2458 | "subject_types_supported", | ||
2459 | sub_types); | ||
2460 | claim_types = json_array (); | ||
2461 | json_array_append_new (claim_types, | ||
2462 | json_string ("normal")); | ||
2463 | json_array_append_new (claim_types, | ||
2464 | json_string ("aggregated")); | ||
2465 | json_object_set_new (oidc_config, | ||
2466 | "claim_types_supported", | ||
2467 | claim_types); | ||
2468 | json_object_set_new (oidc_config, | ||
2469 | "claims_parameter_supported", | ||
2470 | json_boolean (1)); | ||
2471 | oidc_config_str = json_dumps (oidc_config, JSON_INDENT (1)); | ||
2472 | resp = GNUNET_REST_create_response (oidc_config_str); | ||
2473 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
2474 | GNUNET_free (oidc_config_str); | ||
2475 | cleanup_handle (handle); | ||
2476 | } | ||
2477 | |||
2478 | |||
2479 | /** | ||
2480 | * Respond to OPTIONS request | ||
2481 | * | ||
2482 | * @param con_handle the connection handle | ||
2483 | * @param url the url | ||
2484 | * @param cls the RequestHandle | ||
2485 | */ | ||
2486 | static void | ||
2487 | oidc_config_cors (struct GNUNET_REST_RequestHandle *con_handle, | ||
2488 | const char *url, | ||
2489 | void *cls) | ||
2490 | { | ||
2491 | struct MHD_Response *resp; | ||
2492 | struct RequestHandle *handle = cls; | ||
2493 | |||
2494 | // For now, independent of path return all options | ||
2495 | resp = GNUNET_REST_create_response (NULL); | ||
2496 | MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods); | ||
2497 | MHD_add_response_header (resp, "Access-Control-Allow-Origin", "*"); | ||
2498 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
2499 | cleanup_handle (handle); | ||
2500 | return; | ||
2501 | } | ||
2502 | |||
2503 | |||
2504 | static enum GNUNET_GenericReturnValue | ||
2418 | rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle, | 2505 | rest_identity_process_request (struct GNUNET_REST_RequestHandle *rest_handle, |
2419 | GNUNET_REST_ResultProcessor proc, | 2506 | GNUNET_REST_ResultProcessor proc, |
2420 | void *proc_cls) | 2507 | void *proc_cls) |
2421 | { | 2508 | { |
2422 | struct RequestHandle *handle = GNUNET_new (struct RequestHandle); | 2509 | struct RequestHandle *handle = GNUNET_new (struct RequestHandle); |
2510 | struct GNUNET_REST_RequestHandlerError err; | ||
2511 | static const struct GNUNET_REST_RequestHandler handlers[] = | ||
2512 | { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint }, | ||
2513 | { MHD_HTTP_METHOD_POST, | ||
2514 | GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint }, // url-encoded | ||
2515 | { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont }, | ||
2516 | { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint }, | ||
2517 | { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint }, | ||
2518 | { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint }, | ||
2519 | { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_OIDC_CONFIG, | ||
2520 | &oidc_config_endpoint }, | ||
2521 | { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC_CONFIG, | ||
2522 | &oidc_config_cors }, | ||
2523 | { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont }, | ||
2524 | GNUNET_REST_HANDLER_END }; | ||
2423 | 2525 | ||
2424 | handle->oidc = GNUNET_new (struct OIDC_Variables); | 2526 | handle->oidc = GNUNET_new (struct OIDC_Variables); |
2425 | if (NULL == OIDC_cookie_jar_map) | 2527 | if (NULL == OIDC_cookie_jar_map) |
2426 | OIDC_cookie_jar_map = GNUNET_CONTAINER_multihashmap_create (10, | 2528 | OIDC_cookie_jar_map = GNUNET_CONTAINER_multihashmap_create (10, |
2427 | GNUNET_NO); | 2529 | GNUNET_NO); |
2428 | if (NULL == OIDC_access_token_map) | ||
2429 | OIDC_access_token_map = | ||
2430 | GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO); | ||
2431 | handle->response_code = 0; | 2530 | handle->response_code = 0; |
2432 | handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; | 2531 | handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; |
2433 | handle->proc_cls = proc_cls; | 2532 | handle->proc_cls = proc_cls; |
2434 | handle->proc = proc; | 2533 | handle->proc = proc; |
2435 | handle->state = ID_REST_STATE_INIT; | ||
2436 | handle->rest_handle = rest_handle; | 2534 | handle->rest_handle = rest_handle; |
2437 | |||
2438 | handle->url = GNUNET_strdup (rest_handle->url); | 2535 | handle->url = GNUNET_strdup (rest_handle->url); |
2439 | if (handle->url[strlen (handle->url) - 1] == '/') | 2536 | if (handle->url[strlen (handle->url) - 1] == '/') |
2440 | handle->url[strlen (handle->url) - 1] = '\0'; | 2537 | handle->url[strlen (handle->url) - 1] = '\0'; |
2441 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n"); | 2538 | if (GNUNET_NO == |
2442 | handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, handle); | 2539 | GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle)) |
2443 | handle->gns_handle = GNUNET_GNS_connect (cfg); | 2540 | return GNUNET_NO; |
2444 | handle->namestore_handle = GNUNET_NAMESTORE_connect (cfg); | 2541 | |
2445 | handle->timeout_task = | 2542 | handle->timeout_task = |
2446 | GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle); | 2543 | GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle); |
2447 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n"); | 2544 | return GNUNET_YES; |
2448 | } | 2545 | } |
2449 | 2546 | ||
2450 | 2547 | ||
@@ -2469,6 +2566,11 @@ libgnunet_plugin_rest_openid_connect_init (void *cls) | |||
2469 | api->cls = &plugin; | 2566 | api->cls = &plugin; |
2470 | api->name = GNUNET_REST_API_NS_OIDC; | 2567 | api->name = GNUNET_REST_API_NS_OIDC; |
2471 | api->process_request = &rest_identity_process_request; | 2568 | api->process_request = &rest_identity_process_request; |
2569 | identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL); | ||
2570 | gns_handle = GNUNET_GNS_connect (cfg); | ||
2571 | idp = GNUNET_RECLAIM_connect (cfg); | ||
2572 | |||
2573 | state = ID_REST_STATE_INIT; | ||
2472 | GNUNET_asprintf (&allow_methods, | 2574 | GNUNET_asprintf (&allow_methods, |
2473 | "%s, %s, %s, %s, %s", | 2575 | "%s, %s, %s, %s, %s", |
2474 | MHD_HTTP_METHOD_GET, | 2576 | MHD_HTTP_METHOD_GET, |
@@ -2494,6 +2596,7 @@ libgnunet_plugin_rest_openid_connect_done (void *cls) | |||
2494 | { | 2596 | { |
2495 | struct GNUNET_REST_Plugin *api = cls; | 2597 | struct GNUNET_REST_Plugin *api = cls; |
2496 | struct Plugin *plugin = api->cls; | 2598 | struct Plugin *plugin = api->cls; |
2599 | struct EgoEntry *ego_entry; | ||
2497 | 2600 | ||
2498 | plugin->cfg = NULL; | 2601 | plugin->cfg = NULL; |
2499 | 2602 | ||
@@ -2508,15 +2611,23 @@ libgnunet_plugin_rest_openid_connect_done (void *cls) | |||
2508 | GNUNET_CONTAINER_multihashmap_iterator_destroy (hashmap_it); | 2611 | GNUNET_CONTAINER_multihashmap_iterator_destroy (hashmap_it); |
2509 | GNUNET_CONTAINER_multihashmap_destroy (OIDC_cookie_jar_map); | 2612 | GNUNET_CONTAINER_multihashmap_destroy (OIDC_cookie_jar_map); |
2510 | 2613 | ||
2511 | hashmap_it = | ||
2512 | GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_access_token_map); | ||
2513 | while (GNUNET_YES == | ||
2514 | GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, | ||
2515 | value)) | ||
2516 | GNUNET_free (value); | ||
2517 | GNUNET_CONTAINER_multihashmap_destroy (OIDC_access_token_map); | ||
2518 | GNUNET_CONTAINER_multihashmap_iterator_destroy (hashmap_it); | 2614 | GNUNET_CONTAINER_multihashmap_iterator_destroy (hashmap_it); |
2519 | GNUNET_free (allow_methods); | 2615 | GNUNET_free (allow_methods); |
2616 | if (NULL != gns_handle) | ||
2617 | GNUNET_GNS_disconnect (gns_handle); | ||
2618 | if (NULL != identity_handle) | ||
2619 | GNUNET_IDENTITY_disconnect (identity_handle); | ||
2620 | if (NULL != idp) | ||
2621 | GNUNET_RECLAIM_disconnect (idp); | ||
2622 | while (NULL != (ego_entry = ego_head)) | ||
2623 | { | ||
2624 | GNUNET_CONTAINER_DLL_remove (ego_head, | ||
2625 | ego_tail, | ||
2626 | ego_entry); | ||
2627 | GNUNET_free (ego_entry->identifier); | ||
2628 | GNUNET_free (ego_entry->keystring); | ||
2629 | GNUNET_free (ego_entry); | ||
2630 | } | ||
2520 | GNUNET_free (api); | 2631 | GNUNET_free (api); |
2521 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2632 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
2522 | "OpenID Connect REST plugin is finished\n"); | 2633 | "OpenID Connect REST plugin is finished\n"); |