GNUnet  0.19.3
oidc_helper.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2010-2015 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  */
20 
27 #include "platform.h"
28 #include <inttypes.h>
29 #include <jansson.h>
30 #include <jose/jose.h>
31 #include "gnunet_util_lib.h"
32 #include "gnunet_reclaim_lib.h"
33 #include "gnunet_reclaim_service.h"
34 #include "gnunet_signatures.h"
35 #include "oidc_helper.h"
36 // #include "benchmark.h"
37 #include <gcrypt.h>
38 
40 
45 {
50 
55 
60 
65 
70 };
71 
73 
77 static char OIDC_profile_claims[14][32] = {
78  "name", "family_name", "given_name", "middle_name", "nickname",
79  "preferred_username", "profile", "picture", "website", "gender", "birthdate",
80  "zoneinfo", "locale", "updated_at"
81 };
82 
86 static char OIDC_email_claims[2][16] = {
87  "email", "email_verified"
88 };
89 
93 static char OIDC_phone_claims[2][32] = {
94  "phone_number", "phone_number_verified"
95 };
96 
100 static char OIDC_address_claims[5][32] = {
101  "street_address", "locality", "region", "postal_code", "country"
102 };
103 
104 static enum GNUNET_GenericReturnValue
105 is_claim_in_address_scope (const char *claim)
106 {
107  int i;
108  for (i = 0; i < 5; i++)
109  {
110  if (0 == strcmp (claim, OIDC_address_claims[i]))
111  {
112  return GNUNET_YES;
113  }
114  }
115  return GNUNET_NO;
116 }
117 
118 
119 static char *
121 {
122  json_t *root;
123  char *json_str;
124 
125  root = json_object ();
126  json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE_HMAC));
127  json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE));
128 
129  json_str = json_dumps (root, JSON_INDENT (0) | JSON_COMPACT);
130  json_decref (root);
131  return json_str;
132 }
133 
134 
135 static void
136 replace_char (char *str, char find, char replace)
137 {
138  char *current_pos = strchr (str, find);
139 
140  while (current_pos)
141  {
142  *current_pos = replace;
143  current_pos = strchr (current_pos, find);
144  }
145 }
146 
147 
148 // RFC4648
149 static void
150 fix_base64 (char *str)
151 {
152  // Replace + with -
153  replace_char (str, '+', '-');
154 
155  // Replace / with _
156  replace_char (str, '/', '_');
157 }
158 
159 
160 static json_t*
162  const struct GNUNET_RECLAIM_AttributeList *attrs,
163  const struct
164  GNUNET_RECLAIM_PresentationList *presentations)
165 {
168  char *subject;
169  char *source_name;
170  char *attr_val_str;
171  char *pres_val_str;
172  json_t *body;
173  json_t *aggr_names;
174  json_t *aggr_sources;
175  json_t *aggr_sources_jwt;
176  json_t *addr_claim = NULL;
177  int num_presentations = 0;
178  for (le = attrs->list_head; NULL != le; le = le->next)
179  {
181  num_presentations++;
182  }
183 
184  subject =
186  sizeof(struct
188  body = json_object ();
189  aggr_names = json_object ();
190  aggr_sources = json_object ();
191 
192  // iss REQUIRED case sensitive server uri with https
193  // The issuer is the local reclaim instance (e.g.
194  // https://reclaim.id/api/openid)
195  json_object_set_new (body, "iss", json_string (SERVER_ADDRESS));
196  // sub REQUIRED public key identity, not exceed 255 ASCII length
197  json_object_set_new (body, "sub", json_string (subject));
199  pres_val_str = NULL;
200  source_name = NULL;
201  int i = 0;
202  for (ple = presentations->list_head; NULL != ple; ple = ple->next)
203  {
204  // New presentation
205  GNUNET_asprintf (&source_name,
206  "src%d",
207  i);
209  "Adding new presentation source #%d\n", i);
210  aggr_sources_jwt = json_object ();
211  pres_val_str =
213  ple->presentation->data,
214  ple->presentation->data_size);
216  "Presentation is: %s\n", pres_val_str);
217  json_object_set_new (aggr_sources_jwt,
219  ple->presentation->type),
220  json_string (pres_val_str) );
221  json_object_set_new (aggr_sources, source_name, aggr_sources_jwt);
222  GNUNET_free (pres_val_str);
223  GNUNET_free (source_name);
224  source_name = NULL;
225  i++;
226  }
227 
228  int addr_is_aggregated = GNUNET_NO;
229  int addr_is_normal = GNUNET_NO;
230  for (le = attrs->list_head; NULL != le; le = le->next)
231  {
233  "Processing %s for userinfo body\n",
234  le->attribute->name);
236  {
237  attr_val_str =
239  le->attribute->data,
240  le->attribute->data_size);
246  {
247  if (GNUNET_YES == addr_is_aggregated)
248  {
250  "Address is set as aggregated claim. Skipping self-issued value...\n");
251  GNUNET_free (attr_val_str);
252  continue;
253  }
254  addr_is_normal = GNUNET_YES;
255 
256  if (NULL == addr_claim)
257  {
258  addr_claim = json_object ();
259  json_object_set_new (body, "address", addr_claim);
260  }
261  json_object_set_new (addr_claim, le->attribute->name,
262  json_string (attr_val_str));
263 
264  }
265  else
266  {
267  json_object_set_new (body, le->attribute->name,
268  json_string (attr_val_str));
269  }
270  GNUNET_free (attr_val_str);
271  }
272  else
273  {
274  // Check if presentation is there
275  int j = 0;
276  for (ple = presentations->list_head; NULL != ple; ple = ple->next)
277  {
278  if (GNUNET_YES ==
280  &le->attribute->credential))
281  break;
282  j++;
283  }
284  if (NULL == ple)
285  {
287  "Presentation for `%s' missing...\n",
288  le->attribute->name);
289  continue;
290  }
296  {
297  if (GNUNET_YES == addr_is_normal)
298  {
300  "Address is already set as normal claim. Skipping attested value...\n");
301  continue;
302  }
303  addr_is_aggregated = GNUNET_YES;
305  if (NULL != addr_claim)
306  continue;
307  addr_claim = json_object ();
308  GNUNET_asprintf (&source_name,
309  "src%d",
310  j);
311  json_object_set_new (aggr_names, "address",
312  json_string (source_name));
313  GNUNET_free (source_name);
314  }
315  else
316  {
317  // Presentation exists, hence take the respective source str
318  GNUNET_asprintf (&source_name,
319  "src%d",
320  j);
321  json_object_set_new (aggr_names, le->attribute->name,
322  json_string (source_name));
323  GNUNET_free (source_name);
324  }
325  }
326  }
327  if (0 != i)
328  {
329  json_object_set_new (body, "_claim_names", aggr_names);
330  json_object_set_new (body, "_claim_sources", aggr_sources);
331  }
332 
333  return body;
334 }
335 
336 
345 char *
347  const struct GNUNET_RECLAIM_AttributeList *attrs,
348  const struct
349  GNUNET_RECLAIM_PresentationList *presentations)
350 {
351  char *body_str;
352  json_t*body = generate_userinfo_json (sub_key,
353  attrs,
354  presentations);
355  body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT);
356  json_decref (body);
357  return body_str;
358 }
359 
360 
361 char *
363  const struct GNUNET_IDENTITY_PublicKey *sub_key,
364  const struct GNUNET_RECLAIM_AttributeList *attrs,
365  const struct
366  GNUNET_RECLAIM_PresentationList *presentations,
367  const struct GNUNET_TIME_Relative *expiration_time,
368  const char *nonce)
369 {
370  struct GNUNET_TIME_Absolute exp_time;
371  struct GNUNET_TIME_Absolute time_now;
372  json_t *body;
373  char *audience;
374  char *subject;
375  char *body_str;
376 
377  body = generate_userinfo_json (sub_key,
378  attrs,
379  presentations);
380  // iat REQUIRED time now
381  time_now = GNUNET_TIME_absolute_get ();
382  // exp REQUIRED time expired from config
383  exp_time = GNUNET_TIME_absolute_add (time_now, *expiration_time);
384  // auth_time only if max_age
385  // nonce only if nonce
386  // OPTIONAL acr,amr,azp
387  subject =
389  sizeof(struct
391  audience =
393  sizeof(struct
395 
396  // aud REQUIRED public key client_id must be there
397  json_object_set_new (body, "aud", json_string (audience));
398  // iat
399  json_object_set_new (body,
400  "iat",
401  json_integer (time_now.abs_value_us / (1000 * 1000)));
402  // exp
403  json_object_set_new (body,
404  "exp",
405  json_integer (exp_time.abs_value_us / (1000 * 1000)));
406  // nbf
407  json_object_set_new (body,
408  "nbf",
409  json_integer (time_now.abs_value_us / (1000 * 1000)));
410  // nonce
411  if (NULL != nonce)
412  json_object_set_new (body, "nonce", json_string (nonce));
413 
414  // Error checking
415  body_str = json_dumps (body, JSON_INDENT (2) | JSON_COMPACT);
416  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"ID-Token: %s\n", body_str);
417 
418  json_decref (body);
420  GNUNET_free (audience);
421 
422  return body_str;
423 }
424 
425 
426 char *
428  const struct GNUNET_IDENTITY_PublicKey *sub_key,
429  const struct GNUNET_RECLAIM_AttributeList *attrs,
430  const struct
431  GNUNET_RECLAIM_PresentationList *presentations,
432  const struct GNUNET_TIME_Relative *expiration_time,
433  const char *nonce,
434  const json_t *secret_rsa_key)
435 {
436  json_t *jws;
437  char *body_str;
438  char *result;
439 
440  // Generate the body of the JSON Web Signature
441  body_str = generate_id_token_body (aud_key,
442  sub_key,
443  attrs,
444  presentations,
445  expiration_time,
446  nonce);
447 
448  if (NULL == body_str)
449  {
451  "Body for the JWS could not be generated\n");
452  return NULL;
453  }
454 
455  // Creating the JSON Web Signature.
456  jws = json_pack ("{s:o}", "payload",
457  jose_b64_enc (body_str, strlen (body_str)));
458  GNUNET_free (body_str);
459 
460  if (! jose_jws_sig (NULL, jws, NULL, secret_rsa_key))
461  {
463  "Signature generation failed\n");
464  return NULL;
465  }
466 
467  // Encoding JSON as compact JSON Web Signature
468  GNUNET_asprintf (&result, "%s.%s.%s",
469  json_string_value (json_object_get (jws, "protected")),
470  json_string_value (json_object_get (jws, "payload")),
471  json_string_value (json_object_get (jws, "signature")) );
472 
473  json_decref (jws);
474  return result;
475 }
476 
488 char *
490  const struct GNUNET_IDENTITY_PublicKey *sub_key,
491  const struct GNUNET_RECLAIM_AttributeList *attrs,
492  const struct
493  GNUNET_RECLAIM_PresentationList *presentations,
494  const struct GNUNET_TIME_Relative *expiration_time,
495  const char *nonce,
496  const char *secret_key)
497 {
498  struct GNUNET_HashCode signature;
499  char *header;
500  char *header_base64;
501  char *body_str;
502  char *body_base64;
503  char *signature_target;
504  char *signature_base64;
505  char *result;
506 
507  // Generate and encode Header
508  header = create_jwt_hmac_header ();
509  if (NULL == header)
510  {
512  "Header for the JWS could not be generated\n");
513  return NULL;
514  }
515  GNUNET_STRINGS_base64url_encode (header, strlen (header), &header_base64);
516  GNUNET_free (header);
517  fix_base64 (header_base64);
518 
519  // Generate and encode the body of the JSON Web Signature
520  body_str = generate_id_token_body (aud_key,
521  sub_key,
522  attrs,
523  presentations,
524  expiration_time,
525  nonce);
526 
527  if (NULL == body_str)
528  {
530  "Body for the JWS could not be generated\n");
531  GNUNET_free (header_base64);
532  return NULL;
533  }
534 
535  GNUNET_STRINGS_base64url_encode (body_str, strlen (body_str), &body_base64);
536  fix_base64 (body_base64);
537 
542  GNUNET_asprintf (&signature_target, "%s.%s", header_base64, body_base64);
543  GNUNET_CRYPTO_hmac_raw (secret_key,
544  strlen (secret_key),
545  signature_target,
546  strlen (signature_target),
547  &signature);
548  GNUNET_STRINGS_base64url_encode ((const char *) &signature,
549  sizeof(struct GNUNET_HashCode),
550  &signature_base64);
551  fix_base64 (signature_base64);
552 
554  "%s.%s.%s",
555  header_base64,
556  body_base64,
557  signature_base64);
558 
559  GNUNET_free (header_base64);
560  GNUNET_free (body_str);
561  GNUNET_free (body_base64);
562  GNUNET_free (signature_target);
563  GNUNET_free (signature_base64);
564  return result;
565 }
566 
567 
580 char *
582  const struct GNUNET_RECLAIM_Ticket *ticket,
583  const struct GNUNET_RECLAIM_AttributeList *attrs,
584  const struct
585  GNUNET_RECLAIM_PresentationList *presentations,
586  const char *nonce_str,
587  const char *code_challenge)
588 {
589  struct OIDC_Parameters params;
590  char *code_payload;
591  char *payload;
592  char *tmp;
593  char *code_str;
594  char *buf_ptr = NULL;
595  size_t payload_len;
596  size_t code_payload_len;
597  size_t attr_list_len = 0;
598  size_t pres_list_len = 0;
599  size_t code_challenge_len = 0;
600  uint32_t nonce_len = 0;
602 
604  // Assign ticket
605  memset (&params, 0, sizeof(params));
606  params.ticket = *ticket;
607  // Assign nonce
608  payload_len = sizeof(struct OIDC_Parameters);
609  if ((NULL != nonce_str) && (strcmp ("", nonce_str) != 0))
610  {
611  nonce_len = strlen (nonce_str);
612  payload_len += nonce_len;
613  }
614  params.nonce_len = htonl (nonce_len);
615  // Assign code challenge
616  if (NULL != code_challenge)
617  code_challenge_len = strlen (code_challenge);
618  payload_len += code_challenge_len;
619  params.code_challenge_len = htonl (code_challenge_len);
620  // Assign attributes
621  if (NULL != attrs)
622  {
623  // Get length
625  params.attr_list_len = htonl (attr_list_len);
627  "Length of serialized attributes: %lu\n",
628  attr_list_len);
629  // Get serialized attributes
630  payload_len += attr_list_len;
631  }
632  if (NULL != presentations)
633  {
634  // Get length
635  // FIXME only add presentations relevant for attribute list!!!
636  // This is important because of the distinction between id_token and
637  // userinfo in OIDC
638  pres_list_len =
640  params.pres_list_len = htonl (pres_list_len);
642  "Length of serialized presentations: %lu\n",
643  pres_list_len);
644  // Get serialized attributes
645  payload_len += pres_list_len;
646  }
647 
648  // Get plaintext length
649  payload = GNUNET_malloc (payload_len);
650  memcpy (payload, &params, sizeof(params));
651  tmp = payload + sizeof(params);
652  if (0 < code_challenge_len)
653  {
654  memcpy (tmp, code_challenge, code_challenge_len);
655  tmp += code_challenge_len;
656  }
657  if (0 < nonce_len)
658  {
659  memcpy (tmp, nonce_str, nonce_len);
660  tmp += nonce_len;
661  }
662  if (0 < attr_list_len)
664  tmp += attr_list_len;
665  if (0 < pres_list_len)
666  GNUNET_RECLAIM_presentation_list_serialize (presentations, tmp);
667  tmp += pres_list_len;
668 
671  // Get length
672  code_payload_len = sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
673  + payload_len + sizeof(struct
676  "Length of data to encode: %lu\n",
677  code_payload_len);
678 
679  // Initialize code payload
680  code_payload = GNUNET_malloc (code_payload_len);
681  GNUNET_assert (NULL != code_payload);
682  purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload;
683  purpose->size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
684  + payload_len);
686  // Store pubkey
687  buf_ptr = (char *) &purpose[1];
688  memcpy (buf_ptr, payload, payload_len);
690  buf_ptr += payload_len;
691  // Sign and store signature
692  if (GNUNET_SYSERR ==
693  GNUNET_IDENTITY_sign_ (issuer,
694  purpose,
695  (struct GNUNET_IDENTITY_Signature *)
696  buf_ptr))
697  {
698  GNUNET_break (0);
699  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unable to sign code\n");
700  GNUNET_free (code_payload);
701  return NULL;
702  }
703  GNUNET_STRINGS_base64url_encode (code_payload, code_payload_len, &code_str);
704  GNUNET_free (code_payload);
705  return code_str;
706 }
707 
708 
710 check_code_challenge (const char *code_challenge,
711  uint32_t code_challenge_len,
712  const char *code_verifier)
713 {
714  char *code_verifier_hash;
715  char *expected_code_challenge;
716 
717  if (0 == code_challenge_len) /* Only check if this code requires a CV */
718  return GNUNET_OK;
719  if (NULL == code_verifier)
720  {
722  "Expected code verifier!\n");
723  return GNUNET_SYSERR;
724  }
725  code_verifier_hash = GNUNET_malloc (256 / 8);
726  // hash code verifier
727  gcry_md_hash_buffer (GCRY_MD_SHA256,
728  code_verifier_hash,
729  code_verifier,
730  strlen (code_verifier));
731  // encode code verifier
732  GNUNET_STRINGS_base64url_encode (code_verifier_hash, 256 / 8,
733  &expected_code_challenge);
734  GNUNET_free (code_verifier_hash);
735  if (0 !=
736  strncmp (expected_code_challenge, code_challenge, code_challenge_len))
737  {
739  "Invalid code verifier! Expected: %s, Got: %.*s\n",
740  expected_code_challenge,
741  code_challenge_len,
742  code_challenge);
743  GNUNET_free (expected_code_challenge);
744  return GNUNET_SYSERR;
745  }
746  GNUNET_free (expected_code_challenge);
747  return GNUNET_OK;
748 }
749 
750 
766 int
768  const char *code,
769  const char *code_verifier,
771  struct GNUNET_RECLAIM_AttributeList **attrs,
772  struct GNUNET_RECLAIM_PresentationList **presentations,
773  char **nonce_str,
775 {
776  char *code_payload;
777  char *ptr;
778  char *plaintext;
779  char *attrs_ser;
780  char *presentations_ser;
781  char *code_challenge;
783  struct GNUNET_IDENTITY_Signature *signature;
784  uint32_t code_challenge_len;
785  uint32_t attrs_ser_len;
786  uint32_t pres_ser_len;
787  size_t plaintext_len;
788  size_t code_payload_len;
789  uint32_t nonce_len = 0;
790  struct OIDC_Parameters *params;
791 
792  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to decode `%s'\n", code);
793  code_payload = NULL;
794  code_payload_len =
795  GNUNET_STRINGS_base64url_decode (code, strlen (code),
796  (void **) &code_payload);
797  if (code_payload_len < sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
798  + sizeof(struct OIDC_Parameters)
799  + sizeof(struct GNUNET_IDENTITY_Signature))
800  {
801  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Authorization code malformed\n");
802  GNUNET_free (code_payload);
803  return GNUNET_SYSERR;
804  }
805 
806  purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload;
807  plaintext_len = code_payload_len;
808  plaintext_len -= sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose);
809  ptr = (char *) &purpose[1];
810  plaintext_len -= sizeof(struct GNUNET_IDENTITY_Signature);
811  plaintext = ptr;
812  ptr += plaintext_len;
813  signature = (struct GNUNET_IDENTITY_Signature *) ptr;
814  params = (struct OIDC_Parameters *) plaintext;
815 
816  // cmp code_challenge code_verifier
817  code_challenge_len = ntohl (params->code_challenge_len);
818  code_challenge = ((char *) &params[1]);
820  {
821  if (GNUNET_OK != check_code_challenge (code_challenge,
823  code_verifier))
824  {
825  GNUNET_free (code_payload);
826  return GNUNET_SYSERR;
827  }
828  }
829  nonce_len = ntohl (params->nonce_len);
830  if (0 != nonce_len)
831  {
832  *nonce_str = GNUNET_strndup (code_challenge + code_challenge_len,
833  nonce_len);
834  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got nonce: %s\n", *nonce_str);
835  }
836 
837  // Ticket
838  memcpy (ticket, &params->ticket, sizeof(params->ticket));
839  // Signature
840  // GNUNET_CRYPTO_ecdsa_key_get_public (ecdsa_priv, &ecdsa_pub);
841  if (0 != GNUNET_memcmp (audience, &ticket->audience))
842  {
843  GNUNET_free (code_payload);
844  if (NULL != *nonce_str)
845  GNUNET_free (*nonce_str);
847  "Audience in ticket does not match client!\n");
848  return GNUNET_SYSERR;
849  }
850  if (GNUNET_OK !=
853  purpose,
854  signature,
855  &(ticket->identity)))
856  {
857  GNUNET_free (code_payload);
858  if (NULL != *nonce_str)
859  GNUNET_free (*nonce_str);
860  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Signature of AuthZ code invalid!\n");
861  return GNUNET_SYSERR;
862  }
863  // Attributes
864  attrs_ser = ((char *) &params[1]) + code_challenge_len + nonce_len;
865  attrs_ser_len = ntohl (params->attr_list_len);
866  *attrs = GNUNET_RECLAIM_attribute_list_deserialize (attrs_ser, attrs_ser_len);
867  presentations_ser = ((char*) attrs_ser) + attrs_ser_len;
868  pres_ser_len = ntohl (params->pres_list_len);
869  *presentations =
871  pres_ser_len);
872 
873  GNUNET_free (code_payload);
874  return GNUNET_OK;
875 }
876 
877 
887 void
888 OIDC_build_token_response (const char *access_token,
889  const char *id_token,
890  const struct GNUNET_TIME_Relative *expiration_time,
891  char **token_response)
892 {
893  json_t *root_json;
894 
895  root_json = json_object ();
896 
897  GNUNET_assert (NULL != access_token);
898  GNUNET_assert (NULL != id_token);
899  GNUNET_assert (NULL != expiration_time);
900  json_object_set_new (root_json, "access_token", json_string (access_token));
901  json_object_set_new (root_json, "token_type", json_string ("Bearer"));
902  json_object_set_new (root_json,
903  "expires_in",
904  json_integer (expiration_time->rel_value_us
905  / (1000 * 1000)));
906  json_object_set_new (root_json, "id_token", json_string (id_token));
907  *token_response = json_dumps (root_json, JSON_INDENT (0) | JSON_COMPACT);
908  json_decref (root_json);
909 }
910 
911 
915 char *
917 {
918  char *access_token;
919 
921  sizeof(*ticket),
922  &access_token);
923  return access_token;
924 }
925 
926 
930 int
931 OIDC_access_token_parse (const char *token,
932  struct GNUNET_RECLAIM_Ticket **ticket)
933 {
934  size_t sret;
935  char *decoded;
936  sret = GNUNET_STRINGS_base64_decode (token,
937  strlen (token),
938  (void**) &decoded);
939  if (sizeof (struct GNUNET_RECLAIM_Ticket) != sret)
940  {
941  GNUNET_free (decoded);
942  return GNUNET_SYSERR;
943  }
944  *ticket = (struct GNUNET_RECLAIM_Ticket *) decoded;
945  return GNUNET_OK;
946 }
947 
948 
958 OIDC_check_scopes_for_claim_request (const char*scopes,
959  const char*attr)
960 {
961  char *scope_variables;
962  char *scope_variable;
963  char delimiter[] = " ";
964  int i;
965 
966  scope_variables = GNUNET_strdup (scopes);
967  scope_variable = strtok (scope_variables, delimiter);
968  while (NULL != scope_variable)
969  {
970  if (0 == strcmp ("profile", scope_variable))
971  {
972  for (i = 0; i < 14; i++)
973  {
974  if (0 == strcmp (attr, OIDC_profile_claims[i]))
975  {
976  GNUNET_free (scope_variables);
977  return GNUNET_YES;
978  }
979  }
980  }
981  else if (0 == strcmp ("address", scope_variable))
982  {
983  for (i = 0; i < 5; i++)
984  {
985  if (0 == strcmp (attr, OIDC_address_claims[i]))
986  {
987  GNUNET_free (scope_variables);
988  return GNUNET_YES;
989  }
990  }
991  }
992  else if (0 == strcmp ("email", scope_variable))
993  {
994  for (i = 0; i < 2; i++)
995  {
996  if (0 == strcmp (attr, OIDC_email_claims[i]))
997  {
998  GNUNET_free (scope_variables);
999  return GNUNET_YES;
1000  }
1001  }
1002  }
1003  else if (0 == strcmp ("phone", scope_variable))
1004  {
1005  for (i = 0; i < 2; i++)
1006  {
1007  if (0 == strcmp (attr, OIDC_phone_claims[i]))
1008  {
1009  GNUNET_free (scope_variables);
1010  return GNUNET_YES;
1011  }
1012  }
1013 
1014  }
1015  else if (0 == strcmp (attr, scope_variable))
1016  {
1018  GNUNET_free (scope_variables);
1019  return GNUNET_YES;
1020  }
1021  scope_variable = strtok (NULL, delimiter);
1022  }
1023  GNUNET_free (scope_variables);
1024  return GNUNET_NO;
1025 
1026 }
#define GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN
Signature for a GNUid Ticket (Reclaim)
static char * subject
Subject pubkey string.
Definition: gnunet-abd.c:86
static int replace
Replace DID Document Flag.
Definition: gnunet-did.c:56
struct GNUNET_RECLAIM_Attribute * claim
Claim to store.
static struct GNUNET_RECLAIM_Ticket ticket
Ticket to consume.
static int result
Global testing status.
static unsigned long long payload
How much data are we currently storing in the database?
Identity attribute definitions.
reclaim service; implements identity and personal data sharing for GNUnet
enum GNUNET_GenericReturnValue GNUNET_IDENTITY_sign_(const struct GNUNET_IDENTITY_PrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_IDENTITY_Signature *sig)
Sign a given block.
enum GNUNET_GenericReturnValue GNUNET_IDENTITY_signature_verify_(uint32_t purpose, const struct GNUNET_CRYPTO_EccSignaturePurpose *validate, const struct GNUNET_IDENTITY_Signature *sig, const struct GNUNET_IDENTITY_PublicKey *pub)
Verify a given signature.
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32.
#define GNUNET_log(kind,...)
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
GNUNET_GenericReturnValue
Named constants for return values.
void GNUNET_CRYPTO_hmac_raw(const void *key, size_t key_len, const void *plaintext, size_t plaintext_len, struct GNUNET_HashCode *hmac)
Calculate HMAC of a message (RFC 2104) TODO: Shouldn't this be the standard hmac function and the abo...
Definition: crypto_hash.c:299
#define GNUNET_PACKED
gcc-ism to get packed structs.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_RECLAIM_id_is_equal(a, b)
#define GNUNET_RECLAIM_id_is_zero(a)
char * GNUNET_RECLAIM_attribute_value_to_string(uint32_t type, const void *data, size_t data_size)
Convert the 'claim' of an attribute to a string.
char * GNUNET_RECLAIM_presentation_value_to_string(uint32_t type, const void *data, size_t data_size)
Convert the 'claim' of a presentation to a string.
struct GNUNET_RECLAIM_AttributeList * GNUNET_RECLAIM_attribute_list_deserialize(const char *data, size_t data_size)
Deserialize an attribute list.
size_t GNUNET_RECLAIM_attribute_list_serialize(const struct GNUNET_RECLAIM_AttributeList *attrs, char *result)
Serialize an attribute list.
size_t GNUNET_RECLAIM_presentation_list_serialize(const struct GNUNET_RECLAIM_PresentationList *presentations, char *result)
Serialize a presentation list.
const char * GNUNET_RECLAIM_presentation_number_to_typename(uint32_t type)
Convert a presentation type number to the corresponding credential type string.
struct GNUNET_RECLAIM_PresentationList * GNUNET_RECLAIM_presentation_list_deserialize(const char *data, size_t data_size)
Deserialize a presentation list.
size_t GNUNET_RECLAIM_presentation_list_serialize_get_size(const struct GNUNET_RECLAIM_PresentationList *presentations)
Get required size for serialization buffer.
size_t GNUNET_RECLAIM_attribute_list_serialize_get_size(const struct GNUNET_RECLAIM_AttributeList *attrs)
Get required size for serialization buffer.
size_t GNUNET_STRINGS_base64url_decode(const char *data, size_t len, void **out)
Decode from Base64url.
Definition: strings.c:1760
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
Definition: strings.c:763
size_t GNUNET_STRINGS_base64url_encode(const void *in, size_t len, char **output)
Encode into Base64url.
Definition: strings.c:1656
size_t GNUNET_STRINGS_base64_decode(const char *data, size_t len, void **output)
Decode from Base64.
Definition: strings.c:1695
size_t GNUNET_STRINGS_base64_encode(const void *in, size_t len, char **output)
Encode into Base64.
Definition: strings.c:1607
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_add(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Add a given relative duration to the given start time.
Definition: time.c:450
static char * create_jwt_hmac_header(void)
Definition: oidc_helper.c:120
char * OIDC_generate_id_token_hmac(const struct GNUNET_IDENTITY_PublicKey *aud_key, const struct GNUNET_IDENTITY_PublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations, const struct GNUNET_TIME_Relative *expiration_time, const char *nonce, const char *secret_key)
Create a JWT using HMAC (HS256) from attributes.
Definition: oidc_helper.c:489
static void replace_char(char *str, char find, char replace)
Definition: oidc_helper.c:136
static char OIDC_email_claims[2][16]
Standard claims represented by the "email" scope in OIDC.
Definition: oidc_helper.c:86
static char OIDC_address_claims[5][32]
Standard claims represented by the "address" scope in OIDC.
Definition: oidc_helper.c:100
static void fix_base64(char *str)
Definition: oidc_helper.c:150
enum GNUNET_GenericReturnValue check_code_challenge(const char *code_challenge, uint32_t code_challenge_len, const char *code_verifier)
Definition: oidc_helper.c:710
static json_t * generate_userinfo_json(const struct GNUNET_IDENTITY_PublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations)
Definition: oidc_helper.c:161
char * OIDC_generate_userinfo(const struct GNUNET_IDENTITY_PublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations)
Generate userinfo JSON as string.
Definition: oidc_helper.c:346
static enum GNUNET_GenericReturnValue is_claim_in_address_scope(const char *claim)
Definition: oidc_helper.c:105
char * OIDC_access_token_new(const struct GNUNET_RECLAIM_Ticket *ticket)
Generate a new access token.
Definition: oidc_helper.c:916
enum GNUNET_GenericReturnValue OIDC_check_scopes_for_claim_request(const char *scopes, const char *attr)
Checks if a claim is implicitly requested through standard scope(s) or explicitly through non-standar...
Definition: oidc_helper.c:958
char * generate_id_token_body(const struct GNUNET_IDENTITY_PublicKey *aud_key, const struct GNUNET_IDENTITY_PublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations, const struct GNUNET_TIME_Relative *expiration_time, const char *nonce)
Definition: oidc_helper.c:362
char * OIDC_build_authz_code(const struct GNUNET_IDENTITY_PrivateKey *issuer, const struct GNUNET_RECLAIM_Ticket *ticket, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations, const char *nonce_str, const char *code_challenge)
Builds an OIDC authorization code including a reclaim ticket and nonce.
Definition: oidc_helper.c:581
static char OIDC_phone_claims[2][32]
Standard claims represented by the "phone" scope in OIDC.
Definition: oidc_helper.c:93
int OIDC_parse_authz_code(const struct GNUNET_IDENTITY_PublicKey *audience, const char *code, const char *code_verifier, struct GNUNET_RECLAIM_Ticket *ticket, struct GNUNET_RECLAIM_AttributeList **attrs, struct GNUNET_RECLAIM_PresentationList **presentations, char **nonce_str, enum OIDC_VerificationOptions opts)
Parse reclaim ticket and nonce from authorization code.
Definition: oidc_helper.c:767
void OIDC_build_token_response(const char *access_token, const char *id_token, const struct GNUNET_TIME_Relative *expiration_time, char **token_response)
Build a token response for a token request TODO: Maybe we should add the scope here?
Definition: oidc_helper.c:888
static GNUNET_NETWORK_STRUCT_END char OIDC_profile_claims[14][32]
Standard claims represented by the "profile" scope in OIDC.
Definition: oidc_helper.c:77
int OIDC_access_token_parse(const char *token, struct GNUNET_RECLAIM_Ticket **ticket)
Parse an access token.
Definition: oidc_helper.c:931
char * OIDC_generate_id_token_rsa(const struct GNUNET_IDENTITY_PublicKey *aud_key, const struct GNUNET_IDENTITY_PublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations, const struct GNUNET_TIME_Relative *expiration_time, const char *nonce, const json_t *secret_rsa_key)
Create a JWT using RSA256 algorithm from attributes.
Definition: oidc_helper.c:427
helper library for OIDC related functions
#define JWT_TYP_VALUE
Definition: oidc_helper.h:32
#define JWT_ALG
Definition: oidc_helper.h:30
#define SERVER_ADDRESS
Definition: oidc_helper.h:37
OIDC_VerificationOptions
Definition: oidc_helper.h:40
@ OIDC_VERIFICATION_NO_CODE_VERIFIER
Do not check code verifier even if expected.
Definition: oidc_helper.h:49
#define JWT_TYP
Definition: oidc_helper.h:31
#define JWT_ALG_VALUE_HMAC
Definition: oidc_helper.h:34
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
A 512-bit hashcode.
A private key for an identity as per LSD0001.
An identity key as per LSD0001.
An identity signature as per LSD0001.
struct GNUNET_RECLAIM_Attribute * attribute
The attribute claim.
struct GNUNET_RECLAIM_AttributeListEntry * next
DLL.
A list of GNUNET_RECLAIM_Attribute structures.
struct GNUNET_RECLAIM_AttributeListEntry * list_head
List head.
const char * name
The name of the attribute.
struct GNUNET_RECLAIM_Identifier credential
Referenced ID of credential (may be GNUNET_RECLAIM_ID_ZERO if self-creded)
uint32_t type
Type of Claim.
const void * data
Binary value stored as attribute value.
size_t data_size
Number of bytes in data.
struct GNUNET_RECLAIM_Presentation * presentation
The credential.
struct GNUNET_RECLAIM_PresentationListEntry * next
DLL.
A list of GNUNET_RECLAIM_Presentation structures.
struct GNUNET_RECLAIM_PresentationListEntry * list_head
List head.
const void * data
Binary value stored as presentation value.
uint32_t type
Type/Format of Claim.
size_t data_size
Number of bytes in data.
struct GNUNET_RECLAIM_Identifier credential_id
The credential id of which this is a presentation.
The authorization ticket.
struct GNUNET_IDENTITY_PublicKey audience
The ticket audience (= relying party)
struct GNUNET_IDENTITY_PublicKey identity
The ticket issuer (= the user)
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
The signature used to generate the authorization code.
Definition: oidc_helper.c:45
struct GNUNET_RECLAIM_Ticket ticket
The reclaim ticket.
Definition: oidc_helper.c:49
uint32_t pres_list_len
The length of the presentation list.
Definition: oidc_helper.c:69
uint32_t nonce_len
The nonce length.
Definition: oidc_helper.c:54
uint32_t attr_list_len
The length of the attributes list.
Definition: oidc_helper.c:64
uint32_t code_challenge_len
The length of the PKCE code_challenge.
Definition: oidc_helper.c:59