GNUnet 0.25.2-11-g84e94e98c
 
Loading...
Searching...
No Matches
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 <inttypes.h>
28#include <jansson.h>
29#include <jose/jose.h>
30#include "gnunet_gns_service.h"
32#include "gnunet_util_lib.h"
33#include "gnunet_reclaim_lib.h"
35#include "gnunet_signatures.h"
36#include "oidc_helper.h"
37// #include "benchmark.h"
38#include <gcrypt.h>
39
41
72
74
78static char OIDC_profile_claims[14][32] = {
79 "name", "family_name", "given_name", "middle_name", "nickname",
80 "preferred_username", "profile", "picture", "website", "gender", "birthdate",
81 "zoneinfo", "locale", "updated_at"
82};
83
87static char OIDC_email_claims[2][16] = {
88 "email", "email_verified"
89};
90
94static char OIDC_phone_claims[2][32] = {
95 "phone_number", "phone_number_verified"
96};
97
101static char OIDC_address_claims[5][32] = {
102 "street_address", "locality", "region", "postal_code", "country"
103};
104
107{
108 int i;
109 for (i = 0; i < 5; i++)
110 {
111 if (0 == strcmp (claim, OIDC_address_claims[i]))
112 {
113 return GNUNET_YES;
114 }
115 }
116 return GNUNET_NO;
117}
118
119
120static char *
122{
123 json_t *root;
124 char *json_str;
125
126 root = json_object ();
127 json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE_HMAC));
128 json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE));
129
130 json_str = json_dumps (root, JSON_INDENT (0) | JSON_COMPACT);
131 json_decref (root);
132 return json_str;
133}
134
135
136static void
137replace_char (char *str, char find, char replace)
138{
139 char *current_pos = strchr (str, find);
140
141 while (current_pos)
142 {
143 *current_pos = replace;
144 current_pos = strchr (current_pos, find);
145 }
146}
147
148
149// RFC4648
150static void
152{
153 // Replace + with -
154 replace_char (str, '+', '-');
155
156 // Replace / with _
157 replace_char (str, '/', '_');
158}
159
160
161static json_t*
163 const struct GNUNET_RECLAIM_AttributeList *attrs,
164 const struct
165 GNUNET_RECLAIM_PresentationList *presentations)
166{
169 char *subject;
170 char *source_name;
171 char *attr_val_str;
172 char *pres_val_str;
173 json_t *body;
174 json_t *aggr_names;
175 json_t *aggr_sources;
176 json_t *aggr_sources_jwt;
177 json_t *addr_claim = NULL;
178
179 subject =
181 sizeof(struct
183 body = json_object ();
184 aggr_names = json_object ();
185 aggr_sources = json_object ();
186
187 // iss REQUIRED case sensitive server uri with https
188 // The issuer is the local reclaim instance (e.g.
189 // https://reclaim.id/api/openid)
190 json_object_set_new (body, "iss", json_string (SERVER_ADDRESS));
191 // sub REQUIRED public key identity, not exceed 255 ASCII length
192 json_object_set_new (body, "sub", json_string (subject));
194 pres_val_str = NULL;
195 source_name = NULL;
196 int i = 0;
197 for (ple = presentations->list_head; NULL != ple; ple = ple->next)
198 {
199 // New presentation
200 GNUNET_asprintf (&source_name,
201 "src%d",
202 i);
204 "Adding new presentation source #%d\n", i);
205 aggr_sources_jwt = json_object ();
206 pres_val_str =
208 ple->presentation->data,
210 ;
212 "Presentation is: %s\n", pres_val_str);
213 json_object_set_new (aggr_sources_jwt,
215 ple->presentation->type),
216 json_string (pres_val_str) );
217 json_object_set_new (aggr_sources, source_name, aggr_sources_jwt);
218 GNUNET_free (pres_val_str);
219 GNUNET_free (source_name);
220 source_name = NULL;
221 i++;
222 }
223
224 int addr_is_aggregated = GNUNET_NO;
225 int addr_is_normal = GNUNET_NO;
226 for (le = attrs->list_head; NULL != le; le = le->next)
227 {
229 "Processing %s for userinfo body\n",
230 le->attribute->name);
232 {
233 attr_val_str =
235 le->attribute->data,
236 le->attribute->data_size);
242 {
243 if (GNUNET_YES == addr_is_aggregated)
244 {
246 "Address is set as aggregated claim. Skipping self-issued value...\n");
247 GNUNET_free (attr_val_str);
248 continue;
249 }
250 addr_is_normal = GNUNET_YES;
251
252 if (NULL == addr_claim)
253 {
254 addr_claim = json_object ();
255 json_object_set_new (body, "address", addr_claim);
256 }
257 json_object_set_new (addr_claim, le->attribute->name,
258 json_string (attr_val_str));
259
260 }
261 else
262 {
263 json_object_set_new (body, le->attribute->name,
264 json_string (attr_val_str));
265 }
266 GNUNET_free (attr_val_str);
267 }
268 else
269 {
270 // Check if presentation is there
271 int j = 0;
272 for (ple = presentations->list_head; NULL != ple; ple = ple->next)
273 {
274 if (GNUNET_YES ==
276 &le->attribute->credential))
277 break;
278 j++;
279 }
280 if (NULL == ple)
281 {
283 "Presentation for `%s' missing...\n",
284 le->attribute->name);
285 continue;
286 }
292 {
293 if (GNUNET_YES == addr_is_normal)
294 {
296 "Address is already set as normal claim. Skipping attested value...\n");
297 continue;
298 }
299 addr_is_aggregated = GNUNET_YES;
301 if (NULL != addr_claim)
302 continue;
303 addr_claim = json_object ();
304 GNUNET_asprintf (&source_name,
305 "src%d",
306 j);
307 json_object_set_new (aggr_names, "address",
308 json_string (source_name));
309 GNUNET_free (source_name);
310 }
311 else
312 {
313 // Presentation exists, hence take the respective source str
314 GNUNET_asprintf (&source_name,
315 "src%d",
316 j);
317 json_object_set_new (aggr_names, le->attribute->name,
318 json_string (source_name));
319 GNUNET_free (source_name);
320 }
321 }
322 }
323 if (0 != i)
324 {
325 json_object_set_new (body, "_claim_names", aggr_names);
326 json_object_set_new (body, "_claim_sources", aggr_sources);
327 }
328
329 return body;
330}
331
332
341char *
343 const struct GNUNET_RECLAIM_AttributeList *attrs,
344 const struct
345 GNUNET_RECLAIM_PresentationList *presentations)
346{
347 char *body_str;
348 json_t*body = generate_userinfo_json (sub_key,
349 attrs,
350 presentations);
351 body_str = json_dumps (body, JSON_INDENT (0) | JSON_COMPACT);
352 json_decref (body);
353 return body_str;
354}
355
356
357static char *
358generate_id_token_body (const char *rp_uri,
359 const struct GNUNET_CRYPTO_BlindablePublicKey *sub_key,
360 const struct GNUNET_RECLAIM_AttributeList *attrs,
361 const struct
362 GNUNET_RECLAIM_PresentationList *presentations,
363 const struct GNUNET_TIME_Relative *expiration_time,
364 const char *nonce)
365{
366 struct GNUNET_TIME_Absolute exp_time;
367 struct GNUNET_TIME_Absolute time_now;
368 json_t *body;
369 char *subject;
370 char *body_str;
371
372 body = generate_userinfo_json (sub_key,
373 attrs,
374 presentations);
375 // iat REQUIRED time now
376 time_now = GNUNET_TIME_absolute_get ();
377 // exp REQUIRED time expired from config
378 exp_time = GNUNET_TIME_absolute_add (time_now, *expiration_time);
379 // auth_time only if max_age
380 // nonce only if nonce
381 // OPTIONAL acr,amr,azp
382 subject =
384 sizeof(struct
386
387 // aud REQUIRED public key client_id must be there
388 json_object_set_new (body, "aud", json_string (rp_uri));
389 // iat
390 json_object_set_new (body,
391 "iat",
392 json_integer (time_now.abs_value_us / (1000 * 1000)));
393 // exp
394 json_object_set_new (body,
395 "exp",
396 json_integer (exp_time.abs_value_us / (1000 * 1000)));
397 // nbf
398 json_object_set_new (body,
399 "nbf",
400 json_integer (time_now.abs_value_us / (1000 * 1000)));
401 // nonce
402 if (NULL != nonce)
403 json_object_set_new (body, "nonce", json_string (nonce));
404
405 // Error checking
406 body_str = json_dumps (body, JSON_INDENT (2) | JSON_COMPACT);
407 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"ID-Token: %s\n", body_str);
408
409 json_decref (body);
411
412 return body_str;
413}
414
415
416char *
417OIDC_generate_id_token_rsa (const char *rp_uri,
419 sub_key,
420 const struct GNUNET_RECLAIM_AttributeList *attrs,
421 const struct
422 GNUNET_RECLAIM_PresentationList *presentations,
423 const struct GNUNET_TIME_Relative *expiration_time,
424 const char *nonce,
425 const json_t *secret_rsa_key)
426{
427 json_t *jws;
428 char *body_str;
429 char *result;
430
431 // Generate the body of the JSON Web Signature
432 body_str = generate_id_token_body (rp_uri,
433 sub_key,
434 attrs,
435 presentations,
436 expiration_time,
437 nonce);
438
439 if (NULL == body_str)
440 {
442 "Body for the JWS could not be generated\n");
443 return NULL;
444 }
445
446 // Creating the JSON Web Signature.
447 jws = json_pack ("{s:o}", "payload",
448 jose_b64_enc (body_str, strlen (body_str)));
449 GNUNET_free (body_str);
450
451 if (! jose_jws_sig (NULL, jws, NULL, secret_rsa_key))
452 {
454 "Signature generation failed\n");
455 return NULL;
456 }
457
458 // Encoding JSON as compact JSON Web Signature
459 GNUNET_asprintf (&result, "%s.%s.%s",
460 json_string_value (json_object_get (jws, "protected")),
461 json_string_value (json_object_get (jws, "payload")),
462 json_string_value (json_object_get (jws, "signature")) );
463
464 json_decref (jws);
465 return result;
466}
467
468
469char *
470OIDC_generate_id_token_hmac (const char *rp_uri,
472 sub_key,
473 const struct GNUNET_RECLAIM_AttributeList *attrs,
474 const struct
475 GNUNET_RECLAIM_PresentationList *presentations,
476 const struct GNUNET_TIME_Relative *expiration_time,
477 const char *nonce,
478 const char *secret_key)
479{
480 struct GNUNET_HashCode signature;
481 char *header;
482 char *header_base64;
483 char *body_str;
484 char *body_base64;
485 char *signature_target;
486 char *signature_base64;
487 char *result;
488
489 // Generate and encode Header
490 header = create_jwt_hmac_header ();
491 if (NULL == header)
492 {
494 "Header for the JWS could not be generated\n");
495 return NULL;
496 }
497 GNUNET_STRINGS_base64url_encode (header, strlen (header), &header_base64);
498 GNUNET_free (header);
499 fix_base64 (header_base64);
500
501 // Generate and encode the body of the JSON Web Signature
502 body_str = generate_id_token_body (rp_uri,
503 sub_key,
504 attrs,
505 presentations,
506 expiration_time,
507 nonce);
508
509 if (NULL == body_str)
510 {
512 "Body for the JWS could not be generated\n");
513 GNUNET_free (header_base64);
514 return NULL;
515 }
516
517 GNUNET_STRINGS_base64url_encode (body_str, strlen (body_str), &body_base64);
518 fix_base64 (body_base64);
519
524 GNUNET_asprintf (&signature_target, "%s.%s", header_base64, body_base64);
525 GNUNET_CRYPTO_hmac_raw (secret_key,
526 strlen (secret_key),
527 signature_target,
528 strlen (signature_target),
529 &signature);
530 GNUNET_STRINGS_base64url_encode ((const char *) &signature,
531 sizeof(struct GNUNET_HashCode),
532 &signature_base64);
533 fix_base64 (signature_base64);
534
536 "%s.%s.%s",
537 header_base64,
538 body_base64,
539 signature_base64);
540
541 GNUNET_free (header_base64);
542 GNUNET_free (body_str);
543 GNUNET_free (body_base64);
544 GNUNET_free (signature_target);
545 GNUNET_free (signature_base64);
546 return result;
547}
548
549
562char *
564 const struct GNUNET_RECLAIM_Ticket *ticket,
565 const struct GNUNET_RECLAIM_AttributeList *attrs,
566 const struct
567 GNUNET_RECLAIM_PresentationList *presentations,
568 const char *nonce_str,
569 const char *code_challenge)
570{
571 struct OIDC_Parameters params;
572 char *code_payload;
573 char *payload;
574 char *tmp;
575 char *code_str;
576 char *buf_ptr = NULL;
577 size_t payload_len;
578 size_t code_payload_len;
579 size_t attr_list_len = 0;
580 size_t pres_list_len = 0;
581 size_t code_challenge_len = 0;
582 uint32_t nonce_len = 0;
584
586 // Assign ticket
587 memset (&params, 0, sizeof(params));
588 memcpy (params.ticket.gns_name, ticket->gns_name, strlen (ticket->gns_name)
589 + 1);
590 // Assign nonce
591 payload_len = sizeof(struct OIDC_Parameters);
592 if ((NULL != nonce_str) && (strcmp ("", nonce_str) != 0))
593 {
594 nonce_len = strlen (nonce_str);
595 payload_len += nonce_len;
596 }
597 params.nonce_len = htonl (nonce_len);
598 // Assign code challenge
599 if (NULL != code_challenge)
600 code_challenge_len = strlen (code_challenge);
601 payload_len += code_challenge_len;
602 params.code_challenge_len = htonl (code_challenge_len);
603 // Assign attributes
604 if (NULL != attrs)
605 {
606 // Get length
608 params.attr_list_len = htonl (attr_list_len);
610 "Length of serialized attributes: %lu\n",
612 // Get serialized attributes
613 payload_len += attr_list_len;
614 }
615 if (NULL != presentations)
616 {
617 // Get length
618 // FIXME only add presentations relevant for attribute list!!!
619 // This is important because of the distinction between id_token and
620 // userinfo in OIDC
623 params.pres_list_len = htonl (pres_list_len);
625 "Length of serialized presentations: %lu\n",
627 // Get serialized attributes
628 payload_len += pres_list_len;
629 }
630
631 // Get plaintext length
632 payload = GNUNET_malloc (payload_len);
633 memcpy (payload, &params, sizeof(params));
634 tmp = payload + sizeof(params);
635 if (0 < code_challenge_len)
636 {
637 memcpy (tmp, code_challenge, code_challenge_len);
638 tmp += code_challenge_len;
639 }
640 if (0 < nonce_len)
641 {
642 memcpy (tmp, nonce_str, nonce_len);
643 tmp += nonce_len;
644 }
645 if (0 < attr_list_len)
647 tmp += attr_list_len;
648 if (0 < pres_list_len)
650 tmp += pres_list_len;
651
654 // Get length
655 code_payload_len = sizeof(struct GNUNET_CRYPTO_SignaturePurpose)
656 + payload_len + sizeof(struct
658 ;
660 "Length of data to encode: %lu\n",
661 code_payload_len);
662
663 // Initialize code payload
664 code_payload = GNUNET_malloc (code_payload_len);
665 GNUNET_assert (NULL != code_payload);
666 purpose = (struct GNUNET_CRYPTO_SignaturePurpose *) code_payload;
667 purpose->size = htonl (sizeof(struct GNUNET_CRYPTO_SignaturePurpose)
668 + payload_len);
670 // Store pubkey
671 buf_ptr = (char *) &purpose[1];
672 memcpy (buf_ptr, payload, payload_len);
674 buf_ptr += payload_len;
675 // Sign and store signature
676 if (GNUNET_SYSERR ==
678 purpose,
679 (struct
681 buf_ptr))
682 {
683 GNUNET_break (0);
684 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unable to sign code\n");
685 GNUNET_free (code_payload);
686 return NULL;
687 }
688 GNUNET_STRINGS_base64url_encode (code_payload, code_payload_len, &code_str);
689 GNUNET_free (code_payload);
690 return code_str;
691}
692
693
695check_code_challenge (const char *code_challenge,
696 uint32_t code_challenge_len,
697 const char *code_verifier)
698{
699 char *code_verifier_hash;
700 char *expected_code_challenge;
701
702 if (0 == code_challenge_len) /* Only check if this code requires a CV */
703 return GNUNET_OK;
704 if (NULL == code_verifier)
705 {
707 "Expected code verifier!\n");
708 return GNUNET_SYSERR;
709 }
710 code_verifier_hash = GNUNET_malloc (256 / 8);
711 // hash code verifier
712 gcry_md_hash_buffer (GCRY_MD_SHA256,
713 code_verifier_hash,
714 code_verifier,
715 strlen (code_verifier));
716 // encode code verifier
717 GNUNET_STRINGS_base64url_encode (code_verifier_hash, 256 / 8,
718 &expected_code_challenge);
719 GNUNET_free (code_verifier_hash);
720 if (0 !=
721 strncmp (expected_code_challenge, code_challenge, code_challenge_len))
722 {
724 "Invalid code verifier! Expected: %s, Got: %.*s\n",
725 expected_code_challenge,
726 code_challenge_len,
727 code_challenge);
728 GNUNET_free (expected_code_challenge);
729 return GNUNET_SYSERR;
730 }
731 GNUNET_free (expected_code_challenge);
732 return GNUNET_OK;
733}
734
735
751int
752OIDC_parse_authz_code (const char *rp_uri,
753 const struct GNUNET_CRYPTO_BlindablePublicKey *cid,
754 const char *code,
755 const char *code_verifier,
757 struct GNUNET_RECLAIM_AttributeList **attrs,
758 struct GNUNET_RECLAIM_PresentationList **presentations,
759 char **nonce_str,
760 enum OIDC_VerificationOptions opts, char **emsg)
761{
762 char *code_payload;
763 char *ptr;
764 char *plaintext;
765 char *attrs_ser;
766 char *presentations_ser;
767 char *code_challenge;
769 struct GNUNET_CRYPTO_BlindableKeySignature *signature;
771 uint32_t code_challenge_len;
772 uint32_t attrs_ser_len;
773 uint32_t pres_ser_len;
774 size_t plaintext_len;
775 size_t code_payload_len;
776 uint32_t nonce_len = 0;
777 struct OIDC_Parameters *params;
778
779
781 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to decode `%s'\n", code);
782 code_payload = NULL;
783 code_payload_len =
784 GNUNET_STRINGS_base64url_decode (code, strlen (code),
785 (void **) &code_payload);
786 if (code_payload_len < sizeof(struct GNUNET_CRYPTO_SignaturePurpose)
787 + sizeof(struct OIDC_Parameters)
789 {
790 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Authorization code malformed\n");
791 GNUNET_free (code_payload);
792 return GNUNET_SYSERR;
793 }
794
795 purpose = (struct GNUNET_CRYPTO_SignaturePurpose *) code_payload;
796 plaintext_len = code_payload_len;
797 plaintext_len -= sizeof(struct GNUNET_CRYPTO_SignaturePurpose);
798 ptr = (char *) &purpose[1];
799 plaintext_len -= sizeof(struct GNUNET_CRYPTO_BlindableKeySignature);
800 plaintext = ptr;
801 ptr += plaintext_len;
802 signature = (struct GNUNET_CRYPTO_BlindableKeySignature *) ptr;
803 params = (struct OIDC_Parameters *) plaintext;
804
805 // cmp code_challenge code_verifier
806 code_challenge_len = ntohl (params->code_challenge_len);
807 code_challenge = ((char *) &params[1]);
809 {
810 if (GNUNET_OK != check_code_challenge (code_challenge,
812 code_verifier))
813 {
814 GNUNET_asprintf (emsg, "Code verifier `%s' invalid for challenge `%s'",
815 code_verifier, code_challenge);
816 GNUNET_free (code_payload);
817 return GNUNET_SYSERR;
818 }
819 }
820 nonce_len = ntohl (params->nonce_len);
821 if (0 != nonce_len)
822 {
823 *nonce_str = GNUNET_strndup (code_challenge + code_challenge_len,
824 nonce_len);
825 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got nonce: %s\n", *nonce_str);
826 }
827
828 // Ticket
829 memcpy (ticket, &params->ticket, sizeof(params->ticket));
830 // Signature
831 // GNUNET_CRYPTO_ecdsa_key_get_public (ecdsa_priv, &ecdsa_pub);
832 if (GNUNET_OK !=
835 purpose,
836 signature,
837 &iss))
838 {
839 GNUNET_free (code_payload);
840 if (NULL != *nonce_str)
841 GNUNET_free (*nonce_str);
842 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Signature of AuthZ code invalid!\n");
843 *emsg = GNUNET_strdup ("Signature verification failed");
844 return GNUNET_SYSERR;
845 }
846 // Attributes
847 attrs_ser = ((char *) &params[1]) + code_challenge_len + nonce_len;
848 attrs_ser_len = ntohl (params->attr_list_len);
849 *attrs = GNUNET_RECLAIM_attribute_list_deserialize (attrs_ser, attrs_ser_len);
850 presentations_ser = ((char*) attrs_ser) + attrs_ser_len;
851 pres_ser_len = ntohl (params->pres_list_len);
852 *presentations =
854 pres_ser_len);
855
856 GNUNET_free (code_payload);
857 return GNUNET_OK;
858}
859
860
870void
871OIDC_build_token_response (const char *access_token,
872 const char *id_token,
873 const struct GNUNET_TIME_Relative *expiration_time,
874 char **token_response)
875{
876 json_t *root_json;
877
878 root_json = json_object ();
879
880 GNUNET_assert (NULL != access_token);
881 GNUNET_assert (NULL != id_token);
882 GNUNET_assert (NULL != expiration_time);
883 json_object_set_new (root_json, "access_token", json_string (access_token));
884 json_object_set_new (root_json, "token_type", json_string ("Bearer"));
885 json_object_set_new (root_json,
886 "expires_in",
887 json_integer (expiration_time->rel_value_us
888 / (1000 * 1000)));
889 json_object_set_new (root_json, "id_token", json_string (id_token));
890 *token_response = json_dumps (root_json, JSON_INDENT (0) | JSON_COMPACT);
891 json_decref (root_json);
892}
893
894
898char *
900 const char *rp_uri)
901{
902 char *access_token;
903 char *tkt_b64;
904
906 sizeof(*ticket),
907 &tkt_b64);
908 GNUNET_asprintf (&access_token, "%s-%s", tkt_b64, rp_uri);
909 GNUNET_free (tkt_b64);
910 return access_token;
911}
912
913
917int
918OIDC_access_token_parse (const char *token,
920 char **rp_uri)
921{
922 size_t sret;
923 char *decoded;
924 char *tmp;
925 char *tkt_str;
926 char *rp_uri_str;
927 tmp = GNUNET_strdup (token);
928 tkt_str = strtok (tmp, "-");
929 GNUNET_assert (NULL != tkt_str); // FIXME handle
930 rp_uri_str = strtok (NULL, "-");
931 GNUNET_assert (NULL != rp_uri_str); // FIXME handle
932 sret = GNUNET_STRINGS_base64_decode (tkt_str,
933 strlen (tkt_str),
934 (void**) &decoded);
935 if (sizeof (struct GNUNET_RECLAIM_Ticket) != sret)
936 {
937 GNUNET_free (decoded);
938 GNUNET_free (tmp);
939 return GNUNET_SYSERR;
940 }
941 *ticket = (struct GNUNET_RECLAIM_Ticket *) decoded;
942 *rp_uri = GNUNET_strdup (rp_uri_str);
943 GNUNET_free (tmp);
944 return GNUNET_OK;
945}
946
947
958 const char*attr)
959{
960 char *scope_variables;
961 char *scope_variable;
962 char delimiter[] = " ";
963 int i;
964
965 scope_variables = GNUNET_strdup (scopes);
966 scope_variable = strtok (scope_variables, delimiter);
967 while (NULL != scope_variable)
968 {
969 if (0 == strcmp ("profile", scope_variable))
970 {
971 for (i = 0; i < 14; i++)
972 {
973 if (0 == strcmp (attr, OIDC_profile_claims[i]))
974 {
975 GNUNET_free (scope_variables);
976 return GNUNET_YES;
977 }
978 }
979 }
980 else if (0 == strcmp ("address", scope_variable))
981 {
982 for (i = 0; i < 5; i++)
983 {
984 if (0 == strcmp (attr, OIDC_address_claims[i]))
985 {
986 GNUNET_free (scope_variables);
987 return GNUNET_YES;
988 }
989 }
990 }
991 else if (0 == strcmp ("email", scope_variable))
992 {
993 for (i = 0; i < 2; i++)
994 {
995 if (0 == strcmp (attr, OIDC_email_claims[i]))
996 {
997 GNUNET_free (scope_variables);
998 return GNUNET_YES;
999 }
1000 }
1001 }
1002 else if (0 == strcmp ("phone", scope_variable))
1003 {
1004 for (i = 0; i < 2; i++)
1005 {
1006 if (0 == strcmp (attr, OIDC_phone_claims[i]))
1007 {
1008 GNUNET_free (scope_variables);
1009 return GNUNET_YES;
1010 }
1011 }
1012
1013 }
1014 else if (0 == strcmp (attr, scope_variable))
1015 {
1017 GNUNET_free (scope_variables);
1018 return GNUNET_YES;
1019 }
1020 scope_variable = strtok (NULL, delimiter);
1021 }
1022 GNUNET_free (scope_variables);
1023 return GNUNET_NO;
1024
1025}
static char * subject
Subject pubkey string.
Definition gnunet-abd.c:87
static int replace
Replace DID Document Flag.
Definition gnunet-did.c:53
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?
API to the GNS service.
API that can be used to manipulate GNS record data.
Identity attribute definitions.
reclaim service; implements identity and personal data sharing for GNUnet
#define GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN
Signature for a GNUid Ticket (Reclaim)
enum GNUNET_GenericReturnValue GNUNET_GNS_parse_ztld(const char *name, struct GNUNET_CRYPTO_BlindablePublicKey *ztld_key)
Try to parse the zTLD into a public key.
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32.
#define GNUNET_log(kind,...)
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_blinded_key_sign_(const struct GNUNET_CRYPTO_BlindablePrivateKey *priv, const struct GNUNET_CRYPTO_SignaturePurpose *purpose, struct GNUNET_CRYPTO_BlindableKeySignature *sig)
Sign a given block.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_blinded_key_signature_verify_(uint32_t purpose, const struct GNUNET_CRYPTO_SignaturePurpose *validate, const struct GNUNET_CRYPTO_BlindableKeySignature *sig, const struct GNUNET_CRYPTO_BlindablePublicKey *pub)
Verify a given signature.
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;.
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...
#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)
struct GNUNET_RECLAIM_PresentationList * GNUNET_RECLAIM_presentation_list_deserialize(const char *data, size_t data_size)
Deserialize a presentation list.
#define GNUNET_RECLAIM_id_is_zero(a)
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.
const char * GNUNET_RECLAIM_presentation_number_to_typename(uint32_t type)
Convert a presentation type number to the corresponding credential type string.
size_t GNUNET_RECLAIM_presentation_list_serialize(const struct GNUNET_RECLAIM_PresentationList *presentations, char *result)
Serialize a presentation list.
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.
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.
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.
size_t GNUNET_STRINGS_base64url_decode(const char *data, size_t len, void **out)
Decode from Base64url.
Definition strings.c:1778
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
Definition strings.c:807
size_t GNUNET_STRINGS_base64url_encode(const void *in, size_t len, char **output)
Encode into Base64url.
Definition strings.c:1667
size_t GNUNET_STRINGS_base64_decode(const char *data, size_t len, void **output)
Decode from Base64.
Definition strings.c:1720
size_t GNUNET_STRINGS_base64_encode(const void *in, size_t len, char **output)
Encode into Base64.
Definition strings.c:1618
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:452
static void replace_char(char *str, char find, char replace)
static char OIDC_email_claims[2][16]
Standard claims represented by the "email" scope in OIDC.
Definition oidc_helper.c:87
static json_t * generate_userinfo_json(const struct GNUNET_CRYPTO_BlindablePublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations)
static char OIDC_address_claims[5][32]
Standard claims represented by the "address" scope in OIDC.
static void fix_base64(char *str)
char * OIDC_generate_userinfo(const struct GNUNET_CRYPTO_BlindablePublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations)
Generate userinfo JSON as string.
char * OIDC_build_authz_code(const struct GNUNET_CRYPTO_BlindablePrivateKey *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.
static enum GNUNET_GenericReturnValue check_code_challenge(const char *code_challenge, uint32_t code_challenge_len, const char *code_verifier)
static enum GNUNET_GenericReturnValue is_claim_in_address_scope(const char *claim)
char * OIDC_generate_id_token_rsa(const char *rp_uri, const struct GNUNET_CRYPTO_BlindablePublicKey *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.
static char * generate_id_token_body(const char *rp_uri, const struct GNUNET_CRYPTO_BlindablePublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations, const struct GNUNET_TIME_Relative *expiration_time, const char *nonce)
char * OIDC_access_token_new(const struct GNUNET_RECLAIM_Ticket *ticket, const char *rp_uri)
Generate a new access token.
int OIDC_parse_authz_code(const char *rp_uri, const struct GNUNET_CRYPTO_BlindablePublicKey *cid, 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, char **emsg)
Parse reclaim ticket and nonce from authorization code.
static char * create_jwt_hmac_header(void)
int OIDC_access_token_parse(const char *token, struct GNUNET_RECLAIM_Ticket **ticket, char **rp_uri)
Parse an access token.
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...
static char OIDC_phone_claims[2][32]
Standard claims represented by the "phone" scope in OIDC.
Definition oidc_helper.c:94
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?
static GNUNET_NETWORK_STRUCT_END char OIDC_profile_claims[14][32]
Standard claims represented by the "profile" scope in OIDC.
Definition oidc_helper.c:78
char * OIDC_generate_id_token_hmac(const char *rp_uri, const struct GNUNET_CRYPTO_BlindablePublicKey *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.
#define JWT_TYP_VALUE
Definition oidc_helper.h:34
#define JWT_ALG
Definition oidc_helper.h:32
#define SERVER_ADDRESS
Definition oidc_helper.h:39
OIDC_VerificationOptions
Definition oidc_helper.h:42
@ OIDC_VERIFICATION_NO_CODE_VERIFIER
Do not check code verifier even if expected.
Definition oidc_helper.h:51
#define JWT_TYP
Definition oidc_helper.h:33
#define JWT_ALG_VALUE_HMAC
Definition oidc_helper.h:36
An identity signature as per LSD0001.
A private key for an identity as per LSD0001.
An identity key as per LSD0001.
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.
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.
char gns_name[63 *2+2]
The ticket.
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:46
struct GNUNET_RECLAIM_Ticket ticket
The reclaim ticket.
Definition oidc_helper.c:50
uint32_t pres_list_len
The length of the presentation list.
Definition oidc_helper.c:70
uint32_t nonce_len
The nonce length.
Definition oidc_helper.c:55
uint32_t attr_list_len
The length of the attributes list.
Definition oidc_helper.c:65
uint32_t code_challenge_len
The length of the PKCE code_challenge.
Definition oidc_helper.c:60
const char * str
Definition time.c:1252