summaryrefslogtreecommitdiff
path: root/src/exchange
diff options
context:
space:
mode:
Diffstat (limited to 'src/exchange')
-rw-r--r--src/exchange/exchange.conf9
-rw-r--r--src/exchange/taler-exchange-aggregator.c104
-rw-r--r--src/exchange/taler-exchange-closer.c21
-rw-r--r--src/exchange/taler-exchange-httpd.c58
-rw-r--r--src/exchange/taler-exchange-httpd.h7
-rw-r--r--src/exchange/taler-exchange-httpd_auditors.c6
-rw-r--r--src/exchange/taler-exchange-httpd_auditors.h2
-rw-r--r--src/exchange/taler-exchange-httpd_db.c2
-rw-r--r--src/exchange/taler-exchange-httpd_deposit.c140
-rw-r--r--src/exchange/taler-exchange-httpd_deposits_get.c4
-rw-r--r--src/exchange/taler-exchange-httpd_keys.c239
-rw-r--r--src/exchange/taler-exchange-httpd_keys.h24
-rw-r--r--src/exchange/taler-exchange-httpd_kyc-check.c419
-rw-r--r--src/exchange/taler-exchange-httpd_kyc-check.h7
-rw-r--r--src/exchange/taler-exchange-httpd_kyc-proof.c345
-rw-r--r--src/exchange/taler-exchange-httpd_kyc-wallet.c1
-rw-r--r--src/exchange/taler-exchange-httpd_link.c8
-rw-r--r--src/exchange/taler-exchange-httpd_management.h2
-rw-r--r--src/exchange/taler-exchange-httpd_management_denominations_HDP_revoke.c2
-rw-r--r--src/exchange/taler-exchange-httpd_management_post_keys.c128
-rw-r--r--src/exchange/taler-exchange-httpd_melt.c6
-rw-r--r--src/exchange/taler-exchange-httpd_recoup.c71
-rw-r--r--src/exchange/taler-exchange-httpd_refreshes_reveal.c28
-rw-r--r--src/exchange/taler-exchange-httpd_refund.c2
-rw-r--r--src/exchange/taler-exchange-httpd_reserves_get.c3
-rw-r--r--src/exchange/taler-exchange-httpd_responses.c46
-rw-r--r--src/exchange/taler-exchange-httpd_responses.h4
-rw-r--r--src/exchange/taler-exchange-httpd_transfers_get.c87
-rw-r--r--src/exchange/taler-exchange-httpd_wire.c6
-rw-r--r--src/exchange/taler-exchange-httpd_withdraw.c52
30 files changed, 1221 insertions, 612 deletions
diff --git a/src/exchange/exchange.conf b/src/exchange/exchange.conf
index 3bcea08f..4d353ace 100644
--- a/src/exchange/exchange.conf
+++ b/src/exchange/exchange.conf
@@ -90,13 +90,18 @@ KYC_MODE = NONE
# Balance threshold above which wallets are told
# to undergo a KYC check at the exchange. Optional,
# if not given there is no limit.
-# KYC_WALLET_BALANCE_LIMIT = 150:CURRENCY
+# KYC_WALLET_BALANCE_LIMIT = CURRENCY:150
+#
+# KYC_WITHDRAW_PERIOD = 1 month
[exchange-kyc-oauth2]
# URL of the OAuth endpoint for KYC checks
# KYC_OAUTH2_URL =
+# URL of the "information" endpoint for KYC checks
+# KYC_INFO_URL =
+
# KYC Oauth client ID.
# KYC_OAUTH2_CLIENT_ID =
@@ -105,4 +110,4 @@ KYC_MODE = NONE
# Where to redirect clients after successful
# authorization?
-# KYC_OAUTH_POST_URL = https://bank.com/
+# KYC_OAUTH2_POST_URL = https://bank.com/
diff --git a/src/exchange/taler-exchange-aggregator.c b/src/exchange/taler-exchange-aggregator.c
index afedd7e3..73bbcc59 100644
--- a/src/exchange/taler-exchange-aggregator.c
+++ b/src/exchange/taler-exchange-aggregator.c
@@ -58,11 +58,6 @@ struct AggregationUnit
struct TALER_Amount wire_fee;
/**
- * Hash of @e wire.
- */
- struct GNUNET_HashCode h_wire;
-
- /**
* Wire transfer identifier we use.
*/
struct TALER_WireTransferIdentifierRawP wtid;
@@ -81,7 +76,12 @@ struct AggregationUnit
/**
* Wire details of the merchant.
*/
- json_t *wire;
+ char *payto_uri;
+
+ /**
+ * Selected wire target for the aggregation.
+ */
+ uint64_t wire_target;
/**
* Exchange wire account to be used for the preparation and
@@ -150,6 +150,13 @@ static struct TALER_Amount currency_round_unit;
static char *exchange_base_url;
/**
+ * Set to #GNUNET_YES if this exchange does not support KYC checks
+ * and thus deposits are to be aggregated regardless of the
+ * KYC status of the target account.
+ */
+static int kyc_off;
+
+/**
* The exchange's configuration.
*/
static const struct GNUNET_CONFIGURATION_Handle *cfg;
@@ -216,8 +223,7 @@ static void
cleanup_au (struct AggregationUnit *au)
{
GNUNET_assert (NULL != au);
- if (NULL != au->wire)
- json_decref (au->wire);
+ GNUNET_free (au->payto_uri);
memset (au,
0,
sizeof (*au));
@@ -320,7 +326,7 @@ parse_wirewatch_config (void)
* @param amount_with_fee what was the refunded amount with the fee
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
*/
-static int
+static enum GNUNET_GenericReturnValue
refund_by_coin_cb (void *cls,
const struct TALER_Amount *amount_with_fee)
{
@@ -353,7 +359,8 @@ refund_by_coin_cb (void *cls,
* @param amount_with_fee amount that was deposited including fee
* @param deposit_fee amount the exchange gets to keep as transaction fees
* @param h_contract_terms hash of the proposal data known to merchant and customer
- * @param wire target account for the wire transfer
+ * @param wire_target target account for the wire transfer
+ * @param payto_uri URI of the target account
* @return transaction status code, #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT to continue to iterate
*/
static enum GNUNET_DB_QueryStatus
@@ -363,8 +370,9 @@ deposit_cb (void *cls,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_Amount *amount_with_fee,
const struct TALER_Amount *deposit_fee,
- const struct GNUNET_HashCode *h_contract_terms,
- const json_t *wire)
+ const struct TALER_PrivateContractHash *h_contract_terms,
+ uint64_t wire_target,
+ const char *payto_uri)
{
struct AggregationUnit *au = cls;
enum GNUNET_DB_QueryStatus qs;
@@ -416,21 +424,9 @@ deposit_cb (void *cls,
}
}
- GNUNET_assert (NULL == au->wire);
- if (NULL == (au->wire = json_incref ((json_t *) wire)))
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- if (GNUNET_OK !=
- TALER_JSON_merchant_wire_signature_hash (wire,
- &au->h_wire))
- {
- GNUNET_break (0);
- json_decref (au->wire);
- au->wire = NULL;
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
+ GNUNET_assert (NULL == au->payto_uri);
+ au->payto_uri = GNUNET_strdup (payto_uri);
+ au->wire_target = wire_target;
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
&au->wtid,
sizeof (au->wtid));
@@ -439,20 +435,13 @@ deposit_cb (void *cls,
TALER_B2S (&au->wtid),
TALER_amount2s (amount_with_fee),
(unsigned long long) row_id);
+ au->wa = TALER_EXCHANGEDB_find_account_by_payto_uri (payto_uri);
+ if (NULL == au->wa)
{
- char *url;
-
- url = TALER_JSON_wire_to_payto (au->wire);
- au->wa = TALER_EXCHANGEDB_find_account_by_payto_uri (url);
- if (NULL == au->wa)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "No exchange account configured for `%s', please fix your setup to continue!\n",
- url);
- GNUNET_free (url);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- GNUNET_free (url);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "No exchange account configured for `%s', please fix your setup to continue!\n",
+ payto_uri);
+ return GNUNET_DB_STATUS_HARD_ERROR;
}
/* make sure we have current fees */
@@ -528,7 +517,7 @@ aggregate_cb (void *cls,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_Amount *amount_with_fee,
const struct TALER_Amount *deposit_fee,
- const struct GNUNET_HashCode *h_contract_terms)
+ const struct TALER_PrivateContractHash *h_contract_terms)
{
struct AggregationUnit *au = cls;
struct TALER_Amount old;
@@ -724,6 +713,7 @@ run_aggregation (void *cls)
db_plugin->cls,
s->shard_start,
s->shard_end,
+ kyc_off ? true : false,
&deposit_cb,
&au_active);
switch (qs)
@@ -786,10 +776,11 @@ run_aggregation (void *cls)
/* Now try to find other deposits to aggregate */
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Found ready deposit for %s, aggregating\n",
- TALER_B2S (&au_active.merchant_pub));
+ "Found ready deposit for %s, aggregating by target %llu\n",
+ TALER_B2S (&au_active.merchant_pub),
+ (unsigned long long) au_active.wire_target);
qs = db_plugin->iterate_matching_deposits (db_plugin->cls,
- &au_active.h_wire,
+ au_active.wire_target,
&au_active.merchant_pub,
&aggregate_cb,
&au_active,
@@ -908,19 +899,12 @@ run_aggregation (void *cls)
void *buf;
size_t buf_size;
- {
- char *url;
-
- url = TALER_JSON_wire_to_payto (au_active.wire);
- TALER_BANK_prepare_transfer (url,
- &au_active.final_amount,
- exchange_base_url,
- &au_active.wtid,
- &buf,
- &buf_size);
- GNUNET_free (url);
- }
-
+ TALER_BANK_prepare_transfer (au_active.payto_uri,
+ &au_active.final_amount,
+ exchange_base_url,
+ &au_active.wtid,
+ &buf,
+ &buf_size);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Storing %u bytes of wire prepare data\n",
(unsigned int) buf_size);
@@ -937,7 +921,7 @@ run_aggregation (void *cls)
qs = db_plugin->store_wire_transfer_out (db_plugin->cls,
au_active.execution_time,
&au_active.wtid,
- au_active.wire,
+ au_active.wire_target,
au_active.wa->section_name,
&au_active.final_amount);
cleanup_au (&au_active);
@@ -1130,6 +1114,10 @@ main (int argc,
"test",
"run in test mode and exit when idle",
&test_mode),
+ GNUNET_GETOPT_option_flag ('y',
+ "kyc-off",
+ "perform wire transfers without KYC checks",
+ &kyc_off),
GNUNET_GETOPT_OPTION_END
};
enum GNUNET_GenericReturnValue ret;
diff --git a/src/exchange/taler-exchange-closer.c b/src/exchange/taler-exchange-closer.c
index 91ececc8..3f30db7b 100644
--- a/src/exchange/taler-exchange-closer.c
+++ b/src/exchange/taler-exchange-closer.c
@@ -217,7 +217,7 @@ expired_reserve_cb (void *cls,
struct TALER_WireTransferIdentifierRawP wtid;
struct TALER_Amount amount_without_fee;
struct TALER_Amount closing_fee;
- int ret;
+ enum TALER_AmountArithmeticResult ret;
enum GNUNET_DB_QueryStatus qs;
const struct TALER_EXCHANGEDB_AccountInfo *wa;
@@ -273,8 +273,8 @@ expired_reserve_cb (void *cls,
ret = TALER_amount_subtract (&amount_without_fee,
left,
&closing_fee);
- if ( (GNUNET_SYSERR == ret) ||
- (GNUNET_NO == ret) )
+ if ( (TALER_AAR_INVALID_NEGATIVE_RESULT == ret) ||
+ (TALER_AAR_RESULT_ZERO == ret) )
{
/* Closing fee higher than or equal to remaining balance, close
without wire transfer. */
@@ -283,6 +283,7 @@ expired_reserve_cb (void *cls,
TALER_amount_set_zero (left->currency,
&amount_without_fee));
}
+ GNUNET_assert (TALER_AAR_RESULT_POSITIVE == ret);
/* round down to enable transfer */
if (GNUNET_SYSERR ==
TALER_amount_round_down (&amount_without_fee,
@@ -293,10 +294,6 @@ expired_reserve_cb (void *cls,
GNUNET_SCHEDULER_shutdown ();
return GNUNET_DB_STATUS_HARD_ERROR;
}
- if ( (0 == amount_without_fee.value) &&
- (0 == amount_without_fee.fraction) )
- ret = GNUNET_NO;
-
/* NOTE: sizeof (*reserve_pub) == sizeof (wtid) right now, but to
be future-compatible, we use the memset + min construction */
memset (&wtid,
@@ -306,7 +303,7 @@ expired_reserve_cb (void *cls,
reserve_pub,
GNUNET_MIN (sizeof (wtid),
sizeof (*reserve_pub)));
- if (GNUNET_SYSERR != ret)
+ if (TALER_AAR_INVALID_NEGATIVE_RESULT != ret)
qs = db_plugin->insert_reserve_closed (db_plugin->cls,
reserve_pub,
now,
@@ -320,10 +317,10 @@ expired_reserve_cb (void *cls,
"Closing reserve %s over %s (%d, %d)\n",
TALER_B2S (reserve_pub),
TALER_amount2s (left),
- ret,
+ (int) ret,
qs);
/* Check for hard failure */
- if ( (GNUNET_SYSERR == ret) ||
+ if ( (TALER_AAR_INVALID_NEGATIVE_RESULT == ret) ||
(GNUNET_DB_STATUS_HARD_ERROR == qs) )
{
GNUNET_break (0);
@@ -331,10 +328,10 @@ expired_reserve_cb (void *cls,
GNUNET_SCHEDULER_shutdown ();
return GNUNET_DB_STATUS_HARD_ERROR;
}
- if ( (GNUNET_OK != ret) ||
+ if ( (TALER_AAR_RESULT_ZERO == ret) ||
(GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) )
{
- /* Reserve balance was almost zero OR soft error */
+ /* Reserve balance was zero OR soft error */
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Reserve was virtually empty, moving on\n");
(void) commit_or_warn ();
diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c
index 1feede1a..0a8798ae 100644
--- a/src/exchange/taler-exchange-httpd.c
+++ b/src/exchange/taler-exchange-httpd.c
@@ -67,6 +67,11 @@
int TEH_allow_keys_timetravel;
/**
+ * Should we allow two HTTPDs to bind to the same port?
+ */
+static int allow_address_reuse;
+
+/**
* The exchange's configuration (global)
*/
const struct GNUNET_CONFIGURATION_Handle *TEH_cfg;
@@ -285,8 +290,10 @@ handle_mhd_completion_callback (void *cls,
return;
GNUNET_async_scope_enter (&rc->async_scope_id,
&old_scope);
+ TEH_check_invariants ();
if (NULL != rc->rh_cleaner)
rc->rh_cleaner (rc);
+ TEH_check_invariants ();
{
#if MHD_VERSION >= 0x00097304
const union MHD_ConnectionInfo *ci;
@@ -467,6 +474,7 @@ handler_seed (struct TEH_RequestContext *rc,
MHD_RESULT ret;
struct MHD_Response *resp;
+ (void) args;
body = malloc (SEED_SIZE); /* must use malloc(), because MHD will use free() */
if (NULL == body)
return MHD_NO;
@@ -540,7 +548,7 @@ handle_post_management (struct TEH_RequestContext *rc,
if (0 == strcmp (args[0],
"denominations"))
{
- struct GNUNET_HashCode h_denom_pub;
+ struct TALER_DenominationHash h_denom_pub;
if ( (NULL == args[0]) ||
(NULL == args[1]) ||
@@ -646,12 +654,12 @@ handle_post_management (struct TEH_RequestContext *rc,
* Handle a get "/management" request.
*
* @param rc request context
- * @param args array of additional options (must be empty for this function)
+ * @param args array of additional options (must be [0] == "keys")
* @return MHD result code
*/
static MHD_RESULT
handle_get_management (struct TEH_RequestContext *rc,
- const char *const args[1])
+ const char *const args[2])
{
if ( (NULL != args[0]) &&
(0 == strcmp (args[0],
@@ -681,7 +689,7 @@ handle_post_auditors (struct TEH_RequestContext *rc,
const char *const args[])
{
struct TALER_AuditorPublicKeyP auditor_pub;
- struct GNUNET_HashCode h_denom_pub;
+ struct TALER_DenominationHash h_denom_pub;
if ( (NULL == args[0]) ||
(NULL == args[1]) ||
@@ -925,6 +933,7 @@ handle_mhd_request (void *cls,
/* We're in a new async scope! */
rc = *con_cls = GNUNET_new (struct TEH_RequestContext);
GNUNET_async_scope_fresh (&rc->async_scope_id);
+ TEH_check_invariants ();
rc->url = url;
rc->connection = connection;
/* We only read the correlation ID on the first callback for every client */
@@ -943,6 +952,7 @@ handle_mhd_request (void *cls,
GNUNET_async_scope_enter (&rc->async_scope_id,
&old_scope);
+ TEH_check_invariants ();
if (NULL != correlation_id)
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Handling request (%s) for URL '%s', correlation_id=%s\n",
@@ -1197,6 +1207,34 @@ parse_kyc_oauth_cfg (void)
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
"exchange-kyc-oauth2",
+ "KYC_INFO_URL",
+ &s))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "exchange-kyc-oauth2",
+ "KYC_INFO_URL");
+ return GNUNET_SYSERR;
+ }
+ if ( (! TALER_url_valid_charset (s)) ||
+ ( (0 != strncasecmp (s,
+ "http://",
+ strlen ("http://"))) &&
+ (0 != strncasecmp (s,
+ "https://",
+ strlen ("https://"))) ) )
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ "exchange-kyc-oauth2",
+ "KYC_INFO_URL",
+ "not a valid URL");
+ GNUNET_free (s);
+ return GNUNET_SYSERR;
+ }
+ TEH_kyc_config.details.oauth2.info_url = s;
+
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
+ "exchange-kyc-oauth2",
"KYC_OAUTH2_CLIENT_ID",
&s))
{
@@ -1642,6 +1680,7 @@ do_shutdown (void *cls)
mhd = TALER_MHD_daemon_stop ();
TEH_resume_keys_requests (true);
TEH_reserves_get_cleanup ();
+ TEH_kyc_check_cleanup ();
TEH_kyc_proof_cleanup ();
if (NULL != mhd)
MHD_stop_daemon (mhd);
@@ -1683,6 +1722,9 @@ run (void *cls,
enum TALER_MHD_GlobalOptions go;
int fh;
+ (void) cls;
+ (void) args;
+ (void ) cfgfile;
go = TALER_MHD_GO_NONE;
if (connection_close)
go |= TALER_MHD_GO_FORCE_CONNECTION_CLOSE;
@@ -1766,6 +1808,10 @@ run (void *cls,
NULL,
MHD_OPTION_CONNECTION_TIMEOUT,
connection_timeout,
+ (0 == allow_address_reuse)
+ ? MHD_OPTION_END
+ : MHD_OPTION_LISTENING_ADDRESS_REUSE,
+ (unsigned int) allow_address_reuse,
MHD_OPTION_END);
if (NULL == mhd)
{
@@ -1806,6 +1852,10 @@ main (int argc,
"connection-close",
"force HTTP connections to be closed after each request",
&connection_close),
+ GNUNET_GETOPT_option_flag ('r',
+ "allow-reuse-address",
+ "allow multiple HTTPDs to listen to the same port",
+ &allow_address_reuse),
GNUNET_GETOPT_option_uint ('t',
"timeout",
"SECONDS",
diff --git a/src/exchange/taler-exchange-httpd.h b/src/exchange/taler-exchange-httpd.h
index f66626b3..d52ce1a0 100644
--- a/src/exchange/taler-exchange-httpd.h
+++ b/src/exchange/taler-exchange-httpd.h
@@ -91,11 +91,16 @@ struct TEH_KycOptions
{
/**
- * URL of tue OAuth2.0 endpoint for KYC checks.
+ * URL of the OAuth2.0 endpoint for KYC checks.
*/
char *url;
/**
+ * URL of the user info access endpoint.
+ */
+ char *info_url;
+
+ /**
* Our client ID for OAuth2.0.
*/
char *client_id;
diff --git a/src/exchange/taler-exchange-httpd_auditors.c b/src/exchange/taler-exchange-httpd_auditors.c
index 34e640ad..bf4a9b2c 100644
--- a/src/exchange/taler-exchange-httpd_auditors.c
+++ b/src/exchange/taler-exchange-httpd_auditors.c
@@ -45,7 +45,7 @@ struct AddAuditorDenomContext
/**
* Denomination this is about.
*/
- const struct GNUNET_HashCode *h_denom_pub;
+ const struct TALER_DenominationHash *h_denom_pub;
/**
* Auditor this is about.
@@ -101,7 +101,7 @@ add_auditor_denom_sig (void *cls,
connection,
MHD_HTTP_NOT_FOUND,
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN,
- GNUNET_h2s (awc->h_denom_pub));
+ GNUNET_h2s (&awc->h_denom_pub->hash));
return GNUNET_DB_STATUS_HARD_ERROR;
}
@@ -192,7 +192,7 @@ MHD_RESULT
TEH_handler_auditors (
struct MHD_Connection *connection,
const struct TALER_AuditorPublicKeyP *auditor_pub,
- const struct GNUNET_HashCode *h_denom_pub,
+ const struct TALER_DenominationHash *h_denom_pub,
const json_t *root)
{
struct AddAuditorDenomContext awc = {
diff --git a/src/exchange/taler-exchange-httpd_auditors.h b/src/exchange/taler-exchange-httpd_auditors.h
index f8191f8a..00a2e57a 100644
--- a/src/exchange/taler-exchange-httpd_auditors.h
+++ b/src/exchange/taler-exchange-httpd_auditors.h
@@ -39,7 +39,7 @@ MHD_RESULT
TEH_handler_auditors (
struct MHD_Connection *connection,
const struct TALER_AuditorPublicKeyP *auditor_pub,
- const struct GNUNET_HashCode *h_denom_pub,
+ const struct TALER_DenominationHash *h_denom_pub,
const json_t *root);
diff --git a/src/exchange/taler-exchange-httpd_db.c b/src/exchange/taler-exchange-httpd_db.c
index 3c693649..1d78fb8e 100644
--- a/src/exchange/taler-exchange-httpd_db.c
+++ b/src/exchange/taler-exchange-httpd_db.c
@@ -182,7 +182,7 @@ TEH_DB_run_transaction (struct MHD_Connection *connection,
}
/* make sure callback did not violate invariants! */
GNUNET_assert ( (NULL == mhd_ret) ||
- (-1 == *mhd_ret) );
+ (-1 == (int) *mhd_ret) );
if (0 <= qs)
return GNUNET_OK;
}
diff --git a/src/exchange/taler-exchange-httpd_deposit.c b/src/exchange/taler-exchange-httpd_deposit.c
index 38dfd447..e9851de7 100644
--- a/src/exchange/taler-exchange-httpd_deposit.c
+++ b/src/exchange/taler-exchange-httpd_deposit.c
@@ -57,10 +57,12 @@
static MHD_RESULT
reply_deposit_success (struct MHD_Connection *connection,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
- const struct GNUNET_HashCode *h_wire,
- const struct GNUNET_HashCode *h_contract_terms,
+ const struct TALER_MerchantWireHash *h_wire,
+ const struct TALER_ExtensionContractHash *h_extensions,
+ const struct TALER_PrivateContractHash *h_contract_terms,
struct GNUNET_TIME_Absolute exchange_timestamp,
struct GNUNET_TIME_Absolute refund_deadline,
+ struct GNUNET_TIME_Absolute wire_deadline,
const struct TALER_MerchantPublicKeyP *merchant,
const struct TALER_Amount *amount_without_fee)
{
@@ -73,11 +75,14 @@ reply_deposit_success (struct MHD_Connection *connection,
.h_wire = *h_wire,
.exchange_timestamp = GNUNET_TIME_absolute_hton (exchange_timestamp),
.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline),
+ .wire_deadline = GNUNET_TIME_absolute_hton (wire_deadline),
.coin_pub = *coin_pub,
- .merchant = *merchant
+ .merchant_pub = *merchant
};
enum TALER_ErrorCode ec;
+ if (NULL != h_extensions)
+ dc.h_extensions = *h_extensions;
TALER_amount_hton (&dc.amount_without_fee,
amount_without_fee);
if (TALER_EC_NONE !=
@@ -117,6 +122,11 @@ struct DepositContext
struct GNUNET_TIME_Absolute exchange_timestamp;
/**
+ * Calculated hash over the wire details.
+ */
+ struct TALER_MerchantWireHash h_wire;
+
+ /**
* Value of the coin.
*/
struct TALER_Amount value;
@@ -124,7 +134,7 @@ struct DepositContext
/**
* payto:// URI of the credited account.
*/
- char *payto_uri;
+ const char *payto_uri;
};
@@ -152,7 +162,6 @@ deposit_precheck (void *cls,
qs = TEH_plugin->have_deposit (TEH_plugin->cls,
deposit,
- GNUNET_YES /* check refund deadline */,
&deposit_fee,
&dc->exchange_timestamp);
if (qs < 0)
@@ -179,10 +188,12 @@ deposit_precheck (void *cls,
&deposit_fee));
*mhd_ret = reply_deposit_success (connection,
&deposit->coin.coin_pub,
- &deposit->h_wire,
+ &dc->h_wire,
+ NULL /* h_extensions! */,
&deposit->h_contract_terms,
dc->exchange_timestamp,
deposit->refund_deadline,
+ deposit->wire_deadline,
&deposit->merchant_pub,
&amount_without_fee);
/* Treat as 'hard' DB error as we want to rollback and
@@ -318,25 +329,24 @@ TEH_handler_deposit (struct MHD_Connection *connection,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const json_t *root)
{
- json_t *wire;
struct DepositContext dc;
struct TALER_EXCHANGEDB_Deposit deposit;
- struct GNUNET_HashCode my_h_wire;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_json ("wire", &wire),
+ GNUNET_JSON_spec_string ("merchant_payto_uri",
+ &dc.payto_uri),
+ GNUNET_JSON_spec_fixed_auto ("wire_salt",
+ &deposit.wire_salt),
TALER_JSON_spec_amount ("contribution",
TEH_currency,
&deposit.amount_with_fee),
GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
&deposit.coin.denom_pub_hash),
- TALER_JSON_spec_denomination_signature ("ub_sig",
- &deposit.coin.denom_sig),
+ TALER_JSON_spec_denom_sig ("ub_sig",
+ &deposit.coin.denom_sig),
GNUNET_JSON_spec_fixed_auto ("merchant_pub",
&deposit.merchant_pub),
GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
&deposit.h_contract_terms),
- GNUNET_JSON_spec_fixed_auto ("h_wire",
- &deposit.h_wire),
GNUNET_JSON_spec_fixed_auto ("coin_sig",
&deposit.csig),
TALER_JSON_spec_absolute_time ("timestamp",
@@ -374,16 +384,6 @@ TEH_handler_deposit (struct MHD_Connection *connection,
{
char *emsg;
- dc.payto_uri = TALER_JSON_wire_to_payto (wire);
- if (NULL == dc.payto_uri)
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "wire");
- }
emsg = TALER_payto_validate (dc.payto_uri);
if (NULL != emsg)
{
@@ -396,46 +396,22 @@ TEH_handler_deposit (struct MHD_Connection *connection,
TALER_EC_GENERIC_PARAMETER_MALFORMED,
emsg);
GNUNET_free (emsg);
- GNUNET_free (dc.payto_uri);
return ret;
}
}
- deposit.receiver_wire_account = wire;
+ deposit.receiver_wire_account = (char *) dc.payto_uri;
if (deposit.refund_deadline.abs_value_us > deposit.wire_deadline.abs_value_us)
{
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
- GNUNET_free (dc.payto_uri);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_EXCHANGE_DEPOSIT_REFUND_DEADLINE_AFTER_WIRE_DEADLINE,
NULL);
}
- if (GNUNET_OK !=
- TALER_JSON_merchant_wire_signature_hash (wire,
- &my_h_wire))
- {
- TALER_LOG_WARNING (
- "Failed to parse JSON wire format specification for /deposit request\n");
- GNUNET_JSON_parse_free (spec);
- GNUNET_free (dc.payto_uri);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_EXCHANGE_DEPOSIT_INVALID_WIRE_FORMAT_JSON,
- NULL);
- }
- if (0 != GNUNET_memcmp (&deposit.h_wire,
- &my_h_wire))
- {
- /* Client hashed wire details differently than we did, reject */
- GNUNET_JSON_parse_free (spec);
- GNUNET_free (dc.payto_uri);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_EXCHANGE_DEPOSIT_INVALID_WIRE_FORMAT_CONTRACT_HASH_CONFLICT,
- NULL);
- }
-
+ TALER_merchant_wire_signature_hash (dc.payto_uri,
+ &deposit.wire_salt,
+ &dc.h_wire);
/* Check for idempotency: did we get this request before? */
dc.deposit = &deposit;
{
@@ -449,7 +425,6 @@ TEH_handler_deposit (struct MHD_Connection *connection,
&dc))
{
GNUNET_JSON_parse_free (spec);
- GNUNET_free (dc.payto_uri);
return mhd_ret;
}
}
@@ -468,7 +443,6 @@ TEH_handler_deposit (struct MHD_Connection *connection,
if (NULL == dk)
{
GNUNET_JSON_parse_free (spec);
- GNUNET_free (dc.payto_uri);
return mret;
}
if (GNUNET_TIME_absolute_is_past (dk->meta.expire_deposit))
@@ -479,7 +453,6 @@ TEH_handler_deposit (struct MHD_Connection *connection,
now = GNUNET_TIME_absolute_get ();
(void) GNUNET_TIME_round_abs (&now);
GNUNET_JSON_parse_free (spec);
- GNUNET_free (dc.payto_uri);
return TEH_RESPONSE_reply_expired_denom_pub_hash (
connection,
&deposit.coin.denom_pub_hash,
@@ -495,7 +468,6 @@ TEH_handler_deposit (struct MHD_Connection *connection,
now = GNUNET_TIME_absolute_get ();
(void) GNUNET_TIME_round_abs (&now);
GNUNET_JSON_parse_free (spec);
- GNUNET_free (dc.payto_uri);
return TEH_RESPONSE_reply_expired_denom_pub_hash (
connection,
&deposit.coin.denom_pub_hash,
@@ -511,7 +483,6 @@ TEH_handler_deposit (struct MHD_Connection *connection,
(void) GNUNET_TIME_round_abs (&now);
/* This denomination has been revoked */
GNUNET_JSON_parse_free (spec);
- GNUNET_free (dc.payto_uri);
return TEH_RESPONSE_reply_expired_denom_pub_hash (
connection,
&deposit.coin.denom_pub_hash,
@@ -528,7 +499,6 @@ TEH_handler_deposit (struct MHD_Connection *connection,
{
TALER_LOG_WARNING ("Invalid coin passed for /deposit\n");
GNUNET_JSON_parse_free (spec);
- GNUNET_free (dc.payto_uri);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_UNAUTHORIZED,
TALER_EC_EXCHANGE_DENOMINATION_SIGNATURE_INVALID,
@@ -541,45 +511,31 @@ TEH_handler_deposit (struct MHD_Connection *connection,
{
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
- GNUNET_free (dc.payto_uri);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_EXCHANGE_DEPOSIT_NEGATIVE_VALUE_AFTER_FEE,
NULL);
}
- /* check deposit signature */
+ if (GNUNET_OK !=
+ TALER_wallet_deposit_verify (&deposit.amount_with_fee,
+ &deposit.deposit_fee,
+ &dc.h_wire,
+ &deposit.h_contract_terms,
+ NULL /* h_extensions! */,
+ &deposit.coin.denom_pub_hash,
+ deposit.timestamp,
+ &deposit.merchant_pub,
+ deposit.refund_deadline,
+ &deposit.coin.coin_pub,
+ &deposit.csig))
{
- struct TALER_DepositRequestPS dr = {
- .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT),
- .purpose.size = htonl (sizeof (dr)),
- .h_contract_terms = deposit.h_contract_terms,
- .h_wire = deposit.h_wire,
- .h_denom_pub = deposit.coin.denom_pub_hash,
- .wallet_timestamp = GNUNET_TIME_absolute_hton (deposit.timestamp),
- .refund_deadline = GNUNET_TIME_absolute_hton (deposit.refund_deadline),
- .merchant = deposit.merchant_pub,
- .coin_pub = deposit.coin.coin_pub
- };
-
- TALER_amount_hton (&dr.amount_with_fee,
- &deposit.amount_with_fee);
- TALER_amount_hton (&dr.deposit_fee,
- &deposit.deposit_fee);
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_DEPOSIT,
- &dr,
- &deposit.csig.eddsa_signature,
- &deposit.coin.coin_pub.eddsa_pub))
- {
- TALER_LOG_WARNING ("Invalid signature on /deposit request\n");
- GNUNET_JSON_parse_free (spec);
- GNUNET_free (dc.payto_uri);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_UNAUTHORIZED,
- TALER_EC_EXCHANGE_DEPOSIT_COIN_SIGNATURE_INVALID,
- NULL);
- }
+ TALER_LOG_WARNING ("Invalid signature on /deposit request\n");
+ GNUNET_JSON_parse_free (spec);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_UNAUTHORIZED,
+ TALER_EC_EXCHANGE_DEPOSIT_COIN_SIGNATURE_INVALID,
+ NULL);
}
/* execute transaction */
@@ -594,11 +550,9 @@ TEH_handler_deposit (struct MHD_Connection *connection,
&dc))
{
GNUNET_JSON_parse_free (spec);
- GNUNET_free (dc.payto_uri);
return mhd_ret;
}
}
- GNUNET_free (dc.payto_uri);
/* generate regular response */
{
@@ -611,10 +565,12 @@ TEH_handler_deposit (struct MHD_Connection *connection,
&deposit.deposit_fee));
res = reply_deposit_success (connection,
&deposit.coin.coin_pub,
- &deposit.h_wire,
+ &dc.h_wire,
+ NULL /* h_extensions! */,
&deposit.h_contract_terms,
dc.exchange_timestamp,
deposit.refund_deadline,
+ deposit.wire_deadline,
&deposit.merchant_pub,
&amount_without_fee);
GNUNET_JSON_parse_free (spec);
diff --git a/src/exchange/taler-exchange-httpd_deposits_get.c b/src/exchange/taler-exchange-httpd_deposits_get.c
index 2423cc96..d981a8dd 100644
--- a/src/exchange/taler-exchange-httpd_deposits_get.c
+++ b/src/exchange/taler-exchange-httpd_deposits_get.c
@@ -47,8 +47,8 @@
*/
static MHD_RESULT
reply_deposit_details (struct MHD_Connection *connection,
- const struct GNUNET_HashCode *h_contract_terms,
- const struct GNUNET_HashCode *h_wire,
+ const struct TALER_PrivateContractHash *h_contract_terms,
+ const struct TALER_MerchantWireHash *h_wire,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_Amount *coin_contribution,
const struct TALER_WireTransferIdentifierRawP *wtid,
diff --git a/src/exchange/taler-exchange-httpd_keys.c b/src/exchange/taler-exchange-httpd_keys.c
index 70590020..5f747ccc 100644
--- a/src/exchange/taler-exchange-httpd_keys.c
+++ b/src/exchange/taler-exchange-httpd_keys.c
@@ -50,7 +50,7 @@
* #TALER_PROTOCOL_CURRENT and #TALER_PROTOCOL_AGE in
* exchange_api_handle.c!
*/
-#define EXCHANGE_PROTOCOL_VERSION "9:0:0"
+#define EXCHANGE_PROTOCOL_VERSION "10:0:0"
/**
@@ -71,9 +71,9 @@ struct HelperDenomination
struct GNUNET_TIME_Relative validity_duration;
/**
- * Hash of the denomination key.
+ * Hash of the full denomination key.
*/
- struct GNUNET_HashCode h_denom_pub;
+ struct TALER_DenominationHash h_denom_pub;
/**
* Signature over this key from the security module's key.
@@ -86,10 +86,24 @@ struct HelperDenomination
struct TALER_DenominationPublicKey denom_pub;
/**
+ * Details depend on the @e denom_pub.cipher type.
+ */
+ union
+ {
+
+ /**
+ * Hash of the RSA key.
+ */
+ struct TALER_RsaPubHashP h_rsa;
+
+ } h_details;
+
+ /**
* Name in configuration section for this denomination type.
*/
char *section_name;
+
};
@@ -167,7 +181,7 @@ struct HelperState
/**
* Handle for the denom/RSA helper.
*/
- struct TALER_CRYPTO_DenominationHelper *dh;
+ struct TALER_CRYPTO_RsaDenominationHelper *dh;
/**
* Map from H(denom_pub) to `struct HelperDenomination` entries.
@@ -175,6 +189,11 @@ struct HelperState
struct GNUNET_CONTAINER_MultiHashMap *denom_keys;
/**
+ * Map from H(rsa_pub) to `struct HelperDenomination` entries.
+ */
+ struct GNUNET_CONTAINER_MultiHashMap *rsa_keys;
+
+ /**
* Map from `struct TALER_ExchangePublicKey` to `struct HelperSignkey`
* entries. Based on the fact that a `struct GNUNET_PeerIdentity` is also
* an EdDSA public key.
@@ -442,6 +461,44 @@ suspend_request (struct MHD_Connection *connection)
}
+/**
+ * Called on each denomination key. Checks that the key still works.
+ *
+ * @param cls NULL
+ * @param hc denomination hash (unused)
+ * @param value a `struct TEH_DenominationKey`
+ * @return #GNUNET_OK
+ */
+static int
+check_dk (void *cls,
+ const struct GNUNET_HashCode *hc,
+ void *value)
+{
+ struct TEH_DenominationKey *dk = value;
+
+
+ (void) hc;
+ (void) value;
+ GNUNET_assert (TALER_DENOMINATION_INVALID != dk->denom_pub.cipher);
+ if (TALER_DENOMINATION_RSA == dk->denom_pub.cipher)
+ GNUNET_assert (GNUNET_CRYPTO_rsa_public_key_check (
+ dk->denom_pub.details.rsa_public_key));
+ return GNUNET_OK;
+}
+
+
+void
+TEH_check_invariants ()
+{
+ struct TEH_KeyStateHandle *ksh;
+
+ ksh = TEH_keys_get_state ();
+ GNUNET_CONTAINER_multihashmap_iterate (ksh->denomkey_map,
+ &check_dk,
+ NULL);
+}
+
+
void
TEH_resume_keys_requests (bool do_shutdown)
{
@@ -549,7 +606,7 @@ free_denom_cb (void *cls,
(void) cls;
(void) h_denom_pub;
- GNUNET_CRYPTO_rsa_public_key_free (hd->denom_pub.rsa_public_key);
+ TALER_denom_pub_free (&hd->denom_pub);
GNUNET_free (hd->section_name);
GNUNET_free (hd);
return GNUNET_OK;
@@ -591,6 +648,8 @@ destroy_key_helpers (struct HelperState *hs)
GNUNET_CONTAINER_multihashmap_iterate (hs->denom_keys,
&free_denom_cb,
hs);
+ GNUNET_CONTAINER_multihashmap_destroy (hs->rsa_keys);
+ hs->rsa_keys = NULL;
GNUNET_CONTAINER_multihashmap_destroy (hs->denom_keys);
hs->denom_keys = NULL;
GNUNET_CONTAINER_multipeermap_iterate (hs->esign_keys,
@@ -600,7 +659,7 @@ destroy_key_helpers (struct HelperState *hs)
hs->esign_keys = NULL;
if (NULL != hs->dh)
{
- TALER_CRYPTO_helper_denom_disconnect (hs->dh);
+ TALER_CRYPTO_helper_rsa_disconnect (hs->dh);
hs->dh = NULL;
}
if (NULL != hs->esh)
@@ -630,12 +689,12 @@ destroy_key_helpers (struct HelperState *hs)
* The signature was already verified against @a sm_pub.
*/
static void
-helper_denom_cb (
+helper_rsa_cb (
void *cls,
const char *section_name,
struct GNUNET_TIME_Absolute start_time,
struct GNUNET_TIME_Relative validity_duration,
- const struct GNUNET_HashCode *h_denom_pub,
+ const struct TALER_RsaPubHashP *h_rsa,
const struct TALER_DenominationPublicKey *denom_pub,
const struct TALER_SecurityModulePublicKeyP *sm_pub,
const struct TALER_SecurityModuleSignatureP *sm_sig)
@@ -645,14 +704,14 @@ helper_denom_cb (
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"RSA helper announces key %s for denomination type %s with validity %s\n",
- GNUNET_h2s (h_denom_pub),
+ GNUNET_h2s (&h_rsa->hash),
section_name,
GNUNET_STRINGS_relative_time_to_string (validity_duration,
GNUNET_NO));
key_generation++;
TEH_resume_keys_requests (false);
- hd = GNUNET_CONTAINER_multihashmap_get (hs->denom_keys,
- h_denom_pub);
+ hd = GNUNET_CONTAINER_multihashmap_get (hs->rsa_keys,
+ &h_rsa->hash);
if (NULL != hd)
{
/* should be just an update (revocation!), so update existing entry */
@@ -664,16 +723,34 @@ helper_denom_cb (
hd = GNUNET_new (struct HelperDenomination);
hd->start_time = start_time;
hd->validity_duration = validity_duration;
- hd->h_denom_pub = *h_denom_pub;
+ hd->h_details.h_rsa = *h_rsa;
hd->sm_sig = *sm_sig;
- hd->denom_pub.rsa_public_key
- = GNUNET_CRYPTO_rsa_public_key_dup (denom_pub->rsa_public_key);
+ GNUNET_assert (TALER_DENOMINATION_RSA == denom_pub->cipher);
+ TALER_denom_pub_deep_copy (&hd->denom_pub,
+ denom_pub);
+ GNUNET_assert (TALER_DENOMINATION_RSA == hd->denom_pub.cipher);
+ // FIXME-OEC: set AGE RESTRICTION (from 'global' variable,
+ // that itself is set from /managmenet API!) HERE!
+ // ISSUE: tricky to handle if configuration changes
+ // between denominations (some with/without age
+ // restrictions). For that, we probably need to look at
+ // configuration [$section_name] (!?).
+ hd->denom_pub.age_mask.mask = 0;
+ TALER_denom_pub_hash (&hd->denom_pub,
+ &hd->h_denom_pub);
hd->section_name = GNUNET_strdup (section_name);
GNUNET_assert (
GNUNET_OK ==
GNUNET_CONTAINER_multihashmap_put (
hs->denom_keys,
- &hd->h_denom_pub,
+ &hd->h_denom_pub.hash,
+ hd,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+ GNUNET_assert (
+ GNUNET_OK ==
+ GNUNET_CONTAINER_multihashmap_put (
+ hs->rsa_keys,
+ &hd->h_details.h_rsa.hash,
hd,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
}
@@ -721,7 +798,6 @@ helper_esign_cb (
{
/* should be just an update (revocation!), so update existing entry */
hsk->validity_duration = validity_duration;
- GNUNET_break (0 == start_time.abs_value_us);
return;
}
GNUNET_assert (NULL != sm_pub);
@@ -753,12 +829,15 @@ setup_key_helpers (struct HelperState *hs)
hs->denom_keys
= GNUNET_CONTAINER_multihashmap_create (1024,
GNUNET_YES);
+ hs->rsa_keys
+ = GNUNET_CONTAINER_multihashmap_create (1024,
+ GNUNET_YES);
hs->esign_keys
= GNUNET_CONTAINER_multipeermap_create (32,
GNUNET_NO /* MUST BE NO! */);
- hs->dh = TALER_CRYPTO_helper_denom_connect (TEH_cfg,
- &helper_denom_cb,
- hs);
+ hs->dh = TALER_CRYPTO_helper_rsa_connect (TEH_cfg,
+ &helper_rsa_cb,
+ hs);
if (NULL == hs->dh)
{
destroy_key_helpers (hs);
@@ -784,7 +863,7 @@ setup_key_helpers (struct HelperState *hs)
static void
sync_key_helpers (struct HelperState *hs)
{
- TALER_CRYPTO_helper_denom_poll (hs->dh);
+ TALER_CRYPTO_helper_rsa_poll (hs->dh);
TALER_CRYPTO_helper_esign_poll (hs->esh);
}
@@ -807,7 +886,7 @@ clear_denomination_cb (void *cls,
(void) cls;
(void) h_denom_pub;
- GNUNET_CRYPTO_rsa_public_key_free (dk->denom_pub.rsa_public_key);
+ TALER_denom_pub_free (&dk->denom_pub);
while (NULL != (as = dk->as_head))
{
GNUNET_CONTAINER_DLL_remove (dk->as_head,
@@ -894,8 +973,12 @@ keys_update_event_cb (void *cls,
(void) cls;
(void) extra;
(void) extra_size;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Received /keys update event\n");
+ TEH_check_invariants ();
key_generation++;
TEH_resume_keys_requests (false);
+ TEH_check_invariants ();
}
@@ -965,7 +1048,7 @@ static void
denomination_info_cb (
void *cls,
const struct TALER_DenominationPublicKey *denom_pub,
- const struct GNUNET_HashCode *h_denom_pub,
+ const struct TALER_DenominationHash *h_denom_pub,
const struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta,
const struct TALER_MasterSignatureP *master_sig,
bool recoup_possible)
@@ -973,6 +1056,7 @@ denomination_info_cb (
struct TEH_KeyStateHandle *ksh = cls;
struct TEH_DenominationKey *dk;
+ GNUNET_assert (TALER_DENOMINATION_INVALID != denom_pub->cipher);
if ( (0 == meta->start.abs_value_us) ||
(0 == meta->expire_withdraw.abs_value_us) ||
(0 == meta->expire_deposit.abs_value_us) ||
@@ -980,12 +1064,12 @@ denomination_info_cb (
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Database contains invalid denomination key %s\n",
- GNUNET_h2s (h_denom_pub));
+ GNUNET_h2s (&h_denom_pub->hash));
return;
}
dk = GNUNET_new (struct TEH_DenominationKey);
- dk->denom_pub.rsa_public_key
- = GNUNET_CRYPTO_rsa_public_key_dup (denom_pub->rsa_public_key);
+ TALER_denom_pub_deep_copy (&dk->denom_pub,
+ denom_pub);
dk->h_denom_pub = *h_denom_pub;
dk->meta = *meta;
dk->master_sig = *master_sig;
@@ -993,7 +1077,7 @@ denomination_info_cb (
GNUNET_assert (
GNUNET_OK ==
GNUNET_CONTAINER_multihashmap_put (ksh->denomkey_map,
- &dk->h_denom_pub,
+ &dk->h_denom_pub.hash,
dk,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
}
@@ -1139,7 +1223,7 @@ static void
auditor_denom_cb (
void *cls,
const struct TALER_AuditorPublicKeyP *auditor_pub,
- const struct GNUNET_HashCode *h_denom_pub,
+ const struct TALER_DenominationHash *h_denom_pub,
const struct TALER_AuditorSignatureP *auditor_sig)
{
struct TEH_KeyStateHandle *ksh = cls;
@@ -1147,7 +1231,7 @@ auditor_denom_cb (
struct TEH_AuditorSignature *as;
dk = GNUNET_CONTAINER_multihashmap_get (ksh->denomkey_map,
- h_denom_pub);
+ &h_denom_pub->hash);
if (NULL == dk)
{
/* Odd, this should be impossible as per foreign key
@@ -1199,6 +1283,7 @@ add_sign_key_cb (void *cls,
struct SignKeyCtx *ctx = cls;
struct SigningKey *sk = value;
+ (void) pid;
ctx->next_sk_expire =
GNUNET_TIME_absolute_min (ctx->next_sk_expire,
sk->meta.expire_sign);
@@ -1639,8 +1724,8 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
dk->meta.expire_deposit),
GNUNET_JSON_pack_time_abs ("stamp_expire_legal",
dk->meta.expire_legal),
- GNUNET_JSON_pack_rsa_public_key ("denom_pub",
- dk->denom_pub.rsa_public_key),
+ TALER_JSON_pack_denom_pub ("denom_pub",
+ &dk->denom_pub),
TALER_JSON_pack_amount ("value",
&dk->meta.value),
TALER_JSON_pack_amount ("fee_withdraw",
@@ -1875,7 +1960,7 @@ TEH_keys_get_state (void)
struct TEH_DenominationKey *
-TEH_keys_denomination_by_hash (const struct GNUNET_HashCode *h_denom_pub,
+TEH_keys_denomination_by_hash (const struct TALER_DenominationHash *h_denom_pub,
struct MHD_Connection *conn,
MHD_RESULT *mret)
{
@@ -1898,15 +1983,16 @@ TEH_keys_denomination_by_hash (const struct GNUNET_HashCode *h_denom_pub,
struct TEH_DenominationKey *
-TEH_keys_denomination_by_hash2 (struct TEH_KeyStateHandle *ksh,
- const struct GNUNET_HashCode *h_denom_pub,
- struct MHD_Connection *conn,
- MHD_RESULT *mret)
+TEH_keys_denomination_by_hash2 (
+ struct TEH_KeyStateHandle *ksh,
+ const struct TALER_DenominationHash *h_denom_pub,
+ struct MHD_Connection *conn,
+ MHD_RESULT *mret)
{
struct TEH_DenominationKey *dk;
dk = GNUNET_CONTAINER_multihashmap_get (ksh->denomkey_map,
- h_denom_pub);
+ &h_denom_pub->hash);
if (NULL == dk)
{
*mret = TEH_RESPONSE_reply_unknown_denom_pub_hash (conn,
@@ -1917,33 +2003,52 @@ TEH_keys_denomination_by_hash2 (struct TEH_KeyStateHandle *ksh,
}
-struct TALER_DenominationSignature
-TEH_keys_denomination_sign (const struct GNUNET_HashCode *h_denom_pub,
+struct TALER_BlindedDenominationSignature
+TEH_keys_denomination_sign (const struct TALER_DenominationHash *h_denom_pub,
const void *msg,
size_t msg_size,
enum TALER_ErrorCode *ec)
{
struct TEH_KeyStateHandle *ksh;
- struct TALER_DenominationSignature none = { NULL };
+ struct TALER_BlindedDenominationSignature none;
+ struct HelperDenomination *hd;
+ memset (&none,
+ 0,
+ sizeof (none));
ksh = TEH_keys_get_state ();
if (NULL == ksh)
{
*ec = TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING;
return none;
}
- return TALER_CRYPTO_helper_denom_sign (ksh->helpers->dh,
- h_denom_pub,
+ hd = GNUNET_CONTAINER_multihashmap_get (ksh->helpers->denom_keys,
+ &h_denom_pub->hash);
+ if (NULL == hd)
+ {
+ *ec = TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN;
+ return none;
+ }
+ switch (hd->denom_pub.cipher)
+ {
+ case TALER_DENOMINATION_RSA:
+ return TALER_CRYPTO_helper_rsa_sign (ksh->helpers->dh,
+ &hd->h_details.h_rsa,
msg,
msg_size,
ec);
+ default:
+ *ec = TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
+ return none;
+ }
}
void
-TEH_keys_denomination_revoke (const struct GNUNET_HashCode *h_denom_pub)
+TEH_keys_denomination_revoke (const struct TALER_DenominationHash *h_denom_pub)
{
struct TEH_KeyStateHandle *ksh;
+ struct HelperDenomination *hd;
ksh = TEH_keys_get_state ();
if (NULL == ksh)
@@ -1951,9 +2056,24 @@ TEH_keys_denomination_revoke (const struct GNUNET_HashCode *h_denom_pub)
GNUNET_break (0);
return;
}
- TALER_CRYPTO_helper_denom_revoke (ksh->helpers->dh,
- h_denom_pub);
- TEH_keys_update_states ();
+ hd = GNUNET_CONTAINER_multihashmap_get (ksh->helpers->denom_keys,
+ &h_denom_pub->hash);
+ if (NULL == hd)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ switch (hd->denom_pub.cipher)
+ {
+ case TALER_DENOMINATION_RSA:
+ TALER_CRYPTO_helper_rsa_revoke (ksh->helpers->dh,
+ &hd->h_details.h_rsa);
+ TEH_keys_update_states ();
+ return;
+ default:
+ GNUNET_break (0);
+ return;
+ }
}
@@ -2284,7 +2404,7 @@ load_fees (const char *section_name,
enum GNUNET_GenericReturnValue
-TEH_keys_load_fees (const struct GNUNET_HashCode *h_denom_pub,
+TEH_keys_load_fees (const struct TALER_DenominationHash *h_denom_pub,
struct TALER_DenominationPublicKey *denom_pub,
struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta)
{
@@ -2300,12 +2420,12 @@ TEH_keys_load_fees (const struct GNUNET_HashCode *h_denom_pub,
}
hd = GNUNET_CONTAINER_multihashmap_get (ksh->helpers->denom_keys,
- h_denom_pub);
+ &h_denom_pub->hash);
if (NULL == hd)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Denomination %s not known\n",
- GNUNET_h2s (h_denom_pub));
+ GNUNET_h2s (&h_denom_pub->hash));
return GNUNET_NO;
}
meta->start = hd->start_time;
@@ -2314,15 +2434,25 @@ TEH_keys_load_fees (const struct GNUNET_HashCode *h_denom_pub,
ok = load_fees (hd->section_name,
meta);
if (GNUNET_OK == ok)
- denom_pub->rsa_public_key
- = GNUNET_CRYPTO_rsa_public_key_dup (hd->denom_pub.rsa_public_key);
+ {
+ GNUNET_assert (TALER_DENOMINATION_INVALID != hd->denom_pub.cipher);
+ TALER_denom_pub_deep_copy (denom_pub,
+ &hd->denom_pub);
+ }
else
- denom_pub->rsa_public_key = NULL;
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "No fees for `%s', voiding key\n",
+ hd->section_name);
+ memset (denom_pub,
+ 0,
+ sizeof (*denom_pub));
+ }
return ok;
}
-int
+enum GNUNET_GenericReturnValue
TEH_keys_get_timing (const struct TALER_ExchangePublicKeyP *exchange_pub,
struct TALER_EXCHANGEDB_SignkeyMetaData *meta)
{
@@ -2424,8 +2554,8 @@ add_future_denomkey_cb (void *cls,
meta.expire_deposit),
GNUNET_JSON_pack_time_abs ("stamp_expire_legal",
meta.expire_legal),
- GNUNET_JSON_pack_rsa_public_key ("denom_pub",
- hd->denom_pub.rsa_public_key),
+ TALER_JSON_pack_denom_pub ("denom_pub",
+ &hd->denom_pub),
TALER_JSON_pack_amount ("fee_withdraw",
&meta.fee_withdraw),
TALER_JSON_pack_amount ("fee_deposit",
@@ -2499,6 +2629,7 @@ TEH_keys_management_get_keys_handler (const struct TEH_RequestHandler *rh,
struct TEH_KeyStateHandle *ksh;
json_t *reply;
+ (void) rh;
ksh = get_key_state (true);
if (NULL == ksh)
{
diff --git a/src/exchange/taler-exchange-httpd_keys.h b/src/exchange/taler-exchange-httpd_keys.h
index ce5e2b73..75de7cba 100644
--- a/src/exchange/taler-exchange-httpd_keys.h
+++ b/src/exchange/taler-exchange-httpd_keys.h
@@ -50,7 +50,7 @@ struct TEH_DenominationKey
/**
* Hash code of the denomination public key.
*/
- struct GNUNET_HashCode h_denom_pub;
+ struct TALER_DenominationHash h_denom_pub;
/**
* Meta data about the type of the denomination, such as fees and validity
@@ -97,6 +97,13 @@ struct TEH_KeyStateHandle;
/**
+ * Run internal invariant checks. For debugging.
+ */
+void
+TEH_check_invariants (void);
+
+
+/**
* Return the current key state for this thread. Possibly re-builds the key
* state if we have reason to believe that something changed.
*
@@ -135,7 +142,7 @@ TEH_keys_update_states (void);
* or NULL if @a h_denom_pub could not be found
*/
struct TEH_DenominationKey *
-TEH_keys_denomination_by_hash (const struct GNUNET_HashCode *h_denom_pub,
+TEH_keys_denomination_by_hash (const struct TALER_DenominationHash *h_denom_pub,
struct MHD_Connection *conn,
MHD_RESULT *mret);
@@ -155,7 +162,8 @@ TEH_keys_denomination_by_hash (const struct GNUNET_HashCode *h_denom_pub,
*/
struct TEH_DenominationKey *
TEH_keys_denomination_by_hash2 (struct TEH_KeyStateHandle *ksh,
- const struct GNUNET_HashCode *h_denom_pub,
+ const struct
+ TALER_DenominationHash *h_denom_pub,
struct MHD_Connection *conn,
MHD_RESULT *mret);
@@ -170,8 +178,8 @@ TEH_keys_denomination_by_hash2 (struct TEH_KeyStateHandle *ksh,
* @return signature, the value inside the structure will be NULL on failure,
* see @a ec for details about the failure
*/
-struct TALER_DenominationSignature
-TEH_keys_denomination_sign (const struct GNUNET_HashCode *h_denom_pub,
+struct TALER_BlindedDenominationSignature
+TEH_keys_denomination_sign (const struct TALER_DenominationHash *h_denom_pub,
const void *msg,
size_t msg_size,
enum TALER_ErrorCode *ec);
@@ -189,7 +197,7 @@ TEH_keys_denomination_sign (const struct GNUNET_HashCode *h_denom_pub,
* @param h_denom_pub hash of the public key to revoke
*/
void
-TEH_keys_denomination_revoke (const struct GNUNET_HashCode *h_denom_pub);
+TEH_keys_denomination_revoke (const struct TALER_DenominationHash *h_denom_pub);
/**
@@ -366,7 +374,7 @@ TEH_keys_management_get_keys_handler (const struct TEH_RequestHandler *rh,
* #GNUNET_SYSERR on hard errors
*/
enum GNUNET_GenericReturnValue
-TEH_keys_load_fees (const struct GNUNET_HashCode *h_denom_pub,
+TEH_keys_load_fees (const struct TALER_DenominationHash *h_denom_pub,
struct TALER_DenominationPublicKey *denom_pub,
struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta);
@@ -378,7 +386,7 @@ TEH_keys_load_fees (const struct GNUNET_HashCode *h_denom_pub,
* @param[out] meta set to meta data about the key
* @return #GNUNET_OK on success
*/
-int
+enum GNUNET_GenericReturnValue
TEH_keys_get_timing (const struct TALER_ExchangePublicKeyP *exchange_pub,
struct TALER_EXCHANGEDB_SignkeyMetaData *meta);
diff --git a/src/exchange/taler-exchange-httpd_kyc-check.c b/src/exchange/taler-exchange-httpd_kyc-check.c
index ae1ab34f..76d09481 100644
--- a/src/exchange/taler-exchange-httpd_kyc-check.c
+++ b/src/exchange/taler-exchange-httpd_kyc-check.c
@@ -27,17 +27,39 @@
#include "taler_json_lib.h"
#include "taler_mhd_lib.h"
#include "taler_signatures.h"
+#include "taler_dbevents.h"
#include "taler-exchange-httpd_keys.h"
#include "taler-exchange-httpd_kyc-wallet.h"
#include "taler-exchange-httpd_responses.h"
/**
- * Context for the request.
+ * Reserve GET request that is long-polling.
*/
-struct KycCheckContext
+struct KycPoller
{
/**
+ * Kept in a DLL.
+ */
+ struct KycPoller *next;
+
+ /**
+ * Kept in a DLL.
+ */
+ struct KycPoller *prev;
+
+ /**
+ * Connection we are handling.
+ */
+ struct MHD_Connection *connection;
+
+ /**
+ * Subscription for the database event we are
+ * waiting for.
+ */
+ struct GNUNET_DB_EventHandler *eh;
+
+ /**
* UUID being checked.
*/
uint64_t payment_target_uuid;
@@ -51,11 +73,81 @@ struct KycCheckContext
* Hash of the payto:// URI we are confirming to
* have finished the KYC for.
*/
- struct GNUNET_HashCode h_payto;
+ struct TALER_PaytoHash h_payto;
+
+ /**
+ * Hash of the payto:// URI that was given to us for auth.
+ */
+ struct TALER_PaytoHash auth_h_payto;
+
+ /**
+ * When will this request time out?
+ */
+ struct GNUNET_TIME_Absolute timeout;
+
+ /**
+ * True if we are still suspended.
+ */
+ bool suspended;
+
};
/**
+ * Head of list of requests in long polling.
+ */
+static struct KycPoller *kyp_head;
+
+/**
+ * Tail of list of requests in long polling.
+ */
+static struct KycPoller *kyp_tail;
+
+
+void
+TEH_kyc_check_cleanup ()
+{
+ struct KycPoller *kyp;
+
+ while (NULL != (kyp = kyp_head))
+ {
+ GNUNET_CONTAINER_DLL_remove (kyp_head,
+ kyp_tail,
+ kyp);
+ if (kyp->suspended)
+ {
+ kyp->suspended = false;
+ MHD_resume_connection (kyp->connection);
+ }
+ }
+}
+
+
+/**
+ * Function called once a connection is done to
+ * clean up the `struct ReservePoller` state.
+ *
+ * @param rc context to clean up for
+ */
+static void
+kyp_cleanup (struct TEH_RequestContext *rc)
+{
+ struct KycPoller *kyp = rc->rh_ctx;
+
+ GNUNET_assert (! kyp->suspended);
+ if (NULL != kyp->eh)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Cancelling DB event listening\n");
+ TEH_plugin->event_listen_cancel (TEH_plugin->cls,
+ kyp->eh);
+ kyp->eh = NULL;
+ }
+ GNUNET_free (kyp);
+}
+
+
+/**
* Function implementing database transaction to check wallet's KYC status.
* Runs the transaction logic; IF it returns a non-error code, the transaction
* logic MUST NOT queue a MHD response. IF it returns an hard error, the
@@ -63,7 +155,7 @@ struct KycCheckContext
* returns the soft error code, the function MAY be called again to retry and
* MUST not queue a MHD response.
*
- * @param cls closure with a `struct KycCheckContext *`
+ * @param cls closure with a `struct KycPoller *`
* @param connection MHD request which triggered the transaction
* @param[out] mhd_ret set to MHD response status for @a connection,
* if transaction failed (!)
@@ -74,13 +166,13 @@ kyc_check (void *cls,
struct MHD_Connection *connection,
MHD_RESULT *mhd_ret)
{
- struct KycCheckContext *kcc = cls;
+ struct KycPoller *kyp = cls;
enum GNUNET_DB_QueryStatus qs;
qs = TEH_plugin->select_kyc_status (TEH_plugin->cls,
- kcc->payment_target_uuid,
- &kcc->h_payto,
- &kcc->kyc);
+ kyp->payment_target_uuid,
+ &kyp->h_payto,
+ &kyp->kyc);
if (qs < 0)
{
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
@@ -96,27 +188,136 @@ kyc_check (void *cls,
}
+/**
+ * Function called on events received from Postgres.
+ * Wakes up long pollers.
+ *
+ * @param cls the `struct TEH_RequestContext *`
+ * @param extra additional event data provided
+ * @param extra_size number of bytes in @a extra
+ */
+static void
+db_event_cb (void *cls,
+ const void *extra,
+ size_t extra_size)
+{
+ struct TEH_RequestContext *rc = cls;
+ struct KycPoller *kyp = rc->rh_ctx;
+ struct GNUNET_AsyncScopeSave old_scope;
+
+ (void) extra;
+ (void) extra_size;
+ if (! kyp->suspended)
+ return; /* event triggered while main transaction
+ was still running, or got multiple wake-up events */
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Received KYC update event\n");
+ kyp->suspended = false;
+ GNUNET_async_scope_enter (&rc->async_scope_id,
+ &old_scope);
+ TEH_check_invariants ();
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Resuming from long-polling on KYC status\n");
+ GNUNET_CONTAINER_DLL_remove (kyp_head,
+ kyp_tail,
+ kyp);
+ MHD_resume_connection (kyp->connection);
+ TALER_MHD_daemon_trigger ();
+ TEH_check_invariants ();
+ GNUNET_async_scope_restore (&old_scope);
+}
+
+
MHD_RESULT
TEH_handler_kyc_check (
struct TEH_RequestContext *rc,
const char *const args[])
{
- unsigned long long payment_target_uuid;
+ struct KycPoller *kyp = rc->rh_ctx;
MHD_RESULT res;
enum GNUNET_GenericReturnValue ret;
- char dummy;
+ struct GNUNET_TIME_Absolute now;
- if (1 !=
- sscanf (args[0],
- "%llu%c",
- &payment_target_uuid,
- &dummy))
+ if (NULL == kyp)
{
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "payment_target_uuid");
+ kyp = GNUNET_new (struct KycPoller);
+ kyp->connection = rc->connection;
+ rc->rh_ctx = kyp;
+ rc->rh_cleaner = &kyp_cleanup;
+
+ {
+ unsigned long long payment_target_uuid;
+ char dummy;
+
+ if (1 !=
+ sscanf (args[0],
+ "%llu%c",
+ &payment_target_uuid,
+ &dummy))
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (rc->connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "payment_target_uuid");
+ }
+ kyp->payment_target_uuid = (uint64_t) payment_target_uuid;
+ }
+ {
+ const char *ts;
+
+ ts = MHD_lookup_connection_value (rc->connection,
+ MHD_GET_ARGUMENT_KIND,
+ "timeout_ms");
+ if (NULL != ts)
+ {
+ char dummy;
+ unsigned long long tms;
+
+ if (1 !=
+ sscanf (ts,
+ "%llu%c",
+ &tms,
+ &dummy))
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (rc->connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "timeout_ms");
+ }
+ kyp->timeout = GNUNET_TIME_relative_to_absolute (
+ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
+ tms));
+ }
+ }
+ {
+ const char *hps;
+
+ hps = MHD_lookup_connection_value (rc->connection,
+ MHD_GET_ARGUMENT_KIND,
+ "h_payto");
+ if (NULL == hps)
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (rc->connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MISSING,
+ "h_payto");
+ }
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (hps,
+ strlen (hps),
+ &kyp->auth_h_payto,
+ sizeof (kyp->auth_h_payto)))
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (rc->connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "h_payto");
+ }
+ }
}
if (TEH_KYC_NONE == TEH_kyc_config.mode)
@@ -126,80 +327,120 @@ TEH_handler_kyc_check (
NULL,
NULL,
0);
+
+ if ( (NULL == kyp->eh) &&
+ GNUNET_TIME_absolute_is_future (kyp->timeout) )
{
- struct GNUNET_TIME_Absolute now;
- struct KycCheckContext kcc = {
- .payment_target_uuid = payment_target_uuid
+ struct TALER_KycCompletedEventP rep = {
+ .header.size = htons (sizeof (rep)),
+ .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
+ .h_payto = kyp->auth_h_payto
};
- now = GNUNET_TIME_absolute_get ();
- (void) GNUNET_TIME_round_abs (&now);
- ret = TEH_DB_run_transaction (rc->connection,
- "kyc check",
- &res,
- &kyc_check,
- &kcc);
- if (GNUNET_SYSERR == ret)
- return res;
- if (! kcc.kyc.ok)
- {
- char *url;
- char *redirect_uri;
- char *redirect_uri_encoded;
-
- GNUNET_assert (TEH_KYC_OAUTH2 == TEH_kyc_config.mode);
- GNUNET_asprintf (&redirect_uri,
- "%s/kyc-proof/%llu",
- TEH_base_url,
- payment_target_uuid);
- redirect_uri_encoded = TALER_urlencode (redirect_uri);
- GNUNET_free (redirect_uri);
- GNUNET_asprintf (&url,
- "%s/login?client_id=%s&redirect_uri=%s",
- TEH_kyc_config.details.oauth2.url,
- TEH_kyc_config.details.oauth2.client_id,
- redirect_uri_encoded);
- GNUNET_free (redirect_uri_encoded);
-
- res = TALER_MHD_REPLY_JSON_PACK (
- rc->connection,
- MHD_HTTP_ACCEPTED,
- GNUNET_JSON_pack_string ("kyc_url",
- url));
- GNUNET_free (url);
- return res;
- }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Starting DB event listening\n");
+ kyp->eh = TEH_plugin->event_listen (
+ TEH_plugin->cls,
+ GNUNET_TIME_absolute_get_remaining (kyp->timeout),
+ &rep.header,
+ &db_event_cb,
+ rc);
+ }
+
+ now = GNUNET_TIME_absolute_get ();
+ (void) GNUNET_TIME_round_abs (&now);
+ ret = TEH_DB_run_transaction (rc->connection,
+ "kyc check",
+ &res,
+ &kyc_check,
+ kyp);
+ if (GNUNET_SYSERR == ret)
+ return res;
+ if (0 !=
+ GNUNET_memcmp (&kyp->h_payto,
+ &kyp->auth_h_payto))
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (rc->connection,
+ MHD_HTTP_UNAUTHORIZED,
+ TALER_EC_EXCHANGE_KYC_CHECK_AUTHORIZATION_FAILED,
+ "h_payto");
+ }
+
+ /* long polling? */
+ if ( (! kyp->kyc.ok) &&
+ GNUNET_TIME_absolute_is_future (kyp->timeout))
+ {
+ GNUNET_assert (NULL != kyp->eh);
+ kyp->suspended = true;
+ GNUNET_CONTAINER_DLL_insert (kyp_head,
+ kyp_tail,
+ kyp);
+ MHD_suspend_connection (kyp->connection);
+ return MHD_YES;
+ }
+
+ /* KYC failed? */
+ if (! kyp->kyc.ok)
+ {
+ char *url;
+ char *redirect_uri;
+ char *redirect_uri_encoded;
+
+ GNUNET_assert (TEH_KYC_OAUTH2 == TEH_kyc_config.mode);
+ GNUNET_asprintf (&redirect_uri,
+ "%s/kyc-proof/%llu",
+ TEH_base_url,
+ (unsigned long long) kyp->payment_target_uuid);
+ redirect_uri_encoded = TALER_urlencode (redirect_uri);
+ GNUNET_free (redirect_uri);
+ GNUNET_asprintf (&url,
+ "%s/login?client_id=%s&redirect_uri=%s",
+ TEH_kyc_config.details.oauth2.url,
+ TEH_kyc_config.details.oauth2.client_id,
+ redirect_uri_encoded);
+ GNUNET_free (redirect_uri_encoded);
+
+ res = TALER_MHD_REPLY_JSON_PACK (
+ rc->connection,
+ MHD_HTTP_ACCEPTED,
+ GNUNET_JSON_pack_string ("kyc_url",
+ url));
+ GNUNET_free (url);
+ return res;
+ }
+
+ /* KYC succeeded! */
+ {
+ struct TALER_ExchangePublicKeyP pub;
+ struct TALER_ExchangeSignatureP sig;
+ struct TALER_ExchangeAccountSetupSuccessPS as = {
+ .purpose.purpose = htonl (
+ TALER_SIGNATURE_EXCHANGE_ACCOUNT_SETUP_SUCCESS),
+ .purpose.size = htonl (sizeof (as)),
+ .h_payto = kyp->h_payto,
+ .timestamp = GNUNET_TIME_absolute_hton (now)
+ };
+ enum TALER_ErrorCode ec;
+
+ if (TALER_EC_NONE !=
+ (ec = TEH_keys_exchange_sign (&as,
+ &pub,
+ &sig)))
{
- struct TALER_ExchangePublicKeyP pub;
- struct TALER_ExchangeSignatureP sig;
- struct TALER_ExchangeAccountSetupSuccessPS as = {
- .purpose.purpose = htonl (
- TALER_SIGNATURE_EXCHANGE_ACCOUNT_SETUP_SUCCESS),
- .purpose.size = htonl (sizeof (as)),
- .h_payto = kcc.h_payto,
- .timestamp = GNUNET_TIME_absolute_hton (now)
- };
- enum TALER_ErrorCode ec;
-
- if (TALER_EC_NONE !=
- (ec = TEH_keys_exchange_sign (&as,
- &pub,
- &sig)))
- {
- return TALER_MHD_reply_with_ec (rc->connection,
- ec,
- NULL);
- }
- return TALER_MHD_REPLY_JSON_PACK (
- rc->connection,
- MHD_HTTP_OK,
- GNUNET_JSON_pack_data_auto ("exchange_sig",
- &sig),
- GNUNET_JSON_pack_data_auto ("exchange_pub",
- &pub),
- GNUNET_JSON_pack_time_abs ("now",
- now));
+ return TALER_MHD_reply_with_ec (rc->connection,
+ ec,
+ NULL);
}
+ return TALER_MHD_REPLY_JSON_PACK (
+ rc->connection,
+ MHD_HTTP_OK,
+ GNUNET_JSON_pack_data_auto ("exchange_sig",
+ &sig),
+ GNUNET_JSON_pack_data_auto ("exchange_pub",
+ &pub),
+ GNUNET_JSON_pack_time_abs ("now",
+ now));
}
}
diff --git a/src/exchange/taler-exchange-httpd_kyc-check.h b/src/exchange/taler-exchange-httpd_kyc-check.h
index 8120a173..52fe5f16 100644
--- a/src/exchange/taler-exchange-httpd_kyc-check.h
+++ b/src/exchange/taler-exchange-httpd_kyc-check.h
@@ -39,4 +39,11 @@ TEH_handler_kyc_check (
const char *const args[]);
+/**
+ * Clean up long-polling KYC requests during shutdown.
+ */
+void
+TEH_kyc_check_cleanup (void);
+
+
#endif
diff --git a/src/exchange/taler-exchange-httpd_kyc-proof.c b/src/exchange/taler-exchange-httpd_kyc-proof.c
index 842e5dfd..6bd98abf 100644
--- a/src/exchange/taler-exchange-httpd_kyc-proof.c
+++ b/src/exchange/taler-exchange-httpd_kyc-proof.c
@@ -73,6 +73,11 @@ struct KycProofContext
char *post_body;
/**
+ * User ID extracted from the OAuth 2.0 service, or NULL.
+ */
+ char *id;
+
+ /**
* Payment target this is about.
*/
unsigned long long payment_target_uuid;
@@ -108,6 +113,24 @@ static struct KycProofContext *kpc_head;
static struct KycProofContext *kpc_tail;
+/**
+ * Resume processing the @a kpc request.
+ *
+ * @param kpc request to resume
+ */
+static void
+kpc_resume (struct KycProofContext *kpc)
+{
+ GNUNET_assert (GNUNET_YES == kpc->suspended);
+ kpc->suspended = GNUNET_NO;
+ GNUNET_CONTAINER_DLL_remove (kpc_head,
+ kpc_tail,
+ kpc);
+ MHD_resume_connection (kpc->rc->connection);
+ TALER_MHD_daemon_trigger ();
+}
+
+
void
TEH_kyc_proof_cleanup (void)
{
@@ -120,11 +143,7 @@ TEH_kyc_proof_cleanup (void)
GNUNET_CURL_job_cancel (kpc->job);
kpc->job = NULL;
}
- GNUNET_CONTAINER_DLL_remove (kpc_head,
- kpc_tail,
- kpc);
- kpc->suspended = GNUNET_NO;
- MHD_resume_connection (kpc->rc->connection);
+ kpc_resume (kpc);
}
}
@@ -149,15 +168,197 @@ persist_kyc_ok (void *cls,
MHD_RESULT *mhd_ret)
{
struct KycProofContext *kpc = cls;
+ enum GNUNET_DB_QueryStatus qs;
- return TEH_plugin->set_kyc_ok (TEH_plugin->cls,
- kpc->payment_target_uuid);
+ qs = TEH_plugin->set_kyc_ok (TEH_plugin->cls,
+ kpc->payment_target_uuid,
+ kpc->id);
+ if (GNUNET_DB_STATUS_HARD_ERROR == qs)
+ {
+ GNUNET_break (0);
+ *mhd_ret = TALER_MHD_reply_with_ec (connection,
+ TALER_EC_GENERIC_DB_STORE_FAILED,
+ "set_kyc_ok");
+ }
+ return qs;
+}
+
+
+/**
+ * The request for @a kpc failed. We may have gotten a useful error
+ * message in @a j. Generate a failure response.
+ *
+ * @param[in,out] kpc request that failed
+ * @param j reply from the server (or NULL)
+ */
+static void
+handle_error (struct KycProofContext *kpc,
+ const json_t *j)
+{
+ const char *msg;
+ const char *desc;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_string ("error",
+ &msg),
+ GNUNET_JSON_spec_string ("error_description",
+ &desc),
+ GNUNET_JSON_spec_end ()
+ };
+
+ {
+ enum GNUNET_GenericReturnValue res;
+ const char *emsg;
+ unsigned int line;
+
+ res = GNUNET_JSON_parse (j,
+ spec,
+ &emsg,
+ &line);
+ if (GNUNET_OK != res)
+ {
+ GNUNET_break_op (0);
+ kpc->response
+ = TALER_MHD_make_error (
+ TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE,
+ "Unexpected response from KYC gateway");
+ kpc->response_code
+ = MHD_HTTP_BAD_GATEWAY;
+ return;
+ }
+ }
+ /* case TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_AUTHORZATION_FAILED,
+ we MAY want to in the future look at the requested content type
+ and possibly respond in JSON if indicated. */
+ {
+ char *reply;
+
+ GNUNET_asprintf (&reply,
+ "<html><head><title>%s</title></head><body><h1>%s</h1><p>%s</p></body></html>",
+ msg,
+ msg,
+ desc);
+ kpc->response
+ = MHD_create_response_from_buffer (strlen (reply),
+ reply,
+ MHD_RESPMEM_MUST_COPY);
+ GNUNET_assert (NULL != kpc->response);
+ GNUNET_free (reply);
+ }
+ kpc->response_code = MHD_HTTP_FORBIDDEN;
+}
+
+
+/**
+ * The request for @a kpc succeeded (presumably).
+ * Parse the user ID and store it in @a kpc (if possible).
+ *
+ * @param[in,out] kpc request that succeeded
+ * @param j reply from the server
+ */
+static void
+parse_success_reply (struct KycProofContext *kpc,
+ const json_t *j)
+{
+ const char *state;
+ json_t *data;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_string ("status",
+ &state),
+ GNUNET_JSON_spec_json ("data",
+ &data),
+ GNUNET_JSON_spec_end ()
+ };
+ enum GNUNET_GenericReturnValue res;
+ const char *emsg;
+ unsigned int line;
+
+ res = GNUNET_JSON_parse (j,
+ spec,
+ &emsg,
+ &line);
+ if (GNUNET_OK != res)
+ {
+ GNUNET_break_op (0);
+ kpc->response
+ = TALER_MHD_make_error (
+ TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE,
+ "Unexpected response from KYC gateway");
+ kpc->response_code
+ = MHD_HTTP_BAD_GATEWAY;
+ return;
+ }
+ if (0 != strcasecmp (state,
+ "success"))
+ {
+ GNUNET_break_op (0);
+ handle_error (kpc,
+ j);
+ return;
+ }
+ {
+ const char *id;
+ struct GNUNET_JSON_Specification ispec[] = {
+ GNUNET_JSON_spec_string ("id",
+ &id),
+ GNUNET_JSON_spec_end ()
+ };
+
+ res = GNUNET_JSON_parse (data,
+ ispec,
+ &emsg,
+ &line);
+ if (GNUNET_OK != res)
+ {
+ GNUNET_break_op (0);
+ kpc->response
+ = TALER_MHD_make_error (
+ TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE,
+ "Unexpected response from KYC gateway");
+ kpc->response_code
+ = MHD_HTTP_BAD_GATEWAY;
+ return;
+ }
+ kpc->id = GNUNET_strdup (id);
+ }
}
/**
* After we are done with the CURL interaction we
- * need to update our database state.
+ * need to update our database state with the information
+ * retrieved.
+ *
+ * @param cls our `struct KycProofContext`
+ * @param response_code HTTP response code from server, 0 on hard error
+ * @param response in JSON, NULL if response was not in JSON format
+ */
+static void
+handle_curl_fetch_finished (void *cls,
+ long response_code,
+ const void *response)
+{
+ struct KycProofContext *kpc = cls;
+ const json_t *j = response;
+
+ kpc->job = NULL;
+ switch (response_code)
+ {
+ case MHD_HTTP_OK:
+ parse_success_reply (kpc,
+ j);
+ break;
+ default:
+ handle_error (kpc,
+ j);
+ break;
+ }
+ kpc_resume (kpc);
+}
+
+
+/**
+ * After we are done with the CURL interaction we
+ * need to fetch the user's account details.
*
* @param cls our `struct KycProofContext`
* @param response_code HTTP response code from server, 0 on hard error
@@ -191,6 +392,7 @@ handle_curl_login_finished (void *cls,
&refresh_token),
GNUNET_JSON_spec_end ()
};
+ CURL *eh;
{
enum GNUNET_GenericReturnValue res;
@@ -210,9 +412,7 @@ handle_curl_login_finished (void *cls,
"Unexpected response from KYC gateway");
kpc->response_code
= MHD_HTTP_BAD_GATEWAY;
- MHD_resume_connection (kpc->rc->connection);
- TALER_MHD_daemon_trigger ();
- return;
+ break;
}
}
if (0 != strcasecmp (token_type,
@@ -225,78 +425,72 @@ handle_curl_login_finished (void *cls,
"Unexpected token type in response from KYC gateway");
kpc->response_code
= MHD_HTTP_BAD_GATEWAY;
- MHD_resume_connection (kpc->rc->connection);
- TALER_MHD_daemon_trigger ();
- return;
+ break;
}
- /* TODO: Here we might want to keep something to persist in the DB, and
- possibly use the access_token to download information we should
- persist; then continue! */
-
- MHD_resume_connection (kpc->rc->connection);
- TALER_MHD_daemon_trigger ();
- return;
- }
- default:
- {
- const char *msg;
- const char *desc;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_string ("error",
- &msg),
- GNUNET_JSON_spec_string ("error_description",
- &desc),
- GNUNET_JSON_spec_end ()
- };
-
+ /* We guard against a few characters that could
+ conceivably be abused to mess with the HTTP header */
+ if ( (NULL != strchr (access_token,
+ '\n')) ||
+ (NULL != strchr (access_token,
+ '\r')) ||
+ (NULL != strchr (access_token,
+ ' ')) ||
+ (NULL != strchr (access_token,
+ ';')) )
{
- enum GNUNET_GenericReturnValue res;
- const char *emsg;
- unsigned int line;
-
- res = GNUNET_JSON_parse (j,
- spec,
- &emsg,
- &line);
- if (GNUNET_OK != res)
- {
- GNUNET_break_op (0);
- kpc->response
- = TALER_MHD_make_error (
- TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE,
- "Unexpected response from KYC gateway");
- kpc->response_code
- = MHD_HTTP_BAD_GATEWAY;
- MHD_resume_connection (kpc->rc->connection);
- TALER_MHD_daemon_trigger ();
- return;
- }
+ GNUNET_break_op (0);
+ kpc->response
+ = TALER_MHD_make_error (
+ TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE,
+ "Illegal character in access token");
+ kpc->response_code
+ = MHD_HTTP_BAD_GATEWAY;
+ break;
}
- /* case TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_AUTHORZATION_FAILED,
- we MAY want to in the future look at the requested content type
- and possibly respond in JSON if indicated. */
- {
- char *reply;
- GNUNET_asprintf (&reply,
- "<html><head><title>%s</title></head><body><h1>%s</h1><p>%s</p></body></html>",
- msg,
- msg,
- desc);
+ eh = curl_easy_init ();
+ if (NULL == eh)
+ {
+ GNUNET_break_op (0);
kpc->response
- = MHD_create_response_from_buffer (strlen (reply),
- reply,
- MHD_RESPMEM_MUST_COPY);
- GNUNET_assert (NULL != kpc->response);
- GNUNET_free (reply);
+ = TALER_MHD_make_error (
+ TALER_EC_GENERIC_ALLOCATION_FAILURE,
+ "curl_easy_init");
+ kpc->response_code
+ = MHD_HTTP_INTERNAL_SERVER_ERROR;
+ break;
}
- kpc->response_code = MHD_HTTP_FORBIDDEN;
- MHD_resume_connection (kpc->rc->connection);
- TALER_MHD_daemon_trigger ();
+ GNUNET_assert (CURLE_OK ==
+ curl_easy_setopt (eh,
+ CURLOPT_URL,
+ TEH_kyc_config.details.oauth2.info_url));
+ {
+ char *hdr;
+ struct curl_slist *slist;
+
+ GNUNET_asprintf (&hdr,
+ "%s: Bearer %s",
+ MHD_HTTP_HEADER_AUTHORIZATION,
+ access_token);
+ slist = curl_slist_append (NULL,
+ hdr);
+ kpc->job = GNUNET_CURL_job_add2 (TEH_curl_ctx,
+ eh,
+ slist,
+ &handle_curl_fetch_finished,
+ kpc);
+ curl_slist_free_all (slist);
+ GNUNET_free (hdr);
+ }
+ return;
}
+ default:
+ handle_error (kpc,
+ j);
break;
}
+ kpc_resume (kpc);
}
@@ -322,6 +516,7 @@ clean_kpc (struct TEH_RequestContext *rc)
}
GNUNET_free (kpc->post_body);
GNUNET_free (kpc->token_url);
+ GNUNET_free (kpc->id);
GNUNET_free (kpc);
}
@@ -387,7 +582,7 @@ TEH_handler_kyc_proof (
"curl_easy_init");
}
GNUNET_asprintf (&kpc->token_url,
- "%s/token",
+ "%stoken",
TEH_kyc_config.details.oauth2.url);
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
@@ -411,7 +606,7 @@ TEH_handler_kyc_proof (
char *request_uri;
GNUNET_asprintf (&request_uri,
- "%s/login?client_id=%s",
+ "%slogin?client_id=%s",
TEH_kyc_config.details.oauth2.url,
TEH_kyc_config.details.oauth2.client_id);
redirect_uri = curl_easy_escape (eh,
diff --git a/src/exchange/taler-exchange-httpd_kyc-wallet.c b/src/exchange/taler-exchange-httpd_kyc-wallet.c
index dcab3dca..3db174bf 100644
--- a/src/exchange/taler-exchange-httpd_kyc-wallet.c
+++ b/src/exchange/taler-exchange-httpd_kyc-wallet.c
@@ -109,6 +109,7 @@ TEH_handler_kyc_wallet (
.purpose = htonl (TALER_SIGNATURE_WALLET_ACCOUNT_SETUP)
};
+ (void) args;
ret = TALER_MHD_parse_json_data (rc->connection,
root,
spec);
diff --git a/src/exchange/taler-exchange-httpd_link.c b/src/exchange/taler-exchange-httpd_link.c
index 75d32e56..3393e068 100644
--- a/src/exchange/taler-exchange-httpd_link.c
+++ b/src/exchange/taler-exchange-httpd_link.c
@@ -82,10 +82,10 @@ handle_link_data (void *cls,
json_t *obj;
obj = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_rsa_public_key ("denom_pub",
- pos->denom_pub.rsa_public_key),
- GNUNET_JSON_pack_rsa_signature ("ev_sig",
- pos->ev_sig.rsa_signature),
+ TALER_JSON_pack_denom_pub ("denom_pub",
+ &pos->denom_pub),
+ TALER_JSON_pack_blinded_denom_sig ("ev_sig",
+ &pos->ev_sig),
GNUNET_JSON_pack_data_auto ("link_sig",
&pos->orig_coin_link_sig));
if ( (NULL == obj) ||
diff --git a/src/exchange/taler-exchange-httpd_management.h b/src/exchange/taler-exchange-httpd_management.h
index 3f58083e..d46aad9e 100644
--- a/src/exchange/taler-exchange-httpd_management.h
+++ b/src/exchange/taler-exchange-httpd_management.h
@@ -64,7 +64,7 @@ TEH_handler_management_auditors_AP_disable (
MHD_RESULT
TEH_handler_management_denominations_HDP_revoke (
struct MHD_Connection *connection,
- const struct GNUNET_HashCode *h_denom_pub,
+ const struct TALER_DenominationHash *h_denom_pub,
const json_t *root);
diff --git a/src/exchange/taler-exchange-httpd_management_denominations_HDP_revoke.c b/src/exchange/taler-exchange-httpd_management_denominations_HDP_revoke.c
index 6519404d..a8acf2f7 100644
--- a/src/exchange/taler-exchange-httpd_management_denominations_HDP_revoke.c
+++ b/src/exchange/taler-exchange-httpd_management_denominations_HDP_revoke.c
@@ -34,7 +34,7 @@
MHD_RESULT
TEH_handler_management_denominations_HDP_revoke (
struct MHD_Connection *connection,
- const struct GNUNET_HashCode *h_denom_pub,
+ const struct TALER_DenominationHash *h_denom_pub,
const json_t *root)
{
struct TALER_MasterSignatureP master_sig;
diff --git a/src/exchange/taler-exchange-httpd_management_post_keys.c b/src/exchange/taler-exchange-httpd_management_post_keys.c
index 311fff78..86b17cb3 100644
--- a/src/exchange/taler-exchange-httpd_management_post_keys.c
+++ b/src/exchange/taler-exchange-httpd_management_post_keys.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2020 Taler Systems SA
+ Copyright (C) 2020, 2021 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software
@@ -40,7 +40,7 @@ struct DenomSig
/**
* Hash of a denomination public key.
*/
- struct GNUNET_HashCode h_denom_pub;
+ struct TALER_DenominationHash h_denom_pub;
/**
* Master signature for the @e h_denom_pub.
@@ -121,15 +121,19 @@ add_keys (void *cls,
/* activate all denomination keys */
for (unsigned int i = 0; i<akc->nd_sigs; i++)
{
+ struct DenomSig *d = &akc->d_sigs[i];
enum GNUNET_DB_QueryStatus qs;
bool is_active = false;
struct TALER_EXCHANGEDB_DenominationKeyMetaData meta;
struct TALER_DenominationPublicKey denom_pub;
/* For idempotency, check if the key is already active */
+ memset (&denom_pub,
+ 0,
+ sizeof (denom_pub));
qs = TEH_plugin->lookup_denomination_key (
TEH_plugin->cls,
- &akc->d_sigs[i].h_denom_pub,
+ &d->h_denom_pub,
&meta);
if (qs < 0)
{
@@ -146,7 +150,7 @@ add_keys (void *cls,
{
enum GNUNET_GenericReturnValue rv;
- rv = TEH_keys_load_fees (&akc->d_sigs[i].h_denom_pub,
+ rv = TEH_keys_load_fees (&d->h_denom_pub,
&denom_pub,
&meta);
switch (rv)
@@ -156,14 +160,14 @@ add_keys (void *cls,
connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_EXCHANGE_GENERIC_BAD_CONFIGURATION,
- GNUNET_h2s (&akc->d_sigs[i].h_denom_pub));
+ GNUNET_h2s (&d->h_denom_pub.hash));
return GNUNET_DB_STATUS_HARD_ERROR;
case GNUNET_NO:
*mhd_ret = TALER_MHD_reply_with_error (
connection,
MHD_HTTP_NOT_FOUND,
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN,
- GNUNET_h2s (&akc->d_sigs[i].h_denom_pub));
+ GNUNET_h2s (&d->h_denom_pub.hash));
return GNUNET_DB_STATUS_HARD_ERROR;
case GNUNET_OK:
break;
@@ -175,40 +179,45 @@ add_keys (void *cls,
}
/* check signature is valid */
+ if (GNUNET_OK !=
+ TALER_exchange_offline_denom_validity_verify (
+ &d->h_denom_pub,
+ meta.start,
+ meta.expire_withdraw,
+ meta.expire_deposit,
+ meta.expire_legal,
+ &meta.value,
+ &meta.fee_withdraw,
+ &meta.fee_deposit,
+ &meta.fee_refresh,
+ &meta.fee_refund,
+ &TEH_master_public_key,
+ &d->master_sig))
{
- if (GNUNET_OK !=
- TALER_exchange_offline_denom_validity_verify (
- &akc->d_sigs[i].h_denom_pub,
- meta.start,
- meta.expire_withdraw,
- meta.expire_deposit,
- meta.expire_legal,
- &meta.value,
- &meta.fee_withdraw,
- &meta.fee_deposit,
- &meta.fee_refresh,
- &meta.fee_refund,
- &TEH_master_public_key,
- &akc->d_sigs[i].master_sig))
- {
- GNUNET_break_op (0);
- *mhd_ret = TALER_MHD_reply_with_error (
- connection,
- MHD_HTTP_FORBIDDEN,
- TALER_EC_EXCHANGE_MANAGEMENT_KEYS_DENOMKEY_ADD_SIGNATURE_INVALID,
- GNUNET_h2s (&akc->d_sigs[i].h_denom_pub));
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
+ GNUNET_break_op (0);
+ *mhd_ret = TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_FORBIDDEN,
+ TALER_EC_EXCHANGE_MANAGEMENT_KEYS_DENOMKEY_ADD_SIGNATURE_INVALID,
+ GNUNET_h2s (&d->h_denom_pub.hash));
+ if (! is_active)
+ TALER_denom_pub_free (&denom_pub);
+ return GNUNET_DB_STATUS_HARD_ERROR;
}
if (is_active)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Denomination key %s already active, skipping\n",
+ GNUNET_h2s (&d->h_denom_pub.hash));
continue; /* skip, already known */
+ }
qs = TEH_plugin->add_denomination_key (
TEH_plugin->cls,
- &akc->d_sigs[i].h_denom_pub,
+ &d->h_denom_pub,
&denom_pub,
&meta,
- &akc->d_sigs[i].master_sig);
- GNUNET_CRYPTO_rsa_public_key_free (denom_pub.rsa_public_key);
+ &d->master_sig);
+ TALER_denom_pub_free (&denom_pub);
if (qs < 0)
{
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
@@ -222,20 +231,20 @@ add_keys (void *cls,
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Added offline signature for denomination `%s'\n",
- GNUNET_h2s (&akc->d_sigs[i].h_denom_pub));
+ GNUNET_h2s (&d->h_denom_pub.hash));
GNUNET_assert (0 != qs);
}
-
for (unsigned int i = 0; i<akc->ns_sigs; i++)
{
+ struct SigningSig *s = &akc->s_sigs[i];
enum GNUNET_DB_QueryStatus qs;
bool is_active = false;
struct TALER_EXCHANGEDB_SignkeyMetaData meta;
qs = TEH_plugin->lookup_signing_key (
TEH_plugin->cls,
- &akc->s_sigs[i].exchange_pub,
+ &s->exchange_pub,
&meta);
if (qs < 0)
{
@@ -251,7 +260,7 @@ add_keys (void *cls,
if (0 == qs)
{
if (GNUNET_OK !=
- TEH_keys_get_timing (&akc->s_sigs[i].exchange_pub,
+ TEH_keys_get_timing (&s->exchange_pub,
&meta))
{
/* For idempotency, check if the key is already active */
@@ -259,7 +268,7 @@ add_keys (void *cls,
connection,
MHD_HTTP_NOT_FOUND,
TALER_EC_EXCHANGE_MANAGEMENT_KEYS_SIGNKEY_UNKNOWN,
- TALER_B2S (&akc->s_sigs[i].exchange_pub));
+ TALER_B2S (&s->exchange_pub));
return GNUNET_DB_STATUS_HARD_ERROR;
}
}
@@ -269,32 +278,35 @@ add_keys (void *cls,
}
/* check signature is valid */
+ if (GNUNET_OK !=
+ TALER_exchange_offline_signkey_validity_verify (
+ &s->exchange_pub,
+ meta.start,
+ meta.expire_sign,
+ meta.expire_legal,
+ &TEH_master_public_key,
+ &s->master_sig))
{
- if (GNUNET_OK !=
- TALER_exchange_offline_signkey_validity_verify (
- &akc->s_sigs[i].exchange_pub,
- meta.start,
- meta.expire_sign,
- meta.expire_legal,
- &TEH_master_public_key,
- &akc->s_sigs[i].master_sig))
- {
- GNUNET_break_op (0);
- *mhd_ret = TALER_MHD_reply_with_error (
- connection,
- MHD_HTTP_FORBIDDEN,
- TALER_EC_EXCHANGE_MANAGEMENT_KEYS_SIGNKEY_ADD_SIGNATURE_INVALID,
- GNUNET_h2s (&akc->d_sigs[i].h_denom_pub));
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
+ GNUNET_break_op (0);
+ *mhd_ret = TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_FORBIDDEN,
+ TALER_EC_EXCHANGE_MANAGEMENT_KEYS_SIGNKEY_ADD_SIGNATURE_INVALID,
+ TALER_B2S (&s->exchange_pub));
+ return GNUNET_DB_STATUS_HARD_ERROR;
}
if (is_active)
- continue; /* skip, already known */
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Signing key %s already active, skipping\n",
+ TALER_B2S (&s->exchange_pub));
+ continue; /* skip, already known */
+ }
qs = TEH_plugin->activate_signing_key (
TEH_plugin->cls,
- &akc->s_sigs[i].exchange_pub,
+ &s->exchange_pub,
&meta,
- &akc->s_sigs[i].master_sig);
+ &s->master_sig);
if (qs < 0)
{
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
@@ -308,7 +320,7 @@ add_keys (void *cls,
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Added offline signature for signing key `%s'\n",
- TALER_B2S (&akc->s_sigs[i].exchange_pub));
+ TALER_B2S (&s->exchange_pub));
GNUNET_assert (0 != qs);
}
return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; /* only 'success', so >=0, matters here */
diff --git a/src/exchange/taler-exchange-httpd_melt.c b/src/exchange/taler-exchange-httpd_melt.c
index af0a0a63..c33473b4 100644
--- a/src/exchange/taler-exchange-httpd_melt.c
+++ b/src/exchange/taler-exchange-httpd_melt.c
@@ -494,7 +494,7 @@ check_for_denomination_key (struct MHD_Connection *connection,
if (GNUNET_TIME_absolute_is_past (dk->meta.expire_deposit))
{
/* We are past deposit expiration time, but maybe this is a zombie? */
- struct GNUNET_HashCode denom_hash;
+ struct TALER_DenominationHash denom_hash;
enum GNUNET_DB_QueryStatus qs;
/* Check that the coin is dirty (we have seen it before), as we will
@@ -590,8 +590,8 @@ TEH_handler_melt (struct MHD_Connection *connection,
enum GNUNET_GenericReturnValue ret;
MHD_RESULT res;
struct GNUNET_JSON_Specification spec[] = {
- TALER_JSON_spec_denomination_signature ("denom_sig",
- &rmc.refresh_session.coin.denom_sig),
+ TALER_JSON_spec_denom_sig ("denom_sig",
+ &rmc.refresh_session.coin.denom_sig),
GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
&rmc.refresh_session.coin.denom_pub_hash),
GNUNET_JSON_spec_fixed_auto ("confirm_sig",
diff --git a/src/exchange/taler-exchange-httpd_recoup.c b/src/exchange/taler-exchange-httpd_recoup.c
index 137034a4..b5074ce3 100644
--- a/src/exchange/taler-exchange-httpd_recoup.c
+++ b/src/exchange/taler-exchange-httpd_recoup.c
@@ -41,7 +41,7 @@ struct RecoupContext
/**
* Hash of the blinded coin.
*/
- struct GNUNET_HashCode h_blind;
+ struct TALER_BlindedCoinHash h_blind;
/**
* Full value of the coin.
@@ -56,7 +56,7 @@ struct RecoupContext
/**
* Key used to blind the coin.
*/
- const struct TALER_DenominationBlindingKeyP *coin_bks;
+ const union TALER_DenominationBlindingKeyP *coin_bks;
/**
* Signature of the coin requesting recoup.
@@ -179,7 +179,7 @@ recoup_transaction (void *cls,
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Recoup requested for unknown envelope %s\n",
- GNUNET_h2s (&pc->h_blind));
+ GNUNET_h2s (&pc->h_blind.hash));
*mhd_ret = TALER_MHD_reply_with_error (connection,
MHD_HTTP_NOT_FOUND,
TALER_EC_EXCHANGE_RECOUP_WITHDRAW_NOT_FOUND,
@@ -342,18 +342,16 @@ recoup_transaction (void *cls,
* @return MHD result code
*/
static MHD_RESULT
-verify_and_execute_recoup (struct MHD_Connection *connection,
- const struct TALER_CoinPublicInfo *coin,
- const struct
- TALER_DenominationBlindingKeyP *coin_bks,
- const struct TALER_CoinSpendSignatureP *coin_sig,
- int refreshed)
+verify_and_execute_recoup (
+ struct MHD_Connection *connection,
+ const struct TALER_CoinPublicInfo *coin,
+ const union TALER_DenominationBlindingKeyP *coin_bks,
+ const struct TALER_CoinSpendSignatureP *coin_sig,
+ int refreshed)
{
struct RecoupContext pc;
const struct TEH_DenominationKey *dk;
- struct GNUNET_HashCode c_hash;
- void *coin_ev;
- size_t coin_ev_size;
+ struct TALER_CoinPubHash c_hash;
MHD_RESULT mret;
/* check denomination exists and is in recoup mode */
@@ -423,7 +421,7 @@ verify_and_execute_recoup (struct MHD_Connection *connection,
{
struct TALER_RecoupRequestPS pr = {
.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP),
- .purpose.size = htonl (sizeof (struct TALER_RecoupRequestPS)),
+ .purpose.size = htonl (sizeof (pr)),
.coin_pub = coin->coin_pub,
.h_denom_pub = coin->denom_pub_hash,
.coin_blind = *coin_bks
@@ -442,26 +440,31 @@ verify_and_execute_recoup (struct MHD_Connection *connection,
NULL);
}
}
- GNUNET_CRYPTO_hash (&coin->coin_pub.eddsa_pub,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
- &c_hash);
- if (GNUNET_YES !=
- TALER_rsa_blind (&c_hash,
- &coin_bks->bks,
- dk->denom_pub.rsa_public_key,
- &coin_ev,
- &coin_ev_size))
+
{
- GNUNET_break (0);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_EXCHANGE_RECOUP_BLINDING_FAILED,
- NULL);
+ void *coin_ev;
+ size_t coin_ev_size;
+
+ if (GNUNET_OK !=
+ TALER_denom_blind (&dk->denom_pub,
+ coin_bks,
+ NULL, /* FIXME-Oec: TALER_AgeHash * */
+ &coin->coin_pub,
+ &c_hash,
+ &coin_ev,
+ &coin_ev_size))
+ {
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_EXCHANGE_RECOUP_BLINDING_FAILED,
+ NULL);
+ }
+ TALER_coin_ev_hash (coin_ev,
+ coin_ev_size,
+ &pc.h_blind);
+ GNUNET_free (coin_ev);
}
- GNUNET_CRYPTO_hash (coin_ev,
- coin_ev_size,
- &pc.h_blind);
- GNUNET_free (coin_ev);
/* Perform actual recoup transaction */
pc.coin_sig = coin_sig;
@@ -516,14 +519,14 @@ TEH_handler_recoup (struct MHD_Connection *connection,
{
enum GNUNET_GenericReturnValue ret;
struct TALER_CoinPublicInfo coin;
- struct TALER_DenominationBlindingKeyP coin_bks;
+ union TALER_DenominationBlindingKeyP coin_bks;
struct TALER_CoinSpendSignatureP coin_sig;
int refreshed = GNUNET_NO;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
&coin.denom_pub_hash),
- TALER_JSON_spec_denomination_signature ("denom_sig",
- &coin.denom_sig),
+ TALER_JSON_spec_denom_sig ("denom_sig",
+ &coin.denom_sig),
GNUNET_JSON_spec_fixed_auto ("coin_blind_key_secret",
&coin_bks),
GNUNET_JSON_spec_fixed_auto ("coin_sig",
diff --git a/src/exchange/taler-exchange-httpd_refreshes_reveal.c b/src/exchange/taler-exchange-httpd_refreshes_reveal.c
index 4ca6bd15..4ec70313 100644
--- a/src/exchange/taler-exchange-httpd_refreshes_reveal.c
+++ b/src/exchange/taler-exchange-httpd_refreshes_reveal.c
@@ -55,7 +55,8 @@
static MHD_RESULT
reply_refreshes_reveal_success (struct MHD_Connection *connection,
unsigned int num_freshcoins,
- const struct TALER_DenominationSignature *sigs)
+ const struct
+ TALER_BlindedDenominationSignature *sigs)
{
json_t *list;
@@ -68,8 +69,8 @@ reply_refreshes_reveal_success (struct MHD_Connection *connection,
json_t *obj;
obj = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_rsa_signature ("ev_sig",
- sigs[freshcoin_index].rsa_signature));
+ TALER_JSON_pack_blinded_denom_sig ("ev_sig",
+ &sigs[freshcoin_index]));
GNUNET_assert (0 ==
json_array_append_new (list,
obj));
@@ -123,7 +124,7 @@ struct RevealContext
/**
* Envelopes with the signatures to be returned. Initially NULL.
*/
- struct TALER_DenominationSignature *ev_sigs;
+ struct TALER_BlindedDenominationSignature *ev_sigs;
/**
* Size of the @e dks, @e rcds and @e ev_sigs arrays (if non-NULL).
@@ -187,10 +188,10 @@ check_exists_cb (void *cls,
if (NULL == rctx->ev_sigs)
{
rctx->ev_sigs = GNUNET_new_array (num_freshcoins,
- struct TALER_DenominationSignature);
+ struct TALER_BlindedDenominationSignature);
for (unsigned int i = 0; i<num_freshcoins; i++)
- rctx->ev_sigs[i].rsa_signature
- = GNUNET_CRYPTO_rsa_signature_dup (rrcs[i].coin_sig.rsa_signature);
+ TALER_blinded_denom_sig_deep_copy (&rctx->ev_sigs[i],
+ &rrcs[i].coin_sig);
}
}
@@ -334,7 +335,7 @@ refreshes_reveal_transaction (void *cls,
struct TALER_RefreshCoinData *rcd = &rce->new_coins[j];
struct TALER_PlanchetSecretsP ps;
struct TALER_PlanchetDetail pd;
- struct GNUNET_HashCode c_hash;
+ struct TALER_CoinPubHash c_hash;
rcd->dk = &rctx->dks[j]->denom_pub;
TALER_planchet_setup_refresh (&ts,
@@ -500,7 +501,7 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
unsigned int num_fresh_coins = json_array_size (new_denoms_h_json);
/* We know num_fresh_coins is bounded by #MAX_FRESH_COINS, so this is safe */
const struct TEH_DenominationKey *dks[num_fresh_coins];
- struct GNUNET_HashCode dk_h[num_fresh_coins];
+ struct TALER_DenominationHash dk_h[num_fresh_coins];
struct TALER_RefreshCoinData rcds[num_fresh_coins];
struct TALER_CoinSpendSignatureP link_sigs[num_fresh_coins];
struct TALER_EXCHANGEDB_Melt melt;
@@ -683,10 +684,10 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
/* sign _early_ (optimistic!) to keep out of transaction scope! */
rctx->ev_sigs = GNUNET_new_array (rctx->num_fresh_coins,
- struct TALER_DenominationSignature);
+ struct TALER_BlindedDenominationSignature);
for (unsigned int i = 0; i<rctx->num_fresh_coins; i++)
{
- enum TALER_ErrorCode ec;
+ enum TALER_ErrorCode ec = TALER_EC_NONE;
rctx->ev_sigs[i]
= TEH_keys_denomination_sign (
@@ -694,7 +695,7 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
rctx->rcds[i].coin_ev,
rctx->rcds[i].coin_ev_size,
&ec);
- if (NULL == rctx->ev_sigs[i].rsa_signature)
+ if (TALER_EC_NONE != ec)
{
GNUNET_break (0);
ret = TALER_MHD_reply_with_ec (connection,
@@ -769,8 +770,7 @@ cleanup:
if (NULL != rctx->ev_sigs)
{
for (unsigned int i = 0; i<num_fresh_coins; i++)
- if (NULL != rctx->ev_sigs[i].rsa_signature)
- GNUNET_CRYPTO_rsa_signature_free (rctx->ev_sigs[i].rsa_signature);
+ TALER_blinded_denom_sig_free (&rctx->ev_sigs[i]);
GNUNET_free (rctx->ev_sigs);
rctx->ev_sigs = NULL; /* just to be safe... */
}
diff --git a/src/exchange/taler-exchange-httpd_refund.c b/src/exchange/taler-exchange-httpd_refund.c
index 73b4b251..be8a88df 100644
--- a/src/exchange/taler-exchange-httpd_refund.c
+++ b/src/exchange/taler-exchange-httpd_refund.c
@@ -370,7 +370,7 @@ static MHD_RESULT
verify_and_execute_refund (struct MHD_Connection *connection,
struct TALER_EXCHANGEDB_Refund *refund)
{
- struct GNUNET_HashCode denom_hash;
+ struct TALER_DenominationHash denom_hash;
{
struct TALER_RefundRequestPS rr = {
diff --git a/src/exchange/taler-exchange-httpd_reserves_get.c b/src/exchange/taler-exchange-httpd_reserves_get.c
index 57ab7137..89a7dd49 100644
--- a/src/exchange/taler-exchange-httpd_reserves_get.c
+++ b/src/exchange/taler-exchange-httpd_reserves_get.c
@@ -26,6 +26,7 @@
#include "taler_mhd_lib.h"
#include "taler_json_lib.h"
#include "taler_dbevents.h"
+#include "taler-exchange-httpd_keys.h"
#include "taler-exchange-httpd_reserves_get.h"
#include "taler-exchange-httpd_responses.h"
@@ -152,11 +153,13 @@ db_event_cb (void *cls,
&old_scope);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Resuming from long-polling on reserve\n");
+ TEH_check_invariants ();
GNUNET_CONTAINER_DLL_remove (rp_head,
rp_tail,
rp);
MHD_resume_connection (rp->connection);
TALER_MHD_daemon_trigger ();
+ TEH_check_invariants ();
GNUNET_async_scope_restore (&old_scope);
}
diff --git a/src/exchange/taler-exchange-httpd_responses.c b/src/exchange/taler-exchange-httpd_responses.c
index 66da1216..cb1179d6 100644
--- a/src/exchange/taler-exchange-httpd_responses.c
+++ b/src/exchange/taler-exchange-httpd_responses.c
@@ -61,30 +61,25 @@ TEH_RESPONSE_compile_transaction_history (
{
const struct TALER_EXCHANGEDB_DepositListEntry *deposit =
pos->details.deposit;
- struct TALER_DepositRequestPS dr = {
- .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT),
- .purpose.size = htonl (sizeof (dr)),
- .h_contract_terms = deposit->h_contract_terms,
- .h_wire = deposit->h_wire,
- .h_denom_pub = deposit->h_denom_pub,
- .wallet_timestamp = GNUNET_TIME_absolute_hton (deposit->timestamp),
- .refund_deadline = GNUNET_TIME_absolute_hton (
- deposit->refund_deadline),
- .merchant = deposit->merchant_pub,
- .coin_pub = *coin_pub
- };
+ struct TALER_MerchantWireHash h_wire;
- TALER_amount_hton (&dr.amount_with_fee,
- &deposit->amount_with_fee);
- TALER_amount_hton (&dr.deposit_fee,
- &deposit->deposit_fee);
+ TALER_merchant_wire_signature_hash (deposit->receiver_wire_account,
+ &deposit->wire_salt,
+ &h_wire);
#if ENABLE_SANITY_CHECKS
/* internal sanity check before we hand out a bogus sig... */
if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_DEPOSIT,
- &dr,
- &deposit->csig.eddsa_signature,
- &coin_pub->eddsa_pub))
+ TALER_wallet_deposit_verify (&deposit->amount_with_fee,
+ &deposit->deposit_fee,
+ &h_wire,
+ &deposit->h_contract_terms,
+ NULL /* h_extensions! */,
+ &deposit->h_denom_pub,
+ deposit->timestamp,
+ &deposit->merchant_pub,
+ deposit->refund_deadline,
+ coin_pub,
+ &deposit->csig))
{
GNUNET_break (0);
json_decref (history);
@@ -111,7 +106,7 @@ TEH_RESPONSE_compile_transaction_history (
GNUNET_JSON_pack_data_auto ("h_contract_terms",
&deposit->h_contract_terms),
GNUNET_JSON_pack_data_auto ("h_wire",
- &deposit->h_wire),
+ &h_wire),
GNUNET_JSON_pack_data_auto ("h_denom_pub",
&deposit->h_denom_pub),
GNUNET_JSON_pack_data_auto ("coin_sig",
@@ -419,7 +414,7 @@ TEH_RESPONSE_compile_transaction_history (
MHD_RESULT
TEH_RESPONSE_reply_unknown_denom_pub_hash (
struct MHD_Connection *connection,
- const struct GNUNET_HashCode *dph)
+ const struct TALER_DenominationHash *dph)
{
struct TALER_ExchangePublicKeyP epub;
struct TALER_ExchangeSignatureP esig;
@@ -466,7 +461,7 @@ TEH_RESPONSE_reply_unknown_denom_pub_hash (
MHD_RESULT
TEH_RESPONSE_reply_expired_denom_pub_hash (
struct MHD_Connection *connection,
- const struct GNUNET_HashCode *dph,
+ const struct TALER_DenominationHash *dph,
struct GNUNET_TIME_Absolute now,
enum TALER_ErrorCode ec,
const char *oper)
@@ -779,9 +774,8 @@ TEH_RESPONSE_compile_reserve_history (
&value);
TALER_amount_hton (&rcc.closing_fee,
&closing->closing_fee);
- GNUNET_CRYPTO_hash (closing->receiver_account_details,
- strlen (closing->receiver_account_details) + 1,
- &rcc.h_wire);
+ TALER_payto_hash (closing->receiver_account_details,
+ &rcc.h_payto);
if (TALER_EC_NONE !=
TEH_keys_exchange_sign (&rcc,
&pub,
diff --git a/src/exchange/taler-exchange-httpd_responses.h b/src/exchange/taler-exchange-httpd_responses.h
index b46e85ce..09d566af 100644
--- a/src/exchange/taler-exchange-httpd_responses.h
+++ b/src/exchange/taler-exchange-httpd_responses.h
@@ -59,7 +59,7 @@ TEH_RESPONSE_compile_reserve_history (
MHD_RESULT
TEH_RESPONSE_reply_unknown_denom_pub_hash (
struct MHD_Connection *connection,
- const struct GNUNET_HashCode *dph);
+ const struct TALER_DenominationHash *dph);
/**
@@ -76,7 +76,7 @@ TEH_RESPONSE_reply_unknown_denom_pub_hash (
MHD_RESULT
TEH_RESPONSE_reply_expired_denom_pub_hash (
struct MHD_Connection *connection,
- const struct GNUNET_HashCode *dph,
+ const struct TALER_DenominationHash *dph,
struct GNUNET_TIME_Absolute now,
enum TALER_ErrorCode ec,
const char *oper);
diff --git a/src/exchange/taler-exchange-httpd_transfers_get.c b/src/exchange/taler-exchange-httpd_transfers_get.c
index abf0fdbc..e63acdc2 100644
--- a/src/exchange/taler-exchange-httpd_transfers_get.c
+++ b/src/exchange/taler-exchange-httpd_transfers_get.c
@@ -51,7 +51,7 @@ struct AggregatedDepositDetail
/**
* Hash of the contract terms.
*/
- struct GNUNET_HashCode h_contract_terms;
+ struct TALER_PrivateContractHash h_contract_terms;
/**
* Coin's public key of the deposited coin.
@@ -77,7 +77,7 @@ struct AggregatedDepositDetail
* @param connection connection to the client
* @param total total amount that was transferred
* @param merchant_pub public key of the merchant
- * @param h_wire destination account
+ * @param payto_uri destination account
* @param wire_fee wire fee that was charged
* @param exec_time execution time of the wire transfer
* @param wdd_head linked list with details about the combined deposits
@@ -87,7 +87,7 @@ static MHD_RESULT
reply_transfer_details (struct MHD_Connection *connection,
const struct TALER_Amount *total,
const struct TALER_MerchantPublicKeyP *merchant_pub,
- const struct GNUNET_HashCode *h_wire,
+ const char *payto_uri,
const struct TALER_Amount *wire_fee,
struct GNUNET_TIME_Absolute exec_time,
const struct AggregatedDepositDetail *wdd_head)
@@ -145,7 +145,8 @@ reply_transfer_details (struct MHD_Connection *connection,
TALER_amount_hton (&wdp.wire_fee,
wire_fee);
wdp.merchant_pub = *merchant_pub;
- wdp.h_wire = *h_wire;
+ TALER_payto_hash (payto_uri,
+ &wdp.h_payto);
GNUNET_CRYPTO_hash_context_finish (hash_context,
&wdp.h_details);
{
@@ -172,8 +173,8 @@ reply_transfer_details (struct MHD_Connection *connection,
wire_fee),
GNUNET_JSON_pack_data_auto ("merchant_pub",
merchant_pub),
- GNUNET_JSON_pack_data_auto ("h_wire",
- h_wire),
+ GNUNET_JSON_pack_data_auto ("h_payto",
+ &wdp.h_payto),
GNUNET_JSON_pack_time_abs ("execution_time",
exec_time),
GNUNET_JSON_pack_array_steal ("deposits",
@@ -211,12 +212,6 @@ struct WtidTransactionContext
struct TALER_MerchantPublicKeyP merchant_pub;
/**
- * Hash of the wire details of the merchant (identical for all
- * deposits), only valid if @e is_valid is #GNUNET_YES.
- */
- struct GNUNET_HashCode h_wire;
-
- /**
* Wire fee applicable at @e exec_time.
*/
struct TALER_Amount wire_fee;
@@ -237,9 +232,9 @@ struct WtidTransactionContext
struct AggregatedDepositDetail *wdd_tail;
/**
- * Which method was used to wire the funds?
+ * Where were the funds wired?
*/
- char *wire_method;
+ char *payto_uri;
/**
* JSON array with details about the individual deposits.
@@ -253,7 +248,7 @@ struct WtidTransactionContext
* (as they should). Set to #GNUNET_SYSERR if we encountered an
* internal error.
*/
- int is_valid;
+ enum GNUNET_GenericReturnValue is_valid;
};
@@ -265,8 +260,7 @@ struct WtidTransactionContext
* @param cls our context for transmission
* @param rowid which row in the DB is the information from (for diagnostics), ignored
* @param merchant_pub public key of the merchant (should be same for all callbacks with the same @e cls)
- * @param h_wire hash of wire transfer details of the merchant (should be same for all callbacks with the same @e cls)
- * @param wire where the funds were sent
+ * @param account_payto_uri where the funds were sent
* @param exec_time execution time of the wire transfer (should be same for all callbacks with the same @e cls)
* @param h_contract_terms which proposal was this payment about
* @param denom_pub denomination public key of the @a coin_pub (ignored)
@@ -278,35 +272,26 @@ static void
handle_deposit_data (void *cls,
uint64_t rowid,
const struct TALER_MerchantPublicKeyP *merchant_pub,
- const struct GNUNET_HashCode *h_wire,
- const json_t *wire,
+ const char *account_payto_uri,
struct GNUNET_TIME_Absolute exec_time,
- const struct GNUNET_HashCode *h_contract_terms,
+ const struct TALER_PrivateContractHash *h_contract_terms,
const struct TALER_DenominationPublicKey *denom_pub,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_Amount *deposit_value,
const struct TALER_Amount *deposit_fee)
{
struct WtidTransactionContext *ctx = cls;
- char *wire_method;
(void) rowid;
(void) denom_pub;
if (GNUNET_SYSERR == ctx->is_valid)
return;
- if (NULL == (wire_method = TALER_JSON_wire_to_method (wire)))
- {
- GNUNET_break (0);
- ctx->is_valid = GNUNET_SYSERR;
- return;
- }
if (GNUNET_NO == ctx->is_valid)
{
/* First one we encounter, setup general information in 'ctx' */
ctx->merchant_pub = *merchant_pub;
- ctx->h_wire = *h_wire;
+ ctx->payto_uri = GNUNET_strdup (account_payto_uri);
ctx->exec_time = exec_time;
- ctx->wire_method = wire_method; /* captures the reference */
ctx->is_valid = GNUNET_YES;
if (0 >
TALER_amount_subtract (&ctx->total,
@@ -326,17 +311,13 @@ handle_deposit_data (void *cls,
(it should, otherwise the deposits should not have been aggregated) */
if ( (0 != GNUNET_memcmp (&ctx->merchant_pub,
merchant_pub)) ||
- (0 != strcmp (wire_method,
- ctx->wire_method)) ||
- (0 != GNUNET_memcmp (&ctx->h_wire,
- h_wire)) )
+ (0 != strcmp (account_payto_uri,
+ ctx->payto_uri)) )
{
GNUNET_break (0);
ctx->is_valid = GNUNET_SYSERR;
- GNUNET_free (wire_method);
return;
}
- GNUNET_free (wire_method);
if (0 >
TALER_amount_subtract (&delta,
deposit_value,
@@ -389,8 +370,7 @@ free_ctx (struct WtidTransactionContext *ctx)
wdd);
GNUNET_free (wdd);
}
- GNUNET_free (ctx->wire_method);
- ctx->wire_method = NULL;
+ GNUNET_free (ctx->payto_uri);
}
@@ -458,14 +438,29 @@ get_transfer_deposits (void *cls,
NULL);
return GNUNET_DB_STATUS_HARD_ERROR;
}
- qs = TEH_plugin->get_wire_fee (TEH_plugin->cls,
- ctx->wire_method,
- ctx->exec_time,
- &wire_fee_start_date,
- &wire_fee_end_date,
- &ctx->wire_fee,
- &closing_fee,
- &wire_fee_master_sig);
+ {
+ char *wire_method;
+
+ wire_method = TALER_payto_get_method (ctx->payto_uri);
+ if (NULL == wire_method)
+ {
+ GNUNET_break (0);
+ *mhd_ret = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_INVARIANT_FAILURE,
+ "payto:// without wire method encountered");
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ qs = TEH_plugin->get_wire_fee (TEH_plugin->cls,
+ wire_method,
+ ctx->exec_time,
+ &wire_fee_start_date,
+ &wire_fee_end_date,
+ &ctx->wire_fee,
+ &closing_fee,
+ &wire_fee_master_sig);
+ GNUNET_free (wire_method);
+ }
if (0 >= qs)
{
if ( (GNUNET_DB_STATUS_HARD_ERROR == qs) ||
@@ -530,7 +525,7 @@ TEH_handler_transfers_get (struct TEH_RequestContext *rc,
mhd_ret = reply_transfer_details (rc->connection,
&ctx.total,
&ctx.merchant_pub,
- &ctx.h_wire,
+ ctx.payto_uri,
&ctx.wire_fee,
ctx.exec_time,
ctx.wdd_head);
diff --git a/src/exchange/taler-exchange-httpd_wire.c b/src/exchange/taler-exchange-httpd_wire.c
index 8e4465ad..802204e3 100644
--- a/src/exchange/taler-exchange-httpd_wire.c
+++ b/src/exchange/taler-exchange-httpd_wire.c
@@ -22,6 +22,7 @@
#include <gnunet/gnunet_json_lib.h>
#include "taler_dbevents.h"
#include "taler-exchange-httpd_responses.h"
+#include "taler-exchange-httpd_keys.h"
#include "taler-exchange-httpd_wire.h"
#include "taler_json_lib.h"
#include "taler_mhd_lib.h"
@@ -99,6 +100,9 @@ wire_update_event_cb (void *cls,
(void) cls;
(void) extra;
(void) extra_size;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Received /wire update event\n");
+ TEH_check_invariants ();
wire_generation++;
}
@@ -387,10 +391,12 @@ get_wire_state (void)
{
struct WireStateHandle *wsh;
+ TEH_check_invariants ();
wsh = build_wire_state ();
wire_state = wsh;
if (NULL != old_wsh)
destroy_wire_state (old_wsh);
+ TEH_check_invariants ();
return wsh;
}
return old_wsh;
diff --git a/src/exchange/taler-exchange-httpd_withdraw.c b/src/exchange/taler-exchange-httpd_withdraw.c
index 4839ec97..d393567e 100644
--- a/src/exchange/taler-exchange-httpd_withdraw.c
+++ b/src/exchange/taler-exchange-httpd_withdraw.c
@@ -107,7 +107,7 @@ struct WithdrawContext
/**
* Hash of the denomination public key.
*/
- struct GNUNET_HashCode denom_pub_hash;
+ struct TALER_DenominationHash denom_pub_hash;
/**
* Signature over the request.
@@ -199,13 +199,15 @@ withdraw_transaction (void *cls,
struct WithdrawContext *wc = cls;
struct TALER_EXCHANGEDB_Reserve r;
enum GNUNET_DB_QueryStatus qs;
- struct TALER_DenominationSignature denom_sig;
+ struct TALER_BlindedDenominationSignature denom_sig;
#if OPTIMISTIC_SIGN
/* store away optimistic signature to protect
it from being overwritten by get_withdraw_info */
denom_sig = wc->collectable.sig;
- wc->collectable.sig.rsa_signature = NULL;
+ memset (&wc->collectable.sig,
+ 0,
+ sizeof (wc->collectable.sig));
#endif
qs = TEH_plugin->get_withdraw_info (TEH_plugin->cls,
&wc->wsrd.h_coin_envelope,
@@ -222,6 +224,10 @@ withdraw_transaction (void *cls,
return qs;
}
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Asked to withdraw from %s amount of %s\n",
+ TALER_B2S (&wc->wsrd.reserve_pub),
+ TALER_amount2s (&wc->amount_required));
/* Don't sign again if we have already signed the coin */
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
{
@@ -229,7 +235,7 @@ withdraw_transaction (void *cls,
optimization trade-off loses in this case: we unnecessarily computed
a signature :-( */
#if OPTIMISTIC_SIGN
- GNUNET_CRYPTO_rsa_signature_free (denom_sig.rsa_signature);
+ TALER_blinded_denom_sig_free (&denom_sig);
#endif
return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
}
@@ -304,6 +310,10 @@ withdraw_transaction (void *cls,
return GNUNET_DB_STATUS_HARD_ERROR;
}
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "KYC status is %s for %s\n",
+ wc->kyc.ok ? "ok" : "missing",
+ TALER_B2S (&r.pub));
if ( (! wc->kyc.ok) &&
(TEH_KYC_NONE != TEH_kyc_config.mode) &&
(TALER_EXCHANGEDB_KYC_W2W == wc->kyc.type) )
@@ -321,10 +331,7 @@ withdraw_transaction (void *cls,
struct TALER_Amount acc;
enum GNUNET_DB_QueryStatus qs2;
- TALER_amount_set_zero (TEH_currency,
- &acc);
- accumulate_withdraws (&acc,
- &wc->amount_required);
+ acc = wc->amount_required;
qs2 = TEH_plugin->select_withdraw_amounts_by_account (
TEH_plugin->cls,
&wc->wsrd.reserve_pub,
@@ -351,6 +358,9 @@ withdraw_transaction (void *cls,
NULL);
return GNUNET_DB_STATUS_HARD_ERROR;
}
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Amount withdrawn so far is %s\n",
+ TALER_amount2s (&acc));
if (1 == /* 1: acc > withdraw_limit */
TALER_amount_cmp (&acc,
&TEH_kyc_config.withdraw_limit))
@@ -364,14 +374,14 @@ withdraw_transaction (void *cls,
#if ! OPTIMISTIC_SIGN
if (NULL == wc->collectable.sig.rsa_signature)
{
- enum TALER_ErrorCode ec;
+ enum TALER_ErrorCode ec = TALER_EC_NONE;
wc->collectable.sig
= TEH_keys_denomination_sign (&wc->denom_pub_hash,
wc->blinded_msg,
wc->blinded_msg_len,
&ec);
- if (NULL == wc->collectable.sig.rsa_signature)
+ if (TALER_EC_NONE != ec)
{
GNUNET_break (0);
*mhd_ret = TALER_MHD_reply_with_ec (connection,
@@ -386,6 +396,10 @@ withdraw_transaction (void *cls,
wc->collectable.reserve_pub = wc->wsrd.reserve_pub;
wc->collectable.h_coin_envelope = wc->wsrd.h_coin_envelope;
wc->collectable.reserve_sig = wc->signature;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Persisting withdraw from %s over %s\n",
+ TALER_B2S (&r.pub),
+ TALER_amount2s (&wc->amount_required));
qs = TEH_plugin->insert_withdraw_info (TEH_plugin->cls,
&wc->collectable);
if (0 > qs)
@@ -530,7 +544,7 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
= htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW);
wc.wsrd.h_denomination_pub
= wc.denom_pub_hash;
- GNUNET_CRYPTO_hash (wc.blinded_msg,
+ TALER_coin_ev_hash (wc.blinded_msg,
wc.blinded_msg_len,
&wc.wsrd.h_coin_envelope);
if (GNUNET_OK !=
@@ -550,12 +564,13 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
#if OPTIMISTIC_SIGN
/* Sign before transaction! */
+ ec = TALER_EC_NONE;
wc.collectable.sig
= TEH_keys_denomination_sign (&wc.denom_pub_hash,
wc.blinded_msg,
wc.blinded_msg_len,
&ec);
- if (NULL == wc.collectable.sig.rsa_signature)
+ if (TALER_EC_NONE != ec)
{
GNUNET_break (0);
GNUNET_JSON_parse_free (spec);
@@ -579,8 +594,7 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
{
/* Even if #withdraw_transaction() failed, it may have created a signature
(or we might have done it optimistically above). */
- if (NULL != wc.collectable.sig.rsa_signature)
- GNUNET_CRYPTO_rsa_signature_free (wc.collectable.sig.rsa_signature);
+ TALER_blinded_denom_sig_free (&wc.collectable.sig);
GNUNET_JSON_parse_free (spec);
return mhd_ret;
}
@@ -591,9 +605,7 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
if (wc.kyc_denied)
{
- if (NULL != wc.collectable.sig.rsa_signature)
- GNUNET_CRYPTO_rsa_signature_free (wc.collectable.sig.rsa_signature);
-
+ TALER_blinded_denom_sig_free (&wc.collectable.sig);
return TALER_MHD_REPLY_JSON_PACK (
rc->connection,
MHD_HTTP_ACCEPTED,
@@ -607,9 +619,9 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
ret = TALER_MHD_REPLY_JSON_PACK (
rc->connection,
MHD_HTTP_OK,
- GNUNET_JSON_pack_rsa_signature ("ev_sig",
- wc.collectable.sig.rsa_signature));
- GNUNET_CRYPTO_rsa_signature_free (wc.collectable.sig.rsa_signature);
+ TALER_JSON_pack_blinded_denom_sig ("ev_sig",
+ &wc.collectable.sig));
+ TALER_blinded_denom_sig_free (&wc.collectable.sig);
return ret;
}
}