diff options
author | Alexia Pagkopoulou <a.pagkopoulou@tum.de> | 2019-09-04 15:27:54 +0200 |
---|---|---|
committer | Alexia Pagkopoulou <a.pagkopoulou@tum.de> | 2019-09-04 15:27:54 +0200 |
commit | de8c2a206a6e1fe92cf01be548b6069e7e78e679 (patch) | |
tree | 442fe3732d8ca787d63c431a43861300f95f0400 /src/reclaim | |
parent | 86d9a1259ace3d5c6cf646a6d61f7f424b50a112 (diff) | |
download | gnunet-de8c2a206a6e1fe92cf01be548b6069e7e78e679.tar.gz gnunet-de8c2a206a6e1fe92cf01be548b6069e7e78e679.zip |
support for PKCE extension
Diffstat (limited to 'src/reclaim')
-rw-r--r-- | src/reclaim/Makefile.am | 3 | ||||
-rw-r--r-- | src/reclaim/oidc_helper.c | 179 | ||||
-rw-r--r-- | src/reclaim/oidc_helper.h | 8 | ||||
-rw-r--r-- | src/reclaim/plugin_rest_openid_connect.c | 55 |
4 files changed, 183 insertions, 62 deletions
diff --git a/src/reclaim/Makefile.am b/src/reclaim/Makefile.am index 6937b1af6..69dcc605e 100644 --- a/src/reclaim/Makefile.am +++ b/src/reclaim/Makefile.am | |||
@@ -77,7 +77,8 @@ libgnunet_plugin_rest_openid_connect_la_LIBADD = \ | |||
77 | $(top_builddir)/src/gns/libgnunetgns.la \ | 77 | $(top_builddir)/src/gns/libgnunetgns.la \ |
78 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | 78 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ |
79 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ | 79 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ |
80 | $(LTLIBINTL) -ljansson $(MHD_LIBS) | 80 | $(LTLIBINTL) -ljansson $(MHD_LIBS) \ |
81 | $(LIBGCRYPT_LIBS) | ||
81 | libgnunet_plugin_rest_openid_connect_la_LDFLAGS = \ | 82 | libgnunet_plugin_rest_openid_connect_la_LDFLAGS = \ |
82 | $(GN_PLUGIN_LDFLAGS) | 83 | $(GN_PLUGIN_LDFLAGS) |
83 | libgnunet_plugin_rest_openid_connect_la_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS) | 84 | libgnunet_plugin_rest_openid_connect_la_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS) |
diff --git a/src/reclaim/oidc_helper.c b/src/reclaim/oidc_helper.c index d2789f978..01a3d0179 100644 --- a/src/reclaim/oidc_helper.c +++ b/src/reclaim/oidc_helper.c | |||
@@ -31,7 +31,48 @@ | |||
31 | #include "gnunet_reclaim_service.h" | 31 | #include "gnunet_reclaim_service.h" |
32 | #include "gnunet_signatures.h" | 32 | #include "gnunet_signatures.h" |
33 | #include "oidc_helper.h" | 33 | #include "oidc_helper.h" |
34 | //#include "benchmark.h" | ||
35 | #include <gcrypt.h> | ||
34 | 36 | ||
37 | GNUNET_NETWORK_STRUCT_BEGIN | ||
38 | |||
39 | /** | ||
40 | * The signature used to generate the authorization code | ||
41 | */ | ||
42 | struct OIDC_Parameters | ||
43 | { | ||
44 | /** | ||
45 | * The reclaim ticket | ||
46 | */ | ||
47 | const struct GNUNET_RECLAIM_Ticket *ticket; | ||
48 | |||
49 | /** | ||
50 | * The nonce | ||
51 | */ | ||
52 | uint32_t nonce GNUNET_PACKED; | ||
53 | |||
54 | /** | ||
55 | * The length of the PKCE code_challenge | ||
56 | */ | ||
57 | uint16_t code_challenge_len GNUNET_PACKED; | ||
58 | |||
59 | /** | ||
60 | * The length of the attributes list | ||
61 | */ | ||
62 | uint16_t attr_list_len GNUNET_PACKED; | ||
63 | |||
64 | /** | ||
65 | * The PKCE code_challenge | ||
66 | */ | ||
67 | const char *code_challenge; | ||
68 | |||
69 | /** | ||
70 | * The (serialized) attributes | ||
71 | */ | ||
72 | char *attrs_ser; | ||
73 | }; | ||
74 | |||
75 | GNUNET_NETWORK_STRUCT_END | ||
35 | 76 | ||
36 | static char * | 77 | static char * |
37 | create_jwt_header (void) | 78 | create_jwt_header (void) |
@@ -371,30 +412,30 @@ encrypt_payload (const struct GNUNET_CRYPTO_EcdsaPublicKey *ecdsa_pub, | |||
371 | GNUNET_CRYPTO_symmetric_encrypt (payload, payload_len, &key, &iv, buf)); | 412 | GNUNET_CRYPTO_symmetric_encrypt (payload, payload_len, &key, &iv, buf)); |
372 | } | 413 | } |
373 | 414 | ||
374 | |||
375 | /** | 415 | /** |
376 | * Builds an OIDC authorization code including | 416 | * Builds an OIDC authorization code including |
377 | * a reclaim ticket and nonce | 417 | * a reclaim ticket and nonce |
378 | * | 418 | * |
379 | * @param issuer the issuer of the ticket, used to sign the ticket and nonce | 419 | * @param issuer the issuer of the ticket, used to sign the ticket and nonce |
380 | * @param ticket the ticket to include in the code | 420 | * @param ticket the ticket to include in the code |
381 | * @param attrs list of attributes whicha re shared | 421 | * @param attrs list of attributes which are shared |
382 | * @param nonce the nonce to include in the code | 422 | * @param nonce the nonce to include in the code |
423 | * @param code_challenge PKCE code challenge | ||
383 | * @return a new authorization code (caller must free) | 424 | * @return a new authorization code (caller must free) |
384 | */ | 425 | */ |
385 | char * | 426 | char * |
386 | OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, | 427 | OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, |
387 | const struct GNUNET_RECLAIM_Ticket *ticket, | 428 | const struct GNUNET_RECLAIM_Ticket *ticket, |
388 | struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, | 429 | struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, |
389 | const char *nonce_str) | 430 | const char *nonce_str, |
431 | const char *code_challenge) | ||
390 | { | 432 | { |
433 | struct OIDC_Parameters *params = GNUNET_new (struct OIDC_Parameters); | ||
391 | char *code_payload; | 434 | char *code_payload; |
392 | char *plaintext; | 435 | char *plaintext; |
393 | char *attrs_ser; | ||
394 | char *code_str; | 436 | char *code_str; |
395 | char *buf_ptr; | 437 | char *buf_ptr = NULL; |
396 | size_t signature_payload_len; | 438 | size_t signature_payload_len; |
397 | size_t attr_list_len; | ||
398 | size_t code_payload_len; | 439 | size_t code_payload_len; |
399 | uint32_t nonce; | 440 | uint32_t nonce; |
400 | uint32_t nonce_tmp; | 441 | uint32_t nonce_tmp; |
@@ -402,61 +443,67 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, | |||
402 | struct GNUNET_CRYPTO_EcdhePrivateKey *ecdh_priv; | 443 | struct GNUNET_CRYPTO_EcdhePrivateKey *ecdh_priv; |
403 | struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pub; | 444 | struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pub; |
404 | 445 | ||
405 | attrs_ser = NULL; | 446 | /** PLAINTEXT **/ |
406 | signature_payload_len = | 447 | // Assign ticket |
407 | sizeof (struct GNUNET_RECLAIM_Ticket) + sizeof (uint32_t); | 448 | params->ticket = ticket; |
408 | 449 | // Assign nonce | |
409 | if (NULL != attrs) | ||
410 | { | ||
411 | attr_list_len = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (attrs); | ||
412 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
413 | "Length of serialized attributes: %lu\n", | ||
414 | attr_list_len); | ||
415 | signature_payload_len += attr_list_len; | ||
416 | attrs_ser = GNUNET_malloc (attr_list_len); | ||
417 | GNUNET_RECLAIM_ATTRIBUTE_list_serialize (attrs, attrs_ser); | ||
418 | } | ||
419 | |||
420 | code_payload_len = sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + | ||
421 | sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + | ||
422 | signature_payload_len + | ||
423 | sizeof (struct GNUNET_CRYPTO_EcdsaSignature); | ||
424 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
425 | "Length of data to encode: %lu\n", | ||
426 | code_payload_len); | ||
427 | plaintext = GNUNET_malloc (signature_payload_len); | ||
428 | // First, copy ticket | ||
429 | buf_ptr = plaintext; | ||
430 | memcpy (buf_ptr, ticket, sizeof (struct GNUNET_RECLAIM_Ticket)); | ||
431 | buf_ptr += sizeof (struct GNUNET_RECLAIM_Ticket); | ||
432 | |||
433 | // Then copy nonce | ||
434 | nonce = 0; | 450 | nonce = 0; |
435 | if (NULL != nonce_str && strcmp("", nonce_str) != 0) | 451 | if (NULL != nonce_str && strcmp("", nonce_str) != 0) |
436 | { | 452 | { |
437 | if ((1 != SSCANF (nonce_str, "%u", &nonce)) || (nonce > UINT32_MAX)) | 453 | if ((1 != SSCANF (nonce_str, "%u", &nonce)) || (nonce > UINT32_MAX)) |
438 | { | 454 | { |
439 | GNUNET_break (0); | 455 | GNUNET_break (0); |
440 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid nonce %s\n", nonce_str); | 456 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid nonce %s\n", nonce_str); |
441 | GNUNET_free (plaintext); | 457 | GNUNET_free (params); |
442 | GNUNET_free_non_null (attrs_ser); | ||
443 | return NULL; | 458 | return NULL; |
444 | } | 459 | } |
445 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 460 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
446 | "Got nonce: %u from %s\n", | 461 | "Got nonce: %u from %s\n", |
447 | nonce, | 462 | nonce, |
448 | nonce_str); | 463 | nonce_str); |
449 | } | 464 | } |
450 | nonce_tmp = htonl (nonce); | 465 | nonce_tmp = htonl (nonce); |
451 | memcpy (buf_ptr, &nonce_tmp, sizeof (uint32_t)); | 466 | params->nonce = nonce_tmp; |
452 | buf_ptr += sizeof (uint32_t); | 467 | // Assign code challenge |
453 | 468 | if (NULL == code_challenge || strcmp("", code_challenge) == 0) | |
454 | // Finally, attributes | 469 | { |
455 | if (NULL != attrs_ser) | 470 | GNUNET_break (0); |
471 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "PKCE: Code challenge missing"); | ||
472 | GNUNET_free (params); | ||
473 | return NULL; | ||
474 | } | ||
475 | params->code_challenge_len = strlen (code_challenge); | ||
476 | params->code_challenge = code_challenge; | ||
477 | // Assign attributes | ||
478 | params->attrs_ser = NULL; | ||
479 | if (NULL != attrs) | ||
456 | { | 480 | { |
457 | memcpy (buf_ptr, attrs_ser, attr_list_len); | 481 | // Get length |
458 | GNUNET_free (attrs_ser); | 482 | params->attr_list_len = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (attrs); |
483 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
484 | "Length of serialized attributes: %lu\n", | ||
485 | params->attr_list_len); | ||
486 | // Get serialized attributes | ||
487 | params->attrs_ser = GNUNET_malloc (params->attr_list_len); | ||
488 | GNUNET_RECLAIM_ATTRIBUTE_list_serialize (attrs, params->attrs_ser); | ||
459 | } | 489 | } |
490 | |||
491 | // Get plaintext length | ||
492 | signature_payload_len = sizeof (struct OIDC_Parameters); | ||
493 | plaintext = GNUNET_malloc (signature_payload_len); | ||
494 | memcpy (plaintext, params, signature_payload_len); | ||
495 | /** END **/ | ||
496 | |||
497 | /** ENCRYPT **/ | ||
498 | // Get length | ||
499 | code_payload_len = sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + | ||
500 | sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + | ||
501 | signature_payload_len + | ||
502 | sizeof (struct GNUNET_CRYPTO_EcdsaSignature); | ||
503 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
504 | "Length of data to encode: %lu\n", | ||
505 | code_payload_len); | ||
506 | |||
460 | // Generate ECDH key | 507 | // Generate ECDH key |
461 | ecdh_priv = GNUNET_CRYPTO_ecdhe_key_create (); | 508 | ecdh_priv = GNUNET_CRYPTO_ecdhe_key_create (); |
462 | GNUNET_CRYPTO_ecdhe_key_get_public (ecdh_priv, &ecdh_pub); | 509 | GNUNET_CRYPTO_ecdhe_key_get_public (ecdh_priv, &ecdh_pub); |
@@ -479,6 +526,7 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, | |||
479 | buf_ptr); | 526 | buf_ptr); |
480 | GNUNET_free (ecdh_priv); | 527 | GNUNET_free (ecdh_priv); |
481 | GNUNET_free (plaintext); | 528 | GNUNET_free (plaintext); |
529 | GNUNET_free (params); | ||
482 | buf_ptr += signature_payload_len; | 530 | buf_ptr += signature_payload_len; |
483 | // Sign and store signature | 531 | // Sign and store signature |
484 | if (GNUNET_SYSERR == | 532 | if (GNUNET_SYSERR == |
@@ -505,6 +553,7 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, | |||
505 | * | 553 | * |
506 | * @param audience the expected audience of the code | 554 | * @param audience the expected audience of the code |
507 | * @param code the string representation of the code | 555 | * @param code the string representation of the code |
556 | * @param code_verfier PKCE code verifier | ||
508 | * @param ticket where to store the ticket | 557 | * @param ticket where to store the ticket |
509 | * @param attrs the attributes in the code | 558 | * @param attrs the attributes in the code |
510 | * @param nonce where to store the nonce | 559 | * @param nonce where to store the nonce |
@@ -513,6 +562,7 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, | |||
513 | int | 562 | int |
514 | OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv, | 563 | OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv, |
515 | const char *code, | 564 | const char *code, |
565 | const char *code_verifier, | ||
516 | struct GNUNET_RECLAIM_Ticket *ticket, | 566 | struct GNUNET_RECLAIM_Ticket *ticket, |
517 | struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList **attrs, | 567 | struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList **attrs, |
518 | char **nonce_str) | 568 | char **nonce_str) |
@@ -520,6 +570,7 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv, | |||
520 | char *code_payload; | 570 | char *code_payload; |
521 | char *ptr; | 571 | char *ptr; |
522 | char *plaintext; | 572 | char *plaintext; |
573 | char *code_verifier_tmp; | ||
523 | struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; | 574 | struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; |
524 | struct GNUNET_CRYPTO_EcdsaSignature *signature; | 575 | struct GNUNET_CRYPTO_EcdsaSignature *signature; |
525 | struct GNUNET_CRYPTO_EcdsaPublicKey ecdsa_pub; | 576 | struct GNUNET_CRYPTO_EcdsaPublicKey ecdsa_pub; |
@@ -529,6 +580,7 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv, | |||
529 | size_t signature_offset; | 580 | size_t signature_offset; |
530 | size_t plaintext_len; | 581 | size_t plaintext_len; |
531 | uint32_t nonce = 0; | 582 | uint32_t nonce = 0; |
583 | struct OIDC_Parameters *params; | ||
532 | 584 | ||
533 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to decode `%s'\n", code); | 585 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to decode `%s'\n", code); |
534 | code_payload = NULL; | 586 | code_payload = NULL; |
@@ -558,19 +610,35 @@ OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv, | |||
558 | plaintext_len = attrs_ser_len - sizeof (struct GNUNET_CRYPTO_EcdsaSignature); | 610 | plaintext_len = attrs_ser_len - sizeof (struct GNUNET_CRYPTO_EcdsaSignature); |
559 | plaintext = GNUNET_malloc (plaintext_len); | 611 | plaintext = GNUNET_malloc (plaintext_len); |
560 | decrypt_payload (ecdsa_priv, ecdh_pub, ptr, plaintext_len, plaintext); | 612 | decrypt_payload (ecdsa_priv, ecdh_pub, ptr, plaintext_len, plaintext); |
561 | ptr = plaintext; | 613 | //ptr = plaintext; |
614 | params = (struct OIDC_Parameters *) plaintext; | ||
615 | |||
616 | // cmp code_challenge code_verifier | ||
617 | code_verifier_tmp = GNUNET_malloc (strlen (code_verifier)); | ||
618 | // hash code verifier | ||
619 | gcry_md_hash_buffer (GCRY_MD_SHA256, | ||
620 | code_verifier_tmp, | ||
621 | code_verifier, | ||
622 | strlen(code_verifier)); | ||
623 | // encode code verifier | ||
624 | code_verifier_tmp = base64_encode (code_verifier_tmp, strlen (code_verifier_tmp)); | ||
625 | |||
626 | if (0 != strcmp (code_verifier_tmp, params->code_challenge)) | ||
627 | { | ||
628 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid code verifier\n"); | ||
629 | GNUNET_free_non_null (code_payload); | ||
630 | GNUNET_free (code_verifier_tmp); | ||
631 | return GNUNET_SYSERR; | ||
632 | } | ||
633 | GNUNET_free (code_verifier_tmp); | ||
634 | |||
562 | // Ticket | 635 | // Ticket |
563 | *ticket = *((struct GNUNET_RECLAIM_Ticket *) ptr); | 636 | ticket = params->ticket; |
564 | attrs_ser_len -= sizeof (struct GNUNET_RECLAIM_Ticket); | ||
565 | ptr += sizeof (struct GNUNET_RECLAIM_Ticket); | ||
566 | // Nonce | 637 | // Nonce |
567 | nonce = ntohl (*((uint32_t *) ptr)); | 638 | nonce = ntohl (params->nonce);//ntohl (*((uint32_t *) ptr)); |
568 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got nonce: %u\n", nonce); | 639 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got nonce: %u\n", nonce); |
569 | attrs_ser_len -= sizeof (uint32_t); | ||
570 | ptr += sizeof (uint32_t); | ||
571 | // Attributes | 640 | // Attributes |
572 | attrs_ser_len -= sizeof (struct GNUNET_CRYPTO_EcdsaSignature); | 641 | *attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (params->attrs_ser, params->attr_list_len); |
573 | *attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (ptr, attrs_ser_len); | ||
574 | // Signature | 642 | // Signature |
575 | signature_offset = | 643 | signature_offset = |
576 | code_payload_len - sizeof (struct GNUNET_CRYPTO_EcdsaSignature); | 644 | code_payload_len - sizeof (struct GNUNET_CRYPTO_EcdsaSignature); |
@@ -656,3 +724,4 @@ OIDC_access_token_new () | |||
656 | &access_token); | 724 | &access_token); |
657 | return access_token; | 725 | return access_token; |
658 | } | 726 | } |
727 | |||
diff --git a/src/reclaim/oidc_helper.h b/src/reclaim/oidc_helper.h index 6c10a4ab0..10e43ea27 100644 --- a/src/reclaim/oidc_helper.h +++ b/src/reclaim/oidc_helper.h | |||
@@ -64,13 +64,15 @@ OIDC_id_token_new (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, | |||
64 | * @param ticket the ticket to include in the code | 64 | * @param ticket the ticket to include in the code |
65 | * @param attrs list of attributes to share | 65 | * @param attrs list of attributes to share |
66 | * @param nonce the nonce to include in the code | 66 | * @param nonce the nonce to include in the code |
67 | * @param code_challenge PKCE code challenge | ||
67 | * @return a new authorization code (caller must free) | 68 | * @return a new authorization code (caller must free) |
68 | */ | 69 | */ |
69 | char* | 70 | char* |
70 | OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, | 71 | OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, |
71 | const struct GNUNET_RECLAIM_Ticket *ticket, | 72 | const struct GNUNET_RECLAIM_Ticket *ticket, |
72 | struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, | 73 | struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs, |
73 | const char* nonce); | 74 | const char *nonce, |
75 | const char *code_challenge); | ||
74 | 76 | ||
75 | /** | 77 | /** |
76 | * Parse reclaim ticket and nonce from | 78 | * Parse reclaim ticket and nonce from |
@@ -79,6 +81,7 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, | |||
79 | * | 81 | * |
80 | * @param ecdsa_priv the audience of the ticket | 82 | * @param ecdsa_priv the audience of the ticket |
81 | * @param code the string representation of the code | 83 | * @param code the string representation of the code |
84 | * @param code_verfier PKCE code verifier | ||
82 | * @param ticket where to store the ticket | 85 | * @param ticket where to store the ticket |
83 | * @param attrs the attributes found in the code | 86 | * @param attrs the attributes found in the code |
84 | * @param nonce where to store the nonce | 87 | * @param nonce where to store the nonce |
@@ -86,7 +89,8 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, | |||
86 | */ | 89 | */ |
87 | int | 90 | int |
88 | OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv, | 91 | OIDC_parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa_priv, |
89 | const char* code, | 92 | const char *code, |
93 | const char *code_verifier, | ||
90 | struct GNUNET_RECLAIM_Ticket *ticket, | 94 | struct GNUNET_RECLAIM_Ticket *ticket, |
91 | struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList **attrs, | 95 | struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList **attrs, |
92 | char **nonce); | 96 | char **nonce); |
diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c index 03e037261..a16e6592c 100644 --- a/src/reclaim/plugin_rest_openid_connect.c +++ b/src/reclaim/plugin_rest_openid_connect.c | |||
@@ -120,6 +120,16 @@ | |||
120 | #define OIDC_NONCE_KEY "nonce" | 120 | #define OIDC_NONCE_KEY "nonce" |
121 | 121 | ||
122 | /** | 122 | /** |
123 | * OIDC PKCE code challenge | ||
124 | */ | ||
125 | #define OIDC_CODE_CHALLENGE_KEY "code_challenge" | ||
126 | |||
127 | /** | ||
128 | * OIDC PKCE code verifier | ||
129 | */ | ||
130 | #define OIDC_CODE_VERIFIER_KEY "code_verifier" | ||
131 | |||
132 | /** | ||
123 | * OIDC cookie expiration (in seconds) | 133 | * OIDC cookie expiration (in seconds) |
124 | */ | 134 | */ |
125 | #define OIDC_COOKIE_EXPIRATION 3 | 135 | #define OIDC_COOKIE_EXPIRATION 3 |
@@ -296,6 +306,16 @@ struct OIDC_Variables | |||
296 | int user_cancelled; | 306 | int user_cancelled; |
297 | 307 | ||
298 | /** | 308 | /** |
309 | * The PKCE code_challenge | ||
310 | */ | ||
311 | char *code_challenge; | ||
312 | |||
313 | /** | ||
314 | * The PKCE code_verifier | ||
315 | */ | ||
316 | char *code_verifier; | ||
317 | |||
318 | /** | ||
299 | * The response JSON | 319 | * The response JSON |
300 | */ | 320 | */ |
301 | json_t *response; | 321 | json_t *response; |
@@ -812,7 +832,7 @@ login_redirect (void *cls) | |||
812 | &login_base_url)) | 832 | &login_base_url)) |
813 | { | 833 | { |
814 | GNUNET_asprintf (&new_redirect, | 834 | GNUNET_asprintf (&new_redirect, |
815 | "%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s", | 835 | "%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s", |
816 | login_base_url, | 836 | login_base_url, |
817 | OIDC_RESPONSE_TYPE_KEY, | 837 | OIDC_RESPONSE_TYPE_KEY, |
818 | handle->oidc->response_type, | 838 | handle->oidc->response_type, |
@@ -824,6 +844,8 @@ login_redirect (void *cls) | |||
824 | handle->oidc->scope, | 844 | handle->oidc->scope, |
825 | OIDC_STATE_KEY, | 845 | OIDC_STATE_KEY, |
826 | (NULL != handle->oidc->state) ? handle->oidc->state : "", | 846 | (NULL != handle->oidc->state) ? handle->oidc->state : "", |
847 | OIDC_CODE_CHALLENGE_KEY, | ||
848 | (NULL != handle->oidc->code_challenge) ? handle->oidc->code_challenge : "", | ||
827 | OIDC_NONCE_KEY, | 849 | OIDC_NONCE_KEY, |
828 | (NULL != handle->oidc->nonce) ? handle->oidc->nonce : ""); | 850 | (NULL != handle->oidc->nonce) ? handle->oidc->nonce : ""); |
829 | resp = GNUNET_REST_create_response (""); | 851 | resp = GNUNET_REST_create_response (""); |
@@ -885,7 +907,8 @@ oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket) | |||
885 | code_string = OIDC_build_authz_code (&handle->priv_key, | 907 | code_string = OIDC_build_authz_code (&handle->priv_key, |
886 | &handle->ticket, | 908 | &handle->ticket, |
887 | handle->attr_list, | 909 | handle->attr_list, |
888 | handle->oidc->nonce); | 910 | handle->oidc->nonce, |
911 | handle->oidc->code_challenge); | ||
889 | if ((NULL != handle->redirect_prefix) && (NULL != handle->redirect_suffix) && | 912 | if ((NULL != handle->redirect_prefix) && (NULL != handle->redirect_suffix) && |
890 | (NULL != handle->tld)) | 913 | (NULL != handle->tld)) |
891 | { | 914 | { |
@@ -1382,6 +1405,17 @@ authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
1382 | return; | 1405 | return; |
1383 | } | 1406 | } |
1384 | 1407 | ||
1408 | // REQUIRED value: code_challenge | ||
1409 | handle->oidc->code_challenge = get_url_parameter_copy (handle, OIDC_CODE_CHALLENGE_KEY); | ||
1410 | if (NULL == handle->oidc->code_challenge) | ||
1411 | { | ||
1412 | handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST); | ||
1413 | handle->edesc = GNUNET_strdup ("missing parameter code_challenge"); | ||
1414 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
1415 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1416 | return; | ||
1417 | } | ||
1418 | |||
1385 | if (GNUNET_OK != | 1419 | if (GNUNET_OK != |
1386 | GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->oidc->client_id, | 1420 | GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->oidc->client_id, |
1387 | strlen ( | 1421 | strlen ( |
@@ -1666,7 +1700,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
1666 | char *access_token; | 1700 | char *access_token; |
1667 | char *jwt_secret; | 1701 | char *jwt_secret; |
1668 | char *nonce; | 1702 | char *nonce; |
1669 | 1703 | char *code_verifier; | |
1670 | /* | 1704 | /* |
1671 | * Check Authorization | 1705 | * Check Authorization |
1672 | */ | 1706 | */ |
@@ -1728,8 +1762,20 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
1728 | return; | 1762 | return; |
1729 | } | 1763 | } |
1730 | privkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); | 1764 | privkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); |
1765 | |||
1766 | // REQUIRED code verifier | ||
1767 | code_verifier = get_url_parameter_copy (handle, OIDC_CODE_VERIFIER_KEY); | ||
1768 | if (NULL == code_verifier) | ||
1769 | { | ||
1770 | handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST); | ||
1771 | handle->edesc = GNUNET_strdup ("missing parameter code_verifier"); | ||
1772 | handle->response_code = MHD_HTTP_BAD_REQUEST; | ||
1773 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1774 | return; | ||
1775 | } | ||
1776 | |||
1731 | // decode code | 1777 | // decode code |
1732 | if (GNUNET_OK != OIDC_parse_authz_code (privkey, code, &ticket, &cl, &nonce)) | 1778 | if (GNUNET_OK != OIDC_parse_authz_code (privkey, code, code_verifier, &ticket, &cl, &nonce)) |
1733 | { | 1779 | { |
1734 | handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST); | 1780 | handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST); |
1735 | handle->edesc = GNUNET_strdup ("invalid code"); | 1781 | handle->edesc = GNUNET_strdup ("invalid code"); |
@@ -2003,6 +2049,7 @@ list_ego (void *cls, | |||
2003 | } | 2049 | } |
2004 | GNUNET_assert (NULL != ego); | 2050 | GNUNET_assert (NULL != ego); |
2005 | if (ID_REST_STATE_INIT == handle->state) | 2051 | if (ID_REST_STATE_INIT == handle->state) |
2052 | |||
2006 | { | 2053 | { |
2007 | ego_entry = GNUNET_new (struct EgoEntry); | 2054 | ego_entry = GNUNET_new (struct EgoEntry); |
2008 | GNUNET_IDENTITY_ego_get_public_key (ego, &pk); | 2055 | GNUNET_IDENTITY_ego_get_public_key (ego, &pk); |