Compare commits
4 Commits
1090389d6f
...
1b1a6c142a
Author | SHA1 | Date | |
---|---|---|---|
1b1a6c142a | |||
632d17f642 | |||
d02b5e213a | |||
f8b1c3f8db |
@ -152,6 +152,10 @@ static char *currency;
|
||||
*/
|
||||
static char *CFG_exchange_url;
|
||||
|
||||
/**
|
||||
* If age restriction is enabled, the age mask to be used
|
||||
*/
|
||||
static struct TALER_AgeMask age_mask = {0};
|
||||
|
||||
/**
|
||||
* A subcommand supported by this program.
|
||||
@ -3037,6 +3041,7 @@ do_show (char *const *args)
|
||||
keys = parse_keys_input ("show");
|
||||
if (NULL == keys)
|
||||
return;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
load_offline_key (GNUNET_NO))
|
||||
return;
|
||||
@ -3197,6 +3202,43 @@ sign_signkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Looks up the AGE_RESTRICTED setting for a denomination in the config and
|
||||
* returns the age restriction (mask) accordingly.
|
||||
*
|
||||
* @param section_name Section in the configuration for the particular
|
||||
* denomination.
|
||||
*/
|
||||
static struct TALER_AgeMask
|
||||
load_age_mask (const char*section_name)
|
||||
{
|
||||
static const struct TALER_AgeMask null_mask = {0};
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
|
||||
if (age_mask.mask == 0)
|
||||
return null_mask;
|
||||
|
||||
if (GNUNET_OK != (GNUNET_CONFIGURATION_have_value (
|
||||
kcfg,
|
||||
section_name,
|
||||
"AGE_RESTRICTED")))
|
||||
return null_mask;
|
||||
|
||||
ret = GNUNET_CONFIGURATION_get_value_yesno (kcfg,
|
||||
section_name,
|
||||
"AGE_RESTRICTED");
|
||||
if (GNUNET_YES == ret)
|
||||
return age_mask;
|
||||
|
||||
if (GNUNET_SYSERR == ret)
|
||||
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
|
||||
section_name,
|
||||
"AGE_RESTRICTED",
|
||||
"Value must be YES or NO\n");
|
||||
return null_mask;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sign @a denomkeys with offline key.
|
||||
*
|
||||
@ -3285,7 +3327,10 @@ sign_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub,
|
||||
duration = GNUNET_TIME_absolute_get_difference (
|
||||
stamp_start.abs_time,
|
||||
stamp_expire_withdraw.abs_time);
|
||||
// FIXME-Oec: setup age mask here?
|
||||
|
||||
/* Load the age mask, if applicable to this denomination */
|
||||
denom_pub.age_mask = load_age_mask (section_name);
|
||||
|
||||
TALER_denom_pub_hash (&denom_pub,
|
||||
&h_denom_pub);
|
||||
switch (denom_pub.cipher)
|
||||
@ -3519,14 +3564,6 @@ do_extensions_show (char *const *args)
|
||||
json_t *exts = json_object ();
|
||||
const struct TALER_Extension *it;
|
||||
|
||||
TALER_extensions_init ();
|
||||
if (GNUNET_OK != TALER_extensions_load_taler_config (kcfg))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"error while loading taler config for extensions\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (it = TALER_extensions_get_head ();
|
||||
NULL != it;
|
||||
it = it->next)
|
||||
@ -3780,6 +3817,17 @@ run (void *cls,
|
||||
global_ret = EXIT_NOTCONFIGURED;
|
||||
return;
|
||||
}
|
||||
|
||||
/* load age mask, if age restriction is enabled */
|
||||
TALER_extensions_init ();
|
||||
if (GNUNET_OK != TALER_extensions_load_taler_config (kcfg))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"error while loading taler config for extensions\n");
|
||||
return;
|
||||
}
|
||||
age_mask = TALER_extensions_age_restriction_ageMask ();
|
||||
|
||||
ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
|
||||
&rc);
|
||||
rc = GNUNET_CURL_gnunet_rc_create (ctx);
|
||||
|
@ -157,6 +157,12 @@ TEH_extensions_init ()
|
||||
it = it->next)
|
||||
extension_update_event_cb (NULL, &it->type, sizeof(it->type));
|
||||
|
||||
/* FIXME: shall we load the extensions from the config right away?
|
||||
* We do have to for now, as otherwise denominations with age restriction
|
||||
* will not have the age mask set right upon initial generation.
|
||||
*/
|
||||
TALER_extensions_load_taler_config (TEH_cfg);
|
||||
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
@ -743,43 +743,30 @@ static struct TALER_AgeMask
|
||||
load_age_mask (const char*section_name)
|
||||
{
|
||||
static const struct TALER_AgeMask null_mask = {0};
|
||||
struct TALER_AgeMask age_mask = {0};
|
||||
/* TODO: optimize by putting this into global? */
|
||||
const struct TALER_Extension *age_ext =
|
||||
TALER_extensions_get_by_type (TALER_Extension_AgeRestriction);
|
||||
|
||||
// Get the age mask from the extension, if configured
|
||||
/* TODO: optimize by putting this into global? */
|
||||
if (TALER_extensions_is_enabled (age_ext))
|
||||
age_mask = *(struct TALER_AgeMask *) age_ext->config;
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
struct TALER_AgeMask age_mask = TALER_extensions_age_restriction_ageMask ();
|
||||
|
||||
if (age_mask.mask == 0)
|
||||
{
|
||||
/* Age restriction support is not enabled. Ignore the AGE_RESTRICTED field
|
||||
* for the particular denomination and simply return the null_mask
|
||||
*/
|
||||
return null_mask;
|
||||
}
|
||||
|
||||
if (GNUNET_OK == (GNUNET_CONFIGURATION_have_value (
|
||||
if (GNUNET_OK != (GNUNET_CONFIGURATION_have_value (
|
||||
TEH_cfg,
|
||||
section_name,
|
||||
"AGE_RESTRICTED")))
|
||||
{
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
if (GNUNET_SYSERR == (ret = GNUNET_CONFIGURATION_get_value_yesno (TEH_cfg,
|
||||
section_name,
|
||||
"AGE_RESTRICTED")))
|
||||
{
|
||||
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
|
||||
section_name,
|
||||
"AGE_RESTRICTED",
|
||||
"Value must be YES or NO\n");
|
||||
return null_mask;
|
||||
}
|
||||
}
|
||||
return null_mask;
|
||||
|
||||
return age_mask;
|
||||
ret = GNUNET_CONFIGURATION_get_value_yesno (TEH_cfg,
|
||||
section_name,
|
||||
"AGE_RESTRICTED");
|
||||
if (GNUNET_YES == ret)
|
||||
return age_mask;
|
||||
|
||||
if (GNUNET_SYSERR == ret)
|
||||
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
|
||||
section_name,
|
||||
"AGE_RESTRICTED",
|
||||
"Value must be YES or NO\n");
|
||||
return null_mask;
|
||||
}
|
||||
|
||||
|
||||
@ -1187,6 +1174,8 @@ denomination_info_cb (
|
||||
dk->meta = *meta;
|
||||
dk->master_sig = *master_sig;
|
||||
dk->recoup_possible = recoup_possible;
|
||||
dk->denom_pub.age_mask = meta->age_mask;
|
||||
|
||||
GNUNET_assert (
|
||||
GNUNET_OK ==
|
||||
GNUNET_CONTAINER_multihashmap_put (ksh->denomkey_map,
|
||||
@ -1601,7 +1590,7 @@ setup_general_response_headers (struct TEH_KeyStateHandle *ksh,
|
||||
* @a recoup and @a denoms.
|
||||
*
|
||||
* @param[in,out] ksh key state handle we build @a krd for
|
||||
* @param[in] denom_keys_hash hash over all the denominatoin keys in @a denoms
|
||||
* @param[in] denom_keys_hash hash over all the denominatoin keys in @a denoms and age_restricted_denoms
|
||||
* @param last_cpd timestamp to use
|
||||
* @param signkeys list of sign keys to return
|
||||
* @param recoup list of revoked keys to return
|
||||
@ -1771,7 +1760,7 @@ create_krd (struct TEH_KeyStateHandle *ksh,
|
||||
GNUNET_assert (0 == r);
|
||||
}
|
||||
|
||||
// Special case for age restrictions: if enabled, provide the lits of
|
||||
// Special case for age restrictions: if enabled, provide the list of
|
||||
// age-restricted denominations.
|
||||
if (age_restriction_enabled &&
|
||||
NULL != age_restricted_denoms)
|
||||
@ -1857,9 +1846,11 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
|
||||
json_t *age_restricted_denoms = NULL;
|
||||
struct GNUNET_TIME_Timestamp last_cpd;
|
||||
struct GNUNET_CONTAINER_Heap *heap;
|
||||
struct GNUNET_HashContext *hash_context;
|
||||
struct GNUNET_HashContext *hash_context = NULL;
|
||||
struct GNUNET_HashContext *hash_context_restricted = NULL;
|
||||
bool age_restriction_active =
|
||||
TALER_extensions_is_enabled_type (TALER_Extension_AgeRestriction);
|
||||
bool have_age_restricted_denoms = false;
|
||||
|
||||
sctx.signkeys = json_array ();
|
||||
GNUNET_assert (NULL != sctx.signkeys);
|
||||
@ -1884,19 +1875,24 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
|
||||
= GNUNET_TIME_relative_min (dkc.min_dk_frequency,
|
||||
sctx.min_sk_frequency);
|
||||
}
|
||||
|
||||
denoms = json_array ();
|
||||
GNUNET_assert (NULL != denoms);
|
||||
hash_context = GNUNET_CRYPTO_hash_context_start ();
|
||||
|
||||
// If age restriction is enabled, initialize the array of age restricted denoms.
|
||||
/* TODO: optimize by putting this into global? */
|
||||
/* If age restriction is enabled, initialize the array of age restricted
|
||||
denoms and prepare a hash for them, separate from the others. We will join
|
||||
those hashes afterwards.*/
|
||||
if (age_restriction_active)
|
||||
{
|
||||
age_restricted_denoms = json_array ();
|
||||
GNUNET_assert (NULL != age_restricted_denoms);
|
||||
|
||||
hash_context_restricted = GNUNET_CRYPTO_hash_context_start ();
|
||||
}
|
||||
|
||||
last_cpd = GNUNET_TIME_UNIT_ZERO_TS;
|
||||
hash_context = GNUNET_CRYPTO_hash_context_start ();
|
||||
|
||||
{
|
||||
struct TEH_DenominationKey *dk;
|
||||
|
||||
@ -1938,14 +1934,14 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
}
|
||||
|
||||
last_cpd = dk->meta.start;
|
||||
GNUNET_CRYPTO_hash_context_read (hash_context,
|
||||
&dk->h_denom_pub,
|
||||
sizeof (struct GNUNET_HashCode));
|
||||
|
||||
{
|
||||
json_t *denom;
|
||||
json_t *array;
|
||||
struct GNUNET_HashContext *hc;
|
||||
|
||||
|
||||
denom =
|
||||
GNUNET_JSON_PACK (
|
||||
@ -1972,19 +1968,25 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
|
||||
TALER_JSON_pack_amount ("fee_refund",
|
||||
&dk->meta.fee_refund));
|
||||
|
||||
/* Put the denom into the correct array - denoms or age_restricted_denoms -
|
||||
* depending on the settings and the properties of the denomination */
|
||||
/* Put the denom into the correct array depending on the settings and
|
||||
* the properties of the denomination. Also, we build up the right
|
||||
* hash for the corresponding array. */
|
||||
if (age_restriction_active &&
|
||||
(0 != dk->denom_pub.age_mask.mask))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"got agerestricted denom %p with mask %d\n",
|
||||
&dk->denom_pub,
|
||||
dk->denom_pub.age_mask.mask);
|
||||
have_age_restricted_denoms = true;
|
||||
array = age_restricted_denoms;
|
||||
hc = hash_context_restricted;
|
||||
}
|
||||
else
|
||||
{
|
||||
array = denoms;
|
||||
hc = hash_context;
|
||||
}
|
||||
|
||||
GNUNET_CRYPTO_hash_context_read (hc,
|
||||
&dk->h_denom_pub,
|
||||
sizeof (struct GNUNET_HashCode));
|
||||
|
||||
GNUNET_assert (
|
||||
0 ==
|
||||
@ -2000,8 +2002,21 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
|
||||
{
|
||||
struct GNUNET_HashCode hc;
|
||||
|
||||
/* If age restriction is active and we had at least one denomination of
|
||||
* that sort, we simply add the hash of all age restricted denominations at
|
||||
* the end of the others. */
|
||||
if (age_restriction_active && have_age_restricted_denoms)
|
||||
{
|
||||
struct GNUNET_HashCode hcr;
|
||||
GNUNET_CRYPTO_hash_context_finish (hash_context_restricted, &hcr);
|
||||
GNUNET_CRYPTO_hash_context_read (hash_context,
|
||||
&hcr,
|
||||
sizeof (struct GNUNET_HashCode));
|
||||
}
|
||||
|
||||
GNUNET_CRYPTO_hash_context_finish (hash_context,
|
||||
&hc);
|
||||
|
||||
if (GNUNET_OK !=
|
||||
create_krd (ksh,
|
||||
&hc,
|
||||
@ -2672,7 +2687,9 @@ load_extension_data (const char *section_name,
|
||||
TEH_currency);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
meta->age_restrictions = load_age_mask (section_name);
|
||||
|
||||
meta->age_mask = load_age_mask (section_name);
|
||||
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
@ -2799,7 +2816,7 @@ add_future_denomkey_cb (void *cls,
|
||||
struct FutureBuilderContext *fbc = cls;
|
||||
struct HelperDenomination *hd = value;
|
||||
struct TEH_DenominationKey *dk;
|
||||
struct TALER_EXCHANGEDB_DenominationKeyMetaData meta;
|
||||
struct TALER_EXCHANGEDB_DenominationKeyMetaData meta = {0};
|
||||
|
||||
dk = GNUNET_CONTAINER_multihashmap_get (fbc->ksh->denomkey_map,
|
||||
h_denom_pub);
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include "taler_extensions.h"
|
||||
#include "taler_dbevents.h"
|
||||
|
||||
|
||||
/**
|
||||
* Extension carries the necessary data for a particular extension.
|
||||
*
|
||||
@ -295,6 +294,10 @@ TEH_handler_management_post_extensions (
|
||||
NULL,
|
||||
0);
|
||||
|
||||
|
||||
/* FIXME-oec. Because of a change of extensions, the key might */
|
||||
TEH_keys_update_states ();
|
||||
|
||||
CLEANUP:
|
||||
for (unsigned int i = 0; i < sec.num_extensions; i++)
|
||||
{
|
||||
|
@ -204,6 +204,7 @@ add_keys (void *cls,
|
||||
TALER_denom_pub_free (&denom_pub);
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
}
|
||||
|
||||
if (is_active)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
@ -211,6 +212,7 @@ add_keys (void *cls,
|
||||
GNUNET_h2s (&d->h_denom_pub.hash));
|
||||
continue; /* skip, already known */
|
||||
}
|
||||
|
||||
qs = TEH_plugin->add_denomination_key (
|
||||
TEH_plugin->cls,
|
||||
&d->h_denom_pub,
|
||||
|
@ -25,7 +25,7 @@ CREATE TABLE IF NOT EXISTS denominations
|
||||
(denominations_serial BIGSERIAL UNIQUE
|
||||
,denom_pub_hash BYTEA PRIMARY KEY CHECK (LENGTH(denom_pub_hash)=64)
|
||||
,denom_type INT4 NOT NULL DEFAULT (1) -- 1 == RSA (for now, remove default later!)
|
||||
,age_restrictions INT4 NOT NULL DEFAULT (0)
|
||||
,age_mask INT4 NOT NULL DEFAULT (0)
|
||||
,denom_pub BYTEA NOT NULL
|
||||
,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)
|
||||
,valid_from INT8 NOT NULL
|
||||
@ -47,7 +47,7 @@ COMMENT ON TABLE denominations
|
||||
IS 'Main denominations table. All the valid denominations the exchange knows about.';
|
||||
COMMENT ON COLUMN denominations.denom_type
|
||||
IS 'determines cipher type for blind signatures used with this denomination; 0 is for RSA';
|
||||
COMMENT ON COLUMN denominations.age_restrictions
|
||||
COMMENT ON COLUMN denominations.age_mask
|
||||
IS 'bitmask with the age restrictions that are being used for this denomination; 0 if denomination does not support the use of age restrictions';
|
||||
COMMENT ON COLUMN denominations.denominations_serial
|
||||
IS 'needed for exchange-auditor replication logic';
|
||||
|
@ -231,10 +231,11 @@ prepare_statements (struct PostgresClosure *pg)
|
||||
",fee_refresh_frac"
|
||||
",fee_refund_val"
|
||||
",fee_refund_frac"
|
||||
",age_mask"
|
||||
") VALUES "
|
||||
"($1, $2, $3, $4, $5, $6, $7, $8, $9, $10,"
|
||||
" $11, $12, $13, $14, $15, $16, $17);",
|
||||
17),
|
||||
" $11, $12, $13, $14, $15, $16, $17, $18);",
|
||||
18),
|
||||
/* Used in #postgres_iterate_denomination_info() */
|
||||
GNUNET_PQ_make_prepare (
|
||||
"denomination_iterate",
|
||||
@ -255,6 +256,7 @@ prepare_statements (struct PostgresClosure *pg)
|
||||
",fee_refund_val"
|
||||
",fee_refund_frac"
|
||||
",denom_pub"
|
||||
",age_mask"
|
||||
" FROM denominations;",
|
||||
0),
|
||||
/* Used in #postgres_iterate_denominations() */
|
||||
@ -278,6 +280,7 @@ prepare_statements (struct PostgresClosure *pg)
|
||||
",fee_refund_val"
|
||||
",fee_refund_frac"
|
||||
",denom_pub"
|
||||
",age_mask"
|
||||
" FROM denominations"
|
||||
" LEFT JOIN "
|
||||
" denomination_revocations USING (denominations_serial);",
|
||||
@ -341,6 +344,7 @@ prepare_statements (struct PostgresClosure *pg)
|
||||
",fee_refresh_frac"
|
||||
",fee_refund_val"
|
||||
",fee_refund_frac"
|
||||
",age_mask"
|
||||
" FROM denominations"
|
||||
" WHERE denom_pub_hash=$1;",
|
||||
1),
|
||||
@ -2071,7 +2075,6 @@ prepare_statements (struct PostgresClosure *pg)
|
||||
"SELECT"
|
||||
" denominations_serial AS serial"
|
||||
",denom_type"
|
||||
",age_restrictions"
|
||||
",denom_pub"
|
||||
",master_sig"
|
||||
",valid_from"
|
||||
@ -2088,6 +2091,7 @@ prepare_statements (struct PostgresClosure *pg)
|
||||
",fee_refresh_frac"
|
||||
",fee_refund_val"
|
||||
",fee_refund_frac"
|
||||
",age_mask"
|
||||
" FROM denominations"
|
||||
" WHERE denominations_serial > $1"
|
||||
" ORDER BY denominations_serial ASC;",
|
||||
@ -2390,10 +2394,11 @@ prepare_statements (struct PostgresClosure *pg)
|
||||
",fee_refresh_frac"
|
||||
",fee_refund_val"
|
||||
",fee_refund_frac"
|
||||
",age_mask"
|
||||
") VALUES "
|
||||
"($1, $2, $3, $4, $5, $6, $7, $8, $9, $10,"
|
||||
" $11, $12, $13, $14, $15, $16, $17, $18);",
|
||||
18),
|
||||
" $11, $12, $13, $14, $15, $16, $17, $18, $19);",
|
||||
19),
|
||||
GNUNET_PQ_make_prepare (
|
||||
"insert_into_table_denomination_revocations",
|
||||
"INSERT INTO denomination_revocations"
|
||||
@ -3096,9 +3101,12 @@ postgres_insert_denomination_info (
|
||||
TALER_PQ_query_param_amount_nbo (&issue->properties.fee_deposit),
|
||||
TALER_PQ_query_param_amount_nbo (&issue->properties.fee_refresh),
|
||||
TALER_PQ_query_param_amount_nbo (&issue->properties.fee_refund),
|
||||
GNUNET_PQ_query_param_uint32 (&denom_pub->age_mask.mask),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
|
||||
GNUNET_assert (denom_pub->age_mask.mask == issue->age_mask.mask);
|
||||
|
||||
GNUNET_assert (! GNUNET_TIME_absolute_is_zero (
|
||||
GNUNET_TIME_timestamp_ntoh (
|
||||
issue->properties.start).abs_time));
|
||||
@ -3172,6 +3180,8 @@ postgres_get_denomination_info (
|
||||
&issue->properties.fee_refresh),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_refund",
|
||||
&issue->properties.fee_refund),
|
||||
GNUNET_PQ_result_spec_uint32 ("age_mask",
|
||||
&issue->age_mask.mask),
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
|
||||
@ -3258,12 +3268,15 @@ domination_cb_helper (void *cls,
|
||||
&issue.properties.fee_refund),
|
||||
TALER_PQ_result_spec_denom_pub ("denom_pub",
|
||||
&denom_pub),
|
||||
GNUNET_PQ_result_spec_uint32 ("age_mask",
|
||||
&issue.age_mask.mask),
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
|
||||
memset (&issue.properties.master,
|
||||
0,
|
||||
sizeof (issue.properties.master));
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_PQ_extract_result (result,
|
||||
rs,
|
||||
@ -3272,6 +3285,13 @@ domination_cb_helper (void *cls,
|
||||
GNUNET_break (0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Unfortunately we have to carry the age mask in both, the
|
||||
* TALER_DenominationPublicKey and
|
||||
* TALER_EXCHANGEDB_DenominationKeyInformationP at different times.
|
||||
* Here we use _both_ so let's make sure the values are the same. */
|
||||
denom_pub.age_mask = issue.age_mask;
|
||||
|
||||
issue.properties.purpose.size
|
||||
= htonl (sizeof (struct TALER_DenominationKeyValidityPS));
|
||||
issue.properties.purpose.purpose
|
||||
@ -3357,10 +3377,10 @@ dominations_cb_helper (void *cls,
|
||||
|
||||
for (unsigned int i = 0; i<num_results; i++)
|
||||
{
|
||||
struct TALER_EXCHANGEDB_DenominationKeyMetaData meta;
|
||||
struct TALER_DenominationPublicKey denom_pub;
|
||||
struct TALER_MasterSignatureP master_sig;
|
||||
struct TALER_DenominationHash h_denom_pub;
|
||||
struct TALER_EXCHANGEDB_DenominationKeyMetaData meta = {0};
|
||||
struct TALER_DenominationPublicKey denom_pub = {0};
|
||||
struct TALER_MasterSignatureP master_sig = {0};
|
||||
struct TALER_DenominationHash h_denom_pub = {0};
|
||||
bool revoked;
|
||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||
GNUNET_PQ_result_spec_auto_from_type ("master_sig",
|
||||
@ -3387,6 +3407,8 @@ dominations_cb_helper (void *cls,
|
||||
&meta.fee_refund),
|
||||
TALER_PQ_result_spec_denom_pub ("denom_pub",
|
||||
&denom_pub),
|
||||
GNUNET_PQ_result_spec_uint32 ("age_mask",
|
||||
&meta.age_mask.mask),
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
|
||||
@ -3398,6 +3420,10 @@ dominations_cb_helper (void *cls,
|
||||
GNUNET_break (0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* make sure the mask information is the same */
|
||||
denom_pub.age_mask = meta.age_mask;
|
||||
|
||||
TALER_denom_pub_hash (&denom_pub,
|
||||
&h_denom_pub);
|
||||
dic->cb (dic->cb_cls,
|
||||
@ -10193,6 +10219,8 @@ postgres_lookup_denomination_key (
|
||||
&meta->fee_refresh),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
|
||||
&meta->fee_refund),
|
||||
GNUNET_PQ_result_spec_uint32 ("age_mask",
|
||||
&meta->age_mask.mask),
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
|
||||
@ -10236,6 +10264,7 @@ postgres_add_denomination_key (
|
||||
TALER_PQ_query_param_amount (&meta->fee_deposit),
|
||||
TALER_PQ_query_param_amount (&meta->fee_refresh),
|
||||
TALER_PQ_query_param_amount (&meta->fee_refund),
|
||||
GNUNET_PQ_query_param_uint32 (&meta->age_mask.mask),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
|
||||
|
@ -224,6 +224,9 @@ age_restriction_load_taler_config (
|
||||
|
||||
if (GNUNET_OK == ret)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"setting age mask to %x with #groups: %d\n", mask.mask,
|
||||
__builtin_popcount (mask.mask) - 1);
|
||||
_config.mask.mask = mask.mask;
|
||||
_config.num_groups = __builtin_popcount (mask.mask) - 1; /* no underflow, first bit always set */
|
||||
this->config = &_config;
|
||||
@ -277,6 +280,10 @@ age_restriction_load_json_config (
|
||||
|
||||
this->config_json = jconfig;
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"loaded new age restriction config with age groups: %s\n",
|
||||
TALER_age_mask_to_string (&mask));
|
||||
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
@ -350,6 +357,13 @@ TALER_extensions_age_restriction_enabled ()
|
||||
}
|
||||
|
||||
|
||||
struct TALER_AgeMask
|
||||
TALER_extensions_age_restriction_ageMask ()
|
||||
{
|
||||
return _config.mask;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
TALER_extensions_age_restriction_num_groups ()
|
||||
{
|
||||
|
@ -159,13 +159,6 @@ struct TALER_EXCHANGE_DenomPublicKey
|
||||
* revoked by the exchange.
|
||||
*/
|
||||
bool revoked;
|
||||
|
||||
/**
|
||||
* If age_mask non-zero, the denomination is age-restricted, with the age
|
||||
* groups as defined in the mask.
|
||||
*/
|
||||
struct TALER_AgeMask age_mask;
|
||||
bool age_restricted;
|
||||
};
|
||||
|
||||
|
||||
|
@ -70,6 +70,12 @@ struct TALER_EXCHANGEDB_DenominationKeyInformationP
|
||||
* Signed properties of the denomination key.
|
||||
*/
|
||||
struct TALER_DenominationKeyValidityPS properties;
|
||||
|
||||
/**
|
||||
* If denomination was setup for age restriction, non-zero age mask.
|
||||
* Note that the mask is not part of the signature.
|
||||
*/
|
||||
struct TALER_AgeMask age_mask;
|
||||
};
|
||||
|
||||
|
||||
@ -643,7 +649,7 @@ struct TALER_EXCHANGEDB_DenominationKeyMetaData
|
||||
* A value of 0 means that the denomination does not support the extension for
|
||||
* age-restriction.
|
||||
*/
|
||||
struct TALER_AgeMask age_restrictions;
|
||||
struct TALER_AgeMask age_mask;
|
||||
};
|
||||
|
||||
|
||||
|
@ -238,6 +238,13 @@ TALER_age_mask_to_string (
|
||||
bool
|
||||
TALER_extensions_age_restriction_enabled ();
|
||||
|
||||
/**
|
||||
* Returns the currently set age mask
|
||||
*/
|
||||
struct TALER_AgeMask
|
||||
TALER_extensions_age_restriction_ageMask ();
|
||||
|
||||
|
||||
/**
|
||||
* Returns the amount of age groups defined. 0 means no age restriction
|
||||
* enabled.
|
||||
|
@ -67,7 +67,7 @@
|
||||
/**
|
||||
* Set to 1 for extra debug logging.
|
||||
*/
|
||||
#define DEBUG 1 /* FIXME-oec */
|
||||
#define DEBUG 0
|
||||
|
||||
/**
|
||||
* Log error related to CURL operations.
|
||||
@ -667,7 +667,9 @@ decode_keys_json (const json_t *resp_obj,
|
||||
enum TALER_EXCHANGE_VersionCompatibility *vc)
|
||||
{
|
||||
struct TALER_ExchangeSignatureP sig;
|
||||
struct GNUNET_HashContext *hash_context;
|
||||
struct GNUNET_HashContext *hash_context = NULL;
|
||||
struct GNUNET_HashContext *hash_context_restricted = NULL;
|
||||
bool have_age_restricted_denom = false;
|
||||
struct TALER_ExchangePublicKeyP pub;
|
||||
const char *currency;
|
||||
struct GNUNET_JSON_Specification mspec[] = {
|
||||
@ -746,7 +748,6 @@ decode_keys_json (const json_t *resp_obj,
|
||||
key_data->version = GNUNET_strdup (ver);
|
||||
}
|
||||
|
||||
hash_context = NULL;
|
||||
EXITIF (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (resp_obj,
|
||||
(check_sig) ? mspec : &mspec[2],
|
||||
@ -766,7 +767,10 @@ decode_keys_json (const json_t *resp_obj,
|
||||
|
||||
/* parse the master public key and issue date of the response */
|
||||
if (check_sig)
|
||||
{
|
||||
hash_context = GNUNET_CRYPTO_hash_context_start ();
|
||||
hash_context_restricted = GNUNET_CRYPTO_hash_context_start ();
|
||||
}
|
||||
|
||||
/* parse the signing keys */
|
||||
{
|
||||
@ -829,6 +833,9 @@ decode_keys_json (const json_t *resp_obj,
|
||||
EXITIF (GNUNET_OK !=
|
||||
TALER_extensions_load_json_config (extensions));
|
||||
}
|
||||
|
||||
/* 4. assuming we might have now a new value for age_mask, set it in key_data */
|
||||
key_data->age_mask = TALER_extensions_age_restriction_ageMask ();
|
||||
}
|
||||
|
||||
/* parse the denomination keys, merging with the
|
||||
@ -839,10 +846,15 @@ decode_keys_json (const json_t *resp_obj,
|
||||
*/
|
||||
struct
|
||||
{ char *name;
|
||||
struct GNUNET_HashContext *hc;
|
||||
bool is_optional_age_restriction;}
|
||||
hive[2] = {
|
||||
{ "denoms", false },
|
||||
{ "age_restricted_denoms", true }
|
||||
{ "denoms",
|
||||
hash_context,
|
||||
false },
|
||||
{ "age_restricted_denoms",
|
||||
hash_context_restricted,
|
||||
true }
|
||||
};
|
||||
|
||||
for (size_t s = 0; s < sizeof(hive) / sizeof(hive[0]); s++)
|
||||
@ -873,6 +885,8 @@ decode_keys_json (const json_t *resp_obj,
|
||||
struct TALER_EXCHANGE_DenomPublicKey dk;
|
||||
bool found = false;
|
||||
|
||||
have_age_restricted_denom = true;
|
||||
|
||||
memset (&dk,
|
||||
0,
|
||||
sizeof (dk));
|
||||
@ -881,14 +895,15 @@ decode_keys_json (const json_t *resp_obj,
|
||||
check_sig,
|
||||
denom_key_obj,
|
||||
&key_data->master_pub,
|
||||
hash_context));
|
||||
hive[s].hc));
|
||||
|
||||
/* Mark age restriction according where we got this denomination from,
|
||||
* "denoms" or "age_restricted_denoms" */
|
||||
if (hive[s].is_optional_age_restriction)
|
||||
{
|
||||
dk.age_restricted = true;
|
||||
dk.age_mask.mask = key_data->age_mask.mask;
|
||||
// dk.age_restricted = true;
|
||||
// dk.age_mask.mask = key_data->age_mask.mask;
|
||||
GNUNET_assert (0 != key_data->age_mask.mask);
|
||||
}
|
||||
|
||||
for (unsigned int j = 0;
|
||||
@ -1048,6 +1063,18 @@ decode_keys_json (const json_t *resp_obj,
|
||||
.list_issue_date = GNUNET_TIME_timestamp_hton (key_data->list_issue_date)
|
||||
};
|
||||
|
||||
/* If we had any age restricted denominations, add their hash to the end of
|
||||
* the normal denominations. */
|
||||
if (have_age_restricted_denom)
|
||||
{
|
||||
struct GNUNET_HashCode hcr;
|
||||
GNUNET_CRYPTO_hash_context_finish (hash_context_restricted,
|
||||
&hcr);
|
||||
GNUNET_CRYPTO_hash_context_read (hash_context,
|
||||
&hcr,
|
||||
sizeof(struct GNUNET_HashCode));
|
||||
}
|
||||
|
||||
GNUNET_CRYPTO_hash_context_finish (hash_context,
|
||||
&ks.hc);
|
||||
hash_context = NULL;
|
||||
|
@ -32,7 +32,7 @@
|
||||
/**
|
||||
* Set to 1 for extra debug logging.
|
||||
*/
|
||||
#define DEBUG 0
|
||||
#define DEBUG 1 /* FIXME-oec */
|
||||
|
||||
|
||||
/**
|
||||
|
@ -355,6 +355,7 @@ TALER_EXCHANGE_refresh_prepare (
|
||||
struct MeltData md;
|
||||
json_t *ret;
|
||||
struct TALER_Amount total;
|
||||
struct TALER_AgeCommitmentHash ach = {0};
|
||||
struct TALER_CoinSpendPublicKeyP coin_pub;
|
||||
struct TALER_TransferSecretP trans_sec[TALER_CNC_KAPPA];
|
||||
struct TALER_RefreshCommitmentEntry rce[TALER_CNC_KAPPA];
|
||||
@ -372,6 +373,7 @@ TALER_EXCHANGE_refresh_prepare (
|
||||
md.melted_coin.original_value = melt_pk->value;
|
||||
md.melted_coin.expire_deposit
|
||||
= melt_pk->expire_deposit;
|
||||
md.melted_coin.h_age_commitment = ach;
|
||||
TALER_age_commitment_hash (age_commitment,
|
||||
&md.melted_coin.h_age_commitment);
|
||||
|
||||
|
@ -184,6 +184,7 @@ TALER_EXCHANGE_withdraw (
|
||||
{
|
||||
struct TALER_PlanchetDetail pd;
|
||||
struct TALER_EXCHANGE_WithdrawHandle *wh;
|
||||
bool age_restricted = (0 != pk->key.age_mask.mask);
|
||||
|
||||
wh = GNUNET_new (struct TALER_EXCHANGE_WithdrawHandle);
|
||||
wh->exchange = exchange;
|
||||
@ -193,8 +194,8 @@ TALER_EXCHANGE_withdraw (
|
||||
wh->ps = *ps;
|
||||
wh->ach = ach;
|
||||
|
||||
GNUNET_assert ( (pk->age_restricted && (NULL != ach)) ||
|
||||
(! pk->age_restricted && (NULL == ach)) );
|
||||
GNUNET_assert ( (age_restricted && (NULL != ach)) ||
|
||||
(! age_restricted && (NULL == ach)));
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_planchet_prepare (&pk->key,
|
||||
|
@ -209,6 +209,7 @@ test_exchange_api_LDADD = \
|
||||
-lgnunetcurl \
|
||||
-lgnunetutil \
|
||||
-ljansson \
|
||||
-ltalerextensions \
|
||||
$(XLIB)
|
||||
|
||||
test_exchange_management_api_SOURCES = \
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "taler_bank_service.h"
|
||||
#include "taler_fakebank_lib.h"
|
||||
#include "taler_testing_lib.h"
|
||||
#include "taler_extensions.h"
|
||||
|
||||
/**
|
||||
* Configuration file we use. One (big) configuration is used
|
||||
@ -983,12 +984,12 @@ run (void *cls,
|
||||
TALER_TESTING_cmd_auditor_add ("add-auditor-OK",
|
||||
MHD_HTTP_NO_CONTENT,
|
||||
false),
|
||||
TALER_TESTING_cmd_exec_offline_sign_extensions ("offline-sign-extensions",
|
||||
CONFIG_FILE),
|
||||
TALER_TESTING_cmd_wire_add ("add-wire-account",
|
||||
"payto://x-taler-bank/localhost/2",
|
||||
MHD_HTTP_NO_CONTENT,
|
||||
false),
|
||||
TALER_TESTING_cmd_exec_offline_sign_extensions ("offline-sign-extensions",
|
||||
CONFIG_FILE),
|
||||
TALER_TESTING_cmd_exec_offline_sign_keys ("offline-sign-future-keys",
|
||||
CONFIG_FILE),
|
||||
TALER_TESTING_cmd_exec_offline_sign_fees ("offline-sign-fees",
|
||||
@ -1042,6 +1043,9 @@ main (int argc,
|
||||
GNUNET_log_setup ("test-exchange-api",
|
||||
"INFO",
|
||||
NULL);
|
||||
|
||||
TALER_extensions_init ();
|
||||
|
||||
/* Check fakebank port is available and get config */
|
||||
if (GNUNET_OK !=
|
||||
TALER_TESTING_prepare_fakebank (CONFIG_FILE,
|
||||
|
@ -997,6 +997,7 @@ melt_run (void *cls,
|
||||
const struct TALER_DenominationSignature *melt_sig;
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *melt_denom_pub;
|
||||
const struct TALER_TESTING_Command *coin_command;
|
||||
bool age_restricted;
|
||||
|
||||
if (NULL == (coin_command
|
||||
= TALER_TESTING_interpreter_lookup_command
|
||||
@ -1026,6 +1027,7 @@ melt_run (void *cls,
|
||||
TALER_TESTING_interpreter_fail (rms->is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_TESTING_get_trait_denom_pub (coin_command,
|
||||
0,
|
||||
@ -1035,9 +1037,11 @@ melt_run (void *cls,
|
||||
TALER_TESTING_interpreter_fail (rms->is);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Melt amount starts with the melt fee of the old coin; we'll add the
|
||||
values and withdraw fees of the fresh coins next */
|
||||
melt_amount = melt_denom_pub->fee_refresh;
|
||||
age_restricted = melt_denom_pub->key.age_mask.mask != 0;
|
||||
for (unsigned int i = 0; i<num_fresh_coins; i++)
|
||||
{
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *fresh_pk;
|
||||
@ -1055,7 +1059,7 @@ melt_run (void *cls,
|
||||
}
|
||||
fresh_pk = TALER_TESTING_find_pk (TALER_EXCHANGE_get_keys (is->exchange),
|
||||
&fresh_amount,
|
||||
melt_denom_pub->age_restricted);
|
||||
age_restricted);
|
||||
if (NULL == fresh_pk)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
@ -1080,8 +1084,7 @@ melt_run (void *cls,
|
||||
{
|
||||
struct TALER_AgeCommitment *ac = NULL;
|
||||
|
||||
GNUNET_assert (melt_denom_pub->age_restricted ==
|
||||
(NULL != rms->age_commitment));
|
||||
GNUNET_assert (age_restricted == (NULL != rms->age_commitment));
|
||||
|
||||
if (NULL != rms->age_commitment)
|
||||
{
|
||||
|
@ -464,12 +464,14 @@ withdraw_run (void *cls,
|
||||
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_age_restriction_commit (
|
||||
&ws->pk->age_mask,
|
||||
&ws->pk->key.age_mask,
|
||||
ws->age,
|
||||
seed,
|
||||
ac));
|
||||
|
||||
ws->age_commitment = ac;
|
||||
ws->h_age_commitment = GNUNET_malloc (sizeof(struct
|
||||
TALER_AgeCommitmentHash));
|
||||
TALER_age_commitment_hash (
|
||||
ac,
|
||||
ws->h_age_commitment);
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "taler_signatures.h"
|
||||
#include "taler_extensions.h"
|
||||
#include "taler_testing_lib.h"
|
||||
|
||||
/**
|
||||
@ -440,7 +441,7 @@ TALER_TESTING_find_pk (const struct TALER_EXCHANGE_Keys *keys,
|
||||
(GNUNET_TIME_timestamp_cmp (now,
|
||||
<,
|
||||
pk->withdraw_valid_until)) &&
|
||||
(age_restricted == pk->age_restricted) )
|
||||
(age_restricted == (0 != pk->key.age_mask.mask)) )
|
||||
return pk;
|
||||
}
|
||||
/* do 2nd pass to check if expiration times are to blame for
|
||||
@ -457,7 +458,7 @@ TALER_TESTING_find_pk (const struct TALER_EXCHANGE_Keys *keys,
|
||||
GNUNET_TIME_timestamp_cmp (now,
|
||||
>,
|
||||
pk->withdraw_valid_until) ) &&
|
||||
(age_restricted == pk->age_restricted) )
|
||||
(age_restricted == (0 != pk->key.age_mask.mask)) )
|
||||
{
|
||||
GNUNET_log
|
||||
(GNUNET_ERROR_TYPE_WARNING,
|
||||
|
Loading…
Reference in New Issue
Block a user