From cb55c1a3af9f56a6da38e5589e72df0b70d355b1 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 2 Apr 2018 14:24:45 +0200 Subject: Changing configuration structure to enable multiple accounts. This change enables using multiple wire plugins at the same time. Also, we now distinguish between the wire plugin (i.e. EBICS or taler_bank) and the wire method (i.e. SEPA or x-taler-bank) that the wire plugin is implementing. The "taler-bank" wire method was renamed from "test" to "x-taler-bank". This also changes the format of the /wire response of the exchange, as we now need to return multiple accounts. Note that wire fees are specified per wire method, not per wire account. taler-exchange-keyup now automatically signs all of the /wire responses in the location specified by the configuration. Account identification in wire plugins was changed to use payto://-URLs instead of method-specific JSON fields. Signing and validation of /wire responses was moved from each wire plugin to a generic validation method in libtalerutil (crypto) or libtalerjson (for JSON-formatted inputs). Convenience methods were added to generate JSON for wire accounts (salting, signing). Various section and option names were adjusted to streamline the configuration and make it more consistent overall. Documentation was updated as well. --- src/json/Makefile.am | 4 +- src/json/json_wire.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 src/json/json_wire.c (limited to 'src/json') diff --git a/src/json/Makefile.am b/src/json/Makefile.am index d26f731ac..4b40e94b4 100644 --- a/src/json/Makefile.am +++ b/src/json/Makefile.am @@ -11,12 +11,14 @@ lib_LTLIBRARIES = \ libtalerjson_la_SOURCES = \ json.c \ - json_helper.c + json_helper.c \ + json_wire.c libtalerjson_la_LDFLAGS = \ -version-info 1:0:1 \ -export-dynamic -no-undefined libtalerjson_la_LIBADD = \ -lgnunetjson \ + $(top_builddir)/src/wire/libtalerwire.la \ $(top_builddir)/src/util/libtalerutil.la \ -lgnunetutil \ -ljansson \ diff --git a/src/json/json_wire.c b/src/json/json_wire.c new file mode 100644 index 000000000..f0bd17578 --- /dev/null +++ b/src/json/json_wire.c @@ -0,0 +1,193 @@ +/* + This file is part of TALER + Copyright (C) 2018 Taler Systems SA + + 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, see +*/ +/** + * @file json/json_wire.c + * @brief helper functions to generate or check /wire replies + * @author Christian Grothoff + */ +#include "platform.h" +#include +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_wire_lib.h" + + +/** + * Compute the hash of the given wire details. The resulting + * hash is what is put into the contract. + * + * @param wire_s wire details to hash + * @param hc[out] set to the hash + * @return #GNUNET_OK on success, #GNUNET_SYSERR if @a wire_s is malformed + */ +int +TALER_JSON_wire_signature_hash (const json_t *wire_s, + struct GNUNET_HashCode *hc) +{ + const char *payto_url; + const char *salt; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_string ("url", &payto_url), + GNUNET_JSON_spec_string ("salt", &salt), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (wire_s, + spec, + NULL, NULL)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + TALER_wire_signature_hash (payto_url, + salt, + hc); + return GNUNET_OK; +} + + +/** + * Check the signature in @a wire_s. + * + * @param wire_s signed wire information of an exchange + * @param master_pub master public key of the exchange + * @return #GNUNET_OK if signature is valid + */ +int +TALER_JSON_wire_signature_check (const json_t *wire_s, + const struct TALER_MasterPublicKeyP *master_pub) +{ + const char *payto_url; + const char *salt; + struct TALER_MasterSignatureP master_sig; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_string ("url", &payto_url), + GNUNET_JSON_spec_string ("salt", &salt), + GNUNET_JSON_spec_fixed_auto ("master_sig", &master_sig), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (wire_s, + spec, + NULL, NULL)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + return TALER_wire_signature_check (payto_url, + salt, + master_pub, + &master_sig); +} + + +/** + * Create a signed wire statement for the given account. + * + * @param payto_url account specification + * @param master_priv private key to sign with, NULL to not sign + */ +json_t * +TALER_JSON_wire_signature_make (const char *payto_url, + const struct TALER_MasterPrivateKeyP *master_priv) +{ + struct TALER_MasterSignatureP master_sig; + struct GNUNET_HashCode salt; + char *salt_str; + json_t *ret; + + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, + &salt, + sizeof (salt)); + salt_str = GNUNET_STRINGS_data_to_string_alloc (&salt, + sizeof (salt)); + if (NULL != master_priv) + { + TALER_wire_signature_make (payto_url, + salt_str, + master_priv, + &master_sig); + ret = json_pack ("{s:s, s:s, s:o}", + "url", payto_url, + "salt", salt_str, + "master_sig", GNUNET_JSON_from_data_auto (&master_sig)); + } + else + { + ret = json_pack ("{s:s, s:s}", + "url", payto_url, + "salt", salt_str); + } + GNUNET_free (salt_str); + return ret; +} + + +/** + * Obtain the wire method associated with the given + * wire account details. @a wire_s must contain a payto://-URL + * under 'url'. + * + * @return NULL on error + */ +char * +TALER_JSON_wire_to_payto (const json_t *wire_s) +{ + json_t *payto_o; + const char *payto_str; + + payto_o = json_object_get (wire_s, + "url"); + if ( (NULL == payto_o) || + (NULL == (payto_str = json_string_value (payto_o))) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Fatally malformed wire record encountered: lacks payto://-url\n"); + return NULL; + } + return GNUNET_strdup (payto_str); +} + + +/** + * Obtain the wire method associated with the given + * wire account details. @a wire_s must contain a payto://-URL + * under 'url'. + * + * @return NULL on error + */ +char * +TALER_JSON_wire_to_method (const json_t *wire_s) +{ + json_t *payto_o; + const char *payto_str; + + payto_o = json_object_get (wire_s, + "url"); + if ( (NULL == payto_o) || + (NULL == (payto_str = json_string_value (payto_o))) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Fatally malformed wire record encountered: lacks payto://-url\n"); + return NULL; + } + return TALER_WIRE_payto_get_method (payto_str); +} + + +/* end of json_wire.c */ -- cgit v1.2.3