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"
|
#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().
|
* 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.
|
* Perform uploads based on the JSON in #out.
|
||||||
*
|
*
|
||||||
@ -1704,6 +1727,10 @@ trigger_upload (const char *exchange_url)
|
|||||||
.key = OP_UPLOAD_SIGS,
|
.key = OP_UPLOAD_SIGS,
|
||||||
.cb = &upload_keys
|
.cb = &upload_keys
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.key = OP_EXTENSIONS,
|
||||||
|
.cb = &upload_extensions
|
||||||
|
},
|
||||||
/* array termination */
|
/* array termination */
|
||||||
{
|
{
|
||||||
.key = NULL
|
.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
|
struct extension
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
|
bool enabled;
|
||||||
bool critical;
|
bool critical;
|
||||||
char *version;
|
char *version;
|
||||||
void *config;
|
void *config;
|
||||||
@ -3328,54 +3360,85 @@ struct extension
|
|||||||
json_t *(*config_json)(const struct extension *this);
|
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
|
static enum GNUNET_GenericReturnValue
|
||||||
age_restriction_parse_config (struct extension *this, const char *section)
|
age_restriction_parse_config (struct extension *this, const char *section)
|
||||||
{
|
{
|
||||||
char *age_groups;
|
char *age_groups = NULL;
|
||||||
struct TALER_AgeMask *mask = GNUNET_malloc (sizeof(struct TALER_AgeMask));
|
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,
|
if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (kcfg,
|
||||||
section,
|
section,
|
||||||
"AGE_GROUPS",
|
"AGE_GROUPS",
|
||||||
&age_groups))
|
&age_groups))
|
||||||
goto ERROR;
|
age_groups = DEFAULT_AGE_GROUPS;
|
||||||
|
|
||||||
if (GNUNET_OK != TALER_parse_age_group_string (age_groups, mask))
|
if (GNUNET_OK != TALER_parse_age_group_string (age_groups, &mask))
|
||||||
goto ERROR;
|
{
|
||||||
|
|
||||||
this->config = mask;
|
|
||||||
return GNUNET_OK;
|
|
||||||
|
|
||||||
ERROR:
|
|
||||||
GNUNET_free (mask);
|
|
||||||
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
||||||
section,
|
section,
|
||||||
"AGE_GROUPS");
|
"AGE_GROUPS");
|
||||||
test_shutdown ();
|
test_shutdown ();
|
||||||
global_ret = EXIT_NOTCONFIGURED;
|
global_ret = EXIT_NOTCONFIGURED;
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't look here. We just store the mask in/as the pointer .*/
|
||||||
|
this->config = (void *) (size_t) mask.mask;
|
||||||
|
return GNUNET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static json_t *
|
static json_t *
|
||||||
age_restriction_json (const struct extension *this)
|
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);
|
json_t *obj = GNUNET_JSON_PACK (GNUNET_JSON_pack_bool ("enabled",
|
||||||
return GNUNET_JSON_PACK (
|
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",
|
GNUNET_JSON_pack_bool ("critical",
|
||||||
this->critical),
|
this->critical),
|
||||||
GNUNET_JSON_pack_string ("version",
|
GNUNET_JSON_pack_string ("version",
|
||||||
this->version),
|
this->version),
|
||||||
GNUNET_JSON_pack_string ("age_groups", groups)
|
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[] = {
|
static struct extension extensions[] = {
|
||||||
{
|
{
|
||||||
.name = "age-restriction",
|
.name = "age_restriction",
|
||||||
.version = "1",
|
.version = "1",
|
||||||
|
.config = 0,
|
||||||
.parse_config = &age_restriction_parse_config,
|
.parse_config = &age_restriction_parse_config,
|
||||||
.config_json = &age_restriction_json,
|
.config_json = &age_restriction_json,
|
||||||
},
|
},
|
||||||
@ -3387,9 +3450,13 @@ static struct extension extensions[] = {
|
|||||||
static const struct extension*
|
static const struct extension*
|
||||||
get_extension (const char *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 known;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -3397,100 +3464,47 @@ get_extension (const char *extension)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
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)
|
if (0 != global_ret)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (0 != strncasecmp (section,
|
||||||
|
EXT_PREFIX,
|
||||||
|
sizeof(EXT_PREFIX) - 1))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 == strncasecmp (section,
|
name = section + sizeof(EXT_PREFIX) - 1;
|
||||||
"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)
|
if (NULL == (extension = get_extension (name)))
|
||||||
{
|
{
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
"Unsupported extension `%s` (section [%s]).\n", name,
|
"Unsupported extension `%s` (section [%s]).\n", name,
|
||||||
section);
|
section);
|
||||||
test_shutdown ();
|
test_shutdown ();
|
||||||
global_ret = EXIT_INVALIDARGUMENT;
|
global_ret = EXIT_NOTCONFIGURED;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "found extension %s\n", name);
|
if (GNUNET_OK != extension->parse_config ((struct extension *) extension,
|
||||||
{
|
section))
|
||||||
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,
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
"Couldn't parse configuration for extension `%s` (section [%s]).\n",
|
"Couldn't parse configuration for extension `%s` (section [%s]).\n",
|
||||||
name,
|
name,
|
||||||
section);
|
section);
|
||||||
test_shutdown ();
|
test_shutdown ();
|
||||||
global_ret = EXIT_INVALIDARGUMENT;
|
global_ret = EXIT_NOTCONFIGURED;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
json_t *cfg = extension->config_json (extension);
|
json_object_set (obj, name, 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)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3501,18 +3515,102 @@ static void
|
|||||||
do_extensions_show (char *const *args)
|
do_extensions_show (char *const *args)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
json_t *obj = json_object ();
|
||||||
|
json_t *exts = json_object ();
|
||||||
|
|
||||||
GNUNET_CONFIGURATION_iterate_sections (kcfg,
|
GNUNET_CONFIGURATION_iterate_sections (kcfg,
|
||||||
&show_extensions,
|
&collect_extensions,
|
||||||
NULL);
|
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
|
static void
|
||||||
do_extensions_sign (char *const *args)
|
cmd_handler (char *const *args, const struct SubCommand *cmds)
|
||||||
{
|
{
|
||||||
GNUNET_CONFIGURATION_iterate_sections (kcfg,
|
nxt = NULL;
|
||||||
&sign_extensions,
|
for (unsigned int i = 0; NULL != cmds[i].name; i++)
|
||||||
NULL);
|
{
|
||||||
|
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,
|
.name = NULL,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (NULL == args[0])
|
if (NULL == args[0])
|
||||||
{
|
{
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
@ -3544,34 +3643,9 @@ do_work_extensions (char *const *args)
|
|||||||
global_ret = EXIT_INVALIDARGUMENT;
|
global_ret = EXIT_INVALIDARGUMENT;
|
||||||
return;
|
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",
|
cmd_handler (args, cmds);
|
||||||
args[0]))
|
next (args + 1);
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3663,34 +3737,7 @@ work (void *cls)
|
|||||||
};
|
};
|
||||||
(void) cls;
|
(void) cls;
|
||||||
|
|
||||||
nxt = NULL;
|
cmd_handler (args, cmds);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@ TEH_handler_management_post_extensions (
|
|||||||
struct MHD_Connection *connection,
|
struct MHD_Connection *connection,
|
||||||
const json_t *root)
|
const json_t *root)
|
||||||
{
|
{
|
||||||
struct SetExtensionsContext sec = {0};
|
MHD_RESULT ret;
|
||||||
json_t *extensions;
|
json_t *extensions;
|
||||||
json_t *extensions_sigs;
|
json_t *extensions_sigs;
|
||||||
struct GNUNET_JSON_Specification top_spec[] = {
|
struct GNUNET_JSON_Specification top_spec[] = {
|
||||||
@ -186,9 +186,9 @@ TEH_handler_management_post_extensions (
|
|||||||
&extensions_sigs),
|
&extensions_sigs),
|
||||||
GNUNET_JSON_spec_end ()
|
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;
|
enum GNUNET_GenericReturnValue res;
|
||||||
|
|
||||||
@ -201,9 +201,9 @@ TEH_handler_management_post_extensions (
|
|||||||
return MHD_YES; /* failure */
|
return MHD_YES; /* failure */
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure we have two arrays of the same size
|
/* Ensure we have two objects of the same size */
|
||||||
if (! (json_is_array (extensions) &&
|
if (! (json_is_object (extensions) &&
|
||||||
json_is_array (extensions_sigs)) )
|
json_is_object (extensions_sigs)) )
|
||||||
{
|
{
|
||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
GNUNET_JSON_parse_free (top_spec);
|
GNUNET_JSON_parse_free (top_spec);
|
||||||
@ -211,11 +211,11 @@ TEH_handler_management_post_extensions (
|
|||||||
connection,
|
connection,
|
||||||
MHD_HTTP_BAD_REQUEST,
|
MHD_HTTP_BAD_REQUEST,
|
||||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
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);
|
sec.num_extensions = json_object_size (extensions);
|
||||||
if (json_array_size (extensions) != sec.num_extensions)
|
if (json_object_size (extensions_sigs) != sec.num_extensions)
|
||||||
{
|
{
|
||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
GNUNET_JSON_parse_free (top_spec);
|
GNUNET_JSON_parse_free (top_spec);
|
||||||
@ -223,7 +223,7 @@ TEH_handler_management_post_extensions (
|
|||||||
connection,
|
connection,
|
||||||
MHD_HTTP_BAD_REQUEST,
|
MHD_HTTP_BAD_REQUEST,
|
||||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
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,
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
@ -234,38 +234,16 @@ TEH_handler_management_post_extensions (
|
|||||||
sec.extensions_sigs = GNUNET_new_array (sec.num_extensions,
|
sec.extensions_sigs = GNUNET_new_array (sec.num_extensions,
|
||||||
struct TALER_MasterSignatureP);
|
struct TALER_MasterSignatureP);
|
||||||
|
|
||||||
// Now parse individual extensions and signatures from those arrays.
|
/* Now parse individual extensions and signatures from those objects. */
|
||||||
for (unsigned int i = 0; i<sec.num_extensions; i++)
|
|
||||||
{
|
{
|
||||||
// 1. parse the extension out of the json
|
|
||||||
enum GNUNET_GenericReturnValue res;
|
|
||||||
const struct TALER_Extension *extension;
|
const struct TALER_Extension *extension;
|
||||||
const char *name;
|
const char *name;
|
||||||
struct GNUNET_JSON_Specification ext_spec[] = {
|
json_t *config;
|
||||||
GNUNET_JSON_spec_string ("extension",
|
int idx = 0;
|
||||||
&name),
|
|
||||||
GNUNET_JSON_spec_json ("config",
|
|
||||||
&sec.extensions[i].config),
|
|
||||||
GNUNET_JSON_spec_end ()
|
|
||||||
};
|
|
||||||
|
|
||||||
res = TALER_MHD_parse_json_array (connection,
|
json_object_foreach (extensions, name, config){
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 2. Make sure name refers to a supported extension */
|
/* 1. Make sure name refers to a supported extension */
|
||||||
if (GNUNET_OK != TALER_extension_get_by_name (name,
|
if (GNUNET_OK != TALER_extension_get_by_name (name,
|
||||||
(const struct
|
(const struct
|
||||||
TALER_Extension **)
|
TALER_Extension **)
|
||||||
@ -280,39 +258,38 @@ TEH_handler_management_post_extensions (
|
|||||||
goto CLEANUP;
|
goto CLEANUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
sec.extensions[i].type = extension->type;
|
sec.extensions[idx].config = config;
|
||||||
|
sec.extensions[idx].type = extension->type;
|
||||||
|
|
||||||
/* 3. Extract the signature out of the json array */
|
/* 2. Extract the corresponding signature */
|
||||||
{
|
{
|
||||||
enum GNUNET_GenericReturnValue res;
|
|
||||||
struct GNUNET_JSON_Specification sig_spec[] = {
|
struct GNUNET_JSON_Specification sig_spec[] = {
|
||||||
GNUNET_JSON_spec_fixed_auto (NULL,
|
GNUNET_JSON_spec_fixed_auto (name,
|
||||||
&sec.extensions_sigs[i]),
|
&sec.extensions_sigs[idx]),
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
};
|
};
|
||||||
|
|
||||||
res = TALER_MHD_parse_json_array (connection,
|
if (GNUNET_OK != TALER_MHD_parse_json_data (connection,
|
||||||
extensions_sigs,
|
extensions_sigs,
|
||||||
sig_spec,
|
sig_spec))
|
||||||
i,
|
|
||||||
-1);
|
|
||||||
if (GNUNET_SYSERR == res)
|
|
||||||
{
|
{
|
||||||
ret = MHD_NO; /* hard failure */
|
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;
|
goto CLEANUP;
|
||||||
}
|
}
|
||||||
if (GNUNET_NO == res)
|
|
||||||
{
|
|
||||||
ret = MHD_YES;
|
|
||||||
goto CLEANUP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 4. Verify the signature of the config */
|
GNUNET_JSON_parse_free (sig_spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 3. Verify the signature of the config */
|
||||||
if (GNUNET_OK != config_verify (
|
if (GNUNET_OK != config_verify (
|
||||||
sec.extensions[i].config,
|
sec.extensions[idx].config,
|
||||||
&TEH_master_public_key,
|
&TEH_master_public_key,
|
||||||
&sec.extensions_sigs[i]))
|
&sec.extensions_sigs[idx]))
|
||||||
{
|
{
|
||||||
ret = TALER_MHD_reply_with_error (
|
ret = TALER_MHD_reply_with_error (
|
||||||
connection,
|
connection,
|
||||||
@ -322,10 +299,9 @@ TEH_handler_management_post_extensions (
|
|||||||
goto CLEANUP;
|
goto CLEANUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 5. Make sure the config is sound */
|
/* 4. Make sure the config is sound */
|
||||||
if (GNUNET_OK != extension->test_config (sec.extensions[i].config))
|
if (GNUNET_OK != extension->test_config (sec.extensions[idx].config))
|
||||||
{
|
{
|
||||||
GNUNET_JSON_parse_free (ext_spec);
|
|
||||||
ret = TALER_MHD_reply_with_error (
|
ret = TALER_MHD_reply_with_error (
|
||||||
connection,
|
connection,
|
||||||
MHD_HTTP_BAD_REQUEST,
|
MHD_HTTP_BAD_REQUEST,
|
||||||
@ -335,19 +311,21 @@ TEH_handler_management_post_extensions (
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have a validly signed JSON object for the extension.
|
/* We have a validly signed JSON object for the extension. Increment its
|
||||||
* Increment its refcount and free the parser for the extension.
|
* refcount.
|
||||||
*/
|
*/
|
||||||
json_incref (sec.extensions[i].config);
|
json_incref (sec.extensions[idx].config);
|
||||||
GNUNET_JSON_parse_free (ext_spec);
|
idx++;
|
||||||
|
|
||||||
|
} /* json_object_foreach */
|
||||||
|
}
|
||||||
|
|
||||||
} /* for-loop */
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
// now run the transaction to persist the configurations
|
/* now run the transaction to persist the configurations */
|
||||||
{
|
{
|
||||||
enum GNUNET_GenericReturnValue res;
|
enum GNUNET_GenericReturnValue res;
|
||||||
|
|
||||||
|
@ -78,9 +78,10 @@ WIRE_GATEWAY_URL = "http://localhost:9081/2/"
|
|||||||
HTTP_PORT = 9081
|
HTTP_PORT = 9081
|
||||||
|
|
||||||
# Enabled extensions
|
# Enabled extensions
|
||||||
[exchange-extension-age-restriction]
|
[exchange-extension-age_restriction]
|
||||||
ENABLED = YES
|
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
|
# Sections starting with "coin_" specify which denominations
|
||||||
# the exchange should support (and their respective fee structure)
|
# 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)
|
struct TALER_AgeMask *mask)
|
||||||
{
|
{
|
||||||
|
|
||||||
const char *end = groups + strlen (groups);
|
|
||||||
const char *pos = groups;
|
const char *pos = groups;
|
||||||
unsigned int prev = 0;
|
unsigned int prev = 0;
|
||||||
unsigned int val = 0;
|
unsigned int val = 0;
|
||||||
|
char c;
|
||||||
|
|
||||||
while (pos < end)
|
while (*pos)
|
||||||
{
|
{
|
||||||
char c = *pos++;
|
c = *pos++;
|
||||||
if (':' == c)
|
if (':' == c)
|
||||||
{
|
{
|
||||||
if (prev >= val)
|
if (prev >= val)
|
||||||
@ -100,9 +100,9 @@ TALER_parse_age_group_string (const char *groups,
|
|||||||
mask->mask |= 1 << val;
|
mask->mask |= 1 << val;
|
||||||
prev = val;
|
prev = val;
|
||||||
val = 0;
|
val = 0;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
if ('0'>c || '9'<c)
|
if ('0'>c || '9'<c)
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
|
|
||||||
@ -111,12 +111,12 @@ TALER_parse_age_group_string (const char *groups,
|
|||||||
if (0>=val || 32<=val)
|
if (0>=val || 32<=val)
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (0>=val || 32<=val || prev>=val)
|
if (0>val || 32<=val || prev>=val)
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
|
|
||||||
mask->mask |= 1 << val;
|
mask->mask |= (1 << val);
|
||||||
|
mask->mask |= 1; // mark zeroth group, too
|
||||||
|
|
||||||
return GNUNET_OK;
|
return GNUNET_OK;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user