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 
230 
234 static char *OIDC_ignored_parameter_array[] = { "display",
235  "prompt",
236  "ui_locales",
237  "response_mode",
238  "id_token_hint",
239  "login_hint",
240  "acr_values" };
241 
246 
251 
255 static char *allow_methods;
256 
260 static struct EgoEntry *ego_head;
261 
265 static struct EgoEntry *ego_tail;
266 
270 static int state;
271 
276 
281 
285 static struct GNUNET_RECLAIM_Handle *idp;
286 
290 struct Plugin
291 {
292  const struct GNUNET_CONFIGURATION_Handle *cfg;
293 };
294 
299 {
303  struct GNUNET_CRYPTO_EcdsaPublicKey client_pkey;
304 
308  char *client_id;
309 
314 
318  char *scope;
319 
323  char *state;
324 
328  char *nonce;
329 
333  char *claims;
334 
339 
344 
349 
354 
359 
360 };
361 
365 struct EgoEntry
366 {
370  struct EgoEntry *next;
371 
375  struct EgoEntry *prev;
376 
380  char *identifier;
381 
385  char *keystring;
386 
390  struct GNUNET_IDENTITY_Ego *ego;
391 };
392 
393 
394 struct RequestHandle
395 {
399  struct RequestHandle *next;
400 
404  struct RequestHandle *prev;
405 
409  struct EgoEntry *ego_entry;
410 
415 
420 
425 
429  struct GNUNET_REST_RequestHandle *rest_handle;
430 
435 
440 
445 
450 
455 
456 
461 
466 
471 
472 
477 
482 
487 
492 
497 
501  void *proc_cls;
502 
506  char *url;
507 
511  char *tld;
512 
517 
522 
526  char *emsg;
527 
531  char *edesc;
532 
536  int response_code;
537 
542 };
543 
548 
553 
554 
559 static void
561 {
562 
563  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
564  if (NULL != handle->timeout_task)
566  if (NULL != handle->attr_it)
568  if (NULL != handle->cred_it)
570  if (NULL != handle->ticket_it)
572  if (NULL != handle->idp_op)
573  GNUNET_RECLAIM_cancel (handle->idp_op);
574  GNUNET_free (handle->url);
575  GNUNET_free (handle->tld);
576  GNUNET_free (handle->redirect_prefix);
577  GNUNET_free (handle->redirect_suffix);
578  GNUNET_free (handle->emsg);
579  GNUNET_free (handle->edesc);
580  if (NULL != handle->gns_op)
582  if (NULL != handle->oidc)
583  {
584  GNUNET_free (handle->oidc->client_id);
585  GNUNET_free (handle->oidc->login_identity);
586  GNUNET_free (handle->oidc->nonce);
587  GNUNET_free (handle->oidc->redirect_uri);
588  GNUNET_free (handle->oidc->response_type);
589  GNUNET_free (handle->oidc->scope);
590  GNUNET_free (handle->oidc->state);
591  GNUNET_free (handle->oidc);
592  }
593  if (NULL!=handle->attr_idtoken_list)
595  if (NULL!=handle->attr_userinfo_list)
597  if (NULL!=handle->credentials)
599  if (NULL!=handle->presentations)
601  GNUNET_CONTAINER_DLL_remove (requests_head,
602  requests_tail,
603  handle);
604  GNUNET_free (handle);
605 }
606 
607 
613 static void
614 do_error (void *cls)
615 {
616  struct RequestHandle *handle = cls;
617  struct MHD_Response *resp;
618  char *json_error;
619 
620  GNUNET_asprintf (&json_error,
621  "{ \"error\" : \"%s\", \"error_description\" : \"%s\"%s%s%s}",
622  handle->emsg,
623  (NULL != handle->edesc) ? handle->edesc : "",
624  (NULL != handle->oidc->state) ? ", \"state\":\"" : "",
625  (NULL != handle->oidc->state) ? handle->oidc->state : "",
626  (NULL != handle->oidc->state) ? "\"" : "");
627  if (0 == handle->response_code)
628  handle->response_code = MHD_HTTP_BAD_REQUEST;
629  resp = GNUNET_REST_create_response (json_error);
630  if (MHD_HTTP_UNAUTHORIZED == handle->response_code)
631  MHD_add_response_header (resp, MHD_HTTP_HEADER_WWW_AUTHENTICATE, "Basic");
632  MHD_add_response_header (resp,
633  MHD_HTTP_HEADER_CONTENT_TYPE,
634  "application/json");
635  handle->proc (handle->proc_cls, resp, handle->response_code);
636  cleanup_handle (handle);
637  GNUNET_free (json_error);
638 }
639 
640 
647 static void
648 do_userinfo_error (void *cls)
649 {
650  struct RequestHandle *handle = cls;
651  struct MHD_Response *resp;
652  char *error;
653 
655  "Error: %s\n", handle->edesc);
656  GNUNET_asprintf (&error,
657  "error=\"%s\", error_description=\"%s\"",
658  handle->emsg,
659  (NULL != handle->edesc) ? handle->edesc : "");
660  resp = GNUNET_REST_create_response ("");
661  MHD_add_response_header (resp, MHD_HTTP_HEADER_WWW_AUTHENTICATE, "Bearer");
662  handle->proc (handle->proc_cls, resp, handle->response_code);
663  cleanup_handle (handle);
664  GNUNET_free (error);
665 }
666 
667 
673 static void
674 do_redirect_error (void *cls)
675 {
676  struct RequestHandle *handle = cls;
677  struct MHD_Response *resp;
678  char *redirect;
679 
680  GNUNET_asprintf (&redirect,
681  "%s?error=%s&error_description=%s%s%s",
682  handle->oidc->redirect_uri,
683  handle->emsg,
684  handle->edesc,
685  (NULL != handle->oidc->state) ? "&state=" : "",
686  (NULL != handle->oidc->state) ? handle->oidc->state : "");
687  resp = GNUNET_REST_create_response ("");
688  MHD_add_response_header (resp, "Location", redirect);
689  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
690  cleanup_handle (handle);
691  GNUNET_free (redirect);
692 }
693 
694 
700 static void
701 do_timeout (void *cls)
702 {
703  struct RequestHandle *handle = cls;
704 
705  handle->timeout_task = NULL;
706  do_error (handle);
707 }
708 
709 
717 static void
719  const char *url,
720  void *cls)
721 {
722  struct MHD_Response *resp;
723  struct RequestHandle *handle = cls;
724 
725  // For now, independent of path return all options
726  resp = GNUNET_REST_create_response (NULL);
727  MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
728  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
729  cleanup_handle (handle);
730  return;
731 }
732 
733 
737 static void
739 {
740  struct GNUNET_HashCode cache_key;
741  char *cookies;
742  struct GNUNET_TIME_Absolute current_time, *relog_time;
743  char delimiter[] = "; ";
744  char *tmp_cookies;
745  char *token;
746  char *value;
747 
748  // gets identity of login try with cookie
750  strlen (OIDC_COOKIE_HEADER_KEY),
751  &cache_key);
754  &cache_key))
755  {
756  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No cookie found\n");
757  return;
758  }
759  // splits cookies and find 'Identity' cookie
760  tmp_cookies =
762  &cache_key);
763  cookies = GNUNET_strdup (tmp_cookies);
764  token = strtok (cookies, delimiter);
765  handle->oidc->user_cancelled = GNUNET_NO;
766  handle->oidc->login_identity = NULL;
767  if (NULL == token)
768  {
770  "Unable to parse cookie: %s\n",
771  cookies);
772  GNUNET_free (cookies);
773  return;
774  }
775 
776  while (NULL != token)
777  {
778  if (0 == strcmp (token, OIDC_COOKIE_HEADER_ACCESS_DENIED))
779  {
780  handle->oidc->user_cancelled = GNUNET_YES;
781  GNUNET_free (cookies);
782  return;
783  }
784  if (NULL != strstr (token, OIDC_COOKIE_HEADER_INFORMATION_KEY))
785  break;
786  token = strtok (NULL, delimiter);
787  }
788  if (NULL == token)
789  {
791  "No cookie value to process: %s\n",
792  cookies);
793  GNUNET_free (cookies);
794  return;
795  }
796  GNUNET_CRYPTO_hash (token, strlen (token), &cache_key);
797  if (GNUNET_NO ==
798  GNUNET_CONTAINER_multihashmap_contains (OIDC_cookie_jar_map, &cache_key))
799  {
800  GNUNET_log (
802  "Found cookie `%s', but no corresponding expiration entry present...\n",
803  token);
804  GNUNET_free (cookies);
805  return;
806  }
807  relog_time =
808  GNUNET_CONTAINER_multihashmap_get (OIDC_cookie_jar_map, &cache_key);
809  current_time = GNUNET_TIME_absolute_get ();
810  // 30 min after old login -> redirect to login
811  if (current_time.abs_value_us > relog_time->abs_value_us)
812  {
814  "Found cookie `%s', but it is expired.\n",
815  token);
816  GNUNET_free (cookies);
817  return;
818  }
819  value = strtok (token, OIDC_COOKIE_HEADER_INFORMATION_KEY);
820  GNUNET_assert (NULL != value);
821  handle->oidc->login_identity = GNUNET_strdup (value);
822  GNUNET_free (cookies);
823 }
824 
825 
829 static void
830 login_redirect (void *cls)
831 {
832  char *login_base_url;
833  char *new_redirect;
834  char *tmp;
835  struct MHD_Response *resp;
836  struct GNUNET_Buffer buf = { 0 };
837  struct RequestHandle *handle = cls;
838 
840  "reclaim-rest-plugin",
841  "address",
842  &login_base_url))
843  {
844  GNUNET_buffer_write_str (&buf, login_base_url);
846  "?%s=%s",
848  handle->oidc->response_type);
850  "&%s=%s",
852  handle->oidc->client_id);
854  strlen (handle->oidc->redirect_uri),
855  &tmp);
857  "&%s=%s",
859  tmp);
860  GNUNET_free (tmp);
862  strlen (handle->oidc->scope),
863  &tmp);
865  "&%s=%s",
867  tmp);
868  GNUNET_free (tmp);
869  if (NULL != handle->oidc->state)
870  {
872  strlen (handle->oidc->state),
873  &tmp);
875  "&%s=%s",
877  handle->oidc->state);
878  GNUNET_free (tmp);
879  }
880  if (NULL != handle->oidc->code_challenge)
881  {
883  "&%s=%s",
885  handle->oidc->code_challenge);
886  }
887  if (NULL != handle->oidc->nonce)
888  {
890  "&%s=%s",
892  handle->oidc->nonce);
893  }
894  if (NULL != handle->oidc->claims)
895  {
897  strlen (handle->oidc->claims),
898  &tmp);
900  "&%s=%s",
902  tmp);
903  GNUNET_free (tmp);
904  }
905  new_redirect = GNUNET_buffer_reap_str (&buf);
906  resp = GNUNET_REST_create_response ("");
907  MHD_add_response_header (resp, "Location", new_redirect);
908  GNUNET_free (login_base_url);
909  }
910  else
911  {
913  handle->edesc = GNUNET_strdup ("gnunet configuration failed");
914  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
916  return;
917  }
918  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
919  GNUNET_free (new_redirect);
920  cleanup_handle (handle);
921 }
922 
923 
927 static void
929 {
930  struct RequestHandle *handle = cls;
931 
933  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
935 }
936 
937 
942 static void
944  const struct GNUNET_RECLAIM_Ticket *ticket,
945  const struct GNUNET_RECLAIM_PresentationList *pres)
946 {
947  struct RequestHandle *handle = cls;
948  struct MHD_Response *resp;
949  char *ticket_str;
950  char *redirect_uri;
951  char *code_string;
952 
953  handle->idp_op = NULL;
954  if (NULL == ticket)
955  {
957  handle->edesc = GNUNET_strdup ("Server cannot generate ticket.");
959  return;
960  }
961  handle->ticket = *ticket;
962  ticket_str =
964  sizeof(struct GNUNET_RECLAIM_Ticket));
965  code_string = OIDC_build_authz_code (&handle->priv_key,
966  &handle->ticket,
967  handle->attr_idtoken_list,
968  pres,
969  handle->oidc->nonce,
970  handle->oidc->code_challenge);
971  if ((NULL != handle->redirect_prefix) && (NULL != handle->redirect_suffix) &&
972  (NULL != handle->tld))
973  {
974  GNUNET_asprintf (&redirect_uri,
975  "%s.%s/%s?%s=%s&state=%s",
976  handle->redirect_prefix,
977  handle->tld,
978  handle->redirect_suffix,
979  (NULL == strchr (handle->redirect_suffix, '?') ? "?" :
980  "&"),
981  handle->oidc->response_type,
982  code_string,
983  handle->oidc->state);
984  }
985  else
986  {
987  GNUNET_asprintf (&redirect_uri,
988  "%s%s%s=%s&state=%s",
989  handle->oidc->redirect_uri,
990  (NULL == strchr (handle->oidc->redirect_uri, '?') ? "?" :
991  "&"),
992  handle->oidc->response_type,
993  code_string,
994  handle->oidc->state);
995  }
996  resp = GNUNET_REST_create_response ("");
997  MHD_add_response_header (resp, "Location", redirect_uri);
998  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
999  cleanup_handle (handle);
1000  GNUNET_free (redirect_uri);
1001  GNUNET_free (ticket_str);
1002  GNUNET_free (code_string);
1003 }
1004 
1005 
1006 static struct GNUNET_RECLAIM_AttributeList*
1008  struct GNUNET_RECLAIM_AttributeList *list_b)
1009 {
1010  struct GNUNET_RECLAIM_AttributeList *merged_list;
1011  struct GNUNET_RECLAIM_AttributeListEntry *le_a;
1012  struct GNUNET_RECLAIM_AttributeListEntry *le_b;
1013  struct GNUNET_RECLAIM_AttributeListEntry *le_m;
1014 
1015  merged_list = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
1016  for (le_a = list_a->list_head; NULL != le_a; le_a = le_a->next)
1017  {
1020  &le_a->attribute->
1021  credential,
1022  le_a->attribute->type,
1023  le_a->attribute->data,
1024  le_a->attribute->data_size);
1025  le_m->attribute->id = le_a->attribute->id;
1026  le_m->attribute->flag = le_a->attribute->flag;
1027  le_m->attribute->credential = le_a->attribute->credential;
1028  GNUNET_CONTAINER_DLL_insert (merged_list->list_head,
1029  merged_list->list_tail,
1030  le_m);
1031  }
1032  le_m = NULL;
1033  for (le_b = list_b->list_head; NULL != le_b; le_b = le_b->next)
1034  {
1035  for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1036  {
1038  &le_b->attribute->id))
1039  break;
1040  }
1041  if (NULL != le_m)
1042  continue;
1045  &le_b->attribute->
1046  credential,
1047  le_b->attribute->type,
1048  le_b->attribute->data,
1049  le_b->attribute->data_size);
1050  le_m->attribute->id = le_b->attribute->id;
1051  le_m->attribute->flag = le_b->attribute->flag;
1052  le_m->attribute->credential = le_b->attribute->credential;
1053  GNUNET_CONTAINER_DLL_insert (merged_list->list_head,
1054  merged_list->list_tail,
1055  le_m);
1056  }
1057  return merged_list;
1058 }
1059 
1060 
1061 static void
1063 {
1064  struct RequestHandle *handle = cls;
1065  struct GNUNET_RECLAIM_AttributeList *merged_list;
1066  struct GNUNET_RECLAIM_AttributeListEntry *le_m;
1067 
1068  handle->cred_it = NULL;
1069  merged_list = attribute_list_merge (handle->attr_idtoken_list,
1070  handle->attr_userinfo_list);
1071  for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next)
1073  "List Attibute in ticket to issue: %s\n",
1074  le_m->attribute->name);
1075  handle->idp_op = GNUNET_RECLAIM_ticket_issue (idp,
1076  &handle->priv_key,
1077  &handle->oidc->client_pkey,
1078  merged_list,
1080  handle);
1082 }
1083 
1084 
1088 static void
1090  const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
1091  const struct GNUNET_RECLAIM_Credential *cred)
1092 {
1093  struct RequestHandle *handle = cls;
1096 
1097  for (ale = handle->credentials->list_head; NULL != ale; ale = ale->next)
1098  {
1100  &cred->id))
1101  continue;
1104  return;
1105  }
1106 
1107  for (le = handle->attr_idtoken_list->list_head; NULL != le; le = le->next)
1108  {
1110  &cred->id))
1111  continue;
1115  cred->type,
1116  cred->data,
1117  cred->data_size);
1119  handle->credentials->list_tail,
1120  ale);
1121  }
1123 }
1124 
1125 
1126 static void
1128 {
1129  struct RequestHandle *handle = cls;
1130 
1131  handle->attr_it = NULL;
1132  handle->ticket_it = NULL;
1133  if (NULL == handle->attr_idtoken_list->list_head)
1134  {
1136  handle->edesc = GNUNET_strdup ("The requested scope is not available.");
1138  return;
1139  }
1141  handle->cred_it =
1143  &handle->priv_key,
1145  handle,
1147  handle,
1149  handle);
1150 
1151 }
1152 
1153 
1154 static int
1156  const char *attr_name,
1157  const char *claims_parameter)
1158 {
1159  int ret = GNUNET_NO;
1160  json_t *root;
1161  json_error_t error;
1162  json_t *claims_j;
1163  const char *key;
1164  json_t *value;
1165 
1168  attr_name))
1169  return GNUNET_YES;
1170 
1172  if ((NULL != handle->oidc->claims) &&
1173  (GNUNET_YES != ret))
1174  {
1175  root = json_loads (handle->oidc->claims, JSON_DECODE_ANY, &error);
1176  claims_j = json_object_get (root, claims_parameter);
1177  /* obj is a JSON object */
1178  if (NULL != claims_j)
1179  {
1180  json_object_foreach (claims_j, key, value) {
1181  if (0 != strcmp (attr_name, key))
1182  continue;
1183  ret = GNUNET_YES;
1184  break;
1185  }
1186  }
1187  json_decref (root);
1188  }
1189  return ret;
1190 }
1191 
1192 
1193 static int
1195  const char *attr_name)
1196 {
1197  return attr_in_claims_request (handle, attr_name, "id_token");
1198 }
1199 
1200 
1201 static int
1203  const char *attr_name)
1204 {
1205  return attr_in_claims_request (handle, attr_name, "userinfo");
1206 }
1207 
1208 
1212 static void
1214  const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
1215  const struct GNUNET_RECLAIM_Attribute *attr)
1216 {
1217  struct RequestHandle *handle = cls;
1219  if (GNUNET_YES == attr_in_idtoken_request (handle, attr->name))
1220  {
1223  &attr->credential,
1224  attr->type,
1225  attr->data,
1226  attr->data_size);
1227  le->attribute->id = attr->id;
1228  le->attribute->flag = attr->flag;
1229  le->attribute->credential = attr->credential;
1231  handle->attr_idtoken_list->list_tail,
1232  le);
1233  }
1234  if (GNUNET_YES == attr_in_userinfo_request (handle, attr->name))
1235  {
1238  &attr->credential,
1239  attr->type,
1240  attr->data,
1241  attr->data_size);
1242  le->attribute->id = attr->id;
1243  le->attribute->flag = attr->flag;
1244  le->attribute->credential = attr->credential;
1246  handle->attr_userinfo_list->list_tail,
1247  le);
1248  }
1249 
1251 }
1252 
1253 
1257 static void
1258 code_redirect (void *cls)
1259 {
1260  struct RequestHandle *handle = cls;
1261  struct GNUNET_TIME_Absolute current_time;
1262  struct GNUNET_TIME_Absolute *relog_time;
1263  struct GNUNET_CRYPTO_EcdsaPublicKey pubkey;
1264  struct GNUNET_CRYPTO_EcdsaPublicKey ego_pkey;
1265  struct GNUNET_HashCode cache_key;
1266  char *identity_cookie;
1267 
1268  GNUNET_asprintf (&identity_cookie,
1269  "Identity=%s",
1270  handle->oidc->login_identity);
1271  GNUNET_CRYPTO_hash (identity_cookie, strlen (identity_cookie), &cache_key);
1272  GNUNET_free (identity_cookie);
1273  // No login time for identity -> redirect to login
1274  if (GNUNET_YES ==
1275  GNUNET_CONTAINER_multihashmap_contains (OIDC_cookie_jar_map, &cache_key))
1276  {
1277  relog_time =
1278  GNUNET_CONTAINER_multihashmap_get (OIDC_cookie_jar_map, &cache_key);
1279  current_time = GNUNET_TIME_absolute_get ();
1280  // 30 min after old login -> redirect to login
1281  if (current_time.abs_value_us <= relog_time->abs_value_us)
1282  {
1283  if (GNUNET_OK !=
1285  ->login_identity,
1286  strlen (
1287  handle->oidc
1288  ->login_identity),
1289  &pubkey))
1290  {
1292  handle->edesc =
1293  GNUNET_strdup ("The cookie of a login identity is not valid");
1295  return;
1296  }
1297  // iterate over egos and compare their public key
1298  for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
1299  handle->ego_entry = handle->ego_entry->next)
1300  {
1301  GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey);
1302  if (0 == GNUNET_memcmp (&ego_pkey, &pubkey))
1303  {
1304  handle->priv_key =
1306  handle->attr_idtoken_list =
1308  handle->attr_userinfo_list =
1310  handle->attr_it =
1312  &handle->priv_key,
1314  handle,
1316  handle,
1318  handle);
1319  return;
1320  }
1321  }
1323  return;
1324  }
1325  }
1326 }
1327 
1328 
1329 static void
1330 build_redirect (void *cls)
1331 {
1332  struct RequestHandle *handle = cls;
1333  struct MHD_Response *resp;
1334  char *redirect_uri;
1335 
1336  if (GNUNET_YES == handle->oidc->user_cancelled)
1337  {
1338  if ((NULL != handle->redirect_prefix) &&
1339  (NULL != handle->redirect_suffix) && (NULL != handle->tld))
1340  {
1341  GNUNET_asprintf (&redirect_uri,
1342  "%s.%s/%s?error=%s&error_description=%s&state=%s",
1343  handle->redirect_prefix,
1344  handle->tld,
1345  handle->redirect_suffix,
1346  "access_denied",
1347  "User denied access",
1348  handle->oidc->state);
1349  }
1350  else
1351  {
1352  GNUNET_asprintf (&redirect_uri,
1353  "%s?error=%s&error_description=%s&state=%s",
1354  handle->oidc->redirect_uri,
1355  "access_denied",
1356  "User denied access",
1357  handle->oidc->state);
1358  }
1359  resp = GNUNET_REST_create_response ("");
1360  MHD_add_response_header (resp, "Location", redirect_uri);
1361  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1362  cleanup_handle (handle);
1363  GNUNET_free (redirect_uri);
1364  return;
1365  }
1367 }
1368 
1369 
1370 static void
1372  uint32_t rd_count,
1373  const struct GNUNET_GNSRECORD_Data *rd)
1374 {
1375  struct RequestHandle *handle = cls;
1376  char *tmp;
1377  char *tmp_key_str;
1378  char *pos;
1379  struct GNUNET_CRYPTO_EcdsaPublicKey redirect_zone;
1380 
1381  handle->gns_op = NULL;
1382  if (0 == rd_count)
1383  {
1385  handle->edesc =
1386  GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1388  return;
1389  }
1390  for (int i = 0; i < rd_count; i++)
1391  {
1392  if (GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT != rd[i].record_type)
1393  continue;
1394  if (0 != strncmp (rd[i].data, handle->oidc->redirect_uri, rd[i].data_size))
1395  continue;
1396  tmp = GNUNET_strndup (rd[i].data, rd[i].data_size);
1397  if (NULL == strstr (tmp, handle->oidc->client_id))
1398  {
1400  "Redirect uri %s does not contain client_id %s\n",
1401  tmp,
1402  handle->oidc->client_id);
1403  }
1404  else
1405  {
1406  pos = strrchr (tmp, (unsigned char) '.');
1407  if (NULL == pos)
1408  {
1410  "Redirect uri %s contains client_id but is malformed\n",
1411  tmp);
1412  GNUNET_free (tmp);
1413  continue;
1414  }
1415  *pos = '\0';
1416  handle->redirect_prefix = GNUNET_strdup (tmp);
1417  tmp_key_str = pos + 1;
1418  pos = strchr (tmp_key_str, (unsigned char) '/');
1419  if (NULL == pos)
1420  {
1422  "Redirect uri %s contains client_id but is malformed\n",
1423  tmp);
1424  GNUNET_free (tmp);
1425  continue;
1426  }
1427  *pos = '\0';
1428  handle->redirect_suffix = GNUNET_strdup (pos + 1);
1429 
1430  GNUNET_STRINGS_string_to_data (tmp_key_str,
1431  strlen (tmp_key_str),
1432  &redirect_zone,
1433  sizeof(redirect_zone));
1434  }
1436  GNUNET_free (tmp);
1437  return;
1438  }
1440  handle->edesc =
1441  GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1443 }
1444 
1445 
1449 static void
1450 client_redirect (void *cls)
1451 {
1452  struct RequestHandle *handle = cls;
1453 
1454  /* Lookup client redirect uri to verify request */
1455  handle->gns_op =
1456  GNUNET_GNS_lookup (gns_handle,
1458  &handle->oidc->client_pkey,
1462  handle);
1463 }
1464 
1465 
1466 static char *
1467 get_url_parameter_copy (const struct RequestHandle *handle, const char *key)
1468 {
1469  struct GNUNET_HashCode hc;
1470  char *value;
1471  char *res;
1472 
1473  GNUNET_CRYPTO_hash (key, strlen (key), &hc);
1475  ->url_param_map,
1476  &hc))
1477  return NULL;
1478  value =
1480  if (NULL == value)
1481  return NULL;
1482  GNUNET_STRINGS_urldecode (value, strlen (value), &res);
1483  return res;
1484 }
1485 
1486 
1493 static void
1495 {
1496  struct RequestHandle *handle = cls;
1497  struct GNUNET_HashCode cache_key;
1498 
1499  char *expected_scope;
1500  char delimiter[] = " ";
1501  int number_of_ignored_parameter, iterator;
1502 
1503 
1504  // REQUIRED value: redirect_uri
1505  handle->oidc->redirect_uri =
1507  if (NULL == handle->oidc->redirect_uri)
1508  {
1510  handle->edesc = GNUNET_strdup ("missing parameter redirect_uri");
1512  return;
1513  }
1514 
1515  // REQUIRED value: response_type
1516  handle->oidc->response_type =
1518  if (NULL == handle->oidc->response_type)
1519  {
1521  handle->edesc = GNUNET_strdup ("missing parameter response_type");
1523  return;
1524  }
1525 
1526  // REQUIRED value: scope
1527  handle->oidc->scope = get_url_parameter_copy (handle, OIDC_SCOPE_KEY);
1528  if (NULL == handle->oidc->scope)
1529  {
1531  handle->edesc = GNUNET_strdup ("missing parameter scope");
1533  return;
1534  }
1535 
1536  // OPTIONAL value: nonce
1537  handle->oidc->nonce = get_url_parameter_copy (handle, OIDC_NONCE_KEY);
1538 
1539  // OPTIONAL value: claims
1540  handle->oidc->claims = get_url_parameter_copy (handle, OIDC_CLAIMS_KEY);
1541 
1542  // TODO check other values if needed
1543  number_of_ignored_parameter =
1544  sizeof(OIDC_ignored_parameter_array) / sizeof(char *);
1545  for (iterator = 0; iterator < number_of_ignored_parameter; iterator++)
1546  {
1548  strlen (OIDC_ignored_parameter_array[iterator]),
1549  &cache_key);
1550  if (GNUNET_YES ==
1552  ->url_param_map,
1553  &cache_key))
1554  {
1556  GNUNET_asprintf (&handle->edesc,
1557  "Server will not handle parameter: %s",
1558  OIDC_ignored_parameter_array[iterator]);
1560  return;
1561  }
1562  }
1563 
1564  // We only support authorization code flows.
1565  if (0 != strcmp (handle->oidc->response_type,
1567  {
1569  handle->edesc = GNUNET_strdup ("The authorization server does not support "
1570  "obtaining this authorization code.");
1572  return;
1573  }
1574 
1575  // Checks if scope contains 'openid'
1576  expected_scope = GNUNET_strdup (handle->oidc->scope);
1577  char *test;
1578  test = strtok (expected_scope, delimiter);
1579  while (NULL != test)
1580  {
1581  if (0 == strcmp (OIDC_EXPECTED_AUTHORIZATION_SCOPE, expected_scope))
1582  break;
1583  test = strtok (NULL, delimiter);
1584  }
1585  if (NULL == test)
1586  {
1588  handle->edesc =
1589  GNUNET_strdup ("The requested scope is invalid, unknown, or malformed.");
1591  GNUNET_free (expected_scope);
1592  return;
1593  }
1594 
1595  GNUNET_free (expected_scope);
1596  if ((NULL == handle->oidc->login_identity) &&
1597  (GNUNET_NO == handle->oidc->user_cancelled))
1599  else
1601 }
1602 
1603 
1607 static void
1608 tld_iter (void *cls, const char *section, const char *option, const char *value)
1609 {
1610  struct RequestHandle *handle = cls;
1611  struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
1612 
1613  if (GNUNET_OK !=
1614  GNUNET_CRYPTO_ecdsa_public_key_from_string (value, strlen (value), &pkey))
1615  {
1616  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Skipping non key %s\n", value);
1617  return;
1618  }
1619  if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1620  handle->tld = GNUNET_strdup (option + 1);
1621 }
1622 
1623 
1631 static void
1633  const char *url,
1634  void *cls)
1635 {
1636  struct RequestHandle *handle = cls;
1637  struct EgoEntry *tmp_ego;
1638  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
1639  struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
1640 
1642 
1643  // RECOMMENDED value: state - REQUIRED for answers
1644  handle->oidc->state = get_url_parameter_copy (handle, OIDC_STATE_KEY);
1645 
1646  // REQUIRED value: client_id
1648  if (NULL == handle->oidc->client_id)
1649  {
1651  handle->edesc = GNUNET_strdup ("missing parameter client_id");
1652  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1654  return;
1655  }
1656 
1657  // OPTIONAL value: code_challenge
1658  handle->oidc->code_challenge = get_url_parameter_copy (handle,
1660  if (NULL == handle->oidc->code_challenge)
1661  {
1663  "OAuth authorization request does not contain PKCE parameters!\n");
1664  }
1665 
1666  if (GNUNET_OK !=
1668  strlen (
1669  handle->oidc->client_id),
1670  &handle->oidc->client_pkey))
1671  {
1673  handle->edesc = GNUNET_strdup ("The client is not authorized to request an "
1674  "authorization code using this method.");
1675  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1677  return;
1678  }
1679 
1680  // If we know this identity, translated the corresponding TLD
1681  // TODO: We might want to have a reverse lookup functionality for TLDs?
1682  for (tmp_ego = ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next)
1683  {
1684  priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego);
1685  GNUNET_CRYPTO_ecdsa_key_get_public (priv_key, &pkey);
1686  if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1687  {
1688  handle->tld = GNUNET_strdup (tmp_ego->identifier);
1689  handle->ego_entry = ego_tail;
1690  }
1691  }
1692  handle->oidc->scope = get_url_parameter_copy (handle, OIDC_SCOPE_KEY);
1693  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Scope: %s\n", handle->oidc->scope);
1694  if (NULL == handle->tld)
1696  if (NULL == handle->tld)
1697  handle->tld = GNUNET_strdup (handle->oidc->client_id);
1699 }
1700 
1701 
1709 static void
1711  const char *url,
1712  void *cls)
1713 {
1714  struct MHD_Response *resp = GNUNET_REST_create_response ("");
1715  struct RequestHandle *handle = cls;
1716  struct GNUNET_HashCode cache_key;
1717  struct GNUNET_TIME_Absolute *current_time;
1718  struct GNUNET_TIME_Absolute *last_time;
1719  char *cookie;
1720  char *header_val;
1721  json_t *root;
1722  json_error_t error;
1723  json_t *identity;
1724  char term_data[handle->rest_handle->data_size + 1];
1725 
1726  term_data[handle->rest_handle->data_size] = '\0';
1727  GNUNET_memcpy (term_data,
1728  handle->rest_handle->data,
1729  handle->rest_handle->data_size);
1730  root = json_loads (term_data, JSON_DECODE_ANY, &error);
1731  identity = json_object_get (root, "identity");
1732  if (! json_is_string (identity))
1733  {
1735  "Error parsing json string from %s\n",
1736  term_data);
1737  handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
1738  json_decref (root);
1739  cleanup_handle (handle);
1740  return;
1741  }
1742  GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity));
1743  GNUNET_asprintf (&header_val,
1744  "%s;Max-Age=%d",
1745  cookie,
1747  MHD_add_response_header (resp, "Set-Cookie", header_val);
1748  MHD_add_response_header (resp, "Access-Control-Allow-Methods", "POST");
1749  GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key);
1750 
1751  if (0 != strcmp (json_string_value (identity), "Denied"))
1752  {
1753  current_time = GNUNET_new (struct GNUNET_TIME_Absolute);
1754  *current_time = GNUNET_TIME_relative_to_absolute (
1757  last_time =
1758  GNUNET_CONTAINER_multihashmap_get (OIDC_cookie_jar_map, &cache_key);
1759  GNUNET_free (last_time);
1760  GNUNET_CONTAINER_multihashmap_put (OIDC_cookie_jar_map,
1761  &cache_key,
1762  current_time,
1764  }
1765  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1766  GNUNET_free (cookie);
1767  GNUNET_free (header_val);
1768  json_decref (root);
1769  cleanup_handle (handle);
1770 }
1771 
1772 
1773 static int
1775  char **client_id,
1776  char **client_secret)
1777 {
1778  struct GNUNET_HashCode cache_key;
1779  char *authorization;
1780  char *credentials;
1781  char *basic_authorization;
1782  char *client_id_tmp;
1783  char *pass;
1784 
1787  &cache_key);
1789  ->header_param_map,
1790  &cache_key))
1791  return GNUNET_SYSERR;
1792  authorization =
1794  &cache_key);
1795 
1796  // split header in "Basic" and [content]
1797  credentials = strtok (authorization, " ");
1798  if ((NULL == credentials) || (0 != strcmp ("Basic", credentials)))
1799  return GNUNET_SYSERR;
1800  credentials = strtok (NULL, " ");
1801  if (NULL == credentials)
1802  return GNUNET_SYSERR;
1803  GNUNET_STRINGS_base64_decode (credentials,
1804  strlen (credentials),
1805  (void **) &basic_authorization);
1806 
1807  if (NULL == basic_authorization)
1808  return GNUNET_SYSERR;
1809  client_id_tmp = strtok (basic_authorization, ":");
1810  if (NULL == client_id_tmp)
1811  {
1812  GNUNET_free (basic_authorization);
1813  return GNUNET_SYSERR;
1814  }
1815  pass = strtok (NULL, ":");
1816  if (NULL == pass)
1817  {
1818  GNUNET_free (basic_authorization);
1819  return GNUNET_SYSERR;
1820  }
1821  *client_id = strdup (client_id_tmp);
1822  *client_secret = strdup (pass);
1823  GNUNET_free (basic_authorization);
1824  return GNUNET_OK;
1825 }
1826 
1827 
1828 static int
1830  char **client_id,
1831  char **client_secret)
1832 {
1833  struct GNUNET_HashCode cache_key;
1834  char *client_id_tmp;
1835  char *pass;
1836 
1837  GNUNET_CRYPTO_hash ("client_id",
1838  strlen ("client_id"),
1839  &cache_key);
1841  ->url_param_map,
1842  &cache_key))
1843  return GNUNET_SYSERR;
1844  client_id_tmp = GNUNET_CONTAINER_multihashmap_get (
1845  handle->rest_handle->url_param_map,
1846  &cache_key);
1847  if (NULL == client_id_tmp)
1848  return GNUNET_SYSERR;
1849  *client_id = strdup (client_id_tmp);
1850  GNUNET_CRYPTO_hash ("client_secret",
1851  strlen ("client_secret"),
1852  &cache_key);
1854  ->url_param_map,
1855  &cache_key))
1856  return GNUNET_SYSERR;
1858  &cache_key);
1859  if (NULL == pass)
1860  return GNUNET_SYSERR;
1861  *client_secret = strdup (pass);
1862  return GNUNET_OK;
1863 }
1864 
1865 
1866 static int
1868  struct GNUNET_CRYPTO_EcdsaPublicKey *cid)
1869 {
1870  char *expected_pass;
1871  char *received_cid;
1872  char *received_cpw;
1873  char *pkce_cv;
1874 
1875  if (GNUNET_OK == parse_credentials_basic_auth (handle,
1876  &received_cid,
1877  &received_cpw))
1878  {
1880  "Received client credentials in HTTP AuthZ header\n");
1881  }
1882  else if (GNUNET_OK == parse_credentials_post_body (handle,
1883  &received_cid,
1884  &received_cpw))
1885  {
1887  "Received client credentials in POST body\n");
1888  }
1889  else
1890  {
1892  pkce_cv = get_url_parameter_copy (handle, OIDC_CODE_VERIFIER_KEY);
1893  if (NULL == pkce_cv)
1894  {
1896  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1897  return GNUNET_SYSERR;
1898  }
1899  handle->public_client = GNUNET_YES;
1900  GNUNET_free (pkce_cv);
1901  received_cid = get_url_parameter_copy (handle, OIDC_CLIENT_ID_KEY);
1902  GNUNET_STRINGS_string_to_data (received_cid,
1903  strlen (received_cid),
1904  cid,
1905  sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey));
1906  GNUNET_free (received_cid);
1907  return GNUNET_OK;
1908 
1909  }
1910 
1911  // check client password
1913  "reclaim-rest-plugin",
1914  "OIDC_CLIENT_SECRET",
1915  &expected_pass))
1916  {
1917  if (0 != strcmp (expected_pass, received_cpw))
1918  {
1919  GNUNET_free (expected_pass);
1921  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1922  return GNUNET_SYSERR;
1923  }
1924  GNUNET_free (expected_pass);
1925  }
1926  else
1927  {
1929  handle->edesc = GNUNET_strdup ("gnunet configuration failed");
1930  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1931  return GNUNET_SYSERR;
1932  }
1933  // check client_id
1934  for (handle->ego_entry = ego_head; NULL != handle->ego_entry;
1935  handle->ego_entry = handle->ego_entry->next)
1936  {
1937  if (0 == strcmp (handle->ego_entry->keystring, received_cid))
1938  break;
1939  }
1940  if (NULL == handle->ego_entry)
1941  {
1942  GNUNET_free (received_cpw);
1943  GNUNET_free (received_cid);
1945  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1946  return GNUNET_SYSERR;
1947  }
1948  GNUNET_STRINGS_string_to_data (received_cid,
1949  strlen (received_cid),
1950  cid,
1951  sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey));
1952 
1953  GNUNET_free (received_cpw);
1954  GNUNET_free (received_cid);
1955  return GNUNET_OK;
1956 }
1957 
1958 
1959 const struct EgoEntry *
1961  struct GNUNET_CRYPTO_EcdsaPublicKey *test_key)
1962 {
1963  struct EgoEntry *ego_entry;
1964  struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
1965 
1966  for (ego_entry = ego_head; NULL != ego_entry;
1967  ego_entry = ego_entry->next)
1968  {
1969  GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key);
1970  if (0 == GNUNET_memcmp (&pub_key, test_key))
1971  return ego_entry;
1972  }
1973  return NULL;
1974 }
1975 
1976 
1984 static void
1986  const char *url,
1987  void *cls)
1988 {
1989  struct RequestHandle *handle = cls;
1990  const struct EgoEntry *ego_entry;
1991  struct GNUNET_TIME_Relative expiration_time;
1992  struct GNUNET_RECLAIM_AttributeList *cl = NULL;
1993  struct GNUNET_RECLAIM_PresentationList *pl = NULL;
1994  struct GNUNET_RECLAIM_Ticket ticket;
1995  struct GNUNET_CRYPTO_EcdsaPublicKey cid;
1996  struct GNUNET_HashCode cache_key;
1997  struct MHD_Response *resp;
1998  char *grant_type;
1999  char *code;
2000  char *json_response;
2001  char *id_token;
2002  char *access_token;
2003  char *jwt_secret;
2004  char *nonce;
2005  char *code_verifier;
2006 
2007  /*
2008  * Check Authorization
2009  */
2010  if (GNUNET_SYSERR == check_authorization (handle, &cid))
2011  {
2013  "OIDC authorization for token endpoint failed\n");
2015  return;
2016  }
2017 
2018  /*
2019  * Check parameter
2020  */
2021 
2022  // TODO Do not allow multiple equal parameter names
2023  // REQUIRED grant_type
2025  strlen (OIDC_GRANT_TYPE_KEY),
2026  &cache_key);
2027  grant_type = get_url_parameter_copy (handle, OIDC_GRANT_TYPE_KEY);
2028  if (NULL == grant_type)
2029  {
2031  handle->edesc = GNUNET_strdup ("missing parameter grant_type");
2032  handle->response_code = MHD_HTTP_BAD_REQUEST;
2034  return;
2035  }
2036 
2037  // Check parameter grant_type == "authorization_code"
2038  if (0 != strcmp (OIDC_GRANT_TYPE_VALUE, grant_type))
2039  {
2041  handle->response_code = MHD_HTTP_BAD_REQUEST;
2042  GNUNET_free (grant_type);
2044  return;
2045  }
2046  GNUNET_free (grant_type);
2047  // REQUIRED code
2048  code = get_url_parameter_copy (handle, OIDC_CODE_KEY);
2049  if (NULL == code)
2050  {
2052  handle->edesc = GNUNET_strdup ("missing parameter code");
2053  handle->response_code = MHD_HTTP_BAD_REQUEST;
2055  return;
2056  }
2057  ego_entry = find_ego (handle, &cid);
2058  if (NULL == ego_entry)
2059  {
2061  handle->edesc = GNUNET_strdup ("Unknown client");
2062  handle->response_code = MHD_HTTP_BAD_REQUEST;
2063  GNUNET_free (code);
2065  return;
2066  }
2067 
2068  // REQUIRED code verifier
2069  code_verifier = get_url_parameter_copy (handle, OIDC_CODE_VERIFIER_KEY);
2070  if (NULL == code_verifier)
2071  {
2073  "OAuth authorization request does not contain PKCE parameters!\n");
2074 
2075  }
2076 
2077  // decode code
2078  if (GNUNET_OK != OIDC_parse_authz_code (&cid, code, code_verifier, &ticket,
2079  &cl, &pl, &nonce))
2080  {
2082  handle->edesc = GNUNET_strdup ("invalid code");
2083  handle->response_code = MHD_HTTP_BAD_REQUEST;
2084  GNUNET_free (code);
2086  return;
2087  }
2088  GNUNET_free (code);
2089 
2090  // create jwt
2092  "reclaim-rest-plugin",
2093  "expiration_time",
2094  &expiration_time))
2095  {
2097  handle->edesc = GNUNET_strdup ("gnunet configuration failed");
2098  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2100  return;
2101  }
2102 
2103 
2104  // TODO OPTIONAL acr,amr,azp
2106  "reclaim-rest-plugin",
2107  "jwt_secret",
2108  &jwt_secret))
2109  {
2111  handle->edesc = GNUNET_strdup ("No signing secret configured!");
2112  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2114  return;
2115  }
2116  id_token = OIDC_generate_id_token (&ticket.audience,
2117  &ticket.identity,
2118  cl,
2119  pl,
2120  &expiration_time,
2121  (NULL != nonce) ? nonce : NULL,
2122  jwt_secret);
2123  access_token = OIDC_access_token_new (&ticket);
2124  OIDC_build_token_response (access_token,
2125  id_token,
2126  &expiration_time,
2127  &json_response);
2128 
2129  resp = GNUNET_REST_create_response (json_response);
2130  MHD_add_response_header (resp, "Cache-Control", "no-store");
2131  MHD_add_response_header (resp, "Pragma", "no-cache");
2132  MHD_add_response_header (resp, "Content-Type", "application/json");
2133  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2136  GNUNET_free (access_token);
2137  GNUNET_free (json_response);
2138  GNUNET_free (id_token);
2139  cleanup_handle (handle);
2140 }
2141 
2142 
2146 static void
2147 consume_ticket (void *cls,
2148  const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
2149  const struct GNUNET_RECLAIM_Attribute *attr,
2150  const struct GNUNET_RECLAIM_Presentation *pres)
2151 {
2152  struct RequestHandle *handle = cls;
2155  struct MHD_Response *resp;
2156  char *result_str;
2157  handle->idp_op = NULL;
2158 
2159  if (NULL == identity)
2160  {
2161  result_str = OIDC_generate_userinfo (&handle->ticket.identity,
2162  handle->attr_userinfo_list,
2163  handle->presentations);
2164  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Userinfo: %s\n", result_str);
2165  resp = GNUNET_REST_create_response (result_str);
2166  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2167  GNUNET_free (result_str);
2168  cleanup_handle (handle);
2169  return;
2170  }
2173  &attr->credential,
2174  attr->type,
2175  attr->data,
2176  attr->data_size);
2177  ale->attribute->id = attr->id;
2178  ale->attribute->flag = attr->flag;
2179  ale->attribute->credential = attr->credential;
2181  handle->attr_userinfo_list->list_tail,
2182  ale);
2183  if (NULL == pres)
2184  return;
2185  for (atle = handle->presentations->list_head;
2186  NULL != atle; atle = atle->next)
2187  {
2189  &pres->credential_id))
2190  continue;
2191  break;
2192  }
2193  if (NULL == atle)
2194  {
2198  pres->data,
2199  pres->data_size);
2201  handle->presentations->list_tail,
2202  atle);
2203  }
2204 }
2205 
2206 
2214 static void
2216  const char *url,
2217  void *cls)
2218 {
2219  // TODO expiration time
2220  struct RequestHandle *handle = cls;
2221  struct GNUNET_RECLAIM_Ticket *ticket;
2222  char delimiter[] = " ";
2223  struct GNUNET_HashCode cache_key;
2224  char *authorization;
2225  char *authorization_type;
2226  char *authorization_access_token;
2227  const struct EgoEntry *aud_ego;
2228  const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
2229 
2230  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Getting userinfo\n");
2233  &cache_key);
2235  ->header_param_map,
2236  &cache_key))
2237  {
2239  handle->edesc = GNUNET_strdup ("No Access Token");
2240  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2242  return;
2243  }
2244  authorization =
2246  &cache_key);
2247 
2248  // split header in "Bearer" and access_token
2249  authorization = GNUNET_strdup (authorization);
2250  authorization_type = strtok (authorization, delimiter);
2251  if ((NULL == authorization_type) ||
2252  (0 != strcmp ("Bearer", authorization_type)))
2253  {
2255  handle->edesc = GNUNET_strdup ("No Access Token");
2256  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2258  GNUNET_free (authorization);
2259  return;
2260  }
2261  authorization_access_token = strtok (NULL, delimiter);
2262  if (NULL == authorization_access_token)
2263  {
2265  handle->edesc = GNUNET_strdup ("Access token missing");
2266  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2268  GNUNET_free (authorization);
2269  return;
2270  }
2271 
2272  if (GNUNET_OK != OIDC_access_token_parse (authorization_access_token,
2273  &ticket))
2274  {
2276  handle->edesc = GNUNET_strdup ("The access token is invalid");
2277  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2279  GNUNET_free (authorization);
2280  return;
2281 
2282  }
2283  GNUNET_assert (NULL != ticket);
2284  handle->ticket = *ticket;
2285  GNUNET_free (ticket);
2286  aud_ego = find_ego (handle, &handle->ticket.audience);
2287  if (NULL == aud_ego)
2288  {
2290  handle->edesc = GNUNET_strdup ("The access token expired");
2291  handle->response_code = MHD_HTTP_UNAUTHORIZED;
2293  GNUNET_free (authorization);
2294  return;
2295  }
2296  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Consuming ticket\n");
2297  privkey = GNUNET_IDENTITY_ego_get_private_key (aud_ego->ego);
2298  handle->attr_userinfo_list =
2300  handle->presentations =
2302 
2303  handle->idp_op = GNUNET_RECLAIM_ticket_consume (idp,
2304  privkey,
2305  &handle->ticket,
2306  &consume_ticket,
2307  handle);
2308  GNUNET_free (authorization);
2309 }
2310 
2311 
2345 static void
2346 list_ego (void *cls,
2347  struct GNUNET_IDENTITY_Ego *ego,
2348  void **ctx,
2349  const char *identifier)
2350 {
2351  struct EgoEntry *ego_entry;
2352  struct GNUNET_CRYPTO_EcdsaPublicKey pk;
2353 
2354  if ((NULL == ego) && (ID_REST_STATE_INIT == state))
2355  {
2357  return;
2358  }
2359  GNUNET_assert (NULL != ego);
2360  if (ID_REST_STATE_INIT == state)
2361 
2362  {
2363  ego_entry = GNUNET_new (struct EgoEntry);
2366  ego_entry->ego = ego;
2367  ego_entry->identifier = GNUNET_strdup (identifier);
2369  ego_tail,
2370  ego_entry);
2371  return;
2372  }
2373  /* Ego renamed or added */
2374  if (identifier != NULL)
2375  {
2376  for (ego_entry = ego_head; NULL != ego_entry;
2377  ego_entry = ego_entry->next)
2378  {
2379  if (ego_entry->ego == ego)
2380  {
2381  /* Rename */
2382  GNUNET_free (ego_entry->identifier);
2383  ego_entry->identifier = GNUNET_strdup (identifier);
2384  break;
2385  }
2386  }
2387  if (NULL == ego_entry)
2388  {
2389  /* Add */
2390  ego_entry = GNUNET_new (struct EgoEntry);
2393  ego_entry->ego = ego;
2394  ego_entry->identifier = GNUNET_strdup (identifier);
2396  ego_tail,
2397  ego_entry);
2398  }
2399  }
2400  else
2401  {
2402  /* Delete */
2403  for (ego_entry = ego_head; NULL != ego_entry;
2404  ego_entry = ego_entry->next)
2405  {
2406  if (ego_entry->ego == ego)
2407  break;
2408  }
2409  if (NULL == ego_entry)
2410  return; /* Not found */
2411 
2412  GNUNET_CONTAINER_DLL_remove (ego_head,
2413  ego_tail,
2414  ego_entry);
2415  GNUNET_free (ego_entry->identifier);
2416  GNUNET_free (ego_entry->keystring);
2417  GNUNET_free (ego_entry);
2418  return;
2419  }
2420 }
2421 
2422 
2423 static void
2425  const char *url,
2426  void *cls)
2427 {
2428  json_t *oidc_config;
2429  json_t *auth_methods;
2430  json_t *sig_algs;
2431  json_t *scopes;
2432  json_t *response_types;
2433  json_t *sub_types;
2434  json_t *claim_types;
2435  char *oidc_config_str;
2436  struct MHD_Response *resp;
2437  struct RequestHandle *handle = cls;
2438 
2439  oidc_config = json_object ();
2440  // FIXME get from config?
2441  json_object_set_new (oidc_config,
2442  "issuer", json_string ("http://localhost:7776"));
2443  json_object_set_new (oidc_config,
2444  "authorization_endpoint",
2445  json_string ("https://api.reclaim/openid/authorize"));
2446  json_object_set_new (oidc_config,
2447  "token_endpoint",
2448  json_string ("http://localhost:7776/openid/token"));
2449  auth_methods = json_array ();
2450  json_array_append_new (auth_methods,
2451  json_string ("client_secret_basic"));
2452  json_array_append_new (auth_methods,
2453  json_string ("client_secret_post"));
2454  json_object_set_new (oidc_config,
2455  "token_endpoint_auth_methods_supported",
2456  auth_methods);
2457  sig_algs = json_array ();
2458  json_array_append_new (sig_algs,
2459  json_string ("HS512"));
2460  json_object_set_new (oidc_config,
2461  "id_token_signing_alg_values_supported",
2462  sig_algs);
2463  json_object_set_new (oidc_config,
2464  "userinfo_endpoint",
2465  json_string ("http://localhost:7776/openid/userinfo"));
2466  scopes = json_array ();
2467  json_array_append_new (scopes,
2468  json_string ("openid"));
2469  json_array_append_new (scopes,
2470  json_string ("profile"));
2471  json_array_append_new (scopes,
2472  json_string ("email"));
2473  json_array_append_new (scopes,
2474  json_string ("address"));
2475  json_array_append_new (scopes,
2476  json_string ("phone"));
2477  json_object_set_new (oidc_config,
2478  "scopes_supported",
2479  scopes);
2480  response_types = json_array ();
2481  json_array_append_new (response_types,
2482  json_string ("code"));
2483  json_object_set_new (oidc_config,
2484  "response_types_supported",
2485  response_types);
2486  sub_types = json_array ();
2487  json_array_append_new (sub_types,
2488  json_string ("public")); /* no pairwise suppport */
2489  json_object_set_new (oidc_config,
2490  "subject_types_supported",
2491  sub_types);
2492  claim_types = json_array ();
2493  json_array_append_new (claim_types,
2494  json_string ("normal"));
2495  json_array_append_new (claim_types,
2496  json_string ("aggregated"));
2497  json_object_set_new (oidc_config,
2498  "claim_types_supported",
2499  claim_types);
2500  json_object_set_new (oidc_config,
2501  "claims_parameter_supported",
2502  json_boolean (1));
2503  oidc_config_str = json_dumps (oidc_config, JSON_INDENT (1));
2504  resp = GNUNET_REST_create_response (oidc_config_str);
2505  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2506  GNUNET_free (oidc_config_str);
2507  cleanup_handle (handle);
2508 }
2509 
2510 
2518 static void
2520  const char *url,
2521  void *cls)
2522 {
2523  struct MHD_Response *resp;
2524  struct RequestHandle *handle = cls;
2525 
2526  // For now, independent of path return all options
2527  resp = GNUNET_REST_create_response (NULL);
2528  MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
2529  MHD_add_response_header (resp, "Access-Control-Allow-Origin", "*");
2530  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2531  cleanup_handle (handle);
2532  return;
2533 }
2534 
2535 
2536 static enum GNUNET_GenericReturnValue
2539  void *proc_cls)
2540 {
2541  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
2543  static const struct GNUNET_REST_RequestHandler handlers[] =
2544  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint },
2545  { MHD_HTTP_METHOD_POST,
2546  GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint }, // url-encoded
2547  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont },
2548  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
2549  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
2550  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
2551  { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_OIDC_CONFIG,
2553  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC_CONFIG,
2554  &oidc_config_cors },
2555  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont },
2557 
2558  handle->oidc = GNUNET_new (struct OIDC_Variables);
2559  if (NULL == OIDC_cookie_jar_map)
2560  OIDC_cookie_jar_map = GNUNET_CONTAINER_multihashmap_create (10,
2561  GNUNET_NO);
2562  handle->response_code = 0;
2564  handle->proc_cls = proc_cls;
2565  handle->proc = proc;
2566  handle->rest_handle = rest_handle;
2567  handle->url = GNUNET_strdup (rest_handle->url);
2568  handle->timeout_task =
2569  GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
2570  GNUNET_CONTAINER_DLL_insert (requests_head,
2571  requests_tail,
2572  handle);
2573  if (handle->url[strlen (handle->url) - 1] == '/')
2574  handle->url[strlen (handle->url) - 1] = '\0';
2575  if (GNUNET_NO ==
2576  GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
2577  return GNUNET_NO;
2578 
2579  return GNUNET_YES;
2580 }
2581 
2582 
2589 void *
2591 {
2592  static struct Plugin plugin;
2593  struct GNUNET_REST_Plugin *api;
2594 
2595  cfg = cls;
2596  if (NULL != plugin.cfg)
2597  return NULL; /* can only initialize once! */
2598  memset (&plugin, 0, sizeof(struct Plugin));
2599  plugin.cfg = cfg;
2600  api = GNUNET_new (struct GNUNET_REST_Plugin);
2601  api->cls = &plugin;
2604  identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL);
2605  gns_handle = GNUNET_GNS_connect (cfg);
2606  idp = GNUNET_RECLAIM_connect (cfg);
2607 
2610  "%s, %s, %s, %s, %s",
2611  MHD_HTTP_METHOD_GET,
2612  MHD_HTTP_METHOD_POST,
2613  MHD_HTTP_METHOD_PUT,
2614  MHD_HTTP_METHOD_DELETE,
2615  MHD_HTTP_METHOD_OPTIONS);
2616 
2618  _ ("OpenID Connect REST API initialized\n"));
2619  return api;
2620 }
2621 
2622 
2623 static int
2624 cleanup_hashmap (void *cls, const struct GNUNET_HashCode *key, void *value)
2625 {
2626  GNUNET_free (value);
2627  return GNUNET_YES;
2628 }
2629 
2630 
2637 void *
2639 {
2640  struct GNUNET_REST_Plugin *api = cls;
2641  struct Plugin *plugin = api->cls;
2642  struct EgoEntry *ego_entry;
2643 
2644  plugin->cfg = NULL;
2645  while (NULL != requests_head)
2646  cleanup_handle (requests_head);
2647  if (NULL != OIDC_cookie_jar_map)
2648  {
2649  GNUNET_CONTAINER_multihashmap_iterate (OIDC_cookie_jar_map,
2650  &cleanup_hashmap,
2651  NULL);
2652  GNUNET_CONTAINER_multihashmap_destroy (OIDC_cookie_jar_map);
2653  }
2655  if (NULL != gns_handle)
2656  GNUNET_GNS_disconnect (gns_handle);
2657  if (NULL != identity_handle)
2658  GNUNET_IDENTITY_disconnect (identity_handle);
2659  if (NULL != idp)
2661  while (NULL != (ego_entry = ego_head))
2662  {
2663  GNUNET_CONTAINER_DLL_remove (ego_head,
2664  ego_tail,
2665  ego_entry);
2666  GNUNET_free (ego_entry->identifier);
2667  GNUNET_free (ego_entry->keystring);
2668  GNUNET_free (ego_entry);
2669  }
2670  GNUNET_free (api);
2672  "OpenID Connect REST plugin is finished\n");
2673  return NULL;
2674 }
2675 
2676 
2677 /* end of plugin_rest_openid_connect.c */
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:566
static void build_redirect(void *cls)
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
static int iterator(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Iterator over hash map entries.
struct GNUNET_RECLAIM_AttributeList * attr_userinfo_list
Attribute claim list for userinfo.
Connection to the GNS service.
Definition: gns_api.h:35
char * redirect_uri
The OIDC redirect uri.
char * scope
The list of oidc scopes.
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:1487
Handle to the service.
Definition: reclaim_api.c:317
The authorization ticket.
#define OIDC_NONCE_KEY
OIDC nonce key.
void(* GNUNET_REST_ResultProcessor)(void *cls, struct MHD_Response *resp, int status)
Iterator called on obtained result for a REST result.
size_t GNUNET_STRINGS_urldecode(const char *data, size_t len, char **out)
url/percent encode (RFC3986).
Definition: strings.c:2102
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.
static struct GNUNET_GNS_Handle * gns_handle
GNS handle.
static int parse_credentials_basic_auth(struct RequestHandle *handle, char **client_id, char **client_secret)
#define OIDC_CODE_CHALLENGE_KEY
OIDC PKCE code challenge.
struct GNUNET_RECLAIM_AttributeIterator * GNUNET_RECLAIM_get_attributes_start(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *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:1331
int 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.
struct GNUNET_RECLAIM_Identifier id
ID.
uint32_t type
Type/Format of Claim.
struct GNUNET_RECLAIM_Operation * GNUNET_RECLAIM_ticket_consume(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, const struct GNUNET_RECLAIM_Ticket *ticket, GNUNET_RECLAIM_AttributeTicketResult cb, void *cb_cls)
Consumes an issued ticket.
Definition: reclaim_api.c:1591
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_insert(head, tail, element)
Insert an element at the head of a DLL.
uint32_t type
Type/Format of Claim.
If a value with the given key exists, replace it.
static struct GNUNET_RECLAIM_AttributeList * attribute_list_merge(struct GNUNET_RECLAIM_AttributeList *list_a, struct GNUNET_RECLAIM_AttributeList *list_b)
void GNUNET_RECLAIM_get_credentials_stop(struct GNUNET_RECLAIM_CredentialIterator *ait)
Stops iteration and releases the handle for further calls.
Definition: reclaim_api.c:1509
char * nonce
The OIDC nonce.
void GNUNET_RECLAIM_attribute_list_destroy(struct GNUNET_RECLAIM_AttributeList *attrs)
Destroy claim list.
#define GNUNET_GNS_EMPTY_LABEL_AT
String we use to indicate an empty label (top-level entry in the zone).
#define OIDC_GRANT_TYPE_KEY
OIDC grant_type key.
#define OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE
OIDC expected response_type while authorizing.
void * cls
The closure of the plugin.
static void oidc_cred_collect_finished_cb(void *cls)
size_t data_size
The POST data size.
static int parse_credentials_post_body(struct RequestHandle *handle, char **client_id, char **client_secret)
struct GNUNET_RECLAIM_AttributeIterator * attr_it
Attribute iterator.
const char * name
The name of the attribute.
static int cleanup_hashmap(void *cls, const struct GNUNET_HashCode *key, void *value)
static void cookie_identity_interpretation(struct RequestHandle *handle)
Interprets cookie header and pass its identity keystring to handle.
struct GNUNET_RECLAIM_Credential * credential
The credential.
static struct RequestHandle * requests_tail
DLL.
#define OIDC_CODE_KEY
OIDC code key.
GNUNET_REST_ResultProcessor proc
The plugin result processor.
#define OIDC_ERROR_KEY_SERVER_ERROR
OIDC error key for generic server errors.
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:246
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define OIDC_REDIRECT_URI_KEY
OIDC redirect_uri key.
char * GNUNET_buffer_reap_str(struct GNUNET_Buffer *buf)
Clear the buffer and return the string it contained.
Definition: buffer.c:123
#define OIDC_ERROR_KEY_UNAUTHORIZED_CLIENT
OIDC error key for unauthorized clients.
size_t data_size
Number of bytes in data.
struct GNUNET_GNS_LookupRequest * gns_op
GNS lookup op.
struct GNUNET_RECLAIM_PresentationListEntry * next
DLL.
#define OIDC_CLAIMS_KEY
OIDC claims key.
struct GNUNET_RECLAIM_CredentialListEntry * list_tail
List tail.
char * key
TLS key.
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Handle to a lookup request.
Definition: gns_api.c:48
const struct GNUNET_CRYPTO_EcdsaPrivateKey * GNUNET_IDENTITY_ego_get_private_key(const struct GNUNET_IDENTITY_Ego *ego)
Obtain the ECC key associated with a ego.
Definition: identity_api.c:595
void GNUNET_RECLAIM_disconnect(struct GNUNET_RECLAIM_Handle *h)
Disconnect from identity provider service.
Definition: reclaim_api.c:1104
struct GNUNET_RECLAIM_CredentialListEntry * next
DLL.
#define OIDC_COOKIE_EXPIRATION
OIDC cookie expiration (in seconds)
void GNUNET_RECLAIM_cancel(struct GNUNET_RECLAIM_Operation *op)
Cancel an identity provider operation.
Definition: reclaim_api.c:1089
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
struct returned by the initialization function of the plugin
struct GNUNET_RECLAIM_PresentationListEntry * list_head
List head.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
GNUNET_GenericReturnValue
Named constants for return values.
Definition: gnunet_common.h:83
helper library for OIDC related functions
#define OIDC_COOKIE_HEADER_INFORMATION_KEY
OIDC cookie header information key.
A list of GNUNET_RECLAIM_Attribute structures.
void GNUNET_RECLAIM_ticket_iteration_stop(struct GNUNET_RECLAIM_TicketIterator *it)
Stops iteration and releases the handle for further calls.
Definition: reclaim_api.c:1701
size_t data_size
Number of bytes in data.
const void * data
Binary value stored as credential value.
static void tld_iter(void *cls, const char *section, const char *option, const char *value)
Iterate over tlds in config.
#define OIDC_COOKIE_HEADER_ACCESS_DENIED
OIDC cookie header if user cancelled.
int user_cancelled
User cancelled authorization/login.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
Private ECC key encoded for transmission.
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:1377
#define OIDC_ERROR_KEY_INVALID_TOKEN
OIDC error key for invalid tokens.
void(* proc)(struct GNUNET_REST_RequestHandle *handle, const char *url, void *cls)
Namespace to handle.
void * libgnunet_plugin_rest_openid_connect_init(void *cls)
Entry point for the plugin.
static struct RequestHandle * requests_head
DLL.
static int state
The processing state.
Handle for an operation with the service.
Definition: reclaim_api.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)...
void GNUNET_buffer_write_fstr(struct GNUNET_Buffer *buf, const char *fmt,...)
Write a 0-terminated formatted string to a buffer, excluding the 0-terminator.
Definition: buffer.c:209
struct GNUNET_RECLAIM_Identifier credential
Referenced ID of credential (may be GNUNET_RECLAIM_ID_ZERO if self-creded)
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:723
struct GNUNET_RECLAIM_CredentialIterator * GNUNET_RECLAIM_get_credentials_start(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *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:1440
char * OIDC_build_authz_code(const struct GNUNET_CRYPTO_EcdsaPrivateKey *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:441
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
static void login_redirect(void *cls)
Redirects to login page stored in configuration file.
void * proc_cls
The closure of the result processor.
uint64_t abs_value_us
The actual value.
char * edesc
Error response description.
struct OIDC_Variables * oidc
OIDC variables.
Internal representation of the hash map.
Handle for an operation with the identity service.
Definition: identity_api.c:39
#define GNUNET_REST_HANDLER_END
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
struct GNUNET_BLOCK_PluginFunctions * api
Plugin API.
Definition: block.c:47
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:787
#define OIDC_STATE_KEY
OIDC state key.
struct GNUNET_RECLAIM_Attribute * attribute
The attribute claim.
static struct EgoEntry * ego_tail
Ego list.
The request handle.
#define GNUNET_REST_API_NS_OIDC_CONFIG
OIDC config.
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.
#define _(String)
GNU gettext support macro.
Definition: platform.h:184
static char * section
Name of the section.
Definition: gnunet-config.c:33
#define OIDC_ERROR_KEY_UNSUPPORTED_GRANT_TYPE
OIDC error key for unsupported grants.
The ego list.
char * response_type
The OIDC response type.
#define OIDC_RESPONSE_TYPE_KEY
OIDC response_type key.
static struct GNUNET_RECLAIM_Ticket ticket
Ticket to consume.
struct GNUNET_CRYPTO_EcdsaPublicKey client_pkey
The RP client public key.
struct GNUNET_IDENTITY_Ego * ego
The Ego.
OIDC needed variables.
struct GNUNET_RECLAIM_PresentationList * presentations
Presentations.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
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
static void oidc_ticket_issue_cb(void *cls, const struct GNUNET_RECLAIM_Ticket *ticket, const struct GNUNET_RECLAIM_PresentationList *pres)
Issues ticket and redirects to relying party with the authorization code as parameter.
Handle for an ego.
Definition: identity.h:245
Handle for a attribute iterator operation.
Definition: reclaim_api.c:182
static void do_timeout(void *cls)
Task run on timeout, sends error message.
const struct EgoEntry * find_ego(struct RequestHandle *handle, struct GNUNET_CRYPTO_EcdsaPublicKey *test_key)
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
struct GNUNET_RECLAIM_CredentialList * credentials
Credentials.
static char * value
Value of the record to add/remove.
char * emsg
Error response message.
char * OIDC_generate_id_token(const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, const struct GNUNET_CRYPTO_EcdsaPublicKey *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:324
static void oidc_attr_collect(void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, const struct GNUNET_RECLAIM_Attribute *attr)
Collects all attributes for an ego if in scope parameter.
struct GNUNET_CONTAINER_MultiHashMap * url_param_map
Map of url parameters.
static char * attr_name
The attribute.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:48
const char * url
The url as string.
char * client_id
The OIDC client id of the RP.
Handle for the service.
Definition: identity_api.c:95
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
static void oidc_config_cors(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Respond to OPTIONS request.
struct GNUNET_RECLAIM_AttributeListEntry * list_tail
List tail.
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
char * name
Plugin name.
void GNUNET_GNS_disconnect(struct GNUNET_GNS_Handle *handle)
Shutdown connection with the GNS service.
Definition: gns_api.c:290
struct GNUNET_RECLAIM_Operation * GNUNET_RECLAIM_ticket_issue(struct GNUNET_RECLAIM_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss, const struct GNUNET_CRYPTO_EcdsaPublicKey *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:1542
#define OIDC_ERROR_KEY_INVALID_COOKIE
OIDC error key for invalid cookies.
#define OIDC_ERROR_KEY_INVALID_REQUEST
OIDC error key for invalid requests.
struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
static void lookup_redirect_uri_result(void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd)
struct GNUNET_RECLAIM_TicketIterator * ticket_it
Ticket iterator.
char * tld
The tld for redirect.
static int attr_in_userinfo_request(struct RequestHandle *handle, const char *attr_name)
static void oidc_config_endpoint(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
char * OIDC_access_token_new(const struct GNUNET_RECLAIM_Ticket *ticket)
Generate a new access token.
Definition: oidc_helper.c:751
void GNUNET_RECLAIM_credential_list_destroy(struct GNUNET_RECLAIM_CredentialList *credentials)
Destroy claim list.
static char * get_url_parameter_copy(const struct RequestHandle *handle, const char *key)
static char * option
Name of the option.
Definition: gnunet-config.c:38
#define GNUNET_REST_API_NS_AUTHORIZE
Authorize endpoint.
static struct GNUNET_DNS_Handle * handle
Handle to transport service.
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:442
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
void GNUNET_IDENTITY_disconnect(struct GNUNET_IDENTITY_Handle *h)
Disconnect from identity service.
Definition: identity_api.c:884
struct GNUNET_RECLAIM_Identifier credential_id
The credential id of which this is a presentation.
const void * data
Binary value stored as presentation value.
struct GNUNET_RECLAIM_Identifier id
ID.
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
size_t data_size
Number of bytes in data.
#define OIDC_ERROR_KEY_UNSUPPORTED_RESPONSE_TYPE
OIDC error key for unsupported response types.
#define OIDC_CODE_VERIFIER_KEY
OIDC PKCE code verifier.
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
static void cleanup_handle(struct RequestHandle *handle)
Cleanup lookup handle.
struct GNUNET_REST_RequestHandle * rest_handle
Rest connection.
A 512-bit hashcode.
int response_code
Response code.
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 int res
static void code_redirect(void *cls)
Checks time and cookie and redirects accordingly.
static char * plugin
Solver plugin name as string.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
size_t GNUNET_STRINGS_base64_decode(const char *data, size_t len, void **output)
Decode from Base64.
Definition: strings.c:1977
int OIDC_parse_authz_code(const struct GNUNET_CRYPTO_EcdsaPublicKey *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)
Parse reclaim ticket and nonce from authorization code.
Definition: oidc_helper.c:579
char * GNUNET_CRYPTO_ecdsa_public_key_to_string(const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
Convert a public key to a string.
Definition: crypto_ecc.c:232
int 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.
const char * data
The POST data.
struct RequestHandle * next
DLL.
char * claims
The OIDC claims.
struct GNUNET_CRYPTO_EcdsaPublicKey identity
The ticket issuer (= the user)
char * keystring
Public key string.
A credential presentation.
void GNUNET_RECLAIM_presentation_list_destroy(struct GNUNET_RECLAIM_PresentationList *presentations)
Destroy presentations list.
static struct GNUNET_IDENTITY_Handle * identity
Which namespace do we publish to? NULL if we do not publish to a namespace.
size_t data_size
Number of bytes in data.
void GNUNET_CRYPTO_ecdsa_key_get_public(const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
Extract the public key for the given private key.
Definition: crypto_ecc.c:176
#define OIDC_ERROR_KEY_ACCESS_DENIED
OIDC error key for denied access.
size_t GNUNET_STRINGS_urlencode(const char *data, size_t len, char **out)
url/percent encode (RFC3986).
Definition: strings.c:2146
struct GNUNET_RECLAIM_CredentialListEntry * list_head
List head.
const char * name
The name of the credential.
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 struct GNUNET_RECLAIM_Handle * idp
Identity Provider.
#define OIDC_AUTHORIZATION_HEADER_KEY
OIDC cookie header information key.
struct GNUNET_RECLAIM_AttributeListEntry * next
DLL.
static struct GNUNET_RECLAIM_Identifier credential
Credential ID.
struct RequestHandle * prev
DLL.
struct GNUNET_RECLAIM_CredentialIterator * cred_it
Credential iterator.
#define OIDC_EXPECTED_AUTHORIZATION_SCOPE
OIDC expected scope part while authorizing.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
#define GNUNET_REST_API_NS_LOGIN
Login namespace.
static struct GNUNET_SCHEDULER_Task * timeout_task
Task to be run on timeout.
Definition: gnunet-arm.c:124
static char * OIDC_ignored_parameter_array[]
OIDC ignored parameter array.
static int check_authorization(struct RequestHandle *handle, struct GNUNET_CRYPTO_EcdsaPublicKey *cid)
static void build_authz_response(void *cls)
Iteration over all results finished, build final response.
char * state
The OIDC state.
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.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_REST_API_NS_OIDC
REST root namespace.
static void client_redirect(void *cls)
Initiate redirect back to client.
char * OIDC_generate_userinfo(const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations)
Generate userinfo JSON as string.
Definition: oidc_helper.c:298
static void authorize_endpoint(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Responds to authorization GET and url-encoded POST request.
char * identifier
Ego Identifier.
static void do_error(void *cls)
Task run on error, sends error message.
#define GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT
Record type for reclaim OIDC redirect URIs.
static struct GNUNET_IDENTITY_Handle * identity_handle
Handle to Identity service.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
static void oidc_cred_collect(void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, const struct GNUNET_RECLAIM_Credential *cred)
Collects all attributes for an ego if in scope parameter.
struct GNUNET_RECLAIM_Presentation * presentation
The credential.
char * redirect_prefix
The redirect prefix.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_get_second_(void)
Return relative time of 1s.
Definition: time.c:183
static char * allow_methods
HTTP methods allows for this plugin.
struct GNUNET_RECLAIM_Ticket ticket
A ticket.
int GNUNET_CRYPTO_ecdsa_public_key_from_string(const char *enc, size_t enclen, struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
Convert a string representing a public key to a public key.
Definition: crypto_ecc.c:366
A list of GNUNET_RECLAIM_Presentation structures.
configuration data
Definition: configuration.c:84
static int attr_in_claims_request(struct RequestHandle *handle, const char *attr_name, const char *claims_parameter)
Handle for a plugin.
Definition: block.c:37
static void options_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Respond to OPTIONS request.
void GNUNET_RECLAIM_get_attributes_stop(struct GNUNET_RECLAIM_AttributeIterator *it)
Stops iteration and releases the handle for further calls.
Definition: reclaim_api.c:1398
struct GNUNET_CRYPTO_EcdsaPublicKey audience
The ticket audience (= relying party)
struct GNUNET_SCHEDULER_Task * timeout_task
ID of a task associated with the resolution process.
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 enum GNUNET_GenericReturnValue rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
static void token_endpoint(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Responds to token url-encoded POST request.
A list of GNUNET_RECLAIM_Credential structures.
char * redirect_suffix
The redirect suffix.
#define OIDC_ERROR_KEY_INVALID_CLIENT
OIDC error key for invalid client.
struct MHD_Response * GNUNET_REST_create_response(const char *data)
Create REST MHD response.
Definition: rest.c:57
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and ECDS...
struct GNUNET_RECLAIM_Presentation * GNUNET_RECLAIM_presentation_new(uint32_t type, const void *data, size_t data_size)
#define GNUNET_RECLAIM_id_is_equal(a, b)
Handle for a ticket iterator operation.
Definition: reclaim_api.c:119
#define GNUNET_log(kind,...)
const struct GNUNET_CONFIGURATION_Handle * cfg
The configuration handle.
Entry in list of pending tasks.
Definition: scheduler.c:134
struct GNUNET_RECLAIM_AttributeList * attr_idtoken_list
Attribute claim list for id_token.
const void * data
Binary value stored as attribute value.
#define OIDC_SCOPE_KEY
OIDC scope key.
static int attr_in_idtoken_request(struct RequestHandle *handle, const char *attr_name)
struct GNUNET_RECLAIM_Operation * idp_op
Idp Operation.
void * GNUNET_GNS_lookup_cancel(struct GNUNET_GNS_LookupRequest *lr)
Cancel pending lookup request.
Definition: gns_api.c:314
#define OIDC_GRANT_TYPE_VALUE
OIDC grant_type key.
#define ID_REST_STATE_INIT
State while collecting all egos.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
uint32_t type
Type of Claim.
#define OIDC_CLIENT_ID_KEY
OIDC client_id key.
struct GNUNET_RECLAIM_PresentationListEntry * list_tail
List tail.
char * code_verifier
The PKCE code_verifier.
int OIDC_access_token_parse(const char *token, struct GNUNET_RECLAIM_Ticket **ticket)
Parse an access token.
Definition: oidc_helper.c:766
Time for absolute times used by GNUnet, in microseconds.
struct GNUNET_CONTAINER_MultiHashMap * header_param_map
Map of headers.
static void consume_ticket(void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, const struct GNUNET_RECLAIM_Attribute *attr, const struct GNUNET_RECLAIM_Presentation *pres)
Collects claims and stores them in handle.
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.
Defaults, look in cache, then in DHT.
Common buffer management functions.
struct EgoEntry * prev
DLL.
struct GNUNET_CONTAINER_MultiHashMap * OIDC_cookie_jar_map
OIDC Hash map that keeps track of issued cookies.
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
Definition: strings.c:936
void * libgnunet_plugin_rest_openid_connect_done(void *cls)
Exit point from the plugin.
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
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:144
char * code_challenge
The PKCE code_challenge.
struct EgoEntry * ego_entry
IDENTITY Operation.
struct GNUNET_GNS_LookupRequest * GNUNET_GNS_lookup(struct GNUNET_GNS_Handle *handle, const char *name, const struct GNUNET_CRYPTO_EcdsaPublicKey *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
static void oidc_iteration_error(void *cls)
Does internal server error when iteration failed.
enum GNUNET_GenericReturnValue(* process_request)(struct GNUNET_REST_RequestHandle *handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function to process a REST call.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
struct GNUNET_RECLAIM_Handle * GNUNET_RECLAIM_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the re:claimID service.
Definition: reclaim_api.c:1064
uint32_t data
The data value.
int public_client
Public client.
#define OIDC_COOKIE_HEADER_KEY
OIDC cookie header key.
void GNUNET_IDENTITY_ego_get_public_key(struct GNUNET_IDENTITY_Ego *ego, struct GNUNET_CRYPTO_EcdsaPublicKey *pk)
Get the identifier (public key) of an ego.
Definition: identity_api.c:608
struct EgoEntry * next
DLL.
static struct EgoEntry * ego_head
Ego list.
#define GNUNET_REST_API_NS_USERINFO
UserInfo endpoint.
Handle for a credential iterator operation.
Definition: reclaim_api.c:249
struct GNUNET_RECLAIM_AttributeListEntry * list_head
List head.
int 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:971
#define ID_REST_STATE_POST_INIT
Done collecting egos.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
static void oidc_attr_collect_finished_cb(void *cls)
#define OIDC_ERROR_KEY_INVALID_SCOPE
OIDC error key for invalid scopes.
#define GNUNET_REST_API_NS_TOKEN
Token endpoint.
char * login_identity
The identity chosen by the user to login.
struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key
Pointer to ego private key.
static void do_userinfo_error(void *cls)
Task run on error in userinfo endpoint, sends error header.
static void do_redirect_error(void *cls)
Task run on error, sends error message and redirects.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:972
char * url
The url.