diff options
author | Christian Grothoff <christian@grothoff.org> | 2019-06-26 23:58:48 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2019-06-27 00:04:20 +0200 |
commit | 19e0b66f8780f97f15f0a40a739eb277244750f1 (patch) | |
tree | 1823f46f36a74e7b54bbc4be4640eef5a95a666d | |
parent | 9a69fd81ed1eb5de13509f565947f01de8bdf38c (diff) | |
download | exchange-19e0b66f8780f97f15f0a40a739eb277244750f1.tar.xz |
first steps on #5777
-rw-r--r-- | src/exchange/taler-exchange-httpd_keystate.c | 13 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_keystate.h | 9 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_refresh_melt.c | 61 | ||||
-rw-r--r-- | src/exchangedb/plugin_exchangedb_postgres.c | 3 |
4 files changed, 82 insertions, 4 deletions
diff --git a/src/exchange/taler-exchange-httpd_keystate.c b/src/exchange/taler-exchange-httpd_keystate.c index 24eef36ea..7d67b8768 100644 --- a/src/exchange/taler-exchange-httpd_keystate.c +++ b/src/exchange/taler-exchange-httpd_keystate.c @@ -1907,6 +1907,9 @@ TEH_KS_denomination_key_lookup_by_hash (const struct TEH_KS_StateHandle *key_sta map = (TEH_KS_DKU_PAYBACK == use) ? key_state->revoked_map : key_state->denomkey_map; dki = GNUNET_CONTAINER_multihashmap_get (map, denom_pub_hash); + if ( (NULL == dki) && (TEH_KS_DKU_ZOMBIE == use)) + dki = GNUNET_CONTAINER_multihashmap_get (key_state->revoked_map, + denom_pub_hash); if (NULL == dki) return NULL; now = GNUNET_TIME_absolute_get (); @@ -1958,6 +1961,16 @@ TEH_KS_denomination_key_lookup_by_hash (const struct TEH_KS_StateHandle *key_sta return NULL; } break; + case TEH_KS_DKU_ZOMBIE: + if (now.abs_value_us > + GNUNET_TIME_absolute_ntoh (dki->issue.properties.expire_legal).abs_value_us) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Not returning DKI for %s, as legal expiration of coin has passed\n", + GNUNET_h2s (denom_pub_hash)); + return NULL; + } + break; } return dki; } diff --git a/src/exchange/taler-exchange-httpd_keystate.h b/src/exchange/taler-exchange-httpd_keystate.h index e197e7acc..6f5d338cb 100644 --- a/src/exchange/taler-exchange-httpd_keystate.h +++ b/src/exchange/taler-exchange-httpd_keystate.h @@ -109,7 +109,14 @@ enum TEH_KS_DenominationKeyUse { /** * The key is to be used for a /payback operation. */ - TEH_KS_DKU_PAYBACK + TEH_KS_DKU_PAYBACK, + + /** + * The key is to be used for a /refresh/payback operation, + * i.e. it is an old coin that regained value from a + * payback on a new coin derived from the old coin. + */ + TEH_KS_DKU_ZOMBIE }; diff --git a/src/exchange/taler-exchange-httpd_refresh_melt.c b/src/exchange/taler-exchange-httpd_refresh_melt.c index 36ad1a738..5674a12f8 100644 --- a/src/exchange/taler-exchange-httpd_refresh_melt.c +++ b/src/exchange/taler-exchange-httpd_refresh_melt.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2019 Inria & GNUnet e.V. + Copyright (C) 2014-2019 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 @@ -173,12 +173,12 @@ refresh_check_melt (struct MHD_Connection *connection, session, &rmc->refresh_session.coin.coin_pub, GNUNET_NO, - &tl); + &tl); if (0 > qs) { if (GNUNET_DB_STATUS_HARD_ERROR == qs) *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_REFRESH_MELT_DB_FETCH_ERROR); + TALER_EC_REFRESH_MELT_DB_FETCH_ERROR); return qs; } if (GNUNET_OK != @@ -453,9 +453,64 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh, "no keys"); goto cleanup; } + + /* Baseline: check if deposits/refreshs are generally + simply still allowed for this denomination */ rmc.dki = TEH_KS_denomination_key_lookup_by_hash (key_state, &rmc.refresh_session.coin.denom_pub_hash, TEH_KS_DKU_DEPOSIT); + /* Consider case that denomination was revoked but + this coin was already seen and thus refresh is OK. */ + if (NULL == rmc.dki) + { + struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki; + + dki = TEH_KS_denomination_key_lookup_by_hash (key_state, + &rmc.refresh_session.coin.denom_pub_hash, + TEH_KS_DKU_PAYBACK); + if (NULL != dki) + { + struct TALER_CoinPublicInfo coin_info; + enum GNUNET_DB_QueryStatus qs; + + qs = TEH_plugin->get_known_coin (TEH_plugin->cls, + NULL, + &rmc.refresh_session.coin.coin_pub, + &coin_info); + if (0 > qs) + { + GNUNET_break (0); + res = TEH_RESPONSE_reply_internal_db_error (connection, + TALER_EC_REFRESH_MELT_DB_FETCH_ERROR); + goto cleanup; + } + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) + { + /* Coin was known beforehand, so we should allow the refresh */ + rmc.dki = dki; + GNUNET_CRYPTO_rsa_signature_free (coin_info.denom_sig.rsa_signature); + } + } + } + + /* Consider the case that the denomination expired for deposits, + but /refresh/payback refilled the balance of the 'zombie' coin + and we should thus allow the refresh during the legal period. */ + if (NULL == rmc.dki) + { + struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki; + + dki = TEH_KS_denomination_key_lookup_by_hash (key_state, + &rmc.refresh_session.coin.denom_pub_hash, + TEH_KS_DKU_ZOMBIE); + if (NULL != dki) + { + /* Test if zombie-condition is actually satisfied for the coin */ + if (0 /* FIXME: test if zombie-satisfied */) + rmc.dki = dki; + } + } + if (NULL == rmc.dki) { TALER_LOG_WARNING ("Unknown denomination key in /refresh/melt request\n"); diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index a8b2e36c6..b4c2d49d8 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -3304,6 +3304,7 @@ postgres_get_known_coin (void *cls, const struct TALER_CoinSpendPublicKeyP *coin_pub, struct TALER_CoinPublicInfo *coin_info) { + struct PostgresClosure *pc = cls; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_auto_from_type (coin_pub), GNUNET_PQ_query_param_end @@ -3320,6 +3321,8 @@ postgres_get_known_coin (void *cls, "Getting known coin data for coin %s\n", TALER_B2S (coin_pub)); coin_info->coin_pub = *coin_pub; + if (NULL == session) + session = postgres_get_session (pc); return GNUNET_PQ_eval_prepared_singleton_select (session->conn, "get_known_coin", params, |