aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/exchange/taler-exchange-httpd_keystate.c138
1 files changed, 106 insertions, 32 deletions
diff --git a/src/exchange/taler-exchange-httpd_keystate.c b/src/exchange/taler-exchange-httpd_keystate.c
index 164f61abb..41c004593 100644
--- a/src/exchange/taler-exchange-httpd_keystate.c
+++ b/src/exchange/taler-exchange-httpd_keystate.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014, 2015 GNUnet e.V.
+ Copyright (C) 2014-2017 GNUnet e.V.
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
@@ -59,6 +59,12 @@ struct TEH_KS_StateHandle
json_t *auditors_array;
/**
+ * JSON array with revoked denomination keys. (Currently not really used
+ * after initialization).
+ */
+ json_t *payback_array;
+
+ /**
* Cached JSON text that the exchange will send for a "/keys" request.
* Includes our @e TEH_master_public_key public key, the signing and
* denomination keys as well as the @e reload_time.
@@ -72,6 +78,12 @@ struct TEH_KS_StateHandle
struct GNUNET_CONTAINER_MultiHashMap *denomkey_map;
/**
+ * Mapping from revoked denomination keys to denomination key issue struct.
+ * Used to lookup the key by hash.
+ */
+ struct GNUNET_CONTAINER_MultiHashMap *revoked_map;
+
+ /**
* Hash context we used to combine the hashes of all denomination
* keys into one big hash.
*/
@@ -205,6 +217,45 @@ TALER_EXCHANGE_conf_duration_provide ()
/**
+ * Store a copy of @a dki in @a map.
+ *
+ * @param map hash map to store @a dki in
+ * @param dki information to store in @a map
+ * @return #GNUNET_OK on success,
+ * #GNUNET_NO if such an entry already exists
+ */
+static int
+store_in_map (struct GNUNET_CONTAINER_MultiHashMap *map,
+ const struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki)
+{
+ struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *d2;
+ int res;
+
+ d2 = GNUNET_new (struct TALER_EXCHANGEDB_DenominationKeyIssueInformation);
+ d2->issue = dki->issue;
+ d2->denom_priv.rsa_private_key
+ = GNUNET_CRYPTO_rsa_private_key_dup (dki->denom_priv.rsa_private_key);
+ d2->denom_pub.rsa_public_key
+ = GNUNET_CRYPTO_rsa_public_key_dup (dki->denom_pub.rsa_public_key);
+ res = GNUNET_CONTAINER_multihashmap_put (map,
+ &d2->issue.properties.denom_hash,
+ d2,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
+ if (GNUNET_OK != res)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Duplicate denomination key `%s'\n",
+ GNUNET_h2s (&d2->issue.properties.denom_hash));
+ GNUNET_CRYPTO_rsa_private_key_free (d2->denom_priv.rsa_private_key);
+ GNUNET_CRYPTO_rsa_public_key_free (d2->denom_pub.rsa_public_key);
+ GNUNET_free (d2);
+ return GNUNET_NO;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
* Iterator for (re)loading/initializing denomination keys.
*
* @param cls closure
@@ -226,28 +277,38 @@ reload_keys_denom_iter (void *cls,
struct GNUNET_TIME_Absolute horizon;
struct GNUNET_TIME_Absolute expire_deposit;
struct GNUNET_HashCode denom_key_hash;
- struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *d2;
struct TALER_EXCHANGEDB_Session *session;
int res;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Loading denomination key `%s'\n",
alias);
- horizon = GNUNET_TIME_relative_to_absolute (TALER_EXCHANGE_conf_duration_provide ());
- if (GNUNET_TIME_absolute_ntoh (dki->issue.properties.start).abs_value_us >
- horizon.abs_value_us)
+ 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)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Skipping future denomination key `%s'\n",
+ "Skipping expired denomination key `%s'\n",
alias);
return GNUNET_OK;
}
- 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 (GNUNET_YES == was_revoked)
+ {
+ res = store_in_map (ctx->revoked_map,
+ dki);
+ if (GNUNET_NO == res)
+ return GNUNET_OK;
+ GNUNET_assert (0 ==
+ json_array_append_new (ctx->payback_array,
+ GNUNET_JSON_from_data_auto (&dki->issue.properties.denom_hash)));
+ return GNUNET_OK;
+ }
+ horizon = GNUNET_TIME_relative_to_absolute (TALER_EXCHANGE_conf_duration_provide ());
+ if (GNUNET_TIME_absolute_ntoh (dki->issue.properties.start).abs_value_us >
+ horizon.abs_value_us)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Skipping expired denomination key `%s'\n",
+ "Skipping future denomination key `%s'\n",
alias);
return GNUNET_OK;
}
@@ -327,26 +388,10 @@ reload_keys_denom_iter (void *cls,
as it is possible we just retry until we succeed. */
}
- d2 = GNUNET_new (struct TALER_EXCHANGEDB_DenominationKeyIssueInformation);
- d2->issue = dki->issue;
- d2->denom_priv.rsa_private_key
- = GNUNET_CRYPTO_rsa_private_key_dup (dki->denom_priv.rsa_private_key);
- d2->denom_pub.rsa_public_key
- = GNUNET_CRYPTO_rsa_public_key_dup (dki->denom_pub.rsa_public_key);
- res = GNUNET_CONTAINER_multihashmap_put (ctx->denomkey_map,
- &denom_key_hash,
- d2,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
- if (GNUNET_OK != res)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Duplicate denomination key `%s'\n",
- alias);
- GNUNET_CRYPTO_rsa_private_key_free (d2->denom_priv.rsa_private_key);
- GNUNET_CRYPTO_rsa_public_key_free (d2->denom_pub.rsa_public_key);
- GNUNET_free (d2);
+ res = store_in_map (ctx->denomkey_map,
+ dki);
+ if (GNUNET_NO == res)
return GNUNET_OK;
- }
ctx->min_dk_expire = GNUNET_TIME_absolute_min (ctx->min_dk_expire,
expire_deposit);
GNUNET_assert (0 ==
@@ -594,6 +639,11 @@ ks_release_ (struct TEH_KS_StateHandle *key_state)
json_decref (key_state->denom_keys_array);
key_state->denom_keys_array = NULL;
}
+ if (NULL != key_state->payback_array)
+ {
+ json_decref (key_state->payback_array);
+ key_state->payback_array = NULL;
+ }
if (NULL != key_state->sign_keys_array)
{
json_decref (key_state->sign_keys_array);
@@ -607,6 +657,14 @@ ks_release_ (struct TEH_KS_StateHandle *key_state)
GNUNET_CONTAINER_multihashmap_destroy (key_state->denomkey_map);
key_state->denomkey_map = NULL;
}
+ if (NULL != key_state->revoked_map)
+ {
+ GNUNET_CONTAINER_multihashmap_iterate (key_state->revoked_map,
+ &free_denom_key,
+ key_state);
+ GNUNET_CONTAINER_multihashmap_destroy (key_state->revoked_map);
+ key_state->revoked_map = NULL;
+ }
GNUNET_free_non_null (key_state->keys_json);
GNUNET_free (key_state);
}
@@ -662,6 +720,9 @@ TEH_KS_acquire_ (const char *location)
key_state->denom_keys_array = json_array ();
GNUNET_assert (NULL != key_state->denom_keys_array);
+ key_state->payback_array = json_array ();
+ GNUNET_assert (NULL != key_state->payback_array);
+
key_state->sign_keys_array = json_array ();
GNUNET_assert (NULL != key_state->sign_keys_array);
@@ -670,6 +731,8 @@ TEH_KS_acquire_ (const char *location)
key_state->denomkey_map = GNUNET_CONTAINER_multihashmap_create (32,
GNUNET_NO);
+ key_state->revoked_map = GNUNET_CONTAINER_multihashmap_create (4,
+ GNUNET_NO);
key_state->reload_time = GNUNET_TIME_absolute_get ();
GNUNET_TIME_round_abs (&key_state->reload_time);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -731,6 +794,7 @@ TEH_KS_acquire_ (const char *location)
GNUNET_JSON_from_data_auto (&TEH_master_public_key),
"signkeys", key_state->sign_keys_array,
"denoms", key_state->denom_keys_array,
+ "payback", key_state->payback_array,
"auditors", key_state->auditors_array,
"list_issue_date", GNUNET_JSON_from_time_abs (key_state->reload_time),
"eddsa_pub", GNUNET_JSON_from_data_auto (&key_state->current_sign_key_issue.issue.signkey_pub),
@@ -739,6 +803,7 @@ TEH_KS_acquire_ (const char *location)
key_state->auditors_array = NULL;
key_state->sign_keys_array = NULL;
key_state->denom_keys_array = NULL;
+ key_state->payback_array = NULL;
key_state->keys_json = json_dumps (keys,
JSON_INDENT (2));
GNUNET_assert (NULL != key_state->keys_json);
@@ -770,10 +835,12 @@ TEH_KS_denomination_key_lookup (const struct TEH_KS_StateHandle *key_state,
struct GNUNET_HashCode hc;
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
struct GNUNET_TIME_Absolute now;
+ const struct GNUNET_CONTAINER_MultiHashMap *map;
GNUNET_CRYPTO_rsa_public_key_hash (denom_pub->rsa_public_key,
&hc);
- dki = GNUNET_CONTAINER_multihashmap_get (key_state->denomkey_map,
+ map = (TEH_KS_DKU_PAYBACK == use) ? key_state->revoked_map : key_state->denomkey_map;
+ dki = GNUNET_CONTAINER_multihashmap_get (map,
&hc);
if (NULL == dki)
return NULL;
@@ -810,8 +877,15 @@ TEH_KS_denomination_key_lookup (const struct TEH_KS_StateHandle *key_state,
}
break;
case TEH_KS_DKU_PAYBACK:
- GNUNET_break (0); /* not implemented (#3887) */
- return NULL;
+ if (now.abs_value_us >
+ GNUNET_TIME_absolute_ntoh (dki->issue.properties.expire_deposit).abs_value_us)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Not returning DKI for %s, as time to payback coin has passed\n",
+ GNUNET_h2s (&hc));
+ return NULL;
+ }
+ break;
}
return dki;
}