implement #3972: support multiple wire formats concurrently

This commit is contained in:
Christian Grothoff 2015-09-20 13:48:15 +02:00
parent 1eadd66ae0
commit a6f8fa98b0
10 changed files with 93 additions and 41 deletions

1
.gitignore vendored
View File

@ -30,6 +30,7 @@ GTAGS
src/lib/test_mint_api src/lib/test_mint_api
doc/doxygen/doxygen_sqlite3.db doc/doxygen/doxygen_sqlite3.db
src/mint-lib/test_mint_api src/mint-lib/test_mint_api
src/mint-tools/taler-auditor-sign
src/mint-tools/taler-mint-dbinit src/mint-tools/taler-mint-dbinit
src/mint-tools/taler-mint-keycheck src/mint-tools/taler-mint-keycheck
src/mint-tools/taler-mint-keyup src/mint-tools/taler-mint-keyup

View File

@ -167,12 +167,12 @@ TALER_hash_json (json_t *json,
/** /**
* Check if the given wire format JSON object is correctly formatted * 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 * @param wire the JSON wire format object
* @return #GNUNET_YES if correctly formatted; #GNUNET_NO if not * @return #GNUNET_YES if correctly formatted; #GNUNET_NO if not
*/ */
int int
TALER_json_validate_wireformat (const char *type, TALER_json_validate_wireformat (const char **allowed,
const json_t *wire); const json_t *wire);

View File

@ -1992,13 +1992,13 @@ run (void *cls,
#if WIRE_TEST #if WIRE_TEST
{ .oc = OC_WIRE, { .oc = OC_WIRE,
.label = "wire", .label = "wire-test",
/* /wire/test replies with a 302 redirect */ /* /wire/test replies with a 302 redirect */
.expected_response_code = MHD_HTTP_FOUND }, .expected_response_code = MHD_HTTP_FOUND },
#endif #endif
#if WIRE_SEPA #if WIRE_SEPA
{ .oc = OC_WIRE, { .oc = OC_WIRE,
.label = "wire", .label = "wire-sepa",
/* /wire/sepa replies with a 200 redirect */ /* /wire/sepa replies with a 200 redirect */
.expected_response_code = MHD_HTTP_OK }, .expected_response_code = MHD_HTTP_OK },
#endif #endif

View File

@ -62,8 +62,10 @@ struct GNUNET_CRYPTO_EddsaPublicKey TMH_master_public_key;
/** /**
* In which format does this MINT expect wiring instructions? * 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. * Our DB plugin.
@ -363,6 +365,9 @@ mint_serve_process_config (const char *mint_directory)
{ {
unsigned long long port; unsigned long long port;
char *TMH_master_public_key_str; char *TMH_master_public_key_str;
char *wireformats;
const char *token;
unsigned int len;
cfg = TALER_config_load (mint_directory); cfg = TALER_config_load (mint_directory);
if (NULL == cfg) if (NULL == cfg)
@ -390,17 +395,36 @@ mint_serve_process_config (const char *mint_directory)
(unsigned int) TALER_CURRENCY_LEN); (unsigned int) TALER_CURRENCY_LEN);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
/* Find out list of supported wire formats */
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (cfg, GNUNET_CONFIGURATION_get_value_string (cfg,
"mint", "mint",
"wireformat", "wireformat",
&TMH_expected_wire_format)) &wireformats))
{ {
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"mint", "mint",
"wireformat"); "wireformat");
return GNUNET_SYSERR; 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 != if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (cfg, GNUNET_CONFIGURATION_get_value_string (cfg,
"mint", "mint",

View File

@ -48,9 +48,11 @@ extern int TMH_test_mode;
extern char *TMH_mint_directory; 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 * Master public key (according to the

View File

@ -142,7 +142,7 @@ TMH_ADMIN_handler_admin_add_incoming (struct TMH_RequestHandler *rh,
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
} }
if (GNUNET_YES != if (GNUNET_YES !=
TALER_json_validate_wireformat (TMH_expected_wire_format, TALER_json_validate_wireformat (TMH_expected_wire_formats,
wire)) wire))
{ {
TMH_PARSE_release_data (spec); TMH_PARSE_release_data (spec);

View File

@ -160,7 +160,7 @@ parse_and_handle_deposit_request (struct MHD_Connection *connection,
return MHD_YES; /* failure */ return MHD_YES; /* failure */
if (GNUNET_YES != if (GNUNET_YES !=
TALER_json_validate_wireformat (TMH_expected_wire_format, TALER_json_validate_wireformat (TMH_expected_wire_formats,
wire)) wire))
{ {
TMH_PARSE_release_data (spec); TMH_PARSE_release_data (spec);

View File

@ -45,23 +45,32 @@ TMH_WIRE_handler_wire (struct TMH_RequestHandler *rh,
struct TALER_MintPublicKeyP pub; struct TALER_MintPublicKeyP pub;
struct TALER_MintSignatureP sig; struct TALER_MintSignatureP sig;
json_t *methods; 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.size = htonl (sizeof (wsm));
wsm.purpose.purpose = htonl (TALER_SIGNATURE_MINT_WIRE_TYPES); wsm.purpose.purpose = htonl (TALER_SIGNATURE_MINT_WIRE_TYPES);
GNUNET_CRYPTO_hash (TMH_expected_wire_format, GNUNET_CRYPTO_hash_context_finish (hc,
strlen (TMH_expected_wire_format) + 1, &wsm.h_wire_types);
&wsm.h_wire_types);
TMH_KS_sign (&wsm.purpose, TMH_KS_sign (&wsm.purpose,
&pub, &pub,
&sig); &sig);
methods = json_array ();
/* NOTE: for now, we only support *ONE* wire format per /* NOTE: for now, we only support *ONE* wire format per
mint instance; if we supply multiple, we need to mint instance; if we supply multiple, we need to
add the strings for each type separately here -- and add the strings for each type separately here -- and
hash the 0-terminated strings above differently as well... hash the 0-terminated strings above differently as well...
See #3972. */ See #3972. */
json_array_append_new (methods,
json_string (TMH_expected_wire_format));
return TMH_RESPONSE_reply_json_pack (connection, return TMH_RESPONSE_reply_json_pack (connection,
MHD_HTTP_OK, MHD_HTTP_OK,
"{s:o, s:o, s:o}", "{s:o, s:o, s:o}",
@ -93,6 +102,7 @@ TMH_WIRE_handler_wire_test (struct TMH_RequestHandler *rh,
struct MHD_Response *response; struct MHD_Response *response;
int ret; int ret;
char *wire_test_redirect; char *wire_test_redirect;
unsigned int i;
response = MHD_create_response_from_buffer (0, NULL, response = MHD_create_response_from_buffer (0, NULL,
MHD_RESPMEM_PERSISTENT); MHD_RESPMEM_PERSISTENT);
@ -101,8 +111,11 @@ TMH_WIRE_handler_wire_test (struct TMH_RequestHandler *rh,
GNUNET_break (0); GNUNET_break (0);
return MHD_NO; return MHD_NO;
} }
if (0 != strcasecmp ("test", for (i=0;NULL != TMH_expected_wire_formats[i];i++)
TMH_expected_wire_format)) if (0 == strcasecmp ("test",
TMH_expected_wire_formats[i]))
break;
if (NULL == TMH_expected_wire_formats[i])
{ {
/* Return 501: not implemented */ /* Return 501: not implemented */
ret = MHD_queue_response (connection, ret = MHD_queue_response (connection,
@ -155,9 +168,13 @@ TMH_WIRE_handler_wire_sepa (struct TMH_RequestHandler *rh,
char *sepa_wire_file; char *sepa_wire_file;
int fd; int fd;
struct stat sbuf; struct stat sbuf;
unsigned int i;
if (0 != strcasecmp ("sepa", for (i=0;NULL != TMH_expected_wire_formats[i];i++)
TMH_expected_wire_format)) if (0 == strcasecmp ("sepa",
TMH_expected_wire_formats[i]))
break;
if (NULL == TMH_expected_wire_formats[i])
{ {
/* Return 501: not implemented */ /* Return 501: not implemented */
response = MHD_create_response_from_buffer (0, NULL, response = MHD_create_response_from_buffer (0, NULL,

View File

@ -15,7 +15,7 @@
*/ */
/** /**
* @file util/test_json_validations.c * @file util/test_wireformats.c
* @brief Tests for JSON validations * @brief Tests for JSON validations
* @author Sree Harsha Totakura <sreeharsha@totakura.in> * @author Sree Harsha Totakura <sreeharsha@totakura.in>
*/ */
@ -69,6 +69,14 @@ int
main(int argc, main(int argc,
const char *const argv[]) const char *const argv[])
{ {
const char *unsupported[] = {
"unsupported",
NULL
};
const char *sepa[] = {
"SEPA",
NULL
};
json_t *wire; json_t *wire;
json_error_t error; json_error_t error;
int ret; int ret;
@ -76,16 +84,16 @@ main(int argc,
GNUNET_log_setup ("test-json-validations", "WARNING", NULL); GNUNET_log_setup ("test-json-validations", "WARNING", NULL);
(void) memset(&error, 0, sizeof(error)); (void) memset(&error, 0, sizeof(error));
GNUNET_assert (NULL != (wire = json_loads (unsupported_wire_str, 0, NULL))); 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); json_decref (wire);
GNUNET_assert (NULL != (wire = json_loads (invalid_wire_str, 0, NULL))); 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); json_decref (wire);
GNUNET_assert (NULL != (wire = json_loads (invalid_wire_str2, 0, NULL))); 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); json_decref (wire);
GNUNET_assert (NULL != (wire = json_loads (valid_wire_str, 0, &error))); 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); json_decref (wire);
if (1 == ret) if (1 == ret)
return 0; return 0;

View File

@ -395,12 +395,12 @@ struct FormatHandler
/** /**
* Check if the given wire format JSON object is correctly formatted * 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 * @param wire the JSON wire format object
* @return #GNUNET_YES if correctly formatted; #GNUNET_NO if not * @return #GNUNET_YES if correctly formatted; #GNUNET_NO if not
*/ */
int int
TALER_json_validate_wireformat (const char *type, TALER_json_validate_wireformat (const char **allowed,
const json_t *wire) const json_t *wire)
{ {
static const struct FormatHandler format_handlers[] = { static const struct FormatHandler format_handlers[] = {
@ -409,33 +409,33 @@ TALER_json_validate_wireformat (const char *type,
{ NULL, NULL} { NULL, NULL}
}; };
unsigned int i; unsigned int i;
char *stype; const char *stype;
json_error_t error; json_error_t error;
UNPACK_EXITIF (0 != json_unpack_ex UNPACK_EXITIF (0 != json_unpack_ex
((json_t *) wire, ((json_t *) wire,
&error, 0, &error, 0,
"{" "{s:s}",
"s:s " /* TYPE: type */
"}",
"type", &stype)); "type", &stype));
if (0 != strcasecmp (type, for (i=0;NULL != allowed[i];i++)
stype)) if (0 == strcasecmp (allowed[i],
stype))
break;
if (NULL == allowed[i])
{ {
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Wireformat `%s' does not match mint's expected `%s' format\n", "Wireformat `%s' does not match mint's allowed formats\n",
stype, stype);
type);
return GNUNET_NO; return GNUNET_NO;
} }
for (i=0;NULL != format_handlers[i].type;i++) for (i=0;NULL != format_handlers[i].type;i++)
if (0 == strcasecmp (format_handlers[i].type, if (0 == strcasecmp (format_handlers[i].type,
type)) stype))
return format_handlers[i].handler (wire); return format_handlers[i].handler (wire);
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Wireformat `%s' not supported\n", "Wireformat `%s' not supported\n",
type); stype);
return GNUNET_NO; return GNUNET_NO;
EXITIF_exit: EXITIF_exit:
return GNUNET_NO; return GNUNET_NO;