GNUnet 0.25.2-1-g44a9a8846
 
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
151fix_base64 (char *str)
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_PublicKey *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,
418 const struct GNUNET_CRYPTO_PublicKey *sub_key,
419 const struct GNUNET_RECLAIM_AttributeList *attrs,
420 const struct
421 GNUNET_RECLAIM_PresentationList *presentations,
422 const struct GNUNET_TIME_Relative *expiration_time,
423 const char *nonce,
424 const json_t *secret_rsa_key)
425{
426 json_t *jws;
427 char *body_str;
428 char *result;
429
430 // Generate the body of the JSON Web Signature
431 body_str = generate_id_token_body (rp_uri,
432 sub_key,
433 attrs,
434 presentations,
435 expiration_time,
436 nonce);
437
438 if (NULL == body_str)
439 {
441 "Body for the JWS could not be generated\n");
442 return NULL;
443 }
444
445 // Creating the JSON Web Signature.
446 jws = json_pack ("{s:o}", "payload",
447 jose_b64_enc (body_str, strlen (body_str)));
448 GNUNET_free (body_str);
449
450 if (! jose_jws_sig (NULL, jws, NULL, secret_rsa_key))
451 {
453 "Signature generation failed\n");
454 return NULL;
455 }
456
457 // Encoding JSON as compact JSON Web Signature
458 GNUNET_asprintf (&result, "%s.%s.%s",
459 json_string_value (json_object_get (jws, "protected")),
460 json_string_value (json_object_get (jws, "payload")),
461 json_string_value (json_object_get (jws, "signature")) );
462
463 json_decref (jws);
464 return result;
465}
466
467
468char *
469OIDC_generate_id_token_hmac (const char *rp_uri,
470 const struct GNUNET_CRYPTO_PublicKey *sub_key,
471 const struct GNUNET_RECLAIM_AttributeList *attrs,
472 const struct
473 GNUNET_RECLAIM_PresentationList *presentations,
474 const struct GNUNET_TIME_Relative *expiration_time,
475 const char *nonce,
476 const char *secret_key)
477{
478 struct GNUNET_HashCode signature;
479 char *header;
480 char *header_base64;
481 char *body_str;
482 char *body_base64;
483 char *signature_target;
484 char *signature_base64;
485 char *result;
486
487 // Generate and encode Header
488 header = create_jwt_hmac_header ();
489 if (NULL == header)
490 {
492 "Header for the JWS could not be generated\n");
493 return NULL;
494 }
495 GNUNET_STRINGS_base64url_encode (header, strlen (header), &header_base64);
496 GNUNET_free (header);
497 fix_base64 (header_base64);
498
499 // Generate and encode the body of the JSON Web Signature
500 body_str = generate_id_token_body (rp_uri,
501 sub_key,
502 attrs,
503 presentations,
504 expiration_time,
505 nonce);
506
507 if (NULL == body_str)
508 {
510 "Body for the JWS could not be generated\n");
511 GNUNET_free (header_base64);
512 return NULL;
513 }
514
515 GNUNET_STRINGS_base64url_encode (body_str, strlen (body_str), &body_base64);
516 fix_base64 (body_base64);
517
522 GNUNET_asprintf (&signature_target, "%s.%s", header_base64, body_base64);
523 GNUNET_CRYPTO_hmac_raw (secret_key,
524 strlen (secret_key),
525 signature_target,
526 strlen (signature_target),
527 &signature);
528 GNUNET_STRINGS_base64url_encode ((const char *) &signature,
529 sizeof(struct GNUNET_HashCode),
530 &signature_base64);
531 fix_base64 (signature_base64);
532
534 "%s.%s.%s",
535 header_base64,
536 body_base64,
537 signature_base64);
538
539 GNUNET_free (header_base64);
540 GNUNET_free (body_str);
541 GNUNET_free (body_base64);
542 GNUNET_free (signature_target);
543 GNUNET_free (signature_base64);
544 return result;
545}
546
547
560char *
562 const struct GNUNET_RECLAIM_Ticket *ticket,
563 const struct GNUNET_RECLAIM_AttributeList *attrs,
564 const struct
565 GNUNET_RECLAIM_PresentationList *presentations,
566 const char *nonce_str,
567 const char *code_challenge)
568{
569 struct OIDC_Parameters params;
570 char *code_payload;
571 char *payload;
572 char *tmp;
573 char *code_str;
574 char *buf_ptr = NULL;
575 size_t payload_len;
576 size_t code_payload_len;
577 size_t attr_list_len = 0;
578 size_t pres_list_len = 0;
579 size_t code_challenge_len = 0;
580 uint32_t nonce_len = 0;
582
584 // Assign ticket
585 memset (&params, 0, sizeof(params));
586 memcpy (params.ticket.gns_name, ticket->gns_name, strlen (ticket->gns_name)
587 + 1);
588 // Assign nonce
589 payload_len = sizeof(struct OIDC_Parameters);
590 if ((NULL != nonce_str) && (strcmp ("", nonce_str) != 0))
591 {
592 nonce_len = strlen (nonce_str);
593 payload_len += nonce_len;
594 }
595 params.nonce_len = htonl (nonce_len);
596 // Assign code challenge
597 if (NULL != code_challenge)
598 code_challenge_len = strlen (code_challenge);
599 payload_len += code_challenge_len;
600 params.code_challenge_len = htonl (code_challenge_len);
601 // Assign attributes
602 if (NULL != attrs)
603 {
604 // Get length
606 params.attr_list_len = htonl (attr_list_len);
608 "Length of serialized attributes: %lu\n",
610 // Get serialized attributes
611 payload_len += attr_list_len;
612 }
613 if (NULL != presentations)
614 {
615 // Get length
616 // FIXME only add presentations relevant for attribute list!!!
617 // This is important because of the distinction between id_token and
618 // userinfo in OIDC
621 params.pres_list_len = htonl (pres_list_len);
623 "Length of serialized presentations: %lu\n",
625 // Get serialized attributes
626 payload_len += pres_list_len;
627 }
628
629 // Get plaintext length
630 payload = GNUNET_malloc (payload_len);
631 memcpy (payload, &params, sizeof(params));
632 tmp = payload + sizeof(params);
633 if (0 < code_challenge_len)
634 {
635 memcpy (tmp, code_challenge, code_challenge_len);
636 tmp += code_challenge_len;
637 }
638 if (0 < nonce_len)
639 {
640 memcpy (tmp, nonce_str, nonce_len);
641 tmp += nonce_len;
642 }
643 if (0 < attr_list_len)
645 tmp += attr_list_len;
646 if (0 < pres_list_len)
648 tmp += pres_list_len;
649
652 // Get length
653 code_payload_len = sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
654 + payload_len + sizeof(struct
657 "Length of data to encode: %lu\n",
658 code_payload_len);
659
660 // Initialize code payload
661 code_payload = GNUNET_malloc (code_payload_len);
662 GNUNET_assert (NULL != code_payload);
663 purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload;
664 purpose->size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
665 + payload_len);
667 // Store pubkey
668 buf_ptr = (char *) &purpose[1];
669 memcpy (buf_ptr, payload, payload_len);
671 buf_ptr += payload_len;
672 // Sign and store signature
673 if (GNUNET_SYSERR ==
674 GNUNET_CRYPTO_sign_ (issuer,
675 purpose,
676 (struct GNUNET_CRYPTO_Signature *)
677 buf_ptr))
678 {
679 GNUNET_break (0);
680 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unable to sign code\n");
681 GNUNET_free (code_payload);
682 return NULL;
683 }
684 GNUNET_STRINGS_base64url_encode (code_payload, code_payload_len, &code_str);
685 GNUNET_free (code_payload);
686 return code_str;
687}
688
689
691check_code_challenge (const char *code_challenge,
692 uint32_t code_challenge_len,
693 const char *code_verifier)
694{
695 char *code_verifier_hash;
696 char *expected_code_challenge;
697
698 if (0 == code_challenge_len) /* Only check if this code requires a CV */
699 return GNUNET_OK;
700 if (NULL == code_verifier)
701 {
703 "Expected code verifier!\n");
704 return GNUNET_SYSERR;
705 }
706 code_verifier_hash = GNUNET_malloc (256 / 8);
707 // hash code verifier
708 gcry_md_hash_buffer (GCRY_MD_SHA256,
709 code_verifier_hash,
710 code_verifier,
711 strlen (code_verifier));
712 // encode code verifier
713 GNUNET_STRINGS_base64url_encode (code_verifier_hash, 256 / 8,
714 &expected_code_challenge);
715 GNUNET_free (code_verifier_hash);
716 if (0 !=
717 strncmp (expected_code_challenge, code_challenge, code_challenge_len))
718 {
720 "Invalid code verifier! Expected: %s, Got: %.*s\n",
721 expected_code_challenge,
722 code_challenge_len,
723 code_challenge);
724 GNUNET_free (expected_code_challenge);
725 return GNUNET_SYSERR;
726 }
727 GNUNET_free (expected_code_challenge);
728 return GNUNET_OK;
729}
730
731
747int
748OIDC_parse_authz_code (const char *rp_uri,
749 const struct GNUNET_CRYPTO_PublicKey *cid,
750 const char *code,
751 const char *code_verifier,
753 struct GNUNET_RECLAIM_AttributeList **attrs,
754 struct GNUNET_RECLAIM_PresentationList **presentations,
755 char **nonce_str,
756 enum OIDC_VerificationOptions opts, char **emsg)
757{
758 char *code_payload;
759 char *ptr;
760 char *plaintext;
761 char *attrs_ser;
762 char *presentations_ser;
763 char *code_challenge;
765 struct GNUNET_CRYPTO_Signature *signature;
766 struct GNUNET_CRYPTO_PublicKey iss;
767 uint32_t code_challenge_len;
768 uint32_t attrs_ser_len;
769 uint32_t pres_ser_len;
770 size_t plaintext_len;
771 size_t code_payload_len;
772 uint32_t nonce_len = 0;
773 struct OIDC_Parameters *params;
774
775
777 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to decode `%s'\n", code);
778 code_payload = NULL;
779 code_payload_len =
780 GNUNET_STRINGS_base64url_decode (code, strlen (code),
781 (void **) &code_payload);
782 if (code_payload_len < sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
783 + sizeof(struct OIDC_Parameters)
784 + sizeof(struct GNUNET_CRYPTO_Signature))
785 {
786 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Authorization code malformed\n");
787 GNUNET_free (code_payload);
788 return GNUNET_SYSERR;
789 }
790
791 purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) code_payload;
792 plaintext_len = code_payload_len;
793 plaintext_len -= sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose);
794 ptr = (char *) &purpose[1];
795 plaintext_len -= sizeof(struct GNUNET_CRYPTO_Signature);
796 plaintext = ptr;
797 ptr += plaintext_len;
798 signature = (struct GNUNET_CRYPTO_Signature *) ptr;
799 params = (struct OIDC_Parameters *) plaintext;
800
801 // cmp code_challenge code_verifier
802 code_challenge_len = ntohl (params->code_challenge_len);
803 code_challenge = ((char *) &params[1]);
805 {
806 if (GNUNET_OK != check_code_challenge (code_challenge,
808 code_verifier))
809 {
810 GNUNET_asprintf (emsg, "Code verifier `%s' invalid for challenge `%s'",
811 code_verifier, code_challenge);
812 GNUNET_free (code_payload);
813 return GNUNET_SYSERR;
814 }
815 }
816 nonce_len = ntohl (params->nonce_len);
817 if (0 != nonce_len)
818 {
819 *nonce_str = GNUNET_strndup (code_challenge + code_challenge_len,
820 nonce_len);
821 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got nonce: %s\n", *nonce_str);
822 }
823
824 // Ticket
825 memcpy (ticket, &params->ticket, sizeof(params->ticket));
826 // Signature
827 // GNUNET_CRYPTO_ecdsa_key_get_public (ecdsa_priv, &ecdsa_pub);
828 if (GNUNET_OK !=
831 purpose,
832 signature,
833 &iss))
834 {
835 GNUNET_free (code_payload);
836 if (NULL != *nonce_str)
837 GNUNET_free (*nonce_str);
838 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Signature of AuthZ code invalid!\n");
839 *emsg = GNUNET_strdup ("Signature verification failed");
840 return GNUNET_SYSERR;
841 }
842 // Attributes
843 attrs_ser = ((char *) &params[1]) + code_challenge_len + nonce_len;
844 attrs_ser_len = ntohl (params->attr_list_len);
845 *attrs = GNUNET_RECLAIM_attribute_list_deserialize (attrs_ser, attrs_ser_len);
846 presentations_ser = ((char*) attrs_ser) + attrs_ser_len;
847 pres_ser_len = ntohl (params->pres_list_len);
848 *presentations =
850 pres_ser_len);
851
852 GNUNET_free (code_payload);
853 return GNUNET_OK;
854}
855
856
866void
867OIDC_build_token_response (const char *access_token,
868 const char *id_token,
869 const struct GNUNET_TIME_Relative *expiration_time,
870 char **token_response)
871{
872 json_t *root_json;
873
874 root_json = json_object ();
875
876 GNUNET_assert (NULL != access_token);
877 GNUNET_assert (NULL != id_token);
878 GNUNET_assert (NULL != expiration_time);
879 json_object_set_new (root_json, "access_token", json_string (access_token));
880 json_object_set_new (root_json, "token_type", json_string ("Bearer"));
881 json_object_set_new (root_json,
882 "expires_in",
883 json_integer (expiration_time->rel_value_us
884 / (1000 * 1000)));
885 json_object_set_new (root_json, "id_token", json_string (id_token));
886 *token_response = json_dumps (root_json, JSON_INDENT (0) | JSON_COMPACT);
887 json_decref (root_json);
888}
889
890
894char *
896 const char *rp_uri)
897{
898 char *access_token;
899 char *tkt_b64;
900
902 sizeof(*ticket),
903 &tkt_b64);
904 GNUNET_asprintf (&access_token, "%s-%s", tkt_b64, rp_uri);
905 GNUNET_free (tkt_b64);
906 return access_token;
907}
908
909
913int
914OIDC_access_token_parse (const char *token,
916 char **rp_uri)
917{
918 size_t sret;
919 char *decoded;
920 char *tmp;
921 char *tkt_str;
922 char *rp_uri_str;
923 tmp = GNUNET_strdup (token);
924 tkt_str = strtok (tmp, "-");
925 GNUNET_assert (NULL != tkt_str); // FIXME handle
926 rp_uri_str = strtok (NULL, "-");
927 GNUNET_assert (NULL != rp_uri_str); // FIXME handle
928 sret = GNUNET_STRINGS_base64_decode (tkt_str,
929 strlen (tkt_str),
930 (void**) &decoded);
931 if (sizeof (struct GNUNET_RECLAIM_Ticket) != sret)
932 {
933 GNUNET_free (decoded);
934 GNUNET_free (tmp);
935 return GNUNET_SYSERR;
936 }
937 *ticket = (struct GNUNET_RECLAIM_Ticket *) decoded;
938 *rp_uri = GNUNET_strdup (rp_uri_str);
939 GNUNET_free (tmp);
940 return GNUNET_OK;
941}
942
943
954 const char*attr)
955{
956 char *scope_variables;
957 char *scope_variable;
958 char delimiter[] = " ";
959 int i;
960
961 scope_variables = GNUNET_strdup (scopes);
962 scope_variable = strtok (scope_variables, delimiter);
963 while (NULL != scope_variable)
964 {
965 if (0 == strcmp ("profile", scope_variable))
966 {
967 for (i = 0; i < 14; i++)
968 {
969 if (0 == strcmp (attr, OIDC_profile_claims[i]))
970 {
971 GNUNET_free (scope_variables);
972 return GNUNET_YES;
973 }
974 }
975 }
976 else if (0 == strcmp ("address", scope_variable))
977 {
978 for (i = 0; i < 5; i++)
979 {
980 if (0 == strcmp (attr, OIDC_address_claims[i]))
981 {
982 GNUNET_free (scope_variables);
983 return GNUNET_YES;
984 }
985 }
986 }
987 else if (0 == strcmp ("email", scope_variable))
988 {
989 for (i = 0; i < 2; i++)
990 {
991 if (0 == strcmp (attr, OIDC_email_claims[i]))
992 {
993 GNUNET_free (scope_variables);
994 return GNUNET_YES;
995 }
996 }
997 }
998 else if (0 == strcmp ("phone", scope_variable))
999 {
1000 for (i = 0; i < 2; i++)
1001 {
1002 if (0 == strcmp (attr, OIDC_phone_claims[i]))
1003 {
1004 GNUNET_free (scope_variables);
1005 return GNUNET_YES;
1006 }
1007 }
1008
1009 }
1010 else if (0 == strcmp (attr, scope_variable))
1011 {
1013 GNUNET_free (scope_variables);
1014 return GNUNET_YES;
1015 }
1016 scope_variable = strtok (NULL, delimiter);
1017 }
1018 GNUNET_free (scope_variables);
1019 return GNUNET_NO;
1020
1021}
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_PublicKey *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_signature_verify_(uint32_t purpose, const struct GNUNET_CRYPTO_EccSignaturePurpose *validate, const struct GNUNET_CRYPTO_Signature *sig, const struct GNUNET_CRYPTO_PublicKey *pub)
Verify a given signature.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_sign_(const struct GNUNET_CRYPTO_PrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_Signature *sig)
Sign a given block.
#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
char * OIDC_generate_id_token_rsa(const char *rp_uri, const struct GNUNET_CRYPTO_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.
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_PublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations)
Generate userinfo JSON as string.
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)
int OIDC_parse_authz_code(const char *rp_uri, const struct GNUNET_CRYPTO_PublicKey *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.
char * OIDC_build_authz_code(const struct GNUNET_CRYPTO_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.
char * OIDC_generate_id_token_hmac(const char *rp_uri, const struct GNUNET_CRYPTO_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.
char * OIDC_access_token_new(const struct GNUNET_RECLAIM_Ticket *ticket, const char *rp_uri)
Generate a new access token.
static char * generate_id_token_body(const char *rp_uri, const struct GNUNET_CRYPTO_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)
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 json_t * generate_userinfo_json(const struct GNUNET_CRYPTO_PublicKey *sub_key, const struct GNUNET_RECLAIM_AttributeList *attrs, const struct GNUNET_RECLAIM_PresentationList *presentations)
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
#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
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 private key for an identity as per LSD0001.
An identity key as per LSD0001.
An identity signature as per LSD0001.
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