Faking the time.

Allow the user to pass a "now" value along the "/keys"
request.
This commit is contained in:
Marcello Stanisci 2019-04-03 15:20:50 +02:00
parent 41afe6fd67
commit 219f702926
No known key found for this signature in database
GPG Key ID: 8D526861953F4C0F
8 changed files with 58 additions and 29 deletions

View File

@ -274,7 +274,7 @@ verify_and_execute_deposit (struct MHD_Connection *connection,
} }
/* check denomination */ /* check denomination */
mks = TEH_KS_acquire (); mks = TEH_KS_acquire (GNUNET_TIME_absolute_get ());
if (NULL == mks) if (NULL == mks)
{ {
TALER_LOG_ERROR ("Lacking keys to operate\n"); 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 */ /* check denomination exists and is valid */
key_state = TEH_KS_acquire (); key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ());
if (NULL == key_state) if (NULL == key_state)
{ {
TALER_LOG_ERROR ("Lacking keys to operate\n"); TALER_LOG_ERROR ("Lacking keys to operate\n");

View File

@ -211,6 +211,10 @@ struct ResponseFactoryContext
*/ */
unsigned int denomkey_array_length; 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 ResponseFactoryContext *rfc = cls;
struct TEH_KS_StateHandle *key_state = rfc->key_state; struct TEH_KS_StateHandle *key_state = rfc->key_state;
struct GNUNET_TIME_Absolute now;
struct GNUNET_TIME_Absolute start; struct GNUNET_TIME_Absolute start;
struct GNUNET_TIME_Absolute horizon; struct GNUNET_TIME_Absolute horizon;
struct GNUNET_TIME_Absolute expire_deposit; struct GNUNET_TIME_Absolute expire_deposit;
@ -709,9 +712,8 @@ reload_keys_denom_iter (void *cls,
"Loading denomination key `%s' (%s)\n", "Loading denomination key `%s' (%s)\n",
alias, alias,
GNUNET_h2s (&dki->issue.properties.denom_hash)); GNUNET_h2s (&dki->issue.properties.denom_hash));
now = GNUNET_TIME_absolute_get ();
expire_deposit = GNUNET_TIME_absolute_ntoh (dki->issue.properties.expire_deposit); 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, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Skipping expired denomination key `%s'\n", "Skipping expired denomination key `%s'\n",
@ -1524,7 +1526,7 @@ reload_public_denoms_cb (void *cls,
* @return NULL on error (usually pretty fatal...) * @return NULL on error (usually pretty fatal...)
*/ */
static struct TEH_KS_StateHandle * 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 TEH_KS_StateHandle *key_state;
struct ResponseFactoryContext rfc; struct ResponseFactoryContext rfc;
@ -1551,6 +1553,7 @@ make_fresh_key_state ()
key_state = GNUNET_new (struct TEH_KS_StateHandle); key_state = GNUNET_new (struct TEH_KS_StateHandle);
rfc.key_state = key_state; rfc.key_state = key_state;
rfc.now = now;
key_state->min_dk_expire = GNUNET_TIME_UNIT_FOREVER_ABS; key_state->min_dk_expire = GNUNET_TIME_UNIT_FOREVER_ABS;
key_state->denomkey_map = GNUNET_CONTAINER_multihashmap_create (32, key_state->denomkey_map = GNUNET_CONTAINER_multihashmap_create (32,
GNUNET_NO); GNUNET_NO);
@ -1774,9 +1777,9 @@ TEH_KS_release_ (const char *location,
* @return the key state, NULL on error (usually pretty fatal) * @return the key state, NULL on error (usually pretty fatal)
*/ */
struct TEH_KS_StateHandle * 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; struct TEH_KS_StateHandle *key_state;
unsigned int rcd; unsigned int rcd;
@ -1795,7 +1798,7 @@ TEH_KS_acquire_ (const char *location)
} }
if (NULL == internal_key_state) 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 */ /* bump RC by 1 if we released internal_key_state above */
if (NULL == internal_key_state) if (NULL == internal_key_state)
{ {
@ -2041,7 +2044,7 @@ TEH_KS_loop (void)
} }
/* This will re-initialize 'internal_key_state' with /* This will re-initialize 'internal_key_state' with
an initial refcnt of 1 */ an initial refcnt of 1 */
if (NULL == TEH_KS_acquire ()) if (NULL == TEH_KS_acquire (GNUNET_TIME_absolute_get ()))
{ {
ret = GNUNET_SYSERR; ret = GNUNET_SYSERR;
break; break;
@ -2133,7 +2136,7 @@ TEH_KS_sign (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
{ {
struct TEH_KS_StateHandle *key_state; struct TEH_KS_StateHandle *key_state;
key_state = TEH_KS_acquire (); key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ());
if (NULL == key_state) if (NULL == key_state)
{ {
/* This *can* happen if the exchange's keys are /* 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; struct TEH_KS_StateHandle *key_state;
int ret; int ret;
const char *have; const char *have_cherrypick;
const char *have_fakenow;
struct GNUNET_TIME_Absolute last_issue_date; struct GNUNET_TIME_Absolute last_issue_date;
struct GNUNET_TIME_Absolute now;
const struct KeysResponseData *krd; const struct KeysResponseData *krd;
have = MHD_lookup_connection_value (connection, have_cherrypick = MHD_lookup_connection_value (connection,
MHD_GET_ARGUMENT_KIND, MHD_GET_ARGUMENT_KIND,
"last_issue_date"); "last_issue_date");
if (NULL != have) if (NULL != have_cherrypick)
{ {
unsigned long long haven; unsigned long long cherrypickn;
if (1 != if (1 !=
sscanf (have, sscanf (have_cherrypick,
"%llu", "%llu",
&haven)) &cherrypickn))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return TEH_RESPONSE_reply_arg_invalid (connection, return TEH_RESPONSE_reply_arg_invalid (connection,
TALER_EC_KEYS_HAVE_NOT_NUMERIC, 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 else
{ {
last_issue_date.abs_value_us = 0LLU; 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) if (NULL == key_state)
{ {
TALER_LOG_ERROR ("Lacking keys to operate\n"); TALER_LOG_ERROR ("Lacking keys to operate\n");

View File

@ -45,7 +45,8 @@ struct TEH_KS_StateHandle;
* @return the key state, NULL on error (usually pretty fatal) * @return the key state, NULL on error (usually pretty fatal)
*/ */
struct TEH_KS_StateHandle * 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 * For every call to #TEH_KS_acquire(), a matching call
* to #TEH_KS_release() must be made. * 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 * @return the key state
*/ */
#define TEH_KS_acquire(void) TEH_KS_acquire_(__FUNCTION__) #define TEH_KS_acquire(now) TEH_KS_acquire_(now, __FUNCTION__)
/** /**

View File

@ -318,7 +318,7 @@ verify_and_execute_payback (struct MHD_Connection *connection,
int mhd_ret; int mhd_ret;
/* check denomination exists and is in payback mode */ /* 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) if (NULL == key_state)
{ {
TALER_LOG_ERROR ("Lacking keys to operate\n"); TALER_LOG_ERROR ("Lacking keys to operate\n");

View File

@ -455,7 +455,7 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh,
} }
/* run actual logic, now that the request was parsed */ /* 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) if (NULL == key_state)
{ {
TALER_LOG_ERROR ("Lacking keys to operate\n"); TALER_LOG_ERROR ("Lacking keys to operate\n");

View File

@ -579,7 +579,7 @@ handle_refresh_reveal_json (struct MHD_Connection *connection,
int res; int res;
/* Resolve denomination hashes */ /* Resolve denomination hashes */
key_state = TEH_KS_acquire (); key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ());
if (NULL == key_state) if (NULL == key_state)
{ {
TALER_LOG_ERROR ("Lacking keys to operate\n"); TALER_LOG_ERROR ("Lacking keys to operate\n");

View File

@ -331,7 +331,7 @@ refund_transaction (void *cls,
// FIXME: do this outside of transaction function? // FIXME: do this outside of transaction function?
/* Check refund fee matches fee of denomination key! */ /* Check refund fee matches fee of denomination key! */
mks = TEH_KS_acquire (); mks = TEH_KS_acquire (GNUNET_TIME_absolute_get ());
if (NULL == mks) if (NULL == mks)
{ {
TALER_LOG_ERROR ("Lacking keys to operate\n"); TALER_LOG_ERROR ("Lacking keys to operate\n");

View File

@ -390,7 +390,7 @@ TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh,
json_decref (root); json_decref (root);
if (GNUNET_OK != res) if (GNUNET_OK != res)
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; 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) if (NULL == wc.key_state)
{ {
TALER_LOG_ERROR ("Lacking keys to operate\n"); TALER_LOG_ERROR ("Lacking keys to operate\n");