challenger

OAuth 2.0-based authentication service that validates user can receive messages at a certain address
Log | Files | Refs | Submodules | README | LICENSE

commit 56e0ccafe17796c8582631650e3082febf5860fa
parent fc3440fe1e2e41ae55face57c5c0a583d8b6c26e
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sat,  6 May 2023 23:39:20 +0200

-bugfixes

Diffstat:
Msrc/challenger/challenger-httpd.c | 30+++++++++++++++++++++---------
Msrc/challenger/challenger-httpd_challenge.c | 8++++++++
Msrc/challenger/challenger-httpd_login.c | 4+++-
Msrc/challenger/test-challenger.sh | 73++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/challengerdb/challenger-0001.sql | 2+-
Msrc/challengerdb/pg_client_check.c | 6+++---
Msrc/challengerdb/pg_login_start.c | 9++++++---
Msrc/challengerdb/pg_setup_nonce.c | 4++--
8 files changed, 114 insertions(+), 22 deletions(-)

diff --git a/src/challenger/challenger-httpd.c b/src/challenger/challenger-httpd.c @@ -33,6 +33,8 @@ #include "challenger-httpd_solve.h" #include "challenger_database_lib.h" #include "challenger-httpd_config.h" +#include <taler/taler_templating_lib.h> + /** * Backlog for listen operation on unix-domain sockets. @@ -170,27 +172,27 @@ url_handler (void *cls, .handler = &CH_handler_config }, { - .url = "/setup", - .method = MHD_HTTP_METHOD_GET, + .url = "/setup/", + .method = MHD_HTTP_METHOD_POST, .handler = &CH_handler_setup }, { - .url = "/setup", - .method = MHD_HTTP_METHOD_POST, - .handler = &CH_handler_setup + .url = "/login/", + .method = MHD_HTTP_METHOD_GET, + .handler = &CH_handler_login }, { - .url = "/login", + .url = "/login/", .method = MHD_HTTP_METHOD_POST, .handler = &CH_handler_login }, { - .url = "/challenge", + .url = "/challenge/", .method = MHD_HTTP_METHOD_POST, .handler = &CH_handler_challenge }, { - .url = "/solve", + .url = "/solve/", .method = MHD_HTTP_METHOD_POST, .handler = &CH_handler_solve }, @@ -212,6 +214,10 @@ url_handler (void *cls, (void) cls; (void) version; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Handling %s request for `%s'\n", + method, + url); hc = *con_cls; if (NULL == hc) { @@ -515,6 +521,12 @@ run (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Starting challenger-httpd\n"); + if (GNUNET_OK != + TALER_TEMPLATING_init (".")) + { + GNUNET_break (0); + return; + } go = TALER_MHD_GO_NONE; if (CH_challenger_connection_close) go |= TALER_MHD_GO_FORCE_CONNECTION_CLOSE; @@ -651,7 +663,7 @@ main (int argc, GNUNET_OS_init (CHALLENGER_project_data_default ()); ret = GNUNET_PROGRAM_run (argc, argv, "challenger-httpd", - "challenger HTTP interface", + "challenger REST and OAuth 2.0 API", options, &run, NULL); if (GNUNET_NO == ret) diff --git a/src/challenger/challenger-httpd_challenge.c b/src/challenger/challenger-httpd_challenge.c @@ -205,6 +205,8 @@ child_done_cb (void *cls, { struct ChallengeContext *bc = cls; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Child done\n"); bc->child = NULL; bc->cwh = NULL; bc->pst = type; @@ -378,6 +380,9 @@ CH_handler_challenge (struct CH_HandlerContext *hc, { struct ChallengeContext *bc = hc->ctx; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Got /challenge request\n"); + if (NULL == bc) { /* first call, setup internals */ @@ -493,6 +498,9 @@ CH_handler_challenge (struct CH_HandlerContext *hc, if (bc->retransmit) { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Transmitting PIN to `%s'\n", + bc->address); /* (Re)transmit PIN/TAN */ send_tan (bc); if (GNUNET_YES == bc->suspended) diff --git a/src/challenger/challenger-httpd_login.c b/src/challenger/challenger-httpd_login.c @@ -171,7 +171,9 @@ CH_handler_login (struct CH_HandlerContext *hc, GNUNET_JSON_pack_string ("nonce", hc->path), GNUNET_JSON_pack_string ("last_address", - last_address), + (NULL == last_address) + ? "" + : last_address), GNUNET_JSON_pack_uint64 ("changes_left", address_attempts_left) ); diff --git a/src/challenger/test-challenger.sh b/src/challenger/test-challenger.sh @@ -22,9 +22,13 @@ function cleanup() do kill $n 2> /dev/null || true done + rm -f "$LAST_RESPONSE" "$FILENAME" wait } +LAST_RESPONSE=`mktemp responseXXXXXX.log` +FILENAME="test-challenger.txt" + # Install cleanup handler (except for kill -9) trap cleanup EXIT @@ -43,17 +47,21 @@ echo " FOUND" CONF="test-challenger.conf" BURL="http://localhost:9967" +REDIRECT_URI="http://client.example.com/" echo -n "Initialize challenger database ..." challenger-dbinit -r -c "${CONF}" &> dbinit.log echo " OK" echo -n "Add challenger client ..." -challenger-admin -c "${CONF}" -a "secret" "http://client.com/" &> admin.log +CLIENT_SECRET="secret-token:secret" +challenger-admin -c "${CONF}" -a "${CLIENT_SECRET}" "${REDIRECT_URI}" &> admin.log echo " OK" +# We just reset the DB, thus the client ID must be 1 here: +CLIENT_ID=1 echo -n "Start challenger-httpd ..." -challenger-httpd -c "${CONF}" &> httpd.log & +challenger-httpd -L INFO -c "${CONF}" &> httpd.log & # Wait for challenger to be available for n in `seq 1 50` @@ -71,7 +79,66 @@ then exit_skip "Failed to launch challenger service" fi -# FIXME: actually use service! + +echo -n "Setup new validation process..." +STATUS=$(curl "${BURL}/setup/${CLIENT_ID}" \ + -H "Authorization: Bearer ${CLIENT_SECRET}" \ + -d '' \ + -w "%{http_code}" -s -o $LAST_RESPONSE) + +if [ "$STATUS" != "200" ] +then + echo "Expected 200 OK. Got: $STATUS" `cat $LAST_RESPONSE` + exit 1 +fi +NONCE=`jq -r .nonce < "$LAST_RESPONSE"` +echo " OK" + +CLIENT_STATE="the-client-state" +CLIENT_SCOPE="the-client-scope" + +echo -n "Initiating user login..." +STATUS=$(curl "${BURL}/login/${NONCE}" \ + -G \ + --data-urlencode "response_type=code" \ + --data-urlencode "client_id=${CLIENT_ID}" \ + --data-urlencode "redirect_uri=${REDIRECT_URI}" \ + --data-urlencode "state=${CLIENT_STATE}" \ + --data-urlencode "scope=${CLIENT_SCOPE}" \ + -w "%{http_code}" -s -o $LAST_RESPONSE) + +if [ "$STATUS" != "200" ] +then + echo "Expected 200 OK. Got: $STATUS" `cat $LAST_RESPONSE` + exit 1 +fi +echo "OK" + + +echo -n "Initiating address submission..." +STATUS=$(curl "${BURL}/challenge/${NONCE}" \ + -X POST \ + --data-urlencode "address=${FILENAME}" \ + -w "%{http_code}" -s -o $LAST_RESPONSE) + +if [ "$STATUS" != "200" ] +then + echo "Expected 200 OK. Got: $STATUS" `cat $LAST_RESPONSE` + exit 1 +fi +echo "OK" + + exit 0 + +# Archived for later... +echo -n "Initiating user login..." +STATUS=$(curl "${BURL}/login/${NONCE}?response_type=code&client_id=${CLIENT_ID}" \ + --data-urlencode "response_type=code" \ + --data-urlencode "client_id=${CLIENT_ID}" \ + --data-urlencode "redirect_uri=${REDIRECT_URI}" \ + --data-urlencode "state=${CLIENT_STATE}" \ + --data-urlencode "scope=${CLIENT_SCOPE}" \ + -w "%{http_code}" -o $LAST_RESPONSE) diff --git a/src/challengerdb/challenger-0001.sql b/src/challengerdb/challenger-0001.sql @@ -52,7 +52,7 @@ CREATE TABLE IF NOT EXISTS validations ,expiration_time INT8 NOT NULL ,last_tx_time INT8 NOT NULL DEFAULT (0) ,address_attempts_left INT4 DEFAULT(3) - ,last_pin INT4 NOT NULL + ,last_pin INT4 ,pin_attempts_left INT4 DEFAULT(0) ,auth_attempts_left INT4 DEFAULT(0) ,address VARCHAR diff --git a/src/challengerdb/pg_client_check.c b/src/challengerdb/pg_client_check.c @@ -52,10 +52,10 @@ CH_PG_client_check (void *cls, PREPARE (pg, "client_check", "UPDATE clients SET" - " validation_counter=validation_counter+$3" - " WHERE client_id=$1" + " validation_counter=validation_counter+CAST($3::INT4 AS INT8)" + " WHERE client_serial_id=$1" " AND client_secret=$2" - " RETURNING client_url"); + " RETURNING url;"); return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "client_check", params, diff --git a/src/challengerdb/pg_login_start.c b/src/challengerdb/pg_login_start.c @@ -48,13 +48,16 @@ CH_PG_login_start (void *cls, GNUNET_PQ_query_param_end }; struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_string ("address", - last_address), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("address", + last_address), + NULL), GNUNET_PQ_result_spec_uint32 ("address_attempts_left", address_attempts_left), GNUNET_PQ_result_spec_end }; + *last_address = NULL; PREPARE (pg, "login_start_validation", "UPDATE validations SET" @@ -62,7 +65,7 @@ CH_PG_login_start (void *cls, " ,client_state=$4" " ,client_redirect_url=$5" " WHERE nonce=$1" - " AND client_id=$2" + " AND client_serial_id=$2" " RETURNING" " address" " ,address_attempts_left;"); diff --git a/src/challengerdb/pg_setup_nonce.c b/src/challengerdb/pg_setup_nonce.c @@ -41,13 +41,13 @@ CH_PG_setup_nonce (void *cls, }; PREPARE (pg, - "validation_setup", + "setup_nonce", "INSERT INTO validations" " (client_serial_id" " ,nonce" " ,expiration_time" ") VALUES ($1, $2, $3);"); return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "validation_setup", + "setup_nonce", params); }