Merge branch 'master' into age_restriction

This commit is contained in:
Özgür Kesim 2021-12-03 14:26:15 +01:00
commit 5104b43902
Signed by: oec
GPG Key ID: 3D76A56D79EDD9D7
20 changed files with 437 additions and 162 deletions

View File

@ -5,7 +5,8 @@ PartOf=taler-exchange.target
[Service] [Service]
User=taler-exchange-aggregator User=taler-exchange-aggregator
Type=simple Type=simple
Restart=on-failure Restart=always
RestartSec=100ms
ExecStart=/usr/bin/taler-exchange-aggregator -c /etc/taler/taler.conf ExecStart=/usr/bin/taler-exchange-aggregator -c /etc/taler/taler.conf
StandardOutput=journal StandardOutput=journal
StandardError=journal StandardError=journal

View File

@ -5,7 +5,8 @@ PartOf=taler-exchange.target
[Service] [Service]
User=taler-exchange-closer User=taler-exchange-closer
Type=simple Type=simple
Restart=on-failure Restart=always
RestartSec=100ms
ExecStart=/usr/bin/taler-exchange-closer -c /etc/taler/taler.conf ExecStart=/usr/bin/taler-exchange-closer -c /etc/taler/taler.conf
StandardOutput=journal StandardOutput=journal
StandardError=journal StandardError=journal

View File

@ -8,7 +8,11 @@ PartOf=taler-exchange.target
[Service] [Service]
User=taler-exchange-httpd User=taler-exchange-httpd
Type=simple Type=simple
Restart=on-failure # Depending on the configuration, the service suicides and then
# needs to be restarted.
Restart=always
# Do not dally on restarts.
RestartSec=1ms
ExecStart=/usr/bin/taler-exchange-httpd -c /etc/taler/taler.conf ExecStart=/usr/bin/taler-exchange-httpd -c /etc/taler/taler.conf
StandardOutput=journal StandardOutput=journal
StandardError=journal StandardError=journal

View File

@ -0,0 +1,26 @@
% This is a systemd service template.
[Unit]
Description=GNU Taler payment system exchange REST API at %I
AssertPathExists=/run/taler/exchange-httpd
Requires=taler-exchange-httpd@%i.socket taler-exchange-secmod-rsa.service taler-exchange-secmod-eddsa.service
After=postgres.service network.target taler-exchange-secmod-rsa.service taler-exchange-secmod-eddsa.service
PartOf=taler-exchange.target
[Service]
User=taler-exchange-httpd
Type=simple
# Depending on the configuration, the service suicides and then
# needs to be restarted.
Restart=always
# Do not dally on restarts.
RestartSec=1ms
EnvironmentFile=/etc/environment
ExecStart=/usr/bin/taler-exchange-httpd -c /etc/taler/taler.conf
StandardOutput=journal
StandardError=journal
PrivateTmp=no
PrivateDevices=yes
ProtectSystem=full
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,14 @@
[Unit]
Description=Taler Exchange Socket at %I
PartOf=taler-exchange-httpd@%i.service
[Socket]
ListenStream=80
Accept=no
Service=taler-exchange-httpd@%i.service
SocketUser=taler-exchange-httpd
SocketGroup=www-data
SocketMode=0660
[Install]
WantedBy=sockets.target

View File

@ -6,7 +6,8 @@ PartOf=taler-exchange.target
[Service] [Service]
User=taler-exchange-secmod-eddsa User=taler-exchange-secmod-eddsa
Type=simple Type=simple
Restart=on-failure Restart=always
RestartSec=100ms
ExecStart=/usr/bin/taler-exchange-secmod-eddsa -c /etc/taler/taler.conf ExecStart=/usr/bin/taler-exchange-secmod-eddsa -c /etc/taler/taler.conf
StandardOutput=journal StandardOutput=journal
StandardError=journal StandardError=journal

View File

@ -6,7 +6,8 @@ PartOf=taler-exchange.target
[Service] [Service]
User=taler-exchange-secmod-rsa User=taler-exchange-secmod-rsa
Type=simple Type=simple
Restart=on-failure Restart=always
RestartSec=100ms
ExecStart=/usr/bin/taler-exchange-secmod-rsa -c /etc/taler/taler.conf ExecStart=/usr/bin/taler-exchange-secmod-rsa -c /etc/taler/taler.conf
StandardOutput=journal StandardOutput=journal
StandardError=journal StandardError=journal

View File

@ -6,7 +6,8 @@ PartOf=taler-exchange.target
[Service] [Service]
User=taler-exchange-wire User=taler-exchange-wire
Type=simple Type=simple
Restart=on-failure Restart=always
RestartSec=100ms
ExecStart=/usr/bin/taler-exchange-transfer -c /etc/taler/taler.conf ExecStart=/usr/bin/taler-exchange-transfer -c /etc/taler/taler.conf
StandardOutput=journal StandardOutput=journal
StandardError=journal StandardError=journal

