diff options
Diffstat (limited to 'src/exchange/taler-exchange-httpd_management_extensions.c')
-rw-r--r-- | src/exchange/taler-exchange-httpd_management_extensions.c | 229 |
1 files changed, 73 insertions, 156 deletions
diff --git a/src/exchange/taler-exchange-httpd_management_extensions.c b/src/exchange/taler-exchange-httpd_management_extensions.c index 96b855c3c..8476e669d 100644 --- a/src/exchange/taler-exchange-httpd_management_extensions.c +++ b/src/exchange/taler-exchange-httpd_management_extensions.c @@ -49,41 +49,8 @@ struct SetExtensionsContext { uint32_t num_extensions; struct Extension *extensions; - struct TALER_MasterSignatureP *extensions_sigs; }; - -/** - * @brief verifies the signature a configuration with the offline master key. - * - * @param config configuration of an extension given as JSON object - * @param master_priv offline master public key of the exchange - * @param[out] master_sig signature - * @return GNUNET_OK on success, GNUNET_SYSERR otherwise - */ -static enum GNUNET_GenericReturnValue -config_verify ( - const json_t *config, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_MasterSignatureP *master_sig - ) -{ - enum GNUNET_GenericReturnValue ret; - struct TALER_ExtensionConfigHash h_config; - - ret = TALER_extension_config_hash (config, &h_config); - if (GNUNET_OK != ret) - { - GNUNET_break (0); - return ret; - } - - return TALER_exchange_offline_extension_config_hash_verify (h_config, - master_pub, - master_sig); -} - - /** * Function implementing database transaction to set the configuration of * extensions. It runs the transaction logic. @@ -111,14 +78,13 @@ set_extensions (void *cls, for (uint32_t i = 0; i<sec->num_extensions; i++) { struct Extension *ext = &sec->extensions[i]; - struct TALER_MasterSignatureP *sig = &sec->extensions_sigs[i]; enum GNUNET_DB_QueryStatus qs; char *config; /* Sanity check. - * TODO: replace with general API to retrieve the extension-handler + * TODO: This will not work anymore, once we have plugable extensions */ - if (0 > ext->type || TALER_Extension_Max <= ext->type) + if (0 > ext->type || TALER_Extension_MaxPredefined <= ext->type) { GNUNET_break (0); return GNUNET_DB_STATUS_HARD_ERROR; @@ -138,8 +104,7 @@ set_extensions (void *cls, qs = TEH_plugin->set_extension_config ( TEH_plugin->cls, TEH_extensions[ext->type]->name, - config, - sig); + config); if (qs < 0) { @@ -176,19 +141,19 @@ 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 TALER_MasterSignatureP sig = {0}; struct GNUNET_JSON_Specification top_spec[] = { GNUNET_JSON_spec_json ("extensions", &extensions), - GNUNET_JSON_spec_json ("extensions_sigs", - &extensions_sigs), + GNUNET_JSON_spec_fixed_auto ("extensions_sig", + &sig), 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,153 +166,106 @@ 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 an object */ + if (! json_is_object (extensions)) { - GNUNET_break_op (0); GNUNET_JSON_parse_free (top_spec); return TALER_MHD_reply_with_error ( connection, MHD_HTTP_BAD_REQUEST, TALER_EC_GENERIC_PARAMETER_MALFORMED, - "array expected for extensions and extensions_sigs"); + "invalid object"); } - sec.num_extensions = json_array_size (extensions_sigs); - if (json_array_size (extensions) != sec.num_extensions) + /* Verify the signature */ { - GNUNET_break_op (0); - GNUNET_JSON_parse_free (top_spec); - return TALER_MHD_reply_with_error ( - connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PARAMETER_MALFORMED, - "arrays extensions and extensions_sigs are not of the same size"); + 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, + &TEH_master_public_key, + &sig)) + { + GNUNET_JSON_parse_free (top_spec); + return TALER_MHD_reply_with_error ( + connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + "invalid signuture"); + } } + 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); - 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 () - }; - - 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_t *config; + int idx = 0; - /* 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; + json_object_foreach (extensions, name, config){ - /* 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. Make sure the config is sound */ + if (GNUNET_OK != extension->test_config (sec.extensions[idx].config)) { - ret = MHD_YES; + ret = TALER_MHD_reply_with_error ( + connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + "invalid configuration 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; - } - /* 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; @@ -378,7 +296,6 @@ CLEANUP: } } GNUNET_free (sec.extensions); - GNUNET_free (sec.extensions_sigs); GNUNET_JSON_parse_free (top_spec); return ret; } |