diff options
Diffstat (limited to 'src/authorization/anastasis_authorization_plugin_iban.c')
-rw-r--r-- | src/authorization/anastasis_authorization_plugin_iban.c | 281 |
1 files changed, 146 insertions, 135 deletions
diff --git a/src/authorization/anastasis_authorization_plugin_iban.c b/src/authorization/anastasis_authorization_plugin_iban.c index 7717770..92b4565 100644 --- a/src/authorization/anastasis_authorization_plugin_iban.c +++ b/src/authorization/anastasis_authorization_plugin_iban.c @@ -3,7 +3,7 @@ Copyright (C) 2021 Anastasis SARL Anastasis is free software; you can redistribute it and/or modify it under the - terms of the GNU Lesser General Public License as published by the Free Software + terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY @@ -209,7 +209,7 @@ iban_validate (void *cls, GNUNET_free (iban_number); if (MHD_NO == TALER_MHD_reply_with_error (connection, - MHD_HTTP_EXPECTATION_FAILED, + MHD_HTTP_CONFLICT, TALER_EC_ANASTASIS_IBAN_INVALID, emsg)) { @@ -293,105 +293,13 @@ bank_event_cb (void *cls, } GNUNET_free (amount_s); } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "IBAN event triggers resumption of request handling\n"); MHD_resume_connection (as->connection); as->trigger (as->trigger_cls); } -/** - * Respond with instructions to the user how to - * satisfy the challenge. - * - * @param as our state - * @param connection connection to respond on - * @return state of the request - */ -static enum ANASTASIS_AUTHORIZATION_Result -respond_with_challenge (struct ANASTASIS_AUTHORIZATION_State *as, - struct MHD_Connection *connection) -{ - struct IBAN_Context *ctx = as->ctx; - const char *mime; - const char *lang; - MHD_RESULT mres; - - mime = MHD_lookup_connection_value (connection, - MHD_HEADER_KIND, - MHD_HTTP_HEADER_ACCEPT); - if (NULL == mime) - mime = "text/plain"; - lang = MHD_lookup_connection_value (connection, - MHD_HEADER_KIND, - MHD_HTTP_HEADER_ACCEPT_LANGUAGE); - if (NULL == lang) - lang = "en"; - - /* Build HTTP response */ - { - struct MHD_Response *resp; - - if (TALER_MHD_xmime_matches (mime, - "application/json")) - { - char subject[64]; - - GNUNET_snprintf (subject, - sizeof (subject), - "Anastasis %llu", - (unsigned long long) as->code); - resp = TALER_MHD_MAKE_JSON_PACK ( - GNUNET_JSON_pack_string ("method", - "iban"), - GNUNET_JSON_pack_bool ("async", - true), - GNUNET_JSON_pack_uint64 ("answer_code", - as->code), - GNUNET_JSON_pack_object_steal ( - "details", - GNUNET_JSON_PACK ( - TALER_JSON_pack_amount ("challenge_amount", - &ctx->expected_amount), - GNUNET_JSON_pack_string ("credit_iban", - ctx->business_iban), - GNUNET_JSON_pack_string ("business_name", - ctx->business_name), - GNUNET_JSON_pack_string ("wire_transfer_subject", - subject)))); - } - else - { - size_t reply_len; - char *reply; - - reply_len = GNUNET_asprintf (&reply, - get_message (ctx->messages, - connection, - "instructions"), - TALER_amount2s (&ctx->expected_amount), - ctx->business_name, - ctx->business_iban, - (unsigned long long) as->code); - resp = MHD_create_response_from_buffer (reply_len, - reply, - MHD_RESPMEM_MUST_COPY); - GNUNET_free (reply); - TALER_MHD_add_global_headers (resp); - GNUNET_break (MHD_YES == - MHD_add_response_header (resp, - MHD_HTTP_HEADER_CONTENT_TYPE, - "text/plain")); - } - mres = MHD_queue_response (connection, - MHD_HTTP_ACCEPTED, - resp); - MHD_destroy_response (resp); - if (MHD_YES != mres) - return ANASTASIS_AUTHORIZATION_RES_SUCCESS_REPLY_FAILED; - return ANASTASIS_AUTHORIZATION_RES_SUCCESS; - } -} - - #include "iban.c" @@ -461,12 +369,14 @@ test_wire_transfers (struct ANASTASIS_AUTHORIZATION_State *as) struct ANASTASIS_DatabasePlugin *db = ctx->ac->db; enum GNUNET_DB_QueryStatus qs; struct GNUNET_TIME_Absolute now; - struct GNUNET_TIME_Absolute limit; + struct GNUNET_TIME_Timestamp limit; now = GNUNET_TIME_absolute_get (); - limit = GNUNET_TIME_absolute_subtract (now, - CODE_VALIDITY_PERIOD); - (void) GNUNET_TIME_round_abs (&limit); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Testing for wire transfers\n"); + limit = GNUNET_TIME_absolute_to_timestamp ( + GNUNET_TIME_absolute_subtract (now, + CODE_VALIDITY_PERIOD)); qs = db->test_auth_iban_payment ( db->cls, as->iban_number, @@ -482,15 +392,13 @@ test_wire_transfers (struct ANASTASIS_AUTHORIZATION_State *as) MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_FETCH_FAILED, NULL)) - ? WTS_FAILED_WITH_REPLY - : WTS_FAILED_WITHOUT_REPLY; + ? WTS_FAILED_WITH_REPLY + : WTS_FAILED_WITHOUT_REPLY; case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: return WTS_NOT_READY; case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: break; } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Marking IBAN challenge as satisfied!\n"); qs = db->mark_challenge_code_satisfied ( db->cls, &as->truth_uuid, @@ -501,26 +409,124 @@ test_wire_transfers (struct ANASTASIS_AUTHORIZATION_State *as) /** + * Respond with instructions to the user how to + * satisfy the challenge. + * + * @param as authorization state + * @param connection HTTP client request (for queuing response, such as redirection to video portal) + * @return state of the request + */ +static enum ANASTASIS_AUTHORIZATION_ChallengeResult +iban_challenge (struct ANASTASIS_AUTHORIZATION_State *as, + struct MHD_Connection *connection) +{ + struct IBAN_Context *ctx = as->ctx; + const char *mime; + const char *lang; + MHD_RESULT mres; + + mime = MHD_lookup_connection_value (connection, + MHD_HEADER_KIND, + MHD_HTTP_HEADER_ACCEPT); + if (NULL == mime) + mime = "text/plain"; + lang = MHD_lookup_connection_value (connection, + MHD_HEADER_KIND, + MHD_HTTP_HEADER_ACCEPT_LANGUAGE); + if (NULL == lang) + lang = "en"; + + /* Build HTTP response */ + { + struct MHD_Response *resp; + + if (TALER_MHD_xmime_matches (mime, + "application/json")) + { + char subject[64]; + + GNUNET_snprintf (subject, + sizeof (subject), + "Anastasis %llu", + (unsigned long long) as->code); + resp = TALER_MHD_MAKE_JSON_PACK ( + GNUNET_JSON_pack_string ("challenge_type", + "IBAN_WIRE"), + GNUNET_JSON_pack_object_steal ( + "wire_details", + GNUNET_JSON_PACK ( + GNUNET_JSON_pack_uint64 ( + "answer_code", + as->code), + TALER_JSON_pack_amount ( + "challenge_amount", + &ctx->expected_amount), + GNUNET_JSON_pack_string ( + "credit_iban", + ctx->business_iban), + GNUNET_JSON_pack_string ( + "business_name", + ctx->business_name), + GNUNET_JSON_pack_string ( + "wire_transfer_subject", + subject)))); + } + else + { + size_t reply_len; + char *reply; + + reply_len = GNUNET_asprintf (&reply, + get_message (ctx->messages, + connection, + "instructions"), + TALER_amount2s (&ctx->expected_amount), + ctx->business_name, + ctx->business_iban, + (unsigned long long) as->code); + resp = MHD_create_response_from_buffer (reply_len, + reply, + MHD_RESPMEM_MUST_COPY); + GNUNET_free (reply); + TALER_MHD_add_global_headers (resp); + GNUNET_break (MHD_YES == + MHD_add_response_header (resp, + MHD_HTTP_HEADER_CONTENT_TYPE, + "text/plain")); + } + mres = MHD_queue_response (connection, + MHD_HTTP_OK, + resp); + MHD_destroy_response (resp); + if (MHD_YES != mres) + return ANASTASIS_AUTHORIZATION_CRES_SUCCESS_REPLY_FAILED; + return ANASTASIS_AUTHORIZATION_CRES_SUCCESS; + } +} + + +/** * Begin issuing authentication challenge to user based on @a data. * I.e. start to send IBAN or e-mail or launch video identification. * * @param as authorization state * @param timeout how long do we have to produce a reply + * @param challenge_response hash of the challenge response, or NULL * @param connection HTTP client request (for queuing response, such as redirection to video portal) * @return state of the request */ -static enum ANASTASIS_AUTHORIZATION_Result -iban_process (struct ANASTASIS_AUTHORIZATION_State *as, - struct GNUNET_TIME_Absolute timeout, - struct MHD_Connection *connection) +static enum ANASTASIS_AUTHORIZATION_SolveResult +iban_solve (struct ANASTASIS_AUTHORIZATION_State *as, + struct GNUNET_TIME_Absolute timeout, + const struct GNUNET_HashCode *challenge_response, + 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; + struct GNUNET_TIME_Timestamp after; if (NULL == as->eh) { @@ -530,10 +536,6 @@ iban_process (struct ANASTASIS_AUTHORIZATION_State *as, .code = GNUNET_htonll (as->code) }; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Subscribing to events for code %llu from %s\n", - (unsigned long long) as->code, - as->iban_number); GNUNET_CRYPTO_hash (as->iban_number, strlen (as->iban_number), &espec.debit_iban_hash); @@ -544,9 +546,9 @@ iban_process (struct ANASTASIS_AUTHORIZATION_State *as, &bank_event_cb, as); } - after = GNUNET_TIME_absolute_subtract (now, - CODE_VALIDITY_PERIOD); - (void) GNUNET_TIME_round_abs (&after); + after = GNUNET_TIME_absolute_to_timestamp ( + GNUNET_TIME_absolute_subtract (now, + CODE_VALIDITY_PERIOD)); qs = db->test_challenge_code_satisfied (db->cls, &as->truth_uuid, as->code, @@ -555,45 +557,54 @@ iban_process (struct ANASTASIS_AUTHORIZATION_State *as, { case GNUNET_DB_STATUS_HARD_ERROR: case GNUNET_DB_STATUS_SOFT_ERROR: - resp = TALER_MHD_make_error (TALER_EC_GENERIC_DB_FETCH_FAILED, - "test_challenge_code_satisfied"); - mres = MHD_queue_response (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - resp); - MHD_destroy_response (resp); + mres = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_FETCH_FAILED, + "test challenge code satisfied"); if (MHD_YES != mres) - return ANASTASIS_AUTHORIZATION_RES_FAILED_REPLY_FAILED; - return ANASTASIS_AUTHORIZATION_RES_FAILED; + return ANASTASIS_AUTHORIZATION_SRES_FAILED_REPLY_FAILED; + return ANASTASIS_AUTHORIZATION_SRES_FAILED; case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: switch (test_wire_transfers (as)) { case WTS_SUCCESS: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "IBAN authorization finished!\n"); - return ANASTASIS_AUTHORIZATION_RES_FINISHED; + return ANASTASIS_AUTHORIZATION_SRES_FINISHED; case WTS_NOT_READY: break; /* continue below */ case WTS_FAILED_WITH_REPLY: - return ANASTASIS_AUTHORIZATION_RES_FAILED; + return ANASTASIS_AUTHORIZATION_SRES_FAILED; case WTS_FAILED_WITHOUT_REPLY: - return ANASTASIS_AUTHORIZATION_RES_FAILED_REPLY_FAILED; + return ANASTASIS_AUTHORIZATION_SRES_FAILED_REPLY_FAILED; } if (GNUNET_TIME_absolute_is_future (timeout)) { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Suspending IBAN check until %s\n", + GNUNET_TIME_absolute2s (timeout)); as->connection = connection; MHD_suspend_connection (connection); - return ANASTASIS_AUTHORIZATION_RES_SUSPENDED; + return ANASTASIS_AUTHORIZATION_SRES_SUSPENDED; } - return respond_with_challenge (as, - connection); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Timeout reached at %s, failing request\n", + GNUNET_TIME_absolute2s (timeout)); + mres = TALER_MHD_reply_with_error (connection, + MHD_HTTP_FORBIDDEN, + TALER_EC_ANASTASIS_IBAN_MISSING_TRANSFER, + NULL); + if (MHD_YES != mres) + return ANASTASIS_AUTHORIZATION_SRES_FAILED_REPLY_FAILED; + return ANASTASIS_AUTHORIZATION_SRES_FAILED; case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "IBAN authorization finished!\n"); - return ANASTASIS_AUTHORIZATION_RES_FINISHED; + return ANASTASIS_AUTHORIZATION_SRES_FINISHED; } /* should be impossible */ GNUNET_break (0); - return ANASTASIS_AUTHORIZATION_RES_FAILED_REPLY_FAILED; + return ANASTASIS_AUTHORIZATION_SRES_FAILED_REPLY_FAILED; } @@ -708,9 +719,9 @@ libanastasis_plugin_authorization_iban_init (void *cls) plugin->cls = ctx; plugin->validate = &iban_validate; plugin->start = &iban_start; - plugin->process = &iban_process; + plugin->challenge = &iban_challenge; + plugin->solve = &iban_solve; plugin->cleanup = &iban_cleanup; - return plugin; } |