summaryrefslogtreecommitdiff
path: root/src/authorization/anastasis_authorization_plugin_iban.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/authorization/anastasis_authorization_plugin_iban.c')
-rw-r--r--src/authorization/anastasis_authorization_plugin_iban.c281
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;
}