View File

@ -6,7 +6,8 @@ PartOf=taler-exchange.target
[Service] [Service]
User=taler-exchange-wire User=taler-exchange-wire
Type=simple Type=simple
Restart=on-failure Restart=always
RestartSec=100ms
ExecStart=/usr/bin/taler-exchange-wirewatch -c /etc/taler/taler.conf ExecStart=/usr/bin/taler-exchange-wirewatch -c /etc/taler/taler.conf
StandardOutput=journal StandardOutput=journal
StandardError=journal StandardError=journal

View File

@ -0,0 +1,16 @@
[Unit]
Description=GNU Taler payment system exchange wirewatch service
After=network.target
PartOf=taler-exchange.target
[Service]
User=taler-exchange-wire
Type=simple
Restart=always
RestartSec=100ms
ExecStart=/usr/bin/taler-exchange-wirewatch -c /etc/taler/taler.conf
StandardOutput=journal
StandardError=journal
PrivateTmp=yes
PrivateDevices=yes
ProtectSystem=full

View File

@ -40,6 +40,9 @@ PORT = 8081
# transfers to enable tracking. # transfers to enable tracking.
BASE_URL = http://localhost:8081/ BASE_URL = http://localhost:8081/
# Maximum number of requests this process should handle before
# committing suicide.
# MAX_REQUESTS =
# How long should the aggregator sleep if it has nothing to do? # How long should the aggregator sleep if it has nothing to do?
AGGREGATOR_IDLE_SLEEP_INTERVAL = 60 s AGGREGATOR_IDLE_SLEEP_INTERVAL = 60 s

View File

