return more error details for /wire and /keys to clients

This commit is contained in:
Christian Grothoff 2020-04-04 13:27:46 +02:00
parent 643b3e3be3
commit 299b4b78e0
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
8 changed files with 121 additions and 73 deletions

View File

@ -111,6 +111,12 @@ enum TALER_ErrorCode
*/
TALER_EC_WRONG_NUMBER_OF_SEGMENTS = 12,
/**
* The start and end-times in the wire fee structure leave a hole.
* This is not allowed. Generated as an error on the client-side.
*/
TALER_EC_HOLE_IN_WIRE_FEE_STRUCTURE = 13,
/**
* The exchange failed to even just initialize its connection to the
* database. This response is provided with HTTP status code

View File

@ -359,12 +359,18 @@ enum TALER_EXCHANGE_VersionCompatibility
* @param keys information about the various keys used
* by the exchange, NULL if /keys failed
* @param compat protocol compatibility information
* @param ec error code, #TALER_EC_NONE on success
* @param http_status status returned by /keys, #MHD_HTTP_OK on success
* @param full_reply JSON body of /keys request, NULL if reply was not in JSON
*/
typedef void
(*TALER_EXCHANGE_CertificationCallback) (
void *cls,
const struct TALER_EXCHANGE_Keys *keys,
enum TALER_EXCHANGE_VersionCompatibility compat);
enum TALER_EXCHANGE_VersionCompatibility compat,
enum TALER_ErrorCode ec,
unsigned int http_status,
const json_t *full_reply);
/**
@ -649,6 +655,7 @@ struct TALER_EXCHANGE_WireAccount
* @param ec taler-specific error code, #TALER_EC_NONE on success
* @param accounts_len length of the @a accounts array
* @param accounts list of wire accounts of the exchange, NULL on error
* @param full_reply the complete reply from the exchange (if it was in JSON)
*/
typedef void
(*TALER_EXCHANGE_WireCallback) (
@ -656,7 +663,8 @@ typedef void
unsigned int http_status,
enum TALER_ErrorCode ec,
unsigned int accounts_len,
const struct TALER_EXCHANGE_WireAccount *accounts);
const struct TALER_EXCHANGE_WireAccount *accounts,
const json_t *full_reply);
/**

View File

@ -137,11 +137,17 @@ TALER_TESTING_prepare_exchange (const char *config_filename,
* all the commands to be run, and a closure for it.
* @param keys the exchange's keys.
* @param compat protocol compatibility information.
* @param ec error code, #TALER_EC_NONE on success
* @param http_status status returned by /keys, #MHD_HTTP_OK on success
* @param full_reply JSON body of /keys request, NULL if reply was not in JSON
*/
void
TALER_TESTING_cert_cb (void *cls,
const struct TALER_EXCHANGE_Keys *keys,
enum TALER_EXCHANGE_VersionCompatibility compat);
enum TALER_EXCHANGE_VersionCompatibility compat,
enum TALER_ErrorCode ec,
unsigned int http_status,
const json_t *full_reply);
/**

View File

@ -373,7 +373,6 @@ parse_json_signkey (struct TALER_EXCHANGE_SigningPublicKey *sign_key,
json_t *sign_key_obj,
const struct TALER_MasterPublicKeyP *master_key)
{
struct TALER_ExchangeSigningKeyValidityPS sign_key_issue;
struct TALER_MasterSignatureP sign_key_issue_sig;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("master_sig",
@ -400,23 +399,26 @@ parse_json_signkey (struct TALER_EXCHANGE_SigningPublicKey *sign_key,
if (! check_sigs)
return GNUNET_OK;
sign_key_issue.signkey_pub = sign_key->key;
sign_key_issue.purpose.purpose = htonl (
TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY);
sign_key_issue.purpose.size = htonl (sizeof (struct
TALER_ExchangeSigningKeyValidityPS));
sign_key_issue.master_public_key = *master_key;
sign_key_issue.start = GNUNET_TIME_absolute_hton (sign_key->valid_from);
sign_key_issue.expire = GNUNET_TIME_absolute_hton (sign_key->valid_until);
sign_key_issue.end = GNUNET_TIME_absolute_hton (sign_key->valid_legal);
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY,
&sign_key_issue.purpose,
&sign_key_issue_sig.eddsa_signature,
&master_key->eddsa_pub))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
struct TALER_ExchangeSigningKeyValidityPS sign_key_issue = {
.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY),
.purpose.size = htonl (sizeof (sign_key_issue)),
.signkey_pub = sign_key->key,
.master_public_key = *master_key,
.start = GNUNET_TIME_absolute_hton (sign_key->valid_from),
.expire = GNUNET_TIME_absolute_hton (sign_key->valid_until),
.end = GNUNET_TIME_absolute_hton (sign_key->valid_legal)
};
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY,
&sign_key_issue.purpose,
&sign_key_issue_sig.eddsa_signature,
&master_key->eddsa_pub))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
}
sign_key->master_sig = sign_key_issue_sig;
return GNUNET_OK;
@ -441,7 +443,6 @@ parse_json_denomkey (struct TALER_EXCHANGE_DenomPublicKey *denom_key,
struct TALER_MasterPublicKeyP *master_key,
struct GNUNET_HashContext *hash_context)
{
struct TALER_DenominationKeyValidityPS denom_key_issue;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("master_sig",
&denom_key->master_sig),
@ -479,46 +480,50 @@ parse_json_denomkey (struct TALER_EXCHANGE_DenomPublicKey *denom_key,
GNUNET_CRYPTO_rsa_public_key_hash (denom_key->key.rsa_public_key,
&denom_key->h_key);
if (NULL != hash_context)
GNUNET_CRYPTO_hash_context_read (hash_context,
&denom_key->h_key,
sizeof (struct GNUNET_HashCode));
if (! check_sigs)
return GNUNET_OK;
memset (&denom_key_issue,
0,
sizeof (denom_key_issue));
denom_key_issue.purpose.purpose
= htonl (TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY);
denom_key_issue.purpose.size
= htonl (sizeof (struct TALER_DenominationKeyValidityPS));
denom_key_issue.master = *master_key;
denom_key_issue.denom_hash = denom_key->h_key;
denom_key_issue.start = GNUNET_TIME_absolute_hton (denom_key->valid_from);
denom_key_issue.expire_withdraw = GNUNET_TIME_absolute_hton (
denom_key->withdraw_valid_until);
denom_key_issue.expire_deposit = GNUNET_TIME_absolute_hton (
denom_key->expire_deposit);
denom_key_issue.expire_legal = GNUNET_TIME_absolute_hton (
denom_key->expire_legal);
TALER_amount_hton (&denom_key_issue.value,
&denom_key->value);
TALER_amount_hton (&denom_key_issue.fee_withdraw,
&denom_key->fee_withdraw);
TALER_amount_hton (&denom_key_issue.fee_deposit,
&denom_key->fee_deposit);
TALER_amount_hton (&denom_key_issue.fee_refresh,
&denom_key->fee_refresh);
TALER_amount_hton (&denom_key_issue.fee_refund,
&denom_key->fee_refund);
EXITIF (GNUNET_SYSERR ==
GNUNET_CRYPTO_eddsa_verify (
TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY,
&denom_key_issue.purpose,
&denom_key->master_sig.eddsa_signature,
&master_key->eddsa_pub));
GNUNET_CRYPTO_hash_context_read (hash_context,
&denom_key_issue.denom_hash,
sizeof (struct GNUNET_HashCode));
{
struct TALER_DenominationKeyValidityPS denom_key_issue = {
.purpose.purpose
= htonl (TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY),
.purpose.size = htonl (sizeof (denom_key_issue)),
.master = *master_key,
.denom_hash = denom_key->h_key,
.start = GNUNET_TIME_absolute_hton (denom_key->valid_from),
.expire_withdraw
= GNUNET_TIME_absolute_hton (denom_key->withdraw_valid_until),
.expire_deposit = GNUNET_TIME_absolute_hton (denom_key->expire_deposit),
.expire_legal = GNUNET_TIME_absolute_hton (denom_key->expire_legal)
};
TALER_amount_hton (&denom_key_issue.value,
&denom_key->value);
TALER_amount_hton (&denom_key_issue.fee_withdraw,
&denom_key->fee_withdraw);
TALER_amount_hton (&denom_key_issue.fee_deposit,
&denom_key->fee_deposit);
TALER_amount_hton (&denom_key_issue.fee_refresh,
&denom_key->fee_refresh);
TALER_amount_hton (&denom_key_issue.fee_refund,
&denom_key->fee_refund);
EXITIF (GNUNET_SYSERR ==
GNUNET_CRYPTO_eddsa_verify (
TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY,
&denom_key_issue.purpose,
&denom_key->master_sig.eddsa_signature,
&master_key->eddsa_pub));
}
return GNUNET_OK;
EXITIF_exit:
/* invalidate denom_key, just to be sure */
memset (denom_key,
0,
sizeof (*denom_key));
GNUNET_JSON_parse_free (spec);
return GNUNET_SYSERR;
}
@ -1376,7 +1381,10 @@ keys_completed_cb (void *cls,
/* notify application that we failed */
exchange->cert_cb (exchange->cert_cb_cls,
NULL,
vc);
vc,
TALER_JSON_get_error_code (j),
response_code,
j);
return;
}
@ -1390,7 +1398,10 @@ keys_completed_cb (void *cls,
/* notify application about the key information */
exchange->cert_cb (exchange->cert_cb_cls,
&exchange->key_data,
vc);
vc,
TALER_EC_NONE,
MHD_HTTP_OK,
j);
free_key_data (&kd_old);
}
@ -1612,7 +1623,10 @@ deserialize_data (struct TALER_EXCHANGE_Handle *exchange,
/* notify application about the key information */
exchange->cert_cb (exchange->cert_cb_cls,
&exchange->key_data,
vc);
vc,
TALER_EC_NONE,
MHD_HTTP_OK,
data);
GNUNET_JSON_parse_free (spec);
}

