gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated (2c88cff2 -> 1e6091d1)


From: gnunet
Subject: [taler-exchange] branch master updated (2c88cff2 -> 1e6091d1)
Date: Fri, 27 Nov 2020 00:05:42 +0100

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

grothoff pushed a change to branch master
in repository exchange.

    from 2c88cff2 add logic to parse and check secmod signatures
     new 1c1d4d99 cmd to add auditor
     new 98f59604 cmd to del auditor
     new 7ddd1da7 cmd to sign keys with offline process
     new 1e6091d1 cmd to add/del wire methods from list of accounts

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/include/taler_crypto_lib.h                     |  12 +
 src/include/taler_exchange_service.h               |  12 +-
 src/include/taler_signatures.h                     | 133 ++++++++
 src/include/taler_testing_lib.h                    | 128 +++++++-
 src/lib/exchange_api_management_auditor_disable.c  |   1 -
 src/lib/exchange_api_management_wire_disable.c     |   2 +-
 src/lib/exchange_api_management_wire_enable.c      |  20 +-
 src/testing/Makefile.am                            |   5 +
 src/testing/testing_api_cmd_auditor_add.c          | 340 +++++++++++++++++++++
 src/testing/testing_api_cmd_auditor_del.c          | 316 +++++++++++++++++++
 ...ditor.c => testing_api_cmd_offline_sign_keys.c} | 106 +++----
 src/testing/testing_api_cmd_wire_add.c             | 295 ++++++++++++++++++
 src/testing/testing_api_cmd_wire_del.c             | 282 +++++++++++++++++
 13 files changed, 1580 insertions(+), 72 deletions(-)
 create mode 100644 src/testing/testing_api_cmd_auditor_add.c
 create mode 100644 src/testing/testing_api_cmd_auditor_del.c
 copy src/testing/{testing_api_cmd_auditor_exec_auditor.c => 
testing_api_cmd_offline_sign_keys.c} (50%)
 create mode 100644 src/testing/testing_api_cmd_wire_add.c
 create mode 100644 src/testing/testing_api_cmd_wire_del.c

diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h
index d6f19f44..8be0bad4 100644
--- a/src/include/taler_crypto_lib.h
+++ b/src/include/taler_crypto_lib.h
@@ -222,6 +222,18 @@ struct TALER_MasterPublicKeyP
 };
 
 
+/**
+ * @brief Type of the private key used by the auditor.
+ */
+struct TALER_AuditorPrivateKeyP
+{
+  /**
+   * Taler uses EdDSA for the auditor's signing key.
+   */
+  struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv;
+};
+
+
 /**
  * @brief Type of the public key used by the auditor.
  */
diff --git a/src/include/taler_exchange_service.h 
b/src/include/taler_exchange_service.h
index 8b1feb15..4ad05a68 100644
--- a/src/include/taler_exchange_service.h
+++ b/src/include/taler_exchange_service.h
@@ -2398,7 +2398,6 @@ struct TALER_EXCHANGE_ManagementAuditorDisableHandle;
  * @param ctx the context
  * @param url HTTP base URL for the exchange
  * @param auditor_pub the public signing key of the auditor
- * @param auditor_url base URL of the auditor
  * @param validity_end when was this decided?
  * @param master_sig signature affirming the auditor addition
  * @param cb function to call with the exchange's result
@@ -2410,7 +2409,6 @@ TALER_EXCHANGE_management_disable_auditor (
   struct GNUNET_CURL_Context *ctx,
   const char *url,
   const struct TALER_AuditorPublicKeyP *auditor_pub,
-  const char *auditor_url,
   struct GNUNET_TIME_Absolute validity_end,
   const struct TALER_MasterSignatureP *master_sig,
   TALER_EXCHANGE_ManagementAuditorDisableCallback cb,
@@ -2453,7 +2451,10 @@ struct TALER_EXCHANGE_ManagementWireEnableHandle;
  * @param salt salt to use when hashing the account for the signature
  * @param payto_uri RFC 8905 URI of the exchange's bank account
  * @param validity_start when was this decided?
- * @param master_sig signature affirming the wire addition
+ * @param master_sig1 signature affirming the wire addition
+ *        of purpose #TALER_SIGNATURE_MASTER_ADD_WIRE
+ * @param master_sig2 signature affirming the validity of the account for 
clients;
+ *        of purpose #TALER_SIGNATURE_MASTER_WIRE_DETAILS.
  * @param cb function to call with the exchange's result
  * @param cb_cls closure for @a cb
  * @return the request handle; NULL upon error
@@ -2462,10 +2463,10 @@ struct TALER_EXCHANGE_ManagementWireEnableHandle *
 TALER_EXCHANGE_management_enable_wire (
   struct GNUNET_CURL_Context *ctx,
   const char *url,
-  const char *salt,
   const char *payto_uri,
   struct GNUNET_TIME_Absolute validity_start,
-  const struct TALER_MasterSignatureP *master_sig,
+  const struct TALER_MasterSignatureP *master_sig1,
+  const struct TALER_MasterSignatureP *master_sig2,
   TALER_EXCHANGE_ManagementWireEnableCallback cb,
   void *cb_cls);
 
@@ -2506,6 +2507,7 @@ struct TALER_EXCHANGE_ManagementWireDisableHandle;
  * @param payto_uri RFC 8905 URI of the exchange's bank account
  * @param validity_end when was this decided?
  * @param master_sig signature affirming the wire addition
+ *        of purpose #TALER_SIGNATURE_MASTER_DEL_WIRE
  * @param cb function to call with the exchange's result
  * @param cb_cls closure for @a cb
  * @return the request handle; NULL upon error
diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h
index d72dd11b..90d77244 100644
--- a/src/include/taler_signatures.h
+++ b/src/include/taler_signatures.h
@@ -46,6 +46,21 @@
 /* Exchange offline signatures (with master key) */
 /*********************************************/
 
+/**
+ * The given revocation key was revoked and must no longer be used.
+ */
+#define TALER_SIGNATURE_MASTER_SIGNING_KEY_REVOKED 1020
+
+/**
+ * Add payto URI to the list of our wire methods.
+ */
+#define TALER_SIGNATURE_MASTER_ADD_WIRE 1021
+
+/**
+ * Remove payto URI from the list of our wire methods.
+ */
+#define TALER_SIGNATURE_MASTER_DEL_WIRE 1023
+
 /**
  * Purpose for signing public keys signed by the exchange master key.
  */
@@ -56,6 +71,16 @@
  */
 #define TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY 1025
 
+/**
+ * Add an auditor to the list of our auditors.
+ */
+#define TALER_SIGNATURE_MASTER_ADD_AUDITOR 1026
+
+/**
+ * Remove an auditor from the list of our auditors.
+ */
+#define TALER_SIGNATURE_MASTER_DEL_AUDITOR 1027
+
 /**
  * Fees charged per (aggregate) wire transfer to the merchant.
  */
@@ -72,6 +97,7 @@
  */
 #define TALER_SIGNATURE_MASTER_WIRE_DETAILS 1030
 
+
 /*********************************************/
 /* Exchange online signatures (with signing key) */
 /*********************************************/
@@ -791,6 +817,113 @@ struct TALER_ExchangeKeySetPS
 };
 
 
