[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-anastasis] branch master updated: first rough pass over backend
From: |
gnunet |
Subject: |
[taler-anastasis] branch master updated: first rough pass over backend |
Date: |
Mon, 08 Feb 2021 14:32:48 +0100 |
This is an automated email from the git hooks/post-receive script.
grothoff pushed a commit to branch master
in repository anastasis.
The following commit(s) were added to refs/heads/master by this push:
new 5464120 first rough pass over backend
5464120 is described below
commit 5464120715ccfe37b3252ff0f0de8788f4a01227
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Mon Feb 8 14:32:46 2021 +0100
first rough pass over backend
---
contrib/gana | 2 +-
src/backend/Makefile.am | 25 +-
src/backend/anastasis-httpd.c | 17 +
src/backend/anastasis-httpd.h | 5 +
src/backend/anastasis-httpd_config.c | 18 +-
src/backend/anastasis-httpd_policy.c | 6 +-
src/backend/anastasis-httpd_policy_upload.c | 14 +-
src/backend/anastasis-httpd_truth.c | 984 +++++++++++-----------
src/backend/anastasis-httpd_truth_upload.c | 4 +-
src/backend/anastasis_authorization_plugin.c | 38 +-
src/backend/anastasis_authorization_plugin_file.c | 3 -
src/backend/anastasis_authorization_plugin_sms.c | 350 ++++++--
src/include/anastasis_authorization_lib.h | 21 +-
src/include/anastasis_authorization_plugin.h | 7 -
src/include/anastasis_util_lib.h | 7 +-
15 files changed, 842 insertions(+), 659 deletions(-)
diff --git a/contrib/gana b/contrib/gana
index df16026..f5b0263 160000
--- a/contrib/gana
+++ b/contrib/gana
@@ -1 +1 @@
-Subproject commit df1602616af682c4960d08784b7acba5896dcc81
+Subproject commit f5b02632094606010ed1c28c21931c81fa852d2b
diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am
index 7d4ab65..6b170f9 100644
--- a/src/backend/Makefile.am
+++ b/src/backend/Makefile.am
@@ -22,8 +22,7 @@ libanastasisauthorization_la_LDFLAGS = \
plugin_LTLIBRARIES = \
libanastasis_plugin_authorization_file.la \
- libanastasis_plugin_authorization_email.la \
- libanastasis_plugin_authorization_sms.la
+ libanastasis_plugin_authorization_sms.la
libanastasis_plugin_authorization_file_la_SOURCES = \
anastasis_authorization_plugin_file.c
libanastasis_plugin_authorization_file_la_LIBADD = \
@@ -34,16 +33,18 @@ libanastasis_plugin_authorization_file_la_LDFLAGS = \
-ltalerutil \
-lgnunetutil \
$(XLIB)
-libanastasis_plugin_authorization_email_la_SOURCES = \
- anastasis_authorization_plugin_email.c
-libanastasis_plugin_authorization_email_la_LIBADD = \
- $(LTLIBINTL)
-libanastasis_plugin_authorization_email_la_LDFLAGS = \
- $(ANASTASIS_PLUGIN_LDFLAGS) \
- -ljansson \
- -ltalerutil \
- -lgnunetutil \
- $(XLIB)
+
+#libanastasis_plugin_authorization_email_la_SOURCES = \
+# anastasis_authorization_plugin_email.c
+#libanastasis_plugin_authorization_email_la_LIBADD = \
+# $(LTLIBINTL)
+#libanastasis_plugin_authorization_email_la_LDFLAGS = \
+# $(ANASTASIS_PLUGIN_LDFLAGS) \
+# -ljansson \
+# -ltalerutil \
+# -lgnunetutil \
+# $(XLIB)
+
libanastasis_plugin_authorization_sms_la_SOURCES = \
anastasis_authorization_plugin_sms.c
libanastasis_plugin_authorization_sms_la_LIBADD = \
diff --git a/src/backend/anastasis-httpd.c b/src/backend/anastasis-httpd.c
index e5ac332..0dcecf1 100644
--- a/src/backend/anastasis-httpd.c
+++ b/src/backend/anastasis-httpd.c
@@ -52,6 +52,11 @@ struct TALER_Amount AH_annual_fee;
*/
struct TALER_Amount AH_insurance;
+/**
+ * Cost for secure question truth download.
+ */
+struct TALER_Amount AH_question_cost;
+
/**
* Our configuration.
*/
@@ -590,6 +595,18 @@ run (void *cls,
GNUNET_SCHEDULER_shutdown ();
return;
}
+ if (GNUNET_OK !=
+ TALER_config_get_amount (config,
+ "authorization-question",
+ "COST",
+ &AH_question_cost))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "authorization-question",
+ "COST");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
if (GNUNET_OK !=
TALER_config_get_amount (config,
"anastasis",
diff --git a/src/backend/anastasis-httpd.h b/src/backend/anastasis-httpd.h
index 96282e2..7f50aff 100644
--- a/src/backend/anastasis-httpd.h
+++ b/src/backend/anastasis-httpd.h
@@ -149,6 +149,11 @@ extern struct TALER_Amount AH_annual_fee;
*/
extern struct TALER_Amount AH_insurance;
+/**
+ * Cost for secure question truth download.
+ */
+extern struct TALER_Amount AH_question_cost;
+
/**
* Our Taler backend to process payments.
*/
diff --git a/src/backend/anastasis-httpd_config.c
b/src/backend/anastasis-httpd_config.c
index e7e24bb..bc5cff3 100644
--- a/src/backend/anastasis-httpd_config.c
+++ b/src/backend/anastasis-httpd_config.c
@@ -23,8 +23,9 @@
#include "platform.h"
#include <jansson.h>
#include "anastasis-httpd_config.h"
+#include "anastasis-httpd.h"
#include <taler/taler_json_lib.h>
-
+#include "anastasis_authorization_lib.h"
/**
* Add enabled methods and their fees to the ``/config`` response.
@@ -65,7 +66,7 @@ add_methods (void *cls,
"method",
section,
"cost",
- TALER_JSON_from_amount (&AH_question_cost));
+ TALER_JSON_from_amount (&cost));
GNUNET_assert (
0 ==
json_array_append_new (method_arr,
@@ -87,6 +88,19 @@ AH_handler_config (struct TMH_RequestHandler *rh,
json_t *method_arr = json_array ();
GNUNET_assert (NULL != method_arr);
+ {
+ json_t *method;
+
+ method = json_pack ("{s:s, s:o}",
+ "method",
+ "question",
+ "cost",
+ TALER_JSON_from_amount (&AH_question_cost));
+ GNUNET_assert (
+ 0 ==
+ json_array_append_new (method_arr,
+ method));
+ }
GNUNET_CONFIGURATION_iterate_sections (AH_cfg,
&add_methods,
method_arr);
diff --git a/src/backend/anastasis-httpd_policy.c
b/src/backend/anastasis-httpd_policy.c
index 23873c0..0a1396a 100644
--- a/src/backend/anastasis-httpd_policy.c
+++ b/src/backend/anastasis-httpd_policy.c
@@ -158,10 +158,12 @@ AH_policy_get (struct MHD_Connection *connection,
struct GNUNET_HashCode recovery_data_hash;
enum ANASTASIS_DB_AccountStatus as;
MHD_RESULT ret;
+ uint32_t version;
as = db->lookup_account (db->cls,
account_pub,
- &recovery_data_hash);
+ &recovery_data_hash,
+ &version);
switch (as)
{
case ANASTASIS_DB_ACCOUNT_STATUS_PAYMENT_REQUIRED:
@@ -209,7 +211,7 @@ AH_policy_get (struct MHD_Connection *connection,
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
-
TALER_EC_ANASTASIS_BAD_IF_NONE_MATCH,
+
TALER_EC_ANASTASIS_POLICY_BAD_IF_NONE_MATCH,
"Etag must be a base32-encoded
SHA-512 hash");
}
if (0 == GNUNET_memcmp (&inm_h,
diff --git a/src/backend/anastasis-httpd_policy_upload.c
b/src/backend/anastasis-httpd_policy_upload.c
index 69b3ee5..f37cb39 100644
--- a/src/backend/anastasis-httpd_policy_upload.c
+++ b/src/backend/anastasis-httpd_policy_upload.c
@@ -731,8 +731,8 @@ AH_handler_policy_post (
connection,
MHD_HTTP_BAD_REQUEST,
(NULL == lens)
- ? TALER_EC_ANASTASIS_MISSING_CONTENT_LENGTH
- : TALER_EC_ANASTASIS_MALFORMED_CONTENT_LENGTH,
+ ? TALER_EC_ANASTASIS_POLICY_MISSING_CONTENT_LENGTH
+ : TALER_EC_ANASTASIS_POLICY_MALFORMED_CONTENT_LENGTH,
NULL);
}
if (len / 1024 / 1024 >= AH_upload_limit_mb)
@@ -750,7 +750,7 @@ AH_handler_policy_post (
"malloc");
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_PAYLOAD_TOO_LARGE,
-
TALER_EC_ANASTASIS_OUT_OF_MEMORY_ON_CONTENT_LENGTH,
+
TALER_EC_ANASTASIS_POLICY_OUT_OF_MEMORY_ON_CONTENT_LENGTH,
NULL);
}
puc->upload_size = (size_t) len;
@@ -772,7 +772,7 @@ AH_handler_policy_post (
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
-
TALER_EC_ANASTASIS_BAD_POLICY_SIGNATURE,
+
TALER_EC_ANASTASIS_POLICY_BAD_SIGNATURE,
"Anastasis-Policy-Signature does
not include a base32-encoded EdDSA signature");
}
}
@@ -793,7 +793,7 @@ AH_handler_policy_post (
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
- TALER_EC_ANASTASIS_BAD_IF_MATCH,
+
TALER_EC_ANASTASIS_POLICY_BAD_IF_MATCH,
"Etag must include a base32-encoded
SHA-512 hash");
}
}
@@ -815,7 +815,7 @@ AH_handler_policy_post (
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_FORBIDDEN,
-
TALER_EC_ANASTASIS_GENERIC_BAD_SIGNATURE,
+
TALER_EC_ANASTASIS_POLICY_BAD_SIGNATURE,
"Anastasis-Policy-Signature");
}
}
@@ -1015,7 +1015,7 @@ AH_handler_policy_post (
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
-
TALER_EC_ANASTASIS_INVALID_POLICY_UPLOAD,
+
TALER_EC_ANASTASIS_POLICY_INVALID_UPLOAD,
"Data uploaded does not match Etag
promise");
}
}
diff --git a/src/backend/anastasis-httpd_truth.c
b/src/backend/anastasis-httpd_truth.c
index 0b7cdd3..fd101ac 100644
--- a/src/backend/anastasis-httpd_truth.c
+++ b/src/backend/anastasis-httpd_truth.c
@@ -40,6 +40,27 @@
struct GetContext
{
+
+ /**
+ * Payment Identifier
+ */
+ struct ANASTASIS_PaymentSecretP payment_identifier;
+
+ /**
+ * Public key of the challenge which is solved.
+ */
+ struct ANASTASIS_CRYPTO_TruthPublicKeyP truth_public_key;
+
+ /**
+ * true if client provided a payment secret / order ID?
+ */
+ struct TALER_Amount challenge_cost;
+
+ /**
+ * Our handler context.
+ */
+ struct TM_HandlerContext *hc;
+
/**
* Kept in DLL for shutdown handling while suspended.
*/
@@ -65,11 +86,6 @@ struct GetContext
*/
struct ANASTASIS_AUTHORIZATION_State *as;
- /**
- * Public key of the challenge which is solved.
- */
- struct ANASTASIS_CRYPTO_TruthPublicKeyP truth_public_key;
-
/**
* Used while we are awaiting proposal creation.
*/
@@ -85,48 +101,27 @@ struct GetContext
*/
struct MHD_Response *resp;
- /**
- * Timestamp of the order in @e existing_order_id. Used to
- * select the most recent unpaid offer.
- */
- struct GNUNET_TIME_Absolute existing_pi_timestamp;
-
- /**
- * Payment Identifier
- */
- struct ANASTASIS_PaymentSecretP payment_identifier;
-
/**
* HTTP response code to use on resume, if resp is set.
*/
unsigned int response_code;
- /**
- * Whether to generate a claim token.
- */
- bool make_claim_token;
-
- /**
- * The claim token
- */
- struct TALER_ClaimTokenP claim_token;
-
/**
* true if client provided a payment secret / order ID?
*/
bool payment_identifier_provided;
- /**
- * true if client provided a payment secret / order ID?
- */
- struct TALER_Amount challenge_cost;
};
+
/**
- * Linked list over all authorization processes
+ * Head of linked list over all authorization processes
*/
-
static struct GetContext *gc_head;
+
+/**
+ * Tail of linked list over all authorization processes
+ */
static struct GetContext *gc_tail;
@@ -151,6 +146,7 @@ AH_truth_shutdown (void)
/**
* Callback used to notify the application about completed requests.
+ * Cleans up the requests data structures.
*
* @param hc
*/
@@ -161,6 +157,7 @@ request_done (struct TM_HandlerContext *hc)
if (NULL == gc)
return;
+ hc->cc = NULL;
GNUNET_CONTAINER_DLL_remove (gc_head,
gc_tail,
gc);
@@ -179,20 +176,16 @@ request_done (struct TM_HandlerContext *hc)
* Transmit a payment request for @a order_id on @a connection
*
* @param gc context to make payment request for
- * @return MHD response to use
*/
-// FIXME: share logic with anastasis-http_policy_upload.c!
-static int
+static void
make_payment_request (struct GetContext *gc)
{
struct MHD_Response *resp;
- /* request payment via Taler */
resp = MHD_create_response_from_buffer (0,
NULL,
MHD_RESPMEM_PERSISTENT);
- if (NULL == resp)
- return GNUNET_SYSERR;
+ GNUNET_assert (NULL != resp);
TALER_MHD_add_global_headers (resp);
{
char *hdr;
@@ -201,7 +194,6 @@ make_payment_request (struct GetContext *gc)
order_id = GNUNET_STRINGS_data_to_string_alloc (
&gc->payment_identifier,
sizeof (gc->payment_identifier));
-
GNUNET_asprintf (&hdr,
"taler://pay/%s/%s",
AH_backend_url,
@@ -215,7 +207,6 @@ make_payment_request (struct GetContext *gc)
}
gc->resp = resp;
gc->response_code = MHD_HTTP_PAYMENT_REQUIRED;
- return GNUNET_OK;
}
@@ -223,7 +214,7 @@ make_payment_request (struct GetContext *gc)
* Callbacks of this type are used to serve the result of submitting a
* /contract request to a merchant.
*
- * @param cls our `struct PolicyUploadContext`
+ * @param cls our `struct GetContext`
* @param por response details
*/
static void
@@ -233,6 +224,7 @@ proposal_cb (void *cls,
struct GetContext *gc = cls;
enum GNUNET_DB_QueryStatus qs;
+ gc->hc->cc = NULL;
GNUNET_CONTAINER_DLL_remove (gc_head,
gc_tail,
gc);
@@ -248,7 +240,7 @@ proposal_cb (void *cls,
gc->resp = TALER_MHD_make_json_pack (
"{s:I, s:s, s:I, s:I, s:O?}",
"code",
- (json_int_t) TALER_EC_SYNC_PAYMENT_CREATE_BACKEND_ERROR,
+ (json_int_t) TALER_EC_ANASTASIS_TRUTH_PAYMENT_CREATE_BACKEND_ERROR,
"hint",
"Failed to setup order with merchant backend",
"backend-ec",
@@ -258,12 +250,9 @@ proposal_cb (void *cls,
"backend-reply",
por->hr.reply);
GNUNET_assert (NULL != gc->resp);
- gc->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+ gc->response_code = MHD_HTTP_BAD_GATEWAY;
return;
}
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Storing payment request for order `%s'\n",
- por->details.ok.order_id);
qs = db->record_challenge_payment (db->cls,
&gc->truth_public_key,
&gc->payment_identifier,
@@ -276,83 +265,14 @@ proposal_cb (void *cls,
gc->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
return;
}
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Obtained fresh order `%s'\n",
- por->details.ok.order_id);
- if (GNUNET_OK !=
- make_payment_request (por->details.ok.order_id))
- {
- // FIXME: generate error!
- }
-}
-
-
-static MHD_RESULT
-return_key_share (const struct
- ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
- struct MHD_Connection *connection)
-{
- // load encrypted keyshare from db
- enum GNUNET_DB_QueryStatus qs;
- void *encrypted_keyshare;
- size_t encrypted_keyshare_size;
- struct MHD_Response *resp;
- MHD_RESULT ret;
-
- qs = db->get_key_share (db->cls,
- truth_public_key,
- &encrypted_keyshare,
- &encrypted_keyshare_size);
-
- if (qs != GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)
- {
- return MHD_HTTP_NOT_FOUND;
- }
-
- resp = MHD_create_response_from_buffer (encrypted_keyshare_size,
- encrypted_keyshare,
- MHD_RESPMEM_MUST_FREE);
- TALER_MHD_add_global_headers (resp);
- ret = MHD_queue_response (connection,
- MHD_HTTP_OK,
- resp);
- MHD_destroy_response (resp);
- return ret;
-}
-
-
-/**
- * Function called on all pending payments for the right
- * account.
- *
- * @param cls closure, our `struct BackupContext`
- * @param timestamp for how long have we been waiting
- * @param ps order id in the backend
- * @param amount how much is the order for
- */
-static void
-ongoing_payment_cb (void *cls,
- struct GNUNET_TIME_Absolute timestamp,
- const struct ANASTASIS_PaymentSecretP *ps,
- const struct TALER_Amount *amount)
-{
- struct GetContext *gc = cls;
-
- if (0 != TALER_amount_cmp (amount,
- &gc->challenge_cost))
- return; /* can't re-use, fees changed */
- if (gc->existing_pi_timestamp.abs_value_us < timestamp.abs_value_us)
- {
- gc->payment_identifier = *ps;
- gc->existing_pi_timestamp = timestamp;
- }
+ make_payment_request (gc);
}
/**
* Callback to process a GET /check-payment request
*
- * @param cls our `struct PolicyUploadContext`
+ * @param cls our `struct GetContext`
* @param hr HTTP response details
* @param osr order status
*/
@@ -364,225 +284,218 @@ check_payment_cb (void *cls,
{
struct GetContext *gc = cls;
- /* refunds are not supported, verify */
gc->cpo = NULL;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Payment status checked: %s\n",
- osr->status ? "paid" : "unpaid");
+ gc->hc->cc = NULL;
GNUNET_CONTAINER_DLL_remove (gc_head,
gc_tail,
gc);
MHD_resume_connection (gc->connection);
AH_trigger_daemon ();
- if (osr->status)
+ switch (hr->http_status)
{
- enum GNUNET_DB_QueryStatus qs;
-
- qs = db->update_challenge_payment (db->cls,
- &gc->truth_public_key,
- &gc->payment_identifier);
- if (0 <= qs)
- return; /* continue as planned */
+ case MHD_HTTP_OK:
+ GNUNET_assert (NULL != osr);
+ break;
+ case MHD_HTTP_NOT_FOUND:
+ /* We created this order before, how can it be not found now? */
GNUNET_break (0);
- gc->resp = TALER_MHD_make_error (TALER_EC_GENERIC_DB_STORE_FAILED,
- "challenge payment");
- gc->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
- return; /* continue as planned */
- }
- if (0 != gc->existing_pi_timestamp.abs_value_us)
- {
- /* repeat payment request */
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Repeating payment request\n");
- if (GNUNET_OK !=
- make_payment_request (gc))
+ gc->resp = TALER_MHD_make_error
(TALER_EC_ANASTASIS_TRUTH_ORDER_DISAPPEARED,
+ NULL);
+ gc->response_code = MHD_HTTP_BAD_GATEWAY;
+ return;
+ case MHD_HTTP_BAD_GATEWAY:
+ gc->resp = TALER_MHD_make_error (
+ TALER_EC_ANASTASIS_TRUTH_BACKEND_EXCHANGE_BAD,
+ NULL);
+ gc->response_code = MHD_HTTP_BAD_GATEWAY;
+ return;
+ case MHD_HTTP_GATEWAY_TIMEOUT:
+ gc->resp = TALER_MHD_make_error
(TALER_EC_ANASTASIS_GENERIC_BACKEND_TIMEOUT,
+ "Timeout check payment status");
+ GNUNET_assert (NULL != gc->resp);
+ gc->response_code = MHD_HTTP_GATEWAY_TIMEOUT;
+ return;
+ default:
{
- // FIXME: generate error
+ char status[14];
+
+ GNUNET_snprintf (status,
+ sizeof (status),
+ "%u",
+ hr->http_status);
+ gc->resp = TALER_MHD_make_error (
+ TALER_EC_ANASTASIS_TRUTH_UNEXPECTED_PAYMENT_STATUS,
+ status);
+ GNUNET_assert (NULL != gc->resp);
+ gc->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+ return;
}
- return;
}
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Timeout waiting for payment\n");
- gc->resp = TALER_MHD_make_error (TALER_EC_SYNC_PAYMENT_GENERIC_TIMEOUT,
- "Timeout awaiting promised payment");
- GNUNET_assert (NULL != gc->resp);
- gc->response_code = MHD_HTTP_REQUEST_TIMEOUT;
-}
-
-/**
- * Helper function used to ask our backend to await
- * a payment for the user's account.
- *
- * @param puc context to begin payment for.
- * @param timeout when to give up trying
- */
-static void
-await_payment (struct GetContext *gc,
- struct GNUNET_TIME_Relative timeout)
-{
- GNUNET_CONTAINER_DLL_insert (gc_tail,
- gc_head,
- gc);
- MHD_suspend_connection (gc->connection);
+ switch (osr->status)
{
- char *order_id;
+ case TALER_MERCHANT_OSC_PAID:
+ {
+ enum GNUNET_DB_QueryStatus qs;
- order_id = GNUNET_STRINGS_data_to_string_alloc (
- &gc->payment_identifier,
- sizeof (gc->payment_identifier));
- gc->cpo = TALER_MERCHANT_merchant_order_get (AH_ctx,
- AH_backend_url,
- order_id,
- NULL /* our payments are NOT
session-bound */,
- false,
- timeout,
- &check_payment_cb,
- gc);
- GNUNET_free (order_id);
+ qs = db->update_challenge_payment (db->cls,
+ &gc->truth_public_key,
+ &gc->payment_identifier);
+ if (0 <= qs)
+ return; /* continue as planned */
+ GNUNET_break (0);
+ gc->resp = TALER_MHD_make_error (TALER_EC_GENERIC_DB_STORE_FAILED,
+ "update challenge payment");
+ gc->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+ return; /* continue as planned */
+ }
+ case TALER_MERCHANT_OSC_CLAIMED:
+ case TALER_MERCHANT_OSC_UNPAID:
+ /* repeat payment request */
+ make_payment_request (gc);
+ return;
}
- AH_trigger_curl ();
+ /* should never get here */
+ GNUNET_break (0);
}
/**
- * Helper function used to ask our backend to begin
- * processing a payment for the user's account.
- * May perform asynchronous operations by suspending the connection
- * if required.
+ * Helper function used to ask our backend to begin processing a
+ * payment for the user's account. May perform asynchronous
+ * operations by suspending the connection if required.
*
- * @param puc context to begin payment for.
- * @param pay_req #GNUNET_YES if payment was explicitly requested,
- * #GNUNET_NO if payment is needed
+ * @param gc context to begin payment for.
* @return MHD status code
*/
static MHD_RESULT
-begin_payment (struct GetContext *gc,
- int pay_req)
+begin_payment (struct GetContext *gc)
{
- json_t *order;
enum GNUNET_DB_QueryStatus qs;
+ char *order_id;
qs = db->lookup_challenge_payment (db->cls,
&gc->truth_public_key,
- &ongoing_payment_cb,
- gc);
+ &gc->payment_identifier);
if (qs < 0)
{
- struct MHD_Response *resp;
- MHD_RESULT ret;
-
- resp = TALER_MHD_make_error (TALER_EC_GENERIC_DB_FETCH_FAILED,
- "challenge payment");
- ret = MHD_queue_response (gc->connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- resp);
- MHD_destroy_response (resp);
- return ret;
- }
-
- if (0 != gc->existing_pi_timestamp.abs_value_us)
- {
- await_payment (gc,
- GNUNET_TIME_UNIT_ZERO);
- return MHD_YES;
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (gc->connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "lookup challenge payment");
}
-
- GNUNET_CONTAINER_DLL_insert (gc_head,
- gc_tail,
+ gc->hc->cc = &request_done;
+ GNUNET_CONTAINER_DLL_insert (gc_tail,
+ gc_head,
gc);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Suspending connection while creating order at `%s'\n",
- AH_backend_url);
MHD_suspend_connection (gc->connection);
+ order_id = GNUNET_STRINGS_data_to_string_alloc (
+ &gc->payment_identifier,
+ sizeof (gc->payment_identifier));
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
{
- char *order_id;
+ /* We already created the order, check if it was paid */
+ gc->cpo = TALER_MERCHANT_merchant_order_get (AH_ctx,
+ AH_backend_url,
+ order_id,
+ NULL /* NOT session-bound */,
+ false,
+ GNUNET_TIME_UNIT_ZERO,
+ &check_payment_cb,
+ gc);
+ }
+ else
+ {
+ /* Create a fresh order */
+ json_t *order;
- order_id = GNUNET_STRINGS_data_to_string_alloc (
- &gc->payment_identifier,
- sizeof(struct ANASTASIS_PaymentSecretP));
order = json_pack ("{s:o, s:s, s:s, s:s}",
"amount", TALER_JSON_from_amount (&gc->challenge_cost),
"summary", "annual fee for anastasis service",
"fulfillment_url", AH_fulfillment_url,
"order_id", order_id);
- GNUNET_free (order_id);
+ gc->po = TALER_MERCHANT_orders_post2 (AH_ctx,
+ AH_backend_url,
+ order,
+ GNUNET_TIME_UNIT_ZERO,
+ NULL, /* no payment target */
+ 0,
+ NULL, /* no inventory products */
+ 0,
+ NULL, /* no uuids */
+ false, /* do NOT require claim token
*/
+ &proposal_cb,
+ gc);
+ json_decref (order);
}
- gc->po = TALER_MERCHANT_orders_post2 (AH_ctx,
- AH_backend_url,
- order,
- GNUNET_TIME_UNIT_ZERO,
- NULL, /* no payment target */
- 0,
- NULL, /* no inventory products */
- 0,
- NULL, /* no uuids */
- false, /* do NOT require claim token */
- &proposal_cb,
- gc);
-
+ GNUNET_free (order_id);
AH_trigger_curl ();
- json_decref (order);
return MHD_YES;
}
/**
- * We got some query status from the DB. Handle the error cases.
- * May perform asynchronous operations by suspending the connection
- * if required.
+ * Load encrypted keyshare from db and return it to the client.
*
- * @param gc connection to handle status for
- * @param qs query status to handle
- * @return #MHD_YES or #MHD_NO
+ * @param truth_public key the key to the truth for the looup
+ * @param connection the connection to respond upon
+ * @return MHD status code
*/
static MHD_RESULT
-handle_database_error (struct GetContext *gc,
- enum ANASTASIS_DB_QueryStatus qs)
+return_key_share (
+ const struct ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
+ struct MHD_Connection *connection)
{
- switch (qs)
+ void *encrypted_keyshare;
+ size_t encrypted_keyshare_size;
+
{
- case ANASTASIS_DB_STATUS_PAYMENT_REQUIRED:
+ enum GNUNET_DB_QueryStatus qs;
+
+ qs = db->get_key_share (db->cls,
+ truth_public_key,
+ &encrypted_keyshare,
+ &encrypted_keyshare_size);
+ switch (qs)
{
- if (! gc->payment_identifier_provided)
- {
- GNUNET_CRYPTO_random_block (
- GNUNET_CRYPTO_QUALITY_NONCE,
- &gc->payment_identifier,
- sizeof (struct ANASTASIS_PaymentSecretP));
- return begin_payment (gc,
- GNUNET_NO);
- }
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "get key share");
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_NOT_FOUND,
+
TALER_EC_ANASTASIS_TRUTH_KEY_SHARE_GONE,
+ NULL);
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ break;
+ }
+ }
+
+ {
+ struct MHD_Response *resp;
+
+ resp = MHD_create_response_from_buffer (encrypted_keyshare_size,
+ encrypted_keyshare,
+ MHD_RESPMEM_MUST_COPY);
+ GNUNET_free (encrypted_keyshare);
+ TALER_MHD_add_global_headers (resp);
+
+ {
+ MHD_RESULT ret;
- await_payment (gc,
- CHECK_PAYMENT_GENERIC_TIMEOUT);
+ ret = MHD_queue_response (connection,
+ MHD_HTTP_OK,
+ resp);
+ MHD_destroy_response (resp);
+ return ret;
}
- return MHD_YES;
- case ANASTASIS_DB_STATUS_HARD_ERROR:
- case ANASTASIS_DB_STATUS_SOFT_ERROR:
- GNUNET_break (0);
- return TALER_MHD_reply_with_error (gc->connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- NULL);
- case ANASTASIS_DB_STATUS_NO_RESULTS:
- GNUNET_assert (0);
- return MHD_NO;
- /* intentional fall-through! */
- case ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT:
- GNUNET_assert (0);
- return MHD_NO;
- /*Should never happen*/
- default:
- GNUNET_break (0);
- return TALER_MHD_reply_with_error (gc->connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- NULL);
}
- GNUNET_break (0);
- return MHD_NO;
}
@@ -598,19 +511,16 @@ AH_handler_truth_get (struct MHD_Connection *connection,
struct TM_HandlerContext *hc)
{
struct GetContext *gc = hc->ctx;
- struct ANASTASIS_CRYPTO_TruthPublicKeyP truth_public_key;
struct ANASTASIS_CRYPTO_TruthKeyP truth_key;
struct GNUNET_HashCode challenge_response;
- const char *challenge_response_s;
+ struct ANASTASIS_AuthorizationPlugin *p;
+ bool have_response;
void *encrypted_truth;
size_t encrypted_truth_size;
void *decrypted_truth;
size_t decrypted_truth_size;
char *truth_mime;
- char *method;
- struct TALER_Amount zero_amount;
- TALER_amount_get_zero (AH_currency, &zero_amount);
- bool zero_cost = false;
+ bool is_question;
if (NULL != gc)
{
@@ -619,9 +529,6 @@ AH_handler_truth_get (struct MHD_Connection *connection,
MHD_RESULT ret;
/* We generated a response asynchronously, queue that */
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Returning asynchronously generated response with HTTP
status %u\n",
- gc->response_code);
ret = MHD_queue_response (connection,
gc->response_code,
gc->resp);
@@ -632,6 +539,7 @@ AH_handler_truth_get (struct MHD_Connection *connection,
}
if (NULL != gc->as)
{
+ /* Authorization process is "running", check what is going on */
enum ANASTASIS_AUTHORIZATION_Result ret;
ret = gc->authorization->process (gc->as,
@@ -666,13 +574,17 @@ AH_handler_truth_get (struct MHD_Connection *connection,
return MHD_NO;
}
}
+ /* How can we get here? */
+ GNUNET_break (0);
+ return MHD_NO;
}
- else
- {
- gc = GNUNET_new (struct GetContext);
- hc->ctx = gc;
- gc->connection = connection;
- }
+
+ /* Fresh request, do initial setup */
+ gc = GNUNET_new (struct GetContext);
+ gc->hc = hc;
+ hc->ctx = gc;
+ gc->connection = connection;
+
{
const char *pay_id;
@@ -682,18 +594,17 @@ AH_handler_truth_get (struct MHD_Connection *connection,
if (NULL != pay_id)
{
if (GNUNET_OK !=
- GNUNET_STRINGS_string_to_data (pay_id,
- strlen (pay_id),
- &gc->payment_identifier,
- sizeof (struct
- ANASTASIS_PaymentSecretP)))
+ GNUNET_STRINGS_string_to_data (
+ pay_id,
+ strlen (pay_id),
+ &gc->payment_identifier,
+ sizeof (struct ANASTASIS_PaymentSecretP)))
{
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
- // FIXME: find error code
- TALER_EC_SYNC_BAD_IF_MATCH,
- "Payment-Identifier does not
include a base32-encoded Payment-Secret");
+
TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "Payment-Identifier");
}
gc->payment_identifier_provided = true;
}
@@ -702,223 +613,262 @@ AH_handler_truth_get (struct MHD_Connection *connection,
const char *pub_key_str;
pub_key_str = &url[strlen ("/truth/")];
- GNUNET_assert (NULL != pub_key_str);
-
- GNUNET_STRINGS_string_to_data (pub_key_str,
- strlen (pub_key_str),
- &truth_public_key,
- sizeof(struct
- ANASTASIS_CRYPTO_TruthPublicKeyP));
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "public key from Url (keyshare lookup): %s\n",
- TALER_B2S (&truth_public_key));
-
- challenge_response_s = MHD_lookup_connection_value (connection,
- MHD_GET_ARGUMENT_KIND,
- "response");
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Challenge response from url (keyshare lookup): %s\n",
- challenge_response_s);
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (
+ pub_key_str,
+ strlen (pub_key_str),
+ &gc->truth_public_key,
+ sizeof(struct ANASTASIS_CRYPTO_TruthPublicKeyP)))
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "truth public key");
+ }
}
+
{
- // check if header contains Truth-Decryption-Key
+ /* check if header contains Truth-Decryption-Key */
const char *tdk;
tdk = MHD_lookup_connection_value (connection,
MHD_HEADER_KIND,
"Truth-Decryption-Key");
- if (NULL == tdk)
- return MHD_HTTP_PRECONDITION_FAILED;
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MISSING,
+ "Truth-Decryption-Key");
+ }
- if ( (NULL != tdk) &&
- (GNUNET_OK !=
- GNUNET_STRINGS_string_to_data (tdk,
- strlen (tdk),
- &truth_key,
- sizeof (struct
- ANASTASIS_CRYPTO_TruthKeyP))))
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (
+ tdk,
+ strlen (tdk),
+ &truth_key,
+ sizeof (struct ANASTASIS_CRYPTO_TruthKeyP)))
{
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
- // FIXME: find error code
- TALER_EC_SYNC_BAD_IF_MATCH, // use
description in gana: "Truth-Decryption-Key does not include a base32-encoded
decryption key"
- tdk);
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "Truth-Decryption-Key");
}
+ }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "TruthKey from header: %s\n",
- TALER_B2S (&truth_key));
+ {
+ const char *challenge_response_s;
+
+ challenge_response_s = MHD_lookup_connection_value (connection,
+ MHD_GET_ARGUMENT_KIND,
+ "response");
+ if ( (NULL != challenge_response_s) &&
+ (GNUNET_OK !=
+ GNUNET_CRYPTO_hash_from_string (challenge_response_s,
+ &challenge_response)) )
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "response");
+ }
+ have_response = (NULL != challenge_response_s);
}
+
{
- // load encrypted truth from db
+ /* load encrypted truth from DB */
enum GNUNET_DB_QueryStatus qs;
+ char *method;
qs = db->get_escrow_challenge (db->cls,
- &truth_public_key,
+ &gc->truth_public_key,
&encrypted_truth,
&encrypted_truth_size,
&truth_mime,
&method);
- if (qs != GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)
+ switch (qs)
{
- return MHD_HTTP_NOT_FOUND;
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (gc->connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "get escrow challenge");
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_ANASTASIS_TRUTH_UNKNOWN,
+ NULL);
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ break;
}
- }
- {
- // decrypt encrypted_truth
- ANASTASIS_CRYPTO_truth_decrypt (&truth_key,
- encrypted_truth,
- encrypted_truth_size,
- &decrypted_truth,
- &decrypted_truth_size);
- }
-
- /* Check if the cost is zero to skip the payment */
- // FIXME: lookup costs properly!
- if (0 == strcmp ("question",
- method))
- {
- if (0 == TALER_amount_cmp (&AH_question_cost, &zero_amount))
- zero_cost = true;
- }
- if (0 == strcmp ("file",
- method))
- {
- if (0 == TALER_amount_cmp (&AH_file_cost, &zero_amount))
- zero_cost = true;
- }
-
- /* Check database to see if the transaction is permissible */
-
- if (! zero_cost)
- {
- enum GNUNET_DB_QueryStatus qs;
-
- if (0 == strcmp ("question",
- method))
+ is_question = strcmp ("question",
+ method);
+ if (! is_question)
{
- gc->challenge_cost = AH_question_cost;
+ gc->authorization
+ = ANASTASIS_authorization_plugin_load (method,
+ AH_cfg,
+ &gc->challenge_cost);
+ if (NULL == gc->authorization)
+ {
+ MHD_RESULT ret;
+
+ ret = TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_ANASTASIS_TRUTH_AUTHORIZATION_METHOD_NO_LONGER_SUPPORTED,
+ method);
+ GNUNET_free (encrypted_truth);
+ GNUNET_free (method);
+ return ret;
+ }
+ GNUNET_free (method);
}
- if (0 == strcmp ("file",
- method))
+ else
{
- gc->challenge_cost = AH_file_cost;
+ gc->challenge_cost = AH_question_cost;
}
+ }
+
+ {
+ struct TALER_Amount zero_amount;
- if (gc->payment_identifier_provided)
+ TALER_amount_get_zero (AH_currency,
+ &zero_amount);
+ if (0 != TALER_amount_cmp (&gc->challenge_cost,
+ &zero_amount))
{
- bool paid = false;
+ /* Check database to see if the transaction is paid for */
+ enum GNUNET_DB_QueryStatus qs;
+ bool paid;
+ if (! gc->payment_identifier_provided)
+ {
+ GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+ &gc->payment_identifier,
+ sizeof (struct ANASTASIS_PaymentSecretP));
+ GNUNET_free (encrypted_truth);
+ return begin_payment (gc);
+ }
qs = db->check_challenge_payment (db->cls,
&gc->payment_identifier,
&paid);
- if (qs < 0)
- return handle_database_error (gc,
- qs);
-
- if ((qs >= 0) && (! paid))
+ switch (qs)
{
- return begin_payment (gc,
- GNUNET_YES);
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_break (0);
+ GNUNET_free (encrypted_truth);
+ return TALER_MHD_reply_with_error (gc->connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "check challenge payment");
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ /* Re-use existing payment identifier */
+ GNUNET_free (encrypted_truth);
+ return begin_payment (gc);
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ if (! paid)
+ {
+ GNUNET_free (encrypted_truth);
+ return begin_payment (gc);
+ }
+ break;
}
}
-
- if (! gc->payment_identifier_provided)
- {
- GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
- &gc->payment_identifier,
- sizeof (struct ANASTASIS_PaymentSecretP));
- return begin_payment (gc,
- GNUNET_YES);
- }
}
- if (NULL == challenge_response_s)
+
+ /* We've been paid, now validate response */
{
- // FIXME: queue PROPER reply...
- GNUNET_free (decrypted_truth);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_FORBIDDEN,
- // FIXME: find error code
- TALER_EC_SYNC_BAD_IF_MATCH,
- NULL);
+ /* decrypt encrypted_truth */
+ ANASTASIS_CRYPTO_truth_decrypt (&truth_key,
+ encrypted_truth,
+ encrypted_truth_size,
+ &decrypted_truth,
+ &decrypted_truth_size);
+ GNUNET_free (encrypted_truth);
}
- GNUNET_CRYPTO_hash_from_string (challenge_response_s,
- &challenge_response);
- if (0 == strcmp ("question",
- method))
+
+ /* Special case for secure question: we do not generate a numeric challenge,
+ but check that the hash matches */
+ if (is_question)
{
- if (0 != GNUNET_memcmp (&challenge_response,
- decrypted_truth))
+ if (! have_response)
{
- GNUNET_break (0);
+ GNUNET_free (decrypted_truth);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_FORBIDDEN,
- // FIXME: find error code
- TALER_EC_SYNC_BAD_IF_MATCH,
- challenge_response_s);
+
TALER_EC_ANASTASIS_TRUTH_CHALLENGE_RESPONSE_REQUIRED,
+ NULL);
}
- else
+ if ( (decrypted_truth_size != sizeof (challenge_response)) ||
+ (0 != memcmp (&challenge_response,
+ decrypted_truth,
+ decrypted_truth_size)) )
{
- return return_key_share (&truth_public_key,
- connection);
+ GNUNET_break_op (0);
+ GNUNET_free (decrypted_truth);
+ // FIXME: mark in DB that we did it (now, for
code_retransmission_frequency!)
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_FORBIDDEN,
+
TALER_EC_ANASTASIS_TRUTH_CHALLENGE_FAILED,
+ NULL);
}
+ return return_key_share (&gc->truth_public_key,
+ connection);
}
- GNUNET_free (decrypted_truth);
/* Not security question, check for answer in DB */
- if (NULL != challenge_response_s)
+ if (have_response)
{
enum ANASTASIS_DB_CodeStatus cs;
+ GNUNET_free (decrypted_truth);
cs = db->verify_challenge_code (db->cls,
- &truth_public_key,
+ &gc->truth_public_key,
&challenge_response);
switch (cs)
{
- case ANASTASIS_DB_STATUS_CHALLENGE_CODE_MISMATCH:
-
- case ANASTASIS_DB_STATUS_HARD_ERROR:
- // FIXME: proper reply!
- return MHD_NO;
- case ANASTASIS_DB_STATUS_SOFT_ERROR:
- // FIXME: proper reply!
- return MHD_NO;
- case ANASTASIS_DB_STATUS_NO_RESULTS:
- // FIXME: proper reply!
- return MHD_NO;
- case ANASTASIS_DB_STATUS_VALID_CODE_STORED:
- return return_key_share (&truth_public_key,
+ case ANASTASIS_DB_CODE_STATUS_CHALLENGE_CODE_MISMATCH:
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_FORBIDDEN,
+
TALER_EC_ANASTASIS_TRUTH_CHALLENGE_FAILED,
+ NULL);
+ case ANASTASIS_DB_CODE_STATUS_HARD_ERROR:
+ case ANASTASIS_DB_CODE_STATUS_SOFT_ERROR:
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (gc->connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "verify_challenge_code");
+ case ANASTASIS_DB_CODE_STATUS_NO_RESULTS:
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_GONE,
+
TALER_EC_ANASTASIS_TRUTH_CHALLENGE_UNKNOWN,
+ NULL);
+ case ANASTASIS_DB_CODE_STATUS_VALID_CODE_STORED:
+ return return_key_share (&gc->truth_public_key,
connection);
}
GNUNET_break (0);
return MHD_NO;
}
- /* Not security question and no answer: use plugin to generate challenge! */
+ /* Not security question and no answer: use plugin to check if
+ decrypted truth is a valid challenge! */
{
- struct ANASTASIS_AuthorizationPlugin *authorization;
enum GNUNET_GenericReturnValue ret;
- struct ANASTASIS_AUTHORIZATION_State *as;
- enum ANASTASIS_AUTHORIZATION_Result aret;
- enum ANASTASIS_DB_QueryStatus qs;
- struct GNUNET_TIME_Relative challenge_expiration;
- challenge_expiration = GNUNET_TIME_UNIT_HOURS;
- authorization = ANASTASIS_authorization_plugin_load (method);
- if (NULL == authorization)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Plugin not found: %s",method);
- GNUNET_free (decrypted_truth);
- return MHD_NO;
- }
-
- ret = authorization->validate (authorization->cls,
- connection,
- decrypted_truth,
- decrypted_truth_size);
+ ret = gc->authorization->validate (gc->authorization->cls,
+ connection,
+ decrypted_truth,
+ decrypted_truth_size);
switch (ret)
{
case GNUNET_OK:
@@ -933,86 +883,96 @@ AH_handler_truth_get (struct MHD_Connection *connection,
GNUNET_free (decrypted_truth);
return MHD_NO;
}
+ }
- uint64_t code = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE,
- 999999);
+ /* Setup challenge and begin authorization process */
+ {
+ uint64_t code;
+ enum GNUNET_DB_QueryStatus qs;
+ code = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE,
+ 999999);
+ // FIXME: this is more complex:
+ // - p->code_rotation_period
+ // - p->code_validity_period
+ // - p->code_retransmission_frequency
+ // all MUST be considered here!
+ // -> DB API change needed!
qs = db->store_challenge_code (db->cls,
- &truth_public_key,
+ &gc->truth_public_key,
code,
- challenge_expiration,
+ p->code_validity_period,
3);
-
switch (qs)
{
- case ANASTASIS_DB_STATUS_HARD_ERROR:
- /* data invalid, reply was NOT queued */
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_break (0);
GNUNET_free (decrypted_truth);
- return MHD_NO;
- case ANASTASIS_DB_STATUS_SOFT_ERROR:
- /* data invalid, reply was NOT queued */
+ return TALER_MHD_reply_with_error (gc->connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "store_challenge_code");
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
GNUNET_free (decrypted_truth);
- return MHD_NO;
- case ANASTASIS_DB_STATUS_VALID_CODE_STORED:
- /*FIXME already code stored message */
- return MHD_NO;
- case ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT:
- /*challengecode was stored successfully*/
+ return TALER_MHD_reply_with_error (gc->connection,
+ MHD_HTTP_ALREADY_REPORTED,
+
TALER_EC_ANASTASIS_TRUTH_CHALLENGE_ACTIVE,
+ NULL);
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ /* challenge code was stored successfully*/
break;
- default:
- GNUNET_free (decrypted_truth);
- return MHD_NO;
}
- as = authorization->start (authorization->cls,
- &truth_public_key,
- code,
- authorization->auth_command,
- decrypted_truth,
- decrypted_truth_size);
-
- if (NULL == as)
+ gc->as = gc->authorization->start (gc->authorization->cls,
+ &gc->truth_public_key,
+ code,
+ decrypted_truth,
+ decrypted_truth_size);
+ GNUNET_free (decrypted_truth);
+ if (NULL == gc->as)
{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- ("AUTHORIZATION START FAILED"));
- // FIXME: queue PROPER reply...
- return MHD_NO;
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (gc->connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+
TALER_EC_ANASTASIS_TRUTH_AUTHORIZATION_START_FAILED,
+ NULL);
}
- gc->connection = connection;
- gc->authorization = authorization;
- gc->as = as;
- hc->ctx = gc;
hc->cc = &request_done;
GNUNET_CONTAINER_DLL_insert (gc_head,
gc_tail,
gc);
- aret = authorization->process (as,
- connection);
- switch (aret)
{
- case ANASTASIS_AUTHORIZATION_RES_SUCCESS:
- /* all good, challenge sent! */
- // FIXME: mark in DB that we did it (now, for
code_retransmission_frequency!)
- break;
- case ANASTASIS_AUTHORIZATION_RES_FAILED:
- /* sending challenge failed */
- // FIXME: give at least a refund!?
- break;
- case ANASTASIS_AUTHORIZATION_RES_SUSPENDED:
- /* we have been suspended, see you later */
+ enum ANASTASIS_AUTHORIZATION_Result aret;
+
+ aret = gc->authorization->process (gc->as,
+ connection);
+ switch (aret)
+ {
+ case ANASTASIS_AUTHORIZATION_RES_SUCCESS:
+ /* all good, challenge sent! */
+ // FIXME: mark in DB that we did it (now, for
code_retransmission_frequency!)
+ break;
+ case ANASTASIS_AUTHORIZATION_RES_FAILED:
+ /* sending challenge failed */
+ // FIXME: give at least a refund!?
+ break;
+ case ANASTASIS_AUTHORIZATION_RES_SUSPENDED:
+ /* we have been suspended, see you later */
+ return MHD_YES;
+ case ANASTASIS_AUTHORIZATION_RES_SUCCESS_REPLY_FAILED:
+ /* Challenge sent successfully, but HTTP reply failed */
+ // FIXME: mark in DB that we did it (now, for
code_retransmission_frequency!)
+ gc->authorization->cleanup (gc->as);
+ return MHD_NO;
+ case ANASTASIS_AUTHORIZATION_RES_FAILED_REPLY_FAILED:
+ /* failure to send challenge AND to queue reply, kill connection */
+ gc->authorization->cleanup (gc->as);
+ return MHD_NO;
+ }
+ gc->authorization->cleanup (gc->as);
+ gc->as = NULL;
return MHD_YES;
- case ANASTASIS_AUTHORIZATION_RES_SUCCESS_REPLY_FAILED:
- /* Challenge sent successfully */
- // FIXME: mark in DB that we did it (now, for
code_retransmission_frequency!)
- authorization->cleanup (gc->as);
- return MHD_NO;
- case ANASTASIS_AUTHORIZATION_RES_FAILED_REPLY_FAILED:
- /* failure to queue reply, kill connection */
- authorization->cleanup (gc->as);
- return MHD_NO;
}
- authorization->cleanup (gc->as);
- gc->as = NULL;
- return MHD_YES;
}
}
diff --git a/src/backend/anastasis-httpd_truth_upload.c
b/src/backend/anastasis-httpd_truth_upload.c
index 7228d99..d231aac 100644
--- a/src/backend/anastasis-httpd_truth_upload.c
+++ b/src/backend/anastasis-httpd_truth_upload.c
@@ -58,7 +58,7 @@ AH_handler_truth_post (struct MHD_Connection *connection,
struct ANASTASIS_CRYPTO_TruthPublicKeyP truth_public_key;
int res;
struct ANASTASIS_DB_Truth truth;
- enum ANASTASIS_DB_QueryStatus qs;
+ enum GNUNET_DB_QueryStatus qs;
/* extract public key from url */
{
@@ -113,7 +113,7 @@ AH_handler_truth_post (struct MHD_Connection *connection,
qs);
json_decref (json);
GNUNET_JSON_parse_free (spec);
- if (ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
{
struct MHD_Response *resp;
diff --git a/src/backend/anastasis_authorization_plugin.c
b/src/backend/anastasis_authorization_plugin.c
index b79fb84..b1824ee 100644
--- a/src/backend/anastasis_authorization_plugin.c
+++ b/src/backend/anastasis_authorization_plugin.c
@@ -21,6 +21,7 @@
*/
#include "platform.h"
#include "anastasis_authorization_plugin.h"
+#include "anastasis-httpd.h"
#include <ltdl.h>
@@ -73,14 +74,6 @@ struct AuthPlugin
};
-/**
- * Load authorization plugin.
- *
- * @param method name of the method to load
- * @param AH_cfg configuration to use
- * @param[out] set to the cost for using the plugin during recovery
- * @return #GNUNET_OK on success
- */
struct ANASTASIS_AuthorizationPlugin *
ANASTASIS_authorization_plugin_load (
const char *method,
@@ -117,14 +110,15 @@ ANASTASIS_authorization_plugin_load (
GNUNET_free (ap);
return NULL;
}
+ // FIXME: AH_annual_fee is not a symbol of this library!!!
if (GNUNET_OK !=
TALER_amount_cmp_currency (&ap->cost,
&AH_annual_fee))
{
- GNUNET_log_config_malformed (GNUNET_ERROR_TYPE_ERROR,
- sec_name,
- "COST",
- "currency mismatch");
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ sec_name,
+ "COST",
+ "currency mismatch");
GNUNET_free (sec_name);
GNUNET_free (ap);
return NULL;
@@ -155,26 +149,6 @@ ANASTASIS_authorization_plugin_load (
}
-/**
- * Shutdown the plugin.
- *
- * @param plugin the plugin to unload
- */
-void
-ANASTASIS_authorization_plugin_unload (
- struct ANASTASIS_AuthorizationPlugin *plugin)
-{
- char *lib_name;
-
- if (NULL == plugin)
- return;
- lib_name = plugin->library_name;
- GNUNET_assert (NULL == GNUNET_PLUGIN_unload (lib_name,
- plugin));
- GNUNET_free (lib_name);
-}
-
-
void
ANASTASIS_authorization_plugin_shutdown (void)
{
diff --git a/src/backend/anastasis_authorization_plugin_file.c
b/src/backend/anastasis_authorization_plugin_file.c
index e23a21b..691aaef 100644
--- a/src/backend/anastasis_authorization_plugin_file.c
+++ b/src/backend/anastasis_authorization_plugin_file.c
@@ -113,7 +113,6 @@ static struct ANASTASIS_AUTHORIZATION_State *
file_start (void *cls,
const struct ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
uint64_t code,
- char *auth_command,
const void *data,
size_t data_length)
{
@@ -183,8 +182,6 @@ file_process (struct ANASTASIS_AUTHORIZATION_State *as,
strlen (as->filename),
response,
response_size);
- char *test = GNUNET_STRINGS_data_to_string_alloc (response,
- response_size);
resp = MHD_create_response_from_buffer (response_size,
response,
MHD_RESPMEM_MUST_FREE);
diff --git a/src/backend/anastasis_authorization_plugin_sms.c
b/src/backend/anastasis_authorization_plugin_sms.c
index f3d1ea8..579992c 100644
--- a/src/backend/anastasis_authorization_plugin_sms.c
+++ b/src/backend/anastasis_authorization_plugin_sms.c
@@ -1,6 +1,6 @@
/*
This file is part of Anastasis
- Copyright (C) 2019 Taler Systems SA
+ Copyright (C) 2019, 2021 Taler Systems SA
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
@@ -29,29 +29,83 @@
/**
* Saves the State of a authorization process
*/
+struct SMS_Context
+{
+
+ /**
+ * Command which is executed to run the plugin (some bash script or a
+ * command line argument)
+ */
+ char *auth_command;
+
+ /**
+ * Regex for phone number validation.
+ */
+ regex_t regex;
+
+};
+
+/**
+ * Saves the State of a authorization process
+ */
struct ANASTASIS_AUTHORIZATION_State
{
/**
* Public key of the challenge which is authorised
*/
- const struct ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key;
+ struct ANASTASIS_CRYPTO_TruthPublicKeyP truth_public_key;
+
/**
* Code which is sent to the user (here sent via SMS)
*/
uint64_t code;
+
+ /**
+ * Our plugin context.
+ */
+ struct SMS_Context *ctx;
+
/**
* holds the truth information
*/
char *phone_number;
+
/**
- * closure
+ * Handle to the helper process.
*/
- void *cls;
+ struct GNUNET_OS_Process *child;
+
/**
- * Command which is executed to run the sms authentication
+ * Handle to wait for @e child
*/
- char *auth_command;
+ struct ANASTASIS_ChildWaitHandle *cwh;
+
+ /**
+ * Our client connection, set if suspended.
+ */
+ struct MHD_Connection *connection;
+
+ /**
+ * Message to send.
+ */
+ char *msg;
+
+ /**
+ * Offset of transmission in msg.
+ */
+ size_t msg_off;
+
+ /**
+ * Exit code from helper.
+ */
+ long unsigned int exit_code;
+
+ /**
+ * How did the helper die?
+ */
+ enum GNUNET_OS_ProcessStatusType pst;
+
};
@@ -63,7 +117,7 @@ struct ANASTASIS_AUTHORIZATION_State
*
* To be possibly used before issuing a 402 payment required to the client.
*
- * @param cls closure
+ * @param cls closure with a `struct SMS_Context`
* @param connection HTTP client request (for queuing response)
* @param data input to validate (i.e. is it a valid phone number, etc.)
* @param data_length number of bytes in @a data
@@ -77,46 +131,37 @@ sms_validate (void *cls,
const char *data,
size_t data_length)
{
- regex_t regex;
+ struct SMS_Context *ctx = cls;
int regex_result;
- /*FIXME very basic check */
- const char *regexp = "^[0-9]+$";
- char *phone_number = GNUNET_STRINGS_data_to_string_alloc (data,
- data_length);
-
- regex_result = regcomp (®ex,
- regexp,
- REG_EXTENDED);
- if (0 < regex_result)
- {
- GNUNET_break (0);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to compile regular expression.");
- regfree (®ex);
- return GNUNET_NO;
- }
+ char *phone_number;
- regex_result = regexec (®ex,
+ phone_number = GNUNET_strndup (data,
+ data_length);
+ regex_result = regexec (&ctx->regex,
phone_number,
0,
NULL,
0);
+ GNUNET_free (phone_number);
if (0 != regex_result)
{
- regfree (®ex);
+ if (MHD_NO ==
+ TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_EXPECTATION_FAILED,
+ TALER_EC_ANASTASIS_SMS_PHONE_INVALID,
+ NULL))
+ return GNUNET_SYSERR;
return GNUNET_NO;
}
- regfree (®ex);
- GNUNET_free (phone_number);
return GNUNET_OK;
}
/**
* Begin issuing authentication challenge to user based on @a data.
- * I.e. start to send SMS or e-mail or launch video identification.
+ * Sends SMS.
*
- * @param cls closure
+ * @param cls closure with a `struct SMS_Context`
* @param truth_public_key Identifier of the challenge, to be (if possible)
included in the
* interaction with the user
* @param code secret code that the user has to provide back to satisfy the
challenge in
@@ -128,23 +173,45 @@ static struct ANASTASIS_AUTHORIZATION_State *
sms_start (void *cls,
const struct ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
uint64_t code,
- char *auth_command,
const void *data,
size_t data_length)
{
+ struct SMS_Context *ctx = cls;
struct ANASTASIS_AUTHORIZATION_State *as;
as = GNUNET_new (struct ANASTASIS_AUTHORIZATION_State);
- as->cls = cls;
- as->truth_public_key = truth_public_key;
+ as->ctx = ctx;
+ as->truth_public_key = *truth_public_key;
as->code = code;
- as->auth_command = auth_command;
- as->phone_number = GNUNET_STRINGS_data_to_string_alloc (data,
- data_length);
+ as->phone_number = GNUNET_strndup (data,
+ data_length);
return as;
}
+/**
+ * Function called when our SMS helper has terminated.
+ *
+ * @param cls our `struct ANASTASIS_AUHTORIZATION_State`
+ * @param type type of the process
+ * @param exit_code status code of the process
+ */
+static void
+sms_done_cb (void *cls,
+ enum GNUNET_OS_ProcessStatusType type,
+ long unsigned int exit_code)
+{
+ struct ANASTASIS_AUTHORIZATION_State *as = cls;
+
+ as->child = NULL;
+ as->cwh = NULL;
+ as->pst = type;
+ as->exit_code = exit_code;
+ MHD_resume_connection (as->connection);
+ AH_trigger_daemon (); // FIXME: unclean, linker issue => change API to get a
callback?
+}
+
+
/**
* Begin issuing authentication challenge to user based on @a data.
* I.e. start to send SMS or e-mail or launch video identification.
@@ -158,40 +225,153 @@ sms_process (struct ANASTASIS_AUTHORIZATION_State *as,
struct MHD_Connection *connection)
{
MHD_RESULT mres;
- struct MHD_Response *resp;
- int p[2];
- /*FIXME ERROR HANDLING*/
- int ret = pipe (p);
- pid_t pid = fork ();
- switch (pid)
+
+ if (NULL == as->msg)
{
- case -1:
- close (p[0]);
- close (p[1]);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Error while trying to send email");
- resp = TALER_MHD_make_error (TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
- "Failed to fork process");
- mres = MHD_queue_response (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- resp);
- MHD_destroy_response (resp);
+ /* First time, start child process and feed pipe */
+ struct GNUNET_DISK_PipeHandle *p;
+ struct GNUNET_DISK_FileHandle *pipe_stdin;
+
+ p = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW);
+ if (NULL == p)
+ {
+ mres = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+
TALER_EC_ANASTASIS_SMS_HELPER_EXEC_FAILED,
+ "pipe");
+ if (MHD_YES != mres)
+ return ANASTASIS_AUTHORIZATION_RES_FAILED_REPLY_FAILED;
+ return ANASTASIS_AUTHORIZATION_RES_FAILED;
+ }
+ as->child = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ERR,
+ p,
+ NULL,
+ NULL,
+ as->ctx->auth_command,
+ as->ctx->auth_command,
+ as->phone_number,
+ NULL);
+ if (NULL == as->child)
+ {
+ GNUNET_DISK_pipe_close (p);
+ mres = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+
TALER_EC_ANASTASIS_SMS_HELPER_EXEC_FAILED,
+ "exec");
+ if (MHD_YES != mres)
+ return ANASTASIS_AUTHORIZATION_RES_FAILED_REPLY_FAILED;
+ return ANASTASIS_AUTHORIZATION_RES_FAILED;
+ }
+ pipe_stdin = GNUNET_DISK_pipe_detach_end (p,
+ GNUNET_DISK_PIPE_END_WRITE);
+ GNUNET_assert (NULL != pipe_stdin);
+ GNUNET_DISK_pipe_close (p);
+ {
+ char *tpk;
+
+ tpk = GNUNET_STRINGS_data_to_string_alloc (
+ &as->truth_public_key,
+ sizeof (as->truth_public_key));
+ GNUNET_asprintf (&as->msg,
+ "#%llu\nAnastasis\n%s",
+ (unsigned long long) as->code,
+ tpk);
+ GNUNET_free (tpk);
+ }
+
+ {
+ const char *off = as->msg;
+ size_t left = strlen (off);
+
+ while (0 != left)
+ {
+ ssize_t ret;
+
+ if (0 == left)
+ break;
+ ret = GNUNET_DISK_file_write (pipe_stdin,
+ off,
+ left);
+ if (ret <= 0)
+ {
+ mres = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+
TALER_EC_ANASTASIS_SMS_HELPER_EXEC_FAILED,
+ "write");
+ if (MHD_YES != mres)
+ return ANASTASIS_AUTHORIZATION_RES_FAILED_REPLY_FAILED;
+ return ANASTASIS_AUTHORIZATION_RES_FAILED;
+ }
+ as->msg_off += ret;
+ off += ret;
+ left -= ret;
+ }
+ GNUNET_DISK_file_close (pipe_stdin);
+ }
+ as->cwh = ANASTASIS_wait_child (as->child,
+ &sms_done_cb,
+ as);
+ as->connection = connection;
+ MHD_suspend_connection (connection);
+ return ANASTASIS_AUTHORIZATION_RES_SUSPENDED;
+ }
+ if (NULL != as->cwh)
+ {
+ /* Spurious call, why are we here? */
+ GNUNET_break (0);
+ MHD_suspend_connection (connection);
+ return ANASTASIS_AUTHORIZATION_RES_SUSPENDED;
+ }
+ if ( (GNUNET_OS_PROCESS_EXITED != as->pst) ||
+ (0 != as->exit_code) )
+ {
+ char es[32];
+
+ GNUNET_snprintf (es,
+ sizeof (es),
+ "%u/%d",
+ (unsigned int) as->exit_code,
+ as->pst);
+ mres = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+
TALER_EC_ANASTASIS_SMS_HELPER_COMMAND_FAILED,
+ es);
if (MHD_YES != mres)
return ANASTASIS_AUTHORIZATION_RES_FAILED_REPLY_FAILED;
return ANASTASIS_AUTHORIZATION_RES_FAILED;
- case 0:
- dup2 (p[0],0);
- close (p[1]);
- char buff[21];
- sprintf (buff, "%lu", as->code);
- execlp (as->auth_command, buff, as->phone_number, NULL);
- close (p[0]);
- close (p[1]);
- break;
- default:
- /*FIXME */
- break;
}
+
+ /* Build HTTP response */
+ {
+ struct MHD_Response *resp;
+ size_t reply_len;
+ char *reply;
+ const char *end;
+ size_t slen;
+
+ /* FIXME: i18n based on language preferences of the client */
+ /* FIXME: Reply in JSON if requested by client */
+ slen = strlen (as->phone_number);
+ if (slen > 4)
+ end = &as->phone_number[slen - 4];
+ else
+ end = &as->phone_number[slen / 2];
+ reply_len = GNUNET_asprintf (&reply,
+ "Recovery TAN send to phone number ending
with %s",
+ end);
+ resp = MHD_create_response_from_buffer (reply_len,
+ reply,
+ MHD_RESPMEM_MUST_COPY);
+ GNUNET_free (reply);
+ TALER_MHD_add_global_headers (resp);
+ mres = MHD_queue_response (connection,
+ MHD_HTTP_OK,
+ resp);
+ MHD_destroy_response (resp);
+ }
+
+ if (MHD_YES != mres)
+ return ANASTASIS_AUTHORIZATION_RES_SUCCESS_REPLY_FAILED;
return ANASTASIS_AUTHORIZATION_RES_SUCCESS;
}
@@ -204,6 +384,20 @@ sms_process (struct ANASTASIS_AUTHORIZATION_State *as,
static void
sms_cleanup (struct ANASTASIS_AUTHORIZATION_State *as)
{
+ if (NULL != as->cwh)
+ {
+ ANASTASIS_wait_child_cancel (as->cwh);
+ as->cwh = NULL;
+ }
+ if (NULL != as->child)
+ {
+ (void) GNUNET_OS_process_kill (as->child,
+ SIGKILL);
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_OS_process_wait (as->child));
+ as->child = NULL;
+ }
+ GNUNET_free (as->msg);
GNUNET_free (as->phone_number);
GNUNET_free (as);
}
@@ -220,7 +414,25 @@ libanastasis_plugin_authorization_sms_init (void *cls)
{
struct ANASTASIS_AuthorizationPlugin *plugin;
struct GNUNET_CONFIGURATION_Handle *cfg = cls;
+ struct SMS_Context *ctx;
+
+ ctx = GNUNET_new (struct SMS_Context);
+ {
+ int regex_result;
+ const char *regexp = "^+?[0-9]+$";
+
+ regex_result = regcomp (&ctx->regex,
+ regexp,
+ REG_EXTENDED);
+ if (0 < regex_result)
+ {
+ GNUNET_break (0);
+ GNUNET_free (ctx);
+ return NULL;
+ }
+ }
plugin = GNUNET_new (struct ANASTASIS_AuthorizationPlugin);
+ plugin->cls = ctx;
plugin->validate = &sms_validate;
plugin->start = &sms_start;
plugin->process = &sms_process;
@@ -230,11 +442,12 @@ libanastasis_plugin_authorization_sms_init (void *cls)
GNUNET_CONFIGURATION_get_value_string (cfg,
"authorization-sms",
"SMSAUTH_COMMAND",
- &plugin->auth_command))
+ &ctx->auth_command))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"authorization-sms",
"SMSAUTH_COMMAND");
+ GNUNET_free (ctx);
GNUNET_free (plugin);
return NULL;
}
@@ -252,6 +465,11 @@ void *
libanastasis_plugin_authorization_email_done (void *cls)
{
struct ANASTASIS_AuthorizationPlugin *plugin = cls;
+ struct SMS_Context *ctx = plugin->cls;
+
+ GNUNET_free (ctx->auth_command);
+ regfree (&ctx->regex);
+ GNUNET_free (ctx);
GNUNET_free (plugin);
return NULL;
}
diff --git a/src/include/anastasis_authorization_lib.h
b/src/include/anastasis_authorization_lib.h
index efb6b92..80740be 100644
--- a/src/include/anastasis_authorization_lib.h
+++ b/src/include/anastasis_authorization_lib.h
@@ -26,23 +26,20 @@
#include "anastasis_authorization_plugin.h"
/**
- * Initialize the plugin.
+ * Load authorization plugin.
*
- * @param cfg configuration to use
- * @return NULL on failure
+ * @param method name of the method to load
+ * @param AH_cfg configuration to use
+ * @param[out] set to the cost for using the plugin during recovery
+ * @return #GNUNET_OK on success
*/
struct ANASTASIS_AuthorizationPlugin *
-ANASTASIS_authorization_plugin_load (const char *method);
+ANASTASIS_authorization_plugin_load (
+ const char *method,
+ const struct GNUNET_CONFIGURATION_Handle *AH_cfg,
+ struct TALER_Amount *cost);
-/**
- * unload a plugin.
- *
- * @param plugin plugin to unload
- */
-void
-ANASTASIS_authorization_plugin_unload (struct ANASTASIS_DatabasePlugin
*plugin);
-
/**
* shutdown all loaded plugins.
*
diff --git a/src/include/anastasis_authorization_plugin.h
b/src/include/anastasis_authorization_plugin.h
index c0dffbd..7a69dc1 100644
--- a/src/include/anastasis_authorization_plugin.h
+++ b/src/include/anastasis_authorization_plugin.h
@@ -110,12 +110,6 @@ struct ANASTASIS_AuthorizationPlugin
*/
struct GNUNET_TIME_Relative code_retransmission_frequency;
- /**
- * Command which is executed to run the plugin (some bash script or a
- * command line argument)
- */
- char *auth_command;
-
/**
* Validate @a data is a well-formed input into the challenge method,
* i.e. @a data is a well-formed phone number for sending an SMS, or
@@ -158,7 +152,6 @@ struct ANASTASIS_AuthorizationPlugin
(*start)(void *cls,
const struct ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
uint64_t code,
- char *auth_command,
const void *data,
size_t data_length);
diff --git a/src/include/anastasis_util_lib.h b/src/include/anastasis_util_lib.h
index 35ad8e3..3cfb7a7 100644
--- a/src/include/anastasis_util_lib.h
+++ b/src/include/anastasis_util_lib.h
@@ -43,7 +43,7 @@ struct ANASTASIS_ChildWaitHandle;
/**
* Defines a ANASTASIS_ChildCompletedCallback which is sent back
- * upon death or complettion of a child process. Used to trigger
+ * upon death or completion of a child process. Used to trigger
* authentication commands.
*
* @param cls handle for the callback
@@ -55,6 +55,8 @@ typedef void
(*ANASTASIS_ChildCompletedCallback)(void *cls,
enum GNUNET_OS_ProcessStatusType type,
long unsigned int exit_code);
+
+
/**
* Starts the handling of the child processes.
* Function checks the status of the child process and sends back a
@@ -70,6 +72,9 @@ ANASTASIS_wait_child (struct GNUNET_OS_Process *proc,
ANASTASIS_ChildCompletedCallback cb,
void *cb_cls);
+/**
+ * Stop waiting on this child.
+ */
void
ANASTASIS_wait_child_cancel (struct ANASTASIS_ChildWaitHandle *cwh);
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [taler-anastasis] branch master updated: first rough pass over backend,
gnunet <=