implement auditor's exchange signing key caching (#6052)
This commit is contained in:
parent
b332604325
commit
9e0a813b38
@ -594,7 +594,7 @@ main (int argc,
|
|||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
auditor_serve_process_config ())
|
auditor_serve_process_config ())
|
||||||
return 1;
|
return 1;
|
||||||
|
TEAH_DEPOSIT_CONFIRMATION_init ();
|
||||||
/* check for systemd-style FD passing */
|
/* check for systemd-style FD passing */
|
||||||
listen_pid = getenv ("LISTEN_PID");
|
listen_pid = getenv ("LISTEN_PID");
|
||||||
listen_fds = getenv ("LISTEN_FDS");
|
listen_fds = getenv ("LISTEN_FDS");
|
||||||
@ -635,8 +635,11 @@ main (int argc,
|
|||||||
fh = TALER_MHD_open_unix_path (serve_unixpath,
|
fh = TALER_MHD_open_unix_path (serve_unixpath,
|
||||||
unixpath_mode);
|
unixpath_mode);
|
||||||
if (-1 == fh)
|
if (-1 == fh)
|
||||||
|
{
|
||||||
|
TEAH_DEPOSIT_CONFIRMATION_done ();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mhd
|
mhd
|
||||||
= MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_PIPE_FOR_SHUTDOWN
|
= MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_PIPE_FOR_SHUTDOWN
|
||||||
@ -659,6 +662,7 @@ main (int argc,
|
|||||||
{
|
{
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
"Failed to start HTTP server.\n");
|
"Failed to start HTTP server.\n");
|
||||||
|
TEAH_DEPOSIT_CONFIRMATION_done ();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -732,6 +736,7 @@ main (int argc,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
TALER_AUDITORDB_plugin_unload (TAH_plugin);
|
TALER_AUDITORDB_plugin_unload (TAH_plugin);
|
||||||
|
TEAH_DEPOSIT_CONFIRMATION_done ();
|
||||||
return (GNUNET_SYSERR == ret) ? 1 : 0;
|
return (GNUNET_SYSERR == ret) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,19 @@
|
|||||||
#include "taler-auditor-httpd_deposit-confirmation.h"
|
#include "taler-auditor-httpd_deposit-confirmation.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache of already verified exchange signing keys. Maps the hash of the
|
||||||
|
* `struct TALER_ExchangeSigningKeyValidityPS` to the (static) string
|
||||||
|
* "verified". Access to this map is guarded by the #lock.
|
||||||
|
*/
|
||||||
|
static struct GNUNET_CONTAINER_MultiHashMap *cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lock for operations on #cache.
|
||||||
|
*/
|
||||||
|
static pthread_mutex_t lock;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We have parsed the JSON information about the deposit, do some
|
* We have parsed the JSON information about the deposit, do some
|
||||||
* basic sanity checks (especially that the signature on the coin is
|
* basic sanity checks (especially that the signature on the coin is
|
||||||
@ -55,6 +68,8 @@ verify_and_execute_deposit_confirmation (struct MHD_Connection *connection,
|
|||||||
struct TALER_AUDITORDB_Session *session;
|
struct TALER_AUDITORDB_Session *session;
|
||||||
enum GNUNET_DB_QueryStatus qs;
|
enum GNUNET_DB_QueryStatus qs;
|
||||||
struct GNUNET_TIME_Absolute now;
|
struct GNUNET_TIME_Absolute now;
|
||||||
|
struct GNUNET_HashCode h;
|
||||||
|
int cached;
|
||||||
|
|
||||||
now = GNUNET_TIME_absolute_get ();
|
now = GNUNET_TIME_absolute_get ();
|
||||||
if ( (es->ep_start.abs_value_us > now.abs_value_us) ||
|
if ( (es->ep_start.abs_value_us > now.abs_value_us) ||
|
||||||
@ -68,10 +83,6 @@ verify_and_execute_deposit_confirmation (struct MHD_Connection *connection,
|
|||||||
"master_sig (expired)");
|
"master_sig (expired)");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO (#6052): consider having an in-memory cache of already
|
|
||||||
verified exchange signing keys, this could save us
|
|
||||||
a signature check AND a database transaction per
|
|
||||||
operation. */
|
|
||||||
/* check exchange signing key signature */
|
/* check exchange signing key signature */
|
||||||
skv.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY);
|
skv.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY);
|
||||||
skv.purpose.size = htonl (sizeof (struct TALER_ExchangeSigningKeyValidityPS));
|
skv.purpose.size = htonl (sizeof (struct TALER_ExchangeSigningKeyValidityPS));
|
||||||
@ -80,6 +91,19 @@ verify_and_execute_deposit_confirmation (struct MHD_Connection *connection,
|
|||||||
skv.expire = GNUNET_TIME_absolute_hton (es->ep_expire);
|
skv.expire = GNUNET_TIME_absolute_hton (es->ep_expire);
|
||||||
skv.end = GNUNET_TIME_absolute_hton (es->ep_end);
|
skv.end = GNUNET_TIME_absolute_hton (es->ep_end);
|
||||||
skv.signkey_pub = es->exchange_pub;
|
skv.signkey_pub = es->exchange_pub;
|
||||||
|
|
||||||
|
/* check our cache */
|
||||||
|
GNUNET_CRYPTO_hash (&skv,
|
||||||
|
sizeof (skv),
|
||||||
|
&h);
|
||||||
|
GNUNET_assert (0 == pthread_mutex_lock (&lock));
|
||||||
|
cached = GNUNET_CONTAINER_multihashmap_contains (cache,
|
||||||
|
&h);
|
||||||
|
GNUNET_assert (0 == pthread_mutex_unlock (&lock));
|
||||||
|
|
||||||
|
if (! cached)
|
||||||
|
{
|
||||||
|
/* Not in cache, need to verify the signature, persist it, and possibly cache it */
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY,
|
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY,
|
||||||
&skv.purpose,
|
&skv.purpose,
|
||||||
@ -116,6 +140,17 @@ verify_and_execute_deposit_confirmation (struct MHD_Connection *connection,
|
|||||||
"failed to persist exchange signing key");
|
"failed to persist exchange signing key");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Cache it, due to concurreny it might already be in the cache,
|
||||||
|
so we do not cache it twice but also don't insist on the 'put' to
|
||||||
|
succeed. */
|
||||||
|
GNUNET_assert (0 == pthread_mutex_lock (&lock));
|
||||||
|
(void) GNUNET_CONTAINER_multihashmap_put (cache,
|
||||||
|
&h,
|
||||||
|
"verified",
|
||||||
|
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
|
||||||
|
GNUNET_assert (0 == pthread_mutex_unlock (&lock));
|
||||||
|
}
|
||||||
|
|
||||||
/* check deposit confirmation signature */
|
/* check deposit confirmation signature */
|
||||||
dcs.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT);
|
dcs.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT);
|
||||||
dcs.purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS));
|
dcs.purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS));
|
||||||
@ -237,4 +272,28 @@ TAH_DEPOSIT_CONFIRMATION_handler (struct TAH_RequestHandler *rh,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize subsystem.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
TEAH_DEPOSIT_CONFIRMATION_init (void)
|
||||||
|
{
|
||||||
|
cache = GNUNET_CONTAINER_multihashmap_create (32,
|
||||||
|
GNUNET_NO);
|
||||||
|
GNUNET_assert (0 == pthread_mutex_init (&lock, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shut down subsystem.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
TEAH_DEPOSIT_CONFIRMATION_done (void)
|
||||||
|
{
|
||||||
|
GNUNET_CONTAINER_multihashmap_destroy (cache);
|
||||||
|
cache = NULL;
|
||||||
|
GNUNET_assert (0 == pthread_mutex_destroy (&lock));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* end of taler-auditor-httpd_deposit-confirmation.c */
|
/* end of taler-auditor-httpd_deposit-confirmation.c */
|
||||||
|
@ -25,6 +25,18 @@
|
|||||||
#include <microhttpd.h>
|
#include <microhttpd.h>
|
||||||
#include "taler-auditor-httpd.h"
|
#include "taler-auditor-httpd.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize subsystem.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
TEAH_DEPOSIT_CONFIRMATION_init (void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shut down subsystem.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
TEAH_DEPOSIT_CONFIRMATION_done (void);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a "/deposit-confirmation" request. Parses the JSON, and, if
|
* Handle a "/deposit-confirmation" request. Parses the JSON, and, if
|
||||||
|
Loading…
Reference in New Issue
Block a user