diff options
| author | Christian Grothoff <christian@grothoff.org> | 2019-07-27 20:06:55 +0200 | 
|---|---|---|
| committer | Christian Grothoff <christian@grothoff.org> | 2019-07-27 20:06:55 +0200 | 
| commit | 1057333666ad3aa17568255f0b7ffa1a2d9bcf40 (patch) | |
| tree | 54a0f26b9cb3971e9bd1b6d33b2d7d654db86215 /src | |
| parent | 19c4feda562ca09ecef5c79d29fae36169ea9900 (diff) | |
add check that denomination was actually revoked if it is involved in /payback
Diffstat (limited to 'src')
| -rw-r--r-- | src/auditor/taler-auditor.c | 67 | 
1 files changed, 57 insertions, 10 deletions
| diff --git a/src/auditor/taler-auditor.c b/src/auditor/taler-auditor.c index a63ac8bd..c8becdaa 100644 --- a/src/auditor/taler-auditor.c +++ b/src/auditor/taler-auditor.c @@ -30,8 +30,6 @@   *   (While as the exchange could easily falsify those, we should   *    probably check as otherwise insider *without* RSA private key   *    access could still create false paybacks to drain exchange funds!) - * - we don't check that for payback operations the denomination was actually - *   revoked (FIXME exists!)   * - error handling if denomination keys are used that are not known to the   *   auditor is, eh, awful / non-existent. We just throw the DB's constraint   *   violation back at the user. Great UX. @@ -581,7 +579,7 @@ static struct GNUNET_CONTAINER_MultiHashMap *denominations;   */  static enum GNUNET_DB_QueryStatus  get_denomination_info_by_hash (const struct GNUNET_HashCode *dh, -                       const struct TALER_EXCHANGEDB_DenominationKeyInformationP **dki) +                               const struct TALER_EXCHANGEDB_DenominationKeyInformationP **dki)  {    struct TALER_EXCHANGEDB_DenominationKeyInformationP *dkip;    enum GNUNET_DB_QueryStatus qs; @@ -964,8 +962,8 @@ handle_reserve_out (void *cls,    /* lookup denomination pub data (make sure denom_pub is valid, establish fees) */    qs = get_denomination_info (denom_pub, -			      &dki, -			      &wsrd.h_denomination_pub); +                              &dki, +                              &wsrd.h_denomination_pub);    if (0 > qs)    {      GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); @@ -2897,6 +2895,11 @@ struct DenominationSummary     * #sync_denomination().     */    int in_db; + +  /** +   * #GNUNET_YES if this denomination was revoked. +   */ +  int was_revoked;  }; @@ -2936,6 +2939,8 @@ init_denomination (const struct GNUNET_HashCode *denom_hash,                     struct DenominationSummary *ds)  {    enum GNUNET_DB_QueryStatus qs; +  struct TALER_MasterSignatureP msig; +  uint64_t rowid;    qs = adb->get_denomination_balance (adb->cls,                                        asession, @@ -2958,6 +2963,39 @@ init_denomination (const struct GNUNET_HashCode *denom_hash,                  TALER_amount2s (&ds->denom_balance));      return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;    } +  qs = edb->get_denomination_revocation (edb->cls, +                                         esession, +                                         denom_hash, +                                         &msig, +                                         &rowid); +  if (0 > qs) +  { +    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); +    return qs; +  } +  if (0 < qs) +  { +    /* check revocation signature */ +    struct TALER_MasterDenominationKeyRevocationPS rm; + +    rm.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_DENOMINATION_KEY_REVOKED); +    rm.purpose.size = htonl (sizeof (rm)); +    rm.h_denom_pub = *denom_hash; +    if (GNUNET_OK != +        GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_DENOMINATION_KEY_REVOKED, +                                    &rm.purpose, +                                    &msig.eddsa_signature, +                                    &master_pub.eddsa_pub)) +    { +      report_row_inconsistency ("denomination revocation table", +                                rowid, +                                "revocation signature invalid"); +    } +    else +    { +      ds->was_revoked = GNUNET_YES; +    } +  }    GNUNET_assert (GNUNET_OK ==                   TALER_amount_get_zero (currency,                                          &ds->denom_balance)); @@ -3351,8 +3389,8 @@ refresh_session_cb (void *cls,    ppc.last_melt_serial_id = rowid + 1;    qs = get_denomination_info (denom_pub, -			      &dki, -			      NULL); +                              &dki, +                              NULL);    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)    {      GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); @@ -3686,8 +3724,8 @@ deposit_cb (void *cls,    ppc.last_deposit_serial_id = rowid + 1;    qs = get_denomination_info (denom_pub, -			      &dki, -			      NULL); +                              &dki, +                              NULL);    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)    {      GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); @@ -4023,7 +4061,16 @@ check_payback (struct CoinContext *cc,    ds = get_denomination_summary (cc,                                   dki,                                   &dki->properties.denom_hash); -  /* FIXME: should check that denomination was actually revoked! */ +  if (GNUNET_NO == ds->was_revoked) +  { +    /* Woopsie, we allowed payback on non-revoked denomination!? */ +    report (report_bad_sig_losses, +            json_pack ("{s:s, s:I, s:o, s:o}", +                       "operation", "payback (denomination not revoked)", +                       "row", (json_int_t) rowid, +                       "loss", TALER_JSON_from_amount (amount), +                       "coin_pub", GNUNET_JSON_from_data_auto (&coin->coin_pub))); +  }    GNUNET_break (GNUNET_OK ==                  TALER_amount_add (&ds->denom_payback,                                    &ds->denom_payback, | 
