progress re: extension config upload
- taler-exchange-offline tool - now parses extensions - creates signed configuaration for upload - echanged-handler for /management/extensions adjusted to new datastructures
This commit is contained in:
parent
601c18caba
commit
6628f6a7af
@ -95,6 +95,11 @@
|
||||
*/
|
||||
#define OP_SETUP "exchange-setup-0"
|
||||
|
||||
/**
|
||||
* sign the enabled and configured extensions.
|
||||
*/
|
||||
#define OP_EXTENSIONS "exchange-extensions-0"
|
||||
|
||||
|
||||
/**
|
||||
* Our private key, initialized in #load_offline_key().
|
||||
@ -1663,6 +1668,24 @@ upload_keys (const char *exchange_url,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Upload extension configuration
|
||||
*
|
||||
* @param exchange_url base URL of the exchange
|
||||
* @param idx index of the operation we are performing (for logging)
|
||||
* @param value arguments for POSTing configurations of extensions
|
||||
*/
|
||||
static void
|
||||
upload_extensions (const char *exchange_url,
|
||||
size_t idx,
|
||||
const json_t *value)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "uploading extensions %s\n",
|
||||
json_dumps (value, JSON_INDENT (2)));
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform uploads based on the JSON in #out.
|
||||
*
|
||||
@ -1704,6 +1727,10 @@ trigger_upload (const char *exchange_url)
|
||||
.key = OP_UPLOAD_SIGS,
|
||||
.cb = &upload_keys
|
||||
},
|
||||
{
|
||||
.key = OP_EXTENSIONS,
|
||||
.cb = &upload_extensions
|
||||
},
|
||||
/* array termination */
|
||||
{
|
||||
.key = NULL
|
||||
@ -3316,9 +3343,14 @@ do_setup (char *const *args)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* struct extension carries the information about an extension together with
|
||||
* callbacks to parse the configuration and marshal it as JSON
|
||||
*/
|
||||
struct extension
|
||||
{
|
||||
char *name;
|
||||
bool enabled;
|
||||
bool critical;
|
||||
char *version;
|
||||
void *config;
|
||||
@ -3328,54 +3360,85 @@ struct extension
|
||||
json_t *(*config_json)(const struct extension *this);
|
||||
};
|
||||
|
||||
#define EXT_PREFIX "exchange-extension-"
|
||||
|
||||
#define DEFAULT_AGE_GROUPS "8:10:12:14:16:18:21"
|
||||
|
||||
static enum GNUNET_GenericReturnValue
|
||||
age_restriction_parse_config (struct extension *this, const char *section)
|
||||
{
|
||||
char *age_groups;
|
||||
struct TALER_AgeMask *mask = GNUNET_malloc (sizeof(struct TALER_AgeMask));
|
||||
char *age_groups = NULL;
|
||||
struct TALER_AgeMask mask = {0};
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
|
||||
ret = GNUNET_CONFIGURATION_get_value_yesno (kcfg, section, "ENABLED");
|
||||
|
||||
this->enabled = (GNUNET_YES == ret);
|
||||
|
||||
if (! this->enabled)
|
||||
return GNUNET_OK;
|
||||
|
||||
if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (kcfg,
|
||||
section,
|
||||
"AGE_GROUPS",
|
||||
&age_groups))
|
||||
goto ERROR;
|
||||
age_groups = DEFAULT_AGE_GROUPS;
|
||||
|
||||
if (GNUNET_OK != TALER_parse_age_group_string (age_groups, mask))
|
||||
goto ERROR;
|
||||
if (GNUNET_OK != TALER_parse_age_group_string (age_groups, &mask))
|
||||
{
|
||||
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
||||
section,
|
||||
"AGE_GROUPS");
|
||||
test_shutdown ();
|
||||
global_ret = EXIT_NOTCONFIGURED;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
this->config = mask;
|
||||
/* Don't look here. We just store the mask in/as the pointer .*/
|
||||
this->config = (void *) (size_t) mask.mask;
|
||||
return GNUNET_OK;
|
||||
|
||||
ERROR:
|
||||
GNUNET_free (mask);
|
||||
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
||||
section,
|
||||
"AGE_GROUPS");
|
||||
test_shutdown ();
|
||||
global_ret = EXIT_NOTCONFIGURED;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
|
||||
static json_t *
|
||||
age_restriction_json (const struct extension *this)
|
||||
{
|
||||
/* Don't look here. We just restore the mask from/as the pointer .*/
|
||||
struct TALER_AgeMask mask = { .mask = (uint32_t) (size_t) this->config };
|
||||
char *groups = TALER_age_mask_to_string (&mask);
|
||||
|
||||
char *groups = TALER_age_mask_to_string (this->config);
|
||||
return GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_bool ("critical",
|
||||
this->critical),
|
||||
GNUNET_JSON_pack_string ("version",
|
||||
this->version),
|
||||
GNUNET_JSON_pack_string ("age_groups", groups)
|
||||
);
|
||||
json_t *obj = GNUNET_JSON_PACK (GNUNET_JSON_pack_bool ("enabled",
|
||||
this->enabled));
|
||||
if (this->enabled)
|
||||
{
|
||||
int ret = json_object_update (obj, GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_bool ("enabled",
|
||||
this->enabled),
|
||||
GNUNET_JSON_pack_bool ("critical",
|
||||
this->critical),
|
||||
GNUNET_JSON_pack_string ("version",
|
||||
this->version),
|
||||
GNUNET_JSON_pack_string ("age_groups",
|
||||
groups)
|
||||
));
|
||||
if (0>ret)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"couldn't update json object for age_restriction");
|
||||
test_shutdown ();
|
||||
global_ret = EXIT_FAILURE;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
static struct extension extensions[] = {
|
||||
{
|
||||
.name = "age-restriction",
|
||||
.name = "age_restriction",
|
||||
.version = "1",
|
||||
.config = 0,
|
||||
.parse_config = &age_restriction_parse_config,
|
||||
.config_json = &age_restriction_json,
|
||||
},
|
||||
@ -3387,9 +3450,13 @@ static struct extension extensions[] = {
|
||||
static const struct extension*
|
||||
get_extension (const char *extension)
|
||||
{
|
||||
for (const struct extension *known = extensions; NULL != known->name; known++)
|
||||
for (const struct extension *known = extensions;
|
||||
NULL != known->name;
|
||||
known++)
|
||||
{
|
||||
if (0 == strncasecmp (extension, known->name, strlen (known->name)))
|
||||
if (0 == strncasecmp (extension,
|
||||
known->name,
|
||||
strlen (known->name)))
|
||||
return known;
|
||||
}
|
||||
return NULL;
|
||||
@ -3397,100 +3464,47 @@ get_extension (const char *extension)
|
||||
|
||||
|
||||
static void
|
||||
show_extensions (void *cls, const char *section)
|
||||
collect_extensions (void *cls, const char *section)
|
||||
{
|
||||
json_t *obj = (json_t *) cls;
|
||||
const char *name;
|
||||
const struct extension *extension;
|
||||
|
||||
if (0 != global_ret)
|
||||
return;
|
||||
|
||||
if (0 != strncasecmp (section,
|
||||
EXT_PREFIX,
|
||||
sizeof(EXT_PREFIX) - 1))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 == strncasecmp (section,
|
||||
"exchange-extension-",
|
||||
sizeof("exchange-extension-") - 1))
|
||||
{
|
||||
const char *name = section + sizeof("exchange-extension-") - 1;
|
||||
const struct extension *extension = get_extension (name);
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
|
||||
if (NULL == extension)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Unsupported extension `%s` (section [%s]).\n", name,
|
||||
section);
|
||||
test_shutdown ();
|
||||
global_ret = EXIT_INVALIDARGUMENT;
|
||||
return;
|
||||
}
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "found extension %s\n", name);
|
||||
{
|
||||
bool enabled = (GNUNET_YES ==
|
||||
GNUNET_CONFIGURATION_get_value_yesno (
|
||||
kcfg, section, "ENABLED"));
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
|
||||
"\textension is %s\n",
|
||||
enabled?"ENABLED":"DISABLED");
|
||||
if (! enabled)
|
||||
return;
|
||||
|
||||
ret = extension->parse_config ((struct extension *) extension, section);
|
||||
if (GNUNET_OK != ret)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Couldn't parse configuration for extension `%s` (section [%s]).\n",
|
||||
name,
|
||||
section);
|
||||
test_shutdown ();
|
||||
global_ret = EXIT_INVALIDARGUMENT;
|
||||
return;
|
||||
}
|
||||
|
||||
json_t *cfg = extension->config_json (extension);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
|
||||
"\tconfig: %s\n",
|
||||
json_dumps (cfg, JSON_INDENT (2)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sign_extensions (void *cls, const char *section)
|
||||
{
|
||||
if (0 != global_ret)
|
||||
name = section + sizeof(EXT_PREFIX) - 1;
|
||||
|
||||
if (NULL == (extension = get_extension (name)))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Unsupported extension `%s` (section [%s]).\n", name,
|
||||
section);
|
||||
test_shutdown ();
|
||||
global_ret = EXIT_NOTCONFIGURED;
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 == strncasecmp (section,
|
||||
"exchange-extension-",
|
||||
sizeof("exchange-extension-") - 1))
|
||||
if (GNUNET_OK != extension->parse_config ((struct extension *) extension,
|
||||
section))
|
||||
{
|
||||
const char *name = section + sizeof("exchange-extension-") - 1;
|
||||
const struct extension *extension = get_extension (name);
|
||||
|
||||
if (NULL == extension)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Unsupported extension `%s` (section [%s]).\n", name,
|
||||
section);
|
||||
test_shutdown ();
|
||||
global_ret = EXIT_INVALIDARGUMENT;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (GNUNET_YES ==
|
||||
GNUNET_CONFIGURATION_get_value_yesno (
|
||||
kcfg, section, "ENABLED"))
|
||||
{
|
||||
// TODO
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "TODO signing extension %s\n",
|
||||
name);
|
||||
}
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Couldn't parse configuration for extension `%s` (section [%s]).\n",
|
||||
name,
|
||||
section);
|
||||
test_shutdown ();
|
||||
global_ret = EXIT_NOTCONFIGURED;
|
||||
return;
|
||||
}
|
||||
|
||||
json_object_set (obj, name, extension->config_json (extension));
|
||||
}
|
||||
|
||||
|
||||
@ -3501,18 +3515,102 @@ static void
|
||||
do_extensions_show (char *const *args)
|
||||
{
|
||||
|
||||
json_t *obj = json_object ();
|
||||
json_t *exts = json_object ();
|
||||
|
||||
GNUNET_CONFIGURATION_iterate_sections (kcfg,
|
||||
&show_extensions,
|
||||
NULL);
|
||||
&collect_extensions,
|
||||
exts);
|
||||
json_object_set (obj, "extensions", exts);
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "%s\n",
|
||||
json_dumps (obj, JSON_INDENT (2)));
|
||||
|
||||
json_decref (obj);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Sign the configurations of the enabled extensions
|
||||
*/
|
||||
static void
|
||||
do_extensions_sign (char *const *args)
|
||||
{
|
||||
json_t *obj = json_object ();
|
||||
json_t *exts = json_object ();
|
||||
json_t *sigs = json_object ();
|
||||
|
||||
GNUNET_CONFIGURATION_iterate_sections (kcfg,
|
||||
&collect_extensions,
|
||||
exts);
|
||||
json_object_set (obj, "extensions", exts);
|
||||
|
||||
/* sign the extensions */
|
||||
{
|
||||
const char *name;
|
||||
json_t *config;
|
||||
|
||||
json_object_foreach (exts, name, config){
|
||||
struct TALER_ExtensionConfigHash h_config;
|
||||
struct TALER_MasterSignatureP sig;
|
||||
|
||||
if (GNUNET_OK != TALER_extension_config_hash (config, &h_config))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"error while hashing config for extension %s\n",
|
||||
name);
|
||||
return;
|
||||
}
|
||||
|
||||
TALER_exchange_offline_extension_config_hash_sign (h_config, &master_priv,
|
||||
&sig);
|
||||
json_object_update (sigs,
|
||||
GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_auto (
|
||||
name,
|
||||
&sig)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
json_object_set (obj, "extensions_sigs", sigs);
|
||||
|
||||
output_operation (OP_EXTENSIONS, obj);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_extensions_sign (char *const *args)
|
||||
cmd_handler (char *const *args, const struct SubCommand *cmds)
|
||||
{
|
||||
GNUNET_CONFIGURATION_iterate_sections (kcfg,
|
||||
&sign_extensions,
|
||||
NULL);
|
||||
nxt = NULL;
|
||||
for (unsigned int i = 0; NULL != cmds[i].name; i++)
|
||||
{
|
||||
if (0 == strcasecmp (cmds[i].name,
|
||||
args[0]))
|
||||
{
|
||||
cmds[i].cb (&args[1]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != strcasecmp ("help",
|
||||
args[0]))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
|
||||
"Unexpected command `%s'\n",
|
||||
args[0]);
|
||||
global_ret = EXIT_INVALIDARGUMENT;
|
||||
}
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
|
||||
"Supported subcommands:\n");
|
||||
for (unsigned int i = 0; NULL != cmds[i].name; i++)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
|
||||
"- %s: %s\n",
|
||||
cmds[i].name,
|
||||
cmds[i].help);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3536,6 +3634,7 @@ do_work_extensions (char *const *args)
|
||||
.name = NULL,
|
||||
}
|
||||
};
|
||||
|
||||
if (NULL == args[0])
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
@ -3544,34 +3643,9 @@ do_work_extensions (char *const *args)
|
||||
global_ret = EXIT_INVALIDARGUMENT;
|
||||
return;
|
||||
}
|
||||
nxt = NULL;
|
||||
for (unsigned int i = 0; NULL != cmds[i].name; i++)
|
||||
{
|
||||
if (0 == strcasecmp (cmds[i].name,
|
||||
args[0]))
|
||||
{
|
||||
cmds[i].cb (&args[1]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != strcasecmp ("help",
|
||||
args[0]))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
|
||||
"Unexpected command `%s'\n",
|
||||
args[0]);
|
||||
global_ret = EXIT_INVALIDARGUMENT;
|
||||
}
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
|
||||
"Supported subcommands:\n");
|
||||
for (unsigned int i = 0; NULL != cmds[i].name; i++)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
|
||||
"- %s: %s\n",
|
||||
cmds[i].name,
|
||||
cmds[i].help);
|
||||
}
|
||||
cmd_handler (args, cmds);
|
||||
next (args + 1);
|
||||
}
|
||||
|
||||
|
||||
@ -3663,34 +3737,7 @@ work (void *cls)
|
||||
};
|
||||
(void) cls;
|
||||
|
||||
nxt = NULL;
|
||||
for (unsigned int i = 0; NULL != cmds[i].name; i++)
|
||||
{
|
||||
if (0 == strcasecmp (cmds[i].name,
|
||||
args[0]))
|
||||
{
|
||||
cmds[i].cb (&args[1]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != strcasecmp ("help",
|
||||
args[0]))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
|
||||
"Unexpected command `%s'\n",
|
||||
args[0]);
|
||||
global_ret = EXIT_INVALIDARGUMENT;
|
||||
}
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
|
||||
"Supported subcommands:\n");
|
||||
for (unsigned int i = 0; NULL != cmds[i].name; i++)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
|
||||
"- %s: %s\n",
|
||||
cmds[i].name,
|
||||
cmds[i].help);
|
||||
}
|
||||
cmd_handler (args, cmds);
|
||||
}
|
||||
|
||||
|
||||
|
@ -176,7 +176,7 @@ TEH_handler_management_post_extensions (
|
||||
struct MHD_Connection *connection,
|
||||
const json_t *root)
|
||||
{
|
||||
struct SetExtensionsContext sec = {0};
|
||||
MHD_RESULT ret;
|
||||
json_t *extensions;
|
||||
json_t *extensions_sigs;
|
||||
struct GNUNET_JSON_Specification top_spec[] = {
|
||||
@ -186,9 +186,9 @@ TEH_handler_management_post_extensions (
|
||||
&extensions_sigs),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
MHD_RESULT ret;
|
||||
struct SetExtensionsContext sec = {0};
|
||||
|
||||
// Parse the top level json structure
|
||||
/* Parse the top level json structure */
|
||||
{
|
||||
enum GNUNET_GenericReturnValue res;
|
||||
|
||||
@ -201,9 +201,9 @@ TEH_handler_management_post_extensions (
|
||||
return MHD_YES; /* failure */
|
||||
}
|
||||
|
||||
// Ensure we have two arrays of the same size
|
||||
if (! (json_is_array (extensions) &&
|
||||
json_is_array (extensions_sigs)) )
|
||||
/* Ensure we have two objects of the same size */
|
||||
if (! (json_is_object (extensions) &&
|
||||
json_is_object (extensions_sigs)) )
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
GNUNET_JSON_parse_free (top_spec);
|
||||
@ -211,11 +211,11 @@ TEH_handler_management_post_extensions (
|
||||
connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
||||
"array expected for extensions and extensions_sigs");
|
||||
"objects expected for extensions and extensions_sigs");
|
||||
}
|
||||
|
||||
sec.num_extensions = json_array_size (extensions_sigs);
|
||||
if (json_array_size (extensions) != sec.num_extensions)
|
||||
sec.num_extensions = json_object_size (extensions);
|
||||
if (json_object_size (extensions_sigs) != sec.num_extensions)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
GNUNET_JSON_parse_free (top_spec);
|
||||
@ -223,7 +223,7 @@ TEH_handler_management_post_extensions (
|
||||
connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
||||
"arrays extensions and extensions_sigs are not of the same size");
|
||||
"objects extensions and extensions_sigs are not of the same size");
|
||||
}
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
@ -234,120 +234,98 @@ TEH_handler_management_post_extensions (
|
||||
sec.extensions_sigs = GNUNET_new_array (sec.num_extensions,
|
||||
struct TALER_MasterSignatureP);
|
||||
|
||||
// Now parse individual extensions and signatures from those arrays.
|
||||
for (unsigned int i = 0; i<sec.num_extensions; i++)
|
||||
/* Now parse individual extensions and signatures from those objects. */
|
||||
{
|
||||
// 1. parse the extension out of the json
|
||||
enum GNUNET_GenericReturnValue res;
|
||||
const struct TALER_Extension *extension;
|
||||
const char *name;
|
||||
struct GNUNET_JSON_Specification ext_spec[] = {
|
||||
GNUNET_JSON_spec_string ("extension",
|
||||
&name),
|
||||
GNUNET_JSON_spec_json ("config",
|
||||
&sec.extensions[i].config),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
json_t *config;
|
||||
int idx = 0;
|
||||
|
||||
res = TALER_MHD_parse_json_array (connection,
|
||||
extensions,
|
||||
ext_spec,
|
||||
i,
|
||||
-1);
|
||||
if (GNUNET_SYSERR == res)
|
||||
{
|
||||
ret = MHD_NO; /* hard failure */
|
||||
goto CLEANUP;
|
||||
}
|
||||
if (GNUNET_NO == res)
|
||||
{
|
||||
ret = MHD_YES;
|
||||
goto CLEANUP;
|
||||
}
|
||||
json_object_foreach (extensions, name, config){
|
||||
|
||||
/* 2. Make sure name refers to a supported extension */
|
||||
if (GNUNET_OK != TALER_extension_get_by_name (name,
|
||||
(const struct
|
||||
TALER_Extension **)
|
||||
TEH_extensions,
|
||||
&extension))
|
||||
{
|
||||
ret = TALER_MHD_reply_with_error (
|
||||
connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
||||
"invalid extension type");
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
sec.extensions[i].type = extension->type;
|
||||
|
||||
/* 3. Extract the signature out of the json array */
|
||||
{
|
||||
enum GNUNET_GenericReturnValue res;
|
||||
struct GNUNET_JSON_Specification sig_spec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto (NULL,
|
||||
&sec.extensions_sigs[i]),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
res = TALER_MHD_parse_json_array (connection,
|
||||
extensions_sigs,
|
||||
sig_spec,
|
||||
i,
|
||||
-1);
|
||||
if (GNUNET_SYSERR == res)
|
||||
/* 1. Make sure name refers to a supported extension */
|
||||
if (GNUNET_OK != TALER_extension_get_by_name (name,
|
||||
(const struct
|
||||
TALER_Extension **)
|
||||
TEH_extensions,
|
||||
&extension))
|
||||
{
|
||||
ret = MHD_NO; /* hard failure */
|
||||
ret = TALER_MHD_reply_with_error (
|
||||
connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
||||
"invalid extension type");
|
||||
goto CLEANUP;
|
||||
}
|
||||
if (GNUNET_NO == res)
|
||||
|
||||
sec.extensions[idx].config = config;
|
||||
sec.extensions[idx].type = extension->type;
|
||||
|
||||
/* 2. Extract the corresponding signature */
|
||||
{
|
||||
ret = MHD_YES;
|
||||
struct GNUNET_JSON_Specification sig_spec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto (name,
|
||||
&sec.extensions_sigs[idx]),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
if (GNUNET_OK != TALER_MHD_parse_json_data (connection,
|
||||
extensions_sigs,
|
||||
sig_spec))
|
||||
{
|
||||
GNUNET_JSON_parse_free (sig_spec);
|
||||
ret = TALER_MHD_reply_with_error (
|
||||
connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
||||
"extension signature missing");
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
GNUNET_JSON_parse_free (sig_spec);
|
||||
}
|
||||
|
||||
/* 3. Verify the signature of the config */
|
||||
if (GNUNET_OK != config_verify (
|
||||
sec.extensions[idx].config,
|
||||
&TEH_master_public_key,
|
||||
&sec.extensions_sigs[idx]))
|
||||
{
|
||||
ret = TALER_MHD_reply_with_error (
|
||||
connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
||||
"invalid signature for extension");
|
||||
goto CLEANUP;
|
||||
}
|
||||
}
|
||||
|
||||
/* 4. Verify the signature of the config */
|
||||
if (GNUNET_OK != config_verify (
|
||||
sec.extensions[i].config,
|
||||
&TEH_master_public_key,
|
||||
&sec.extensions_sigs[i]))
|
||||
{
|
||||
ret = TALER_MHD_reply_with_error (
|
||||
connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
||||
"invalid signature for extension");
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* 4. Make sure the config is sound */
|
||||
if (GNUNET_OK != extension->test_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;
|
||||
|
||||
/* 5. Make sure the config is sound */
|
||||
if (GNUNET_OK != extension->test_config (sec.extensions[i].config))
|
||||
{
|
||||
GNUNET_JSON_parse_free (ext_spec);
|
||||
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++;
|
||||
|
||||
/* We have a validly signed JSON object for the extension.
|
||||
* Increment its refcount and free the parser for the extension.
|
||||
*/
|
||||
json_incref (sec.extensions[i].config);
|
||||
GNUNET_JSON_parse_free (ext_spec);
|
||||
} /* json_object_foreach */
|
||||
}
|
||||
|
||||
} /* for-loop */
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Received %u extensions\n",
|
||||
sec.num_extensions);
|
||||
|
||||
// now run the transaction to persist the configurations
|
||||
/* now run the transaction to persist the configurations */
|
||||
{
|
||||
enum GNUNET_GenericReturnValue res;
|
||||
|
||||
|
@ -78,9 +78,10 @@ WIRE_GATEWAY_URL = "http://localhost:9081/2/"
|
||||
HTTP_PORT = 9081
|
||||
|
||||
# Enabled extensions
|
||||
[exchange-extension-age-restriction]
|
||||
[exchange-extension-age_restriction]
|
||||
ENABLED = YES
|
||||
AGE_GROUPS = "8:10:12:14:16:18:21"
|
||||
# default age groups:
|
||||
#AGE_GROUPS = "8:10:12:14:16:18:21"
|
||||
|
||||
# Sections starting with "coin_" specify which denominations
|
||||
# the exchange should support (and their respective fee structure)
|
||||
|
@ -84,14 +84,14 @@ TALER_parse_age_group_string (const char *groups,
|
||||
struct TALER_AgeMask *mask)
|
||||
{
|
||||
|
||||
const char *end = groups + strlen (groups);
|
||||
const char *pos = groups;
|
||||
unsigned int prev = 0;
|
||||
unsigned int val = 0;
|
||||
char c;
|
||||
|
||||
while (pos < end)
|
||||
while (*pos)
|
||||
{
|
||||
char c = *pos++;
|
||||
c = *pos++;
|
||||
if (':' == c)
|
||||
{
|
||||
if (prev >= val)
|
||||
@ -100,23 +100,23 @@ TALER_parse_age_group_string (const char *groups,
|
||||
mask->mask |= 1 << val;
|
||||
prev = val;
|
||||
val = 0;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ('0'>c || '9'<c)
|
||||
return GNUNET_SYSERR;
|
||||
|
||||
val = 10 * val + c - '0';
|
||||
if ('0'>c || '9'<c)
|
||||
return GNUNET_SYSERR;
|
||||
|
||||
if (0>=val || 32<=val)
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
val = 10 * val + c - '0';
|
||||
|
||||
if (0>=val || 32<=val)
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
if (0>=val || 32<=val || prev>=val)
|
||||
if (0>val || 32<=val || prev>=val)
|
||||
return GNUNET_SYSERR;
|
||||
|
||||
mask->mask |= 1 << val;
|
||||
mask->mask |= (1 << val);
|
||||
mask->mask |= 1; // mark zeroth group, too
|
||||
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user