diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h index 04b731b32..f1fccd70a 100644 --- a/src/include/taler_exchange_service.h +++ b/src/include/taler_exchange_service.h @@ -159,6 +159,11 @@ struct TALER_EXCHANGE_DenomPublicKey * revoked by the exchange. */ bool revoked; + + /** + * Is the denomination age-restricted? + */ + bool age_restricted; }; diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c index df501f0b7..8919ae601 100644 --- a/src/lib/exchange_api_handle.c +++ b/src/lib/exchange_api_handle.c @@ -345,6 +345,7 @@ parse_json_denomkey (struct TALER_EXCHANGE_DenomPublicKey *denom_key, GNUNET_JSON_spec_end () }; + if (GNUNET_OK != GNUNET_JSON_parse (denom_key_obj, spec, @@ -794,60 +795,86 @@ decode_keys_json (const json_t *resp_obj, /* parse the denomination keys, merging with the possibly EXISTING array as required (/keys cherry picking) */ { - json_t *denom_keys_array; - json_t *denom_key_obj; - unsigned int index; - - EXITIF (NULL == (denom_keys_array = - json_object_get (resp_obj, - "denoms"))); - EXITIF (JSON_ARRAY != json_typeof (denom_keys_array)); - - json_array_foreach (denom_keys_array, index, denom_key_obj) { - struct TALER_EXCHANGE_DenomPublicKey dk; - bool found = false; - - memset (&dk, - 0, - sizeof (dk)); - EXITIF (GNUNET_SYSERR == - parse_json_denomkey (&dk, - check_sig, - denom_key_obj, - &key_data->master_pub, - hash_context)); - - for (unsigned int j = 0; - jnum_denom_keys; - j++) - { - if (0 == denoms_cmp (&dk, - &key_data->denom_keys[j])) - { - found = true; - break; - } - } - if (found) - { - /* 0:0:0 did not support /keys cherry picking */ - TALER_LOG_DEBUG ("Skipping denomination key: already know it\n"); - TALER_denom_pub_free (&dk.key); - continue; - } - if (key_data->denom_keys_size == key_data->num_denom_keys) - GNUNET_array_grow (key_data->denom_keys, - key_data->denom_keys_size, - key_data->denom_keys_size * 2 + 2); - key_data->denom_keys[key_data->num_denom_keys++] = dk; - - /* Update "last_denom_issue_date" */ - TALER_LOG_DEBUG ("Adding denomination key that is valid_until %s\n", - GNUNET_TIME_timestamp2s (dk.valid_from)); - key_data->last_denom_issue_date - = GNUNET_TIME_timestamp_max (key_data->last_denom_issue_date, - dk.valid_from); + struct + { + char *name; + bool is_optional_age_restriction; + } section[2] = { + /* The denominations can be in "denoms" or in + * "age_restricted_denoms", the later being optional */ + { "denoms", false }, + { "age_restricted_denoms", true}, }; + + for (size_t s = 0; s < sizeof(section) / sizeof(section[0]); s++) + { + json_t *denom_keys_array; + json_t *denom_key_obj; + unsigned int index; + + denom_keys_array = json_object_get (resp_obj, + section[s].name); + + EXITIF (NULL == denom_keys_array && + ! section[s].is_optional_age_restriction); + + if (NULL == denom_keys_array && + section[s].is_optional_age_restriction) + continue; + + EXITIF (JSON_ARRAY != json_typeof (denom_keys_array)); + + json_array_foreach (denom_keys_array, index, denom_key_obj) { + struct TALER_EXCHANGE_DenomPublicKey dk; + bool found = false; + + memset (&dk, + 0, + sizeof (dk)); + EXITIF (GNUNET_SYSERR == + parse_json_denomkey (&dk, + check_sig, + denom_key_obj, + &key_data->master_pub, + hash_context)); + + /* Mark age restriction according where we got this denomination from, + * "denoms" or "age_restricted_denoms" */ + if (section[s].is_optional_age_restriction) + dk.age_restricted = true; + + for (unsigned int j = 0; + jnum_denom_keys; + j++) + { + if (0 == denoms_cmp (&dk, + &key_data->denom_keys[j])) + { + found = true; + break; + } + } + if (found) + { + /* 0:0:0 did not support /keys cherry picking */ + TALER_LOG_DEBUG ("Skipping denomination key: already know it\n"); + TALER_denom_pub_free (&dk.key); + continue; + } + if (key_data->denom_keys_size == key_data->num_denom_keys) + GNUNET_array_grow (key_data->denom_keys, + key_data->denom_keys_size, + key_data->denom_keys_size * 2 + 2); + key_data->denom_keys[key_data->num_denom_keys++] = dk; + + /* Update "last_denom_issue_date" */ + TALER_LOG_DEBUG ("Adding denomination key that is valid_until %s\n", + GNUNET_TIME_timestamp2s (dk.valid_from)); + key_data->last_denom_issue_date + = GNUNET_TIME_timestamp_max (key_data->last_denom_issue_date, + dk.valid_from); + }; + } } /* parse the auditor information */