implementing #4357, but test missing

This commit is contained in:
Christian Grothoff 2016-04-11 02:37:56 +02:00
parent 30d66bcebc
commit b018d4d5b0
14 changed files with 224 additions and 121 deletions

View File

@ -62,5 +62,6 @@ test_exchange_api_LDADD = \
EXTRA_DIST = \
test_taler_exchange_api_home/.local/share/taler/exchange/offline-keys/master.priv \
test_taler_exchange_api_home/.config/taler/test.json \
test_taler_exchange_api_home/.config/taler/sepa.json \
test_taler_exchange_api.conf

View File

@ -2327,7 +2327,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_uri\":\"http://localhost:8082/\", \"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,
@ -2348,7 +2348,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_uri\":\"http://localhost:8082/\", \"account_number\":42 }",
.details.deposit.contract = "{ \"items\": [ { \"name\":\"ice cream\", \"value\":1 } ] }",
.details.deposit.transaction_id = 1 },
@ -2365,7 +2365,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_uri\":\"http://localhost:8082/\", \"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
@ -2375,7 +2375,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_uri\":\"http://localhost:8082/\", \"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
@ -2385,7 +2385,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_uri\":\"http://localhost:8082/\", \"account_number\":42 }",
.details.deposit.contract = "{ \"items\":[{ \"name\":\"ice cream\", \"value\":2 } ] }",
.details.deposit.transaction_id = 1 },
@ -2395,7 +2395,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_uri\":\"http://localhost:8082/\", \"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,
@ -2410,7 +2410,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_uri\":\"http://localhost:8082/\", \"account_number\":42 }",
.details.deposit.contract = "{ \"items\" : [ { \"name\":\"ice cream\", \"value\":\"EUR:1\" } ] }",
.details.deposit.transaction_id = 42421 },
@ -2444,7 +2444,7 @@ run (void *cls)
.details.deposit.amount = "EUR:1",
.details.deposit.coin_ref = "refresh-reveal-1",
.details.deposit.coin_idx = 0,
.details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account_number\":42 }",
.details.deposit.wire_details = "{ \"type\":\"test\", \"bank_uri\":\"http://localhost:8082/\", \"account_number\":42 }",
.details.deposit.contract = "{ \"items\": [ { \"name\":\"ice cream\", \"value\":3 } ] }",
.details.deposit.transaction_id = 2 },
@ -2456,7 +2456,7 @@ run (void *cls)
.details.deposit.amount = "EUR:0.1",
.details.deposit.coin_ref = "refresh-reveal-1",
.details.deposit.coin_idx = 4,
.details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account_number\":42 }",
.details.deposit.wire_details = "{ \"type\":\"test\", \"bank_uri\":\"http://localhost:8082/\", \"account_number\":42 }",
.details.deposit.contract = "{ \"items\": [ { \"name\":\"ice cream\", \"value\":3 } ] }",
.details.deposit.transaction_id = 2 },

View File

@ -29,14 +29,13 @@ TESTRUN = YES
DB_CONN_STR = "postgres:///talercheck"
[wire-incoming-test]
# What is the main website of the bank?
BANK_URI = "http://localhost/"
# Into which account at the 'bank' should (incoming) wire transfers be made?
BANK_ACCOUNT_NUMBER = 2
# This is the response we give out for the /wire request. It provides
# wallets with the bank information for transfers to the exchange.
TEST_RESPONSE_FILE = ${TALER_CONFIG_HOME}/test.json
[wire-outgoing-test]
# What is the main website of the bank?
BANK_URI = "http://localhost/"
BANK_URI = "http://localhost:8082/"
# Into which account at the 'bank' should (incoming) wire transfers be made?
BANK_ACCOUNT_NUMBER = 2

View File

@ -0,0 +1,8 @@
{
"salt": "AZPRFVJ58NM6M7J5CZQPJAH3EW5DYM52AEZ9Y1C1ER3W94QV8D8TQKF6CK8MYQRA9QMSKDQTGZ306ZS9GQ0M6R01CJ20KPP49WFDZK8",
"name": "The exchange",
"account_number": 3,
"bank_uri": "http://localhost:8082/",
"type": "test",
"sig": "RPQXP9S4P8PQP7HEZQNRSZCT0ATNEP8GW0P5TPM34V5RX86FCD670V44R9NETSYDDKB8SZV7TKY9PAJYTY51D3VDWY9XXQ5BPFRXR28"
}

View File

@ -145,7 +145,8 @@ TMH_ADMIN_handler_admin_add_incoming (struct TMH_RequestHandler *rh,
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
}
if (GNUNET_YES !=
TMH_json_validate_wireformat (wire))
TMH_json_validate_wireformat (wire,
GNUNET_NO))
{
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);

View File

