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