+/**
+ * @brief Signature made by the exchange offline key over the information of
+ * an auditor to be added to the exchange's set of auditors.
+ */
+struct TALER_MasterAddAuditorPS
+{
+
+  /**
+   * Purpose is #TALER_SIGNATURE_MASTER_ADD_AUDITOR.   Signed
+   * by a `struct TALER_MasterPublicKeyP` using EdDSA.
+   */
+  struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
+
+  /**
+   * Time of the change.
+   */
+  struct GNUNET_TIME_AbsoluteNBO start_date;
+
+  /**
+   * Public key of the auditor.
+   */
+  struct TALER_AuditorPublicKeyP auditor_pub;
+
+  /**
+   * Hash over the auditor's URL.
+   */
+  struct GNUNET_HashCode h_auditor_url GNUNET_PACKED;
+};
+
+
+/**
+ * @brief Signature made by the exchange offline key over the information of
+ * an auditor to be removed from the exchange's set of auditors.
+ */
+struct TALER_MasterDelAuditorPS
+{
+
+  /**
+   * Purpose is #TALER_SIGNATURE_MASTER_DEL_AUDITOR.   Signed
+   * by a `struct TALER_MasterPublicKeyP` using EdDSA.
+   */
+  struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
+
+  /**
+   * Time of the change.
+   */
+  struct GNUNET_TIME_AbsoluteNBO end_date;
+
+  /**
+   * Public key of the auditor.
+   */
+  struct TALER_AuditorPublicKeyP auditor_pub;
+
+};
+
+
+/**
+ * @brief Signature made by the exchange offline key over the information of
+ * a payto:// URI to be added to the exchange's set of active wire accounts.
+ */
+struct TALER_MasterAddWirePS
+{
+
+  /**
+   * Purpose is #TALER_SIGNATURE_MASTER_ADD_WIRE.   Signed
+   * by a `struct TALER_MasterPublicKeyP` using EdDSA.
+   */
+  struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
+
+  /**
+   * Time of the change.
+   */
+  struct GNUNET_TIME_AbsoluteNBO start_date;
+
+  /**
+   * Hash over the exchange's payto URI.
+   */
+  struct GNUNET_HashCode h_wire GNUNET_PACKED;
+};
+
+
+/**
+ * @brief Signature made by the exchange offline key over the information of
+ * a  wire method to be removed to the exchange's set of active accounts.
+ */
+struct TALER_MasterDelWirePS
+{
+
+  /**
+   * Purpose is #TALER_SIGNATURE_MASTER_DEL_WIRE.   Signed
+   * by a `struct TALER_MasterPublicKeyP` using EdDSA.
+   */
+  struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
+
+  /**
+   * Time of the change.
+   */
+  struct GNUNET_TIME_AbsoluteNBO end_date;
+
+  /**
+   * Hash over the exchange's payto URI.
+   */
+  struct GNUNET_HashCode h_wire GNUNET_PACKED;
+
+};
+
+
 /**
  * @brief Information about a denomination key. Denomination keys
  * are used to sign coins of a certain value into existence.
diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h
index 74148b8f..05172644 100644
--- a/src/include/taler_testing_lib.h
+++ b/src/include/taler_testing_lib.h
@@ -417,7 +417,7 @@ struct TALER_TESTING_Interpreter
   struct GNUNET_OS_Process *exchanged;
 
   /**
-   * GNUNET_OK if key state should be reloaded.  NOTE: this
+   * #GNUNET_OK if key state should be reloaded.  NOTE: this
    * field can be removed because a new "send signal" command
    * has been introduced.
    */
@@ -1083,8 +1083,6 @@ struct TALER_TESTING_Command
 TALER_TESTING_cmd_exchanges_with_retry (struct TALER_TESTING_Command cmd);
 
 