View File

@ -328,7 +328,8 @@ handle_wire_finished (void *cls,
response_code,
ec,
num_accounts,
was);
was,
j);
wh->cb = NULL;
}
} /* end of 'parse accounts */
@ -367,7 +368,8 @@ handle_wire_finished (void *cls,
response_code,
ec,
0,
NULL);
NULL,
j);
TALER_EXCHANGE_wire_cancel (wh);
}

View File

@ -209,7 +209,7 @@ connect_with_state_run (void *cls,
&exchange_url));
is->exchange = TALER_EXCHANGE_connect (is->ctx,
exchange_url,
TALER_TESTING_cert_cb,
&TALER_TESTING_cert_cb,
cwss,
TALER_EXCHANGE_OPTION_DATA,
serialized_keys,

View File

@ -77,19 +77,22 @@ struct WireState
* @param accounts_len length of the @a accounts array.
* @param accounts list of wire accounts of the exchange,
* NULL on error.
* @param full_reply the complete response from the exchange
*/
static void
wire_cb (void *cls,
unsigned int http_status,
enum TALER_ErrorCode ec,
unsigned int accounts_len,
const struct TALER_EXCHANGE_WireAccount *accounts)
const struct TALER_EXCHANGE_WireAccount *accounts,
const json_t *full_reply)
{
struct WireState *ws = cls;
struct TALER_TESTING_Command *cmd = &ws->is->commands[ws->is->ip];
struct TALER_Amount expected_fee;
(void) ec;
(void) full_reply;
TALER_LOG_DEBUG ("Checking parsed /wire response\n");
ws->wh = NULL;
if (ws->expected_response_code != http_status)

View File

@ -570,7 +570,7 @@ struct MainContext
* respective handler by writing to the trigger pipe.
*/
static void
sighandler_child_death ()
sighandler_child_death (void)
{
static char c;
int old_errno = errno; /* back-up errno */
@ -591,24 +591,31 @@ sighandler_child_death ()
* all the commands to be run, and a closure for it.
* @param keys the exchange's keys.
* @param compat protocol compatibility information.
* @param ec error code, #TALER_EC_NONE on success
* @param http_status status returned by /keys, #MHD_HTTP_OK on success
* @param full_reply JSON body of /keys request, NULL if reply was not in JSON
*/
void
TALER_TESTING_cert_cb (void *cls,
const struct TALER_EXCHANGE_Keys *keys,
enum TALER_EXCHANGE_VersionCompatibility compat)
enum TALER_EXCHANGE_VersionCompatibility compat,
enum TALER_ErrorCode ec,
unsigned int http_status,
const json_t *full_reply)
{
struct MainContext *main_ctx = cls;
struct TALER_TESTING_Interpreter *is = main_ctx->is;
(void) compat;
(void) full_reply;
if (NULL == keys)
{
if (GNUNET_NO == is->working)
{
GNUNET_log
(GNUNET_ERROR_TYPE_WARNING,
"Got NULL response for /keys"
" during startup, retrying!\n");
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Got NULL response for /keys during startup (%u/%d), retrying!\n",
http_status,
(int) ec);
TALER_EXCHANGE_disconnect (is->exchange);
GNUNET_assert
(NULL != (is->exchange = TALER_EXCHANGE_connect
@ -620,10 +627,12 @@ TALER_TESTING_cert_cb (void *cls,
return;
}
else
GNUNET_log
(GNUNET_ERROR_TYPE_ERROR,
"Got NULL response for /keys"
" during execution!\n");
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Got NULL response for /keys during execution (%u/%d)!\n",
http_status,
(int) ec);
}
}
else
{