Towards a complete test with age restriction
- substantial amount of fixes in various parts - slight refactoring of extensions - fixes of post handler for /management/extensions - fixes for offline tool extensions signing State: - compiles, runs and tests succeed when age restriction is not enabled - compiles, runs and tests fail, when age restriction is enabled
This commit is contained in:
parent
f48ba6f043
commit
932dcde25c
@ -1924,6 +1924,7 @@ trigger_upload (const char *exchange_url)
|
|||||||
if (0 == strcasecmp (key,
|
if (0 == strcasecmp (key,
|
||||||
uhs[i].key))
|
uhs[i].key))
|
||||||
{
|
{
|
||||||
|
|
||||||
found = true;
|
found = true;
|
||||||
uhs[i].cb (exchange_url,
|
uhs[i].cb (exchange_url,
|
||||||
index,
|
index,
|
||||||
|
@ -736,6 +736,12 @@ handle_post_management (struct TEH_RequestContext *rc,
|
|||||||
return TEH_handler_management_post_wire_fees (rc->connection,
|
return TEH_handler_management_post_wire_fees (rc->connection,
|
||||||
root);
|
root);
|
||||||
}
|
}
|
||||||
|
if (0 == strcmp (args[0],
|
||||||
|
"extensions"))
|
||||||
|
{
|
||||||
|
return TEH_handler_management_post_extensions (rc->connection,
|
||||||
|
root);
|
||||||
|
}
|
||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
return r404 (rc->connection,
|
return r404 (rc->connection,
|
||||||
"/management/*");
|
"/management/*");
|
||||||
|
@ -1755,7 +1755,7 @@ create_krd (struct TEH_KeyStateHandle *ksh,
|
|||||||
json_t *sig;
|
json_t *sig;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = json_object_set_new (
|
r = json_object_set (
|
||||||
keys,
|
keys,
|
||||||
"extensions",
|
"extensions",
|
||||||
extensions);
|
extensions);
|
||||||
@ -1778,7 +1778,7 @@ create_krd (struct TEH_KeyStateHandle *ksh,
|
|||||||
{
|
{
|
||||||
GNUNET_assert (
|
GNUNET_assert (
|
||||||
0 ==
|
0 ==
|
||||||
json_object_set_new (
|
json_object_set (
|
||||||
keys,
|
keys,
|
||||||
"age_restricted_denoms",
|
"age_restricted_denoms",
|
||||||
age_restricted_denoms));
|
age_restricted_denoms));
|
||||||
@ -1858,6 +1858,8 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
|
|||||||
struct GNUNET_TIME_Timestamp last_cpd;
|
struct GNUNET_TIME_Timestamp last_cpd;
|
||||||
struct GNUNET_CONTAINER_Heap *heap;
|
struct GNUNET_CONTAINER_Heap *heap;
|
||||||
struct GNUNET_HashContext *hash_context;
|
struct GNUNET_HashContext *hash_context;
|
||||||
|
bool age_restriction_active =
|
||||||
|
TALER_extensions_is_enabled_type (TALER_Extension_AgeRestriction);
|
||||||
|
|
||||||
sctx.signkeys = json_array ();
|
sctx.signkeys = json_array ();
|
||||||
GNUNET_assert (NULL != sctx.signkeys);
|
GNUNET_assert (NULL != sctx.signkeys);
|
||||||
@ -1887,7 +1889,7 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
|
|||||||
|
|
||||||
// If age restriction is enabled, initialize the array of age restricted denoms.
|
// If age restriction is enabled, initialize the array of age restricted denoms.
|
||||||
/* TODO: optimize by putting this into global? */
|
/* TODO: optimize by putting this into global? */
|
||||||
if (TALER_extensions_is_enabled_type (TALER_Extension_AgeRestriction))
|
if (age_restriction_active)
|
||||||
{
|
{
|
||||||
age_restricted_denoms = json_array ();
|
age_restricted_denoms = json_array ();
|
||||||
GNUNET_assert (NULL != age_restricted_denoms);
|
GNUNET_assert (NULL != age_restricted_denoms);
|
||||||
@ -1972,15 +1974,14 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
|
|||||||
|
|
||||||
/* Put the denom into the correct array - denoms or age_restricted_denoms -
|
/* Put the denom into the correct array - denoms or age_restricted_denoms -
|
||||||
* depending on the settings and the properties of the denomination */
|
* depending on the settings and the properties of the denomination */
|
||||||
if (NULL != age_restricted_denoms &&
|
if (age_restriction_active &&
|
||||||
0 != dk->meta.age_restrictions.mask)
|
(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);
|
||||||
array = age_restricted_denoms;
|
array = age_restricted_denoms;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
array = denoms;
|
array = denoms;
|
||||||
}
|
|
||||||
|
|
||||||
GNUNET_assert (
|
GNUNET_assert (
|
||||||
0 ==
|
0 ==
|
||||||
@ -1990,6 +1991,7 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GNUNET_CONTAINER_heap_destroy (heap);
|
GNUNET_CONTAINER_heap_destroy (heap);
|
||||||
if (! GNUNET_TIME_absolute_is_zero (last_cpd.abs_time))
|
if (! GNUNET_TIME_absolute_is_zero (last_cpd.abs_time))
|
||||||
{
|
{
|
||||||
@ -2010,7 +2012,7 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
|
|||||||
"Failed to generate key response data for %s\n",
|
"Failed to generate key response data for %s\n",
|
||||||
GNUNET_TIME_timestamp2s (last_cpd));
|
GNUNET_TIME_timestamp2s (last_cpd));
|
||||||
json_decref (denoms);
|
json_decref (denoms);
|
||||||
if (NULL != age_restricted_denoms)
|
if (age_restriction_active && NULL != age_restricted_denoms)
|
||||||
json_decref (age_restricted_denoms);
|
json_decref (age_restricted_denoms);
|
||||||
json_decref (sctx.signkeys);
|
json_decref (sctx.signkeys);
|
||||||
json_decref (recoup);
|
json_decref (recoup);
|
||||||
|
@ -91,6 +91,8 @@ set_extensions (void *cls,
|
|||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GNUNET_assert(NULL != ext->config);
|
||||||
|
|
||||||
config = json_dumps (ext->config, JSON_COMPACT | JSON_SORT_KEYS);
|
config = json_dumps (ext->config, JSON_COMPACT | JSON_SORT_KEYS);
|
||||||
if (NULL == config)
|
if (NULL == config)
|
||||||
{
|
{
|
||||||
@ -140,6 +142,58 @@ set_extensions (void *cls,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static enum GNUNET_GenericReturnValue
|
||||||
|
verify_extensions_from_json (
|
||||||
|
json_t *extensions,
|
||||||
|
struct SetExtensionsContext *sec)
|
||||||
|
{
|
||||||
|
const char*name;
|
||||||
|
const struct TALER_Extension *extension;
|
||||||
|
size_t i=0;
|
||||||
|
json_t *blob;
|
||||||
|
|
||||||
|
GNUNET_assert (NULL != extensions);
|
||||||
|
GNUNET_assert (json_is_object (extensions));
|
||||||
|
|
||||||
|
sec->num_extensions = json_object_size (extensions);
|
||||||
|
sec->extensions = GNUNET_new_array (sec->num_extensions,
|
||||||
|
struct Extension);
|
||||||
|
|
||||||
|
json_object_foreach (extensions, name, blob)
|
||||||
|
{
|
||||||
|
int critical = 0;
|
||||||
|
json_t *config;
|
||||||
|
const char *version = NULL;
|
||||||
|
|
||||||
|
/* load and verify criticality, version, etc. */
|
||||||
|
extension = TALER_extensions_get_by_name (name);
|
||||||
|
if (NULL == extension)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
"no such extension: %s\n", name);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
TALER_extensions_is_json_config (
|
||||||
|
blob, &critical, &version, &config))
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
|
||||||
|
if (critical != extension->critical
|
||||||
|
|| 0 != strcmp (version, extension->version) // TODO: libtool compare?
|
||||||
|
|| NULL == config
|
||||||
|
|| GNUNET_OK != extension->test_json_config (config))
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
|
||||||
|
sec->extensions[i].type = extension->type;
|
||||||
|
sec->extensions[i].config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GNUNET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
MHD_RESULT
|
MHD_RESULT
|
||||||
TEH_handler_management_post_extensions (
|
TEH_handler_management_post_extensions (
|
||||||
struct MHD_Connection *connection,
|
struct MHD_Connection *connection,
|
||||||
@ -204,57 +258,18 @@ TEH_handler_management_post_extensions (
|
|||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
"Received /management/extensions\n");
|
"Received /management/extensions\n");
|
||||||
|
|
||||||
sec.num_extensions = json_object_size (extensions);
|
|
||||||
sec.extensions = GNUNET_new_array (sec.num_extensions,
|
|
||||||
struct Extension);
|
|
||||||
|
|
||||||
/* Now parse individual extensions and signatures from those objects. */
|
/* Now parse individual extensions and signatures from those objects. */
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
verify_extensions_from_json (extensions, &sec))
|
||||||
{
|
{
|
||||||
const struct TALER_Extension *extension = NULL;
|
GNUNET_JSON_parse_free (top_spec);
|
||||||
const char *name;
|
return TALER_MHD_reply_with_error (
|
||||||
json_t *config;
|
connection,
|
||||||
int idx = 0;
|
MHD_HTTP_BAD_REQUEST,
|
||||||
|
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
||||||
json_object_foreach (extensions, name, config){
|
"invalid object");
|
||||||
|
|
||||||
/* 1. Make sure name refers to a supported extension */
|
|
||||||
extension = TALER_extensions_get_by_name (name);
|
|
||||||
if (NULL == extension)
|
|
||||||
{
|
|
||||||
ret = TALER_MHD_reply_with_error (
|
|
||||||
connection,
|
|
||||||
MHD_HTTP_BAD_REQUEST,
|
|
||||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
|
||||||
"invalid extension type");
|
|
||||||
goto CLEANUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
sec.extensions[idx].config = config;
|
|
||||||
sec.extensions[idx].type = extension->type;
|
|
||||||
|
|
||||||
/* 2. Make sure the config is sound */
|
|
||||||
if (GNUNET_OK !=
|
|
||||||
extension->test_json_config (
|
|
||||||
sec.extensions[idx].config))
|
|
||||||
{
|
|
||||||
ret = TALER_MHD_reply_with_error (
|
|
||||||
connection,
|
|
||||||
MHD_HTTP_BAD_REQUEST,
|
|
||||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
|
||||||
"invalid configuration for extension");
|
|
||||||
goto CLEANUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We have a validly signed JSON object for the extension. Increment its
|
|
||||||
* refcount.
|
|
||||||
*/
|
|
||||||
json_incref (sec.extensions[idx].config);
|
|
||||||
idx++;
|
|
||||||
|
|
||||||
} /* json_object_foreach */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
"Received %u extensions\n",
|
"Received %u extensions\n",
|
||||||
sec.num_extensions);
|
sec.num_extensions);
|
||||||
|
@ -247,7 +247,7 @@ age_restriction_load_json_config (
|
|||||||
struct TALER_AgeMask mask = {0};
|
struct TALER_AgeMask mask = {0};
|
||||||
enum GNUNET_GenericReturnValue ret;
|
enum GNUNET_GenericReturnValue ret;
|
||||||
|
|
||||||
ret = TALER_JSON_parse_agemask (jconfig, &mask);
|
ret = TALER_JSON_parse_age_groups (jconfig, &mask);
|
||||||
if (GNUNET_OK != ret)
|
if (GNUNET_OK != ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -323,7 +323,7 @@ age_restriction_test_json_config (
|
|||||||
{
|
{
|
||||||
struct TALER_AgeMask mask = {0};
|
struct TALER_AgeMask mask = {0};
|
||||||
|
|
||||||
return TALER_JSON_parse_agemask (config, &mask);
|
return TALER_JSON_parse_age_groups (config, &mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -357,4 +357,29 @@ TALER_extensions_age_restriction_num_groups ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum GNUNET_GenericReturnValue
|
||||||
|
TALER_JSON_parse_age_groups (const json_t *root,
|
||||||
|
struct TALER_AgeMask *mask)
|
||||||
|
{
|
||||||
|
enum GNUNET_GenericReturnValue ret;
|
||||||
|
const char *str;
|
||||||
|
struct GNUNET_JSON_Specification spec[] = {
|
||||||
|
GNUNET_JSON_spec_string ("age_groups",
|
||||||
|
&str),
|
||||||
|
GNUNET_JSON_spec_end ()
|
||||||
|
};
|
||||||
|
|
||||||
|
ret = GNUNET_JSON_parse (root,
|
||||||
|
spec,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
if (GNUNET_OK == ret)
|
||||||
|
TALER_parse_age_group_string (str, mask);
|
||||||
|
|
||||||
|
GNUNET_JSON_parse_free (spec);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* end of extension_age_restriction.c */
|
/* end of extension_age_restriction.c */
|
||||||
|
@ -247,27 +247,31 @@ TALER_extensions_load_taler_config (
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static enum GNUNET_GenericReturnValue
|
enum GNUNET_GenericReturnValue
|
||||||
is_json_extension_config (
|
TALER_extensions_is_json_config (
|
||||||
json_t *obj,
|
json_t *obj,
|
||||||
int *critical,
|
int *critical,
|
||||||
const char **version,
|
const char **version,
|
||||||
json_t **config)
|
json_t **config)
|
||||||
{
|
{
|
||||||
enum GNUNET_GenericReturnValue ret;
|
enum GNUNET_GenericReturnValue ret;
|
||||||
|
json_t *cfg;
|
||||||
struct GNUNET_JSON_Specification spec[] = {
|
struct GNUNET_JSON_Specification spec[] = {
|
||||||
GNUNET_JSON_spec_boolean ("critical",
|
GNUNET_JSON_spec_boolean ("critical",
|
||||||
critical),
|
critical),
|
||||||
GNUNET_JSON_spec_string ("version",
|
GNUNET_JSON_spec_string ("version",
|
||||||
version),
|
version),
|
||||||
GNUNET_JSON_spec_json ("config",
|
GNUNET_JSON_spec_json ("config",
|
||||||
config),
|
&cfg),
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
};
|
};
|
||||||
|
|
||||||
ret = GNUNET_JSON_parse (obj, spec, NULL, NULL);
|
ret = GNUNET_JSON_parse (obj, spec, NULL, NULL);
|
||||||
if (GNUNET_OK == ret)
|
if (GNUNET_OK == ret)
|
||||||
|
{
|
||||||
|
*config = json_copy (cfg);
|
||||||
GNUNET_JSON_parse_free (spec);
|
GNUNET_JSON_parse_free (spec);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -300,7 +304,7 @@ TALER_extensions_load_json_config (
|
|||||||
|
|
||||||
/* load and verify criticality, version, etc. */
|
/* load and verify criticality, version, etc. */
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
is_json_extension_config (
|
TALER_extensions_is_json_config (
|
||||||
blob, &critical, &version, &config))
|
blob, &critical, &version, &config))
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
|
|
||||||
|
@ -85,6 +85,31 @@ enum GNUNET_GenericReturnValue
|
|||||||
TALER_extensions_load_taler_config (
|
TALER_extensions_load_taler_config (
|
||||||
const struct GNUNET_CONFIGURATION_Handle *cfg);
|
const struct GNUNET_CONFIGURATION_Handle *cfg);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check the given obj to be a valid extension object and fill the fields
|
||||||
|
* accordingly.
|
||||||
|
*/
|
||||||
|
enum GNUNET_GenericReturnValue
|
||||||
|
TALER_extensions_is_json_config (
|
||||||
|
json_t *obj,
|
||||||
|
int *critical,
|
||||||
|
const char **version,
|
||||||
|
json_t **config);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sets the configuration of the extensions from a given JSON object.
|
||||||
|
*
|
||||||
|
* he JSON object must be of type ExchangeKeysResponse as described in
|
||||||
|
* https://docs.taler.net/design-documents/006-extensions.html#exchange
|
||||||
|
*
|
||||||
|
* @param cfg JSON object containting the configuration for all extensions
|
||||||
|
* @return GNUNET_OK on success, GNUNET_SYSERR if unknown extensions were found
|
||||||
|
* or any particular configuration couldn't be parsed.
|
||||||
|
*/
|
||||||
|
enum GNUNET_GenericReturnValue
|
||||||
|
TALER_extensions_load_json_config (
|
||||||
|
json_t *cfg);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the head of the linked list of extensions
|
* Returns the head of the linked list of extensions
|
||||||
*/
|
*/
|
||||||
@ -156,20 +181,6 @@ TALER_extensions_verify_json_config_signature (
|
|||||||
struct TALER_MasterSignatureP *extensions_sig,
|
struct TALER_MasterSignatureP *extensions_sig,
|
||||||
struct TALER_MasterPublicKeyP *master_pub);
|
struct TALER_MasterPublicKeyP *master_pub);
|
||||||
|
|
||||||
/*
|
|
||||||
* Sets the configuration of the extensions from a given JSON object.
|
|
||||||
*
|
|
||||||
* The JSON object must be of type ExchangeKeysResponse as described in
|
|
||||||
* https://docs.taler.net/design-documents/006-extensions.html#exchange
|
|
||||||
*
|
|
||||||
* @param cfg Handle to the TALER configuration
|
|
||||||
* @return GNUNET_OK on success, GNUNET_SYSERR if unknown extensions were found
|
|
||||||
* or any particular configuration couldn't be parsed.
|
|
||||||
*/
|
|
||||||
enum GNUNET_GenericReturnValue
|
|
||||||
TALER_extensions_load_json_config (
|
|
||||||
json_t *extensions);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TALER Age Restriction Extension
|
* TALER Age Restriction Extension
|
||||||
@ -234,6 +245,18 @@ TALER_extensions_age_restriction_enabled ();
|
|||||||
size_t
|
size_t
|
||||||
TALER_extensions_age_restriction_num_groups ();
|
TALER_extensions_age_restriction_num_groups ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a JSON object { "age_groups": "a:b:...y:z" }.
|
||||||
|
*
|
||||||
|
* @param root is the json object
|
||||||
|
* @param[out] mask on succes, will contain the age mask
|
||||||
|
* @return #GNUNET_OK on success and #GNUNET_SYSERR on failure.
|
||||||
|
*/
|
||||||
|
enum GNUNET_GenericReturnValue
|
||||||
|
TALER_JSON_parse_age_groups (const json_t *root,
|
||||||
|
struct TALER_AgeMask *mask);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO: Add Peer2Peer Extension
|
* TODO: Add Peer2Peer Extension
|
||||||
*/
|
*/
|
||||||
|
@ -552,17 +552,6 @@ enum GNUNET_GenericReturnValue
|
|||||||
TALER_JSON_extensions_config_hash (const json_t *config,
|
TALER_JSON_extensions_config_hash (const json_t *config,
|
||||||
struct TALER_ExtensionConfigHash *eh);
|
struct TALER_ExtensionConfigHash *eh);
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses a JSON object { "extension": "age_restriction", "mask": <uint32> }.
|
|
||||||
*
|
|
||||||
* @param root is the json object
|
|
||||||
* @param[out] mask on succes, will contain the age mask
|
|
||||||
* @return #GNUNET_OK on success and #GNUNET_SYSERR on failure.
|
|
||||||
*/
|
|
||||||
enum GNUNET_GenericReturnValue
|
|
||||||
TALER_JSON_parse_agemask (const json_t *root,
|
|
||||||
struct TALER_AgeMask *mask);
|
|
||||||
|
|
||||||
#endif /* TALER_JSON_LIB_H_ */
|
#endif /* TALER_JSON_LIB_H_ */
|
||||||
|
|
||||||
/* End of taler_json_lib.h */
|
/* End of taler_json_lib.h */
|
||||||
|
@ -2144,6 +2144,19 @@ TALER_TESTING_cmd_wire_del (const char *label,
|
|||||||
unsigned int expected_http_status,
|
unsigned int expected_http_status,
|
||||||
bool bad_sig);
|
bool bad_sig);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sign all extensions that the exchange has to offer, f. e. the extension for
|
||||||
|
* age restriction. This has to be run before any withdrawal of age restricted
|
||||||
|
* can be performed.
|
||||||
|
*
|
||||||
|
* @param label command label.
|
||||||
|
* @param config_filename configuration filename.
|
||||||
|
* @return the command
|
||||||
|
*/
|
||||||
|
struct TALER_TESTING_Command
|
||||||
|
TALER_TESTING_cmd_exec_offline_sign_extensions (const char *label,
|
||||||
|
const char *config_filename);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sign all exchange denomination and online signing keys
|
* Sign all exchange denomination and online signing keys
|
||||||
|
@ -658,37 +658,4 @@ TALER_JSON_spec_i18n_str (const char *name,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
enum GNUNET_GenericReturnValue
|
|
||||||
TALER_JSON_parse_agemask (const json_t *root,
|
|
||||||
struct TALER_AgeMask *mask)
|
|
||||||
{
|
|
||||||
const char *name;
|
|
||||||
struct GNUNET_JSON_Specification spec[] = {
|
|
||||||
GNUNET_JSON_spec_string ("extension",
|
|
||||||
&name),
|
|
||||||
GNUNET_JSON_spec_uint32 ("mask",
|
|
||||||
&mask->mask),
|
|
||||||
GNUNET_JSON_spec_end ()
|
|
||||||
};
|
|
||||||
|
|
||||||
if (GNUNET_OK != GNUNET_JSON_parse (root,
|
|
||||||
spec,
|
|
||||||
NULL,
|
|
||||||
NULL))
|
|
||||||
{
|
|
||||||
return GNUNET_SYSERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! strncmp (name,
|
|
||||||
"age_restriction",
|
|
||||||
sizeof("age_restriction")))
|
|
||||||
{
|
|
||||||
return GNUNET_SYSERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GNUNET_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* end of json/json_helper.c */
|
/* end of json/json_helper.c */
|
||||||
|
@ -67,7 +67,7 @@
|
|||||||
/**
|
/**
|
||||||
* Set to 1 for extra debug logging.
|
* Set to 1 for extra debug logging.
|
||||||
*/
|
*/
|
||||||
#define DEBUG 0
|
#define DEBUG 1 /* FIXME-oec */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log error related to CURL operations.
|
* Log error related to CURL operations.
|
||||||
@ -839,9 +839,10 @@ decode_keys_json (const json_t *resp_obj,
|
|||||||
*/
|
*/
|
||||||
struct
|
struct
|
||||||
{ char *name;
|
{ char *name;
|
||||||
bool is_optional_age_restriction;} hive[2] = {
|
bool is_optional_age_restriction;}
|
||||||
|
hive[2] = {
|
||||||
{ "denoms", false },
|
{ "denoms", false },
|
||||||
{ "age_restricted_denoms", true },
|
{ "age_restricted_denoms", true }
|
||||||
};
|
};
|
||||||
|
|
||||||
for (size_t s = 0; s < sizeof(hive) / sizeof(hive[0]); s++)
|
for (size_t s = 0; s < sizeof(hive) / sizeof(hive[0]); s++)
|
||||||
|
@ -151,7 +151,7 @@ TALER_EXCHANGE_management_post_extensions (
|
|||||||
body = GNUNET_JSON_PACK (
|
body = GNUNET_JSON_PACK (
|
||||||
GNUNET_JSON_pack_object_steal ("extensions",
|
GNUNET_JSON_pack_object_steal ("extensions",
|
||||||
ped->extensions),
|
ped->extensions),
|
||||||
GNUNET_JSON_pack_data_auto ("extensions_sigs",
|
GNUNET_JSON_pack_data_auto ("extensions_sig",
|
||||||
&ped->extensions_sig));
|
&ped->extensions_sig));
|
||||||
|
|
||||||
eh = curl_easy_init ();
|
eh = curl_easy_init ();
|
||||||
@ -168,7 +168,7 @@ TALER_EXCHANGE_management_post_extensions (
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
json_decref (body);
|
json_decref (body);
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
"Requesting URL '%s'\n",
|
"Requesting URL '%s'\n",
|
||||||
ph->url);
|
ph->url);
|
||||||
GNUNET_assert (CURLE_OK == curl_easy_setopt (eh,
|
GNUNET_assert (CURLE_OK == curl_easy_setopt (eh,
|
||||||
|
@ -68,6 +68,7 @@ libtalertesting_la_SOURCES = \
|
|||||||
testing_api_cmd_oauth.c \
|
testing_api_cmd_oauth.c \
|
||||||
testing_api_cmd_offline_sign_fees.c \
|
testing_api_cmd_offline_sign_fees.c \
|
||||||
testing_api_cmd_offline_sign_keys.c \
|
testing_api_cmd_offline_sign_keys.c \
|
||||||
|
testing_api_cmd_offline_sign_extensions.c \
|
||||||
testing_api_cmd_set_wire_fee.c \
|
testing_api_cmd_set_wire_fee.c \
|
||||||
testing_api_cmd_recoup.c \
|
testing_api_cmd_recoup.c \
|
||||||
testing_api_cmd_recoup_refresh.c \
|
testing_api_cmd_recoup_refresh.c \
|
||||||
|
@ -168,6 +168,42 @@ run (void *cls,
|
|||||||
TALER_TESTING_cmd_end ()
|
TALER_TESTING_cmd_end ()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test withdrawal with age restriction. Success is expected, so it MUST be
|
||||||
|
* called _after_ TALER_TESTING_cmd_exec_offline_sign_extensions is called,
|
||||||
|
* i. e. age restriction is activated in the exchange!
|
||||||
|
*
|
||||||
|
* TODO: create a test that tries to withdraw coins with age restriction but
|
||||||
|
* (expectedly) fails because the exchange doesn't support age restriction
|
||||||
|
* yet.
|
||||||
|
*/
|
||||||
|
struct TALER_TESTING_Command withdraw_age[] = {
|
||||||
|
/**
|
||||||
|
* Move money to the exchange's bank account.
|
||||||
|
*/
|
||||||
|
CMD_TRANSFER_TO_EXCHANGE ("create-reserve-age",
|
||||||
|
"EUR:6.02"),
|
||||||
|
TALER_TESTING_cmd_check_bank_admin_transfer ("check-create-reserve-age",
|
||||||
|
"EUR:6.02",
|
||||||
|
bc.user42_payto,
|
||||||
|
bc.exchange_payto,
|
||||||
|
"create-reserve-age"),
|
||||||
|
/**
|
||||||
|
* Make a reserve exist, according to the previous
|
||||||
|
* transfer.
|
||||||
|
*/
|
||||||
|
CMD_EXEC_WIREWATCH ("wirewatch-age"),
|
||||||
|
/**
|
||||||
|
* Withdraw EUR:5.
|
||||||
|
*/
|
||||||
|
TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-age",
|
||||||
|
"create-reserve-age",
|
||||||
|
"EUR:5",
|
||||||
|
13,
|
||||||
|
MHD_HTTP_OK),
|
||||||
|
TALER_TESTING_cmd_end ()
|
||||||
|
};
|
||||||
|
|
||||||
struct TALER_TESTING_Command spend[] = {
|
struct TALER_TESTING_Command spend[] = {
|
||||||
/**
|
/**
|
||||||
* Spend the coin.
|
* Spend the coin.
|
||||||
@ -951,6 +987,8 @@ run (void *cls,
|
|||||||
"payto://x-taler-bank/localhost/2",
|
"payto://x-taler-bank/localhost/2",
|
||||||
MHD_HTTP_NO_CONTENT,
|
MHD_HTTP_NO_CONTENT,
|
||||||
false),
|
false),
|
||||||
|
TALER_TESTING_cmd_exec_offline_sign_extensions ("offline-sign-extensions",
|
||||||
|
CONFIG_FILE),
|
||||||
TALER_TESTING_cmd_exec_offline_sign_keys ("offline-sign-future-keys",
|
TALER_TESTING_cmd_exec_offline_sign_keys ("offline-sign-future-keys",
|
||||||
CONFIG_FILE),
|
CONFIG_FILE),
|
||||||
TALER_TESTING_cmd_exec_offline_sign_fees ("offline-sign-fees",
|
TALER_TESTING_cmd_exec_offline_sign_fees ("offline-sign-fees",
|
||||||
@ -963,6 +1001,8 @@ run (void *cls,
|
|||||||
wire),
|
wire),
|
||||||
TALER_TESTING_cmd_batch ("withdraw",
|
TALER_TESTING_cmd_batch ("withdraw",
|
||||||
withdraw),
|
withdraw),
|
||||||
|
TALER_TESTING_cmd_batch ("withdraw-age",
|
||||||
|
withdraw_age),
|
||||||
TALER_TESTING_cmd_batch ("spend",
|
TALER_TESTING_cmd_batch ("spend",
|
||||||
spend),
|
spend),
|
||||||
TALER_TESTING_cmd_batch ("refresh",
|
TALER_TESTING_cmd_batch ("refresh",
|
||||||
|
@ -150,7 +150,7 @@ fee_deposit = EUR:0.00
|
|||||||
fee_refresh = EUR:0.01
|
fee_refresh = EUR:0.01
|
||||||
fee_refund = EUR:0.01
|
fee_refund = EUR:0.01
|
||||||
rsa_keysize = 1024
|
rsa_keysize = 1024
|
||||||
age_restricted = true
|
age_restricted = YES
|
||||||
|
|
||||||
[coin_eur_ct_10_age_restricted]
|
[coin_eur_ct_10_age_restricted]
|
||||||
value = EUR:0.10
|
value = EUR:0.10
|
||||||
@ -162,7 +162,7 @@ fee_deposit = EUR:0.01
|
|||||||
fee_refresh = EUR:0.03
|
fee_refresh = EUR:0.03
|
||||||
fee_refund = EUR:0.01
|
fee_refund = EUR:0.01
|
||||||
rsa_keysize = 1024
|
rsa_keysize = 1024
|
||||||
age_restricted = true
|
age_restricted = YES
|
||||||
|
|
||||||
[coin_eur_1_age_restricted]
|
[coin_eur_1_age_restricted]
|
||||||
value = EUR:1
|
value = EUR:1
|
||||||
@ -174,7 +174,7 @@ fee_deposit = EUR:0.01
|
|||||||
fee_refresh = EUR:0.03
|
fee_refresh = EUR:0.03
|
||||||
fee_refund = EUR:0.01
|
fee_refund = EUR:0.01
|
||||||
rsa_keysize = 1024
|
rsa_keysize = 1024
|
||||||
age_restricted = true
|
age_restricted = YES
|
||||||
|
|
||||||
[coin_eur_5_age_restricted]
|
[coin_eur_5_age_restricted]
|
||||||
value = EUR:5
|
value = EUR:5
|
||||||
@ -186,7 +186,7 @@ fee_deposit = EUR:0.01
|
|||||||
fee_refresh = EUR:0.03
|
fee_refresh = EUR:0.03
|
||||||
fee_refund = EUR:0.01
|
fee_refund = EUR:0.01
|
||||||
rsa_keysize = 1024
|
rsa_keysize = 1024
|
||||||
age_restricted = true
|
age_restricted = YES
|
||||||
|
|
||||||
[coin_eur_10_age_restricted]
|
[coin_eur_10_age_restricted]
|
||||||
value = EUR:10
|
value = EUR:10
|
||||||
@ -198,4 +198,4 @@ fee_deposit = EUR:0.01
|
|||||||
fee_refresh = EUR:0.03
|
fee_refresh = EUR:0.03
|
||||||
fee_refund = EUR:0.01
|
fee_refund = EUR:0.01
|
||||||
rsa_keysize = 1024
|
rsa_keysize = 1024
|
||||||
age_restricted = true
|
age_restricted = YES
|
||||||
|
164
src/testing/testing_api_cmd_offline_sign_extensions.c
Normal file
164
src/testing/testing_api_cmd_offline_sign_extensions.c
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
This file is part of TALER
|
||||||
|
Copyright (C) 2022 Taler Systems SA
|
||||||
|
|
||||||
|
TALER is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published
|
||||||
|
by the Free Software Foundation; either version 3, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
TALER is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public
|
||||||
|
License along with TALER; see the file COPYING. If not,
|
||||||
|
see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file testing/testing_api_cmd_offline_sign_extensions.c
|
||||||
|
* @brief run the taler-exchange-offline command to sign extensions (and therefore activate them)
|
||||||
|
* @author Özgür Kesim
|
||||||
|
*/
|
||||||
|
#include "platform.h"
|
||||||
|
#include "taler_json_lib.h"
|
||||||
|
#include <gnunet/gnunet_curl_lib.h>
|
||||||
|
#include "taler_signatures.h"
|
||||||
|
#include "taler_testing_lib.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State for a "extensionssign" CMD.
|
||||||
|
*/
|
||||||
|
struct ExtensionsSignState
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process for the "extensionssign" command.
|
||||||
|
*/
|
||||||
|
struct GNUNET_OS_Process *extensionssign_proc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration file used by the command.
|
||||||
|
*/
|
||||||
|
const char *config_filename;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the command; calls the `taler-exchange-offline' program.
|
||||||
|
*
|
||||||
|
* @param cls closure.
|
||||||
|
* @param cmd the commaind being run.
|
||||||
|
* @param is interpreter state.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
extensionssign_run (void *cls,
|
||||||
|
const struct TALER_TESTING_Command *cmd,
|
||||||
|
struct TALER_TESTING_Interpreter *is)
|
||||||
|
{
|
||||||
|
struct ExtensionsSignState *ks = cls;
|
||||||
|
|
||||||
|
ks->extensionssign_proc
|
||||||
|
= GNUNET_OS_start_process (
|
||||||
|
GNUNET_OS_INHERIT_STD_ALL,
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
"taler-exchange-offline",
|
||||||
|
"taler-exchange-offline",
|
||||||
|
"-c", ks->config_filename,
|
||||||
|
"-L", "INFO",
|
||||||
|
"extensions",
|
||||||
|
"sign",
|
||||||
|
"upload",
|
||||||
|
NULL);
|
||||||
|
if (NULL == ks->extensionssign_proc)
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
TALER_TESTING_interpreter_fail (is);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TALER_TESTING_wait_for_sigchld (is);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free the state of a "extensionssign" CMD, and possibly kills its
|
||||||
|
* process if it did not terminate correctly.
|
||||||
|
*
|
||||||
|
* @param cls closure.
|
||||||
|
* @param cmd the command being freed.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
extensionssign_cleanup (void *cls,
|
||||||
|
const struct TALER_TESTING_Command *cmd)
|
||||||
|
{
|
||||||
|
struct ExtensionsSignState *ks = cls;
|
||||||
|
|
||||||
|
(void) cmd;
|
||||||
|
if (NULL != ks->extensionssign_proc)
|
||||||
|
{
|
||||||
|
GNUNET_break (0 ==
|
||||||
|
GNUNET_OS_process_kill (ks->extensionssign_proc,
|
||||||
|
SIGKILL));
|
||||||
|
GNUNET_OS_process_wait (ks->extensionssign_proc);
|
||||||
|
GNUNET_OS_process_destroy (ks->extensionssign_proc);
|
||||||
|
ks->extensionssign_proc = NULL;
|
||||||
|
}
|
||||||
|
GNUNET_free (ks);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Offer "extensionssign" CMD internal data to other commands.
|
||||||
|
*
|
||||||
|
* @param cls closure.
|
||||||
|
* @param[out] ret result
|
||||||
|
* @param trait name of the trait.
|
||||||
|
* @param index index number of the object to offer.
|
||||||
|
* @return #GNUNET_OK on success.
|
||||||
|
*/
|
||||||
|
static enum GNUNET_GenericReturnValue
|
||||||
|
extensionssign_traits (void *cls,
|
||||||
|
const void **ret,
|
||||||
|
const char *trait,
|
||||||
|
unsigned int index)
|
||||||
|
{
|
||||||
|
struct ExtensionsSignState *ks = cls;
|
||||||
|
struct TALER_TESTING_Trait traits[] = {
|
||||||
|
TALER_TESTING_make_trait_process (&ks->extensionssign_proc),
|
||||||
|
TALER_TESTING_trait_end ()
|
||||||
|
};
|
||||||
|
|
||||||
|
return TALER_TESTING_get_trait (traits,
|
||||||
|
ret,
|
||||||
|
trait,
|
||||||
|
index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct TALER_TESTING_Command
|
||||||
|
TALER_TESTING_cmd_exec_offline_sign_extensions (const char *label,
|
||||||
|
const char *config_filename)
|
||||||
|
{
|
||||||
|
struct ExtensionsSignState *ks;
|
||||||
|
|
||||||
|
ks = GNUNET_new (struct ExtensionsSignState);
|
||||||
|
ks->config_filename = config_filename;
|
||||||
|
{
|
||||||
|
struct TALER_TESTING_Command cmd = {
|
||||||
|
.cls = ks,
|
||||||
|
.label = label,
|
||||||
|
.run = &extensionssign_run,
|
||||||
|
.cleanup = &extensionssign_cleanup,
|
||||||
|
.traits = &extensionssign_traits
|
||||||
|
};
|
||||||
|
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* end of testing_api_cmd_exec_offline_sign_extensions.c */
|
Loading…
Reference in New Issue
Block a user