GNUnet  0.10.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_gns_service.h"
32 #include "gnunet_gnsrecord_lib.h"
36 #include "gnunet_reclaim_service.h"
37 #include "gnunet_rest_lib.h"
38 #include "gnunet_rest_plugin.h"
39 #include "gnunet_signatures.h"
40 #include "microhttpd.h"
41 #include "oidc_helper.h"
45 #define GNUNET_REST_API_NS_OIDC "/openid"
46 
50 #define GNUNET_REST_API_NS_AUTHORIZE "/openid/authorize"
51 
55 #define GNUNET_REST_API_NS_TOKEN "/openid/token"
56 
60 #define GNUNET_REST_API_NS_USERINFO "/openid/userinfo"
61 
65 #define GNUNET_REST_API_NS_LOGIN "/openid/login"
66 
70 #define ID_REST_STATE_INIT 0
71 
75 #define ID_REST_STATE_POST_INIT 1
76 
80 #define OIDC_GRANT_TYPE_KEY "grant_type"
81 
85 #define OIDC_GRANT_TYPE_VALUE "authorization_code"
86 
90 #define OIDC_CODE_KEY "code"
91 
95 #define OIDC_RESPONSE_TYPE_KEY "response_type"
96 
100 #define OIDC_CLIENT_ID_KEY "client_id"
101 
105 #define OIDC_SCOPE_KEY "scope"
106 
110 #define OIDC_REDIRECT_URI_KEY "redirect_uri"
111 
115 #define OIDC_STATE_KEY "state"
116 
120 #define OIDC_NONCE_KEY "nonce"
121 
125 #define OIDC_COOKIE_EXPIRATION 3
126 
130 #define OIDC_COOKIE_HEADER_KEY "cookie"
131 
135 #define OIDC_AUTHORIZATION_HEADER_KEY "authorization"
136 
140 #define OIDC_COOKIE_HEADER_INFORMATION_KEY "Identity="
141 
145 #define OIDC_COOKIE_HEADER_ACCESS_DENIED "Identity=Denied"
146 
150 #define OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE "code"
151 
155 #define OIDC_EXPECTED_AUTHORIZATION_SCOPE "openid"
156 
160 #define OIDC_ERROR_KEY_INVALID_CLIENT "invalid_client"
161 
165 #define OIDC_ERROR_KEY_INVALID_SCOPE "invalid_scope"
166 
170 #define OIDC_ERROR_KEY_INVALID_REQUEST "invalid_request"
171 
175 #define OIDC_ERROR_KEY_INVALID_TOKEN "invalid_token"
176 
180 #define OIDC_ERROR_KEY_INVALID_COOKIE "invalid_cookie"
181 
185 #define OIDC_ERROR_KEY_SERVER_ERROR "server_error"
186 
190 #define OIDC_ERROR_KEY_UNSUPPORTED_GRANT_TYPE "unsupported_grant_type"
191 
195 #define OIDC_ERROR_KEY_UNSUPPORTED_RESPONSE_TYPE "unsupported_response_type"
196 
200 #define OIDC_ERROR_KEY_UNAUTHORIZED_CLIENT "unauthorized_client"
201 
205 #define OIDC_ERROR_KEY_ACCESS_DENIED "access_denied"
206 
207 
211 static char *OIDC_ignored_parameter_array[] = {"display",
212  "prompt",
213  "ui_locales",
214  "response_mode",
215  "id_token_hint",
216  "login_hint",
217  "acr_values"};
218 
223 
229 
234 
238 static char *allow_methods;
239 
243 struct Plugin
244 {
245  const struct GNUNET_CONFIGURATION_Handle *cfg;
246 };
247 
252 {
256  struct GNUNET_CRYPTO_EcdsaPublicKey client_pkey;
257 
261  char *client_id;
262 
267 
271  char *scope;
272 
276  char *state;
277 
281  char *nonce;
282 
287 
292 
297 
301  json_t *response;
302 };
303 
307 struct EgoEntry
308 {
312  struct EgoEntry *next;
313 
317  struct EgoEntry *prev;
318 
322  char *identifier;
323 
327  char *keystring;
328 
332  struct GNUNET_IDENTITY_Ego *ego;
333 };
334 
335 
336 struct RequestHandle
337 {
341  struct EgoEntry *ego_head;
342 
346  struct EgoEntry *ego_tail;
347 
351  struct EgoEntry *ego_entry;
352 
357 
362 
366  int state;
367 
372 
376  struct GNUNET_REST_RequestHandle *rest_handle;
377 
382 
387 
392 
397 
402 
407 
412 
417 
422 
427 
432 
437 
442 
447 
451  void *proc_cls;
452 
456  char *url;
457 
461  char *tld;
462 
467 
472 
476  char *emsg;
477 
481  char *edesc;
482 
486  int response_code;
487 };
488 
493 static void
495 {
496  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *claim_entry;
497  struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *claim_tmp;
498  struct EgoEntry *ego_entry;
499  struct EgoEntry *ego_tmp;
500  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
501  if (NULL != handle->timeout_task)
503  if (NULL != handle->identity_handle)
505  if (NULL != handle->attr_it)
507  if (NULL != handle->ticket_it)
509  if (NULL != handle->idp)
510  GNUNET_RECLAIM_disconnect (handle->idp);
511  GNUNET_free_non_null (handle->url);
512  GNUNET_free_non_null (handle->tld);
515  GNUNET_free_non_null (handle->emsg);
516  GNUNET_free_non_null (handle->edesc);
517  if (NULL != handle->gns_op)
519  if (NULL != handle->gns_handle)
521 
522  if (NULL != handle->namestore_handle)
524  if (NULL != handle->oidc)
525  {
528  GNUNET_free_non_null (handle->oidc->nonce);
531  GNUNET_free_non_null (handle->oidc->scope);
532  GNUNET_free_non_null (handle->oidc->state);
533  json_decref (handle->oidc->response);
534  GNUNET_free (handle->oidc);
535  }
536  if (NULL != handle->attr_list)
537  {
538  for (claim_entry = handle->attr_list->list_head; NULL != claim_entry;)
539  {
540  claim_tmp = claim_entry;
541  claim_entry = claim_entry->next;
542  GNUNET_free (claim_tmp->claim);
543  GNUNET_free (claim_tmp);
544  }
545  GNUNET_free (handle->attr_list);
546  }
547  for (ego_entry = handle->ego_head; NULL != ego_entry;)
548  {
549  ego_tmp = ego_entry;
550  ego_entry = ego_entry->next;
551  GNUNET_free (ego_tmp->identifier);
552  GNUNET_free (ego_tmp->keystring);
553  GNUNET_free (ego_tmp);
554  }
555  GNUNET_free (handle);
556 }
557 
558 static void
560 {
561  cleanup_handle (cls);
562 }
563 
564 
570 static void
571 do_error (void *cls)
572 {
573  struct RequestHandle *handle = cls;
574  struct MHD_Response *resp;
575  char *json_error;
576 
577  GNUNET_asprintf (&json_error,
578  "{ \"error\" : \"%s\", \"error_description\" : \"%s\"%s%s%s}",
579  handle->emsg,
580  (NULL != handle->edesc) ? handle->edesc : "",
581  (NULL != handle->oidc->state) ? ", \"state\":\"" : "",
582  (NULL != handle->oidc->state) ? handle->oidc->state : "",
583  (NULL != handle->oidc->state) ? "\"" : "");
584  if (0 == handle->response_code)
585  handle->response_code = MHD_HTTP_BAD_REQUEST;
586  resp = GNUNET_REST_create_response (json_error);
587  if (MHD_HTTP_UNAUTHORIZED == handle->response_code)
588  MHD_add_response_header (resp, MHD_HTTP_HEADER_WWW_AUTHENTICATE, "Basic");
589  MHD_add_response_header (resp,
590  MHD_HTTP_HEADER_CONTENT_TYPE,
591  "application/json");
592  handle->proc (handle->proc_cls, resp, handle->response_code);
594  GNUNET_free (json_error);
595 }
596 
597 
604 static void
605 do_userinfo_error (void *cls)
606 {
607  struct RequestHandle *handle = cls;
608  struct MHD_Response *resp;
609  char *error;
610 
611  GNUNET_asprintf (&error,
612  "error=\"%s\", error_description=\"%s\"",
613  handle->emsg,
614  (NULL != handle->edesc) ? handle->edesc : "");
615  resp = GNUNET_REST_create_response ("");
616  MHD_add_response_header (resp, MHD_HTTP_HEADER_WWW_AUTHENTICATE, "Bearer");
617  handle->proc (handle->proc_cls, resp, handle->response_code);
619  GNUNET_free (error);
620 }
621 
622 
628 static void
629 do_redirect_error (void *cls)
630 {
631  struct RequestHandle *handle = cls;
632  struct MHD_Response *resp;
633  char *redirect;
634  GNUNET_asprintf (&redirect,
635  "%s?error=%s&error_description=%s%s%s",
636  handle->oidc->redirect_uri,
637  handle->emsg,
638  handle->edesc,
639  (NULL != handle->oidc->state) ? "&state=" : "",
640  (NULL != handle->oidc->state) ? handle->oidc->state : "");
641  resp = GNUNET_REST_create_response ("");
642  MHD_add_response_header (resp, "Location", redirect);
643  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
645  GNUNET_free (redirect);
646 }
647 
653 static void
654 do_timeout (void *cls)
655 {
656  struct RequestHandle *handle = cls;
657 
658  handle->timeout_task = NULL;
659  do_error (handle);
660 }
661 
667 static void
669 {
670  char *result_str;
671  struct RequestHandle *handle = cls;
672  struct MHD_Response *resp;
673 
674  result_str = json_dumps (handle->oidc->response, 0);
675 
676  resp = GNUNET_REST_create_response (result_str);
677  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
678  GNUNET_free (result_str);
679  cleanup_handle (handle);
680 }
681 
682 
690 static void
692  const char *url,
693  void *cls)
694 {
695  struct MHD_Response *resp;
696  struct RequestHandle *handle = cls;
697 
698  // For now, independent of path return all options
699  resp = GNUNET_REST_create_response (NULL);
700  MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
701  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
702  cleanup_handle (handle);
703  return;
704 }
705 
706 
710 static void
712 {
713  struct GNUNET_HashCode cache_key;
714  char *cookies;
715  struct GNUNET_TIME_Absolute current_time, *relog_time;
716  char delimiter[] = "; ";
717  char *tmp_cookies;
718  char *token;
719  char *value;
720 
721  // gets identity of login try with cookie
723  strlen (OIDC_COOKIE_HEADER_KEY),
724  &cache_key);
727  &cache_key))
728  {
729  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No cookie found\n");
730  return;
731  }
732  // splits cookies and find 'Identity' cookie
733  tmp_cookies =
735  &cache_key);
736  cookies = GNUNET_strdup (tmp_cookies);
737  token = strtok (cookies, delimiter);
738  handle->oidc->user_cancelled = GNUNET_NO;
739  handle->oidc->login_identity = NULL;
740  if (NULL == token)
741  {
743  "Unable to parse cookie: %s\n",
744  cookies);
745  GNUNET_free (cookies);
746  return;
747  }
748 
749  while (NULL != token)
750  {
751  if (0 == strcmp (token, OIDC_COOKIE_HEADER_ACCESS_DENIED))
752  {
753  handle->oidc->user_cancelled = GNUNET_YES;
754  GNUNET_free (cookies);
755  return;
756  }
757  if (NULL != strstr (token, OIDC_COOKIE_HEADER_INFORMATION_KEY))
758  break;
759  token = strtok (NULL, delimiter);
760  }
761  if (NULL == token)
762  {
764  "No cookie value to process: %s\n",
765  cookies);
766  GNUNET_free (cookies);
767  return;
768  }
769  GNUNET_CRYPTO_hash (token, strlen (token), &cache_key);
770  if (GNUNET_NO ==
771  GNUNET_CONTAINER_multihashmap_contains (OIDC_cookie_jar_map, &cache_key))
772  {
773  GNUNET_log (
775  "Found cookie `%s', but no corresponding expiration entry present...\n",
776  token);
777  GNUNET_free (cookies);
778  return;
779  }
780  relog_time =
781  GNUNET_CONTAINER_multihashmap_get (OIDC_cookie_jar_map, &cache_key);
782  current_time = GNUNET_TIME_absolute_get ();
783  // 30 min after old login -> redirect to login
784  if (current_time.abs_value_us > relog_time->abs_value_us)
785  {
787  "Found cookie `%s', but it is expired.\n",
788  token);
789  GNUNET_free (cookies);
790  return;
791  }
792  value = strtok (token, OIDC_COOKIE_HEADER_INFORMATION_KEY);
793  GNUNET_assert (NULL != value);
794  handle->oidc->login_identity = GNUNET_strdup (value);
795  GNUNET_free (cookies);
796 }
797 
801 static void
802 login_redirect (void *cls)
803 {
804  char *login_base_url;
805  char *new_redirect;
806  struct MHD_Response *resp;
807  struct RequestHandle *handle = cls;
808 
810  "reclaim-rest-plugin",
811  "address",
812  &login_base_url))
813  {
814  GNUNET_asprintf (&new_redirect,
815  "%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s",
816  login_base_url,
818  handle->oidc->response_type,
820  handle->oidc->client_id,
822  handle->oidc->redirect_uri,
824  handle->oidc->scope,
826  (NULL != handle->oidc->state) ? handle->oidc->state : "",
828  (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "");
829  resp = GNUNET_REST_create_response ("");
830  MHD_add_response_header (resp, "Location", new_redirect);
831  GNUNET_free (login_base_url);
832  }
833  else
834  {
836  handle->edesc = GNUNET_strdup ("gnunet configuration failed");
837  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
839  return;
840  }
841  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
842  GNUNET_free (new_redirect);
844 }
845 
849 static void
851 {
852  struct RequestHandle *handle = cls;
854  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
856 }
857 
858 
863 static void
865 {
866  struct RequestHandle *handle = cls;
867  struct MHD_Response *resp;
868  char *ticket_str;
869  char *redirect_uri;
870  char *code_string;
871 
872  handle->idp_op = NULL;
873  if (NULL == ticket)
874  {
876  handle->edesc = GNUNET_strdup ("Server cannot generate ticket.");
878  return;
879  }
880  handle->ticket = *ticket;
881  ticket_str =
883  sizeof (struct GNUNET_RECLAIM_Ticket));
884  // TODO change if more attributes are needed (see max_age)
885  code_string = OIDC_build_authz_code (&handle->priv_key,
886  &handle->ticket,
887  handle->attr_list,
888  handle->oidc->nonce);
889  if ((NULL != handle->redirect_prefix) && (NULL != handle->redirect_suffix) &&
890  (NULL != handle->tld))
891  {
892 
893  GNUNET_asprintf (&redirect_uri,
894  "%s.%s/%s?%s=%s&state=%s",
895  handle->redirect_prefix,
896  handle->tld,
897  handle->redirect_suffix,
898  handle->oidc->response_type,
899  code_string,
900  handle->oidc->state);
901  }
902  else
903  {
904  GNUNET_asprintf (&redirect_uri,
905  "%s?%s=%s&state=%s",
906  handle->oidc->redirect_uri,
907  handle->oidc->response_type,
908  code_string,
909  handle->oidc->state);
910  }
911  resp = GNUNET_REST_create_response ("");
912  MHD_add_response_header (resp, "Location", redirect_uri);
913  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
915  GNUNET_free (redirect_uri);
916  GNUNET_free (ticket_str);
917  GNUNET_free (code_string);
918 }
919 
920 static void
922 {
923  struct RequestHandle *handle = cls;
924  handle->attr_it = NULL;
925  handle->ticket_it = NULL;
926  if (NULL == handle->attr_list->list_head)
927  {
929  handle->edesc = GNUNET_strdup ("The requested scope is not available.");
931  return;
932  }
933  handle->idp_op = GNUNET_RECLAIM_ticket_issue (handle->idp,
934  &handle->priv_key,
935  &handle->oidc->client_pkey,
936  handle->attr_list,
938  handle);
939 }
940 
941 
945 static void
946 oidc_attr_collect (void *cls,
948  const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
949 {
950  struct RequestHandle *handle = cls;
952  char *scope_variables;
953  char *scope_variable;
954  char delimiter[] = " ";
955 
956  if ((NULL == attr->name) || (NULL == attr->data))
957  {
959  return;
960  }
961 
962  scope_variables = GNUNET_strdup (handle->oidc->scope);
963  scope_variable = strtok (scope_variables, delimiter);
964  while (NULL != scope_variable)
965  {
966  if (0 == strcmp (attr->name, scope_variable))
967  break;
968  scope_variable = strtok (NULL, delimiter);
969  }
970  if (NULL == scope_variable)
971  {
973  GNUNET_free (scope_variables);
974  return;
975  }
976  GNUNET_free (scope_variables);
977 
980  attr->type,
981  attr->data,
982  attr->data_size);
983  le->claim->id = attr->id;
984  le->claim->version = attr->version;
986  handle->attr_list->list_tail,
987  le);
989 }
990 
991 
995 static void
996 code_redirect (void *cls)
997 {
998  struct RequestHandle *handle = cls;
999  struct GNUNET_TIME_Absolute current_time;
1000  struct GNUNET_TIME_Absolute *relog_time;
1001  struct GNUNET_CRYPTO_EcdsaPublicKey pubkey;
1002  struct GNUNET_CRYPTO_EcdsaPublicKey ego_pkey;
1003  struct GNUNET_HashCode cache_key;
1004  char *identity_cookie;
1005 
1006  GNUNET_asprintf (&identity_cookie,
1007  "Identity=%s",
1008  handle->oidc->login_identity);
1009  GNUNET_CRYPTO_hash (identity_cookie, strlen (identity_cookie), &cache_key);
1010  GNUNET_free (identity_cookie);
1011  // No login time for identity -> redirect to login
1012  if (GNUNET_YES ==
1013  GNUNET_CONTAINER_multihashmap_contains (OIDC_cookie_jar_map, &cache_key))
1014  {
1015  relog_time =
1016  GNUNET_CONTAINER_multihashmap_get (OIDC_cookie_jar_map, &cache_key);
1017  current_time = GNUNET_TIME_absolute_get ();
1018  // 30 min after old login -> redirect to login
1019  if (current_time.abs_value_us <= relog_time->abs_value_us)
1020  {
1021  if (GNUNET_OK !=
1023  ->login_identity,
1024  strlen (
1025  handle->oidc
1026  ->login_identity),
1027  &pubkey))
1028  {
1030  handle->edesc =
1031  GNUNET_strdup ("The cookie of a login identity is not valid");
1033  return;
1034  }
1035  // iterate over egos and compare their public key
1036  for (handle->ego_entry = handle->ego_head; NULL != handle->ego_entry;
1037  handle->ego_entry = handle->ego_entry->next)
1038  {
1039  GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey);
1040  if (0 == GNUNET_memcmp (&ego_pkey, &pubkey))
1041  {
1042  handle->priv_key =
1044  handle->idp = GNUNET_RECLAIM_connect (cfg);
1045  handle->attr_list =
1047  handle->attr_it =
1049  &handle->priv_key,
1051  handle,
1053  handle,
1055  handle);
1056  return;
1057  }
1058  }
1060  return;
1061  }
1062  }
1063 }
1064 
1065 
1066 static void
1067 build_redirect (void *cls)
1068 {
1069  struct RequestHandle *handle = cls;
1070  struct MHD_Response *resp;
1071  char *redirect_uri;
1072 
1073  if (GNUNET_YES == handle->oidc->user_cancelled)
1074  {
1075  if ((NULL != handle->redirect_prefix) &&
1076  (NULL != handle->redirect_suffix) && (NULL != handle->tld))
1077  {
1078  GNUNET_asprintf (&redirect_uri,
1079  "%s.%s/%s?error=%s&error_description=%s&state=%s",
1080  handle->redirect_prefix,
1081  handle->tld,
1082  handle->redirect_suffix,
1083  "access_denied",
1084  "User denied access",
1085  handle->oidc->state);
1086  }
1087  else
1088  {
1089  GNUNET_asprintf (&redirect_uri,
1090  "%s?error=%s&error_description=%s&state=%s",
1091  handle->oidc->redirect_uri,
1092  "access_denied",
1093  "User denied access",
1094  handle->oidc->state);
1095  }
1096  resp = GNUNET_REST_create_response ("");
1097  MHD_add_response_header (resp, "Location", redirect_uri);
1098  handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND);
1100  GNUNET_free (redirect_uri);
1101  return;
1102  }
1104 }
1105 
1106 
1107 static void
1109  uint32_t rd_count,
1110  const struct GNUNET_GNSRECORD_Data *rd)
1111 {
1112  struct RequestHandle *handle = cls;
1113  char *tmp;
1114  char *tmp_key_str;
1115  char *pos;
1116  struct GNUNET_CRYPTO_EcdsaPublicKey redirect_zone;
1117 
1118  handle->gns_op = NULL;
1119  if (0 == rd_count)
1120  {
1122  handle->edesc =
1123  GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1125  return;
1126  }
1127  for (int i = 0; i < rd_count; i++)
1128  {
1129  if (GNUNET_GNSRECORD_TYPE_RECLAIM_OIDC_REDIRECT != rd[i].record_type)
1130  continue;
1131  if (0 != strncmp (rd[i].data, handle->oidc->redirect_uri, rd[i].data_size))
1132  continue;
1133  tmp = GNUNET_strndup (rd[i].data, rd[i].data_size);
1134  if (NULL == strstr (tmp, handle->oidc->client_id))
1135  {
1137  "Redirect uri %s does not contain client_id %s\n",
1138  tmp,
1139  handle->oidc->client_id);
1140  }
1141  else
1142  {
1143  pos = strrchr (tmp, (unsigned char) '.');
1144  if (NULL == pos)
1145  {
1147  "Redirect uri %s contains client_id but is malformed\n",
1148  tmp);
1149  GNUNET_free (tmp);
1150  continue;
1151  }
1152  *pos = '\0';
1153  handle->redirect_prefix = GNUNET_strdup (tmp);
1154  tmp_key_str = pos + 1;
1155  pos = strchr (tmp_key_str, (unsigned char) '/');
1156  if (NULL == pos)
1157  {
1159  "Redirect uri %s contains client_id but is malformed\n",
1160  tmp);
1161  GNUNET_free (tmp);
1162  continue;
1163  }
1164  *pos = '\0';
1165  handle->redirect_suffix = GNUNET_strdup (pos + 1);
1166 
1167  GNUNET_STRINGS_string_to_data (tmp_key_str,
1168  strlen (tmp_key_str),
1169  &redirect_zone,
1170  sizeof (redirect_zone));
1171  }
1173  GNUNET_free (tmp);
1174  return;
1175  }
1177  handle->edesc =
1178  GNUNET_strdup ("Server cannot generate ticket, redirect uri not found.");
1180 }
1181 
1182 
1186 static void
1187 client_redirect (void *cls)
1188 {
1189  struct RequestHandle *handle = cls;
1190 
1191  /* Lookup client redirect uri to verify request */
1192  handle->gns_op =
1193  GNUNET_GNS_lookup (handle->gns_handle,
1195  &handle->oidc->client_pkey,
1199  handle);
1200 }
1201 
1202 static char *
1203 get_url_parameter_copy (const struct RequestHandle *handle, const char *key)
1204 {
1205  struct GNUNET_HashCode hc;
1206  char *value;
1207  GNUNET_CRYPTO_hash (key, strlen (key), &hc);
1209  ->url_param_map,
1210  &hc))
1211  return NULL;
1212  value =
1214  if (NULL == value)
1215  return NULL;
1216  return GNUNET_strdup (value);
1217 }
1218 
1219 
1226 static void
1228 {
1229  struct RequestHandle *handle = cls;
1230  struct GNUNET_HashCode cache_key;
1231 
1232  char *expected_scope;
1233  char delimiter[] = " ";
1234  int number_of_ignored_parameter, iterator;
1235 
1236 
1237  // REQUIRED value: redirect_uri
1238  handle->oidc->redirect_uri =
1240  if (NULL == handle->oidc->redirect_uri)
1241  {
1243  handle->edesc = GNUNET_strdup ("missing parameter redirect_uri");
1245  return;
1246  }
1247 
1248  // REQUIRED value: response_type
1249  handle->oidc->response_type =
1251  if (NULL == handle->oidc->response_type)
1252  {
1254  handle->edesc = GNUNET_strdup ("missing parameter response_type");
1256  return;
1257  }
1258 
1259  // REQUIRED value: scope
1260  handle->oidc->scope = get_url_parameter_copy (handle, OIDC_SCOPE_KEY);
1261  if (NULL == handle->oidc->scope)
1262  {
1264  handle->edesc = GNUNET_strdup ("missing parameter scope");
1266  return;
1267  }
1268 
1269  // OPTIONAL value: nonce
1270  handle->oidc->nonce = get_url_parameter_copy (handle, OIDC_NONCE_KEY);
1271 
1272  // TODO check other values if needed
1273  number_of_ignored_parameter =
1274  sizeof (OIDC_ignored_parameter_array) / sizeof (char *);
1275  for (iterator = 0; iterator < number_of_ignored_parameter; iterator++)
1276  {
1278  strlen (OIDC_ignored_parameter_array[iterator]),
1279  &cache_key);
1280  if (GNUNET_YES ==
1282  ->url_param_map,
1283  &cache_key))
1284  {
1286  GNUNET_asprintf (&handle->edesc,
1287  "Server will not handle parameter: %s",
1288  OIDC_ignored_parameter_array[iterator]);
1290  return;
1291  }
1292  }
1293 
1294  // We only support authorization code flows.
1295  if (0 != strcmp (handle->oidc->response_type,
1297  {
1299  handle->edesc = GNUNET_strdup ("The authorization server does not support "
1300  "obtaining this authorization code.");
1302  return;
1303  }
1304 
1305  // Checks if scope contains 'openid'
1306  expected_scope = GNUNET_strdup (handle->oidc->scope);
1307  char *test;
1308  test = strtok (expected_scope, delimiter);
1309  while (NULL != test)
1310  {
1311  if (0 == strcmp (OIDC_EXPECTED_AUTHORIZATION_SCOPE, expected_scope))
1312  break;
1313  test = strtok (NULL, delimiter);
1314  }
1315  if (NULL == test)
1316  {
1318  handle->edesc =
1319  GNUNET_strdup ("The requested scope is invalid, unknown, or malformed.");
1321  GNUNET_free (expected_scope);
1322  return;
1323  }
1324 
1325  GNUNET_free (expected_scope);
1326  if ((NULL == handle->oidc->login_identity) &&
1327  (GNUNET_NO == handle->oidc->user_cancelled))
1329  else
1331 }
1332 
1336 static void
1337 tld_iter (void *cls, const char *section, const char *option, const char *value)
1338 {
1339  struct RequestHandle *handle = cls;
1340  struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
1341 
1342  if (GNUNET_OK !=
1343  GNUNET_CRYPTO_ecdsa_public_key_from_string (value, strlen (value), &pkey))
1344  {
1345  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Skipping non key %s\n", value);
1346  return;
1347  }
1348  if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1349  handle->tld = GNUNET_strdup (option + 1);
1350 }
1351 
1359 static void
1361  const char *url,
1362  void *cls)
1363 {
1364  struct RequestHandle *handle = cls;
1365  struct EgoEntry *tmp_ego;
1366  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key;
1367  struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
1368 
1370 
1371  // RECOMMENDED value: state - REQUIRED for answers
1372  handle->oidc->state = get_url_parameter_copy (handle, OIDC_STATE_KEY);
1373 
1374  // REQUIRED value: client_id
1376  if (NULL == handle->oidc->client_id)
1377  {
1379  handle->edesc = GNUNET_strdup ("missing parameter client_id");
1380  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1382  return;
1383  }
1384 
1385  if (GNUNET_OK !=
1387  strlen (
1388  handle->oidc->client_id),
1389  &handle->oidc->client_pkey))
1390  {
1392  handle->edesc = GNUNET_strdup ("The client is not authorized to request an "
1393  "authorization code using this method.");
1394  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1396  return;
1397  }
1398 
1399  // If we know this identity, translated the corresponding TLD
1400  // TODO: We might want to have a reverse lookup functionality for TLDs?
1401  for (tmp_ego = handle->ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next)
1402  {
1403  priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego);
1404  GNUNET_CRYPTO_ecdsa_key_get_public (priv_key, &pkey);
1405  if (0 == GNUNET_memcmp (&pkey, &handle->oidc->client_pkey))
1406  {
1407  handle->tld = GNUNET_strdup (tmp_ego->identifier);
1408  handle->ego_entry = handle->ego_tail;
1409  }
1410  }
1411  if (NULL == handle->tld)
1413  if (NULL == handle->tld)
1414  handle->tld = GNUNET_strdup (handle->oidc->client_id);
1416 }
1417 
1425 static void
1427  const char *url,
1428  void *cls)
1429 {
1430  struct MHD_Response *resp = GNUNET_REST_create_response ("");
1431  struct RequestHandle *handle = cls;
1432  struct GNUNET_HashCode cache_key;
1433  struct GNUNET_TIME_Absolute *current_time;
1434  struct GNUNET_TIME_Absolute *last_time;
1435  char *cookie;
1436  char *header_val;
1437  json_t *root;
1438  json_error_t error;
1439  json_t *identity;
1440  char term_data[handle->rest_handle->data_size + 1];
1441  term_data[handle->rest_handle->data_size] = '\0';
1442  GNUNET_memcpy (term_data,
1443  handle->rest_handle->data,
1444  handle->rest_handle->data_size);
1445  root = json_loads (term_data, JSON_DECODE_ANY, &error);
1446  identity = json_object_get (root, "identity");
1447  if (! json_is_string (identity))
1448  {
1450  "Error parsing json string from %s\n",
1451  term_data);
1452  handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
1453  json_decref (root);
1455  return;
1456  }
1457  GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity));
1458  GNUNET_asprintf (&header_val,
1459  "%s;Max-Age=%d",
1460  cookie,
1462  MHD_add_response_header (resp, "Set-Cookie", header_val);
1463  MHD_add_response_header (resp, "Access-Control-Allow-Methods", "POST");
1464  GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key);
1465 
1466  if (0 != strcmp (json_string_value (identity), "Denied"))
1467  {
1468  current_time = GNUNET_new (struct GNUNET_TIME_Absolute);
1469  *current_time = GNUNET_TIME_relative_to_absolute (
1472  last_time =
1473  GNUNET_CONTAINER_multihashmap_get (OIDC_cookie_jar_map, &cache_key);
1474  GNUNET_free_non_null (last_time);
1475  GNUNET_CONTAINER_multihashmap_put (OIDC_cookie_jar_map,
1476  &cache_key,
1477  current_time,
1479  }
1480  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1481  GNUNET_free (cookie);
1482  GNUNET_free (header_val);
1483  json_decref (root);
1485 }
1486 
1487 static int
1489  struct GNUNET_CRYPTO_EcdsaPublicKey *cid)
1490 {
1491  struct GNUNET_HashCode cache_key;
1492  char *authorization;
1493  char *credentials;
1494  char *basic_authorization;
1495  char *client_id;
1496  char *pass;
1497  char *expected_pass;
1498 
1501  &cache_key);
1503  ->header_param_map,
1504  &cache_key))
1505  {
1507  handle->edesc = GNUNET_strdup ("missing authorization");
1508  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1509  return GNUNET_SYSERR;
1510  }
1511  authorization =
1513  &cache_key);
1514 
1515  // split header in "Basic" and [content]
1516  credentials = strtok (authorization, " ");
1517  if ((NULL == credentials) || (0 != strcmp ("Basic", credentials)))
1518  {
1520  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1521  return GNUNET_SYSERR;
1522  }
1523  credentials = strtok (NULL, " ");
1524  if (NULL == credentials)
1525  {
1527  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1528  return GNUNET_SYSERR;
1529  }
1530  GNUNET_STRINGS_base64_decode (credentials,
1531  strlen (credentials),
1532  (void **) &basic_authorization);
1533 
1534  if (NULL == basic_authorization)
1535  {
1537  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1538  return GNUNET_SYSERR;
1539  }
1540  client_id = strtok (basic_authorization, ":");
1541  if (NULL == client_id)
1542  {
1543  GNUNET_free_non_null (basic_authorization);
1545  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1546  return GNUNET_SYSERR;
1547  }
1548  pass = strtok (NULL, ":");
1549  if (NULL == pass)
1550  {
1551  GNUNET_free_non_null (basic_authorization);
1553  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1554  return GNUNET_SYSERR;
1555  }
1556 
1557  // check client password
1559  "reclaim-rest-plugin",
1560  "OIDC_CLIENT_SECRET",
1561  &expected_pass))
1562  {
1563  if (0 != strcmp (expected_pass, pass))
1564  {
1565  GNUNET_free_non_null (basic_authorization);
1566  GNUNET_free (expected_pass);
1568  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1569  return GNUNET_SYSERR;
1570  }
1571  GNUNET_free (expected_pass);
1572  }
1573  else
1574  {
1575  GNUNET_free_non_null (basic_authorization);
1577  handle->edesc = GNUNET_strdup ("gnunet configuration failed");
1578  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1579  return GNUNET_SYSERR;
1580  }
1581 
1582  // check client_id
1583  for (handle->ego_entry = handle->ego_head; NULL != handle->ego_entry;
1584  handle->ego_entry = handle->ego_entry->next)
1585  {
1586  if (0 == strcmp (handle->ego_entry->keystring, client_id))
1587  break;
1588  }
1589  if (NULL == handle->ego_entry)
1590  {
1591  GNUNET_free_non_null (basic_authorization);
1593  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1594  return GNUNET_SYSERR;
1595  }
1596  GNUNET_STRINGS_string_to_data (client_id,
1597  strlen (client_id),
1598  cid,
1599  sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
1600 
1601  GNUNET_free (basic_authorization);
1602  return GNUNET_OK;
1603 }
1604 
1605 const struct EgoEntry *
1607  struct GNUNET_CRYPTO_EcdsaPublicKey *test_key)
1608 {
1609  struct EgoEntry *ego_entry;
1610  struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
1611 
1612  for (ego_entry = handle->ego_head; NULL != ego_entry;
1613  ego_entry = ego_entry->next)
1614  {
1615  GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key);
1616  if (0 == GNUNET_memcmp (&pub_key, test_key))
1617  return ego_entry;
1618  }
1619  return NULL;
1620 }
1621 
1622 static void
1624  const char *access_token,
1625  const struct GNUNET_RECLAIM_Ticket *ticket)
1626 {
1627  struct GNUNET_HashCode hc;
1628  struct GNUNET_RECLAIM_Ticket *ticketbuf;
1629 
1630  GNUNET_CRYPTO_hash (access_token, strlen (access_token), &hc);
1631  ticketbuf = GNUNET_new (struct GNUNET_RECLAIM_Ticket);
1632  *ticketbuf = *ticket;
1635  OIDC_access_token_map,
1636  &hc,
1637  ticketbuf,
1639 }
1640 
1648 static void
1650  const char *url,
1651  void *cls)
1652 {
1653  struct RequestHandle *handle = cls;
1654  const struct EgoEntry *ego_entry;
1655  struct GNUNET_TIME_Relative expiration_time;
1657  struct GNUNET_RECLAIM_Ticket ticket;
1658  struct GNUNET_CRYPTO_EcdsaPublicKey cid;
1659  const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
1660  struct GNUNET_HashCode cache_key;
1661  struct MHD_Response *resp;
1662  char *grant_type;
1663  char *code;
1664  char *json_response;
1665  char *id_token;
1666  char *access_token;
1667  char *jwt_secret;
1668  char *nonce;
1669 
1670  /*
1671  * Check Authorization
1672  */
1673  if (GNUNET_SYSERR == check_authorization (handle, &cid))
1674  {
1676  "OIDC authorization for token endpoint failed\n");
1678  return;
1679  }
1680 
1681  /*
1682  * Check parameter
1683  */
1684 
1685  // TODO Do not allow multiple equal parameter names
1686  // REQUIRED grant_type
1688  strlen (OIDC_GRANT_TYPE_KEY),
1689  &cache_key);
1690  grant_type = get_url_parameter_copy (handle, OIDC_GRANT_TYPE_KEY);
1691  if (NULL == grant_type)
1692  {
1694  handle->edesc = GNUNET_strdup ("missing parameter grant_type");
1695  handle->response_code = MHD_HTTP_BAD_REQUEST;
1697  return;
1698  }
1699 
1700  // Check parameter grant_type == "authorization_code"
1701  if (0 != strcmp (OIDC_GRANT_TYPE_VALUE, grant_type))
1702  {
1704  handle->response_code = MHD_HTTP_BAD_REQUEST;
1705  GNUNET_free (grant_type);
1707  return;
1708  }
1709  GNUNET_free (grant_type);
1710  // REQUIRED code
1711  code = get_url_parameter_copy (handle, OIDC_CODE_KEY);
1712  if (NULL == code)
1713  {
1715  handle->edesc = GNUNET_strdup ("missing parameter code");
1716  handle->response_code = MHD_HTTP_BAD_REQUEST;
1718  return;
1719  }
1720  ego_entry = find_ego (handle, &cid);
1721  if (NULL == ego_entry)
1722  {
1724  handle->edesc = GNUNET_strdup ("Unknown client");
1725  handle->response_code = MHD_HTTP_BAD_REQUEST;
1726  GNUNET_free (code);
1728  return;
1729  }
1730  privkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1731  // decode code
1732  if (GNUNET_OK != OIDC_parse_authz_code (privkey, code, &ticket, &cl, &nonce))
1733  {
1735  handle->edesc = GNUNET_strdup ("invalid code");
1736  handle->response_code = MHD_HTTP_BAD_REQUEST;
1737  GNUNET_free (code);
1739  return;
1740  }
1741  GNUNET_free (code);
1742 
1743  // create jwt
1745  "reclaim-rest-plugin",
1746  "expiration_time",
1747  &expiration_time))
1748  {
1750  handle->edesc = GNUNET_strdup ("gnunet configuration failed");
1751  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1753  return;
1754  }
1755 
1756 
1757  // TODO OPTIONAL acr,amr,azp
1759  "reclaim-rest-plugin",
1760  "jwt_secret",
1761  &jwt_secret))
1762  {
1764  handle->edesc = GNUNET_strdup ("No signing secret configured!");
1765  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
1767  return;
1768  }
1769  id_token = OIDC_id_token_new (&ticket.audience,
1770  &ticket.identity,
1771  cl,
1772  &expiration_time,
1773  (NULL != nonce) ? nonce : NULL,
1774  jwt_secret);
1775  access_token = OIDC_access_token_new ();
1776  OIDC_build_token_response (access_token,
1777  id_token,
1778  &expiration_time,
1779  &json_response);
1780 
1781  persist_access_token (handle, access_token, &ticket);
1782  resp = GNUNET_REST_create_response (json_response);
1783  MHD_add_response_header (resp, "Cache-Control", "no-store");
1784  MHD_add_response_header (resp, "Pragma", "no-cache");
1785  MHD_add_response_header (resp, "Content-Type", "application/json");
1786  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1788  GNUNET_free (access_token);
1789  GNUNET_free (json_response);
1790  GNUNET_free (id_token);
1792 }
1793 
1797 static void
1798 consume_ticket (void *cls,
1799  const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
1800  const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
1801 {
1802  struct RequestHandle *handle = cls;
1803  char *tmp_value;
1804  json_t *value;
1805 
1806  if (NULL == identity)
1807  {
1809  return;
1810  }
1812  attr->data,
1813  attr->data_size);
1814  value = json_string (tmp_value);
1815  json_object_set_new (handle->oidc->response, attr->name, value);
1816  GNUNET_free (tmp_value);
1817 }
1818 
1826 static void
1828  const char *url,
1829  void *cls)
1830 {
1831  // TODO expiration time
1832  struct RequestHandle *handle = cls;
1833  char delimiter[] = " ";
1834  struct GNUNET_HashCode cache_key;
1835  char *authorization;
1836  char *authorization_type;
1837  char *authorization_access_token;
1838  struct GNUNET_RECLAIM_Ticket *ticket;
1839  const struct EgoEntry *ego_entry;
1840  const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
1841 
1844  &cache_key);
1846  ->header_param_map,
1847  &cache_key))
1848  {
1850  handle->edesc = GNUNET_strdup ("No Access Token");
1851  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1853  return;
1854  }
1855  authorization =
1857  &cache_key);
1858 
1859  // split header in "Bearer" and access_token
1860  authorization = GNUNET_strdup (authorization);
1861  authorization_type = strtok (authorization, delimiter);
1862  if ((NULL == authorization_type) ||
1863  (0 != strcmp ("Bearer", authorization_type)))
1864  {
1866  handle->edesc = GNUNET_strdup ("No Access Token");
1867  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1869  GNUNET_free (authorization);
1870  return;
1871  }
1872  authorization_access_token = strtok (NULL, delimiter);
1873  if (NULL == authorization_access_token)
1874  {
1876  handle->edesc = GNUNET_strdup ("Access token missing");
1877  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1879  GNUNET_free (authorization);
1880  return;
1881  }
1882 
1883  GNUNET_CRYPTO_hash (authorization_access_token,
1884  strlen (authorization_access_token),
1885  &cache_key);
1886  if (GNUNET_NO ==
1887  GNUNET_CONTAINER_multihashmap_contains (OIDC_access_token_map,
1888  &cache_key))
1889  {
1891  handle->edesc = GNUNET_strdup ("The access token expired");
1892  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1894  GNUNET_free (authorization);
1895  return;
1896  }
1897  ticket =
1898  GNUNET_CONTAINER_multihashmap_get (OIDC_access_token_map, &cache_key);
1899  GNUNET_assert (NULL != ticket);
1900  ego_entry = find_ego (handle, &ticket->audience);
1901  if (NULL == ego_entry)
1902  {
1904  handle->edesc = GNUNET_strdup ("The access token expired");
1905  handle->response_code = MHD_HTTP_UNAUTHORIZED;
1907  GNUNET_free (authorization);
1908  return;
1909  }
1910 
1911  handle->idp = GNUNET_RECLAIM_connect (cfg);
1912  handle->oidc->response = json_object ();
1913  json_object_set_new (handle->oidc->response,
1914  "sub",
1915  json_string (ego_entry->keystring));
1916  privkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1917  handle->idp_op = GNUNET_RECLAIM_ticket_consume (handle->idp,
1918  privkey,
1919  ticket,
1921  handle);
1922  GNUNET_free (authorization);
1923 }
1924 
1925 
1931 static void
1933 {
1935  static const struct GNUNET_REST_RequestHandler handlers[] =
1936  {{MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint},
1937  {MHD_HTTP_METHOD_POST,
1939  &authorize_endpoint}, // url-encoded
1940  {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont},
1941  {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint},
1942  {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint},
1943  {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint},
1944  {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, &options_cont},
1946 
1947  if (GNUNET_NO ==
1948  GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
1949  {
1950  handle->response_code = err.error_code;
1952  }
1953 }
1954 
1988 static void
1989 list_ego (void *cls,
1990  struct GNUNET_IDENTITY_Ego *ego,
1991  void **ctx,
1992  const char *identifier)
1993 {
1994  struct RequestHandle *handle = cls;
1995  struct EgoEntry *ego_entry;
1996  struct GNUNET_CRYPTO_EcdsaPublicKey pk;
1997 
1998  if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
1999  {
2000  handle->state = ID_REST_STATE_POST_INIT;
2001  init_cont (handle);
2002  return;
2003  }
2004  GNUNET_assert (NULL != ego);
2005  if (ID_REST_STATE_INIT == handle->state)
2006  {
2007  ego_entry = GNUNET_new (struct EgoEntry);
2010  ego_entry->ego = ego;
2011  ego_entry->identifier = GNUNET_strdup (identifier);
2013  handle->ego_tail,
2014  ego_entry);
2015  return;
2016  }
2017  /* Ego renamed or added */
2018  if (identifier != NULL)
2019  {
2020  for (ego_entry = handle->ego_head; NULL != ego_entry;
2021  ego_entry = ego_entry->next)
2022  {
2023  if (ego_entry->ego == ego)
2024  {
2025  /* Rename */
2026  GNUNET_free (ego_entry->identifier);
2027  ego_entry->identifier = GNUNET_strdup (identifier);
2028  break;
2029  }
2030  }
2031  if (NULL == ego_entry)
2032  {
2033  /* Add */
2034  ego_entry = GNUNET_new (struct EgoEntry);
2037  ego_entry->ego = ego;
2038  ego_entry->identifier = GNUNET_strdup (identifier);
2040  handle->ego_tail,
2041  ego_entry);
2042  }
2043  }
2044  else
2045  {
2046  /* Delete */
2047  for (ego_entry = handle->ego_head; NULL != ego_entry;
2048  ego_entry = ego_entry->next)
2049  {
2050  if (ego_entry->ego == ego)
2051  break;
2052  }
2053  if (NULL != ego_entry)
2055  handle->ego_tail,
2056  ego_entry);
2057  }
2058 }
2059 
2060 static void
2063  void *proc_cls)
2064 {
2065  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
2066  handle->oidc = GNUNET_new (struct OIDC_Variables);
2067  if (NULL == OIDC_cookie_jar_map)
2068  OIDC_cookie_jar_map = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
2069  if (NULL == OIDC_access_token_map)
2070  OIDC_access_token_map =
2072  handle->response_code = 0;
2074  handle->proc_cls = proc_cls;
2075  handle->proc = proc;
2076  handle->state = ID_REST_STATE_INIT;
2077  handle->rest_handle = rest_handle;
2078 
2079  handle->url = GNUNET_strdup (rest_handle->url);
2080  if (handle->url[strlen (handle->url) - 1] == '/')
2081  handle->url[strlen (handle->url) - 1] = '\0';
2082  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
2083  handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, handle);
2084  handle->gns_handle = GNUNET_GNS_connect (cfg);
2086  handle->timeout_task =
2087  GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
2088  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
2089 }
2090 
2097 void *
2099 {
2100  static struct Plugin plugin;
2101  struct GNUNET_REST_Plugin *api;
2102 
2103  cfg = cls;
2104  if (NULL != plugin.cfg)
2105  return NULL; /* can only initialize once! */
2106  memset (&plugin, 0, sizeof (struct Plugin));
2107  plugin.cfg = cfg;
2108  api = GNUNET_new (struct GNUNET_REST_Plugin);
2109  api->cls = &plugin;
2113  "%s, %s, %s, %s, %s",
2114  MHD_HTTP_METHOD_GET,
2115  MHD_HTTP_METHOD_POST,
2116  MHD_HTTP_METHOD_PUT,
2117  MHD_HTTP_METHOD_DELETE,
2118  MHD_HTTP_METHOD_OPTIONS);
2119 
2121  _ ("OpenID Connect REST API initialized\n"));
2122  return api;
2123 }
2124 
2125 
2132 void *
2134 {
2135  struct GNUNET_REST_Plugin *api = cls;
2136  struct Plugin *plugin = api->cls;
2137  plugin->cfg = NULL;
2138 
2139  struct GNUNET_CONTAINER_MultiHashMapIterator *hashmap_it;
2140  void *value = NULL;
2141  hashmap_it =
2142  GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_cookie_jar_map);
2143  while (GNUNET_YES ==
2144  GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value))
2145  GNUNET_free_non_null (value);
2147  GNUNET_CONTAINER_multihashmap_destroy (OIDC_cookie_jar_map);
2148 
2149  hashmap_it =
2150  GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_access_token_map);
2151  while (GNUNET_YES ==
2152  GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value))
2153  GNUNET_free_non_null (value);
2154  GNUNET_CONTAINER_multihashmap_destroy (OIDC_access_token_map);
2157  GNUNET_free (api);
2159  "OpenID Connect REST plugin is finished\n");
2160  return NULL;
2161 }
2162 
2163 /* 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:528
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
static void build_redirect(void *cls)
static int iterator(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Iterator over hash map entries.
const char * name
The name of the attribute.
struct GNUNET_RECLAIM_ATTRIBUTE_Claim * claim
The attribute claim.
Connection to the GNS service.
Definition: gns_api.h:35
void GNUNET_CONTAINER_multihashmap_iterator_destroy(struct GNUNET_CONTAINER_MultiHashMapIterator *iter)
Destroy a multihashmap iterator.
char * GNUNET_RECLAIM_ATTRIBUTE_value_to_string(uint32_t type, const void *data, size_t data_size)
Convert the &#39;claim&#39; of an attribute to a string.
char * redirect_uri
The OIDC redirect uri.
char * scope
The list of oidc scopes.
Handle to the service.
Definition: reclaim_api.c:238
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.
int GNUNET_CONTAINER_multihashmap_iterator_next(struct GNUNET_CONTAINER_MultiHashMapIterator *iter, struct GNUNET_HashCode *key, const void **value)
Retrieve the next element from the hash map at the iterator&#39;s position.
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:953
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 EgoEntry * ego_tail
Ego list.
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.
If a value with the given key exists, replace it.
char * nonce
The OIDC nonce.
size_t data_size
Number of bytes in data.
#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.
struct GNUNET_CONTAINER_MultiHashMapIterator * GNUNET_CONTAINER_multihashmap_iterator_create(const struct GNUNET_CONTAINER_MultiHashMap *map)
Create an iterator for a multihashmap.
void * cls
The closure of the plugin.
struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry * list_tail
List tail.
size_t data_size
The POST data size.
struct GNUNET_RECLAIM_AttributeIterator * attr_it
Attribute iterator.
static void cookie_identity_interpretation(struct RequestHandle *handle)
Interprets cookie header and pass its identity keystring to handle.
static void persist_access_token(const struct RequestHandle *handle, const char *access_token, const struct GNUNET_RECLAIM_Ticket *ticket)
#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:245
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define OIDC_REDIRECT_URI_KEY
OIDC redirect_uri key.
#define OIDC_ERROR_KEY_UNAUTHORIZED_CLIENT
OIDC error key for unauthorized clients.
struct GNUNET_GNS_LookupRequest * gns_op
GNS lookup op.
char * key
TLS key.
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Handle to a lookup request.
Definition: gns_api.c:42
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:556
void GNUNET_RECLAIM_disconnect(struct GNUNET_RECLAIM_Handle *h)
Disconnect from identity provider service.
Definition: reclaim_api.c:819
#define OIDC_COOKIE_EXPIRATION
OIDC cookie expiration (in seconds)
struct returned by the initialization function of the plugin
static void oidc_ticket_issue_cb(void *cls, const struct GNUNET_RECLAIM_Ticket *ticket)
Issues ticket and redirects to relying party with the authorization code as parameter.
helper library for OIDC related functions
#define GNUNET_NO
Definition: gnunet_common.h:81
#define OIDC_COOKIE_HEADER_INFORMATION_KEY
OIDC cookie header information key.
void GNUNET_RECLAIM_ticket_iteration_stop(struct GNUNET_RECLAIM_TicketIterator *it)
Stops iteration and releases the handle for further calls.
Definition: reclaim_api.c:1207
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
size_t data_size
Number of bytes in data.
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
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.
static void rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
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:999
#define OIDC_ERROR_KEY_INVALID_TOKEN
OIDC error key for invalid tokens.
void * libgnunet_plugin_rest_openid_connect_init(void *cls)
Entry point for the plugin.
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(* process_request)(struct GNUNET_REST_RequestHandle *handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function to process a REST call.
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:620
#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
#define OIDC_STATE_KEY
OIDC state key.
The request handle.
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:208
static char * section
Name of the section.
Definition: gnunet-config.c:33
const void * data
Binary value stored as attribute value.
#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.
void GNUNET_NAMESTORE_disconnect(struct GNUNET_NAMESTORE_Handle *h)
Disconnect from the namestore service (and free associated resources).
OIDC needed variables.
static struct GNUNET_ATS_SolverFunctions * plugin
Our solver.
void GNUNET_RECLAIM_ATTRIBUTE_list_destroy(struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
Destroy claim list.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
Handle for a zone iterator operation.
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:1246
Handle for an ego.
Definition: identity.h:245
Handle for a attribute iterator operation.
Definition: reclaim_api.c:169
enum State state
current state of profiling
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
User defined timestamp for completing operations.
Definition: gnunet-arm.c:114
#define GNUNET_memcpy(dst, src, n)
static char * value
Value of the record to add/remove.
char * emsg
Error response message.
struct GNUNET_CONTAINER_MultiHashMap * url_param_map
Map of url parameters.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
const char * url
The url as string.
char * client_id
The OIDC client id of the RP.
Connection to the NAMESTORE service.
Handle for the service.
Definition: identity_api.c:96
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
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:1273
char * name
Plugin name.
void GNUNET_GNS_disconnect(struct GNUNET_GNS_Handle *handle)
Shutdown connection with the GNS service.
Definition: gns_api.c:285
#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
Timeout.
static void lookup_redirect_uri_result(void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd)
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_ATTRIBUTE_ClaimList *attrs, GNUNET_RECLAIM_TicketCallback cb, void *cb_cls)
Issues a ticket to a relying party.
Definition: reclaim_api.c:1051
struct GNUNET_RECLAIM_TicketIterator * ticket_it
Ticket iterator.
char * tld
The tld for redirect.
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
static struct GNUNET_IDENTITY_Handle * identity_handle
Identity handle.
#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:439
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
char * OIDC_build_authz_code(const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, const struct GNUNET_RECLAIM_Ticket *ticket, struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, const char *nonce_str)
Builds an OIDC authorization code including a reclaim ticket and nonce.
Definition: oidc_helper.c:386
void GNUNET_IDENTITY_disconnect(struct GNUNET_IDENTITY_Handle *h)
Disconnect from identity service.
Definition: identity_api.c:838
struct GNUNET_GNS_Handle * GNUNET_GNS_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Initialize the connection with the GNS service.
Definition: gns_api.c:263
#define OIDC_ERROR_KEY_UNSUPPORTED_RESPONSE_TYPE
OIDC error key for unsupported response types.
static void init_cont(struct RequestHandle *handle)
Handle rest request.
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:76
static void cleanup_handle(struct RequestHandle *handle)
Cleanup lookup handle.
struct GNUNET_REST_RequestHandle * rest_handle
Handle to rest request.
A 512-bit hashcode.
int response_code
HTTP response code.
int state
The processing state.
static void login_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Combines an identity with a login time and responds OK to login request.
static void code_redirect(void *cls)
Checks time and cookie and redirects accordingly.
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:2067
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:334
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.
int OIDC_parse_authz_code(const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv, const char *code, struct GNUNET_RECLAIM_Ticket *ticket, struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList **attrs, char **nonce_str)
Parse reclaim ticket and nonce from authorization code.
Definition: oidc_helper.c:514
struct GNUNET_CRYPTO_EcdsaPublicKey identity
The ticket issuer (= the user)
char * keystring
Public key string.
struct GNUNET_RECLAIM_Handle * idp
Identity Provider.
static struct GNUNET_IDENTITY_Handle * identity
Which namespace do we publish to? NULL if we do not publish to a namespace.
struct GNUNET_CONTAINER_MultiHashMap * OIDC_access_token_map
Hash map that links the issued access token to the corresponding ticket and ego.
There must only be one value per key; storing a value should fail if a value under the same key alrea...
struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList * attr_list
Attribute claim list.
static void return_userinfo_response(void *cls)
Return attributes for claim.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
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:241
#define OIDC_ERROR_KEY_ACCESS_DENIED
OIDC error key for denied access.
static void userinfo_endpoint(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Responds to userinfo GET and url-encoded POST request.
struct GNUNET_NAMESTORE_Handle * GNUNET_NAMESTORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the namestore service.
#define OIDC_AUTHORIZATION_HEADER_KEY
OIDC cookie header information key.
static void oidc_attr_collect(void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
Collects all attributes for an ego if in scope parameter.
#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:119
static char * OIDC_ignored_parameter_array[]
OIDC ignored parameter array.
static struct Ego * ego_head
Head of DLL of all egos.
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.
static void consume_ticket(void *cls, const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
Collects claims and stores them in handle.
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.
void GNUNET_IDENTITY_ego_get_public_key(const struct GNUNET_IDENTITY_Ego *ego, struct GNUNET_CRYPTO_EcdsaPublicKey *pk)
Get the identifier (public key) of an ego.
Definition: identity_api.c:569
#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.
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.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
static void cleanup_handle_delayed(void *cls)
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.
char * OIDC_access_token_new()
Generate a new access token.
Definition: oidc_helper.c:647
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:468
struct GNUNET_GNS_Handle * gns_handle
GNS handle.
configuration data
Definition: configuration.c:85
struct EgoEntry * ego_head
Ego list.
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:1020
struct GNUNET_RECLAIM_ATTRIBUTE_Claim * GNUNET_RECLAIM_ATTRIBUTE_claim_new(const char *attr_name, uint32_t type, const void *data, size_t data_size)
Create a new attribute claim.
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 void token_endpoint(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Responds to token url-encoded POST request.
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:56
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and ECDS...
A list of GNUNET_RECLAIM_ATTRIBUTE_Claim structures.
Handle for a ticket iterator operation.
Definition: reclaim_api.c:105
#define GNUNET_log(kind,...)
const struct GNUNET_CONFIGURATION_Handle * cfg
The configuration handle.
Entry in list of pending tasks.
Definition: scheduler.c:134
#define OIDC_SCOPE_KEY
OIDC scope key.
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:309
#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.
struct GNUNET_NAMESTORE_ZoneIterator * namestore_handle_it
Iterator for NAMESTORE.
#define OIDC_CLIENT_ID_KEY
OIDC client_id key.
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_AttributeResult cb, void *cb_cls)
Consumes an issued ticket.
Definition: reclaim_api.c:1099
Time for absolute times used by GNUnet, in microseconds.
json_t * response
The response JSON.
#define GNUNET_YES
Definition: gnunet_common.h:80
struct GNUNET_CONTAINER_MultiHashMap * header_param_map
Map of headers.
Defaults, look in cache, then in DHT.
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:988
static void oidc_collect_finished_cb(void *cls)
void * libgnunet_plugin_rest_openid_connect_done(void *cls)
Exit point from the plugin.
static struct Ego * ego_tail
Tail of DLL of all egos.
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:139
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:337
static void oidc_iteration_error(void *cls)
Does internal server error when iteration failed.
struct GNUNET_RECLAIM_Handle * GNUNET_RECLAIM_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the re:claimID service.
Definition: reclaim_api.c:779
uint32_t data
The data value.
struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry * next
DLL.
static size_t data_size
Number of bytes in data.
#define OIDC_COOKIE_HEADER_KEY
OIDC cookie header key.
struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry * list_head
List head.
char * OIDC_id_token_new(const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, const struct GNUNET_CRYPTO_EcdsaPublicKey *sub_key, const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, const struct GNUNET_TIME_Relative *expiration_time, const char *nonce, const char *secret_key)
Create a JWT from attributes.
Definition: oidc_helper.c:84
struct EgoEntry * next
DLL.
#define GNUNET_REST_API_NS_USERINFO
UserInfo endpoint.
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:1021
struct GNUNET_IDENTITY_Handle * identity_handle
Handle to Identity service.
#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.
#define OIDC_ERROR_KEY_INVALID_SCOPE
OIDC error key for invalid scopes.
#define GNUNET_REST_API_NS_TOKEN
Token endpoint.
struct GNUNET_NAMESTORE_Handle * namestore_handle
Handle to NAMESTORE.
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:965
char * url
The url.