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.c134
1 files changed, 132 insertions, 2 deletions
diff --git a/src/authorization/anastasis_authorization_plugin_iban.c b/src/authorization/anastasis_authorization_plugin_iban.c
index eee8e7e..4f43d3f 100644
--- a/src/authorization/anastasis_authorization_plugin_iban.c
+++ b/src/authorization/anastasis_authorization_plugin_iban.c
@@ -29,6 +29,16 @@
#include "iban.h"
/**
+ * How long is a code valid once generated? Very long
+ * here as we do not want to refuse authentication
+ * just because the user took a while to execute the
+ * wire transfer (and then get back to their recovery
+ * operation).
+ */
+#define CODE_VALIDITY_PERIOD GNUNET_TIME_UNIT_MONTHS
+
+
+/**
* Saves the State of a authorization plugin.
*/
struct IBAN_Context
@@ -367,7 +377,116 @@ respond_with_challenge (struct ANASTASIS_AUTHORIZATION_State *as,
return ANASTASIS_AUTHORIZATION_RES_SUCCESS_REPLY_FAILED;
return ANASTASIS_AUTHORIZATION_RES_SUCCESS;
}
+}
+
+
+#include "iban.c"
+
+
+/**
+ * Check if the @a wire_subject matches the challenge in the context
+ * and if the @a amount is sufficient. If so, return true.
+ *
+ * @param cls a `const struct ANASTASIS_AUTHORIZATION_State *`
+ * @param amount the amount that was transferred
+ * @param wire_subject a wire subject we received
+ * @return true if the wire transfer satisfied the check
+ */
+static bool
+check_payment_ok (void *cls,
+ const struct TALER_Amount *amount,
+ const char *wire_subject)
+{
+ const struct ANASTASIS_AUTHORIZATION_State *as = cls;
+ struct IBAN_Context *ctx = as->ctx;
+ uint64_t code;
+
+ if (GNUNET_OK !=
+ extract_code (wire_subject,
+ &code))
+ return false;
+ if (GNUNET_OK !=
+ TALER_amount_cmp_currency (&ctx->expected_amount,
+ amount))
+ {
+ /* currency wrong!? */
+ GNUNET_break (0);
+ return false;
+ }
+ if (1 ==
+ TALER_amount_cmp (&ctx->expected_amount,
+ amount))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Amount `%s' insufficient for authorization\n",
+ TALER_amount2s (amount));
+ return false;
+ }
+ return (code == as->code);
+}
+
+/**
+ * Check if we have received a wire transfer with a subject
+ * authorizing the disclosure of the credential in the meantime.
+ *
+ * @param as state to check for
+ * @return WTS_SUCCESS if a transfer was received,
+ * WTS_NOT_READY if no transfer was received,
+ * WTS_FAILED_WITH_REPLY if we had an internal error and queued a reply
+ * WTS_FAILED_WITHOUT_REPLY if we had an internal error and failed to queue a reply
+ */
+static enum
+{
+ WTS_SUCCESS,
+ WTS_NOT_READY,
+ WTS_FAILED_WITH_REPLY,
+ WTS_FAILED_WITHOUT_REPLY
+}
+test_wire_transfers (struct ANASTASIS_AUTHORIZATION_State *as)
+{
+ struct IBAN_Context *ctx = as->ctx;
+ struct ANASTASIS_DatabasePlugin *db = ctx->ac->db;
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_TIME_Absolute now;
+ struct GNUNET_TIME_Absolute limit;
+ char *debit_account_uri;
+
+ now = GNUNET_TIME_absolute_get ();
+ limit = GNUNET_TIME_absolute_subtract (now,
+ CODE_VALIDITY_PERIOD);
+ GNUNET_asprintf (&debit_account_uri,
+ "payto://iban/%s",
+ as->iban_number);
+ qs = db->test_auth_iban_payment (
+ db->cls,
+ debit_account_uri,
+ limit,
+ &check_payment_ok,
+ as);
+ GNUNET_free (debit_account_uri);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ return (MHD_YES ==
+ TALER_MHD_reply_with_error (as->connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ NULL))
+ ? 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;
+ }
+ qs = db->mark_challenge_code_satisfied (
+ db->cls,
+ &as->truth_uuid,
+ as->code);
+ GNUNET_break (qs > 0);
+ return WTS_SUCCESS;
}
@@ -423,6 +542,17 @@ iban_process (struct ANASTASIS_AUTHORIZATION_State *as,
return ANASTASIS_AUTHORIZATION_RES_FAILED_REPLY_FAILED;
return ANASTASIS_AUTHORIZATION_RES_FAILED;
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ switch (test_wire_transfers (as))
+ {
+ case WTS_SUCCESS:
+ return ANASTASIS_AUTHORIZATION_RES_FINISHED;
+ case WTS_NOT_READY:
+ break; /* continue below */
+ case WTS_FAILED_WITH_REPLY:
+ return ANASTASIS_AUTHORIZATION_RES_FAILED;
+ case WTS_FAILED_WITHOUT_REPLY:
+ return ANASTASIS_AUTHORIZATION_RES_FAILED_REPLY_FAILED;
+ }
if (GNUNET_TIME_absolute_is_future (timeout))
{
as->connection = connection;
@@ -529,9 +659,9 @@ libanastasis_plugin_authorization_iban_init (void *cls)
ctx->ac = ac;
plugin = GNUNET_new (struct ANASTASIS_AuthorizationPlugin);
plugin->payment_plugin_managed = true;
- plugin->code_validity_period = GNUNET_TIME_UNIT_MONTHS;
+ plugin->code_validity_period = CODE_VALIDITY_PERIOD;
plugin->code_rotation_period = GNUNET_TIME_UNIT_WEEKS;
- plugin->code_retransmission_frequency = GNUNET_TIME_UNIT_FOREVER_REL;
+ plugin->code_retransmission_frequency = GNUNET_TIME_UNIT_FOREVER_REL; /* not applicable */
plugin->cls = ctx;
plugin->validate = &iban_validate;
plugin->start = &iban_start;