aboutsummaryrefslogtreecommitdiff
path: root/src/wire
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-04-02 20:58:22 +0200
committerChristian Grothoff <christian@grothoff.org>2016-04-02 20:58:22 +0200
commitdaae3d3ddf1cbee4761a6a2c0066732fb4723fb0 (patch)
treeba2e9a677f6a1bede7f871adc9ca0c97ac62e7c6 /src/wire
parent937078bbdc747c92d45a3879862ff4664d1ff636 (diff)
change taler-exchange-sepa to a more generic taler-exchange-wire tool using the wire plugins (#4237)
Diffstat (limited to 'src/wire')
-rw-r--r--src/wire/plugin_wire_sepa.c132
-rw-r--r--src/wire/plugin_wire_template.c23
-rw-r--r--src/wire/plugin_wire_test.c93
3 files changed, 226 insertions, 22 deletions
diff --git a/src/wire/plugin_wire_sepa.c b/src/wire/plugin_wire_sepa.c
index 995436725..466e450be 100644
--- a/src/wire/plugin_wire_sepa.c
+++ b/src/wire/plugin_wire_sepa.c
@@ -352,6 +352,42 @@ validate_iban (const char *iban)
/**
+ * Compute purpose for signing.
+ *
+ * @param sepa_name name of the account holder
+ * @param iban bank account number in IBAN format
+ * @param bic bank identifier
+ * @param[out] mp purpose to be signed
+ */
+static void
+compute_purpose (const char *sepa_name,
+ const char *iban,
+ const char *bic,
+ struct TALER_MasterWireDetailsPS *wsd)
+{
+ struct GNUNET_HashContext *hc;
+
+ wsd->purpose.size = htonl (sizeof (struct TALER_MasterWireDetailsPS));
+ wsd->purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SEPA_DETAILS);
+ hc = GNUNET_CRYPTO_hash_context_start ();
+ GNUNET_CRYPTO_hash_context_read (hc,
+ "sepa",
+ strlen ("sepa") + 1);
+ GNUNET_CRYPTO_hash_context_read (hc,
+ sepa_name,
+ strlen (sepa_name) + 1);
+ GNUNET_CRYPTO_hash_context_read (hc,
+ iban,
+ strlen (iban) + 1);
+ GNUNET_CRYPTO_hash_context_read (hc,
+ bic,
+ strlen (bic) + 1);
+ GNUNET_CRYPTO_hash_context_finish (hc,
+ &wsd->h_sepa_details);
+}
+
+
+/**
* Verify that the signature in the @a json for /wire/sepa is valid.
*
* @param json json reply with the signature
@@ -365,14 +401,13 @@ verify_wire_sepa_signature_ok (const json_t *json,
const struct TALER_MasterPublicKeyP *master_pub)
{
struct TALER_MasterSignatureP exchange_sig;
- struct TALER_MasterWireSepaDetailsPS mp;
- const char *receiver_name;
+ struct TALER_MasterWireDetailsPS mp;
+ const char *name;
const char *iban;
const char *bic;
- struct GNUNET_HashContext *hc;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("sig", &exchange_sig),
- GNUNET_JSON_spec_string ("receiver_name", &receiver_name),
+ GNUNET_JSON_spec_string ("name", &name),
GNUNET_JSON_spec_string ("iban", &iban),
GNUNET_JSON_spec_string ("bic", &bic),
GNUNET_JSON_spec_end()
@@ -391,22 +426,10 @@ verify_wire_sepa_signature_ok (const json_t *json,
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
-
- mp.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SEPA_DETAILS);
- mp.purpose.size = htonl (sizeof (struct TALER_MasterWireSepaDetailsPS));
- hc = GNUNET_CRYPTO_hash_context_start ();
- GNUNET_CRYPTO_hash_context_read (hc,
- receiver_name,
- strlen (receiver_name) + 1);
- GNUNET_CRYPTO_hash_context_read (hc,
- iban,
- strlen (iban) + 1);
- GNUNET_CRYPTO_hash_context_read (hc,
- bic,
- strlen (bic) + 1);
- GNUNET_CRYPTO_hash_context_finish (hc,
- &mp.h_sepa_details);
-
+ compute_purpose (name,
+ iban,
+ bic,
+ &mp);
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_SEPA_DETAILS,
&mp.purpose,
@@ -447,12 +470,12 @@ sepa_wire_validate (void *cls,
"{"
"s:s," /* type: sepa */
"s:s," /* iban: IBAN */
- "s:s," /* receiver_name: beneficiary name */
+ "s:s," /* name: beneficiary name */
"s:s" /* bic: beneficiary bank's BIC */
"}",
"type", &type,
"iban", &iban,
- "receiver_name", &name,
+ "name", &name,
"bic", &bic))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -549,6 +572,70 @@ sepa_get_wire_details (void *cls,
/**
+ * Sign wire transfer details in the plugin-specific format.
+ *
+ * @param cls closure
+ * @param in wire transfer details in JSON format
+ * @param key private signing key to use
+ * @param salt salt to add
+ * @param[out] sig where to write the signature
+ * @return #GNUNET_OK on success
+ */
+static int
+sepa_sign_wire_details (void *cls,
+ const json_t *in,
+ const struct TALER_MasterPrivateKeyP *key,
+ const struct GNUNET_HashCode *salt,
+ struct TALER_MasterSignatureP *sig)
+{
+ struct TALER_MasterWireDetailsPS wsd;
+ const char *sepa_name;
+ const char *iban;
+ const char *bic;
+ const char *type;
+ json_error_t err;
+
+ if (0 !=
+ json_unpack_ex ((json_t *) in,
+ &err,
+ 0 /* flags */,
+ "{s:s, s:s, s:s, s:s}",
+ "type", &type,
+ "name", &sepa_name,
+ "iban", &iban,
+ "bic", &bic))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to unpack JSON: %s (at %u)\n",
+ err.text,
+ err.position);
+ return GNUNET_SYSERR;
+ }
+ if (0 != strcmp (type,
+ "sepa"))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "`type' must be `sepa' for SEPA wire details\n");
+ return GNUNET_SYSERR;
+ }
+ if (1 != validate_iban (iban))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "IBAN invalid in SEPA wire details\n");
+ return GNUNET_SYSERR;
+ }
+ compute_purpose (sepa_name,
+ iban,
+ bic,
+ &wsd);
+ GNUNET_CRYPTO_eddsa_sign (&key->eddsa_priv,
+ &wsd.purpose,
+ &sig->eddsa_signature);
+ return GNUNET_OK;
+}
+
+
+/**
* Prepare for exeuction of a wire transfer.
*
* @param cls the @e cls of this struct with the plugin-specific state
@@ -662,6 +749,7 @@ libtaler_plugin_wire_sepa_init (void *cls)
plugin->cls = sc;
plugin->amount_round = &sepa_amount_round;
plugin->get_wire_details = &sepa_get_wire_details;
+ plugin->sign_wire_details = &sepa_sign_wire_details;
plugin->wire_validate = &sepa_wire_validate;
plugin->prepare_wire_transfer = &sepa_prepare_wire_transfer;
plugin->prepare_wire_transfer_cancel = &sepa_prepare_wire_transfer_cancel;
diff --git a/src/wire/plugin_wire_template.c b/src/wire/plugin_wire_template.c
index fd6fbfbe9..46908c297 100644
--- a/src/wire/plugin_wire_template.c
+++ b/src/wire/plugin_wire_template.c
@@ -172,6 +172,28 @@ template_execute_wire_transfer (void *cls,
/**
+ * Sign wire transfer details in the plugin-specific format.
+ *
+ * @param cls closure
+ * @param in wire transfer details in JSON format
+ * @param key private signing key to use
+ * @param salt salt to add
+ * @param[out] sig where to write the signature
+ * @return #GNUNET_OK on success
+ */
+static int
+template_sign_wire_details (void *cls,
+ const json_t *in,
+ const struct TALER_MasterPrivateKeyP *key,
+ const struct GNUNET_HashCode *salt,
+ struct TALER_MasterSignatureP *sig)
+{
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+}
+
+
+/**
* Abort execution of a wire transfer. For example, because we are
* shutting down. Note that if an execution is aborted, it may or
* may not still succeed. The caller MUST run @e
@@ -236,6 +258,7 @@ libtaler_plugin_wire_template_init (void *cls)
plugin->cls = tc;
plugin->amount_round = &template_amount_round;
plugin->get_wire_details = &template_get_wire_details;
+ plugin->sign_wire_details = &template_sign_wire_details;
plugin->wire_validate = &template_wire_validate;
plugin->prepare_wire_transfer = &template_prepare_wire_transfer;
plugin->prepare_wire_transfer_cancel = &template_prepare_wire_transfer_cancel;
diff --git a/src/wire/plugin_wire_test.c b/src/wire/plugin_wire_test.c
index 304380721..8c03d155e 100644
--- a/src/wire/plugin_wire_test.c
+++ b/src/wire/plugin_wire_test.c
@@ -22,6 +22,7 @@
#include "platform.h"
#include "taler_wire_plugin.h"
#include "taler_bank_service.h"
+#include "taler_signatures.h"
/* only for HTTP status codes */
#include <microhttpd.h>
@@ -286,6 +287,38 @@ test_get_wire_details (void *cls,
/**
+ * Compute purpose for signing.
+ *
+ * @param account number of the account
+ * @param bank_uri URI of the bank
+ * @param[out] mp purpose to be signed
+ */
+static void
+compute_purpose (uint64_t account,
+ const char *bank_uri,
+ struct TALER_MasterWireDetailsPS *wsd)
+{
+ struct GNUNET_HashContext *hc;
+ uint64_t n = GNUNET_htonll (account);
+
+ wsd->purpose.size = htonl (sizeof (struct TALER_MasterWireDetailsPS));
+ wsd->purpose.purpose = htonl (TALER_SIGNATURE_MASTER_TEST_DETAILS);
+ hc = GNUNET_CRYPTO_hash_context_start ();
+ GNUNET_CRYPTO_hash_context_read (hc,
+ "test",
+ strlen ("test") + 1);
+ GNUNET_CRYPTO_hash_context_read (hc,
+ &n,
+ sizeof (n));
+ GNUNET_CRYPTO_hash_context_read (hc,
+ bank_uri,
+ strlen (bank_uri) + 1);
+ GNUNET_CRYPTO_hash_context_finish (hc,
+ &wsd->h_sepa_details);
+}
+
+
+/**
* Check if the given wire format JSON object is correctly formatted.
* Right now, the only thing we require is a field
* "account_number" which must contain a positive 53-bit integer.
@@ -319,6 +352,10 @@ test_wire_validate (void *cls,
GNUNET_break (0);
return GNUNET_SYSERR;
}
+ /* FIXME: should check signature here in the future!
+ (note: right now the sig is not properly provided
+ by the exchange due to the way account data is
+ specified in the configuration) */
return GNUNET_YES;
}
@@ -511,6 +548,61 @@ execute_cb (void *cls,
/**
+ * Sign wire transfer details in the plugin-specific format.
+ *
+ * @param cls closure
+ * @param in wire transfer details in JSON format
+ * @param key private signing key to use
+ * @param salt salt to add
+ * @param[out] sig where to write the signature
+ * @return #GNUNET_OK on success
+ */
+static int
+test_sign_wire_details (void *cls,
+ const json_t *in,
+ const struct TALER_MasterPrivateKeyP *key,
+ const struct GNUNET_HashCode *salt,
+ struct TALER_MasterSignatureP *sig)
+{
+ struct TALER_MasterWireDetailsPS wsd;
+ const char *bank_uri;
+ const char *type;
+ json_int_t account;
+ json_error_t err;
+
+ if (0 !=
+ json_unpack_ex ((json_t *) in,
+ &err,
+ 0 /* flags */,
+ "{s:s, s:s, s:I}",
+ "type", &type,
+ "bank_uri", &bank_uri,
+ "account_number", &account))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to unpack JSON: %s (at %u)\n",
+ err.text,
+ err.position);
+ return GNUNET_SYSERR;
+ }
+ if (0 != strcmp (type,
+ "test"))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "`type' must be `test' for test wire details\n");
+ return GNUNET_SYSERR;
+ }
+ compute_purpose (account,
+ bank_uri,
+ &wsd);
+ GNUNET_CRYPTO_eddsa_sign (&key->eddsa_priv,
+ &wsd.purpose,
+ &sig->eddsa_signature);
+ return GNUNET_OK;
+}
+
+
+/**
* Execute a wire transfer.
*
* @param cls the @e cls of this struct with the plugin-specific state
@@ -682,6 +774,7 @@ libtaler_plugin_wire_test_init (void *cls)
plugin->cls = tc;
plugin->amount_round = &test_amount_round;
plugin->get_wire_details = &test_get_wire_details;
+ plugin->sign_wire_details = &test_sign_wire_details;
plugin->wire_validate = &test_wire_validate;
plugin->prepare_wire_transfer = &test_prepare_wire_transfer;
plugin->prepare_wire_transfer_cancel = &test_prepare_wire_transfer_cancel;