diff options
Diffstat (limited to 'src')
53 files changed, 878 insertions, 2517 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 37c902e65..6e0fb2049 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,7 +15,7 @@ if WALLET_ONLY SUBDIRS = include util else -SUBDIRS = include util $(PQ_DIR) $(BANK_LIB) wire exchangedb exchange exchange-tools +SUBDIRS = include util json $(PQ_DIR) $(BANK_LIB) wire exchangedb exchange exchange-tools if HAVE_LIBCURL SUBDIRS += exchange-lib else diff --git a/src/bank-lib/Makefile.am b/src/bank-lib/Makefile.am index 2f44adada..4cf3472ec 100644 --- a/src/bank-lib/Makefile.am +++ b/src/bank-lib/Makefile.am @@ -15,10 +15,11 @@ libtalerbank_la_LDFLAGS = \ libtalerbank_la_SOURCES = \ bank_api_context.c bank_api_context.h \ - bank_api_json.c bank_api_json.h \ bank_api_admin.c libtalerbank_la_LIBADD = \ + $(top_builddir)/src/json/libtalerjson.la \ + -lgnunetjson \ -lgnunetutil \ -ljansson \ $(XLIB) diff --git a/src/bank-lib/bank_api_admin.c b/src/bank-lib/bank_api_admin.c index 5deb4aa72..443f24a8a 100644 --- a/src/bank-lib/bank_api_admin.c +++ b/src/bank-lib/bank_api_admin.c @@ -24,8 +24,9 @@ #include <jansson.h> #include <microhttpd.h> /* just for HTTP status codes */ #include <gnunet/gnunet_util_lib.h> +#include <gnunet/gnunet_json_lib.h> #include "taler_bank_service.h" -#include "bank_api_json.h" +#include "taler_json_lib.h" #include "bank_api_context.h" #include "taler_signatures.h" @@ -173,9 +174,9 @@ TALER_BANK_admin_add_incoming (struct TALER_BANK_Context *bank, admin_obj = json_pack ("{s:o, s:o," " s:I, s:I}", - "wtid", TALER_json_from_data (wtid, + "wtid", GNUNET_JSON_from_data (wtid, sizeof (*wtid)), - "amount", TALER_json_from_amount (amount), + "amount", TALER_JSON_from_amount (amount), "debit_account", (json_int_t) debit_account_no, "credit_account", (json_int_t) credit_account_no); aai = GNUNET_new (struct TALER_BANK_AdminAddIncomingHandle); diff --git a/src/bank-lib/bank_api_context.h b/src/bank-lib/bank_api_context.h index 552cbe440..1f21cb8d2 100644 --- a/src/bank-lib/bank_api_context.h +++ b/src/bank-lib/bank_api_context.h @@ -21,6 +21,7 @@ * @author Christian Grothoff */ #include "platform.h" +#include <jansson.h> #include <curl/curl.h> #include <gnunet/gnunet_util_lib.h> #include "taler_bank_service.h" diff --git a/src/bank-lib/bank_api_json.c b/src/bank-lib/bank_api_json.c deleted file mode 100644 index 2a09e5272..000000000 --- a/src/bank-lib/bank_api_json.c +++ /dev/null @@ -1,525 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014, 2015 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 <http://www.gnu.org/licenses/> -*/ -/** - * @file bank-lib/bank_api_json.c - * @brief functions to parse incoming requests (JSON snippets) - * @author Florian Dold - * @author Benedikt Mueller - * @author Christian Grothoff - */ -#include "platform.h" -#include "bank_api_json.h" - -/** - * Navigate and parse data in a JSON tree. - * - * @param root the JSON node to start the navigation at. - * @param spec parse specification array - * @return offset in @a spec where parsing failed, -1 on success (!) - */ -static int -parse_json (json_t *root, - struct BAJ_Specification *spec) -{ - int i; - json_t *pos; /* what's our current position? */ - - pos = root; - for (i=0;BAJ_CMD_END != spec[i].cmd;i++) - { - pos = json_object_get (root, - spec[i].field); - if (NULL == pos) - { - GNUNET_break_op (0); - return i; - } - switch (spec[i].cmd) - { - case BAJ_CMD_END: - GNUNET_assert (0); - return i; - case BAJ_CMD_AMOUNT: - if (GNUNET_OK != - TALER_json_to_amount (pos, - spec[i].details.amount)) - { - GNUNET_break_op (0); - return i; - } - break; - case BAJ_CMD_TIME_ABSOLUTE: - if (GNUNET_OK != - TALER_json_to_abs (pos, - spec[i].details.abs_time)) - { - GNUNET_break_op (0); - return i; - } - break; - - case BAJ_CMD_STRING: - { - const char *str; - - str = json_string_value (pos); - if (NULL == str) - { - GNUNET_break_op (0); - return i; - } - *spec[i].details.strptr = str; - } - break; - - case BAJ_CMD_BINARY_FIXED: - { - const char *str; - int res; - - str = json_string_value (pos); - if (NULL == str) - { - GNUNET_break_op (0); - return i; - } - res = GNUNET_STRINGS_string_to_data (str, strlen (str), - spec[i].details.fixed_data.dest, - spec[i].details.fixed_data.dest_size); - if (GNUNET_OK != res) - { - GNUNET_break_op (0); - return i; - } - } - break; - - case BAJ_CMD_BINARY_VARIABLE: - { - const char *str; - size_t size; - void *data; - int res; - - str = json_string_value (pos); - if (NULL == str) - { - GNUNET_break_op (0); - return i; - } - size = (strlen (str) * 5) / 8; - if (size >= 1024) - { - GNUNET_break_op (0); - return i; - } - data = GNUNET_malloc (size); - res = GNUNET_STRINGS_string_to_data (str, - strlen (str), - data, - size); - if (GNUNET_OK != res) - { - GNUNET_break_op (0); - GNUNET_free (data); - return i; - } - *spec[i].details.variable_data.dest_p = data; - *spec[i].details.variable_data.dest_size_p = size; - } - break; - - case BAJ_CMD_RSA_PUBLIC_KEY: - { - size_t size; - const char *str; - int res; - void *buf; - - str = json_string_value (pos); - if (NULL == str) - { - GNUNET_break_op (0); - return i; - } - size = (strlen (str) * 5) / 8; - buf = GNUNET_malloc (size); - res = GNUNET_STRINGS_string_to_data (str, - strlen (str), - buf, - size); - if (GNUNET_OK != res) - { - GNUNET_free (buf); - GNUNET_break_op (0); - return i; - } - *spec[i].details.rsa_public_key - = GNUNET_CRYPTO_rsa_public_key_decode (buf, - size); - GNUNET_free (buf); - if (NULL == spec[i].details.rsa_public_key) - { - GNUNET_break_op (0); - return i; - } - } - break; - - case BAJ_CMD_RSA_SIGNATURE: - { - size_t size; - const char *str; - int res; - void *buf; - - str = json_string_value (pos); - if (NULL == str) - { - GNUNET_break_op (0); - return i; - } - size = (strlen (str) * 5) / 8; - buf = GNUNET_malloc (size); - res = GNUNET_STRINGS_string_to_data (str, - strlen (str), - buf, - size); - if (GNUNET_OK != res) - { - GNUNET_free (buf); - GNUNET_break_op (0); - return i; - } - *spec[i].details.rsa_signature - = GNUNET_CRYPTO_rsa_signature_decode (buf, - size); - GNUNET_free (buf); - if (NULL == spec[i].details.rsa_signature) - return i; - } - break; - - case BAJ_CMD_UINT16: - { - json_int_t val; - - if (! json_is_integer (pos)) - { - GNUNET_break_op (0); - return i; - } - val = json_integer_value (pos); - if ( (0 > val) || (val > UINT16_MAX) ) - { - GNUNET_break_op (0); - return i; - } - *spec[i].details.u16 = (uint16_t) val; - } - break; - - case BAJ_CMD_UINT64: - { - json_int_t val; - - if (! json_is_integer (pos)) - { - GNUNET_break_op (0); - return i; - } - val = json_integer_value (pos); - *spec[i].details.u64 = (uint64_t) val; - } - break; - - case BAJ_CMD_JSON_OBJECT: - { - if (! (json_is_object (pos) || json_is_array (pos)) ) - { - GNUNET_break_op (0); - return i; - } - json_incref (pos); - *spec[i].details.obj = pos; - } - break; - - default: - GNUNET_break (0); - return i; - } - } - return -1; /* all OK! */ -} - - -/** - * Free all elements allocated during a - * #BAJ_parse_json() operation. - * - * @param spec specification of the parse operation - * @param end number of elements in @a spec to process - */ -static void -parse_free (struct BAJ_Specification *spec, - int end) -{ - int i; - - for (i=0;i<end;i++) - { - switch (spec[i].cmd) - { - case BAJ_CMD_END: - GNUNET_assert (0); - return; - case BAJ_CMD_AMOUNT: - break; - case BAJ_CMD_TIME_ABSOLUTE: - break; - case BAJ_CMD_BINARY_FIXED: - break; - case BAJ_CMD_STRING: - break; - case BAJ_CMD_BINARY_VARIABLE: - GNUNET_free (*spec[i].details.variable_data.dest_p); - *spec[i].details.variable_data.dest_p = NULL; - *spec[i].details.variable_data.dest_size_p = 0; - break; - case BAJ_CMD_RSA_PUBLIC_KEY: - GNUNET_CRYPTO_rsa_public_key_free (*spec[i].details.rsa_public_key); - *spec[i].details.rsa_public_key = NULL; - break; - case BAJ_CMD_RSA_SIGNATURE: - GNUNET_CRYPTO_rsa_signature_free (*spec[i].details.rsa_signature); - *spec[i].details.rsa_signature = NULL; - break; - case BAJ_CMD_JSON_OBJECT: - json_decref (*spec[i].details.obj); - *spec[i].details.obj = NULL; - break; - default: - GNUNET_break (0); - break; - } - } -} - - -/** - * Navigate and parse data in a JSON tree. - * - * @param root the JSON node to start the navigation at. - * @param spec parse specification array - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - */ -int -BAJ_parse_json (const json_t *root, - struct BAJ_Specification *spec) -{ - int ret; - - ret = parse_json ((json_t *) root, - spec); - if (-1 == ret) - return GNUNET_OK; - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "JSON field `%s` (%d) had unexpected value\n", - spec[ret].field, - ret); - parse_free (spec, ret); - return GNUNET_SYSERR; -} - - -/** - * Free all elements allocated during a - * #BAJ_parse_json() operation. - * - * @param spec specification of the parse operation - */ -void -BAJ_parse_free (struct BAJ_Specification *spec) -{ - int i; - - for (i=0;BAJ_CMD_END != spec[i].cmd;i++) ; - parse_free (spec, i); -} - - -/** - * The expected field stores a string. - * - * @param name name of the JSON field - * @param strptr where to store a pointer to the field - */ -struct BAJ_Specification -BAJ_spec_string (const char *name, - const char **strptr) -{ - struct BAJ_Specification ret = - { - .cmd = BAJ_CMD_STRING, - .field = name, - .details.strptr = strptr - }; - return ret; -} - - -/** - * Specification for parsing an absolute time value. - * - * @param name name of the JSON field - * @param at where to store the absolute time found under @a name - */ -struct BAJ_Specification -BAJ_spec_absolute_time (const char *name, - struct GNUNET_TIME_Absolute *at) -{ - struct BAJ_Specification ret = - { - .cmd = BAJ_CMD_TIME_ABSOLUTE, - .field = name, - .details.abs_time = at - }; - return ret; -} - - -/** - * Specification for parsing an amount value. - * - * @param name name of the JSON field - * @param amount where to store the amount found under @a name - */ -struct BAJ_Specification -BAJ_spec_amount (const char *name, - struct TALER_Amount *amount) -{ - struct BAJ_Specification ret = - { - .cmd = BAJ_CMD_AMOUNT, - .field = name, - .details.amount = amount - }; - return ret; -} - - -/** - * 16-bit integer. - * - * @param name name of the JSON field - * @param[out] u16 where to store the integer found under @a name - */ -struct BAJ_Specification -BAJ_spec_uint16 (const char *name, - uint16_t *u16) -{ - struct BAJ_Specification ret = - { - .cmd = BAJ_CMD_UINT16, - .field = name, - .details.u16 = u16 - }; - return ret; -} - - -/** - * 64-bit integer. - * - * @param name name of the JSON field - * @param[out] u64 where to store the integer found under @a name - */ -struct BAJ_Specification -BAJ_spec_uint64 (const char *name, - uint64_t *u64) -{ - struct BAJ_Specification ret = - { - .cmd = BAJ_CMD_UINT64, - .field = name, - .details.u64 = u64 - }; - return ret; -} - - -/** - * JSON object. - * - * @param name name of the JSON field - * @param[out] jsonp where to store the JSON found under @a name - */ -struct BAJ_Specification -BAJ_spec_json (const char *name, - json_t **jsonp) -{ - struct BAJ_Specification ret = - { - .cmd = BAJ_CMD_JSON_OBJECT, - .field = name, - .details.obj = jsonp - }; - return ret; -} - - -/** - * Specification for parsing an RSA public key. - * - * @param name name of the JSON field - * @param pk where to store the RSA key found under @a name - */ -struct BAJ_Specification -BAJ_spec_rsa_public_key (const char *name, - struct GNUNET_CRYPTO_rsa_PublicKey **pk) -{ - struct BAJ_Specification ret = - { - .cmd = BAJ_CMD_RSA_PUBLIC_KEY, - .field = name, - .details.rsa_public_key = pk - }; - return ret; -} - - -/** - * Specification for parsing an RSA signature. - * - * @param name name of the JSON field - * @param sig where to store the RSA signature found under @a name - */ -struct BAJ_Specification -BAJ_spec_rsa_signature (const char *name, - struct GNUNET_CRYPTO_rsa_Signature **sig) -{ - struct BAJ_Specification ret = - { - .cmd = BAJ_CMD_RSA_SIGNATURE, - .field = name, - .details.rsa_signature = sig - }; - return ret; -} - - -/* end of bank_api_json.c */ diff --git a/src/bank-lib/bank_api_json.h b/src/bank-lib/bank_api_json.h deleted file mode 100644 index 92fe0b1d4..000000000 --- a/src/bank-lib/bank_api_json.h +++ /dev/null @@ -1,352 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014, 2015 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 <http://www.gnu.org/licenses/> -*/ -/** - * @file exchange-lib/exchange_api_json.h - * @brief functions to parse incoming requests (JSON snippets) - * @author Florian Dold - * @author Benedikt Mueller - * @author Christian Grothoff - */ -#include "platform.h" -#include <gnunet/gnunet_util_lib.h> -#include "taler_util.h" -#include <jansson.h> - - -/** - * Enumeration with the various commands for the - * #BAJ_parse_json interpreter. - */ -enum BAJ_Command -{ - - /** - * End of command list. - */ - BAJ_CMD_END, - - /** - * Parse amount at current position. - */ - BAJ_CMD_AMOUNT, - - /** - * Parse absolute time at current position. - */ - BAJ_CMD_TIME_ABSOLUTE, - - /** - * Parse fixed binary value at current position. - */ - BAJ_CMD_BINARY_FIXED, - - /** - * Parse variable-size binary value at current position. - */ - BAJ_CMD_BINARY_VARIABLE, - - /** - * Parse RSA public key at current position. - */ - BAJ_CMD_RSA_PUBLIC_KEY, - - /** - * Parse RSA signature at current position. - */ - BAJ_CMD_RSA_SIGNATURE, - - /** - * Parse `const char *` JSON string at current position. - */ - BAJ_CMD_STRING, - - /** - * Parse `uint16_t` integer at the current position. - */ - BAJ_CMD_UINT16, - - /** - * Parse `uint64_t` integer at the current position. - */ - BAJ_CMD_UINT64, - - /** - * Parse JSON object at the current position. - */ - BAJ_CMD_JSON_OBJECT, - - /** - * Parse ??? at current position. - */ - BAJ_CMD_C - -}; - - -/** - * @brief Entry in parser specification for #BAJ_parse_json. - */ -struct BAJ_Specification -{ - - /** - * Command to execute. - */ - enum BAJ_Command cmd; - - /** - * Name of the field to access. - */ - const char *field; - - /** - * Further details for the command. - */ - union { - - /** - * Where to store amount for #BAJ_CMD_AMOUNT. - */ - struct TALER_Amount *amount; - - /** - * Where to store time, for #BAJ_CMD_TIME_ABSOLUTE. - */ - struct GNUNET_TIME_Absolute *abs_time; - - /** - * Where to write binary data, for #BAJ_CMD_BINARY_FIXED. - */ - struct { - /** - * Where to write the data. - */ - void *dest; - - /** - * How many bytes to write to @e dest. - */ - size_t dest_size; - - } fixed_data; - - /** - * Where to write binary data, for #BAJ_CMD_BINARY_VARIABLE. - */ - struct { - /** - * Where to store the pointer with the data (is allocated). - */ - void **dest_p; - - /** - * Where to store the number of bytes allocated at `*dest`. - */ - size_t *dest_size_p; - - } variable_data; - - /** - * Where to store the RSA public key for #BAJ_CMD_RSA_PUBLIC_KEY - */ - struct GNUNET_CRYPTO_rsa_PublicKey **rsa_public_key; - - /** - * Where to store the RSA signature for #BAJ_CMD_RSA_SIGNATURE - */ - struct GNUNET_CRYPTO_rsa_Signature **rsa_signature; - - /** - * Details for #BAJ_CMD_EDDSA_SIGNATURE - */ - struct { - - /** - * Where to store the purpose. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose **purpose_p; - - /** - * Key to verify the signature against. - */ - const struct GNUNET_CRYPTO_EddsaPublicKey *pub_key; - - } eddsa_signature; - - /** - * Where to store a pointer to the string. - */ - const char **strptr; - - /** - * Where to store 16-bit integer. - */ - uint16_t *u16; - - /** - * Where to store 64-bit integer. - */ - uint64_t *u64; - - /** - * Where to store a JSON object. - */ - json_t **obj; - - } details; - -}; - - -/** - * Navigate and parse data in a JSON tree. - * - * @param root the JSON node to start the navigation at. - * @param spec parse specification array - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - */ -int -BAJ_parse_json (const json_t *root, - struct BAJ_Specification *spec); - - -/** - * Free all elements allocated during a - * #BAJ_parse_json() operation. - * - * @param spec specification of the parse operation - */ -void -BAJ_parse_free (struct BAJ_Specification *spec); - - -/** - * End of a parser specification. - */ -#define BAJ_spec_end { .cmd = BAJ_CMD_END } - -/** - * Fixed size object (in network byte order, encoded using Crockford - * Base32hex encoding). - * - * @param name name of the JSON field - * @param obj pointer where to write the data (type of `*obj` will determine size) - */ -#define BAJ_spec_fixed_auto(name,obj) { .cmd = BAJ_CMD_BINARY_FIXED, .field = name, .details.fixed_data.dest = obj, .details.fixed_data.dest_size = sizeof (*obj) } - - -/** - * Variable size object (in network byte order, encoded using Crockford - * Base32hex encoding). - * - * @param name name of the JSON field - * @param obj pointer where to write the data (a `void **`) - * @param size where to store the number of bytes allocated for @a obj (of type `size_t *` - */ -#define BAJ_spec_varsize(name,obj,size) { .cmd = BAJ_CMD_BINARY_VARIABLE, .field = name, .details.variable_data.dest_p = obj, .details.variable_data.dest_size_p = size } - - -/** - * The expected field stores a string. - * - * @param name name of the JSON field - * @param strptr where to store a pointer to the field - */ -struct BAJ_Specification -BAJ_spec_string (const char *name, - const char **strptr); - - -/** - * Absolute time. - * - * @param name name of the JSON field - * @param[out] at where to store the absolute time found under @a name - */ -struct BAJ_Specification -BAJ_spec_absolute_time (const char *name, - struct GNUNET_TIME_Absolute *at); - - -/** - * 16-bit integer. - * - * @param name name of the JSON field - * @param[out] u16 where to store the integer found under @a name - */ -struct BAJ_Specification -BAJ_spec_uint16 (const char *name, - uint16_t *u16); - - -/** - * 64-bit integer. - * - * @param name name of the JSON field - * @param[out] u64 where to store the integer found under @a name - */ -struct BAJ_Specification -BAJ_spec_uint64 (const char *name, - uint64_t *u64); - - -/** - * JSON object. - * - * @param name name of the JSON field - * @param[out] jsonp where to store the JSON found under @a name - */ -struct BAJ_Specification -BAJ_spec_json (const char *name, - json_t **jsonp); - - -/** - * Specification for parsing an amount value. - * - * @param name name of the JSON field - * @param amount where to store the amount under @a name - */ -struct BAJ_Specification -BAJ_spec_amount (const char *name, - struct TALER_Amount *amount); - - -/** - * Specification for parsing an RSA public key. - * - * @param name name of the JSON field - * @param pk where to store the RSA key found under @a name - */ -struct BAJ_Specification -BAJ_spec_rsa_public_key (const char *name, - struct GNUNET_CRYPTO_rsa_PublicKey **pk); - - -/** - * Specification for parsing an RSA signature. - * - * @param name name of the JSON field - * @param sig where to store the RSA signature found under @a name - */ -struct BAJ_Specification -BAJ_spec_rsa_signature (const char *name, - struct GNUNET_CRYPTO_rsa_Signature **sig); - - - - -/* end of exchange_api_json.h */ diff --git a/src/exchange-lib/Makefile.am b/src/exchange-lib/Makefile.am index 6d5e842be..a043e8601 100644 --- a/src/exchange-lib/Makefile.am +++ b/src/exchange-lib/Makefile.am @@ -28,6 +28,9 @@ libtalerexchange_la_SOURCES = \ exchange_api_wire_deposits.c libtalerexchange_la_LIBADD = \ + $(top_builddir)/src/json/libtalerjson.la \ + $(top_builddir)/src/util/libtalerutil.la \ + -lgnunetjson \ -lgnunetutil \ -ljansson \ $(XLIB) @@ -51,6 +54,7 @@ test_exchange_api_SOURCES = \ test_exchange_api_LDADD = \ libtalerexchange.la \ $(LIBGCRYPT_LIBS) \ + $(top_builddir)/src/json/libtalerjson.la \ $(top_builddir)/src/util/libtalerutil.la \ -lgnunetutil \ -ljansson diff --git a/src/exchange-lib/exchange_api_admin.c b/src/exchange-lib/exchange_api_admin.c index 3dcbb80e9..4ed761fb2 100644 --- a/src/exchange-lib/exchange_api_admin.c +++ b/src/exchange-lib/exchange_api_admin.c @@ -24,6 +24,8 @@ #include <jansson.h> #include <microhttpd.h> /* just for HTTP status codes */ #include <gnunet/gnunet_util_lib.h> +#include <gnunet/gnunet_json_lib.h> +#include "taler_json_lib.h" #include "taler_exchange_service.h" #include "exchange_api_json.h" #include "exchange_api_context.h" @@ -174,7 +176,7 @@ TALER_EXCHANGE_admin_add_incoming (struct TALER_EXCHANGE_Handle *exchange, CURL *eh; GNUNET_assert (GNUNET_OK == - TALER_round_abs_time (&execution_date)); + GNUNET_TIME_round_abs (&execution_date)); if (GNUNET_YES != MAH_handle_is_ready (exchange)) { @@ -183,10 +185,10 @@ TALER_EXCHANGE_admin_add_incoming (struct TALER_EXCHANGE_Handle *exchange, } admin_obj = json_pack ("{s:o, s:o," /* reserve_pub/amount */ " s:o, s:O}", /* execution_Date/wire */ - "reserve_pub", TALER_json_from_data (reserve_pub, + "reserve_pub", GNUNET_JSON_from_data (reserve_pub, sizeof (*reserve_pub)), - "amount", TALER_json_from_amount (amount), - "execution_date", TALER_json_from_abs (execution_date), + "amount", TALER_JSON_from_amount (amount), + "execution_date", GNUNET_JSON_from_time_abs (execution_date), "wire", wire); aai = GNUNET_new (struct TALER_EXCHANGE_AdminAddIncomingHandle); aai->exchange = exchange; diff --git a/src/exchange-lib/exchange_api_deposit.c b/src/exchange-lib/exchange_api_deposit.c index deba4877d..ef7a59e69 100644 --- a/src/exchange-lib/exchange_api_deposit.c +++ b/src/exchange-lib/exchange_api_deposit.c @@ -25,6 +25,8 @@ #include <jansson.h> #include <microhttpd.h> /* just for HTTP status codes */ #include <gnunet/gnunet_util_lib.h> +#include <gnunet/gnunet_json_lib.h> +#include "taler_json_lib.h" #include "taler_exchange_service.h" #include "exchange_api_common.h" #include "exchange_api_json.h" @@ -411,7 +413,7 @@ TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle *exchange, struct GNUNET_HashCode h_wire; struct TALER_Amount amount_without_fee; - (void) TALER_round_abs_time (&wire_deadline); + (void) GNUNET_TIME_round_abs (&wire_deadline); if (GNUNET_YES != MAH_handle_is_ready (exchange)) { @@ -420,7 +422,7 @@ TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle *exchange, } /* initialize h_wire */ if (GNUNET_OK != - TALER_hash_json (wire_details, + TALER_JSON_hash (wire_details, &h_wire)) { GNUNET_break (0); @@ -468,23 +470,23 @@ TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle *exchange, " s:I, s:o," /* transaction id, merchant_pub */ " s:o, s:o," /* refund_deadline, wire_deadline */ " s:o}", /* coin_sig */ - "f", TALER_json_from_amount (amount), + "f", TALER_JSON_from_amount (amount), "wire", wire_details, - "H_wire", TALER_json_from_data (&h_wire, + "H_wire", GNUNET_JSON_from_data (&h_wire, sizeof (h_wire)), - "H_contract", TALER_json_from_data (h_contract, + "H_contract", GNUNET_JSON_from_data (h_contract, sizeof (struct GNUNET_HashCode)), - "coin_pub", TALER_json_from_data (coin_pub, + "coin_pub", GNUNET_JSON_from_data (coin_pub, sizeof (*coin_pub)), - "denom_pub", TALER_json_from_rsa_public_key (denom_pub->rsa_public_key), - "ub_sig", TALER_json_from_rsa_signature (denom_sig->rsa_signature), - "timestamp", TALER_json_from_abs (timestamp), + "denom_pub", GNUNET_JSON_from_rsa_public_key (denom_pub->rsa_public_key), + "ub_sig", GNUNET_JSON_from_rsa_signature (denom_sig->rsa_signature), + "timestamp", GNUNET_JSON_from_time_abs (timestamp), "transaction_id", (json_int_t) transaction_id, - "merchant_pub", TALER_json_from_data (merchant_pub, + "merchant_pub", GNUNET_JSON_from_data (merchant_pub, sizeof (*merchant_pub)), - "refund_deadline", TALER_json_from_abs (refund_deadline), - "edate", TALER_json_from_abs (wire_deadline), - "coin_sig", TALER_json_from_data (coin_sig, + "refund_deadline", GNUNET_JSON_from_time_abs (refund_deadline), + "edate", GNUNET_JSON_from_time_abs (wire_deadline), + "coin_sig", GNUNET_JSON_from_data (coin_sig, sizeof (*coin_sig)) ); diff --git a/src/exchange-lib/exchange_api_deposit_wtid.c b/src/exchange-lib/exchange_api_deposit_wtid.c index 83beb03ae..f3b5d2c0d 100644 --- a/src/exchange-lib/exchange_api_deposit_wtid.c +++ b/src/exchange-lib/exchange_api_deposit_wtid.c @@ -24,6 +24,7 @@ #include <jansson.h> #include <microhttpd.h> /* just for HTTP status codes */ #include <gnunet/gnunet_util_lib.h> +#include <gnunet/gnunet_json_lib.h> #include "taler_exchange_service.h" #include "exchange_api_common.h" #include "exchange_api_json.h" @@ -296,16 +297,16 @@ TALER_EXCHANGE_deposit_wtid (struct TALER_EXCHANGE_Handle *exchange, deposit_wtid_obj = json_pack ("{s:o, s:o," /* H_wire, H_contract */ " s:o, s:I," /* coin_pub, transaction_id */ " s:o, s:o}", /* merchant_pub, merchant_sig */ - "H_wire", TALER_json_from_data (h_wire, + "H_wire", GNUNET_JSON_from_data (h_wire, sizeof (struct GNUNET_HashCode)), - "H_contract", TALER_json_from_data (h_contract, + "H_contract", GNUNET_JSON_from_data (h_contract, sizeof (struct GNUNET_HashCode)), - "coin_pub", TALER_json_from_data (coin_pub, + "coin_pub", GNUNET_JSON_from_data (coin_pub, sizeof (*coin_pub)), "transaction_id", (json_int_t) transaction_id, - "merchant_pub", TALER_json_from_data (&dtp.merchant, + "merchant_pub", GNUNET_JSON_from_data (&dtp.merchant, sizeof (struct TALER_MerchantPublicKeyP)), - "merchant_sig", TALER_json_from_data (&merchant_sig, + "merchant_sig", GNUNET_JSON_from_data (&merchant_sig, sizeof (merchant_sig))); dwh = GNUNET_new (struct TALER_EXCHANGE_DepositWtidHandle); diff --git a/src/exchange-lib/exchange_api_json.c b/src/exchange-lib/exchange_api_json.c index d91feba0e..d6c54be5b 100644 --- a/src/exchange-lib/exchange_api_json.c +++ b/src/exchange-lib/exchange_api_json.c @@ -22,6 +22,7 @@ */ #include "platform.h" #include "exchange_api_json.h" +#include "taler_json_lib.h" /** * Navigate and parse data in a JSON tree. @@ -53,24 +54,39 @@ parse_json (json_t *root, GNUNET_assert (0); return i; case MAJ_CMD_AMOUNT: - if (GNUNET_OK != - TALER_json_to_amount (pos, - spec[i].details.amount)) { - GNUNET_break_op (0); - return i; + struct GNUNET_JSON_Specification nspec[] = { + TALER_JSON_spec_amount (NULL, spec[i].details.amount), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (pos, + nspec, + NULL, NULL)) + { + GNUNET_break_op (0); + return i; + } + break; } - break; case MAJ_CMD_TIME_ABSOLUTE: - if (GNUNET_OK != - TALER_json_to_abs (pos, - spec[i].details.abs_time)) { - GNUNET_break_op (0); - return i; + struct GNUNET_JSON_Specification nspec[] = { + GNUNET_JSON_spec_absolute_time (NULL, spec[i].details.abs_time), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (pos, + nspec, + NULL, NULL)) + { + GNUNET_break_op (0); + return i; + } + break; } - break; - case MAJ_CMD_STRING: { const char *str; diff --git a/src/exchange-lib/exchange_api_refresh.c b/src/exchange-lib/exchange_api_refresh.c index 03d59ea3b..bcec13544 100644 --- a/src/exchange-lib/exchange_api_refresh.c +++ b/src/exchange-lib/exchange_api_refresh.c @@ -24,6 +24,8 @@ #include <jansson.h> #include <microhttpd.h> /* just for HTTP status codes */ #include <gnunet/gnunet_util_lib.h> +#include <gnunet/gnunet_json_lib.h> +#include "taler_json_lib.h" #include "taler_exchange_service.h" #include "exchange_api_common.h" #include "exchange_api_json.h" @@ -1373,17 +1375,17 @@ melted_coin_to_json (const struct GNUNET_HashCode *melt_session_hash, &confirm_sig.eddsa_signature); return json_pack ("{s:o, s:o, s:o, s:o, s:o}", "coin_pub", - TALER_json_from_data (&melt.coin_pub, + GNUNET_JSON_from_data (&melt.coin_pub, sizeof (melt.coin_pub)), "denom_pub", - TALER_json_from_rsa_public_key (mc->pub_key.rsa_public_key), + GNUNET_JSON_from_rsa_public_key (mc->pub_key.rsa_public_key), "denom_sig", - TALER_json_from_rsa_signature (mc->sig.rsa_signature), + GNUNET_JSON_from_rsa_signature (mc->sig.rsa_signature), "confirm_sig", - TALER_json_from_data (&confirm_sig, + GNUNET_JSON_from_data (&confirm_sig, sizeof (confirm_sig)), "value_with_fee", - TALER_json_from_amount (&mc->melt_amount_with_fee)); + TALER_JSON_from_amount (&mc->melt_amount_with_fee)); } @@ -1472,7 +1474,7 @@ TALER_EXCHANGE_refresh_melt (struct TALER_EXCHANGE_Handle *exchange, GNUNET_CRYPTO_ecdhe_key_get_public (&mc->transfer_priv[j].ecdhe_priv, &transfer_pub.ecdhe_pub); json_array_append (tmp, - TALER_json_from_data (&transfer_pub, + GNUNET_JSON_from_data (&transfer_pub, sizeof (transfer_pub))); } json_array_append (transfer_pubs, @@ -1497,7 +1499,7 @@ TALER_EXCHANGE_refresh_melt (struct TALER_EXCHANGE_Handle *exchange, &trans_sec, &els)); json_array_append (tmp, - TALER_json_from_data (&els, + GNUNET_JSON_from_data (&els, sizeof (els))); } json_array_append (secret_encs, @@ -1508,7 +1510,7 @@ TALER_EXCHANGE_refresh_melt (struct TALER_EXCHANGE_Handle *exchange, for (i=0;i<md->num_fresh_coins;i++) { json_array_append (new_denoms, - TALER_json_from_rsa_public_key + GNUNET_JSON_from_rsa_public_key (md->fresh_pks[i].rsa_public_key)); } @@ -1533,7 +1535,7 @@ TALER_EXCHANGE_refresh_melt (struct TALER_EXCHANGE_Handle *exchange, &buf_len); GNUNET_assert (NULL != buf); json_array_append (tmp, - TALER_json_from_data (buf, + GNUNET_JSON_from_data (buf, buf_len)); GNUNET_free (buf); GNUNET_free (rle); @@ -1564,7 +1566,7 @@ TALER_EXCHANGE_refresh_melt (struct TALER_EXCHANGE_Handle *exchange, md->fresh_pks[i].rsa_public_key, &coin_ev); json_array_append (tmp, - TALER_json_from_data (coin_ev, + GNUNET_JSON_from_data (coin_ev, coin_ev_size)); GNUNET_free (coin_ev); } @@ -1975,7 +1977,7 @@ TALER_EXCHANGE_refresh_reveal (struct TALER_EXCHANGE_Handle *exchange, const struct MeltedCoin *mc = &md->melted_coins[i]; json_array_append (tmp, - TALER_json_from_data (&mc->transfer_priv[j], + GNUNET_JSON_from_data (&mc->transfer_priv[j], sizeof (struct TALER_TransferPrivateKeyP))); } json_array_append (transfer_privs, @@ -1985,7 +1987,7 @@ TALER_EXCHANGE_refresh_reveal (struct TALER_EXCHANGE_Handle *exchange, /* build main JSON request */ reveal_obj = json_pack ("{s:o, s:o}", "session_hash", - TALER_json_from_data (&md->melt_session_hash, + GNUNET_JSON_from_data (&md->melt_session_hash, sizeof (struct GNUNET_HashCode)), "transfer_privs", transfer_privs); diff --git a/src/exchange-lib/exchange_api_reserve.c b/src/exchange-lib/exchange_api_reserve.c index e694b8d95..1237f7cbe 100644 --- a/src/exchange-lib/exchange_api_reserve.c +++ b/src/exchange-lib/exchange_api_reserve.c @@ -24,6 +24,7 @@ #include <jansson.h> #include <microhttpd.h> /* just for HTTP status codes */ #include <gnunet/gnunet_util_lib.h> +#include <gnunet/gnunet_json_lib.h> #include "taler_exchange_service.h" #include "exchange_api_json.h" #include "exchange_api_context.h" @@ -859,12 +860,12 @@ TALER_EXCHANGE_reserve_withdraw (struct TALER_EXCHANGE_Handle *exchange, &reserve_sig.eddsa_signature)); withdraw_obj = json_pack ("{s:o, s:o," /* denom_pub and coin_ev */ " s:o, s:o}",/* reserve_pub and reserve_sig */ - "denom_pub", TALER_json_from_rsa_public_key (pk->key.rsa_public_key), - "coin_ev", TALER_json_from_data (coin_ev, + "denom_pub", GNUNET_JSON_from_rsa_public_key (pk->key.rsa_public_key), + "coin_ev", GNUNET_JSON_from_data (coin_ev, coin_ev_size), - "reserve_pub", TALER_json_from_data (&wsh->reserve_pub, + "reserve_pub", GNUNET_JSON_from_data (&wsh->reserve_pub, sizeof (struct TALER_ReservePublicKeyP)), - "reserve_sig", TALER_json_from_data (&reserve_sig, + "reserve_sig", GNUNET_JSON_from_data (&reserve_sig, sizeof (reserve_sig))); GNUNET_free (coin_ev); diff --git a/src/exchange-lib/exchange_api_wire.c b/src/exchange-lib/exchange_api_wire.c index f01c5000b..35c443ff5 100644 --- a/src/exchange-lib/exchange_api_wire.c +++ b/src/exchange-lib/exchange_api_wire.c @@ -25,11 +25,11 @@ #include <microhttpd.h> /* just for HTTP status codes */ #include <gnunet/gnunet_util_lib.h> #include "taler_exchange_service.h" +#include "taler_wire_plugin.h" #include "exchange_api_common.h" #include "exchange_api_json.h" #include "exchange_api_context.h" #include "exchange_api_handle.h" -#include "taler_signatures.h" /** @@ -84,93 +84,6 @@ struct TALER_EXCHANGE_WireHandle /** * Verify that the signature on the "200 OK" response - * for /wire/test from the exchange is valid. - * Accepts everything. - * - * @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_test_signature_ok (const struct TALER_EXCHANGE_WireHandle *wh, - json_t *json) -{ - return GNUNET_OK; -} - - -/** - * Verify that the signature on the "200 OK" response - * for /wire/sepa from the exchange 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_EXCHANGE_WireHandle *wh, - json_t *json) -{ - struct TALER_MasterSignatureP exchange_sig; - struct TALER_MasterWireSepaDetailsPS mp; - const char *receiver_name; - const char *iban; - const char *bic; - const struct TALER_EXCHANGE_Keys *key_state; - struct GNUNET_HashContext *hc; - struct MAJ_Specification spec[] = { - MAJ_spec_fixed_auto ("sig", &exchange_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_EXCHANGE_get_keys (wh->exchange); - 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, - &exchange_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 exchange is valid. * * @param wh wire handle with key material @@ -185,37 +98,33 @@ verify_wire_method_signature_ok (const struct TALER_EXCHANGE_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_EXCHANGE_WireHandle *wh, - json_t *json); - } handlers[] = { - { "test", &verify_wire_test_signature_ok }, - { "sepa", &verify_wire_sepa_signature_ok }, - { NULL, NULL } - }; - unsigned int i; + const struct TALER_EXCHANGE_Keys *key_state; + struct TALER_WIRE_Plugin *plugin; + char *lib_name; + int ret; - 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; + key_state = TALER_EXCHANGE_get_keys (wh->exchange); + (void) GNUNET_asprintf (&lib_name, + "libtaler_plugin_wire_%s", + method); + plugin = GNUNET_PLUGIN_load (lib_name, + NULL); + if (NULL == plugin) + { + GNUNET_free (lib_name); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Wire transfer method `%s' not supported\n", + method); + return GNUNET_NO; + } + plugin->library_name = lib_name; + ret = plugin->wire_validate (plugin->cls, + json, + &key_state->master_pub); + GNUNET_PLUGIN_unload (lib_name, + plugin); + GNUNET_free (lib_name); + return (GNUNET_YES == ret) ? GNUNET_OK : GNUNET_SYSERR; } @@ -312,6 +221,7 @@ handle_wire_method_finished (void *cls, json_string_value (json_array_get (wh->methods, wh->methods_off-1)), json); + json_decref (json); /* trigger request for the next /wire/method */ request_wire_method (wh); } diff --git a/src/exchange-lib/exchange_api_wire_deposits.c b/src/exchange-lib/exchange_api_wire_deposits.c index 281ae2097..406256025 100644 --- a/src/exchange-lib/exchange_api_wire_deposits.c +++ b/src/exchange-lib/exchange_api_wire_deposits.c @@ -24,6 +24,7 @@ #include <jansson.h> #include <microhttpd.h> /* just for HTTP status codes */ #include <gnunet/gnunet_util_lib.h> +#include <gnunet/gnunet_json_lib.h> #include "taler_exchange_service.h" #include "exchange_api_common.h" #include "exchange_api_json.h" diff --git a/src/exchange-lib/test-exchange-home/sepa.json b/src/exchange-lib/test-exchange-home/sepa.json index 36d12f661..92ca25566 100644 --- a/src/exchange-lib/test-exchange-home/sepa.json +++ b/src/exchange-lib/test-exchange-home/sepa.json @@ -1,6 +1,9 @@ { - "receiver_name": "Max Mustermann", - "iban": "DE89370400440532013000", + "type": "sepa", "bic": "COBADEFF370", - "sig": "8M5YJXM68PRAXKH76HYEBCJW657B23JA0RFGNDMZK2379YZMT626H1BN89KC0M1KJBWGYEN5Z763Q0Y7MCTZQ6BPPT7D9KFCTW60C10" + "address": "Musterstadt", + "iban": "DE89370400440532013000", + "receiver_name": "Max Musterman", + "salt": "J5AP2BJ8MQAM1WQYQ9YPTAHZVTDXCT3RKHX851S5Q2A42T11K796MNMKJ78VBGDKCFMETMBDPM35D81NCCN77YRW92GDFSQ6P4CZ720", + "sig": "FF4JZ1FPNVEFPM6ZXD3QN1M225T9X912PX1GJDWGGJX6KBSTR2EZHK24E1PYW7P64YGGQG7Q9HJW0XE36HBBYZWXW83PKVZEYNVG038" }
\ No newline at end of file diff --git a/src/exchange-lib/test_exchange_api.c b/src/exchange-lib/test_exchange_api.c index 890e80756..fc0945d62 100644 --- a/src/exchange-lib/test_exchange_api.c +++ b/src/exchange-lib/test_exchange_api.c @@ -23,6 +23,7 @@ #include "taler_util.h" #include "taler_signatures.h" #include "taler_exchange_service.h" +#include "taler_json_lib.h" #include <gnunet/gnunet_util_lib.h> #include <microhttpd.h> @@ -1502,7 +1503,7 @@ interpreter_run (void *cls, return; } execution_date = GNUNET_TIME_absolute_get (); - TALER_round_abs_time (&execution_date); + GNUNET_TIME_round_abs (&execution_date); cmd->details.admin_add_incoming.aih = TALER_EXCHANGE_admin_add_incoming (exchange, &reserve_pub, @@ -1664,7 +1665,7 @@ interpreter_run (void *cls, fail (is); return; } - TALER_hash_json (contract, + TALER_JSON_hash (contract, &h_contract); wire = json_loads (cmd->details.deposit.wire_details, JSON_REJECT_DUPLICATES, @@ -1698,7 +1699,7 @@ interpreter_run (void *cls, wire_deadline = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_DAYS); timestamp = GNUNET_TIME_absolute_get (); - TALER_round_abs_time (×tamp); + GNUNET_TIME_round_abs (×tamp); { struct TALER_DepositRequestPS dr; @@ -1706,7 +1707,7 @@ interpreter_run (void *cls, dr.purpose.size = htonl (sizeof (struct TALER_DepositRequestPS)); dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT); dr.h_contract = h_contract; - TALER_hash_json (wire, + TALER_JSON_hash (wire, &dr.h_wire); dr.timestamp = GNUNET_TIME_absolute_hton (timestamp); dr.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline); @@ -1964,14 +1965,14 @@ interpreter_run (void *cls, JSON_REJECT_DUPLICATES, NULL); GNUNET_assert (NULL != wire); - TALER_hash_json (wire, + TALER_JSON_hash (wire, &h_wire); json_decref (wire); contract = json_loads (ref->details.deposit.contract, JSON_REJECT_DUPLICATES, NULL); GNUNET_assert (NULL != contract); - TALER_hash_json (contract, + TALER_JSON_hash (contract, &h_contract); json_decref (contract); cmd->details.deposit_wtid.dwh @@ -2349,7 +2350,7 @@ run (void *cls, { .oc = OC_ADMIN_ADD_INCOMING, .label = "create-reserve-1", .expected_response_code = MHD_HTTP_OK, - .details.admin_add_incoming.wire = "{ \"type\":\"TEST\", \"bank\":\"source bank\", \"account_number\":42 }", + .details.admin_add_incoming.wire = "{ \"type\":\"test\", \"bank\":\"source bank\", \"account_number\":42 }", .details.admin_add_incoming.amount = "EUR:5.01" }, /* Withdraw a 5 EUR coin, at fee of 1 ct */ { .oc = OC_WITHDRAW_SIGN, @@ -2370,7 +2371,7 @@ run (void *cls, .expected_response_code = MHD_HTTP_OK, .details.deposit.amount = "EUR:5", .details.deposit.coin_ref = "withdraw-coin-1", - .details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account_number\":42 }", + .details.deposit.wire_details = "{ \"type\":\"test\", \"bank\":\"dest bank\", \"account_number\":42 }", .details.deposit.contract = "{ \"items\": [ { \"name\":\"ice cream\", \"value\":1 } ] }", .details.deposit.transaction_id = 1 }, @@ -2387,7 +2388,7 @@ run (void *cls, .expected_response_code = MHD_HTTP_FORBIDDEN, .details.deposit.amount = "EUR:5", .details.deposit.coin_ref = "withdraw-coin-1", - .details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account_number\":43 }", + .details.deposit.wire_details = "{ \"type\":\"test\", \"bank\":\"dest bank\", \"account_number\":43 }", .details.deposit.contract = "{ \"items\": [ { \"name\":\"ice cream\", \"value\":1 } ] }", .details.deposit.transaction_id = 1 }, /* Try to double-spend the 5 EUR coin at the same merchant (but different @@ -2397,7 +2398,7 @@ run (void *cls, .expected_response_code = MHD_HTTP_FORBIDDEN, .details.deposit.amount = "EUR:5", .details.deposit.coin_ref = "withdraw-coin-1", - .details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account_number\":42 }", + .details.deposit.wire_details = "{ \"type\":\"test\", \"bank\":\"dest bank\", \"account_number\":42 }", .details.deposit.contract = "{ \"items\": [ { \"name\":\"ice cream\", \"value\":1 } ] }", .details.deposit.transaction_id = 2 }, /* Try to double-spend the 5 EUR coin at the same merchant (but different @@ -2407,7 +2408,7 @@ run (void *cls, .expected_response_code = MHD_HTTP_FORBIDDEN, .details.deposit.amount = "EUR:5", .details.deposit.coin_ref = "withdraw-coin-1", - .details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account_number\":42 }", + .details.deposit.wire_details = "{ \"type\":\"test\", \"bank\":\"dest bank\", \"account_number\":42 }", .details.deposit.contract = "{ \"items\":[{ \"name\":\"ice cream\", \"value\":2 } ] }", .details.deposit.transaction_id = 1 }, @@ -2417,7 +2418,7 @@ run (void *cls, { .oc = OC_ADMIN_ADD_INCOMING, .label = "refresh-create-reserve-1", .expected_response_code = MHD_HTTP_OK, - .details.admin_add_incoming.wire = "{ \"type\":\"TEST\", \"bank\":\"source bank\", \"account_number\":424 }", + .details.admin_add_incoming.wire = "{ \"type\":\"test\", \"bank\":\"source bank\", \"account_number\":424 }", .details.admin_add_incoming.amount = "EUR:5.01" }, /* Withdraw a 5 EUR coin, at fee of 1 ct */ { .oc = OC_WITHDRAW_SIGN, @@ -2432,7 +2433,7 @@ run (void *cls, .expected_response_code = MHD_HTTP_OK, .details.deposit.amount = "EUR:1", .details.deposit.coin_ref = "refresh-withdraw-coin-1", - .details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account_number\":42 }", + .details.deposit.wire_details = "{ \"type\":\"test\", \"bank\":\"dest bank\", \"account_number\":42 }", .details.deposit.contract = "{ \"items\" : [ { \"name\":\"ice cream\", \"value\":\"EUR:1\" } ] }", .details.deposit.transaction_id = 42421 }, diff --git a/src/exchange-tools/Makefile.am b/src/exchange-tools/Makefile.am index 4ffabd15d..fda9cefa3 100644 --- a/src/exchange-tools/Makefile.am +++ b/src/exchange-tools/Makefile.am @@ -38,7 +38,9 @@ taler_exchange_sepa_SOURCES = \ taler_exchange_sepa_LDADD = \ $(LIBGCRYPT_LIBS) \ $(top_builddir)/src/util/libtalerutil.la \ - -lgnunetutil -ljansson $(XLIB) + -lgnunetjson \ + -lgnunetutil \ + -ljansson $(XLIB) taler_exchange_sepa_LDFLAGS = $(POSTGRESQL_LDFLAGS) taler_exchange_keycheck_SOURCES = \ diff --git a/src/exchange-tools/taler-exchange-keyup.c b/src/exchange-tools/taler-exchange-keyup.c index 779e3a3d3..861a9a7c8 100644 --- a/src/exchange-tools/taler-exchange-keyup.c +++ b/src/exchange-tools/taler-exchange-keyup.c @@ -518,7 +518,7 @@ exchange_keys_update_signkeys () "must be longer than signkey_duration"); return GNUNET_SYSERR; } - TALER_round_rel_time (&signkey_duration); + GNUNET_TIME_round_rel (&signkey_duration); GNUNET_asprintf (&signkey_dir, "%s" DIR_SEPARATOR_STR TALER_EXCHANGEDB_DIR_SIGNING_KEYS, exchange_directory); @@ -600,7 +600,7 @@ get_cointype_params (const char *ct, "duration_withdraw"); return GNUNET_SYSERR; } - TALER_round_rel_time (¶ms->duration_withdraw); + GNUNET_TIME_round_rel (¶ms->duration_withdraw); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (kcfg, ct, @@ -612,7 +612,7 @@ get_cointype_params (const char *ct, "duration_spend"); return GNUNET_SYSERR; } - TALER_round_rel_time (¶ms->duration_spend); + GNUNET_TIME_round_rel (¶ms->duration_spend); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (kcfg, ct, @@ -624,7 +624,7 @@ get_cointype_params (const char *ct, "duration_legal"); return GNUNET_SYSERR; } - TALER_round_rel_time (¶ms->duration_legal); + GNUNET_TIME_round_rel (¶ms->duration_legal); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (kcfg, ct, @@ -636,7 +636,7 @@ get_cointype_params (const char *ct, "exchange_denom_duration_overlap"); return GNUNET_SYSERR; } - TALER_round_rel_time (¶ms->duration_overlap); + GNUNET_TIME_round_rel (¶ms->duration_overlap); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (kcfg, ct, @@ -927,7 +927,7 @@ main (int argc, { now = GNUNET_TIME_absolute_get (); } - TALER_round_abs_time (&now); + GNUNET_TIME_round_abs (&now); kcfg = TALER_config_load (exchange_directory); if (NULL == kcfg) @@ -1017,7 +1017,7 @@ main (int argc, _("must not be zero")); return GNUNET_SYSERR; } - TALER_round_rel_time (&lookahead_sign); + GNUNET_TIME_round_rel (&lookahead_sign); lookahead_sign_stamp = GNUNET_TIME_absolute_add (now, lookahead_sign); diff --git a/src/exchange-tools/taler-exchange-sepa.c b/src/exchange-tools/taler-exchange-sepa.c index a3ac95436..1bfb49132 100644 --- a/src/exchange-tools/taler-exchange-sepa.c +++ b/src/exchange-tools/taler-exchange-sepa.c @@ -20,6 +20,7 @@ */ #include <platform.h> #include <jansson.h> +#include <gnunet/gnunet_json_lib.h> #include "taler_crypto_lib.h" #include "taler_signatures.h" @@ -35,6 +36,11 @@ static char *masterkeyfile; static char *sepa_name; /** + * Account holder address. + */ +static char *sepa_address; + +/** * IBAN number. */ static char *iban; @@ -63,6 +69,9 @@ main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { + {'a', "address", "ADDRESS", + "account holder address", 1, + &GNUNET_GETOPT_set_string, &sepa_address}, {'b', "bic", "BICCODE", "bank BIC code", 1, &GNUNET_GETOPT_set_string, &bic}, @@ -88,6 +97,7 @@ main (int argc, struct GNUNET_HashContext *hc; json_t *reply; char *json_str; + struct GNUNET_HashCode salt; GNUNET_assert (GNUNET_OK == GNUNET_log_setup ("taler-exchange-sepa", @@ -112,8 +122,20 @@ main (int argc, masterkeyfile); return 1; } + if ( (NULL == sepa_address) || + (NULL == iban) || + (NULL == sepa_name) || + (NULL == bic) ) + { + fprintf (stderr, + "Required arguments missing\n"); + return 1; + } /* Compute message to sign */ + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, + &salt, + sizeof (salt)); hc = GNUNET_CRYPTO_hash_context_start (); GNUNET_CRYPTO_hash_context_read (hc, sepa_name, @@ -132,27 +154,31 @@ main (int argc, &wsd.purpose, &sig.eddsa_signature); GNUNET_free (eddsa_priv); - + /* build JSON message */ - reply = json_pack ("{s:s, s:s, s:s, s:o}", + reply = json_pack ("{s:s, s:s, s:s, s:s, s:s, s:o, s:o}", + "type", "sepa", + "address", sepa_address, "receiver_name", sepa_name, "iban", iban, "bic", bic, - "sig", TALER_json_from_data (&sig, - sizeof (sig))); + "salt", GNUNET_JSON_from_data (&salt, + sizeof (salt)), + "sig", GNUNET_JSON_from_data (&sig, + sizeof (sig))); GNUNET_assert (NULL != reply); /* dump result to stdout */ json_str = json_dumps (reply, JSON_INDENT(2)); GNUNET_assert (NULL != json_str); - + if (NULL != output_filename) { fclose (stdout); stdout = fopen (output_filename, "w+"); } - fprintf (stdout, + fprintf (stdout, "%s", json_str); fflush (stdout); diff --git a/src/exchange/Makefile.am b/src/exchange/Makefile.am index 443ac511a..e29a51bbb 100644 --- a/src/exchange/Makefile.am +++ b/src/exchange/Makefile.am @@ -14,6 +14,7 @@ taler_exchange_aggregator_SOURCES = \ taler-exchange-aggregator.c taler_exchange_aggregator_LDADD = \ $(LIBGCRYPT_LIBS) \ + $(top_builddir)/src/json/libtalerjson.la \ $(top_builddir)/src/util/libtalerutil.la \ $(top_builddir)/src/wire/libtalerwire.la \ $(top_builddir)/src/exchangedb/libtalerexchangedb.la \ @@ -36,11 +37,13 @@ taler_exchange_httpd_SOURCES = \ taler-exchange-httpd_validation.c taler-exchange-httpd_validation.h taler_exchange_httpd_LDADD = \ $(LIBGCRYPT_LIBS) \ + $(top_builddir)/src/json/libtalerjson.la \ $(top_builddir)/src/util/libtalerutil.la \ $(top_builddir)/src/exchangedb/libtalerexchangedb.la \ -lmicrohttpd \ - -ljansson \ -lgnunetutil \ + -lgnunetjson \ + -ljansson \ -lpthread if HAVE_DEVELOPER diff --git a/src/exchange/taler-exchange-aggregator.c b/src/exchange/taler-exchange-aggregator.c index 3ffce1d3f..e399a422e 100644 --- a/src/exchange/taler-exchange-aggregator.c +++ b/src/exchange/taler-exchange-aggregator.c @@ -29,6 +29,7 @@ #include <pthread.h> #include "taler_exchangedb_lib.h" #include "taler_exchangedb_plugin.h" +#include "taler_json_lib.h" #include "taler_wire_lib.h" /** @@ -277,7 +278,7 @@ deposit_cb (void *cls, au->row_id = row_id; au->wire = (json_t *) wire; au->execution_time = GNUNET_TIME_absolute_get (); - TALER_hash_json (au->wire, + TALER_JSON_hash (au->wire, &au->h_wire); json_incref (au->wire); GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c index c16e26409..877876dbb 100644 --- a/src/exchange/taler-exchange-httpd.c +++ b/src/exchange/taler-exchange-httpd.c @@ -65,7 +65,7 @@ struct GNUNET_CONFIGURATION_Handle *cfg; * Master public key (according to the * configuration in the exchange directory). */ -struct GNUNET_CRYPTO_EddsaPublicKey TMH_master_public_key; +struct TALER_MasterPublicKeyP TMH_master_public_key; /** * Our DB plugin. @@ -424,7 +424,7 @@ exchange_serve_process_config (const char *exchange_directory) if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (TMH_master_public_key_str, strlen (TMH_master_public_key_str), - &TMH_master_public_key)) + &TMH_master_public_key.eddsa_pub)) { fprintf (stderr, "Invalid master public key given in exchange configuration."); diff --git a/src/exchange/taler-exchange-httpd.h b/src/exchange/taler-exchange-httpd.h index 5f17eac5b..236df9e19 100644 --- a/src/exchange/taler-exchange-httpd.h +++ b/src/exchange/taler-exchange-httpd.h @@ -57,7 +57,7 @@ extern char *TMH_exchange_directory; * Master public key (according to the * configuration in the exchange directory). */ -extern struct GNUNET_CRYPTO_EddsaPublicKey TMH_master_public_key; +extern struct TALER_MasterPublicKeyP TMH_master_public_key; /** * Private key of the exchange we use to sign messages. diff --git a/src/exchange/taler-exchange-httpd_db.c b/src/exchange/taler-exchange-httpd_db.c index 9d04efa9b..e96653a63 100644 --- a/src/exchange/taler-exchange-httpd_db.c +++ b/src/exchange/taler-exchange-httpd_db.c @@ -21,6 +21,8 @@ #include "platform.h" #include <pthread.h> #include <jansson.h> +#include <gnunet/gnunet_json_lib.h> +#include "taler_json_lib.h" #include "taler-exchange-httpd_responses.h" #include "taler-exchange-httpd_keystate.h" @@ -1673,12 +1675,12 @@ handle_transaction_data (void *cls, is also ugly if we ever add signatures over this data. (#4135) */ json_array_append (ctx->deposits, json_pack ("{s:o, s:o, s:o, s:I, s:o}", - "deposit_value", TALER_json_from_amount (deposit_value), - "deposit_fee", TALER_json_from_amount (deposit_fee), - "H_contract", TALER_json_from_data (h_contract, + "deposit_value", TALER_JSON_from_amount (deposit_value), + "deposit_fee", TALER_JSON_from_amount (deposit_fee), + "H_contract", GNUNET_JSON_from_data (h_contract, sizeof (struct GNUNET_HashCode)), "transaction_id", (json_int_t) transaction_id, - "coin_pub", TALER_json_from_data (coin_pub, + "coin_pub", GNUNET_JSON_from_data (coin_pub, sizeof (struct TALER_CoinSpendPublicKeyP)))); } diff --git a/src/exchange/taler-exchange-httpd_deposit.c b/src/exchange/taler-exchange-httpd_deposit.c index 629d6f8b5..82dcf1a55 100644 --- a/src/exchange/taler-exchange-httpd_deposit.c +++ b/src/exchange/taler-exchange-httpd_deposit.c @@ -27,9 +27,11 @@ */ #include "platform.h" #include <gnunet/gnunet_util_lib.h> +#include <gnunet/gnunet_json_lib.h> #include <jansson.h> #include <microhttpd.h> #include <pthread.h> +#include "taler_json_lib.h" #include "taler-exchange-httpd_parsing.h" #include "taler-exchange-httpd_deposit.h" #include "taler-exchange-httpd_responses.h" @@ -170,7 +172,7 @@ parse_and_handle_deposit_request (struct MHD_Connection *connection, "wire"); } if (GNUNET_OK != - TALER_hash_json (wire, + TALER_JSON_hash (wire, &my_h_wire)) { TALER_LOG_WARNING ("Failed to parse JSON wire format specification for /deposit request\n"); diff --git a/src/exchange/taler-exchange-httpd_keystate.c b/src/exchange/taler-exchange-httpd_keystate.c index e278882fe..bf91b8183 100644 --- a/src/exchange/taler-exchange-httpd_keystate.c +++ b/src/exchange/taler-exchange-httpd_keystate.c @@ -22,6 +22,7 @@ */ #include "platform.h" #include <pthread.h> +#include "taler_json_lib.h" #include "taler-exchange-httpd_keystate.h" #include "taler-exchange-httpd_responses.h" #include "taler_exchangedb_plugin.h" @@ -144,26 +145,26 @@ denom_key_issue_to_json (const struct TALER_DenominationPublicKey *pk, return json_pack ("{s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o}", "master_sig", - TALER_json_from_data (&dki->signature, + GNUNET_JSON_from_data (&dki->signature, sizeof (struct GNUNET_CRYPTO_EddsaSignature)), "stamp_start", - TALER_json_from_abs (GNUNET_TIME_absolute_ntoh (dki->properties.start)), + GNUNET_JSON_from_time_abs (GNUNET_TIME_absolute_ntoh (dki->properties.start)), "stamp_expire_withdraw", - TALER_json_from_abs (GNUNET_TIME_absolute_ntoh (dki->properties.expire_withdraw)), + GNUNET_JSON_from_time_abs (GNUNET_TIME_absolute_ntoh (dki->properties.expire_withdraw)), "stamp_expire_deposit", - TALER_json_from_abs (GNUNET_TIME_absolute_ntoh (dki->properties.expire_spend)), + GNUNET_JSON_from_time_abs (GNUNET_TIME_absolute_ntoh (dki->properties.expire_spend)), "stamp_expire_legal", - TALER_json_from_abs (GNUNET_TIME_absolute_ntoh (dki->properties.expire_legal)), + GNUNET_JSON_from_time_abs (GNUNET_TIME_absolute_ntoh (dki->properties.expire_legal)), "denom_pub", - TALER_json_from_rsa_public_key (pk->rsa_public_key), + GNUNET_JSON_from_rsa_public_key (pk->rsa_public_key), "value", - TALER_json_from_amount (&value), + TALER_JSON_from_amount (&value), "fee_withdraw", - TALER_json_from_amount (&fee_withdraw), + TALER_JSON_from_amount (&fee_withdraw), "fee_deposit", - TALER_json_from_amount (&fee_deposit), + TALER_JSON_from_amount (&fee_deposit), "fee_refresh", - TALER_json_from_amount (&fee_refresh)); + TALER_JSON_from_amount (&fee_refresh)); } @@ -342,19 +343,19 @@ sign_key_issue_to_json (const struct TALER_ExchangeSigningKeyValidityPS *ski) return json_pack ("{s:o, s:o, s:o, s:o, s:o, s:o}", "stamp_start", - TALER_json_from_abs (GNUNET_TIME_absolute_ntoh (ski->start)), + GNUNET_JSON_from_time_abs (GNUNET_TIME_absolute_ntoh (ski->start)), "stamp_expire", - TALER_json_from_abs (GNUNET_TIME_absolute_ntoh (ski->expire)), + GNUNET_JSON_from_time_abs (GNUNET_TIME_absolute_ntoh (ski->expire)), "stamp_end", - TALER_json_from_abs (GNUNET_TIME_absolute_ntoh (ski->end)), + GNUNET_JSON_from_time_abs (GNUNET_TIME_absolute_ntoh (ski->end)), "master_pub", - TALER_json_from_data (&ski->master_public_key, + GNUNET_JSON_from_data (&ski->master_public_key, sizeof (struct TALER_MasterPublicKeyP)), "master_sig", - TALER_json_from_data (&ski->signature, + GNUNET_JSON_from_data (&ski->signature, sizeof (struct TALER_MasterSignatureP)), "key", - TALER_json_from_data (&ski->signkey_pub, + GNUNET_JSON_from_data (&ski->signkey_pub, sizeof (struct TALER_ExchangePublicKeyP))); } @@ -437,16 +438,16 @@ auditor_to_json (const struct TALER_AuditorPublicKeyP *apub, json_array_append_new (ja, json_pack ("{s:o, s:o}", "denom_pub_h", - TALER_json_from_data (&dki[i]->denom_hash, + GNUNET_JSON_from_data (&dki[i]->denom_hash, sizeof (struct GNUNET_HashCode)), "auditor_sig", - TALER_json_from_data (asigs[i], + GNUNET_JSON_from_data (asigs[i], sizeof (struct TALER_AuditorSignatureP)))); return json_pack ("{s:o, s:o}", "denomination_keys", ja, "auditor_pub", - TALER_json_from_data (apub, + GNUNET_JSON_from_data (apub, sizeof (struct TALER_AuditorPublicKeyP))); } @@ -633,7 +634,7 @@ TMH_KS_acquire_ (const char *location) key_state->denomkey_map = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); key_state->reload_time = GNUNET_TIME_absolute_get (); - TALER_round_abs_time (&key_state->reload_time); + GNUNET_TIME_round_abs (&key_state->reload_time); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Loading keys from `%s'\n", TMH_exchange_directory); @@ -663,15 +664,15 @@ TMH_KS_acquire_ (const char *location) keys = json_pack ("{s:o, s:o, s:o, s:o, s:o, s:o, s:o}", "master_public_key", - TALER_json_from_data (&TMH_master_public_key, + GNUNET_JSON_from_data (&TMH_master_public_key, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)), "signkeys", key_state->sign_keys_array, "denoms", key_state->denom_keys_array, "auditors", key_state->auditors_array, - "list_issue_date", TALER_json_from_abs (key_state->reload_time), - "eddsa_pub", TALER_json_from_data (&key_state->current_sign_key_issue.issue.signkey_pub, + "list_issue_date", GNUNET_JSON_from_time_abs (key_state->reload_time), + "eddsa_pub", GNUNET_JSON_from_data (&key_state->current_sign_key_issue.issue.signkey_pub, sizeof (struct TALER_ExchangePublicKeyP)), - "eddsa_sig", TALER_json_from_data (&sig, + "eddsa_sig", GNUNET_JSON_from_data (&sig, sizeof (struct TALER_ExchangeSignatureP))); key_state->auditors_array = NULL; key_state->sign_keys_array = NULL; diff --git a/src/exchange/taler-exchange-httpd_parsing.c b/src/exchange/taler-exchange-httpd_parsing.c index 25539aeb7..3fd69ae50 100644 --- a/src/exchange/taler-exchange-httpd_parsing.c +++ b/src/exchange/taler-exchange-httpd_parsing.c @@ -24,6 +24,7 @@ #include "platform.h" #include <gnunet/gnunet_util_lib.h> +#include "taler_json_lib.h" #include "taler-exchange-httpd_parsing.h" #include "taler-exchange-httpd_responses.h" @@ -786,10 +787,15 @@ TMH_PARSE_navigate_json (struct MHD_Connection *connection, case TMH_PARSE_JNC_RET_AMOUNT: { struct TALER_Amount *where = va_arg (argp, void *); + struct GNUNET_JSON_Specification spec[] = { + TALER_JSON_spec_amount (NULL, where), + GNUNET_JSON_spec_end () + }; if (GNUNET_OK != - TALER_json_to_amount ((json_t *) root, - where)) + GNUNET_JSON_parse ((json_t *) root, + spec, + NULL, NULL)) { GNUNET_break_op (0); ret = (MHD_YES != @@ -823,10 +829,15 @@ TMH_PARSE_navigate_json (struct MHD_Connection *connection, case TMH_PARSE_JNC_RET_TIME_ABSOLUTE: { struct GNUNET_TIME_Absolute *where = va_arg (argp, void *); + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_absolute_time (NULL, where), + GNUNET_JSON_spec_end () + }; if (GNUNET_OK != - TALER_json_to_abs ((json_t *) root, - where)) + GNUNET_JSON_parse ((json_t *) root, + spec, + NULL, NULL)) { GNUNET_break_op (0); ret = (MHD_YES != diff --git a/src/exchange/taler-exchange-httpd_responses.c b/src/exchange/taler-exchange-httpd_responses.c index d6cf81bb7..a47b29cae 100644 --- a/src/exchange/taler-exchange-httpd_responses.c +++ b/src/exchange/taler-exchange-httpd_responses.c @@ -25,7 +25,7 @@ #include "platform.h" #include "taler-exchange-httpd_responses.h" #include "taler_util.h" -#include <gnunet/gnunet_util_lib.h> +#include "taler_json_lib.h" #include "taler-exchange-httpd_keystate.h" @@ -388,9 +388,9 @@ TMH_RESPONSE_reply_deposit_success (struct MHD_Connection *connection, MHD_HTTP_OK, "{s:s, s:o, s:o}", "status", "DEPOSIT_OK", - "sig", TALER_json_from_data (&sig, + "sig", GNUNET_JSON_from_data (&sig, sizeof (sig)), - "pub", TALER_json_from_data (&pub, + "pub", GNUNET_JSON_from_data (&pub, sizeof (pub))); } @@ -449,7 +449,7 @@ compile_transaction_history (const struct TALER_EXCHANGEDB_TransactionList *tl) return NULL; } - details = TALER_json_from_data (&dr.purpose, + details = GNUNET_JSON_from_data (&dr.purpose, sizeof (struct TALER_DepositRequestPS)); break; } @@ -481,7 +481,7 @@ compile_transaction_history (const struct TALER_EXCHANGEDB_TransactionList *tl) return NULL; } - details = TALER_json_from_data (&ms.purpose, + details = GNUNET_JSON_from_data (&ms.purpose, sizeof (struct TALER_RefreshMeltCoinAffirmationPS)); } break; @@ -491,8 +491,8 @@ compile_transaction_history (const struct TALER_EXCHANGEDB_TransactionList *tl) json_array_append_new (history, json_pack ("{s:s, s:o, s:o, s:o}", "type", type, - "amount", TALER_json_from_amount (&value), - "signature", TALER_json_from_data (sig, + "amount", TALER_JSON_from_amount (&value), + "signature", GNUNET_JSON_from_data (sig, sizeof (struct TALER_CoinSpendSignatureP)), "details", details)); } @@ -569,7 +569,7 @@ compile_reserve_history (const struct TALER_EXCHANGEDB_ReserveHistory *rh, json_pack ("{s:s, s:O, s:o}", "type", "DEPOSIT", "wire", pos->details.bank->wire, - "amount", TALER_json_from_amount (&pos->details.bank->amount))); + "amount", TALER_JSON_from_amount (&pos->details.bank->amount))); break; case TALER_EXCHANGEDB_RO_WITHDRAW_COIN: break; @@ -614,11 +614,11 @@ compile_reserve_history (const struct TALER_EXCHANGEDB_ReserveHistory *rh, json_array_append_new (json_history, json_pack ("{s:s, s:o, s:o, s:o}", "type", "WITHDRAW", - "signature", TALER_json_from_data (&pos->details.withdraw->reserve_sig, + "signature", GNUNET_JSON_from_data (&pos->details.withdraw->reserve_sig, sizeof (struct TALER_ReserveSignatureP)), - "details", TALER_json_from_data (&wr, + "details", GNUNET_JSON_from_data (&wr, sizeof (wr)), - "amount", TALER_json_from_amount (&value))); + "amount", TALER_JSON_from_amount (&value))); break; } } @@ -662,7 +662,7 @@ TMH_RESPONSE_reply_reserve_status_success (struct MHD_Connection *connection, if (NULL == json_history) return TMH_RESPONSE_reply_internal_error (connection, "balance calculation failure"); - json_balance = TALER_json_from_amount (&balance); + json_balance = TALER_JSON_from_amount (&balance); return TMH_RESPONSE_reply_json_pack (connection, MHD_HTTP_OK, "{s:o, s:o}", @@ -693,7 +693,7 @@ TMH_RESPONSE_reply_reserve_withdraw_insufficient_funds (struct MHD_Connection *c if (NULL == json_history) return TMH_RESPONSE_reply_internal_error (connection, "balance calculation failure"); - json_balance = TALER_json_from_amount (&balance); + json_balance = TALER_JSON_from_amount (&balance); return TMH_RESPONSE_reply_json_pack (connection, MHD_HTTP_PAYMENT_REQUIRED, "{s:s, s:o, s:o}", @@ -716,7 +716,7 @@ TMH_RESPONSE_reply_reserve_withdraw_success (struct MHD_Connection *connection, { json_t *sig_json; - sig_json = TALER_json_from_rsa_signature (collectable->sig.rsa_signature); + sig_json = GNUNET_JSON_from_rsa_signature (collectable->sig.rsa_signature); return TMH_RESPONSE_reply_json_pack (connection, MHD_HTTP_OK, "{s:o}", @@ -758,14 +758,14 @@ TMH_RESPONSE_reply_refresh_melt_insufficient_funds (struct MHD_Connection *conne "error", "insufficient funds", "coin_pub", - TALER_json_from_data (coin_pub, + GNUNET_JSON_from_data (coin_pub, sizeof (struct TALER_CoinSpendPublicKeyP)), "original_value", - TALER_json_from_amount (&coin_value), + TALER_JSON_from_amount (&coin_value), "residual_value", - TALER_json_from_amount (&residual), + TALER_JSON_from_amount (&residual), "requested_value", - TALER_json_from_amount (&requested), + TALER_JSON_from_amount (&requested), "history", history); } @@ -797,7 +797,7 @@ TMH_RESPONSE_reply_refresh_melt_success (struct MHD_Connection *connection, TMH_KS_sign (&body.purpose, &pub, &sig); - sig_json = TALER_json_from_data (&sig, + sig_json = GNUNET_JSON_from_data (&sig, sizeof (sig)); GNUNET_assert (NULL != sig_json); return TMH_RESPONSE_reply_json_pack (connection, @@ -805,7 +805,7 @@ TMH_RESPONSE_reply_refresh_melt_success (struct MHD_Connection *connection, "{s:i, s:o, s:o}", "noreveal_index", (int) noreveal_index, "exchange_sig", sig_json, - "exchange_pub", TALER_json_from_data (&pub, + "exchange_pub", GNUNET_JSON_from_data (&pub, sizeof (pub))); } @@ -835,7 +835,7 @@ TMH_RESPONSE_reply_refresh_reveal_success (struct MHD_Connection *connection, obj = json_object (); json_object_set_new (obj, "ev_sig", - TALER_json_from_rsa_signature (sigs[newcoin_index].rsa_signature)); + GNUNET_JSON_from_rsa_signature (sigs[newcoin_index].rsa_signature)); json_array_append_new (list, obj); } @@ -889,18 +889,18 @@ TMH_RESPONSE_reply_refresh_reveal_missmatch (struct MHD_Connection *connection, rm_json = json_object (); json_object_set_new (rm_json, "coin_sig", - TALER_json_from_data (&rm->coin_sig, + GNUNET_JSON_from_data (&rm->coin_sig, sizeof (struct TALER_CoinSpendSignatureP))); json_object_set_new (rm_json, "coin_pub", - TALER_json_from_data (&rm->coin.coin_pub, + GNUNET_JSON_from_data (&rm->coin.coin_pub, sizeof (struct TALER_CoinSpendPublicKeyP))); json_object_set_new (rm_json, "melt_amount_with_fee", - TALER_json_from_amount (&rm->amount_with_fee)); + TALER_JSON_from_amount (&rm->amount_with_fee)); json_object_set_new (rm_json, "melt_fee", - TALER_json_from_amount (&rm->melt_fee)); + TALER_JSON_from_amount (&rm->melt_fee)); json_array_append_new (info_old, rm_json); } @@ -911,7 +911,7 @@ TMH_RESPONSE_reply_refresh_reveal_missmatch (struct MHD_Connection *connection, pk = &mc->denom_pubs[i]; json_array_append_new (info_new, - TALER_json_from_rsa_public_key (pk->rsa_public_key)); + GNUNET_JSON_from_rsa_public_key (pk->rsa_public_key)); } info_commit = json_array (); @@ -931,15 +931,15 @@ TMH_RESPONSE_reply_refresh_reveal_missmatch (struct MHD_Connection *connection, cc_json = json_object (); json_object_set_new (cc_json, "coin_ev", - TALER_json_from_data (cc->coin_ev, + GNUNET_JSON_from_data (cc->coin_ev, cc->coin_ev_size)); json_object_set_new (cc_json, "coin_priv_enc", - TALER_json_from_data (cc->refresh_link->coin_priv_enc, + GNUNET_JSON_from_data (cc->refresh_link->coin_priv_enc, sizeof (struct TALER_CoinSpendPrivateKeyP))); json_object_set_new (cc_json, "blinding_key_enc", - TALER_json_from_data (cc->refresh_link->blinding_key_enc, + GNUNET_JSON_from_data (cc->refresh_link->blinding_key_enc, cc->refresh_link->blinding_key_enc_size)); json_array_append_new (info_commit_k, @@ -957,11 +957,11 @@ TMH_RESPONSE_reply_refresh_reveal_missmatch (struct MHD_Connection *connection, cl_json = json_object (); json_object_set_new (cl_json, "transfer_pub", - TALER_json_from_data (&cl->transfer_pub, + GNUNET_JSON_from_data (&cl->transfer_pub, sizeof (struct TALER_TransferPublicKeyP))); json_object_set_new (cl_json, "shared_secret_enc", - TALER_json_from_data (&cl->shared_secret_enc, + GNUNET_JSON_from_data (&cl->shared_secret_enc, sizeof (struct TALER_EncryptedLinkSecretP))); json_array_append_new (info_link_k, cl_json); @@ -1015,15 +1015,15 @@ TMH_RESPONSE_reply_refresh_link_success (struct MHD_Connection *connection, obj = json_object (); json_object_set_new (obj, "link_enc", - TALER_json_from_data (pos->link_data_enc->coin_priv_enc, + GNUNET_JSON_from_data (pos->link_data_enc->coin_priv_enc, sizeof (struct TALER_CoinSpendPrivateKeyP) + pos->link_data_enc->blinding_key_enc_size)); json_object_set_new (obj, "denom_pub", - TALER_json_from_rsa_public_key (pos->denom_pub.rsa_public_key)); + GNUNET_JSON_from_rsa_public_key (pos->denom_pub.rsa_public_key)); json_object_set_new (obj, "ev_sig", - TALER_json_from_rsa_signature (pos->ev_sig.rsa_signature)); + GNUNET_JSON_from_rsa_signature (pos->ev_sig.rsa_signature)); json_array_append_new (list, obj); } @@ -1033,11 +1033,11 @@ TMH_RESPONSE_reply_refresh_link_success (struct MHD_Connection *connection, list); json_object_set_new (root, "transfer_pub", - TALER_json_from_data (&sessions[i].transfer_pub, + GNUNET_JSON_from_data (&sessions[i].transfer_pub, sizeof (struct TALER_TransferPublicKeyP))); json_object_set_new (root, "secret_enc", - TALER_json_from_data (&sessions[i].shared_secret_enc, + GNUNET_JSON_from_data (&sessions[i].shared_secret_enc, sizeof (struct TALER_EncryptedLinkSecretP))); json_array_append_new (mlist, root); @@ -1083,7 +1083,7 @@ TMH_RESPONSE_reply_deposit_pending (struct MHD_Connection *connection, return TMH_RESPONSE_reply_json_pack (connection, MHD_HTTP_ACCEPTED, "{s:o}", - "execution_time", TALER_json_from_abs (planned_exec_time)); + "execution_time", GNUNET_JSON_from_time_abs (planned_exec_time)); } @@ -1132,13 +1132,13 @@ TMH_RESPONSE_reply_deposit_wtid (struct MHD_Connection *connection, return TMH_RESPONSE_reply_json_pack (connection, MHD_HTTP_OK, "{s:o, s:o, s:o, s:o, s:o, s:o}", - "wtid", TALER_json_from_data (wtid, + "wtid", GNUNET_JSON_from_data (wtid, sizeof (*wtid)), - "execution_time", TALER_json_from_abs (exec_time), - "coin_contribution", TALER_json_from_amount (coin_contribution), - "exchange_sig", TALER_json_from_data (&sig, + "execution_time", GNUNET_JSON_from_time_abs (exec_time), + "coin_contribution", TALER_JSON_from_amount (coin_contribution), + "exchange_sig", GNUNET_JSON_from_data (&sig, sizeof (sig)), - "exchange_pub", TALER_json_from_data (&pub, + "exchange_pub", GNUNET_JSON_from_data (&pub, sizeof (pub))); } @@ -1165,10 +1165,10 @@ TMH_RESPONSE_reply_wire_deposit_details (struct MHD_Connection *connection, return TMH_RESPONSE_reply_json_pack (connection, MHD_HTTP_OK, "{s:o, s:o, s:o, s:o}", - "total", TALER_json_from_amount (total), - "merchant_pub", TALER_json_from_data (merchant_pub, + "total", TALER_JSON_from_amount (total), + "merchant_pub", GNUNET_JSON_from_data (merchant_pub, sizeof (struct TALER_MerchantPublicKeyP)), - "h_wire", TALER_json_from_data (h_wire, + "h_wire", GNUNET_JSON_from_data (h_wire, sizeof (struct GNUNET_HashCode)), "deposits", deposits); } diff --git a/src/exchange/taler-exchange-httpd_test.c b/src/exchange/taler-exchange-httpd_test.c index 876869d86..7b6438cae 100644 --- a/src/exchange/taler-exchange-httpd_test.c +++ b/src/exchange/taler-exchange-httpd_test.c @@ -21,6 +21,7 @@ */ #include "platform.h" #include <gnunet/gnunet_util_lib.h> +#include <gnunet/gnunet_json_lib.h> #include <jansson.h> #include <microhttpd.h> #include "taler_signatures.h" @@ -90,7 +91,7 @@ TMH_TEST_handler_test_base32 (struct TMH_RequestHandler *rh, MHD_HTTP_OK, "{s:o}", "output", - TALER_json_from_data (&hc, sizeof (struct GNUNET_HashCode))); + GNUNET_JSON_from_data (&hc, sizeof (struct GNUNET_HashCode))); } @@ -164,7 +165,7 @@ TMH_TEST_handler_test_encrypt (struct TMH_RequestHandler *rh, &skey, &iv, out)); - json = TALER_json_from_data (out, + json = GNUNET_JSON_from_data (out, in_ptr_size); GNUNET_free (out); TMH_PARSE_release_data (spec); @@ -231,7 +232,7 @@ TMH_TEST_handler_test_hkdf (struct TMH_RequestHandler *rh, in_ptr_size, NULL, 0); TMH_PARSE_release_data (spec); - json = TALER_json_from_data (&hc, + json = GNUNET_JSON_from_data (&hc, sizeof (struct GNUNET_HashCode)); return TMH_RESPONSE_reply_json_pack (connection, MHD_HTTP_OK, @@ -302,7 +303,7 @@ TMH_TEST_handler_test_ecdhe (struct TMH_RequestHandler *rh, MHD_HTTP_OK, "{s:o}", "ecdh_hash", - TALER_json_from_data (&hc, + GNUNET_JSON_from_data (&hc, sizeof (hc))); } @@ -387,10 +388,10 @@ TMH_TEST_handler_test_eddsa (struct TMH_RequestHandler *rh, MHD_HTTP_OK, "{s:o, s:o}", "eddsa_pub", - TALER_json_from_data (&pub, + GNUNET_JSON_from_data (&pub, sizeof (pub)), "eddsa_sig", - TALER_json_from_data (&sig, + GNUNET_JSON_from_data (&sig, sizeof (sig))); } @@ -435,7 +436,7 @@ TMH_TEST_handler_test_rsa_get (struct TMH_RequestHandler *rh, MHD_HTTP_OK, "{s:o}", "rsa_pub", - TALER_json_from_rsa_public_key (pub)); + GNUNET_JSON_from_rsa_public_key (pub)); GNUNET_CRYPTO_rsa_public_key_free (pub); return res; } @@ -509,7 +510,7 @@ TMH_TEST_handler_test_rsa_sign (struct TMH_RequestHandler *rh, MHD_HTTP_OK, "{s:o}", "rsa_blind_sig", - TALER_json_from_rsa_signature (sig)); + GNUNET_JSON_from_rsa_signature (sig)); GNUNET_CRYPTO_rsa_signature_free (sig); return res; } @@ -578,7 +579,7 @@ TMH_TEST_handler_test_transfer (struct TMH_RequestHandler *rh, MHD_HTTP_OK, "{s:o}", "secret", - TALER_json_from_data (&secret, + GNUNET_JSON_from_data (&secret, sizeof (secret))); } diff --git a/src/exchange/taler-exchange-httpd_validation.c b/src/exchange/taler-exchange-httpd_validation.c index 9132e3e02..b7e8a7f80 100644 --- a/src/exchange/taler-exchange-httpd_validation.c +++ b/src/exchange/taler-exchange-httpd_validation.c @@ -21,6 +21,7 @@ */ #include "platform.h" #include <gnunet/gnunet_util_lib.h> +#include "taler-exchange-httpd.h" #include "taler-exchange-httpd_validation.h" #include "taler_wire_plugin.h" @@ -172,7 +173,9 @@ TMH_json_validate_wireformat (const json_t *wire) for (p=wire_head; NULL != p; p = p->next) if (0 == strcasecmp (p->type, stype)) - return p->plugin->wire_validate (wire); + return p->plugin->wire_validate (p->plugin->cls, + wire, + &TMH_master_public_key); return GNUNET_NO; } diff --git a/src/exchange/taler-exchange-httpd_wire.c b/src/exchange/taler-exchange-httpd_wire.c index cec041762..1b3d3b541 100644 --- a/src/exchange/taler-exchange-httpd_wire.c +++ b/src/exchange/taler-exchange-httpd_wire.c @@ -19,6 +19,7 @@ * @author Christian Grothoff */ #include "platform.h" +#include <gnunet/gnunet_json_lib.h> #include "taler-exchange-httpd_keystate.h" #include "taler-exchange-httpd_responses.h" #include "taler-exchange-httpd_validation.h" @@ -57,9 +58,9 @@ TMH_WIRE_handler_wire (struct TMH_RequestHandler *rh, MHD_HTTP_OK, "{s:o, s:o, s:o}", "methods", methods, - "sig", TALER_json_from_data (&sig, + "sig", GNUNET_JSON_from_data (&sig, sizeof (sig)), - "pub", TALER_json_from_data (&pub, + "pub", GNUNET_JSON_from_data (&pub, sizeof (pub))); } diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h index 566dec6f8..c3ecba968 100644 --- a/src/include/taler_exchange_service.h +++ b/src/include/taler_exchange_service.h @@ -22,6 +22,7 @@ #ifndef _TALER_EXCHANGE_SERVICE_H #define _TALER_EXCHANGE_SERVICE_H +#include <jansson.h> #include "taler_util.h" /* ********************* event loop *********************** */ @@ -292,7 +293,7 @@ struct TALER_EXCHANGE_Keys */ typedef void (*TALER_EXCHANGE_CertificationCallback) (void *cls, - const struct TALER_EXCHANGE_Keys *keys); + const struct TALER_EXCHANGE_Keys *keys); /** @@ -319,10 +320,10 @@ struct TALER_EXCHANGE_Handle; */ struct TALER_EXCHANGE_Handle * TALER_EXCHANGE_connect (struct TALER_EXCHANGE_Context *ctx, - const char *url, - TALER_EXCHANGE_CertificationCallback cert_cb, - void *cert_cb_cls, - ...); + const char *url, + TALER_EXCHANGE_CertificationCallback cert_cb, + void *cert_cb_cls, + ...); /** @@ -354,7 +355,7 @@ TALER_EXCHANGE_get_keys (const struct TALER_EXCHANGE_Handle *exchange); */ int TALER_EXCHANGE_test_signing_key (const struct TALER_EXCHANGE_Keys *keys, - const struct TALER_ExchangePublicKeyP *pub); + const struct TALER_ExchangePublicKeyP *pub); /** @@ -367,7 +368,7 @@ TALER_EXCHANGE_test_signing_key (const struct TALER_EXCHANGE_Keys *keys, */ const struct TALER_EXCHANGE_DenomPublicKey * TALER_EXCHANGE_get_denomination_key (const struct TALER_EXCHANGE_Keys *keys, - const struct TALER_DenominationPublicKey *pk); + const struct TALER_DenominationPublicKey *pk); /** @@ -379,7 +380,7 @@ TALER_EXCHANGE_get_denomination_key (const struct TALER_EXCHANGE_Keys *keys, */ const struct TALER_EXCHANGE_DenomPublicKey * TALER_EXCHANGE_get_denomination_key_by_hash (const struct TALER_EXCHANGE_Keys *keys, - const struct GNUNET_HashCode *hc); + const struct GNUNET_HashCode *hc); /* ********************* /wire *********************** */ @@ -423,9 +424,9 @@ struct TALER_EXCHANGE_WireHandle; */ typedef void (*TALER_EXCHANGE_WireResultCallback) (void *cls, - unsigned int http_status, - const char *method, - json_t *obj); + unsigned int http_status, + const char *method, + json_t *obj); /** diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index aecb050a7..f45014463 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -22,6 +22,7 @@ #ifndef TALER_EXCHANGEDB_PLUGIN_H #define TALER_EXCHANGEDB_PLUGIN_H +#include <jansson.h> #include <gnunet/gnunet_util_lib.h> #include "taler_exchangedb_lib.h" diff --git a/src/include/taler_json_lib.h b/src/include/taler_json_lib.h index d9fa05188..aee151b97 100644 --- a/src/include/taler_json_lib.h +++ b/src/include/taler_json_lib.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 GNUnet e.V. + Copyright (C) 2014, 2015, 2016 GNUnet e.V. 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 @@ -17,14 +17,18 @@ * @file include/taler_json_lib.h * @brief helper functions for JSON processing using libjansson * @author Sree Harsha Totakura <sreeharsha@totakura.in> + * @author Christian Grothoff */ -#ifndef TALER_json_LIB_H_ -#define TALER_json_LIB_H_ +#ifndef TALER_JSON_LIB_H_ +#define TALER_JSON_LIB_H_ #include <jansson.h> +#include <gnunet/gnunet_json_lib.h> +#include "taler_util.h" /** * Print JSON parsing related error information + * @deprecated */ #define TALER_json_warn(error) \ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, \ @@ -39,106 +43,18 @@ * @return a json object describing the amount */ json_t * -TALER_json_from_amount (const struct TALER_Amount *amount); +TALER_JSON_from_amount (const struct TALER_Amount *amount); /** - * Convert absolute timestamp to a json string. + * Provide specification to parse given JSON object to an amount. * - * @param stamp the time stamp - * @return a json string with the timestamp in @a stamp - */ -json_t * -TALER_json_from_abs (struct GNUNET_TIME_Absolute stamp); - - -/** - * Convert RSA public key to JSON. - * - * @param pk public key to convert - * @return corresponding JSON encoding - */ -json_t * -TALER_json_from_rsa_public_key (struct GNUNET_CRYPTO_rsa_PublicKey *pk); - - -/** - * Convert RSA signature to JSON. - * - * @param sig signature to convert - * @return corresponding JSON encoding - */ -json_t * -TALER_json_from_rsa_signature (struct GNUNET_CRYPTO_rsa_Signature *sig); - - -/** - * Convert binary data to a JSON string - * with the base32crockford encoding. - * - * @param data binary data - * @param size size of @a data in bytes - * @return json string that encodes @a data - */ -json_t * -TALER_json_from_data (const void *data, - size_t size); - - -/** - * Parse given JSON object to Amount - * - * @param json the json object representing Amount + * @param name name of the amount field in the JSON * @param[out] r_amount where the amount has to be written - * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error - */ -int -TALER_json_to_amount (json_t *json, - struct TALER_Amount *r_amount); - -/** - * Parse given JSON object to absolute time. - * - * @param json the json object representing absolute time in seconds - * @param[out] abs where the time has to be written - * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error - */ -int -TALER_json_to_abs (json_t *json, - struct GNUNET_TIME_Absolute *abs); - -/** - * Parse given JSON object to data - * - * @param json the json object representing data - * @param out the pointer to hold the parsed data. - * @param out_size the size of @a out - * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error - */ -int -TALER_json_to_data (json_t *json, - void *out, - size_t out_size); - - -/** - * Convert JSON to RSA public key. - * - * @param json JSON encoding to convert - * @return corresponding public key */ -struct GNUNET_CRYPTO_rsa_PublicKey * -TALER_json_to_rsa_public_key (json_t *json); - - -/** - * Convert JSON to RSA signature. - * - * @param json JSON encoding to convert - * @return corresponding signature - */ -struct GNUNET_CRYPTO_rsa_Signature * -TALER_json_to_rsa_signature (json_t *json); +struct GNUNET_JSON_Specification +TALER_JSON_spec_amount (const char *name, + struct TALER_Amount *r_amount); /** @@ -149,22 +65,9 @@ TALER_json_to_rsa_signature (json_t *json); * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int -TALER_hash_json (json_t *json, +TALER_JSON_hash (json_t *json, struct GNUNET_HashCode *hc); - -/** - * Check if the given wire format JSON object is correctly formatted - * - * @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 **allowed, - const json_t *wire); - - -#endif /* TALER_json_LIB_H_ */ +#endif /* TALER_JSON_LIB_H_ */ /* End of taler_json_lib.h */ diff --git a/src/include/taler_pq_lib.h b/src/include/taler_pq_lib.h index 49e067846..dfcea30e1 100644 --- a/src/include/taler_pq_lib.h +++ b/src/include/taler_pq_lib.h @@ -24,6 +24,7 @@ #define TALER_PQ_LIB_H_ #include <libpq-fe.h> +#include <jansson.h> #include <gnunet/gnunet_pq_lib.h> #include "taler_util.h" diff --git a/src/include/taler_util.h b/src/include/taler_util.h index 380901812..f0da795a4 100644 --- a/src/include/taler_util.h +++ b/src/include/taler_util.h @@ -24,8 +24,6 @@ #include <gnunet/gnunet_util_lib.h> #include "taler_amount_lib.h" #include "taler_crypto_lib.h" -#include "taler_json_lib.h" - /* Define logging functions */ @@ -98,30 +96,6 @@ TALER_b2s (const void *buf, /** - * Round a time value so that it is suitable for transmission - * via JSON encodings. - * - * @param at time to round - * @return #GNUNET_OK if time was already rounded, #GNUNET_NO if - * it was just now rounded - */ -int -TALER_round_abs_time (struct GNUNET_TIME_Absolute *at); - - -/** - * Round a time value so that it is suitable for transmission - * via JSON encodings. - * - * @param rt time to round - * @return #GNUNET_OK if time was already rounded, #GNUNET_NO if - * it was just now rounded - */ -int -TALER_round_rel_time (struct GNUNET_TIME_Relative *rt); - - -/** * Load configuration by parsing all configuration * files in the given directory. * diff --git a/src/include/taler_wire_plugin.h b/src/include/taler_wire_plugin.h index 8fb194c57..c80aa2e49 100644 --- a/src/include/taler_wire_plugin.h +++ b/src/include/taler_wire_plugin.h @@ -101,11 +101,15 @@ struct TALER_WIRE_Plugin /** * Check if the given wire format JSON object is correctly formatted * + * @param cls the @e cls of this struct with the plugin-specific state * @param wire the JSON wire format object + * @param master_pub public key of the exchange to verify against * @return #GNUNET_YES if correctly formatted; #GNUNET_NO if not */ int - (*wire_validate) (const json_t *wire); + (*wire_validate) (void *cls, + const json_t *wire, + const struct TALER_MasterPublicKeyP *master_pub); /** diff --git a/src/json/Makefile.am b/src/json/Makefile.am new file mode 100644 index 000000000..6f71b8718 --- /dev/null +++ b/src/json/Makefile.am @@ -0,0 +1,38 @@ +# This Makefile.am is in the public domain +AM_CPPFLAGS = -I$(top_srcdir)/src/include + +if USE_COVERAGE + AM_CFLAGS = --coverage -O0 + XLIB = -lgcov +endif + +lib_LTLIBRARIES = \ + libtalerjson.la + +libtalerjson_la_SOURCES = \ + json.c \ + json_helper.c +libtalerjson_la_LDFLAGS = \ + -version-info 0:0:0 \ + -export-dynamic -no-undefined +libtalerjson_la_LIBADD = \ + -lgnunetjson \ + $(top_builddir)/src/util/libtalerutil.la \ + -lgnunetutil \ + -ljansson \ + $(XLIB) + +TESTS = \ + test_json + +check_PROGRAMS= \ + test_json + +test_json_SOURCES = \ + test_json.c +test_json_LDADD = \ + -ltalerjson \ + -lgnunetjson \ + $(top_builddir)/src/util/libtalerutil.la \ + -lgnunetutil \ + -ljansson diff --git a/src/json/json.c b/src/json/json.c new file mode 100644 index 000000000..1fbc59a73 --- /dev/null +++ b/src/json/json.c @@ -0,0 +1,53 @@ +/* + This file is part of TALER + Copyright (C) 2014, 2015, 2016 GNUnet e.V. + + 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 <http://www.gnu.org/licenses/> +*/ +/** + * @file json/json.c + * @brief helper functions for JSON processing using libjansson + * @author Sree Harsha Totakura <sreeharsha@totakura.in> + */ +#include "platform.h" +#include <gnunet/gnunet_util_lib.h> +#include "taler_util.h" +#include "taler_json_lib.h" + + +/** + * Hash a JSON for binary signing. + * + * @param[in] json some JSON value + * @param[out] hc resulting hash code + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ +int +TALER_JSON_hash (json_t *json, + struct GNUNET_HashCode *hc) +{ + char *wire_enc; + size_t len; + + if (NULL == (wire_enc = json_dumps (json, + JSON_COMPACT | JSON_SORT_KEYS))) + return GNUNET_SYSERR; + len = strlen (wire_enc) + 1; + GNUNET_CRYPTO_hash (wire_enc, + len, + hc); + free (wire_enc); + return GNUNET_OK; +} + + +/* End of json/json.c */ diff --git a/src/json/json_helper.c b/src/json/json_helper.c new file mode 100644 index 000000000..b61fe21a6 --- /dev/null +++ b/src/json/json_helper.c @@ -0,0 +1,146 @@ +/* + This file is part of TALER + Copyright (C) 2014, 2015, 2016 GNUnet e.V. + + 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 <http://www.gnu.org/licenses/> +*/ +/** + * @file json/json_helper.c + * @brief helper functions to generate specifications to parse + * Taler-specific JSON objects with libgnunetjson + * @author Sree Harsha Totakura <sreeharsha@totakura.in> + * @author Christian Grothoff + */ +#include "platform.h" +#include <gnunet/gnunet_util_lib.h> +#include "taler_util.h" +#include "taler_json_lib.h" + + +/** + * Convert a TALER amount to a JSON object. + * + * @param amount the amount + * @return a json object describing the amount + */ +json_t * +TALER_JSON_from_amount (const struct TALER_Amount *amount) +{ + json_t *j; + + if ( (amount->value != (uint64_t) ((json_int_t) amount->value)) || + (0 > ((json_int_t) amount->value)) ) + { + /* Theoretically, json_int_t can be a 32-bit "long", or we might + have a 64-bit value which converted to a 63-bit signed long + long causes problems here. So we check. Note that depending + on the platform, the compiler may be able to statically tell + that at least the first check is always false. */ + GNUNET_break (0); + return NULL; + } + j = json_pack ("{s:s, s:I, s:I}", + "currency", amount->currency, + "value", (json_int_t) amount->value, + "fraction", (json_int_t) amount->fraction); + GNUNET_assert (NULL != j); + return j; +} + + +/** + * Parse given JSON object to Amount + * + * @param cls closure, NULL + * @param root the json object representing data + * @param[out] spec where to write the data + * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error + */ +static int +parse_amount (void *cls, + json_t *root, + struct GNUNET_JSON_Specification *spec) +{ + struct TALER_Amount *r_amount = spec->ptr; + json_int_t value; + json_int_t fraction; + const char *currency; + + memset (r_amount, + 0, + sizeof (struct TALER_Amount)); + if (0 != json_unpack (root, + "{s:I, s:I, s:s}", + "value", &value, + "fraction", &fraction, + "currency", ¤cy)) + { + char *json_enc; + + if (NULL == (json_enc = json_dumps (root, + JSON_COMPACT | JSON_ENCODE_ANY))) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Malformed JSON amount: %s\n", + json_enc); + free (json_enc); + return GNUNET_SYSERR; + } + if ( (value < 0) || + (fraction < 0) || + (value > UINT64_MAX) || + (fraction > UINT32_MAX) ) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if (strlen (currency) >= TALER_CURRENCY_LEN) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + r_amount->value = (uint64_t) value; + r_amount->fraction = (uint32_t) fraction; + strcpy (r_amount->currency, currency); + (void) TALER_amount_normalize (r_amount); + return GNUNET_OK; +} + + + +/** + * Provide specification to parse given JSON object to an amount. + * + * @param name name of the amount field in the JSON + * @param[out] r_amount where the amount has to be written + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_amount (const char *name, + struct TALER_Amount *r_amount) +{ + struct GNUNET_JSON_Specification ret = { + .parser = &parse_amount, + .cleaner = NULL, + .cls = NULL, + .field = name, + .ptr = r_amount, + .ptr_size = 0, + .size_ptr = NULL + }; + return ret; +} + + +/* end of json/json_helper.c */ diff --git a/src/json/test_json.c b/src/json/test_json.c new file mode 100644 index 000000000..9f42dbd34 --- /dev/null +++ b/src/json/test_json.c @@ -0,0 +1,71 @@ +/* + This file is part of TALER + (C) 2015, 2016 GNUnet e.V. and Inria + + 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 <http://www.gnu.org/licenses/> +*/ + +/** + * @file json/test_json.c + * @brief Tests for Taler-specific crypto logic + * @author Christian Grothoff <christian@grothoff.org> + */ +#include "platform.h" +#include "taler_util.h" +#include "taler_json_lib.h" + + +/** + * Test amount conversion from/to JSON. + * + * @return 0 on success + */ +static int +test_amount () +{ + json_t *j; + struct TALER_Amount a1; + struct TALER_Amount a2; + struct GNUNET_JSON_Specification spec[] = { + TALER_JSON_spec_amount (NULL, &a2), + GNUNET_JSON_spec_end() + }; + + GNUNET_assert (GNUNET_OK == + TALER_string_to_amount ("EUR:4.3", + &a1)); + j = TALER_JSON_from_amount (&a1); + GNUNET_assert (NULL != j); + GNUNET_assert (GNUNET_OK == + GNUNET_JSON_parse (j, spec, + NULL, NULL)); + GNUNET_assert (0 == + TALER_amount_cmp (&a1, + &a2)); + json_decref (j); + return 0; +} + + +int +main(int argc, + const char *const argv[]) +{ + GNUNET_log_setup ("test-json", + "WARNING", + NULL); + if (0 != test_amount ()) + return 1; + return 0; +} + +/* end of test_json.c */ diff --git a/src/pq/pq_result_helper.c b/src/pq/pq_result_helper.c index 748ce0c29..49d0668a0 100644 --- a/src/pq/pq_result_helper.c +++ b/src/pq/pq_result_helper.c @@ -72,7 +72,7 @@ extract_amount_nbo_helper (PGresult *result, frac_name); curr_num = PQfnumber (result, curr_name); - if (val_num < 0) + if (val_num < 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Field `%s' does not exist in result\n", @@ -140,7 +140,7 @@ extract_amount_nbo_helper (PGresult *result, * #GNUNET_YES if all results could be extracted * #GNUNET_NO if at least one result was NULL * #GNUNET_SYSERR if a result was invalid (non-existing field) - */ + */ static int extract_amount_nbo (void *cls, PGresult *result, @@ -153,7 +153,7 @@ extract_amount_nbo (void *cls, char *frac_name; char *curr_name; int ret; - + GNUNET_asprintf (&val_name, "%s_val", fname); @@ -189,7 +189,7 @@ TALER_PQ_result_spec_amount_nbo (const char *name, { struct GNUNET_PQ_ResultSpec res = { &extract_amount_nbo, NULL, NULL, - (void *) amount, sizeof (*amount), + (void *) amount, sizeof (*amount), name, NULL }; return res; } @@ -208,7 +208,7 @@ TALER_PQ_result_spec_amount_nbo (const char *name, * #GNUNET_YES if all results could be extracted * #GNUNET_NO if at least one result was NULL * #GNUNET_SYSERR if a result was invalid (non-existing field) - */ + */ static int extract_amount (void *cls, PGresult *result, @@ -223,7 +223,7 @@ extract_amount (void *cls, char *curr_name; struct TALER_AmountNBO amount_nbo; int ret; - + GNUNET_asprintf (&val_name, "%s_val", fname); @@ -280,7 +280,7 @@ TALER_PQ_result_spec_amount (const char *name, * #GNUNET_YES if all results could be extracted * #GNUNET_NO if at least one result was NULL * #GNUNET_SYSERR if a result was invalid (non-existing field) - */ + */ static int extract_json (void *cls, PGresult *result, @@ -294,7 +294,7 @@ extract_json (void *cls, int fnum; json_error_t json_error; size_t slen; - + fnum = PQfnumber (result, fname); if (fnum < 0) @@ -320,10 +320,11 @@ extract_json (void *cls, &json_error); if (NULL == *j_dst) { - TALER_json_warn (json_error); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to parse JSON result for field `%s'\n", - fname); + "Failed to parse JSON result for field `%s': %s (%s)\n", + fname, + json_error.text, + json_error.source); return GNUNET_SYSERR; } return GNUNET_OK; @@ -364,7 +365,7 @@ TALER_PQ_result_spec_json (const char *name, { struct GNUNET_PQ_ResultSpec res = { &extract_json, &clean_json, NULL, - (void *) jp, 0, + (void *) jp, 0, name, NULL }; return res; } diff --git a/src/util/Makefile.am b/src/util/Makefile.am index 8efc3987a..41afcc97f 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -1,5 +1,5 @@ # This Makefile.am is in the public domain -AM_CPPFLAGS = -I$(top_srcdir)/src/include $(LIBGCRYPT_CFLAGS) $(POSTGRESQL_CPPFLAGS) +AM_CPPFLAGS = -I$(top_srcdir)/src/include $(LIBGCRYPT_CFLAGS) if USE_COVERAGE AM_CFLAGS = --coverage -O0 @@ -31,15 +31,12 @@ libtalerutil_la_SOURCES = \ amount.c \ crypto.c \ util.c \ - json.c \ os_installation.c \ - plugin.c \ - wireformats.c + plugin.c libtalerutil_la_LIBADD = \ -lgnunetutil \ $(LIBGCRYPT_LIBS) \ - -ljansson \ -lmicrohttpd $(XLIB) libtalerutil_la_LDFLAGS = \ @@ -48,13 +45,11 @@ libtalerutil_la_LDFLAGS = \ TESTS = \ test_amount \ - test_crypto \ - test_json + test_crypto check_PROGRAMS= \ test_amount \ - test_crypto \ - test_json + test_crypto test_amount_SOURCES = \ @@ -68,10 +63,3 @@ test_crypto_SOURCES = \ test_crypto_LDADD = \ -lgnunetutil \ libtalerutil.la - -test_json_SOURCES = \ - test_json.c -test_json_LDADD = \ - -lgnunetutil \ - -ljansson \ - libtalerutil.la diff --git a/src/util/json.c b/src/util/json.c deleted file mode 100644 index 6aca7548c..000000000 --- a/src/util/json.c +++ /dev/null @@ -1,400 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014, 2015 GNUnet e.V. - - 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 <http://www.gnu.org/licenses/> -*/ -/** - * @file util/json.c - * @brief helper functions for JSON processing using libjansson - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ -#include "platform.h" -#if HAVE_GNUNET_GNUNET_UTIL_TALER_WALLET_LIB_H -#include <gnunet/gnunet_util_taler_wallet_lib.h> -#endif -#if HAVE_GNUNET_GNUNET_UTIL_LIB_H -#include <gnunet/gnunet_util_lib.h> -#endif -#include "taler_util.h" - -/** - * Shorthand for exit jumps. - */ -#define EXITIF(cond) \ - do { \ - if (cond) { GNUNET_break (0); goto EXITIF_exit; } \ - } while (0) - -/** - * Shorthand for JSON parsing related exit jumps. - */ -#define UNPACK_EXITIF(cond) \ - do { \ - if (cond) { TALER_json_warn (error); goto EXITIF_exit; } \ - } while (0) - - -/** - * Convert a TALER amount to a JSON - * object. - * - * @param amount the amount - * @return a json object describing the amount - */ -json_t * -TALER_json_from_amount (const struct TALER_Amount *amount) -{ - json_t *j; - - if ( (amount->value != (uint64_t) ((json_int_t) amount->value)) || - (0 > ((json_int_t) amount->value)) ) - { - /* Theoretically, json_int_t can be a 32-bit "long", or we might - have a 64-bit value which converted to a 63-bit signed long - long causes problems here. So we check. Note that depending - on the platform, the compiler may be able to statically tell - that at least the first check is always false. */ - GNUNET_break (0); - return NULL; - } - j = json_pack ("{s:s, s:I, s:I}", - "currency", amount->currency, - "value", (json_int_t) amount->value, - "fraction", (json_int_t) amount->fraction); - GNUNET_assert (NULL != j); - return j; -} - - -/** - * Convert absolute timestamp to a json string. - * - * @param stamp the time stamp - * @return a json string with the timestamp in @a stamp - */ -json_t * -TALER_json_from_abs (struct GNUNET_TIME_Absolute stamp) -{ - json_t *j; - char *mystr; - int ret; - - GNUNET_assert (GNUNET_OK == - TALER_round_abs_time (&stamp)); - if (stamp.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) - return json_string ("/never/"); - ret = GNUNET_asprintf (&mystr, - "/Date(%llu)/", - (unsigned long long) (stamp.abs_value_us / (1000LL * 1000LL))); - GNUNET_assert (ret > 0); - j = json_string (mystr); - GNUNET_free (mystr); - return j; -} - - -/** - * Convert RSA public key to JSON. - * - * @param pk public key to convert - * @return corresponding JSON encoding - */ -json_t * -TALER_json_from_rsa_public_key (struct GNUNET_CRYPTO_rsa_PublicKey *pk) -{ - char *buf; - size_t buf_len; - json_t *ret; - - buf_len = GNUNET_CRYPTO_rsa_public_key_encode (pk, - &buf); - ret = TALER_json_from_data (buf, - buf_len); - GNUNET_free (buf); - return ret; -} - - -/** - * Convert JSON to RSA public key. - * - * @param json JSON encoding to convert - * @return corresponding public key - */ -struct GNUNET_CRYPTO_rsa_PublicKey * -TALER_json_to_rsa_public_key (json_t *json) -{ - const char *enc; - char *buf; - size_t len; - size_t buf_len; - struct GNUNET_CRYPTO_rsa_PublicKey *pk; - - buf = NULL; - EXITIF (NULL == (enc = json_string_value (json))); - len = strlen (enc); - buf_len = (len * 5) / 8; - buf = GNUNET_malloc (buf_len); - EXITIF (GNUNET_OK != - GNUNET_STRINGS_string_to_data (enc, - len, - buf, - buf_len)); - EXITIF (NULL == (pk = GNUNET_CRYPTO_rsa_public_key_decode (buf, - buf_len))); - GNUNET_free (buf); - return pk; - EXITIF_exit: - GNUNET_free_non_null (buf); - return NULL; -} - - -/** - * Convert JSON to RSA signature. - * - * @param json JSON encoding to convert - * @return corresponding signature - */ -struct GNUNET_CRYPTO_rsa_Signature * -TALER_json_to_rsa_signature (json_t *json) -{ - const char *enc; - char *buf; - size_t len; - size_t buf_len; - struct GNUNET_CRYPTO_rsa_Signature *sig; - - buf = NULL; - EXITIF (NULL == (enc = json_string_value (json))); - len = strlen (enc); - buf_len = (len * 5) / 8; - buf = GNUNET_malloc (buf_len); - EXITIF (GNUNET_OK != - GNUNET_STRINGS_string_to_data (enc, - len, - buf, - buf_len)); - EXITIF (NULL == (sig = GNUNET_CRYPTO_rsa_signature_decode (buf, - buf_len))); - GNUNET_free (buf); - return sig; - EXITIF_exit: - GNUNET_free_non_null (buf); - return NULL; -} - - -/** - * Convert RSA signature to JSON. - * - * @param sig signature to convert - * @return corresponding JSON encoding - */ -json_t * -TALER_json_from_rsa_signature (struct GNUNET_CRYPTO_rsa_Signature *sig) -{ - char *buf; - size_t buf_len; - json_t *ret; - - buf_len = GNUNET_CRYPTO_rsa_signature_encode (sig, - &buf); - ret = TALER_json_from_data (buf, - buf_len); - GNUNET_free (buf); - return ret; -} - - -/** - * Convert binary data to a JSON string - * with the base32crockford encoding. - * - * @param data binary data - * @param size size of @a data in bytes - * @return json string that encodes @a data - */ -json_t * -TALER_json_from_data (const void *data, - size_t size) -{ - char *buf; - json_t *json; - - buf = GNUNET_STRINGS_data_to_string_alloc (data, size); - json = json_string (buf); - GNUNET_free (buf); - return json; -} - - -/** - * Parse given JSON object to Amount - * - * @param json the json object representing Amount - * @param[out] r_amount where the amount has to be written - * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error - */ -int -TALER_json_to_amount (json_t *json, - struct TALER_Amount *r_amount) -{ - json_int_t value; - json_int_t fraction; - const char *currency; - - memset (r_amount, - 0, - sizeof (struct TALER_Amount)); - if (0 != json_unpack (json, - "{s:I, s:I, s:s}", - "value", &value, - "fraction", &fraction, - "currency", ¤cy)) - { - char *json_enc; - - if (NULL == (json_enc = json_dumps (json, - JSON_COMPACT | JSON_ENCODE_ANY))) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Malformed JSON amount: %s\n", - json_enc); - free (json_enc); - return GNUNET_SYSERR; - } - if ( (value < 0) || - (fraction < 0) || - (value > UINT64_MAX) || - (fraction > UINT32_MAX) ) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if (strlen (currency) >= TALER_CURRENCY_LEN) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - r_amount->value = (uint64_t) value; - r_amount->fraction = (uint32_t) fraction; - strcpy (r_amount->currency, currency); - (void) TALER_amount_normalize (r_amount); - return GNUNET_OK; -} - - -/** - * Parse given JSON object to absolute time. - * - * @param json the json object representing Amount - * @param[out] abs where the amount has to be written - * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error - */ -int -TALER_json_to_abs (json_t *json, - struct GNUNET_TIME_Absolute *abs) -{ - const char *val; - unsigned long long int tval; - - val = json_string_value (json); - if (NULL == val) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if ( (0 == strcasecmp (val, - "/forever/")) || - (0 == strcasecmp (val, - "/never/")) ) - { - *abs = GNUNET_TIME_UNIT_FOREVER_ABS; - return GNUNET_OK; - } - if (1 != sscanf (val, - "/Date(%llu)/", - &tval)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - /* Time is in seconds in JSON, but in microseconds in GNUNET_TIME_Absolute */ - abs->abs_value_us = tval * 1000LL * 1000LL; - if ( (abs->abs_value_us) / 1000LL / 1000LL != tval) - { - /* Integer overflow */ - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -/** - * Parse given JSON object to data - * - * @param json the json object representing data - * @param out the pointer to hold the parsed data. - * @param out_size the size of @a out - * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error - */ -int -TALER_json_to_data (json_t *json, - void *out, - size_t out_size) -{ - const char *enc; - unsigned int len; - - EXITIF (NULL == (enc = json_string_value (json))); - len = strlen (enc); - EXITIF (((len * 5) / 8) != out_size); - EXITIF (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, len, out, out_size)); - return GNUNET_OK; - EXITIF_exit: - return GNUNET_SYSERR; -} - - -/** - * Hash a JSON for binary signing. - * - * @param[in] json some JSON value - * @param[out] hc resulting hash code - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - */ -int -TALER_hash_json (json_t *json, - struct GNUNET_HashCode *hc) -{ - char *wire_enc; - size_t len; - - if (NULL == (wire_enc = json_dumps (json, - JSON_COMPACT | JSON_SORT_KEYS))) - return GNUNET_SYSERR; - len = strlen (wire_enc) + 1; - GNUNET_CRYPTO_hash (wire_enc, - len, - hc); - free (wire_enc); - return GNUNET_OK; -} - - -/* End of util/json.c */ diff --git a/src/util/test_json.c b/src/util/test_json.c deleted file mode 100644 index 5e2f50fe8..000000000 --- a/src/util/test_json.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - This file is part of TALER - (C) 2015 GNUnet e.V. - - 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 <http://www.gnu.org/licenses/> -*/ - -/** - * @file util/test_json.c - * @brief Tests for Taler-specific crypto logic - * @author Christian Grothoff <christian@grothoff.org> - */ -#include "platform.h" -#include "taler_util.h" -#include "taler_json_lib.h" - - -/** - * Test amount conversion from/to JSON. - * - * @return 0 on success - */ -static int -test_amount () -{ - json_t *j; - struct TALER_Amount a1; - struct TALER_Amount a2; - - GNUNET_assert (GNUNET_OK == - TALER_string_to_amount ("EUR:4.3", - &a1)); - j = TALER_json_from_amount (&a1); - GNUNET_assert (NULL != j); - GNUNET_assert (GNUNET_OK == - TALER_json_to_amount (j, - &a2)); - GNUNET_assert (0 == - TALER_amount_cmp (&a1, - &a2)); - json_decref (j); - return 0; -} - - -/** - * Test time conversion from/to JSON. - * - * @return 0 on success - */ -static int -test_time () -{ - json_t *j; - struct GNUNET_TIME_Absolute a1; - struct GNUNET_TIME_Absolute a2; - - a1 = GNUNET_TIME_absolute_get (); - TALER_round_abs_time (&a1); - j = TALER_json_from_abs (a1); - GNUNET_assert (NULL != j); - GNUNET_assert (GNUNET_OK == - TALER_json_to_abs (j, - &a2)); - GNUNET_assert (a1.abs_value_us == - a2.abs_value_us); - json_decref (j); - - a1 = GNUNET_TIME_UNIT_FOREVER_ABS; - j = TALER_json_from_abs (a1); - GNUNET_assert (NULL != j); - GNUNET_assert (GNUNET_OK == - TALER_json_to_abs (j, - &a2)); - GNUNET_assert (a1.abs_value_us == - a2.abs_value_us); - json_decref (j); - return 0; -} - - -/** - * Test raw (binary) conversion from/to JSON. - * - * @return 0 on success - */ -static int -test_raw () -{ - char blob[256]; - char blob2[256]; - unsigned int i; - json_t *j; - - for (i=0;i<=256;i++) - { - memset (blob, i, i); - j = TALER_json_from_data (blob, i); - GNUNET_assert (NULL != j); - GNUNET_assert (GNUNET_OK == - TALER_json_to_data (j, - blob2, - i)); - GNUNET_assert (0 == - memcmp (blob, - blob2, - i)); - } - return 0; -} - - -/** - * Test rsa conversions from/to JSON. - * - * @return 0 on success - */ -static int -test_rsa () -{ - struct GNUNET_CRYPTO_rsa_PublicKey *pub; - struct GNUNET_CRYPTO_rsa_PublicKey *pub2; - struct GNUNET_CRYPTO_rsa_Signature *sig; - struct GNUNET_CRYPTO_rsa_Signature *sig2; - struct GNUNET_CRYPTO_rsa_PrivateKey *priv; - char msg[] = "Hello"; - json_t *jp; - json_t *js; - - priv = GNUNET_CRYPTO_rsa_private_key_create (1024); - pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv); - sig = GNUNET_CRYPTO_rsa_sign (priv, - msg, - sizeof (msg)); - GNUNET_assert (NULL != (jp = TALER_json_from_rsa_public_key (pub))); - GNUNET_assert (NULL != (js = TALER_json_from_rsa_signature (sig))); - GNUNET_assert (NULL != (pub2 = TALER_json_to_rsa_public_key (jp))); - GNUNET_assert (NULL != (sig2 = TALER_json_to_rsa_signature (js))); - GNUNET_break (0 == - GNUNET_CRYPTO_rsa_signature_cmp (sig, - sig2)); - GNUNET_break (0 == - GNUNET_CRYPTO_rsa_public_key_cmp (pub, - pub2)); - GNUNET_CRYPTO_rsa_signature_free (sig); - GNUNET_CRYPTO_rsa_signature_free (sig2); - GNUNET_CRYPTO_rsa_private_key_free (priv); - GNUNET_CRYPTO_rsa_public_key_free (pub); - GNUNET_CRYPTO_rsa_public_key_free (pub2); - return 0; -} - - -int -main(int argc, - const char *const argv[]) -{ - GNUNET_log_setup ("test-json", - "WARNING", - NULL); - if (0 != test_amount ()) - return 1; - if (0 != test_time ()) - return 1; - if (0 != test_raw ()) - return 1; - if (0 != test_rsa ()) - return 1; - /* FIXME: test EdDSA signature conversion... */ - return 0; -} - -/* end of test_json.c */ diff --git a/src/util/util.c b/src/util/util.c index addafacf7..6dcd0dc29 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -56,7 +56,7 @@ TALER_b2s (const void *buf, GNUNET_free (tmp); ret[8] = '\0'; return ret; -} +} /** @@ -90,46 +90,6 @@ TALER_config_get_denom (struct GNUNET_CONFIGURATION_Handle *cfg, /** - * Round a time value so that it is suitable for transmission - * via JSON encodings. - * - * @param at time to round - * @return #GNUNET_OK if time was already rounded, #GNUNET_NO if - * it was just now rounded - */ -int -TALER_round_abs_time (struct GNUNET_TIME_Absolute *at) -{ - if (at->abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) - return GNUNET_OK; - if (0 == at->abs_value_us % 1000000) - return GNUNET_OK; - at->abs_value_us -= at->abs_value_us % 1000000; - return GNUNET_NO; -} - - -/** - * Round a time value so that it is suitable for transmission - * via JSON encodings. - * - * @param rt time to round - * @return #GNUNET_OK if time was already rounded, #GNUNET_NO if - * it was just now rounded - */ -int -TALER_round_rel_time (struct GNUNET_TIME_Relative *rt) -{ - if (rt->rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) - return GNUNET_OK; - if (0 == rt->rel_value_us % 1000000) - return GNUNET_OK; - rt->rel_value_us -= rt->rel_value_us % 1000000; - return GNUNET_NO; -} - - -/** * Load configuration by parsing all configuration * files in the given directory. * diff --git a/src/util/wireformats.c b/src/util/wireformats.c deleted file mode 100644 index a69e8a093..000000000 --- a/src/util/wireformats.c +++ /dev/null @@ -1,441 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014, 2015 GNUnet e.V. - - 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 <http://www.gnu.org/licenses/> -*/ -/** - * @file util/wireformats.c - * @brief helper functions for JSON processing using libjansson - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - * @author Christian Grothoff - */ -#include "platform.h" -#include <gnunet/gnunet_util_lib.h> -#include "taler_util.h" - -/** - * Shorthand for exit jumps. - */ -#define EXITIF(cond) \ - do { \ - if (cond) { GNUNET_break (0); goto EXITIF_exit; } \ - } while (0) - -/** - * Shorthand for JSON parsing related exit jumps. - */ -#define UNPACK_EXITIF(cond) \ - do { \ - if (cond) { TALER_json_warn (error); goto EXITIF_exit; } \ - } while (0) - - -/* Taken from GNU gettext */ - -/** - * Entry in the country table. - */ -struct table_entry -{ - /** - * 2-Character international country code. - */ - const char *code; - - /** - * Long English name of the country. - */ - const char *english; -}; - -/* Keep the following table in sync with gettext. - WARNING: the entries should stay sorted according to the code */ -/** - * List of country codes. - */ -static const struct table_entry country_table[] = - { - { "AE", "U.A.E." }, - { "AF", "Afghanistan" }, - { "AL", "Albania" }, - { "AM", "Armenia" }, - { "AN", "Netherlands Antilles" }, - { "AR", "Argentina" }, - { "AT", "Austria" }, - { "AU", "Australia" }, - { "AZ", "Azerbaijan" }, - { "BA", "Bosnia and Herzegovina" }, - { "BD", "Bangladesh" }, - { "BE", "Belgium" }, - { "BG", "Bulgaria" }, - { "BH", "Bahrain" }, - { "BN", "Brunei Darussalam" }, - { "BO", "Bolivia" }, - { "BR", "Brazil" }, - { "BT", "Bhutan" }, - { "BY", "Belarus" }, - { "BZ", "Belize" }, - { "CA", "Canada" }, - { "CG", "Congo" }, - { "CH", "Switzerland" }, - { "CI", "Cote d'Ivoire" }, - { "CL", "Chile" }, - { "CM", "Cameroon" }, - { "CN", "People's Republic of China" }, - { "CO", "Colombia" }, - { "CR", "Costa Rica" }, - { "CS", "Serbia and Montenegro" }, - { "CZ", "Czech Republic" }, - { "DE", "Germany" }, - { "DK", "Denmark" }, - { "DO", "Dominican Republic" }, - { "DZ", "Algeria" }, - { "EC", "Ecuador" }, - { "EE", "Estonia" }, - { "EG", "Egypt" }, - { "ER", "Eritrea" }, - { "ES", "Spain" }, - { "ET", "Ethiopia" }, - { "FI", "Finland" }, - { "FO", "Faroe Islands" }, - { "FR", "France" }, - { "GB", "United Kingdom" }, - { "GD", "Caribbean" }, - { "GE", "Georgia" }, - { "GL", "Greenland" }, - { "GR", "Greece" }, - { "GT", "Guatemala" }, - { "HK", "Hong Kong" }, - { "HK", "Hong Kong S.A.R." }, - { "HN", "Honduras" }, - { "HR", "Croatia" }, - { "HT", "Haiti" }, - { "HU", "Hungary" }, - { "ID", "Indonesia" }, - { "IE", "Ireland" }, - { "IL", "Israel" }, - { "IN", "India" }, - { "IQ", "Iraq" }, - { "IR", "Iran" }, - { "IS", "Iceland" }, - { "IT", "Italy" }, - { "JM", "Jamaica" }, - { "JO", "Jordan" }, - { "JP", "Japan" }, - { "KE", "Kenya" }, - { "KG", "Kyrgyzstan" }, - { "KH", "Cambodia" }, - { "KR", "South Korea" }, - { "KW", "Kuwait" }, - { "KZ", "Kazakhstan" }, - { "LA", "Laos" }, - { "LB", "Lebanon" }, - { "LI", "Liechtenstein" }, - { "LK", "Sri Lanka" }, - { "LT", "Lithuania" }, - { "LU", "Luxembourg" }, - { "LV", "Latvia" }, - { "LY", "Libya" }, - { "MA", "Morocco" }, - { "MC", "Principality of Monaco" }, - { "MD", "Moldava" }, - { "MD", "Moldova" }, - { "ME", "Montenegro" }, - { "MK", "Former Yugoslav Republic of Macedonia" }, - { "ML", "Mali" }, - { "MM", "Myanmar" }, - { "MN", "Mongolia" }, - { "MO", "Macau S.A.R." }, - { "MT", "Malta" }, - { "MV", "Maldives" }, - { "MX", "Mexico" }, - { "MY", "Malaysia" }, - { "NG", "Nigeria" }, - { "NI", "Nicaragua" }, - { "NL", "Netherlands" }, - { "NO", "Norway" }, - { "NP", "Nepal" }, - { "NZ", "New Zealand" }, - { "OM", "Oman" }, - { "PA", "Panama" }, - { "PE", "Peru" }, - { "PH", "Philippines" }, - { "PK", "Islamic Republic of Pakistan" }, - { "PL", "Poland" }, - { "PR", "Puerto Rico" }, - { "PT", "Portugal" }, - { "PY", "Paraguay" }, - { "QA", "Qatar" }, - { "RE", "Reunion" }, - { "RO", "Romania" }, - { "RS", "Serbia" }, - { "RU", "Russia" }, - { "RW", "Rwanda" }, - { "SA", "Saudi Arabia" }, - { "SE", "Sweden" }, - { "SG", "Singapore" }, - { "SI", "Slovenia" }, - { "SK", "Slovak" }, - { "SN", "Senegal" }, - { "SO", "Somalia" }, - { "SR", "Suriname" }, - { "SV", "El Salvador" }, - { "SY", "Syria" }, - { "TH", "Thailand" }, - { "TJ", "Tajikistan" }, - { "TM", "Turkmenistan" }, - { "TN", "Tunisia" }, - { "TR", "Turkey" }, - { "TT", "Trinidad and Tobago" }, - { "TW", "Taiwan" }, - { "TZ", "Tanzania" }, - { "UA", "Ukraine" }, - { "US", "United States" }, - { "UY", "Uruguay" }, - { "VA", "Vatican" }, - { "VE", "Venezuela" }, - { "VN", "Viet Nam" }, - { "YE", "Yemen" }, - { "ZA", "South Africa" }, - { "ZW", "Zimbabwe" } - }; - - -/** - * Country code comparator function, for binary search with bsearch(). - * - * @param ptr1 pointer to a `struct table_entry` - * @param ptr2 pointer to a `struct table_entry` - * @return result of strncmp()'ing the 2-digit country codes of the entries - */ -static int -cmp_country_code (const void *ptr1, - const void *ptr2) -{ - const struct table_entry *cc1 = ptr1; - const struct table_entry *cc2 = ptr2; - - return strncmp (cc1->code, cc2->code, 2); -} - - -/** - * Validates given IBAN according to the European Banking Standards. See: - * http://www.europeanpaymentscouncil.eu/documents/ECBS%20IBAN%20standard%20EBS204_V3.2.pdf - * - * @param iban the IBAN number to validate - * @return #GNUNET_YES if correctly formatted; #GNUNET_NO if not - */ -static int -validate_iban (const char *iban) -{ - char cc[2]; - char ibancpy[35]; - struct table_entry cc_entry; - unsigned int len; - char *nbuf; - unsigned int i; - unsigned int j; - unsigned long long dividend; - unsigned long long remainder; - int nread; - int ret; - - len = strlen (iban); - if (len > 34) - return GNUNET_NO; - strncpy (cc, iban, 2); - strncpy (ibancpy, iban + 4, len - 4); - strncpy (ibancpy + len - 4, iban, 4); - ibancpy[len] = '\0'; - cc_entry.code = cc; - cc_entry.english = NULL; - if (NULL == - bsearch (&cc_entry, - country_table, - sizeof (country_table) / sizeof (struct table_entry), - sizeof (struct table_entry), - &cmp_country_code)) - return GNUNET_NO; - nbuf = GNUNET_malloc ((len * 2) + 1); - for (i=0, j=0; i < len; i++) - { - if (isalpha ((int) ibancpy[i])) - { - EXITIF(2 != snprintf(&nbuf[j], - 3, - "%2u", - (ibancpy[i] - 'A' + 10))); - j += 2; - continue; - } - nbuf[j] = ibancpy[i]; - j++; - } - for (j=0;'\0' != nbuf[j];j++) - GNUNET_assert (isdigit(nbuf[j])); - GNUNET_assert (sizeof(dividend) >= 8); - remainder = 0; - for (i=0; i<j; i+=16) - { - EXITIF (1 != - (ret = sscanf (&nbuf[i], - "%16llu %n", - ÷nd, - &nread))); - if (0 != remainder) - dividend += remainder * (pow (10, nread)); - remainder = dividend % 97; - } - if (1 == remainder) - { - GNUNET_free (nbuf); - return GNUNET_YES; - } - EXITIF_exit: - GNUNET_free (nbuf); - return GNUNET_NO; -} - - -/** - * Validate SEPA account details. - * - * @param wire JSON with the SEPA details - * @return #GNUNET_YES if correctly formatted; #GNUNET_NO if not - */ -static int -validate_sepa (const json_t *wire) -{ - json_error_t error; - const char *type; - const char *iban; - const char *name; - const char *bic; - uint64_t r; - const char *address; - - UNPACK_EXITIF (0 != json_unpack_ex - ((json_t *) wire, - &error, JSON_STRICT, - "{" - "s:s," /* TYPE: sepa */ - "s:s," /* IBAN: iban */ - "s:s," /* name: beneficiary name */ - "s:s," /* BIC: beneficiary bank's BIC */ - "s:i," /* r: random 64-bit integer nounce */ - "s:s" /* address: address of the beneficiary */ - "}", - "type", &type, - "IBAN", &iban, - "name", &name, - "bic", &bic, - "r", &r, - "address", &address)); - if (1 != validate_iban (iban)) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "IBAN `%s' invalid\n", - iban); - return GNUNET_NO; - } - return GNUNET_YES; - EXITIF_exit: - return GNUNET_NO; -} - - -/** - * Validate TEST account details. The "test" format is used - * for testing, so this validator does nothing. - * - * @param wire JSON with the TEST details - * @return #GNUNET_YES if correctly formatted; #GNUNET_NO if not - */ -static int -validate_test (const json_t *wire) -{ - return GNUNET_YES; -} - - -/** - * Handler for a wire format. - */ -struct FormatHandler -{ - /** - * Type handled by this format handler. - */ - const char *type; - - /** - * Function to call to evaluate the format. - * - * @param wire the JSON to evaluate - * @return #GNUNET_YES if correctly formatted; #GNUNET_NO if not - */ - int (*handler)(const json_t *wire); -}; - - -/** - * Check if the given wire format JSON object is correctly formatted - * - * @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 **allowed, - const json_t *wire) -{ - static const struct FormatHandler format_handlers[] = { - { "SEPA", &validate_sepa }, - { "TEST", &validate_test }, - { NULL, NULL} - }; - unsigned int i; - const char *stype; - json_error_t error; - - UNPACK_EXITIF (0 != json_unpack_ex - ((json_t *) wire, - &error, 0, - "{s:s}", - "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 exchange's allowed formats\n", - stype); - return GNUNET_NO; - } - - for (i=0;NULL != format_handlers[i].type;i++) - if (0 == strcasecmp (format_handlers[i].type, - stype)) - return format_handlers[i].handler (wire); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Wireformat `%s' not supported\n", - stype); - return GNUNET_NO; - EXITIF_exit: - return GNUNET_NO; -} - -/* end of wireformats.c */ diff --git a/src/wire/Makefile.am b/src/wire/Makefile.am index eb2e893fa..67a559a36 100644 --- a/src/wire/Makefile.am +++ b/src/wire/Makefile.am @@ -36,7 +36,9 @@ libtaler_plugin_wire_sepa_la_LIBADD = \ $(LTLIBINTL) libtaler_plugin_wire_sepa_la_LDFLAGS = \ $(TALER_PLUGIN_LDFLAGS) \ + $(top_builddir)/src/json/libtalerjson.la \ $(top_builddir)/src/util/libtalerutil.la \ + -lgnunetjson \ -lgnunetutil $(XLIB) @@ -75,4 +77,3 @@ test_sepa_wireformat_LDADD = \ -ljansson \ libtalerwire.la \ $(top_builddir)/src/util/libtalerutil.la - diff --git a/src/wire/plugin_wire_sepa.c b/src/wire/plugin_wire_sepa.c index 4d902f962..904afa9bf 100644 --- a/src/wire/plugin_wire_sepa.c +++ b/src/wire/plugin_wire_sepa.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2016 GNUnet e.V. + Copyright (C) 2016 GNUnet e.V. & Inria 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 @@ -23,6 +23,8 @@ */ #include "platform.h" #include "taler_wire_plugin.h" +#include "taler_signatures.h" +#include <gnunet/gnunet_json_lib.h> /** @@ -58,6 +60,8 @@ sepa_amount_round (void *cls, struct SepaClosure *sc = cls; uint32_t delta; + if (NULL == sc->currency) + return GNUNET_SYSERR; if (0 != strcasecmp (amount->currency, sc->currency)) { @@ -348,41 +352,115 @@ validate_iban (const char *iban) /** + * Verify that the signature in the @a json for /wire/sepa is valid. + * + * @param json json reply with the signature + * @param master_pub public key of the exchange to verify against + * @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 json_t *json, + const struct TALER_MasterPublicKeyP *master_pub) +{ + struct TALER_MasterSignatureP exchange_sig; + struct TALER_MasterWireSepaDetailsPS mp; + const char *receiver_name; + const char *iban; + const char *bic; + struct GNUNET_HashContext *hc; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_fixed_auto ("sig", &exchange_sig), + GNUNET_JSON_spec_string ("receiver_name", &receiver_name), + GNUNET_JSON_spec_string ("iban", &iban), + GNUNET_JSON_spec_string ("bic", &bic), + GNUNET_JSON_spec_end() + }; + + if (NULL == master_pub) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Skipping signature check as master public key not given\n"); + return GNUNET_OK; + } + if (GNUNET_OK != + GNUNET_JSON_parse (json, spec, + NULL, NULL)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + + 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, + &exchange_sig.eddsa_signature, + &master_pub->eddsa_pub)) + { + GNUNET_break_op (0); + GNUNET_JSON_parse_free (spec); + return GNUNET_SYSERR; + } + GNUNET_JSON_parse_free (spec); + return GNUNET_OK; +} + + +/** * Check if the given wire format JSON object is correctly formatted * + * @param cls the @e cls of this struct with the plugin-specific state * @param wire the JSON wire format object + * @param master_pub public key of the exchange to verify against * @return #GNUNET_YES if correctly formatted; #GNUNET_NO if not */ static int -sepa_wire_validate (const json_t *wire) +sepa_wire_validate (void *cls, + const json_t *wire, + const struct TALER_MasterPublicKeyP *master_pub) { json_error_t error; const char *type; const char *iban; const char *name; const char *bic; - uint64_t r; - const char *address; if (0 != json_unpack_ex ((json_t *) wire, - &error, JSON_STRICT, + &error, 0, "{" - "s:s," /* TYPE: sepa */ - "s:s," /* IBAN: iban */ - "s:s," /* name: beneficiary name */ - "s:s," /* BIC: beneficiary bank's BIC */ - "s:i," /* r: random 64-bit integer nounce */ - "s:s" /* address: address of the beneficiary */ + "s:s," /* type: sepa */ + "s:s," /* iban: IBAN */ + "s:s," /* receiver_name: beneficiary name */ + "s:s" /* bic: beneficiary bank's BIC */ "}", "type", &type, - "IBAN", &iban, - "name", &name, - "bic", &bic, - "r", &r, - "address", &address)) + "iban", &iban, + "receiver_name", &name, + "bic", &bic)) { - TALER_json_warn (error); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "JSON parsing failed at %s:%u: %s (%s)\n", + __FILE__, __LINE__, + error.text, error.source); + json_dumpf (wire, stderr, 0); + fprintf (stderr, "\n"); return GNUNET_SYSERR; } if (0 != strcasecmp (type, @@ -400,6 +478,15 @@ sepa_wire_validate (const json_t *wire) iban); return GNUNET_NO; } + /* FIXME: don't parse again, integrate properly... */ + if (GNUNET_OK != + verify_wire_sepa_signature_ok (wire, + master_pub)) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Signature invalid\n"); + return GNUNET_NO; + } return GNUNET_YES; } @@ -499,19 +586,21 @@ libtaler_plugin_wire_sepa_init (void *cls) struct TALER_WIRE_Plugin *plugin; sc = GNUNET_new (struct SepaClosure); - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, - "exchange", - "CURRENCY", - &sc->currency)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "exchange", - "CURRENCY"); - GNUNET_free (sc); - return NULL; - } - + if (NULL != cfg) + { + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + "exchange", + "CURRENCY", + &sc->currency)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "exchange", + "CURRENCY"); + GNUNET_free (sc); + return NULL; + } + } plugin = GNUNET_new (struct TALER_WIRE_Plugin); plugin->cls = sc; plugin->amount_round = &sepa_amount_round; @@ -536,7 +625,7 @@ libtaler_plugin_wire_sepa_done (void *cls) struct TALER_WIRE_Plugin *plugin = cls; struct SepaClosure *sc = plugin->cls; - GNUNET_free (sc->currency); + GNUNET_free_non_null (sc->currency); GNUNET_free (sc); GNUNET_free (plugin); return NULL; diff --git a/src/wire/plugin_wire_template.c b/src/wire/plugin_wire_template.c index 2e9512e57..91b380c38 100644 --- a/src/wire/plugin_wire_template.c +++ b/src/wire/plugin_wire_template.c @@ -76,11 +76,15 @@ template_amount_round (void *cls, /** * Check if the given wire format JSON object is correctly formatted * + * @param cls the @e cls of this struct with the plugin-specific state * @param wire the JSON wire format object + * @param master_pub public key of the exchange to verify against * @return #GNUNET_YES if correctly formatted; #GNUNET_NO if not */ static int -template_wire_validate (const json_t *wire) +template_wire_validate (void *cls, + const json_t *wire, + const struct TALER_MasterPublicKeyP *master_pub) { GNUNET_break (0); return GNUNET_SYSERR; diff --git a/src/wire/plugin_wire_test.c b/src/wire/plugin_wire_test.c index 1d19edf57..70cf82462 100644 --- a/src/wire/plugin_wire_test.c +++ b/src/wire/plugin_wire_test.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2016 GNUnet e.V. + Copyright (C) 2016 GNUnet e.V. & Inria 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 @@ -215,6 +215,8 @@ test_amount_round (void *cls, struct TestClosure *tc = cls; uint32_t delta; + if (NULL == tc->currency) + return GNUNET_SYSERR; /* not configured with currency */ if (0 != strcasecmp (amount->currency, tc->currency)) { @@ -235,11 +237,15 @@ test_amount_round (void *cls, * Right now, the only thing we require is a field * "account_number" which must contain a positive 53-bit integer. * + * @param cls the @e cls of this struct with the plugin-specific state * @param wire the JSON wire format object + * @param master_pub public key of the exchange to verify against * @return #GNUNET_YES if correctly formatted; #GNUNET_NO if not */ static int -test_wire_validate (const json_t *wire) +test_wire_validate (void *cls, + const json_t *wire, + const struct TALER_MasterPublicKeyP *master_pub) { json_error_t error; json_int_t account_no; @@ -368,7 +374,9 @@ test_prepare_wire_transfer (void *cls, struct TALER_WIRE_PrepareHandle *pth; if (GNUNET_YES != - test_wire_validate (wire)) + test_wire_validate (cls, + wire, + NULL)) { GNUNET_break (0); return NULL; @@ -456,6 +464,8 @@ test_execute_wire_transfer (void *cls, json_int_t account_no; struct BufFormatP bf; + if (NULL == tc->bank) + return NULL; /* not initialized with configuration, cannot do transfers */ if ( (buf_size <= sizeof (struct BufFormatP)) || ('\0' != buf[buf_size -1]) ) { @@ -476,7 +486,9 @@ test_execute_wire_transfer (void *cls, return NULL; } GNUNET_assert (GNUNET_YES == - test_wire_validate (wire)); + test_wire_validate (NULL, + wire, + NULL)); if (0 != json_unpack_ex (wire, &error, @@ -545,53 +557,56 @@ libtaler_plugin_wire_test_init (void *cls) struct TALER_WIRE_Plugin *plugin; char *uri; - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, - "wire-test", - "BANK_URI", - &uri)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "wire-test", - "BANK_URI"); - return NULL; - } tc = GNUNET_new (struct TestClosure); - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (cfg, - "wire-test", - "BANK_ACCOUNT_NO_OUTGOING", - &tc->exchange_account_no)) + if (NULL != cfg) { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "wire-test", - "BANK_ACCOUNT_NO_OUTGOING"); - GNUNET_free (uri); - GNUNET_free (tc); - return NULL; - } - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, - "exchange", - "CURRENCY", - &tc->currency)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "exchange", - "CURRENCY"); - GNUNET_free (uri); - GNUNET_free (tc); - return NULL; + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + "wire-test", + "BANK_URI", + &uri)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "wire-test", + "BANK_URI"); + GNUNET_free (tc); + return NULL; + } + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_number (cfg, + "wire-test", + "BANK_ACCOUNT_NO_OUTGOING", + &tc->exchange_account_no)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "wire-test", + "BANK_ACCOUNT_NO_OUTGOING"); + GNUNET_free (uri); + GNUNET_free (tc); + return NULL; + } + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + "exchange", + "CURRENCY", + &tc->currency)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "exchange", + "CURRENCY"); + GNUNET_free (uri); + GNUNET_free (tc); + return NULL; + } + tc->bank = TALER_BANK_init (uri); + if (NULL == tc->bank) + { + GNUNET_break (0); + GNUNET_free (tc->currency); + GNUNET_free (tc); + return NULL; + } } - tc->bank = TALER_BANK_init (uri); - if (NULL == tc->bank) - { - GNUNET_break (0); - GNUNET_free (tc->currency); - GNUNET_free (tc); - return NULL; - } - plugin = GNUNET_new (struct TALER_WIRE_Plugin); plugin->cls = tc; plugin->amount_round = &test_amount_round; @@ -621,8 +636,12 @@ libtaler_plugin_wire_test_done (void *cls) GNUNET_SCHEDULER_cancel (tc->bt); tc->bt = NULL; } - TALER_BANK_fini (tc->bank); - GNUNET_free (tc->currency); + if (NULL != tc->bank) + { + TALER_BANK_fini (tc->bank); + tc->bank = NULL; + } + GNUNET_free_non_null (tc->currency); GNUNET_free (tc); GNUNET_free (plugin); return NULL; diff --git a/src/wire/test_sepa_wireformat.c b/src/wire/test_sepa_wireformat.c index 5081cbe86..f016cf635 100644 --- a/src/wire/test_sepa_wireformat.c +++ b/src/wire/test_sepa_wireformat.c @@ -28,37 +28,37 @@ /* Valid SEPA data */ static const char * const valid_wire_str = "{ \"type\":\"SEPA\", \ -\"IBAN\":\"DE67830654080004822650\", \ -\"name\":\"GNUnet e.V.\", \ +\"iban\":\"DE67830654080004822650\", \ +\"receiver_name\":\"GNUnet e.V.\", \ \"bic\":\"GENODEF1SLR\", \ -\"r\":123456789, \ +\"salt\":\"123456789\", \ \"address\": \"foobar\"}"; /* IBAN has wrong country code */ static const char * const invalid_wire_str = "{ \"type\":\"SEPA\", \ -\"IBAN\":\"XX67830654080004822650\", \ -\"name\":\"GNUnet e.V.\", \ +\"iban\":\"XX67830654080004822650\", \ +\"receiver_name\":\"GNUnet e.V.\", \ \"bic\":\"GENODEF1SLR\", \ -\"r\":123456789, \ +\"salt\":\"123456789\", \ \"address\": \"foobar\"}"; /* IBAN has wrong checksum */ static const char * const invalid_wire_str2 = "{ \"type\":\"SEPA\", \ -\"IBAN\":\"DE67830654080004822651\", \ -\"name\":\"GNUnet e.V.\", \ +\"iban\":\"DE67830654080004822651\", \ +\"receiver_name\":\"GNUnet e.V.\", \ \"bic\":\"GENODEF1SLR\", \ -\"r\":123456789, \ +\"salt\":\"123456789\", \ \"address\": \"foobar\"}"; /* Unsupported wireformat type */ static const char * const unsupported_wire_str = "{ \"type\":\"unsupported\", \ -\"IBAN\":\"DE67830654080004822650\", \ -\"name\":\"GNUnet e.V.\", \ +\"iban\":\"DE67830654080004822650\", \ +\"receiver_name\":\"GNUnet e.V.\", \ \"bic\":\"GENODEF1SLR\", \ -\"r\":123456789, \ +\"salt\":\"123456789\", \ \"address\": \"foobar\"}"; @@ -85,16 +85,24 @@ main(int argc, GNUNET_assert (NULL != plugin); (void) memset(&error, 0, sizeof(error)); GNUNET_assert (NULL != (wire = json_loads (unsupported_wire_str, 0, NULL))); - GNUNET_assert (GNUNET_YES != plugin->wire_validate (wire)); + GNUNET_assert (GNUNET_YES != plugin->wire_validate (NULL, + wire, + NULL)); json_decref (wire); GNUNET_assert (NULL != (wire = json_loads (invalid_wire_str, 0, NULL))); - GNUNET_assert (GNUNET_NO == plugin->wire_validate (wire)); + GNUNET_assert (GNUNET_NO == plugin->wire_validate (NULL, + wire, + NULL)); json_decref (wire); GNUNET_assert (NULL != (wire = json_loads (invalid_wire_str2, 0, NULL))); - GNUNET_assert (GNUNET_NO == plugin->wire_validate (wire)); + GNUNET_assert (GNUNET_NO == plugin->wire_validate (NULL, + wire, + NULL)); json_decref (wire); GNUNET_assert (NULL != (wire = json_loads (valid_wire_str, 0, &error))); - ret = plugin->wire_validate (wire); + ret = plugin->wire_validate (NULL, + wire, + NULL); json_decref (wire); TALER_WIRE_plugin_unload (plugin); GNUNET_CONFIGURATION_destroy (cfg); |