diff options
| author | Christian Grothoff <christian@grothoff.org> | 2019-12-11 14:30:55 +0100 | 
|---|---|---|
| committer | Christian Grothoff <christian@grothoff.org> | 2019-12-11 14:30:55 +0100 | 
| commit | 631bc65253e25fa6a3c6b4a11cb06245cee58293 (patch) | |
| tree | a792f7f45211d157e5859aaecb9e8fa60e7192f1 | |
| parent | 75240345d025ce448b7248a4ec693261ecf8a203 (diff) | |
add logic for privacy policy
| -rw-r--r-- | src/exchange-tools/taler-exchange-keyup.c | 2 | ||||
| -rw-r--r-- | src/exchange/exchange.conf | 15 | ||||
| -rw-r--r-- | src/exchange/taler-exchange-httpd.c | 4 | ||||
| -rw-r--r-- | src/exchange/taler-exchange-httpd_refresh_reveal.c | 6 | ||||
| -rw-r--r-- | src/exchange/taler-exchange-httpd_terms.c | 507 | ||||
| -rw-r--r-- | src/exchange/taler-exchange-httpd_terms.h | 18 | ||||
| -rw-r--r-- | src/lib/exchange_api_handle.c | 2 | 
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 d974ec46..e6e3db0d 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 79b1877d..c2426bc7 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 001d49df..a8f32b03 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 fb2602c6..97e687ea 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 b3d7c344..47905f60 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 18a42809..75909df9 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 efac7077..04de3767 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, | 
