summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/exchange/taler-exchange-httpd.c7
-rw-r--r--src/exchange/taler-exchange-httpd.h5
-rw-r--r--src/exchange/taler-exchange-httpd_extensions.c138
-rw-r--r--src/exchange/taler-exchange-httpd_keys.c92
-rw-r--r--src/exchange/taler-exchange-httpd_management_extensions.c12
-rw-r--r--src/exchangedb/plugin_exchangedb_postgres.c5
-rw-r--r--src/include/taler_extensions.h14
7 files changed, 171 insertions, 102 deletions
diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c
index 59398c6f..5fe70730 100644
--- a/src/exchange/taler-exchange-httpd.c
+++ b/src/exchange/taler-exchange-httpd.c
@@ -153,6 +153,13 @@ bool TEH_suicide;
struct TALER_Extension **TEH_extensions;
/**
+ * Signature of the configuration of all enabled extensions,
+ * signed by the exchange's offline master key with purpose
+ * TALER_SIGNATURE_MASTER_EXTENSION.
+ */
+struct TALER_MasterSignatureP TEH_extensions_sig;
+
+/**
* Value to return from main()
*/
static int global_ret;
diff --git a/src/exchange/taler-exchange-httpd.h b/src/exchange/taler-exchange-httpd.h
index 39666379..017d5520 100644
--- a/src/exchange/taler-exchange-httpd.h
+++ b/src/exchange/taler-exchange-httpd.h
@@ -206,6 +206,11 @@ extern struct GNUNET_CURL_Context *TEH_curl_ctx;
*/
extern struct TALER_Extension **TEH_extensions;
+/*
+ * Signature of the offline master key of all enabled extensions' configuration
+ */
+extern struct TALER_MasterSignatureP TEH_extensions_sig;
+
/* TODO: this will not work anymore, once we have plugable extensions */
#define TEH_extension_enabled(ext) (0 <= ext && TALER_Extension_MaxPredefined > \
ext && \
diff --git a/src/exchange/taler-exchange-httpd_extensions.c b/src/exchange/taler-exchange-httpd_extensions.c
index 1a2c4552..0245797d 100644
--- a/src/exchange/taler-exchange-httpd_extensions.c
+++ b/src/exchange/taler-exchange-httpd_extensions.c
@@ -28,28 +28,57 @@
#include <jansson.h>
/**
+ * @brief implements the TALER_Extension.disable interface.
+ */
+void
+age_restriction_disable (struct TALER_Extension *this)
+{
+ if (NULL == this)
+ return;
+
+ this->config = NULL;
+
+ if (NULL != this->config_json)
+ {
+ json_decref (this->config_json);
+ this->config_json = NULL;
+ }
+}
+
+
+/**
* @brief implements the TALER_Extension.parse_and_set_config interface.
+ * @param this if NULL, only tests the configuration
+ * @param config the configuration as json
*/
static enum GNUNET_GenericReturnValue
age_restriction_parse_and_set_config (struct TALER_Extension *this,
- const json_t *config)
+ json_t *config)
{
- enum GNUNET_GenericReturnValue ret;
struct TALER_AgeMask mask = {0};
+ enum GNUNET_GenericReturnValue ret;
ret = TALER_agemask_parse_json (config, &mask);
if (GNUNET_OK != ret)
return ret;
- if (this != NULL && TALER_Extension_AgeRestriction == this->type)
- {
- if (NULL != this->config)
- {
- GNUNET_free (this->config);
- }
- this->config = GNUNET_malloc (sizeof(struct TALER_AgeMask));
- GNUNET_memcpy (this->config, &mask, sizeof(struct TALER_AgeMask));
- }
+ /* only testing the parser */
+ if (this == NULL)
+ return GNUNET_OK;
+
+ if (TALER_Extension_AgeRestriction != this->type)
+ return GNUNET_SYSERR;
+
+ if (NULL != this->config)
+ GNUNET_free (this->config);
+
+ this->config = GNUNET_malloc (sizeof(struct TALER_AgeMask));
+ GNUNET_memcpy (this->config, &mask, sizeof(struct TALER_AgeMask));
+
+ if (NULL != this->config_json)
+ json_decref (this->config_json);
+
+ this->config_json = config;
return GNUNET_OK;
}
@@ -61,28 +90,9 @@ age_restriction_parse_and_set_config (struct TALER_Extension *this,
static enum GNUNET_GenericReturnValue
age_restriction_test_config (const json_t *config)
{
- return age_restriction_parse_and_set_config (NULL, config);
-}
-
+ struct TALER_AgeMask mask = {0};
-/**
- * @brief implements the TALER_Extension.config_to_json interface.
- */
-static json_t *
-age_restriction_config_to_json (const struct TALER_Extension *this)
-{
- const struct TALER_AgeMask *mask;
- if (NULL == this || TALER_Extension_AgeRestriction != this->type)
- return NULL;
-
- mask = (struct TALER_AgeMask *) this->config;
- json_t *config = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("extension", this->name),
- GNUNET_JSON_pack_string ("mask",
- TALER_age_mask_to_string (mask))
- );
-
- return config;
+ return TALER_agemask_parse_json (config, &mask);
}
@@ -91,26 +101,17 @@ static struct TALER_Extension extension_age_restriction = {
.type = TALER_Extension_AgeRestriction,
.name = "age_restriction",
.critical = false,
+ .version = "1",
.config = NULL, // disabled per default
+ .config_json = NULL,
+ .disable = &age_restriction_disable,
.test_config = &age_restriction_test_config,
.parse_and_set_config = &age_restriction_parse_and_set_config,
- .config_to_json = &age_restriction_config_to_json,
-};
-
-/* TODO: The extension for peer2peer */
-static struct TALER_Extension extension_peer2peer = {
- .type = TALER_Extension_Peer2Peer,
- .name = "peer2peer",
- .critical = false,
- .config = NULL, // disabled per default
- .test_config = NULL, // TODO
- .parse_and_set_config = NULL, // TODO
- .config_to_json = NULL, // TODO
};
-
/**
- * Create a list with the extensions for Age Restriction and Peer2Peer
+ * Create a list with the extensions for Age Restriction (and later Peer2Peer,
+ * ...)
*/
static struct TALER_Extension **
get_known_extensions ()
@@ -120,7 +121,6 @@ get_known_extensions ()
TALER_Extension_MaxPredefined + 1,
struct TALER_Extension *);
list[TALER_Extension_AgeRestriction] = &extension_age_restriction;
- list[TALER_Extension_Peer2Peer] = &extension_peer2peer;
list[TALER_Extension_MaxPredefined] = NULL;
return list;
@@ -172,14 +172,13 @@ extension_update_event_cb (void *cls,
// Get the config from the database as string
{
- char *config_str;
+ char *config_str = NULL;
enum GNUNET_DB_QueryStatus qs;
struct TALER_Extension *extension;
json_error_t err;
json_t *config;
enum GNUNET_GenericReturnValue ret;
- // TODO: make this a safe lookup
extension = TEH_extensions[type];
qs = TEH_plugin->get_extension_config (TEH_plugin->cls,
@@ -194,6 +193,13 @@ extension_update_event_cb (void *cls,
return;
}
+ // No config found -> extension is disabled
+ if (NULL == config_str)
+ {
+ extension->disable (extension);
+ return;
+ }
+
// Parse the string as JSON
config = json_loads (config_str, JSON_DECODE_ANY, &err);
if (NULL == config)
@@ -223,25 +229,29 @@ extension_update_event_cb (void *cls,
enum GNUNET_GenericReturnValue
TEH_extensions_init ()
{
+ /* Populate the known extensions. */
TEH_extensions = get_known_extensions ();
+ /* Set the event handler for updates */
+ struct GNUNET_DB_EventHeaderP ev = {
+ .size = htons (sizeof (ev)),
+ .type = htons (TALER_DBEVENT_EXCHANGE_EXTENSIONS_UPDATED),
+ };
+ extensions_eh = TEH_plugin->event_listen (TEH_plugin->cls,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ &ev,
+ &extension_update_event_cb,
+ NULL);
+ if (NULL == extensions_eh)
{
- struct GNUNET_DB_EventHeaderP ev = {
- .size = htons (sizeof (ev)),
- .type = htons (TALER_DBEVENT_EXCHANGE_EXTENSIONS_UPDATED),
- };
-
- extensions_eh = TEH_plugin->event_listen (TEH_plugin->cls,
- GNUNET_TIME_UNIT_FOREVER_REL,
- &ev,
- &extension_update_event_cb,
- NULL);
- if (NULL == extensions_eh)
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
}
+
+ /* Trigger the initial load of configuration from the db */
+ for (struct TALER_Extension **it = TEH_extensions; NULL != *it; it++)
+ extension_update_event_cb (NULL, &(*it)->type, sizeof((*it)->type));
+
return GNUNET_OK;
}
diff --git a/src/exchange/taler-exchange-httpd_keys.c b/src/exchange/taler-exchange-httpd_keys.c
index 30bbe8eb..7c64cdb7 100644
--- a/src/exchange/taler-exchange-httpd_keys.c
+++ b/src/exchange/taler-exchange-httpd_keys.c
@@ -1703,29 +1703,79 @@ create_krd (struct TEH_KeyStateHandle *ksh,
&TEH_kyc_config.wallet_balance_limit)));
}
- // Signal support for the age-restriction extension, if so configured, and
- // add the array of age-restricted denominations.
- if (TEH_extension_enabled (TALER_Extension_AgeRestriction) &&
- NULL != age_restricted_denoms)
+ // Signal support for the configured, enabled extensions.
{
- struct TALER_AgeMask *mask;
- json_t *config;
-
- mask = (struct
- TALER_AgeMask *) TEH_extensions[TALER_Extension_AgeRestriction]->
- config;
- config = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_bool ("critical", false),
- GNUNET_JSON_pack_string ("version", "1"),
- GNUNET_JSON_pack_string ("age_groups", TALER_age_mask_to_string (mask)));
- GNUNET_assert (NULL != config);
- GNUNET_assert (
- 0 ==
- json_object_set_new (
+ json_t *extensions = json_object ();
+ bool has_extensions;
+
+ /* Fill in the configurations of the enabled extensions */
+ for (struct TALER_Extension **it = TEH_extensions;
+ NULL != *it;
+ it++)
+ {
+ const struct TALER_Extension *extension = *it;
+ json_t *ext;
+ json_t *config_json;
+ int r;
+
+ /* skip if not configured == disabled */
+ if (NULL == extension->config)
+ continue;
+
+ has_extensions = true;
+
+ GNUNET_assert (NULL != extension->config_json);
+
+ config_json = json_copy (extension->config_json);
+ GNUNET_assert (NULL != config_json);
+
+ ext = GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_bool ("critical",
+ extension->critical),
+ GNUNET_JSON_pack_string ("version",
+ extension->version),
+ GNUNET_JSON_pack_object_steal ("config",
+ config_json)
+ );
+ GNUNET_assert (NULL != ext);
+
+ r = json_object_set_new (
+ extensions,
+ extension->name,
+ ext);
+
+ GNUNET_assert (0 == r);
+ }
+
+ /* Update the keys object with the extensions */
+ if (has_extensions)
+ {
+ json_t *sig;
+ int r;
+
+ r = json_object_set_new (
keys,
- "age_restriction",
- config));
+ "extensions",
+ extensions);
+ GNUNET_assert (0 == r);
+
+ /* add extensions_sig */
+ sig = GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_data_auto ("extensions_sig",
+ &TEH_extensions_sig));
+
+ /* update the keys object with extensions_sig */
+ r = json_object_update (keys, sig);
+ GNUNET_assert (0 == r);
+ }
+ }
+
+ // Special case for age restrictions: if enabled, provide the lits of
+ // age-restricted denominations.
+ if (TEH_extension_enabled (TALER_Extension_AgeRestriction) &&
+ NULL != age_restricted_denoms)
+ {
GNUNET_assert (
0 ==
json_object_set_new (
@@ -1734,8 +1784,6 @@ create_krd (struct TEH_KeyStateHandle *ksh,
age_restricted_denoms));
}
- // TODO: signal support and configuration for the P2P extension, once
- // implemented.
{
char *keys_json;
diff --git a/src/exchange/taler-exchange-httpd_management_extensions.c b/src/exchange/taler-exchange-httpd_management_extensions.c
index 8476e669..17db8e8c 100644
--- a/src/exchange/taler-exchange-httpd_management_extensions.c
+++ b/src/exchange/taler-exchange-httpd_management_extensions.c
@@ -49,6 +49,7 @@ struct SetExtensionsContext
{
uint32_t num_extensions;
struct Extension *extensions;
+ struct TALER_MasterSignatureP extensions_sig;
};
/**
@@ -132,6 +133,9 @@ set_extensions (void *cls,
}
+ /* All extensions configured, update the signature */
+ TEH_extensions_sig = sec->extensions_sig;
+
return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; /* only 'success', so >=0, matters here */
}
@@ -143,15 +147,14 @@ TEH_handler_management_post_extensions (
{
MHD_RESULT ret;
json_t *extensions;
- struct TALER_MasterSignatureP sig = {0};
+ struct SetExtensionsContext sec = {0};
struct GNUNET_JSON_Specification top_spec[] = {
GNUNET_JSON_spec_json ("extensions",
&extensions),
GNUNET_JSON_spec_fixed_auto ("extensions_sig",
- &sig),
+ &sec.extensions_sig),
GNUNET_JSON_spec_end ()
};
- struct SetExtensionsContext sec = {0};
/* Parse the top level json structure */
{
@@ -193,7 +196,7 @@ TEH_handler_management_post_extensions (
if (GNUNET_OK != TALER_exchange_offline_extension_config_hash_verify (
&h_config,
&TEH_master_public_key,
- &sig))
+ &sec.extensions_sig))
{
GNUNET_JSON_parse_free (top_spec);
return TALER_MHD_reply_with_error (
@@ -248,7 +251,6 @@ TEH_handler_management_post_extensions (
TALER_EC_GENERIC_PARAMETER_MALFORMED,
"invalid configuration for extension");
goto CLEANUP;
-
}
/* We have a validly signed JSON object for the extension. Increment its
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c
index 918fc38c..f9f0ce41 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -11455,6 +11455,7 @@ postgres_get_extension_config (void *cls,
GNUNET_PQ_query_param_end
};
bool is_null;
+ *config = NULL;
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_allow_null (
GNUNET_PQ_result_spec_string ("config", config),
@@ -11467,10 +11468,6 @@ postgres_get_extension_config (void *cls,
"get_extension_config",
params,
rs);
- if (is_null)
- {
- *config = NULL;
- }
return qs;
}
diff --git a/src/include/taler_extensions.h b/src/include/taler_extensions.h
index 31e5c673..7199304d 100644
--- a/src/include/taler_extensions.h
+++ b/src/include/taler_extensions.h
@@ -31,26 +31,27 @@
enum TALER_Extension_Type
{
TALER_Extension_AgeRestriction = 0,
- TALER_Extension_Peer2Peer = 1,
- TALER_Extension_MaxPredefined = 2 // Must be last
+ TALER_Extension_MaxPredefined = 1 // Must be last of the predefined
};
/*
* Represents the implementation of an extension.
+ * TODO: add documentation
*/
struct TALER_Extension
{
enum TALER_Extension_Type type;
char *name;
bool critical;
- bool enabled;
+ char *version;
void *config;
+ json_t *config_json;
+ void (*disable)(struct TALER_Extension *this);
enum GNUNET_GenericReturnValue (*test_config)(const json_t *config);
enum GNUNET_GenericReturnValue (*parse_and_set_config)(struct
TALER_Extension *this,
- const json_t *config);
- json_t *(*config_to_json)(const struct TALER_Extension *this);
+ json_t *config);
};
/**
@@ -132,8 +133,7 @@ TALER_get_age_mask (const struct GNUNET_CONFIGURATION_Handle *cfg,
/*
- * TALER Peer2Peer Extension
- * TODO oec
+ * TODO: Add Peer2Peer Extension
*/
#endif