From e7e10a2931cc19969b2c060a0996506e5b7ce43e Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 23 Aug 2021 12:50:34 +0200 Subject: -misc bugfixes for IBAN plugin --- .../anastasis_authorization_plugin_iban.c | 47 ++++++++--- src/cli/test_iban.sh | 6 +- src/include/anastasis.h | 7 +- src/include/anastasis_database_plugin.h | 4 +- src/lib/anastasis_recovery.c | 9 +-- src/reducer/anastasis_api_recovery_redux.c | 90 ++++++++-------------- src/restclient/anastasis_api_keyshare_lookup.c | 12 ++- src/stasis/plugin_anastasis_postgres.c | 14 +++- 8 files changed, 101 insertions(+), 88 deletions(-) diff --git a/src/authorization/anastasis_authorization_plugin_iban.c b/src/authorization/anastasis_authorization_plugin_iban.c index f8a4868..3c72e16 100644 --- a/src/authorization/anastasis_authorization_plugin_iban.c +++ b/src/authorization/anastasis_authorization_plugin_iban.c @@ -198,9 +198,13 @@ iban_validate (void *cls, iban_number = GNUNET_strndup (data, data_length); emsg = TALER_iban_validate (iban_number); - GNUNET_free (iban_number); if (NULL != emsg) { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Invalid IBAN `%s' provided: %s\n", + iban_number, + emsg); + GNUNET_free (iban_number); if (MHD_NO == TALER_MHD_reply_with_error (connection, MHD_HTTP_EXPECTATION_FAILED, @@ -213,6 +217,7 @@ iban_validate (void *cls, GNUNET_free (emsg); return GNUNET_NO; } + GNUNET_free (iban_number); return GNUNET_OK; } @@ -447,6 +452,7 @@ test_wire_transfers (struct ANASTASIS_AUTHORIZATION_State *as) now = GNUNET_TIME_absolute_get (); limit = GNUNET_TIME_absolute_subtract (now, CODE_VALIDITY_PERIOD); + (void) GNUNET_TIME_round_abs (&limit); GNUNET_asprintf (&debit_account_uri, "payto://iban/%s", as->iban_number); @@ -497,9 +503,12 @@ iban_process (struct ANASTASIS_AUTHORIZATION_State *as, struct MHD_Connection *connection) { struct IBAN_Context *ctx = as->ctx; + struct ANASTASIS_DatabasePlugin *db = ctx->ac->db; MHD_RESULT mres; enum GNUNET_DB_QueryStatus qs; struct MHD_Response *resp; + struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); + struct GNUNET_TIME_Absolute after; if (NULL == as->eh) { @@ -512,16 +521,20 @@ iban_process (struct ANASTASIS_AUTHORIZATION_State *as, GNUNET_CRYPTO_hash (as->iban_number, strlen (as->iban_number), &espec.debit_iban_hash); - as->eh = ctx->ac->db->event_listen (ctx->ac->db->cls, - &espec.header, - GNUNET_TIME_absolute_get_remaining ( - timeout), - &bank_event_cb, - as); + as->eh = db->event_listen (db->cls, + &espec.header, + GNUNET_TIME_absolute_get_remaining ( + timeout), + &bank_event_cb, + as); } - qs = ctx->ac->db->test_challenge_code_satisfied (ctx->ac->db->cls, - &as->truth_uuid, - as->code); + after = GNUNET_TIME_absolute_subtract (now, + CODE_VALIDITY_PERIOD); + (void) GNUNET_TIME_round_abs (&after); + qs = db->test_challenge_code_satisfied (db->cls, + &as->truth_uuid, + as->code, + after); switch (qs) { case GNUNET_DB_STATUS_HARD_ERROR: @@ -611,6 +624,18 @@ libanastasis_plugin_authorization_iban_init (void *cls) GNUNET_free (ctx); return NULL; } + if (GNUNET_OK != + TALER_config_get_amount (cfg, + "authorization-iban", + "COST", + &ctx->expected_amount)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "authorization-iban", + "COST"); + GNUNET_free (ctx); + return NULL; + } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "authorization-iban", @@ -655,7 +680,7 @@ libanastasis_plugin_authorization_iban_init (void *cls) plugin->payment_plugin_managed = true; plugin->code_validity_period = CODE_VALIDITY_PERIOD; plugin->code_rotation_period = GNUNET_TIME_UNIT_WEEKS; - plugin->code_retransmission_frequency = GNUNET_TIME_UNIT_FOREVER_REL; /* not applicable */ + plugin->code_retransmission_frequency = GNUNET_TIME_UNIT_ZERO; /* not applicable */ plugin->cls = ctx; plugin->validate = &iban_validate; plugin->start = &iban_start; diff --git a/src/cli/test_iban.sh b/src/cli/test_iban.sh index f3f127e..620b2a5 100755 --- a/src/cli/test_iban.sh +++ b/src/cli/test_iban.sh @@ -189,8 +189,8 @@ echo " OK" CURRENCY="TESTKUDOS" EBICS_HOST="ebicstesthost" -IBAN_CREDIT="AA3314655813489414469157" -IBAN_DEBIT="BB3314655813489414469157" +IBAN_CREDIT="DE89370400440532013000" +IBAN_DEBIT="FR1420041010050500013M02606" export IBAN_CREDIT export IBAN_DEBIT @@ -332,7 +332,7 @@ anastasis-reducer -a \ "birthdate": "2000-01-01"}}' \ enter_user_attributes < $B1FILE > $B2FILE 2>> test_reducer.err echo -n "," -BASEIBAN=`echo $IBAN_DEBIT | gnunet-base32` +BASEIBAN=`echo -n $IBAN_DEBIT | gnunet-base32` anastasis-reducer -a \ "$(jq -n '{ authentication_method: { type: "iban", diff --git a/src/include/anastasis.h b/src/include/anastasis.h index 3027e2a..a950172 100644 --- a/src/include/anastasis.h +++ b/src/include/anastasis.h @@ -180,7 +180,6 @@ struct ANASTASIS_ChallengeStartResponse /** * Challenge details provided if * @e cs is #ANASTASIS_CHALLENGE_STATUS_INSTRUCTIONS - * or #ANASTASIS_CHALLENGE_STATUS_EXTERNAL_INSTRUCTIONS. */ struct { @@ -209,6 +208,12 @@ struct ANASTASIS_ChallengeStartResponse } open_challenge; + /** + * Response with details if + * @e cs is #ANASTASIS_CHALLENGE_STATUS_EXTERNAL_INSTRUCTIONS. + */ + const json_t *external_challenge; + /** * Response with URL to redirect the user to, if * @e cs is #ANASTASIS_CHALLENGE_STATUS_REDIRECT_FOR_AUTHENTICATION. diff --git a/src/include/anastasis_database_plugin.h b/src/include/anastasis_database_plugin.h index 96a9367..1265f7b 100644 --- a/src/include/anastasis_database_plugin.h +++ b/src/include/anastasis_database_plugin.h @@ -620,6 +620,7 @@ struct ANASTASIS_DatabasePlugin * @param cls closure * @param truth_uuid identification of the challenge which the code corresponds to * @param code code which is now satisfied + * @param after after what time must the challenge have been created * @return transaction status, * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if the challenge code is not satisfied or expired * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the challenge code has been marked as satisfied @@ -628,7 +629,8 @@ struct ANASTASIS_DatabasePlugin (*test_challenge_code_satisfied)( void *cls, const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid, - const uint64_t code); + const uint64_t code, + struct GNUNET_TIME_Absolute after); /** diff --git a/src/lib/anastasis_recovery.c b/src/lib/anastasis_recovery.c index 623e882..ac10418 100644 --- a/src/lib/anastasis_recovery.c +++ b/src/lib/anastasis_recovery.c @@ -358,14 +358,7 @@ keyshare_lookup_cb (void *cls, struct ANASTASIS_ChallengeStartResponse csr = { .cs = ANASTASIS_CHALLENGE_STATUS_EXTERNAL_INSTRUCTIONS, .challenge = c, - .details.open_challenge.body - = dd->details.open_challenge.body, - .details.open_challenge.content_type - = dd->details.open_challenge.content_type, - .details.open_challenge.body_size - = dd->details.open_challenge.body_size, - .details.open_challenge.http_status - = dd->details.open_challenge.http_status + .details.external_challenge = dd->details.external_challenge }; c->af (c->af_cls, diff --git a/src/reducer/anastasis_api_recovery_redux.c b/src/reducer/anastasis_api_recovery_redux.c index 5513e83..c29a08a 100644 --- a/src/reducer/anastasis_api_recovery_redux.c +++ b/src/reducer/anastasis_api_recovery_redux.c @@ -635,7 +635,6 @@ answer_feedback_cb ( uuid, err)); } - GNUNET_break_op (0); set_state (sctx->state, ANASTASIS_RECOVERY_STATE_CHALLENGE_SELECTING); sctx->cb (sctx->cb_cls, @@ -711,79 +710,50 @@ answer_feedback_cb ( case ANASTASIS_CHALLENGE_STATUS_EXTERNAL_INSTRUCTIONS: { - json_t *body = NULL; - const char *mime; + const json_t *body = csr->details.external_challenge; + const char *method; + json_t *details; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_string ("method", + &method), + GNUNET_JSON_spec_json ("details", + &details), + GNUNET_JSON_spec_end () + }; + json_t *reply; - mime = csr->details.open_challenge.content_type; - if (0 == strcasecmp (mime, - "application/json")) - { - body = json_loadb (csr->details.open_challenge.body, - csr->details.open_challenge.body_size, - JSON_REJECT_DUPLICATES, - NULL); - GNUNET_break_op (NULL != body); - } - if (NULL == body) + if (GNUNET_OK != + GNUNET_JSON_parse (body, + spec, + NULL, NULL)) { json_t *err; + GNUNET_break_op (0); err = GNUNET_JSON_PACK ( GNUNET_JSON_pack_string ("state", "server-failure"), GNUNET_JSON_pack_uint64 ("error_code", - TALER_EC_GENERIC_INVALID_RESPONSE)); + TALER_EC_GENERIC_REPLY_MALFORMED)); GNUNET_assert (0 == json_object_set_new (feedback, uuid, err)); + return; } - else - { - const char *method; - json_t *details; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_string ("method", - &method), - GNUNET_JSON_spec_json ("details", - &details), - GNUNET_JSON_spec_end () - }; - json_t *reply; - if (GNUNET_OK != - GNUNET_JSON_parse (body, - spec, - NULL, NULL)) - { - json_t *err; - - GNUNET_break_op (0); - err = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("state", - "server-failure"), - GNUNET_JSON_pack_uint64 ("error_code", - TALER_EC_GENERIC_REPLY_MALFORMED)); - GNUNET_assert (0 == - json_object_set_new (feedback, - uuid, - err)); - return; - } - - reply = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("state", - "external-instructions"), - GNUNET_JSON_pack_string ("method", - method), - GNUNET_JSON_pack_object_incref ("details", - details)); - GNUNET_JSON_parse_free (spec); - GNUNET_assert (0 == - json_object_set_new (feedback, - uuid, - reply)); - } + reply = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ("state", + "external-instructions"), + GNUNET_JSON_pack_string ("method", + method), + GNUNET_JSON_pack_object_incref ("details", + details)); + GNUNET_JSON_parse_free (spec); + GNUNET_assert (0 == + json_object_set_new (feedback, + uuid, + reply)); } set_state (sctx->state, ANASTASIS_RECOVERY_STATE_CHALLENGE_SELECTING); diff --git a/src/restclient/anastasis_api_keyshare_lookup.c b/src/restclient/anastasis_api_keyshare_lookup.c index bb463b6..c0c2812 100644 --- a/src/restclient/anastasis_api_keyshare_lookup.c +++ b/src/restclient/anastasis_api_keyshare_lookup.c @@ -144,13 +144,14 @@ handle_keyshare_lookup_finished (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Backend didn't even return from GET /truth\n"); kdd.status = ANASTASIS_KSD_SERVER_ERROR; + kdd.details.server_failure.ec = TALER_EC_GENERIC_INVALID_RESPONSE; break; case MHD_HTTP_OK: if (sizeof (struct ANASTASIS_CRYPTO_EncryptedKeyShareP) != data_size) { GNUNET_break_op (0); kdd.status = ANASTASIS_KSD_SERVER_ERROR; - kdd.details.server_failure.http_status = MHD_HTTP_ACCEPTED; + kdd.details.server_failure.http_status = MHD_HTTP_OK; kdd.details.server_failure.ec = TALER_EC_GENERIC_INVALID_RESPONSE; break; } @@ -179,6 +180,8 @@ handle_keyshare_lookup_finished (void *cls, (or API version conflict); just pass JSON reply to the application */ GNUNET_break (0); kdd.status = ANASTASIS_KSD_CLIENT_FAILURE; + kdd.details.server_failure.http_status = MHD_HTTP_BAD_REQUEST; + kdd.details.server_failure.ec = TALER_EC_GENERIC_JSON_INVALID; break; case MHD_HTTP_PAYMENT_REQUIRED: { @@ -193,6 +196,8 @@ handle_keyshare_lookup_finished (void *cls, "Failed to parse `%s'\n", kslo->pay_uri); kdd.status = ANASTASIS_KSD_SERVER_ERROR; + kdd.details.server_failure.http_status = MHD_HTTP_PAYMENT_REQUIRED; + kdd.details.server_failure.ec = TALER_EC_GENERIC_REPLY_MALFORMED; break; } if (GNUNET_OK != @@ -204,6 +209,8 @@ handle_keyshare_lookup_finished (void *cls, { GNUNET_break (0); kdd.status = ANASTASIS_KSD_SERVER_ERROR; + kdd.details.server_failure.http_status = MHD_HTTP_PAYMENT_REQUIRED; + kdd.details.server_failure.ec = TALER_EC_GENERIC_REPLY_MALFORMED; TALER_MERCHANT_parse_pay_uri_free (&pd); break; } @@ -245,6 +252,9 @@ handle_keyshare_lookup_finished (void *cls, case MHD_HTTP_EXPECTATION_FAILED: /* Nothing really to verify */ kdd.status = ANASTASIS_KSD_CLIENT_FAILURE; + kdd.details.server_failure.http_status = MHD_HTTP_EXPECTATION_FAILED; + kdd.details.server_failure.ec = TALER_JSON_get_error_code2 (data, + data_size); break; case MHD_HTTP_TOO_MANY_REQUESTS: kdd.status = ANASTASIS_KSD_RATE_LIMIT_EXCEEDED; diff --git a/src/stasis/plugin_anastasis_postgres.c b/src/stasis/plugin_anastasis_postgres.c index b7fda3d..8c06243 100644 --- a/src/stasis/plugin_anastasis_postgres.c +++ b/src/stasis/plugin_anastasis_postgres.c @@ -1945,14 +1945,14 @@ static enum GNUNET_DB_QueryStatus postgres_test_challenge_code_satisfied ( void *cls, const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid, - const uint64_t code) + const uint64_t code, + struct GNUNET_TIME_Absolute after) { struct PostgresClosure *pg = cls; - struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_auto_from_type (truth_uuid), GNUNET_PQ_query_param_uint64 (&code), - GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_absolute_time (&after), GNUNET_PQ_query_param_end }; struct GNUNET_PQ_ResultSpec rs[] = { @@ -2558,6 +2558,14 @@ libanastasis_plugin_db_postgres_init (void *cls) " ORDER BY creation_date DESC" " LIMIT 1);", 2), + GNUNET_PQ_make_prepare ("challengecode_test_satisfied", + "SELECT 1 FROM anastasis_challengecode" + " WHERE truth_uuid=$1" + " AND satisfied=TRUE" + " AND code=$2" + " AND creation_date >= $3" + " LIMIT 1;", + 3), GNUNET_PQ_make_prepare ("challengecode_select_meta", "SELECT " " code" -- cgit v1.2.3