From a6f8fa98b0253091cae0f2e38fb5fcec47e115fa Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 20 Sep 2015 13:48:15 +0200 Subject: [PATCH] implement #3972: support multiple wire formats concurrently --- .gitignore | 1 + src/include/taler_json_lib.h | 4 ++-- src/mint-lib/test_mint_api.c | 4 ++-- src/mint/taler-mint-httpd.c | 28 ++++++++++++++++++++-- src/mint/taler-mint-httpd.h | 6 +++-- src/mint/taler-mint-httpd_admin.c | 2 +- src/mint/taler-mint-httpd_deposit.c | 2 +- src/mint/taler-mint-httpd_wire.c | 37 +++++++++++++++++++++-------- src/util/test_wireformats.c | 24 ++++++++++++------- src/util/wireformats.c | 26 ++++++++++---------- 10 files changed, 93 insertions(+), 41 deletions(-) diff --git a/.gitignore b/.gitignore index 851e442c9..31f08e1d9 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,7 @@ GTAGS src/lib/test_mint_api doc/doxygen/doxygen_sqlite3.db src/mint-lib/test_mint_api +src/mint-tools/taler-auditor-sign src/mint-tools/taler-mint-dbinit src/mint-tools/taler-mint-keycheck src/mint-tools/taler-mint-keyup diff --git a/src/include/taler_json_lib.h b/src/include/taler_json_lib.h index 5a13b9bca..63cb81791 100644 --- a/src/include/taler_json_lib.h +++ b/src/include/taler_json_lib.h @@ -167,12 +167,12 @@ TALER_hash_json (json_t *json, /** * Check if the given wire format JSON object is correctly formatted * - * @param type the type of the wire format + * @param allowed NULL-terminated array of allowed wire format types * @param wire the JSON wire format object * @return #GNUNET_YES if correctly formatted; #GNUNET_NO if not */ int -TALER_json_validate_wireformat (const char *type, +TALER_json_validate_wireformat (const char **allowed, const json_t *wire); diff --git a/src/mint-lib/test_mint_api.c b/src/mint-lib/test_mint_api.c index b2f833d08..6fb099095 100644 --- a/src/mint-lib/test_mint_api.c +++ b/src/mint-lib/test_mint_api.c @@ -1992,13 +1992,13 @@ run (void *cls, #if WIRE_TEST { .oc = OC_WIRE, - .label = "wire", + .label = "wire-test", /* /wire/test replies with a 302 redirect */ .expected_response_code = MHD_HTTP_FOUND }, #endif #if WIRE_SEPA { .oc = OC_WIRE, - .label = "wire", + .label = "wire-sepa", /* /wire/sepa replies with a 200 redirect */ .expected_response_code = MHD_HTTP_OK }, #endif diff --git a/src/mint/taler-mint-httpd.c b/src/mint/taler-mint-httpd.c index cd2f62768..86d20fdba 100644 --- a/src/mint/taler-mint-httpd.c +++ b/src/mint/taler-mint-httpd.c @@ -62,8 +62,10 @@ 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(). */ -char *TMH_expected_wire_format; +const char **TMH_expected_wire_formats; /** * Our DB plugin. @@ -363,6 +365,9 @@ 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) @@ -390,17 +395,36 @@ 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", - &TMH_expected_wire_format)) + &wireformats)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "mint", "wireformat"); 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, "mint", diff --git a/src/mint/taler-mint-httpd.h b/src/mint/taler-mint-httpd.h index a54e5aa2e..3cbbc0dfd 100644 --- a/src/mint/taler-mint-httpd.h +++ b/src/mint/taler-mint-httpd.h @@ -48,9 +48,11 @@ extern int TMH_test_mode; extern char *TMH_mint_directory; /** - * In which format does this MINT expect wiring instructions? + * 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 char *TMH_expected_wire_format; +extern const char **TMH_expected_wire_formats; /** * Master public key (according to the diff --git a/src/mint/taler-mint-httpd_admin.c b/src/mint/taler-mint-httpd_admin.c index 5fdfa58ee..3e3f13ad3 100644 --- a/src/mint/taler-mint-httpd_admin.c +++ b/src/mint/taler-mint-httpd_admin.c @@ -142,7 +142,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_format, + TALER_json_validate_wireformat (TMH_expected_wire_formats, wire)) { TMH_PARSE_release_data (spec); diff --git a/src/mint/taler-mint-httpd_deposit.c b/src/mint/taler-mint-httpd_deposit.c index 5725cd1c6..c6ebe1d0d 100644 --- a/src/mint/taler-mint-httpd_deposit.c +++ b/src/mint/taler-mint-httpd_deposit.c @@ -160,7 +160,7 @@ parse_and_handle_deposit_request (struct MHD_Connection *connection, return MHD_YES; /* failure */ if (GNUNET_YES != - TALER_json_validate_wireformat (TMH_expected_wire_format, + TALER_json_validate_wireformat (TMH_expected_wire_formats, wire)) { TMH_PARSE_release_data (spec); diff --git a/src/mint/taler-mint-httpd_wire.c b/src/mint/taler-mint-httpd_wire.c index 13f23e8e0..68dc1419f 100644 --- a/src/mint/taler-mint-httpd_wire.c +++ b/src/mint/taler-mint-httpd_wire.c @@ -45,23 +45,32 @@ 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 (TMH_expected_wire_format, - strlen (TMH_expected_wire_format) + 1, - &wsm.h_wire_types); + GNUNET_CRYPTO_hash_context_finish (hc, + &wsm.h_wire_types); TMH_KS_sign (&wsm.purpose, &pub, &sig); - methods = json_array (); /* NOTE: for now, we only support *ONE* wire format per mint instance; if we supply multiple, we need to add the strings for each type separately here -- and hash the 0-terminated strings above differently as well... See #3972. */ - json_array_append_new (methods, - json_string (TMH_expected_wire_format)); return TMH_RESPONSE_reply_json_pack (connection, MHD_HTTP_OK, "{s:o, s:o, s:o}", @@ -93,6 +102,7 @@ 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); @@ -101,8 +111,11 @@ TMH_WIRE_handler_wire_test (struct TMH_RequestHandler *rh, GNUNET_break (0); return MHD_NO; } - if (0 != strcasecmp ("test", - TMH_expected_wire_format)) + 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]) { /* Return 501: not implemented */ ret = MHD_queue_response (connection, @@ -155,9 +168,13 @@ TMH_WIRE_handler_wire_sepa (struct TMH_RequestHandler *rh, char *sepa_wire_file; int fd; struct stat sbuf; + unsigned int i; - if (0 != strcasecmp ("sepa", - TMH_expected_wire_format)) + 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]) { /* Return 501: not implemented */ response = MHD_create_response_from_buffer (0, NULL, diff --git a/src/util/test_wireformats.c b/src/util/test_wireformats.c index ebb96604c..e4bd238f7 100644 --- a/src/util/test_wireformats.c +++ b/src/util/test_wireformats.c @@ -15,9 +15,9 @@ */ /** - * @file util/test_json_validations.c + * @file util/test_wireformats.c * @brief Tests for JSON validations - * @author Sree Harsha Totakura + * @author Sree Harsha Totakura */ #include "platform.h" @@ -65,10 +65,18 @@ static const char * const unsupported_wire_str = \"address\": \"foobar\"}"; -int -main(int argc, +int +main(int argc, const char *const argv[]) { + const char *unsupported[] = { + "unsupported", + NULL + }; + const char *sepa[] = { + "SEPA", + NULL + }; json_t *wire; json_error_t error; int ret; @@ -76,16 +84,16 @@ main(int argc, GNUNET_log_setup ("test-json-validations", "WARNING", NULL); (void) memset(&error, 0, sizeof(error)); GNUNET_assert (NULL != (wire = json_loads (unsupported_wire_str, 0, NULL))); - GNUNET_assert (1 != TALER_json_validate_wireformat ("unsupported", wire)); + GNUNET_assert (1 != TALER_json_validate_wireformat (unsupported, wire)); json_decref (wire); GNUNET_assert (NULL != (wire = json_loads (invalid_wire_str, 0, NULL))); - GNUNET_assert (1 != TALER_json_validate_wireformat ("SEPA", wire)); + GNUNET_assert (1 != TALER_json_validate_wireformat (sepa, wire)); json_decref (wire); GNUNET_assert (NULL != (wire = json_loads (invalid_wire_str2, 0, NULL))); - GNUNET_assert (1 != TALER_json_validate_wireformat ("SEPA", wire)); + GNUNET_assert (1 != TALER_json_validate_wireformat (sepa, wire)); json_decref (wire); GNUNET_assert (NULL != (wire = json_loads (valid_wire_str, 0, &error))); - ret = TALER_json_validate_wireformat ("SEPA", wire); + ret = TALER_json_validate_wireformat (sepa, wire); json_decref (wire); if (1 == ret) return 0; diff --git a/src/util/wireformats.c b/src/util/wireformats.c index 88af4a438..5f9678526 100644 --- a/src/util/wireformats.c +++ b/src/util/wireformats.c @@ -395,12 +395,12 @@ struct FormatHandler /** * Check if the given wire format JSON object is correctly formatted * - * @param type the expected type of the wire format + * @param allowed NULL-terminated array of allowed wire format types * @param wire the JSON wire format object * @return #GNUNET_YES if correctly formatted; #GNUNET_NO if not */ int -TALER_json_validate_wireformat (const char *type, +TALER_json_validate_wireformat (const char **allowed, const json_t *wire) { static const struct FormatHandler format_handlers[] = { @@ -409,33 +409,33 @@ TALER_json_validate_wireformat (const char *type, { NULL, NULL} }; unsigned int i; - char *stype; + const char *stype; json_error_t error; UNPACK_EXITIF (0 != json_unpack_ex ((json_t *) wire, &error, 0, - "{" - "s:s " /* TYPE: type */ - "}", + "{s:s}", "type", &stype)); - if (0 != strcasecmp (type, - stype)) + for (i=0;NULL != allowed[i];i++) + if (0 == strcasecmp (allowed[i], + stype)) + break; + if (NULL == allowed[i]) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Wireformat `%s' does not match mint's expected `%s' format\n", - stype, - type); + "Wireformat `%s' does not match mint's allowed formats\n", + stype); return GNUNET_NO; } for (i=0;NULL != format_handlers[i].type;i++) if (0 == strcasecmp (format_handlers[i].type, - type)) + stype)) return format_handlers[i].handler (wire); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Wireformat `%s' not supported\n", - type); + stype); return GNUNET_NO; EXITIF_exit: return GNUNET_NO;