-/* ***** Commands ONLY for testing (/admin-API) **** */
-
 /**
  * Create /admin/add-incoming command.
  *
@@ -2021,6 +2019,130 @@ struct TALER_TESTING_Command
 TALER_TESTING_cmd_stat (struct TALER_TESTING_Timer *timers);
 
 
+/**
+ * Add the auditor to the exchange's list of auditors.
+ * The information about the auditor is taken from the
+ * "[auditor]" section in the configuration file.
+ *
+ * @param label command label.
+ * @param expected_http_status expected HTTP status from exchange
+ * @param bad_sig should we use a bogus signature?
+ * @return the command
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_auditor_add (const char *label,
+                               unsigned int expected_http_status,
+                               bool bad_sig);
+
+
+/**
+ * Remove the auditor from the exchange's list of auditors.
+ * The information about the auditor is taken from the
+ * "[auditor]" section in the configuration file.
+ *
+ * @param label command label.
+ * @param expected_http_status expected HTTP status from exchange
+ * @param bad_sig should we use a bogus signature?
+ * @return the command
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_auditor_del (const char *label,
+                               unsigned int expected_http_status,
+                               bool bad_sig);
+
+
+/**
+ * Add the given payto-URI bank account to the list of bank
+ * accounts used by the exchange.
+ *
+ * @param label command label.
+ * @param payto_uri URI identifying the bank account
+ * @param expected_http_status expected HTTP status from exchange
+ * @param bad_sig should we use a bogus signature?
+ * @return the command
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_wire_add (const char *label,
+                            const char *payto_uri,
+                            unsigned int expected_http_status,
+                            bool bad_sig);
+
+
+/**
+ * Remove the given payto-URI bank account from the list of bank
+ * accounts used by the exchange.
+ *
+ * @param label command label.
+ * @param payto_uri URI identifying the bank account
+ * @param expected_http_status expected HTTP status from exchange
+ * @param bad_sig should we use a bogus signature?
+ * @return the command
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_wire_del (const char *label,
+                            const char *payto_uri,
+                            unsigned int expected_http_status,
+                            bool bad_sig);
+
+
+/**
+ * Sign all exchange denomination and online signing keys
+ * with the "offline" key and provide those signatures to
+ * the exchange. (Downloads the keys, makes the signature
+ * and uploads the result, all in one.)
+ *
+ * @param label command label.
+ * @param config_filename configuration filename.
+ * @return the command
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_offline_sign_keys (const char *label,
+                                     const char *config_filename);
+
+
+/**
+ * Revoke an exchange denomination key.
+ *
+ * @param label command label.
+ * @param denom_ref reference to a command that identifies
+ *        a denomination key (i.e. because it was used to
+ *        withdraw a coin).
+ * @return the command
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_revoke_denom_key (const char *label,
+                                    const char *denom_ref);
+
+
+/**
+ * Have the auditor affirm that it is auditing the given
+ * denomination key and upload the auditor's signature to
+ * the exchange.
+ *
+ * @param label command label.
+ * @param denom_ref reference to a command that identifies
+ *        a denomination key (i.e. because it was used to
+ *        withdraw a coin).
+ * @return the command
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_auditor_add_denom_key (const char *denom_ref);
+
+
+/**
+ * Revoke an exchange signing key.
+ *
+ * @param label command label.
+ * @param denom_ref reference to a command that identifies
+ *        a signing key (i.e. because it was used to
+ *        sign a deposit confirmation).
+ * @return the command
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_revoke_denom_key (const char *label,
+                                    const char *signkey_ref);
+
+
 /* *** Generic trait logic for implementing traits ********* */
 
 /**
diff --git a/src/lib/exchange_api_management_auditor_disable.c 
b/src/lib/exchange_api_management_auditor_disable.c
index d9181870..823f9b13 100644
--- a/src/lib/exchange_api_management_auditor_disable.c
+++ b/src/lib/exchange_api_management_auditor_disable.c
@@ -128,7 +128,6 @@ TALER_EXCHANGE_management_disable_auditor (
   struct GNUNET_CURL_Context *ctx,
   const char *url,
   const struct TALER_AuditorPublicKeyP *auditor_pub,
-  const char *auditor_url,
   struct GNUNET_TIME_Absolute validity_end,
   const struct TALER_MasterSignatureP *master_sig,
   TALER_EXCHANGE_ManagementAuditorDisableCallback cb,
diff --git a/src/lib/exchange_api_management_wire_disable.c 
b/src/lib/exchange_api_management_wire_disable.c
index b510970a..157d146b 100644
--- a/src/lib/exchange_api_management_wire_disable.c
+++ b/src/lib/exchange_api_management_wire_disable.c
@@ -152,7 +152,7 @@ TALER_EXCHANGE_management_disable_wire (
   body = json_pack ("{s:s, s:o, s:o}",
                     "payto_uri",
                     payto_uri,
-                    "master_sig",
+                    "master_sig_del",
                     GNUNET_JSON_from_data_auto (master_sig),
                     "validity_end",
                     GNUNET_JSON_from_time_abs (validity_end));
diff --git a/src/lib/exchange_api_management_wire_enable.c 
b/src/lib/exchange_api_management_wire_enable.c
index 298fe5d2..9de52fe0 100644
--- a/src/lib/exchange_api_management_wire_enable.c
+++ b/src/lib/exchange_api_management_wire_enable.c
@@ -122,10 +122,12 @@ handle_auditor_enable_finished (void *cls,
  *
  * @param ctx the context
  * @param url HTTP base URL for the exchange
- * @param salt salt to use when hashing the account for the signature
  * @param payto_uri RFC 8905 URI of the exchange's bank account
  * @param validity_start when was this decided?
- * @param master_sig signature affirming the wire addition
+ * @param master_sig1 signature affirming the wire addition
+ *        of purpose #TALER_SIGNATURE_MASTER_ADD_WIRE
+ * @param master_sig2 signature affirming the validity of the account for 
clients;
+ *        of purpose #TALER_SIGNATURE_MASTER_WIRE_DETAILS.
  * @param cb function to call with the exchange's result
  * @param cb_cls closure for @a cb
  * @return the request handle; NULL upon error
@@ -134,10 +136,10 @@ struct TALER_EXCHANGE_ManagementWireEnableHandle *
 TALER_EXCHANGE_management_enable_wire (
   struct GNUNET_CURL_Context *ctx,
   const char *url,
-  const char *salt,
   const char *payto_uri,
   struct GNUNET_TIME_Absolute validity_start,
-  const struct TALER_MasterSignatureP *master_sig,
+  const struct TALER_MasterSignatureP *master_sig1,
+  const struct TALER_MasterSignatureP *master_sig2,
   TALER_EXCHANGE_ManagementWireEnableCallback cb,
   void *cb_cls)
 {
@@ -159,13 +161,13 @@ TALER_EXCHANGE_management_enable_wire (
     GNUNET_free (wh);
     return NULL;
   }
-  body = json_pack ("{s:s, s:s, s:o, s:o}",
+  body = json_pack ("{s:s, s:s, s:o, s:o, s:o}",
                     "payto_uri",
                     payto_uri,
-                    "salt",
-                    salt,
-                    "master_sig",
-                    GNUNET_JSON_from_data_auto (master_sig),
+                    "master_sig_add",
+                    GNUNET_JSON_from_data_auto (master_sig1),
+                    "master_sig_wire",
+                    GNUNET_JSON_from_data_auto (master_sig2),
                     "validity_start",
                     GNUNET_JSON_from_time_abs (validity_start));
   if (NULL == body)
diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am
index fc2f7f87..0850f842 100644
--- a/src/testing/Makefile.am
+++ b/src/testing/Makefile.am
@@ -35,6 +35,8 @@ libtalertesting_la_LDFLAGS = \
   -version-info 0:0:0 \
   -no-undefined
 libtalertesting_la_SOURCES = \
+  testing_api_cmd_auditor_add.c \
+  testing_api_cmd_auditor_del.c \
   testing_api_cmd_auditor_deposit_confirmation.c \
   testing_api_cmd_auditor_exchanges.c \
   testing_api_cmd_auditor_exec_auditor.c \
@@ -57,6 +59,7 @@ libtalertesting_la_SOURCES = \
   testing_api_cmd_exec_transfer.c \
   testing_api_cmd_exec_wirewatch.c \
   testing_api_cmd_insert_deposit.c \
+  testing_api_cmd_offline_sign_keys.c \
   testing_api_cmd_recoup.c \
   testing_api_cmd_refund.c \
   testing_api_cmd_refresh.c \
@@ -70,6 +73,8 @@ libtalertesting_la_SOURCES = \
   testing_api_cmd_transfer_get.c \
   testing_api_cmd_wait.c \
   testing_api_cmd_wire.c \
+  testing_api_cmd_wire_add.c \
+  testing_api_cmd_wire_del.c \
   testing_api_cmd_withdraw.c \
   testing_api_helpers_auditor.c \
   testing_api_helpers_bank.c \
diff --git a/src/testing/testing_api_cmd_auditor_add.c 
b/src/testing/testing_api_cmd_auditor_add.c
new file mode 100644
index 00000000..0a37c73d
--- /dev/null
+++ b/src/testing/testing_api_cmd_auditor_add.c
@@ -0,0 +1,340 @@
+/*
+  This file is part of TALER
+  Copyright (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 testing/testing_api_cmd_auditor_add.c
+ * @brief command for testing /auditor_add.
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_json_lib.h"
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_testing_lib.h"
+#include "taler_signatures.h"
+#include "backoff.h"
+
+
+/**
+ * State for a "auditor_add" CMD.
+ */
+struct AuditorAddState
+{
+
+  /**
+   * Auditor enable handle while operation is running.
+   */
+  struct TALER_EXCHANGE_ManagementAuditorEnableHandle *dh;
+
+  /**
+   * Our interpreter.
+   */
+  struct TALER_TESTING_Interpreter *is;
+
+  /**
+   * Expected HTTP response code.
+   */
+  unsigned int expected_response_code;
+
+  /**
+   * Should we make the request with a bad master_sig signature?
+   */
+  bool bad_sig;
+};
+
+
+/**
+ * Callback to analyze the /management/auditors response, just used to check
+ * if the response code is acceptable.
+ *
+ * @param cls closure.
+ * @param hr HTTP response details
+ */
+static void
+auditor_add_cb (void *cls,
+                const struct TALER_EXCHANGE_HttpResponse *hr)
+{
+  struct AuditorAddState *ds = cls;
+
+  ds->dh = NULL;
+  if (ds->expected_response_code != hr->http_status)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unexpected response code %u to command %s in %s:%u\n",
+                hr->http_status,
+                ds->is->commands[ds->is->ip].label,
+                __FILE__,
+                __LINE__);
+    json_dumpf (hr->reply,
+                stderr,
+                0);
+    TALER_TESTING_interpreter_fail (ds->is);
+    return;
+  }
+  TALER_TESTING_interpreter_next (ds->is);
+}
+
+
+/**
+ * Run the command.
+ *
+ * @param cls closure.
+ * @param cmd the command to execute.
+ * @param is the interpreter state.
+ */
+static void
+auditor_add_run (void *cls,
+                 const struct TALER_TESTING_Command *cmd,
+                 struct TALER_TESTING_Interpreter *is)
+{
+  struct AuditorAddState *ds = cls;
+  struct TALER_AuditorPublicKeyP auditor_pub;
+  char *auditor_url;
+  char *exchange_url;
+  struct TALER_MasterSignatureP master_sig;
+  struct GNUNET_TIME_Absolute now;
+
+  (void) cmd;
+  now = GNUNET_TIME_absolute_get ();
+  (void) GNUNET_TIME_round_abs (&now);
+  ds->is = is;
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_filename (is->cfg,
+                                               "auditor",
+                                               "BASE_URL",
+                                               &auditor_url))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "auditor",
+                               "BASE_URL");
+    TALER_TESTING_interpreter_next (ds->is);
+    return;
+  }
+  if (ds->bad_sig)
+  {
+    memset (&master_sig,
+            42,
+            sizeof (master_sig));
+  }
+  else
+  {
+    char *fn;
+    struct TALER_MasterPrivateKeyP master_priv;
+    struct TALER_AuditorPrivateKeyP auditor_priv;
+
+    if (GNUNET_OK !=
+        GNUNET_CONFIGURATION_get_value_filename (is->cfg,
+                                                 "exchange-offline",
+                                                 "MASTER_PRIV_FILE",
+                                                 &fn))
+    {
+      GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                                 "exchange-offline",
+                                 "MASTER_PRIV_FILE");
+      TALER_TESTING_interpreter_next (ds->is);
+      GNUNET_free (auditor_url);
+      return;
+    }
+    if (GNUNET_SYSERR ==
+        GNUNET_DISK_directory_create_for_file (fn))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Could not setup directory for master private key file 
`%s'\n",
+                  fn);
+      GNUNET_free (fn);
+      TALER_TESTING_interpreter_next (ds->is);
+      GNUNET_free (auditor_url);
+      return;
+    }
+    if (GNUNET_OK !=
+        GNUNET_CRYPTO_eddsa_key_from_file (fn,
+                                           GNUNET_YES,
+                                           &master_priv.eddsa_priv))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Could not load master private key from `%s'\n",
+                  fn);
+      GNUNET_free (fn);
+      TALER_TESTING_interpreter_next (ds->is);
+      GNUNET_free (auditor_url);
+      return;
+    }
+    GNUNET_free (fn);
+
+    if (GNUNET_OK !=
+        GNUNET_CONFIGURATION_get_value_filename (is->cfg,
+                                                 "auditor",
+                                                 "AUDITOR_PRIV_FILE",
+                                                 &fn))
+    {
+      GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                                 "auditor",
+                                 "AUDITOR_PRIV_FILE");
+      TALER_TESTING_interpreter_next (ds->is);
+      GNUNET_free (auditor_url);
+      return;
+    }
+    if (GNUNET_SYSERR ==
+        GNUNET_DISK_directory_create_for_file (fn))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Could not setup directory for auditor private key file 
`%s'\n",
+                  fn);
+      GNUNET_free (fn);
+      TALER_TESTING_interpreter_next (ds->is);
+      GNUNET_free (auditor_url);
+      return;
+    }
+    if (GNUNET_OK !=
+        GNUNET_CRYPTO_eddsa_key_from_file (fn,
+                                           GNUNET_YES,
+                                           &auditor_priv.eddsa_priv))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Could not load auditor private key from `%s'\n",
+                  fn);
+      GNUNET_free (fn);
+      TALER_TESTING_interpreter_next (ds->is);
+      GNUNET_free (auditor_url);
+      return;
+    }
+    GNUNET_free (fn);
+    GNUNET_CRYPTO_eddsa_key_get_public (&auditor_priv.eddsa_priv,
+                                        &auditor_pub.eddsa_pub);
+
+    /* now sign */
+    {
+      struct TALER_MasterAddAuditorPS kv = {
+        .purpose.purpose = htonl (TALER_SIGNATURE_MASTER_ADD_AUDITOR),
+        .purpose.size = htonl (sizeof (kv)),
+        .start_date = GNUNET_TIME_absolute_hton (now),
+        .auditor_pub = auditor_pub,
+      };
+
+      GNUNET_CRYPTO_hash (auditor_url,
+                          strlen (auditor_url) + 1,
+                          &kv.h_auditor_url);
+      /* Finally sign ... */
+      GNUNET_CRYPTO_eddsa_sign (&master_priv.eddsa_priv,
+                                &kv,
+                                &master_sig.eddsa_signature);
+    }
+  }
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (is->cfg,
+                                             "exchange",
+                                             "BASE_URL",
+                                             &exchange_url))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "exchange",
+                               "BASE_URL");
+    GNUNET_free (auditor_url);
+    TALER_TESTING_interpreter_next (ds->is);
+    return;
+  }
+  ds->dh = TALER_EXCHANGE_management_enable_auditor (
+    is->ctx,
+    exchange_url,
+    &auditor_pub,
+    auditor_url,
+    now,
+    &master_sig,
+    &auditor_add_cb,
+    ds);
+  GNUNET_free (exchange_url);
+  GNUNET_free (auditor_url);
+  if (NULL == ds->dh)
+  {
+    GNUNET_break (0);
+    TALER_TESTING_interpreter_fail (is);
+    return;
+  }
+}
+
+
+/**
+ * Free the state of a "auditor_add" CMD, and possibly cancel a
+ * pending operation thereof.
+ *
+ * @param cls closure, must be a `struct AuditorAddState`.
+ * @param cmd the command which is being cleaned up.
+ */
+static void
+auditor_add_cleanup (void *cls,
+                     const struct TALER_TESTING_Command *cmd)
+{
+  struct AuditorAddState *ds = cls;
+
+  if (NULL != ds->dh)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Command %u (%s) did not complete\n",
+                ds->is->ip,
+                cmd->label);
+    TALER_EXCHANGE_management_enable_auditor_cancel (ds->dh);
+    ds->dh = NULL;
+  }
+  GNUNET_free (ds);
+}
+
+
+/**
+ * Offer internal data from a "auditor_add" CMD, to other commands.
+ *
+ * @param cls closure.
+ * @param[out] ret result.
+ * @param trait name of the trait.
+ * @param index index number of the object to offer.
+ *
+ * @return #GNUNET_OK on success.
+ */
+static int
+auditor_add_traits (void *cls,
+                    const void **ret,
+                    const char *trait,
+                    unsigned int index)
+{
+  return GNUNET_NO;
+}
+
+
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_auditor_add (const char *label,
+                               unsigned int expected_http_status,
+                               bool bad_sig)
+{
+  struct AuditorAddState *ds;
+
+  ds = GNUNET_new (struct AuditorAddState);
+  ds->expected_response_code = expected_http_status;
+  ds->bad_sig = bad_sig;
+  {
+    struct TALER_TESTING_Command cmd = {
+      .cls = ds,
+      .label = label,
+      .run = &auditor_add_run,
+      .cleanup = &auditor_add_cleanup,
+      .traits = &auditor_add_traits
+    };
+
+    return cmd;
+  }
+}
+
+
+/* end of testing_api_cmd_auditor_add.c */
diff --git a/src/testing/testing_api_cmd_auditor_del.c 
b/src/testing/testing_api_cmd_auditor_del.c
new file mode 100644
index 00000000..11efbd40
--- /dev/null
+++ b/src/testing/testing_api_cmd_auditor_del.c
@@ -0,0 +1,316 @@
+/*
+  This file is part of TALER
+  Copyright (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 testing/testing_api_cmd_auditor_del.c
+ * @brief command for testing /management/auditor/disable.
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_json_lib.h"
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_testing_lib.h"
+#include "taler_signatures.h"
+#include "backoff.h"
+
+
+/**
+ * State for a "auditor_del" CMD.
+ */
+struct AuditorDelState
+{
+
+  /**
+   * Auditor enable handle while operation is running.
+   */
+  struct TALER_EXCHANGE_ManagementAuditorDisableHandle *dh;
+
+  /**
+   * Our interpreter.
+   */
+  struct TALER_TESTING_Interpreter *is;
+
+  /**
+   * Expected HTTP response code.
+   */
+  unsigned int expected_response_code;
+
+  /**
+   * Should we make the request with a bad master_sig signature?
+   */
+  bool bad_sig;
+};
+
+
+/**
+ * Callback to analyze the /management/auditors response, just used to check
+ * if the response code is acceptable.
+ *
+ * @param cls closure.
+ * @param hr HTTP response details
+ */
+static void
+auditor_del_cb (void *cls,
+                const struct TALER_EXCHANGE_HttpResponse *hr)
+{
+  struct AuditorDelState *ds = cls;
+
+  ds->dh = NULL;
+  if (ds->expected_response_code != hr->http_status)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unexpected response code %u to command %s in %s:%u\n",
+                hr->http_status,
+                ds->is->commands[ds->is->ip].label,
+                __FILE__,
+                __LINE__);
+    json_dumpf (hr->reply,
+                stderr,
+                0);
+    TALER_TESTING_interpreter_fail (ds->is);
+    return;
+  }
+  TALER_TESTING_interpreter_next (ds->is);
+}
+
+
+/**
+ * Run the command.
+ *
+ * @param cls closure.
+ * @param cmd the command to execute.
+ * @param is the interpreter state.
+ */
+static void
+auditor_del_run (void *cls,
+                 const struct TALER_TESTING_Command *cmd,
+                 struct TALER_TESTING_Interpreter *is)
+{
+  struct AuditorDelState *ds = cls;
+  struct TALER_AuditorPublicKeyP auditor_pub;
+  char *exchange_url;
+  struct TALER_MasterSignatureP master_sig;
+  struct GNUNET_TIME_Absolute now;
+
+  (void) cmd;
+  now = GNUNET_TIME_absolute_get ();
+  (void) GNUNET_TIME_round_abs (&now);
+  ds->is = is;
+  if (ds->bad_sig)
+  {
+    memset (&master_sig,
+            42,
+            sizeof (master_sig));
+  }
+  else
+  {
+    char *fn;
+    struct TALER_MasterPrivateKeyP master_priv;
+    struct TALER_AuditorPrivateKeyP auditor_priv;
+
+    if (GNUNET_OK !=
+        GNUNET_CONFIGURATION_get_value_filename (is->cfg,
+                                                 "exchange-offline",
+                                                 "MASTER_PRIV_FILE",
+                                                 &fn))
+    {
+      GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                                 "exchange-offline",
+                                 "MASTER_PRIV_FILE");
+      TALER_TESTING_interpreter_next (ds->is);
+      return;
+    }
+    if (GNUNET_SYSERR ==
+        GNUNET_DISK_directory_create_for_file (fn))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Could not setup directory for master private key file 
`%s'\n",
+                  fn);
+      GNUNET_free (fn);
+      TALER_TESTING_interpreter_next (ds->is);
+      return;
+    }
+    if (GNUNET_OK !=
+        GNUNET_CRYPTO_eddsa_key_from_file (fn,
+                                           GNUNET_YES,
+                                           &master_priv.eddsa_priv))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Could not load master private key from `%s'\n",
+                  fn);
+      GNUNET_free (fn);
+      TALER_TESTING_interpreter_next (ds->is);
+      return;
+    }
+    GNUNET_free (fn);
+
+
+    if (GNUNET_OK !=
+        GNUNET_CONFIGURATION_get_value_filename (is->cfg,
+                                                 "auditor",
+                                                 "AUDITOR_PRIV_FILE",
+                                                 &fn))
+    {
+      GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                                 "auditor",
+                                 "AUDITOR_PRIV_FILE");
+      TALER_TESTING_interpreter_next (ds->is);
+      return;
+    }
+    if (GNUNET_SYSERR ==
+        GNUNET_DISK_directory_create_for_file (fn))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Could not setup directory for auditor private key file 
`%s'\n",
+                  fn);
+      GNUNET_free (fn);
+      TALER_TESTING_interpreter_next (ds->is);
+      return;
+    }
+    if (GNUNET_OK !=
+        GNUNET_CRYPTO_eddsa_key_from_file (fn,
+                                           GNUNET_YES,
+                                           &auditor_priv.eddsa_priv))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Could not load auditor private key from `%s'\n",
+                  fn);
+      GNUNET_free (fn);
+      TALER_TESTING_interpreter_next (ds->is);
+      return;
+    }
+    GNUNET_free (fn);
+    GNUNET_CRYPTO_eddsa_key_get_public (&auditor_priv.eddsa_priv,
+                                        &auditor_pub.eddsa_pub);
+
+    /* now sign */
+    {
+      struct TALER_MasterDelAuditorPS kv = {
+        .purpose.purpose = htonl (TALER_SIGNATURE_MASTER_DEL_AUDITOR),
+        .purpose.size = htonl (sizeof (kv)),
+        .end_date = GNUNET_TIME_absolute_hton (now),
+        .auditor_pub = auditor_pub,
+      };
+
+      /* Finally sign ... */
+      GNUNET_CRYPTO_eddsa_sign (&master_priv.eddsa_priv,
+                                &kv,
+                                &master_sig.eddsa_signature);
+    }
+  }
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (is->cfg,
+                                             "exchange",
+                                             "BASE_URL",
+                                             &exchange_url))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "exchange",
+                               "BASE_URL");
+    TALER_TESTING_interpreter_next (ds->is);
+    return;
+  }
+  ds->dh = TALER_EXCHANGE_management_disable_auditor (
+    is->ctx,
+    exchange_url,
+    &auditor_pub,
+    now,
+    &master_sig,
+    &auditor_del_cb,
+    ds);
+  GNUNET_free (exchange_url);
+  if (NULL == ds->dh)
+  {
+    GNUNET_break (0);
+    TALER_TESTING_interpreter_fail (is);
+    return;
+  }
+}
+
+
+/**
+ * Free the state of a "auditor_del" CMD, and possibly cancel a
+ * pending operation thereof.
+ *
+ * @param cls closure, must be a `struct AuditorDelState`.
+ * @param cmd the command which is being cleaned up.
+ */
+static void
+auditor_del_cleanup (void *cls,
+                     const struct TALER_TESTING_Command *cmd)
+{
+  struct AuditorDelState *ds = cls;
+
+  if (NULL != ds->dh)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Command %u (%s) did not complete\n",
+                ds->is->ip,
+                cmd->label);
+    TALER_EXCHANGE_management_disable_auditor_cancel (ds->dh);
+    ds->dh = NULL;
+  }
+  GNUNET_free (ds);
+}
+
+
+/**
+ * Offer internal data from a "auditor_del" CMD, to other commands.
+ *
+ * @param cls closure.
+ * @param[out] ret result.
+ * @param trait name of the trait.
+ * @param index index number of the object to offer.
+ *
+ * @return #GNUNET_OK on success.
+ */
+static int
+auditor_del_traits (void *cls,
+                    const void **ret,
+                    const char *trait,
+                    unsigned int index)
+{
+  return GNUNET_NO;
+}
+
+
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_auditor_del (const char *label,
+                               unsigned int expected_http_status,
+                               bool bad_sig)
+{
+  struct AuditorDelState *ds;
+
+  ds = GNUNET_new (struct AuditorDelState);
+  ds->expected_response_code = expected_http_status;
+  ds->bad_sig = bad_sig;
+  {
+    struct TALER_TESTING_Command cmd = {
+      .cls = ds,
+      .label = label,
+      .run = &auditor_del_run,
+      .cleanup = &auditor_del_cleanup,
+      .traits = &auditor_del_traits
+    };
+
+    return cmd;
+  }
+}
+
+
+/* end of testing_api_cmd_auditor_del.c */
diff --git a/src/testing/testing_api_cmd_auditor_exec_auditor.c 
b/src/testing/testing_api_cmd_offline_sign_keys.c
similarity index 50%
copy from src/testing/testing_api_cmd_auditor_exec_auditor.c
copy to src/testing/testing_api_cmd_offline_sign_keys.c
index 06dfe91b..3b087409 100644
--- a/src/testing/testing_api_cmd_auditor_exec_auditor.c
+++ b/src/testing/testing_api_cmd_offline_sign_keys.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2018 Taler Systems SA
+  Copyright (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
@@ -16,9 +16,10 @@
   License along with TALER; see the file COPYING.  If not,
   see <http://www.gnu.org/licenses/>
 */
+
 /**
- * @file testing/testing_api_cmd_auditor_exec_auditor.c
- * @brief run the taler-auditor command
+ * @file testing/testing_api_cmd_offline_sign_keys.c
+ * @brief run the taler-exchange-offline command to download, sign and upload 
keys
  * @author Marcello Stanisci
  * @author Christian Grothoff
  */
@@ -30,84 +31,89 @@
 
 
 /**
- * State for a "auditor" CMD.
+ * State for a "offlinesign" CMD.
  */
-struct AuditorState
+struct OfflineSignState
 {
 
   /**
-   * Process for the "auditor" command.
+   * Process for the "offlinesign" command.
    */
-  struct GNUNET_OS_Process *auditor_proc;
+  struct GNUNET_OS_Process *offlinesign_proc;
 
   /**
    * Configuration file used by the command.
    */
   const char *config_filename;
+
 };
 
 
 /**
- * Run the command; calls the `taler-auditor' program.
+ * Run the command; calls the `taler-exchange-offline' program.
  *
  * @param cls closure.
  * @param cmd the commaind being run.
  * @param is interpreter state.
  */
 static void
-auditor_run (void *cls,
-             const struct TALER_TESTING_Command *cmd,
-             struct TALER_TESTING_Interpreter *is)
+offlinesign_run (void *cls,
+                 const struct TALER_TESTING_Command *cmd,
+                 struct TALER_TESTING_Interpreter *is)
 {
-  struct AuditorState *ks = cls;
-
-  (void) cmd;
-  ks->auditor_proc
-    = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
-                               NULL, NULL, NULL,
-                               "taler-auditor",
-                               "taler-auditor",
-                               "-c", ks->config_filename,
-                               NULL);
-  if (NULL == ks->auditor_proc)
+  struct OfflineSignState *ks = cls;
+
+  ks->offlinesign_proc
+    = GNUNET_OS_start_process (
+        GNUNET_OS_INHERIT_STD_ALL,
+        NULL, NULL, NULL,
+        "taler-exchange-offline",
+        "taler-exchange-offline",
+        "-c", ks->config_filename,
+        "--online",
+        "download sign upload",
+        NULL);
+  if (NULL == ks->offlinesign_proc)
   {
     GNUNET_break (0);
     TALER_TESTING_interpreter_fail (is);
     return;
   }
+  /* This function does not tell whether the command
+   * succeeded or not!  */
   TALER_TESTING_wait_for_sigchld (is);
 }
 
 
 /**
- * Free the state of a "auditor" CMD, and possibly kills its
+ * Free the state of a "offlinesign" CMD, and possibly kills its
  * process if it did not terminate correctly.
  *
  * @param cls closure.
  * @param cmd the command being freed.
  */
 static void