@ -76,6 +76,11 @@ static int allow_address_reuse;
*/ */
const struct GNUNET_CONFIGURATION_Handle *TEH_cfg; const struct GNUNET_CONFIGURATION_Handle *TEH_cfg;
/**
* Handle to the HTTP server.
*/
static struct MHD_Daemon *mhd;
/** /**
* Our KYC configuration. * Our KYC configuration.
*/ */
@ -122,6 +127,17 @@ static unsigned int connection_timeout = 30;
*/ */
static int connection_close; static int connection_close;
/**
* -I command-line flag given?
*/
int TEH_check_invariants_flag;
/**
* True if we should commit suicide once all active
* connections are finished.
*/
bool TEH_suicide;
/** /**
* Value to return from main() * Value to return from main()
*/ */
@ -137,6 +153,11 @@ static uint16_t serve_port;
*/ */
static unsigned long long req_count; static unsigned long long req_count;
/**
* Counter for the number of open connections.
*/
static unsigned long long active_connections;
/** /**
* Limit for the number of requests this HTTP may process before restarting. * Limit for the number of requests this HTTP may process before restarting.
* (This was added as one way of dealing with unavoidable memory fragmentation * (This was added as one way of dealing with unavoidable memory fragmentation
@ -262,6 +283,45 @@ handle_post_coins (struct TEH_RequestContext *rc,
} }
/**
* Increments our request counter and checks if this
* process should commit suicide.
*/
static void
check_suicide (void)
{
int fd;
pid_t chld;
unsigned long long cnt;
cnt = req_count++;
if (req_max != cnt)
return;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Restarting exchange service after %llu requests\n",
cnt);
/* Stop accepting new connections */
fd = MHD_quiesce_daemon (mhd);
GNUNET_break (0 == close (fd));
/* Continue handling existing connections in child,
so that this process can die and be replaced by
systemd with a fresh one */
chld = fork ();
if (-1 == chld)
{
GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
"fork");
_exit (1);
}
if (0 != chld)
{
/* We are the parent, instant-suicide! */
_exit (0);
}
TEH_suicide = true;
}
/** /**
* Function called whenever MHD is done with a request. If the * Function called whenever MHD is done with a request. If the
* request was a POST, we may have stored a `struct Buffer *` in the * request was a POST, we may have stored a `struct Buffer *` in the
@ -290,6 +350,7 @@ handle_mhd_completion_callback (void *cls,
return; return;
GNUNET_async_scope_enter (&rc->async_scope_id, GNUNET_async_scope_enter (&rc->async_scope_id,
&old_scope); &old_scope);
check_suicide ();
TEH_check_invariants (); TEH_check_invariants ();
if (NULL != rc->rh_cleaner) if (NULL != rc->rh_cleaner)
rc->rh_cleaner (rc); rc->rh_cleaner (rc);
@ -1642,8 +1703,19 @@ connection_done (void *cls,
(void) cls; (void) cls;
(void) connection; (void) connection;
(void) socket_context; (void) socket_context;
unsigned long long cnt;
switch (toe)
{
case MHD_CONNECTION_NOTIFY_STARTED:
active_connections++;
break;
case MHD_CONNECTION_NOTIFY_CLOSED:
active_connections--;
if (TEH_suicide &&
(0 == active_connections) )
GNUNET_SCHEDULER_shutdown ();
break;
}
#if HAVE_DEVELOPER #if HAVE_DEVELOPER
/* We only act if the connection is closed. */ /* We only act if the connection is closed. */
if (MHD_CONNECTION_NOTIFY_CLOSED != toe) if (MHD_CONNECTION_NOTIFY_CLOSED != toe)
@ -1651,15 +1723,6 @@ connection_done (void *cls,
if (NULL != input_filename) if (NULL != input_filename)
GNUNET_SCHEDULER_shutdown (); GNUNET_SCHEDULER_shutdown ();
#endif #endif
cnt = req_count++;
if (req_max == cnt)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Restarting exchange service after %llu requests\n",
cnt);
(void) kill (getpid (),
SIGTERM);
}
} }
@ -1780,9 +1843,6 @@ run (void *cls,
GNUNET_SCHEDULER_shutdown (); GNUNET_SCHEDULER_shutdown ();
return; return;
} }
{
struct MHD_Daemon *mhd;
mhd = MHD_start_daemon (MHD_USE_SUSPEND_RESUME mhd = MHD_start_daemon (MHD_USE_SUSPEND_RESUME
| MHD_USE_PIPE_FOR_SHUTDOWN | MHD_USE_PIPE_FOR_SHUTDOWN
| MHD_USE_DEBUG | MHD_USE_DUAL_STACK | MHD_USE_DEBUG | MHD_USE_DUAL_STACK
@ -1819,7 +1879,6 @@ run (void *cls,
} }
global_ret = EXIT_SUCCESS; global_ret = EXIT_SUCCESS;
TALER_MHD_daemon_start (mhd); TALER_MHD_daemon_start (mhd);
}
atexit (&write_stats); atexit (&write_stats);
#if HAVE_DEVELOPER #if HAVE_DEVELOPER
@ -1849,6 +1908,10 @@ main (int argc,
"connection-close", "connection-close",
"force HTTP connections to be closed after each request", "force HTTP connections to be closed after each request",
&connection_close), &connection_close),
GNUNET_GETOPT_option_flag ('I',
"check-invariants",
"enable expensive invariant checks",
&TEH_check_invariants_flag),
GNUNET_GETOPT_option_flag ('r', GNUNET_GETOPT_option_flag ('r',
"allow-reuse-address", "allow-reuse-address",
"allow multiple HTTPDs to listen to the same port", "allow multiple HTTPDs to listen to the same port",

View File

@ -144,6 +144,11 @@ extern const struct GNUNET_CONFIGURATION_Handle *TEH_cfg;
*/ */
extern char *TEH_exchange_directory; extern char *TEH_exchange_directory;
/**
* -I command-line flag given?
*/
extern int TEH_check_invariants_flag;
/** /**
* Are clients allowed to request /keys for times other than the * Are clients allowed to request /keys for times other than the
* current time? Allowing this could be abused in a DoS-attack * current time? Allowing this could be abused in a DoS-attack
@ -157,6 +162,13 @@ extern int TEH_allow_keys_timetravel;
*/ */
extern char *TEH_revocation_directory; extern char *TEH_revocation_directory;
/**
* True if we should commit suicide once all active
* connections are finished. Also forces /keys requests
* to terminate if they are long-polling.
*/
extern bool TEH_suicide;
/** /**
* Master public key (according to the * Master public key (according to the
* configuration in the exchange directory). * configuration in the exchange directory).

View File

@ -36,6 +36,12 @@
#define SKR_LIMIT 32 #define SKR_LIMIT 32
/**
* When do we forcefully timeout a /keys request?
*/
#define KEYS_TIMEOUT GNUNET_TIME_UNIT_MINUTES
/** /**
* Taler protocol version in the format CURRENT:REVISION:AGE * Taler protocol version in the format CURRENT:REVISION:AGE
* as used by GNU libtool. See * as used by GNU libtool. See
@ -355,6 +361,11 @@ struct SuspendedKeysRequests
* The suspended connection. * The suspended connection.
*/ */
struct MHD_Connection *connection; struct MHD_Connection *connection;
/**
* When does this request timeout?
*/
struct GNUNET_TIME_Absolute timeout;
}; };
@ -398,6 +409,11 @@ static unsigned int skr_size;
*/ */
static struct MHD_Connection *skr_connection; static struct MHD_Connection *skr_connection;
/**
* Task to force timeouts on /keys requests.
*/
static struct GNUNET_SCHEDULER_Task *keys_tt;
/** /**
* For how long should a signing key be legally retained? * For how long should a signing key be legally retained?
* Configuration value. * Configuration value.
@ -419,6 +435,40 @@ static struct TALER_SecurityModulePublicKeyP esign_sm_pub;
*/ */
static bool terminating; static bool terminating;
/**
* Function called to forcefully resume suspended keys requests.
*
* @param cls unused, NULL
*/
static void
keys_timeout_cb (void *cls)
{
struct SuspendedKeysRequests *skr;
(void) cls;
keys_tt = NULL;
while (NULL != (skr = skr_head))
{
if (GNUNET_TIME_absolute_is_future (skr->timeout))
break;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Resuming /keys request due to timeout\n");
GNUNET_CONTAINER_DLL_remove (skr_head,
skr_tail,
skr);
MHD_resume_connection (skr->connection);
TALER_MHD_daemon_trigger ();
GNUNET_free (skr);
}
if (NULL == skr)
return;
keys_tt = GNUNET_SCHEDULER_add_at (skr->timeout,
&keys_timeout_cb,
NULL);
}
/** /**
* Suspend /keys request while we (hopefully) are waiting to be * Suspend /keys request while we (hopefully) are waiting to be
* provisioned with key material. * provisioned with key material.
@ -445,6 +495,13 @@ suspend_request (struct MHD_Connection *connection)
GNUNET_CONTAINER_DLL_insert (skr_head, GNUNET_CONTAINER_DLL_insert (skr_head,
skr_tail, skr_tail,
skr); skr);
skr->timeout = GNUNET_TIME_relative_to_absolute (KEYS_TIMEOUT);
if (NULL == keys_tt)
{
keys_tt = GNUNET_SCHEDULER_add_at (skr->timeout,
&keys_timeout_cb,
NULL);
}
skr_size++; skr_size++;
if (skr_size > SKR_LIMIT) if (skr_size > SKR_LIMIT)
{ {
@ -477,9 +534,8 @@ check_dk (void *cls,
{ {
struct TEH_DenominationKey *dk = value; struct TEH_DenominationKey *dk = value;
(void) cls;
(void) hc; (void) hc;
(void) value;
GNUNET_assert (TALER_DENOMINATION_INVALID != dk->denom_pub.cipher); GNUNET_assert (TALER_DENOMINATION_INVALID != dk->denom_pub.cipher);
if (TALER_DENOMINATION_RSA == dk->denom_pub.cipher) if (TALER_DENOMINATION_RSA == dk->denom_pub.cipher)
GNUNET_assert (GNUNET_CRYPTO_rsa_public_key_check ( GNUNET_assert (GNUNET_CRYPTO_rsa_public_key_check (
@ -493,6 +549,8 @@ TEH_check_invariants ()
{ {
struct TEH_KeyStateHandle *ksh; struct TEH_KeyStateHandle *ksh;
if (0 == TEH_check_invariants_flag)
return;
ksh = TEH_keys_get_state (); ksh = TEH_keys_get_state ();
if (NULL == ksh) if (NULL == ksh)
return; return;
@ -1073,6 +1131,11 @@ TEH_keys_init ()
void void
TEH_keys_finished () TEH_keys_finished ()
{ {
if (NULL != keys_tt)
{
GNUNET_SCHEDULER_cancel (keys_tt);
keys_tt = NULL;
}
if (NULL != key_state) if (NULL != key_state)
destroy_key_state (key_state, destroy_key_state (key_state,
true); true);
@ -2282,13 +2345,17 @@ TEH_keys_get_handler (struct TEH_RequestContext *rc,
ksh = TEH_keys_get_state (); ksh = TEH_keys_get_state ();
if (NULL == ksh) if (NULL == ksh)
{ {
if ( (SKR_LIMIT == skr_size) && if ( ( (SKR_LIMIT == skr_size) &&
(rc->connection == skr_connection) ) (rc->connection == skr_connection) ) ||
TEH_suicide)
{ {
return TALER_MHD_reply_with_error (rc->connection, return TALER_MHD_reply_with_error (
MHD_HTTP_INTERNAL_SERVER_ERROR, rc->connection,
MHD_HTTP_SERVICE_UNAVAILABLE,
TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING, TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
"too many connections suspended on /keys"); TEH_suicide
? "server terminating"
: "too many connections suspended waiting on /keys");
} }
return suspend_request (rc->connection); return suspend_request (rc->connection);
} }
@ -2688,7 +2755,7 @@ TEH_keys_management_get_keys_handler (const struct TEH_RequestHandler *rh,
if (NULL == ksh) if (NULL == ksh)
{ {
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR, MHD_HTTP_SERVICE_UNAVAILABLE,
TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING, TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
"no key state"); "no key state");
} }

View File

@ -271,6 +271,7 @@ refreshes_reveal_transaction (void *cls,
/* Obtain basic information about the refresh operation and what /* Obtain basic information about the refresh operation and what
gamma we committed to. */ gamma we committed to. */
// FIXME: why do we do 'get_melt' twice?
qs = TEH_plugin->get_melt (TEH_plugin->cls, qs = TEH_plugin->get_melt (TEH_plugin->cls,
&rctx->rc, &rctx->rc,
&melt); &melt);
@ -611,6 +612,7 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
{ {
enum GNUNET_DB_QueryStatus qs; enum GNUNET_DB_QueryStatus qs;
// FIXME: why do we do 'get_melt' twice?
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
(qs = TEH_plugin->get_melt (TEH_plugin->cls, (qs = TEH_plugin->get_melt (TEH_plugin->cls,
&rctx->rc, &rctx->rc,
@ -682,9 +684,13 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
rctx->dks = dks; rctx->dks = dks;
rctx->link_sigs = link_sigs; rctx->link_sigs = link_sigs;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Optimistically creating %u signatures\n",
(unsigned int) rctx->num_fresh_coins);
/* sign _early_ (optimistic!) to keep out of transaction scope! */ /* sign _early_ (optimistic!) to keep out of transaction scope! */
rctx->ev_sigs = GNUNET_new_array (rctx->num_fresh_coins, rctx->ev_sigs = GNUNET_new_array (rctx->num_fresh_coins,
struct TALER_BlindedDenominationSignature); struct TALER_BlindedDenominationSignature);
// FIXME: this is sequential, modify logic to enable parallel signing!
for (unsigned int i = 0; i<rctx->num_fresh_coins; i++) for (unsigned int i = 0; i<rctx->num_fresh_coins; i++)
{ {
enum TALER_ErrorCode ec = TALER_EC_NONE; enum TALER_ErrorCode ec = TALER_EC_NONE;
@ -705,6 +711,8 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
} }
} }
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Signatures ready, starting DB interaction\n");
/* We try the three transactions a few times, as theoretically /* We try the three transactions a few times, as theoretically
the pre-check might be satisfied by a concurrent transaction the pre-check might be satisfied by a concurrent transaction
voiding our final commit due to uniqueness violation; naturally, voiding our final commit due to uniqueness violation; naturally,

View File

@ -37,6 +37,11 @@ struct AuthchangeState
* What is the new authorization token to send? * What is the new authorization token to send?
*/ */
const char *auth_token; const char *auth_token;
/**
* Old context, clean up on termination.
*/
struct GNUNET_CURL_Context *old_ctx;
}; };
@ -55,11 +60,7 @@ authchange_run (void *cls,
struct AuthchangeState *ss = cls; struct AuthchangeState *ss = cls;
(void) cmd; (void) cmd;
if (NULL != is->ctx) ss->old_ctx = is->ctx;
{
GNUNET_CURL_fini (is->ctx);
is->ctx = NULL;
}
if (NULL != is->rc) if (NULL != is->rc)
{ {
GNUNET_CURL_gnunet_rc_destroy (is->rc); GNUNET_CURL_gnunet_rc_destroy (is->rc);
@ -101,6 +102,11 @@ authchange_cleanup (void *cls,
struct AuthchangeState *ss = cls; struct AuthchangeState *ss = cls;
(void) cmd; (void) cmd;
if (NULL != ss->old_ctx)
{
GNUNET_CURL_fini (ss->old_ctx);
ss->old_ctx = NULL;
}
GNUNET_free (ss); GNUNET_free (ss);
} }

View File

@ -42,10 +42,10 @@ TALER_mhd_is_https (struct MHD_Connection *connection)
if (NULL != forwarded_proto) if (NULL != forwarded_proto)
{ {
if (0 == strcmp (forwarded_proto, if (0 == strcasecmp (forwarded_proto,
"https")) "https"))
return GNUNET_YES; return GNUNET_YES;
if (0 == strcmp (forwarded_proto, if (0 == strcasecmp (forwarded_proto,
"http")) "http"))
return GNUNET_NO; return GNUNET_NO;
GNUNET_break (0); GNUNET_break (0);

View File

@ -74,17 +74,15 @@ static volatile bool in_shutdown;
enum GNUNET_GenericReturnValue enum GNUNET_GenericReturnValue
TES_transmit (int sock, TES_transmit_raw (int sock,
const struct GNUNET_MessageHeader *hdr) size_t end,
const void *pos)
{ {
ssize_t off = 0; ssize_t off = 0;
const void *pos = hdr;
uint16_t end = ntohs (hdr->size);
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Sending message of type %u and length %u\n", "Sending message of length %u\n",
(unsigned int) ntohs (hdr->type), (unsigned int) end);
(unsigned int) ntohs (hdr->size));
while (off < end) while (off < end)
{ {
ssize_t ret = send (sock, ssize_t ret = send (sock,
@ -118,6 +116,20 @@ TES_transmit (int sock,
} }
enum GNUNET_GenericReturnValue
TES_transmit (int sock,
const struct GNUNET_MessageHeader *hdr)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Sending message of type %u and length %u\n",
(unsigned int) ntohs (hdr->type),
(unsigned int) ntohs (hdr->size));
return TES_transmit_raw (sock,
ntohs (hdr->size),
hdr);
}
struct GNUNET_NETWORK_Handle * struct GNUNET_NETWORK_Handle *
TES_open_socket (const char *unixpath) TES_open_socket (const char *unixpath)
{ {

View File

@ -51,6 +51,19 @@ TES_transmit (int sock,
const struct GNUNET_MessageHeader *hdr); const struct GNUNET_MessageHeader *hdr);
/**
* Transmit @a end bytes from @a pos on @a sock.
*
* @param sock where to send the data
* @param end how many bytes to send
* @param pos first address with data
* @return #GNUNET_OK on success
*/
enum GNUNET_GenericReturnValue
TES_transmit_raw (int sock,
size_t end,
const void *pos);
/** /**
* Information we keep for a client connected to us. * Information we keep for a client connected to us.
*/ */

View File

@ -85,6 +85,11 @@ struct DenominationKey
*/ */
struct GNUNET_CRYPTO_RsaPublicKey *denom_pub; struct GNUNET_CRYPTO_RsaPublicKey *denom_pub;
/**
* Message to transmit to clients to introduce this public key.
*/
struct TALER_CRYPTO_RsaKeyAvailableNotification *an;
/** /**
* Hash of this denomination's public key. * Hash of this denomination's public key.
*/ */
@ -214,7 +219,6 @@ static struct GNUNET_CONTAINER_MultiHashMap *keys;
*/ */
static struct GNUNET_SCHEDULER_Task *keygen_task; static struct GNUNET_SCHEDULER_Task *keygen_task;
/** /**
* Lock for the keys queue. * Lock for the keys queue.
*/ */
@ -227,15 +231,12 @@ static uint64_t key_gen;
/** /**
* Notify @a client about @a dk becoming available. * Generate the announcement message for @a dk.
* *
* @param[in,out] client the client to notify; possible freed if transmission fails * @param[in,out] denomination key to generate the announcement for
* @param dk the key to notify @a client about
* @return #GNUNET_OK on success
*/ */
static enum GNUNET_GenericReturnValue static void
notify_client_dk_add (struct TES_Client *client, generate_response (struct DenominationKey *dk)
const struct DenominationKey *dk)
{ {
struct Denomination *denom = dk->denom; struct Denomination *denom = dk->denom;
size_t nlen = strlen (denom->section) + 1; size_t nlen = strlen (denom->section) + 1;
@ -273,55 +274,7 @@ notify_client_dk_add (struct TES_Client *client,
memcpy (p + buf_len, memcpy (p + buf_len,
denom->section, denom->section,
nlen); nlen);
GNUNET_log (GNUNET_ERROR_TYPE_INFO, dk->an = an;
"Sending RSA denomination key %s (%s)\n",
GNUNET_h2s (&dk->h_rsa.hash),
denom->section);
if (GNUNET_OK !=
TES_transmit (client->csock,
&an->header))
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Client %p must have disconnected\n",
client);
GNUNET_free (an);
return GNUNET_SYSERR;
}
GNUNET_free (an);
return GNUNET_OK;
}
/**
* Notify @a client about @a dk being purged.
*
* @param[in,out] client the client to notify; possible freed if transmission fails
* @param dk the key to notify @a client about
* @return #GNUNET_OK on success
*/
static enum GNUNET_GenericReturnValue
notify_client_dk_del (struct TES_Client *client,
const struct DenominationKey *dk)
{
struct TALER_CRYPTO_RsaKeyPurgeNotification pn = {
.header.type = htons (TALER_HELPER_RSA_MT_PURGE),
.header.size = htons (sizeof (pn)),
.h_rsa = dk->h_rsa
};
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Sending RSA denomination expiration %s\n",
GNUNET_h2s (&dk->h_rsa.hash));
if (GNUNET_OK !=
TES_transmit (client->csock,
&pn.header))
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Client %p must have disconnected\n",
client);
return GNUNET_SYSERR;
}
return GNUNET_OK;
} }
@ -342,6 +295,7 @@ handle_sign_request (struct TES_Client *client,
const void *blinded_msg = &sr[1]; const void *blinded_msg = &sr[1];
size_t blinded_msg_size = ntohs (sr->header.size) - sizeof (*sr); size_t blinded_msg_size = ntohs (sr->header.size) - sizeof (*sr);
struct GNUNET_CRYPTO_RsaSignature *rsa_signature; struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
GNUNET_assert (0 == pthread_mutex_lock (&keys_lock)); GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
dk = GNUNET_CONTAINER_multihashmap_get (keys, dk = GNUNET_CONTAINER_multihashmap_get (keys,
@ -407,6 +361,7 @@ handle_sign_request (struct TES_Client *client,
return TES_transmit (client->csock, return TES_transmit (client->csock,
&sf.header); &sf.header);
} }
{ {
struct TALER_CRYPTO_SignResponse *sr; struct TALER_CRYPTO_SignResponse *sr;
void *buf; void *buf;
@ -427,7 +382,10 @@ handle_sign_request (struct TES_Client *client,
buf_size); buf_size);
GNUNET_free (buf); GNUNET_free (buf);
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Sending RSA signature\n"); "Sending RSA signature after %s\n",
GNUNET_STRINGS_relative_time_to_string (
GNUNET_TIME_absolute_get_duration (now),
GNUNET_YES));
ret = TES_transmit (client->csock, ret = TES_transmit (client->csock,
&sr->header); &sr->header);
GNUNET_free (sr); GNUNET_free (sr);
@ -502,6 +460,7 @@ setup_key (struct DenominationKey *dk,
dk->denom_priv = priv; dk->denom_priv = priv;
dk->denom_pub = pub; dk->denom_pub = pub;
dk->key_gen = key_gen; dk->key_gen = key_gen;
generate_response (dk);
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_CONTAINER_multihashmap_put ( GNUNET_CONTAINER_multihashmap_put (
keys, keys,
@ -514,6 +473,7 @@ setup_key (struct DenominationKey *dk,
GNUNET_CRYPTO_rsa_private_key_free (dk->denom_priv); GNUNET_CRYPTO_rsa_private_key_free (dk->denom_priv);
GNUNET_CRYPTO_rsa_public_key_free (dk->denom_pub); GNUNET_CRYPTO_rsa_public_key_free (dk->denom_pub);
GNUNET_free (dk->filename); GNUNET_free (dk->filename);
GNUNET_free (dk->an);
GNUNET_free (dk); GNUNET_free (dk);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
@ -660,6 +620,12 @@ rsa_work_dispatch (struct TES_Client *client,
static enum GNUNET_GenericReturnValue static enum GNUNET_GenericReturnValue
rsa_client_init (struct TES_Client *client) rsa_client_init (struct TES_Client *client)
{ {
size_t obs = 0;
char *buf;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Initializing new client %p\n",
client);
GNUNET_assert (0 == pthread_mutex_lock (&keys_lock)); GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
for (struct Denomination *denom = denom_head; for (struct Denomination *denom = denom_head;
NULL != denom; NULL != denom;
@ -669,20 +635,39 @@ rsa_client_init (struct TES_Client *client)
NULL != dk; NULL != dk;
dk = dk->next) dk = dk->next)
{ {
if (GNUNET_OK != obs += ntohs (dk->an->header.size);
notify_client_dk_add (client, }
dk)) }
buf = GNUNET_malloc (obs);
obs = 0;
for (struct Denomination *denom = denom_head;
NULL != denom;
denom = denom->next)
{ {
for (struct DenominationKey *dk = denom->keys_head;
NULL != dk;
dk = dk->next)
{
memcpy (&buf[obs],
dk->an,
ntohs (dk->an->header.size));
obs += ntohs (dk->an->header.size);
}
}
client->key_gen = key_gen;
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock)); GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
if (GNUNET_OK !=
TES_transmit_raw (client->csock,
obs,
buf))
{
GNUNET_free (buf);
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Client %p must have disconnected\n", "Client %p must have disconnected\n",
client); client);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
} GNUNET_free (buf);
}
client->key_gen = key_gen;
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
{ {
struct GNUNET_MessageHeader synced = { struct GNUNET_MessageHeader synced = {
.type = htons (TALER_HELPER_RSA_SYNCED), .type = htons (TALER_HELPER_RSA_SYNCED),
@ -714,6 +699,10 @@ rsa_client_init (struct TES_Client *client)
static enum GNUNET_GenericReturnValue static enum GNUNET_GenericReturnValue
rsa_update_client_keys (struct TES_Client *client) rsa_update_client_keys (struct TES_Client *client)
{ {
size_t obs = 0;
char *buf;
enum GNUNET_GenericReturnValue ret;
GNUNET_assert (0 == pthread_mutex_lock (&keys_lock)); GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
for (struct Denomination *denom = denom_head; for (struct Denomination *denom = denom_head;
NULL != denom; NULL != denom;
@ -726,30 +715,59 @@ rsa_update_client_keys (struct TES_Client *client)
if (key->key_gen <= client->key_gen) if (key->key_gen <= client->key_gen)
continue; continue;
if (key->purge) if (key->purge)
{ obs += sizeof (struct TALER_CRYPTO_RsaKeyPurgeNotification);
if (GNUNET_OK != else
notify_client_dk_del (client, obs += ntohs (key->an->header.size);
key))
{
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
return GNUNET_SYSERR;
} }
} }
if (0 == obs)
{
/* nothing to do */
client->key_gen = key_gen;
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
return GNUNET_OK;
}
buf = GNUNET_malloc (obs);
obs = 0;
for (struct Denomination *denom = denom_head;
NULL != denom;
denom = denom->next)
{
for (struct DenominationKey *key = denom->keys_head;
NULL != key;
key = key->next)
{
if (key->key_gen <= client->key_gen)
continue;
if (key->purge)
{
struct TALER_CRYPTO_RsaKeyPurgeNotification pn = {
.header.type = htons (TALER_HELPER_RSA_MT_PURGE),
.header.size = htons (sizeof (pn)),
.h_rsa = key->h_rsa
};
memcpy (&buf[obs],
&pn,
sizeof (pn));
obs += sizeof (pn);
}
else else
{ {
if (GNUNET_OK != memcpy (&buf[obs],
notify_client_dk_add (client, key->an,
key)) ntohs (key->an->header.size));
{ obs += ntohs (key->an->header.size);
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
return GNUNET_SYSERR;
}
} }
} }
} }
client->key_gen = key_gen; client->key_gen = key_gen;
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock)); GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
return GNUNET_OK; ret = TES_transmit_raw (client->csock,
obs,
buf);
GNUNET_free (buf);
return ret;
} }
@ -896,6 +914,7 @@ update_keys (struct Denomination *denom,
GNUNET_free (key->filename); GNUNET_free (key->filename);
GNUNET_CRYPTO_rsa_private_key_free (key->denom_priv); GNUNET_CRYPTO_rsa_private_key_free (key->denom_priv);
GNUNET_CRYPTO_rsa_public_key_free (key->denom_pub); GNUNET_CRYPTO_rsa_public_key_free (key->denom_pub);
GNUNET_free (key->an);
GNUNET_free (key); GNUNET_free (key);
key = nxt; key = nxt;
} }
@ -943,6 +962,8 @@ update_denominations (void *cls)
keygen_task = NULL; keygen_task = NULL;
now = GNUNET_TIME_absolute_get (); now = GNUNET_TIME_absolute_get ();
(void) GNUNET_TIME_round_abs (&now); (void) GNUNET_TIME_round_abs (&now);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Updating denominations ...\n");
GNUNET_assert (0 == pthread_mutex_lock (&keys_lock)); GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
do { do {
denom = denom_head; denom = denom_head;
@ -953,6 +974,8 @@ update_denominations (void *cls)
return; return;
} while (denom != denom_head); } while (denom != denom_head);
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock)); GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Updating denominations finished ...\n");
if (wake) if (wake)
TES_wake_clients (); TES_wake_clients ();
keygen_task = GNUNET_SCHEDULER_add_at (denomination_action_time (denom), keygen_task = GNUNET_SCHEDULER_add_at (denomination_action_time (denom),
@ -1041,6 +1064,7 @@ parse_key (struct Denomination *denom,
TALER_rsa_pub_hash (pub, TALER_rsa_pub_hash (pub,
&dk->h_rsa); &dk->h_rsa);
dk->denom_pub = pub; dk->denom_pub = pub;
generate_response (dk);
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_CONTAINER_multihashmap_put ( GNUNET_CONTAINER_multihashmap_put (
keys, keys,
@ -1054,6 +1078,7 @@ parse_key (struct Denomination *denom,
filename); filename);
GNUNET_CRYPTO_rsa_private_key_free (priv); GNUNET_CRYPTO_rsa_private_key_free (priv);
GNUNET_CRYPTO_rsa_public_key_free (pub); GNUNET_CRYPTO_rsa_public_key_free (pub);
GNUNET_free (dk->an);
GNUNET_free (dk); GNUNET_free (dk);
return; return;
} }