@ -165,7 +165,8 @@ parse_and_handle_deposit_request (struct MHD_Connection *connection,
return MHD_YES; /* failure */
if (GNUNET_YES !=
TMH_json_validate_wireformat (wire))
TMH_json_validate_wireformat (wire,
GNUNET_NO))
{
GNUNET_JSON_parse_free (spec);
return TMH_RESPONSE_reply_arg_unknown (connection,

View File

@ -153,10 +153,12 @@ TMH_VALIDATION_done ()
* a wire address.
*
* @param wire the JSON wire format object
* @param ours #GNUNET_YES if the signature should match our master key
* @return #GNUNET_YES if correctly formatted; #GNUNET_NO if not
*/
int
TMH_json_validate_wireformat (const json_t *wire)
TMH_json_validate_wireformat (const json_t *wire,
int ours)
{
const char *stype;
json_error_t error;
@ -175,7 +177,9 @@ TMH_json_validate_wireformat (const json_t *wire)
stype))
return p->plugin->wire_validate (p->plugin->cls,
wire,
&TMH_master_public_key);
(GNUNET_YES == ours)
? &TMH_master_public_key
: NULL);
return GNUNET_NO;
}
@ -227,6 +231,16 @@ TMH_VALIDATION_get_wire_methods (const char *prefix)
method = plugin->get_wire_details (plugin->cls,
cfg,
account_name);
if (GNUNET_YES !=
TMH_json_validate_wireformat (method,
GNUNET_YES))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Account details for method `%s' ill-formed. Disabling method\n",
p->type);
json_decref (method);
method = NULL;
}
if (NULL != method)
json_object_set_new (methods,
p->type,

View File

@ -47,10 +47,12 @@ TMH_VALIDATION_done (void);
* a wire address.
*
* @param wire the JSON wire format object
* @param ours #GNUNET_YES if the signature should match our master key
* @return #GNUNET_YES if correctly formatted; #GNUNET_NO if not
*/
int
TMH_json_validate_wireformat (const json_t *wire);
TMH_json_validate_wireformat (const json_t *wire,
int ours);
/**
* Check if we support the given wire method.

View File

@ -481,9 +481,7 @@ do_deposit (struct Command *cmd)
return GNUNET_SYSERR;
}
fake_coin (&deposit.coin);
/* Build JSON for wire details;
note that this simple method may fail in the future if we implement
and enforce signature checking on test-wire account details */
/* Build JSON for wire details */
deposit.wire = json_pack ("{s:s, s:s, s:I}",
"type", "test",
"bank_uri", "http://localhost:8082/",

View File

@ -31,20 +31,13 @@ TESTRUN = YES
DB_CONN_STR = "postgres:///talercheck"
[wire-incoming-test]
# What is the main website of the bank?
BANK_URI = "http://localhost:8082/"
# Into which account at the 'bank' should incoming
# wire transfers be made?
BANK_ACCOUNT_NUMBER = 2
[wire-outgoing-test]
# What is the main website of the bank?
BANK_URI = "http://localhost:8082/"
# From which account at the 'bank' should outgoing
# wire transfers be made?
BANK_ACCOUNT_NUMBER = 3
EXCHANGE_ACCOUNT_NUMBER = 3
# Coins for the tests.

View File

@ -0,0 +1,8 @@
{
"salt": "AZPRFVJ58NM6M7J5CZQPJAH3EW5DYM52AEZ9Y1C1ER3W94QV8D8TQKF6CK8MYQRA9QMSKDQTGZ306ZS9GQ0M6R01CJ20KPP49WFDZK8",
"name": "The exchange",
"account_number": 3,
"bank_uri": "http://localhost:8082/",
"type": "test",
"sig": "RPQXP9S4P8PQP7HEZQNRSZCT0ATNEP8GW0P5TPM34V5RX86FCD670V44R9NETSYDDKB8SZV7TKY9PAJYTY51D3VDWY9XXQ5BPFRXR28"
}

View File

@ -34,27 +34,32 @@
struct TestClosure
{
/**
* Handle to the bank for sending funds to the bank.
*/
struct TALER_BANK_Context *bank;
/**
* Which currency do we support?
*/
char *currency;
/**
* Number of the account that the exchange has at the bank for outgoing
* transfers.
* URI of our bank.
*/
unsigned long long exchange_account_outgoing_no;
char *bank_uri;
/**
* Handle to the bank for sending funds to the bank.
*/
struct TALER_BANK_Context *bank;
/**
* Handle to the bank task, or NULL.
*/
struct GNUNET_SCHEDULER_Task *bt;
/**
* Number of the account that the exchange has at the bank for
* outgoing transfers.
*/
unsigned long long exchange_account_outgoing_no;
};
@ -216,7 +221,12 @@ test_amount_round (void *cls,
uint32_t delta;
if (NULL == tc->currency)
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"exchange",
"CURRENCY");
return GNUNET_SYSERR; /* not configured with currency */
}
if (0 != strcasecmp (amount->currency,
tc->currency))
{
@ -232,58 +242,6 @@ test_amount_round (void *cls,
}
/**
* Obtain wire transfer details in the plugin-specific format
* from the configuration.
*
* @param cls closure
* @param cfg configuration with details about wire accounts
* @param account_name which section in the configuration should we parse
* @return NULL if @a cfg fails to have valid wire details for @a account_name
*/
static json_t *
test_get_wire_details (void *cls,
const struct GNUNET_CONFIGURATION_Handle *cfg,
const char *account_name)
{
json_t *ret;
char *bank_uri;
unsigned long long account_number;
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (cfg,
account_name,
"BANK_URI",
&bank_uri))
{
/* oopsie, configuration error */
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
account_name,
"BANK_URI");
return NULL;
}
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_number (cfg,
account_name,
"BANK_ACCOUNT_NUMBER",
&account_number))
{
/* oopsie, configuration error */
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
account_name,
"BANK_ACCOUNT_NUMBER");
GNUNET_free (bank_uri);
return NULL;
}
ret = json_pack ("{s:s, s:I, s:s}",
"type", "test",
"account_number", (json_int_t) account_number,
"bank_uri", bank_uri);
GNUNET_free (bank_uri);
return ret;
}
/**
* Compute purpose for signing.
*
@ -331,17 +289,23 @@ test_wire_validate (void *cls,
const json_t *wire,
const struct TALER_MasterPublicKeyP *master_pub)
{
struct TestClosure *tc = cls;
json_error_t error;
json_int_t account_no;
const char *bank_uri;
const char *sig_s;
struct TALER_MasterWireDetailsPS wsd;
struct TALER_MasterSignatureP sig;
if (0 !=
json_unpack_ex ((json_t *) wire,
&error,
0,
"{s:I}",
"account_number", &account_no))
"{s:I, s:s}",
"account_number", &account_no,
"bank_uri", &bank_uri))
{
GNUNET_break (0);
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
if ( (account_no < 0) ||
@ -350,14 +314,119 @@ test_wire_validate (void *cls,
GNUNET_break (0);
return GNUNET_SYSERR;
}
/* FIXME: should check signature here in the future!
(note: right now the sig is not properly provided
by the exchange due to the way account data is
specified in the configuration) */
if ( (NULL != tc->bank_uri) &&
(0 != strcmp (bank_uri,
tc->bank_uri)) )
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Wire specifies bank URI %s, but this exchange only supports %s\n",
bank_uri,
tc->bank_uri);
return GNUNET_NO;
}
if (NULL == master_pub)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Skipping signature check as master public key not given\n");
return GNUNET_OK;
}
if (0 !=
json_unpack_ex ((json_t *) wire,
&error,
0,
"{s:s}",
"sig", &sig_s))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Signature check required, but signature is missing\n");
return GNUNET_NO;
}
compute_purpose (account_no,
bank_uri,
&wsd);
if (GNUNET_OK !=
GNUNET_STRINGS_string_to_data (sig_s,
strlen (sig_s),
&sig,
sizeof (sig)))
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_TEST_DETAILS,
&wsd.purpose,
&sig.eddsa_signature,
&master_pub->eddsa_pub))
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
return GNUNET_YES;
}
/**
* Obtain wire transfer details in the plugin-specific format
* from the configuration.
*
* @param cls closure
* @param cfg configuration with details about wire accounts
* @param account_name which section in the configuration should we parse
* @return NULL if @a cfg fails to have valid wire details for @a account_name
*/
static json_t *
test_get_wire_details (void *cls,
const struct GNUNET_CONFIGURATION_Handle *cfg,
const char *account_name)
{
struct TestClosure *tc = cls;
char *test_wire_file;
json_error_t err;
json_t *ret;
/* Fetch reply */
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_filename (cfg,
account_name,
"TEST_RESPONSE_FILE",
&test_wire_file))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
account_name,
"TEST_RESPONSE_FILE");
return NULL;
}
ret = json_load_file (test_wire_file,
JSON_REJECT_DUPLICATES,
&err);
if (NULL == ret)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to parse JSON in %s: %s (%s:%u)\n",
test_wire_file,
err.text,
err.source,
err.line);
GNUNET_free (test_wire_file);
return NULL;
}
if (GNUNET_YES != test_wire_validate (tc,
ret,
NULL))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to validate TEST wire data in %s\n",
test_wire_file);
GNUNET_free (test_wire_file);
json_decref (ret);
return NULL;
}
GNUNET_free (test_wire_file);
return ret;
}
GNUNET_NETWORK_STRUCT_BEGIN
/**
* Format we used for serialized transaction data.
@ -460,11 +529,11 @@ test_prepare_wire_transfer (void *cls,
struct TALER_WIRE_PrepareHandle *pth;
if (GNUNET_YES !=
test_wire_validate (cls,
test_wire_validate (tc,
wire,
NULL))
{
GNUNET_break (0);
GNUNET_break_op (0);
return NULL;
}
pth = GNUNET_new (struct TALER_WIRE_PrepareHandle);
@ -624,7 +693,11 @@ test_execute_wire_transfer (void *cls,
struct BufFormatP bf;
if (NULL == tc->bank)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Bank not initialized, cannot do transfers!\n");
return NULL; /* not initialized with configuration, cannot do transfers */
}
if ( (buf_size <= sizeof (struct BufFormatP)) ||
('\0' != buf[buf_size -1]) )
{
@ -645,7 +718,7 @@ test_execute_wire_transfer (void *cls,
return NULL;
}
GNUNET_assert (GNUNET_YES ==
test_wire_validate (NULL,
test_wire_validate (tc,
wire,
NULL));
if (0 !=
@ -714,7 +787,6 @@ libtaler_plugin_wire_test_init (void *cls)
struct GNUNET_CONFIGURATION_Handle *cfg = cls;
struct TestClosure *tc;
struct TALER_WIRE_Plugin *plugin;
char *uri;
tc = GNUNET_new (struct TestClosure);
if (NULL != cfg)
@ -723,7 +795,7 @@ libtaler_plugin_wire_test_init (void *cls)
GNUNET_CONFIGURATION_get_value_string (cfg,
"wire-outgoing-test",
"BANK_URI",
&uri))
&tc->bank_uri))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"wire-outgoing-test",
@ -734,13 +806,13 @@ libtaler_plugin_wire_test_init (void *cls)
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_number (cfg,
"wire-outgoing-test",
"BANK_ACCOUNT_NUMBER",
"EXCHANGE_ACCOUNT_NUMBER",
&tc->exchange_account_outgoing_no))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"wire-incoming-test",
"BANK_ACCOUNT_NUMBER");
GNUNET_free (uri);
"wire-outgoing-test",
"EXCHANGE_ACCOUNT_NUMBER");
GNUNET_free (tc->bank_uri);
GNUNET_free (tc);
return NULL;
}
@ -753,16 +825,16 @@ libtaler_plugin_wire_test_init (void *cls)
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"exchange",
"CURRENCY");
GNUNET_free (uri);
GNUNET_free (tc->bank_uri);
GNUNET_free (tc);
return NULL;
}
tc->bank = TALER_BANK_init (uri);
GNUNET_free (uri);
tc->bank = TALER_BANK_init (tc->bank_uri);
if (NULL == tc->bank)
{
GNUNET_break (0);
GNUNET_free (tc->currency);
GNUNET_free (tc->bank_uri);
GNUNET_free (tc);
return NULL;
}
@ -804,6 +876,7 @@ libtaler_plugin_wire_test_done (void *cls)
tc->bank = NULL;
}
GNUNET_free_non_null (tc->currency);
GNUNET_free_non_null (tc->bank_uri);
GNUNET_free (tc);
GNUNET_free (plugin);
return NULL;

View File

@ -1,7 +1,10 @@
# Configuration for SEPA wire plugin.
[wire-incoming-sepa]
# This is the response we give out for the /wire request. It provides
# wallets with the bank information for transfers to the exchange.
SEPA_RESPONSE_FILE = ${TALER_CONFIG_HOME}/sepa.json
[wire-incoming-sepa]
SEPA_RESPONSE_FILE = ${TALER_CONFIG_HOME}/sepa.json
[wire-outgoing-sepa]
# This section should contain the options required for making outgoing
# SEPA transfers. Not yet supported (need libebics).

View File

@ -1,14 +1,16 @@
# This file is in the public domain.
#
[wire-incoming-test]
# What is the main website of the bank?
# BANK_URI = "http://localhost:8082/"
# Into which account at the 'bank' should incoming
# wire transfers be made?
# BANK_ACCOUNT_NUMBER = 2
# This is the response we give out for the /wire request. It provides
# wallets with the bank information for transfers to the exchange.
TEST_RESPONSE_FILE = ${TALER_CONFIG_HOME}/test.json
[wire-outgoing-test]
# What is the main website of the bank?
# BANK_URI = "http://localhost:8082/"
# For outgoing transfers, we need to know the exchange's
# account number at the bank.
EXCHANGE_ACCOUNT_NUMBER = 2
# From which account at the 'bank' should outgoing
# wire transfers be made?
# BANK_ACCOUNT_NUMBER = 3
# For transfers made by the exchange, we need to know
# the URI of the bank (where the /admin/add/incoming API
# is avaialble).
# BANK_URI = https://bank.demo.taler.net/