diff options
Diffstat (limited to 'src/exchange')
-rw-r--r-- | src/exchange/taler-exchange-closer.c | 8 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd.c | 37 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_config.h | 2 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_deposits_get.c | 323 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_deposits_get.h | 7 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_kyc-check.c | 30 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_kyc-proof.c | 27 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_management_wire_disable.c | 5 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_management_wire_enable.c | 46 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_purses_delete.c | 26 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_purses_get.c | 32 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_reserves_get.c | 44 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_wire.c | 17 | ||||
-rw-r--r-- | src/exchange/taler-exchange-transfer.c | 6 | ||||
-rw-r--r-- | src/exchange/taler-exchange-wirewatch.c | 4 |
15 files changed, 347 insertions, 267 deletions
diff --git a/src/exchange/taler-exchange-closer.c b/src/exchange/taler-exchange-closer.c index 41c6436a..63a98bd0 100644 --- a/src/exchange/taler-exchange-closer.c +++ b/src/exchange/taler-exchange-closer.c @@ -312,10 +312,10 @@ expired_reserve_cb (void *cls, memset (&wtid, 0, sizeof (wtid)); - memcpy (&wtid, - reserve_pub, - GNUNET_MIN (sizeof (wtid), - sizeof (*reserve_pub))); + GNUNET_memcpy (&wtid, + reserve_pub, + GNUNET_MIN (sizeof (wtid), + sizeof (*reserve_pub))); qs = db_plugin->insert_reserve_closed (db_plugin->cls, reserve_pub, now, diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c index d247d981..7e11655c 100644 --- a/src/exchange/taler-exchange-httpd.c +++ b/src/exchange/taler-exchange-httpd.c @@ -542,7 +542,6 @@ handle_get_aml (struct TEH_RequestContext *rc, TALER_EC_GENERIC_DB_FETCH_FAILED, NULL); case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - GNUNET_break_op (0); return TALER_MHD_reply_with_error (rc->connection, MHD_HTTP_FORBIDDEN, TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_ACCESS_DENIED, @@ -932,9 +931,9 @@ proceed_with_handler (struct TEH_RequestContext *rc, /* Parse command-line arguments */ /* make a copy of 'url' because 'strtok_r()' will modify */ - memcpy (d, - url, - ulen); + GNUNET_memcpy (d, + url, + ulen); i = 0; args[i++] = strtok_r (d, "/", &sp); while ( (NULL != args[i - 1]) && @@ -1617,33 +1616,8 @@ handle_mhd_request (void *cls, if (0 == strcasecmp (method, MHD_HTTP_METHOD_POST)) { - const char *cl; - - /* Maybe check for maximum upload size - and refuse requests if they are just too big. */ - cl = MHD_lookup_connection_value (connection, - MHD_HEADER_KIND, - MHD_HTTP_HEADER_CONTENT_LENGTH); - if (NULL != cl) - { - unsigned long long cv; - char dummy; - - if (1 != sscanf (cl, - "%llu%c", - &cv, - &dummy)) - { - /* Not valid HTTP request, just close connection. */ - GNUNET_break_op (0); - return MHD_NO; - } - if (cv > TALER_MHD_REQUEST_BUFFER_MAX) - { - GNUNET_break_op (0); - return TALER_MHD_reply_request_too_large (connection); - } - } + TALER_MHD_check_content_length (connection, + TALER_MHD_REQUEST_BUFFER_MAX); } } @@ -2215,6 +2189,7 @@ do_shutdown (void *cls) mhd = TALER_MHD_daemon_stop (); TEH_resume_keys_requests (true); + TEH_deposits_get_cleanup (); TEH_reserves_get_cleanup (); TEH_purses_get_cleanup (); TEH_kyc_check_cleanup (); diff --git a/src/exchange/taler-exchange-httpd_config.h b/src/exchange/taler-exchange-httpd_config.h index 7763cdeb..95380e0a 100644 --- a/src/exchange/taler-exchange-httpd_config.h +++ b/src/exchange/taler-exchange-httpd_config.h @@ -41,7 +41,7 @@ * * Returned via both /config and /keys endpoints. */ -#define EXCHANGE_PROTOCOL_VERSION "14:0:2" +#define EXCHANGE_PROTOCOL_VERSION "15:0:0" /** diff --git a/src/exchange/taler-exchange-httpd_deposits_get.c b/src/exchange/taler-exchange-httpd_deposits_get.c index ebbb13e0..818900c6 100644 --- a/src/exchange/taler-exchange-httpd_deposits_get.c +++ b/src/exchange/taler-exchange-httpd_deposits_get.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2017, 2021 Taler Systems SA + Copyright (C) 2014-2023 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 @@ -23,6 +23,7 @@ #include <jansson.h> #include <microhttpd.h> #include <pthread.h> +#include "taler_dbevents.h" #include "taler_json_lib.h" #include "taler_mhd_lib.h" #include "taler_signatures.h" @@ -38,6 +39,26 @@ struct DepositWtidContext { /** + * Kept in a DLL. + */ + struct DepositWtidContext *next; + + /** + * Kept in a DLL. + */ + struct DepositWtidContext *prev; + + /** + * Context for the request we are processing. + */ + struct TEH_RequestContext *rc; + + /** + * Subscription for the database event we are waiting for. + */ + struct GNUNET_DB_EventHandler *eh; + + /** * Hash over the proposal data of the contract for which this deposit is made. */ struct TALER_PrivateContractHashP h_contract_terms; @@ -65,6 +86,12 @@ struct DepositWtidContext struct TALER_WireTransferIdentifierRawP wtid; /** + * Signature by the merchant. + */ + struct TALER_MerchantSignatureP merchant_sig; + + + /** * Set by #handle_wtid data to the coin's contribution to the wire transfer. */ struct TALER_Amount coin_contribution; @@ -80,6 +107,11 @@ struct DepositWtidContext struct GNUNET_TIME_Timestamp execution_time; /** + * Timeout of the request, for long-polling. + */ + struct GNUNET_TIME_Absolute timeout; + + /** * Set by #handle_wtid to the coin contribution to the transaction * (that is, @e coin_contribution minus @e coin_fee). */ @@ -101,10 +133,46 @@ struct DepositWtidContext * Set to #GNUNET_SYSERR if there was a serious error. */ enum GNUNET_GenericReturnValue pending; + + /** + * #GNUNET_YES if we were suspended, #GNUNET_SYSERR + * if we were woken up due to shutdown. + */ + enum GNUNET_GenericReturnValue suspended; }; /** + * Head of DLL of suspended requests. + */ +static struct DepositWtidContext *dwc_head; + +/** + * Tail of DLL of suspended requests. + */ +static struct DepositWtidContext *dwc_tail; + + +void +TEH_deposits_get_cleanup () +{ + struct DepositWtidContext *n; + for (struct DepositWtidContext *ctx = dwc_head; + NULL != ctx; + ctx = n) + { + n = ctx->next; + GNUNET_assert (GNUNET_YES == ctx->suspended); + ctx->suspended = GNUNET_SYSERR; + MHD_resume_connection (ctx->rc->connection); + GNUNET_CONTAINER_DLL_remove (dwc_head, + dwc_tail, + ctx); + } +} + + +/** * A merchant asked for details about a deposit. Provide * them. Generates the 200 reply. * @@ -228,33 +296,96 @@ deposits_get_transaction (void *cls, /** + * Function called on events received from Postgres. + * Wakes up long pollers. + * + * @param cls the `struct DepositWtidContext *` + * @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 DepositWtidContext *ctx = cls; + struct GNUNET_AsyncScopeSave old_scope; + + (void) extra; + (void) extra_size; + if (GNUNET_NO != ctx->suspended) + return; /* might get multiple wake-up events */ + GNUNET_CONTAINER_DLL_remove (dwc_head, + dwc_tail, + ctx); + GNUNET_async_scope_enter (&ctx->rc->async_scope_id, + &old_scope); + TEH_check_invariants (); + ctx->suspended = GNUNET_NO; + MHD_resume_connection (ctx->rc->connection); + TALER_MHD_daemon_trigger (); + TEH_check_invariants (); + GNUNET_async_scope_restore (&old_scope); +} + + +/** * Lookup and return the wire transfer identifier. * - * @param connection the MHD connection to handle * @param ctx context of the signed request to execute * @return MHD result code */ static MHD_RESULT handle_track_transaction_request ( - struct MHD_Connection *connection, struct DepositWtidContext *ctx) { - MHD_RESULT mhd_ret; - - if (GNUNET_OK != - TEH_DB_run_transaction (connection, - "handle deposits GET", - TEH_MT_REQUEST_OTHER, - &mhd_ret, - &deposits_get_transaction, - ctx)) - return mhd_ret; + struct MHD_Connection *connection = ctx->rc->connection; + + if ( (GNUNET_TIME_absolute_is_future (ctx->timeout)) && + (NULL == ctx->eh) ) + { + struct TALER_CoinDepositEventP rep = { + .header.size = htons (sizeof (rep)), + .header.type = htons (TALER_DBEVENT_EXCHANGE_DEPOSIT_STATUS_CHANGED), + .merchant_pub = ctx->merchant + }; + + ctx->eh = TEH_plugin->event_listen ( + TEH_plugin->cls, + GNUNET_TIME_absolute_get_remaining (ctx->timeout), + &rep.header, + &db_event_cb, + ctx); + } + { + MHD_RESULT mhd_ret; + + if (GNUNET_OK != + TEH_DB_run_transaction (connection, + "handle deposits GET", + TEH_MT_REQUEST_OTHER, + &mhd_ret, + &deposits_get_transaction, + ctx)) + return mhd_ret; + } if (GNUNET_SYSERR == ctx->pending) return TALER_MHD_reply_with_error (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_INVARIANT_FAILURE, "wire fees exceed aggregate in database"); - if (ctx->pending) + if (GNUNET_YES == ctx->pending) + { + if ( (GNUNET_TIME_absolute_is_future (ctx->timeout)) && + (GNUNET_NO == ctx->suspended) ) + { + GNUNET_CONTAINER_DLL_insert (dwc_head, + dwc_tail, + ctx); + ctx->suspended = GNUNET_YES; + MHD_suspend_connection (connection); + return MHD_YES; + } return TALER_MHD_REPLY_JSON_PACK ( connection, MHD_HTTP_ACCEPTED, @@ -270,94 +401,118 @@ handle_track_transaction_request ( ctx->kyc.ok), GNUNET_JSON_pack_timestamp ("execution_time", ctx->execution_time)); + } return reply_deposit_details (connection, ctx); } +/** + * Function called to clean up a context. + * + * @param rc request context with data to clean up + */ +static void +dwc_cleaner (struct TEH_RequestContext *rc) +{ + struct DepositWtidContext *ctx = rc->rh_ctx; + + GNUNET_assert (GNUNET_NO == ctx->suspended); + if (NULL != ctx->eh) + { + TEH_plugin->event_listen_cancel (TEH_plugin->cls, + ctx->eh); + ctx->eh = NULL; + } + GNUNET_free (ctx); +} + + MHD_RESULT TEH_handler_deposits_get (struct TEH_RequestContext *rc, const char *const args[4]) { - enum GNUNET_GenericReturnValue res; - struct TALER_MerchantSignatureP merchant_sig; - struct DepositWtidContext ctx; + struct DepositWtidContext *ctx = rc->rh_ctx; - if (GNUNET_OK != - GNUNET_STRINGS_string_to_data (args[0], - strlen (args[0]), - &ctx.h_wire, - sizeof (ctx.h_wire))) - { - GNUNET_break_op (0); - return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_H_WIRE, - args[0]); - } - if (GNUNET_OK != - GNUNET_STRINGS_string_to_data (args[1], - strlen (args[1]), - &ctx.merchant, - sizeof (ctx.merchant))) - { - GNUNET_break_op (0); - return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_MERCHANT_PUB, - args[1]); - } - if (GNUNET_OK != - GNUNET_STRINGS_string_to_data (args[2], - strlen (args[2]), - &ctx.h_contract_terms, - sizeof (ctx.h_contract_terms))) - { - GNUNET_break_op (0); - return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_H_CONTRACT_TERMS, - args[2]); - } - if (GNUNET_OK != - GNUNET_STRINGS_string_to_data (args[3], - strlen (args[3]), - &ctx.coin_pub, - sizeof (ctx.coin_pub))) - { - GNUNET_break_op (0); - return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_COIN_PUB, - args[3]); - } - res = TALER_MHD_parse_request_arg_data (rc->connection, - "merchant_sig", - &merchant_sig, - sizeof (merchant_sig)); - if (GNUNET_SYSERR == res) - return MHD_NO; /* internal error */ - if (GNUNET_NO == res) - return MHD_YES; /* parse error */ - TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++; + if (NULL == ctx) { + ctx = GNUNET_new (struct DepositWtidContext); + ctx->rc = rc; + rc->rh_ctx = ctx; + rc->rh_cleaner = &dwc_cleaner; + + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (args[0], + strlen (args[0]), + &ctx->h_wire, + sizeof (ctx->h_wire))) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (rc->connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_H_WIRE, + args[0]); + } if (GNUNET_OK != - TALER_merchant_deposit_verify (&ctx.merchant, - &ctx.coin_pub, - &ctx.h_contract_terms, - &ctx.h_wire, - &merchant_sig)) + GNUNET_STRINGS_string_to_data (args[1], + strlen (args[1]), + &ctx->merchant, + sizeof (ctx->merchant))) { GNUNET_break_op (0); return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_FORBIDDEN, - TALER_EC_EXCHANGE_DEPOSITS_GET_MERCHANT_SIGNATURE_INVALID, - NULL); + MHD_HTTP_BAD_REQUEST, + TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_MERCHANT_PUB, + args[1]); + } + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (args[2], + strlen (args[2]), + &ctx->h_contract_terms, + sizeof (ctx->h_contract_terms))) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (rc->connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_H_CONTRACT_TERMS, + args[2]); + } + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (args[3], + strlen (args[3]), + &ctx->coin_pub, + sizeof (ctx->coin_pub))) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (rc->connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_COIN_PUB, + args[3]); + } + TALER_MHD_parse_request_arg_auto_t (rc->connection, + "merchant_sig", + &ctx->merchant_sig); + TALER_MHD_parse_request_timeout (rc->connection, + &ctx->timeout); + TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++; + { + if (GNUNET_OK != + TALER_merchant_deposit_verify (&ctx->merchant, + &ctx->coin_pub, + &ctx->h_contract_terms, + &ctx->h_wire, + &ctx->merchant_sig)) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (rc->connection, + MHD_HTTP_FORBIDDEN, + TALER_EC_EXCHANGE_DEPOSITS_GET_MERCHANT_SIGNATURE_INVALID, + NULL); + } } } - return handle_track_transaction_request (rc->connection, - &ctx); + return handle_track_transaction_request (ctx); } diff --git a/src/exchange/taler-exchange-httpd_deposits_get.h b/src/exchange/taler-exchange-httpd_deposits_get.h index aee7521a..c7b1698b 100644 --- a/src/exchange/taler-exchange-httpd_deposits_get.h +++ b/src/exchange/taler-exchange-httpd_deposits_get.h @@ -27,6 +27,13 @@ /** + * Resume long pollers on GET /deposits. + */ +void +TEH_deposits_get_cleanup (void); + + +/** * Handle a "/deposits/$H_WIRE/$MERCHANT_PUB/$H_CONTRACT_TERMS/$COIN_PUB" * request. * diff --git a/src/exchange/taler-exchange-httpd_kyc-check.c b/src/exchange/taler-exchange-httpd_kyc-check.c index bf4e4dea..0372573b 100644 --- a/src/exchange/taler-exchange-httpd_kyc-check.c +++ b/src/exchange/taler-exchange-httpd_kyc-check.c @@ -520,34 +520,8 @@ TEH_handler_kyc_check ( "usertype"); } - { - 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)); - } - } + TALER_MHD_parse_request_timeout (rc->connection, + &kyp->timeout); } if ( (NULL == kyp->eh) && diff --git a/src/exchange/taler-exchange-httpd_kyc-proof.c b/src/exchange/taler-exchange-httpd_kyc-proof.c index 6d06f0c8..9668ee54 100644 --- a/src/exchange/taler-exchange-httpd_kyc-proof.c +++ b/src/exchange/taler-exchange-httpd_kyc-proof.c @@ -297,7 +297,6 @@ TEH_handler_kyc_proof ( { struct KycProofContext *kpc = rc->rh_ctx; const char *provider_section_or_logic = args[0]; - const char *h_payto; if (NULL == kpc) { @@ -310,33 +309,13 @@ TEH_handler_kyc_proof ( TALER_EC_GENERIC_ENDPOINT_UNKNOWN, "'/kyc-proof/$PROVIDER_SECTION?state=$H_PAYTO' required"); } - h_payto = MHD_lookup_connection_value (rc->connection, - MHD_GET_ARGUMENT_KIND, - "state"); - if (NULL == h_payto) - { - GNUNET_break_op (0); - return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PARAMETER_MISSING, - "h_payto"); - } kpc = GNUNET_new (struct KycProofContext); kpc->rc = rc; rc->rh_ctx = kpc; rc->rh_cleaner = &clean_kpc; - if (GNUNET_OK != - GNUNET_STRINGS_string_to_data (h_payto, - strlen (h_payto), - &kpc->h_payto, - sizeof (kpc->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"); - } + TALER_MHD_parse_request_arg_auto_t (rc->connection, + "state", + &kpc->h_payto); if (GNUNET_OK != TALER_KYCLOGIC_lookup_logic (provider_section_or_logic, &kpc->logic, diff --git a/src/exchange/taler-exchange-httpd_management_wire_disable.c b/src/exchange/taler-exchange-httpd_management_wire_disable.c index 34825eda..077a56b2 100644 --- a/src/exchange/taler-exchange-httpd_management_wire_disable.c +++ b/src/exchange/taler-exchange-httpd_management_wire_disable.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2020 Taler Systems SA + Copyright (C) 2020-2023 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 @@ -114,6 +114,9 @@ del_wire (void *cls, } qs = TEH_plugin->update_wire (TEH_plugin->cls, awc->payto_uri, + NULL, + NULL, + NULL, awc->validity_end, false); if (qs < 0) diff --git a/src/exchange/taler-exchange-httpd_management_wire_enable.c b/src/exchange/taler-exchange-httpd_management_wire_enable.c index 25ee0eea..6743b485 100644 --- a/src/exchange/taler-exchange-httpd_management_wire_enable.c +++ b/src/exchange/taler-exchange-httpd_management_wire_enable.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2020 Taler Systems SA + Copyright (C) 2020-2023 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 @@ -55,6 +55,21 @@ struct AddWireContext const char *payto_uri; /** + * (optional) address of a conversion service for this account. + */ + const char *conversion_url; + + /** + * Restrictions imposed when crediting this account. + */ + json_t *credit_restrictions; + + /** + * Restrictions imposed when debiting this account. + */ + json_t *debit_restrictions; + + /** * Timestamp for checking against replay attacks. */ struct GNUNET_TIME_Timestamp validity_start; @@ -114,11 +129,17 @@ add_wire (void *cls, if (0 == qs) qs = TEH_plugin->insert_wire (TEH_plugin->cls, awc->payto_uri, + awc->conversion_url, + awc->debit_restrictions, + awc->credit_restrictions, awc->validity_start, &awc->master_sig_wire); else qs = TEH_plugin->update_wire (TEH_plugin->cls, awc->payto_uri, + awc->conversion_url, + awc->debit_restrictions, + awc->credit_restrictions, awc->validity_start, true); if (qs < 0) @@ -141,7 +162,9 @@ TEH_handler_management_post_wire ( struct MHD_Connection *connection, const json_t *root) { - struct AddWireContext awc; + struct AddWireContext awc = { + .conversion_url = NULL + }; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_fixed_auto ("master_sig_wire", &awc.master_sig_wire), @@ -149,6 +172,14 @@ TEH_handler_management_post_wire ( &awc.master_sig_add), GNUNET_JSON_spec_string ("payto_uri", &awc.payto_uri), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_string ("conversion_url", + &awc.conversion_url), + NULL), + GNUNET_JSON_spec_json ("credit_restrictions", + &awc.credit_restrictions), + GNUNET_JSON_spec_json ("debit_restrictions", + &awc.debit_restrictions), GNUNET_JSON_spec_timestamp ("validity_start", &awc.validity_start), GNUNET_JSON_spec_end () @@ -179,17 +210,22 @@ TEH_handler_management_post_wire ( MHD_HTTP_BAD_REQUEST, TALER_EC_GENERIC_PAYTO_URI_MALFORMED, msg); + GNUNET_JSON_parse_free (spec); GNUNET_free (msg); return ret; } } if (GNUNET_OK != TALER_exchange_offline_wire_add_verify (awc.payto_uri, + awc.conversion_url, + awc.debit_restrictions, + awc.credit_restrictions, awc.validity_start, &TEH_master_public_key, &awc.master_sig_add)) { GNUNET_break_op (0); + GNUNET_JSON_parse_free (spec); return TALER_MHD_reply_with_error ( connection, MHD_HTTP_FORBIDDEN, @@ -199,10 +235,14 @@ TEH_handler_management_post_wire ( TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++; if (GNUNET_OK != TALER_exchange_wire_signature_check (awc.payto_uri, + awc.conversion_url, + awc.debit_restrictions, + awc.credit_restrictions, &TEH_master_public_key, &awc.master_sig_wire)) { GNUNET_break_op (0); + GNUNET_JSON_parse_free (spec); return TALER_MHD_reply_with_error ( connection, MHD_HTTP_FORBIDDEN, @@ -218,6 +258,7 @@ TEH_handler_management_post_wire ( GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "payto:// URI `%s' is malformed\n", awc.payto_uri); + GNUNET_JSON_parse_free (spec); return TALER_MHD_reply_with_error ( connection, MHD_HTTP_BAD_REQUEST, @@ -237,6 +278,7 @@ TEH_handler_management_post_wire ( &ret, &add_wire, &awc); + GNUNET_JSON_parse_free (spec); if (GNUNET_SYSERR == res) return ret; } diff --git a/src/exchange/taler-exchange-httpd_purses_delete.c b/src/exchange/taler-exchange-httpd_purses_delete.c index 58cc7825..5bf7c24c 100644 --- a/src/exchange/taler-exchange-httpd_purses_delete.c +++ b/src/exchange/taler-exchange-httpd_purses_delete.c @@ -57,29 +57,9 @@ TEH_handler_purses_delete ( TALER_EC_EXCHANGE_GENERIC_PURSE_PUB_MALFORMED, args[0]); } - { - const char *sig; - - sig = MHD_lookup_connection_value (connection, - MHD_HEADER_KIND, - "Taler-Purse-Signature"); - if ( (NULL == sig) || - (GNUNET_OK != - GNUNET_STRINGS_string_to_data (sig, - strlen (sig), - &purse_sig, - sizeof (purse_sig))) ) - { - GNUNET_break_op (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - (NULL == sig) - ? TALER_EC_GENERIC_PARAMETER_MISSING - : TALER_EC_GENERIC_PARAMETER_MALFORMED, - "Taler-Purse-Signature"); - } - } - + TALER_MHD_parse_request_header_auto_t (connection, + "Taler-Purse-Signature", + &purse_sig); if (GNUNET_OK != TALER_wallet_purse_delete_verify (&purse_pub, &purse_sig)) diff --git a/src/exchange/taler-exchange-httpd_purses_get.c b/src/exchange/taler-exchange-httpd_purses_get.c index 434798a8..61337235 100644 --- a/src/exchange/taler-exchange-httpd_purses_get.c +++ b/src/exchange/taler-exchange-httpd_purses_get.c @@ -243,36 +243,8 @@ TEH_handler_purses_get (struct TEH_RequestContext *rc, args[1]); } - { - const char *long_poll_timeout_ms; - - long_poll_timeout_ms - = MHD_lookup_connection_value (rc->connection, - MHD_GET_ARGUMENT_KIND, - "timeout_ms"); - if (NULL != long_poll_timeout_ms) - { - unsigned int timeout_ms; - char dummy; - struct GNUNET_TIME_Relative timeout; - - if (1 != sscanf (long_poll_timeout_ms, - "%u%c", - &timeout_ms, - &dummy)) - { - GNUNET_break_op (0); - return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PARAMETER_MALFORMED, - "timeout_ms (must be non-negative number)"); - } - timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, - timeout_ms); - gc->timeout = GNUNET_TIME_relative_to_absolute (timeout); - } - } - + TALER_MHD_parse_request_timeout (rc->connection, + &gc->timeout); if ( (GNUNET_TIME_absolute_is_future (gc->timeout)) && (NULL == gc->eh) ) { diff --git a/src/exchange/taler-exchange-httpd_reserves_get.c b/src/exchange/taler-exchange-httpd_reserves_get.c index c22e62bf..bbaac853 100644 --- a/src/exchange/taler-exchange-httpd_reserves_get.c +++ b/src/exchange/taler-exchange-httpd_reserves_get.c @@ -52,8 +52,12 @@ struct ReservePoller struct MHD_Connection *connection; /** - * Subscription for the database event we are - * waiting for. + * Our request context. + */ + struct TEH_RequestContext *rc; + + /** + * Subscription for the database event we are waiting for. */ struct GNUNET_DB_EventHandler *eh; @@ -154,6 +158,8 @@ db_event_cb (void *cls, (void) extra_size; if (! rp->suspended) return; /* might get multiple wake-up events */ + GNUNET_async_scope_enter (&rp->rc->async_scope_id, + &old_scope); TEH_check_invariants (); rp->suspended = false; MHD_resume_connection (rp->connection); @@ -171,11 +177,9 @@ TEH_handler_reserves_get (struct TEH_RequestContext *rc, if (NULL == rp) { - struct GNUNET_TIME_Relative timeout - = GNUNET_TIME_UNIT_ZERO; - rp = GNUNET_new (struct ReservePoller); rp->connection = rc->connection; + rp->rc = rc; rc->rh_ctx = rp; rc->rh_cleaner = &rp_cleanup; GNUNET_CONTAINER_DLL_insert (rp_head, @@ -193,34 +197,8 @@ TEH_handler_reserves_get (struct TEH_RequestContext *rc, TALER_EC_GENERIC_RESERVE_PUB_MALFORMED, args[0]); } - { - const char *long_poll_timeout_ms; - - long_poll_timeout_ms - = MHD_lookup_connection_value (rc->connection, - MHD_GET_ARGUMENT_KIND, - "timeout_ms"); - if (NULL != long_poll_timeout_ms) - { - unsigned int timeout_ms; - char dummy; - - if (1 != sscanf (long_poll_timeout_ms, - "%u%c", - &timeout_ms, - &dummy)) - { - GNUNET_break_op (0); - return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PARAMETER_MALFORMED, - "timeout_ms (must be non-negative number)"); - } - timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, - timeout_ms); - } - } - rp->timeout = GNUNET_TIME_relative_to_absolute (timeout); + TALER_MHD_parse_request_timeout (rc->connection, + &rp->timeout); } if ( (GNUNET_TIME_absolute_is_future (rp->timeout)) && diff --git a/src/exchange/taler-exchange-httpd_wire.c b/src/exchange/taler-exchange-httpd_wire.c index 34010462..17875a72 100644 --- a/src/exchange/taler-exchange-httpd_wire.c +++ b/src/exchange/taler-exchange-httpd_wire.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2015-2022 Taler Systems SA + Copyright (C) 2015-2023 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 @@ -224,12 +224,18 @@ TEH_wire_done () * * @param cls a `json_t *` object to expand with wire account details * @param payto_uri the exchange bank account URI to add + * @param conversion_url URL of a conversion service, NULL if there is no conversion + * @param debit_restrictions JSON array with debit restrictions on the account + * @param credit_restrictions JSON array with credit restrictions on the account * @param master_sig master key signature affirming that this is a bank * account of the exchange (of purpose #TALER_SIGNATURE_MASTER_WIRE_DETAILS) */ static void add_wire_account (void *cls, const char *payto_uri, + const char *conversion_url, + const json_t *debit_restrictions, + const json_t *credit_restrictions, const struct TALER_MasterSignatureP *master_sig) { json_t *a = cls; @@ -240,6 +246,13 @@ add_wire_account (void *cls, GNUNET_JSON_PACK ( GNUNET_JSON_pack_string ("payto_uri", payto_uri), + GNUNET_JSON_pack_allow_null ( + GNUNET_JSON_pack_string ("conversion_url", + conversion_url)), + GNUNET_JSON_pack_array_incref ("debit_restrictions", + (json_t *) debit_restrictions), + GNUNET_JSON_pack_array_incref ("credit_restrictions", + (json_t *) credit_restrictions), GNUNET_JSON_pack_data_auto ("master_sig", master_sig)))) { @@ -462,6 +475,8 @@ build_wire_state (void) wsh->wire_reply = TALER_MHD_MAKE_JSON_PACK ( GNUNET_JSON_pack_array_steal ("accounts", wire_accounts_array), + GNUNET_JSON_pack_array_steal ("wads", /* #7271 */ + json_array ()), GNUNET_JSON_pack_object_steal ("fees", wire_fee_object), GNUNET_JSON_pack_data_auto ("master_public_key", diff --git a/src/exchange/taler-exchange-transfer.c b/src/exchange/taler-exchange-transfer.c index 5a4aace9..255fe76a 100644 --- a/src/exchange/taler-exchange-transfer.c +++ b/src/exchange/taler-exchange-transfer.c @@ -563,9 +563,9 @@ wire_prepare_cb (void *cls, } wpd = GNUNET_malloc (sizeof (struct WirePrepareData) + buf_size); - memcpy (&wpd[1], - buf, - buf_size); + GNUNET_memcpy (&wpd[1], + buf, + buf_size); wpd->buf_size = buf_size; wpd->row_id = rowid; GNUNET_CONTAINER_DLL_insert (wpd_head, diff --git a/src/exchange/taler-exchange-wirewatch.c b/src/exchange/taler-exchange-wirewatch.c index 235c0153..04704242 100644 --- a/src/exchange/taler-exchange-wirewatch.c +++ b/src/exchange/taler-exchange-wirewatch.c @@ -731,8 +731,8 @@ history_cb (void *cls, { case MHD_HTTP_OK: process_reply (wrap_size, - reply->details.success.details, - reply->details.success.details_length); + reply->details.ok.details, + reply->details.ok.details_length); return; case MHD_HTTP_NO_CONTENT: transaction_completed (); |