activating implementation of #6175
This commit is contained in:
parent
468fc9d1a1
commit
b5d88fc2d1
@ -1 +1 @@
|
|||||||
Subproject commit 3501eb7b857d573258c1ab1c42d7e827c36cec9d
|
Subproject commit 912dc84dc52a1291b635e19da32c7c824719f8d4
|
@ -10,9 +10,9 @@ make
|
|||||||
cd ../../..
|
cd ../../..
|
||||||
if ! diff contrib/gana/gnu-taler-error-codes/taler_error_codes.h src/include/taler_error_codes.h > /dev/null
|
if ! diff contrib/gana/gnu-taler-error-codes/taler_error_codes.h src/include/taler_error_codes.h > /dev/null
|
||||||
then
|
then
|
||||||
echo "Deploying latest new GANA database..."
|
|
||||||
cp contrib/gana/gnu-taler-error-codes/taler_error_codes.h src/include/taler_error_codes.h
|
cp contrib/gana/gnu-taler-error-codes/taler_error_codes.h src/include/taler_error_codes.h
|
||||||
cp contrib/gana/gnu-taler-error-codes/taler_error_codes.c src/util/taler_error_codes.c
|
fi
|
||||||
else
|
if ! diff contrib/gana/gnu-taler-error-codes/taler_error_codes.c src/util/taler_error_codes.c > /dev/null
|
||||||
echo "GANA database already up-to-date"
|
then
|
||||||
|
cp contrib/gana/gnu-taler-error-codes/taler_error_codes.c src/util/taler_error_codes.c
|
||||||
fi
|
fi
|
||||||
|
@ -116,6 +116,11 @@ mv a2e.dat $ABD
|
|||||||
# Launch services
|
# Launch services
|
||||||
echo "Launching services"
|
echo "Launching services"
|
||||||
taler-bank-manage-testing $CONF postgres:///$TARGET_DB serve &
|
taler-bank-manage-testing $CONF postgres:///$TARGET_DB serve &
|
||||||
|
TFN=`which taler-exchange-httpd`
|
||||||
|
TBINPFX=`dirname $TFN`
|
||||||
|
TLIBEXEC=${BINPFX}/../lib/libexec/taler/
|
||||||
|
$TLIBEXEC/taler-helper-crypto-eddsa -c $CONF 2> taler-helper-crypto-eddsa.log &
|
||||||
|
$TLIBEXEC/taler-helper-crypto-rsa -c $CONF 2> taler-helper-crypto-rsa.log &
|
||||||
taler-exchange-httpd -c $CONF 2> taler-exchange-httpd.log &
|
taler-exchange-httpd -c $CONF 2> taler-exchange-httpd.log &
|
||||||
taler-merchant-httpd -c $CONF -L INFO 2> taler-merchant-httpd.log &
|
taler-merchant-httpd -c $CONF -L INFO 2> taler-merchant-httpd.log &
|
||||||
taler-exchange-wirewatch -c $CONF 2> taler-exchange-wirewatch.log &
|
taler-exchange-wirewatch -c $CONF 2> taler-exchange-wirewatch.log &
|
||||||
|
@ -104,6 +104,11 @@ mv a2e.dat $ABD
|
|||||||
# Launch services
|
# Launch services
|
||||||
echo "Launching services"
|
echo "Launching services"
|
||||||
taler-bank-manage-testing $CONF postgres:///$TARGET_DB serve &> revocation-bank.log &
|
taler-bank-manage-testing $CONF postgres:///$TARGET_DB serve &> revocation-bank.log &
|
||||||
|
TFN=`which taler-exchange-httpd`
|
||||||
|
TBINPFX=`dirname $TFN`
|
||||||
|
TLIBEXEC=${BINPFX}/../lib/libexec/taler/
|
||||||
|
$TLIBEXEC/taler-helper-crypto-eddsa -c $CONF 2> taler-helper-crypto-eddsa.log &
|
||||||
|
$TLIBEXEC/taler-helper-crypto-rsa -c $CONF 2> taler-helper-crypto-rsa.log &
|
||||||
taler-exchange-httpd -c $CONF 2> taler-exchange-httpd.log &
|
taler-exchange-httpd -c $CONF 2> taler-exchange-httpd.log &
|
||||||
EXCHANGE_PID=$!
|
EXCHANGE_PID=$!
|
||||||
taler-merchant-httpd -c $CONF -L INFO 2> taler-merchant-httpd.log &
|
taler-merchant-httpd -c $CONF -L INFO 2> taler-merchant-httpd.log &
|
||||||
|
@ -562,8 +562,8 @@ handle_post_management (const struct TEH_RequestHandler *rh,
|
|||||||
return r404 (connection,
|
return r404 (connection,
|
||||||
"/management/denominations/$HDP/revoke");
|
"/management/denominations/$HDP/revoke");
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
GNUNET_STRINGS_string_to_data (args[2],
|
GNUNET_STRINGS_string_to_data (args[1],
|
||||||
strlen (args[2]),
|
strlen (args[1]),
|
||||||
&h_denom_pub,
|
&h_denom_pub,
|
||||||
sizeof (h_denom_pub)))
|
sizeof (h_denom_pub)))
|
||||||
{
|
{
|
||||||
@ -571,7 +571,7 @@ handle_post_management (const struct TEH_RequestHandler *rh,
|
|||||||
return TALER_MHD_reply_with_error (connection,
|
return TALER_MHD_reply_with_error (connection,
|
||||||
MHD_HTTP_BAD_REQUEST,
|
MHD_HTTP_BAD_REQUEST,
|
||||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
||||||
args[2]);
|
args[1]);
|
||||||
}
|
}
|
||||||
return TEH_handler_management_denominations_HDP_revoke (connection,
|
return TEH_handler_management_denominations_HDP_revoke (connection,
|
||||||
&h_denom_pub,
|
&h_denom_pub,
|
||||||
@ -591,8 +591,8 @@ handle_post_management (const struct TEH_RequestHandler *rh,
|
|||||||
return r404 (connection,
|
return r404 (connection,
|
||||||
"/management/signkeys/$HDP/revoke");
|
"/management/signkeys/$HDP/revoke");
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
GNUNET_STRINGS_string_to_data (args[2],
|
GNUNET_STRINGS_string_to_data (args[1],
|
||||||
strlen (args[2]),
|
strlen (args[1]),
|
||||||
&exchange_pub,
|
&exchange_pub,
|
||||||
sizeof (exchange_pub)))
|
sizeof (exchange_pub)))
|
||||||
{
|
{
|
||||||
@ -600,7 +600,7 @@ handle_post_management (const struct TEH_RequestHandler *rh,
|
|||||||
return TALER_MHD_reply_with_error (connection,
|
return TALER_MHD_reply_with_error (connection,
|
||||||
MHD_HTTP_BAD_REQUEST,
|
MHD_HTTP_BAD_REQUEST,
|
||||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
||||||
args[2]);
|
args[1]);
|
||||||
}
|
}
|
||||||
return TEH_handler_management_signkeys_EP_revoke (connection,
|
return TEH_handler_management_signkeys_EP_revoke (connection,
|
||||||
&exchange_pub,
|
&exchange_pub,
|
||||||
@ -805,7 +805,7 @@ handle_mhd_request (void *cls,
|
|||||||
{
|
{
|
||||||
.url = "keys",
|
.url = "keys",
|
||||||
.method = MHD_HTTP_METHOD_GET,
|
.method = MHD_HTTP_METHOD_GET,
|
||||||
.handler.get = &TEH_handler_keys, // FIXME => TEH_keys_get_handler
|
.handler.get = &TEH_keys_get_handler,
|
||||||
},
|
},
|
||||||
/* Requests for wiring information */
|
/* Requests for wiring information */
|
||||||
{
|
{
|
||||||
@ -1427,6 +1427,7 @@ run_single_request (void)
|
|||||||
}
|
}
|
||||||
MHD_run (mhd);
|
MHD_run (mhd);
|
||||||
}
|
}
|
||||||
|
TEH_resume_keys_requests ();
|
||||||
MHD_stop_daemon (mhd);
|
MHD_stop_daemon (mhd);
|
||||||
mhd = NULL;
|
mhd = NULL;
|
||||||
if (cld != waitpid (cld,
|
if (cld != waitpid (cld,
|
||||||
@ -1463,6 +1464,7 @@ run_main_loop (int fh,
|
|||||||
= MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_PIPE_FOR_SHUTDOWN
|
= MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_PIPE_FOR_SHUTDOWN
|
||||||
| MHD_USE_DEBUG | MHD_USE_DUAL_STACK
|
| MHD_USE_DEBUG | MHD_USE_DUAL_STACK
|
||||||
| MHD_USE_INTERNAL_POLLING_THREAD
|
| MHD_USE_INTERNAL_POLLING_THREAD
|
||||||
|
| MHD_ALLOW_SUSPEND_RESUME
|
||||||
| MHD_USE_TCP_FASTOPEN,
|
| MHD_USE_TCP_FASTOPEN,
|
||||||
(-1 == fh) ? serve_port : 0,
|
(-1 == fh) ? serve_port : 0,
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
@ -1484,11 +1486,17 @@ run_main_loop (int fh,
|
|||||||
}
|
}
|
||||||
|
|
||||||
atexit (&write_stats);
|
atexit (&write_stats);
|
||||||
|
ret = TEH_keys_init ();
|
||||||
|
if (GNUNET_OK == ret)
|
||||||
|
{
|
||||||
ret = TEH_KS_loop ();
|
ret = TEH_KS_loop ();
|
||||||
|
TEH_keys_done ();
|
||||||
|
}
|
||||||
switch (ret)
|
switch (ret)
|
||||||
{
|
{
|
||||||
case GNUNET_OK:
|
case GNUNET_OK:
|
||||||
case GNUNET_SYSERR:
|
case GNUNET_SYSERR:
|
||||||
|
TEH_resume_keys_requests ();
|
||||||
MHD_stop_daemon (mhd);
|
MHD_stop_daemon (mhd);
|
||||||
break;
|
break;
|
||||||
case GNUNET_NO:
|
case GNUNET_NO:
|
||||||
@ -1544,11 +1552,13 @@ run_main_loop (int fh,
|
|||||||
num_connections)
|
num_connections)
|
||||||
sleep (1);
|
sleep (1);
|
||||||
/* Now we're really done, practice clean shutdown */
|
/* Now we're really done, practice clean shutdown */
|
||||||
|
TEH_resume_keys_requests ();
|
||||||
MHD_stop_daemon (mhd);
|
MHD_stop_daemon (mhd);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
|
TEH_resume_keys_requests ();
|
||||||
MHD_stop_daemon (mhd);
|
MHD_stop_daemon (mhd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,11 @@ extern struct TALER_EXCHANGEDB_Plugin *TEH_plugin;
|
|||||||
*/
|
*/
|
||||||
extern char *TEH_currency;
|
extern char *TEH_currency;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Are we shutting down?
|
||||||
|
*/
|
||||||
|
extern volatile bool MHD_terminating;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Struct describing an URL and the handler for it.
|
* @brief Struct describing an URL and the handler for it.
|
||||||
*/
|
*/
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "taler-exchange-httpd_deposit.h"
|
#include "taler-exchange-httpd_deposit.h"
|
||||||
#include "taler-exchange-httpd_responses.h"
|
#include "taler-exchange-httpd_responses.h"
|
||||||
#include "taler-exchange-httpd_keystate.h"
|
#include "taler-exchange-httpd_keystate.h"
|
||||||
|
#include "taler-exchange-httpd_keys.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,18 +76,18 @@ reply_deposit_success (struct MHD_Connection *connection,
|
|||||||
.coin_pub = *coin_pub,
|
.coin_pub = *coin_pub,
|
||||||
.merchant = *merchant
|
.merchant = *merchant
|
||||||
};
|
};
|
||||||
|
enum TALER_ErrorCode ec;
|
||||||
|
|
||||||
TALER_amount_hton (&dc.amount_without_fee,
|
TALER_amount_hton (&dc.amount_without_fee,
|
||||||
amount_without_fee);
|
amount_without_fee);
|
||||||
if (GNUNET_OK !=
|
if (TALER_EC_NONE !=
|
||||||
TEH_KS_sign (&dc,
|
(ec = TEH_keys_exchange_sign (&dc,
|
||||||
&pub,
|
&pub,
|
||||||
&sig))
|
&sig)))
|
||||||
{
|
{
|
||||||
return TALER_MHD_reply_with_error (connection,
|
return TALER_MHD_reply_with_ec (connection,
|
||||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
ec,
|
||||||
TALER_EC_EXCHANGE_GENERIC_BAD_CONFIGURATION,
|
NULL);
|
||||||
"no keys");
|
|
||||||
}
|
}
|
||||||
return TALER_MHD_reply_json_pack (
|
return TALER_MHD_reply_json_pack (
|
||||||
connection,
|
connection,
|
||||||
@ -430,9 +431,10 @@ TEH_handler_deposit (struct MHD_Connection *connection,
|
|||||||
/* check denomination exists and is valid */
|
/* check denomination exists and is valid */
|
||||||
{
|
{
|
||||||
struct TEH_KS_StateHandle *key_state;
|
struct TEH_KS_StateHandle *key_state;
|
||||||
struct TALER_EXCHANGEDB_DenominationKey *dki;
|
struct TEH_DenominationKey *dk;
|
||||||
enum TALER_ErrorCode ec;
|
enum TALER_ErrorCode ec;
|
||||||
unsigned int hc;
|
unsigned int hc;
|
||||||
|
struct GNUNET_TIME_Absolute now;
|
||||||
|
|
||||||
key_state = TEH_KS_acquire (dc.exchange_timestamp);
|
key_state = TEH_KS_acquire (dc.exchange_timestamp);
|
||||||
if (NULL == key_state)
|
if (NULL == key_state)
|
||||||
@ -444,12 +446,10 @@ TEH_handler_deposit (struct MHD_Connection *connection,
|
|||||||
TALER_EC_EXCHANGE_GENERIC_BAD_CONFIGURATION,
|
TALER_EC_EXCHANGE_GENERIC_BAD_CONFIGURATION,
|
||||||
"no keys");
|
"no keys");
|
||||||
}
|
}
|
||||||
dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
|
dk = TEH_keys_denomination_by_hash (&deposit.coin.denom_pub_hash,
|
||||||
&deposit.coin.denom_pub_hash,
|
|
||||||
TEH_KS_DKU_DEPOSIT,
|
|
||||||
&ec,
|
&ec,
|
||||||
&hc);
|
&hc);
|
||||||
if (NULL == dki)
|
if (NULL == dk)
|
||||||
{
|
{
|
||||||
TALER_LOG_DEBUG ("Unknown denomination key in /deposit request\n");
|
TALER_LOG_DEBUG ("Unknown denomination key in /deposit request\n");
|
||||||
TEH_KS_release (key_state);
|
TEH_KS_release (key_state);
|
||||||
@ -459,8 +459,42 @@ TEH_handler_deposit (struct MHD_Connection *connection,
|
|||||||
ec,
|
ec,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
TALER_amount_ntoh (&deposit.deposit_fee,
|
now = GNUNET_TIME_absolute_get ();
|
||||||
&dki->issue.properties.fee_deposit);
|
if (now.abs_value_us >= dk->meta.expire_deposit.abs_value_us)
|
||||||
|
{
|
||||||
|
/* This denomination is past the expiration time for deposits */
|
||||||
|
TEH_KS_release (key_state);
|
||||||
|
GNUNET_JSON_parse_free (spec);
|
||||||
|
return TALER_MHD_reply_with_error (
|
||||||
|
connection,
|
||||||
|
MHD_HTTP_GONE,
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
if (now.abs_value_us < dk->meta.start.abs_value_us)
|
||||||
|
{
|
||||||
|
/* This denomination is not yet valid */
|
||||||
|
TEH_KS_release (key_state);
|
||||||
|
GNUNET_JSON_parse_free (spec);
|
||||||
|
return TALER_MHD_reply_with_error (
|
||||||
|
connection,
|
||||||
|
MHD_HTTP_PRECONDITION_FAILED,
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
if (dk->recoup_possible)
|
||||||
|
{
|
||||||
|
/* This denomination has been revoked */
|
||||||
|
TEH_KS_release (key_state);
|
||||||
|
GNUNET_JSON_parse_free (spec);
|
||||||
|
return TALER_MHD_reply_with_error (
|
||||||
|
connection,
|
||||||
|
MHD_HTTP_GONE,
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
deposit.deposit_fee = dk->meta.fee_deposit;
|
||||||
if (GNUNET_YES !=
|
if (GNUNET_YES !=
|
||||||
TALER_amount_cmp_currency (&deposit.amount_with_fee,
|
TALER_amount_cmp_currency (&deposit.amount_with_fee,
|
||||||
&deposit.deposit_fee) )
|
&deposit.deposit_fee) )
|
||||||
@ -476,7 +510,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
|
|||||||
/* check coin signature */
|
/* check coin signature */
|
||||||
if (GNUNET_YES !=
|
if (GNUNET_YES !=
|
||||||
TALER_test_coin_valid (&deposit.coin,
|
TALER_test_coin_valid (&deposit.coin,
|
||||||
&dki->denom_pub))
|
&dk->denom_pub))
|
||||||
{
|
{
|
||||||
TALER_LOG_WARNING ("Invalid coin passed for /deposit\n");
|
TALER_LOG_WARNING ("Invalid coin passed for /deposit\n");
|
||||||
TEH_KS_release (key_state);
|
TEH_KS_release (key_state);
|
||||||
@ -486,8 +520,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
|
|||||||
TALER_EC_EXCHANGE_DENOMINATION_SIGNATURE_INVALID,
|
TALER_EC_EXCHANGE_DENOMINATION_SIGNATURE_INVALID,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
TALER_amount_ntoh (&dc.value,
|
dc.value = dk->meta.value;
|
||||||
&dki->issue.properties.value);
|
|
||||||
TEH_KS_release (key_state);
|
TEH_KS_release (key_state);
|
||||||
}
|
}
|
||||||
if (0 < TALER_amount_cmp (&deposit.deposit_fee,
|
if (0 < TALER_amount_cmp (&deposit.deposit_fee,
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "taler_mhd_lib.h"
|
#include "taler_mhd_lib.h"
|
||||||
#include "taler_signatures.h"
|
#include "taler_signatures.h"
|
||||||
#include "taler-exchange-httpd_keystate.h"
|
#include "taler-exchange-httpd_keystate.h"
|
||||||
|
#include "taler-exchange-httpd_keys.h"
|
||||||
#include "taler-exchange-httpd_deposits_get.h"
|
#include "taler-exchange-httpd_deposits_get.h"
|
||||||
#include "taler-exchange-httpd_responses.h"
|
#include "taler-exchange-httpd_responses.h"
|
||||||
|
|
||||||
@ -65,18 +66,18 @@ reply_deposit_details (struct MHD_Connection *connection,
|
|||||||
.coin_pub = *coin_pub,
|
.coin_pub = *coin_pub,
|
||||||
.execution_time = GNUNET_TIME_absolute_hton (exec_time)
|
.execution_time = GNUNET_TIME_absolute_hton (exec_time)
|
||||||
};
|
};
|
||||||
|
enum TALER_ErrorCode ec;
|
||||||
|
|
||||||
TALER_amount_hton (&cw.coin_contribution,
|
TALER_amount_hton (&cw.coin_contribution,
|
||||||
coin_contribution);
|
coin_contribution);
|
||||||
if (GNUNET_OK !=
|
if (TALER_EC_NONE !=
|
||||||
TEH_KS_sign (&cw,
|
(ec = TEH_keys_exchange_sign (&cw,
|
||||||
&pub,
|
&pub,
|
||||||
&sig))
|
&sig)))
|
||||||
{
|
{
|
||||||
return TALER_MHD_reply_with_error (connection,
|
return TALER_MHD_reply_with_ec (connection,
|
||||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
ec,
|
||||||
TALER_EC_EXCHANGE_GENERIC_BAD_CONFIGURATION,
|
NULL);
|
||||||
"no keys");
|
|
||||||
}
|
}
|
||||||
return TALER_MHD_reply_json_pack (connection,
|
return TALER_MHD_reply_json_pack (connection,
|
||||||
MHD_HTTP_OK,
|
MHD_HTTP_OK,
|
||||||
|
@ -232,17 +232,7 @@ struct SigningKey
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
struct TEH_KeyStateHandle
|
||||||
* Snapshot of the (coin and signing) keys (including private keys) of
|
|
||||||
* the exchange. There can be multiple instances of this struct, as it is
|
|
||||||
* reference counted and only destroyed once the last user is done
|
|
||||||
* with it. The current instance is acquired using
|
|
||||||
* #TEH_KS_acquire(). Using this function increases the
|
|
||||||
* reference count. The contents of this structure (except for the
|
|
||||||
* reference counter) should be considered READ-ONLY until it is
|
|
||||||
* ultimately destroyed (as there can be many concurrent users).
|
|
||||||
*/
|
|
||||||
struct KeyStateHandle
|
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -307,7 +297,30 @@ struct KeyStateHandle
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thread-local. Contains a pointer to `struct KeyStateHandle` or NULL.
|
* Entry of /keys requests that are currently suspended because we are
|
||||||
|
* waiting for /keys to become ready.
|
||||||
|
*/
|
||||||
|
struct SuspendedKeysRequests
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Kept in a DLL.
|
||||||
|
*/
|
||||||
|
struct SuspendedKeysRequests *next;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kept in a DLL.
|
||||||
|
*/
|
||||||
|
struct SuspendedKeysRequests *prev;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The suspended connection.
|
||||||
|
*/
|
||||||
|
struct MHD_Connection *connection;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thread-local. Contains a pointer to `struct TEH_KeyStateHandle` or NULL.
|
||||||
* Stores the per-thread latest generation of our key state.
|
* Stores the per-thread latest generation of our key state.
|
||||||
*/
|
*/
|
||||||
static pthread_key_t key_state;
|
static pthread_key_t key_state;
|
||||||
@ -321,6 +334,16 @@ static pthread_key_t key_state;
|
|||||||
*/
|
*/
|
||||||
static volatile uint64_t key_generation;
|
static volatile uint64_t key_generation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Head of DLL of suspended /keys requests.
|
||||||
|
*/
|
||||||
|
static struct SuspendedKeysRequests *skr_head;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tail of DLL of suspended /keys requests.
|
||||||
|
*/
|
||||||
|
static struct SuspendedKeysRequests *skr_tail;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For how long should a signing key be legally retained?
|
* For how long should a signing key be legally retained?
|
||||||
* Configuration value.
|
* Configuration value.
|
||||||
@ -343,6 +366,73 @@ static struct TALER_SecurityModulePublicKeyP esign_sm_pub;
|
|||||||
*/
|
*/
|
||||||
static pthread_mutex_t sm_pub_mutex = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t sm_pub_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mutex protecting access to #skr_head and #skr_tail.
|
||||||
|
* (Could be split into two locks if ever needed.)
|
||||||
|
*/
|
||||||
|
static pthread_mutex_t skr_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Are we shutting down?
|
||||||
|
*/
|
||||||
|
static bool terminating;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Did we ever initialize #key_state?
|
||||||
|
*/
|
||||||
|
static bool key_state_available;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Suspend /keys request while we (hopefully) are waiting to be
|
||||||
|
* provisioned with key material.
|
||||||
|
*
|
||||||
|
* @param[in] connection to suspend
|
||||||
|
*/
|
||||||
|
static MHD_RESULT
|
||||||
|
suspend_request (struct MHD_Connection *connection)
|
||||||
|
{
|
||||||
|
struct SuspendedKeysRequests *skr;
|
||||||
|
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Suspending /keys request until key material changes\n");
|
||||||
|
GNUNET_assert (0 == pthread_mutex_lock (&skr_mutex));
|
||||||
|
if (terminating)
|
||||||
|
{
|
||||||
|
GNUNET_assert (0 == pthread_mutex_unlock (&skr_mutex));
|
||||||
|
return TALER_MHD_reply_with_error (connection,
|
||||||
|
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
|
||||||
|
"Exchange terminating");
|
||||||
|
}
|
||||||
|
skr = GNUNET_new (struct SuspendedKeysRequests);
|
||||||
|
skr->connection = connection;
|
||||||
|
MHD_suspend_connection (connection);
|
||||||
|
GNUNET_CONTAINER_DLL_insert (skr_head,
|
||||||
|
skr_tail,
|
||||||
|
skr);
|
||||||
|
GNUNET_assert (0 == pthread_mutex_unlock (&skr_mutex));
|
||||||
|
return MHD_YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TEH_resume_keys_requests (void)
|
||||||
|
{
|
||||||
|
struct SuspendedKeysRequests *skr;
|
||||||
|
|
||||||
|
GNUNET_assert (0 == pthread_mutex_lock (&skr_mutex));
|
||||||
|
while (NULL != (skr = skr_head))
|
||||||
|
{
|
||||||
|
GNUNET_CONTAINER_DLL_remove (skr_head,
|
||||||
|
skr_tail,
|
||||||
|
skr);
|
||||||
|
MHD_resume_connection (skr->connection);
|
||||||
|
GNUNET_free (skr);
|
||||||
|
}
|
||||||
|
GNUNET_assert (0 == pthread_mutex_unlock (&skr_mutex));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear memory for responses to "/keys" in @a ksh.
|
* Clear memory for responses to "/keys" in @a ksh.
|
||||||
@ -350,7 +440,7 @@ static pthread_mutex_t sm_pub_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|||||||
* @param[in,out] ksh key state to update
|
* @param[in,out] ksh key state to update
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
clear_response_cache (struct KeyStateHandle *ksh)
|
clear_response_cache (struct TEH_KeyStateHandle *ksh)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i<ksh->krd_array_length; i++)
|
for (unsigned int i = 0; i<ksh->krd_array_length; i++)
|
||||||
{
|
{
|
||||||
@ -530,6 +620,12 @@ helper_denom_cb (
|
|||||||
struct HelperDenomination *hd;
|
struct HelperDenomination *hd;
|
||||||
|
|
||||||
check_denom_sm_pub (sm_pub);
|
check_denom_sm_pub (sm_pub);
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"RSA helper announces key %s for denomination type %s with validity %s\n",
|
||||||
|
GNUNET_h2s (h_denom_pub),
|
||||||
|
section_name,
|
||||||
|
GNUNET_STRINGS_relative_time_to_string (validity_duration,
|
||||||
|
GNUNET_NO));
|
||||||
hd = GNUNET_CONTAINER_multihashmap_get (hs->denom_keys,
|
hd = GNUNET_CONTAINER_multihashmap_get (hs->denom_keys,
|
||||||
h_denom_pub);
|
h_denom_pub);
|
||||||
if (NULL != hd)
|
if (NULL != hd)
|
||||||
@ -594,6 +690,11 @@ helper_esign_cb (
|
|||||||
struct GNUNET_PeerIdentity pid;
|
struct GNUNET_PeerIdentity pid;
|
||||||
|
|
||||||
check_esign_sm_pub (sm_pub);
|
check_esign_sm_pub (sm_pub);
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"EdDSA helper announces signing key %s with validity %s\n",
|
||||||
|
TALER_B2S (exchange_pub),
|
||||||
|
GNUNET_STRINGS_relative_time_to_string (validity_duration,
|
||||||
|
GNUNET_NO));
|
||||||
pid.public_key = exchange_pub->eddsa_pub;
|
pid.public_key = exchange_pub->eddsa_pub;
|
||||||
hsk = GNUNET_CONTAINER_multipeermap_get (hs->esign_keys,
|
hsk = GNUNET_CONTAINER_multipeermap_get (hs->esign_keys,
|
||||||
&pid);
|
&pid);
|
||||||
@ -675,7 +776,7 @@ sync_key_helpers (struct HelperState *hs)
|
|||||||
/**
|
/**
|
||||||
* Free denomination key data.
|
* Free denomination key data.
|
||||||
*
|
*
|
||||||
* @param cls a `struct KeyStateHandle`, unused
|
* @param cls a `struct TEH_KeyStateHandle`, unused
|
||||||
* @param h_denom_pub hash of the denomination public key, unused
|
* @param h_denom_pub hash of the denomination public key, unused
|
||||||
* @param value a `struct TEH_DenominationKey` to free
|
* @param value a `struct TEH_DenominationKey` to free
|
||||||
* @return #GNUNET_OK (continue to iterate)
|
* @return #GNUNET_OK (continue to iterate)
|
||||||
@ -706,7 +807,7 @@ clear_denomination_cb (void *cls,
|
|||||||
/**
|
/**
|
||||||
* Free denomination key data.
|
* Free denomination key data.
|
||||||
*
|
*
|
||||||
* @param cls a `struct KeyStateHandle`, unused
|
* @param cls a `struct TEH_KeyStateHandle`, unused
|
||||||
* @param h_denom_pub hash of the denomination public key, unused
|
* @param h_denom_pub hash of the denomination public key, unused
|
||||||
* @param value a `struct SigningKey` to free
|
* @param value a `struct SigningKey` to free
|
||||||
* @return #GNUNET_OK (continue to iterate)
|
* @return #GNUNET_OK (continue to iterate)
|
||||||
@ -733,7 +834,7 @@ clear_signkey_cb (void *cls,
|
|||||||
* @param free_helper true to also release the helper state
|
* @param free_helper true to also release the helper state
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
destroy_key_state (struct KeyStateHandle *ksh,
|
destroy_key_state (struct TEH_KeyStateHandle *ksh,
|
||||||
bool free_helper)
|
bool free_helper)
|
||||||
{
|
{
|
||||||
clear_response_cache (ksh);
|
clear_response_cache (ksh);
|
||||||
@ -762,12 +863,12 @@ destroy_key_state (struct KeyStateHandle *ksh,
|
|||||||
* Free all resources associated with @a cls. Called when
|
* Free all resources associated with @a cls. Called when
|
||||||
* the respective pthread is destroyed.
|
* the respective pthread is destroyed.
|
||||||
*
|
*
|
||||||
* @param[in] cls a `struct KeyStateHandle`.
|
* @param[in] cls a `struct TEH_KeyStateHandle`.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
destroy_key_state_cb (void *cls)
|
destroy_key_state_cb (void *cls)
|
||||||
{
|
{
|
||||||
struct KeyStateHandle *ksh = cls;
|
struct TEH_KeyStateHandle *ksh = cls;
|
||||||
|
|
||||||
destroy_key_state (ksh,
|
destroy_key_state (ksh,
|
||||||
true);
|
true);
|
||||||
@ -786,6 +887,7 @@ TEH_keys_init ()
|
|||||||
pthread_key_create (&key_state,
|
pthread_key_create (&key_state,
|
||||||
&destroy_key_state_cb))
|
&destroy_key_state_cb))
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
|
key_state_available = true;
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
GNUNET_CONFIGURATION_get_value_time (TEH_cfg,
|
GNUNET_CONFIGURATION_get_value_time (TEH_cfg,
|
||||||
"exchange",
|
"exchange",
|
||||||
@ -801,21 +903,33 @@ TEH_keys_init ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close down keys submodule.
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
TEH_keys_done ()
|
TEH_keys_done ()
|
||||||
|
{
|
||||||
|
GNUNET_assert (0 == pthread_mutex_lock (&skr_mutex));
|
||||||
|
terminating = true;
|
||||||
|
GNUNET_assert (0 == pthread_mutex_unlock (&skr_mutex));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fully clean up our state.
|
||||||
|
*/
|
||||||
|
void __attribute__ ((destructor))
|
||||||
|
TEH_keys_finished ()
|
||||||
|
{
|
||||||
|
if (key_state_available)
|
||||||
{
|
{
|
||||||
GNUNET_assert (0 ==
|
GNUNET_assert (0 ==
|
||||||
pthread_key_delete (key_state));
|
pthread_key_delete (key_state));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function called with information about the exchange's denomination keys.
|
* Function called with information about the exchange's denomination keys.
|
||||||
*
|
*
|
||||||
* @param cls closure with a `struct KeyStateHandle *`
|
* @param cls closure with a `struct TEH_KeyStateHandle *`
|
||||||
* @param denom_pub public key of the denomination
|
* @param denom_pub public key of the denomination
|
||||||
* @param h_denom_pub hash of @a denom_pub
|
* @param h_denom_pub hash of @a denom_pub
|
||||||
* @param meta meta data information about the denomination type (value, expirations, fees)
|
* @param meta meta data information about the denomination type (value, expirations, fees)
|
||||||
@ -832,7 +946,7 @@ denomination_info_cb (
|
|||||||
const struct TALER_MasterSignatureP *master_sig,
|
const struct TALER_MasterSignatureP *master_sig,
|
||||||
bool recoup_possible)
|
bool recoup_possible)
|
||||||
{
|
{
|
||||||
struct KeyStateHandle *ksh = cls;
|
struct TEH_KeyStateHandle *ksh = cls;
|
||||||
struct TEH_DenominationKey *dk;
|
struct TEH_DenominationKey *dk;
|
||||||
|
|
||||||
dk = GNUNET_new (struct TEH_DenominationKey);
|
dk = GNUNET_new (struct TEH_DenominationKey);
|
||||||
@ -854,7 +968,7 @@ denomination_info_cb (
|
|||||||
/**
|
/**
|
||||||
* Function called with information about the exchange's online signing keys.
|
* Function called with information about the exchange's online signing keys.
|
||||||
*
|
*
|
||||||
* @param cls closure with a `struct KeyStateHandle *`
|
* @param cls closure with a `struct TEH_KeyStateHandle *`
|
||||||
* @param exchange_pub the public key
|
* @param exchange_pub the public key
|
||||||
* @param meta meta data information about the denomination type (expirations)
|
* @param meta meta data information about the denomination type (expirations)
|
||||||
* @param master_sig master signature affirming the validity of this denomination
|
* @param master_sig master signature affirming the validity of this denomination
|
||||||
@ -866,7 +980,7 @@ signkey_info_cb (
|
|||||||
const struct TALER_EXCHANGEDB_SignkeyMetaData *meta,
|
const struct TALER_EXCHANGEDB_SignkeyMetaData *meta,
|
||||||
const struct TALER_MasterSignatureP *master_sig)
|
const struct TALER_MasterSignatureP *master_sig)
|
||||||
{
|
{
|
||||||
struct KeyStateHandle *ksh = cls;
|
struct TEH_KeyStateHandle *ksh = cls;
|
||||||
struct SigningKey *sk;
|
struct SigningKey *sk;
|
||||||
struct GNUNET_PeerIdentity pid;
|
struct GNUNET_PeerIdentity pid;
|
||||||
|
|
||||||
@ -884,10 +998,66 @@ signkey_info_cb (
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closure for #get_auditor_sigs.
|
||||||
|
*/
|
||||||
|
struct GetAuditorSigsContext
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Where to store the matching signatures.
|
||||||
|
*/
|
||||||
|
json_t *denom_keys;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public key of the auditor to match against.
|
||||||
|
*/
|
||||||
|
const struct TALER_AuditorPublicKeyP *auditor_pub;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract the auditor signatures matching the auditor's public
|
||||||
|
* key from the @a value and generate the respective JSON.
|
||||||
|
*
|
||||||
|
* @param cls a `struct GetAuditorSigsContext`
|
||||||
|
* @param h_denom_pub hash of the denomination public key
|
||||||
|
* @param value a `struct TEH_DenominationKey`
|
||||||
|
* @return #GNUNET_OK (continue to iterate)
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
get_auditor_sigs (void *cls,
|
||||||
|
const struct GNUNET_HashCode *h_denom_pub,
|
||||||
|
void *value)
|
||||||
|
{
|
||||||
|
struct GetAuditorSigsContext *ctx = cls;
|
||||||
|
struct TEH_DenominationKey *dk = value;
|
||||||
|
|
||||||
|
for (struct TEH_AuditorSignature *as = dk->as_head;
|
||||||
|
NULL != as;
|
||||||
|
as = as->next)
|
||||||
|
{
|
||||||
|
if (0 !=
|
||||||
|
GNUNET_memcmp (ctx->auditor_pub,
|
||||||
|
&as->apub))
|
||||||
|
continue;
|
||||||
|
GNUNET_break (0 ==
|
||||||
|
json_array_append_new (
|
||||||
|
ctx->denom_keys,
|
||||||
|
json_pack (
|
||||||
|
"{s:o, s:o}",
|
||||||
|
"denom_pub_h",
|
||||||
|
GNUNET_JSON_from_data_auto (h_denom_pub),
|
||||||
|
"auditor_sig",
|
||||||
|
GNUNET_JSON_from_data_auto (&as->asig))));
|
||||||
|
}
|
||||||
|
return GNUNET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function called with information about the exchange's auditors.
|
* Function called with information about the exchange's auditors.
|
||||||
*
|
*
|
||||||
* @param cls closure with a `struct KeyStateHandle *`
|
* @param cls closure with a `struct TEH_KeyStateHandle *`
|
||||||
* @param auditor_pub the public key of the auditor
|
* @param auditor_pub the public key of the auditor
|
||||||
* @param auditor_url URL of the REST API of the auditor
|
* @param auditor_url URL of the REST API of the auditor
|
||||||
* @param auditor_name human readable official name of the auditor
|
* @param auditor_name human readable official name of the auditor
|
||||||
@ -899,18 +1069,26 @@ auditor_info_cb (
|
|||||||
const char *auditor_url,
|
const char *auditor_url,
|
||||||
const char *auditor_name)
|
const char *auditor_name)
|
||||||
{
|
{
|
||||||
struct KeyStateHandle *ksh = cls;
|
struct TEH_KeyStateHandle *ksh = cls;
|
||||||
|
struct GetAuditorSigsContext ctx;
|
||||||
|
|
||||||
|
ctx.denom_keys = json_array ();
|
||||||
|
ctx.auditor_pub = auditor_pub;
|
||||||
|
GNUNET_CONTAINER_multihashmap_iterate (ksh->denomkey_map,
|
||||||
|
&get_auditor_sigs,
|
||||||
|
&ctx);
|
||||||
GNUNET_break (0 ==
|
GNUNET_break (0 ==
|
||||||
json_array_append_new (
|
json_array_append_new (
|
||||||
ksh->auditors,
|
ksh->auditors,
|
||||||
json_pack ("{s:s, s:o, s:s}",
|
json_pack ("{s:s, s:o, s:s, s:o}",
|
||||||
"name",
|
"auditor_name",
|
||||||
auditor_name,
|
auditor_name,
|
||||||
"auditor_pub",
|
"auditor_pub",
|
||||||
GNUNET_JSON_from_data_auto (auditor_pub),
|
GNUNET_JSON_from_data_auto (auditor_pub),
|
||||||
"url",
|
"auditor_url",
|
||||||
auditor_url)));
|
auditor_url,
|
||||||
|
"denomination_keys",
|
||||||
|
ctx.denom_keys)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -918,7 +1096,7 @@ auditor_info_cb (
|
|||||||
* Function called with information about the denominations
|
* Function called with information about the denominations
|
||||||
* audited by the exchange's auditors.
|
* audited by the exchange's auditors.
|
||||||
*
|
*
|
||||||
* @param cls closure with a `struct KeyStateHandle *`
|
* @param cls closure with a `struct TEH_KeyStateHandle *`
|
||||||
* @param auditor_pub the public key of an auditor
|
* @param auditor_pub the public key of an auditor
|
||||||
* @param h_denom_pub hash of a denomination key audited by this auditor
|
* @param h_denom_pub hash of a denomination key audited by this auditor
|
||||||
* @param auditor_sig signature from the auditor affirming this
|
* @param auditor_sig signature from the auditor affirming this
|
||||||
@ -930,7 +1108,7 @@ auditor_denom_cb (
|
|||||||
const struct GNUNET_HashCode *h_denom_pub,
|
const struct GNUNET_HashCode *h_denom_pub,
|
||||||
const struct TALER_AuditorSignatureP *auditor_sig)
|
const struct TALER_AuditorSignatureP *auditor_sig)
|
||||||
{
|
{
|
||||||
struct KeyStateHandle *ksh = cls;
|
struct TEH_KeyStateHandle *ksh = cls;
|
||||||
struct TEH_DenominationKey *dk;
|
struct TEH_DenominationKey *dk;
|
||||||
struct TEH_AuditorSignature *as;
|
struct TEH_AuditorSignature *as;
|
||||||
|
|
||||||
@ -959,13 +1137,13 @@ auditor_denom_cb (
|
|||||||
* @param[in] hs helper state to (re)use, NULL if not available
|
* @param[in] hs helper state to (re)use, NULL if not available
|
||||||
* @return NULL on error (i.e. failed to access database)
|
* @return NULL on error (i.e. failed to access database)
|
||||||
*/
|
*/
|
||||||
static struct KeyStateHandle *
|
static struct TEH_KeyStateHandle *
|
||||||
build_key_state (struct HelperState *hs)
|
build_key_state (struct HelperState *hs)
|
||||||
{
|
{
|
||||||
struct KeyStateHandle *ksh;
|
struct TEH_KeyStateHandle *ksh;
|
||||||
enum GNUNET_DB_QueryStatus qs;
|
enum GNUNET_DB_QueryStatus qs;
|
||||||
|
|
||||||
ksh = GNUNET_new (struct KeyStateHandle);
|
ksh = GNUNET_new (struct TEH_KeyStateHandle);
|
||||||
ksh->reload_time = GNUNET_TIME_absolute_get ();
|
ksh->reload_time = GNUNET_TIME_absolute_get ();
|
||||||
GNUNET_TIME_round_abs (&ksh->reload_time);
|
GNUNET_TIME_round_abs (&ksh->reload_time);
|
||||||
/* We must use the key_generation from when we STARTED the process! */
|
/* We must use the key_generation from when we STARTED the process! */
|
||||||
@ -1215,7 +1393,7 @@ get_date_string (struct GNUNET_TIME_Absolute at,
|
|||||||
* @return #GNUNET_OK on success
|
* @return #GNUNET_OK on success
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
setup_general_response_headers (const struct KeyStateHandle *ksh,
|
setup_general_response_headers (const struct TEH_KeyStateHandle *ksh,
|
||||||
struct MHD_Response *response)
|
struct MHD_Response *response)
|
||||||
{
|
{
|
||||||
char dat[128];
|
char dat[128];
|
||||||
@ -1262,9 +1440,10 @@ setup_general_response_headers (const struct KeyStateHandle *ksh,
|
|||||||
* @param signkeys list of sign keys to return
|
* @param signkeys list of sign keys to return
|
||||||
* @param recoup list of revoked keys to return
|
* @param recoup list of revoked keys to return
|
||||||
* @param denoms list of denominations to return
|
* @param denoms list of denominations to return
|
||||||
|
* @return #GNUNET_OK on success
|
||||||
*/
|
*/
|
||||||
static void
|
static int
|
||||||
create_krd (struct KeyStateHandle *ksh,
|
create_krd (struct TEH_KeyStateHandle *ksh,
|
||||||
const struct GNUNET_HashCode *denom_keys_hash,
|
const struct GNUNET_HashCode *denom_keys_hash,
|
||||||
struct GNUNET_TIME_Absolute last_cpd,
|
struct GNUNET_TIME_Absolute last_cpd,
|
||||||
json_t *signkeys,
|
json_t *signkeys,
|
||||||
@ -1284,15 +1463,23 @@ create_krd (struct KeyStateHandle *ksh,
|
|||||||
.list_issue_date = GNUNET_TIME_absolute_hton (last_cpd),
|
.list_issue_date = GNUNET_TIME_absolute_hton (last_cpd),
|
||||||
.hc = *denom_keys_hash
|
.hc = *denom_keys_hash
|
||||||
};
|
};
|
||||||
|
enum TALER_ErrorCode ec;
|
||||||
|
|
||||||
TEH_keys_exchange_sign (&ks,
|
if (TALER_EC_NONE !=
|
||||||
|
(ec = TEH_keys_exchange_sign (&ks,
|
||||||
&exchange_pub,
|
&exchange_pub,
|
||||||
&exchange_sig);
|
&exchange_sig)))
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||||
|
"Could not create key response data: cannot sign (%s)\n",
|
||||||
|
TALER_ErrorCode_get_hint (ec));
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
keys = json_pack (
|
keys = json_pack (
|
||||||
"{s:s, s:o, s:o, s:O, s:O,"
|
"{s:s, s:o, s:o, s:O, s:O,"
|
||||||
" s:O, s:o, s:o, s:o, s:o}",
|
" s:O, s:O, s:o, s:o, s:o}",
|
||||||
/* 1-5 */
|
/* 1-5 */
|
||||||
"version", EXCHANGE_PROTOCOL_VERSION,
|
"version", EXCHANGE_PROTOCOL_VERSION,
|
||||||
"master_public_key", GNUNET_JSON_from_data_auto (&TEH_master_public_key),
|
"master_public_key", GNUNET_JSON_from_data_auto (&TEH_master_public_key),
|
||||||
@ -1352,9 +1539,11 @@ create_krd (struct KeyStateHandle *ksh,
|
|||||||
setup_general_response_headers (ksh,
|
setup_general_response_headers (ksh,
|
||||||
krd.response_compressed));
|
krd.response_compressed));
|
||||||
}
|
}
|
||||||
|
krd.cherry_pick_date = last_cpd;
|
||||||
GNUNET_array_append (ksh->krd_array,
|
GNUNET_array_append (ksh->krd_array,
|
||||||
ksh->krd_array_length,
|
ksh->krd_array_length,
|
||||||
krd);
|
krd);
|
||||||
|
return GNUNET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1364,11 +1553,11 @@ create_krd (struct KeyStateHandle *ksh,
|
|||||||
* This function is to recompute all (including cherry-picked) responses we
|
* This function is to recompute all (including cherry-picked) responses we
|
||||||
* might want to return, based on the state already in @a ksh.
|
* might want to return, based on the state already in @a ksh.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* @param[in,out] ksh state handle to update
|
* @param[in,out] ksh state handle to update
|
||||||
|
* @return #GNUNET_OK on success
|
||||||
*/
|
*/
|
||||||
static void
|
static int
|
||||||
update_keys_response (struct KeyStateHandle *ksh)
|
update_keys_response (struct TEH_KeyStateHandle *ksh)
|
||||||
{
|
{
|
||||||
json_t *recoup;
|
json_t *recoup;
|
||||||
struct SignKeyCtx sctx;
|
struct SignKeyCtx sctx;
|
||||||
@ -1417,12 +1606,24 @@ update_keys_response (struct KeyStateHandle *ksh)
|
|||||||
GNUNET_CRYPTO_hash_context_finish (
|
GNUNET_CRYPTO_hash_context_finish (
|
||||||
GNUNET_CRYPTO_hash_context_copy (hash_context),
|
GNUNET_CRYPTO_hash_context_copy (hash_context),
|
||||||
&hc);
|
&hc);
|
||||||
|
if (GNUNET_OK !=
|
||||||
create_krd (ksh,
|
create_krd (ksh,
|
||||||
&hc,
|
&hc,
|
||||||
last_cpd,
|
last_cpd,
|
||||||
sctx.signkeys,
|
sctx.signkeys,
|
||||||
recoup,
|
recoup,
|
||||||
denoms);
|
denoms))
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||||
|
"Failed to generate key response data for %s\n",
|
||||||
|
GNUNET_STRINGS_absolute_time_to_string (last_cpd));
|
||||||
|
GNUNET_CRYPTO_hash_context_abort (hash_context);
|
||||||
|
GNUNET_CONTAINER_heap_destroy (heap);
|
||||||
|
json_decref (denoms);
|
||||||
|
json_decref (sctx.signkeys);
|
||||||
|
json_decref (recoup);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
last_cpd = dk->meta.start;
|
last_cpd = dk->meta.start;
|
||||||
}
|
}
|
||||||
GNUNET_CRYPTO_hash_context_read (hash_context,
|
GNUNET_CRYPTO_hash_context_read (hash_context,
|
||||||
@ -1468,16 +1669,28 @@ update_keys_response (struct KeyStateHandle *ksh)
|
|||||||
|
|
||||||
GNUNET_CRYPTO_hash_context_finish (hash_context,
|
GNUNET_CRYPTO_hash_context_finish (hash_context,
|
||||||
&hc);
|
&hc);
|
||||||
|
if (GNUNET_OK !=
|
||||||
create_krd (ksh,
|
create_krd (ksh,
|
||||||
&hc,
|
&hc,
|
||||||
last_cpd,
|
last_cpd,
|
||||||
sctx.signkeys,
|
sctx.signkeys,
|
||||||
recoup,
|
recoup,
|
||||||
denoms);
|
denoms))
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||||
|
"Failed to generate key response data for %s\n",
|
||||||
|
GNUNET_STRINGS_absolute_time_to_string (last_cpd));
|
||||||
|
json_decref (denoms);
|
||||||
|
json_decref (sctx.signkeys);
|
||||||
|
json_decref (recoup);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
json_decref (sctx.signkeys);
|
json_decref (sctx.signkeys);
|
||||||
json_decref (recoup);
|
json_decref (recoup);
|
||||||
json_decref (denoms);
|
json_decref (denoms);
|
||||||
|
return GNUNET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1486,21 +1699,17 @@ TEH_keys_update_states ()
|
|||||||
{
|
{
|
||||||
__sync_fetch_and_add (&key_generation,
|
__sync_fetch_and_add (&key_generation,
|
||||||
1);
|
1);
|
||||||
|
TEH_resume_keys_requests ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
struct TEH_KeyStateHandle *
|
||||||
* Return the current key state for this thread. Possibly re-builds the key
|
TEH_get_key_state (void)
|
||||||
* state if we have reason to believe that something changed.
|
|
||||||
*
|
|
||||||
* @return NULL on error
|
|
||||||
*/
|
|
||||||
static struct KeyStateHandle *
|
|
||||||
get_key_state (void)
|
|
||||||
{
|
{
|
||||||
struct KeyStateHandle *old_ksh;
|
struct TEH_KeyStateHandle *old_ksh;
|
||||||
struct KeyStateHandle *ksh;
|
struct TEH_KeyStateHandle *ksh;
|
||||||
|
|
||||||
|
GNUNET_assert (key_state_available);
|
||||||
old_ksh = pthread_getspecific (key_state);
|
old_ksh = pthread_getspecific (key_state);
|
||||||
if (NULL == old_ksh)
|
if (NULL == old_ksh)
|
||||||
{
|
{
|
||||||
@ -1540,21 +1749,34 @@ get_key_state (void)
|
|||||||
|
|
||||||
|
|
||||||
struct TEH_DenominationKey *
|
struct TEH_DenominationKey *
|
||||||
TEH_keys_denomination_by_hash (
|
TEH_keys_denomination_by_hash (const struct GNUNET_HashCode *h_denom_pub,
|
||||||
const struct GNUNET_HashCode *h_denom_pub,
|
|
||||||
enum TALER_ErrorCode *ec,
|
enum TALER_ErrorCode *ec,
|
||||||
unsigned int *hc)
|
unsigned int *hc)
|
||||||
{
|
{
|
||||||
struct KeyStateHandle *ksh;
|
struct TEH_KeyStateHandle *ksh;
|
||||||
struct TEH_DenominationKey *dk;
|
|
||||||
|
|
||||||
ksh = get_key_state ();
|
ksh = TEH_get_key_state ();
|
||||||
if (NULL == ksh)
|
if (NULL == ksh)
|
||||||
{
|
{
|
||||||
*hc = MHD_HTTP_INTERNAL_SERVER_ERROR;
|
*hc = MHD_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
*ec = TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING;
|
*ec = TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
return TEH_keys_denomination_by_hash2 (ksh,
|
||||||
|
h_denom_pub,
|
||||||
|
ec,
|
||||||
|
hc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct TEH_DenominationKey *
|
||||||
|
TEH_keys_denomination_by_hash2 (struct TEH_KeyStateHandle *ksh,
|
||||||
|
const struct GNUNET_HashCode *h_denom_pub,
|
||||||
|
enum TALER_ErrorCode *ec,
|
||||||
|
unsigned int *hc)
|
||||||
|
{
|
||||||
|
struct TEH_DenominationKey *dk;
|
||||||
|
|
||||||
dk = GNUNET_CONTAINER_multihashmap_get (ksh->denomkey_map,
|
dk = GNUNET_CONTAINER_multihashmap_get (ksh->denomkey_map,
|
||||||
h_denom_pub);
|
h_denom_pub);
|
||||||
if (NULL == dk)
|
if (NULL == dk)
|
||||||
@ -1568,16 +1790,15 @@ TEH_keys_denomination_by_hash (
|
|||||||
|
|
||||||
|
|
||||||
struct TALER_DenominationSignature
|
struct TALER_DenominationSignature
|
||||||
TEH_keys_denomination_sign (
|
TEH_keys_denomination_sign (const struct GNUNET_HashCode *h_denom_pub,
|
||||||
const struct GNUNET_HashCode *h_denom_pub,
|
|
||||||
const void *msg,
|
const void *msg,
|
||||||
size_t msg_size,
|
size_t msg_size,
|
||||||
enum TALER_ErrorCode *ec)
|
enum TALER_ErrorCode *ec)
|
||||||
{
|
{
|
||||||
struct KeyStateHandle *ksh;
|
struct TEH_KeyStateHandle *ksh;
|
||||||
struct TALER_DenominationSignature none = { NULL };
|
struct TALER_DenominationSignature none = { NULL };
|
||||||
|
|
||||||
ksh = get_key_state ();
|
ksh = TEH_get_key_state ();
|
||||||
if (NULL == ksh)
|
if (NULL == ksh)
|
||||||
{
|
{
|
||||||
*ec = TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING;
|
*ec = TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING;
|
||||||
@ -1592,12 +1813,11 @@ TEH_keys_denomination_sign (
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TEH_keys_denomination_revoke (
|
TEH_keys_denomination_revoke (const struct GNUNET_HashCode *h_denom_pub)
|
||||||
const struct GNUNET_HashCode *h_denom_pub)
|
|
||||||
{
|
{
|
||||||
struct KeyStateHandle *ksh;
|
struct TEH_KeyStateHandle *ksh;
|
||||||
|
|
||||||
ksh = get_key_state ();
|
ksh = TEH_get_key_state ();
|
||||||
if (NULL == ksh)
|
if (NULL == ksh)
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
@ -1615,10 +1835,10 @@ TEH_keys_exchange_sign_ (const struct
|
|||||||
struct TALER_ExchangePublicKeyP *pub,
|
struct TALER_ExchangePublicKeyP *pub,
|
||||||
struct TALER_ExchangeSignatureP *sig)
|
struct TALER_ExchangeSignatureP *sig)
|
||||||
{
|
{
|
||||||
struct KeyStateHandle *ksh;
|
struct TEH_KeyStateHandle *ksh;
|
||||||
enum TALER_ErrorCode ec;
|
enum TALER_ErrorCode ec;
|
||||||
|
|
||||||
ksh = get_key_state ();
|
ksh = TEH_get_key_state ();
|
||||||
if (NULL == ksh)
|
if (NULL == ksh)
|
||||||
{
|
{
|
||||||
/* This *can* happen if the exchange's crypto helper is not running
|
/* This *can* happen if the exchange's crypto helper is not running
|
||||||
@ -1646,9 +1866,10 @@ TEH_keys_exchange_sign_ (const struct
|
|||||||
&pid);
|
&pid);
|
||||||
if (NULL == sk)
|
if (NULL == sk)
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
|
||||||
/* just to be safe, zero out the (valid) signature, as the key
|
/* just to be safe, zero out the (valid) signature, as the key
|
||||||
should no longer be used */
|
should not or no longer be used */
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||||
|
"Cannot sign, offline key signatures are missing!\n");
|
||||||
memset (sig,
|
memset (sig,
|
||||||
0,
|
0,
|
||||||
sizeof (*sig));
|
sizeof (*sig));
|
||||||
@ -1662,9 +1883,9 @@ TEH_keys_exchange_sign_ (const struct
|
|||||||
void
|
void
|
||||||
TEH_keys_exchange_revoke (const struct TALER_ExchangePublicKeyP *exchange_pub)
|
TEH_keys_exchange_revoke (const struct TALER_ExchangePublicKeyP *exchange_pub)
|
||||||
{
|
{
|
||||||
struct KeyStateHandle *ksh;
|
struct TEH_KeyStateHandle *ksh;
|
||||||
|
|
||||||
ksh = get_key_state ();
|
ksh = TEH_get_key_state ();
|
||||||
if (NULL == ksh)
|
if (NULL == ksh)
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
@ -1742,19 +1963,19 @@ TEH_keys_get_handler (const struct TEH_RequestHandler *rh,
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
struct KeyStateHandle *ksh;
|
struct TEH_KeyStateHandle *ksh;
|
||||||
const struct KeysResponseData *krd;
|
const struct KeysResponseData *krd;
|
||||||
|
|
||||||
ksh = get_key_state ();
|
ksh = TEH_get_key_state ();
|
||||||
if (NULL == ksh)
|
if (NULL == ksh)
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
return suspend_request (connection);
|
||||||
return TALER_MHD_reply_with_error (connection,
|
}
|
||||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
if (GNUNET_OK !=
|
||||||
TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
|
update_keys_response (ksh))
|
||||||
"no key state");
|
{
|
||||||
|
return suspend_request (connection);
|
||||||
}
|
}
|
||||||
update_keys_response (ksh);
|
|
||||||
krd = bsearch (&last_issue_date,
|
krd = bsearch (&last_issue_date,
|
||||||
ksh->krd_array,
|
ksh->krd_array,
|
||||||
ksh->krd_array_length,
|
ksh->krd_array_length,
|
||||||
@ -1927,11 +2148,11 @@ TEH_keys_load_fees (const struct GNUNET_HashCode *h_denom_pub,
|
|||||||
struct TALER_DenominationPublicKey *denom_pub,
|
struct TALER_DenominationPublicKey *denom_pub,
|
||||||
struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta)
|
struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta)
|
||||||
{
|
{
|
||||||
struct KeyStateHandle *ksh;
|
struct TEH_KeyStateHandle *ksh;
|
||||||
struct HelperDenomination *hd;
|
struct HelperDenomination *hd;
|
||||||
int ok;
|
int ok;
|
||||||
|
|
||||||
ksh = get_key_state ();
|
ksh = TEH_get_key_state ();
|
||||||
if (NULL == ksh)
|
if (NULL == ksh)
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
@ -1959,11 +2180,11 @@ int
|
|||||||
TEH_keys_get_timing (const struct TALER_ExchangePublicKeyP *exchange_pub,
|
TEH_keys_get_timing (const struct TALER_ExchangePublicKeyP *exchange_pub,
|
||||||
struct TALER_EXCHANGEDB_SignkeyMetaData *meta)
|
struct TALER_EXCHANGEDB_SignkeyMetaData *meta)
|
||||||
{
|
{
|
||||||
struct KeyStateHandle *ksh;
|
struct TEH_KeyStateHandle *ksh;
|
||||||
struct HelperSignkey *hsk;
|
struct HelperSignkey *hsk;
|
||||||
struct GNUNET_PeerIdentity pid;
|
struct GNUNET_PeerIdentity pid;
|
||||||
|
|
||||||
ksh = get_key_state ();
|
ksh = TEH_get_key_state ();
|
||||||
if (NULL == ksh)
|
if (NULL == ksh)
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
@ -1990,7 +2211,7 @@ struct FutureBuilderContext
|
|||||||
/**
|
/**
|
||||||
* Our key state.
|
* Our key state.
|
||||||
*/
|
*/
|
||||||
struct KeyStateHandle *ksh;
|
struct TEH_KeyStateHandle *ksh;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array of denomination keys.
|
* Array of denomination keys.
|
||||||
@ -2044,7 +2265,10 @@ add_future_denomkey_cb (void *cls,
|
|||||||
0 ==
|
0 ==
|
||||||
json_array_append_new (
|
json_array_append_new (
|
||||||
fbc->denoms,
|
fbc->denoms,
|
||||||
json_pack ("{s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o}",
|
json_pack ("{s:o, s:o, s:o, s:o, s:o,"
|
||||||
|
" s:o, s:o, s:o, s:o, s:o,"
|
||||||
|
" s:o, s:s}",
|
||||||
|
/* 1-5 */
|
||||||
"value",
|
"value",
|
||||||
TALER_JSON_from_amount (&meta.value),
|
TALER_JSON_from_amount (&meta.value),
|
||||||
"stamp_start",
|
"stamp_start",
|
||||||
@ -2055,8 +2279,9 @@ add_future_denomkey_cb (void *cls,
|
|||||||
GNUNET_JSON_from_time_abs (meta.expire_deposit),
|
GNUNET_JSON_from_time_abs (meta.expire_deposit),
|
||||||
"stamp_expire_legal",
|
"stamp_expire_legal",
|
||||||
GNUNET_JSON_from_time_abs (meta.expire_legal),
|
GNUNET_JSON_from_time_abs (meta.expire_legal),
|
||||||
|
/* 6-10 */
|
||||||
"denom_pub",
|
"denom_pub",
|
||||||
GNUNET_JSON_from_rsa_public_key (dk->denom_pub.rsa_public_key),
|
GNUNET_JSON_from_rsa_public_key (hd->denom_pub.rsa_public_key),
|
||||||
"fee_withdraw",
|
"fee_withdraw",
|
||||||
TALER_JSON_from_amount (&meta.fee_withdraw),
|
TALER_JSON_from_amount (&meta.fee_withdraw),
|
||||||
"fee_deposit",
|
"fee_deposit",
|
||||||
@ -2065,8 +2290,11 @@ add_future_denomkey_cb (void *cls,
|
|||||||
TALER_JSON_from_amount (&meta.fee_refresh),
|
TALER_JSON_from_amount (&meta.fee_refresh),
|
||||||
"fee_refund",
|
"fee_refund",
|
||||||
TALER_JSON_from_amount (&meta.fee_refund),
|
TALER_JSON_from_amount (&meta.fee_refund),
|
||||||
|
/* 11- */
|
||||||
"denom_secmod_sig",
|
"denom_secmod_sig",
|
||||||
GNUNET_JSON_from_data_auto (&hd->sm_sig))));
|
GNUNET_JSON_from_data_auto (&hd->sm_sig),
|
||||||
|
"section_name",
|
||||||
|
hd->section_name)));
|
||||||
return GNUNET_OK;
|
return GNUNET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2123,10 +2351,10 @@ MHD_RESULT
|
|||||||
TEH_keys_management_get_handler (const struct TEH_RequestHandler *rh,
|
TEH_keys_management_get_handler (const struct TEH_RequestHandler *rh,
|
||||||
struct MHD_Connection *connection)
|
struct MHD_Connection *connection)
|
||||||
{
|
{
|
||||||
struct KeyStateHandle *ksh;
|
struct TEH_KeyStateHandle *ksh;
|
||||||
json_t *reply;
|
json_t *reply;
|
||||||
|
|
||||||
ksh = get_key_state ();
|
ksh = TEH_get_key_state ();
|
||||||
if (NULL == ksh)
|
if (NULL == ksh)
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
@ -2143,6 +2371,8 @@ TEH_keys_management_get_handler (const struct TEH_RequestHandler *rh,
|
|||||||
.signkeys = json_array ()
|
.signkeys = json_array ()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
GNUNET_assert (NULL != fbc.denoms);
|
||||||
|
GNUNET_assert (NULL != fbc.signkeys);
|
||||||
GNUNET_CONTAINER_multihashmap_iterate (ksh->helpers.denom_keys,
|
GNUNET_CONTAINER_multihashmap_iterate (ksh->helpers.denom_keys,
|
||||||
&add_future_denomkey_cb,
|
&add_future_denomkey_cb,
|
||||||
&fbc);
|
&fbc);
|
||||||
@ -2161,6 +2391,11 @@ TEH_keys_management_get_handler (const struct TEH_RequestHandler *rh,
|
|||||||
GNUNET_JSON_from_data_auto (&denom_sm_pub),
|
GNUNET_JSON_from_data_auto (&denom_sm_pub),
|
||||||
"signkey_secmod_public_key",
|
"signkey_secmod_public_key",
|
||||||
GNUNET_JSON_from_data_auto (&esign_sm_pub));
|
GNUNET_JSON_from_data_auto (&esign_sm_pub));
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Returning GET /management/keys response:\n");
|
||||||
|
json_dumpf (reply,
|
||||||
|
stderr,
|
||||||
|
JSON_INDENT (2));
|
||||||
if (NULL == reply)
|
if (NULL == reply)
|
||||||
return TALER_MHD_reply_with_error (connection,
|
return TALER_MHD_reply_with_error (connection,
|
||||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||||
|
@ -83,6 +83,33 @@ struct TEH_DenominationKey
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Snapshot of the (coin and signing) keys (including private keys) of
|
||||||
|
* the exchange. There can be multiple instances of this struct, as it is
|
||||||
|
* reference counted and only destroyed once the last user is done
|
||||||
|
* with it. The current instance is acquired using
|
||||||
|
* #TEH_KS_acquire(). Using this function increases the
|
||||||
|
* reference count. The contents of this structure (except for the
|
||||||
|
* reference counter) should be considered READ-ONLY until it is
|
||||||
|
* ultimately destroyed (as there can be many concurrent users).
|
||||||
|
*/
|
||||||
|
struct TEH_KeyStateHandle;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the current key state for this thread. Possibly re-builds the key
|
||||||
|
* state if we have reason to believe that something changed.
|
||||||
|
*
|
||||||
|
* The result is ONLY valid until the next call to
|
||||||
|
* #TEH_keys_denomination_by_hash() or #TEH_get_key_state()
|
||||||
|
* or #TEH_keys_exchange_sign().
|
||||||
|
*
|
||||||
|
* @return NULL on error
|
||||||
|
*/
|
||||||
|
struct TEH_KeyStateHandle *
|
||||||
|
TEH_get_key_state (void);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Something changed in the database. Rebuild all key states. This function
|
* Something changed in the database. Rebuild all key states. This function
|
||||||
* should be called if the exchange learns about a new signature from an
|
* should be called if the exchange learns about a new signature from an
|
||||||
@ -109,12 +136,30 @@ TEH_keys_update_states (void);
|
|||||||
* or NULL if @a h_denom_pub could not be found
|
* or NULL if @a h_denom_pub could not be found
|
||||||
*/
|
*/
|
||||||
struct TEH_DenominationKey *
|
struct TEH_DenominationKey *
|
||||||
TEH_keys_denomination_by_hash (
|
TEH_keys_denomination_by_hash (const struct GNUNET_HashCode *h_denom_pub,
|
||||||
const struct GNUNET_HashCode *h_denom_pub,
|
|
||||||
enum TALER_ErrorCode *ec,
|
enum TALER_ErrorCode *ec,
|
||||||
unsigned int *hc);
|
unsigned int *hc);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up the issue for a denom public key using a given @a ksh. This allows
|
||||||
|
* requesting multiple denominations with the same @a ksh which thus will
|
||||||
|
* remain valid until the next call to #TEH_keys_denomination_by_hash() or
|
||||||
|
* #TEH_get_key_state() or #TEH_keys_exchange_sign().
|
||||||
|
*
|
||||||
|
* @param key_state state to look in
|
||||||
|
* @param h_denom_pub hash of denomination public key
|
||||||
|
* @param[out] ec set to the error code, in case the operation failed
|
||||||
|
* @param[out] hc set to the HTTP status code to use
|
||||||
|
* @return the denomination key issue,
|
||||||
|
* or NULL if @a h_denom_pub could not be found
|
||||||
|
*/
|
||||||
|
struct TEH_DenominationKey *
|
||||||
|
TEH_keys_denomination_by_hash2 (struct TEH_KeyStateHandle *ksh,
|
||||||
|
const struct GNUNET_HashCode *h_denom_pub,
|
||||||
|
enum TALER_ErrorCode *ec,
|
||||||
|
unsigned int *hc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request to sign @a msg using the public key corresponding to
|
* Request to sign @a msg using the public key corresponding to
|
||||||
* @a h_denom_pub.
|
* @a h_denom_pub.
|
||||||
@ -127,8 +172,7 @@ TEH_keys_denomination_by_hash (
|
|||||||
* see @a ec for details about the failure
|
* see @a ec for details about the failure
|
||||||
*/
|
*/
|
||||||
struct TALER_DenominationSignature
|
struct TALER_DenominationSignature
|
||||||
TEH_keys_denomination_sign (
|
TEH_keys_denomination_sign (const struct GNUNET_HashCode *h_denom_pub,
|
||||||
const struct GNUNET_HashCode *h_denom_pub,
|
|
||||||
const void *msg,
|
const void *msg,
|
||||||
size_t msg_size,
|
size_t msg_size,
|
||||||
enum TALER_ErrorCode *ec);
|
enum TALER_ErrorCode *ec);
|
||||||
@ -146,8 +190,17 @@ TEH_keys_denomination_sign (
|
|||||||
* @param h_denom_pub hash of the public key to revoke
|
* @param h_denom_pub hash of the public key to revoke
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
TEH_keys_denomination_revoke (
|
TEH_keys_denomination_revoke (const struct GNUNET_HashCode *h_denom_pub);
|
||||||
const struct GNUNET_HashCode *h_denom_pub);
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resumse all suspended /keys requests, we may now have key material
|
||||||
|
* (or are shuting down).
|
||||||
|
*
|
||||||
|
* @param[in] connection to suspend
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
TEH_resume_keys_requests (void);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2054,7 +2054,7 @@ TEH_KS_denomination_key_lookup_by_hash (
|
|||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
"Not returning DKI for %s, as time to create coins has passed\n",
|
"Not returning DKI for %s, as time to create coins has passed\n",
|
||||||
GNUNET_h2s (denom_pub_hash));
|
GNUNET_h2s (denom_pub_hash));
|
||||||
*ec = TALER_EC_EXCHANGE_WITHDRAW_VALIDITY_IN_PAST;
|
*ec = TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED;
|
||||||
*hc = MHD_HTTP_GONE;
|
*hc = MHD_HTTP_GONE;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,8 @@ add_auditor (void *cls,
|
|||||||
"lookup auditor");
|
"lookup auditor");
|
||||||
return qs;
|
return qs;
|
||||||
}
|
}
|
||||||
if (last_date.abs_value_us > aac->validity_start.abs_value_us)
|
if ( (0 < qs) &&
|
||||||
|
(last_date.abs_value_us > aac->validity_start.abs_value_us) )
|
||||||
{
|
{
|
||||||
*mhd_ret = TALER_MHD_reply_with_error (
|
*mhd_ret = TALER_MHD_reply_with_error (
|
||||||
connection,
|
connection,
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "taler-exchange-httpd_management.h"
|
#include "taler-exchange-httpd_management.h"
|
||||||
#include "taler-exchange-httpd_responses.h"
|
#include "taler-exchange-httpd_responses.h"
|
||||||
#include "taler-exchange-httpd_keystate.h"
|
#include "taler-exchange-httpd_keystate.h"
|
||||||
|
#include "taler-exchange-httpd_keys.h"
|
||||||
|
|
||||||
|
|
||||||
MHD_RESULT
|
MHD_RESULT
|
||||||
@ -81,7 +82,7 @@ TEH_handler_management_denominations_HDP_revoke (
|
|||||||
TALER_EC_GENERIC_DB_STORE_FAILED,
|
TALER_EC_GENERIC_DB_STORE_FAILED,
|
||||||
"denomination revocation");
|
"denomination revocation");
|
||||||
}
|
}
|
||||||
// FIXME: also update our '/keys' replies! (signal all threads!?!?)
|
TEH_keys_update_states ();
|
||||||
return TALER_MHD_reply_static (
|
return TALER_MHD_reply_static (
|
||||||
connection,
|
connection,
|
||||||
MHD_HTTP_NO_CONTENT,
|
MHD_HTTP_NO_CONTENT,
|
||||||
|
@ -212,6 +212,9 @@ add_keys (void *cls,
|
|||||||
"activate denomination key");
|
"activate denomination key");
|
||||||
return qs;
|
return qs;
|
||||||
}
|
}
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Added offline signature for denomination `%s'\n",
|
||||||
|
GNUNET_h2s (&akc->d_sigs[i].h_denom_pub));
|
||||||
GNUNET_assert (0 != qs);
|
GNUNET_assert (0 != qs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,9 +299,11 @@ add_keys (void *cls,
|
|||||||
"activate signing key");
|
"activate signing key");
|
||||||
return qs;
|
return qs;
|
||||||
}
|
}
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Added offline signature for signing key `%s'\n",
|
||||||
|
TALER_B2S (&akc->s_sigs[i].exchange_pub));
|
||||||
GNUNET_assert (0 != qs);
|
GNUNET_assert (0 != qs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; /* only 'success', so >=0, matters here */
|
return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; /* only 'success', so >=0, matters here */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -382,9 +387,9 @@ TEH_handler_management_post_keys (
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
akc.ns_sigs = json_array_size (signkey_sigs);
|
akc.ns_sigs = json_array_size (signkey_sigs);
|
||||||
akc.s_sigs = GNUNET_new_array (akc.nd_sigs,
|
akc.s_sigs = GNUNET_new_array (akc.ns_sigs,
|
||||||
struct SigningSig);
|
struct SigningSig);
|
||||||
for (unsigned int i = 0; i<akc.nd_sigs; i++)
|
for (unsigned int i = 0; i<akc.ns_sigs; i++)
|
||||||
{
|
{
|
||||||
struct SigningSig *s = &akc.s_sigs[i];
|
struct SigningSig *s = &akc.s_sigs[i];
|
||||||
struct GNUNET_JSON_Specification ispec[] = {
|
struct GNUNET_JSON_Specification ispec[] = {
|
||||||
@ -419,6 +424,10 @@ TEH_handler_management_post_keys (
|
|||||||
GNUNET_free (akc.s_sigs);
|
GNUNET_free (akc.s_sigs);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Received %u denomination and %u signing key signatures\n",
|
||||||
|
akc.nd_sigs,
|
||||||
|
akc.ns_sigs);
|
||||||
qs = TEH_DB_run_transaction (connection,
|
qs = TEH_DB_run_transaction (connection,
|
||||||
"add keys",
|
"add keys",
|
||||||
&ret,
|
&ret,
|
||||||
@ -426,6 +435,7 @@ TEH_handler_management_post_keys (
|
|||||||
&akc);
|
&akc);
|
||||||
if (qs < 0)
|
if (qs < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
TEH_keys_update_states ();
|
||||||
return TALER_MHD_reply_static (
|
return TALER_MHD_reply_static (
|
||||||
connection,
|
connection,
|
||||||
MHD_HTTP_NO_CONTENT,
|
MHD_HTTP_NO_CONTENT,
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "taler-exchange-httpd_management.h"
|
#include "taler-exchange-httpd_management.h"
|
||||||
#include "taler-exchange-httpd_responses.h"
|
#include "taler-exchange-httpd_responses.h"
|
||||||
#include "taler-exchange-httpd_keystate.h"
|
#include "taler-exchange-httpd_keystate.h"
|
||||||
|
#include "taler-exchange-httpd_keys.h"
|
||||||
|
|
||||||
|
|
||||||
MHD_RESULT
|
MHD_RESULT
|
||||||
@ -80,7 +81,7 @@ TEH_handler_management_signkeys_EP_revoke (
|
|||||||
TALER_EC_GENERIC_DB_STORE_FAILED,
|
TALER_EC_GENERIC_DB_STORE_FAILED,
|
||||||
"signkey revocation");
|
"signkey revocation");
|
||||||
}
|
}
|
||||||
// FIXME: also update our '/keys' replies! (signal all threads!?!?)
|
TEH_keys_update_states ();
|
||||||
return TALER_MHD_reply_static (
|
return TALER_MHD_reply_static (
|
||||||
connection,
|
connection,
|
||||||
MHD_HTTP_NO_CONTENT,
|
MHD_HTTP_NO_CONTENT,
|
||||||
|
@ -101,7 +101,8 @@ add_wire (void *cls,
|
|||||||
"lookup wire");
|
"lookup wire");
|
||||||
return qs;
|
return qs;
|
||||||
}
|
}
|
||||||
if (last_date.abs_value_us > awc->validity_start.abs_value_us)
|
if ( (0 < qs) &&
|
||||||
|
(last_date.abs_value_us > awc->validity_start.abs_value_us) )
|
||||||
{
|
{
|
||||||
*mhd_ret = TALER_MHD_reply_with_error (
|
*mhd_ret = TALER_MHD_reply_with_error (
|
||||||
connection,
|
connection,
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "taler-exchange-httpd_melt.h"
|
#include "taler-exchange-httpd_melt.h"
|
||||||
#include "taler-exchange-httpd_responses.h"
|
#include "taler-exchange-httpd_responses.h"
|
||||||
#include "taler-exchange-httpd_keystate.h"
|
#include "taler-exchange-httpd_keystate.h"
|
||||||
|
#include "taler-exchange-httpd_keys.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -107,16 +108,16 @@ reply_melt_success (struct MHD_Connection *connection,
|
|||||||
.rc = *rc,
|
.rc = *rc,
|
||||||
.noreveal_index = htonl (noreveal_index)
|
.noreveal_index = htonl (noreveal_index)
|
||||||
};
|
};
|
||||||
|
enum TALER_ErrorCode ec;
|
||||||
|
|
||||||
if (GNUNET_OK !=
|
if (TALER_EC_NONE !=
|
||||||
TEH_KS_sign (&body,
|
(ec = TEH_keys_exchange_sign (&body,
|
||||||
&pub,
|
&pub,
|
||||||
&sig))
|
&sig)))
|
||||||
{
|
{
|
||||||
return TALER_MHD_reply_with_error (connection,
|
return TALER_MHD_reply_with_ec (connection,
|
||||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
ec,
|
||||||
TALER_EC_EXCHANGE_GENERIC_BAD_CONFIGURATION,
|
NULL);
|
||||||
"no keys");
|
|
||||||
}
|
}
|
||||||
return TALER_MHD_reply_json_pack (
|
return TALER_MHD_reply_json_pack (
|
||||||
connection,
|
connection,
|
||||||
@ -477,28 +478,48 @@ check_for_denomination_key (struct MHD_Connection *connection,
|
|||||||
{
|
{
|
||||||
/* Baseline: check if deposits/refreshs are generally
|
/* Baseline: check if deposits/refreshs are generally
|
||||||
simply still allowed for this denomination */
|
simply still allowed for this denomination */
|
||||||
struct TALER_EXCHANGEDB_DenominationKey *dki;
|
struct TEH_DenominationKey *dk;
|
||||||
unsigned int hc;
|
unsigned int hc;
|
||||||
enum TALER_ErrorCode ec;
|
enum TALER_ErrorCode ec;
|
||||||
|
struct GNUNET_TIME_Absolute now;
|
||||||
|
|
||||||
dki = TEH_KS_denomination_key_lookup_by_hash (
|
dk = TEH_keys_denomination_by_hash (
|
||||||
key_state,
|
|
||||||
&rmc->refresh_session.coin.denom_pub_hash,
|
&rmc->refresh_session.coin.denom_pub_hash,
|
||||||
TEH_KS_DKU_DEPOSIT,
|
|
||||||
&ec,
|
&ec,
|
||||||
&hc);
|
&hc);
|
||||||
/* Consider case that denomination was revoked but
|
if (NULL == dk)
|
||||||
this coin was already seen and thus refresh is OK. */
|
|
||||||
if (NULL == dki)
|
|
||||||
{
|
{
|
||||||
dki = TEH_KS_denomination_key_lookup_by_hash (
|
TEH_KS_release (key_state);
|
||||||
key_state,
|
return TALER_MHD_reply_with_error (
|
||||||
&rmc->refresh_session.coin.denom_pub_hash,
|
connection,
|
||||||
TEH_KS_DKU_RECOUP,
|
MHD_HTTP_NOT_FOUND,
|
||||||
&ec,
|
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN,
|
||||||
&hc);
|
NULL);
|
||||||
if (NULL != dki)
|
}
|
||||||
|
now = GNUNET_TIME_absolute_get ();
|
||||||
|
if (now.abs_value_us >= dk->meta.expire_legal.abs_value_us)
|
||||||
{
|
{
|
||||||
|
/* Way too late now, even zombies have expired */
|
||||||
|
TEH_KS_release (key_state);
|
||||||
|
return TALER_MHD_reply_with_error (
|
||||||
|
connection,
|
||||||
|
MHD_HTTP_GONE,
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
if (now.abs_value_us < dk->meta.start.abs_value_us)
|
||||||
|
{
|
||||||
|
/* This denomination is not yet valid */
|
||||||
|
TEH_KS_release (key_state);
|
||||||
|
return TALER_MHD_reply_with_error (
|
||||||
|
connection,
|
||||||
|
MHD_HTTP_PRECONDITION_FAILED,
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
if (now.abs_value_us >= dk->meta.expire_deposit.abs_value_us)
|
||||||
|
{
|
||||||
|
/* We are past deposit expiration time, but maybe this is a zombie? */
|
||||||
struct GNUNET_HashCode denom_hash;
|
struct GNUNET_HashCode denom_hash;
|
||||||
enum GNUNET_DB_QueryStatus qs;
|
enum GNUNET_DB_QueryStatus qs;
|
||||||
|
|
||||||
@ -527,7 +548,12 @@ check_for_denomination_key (struct MHD_Connection *connection,
|
|||||||
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
|
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
|
||||||
{
|
{
|
||||||
/* We never saw this coin before, so _this_ justification is not OK */
|
/* We never saw this coin before, so _this_ justification is not OK */
|
||||||
dki = NULL;
|
TEH_KS_release (key_state);
|
||||||
|
return TALER_MHD_reply_with_error (
|
||||||
|
connection,
|
||||||
|
MHD_HTTP_GONE,
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -535,36 +561,11 @@ check_for_denomination_key (struct MHD_Connection *connection,
|
|||||||
"ensure_coin_known" part of the transaction */
|
"ensure_coin_known" part of the transaction */
|
||||||
rmc->coin_is_dirty = true;
|
rmc->coin_is_dirty = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Consider the case that the denomination expired for deposits, but
|
|
||||||
recoup of a refreshed coin refilled the balance of the 'zombie' coin
|
|
||||||
and we should thus allow the refresh during the legal period. */
|
|
||||||
if (NULL == dki)
|
|
||||||
{
|
|
||||||
dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
|
|
||||||
&rmc->refresh_session.coin.
|
|
||||||
denom_pub_hash,
|
|
||||||
TEH_KS_DKU_ZOMBIE,
|
|
||||||
&ec,
|
|
||||||
&hc);
|
|
||||||
if (NULL != dki)
|
|
||||||
rmc->zombie_required = true; /* check later that zombie is satisfied */
|
rmc->zombie_required = true; /* check later that zombie is satisfied */
|
||||||
}
|
}
|
||||||
if (NULL == dki)
|
|
||||||
{
|
|
||||||
TEH_KS_release (key_state);
|
|
||||||
return TALER_MHD_reply_with_error (connection,
|
|
||||||
hc,
|
|
||||||
ec,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
TALER_amount_ntoh (&rmc->coin_refresh_fee,
|
rmc->coin_refresh_fee = dk->meta.fee_refresh;
|
||||||
&dki->issue.properties.fee_refresh);
|
rmc->coin_value = dk->meta.value;
|
||||||
TALER_amount_ntoh (&rmc->coin_value,
|
|
||||||
&dki->issue.properties.value);
|
|
||||||
/* check client used sane currency */
|
/* check client used sane currency */
|
||||||
if (GNUNET_YES !=
|
if (GNUNET_YES !=
|
||||||
TALER_amount_cmp_currency (&rmc->refresh_session.amount_with_fee,
|
TALER_amount_cmp_currency (&rmc->refresh_session.amount_with_fee,
|
||||||
@ -581,7 +582,7 @@ check_for_denomination_key (struct MHD_Connection *connection,
|
|||||||
/* check coin is actually properly signed */
|
/* check coin is actually properly signed */
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
TALER_test_coin_valid (&rmc->refresh_session.coin,
|
TALER_test_coin_valid (&rmc->refresh_session.coin,
|
||||||
&dki->denom_pub))
|
&dk->denom_pub))
|
||||||
{
|
{
|
||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
TEH_KS_release (key_state);
|
TEH_KS_release (key_state);
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "taler-exchange-httpd_recoup.h"
|
#include "taler-exchange-httpd_recoup.h"
|
||||||
#include "taler-exchange-httpd_responses.h"
|
#include "taler-exchange-httpd_responses.h"
|
||||||
#include "taler-exchange-httpd_keystate.h"
|
#include "taler-exchange-httpd_keystate.h"
|
||||||
|
#include "taler-exchange-httpd_keys.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -359,7 +360,7 @@ verify_and_execute_recoup (struct MHD_Connection *connection,
|
|||||||
int refreshed)
|
int refreshed)
|
||||||
{
|
{
|
||||||
struct RecoupContext pc;
|
struct RecoupContext pc;
|
||||||
const struct TALER_EXCHANGEDB_DenominationKey *dki;
|
const struct TEH_DenominationKey *dk;
|
||||||
struct GNUNET_HashCode c_hash;
|
struct GNUNET_HashCode c_hash;
|
||||||
void *coin_ev;
|
void *coin_ev;
|
||||||
size_t coin_ev_size;
|
size_t coin_ev_size;
|
||||||
@ -369,6 +370,7 @@ verify_and_execute_recoup (struct MHD_Connection *connection,
|
|||||||
/* check denomination exists and is in recoup mode */
|
/* check denomination exists and is in recoup mode */
|
||||||
{
|
{
|
||||||
struct TEH_KS_StateHandle *key_state;
|
struct TEH_KS_StateHandle *key_state;
|
||||||
|
struct GNUNET_TIME_Absolute now;
|
||||||
|
|
||||||
key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ());
|
key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ());
|
||||||
if (NULL == key_state)
|
if (NULL == key_state)
|
||||||
@ -379,12 +381,10 @@ verify_and_execute_recoup (struct MHD_Connection *connection,
|
|||||||
TALER_EC_EXCHANGE_GENERIC_BAD_CONFIGURATION,
|
TALER_EC_EXCHANGE_GENERIC_BAD_CONFIGURATION,
|
||||||
"no keys");
|
"no keys");
|
||||||
}
|
}
|
||||||
dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
|
dk = TEH_keys_denomination_by_hash (&coin->denom_pub_hash,
|
||||||
&coin->denom_pub_hash,
|
|
||||||
TEH_KS_DKU_RECOUP,
|
|
||||||
&ec,
|
&ec,
|
||||||
&hc);
|
&hc);
|
||||||
if (NULL == dki)
|
if (NULL == dk)
|
||||||
{
|
{
|
||||||
TEH_KS_release (key_state);
|
TEH_KS_release (key_state);
|
||||||
TALER_LOG_WARNING (
|
TALER_LOG_WARNING (
|
||||||
@ -394,13 +394,45 @@ verify_and_execute_recoup (struct MHD_Connection *connection,
|
|||||||
ec,
|
ec,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
TALER_amount_ntoh (&pc.value,
|
|
||||||
&dki->issue.properties.value);
|
now = GNUNET_TIME_absolute_get ();
|
||||||
|
if (now.abs_value_us >= dk->meta.expire_deposit.abs_value_us)
|
||||||
|
{
|
||||||
|
/* This denomination is past the expiration time for recoup */
|
||||||
|
TEH_KS_release (key_state);
|
||||||
|
return TALER_MHD_reply_with_error (
|
||||||
|
connection,
|
||||||
|
MHD_HTTP_GONE,
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
if (now.abs_value_us < dk->meta.start.abs_value_us)
|
||||||
|
{
|
||||||
|
/* This denomination is not yet valid */
|
||||||
|
TEH_KS_release (key_state);
|
||||||
|
return TALER_MHD_reply_with_error (
|
||||||
|
connection,
|
||||||
|
MHD_HTTP_PRECONDITION_FAILED,
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
if (! dk->recoup_possible)
|
||||||
|
{
|
||||||
|
/* This denomination is not eligible for recoup */
|
||||||
|
TEH_KS_release (key_state);
|
||||||
|
return TALER_MHD_reply_with_error (
|
||||||
|
connection,
|
||||||
|
MHD_HTTP_NOT_FOUND,
|
||||||
|
TALER_EC_EXCHANGE_RECOUP_NOT_ELIGIBLE,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
pc.value = dk->meta.value;
|
||||||
|
|
||||||
/* check denomination signature */
|
/* check denomination signature */
|
||||||
if (GNUNET_YES !=
|
if (GNUNET_YES !=
|
||||||
TALER_test_coin_valid (coin,
|
TALER_test_coin_valid (coin,
|
||||||
&dki->denom_pub))
|
&dk->denom_pub))
|
||||||
{
|
{
|
||||||
TALER_LOG_WARNING ("Invalid coin passed for recoup\n");
|
TALER_LOG_WARNING ("Invalid coin passed for recoup\n");
|
||||||
TEH_KS_release (key_state);
|
TEH_KS_release (key_state);
|
||||||
@ -416,7 +448,7 @@ verify_and_execute_recoup (struct MHD_Connection *connection,
|
|||||||
.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP),
|
.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP),
|
||||||
.purpose.size = htonl (sizeof (struct TALER_RecoupRequestPS)),
|
.purpose.size = htonl (sizeof (struct TALER_RecoupRequestPS)),
|
||||||
.coin_pub = coin->coin_pub,
|
.coin_pub = coin->coin_pub,
|
||||||
.h_denom_pub = dki->issue.properties.denom_hash,
|
.h_denom_pub = coin->denom_pub_hash,
|
||||||
.coin_blind = *coin_bks
|
.coin_blind = *coin_bks
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -440,7 +472,7 @@ verify_and_execute_recoup (struct MHD_Connection *connection,
|
|||||||
if (GNUNET_YES !=
|
if (GNUNET_YES !=
|
||||||
TALER_rsa_blind (&c_hash,
|
TALER_rsa_blind (&c_hash,
|
||||||
&coin_bks->bks,
|
&coin_bks->bks,
|
||||||
dki->denom_pub.rsa_public_key,
|
dk->denom_pub.rsa_public_key,
|
||||||
&coin_ev,
|
&coin_ev,
|
||||||
&coin_ev_size))
|
&coin_ev_size))
|
||||||
{
|
{
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "taler-exchange-httpd_refreshes_reveal.h"
|
#include "taler-exchange-httpd_refreshes_reveal.h"
|
||||||
#include "taler-exchange-httpd_responses.h"
|
#include "taler-exchange-httpd_responses.h"
|
||||||
#include "taler-exchange-httpd_keystate.h"
|
#include "taler-exchange-httpd_keystate.h"
|
||||||
|
#include "taler-exchange-httpd_keys.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -132,7 +133,7 @@ struct RevealContext
|
|||||||
/**
|
/**
|
||||||
* Denominations being requested.
|
* Denominations being requested.
|
||||||
*/
|
*/
|
||||||
const struct TALER_EXCHANGEDB_DenominationKey **dkis;
|
const struct TEH_DenominationKey **dks;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Envelopes to be signed.
|
* Envelopes to be signed.
|
||||||
@ -151,7 +152,7 @@ struct RevealContext
|
|||||||
struct TALER_DenominationSignature *ev_sigs;
|
struct TALER_DenominationSignature *ev_sigs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Size of the @e dkis, @e rcds and @e ev_sigs arrays (if non-NULL).
|
* Size of the @e dks, @e rcds and @e ev_sigs arrays (if non-NULL).
|
||||||
*/
|
*/
|
||||||
unsigned int num_fresh_coins;
|
unsigned int num_fresh_coins;
|
||||||
|
|
||||||
@ -367,7 +368,7 @@ refreshes_reveal_transaction (void *cls,
|
|||||||
struct TALER_PlanchetDetail pd;
|
struct TALER_PlanchetDetail pd;
|
||||||
struct GNUNET_HashCode c_hash;
|
struct GNUNET_HashCode c_hash;
|
||||||
|
|
||||||
rcd->dk = &rctx->dkis[j]->denom_pub;
|
rcd->dk = &rctx->dks[j]->denom_pub;
|
||||||
TALER_planchet_setup_refresh (&ts,
|
TALER_planchet_setup_refresh (&ts,
|
||||||
j,
|
j,
|
||||||
&ps);
|
&ps);
|
||||||
@ -432,18 +433,12 @@ refreshes_reveal_transaction (void *cls,
|
|||||||
refresh_cost = melt.melt_fee;
|
refresh_cost = melt.melt_fee;
|
||||||
for (unsigned int i = 0; i<rctx->num_fresh_coins; i++)
|
for (unsigned int i = 0; i<rctx->num_fresh_coins; i++)
|
||||||
{
|
{
|
||||||
struct TALER_Amount fee_withdraw;
|
|
||||||
struct TALER_Amount value;
|
|
||||||
struct TALER_Amount total;
|
struct TALER_Amount total;
|
||||||
|
|
||||||
TALER_amount_ntoh (&fee_withdraw,
|
|
||||||
&rctx->dkis[i]->issue.properties.fee_withdraw);
|
|
||||||
TALER_amount_ntoh (&value,
|
|
||||||
&rctx->dkis[i]->issue.properties.value);
|
|
||||||
if ( (0 >
|
if ( (0 >
|
||||||
TALER_amount_add (&total,
|
TALER_amount_add (&total,
|
||||||
&fee_withdraw,
|
&rctx->dks[i]->meta.fee_withdraw,
|
||||||
&value)) ||
|
&rctx->dks[i]->meta.value)) ||
|
||||||
(0 >
|
(0 >
|
||||||
TALER_amount_add (&refresh_cost,
|
TALER_amount_add (&refresh_cost,
|
||||||
&refresh_cost,
|
&refresh_cost,
|
||||||
@ -499,7 +494,7 @@ refreshes_reveal_persist (void *cls,
|
|||||||
{
|
{
|
||||||
struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &rrcs[i];
|
struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &rrcs[i];
|
||||||
|
|
||||||
rrc->denom_pub = rctx->dkis[i]->denom_pub;
|
rrc->denom_pub = rctx->dks[i]->denom_pub;
|
||||||
rrc->orig_coin_link_sig = rctx->link_sigs[i];
|
rrc->orig_coin_link_sig = rctx->link_sigs[i];
|
||||||
rrc->coin_ev = rctx->rcds[i].coin_ev;
|
rrc->coin_ev = rctx->rcds[i].coin_ev;
|
||||||
rrc->coin_ev_size = rctx->rcds[i].coin_ev_size;
|
rrc->coin_ev_size = rctx->rcds[i].coin_ev_size;
|
||||||
@ -546,20 +541,31 @@ resolve_refreshes_reveal_denominations (struct TEH_KS_StateHandle *key_state,
|
|||||||
{
|
{
|
||||||
unsigned int num_fresh_coins = json_array_size (new_denoms_h_json);
|
unsigned int num_fresh_coins = json_array_size (new_denoms_h_json);
|
||||||
/* We know num_fresh_coins is bounded by #MAX_FRESH_COINS, so this is safe */
|
/* We know num_fresh_coins is bounded by #MAX_FRESH_COINS, so this is safe */
|
||||||
const struct TALER_EXCHANGEDB_DenominationKey *dkis[num_fresh_coins];
|
const struct TEH_DenominationKey *dks[num_fresh_coins];
|
||||||
struct GNUNET_HashCode dki_h[num_fresh_coins];
|
struct GNUNET_HashCode dk_h[num_fresh_coins];
|
||||||
struct TALER_RefreshCoinData rcds[num_fresh_coins];
|
struct TALER_RefreshCoinData rcds[num_fresh_coins];
|
||||||
struct TALER_CoinSpendSignatureP link_sigs[num_fresh_coins];
|
struct TALER_CoinSpendSignatureP link_sigs[num_fresh_coins];
|
||||||
struct TALER_EXCHANGEDB_Melt melt;
|
struct TALER_EXCHANGEDB_Melt melt;
|
||||||
enum GNUNET_GenericReturnValue res;
|
enum GNUNET_GenericReturnValue res;
|
||||||
MHD_RESULT ret;
|
MHD_RESULT ret;
|
||||||
|
struct TEH_KeyStateHandle *ksh;
|
||||||
|
struct GNUNET_TIME_Absolute now;
|
||||||
|
|
||||||
|
ksh = TEH_get_key_state ();
|
||||||
|
if (NULL == ksh)
|
||||||
|
{
|
||||||
|
return TALER_MHD_reply_with_error (connection,
|
||||||
|
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
/* Parse denomination key hashes */
|
/* Parse denomination key hashes */
|
||||||
|
now = GNUNET_TIME_absolute_get ();
|
||||||
for (unsigned int i = 0; i<num_fresh_coins; i++)
|
for (unsigned int i = 0; i<num_fresh_coins; i++)
|
||||||
{
|
{
|
||||||
struct GNUNET_JSON_Specification spec[] = {
|
struct GNUNET_JSON_Specification spec[] = {
|
||||||
GNUNET_JSON_spec_fixed_auto (NULL,
|
GNUNET_JSON_spec_fixed_auto (NULL,
|
||||||
&dki_h[i]),
|
&dk_h[i]),
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
};
|
};
|
||||||
unsigned int hc;
|
unsigned int hc;
|
||||||
@ -574,21 +580,45 @@ resolve_refreshes_reveal_denominations (struct TEH_KS_StateHandle *key_state,
|
|||||||
{
|
{
|
||||||
return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
|
return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
|
||||||
}
|
}
|
||||||
dkis[i] = TEH_KS_denomination_key_lookup_by_hash (key_state,
|
dks[i] = TEH_keys_denomination_by_hash2 (ksh,
|
||||||
&dki_h[i],
|
&dk_h[i],
|
||||||
TEH_KS_DKU_WITHDRAW,
|
|
||||||
&ec,
|
&ec,
|
||||||
&hc);
|
&hc);
|
||||||
if (NULL == dkis[i])
|
if (NULL == dks[i])
|
||||||
{
|
{
|
||||||
return TALER_MHD_reply_with_error (connection,
|
return TALER_MHD_reply_with_error (connection,
|
||||||
hc,
|
hc,
|
||||||
ec,
|
ec,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
/* #TEH_KS_DKU_WITHDRAW should warrant that we only get denomination
|
|
||||||
keys where we did not yet forget the private key */
|
if (now.abs_value_us >= dks[i]->meta.expire_withdraw.abs_value_us)
|
||||||
GNUNET_assert (NULL != dkis[i]->denom_priv.rsa_private_key);
|
{
|
||||||
|
/* This denomination is past the expiration time for withdraws */
|
||||||
|
return TALER_MHD_reply_with_error (
|
||||||
|
connection,
|
||||||
|
MHD_HTTP_GONE,
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
if (now.abs_value_us < dks[i]->meta.start.abs_value_us)
|
||||||
|
{
|
||||||
|
/* This denomination is not yet valid */
|
||||||
|
return TALER_MHD_reply_with_error (
|
||||||
|
connection,
|
||||||
|
MHD_HTTP_PRECONDITION_FAILED,
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
if (dks[i]->recoup_possible)
|
||||||
|
{
|
||||||
|
/* This denomination has been revoked */
|
||||||
|
return TALER_MHD_reply_with_error (
|
||||||
|
connection,
|
||||||
|
MHD_HTTP_GONE,
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse coin envelopes */
|
/* Parse coin envelopes */
|
||||||
@ -613,7 +643,7 @@ resolve_refreshes_reveal_denominations (struct TEH_KS_StateHandle *key_state,
|
|||||||
GNUNET_free (rcds[j].coin_ev);
|
GNUNET_free (rcds[j].coin_ev);
|
||||||
return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
|
return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
|
||||||
}
|
}
|
||||||
rcd->dk = &dkis[i]->denom_pub;
|
rcd->dk = &dks[i]->denom_pub;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* lookup old_coin_pub in database */
|
/* lookup old_coin_pub in database */
|
||||||
@ -672,7 +702,7 @@ resolve_refreshes_reveal_denominations (struct TEH_KS_StateHandle *key_state,
|
|||||||
struct TALER_LinkDataPS ldp = {
|
struct TALER_LinkDataPS ldp = {
|
||||||
.purpose.size = htonl (sizeof (ldp)),
|
.purpose.size = htonl (sizeof (ldp)),
|
||||||
.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_LINK),
|
.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_LINK),
|
||||||
.h_denom_pub = dki_h[i],
|
.h_denom_pub = dk_h[i],
|
||||||
.old_coin_pub = melt.session.coin.coin_pub,
|
.old_coin_pub = melt.session.coin.coin_pub,
|
||||||
.transfer_pub = rctx->gamma_tp
|
.transfer_pub = rctx->gamma_tp
|
||||||
};
|
};
|
||||||
@ -699,7 +729,7 @@ resolve_refreshes_reveal_denominations (struct TEH_KS_StateHandle *key_state,
|
|||||||
|
|
||||||
rctx->num_fresh_coins = num_fresh_coins;
|
rctx->num_fresh_coins = num_fresh_coins;
|
||||||
rctx->rcds = rcds;
|
rctx->rcds = rcds;
|
||||||
rctx->dkis = dkis;
|
rctx->dks = dks;
|
||||||
rctx->link_sigs = link_sigs;
|
rctx->link_sigs = link_sigs;
|
||||||
|
|
||||||
/* sign _early_ (optimistic!) to keep out of transaction scope! */
|
/* sign _early_ (optimistic!) to keep out of transaction scope! */
|
||||||
@ -707,17 +737,19 @@ resolve_refreshes_reveal_denominations (struct TEH_KS_StateHandle *key_state,
|
|||||||
struct TALER_DenominationSignature);
|
struct TALER_DenominationSignature);
|
||||||
for (unsigned int i = 0; i<rctx->num_fresh_coins; i++)
|
for (unsigned int i = 0; i<rctx->num_fresh_coins; i++)
|
||||||
{
|
{
|
||||||
rctx->ev_sigs[i].rsa_signature
|
enum TALER_ErrorCode ec;
|
||||||
= GNUNET_CRYPTO_rsa_sign_blinded (
|
|
||||||
rctx->dkis[i]->denom_priv.rsa_private_key,
|
rctx->ev_sigs[i]
|
||||||
|
= TEH_keys_denomination_sign (
|
||||||
|
&dk_h[i],
|
||||||
rctx->rcds[i].coin_ev,
|
rctx->rcds[i].coin_ev,
|
||||||
rctx->rcds[i].coin_ev_size);
|
rctx->rcds[i].coin_ev_size,
|
||||||
|
&ec);
|
||||||
if (NULL == rctx->ev_sigs[i].rsa_signature)
|
if (NULL == rctx->ev_sigs[i].rsa_signature)
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
ret = TALER_MHD_reply_with_error (connection,
|
ret = TALER_MHD_reply_with_ec (connection,
|
||||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
ec,
|
||||||
TALER_EC_EXCHANGE_REFRESHES_REVEAL_SIGNING_ERROR,
|
|
||||||
NULL);
|
NULL);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "taler-exchange-httpd_refund.h"
|
#include "taler-exchange-httpd_refund.h"
|
||||||
#include "taler-exchange-httpd_responses.h"
|
#include "taler-exchange-httpd_responses.h"
|
||||||
#include "taler-exchange-httpd_keystate.h"
|
#include "taler-exchange-httpd_keystate.h"
|
||||||
|
#include "taler-exchange-httpd_keys.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -58,18 +59,18 @@ reply_refund_success (struct MHD_Connection *connection,
|
|||||||
.merchant = refund->merchant_pub,
|
.merchant = refund->merchant_pub,
|
||||||
.rtransaction_id = GNUNET_htonll (refund->rtransaction_id)
|
.rtransaction_id = GNUNET_htonll (refund->rtransaction_id)
|
||||||
};
|
};
|
||||||
|
enum TALER_ErrorCode ec;
|
||||||
|
|
||||||
TALER_amount_hton (&rc.refund_amount,
|
TALER_amount_hton (&rc.refund_amount,
|
||||||
&refund->refund_amount);
|
&refund->refund_amount);
|
||||||
if (GNUNET_OK !=
|
if (TALER_EC_NONE !=
|
||||||
TEH_KS_sign (&rc,
|
(ec = TEH_keys_exchange_sign (&rc,
|
||||||
&pub,
|
&pub,
|
||||||
&sig))
|
&sig)))
|
||||||
{
|
{
|
||||||
return TALER_MHD_reply_with_error (connection,
|
return TALER_MHD_reply_with_ec (connection,
|
||||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
ec,
|
||||||
TALER_EC_EXCHANGE_GENERIC_BAD_CONFIGURATION,
|
NULL);
|
||||||
"no online signing key");
|
|
||||||
}
|
}
|
||||||
return TALER_MHD_reply_json_pack (
|
return TALER_MHD_reply_json_pack (
|
||||||
connection,
|
connection,
|
||||||
@ -460,16 +461,14 @@ verify_and_execute_refund (struct MHD_Connection *connection,
|
|||||||
}
|
}
|
||||||
/* Obtain information about the coin's denomination! */
|
/* Obtain information about the coin's denomination! */
|
||||||
{
|
{
|
||||||
struct TALER_EXCHANGEDB_DenominationKey *dki;
|
struct TEH_DenominationKey *dk;
|
||||||
unsigned int hc;
|
unsigned int hc;
|
||||||
enum TALER_ErrorCode ec;
|
enum TALER_ErrorCode ec;
|
||||||
|
|
||||||
dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
|
dk = TEH_keys_denomination_by_hash (&denom_hash,
|
||||||
&denom_hash,
|
|
||||||
TEH_KS_DKU_DEPOSIT,
|
|
||||||
&ec,
|
&ec,
|
||||||
&hc);
|
&hc);
|
||||||
if (NULL == dki)
|
if (NULL == dk)
|
||||||
{
|
{
|
||||||
/* DKI not found, but we do have a coin with this DK in our database;
|
/* DKI not found, but we do have a coin with this DK in our database;
|
||||||
not good... */
|
not good... */
|
||||||
@ -480,8 +479,19 @@ verify_and_execute_refund (struct MHD_Connection *connection,
|
|||||||
ec,
|
ec,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
TALER_amount_ntoh (&refund->details.refund_fee,
|
|
||||||
&dki->issue.properties.fee_refund);
|
if (GNUNET_TIME_absolute_get ().abs_value_us >=
|
||||||
|
dk->meta.expire_deposit.abs_value_us)
|
||||||
|
{
|
||||||
|
/* This denomination is past the expiration time for deposits, and thus refunds */
|
||||||
|
TEH_KS_release (key_state);
|
||||||
|
return TALER_MHD_reply_with_error (
|
||||||
|
connection,
|
||||||
|
MHD_HTTP_GONE,
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
refund->details.refund_fee = dk->meta.fee_refund;
|
||||||
}
|
}
|
||||||
TEH_KS_release (key_state);
|
TEH_KS_release (key_state);
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "taler_json_lib.h"
|
#include "taler_json_lib.h"
|
||||||
#include "taler_mhd_lib.h"
|
#include "taler_mhd_lib.h"
|
||||||
#include "taler-exchange-httpd_keystate.h"
|
#include "taler-exchange-httpd_keystate.h"
|
||||||
|
#include "taler-exchange-httpd_keys.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -256,8 +257,8 @@ TEH_RESPONSE_compile_transaction_history (
|
|||||||
|
|
||||||
TALER_amount_hton (&pc.recoup_amount,
|
TALER_amount_hton (&pc.recoup_amount,
|
||||||
&pr->value);
|
&pr->value);
|
||||||
if (GNUNET_OK !=
|
if (TALER_EC_NONE !=
|
||||||
TEH_KS_sign (&pc,
|
TEH_keys_exchange_sign (&pc,
|
||||||
&epub,
|
&epub,
|
||||||
&esig))
|
&esig))
|
||||||
{
|
{
|
||||||
@ -309,8 +310,8 @@ TEH_RESPONSE_compile_transaction_history (
|
|||||||
|
|
||||||
TALER_amount_hton (&pc.recoup_amount,
|
TALER_amount_hton (&pc.recoup_amount,
|
||||||
&recoup->value);
|
&recoup->value);
|
||||||
if (GNUNET_OK !=
|
if (TALER_EC_NONE !=
|
||||||
TEH_KS_sign (&pc,
|
TEH_keys_exchange_sign (&pc,
|
||||||
&epub,
|
&epub,
|
||||||
&esig))
|
&esig))
|
||||||
{
|
{
|
||||||
@ -366,8 +367,8 @@ TEH_RESPONSE_compile_transaction_history (
|
|||||||
|
|
||||||
TALER_amount_hton (&pc.recoup_amount,
|
TALER_amount_hton (&pc.recoup_amount,
|
||||||
&pr->value);
|
&pr->value);
|
||||||
if (GNUNET_OK !=
|
if (TALER_EC_NONE !=
|
||||||
TEH_KS_sign (&pc,
|
TEH_keys_exchange_sign (&pc,
|
||||||
&epub,
|
&epub,
|
||||||
&esig))
|
&esig))
|
||||||
{
|
{
|
||||||
@ -610,8 +611,8 @@ TEH_RESPONSE_compile_reserve_history (
|
|||||||
|
|
||||||
TALER_amount_hton (&pc.recoup_amount,
|
TALER_amount_hton (&pc.recoup_amount,
|
||||||
&recoup->value);
|
&recoup->value);
|
||||||
if (GNUNET_OK !=
|
if (TALER_EC_NONE !=
|
||||||
TEH_KS_sign (&pc,
|
TEH_keys_exchange_sign (&pc,
|
||||||
&pub,
|
&pub,
|
||||||
&sig))
|
&sig))
|
||||||
{
|
{
|
||||||
@ -686,8 +687,8 @@ TEH_RESPONSE_compile_reserve_history (
|
|||||||
GNUNET_CRYPTO_hash (closing->receiver_account_details,
|
GNUNET_CRYPTO_hash (closing->receiver_account_details,
|
||||||
strlen (closing->receiver_account_details) + 1,
|
strlen (closing->receiver_account_details) + 1,
|
||||||
&rcc.h_wire);
|
&rcc.h_wire);
|
||||||
if (GNUNET_OK !=
|
if (TALER_EC_NONE !=
|
||||||
TEH_KS_sign (&rcc,
|
TEH_keys_exchange_sign (&rcc,
|
||||||
&pub,
|
&pub,
|
||||||
&sig))
|
&sig))
|
||||||
{
|
{
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <microhttpd.h>
|
#include <microhttpd.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include "taler_signatures.h"
|
#include "taler_signatures.h"
|
||||||
|
#include "taler-exchange-httpd_keys.h"
|
||||||
#include "taler-exchange-httpd_keystate.h"
|
#include "taler-exchange-httpd_keystate.h"
|
||||||
#include "taler-exchange-httpd_transfers_get.h"
|
#include "taler-exchange-httpd_transfers_get.h"
|
||||||
#include "taler-exchange-httpd_responses.h"
|
#include "taler-exchange-httpd_responses.h"
|
||||||
@ -99,6 +100,7 @@ reply_transfer_details (struct MHD_Connection *connection,
|
|||||||
struct TALER_ExchangePublicKeyP pub;
|
struct TALER_ExchangePublicKeyP pub;
|
||||||
struct TALER_ExchangeSignatureP sig;
|
struct TALER_ExchangeSignatureP sig;
|
||||||
|
|
||||||
|
|
||||||
GNUNET_TIME_round_abs (&exec_time);
|
GNUNET_TIME_round_abs (&exec_time);
|
||||||
deposits = json_array ();
|
deposits = json_array ();
|
||||||
if (NULL == deposits)
|
if (NULL == deposits)
|
||||||
@ -158,16 +160,19 @@ reply_transfer_details (struct MHD_Connection *connection,
|
|||||||
wdp.h_wire = *h_wire;
|
wdp.h_wire = *h_wire;
|
||||||
GNUNET_CRYPTO_hash_context_finish (hash_context,
|
GNUNET_CRYPTO_hash_context_finish (hash_context,
|
||||||
&wdp.h_details);
|
&wdp.h_details);
|
||||||
if (GNUNET_OK !=
|
{
|
||||||
TEH_KS_sign (&wdp,
|
enum TALER_ErrorCode ec;
|
||||||
|
|
||||||
|
if (TALER_EC_NONE !=
|
||||||
|
(ec = TEH_keys_exchange_sign (&wdp,
|
||||||
&pub,
|
&pub,
|
||||||
&sig))
|
&sig)))
|
||||||
{
|
{
|
||||||
json_decref (deposits);
|
json_decref (deposits);
|
||||||
return TALER_MHD_reply_with_error (connection,
|
return TALER_MHD_reply_with_ec (connection,
|
||||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
ec,
|
||||||
TALER_EC_EXCHANGE_GENERIC_BAD_CONFIGURATION,
|
NULL);
|
||||||
"no keys");
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TALER_MHD_reply_json_pack (connection,
|
return TALER_MHD_reply_json_pack (connection,
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "taler-exchange-httpd_withdraw.h"
|
#include "taler-exchange-httpd_withdraw.h"
|
||||||
#include "taler-exchange-httpd_responses.h"
|
#include "taler-exchange-httpd_responses.h"
|
||||||
#include "taler-exchange-httpd_keystate.h"
|
#include "taler-exchange-httpd_keystate.h"
|
||||||
|
#include "taler-exchange-httpd_keys.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -133,11 +134,6 @@ struct WithdrawContext
|
|||||||
*/
|
*/
|
||||||
size_t blinded_msg_len;
|
size_t blinded_msg_len;
|
||||||
|
|
||||||
/**
|
|
||||||
* Details about denomination we are about to withdraw.
|
|
||||||
*/
|
|
||||||
struct TALER_EXCHANGEDB_DenominationKey *dki;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set to the resulting signed coin data to be returned to the client.
|
* Set to the resulting signed coin data to be returned to the client.
|
||||||
*/
|
*/
|
||||||
@ -291,16 +287,18 @@ withdraw_transaction (void *cls,
|
|||||||
#if ! OPTIMISTIC_SIGN
|
#if ! OPTIMISTIC_SIGN
|
||||||
if (NULL == wc->collectable.sig.rsa_signature)
|
if (NULL == wc->collectable.sig.rsa_signature)
|
||||||
{
|
{
|
||||||
wc->collectable.sig.rsa_signature
|
enum TALER_ErrorCode ec;
|
||||||
= GNUNET_CRYPTO_rsa_sign_blinded (wc->dki->denom_priv.rsa_private_key,
|
|
||||||
|
wc->collectable.sig
|
||||||
|
= TEH_keys_denomination_sign (&wc->denom_pub_hash,
|
||||||
wc->blinded_msg,
|
wc->blinded_msg,
|
||||||
wc->blinded_msg_len);
|
wc->blinded_msg_len,
|
||||||
|
&ec);
|
||||||
if (NULL == wc->collectable.sig.rsa_signature)
|
if (NULL == wc->collectable.sig.rsa_signature)
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
*mhd_ret = TALER_MHD_reply_with_error (connection,
|
*mhd_ret = TALER_MHD_reply_with_ec (connection,
|
||||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
ec,
|
||||||
TALER_EC_EXCHANGE_WITHDRAW_SIGNATURE_FAILED,
|
|
||||||
NULL);
|
NULL);
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
}
|
}
|
||||||
@ -360,6 +358,8 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
|
|||||||
&wc.denom_pub_hash),
|
&wc.denom_pub_hash),
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
};
|
};
|
||||||
|
enum TALER_ErrorCode ec;
|
||||||
|
struct TEH_DenominationKey *dk;
|
||||||
|
|
||||||
(void) rh;
|
(void) rh;
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
@ -397,13 +397,12 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
|
|||||||
{
|
{
|
||||||
unsigned int hc;
|
unsigned int hc;
|
||||||
enum TALER_ErrorCode ec;
|
enum TALER_ErrorCode ec;
|
||||||
|
struct GNUNET_TIME_Absolute now;
|
||||||
|
|
||||||
wc.dki = TEH_KS_denomination_key_lookup_by_hash (wc.key_state,
|
dk = TEH_keys_denomination_by_hash (&wc.denom_pub_hash,
|
||||||
&wc.denom_pub_hash,
|
|
||||||
TEH_KS_DKU_WITHDRAW,
|
|
||||||
&ec,
|
&ec,
|
||||||
&hc);
|
&hc);
|
||||||
if (NULL == wc.dki)
|
if (NULL == dk)
|
||||||
{
|
{
|
||||||
GNUNET_JSON_parse_free (spec);
|
GNUNET_JSON_parse_free (spec);
|
||||||
TEH_KS_release (wc.key_state);
|
TEH_KS_release (wc.key_state);
|
||||||
@ -412,20 +411,47 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
|
|||||||
ec,
|
ec,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
}
|
now = GNUNET_TIME_absolute_get ();
|
||||||
GNUNET_assert (NULL != wc.dki->denom_priv.rsa_private_key);
|
if (now.abs_value_us >= dk->meta.expire_withdraw.abs_value_us)
|
||||||
{
|
{
|
||||||
struct TALER_Amount amount;
|
/* This denomination is past the expiration time for withdraws */
|
||||||
struct TALER_Amount fee_withdraw;
|
TEH_KS_release (wc.key_state);
|
||||||
|
GNUNET_JSON_parse_free (spec);
|
||||||
|
return TALER_MHD_reply_with_error (
|
||||||
|
connection,
|
||||||
|
MHD_HTTP_GONE,
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
if (now.abs_value_us < dk->meta.start.abs_value_us)
|
||||||
|
{
|
||||||
|
/* This denomination is not yet valid */
|
||||||
|
TEH_KS_release (wc.key_state);
|
||||||
|
GNUNET_JSON_parse_free (spec);
|
||||||
|
return TALER_MHD_reply_with_error (
|
||||||
|
connection,
|
||||||
|
MHD_HTTP_PRECONDITION_FAILED,
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
if (dk->recoup_possible)
|
||||||
|
{
|
||||||
|
/* This denomination has been revoked */
|
||||||
|
TEH_KS_release (wc.key_state);
|
||||||
|
GNUNET_JSON_parse_free (spec);
|
||||||
|
return TALER_MHD_reply_with_error (
|
||||||
|
connection,
|
||||||
|
MHD_HTTP_GONE,
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TALER_amount_ntoh (&amount,
|
{
|
||||||
&wc.dki->issue.properties.value);
|
|
||||||
TALER_amount_ntoh (&fee_withdraw,
|
|
||||||
&wc.dki->issue.properties.fee_withdraw);
|
|
||||||
if (0 >
|
if (0 >
|
||||||
TALER_amount_add (&wc.amount_required,
|
TALER_amount_add (&wc.amount_required,
|
||||||
&amount,
|
&dk->meta.value,
|
||||||
&fee_withdraw))
|
&dk->meta.fee_withdraw))
|
||||||
{
|
{
|
||||||
GNUNET_JSON_parse_free (spec);
|
GNUNET_JSON_parse_free (spec);
|
||||||
TEH_KS_release (wc.key_state);
|
TEH_KS_release (wc.key_state);
|
||||||
@ -466,18 +492,18 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
|
|||||||
|
|
||||||
#if OPTIMISTIC_SIGN
|
#if OPTIMISTIC_SIGN
|
||||||
/* Sign before transaction! */
|
/* Sign before transaction! */
|
||||||
wc.collectable.sig.rsa_signature
|
wc.collectable.sig
|
||||||
= GNUNET_CRYPTO_rsa_sign_blinded (wc.dki->denom_priv.rsa_private_key,
|
= TEH_keys_denomination_sign (&wc.denom_pub_hash,
|
||||||
wc.blinded_msg,
|
wc.blinded_msg,
|
||||||
wc.blinded_msg_len);
|
wc.blinded_msg_len,
|
||||||
|
&ec);
|
||||||
if (NULL == wc.collectable.sig.rsa_signature)
|
if (NULL == wc.collectable.sig.rsa_signature)
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
GNUNET_JSON_parse_free (spec);
|
GNUNET_JSON_parse_free (spec);
|
||||||
TEH_KS_release (wc.key_state);
|
TEH_KS_release (wc.key_state);
|
||||||
return TALER_MHD_reply_with_error (connection,
|
return TALER_MHD_reply_with_ec (connection,
|
||||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
ec,
|
||||||
TALER_EC_EXCHANGE_WITHDRAW_SIGNATURE_FAILED,
|
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -18,6 +18,7 @@ TERMS_DIR = ../../contrib/tos
|
|||||||
# Etag / filename for the terms of service.
|
# Etag / filename for the terms of service.
|
||||||
TERMS_ETAG = 0
|
TERMS_ETAG = 0
|
||||||
|
|
||||||
|
SIGNKEY_LEGAL_DURATION = 2 years
|
||||||
|
|
||||||
# Directory with our privacy policy.
|
# Directory with our privacy policy.
|
||||||
PRIVACY_DIR = ../../contrib/pp
|
PRIVACY_DIR = ../../contrib/pp
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#
|
#
|
||||||
/
|
/
|
||||||
/agpl
|
/agpl
|
||||||
/keys
|
/seed
|
||||||
/robots.txt
|
/robots.txt
|
||||||
/terms
|
/terms
|
||||||
/privacy
|
/privacy
|
||||||
|
@ -31,10 +31,6 @@ PREFIX=
|
|||||||
|
|
||||||
# Setup database
|
# Setup database
|
||||||
taler-exchange-dbinit -c test_taler_exchange_httpd.conf &> /dev/null
|
taler-exchange-dbinit -c test_taler_exchange_httpd.conf &> /dev/null
|
||||||
# Setup keys.
|
|
||||||
taler-exchange-keyup -c test_taler_exchange_httpd.conf || exit 1
|
|
||||||
# Setup wire accounts.
|
|
||||||
taler-exchange-wire -c test_taler_exchange_httpd.conf > /dev/null || exit 1
|
|
||||||
# Run Exchange HTTPD (in background)
|
# Run Exchange HTTPD (in background)
|
||||||
$PREFIX taler-exchange-httpd -c test_taler_exchange_httpd.conf 2> test-exchange.log &
|
$PREFIX taler-exchange-httpd -c test_taler_exchange_httpd.conf 2> test-exchange.log &
|
||||||
|
|
||||||
@ -45,7 +41,7 @@ do
|
|||||||
echo -n "."
|
echo -n "."
|
||||||
sleep 0.1
|
sleep 0.1
|
||||||
OK=1
|
OK=1
|
||||||
wget http://localhost:8081/ -o /dev/null -O /dev/null >/dev/null && break
|
wget http://localhost:8081/seed -o /dev/null -O /dev/null >/dev/null && break
|
||||||
OK=0
|
OK=0
|
||||||
done
|
done
|
||||||
if [ 1 != $OK ]
|
if [ 1 != $OK ]
|
||||||
|
@ -53,10 +53,6 @@ PREFIX=
|
|||||||
|
|
||||||
# Setup database
|
# Setup database
|
||||||
taler-exchange-dbinit -c test_taler_exchange_unix.conf &> /dev/null
|
taler-exchange-dbinit -c test_taler_exchange_unix.conf &> /dev/null
|
||||||
# Setup keys.
|
|
||||||
taler-exchange-keyup -c test_taler_exchange_unix.conf || exit 1
|
|
||||||
# Setup wire accounts.
|
|
||||||
taler-exchange-wire -c test_taler_exchange_unix.conf > /dev/null || exit 1
|
|
||||||
# Run Exchange HTTPD (in background)
|
# Run Exchange HTTPD (in background)
|
||||||
$PREFIX taler-exchange-httpd -c test_taler_exchange_unix.conf 2> test-exchange.log &
|
$PREFIX taler-exchange-httpd -c test_taler_exchange_unix.conf 2> test-exchange.log &
|
||||||
|
|
||||||
@ -79,13 +75,6 @@ then
|
|||||||
fi
|
fi
|
||||||
echo " DONE"
|
echo " DONE"
|
||||||
|
|
||||||
# Finally run test...
|
|
||||||
echo -n "Reloading keys ..."
|
|
||||||
kill -SIGUSR1 $!
|
|
||||||
sleep 1
|
|
||||||
curl --unix-socket "${UNIXPATH}" "http://ignored/" >/dev/null 2> /dev/null || exit_fail "SIGUSR1 killed HTTP service"
|
|
||||||
echo " DONE"
|
|
||||||
|
|
||||||
# Finally run test...
|
# Finally run test...
|
||||||
echo -n "Restarting program ..."
|
echo -n "Restarting program ..."
|
||||||
kill -SIGHUP $!
|
kill -SIGHUP $!
|
||||||
|
@ -15,6 +15,7 @@ TERMS_DIR = ../../contrib/tos
|
|||||||
# Etag / filename for the terms of service.
|
# Etag / filename for the terms of service.
|
||||||
TERMS_ETAG = 0
|
TERMS_ETAG = 0
|
||||||
|
|
||||||
|
SIGNKEY_LEGAL_DURATION = 2 years
|
||||||
|
|
||||||
# Directory with our privacy policy.
|
# Directory with our privacy policy.
|
||||||
PRIVACY_DIR = ../../contrib/pp
|
PRIVACY_DIR = ../../contrib/pp
|
||||||
|
@ -143,6 +143,21 @@ TALER_MHD_reply_with_error (struct MHD_Connection *connection,
|
|||||||
const char *detail);
|
const char *detail);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a response indicating an error. The HTTP status code is
|
||||||
|
* to be derived from the @a ec.
|
||||||
|
*
|
||||||
|
* @param connection the MHD connection to use
|
||||||
|
* @param ec error code uniquely identifying the error
|
||||||
|
* @param detail additional optional detail about the error
|
||||||
|
* @return a MHD result code
|
||||||
|
*/
|
||||||
|
MHD_RESULT
|
||||||
|
TALER_MHD_reply_with_ec (struct MHD_Connection *connection,
|
||||||
|
enum TALER_ErrorCode ec,
|
||||||
|
const char *detail);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make JSON response object.
|
* Make JSON response object.
|
||||||
*
|
*
|
||||||
|
@ -442,6 +442,37 @@ TALER_MHD_reply_with_error (struct MHD_Connection *connection,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a response indicating an error. The HTTP status code is
|
||||||
|
* to be derived from the @a ec.
|
||||||
|
*
|
||||||
|
* @param connection the MHD connection to use
|
||||||
|
* @param ec error code uniquely identifying the error
|
||||||
|
* @param detail additional optional detail about the error
|
||||||
|
* @return a MHD result code
|
||||||
|
*/
|
||||||
|
MHD_RESULT
|
||||||
|
TALER_MHD_reply_with_ec (struct MHD_Connection *connection,
|
||||||
|
enum TALER_ErrorCode ec,
|
||||||
|
const char *detail)
|
||||||
|
{
|
||||||
|
unsigned int hc = TALER_ErrorCode_get_http_status (ec);
|
||||||
|
|
||||||
|
if ( (0 == hc) ||
|
||||||
|
(UINT_MAX == hc) )
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
"Invalid Taler error code %d provided for response!\n",
|
||||||
|
(int) ec);
|
||||||
|
hc = MHD_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
|
}
|
||||||
|
return TALER_MHD_reply_with_error (connection,
|
||||||
|
hc,
|
||||||
|
ec,
|
||||||
|
detail);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a response indicating that the request was too big.
|
* Send a response indicating that the request was too big.
|
||||||
*
|
*
|
||||||
|
@ -131,7 +131,6 @@ check_PROGRAMS = \
|
|||||||
test_bank_api_with_pybank \
|
test_bank_api_with_pybank \
|
||||||
test_bank_api_with_nexus \
|
test_bank_api_with_nexus \
|
||||||
test_exchange_api \
|
test_exchange_api \
|
||||||
test_exchange_api_keys_cherry_picking \
|
|
||||||
test_exchange_api_revocation \
|
test_exchange_api_revocation \
|
||||||
test_exchange_api_overlapping_keys_bug \
|
test_exchange_api_overlapping_keys_bug \
|
||||||
test_exchange_management_api \
|
test_exchange_management_api \
|
||||||
@ -144,6 +143,10 @@ if HAVE_TWISTER
|
|||||||
test_bank_api_with_pybank_twisted
|
test_bank_api_with_pybank_twisted
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# test_exchange_api_keys_cherry_picking disabled for now:
|
||||||
|
# needs to be rewritten as we no longer support /keys timetravel!
|
||||||
|
|
||||||
|
|
||||||
TESTS = \
|
TESTS = \
|
||||||
$(check_PROGRAMS)
|
$(check_PROGRAMS)
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of TALER
|
This file is part of TALER
|
||||||
Copyright (C) 2014-2018 Taler Systems SA
|
Copyright (C) 2014-2020 Taler Systems SA
|
||||||
|
|
||||||
TALER is free software; you can redistribute it and/or modify
|
TALER is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as
|
it under the terms of the GNU General Public License as
|
||||||
@ -630,8 +630,8 @@ run (void *cls,
|
|||||||
TALER_TESTING_cmd_exec_offline_sign_keys ("offline-sign-future-keys",
|
TALER_TESTING_cmd_exec_offline_sign_keys ("offline-sign-future-keys",
|
||||||
CONFIG_FILE),
|
CONFIG_FILE),
|
||||||
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys",
|
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys",
|
||||||
1,
|
2,
|
||||||
5 /* FIXME: wrong number... */),
|
270 /* FIXME: wrong number... */),
|
||||||
CMD_RUN_AUDITOR ("virgin-auditor"),
|
CMD_RUN_AUDITOR ("virgin-auditor"),
|
||||||
TALER_TESTING_cmd_exchanges_with_url ("check-exchange",
|
TALER_TESTING_cmd_exchanges_with_url ("check-exchange",
|
||||||
MHD_HTTP_OK,
|
MHD_HTTP_OK,
|
||||||
|
@ -880,11 +880,11 @@ run (void *cls,
|
|||||||
"{\"items\":[{\"name\":\"more ice cream\",\"value\":1}]}",
|
"{\"items\":[{\"name\":\"more ice cream\",\"value\":1}]}",
|
||||||
GNUNET_TIME_UNIT_ZERO,
|
GNUNET_TIME_UNIT_ZERO,
|
||||||
"EUR:1",
|
"EUR:1",
|
||||||
MHD_HTTP_NOT_FOUND),
|
MHD_HTTP_GONE),
|
||||||
/* Test deposit fails after recoup, with proof in recoup */
|
/* Test deposit fails after recoup, with proof in recoup */
|
||||||
|
|
||||||
/* Note that, the exchange will never return the coin's transaction
|
/* Note that, the exchange will never return the coin's transaction
|
||||||
* history with recoup data, as we get a 404 on the DK! */
|
* history with recoup data, as we get a 410 on the DK! */
|
||||||
TALER_TESTING_cmd_deposit ("recoup-deposit-partial-after-recoup",
|
TALER_TESTING_cmd_deposit ("recoup-deposit-partial-after-recoup",
|
||||||
"recoup-withdraw-coin-2a",
|
"recoup-withdraw-coin-2a",
|
||||||
0,
|
0,
|
||||||
@ -892,7 +892,7 @@ run (void *cls,
|
|||||||
"{\"items\":[{\"name\":\"extra ice cream\",\"value\":1}]}",
|
"{\"items\":[{\"name\":\"extra ice cream\",\"value\":1}]}",
|
||||||
GNUNET_TIME_UNIT_ZERO,
|
GNUNET_TIME_UNIT_ZERO,
|
||||||
"EUR:0.5",
|
"EUR:0.5",
|
||||||
MHD_HTTP_NOT_FOUND),
|
MHD_HTTP_GONE),
|
||||||
/* Test that revoked coins cannot be withdrawn */
|
/* Test that revoked coins cannot be withdrawn */
|
||||||
CMD_TRANSFER_TO_EXCHANGE ("recoup-create-reserve-3",
|
CMD_TRANSFER_TO_EXCHANGE ("recoup-create-reserve-3",
|
||||||
"EUR:1.01"),
|
"EUR:1.01"),
|
||||||
@ -906,7 +906,7 @@ run (void *cls,
|
|||||||
TALER_TESTING_cmd_withdraw_amount ("recoup-withdraw-coin-3-revoked",
|
TALER_TESTING_cmd_withdraw_amount ("recoup-withdraw-coin-3-revoked",
|
||||||
"recoup-create-reserve-3",
|
"recoup-create-reserve-3",
|
||||||
"EUR:1",
|
"EUR:1",
|
||||||
MHD_HTTP_NOT_FOUND),
|
MHD_HTTP_GONE),
|
||||||
/* check that we are empty before the rejection test */
|
/* check that we are empty before the rejection test */
|
||||||
TALER_TESTING_cmd_check_bank_empty ("check-empty-again"),
|
TALER_TESTING_cmd_check_bank_empty ("check-empty-again"),
|
||||||
|
|
||||||
@ -958,7 +958,7 @@ run (void *cls,
|
|||||||
CONFIG_FILE),
|
CONFIG_FILE),
|
||||||
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys",
|
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys",
|
||||||
1,
|
1,
|
||||||
5 /* FIXME: wrong number... */),
|
270 /* FIXME: wrong number... */),
|
||||||
TALER_TESTING_cmd_batch ("wire",
|
TALER_TESTING_cmd_batch ("wire",
|
||||||
wire),
|
wire),
|
||||||
TALER_TESTING_cmd_batch ("withdraw",
|
TALER_TESTING_cmd_batch ("withdraw",
|
||||||
|
@ -129,8 +129,8 @@ run (void *cls,
|
|||||||
* Make sure we have the same keys situation as
|
* Make sure we have the same keys situation as
|
||||||
* it was before the serialization.
|
* it was before the serialization.
|
||||||
*/
|
*/
|
||||||
TALER_TESTING_cmd_check_keys_with_now
|
TALER_TESTING_cmd_check_keys_with_now (
|
||||||
("check-keys-after-deserialization",
|
"check-keys-after-deserialization",
|
||||||
4,
|
4,
|
||||||
NDKS_RIGHT_BEFORE_SERIALIZATION,
|
NDKS_RIGHT_BEFORE_SERIALIZATION,
|
||||||
/**
|
/**
|
||||||
@ -198,8 +198,8 @@ run (void *cls,
|
|||||||
* ----
|
* ----
|
||||||
* 40
|
* 40
|
||||||
*///
|
*///
|
||||||
TALER_TESTING_cmd_check_keys_with_now
|
TALER_TESTING_cmd_check_keys_with_now (
|
||||||
("check-keys-3",
|
"check-keys-3",
|
||||||
3 /* generation */,
|
3 /* generation */,
|
||||||
NDKS_RIGHT_BEFORE_SERIALIZATION,
|
NDKS_RIGHT_BEFORE_SERIALIZATION,
|
||||||
TTH_parse_time (JAN2030)),
|
TTH_parse_time (JAN2030)),
|
||||||
|
@ -73,7 +73,7 @@ run (void *cls,
|
|||||||
CONFIG_FILE),
|
CONFIG_FILE),
|
||||||
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys",
|
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys",
|
||||||
1,
|
1,
|
||||||
5 /* FIXME: wrong number... */),
|
270 /* FIXME: wrong number... */),
|
||||||
/**
|
/**
|
||||||
* Fill reserve with EUR:10.02, as withdraw fee is 1 ct per
|
* Fill reserve with EUR:10.02, as withdraw fee is 1 ct per
|
||||||
* config.
|
* config.
|
||||||
|
@ -222,7 +222,7 @@ run (void *cls,
|
|||||||
TALER_TESTING_cmd_check_keys_pull_all_keys (
|
TALER_TESTING_cmd_check_keys_pull_all_keys (
|
||||||
"check-keys-expiration-0",
|
"check-keys-expiration-0",
|
||||||
2,
|
2,
|
||||||
5),
|
270),
|
||||||
/**
|
/**
|
||||||
* Run some normal commands after this to make sure everything is fine.
|
* Run some normal commands after this to make sure everything is fine.
|
||||||
*/
|
*/
|
||||||
@ -237,6 +237,15 @@ run (void *cls,
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct TALER_TESTING_Command commands[] = {
|
struct TALER_TESTING_Command commands[] = {
|
||||||
|
TALER_TESTING_cmd_wire_add ("add-wire-account",
|
||||||
|
"payto://x-taler-bank/localhost/2",
|
||||||
|
MHD_HTTP_NO_CONTENT,
|
||||||
|
false),
|
||||||
|
TALER_TESTING_cmd_exec_offline_sign_keys ("offline-sign-future-keys",
|
||||||
|
CONFIG_FILE),
|
||||||
|
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys",
|
||||||
|
1,
|
||||||
|
270 /* FIXME: wrong number... */),
|
||||||
TALER_TESTING_cmd_batch ("refresh-reveal-409-conflict",
|
TALER_TESTING_cmd_batch ("refresh-reveal-409-conflict",
|
||||||
refresh_409_conflict),
|
refresh_409_conflict),
|
||||||
TALER_TESTING_cmd_batch ("refund",
|
TALER_TESTING_cmd_batch ("refund",
|
||||||
|
@ -144,7 +144,7 @@ run (void *cls,
|
|||||||
CONFIG_FILE),
|
CONFIG_FILE),
|
||||||
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys",
|
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys",
|
||||||
1,
|
1,
|
||||||
5 /* FIXME: wrong number... */),
|
270 /* FIXME: wrong number... */),
|
||||||
TALER_TESTING_cmd_end ()
|
TALER_TESTING_cmd_end ()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ run (void *cls,
|
|||||||
config_filename),
|
config_filename),
|
||||||
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys",
|
TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys",
|
||||||
1,
|
1,
|
||||||
5 /* FIXME: wrong number... */),
|
58 /* FIXME: wrong number... */),
|
||||||
TALER_TESTING_cmd_check_bank_empty ("expect-empty-transactions-on-start"),
|
TALER_TESTING_cmd_check_bank_empty ("expect-empty-transactions-on-start"),
|
||||||
CMD_EXEC_AGGREGATOR ("run-aggregator-on-empty"),
|
CMD_EXEC_AGGREGATOR ("run-aggregator-on-empty"),
|
||||||
TALER_TESTING_cmd_exec_wirewatch ("run-wirewatch-on-empty",
|
TALER_TESTING_cmd_exec_wirewatch ("run-wirewatch-on-empty",
|
||||||
|
@ -70,6 +70,7 @@ offlinesign_run (void *cls,
|
|||||||
"taler-exchange-offline",
|
"taler-exchange-offline",
|
||||||
"taler-exchange-offline",
|
"taler-exchange-offline",
|
||||||
"-c", ks->config_filename,
|
"-c", ks->config_filename,
|
||||||
|
"-L", "INFO",
|
||||||
"download",
|
"download",
|
||||||
"sign",
|
"sign",
|
||||||
"upload",
|
"upload",
|
||||||
@ -80,8 +81,6 @@ offlinesign_run (void *cls,
|
|||||||
TALER_TESTING_interpreter_fail (is);
|
TALER_TESTING_interpreter_fail (is);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* This function does not tell whether the command
|
|
||||||
* succeeded or not! */
|
|
||||||
TALER_TESTING_wait_for_sigchld (is);
|
TALER_TESTING_wait_for_sigchld (is);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,8 +79,9 @@ revoke_cleanup (void *cls,
|
|||||||
|
|
||||||
if (NULL != rs->revoke_proc)
|
if (NULL != rs->revoke_proc)
|
||||||
{
|
{
|
||||||
GNUNET_break (0 == GNUNET_OS_process_kill
|
GNUNET_break (0 ==
|
||||||
(rs->revoke_proc, SIGKILL));
|
GNUNET_OS_process_kill (rs->revoke_proc,
|
||||||
|
SIGKILL));
|
||||||
GNUNET_OS_process_wait (rs->revoke_proc);
|
GNUNET_OS_process_wait (rs->revoke_proc);
|
||||||
GNUNET_OS_process_destroy (rs->revoke_proc);
|
GNUNET_OS_process_destroy (rs->revoke_proc);
|
||||||
rs->revoke_proc = NULL;
|
rs->revoke_proc = NULL;
|
||||||
@ -163,13 +164,13 @@ revoke_run (void *cls,
|
|||||||
rs->dhks = GNUNET_STRINGS_data_to_string_alloc (
|
rs->dhks = GNUNET_STRINGS_data_to_string_alloc (
|
||||||
&denom_pub->h_key,
|
&denom_pub->h_key,
|
||||||
sizeof (struct GNUNET_HashCode));
|
sizeof (struct GNUNET_HashCode));
|
||||||
|
|
||||||
rs->revoke_proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
|
rs->revoke_proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
"taler-exchange-keyup",
|
"taler-exchange-offline",
|
||||||
"taler-exchange-keyup",
|
"taler-exchange-offline",
|
||||||
"-c", rs->config_filename,
|
"-c", rs->config_filename,
|
||||||
"-r", rs->dhks,
|
"revoke-denomination", rs->dhks,
|
||||||
|
"upload",
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (NULL == rs->revoke_proc)
|
if (NULL == rs->revoke_proc)
|
||||||
|
@ -617,7 +617,7 @@ TALER_TESTING_wait_exchange_ready (const char *base_url)
|
|||||||
unsigned int iter;
|
unsigned int iter;
|
||||||
|
|
||||||
GNUNET_asprintf (&wget_cmd,
|
GNUNET_asprintf (&wget_cmd,
|
||||||
"wget -q -t 1 -T 1 %skeys -o /dev/null -O /dev/null",
|
"wget -q -t 1 -T 1 %sseed -o /dev/null -O /dev/null",
|
||||||
base_url); // make sure ends with '/'
|
base_url); // make sure ends with '/'
|
||||||
/* give child time to start and bind against the socket */
|
/* give child time to start and bind against the socket */
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
|
@ -388,24 +388,25 @@ maint_child_death (void *cls)
|
|||||||
struct TALER_TESTING_Interpreter *is = cls;
|
struct TALER_TESTING_Interpreter *is = cls;
|
||||||
struct TALER_TESTING_Command *cmd = &is->commands[is->ip];
|
struct TALER_TESTING_Command *cmd = &is->commands[is->ip];
|
||||||
const struct GNUNET_DISK_FileHandle *pr;
|
const struct GNUNET_DISK_FileHandle *pr;
|
||||||
|
|
||||||
struct GNUNET_OS_Process **processp;
|
struct GNUNET_OS_Process **processp;
|
||||||
char c[16];
|
char c[16];
|
||||||
|
enum GNUNET_OS_ProcessStatusType type;
|
||||||
|
unsigned long code;
|
||||||
|
|
||||||
if (TALER_TESTING_cmd_is_batch (cmd))
|
if (TALER_TESTING_cmd_is_batch (cmd))
|
||||||
{
|
{
|
||||||
struct TALER_TESTING_Command *batch_cmd;
|
struct TALER_TESTING_Command *batch_cmd;
|
||||||
|
|
||||||
GNUNET_assert
|
GNUNET_assert (GNUNET_OK ==
|
||||||
(GNUNET_OK == TALER_TESTING_get_trait_cmd
|
TALER_TESTING_get_trait_cmd (cmd,
|
||||||
(cmd, 0, &batch_cmd)); /* bad? */
|
0,
|
||||||
|
&batch_cmd));
|
||||||
cmd = batch_cmd;
|
cmd = batch_cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
"Got SIGCHLD for `%s'.\n",
|
"Got SIGCHLD for `%s'.\n",
|
||||||
cmd->label);
|
cmd->label);
|
||||||
|
|
||||||
is->child_death_task = NULL;
|
is->child_death_task = NULL;
|
||||||
pr = GNUNET_DISK_pipe_handle (sigpipe,
|
pr = GNUNET_DISK_pipe_handle (sigpipe,
|
||||||
GNUNET_DISK_PIPE_END_READ);
|
GNUNET_DISK_PIPE_END_READ);
|
||||||
@ -424,16 +425,45 @@ maint_child_death (void *cls)
|
|||||||
}
|
}
|
||||||
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
"Got the dead child process handle"
|
"Got the dead child process handle, waiting for termination ...\n");
|
||||||
", waiting for termination ...\n");
|
GNUNET_OS_process_wait_status (*processp,
|
||||||
|
&type,
|
||||||
GNUNET_OS_process_wait (*processp);
|
&code);
|
||||||
GNUNET_OS_process_destroy (*processp);
|
GNUNET_OS_process_destroy (*processp);
|
||||||
*processp = NULL;
|
*processp = NULL;
|
||||||
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
"... definitively terminated\n");
|
"... definitively terminated\n");
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case GNUNET_OS_PROCESS_UNKNOWN:
|
||||||
|
GNUNET_break (0);
|
||||||
|
TALER_TESTING_interpreter_fail (is);
|
||||||
|
return;
|
||||||
|
case GNUNET_OS_PROCESS_RUNNING:
|
||||||
|
GNUNET_break (0);
|
||||||
|
TALER_TESTING_interpreter_fail (is);
|
||||||
|
return;
|
||||||
|
case GNUNET_OS_PROCESS_STOPPED:
|
||||||
|
GNUNET_break (0);
|
||||||
|
TALER_TESTING_interpreter_fail (is);
|
||||||
|
return;
|
||||||
|
case GNUNET_OS_PROCESS_EXITED:
|
||||||
|
if (0 != code)
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
"Process exited with unexpected status %u\n",
|
||||||
|
(unsigned int) code);
|
||||||
|
TALER_TESTING_interpreter_fail (is);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GNUNET_OS_PROCESS_SIGNALED:
|
||||||
|
GNUNET_break (0);
|
||||||
|
TALER_TESTING_interpreter_fail (is);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: remove reload_keys, obsolete!
|
||||||
if (GNUNET_OK == is->reload_keys)
|
if (GNUNET_OK == is->reload_keys)
|
||||||
{
|
{
|
||||||
if (NULL == is->exchanged)
|
if (NULL == is->exchanged)
|
||||||
@ -444,8 +474,9 @@ maint_child_death (void *cls)
|
|||||||
{
|
{
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
"Triggering key state reload at exchange\n");
|
"Triggering key state reload at exchange\n");
|
||||||
GNUNET_break (0 == GNUNET_OS_process_kill
|
GNUNET_break (0 ==
|
||||||
(is->exchanged, SIGUSR1));
|
GNUNET_OS_process_kill (is->exchanged,
|
||||||
|
SIGUSR1));
|
||||||
sleep (5); /* make sure signal was received and processed */
|
sleep (5); /* make sure signal was received and processed */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -643,19 +674,8 @@ TALER_TESTING_cert_cb (void *cls,
|
|||||||
* the interpreter is already running. */
|
* the interpreter is already running. */
|
||||||
if (GNUNET_YES == is->working)
|
if (GNUNET_YES == is->working)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
is->working = GNUNET_YES;
|
is->working = GNUNET_YES;
|
||||||
|
/* Trigger the next command. */
|
||||||
/* Very first start of tests, call "run()" */
|
|
||||||
if (1 == is->key_generation)
|
|
||||||
{
|
|
||||||
main_ctx->main_cb (main_ctx->main_cb_cls,
|
|
||||||
is);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tests already started, just trigger the
|
|
||||||
* next command. */
|
|
||||||
TALER_LOG_DEBUG ("Cert_cb, scheduling CMD (ip: %d)\n",
|
TALER_LOG_DEBUG ("Cert_cb, scheduling CMD (ip: %d)\n",
|
||||||
is->ip);
|
is->ip);
|
||||||
GNUNET_SCHEDULER_add_now (&interpreter_run,
|
GNUNET_SCHEDULER_add_now (&interpreter_run,
|
||||||
@ -740,6 +760,7 @@ main_wrapper_exchange_connect (void *cls)
|
|||||||
main_ctx->exchange_url = exchange_url;
|
main_ctx->exchange_url = exchange_url;
|
||||||
is->timeout_task = GNUNET_SCHEDULER_add_shutdown (&do_abort,
|
is->timeout_task = GNUNET_SCHEDULER_add_shutdown (&do_abort,
|
||||||
main_ctx);
|
main_ctx);
|
||||||
|
is->working = GNUNET_YES;
|
||||||
GNUNET_break
|
GNUNET_break
|
||||||
(NULL != (is->exchange =
|
(NULL != (is->exchange =
|
||||||
TALER_EXCHANGE_connect (is->ctx,
|
TALER_EXCHANGE_connect (is->ctx,
|
||||||
@ -747,6 +768,10 @@ main_wrapper_exchange_connect (void *cls)
|
|||||||
&TALER_TESTING_cert_cb,
|
&TALER_TESTING_cert_cb,
|
||||||
main_ctx,
|
main_ctx,
|
||||||
TALER_EXCHANGE_OPTION_END)));
|
TALER_EXCHANGE_OPTION_END)));
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Starting main test loop\n");
|
||||||
|
main_ctx->main_cb (main_ctx->main_cb_cls,
|
||||||
|
is);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -842,7 +867,7 @@ static int
|
|||||||
load_urls (struct TALER_TESTING_Interpreter *is)
|
load_urls (struct TALER_TESTING_Interpreter *is)
|
||||||
{
|
{
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
GNUNET_CONFIGURATION_get_value_filename (is->cfg,
|
GNUNET_CONFIGURATION_get_value_string (is->cfg,
|
||||||
"auditor",
|
"auditor",
|
||||||
"BASE_URL",
|
"BASE_URL",
|
||||||
&is->auditor_url))
|
&is->auditor_url))
|
||||||
|
@ -1112,17 +1112,16 @@ read_job (void *cls)
|
|||||||
* Create a new denomination key (we do not have enough).
|
* Create a new denomination key (we do not have enough).
|
||||||
*
|
*
|
||||||
* @param denom denomination key to create
|
* @param denom denomination key to create
|
||||||
|
* @param now current time to use (to get many keys to use the exact same time)
|
||||||
* @return #GNUNET_OK on success
|
* @return #GNUNET_OK on success
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
create_key (struct Denomination *denom)
|
create_key (struct Denomination *denom,
|
||||||
|
struct GNUNET_TIME_Absolute now)
|
||||||
{
|
{
|
||||||
struct DenominationKey *dk;
|
struct DenominationKey *dk;
|
||||||
struct GNUNET_TIME_Absolute anchor;
|
struct GNUNET_TIME_Absolute anchor;
|
||||||
struct GNUNET_TIME_Absolute now;
|
|
||||||
|
|
||||||
now = GNUNET_TIME_absolute_get ();
|
|
||||||
(void) GNUNET_TIME_round_abs (&now);
|
|
||||||
if (NULL == denom->keys_tail)
|
if (NULL == denom->keys_tail)
|
||||||
{
|
{
|
||||||
anchor = now;
|
anchor = now;
|
||||||
@ -1237,9 +1236,11 @@ purge_key (struct DenominationKey *dk)
|
|||||||
* correct location sorted by next maintenance activity.
|
* correct location sorted by next maintenance activity.
|
||||||
*
|
*
|
||||||
* @param[in,out] denom denomination to update material for
|
* @param[in,out] denom denomination to update material for
|
||||||
|
* @param now current time to use (to get many keys to use the exact same time)
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
update_keys (struct Denomination *denom)
|
update_keys (struct Denomination *denom,
|
||||||
|
struct GNUNET_TIME_Absolute now)
|
||||||
{
|
{
|
||||||
/* create new denomination keys */
|
/* create new denomination keys */
|
||||||
while ( (NULL == denom->keys_tail) ||
|
while ( (NULL == denom->keys_tail) ||
|
||||||
@ -1252,7 +1253,8 @@ update_keys (struct Denomination *denom)
|
|||||||
lookahead_sign),
|
lookahead_sign),
|
||||||
overlap_duration)).rel_value_us) )
|
overlap_duration)).rel_value_us) )
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
create_key (denom))
|
create_key (denom,
|
||||||
|
now))
|
||||||
{
|
{
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
"Failed to create keys for `%s'\n",
|
"Failed to create keys for `%s'\n",
|
||||||
@ -1273,18 +1275,19 @@ update_keys (struct Denomination *denom)
|
|||||||
struct GNUNET_TIME_Absolute at;
|
struct GNUNET_TIME_Absolute at;
|
||||||
|
|
||||||
at = denomination_action_time (denom);
|
at = denomination_action_time (denom);
|
||||||
before = NULL;
|
|
||||||
GNUNET_CONTAINER_DLL_remove (denom_head,
|
GNUNET_CONTAINER_DLL_remove (denom_head,
|
||||||
denom_tail,
|
denom_tail,
|
||||||
denom);
|
denom);
|
||||||
|
before = NULL;
|
||||||
for (struct Denomination *pos = denom_head;
|
for (struct Denomination *pos = denom_head;
|
||||||
NULL != pos;
|
NULL != pos;
|
||||||
pos = pos->next)
|
pos = pos->next)
|
||||||
{
|
{
|
||||||
if (denomination_action_time (pos).abs_value_us > at.abs_value_us)
|
if (denomination_action_time (pos).abs_value_us >= at.abs_value_us)
|
||||||
break;
|
break;
|
||||||
before = pos;
|
before = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
GNUNET_CONTAINER_DLL_insert_after (denom_head,
|
GNUNET_CONTAINER_DLL_insert_after (denom_head,
|
||||||
denom_tail,
|
denom_tail,
|
||||||
before,
|
before,
|
||||||
@ -1302,12 +1305,16 @@ static void
|
|||||||
update_denominations (void *cls)
|
update_denominations (void *cls)
|
||||||
{
|
{
|
||||||
struct Denomination *denom;
|
struct Denomination *denom;
|
||||||
|
struct GNUNET_TIME_Absolute now;
|
||||||
|
|
||||||
(void) cls;
|
(void) cls;
|
||||||
|
now = GNUNET_TIME_absolute_get ();
|
||||||
|
(void) GNUNET_TIME_round_abs (&now);
|
||||||
keygen_task = NULL;
|
keygen_task = NULL;
|
||||||
do {
|
do {
|
||||||
denom = denom_head;
|
denom = denom_head;
|
||||||
update_keys (denom);
|
update_keys (denom,
|
||||||
|
now);
|
||||||
} while (denom != denom_head);
|
} while (denom != denom_head);
|
||||||
keygen_task = GNUNET_SCHEDULER_add_at (denomination_action_time (denom),
|
keygen_task = GNUNET_SCHEDULER_add_at (denomination_action_time (denom),
|
||||||
&update_denominations,
|
&update_denominations,
|
||||||
@ -1609,18 +1616,35 @@ parse_denomination_cfg (const char *ct,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closure for #load_denominations.
|
||||||
|
*/
|
||||||
|
struct LoadContext
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Current time to use.
|
||||||
|
*/
|
||||||
|
struct GNUNET_TIME_Absolute now;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status, to be set to #GNUNET_SYSERR on failure
|
||||||
|
*/
|
||||||
|
int ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate new denomination signing keys for the denomination type of the given @a
|
* Generate new denomination signing keys for the denomination type of the given @a
|
||||||
* denomination_alias.
|
* denomination_alias.
|
||||||
*
|
*
|
||||||
* @param cls a `int *`, to be set to #GNUNET_SYSERR on failure
|
* @param cls a `struct LoadContext`, with 'ret' to be set to #GNUNET_SYSERR on failure
|
||||||
* @param denomination_alias name of the denomination's section in the configuration
|
* @param denomination_alias name of the denomination's section in the configuration
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
load_denominations (void *cls,
|
load_denominations (void *cls,
|
||||||
const char *denomination_alias)
|
const char *denomination_alias)
|
||||||
{
|
{
|
||||||
int *ret = cls;
|
struct LoadContext *ctx = cls;
|
||||||
struct Denomination *denom;
|
struct Denomination *denom;
|
||||||
|
|
||||||
if (0 != strncasecmp (denomination_alias,
|
if (0 != strncasecmp (denomination_alias,
|
||||||
@ -1632,7 +1656,7 @@ load_denominations (void *cls,
|
|||||||
parse_denomination_cfg (denomination_alias,
|
parse_denomination_cfg (denomination_alias,
|
||||||
denom))
|
denom))
|
||||||
{
|
{
|
||||||
*ret = GNUNET_SYSERR;
|
ctx->ret = GNUNET_SYSERR;
|
||||||
GNUNET_free (denom);
|
GNUNET_free (denom);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1656,7 +1680,8 @@ load_denominations (void *cls,
|
|||||||
GNUNET_CONTAINER_DLL_insert (denom_head,
|
GNUNET_CONTAINER_DLL_insert (denom_head,
|
||||||
denom_tail,
|
denom_tail,
|
||||||
denom);
|
denom);
|
||||||
update_keys (denom);
|
update_keys (denom,
|
||||||
|
ctx->now);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1905,13 +1930,16 @@ run (void *cls,
|
|||||||
keys = GNUNET_CONTAINER_multihashmap_create (65536,
|
keys = GNUNET_CONTAINER_multihashmap_create (65536,
|
||||||
GNUNET_YES);
|
GNUNET_YES);
|
||||||
{
|
{
|
||||||
int ok;
|
struct LoadContext lc = {
|
||||||
|
.ret = GNUNET_OK,
|
||||||
|
.now = GNUNET_TIME_absolute_get ()
|
||||||
|
};
|
||||||
|
|
||||||
ok = GNUNET_OK;
|
(void) GNUNET_TIME_round_abs (&lc.now);
|
||||||
GNUNET_CONFIGURATION_iterate_sections (kcfg,
|
GNUNET_CONFIGURATION_iterate_sections (kcfg,
|
||||||
&load_denominations,
|
&load_denominations,
|
||||||
&ok);
|
&lc);
|
||||||
if (GNUNET_OK != ok)
|
if (GNUNET_OK != lc.ret)
|
||||||
{
|
{
|
||||||
global_ret = 4;
|
global_ret = 4;
|
||||||
GNUNET_SCHEDULER_shutdown ();
|
GNUNET_SCHEDULER_shutdown ();
|
||||||
|
Loading…
Reference in New Issue
Block a user