load fees from DB instead of from config, also in wire tools
This commit is contained in:
parent
e0497239e9
commit
6f6c71a8d3
@ -15,7 +15,6 @@ bin_PROGRAMS = \
|
||||
taler-auditor-dbinit \
|
||||
taler-auditor-exchange \
|
||||
taler-auditor-httpd \
|
||||
taler-auditor-sign \
|
||||
taler-helper-auditor-aggregation \
|
||||
taler-helper-auditor-coins \
|
||||
taler-helper-auditor-deposits \
|
||||
@ -156,17 +155,6 @@ taler_auditor_httpd_LDADD = \
|
||||
-lz \
|
||||
$(XLIB)
|
||||
|
||||
taler_auditor_sign_SOURCES = \
|
||||
taler-auditor-sign.c
|
||||
taler_auditor_sign_LDADD = \
|
||||
$(LIBGCRYPT_LIBS) \
|
||||
$(top_builddir)/src/util/libtalerutil.la \
|
||||
$(top_builddir)/src/auditordb/libtalerauditordb.la \
|
||||
$(top_builddir)/src/exchangedb/libtalerexchangedb.la \
|
||||
-lgnunetutil \
|
||||
$(XLIB)
|
||||
|
||||
|
||||
taler_auditor_exchange_SOURCES = \
|
||||
taler-auditor-exchange.c
|
||||
taler_auditor_exchange_LDADD = \
|
||||
@ -195,9 +183,7 @@ EXTRA_DIST = \
|
||||
$(check_SCRIPTS) \
|
||||
auditor-basedb.age \
|
||||
auditor-basedb.sql \
|
||||
auditor-basedb.fees \
|
||||
auditor-basedb.mpub \
|
||||
revoke-basedb.age \
|
||||
revoke-basedb.sql \
|
||||
revoke-basedb.fees \
|
||||
revoke-basedb.mpub
|
||||
|
@ -1 +1 @@
|
||||
1607688843
|
||||
1608125224
|
||||
|
@ -1 +1 @@
|
||||
7W3RY6X05KGPE78JXGGGZWQ3XKA7TW4CVBEWZQA4PRVHFZEW05WG
|
||||
NKW2PKVQP9DZSBWGEX7Y7AP3BEV0MYYNZWC8WQ9EED22E74PGH50
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,437 +0,0 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014, 2015, 2018 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 3, or (at your option) any later version.
|
||||
|
||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file taler-auditor-sign.c
|
||||
* @brief Tool used by the auditor to sign the exchange's master key and the
|
||||
* denomination key(s).
|
||||
* @author Christian Grothoff
|
||||
*/
|
||||
#include <platform.h>
|
||||
#include "taler_exchangedb_lib.h"
|
||||
#include "taler_auditordb_lib.h"
|
||||
|
||||
|
||||
/**
|
||||
* Are we running in verbose mode?
|
||||
*/
|
||||
static unsigned int verbose;
|
||||
|
||||
/**
|
||||
* Filename of the auditor's private key.
|
||||
*/
|
||||
static char *auditor_key_file;
|
||||
|
||||
/**
|
||||
* File with the Exchange's denomination keys to sign, itself
|
||||
* signed by the Exchange's public key.
|
||||
*/
|
||||
static char *exchange_request_file;
|
||||
|
||||
/**
|
||||
* Where should we write the auditor's signature?
|
||||
*/
|
||||
static char *output_file;
|
||||
|
||||
/**
|
||||
* URL of the auditor (informative for the user).
|
||||
*/
|
||||
static char *auditor_url;
|
||||
|
||||
/**
|
||||
* Master public key of the exchange.
|
||||
*/
|
||||
static struct TALER_MasterPublicKeyP master_public_key;
|
||||
|
||||
/**
|
||||
* Our configuration.
|
||||
*/
|
||||
static struct GNUNET_CONFIGURATION_Handle *cfg;
|
||||
|
||||
/**
|
||||
* Handle to access the auditor's database.
|
||||
*/
|
||||
static struct TALER_AUDITORDB_Plugin *adb;
|
||||
|
||||
|
||||
/**
|
||||
* Print denomination key details for diagnostics.
|
||||
*
|
||||
* @param dk denomination key to print
|
||||
*/
|
||||
static void
|
||||
print_dk (const struct TALER_DenominationKeyValidityPS *dk)
|
||||
{
|
||||
struct TALER_Amount a;
|
||||
char *s;
|
||||
|
||||
fprintf (stdout,
|
||||
"Denomination key hash: %s\n",
|
||||
GNUNET_h2s_full (&dk->denom_hash));
|
||||
TALER_amount_ntoh (&a,
|
||||
&dk->value);
|
||||
fprintf (stdout,
|
||||
"Value: %s\n",
|
||||
s = TALER_amount_to_string (&a));
|
||||
GNUNET_free (s);
|
||||
TALER_amount_ntoh (&a,
|
||||
&dk->fee_withdraw);
|
||||
fprintf (stdout,
|
||||
"Withdraw fee: %s\n",
|
||||
s = TALER_amount_to_string (&a));
|
||||
GNUNET_free (s);
|
||||
TALER_amount_ntoh (&a,
|
||||
&dk->fee_deposit);
|
||||
fprintf (stdout,
|
||||
"Deposit fee: %s\n",
|
||||
s = TALER_amount_to_string (&a));
|
||||
GNUNET_free (s);
|
||||
TALER_amount_ntoh (&a,
|
||||
&dk->fee_refresh);
|
||||
fprintf (stdout,
|
||||
"Refresh fee: %s\n",
|
||||
s = TALER_amount_to_string (&a));
|
||||
GNUNET_free (s);
|
||||
TALER_amount_ntoh (&a,
|
||||
&dk->fee_refund);
|
||||
fprintf (stdout,
|
||||
"Refund fee: %s\n",
|
||||
s = TALER_amount_to_string (&a));
|
||||
GNUNET_free (s);
|
||||
|
||||
fprintf (stdout,
|
||||
"Validity start time: %s\n",
|
||||
GNUNET_STRINGS_absolute_time_to_string (GNUNET_TIME_absolute_ntoh (
|
||||
dk->start)));
|
||||
fprintf (stdout,
|
||||
"Withdraw end time: %s\n",
|
||||
GNUNET_STRINGS_absolute_time_to_string (GNUNET_TIME_absolute_ntoh (
|
||||
dk->expire_withdraw)));
|
||||
fprintf (stdout,
|
||||
"Deposit end time: %s\n",
|
||||
GNUNET_STRINGS_absolute_time_to_string (GNUNET_TIME_absolute_ntoh (
|
||||
dk->expire_deposit)));
|
||||
fprintf (stdout,
|
||||
"Legal dispute end time: %s\n",
|
||||
GNUNET_STRINGS_absolute_time_to_string (GNUNET_TIME_absolute_ntoh (
|
||||
dk->expire_legal)));
|
||||
|
||||
fprintf (stdout,
|
||||
"\n");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The main function of the taler-auditor-sign tool. This tool is used
|
||||
* to sign a exchange's master and denomination keys, affirming that the
|
||||
* auditor is aware of them and will validate the exchange's database with
|
||||
* respect to these keys.
|
||||
*
|
||||
* @param argc number of arguments from the command line
|
||||
* @param argv command line arguments
|
||||
* @return 0 ok, 1 on error
|
||||
*/
|
||||
int
|
||||
main (int argc,
|
||||
char *const *argv)
|
||||
{
|
||||
char *cfgfile = NULL;
|
||||
char *loglev = NULL;
|
||||
char *logfile = NULL;
|
||||
const struct GNUNET_GETOPT_CommandLineOption options[] = {
|
||||
GNUNET_GETOPT_option_filename ('a',
|
||||
"auditor-key",
|
||||
"FILENAME",
|
||||
"file containing the private key of the auditor",
|
||||
&auditor_key_file),
|
||||
GNUNET_GETOPT_option_cfgfile (&cfgfile),
|
||||
GNUNET_GETOPT_option_help ("Sign denomination keys of an exchange"),
|
||||
GNUNET_GETOPT_option_loglevel (&loglev),
|
||||
GNUNET_GETOPT_option_logfile (&logfile),
|
||||
GNUNET_GETOPT_option_mandatory
|
||||
(GNUNET_GETOPT_option_base32_auto ('m',
|
||||
"exchange-key",
|
||||
"KEY",
|
||||
"public key of the exchange (Crockford base32 encoded)",
|
||||
&master_public_key)),
|
||||
GNUNET_GETOPT_option_string ('u',
|
||||
"auditor-url",
|
||||
"URL",
|
||||
"URL of the auditor (informative link for the user)",
|
||||
&auditor_url),
|
||||
GNUNET_GETOPT_option_mandatory
|
||||
(GNUNET_GETOPT_option_filename ('r',
|
||||
"exchange-request",
|
||||
"FILENAME",
|
||||
"set of keys the exchange requested the auditor to sign",
|
||||
&exchange_request_file)),
|
||||
GNUNET_GETOPT_option_filename ('o',
|
||||
"output",
|
||||
"FILENAME",
|
||||
"where to write our signature",
|
||||
&output_file),
|
||||
GNUNET_GETOPT_option_version (VERSION "-" VCS_VERSION),
|
||||
GNUNET_GETOPT_option_verbose (&verbose),
|
||||
GNUNET_GETOPT_OPTION_END
|
||||
};
|
||||
struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv;
|
||||
struct TALER_AuditorSignatureP *sigs;
|
||||
struct TALER_AuditorPublicKeyP apub;
|
||||
struct GNUNET_DISK_FileHandle *fh;
|
||||
struct TALER_DenominationKeyValidityPS *dki;
|
||||
unsigned int dki_len;
|
||||
struct TALER_ExchangeKeyValidityPS kv;
|
||||
off_t in_size;
|
||||
|
||||
if (GNUNET_GETOPT_run ("taler-auditor-sign",
|
||||
options,
|
||||
argc, argv) <= 0)
|
||||
return 1;
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
GNUNET_log_setup ("taler-auditor-sign",
|
||||
loglev,
|
||||
logfile));
|
||||
if (NULL == cfgfile)
|
||||
cfgfile = GNUNET_strdup (GNUNET_OS_project_data_get ()->user_config_file);
|
||||
cfg = GNUNET_CONFIGURATION_create ();
|
||||
if (GNUNET_SYSERR ==
|
||||
GNUNET_CONFIGURATION_load (cfg,
|
||||
cfgfile))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Malformed configuration file `%s', exiting ...\n",
|
||||
cfgfile);
|
||||
GNUNET_free (cfgfile);
|
||||
return 1;
|
||||
}
|
||||
GNUNET_free (cfgfile);
|
||||
if ( (NULL == auditor_key_file) &&
|
||||
(GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_get_value_filename (cfg,
|
||||
"auditor",
|
||||
"AUDITOR_PRIV_FILE",
|
||||
&auditor_key_file)) )
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Auditor key file not given in neither configuration nor command-line\n");
|
||||
return 1;
|
||||
}
|
||||
if ( (NULL == auditor_url) &&
|
||||
(GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_get_value_string (cfg,
|
||||
"auditor",
|
||||
"AUDITOR_URL",
|
||||
&auditor_url)) )
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Auditor URL not given in neither configuration nor command-line\n");
|
||||
return 1;
|
||||
}
|
||||
if (GNUNET_SYSERR ==
|
||||
GNUNET_CRYPTO_eddsa_key_from_file (auditor_key_file,
|
||||
GNUNET_YES,
|
||||
&eddsa_priv))
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Failed to initialize auditor private key from file `%s'\n",
|
||||
auditor_key_file);
|
||||
return 1;
|
||||
}
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&eddsa_priv,
|
||||
&apub.eddsa_pub);
|
||||
fh = GNUNET_DISK_file_open (exchange_request_file,
|
||||
GNUNET_DISK_OPEN_READ,
|
||||
GNUNET_DISK_PERM_NONE);
|
||||
if (NULL == fh)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Failed to open file `%s': %s\n",
|
||||
exchange_request_file,
|
||||
strerror (errno));
|
||||
return 1;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_DISK_file_handle_size (fh,
|
||||
&in_size))
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Failed to obtain input file size `%s': %s\n",
|
||||
exchange_request_file,
|
||||
strerror (errno));
|
||||
GNUNET_DISK_file_close (fh);
|
||||
return 1;
|
||||
}
|
||||
if (0 != (in_size % sizeof (struct TALER_DenominationKeyValidityPS)))
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Input file size of file `%s' is invalid\n",
|
||||
exchange_request_file);
|
||||
GNUNET_DISK_file_close (fh);
|
||||
return 1;
|
||||
}
|
||||
dki_len = in_size / sizeof (struct TALER_DenominationKeyValidityPS);
|
||||
if (0 == dki_len)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Failed to produce auditor signature, denomination list is empty.\n");
|
||||
GNUNET_DISK_file_close (fh);
|
||||
return 2;
|
||||
}
|
||||
if (NULL ==
|
||||
(adb = TALER_AUDITORDB_plugin_load (cfg)))
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Failed to initialize auditor database plugin.\n");
|
||||
GNUNET_DISK_file_close (fh);
|
||||
return 3;
|
||||
}
|
||||
|
||||
kv.purpose.purpose = htonl (TALER_SIGNATURE_AUDITOR_EXCHANGE_KEYS);
|
||||
kv.purpose.size = htonl (sizeof (struct TALER_ExchangeKeyValidityPS));
|
||||
GNUNET_CRYPTO_hash (auditor_url,
|
||||
strlen (auditor_url) + 1,
|
||||
&kv.auditor_url_hash);
|
||||
kv.master = master_public_key;
|
||||
dki = GNUNET_new_array (dki_len,
|
||||
struct TALER_DenominationKeyValidityPS);
|
||||
if (in_size !=
|
||||
GNUNET_DISK_file_read (fh,
|
||||
dki,
|
||||
in_size))
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Failed to read input file `%s': %s\n",
|
||||
exchange_request_file,
|
||||
strerror (errno));
|
||||
TALER_AUDITORDB_plugin_unload (adb);
|
||||
GNUNET_DISK_file_close (fh);
|
||||
GNUNET_free (dki);
|
||||
return 1;
|
||||
}
|
||||
GNUNET_DISK_file_close (fh);
|
||||
sigs = GNUNET_new_array (dki_len,
|
||||
struct TALER_AuditorSignatureP);
|
||||
for (unsigned int i = 0; i<dki_len; i++)
|
||||
{
|
||||
struct TALER_DenominationKeyValidityPS *dk = &dki[i];
|
||||
|
||||
if (verbose)
|
||||
print_dk (dk);
|
||||
kv.start = dk->start;
|
||||
kv.expire_withdraw = dk->expire_withdraw;
|
||||
kv.expire_deposit = dk->expire_deposit;
|
||||
kv.expire_legal = dk->expire_legal;
|
||||
kv.value = dk->value;
|
||||
kv.fee_withdraw = dk->fee_withdraw;
|
||||
kv.fee_deposit = dk->fee_deposit;
|
||||
kv.fee_refresh = dk->fee_refresh;
|
||||
kv.fee_refund = dk->fee_refund;
|
||||
kv.denom_hash = dk->denom_hash;
|
||||
|
||||
/* Finally sign ... */
|
||||
GNUNET_CRYPTO_eddsa_sign (&eddsa_priv,
|
||||
&kv,
|
||||
&sigs[i].eddsa_sig);
|
||||
}
|
||||
|
||||
if (NULL == output_file)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Output file not given\n");
|
||||
TALER_AUDITORDB_plugin_unload (adb);
|
||||
GNUNET_free (dki);
|
||||
GNUNET_free (sigs);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Create required tables */
|
||||
if (GNUNET_OK !=
|
||||
adb->create_tables (adb->cls))
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Failed to create tables in auditor's database\n");
|
||||
TALER_AUDITORDB_plugin_unload (adb);
|
||||
GNUNET_free (dki);
|
||||
GNUNET_free (sigs);
|
||||
return 3;
|
||||
}
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Taler auditor importing keys for exchange master public key %s\n",
|
||||
TALER_B2S (&master_public_key));
|
||||
|
||||
/* Update DB */
|
||||
{
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
struct TALER_AUDITORDB_Session *session;
|
||||
|
||||
session = adb->get_session (adb->cls);
|
||||
if (NULL == session)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Failed to initialize database session\n");
|
||||
TALER_AUDITORDB_plugin_unload (adb);
|
||||
GNUNET_free (dki);
|
||||
GNUNET_free (sigs);
|
||||
return 3;
|
||||
}
|
||||
for (unsigned int i = 0; i<dki_len; i++)
|
||||
{
|
||||
const struct TALER_DenominationKeyValidityPS *dk = &dki[i];
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Adding denomination key %s to auditor database\n",
|
||||
TALER_B2S (&dk->denom_hash));
|
||||
qs = adb->insert_denomination_info (adb->cls,
|
||||
session,
|
||||
dk);
|
||||
if (0 > qs)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Failed to store key in auditor DB (did you add the exchange using taler-auditor-exchange first?)\n");
|
||||
TALER_AUDITORDB_plugin_unload (adb);
|
||||
GNUNET_free (dki);
|
||||
GNUNET_free (sigs);
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
TALER_AUDITORDB_plugin_unload (adb);
|
||||
|
||||
/* write result to disk */
|
||||
if (GNUNET_OK !=
|
||||
TALER_EXCHANGEDB_auditor_write (output_file,
|
||||
&apub,
|
||||
auditor_url,
|
||||
sigs,
|
||||
&master_public_key,
|
||||
dki_len,
|
||||
dki))
|
||||
{
|
||||
fprintf (stderr,
|
||||
"Failed to write to file `%s': %s\n",
|
||||
output_file,
|
||||
strerror (errno));
|
||||
GNUNET_free (sigs);
|
||||
GNUNET_free (dki);
|
||||
return 1;
|
||||
}
|
||||
GNUNET_free (sigs);
|
||||
GNUNET_free (dki);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* end of taler-auditor-sign.c */
|
@ -1798,12 +1798,6 @@ check_with_database()
|
||||
# Setup database-specific globals
|
||||
MASTER_PUB=`cat ${BASEDB}.mpub`
|
||||
|
||||
# Where to store wire fee details for aggregator
|
||||
echo "Storing wire fees"
|
||||
WIRE_FEE_DIR=`taler-config -c $CONF -f -s exchangedb -o WIREFEE_BASE_DIR`
|
||||
mkdir -p $WIRE_FEE_DIR
|
||||
cp ${BASEDB}.fees $WIRE_FEE_DIR/x-taler-bank.fee
|
||||
|
||||
# Determine database age
|
||||
echo "Calculating database age based on ${BASEDB}.age"
|
||||
AGE=`cat ${BASEDB}.age`
|
||||
|
@ -472,12 +472,6 @@ check_with_database()
|
||||
# Setup database-specific globals
|
||||
MASTER_PUB=`cat ${BASEDB}.mpub`
|
||||
|
||||
# Where to store wire fee details for aggregator
|
||||
echo "Storing wire fees"
|
||||
WIRE_FEE_DIR=`taler-config -c $CONF -f -s exchangedb -o WIREFEE_BASE_DIR`
|
||||
mkdir -p $WIRE_FEE_DIR
|
||||
cp ${BASEDB}.fees $WIRE_FEE_DIR/x-taler-bank.fee
|
||||
|
||||
# Determine database age
|
||||
echo "Calculating database age based on ${BASEDB}.age"
|
||||
AGE=`cat ${BASEDB}.age`
|
||||
|
@ -455,21 +455,29 @@ deposit_cb (void *cls,
|
||||
au->execution_time = GNUNET_TIME_absolute_get ();
|
||||
(void) GNUNET_TIME_round_abs (&au->execution_time);
|
||||
{
|
||||
struct TALER_EXCHANGEDB_AggregateFees *af;
|
||||
struct TALER_Amount closing_fee;
|
||||
struct GNUNET_TIME_Absolute start_date;
|
||||
struct GNUNET_TIME_Absolute end_date;
|
||||
struct TALER_MasterSignatureP master_sig;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
af = TALER_EXCHANGEDB_update_fees (cfg,
|
||||
db_plugin,
|
||||
au->wa,
|
||||
qs = db_plugin->get_wire_fee (db_plugin->cls,
|
||||
au->session,
|
||||
au->wa->method,
|
||||
au->execution_time,
|
||||
au->session);
|
||||
if (NULL == af)
|
||||
&start_date,
|
||||
&end_date,
|
||||
&au->wire_fee,
|
||||
&closing_fee,
|
||||
&master_sig);
|
||||
if (0 >= qs)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Could not get or persist wire fees for %s. Aborting run.\n",
|
||||
"Could not get wire fees for %s at %s. Aborting run.\n",
|
||||
au->wa->method,
|
||||
GNUNET_STRINGS_absolute_time_to_string (au->execution_time));
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
}
|
||||
au->wire_fee = af->wire_fee;
|
||||
}
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
|
@ -248,7 +248,7 @@ expired_reserve_cb (void *cls,
|
||||
struct GNUNET_TIME_Absolute now;
|
||||
struct TALER_WireTransferIdentifierRawP wtid;
|
||||
struct TALER_Amount amount_without_fee;
|
||||
const struct TALER_Amount *closing_fee;
|
||||
struct TALER_Amount closing_fee;
|
||||
int ret;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
struct TALER_EXCHANGEDB_WireAccount *wa;
|
||||
@ -276,32 +276,41 @@ expired_reserve_cb (void *cls,
|
||||
/* lookup `closing_fee` from time of actual reserve expiration
|
||||
(we may be lagging behind!) */
|
||||
{
|
||||
struct TALER_EXCHANGEDB_AggregateFees *af;
|
||||
struct TALER_Amount wire_fee;
|
||||
struct GNUNET_TIME_Absolute start_date;
|
||||
struct GNUNET_TIME_Absolute end_date;
|
||||
struct TALER_MasterSignatureP master_sig;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
af = TALER_EXCHANGEDB_update_fees (cfg,
|
||||
db_plugin,
|
||||
wa,
|
||||
qs = db_plugin->get_wire_fee (db_plugin->cls,
|
||||
session,
|
||||
wa->method,
|
||||
expiration_date,
|
||||
session);
|
||||
if (NULL == af)
|
||||
&start_date,
|
||||
&end_date,
|
||||
&wire_fee,
|
||||
&closing_fee,
|
||||
&master_sig);
|
||||
if (0 >= qs)
|
||||
{
|
||||
global_ret = GR_WIRE_TRANSFER_FEES_NOT_CONFIGURED;
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Could not get wire fees for %s at %s. Aborting run.\n",
|
||||
wa->method,
|
||||
GNUNET_STRINGS_absolute_time_to_string (expiration_date));
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
}
|
||||
closing_fee = &af->closing_fee;
|
||||
}
|
||||
|
||||
/* calculate transfer amount */
|
||||
ret = TALER_amount_subtract (&amount_without_fee,
|
||||
left,
|
||||
closing_fee);
|
||||
&closing_fee);
|
||||
if ( (GNUNET_SYSERR == ret) ||
|
||||
(GNUNET_NO == ret) )
|
||||
{
|
||||
/* Closing fee higher than or equal to remaining balance, close
|
||||
without wire transfer. */
|
||||
closing_fee = left;
|
||||
closing_fee = *left;
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_amount_get_zero (left->currency,
|
||||
&amount_without_fee));
|
||||
@ -337,7 +346,7 @@ expired_reserve_cb (void *cls,
|
||||
account_payto_uri,
|
||||
&wtid,
|
||||
left,
|
||||
closing_fee);
|
||||
&closing_fee);
|
||||
else
|
||||
qs = GNUNET_DB_STATUS_HARD_ERROR;
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
|
@ -53,11 +53,7 @@ lib_LTLIBRARIES = \
|
||||
|
||||
libtalerexchangedb_la_SOURCES = \
|
||||
exchangedb_accounts.c \
|
||||
exchangedb_auditorkeys.c \
|
||||
exchangedb_denomkeys.c \
|
||||
exchangedb_fees.c \
|
||||
exchangedb_plugin.c \
|
||||
exchangedb_signkeys.c \
|
||||
exchangedb_transactions.c
|
||||
libtalerexchangedb_la_LIBADD = \
|
||||
$(top_builddir)/src/bank-lib/libtalerbank.la \
|
||||
@ -71,51 +67,11 @@ libtalerexchangedb_la_LDFLAGS = \
|
||||
|
||||
|
||||
check_PROGRAMS = \
|
||||
test-exchangedb-auditors \
|
||||
test-exchangedb-denomkeys \
|
||||
test-exchangedb-fees \
|
||||
test-exchangedb-signkeys \
|
||||
test-exchangedb-postgres
|
||||
|
||||
AM_TESTS_ENVIRONMENT=export TALER_PREFIX=$${TALER_PREFIX:-@libdir@};export PATH=$${TALER_PREFIX:-@prefix@}/bin:$$PATH;
|
||||
TESTS = \
|
||||
test-exchangedb-auditors \
|
||||
test-exchangedb-denomkeys \
|
||||
test-exchangedb-fees \
|
||||
test-exchangedb-postgres \
|
||||
test-exchangedb-signkeys
|
||||
|
||||
test_exchangedb_auditors_SOURCES = \
|
||||
test_exchangedb_auditors.c
|
||||
test_exchangedb_auditors_LDADD = \
|
||||
libtalerexchangedb.la \
|
||||
$(top_srcdir)/src/util/libtalerutil.la \
|
||||
-lgnunetutil \
|
||||
$(XLIB)
|
||||
|
||||
test_exchangedb_denomkeys_SOURCES = \
|
||||
test_exchangedb_denomkeys.c
|
||||
test_exchangedb_denomkeys_LDADD = \
|
||||
libtalerexchangedb.la \
|
||||
$(top_srcdir)/src/util/libtalerutil.la \
|
||||
-lgnunetutil \
|
||||
$(XLIB)
|
||||
|
||||
test_exchangedb_fees_SOURCES = \
|
||||
test_exchangedb_fees.c
|
||||
test_exchangedb_fees_LDADD = \
|
||||
libtalerexchangedb.la \
|
||||
$(top_srcdir)/src/util/libtalerutil.la \
|
||||
-lgnunetutil \
|
||||
$(XLIB)
|
||||
|
||||
test_exchangedb_signkeys_SOURCES = \
|
||||
test_exchangedb_signkeys.c
|
||||
test_exchangedb_signkeys_LDADD = \
|
||||
libtalerexchangedb.la \
|
||||
$(top_srcdir)/src/util/libtalerutil.la \
|
||||
-lgnunetutil \
|
||||
$(XLIB)
|
||||
test-exchangedb-postgres
|
||||
|
||||
test_exchangedb_postgres_SOURCES = \
|
||||
test_exchangedb.c
|
||||
|
@ -305,7 +305,6 @@ TALER_EXCHANGEDB_unload_accounts (void)
|
||||
wa_tail,
|
||||
wa);
|
||||
TALER_BANK_auth_free (&wa->auth);
|
||||
TALER_EXCHANGEDB_fees_free (wa->af);
|
||||
GNUNET_free (wa->section_name);
|
||||
GNUNET_free (wa->method);
|
||||
GNUNET_free (wa);
|
||||
|
@ -1,344 +0,0 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014--2019 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 3, or (at your option) any later version.
|
||||
|
||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file exchangedb/exchangedb_auditorkeys.c
|
||||
* @brief I/O operations for the Exchange's auditor data
|
||||
* @author Florian Dold
|
||||
* @author Benedikt Mueller
|
||||
* @author Sree Harsha Totakura
|
||||
* @author Christian Grothoff
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "taler_exchangedb_lib.h"
|
||||
|
||||
|
||||
/**
|
||||
* Closure for #auditor_iter() and
|
||||
*/
|
||||
struct AuditorIterateContext
|
||||
{
|
||||
|
||||
/**
|
||||
* Function to call with the information for each auditor.
|
||||
*/
|
||||
TALER_EXCHANGEDB_AuditorIterator it;
|
||||
|
||||
/**
|
||||
* Closure for @e it.
|
||||
*/
|
||||
void *it_cls;
|
||||
|
||||
/**
|
||||
* Status of the iteration.
|
||||
*/
|
||||
int status;
|
||||
};
|
||||
|
||||
|
||||
GNUNET_NETWORK_STRUCT_BEGIN
|
||||
|
||||
/**
|
||||
* Header of a file with auditing information.
|
||||
*/
|
||||
struct AuditorFileHeaderP
|
||||
{
|
||||
|
||||
/**
|
||||
* Public key of the auditor.
|
||||
*/
|
||||
struct TALER_AuditorPublicKeyP apub;
|
||||
|
||||
/**
|
||||
* Master public key of the exchange the auditor is signing
|
||||
* information for.
|
||||
*/
|
||||
struct TALER_MasterPublicKeyP mpub;
|
||||
|
||||
/**
|
||||
* Number of signatures and DKI entries in this file.
|
||||
*/
|
||||
uint32_t dki_len;
|
||||
|
||||
};
|
||||
GNUNET_NETWORK_STRUCT_END
|
||||
|
||||
|
||||
/**
|
||||
* Load the auditor signature and the information signed by the
|
||||
* auditor and call the callback in @a cls with the information.
|
||||
*
|
||||
* @param cls the `struct AuditorIterateContext *`
|
||||
* @param filename name of a file that should contain
|
||||
* a denomination key
|
||||
* @return #GNUNET_OK to continue to iterate
|
||||
* #GNUNET_NO to abort iteration with success
|
||||
* #GNUNET_SYSERR to abort iteration with failure
|
||||
*/
|
||||
static int
|
||||
auditor_iter (void *cls,
|
||||
const char *filename)
|
||||
{
|
||||
struct AuditorIterateContext *aic = cls;
|
||||
uint64_t size;
|
||||
struct AuditorFileHeaderP *af;
|
||||
const struct TALER_AuditorSignatureP *sigs;
|
||||
const struct TALER_DenominationKeyValidityPS *dki;
|
||||
const char *auditor_url;
|
||||
uint32_t dki_len;
|
||||
size_t url_len;
|
||||
int iret;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_DISK_file_size (filename,
|
||||
&size,
|
||||
GNUNET_YES,
|
||||
GNUNET_YES))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Skipping inaccessible auditor information file `%s'\n",
|
||||
filename);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
if (size < sizeof (struct AuditorFileHeaderP))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"File size (%llu bytes) too small for file `%s' to contain auditor data. Skipping it.\n",
|
||||
(unsigned long long) size,
|
||||
filename);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
if (size >= GNUNET_MAX_MALLOC_CHECKED)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"File size (%llu bytes) too large for file `%s' to contain auditor data. Skipping it.\n",
|
||||
(unsigned long long) size,
|
||||
filename);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
af = GNUNET_malloc (size);
|
||||
if (((ssize_t) size) !=
|
||||
GNUNET_DISK_fn_read (filename,
|
||||
af,
|
||||
size))
|
||||
{
|
||||
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
|
||||
"read",
|
||||
filename);
|
||||
GNUNET_free (af);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
dki_len = ntohl (af->dki_len);
|
||||
if (0 == dki_len)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"No signed keys in %s\n",
|
||||
filename);
|
||||
GNUNET_free (af);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
size -= sizeof (struct AuditorFileHeaderP);
|
||||
if ( (size / dki_len) <
|
||||
(sizeof (struct TALER_DenominationKeyValidityPS)
|
||||
+ sizeof (struct TALER_AuditorSignatureP)) )
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Malformed auditor data file %s (file too short for %u keys)\n",
|
||||
filename,
|
||||
(unsigned int) dki_len);
|
||||
GNUNET_free (af);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
url_len = size - dki_len * (sizeof (struct TALER_DenominationKeyValidityPS)
|
||||
+ sizeof (struct TALER_AuditorSignatureP));
|
||||
sigs = (const struct TALER_AuditorSignatureP *) &af[1];
|
||||
dki = (const struct TALER_DenominationKeyValidityPS *) &sigs[dki_len];
|
||||
auditor_url = (const char *) &dki[dki_len];
|
||||
if ( (0 == url_len) ||
|
||||
('\0' != auditor_url[url_len - 1]) )
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Malformed auditor data file %s (no 0-terminator)\n",
|
||||
filename);
|
||||
GNUNET_free (af);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
(iret = aic->it (aic->it_cls,
|
||||
&af->apub,
|
||||
auditor_url,
|
||||
&af->mpub,
|
||||
dki_len,
|
||||
sigs,
|
||||
dki)))
|
||||
{
|
||||
GNUNET_free (af);
|
||||
if (GNUNET_SYSERR == iret)
|
||||
aic->status = GNUNET_SYSERR;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
aic->status++;
|
||||
GNUNET_free (af);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call @a it with information for each auditor found in the @a exchange_base_dir.
|
||||
*
|
||||
* @param cfg configuration to use
|
||||
* @param it function to call with auditor information
|
||||
* @param it_cls closure for @a it
|
||||
* @return -1 on error, 0 if no files were found, otherwise
|
||||
* a positive number (however, even with a positive
|
||||
* number it is possible that @a it was never called
|
||||
* as maybe none of the files were well-formed)
|
||||
*/
|
||||
int
|
||||
TALER_EXCHANGEDB_auditor_iterate (const struct GNUNET_CONFIGURATION_Handle *cfg,
|
||||
TALER_EXCHANGEDB_AuditorIterator it,
|
||||
void *it_cls)
|
||||
{
|
||||
struct AuditorIterateContext aic;
|
||||
int ret;
|
||||
char *auditor_base_dir;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_get_value_filename (cfg,
|
||||
"exchangedb",
|
||||
"AUDITOR_BASE_DIR",
|
||||
&auditor_base_dir))
|
||||
return -1;
|
||||
aic.it = it;
|
||||
aic.it_cls = it_cls;
|
||||
aic.status = 0;
|
||||
ret = GNUNET_DISK_directory_scan (auditor_base_dir,
|
||||
&auditor_iter,
|
||||
&aic);
|
||||
GNUNET_free (auditor_base_dir);
|
||||
if ( (0 != aic.status) ||
|
||||
(GNUNET_OK == ret) )
|
||||
return aic.status;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write auditor information to the given file.
|
||||
*
|
||||
* @param filename the file where to write the auditor information to
|
||||
* @param apub the auditor's public key
|
||||
* @param auditor_url the URL of the auditor
|
||||
* @param asigs the auditor's signatures, array of length @a dki_len
|
||||
* @param mpub the exchange's public key (as expected by the auditor)
|
||||
* @param dki_len length of @a dki
|
||||
* @param dki array of denomination coin data signed by the auditor
|
||||
* @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure.
|
||||
*/
|
||||
int
|
||||
TALER_EXCHANGEDB_auditor_write (
|
||||
const char *filename,
|
||||
const struct TALER_AuditorPublicKeyP *apub,
|
||||
const char *auditor_url,
|
||||
const struct TALER_AuditorSignatureP *asigs,
|
||||
const struct TALER_MasterPublicKeyP *mpub,
|
||||
uint32_t dki_len,
|
||||
const struct TALER_DenominationKeyValidityPS *dki)
|
||||
{
|
||||
struct GNUNET_DISK_FileHandle *fh;
|
||||
ssize_t wrote;
|
||||
size_t wsize;
|
||||
int eno;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_DISK_directory_create_for_file (filename))
|
||||
{
|
||||
eno = errno;
|
||||
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
|
||||
"mkdir (for file)",
|
||||
filename);
|
||||
errno = eno;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (NULL == (fh = GNUNET_DISK_file_open
|
||||
(filename,
|
||||
GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE
|
||||
| GNUNET_DISK_OPEN_TRUNCATE,
|
||||
GNUNET_DISK_PERM_USER_READ
|
||||
| GNUNET_DISK_PERM_USER_WRITE)))
|
||||
{
|
||||
eno = errno;
|
||||
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
|
||||
"open",
|
||||
filename);
|
||||
errno = eno;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
{
|
||||
struct AuditorFileHeaderP af = {
|
||||
.apub = *apub,
|
||||
.mpub = *mpub,
|
||||
.dki_len = htonl (dki_len)
|
||||
};
|
||||
|
||||
wsize = sizeof (struct AuditorFileHeaderP);
|
||||
if ( (GNUNET_SYSERR == (wrote = GNUNET_DISK_file_write (fh,
|
||||
&af,
|
||||
wsize))) ||
|
||||
(wrote != (ssize_t) wsize) )
|
||||
goto cleanup;
|
||||
}
|
||||
wsize = dki_len * sizeof (struct TALER_AuditorSignatureP);
|
||||
if (((ssize_t) wsize) !=
|
||||
GNUNET_DISK_file_write (fh,
|
||||
asigs,
|
||||
wsize))
|
||||
goto cleanup;
|
||||
wsize = dki_len * sizeof (struct TALER_DenominationKeyValidityPS);
|
||||
if (((ssize_t) wsize) !=
|
||||
GNUNET_DISK_file_write (fh,
|
||||
dki,
|
||||
wsize))
|
||||
goto cleanup;
|
||||
wsize = strlen (auditor_url) + 1;
|
||||
if (((ssize_t) wsize) !=
|
||||
GNUNET_DISK_file_write (fh,
|
||||
auditor_url,
|
||||
wsize))
|
||||
goto cleanup;
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
GNUNET_DISK_file_close (fh));
|
||||
return GNUNET_OK;
|
||||
cleanup:
|
||||
eno = errno;
|
||||
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
|
||||
"write",
|
||||
filename);
|
||||
GNUNET_break (GNUNET_OK ==
|
||||
GNUNET_DISK_file_close (fh));
|
||||
/* try to remove the file, as it must be malformed */
|
||||
if (0 != unlink (filename))
|
||||
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
|
||||
"unlink",
|
||||
filename);
|
||||
errno = eno;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
|
||||
/* end of exchangedb_auditorkeys.c */
|
@ -1,518 +0,0 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2019 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 3, or (at your option) any later version.
|
||||
|
||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file exchangedb/exchangedb_denomkeys.c
|
||||
* @brief I/O operations for the Exchange's denomination private keys
|
||||
* @author Florian Dold
|
||||
* @author Benedikt Mueller
|
||||
* @author Sree Harsha Totakura
|
||||
* @author Christian Grothoff
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "taler_crypto_lib.h"
|
||||
#include "taler_exchangedb_lib.h"
|
||||
|
||||
|
||||
GNUNET_NETWORK_STRUCT_BEGIN
|
||||
|
||||
/**
|
||||
* Contents of a file with a revocation certificate.
|
||||
*/
|
||||
struct RevocationFileP
|
||||
{
|
||||
|
||||
/**
|
||||
* Hash of the denomination public key being revoked.
|
||||
*/
|
||||
struct GNUNET_HashCode denom_hash;
|
||||
|
||||
/**
|
||||
* Master signature over the revocation, must match purpose
|
||||
* #TALER_SIGNATURE_MASTER_DENOMINATION_KEY_REVOKED.
|
||||
*/
|
||||
struct TALER_MasterSignatureP msig;
|
||||
};
|
||||
|
||||
GNUNET_NETWORK_STRUCT_END
|
||||
|
||||
|
||||
/**
|
||||
* Mark the given denomination key as revoked and request the wallets
|
||||
* to initiate /recoup.
|
||||
*
|
||||
* @param revocation_dir where to write the revocation certificate
|
||||
* @param denom_hash hash of the denomination key to revoke
|
||||
* @param mpriv master private key to sign with
|
||||
* @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure.
|
||||
*/
|
||||
int
|
||||
TALER_EXCHANGEDB_denomination_key_revoke (
|
||||
const char *revocation_dir,
|
||||
const struct GNUNET_HashCode *denom_hash,
|
||||
const struct TALER_MasterPrivateKeyP *mpriv)
|
||||
{
|
||||
char *fn;
|
||||
int ret;
|
||||
struct RevocationFileP rd;
|
||||
|
||||
TALER_exchange_offline_denomination_revoke_sign (denom_hash,
|
||||
mpriv,
|
||||
&rd.msig);
|
||||
GNUNET_asprintf (&fn,
|
||||
"%s" DIR_SEPARATOR_STR
|
||||
"%s.rev",
|
||||
revocation_dir,
|
||||
GNUNET_h2s_full (denom_hash));
|
||||
rd.denom_hash = *denom_hash;
|
||||
ret = (sizeof (rd) !=
|
||||
GNUNET_DISK_fn_write (fn,
|
||||
&rd,
|
||||
sizeof (rd),
|
||||
GNUNET_DISK_PERM_USER_READ
|
||||
| GNUNET_DISK_PERM_USER_WRITE))
|
||||
? GNUNET_SYSERR
|
||||
: GNUNET_OK;
|
||||
GNUNET_free (fn);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Import a denomination key from the given file.
|
||||
*
|
||||
* @param filename the file to import the key from
|
||||
* @param[out] dki set to the imported denomination key
|
||||
* @return #GNUNET_OK upon success;
|
||||
* #GNUNET_SYSERR upon failure
|
||||
*/
|
||||
int
|
||||
TALER_EXCHANGEDB_denomination_key_read (
|
||||
const char *filename,
|
||||
struct TALER_EXCHANGEDB_DenominationKey *dki)
|
||||
{
|
||||
uint64_t size;
|
||||
size_t offset;
|
||||
void *data;
|
||||
struct GNUNET_CRYPTO_RsaPrivateKey *priv;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_DISK_file_size (filename,
|
||||
&size,
|
||||
GNUNET_YES,
|
||||
GNUNET_YES))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Skipping inaccessible denomination key file `%s'\n",
|
||||
filename);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
offset = sizeof (struct TALER_EXCHANGEDB_DenominationKeyInformationP);
|
||||
if (size <= offset)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"File size (%llu bytes) too small for file `%s' to contain denomination key data. Skipping it.\n",
|
||||
(unsigned long long) size,
|
||||
filename);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (size >= GNUNET_MAX_MALLOC_CHECKED)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"File size (%llu bytes) too large for file `%s' to contain denomination key data. Skipping it.\n",
|
||||
(unsigned long long) size,
|
||||
filename);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
data = GNUNET_malloc (size);
|
||||
if (((ssize_t) size) !=
|
||||
GNUNET_DISK_fn_read (filename,
|
||||
data,
|
||||
size))
|
||||
{
|
||||
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
|
||||
"read",
|
||||
filename);
|
||||
GNUNET_free (data);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (NULL ==
|
||||
(priv = GNUNET_CRYPTO_rsa_private_key_decode (data + offset,
|
||||
size - offset)))
|
||||
{
|
||||
GNUNET_free (data);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
GNUNET_assert (NULL == dki->denom_priv.rsa_private_key);
|
||||
dki->denom_priv.rsa_private_key = priv;
|
||||
dki->denom_pub.rsa_public_key
|
||||
= GNUNET_CRYPTO_rsa_private_key_get_public (priv);
|
||||
memcpy (&dki->issue,
|
||||
data,
|
||||
offset);
|
||||
GNUNET_free (data);
|
||||
if (0 == GNUNET_TIME_absolute_get_remaining
|
||||
(GNUNET_TIME_absolute_ntoh
|
||||
(dki->issue.properties.expire_withdraw)).rel_value_us)
|
||||
{
|
||||
/* key expired for withdrawal, remove private key to
|
||||
minimize chance of compromise */
|
||||
if (0 != unlink (filename))
|
||||
{
|
||||
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
|
||||
"unlink",
|
||||
filename);
|
||||
/* yes, we had an error, but the file content
|
||||
was fine and is being returned */
|
||||
return GNUNET_OK;
|
||||
}
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Exports a denomination key to the given file.
|
||||
*
|
||||
* @param filename the file where to write the denomination key
|
||||
* @param dki the denomination key
|
||||
* @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure.
|
||||
*/
|
||||
int
|
||||
TALER_EXCHANGEDB_denomination_key_write (
|
||||
const char *filename,
|
||||
const struct TALER_EXCHANGEDB_DenominationKey *dki)
|
||||
{
|
||||
struct GNUNET_DISK_FileHandle *fh;
|
||||
ssize_t wrote;
|
||||
size_t wsize;
|
||||
int eno;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_DISK_directory_create_for_file (filename))
|
||||
{
|
||||
eno = errno;
|
||||
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
|
||||
"mkdir (for file)",
|
||||
filename);
|
||||
errno = eno;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (NULL == (fh = GNUNET_DISK_file_open
|
||||
(filename,
|
||||
GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE
|
||||
| GNUNET_DISK_OPEN_TRUNCATE
|
||||
| GNUNET_DISK_OPEN_FAILIFEXISTS,
|
||||
GNUNET_DISK_PERM_USER_READ
|
||||
| GNUNET_DISK_PERM_USER_WRITE)))
|
||||
{
|
||||
eno = errno;
|
||||
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
|
||||
"open",
|
||||
filename);
|
||||
errno = eno;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
wsize = sizeof (struct TALER_EXCHANGEDB_DenominationKeyInformationP);
|
||||
if ( (GNUNET_SYSERR == (wrote = GNUNET_DISK_file_write (fh,
|
||||
&dki->issue,
|
||||
wsize))) ||
|
||||
(wrote != (ssize_t) wsize) )
|
||||
goto cleanup;
|
||||
{
|
||||
void *priv_enc;
|
||||
size_t priv_enc_size;
|
||||
|
||||
priv_enc_size
|
||||
= GNUNET_CRYPTO_rsa_private_key_encode (dki->denom_priv.rsa_private_key,
|
||||
&priv_enc);
|
||||
wrote = GNUNET_DISK_file_write (fh,
|
||||
priv_enc,
|
||||
priv_enc_size);
|
||||
GNUNET_free (priv_enc);
|
||||
if ( (GNUNET_SYSERR == wrote) ||
|
||||
(wrote != (ssize_t) priv_enc_size) )
|
||||
goto cleanup;
|
||||
}
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
GNUNET_DISK_file_close (fh));
|
||||
return GNUNET_OK;
|
||||
|
||||
cleanup:
|
||||
eno = errno;
|
||||
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
|
||||
"write",
|
||||
filename);
|
||||
GNUNET_break (GNUNET_OK ==
|
||||
GNUNET_DISK_file_close (fh));
|
||||
/* try to remove the file, as it must be malformed */
|
||||
if (0 != unlink (filename))
|
||||
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
|
||||
"unlink",
|
||||
filename);
|
||||
errno = eno;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closure for #denomkeys_iterate_keydir_iter() and
|
||||
* #denomkeys_iterate_topdir_iter().
|
||||
*/
|
||||
struct DenomkeysIterateContext
|
||||
{
|
||||
|
||||
/**
|
||||
* Set to the name of the directory below the top-level directory
|
||||
* during the call to #denomkeys_iterate_keydir_iter().
|
||||
*/
|
||||
const char *alias;
|
||||
|
||||
/**
|
||||
* Function to call on each denomination key.
|
||||
*/
|
||||
TALER_EXCHANGEDB_DenominationKeyIterator it;
|
||||
|
||||
/**
|
||||
* Closure for @e it.
|
||||
*/
|
||||
void *it_cls;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Decode the denomination key in the given file @a filename and call
|
||||
* the callback in @a cls with the information.
|
||||
*
|
||||
* @param cls the `struct DenomkeysIterateContext *`
|
||||
* @param filename name of a file that should contain
|
||||
* a denomination key
|
||||
* @return #GNUNET_OK to continue to iterate
|
||||
* #GNUNET_NO to abort iteration with success
|
||||
* #GNUNET_SYSERR to abort iteration with failure
|
||||
*/
|
||||
static int
|
||||
denomkeys_iterate_keydir_iter (void *cls,
|
||||
const char *filename)
|
||||
{
|
||||
struct DenomkeysIterateContext *dic = cls;
|
||||
struct TALER_EXCHANGEDB_DenominationKey issue;
|
||||
int ret;
|
||||
|
||||
memset (&issue, 0, sizeof (issue));
|
||||
if (GNUNET_OK !=
|
||||
TALER_EXCHANGEDB_denomination_key_read (filename,
|
||||
&issue))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Invalid denomkey file: '%s'\n",
|
||||
filename);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
ret = dic->it (dic->it_cls,
|
||||
dic->alias,
|
||||
&issue);
|
||||
GNUNET_CRYPTO_rsa_private_key_free (issue.denom_priv.rsa_private_key);
|
||||
GNUNET_CRYPTO_rsa_public_key_free (issue.denom_pub.rsa_public_key);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called on each subdirectory in the #TALER_EXCHANGEDB_DIR_DENOMINATION_KEYS. Will
|
||||
* call the #denomkeys_iterate_keydir_iter() on each file in the
|
||||
* subdirectory.
|
||||
*
|
||||
* @param cls the `struct DenomkeysIterateContext *`
|
||||
* @param filename name of the subdirectory to scan
|
||||
* @return #GNUNET_OK on success,
|
||||
* #GNUNET_SYSERR if we need to abort
|
||||
*/
|
||||
static int
|
||||
denomkeys_iterate_topdir_iter (void *cls,
|
||||
const char *filename)
|
||||
{
|
||||
struct DenomkeysIterateContext *dic = cls;
|
||||
|
||||
dic->alias = GNUNET_STRINGS_get_short_name (filename);
|
||||
if (0 > GNUNET_DISK_directory_scan (filename,
|
||||
&denomkeys_iterate_keydir_iter,
|
||||
dic))
|
||||
return GNUNET_SYSERR;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call @a it for each denomination key found in the @a exchange_base_dir.
|
||||
*
|
||||
* @param exchange_base_dir base directory for the exchange,
|
||||
* the signing keys must be in the #TALER_EXCHANGEDB_DIR_DENOMINATION_KEYS
|
||||
* subdirectory
|
||||
* @param it function to call on each denomination key found
|
||||
* @param it_cls closure for @a it
|
||||
* @return -1 on error, 0 if no files were found, otherwise
|
||||
* a positive number (however, even with a positive
|
||||
* number it is possible that @a it was never called
|
||||
* as maybe none of the files were well-formed)
|
||||
*/
|
||||
int
|
||||
TALER_EXCHANGEDB_denomination_keys_iterate (
|
||||
const char *exchange_base_dir,
|
||||
TALER_EXCHANGEDB_DenominationKeyIterator it,
|
||||
void *it_cls)
|
||||
{
|
||||
struct DenomkeysIterateContext dic = {
|
||||
.it = it,
|
||||
.it_cls = it_cls
|
||||
};
|
||||
char *dir;
|
||||
int ret;
|
||||
|
||||
GNUNET_asprintf (&dir,
|
||||
"%s" DIR_SEPARATOR_STR
|
||||
TALER_EXCHANGEDB_DIR_DENOMINATION_KEYS,
|
||||
exchange_base_dir);
|
||||
ret = GNUNET_DISK_directory_scan (dir,
|
||||
&denomkeys_iterate_topdir_iter,
|
||||
&dic);
|
||||
GNUNET_free (dir);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closure for #revocations_iterate_cb().
|
||||
*/
|
||||
struct RevocationsIterateContext
|
||||
{
|
||||
|
||||
/**
|
||||
* Function to call on each revoked denomination key.
|
||||
*/
|
||||
TALER_EXCHANGEDB_RevocationIterator it;
|
||||
|
||||
/**
|
||||
* Closure for @e it.
|
||||
*/
|
||||
void *it_cls;
|
||||
|
||||
/**
|
||||
* Master public key to use to validate revocations.
|
||||
*/
|
||||
const struct TALER_MasterPublicKeyP *master_pub;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Decode the revocation certificate in the given file @a filename and call
|
||||
* the callback in @a cls with the information.
|
||||
*
|
||||
* @param cls the `struct RevocationsIterateContext *`
|
||||
* @param filename name of a file that should contain
|
||||
* a denomination key
|
||||
* @return #GNUNET_OK to continue to iterate
|
||||
* #GNUNET_NO to abort iteration with success
|
||||
* #GNUNET_SYSERR to abort iteration with failure
|
||||
*/
|
||||
static int
|
||||
revocations_iterate_cb (void *cls,
|
||||
const char *filename)
|
||||
{
|
||||
struct RevocationsIterateContext *ric = cls;
|
||||
struct RevocationFileP rf;
|
||||
ssize_t rd;
|
||||
|
||||
/* Check if revocation is valid... */
|
||||
rd = GNUNET_DISK_fn_read (filename,
|
||||
&rf,
|
||||
sizeof (rf));
|
||||
if (GNUNET_SYSERR == rd)
|
||||
{
|
||||
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
|
||||
"read",
|
||||
filename);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
if (sizeof (rf) != (size_t) rd)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Invalid revocation file `%s' found and ignored (bad size: %llu)\n",
|
||||
filename,
|
||||
(unsigned long long) rd);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_exchange_offline_denomination_revoke_verify (
|
||||
&rf.denom_hash,
|
||||
ric->master_pub,
|
||||
&rf.msig))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Invalid revocation file `%s' found and ignored (bad signature)\n",
|
||||
filename);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Denomination key `%s' was revoked!\n",
|
||||
GNUNET_h2s (&rf.denom_hash));
|
||||
return ric->it (ric->it_cls,
|
||||
&rf.denom_hash,
|
||||
&rf.msig);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call @a it for each revoked denomination key found in the @a revocation_dir.
|
||||
*
|
||||
* @param revocation_dir base directory where revocations are stored
|
||||
* @param master_pub master public key (used to check revocations)
|
||||
* @param it function to call on each revoked denomination key found
|
||||
* @param it_cls closure for @a it
|
||||
* @return -1 on error, 0 if no files were found, otherwise
|
||||
* a positive number (however, even with a positive
|
||||
* number it is possible that @a it was never called
|
||||
* as maybe none of the files were well-formed)
|
||||
*/
|
||||
int
|
||||
TALER_EXCHANGEDB_revocations_iterate (const char *revocation_dir,
|
||||
const struct
|
||||
TALER_MasterPublicKeyP *master_pub,
|
||||
TALER_EXCHANGEDB_RevocationIterator it,
|
||||
void *it_cls)
|
||||
{
|
||||
struct RevocationsIterateContext ric = {
|
||||
.it = it,
|
||||
.it_cls = it_cls,
|
||||
.master_pub = master_pub
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_DISK_directory_create (revocation_dir))
|
||||
{
|
||||
/* directory doesn't exist and we couldn't even create it,
|
||||
clearly means there are no revocations there */
|
||||
return 0;
|
||||
}
|
||||
return GNUNET_DISK_directory_scan (revocation_dir,
|
||||
&revocations_iterate_cb,
|
||||
&ric);
|
||||
}
|
||||
|
||||
|
||||
/* end of exchangedb_denomkeys.c */
|
@ -1,412 +0,0 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2017 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 3, or (at your option) any later version.
|
||||
|
||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file exchangedb/exchangedb_fees.c
|
||||
* @brief Logic to read/write/convert aggregation wire fees (not other fees!)
|
||||
* @author Christian Grothoff
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "taler_exchangedb_lib.h"
|
||||
|
||||
|
||||
GNUNET_NETWORK_STRUCT_BEGIN
|
||||
|
||||
/**
|
||||
* Structure for wire fees on disk.
|
||||
*/
|
||||
struct TALER_WireFeeDiskP
|
||||
{
|
||||
|
||||
/**
|
||||
* Wire fee details.
|
||||
*/
|
||||
struct TALER_MasterWireFeePS wf;
|
||||
|
||||
|
||||
/**
|
||||
* Signature affirming the above fee structure.
|
||||
*/
|
||||
struct TALER_MasterSignatureP master_sig;
|
||||
|
||||
};
|
||||
|
||||
GNUNET_NETWORK_STRUCT_END
|
||||
|
||||
|
||||
/**
|
||||
* Convert @a wd disk format to host format.
|
||||
*
|
||||
* @param wd aggregate fees, disk format
|
||||
* @return fees in host format
|
||||
*/
|
||||
static struct TALER_EXCHANGEDB_AggregateFees *
|
||||
wd2af (const struct TALER_WireFeeDiskP *wd)
|
||||
{
|
||||
struct TALER_EXCHANGEDB_AggregateFees *af;
|
||||
|
||||
af = GNUNET_new (struct TALER_EXCHANGEDB_AggregateFees);
|
||||
af->start_date = GNUNET_TIME_absolute_ntoh (wd->wf.start_date);
|
||||
af->end_date = GNUNET_TIME_absolute_ntoh (wd->wf.end_date);
|
||||
TALER_amount_ntoh (&af->wire_fee,
|
||||
&wd->wf.wire_fee);
|
||||
TALER_amount_ntoh (&af->closing_fee,
|
||||
&wd->wf.closing_fee);
|
||||
af->master_sig = wd->master_sig;
|
||||
return af;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read the current fee structure from disk.
|
||||
*
|
||||
* @param cfg configuration to use
|
||||
* @param wireplugin name of the wire plugin to read fees for
|
||||
* @return sorted list of aggregation fees, NULL on error
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_AggregateFees *
|
||||
TALER_EXCHANGEDB_fees_read (const struct GNUNET_CONFIGURATION_Handle *cfg,
|
||||
const char *wireplugin)
|
||||
{
|
||||
char *wirefee_base_dir;
|
||||
char *fn;
|
||||
struct GNUNET_DISK_FileHandle *fh;
|
||||
struct TALER_WireFeeDiskP wd;
|
||||
struct TALER_EXCHANGEDB_AggregateFees *af;
|
||||
struct TALER_EXCHANGEDB_AggregateFees *endp;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_get_value_filename (cfg,
|
||||
"exchangedb",
|
||||
"WIREFEE_BASE_DIR",
|
||||
&wirefee_base_dir))
|
||||
{
|
||||
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
|
||||
"exchangedb",
|
||||
"WIREFEE_BASE_DIR");
|
||||
return NULL;
|
||||
}
|
||||
GNUNET_asprintf (&fn,
|
||||
"%s/%s.fee",
|
||||
wirefee_base_dir,
|
||||
wireplugin);
|
||||
GNUNET_free (wirefee_base_dir);
|
||||
fh = GNUNET_DISK_file_open (fn,
|
||||
GNUNET_DISK_OPEN_READ,
|
||||
GNUNET_DISK_PERM_NONE);
|
||||
if (NULL == fh)
|
||||
{
|
||||
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
|
||||
"open",
|
||||
fn);
|
||||
GNUNET_free (fn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
af = NULL;
|
||||
endp = NULL;
|
||||
while (1)
|
||||
{
|
||||
struct TALER_EXCHANGEDB_AggregateFees *n;
|
||||
ssize_t in = GNUNET_DISK_file_read (fh,
|
||||
&wd,
|
||||
sizeof (wd));
|
||||
if (-1 == in)
|
||||
{
|
||||
/* Unexpected I/O error */
|
||||
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
|
||||
"read",
|
||||
fn);
|
||||
GNUNET_break (GNUNET_OK ==
|
||||
GNUNET_DISK_file_close (fh));
|
||||
GNUNET_free (fn);
|
||||
TALER_EXCHANGEDB_fees_free (af);
|
||||
return NULL;
|
||||
}
|
||||
if (0 == in)
|
||||
break; /* EOF, terminate normally */
|
||||
if (sizeof (wd) != in)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"File `%s' has wrong size for fee structure\n",
|
||||
fn);
|
||||
GNUNET_break (GNUNET_OK ==
|
||||
GNUNET_DISK_file_close (fh));
|
||||
GNUNET_free (fn);
|
||||
TALER_EXCHANGEDB_fees_free (af);
|
||||
return NULL;
|
||||
}
|
||||
n = wd2af (&wd);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Loaded wire fees starting at %s from file\n",
|
||||
GNUNET_STRINGS_absolute_time_to_string (n->start_date));
|
||||
if ( ( (NULL == af) ||
|
||||
(endp->end_date.abs_value_us == n->start_date.abs_value_us) ) &&
|
||||
(n->start_date.abs_value_us < n->end_date.abs_value_us) )
|
||||
{
|
||||
/* append to list */
|
||||
if (NULL != endp)
|
||||
endp->next = n;
|
||||
else
|
||||
af = n;
|
||||
endp = n;
|
||||
}
|
||||
else
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"File `%s' does not have wire fees in chronological order\n",
|
||||
fn);
|
||||
GNUNET_DISK_file_close (fh);
|
||||
GNUNET_free (n);
|
||||
GNUNET_free (fn);
|
||||
TALER_EXCHANGEDB_fees_free (af);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
GNUNET_DISK_file_close (fh));
|
||||
GNUNET_free (fn);
|
||||
return af;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert @a af to @a wf.
|
||||
*
|
||||
* @param wiremethod name of the wire method the fees are for
|
||||
* @param[in,out] af aggregate fees, host format (updated to round time)
|
||||
* @param[out] wf aggregate fees, disk / signature format
|
||||
*/
|
||||
void
|
||||
TALER_EXCHANGEDB_fees_2_wf (const char *wiremethod,
|
||||
struct TALER_EXCHANGEDB_AggregateFees *af,
|
||||
struct TALER_MasterWireFeePS *wf)
|
||||
{
|
||||
(void) GNUNET_TIME_round_abs (&af->start_date);
|
||||
(void) GNUNET_TIME_round_abs (&af->end_date);
|
||||
wf->purpose.size = htonl (sizeof (*wf));
|
||||
wf->purpose.purpose = htonl (TALER_SIGNATURE_MASTER_WIRE_FEES);
|
||||
GNUNET_CRYPTO_hash (wiremethod,
|
||||
strlen (wiremethod) + 1,
|
||||
&wf->h_wire_method);
|
||||
wf->start_date = GNUNET_TIME_absolute_hton (af->start_date);
|
||||
wf->end_date = GNUNET_TIME_absolute_hton (af->end_date);
|
||||
TALER_amount_hton (&wf->wire_fee,
|
||||
&af->wire_fee);
|
||||
TALER_amount_hton (&wf->closing_fee,
|
||||
&af->closing_fee);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write given fee structure to disk.
|
||||
*
|
||||
* @param filename where to write the fees
|
||||
* @param wireplugin which plugin the fees are about
|
||||
* @param af fee structure to write
|
||||
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
|
||||
*/
|
||||
int
|
||||
TALER_EXCHANGEDB_fees_write (const char *filename,
|
||||
const char *wireplugin,
|
||||
struct TALER_EXCHANGEDB_AggregateFees *af)
|
||||
{
|
||||
struct GNUNET_DISK_FileHandle *fh;
|
||||
struct TALER_WireFeeDiskP wd;
|
||||
struct TALER_EXCHANGEDB_AggregateFees *last;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_DISK_directory_create_for_file (filename))
|
||||
{
|
||||
int eno;
|
||||
|
||||
eno = errno;
|
||||
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
|
||||
"mkdir (for file)",
|
||||
filename);
|
||||
errno = eno;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
fh = GNUNET_DISK_file_open (filename,
|
||||
GNUNET_DISK_OPEN_WRITE
|
||||
| GNUNET_DISK_OPEN_TRUNCATE
|
||||
| GNUNET_DISK_OPEN_CREATE,
|
||||
GNUNET_DISK_PERM_USER_READ
|
||||
| GNUNET_DISK_PERM_USER_WRITE);
|
||||
if (NULL == fh)
|
||||
{
|
||||
int eno;
|
||||
|
||||
eno = errno;
|
||||
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
|
||||
"open",
|
||||
filename);
|
||||
errno = eno;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
last = NULL;
|
||||
while (NULL != af)
|
||||
{
|
||||
if ( ( (NULL != last) &&
|
||||
(last->end_date.abs_value_us != af->start_date.abs_value_us) ) ||
|
||||
(af->start_date.abs_value_us >= af->end_date.abs_value_us) )
|
||||
{
|
||||
/* @a af malformed, refusing to write file that will be rejected */
|
||||
GNUNET_break (0);
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
GNUNET_DISK_file_close (fh));
|
||||
/* try to remove the file, as it would be malformed */
|
||||
if (0 != unlink (filename))
|
||||
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
|
||||
"unlink",
|
||||
filename);
|
||||
errno = EINVAL; /* invalid inputs */
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
TALER_EXCHANGEDB_fees_2_wf (wireplugin,
|
||||
af,
|
||||
&wd.wf);
|
||||
wd.master_sig = af->master_sig;
|
||||
last = af;
|
||||
af = af->next;
|
||||
if (sizeof (wd) !=
|
||||
GNUNET_DISK_file_write (fh,
|
||||
&wd,
|
||||
sizeof (wd)))
|
||||
{
|
||||
int eno = errno;
|
||||
|
||||
GNUNET_break (GNUNET_OK ==
|
||||
GNUNET_DISK_file_close (fh));
|
||||
/* try to remove the file, as it must be malformed */
|
||||
if (0 != unlink (filename))
|
||||
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
|
||||
"unlink",
|
||||
filename);
|
||||
errno = eno;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
}
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
GNUNET_DISK_file_close (fh));
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Free @a af data structure
|
||||
*
|
||||
* @param af list to free
|
||||
*/
|
||||
void
|
||||
TALER_EXCHANGEDB_fees_free (struct TALER_EXCHANGEDB_AggregateFees *af)
|
||||
{
|
||||
while (NULL != af)
|
||||
{
|
||||
struct TALER_EXCHANGEDB_AggregateFees *next;
|
||||
|
||||
next = af->next;
|
||||
GNUNET_free (af);
|
||||
af = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find the record valid at time @a now in the fee structure.
|
||||
*
|
||||
* @param wa wire transfer fee data structure to update
|
||||
* @param now timestamp to update fees to
|
||||
* @return fee valid at @a now, or NULL if unknown
|
||||
*/
|
||||
static struct TALER_EXCHANGEDB_AggregateFees *
|
||||
advance_fees (struct TALER_EXCHANGEDB_WireAccount *wa,
|
||||
struct GNUNET_TIME_Absolute now)
|
||||
{
|
||||
struct TALER_EXCHANGEDB_AggregateFees *af;
|
||||
|
||||
af = wa->af;
|
||||
while ( (NULL != af) &&
|
||||
(af->end_date.abs_value_us < now.abs_value_us) )
|
||||
af = af->next;
|
||||
return af;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update wire transfer fee data structure in @a wa.
|
||||
*
|
||||
* @param cfg configuration to use
|
||||
* @param db_plugin database plugin to use
|
||||
* @param wa wire account data structure to update
|
||||
* @param now timestamp to update fees to
|
||||
* @param session DB session to use
|
||||
* @return fee valid at @a now, or NULL if unknown
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_AggregateFees *
|
||||
TALER_EXCHANGEDB_update_fees (const struct GNUNET_CONFIGURATION_Handle *cfg,
|
||||
struct TALER_EXCHANGEDB_Plugin *db_plugin,
|
||||
struct TALER_EXCHANGEDB_WireAccount *wa,
|
||||
struct GNUNET_TIME_Absolute now,
|
||||
struct TALER_EXCHANGEDB_Session *session)
|
||||
{
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
struct TALER_EXCHANGEDB_AggregateFees *af;
|
||||
|
||||
af = advance_fees (wa,
|
||||
now);
|
||||
if (NULL != af)
|
||||
return af;
|
||||
/* Let's try to load it from disk... */
|
||||
wa->af = TALER_EXCHANGEDB_fees_read (cfg,
|
||||
wa->method);
|
||||
for (struct TALER_EXCHANGEDB_AggregateFees *p = wa->af;
|
||||
NULL != p;
|
||||
p = p->next)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Persisting fees starting at %s in database\n",
|
||||
GNUNET_STRINGS_absolute_time_to_string (p->start_date));
|
||||
qs = db_plugin->insert_wire_fee (db_plugin->cls,
|
||||
session,
|
||||
wa->method,
|
||||
p->start_date,
|
||||
p->end_date,
|
||||
&p->wire_fee,
|
||||
&p->closing_fee,
|
||||
&p->master_sig);
|
||||
if (qs < 0)
|
||||
{
|
||||
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
|
||||
TALER_EXCHANGEDB_fees_free (wa->af);
|
||||
wa->af = NULL;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
af = advance_fees (wa,
|
||||
now);
|
||||
if (NULL != af)
|
||||
return af;
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to find current wire transfer fees for `%s' at %s\n",
|
||||
wa->method,
|
||||
GNUNET_STRINGS_absolute_time_to_string (now));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* end of exchangedb_fees.c */
|
@ -1,187 +0,0 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014, 2015, 2016, 2020 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 3, or (at your option) any later version.
|
||||
|
||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file exchangedb/exchangedb_signkeys.c
|
||||
* @brief I/O operations for the Exchange's private online signing keys
|
||||
* @author Florian Dold
|
||||
* @author Benedikt Mueller
|
||||
* @author Sree Harsha Totakura
|
||||
* @author Christian Grothoff
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "taler_exchangedb_lib.h"
|
||||
|
||||
|
||||
/**
|
||||
* Closure for the #signkeys_iterate_dir_iter().
|
||||
*/
|
||||
struct SignkeysIterateContext
|
||||
{
|
||||
|
||||
/**
|
||||
* Function to call on each signing key.
|
||||
*/
|
||||
TALER_EXCHANGEDB_SigningKeyIterator it;
|
||||
|
||||
/**
|
||||
* Closure for @e it.
|
||||
*/
|
||||
void *it_cls;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Function called on each file in the directory with our signing
|
||||
* keys. Parses the file and calls the iterator from @a cls.
|
||||
*
|
||||
* @param cls the `struct SignkeysIterateContext *`
|
||||
* @param filename name of the file to parse
|
||||
* @return #GNUNET_OK to continue,
|
||||
* #GNUNET_NO to stop iteration without error,
|
||||
* #GNUNET_SYSERR to stop iteration with error
|
||||
*/
|
||||
static int
|
||||
signkeys_iterate_dir_iter (void *cls,
|
||||
const char *filename)
|
||||
{
|
||||
struct SignkeysIterateContext *skc = cls;
|
||||
ssize_t nread;
|
||||
struct TALER_EXCHANGEDB_PrivateSigningKeyInformationP issue;
|
||||
|
||||
nread = GNUNET_DISK_fn_read (filename,
|
||||
&issue,
|
||||
sizeof (struct
|
||||
TALER_EXCHANGEDB_PrivateSigningKeyInformationP));
|
||||
if (nread != sizeof (struct TALER_EXCHANGEDB_PrivateSigningKeyInformationP))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Invalid signkey file `%s': wrong size (%d, expected %u)\n",
|
||||
filename,
|
||||
(int) nread,
|
||||
(unsigned int) sizeof (struct
|
||||
TALER_EXCHANGEDB_PrivateSigningKeyInformationP));
|
||||
return GNUNET_OK;
|
||||
}
|
||||
if (0 == GNUNET_TIME_absolute_get_remaining
|
||||
(GNUNET_TIME_absolute_ntoh (issue.issue.expire)).rel_value_us)
|
||||
{
|
||||
if (0 != unlink (filename))
|
||||
{
|
||||
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
|
||||
"unlink",
|
||||
filename);
|
||||
return GNUNET_OK; /* yes, we had an error, but continue to iterate anyway */
|
||||
}
|
||||
/* Expired file deleted, continue to iterate -without- calling iterator
|
||||
as this key is expired */
|
||||
return GNUNET_OK;
|
||||
}
|
||||
return skc->it (skc->it_cls,
|
||||
filename,
|
||||
&issue);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call @a it for each signing key found in the @a exchange_base_dir.
|
||||
*
|
||||
* @param exchange_base_dir base directory for the exchange,
|
||||
* the signing keys must be in the #TALER_EXCHANGEDB_DIR_SIGNING_KEYS
|
||||
* subdirectory
|
||||
* @param it function to call on each signing key
|
||||
* @param it_cls closure for @a it
|
||||
* @return number of files found (may not match
|
||||
* number of keys given to @a it as malformed
|
||||
* files are simply skipped), -1 on error
|
||||
*/
|
||||
int
|
||||
TALER_EXCHANGEDB_signing_keys_iterate (const char *exchange_base_dir,
|
||||
TALER_EXCHANGEDB_SigningKeyIterator it,
|
||||
void *it_cls)
|
||||
{
|
||||
struct SignkeysIterateContext skc = {
|
||||
.it = it,
|
||||
.it_cls = it_cls
|
||||
};
|
||||
char *signkey_dir;
|
||||
int ret;
|
||||
|
||||
GNUNET_asprintf (&signkey_dir,
|
||||
"%s" DIR_SEPARATOR_STR TALER_EXCHANGEDB_DIR_SIGNING_KEYS,
|
||||
exchange_base_dir);
|
||||
ret = GNUNET_DISK_directory_scan (signkey_dir,
|
||||
&signkeys_iterate_dir_iter,
|
||||
&skc);
|
||||
GNUNET_free (signkey_dir);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Exports a signing key to the given file.
|
||||
*
|
||||
* @param exchange_base_dir base directory for the keys
|
||||
* @param start start time of the validity for the key
|
||||
* @param ski the signing key
|
||||
* @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure.
|
||||
*/
|
||||
int
|
||||
TALER_EXCHANGEDB_signing_key_write (
|
||||
const char *exchange_base_dir,
|
||||
struct GNUNET_TIME_Absolute start,
|
||||
const struct TALER_EXCHANGEDB_PrivateSigningKeyInformationP *ski)
|
||||
{
|
||||
char *skf;
|
||||
ssize_t nwrite;
|
||||
|
||||
GNUNET_asprintf (&skf,
|
||||
"%s" DIR_SEPARATOR_STR TALER_EXCHANGEDB_DIR_SIGNING_KEYS
|
||||
DIR_SEPARATOR_STR "%llu",
|
||||
exchange_base_dir,
|
||||
(unsigned long long) start.abs_value_us);
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_DISK_directory_create_for_file (skf))
|
||||
{
|
||||
int eno;
|
||||
|
||||
eno = errno;
|
||||
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
|
||||
"mkdir (for file)",
|
||||
skf);
|
||||
errno = eno;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
nwrite = GNUNET_DISK_fn_write (skf,
|
||||
ski,
|
||||
sizeof (struct
|
||||
TALER_EXCHANGEDB_PrivateSigningKeyInformationP),
|
||||
GNUNET_DISK_PERM_USER_WRITE
|
||||
| GNUNET_DISK_PERM_USER_READ);
|
||||
if (sizeof (struct TALER_EXCHANGEDB_PrivateSigningKeyInformationP) !=
|
||||
(size_t) nwrite)
|
||||
{
|
||||
GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
|
||||
"write",
|
||||
skf);
|
||||
GNUNET_free (skf);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
GNUNET_free (skf);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/* end of exchangedb_signkeys.c */
|
@ -1,169 +0,0 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2016 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 3, or (at your option) any later version.
|
||||
|
||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file exchangedb/test_exchangedb_auditors.c
|
||||
* @brief test cases for some functions in exchangedb/exchangedb_auditorkeys.c
|
||||
* @author Christian Grothoff
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "gnunet/gnunet_util_lib.h"
|
||||
#include "taler_signatures.h"
|
||||
#include "taler_exchangedb_lib.h"
|
||||
|
||||
|
||||
#define RSA_KEY_SIZE 1024
|
||||
|
||||
|
||||
#define EXITIF(cond) \
|
||||
do { \
|
||||
if (cond) { GNUNET_break (0); goto EXITIF_exit; } \
|
||||
} while (0)
|
||||
|
||||
|
||||
static struct TALER_AuditorPublicKeyP want_apub;
|
||||
|
||||
static struct TALER_AuditorSignatureP want_asigs;
|
||||
|
||||
static struct TALER_MasterPublicKeyP want_mpub;
|
||||
|
||||
static struct TALER_DenominationKeyValidityPS want_dki;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Function called with auditor information.
|
||||
*
|
||||
* @param cls NULL
|
||||
* @param apub the auditor's public key
|
||||
* @param auditor_url URL of the auditor
|
||||
* @param mpub the exchange's public key (as expected by the auditor)
|
||||
* @param dki_len length of @a asig and @a dki arrays
|
||||
* @param asigs array of the auditor's signatures over the @a dks, of length @a dki_len
|
||||
* @param dki array of denomination coin data signed by the auditor, of length @a dki_len
|
||||
* @return #GNUNET_OK to continue to iterate,
|
||||
* #GNUNET_NO to stop iteration with no error,
|
||||
* #GNUNET_SYSERR to abort iteration with error!
|
||||
*/
|
||||
static int
|
||||
auditor_cb (void *cls,
|
||||
const struct TALER_AuditorPublicKeyP *apub,
|
||||
const char *auditor_url,
|
||||
const struct TALER_MasterPublicKeyP *mpub,
|
||||
unsigned int dki_len,
|
||||
const struct TALER_AuditorSignatureP *asigs,
|
||||
const struct TALER_DenominationKeyValidityPS *dki)
|
||||
{
|
||||
GNUNET_assert (NULL == cls);
|
||||
if (0 != strcmp (auditor_url,
|
||||
"http://auditor/"))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (1 != dki_len)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (0 != GNUNET_memcmp (&want_apub,
|
||||
apub))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (0 != GNUNET_memcmp (&want_mpub,
|
||||
mpub))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (0 != GNUNET_memcmp (&want_asigs,
|
||||
asigs))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (0 != GNUNET_memcmp (&want_dki,
|
||||
dki))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
const char *const argv[])
|
||||
{
|
||||
char *tmpfile = NULL;
|
||||
char *tmpdir;
|
||||
struct GNUNET_CONFIGURATION_Handle *cfg = NULL;
|
||||
int ret;
|
||||
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
ret = 1;
|
||||
GNUNET_log_setup ("test-exchangedb-auditors",
|
||||
"WARNING",
|
||||
NULL);
|
||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
|
||||
&want_apub,
|
||||
sizeof (want_apub));
|
||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
|
||||
&want_asigs,
|
||||
sizeof (want_asigs));
|
||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
|
||||
&want_mpub,
|
||||
sizeof (want_mpub));
|
||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
|
||||
&want_dki,
|
||||
sizeof (struct TALER_DenominationKeyValidityPS));
|
||||
EXITIF (NULL == (tmpdir = GNUNET_DISK_mkdtemp ("test_exchangedb_auditors")));
|
||||
GNUNET_asprintf (&tmpfile,
|
||||
"%s/%s",
|
||||
tmpdir,
|
||||
"testauditor");
|
||||
EXITIF (GNUNET_OK !=
|
||||
TALER_EXCHANGEDB_auditor_write (tmpfile,
|
||||
&want_apub,
|
||||
"http://auditor/",
|
||||
&want_asigs,
|
||||
&want_mpub,
|
||||
1,
|
||||
&want_dki));
|
||||
cfg = GNUNET_CONFIGURATION_create ();
|
||||
|
||||
GNUNET_CONFIGURATION_set_value_string (cfg,
|
||||
"exchangedb",
|
||||
"AUDITOR_BASE_DIR",
|
||||
tmpdir);
|
||||
EXITIF (1 !=
|
||||
TALER_EXCHANGEDB_auditor_iterate (cfg,
|
||||
&auditor_cb,
|
||||
NULL));
|
||||
ret = 0;
|
||||
EXITIF_exit:
|
||||
if (NULL != tmpdir)
|
||||
{
|
||||
(void) GNUNET_DISK_directory_remove (tmpdir);
|
||||
GNUNET_free (tmpdir);
|
||||
}
|
||||
if (NULL != cfg)
|
||||
GNUNET_CONFIGURATION_destroy (cfg);
|
||||
GNUNET_free (tmpfile);
|
||||
return ret;
|
||||
}
|
@ -1,213 +0,0 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2017 Taler Systems SA (and other contributing authors)
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 3, or (at your option) any later version.
|
||||
|
||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file exchangedb/test_exchangedb_denomkeys.c
|
||||
* @brief test cases for some functions in exchangedb/exchangedb_denomkeys.c
|
||||
* @author Sree Harsha Totakura <sreeharsha@totakura.in>
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "gnunet/gnunet_util_lib.h"
|
||||
#include "taler_signatures.h"
|
||||
#include "taler_exchangedb_lib.h"
|
||||
|
||||
#define RSA_KEY_SIZE 1024
|
||||
|
||||
|
||||
#define EXITIF(cond) \
|
||||
do { \
|
||||
if (cond) { GNUNET_break (0); goto EXITIF_exit; } \
|
||||
} while (0)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Iterator called on denomination key.
|
||||
*
|
||||
* @param cls closure with expected DKI
|
||||
* @param dki the denomination key
|
||||
* @param alias coin alias
|
||||
* @return #GNUNET_OK to continue to iterate,
|
||||
* #GNUNET_NO to stop iteration with no error,
|
||||
* #GNUNET_SYSERR to abort iteration with error!
|
||||
*/
|
||||
static int
|
||||
dki_iter (void *cls,
|
||||
const char *alias,
|
||||
const struct TALER_EXCHANGEDB_DenominationKey *dki)
|
||||
{
|
||||
const struct TALER_EXCHANGEDB_DenominationKey *exp = cls;
|
||||
|
||||
(void) alias;
|
||||
if (0 != GNUNET_memcmp (&exp->issue,
|
||||
&dki->issue))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (0 !=
|
||||
GNUNET_CRYPTO_rsa_private_key_cmp (exp->denom_priv.rsa_private_key,
|
||||
dki->denom_priv.rsa_private_key))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (0 !=
|
||||
GNUNET_CRYPTO_rsa_public_key_cmp (exp->denom_pub.rsa_public_key,
|
||||
dki->denom_pub.rsa_public_key))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Iterator called on revoked denomination key.
|
||||
*
|
||||
* @param cls closure with expected DKI
|
||||
* @param denom_hash hash of the revoked denomination key
|
||||
* @param revocation_master_sig non-NULL if @a dki was revoked
|
||||
* @return #GNUNET_OK to continue to iterate,
|
||||
* #GNUNET_NO to stop iteration with no error,
|
||||
* #GNUNET_SYSERR to abort iteration with error!
|
||||
*/
|
||||
static int
|
||||
dki_iter_revoked (void *cls,
|
||||
const struct GNUNET_HashCode *denom_hash,
|
||||
const struct TALER_MasterSignatureP *revocation_master_sig)
|
||||
{
|
||||
const struct TALER_EXCHANGEDB_DenominationKey *exp = cls;
|
||||
|
||||
if (NULL == revocation_master_sig)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (0 != GNUNET_memcmp (denom_hash,
|
||||
&exp->issue.properties.denom_hash))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
const char *const argv[])
|
||||
{
|
||||
struct TALER_EXCHANGEDB_DenominationKey dki;
|
||||
void *enc;
|
||||
size_t enc_size;
|
||||
struct TALER_EXCHANGEDB_DenominationKey dki_read;
|
||||
struct TALER_MasterPrivateKeyP master_priv;
|
||||
struct TALER_MasterPublicKeyP master_pub;
|
||||
void *enc_read;
|
||||
size_t enc_read_size;
|
||||
char *tmpfile;
|
||||
char *tmpdir;
|
||||
char *revdir;
|
||||
int ret;
|
||||
struct GNUNET_TIME_Absolute start;
|
||||
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
ret = 1;
|
||||
GNUNET_log_setup ("test-exchangedb-denomkeys",
|
||||
"WARNING",
|
||||
NULL);
|
||||
enc = NULL;
|
||||
enc_read = NULL;
|
||||
tmpfile = NULL;
|
||||
dki.denom_priv.rsa_private_key = NULL;
|
||||
dki_read.denom_priv.rsa_private_key = NULL;
|
||||
GNUNET_CRYPTO_eddsa_key_create (&master_priv.eddsa_priv);
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&master_priv.eddsa_priv,
|
||||
&master_pub.eddsa_pub);
|
||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
|
||||
&dki.issue,
|
||||
sizeof (struct
|
||||
TALER_EXCHANGEDB_DenominationKeyInformationP));
|
||||
dki.denom_priv.rsa_private_key
|
||||
= GNUNET_CRYPTO_rsa_private_key_create (RSA_KEY_SIZE);
|
||||
dki.denom_pub.rsa_public_key
|
||||
= GNUNET_CRYPTO_rsa_private_key_get_public (dki.denom_priv.rsa_private_key);
|
||||
enc_size = GNUNET_CRYPTO_rsa_private_key_encode (
|
||||
dki.denom_priv.rsa_private_key,
|
||||
&enc);
|
||||
EXITIF (NULL == (tmpdir = GNUNET_DISK_mkdtemp ("test_exchangedb_dki")));
|
||||
start = GNUNET_TIME_absolute_ntoh (dki.issue.properties.start);
|
||||
GNUNET_asprintf (&tmpfile,
|
||||
"%s/%s/%s/%llu",
|
||||
tmpdir,
|
||||
TALER_EXCHANGEDB_DIR_DENOMINATION_KEYS,
|
||||
"cur-unit-uuid",
|
||||
(unsigned long long) start.abs_value_us);
|
||||
GNUNET_asprintf (&revdir,
|
||||
"%s/revocations/",
|
||||
tmpdir);
|
||||
EXITIF (GNUNET_OK !=
|
||||
TALER_EXCHANGEDB_denomination_key_write (tmpfile,
|
||||
&dki));
|
||||
EXITIF (GNUNET_OK !=
|
||||
TALER_EXCHANGEDB_denomination_key_read (tmpfile,
|
||||
&dki_read));
|
||||
EXITIF (1 !=
|
||||
TALER_EXCHANGEDB_denomination_keys_iterate (tmpdir,
|
||||
&dki_iter,
|
||||
&dki));
|
||||
|
||||
EXITIF (GNUNET_OK !=
|
||||
TALER_EXCHANGEDB_denomination_key_revoke (revdir,
|
||||
&dki.issue.properties.
|
||||
denom_hash,
|
||||
&master_priv));
|
||||
EXITIF (1 !=
|
||||
TALER_EXCHANGEDB_revocations_iterate (revdir,
|
||||
&master_pub,
|
||||
&dki_iter_revoked,
|
||||
&dki));
|
||||
GNUNET_free (revdir);
|
||||
|
||||
enc_read_size = GNUNET_CRYPTO_rsa_private_key_encode (
|
||||
dki_read.denom_priv.rsa_private_key,
|
||||
&enc_read);
|
||||
EXITIF (enc_size != enc_read_size);
|
||||
EXITIF (0 != memcmp (enc,
|
||||
enc_read,
|
||||
enc_size));
|
||||
ret = 0;
|
||||
|
||||
EXITIF_exit:
|
||||
GNUNET_free (enc);
|
||||
GNUNET_free (tmpfile);
|
||||
if (NULL != tmpdir)
|
||||
{
|
||||
(void) GNUNET_DISK_directory_remove (tmpdir);
|
||||
GNUNET_free (tmpdir);
|
||||
}
|
||||
GNUNET_free (enc_read);
|
||||
if (NULL != dki.denom_priv.rsa_private_key)
|
||||
GNUNET_CRYPTO_rsa_private_key_free (dki.denom_priv.rsa_private_key);
|
||||
if (NULL != dki.denom_pub.rsa_public_key)
|
||||
GNUNET_CRYPTO_rsa_public_key_free (dki.denom_pub.rsa_public_key);
|
||||
if (NULL != dki_read.denom_priv.rsa_private_key)
|
||||
GNUNET_CRYPTO_rsa_private_key_free (dki_read.denom_priv.rsa_private_key);
|
||||
if (NULL != dki_read.denom_pub.rsa_public_key)
|
||||
GNUNET_CRYPTO_rsa_public_key_free (dki_read.denom_pub.rsa_public_key);
|
||||
return ret;
|
||||
}
|
@ -1,153 +0,0 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2017 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 3, or (at your option) any later version.
|
||||
|
||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file exchangedb/test_exchangedb_fees.c
|
||||
* @brief test cases for functions in exchangedb/exchangedb_fees.c
|
||||
* @author Christian Grothoff
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "gnunet/gnunet_util_lib.h"
|
||||
#include "taler_signatures.h"
|
||||
#include "taler_exchangedb_lib.h"
|
||||
|
||||
|
||||
/**
|
||||
* Sign @a af with @a priv
|
||||
*
|
||||
* @param[in|out] af fee structure to sign
|
||||
* @param priv private key to use for signing
|
||||
*/
|
||||
static void
|
||||
sign_af (struct TALER_EXCHANGEDB_AggregateFees *af,
|
||||
const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
|
||||
{
|
||||
struct TALER_MasterWireFeePS wf;
|
||||
|
||||
TALER_EXCHANGEDB_fees_2_wf ("test",
|
||||
af,
|
||||
&wf);
|
||||
GNUNET_CRYPTO_eddsa_sign (priv,
|
||||
&wf,
|
||||
&af->master_sig.eddsa_signature);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
const char *const argv[])
|
||||
{
|
||||
struct GNUNET_CONFIGURATION_Handle *cfg;
|
||||
struct TALER_EXCHANGEDB_AggregateFees *af;
|
||||
struct TALER_EXCHANGEDB_AggregateFees *n;
|
||||
struct TALER_MasterPublicKeyP master_pub;
|
||||
struct GNUNET_CRYPTO_EddsaPrivateKey priv;
|
||||
char *tmpdir;
|
||||
char *tmpfile = NULL;
|
||||
int ret;
|
||||
unsigned int year;
|
||||
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
GNUNET_log_setup ("test-exchangedb-fees",
|
||||
"WARNING",
|
||||
NULL);
|
||||
tmpdir = GNUNET_DISK_mkdtemp ("test_exchangedb_fees");
|
||||
if (NULL == tmpdir)
|
||||
return 77; /* skip test */
|
||||
GNUNET_CRYPTO_eddsa_key_create (&priv);
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&priv,
|
||||
&master_pub.eddsa_pub);
|
||||
cfg = GNUNET_CONFIGURATION_create ();
|
||||
GNUNET_CONFIGURATION_set_value_string (cfg,
|
||||
"exchangedb",
|
||||
"WIREFEE_BASE_DIR",
|
||||
tmpdir);
|
||||
GNUNET_asprintf (&tmpfile,
|
||||
"%s/%s.fee",
|
||||
tmpdir,
|
||||
"test");
|
||||
ret = 0;
|
||||
af = GNUNET_new (struct TALER_EXCHANGEDB_AggregateFees);
|
||||
year = GNUNET_TIME_get_current_year ();
|
||||
af->start_date = GNUNET_TIME_year_to_time (year);
|
||||
af->end_date = GNUNET_TIME_year_to_time (year + 1);
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount ("EUR:1.0",
|
||||
&af->wire_fee));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount ("EUR:1.0",
|
||||
&af->closing_fee));
|
||||
sign_af (af,
|
||||
&priv);
|
||||
n = GNUNET_new (struct TALER_EXCHANGEDB_AggregateFees);
|
||||
n->start_date = GNUNET_TIME_year_to_time (year + 1);
|
||||
n->end_date = GNUNET_TIME_year_to_time (year + 2);
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount ("EUR:0.1",
|
||||
&n->wire_fee));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount ("EUR:0.1",
|
||||
&n->closing_fee));
|
||||
sign_af (n,
|
||||
&priv);
|
||||
af->next = n;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_EXCHANGEDB_fees_write (tmpfile,
|
||||
"test",
|
||||
af))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
ret = 1;
|
||||
}
|
||||
TALER_EXCHANGEDB_fees_free (af);
|
||||
GNUNET_free (tmpfile);
|
||||
af = TALER_EXCHANGEDB_fees_read (cfg,
|
||||
"test");
|
||||
if (NULL == af)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
ret = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (struct TALER_EXCHANGEDB_AggregateFees *p = af;
|
||||
NULL != p;
|
||||
p = p->next)
|
||||
{
|
||||
struct TALER_MasterWireFeePS wf;
|
||||
|
||||
TALER_EXCHANGEDB_fees_2_wf ("test",
|
||||
p,
|
||||
&wf);
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_WIRE_FEES,
|
||||
&wf,
|
||||
&p->master_sig.eddsa_signature,
|
||||
&master_pub.eddsa_pub))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
TALER_EXCHANGEDB_fees_free (af);
|
||||
}
|
||||
|
||||
(void) GNUNET_DISK_directory_remove (tmpdir);
|
||||
GNUNET_free (tmpdir);
|
||||
GNUNET_CONFIGURATION_destroy (cfg);
|
||||
return ret;
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2016 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 3, or (at your option) any later version.
|
||||
|
||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file exchangedb/test_exchangedb_signkeys.c
|
||||
* @brief test cases for some functions in exchangedb/exchangedb_signkeys.c
|
||||
* @author Christian Grothoff
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "gnunet/gnunet_util_lib.h"
|
||||
#include "taler_signatures.h"
|
||||
#include "taler_exchangedb_lib.h"
|
||||
|
||||
|
||||
#define EXITIF(cond) \
|
||||
do { \
|
||||
if (cond) { GNUNET_break (0); goto EXITIF_exit; } \
|
||||
} while (0)
|
||||
|
||||
|
||||
/**
|
||||
* @brief Iterator over signing keys.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param filename name of the file the key came from
|
||||
* @param ski the sign key
|
||||
* @return #GNUNET_OK to continue to iterate,
|
||||
* #GNUNET_NO to stop iteration with no error,
|
||||
* #GNUNET_SYSERR to abort iteration with error!
|
||||
*/
|
||||
static int
|
||||
ski_iter (void *cls,
|
||||
const char *filename,
|
||||
const struct TALER_EXCHANGEDB_PrivateSigningKeyInformationP *ski)
|
||||
{
|
||||
const struct TALER_EXCHANGEDB_PrivateSigningKeyInformationP *exp = cls;
|
||||
|
||||
(void) filename;
|
||||
if (0 != GNUNET_memcmp (ski,
|
||||
exp))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
const char *const argv[])
|
||||
{
|
||||
struct TALER_EXCHANGEDB_PrivateSigningKeyInformationP ski;
|
||||
struct GNUNET_TIME_Absolute now;
|
||||
char *tmpfile;
|
||||
int ret;
|
||||
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
ret = 1;
|
||||
tmpfile = NULL;
|
||||
GNUNET_log_setup ("test-exchangedb-signkeys",
|
||||
"WARNING",
|
||||
NULL);
|
||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
|
||||
&ski,
|
||||
sizeof (struct
|
||||
TALER_EXCHANGEDB_PrivateSigningKeyInformationP));
|
||||
now = GNUNET_TIME_absolute_get ();
|
||||
EXITIF (NULL == (tmpfile = GNUNET_DISK_mkdtemp ("test_exchangedb_ski")));
|
||||
EXITIF (GNUNET_OK !=
|
||||
TALER_EXCHANGEDB_signing_key_write (tmpfile,
|
||||
now,
|
||||
&ski));
|
||||
EXITIF (1 !=
|
||||
TALER_EXCHANGEDB_signing_keys_iterate (tmpfile,
|
||||
&ski_iter,
|
||||
&ski));
|
||||
ret = 0;
|
||||
EXITIF_exit:
|
||||
if (NULL != tmpfile)
|
||||
{
|
||||
(void) GNUNET_DISK_directory_remove (tmpfile);
|
||||
GNUNET_free (tmpfile);
|
||||
}
|
||||
return ret;
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2017 Taler Systems SA
|
||||
Copyright (C) 2014-2020 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
@ -27,250 +27,6 @@
|
||||
#include "taler_exchangedb_plugin.h"
|
||||
#include "taler_bank_service.h"
|
||||
|
||||
/**
|
||||
* Subdirectroy under the exchange's base directory which contains
|
||||
* the exchange's signing keys.
|
||||
*/
|
||||
#define TALER_EXCHANGEDB_DIR_SIGNING_KEYS "signkeys"
|
||||
|
||||
/**
|
||||
* Subdirectory under the exchange's base directory which contains
|
||||
* the exchange's denomination keys.
|
||||
*/
|
||||
#define TALER_EXCHANGEDB_DIR_DENOMINATION_KEYS "denomkeys"
|
||||
|
||||
|
||||
/**
|
||||
* @brief Iterator over signing keys.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param filename name of the file the key came from
|
||||
* @param ski the sign key
|
||||
* @return #GNUNET_OK to continue to iterate,
|
||||
* #GNUNET_NO to stop iteration with no error,
|
||||
* #GNUNET_SYSERR to abort iteration with error!
|
||||
*/
|
||||
typedef int
|
||||
(*TALER_EXCHANGEDB_SigningKeyIterator)(
|
||||
void *cls,
|
||||
const char *filename,
|
||||
const struct TALER_EXCHANGEDB_PrivateSigningKeyInformationP *ski);
|
||||
|
||||
|
||||
/**
|
||||
* Call @a it for each signing key found in the @a exchange_base_dir.
|
||||
*
|
||||
* @param exchange_base_dir base directory for the exchange,
|
||||
* the signing keys must be in the #TALER_EXCHANGEDB_DIR_SIGNING_KEYS
|
||||
* subdirectory
|
||||
* @param it function to call on each signing key
|
||||
* @param it_cls closure for @a it
|
||||
* @return number of files found (may not match
|
||||
* number of keys given to @a it as malformed
|
||||
* files are simply skipped), -1 on error
|
||||
*/
|
||||
int
|
||||
TALER_EXCHANGEDB_signing_keys_iterate (const char *exchange_base_dir,
|
||||
TALER_EXCHANGEDB_SigningKeyIterator it,
|
||||
void *it_cls);
|
||||
|
||||
|
||||
/**
|
||||
* Exports a signing key to the given file.
|
||||
*
|
||||
* @param exchange_base_dir base directory for the keys
|
||||
* @param start start time of the validity for the key
|
||||
* @param ski the signing key
|
||||
* @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure.
|
||||
*/
|
||||
int
|
||||
TALER_EXCHANGEDB_signing_key_write (
|
||||
const char *exchange_base_dir,
|
||||
struct GNUNET_TIME_Absolute start,
|
||||
const struct TALER_EXCHANGEDB_PrivateSigningKeyInformationP *ski);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Iterator over denomination keys.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param alias coin alias
|
||||
* @param dki the denomination key
|
||||
* @return #GNUNET_OK to continue to iterate,
|
||||
* #GNUNET_NO to stop iteration with no error,
|
||||
* #GNUNET_SYSERR to abort iteration with error!
|
||||
*/
|
||||
typedef int
|
||||
(*TALER_EXCHANGEDB_DenominationKeyIterator)(
|
||||
void *cls,
|
||||
const char *alias,
|
||||
const struct TALER_EXCHANGEDB_DenominationKey *dki);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Iterator over revoked denomination keys.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param denom_hash hash of the denomination public key
|
||||
* @param revocation_master_sig signature showing @a denom_hash was revoked
|
||||
* @return #GNUNET_OK to continue to iterate,
|
||||
* #GNUNET_NO to stop iteration with no error,
|
||||
* #GNUNET_SYSERR to abort iteration with error!
|
||||
*/
|
||||
typedef int
|
||||
(*TALER_EXCHANGEDB_RevocationIterator)(
|
||||
void *cls,
|
||||
const struct GNUNET_HashCode *denom_hash,
|
||||
const struct TALER_MasterSignatureP *revocation_master_sig);
|
||||
|
||||
|
||||
/**
|
||||
* Call @a it for each denomination key found in the @a exchange_base_dir.
|
||||
*
|
||||
* @param exchange_base_dir base directory for the exchange,
|
||||
* the signing keys must be in the #TALER_EXCHANGEDB_DIR_DENOMINATION_KEYS
|
||||
* subdirectory
|
||||
* @param it function to call on each denomination key found
|
||||
* @param it_cls closure for @a it
|
||||
* @return -1 on error, 0 if no files were found, otherwise
|
||||
* a positive number (however, even with a positive
|
||||
* number it is possible that @a it was never called
|
||||
* as maybe none of the files were well-formed)
|
||||
*/
|
||||
int
|
||||
TALER_EXCHANGEDB_denomination_keys_iterate (
|
||||
const char *exchange_base_dir,
|
||||
TALER_EXCHANGEDB_DenominationKeyIterator it,
|
||||
void *it_cls);
|
||||
|
||||
|
||||
/**
|
||||
* Call @a it for each revoked denomination key found in the @a revocation_dir.
|
||||
*
|
||||
* @param revocation_dir base directory where revocations are stored
|
||||
* @param master_pub master public key (used to check revocations)
|
||||
* @param it function to call on each revoked denomination key found
|
||||
* @param it_cls closure for @a it
|
||||
* @return -1 on error, 0 if no files were found, otherwise
|
||||
* a positive number (however, even with a positive
|
||||
* number it is possible that @a it was never called
|
||||
* as maybe none of the files were well-formed)
|
||||
*/
|
||||
int
|
||||
TALER_EXCHANGEDB_revocations_iterate (
|
||||
const char *revocation_dir,
|
||||
const struct TALER_MasterPublicKeyP *master_pub,
|
||||
TALER_EXCHANGEDB_RevocationIterator it,
|
||||
void *it_cls);
|
||||
|
||||
|
||||
/**
|
||||
* Mark the given denomination key as revoked and request the wallets
|
||||
* to initiate recoup.
|
||||
*
|
||||
* @param revocation_dir where to write the revocation certificate
|
||||
* @param denom_hash hash of the denomination key to revoke
|
||||
* @param mpriv master private key to sign with
|
||||
* @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure.
|
||||
*/
|
||||
int
|
||||
TALER_EXCHANGEDB_denomination_key_revoke (
|
||||
const char *revocation_dir,
|
||||
const struct GNUNET_HashCode *denom_hash,
|
||||
const struct TALER_MasterPrivateKeyP *mpriv);
|
||||
|
||||
|
||||
/**
|
||||
* Exports a denomination key to the given file.
|
||||
*
|
||||
* @param filename the file where to write the denomination key
|
||||
* @param dki the denomination key
|
||||
* @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure.
|
||||
*/
|
||||
int
|
||||
TALER_EXCHANGEDB_denomination_key_write (
|
||||
const char *filename,
|
||||
const struct TALER_EXCHANGEDB_DenominationKey *dki);
|
||||
|
||||
|
||||
/**
|
||||
* Import a denomination key from the given file.
|
||||
*
|
||||
* @param filename the file to import the key from
|
||||
* @param[out] dki set to the imported denomination key
|
||||
* @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
|
||||
*/
|
||||
int
|
||||
TALER_EXCHANGEDB_denomination_key_read (
|
||||
const char *filename,
|
||||
struct TALER_EXCHANGEDB_DenominationKey *dki);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Iterator over auditor information.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param apub the auditor's public key
|
||||
* @param auditor_url URL of the auditor
|
||||
* @param mpub the exchange's public key (as expected by the auditor)
|
||||
* @param dki_len length of @a asig and @a dki arrays
|
||||
* @param asigs array of the auditor's signatures over the @a dks, of length @a dki_len
|
||||
* @param dki array of denomination coin data signed by the auditor, of length @a dki_len
|
||||
* @return #GNUNET_OK to continue to iterate,
|
||||
* #GNUNET_NO to stop iteration with no error,
|
||||
* #GNUNET_SYSERR to abort iteration with error!
|
||||
*/
|
||||
typedef int
|
||||
(*TALER_EXCHANGEDB_AuditorIterator)(
|
||||
void *cls,
|
||||
const struct TALER_AuditorPublicKeyP *apub,
|
||||
const char *auditor_url,
|
||||
const struct TALER_MasterPublicKeyP *mpub,
|
||||
unsigned int dki_len,
|
||||
const struct TALER_AuditorSignatureP *asigs,
|
||||
const struct TALER_DenominationKeyValidityPS *dki);
|
||||
|
||||
|
||||
/**
|
||||
* Call @a it with information for each auditor found in the
|
||||
* directory with auditor information as specified in @a cfg.
|
||||
*
|
||||
* @param cfg configuration to use
|
||||
* @param it function to call with auditor information
|
||||
* @param it_cls closure for @a it
|
||||
* @return -1 on error, 0 if no files were found, otherwise
|
||||
* a positive number (however, even with a positive
|
||||
* number it is possible that @a it was never called
|
||||
* as maybe none of the files were well-formed)
|
||||
*/
|
||||
int
|
||||
TALER_EXCHANGEDB_auditor_iterate (const struct GNUNET_CONFIGURATION_Handle *cfg,
|
||||
TALER_EXCHANGEDB_AuditorIterator it,
|
||||
void *it_cls);
|
||||
|
||||
|
||||
/**
|
||||
* Write auditor information to the given file.
|
||||
*
|
||||
* @param filename the file where to write the auditor information to
|
||||
* @param apub the auditor's public key
|
||||
* @param auditor_url the URL of the auditor
|
||||
* @param asigs the auditor's signatures, array of length @a dki_len
|
||||
* @param mpub the exchange's public key (as expected by the auditor)
|
||||
* @param dki_len length of @a dki and @a asigs arrays
|
||||
* @param dki array of denomination coin data signed by the auditor
|
||||
* @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure.
|
||||
*/
|
||||
int
|
||||
TALER_EXCHANGEDB_auditor_write (
|
||||
const char *filename,
|
||||
const struct TALER_AuditorPublicKeyP *apub,
|
||||
const char *auditor_url,
|
||||
const struct TALER_AuditorSignatureP *asigs,
|
||||
const struct TALER_MasterPublicKeyP *mpub,
|
||||
uint32_t dki_len,
|
||||
const struct TALER_DenominationKeyValidityPS *dki);
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the plugin.
|
||||
@ -291,93 +47,6 @@ void
|
||||
TALER_EXCHANGEDB_plugin_unload (struct TALER_EXCHANGEDB_Plugin *plugin);
|
||||
|
||||
|
||||
/**
|
||||
* Sorted list of fees to be paid for aggregate wire transfers.
|
||||
* Sorted by @e start_date or @e end_date --- both work fine as
|
||||
* the resulting order must be the same.
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_AggregateFees
|
||||
{
|
||||
/**
|
||||
* This is a linked list.
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_AggregateFees *next;
|
||||
|
||||
/**
|
||||
* Fee to be paid for wire transfers to a merchant.
|
||||
*/
|
||||
struct TALER_Amount wire_fee;
|
||||
|
||||
/**
|
||||
* Fee to be paid when we close a reserve and send funds back.
|
||||
*/
|
||||
struct TALER_Amount closing_fee;
|
||||
|
||||
/**
|
||||
* Time when this fee goes into effect (inclusive)
|
||||
*/
|
||||
struct GNUNET_TIME_Absolute start_date;
|
||||
|
||||
/**
|
||||
* Time when this fee stops being in effect (exclusive).
|
||||
*/
|
||||
struct GNUNET_TIME_Absolute end_date;
|
||||
|
||||
/**
|
||||
* Signature affirming the above fee structure.
|
||||
*/
|
||||
struct TALER_MasterSignatureP master_sig;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Read the current fee structure from disk.
|
||||
*
|
||||
* @param cfg configuration to use
|
||||
* @param wireplugin name of the wire plugin to read fees for
|
||||
* @return sorted list of aggregation fees, NULL on error
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_AggregateFees *
|
||||
TALER_EXCHANGEDB_fees_read (const struct GNUNET_CONFIGURATION_Handle *cfg,
|
||||
const char *wireplugin);
|
||||
|
||||
|
||||
/**
|
||||
* Convert @a af to @a wf.
|
||||
*
|
||||
* @param wiremethod name of the wire method the fees are for
|
||||
* @param[in,out] af aggregate fees, host format (updated to round time)
|
||||
* @param[out] wf aggregate fees, disk / signature format
|
||||
*/
|
||||
void
|
||||
TALER_EXCHANGEDB_fees_2_wf (const char *wiremethod,
|
||||
struct TALER_EXCHANGEDB_AggregateFees *af,
|
||||
struct TALER_MasterWireFeePS *wf);
|
||||
|
||||
|
||||
/**
|
||||
* Write given fee structure to disk.
|
||||
*
|
||||
* @param filename where to write the fees
|
||||
* @param wireplugin name of the plugin for which we write the fees
|
||||
* @param af fee structure to write
|
||||
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
|
||||
*/
|
||||
int
|
||||
TALER_EXCHANGEDB_fees_write (const char *filename,
|
||||
const char *wireplugin,
|
||||
struct TALER_EXCHANGEDB_AggregateFees *af);
|
||||
|
||||
|
||||
/**
|
||||
* Free @a af data structure
|
||||
*
|
||||
* @param af list to free
|
||||
*/
|
||||
void
|
||||
TALER_EXCHANGEDB_fees_free (struct TALER_EXCHANGEDB_AggregateFees *af);
|
||||
|
||||
|
||||
/**
|
||||
* Information about an account from the configuration.
|
||||
*/
|
||||
@ -485,11 +154,6 @@ struct TALER_EXCHANGEDB_WireAccount
|
||||
*/
|
||||
struct TALER_BANK_AuthenticationData auth;
|
||||
|
||||
/**
|
||||
* Wire transfer fee structure.
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_AggregateFees *af;
|
||||
|
||||
/**
|
||||
* Name of the section that configures this account.
|
||||
*/
|
||||
@ -503,24 +167,6 @@ struct TALER_EXCHANGEDB_WireAccount
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Update wire transfer fee data structure in @a wa.
|
||||
*
|
||||
* @param cfg configuration to use
|
||||
* @param db_plugin database plugin to use
|
||||
* @param wa wire account data structure to update
|
||||
* @param now timestamp to update fees to
|
||||
* @param session DB session to use
|
||||
* @return fee valid at @a now, or NULL if unknown
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_AggregateFees *
|
||||
TALER_EXCHANGEDB_update_fees (const struct GNUNET_CONFIGURATION_Handle *cfg,
|
||||
struct TALER_EXCHANGEDB_Plugin *db_plugin,
|
||||
struct TALER_EXCHANGEDB_WireAccount *wa,
|
||||
struct GNUNET_TIME_Absolute now,
|
||||
struct TALER_EXCHANGEDB_Session *session);
|
||||
|
||||
|
||||
/**
|
||||
* Find the wire plugin for the given payto:// URL.
|
||||
* Only useful after the accounts have been loaded
|
||||
|
@ -206,15 +206,19 @@ TALER_TESTING_cleanup_files_cfg (void *cls,
|
||||
|
||||
|
||||
/**
|
||||
* Run `taler-exchange-keyup`.
|
||||
* Run `taler-exchange-offline`.
|
||||
*
|
||||
* @param config_filename configuration file to use
|
||||
* @param output_filename where to write the output for the auditor
|
||||
* @param payto_uri bank account to enable, can be NULL
|
||||
* @param auditor_pub public key of auditor to enable, can be NULL
|
||||
* @param auditor_url URL of auditor to enable, can be NULL
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
int
|
||||
TALER_TESTING_run_keyup (const char *config_filename,
|
||||
const char *output_filename);
|
||||
TALER_TESTING_run_exchange_offline (const char *config_filename,
|
||||
const char *payto_uri,
|
||||
const char *auditor_pub,
|
||||
const char *auditor_url);
|
||||
|
||||
|
||||
/**
|
||||
@ -238,21 +242,13 @@ TALER_TESTING_exchange_db_reset (const char *config_filename);
|
||||
|
||||
|
||||
/**
|
||||
* Run `taler-auditor-sign`.
|
||||
* Run `taler-auditor-offline` tool.
|
||||
*
|
||||
* @param config_filename configuration file to use
|
||||
* @param exchange_master_pub master public key of the exchange
|
||||
* @param auditor_base_url what is the base URL of the auditor
|
||||
* @param signdata_in where is the information from taler-exchange-keyup
|
||||
* @param signdata_out where to write the output for the exchange
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
int
|
||||
TALER_TESTING_run_auditor_sign (const char *config_filename,
|
||||
const char *exchange_master_pub,
|
||||
const char *auditor_base_url,
|
||||
const char *signdata_in,
|
||||
const char *signdata_out);
|
||||
TALER_TESTING_run_auditor_offline (const char *config_filename);
|
||||
|
||||
|
||||
/**
|
||||
@ -1220,18 +1216,6 @@ TALER_TESTING_cmd_exec_transfer (const char *label,
|
||||
const char *config_filename);
|
||||
|
||||
|
||||
/**
|
||||
* Make a "auditor sign" CMD.
|
||||
*
|
||||
* @param label command label
|
||||
* @param config_filename configuration filename
|
||||
* @return the command.
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_exec_auditor_sign (const char *label,
|
||||
const char *config_filename);
|
||||
|
||||
|
||||
/**
|
||||
* Create a withdraw command, letting the caller specify
|
||||
* the desired amount as string.
|
||||
|
@ -54,7 +54,6 @@ libtalertesting_la_SOURCES = \
|
||||
testing_api_cmd_deposit.c \
|
||||
testing_api_cmd_deposits_get.c \
|
||||
testing_api_cmd_exec_aggregator.c \
|
||||
testing_api_cmd_exec_auditor-sign.c \
|
||||
testing_api_cmd_exec_closer.c \
|
||||
testing_api_cmd_exec_transfer.c \
|
||||
testing_api_cmd_exec_wirewatch.c \
|
||||
|
@ -1,232 +0,0 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2018 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 3, or (at your
|
||||
option) any later version.
|
||||
|
||||
TALER is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with TALER; see the file COPYING. If not,
|
||||
see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file testing/testing_api_cmd_exec_auditor-sign.c
|
||||
* @brief run the taler-exchange-aggregator command
|
||||
* @author Marcello Stanisci
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "taler_signatures.h"
|
||||
#include "taler_testing_lib.h"
|
||||
|
||||
|
||||
/**
|
||||
* State for a "auditor sign" CMD.
|
||||
*/
|
||||
struct AuditorSignState
|
||||
{
|
||||
|
||||
/**
|
||||
* Handle to the process making the signature.
|
||||
*/
|
||||
struct GNUNET_OS_Process *auditor_sign_proc;
|
||||
|
||||
/**
|
||||
* Configuration file used by the command.
|
||||
*/
|
||||
const char *config_filename;
|
||||
|
||||
/**
|
||||
* File name of signed blob.
|
||||
*/
|
||||
char *signed_keys_out;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Run the command; calls the `taler-auditor-sign' program.
|
||||
*
|
||||
* @param cls closure.
|
||||
* @param cmd the command.
|
||||
* @param is interpreter state.
|
||||
*/
|
||||
static void
|
||||
auditor_sign_run (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd,
|
||||
struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
struct AuditorSignState *ass = cls;
|
||||
struct GNUNET_CONFIGURATION_Handle *cfg;
|
||||
char *test_home_dir;
|
||||
char *exchange_master_pub;
|
||||
struct GNUNET_TIME_Absolute now;
|
||||
|
||||
(void) cmd;
|
||||
cfg = GNUNET_CONFIGURATION_create ();
|
||||
if (GNUNET_OK != GNUNET_CONFIGURATION_load
|
||||
(cfg, ass->config_filename))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_get_value_filename (cfg,
|
||||
"paths",
|
||||
"TALER_TEST_HOME",
|
||||
&test_home_dir))
|
||||
{
|
||||
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
||||
"paths",
|
||||
"TALER_TEST_HOME");
|
||||
GNUNET_CONFIGURATION_destroy (cfg);
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
now = GNUNET_TIME_absolute_get ();
|
||||
GNUNET_asprintf
|
||||
(&ass->signed_keys_out,
|
||||
"%s/.local/share/taler/auditors/auditor-%llu.out",
|
||||
test_home_dir,
|
||||
(unsigned long long) now.abs_value_us);
|
||||
GNUNET_free (test_home_dir);
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_get_value_string (cfg,
|
||||
"exchange",
|
||||
"MASTER_PUBLIC_KEY",
|
||||
&exchange_master_pub))
|
||||
{
|
||||
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
||||
"exchange",
|
||||
"MASTER_PUBLIC_KEY");
|
||||
GNUNET_CONFIGURATION_destroy (cfg);
|
||||
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
|
||||
GNUNET_CONFIGURATION_destroy (cfg);
|
||||
|
||||
ass->auditor_sign_proc
|
||||
= GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
|
||||
NULL, NULL, NULL,
|
||||
"taler-auditor-sign",
|
||||
"taler-auditor-sign",
|
||||
"-c", ass->config_filename,
|
||||
"-u", "http://auditor/",
|
||||
"-m", exchange_master_pub,
|
||||
"-r", "auditor.in",
|
||||
"-o", ass->signed_keys_out,
|
||||
NULL);
|
||||
GNUNET_free (exchange_master_pub);
|
||||
if (NULL == ass->auditor_sign_proc)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
TALER_TESTING_wait_for_sigchld (is);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Free the state of a "auditor sign" CMD, and possibly
|
||||
* kill its process if it did not terminate correctly.
|
||||
*
|
||||
* @param cls closure.
|
||||
* @param cmd the command being freed.
|
||||
*/
|
||||
static void
|
||||
auditor_sign_cleanup (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd)
|
||||
{
|
||||
struct AuditorSignState *ass = cls;
|
||||
|
||||
(void) cmd;
|
||||
if (NULL != ass->auditor_sign_proc)
|
||||
{
|
||||
GNUNET_break (0 == GNUNET_OS_process_kill
|
||||
(ass->auditor_sign_proc, SIGKILL));
|
||||
GNUNET_OS_process_wait (ass->auditor_sign_proc);
|
||||
GNUNET_OS_process_destroy (ass->auditor_sign_proc);
|
||||
ass->auditor_sign_proc = NULL;
|
||||
}
|
||||
GNUNET_free (ass->signed_keys_out);
|
||||
GNUNET_free (ass);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Offer "auditor sign" CMD internal data to other commands.
|
||||
*
|
||||
* @param cls closure.
|
||||
* @param[out] ret result.
|
||||
* @param trait name of the trait.
|
||||
* @param index index number of the object to offer.
|
||||
* @return #GNUNET_OK on success.
|
||||
*/
|
||||
static int
|
||||
auditor_sign_traits (void *cls,
|
||||
const void **ret,
|
||||
const char *trait,
|
||||
unsigned int index)
|
||||
{
|
||||
struct AuditorSignState *ass = cls;
|
||||
struct TALER_TESTING_Trait traits[] = {
|
||||
TALER_TESTING_make_trait_process (0, &ass->auditor_sign_proc),
|
||||
TALER_TESTING_trait_end ()
|
||||
};
|
||||
|
||||
return TALER_TESTING_get_trait (traits,
|
||||
ret,
|
||||
trait,
|
||||
index);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make a "auditor sign" CMD.
|
||||
*
|
||||
* @param label command label
|
||||
* @param config_filename configuration filename
|
||||
*
|
||||
* @return the command.
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_exec_auditor_sign (const char *label,
|
||||
const char *config_filename)
|
||||
{
|
||||
struct AuditorSignState *ass;
|
||||
|
||||
ass = GNUNET_new (struct AuditorSignState);
|
||||
ass->config_filename = config_filename;
|
||||
|
||||
{
|
||||
struct TALER_TESTING_Command cmd = {
|
||||
.cls = ass,
|
||||
.label = label,
|
||||
.run = &auditor_sign_run,
|
||||
.cleanup = &auditor_sign_cleanup,
|
||||
.traits = &auditor_sign_traits
|
||||
};
|
||||
|
||||
return cmd;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* end of testing_api_cmd_exec_auditor-sign.c */
|
Loading…
Reference in New Issue
Block a user