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,
|
||||
uhs[i].key))
|
||||
{
|
||||
|
||||
found = true;
|
||||
uhs[i].cb (exchange_url,
|
||||
index,
|
||||
|
@ -736,6 +736,12 @@ handle_post_management (struct TEH_RequestContext *rc,
|
||||
return TEH_handler_management_post_wire_fees (rc->connection,
|
||||
root);
|
||||
}
|
||||
if (0 == strcmp (args[0],
|
||||
"extensions"))
|
||||
{
|
||||
return TEH_handler_management_post_extensions (rc->connection,
|
||||
root);
|
||||
}
|
||||
GNUNET_break_op (0);
|
||||
return r404 (rc->connection,
|
||||
"/management/*");
|
||||
|
@ -1755,7 +1755,7 @@ create_krd (struct TEH_KeyStateHandle *ksh,
|
||||
json_t *sig;
|
||||
int r;
|
||||
|
||||
r = json_object_set_new (
|
||||
r = json_object_set (
|
||||
keys,
|
||||
"extensions",
|
||||
extensions);
|
||||
@ -1778,7 +1778,7 @@ create_krd (struct TEH_KeyStateHandle *ksh,
|
||||
{
|
||||
GNUNET_assert (
|
||||
0 ==
|
||||
json_object_set_new (
|
||||
json_object_set (
|
||||
keys,
|
||||
"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_CONTAINER_Heap *heap;
|
||||
struct GNUNET_HashContext *hash_context;
|
||||
bool age_restriction_active =
|
||||
TALER_extensions_is_enabled_type (TALER_Extension_AgeRestriction);
|
||||
|
||||
sctx.signkeys = json_array ();
|
||||
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.
|
||||
/* 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 ();
|
||||
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 -
|
||||
* depending on the settings and the properties of the denomination */
|
||||
if (NULL != age_restricted_denoms &&
|
||||
0 != dk->meta.age_restrictions.mask)
|
||||
{
|
||||
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);
|
||||
array = age_restricted_denoms;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
array = denoms;
|
||||
}
|
||||
|
||||
GNUNET_assert (
|
||||
0 ==
|
||||
@ -1990,6 +1991,7 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GNUNET_CONTAINER_heap_destroy (heap);
|
||||
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",
|
||||
GNUNET_TIME_timestamp2s (last_cpd));
|
||||
json_decref (denoms);
|
||||
if (NULL != age_restricted_denoms)
|
||||
if (age_restriction_active && NULL != age_restricted_denoms)
|
||||
json_decref (age_restricted_denoms);
|
||||
json_decref (sctx.signkeys);
|
||||
json_decref (recoup);
|
||||
|
@ -91,6 +91,8 @@ set_extensions (void *cls,
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
}
|
||||
|
||||
GNUNET_assert(NULL != ext->config);
|
||||
|
||||
config = json_dumps (ext->config, JSON_COMPACT | JSON_SORT_KEYS);
|
||||
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
|
||||
TEH_handler_management_post_extensions (
|
||||
struct MHD_Connection *connection,
|
||||
@ -204,57 +258,18 @@ TEH_handler_management_post_extensions (
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"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. */
|
||||
if (GNUNET_OK !=
|
||||
verify_extensions_from_json (extensions, &sec))
|
||||
{
|
||||
const struct TALER_Extension *extension = NULL;
|
||||
const char *name;
|
||||
json_t *config;
|
||||
int idx = 0;
|
||||
|
||||
json_object_foreach (extensions, name, config){
|
||||
|
||||
/* 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_JSON_parse_free (top_spec);
|
||||
return TALER_MHD_reply_with_error (
|
||||
connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
||||
"invalid object");
|
||||
}
|
||||
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Received %u extensions\n",
|
||||
sec.num_extensions);
|
||||
|
@ -247,7 +247,7 @@ age_restriction_load_json_config (
|
||||
struct TALER_AgeMask mask = {0};
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
|
||||
ret = TALER_JSON_parse_agemask (jconfig, &mask);
|
||||
ret = TALER_JSON_parse_age_groups (jconfig, &mask);
|
||||
if (GNUNET_OK != ret)
|
||||
return ret;
|
||||
|
||||
@ -323,7 +323,7 @@ age_restriction_test_json_config (
|
||||
{
|
||||
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 */
|
||||
|
@ -247,27 +247,31 @@ TALER_extensions_load_taler_config (
|
||||
}
|
||||
|
||||
|
||||
static enum GNUNET_GenericReturnValue
|
||||
is_json_extension_config (
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_extensions_is_json_config (
|
||||
json_t *obj,
|
||||
int *critical,
|
||||
const char **version,
|
||||
json_t **config)
|
||||
{
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
json_t *cfg;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_boolean ("critical",
|
||||
critical),
|
||||
GNUNET_JSON_spec_string ("version",
|
||||
version),
|
||||
GNUNET_JSON_spec_json ("config",
|
||||
config),
|
||||
&cfg),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
ret = GNUNET_JSON_parse (obj, spec, NULL, NULL);
|
||||
if (GNUNET_OK == ret)
|
||||
{
|
||||
*config = json_copy (cfg);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -300,7 +304,7 @@ TALER_extensions_load_json_config (
|
||||
|
||||
/* load and verify criticality, version, etc. */
|
||||
if (GNUNET_OK !=
|
||||
is_json_extension_config (
|
||||
TALER_extensions_is_json_config (
|
||||
blob, &critical, &version, &config))
|
||||
return GNUNET_SYSERR;
|
||||
|
||||
|
@ -85,6 +85,31 @@ enum GNUNET_GenericReturnValue
|
||||
TALER_extensions_load_taler_config (
|
||||
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
|
||||
*/
|
||||
@ -156,20 +181,6 @@ TALER_extensions_verify_json_config_signature (
|
||||
struct TALER_MasterSignatureP *extensions_sig,
|
||||
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
|
||||
@ -234,6 +245,18 @@ TALER_extensions_age_restriction_enabled ();
|
||||
size_t
|
||||
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
|
||||
*/
|
||||
|
@ -552,17 +552,6 @@ enum GNUNET_GenericReturnValue
|
||||
TALER_JSON_extensions_config_hash (const json_t *config,
|
||||
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_ */
|
||||
|
||||
/* End of taler_json_lib.h */
|
||||
|
@ -2144,6 +2144,19 @@ TALER_TESTING_cmd_wire_del (const char *label,
|
||||
unsigned int expected_http_status,
|
||||
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
|
||||
|
@ -658,37 +658,4 @@ TALER_JSON_spec_i18n_str (const char *name,
|
||||
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 */
|
||||
|
@ -67,7 +67,7 @@
|
||||
/**
|
||||
* Set to 1 for extra debug logging.
|
||||
*/
|
||||
#define DEBUG 0
|
||||
#define DEBUG 1 /* FIXME-oec */
|
||||
|
||||
/**
|
||||
* Log error related to CURL operations.
|
||||
@ -839,9 +839,10 @@ decode_keys_json (const json_t *resp_obj,
|
||||
*/
|
||||
struct
|
||||
{ char *name;
|
||||
bool is_optional_age_restriction;} hive[2] = {
|
||||
bool is_optional_age_restriction;}
|
||||
hive[2] = {
|
||||
{ "denoms", false },
|
||||
{ "age_restricted_denoms", true },
|
||||
{ "age_restricted_denoms", true }
|
||||
};
|
||||
|
||||
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 (
|
||||
GNUNET_JSON_pack_object_steal ("extensions",
|
||||
ped->extensions),
|
||||
GNUNET_JSON_pack_data_auto ("extensions_sigs",
|
||||
GNUNET_JSON_pack_data_auto ("extensions_sig",
|
||||
&ped->extensions_sig));
|
||||
|
||||
eh = curl_easy_init ();
|
||||
@ -168,7 +168,7 @@ TALER_EXCHANGE_management_post_extensions (
|
||||
return NULL;
|
||||
}
|
||||
json_decref (body);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Requesting URL '%s'\n",
|
||||
ph->url);
|
||||
GNUNET_assert (CURLE_OK == curl_easy_setopt (eh,
|
||||
|
@ -68,6 +68,7 @@ libtalertesting_la_SOURCES = \
|
||||
testing_api_cmd_oauth.c \
|
||||
testing_api_cmd_offline_sign_fees.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_recoup.c \
|
||||
testing_api_cmd_recoup_refresh.c \
|
||||
|
@ -168,6 +168,42 @@ run (void *cls,
|
||||
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[] = {
|
||||
/**
|
||||
* Spend the coin.
|
||||
@ -951,6 +987,8 @@ run (void *cls,
|
||||
"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",
|
||||
@ -963,6 +1001,8 @@ run (void *cls,
|
||||
wire),
|
||||
TALER_TESTING_cmd_batch ("withdraw",
|
||||
withdraw),
|
||||
TALER_TESTING_cmd_batch ("withdraw-age",
|
||||
withdraw_age),
|
||||
TALER_TESTING_cmd_batch ("spend",
|
||||
spend),
|
||||
TALER_TESTING_cmd_batch ("refresh",
|
||||
|
@ -150,7 +150,7 @@ fee_deposit = EUR:0.00
|
||||
fee_refresh = EUR:0.01
|
||||
fee_refund = EUR:0.01
|
||||
rsa_keysize = 1024
|
||||
age_restricted = true
|
||||
age_restricted = YES
|
||||
|
||||
[coin_eur_ct_10_age_restricted]
|
||||
value = EUR:0.10
|
||||
@ -162,7 +162,7 @@ fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
rsa_keysize = 1024
|
||||
age_restricted = true
|
||||
age_restricted = YES
|
||||
|
||||
[coin_eur_1_age_restricted]
|
||||
value = EUR:1
|
||||
@ -174,7 +174,7 @@ fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
rsa_keysize = 1024
|
||||
age_restricted = true
|
||||
age_restricted = YES
|
||||
|
||||
[coin_eur_5_age_restricted]
|
||||
value = EUR:5
|
||||
@ -186,7 +186,7 @@ fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
rsa_keysize = 1024
|
||||
age_restricted = true
|
||||
age_restricted = YES
|
||||
|
||||
[coin_eur_10_age_restricted]
|
||||
value = EUR:10
|
||||
@ -198,4 +198,4 @@ fee_deposit = EUR:0.01
|
||||
fee_refresh = EUR:0.03
|
||||
fee_refund = EUR:0.01
|
||||
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