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, 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 * The exchange failed to even just initialize its connection to the
* database. This response is provided with HTTP status code * 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 * @param keys information about the various keys used
* by the exchange, NULL if /keys failed * by the exchange, NULL if /keys failed
* @param compat protocol compatibility information * @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 typedef void
(*TALER_EXCHANGE_CertificationCallback) ( (*TALER_EXCHANGE_CertificationCallback) (
void *cls, void *cls,
const struct TALER_EXCHANGE_Keys *keys, 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 ec taler-specific error code, #TALER_EC_NONE on success
* @param accounts_len length of the @a accounts array * @param accounts_len length of the @a accounts array
* @param accounts list of wire accounts of the exchange, NULL on error * @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 typedef void
(*TALER_EXCHANGE_WireCallback) ( (*TALER_EXCHANGE_WireCallback) (
@ -656,7 +663,8 @@ typedef void
unsigned int http_status, unsigned int http_status,
enum TALER_ErrorCode ec, enum TALER_ErrorCode ec,
unsigned int accounts_len, 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. * all the commands to be run, and a closure for it.
* @param keys the exchange's keys. * @param keys the exchange's keys.
* @param compat protocol compatibility information. * @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 void
TALER_TESTING_cert_cb (void *cls, TALER_TESTING_cert_cb (void *cls,
const struct TALER_EXCHANGE_Keys *keys, 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, json_t *sign_key_obj,
const struct TALER_MasterPublicKeyP *master_key) const struct TALER_MasterPublicKeyP *master_key)
{ {
struct TALER_ExchangeSigningKeyValidityPS sign_key_issue;
struct TALER_MasterSignatureP sign_key_issue_sig; struct TALER_MasterSignatureP sign_key_issue_sig;
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("master_sig", GNUNET_JSON_spec_fixed_auto ("master_sig",
@ -400,15 +399,17 @@ parse_json_signkey (struct TALER_EXCHANGE_SigningPublicKey *sign_key,
if (! check_sigs) if (! check_sigs)
return GNUNET_OK; return GNUNET_OK;
sign_key_issue.signkey_pub = sign_key->key; {
sign_key_issue.purpose.purpose = htonl ( struct TALER_ExchangeSigningKeyValidityPS sign_key_issue = {
TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY); .purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY),
sign_key_issue.purpose.size = htonl (sizeof (struct .purpose.size = htonl (sizeof (sign_key_issue)),
TALER_ExchangeSigningKeyValidityPS)); .signkey_pub = sign_key->key,
sign_key_issue.master_public_key = *master_key; .master_public_key = *master_key,
sign_key_issue.start = GNUNET_TIME_absolute_hton (sign_key->valid_from); .start = GNUNET_TIME_absolute_hton (sign_key->valid_from),
sign_key_issue.expire = GNUNET_TIME_absolute_hton (sign_key->valid_until); .expire = GNUNET_TIME_absolute_hton (sign_key->valid_until),
sign_key_issue.end = GNUNET_TIME_absolute_hton (sign_key->valid_legal); .end = GNUNET_TIME_absolute_hton (sign_key->valid_legal)
};
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY, GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY,
&sign_key_issue.purpose, &sign_key_issue.purpose,
@ -418,6 +419,7 @@ parse_json_signkey (struct TALER_EXCHANGE_SigningPublicKey *sign_key,
GNUNET_break_op (0); GNUNET_break_op (0);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
}
sign_key->master_sig = sign_key_issue_sig; sign_key->master_sig = sign_key_issue_sig;
return GNUNET_OK; return GNUNET_OK;
} }
@ -441,7 +443,6 @@ parse_json_denomkey (struct TALER_EXCHANGE_DenomPublicKey *denom_key,
struct TALER_MasterPublicKeyP *master_key, struct TALER_MasterPublicKeyP *master_key,
struct GNUNET_HashContext *hash_context) struct GNUNET_HashContext *hash_context)
{ {
struct TALER_DenominationKeyValidityPS denom_key_issue;
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("master_sig", GNUNET_JSON_spec_fixed_auto ("master_sig",
&denom_key->master_sig), &denom_key->master_sig),
@ -479,24 +480,26 @@ parse_json_denomkey (struct TALER_EXCHANGE_DenomPublicKey *denom_key,
GNUNET_CRYPTO_rsa_public_key_hash (denom_key->key.rsa_public_key, GNUNET_CRYPTO_rsa_public_key_hash (denom_key->key.rsa_public_key,
&denom_key->h_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) if (! check_sigs)
return GNUNET_OK; return GNUNET_OK;
memset (&denom_key_issue, {
0, struct TALER_DenominationKeyValidityPS denom_key_issue = {
sizeof (denom_key_issue)); .purpose.purpose
denom_key_issue.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY),
= htonl (TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY); .purpose.size = htonl (sizeof (denom_key_issue)),
denom_key_issue.purpose.size .master = *master_key,
= htonl (sizeof (struct TALER_DenominationKeyValidityPS)); .denom_hash = denom_key->h_key,
denom_key_issue.master = *master_key; .start = GNUNET_TIME_absolute_hton (denom_key->valid_from),
denom_key_issue.denom_hash = denom_key->h_key; .expire_withdraw
denom_key_issue.start = GNUNET_TIME_absolute_hton (denom_key->valid_from); = GNUNET_TIME_absolute_hton (denom_key->withdraw_valid_until),
denom_key_issue.expire_withdraw = GNUNET_TIME_absolute_hton ( .expire_deposit = GNUNET_TIME_absolute_hton (denom_key->expire_deposit),
denom_key->withdraw_valid_until); .expire_legal = GNUNET_TIME_absolute_hton (denom_key->expire_legal)
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, TALER_amount_hton (&denom_key_issue.value,
&denom_key->value); &denom_key->value);
TALER_amount_hton (&denom_key_issue.fee_withdraw, TALER_amount_hton (&denom_key_issue.fee_withdraw,
@ -513,12 +516,14 @@ parse_json_denomkey (struct TALER_EXCHANGE_DenomPublicKey *denom_key,
&denom_key_issue.purpose, &denom_key_issue.purpose,
&denom_key->master_sig.eddsa_signature, &denom_key->master_sig.eddsa_signature,
&master_key->eddsa_pub)); &master_key->eddsa_pub));
GNUNET_CRYPTO_hash_context_read (hash_context, }
&denom_key_issue.denom_hash,
sizeof (struct GNUNET_HashCode));
return GNUNET_OK; return GNUNET_OK;
EXITIF_exit: EXITIF_exit:
/* invalidate denom_key, just to be sure */
memset (denom_key,
0,
sizeof (*denom_key));
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
@ -1376,7 +1381,10 @@ keys_completed_cb (void *cls,
/* notify application that we failed */ /* notify application that we failed */
exchange->cert_cb (exchange->cert_cb_cls, exchange->cert_cb (exchange->cert_cb_cls,
NULL, NULL,
vc); vc,
TALER_JSON_get_error_code (j),
response_code,
j);
return; return;
} }
@ -1390,7 +1398,10 @@ keys_completed_cb (void *cls,
/* notify application about the key information */ /* notify application about the key information */
exchange->cert_cb (exchange->cert_cb_cls, exchange->cert_cb (exchange->cert_cb_cls,
&exchange->key_data, &exchange->key_data,
vc); vc,
TALER_EC_NONE,
MHD_HTTP_OK,
j);
free_key_data (&kd_old); free_key_data (&kd_old);
} }
@ -1612,7 +1623,10 @@ deserialize_data (struct TALER_EXCHANGE_Handle *exchange,
/* notify application about the key information */ /* notify application about the key information */
exchange->cert_cb (exchange->cert_cb_cls, exchange->cert_cb (exchange->cert_cb_cls,
&exchange->key_data, &exchange->key_data,
vc); vc,
TALER_EC_NONE,
MHD_HTTP_OK,
data);
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
} }

View File

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

View File

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

View File

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

View File

@ -570,7 +570,7 @@ struct MainContext
* respective handler by writing to the trigger pipe. * respective handler by writing to the trigger pipe.
*/ */
static void static void
sighandler_child_death () sighandler_child_death (void)
{ {
static char c; static char c;
int old_errno = errno; /* back-up errno */ 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. * all the commands to be run, and a closure for it.
* @param keys the exchange's keys. * @param keys the exchange's keys.
* @param compat protocol compatibility information. * @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 void
TALER_TESTING_cert_cb (void *cls, TALER_TESTING_cert_cb (void *cls,
const struct TALER_EXCHANGE_Keys *keys, 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 MainContext *main_ctx = cls;
struct TALER_TESTING_Interpreter *is = main_ctx->is; struct TALER_TESTING_Interpreter *is = main_ctx->is;
(void) compat; (void) compat;
(void) full_reply;
if (NULL == keys) if (NULL == keys)
{ {
if (GNUNET_NO == is->working) if (GNUNET_NO == is->working)
{ {
GNUNET_log GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
(GNUNET_ERROR_TYPE_WARNING, "Got NULL response for /keys during startup (%u/%d), retrying!\n",
"Got NULL response for /keys" http_status,
" during startup, retrying!\n"); (int) ec);
TALER_EXCHANGE_disconnect (is->exchange); TALER_EXCHANGE_disconnect (is->exchange);
GNUNET_assert GNUNET_assert
(NULL != (is->exchange = TALER_EXCHANGE_connect (NULL != (is->exchange = TALER_EXCHANGE_connect
@ -620,10 +627,12 @@ TALER_TESTING_cert_cb (void *cls,
return; return;
} }
else else
GNUNET_log {
(GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Got NULL response for /keys" "Got NULL response for /keys during execution (%u/%d)!\n",
" during execution!\n"); http_status,
(int) ec);
}
} }
else else
{ {