summaryrefslogtreecommitdiff
path: root/src/exchange/taler-exchange-httpd_management_extensions.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/exchange/taler-exchange-httpd_management_extensions.c')
-rw-r--r--src/exchange/taler-exchange-httpd_management_extensions.c190
1 files changed, 92 insertions, 98 deletions
diff --git a/src/exchange/taler-exchange-httpd_management_extensions.c b/src/exchange/taler-exchange-httpd_management_extensions.c
index 17db8e8c4..3b24bace7 100644
--- a/src/exchange/taler-exchange-httpd_management_extensions.c
+++ b/src/exchange/taler-exchange-httpd_management_extensions.c
@@ -31,7 +31,6 @@
#include "taler_extensions.h"
#include "taler_dbevents.h"
-
/**
* Extension carries the necessary data for a particular extension.
*
@@ -39,7 +38,7 @@
struct Extension
{
enum TALER_Extension_Type type;
- json_t *config;
+ json_t *manifest;
};
/**
@@ -53,7 +52,7 @@ struct SetExtensionsContext
};
/**
- * Function implementing database transaction to set the configuration of
+ * Function implementing database transaction to set the manifests of
* extensions. It runs the transaction logic.
* - IF it returns a non-error code, the transaction logic MUST NOT queue a
* MHD response.
@@ -75,24 +74,24 @@ set_extensions (void *cls,
{
struct SetExtensionsContext *sec = cls;
- /* save the configurations of all extensions */
+ /* save the manifests of all extensions */
for (uint32_t i = 0; i<sec->num_extensions; i++)
{
struct Extension *ext = &sec->extensions[i];
+ const struct TALER_Extension *taler_ext;
enum GNUNET_DB_QueryStatus qs;
- char *config;
+ char *manifest;
- /* Sanity check.
- * TODO: This will not work anymore, once we have plugable extensions
- */
- if (0 > ext->type || TALER_Extension_MaxPredefined <= ext->type)
+ taler_ext = TALER_extensions_get_by_type (ext->type);
+ if (NULL == taler_ext)
{
+ /* No such extension found */
GNUNET_break (0);
return GNUNET_DB_STATUS_HARD_ERROR;
}
- config = json_dumps (ext->config, JSON_COMPACT | JSON_SORT_KEYS);
- if (NULL == config)
+ manifest = json_dumps (ext->manifest, JSON_COMPACT | JSON_SORT_KEYS);
+ if (NULL == manifest)
{
GNUNET_break (0);
*mhd_ret = TALER_MHD_reply_with_error (connection,
@@ -102,10 +101,12 @@ set_extensions (void *cls,
return GNUNET_DB_STATUS_HARD_ERROR;
}
- qs = TEH_plugin->set_extension_config (
+ qs = TEH_plugin->set_extension_manifest (
TEH_plugin->cls,
- TEH_extensions[ext->type]->name,
- config);
+ taler_ext->name,
+ manifest);
+
+ free (manifest);
if (qs < 0)
{
@@ -120,37 +121,90 @@ set_extensions (void *cls,
/* Success, trigger event */
{
- enum TALER_Extension_Type *type = &sec->extensions[i].type;
+ uint32_t nbo_type = htonl (sec->extensions[i].type);
struct GNUNET_DB_EventHeaderP ev = {
.size = htons (sizeof (ev)),
.type = htons (TALER_DBEVENT_EXCHANGE_EXTENSIONS_UPDATED)
};
+
TEH_plugin->event_notify (TEH_plugin->cls,
&ev,
- type,
- sizeof(*type));
+ &nbo_type,
+ sizeof(nbo_type));
}
}
/* All extensions configured, update the signature */
TEH_extensions_sig = sec->extensions_sig;
+ TEH_extensions_signed = true;
return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; /* only 'success', so >=0, matters here */
}
+static enum GNUNET_GenericReturnValue
+verify_extensions_from_json (
+ const json_t *extensions,
+ struct SetExtensionsContext *sec)
+{
+ const char*name;
+ const struct TALER_Extension *extension;
+ size_t i = 0;
+ json_t *manifest;
+
+ 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 ((json_t *) extensions, name, manifest)
+ {
+ 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_parse_manifest (
+ manifest, &critical, &version, &config))
+ return GNUNET_SYSERR;
+
+ if (critical != extension->critical
+ || 0 != strcmp (version, extension->version) // FIXME-oec: libtool compare
+ || NULL == config
+ || GNUNET_OK != extension->load_config (config, NULL))
+ return GNUNET_SYSERR;
+
+ sec->extensions[i].type = extension->type;
+ sec->extensions[i].manifest = json_copy (manifest);
+ }
+
+ return GNUNET_OK;
+}
+
+
MHD_RESULT
TEH_handler_management_post_extensions (
struct MHD_Connection *connection,
const json_t *root)
{
MHD_RESULT ret;
- json_t *extensions;
+ const json_t *extensions;
struct SetExtensionsContext sec = {0};
struct GNUNET_JSON_Specification top_spec[] = {
- GNUNET_JSON_spec_json ("extensions",
- &extensions),
+ GNUNET_JSON_spec_object_const ("extensions",
+ &extensions),
GNUNET_JSON_spec_fixed_auto ("extensions_sig",
&sec.extensions_sig),
GNUNET_JSON_spec_end ()
@@ -169,36 +223,19 @@ TEH_handler_management_post_extensions (
return MHD_YES; /* failure */
}
- /* Ensure we have an object */
- if (! json_is_object (extensions))
- {
- GNUNET_JSON_parse_free (top_spec);
- return TALER_MHD_reply_with_error (
- connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "invalid object");
- }
-
/* Verify the signature */
{
- struct TALER_ExtensionConfigHash h_config;
- if (GNUNET_OK != TALER_extension_config_hash (extensions, &h_config))
- {
- GNUNET_JSON_parse_free (top_spec);
- return TALER_MHD_reply_with_error (
- connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "invalid object, non-hashable");
- }
-
- if (GNUNET_OK != TALER_exchange_offline_extension_config_hash_verify (
- &h_config,
+ struct TALER_ExtensionManifestsHashP h_manifests;
+
+ if (GNUNET_OK !=
+ TALER_JSON_extensions_manifests_hash (extensions,
+ &h_manifests) ||
+ GNUNET_OK !=
+ TALER_exchange_offline_extension_manifests_hash_verify (
+ &h_manifests,
&TEH_master_public_key,
&sec.extensions_sig))
{
- GNUNET_JSON_parse_free (top_spec);
return TALER_MHD_reply_with_error (
connection,
MHD_HTTP_BAD_REQUEST,
@@ -207,62 +244,20 @@ 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;
- const char *name;
- json_t *config;
- int idx = 0;
-
- json_object_foreach (extensions, name, config){
-
- /* 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 = 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_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 */
+ 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);
@@ -273,7 +268,7 @@ TEH_handler_management_post_extensions (
res = TEH_DB_run_transaction (connection,
"set extensions",
- TEH_MT_OTHER,
+ TEH_MT_REQUEST_OTHER,
&ret,
&set_extensions,
&sec);
@@ -292,13 +287,12 @@ TEH_handler_management_post_extensions (
CLEANUP:
for (unsigned int i = 0; i < sec.num_extensions; i++)
{
- if (NULL != sec.extensions[i].config)
+ if (NULL != sec.extensions[i].manifest)
{
- json_decref (sec.extensions[i].config);
+ json_decref (sec.extensions[i].manifest);
}
}
GNUNET_free (sec.extensions);
- GNUNET_JSON_parse_free (top_spec);
return ret;
}