aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2019-12-11 14:30:55 +0100
committerChristian Grothoff <christian@grothoff.org>2019-12-11 14:30:55 +0100
commit631bc65253e25fa6a3c6b4a11cb06245cee58293 (patch)
treea792f7f45211d157e5859aaecb9e8fa60e7192f1
parent75240345d025ce448b7248a4ec693261ecf8a203 (diff)
add logic for privacy policy
-rw-r--r--src/exchange-tools/taler-exchange-keyup.c2
-rw-r--r--src/exchange/exchange.conf15
-rw-r--r--src/exchange/taler-exchange-httpd.c4
-rw-r--r--src/exchange/taler-exchange-httpd_refresh_reveal.c6
-rw-r--r--src/exchange/taler-exchange-httpd_terms.c507
-rw-r--r--src/exchange/taler-exchange-httpd_terms.h18
-rw-r--r--src/lib/exchange_api_handle.c2
7 files changed, 81 insertions, 473 deletions
diff --git a/src/exchange-tools/taler-exchange-keyup.c b/src/exchange-tools/taler-exchange-keyup.c
index d974ec46a..e6e3db0d1 100644
--- a/src/exchange-tools/taler-exchange-keyup.c
+++ b/src/exchange-tools/taler-exchange-keyup.c
@@ -765,7 +765,7 @@ create_denomkey_issue (const struct CoinTypeParams *params,
GNUNET_assert (NULL != dki->denom_priv.rsa_private_key);
dki->denom_pub.rsa_public_key
= GNUNET_CRYPTO_rsa_private_key_get_public (
- dki->denom_priv.rsa_private_key);
+ dki->denom_priv.rsa_private_key);
GNUNET_CRYPTO_rsa_public_key_hash (dki->denom_pub.rsa_public_key,
&dki->issue.properties.denom_hash);
dki->issue.properties.master = master_public_key;
diff --git a/src/exchange/exchange.conf b/src/exchange/exchange.conf
index 79b1877d9..c2426bc7f 100644
--- a/src/exchange/exchange.conf
+++ b/src/exchange/exchange.conf
@@ -67,3 +67,18 @@ LOOKAHEAD_SIGN = 32 weeks 1 day
# how long do we provide to clients denomination and signing keys
# ahead of time?
LOOKAHEAD_PROVIDE = 4 weeks 1 day
+
+
+# Directory with our terms of service.
+# TERMS_DIR =
+
+# Etag / filename for the terms of service.
+# TERMS_ETAG =
+
+
+# Directory with our privacy policy.
+# PRIVACY_DIR =
+
+# Etag / filename for the privacy policy.
+# PRIVACY_ETAG =
+
diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c
index 001d49df8..a8f32b030 100644
--- a/src/exchange/taler-exchange-httpd.c
+++ b/src/exchange/taler-exchange-httpd.c
@@ -256,6 +256,10 @@ handle_mhd_request (void *cls,
{ "/terms", MHD_HTTP_METHOD_GET, NULL,
NULL, 0,
&TEH_handler_terms, MHD_HTTP_OK },
+ /* Privacy policy */
+ { "/privacy", MHD_HTTP_METHOD_GET, NULL,
+ NULL, 0,
+ &TEH_handler_privacy, MHD_HTTP_OK },
/* Return key material and fundamental properties for this exchange */
{ "/keys", MHD_HTTP_METHOD_GET, "application/json",
NULL, 0,
diff --git a/src/exchange/taler-exchange-httpd_refresh_reveal.c b/src/exchange/taler-exchange-httpd_refresh_reveal.c
index fb2602c61..97e687ea9 100644
--- a/src/exchange/taler-exchange-httpd_refresh_reveal.c
+++ b/src/exchange/taler-exchange-httpd_refresh_reveal.c
@@ -771,9 +771,9 @@ handle_refresh_reveal_json (struct MHD_Connection *connection,
{
rctx->ev_sigs[i].rsa_signature
= GNUNET_CRYPTO_rsa_sign_blinded (
- rctx->dkis[i]->denom_priv.rsa_private_key,
- rctx->rcds[i].coin_ev,
- rctx->rcds[i].coin_ev_size);
+ rctx->dkis[i]->denom_priv.rsa_private_key,
+ rctx->rcds[i].coin_ev,
+ rctx->rcds[i].coin_ev_size);
if (NULL == rctx->ev_sigs[i].rsa_signature)
{
GNUNET_break (0);
diff --git a/src/exchange/taler-exchange-httpd_terms.c b/src/exchange/taler-exchange-httpd_terms.c
index b3d7c3442..47905f601 100644
--- a/src/exchange/taler-exchange-httpd_terms.c
+++ b/src/exchange/taler-exchange-httpd_terms.c
@@ -26,118 +26,16 @@
#include "taler_mhd_lib.h"
#include "taler-exchange-httpd_responses.h"
-
-/**
- * Entry in the terms-of-service array.
- */
-struct Terms
-{
- /**
- * Mime type of the terms.
- */
- const char *mime_type;
-
- /**
- * The terms (NOT 0-terminated!).
- */
- const void *terms;
-
- /**
- * The desired language.
- */
- char *language;
-
- /**
- * Number of bytes in @e terms.
- */
- size_t terms_size;
-};
-
-
-/**
- * Array of terms of service, terminated by NULL/0 value.
- */
-static struct Terms *terms;
-
-/**
- * Length of the #terms array.
- */
-static unsigned int terms_len;
-
-/**
- * Etag to use for the terms of service (= version).
- */
-static char *terms_etag;
-
-
/**
- * Check if @a mime matches the @a accept_pattern.
- *
- * @param accept_pattern a mime pattern like text/plain or image/<STAR>
- * @param mime the mime type to match
- * @return true if @a mime matches the @a accept_pattern
+ * Our terms of service.
*/
-static bool
-mime_matches (const char *accept_pattern,
- const char *mime)
-{
- const char *da = strchr (accept_pattern, '/');
- const char *dm = strchr (mime, '/');
-
- if ( (NULL == da) ||
- (NULL == dm) )
- return (0 == strcmp ("*", accept_pattern));
- return
- ( ( (1 == da - accept_pattern) &&
- ('*' == *accept_pattern) ) ||
- ( (da - accept_pattern == dm - mime) &&
- (0 == strncasecmp (accept_pattern,
- mime,
- da - accept_pattern)) ) ) &&
- ( (0 == strcmp (da, "/*")) ||
- (0 == strcasecmp (da,
- dm)) );
-}
+static struct TALER_MHD_Legal *tos;
/**
- * Check if @a lang matches the @a language_pattern, and if so with
- * which preference.
- *
- * @param language_pattern a language preferences string
- * like "fr-CH, fr;q=0.9, en;q=0.8, *;q=0.1"
- * @param lang the 2-digit language to match
- * @return q-weight given for @a lang in @a language_pattern, 1.0 if no weights are given;
- * 0 if @a lang is not in @a language_pattern
+ * Our privacy policy.
*/
-static double
-language_matches (const char *language_pattern,
- const char *lang)
-{
- char *p = GNUNET_strdup (language_pattern);
- char *sptr;
- double r = 0.0;
-
- for (char *tok = strtok_r (p, ", ", &sptr);
- NULL != tok;
- tok = strtok_r (NULL, ", ", &sptr))
- {
- char *sptr2;
- char *lp = strtok_r (tok, ";", &sptr2);
- char *qp = strtok_r (NULL, ";", &sptr2);
- double q = 1.0;
-
- GNUNET_break_op ( (NULL == qp) ||
- (1 == sscanf (qp,
- "q=%lf",
- &q)) );
- if (0 == strcasecmp (lang,
- lp))
- r = GNUNET_MAX (r, q);
- }
- GNUNET_free (p);
- return r;
-}
+static struct TALER_MHD_Legal *pp;
/**
@@ -157,340 +55,38 @@ TEH_handler_terms (struct TEH_RequestHandler *rh,
const char *upload_data,
size_t *upload_data_size)
{
- struct MHD_Response *resp;
- struct Terms *t;
-
(void) rh;
(void) upload_data;
(void) upload_data_size;
(void) connection_cls;
- {
- const char *etag;
-
- etag = MHD_lookup_connection_value (connection,
- MHD_HEADER_KIND,
- MHD_HTTP_HEADER_IF_NONE_MATCH);
- if ( (NULL != etag) &&
- (NULL != terms_etag) &&
- (0 == strcasecmp (etag,
- terms_etag)) )
- {
- int ret;
-
- resp = MHD_create_response_from_buffer (0,
- NULL,
- MHD_RESPMEM_PERSISTENT);
- ret = MHD_queue_response (connection,
- MHD_HTTP_NOT_MODIFIED,
- resp);
- GNUNET_break (MHD_YES == ret);
- MHD_destroy_response (resp);
- return ret;
- }
- }
-
- t = NULL;
- {
- const char *mime;
- const char *lang;
-
- mime = MHD_lookup_connection_value (connection,
- MHD_HEADER_KIND,
- MHD_HTTP_HEADER_ACCEPT);
- if (NULL == mime)
- mime = "text/html";
- lang = MHD_lookup_connection_value (connection,
- MHD_HEADER_KIND,
- MHD_HTTP_HEADER_ACCEPT_LANGUAGE);
- if (NULL == lang)
- lang = "en";
- /* Find best match: must match mime type (if possible), and if
- mime type matches, ideally also language */
- for (unsigned int i = 0; i < terms_len; i++)
- {
- struct Terms *p = &terms[i];
-
- if ( (NULL == t) ||
- (mime_matches (mime,
- p->mime_type)) )
- {
- if ( (NULL == t) ||
- (! mime_matches (mime,
- t->mime_type)) ||
- (language_matches (lang,
- p->language) >
- language_matches (lang,
- t->language) ) )
- t = p;
- }
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Best match for %s/%s: %s / %s\n",
- lang,
- mime,
- (NULL != t) ? t->mime_type : "<none>",
- (NULL != t) ? t->language : "<none>");
- }
-
- if (NULL == t)
- {
- /* Default terms of service if none are configured */
- static struct Terms none = {
- .mime_type = "text/plain",
- .terms = "Terms of service not configured",
- .language = "en",
- .terms_size = strlen ("Terms of service not configured")
- };
- t = &none;
- }
-
- /* try to compress the response */
- resp = NULL;
- if (MHD_YES ==
- TALER_MHD_can_compress (connection))
- {
- void *buf = GNUNET_memdup (t->terms,
- t->terms_size);
- size_t buf_size = t->terms_size;
-
- if (TALER_MHD_body_compress (&buf,
- &buf_size))
- {
- resp = MHD_create_response_from_buffer (buf_size,
- buf,
- MHD_RESPMEM_MUST_FREE);
- if (MHD_NO ==
- MHD_add_response_header (resp,
- MHD_HTTP_HEADER_CONTENT_ENCODING,
- "deflate"))
- {
- GNUNET_break (0);
- MHD_destroy_response (resp);
- resp = NULL;
- }
- }
- else
- {
- GNUNET_free (buf);
- }
- }
- if (NULL == resp)
- {
- /* could not generate compressed response, return uncompressed */
- resp = MHD_create_response_from_buffer (t->terms_size,
- (void *) t->terms,
- MHD_RESPMEM_PERSISTENT);
- }
- GNUNET_break (MHD_YES ==
- MHD_add_response_header (resp,
- MHD_HTTP_HEADER_ETAG,
- terms_etag));
- GNUNET_break (MHD_YES ==
- MHD_add_response_header (resp,
- MHD_HTTP_HEADER_CONTENT_TYPE,
- t->mime_type));
- {
- int ret;
-
- ret = MHD_queue_response (connection,
- MHD_HTTP_OK,
- resp);
- MHD_destroy_response (resp);
- return ret;
- }
-}
-
-
-/**
- * Load all the terms of service from @a path under language @a lang
- * from file @a name
- *
- * @param path where the terms are found
- * @param lang which language directory to crawl
- * @param name specific file to access
- */
-static void
-load_terms (const char *path,
- const char *lang,
- const char *name)
-{
- static struct MimeMap
- {
- const char *ext;
- const char *mime;
- } mm[] = {
- { .ext = ".html", .mime = "text/html" },
- { .ext = ".htm", .mime = "text/html" },
- { .ext = ".txt", .mime = "text/plain" },
- { .ext = ".pdf", .mime = "application/pdf" },
- { .ext = ".jpg", .mime = "image/jpeg" },
- { .ext = ".jpeg", .mime = "image/jpeg" },
- { .ext = ".png", .mime = "image/png" },
- { .ext = ".gif", .mime = "image/gif" },
- { .ext = NULL, .mime = NULL }
- };
- const char *ext = strrchr (name, '.');
- const char *mime;
-
- if (NULL == ext)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Unsupported file `%s' in directory `%s/%s': lacks extension\n",
- name,
- path,
- lang);
- return;
- }
- if ( (NULL == terms_etag) ||
- (0 != strncmp (terms_etag,
- name,
- ext - name - 1)) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Filename `%s' does not match Etag `%s' in directory `%s/%s'. Ignoring it.\n",
- name,
- terms_etag,
- path,
- lang);
- return;
- }
- mime = NULL;
- for (unsigned int i = 0; NULL != mm[i].ext; i++)
- if (0 == strcasecmp (mm[i].ext,
- ext))
- {
- mime = mm[i].mime;
- break;
- }
- if (NULL == mime)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Unsupported file extension `%s' of file `%s' in directory `%s/%s'\n",
- ext,
- name,
- path,
- lang);
- return;
- }
- /* try to read the file with the terms of service */
- {
- struct stat st;
- char *fn;
- int fd;
-
- GNUNET_asprintf (&fn,
- "%s/%s/%s",
- path,
- lang,
- name);
- fd = open (fn, O_RDONLY);
- if (-1 == fd)
- {
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
- "open",
- fn);
- GNUNET_free (fn);
- return;
- }
- GNUNET_free (fn);
- if (0 != fstat (fd, &st))
- {
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
- "fstat",
- fn);
- (void) close (fd);
- GNUNET_free (fn);
- return;
- }
- if (SIZE_MAX < st.st_size)
- {
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
- "fstat-size",
- fn);
- (void) close (fd);
- GNUNET_free (fn);
- return;
- }
- {
- char *buf;
- size_t bsize;
- ssize_t ret;
-
- bsize = (size_t) st.st_size;
- buf = GNUNET_malloc_large (bsize);
- if (NULL == buf)
- {
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
- "malloc");
- (void) close (fd);
- GNUNET_free (fn);
- return;
- }
- ret = read (fd,
- buf,
- bsize);
- if ( (ret < 0) ||
- (bsize != ((size_t) ret)) )
- {
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
- "read",
- fn);
- (void) close (fd);
- GNUNET_free (buf);
- GNUNET_free (fn);
- return;
- }
- (void) close (fd);
- GNUNET_free (fn);
-
- /* append to global list of terms of service */
- {
- struct Terms t = {
- .mime_type = mime,
- .terms = buf,
- .language = GNUNET_strdup (lang),
- .terms_size = bsize
- };
-
- GNUNET_array_append (terms,
- terms_len,
- t);
- }
- }
- }
+ return TALER_MHD_reply_legal (connection,
+ tos);
}
/**
- * Load all the terms of service from @a path under language @a lang.
+ * Handle a "/privacy" request.
*
- * @param path where the terms are found
- * @param lang which language directory to crawl
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] connection_cls the connection's closure (can be updated)
+ * @param upload_data upload data
+ * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @return MHD result code
*/
-static void
-load_language (const char *path,
- const char *lang)
+int
+TEH_handler_privacy (struct TEH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ void **connection_cls,
+ const char *upload_data,
+ size_t *upload_data_size)
{
- char *dname;
- DIR *d;
-
- GNUNET_asprintf (&dname,
- "%s/%s",
- path,
- lang);
- d = opendir (dname);
- for (struct dirent *de = readdir (d);
- NULL != de;
- de = readdir (d))
- {
- const char *fn = de->d_name;
-
- if (fn[0] == '.')
- continue;
- load_terms (path, lang, fn);
- }
- closedir (d);
- free (dname);
+ (void) rh;
+ (void) upload_data;
+ (void) upload_data_size;
+ (void) connection_cls;
+ return TALER_MHD_reply_legal (connection,
+ pp);
}
@@ -502,45 +98,20 @@ load_language (const char *path,
void
TEH_load_terms (const struct GNUNET_CONFIGURATION_Handle *cfg)
{
- char *path;
- DIR *d;
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- "exchange",
- "TERMS_ETAG",
- &terms_etag))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
- "exchange",
- "TERMS_ETAG");
- return;
- }
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (cfg,
- "exchange",
- "TERMS_DIR",
- &path))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
- "exchange",
- "TERMS_DIR");
-
- return;
- }
- d = opendir (path);
- for (struct dirent *de = readdir (d);
- NULL != de;
- de = readdir (d))
- {
- const char *lang = de->d_name;
-
- if (lang[0] == '.')
- continue;
- load_language (path, lang);
- }
- closedir (d);
- free (path);
+ tos = TALER_MHD_legal_load (cfg,
+ "exchange",
+ "TERMS_DIR",
+ "TERMS_ETAG");
+ if (NULL == tos)
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Terms of service not configured\n");
+ pp = TALER_MHD_legal_load (cfg,
+ "exchange",
+ "PRIVACY_DIR",
+ "PRIVACY_ETAG");
+ if (NULL == pp)
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Privacy policy not configured\n");
}
diff --git a/src/exchange/taler-exchange-httpd_terms.h b/src/exchange/taler-exchange-httpd_terms.h
index 18a42809d..75909df9a 100644
--- a/src/exchange/taler-exchange-httpd_terms.h
+++ b/src/exchange/taler-exchange-httpd_terms.h
@@ -47,6 +47,24 @@ TEH_handler_terms (struct TEH_RequestHandler *rh,
size_t *upload_data_size);
/**
+ * Handle a "/privacy" request.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param[in,out] connection_cls the connection's closure (can be updated)
+ * @param upload_data upload data
+ * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @return MHD result code
+ */
+int
+TEH_handler_privacy (struct TEH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ void **connection_cls,
+ const char *upload_data,
+ size_t *upload_data_size);
+
+
+/**
* Load our terms of service as per configuration.
*
* @param cfg configuration to process
diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c
index efac70777..04de37677 100644
--- a/src/lib/exchange_api_handle.c
+++ b/src/lib/exchange_api_handle.c
@@ -1262,7 +1262,7 @@ keys_completed_cb (void *cls,
for (unsigned int i = 0; i<kd_old.num_denom_keys; i++)
kd.denom_keys[i].key.rsa_public_key
= GNUNET_CRYPTO_rsa_public_key_dup (
- kd_old.denom_keys[i].key.rsa_public_key);
+ kd_old.denom_keys[i].key.rsa_public_key);
kd.num_auditors = kd_old.num_auditors;
kd.auditors = GNUNET_new_array (kd.num_auditors,