From 79731479333a31955cb8faeceb4e24f3a745208a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 25 Jan 2016 13:21:37 +0100 Subject: [PATCH] fix #4149 --- src/mint/Makefile.am | 13 +- src/mint/taler-mint-httpd.c | 45 +---- src/mint/taler-mint-httpd.h | 8 +- src/mint/taler-mint-httpd_admin.c | 4 +- src/mint/taler-mint-httpd_deposit.c | 4 +- src/mint/taler-mint-httpd_validation.c | 231 +++++++++++++++++++++++++ src/mint/taler-mint-httpd_validation.h | 76 ++++++++ src/mint/taler-mint-httpd_wire.c | 31 +--- 8 files changed, 331 insertions(+), 81 deletions(-) create mode 100644 src/mint/taler-mint-httpd_validation.c create mode 100644 src/mint/taler-mint-httpd_validation.h diff --git a/src/mint/Makefile.am b/src/mint/Makefile.am index a115d63a0..aa9b1974f 100644 --- a/src/mint/Makefile.am +++ b/src/mint/Makefile.am @@ -11,17 +11,18 @@ bin_PROGRAMS = \ taler_mint_httpd_SOURCES = \ taler-mint-httpd.c taler-mint-httpd.h \ - taler-mint-httpd_keystate.c taler-mint-httpd_keystate.h \ - taler-mint-httpd_db.c taler-mint-httpd_db.h \ - taler-mint-httpd_parsing.c taler-mint-httpd_parsing.h \ - taler-mint-httpd_responses.c taler-mint-httpd_responses.h \ - taler-mint-httpd_mhd.c taler-mint-httpd_mhd.h \ taler-mint-httpd_admin.c taler-mint-httpd_admin.h \ + taler-mint-httpd_db.c taler-mint-httpd_db.h \ taler-mint-httpd_deposit.c taler-mint-httpd_deposit.h \ + taler-mint-httpd_keystate.c taler-mint-httpd_keystate.h \ + taler-mint-httpd_mhd.c taler-mint-httpd_mhd.h \ + taler-mint-httpd_parsing.c taler-mint-httpd_parsing.h \ + taler-mint-httpd_refresh.c taler-mint-httpd_refresh.h \ taler-mint-httpd_reserve.c taler-mint-httpd_reserve.h \ + taler-mint-httpd_responses.c taler-mint-httpd_responses.h \ taler-mint-httpd_tracking.c taler-mint-httpd_tracking.h \ taler-mint-httpd_wire.c taler-mint-httpd_wire.h \ - taler-mint-httpd_refresh.c taler-mint-httpd_refresh.h + taler-mint-httpd_validation.c taler-mint-httpd_validation.h taler_mint_httpd_LDADD = \ $(LIBGCRYPT_LIBS) \ $(top_builddir)/src/util/libtalerutil.la \ diff --git a/src/mint/taler-mint-httpd.c b/src/mint/taler-mint-httpd.c index 26a440c95..5d6aa0589 100644 --- a/src/mint/taler-mint-httpd.c +++ b/src/mint/taler-mint-httpd.c @@ -39,6 +39,7 @@ #include "taler-mint-httpd_test.h" #endif #include "taler_mintdb_plugin.h" +#include "taler-mint-httpd_validation.h" /** * Which currency is used by this mint? @@ -66,13 +67,6 @@ struct GNUNET_CONFIGURATION_Handle *cfg; */ struct GNUNET_CRYPTO_EddsaPublicKey TMH_master_public_key; -/** - * In which format does this MINT expect wiring instructions? - * NULL-terminated array of 0-terminated wire format types, - * suitable for passing to #TALER_json_validate_wireformat(). - */ -const char **TMH_expected_wire_formats; - /** * Our DB plugin. */ @@ -384,9 +378,6 @@ mint_serve_process_config (const char *mint_directory) { unsigned long long port; char *TMH_master_public_key_str; - char *wireformats; - const char *token; - unsigned int len; cfg = TALER_config_load (mint_directory); if (NULL == cfg) @@ -414,35 +405,9 @@ mint_serve_process_config (const char *mint_directory) (unsigned int) TALER_CURRENCY_LEN); return GNUNET_SYSERR; } - /* Find out list of supported wire formats */ if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, - "mint", - "wireformat", - &wireformats)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "mint", - "wireformat"); + TMH_VALIDATION_init (cfg)) return GNUNET_SYSERR; - } - /* build NULL-terminated array of TMH_expected_wire_formats */ - TMH_expected_wire_formats = GNUNET_new_array (1, - const char *); - len = 1; - for (token = strtok (wireformats, - " "); - NULL != token; - token = strtok (NULL, - " ")) - { - /* Grow by 1, appending NULL-terminator */ - GNUNET_array_append (TMH_expected_wire_formats, - len, - NULL); - TMH_expected_wire_formats[len - 2] = GNUNET_strdup (token); - } - GNUNET_free (wireformats); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, @@ -453,6 +418,7 @@ mint_serve_process_config (const char *mint_directory) GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "mint", "master_public_key"); + TMH_VALIDATION_done (); return GNUNET_SYSERR; } if (GNUNET_OK != @@ -463,6 +429,7 @@ mint_serve_process_config (const char *mint_directory) fprintf (stderr, "Invalid master public key given in mint configuration."); GNUNET_free (TMH_master_public_key_str); + TMH_VALIDATION_done (); return GNUNET_SYSERR; } GNUNET_free (TMH_master_public_key_str); @@ -472,6 +439,7 @@ mint_serve_process_config (const char *mint_directory) { fprintf (stderr, "Failed to initialize DB subsystem\n"); + TMH_VALIDATION_done (); return GNUNET_SYSERR; } if (GNUNET_YES == @@ -496,6 +464,7 @@ mint_serve_process_config (const char *mint_directory) "mint", "port", "port number required"); + TMH_VALIDATION_done (); return GNUNET_SYSERR; } @@ -505,6 +474,7 @@ mint_serve_process_config (const char *mint_directory) fprintf (stderr, "Invalid configuration (value out of range): %llu is not a valid port\n", port); + TMH_VALIDATION_done (); return GNUNET_SYSERR; } serve_port = (uint16_t) port; @@ -772,6 +742,7 @@ main (int argc, session); } TALER_MINTDB_plugin_unload (TMH_plugin); + TMH_VALIDATION_done (); return (GNUNET_SYSERR == ret) ? 1 : 0; } diff --git a/src/mint/taler-mint-httpd.h b/src/mint/taler-mint-httpd.h index e83dd66f2..d45325aa6 100644 --- a/src/mint/taler-mint-httpd.h +++ b/src/mint/taler-mint-httpd.h @@ -27,6 +27,7 @@ #include + /** * Which currency is used by this mint? */ @@ -52,13 +53,6 @@ extern int TMH_test_mode; */ extern char *TMH_mint_directory; -/** - * In which formats does this MINT expect wiring instructions? - * NULL-terminated array of 0-terminated wire format types, - * suitable for passing to #TALER_json_validate_wireformat(). - */ -extern const char **TMH_expected_wire_formats; - /** * Master public key (according to the * configuration in the mint directory). diff --git a/src/mint/taler-mint-httpd_admin.c b/src/mint/taler-mint-httpd_admin.c index 99f256418..e6f186f0b 100644 --- a/src/mint/taler-mint-httpd_admin.c +++ b/src/mint/taler-mint-httpd_admin.c @@ -24,6 +24,7 @@ #include "taler-mint-httpd_admin.h" #include "taler-mint-httpd_parsing.h" #include "taler-mint-httpd_responses.h" +#include "taler-mint-httpd_validation.h" /** @@ -144,8 +145,7 @@ TMH_ADMIN_handler_admin_add_incoming (struct TMH_RequestHandler *rh, return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; } if (GNUNET_YES != - TALER_json_validate_wireformat (TMH_expected_wire_formats, - wire)) + TMH_json_validate_wireformat (wire)) { GNUNET_break_op (0); TMH_PARSE_release_data (spec); diff --git a/src/mint/taler-mint-httpd_deposit.c b/src/mint/taler-mint-httpd_deposit.c index 0aef4775c..40c5a4db7 100644 --- a/src/mint/taler-mint-httpd_deposit.c +++ b/src/mint/taler-mint-httpd_deposit.c @@ -34,6 +34,7 @@ #include "taler-mint-httpd_deposit.h" #include "taler-mint-httpd_responses.h" #include "taler-mint-httpd_keystate.h" +#include "taler-mint-httpd_validation.h" /** @@ -162,8 +163,7 @@ parse_and_handle_deposit_request (struct MHD_Connection *connection, return MHD_YES; /* failure */ if (GNUNET_YES != - TALER_json_validate_wireformat (TMH_expected_wire_formats, - wire)) + TMH_json_validate_wireformat (wire)) { TMH_PARSE_release_data (spec); return TMH_RESPONSE_reply_arg_unknown (connection, diff --git a/src/mint/taler-mint-httpd_validation.c b/src/mint/taler-mint-httpd_validation.c new file mode 100644 index 000000000..461e88759 --- /dev/null +++ b/src/mint/taler-mint-httpd_validation.c @@ -0,0 +1,231 @@ +/* + This file is part of TALER + Copyright (C) 2016 GNUnet e.V. + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + TALER; see the file COPYING. If not, If not, see +*/ + +/** + * @file taler-mint-httpd_validation.c + * @brief helpers for calling the wire plugins to validate addresses + * @author Christian Grothoff + */ +#include "platform.h" +#include +#include "taler-mint-httpd_validation.h" +#include "taler_wire_plugin.h" + + +/** + * Information we keep for each plugin. + */ +struct Plugin +{ + + /** + * We keep plugins in a DLL. + */ + struct Plugin *next; + + /** + * We keep plugins in a DLL. + */ + struct Plugin *prev; + + /** + * Type of the wireformat. + */ + char *type; + + /** + * Pointer to the plugin. + */ + struct TALER_WIRE_Plugin *plugin; + +}; + +/** + * Head of DLL of wire plugins. + */ +static struct Plugin *wire_head; + +/** + * Tail of DLL of wire plugins. + */ +static struct Plugin *wire_tail; + + +/** + * Initialize validation subsystem. + * + * @param cfg configuration to use + * @return #GNUNET_OK on success + */ +int +TMH_VALIDATION_init (const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + struct Plugin *p; + char *wireformats; + char *lib_name; + const char *token; + + /* Find out list of supported wire formats */ + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + "mint", + "wireformat", + &wireformats)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "mint", + "wireformat"); + return GNUNET_SYSERR; + } + for (token = strtok (wireformats, + " "); + NULL != token; + token = strtok (NULL, + " ")) + { + (void) GNUNET_asprintf (&lib_name, + "libtaler_plugin_wire_%s", + lib_name); + p = GNUNET_new (struct Plugin); + p->type = GNUNET_strdup (token); + p->plugin = GNUNET_PLUGIN_load (lib_name, + (void *) cfg); + if (NULL == p->plugin) + { + GNUNET_free (p); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to load plugin %s\n", + lib_name); + GNUNET_free (lib_name); + TMH_VALIDATION_done (); + return GNUNET_SYSERR; + } + p->plugin->library_name = lib_name; + GNUNET_CONTAINER_DLL_insert (wire_head, + wire_tail, + p); + } + GNUNET_free (wireformats); + return GNUNET_OK; +} + + +/** + * Shutdown validation subsystem. + */ +void +TMH_VALIDATION_done () +{ + struct Plugin *p; + char *lib_name; + + while (NULL != (p = wire_head)) + { + GNUNET_CONTAINER_DLL_remove (wire_head, + wire_tail, + p); + lib_name = p->plugin->library_name; + GNUNET_assert (NULL == GNUNET_PLUGIN_unload (lib_name, + p->plugin)); + GNUNET_free (lib_name); + GNUNET_free (p->type); + GNUNET_free (p); + } +} + + +/** + * Check if the given wire format JSON object is correctly formatted as + * a wire address. + * + * @param wire the JSON wire format object + * @return #GNUNET_YES if correctly formatted; #GNUNET_NO if not + */ +int +TMH_json_validate_wireformat (const json_t *wire) +{ + const char *stype; + json_error_t error; + struct Plugin *p; + + if (0 != json_unpack_ex ((json_t *) wire, + &error, 0, + "{s:s}", + "type", &stype)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + for (p=wire_head; NULL != p; p = p->next) + if (0 == strcasecmp (p->type, + stype)) + return p->plugin->wire_validate (wire); + return GNUNET_NO; +} + + +/** + * Check if we support the given wire method. + * + * @param type type of wire method to check + * @return #GNUNET_YES if the method is supported + */ +int +TMH_VALIDATION_test_method (const char *type) +{ + struct Plugin *p; + + for (p=wire_head;NULL != p;p = p->next) + if (0 == strcasecmp (type, + p->type)) + return GNUNET_YES; + return GNUNET_NO; +} + + +/** + * Obtain supported validation methods as a JSON array, + * and as a hash. + * + * @param[out] h set to the hash of the JSON methods + * @return JSON array with the supported validation methods + */ +json_t * +TMH_VALIDATION_get_methods (struct GNUNET_HashCode *h) +{ + json_t *methods; + struct GNUNET_HashContext *hc; + const char *wf; + struct Plugin *p; + + methods = json_array (); + hc = GNUNET_CRYPTO_hash_context_start (); + for (p=wire_head;NULL != p;p = p->next) + { + wf = p->type; + json_array_append_new (methods, + json_string (wf)); + GNUNET_CRYPTO_hash_context_read (hc, + wf, + strlen (wf) + 1); + } + GNUNET_CRYPTO_hash_context_finish (hc, + h); + return methods; +} + + +/* end of taler-mint-httpd_validation.c */ diff --git a/src/mint/taler-mint-httpd_validation.h b/src/mint/taler-mint-httpd_validation.h new file mode 100644 index 000000000..f5fb19003 --- /dev/null +++ b/src/mint/taler-mint-httpd_validation.h @@ -0,0 +1,76 @@ +/* + This file is part of TALER + Copyright (C) 2016 GNUnet e.V. + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + TALER; see the file COPYING. If not, If not, see +*/ + +/** + * @file taler-mint-httpd_validation.h + * @brief helpers for calling the wire plugins to validate addresses + * @author Christian Grothoff + */ +#ifndef TALER_MINT_HTTPD_VALIDATION_H +#define TALER_MINT_HTTPD_VALIDATION_H +#include +#include + + +/** + * Initialize validation subsystem. + * + * @param cfg configuration to use + * @return #GNUNET_OK on success + */ +int +TMH_VALIDATION_init (const struct GNUNET_CONFIGURATION_Handle *cfg); + + +/** + * Shutdown validation subsystem. + */ +void +TMH_VALIDATION_done (void); + + +/** + * Check if the given wire format JSON object is correctly formatted as + * a wire address. + * + * @param wire the JSON wire format object + * @return #GNUNET_YES if correctly formatted; #GNUNET_NO if not + */ +int +TMH_json_validate_wireformat (const json_t *wire); + +/** + * Check if we support the given wire method. + * + * @param type type of wire method to check + * @return #GNUNET_YES if the method is supported + */ +int +TMH_VALIDATION_test_method (const char *type); + + +/** + * Obtain supported validation methods as a JSON array, + * and as a hash. + * + * @param[out] h set to the hash of the JSON methods + * @return JSON array with the supported validation methods + */ +json_t * +TMH_VALIDATION_get_methods (struct GNUNET_HashCode *h); + + +#endif diff --git a/src/mint/taler-mint-httpd_wire.c b/src/mint/taler-mint-httpd_wire.c index 1eb3f6bef..020a7e108 100644 --- a/src/mint/taler-mint-httpd_wire.c +++ b/src/mint/taler-mint-httpd_wire.c @@ -21,6 +21,7 @@ #include "platform.h" #include "taler-mint-httpd_keystate.h" #include "taler-mint-httpd_responses.h" +#include "taler-mint-httpd_validation.h" #include "taler-mint-httpd_wire.h" #include @@ -45,24 +46,10 @@ TMH_WIRE_handler_wire (struct TMH_RequestHandler *rh, struct TALER_MintPublicKeyP pub; struct TALER_MintSignatureP sig; json_t *methods; - struct GNUNET_HashContext *hc; - unsigned int i; - const char *wf; - methods = json_array (); - hc = GNUNET_CRYPTO_hash_context_start (); - for (i=0;NULL != (wf = TMH_expected_wire_formats[i]); i++) - { - json_array_append_new (methods, - json_string (wf)); - GNUNET_CRYPTO_hash_context_read (hc, - wf, - strlen (wf) + 1); - } wsm.purpose.size = htonl (sizeof (wsm)); wsm.purpose.purpose = htonl (TALER_SIGNATURE_MINT_WIRE_TYPES); - GNUNET_CRYPTO_hash_context_finish (hc, - &wsm.h_wire_types); + methods = TMH_VALIDATION_get_methods (&wsm.h_wire_types); TMH_KS_sign (&wsm.purpose, &pub, &sig); @@ -97,7 +84,6 @@ TMH_WIRE_handler_wire_test (struct TMH_RequestHandler *rh, struct MHD_Response *response; int ret; char *wire_test_redirect; - unsigned int i; response = MHD_create_response_from_buffer (0, NULL, MHD_RESPMEM_PERSISTENT); @@ -107,11 +93,7 @@ TMH_WIRE_handler_wire_test (struct TMH_RequestHandler *rh, return MHD_NO; } TMH_RESPONSE_add_global_headers (response); - for (i=0;NULL != TMH_expected_wire_formats[i];i++) - if (0 == strcasecmp ("test", - TMH_expected_wire_formats[i])) - break; - if (NULL == TMH_expected_wire_formats[i]) + if (GNUNET_NO == TMH_VALIDATION_test_method ("test")) { /* Return 501: not implemented */ ret = MHD_queue_response (connection, @@ -165,13 +147,8 @@ TMH_WIRE_handler_wire_sepa (struct TMH_RequestHandler *rh, char *sepa_wire_file; int fd; struct stat sbuf; - unsigned int i; - for (i=0;NULL != TMH_expected_wire_formats[i];i++) - if (0 == strcasecmp ("sepa", - TMH_expected_wire_formats[i])) - break; - if (NULL == TMH_expected_wire_formats[i]) + if (GNUNET_NO == TMH_VALIDATION_test_method ("sepa")) { /* Return 501: not implemented */ response = MHD_create_response_from_buffer (0, NULL,