From 219f702926c61adedea9458e07a6936e76cfe13e Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Wed, 3 Apr 2019 15:20:50 +0200 Subject: Faking the time. Allow the user to pass a "now" value along the "/keys" request. --- src/exchange/taler-exchange-httpd_deposit.c | 4 +- src/exchange/taler-exchange-httpd_keystate.c | 66 +++++++++++++++------- src/exchange/taler-exchange-httpd_keystate.h | 7 ++- src/exchange/taler-exchange-httpd_payback.c | 2 +- src/exchange/taler-exchange-httpd_refresh_melt.c | 2 +- src/exchange/taler-exchange-httpd_refresh_reveal.c | 2 +- src/exchange/taler-exchange-httpd_refund.c | 2 +- .../taler-exchange-httpd_reserve_withdraw.c | 2 +- 8 files changed, 58 insertions(+), 29 deletions(-) diff --git a/src/exchange/taler-exchange-httpd_deposit.c b/src/exchange/taler-exchange-httpd_deposit.c index 3e91218ce..2aaa3c745 100644 --- a/src/exchange/taler-exchange-httpd_deposit.c +++ b/src/exchange/taler-exchange-httpd_deposit.c @@ -274,7 +274,7 @@ verify_and_execute_deposit (struct MHD_Connection *connection, } /* check denomination */ - mks = TEH_KS_acquire (); + mks = TEH_KS_acquire (GNUNET_TIME_absolute_get ()); if (NULL == mks) { TALER_LOG_ERROR ("Lacking keys to operate\n"); @@ -479,7 +479,7 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh, } /* check denomination exists and is valid */ - key_state = TEH_KS_acquire (); + key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ()); if (NULL == key_state) { TALER_LOG_ERROR ("Lacking keys to operate\n"); diff --git a/src/exchange/taler-exchange-httpd_keystate.c b/src/exchange/taler-exchange-httpd_keystate.c index b15749ca8..0ee3806fa 100644 --- a/src/exchange/taler-exchange-httpd_keystate.c +++ b/src/exchange/taler-exchange-httpd_keystate.c @@ -211,6 +211,10 @@ struct ResponseFactoryContext */ unsigned int denomkey_array_length; + /** + * Time stamp used as "now". + */ + struct GNUNET_TIME_Absolute now; }; @@ -700,7 +704,6 @@ reload_keys_denom_iter (void *cls, { struct ResponseFactoryContext *rfc = cls; struct TEH_KS_StateHandle *key_state = rfc->key_state; - struct GNUNET_TIME_Absolute now; struct GNUNET_TIME_Absolute start; struct GNUNET_TIME_Absolute horizon; struct GNUNET_TIME_Absolute expire_deposit; @@ -709,9 +712,8 @@ reload_keys_denom_iter (void *cls, "Loading denomination key `%s' (%s)\n", alias, GNUNET_h2s (&dki->issue.properties.denom_hash)); - now = GNUNET_TIME_absolute_get (); expire_deposit = GNUNET_TIME_absolute_ntoh (dki->issue.properties.expire_deposit); - if (expire_deposit.abs_value_us < now.abs_value_us) + if (expire_deposit.abs_value_us < rfc->now.abs_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Skipping expired denomination key `%s'\n", @@ -1524,7 +1526,7 @@ reload_public_denoms_cb (void *cls, * @return NULL on error (usually pretty fatal...) */ static struct TEH_KS_StateHandle * -make_fresh_key_state () +make_fresh_key_state (struct GNUNET_TIME_Absolute now) { struct TEH_KS_StateHandle *key_state; struct ResponseFactoryContext rfc; @@ -1551,6 +1553,7 @@ make_fresh_key_state () key_state = GNUNET_new (struct TEH_KS_StateHandle); rfc.key_state = key_state; + rfc.now = now; key_state->min_dk_expire = GNUNET_TIME_UNIT_FOREVER_ABS; key_state->denomkey_map = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); @@ -1774,9 +1777,9 @@ TEH_KS_release_ (const char *location, * @return the key state, NULL on error (usually pretty fatal) */ struct TEH_KS_StateHandle * -TEH_KS_acquire_ (const char *location) +TEH_KS_acquire_ (struct GNUNET_TIME_Absolute now, + const char *location) { - struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); struct TEH_KS_StateHandle *key_state; unsigned int rcd; @@ -1795,7 +1798,7 @@ TEH_KS_acquire_ (const char *location) } if (NULL == internal_key_state) { - internal_key_state = make_fresh_key_state (); + internal_key_state = make_fresh_key_state (now); /* bump RC by 1 if we released internal_key_state above */ if (NULL == internal_key_state) { @@ -2041,7 +2044,7 @@ TEH_KS_loop (void) } /* This will re-initialize 'internal_key_state' with an initial refcnt of 1 */ - if (NULL == TEH_KS_acquire ()) + if (NULL == TEH_KS_acquire (GNUNET_TIME_absolute_get ())) { ret = GNUNET_SYSERR; break; @@ -2133,7 +2136,7 @@ TEH_KS_sign (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, { struct TEH_KS_StateHandle *key_state; - key_state = TEH_KS_acquire (); + key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ()); if (NULL == key_state) { /* This *can* happen if the exchange's keys are @@ -2195,34 +2198,57 @@ TEH_KS_handler_keys (struct TEH_RequestHandler *rh, { struct TEH_KS_StateHandle *key_state; int ret; - const char *have; + const char *have_cherrypick; + const char *have_fakenow; struct GNUNET_TIME_Absolute last_issue_date; + struct GNUNET_TIME_Absolute now; const struct KeysResponseData *krd; - have = MHD_lookup_connection_value (connection, - MHD_GET_ARGUMENT_KIND, - "last_issue_date"); - if (NULL != have) + have_cherrypick = MHD_lookup_connection_value (connection, + MHD_GET_ARGUMENT_KIND, + "last_issue_date"); + if (NULL != have_cherrypick) { - unsigned long long haven; + unsigned long long cherrypickn; if (1 != - sscanf (have, + sscanf (have_cherrypick, "%llu", - &haven)) + &cherrypickn)) { GNUNET_break_op (0); return TEH_RESPONSE_reply_arg_invalid (connection, TALER_EC_KEYS_HAVE_NOT_NUMERIC, - "have"); + "last_issue_date"); } - last_issue_date.abs_value_us = (uint64_t) haven * 1000000LLU; + last_issue_date.abs_value_us = (uint64_t) cherrypickn * 1000000LLU; } else { last_issue_date.abs_value_us = 0LLU; } - key_state = TEH_KS_acquire (); + now = GNUNET_TIME_absolute_get (); + have_fakenow = MHD_lookup_connection_value (connection, + MHD_GET_ARGUMENT_KIND, + "now"); + if (NULL != have_fakenow) + { + unsigned long long fakenown; + + if (1 != + sscanf (have_fakenow, + "%llu", + &fakenown)) + { + GNUNET_break_op (0); + return TEH_RESPONSE_reply_arg_invalid (connection, + TALER_EC_KEYS_HAVE_NOT_NUMERIC, + "now"); + } + now.abs_value_us = (uint64_t) fakenown * 1000000LLU; + } + + key_state = TEH_KS_acquire (now); if (NULL == key_state) { TALER_LOG_ERROR ("Lacking keys to operate\n"); diff --git a/src/exchange/taler-exchange-httpd_keystate.h b/src/exchange/taler-exchange-httpd_keystate.h index 29e8cd50c..62d693731 100644 --- a/src/exchange/taler-exchange-httpd_keystate.h +++ b/src/exchange/taler-exchange-httpd_keystate.h @@ -45,7 +45,8 @@ struct TEH_KS_StateHandle; * @return the key state, NULL on error (usually pretty fatal) */ struct TEH_KS_StateHandle * -TEH_KS_acquire_ (const char *location); +TEH_KS_acquire_ (struct GNUNET_TIME_Absolute now, + const char *location); /** @@ -64,9 +65,11 @@ TEH_KS_release_ (const char *location, * For every call to #TEH_KS_acquire(), a matching call * to #TEH_KS_release() must be made. * + * @param now current time snapshot; either true, or given by the + * client via the "now" URL parameter of "/keys". * @return the key state */ -#define TEH_KS_acquire(void) TEH_KS_acquire_(__FUNCTION__) +#define TEH_KS_acquire(now) TEH_KS_acquire_(now, __FUNCTION__) /** diff --git a/src/exchange/taler-exchange-httpd_payback.c b/src/exchange/taler-exchange-httpd_payback.c index 877a3ce26..2164863ee 100644 --- a/src/exchange/taler-exchange-httpd_payback.c +++ b/src/exchange/taler-exchange-httpd_payback.c @@ -318,7 +318,7 @@ verify_and_execute_payback (struct MHD_Connection *connection, int mhd_ret; /* check denomination exists and is in payback mode */ - key_state = TEH_KS_acquire (); + key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ()); if (NULL == key_state) { TALER_LOG_ERROR ("Lacking keys to operate\n"); diff --git a/src/exchange/taler-exchange-httpd_refresh_melt.c b/src/exchange/taler-exchange-httpd_refresh_melt.c index 81a8aca9e..8e776c77b 100644 --- a/src/exchange/taler-exchange-httpd_refresh_melt.c +++ b/src/exchange/taler-exchange-httpd_refresh_melt.c @@ -455,7 +455,7 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh, } /* run actual logic, now that the request was parsed */ - key_state = TEH_KS_acquire (); + key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ()); if (NULL == key_state) { TALER_LOG_ERROR ("Lacking keys to operate\n"); diff --git a/src/exchange/taler-exchange-httpd_refresh_reveal.c b/src/exchange/taler-exchange-httpd_refresh_reveal.c index 6eaa286d7..14dd12ad2 100644 --- a/src/exchange/taler-exchange-httpd_refresh_reveal.c +++ b/src/exchange/taler-exchange-httpd_refresh_reveal.c @@ -579,7 +579,7 @@ handle_refresh_reveal_json (struct MHD_Connection *connection, int res; /* Resolve denomination hashes */ - key_state = TEH_KS_acquire (); + key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ()); if (NULL == key_state) { TALER_LOG_ERROR ("Lacking keys to operate\n"); diff --git a/src/exchange/taler-exchange-httpd_refund.c b/src/exchange/taler-exchange-httpd_refund.c index 869158063..92dd54e9f 100644 --- a/src/exchange/taler-exchange-httpd_refund.c +++ b/src/exchange/taler-exchange-httpd_refund.c @@ -331,7 +331,7 @@ refund_transaction (void *cls, // FIXME: do this outside of transaction function? /* Check refund fee matches fee of denomination key! */ - mks = TEH_KS_acquire (); + mks = TEH_KS_acquire (GNUNET_TIME_absolute_get ()); if (NULL == mks) { TALER_LOG_ERROR ("Lacking keys to operate\n"); diff --git a/src/exchange/taler-exchange-httpd_reserve_withdraw.c b/src/exchange/taler-exchange-httpd_reserve_withdraw.c index 1a05326dd..370916b00 100644 --- a/src/exchange/taler-exchange-httpd_reserve_withdraw.c +++ b/src/exchange/taler-exchange-httpd_reserve_withdraw.c @@ -390,7 +390,7 @@ TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh, json_decref (root); if (GNUNET_OK != res) return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; - wc.key_state = TEH_KS_acquire (); + wc.key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ()); if (NULL == wc.key_state) { TALER_LOG_ERROR ("Lacking keys to operate\n"); -- cgit v1.2.3