GNUnet  0.11.x
plugin_rest_openid_connect.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  */
27 #include "platform.h"
28 #include <inttypes.h>
29 #include <jansson.h>
30 
31 #include "gnunet_buffer_lib.h"
32 #include "gnunet_strings_lib.h"
33 #include "gnunet_gns_service.h"
34 #include "gnunet_gnsrecord_lib.h"
37 #include "gnunet_reclaim_lib.h"
38 #include "gnunet_reclaim_service.h"
39 #include "gnunet_rest_lib.h"
40 #include "gnunet_rest_plugin.h"
41 #include "gnunet_signatures.h"
42 #include "microhttpd.h"
43 #include "oidc_helper.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_NS_USERINFO "/openid/userinfo"
69 
73 #define GNUNET_REST_API_NS_LOGIN "/openid/login"
74 
78 #define ID_REST_STATE_INIT 0
79 
83 #define ID_REST_STATE_POST_INIT 1
84 
88 #define OIDC_GRANT_TYPE_KEY "grant_type"
89 
93 #define OIDC_GRANT_TYPE_VALUE "authorization_code"
94 
98 #define OIDC_CODE_KEY "code"
99 
103 #define OIDC_RESPONSE_TYPE_KEY "response_type"
104 
108 #define OIDC_CLIENT_ID_KEY "client_id"
109 
113 #define OIDC_SCOPE_KEY "scope"
114 
118 #define OIDC_REDIRECT_URI_KEY "redirect_uri"
119 
123 #define OIDC_STATE_KEY "state"
124 
128 #define OIDC_NONCE_KEY "nonce"
129 
133 #define OIDC_CLAIMS_KEY "claims"
134 
138 #define OIDC_CODE_CHALLENGE_KEY "code_challenge"
139 
143 #define OIDC_CODE_VERIFIER_KEY "code_verifier"
144 
148 #define OIDC_COOKIE_EXPIRATION 3
149 
153 #define OIDC_COOKIE_HEADER_KEY "cookie"
154 
158 #define OIDC_AUTHORIZATION_HEADER_KEY "authorization"
159 
163 #define OIDC_COOKIE_HEADER_INFORMATION_KEY "Identity="
164 
168 #define OIDC_COOKIE_HEADER_ACCESS_DENIED "Identity=Denied"
169 
173 #define OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE "code"
174 
178 #define OIDC_EXPECTED_AUTHORIZATION_SCOPE "openid"
179 
183 #define OIDC_ERROR_KEY_INVALID_CLIENT "invalid_client"
184 
188 #define OIDC_ERROR_KEY_INVALID_SCOPE "invalid_scope"
189 
193 #define OIDC_ERROR_KEY_INVALID_REQUEST "invalid_request"
194 
198 #define OIDC_ERROR_KEY_INVALID_TOKEN "invalid_token"
199 
203 #define OIDC_ERROR_KEY_INVALID_COOKIE "invalid_cookie"
204 
208 #define OIDC_ERROR_KEY_SERVER_ERROR "server_error"
209 
213 #define OIDC_ERROR_KEY_UNSUPPORTED_GRANT_TYPE "unsupported_grant_type"
214 
218 #define OIDC_ERROR_KEY_UNSUPPORTED_RESPONSE_TYPE "unsupported_response_type"
219 
223 #define OIDC_ERROR_KEY_UNAUTHORIZED_CLIENT "unauthorized_client"
224 
228 #define OIDC_ERROR_KEY_ACCESS_DENIED "access_denied"
229 
233 #define CONSUME_TIMEOUT GNUNET_TIME_relative_multiply ( \
234  GNUNET_TIME_UNIT_SECONDS,2)
235 
239 static char *OIDC_ignored_parameter_array[] = { "display",
240  "prompt",
241  "ui_locales",
242  "response_mode",
243  "id_token_hint",
244  "login_hint",
245  "acr_values" };
246 
251 
256 
261 
265 static char *allow_methods;
266 
270 static struct EgoEntry *ego_head;
271 
275 static struct EgoEntry *ego_tail;
276 
280 static int state;
281 
286 
291 
295 static struct GNUNET_RECLAIM_Handle *idp;
296 
300 struct Plugin
301 {
303 };
304 
309 {
314 
318  char *client_id;
319 
324 
328  char *scope;
329 
333  char *state;
334 
338  char *nonce;
339 
343  char *claims;
344 
349 
354 
359 
364 
369 
370 };
371 
375 struct EgoEntry
376 {
380  struct EgoEntry *next;
381 
385  struct EgoEntry *prev;
386 
390  char *identifier;
391 
395  char *keystring;
396 
400  struct GNUNET_IDENTITY_Ego *ego;
401 };
402 
403 
404 struct RequestHandle
405 {
409  struct RequestHandle *next;
410 
414  struct RequestHandle *prev;
415 
420 
425 
430 
435 
440 
445 
450 
455 
460 
465 
466 
471 
476 
481 
486 
487 
492 
497 
502 
507 
512 
516  void *proc_cls;
517 
521  char *url;
522 
527 
531  char *tld;
532 
537 
542 
546  char *emsg;
547 
551  char *edesc;
552 
556  int response_code;
557 
562 };
563 
568 
573 
574 
579 static void
581 {
582 
583  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
584  if (NULL != handle->timeout_task)
585  GNUNET_SCHEDULER_cancel (handle->timeout_task);
586  if (NULL != handle->attr_it)
588  if (NULL != handle->cred_it)
590  if (NULL != handle->ticket_it)
592  if (NULL != handle->idp_op)
593  GNUNET_RECLAIM_cancel (handle->idp_op);
594  if (NULL != handle->consume_timeout_op)
595  GNUNET_SCHEDULER_cancel (handle->consume_timeout_op);
596  GNUNET_free (handle->url);
597  GNUNET_free (handle->tld);
598  GNUNET_free (handle->redirect_prefix);
599  GNUNET_free (handle->redirect_suffix);
600  GNUNET_free (handle->emsg);
601  GNUNET_free (handle->edesc);
602  if (NULL != handle->gns_op)
604  if (NULL != handle->oidc)
605  {
606  GNUNET_free (handle->oidc->client_id);
607  GNUNET_free (handle->oidc->login_identity);
608  GNUNET_free (handle->oidc->nonce);
609  GNUNET_free (handle->oidc->redirect_uri);
610  GNUNET_free (handle->oidc->response_type);
611  GNUNET_free (handle->oidc->scope);
612  GNUNET_free (handle->oidc->state);
613  if (NULL != handle->oidc->claims)
614  GNUNET_free (handle->oidc->claims);
615  if (NULL != handle->oidc->code_challenge)
616  GNUNET_free (handle->oidc->code_challenge);
617  GNUNET_free (handle->oidc);
618  }
619  if (NULL!=handle->attr_idtoken_list)
620  GNUNET_RECLAIM_attribute_list_destroy (handle->attr_idtoken_list);
621  if (NULL!=handle->attr_userinfo_list)
622  GNUNET_RECLAIM_attribute_list_destroy (handle->attr_userinfo_list);
623  if (NULL!=handle->credentials)
625  if (NULL!=handle->presentations)
629  handle);
630  if (NULL != handle->access_token)
631  GNUNET_free (handle->access_token);
633 }
634 
635 
641 static void
642 do_error (void *cls)
643 {
644  struct RequestHandle *handle = cls;
645  struct MHD_Response *resp;
646  char *json_error;
647 
648  GNUNET_asprintf (&json_error,
649  "{ \"error\" : \"%s\", \"error_description\" : \"%s\"%s%s%s}",
650  handle->emsg,
651  (NULL != handle->edesc) ? handle->edesc : "",
652  (NULL != handle->oidc->state) ? ", \"state\":\"" : "",
653  (NULL != handle->oidc->state) ? handle->oidc->state : "",
654  (NULL != handle->oidc->state) ? "\"" : "");
655  if (0 == handle->response_code)
656  handle->response_code = MHD_HTTP_BAD_REQUEST;
657  resp = GNUNET_REST_create_response (json_error);
658  if (MHD_HTTP_UNAUTHORIZED == handle->response_code)
659  GNUNET_assert (MHD_NO !=
660  MHD_add_response_header (resp,
661  MHD_HTTP_HEADER_WWW_AUTHENTICATE,
662  "Basic"));
663  MHD_add_response_header (resp,
664  MHD_HTTP_HEADER_CONTENT_TYPE,
665  "application/json");
666  handle->proc (handle->proc_cls, resp, handle->response_code);
668  GNUNET_free (json_error);
669 }
670 
671 
678 static void
679 do_userinfo_error (void *cls)
680 {
681  struct RequestHandle *handle = cls;
682  struct MHD_Response *resp;
683  char *error;
684 
686  "Error: %s\n", handle->edesc);
687  GNUNET_asprintf (&error,
688  "error=\"%s\", error_description=\"%s\"",
689  handle->emsg,
690  (NULL != handle->edesc) ? handle->edesc : "");
691  resp = GNUNET_REST_create_response ("");
692  GNUNET_assert (MHD_NO !=
693  MHD_add_response_header (resp,
694  MHD_HTTP_HEADER_WWW_AUTHENTICATE,
695  "Bearer"));
696  handle->proc (handle->proc_cls, resp, handle->response_code);
698  GNUNET_free (error);
699 }
700 
701 
707 static void
708 do_redirect_error (void *cls)
709 {
710  struct RequestHandle *handle = cls;
711  struct MHD_Response *resp;
712  char *redirect;
713 
714  GNUNET_asprintf (&redirect,
715  "%s?error=%s&error_description=%s%s%s",
716  handle->oidc->redirect_uri,
717  handle->emsg,
718  handle->edesc,
719  (NULL != handle->oidc->state) ? "&state=" : "",
720  (NULL != handle->oidc->state) ? handle->oidc->state : "");
721  resp = GNUNET_REST_create_response ("");
722  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
723  "Location", redirect));
724  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
726  GNUNET_free (redirect);
727 }
728 
729 
735 static void
736 do_timeout (void *cls)
737 {
738  struct RequestHandle *handle = cls;
739 
740  handle->timeout_task = NULL;
741  do_error (handle);
742 }
743 
744 
752 static void
754  const char *url,
755  void *cls)
756 {
757  struct MHD_Response *resp;
758  struct RequestHandle *handle = cls;
759 
760  // For now, independent of path return all options
761  resp = GNUNET_REST_create_response (NULL);
762  MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
763  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
765  return;
766 }
767 
768 
772 static void
774 {
775  struct GNUNET_HashCode cache_key;
776  char *cookies;
777  struct GNUNET_TIME_Absolute current_time, *relog_time;
778  char delimiter[] = "; ";
779  char *tmp_cookies;
780  char *token;
781  char *value;
782 
783  // gets identity of login try with cookie
785  strlen (OIDC_COOKIE_HEADER_KEY),
786  &cache_key);
788  ->header_param_map,
789  &cache_key))
790  {
791  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No cookie found\n");
792  return;
793  }
794  // splits cookies and find 'Identity' cookie
795  tmp_cookies =
796  GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
797  &cache_key);
798  cookies = GNUNET_strdup (tmp_cookies);
799  token = strtok (cookies, delimiter);
800  handle->oidc->user_cancelled = GNUNET_NO;
801  handle->oidc->login_identity = NULL;
802  if (NULL == token)
803  {
805  "Unable to parse cookie: %s\n",
806  cookies);
807  GNUNET_free (cookies);
808  return;
809  }
810 
811  while (NULL != token)
812  {
813  if (0 == strcmp (token, OIDC_COOKIE_HEADER_ACCESS_DENIED))
814  {
815  handle->oidc->user_cancelled = GNUNET_YES;
816  GNUNET_free (cookies);
817  return;
818  }
819  if (NULL != strstr (token, OIDC_COOKIE_HEADER_INFORMATION_KEY))
820  break;
821  token = strtok (NULL, delimiter);
822  }
823  if (NULL == token)
824  {
826  "No cookie value to process: %s\n",
827  cookies);
828  GNUNET_free (cookies);
829  return;
830  }
831  GNUNET_CRYPTO_hash (token, strlen (token), &cache_key);
832  if (GNUNET_NO ==
834  {
835  GNUNET_log (
837  "Found cookie `%s', but no corresponding expiration entry present...\n",
838  token);
839  GNUNET_free (cookies);
840  return;
841  }
842  relog_time =
844  current_time = GNUNET_TIME_absolute_get ();
845  // 30 min after old login -> redirect to login
846  if (current_time.abs_value_us > relog_time->abs_value_us)
847  {
849  "Found cookie `%s', but it is expired.\n",
850  token);
851  GNUNET_free (cookies);
852  return;
853  }
854  value = strtok (token, OIDC_COOKIE_HEADER_INFORMATION_KEY);
855  GNUNET_assert (NULL != value);
856  handle->oidc->login_identity = GNUNET_strdup (value);
857  GNUNET_free (cookies);
858 }
859 
860 
864 static void
865 login_redirect (void *cls)
866 {
867  char *login_base_url;
868  char *new_redirect;
869  char *tmp;
870  struct MHD_Response *resp;
871  struct GNUNET_Buffer buf = { 0 };
872  struct RequestHandle *handle = cls;
873 
875  "reclaim-rest-plugin",
876  "address",
877  &login_base_url))
878  {
879  GNUNET_buffer_write_str (&buf, login_base_url);
881  "?%s=%s",
883  handle->oidc->response_type);
885  "&%s=%s",
887  handle->oidc->client_id);
888  GNUNET_STRINGS_urlencode (handle->oidc->redirect_uri,
889  strlen (handle->oidc->redirect_uri),
890  &tmp);
892  "&%s=%s",
894  tmp);
895  GNUNET_free (tmp);
896  GNUNET_STRINGS_urlencode (handle->oidc->scope,
897  strlen (handle->oidc->scope),
898  &tmp);
900  "&%s=%s",
902  tmp);
903  GNUNET_free (tmp);
904  if (NULL != handle->oidc->state)
905  {
906  GNUNET_STRINGS_urlencode (handle->oidc->state,
907  strlen (handle->oidc->state),
908  &tmp);
910  "&%s=%s",
912  handle->oidc->state);
913  GNUNET_free (tmp);
914  }
915  if (NULL != handle->oidc->code_challenge)
916  {
918  "&%s=%s",
920  handle->oidc->code_challenge);
921  }
922  if (NULL != handle->oidc->nonce)
923  {
925  "&%s=%s",
927  handle->oidc->nonce);
928  }
929  if (NULL != handle->oidc->claims)
930  {
931  GNUNET_STRINGS_urlencode (handle->oidc->claims,
932  strlen (handle->oidc->claims),
933  &tmp);
935  "&%s=%s",
937  tmp);
938  GNUNET_free (tmp);
939  }
940  new_redirect = GNUNET_buffer_reap_str (&buf);
941  resp = GNUNET_REST_create_response ("");
942  MHD_add_response_header (resp, "Location", new_redirect);
943  GNUNET_free (login_base_url);
944  }
945  else
946  {
948  handle->edesc = GNUNET_strdup ("gnunet configuration failed");
949  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
951  return;
952  }
953  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
954  GNUNET_free (new_redirect);
956 }
957 
958 
962 static void
964 {
965  struct RequestHandle *handle = cls;
966 
968  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
970 }
971 
972 
977 static void
979  const struct GNUNET_RECLAIM_Ticket *ticket,
980  const struct
981  GNUNET_RECLAIM_PresentationList *presentation)
982 {
983  struct RequestHandle *handle = cls;
984  struct MHD_Response *resp;
985  char *ticket_str;
986  char *redirect_uri;
987  char *code_string;
988 
989  handle->idp_op = NULL;
990  if (NULL == ticket)
991  {
993  handle->edesc = GNUNET_strdup ("Server cannot generate ticket.");
995  return;
996  }
997  handle->ticket = *ticket;
998  ticket_str =
1000  sizeof(struct GNUNET_RECLAIM_Ticket));
1001  code_string = OIDC_build_authz_code (&handle->priv_key,
1002  &handle->ticket,
1003  handle->attr_idtoken_list,
1004  presentation,
1005  handle->oidc->nonce,
1006  handle->oidc->code_challenge);
1007  if ((NULL != handle->redirect_prefix) && (NULL != handle->redirect_suffix) &&
1008  (NULL != handle->tld))
1009  {
1010  GNUNET_asprintf (&redirect_uri,
1011  "%s.%s/%s%s%s=%s&state=%s",
1012  handle->redirect_prefix,
1013  handle->tld,
1014  handle->redirect_suffix,
1015  (NULL == strchr (handle->redirect_suffix, '?') ? "?" :
1016  "&"),
1017  handle->oidc->response_type,
1018  code_string,
1019  handle->oidc->state);
1020  }
1021  else
1022  {
1023  GNUNET_asprintf (&redirect_uri,
1024  "%s%s%s=%s&state=%s",
1025  handle->oidc->redirect_uri,
1026  (NULL == strchr (handle->oidc->redirect_uri, '?') ? "?" :
1027  "&"),
1028  handle->oidc->response_type,
1029  code_string,
1030  handle->oidc->state);
1031  }
1032  resp = GNUNET_REST_create_response ("");
1033  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1034  "Location", redirect_uri));
1035  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1037  GNUNET_free (redirect_uri);
1038  GNUNET_free (ticket_str);
1039  GNUNET_free (code_string);
1040 }
1041 
1042 
1043 static struct GNUNET_RECLAIM_AttributeList*
1045  struct GNUNET_RECLAIM_AttributeList *list_b)
1046 {
1047  struct GNUNET_RECLAIM_AttributeList *merged_list;
1048  struct GNUNET_RECLAIM_AttributeListEntry *le_a;
1049  struct GNUNET_RECLAIM_AttributeListEntry *le_b;
1050  struct GNUNET_RECLAIM_AttributeListEntry *le_m;
1051 
1052  merged_list = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
1053  for (le_a = list_a->list_head; NULL != le_a; le_a = le_a->next)
1054  {
1057  &le_a->attribute->
1058  credential,
1059  le_a->attribute->type,
1060  le_a->attribute->data,
1061  le_a->attribute->data_size);
1062  le_m->attribute->id = le_a->attribute->id;
1063  le_m->attribute->flag = le_a->attribute->flag;
1064  le_m->attribute->credential = le_a->attribute->credential;
1065  GNUNET_CONTAINER_DLL_insert (merged_list->list_head,
1066  merged_list->list_tail,
1067  le_m);
1068  }
1069  le_m = NULL;
1070  for (le_b = list_b->list_head; NULL != le_b; le_b = le_b->next)
1071  {
1072  for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1073  {
1075  &le_b->attribute->id))
1076  break;
1077  }
1078  if (NULL != le_m)
1079  continue;
1082  &le_b->attribute->
1083  credential,
1084  le_b->attribute->type,
1085  le_b->attribute->data,
1086  le_b->attribute->data_size);
1087  le_m->attribute->id = le_b->attribute->id;
1088  le_m->attribute->flag = le_b->attribute->flag;
1089  le_m->attribute->credential = le_b->attribute->credential;
1090  GNUNET_CONTAINER_DLL_insert (merged_list->list_head,
1091  merged_list->list_tail,
1092  le_m);
1093  }
1094  return merged_list;
1095 }
1096 
1097 
1098 static void
1100 {
1101  struct RequestHandle *handle = cls;
1102  struct GNUNET_RECLAIM_AttributeList *merged_list;
1103  struct GNUNET_RECLAIM_AttributeListEntry *le_m;
1104 
1105  handle->cred_it = NULL;
1106  merged_list = attribute_list_merge (handle->attr_idtoken_list,
1107  handle->attr_userinfo_list);
1108  for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1110  "List Attribute in ticket to issue: %s\n",
1111  le_m->attribute->name);
1113  &handle->priv_key,
1114  &handle->oidc->client_pkey,
1115  merged_list,
1117  handle);
1119 }
1120 
1121 
1125 static void
1127  const struct GNUNET_IDENTITY_PublicKey *identity,
1128  const struct GNUNET_RECLAIM_Credential *cred)
1129 {
1130  struct RequestHandle *handle = cls;
1133 
1134  for (ale = handle->credentials->list_head; NULL != ale; ale = ale->next)
1135  {
1137  &cred->id))
1138  continue;
1141  return;
1142  }
1143 
1144  for (le = handle->attr_idtoken_list->list_head; NULL != le; le = le->next)
1145  {
1147  &cred->id))
1148  continue;
1152  cred->type,
1153  cred->data,
1154  cred->data_size);
1155  GNUNET_CONTAINER_DLL_insert (handle->credentials->list_head,
1156  handle->credentials->list_tail,
1157  ale);
1158  }
1160 }
1161 
1162 
1163 static void
1165 {
1166  struct RequestHandle *handle = cls;
1167 
1168  handle->attr_it = NULL;
1169  handle->ticket_it = NULL;
1170  if (NULL == handle->attr_idtoken_list->list_head)
1171  {
1173  handle->edesc = GNUNET_strdup ("The requested scope is not available.");
1175  return;
1176  }
1177  handle->credentials = GNUNET_new (struct GNUNET_RECLAIM_CredentialList);
1178  handle->cred_it =
1180  &handle->priv_key,
1182  handle,
1184  handle,
1186  handle);
1187 
1188 }
1189 
1190 
1191 static int
1193  const char *attr_name,
1194  const char *claims_parameter)
1195 {
1196  int ret = GNUNET_NO;
1197  json_t *root;
1198  json_error_t error;
1199  json_t *claims_j;
1200  const char *key;
1201  json_t *value;
1202 
1205  attr_name))
1206  return GNUNET_YES;
1207 
1209  if (NULL != handle->oidc->claims)
1210  {
1211  root = json_loads (handle->oidc->claims, JSON_DECODE_ANY, &error);
1212  claims_j = json_object_get (root, claims_parameter);
1213  /* obj is a JSON object */
1214  if (NULL != claims_j)
1215  {
1216  json_object_foreach (claims_j, key, value) {
1217  if (0 != strcmp (attr_name, key))
1218  continue;
1219  ret = GNUNET_YES;
1220  break;
1221  }
1222  }
1223  json_decref (root);
1224  }
1225  return ret;
1226 }
1227 
1228 
1229 static int
1231  const char *attr_name)
1232 {
1233  return attr_in_claims_request (handle, attr_name, "id_token");
1234 }
1235 
1236 
1237 static int
1239  const char *attr_name)
1240 {
1241  return attr_in_claims_request (handle, attr_name, "userinfo");
1242 }
1243 
1244 
1248 static void
1250  const struct GNUNET_IDENTITY_PublicKey *identity,
1251  const struct GNUNET_RECLAIM_Attribute *attr)
1252 {
1253  struct RequestHandle *handle = cls;
1256  {
1259  &attr->credential,
1260  attr->type,
1261  attr->data,
1262  attr->data_size);
1263  le->attribute->id = attr->id;
1264  le->attribute->flag = attr->flag;
1265  le->attribute->credential = attr->credential;
1266  GNUNET_CONTAINER_DLL_insert (handle->attr_idtoken_list->list_head,
1267  handle->attr_idtoken_list->list_tail,
1268  le);
1269  }
1271  {
1274  &attr->credential,
1275  attr->type,
1276  attr->data,
1277  attr->data_size);
1278  le->attribute->id = attr->id;
1279  le->attribute->flag = attr->flag;
1280  le->attribute->credential = attr->credential;
1281  GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
1282  handle->attr_userinfo_list->list_tail,
1283  le);
1284  }
1285 
1287 }
1288 
1289 
1293 static void
1294 code_redirect (void *cls)
1295 {
1296  struct RequestHandle *handle = cls;
1297  struct GNUNET_TIME_Absolute current_time;
1298  struct GNUNET_TIME_Absolute *relog_time;
1300  struct GNUNET_IDENTITY_PublicKey ego_pkey;
1301  struct GNUNET_HashCode cache_key;
1302  char *identity_cookie;
1303 
1304  GNUNET_asprintf (&identity_cookie,
1305  "Identity=%s",
1306  handle->oidc->login_identity);
1307  GNUNET_CRYPTO_hash (identity_cookie, strlen (identity_cookie), &cache_key);
1308  GNUNET_free (identity_cookie);
1309  // No login time for identity -> redirect to login
1310  if (GNUNET_YES ==
1312  {
1313  relog_time =
1315  current_time = GNUNET_TIME_absolute_get ();
1316  // 30 min after old login -> redirect to login
1317  if (current_time.abs_value_us <= relog_time->abs_value_us)
1318  {
1319  if (GNUNET_OK !=
1321  ->login_identity,
1322  &pubkey))
1323  {
1325  handle->edesc =
1326  GNUNET_strdup ("The cookie of a login identity is not valid");
1328  return;
1329  }
1330  // iterate over egos and compare their public key
1331  for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
1332  handle->ego_entry = handle->ego_entry->next)
1333  {
1334  GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey);
1335  if (0 == GNUNET_memcmp (&ego_pkey, &pubkey))
1336  {
1337  handle->priv_key =
1338  *GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego);
1339  handle->attr_idtoken_list =
1341  handle->attr_userinfo_list =
1343  handle->attr_it =
1345  &handle->priv_key,
1347  handle,
1349  handle,
1351  handle);
1352  return;
1353  }
1354  }
1356  return;
1357  }
1358  }
1359 }
1360 
1361 
1362 static void
1363 build_redirect (void *cls)
1364 {
1365  struct RequestHandle *handle = cls;
1366  struct MHD_Response *resp;
1367  char *redirect_uri;
1368 
1369  if (GNUNET_YES == handle->oidc->user_cancelled)
1370  {
1371  if ((NULL != handle->redirect_prefix) &&
1372  (NULL != handle->redirect_suffix) && (NULL != handle->tld))
1373  {
1374  GNUNET_asprintf (&redirect_uri,
1375  "%s.%s/%s?error=%s&error_description=%s&state=%s",
1376  handle->redirect_prefix,
1377  handle->tld,
1378  handle->redirect_suffix,
1379  "access_denied",
1380  "User denied access",
1381  handle->oidc->state);
1382  }
1383  else
1384  {
1385  GNUNET_asprintf (&redirect_uri,
1386  "%s?error=%s&error_description=%s&state=%s",
1387  handle->oidc->redirect_uri,
1388  "access_denied",
1389  "User denied access",
1390  handle->oidc->state);
1391  }
1392  resp = GNUNET_REST_create_response ("");
1393  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1394  "Location",
1395  redirect_uri));
1396  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1398  GNUNET_free (redirect_uri);
1399  return;
1400  }
1402 }
1403 
1404 
1405 static void
1407  uint32_t rd_count,
1408  const struct GNUNET_GNSRECORD_Data *rd)
1409 {
1410  struct RequestHandle *handle = cls;
1411  char *tmp;
1412  char *tmp_key_str;
1413  char *pos;
1414  struct GNUNET_IDENTITY_PublicKey redirect_zone;
1415 
1416  handle->gns_op = NULL;
1417  if (0 == rd_count)
1418  {
1420  handle->edesc =
1421  GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1423  return;
1424  }
1425  for (int i = 0; i < rd_count; i++)
1426  {
1427  if (GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT != rd[i].record_type)
1428  continue;
1429  if (0 != strncmp (rd[i].data, handle->oidc->redirect_uri, rd[i].data_size))
1430  continue;
1431  tmp = GNUNET_strndup (rd[i].data, rd[i].data_size);
1432  if (NULL == strstr (tmp, handle->oidc->client_id))
1433  {
1435  "Redirect uri %s does not contain client_id %s\n",
1436  tmp,
1437  handle->oidc->client_id);
1438  }
1439  else
1440  {
1441  pos = strrchr (tmp, (unsigned char) '.');
1442  if (NULL == pos)
1443  {
1445  "Redirect uri %s contains client_id but is malformed\n",
1446  tmp);
1447  GNUNET_free (tmp);
1448  continue;
1449  }
1450  *pos = '\0';
1451  handle->redirect_prefix = GNUNET_strdup (tmp);
1452  tmp_key_str = pos + 1;
1453  pos = strchr (tmp_key_str, (unsigned char) '/');
1454  if (NULL == pos)
1455  {
1457  "Redirect uri %s contains client_id but is malformed\n",
1458  tmp);
1459  GNUNET_free (tmp);
1460  continue;
1461  }
1462  *pos = '\0';
1463  handle->redirect_suffix = GNUNET_strdup (pos + 1);
1464 
1465  GNUNET_STRINGS_string_to_data (tmp_key_str,
1466  strlen (tmp_key_str),
1467  &redirect_zone,
1468  sizeof(redirect_zone));
1469  }
1471  GNUNET_free (tmp);
1472  return;
1473  }
1475  handle->edesc =
1476  GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1478 }
1479 
1480 
1484 static void
1485 client_redirect (void *cls)
1486 {
1487  struct RequestHandle *handle = cls;
1488 
1489  /* Lookup client redirect uri to verify request */
1490  handle->gns_op =
1493  &handle->oidc->client_pkey,
1497  handle);
1498 }
1499 
1500 
1501 static char *
1502 get_url_parameter_copy (const struct RequestHandle *handle, const char *key)
1503 {
1504  struct GNUNET_HashCode hc;
1505  char *value;
1506  char *res;
1507 
1508  GNUNET_CRYPTO_hash (key, strlen (key), &hc);
1510  ->url_param_map,
1511  &hc))
1512  return NULL;
1513  value =
1514  GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, &hc);
1515  if (NULL == value)
1516  return NULL;
1517  GNUNET_STRINGS_urldecode (value, strlen (value), &res);
1518  return res;
1519 }
1520 
1521 
1528 static void
1530 {
1531  struct RequestHandle *handle = cls;
1532  struct GNUNET_HashCode cache_key;
1533 
1534  char *expected_scope;
1535  char delimiter[] = " ";
1536  int number_of_ignored_parameter, iterator;
1537 
1538 
1539  // REQUIRED value: redirect_uri
1540  handle->oidc->redirect_uri =
1542  if (NULL == handle->oidc->redirect_uri)
1543  {
1545  handle->edesc = GNUNET_strdup ("missing parameter redirect_uri");
1547  return;
1548  }
1549 
1550  // REQUIRED value: response_type
1551  handle->oidc->response_type =
1553  if (NULL == handle->oidc->response_type)
1554  {
1556  handle->edesc = GNUNET_strdup ("missing parameter response_type");
1558  return;
1559  }
1560 
1561  // REQUIRED value: scope
1563  if (NULL == handle->oidc->scope)
1564  {
1566  handle->edesc = GNUNET_strdup ("missing parameter scope");
1568  return;
1569  }
1570 
1571  // OPTIONAL value: nonce
1573 
1574  // OPTIONAL value: claims
1576 
1577  // TODO check other values if needed
1578  number_of_ignored_parameter =
1579  sizeof(OIDC_ignored_parameter_array) / sizeof(char *);
1580  for (iterator = 0; iterator < number_of_ignored_parameter; iterator++)
1581  {
1584  &cache_key);
1585  if (GNUNET_YES ==
1587  ->url_param_map,
1588  &cache_key))
1589  {
1591  GNUNET_asprintf (&handle->edesc,
1592  "Server will not handle parameter: %s",
1595  return;
1596  }
1597  }
1598 
1599  // We only support authorization code flows.
1600  if (0 != strcmp (handle->oidc->response_type,
1602  {
1604  handle->edesc = GNUNET_strdup ("The authorization server does not support "
1605  "obtaining this authorization code.");
1607  return;
1608  }
1609 
1610  // Checks if scope contains 'openid'
1611  expected_scope = GNUNET_strdup (handle->oidc->scope);
1612  char *test;
1613  test = strtok (expected_scope, delimiter);
1614  while (NULL != test)
1615  {
1616  if (0 == strcmp (OIDC_EXPECTED_AUTHORIZATION_SCOPE, expected_scope))
1617  break;
1618  test = strtok (NULL, delimiter);
1619  }
1620  if (NULL == test)
1621  {
1623  handle->edesc =
1624  GNUNET_strdup ("The requested scope is invalid, unknown, or malformed.");
1626  GNUNET_free (expected_scope);
1627  return;
1628  }
1629 
1630  GNUNET_free (expected_scope);
1631  if ((NULL == handle->oidc->login_identity) &&
1632  (GNUNET_NO == handle->oidc->user_cancelled))
1634  else
1636 }
1637 
1638 
1642 static void
1643 tld_iter (void *cls, const char *section, const char *option, const char *value)
1644 {
1645  struct RequestHandle *handle = cls;
1647 
1648  if (GNUNET_OK !=
1650  {
1651  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Skipping non key %s\n", value);
1652  return;
1653  }
1654  if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1655  handle->tld = GNUNET_strdup (option + 1);
1656 }
1657 
1658 
1666 static void
1668  const char *url,
1669  void *cls)
1670 {
1671  struct RequestHandle *handle = cls;
1672  struct EgoEntry *tmp_ego;
1673  const struct GNUNET_IDENTITY_PrivateKey *priv_key;
1675 
1677 
1678  // RECOMMENDED value: state - REQUIRED for answers
1680 
1681  // REQUIRED value: client_id
1683  if (NULL == handle->oidc->client_id)
1684  {
1686  handle->edesc = GNUNET_strdup ("missing parameter client_id");
1687  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1689  return;
1690  }
1691 
1692  // OPTIONAL value: code_challenge
1693  handle->oidc->code_challenge = get_url_parameter_copy (handle,
1695  if (NULL == handle->oidc->code_challenge)
1696  {
1698  "OAuth authorization request does not contain PKCE parameters!\n");
1699  }
1700 
1701  if (GNUNET_OK !=
1703  &handle->oidc->client_pkey))
1704  {
1706  handle->edesc = GNUNET_strdup ("The client is not authorized to request an "
1707  "authorization code using this method.");
1708  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1710  return;
1711  }
1712 
1713  // If we know this identity, translated the corresponding TLD
1714  // TODO: We might want to have a reverse lookup functionality for TLDs?
1715  for (tmp_ego = ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next)
1716  {
1717  priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego);
1718  GNUNET_IDENTITY_key_get_public (priv_key, &pkey);
1719  if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1720  {
1721  handle->tld = GNUNET_strdup (tmp_ego->identifier);
1722  handle->ego_entry = ego_tail;
1723  }
1724  }
1725  if (NULL == handle->tld)
1727  if (NULL == handle->tld)
1728  handle->tld = GNUNET_strdup (handle->oidc->client_id);
1730 }
1731 
1732 
1740 static void
1742  const char *url,
1743  void *cls)
1744 {
1745  struct MHD_Response *resp = GNUNET_REST_create_response ("");
1746  struct RequestHandle *handle = cls;
1747  struct GNUNET_HashCode cache_key;
1748  struct GNUNET_TIME_Absolute *current_time;
1749  struct GNUNET_TIME_Absolute *last_time;
1750  char *cookie;
1751  char *header_val;
1752  json_t *root;
1753  json_error_t error;
1754  json_t *identity;
1755  char term_data[handle->rest_handle->data_size + 1];
1756 
1757  term_data[handle->rest_handle->data_size] = '\0';
1758  GNUNET_memcpy (term_data,
1759  handle->rest_handle->data,
1760  handle->rest_handle->data_size);
1761  root = json_loads (term_data, JSON_DECODE_ANY, &error);
1762  identity = json_object_get (root, "identity");
1763  if (! json_is_string (identity))
1764  {
1766  "Error parsing json string from %s\n",
1767  term_data);
1768  handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
1769  json_decref (root);
1771  return;
1772  }
1773  GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity));
1774  GNUNET_asprintf (&header_val,
1775  "%s;Max-Age=%d",
1776  cookie,
1778  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
1779  "Set-Cookie", header_val));
1780  GNUNET_assert (MHD_NO !=
1781  MHD_add_response_header (resp,
1782  "Access-Control-Allow-Methods",
1783  "POST"));
1784  GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key);
1785 
1786  if (0 != strcmp (json_string_value (identity), "Denied"))
1787  {
1788  current_time = GNUNET_new (struct GNUNET_TIME_Absolute);
1789  *current_time = GNUNET_TIME_relative_to_absolute (
1792  last_time =
1794  GNUNET_free (last_time);
1796  &cache_key,
1797  current_time,
1799  }
1800  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1801  GNUNET_free (cookie);
1802  GNUNET_free (header_val);
1803  json_decref (root);
1805 }
1806 
1807 
1808 static int
1810  char **client_id,
1811  char **client_secret)
1812 {
1813  struct GNUNET_HashCode cache_key;
1814  char *authorization;
1815  char *credentials;
1816  char *basic_authorization;
1817  char *client_id_tmp;
1818  char *pass;
1819 
1822  &cache_key);
1824  ->header_param_map,
1825  &cache_key))
1826  return GNUNET_SYSERR;
1827  authorization =
1828  GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
1829  &cache_key);
1830 
1831  // split header in "Basic" and [content]
1832  credentials = strtok (authorization, " ");
1833  if ((NULL == credentials) || (0 != strcmp ("Basic", credentials)))
1834  return GNUNET_SYSERR;
1835  credentials = strtok (NULL, " ");
1836  if (NULL == credentials)
1837  return GNUNET_SYSERR;
1838  GNUNET_STRINGS_base64_decode (credentials,
1839  strlen (credentials),
1840  (void **) &basic_authorization);
1841 
1842  if (NULL == basic_authorization)
1843  return GNUNET_SYSERR;
1844  client_id_tmp = strtok (basic_authorization, ":");
1845  if (NULL == client_id_tmp)
1846  {
1847  GNUNET_free (basic_authorization);
1848  return GNUNET_SYSERR;
1849  }
1850  pass = strtok (NULL, ":");
1851  if (NULL == pass)
1852  {
1853  GNUNET_free (basic_authorization);
1854  return GNUNET_SYSERR;
1855  }
1856  *client_id = strdup (client_id_tmp);
1857  *client_secret = strdup (pass);
1858  GNUNET_free (basic_authorization);
1859  return GNUNET_OK;
1860 }
1861 
1862 
1863 static int
1865  char **client_id,
1866  char **client_secret)
1867 {
1868  struct GNUNET_HashCode cache_key;
1869  char *client_id_tmp;
1870  char *pass;
1871 
1872  GNUNET_CRYPTO_hash ("client_id",
1873  strlen ("client_id"),
1874  &cache_key);
1876  ->url_param_map,
1877  &cache_key))
1878  return GNUNET_SYSERR;
1879  client_id_tmp = GNUNET_CONTAINER_multihashmap_get (
1880  handle->rest_handle->url_param_map,
1881  &cache_key);
1882  if (NULL == client_id_tmp)
1883  return GNUNET_SYSERR;
1884  *client_id = strdup (client_id_tmp);
1885  GNUNET_CRYPTO_hash ("client_secret",
1886  strlen ("client_secret"),
1887  &cache_key);
1889  ->url_param_map,
1890  &cache_key))
1891  {
1892  GNUNET_free (*client_id);
1893  *client_id = NULL;
1894  return GNUNET_SYSERR;
1895  }
1896  pass = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
1897  &cache_key);
1898  if (NULL == pass)
1899  {
1900  GNUNET_free (*client_id);
1901  *client_id = NULL;
1902  return GNUNET_SYSERR;
1903  }
1904  *client_secret = strdup (pass);
1905  return GNUNET_OK;
1906 }
1907 
1908 
1909 static int
1911  struct GNUNET_IDENTITY_PublicKey *cid)
1912 {
1913  char *expected_pass;
1914  char *received_cid;
1915  char *received_cpw;
1916  char *pkce_cv;
1917 
1919  &received_cid,
1920  &received_cpw))
1921  {
1923  "Received client credentials in HTTP AuthZ header\n");
1924  }
1926  &received_cid,
1927  &received_cpw))
1928  {
1930  "Received client credentials in POST body\n");
1931  }
1932  else
1933  {
1936  if (NULL == pkce_cv)
1937  {
1939  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1940  return GNUNET_SYSERR;
1941  }
1942  handle->public_client = GNUNET_YES;
1943  GNUNET_free (pkce_cv);
1945  GNUNET_STRINGS_string_to_data (received_cid,
1946  strlen (received_cid),
1947  cid,
1948  sizeof(struct GNUNET_IDENTITY_PublicKey));
1949  GNUNET_free (received_cid);
1950  return GNUNET_OK;
1951 
1952  }
1953 
1954  // check client password
1956  "reclaim-rest-plugin",
1957  "OIDC_CLIENT_SECRET",
1958  &expected_pass))
1959  {
1960  if (0 != strcmp (expected_pass, received_cpw))
1961  {
1962  GNUNET_free (expected_pass);
1964  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1965  GNUNET_free (received_cpw);
1966  GNUNET_free (received_cid);
1967  return GNUNET_SYSERR;
1968  }
1969  GNUNET_free (expected_pass);
1970  }
1971  else
1972  {
1973  GNUNET_free (received_cpw);
1974  GNUNET_free (received_cid);
1976  handle->edesc = GNUNET_strdup ("gnunet configuration failed");
1977  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1978  return GNUNET_SYSERR;
1979  }
1980  // check client_id
1981  for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
1982  handle->ego_entry = handle->ego_entry->next)
1983  {
1984  if (0 == strcmp (handle->ego_entry->keystring, received_cid))
1985  break;
1986  }
1987  if (NULL == handle->ego_entry)
1988  {
1989  GNUNET_free (received_cpw);
1990  GNUNET_free (received_cid);
1992  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1993  return GNUNET_SYSERR;
1994  }
1995  GNUNET_STRINGS_string_to_data (received_cid,
1996  strlen (received_cid),
1997  cid,
1998  sizeof(struct GNUNET_IDENTITY_PublicKey));
1999 
2000  GNUNET_free (received_cpw);
2001  GNUNET_free (received_cid);
2002  return GNUNET_OK;
2003 }
2004 
2005 
2006 const struct EgoEntry *
2008  struct GNUNET_IDENTITY_PublicKey *test_key)
2009 {
2010  struct EgoEntry *ego_entry;
2011  struct GNUNET_IDENTITY_PublicKey pub_key;
2012 
2013  for (ego_entry = ego_head; NULL != ego_entry;
2014  ego_entry = ego_entry->next)
2015  {
2016  GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key);
2017  if (0 == GNUNET_memcmp (&pub_key, test_key))
2018  return ego_entry;
2019  }
2020  return NULL;
2021 }
2022 
2023 
2031 static void
2033  const char *url,
2034  void *cls)
2035 {
2036  struct RequestHandle *handle = cls;
2037  const struct EgoEntry *ego_entry;
2038  struct GNUNET_TIME_Relative expiration_time;
2039  struct GNUNET_RECLAIM_AttributeList *cl = NULL;
2040  struct GNUNET_RECLAIM_PresentationList *pl = NULL;
2042  struct GNUNET_IDENTITY_PublicKey cid;
2043  struct GNUNET_HashCode cache_key;
2044  struct MHD_Response *resp;
2045  char *grant_type;
2046  char *code;
2047  char *json_response;
2048  char *id_token;
2049  char *access_token;
2050  char *jwt_secret;
2051  char *nonce = NULL;
2052  char *code_verifier;
2053 
2054  /*
2055  * Check Authorization
2056  */
2057  if (GNUNET_SYSERR == check_authorization (handle, &cid))
2058  {
2060  "OIDC authorization for token endpoint failed\n");
2062  return;
2063  }
2064 
2065  /*
2066  * Check parameter
2067  */
2068 
2069  // TODO Do not allow multiple equal parameter names
2070  // REQUIRED grant_type
2072  strlen (OIDC_GRANT_TYPE_KEY),
2073  &cache_key);
2075  if (NULL == grant_type)
2076  {
2078  handle->edesc = GNUNET_strdup ("missing parameter grant_type");
2079  handle->response_code = MHD_HTTP_BAD_REQUEST;
2081  return;
2082  }
2083 
2084  // Check parameter grant_type == "authorization_code"
2085  if (0 != strcmp (OIDC_GRANT_TYPE_VALUE, grant_type))
2086  {
2088  handle->response_code = MHD_HTTP_BAD_REQUEST;
2089  GNUNET_free (grant_type);
2091  return;
2092  }
2093  GNUNET_free (grant_type);
2094  // REQUIRED code
2096  if (NULL == code)
2097  {
2099  handle->edesc = GNUNET_strdup ("missing parameter code");
2100  handle->response_code = MHD_HTTP_BAD_REQUEST;
2102  return;
2103  }
2104  ego_entry = find_ego (handle, &cid);
2105  if (NULL == ego_entry)
2106  {
2108  handle->edesc = GNUNET_strdup ("Unknown client");
2109  handle->response_code = MHD_HTTP_BAD_REQUEST;
2110  GNUNET_free (code);
2112  return;
2113  }
2114 
2115  // REQUIRED code verifier
2117  if (NULL == code_verifier)
2118  {
2120  "OAuth authorization request does not contain PKCE parameters!\n");
2121 
2122  }
2123 
2124  // decode code
2125  if (GNUNET_OK != OIDC_parse_authz_code (&cid, code, code_verifier, &ticket,
2126  &cl, &pl, &nonce,
2128  {
2130  handle->edesc = GNUNET_strdup ("invalid code");
2131  handle->response_code = MHD_HTTP_BAD_REQUEST;
2132  GNUNET_free (code);
2133  if (NULL != code_verifier)
2134  GNUNET_free (code_verifier);
2136  return;
2137  }
2138  if (NULL != code_verifier)
2139  GNUNET_free (code_verifier);
2140 
2141  // create jwt
2143  "reclaim-rest-plugin",
2144  "expiration_time",
2145  &expiration_time))
2146  {
2148  handle->edesc = GNUNET_strdup ("gnunet configuration failed");
2149  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2150  GNUNET_free (code);
2151  if (NULL != nonce)
2152  GNUNET_free (nonce);
2156  return;
2157  }
2158 
2159 
2160  // TODO OPTIONAL acr,amr,azp
2162  "reclaim-rest-plugin",
2163  "jwt_secret",
2164  &jwt_secret))
2165  {
2167  handle->edesc = GNUNET_strdup ("No signing secret configured!");
2168  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2169  GNUNET_free (code);
2172  if (NULL != nonce)
2173  GNUNET_free (nonce);
2175  return;
2176  }
2177  id_token = OIDC_generate_id_token (&ticket.audience,
2178  &ticket.identity,
2179  cl,
2180  pl,
2181  &expiration_time,
2182  (NULL != nonce) ? nonce : NULL,
2183  jwt_secret);
2184  GNUNET_free (jwt_secret);
2185  if (NULL != nonce)
2186  GNUNET_free (nonce);
2187  access_token = OIDC_access_token_new (&ticket);
2188  /* Store mapping from access token to code so we can later
2189  * fall back on the provided attributes in userinfo
2190  */
2191  GNUNET_CRYPTO_hash (access_token,
2192  strlen (access_token),
2193  &cache_key);
2195  &cache_key);
2197  &cache_key,
2198  code,
2200  /* If there was a previous code in there, free the old value */
2201  if (NULL != tmp_at)
2202  {
2204  "OIDC access token already issued. Cleanup.\n");
2205  GNUNET_free (tmp_at);
2206  }
2207 
2208  OIDC_build_token_response (access_token,
2209  id_token,
2210  &expiration_time,
2211  &json_response);
2212 
2213  resp = GNUNET_REST_create_response (json_response);
2214  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2215  "Cache-Control",
2216  "no-store"));
2217  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2218  "Pragma", "no-cache"));
2219  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
2220  "Content-Type",
2221  "application/json"));
2222  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2225  GNUNET_free (access_token);
2226  GNUNET_free (json_response);
2227  GNUNET_free (id_token);
2229 }
2230 
2231 
2235 static void
2236 consume_ticket (void *cls,
2237  const struct GNUNET_IDENTITY_PublicKey *identity,
2238  const struct GNUNET_RECLAIM_Attribute *attr,
2239  const struct GNUNET_RECLAIM_Presentation *presentation)
2240 {
2241  struct RequestHandle *handle = cls;
2244  struct MHD_Response *resp;
2245  char *result_str;
2246 
2247  if (NULL != handle->consume_timeout_op)
2248  GNUNET_SCHEDULER_cancel (handle->consume_timeout_op);
2249  handle->consume_timeout_op = NULL;
2250  handle->idp_op = NULL;
2251 
2252  if (NULL == identity)
2253  {
2254  result_str = OIDC_generate_userinfo (&handle->ticket.identity,
2255  handle->attr_userinfo_list,
2256  handle->presentations);
2257  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2258  resp = GNUNET_REST_create_response (result_str);
2259  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2260  GNUNET_free (result_str);
2262  return;
2263  }
2266  &attr->credential,
2267  attr->type,
2268  attr->data,
2269  attr->data_size);
2270  ale->attribute->id = attr->id;
2271  ale->attribute->flag = attr->flag;
2272  ale->attribute->credential = attr->credential;
2273  GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head,
2274  handle->attr_userinfo_list->list_tail,
2275  ale);
2276  if (NULL == presentation)
2277  return;
2278  for (atle = handle->presentations->list_head;
2279  NULL != atle; atle = atle->next)
2280  {
2282  &atle->presentation->credential_id,
2283  &presentation->credential_id))
2284  continue;
2285  break;
2286  }
2287  if (NULL == atle)
2288  {
2291  atle->presentation = GNUNET_RECLAIM_presentation_new (presentation->type,
2292  presentation->data,
2293  presentation->
2294  data_size);
2295  atle->presentation->credential_id = presentation->credential_id;
2296  GNUNET_CONTAINER_DLL_insert (handle->presentations->list_head,
2297  handle->presentations->list_tail,
2298  atle);
2299  }
2300 }
2301 
2302 
2303 static void
2305 {
2306  struct RequestHandle *handle = cls;
2307  struct GNUNET_HashCode cache_key;
2308  struct GNUNET_RECLAIM_AttributeList *cl = NULL;
2309  struct GNUNET_RECLAIM_PresentationList *pl = NULL;
2311  char *nonce;
2312  char *cached_code;
2313 
2314  handle->consume_timeout_op = NULL;
2315  if (NULL != handle->idp_op)
2316  GNUNET_RECLAIM_cancel (handle->idp_op);
2317  handle->idp_op = NULL;
2318 
2320  "Ticket consumptioned timed out. Using cache...\n");
2321  GNUNET_CRYPTO_hash (handle->access_token,
2322  strlen (handle->access_token),
2323  &cache_key);
2325  &cache_key);
2326  if (NULL == cached_code)
2327  {
2329  handle->edesc = GNUNET_strdup ("No Access Token in cache!");
2330  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2332  return;
2333  }
2334 
2335  // decode code
2336  if (GNUNET_OK != OIDC_parse_authz_code (&handle->ticket.audience,
2337  cached_code, NULL, &ticket,
2338  &cl, &pl, &nonce,
2340  {
2342  handle->edesc = GNUNET_strdup ("invalid code");
2343  handle->response_code = MHD_HTTP_BAD_REQUEST;
2344  GNUNET_free (cached_code);
2345  if (NULL != nonce)
2346  GNUNET_free (nonce);
2348  return;
2349  }
2350 
2351  struct MHD_Response *resp;
2352  char *result_str;
2353 
2354  result_str = OIDC_generate_userinfo (&handle->ticket.identity,
2355  cl,
2356  pl);
2357  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2358  resp = GNUNET_REST_create_response (result_str);
2359  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2360  GNUNET_free (result_str);
2361  GNUNET_free (nonce);
2365 }
2366 
2367 
2375 static void
2377  const char *url,
2378  void *cls)
2379 {
2380  // TODO expiration time
2381  struct RequestHandle *handle = cls;
2382  struct GNUNET_RECLAIM_Ticket *ticket;
2383  char delimiter[] = " ";
2384  struct GNUNET_HashCode cache_key;
2385  char *authorization;
2386  char *authorization_type;
2387  char *authorization_access_token;
2388  const struct EgoEntry *aud_ego;
2389  const struct GNUNET_IDENTITY_PrivateKey *privkey;
2390 
2391  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting userinfo\n");
2394  &cache_key);
2396  ->header_param_map,
2397  &cache_key))
2398  {
2400  handle->edesc = GNUNET_strdup ("No Access Token");
2401  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2403  return;
2404  }
2405  authorization =
2406  GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map,
2407  &cache_key);
2408 
2409  // split header in "Bearer" and access_token
2410  authorization = GNUNET_strdup (authorization);
2411  authorization_type = strtok (authorization, delimiter);
2412  if ((NULL == authorization_type) ||
2413  (0 != strcmp ("Bearer", authorization_type)))
2414  {
2416  handle->edesc = GNUNET_strdup ("No Access Token");
2417  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2419  GNUNET_free (authorization);
2420  return;
2421  }
2422  authorization_access_token = strtok (NULL, delimiter);
2423  if (NULL == authorization_access_token)
2424  {
2426  handle->edesc = GNUNET_strdup ("Access token missing");
2427  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2429  GNUNET_free (authorization);
2430  return;
2431  }
2432 
2433  if (GNUNET_OK != OIDC_access_token_parse (authorization_access_token,
2434  &ticket))
2435  {
2437  handle->edesc = GNUNET_strdup ("The access token is invalid");
2438  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2440  GNUNET_free (authorization);
2441  return;
2442 
2443  }
2444  GNUNET_assert (NULL != ticket);
2445  handle->ticket = *ticket;
2446  GNUNET_free (ticket);
2447  aud_ego = find_ego (handle, &handle->ticket.audience);
2448  if (NULL == aud_ego)
2449  {
2451  handle->edesc = GNUNET_strdup ("The access token expired");
2452  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2454  GNUNET_free (authorization);
2455  return;
2456  }
2457  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Consuming ticket\n");
2458  privkey = GNUNET_IDENTITY_ego_get_private_key (aud_ego->ego);
2459  handle->attr_userinfo_list =
2461  handle->presentations =
2463 
2464  /* If the consume takes too long, we use values from the cache */
2465  handle->access_token = GNUNET_strdup (authorization_access_token);
2466  handle->consume_timeout_op = GNUNET_SCHEDULER_add_delayed (CONSUME_TIMEOUT,
2467  &consume_timeout,
2468  handle);
2470  privkey,
2471  &handle->ticket,
2472  &consume_ticket,
2473  handle);
2474  GNUNET_free (authorization);
2475 }
2476 
2477 
2510 static void
2511 list_ego (void *cls,
2512  struct GNUNET_IDENTITY_Ego *ego,
2513  void **ctx,
2514  const char *identifier)
2515 {
2516  struct EgoEntry *ego_entry;
2518 
2519  if (NULL == ego)
2520  {
2522  return;
2523  }
2524  if (ID_REST_STATE_INIT == state)
2525 
2526  {
2527  ego_entry = GNUNET_new (struct EgoEntry);
2530  ego_entry->ego = ego;
2531  ego_entry->identifier = GNUNET_strdup (identifier);
2533  ego_tail,
2534  ego_entry);
2535  return;
2536  }
2537  /* Ego renamed or added */
2538  if (identifier != NULL)
2539  {
2540  for (ego_entry = ego_head; NULL != ego_entry;
2541  ego_entry = ego_entry->next)
2542  {
2543  if (ego_entry->ego == ego)
2544  {
2545  /* Rename */
2546  GNUNET_free (ego_entry->identifier);
2547  ego_entry->identifier = GNUNET_strdup (identifier);
2548  break;
2549  }
2550  }
2551  if (NULL == ego_entry)
2552  {
2553  /* Add */
2554  ego_entry = GNUNET_new (struct EgoEntry);
2557  ego_entry->ego = ego;
2558  ego_entry->identifier = GNUNET_strdup (identifier);
2560  ego_tail,
2561  ego_entry);
2562  }
2563  }
2564  else
2565  {
2566  /* Delete */
2567  for (ego_entry = ego_head; NULL != ego_entry;
2568  ego_entry = ego_entry->next)
2569  {
2570  if (ego_entry->ego == ego)
2571  break;
2572  }
2573  if (NULL == ego_entry)
2574  return; /* Not found */
2575 
2577  ego_tail,
2578  ego_entry);
2579  GNUNET_free (ego_entry->identifier);
2580  GNUNET_free (ego_entry->keystring);
2581  GNUNET_free (ego_entry);
2582  return;
2583  }
2584 }
2585 
2586 
2587 static void
2589  const char *url,
2590  void *cls)
2591 {
2592  json_t *oidc_config;
2593  json_t *auth_methods;
2594  json_t *sig_algs;
2595  json_t *scopes;
2596  json_t *response_types;
2597  json_t *sub_types;
2598  json_t *claim_types;
2599  char *oidc_config_str;
2600  struct MHD_Response *resp;
2601  struct RequestHandle *handle = cls;
2602 
2603  oidc_config = json_object ();
2604  // FIXME get from config?
2605  json_object_set_new (oidc_config,
2606  "issuer", json_string ("http://localhost:7776"));
2607  json_object_set_new (oidc_config,
2608  "authorization_endpoint",
2609  json_string ("https://api.reclaim/openid/authorize"));
2610  json_object_set_new (oidc_config,
2611  "token_endpoint",
2612  json_string ("http://localhost:7776/openid/token"));
2613  auth_methods = json_array ();
2614  json_array_append_new (auth_methods,
2615  json_string ("client_secret_basic"));
2616  json_array_append_new (auth_methods,
2617  json_string ("client_secret_post"));
2618  json_object_set_new (oidc_config,
2619  "token_endpoint_auth_methods_supported",
2620  auth_methods);
2621  sig_algs = json_array ();
2622  json_array_append_new (sig_algs,
2623  json_string ("HS512"));
2624  json_object_set_new (oidc_config,
2625  "id_token_signing_alg_values_supported",
2626  sig_algs);
2627  json_object_set_new (oidc_config,
2628  "userinfo_endpoint",
2629  json_string ("http://localhost:7776/openid/userinfo"));
2630  scopes = json_array ();
2631  json_array_append_new (scopes,
2632  json_string ("openid"));
2633  json_array_append_new (scopes,
2634  json_string ("profile"));
2635  json_array_append_new (scopes,
2636  json_string ("email"));
2637  json_array_append_new (scopes,
2638  json_string ("address"));
2639  json_array_append_new (scopes,
2640  json_string ("phone"));
2641  json_object_set_new (oidc_config,
2642  "scopes_supported",
2643  scopes);
2644  response_types = json_array ();
2645  json_array_append_new (response_types,
2646  json_string ("code"));
2647  json_object_set_new (oidc_config,
2648  "response_types_supported",
2649  response_types);
2650  sub_types = json_array ();
2651  json_array_append_new (sub_types,
2652  json_string ("public")); /* no pairwise support */
2653  json_object_set_new (oidc_config,
2654  "subject_types_supported",
2655  sub_types);
2656  claim_types = json_array ();
2657  json_array_append_new (claim_types,
2658  json_string ("normal"));
2659  json_array_append_new (claim_types,
2660  json_string ("aggregated"));
2661  json_object_set_new (oidc_config,
2662  "claim_types_supported",
2663  claim_types);
2664  json_object_set_new (oidc_config,
2665  "claims_parameter_supported",
2666  json_boolean (1));
2667  oidc_config_str = json_dumps (oidc_config, JSON_INDENT (1));
2668  resp = GNUNET_REST_create_response (oidc_config_str);
2669  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2670  json_decref (oidc_config);
2671  GNUNET_free (oidc_config_str);
2673 }
2674 
2675 
2683 static void
2685  const char *url,
2686  void *cls)
2687 {
2688  struct MHD_Response *resp;
2689  struct RequestHandle *handle = cls;
2690 
2691  // For now, independent of path return all options
2692  resp = GNUNET_REST_create_response (NULL);
2693  GNUNET_assert (MHD_NO !=
2694  MHD_add_response_header (resp,
2695  "Access-Control-Allow-Methods",
2696  allow_methods));
2697  GNUNET_assert (MHD_NO !=
2698  MHD_add_response_header (resp,
2699  "Access-Control-Allow-Origin",
2700  "*"));
2701  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2703  return;
2704 }
2705 
2706 
2707 static enum GNUNET_GenericReturnValue
2710  void *proc_cls)
2711 {
2712  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
2714  static const struct GNUNET_REST_RequestHandler handlers[] =
2715  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint },
2716  { MHD_HTTP_METHOD_POST,
2718  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont },
2719  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
2720  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
2721  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
2722  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_OIDC_CONFIG,
2724  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC_CONFIG,
2725  &oidc_config_cors },
2726  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont },
2728 
2729  handle->oidc = GNUNET_new (struct OIDC_Variables);
2730  if (NULL == OIDC_cookie_jar_map)
2732  GNUNET_NO);
2733  if (NULL == oidc_code_cache)
2735  GNUNET_NO);
2736 
2737  handle->response_code = 0;
2739  handle->proc_cls = proc_cls;
2740  handle->proc = proc;
2741  handle->rest_handle = rest_handle;
2742  handle->url = GNUNET_strdup (rest_handle->url);
2743  handle->timeout_task =
2746  requests_tail,
2747  handle);
2748  if (handle->url[strlen (handle->url) - 1] == '/')
2749  handle->url[strlen (handle->url) - 1] = '\0';
2750  if (GNUNET_NO ==
2751  GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
2752  return GNUNET_NO;
2753 
2754  return GNUNET_YES;
2755 }
2756 
2757 
2764 void *
2766 {
2767  static struct Plugin plugin;
2768  struct GNUNET_REST_Plugin *api;
2769 
2770  cfg = cls;
2771  if (NULL != plugin.cfg)
2772  return NULL; /* can only initialize once! */
2773  memset (&plugin, 0, sizeof(struct Plugin));
2774  plugin.cfg = cfg;
2775  api = GNUNET_new (struct GNUNET_REST_Plugin);
2776  api->cls = &plugin;
2782 
2785  "%s, %s, %s, %s, %s",
2786  MHD_HTTP_METHOD_GET,
2787  MHD_HTTP_METHOD_POST,
2788  MHD_HTTP_METHOD_PUT,
2789  MHD_HTTP_METHOD_DELETE,
2790  MHD_HTTP_METHOD_OPTIONS);
2791 
2793  _ ("OpenID Connect REST API initialized\n"));
2794  return api;
2795 }
2796 
2797 
2798 static int
2799 cleanup_hashmap (void *cls, const struct GNUNET_HashCode *key, void *value)
2800 {
2801  GNUNET_free (value);
2802  return GNUNET_YES;
2803 }
2804 
2805 
2812 void *
2814 {
2815  struct GNUNET_REST_Plugin *api = cls;
2816  struct Plugin *plugin = api->cls;
2817  struct EgoEntry *ego_entry;
2818 
2819  plugin->cfg = NULL;
2820  while (NULL != requests_head)
2822  if (NULL != OIDC_cookie_jar_map)
2823  {
2825  &cleanup_hashmap,
2826  NULL);
2828  }
2829  if (NULL != oidc_code_cache)
2830  {
2832  &cleanup_hashmap,
2833  NULL);
2835  }
2836 
2838  if (NULL != gns_handle)
2840  if (NULL != identity_handle)
2842  if (NULL != idp)
2844  while (NULL != (ego_entry = ego_head))
2845  {
2847  ego_tail,
2848  ego_entry);
2849  GNUNET_free (ego_entry->identifier);
2850  GNUNET_free (ego_entry->keystring);
2851  GNUNET_free (ego_entry);
2852  }
2853  GNUNET_free (api);
2855  "OpenID Connect REST plugin is finished\n");
2856  return NULL;
2857 }
2858 
2859 
2860 /* end of plugin_rest_openid_connect.c */
#define GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT
Used reclaimID OIDC client redirect URIs.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
static int res
static struct GNUNET_CADET_MessageHandler handlers[]
Handlers, for diverse services.
struct Plugin * plugin
The process handle to the testbed service.
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_DNS_Handle * handle
Handle to transport service.
uint32_t data
The data value.
struct GNUNET_IDENTITY_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_IDENTITY_PublicKey pubkey
Public key of the zone to look in.
static char * value
Value of the record to add/remove.
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 char buf[2048]
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
char * GNUNET_buffer_reap_str(struct GNUNET_Buffer *buf)
Clear the buffer and return the string it contained.
Definition: buffer.c:123
void GNUNET_buffer_write_fstr(struct GNUNET_Buffer *buf, const char *fmt,...) __attribute__((format(printf
Write a 0-terminated formatted string to a buffer, excluding the 0-terminator.
void GNUNET_buffer_write_str(struct GNUNET_Buffer *buf, const char *str)
Write a 0-terminated string to a buffer, excluding the 0-terminator.
Definition: buffer.c:103
#define GNUNET_log(kind,...)
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
Definition: gnunet_common.h:92
@ GNUNET_OK
Definition: gnunet_common.h:95
@ GNUNET_YES
Definition: gnunet_common.h:97
@ GNUNET_NO
Definition: gnunet_common.h:94
@ GNUNET_SYSERR
Definition: gnunet_common.h:93
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.
#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.
struct GNUNET_GNS_LookupRequest * GNUNET_GNS_lookup(struct GNUNET_GNS_Handle *handle, const char *name, const struct GNUNET_IDENTITY_PublicKey *zone, uint32_t type, enum GNUNET_GNS_LocalOptions options, GNUNET_GNS_LookupResultProcessor proc, void *proc_cls)
Perform an asynchronous lookup operation on the GNS.
Definition: gns_api.c:412
void GNUNET_GNS_disconnect(struct GNUNET_GNS_Handle *handle)
Shutdown connection with the GNS service.
Definition: gns_api.c:290
void * GNUNET_GNS_lookup_cancel(struct GNUNET_GNS_LookupRequest *lr)
Cancel pending lookup request.
Definition: gns_api.c:314
struct GNUNET_GNS_Handle * GNUNET_GNS_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Initialize the connection with the GNS service.
Definition: gns_api.c:268
#define GNUNET_GNS_EMPTY_LABEL_AT
String we use to indicate an empty label (top-level entry in the zone).
@ GNUNET_GNS_LO_DEFAULT
Defaults, look in cache, then in DHT.
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
int 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).
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
int 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.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash 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.
static int iterator(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Iterator over hash map entries.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE
If a value with the given key exists, replace it.
const struct GNUNET_IDENTITY_PrivateKey * GNUNET_IDENTITY_ego_get_private_key(const struct GNUNET_IDENTITY_Ego *ego)
Obtain the ECC key associated with a ego.
Definition: identity_api.c:639
enum GNUNET_GenericReturnValue GNUNET_IDENTITY_public_key_from_string(const char *str, struct GNUNET_IDENTITY_PublicKey *key)
Parses a (Base32) string representation of the public key.
enum GNUNET_GenericReturnValue GNUNET_IDENTITY_key_get_public(const struct GNUNET_IDENTITY_PrivateKey *privkey, struct GNUNET_IDENTITY_PublicKey *key)
Retrieves the public key representation of a private key.
Definition: identity_api.c:175
void GNUNET_IDENTITY_ego_get_public_key(struct GNUNET_IDENTITY_Ego *ego, struct GNUNET_IDENTITY_PublicKey *pk)
Get the identifier (public key) of an ego.
Definition: identity_api.c:652
char * GNUNET_IDENTITY_public_key_to_string(const struct GNUNET_IDENTITY_PublicKey *key)
Creates a (Base32) string representation of the public key.
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:610
void GNUNET_IDENTITY_disconnect(struct GNUNET_IDENTITY_Handle *h)
Disconnect from identity service.
Definition: identity_api.c:921
#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)
void GNUNET_RECLAIM_attribute_list_destroy(struct GNUNET_RECLAIM_AttributeList *attrs)
Destroy claim list.
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_credential_list_destroy(struct GNUNET_RECLAIM_CredentialList *credentials)
Destroy claim 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_Presentation * GNUNET_RECLAIM_presentation_new(uint32_t type, const void *data, size_t data_size)
void GNUNET_RECLAIM_disconnect(struct GNUNET_RECLAIM_Handle *h)
Disconnect from identity provider service.
Definition: reclaim_api.c:1103
struct GNUNET_RECLAIM_AttributeIterator * GNUNET_RECLAIM_get_attributes_start(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_IDENTITY_PrivateKey *identity, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_RECLAIM_AttributeResult proc, void *proc_cls, GNUNET_SCHEDULER_TaskCallback finish_cb, void *finish_cb_cls)
List all attributes for a local identity.
Definition: reclaim_api.c:1330
void GNUNET_RECLAIM_cancel(struct GNUNET_RECLAIM_Operation *op)
Cancel an identity provider operation.
Definition: reclaim_api.c:1088
void GNUNET_RECLAIM_get_attributes_stop(struct GNUNET_RECLAIM_AttributeIterator *it)
Stops iteration and releases the handle for further calls.
Definition: reclaim_api.c:1397
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:1486
struct GNUNET_RECLAIM_CredentialIterator * GNUNET_RECLAIM_get_credentials_start(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_IDENTITY_PrivateKey *identity, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_RECLAIM_CredentialResult proc, void *proc_cls, GNUNET_SCHEDULER_TaskCallback finish_cb, void *finish_cb_cls)
List all credentials for a local identity.
Definition: reclaim_api.c:1439
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:1376
struct GNUNET_RECLAIM_Operation * GNUNET_RECLAIM_ticket_issue(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_IDENTITY_PrivateKey *iss, const struct GNUNET_IDENTITY_PublicKey *rp, const struct GNUNET_RECLAIM_AttributeList *attrs, GNUNET_RECLAIM_IssueTicketCallback cb, void *cb_cls)
Issues a ticket to a relying party.
Definition: reclaim_api.c:1541
struct GNUNET_RECLAIM_Handle * GNUNET_RECLAIM_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the re:claimID service.
Definition: reclaim_api.c:1063
void GNUNET_RECLAIM_get_credentials_stop(struct GNUNET_RECLAIM_CredentialIterator *ait)
Stops iteration and releases the handle for further calls.
Definition: reclaim_api.c:1508
struct GNUNET_RECLAIM_Operation * GNUNET_RECLAIM_ticket_consume(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_IDENTITY_PrivateKey *identity, const struct GNUNET_RECLAIM_Ticket *ticket, GNUNET_RECLAIM_AttributeTicketResult cb, void *cb_cls)
Consumes an issued ticket.
Definition: reclaim_api.c:1590
void GNUNET_RECLAIM_ticket_iteration_stop(struct GNUNET_RECLAIM_TicketIterator *it)
Stops iteration and releases the handle for further calls.
Definition: reclaim_api.c:1700
struct MHD_Response * GNUNET_REST_create_response(const char *data)
Create REST MHD response.
Definition: rest.c:57
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:77
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 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:1296
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:972
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:1269
size_t GNUNET_STRINGS_urldecode(const char *data, size_t len, char **out)
url/percent encode (RFC3986).
Definition: strings.c:1793
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
Definition: strings.c:750
size_t GNUNET_STRINGS_urlencode(const char *data, size_t len, char **out)
url/percent encode (RFC3986).
Definition: strings.c:1830
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:775
size_t GNUNET_STRINGS_base64_decode(const char *data, size_t len, void **output)
Decode from Base64.
Definition: strings.c:1682
#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:86
struct GNUNET_TIME_Relative GNUNET_TIME_relative_get_second_(void)
Return relative time of 1s.
Definition: time.c:136
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:181
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:311
char * OIDC_generate_id_token(const struct GNUNET_IDENTITY_PublicKey *aud_key, const struct GNUNET_IDENTITY_PublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations, const struct GNUNET_TIME_Relative *expiration_time, const char *nonce, const char *secret_key)
Create a JWT from attributes.
Definition: oidc_helper.c:371
char * OIDC_generate_userinfo(const struct GNUNET_IDENTITY_PublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations)
Generate userinfo JSON as string.
Definition: oidc_helper.c:344
char * OIDC_access_token_new(const struct GNUNET_RECLAIM_Ticket *ticket)
Generate a new access token.
Definition: oidc_helper.c:824
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:866
char * OIDC_build_authz_code(const struct GNUNET_IDENTITY_PrivateKey *issuer, const struct GNUNET_RECLAIM_Ticket *ticket, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations, const char *nonce_str, const char *code_challenge)
Builds an OIDC authorization code including a reclaim ticket and nonce.
Definition: oidc_helper.c:489
int OIDC_parse_authz_code(const struct GNUNET_IDENTITY_PublicKey *audience, const char *code, const char *code_verifier, struct GNUNET_RECLAIM_Ticket *ticket, struct GNUNET_RECLAIM_AttributeList **attrs, struct GNUNET_RECLAIM_PresentationList **presentations, char **nonce_str, enum OIDC_VerificationOptions opts)
Parse reclaim ticket and nonce from authorization code.
Definition: oidc_helper.c:675
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:796
int OIDC_access_token_parse(const char *token, struct GNUNET_RECLAIM_Ticket **ticket)
Parse an access token.
Definition: oidc_helper.c:839
helper library for OIDC related functions
@ 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 _(String)
GNU gettext support macro.
Definition: platform.h:177
static struct EgoEntry * ego_tail
Ego list.
#define OIDC_SCOPE_KEY
OIDC scope key.
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.
static struct GNUNET_RECLAIM_Handle * idp
Identity Provider.
static void consume_timeout(void *cls)
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.
#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)
static void oidc_attr_collect(void *cls, const struct GNUNET_IDENTITY_PublicKey *identity, const struct GNUNET_RECLAIM_Attribute *attr)
Collects all attributes for an ego if in scope parameter.
#define GNUNET_REST_API_NS_LOGIN
Login namespace.
#define OIDC_ERROR_KEY_UNAUTHORIZED_CLIENT
OIDC error key for unauthorized clients.
#define GNUNET_REST_API_NS_OIDC
REST root namespace.
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.
#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.
const struct GNUNET_CONFIGURATION_Handle * cfg
The configuration handle.
#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.
const struct EgoEntry * find_ego(struct RequestHandle *handle, struct GNUNET_IDENTITY_PublicKey *test_key)
static void login_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Combines an identity with a login time and responds OK to login request.
#define OIDC_COOKIE_HEADER_KEY
OIDC cookie header key.
#define ID_REST_STATE_INIT
State while collecting all egos.
#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.
void * libgnunet_plugin_rest_openid_connect_done(void *cls)
Exit point from the plugin.
static int parse_credentials_basic_auth(struct RequestHandle *handle, char **client_id, char **client_secret)
static void oidc_cred_collect(void *cls, const struct GNUNET_IDENTITY_PublicKey *identity, const struct GNUNET_RECLAIM_Credential *cred)
Collects all attributes for an ego if in scope parameter.
#define OIDC_GRANT_TYPE_KEY
OIDC grant_type key.
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.
#define OIDC_COOKIE_HEADER_ACCESS_DENIED
OIDC cookie header if user cancelled.
#define GNUNET_REST_API_NS_TOKEN
Token endpoint.
#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 struct RequestHandle * requests_tail
DLL.
#define OIDC_COOKIE_HEADER_INFORMATION_KEY
OIDC cookie header information key.
static char * get_url_parameter_copy(const struct RequestHandle *handle, const char *key)
#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.
void * libgnunet_plugin_rest_openid_connect_init(void *cls)
Entry point for the plugin.
#define OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE
OIDC expected response_type while authorizing.
static int check_authorization(struct RequestHandle *handle, struct GNUNET_IDENTITY_PublicKey *cid)
#define GNUNET_REST_API_NS_USERINFO
UserInfo endpoint.
static struct GNUNET_RECLAIM_AttributeList * attribute_list_merge(struct GNUNET_RECLAIM_AttributeList *list_a, struct GNUNET_RECLAIM_AttributeList *list_b)
#define GNUNET_REST_API_NS_AUTHORIZE
Authorize endpoint.
static void oidc_config_cors(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Respond to OPTIONS request.
#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.
#define ID_REST_STATE_POST_INIT
Done collecting egos.
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 enum GNUNET_GenericReturnValue rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
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.
static void consume_ticket(void *cls, const struct GNUNET_IDENTITY_PublicKey *identity, const struct GNUNET_RECLAIM_Attribute *attr, const struct GNUNET_RECLAIM_Presentation *presentation)
Collects claims and stores them in handle.
#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)
The ego list.
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.
Common buffer management functions.
Internal representation of the hash map.
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:49
A 512-bit hashcode.
Handle for an ego.
Definition: identity.h:37
Handle for the service.
Definition: identity_api.c:96
Handle for an operation with the identity service.
Definition: identity_api.c:40
A private key for an identity as per LSD0001.
An identity key as per LSD0001.
Handle for a attribute iterator operation.
Definition: reclaim_api.c:183
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:250
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:318
Handle for an operation with the service.
Definition: reclaim_api.c:42
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:120
The authorization ticket.
struct GNUNET_IDENTITY_PublicKey audience
The ticket audience (= relying party)
struct GNUNET_IDENTITY_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.
enum GNUNET_GenericReturnValue(* process_request)(struct GNUNET_REST_RequestHandle *handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function to process a REST call.
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:135
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.
struct GNUNET_IDENTITY_PublicKey client_pkey
The RP client public key.
char * redirect_uri
The OIDC redirect uri.
char * claims
The OIDC claims.
char * code_challenge
The PKCE code_challenge.
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.
struct GNUNET_RECLAIM_TicketIterator * ticket_it
Ticket iterator.
struct GNUNET_RECLAIM_Ticket ticket
A ticket.
char * emsg
Error response message.
struct GNUNET_IDENTITY_Operation * op
IDENTITY Operation.
struct RequestHandle * prev
DLL.
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
Response code.
struct EgoEntry * ego_entry
IDENTITY Operation.
struct GNUNET_SCHEDULER_Task * timeout_task
ID of a task associated with the resolution process.
void * proc_cls
The closure of the result processor.
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.
char * redirect_suffix
The redirect suffix.
struct RequestHandle * next
DLL.
struct GNUNET_IDENTITY_PrivateKey priv_key
Pointer to ego private key.
struct GNUNET_RECLAIM_CredentialIterator * cred_it
Credential iterator.
struct GNUNET_REST_RequestHandle * rest_handle
Rest connection.
char * url
The url.
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).
char * edesc
Error response description.