fix auditor to properly verify wire fee signatures and more gracefully handle arithmetic amount issue

This commit is contained in:
Christian Grothoff 2018-01-04 00:41:19 +01:00
parent d9f16db0ef
commit 5587732f52
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
7 changed files with 64 additions and 9 deletions

View File

@ -1664,10 +1664,15 @@ struct WireFeeInfo
struct GNUNET_TIME_Absolute end_date; struct GNUNET_TIME_Absolute end_date;
/** /**
* How high is the fee. * How high is the wire fee.
*/ */
struct TALER_Amount wire_fee; struct TALER_Amount wire_fee;
/**
* How high is the closing fee.
*/
struct TALER_Amount closing_fee;
}; };
@ -1815,6 +1820,7 @@ check_transaction_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
struct TALER_Amount spent; struct TALER_Amount spent;
struct TALER_Amount value; struct TALER_Amount value;
struct TALER_Amount merchant_loss; struct TALER_Amount merchant_loss;
struct TALER_Amount merchant_delta;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Checking transaction history of coin %s\n", "Checking transaction history of coin %s\n",
@ -2043,7 +2049,7 @@ check_transaction_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
/* Finally, update @a merchant_gain by subtracting what he "lost" from refunds */ /* Finally, update @a merchant_gain by subtracting what he "lost" from refunds */
if (GNUNET_SYSERR == if (GNUNET_SYSERR ==
TALER_amount_subtract (merchant_gain, TALER_amount_subtract (&merchant_delta,
merchant_gain, merchant_gain,
&merchant_loss)) &merchant_loss))
{ {
@ -2055,6 +2061,7 @@ check_transaction_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
0); 0);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
*merchant_gain = merchant_delta;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Coin %s contributes %s to contract %s\n", "Coin %s contributes %s to contract %s\n",
TALER_B2S (coin_pub), TALER_B2S (coin_pub),
@ -2276,6 +2283,7 @@ get_wire_fee (struct AggregationContext *ac,
&wfi->start_date, &wfi->start_date,
&wfi->end_date, &wfi->end_date,
&wfi->wire_fee, &wfi->wire_fee,
&wfi->closing_fee,
&master_sig)) &master_sig))
{ {
GNUNET_break (0); GNUNET_break (0);
@ -2299,6 +2307,8 @@ get_wire_fee (struct AggregationContext *ac,
wp.end_date = GNUNET_TIME_absolute_hton (wfi->end_date); wp.end_date = GNUNET_TIME_absolute_hton (wfi->end_date);
TALER_amount_hton (&wp.wire_fee, TALER_amount_hton (&wp.wire_fee,
&wfi->wire_fee); &wfi->wire_fee);
TALER_amount_hton (&wp.closing_fee,
&wfi->closing_fee);
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_WIRE_FEES, GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_WIRE_FEES,
&wp.purpose, &wp.purpose,

View File

@ -3566,7 +3566,7 @@ run (void *cls)
.label = "check-empty-after-refund" }, .label = "check-empty-after-refund" },
#if 0 #if 1
/* Test refunded coins are never executed, even past /* Test refunded coins are never executed, even past
refund deadline */ refund deadline */
{ .oc = OC_ADMIN_ADD_INCOMING, { .oc = OC_ADMIN_ADD_INCOMING,

View File

@ -374,6 +374,7 @@ update_fees (struct WirePlugin *wp,
p->start_date, p->start_date,
p->end_date, p->end_date,
&p->wire_fee, &p->wire_fee,
&p->closing_fee,
&p->master_sig); &p->master_sig);
if (qs < 0) if (qs < 0)
{ {

View File

@ -352,6 +352,7 @@ track_transfer_transaction (void *cls,
struct GNUNET_TIME_Absolute wire_fee_start_date; struct GNUNET_TIME_Absolute wire_fee_start_date;
struct GNUNET_TIME_Absolute wire_fee_end_date; struct GNUNET_TIME_Absolute wire_fee_end_date;
struct TALER_MasterSignatureP wire_fee_master_sig; struct TALER_MasterSignatureP wire_fee_master_sig;
struct TALER_Amount closing_fee;
ctx->is_valid = GNUNET_NO; ctx->is_valid = GNUNET_NO;
ctx->wdd_head = NULL; ctx->wdd_head = NULL;
@ -393,6 +394,7 @@ track_transfer_transaction (void *cls,
&wire_fee_start_date, &wire_fee_start_date,
&wire_fee_end_date, &wire_fee_end_date,
&ctx->wire_fee, &ctx->wire_fee,
&closing_fee,
&wire_fee_master_sig); &wire_fee_master_sig);
if (0 >= qs) if (0 >= qs)
{ {

View File

@ -383,6 +383,9 @@ postgres_create_tables (void *cls)
",wire_fee_val INT8 NOT NULL" ",wire_fee_val INT8 NOT NULL"
",wire_fee_frac INT4 NOT NULL" ",wire_fee_frac INT4 NOT NULL"
",wire_fee_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL" ",wire_fee_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
",closing_fee_val INT8 NOT NULL"
",closing_fee_frac INT4 NOT NULL"
",closing_fee_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
",master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)" ",master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)"
",PRIMARY KEY (wire_method, start_date)" /* this combo must be unique */ ",PRIMARY KEY (wire_method, start_date)" /* this combo must be unique */
");"), ");"),
@ -1170,6 +1173,9 @@ postgres_prepare (PGconn *db_conn)
",wire_fee_val" ",wire_fee_val"
",wire_fee_frac" ",wire_fee_frac"
",wire_fee_curr" ",wire_fee_curr"
",closing_fee_val"
",closing_fee_frac"
",closing_fee_curr"
",master_sig" ",master_sig"
" FROM wire_fee" " FROM wire_fee"
" WHERE wire_method=$1" " WHERE wire_method=$1"
@ -1185,10 +1191,13 @@ postgres_prepare (PGconn *db_conn)
",wire_fee_val" ",wire_fee_val"
",wire_fee_frac" ",wire_fee_frac"
",wire_fee_curr" ",wire_fee_curr"
",closing_fee_val"
",closing_fee_frac"
",closing_fee_curr"
",master_sig" ",master_sig"
") VALUES " ") VALUES "
"($1, $2, $3, $4, $5, $6, $7);", "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);",
7), 19),
/* Used in #postgres_store_wire_transfer_out */ /* Used in #postgres_store_wire_transfer_out */
GNUNET_PQ_make_prepare ("insert_wire_out", GNUNET_PQ_make_prepare ("insert_wire_out",
"INSERT INTO wire_out " "INSERT INTO wire_out "
@ -4356,6 +4365,7 @@ postgres_insert_aggregation_tracking (void *cls,
* @param[out] start_date when does the fee go into effect * @param[out] start_date when does the fee go into effect
* @param[out] end_date when does the fee end being valid * @param[out] end_date when does the fee end being valid
* @param[out] wire_fee how high is the wire transfer fee * @param[out] wire_fee how high is the wire transfer fee
* @param[out] closing_fee how high is the closing fee
* @param[out] master_sig signature over the above by the exchange master key * @param[out] master_sig signature over the above by the exchange master key
* @return status of the transaction * @return status of the transaction
*/ */
@ -4367,6 +4377,7 @@ postgres_get_wire_fee (void *cls,
struct GNUNET_TIME_Absolute *start_date, struct GNUNET_TIME_Absolute *start_date,
struct GNUNET_TIME_Absolute *end_date, struct GNUNET_TIME_Absolute *end_date,
struct TALER_Amount *wire_fee, struct TALER_Amount *wire_fee,
struct TALER_Amount *closing_fee,
struct TALER_MasterSignatureP *master_sig) struct TALER_MasterSignatureP *master_sig)
{ {
struct GNUNET_PQ_QueryParam params[] = { struct GNUNET_PQ_QueryParam params[] = {
@ -4378,6 +4389,7 @@ postgres_get_wire_fee (void *cls,
TALER_PQ_result_spec_absolute_time ("start_date", start_date), TALER_PQ_result_spec_absolute_time ("start_date", start_date),
TALER_PQ_result_spec_absolute_time ("end_date", end_date), TALER_PQ_result_spec_absolute_time ("end_date", end_date),
TALER_PQ_result_spec_amount ("wire_fee", wire_fee), TALER_PQ_result_spec_amount ("wire_fee", wire_fee),
TALER_PQ_result_spec_amount ("closing_fee", closing_fee),
GNUNET_PQ_result_spec_auto_from_type ("master_sig", master_sig), GNUNET_PQ_result_spec_auto_from_type ("master_sig", master_sig),
GNUNET_PQ_result_spec_end GNUNET_PQ_result_spec_end
}; };
@ -4398,6 +4410,7 @@ postgres_get_wire_fee (void *cls,
* @param start_date when does the fee go into effect * @param start_date when does the fee go into effect
* @param end_date when does the fee end being valid * @param end_date when does the fee end being valid
* @param wire_fee how high is the wire transfer fee * @param wire_fee how high is the wire transfer fee
* @param closing_fee how high is the closing fee
* @param master_sig signature over the above by the exchange master key * @param master_sig signature over the above by the exchange master key
* @return transaction status code * @return transaction status code
*/ */
@ -4408,6 +4421,7 @@ postgres_insert_wire_fee (void *cls,
struct GNUNET_TIME_Absolute start_date, struct GNUNET_TIME_Absolute start_date,
struct GNUNET_TIME_Absolute end_date, struct GNUNET_TIME_Absolute end_date,
const struct TALER_Amount *wire_fee, const struct TALER_Amount *wire_fee,
const struct TALER_Amount *closing_fee,
const struct TALER_MasterSignatureP *master_sig) const struct TALER_MasterSignatureP *master_sig)
{ {
struct GNUNET_PQ_QueryParam params[] = { struct GNUNET_PQ_QueryParam params[] = {
@ -4415,10 +4429,12 @@ postgres_insert_wire_fee (void *cls,
TALER_PQ_query_param_absolute_time (&start_date), TALER_PQ_query_param_absolute_time (&start_date),
TALER_PQ_query_param_absolute_time (&end_date), TALER_PQ_query_param_absolute_time (&end_date),
TALER_PQ_query_param_amount (wire_fee), TALER_PQ_query_param_amount (wire_fee),
TALER_PQ_query_param_amount (closing_fee),
GNUNET_PQ_query_param_auto_from_type (master_sig), GNUNET_PQ_query_param_auto_from_type (master_sig),
GNUNET_PQ_query_param_end GNUNET_PQ_query_param_end
}; };
struct TALER_Amount wf; struct TALER_Amount wf;
struct TALER_Amount cf;
struct TALER_MasterSignatureP sig; struct TALER_MasterSignatureP sig;
struct GNUNET_TIME_Absolute sd; struct GNUNET_TIME_Absolute sd;
struct GNUNET_TIME_Absolute ed; struct GNUNET_TIME_Absolute ed;
@ -4431,6 +4447,7 @@ postgres_insert_wire_fee (void *cls,
&sd, &sd,
&ed, &ed,
&wf, &wf,
&cf,
&sig); &sig);
if (qs < 0) if (qs < 0)
return qs; return qs;
@ -4449,6 +4466,12 @@ postgres_insert_wire_fee (void *cls,
GNUNET_break (0); GNUNET_break (0);
return GNUNET_DB_STATUS_HARD_ERROR; return GNUNET_DB_STATUS_HARD_ERROR;
} }
if (0 != TALER_amount_cmp (closing_fee,
&cf))
{
GNUNET_break (0);
return GNUNET_DB_STATUS_HARD_ERROR;
}
if ( (sd.abs_value_us != start_date.abs_value_us) || if ( (sd.abs_value_us != start_date.abs_value_us) ||
(ed.abs_value_us != end_date.abs_value_us) ) (ed.abs_value_us != end_date.abs_value_us) )
{ {

View File

@ -1062,10 +1062,12 @@ test_wire_fees (struct TALER_EXCHANGEDB_Session *session)
struct GNUNET_TIME_Absolute start_date; struct GNUNET_TIME_Absolute start_date;
struct GNUNET_TIME_Absolute end_date; struct GNUNET_TIME_Absolute end_date;
struct TALER_Amount wire_fee; struct TALER_Amount wire_fee;
struct TALER_Amount closing_fee;
struct TALER_MasterSignatureP master_sig; struct TALER_MasterSignatureP master_sig;
struct GNUNET_TIME_Absolute sd; struct GNUNET_TIME_Absolute sd;
struct GNUNET_TIME_Absolute ed; struct GNUNET_TIME_Absolute ed;
struct TALER_Amount fee; struct TALER_Amount fee;
struct TALER_Amount fee2;
struct TALER_MasterSignatureP ms; struct TALER_MasterSignatureP ms;
start_date = GNUNET_TIME_absolute_get (); start_date = GNUNET_TIME_absolute_get ();
@ -1075,6 +1077,9 @@ test_wire_fees (struct TALER_EXCHANGEDB_Session *session)
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (CURRENCY ":1.424242", TALER_string_to_amount (CURRENCY ":1.424242",
&wire_fee)); &wire_fee));
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (CURRENCY ":2.424242",
&closing_fee));
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
&master_sig, &master_sig,
sizeof (master_sig)); sizeof (master_sig));
@ -1085,6 +1090,7 @@ test_wire_fees (struct TALER_EXCHANGEDB_Session *session)
start_date, start_date,
end_date, end_date,
&wire_fee, &wire_fee,
&closing_fee,
&master_sig)) &master_sig))
{ {
GNUNET_break (0); GNUNET_break (0);
@ -1097,6 +1103,7 @@ test_wire_fees (struct TALER_EXCHANGEDB_Session *session)
start_date, start_date,
end_date, end_date,
&wire_fee, &wire_fee,
&closing_fee,
&master_sig)) &master_sig))
{ {
GNUNET_break (0); GNUNET_break (0);
@ -1112,6 +1119,7 @@ test_wire_fees (struct TALER_EXCHANGEDB_Session *session)
&sd, &sd,
&ed, &ed,
&fee, &fee,
&fee2,
&ms)) &ms))
{ {
GNUNET_break (0); GNUNET_break (0);
@ -1125,6 +1133,7 @@ test_wire_fees (struct TALER_EXCHANGEDB_Session *session)
&sd, &sd,
&ed, &ed,
&fee, &fee,
&fee2,
&ms)) &ms))
{ {
GNUNET_break (0); GNUNET_break (0);
@ -1134,6 +1143,8 @@ test_wire_fees (struct TALER_EXCHANGEDB_Session *session)
(ed.abs_value_us != end_date.abs_value_us) || (ed.abs_value_us != end_date.abs_value_us) ||
(0 != TALER_amount_cmp (&fee, (0 != TALER_amount_cmp (&fee,
&wire_fee)) || &wire_fee)) ||
(0 != TALER_amount_cmp (&fee2,
&closing_fee)) ||
(0 != memcmp (&ms, (0 != memcmp (&ms,
&master_sig, &master_sig,
sizeof (ms))) ) sizeof (ms))) )
@ -1956,7 +1967,8 @@ run (void *cls)
refund.merchant_pub = deposit.merchant_pub; refund.merchant_pub = deposit.merchant_pub;
RND_BLK (&refund.merchant_sig); RND_BLK (&refund.merchant_sig);
refund.h_contract_terms = deposit.h_contract_terms; refund.h_contract_terms = deposit.h_contract_terms;
refund.rtransaction_id = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); refund.rtransaction_id = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
UINT64_MAX);
refund.refund_amount = deposit.amount_with_fee; refund.refund_amount = deposit.amount_with_fee;
refund.refund_fee = fee_refund; refund.refund_fee = fee_refund;
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
@ -2198,9 +2210,11 @@ main (int argc,
NULL); NULL);
plugin_name++; plugin_name++;
(void) GNUNET_asprintf (&testname, (void) GNUNET_asprintf (&testname,
"test-exchange-db-%s", plugin_name); "test-exchange-db-%s",
plugin_name);
(void) GNUNET_asprintf (&config_filename, (void) GNUNET_asprintf (&config_filename,
"%s.conf", testname); "%s.conf",
testname);
cfg = GNUNET_CONFIGURATION_create (); cfg = GNUNET_CONFIGURATION_create ();
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_CONFIGURATION_parse (cfg, GNUNET_CONFIGURATION_parse (cfg,
@ -2211,7 +2225,8 @@ main (int argc,
GNUNET_free (testname); GNUNET_free (testname);
return 2; return 2;
} }
GNUNET_SCHEDULER_run (&run, cfg); GNUNET_SCHEDULER_run (&run,
cfg);
GNUNET_CONFIGURATION_destroy (cfg); GNUNET_CONFIGURATION_destroy (cfg);
GNUNET_free (config_filename); GNUNET_free (config_filename);
GNUNET_free (testname); GNUNET_free (testname);

View File

@ -1698,6 +1698,7 @@ struct TALER_EXCHANGEDB_Plugin
* @param start_date when does the fee go into effect * @param start_date when does the fee go into effect
* @param end_date when does the fee end being valid * @param end_date when does the fee end being valid
* @param wire_fee how high is the wire transfer fee * @param wire_fee how high is the wire transfer fee
* @param closing_fee how high is the closing fee
* @param master_sig signature over the above by the exchange master key * @param master_sig signature over the above by the exchange master key
* @return transaction status code * @return transaction status code
*/ */
@ -1708,6 +1709,7 @@ struct TALER_EXCHANGEDB_Plugin
struct GNUNET_TIME_Absolute start_date, struct GNUNET_TIME_Absolute start_date,
struct GNUNET_TIME_Absolute end_date, struct GNUNET_TIME_Absolute end_date,
const struct TALER_Amount *wire_fee, const struct TALER_Amount *wire_fee,
const struct TALER_Amount *closing_fee,
const struct TALER_MasterSignatureP *master_sig); const struct TALER_MasterSignatureP *master_sig);
@ -1721,6 +1723,7 @@ struct TALER_EXCHANGEDB_Plugin
* @param[out] start_date when does the fee go into effect * @param[out] start_date when does the fee go into effect
* @param[out] end_date when does the fee end being valid * @param[out] end_date when does the fee end being valid
* @param[out] wire_fee how high is the wire transfer fee * @param[out] wire_fee how high is the wire transfer fee
* @param[out] closing_fee how high is the closing fee
* @param[out] master_sig signature over the above by the exchange master key * @param[out] master_sig signature over the above by the exchange master key
* @return query status of the transaction * @return query status of the transaction
*/ */
@ -1732,6 +1735,7 @@ struct TALER_EXCHANGEDB_Plugin
struct GNUNET_TIME_Absolute *start_date, struct GNUNET_TIME_Absolute *start_date,
struct GNUNET_TIME_Absolute *end_date, struct GNUNET_TIME_Absolute *end_date,
struct TALER_Amount *wire_fee, struct TALER_Amount *wire_fee,
struct TALER_Amount *closing_fee,
struct TALER_MasterSignatureP *master_sig); struct TALER_MasterSignatureP *master_sig);