-auditor_cleanup (void *cls,
-                 const struct TALER_TESTING_Command *cmd)
+offlinesign_cleanup (void *cls,
+                     const struct TALER_TESTING_Command *cmd)
 {
-  struct AuditorState *ks = cls;
+  struct OfflineSignState *ks = cls;
 
   (void) cmd;
-  if (NULL != ks->auditor_proc)
+  if (NULL != ks->offlinesign_proc)
   {
     GNUNET_break (0 ==
-                  GNUNET_OS_process_kill (ks->auditor_proc,
+                  GNUNET_OS_process_kill (ks->offlinesign_proc,
                                           SIGKILL));
-    GNUNET_OS_process_wait (ks->auditor_proc);
-    GNUNET_OS_process_destroy (ks->auditor_proc);
-    ks->auditor_proc = NULL;
+    GNUNET_OS_process_wait (ks->offlinesign_proc);
+    GNUNET_OS_process_destroy (ks->offlinesign_proc);
+    ks->offlinesign_proc = NULL;
   }
   GNUNET_free (ks);
 }
 
 
 /**
- * Offer "auditor" CMD internal data to other commands.
+ * Offer "offlinesign" CMD internal data to other commands.
  *
  * @param cls closure.
  * @param[out] ret result
@@ -116,14 +122,15 @@ auditor_cleanup (void *cls,
  * @return #GNUNET_OK on success.
  */
 static int
-auditor_traits (void *cls,
-                const void **ret,
-                const char *trait,
-                unsigned int index)
+offlinesign_traits (void *cls,
+                    const void **ret,
+                    const char *trait,
+                    unsigned int index)
 {
-  struct AuditorState *ks = cls;
+  struct OfflineSignState *ks = cls;
   struct TALER_TESTING_Trait traits[] = {
-    TALER_TESTING_make_trait_process (0, &ks->auditor_proc),
+    TALER_TESTING_make_trait_process (0,
+                                      &ks->offlinesign_proc),
     TALER_TESTING_trait_end ()
   };
 
@@ -134,28 +141,21 @@ auditor_traits (void *cls,
 }
 
 
-/**
- * Make the "exec-auditor" CMD.
- *
- * @param label command label.
- * @param config_filename configuration filename.
- * @return the command.
- */
 struct TALER_TESTING_Command
-TALER_TESTING_cmd_exec_auditor (const char *label,
-                                const char *config_filename)
+TALER_TESTING_cmd_exec_offline_sign_keys (const char *label,
+                                          const char *config_filename)
 {
-  struct AuditorState *ks;
+  struct OfflineSignState *ks;
 
-  ks = GNUNET_new (struct AuditorState);
+  ks = GNUNET_new (struct OfflineSignState);
   ks->config_filename = config_filename;
   {
     struct TALER_TESTING_Command cmd = {
       .cls = ks,
       .label = label,
-      .run = &auditor_run,
-      .cleanup = &auditor_cleanup,
-      .traits = &auditor_traits
+      .run = &offlinesign_run,
+      .cleanup = &offlinesign_cleanup,
+      .traits = &offlinesign_traits
     };
 
     return cmd;
@@ -163,4 +163,4 @@ TALER_TESTING_cmd_exec_auditor (const char *label,
 }
 
 
-/* end of testing_auditor_api_cmd_exec_auditor.c */
+/* end of testing_api_cmd_exec_offline_sign_keys.c */
diff --git a/src/testing/testing_api_cmd_wire_add.c 
b/src/testing/testing_api_cmd_wire_add.c
new file mode 100644
index 00000000..0384e78a
--- /dev/null
+++ b/src/testing/testing_api_cmd_wire_add.c
@@ -0,0 +1,295 @@
+/*
+  This file is part of TALER
+  Copyright (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 testing/testing_api_cmd_wire_add.c
+ * @brief command for testing POST to /management/wire
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_json_lib.h"
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_testing_lib.h"
+#include "taler_signatures.h"
+#include "backoff.h"
+
+
+/**
+ * State for a "wire_add" CMD.
+ */
+struct WireAddState
+{
+
+  /**
+   * Wire enable handle while operation is running.
+   */
+  struct TALER_EXCHANGE_ManagementWireEnableHandle *dh;
+
+  /**
+   * Our interpreter.
+   */
+  struct TALER_TESTING_Interpreter *is;
+
+  /**
+   * Account to add.
+   */
+  const char *payto_uri;
+
+  /**
+   * Expected HTTP response code.
+   */
+  unsigned int expected_response_code;
+
+  /**
+   * Should we make the request with a bad master_sig signature?
+   */
+  bool bad_sig;
+};
+
+
+/**
+ * Callback to analyze the /management/wire response, just used to check
+ * if the response code is acceptable.
+ *
+ * @param cls closure.
+ * @param hr HTTP response details
+ */
+static void
+wire_add_cb (void *cls,
+             const struct TALER_EXCHANGE_HttpResponse *hr)
+{
+  struct WireAddState *ds = cls;
+
+  ds->dh = NULL;
+  if (ds->expected_response_code != hr->http_status)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unexpected response code %u to command %s in %s:%u\n",
+                hr->http_status,
+                ds->is->commands[ds->is->ip].label,
+                __FILE__,
+                __LINE__);
+    json_dumpf (hr->reply,
+                stderr,
+                0);
+    TALER_TESTING_interpreter_fail (ds->is);
+    return;
+  }
+  TALER_TESTING_interpreter_next (ds->is);
+}
+
+
+/**
+ * Run the command.
+ *
+ * @param cls closure.
+ * @param cmd the command to execute.
+ * @param is the interpreter state.
+ */
+static void
+wire_add_run (void *cls,
+              const struct TALER_TESTING_Command *cmd,
+              struct TALER_TESTING_Interpreter *is)
+{
+  struct WireAddState *ds = cls;
+  char *exchange_url;
+  struct TALER_MasterSignatureP master_sig1;
+  struct TALER_MasterSignatureP master_sig2;
+  struct GNUNET_TIME_Absolute now;
+
+  (void) cmd;
+  now = GNUNET_TIME_absolute_get ();
+  (void) GNUNET_TIME_round_abs (&now);
+  ds->is = is;
+  if (ds->bad_sig)
+  {
+    memset (&master_sig1,
+            42,
+            sizeof (master_sig1));
+    memset (&master_sig2,
+            42,
+            sizeof (master_sig2));
+  }
+  else
+  {
+    char *fn;
+    struct TALER_MasterPrivateKeyP master_priv;
+
+    if (GNUNET_OK !=
+        GNUNET_CONFIGURATION_get_value_filename (is->cfg,
+                                                 "exchange-offline",
+                                                 "MASTER_PRIV_FILE",
+                                                 &fn))
+    {
+      GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                                 "exchange-offline",
+                                 "MASTER_PRIV_FILE");
+      TALER_TESTING_interpreter_next (ds->is);
+      return;
+    }
+    if (GNUNET_SYSERR ==
+        GNUNET_DISK_directory_create_for_file (fn))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Could not setup directory for master private key file 
`%s'\n",
+                  fn);
+      GNUNET_free (fn);
+      TALER_TESTING_interpreter_next (ds->is);
+      return;
+    }
+    if (GNUNET_OK !=
+        GNUNET_CRYPTO_eddsa_key_from_file (fn,
+                                           GNUNET_YES,
+                                           &master_priv.eddsa_priv))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Could not load master private key from `%s'\n",
+                  fn);
+      GNUNET_free (fn);
+      TALER_TESTING_interpreter_next (ds->is);
+      return;
+    }
+    GNUNET_free (fn);
+
+    /* now sign */
+    {
+      struct TALER_MasterAddWirePS kv = {
+        .purpose.purpose = htonl (TALER_SIGNATURE_MASTER_ADD_WIRE),
+        .purpose.size = htonl (sizeof (kv)),
+        .start_date = GNUNET_TIME_absolute_hton (now),
+      };
+      struct TALER_MasterWireDetailsPS wd = {
+        .purpose.purpose = htonl (TALER_SIGNATURE_MASTER_WIRE_DETAILS),
+        .purpose.size = htonl (sizeof (wd)),
+      };
+
+      TALER_exchange_wire_signature_hash (ds->payto_uri,
+                                          &kv.h_wire);
+      wd.h_wire_details = kv.h_wire;
+      GNUNET_CRYPTO_eddsa_sign (&master_priv.eddsa_priv,
+                                &kv,
+                                &master_sig1.eddsa_signature);
+      GNUNET_CRYPTO_eddsa_sign (&master_priv.eddsa_priv,
+                                &wd,
+                                &master_sig2.eddsa_signature);
+    }
+  }
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (is->cfg,
+                                             "exchange",
+                                             "BASE_URL",
+                                             &exchange_url))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "exchange",
+                               "BASE_URL");
+    TALER_TESTING_interpreter_next (ds->is);
+    return;
+  }
+  ds->dh = TALER_EXCHANGE_management_enable_wire (
+    is->ctx,
+    exchange_url,
+    ds->payto_uri,
+    now,
+    &master_sig1,
+    &master_sig2,
+    &wire_add_cb,
+    ds);
+  GNUNET_free (exchange_url);
+  if (NULL == ds->dh)
+  {
+    GNUNET_break (0);
+    TALER_TESTING_interpreter_fail (is);
+    return;
+  }
+}
+
+
+/**
+ * Free the state of a "wire_add" CMD, and possibly cancel a
+ * pending operation thereof.
+ *
+ * @param cls closure, must be a `struct WireAddState`.
+ * @param cmd the command which is being cleaned up.
+ */
+static void
+wire_add_cleanup (void *cls,
+                  const struct TALER_TESTING_Command *cmd)
+{
+  struct WireAddState *ds = cls;
+
+  if (NULL != ds->dh)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Command %u (%s) did not complete\n",
+                ds->is->ip,
+                cmd->label);
+    TALER_EXCHANGE_management_enable_wire_cancel (ds->dh);
+    ds->dh = NULL;
+  }
+  GNUNET_free (ds);
+}
+
+
+/**
+ * Offer internal data from a "wire_add" CMD, to other commands.
+ *
+ * @param cls closure.
+ * @param[out] ret result.
+ * @param trait name of the trait.
+ * @param index index number of the object to offer.
+ *
+ * @return #GNUNET_OK on success.
+ */
+static int
+wire_add_traits (void *cls,
+                 const void **ret,
+                 const char *trait,
+                 unsigned int index)
+{
+  return GNUNET_NO;
+}
+
+
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_wire_add (const char *label,
+                            const char *payto_uri,
+                            unsigned int expected_http_status,
+                            bool bad_sig)
+{
+  struct WireAddState *ds;
+
+  ds = GNUNET_new (struct WireAddState);
+  ds->expected_response_code = expected_http_status;
+  ds->bad_sig = bad_sig;
+  ds->payto_uri = payto_uri;
+  {
+    struct TALER_TESTING_Command cmd = {
+      .cls = ds,
+      .label = label,
+      .run = &wire_add_run,
+      .cleanup = &wire_add_cleanup,
+      .traits = &wire_add_traits
+    };
+
+    return cmd;
+  }
+}
+
+
+/* end of testing_api_cmd_wire_add.c */
diff --git a/src/testing/testing_api_cmd_wire_del.c 
b/src/testing/testing_api_cmd_wire_del.c
new file mode 100644
index 00000000..06de499a
--- /dev/null
+++ b/src/testing/testing_api_cmd_wire_del.c
@@ -0,0 +1,282 @@
+/*
+  This file is part of TALER
+  Copyright (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 testing/testing_api_cmd_wire_del.c
+ * @brief command for testing POST to /management/wire
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_json_lib.h"
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_testing_lib.h"
+#include "taler_signatures.h"
+#include "backoff.h"
+
+
+/**
+ * State for a "wire_del" CMD.
+ */
+struct WireDelState
+{
+
+  /**
+   * Wire enable handle while operation is running.
+   */
+  struct TALER_EXCHANGE_ManagementWireDisableHandle *dh;
+
+  /**
+   * Our interpreter.
+   */
+  struct TALER_TESTING_Interpreter *is;
+
+  /**
+   * Account to del.
+   */
+  const char *payto_uri;
+
+  /**
+   * Expected HTTP response code.
+   */
+  unsigned int expected_response_code;
+
+  /**
+   * Should we make the request with a bad master_sig signature?
+   */
+  bool bad_sig;
+};
+
+
+/**
+ * Callback to analyze the /management/wire response, just used to check
+ * if the response code is acceptable.
+ *
+ * @param cls closure.
+ * @param hr HTTP response details
+ */
+static void
+wire_del_cb (void *cls,
+             const struct TALER_EXCHANGE_HttpResponse *hr)
+{
+  struct WireDelState *ds = cls;
+
+  ds->dh = NULL;
+  if (ds->expected_response_code != hr->http_status)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unexpected response code %u to command %s in %s:%u\n",
+                hr->http_status,
+                ds->is->commands[ds->is->ip].label,
+                __FILE__,
+                __LINE__);
+    json_dumpf (hr->reply,
+                stderr,
+                0);
+    TALER_TESTING_interpreter_fail (ds->is);
+    return;
+  }
+  TALER_TESTING_interpreter_next (ds->is);
+}
+
+
+/**
+ * Run the command.
+ *
+ * @param cls closure.
+ * @param cmd the command to execute.
+ * @param is the interpreter state.
+ */
+static void
+wire_del_run (void *cls,
+              const struct TALER_TESTING_Command *cmd,
+              struct TALER_TESTING_Interpreter *is)
+{
+  struct WireDelState *ds = cls;
+  char *exchange_url;
+  struct TALER_MasterSignatureP master_sig;
+  struct GNUNET_TIME_Absolute now;
+
+  (void) cmd;
+  now = GNUNET_TIME_absolute_get ();
+  (void) GNUNET_TIME_round_abs (&now);
+  ds->is = is;
+  if (ds->bad_sig)
+  {
+    memset (&master_sig,
+            42,
+            sizeof (master_sig));
+  }
+  else
+  {
+    char *fn;
+    struct TALER_MasterPrivateKeyP master_priv;
+
+    if (GNUNET_OK !=
+        GNUNET_CONFIGURATION_get_value_filename (is->cfg,
+                                                 "exchange-offline",
+                                                 "MASTER_PRIV_FILE",
+                                                 &fn))
+    {
+      GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                                 "exchange-offline",
+                                 "MASTER_PRIV_FILE");
+      TALER_TESTING_interpreter_next (ds->is);
+      return;
+    }
+    if (GNUNET_SYSERR ==
+        GNUNET_DISK_directory_create_for_file (fn))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Could not setup directory for master private key file 
`%s'\n",
+                  fn);
+      GNUNET_free (fn);
+      TALER_TESTING_interpreter_next (ds->is);
+      return;
+    }
+    if (GNUNET_OK !=
+        GNUNET_CRYPTO_eddsa_key_from_file (fn,
+                                           GNUNET_YES,
+                                           &master_priv.eddsa_priv))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Could not load master private key from `%s'\n",
+                  fn);
+      GNUNET_free (fn);
+      TALER_TESTING_interpreter_next (ds->is);
+      return;
+    }
+    GNUNET_free (fn);
+
+    /* now sign */
+    {
+      struct TALER_MasterDelWirePS kv = {
+        .purpose.purpose = htonl (TALER_SIGNATURE_MASTER_DEL_WIRE),
+        .purpose.size = htonl (sizeof (kv)),
+        .end_date = GNUNET_TIME_absolute_hton (now),
+      };
+
+      TALER_exchange_wire_signature_hash (ds->payto_uri,
+                                          &kv.h_wire);
+      GNUNET_CRYPTO_eddsa_sign (&master_priv.eddsa_priv,
+                                &kv,
+                                &master_sig.eddsa_signature);
+    }
+  }
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (is->cfg,
+                                             "exchange",
+                                             "BASE_URL",
+                                             &exchange_url))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "exchange",
+                               "BASE_URL");
+    TALER_TESTING_interpreter_next (ds->is);
+    return;
+  }
+  ds->dh = TALER_EXCHANGE_management_disable_wire (
+    is->ctx,
+    exchange_url,
+    ds->payto_uri,
+    now,
+    &master_sig,
+    &wire_del_cb,
+    ds);
+  GNUNET_free (exchange_url);
+  if (NULL == ds->dh)
+  {
+    GNUNET_break (0);
+    TALER_TESTING_interpreter_fail (is);
+    return;
+  }
+}
+
+
+/**
+ * Free the state of a "wire_del" CMD, and possibly cancel a
+ * pending operation thereof.
+ *
+ * @param cls closure, must be a `struct WireDelState`.
+ * @param cmd the command which is being cleaned up.
+ */
+static void
+wire_del_cleanup (void *cls,
+                  const struct TALER_TESTING_Command *cmd)
+{
+  struct WireDelState *ds = cls;
+
+  if (NULL != ds->dh)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Command %u (%s) did not complete\n",
+                ds->is->ip,
+                cmd->label);
+    TALER_EXCHANGE_management_disable_wire_cancel (ds->dh);
+    ds->dh = NULL;
+  }
+  GNUNET_free (ds);
+}
+
+
+/**
+ * Offer internal data from a "wire_del" CMD, to other commands.
+ *
+ * @param cls closure.
+ * @param[out] ret result.
+ * @param trait name of the trait.
+ * @param index index number of the object to offer.
+ *
+ * @return #GNUNET_OK on success.
+ */
+static int
+wire_del_traits (void *cls,
+                 const void **ret,
+                 const char *trait,
+                 unsigned int index)
+{
+  return GNUNET_NO;
+}
+
+
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_wire_del (const char *label,
+                            const char *payto_uri,
+                            unsigned int expected_http_status,
+                            bool bad_sig)
+{
+  struct WireDelState *ds;
+
+  ds = GNUNET_new (struct WireDelState);
+  ds->expected_response_code = expected_http_status;
+  ds->bad_sig = bad_sig;
+  ds->payto_uri = payto_uri;
+  {
+    struct TALER_TESTING_Command cmd = {
+      .cls = ds,
+      .label = label,
+      .run = &wire_del_run,
+      .cleanup = &wire_del_cleanup,
+      .traits = &wire_del_traits
+    };
+
+    return cmd;
+  }
+}
+
+
+/* end of testing_api_cmd_wire_del.c */

-- 
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]