diff options
author | Christian Grothoff <christian@grothoff.org> | 2024-09-08 12:25:41 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2024-09-08 12:25:47 +0200 |
commit | 9b11a986f0e85eeec594da346f0b5e364c6b33ec (patch) | |
tree | 5a097e3dbdc2f4b665a237f35b50adcb6b2505c3 | |
parent | 1f935754bdf37f8eae5bce85283e3b3dad7eb128 (diff) |
actually rely upon taler-merchant-exchangekeyupdate in taler-merchant-httpd
-rw-r--r-- | src/backend/taler-merchant-exchangekeyupdate.c | 8 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_exchanges.c | 703 | ||||
-rw-r--r-- | src/backend/taler-merchant-kyccheck.c | 2 | ||||
-rwxr-xr-x | src/testing/test_merchant_instance_auth.sh | 1 |
4 files changed, 146 insertions, 568 deletions
diff --git a/src/backend/taler-merchant-exchangekeyupdate.c b/src/backend/taler-merchant-exchangekeyupdate.c index 4790953a..07d01d11 100644 --- a/src/backend/taler-merchant-exchangekeyupdate.c +++ b/src/backend/taler-merchant-exchangekeyupdate.c @@ -494,10 +494,6 @@ cert_cb ( struct GNUNET_TIME_Absolute n; e->conn = NULL; - /* limit retry */ - e->first_retry - = GNUNET_TIME_relative_to_absolute ( - EXCHANGE_MAXFREQ); switch (kr->hr.http_status) { case MHD_HTTP_OK: @@ -526,6 +522,10 @@ cert_cb ( e->keys = TALER_EXCHANGE_keys_incref (keys); /* Reset back-off */ e->retry_delay = EXCHANGE_MAXFREQ; + /* limit retry */ + e->first_retry + = GNUNET_TIME_relative_to_absolute ( + EXCHANGE_MAXFREQ); /* Limit by expiration */ n = GNUNET_TIME_absolute_max (e->first_retry, keys->key_data_expiration.abs_time); diff --git a/src/backend/taler-merchant-httpd_exchanges.c b/src/backend/taler-merchant-httpd_exchanges.c index 6bcbd5c8..d1397870 100644 --- a/src/backend/taler-merchant-httpd_exchanges.c +++ b/src/backend/taler-merchant-httpd_exchanges.c @@ -1,6 +1,6 @@ /* This file is part of TALER - (C) 2014-2023 Taler Systems SA + (C) 2014-2024 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 @@ -243,12 +243,7 @@ struct TMH_Exchange char *currency; /** - * A connection to this exchange - */ - struct TALER_EXCHANGE_GetKeysHandle *conn; - - /** - * The keys of this exchange + * The keys of this exchange. */ struct TALER_EXCHANGE_Keys *keys; @@ -263,70 +258,24 @@ struct TMH_Exchange struct FeesByWireMethod *wire_fees_tail; /** - * Master public key of the exchange. + * Task to retry downloading /keys again. */ - struct TALER_MasterPublicKeyP master_pub; + struct GNUNET_SCHEDULER_Task *retry_task; /** - * How soon can may we, at the earliest, re-download /keys? + * When are we willing to force downloading again? */ struct GNUNET_TIME_Absolute first_retry; /** - * How long should we wait between the next retry? + * Current exponential back-off for @e retry_task. */ struct GNUNET_TIME_Relative retry_delay; /** - * How long should we wait between the next retry for /wire? - */ - struct GNUNET_TIME_Relative wire_retry_delay; - - /** - * Task where we retry fetching /keys from the exchange. - */ - struct GNUNET_SCHEDULER_Task *retry_task; - - /** - * What state is this exchange in? + * Master public key of the exchange. */ - enum - { - - /** - * Downloading /keys failed. - */ - ESTATE_FAILED = -1, - - /** - * Nothing was ever done. - */ - ESTATE_INIT = 0, - - /** - * We are actively downloading /keys for the first time. - */ - ESTATE_DOWNLOADING_FIRST = 1, - - /** - * We finished downloading /keys and the exchange is - * ready. - */ - ESTATE_DOWNLOADED = 2, - - /** - * We are downloading /keys again after a previous - * success. - */ - ESTATE_REDOWNLOADING_SUCCESS = 3, - - /** - * We are downloading /keys again after a previous - * failure. - */ - ESTATE_REDOWNLOADING_FAILURE = 4 - - } state; + struct TALER_MasterPublicKeyP master_pub; /** * true if this exchange is from our configuration and @@ -446,7 +395,6 @@ static struct TMH_Exchange * lookup_exchange (const char *exchange_url) { struct TMH_Exchange *exchange; - enum GNUNET_DB_QueryStatus qs; for (exchange = exchange_head; NULL != exchange; @@ -459,16 +407,6 @@ lookup_exchange (const char *exchange_url) GNUNET_CONTAINER_DLL_insert (exchange_head, exchange_tail, exchange); - qs = TMH_db->select_exchange_keys (TMH_db->cls, - exchange->url, - &exchange->keys); - GNUNET_break (qs >= 0); - if (qs > 0) - exchange->state = ESTATE_DOWNLOADED; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "The exchange `%s' is new (%d)\n", - exchange_url, - exchange->state); return exchange; } @@ -539,21 +477,6 @@ set_exchange_accounts ( /** - * Function called with information about who is auditing - * a particular exchange and what key the exchange is using. - * - * @param cls closure, will be `struct TMH_Exchange` - * @param kr response details - * @param[in] keys keys object returned - */ -static void -keys_mgmt_cb ( - void *cls, - const struct TALER_EXCHANGE_KeysResponse *kr, - struct TALER_EXCHANGE_Keys *keys); - - -/** * Check if we have any remaining pending requests for the * given @a exchange, and if we have the required data, call * the callback. @@ -606,9 +529,8 @@ process_find_operations (struct TMH_Exchange *exchange) kon = NULL; GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Processing find operations for `%s' (%d)\n", - exchange->url, - exchange->state); + "Processing find operations for `%s'\n", + exchange->url); for (struct TMH_EXCHANGES_KeysOperation *ko = exchange->keys_head; NULL != ko; ko = kon) @@ -699,61 +621,6 @@ process_wire_fees ( /** - * Add account restriction @a a to array of @a restrictions. - * - * @param[in,out] restrictions JSON array to build - * @param r restriction to add to @a restrictions - * @return #GNUNET_SYSERR if @a r is malformed - */ -static enum GNUNET_GenericReturnValue -add_restriction (json_t *restrictions, - const struct TALER_EXCHANGE_AccountRestriction *r) -{ - json_t *jr; - - jr = NULL; - switch (r->type) - { - case TALER_EXCHANGE_AR_INVALID: - GNUNET_break_op (0); - return GNUNET_SYSERR; - case TALER_EXCHANGE_AR_DENY: - jr = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("type", - "deny") - ); - break; - case TALER_EXCHANGE_AR_REGEX: - jr = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ( - "type", - "regex"), - GNUNET_JSON_pack_string ( - "regex", - r->details.regex.posix_egrep), - GNUNET_JSON_pack_string ( - "human_hint", - r->details.regex.human_hint), - GNUNET_JSON_pack_object_incref ( - "human_hint_i18n", - (json_t *) r->details.regex.human_hint_i18n) - ); - break; - } - if (NULL == jr) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - GNUNET_assert (0 == - json_array_append_new (restrictions, - jr)); - return GNUNET_OK; - -} - - -/** * Retry getting keys from the given exchange in the closure. * * @param cls the `struct TMH_Exchange *` @@ -762,49 +629,23 @@ static void retry_exchange (void *cls) { struct TMH_Exchange *exchange = cls; + struct GNUNET_DB_EventHeaderP es = { + .size = ntohs (sizeof (es)), + .type = ntohs (TALER_DBEVENT_MERCHANT_EXCHANGE_FORCE_KEYS) + }; exchange->retry_task = NULL; - GNUNET_assert (NULL == exchange->conn); exchange->retry_delay = GNUNET_TIME_randomized_backoff (exchange->retry_delay, RETRY_BACKOFF_THRESHOLD); - /* Block for the duration of the long-poller */ exchange->first_retry - = GNUNET_TIME_relative_to_absolute (LONG_POLL_THRESHOLD); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Fetching /keys from exchange %s in retry_exchange()\n", - exchange->url); - switch (exchange->state) - { - case ESTATE_FAILED: - exchange->state = ESTATE_REDOWNLOADING_FAILURE; - break; - case ESTATE_INIT: - exchange->state = ESTATE_DOWNLOADING_FIRST; - break; - case ESTATE_DOWNLOADING_FIRST: - GNUNET_break (0); - return; - case ESTATE_DOWNLOADED: - exchange->state = ESTATE_REDOWNLOADING_SUCCESS; - break; - case ESTATE_REDOWNLOADING_SUCCESS: - GNUNET_break (0); - return; - case ESTATE_REDOWNLOADING_FAILURE: - GNUNET_break (0); - return; - } - exchange->conn - = TALER_EXCHANGE_get_keys ( - TMH_curl_ctx, - exchange->url, - exchange->keys, - &keys_mgmt_cb, - exchange); - /* Note: while the API spec says 'returns NULL on error', the implementation - actually never returns NULL. */ - GNUNET_break (NULL != exchange->conn); + = GNUNET_TIME_relative_to_absolute ( + exchange->retry_delay); + + TMH_db->event_notify (TMH_db->cls, + &es, + exchange->url, + strlen (exchange->url) + 1); } @@ -853,26 +694,25 @@ TMH_EXCHANGES_keys4exchange ( GNUNET_CONTAINER_DLL_insert (exchange->keys_head, exchange->keys_tail, fo); - if ( (NULL != exchange->keys) && - (! force_download) && - (GNUNET_TIME_absolute_is_future ( - exchange->keys->key_data_expiration.abs_time)) ) + if ( (NULL == exchange->keys) && + (! force_download) ) { - /* We have a valid reply, immediately return result */ GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "The exchange `%s' is ready\n", + "Waiting for `%skeys' already, failing query instantly\n", exchange->url); GNUNET_assert (NULL == fo->at); fo->at = GNUNET_SCHEDULER_add_now (&return_keys, fo); return fo; } - if ( (NULL == exchange->conn) && - ( (ESTATE_FAILED == exchange->state) || - (ESTATE_REDOWNLOADING_FAILURE == exchange->state) ) ) + if ( (NULL != exchange->keys) && + (! force_download) && + (GNUNET_TIME_absolute_is_future ( + exchange->keys->key_data_expiration.abs_time)) ) { + /* We have a valid reply, immediately return result */ GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Already waiting for `%skeys' for a while, failing query instantly\n", + "The exchange `%s' is ready\n", exchange->url); GNUNET_assert (NULL == fo->at); fo->at = GNUNET_SCHEDULER_add_now (&return_keys, @@ -881,7 +721,7 @@ TMH_EXCHANGES_keys4exchange ( } if ( (force_download) && (GNUNET_TIME_absolute_is_future (exchange->first_retry)) && - (ESTATE_DOWNLOADED == exchange->state) ) + (NULL != exchange->keys) ) { /* Return results immediately. */ fo->at = GNUNET_SCHEDULER_add_now (&return_keys, @@ -889,16 +729,14 @@ TMH_EXCHANGES_keys4exchange ( /* *no* return here, we MAY schedule a 'retry_task' in the next block if there isn't one yet */ } - if ( (NULL == exchange->retry_task) && - (NULL == exchange->conn) ) + if (NULL == exchange->retry_task) exchange->retry_task = GNUNET_SCHEDULER_add_at (exchange->first_retry, &retry_exchange, exchange); GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Next %skeys (%d) request scheduled for %s\n", + "Next %skeys request scheduled for %s\n", exchange->url, - exchange->state, GNUNET_TIME_absolute2s ( exchange->first_retry)); /* No activity to launch, we are already doing so. */ @@ -976,10 +814,9 @@ free_exchange_entry (struct TMH_Exchange *exchange) struct FeesByWireMethod *f; GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Releasing %s exchange %s (%d)\n", + "Releasing %s exchange %s\n", exchange->trusted ? "trusted" : "untrusted", - exchange->url, - exchange->state); + exchange->url); GNUNET_CONTAINER_DLL_remove (exchange_head, exchange_tail, exchange); @@ -999,11 +836,6 @@ free_exchange_entry (struct TMH_Exchange *exchange) GNUNET_free (f->wire_method); GNUNET_free (f); } - if (NULL != exchange->conn) - { - TALER_EXCHANGE_get_keys_cancel (exchange->conn); - exchange->conn = NULL; - } TALER_EXCHANGE_keys_decref (exchange->keys); exchange->keys = NULL; if (NULL != exchange->retry_task) @@ -1019,281 +851,6 @@ free_exchange_entry (struct TMH_Exchange *exchange) } -/** - * We failed downloading /keys from @a exchange. Tell clients - * about our failure, abort pending operations and retry later. - * - * @param exchange exchange that failed - */ -static void -fail_and_retry (struct TMH_Exchange *exchange) -{ - struct TMH_EXCHANGES_KeysOperation *keys; - - exchange->state = ESTATE_FAILED; - while (NULL != (keys = exchange->keys_head)) - { - keys->fc (keys->fc_cls, - NULL, - exchange); - TMH_EXCHANGES_keys4exchange_cancel (keys); - } - exchange->retry_delay - = GNUNET_TIME_randomized_backoff (exchange->retry_delay, - RETRY_BACKOFF_THRESHOLD); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to fetch /keys from `%s'; retrying in %s\n", - exchange->url, - GNUNET_STRINGS_relative_time_to_string (exchange->retry_delay, - true)); - if (NULL != exchange->retry_task) - GNUNET_SCHEDULER_cancel (exchange->retry_task); - exchange->first_retry - = GNUNET_TIME_relative_to_absolute ( - exchange->retry_delay); - exchange->retry_task - = GNUNET_SCHEDULER_add_delayed (exchange->retry_delay, - &retry_exchange, - exchange); -} - - -/** - * Update our information in the database about the - * /keys of an exchange. Run inside of a database - * transaction scope that will re-try and/or commit - * depending on the return value. - * - * @param keys information to persist - * @return transaction status - */ -static enum GNUNET_DB_QueryStatus -insert_keys_data (const struct TALER_EXCHANGE_Keys *keys) -{ - enum GNUNET_DB_QueryStatus qs; - - /* store exchange online signing keys in our DB */ - for (unsigned int i = 0; i<keys->num_sign_keys; i++) - { - struct TALER_EXCHANGE_SigningPublicKey *sign_key = &keys->sign_keys[i]; - - qs = TMH_db->insert_exchange_signkey ( - TMH_db->cls, - &keys->master_pub, - &sign_key->key, - sign_key->valid_from, - sign_key->valid_until, - sign_key->valid_legal, - &sign_key->master_sig); - /* 0 is OK, we may already have the key in the DB! */ - if (0 > qs) - { - GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); - return qs; - } - } - - qs = TMH_db->insert_exchange_keys (TMH_db->cls, - keys); - if (0 > qs) - { - GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); - return qs; - } - - qs = TMH_db->delete_exchange_accounts (TMH_db->cls, - &keys->master_pub); - if (0 > qs) - { - GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); - return qs; - } - - for (unsigned int i = 0; i<keys->accounts_len; i++) - { - const struct TALER_EXCHANGE_WireAccount *account = &keys->accounts[i]; - json_t *debit_restrictions; - json_t *credit_restrictions; - - debit_restrictions = json_array (); - GNUNET_assert (NULL != debit_restrictions); - credit_restrictions = json_array (); - GNUNET_assert (NULL != credit_restrictions); - for (unsigned int j = 0; j<account->debit_restrictions_length; j++) - { - if (GNUNET_OK != - add_restriction (debit_restrictions, - &account->debit_restrictions[j])) - { - TMH_db->rollback (TMH_db->cls); - GNUNET_break (0); - json_decref (debit_restrictions); - json_decref (credit_restrictions); - return GNUNET_DB_STATUS_HARD_ERROR; - } - } - for (unsigned int j = 0; j<account->credit_restrictions_length; j++) - { - if (GNUNET_OK != - add_restriction (credit_restrictions, - &account->credit_restrictions[j])) - { - TMH_db->rollback (TMH_db->cls); - GNUNET_break (0); - json_decref (debit_restrictions); - json_decref (credit_restrictions); - return GNUNET_DB_STATUS_HARD_ERROR; - } - } - qs = TMH_db->insert_exchange_account ( - TMH_db->cls, - &keys->master_pub, - account->payto_uri, - account->conversion_url, - debit_restrictions, - credit_restrictions, - &account->master_sig); - json_decref (debit_restrictions); - json_decref (credit_restrictions); - if (qs < 0) - { - GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); - return qs; - } - } /* end 'for all accounts' */ - - for (unsigned int i = 0; i<keys->fees_len; i++) - { - const struct TALER_EXCHANGE_WireFeesByMethod *fbm = &keys->fees[i]; - const char *wire_method = fbm->method; - const struct TALER_EXCHANGE_WireAggregateFees *fees = fbm->fees_head; - - while (NULL != fees) - { - struct GNUNET_HashCode h_wire_method; - - GNUNET_CRYPTO_hash (wire_method, - strlen (wire_method) + 1, - &h_wire_method); - qs = TMH_db->store_wire_fee_by_exchange (TMH_db->cls, - &keys->master_pub, - &h_wire_method, - &fees->fees, - fees->start_date, - fees->end_date, - &fees->master_sig); - if (0 > qs) - { - GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); - return qs; - } - fees = fees->next; - } /* all fees for this method */ - } /* for all methods (i) */ - - { - struct GNUNET_DB_EventHeaderP es = { - .size = ntohs (sizeof (es)), - .type = ntohs (TALER_DBEVENT_MERCHANT_EXCHANGE_KEYS) - }; - - TMH_db->event_notify (TMH_db->cls, - &es, - keys->exchange_url, - strlen (keys->exchange_url) + 1); - } - return qs; -} - - -static void -keys_mgmt_cb (void *cls, - const struct TALER_EXCHANGE_KeysResponse *kr, - struct TALER_EXCHANGE_Keys *keys) -{ - struct TMH_Exchange *exchange = cls; - enum GNUNET_DB_QueryStatus qs; - - exchange->conn = NULL; - if (MHD_HTTP_OK != kr->hr.http_status) - { - if (GNUNET_TIME_absolute_is_future (exchange->first_retry)) - { - /* /keys failed *before* the long polling threshold. - We apply the exponential back-off from now. */ - exchange->first_retry - = GNUNET_TIME_relative_to_absolute ( - exchange->retry_delay); - } - fail_and_retry (exchange); - TALER_EXCHANGE_keys_decref (keys); - return; - } - if (NULL == exchange->currency) - exchange->currency = GNUNET_strdup (keys->currency); - if (0 != strcmp (exchange->currency, - keys->currency)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "/keys response from `%s' is for currency `%s', but we expected `%s'\n", - exchange->url, - keys->currency, - exchange->currency); - fail_and_retry (exchange); - TALER_EXCHANGE_keys_decref (keys); - return; - } - exchange->state = ESTATE_DOWNLOADED; - TMH_db->preflight (TMH_db->cls); - for (unsigned int r = 0; r<MAX_RETRIES; r++) - { - if (GNUNET_OK != - TMH_db->start (TMH_db->cls, - "update exchange key data")) - { - TMH_db->rollback (TMH_db->cls); - GNUNET_break (0); - fail_and_retry (exchange); - TALER_EXCHANGE_keys_decref (keys); - return; - } - - qs = insert_keys_data (keys); - if (qs < 0) - { - TMH_db->rollback (TMH_db->cls); - if (GNUNET_DB_STATUS_SOFT_ERROR == qs) - continue; - GNUNET_break (0); - fail_and_retry (exchange); - TALER_EXCHANGE_keys_decref (keys); - return; - } - - qs = TMH_db->commit (TMH_db->cls); - if (qs < 0) - { - TMH_db->rollback (TMH_db->cls); - if (GNUNET_DB_STATUS_SOFT_ERROR == qs) - continue; - GNUNET_break (0); - fail_and_retry (exchange); - TALER_EXCHANGE_keys_decref (keys); - return; - } - } /* end of retry loop */ - if (qs < 0) - { - GNUNET_break (0); - fail_and_retry (exchange); - TALER_EXCHANGE_keys_decref (keys); - return; - } - TALER_EXCHANGE_keys_decref (keys); - exchange->retry_delay = GNUNET_TIME_UNIT_ZERO; -} - - enum GNUNET_GenericReturnValue TMH_EXCHANGES_lookup_wire_fee ( const struct TMH_Exchange *exchange, @@ -1326,6 +883,7 @@ TMH_exchange_check_debit ( exchange->url); return GNUNET_SYSERR; } + /* FIXME: move into convenience function in libtalerexchange? See also taler-merchant-httpd_private-get-instances-ID-kyc.c, taler-merchant-kyccheck (!) */ for (struct ExchangeAccount *acc = exchange->acc_head; NULL != acc; acc = acc->next) @@ -1432,6 +990,107 @@ TMH_test_exchange_configured_for_currency ( /** + * (Re)load of keys from DB. + * + * @param exchange exchange to reload keys of + */ +static void +reload_exchange_keys (struct TMH_Exchange *exchange) +{ + enum GNUNET_DB_QueryStatus qs; + struct TALER_EXCHANGE_Keys *keys; + + qs = TMH_db->select_exchange_keys (TMH_db->cls, + exchange->url, + &keys); + if (qs < 0) + { + GNUNET_break (0); + return; + } + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "No keys yet for `%s'\n", + exchange->url); + return; + } + exchange->retry_delay = GNUNET_TIME_UNIT_ZERO; + if (NULL == exchange->currency) + exchange->currency = GNUNET_strdup (keys->currency); + if (0 != strcmp (keys->currency, + exchange->currency)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "/keys cached in our database are for currency `%s', but we expected `%s'\n", + keys->currency, + exchange->currency); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Loaded /keys from database with %u accounts\n", + keys->accounts_len); + if (GNUNET_OK != + set_exchange_accounts (exchange, + keys->accounts_len, + keys->accounts)) + { + /* invalid account specification given */ + GNUNET_break_op (0); + /* but: we can continue anyway, things may just not + work, but probably better than to not keep going. */ + } + if (GNUNET_OK != + process_wire_fees (exchange, + &keys->master_pub, + keys->fees_len, + keys->fees)) + { + /* invalid wire fee specification given */ + GNUNET_break_op (0); + /* but: we can continue anyway, things may just not + work, but probably better than to not keep going. */ + return; + } + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Reloaded /keys of %s from database\n", + exchange->url); + TALER_EXCHANGE_keys_decref (exchange->keys); + exchange->keys = keys; + if ( (exchange->trusted) && + (0 != GNUNET_memcmp (&exchange->master_pub, + &keys->master_pub)) ) + { + /* master pub differs => do not trust the exchange (without auditor) */ + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Master public key of exchange `%s' differs from our configuration. Not trusting exchange.\n", + exchange->url); + exchange->trusted = false; + } + if (! exchange->trusted) + { + exchange->master_pub = keys->master_pub; + for (struct TMH_Exchange *e = exchange_head; + NULL != e; + e = e->next) + { + if (e == exchange) + continue; + if (! e->trusted) + continue; + if (0 == + GNUNET_memcmp (&e->master_pub, + &exchange->master_pub)) + exchange->trusted = true; /* same exchange, different URL => trust applies */ + } + } + + process_find_operations (exchange); +} + + +/** * Function called on each configuration section. Finds sections * about exchanges, parses the entries. * @@ -1484,10 +1143,7 @@ accept_exchanges (void *cls, } exchange = lookup_exchange (url); GNUNET_free (url); - if (NULL == exchange->currency) - exchange->currency = currency; - else - GNUNET_free (currency); + exchange->currency = currency; if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, section, @@ -1522,6 +1178,7 @@ accept_exchanges (void *cls, "Setup exchange %s as %s\n", exchange->url, exchange->trusted ? "trusted" : "untrusted"); + reload_exchange_keys (exchange); if (NULL != exchange->retry_task) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -1549,10 +1206,8 @@ update_exchange_keys (void *cls, const void *extra, size_t extra_len) { - enum GNUNET_DB_QueryStatus qs; const char *url = extra; struct TMH_Exchange *exchange; - struct TALER_EXCHANGE_Keys *keys; if ( (NULL == extra) || (0 == extra_len) ) @@ -1569,85 +1224,7 @@ update_exchange_keys (void *cls, "Received keys change notification: reload `%s'\n", url); exchange = lookup_exchange (url); - qs = TMH_db->select_exchange_keys (TMH_db->cls, - url, - &keys); - if (qs <= 0) - { - GNUNET_break (0); - return; - } - if (NULL == exchange->currency) - exchange->currency = GNUNET_strdup (keys->currency); - if (0 != strcmp (keys->currency, - exchange->currency)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "/keys cached in our database are for currency `%s', but we expected `%s'\n", - keys->currency, - exchange->currency); - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Loaded /keys from database with %u accounts\n", - keys->accounts_len); - if (GNUNET_OK != - set_exchange_accounts (exchange, - keys->accounts_len, - keys->accounts)) - { - /* invalid account specification given */ - GNUNET_break_op (0); - /* but: we can continue anyway, things may just not - work, but probably better than to not keep going. */ - } - if (GNUNET_OK != - process_wire_fees (exchange, - &keys->master_pub, - keys->fees_len, - keys->fees)) - { - /* invalid wire fee specification given */ - GNUNET_break_op (0); - /* but: we can continue anyway, things may just not - work, but probably better than to not keep going. */ - return; - } - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Reloaded /keys of %s from database\n", - url); - TALER_EXCHANGE_keys_decref (exchange->keys); - exchange->keys = keys; - if ( (exchange->trusted) && - (0 != GNUNET_memcmp (&exchange->master_pub, - &keys->master_pub)) ) - { - /* master pub differs => do not trust the exchange (without auditor) */ - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Master public key of exchange `%s' differs from our configuration. Not trusting exchange.\n", - exchange->url); - exchange->trusted = false; - } - if (! exchange->trusted) - { - exchange->master_pub = keys->master_pub; - for (struct TMH_Exchange *e = exchange_head; - NULL != e; - e = e->next) - { - if (e == exchange) - continue; - if (! e->trusted) - continue; - if (0 == - GNUNET_memcmp (&e->master_pub, - &exchange->master_pub)) - exchange->trusted = true; /* same exchange, different URL => trust applies */ - } - } - - process_find_operations (exchange); + reload_exchange_keys (exchange); } diff --git a/src/backend/taler-merchant-kyccheck.c b/src/backend/taler-merchant-kyccheck.c index c55b12c4..933d0984 100644 --- a/src/backend/taler-merchant-kyccheck.c +++ b/src/backend/taler-merchant-kyccheck.c @@ -645,7 +645,7 @@ is_eligible (struct TALER_EXCHANGE_Keys *keys, /* For all accounts of the exchange */ for (unsigned int i = 0; i<keys->accounts_len; i++) { - /* FIXME: move into convenience function in libtalerexchange? See also taler-merchant-httpd_private-get-instances-ID-kyc.c*/ + /* FIXME: move into convenience function in libtalerexchange? See also taler-merchant-httpd_private-get-instances-ID-kyc.c, taler-merchant-httpd_exchanges (!)*/ struct TALER_EXCHANGE_WireAccount *account = &keys->accounts[i]; bool account_restricted = false; diff --git a/src/testing/test_merchant_instance_auth.sh b/src/testing/test_merchant_instance_auth.sh index 85857b4f..1959628b 100755 --- a/src/testing/test_merchant_instance_auth.sh +++ b/src/testing/test_merchant_instance_auth.sh @@ -72,6 +72,7 @@ setup -c test_template.conf -ef -u "exchange-account-2" NEW_SECRET=secret-token:different_value +taler-merchant-exchangekeyupdate -c "${CONF}" -L DEBUG 2> taler-merchant-exchangekeyupdate.log & taler-merchant-httpd -a "${NEW_SECRET}" -c "${CONF}" -L DEBUG 2> taler-merchant-httpd.log & # Install cleanup handler (except for kill -9) trap my_cleanup EXIT |