GNUnet 0.22.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#include "openid_plugin.h"
44
48#define GNUNET_REST_API_NS_OIDC "/openid"
49
53#define GNUNET_REST_API_NS_OIDC_CONFIG "/.well-known/openid-configuration"
54
58#define GNUNET_REST_API_NS_AUTHORIZE "/openid/authorize"
59
63#define GNUNET_REST_API_NS_TOKEN "/openid/token"
64
68#define GNUNET_REST_API_JWKS "/jwks.json"
69
73#define GNUNET_REST_API_NS_USERINFO "/openid/userinfo"
74
78#define GNUNET_REST_API_NS_LOGIN "/openid/login"
79
83#define ID_REST_STATE_INIT 0
84
88#define ID_REST_STATE_POST_INIT 1
89
93#define OIDC_GRANT_TYPE_KEY "grant_type"
94
98#define OIDC_GRANT_TYPE_VALUE "authorization_code"
99
103#define OIDC_CODE_KEY "code"
104
108#define OIDC_RESPONSE_TYPE_KEY "response_type"
109
113#define OIDC_CLIENT_ID_KEY "client_id"
114
118#define OIDC_SCOPE_KEY "scope"
119
123#define OIDC_REDIRECT_URI_KEY "redirect_uri"
124
128#define OIDC_STATE_KEY "state"
129
133#define OIDC_NONCE_KEY "nonce"
134
138#define OIDC_CLAIMS_KEY "claims"
139
143#define OIDC_CODE_CHALLENGE_KEY "code_challenge"
144
148#define OIDC_CODE_VERIFIER_KEY "code_verifier"
149
153#define OIDC_COOKIE_EXPIRATION 3
154
158#define OIDC_COOKIE_HEADER_KEY "cookie"
159
163#define OIDC_AUTHORIZATION_HEADER_KEY "authorization"
164
168#define OIDC_COOKIE_HEADER_INFORMATION_KEY "Identity="
169
173#define OIDC_COOKIE_HEADER_ACCESS_DENIED "Identity=Denied"
174
178#define OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE "code"
179
183#define OIDC_EXPECTED_AUTHORIZATION_SCOPE "openid"
184
188#define OIDC_ERROR_KEY_INVALID_CLIENT "invalid_client"
189
193#define OIDC_ERROR_KEY_INVALID_SCOPE "invalid_scope"
194
198#define OIDC_ERROR_KEY_INVALID_REQUEST "invalid_request"
199
203#define OIDC_ERROR_KEY_INVALID_TOKEN "invalid_token"
204
208#define OIDC_ERROR_KEY_INVALID_COOKIE "invalid_cookie"
209
213#define OIDC_ERROR_KEY_SERVER_ERROR "server_error"
214
218#define OIDC_ERROR_KEY_UNSUPPORTED_GRANT_TYPE "unsupported_grant_type"
219
223#define OIDC_ERROR_KEY_UNSUPPORTED_RESPONSE_TYPE "unsupported_response_type"
224
228#define OIDC_ERROR_KEY_UNAUTHORIZED_CLIENT "unauthorized_client"
229
233#define OIDC_ERROR_KEY_ACCESS_DENIED "access_denied"
234
238#define OIDC_JWK_RSA_FILENAME "jwk_rsa.json"
239
243#define CONSUME_TIMEOUT GNUNET_TIME_relative_multiply ( \
244 GNUNET_TIME_UNIT_SECONDS,2)
245
249static const char *OIDC_ignored_parameter_array[] = { "display",
250 "prompt",
251 "ui_locales",
252 "response_mode",
253 "id_token_hint",
254 "login_hint",
255 "acr_values" };
256
261
266
271
275static char *allow_methods;
276
280static struct EgoEntry *ego_head;
281
285static struct EgoEntry *ego_tail;
286
290static int state;
291
296
301
306
311
315struct Plugin
316{
317 const struct GNUNET_CONFIGURATION_Handle *cfg;
318};
319
323json_t *oidc_jwk;
324
329{
334
339
344
348 char *scope;
349
353 char *state;
354
358 char *nonce;
359
363 char *claims;
364
369
374
379
384
389
390};
391
395struct EgoEntry
396{
400 struct EgoEntry *next;
401
405 struct EgoEntry *prev;
406
410 char *identifier;
411
415 char *keystring;
416
420 struct GNUNET_IDENTITY_Ego *ego;
421};
422
423
424struct RequestHandle
425{
429 struct RequestHandle *next;
430
434 struct RequestHandle *prev;
435
439 struct EgoEntry *ego_entry;
440
445
450
455
460
465
470
475
480
485
486
491
496
501
506
507
512
517
522
527
532
536 void *proc_cls;
537
541 char *url;
542
547
551 char *tld;
552
557
562
566 char *emsg;
567
571 char *edesc;
572
576 int response_code;
577
582};
583
588
593
594
599static void
601{
602
603 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
604 if (NULL != handle->timeout_task)
605 GNUNET_SCHEDULER_cancel (handle->timeout_task);
606 if (NULL != handle->attr_it)
608 if (NULL != handle->cred_it)
610 if (NULL != handle->ticket_it)
612 if (NULL != handle->idp_op)
614 if (NULL != handle->consume_timeout_op)
615 GNUNET_SCHEDULER_cancel (handle->consume_timeout_op);
616 GNUNET_free (handle->url);
617 GNUNET_free (handle->tld);
618 GNUNET_free (handle->redirect_prefix);
619 GNUNET_free (handle->redirect_suffix);
620 GNUNET_free (handle->emsg);
621 GNUNET_free (handle->edesc);
622 if (NULL != handle->gns_op)
624 if (NULL != handle->oidc)
625 {
626 GNUNET_free (handle->oidc->client_id);
627 GNUNET_free (handle->oidc->login_identity);
628 GNUNET_free (handle->oidc->nonce);
629 GNUNET_free (handle->oidc->redirect_uri);
630 GNUNET_free (handle->oidc->response_type);
631 GNUNET_free (handle->oidc->scope);
632 GNUNET_free (handle->oidc->state);
633 if (NULL != handle->oidc->claims)
634 GNUNET_free (handle->oidc->claims);
635 if (NULL != handle->oidc->code_challenge)
636 GNUNET_free (handle->oidc->code_challenge);
637 GNUNET_free (handle->oidc);
638 }
639 if (NULL!=handle->attr_idtoken_list)
641 if (NULL!=handle->attr_userinfo_list)
642 GNUNET_RECLAIM_attribute_list_destroy (handle->attr_userinfo_list);
643 if (NULL!=handle->credentials)
645 if (NULL!=handle->presentations)
649 handle);
650 if (NULL != handle->access_token)
651 GNUNET_free (handle->access_token);
653}
654
655
661static void
662do_error (void *cls)
663{
664 struct RequestHandle *handle = cls;
665 struct MHD_Response *resp;
666 char *json_error;
667
668 GNUNET_asprintf (&json_error,
669 "{ \"error\" : \"%s\", \"error_description\" : \"%s\"%s%s%s}",
670 handle->emsg,
671 (NULL != handle->edesc) ? handle->edesc : "",
672 (NULL != handle->oidc->state) ? ", \"state\":\"" : "",
673 (NULL != handle->oidc->state) ? handle->oidc->state : "",
674 (NULL != handle->oidc->state) ? "\"" : "");
675 if (0 == handle->response_code)
676 handle->response_code = MHD_HTTP_BAD_REQUEST;
677 resp = GNUNET_REST_create_response (json_error);
678 if (MHD_HTTP_UNAUTHORIZED == handle->response_code)
679 GNUNET_assert (MHD_NO !=
680 MHD_add_response_header (resp,
681 MHD_HTTP_HEADER_WWW_AUTHENTICATE,
682 "Basic"));
683 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
684 MHD_HTTP_HEADER_CONTENT_TYPE,
685 "application/json"));
686 handle->proc (handle->proc_cls, resp, handle->response_code);
688 GNUNET_free (json_error);
689}
690
691
698static void
700{
701 struct RequestHandle *handle = cls;
702 struct MHD_Response *resp;
703 char *error;
704
706 "Error: %s\n", handle->edesc);
707 GNUNET_asprintf (&error,
708 "error=\"%s\", error_description=\"%s\"",
709 handle->emsg,
710 (NULL != handle->edesc) ? handle->edesc : "");
711 resp = GNUNET_REST_create_response ("");
712 GNUNET_assert (MHD_NO !=
713 MHD_add_response_header (resp,
714 MHD_HTTP_HEADER_WWW_AUTHENTICATE,
715 "Bearer"));
716 handle->proc (handle->proc_cls, resp, handle->response_code);
718 GNUNET_free (error);
719}
720
721
727static void
729{
730 struct RequestHandle *handle = cls;
731 struct MHD_Response *resp;
732 char *redirect;
733
734 GNUNET_asprintf (&redirect,
735 "%s?error=%s&error_description=%s%s%s",
736 handle->oidc->redirect_uri,
737 handle->emsg,
738 handle->edesc,
739 (NULL != handle->oidc->state) ? "&state=" : "",
740 (NULL != handle->oidc->state) ? handle->oidc->state : "");
741 resp = GNUNET_REST_create_response ("");
742 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
743 "Location", redirect));
744 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
746 GNUNET_free (redirect);
747}
748
749
755static void
756do_timeout (void *cls)
757{
758 struct RequestHandle *handle = cls;
759
760 handle->timeout_task = NULL;
762}
763
764
772static void
774 const char *url,
775 void *cls)
776{
777 struct MHD_Response *resp;
778 struct RequestHandle *handle = cls;
779
780 // For now, independent of path return all options
781 resp = GNUNET_REST_create_response (NULL);
782 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
783 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
785 return;
786}
787
788
792static void
794{
795 struct GNUNET_HashCode cache_key;
796 char *cookies;
797 struct GNUNET_TIME_Absolute current_time, *relog_time;
798 char delimiter[] = "; ";
799 char *tmp_cookies;
800 char *token;
801 char *value;
802
803 // gets identity of login try with cookie
805 strlen (OIDC_COOKIE_HEADER_KEY),
806 &cache_key);
808 ->header_param_map,
809 &cache_key))
810 {
811 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No cookie found\n");
812 return;
813 }
814 // splits cookies and find 'Identity' cookie
815 tmp_cookies =
816 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
817 &cache_key);
818 cookies = GNUNET_strdup (tmp_cookies);
819 token = strtok (cookies, delimiter);
820 handle->oidc->user_cancelled = GNUNET_NO;
821 handle->oidc->login_identity = NULL;
822 if (NULL == token)
823 {
825 "Unable to parse cookie: %s\n",
826 cookies);
827 GNUNET_free (cookies);
828 return;
829 }
830
831 while (NULL != token)
832 {
833 if (0 == strcmp (token, OIDC_COOKIE_HEADER_ACCESS_DENIED))
834 {
835 handle->oidc->user_cancelled = GNUNET_YES;
836 GNUNET_free (cookies);
837 return;
838 }
839 if (NULL != strstr (token, OIDC_COOKIE_HEADER_INFORMATION_KEY))
840 break;
841 token = strtok (NULL, delimiter);
842 }
843 if (NULL == token)
844 {
846 "No cookie value to process: %s\n",
847 cookies);
848 GNUNET_free (cookies);
849 return;
850 }
851 GNUNET_CRYPTO_hash (token, strlen (token), &cache_key);
852 if (GNUNET_NO ==
854 {
855 GNUNET_log (
857 "Found cookie `%s', but no corresponding expiration entry present...\n",
858 token);
859 GNUNET_free (cookies);
860 return;
861 }
862 relog_time =
864 current_time = GNUNET_TIME_absolute_get ();
865 // 30 min after old login -> redirect to login
866 if (current_time.abs_value_us > relog_time->abs_value_us)
867 {
869 "Found cookie `%s', but it is expired.\n",
870 token);
871 GNUNET_free (cookies);
872 return;
873 }
875 GNUNET_assert (NULL != value);
876 handle->oidc->login_identity = GNUNET_strdup (value);
877 GNUNET_free (cookies);
878}
879
880
889static json_t *
891{
892 json_t *jwk;
893 json_error_t error;
894
895 jwk = json_load_file (filename, JSON_DECODE_ANY, &error);
896
897 if (! jwk)
898 {
900 ("Could not read OIDC RSA key from config file; %s\n"),
901 error.text);
902 }
903
904 return jwk;
905}
906
907
915static int
917 json_t *jwk)
918{
919 if (json_dump_file (jwk, filename, JSON_INDENT (2)))
920 {
922 ("Could not write OIDC RSA key to file %s\n"),
923 filename);
925 }
926 else
927 return GNUNET_OK;
928}
929
930
936static json_t *
938{
939 json_t *jwk;
940 jwk = json_pack ("{s:s,s:i}", "kty", "RSA", "bits", 2048);
941 jose_jwk_gen (NULL, jwk);
942 json_incref (jwk);
943 return jwk;
944}
945
946
952static char *
954{
955 char *oidc_directory;
956 struct RequestHandle *handle = cls;
957
958 // Read OIDC directory from config
960 "reclaim-rest-plugin",
961 "oidc_dir",
962 &oidc_directory))
963 {
964 // Could not read Config file
966 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
967 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
969 return NULL;
970 }
971
972 return oidc_directory;
973}
974
975
981static char *
983{
984 char *oidc_directory;
985 char *oidc_jwk_path;
986
987 oidc_directory = get_oidc_dir_path (cls);
988
989 // Create path to file
990 GNUNET_asprintf (&oidc_jwk_path, "%s/%s", oidc_directory,
992
993 return oidc_jwk_path;
994}
995
996
1000static void
1002{
1003 char *login_base_url;
1004 char *new_redirect;
1005 char *tmp;
1006 struct MHD_Response *resp;
1007 struct GNUNET_Buffer buf = { 0 };
1008 struct RequestHandle *handle = cls;
1009
1011 "reclaim-rest-plugin",
1012 "address",
1013 &login_base_url))
1014 {
1015 GNUNET_buffer_write_str (&buf, login_base_url);
1017 "?%s=%s",
1019 handle->oidc->response_type);
1021 "&%s=%s",
1023 handle->oidc->client_id);
1024 GNUNET_STRINGS_urlencode (strlen (handle->oidc->redirect_uri),
1025 handle->oidc->redirect_uri,
1026 &tmp);
1028 "&%s=%s",
1030 tmp);
1031 GNUNET_free (tmp);
1032 GNUNET_STRINGS_urlencode (strlen (handle->oidc->scope),
1033 handle->oidc->scope,
1034 &tmp);
1036 "&%s=%s",
1038 tmp);
1039 GNUNET_free (tmp);
1040 if (NULL != handle->oidc->state)
1041 {
1042 GNUNET_STRINGS_urlencode (strlen (handle->oidc->state),
1043 handle->oidc->state,
1044 &tmp);
1046 "&%s=%s",
1048 handle->oidc->state);
1049 GNUNET_free (tmp);
1050 }
1051 if (NULL != handle->oidc->code_challenge)
1052 {
1054 "&%s=%s",
1056 handle->oidc->code_challenge);
1057 }
1058 if (NULL != handle->oidc->nonce)
1059 {
1061 "&%s=%s",
1063 handle->oidc->nonce);
1064 }
1065 if (NULL != handle->oidc->claims)
1066 {
1067 GNUNET_STRINGS_urlencode (strlen (handle->oidc->claims),
1068 handle->oidc->claims,
1069 &tmp);
1071 "&%s=%s",
1073 tmp);
1074 GNUNET_free (tmp);
1075 }
1076 new_redirect = GNUNET_buffer_reap_str (&buf);
1077 resp = GNUNET_REST_create_response ("");
1078 MHD_add_response_header (resp, "Location", new_redirect);
1079 GNUNET_free (login_base_url);
1080 }
1081 else
1082 {
1084 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
1085 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1087 return;
1088 }
1089 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1090 GNUNET_free (new_redirect);
1092}
1093
1094
1098static void
1100{
1101 struct RequestHandle *handle = cls;
1102
1104 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1106}
1107
1108
1113static void
1115 const struct GNUNET_RECLAIM_Ticket *ticket,
1116 const struct
1117 GNUNET_RECLAIM_PresentationList *presentation)
1118{
1119 struct RequestHandle *handle = cls;
1120 struct MHD_Response *resp;
1121 char *ticket_str;
1122 char *redirect_uri;
1123 char *code_string;
1124
1125 handle->idp_op = NULL;
1126 if (NULL == ticket)
1127 {
1129 handle->edesc = GNUNET_strdup ("Server cannot generate ticket.");
1131 return;
1132 }
1133 handle->ticket = *ticket;
1134 ticket_str =
1136 sizeof(struct GNUNET_RECLAIM_Ticket));
1137 code_string = OIDC_build_authz_code (&handle->priv_key,
1138 &handle->ticket,
1139 handle->attr_idtoken_list,
1140 presentation,
1141 handle->oidc->nonce,
1142 handle->oidc->code_challenge);
1143 if ((NULL != handle->redirect_prefix) && (NULL != handle->redirect_suffix) &&
1144 (NULL != handle->tld))
1145 {
1146 GNUNET_asprintf (&redirect_uri,
1147 "%s.%s/%s%s%s=%s&state=%s",
1148 handle->redirect_prefix,
1149 handle->tld,
1150 handle->redirect_suffix,
1151 (NULL == strchr (handle->redirect_suffix, '?') ? "?" :
1152 "&"),
1153 handle->oidc->response_type,
1154 code_string,
1155 handle->oidc->state);
1156 }
1157 else
1158 {
1159 GNUNET_asprintf (&redirect_uri,
1160 "%s%s%s=%s&state=%s",
1161 handle->oidc->redirect_uri,
1162 (NULL == strchr (handle->oidc->redirect_uri, '?') ? "?" :
1163 "&"),
1164 handle->oidc->response_type,
1165 code_string,
1166 handle->oidc->state);
1167 }
1168 resp = GNUNET_REST_create_response ("");
1169 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1170 "Location", redirect_uri));
1171 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1173 GNUNET_free (redirect_uri);
1174 GNUNET_free (ticket_str);
1175 GNUNET_free (code_string);
1176}
1177
1178
1179static struct GNUNET_RECLAIM_AttributeList*
1181 struct GNUNET_RECLAIM_AttributeList *list_b)
1182{
1183 struct GNUNET_RECLAIM_AttributeList *merged_list;
1187
1188 merged_list = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
1189 for (le_a = list_a->list_head; NULL != le_a; le_a = le_a->next)
1190 {
1193 &le_a->attribute->
1194 credential,
1195 le_a->attribute->type,
1196 le_a->attribute->data,
1197 le_a->attribute->data_size);
1198 le_m->attribute->id = le_a->attribute->id;
1199 le_m->attribute->flag = le_a->attribute->flag;
1200 le_m->attribute->credential = le_a->attribute->credential;
1202 merged_list->list_tail,
1203 le_m);
1204 }
1205 le_m = NULL;
1206 for (le_b = list_b->list_head; NULL != le_b; le_b = le_b->next)
1207 {
1208 for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1209 {
1211 &le_b->attribute->id))
1212 break;
1213 }
1214 if (NULL != le_m)
1215 continue;
1218 &le_b->attribute->
1219 credential,
1220 le_b->attribute->type,
1221 le_b->attribute->data,
1222 le_b->attribute->data_size);
1223 le_m->attribute->id = le_b->attribute->id;
1224 le_m->attribute->flag = le_b->attribute->flag;
1225 le_m->attribute->credential = le_b->attribute->credential;
1227 merged_list->list_tail,
1228 le_m);
1229 }
1230 return merged_list;
1231}
1232
1233
1234static void
1236{
1237 struct RequestHandle *handle = cls;
1238 struct GNUNET_RECLAIM_AttributeList *merged_list;
1240
1241 handle->cred_it = NULL;
1242 merged_list = attribute_list_merge (handle->attr_idtoken_list,
1243 handle->attr_userinfo_list);
1244 for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1246 "List Attribute in ticket to issue: %s\n",
1247 le_m->attribute->name);
1249 &handle->priv_key,
1250 handle->oidc->client_id,
1251 merged_list,
1253 handle);
1255}
1256
1257
1261static void
1263 const struct GNUNET_CRYPTO_PublicKey *identity,
1264 const struct GNUNET_RECLAIM_Credential *cred)
1265{
1266 struct RequestHandle *handle = cls;
1269
1270 for (ale = handle->credentials->list_head; NULL != ale; ale = ale->next)
1271 {
1273 &cred->id))
1274 continue;
1277 return;
1278 }
1279
1280 for (le = handle->attr_idtoken_list->list_head; NULL != le; le = le->next)
1281 {
1283 &cred->id))
1284 continue;
1288 cred->type,
1289 cred->data,
1290 cred->data_size);
1291 GNUNET_CONTAINER_DLL_insert (handle->credentials->list_head,
1292 handle->credentials->list_tail,
1293 ale);
1294 }
1296}
1297
1298
1299static void
1301{
1302 struct RequestHandle *handle = cls;
1303
1304 handle->attr_it = NULL;
1305 handle->ticket_it = NULL;
1306 if (NULL == handle->attr_idtoken_list->list_head)
1307 {
1309 handle->edesc = GNUNET_strdup ("The requested scope is not available.");
1311 return;
1312 }
1313 handle->credentials = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
1314 handle->cred_it =
1316 &handle->priv_key,
1318 handle,
1320 handle,
1322 handle);
1323
1324}
1325
1326
1327static int
1329 const char *attr_name,
1330 const char *claims_parameter)
1331{
1332 int ret = GNUNET_NO;
1333 json_t *root;
1334 json_error_t error;
1335 json_t *claims_j;
1336 const char *key;
1337 json_t *value;
1338
1341 attr_name))
1342 return GNUNET_YES;
1343
1345 if (NULL != handle->oidc->claims)
1346 {
1347 root = json_loads (handle->oidc->claims, JSON_DECODE_ANY, &error);
1348 claims_j = json_object_get (root, claims_parameter);
1349 /* obj is a JSON object */
1350 if (NULL != claims_j)
1351 {
1352 json_object_foreach (claims_j, key, value) {
1353 if (0 != strcmp (attr_name, key))
1354 continue;
1355 ret = GNUNET_YES;
1356 break;
1357 }
1358 }
1359 json_decref (root);
1360 }
1361 return ret;
1362}
1363
1364
1365static int
1367 const char *attr_name)
1368{
1369 return attr_in_claims_request (handle, attr_name, "id_token");
1370}
1371
1372
1373static int
1375 const char *attr_name)
1376{
1377 return attr_in_claims_request (handle, attr_name, "userinfo");
1378}
1379
1380
1384static void
1386 const struct GNUNET_CRYPTO_PublicKey *identity,
1387 const struct GNUNET_RECLAIM_Attribute *attr)
1388{
1389 struct RequestHandle *handle = cls;
1392 {
1395 &attr->credential,
1396 attr->type,
1397 attr->data,
1398 attr->data_size);
1399 le->attribute->id = attr->id;
1400 le->attribute->flag = attr->flag;
1401 le->attribute->credential = attr->credential;
1402 GNUNET_CONTAINER_DLL_insert (handle->attr_idtoken_list->list_head,
1403 handle->attr_idtoken_list->list_tail,
1404 le);
1405 }
1407 {
1410 &attr->credential,
1411 attr->type,
1412 attr->data,
1413 attr->data_size);
1414 le->attribute->id = attr->id;
1415 le->attribute->flag = attr->flag;
1416 le->attribute->credential = attr->credential;
1417 GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
1418 handle->attr_userinfo_list->list_tail,
1419 le);
1420 }
1421
1423}
1424
1425
1429static void
1430code_redirect (void *cls)
1431{
1432 struct RequestHandle *handle = cls;
1433 struct GNUNET_TIME_Absolute current_time;
1434 struct GNUNET_TIME_Absolute *relog_time;
1436 struct GNUNET_CRYPTO_PublicKey ego_pkey;
1437 struct GNUNET_HashCode cache_key;
1438 char *identity_cookie;
1439
1440 GNUNET_asprintf (&identity_cookie,
1441 "Identity=%s",
1442 handle->oidc->login_identity);
1443 GNUNET_CRYPTO_hash (identity_cookie, strlen (identity_cookie), &cache_key);
1444 GNUNET_free (identity_cookie);
1445 // No login time for identity -> redirect to login
1446 if (GNUNET_YES ==
1448 {
1449 relog_time =
1451 current_time = GNUNET_TIME_absolute_get ();
1452 // 30 min after old login -> redirect to login
1453 if (current_time.abs_value_us <= relog_time->abs_value_us)
1454 {
1455 if (GNUNET_OK !=
1457 ->login_identity,
1458 &pubkey))
1459 {
1461 handle->edesc =
1462 GNUNET_strdup ("The cookie of a login identity is not valid");
1464 return;
1465 }
1466 // iterate over egos and compare their public key
1467 for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
1468 handle->ego_entry = handle->ego_entry->next)
1469 {
1470 GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey);
1471 if (0 == GNUNET_memcmp (&ego_pkey, &pubkey))
1472 {
1473 handle->priv_key =
1475 handle->attr_idtoken_list =
1477 handle->attr_userinfo_list =
1479 handle->attr_it =
1481 &handle->priv_key,
1483 handle,
1485 handle,
1487 handle);
1488 return;
1489 }
1490 }
1492 return;
1493 }
1494 }
1495}
1496
1497
1498static void
1500{
1501 struct RequestHandle *handle = cls;
1502 struct MHD_Response *resp;
1503 char *redirect_uri;
1504
1505 if (GNUNET_YES == handle->oidc->user_cancelled)
1506 {
1507 if ((NULL != handle->redirect_prefix) &&
1508 (NULL != handle->redirect_suffix) && (NULL != handle->tld))
1509 {
1510 GNUNET_asprintf (&redirect_uri,
1511 "%s.%s/%s?error=%s&error_description=%s&state=%s",
1512 handle->redirect_prefix,
1513 handle->tld,
1514 handle->redirect_suffix,
1515 "access_denied",
1516 "User denied access",
1517 handle->oidc->state);
1518 }
1519 else
1520 {
1521 GNUNET_asprintf (&redirect_uri,
1522 "%s?error=%s&error_description=%s&state=%s",
1523 handle->oidc->redirect_uri,
1524 "access_denied",
1525 "User denied access",
1526 handle->oidc->state);
1527 }
1528 resp = GNUNET_REST_create_response ("");
1529 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1530 "Location",
1531 redirect_uri));
1532 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1534 GNUNET_free (redirect_uri);
1535 return;
1536 }
1538}
1539
1540
1541static void
1543 uint32_t rd_count,
1544 const struct GNUNET_GNSRECORD_Data *rd)
1545{
1546 struct RequestHandle *handle = cls;
1547 char *tmp;
1548 char *tmp_key_str;
1549 char *pos;
1550 struct GNUNET_CRYPTO_PublicKey redirect_zone;
1551
1552 handle->gns_op = NULL;
1553 if (0 == rd_count)
1554 {
1556 handle->edesc =
1557 GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1559 return;
1560 }
1561 for (int i = 0; i < rd_count; i++)
1562 {
1563 if (GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT != rd[i].record_type)
1564 continue;
1565 if (0 != strncmp (rd[i].data, handle->oidc->redirect_uri, rd[i].data_size))
1566 continue;
1567 tmp = GNUNET_strndup (rd[i].data, rd[i].data_size);
1568 if (NULL == strstr (tmp, handle->oidc->client_id))
1569 {
1571 "Redirect uri %s does not contain client_id %s\n",
1572 tmp,
1573 handle->oidc->client_id);
1574 }
1575 else
1576 {
1577 pos = strrchr (tmp, (unsigned char) '.');
1578 if (NULL == pos)
1579 {
1581 "Redirect uri %s contains client_id but is malformed\n",
1582 tmp);
1583 GNUNET_free (tmp);
1584 continue;
1585 }
1586 *pos = '\0';
1587 handle->redirect_prefix = GNUNET_strdup (tmp);
1588 tmp_key_str = pos + 1;
1589 pos = strchr (tmp_key_str, (unsigned char) '/');
1590 if (NULL == pos)
1591 {
1593 "Redirect uri %s contains client_id but is malformed\n",
1594 tmp);
1595 GNUNET_free (tmp);
1596 continue;
1597 }
1598 *pos = '\0';
1599 handle->redirect_suffix = GNUNET_strdup (pos + 1);
1600
1601 GNUNET_STRINGS_string_to_data (tmp_key_str,
1602 strlen (tmp_key_str),
1603 &redirect_zone,
1604 sizeof(redirect_zone));
1605 }
1607 GNUNET_free (tmp);
1608 return;
1609 }
1611 handle->edesc =
1612 GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1614}
1615
1616
1620static void
1622{
1623 struct RequestHandle *handle = cls;
1624
1625 /* Lookup client redirect uri to verify request */
1626 handle->gns_op =
1629 &handle->oidc->client_pkey,
1633 handle);
1634}
1635
1636
1637static char *
1639{
1640 struct GNUNET_HashCode hc;
1641 char *value;
1642 char *res;
1643
1644 GNUNET_CRYPTO_hash (key, strlen (key), &hc);
1646 ->url_param_map,
1647 &hc))
1648 return NULL;
1649 value =
1650 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, &hc);
1651 if (NULL == value)
1652 return NULL;
1654 return res;
1655}
1656
1657
1664static void
1666{
1667 struct RequestHandle *handle = cls;
1668 struct GNUNET_HashCode cache_key;
1669
1670 char *expected_scope;
1671 char delimiter[] = " ";
1672 char *test;
1673 int number_of_ignored_parameter, iterator;
1674
1675
1676 // REQUIRED value: redirect_uri
1677 handle->oidc->redirect_uri =
1679 if (NULL == handle->oidc->redirect_uri)
1680 {
1682 handle->edesc = GNUNET_strdup ("missing parameter redirect_uri");
1684 return;
1685 }
1686
1687 // REQUIRED value: response_type
1688 handle->oidc->response_type =
1690 if (NULL == handle->oidc->response_type)
1691 {
1693 handle->edesc = GNUNET_strdup ("missing parameter response_type");
1695 return;
1696 }
1697
1698 // REQUIRED value: scope
1700 if (NULL == handle->oidc->scope)
1701 {
1703 handle->edesc = GNUNET_strdup ("missing parameter scope");
1705 return;
1706 }
1707
1708 // OPTIONAL value: nonce
1710
1711 // OPTIONAL value: claims
1713
1714 // TODO check other values if needed
1715 number_of_ignored_parameter =
1716 sizeof(OIDC_ignored_parameter_array) / sizeof(char *);
1717 for (iterator = 0; iterator < number_of_ignored_parameter; iterator++)
1718 {
1720 strlen (OIDC_ignored_parameter_array[iterator]),
1721 &cache_key);
1722 if (GNUNET_YES ==
1724 ->url_param_map,
1725 &cache_key))
1726 {
1728 GNUNET_asprintf (&handle->edesc,
1729 "Server will not handle parameter: %s",
1732 return;
1733 }
1734 }
1735
1736 // We only support authorization code flows.
1737 if (0 != strcmp (handle->oidc->response_type,
1739 {
1741 handle->edesc = GNUNET_strdup ("The authorization server does not support "
1742 "obtaining this authorization code.");
1744 return;
1745 }
1746
1747 // Checks if scope contains 'openid'
1748 expected_scope = GNUNET_strdup (handle->oidc->scope);
1749 test = strtok (expected_scope, delimiter);
1750 while (NULL != test)
1751 {
1752 if (0 == strcmp (OIDC_EXPECTED_AUTHORIZATION_SCOPE, expected_scope))
1753 break;
1754 test = strtok (NULL, delimiter);
1755 }
1756 if (NULL == test)
1757 {
1759 handle->edesc =
1760 GNUNET_strdup ("The requested scope is invalid, unknown, or malformed.");
1762 GNUNET_free (expected_scope);
1763 return;
1764 }
1765
1766 GNUNET_free (expected_scope);
1767 if ((NULL == handle->oidc->login_identity) &&
1768 (GNUNET_NO == handle->oidc->user_cancelled))
1770 else
1772}
1773
1774
1778static void
1779tld_iter (void *cls, const char *section, const char *option, const char *value)
1780{
1781 struct RequestHandle *handle = cls;
1783
1784 if (GNUNET_OK !=
1786 {
1787 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Skipping non key %s\n", value);
1788 return;
1789 }
1790 if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1791 handle->tld = GNUNET_strdup (option + 1);
1792}
1793
1794
1802static void
1804 const char *url,
1805 void *cls)
1806{
1807 struct RequestHandle *handle = cls;
1808 struct EgoEntry *tmp_ego;
1809 const struct GNUNET_CRYPTO_PrivateKey *priv_key;
1811
1813
1814 // RECOMMENDED value: state - REQUIRED for answers
1816
1817 // REQUIRED value: client_id
1819 if (NULL == handle->oidc->client_id)
1820 {
1822 handle->edesc = GNUNET_strdup ("missing parameter client_id");
1823 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1825 return;
1826 }
1827
1828 // OPTIONAL value: code_challenge
1829 handle->oidc->code_challenge = get_url_parameter_copy (handle,
1831 if (NULL == handle->oidc->code_challenge)
1832 {
1834 "OAuth authorization request does not contain PKCE parameters!\n");
1835 }
1836
1837 if (GNUNET_OK !=
1839 &handle->oidc->client_pkey))
1840 {
1842 handle->edesc = GNUNET_strdup ("The client is not authorized to request an "
1843 "authorization code using this method.");
1844 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1846 return;
1847 }
1848
1849 // If we know this identity, translated the corresponding TLD
1850 // TODO: We might want to have a reverse lookup functionality for TLDs?
1851 for (tmp_ego = ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next)
1852 {
1853 priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego);
1855 if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1856 {
1857 handle->tld = GNUNET_strdup (tmp_ego->identifier);
1858 handle->ego_entry = ego_tail;
1859 }
1860 }
1861 if (NULL == handle->tld)
1863 handle);
1864 if (NULL == handle->tld)
1865 handle->tld = GNUNET_strdup (handle->oidc->client_id);
1867}
1868
1869
1877static void
1879 const char *url,
1880 void *cls)
1881{
1882 struct MHD_Response *resp = GNUNET_REST_create_response ("");
1883 struct RequestHandle *handle = cls;
1884 struct GNUNET_HashCode cache_key;
1885 struct GNUNET_TIME_Absolute *current_time;
1886 struct GNUNET_TIME_Absolute *last_time;
1887 char *cookie;
1888 char *header_val;
1889 json_t *root;
1890 json_error_t error;
1891 json_t *identity;
1892 char term_data[handle->rest_handle->data_size + 1];
1893
1894 term_data[handle->rest_handle->data_size] = '\0';
1895 GNUNET_memcpy (term_data,
1896 handle->rest_handle->data,
1897 handle->rest_handle->data_size);
1898 root = json_loads (term_data, JSON_DECODE_ANY, &error);
1899 identity = json_object_get (root, "identity");
1900 if (! json_is_string (identity))
1901 {
1903 "Error parsing json string from %s\n",
1904 term_data);
1905 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
1906 json_decref (root);
1908 return;
1909 }
1910 GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity));
1911 GNUNET_asprintf (&header_val,
1912 "%s;Max-Age=%d",
1913 cookie,
1915 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1916 "Set-Cookie", header_val));
1917 GNUNET_assert (MHD_NO !=
1918 MHD_add_response_header (resp,
1919 "Access-Control-Allow-Methods",
1920 "POST"));
1921 GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key);
1922
1923 if (0 != strcmp (json_string_value (identity), "Denied"))
1924 {
1925 current_time = GNUNET_new (struct GNUNET_TIME_Absolute);
1926 *current_time = GNUNET_TIME_relative_to_absolute (
1929 last_time =
1931 GNUNET_free (last_time);
1933 &cache_key,
1934 current_time,
1936 }
1937 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1938 GNUNET_free (cookie);
1939 GNUNET_free (header_val);
1940 json_decref (root);
1942}
1943
1944
1945static int
1947 char **client_id,
1948 char **client_secret)
1949{
1950 struct GNUNET_HashCode cache_key;
1951 char *authorization;
1952 char *credentials;
1953 char *basic_authorization;
1954 char *client_id_tmp;
1955 char *pass;
1956
1959 &cache_key);
1961 ->header_param_map,
1962 &cache_key))
1963 return GNUNET_SYSERR;
1964 authorization =
1965 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
1966 &cache_key);
1967
1968 // split header in "Basic" and [content]
1969 credentials = strtok (authorization, " ");
1970 if ((NULL == credentials) || (0 != strcmp ("Basic", credentials)))
1971 return GNUNET_SYSERR;
1972 credentials = strtok (NULL, " ");
1973 if (NULL == credentials)
1974 return GNUNET_SYSERR;
1975 GNUNET_STRINGS_base64_decode (credentials,
1976 strlen (credentials),
1977 (void **) &basic_authorization);
1978
1979 if (NULL == basic_authorization)
1980 return GNUNET_SYSERR;
1981 client_id_tmp = strtok (basic_authorization, ":");
1982 if (NULL == client_id_tmp)
1983 {
1984 GNUNET_free (basic_authorization);
1985 return GNUNET_SYSERR;
1986 }
1987 pass = strtok (NULL, ":");
1988 if (NULL == pass)
1989 {
1990 GNUNET_free (basic_authorization);
1991 return GNUNET_SYSERR;
1992 }
1993 *client_id = strdup (client_id_tmp);
1994 *client_secret = strdup (pass);
1995 GNUNET_free (basic_authorization);
1996 return GNUNET_OK;
1997}
1998
1999
2000static int
2002 char **client_id,
2003 char **client_secret)
2004{
2005 struct GNUNET_HashCode cache_key;
2006 char *client_id_tmp;
2007 char *pass;
2008
2009 GNUNET_CRYPTO_hash ("client_id",
2010 strlen ("client_id"),
2011 &cache_key);
2013 ->url_param_map,
2014 &cache_key))
2015 return GNUNET_SYSERR;
2016 client_id_tmp = GNUNET_CONTAINER_multihashmap_get (
2017 handle->rest_handle->url_param_map,
2018 &cache_key);
2019 if (NULL == client_id_tmp)
2020 return GNUNET_SYSERR;
2021 *client_id = strdup (client_id_tmp);
2022 GNUNET_CRYPTO_hash ("client_secret",
2023 strlen ("client_secret"),
2024 &cache_key);
2026 ->url_param_map,
2027 &cache_key))
2028 {
2029 GNUNET_free (*client_id);
2030 *client_id = NULL;
2031 return GNUNET_SYSERR;
2032 }
2033 pass = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
2034 &cache_key);
2035 if (NULL == pass)
2036 {
2037 GNUNET_free (*client_id);
2038 *client_id = NULL;
2039 return GNUNET_SYSERR;
2040 }
2041 *client_secret = strdup (pass);
2042 return GNUNET_OK;
2043}
2044
2045
2046static int
2048 struct GNUNET_CRYPTO_PublicKey *cid)
2049{
2050 char *expected_pass;
2051 char *received_cid;
2052 char *received_cpw;
2053 char *pkce_cv;
2054
2056 &received_cid,
2057 &received_cpw))
2058 {
2060 "Received client credentials in HTTP AuthZ header\n");
2061 }
2063 &received_cid,
2064 &received_cpw))
2065 {
2067 "Received client credentials in POST body\n");
2068 }
2069 else
2070 {
2073 if (NULL == pkce_cv)
2074 {
2076 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2077 return GNUNET_SYSERR;
2078 }
2079 handle->public_client = GNUNET_YES;
2080 GNUNET_free (pkce_cv);
2082 GNUNET_STRINGS_string_to_data (received_cid,
2083 strlen (received_cid),
2084 cid,
2085 sizeof(struct GNUNET_CRYPTO_PublicKey));
2086 GNUNET_free (received_cid);
2087 return GNUNET_OK;
2088
2089 }
2090
2091 // check client password
2093 "reclaim-rest-plugin",
2094 "OIDC_CLIENT_HMAC_SECRET",
2095 &expected_pass))
2096 {
2097 if (0 != strcmp (expected_pass, received_cpw))
2098 {
2099 GNUNET_free (expected_pass);
2101 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2102 GNUNET_free (received_cpw);
2103 GNUNET_free (received_cid);
2104 return GNUNET_SYSERR;
2105 }
2106 GNUNET_free (expected_pass);
2107 }
2108 else
2109 {
2110 GNUNET_free (received_cpw);
2111 GNUNET_free (received_cid);
2113 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
2114 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2115 return GNUNET_SYSERR;
2116 }
2117 // check client_id
2118 for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
2119 handle->ego_entry = handle->ego_entry->next)
2120 {
2121 if (0 == strcmp (handle->ego_entry->keystring, received_cid))
2122 break;
2123 }
2124 if (NULL == handle->ego_entry)
2125 {
2126 GNUNET_free (received_cpw);
2127 GNUNET_free (received_cid);
2129 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2130 return GNUNET_SYSERR;
2131 }
2132 GNUNET_STRINGS_string_to_data (received_cid,
2133 strlen (received_cid),
2134 cid,
2135 sizeof(struct GNUNET_CRYPTO_PublicKey));
2136
2137 GNUNET_free (received_cpw);
2138 GNUNET_free (received_cid);
2139 return GNUNET_OK;
2140}
2141
2142
2143static const struct EgoEntry *
2145 struct GNUNET_CRYPTO_PublicKey *test_key)
2146{
2147 struct EgoEntry *ego_entry;
2148 struct GNUNET_CRYPTO_PublicKey pub_key;
2149
2150 for (ego_entry = ego_head; NULL != ego_entry;
2151 ego_entry = ego_entry->next)
2152 {
2153 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key);
2154 if (0 == GNUNET_memcmp (&pub_key, test_key))
2155 return ego_entry;
2156 }
2157 return NULL;
2158}
2159
2160
2168static void
2170 const char *url,
2171 void *cls)
2172{
2173 struct RequestHandle *handle = cls;
2174 const struct EgoEntry *ego_entry = NULL;
2175 struct GNUNET_TIME_Relative expiration_time;
2176 struct GNUNET_RECLAIM_AttributeList *cl = NULL;
2177 struct GNUNET_RECLAIM_PresentationList *pl = NULL;
2179 struct GNUNET_CRYPTO_PublicKey cid;
2180 struct GNUNET_HashCode cache_key;
2181 struct MHD_Response *resp = NULL;
2182 struct GNUNET_CRYPTO_PublicKey issuer;
2183 char *grant_type = NULL;
2184 char *code = NULL;
2185 char *json_response = NULL;
2186 char *id_token = NULL;
2187 char *access_token = NULL;
2188 char *jwa = NULL;
2189 char *jwt_secret = NULL;
2190 char *nonce = NULL;
2191 char *code_verifier = NULL;
2192 json_t *oidc_jwk_tmp = NULL;
2193 char *oidc_jwk_path = NULL;
2194 char *oidc_directory = NULL;
2195 char *tmp_at = NULL;
2196 char *received_cid = NULL;
2197 char *emsg = NULL;
2198
2199 /*
2200 * Check Authorization
2201 */
2203 {
2205 "OIDC authorization for token endpoint failed\n");
2207 return;
2208 }
2210
2211 /*
2212 * Check parameter
2213 */
2214
2215 // TODO Do not allow multiple equal parameter names
2216 // REQUIRED grant_type
2218 strlen (OIDC_GRANT_TYPE_KEY),
2219 &cache_key);
2221 if (NULL == grant_type)
2222 {
2224 handle->edesc = GNUNET_strdup ("missing parameter grant_type");
2225 handle->response_code = MHD_HTTP_BAD_REQUEST;
2227 return;
2228 }
2229
2230 // Check parameter grant_type == "authorization_code"
2231 if (0 != strcmp (OIDC_GRANT_TYPE_VALUE, grant_type))
2232 {
2234 handle->response_code = MHD_HTTP_BAD_REQUEST;
2235 GNUNET_free (grant_type);
2237 return;
2238 }
2239 GNUNET_free (grant_type);
2240 // REQUIRED code
2242 if (NULL == code)
2243 {
2245 handle->edesc = GNUNET_strdup ("missing parameter code");
2246 handle->response_code = MHD_HTTP_BAD_REQUEST;
2248 return;
2249 }
2250 ego_entry = find_ego (handle, &cid);
2251 if (NULL == ego_entry)
2252 {
2254 handle->edesc = GNUNET_strdup ("Unknown client");
2255 handle->response_code = MHD_HTTP_BAD_REQUEST;
2256 GNUNET_free (code);
2258 return;
2259 }
2260
2261 // REQUIRED code verifier
2263 if (NULL == code_verifier)
2264 {
2266 "OAuth authorization request does not contain PKCE parameters!\n");
2267
2268 }
2269
2270 // decode code
2271 if (GNUNET_OK != OIDC_parse_authz_code (received_cid, &cid, code,
2272 code_verifier,
2273 &ticket,
2274 &cl, &pl, &nonce,
2276 &emsg))
2277 {
2279 handle->edesc = emsg;
2280 handle->response_code = MHD_HTTP_BAD_REQUEST;
2281 GNUNET_free (code);
2282 if (NULL != code_verifier)
2283 GNUNET_free (code_verifier);
2285 return;
2286 }
2287 if (NULL != code_verifier)
2288 GNUNET_free (code_verifier);
2289
2290 // create jwt
2292 "reclaim-rest-plugin",
2293 "expiration_time",
2294 &expiration_time))
2295 {
2297 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
2298 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2299 GNUNET_free (code);
2300 if (NULL != nonce)
2301 GNUNET_free (nonce);
2305 return;
2306 }
2307
2308 // Check if HMAC or RSA should be used
2310 "reclaim-rest-plugin",
2311 "oidc_json_web_algorithm",
2312 &jwa))
2313 {
2315 "Could not read OIDC JSON Web Algorithm config attribute."
2316 "Defaulting to RS256.");
2318 }
2319
2321
2322 if (! strcmp (jwa, JWT_ALG_VALUE_RSA))
2323 {
2324 // Replace for now
2325 oidc_jwk_path = get_oidc_jwk_path (cls);
2326 oidc_jwk_tmp = read_jwk_from_file (oidc_jwk_path);
2327
2328 // Check if secret JWK exists
2329 if (! oidc_jwk_tmp)
2330 {
2331 // Generate and save a new key
2332 oidc_jwk_tmp = generate_jwk ();
2333 oidc_directory = get_oidc_dir_path (cls);
2334
2335 // Create new oidc directory
2336 if (GNUNET_OK != GNUNET_DISK_directory_create (oidc_directory))
2337 {
2339 ("Failed to create directory `%s' for storing oidc data\n"),
2340 oidc_directory);
2341 }
2342 else
2343 {
2344 write_jwk_to_file (oidc_jwk_path, oidc_jwk_tmp);
2345 }
2346 }
2347
2348 // Generate oidc token
2349 id_token = OIDC_generate_id_token_rsa (received_cid,
2350 &issuer,
2351 cl,
2352 pl,
2353 &expiration_time,
2354 (NULL != nonce) ? nonce : NULL,
2355 oidc_jwk_tmp);
2356 }
2357 else if (! strcmp (jwa, JWT_ALG_VALUE_HMAC))
2358 {
2359 // TODO OPTIONAL acr,amr,azp
2361 "reclaim-rest-plugin",
2362 "jwt_secret",
2363 &jwt_secret))
2364 {
2366 handle->edesc = GNUNET_strdup ("No signing secret configured!");
2367 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2368 GNUNET_free (code);
2371 if (NULL != nonce)
2372 GNUNET_free (nonce);
2373 GNUNET_free (jwa);
2375 return;
2376 }
2377
2378 id_token = OIDC_generate_id_token_hmac (received_cid,
2379 &issuer,
2380 cl,
2381 pl,
2382 &expiration_time,
2383 (NULL != nonce) ? nonce : NULL,
2384 jwt_secret);
2385
2386 GNUNET_free (jwt_secret);
2387 }
2388 else
2389 {
2390 // TODO: OPTION NOT FOUND ERROR
2391 }
2392 GNUNET_free (jwa);
2393
2394 if (NULL != nonce)
2395 GNUNET_free (nonce);
2396 access_token = OIDC_access_token_new (&ticket, handle->oidc->redirect_uri);
2401 GNUNET_CRYPTO_hash (access_token,
2402 strlen (access_token),
2403 &cache_key);
2415 &cache_key);
2417 &cache_key,
2418 code,
2420 /* If there was a previous code in there, free the old value */
2421 if (NULL != tmp_at)
2422 {
2424 "OIDC access token already issued. Cleanup.\n");
2425 GNUNET_free (tmp_at);
2426 }
2427
2428 OIDC_build_token_response (access_token,
2429 id_token,
2430 &expiration_time,
2431 &json_response);
2432
2433 resp = GNUNET_REST_create_response (json_response);
2434 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2435 "Cache-Control",
2436 "no-store"));
2437 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2438 "Pragma", "no-cache"));
2439 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2440 "Content-Type",
2441 "application/json"));
2442 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2445 GNUNET_free (access_token);
2446 GNUNET_free (json_response);
2447 GNUNET_free (id_token);
2449}
2450
2451
2455static void
2457 const struct GNUNET_CRYPTO_PublicKey *identity,
2458 const struct GNUNET_RECLAIM_Attribute *attr,
2459 const struct GNUNET_RECLAIM_Presentation *presentation)
2460{
2461 struct RequestHandle *handle = cls;
2464 struct MHD_Response *resp;
2465 struct GNUNET_HashCode cache_key;
2466 char *result_str;
2467 char *cached_code;
2468
2469 if (NULL != handle->consume_timeout_op)
2470 GNUNET_SCHEDULER_cancel (handle->consume_timeout_op);
2471 handle->consume_timeout_op = NULL;
2472 handle->idp_op = NULL;
2473
2477 GNUNET_CRYPTO_hash (handle->access_token,
2478 strlen (handle->access_token),
2479 &cache_key);
2481 &cache_key);
2482 if (NULL != cached_code)
2483 {
2486 &cache_key,
2487 cached_code));
2488 GNUNET_free (cached_code);
2489 }
2490
2491
2492 if (NULL == identity)
2493 {
2494 struct GNUNET_CRYPTO_PublicKey issuer;
2495 char *key;
2496 char *tmp = GNUNET_strdup (handle->ticket.gns_name);
2497 GNUNET_assert (NULL != strtok (tmp, "."));
2498 key = strtok (NULL, ".");
2499 GNUNET_assert (NULL != key);
2502 GNUNET_free (tmp);
2503 result_str = OIDC_generate_userinfo (&issuer,
2504 handle->attr_userinfo_list,
2505 handle->presentations);
2506 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2507 resp = GNUNET_REST_create_response (result_str);
2508 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2509 GNUNET_free (result_str);
2511 return;
2512 }
2515 &attr->credential,
2516 attr->type,
2517 attr->data,
2518 attr->data_size);
2519 ale->attribute->id = attr->id;
2520 ale->attribute->flag = attr->flag;
2521 ale->attribute->credential = attr->credential;
2522 GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
2523 handle->attr_userinfo_list->list_tail,
2524 ale);
2525 if (NULL == presentation)
2526 return;
2527 for (atle = handle->presentations->list_head;
2528 NULL != atle; atle = atle->next)
2529 {
2532 &presentation->credential_id))
2533 continue;
2534 break;
2535 }
2536 if (NULL == atle)
2537 {
2540 atle->presentation = GNUNET_RECLAIM_presentation_new (presentation->type,
2541 presentation->data,
2542 presentation->
2543 data_size);
2544 atle->presentation->credential_id = presentation->credential_id;
2545 GNUNET_CONTAINER_DLL_insert (handle->presentations->list_head,
2546 handle->presentations->list_tail,
2547 atle);
2548 }
2549}
2550
2551
2552static void
2553consume_fail (void *cls)
2554{
2555 struct RequestHandle *handle = cls;
2556 struct GNUNET_HashCode cache_key;
2557 struct GNUNET_RECLAIM_AttributeList *cl = NULL;
2558 struct GNUNET_RECLAIM_PresentationList *pl = NULL;
2560 struct GNUNET_CRYPTO_PublicKey cid;
2561 struct MHD_Response *resp;
2562 struct GNUNET_CRYPTO_PublicKey issuer;
2563 char *nonce;
2564 char *cached_code;
2565 char *result_str;
2566 char *received_cid;
2567 char *emsg;
2568 char *tmp;
2569 char *key;
2570
2571 handle->consume_timeout_op = NULL;
2572 if (NULL != handle->idp_op)
2573 GNUNET_RECLAIM_cancel (handle->idp_op);
2574 handle->idp_op = NULL;
2575
2577 "Ticket consumptioned timed out. Using cache...\n");
2578 GNUNET_CRYPTO_hash (handle->access_token,
2579 strlen (handle->access_token),
2580 &cache_key);
2582 &cache_key);
2583 if (NULL == cached_code)
2584 {
2586 handle->edesc = GNUNET_strdup ("No Access Token in cache!");
2587 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2589 return;
2590 }
2596 &cache_key,
2597 cached_code));
2599 GNUNET_STRINGS_string_to_data (received_cid,
2600 strlen (received_cid),
2601 &cid,
2602 sizeof(struct GNUNET_CRYPTO_PublicKey));
2603
2604 // decode code
2605 if (GNUNET_OK != OIDC_parse_authz_code (received_cid, &cid,
2606 cached_code, NULL, &ticket,
2607 &cl, &pl, &nonce,
2609 emsg))
2610 {
2612 handle->edesc = emsg;
2613 handle->response_code = MHD_HTTP_BAD_REQUEST;
2614 GNUNET_free (cached_code);
2615 if (NULL != nonce)
2616 GNUNET_free (nonce);
2618 return;
2619 }
2620
2621 GNUNET_free (cached_code);
2622
2623 tmp = GNUNET_strdup (handle->ticket.gns_name);
2624 GNUNET_assert (NULL != strtok (tmp, "."));
2625 key = strtok (NULL, ".");
2626 GNUNET_assert (NULL != key);
2629 GNUNET_free (tmp);
2630 result_str = OIDC_generate_userinfo (&issuer,
2631 cl,
2632 pl);
2633 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2634 resp = GNUNET_REST_create_response (result_str);
2635 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2636 GNUNET_free (result_str);
2637 GNUNET_free (nonce);
2641}
2642
2643
2651static void
2653 const char *url,
2654 void *cls)
2655{
2656 // TODO expiration time
2657 struct RequestHandle *handle = cls;
2659 char delimiter[] = " ";
2660 struct GNUNET_HashCode cache_key;
2661 char *authorization;
2662 char *authorization_type;
2663 char *authorization_access_token;
2664
2665 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting userinfo\n");
2668 &cache_key);
2670 ->header_param_map,
2671 &cache_key))
2672 {
2674 handle->edesc = GNUNET_strdup ("No Access Token");
2675 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2677 return;
2678 }
2679 authorization =
2680 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
2681 &cache_key);
2682
2683 // split header in "Bearer" and access_token
2684 authorization = GNUNET_strdup (authorization);
2685 authorization_type = strtok (authorization, delimiter);
2686 if ((NULL == authorization_type) ||
2687 (0 != strcmp ("Bearer", authorization_type)))
2688 {
2690 handle->edesc = GNUNET_strdup ("No Access Token");
2691 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2693 GNUNET_free (authorization);
2694 return;
2695 }
2696 authorization_access_token = strtok (NULL, delimiter);
2697 if (NULL == authorization_access_token)
2698 {
2700 handle->edesc = GNUNET_strdup ("Access token missing");
2701 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2703 GNUNET_free (authorization);
2704 return;
2705 }
2706
2707 {
2708 char *rp_uri;
2709 if (GNUNET_OK != OIDC_access_token_parse (authorization_access_token,
2710 &ticket, &rp_uri))
2711 {
2713 handle->edesc = GNUNET_strdup ("The access token is invalid");
2714 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2716 GNUNET_free (authorization);
2717 return;
2718
2719 }
2720 GNUNET_assert (NULL != ticket);
2721 handle->ticket = *ticket;
2723 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Consuming ticket\n");
2724 handle->attr_userinfo_list =
2726 handle->presentations =
2728
2729 /* If the consume takes too long, we use values from the cache */
2730 handle->access_token = GNUNET_strdup (authorization_access_token);
2732 &consume_fail,
2733 handle);
2735 &handle->ticket,
2736 rp_uri,
2738 handle);
2739 GNUNET_free (authorization);
2740 GNUNET_free (rp_uri);
2741 }
2742}
2743
2744
2752static void
2754 const char *url,
2755 void *cls)
2756{
2757 char *oidc_directory;
2758 char *oidc_jwk_path;
2759 char *oidc_jwk_pub_str;
2760 json_t *oidc_jwk_tmp;
2761 struct MHD_Response *resp;
2762 struct RequestHandle *handle = cls;
2763
2764 oidc_jwk_path = get_oidc_jwk_path (cls);
2765 oidc_jwk_tmp = read_jwk_from_file (oidc_jwk_path);
2766
2767 // Check if secret JWK exists
2768 if (! oidc_jwk_tmp)
2769 {
2770 // Generate and save a new key
2771 oidc_jwk_tmp = generate_jwk ();
2772 oidc_directory = get_oidc_dir_path (cls);
2773
2774 // Create new oidc directory
2775 if (GNUNET_OK != GNUNET_DISK_directory_create (oidc_directory))
2776 {
2778 ("Failed to create directory `%s' for storing oidc data\n"),
2779 oidc_directory);
2780 }
2781 else
2782 {
2783 write_jwk_to_file (oidc_jwk_path, oidc_jwk_tmp);
2784 }
2785 }
2786
2787 // Convert secret JWK to public JWK
2788 jose_jwk_pub (NULL, oidc_jwk_tmp);
2789
2790 // Encode JWK as string and return to API endpoint
2791 oidc_jwk_pub_str = json_dumps (oidc_jwk_tmp, JSON_INDENT (1));
2792 resp = GNUNET_REST_create_response (oidc_jwk_pub_str);
2793 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2794 json_decref (oidc_jwk_tmp);
2795 GNUNET_free (oidc_jwk_pub_str);
2796 GNUNET_free (oidc_jwk_pub_str);
2798}
2799
2800
2833static void
2834list_ego (void *cls,
2835 struct GNUNET_IDENTITY_Ego *ego,
2836 void **ctx,
2837 const char *identifier)
2838{
2839 struct EgoEntry *ego_entry;
2841
2842 if (NULL == ego)
2843 {
2845 return;
2846 }
2848
2849 {
2850 ego_entry = GNUNET_new (struct EgoEntry);
2853 ego_entry->ego = ego;
2854 ego_entry->identifier = GNUNET_strdup (identifier);
2856 ego_tail,
2857 ego_entry);
2858 return;
2859 }
2860 /* Ego renamed or added */
2861 if (identifier != NULL)
2862 {
2863 for (ego_entry = ego_head; NULL != ego_entry;
2864 ego_entry = ego_entry->next)
2865 {
2866 if (ego_entry->ego == ego)
2867 {
2868 /* Rename */
2869 GNUNET_free (ego_entry->identifier);
2870 ego_entry->identifier = GNUNET_strdup (identifier);
2871 break;
2872 }
2873 }
2874 if (NULL == ego_entry)
2875 {
2876 /* Add */
2877 ego_entry = GNUNET_new (struct EgoEntry);
2880 ego_entry->ego = ego;
2881 ego_entry->identifier = GNUNET_strdup (identifier);
2883 ego_tail,
2884 ego_entry);
2885 }
2886 }
2887 else
2888 {
2889 /* Delete */
2890 for (ego_entry = ego_head; NULL != ego_entry;
2891 ego_entry = ego_entry->next)
2892 {
2893 if (ego_entry->ego == ego)
2894 break;
2895 }
2896 if (NULL == ego_entry)
2897 return; /* Not found */
2898
2900 ego_tail,
2901 ego_entry);
2902 GNUNET_free (ego_entry->identifier);
2903 GNUNET_free (ego_entry->keystring);
2904 GNUNET_free (ego_entry);
2905 return;
2906 }
2907}
2908
2909
2910static void
2912 const char *url,
2913 void *cls)
2914{
2915 json_t *oidc_config;
2916 json_t *auth_methods;
2917 json_t *sig_algs;
2918 json_t *scopes;
2919 json_t *response_types;
2920 json_t *sub_types;
2921 json_t *claim_types;
2922 char *oidc_config_str;
2923 struct MHD_Response *resp;
2924 struct RequestHandle *handle = cls;
2925
2926 oidc_config = json_object ();
2927 // FIXME get from config?
2928 json_object_set_new (oidc_config,
2929 "issuer", json_string ("http://localhost:7776"));
2930 json_object_set_new (oidc_config,
2931 "authorization_endpoint",
2932 json_string ("https://api.reclaim/openid/authorize"));
2933 json_object_set_new (oidc_config,
2934 "token_endpoint",
2935 json_string ("http://localhost:7776/openid/token"));
2936 auth_methods = json_array ();
2937 json_array_append_new (auth_methods,
2938 json_string ("client_secret_basic"));
2939 json_array_append_new (auth_methods,
2940 json_string ("client_secret_post"));
2941 json_object_set_new (oidc_config,
2942 "token_endpoint_auth_methods_supported",
2943 auth_methods);
2944 sig_algs = json_array ();
2945 json_array_append_new (sig_algs,
2946 json_string ("HS512"));
2947 json_array_append_new (sig_algs,
2948 json_string ("RS256"));
2949 json_object_set_new (oidc_config,
2950 "id_token_signing_alg_values_supported",
2951 sig_algs);
2952 json_object_set_new (oidc_config,
2953 "jwks_uri",
2954 json_string ("http://localhost:7776/jwks.json"));
2955 json_object_set_new (oidc_config,
2956 "userinfo_endpoint",
2957 json_string ("http://localhost:7776/openid/userinfo"));
2958 scopes = json_array ();
2959 json_array_append_new (scopes,
2960 json_string ("openid"));
2961 json_array_append_new (scopes,
2962 json_string ("profile"));
2963 json_array_append_new (scopes,
2964 json_string ("email"));
2965 json_array_append_new (scopes,
2966 json_string ("address"));
2967 json_array_append_new (scopes,
2968 json_string ("phone"));
2969 json_object_set_new (oidc_config,
2970 "scopes_supported",
2971 scopes);
2972 response_types = json_array ();
2973 json_array_append_new (response_types,
2974 json_string ("code"));
2975 json_object_set_new (oidc_config,
2976 "response_types_supported",
2977 response_types);
2978 sub_types = json_array ();
2979 json_array_append_new (sub_types,
2980 json_string ("public")); /* no pairwise support */
2981 json_object_set_new (oidc_config,
2982 "subject_types_supported",
2983 sub_types);
2984 claim_types = json_array ();
2985 json_array_append_new (claim_types,
2986 json_string ("normal"));
2987 json_array_append_new (claim_types,
2988 json_string ("aggregated"));
2989 json_object_set_new (oidc_config,
2990 "claim_types_supported",
2991 claim_types);
2992 json_object_set_new (oidc_config,
2993 "claims_parameter_supported",
2994 json_boolean (1));
2995 oidc_config_str = json_dumps (oidc_config, JSON_INDENT (1));
2996 resp = GNUNET_REST_create_response (oidc_config_str);
2997 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2998 json_decref (oidc_config);
2999 GNUNET_free (oidc_config_str);
3001}
3002
3003
3011static void
3013 const char *url,
3014 void *cls)
3015{
3016 struct MHD_Response *resp;
3017 struct RequestHandle *handle = cls;
3018
3019 // For now, independent of path return all options
3020 resp = GNUNET_REST_create_response (NULL);
3021 GNUNET_assert (MHD_NO !=
3022 MHD_add_response_header (resp,
3023 "Access-Control-Allow-Methods",
3024 allow_methods));
3025 GNUNET_assert (MHD_NO !=
3026 MHD_add_response_header (resp,
3027 "Access-Control-Allow-Origin",
3028 "*"));
3029 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
3031 return;
3032}
3033
3034
3039 void *proc_cls)
3040{
3041 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
3043 static const struct GNUNET_REST_RequestHandler handlers[] =
3044 { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint },
3045 { MHD_HTTP_METHOD_POST,
3047 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont },
3048 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
3049 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
3050 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
3051 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_JWKS, &jwks_endpoint },
3052 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_OIDC_CONFIG,
3054 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC_CONFIG,
3056 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont },
3058
3059 handle->oidc = GNUNET_new (struct OIDC_Variables);
3060 if (NULL == OIDC_cookie_jar_map)
3062 GNUNET_NO);
3063 if (NULL == oidc_code_cache)
3065 GNUNET_NO);
3066
3067 handle->response_code = 0;
3069 handle->proc_cls = proc_cls;
3070 handle->proc = proc;
3071 handle->rest_handle = rest_handle;
3072 handle->url = GNUNET_strdup (rest_handle->url);
3073 handle->timeout_task =
3077 handle);
3078 if (handle->url[strlen (handle->url) - 1] == '/')
3079 handle->url[strlen (handle->url) - 1] = '\0';
3080 if (GNUNET_NO ==
3081 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
3082 return GNUNET_NO;
3083
3084 return GNUNET_YES;
3085}
3086
3087
3094void *
3096{
3097 static struct Plugin plugin;
3098 struct GNUNET_REST_Plugin *api;
3099
3100 oid_cfg = c;
3101 if (NULL != plugin.cfg)
3102 return NULL; /* can only initialize once! */
3103 memset (&plugin, 0, sizeof(struct Plugin));
3104 plugin.cfg = oid_cfg;
3105 api = GNUNET_new (struct GNUNET_REST_Plugin);
3106 api->cls = &plugin;
3112 "reclaim-rest-plugin",
3113 "OIDC_USERINFO_CONSUME_TIMEOUT",
3115 {
3117 }
3118
3119
3122 "%s, %s, %s, %s, %s",
3123 MHD_HTTP_METHOD_GET,
3124 MHD_HTTP_METHOD_POST,
3125 MHD_HTTP_METHOD_PUT,
3126 MHD_HTTP_METHOD_DELETE,
3127 MHD_HTTP_METHOD_OPTIONS);
3128
3130 _ ("OpenID Connect REST API initialized\n"));
3131 return api;
3132}
3133
3134
3135static int
3136cleanup_hashmap (void *cls, const struct GNUNET_HashCode *key, void *value)
3137{
3139 return GNUNET_YES;
3140}
3141
3142
3143void
3145{
3146 struct Plugin *plugin = api->cls;
3147 struct EgoEntry *ego_entry;
3148
3149 plugin->cfg = NULL;
3150 while (NULL != requests_head)
3152 if (NULL != OIDC_cookie_jar_map)
3153 {
3156 NULL);
3158 }
3159 if (NULL != oidc_code_cache)
3160 {
3163 NULL);
3165 }
3166
3168 if (NULL != gns_handle)
3170 if (NULL != identity_handle)
3172 if (NULL != idp)
3174 while (NULL != (ego_entry = ego_head))
3175 {
3177 ego_tail,
3178 ego_entry);
3179 GNUNET_free (ego_entry->identifier);
3180 GNUNET_free (ego_entry->keystring);
3181 GNUNET_free (ego_entry);
3182 }
3183 GNUNET_free (api);
3185 "OpenID Connect REST plugin is finished\n");
3186}
3187
3188
3189/* 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:93
static struct GNUNET_TESTING_PluginFunctions * plugin
Plugin to dynamically load a test case.
static gnutls_certificate_credentials_t cred
The credential.
static char * data
The data to insert into the dht.
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_FS_Handle * ctx
static char * filename
struct GNUNET_CRYPTO_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:520
#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:379
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:430
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:399
@ 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:980
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1304
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1277
size_t GNUNET_STRINGS_urlencode(size_t len, const char data[static len], char **out)
url/percent encode (RFC3986).
Definition: strings.c:1863
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
Definition: strings.c:787
size_t GNUNET_STRINGS_urldecode(const char *data, size_t len, char **out)
url/percent encode (RFC3986).
Definition: strings.c:1808
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:812
size_t GNUNET_STRINGS_base64_decode(const char *data, size_t len, void **output)
Decode from Base64.
Definition: strings.c:1701
#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:486
@ 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:53
static struct GNUNET_RECLAIM_Handle * idp
Identity Provider.
static const char * OIDC_ignored_parameter_array[]
OIDC ignored parameter array.
struct GNUNET_CONTAINER_MultiHashMap * oidc_code_cache
OIDC hashmap for cached access tokens and codes.
static void cookie_identity_interpretation(struct RequestHandle *handle)
Interprets cookie header and pass its identity keystring to handle.
static struct GNUNET_GNS_Handle * gns_handle
GNS handle.
static int write_jwk_to_file(const char *filename, json_t *jwk)
Write the JWK to file.
static char * get_oidc_dir_path(void *cls)
Return the path to the oidc directory path.
#define OIDC_ERROR_KEY_INVALID_REQUEST
OIDC error key for invalid requests.
static int attr_in_claims_request(struct RequestHandle *handle, const char *attr_name, const char *claims_parameter)
void REST_openid_done(struct GNUNET_REST_Plugin *api)
Exit point from the plugin.
static char * get_url_parameter_copy(const struct RequestHandle *handle, const char *key)
#define GNUNET_REST_API_NS_LOGIN
Login namespace.
Definition: openid_plugin.c:78
#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:48
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.
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:68
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:83
#define OIDC_REDIRECT_URI_KEY
OIDC redirect_uri key.
static void do_redirect_error(void *cls)
Task run on error, sends error message and redirects.
static void code_redirect(void *cls)
Checks time and cookie and redirects accordingly.
static struct RequestHandle * requests_head
DLL.
static void options_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Respond to OPTIONS request.
static json_t * read_jwk_from_file(const char *filename)
Read the the JSON Web Key in the given file and return it.
#define OIDC_NONCE_KEY
OIDC nonce key.
#define OIDC_ERROR_KEY_INVALID_CLIENT
OIDC error key for invalid client.
static int parse_credentials_basic_auth(struct RequestHandle *handle, char **client_id, char **client_secret)
#define OIDC_GRANT_TYPE_KEY
OIDC grant_type key.
Definition: openid_plugin.c:93
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.
static const struct EgoEntry * find_ego(struct RequestHandle *handle, struct GNUNET_CRYPTO_PublicKey *test_key)
const struct GNUNET_CONFIGURATION_Handle * oid_cfg
The configuration handle.
#define OIDC_COOKIE_HEADER_ACCESS_DENIED
OIDC cookie header if user cancelled.
#define GNUNET_REST_API_NS_TOKEN
Token endpoint.
Definition: openid_plugin.c:63
#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:73
#define GNUNET_REST_API_NS_AUTHORIZE
Authorize endpoint.
Definition: openid_plugin.c:58
static void oidc_config_cors(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Respond to OPTIONS request.
#define OIDC_CODE_KEY
OIDC code key.
#define OIDC_CODE_VERIFIER_KEY
OIDC PKCE code verifier.
static void authorize_endpoint(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Responds to authorization GET and url-encoded POST request.
static json_t * generate_jwk()
Generate a new RSA JSON Web Key.
#define OIDC_CLIENT_ID_KEY
OIDC client_id key.
#define OIDC_GRANT_TYPE_VALUE
OIDC grant_type key.
Definition: openid_plugin.c:98
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:88
static int cleanup_hashmap(void *cls, const struct GNUNET_HashCode *key, void *value)
static void lookup_redirect_uri_result(void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd)
static void build_redirect(void *cls)
static void oidc_attr_collect_finished_cb(void *cls)
#define OIDC_ERROR_KEY_UNSUPPORTED_RESPONSE_TYPE
OIDC error key for unsupported response types.
#define OIDC_ERROR_KEY_INVALID_SCOPE
OIDC error key for invalid scopes.
static void do_error(void *cls)
Task run on error, sends error message.
static void oidc_iteration_error(void *cls)
Does internal server error when iteration failed.
static void client_redirect(void *cls)
Initiate redirect back to client.
static void login_redirect(void *cls)
Redirects to login page stored in configuration file.
static int attr_in_idtoken_request(struct RequestHandle *handle, const char *attr_name)
static char * get_oidc_jwk_path(void *cls)
Return the path to the RSA JWK key file.
#define _(String)
GNU gettext support macro.
Definition: platform.h: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.
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
void * cls
The closure of the plugin.
const char * name
Plugin name.
const char * url
The url as string.
void(* proc)(struct GNUNET_REST_RequestHandle *handle, const char *url, void *cls)
Namespace to handle.
Entry in list of pending tasks.
Definition: scheduler.c:136
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds.
OIDC needed variables.
char * login_identity
The identity chosen by the user to login.
char * client_id
The OIDC client id of the RP.
char * response_type
The OIDC response type.
int user_cancelled
User cancelled authorization/login.
char * redirect_uri
The OIDC redirect uri.
char * claims
The OIDC claims.
char * code_challenge
The PKCE code_challenge.
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:47
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:56
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:76
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:71
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:66
char * redirect_suffix
The redirect suffix.
struct RequestHandle * next
DLL.
Definition: config_plugin.c:51
struct GNUNET_RECLAIM_CredentialIterator * cred_it
Credential iterator.
struct GNUNET_REST_RequestHandle * rest_handle
Handle to rest request.
Definition: config_plugin.c:61
char * url
The URL.
Definition: config_plugin.c:81
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.