gnunet

Main GNUnet Logic
Log | Files | Refs | Submodules | README | LICENSE

commit 365e4e6f7b32712891ed79f08401fcc2558f5bbb
parent 7bec20c7d509e16c1061731198b0bf92f84e2631
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date:   Tue,  7 May 2024 22:07:05 +0200

RECLAIM: Start fixing OIDC plugin; add new CLI test

Diffstat:
Msrc/cli/reclaim/test_reclaim.conf | 11++++++++---
Asrc/cli/reclaim/test_reclaim_oidc.sh | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/service/rest/oidc_helper.c | 16+++++++++++++---
Msrc/service/rest/oidc_helper.h | 2+-
Msrc/service/rest/openid_plugin.c | 19++++++++-----------
5 files changed, 87 insertions(+), 18 deletions(-)

diff --git a/src/cli/reclaim/test_reclaim.conf b/src/cli/reclaim/test_reclaim.conf @@ -8,7 +8,8 @@ START_ON_DEMAND = YES [rest] START_ON_DEMAND = YES -PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=$GNUNET_TMP/restlog +# PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=$GNUNET_TMP/restlog +BASIC_AUTH_ENABLED = NO [transport] PLUGINS = @@ -34,6 +35,10 @@ ZONE_PUBLISH_TIME_WINDOW = 1 h DNS_ROOT=PD67SGHF3E0447TU9HADIVU9OM7V4QHTOG0EBU69TFRI2LG63DR0 [reclaim-rest-plugin] -address = http://localhost:8000/#/login -psw = mysupersecretpassword expiration_time = 3600 +JWT_SECRET = secret +OIDC_USERINFO_CONSUME_TIMEOUT = 5s +OIDC_DIR = $GNUNET_DATA_HOME/oidc +OIDC_CLIENT_HMAC_SECRET = secret +OIDC_JSON_WEB_ALGORITHM = RS256 +ADDRESS = https://ui.reclaim/#/login diff --git a/src/cli/reclaim/test_reclaim_oidc.sh b/src/cli/reclaim/test_reclaim_oidc.sh @@ -0,0 +1,57 @@ +#!/bin/bash +trap "gnunet-arm -e -c test_reclaim.conf" SIGINT + +LOCATION=$(which gnunet-config) +if [ -z $LOCATION ] +then + LOCATION="gnunet-config" +fi +$LOCATION --version 1>/dev/null +if test $? != 0 +then + echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" + exit 77 +fi + +rm -rf `gnunet-config -c test_reclaim.conf -s PATHS -o GNUNET_HOME -f` + +which timeout >/dev/null 2>&1 && DO_TIMEOUT="timeout 30" + +RES=0 +TEST_ATTR="test" +REDIRECT_URI="https://example.gns.alt/my_cb" +SCOPE="\"openid email name\"" +gnunet-arm -s -c test_reclaim.conf +gnunet-arm -i rest -c test_reclaim.conf +gnunet-arm -I +gnunet-identity -C testego -c test_reclaim.conf +gnunet-identity -C rpego -c test_reclaim.conf +TEST_KEY=$(gnunet-identity -d -e rpego -q -c test_reclaim.conf) +SUBJECT_KEY=$(gnunet-identity -d -e testego -q -c test_reclaim.conf) +gnunet-reclaim -e testego -a email -V john@doe.gnu -c test_reclaim.conf +gnunet-reclaim -e testego -a name -V John -c test_reclaim.conf + +# Register client +gnunet-namestore -z rpego -a -n @ -t RECLAIM_OIDC_CLIENT -V "My RP" -e 1d -p -c test_reclaim.conf +gnunet-namestore -z rpego -a -n @ -t RECLAIM_OIDC_REDIRECT -V $REDIRECT_URI -e 1d -p -c test_reclaim.conf + +gnunet-gns -u @.$TEST_KEY -t RECLAIM_OIDC_REDIRECT -c test_reclaim.conf +curl -v -X POST -H -v "http://localhost:7776/openid/login" --data "{\"identity\": \"$SUBJECT_KEY\"}" + +PKCE_CHALLENGE=$(echo -n secret | openssl dgst -binary -sha256 | openssl base64 | sed 's/\=//g' | sed 's/+/-/g' | sed 's/\//_/g') + +CODE=$(curl -H "Cookie: Identity=$SUBJECT_KEY" "http://localhost:7776/openid/authorize?client_id=$TEST_KEY&response_type=code&redirect_uri=$REDIRECT_URI&scope=openid&claims=%7B%22userinfo%22%3A%20%7B%22email%22%3A%20%7B%22essential%22%20%20%20%20%3A%20true%7D%7D%2C%22id_token%22%3A%20%7B%22email%22%3A%20%7B%22essential%22%3A%20true%7D%7D%7D&state=xyz&code_challenge=$PKCE_CHALLENGE&code_challenge_method=S256" \ + -sS -D - -o /dev/null | grep "Location: " | cut -d" " -f2 | cut -d"?" -f2 | cut -d"&" -f1 | cut -d"=" -f2) + +echo "Code: $CODE" + +curl -v -X POST -u$TEST_KEY:"secret" "http://localhost:7776/openid/token?client_id=$TEST_KEY&response_type=code&redirect_uri=$REDIRECT_URI&scope=openid&claims=%7B%22userinfo%22%3A%20%7B%22email%22%3A%20%7B%22essential%22%20%20%20%20%3A%20true%7D%7D%2C%22id_token%22%3A%20%7B%22email%22%3A%20%7B%22essential%22%3A%20true%7D%7D%7D&state=xyz&grant_type=authorization_code&code=$CODE&code_verifier=secret" + +gnunet-identity -D testego -c test_reclaim.conf +gnunet-identity -D rpego -c test_reclaim.conf +gnunet-arm -e -c test_reclaim.conf +if test $RES != 0 +then + echo "Failed." +fi + diff --git a/src/service/rest/oidc_helper.c b/src/service/rest/oidc_helper.c @@ -27,6 +27,8 @@ #include <inttypes.h> #include <jansson.h> #include <jose/jose.h> +#include "gnunet_gns_service.h" +#include "gnunet_gnsrecord_lib.h" #include "gnunet_util_lib.h" #include "gnunet_reclaim_lib.h" #include "gnunet_reclaim_service.h" @@ -587,7 +589,8 @@ OIDC_build_authz_code (const struct GNUNET_CRYPTO_PrivateKey *issuer, /** PLAINTEXT **/ // Assign ticket memset (&params, 0, sizeof(params)); - params.ticket = *ticket; + memcpy (params.ticket.gns_name, ticket->gns_name, strlen (ticket->gns_name) + + 1); // Assign nonce payload_len = sizeof(struct OIDC_Parameters); if ((NULL != nonce_str) && (strcmp ("", nonce_str) != 0)) @@ -756,7 +759,7 @@ OIDC_parse_authz_code (const char *rp_uri, struct GNUNET_RECLAIM_AttributeList **attrs, struct GNUNET_RECLAIM_PresentationList **presentations, char **nonce_str, - enum OIDC_VerificationOptions opts) + enum OIDC_VerificationOptions opts, char **emsg) { char *code_payload; char *ptr; @@ -766,6 +769,7 @@ OIDC_parse_authz_code (const char *rp_uri, char *code_challenge; struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; struct GNUNET_CRYPTO_Signature *signature; + struct GNUNET_CRYPTO_PublicKey iss; uint32_t code_challenge_len; uint32_t attrs_ser_len; uint32_t pres_ser_len; @@ -774,6 +778,8 @@ OIDC_parse_authz_code (const char *rp_uri, uint32_t nonce_len = 0; struct OIDC_Parameters *params; + + GNUNET_GNS_parse_ztld (ticket->gns_name, &iss); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to decode `%s'\n", code); code_payload = NULL; code_payload_len = @@ -807,6 +813,8 @@ OIDC_parse_authz_code (const char *rp_uri, code_challenge_len, code_verifier)) { + GNUNET_asprintf (emsg, "Code verifier `%s' invalid for challenge `%s'", + code_verifier, code_challenge); GNUNET_free (code_payload); return GNUNET_SYSERR; } @@ -828,12 +836,13 @@ OIDC_parse_authz_code (const char *rp_uri, GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN, purpose, signature, - cid)) + &iss)) { GNUNET_free (code_payload); if (NULL != *nonce_str) GNUNET_free (*nonce_str); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Signature of AuthZ code invalid!\n"); + *emsg = GNUNET_strdup ("Signature verification failed"); return GNUNET_SYSERR; } // Attributes @@ -899,6 +908,7 @@ OIDC_access_token_new (const struct GNUNET_RECLAIM_Ticket *ticket, sizeof(*ticket), &tkt_b64); GNUNET_asprintf (&access_token, "%s-%s", tkt_b64, rp_uri); + GNUNET_free (tkt_b64); return access_token; } diff --git a/src/service/rest/oidc_helper.h b/src/service/rest/oidc_helper.h @@ -138,7 +138,7 @@ OIDC_parse_authz_code (const char *rp_uri, struct GNUNET_RECLAIM_AttributeList **attrs, struct GNUNET_RECLAIM_PresentationList **presentations, char **nonce, - enum OIDC_VerificationOptions opts); + enum OIDC_VerificationOptions opts, char **emsg); /** * Build a token response for a token request diff --git a/src/service/rest/openid_plugin.c b/src/service/rest/openid_plugin.c @@ -2265,14 +2265,16 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, } // decode code + char *emsg = NULL; if (GNUNET_OK != OIDC_parse_authz_code (received_cid, &cid, code, code_verifier, &ticket, &cl, &pl, &nonce, - OIDC_VERIFICATION_DEFAULT)) + OIDC_VERIFICATION_DEFAULT, + &emsg)) { handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST); - handle->edesc = GNUNET_strdup ("invalid code"); + handle->edesc = emsg; handle->response_code = MHD_HTTP_BAD_REQUEST; GNUNET_free (code); if (NULL != code_verifier) @@ -2313,14 +2315,8 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, jwa = JWT_ALG_VALUE_RSA; } - char *tmp = GNUNET_strdup (ticket.gns_name); - GNUNET_assert (NULL != strtok (tmp, ".")); - char *key = strtok (NULL, "."); struct GNUNET_CRYPTO_PublicKey issuer; - GNUNET_assert (NULL != key); - GNUNET_assert (GNUNET_OK == - GNUNET_CRYPTO_public_key_from_string (key, &issuer)); - GNUNET_free (tmp); + GNUNET_GNS_parse_ztld (ticket.gns_name, &issuer); if (! strcmp (jwa, JWT_ALG_VALUE_RSA)) { @@ -2598,13 +2594,14 @@ consume_fail (void *cls) sizeof(struct GNUNET_CRYPTO_PublicKey)); // decode code + char *emsg; if (GNUNET_OK != OIDC_parse_authz_code (received_cid, &cid, cached_code, NULL, &ticket, &cl, &pl, &nonce, - OIDC_VERIFICATION_NO_CODE_VERIFIER)) + OIDC_VERIFICATION_NO_CODE_VERIFIER, &emsg)) { handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_REQUEST); - handle->edesc = GNUNET_strdup ("invalid code"); + handle->edesc = emsg; handle->response_code = MHD_HTTP_BAD_REQUEST; GNUNET_free (cached_code); if (NULL != nonce)