aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2020-11-22 18:31:33 +0100
committerChristian Grothoff <christian@grothoff.org>2020-11-22 18:31:33 +0100
commita9fb94e916ba6084997571f03fd6c2b4d557576b (patch)
treebe306998212283fa32591308a583bb189c195b22
parent9b68dbb8e6c873ff40c00da85b3a9f709afd42e1 (diff)
start with testing crypto rsa helper
-rw-r--r--src/util/.gitignore1
-rw-r--r--src/util/Makefile.am14
-rw-r--r--src/util/crypto_helper.c161
-rw-r--r--src/util/taler-helper-crypto-rsa.c368
-rw-r--r--src/util/taler-helper-crypto-rsa.h9
-rw-r--r--src/util/test_helper_rsa.c314
-rw-r--r--src/util/test_helper_rsa.conf9
7 files changed, 657 insertions, 219 deletions
diff --git a/src/util/.gitignore b/src/util/.gitignore
index 8409f61d6..8a8cc0524 100644
--- a/src/util/.gitignore
+++ b/src/util/.gitignore
@@ -1,3 +1,4 @@
taler-config
test_payto
taler-helper-crypto-rsa
+test_helper_rsa
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index c74fe2101..505634381 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -7,7 +7,7 @@ if USE_COVERAGE
endif
-libexecdir = $(pkglibdir)/libexec/
+libexecdir = $(libdir)/taler/libexec
pkgcfgdir = $(prefix)/share/taler/config.d/
@@ -17,7 +17,8 @@ pkgcfg_DATA = \
EXTRA_DIST = \
paths.conf \
- taler-config.in
+ taler-config.in \
+ test_helper_rsa.conf
libexec_PROGRAMS = \
taler-helper-crypto-rsa
@@ -72,9 +73,12 @@ libtalerutil_la_LDFLAGS = \
-export-dynamic -no-undefined
+AM_TESTS_ENVIRONMENT=export TALER_PREFIX=$${TALER_PREFIX:-@libdir@};export PATH=$${TALER_PREFIX:-@prefix@}/bin:$$PATH;
+
check_PROGRAMS = \
test_amount \
test_crypto \
+ test_helper_rsa \
test_payto \
test_url
@@ -100,6 +104,12 @@ test_payto_LDADD = \
-lgnunetutil \
libtalerutil.la
+test_helper_rsa_SOURCES = \
+ test_helper_rsa.c
+test_helper_rsa_LDADD = \
+ -lgnunetutil \
+ libtalerutil.la
+
test_url_SOURCES = \
test_url.c
test_url_LDADD = \
diff --git a/src/util/crypto_helper.c b/src/util/crypto_helper.c
index 2b0fbe468..c42f01fc3 100644
--- a/src/util/crypto_helper.c
+++ b/src/util/crypto_helper.c
@@ -42,6 +42,16 @@ struct TALER_CRYPTO_DenominationHelper
struct sockaddr_un sa;
/**
+ * Socket address of this process.
+ */
+ struct sockaddr_un my_sa;
+
+ /**
+ * Template for @e my_sa.
+ */
+ char *template;
+
+ /**
* The UNIX domain socket, -1 if we are currently not connected.
*/
int sock;
@@ -58,6 +68,10 @@ static void
do_disconnect (struct TALER_CRYPTO_DenominationHelper *dh)
{
GNUNET_break (0 == close (dh->sock));
+ if (0 != unlink (dh->my_sa.sun_path))
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
+ "unlink",
+ dh->my_sa.sun_path);
dh->sock = -1;
}
@@ -82,18 +96,73 @@ try_connect (struct TALER_CRYPTO_DenominationHelper *dh)
"socket");
return;
}
- if (0 != connect (dh->sock,
- (const struct sockaddr *) &dh->sa,
- sizeof (dh->sa)))
{
- if (EINPROGRESS != dh->sock)
+ char *tmpdir;
+
+ tmpdir = GNUNET_DISK_mktemp (dh->template);
+ if (NULL == tmpdir)
{
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
- "connect");
do_disconnect (dh);
return;
}
+ /* we use >= here because we want the sun_path to always
+ be 0-terminated */
+ if (strlen (tmpdir) >= sizeof (dh->sa.sun_path))
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ "PATHS",
+ "TALER_RUNTIME_DIR",
+ "path too long");
+ GNUNET_free (tmpdir);
+ do_disconnect (dh);
+ return;
+ }
+ dh->my_sa.sun_family = AF_UNIX;
+ strncpy (dh->my_sa.sun_path,
+ tmpdir,
+ sizeof (dh->sa.sun_path));
+ if (0 != unlink (tmpdir))
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
+ "unlink",
+ tmpdir);
+ GNUNET_free (tmpdir);
}
+ if (0 != bind (dh->sock,
+ (const struct sockaddr *) &dh->my_sa,
+ sizeof (dh->my_sa)))
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "bind");
+ do_disconnect (dh);
+ return;
+ }
+ {
+ struct GNUNET_MessageHeader hdr = {
+ .size = htons (sizeof (hdr)),
+ .type = htons (TALER_HELPER_RSA_MT_REQ_INIT)
+ };
+ ssize_t ret;
+
+ ret = sendto (dh->sock,
+ &hdr,
+ sizeof (hdr),
+ 0,
+ (const struct sockaddr *) &dh->sa,
+ sizeof (dh->sa));
+ if (ret < 0)
+ {
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
+ "sendto",
+ dh->sa.sun_path);
+ do_disconnect (dh);
+ return;
+ }
+ /* We are using SOCK_DGRAM, partial writes should not be possible */
+ GNUNET_break (((size_t) ret) == sizeof (hdr));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Successfully sent REQ_INIT\n");
+ }
+
}
@@ -117,7 +186,9 @@ TALER_CRYPTO_helper_denom_connect (
"UNIXPATH");
return NULL;
}
- if (strlen (unixpath) > sizeof (dh->sa.sun_path))
+ /* we use >= here because we want the sun_path to always
+ be 0-terminated */
+ if (strlen (unixpath) >= sizeof (dh->sa.sun_path))
{
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
"taler-helper-crypto-rsa",
@@ -129,10 +200,39 @@ TALER_CRYPTO_helper_denom_connect (
dh = GNUNET_new (struct TALER_CRYPTO_DenominationHelper);
dh->dkc = dkc;
dh->dkc_cls = dkc_cls;
+ dh->sa.sun_family = AF_UNIX;
strncpy (dh->sa.sun_path,
unixpath,
sizeof (dh->sa.sun_path));
dh->sock = -1;
+ {
+ char *tmpdir;
+ char *template;
+
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_filename (cfg,
+ "PATHS",
+ "TALER_RUNTIME_DIR",
+ &tmpdir))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
+ "PATHS",
+ "TALER_RUNTIME_DIR");
+ tmpdir = GNUNET_strdup ("/tmp");
+ }
+ GNUNET_asprintf (&template,
+ "%s/crypto-rsa-client/XXXXXX",
+ tmpdir);
+ GNUNET_free (tmpdir);
+ if (GNUNET_OK !=
+ GNUNET_DISK_directory_create_for_file (template))
+ {
+ GNUNET_free (dh);
+ GNUNET_free (template);
+ return NULL;
+ }
+ dh->template = template;
+ }
TALER_CRYPTO_helper_poll (dh);
return dh;
}
@@ -157,6 +257,8 @@ TALER_CRYPTO_helper_poll (struct TALER_CRYPTO_DenominationHelper *dh)
MSG_DONTWAIT);
if (ret < 0)
{
+ if (EAGAIN == errno)
+ break;
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
"recv");
do_disconnect (dh);
@@ -180,10 +282,22 @@ TALER_CRYPTO_helper_poll (struct TALER_CRYPTO_DenominationHelper *dh)
struct TALER_DenominationPublicKey denom_pub;
struct GNUNET_HashCode h_denom_pub;
- if ( (sizeof (*kan) < ret) ||
- (sizeof (*kan) + ntohs (kan->pub_size) + ntohs (
- kan->section_name_len)) ||
- ('\0' != buf[ret - 1]) )
+ if (sizeof (*kan) > ret)
+ {
+ GNUNET_break_op (0);
+ do_disconnect (dh);
+ return;
+ }
+ if (ret !=
+ sizeof (*kan)
+ + ntohs (kan->pub_size)
+ + ntohs (kan->section_name_len))
+ {
+ GNUNET_break_op (0);
+ do_disconnect (dh);
+ return;
+ }
+ if ('\0' != buf[ret - 1])
{
GNUNET_break_op (0);
do_disconnect (dh);
@@ -267,14 +381,16 @@ TALER_CRYPTO_helper_denom_sign (
memcpy (&sr[1],
msg,
msg_size);
- ret = send (dh->sock,
- buf,
- sizeof (buf),
- 0);
+ ret = sendto (dh->sock,
+ buf,
+ sizeof (buf),
+ 0,
+ &dh->sa,
+ sizeof (dh->sa));
if (ret < 0)
{
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
- "send");
+ "sendto");
do_disconnect (dh);
*ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
return ds;
@@ -378,14 +494,16 @@ TALER_CRYPTO_helper_denom_revoke (
try_connect (dh);
if (-1 == dh->sock)
return; /* give up */
- ret = send (dh->sock,
- &rr,
- sizeof (rr),
- 0);
+ ret = sendto (dh->sock,
+ &rr,
+ sizeof (rr),
+ 0,
+ (const struct sockaddr *) &dh->sa,
+ sizeof (dh->sa));
if (ret < 0)
{
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
- "send");
+ "sendto");
do_disconnect (dh);
return;
}
@@ -399,6 +517,7 @@ TALER_CRYPTO_helper_denom_disconnect (
struct TALER_CRYPTO_DenominationHelper *dh)
{
do_disconnect (dh);
+ GNUNET_free (dh->template);
GNUNET_free (dh);
}
diff --git a/src/util/taler-helper-crypto-rsa.c b/src/util/taler-helper-crypto-rsa.c
index 92485571f..2d57fe75a 100644
--- a/src/util/taler-helper-crypto-rsa.c
+++ b/src/util/taler-helper-crypto-rsa.c
@@ -92,7 +92,7 @@ struct DenominationKey
/**
* Hash of this denomination's public key.
*/
- struct GNUNET_HashCode h_pub;
+ struct GNUNET_HashCode h_denom_pub;
/**
* Time at which this key is supposed to become valid.
@@ -181,26 +181,14 @@ struct Client
struct Client *prev;
/**
- * Work created by this client, NULL for none.
+ * Client address.
*/
- struct WorkItem *work;
+ struct sockaddr_un addr;
/**
- * Client socket.
+ * Number of bytes used in @e addr.
*/
- struct GNUNET_NETWORK_Handle *sock;
-
- /**
- * Client task to read from @e sock. NULL if we are working.
- */
- struct GNUNET_SCHEDULER_Task *task;
-
- /**
- * Flag set to true if this client has disconnected. Used
- * by the workers to detect that they must free the client
- * instead of returning the result.
- */
- bool gone;
+ socklen_t addr_size;
};
@@ -219,11 +207,6 @@ struct WorkItem
struct WorkItem *prev;
/**
- * The client that created the request.
- */
- struct Client *client;
-
- /**
* Key to be used for this operation.
*/
struct DenominationKey *dk;
@@ -244,6 +227,16 @@ struct WorkItem
*/
size_t blinded_msg_size;
+ /**
+ * Client address.
+ */
+ struct sockaddr_un addr;
+
+ /**
+ * Number of bytes used in @e addr.
+ */
+ socklen_t addr_size;
+
};
@@ -305,7 +298,7 @@ static struct GNUNET_CONTAINER_MultiHashMap *keys;
/**
* Our listen socket.
*/
-static struct GNUNET_NETWORK_Handle *lsock;
+static struct GNUNET_NETWORK_Handle *unix_sock;
/**
* Path where we are listening.
@@ -315,7 +308,7 @@ static char *unixpath;
/**
* Task run to accept new inbound connections.
*/
-static struct GNUNET_SCHEDULER_Task *accept_task;
+static struct GNUNET_SCHEDULER_Task *read_task;
/**
* Task run to generate new keys.
@@ -464,20 +457,10 @@ sign_worker (void *cls)
static void
free_client (struct Client *client)
{
- if (NULL != client->task)
- {
- GNUNET_SCHEDULER_cancel (client->task);
- client->task = NULL;
- }
- GNUNET_NETWORK_socket_close (client->sock);
- client->sock = NULL;
GNUNET_CONTAINER_DLL_remove (clients_head,
clients_tail,
client);
- if (NULL != client->work)
- client->gone = true;
- else
- GNUNET_free (client);
+ GNUNET_free (client);
}
@@ -491,21 +474,6 @@ read_job (void *cls);
/**
- * Start reading requests from the @a client.
- *
- * @param client client to read requests from.
- */
-static void
-client_next (struct Client *client)
-{
- client->task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
- client->sock,
- &read_job,
- client);
-}
-
-
-/**
* Free @a dk. It must already have been removed from #keys and the
* denomination's DLL.
*
@@ -524,25 +492,27 @@ free_dk (struct DenominationKey *dk)
/**
* Send a message starting with @a hdr to @a client.
*
- * @param client where to send @a hdr
+ * @param addr address where to send the message
+ * @param addr_size number of bytes in @a addr
* @param hdr beginning of the message, length indicated in size field
* @return #GNUNET_OK on success
*/
static int
-transmit_to_client (struct Client *client,
- const struct GNUNET_MessageHeader *hdr)
+transmit (const struct sockaddr_un *addr,
+ socklen_t addr_size,
+ const struct GNUNET_MessageHeader *hdr)
{
ssize_t ret;
- ret = send (GNUNET_NETWORK_get_fd (client->sock),
- hdr,
- ntohs (hdr->size),
- 0);
+ ret = GNUNET_NETWORK_socket_sendto (unix_sock,
+ hdr,
+ ntohs (hdr->size),
+ (const struct sockaddr *) addr,
+ addr_size);
if (ret != ntohs (hdr->size))
{
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
- "send");
- free_client (client);
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO,
+ "sendto");
return GNUNET_SYSERR;
}
return GNUNET_OK;
@@ -598,8 +568,9 @@ handle_done (void *cls)
buf,
buf_size);
GNUNET_free (buf);
- (void) transmit_to_client (wi->client,
- &sr->header);
+ (void) transmit (&wi->addr,
+ wi->addr_size,
+ &sr->header);
GNUNET_free (sr);
}
GNUNET_free (wi);
@@ -615,11 +586,13 @@ handle_done (void *cls)
* signature using the respective key and return the result to
* the client.
*
- * @param client the client making the request
+ * @param addr address of the client making the request
+ * @param addr_size number of bytes in @a addr
* @param sr the request details
*/
static void
-handle_sign_request (struct Client *client,
+handle_sign_request (const struct sockaddr_un *addr,
+ socklen_t addr_size,
const struct TALER_CRYPTO_SignRequest *sr)
{
struct DenominationKey *dk;
@@ -638,15 +611,17 @@ handle_sign_request (struct Client *client,
};
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Signing request failed, denomination key unknown\n");
- transmit_to_client (client,
- &sf.header);
- client_next (client);
+ "Signing request failed, denomination key %s unknown\n",
+ GNUNET_h2s (&sr->h_denom_pub));
+ (void) transmit (addr,
+ addr_size,
+ &sf.header);
return;
}
wi = GNUNET_new (struct WorkItem);
- wi->client = client;
+ wi->addr = *addr;
+ wi->addr_size = addr_size;
wi->dk = dk;
dk->rc++;
wi->blinded_msg = GNUNET_memdup (blinded_msg,
@@ -680,7 +655,6 @@ notify_client_dk_add (struct Client *client,
void *buf;
void *p;
size_t tlen;
- int ret;
buf_len = GNUNET_CRYPTO_rsa_public_key_encode (dk->denom_pub.rsa_public_key,
&buf);
@@ -703,10 +677,23 @@ notify_client_dk_add (struct Client *client,
memcpy (p + buf_len,
denom->section,
nlen);
- ret = transmit_to_client (client,
- &an->header);
- GNUNET_free (an);
- return ret;
+ {
+ int ret = GNUNET_OK;
+
+ if (GNUNET_OK !=
+ transmit (&client->addr,
+ client->addr_size,
+ &an->header))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Client %s must have disconnected\n",
+ client->addr.sun_path);
+ free_client (client);
+ ret = GNUNET_SYSERR;
+ }
+ GNUNET_free (an);
+ return ret;
+ }
}
@@ -724,11 +711,21 @@ notify_client_dk_del (struct Client *client,
struct TALER_CRYPTO_RsaKeyPurgeNotification pn = {
.header.type = htons (TALER_HELPER_RSA_MT_PURGE),
.header.size = htons (sizeof (pn)),
- .h_denom_pub = dk->h_pub
+ .h_denom_pub = dk->h_denom_pub
};
- return transmit_to_client (client,
- &pn.header);
+ if (GNUNET_OK !=
+ transmit (&client->addr,
+ client->addr_size,
+ &pn.header))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Client %s must have disconnected\n",
+ client->addr.sun_path);
+ free_client (client);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
}
@@ -767,7 +764,7 @@ setup_key (struct DenominationKey *dk,
buf_size = GNUNET_CRYPTO_rsa_private_key_encode (priv,
&buf);
GNUNET_CRYPTO_rsa_public_key_hash (pub,
- &dk->h_pub);
+ &dk->h_denom_pub);
GNUNET_asprintf (&dk->filename,
"%s/%s/%llu",
keydir,
@@ -789,13 +786,17 @@ setup_key (struct DenominationKey *dk,
return GNUNET_SYSERR;
}
GNUNET_free (buf);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Setup fresh private key %s in `%s'\n",
+ GNUNET_h2s (&dk->h_denom_pub),
+ dk->filename);
dk->denom_priv.rsa_private_key = priv;
dk->denom_pub.rsa_public_key = pub;
if (GNUNET_OK !=
GNUNET_CONTAINER_multihashmap_put (
keys,
- &dk->h_pub,
+ &dk->h_denom_pub,
dk,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
{
@@ -839,11 +840,13 @@ setup_key (struct DenominationKey *dk,
* Check if the key is still in use, and if so replace (!)
* it with a fresh key.
*
- * @param client the client sending the request
+ * @param addr address of the client making the request
+ * @param addr_size number of bytes in @a addr
* @param rr the revocation request
*/
static void
-handle_revoke_request (struct Client *client,
+handle_revoke_request (const struct sockaddr_un *addr,
+ socklen_t addr_size,
const struct TALER_CRYPTO_RevokeRequest *rr)
{
struct DenominationKey *dk;
@@ -854,9 +857,9 @@ handle_revoke_request (struct Client *client,
&rr->h_denom_pub);
if (NULL == dk)
{
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Revocation request ignored, denomination key unknown\n");
- client_next (client);
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Revocation request ignored, denomination key %s unknown\n",
+ GNUNET_h2s (&rr->h_denom_pub));
return;
}
@@ -886,11 +889,13 @@ handle_revoke_request (struct Client *client,
GNUNET_assert (GNUNET_OK ==
GNUNET_CONTAINER_multihashmap_remove (
keys,
- &dk->h_pub,
+ &dk->h_denom_pub,
dk));
GNUNET_CONTAINER_DLL_remove (denom->keys_head,
denom->keys_tail,
dk);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Revocation complete\n");
/* Tell clients this key is gone */
{
@@ -910,8 +915,6 @@ handle_revoke_request (struct Client *client,
}
if (0 == dk->rc)
free_dk (dk);
-
- client_next (client);
}
@@ -921,130 +924,108 @@ read_job (void *cls)
struct Client *client = cls;
char buf[65536];
ssize_t buf_size;
- struct GNUNET_MessageHeader hdr;
+ const struct GNUNET_MessageHeader *hdr;
+ struct sockaddr_un addr;
+ socklen_t addr_size = sizeof (addr);
- client->task = NULL;
- buf_size = GNUNET_NETWORK_socket_recv (client->sock,
- buf,
- sizeof (buf));
+ read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+ unix_sock,
+ &read_job,
+ NULL);
+ buf_size = GNUNET_NETWORK_socket_recvfrom (unix_sock,
+ buf,
+ sizeof (buf),
+ (struct sockaddr *) &addr,
+ &addr_size);
if (-1 == buf_size)
{
- if (EAGAIN == errno)
- {
- client_next (client);
- return;
- }
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
"recv");
- free_client (client);
return;
}
if (0 == buf_size)
{
- free_client (client);
return;
}
- if (buf_size < sizeof (hdr))
+ if (buf_size < sizeof (struct GNUNET_MessageHeader))
{
GNUNET_break_op (0);
- free_client (client);
return;
}
- memcpy (&hdr,
- buf,
- sizeof (hdr));
- if (ntohs (hdr.size) != buf_size)
+ hdr = (const struct GNUNET_MessageHeader *) buf;
+ if (ntohs (hdr->size) != buf_size)
{
GNUNET_break_op (0);
free_client (client);
return;
}
- switch (ntohs (hdr.type))
+ switch (ntohs (hdr->type))
{
+ case TALER_HELPER_RSA_MT_REQ_INIT:
+ if (ntohs (hdr->size) != sizeof (struct GNUNET_MessageHeader))
+ {
+ GNUNET_break_op (0);
+ return;
+ }
+ {
+ struct Client *client;
+
+ client = GNUNET_new (struct Client);
+ client->addr = addr;
+ client->addr_size = addr_size;
+ GNUNET_CONTAINER_DLL_insert (clients_head,
+ clients_tail,
+ client);
+ for (struct Denomination *denom = denom_head;
+ NULL != denom;
+ denom = denom->next)
+ {
+ for (struct DenominationKey *dk = denom->keys_head;
+ NULL != dk;
+ dk = dk->next)
+ {
+ if (GNUNET_OK !=
+ notify_client_dk_add (client,
+ dk))
+ {
+ /* client died, skip the rest */
+ client = NULL;
+ break;
+ }
+ }
+ if (NULL == client)
+ break;
+ }
+ }
+ break;
case TALER_HELPER_RSA_MT_REQ_SIGN:
- if (ntohs (hdr.size) <= sizeof (struct TALER_CRYPTO_SignRequest))
+ if (ntohs (hdr->size) <= sizeof (struct TALER_CRYPTO_SignRequest))
{
GNUNET_break_op (0);
- free_client (client);
return;
}
- handle_sign_request (client,
- (const struct TALER_CRYPTO_SignRequest *) &hdr);
+ handle_sign_request (&addr,
+ addr_size,
+ (const struct TALER_CRYPTO_SignRequest *) buf);
break;
case TALER_HELPER_RSA_MT_REQ_REVOKE:
- if (ntohs (hdr.size) != sizeof (struct TALER_CRYPTO_RevokeRequest))
+ if (ntohs (hdr->size) != sizeof (struct TALER_CRYPTO_RevokeRequest))
{
GNUNET_break_op (0);
- free_client (client);
return;
}
- handle_revoke_request (client,
- (const struct TALER_CRYPTO_RevokeRequest *) &hdr);
+ handle_revoke_request (&addr,
+ addr_size,
+ (const struct TALER_CRYPTO_RevokeRequest *) buf);
break;
default:
GNUNET_break_op (0);
- free_client (client);
return;
}
}
/**
- * Function run to accept incoming connections on #sock.
- *
- * @param cls NULL
- */
-static void
-accept_job (void *cls)
-{
- struct GNUNET_NETWORK_Handle *sock;
- struct sockaddr_storage addr;
- socklen_t alen;
-
- accept_task = NULL;
- alen = sizeof (addr);
- sock = GNUNET_NETWORK_socket_accept (lsock,
- (struct sockaddr *) &addr,
- &alen);
- if (NULL != sock)
- {
- struct Client *client;
-
- client = GNUNET_new (struct Client);
- client->sock = sock;
- GNUNET_CONTAINER_DLL_insert (clients_head,
- clients_tail,
- client);
- client_next (client);
- for (struct Denomination *denom = denom_head;
- NULL != denom;
- denom = denom->next)
- {
- for (struct DenominationKey *dk = denom->keys_head;
- NULL != dk;
- dk = dk->next)
- {
- if (GNUNET_OK !=
- notify_client_dk_add (client,
- dk))
- {
- /* client died, skip the rest */
- client = NULL;
- break;
- }
- }
- if (NULL == client)
- break;
- }
- }
- accept_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
- lsock,
- &accept_job,
- NULL);
-}
-
-
-/**
* Create a new denomination key (we do not have enough).
*
* @param denom denomination key to create
@@ -1137,7 +1118,7 @@ purge_key (struct DenominationKey *dk)
dk);
GNUNET_assert (GNUNET_OK ==
GNUNET_CONTAINER_multihashmap_remove (keys,
- &dk->h_pub,
+ &dk->h_denom_pub,
dk));
if (0 != unlink (dk->filename))
{
@@ -1325,17 +1306,18 @@ parse_key (struct Denomination *denom,
dk->anchor = anchor;
dk->filename = GNUNET_strdup (filename);
GNUNET_CRYPTO_rsa_public_key_hash (pub,
- &dk->h_pub);
+ &dk->h_denom_pub);
dk->denom_pub.rsa_public_key = pub;
if (GNUNET_OK !=
GNUNET_CONTAINER_multihashmap_put (
keys,
- &dk->h_pub,
+ &dk->h_denom_pub,
dk,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Duplicate private key detected in file `%s'. Skipping.\n",
+ "Duplicate private key %s detected in file `%s'. Skipping.\n",
+ GNUNET_h2s (&dk->h_denom_pub),
filename);
GNUNET_CRYPTO_rsa_private_key_free (priv);
GNUNET_CRYPTO_rsa_public_key_free (pub);
@@ -1355,8 +1337,9 @@ parse_key (struct Denomination *denom,
denom->keys_tail,
before,
dk);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Imported key from `%s'\n",
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Imported key %s from `%s'\n",
+ GNUNET_h2s (&dk->h_denom_pub),
filename);
}
}
@@ -1566,7 +1549,7 @@ load_denominations (void *cls,
GNUNET_free (denom);
return;
}
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Loading keys for denomination %s\n",
denom->section);
{
@@ -1576,6 +1559,8 @@ load_denominations (void *cls,
"%s/%s",
keydir,
denom->section);
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_DISK_directory_create (dname));
GNUNET_DISK_directory_scan (dname,
&import_key,
denom);
@@ -1611,17 +1596,16 @@ load_durations (void)
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_time (kcfg,
- "exchange",
+ "taler-helper-crypto-rsa",
"LOOKAHEAD_SIGN",
&lookahead_sign))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "exchange",
+ "taler-helper-crypto-rsa",
"LOOKAHEAD_SIGN");
return GNUNET_SYSERR;
}
GNUNET_TIME_round_rel (&lookahead_sign);
-
return GNUNET_OK;
}
@@ -1635,16 +1619,16 @@ static void
do_shutdown (void *cls)
{
(void) cls;
- if (NULL != accept_task)
+ if (NULL != read_task)
{
- GNUNET_SCHEDULER_cancel (accept_task);
- accept_task = NULL;
+ GNUNET_SCHEDULER_cancel (read_task);
+ read_task = NULL;
}
- if (NULL != lsock)
+ if (NULL != unix_sock)
{
GNUNET_break (GNUNET_OK ==
- GNUNET_NETWORK_socket_close (lsock));
- lsock = NULL;
+ GNUNET_NETWORK_socket_close (unix_sock));
+ unix_sock = NULL;
}
if (0 != unlink (unixpath))
{
@@ -1790,7 +1774,7 @@ run (void *cls,
return;
}
}
- lsock = GNUNET_NETWORK_socket_box_native (sock);
+ unix_sock = GNUNET_NETWORK_socket_box_native (sock);
}
GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
@@ -1823,10 +1807,10 @@ run (void *cls,
}
/* start job to accept incoming requests on 'sock' */
- accept_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
- lsock,
- &accept_job,
- NULL);
+ read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+ unix_sock,
+ &read_job,
+ NULL);
/* start job to keep keys up-to-date */
keygen_task = GNUNET_SCHEDULER_add_now (&update_denominations,
@@ -1893,7 +1877,7 @@ main (int argc,
/* force linker to link against libtalerutil; if we do
not do this, the linker may "optimize" libtalerutil
away and skip #TALER_OS_init(), which we do need */
- (void) TALER_project_data_default ();
+ GNUNET_OS_init (TALER_project_data_default ());
GNUNET_assert (GNUNET_OK ==
GNUNET_log_setup ("taler-helper-crypto-rsa",
"WARNING",
diff --git a/src/util/taler-helper-crypto-rsa.h b/src/util/taler-helper-crypto-rsa.h
index a80c32e67..d2bc07f7a 100644
--- a/src/util/taler-helper-crypto-rsa.h
+++ b/src/util/taler-helper-crypto-rsa.h
@@ -24,11 +24,12 @@
#define TALER_HELPER_RSA_MT_PURGE 1
#define TALER_HELPER_RSA_MT_AVAIL 2
-#define TALER_HELPER_RSA_MT_REQ_SIGN 3
-#define TALER_HELPER_RSA_MT_REQ_REVOKE 4
+#define TALER_HELPER_RSA_MT_REQ_INIT 4
+#define TALER_HELPER_RSA_MT_REQ_SIGN 5
+#define TALER_HELPER_RSA_MT_REQ_REVOKE 6
-#define TALER_HELPER_RSA_MT_RES_SIGNATURE 5
-#define TALER_HELPER_RSA_MT_RES_SIGN_FAILURE 6
+#define TALER_HELPER_RSA_MT_RES_SIGNATURE 7
+#define TALER_HELPER_RSA_MT_RES_SIGN_FAILURE 8
GNUNET_NETWORK_STRUCT_BEGIN
diff --git a/src/util/test_helper_rsa.c b/src/util/test_helper_rsa.c
new file mode 100644
index 000000000..4cb4a5f18
--- /dev/null
+++ b/src/util/test_helper_rsa.c
@@ -0,0 +1,314 @@
+/*
+ This file is part of TALER
+ (C) 2020 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file util/test_helper_rsa.c
+ * @brief Tests for RSA crypto helper
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_util.h"
+
+/**
+ * Configuration has 1 minute duration and 5 minutes lookahead, so
+ * we should never have more than 6 active keys, plus for during
+ * key expiration / revocation.
+ */
+#define MAX_KEYS 7
+
+/**
+ * How many random key revocations should we test?
+ */
+#define NUM_REVOKES 10
+
+
+/**
+ * Number of keys currently in #keys.
+ */
+static unsigned int num_keys;
+
+/**
+ * Keys currently managed by the helper.
+ */
+struct KeyData
+{
+ /**
+ * Validity start point.
+ */
+ struct GNUNET_TIME_Absolute start_time;
+
+ /**
+ * Key expires for signing at @e start_time plus this value.
+ */
+ struct GNUNET_TIME_Relative validity_duration;
+
+ /**
+ * Hash of the public key.
+ */
+ struct GNUNET_HashCode h_denom_pub;
+
+ /**
+ * Full public key.
+ */
+ struct TALER_DenominationPublicKey denom_pub;
+
+ /**
+ * Is this key currently valid?
+ */
+ bool valid;
+
+ /**
+ * Did the test driver revoke this key?
+ */
+ bool revoked;
+};
+
+static struct KeyData keys[MAX_KEYS];
+
+
+static void
+key_cb (void *cls,
+ const char *section_name,
+ struct GNUNET_TIME_Absolute start_time,
+ struct GNUNET_TIME_Relative validity_duration,
+ const struct GNUNET_HashCode *h_denom_pub,
+ const struct TALER_DenominationPublicKey *denom_pub)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Key notification about key %s in `%s'\n",
+ GNUNET_h2s (h_denom_pub),
+ section_name);
+ if (0 == validity_duration.rel_value_us)
+ {
+ bool found = false;
+
+ GNUNET_break (NULL == denom_pub);
+ GNUNET_break (NULL == section_name);
+ for (unsigned int i = 0; i<MAX_KEYS; i++)
+ if (0 == GNUNET_memcmp (h_denom_pub,
+ &keys[i].h_denom_pub))
+ {
+ keys[i].valid = false;
+ keys[i].revoked = false;
+ GNUNET_CRYPTO_rsa_public_key_free (keys[i].denom_pub.rsa_public_key);
+ keys[i].denom_pub.rsa_public_key = NULL;
+ GNUNET_assert (num_keys > 0);
+ num_keys--;
+ found = true;
+ break;
+ }
+ if (! found)
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Error: helper announced expiration of unknown key!\n");
+
+ return;
+ }
+ GNUNET_break (NULL != denom_pub);
+ for (unsigned int i = 0; i<MAX_KEYS; i++)
+ if (! keys[i].valid)
+ {
+ keys[i].valid = true;
+ keys[i].h_denom_pub = *h_denom_pub;
+ keys[i].start_time = start_time;
+ keys[i].validity_duration = validity_duration;
+ keys[i].denom_pub.rsa_public_key
+ = GNUNET_CRYPTO_rsa_public_key_dup (denom_pub->rsa_public_key);
+ num_keys++;
+ return;
+ }
+ /* too many keys! */
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Error: received %d live keys from the service!\n",
+ MAX_KEYS + 1);
+}
+
+
+/**
+ * Main entry point into the test logic with the helper already running.
+ */
+static int
+run_test (void)
+{
+ struct GNUNET_CONFIGURATION_Handle *cfg;
+ struct TALER_CRYPTO_DenominationHelper *dh;
+ struct timespec req = {
+ .tv_nsec = 250000000
+ };
+
+ cfg = GNUNET_CONFIGURATION_create ();
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_load (cfg,
+ "test_helper_rsa.conf"))
+ {
+ GNUNET_break (0);
+ return 77;
+ }
+ dh = TALER_CRYPTO_helper_denom_connect (cfg,
+ &key_cb,
+ NULL);
+ GNUNET_CONFIGURATION_destroy (cfg);
+ if (NULL == dh)
+ {
+ GNUNET_break (0);
+ return 1;
+ }
+ /* wait for helper to start and give us keys */
+ fprintf (stderr, "Waiting for helper to start ");
+ for (unsigned int i = 0; i<80; i++)
+ {
+ TALER_CRYPTO_helper_poll (dh);
+ if (0 != num_keys)
+ break;
+ nanosleep (&req, NULL);
+ fprintf (stderr, ".");
+ }
+ if (0 == num_keys)
+ {
+ fprintf (stderr,
+ "\nFAILED: timeout trying to connect to helper\n");
+ TALER_CRYPTO_helper_denom_disconnect (dh);
+ return 1;
+ }
+ fprintf (stderr,
+ "\nOK: Helper ready (%u keys)\n",
+ num_keys);
+ for (unsigned int i = 0; i<NUM_REVOKES; i++)
+ {
+ uint32_t off;
+
+ off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
+ num_keys);
+ /* find index of key to revoke */
+ for (unsigned int j = 0; j < MAX_KEYS; j++)
+ {
+ if (! keys[j].valid)
+ continue;
+ if (0 != off)
+ {
+ off--;
+ continue;
+ }
+ keys[j].revoked = true;
+ fprintf (stderr,
+ "Revoking key %s ...",
+ GNUNET_h2s (&keys[j].h_denom_pub));
+ TALER_CRYPTO_helper_denom_revoke (dh,
+ &keys[j].h_denom_pub);
+ for (unsigned int k = 0; k<80; k++)
+ {
+ TALER_CRYPTO_helper_poll (dh);
+ if (! keys[j].revoked)
+ break;
+ nanosleep (&req, NULL);
+ fprintf (stderr, ".");
+ }
+ if (keys[j].revoked)
+ {
+ fprintf (stderr,
+ "\nFAILED: timeout trying to revoke key %u\n",
+ j);
+ TALER_CRYPTO_helper_denom_disconnect (dh);
+ return 2;
+ }
+ break;
+ }
+ }
+
+
+ TALER_CRYPTO_helper_denom_disconnect (dh);
+ /* clean up our state */
+ for (unsigned int i = 0; i<MAX_KEYS; i++)
+ if (keys[i].valid)
+ {
+ GNUNET_CRYPTO_rsa_public_key_free (keys[i].denom_pub.rsa_public_key);
+ keys[i].denom_pub.rsa_public_key = NULL;
+ GNUNET_assert (num_keys > 0);
+ num_keys--;
+ }
+ return 0;
+}
+
+
+int
+main (int argc,
+ const char *const argv[])
+{
+ struct GNUNET_OS_Process *helper;
+ char *libexec_dir;
+ char *binary_name;
+ int ret;
+ enum GNUNET_OS_ProcessStatusType type;
+ unsigned long code;
+
+ (void) argc;
+ (void) argv;
+ GNUNET_log_setup ("test-helper-rsa",
+ "INFO",
+ NULL);
+ GNUNET_OS_init (TALER_project_data_default ());
+ libexec_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBEXECDIR);
+ GNUNET_asprintf (&binary_name,
+ "%s/%s",
+ libexec_dir,
+ "taler-helper-crypto-rsa");
+ GNUNET_free (libexec_dir);
+ helper = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ERR,
+ NULL, NULL, NULL,
+ binary_name,
+ binary_name,
+ "-c",
+ "test_helper_rsa.conf",
+ "-L",
+ "INFO",
+ NULL);
+ if (NULL == helper)
+ {
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
+ "exec",
+ binary_name);
+ GNUNET_free (binary_name);
+ return 77;
+ }
+ GNUNET_free (binary_name);
+ ret = run_test ();
+
+ GNUNET_OS_process_kill (helper,
+ SIGTERM);
+ if (GNUNET_OK !=
+ GNUNET_OS_process_wait_status (helper,
+ &type,
+ &code))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Helper process did not die voluntarily, killing hard\n");
+ GNUNET_OS_process_kill (helper,
+ SIGKILL);
+ ret = 4;
+ }
+ else if ( (GNUNET_OS_PROCESS_EXITED != type) ||
+ (0 != code) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Helper died with unexpected status %d/%d\n",
+ (int) type,
+ (int) code);
+ ret = 5;
+ }
+ GNUNET_OS_process_destroy (helper);
+ return ret;
+}
+
+
+/* end of test_helper_rsa.c */
diff --git a/src/util/test_helper_rsa.conf b/src/util/test_helper_rsa.conf
new file mode 100644
index 000000000..9880ae153
--- /dev/null
+++ b/src/util/test_helper_rsa.conf
@@ -0,0 +1,9 @@
+[coin_1]
+duration_withdraw = 1 minute
+rsa_keysize = 2048
+
+[taler-helper-crypto-rsa]
+lookahead_sign = 5 minutes
+overlap_duration = 1 s
+KEY_DIR = ${TALER_RUNTIME_DIR}/test_helper_rsa/
+UNIXPATH = ${TALER_RUNTIME_DIR}test_helper_rsa.unix