gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-exchange] 02/02: misc new /keys management related bugfixes


From: gnunet
Subject: [taler-exchange] 02/02: misc new /keys management related bugfixes
Date: Tue, 15 Dec 2020 21:09:41 +0100

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository exchange.

commit 18c12f62347c2c3767a36577f352fc39df532801
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Tue Dec 15 21:09:36 2020 +0100

    misc new /keys management related bugfixes
---
 src/exchange-tools/taler-exchange-offline.c        |   8 +-
 src/exchange/taler-exchange-httpd.c                |  12 +-
 src/exchange/taler-exchange-httpd_keys.c           | 272 +++++++++++++--------
 src/exchange/taler-exchange-httpd_keys.h           |  63 ++++-
 .../taler-exchange-httpd_management_post_keys.c    |  14 +-
 src/lib/exchange_api_management_post_keys.c        |   4 +
 6 files changed, 249 insertions(+), 124 deletions(-)

diff --git a/src/exchange-tools/taler-exchange-offline.c 
b/src/exchange-tools/taler-exchange-offline.c
index 0fbcd672..28bbbe02 100644
--- a/src/exchange-tools/taler-exchange-offline.c
+++ b/src/exchange-tools/taler-exchange-offline.c
@@ -635,8 +635,8 @@ denom_revocation_cb (
                 "Upload failed for command %u with status %u: %s (%s)\n",
                 (unsigned int) drr->idx,
                 hr->http_status,
-                TALER_ErrorCode_get_hint (hr->ec),
-                hr->hint);
+                hr->hint,
+                TALER_JSON_get_error_hint (hr->reply));
     global_ret = 10;
   }
   GNUNET_CONTAINER_DLL_remove (drr_head,
@@ -724,8 +724,8 @@ signkey_revocation_cb (
                 "Upload failed for command %u with status %u: %s (%s)\n",
                 (unsigned int) srr->idx,
                 hr->http_status,
-                TALER_ErrorCode_get_hint (hr->ec),
-                hr->hint);
+                hr->hint,
+                TALER_JSON_get_error_hint (hr->reply));
     global_ret = 10;
   }
   GNUNET_CONTAINER_DLL_remove (srr_head,
diff --git a/src/exchange/taler-exchange-httpd.c 
b/src/exchange/taler-exchange-httpd.c
index 6009672f..eb9d7c46 100644
--- a/src/exchange/taler-exchange-httpd.c
+++ b/src/exchange/taler-exchange-httpd.c
@@ -696,7 +696,7 @@ handle_post_auditors (const struct TEH_RequestHandler *rh,
 
   if ( (NULL == args[0]) ||
        (NULL == args[1]) ||
-       (NULL != args[0]) )
+       (NULL != args[2]) )
   {
     GNUNET_break_op (0);
     return r404 (connection, "/auditors/$AUDITOR_PUB/$H_DENOM_PUB");
@@ -1476,12 +1476,7 @@ run_main_loop (int fh,
   }
 
   atexit (&write_stats);
-  ret = TEH_keys_init ();
-  if (GNUNET_OK == ret)
-  {
-    ret = TEH_loop_run ();
-    TEH_loop_done ();
-  }
+  ret = TEH_loop_run ();
   switch (ret)
   {
   case GNUNET_OK:
@@ -1696,6 +1691,9 @@ main (int argc,
   if (GNUNET_OK !=
       TEH_WIRE_init ())
     return 42;
+  if (GNUNET_OK !=
+      TEH_keys_init ())
+    return 43;
   ret = TEH_loop_init ();
   if (GNUNET_OK == ret)
   {
diff --git a/src/exchange/taler-exchange-httpd_keys.c 
b/src/exchange/taler-exchange-httpd_keys.c
index fe7a024c..e955cd95 100644
--- a/src/exchange/taler-exchange-httpd_keys.c
+++ b/src/exchange/taler-exchange-httpd_keys.c
@@ -293,6 +293,12 @@ struct TEH_KeyStateHandle
    */
   struct GNUNET_TIME_Absolute next_reload;
 
+  /**
+   * True if #finish_keys_response() was not yet run and this key state
+   * is only suitable for the /management/keys API.
+   */
+  bool management_only;
+
 };
 
 
@@ -888,7 +894,10 @@ TEH_keys_init ()
   if (0 !=
       pthread_key_create (&key_state,
                           &destroy_key_state_cb))
+  {
+    GNUNET_break (0);
     return GNUNET_SYSERR;
+  }
   key_state_available = true;
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_time (TEH_cfg,
@@ -1124,87 +1133,6 @@ auditor_denom_cb (
 }
 
 
-/**
- * Create a key state.
- *
- * @param[in] hs helper state to (re)use, NULL if not available
- * @return NULL on error (i.e. failed to access database)
- */
-static struct TEH_KeyStateHandle *
-build_key_state (struct HelperState *hs)
-{
-  struct TEH_KeyStateHandle *ksh;
-  enum GNUNET_DB_QueryStatus qs;
-
-  ksh = GNUNET_new (struct TEH_KeyStateHandle);
-  ksh->reload_time = GNUNET_TIME_absolute_get ();
-  GNUNET_TIME_round_abs (&ksh->reload_time);
-  /* We must use the key_generation from when we STARTED the process! */
-  ksh->key_generation = key_generation;
-  if (NULL == hs)
-  {
-    if (GNUNET_OK !=
-        setup_key_helpers (&ksh->helpers))
-    {
-      GNUNET_free (ksh);
-      return NULL;
-    }
-  }
-  else
-  {
-    ksh->helpers = *hs;
-  }
-  ksh->denomkey_map = GNUNET_CONTAINER_multihashmap_create (1024,
-                                                            GNUNET_YES);
-  ksh->signkey_map = GNUNET_CONTAINER_multipeermap_create (32,
-                                                           GNUNET_NO /* MUST 
be NO! */);
-  ksh->auditors = json_array ();
-  /* NOTE: fetches master-signed signkeys, but ALSO those that were revoked! */
-  qs = TEH_plugin->iterate_denominations (TEH_plugin->cls,
-                                          &denomination_info_cb,
-                                          ksh);
-  if (qs < 0)
-  {
-    GNUNET_break (0);
-    destroy_key_state (ksh,
-                       true);
-    return NULL;
-  }
-  /* NOTE: ONLY fetches non-revoked AND master-signed signkeys! */
-  qs = TEH_plugin->iterate_active_signkeys (TEH_plugin->cls,
-                                            &signkey_info_cb,
-                                            ksh);
-  if (qs < 0)
-  {
-    GNUNET_break (0);
-    destroy_key_state (ksh,
-                       true);
-    return NULL;
-  }
-  qs = TEH_plugin->iterate_active_auditors (TEH_plugin->cls,
-                                            &auditor_info_cb,
-                                            ksh);
-  if (qs < 0)
-  {
-    GNUNET_break (0);
-    destroy_key_state (ksh,
-                       true);
-    return NULL;
-  }
-  qs = TEH_plugin->iterate_auditor_denominations (TEH_plugin->cls,
-                                                  &auditor_denom_cb,
-                                                  ksh);
-  if (qs < 0)
-  {
-    GNUNET_break (0);
-    destroy_key_state (ksh,
-                       true);
-    return NULL;
-  }
-  return ksh;
-}
-
-
 /**
  * Closure for #add_sign_key_cb.
  */
@@ -1462,9 +1390,10 @@ create_krd (struct TEH_KeyStateHandle *ksh,
     enum TALER_ErrorCode ec;
 
     if (TALER_EC_NONE !=
-        (ec = TEH_keys_exchange_sign (&ks,
-                                      &exchange_pub,
-                                      &exchange_sig)))
+        (ec = TEH_keys_exchange_sign2 (ksh,
+                                       &ks,
+                                       &exchange_pub,
+                                       &exchange_sig)))
     {
       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                   "Could not create key response data: cannot sign (%s)\n",
@@ -1544,7 +1473,7 @@ create_krd (struct TEH_KeyStateHandle *ksh,
 
 
 /**
- * Update the "/keys" responses in @a ksh up to @a now into the future.
+ * Update the "/keys" responses in @a ksh, computing the detailed replies.
  *
  * This function is to recompute all (including cherry-picked) responses we
  * might want to return, based on the state already in @a ksh.
@@ -1553,7 +1482,7 @@ create_krd (struct TEH_KeyStateHandle *ksh,
  * @return #GNUNET_OK on success
  */
 static int
-update_keys_response (struct TEH_KeyStateHandle *ksh)
+finish_keys_response (struct TEH_KeyStateHandle *ksh)
 {
   json_t *recoup;
   struct SignKeyCtx sctx;
@@ -1686,10 +1615,109 @@ update_keys_response (struct TEH_KeyStateHandle *ksh)
   json_decref (sctx.signkeys);
   json_decref (recoup);
   json_decref (denoms);
+  ksh->management_only = false;
   return GNUNET_OK;
 }
 
 
+/**
+ * Create a key state.
+ *
+ * @param[in] hs helper state to (re)use, NULL if not available
+ * @param management_only if we should NOT run 'finish_keys_response()'
+ *                  because we only need the state for the /management/keys API
+ * @return NULL on error (i.e. failed to access database)
+ */
+static struct TEH_KeyStateHandle *
+build_key_state (struct HelperState *hs,
+                 bool management_only)
+{
+  struct TEH_KeyStateHandle *ksh;
+  enum GNUNET_DB_QueryStatus qs;
+
+  ksh = GNUNET_new (struct TEH_KeyStateHandle);
+  ksh->reload_time = GNUNET_TIME_absolute_get ();
+  GNUNET_TIME_round_abs (&ksh->reload_time);
+  /* We must use the key_generation from when we STARTED the process! */
+  ksh->key_generation = key_generation;
+  if (NULL == hs)
+  {
+    if (GNUNET_OK !=
+        setup_key_helpers (&ksh->helpers))
+    {
+      GNUNET_free (ksh);
+      return NULL;
+    }
+  }
+  else
+  {
+    ksh->helpers = *hs;
+  }
+  ksh->denomkey_map = GNUNET_CONTAINER_multihashmap_create (1024,
+                                                            GNUNET_YES);
+  ksh->signkey_map = GNUNET_CONTAINER_multipeermap_create (32,
+                                                           GNUNET_NO /* MUST 
be NO! */);
+  ksh->auditors = json_array ();
+  /* NOTE: fetches master-signed signkeys, but ALSO those that were revoked! */
+  qs = TEH_plugin->iterate_denominations (TEH_plugin->cls,
+                                          &denomination_info_cb,
+                                          ksh);
+  if (qs < 0)
+  {
+    GNUNET_break (0);
+    destroy_key_state (ksh,
+                       true);
+    return NULL;
+  }
+  /* NOTE: ONLY fetches non-revoked AND master-signed signkeys! */
+  qs = TEH_plugin->iterate_active_signkeys (TEH_plugin->cls,
+                                            &signkey_info_cb,
+                                            ksh);
+  if (qs < 0)
+  {
+    GNUNET_break (0);
+    destroy_key_state (ksh,
+                       true);
+    return NULL;
+  }
+  qs = TEH_plugin->iterate_active_auditors (TEH_plugin->cls,
+                                            &auditor_info_cb,
+                                            ksh);
+  if (qs < 0)
+  {
+    GNUNET_break (0);
+    destroy_key_state (ksh,
+                       true);
+    return NULL;
+  }
+  qs = TEH_plugin->iterate_auditor_denominations (TEH_plugin->cls,
+                                                  &auditor_denom_cb,
+                                                  ksh);
+  if (qs < 0)
+  {
+    GNUNET_break (0);
+    destroy_key_state (ksh,
+                       true);
+    return NULL;
+  }
+  if (management_only)
+  {
+    ksh->management_only = true;
+    return ksh;
+  }
+  if (GNUNET_OK !=
+      finish_keys_response (ksh))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Could not finish /keys response (likely no signing keys 
available yet)\n");
+    destroy_key_state (ksh,
+                       true);
+    return NULL;
+  }
+  return ksh;
+}
+
+
 void
 TEH_keys_update_states ()
 {
@@ -1699,8 +1727,16 @@ TEH_keys_update_states ()
 }
 
 
-struct TEH_KeyStateHandle *
-TEH_get_key_state (void)
+/**
+ * Obtain the key state for the current thread. Should ONLY be used
+ * directly if @a management_only is true. Otherwise use #TEH_get_key_state().
+ *
+ * @param management_only if we should NOT run 'finish_keys_response()'
+ *                  because we only need the state for the /management/keys API
+ * @return NULL on error
+ */
+static struct TEH_KeyStateHandle *
+get_key_state (bool management_only)
 {
   struct TEH_KeyStateHandle *old_ksh;
   struct TEH_KeyStateHandle *ksh;
@@ -1709,7 +1745,8 @@ TEH_get_key_state (void)
   old_ksh = pthread_getspecific (key_state);
   if (NULL == old_ksh)
   {
-    ksh = build_key_state (NULL);
+    ksh = build_key_state (NULL,
+                           management_only);
     if (NULL == ksh)
       return NULL;
     if (0 != pthread_setspecific (key_state,
@@ -1728,7 +1765,8 @@ TEH_get_key_state (void)
                 "Rebuilding /keys, generation upgrade from %llu to %llu\n",
                 (unsigned long long) old_ksh->key_generation,
                 (unsigned long long) key_generation);
-    ksh = build_key_state (&old_ksh->helpers);
+    ksh = build_key_state (&old_ksh->helpers,
+                           management_only);
     if (0 != pthread_setspecific (key_state,
                                   ksh))
     {
@@ -1748,6 +1786,24 @@ TEH_get_key_state (void)
 }
 
 
+struct TEH_KeyStateHandle *
+TEH_get_key_state (void)
+{
+  struct TEH_KeyStateHandle *ksh;
+
+  ksh = get_key_state (false);
+  if (NULL == ksh)
+    return NULL;
+  if (ksh->management_only)
+  {
+    if (GNUNET_OK !=
+        finish_keys_response (ksh))
+      return NULL;
+  }
+  return ksh;
+}
+
+
 struct TEH_DenominationKey *
 TEH_keys_denomination_by_hash (const struct GNUNET_HashCode *h_denom_pub,
                                enum TALER_ErrorCode *ec,
@@ -1830,13 +1886,12 @@ TEH_keys_denomination_revoke (const struct 
GNUNET_HashCode *h_denom_pub)
 
 
 enum TALER_ErrorCode
-TEH_keys_exchange_sign_ (const struct
-                         GNUNET_CRYPTO_EccSignaturePurpose *purpose,
-                         struct TALER_ExchangePublicKeyP *pub,
-                         struct TALER_ExchangeSignatureP *sig)
+TEH_keys_exchange_sign_ (
+  const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
+  struct TALER_ExchangePublicKeyP *pub,
+  struct TALER_ExchangeSignatureP *sig)
 {
   struct TEH_KeyStateHandle *ksh;
-  enum TALER_ErrorCode ec;
 
   ksh = TEH_get_key_state ();
   if (NULL == ksh)
@@ -1847,6 +1902,22 @@ TEH_keys_exchange_sign_ (const struct
                 "Cannot sign request, no valid signing keys available.\n");
     return TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING;
   }
+  return TEH_keys_exchange_sign2_ (ksh,
+                                   purpose,
+                                   pub,
+                                   sig);
+}
+
+
+enum TALER_ErrorCode
+TEH_keys_exchange_sign2_ (
+  struct TEH_KeyStateHandle *ksh,
+  const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
+  struct TALER_ExchangePublicKeyP *pub,
+  struct TALER_ExchangeSignatureP *sig)
+{
+  enum TALER_ErrorCode ec;
+
   ec = TALER_CRYPTO_helper_esign_sign_ (ksh->helpers.esh,
                                         purpose,
                                         pub,
@@ -1971,11 +2042,6 @@ TEH_keys_get_handler (const struct TEH_RequestHandler 
*rh,
     {
       return suspend_request (connection);
     }
-    if (GNUNET_OK !=
-        update_keys_response (ksh))
-    {
-      return suspend_request (connection);
-    }
     krd = bsearch (&last_issue_date,
                    ksh->krd_array,
                    ksh->krd_array_length,
@@ -2152,7 +2218,7 @@ TEH_keys_load_fees (const struct GNUNET_HashCode 
*h_denom_pub,
   struct HelperDenomination *hd;
   int ok;
 
-  ksh = TEH_get_key_state ();
+  ksh = get_key_state (true);
   if (NULL == ksh)
   {
     GNUNET_break (0);
@@ -2184,7 +2250,7 @@ TEH_keys_get_timing (const struct 
TALER_ExchangePublicKeyP *exchange_pub,
   struct HelperSignkey *hsk;
   struct GNUNET_PeerIdentity pid;
 
-  ksh = TEH_get_key_state ();
+  ksh = get_key_state (true);
   if (NULL == ksh)
   {
     GNUNET_break (0);
@@ -2354,7 +2420,7 @@ TEH_keys_management_get_handler (const struct 
TEH_RequestHandler *rh,
   struct TEH_KeyStateHandle *ksh;
   json_t *reply;
 
-  ksh = TEH_get_key_state ();
+  ksh = get_key_state (true);
   if (NULL == ksh)
   {
     GNUNET_break (0);
diff --git a/src/exchange/taler-exchange-httpd_keys.h 
b/src/exchange/taler-exchange-httpd_keys.h
index 1bdabd0f..54dc8c73 100644
--- a/src/exchange/taler-exchange-httpd_keys.h
+++ b/src/exchange/taler-exchange-httpd_keys.h
@@ -217,10 +217,31 @@ TEH_resume_keys_requests (bool do_shutdown);
  * @return #TALER_EC_NONE on success
  */
 enum TALER_ErrorCode
-TEH_keys_exchange_sign_ (const struct
-                         GNUNET_CRYPTO_EccSignaturePurpose *purpose,
-                         struct TALER_ExchangePublicKeyP *pub,
-                         struct TALER_ExchangeSignatureP *sig);
+TEH_keys_exchange_sign_ (
+  const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
+  struct TALER_ExchangePublicKeyP *pub,
+  struct TALER_ExchangeSignatureP *sig);
+
+
+/**
+ * Sign the message in @a purpose with the exchange's signing key.
+ *
+ * The @a purpose data is the beginning of the data of which the signature is
+ * to be created. The `size` field in @a purpose must correctly indicate the
+ * number of bytes of the data structure, including its header.  Use
+ * #TEH_keys_exchange_sign() instead of calling this function directly!
+ *
+ * @param purpose the message to sign
+ * @param[out] pub set to the current public signing key of the exchange
+ * @param[out] sig signature over purpose using current signing key
+ * @return #TALER_EC_NONE on success
+ */
+enum TALER_ErrorCode
+TEH_keys_exchange_sign2_ (
+  struct TEH_KeyStateHandle *ksh,
+  const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
+  struct TALER_ExchangePublicKeyP *pub,
+  struct TALER_ExchangeSignatureP *sig);
 
 
 /**
@@ -250,6 +271,40 @@ TEH_keys_exchange_sign_ (const struct
   })
 
 
+/**
+ * @ingroup crypto
+ * @brief EdDSA sign a given block.
+ *
+ * The @a ps data must be a fixed-size struct for which the signature is to be
+ * created. The `size` field in @a ps->purpose must correctly indicate the
+ * number of bytes of the data structure, including its header.
+ *
+ * This allows requesting multiple denominations with the same @a ksh which
+ * thus will remain valid until the next call to
+ * #TEH_keys_denomination_by_hash() or #TEH_get_key_state() or
+ * #TEH_keys_exchange_sign().
+ *
+ * @param ksh key state to use
+ * @param ps packed struct with what to sign, MUST begin with a purpose
+ * @param[out] pub where to store the public key to use for the signing
+ * @param[out] sig where to write the signature
+ * @return #TALER_EC_NONE on success
+ */
+#define TEH_keys_exchange_sign2(ksh,ps,pub,sig)       \
+  ({                                                  \
+    /* check size is set correctly */                 \
+    GNUNET_assert (htonl ((ps)->purpose.size) ==      \
+                   sizeof (*ps));                     \
+    /* check 'ps' begins with the purpose */          \
+    GNUNET_static_assert (((void*) (ps)) ==           \
+                          ((void*) &(ps)->purpose));  \
+    TEH_keys_exchange_sign2_ (ksh,                    \
+                              &(ps)->purpose,         \
+                              pub,                     \
+                              sig);                    \
+  })
+
+
 /**
  * Revoke the given exchange's signing key.
  * This function should be called AFTER the database was
diff --git a/src/exchange/taler-exchange-httpd_management_post_keys.c 
b/src/exchange/taler-exchange-httpd_management_post_keys.c
index 84ec1f53..df044b6d 100644
--- a/src/exchange/taler-exchange-httpd_management_post_keys.c
+++ b/src/exchange/taler-exchange-httpd_management_post_keys.c
@@ -157,7 +157,7 @@ add_keys (void *cls,
           MHD_HTTP_NOT_FOUND,
           TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN,
           GNUNET_h2s (&akc->d_sigs[i].h_denom_pub));
-        return qs;
+        return GNUNET_DB_STATUS_HARD_ERROR;
       }
     }
     else
@@ -183,11 +183,12 @@ add_keys (void *cls,
             &akc->d_sigs[i].master_sig))
       {
         GNUNET_break_op (0);
-        return TALER_MHD_reply_with_error (
+        *mhd_ret = TALER_MHD_reply_with_error (
           connection,
           MHD_HTTP_FORBIDDEN,
-          TALER_EC_EXCHANGE_MANAGEMENT_KEYS_SIGNKEY_ADD_SIGNATURE_INVALID,
+          TALER_EC_EXCHANGE_MANAGEMENT_KEYS_DENOMKEY_ADD_SIGNATURE_INVALID,
           GNUNET_h2s (&akc->d_sigs[i].h_denom_pub));
+        return GNUNET_DB_STATUS_HARD_ERROR;
       }
     }
     if (is_active)
@@ -253,7 +254,7 @@ add_keys (void *cls,
           MHD_HTTP_NOT_FOUND,
           TALER_EC_EXCHANGE_MANAGEMENT_KEYS_SIGNKEY_UNKNOWN,
           TALER_B2S (&akc->s_sigs[i].exchange_pub));
-        return qs;
+        return GNUNET_DB_STATUS_HARD_ERROR;
       }
     }
     else
@@ -273,11 +274,12 @@ add_keys (void *cls,
             &akc->s_sigs[i].master_sig))
       {
         GNUNET_break_op (0);
-        return TALER_MHD_reply_with_error (
+        *mhd_ret = TALER_MHD_reply_with_error (
           connection,
           MHD_HTTP_FORBIDDEN,
-          TALER_EC_EXCHANGE_MANAGEMENT_KEYS_DENOMKEY_ADD_SIGNATURE_INVALID,
+          TALER_EC_EXCHANGE_MANAGEMENT_KEYS_SIGNKEY_ADD_SIGNATURE_INVALID,
           GNUNET_h2s (&akc->d_sigs[i].h_denom_pub));
+        return GNUNET_DB_STATUS_HARD_ERROR;
       }
     }
     if (is_active)
diff --git a/src/lib/exchange_api_management_post_keys.c 
b/src/lib/exchange_api_management_post_keys.c
index b885df7f..7b37bb0c 100644
--- a/src/lib/exchange_api_management_post_keys.c
+++ b/src/lib/exchange_api_management_post_keys.c
@@ -95,6 +95,10 @@ handle_post_keys_finished (void *cls,
     hr.ec = TALER_JSON_get_error_code (json);
     hr.hint = TALER_JSON_get_error_hint (json);
     break;
+  case MHD_HTTP_NOT_FOUND:
+    hr.ec = TALER_JSON_get_error_code (json);
+    hr.hint = TALER_JSON_get_error_hint (json);
+    break;
   default:
     /* unexpected response code */
     GNUNET_break_op (0);

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]