From 899f2b4070ec04af0e0040f6b7fa62d3d860ffee Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 14 Sep 2015 15:29:40 +0200 Subject: implement /wire api (#3947) --- src/mint-lib/mint_api_wire.c | 611 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 611 insertions(+) create mode 100644 src/mint-lib/mint_api_wire.c (limited to 'src/mint-lib/mint_api_wire.c') diff --git a/src/mint-lib/mint_api_wire.c b/src/mint-lib/mint_api_wire.c new file mode 100644 index 00000000..7641af7a --- /dev/null +++ b/src/mint-lib/mint_api_wire.c @@ -0,0 +1,611 @@ +/* + This file is part of TALER + Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, If not, see + +*/ +/** + * @file mint-lib/mint_api_wire.c + * @brief Implementation of the /wire request of the mint's HTTP API + * @author Christian Grothoff + */ +#include "platform.h" +#include +#include +#include /* just for HTTP status codes */ +#include +#include "taler_mint_service.h" +#include "mint_api_common.h" +#include "mint_api_json.h" +#include "mint_api_context.h" +#include "mint_api_handle.h" +#include "taler_signatures.h" + + +/** + * @brief A Wire Handle + */ +struct TALER_MINT_WireHandle +{ + + /** + * The connection to mint this request handle will use + */ + struct TALER_MINT_Handle *mint; + + /** + * The url for this request. + */ + char *url; + + /** + * Handle for the request. + */ + struct MAC_Job *job; + + /** + * Function to call with the result. + */ + TALER_MINT_WireResultCallback cb; + + /** + * Closure for @a cb. + */ + void *cb_cls; + + /** + * Download buffer + */ + struct MAC_DownloadBuffer db; + + /** + * Set to the "methods" JSON array returned by the + * /wire request. + */ + json_t *methods; + + /** + * Current iteration offset in the @e methods array. + */ + unsigned int methods_off; + +}; + + +/** + * Verify that the signature on the "200 OK" response + * for /wire/sepa from the mint is valid. + * + * @param wh wire handle + * @param json json reply with the signature + * @return #GNUNET_SYSERR if @a json is invalid, + * #GNUNET_NO if the method is unknown, + * #GNUNET_OK if the json is valid + */ +static int +verify_wire_sepa_signature_ok (const struct TALER_MINT_WireHandle *wh, + json_t *json) +{ + struct TALER_MasterSignatureP mint_sig; + struct TALER_MasterWireSepaDetailsPS mp; + const char *receiver_name; + const char *iban; + const char *bic; + const struct TALER_MINT_Keys *key_state; + struct GNUNET_HashContext *hc; + struct MAJ_Specification spec[] = { + MAJ_spec_fixed_auto ("sig", &mint_sig), + MAJ_spec_string ("receiver_name", &receiver_name), + MAJ_spec_string ("iban", &iban), + MAJ_spec_string ("bic", &bic), + MAJ_spec_end + }; + + if (GNUNET_OK != + MAJ_parse_json (json, + spec)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + + key_state = TALER_MINT_get_keys (wh->mint); + mp.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SEPA_DETAILS); + mp.purpose.size = htonl (sizeof (struct TALER_MasterWireSepaDetailsPS)); + hc = GNUNET_CRYPTO_hash_context_start (); + GNUNET_CRYPTO_hash_context_read (hc, + receiver_name, + strlen (receiver_name) + 1); + GNUNET_CRYPTO_hash_context_read (hc, + iban, + strlen (iban) + 1); + GNUNET_CRYPTO_hash_context_read (hc, + bic, + strlen (bic) + 1); + GNUNET_CRYPTO_hash_context_finish (hc, + &mp.h_sepa_details); + + if (GNUNET_OK != + GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_SEPA_DETAILS, + &mp.purpose, + &mint_sig.eddsa_signature, + &key_state->master_pub.eddsa_pub)) + { + GNUNET_break_op (0); + MAJ_parse_free (spec); + return GNUNET_SYSERR; + } + MAJ_parse_free (spec); + return GNUNET_OK; +} + + +/** + * Verify that the signature on the "200 OK" response + * for /wire/METHOD from the mint is valid. + * + * @param wh wire handle with key material + * @param method method to verify the reply for + * @param json json reply with the signature + * @return #GNUNET_SYSERR if @a json is invalid, + * #GNUNET_NO if the method is unknown, + * #GNUNET_OK if the json is valid + */ +static int +verify_wire_method_signature_ok (const struct TALER_MINT_WireHandle *wh, + const char *method, + json_t *json) +{ + struct + { + /** + * Name fo the method. + */ + const char *method; + + /** + * Handler to invoke to verify signature. + * + * @param wh wire handle with key material + * @param json json reply with signature to verify + */ + int (*handler)(const struct TALER_MINT_WireHandle *wh, + json_t *json); + } handlers[] = { + { "sepa", &verify_wire_sepa_signature_ok }, + { NULL, NULL } + }; + unsigned int i; + + for (i=0;NULL != handlers[i].method; i++) + if (0 == strcasecmp (handlers[i].method, + method)) + return handlers[i].handler (wh, + json); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Wire transfer method `%s' not supported\n", + method); + return GNUNET_NO; +} + + +/** + * Perform the next /wire/method request or signal + * the end of the iteration. + * + * @param wh the wire handle + * @return a handle for this request + */ +static void +request_wire_method (struct TALER_MINT_WireHandle *wh); + + +/** + * Function called when we're done processing the + * HTTP /wire/METHOD request. + * + * @param cls the `struct TALER_MINT_WireHandle` + * @param eh the curl request handle + */ +static void +handle_wire_method_finished (void *cls, + CURL *eh) +{ + struct TALER_MINT_WireHandle *wh = cls; + long response_code; + json_t *json; + + wh->job = NULL; + json = MAC_download_get_result (&wh->db, + eh, + &response_code); + switch (response_code) + { + case 0: + break; + case MHD_HTTP_OK: + { + const char *method; + + method = json_string_value (json_array_get (wh->methods, + wh->methods_off - 1)); + if (GNUNET_OK != + verify_wire_method_signature_ok (wh, + method, + json)) + { + GNUNET_break_op (0); + response_code = 0; + break; + } + break; + } + case MHD_HTTP_FOUND: + /* /wire/test returns a 302 redirect, we should just give + this information back to the callback below */ + break; + case MHD_HTTP_BAD_REQUEST: + /* This should never happen, either us or the mint is buggy + (or API version conflict); just pass JSON reply to the application */ + break; + case MHD_HTTP_NOT_FOUND: + /* Nothing really to verify, this should never + happen, we should pass the JSON reply to the application */ + break; + case MHD_HTTP_INTERNAL_SERVER_ERROR: + /* Server had an internal issue; we should retry, but this API + leaves this to the application */ + break; + default: + /* unexpected response code */ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected response code %u\n", + response_code); + GNUNET_break (0); + response_code = 0; + break; + } + if (0 == response_code) + { + /* signal end of iteration */ + wh->cb (wh->cb_cls, + 0, + NULL, + NULL); + json_decref (json); + TALER_MINT_wire_cancel (wh); + } + /* pass on successful reply */ + wh->cb (wh->cb_cls, + response_code, + NULL, + json); + /* trigger request for the next /wire/method */ + request_wire_method (wh); +} + + +/** + * Perform the next /wire/method request or signal + * the end of the iteration. + * + * @param wh the wire handle + * @return a handle for this request + */ +static void +request_wire_method (struct TALER_MINT_WireHandle *wh) +{ + struct TALER_MINT_Context *ctx; + CURL *eh; + char *path; + + if (json_array_size (wh->methods) <= wh->methods_off) + { + /* we are done, signal end of iteration */ + wh->cb (wh->cb_cls, + 0, + NULL, + NULL); + TALER_MINT_wire_cancel (wh); + return; + } + GNUNET_free_non_null (wh->db.buf); + wh->db.buf = NULL; + wh->db.buf_size = 0; + wh->db.eno = 0; + GNUNET_free_non_null (wh->url); + GNUNET_asprintf (&path, + "/wire/%s", + json_string_value (json_array_get (wh->methods, + wh->methods_off++))); + wh->url = MAH_path_to_url (wh->mint, + path); + GNUNET_free (path); + + eh = curl_easy_init (); + GNUNET_assert (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_URL, + wh->url)); + GNUNET_assert (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_WRITEFUNCTION, + &MAC_download_cb)); + GNUNET_assert (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_WRITEDATA, + &wh->db)); + ctx = MAH_handle_to_context (wh->mint); + wh->job = MAC_job_add (ctx, + eh, + GNUNET_YES, + &handle_wire_method_finished, + wh); +} + + +/** + * Verify that the signature on the "200 OK" response + * for /wire from the mint is valid. + * + * @param wh wire handle + * @param json json reply with the signature + * @return NULL if @a json is invalid, otherwise the + * "methods" array (with an RC of 1) + */ +static json_t * +verify_wire_signature_ok (const struct TALER_MINT_WireHandle *wh, + json_t *json) +{ + struct TALER_MintSignatureP mint_sig; + struct TALER_MintPublicKeyP mint_pub; + struct TALER_MintWireSupportMethodsPS mp; + json_t *methods; + const struct TALER_MINT_Keys *key_state; + struct GNUNET_HashContext *hc; + struct MAJ_Specification spec[] = { + MAJ_spec_fixed_auto ("sig", &mint_sig), + MAJ_spec_fixed_auto ("pub", &mint_pub), + MAJ_spec_json ("methods", &methods), + MAJ_spec_end + }; + unsigned int i; + + if (GNUNET_OK != + MAJ_parse_json (json, + spec)) + { + GNUNET_break_op (0); + return NULL; + } + if (! json_is_array (methods)) + { + GNUNET_break_op (0); + MAJ_parse_free (spec); + return NULL; + } + + key_state = TALER_MINT_get_keys (wh->mint); + if (GNUNET_OK != + TALER_MINT_test_signing_key (key_state, + &mint_pub)) + { + GNUNET_break_op (0); + return NULL; + } + hc = GNUNET_CRYPTO_hash_context_start (); + for (i=0;ijob = NULL; + json = MAC_download_get_result (&wh->db, + eh, + &response_code); + switch (response_code) + { + case 0: + break; + case MHD_HTTP_OK: + { + json_t *methods; + + if (NULL == + (methods = verify_wire_signature_ok (wh, + json))) + { + GNUNET_break_op (0); + response_code = 0; + break; + } + wh->methods = methods; + request_wire_method (wh); + return; + } + break; + case MHD_HTTP_BAD_REQUEST: + /* This should never happen, either us or the mint is buggy + (or API version conflict); just pass JSON reply to the application */ + break; + case MHD_HTTP_NOT_FOUND: + /* Nothing really to verify, this should never + happen, we should pass the JSON reply to the application */ + break; + case MHD_HTTP_INTERNAL_SERVER_ERROR: + /* Server had an internal issue; we should retry, but this API + leaves this to the application */ + break; + default: + /* unexpected response code */ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected response code %u\n", + response_code); + GNUNET_break (0); + response_code = 0; + break; + } + if (0 != response_code) + { + /* pass on successful reply */ + wh->cb (wh->cb_cls, + response_code, + NULL, + json); + } + /* signal end of iteration */ + wh->cb (wh->cb_cls, + 0, + NULL, + NULL); + json_decref (json); + TALER_MINT_wire_cancel (wh); +} + + +/** + * Obtain information about a mint's wire instructions. + * A mint may provide wire instructions for creating + * a reserve. The wire instructions also indicate + * which wire formats merchants may use with the mint. + * This API is typically used by a wallet for wiring + * funds, and possibly by a merchant to determine + * supported wire formats. + * + * Note that while we return the (main) response verbatim to the + * caller for further processing, we do already verify that the + * response is well-formed (i.e. that signatures included in the + * response are all valid). If the mint's reply is not well-formed, + * we return an HTTP status code of zero to @a cb. + * + * @param mint the mint handle; the mint must be ready to operate + * @param wire_cb the callback to call when a reply for this request is available + * @param wire_cb_cls closure for the above callback + * @return a handle for this request + */ +struct TALER_MINT_WireHandle * +TALER_MINT_wire (struct TALER_MINT_Handle *mint, + TALER_MINT_WireResultCallback wire_cb, + void *wire_cb_cls) +{ + struct TALER_MINT_WireHandle *wh; + struct TALER_MINT_Context *ctx; + CURL *eh; + + if (GNUNET_YES != + MAH_handle_is_ready (mint)) + { + GNUNET_break (0); + return NULL; + } + wh = GNUNET_new (struct TALER_MINT_WireHandle); + wh->mint = mint; + wh->cb = wire_cb; + wh->cb_cls = wire_cb_cls; + wh->url = MAH_path_to_url (mint, "/wire"); + + eh = curl_easy_init (); + GNUNET_assert (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_URL, + wh->url)); + GNUNET_assert (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_WRITEFUNCTION, + &MAC_download_cb)); + GNUNET_assert (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_WRITEDATA, + &wh->db)); + ctx = MAH_handle_to_context (mint); + wh->job = MAC_job_add (ctx, + eh, + GNUNET_YES, + &handle_wire_finished, + wh); + return wh; +} + + +/** + * Cancel a wire information request. This function cannot be used + * on a request handle if a response is already served for it. + * + * @param wire the wire information request handle + */ +void +TALER_MINT_wire_cancel (struct TALER_MINT_WireHandle *wire) +{ + if (NULL != wire->job) + { + MAC_job_cancel (wire->job); + wire->job = NULL; + } + if (NULL != wire->methods) + { + json_decref (wire->methods); + wire->methods = NULL; + } + GNUNET_free_non_null (wire->db.buf); + GNUNET_free (wire->url); + GNUNET_free (wire); +} + + +/* end of mint_api_wire.c */ -- cgit v1.2.3 From e68446e0a8a4a54b99ba5773a9f7ff17837a393b Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 15 Sep 2015 17:27:02 +0200 Subject: adding tests for /wire --- contrib/mint-template/config/mint-common.conf | 8 +++- src/mint-lib/mint_api_context.c | 23 ++++++++++ src/mint-lib/mint_api_wire.c | 9 +++- .../test-mint-home/config/mint-common.conf | 15 +++++-- src/mint-lib/test-mint-home/sepa.json | 6 +++ src/mint-lib/test_mint_api.c | 35 +++++++++++++-- src/mint/taler-mint-httpd.c | 2 +- src/mint/taler-mint-httpd_wire.c | 52 +++++++++++++++------- 8 files changed, 125 insertions(+), 25 deletions(-) create mode 100644 src/mint-lib/test-mint-home/sepa.json (limited to 'src/mint-lib/mint_api_wire.c') diff --git a/contrib/mint-template/config/mint-common.conf b/contrib/mint-template/config/mint-common.conf index e222a36a..958763b2 100644 --- a/contrib/mint-template/config/mint-common.conf +++ b/contrib/mint-template/config/mint-common.conf @@ -2,7 +2,7 @@ # Currency supported by the mint (can only be one) CURRENCY = EUR -# Wire format supproted by the mint (currently only SEPA is implemented) +# Wire format supported by the mint (currently only SEPA is implemented) WIREFORMAT = SEPA # HTTP port the mint listens to @@ -19,3 +19,9 @@ TESTRUN = YES [mintdb-postgres] DB_CONN_STR = "postgres:///talercheck" + +[mint-wire-sepa] +SEPA_RESPONSE_FILE = "sepa.json" + +[mint-wire-test] +REDIRECT_URL = "http://test/" diff --git a/src/mint-lib/mint_api_context.c b/src/mint-lib/mint_api_context.c index 9beeef14..5a14b4a4 100644 --- a/src/mint-lib/mint_api_context.c +++ b/src/mint-lib/mint_api_context.c @@ -435,6 +435,29 @@ MAC_download_get_result (struct MAC_DownloadBuffer *db, { json_t *json; json_error_t error; + char *ct; + + if ( (CURLE_OK != + curl_easy_getinfo (eh, + CURLINFO_CONTENT_TYPE, + &ct)) || + (NULL == ct) || + (0 != strcasecmp (ct, + "application/json")) ) + { + /* No content type or explicitly not JSON, refuse to parse + (but keep response code) */ + if (CURLE_OK != + curl_easy_getinfo (eh, + CURLINFO_RESPONSE_CODE, + response_code)) + { + /* unexpected error... */ + GNUNET_break (0); + *response_code = 0; + } + return NULL; + } json = NULL; if (0 == db->eno) diff --git a/src/mint-lib/mint_api_wire.c b/src/mint-lib/mint_api_wire.c index 7641af7a..f1bbb099 100644 --- a/src/mint-lib/mint_api_wire.c +++ b/src/mint-lib/mint_api_wire.c @@ -284,6 +284,7 @@ handle_wire_method_finished (void *cls, NULL); json_decref (json); TALER_MINT_wire_cancel (wh); + return; } /* pass on successful reply */ wh->cb (wh->cb_cls, @@ -345,6 +346,11 @@ request_wire_method (struct TALER_MINT_WireHandle *wh) curl_easy_setopt (eh, CURLOPT_WRITEDATA, &wh->db)); + /* The default is 'disabled', but let's be sure */ + GNUNET_assert (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_FOLLOWLOCATION, + (long) 0)); ctx = MAH_handle_to_context (wh->mint); wh->job = MAC_job_add (ctx, eh, @@ -514,7 +520,8 @@ handle_wire_finished (void *cls, 0, NULL, NULL); - json_decref (json); + if (NULL != json) + json_decref (json); TALER_MINT_wire_cancel (wh); } diff --git a/src/mint-lib/test-mint-home/config/mint-common.conf b/src/mint-lib/test-mint-home/config/mint-common.conf index 1b8aa421..eb2f7e90 100644 --- a/src/mint-lib/test-mint-home/config/mint-common.conf +++ b/src/mint-lib/test-mint-home/config/mint-common.conf @@ -2,9 +2,12 @@ # Currency supported by the mint (can only be one) CURRENCY = EUR -# Wire format supproted by the mint -# TEST is used for testing... (what a shock) -WIREFORMAT = TEST +# Wire format supported by the mint +# We use 'test' for testing, in principle we should +# run tests for all supported wire formats... +# (we should first implement support for a mint running +# with multiple formats at the same time). +WIREFORMAT = test # HTTP port the mint listens to PORT = 8081 @@ -21,3 +24,9 @@ TESTRUN = YES [mintdb-postgres] DB_CONN_STR = "postgres:///talercheck" + +[mint-wire-sepa] +SEPA_RESPONSE_FILE = "test-mint-home/sepa.json" + +[mint-wire-test] +REDIRECT_URL = "http://www.taler.net/" diff --git a/src/mint-lib/test-mint-home/sepa.json b/src/mint-lib/test-mint-home/sepa.json new file mode 100644 index 00000000..36d12f66 --- /dev/null +++ b/src/mint-lib/test-mint-home/sepa.json @@ -0,0 +1,6 @@ +{ + "receiver_name": "Max Mustermann", + "iban": "DE89370400440532013000", + "bic": "COBADEFF370", + "sig": "8M5YJXM68PRAXKH76HYEBCJW657B23JA0RFGNDMZK2379YZMT626H1BN89KC0M1KJBWGYEN5Z763Q0Y7MCTZQ6BPPT7D9KFCTW60C10" +} \ No newline at end of file diff --git a/src/mint-lib/test_mint_api.c b/src/mint-lib/test_mint_api.c index fdadcd2c..cd1a094c 100644 --- a/src/mint-lib/test_mint_api.c +++ b/src/mint-lib/test_mint_api.c @@ -26,6 +26,15 @@ #include #include +/** + * Is the configuration file is set to include wire format 'test'? + */ +#define WIRE_TEST 1 + +/** + * Is the configuration file is set to include wire format 'sepa'? + */ +#define WIRE_SEPA 0 /** * Main execution context for the main loop. @@ -1357,7 +1366,6 @@ interpreter_run (void *cls, &coin_pub.eddsa_pub); cmd->details.withdraw_sign.blinding_key.rsa_blinding_key = GNUNET_CRYPTO_rsa_blinding_key_create (GNUNET_CRYPTO_rsa_public_key_len (cmd->details.withdraw_sign.pk->key.rsa_public_key)); - cmd->details.withdraw_sign.wsh = TALER_MINT_withdraw_sign (mint, cmd->details.withdraw_sign.pk, @@ -1442,7 +1450,6 @@ interpreter_run (void *cls, fail (is); return; } - GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv, &coin_pub.eddsa_pub); @@ -1464,6 +1471,7 @@ interpreter_run (void *cls, { struct TALER_DepositRequestPS dr; + memset (&dr, 0, sizeof (dr)); dr.purpose.size = htonl (sizeof (struct TALER_DepositRequestPS)); dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT); dr.h_contract = h_contract; @@ -1482,7 +1490,6 @@ interpreter_run (void *cls, GNUNET_CRYPTO_eddsa_sign (&coin_priv->eddsa_priv, &dr.purpose, &coin_sig.eddsa_signature)); - } cmd->details.deposit.dh = TALER_MINT_deposit (mint, @@ -1980,6 +1987,26 @@ run (void *cls, }; static struct Command commands[] = { + /* *************** start of /wire testing ************** */ + +#if WIRE_TEST + { .oc = OC_WIRE, + .label = "wire", + /* /wire/test replies with a 302 redirect */ + .expected_response_code = MHD_HTTP_FOUND }, +#endif +#if WIRE_SEPA + { .oc = OC_WIRE, + .label = "wire", + /* /wire/sepa replies with a 200 redirect */ + .expected_response_code = MHD_HTTP_OK }, +#endif + /* *************** end of /wire testing ************** */ + +#if WIRE_TEST + /* None of this works if 'test' is not allowed as we do + /admin/add/incoming with format 'test' */ + /* Fill reserve with EUR:5.01, as withdraw fee is 1 ct per config */ { .oc = OC_ADMIN_ADD_INCOMING, .label = "create-reserve-1", @@ -2126,8 +2153,8 @@ run (void *cls, // FIXME: also test with coin that was already melted // (signature differs from coin that was deposited...) - /* *************** end of /refresh testing ************** */ +#endif { .oc = OC_END } }; diff --git a/src/mint/taler-mint-httpd.c b/src/mint/taler-mint-httpd.c index 1a5e5a2f..e68cd242 100644 --- a/src/mint/taler-mint-httpd.c +++ b/src/mint/taler-mint-httpd.c @@ -177,7 +177,7 @@ handle_mhd_request (void *cls, { "/wire/test", MHD_HTTP_METHOD_GET, "application/json", NULL, 0, - &TMH_WIRE_handler_wire_test, MHD_HTTP_OK }, + &TMH_WIRE_handler_wire_test, MHD_HTTP_FOUND }, { "/wire/test", NULL, "text/plain", "Only GET is allowed", 0, &TMH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, diff --git a/src/mint/taler-mint-httpd_wire.c b/src/mint/taler-mint-httpd_wire.c index ee3b4ff0..0e28db79 100644 --- a/src/mint/taler-mint-httpd_wire.c +++ b/src/mint/taler-mint-httpd_wire.c @@ -56,14 +56,14 @@ TMH_WIRE_handler_wire (struct TMH_RequestHandler *rh, &sig); methods = json_array (); /* 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 hash the 0-terminated strings above differently as well... */ json_array_append_new (methods, json_string (TMH_expected_wire_format)); return TMH_RESPONSE_reply_json_pack (connection, MHD_HTTP_OK, - "{s:s, s:o, s:o}", + "{s:o, s:o, s:o}", "methods", methods, "sig", TALER_json_from_data (&sig, sizeof (sig)), @@ -100,26 +100,30 @@ TMH_WIRE_handler_wire_test (struct TMH_RequestHandler *rh, GNUNET_break (0); return MHD_NO; } - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, - "mint-wire-test", - "REDIRECT_URL", - &wire_test_redirect)) + if (0 != strcasecmp ("test", + TMH_expected_wire_format)) { + /* Return 501: not implemented */ ret = MHD_queue_response (connection, MHD_HTTP_NOT_IMPLEMENTED, response); MHD_destroy_response (response); return ret; } + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + "mint-wire-test", + "REDIRECT_URL", + &wire_test_redirect)) + { + /* oopsie, configuration error */ + return TMH_RESPONSE_reply_internal_error (connection, + "REDIRECT_URL not configured"); + } MHD_add_response_header (response, MHD_HTTP_HEADER_LOCATION, wire_test_redirect); GNUNET_free (wire_test_redirect); - if (NULL != rh->mime_type) - (void) MHD_add_response_header (response, - MHD_HTTP_HEADER_CONTENT_TYPE, - rh->mime_type); ret = MHD_queue_response (connection, rh->response_code, response); @@ -151,11 +155,29 @@ TMH_WIRE_handler_wire_sepa (struct TMH_RequestHandler *rh, int fd; struct stat sbuf; + if (0 != strcasecmp ("sepa", + TMH_expected_wire_format)) + { + /* Return 501: not implemented */ + response = MHD_create_response_from_buffer (0, NULL, + MHD_RESPMEM_PERSISTENT); + if (NULL == response) + { + GNUNET_break (0); + return MHD_NO; + } + ret = MHD_queue_response (connection, + MHD_HTTP_NOT_IMPLEMENTED, + response); + MHD_destroy_response (response); + return ret; + } + /* Fetch reply */ if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, - "mint-wire-sepa", - "SEPA_RESPONSE_FILE", - &sepa_wire_file)) + GNUNET_CONFIGURATION_get_value_filename (cfg, + "mint-wire-sepa", + "SEPA_RESPONSE_FILE", + &sepa_wire_file)) { return TMH_RESPONSE_reply_internal_error (connection, "SEPA_RESPONSE_FILE not configured"); -- cgit v1.2.3 From 16ed21afe071277d797b575a0d15fa29bd969c0b Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 20 Sep 2015 14:02:10 +0200 Subject: expanding test to cover multi-wire format scenarios (#3972) --- contrib/mint-template/config/mint-common.conf | 3 ++- src/mint-lib/mint_api_wire.c | 3 ++- .../test-mint-home/config/mint-common.conf | 8 +++---- src/mint-lib/test_mint_api.c | 27 ++++++++++++++-------- src/mint/taler-mint-httpd_wire.c | 5 ---- 5 files changed, 25 insertions(+), 21 deletions(-) (limited to 'src/mint-lib/mint_api_wire.c') diff --git a/contrib/mint-template/config/mint-common.conf b/contrib/mint-template/config/mint-common.conf index 958763b2..78a3310a 100644 --- a/contrib/mint-template/config/mint-common.conf +++ b/contrib/mint-template/config/mint-common.conf @@ -2,7 +2,8 @@ # Currency supported by the mint (can only be one) CURRENCY = EUR -# Wire format supported by the mint (currently only SEPA is implemented) +# Wire format supported by the mint, case-insensitive. +# Examples for formats include 'test' for testing and 'sepa' (for EU IBAN). WIREFORMAT = SEPA # HTTP port the mint listens to diff --git a/src/mint-lib/mint_api_wire.c b/src/mint-lib/mint_api_wire.c index f1bbb099..81506961 100644 --- a/src/mint-lib/mint_api_wire.c +++ b/src/mint-lib/mint_api_wire.c @@ -289,7 +289,8 @@ handle_wire_method_finished (void *cls, /* pass on successful reply */ wh->cb (wh->cb_cls, response_code, - NULL, + json_string_value (json_array_get (wh->methods, + wh->methods_off-1)), json); /* trigger request for the next /wire/method */ request_wire_method (wh); diff --git a/src/mint-lib/test-mint-home/config/mint-common.conf b/src/mint-lib/test-mint-home/config/mint-common.conf index eb2f7e90..f4bc2162 100644 --- a/src/mint-lib/test-mint-home/config/mint-common.conf +++ b/src/mint-lib/test-mint-home/config/mint-common.conf @@ -3,11 +3,9 @@ CURRENCY = EUR # Wire format supported by the mint -# We use 'test' for testing, in principle we should -# run tests for all supported wire formats... -# (we should first implement support for a mint running -# with multiple formats at the same time). -WIREFORMAT = test +# We use 'test' for testing of the actual +# coin operations, and 'sepa' to test SEPA-specific routines. +WIREFORMAT = test sepa # HTTP port the mint listens to PORT = 8081 diff --git a/src/mint-lib/test_mint_api.c b/src/mint-lib/test_mint_api.c index 6fb09909..7b96f657 100644 --- a/src/mint-lib/test_mint_api.c +++ b/src/mint-lib/test_mint_api.c @@ -33,9 +33,8 @@ /** * Is the configuration file is set to include wire format 'sepa'? - * Needs #3972 to be solved first. */ -#define WIRE_SEPA 0 +#define WIRE_SEPA 1 /** * Main execution context for the main loop. @@ -464,6 +463,11 @@ struct Command */ struct TALER_MINT_WireHandle *wh; + /** + * Format we expect to see, others will be *ignored*. + */ + const char *format; + } wire; } details; @@ -1038,10 +1042,6 @@ link_cb (void *cls, return; } /* check that the coins match */ - fprintf (stderr, - "Got %u coins\n", - num_coins); - for (i=0;idetails.wire.wh = NULL; } + else if ( (NULL != method) && + (0 != strcasecmp (method, + cmd->details.wire.format)) ) + { + /* not the method we care about, skip */ + return; + } if (cmd->expected_response_code != http_status) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -1994,13 +2001,15 @@ run (void *cls, { .oc = OC_WIRE, .label = "wire-test", /* /wire/test replies with a 302 redirect */ - .expected_response_code = MHD_HTTP_FOUND }, + .expected_response_code = MHD_HTTP_FOUND, + .details.wire.format = "test" }, #endif #if WIRE_SEPA - { .oc = OC_WIRE, + { .oc = OC_WIRE, .label = "wire-sepa", /* /wire/sepa replies with a 200 redirect */ - .expected_response_code = MHD_HTTP_OK }, + .expected_response_code = MHD_HTTP_OK, + .details.wire.format = "sepa" }, #endif /* *************** end of /wire testing ************** */ diff --git a/src/mint/taler-mint-httpd_wire.c b/src/mint/taler-mint-httpd_wire.c index 68dc1419..143d7c48 100644 --- a/src/mint/taler-mint-httpd_wire.c +++ b/src/mint/taler-mint-httpd_wire.c @@ -66,11 +66,6 @@ TMH_WIRE_handler_wire (struct TMH_RequestHandler *rh, TMH_KS_sign (&wsm.purpose, &pub, &sig); - /* 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. */ return TMH_RESPONSE_reply_json_pack (connection, MHD_HTTP_OK, "{s:o, s:o, s:o}", -- cgit v1.2.3