GNUnet 0.21.1
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"
38#include "gnunet_reclaim_lib.h"
40#include "gnunet_rest_lib.h"
41#include "gnunet_rest_plugin.h"
42#include "gnunet_signatures.h"
43#include "microhttpd.h"
44#include "oidc_helper.h"
45
49#define GNUNET_REST_API_NS_OIDC "/openid"
50
54#define GNUNET_REST_API_NS_OIDC_CONFIG "/.well-known/openid-configuration"
55
59#define GNUNET_REST_API_NS_AUTHORIZE "/openid/authorize"
60
64#define GNUNET_REST_API_NS_TOKEN "/openid/token"
65
69#define GNUNET_REST_API_JWKS "/jwks.json"
70
74#define GNUNET_REST_API_NS_USERINFO "/openid/userinfo"
75
79#define GNUNET_REST_API_NS_LOGIN "/openid/login"
80
84#define ID_REST_STATE_INIT 0
85
89#define ID_REST_STATE_POST_INIT 1
90
94#define OIDC_GRANT_TYPE_KEY "grant_type"
95
99#define OIDC_GRANT_TYPE_VALUE "authorization_code"
100
104#define OIDC_CODE_KEY "code"
105
109#define OIDC_RESPONSE_TYPE_KEY "response_type"
110
114#define OIDC_CLIENT_ID_KEY "client_id"
115
119#define OIDC_SCOPE_KEY "scope"
120
124#define OIDC_REDIRECT_URI_KEY "redirect_uri"
125
129#define OIDC_STATE_KEY "state"
130
134#define OIDC_NONCE_KEY "nonce"
135
139#define OIDC_CLAIMS_KEY "claims"
140
144#define OIDC_CODE_CHALLENGE_KEY "code_challenge"
145
149#define OIDC_CODE_VERIFIER_KEY "code_verifier"
150
154#define OIDC_COOKIE_EXPIRATION 3
155
159#define OIDC_COOKIE_HEADER_KEY "cookie"
160
164#define OIDC_AUTHORIZATION_HEADER_KEY "authorization"
165
169#define OIDC_COOKIE_HEADER_INFORMATION_KEY "Identity="
170
174#define OIDC_COOKIE_HEADER_ACCESS_DENIED "Identity=Denied"
175
179#define OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE "code"
180
184#define OIDC_EXPECTED_AUTHORIZATION_SCOPE "openid"
185
189#define OIDC_ERROR_KEY_INVALID_CLIENT "invalid_client"
190
194#define OIDC_ERROR_KEY_INVALID_SCOPE "invalid_scope"
195
199#define OIDC_ERROR_KEY_INVALID_REQUEST "invalid_request"
200
204#define OIDC_ERROR_KEY_INVALID_TOKEN "invalid_token"
205
209#define OIDC_ERROR_KEY_INVALID_COOKIE "invalid_cookie"
210
214#define OIDC_ERROR_KEY_SERVER_ERROR "server_error"
215
219#define OIDC_ERROR_KEY_UNSUPPORTED_GRANT_TYPE "unsupported_grant_type"
220
224#define OIDC_ERROR_KEY_UNSUPPORTED_RESPONSE_TYPE "unsupported_response_type"
225
229#define OIDC_ERROR_KEY_UNAUTHORIZED_CLIENT "unauthorized_client"
230
234#define OIDC_ERROR_KEY_ACCESS_DENIED "access_denied"
235
239#define OIDC_JWK_RSA_FILENAME "jwk_rsa.json"
240
244#define CONSUME_TIMEOUT GNUNET_TIME_relative_multiply ( \
245 GNUNET_TIME_UNIT_SECONDS,2)
246
250static char *OIDC_ignored_parameter_array[] = { "display",
251 "prompt",
252 "ui_locales",
253 "response_mode",
254 "id_token_hint",
255 "login_hint",
256 "acr_values" };
257
262
267
272
276static char *allow_methods;
277
281static struct EgoEntry *ego_head;
282
286static struct EgoEntry *ego_tail;
287
291static int state;
292
297
302
307
312
316struct Plugin
317{
318 const struct GNUNET_CONFIGURATION_Handle *cfg;
319};
320
324json_t *oidc_jwk;
325
330{
335
340
345
349 char *scope;
350
354 char *state;
355
359 char *nonce;
360
364 char *claims;
365
370
375
380
385
390
391};
392
396struct EgoEntry
397{
401 struct EgoEntry *next;
402
406 struct EgoEntry *prev;
407
411 char *identifier;
412
416 char *keystring;
417
421 struct GNUNET_IDENTITY_Ego *ego;
422};
423
424
425struct RequestHandle
426{
430 struct RequestHandle *next;
431
435 struct RequestHandle *prev;
436
440 struct EgoEntry *ego_entry;
441
446
451
456
461
466
471
476
481
486
487
492
497
502
507
508
513
518
523
528
533
537 void *proc_cls;
538
542 char *url;
543
548
552 char *tld;
553
558
563
567 char *emsg;
568
572 char *edesc;
573
577 int response_code;
578
583};
584
589
594
595
600static void
602{
603
604 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
605 if (NULL != handle->timeout_task)
606 GNUNET_SCHEDULER_cancel (handle->timeout_task);
607 if (NULL != handle->attr_it)
609 if (NULL != handle->cred_it)
611 if (NULL != handle->ticket_it)
613 if (NULL != handle->idp_op)
615 if (NULL != handle->consume_timeout_op)
616 GNUNET_SCHEDULER_cancel (handle->consume_timeout_op);
617 GNUNET_free (handle->url);
618 GNUNET_free (handle->tld);
619 GNUNET_free (handle->redirect_prefix);
620 GNUNET_free (handle->redirect_suffix);
621 GNUNET_free (handle->emsg);
622 GNUNET_free (handle->edesc);
623 if (NULL != handle->gns_op)
625 if (NULL != handle->oidc)
626 {
627 GNUNET_free (handle->oidc->client_id);
628 GNUNET_free (handle->oidc->login_identity);
629 GNUNET_free (handle->oidc->nonce);
630 GNUNET_free (handle->oidc->redirect_uri);
631 GNUNET_free (handle->oidc->response_type);
632 GNUNET_free (handle->oidc->scope);
633 GNUNET_free (handle->oidc->state);
634 if (NULL != handle->oidc->claims)
635 GNUNET_free (handle->oidc->claims);
636 if (NULL != handle->oidc->code_challenge)
637 GNUNET_free (handle->oidc->code_challenge);
638 GNUNET_free (handle->oidc);
639 }
640 if (NULL!=handle->attr_idtoken_list)
642 if (NULL!=handle->attr_userinfo_list)
643 GNUNET_RECLAIM_attribute_list_destroy (handle->attr_userinfo_list);
644 if (NULL!=handle->credentials)
646 if (NULL!=handle->presentations)
650 handle);
651 if (NULL != handle->access_token)
652 GNUNET_free (handle->access_token);
654}
655
656
662static void
663do_error (void *cls)
664{
665 struct RequestHandle *handle = cls;
666 struct MHD_Response *resp;
667 char *json_error;
668
669 GNUNET_asprintf (&json_error,
670 "{ \"error\" : \"%s\", \"error_description\" : \"%s\"%s%s%s}",
671 handle->emsg,
672 (NULL != handle->edesc) ? handle->edesc : "",
673 (NULL != handle->oidc->state) ? ", \"state\":\"" : "",
674 (NULL != handle->oidc->state) ? handle->oidc->state : "",
675 (NULL != handle->oidc->state) ? "\"" : "");
676 if (0 == handle->response_code)
677 handle->response_code = MHD_HTTP_BAD_REQUEST;
678 resp = GNUNET_REST_create_response (json_error);
679 if (MHD_HTTP_UNAUTHORIZED == handle->response_code)
680 GNUNET_assert (MHD_NO !=
681 MHD_add_response_header (resp,
682 MHD_HTTP_HEADER_WWW_AUTHENTICATE,
683 "Basic"));
684 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
685 MHD_HTTP_HEADER_CONTENT_TYPE,
686 "application/json"));
687 handle->proc (handle->proc_cls, resp, handle->response_code);
689 GNUNET_free (json_error);
690}
691
692
699static void
701{
702 struct RequestHandle *handle = cls;
703 struct MHD_Response *resp;
704 char *error;
705
707 "Error: %s\n", handle->edesc);
708 GNUNET_asprintf (&error,
709 "error=\"%s\", error_description=\"%s\"",
710 handle->emsg,
711 (NULL != handle->edesc) ? handle->edesc : "");
712 resp = GNUNET_REST_create_response ("");
713 GNUNET_assert (MHD_NO !=
714 MHD_add_response_header (resp,
715 MHD_HTTP_HEADER_WWW_AUTHENTICATE,
716 "Bearer"));
717 handle->proc (handle->proc_cls, resp, handle->response_code);
719 GNUNET_free (error);
720}
721
722
728static void
730{
731 struct RequestHandle *handle = cls;
732 struct MHD_Response *resp;
733 char *redirect;
734
735 GNUNET_asprintf (&redirect,
736 "%s?error=%s&error_description=%s%s%s",
737 handle->oidc->redirect_uri,
738 handle->emsg,
739 handle->edesc,
740 (NULL != handle->oidc->state) ? "&state=" : "",
741 (NULL != handle->oidc->state) ? handle->oidc->state : "");
742 resp = GNUNET_REST_create_response ("");
743 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
744 "Location", redirect));
745 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
747 GNUNET_free (redirect);
748}
749
750
756static void
757do_timeout (void *cls)
758{
759 struct RequestHandle *handle = cls;
760
761 handle->timeout_task = NULL;
763}
764
765
773static void
775 const char *url,
776 void *cls)
777{
778 struct MHD_Response *resp;
779 struct RequestHandle *handle = cls;
780
781 // For now, independent of path return all options
782 resp = GNUNET_REST_create_response (NULL);
783 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
784 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
786 return;
787}
788
789
793static void
795{
796 struct GNUNET_HashCode cache_key;
797 char *cookies;
798 struct GNUNET_TIME_Absolute current_time, *relog_time;
799 char delimiter[] = "; ";
800 char *tmp_cookies;
801 char *token;
802 char *value;
803
804 // gets identity of login try with cookie
806 strlen (OIDC_COOKIE_HEADER_KEY),
807 &cache_key);
809 ->header_param_map,
810 &cache_key))
811 {
812 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No cookie found\n");
813 return;
814 }
815 // splits cookies and find 'Identity' cookie
816 tmp_cookies =
817 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
818 &cache_key);
819 cookies = GNUNET_strdup (tmp_cookies);
820 token = strtok (cookies, delimiter);
821 handle->oidc->user_cancelled = GNUNET_NO;
822 handle->oidc->login_identity = NULL;
823 if (NULL == token)
824 {
826 "Unable to parse cookie: %s\n",
827 cookies);
828 GNUNET_free (cookies);
829 return;
830 }
831
832 while (NULL != token)
833 {
834 if (0 == strcmp (token, OIDC_COOKIE_HEADER_ACCESS_DENIED))
835 {
836 handle->oidc->user_cancelled = GNUNET_YES;
837 GNUNET_free (cookies);
838 return;
839 }
840 if (NULL != strstr (token, OIDC_COOKIE_HEADER_INFORMATION_KEY))
841 break;
842 token = strtok (NULL, delimiter);
843 }
844 if (NULL == token)
845 {
847 "No cookie value to process: %s\n",
848 cookies);
849 GNUNET_free (cookies);
850 return;
851 }
852 GNUNET_CRYPTO_hash (token, strlen (token), &cache_key);
853 if (GNUNET_NO ==
855 {
856 GNUNET_log (
858 "Found cookie `%s', but no corresponding expiration entry present...\n",
859 token);
860 GNUNET_free (cookies);
861 return;
862 }
863 relog_time =
865 current_time = GNUNET_TIME_absolute_get ();
866 // 30 min after old login -> redirect to login
867 if (current_time.abs_value_us > relog_time->abs_value_us)
868 {
870 "Found cookie `%s', but it is expired.\n",
871 token);
872 GNUNET_free (cookies);
873 return;
874 }
876 GNUNET_assert (NULL != value);
877 handle->oidc->login_identity = GNUNET_strdup (value);
878 GNUNET_free (cookies);
879}
880
881
890json_t *
892{
893 json_t *jwk;
894 json_error_t error;
895
896 jwk = json_load_file (filename, JSON_DECODE_ANY, &error);
897
898 if (! jwk)
899 {
901 ("Could not read OIDC RSA key from config file; %s\n"),
902 error.text);
903 }
904
905 return jwk;
906}
907
908
916static int
918 json_t *jwk)
919{
920 if (json_dump_file (jwk, filename, JSON_INDENT (2)))
921 {
923 ("Could not write OIDC RSA key to file %s\n"),
924 filename);
926 }
927 else
928 return GNUNET_OK;
929}
930
931
937json_t *
939{
940 json_t *jwk;
941 jwk = json_pack ("{s:s,s:i}", "kty", "RSA", "bits", 2048);
942 jose_jwk_gen (NULL, jwk);
943 json_incref (jwk);
944 return jwk;
945}
946
947
953char *
955{
956 char *oidc_directory;
957 struct RequestHandle *handle = cls;
958
959 // Read OIDC directory from config
961 "reclaim-rest-plugin",
962 "oidc_dir",
963 &oidc_directory))
964 {
965 // Could not read Config file
967 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
968 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
970 return NULL;
971 }
972
973 return oidc_directory;
974}
975
976
982char *
984{
985 char *oidc_directory;
986 char *oidc_jwk_path;
987
988 oidc_directory = get_oidc_dir_path (cls);
989
990 // Create path to file
991 GNUNET_asprintf (&oidc_jwk_path, "%s/%s", oidc_directory,
993
994 return oidc_jwk_path;
995}
996
997
1001static void
1003{
1004 char *login_base_url;
1005 char *new_redirect;
1006 char *tmp;
1007 struct MHD_Response *resp;
1008 struct GNUNET_Buffer buf = { 0 };
1009 struct RequestHandle *handle = cls;
1010
1012 "reclaim-rest-plugin",
1013 "address",
1014 &login_base_url))
1015 {
1016 GNUNET_buffer_write_str (&buf, login_base_url);
1018 "?%s=%s",
1020 handle->oidc->response_type);
1022 "&%s=%s",
1024 handle->oidc->client_id);
1025 GNUNET_STRINGS_urlencode (strlen (handle->oidc->redirect_uri),
1026 handle->oidc->redirect_uri,
1027 &tmp);
1029 "&%s=%s",
1031 tmp);
1032 GNUNET_free (tmp);
1033 GNUNET_STRINGS_urlencode (strlen (handle->oidc->scope),
1034 handle->oidc->scope,
1035 &tmp);
1037 "&%s=%s",
1039 tmp);
1040 GNUNET_free (tmp);
1041 if (NULL != handle->oidc->state)
1042 {
1043 GNUNET_STRINGS_urlencode (strlen (handle->oidc->state),
1044 handle->oidc->state,
1045 &tmp);
1047 "&%s=%s",
1049 handle->oidc->state);
1050 GNUNET_free (tmp);
1051 }
1052 if (NULL != handle->oidc->code_challenge)
1053 {
1055 "&%s=%s",
1057 handle->oidc->code_challenge);
1058 }
1059 if (NULL != handle->oidc->nonce)
1060 {
1062 "&%s=%s",
1064 handle->oidc->nonce);
1065 }
1066 if (NULL != handle->oidc->claims)
1067 {
1068 GNUNET_STRINGS_urlencode (strlen (handle->oidc->claims),
1069 handle->oidc->claims,
1070 &tmp);
1072 "&%s=%s",
1074 tmp);
1075 GNUNET_free (tmp);
1076 }
1077 new_redirect = GNUNET_buffer_reap_str (&buf);
1078 resp = GNUNET_REST_create_response ("");
1079 MHD_add_response_header (resp, "Location", new_redirect);
1080 GNUNET_free (login_base_url);
1081 }
1082 else
1083 {
1085 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
1086 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1088 return;
1089 }
1090 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1091 GNUNET_free (new_redirect);
1093}
1094
1095
1099static void
1101{
1102 struct RequestHandle *handle = cls;
1103
1105 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1107}
1108
1109
1114static void
1116 const struct GNUNET_RECLAIM_Ticket *ticket,
1117 const struct
1118 GNUNET_RECLAIM_PresentationList *presentation)
1119{
1120 struct RequestHandle *handle = cls;
1121 struct MHD_Response *resp;
1122 char *ticket_str;
1123 char *redirect_uri;
1124 char *code_string;
1125
1126 handle->idp_op = NULL;
1127 if (NULL == ticket)
1128 {
1130 handle->edesc = GNUNET_strdup ("Server cannot generate ticket.");
1132 return;
1133 }
1134 handle->ticket = *ticket;
1135 ticket_str =
1137 sizeof(struct GNUNET_RECLAIM_Ticket));
1138 code_string = OIDC_build_authz_code (&handle->priv_key,
1139 &handle->ticket,
1140 handle->attr_idtoken_list,
1141 presentation,
1142 handle->oidc->nonce,
1143 handle->oidc->code_challenge);
1144 if ((NULL != handle->redirect_prefix) && (NULL != handle->redirect_suffix) &&
1145 (NULL != handle->tld))
1146 {
1147 GNUNET_asprintf (&redirect_uri,
1148 "%s.%s/%s%s%s=%s&state=%s",
1149 handle->redirect_prefix,
1150 handle->tld,
1151 handle->redirect_suffix,
1152 (NULL == strchr (handle->redirect_suffix, '?') ? "?" :
1153 "&"),
1154 handle->oidc->response_type,
1155 code_string,
1156 handle->oidc->state);
1157 }
1158 else
1159 {
1160 GNUNET_asprintf (&redirect_uri,
1161 "%s%s%s=%s&state=%s",
1162 handle->oidc->redirect_uri,
1163 (NULL == strchr (handle->oidc->redirect_uri, '?') ? "?" :
1164 "&"),
1165 handle->oidc->response_type,
1166 code_string,
1167 handle->oidc->state);
1168 }
1169 resp = GNUNET_REST_create_response ("");
1170 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1171 "Location", redirect_uri));
1172 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1174 GNUNET_free (redirect_uri);
1175 GNUNET_free (ticket_str);
1176 GNUNET_free (code_string);
1177}
1178
1179
1180static struct GNUNET_RECLAIM_AttributeList*
1182 struct GNUNET_RECLAIM_AttributeList *list_b)
1183{
1184 struct GNUNET_RECLAIM_AttributeList *merged_list;
1188
1189 merged_list = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
1190 for (le_a = list_a->list_head; NULL != le_a; le_a = le_a->next)
1191 {
1194 &le_a->attribute->
1195 credential,
1196 le_a->attribute->type,
1197 le_a->attribute->data,
1198 le_a->attribute->data_size);
1199 le_m->attribute->id = le_a->attribute->id;
1200 le_m->attribute->flag = le_a->attribute->flag;
1201 le_m->attribute->credential = le_a->attribute->credential;
1203 merged_list->list_tail,
1204 le_m);
1205 }
1206 le_m = NULL;
1207 for (le_b = list_b->list_head; NULL != le_b; le_b = le_b->next)
1208 {
1209 for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1210 {
1212 &le_b->attribute->id))
1213 break;
1214 }
1215 if (NULL != le_m)
1216 continue;
1219 &le_b->attribute->
1220 credential,
1221 le_b->attribute->type,
1222 le_b->attribute->data,
1223 le_b->attribute->data_size);
1224 le_m->attribute->id = le_b->attribute->id;
1225 le_m->attribute->flag = le_b->attribute->flag;
1226 le_m->attribute->credential = le_b->attribute->credential;
1228 merged_list->list_tail,
1229 le_m);
1230 }
1231 return merged_list;
1232}
1233
1234
1235static void
1237{
1238 struct RequestHandle *handle = cls;
1239 struct GNUNET_RECLAIM_AttributeList *merged_list;
1241
1242 handle->cred_it = NULL;
1243 merged_list = attribute_list_merge (handle->attr_idtoken_list,
1244 handle->attr_userinfo_list);
1245 for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1247 "List Attribute in ticket to issue: %s\n",
1248 le_m->attribute->name);
1250 &handle->priv_key,
1251 &handle->oidc->client_pkey,
1252 merged_list,
1254 handle);
1256}
1257
1258
1262static void
1264 const struct GNUNET_CRYPTO_PublicKey *identity,
1265 const struct GNUNET_RECLAIM_Credential *cred)
1266{
1267 struct RequestHandle *handle = cls;
1270
1271 for (ale = handle->credentials->list_head; NULL != ale; ale = ale->next)
1272 {
1274 &cred->id))
1275 continue;
1278 return;
1279 }
1280
1281 for (le = handle->attr_idtoken_list->list_head; NULL != le; le = le->next)
1282 {
1284 &cred->id))
1285 continue;
1289 cred->type,
1290 cred->data,
1291 cred->data_size);
1292 GNUNET_CONTAINER_DLL_insert (handle->credentials->list_head,
1293 handle->credentials->list_tail,
1294 ale);
1295 }
1297}
1298
1299
1300static void
1302{
1303 struct RequestHandle *handle = cls;
1304
1305 handle->attr_it = NULL;
1306 handle->ticket_it = NULL;
1307 if (NULL == handle->attr_idtoken_list->list_head)
1308 {
1310 handle->edesc = GNUNET_strdup ("The requested scope is not available.");
1312 return;
1313 }
1314 handle->credentials = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
1315 handle->cred_it =
1317 &handle->priv_key,
1319 handle,
1321 handle,
1323 handle);
1324
1325}
1326
1327
1328static int
1330 const char *attr_name,
1331 const char *claims_parameter)
1332{
1333 int ret = GNUNET_NO;
1334 json_t *root;
1335 json_error_t error;
1336 json_t *claims_j;
1337 const char *key;
1338 json_t *value;
1339
1342 attr_name))
1343 return GNUNET_YES;
1344
1346 if (NULL != handle->oidc->claims)
1347 {
1348 root = json_loads (handle->oidc->claims, JSON_DECODE_ANY, &error);
1349 claims_j = json_object_get (root, claims_parameter);
1350 /* obj is a JSON object */
1351 if (NULL != claims_j)
1352 {
1353 json_object_foreach (claims_j, key, value) {
1354 if (0 != strcmp (attr_name, key))
1355 continue;
1356 ret = GNUNET_YES;
1357 break;
1358 }
1359 }
1360 json_decref (root);
1361 }
1362 return ret;
1363}
1364
1365
1366static int
1368 const char *attr_name)
1369{
1370 return attr_in_claims_request (handle, attr_name, "id_token");
1371}
1372
1373
1374static int
1376 const char *attr_name)
1377{
1378 return attr_in_claims_request (handle, attr_name, "userinfo");
1379}
1380
1381
1385static void
1387 const struct GNUNET_CRYPTO_PublicKey *identity,
1388 const struct GNUNET_RECLAIM_Attribute *attr)
1389{
1390 struct RequestHandle *handle = cls;
1393 {
1396 &attr->credential,
1397 attr->type,
1398 attr->data,
1399 attr->data_size);
1400 le->attribute->id = attr->id;
1401 le->attribute->flag = attr->flag;
1402 le->attribute->credential = attr->credential;
1403 GNUNET_CONTAINER_DLL_insert (handle->attr_idtoken_list->list_head,
1404 handle->attr_idtoken_list->list_tail,
1405 le);
1406 }
1408 {
1411 &attr->credential,
1412 attr->type,
1413 attr->data,
1414 attr->data_size);
1415 le->attribute->id = attr->id;
1416 le->attribute->flag = attr->flag;
1417 le->attribute->credential = attr->credential;
1418 GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
1419 handle->attr_userinfo_list->list_tail,
1420 le);
1421 }
1422
1424}
1425
1426
1430static void
1431code_redirect (void *cls)
1432{
1433 struct RequestHandle *handle = cls;
1434 struct GNUNET_TIME_Absolute current_time;
1435 struct GNUNET_TIME_Absolute *relog_time;
1437 struct GNUNET_CRYPTO_PublicKey ego_pkey;
1438 struct GNUNET_HashCode cache_key;
1439 char *identity_cookie;
1440
1441 GNUNET_asprintf (&identity_cookie,
1442 "Identity=%s",
1443 handle->oidc->login_identity);
1444 GNUNET_CRYPTO_hash (identity_cookie, strlen (identity_cookie), &cache_key);
1445 GNUNET_free (identity_cookie);
1446 // No login time for identity -> redirect to login
1447 if (GNUNET_YES ==
1449 {
1450 relog_time =
1452 current_time = GNUNET_TIME_absolute_get ();
1453 // 30 min after old login -> redirect to login
1454 if (current_time.abs_value_us <= relog_time->abs_value_us)
1455 {
1456 if (GNUNET_OK !=
1458 ->login_identity,
1459 &pubkey))
1460 {
1462 handle->edesc =
1463 GNUNET_strdup ("The cookie of a login identity is not valid");
1465 return;
1466 }
1467 // iterate over egos and compare their public key
1468 for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
1469 handle->ego_entry = handle->ego_entry->next)
1470 {
1471 GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey);
1472 if (0 == GNUNET_memcmp (&ego_pkey, &pubkey))
1473 {
1474 handle->priv_key =
1476 handle->attr_idtoken_list =
1478 handle->attr_userinfo_list =
1480 handle->attr_it =
1482 &handle->priv_key,
1484 handle,
1486 handle,
1488 handle);
1489 return;
1490 }
1491 }
1493 return;
1494 }
1495 }
1496}
1497
1498
1499static void
1501{
1502 struct RequestHandle *handle = cls;
1503 struct MHD_Response *resp;
1504 char *redirect_uri;
1505
1506 if (GNUNET_YES == handle->oidc->user_cancelled)
1507 {
1508 if ((NULL != handle->redirect_prefix) &&
1509 (NULL != handle->redirect_suffix) && (NULL != handle->tld))
1510 {
1511 GNUNET_asprintf (&redirect_uri,
1512 "%s.%s/%s?error=%s&error_description=%s&state=%s",
1513 handle->redirect_prefix,
1514 handle->tld,
1515 handle->redirect_suffix,
1516 "access_denied",
1517 "User denied access",
1518 handle->oidc->state);
1519 }
1520 else
1521 {
1522 GNUNET_asprintf (&redirect_uri,
1523 "%s?error=%s&error_description=%s&state=%s",
1524 handle->oidc->redirect_uri,
1525 "access_denied",
1526 "User denied access",
1527 handle->oidc->state);
1528 }
1529 resp = GNUNET_REST_create_response ("");
1530 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1531 "Location",
1532 redirect_uri));
1533 handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1535 GNUNET_free (redirect_uri);
1536 return;
1537 }
1539}
1540
1541
1542static void
1544 uint32_t rd_count,
1545 const struct GNUNET_GNSRECORD_Data *rd)
1546{
1547 struct RequestHandle *handle = cls;
1548 char *tmp;
1549 char *tmp_key_str;
1550 char *pos;
1551 struct GNUNET_CRYPTO_PublicKey redirect_zone;
1552
1553 handle->gns_op = NULL;
1554 if (0 == rd_count)
1555 {
1557 handle->edesc =
1558 GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1560 return;
1561 }
1562 for (int i = 0; i < rd_count; i++)
1563 {
1564 if (GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT != rd[i].record_type)
1565 continue;
1566 if (0 != strncmp (rd[i].data, handle->oidc->redirect_uri, rd[i].data_size))
1567 continue;
1568 tmp = GNUNET_strndup (rd[i].data, rd[i].data_size);
1569 if (NULL == strstr (tmp, handle->oidc->client_id))
1570 {
1572 "Redirect uri %s does not contain client_id %s\n",
1573 tmp,
1574 handle->oidc->client_id);
1575 }
1576 else
1577 {
1578 pos = strrchr (tmp, (unsigned char) '.');
1579 if (NULL == pos)
1580 {
1582 "Redirect uri %s contains client_id but is malformed\n",
1583 tmp);
1584 GNUNET_free (tmp);
1585 continue;
1586 }
1587 *pos = '\0';
1588 handle->redirect_prefix = GNUNET_strdup (tmp);
1589 tmp_key_str = pos + 1;
1590 pos = strchr (tmp_key_str, (unsigned char) '/');
1591 if (NULL == pos)
1592 {
1594 "Redirect uri %s contains client_id but is malformed\n",
1595 tmp);
1596 GNUNET_free (tmp);
1597 continue;
1598 }
1599 *pos = '\0';
1600 handle->redirect_suffix = GNUNET_strdup (pos + 1);
1601
1602 GNUNET_STRINGS_string_to_data (tmp_key_str,
1603 strlen (tmp_key_str),
1604 &redirect_zone,
1605 sizeof(redirect_zone));
1606 }
1608 GNUNET_free (tmp);
1609 return;
1610 }
1612 handle->edesc =
1613 GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1615}
1616
1617
1621static void
1623{
1624 struct RequestHandle *handle = cls;
1625
1626 /* Lookup client redirect uri to verify request */
1627 handle->gns_op =
1630 &handle->oidc->client_pkey,
1634 handle);
1635}
1636
1637
1638static char *
1640{
1641 struct GNUNET_HashCode hc;
1642 char *value;
1643 char *res;
1644
1645 GNUNET_CRYPTO_hash (key, strlen (key), &hc);
1647 ->url_param_map,
1648 &hc))
1649 return NULL;
1650 value =
1651 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, &hc);
1652 if (NULL == value)
1653 return NULL;
1655 return res;
1656}
1657
1658
1665static void
1667{
1668 struct RequestHandle *handle = cls;
1669 struct GNUNET_HashCode cache_key;
1670
1671 char *expected_scope;
1672 char delimiter[] = " ";
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 char *test;
1750 test = strtok (expected_scope, delimiter);
1751 while (NULL != test)
1752 {
1753 if (0 == strcmp (OIDC_EXPECTED_AUTHORIZATION_SCOPE, expected_scope))
1754 break;
1755 test = strtok (NULL, delimiter);
1756 }
1757 if (NULL == test)
1758 {
1760 handle->edesc =
1761 GNUNET_strdup ("The requested scope is invalid, unknown, or malformed.");
1763 GNUNET_free (expected_scope);
1764 return;
1765 }
1766
1767 GNUNET_free (expected_scope);
1768 if ((NULL == handle->oidc->login_identity) &&
1769 (GNUNET_NO == handle->oidc->user_cancelled))
1771 else
1773}
1774
1775
1779static void
1780tld_iter (void *cls, const char *section, const char *option, const char *value)
1781{
1782 struct RequestHandle *handle = cls;
1784
1785 if (GNUNET_OK !=
1787 {
1788 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Skipping non key %s\n", value);
1789 return;
1790 }
1791 if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1792 handle->tld = GNUNET_strdup (option + 1);
1793}
1794
1795
1803static void
1805 const char *url,
1806 void *cls)
1807{
1808 struct RequestHandle *handle = cls;
1809 struct EgoEntry *tmp_ego;
1810 const struct GNUNET_CRYPTO_PrivateKey *priv_key;
1812
1814
1815 // RECOMMENDED value: state - REQUIRED for answers
1817
1818 // REQUIRED value: client_id
1820 if (NULL == handle->oidc->client_id)
1821 {
1823 handle->edesc = GNUNET_strdup ("missing parameter client_id");
1824 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1826 return;
1827 }
1828
1829 // OPTIONAL value: code_challenge
1830 handle->oidc->code_challenge = get_url_parameter_copy (handle,
1832 if (NULL == handle->oidc->code_challenge)
1833 {
1835 "OAuth authorization request does not contain PKCE parameters!\n");
1836 }
1837
1838 if (GNUNET_OK !=
1840 &handle->oidc->client_pkey))
1841 {
1843 handle->edesc = GNUNET_strdup ("The client is not authorized to request an "
1844 "authorization code using this method.");
1845 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1847 return;
1848 }
1849
1850 // If we know this identity, translated the corresponding TLD
1851 // TODO: We might want to have a reverse lookup functionality for TLDs?
1852 for (tmp_ego = ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next)
1853 {
1854 priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego);
1856 if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1857 {
1858 handle->tld = GNUNET_strdup (tmp_ego->identifier);
1859 handle->ego_entry = ego_tail;
1860 }
1861 }
1862 if (NULL == handle->tld)
1864 handle);
1865 if (NULL == handle->tld)
1866 handle->tld = GNUNET_strdup (handle->oidc->client_id);
1868}
1869
1870
1878static void
1880 const char *url,
1881 void *cls)
1882{
1883 struct MHD_Response *resp = GNUNET_REST_create_response ("");
1884 struct RequestHandle *handle = cls;
1885 struct GNUNET_HashCode cache_key;
1886 struct GNUNET_TIME_Absolute *current_time;
1887 struct GNUNET_TIME_Absolute *last_time;
1888 char *cookie;
1889 char *header_val;
1890 json_t *root;
1891 json_error_t error;
1892 json_t *identity;
1893 char term_data[handle->rest_handle->data_size + 1];
1894
1895 term_data[handle->rest_handle->data_size] = '\0';
1896 GNUNET_memcpy (term_data,
1897 handle->rest_handle->data,
1898 handle->rest_handle->data_size);
1899 root = json_loads (term_data, JSON_DECODE_ANY, &error);
1900 identity = json_object_get (root, "identity");
1901 if (! json_is_string (identity))
1902 {
1904 "Error parsing json string from %s\n",
1905 term_data);
1906 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
1907 json_decref (root);
1909 return;
1910 }
1911 GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity));
1912 GNUNET_asprintf (&header_val,
1913 "%s;Max-Age=%d",
1914 cookie,
1916 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1917 "Set-Cookie", header_val));
1918 GNUNET_assert (MHD_NO !=
1919 MHD_add_response_header (resp,
1920 "Access-Control-Allow-Methods",
1921 "POST"));
1922 GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key);
1923
1924 if (0 != strcmp (json_string_value (identity), "Denied"))
1925 {
1926 current_time = GNUNET_new (struct GNUNET_TIME_Absolute);
1927 *current_time = GNUNET_TIME_relative_to_absolute (
1930 last_time =
1932 GNUNET_free (last_time);
1934 &cache_key,
1935 current_time,
1937 }
1938 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1939 GNUNET_free (cookie);
1940 GNUNET_free (header_val);
1941 json_decref (root);
1943}
1944
1945
1946static int
1948 char **client_id,
1949 char **client_secret)
1950{
1951 struct GNUNET_HashCode cache_key;
1952 char *authorization;
1953 char *credentials;
1954 char *basic_authorization;
1955 char *client_id_tmp;
1956 char *pass;
1957
1960 &cache_key);
1962 ->header_param_map,
1963 &cache_key))
1964 return GNUNET_SYSERR;
1965 authorization =
1966 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
1967 &cache_key);
1968
1969 // split header in "Basic" and [content]
1970 credentials = strtok (authorization, " ");
1971 if ((NULL == credentials) || (0 != strcmp ("Basic", credentials)))
1972 return GNUNET_SYSERR;
1973 credentials = strtok (NULL, " ");
1974 if (NULL == credentials)
1975 return GNUNET_SYSERR;
1976 GNUNET_STRINGS_base64_decode (credentials,
1977 strlen (credentials),
1978 (void **) &basic_authorization);
1979
1980 if (NULL == basic_authorization)
1981 return GNUNET_SYSERR;
1982 client_id_tmp = strtok (basic_authorization, ":");
1983 if (NULL == client_id_tmp)
1984 {
1985 GNUNET_free (basic_authorization);
1986 return GNUNET_SYSERR;
1987 }
1988 pass = strtok (NULL, ":");
1989 if (NULL == pass)
1990 {
1991 GNUNET_free (basic_authorization);
1992 return GNUNET_SYSERR;
1993 }
1994 *client_id = strdup (client_id_tmp);
1995 *client_secret = strdup (pass);
1996 GNUNET_free (basic_authorization);
1997 return GNUNET_OK;
1998}
1999
2000
2001static int
2003 char **client_id,
2004 char **client_secret)
2005{
2006 struct GNUNET_HashCode cache_key;
2007 char *client_id_tmp;
2008 char *pass;
2009
2010 GNUNET_CRYPTO_hash ("client_id",
2011 strlen ("client_id"),
2012 &cache_key);
2014 ->url_param_map,
2015 &cache_key))
2016 return GNUNET_SYSERR;
2017 client_id_tmp = GNUNET_CONTAINER_multihashmap_get (
2018 handle->rest_handle->url_param_map,
2019 &cache_key);
2020 if (NULL == client_id_tmp)
2021 return GNUNET_SYSERR;
2022 *client_id = strdup (client_id_tmp);
2023 GNUNET_CRYPTO_hash ("client_secret",
2024 strlen ("client_secret"),
2025 &cache_key);
2027 ->url_param_map,
2028 &cache_key))
2029 {
2030 GNUNET_free (*client_id);
2031 *client_id = NULL;
2032 return GNUNET_SYSERR;
2033 }
2034 pass = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
2035 &cache_key);
2036 if (NULL == pass)
2037 {
2038 GNUNET_free (*client_id);
2039 *client_id = NULL;
2040 return GNUNET_SYSERR;
2041 }
2042 *client_secret = strdup (pass);
2043 return GNUNET_OK;
2044}
2045
2046
2047static int
2049 struct GNUNET_CRYPTO_PublicKey *cid)
2050{
2051 char *expected_pass;
2052 char *received_cid;
2053 char *received_cpw;
2054 char *pkce_cv;
2055
2057 &received_cid,
2058 &received_cpw))
2059 {
2061 "Received client credentials in HTTP AuthZ header\n");
2062 }
2064 &received_cid,
2065 &received_cpw))
2066 {
2068 "Received client credentials in POST body\n");
2069 }
2070 else
2071 {
2074 if (NULL == pkce_cv)
2075 {
2077 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2078 return GNUNET_SYSERR;
2079 }
2080 handle->public_client = GNUNET_YES;
2081 GNUNET_free (pkce_cv);
2083 GNUNET_STRINGS_string_to_data (received_cid,
2084 strlen (received_cid),
2085 cid,
2086 sizeof(struct GNUNET_CRYPTO_PublicKey));
2087 GNUNET_free (received_cid);
2088 return GNUNET_OK;
2089
2090 }
2091
2092 // check client password
2094 "reclaim-rest-plugin",
2095 "OIDC_CLIENT_HMAC_SECRET",
2096 &expected_pass))
2097 {
2098 if (0 != strcmp (expected_pass, received_cpw))
2099 {
2100 GNUNET_free (expected_pass);
2102 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2103 GNUNET_free (received_cpw);
2104 GNUNET_free (received_cid);
2105 return GNUNET_SYSERR;
2106 }
2107 GNUNET_free (expected_pass);
2108 }
2109 else
2110 {
2111 GNUNET_free (received_cpw);
2112 GNUNET_free (received_cid);
2114 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
2115 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2116 return GNUNET_SYSERR;
2117 }
2118 // check client_id
2119 for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
2120 handle->ego_entry = handle->ego_entry->next)
2121 {
2122 if (0 == strcmp (handle->ego_entry->keystring, received_cid))
2123 break;
2124 }
2125 if (NULL == handle->ego_entry)
2126 {
2127 GNUNET_free (received_cpw);
2128 GNUNET_free (received_cid);
2130 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2131 return GNUNET_SYSERR;
2132 }
2133 GNUNET_STRINGS_string_to_data (received_cid,
2134 strlen (received_cid),
2135 cid,
2136 sizeof(struct GNUNET_CRYPTO_PublicKey));
2137
2138 GNUNET_free (received_cpw);
2139 GNUNET_free (received_cid);
2140 return GNUNET_OK;
2141}
2142
2143
2144const struct EgoEntry *
2146 struct GNUNET_CRYPTO_PublicKey *test_key)
2147{
2148 struct EgoEntry *ego_entry;
2149 struct GNUNET_CRYPTO_PublicKey pub_key;
2150
2151 for (ego_entry = ego_head; NULL != ego_entry;
2152 ego_entry = ego_entry->next)
2153 {
2154 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key);
2155 if (0 == GNUNET_memcmp (&pub_key, test_key))
2156 return ego_entry;
2157 }
2158 return NULL;
2159}
2160
2161
2169static void
2171 const char *url,
2172 void *cls)
2173{
2174 struct RequestHandle *handle = cls;
2175 const struct EgoEntry *ego_entry = NULL;
2176 struct GNUNET_TIME_Relative expiration_time;
2177 struct GNUNET_RECLAIM_AttributeList *cl = NULL;
2178 struct GNUNET_RECLAIM_PresentationList *pl = NULL;
2180 struct GNUNET_CRYPTO_PublicKey cid;
2181 struct GNUNET_HashCode cache_key;
2182 struct MHD_Response *resp = NULL;
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 = NULL;
2193 char *oidc_jwk_path = NULL;
2194 char *oidc_directory = NULL;
2195 char *tmp_at = NULL;
2196
2197 /*
2198 * Check Authorization
2199 */
2201 {
2203 "OIDC authorization for token endpoint failed\n");
2205 return;
2206 }
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 if (GNUNET_OK != OIDC_parse_authz_code (&cid, code, code_verifier, &ticket,
2269 &cl, &pl, &nonce,
2271 {
2273 handle->edesc = GNUNET_strdup ("invalid code");
2274 handle->response_code = MHD_HTTP_BAD_REQUEST;
2275 GNUNET_free (code);
2276 if (NULL != code_verifier)
2277 GNUNET_free (code_verifier);
2279 return;
2280 }
2281 if (NULL != code_verifier)
2282 GNUNET_free (code_verifier);
2283
2284 // create jwt
2286 "reclaim-rest-plugin",
2287 "expiration_time",
2288 &expiration_time))
2289 {
2291 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
2292 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2293 GNUNET_free (code);
2294 if (NULL != nonce)
2295 GNUNET_free (nonce);
2299 return;
2300 }
2301
2302 // Check if HMAC or RSA should be used
2304 "reclaim-rest-plugin",
2305 "oidc_json_web_algorithm",
2306 &jwa))
2307 {
2309 "Could not read OIDC JSON Web Algorithm config attribute."
2310 "Defaulting to RS256.");
2311 jwa = JWT_ALG_VALUE_RSA;
2312 }
2313
2314 if (! strcmp (jwa, JWT_ALG_VALUE_RSA))
2315 {
2316 // Replace for now
2317 oidc_jwk_path = get_oidc_jwk_path (cls);
2318 oidc_jwk = read_jwk_from_file (oidc_jwk_path);
2319
2320 // Check if secret JWK exists
2321 if (! oidc_jwk)
2322 {
2323 // Generate and save a new key
2325 oidc_directory = get_oidc_dir_path (cls);
2326
2327 // Create new oidc directory
2328 if (GNUNET_OK != GNUNET_DISK_directory_create (oidc_directory))
2329 {
2331 ("Failed to create directory `%s' for storing oidc data\n"),
2332 oidc_directory);
2333 }
2334 else
2335 {
2336 write_jwk_to_file (oidc_jwk_path, oidc_jwk);
2337 }
2338 }
2339
2340 // Generate oidc token
2343 cl,
2344 pl,
2345 &expiration_time,
2346 (NULL != nonce) ? nonce : NULL,
2347 oidc_jwk);
2348 }
2349 else if (! strcmp (jwa, JWT_ALG_VALUE_HMAC))
2350 {
2351 // TODO OPTIONAL acr,amr,azp
2353 "reclaim-rest-plugin",
2354 "jwt_secret",
2355 &jwt_secret))
2356 {
2358 handle->edesc = GNUNET_strdup ("No signing secret configured!");
2359 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2360 GNUNET_free (code);
2363 if (NULL != nonce)
2364 GNUNET_free (nonce);
2366 return;
2367 }
2368
2371 cl,
2372 pl,
2373 &expiration_time,
2374 (NULL != nonce) ? nonce : NULL,
2375 jwt_secret);
2376
2377 GNUNET_free (jwt_secret);
2378 }
2379 else
2380 {
2381 // TODO: OPTION NOT FOUND ERROR
2382 }
2383
2384 if (NULL != nonce)
2385 GNUNET_free (nonce);
2386 access_token = OIDC_access_token_new (&ticket);
2391 GNUNET_CRYPTO_hash (access_token,
2392 strlen (access_token),
2393 &cache_key);
2405 &cache_key);
2407 &cache_key,
2408 code,
2410 /* If there was a previous code in there, free the old value */
2411 if (NULL != tmp_at)
2412 {
2414 "OIDC access token already issued. Cleanup.\n");
2415 GNUNET_free (tmp_at);
2416 }
2417
2418 OIDC_build_token_response (access_token,
2419 id_token,
2420 &expiration_time,
2421 &json_response);
2422
2423 resp = GNUNET_REST_create_response (json_response);
2424 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2425 "Cache-Control",
2426 "no-store"));
2427 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2428 "Pragma", "no-cache"));
2429 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2430 "Content-Type",
2431 "application/json"));
2432 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2435 GNUNET_free (access_token);
2436 GNUNET_free (json_response);
2437 GNUNET_free (id_token);
2439}
2440
2441
2445static void
2447 const struct GNUNET_CRYPTO_PublicKey *identity,
2448 const struct GNUNET_RECLAIM_Attribute *attr,
2449 const struct GNUNET_RECLAIM_Presentation *presentation)
2450{
2451 struct RequestHandle *handle = cls;
2454 struct MHD_Response *resp;
2455 struct GNUNET_HashCode cache_key;
2456 char *result_str;
2457 char *cached_code;
2458
2459 if (NULL != handle->consume_timeout_op)
2460 GNUNET_SCHEDULER_cancel (handle->consume_timeout_op);
2461 handle->consume_timeout_op = NULL;
2462 handle->idp_op = NULL;
2463
2467 GNUNET_CRYPTO_hash (handle->access_token,
2468 strlen (handle->access_token),
2469 &cache_key);
2471 &cache_key);
2472 if (NULL != cached_code)
2473 {
2476 &cache_key,
2477 cached_code));
2478 GNUNET_free (cached_code);
2479 }
2480
2481
2482 if (NULL == identity)
2483 {
2484 result_str = OIDC_generate_userinfo (&handle->ticket.identity,
2485 handle->attr_userinfo_list,
2486 handle->presentations);
2487 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2488 resp = GNUNET_REST_create_response (result_str);
2489 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2490 GNUNET_free (result_str);
2492 return;
2493 }
2496 &attr->credential,
2497 attr->type,
2498 attr->data,
2499 attr->data_size);
2500 ale->attribute->id = attr->id;
2501 ale->attribute->flag = attr->flag;
2502 ale->attribute->credential = attr->credential;
2503 GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
2504 handle->attr_userinfo_list->list_tail,
2505 ale);
2506 if (NULL == presentation)
2507 return;
2508 for (atle = handle->presentations->list_head;
2509 NULL != atle; atle = atle->next)
2510 {
2513 &presentation->credential_id))
2514 continue;
2515 break;
2516 }
2517 if (NULL == atle)
2518 {
2521 atle->presentation = GNUNET_RECLAIM_presentation_new (presentation->type,
2522 presentation->data,
2523 presentation->
2524 data_size);
2525 atle->presentation->credential_id = presentation->credential_id;
2526 GNUNET_CONTAINER_DLL_insert (handle->presentations->list_head,
2527 handle->presentations->list_tail,
2528 atle);
2529 }
2530}
2531
2532
2533static void
2534consume_fail (void *cls)
2535{
2536 struct RequestHandle *handle = cls;
2537 struct GNUNET_HashCode cache_key;
2538 struct GNUNET_RECLAIM_AttributeList *cl = NULL;
2539 struct GNUNET_RECLAIM_PresentationList *pl = NULL;
2541 struct MHD_Response *resp;
2542 char *nonce;
2543 char *cached_code;
2544 char *result_str;
2545
2546
2547 handle->consume_timeout_op = NULL;
2548 if (NULL != handle->idp_op)
2549 GNUNET_RECLAIM_cancel (handle->idp_op);
2550 handle->idp_op = NULL;
2551
2553 "Ticket consumptioned timed out. Using cache...\n");
2554 GNUNET_CRYPTO_hash (handle->access_token,
2555 strlen (handle->access_token),
2556 &cache_key);
2558 &cache_key);
2559 if (NULL == cached_code)
2560 {
2562 handle->edesc = GNUNET_strdup ("No Access Token in cache!");
2563 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2565 return;
2566 }
2572 &cache_key,
2573 cached_code));
2574
2575 // decode code
2576 if (GNUNET_OK != OIDC_parse_authz_code (&handle->ticket.audience,
2577 cached_code, NULL, &ticket,
2578 &cl, &pl, &nonce,
2580 {
2582 handle->edesc = GNUNET_strdup ("invalid code");
2583 handle->response_code = MHD_HTTP_BAD_REQUEST;
2584 GNUNET_free (cached_code);
2585 if (NULL != nonce)
2586 GNUNET_free (nonce);
2588 return;
2589 }
2590
2591 GNUNET_free (cached_code);
2592
2593 result_str = OIDC_generate_userinfo (&handle->ticket.identity,
2594 cl,
2595 pl);
2596 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2597 resp = GNUNET_REST_create_response (result_str);
2598 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2599 GNUNET_free (result_str);
2600 GNUNET_free (nonce);
2604}
2605
2606
2614static void
2616 const char *url,
2617 void *cls)
2618{
2619 // TODO expiration time
2620 struct RequestHandle *handle = cls;
2622 char delimiter[] = " ";
2623 struct GNUNET_HashCode cache_key;
2624 char *authorization;
2625 char *authorization_type;
2626 char *authorization_access_token;
2627 const struct EgoEntry *aud_ego;
2628 const struct GNUNET_CRYPTO_PrivateKey *privkey;
2629
2630 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting userinfo\n");
2633 &cache_key);
2635 ->header_param_map,
2636 &cache_key))
2637 {
2639 handle->edesc = GNUNET_strdup ("No Access Token");
2640 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2642 return;
2643 }
2644 authorization =
2645 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
2646 &cache_key);
2647
2648 // split header in "Bearer" and access_token
2649 authorization = GNUNET_strdup (authorization);
2650 authorization_type = strtok (authorization, delimiter);
2651 if ((NULL == authorization_type) ||
2652 (0 != strcmp ("Bearer", authorization_type)))
2653 {
2655 handle->edesc = GNUNET_strdup ("No Access Token");
2656 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2658 GNUNET_free (authorization);
2659 return;
2660 }
2661 authorization_access_token = strtok (NULL, delimiter);
2662 if (NULL == authorization_access_token)
2663 {
2665 handle->edesc = GNUNET_strdup ("Access token missing");
2666 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2668 GNUNET_free (authorization);
2669 return;
2670 }
2671
2672 if (GNUNET_OK != OIDC_access_token_parse (authorization_access_token,
2673 &ticket))
2674 {
2676 handle->edesc = GNUNET_strdup ("The access token is invalid");
2677 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2679 GNUNET_free (authorization);
2680 return;
2681
2682 }
2683 GNUNET_assert (NULL != ticket);
2684 handle->ticket = *ticket;
2686 aud_ego = find_ego (handle, &handle->ticket.audience);
2687 if (NULL == aud_ego)
2688 {
2690 handle->edesc = GNUNET_strdup ("The access token expired");
2691 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2693 GNUNET_free (authorization);
2694 return;
2695 }
2696 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Consuming ticket\n");
2697 privkey = GNUNET_IDENTITY_ego_get_private_key (aud_ego->ego);
2698 handle->attr_userinfo_list =
2700 handle->presentations =
2702
2703 /* If the consume takes too long, we use values from the cache */
2704 handle->access_token = GNUNET_strdup (authorization_access_token);
2706 &consume_fail,
2707 handle);
2709 privkey,
2710 &handle->ticket,
2712 handle);
2713 GNUNET_free (authorization);
2714}
2715
2716
2724static void
2726 const char *url,
2727 void *cls)
2728{
2729 char *oidc_directory;
2730 char *oidc_jwk_path;
2731 char *oidc_jwk_pub_str;
2732 json_t *oidc_jwk;
2733 struct MHD_Response *resp;
2734 struct RequestHandle *handle = cls;
2735
2736 oidc_jwk_path = get_oidc_jwk_path (cls);
2737 oidc_jwk = read_jwk_from_file (oidc_jwk_path);
2738
2739 // Check if secret JWK exists
2740 if (! oidc_jwk)
2741 {
2742 // Generate and save a new key
2744 oidc_directory = get_oidc_dir_path (cls);
2745
2746 // Create new oidc directory
2747 if (GNUNET_OK != GNUNET_DISK_directory_create (oidc_directory))
2748 {
2750 ("Failed to create directory `%s' for storing oidc data\n"),
2751 oidc_directory);
2752 }
2753 else
2754 {
2755 write_jwk_to_file (oidc_jwk_path, oidc_jwk);
2756 }
2757 }
2758
2759 // Convert secret JWK to public JWK
2760 jose_jwk_pub (NULL, oidc_jwk);
2761
2762 // Encode JWK as string and return to API endpoint
2763 oidc_jwk_pub_str = json_dumps (oidc_jwk, JSON_INDENT (1));
2764 resp = GNUNET_REST_create_response (oidc_jwk_pub_str);
2765 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2766 json_decref (oidc_jwk);
2767 GNUNET_free (oidc_jwk_pub_str);
2768 GNUNET_free (oidc_jwk_pub_str);
2770}
2771
2772
2805static void
2806list_ego (void *cls,
2807 struct GNUNET_IDENTITY_Ego *ego,
2808 void **ctx,
2809 const char *identifier)
2810{
2811 struct EgoEntry *ego_entry;
2813
2814 if (NULL == ego)
2815 {
2817 return;
2818 }
2820
2821 {
2822 ego_entry = GNUNET_new (struct EgoEntry);
2825 ego_entry->ego = ego;
2826 ego_entry->identifier = GNUNET_strdup (identifier);
2828 ego_tail,
2829 ego_entry);
2830 return;
2831 }
2832 /* Ego renamed or added */
2833 if (identifier != NULL)
2834 {
2835 for (ego_entry = ego_head; NULL != ego_entry;
2836 ego_entry = ego_entry->next)
2837 {
2838 if (ego_entry->ego == ego)
2839 {
2840 /* Rename */
2841 GNUNET_free (ego_entry->identifier);
2842 ego_entry->identifier = GNUNET_strdup (identifier);
2843 break;
2844 }
2845 }
2846 if (NULL == ego_entry)
2847 {
2848 /* Add */
2849 ego_entry = GNUNET_new (struct EgoEntry);
2852 ego_entry->ego = ego;
2853 ego_entry->identifier = GNUNET_strdup (identifier);
2855 ego_tail,
2856 ego_entry);
2857 }
2858 }
2859 else
2860 {
2861 /* Delete */
2862 for (ego_entry = ego_head; NULL != ego_entry;
2863 ego_entry = ego_entry->next)
2864 {
2865 if (ego_entry->ego == ego)
2866 break;
2867 }
2868 if (NULL == ego_entry)
2869 return; /* Not found */
2870
2872 ego_tail,
2873 ego_entry);
2874 GNUNET_free (ego_entry->identifier);
2875 GNUNET_free (ego_entry->keystring);
2876 GNUNET_free (ego_entry);
2877 return;
2878 }
2879}
2880
2881
2882static void
2884 const char *url,
2885 void *cls)
2886{
2887 json_t *oidc_config;
2888 json_t *auth_methods;
2889 json_t *sig_algs;
2890 json_t *scopes;
2891 json_t *response_types;
2892 json_t *sub_types;
2893 json_t *claim_types;
2894 char *oidc_config_str;
2895 struct MHD_Response *resp;
2896 struct RequestHandle *handle = cls;
2897
2898 oidc_config = json_object ();
2899 // FIXME get from config?
2900 json_object_set_new (oidc_config,
2901 "issuer", json_string ("http://localhost:7776"));
2902 json_object_set_new (oidc_config,
2903 "authorization_endpoint",
2904 json_string ("https://api.reclaim/openid/authorize"));
2905 json_object_set_new (oidc_config,
2906 "token_endpoint",
2907 json_string ("http://localhost:7776/openid/token"));
2908 auth_methods = json_array ();
2909 json_array_append_new (auth_methods,
2910 json_string ("client_secret_basic"));
2911 json_array_append_new (auth_methods,
2912 json_string ("client_secret_post"));
2913 json_object_set_new (oidc_config,
2914 "token_endpoint_auth_methods_supported",
2915 auth_methods);
2916 sig_algs = json_array ();
2917 json_array_append_new (sig_algs,
2918 json_string ("HS512"));
2919 json_array_append_new (sig_algs,
2920 json_string ("RS256"));
2921 json_object_set_new (oidc_config,
2922 "id_token_signing_alg_values_supported",
2923 sig_algs);
2924 json_object_set_new (oidc_config,
2925 "jwks_uri",
2926 json_string ("http://localhost:7776/jwks.json"));
2927 json_object_set_new (oidc_config,
2928 "userinfo_endpoint",
2929 json_string ("http://localhost:7776/openid/userinfo"));
2930 scopes = json_array ();
2931 json_array_append_new (scopes,
2932 json_string ("openid"));
2933 json_array_append_new (scopes,
2934 json_string ("profile"));
2935 json_array_append_new (scopes,
2936 json_string ("email"));
2937 json_array_append_new (scopes,
2938 json_string ("address"));
2939 json_array_append_new (scopes,
2940 json_string ("phone"));
2941 json_object_set_new (oidc_config,
2942 "scopes_supported",
2943 scopes);
2944 response_types = json_array ();
2945 json_array_append_new (response_types,
2946 json_string ("code"));
2947 json_object_set_new (oidc_config,
2948 "response_types_supported",
2949 response_types);
2950 sub_types = json_array ();
2951 json_array_append_new (sub_types,
2952 json_string ("public")); /* no pairwise support */
2953 json_object_set_new (oidc_config,
2954 "subject_types_supported",
2955 sub_types);
2956 claim_types = json_array ();
2957 json_array_append_new (claim_types,
2958 json_string ("normal"));
2959 json_array_append_new (claim_types,
2960 json_string ("aggregated"));
2961 json_object_set_new (oidc_config,
2962 "claim_types_supported",
2963 claim_types);
2964 json_object_set_new (oidc_config,
2965 "claims_parameter_supported",
2966 json_boolean (1));
2967 oidc_config_str = json_dumps (oidc_config, JSON_INDENT (1));
2968 resp = GNUNET_REST_create_response (oidc_config_str);
2969 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2970 json_decref (oidc_config);
2971 GNUNET_free (oidc_config_str);
2973}
2974
2975
2983static void
2985 const char *url,
2986 void *cls)
2987{
2988 struct MHD_Response *resp;
2989 struct RequestHandle *handle = cls;
2990
2991 // For now, independent of path return all options
2992 resp = GNUNET_REST_create_response (NULL);
2993 GNUNET_assert (MHD_NO !=
2994 MHD_add_response_header (resp,
2995 "Access-Control-Allow-Methods",
2996 allow_methods));
2997 GNUNET_assert (MHD_NO !=
2998 MHD_add_response_header (resp,
2999 "Access-Control-Allow-Origin",
3000 "*"));
3001 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
3003 return;
3004}
3005
3006
3011 void *proc_cls)
3012{
3013 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
3015 static const struct GNUNET_REST_RequestHandler handlers[] =
3016 { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint },
3017 { MHD_HTTP_METHOD_POST,
3019 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont },
3020 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
3021 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
3022 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
3023 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_JWKS, &jwks_endpoint },
3024 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_OIDC_CONFIG,
3026 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC_CONFIG,
3028 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont },
3030
3031 handle->oidc = GNUNET_new (struct OIDC_Variables);
3032 if (NULL == OIDC_cookie_jar_map)
3034 GNUNET_NO);
3035 if (NULL == oidc_code_cache)
3037 GNUNET_NO);
3038
3039 handle->response_code = 0;
3041 handle->proc_cls = proc_cls;
3042 handle->proc = proc;
3043 handle->rest_handle = rest_handle;
3044 handle->url = GNUNET_strdup (rest_handle->url);
3045 handle->timeout_task =
3049 handle);
3050 if (handle->url[strlen (handle->url) - 1] == '/')
3051 handle->url[strlen (handle->url) - 1] = '\0';
3052 if (GNUNET_NO ==
3053 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
3054 return GNUNET_NO;
3055
3056 return GNUNET_YES;
3057}
3058
3059
3066void *
3068{
3069 static struct Plugin plugin;
3070 struct GNUNET_REST_Plugin *api;
3071
3072 oid_cfg = c;
3073 if (NULL != plugin.cfg)
3074 return NULL; /* can only initialize once! */
3075 memset (&plugin, 0, sizeof(struct Plugin));
3076 plugin.cfg = oid_cfg;
3077 api = GNUNET_new (struct GNUNET_REST_Plugin);
3078 api->cls = &plugin;
3084 "reclaim-rest-plugin",
3085 "OIDC_USERINFO_CONSUME_TIMEOUT",
3087 {
3089 }
3090
3091
3094 "%s, %s, %s, %s, %s",
3095 MHD_HTTP_METHOD_GET,
3096 MHD_HTTP_METHOD_POST,
3097 MHD_HTTP_METHOD_PUT,
3098 MHD_HTTP_METHOD_DELETE,
3099 MHD_HTTP_METHOD_OPTIONS);
3100
3102 _ ("OpenID Connect REST API initialized\n"));
3103 return api;
3104}
3105
3106
3107static int
3108cleanup_hashmap (void *cls, const struct GNUNET_HashCode *key, void *value)
3109{
3111 return GNUNET_YES;
3112}
3113
3114
3121void *
3123{
3124 struct GNUNET_REST_Plugin *api = cls;
3125 struct Plugin *plugin = api->cls;
3126 struct EgoEntry *ego_entry;
3127
3128 plugin->cfg = NULL;
3129 while (NULL != requests_head)
3131 if (NULL != OIDC_cookie_jar_map)
3132 {
3135 NULL);
3137 }
3138 if (NULL != oidc_code_cache)
3139 {
3142 NULL);
3144 }
3145
3147 if (NULL != gns_handle)
3149 if (NULL != identity_handle)
3151 if (NULL != idp)
3153 while (NULL != (ego_entry = ego_head))
3154 {
3156 ego_tail,
3157 ego_entry);
3158 GNUNET_free (ego_entry->identifier);
3159 GNUNET_free (ego_entry->keystring);
3160 GNUNET_free (ego_entry);
3161 }
3162 GNUNET_free (api);
3164 "OpenID Connect REST plugin is finished\n");
3165 return NULL;
3166}
3167
3168
3169/* 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
struct TestcasePlugin * plugin
The process handle to the testbed service.
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.
API that can be used to store naming information on a GNUnet node;.
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
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:551
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:602
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:571
@ 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:1145
struct GNUNET_RECLAIM_Operation * GNUNET_RECLAIM_ticket_issue(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_CRYPTO_PrivateKey *iss, const struct GNUNET_CRYPTO_PublicKey *rp, const struct GNUNET_RECLAIM_AttributeList *attrs, GNUNET_RECLAIM_IssueTicketCallback cb, void *cb_cls)
Issues a ticket to a relying party.
Definition: reclaim_api.c:1491
void GNUNET_RECLAIM_cancel(struct GNUNET_RECLAIM_Operation *op)
Cancel an identity provider operation.
Definition: reclaim_api.c:1130
void GNUNET_RECLAIM_get_attributes_stop(struct GNUNET_RECLAIM_AttributeIterator *it)
Stops iteration and releases the handle for further calls.
Definition: reclaim_api.c:1393
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:1456
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:1334
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:1379
struct GNUNET_RECLAIM_Operation * GNUNET_RECLAIM_ticket_consume(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_CRYPTO_PrivateKey *identity, const struct GNUNET_RECLAIM_Ticket *ticket, GNUNET_RECLAIM_AttributeTicketResult cb, void *cb_cls)
Consumes an issued ticket.
Definition: reclaim_api.c:1551
struct GNUNET_RECLAIM_Handle * GNUNET_RECLAIM_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the re:claimID service.
Definition: reclaim_api.c:1113
void GNUNET_RECLAIM_get_credentials_stop(struct GNUNET_RECLAIM_CredentialIterator *ait)
Stops iteration and releases the handle for further calls.
Definition: reclaim_api.c:1471
void GNUNET_RECLAIM_ticket_iteration_stop(struct GNUNET_RECLAIM_TicketIterator *it)
Stops iteration and releases the handle for further calls.
Definition: reclaim_api.c:1663
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:1411
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:1877
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_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:346
char * OIDC_generate_id_token_rsa(const struct GNUNET_CRYPTO_PublicKey *aud_key, 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:427
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:581
char * OIDC_generate_id_token_hmac(const struct GNUNET_CRYPTO_PublicKey *aud_key, 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:489
char * OIDC_access_token_new(const struct GNUNET_RECLAIM_Ticket *ticket)
Generate a new access token.
Definition: oidc_helper.c:916
enum GNUNET_GenericReturnValue OIDC_check_scopes_for_claim_request(const char *scopes, const char *attr)
Checks if a claim is implicitly requested through standard scope(s) or explicitly through non-standar...
Definition: oidc_helper.c:958
void OIDC_build_token_response(const char *access_token, const char *id_token, const struct GNUNET_TIME_Relative *expiration_time, char **token_response)
Build a token response for a token request TODO: Maybe we should add the scope here?
Definition: oidc_helper.c:888
int OIDC_parse_authz_code(const struct GNUNET_CRYPTO_PublicKey *audience, const char *code, const char *code_verifier, struct GNUNET_RECLAIM_Ticket *ticket, struct GNUNET_RECLAIM_AttributeList **attrs, struct GNUNET_RECLAIM_PresentationList **presentations, char **nonce_str, enum OIDC_VerificationOptions opts)
Parse reclaim ticket and nonce from authorization code.
Definition: oidc_helper.c:767
int OIDC_access_token_parse(const char *token, struct GNUNET_RECLAIM_Ticket **ticket)
Parse an access token.
Definition: oidc_helper.c:931
#define JWT_ALG_VALUE_RSA
Definition: oidc_helper.h:35
@ OIDC_VERIFICATION_NO_CODE_VERIFIER
Do not check code verifier even if expected.
Definition: oidc_helper.h:49
@ OIDC_VERIFICATION_DEFAULT
Strict verification.
Definition: oidc_helper.h:44
#define JWT_ALG_VALUE_HMAC
Definition: oidc_helper.h:34
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:54
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:79
#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:49
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:69
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:84
#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:94
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:64
#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:74
void * REST_openid_done(void *cls)
Exit point from the plugin.
#define GNUNET_REST_API_NS_AUTHORIZE
Authorize endpoint.
Definition: openid_plugin.c:59
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:99
json_t * oidc_jwk
The RSA key used by the oidc enpoint.
#define ID_REST_STATE_POST_INIT
Done collecting egos.
Definition: openid_plugin.c:89
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.
struct GNUNET_CRYPTO_PublicKey audience
The ticket audience (= relying party)
struct GNUNET_CRYPTO_PublicKey identity
The ticket issuer (= the user)
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.