summaryrefslogtreecommitdiff
path: root/src/lib/merchant_api_post_order_pay.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2020-06-23 11:00:23 +0200
committerChristian Grothoff <christian@grothoff.org>2020-06-23 11:00:23 +0200
commitf8c01f4b46a8391f3196889e5df7f8ebdfb6475d (patch)
treed17aeee8e0371203a8db9d45aab96e43c8a764f5 /src/lib/merchant_api_post_order_pay.c
parent3e5a21a6178a3aaeccb0c098f01847ef04238544 (diff)
downloadmerchant-f8c01f4b46a8391f3196889e5df7f8ebdfb6475d.tar.gz
merchant-f8c01f4b46a8391f3196889e5df7f8ebdfb6475d.tar.bz2
merchant-f8c01f4b46a8391f3196889e5df7f8ebdfb6475d.zip
implement signature verification on pay response
Diffstat (limited to 'src/lib/merchant_api_post_order_pay.c')
-rw-r--r--src/lib/merchant_api_post_order_pay.c85
1 files changed, 75 insertions, 10 deletions
diff --git a/src/lib/merchant_api_post_order_pay.c b/src/lib/merchant_api_post_order_pay.c
index 650211c9..477c3a31 100644
--- a/src/lib/merchant_api_post_order_pay.c
+++ b/src/lib/merchant_api_post_order_pay.c
@@ -78,10 +78,28 @@ struct TALER_MERCHANT_OrderPayHandle
struct TALER_MERCHANT_PaidCoin *coins;
/**
+ * Hash of the contract we are paying, set
+ * if @e am_wallet is true.
+ */
+ struct GNUNET_HashCode h_contract_terms;
+
+ /**
+ * Public key of the merchant (instance) being paid, set
+ * if @e am_wallet is true.
+ */
+ struct TALER_MerchantPublicKeyP merchant_pub;
+
+ /**
* Number of @e coins we are paying with.
*/
unsigned int num_coins;
+ /**
+ * Set to true if this is the wallet API and we have
+ * initialized @e h_contract_terms and @e merchant_pub.
+ */
+ bool am_wallet;
+
};
@@ -234,8 +252,45 @@ handle_pay_finished (void *cls,
hr.ec = TALER_EC_INVALID_RESPONSE;
break;
case MHD_HTTP_OK:
- // FIXME: should verify 'sig' from merchant here!
- // FIXME: probably should return merchant signature to callback!
+ if (oph->am_wallet)
+ {
+ /* Here we can (and should) verify the merchant's signature */
+ struct PaymentResponsePS pr = {
+ .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_PAYMENT_OK),
+ .purpose.size = htonl (sizeof (pr)),
+ .h_contract_terms = oph->h_contract_terms
+ };
+ struct TALER_MerchantSignatureP merchant_sig;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_fixed_auto ("sig",
+ &merchant_sig),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (json,
+ spec,
+ NULL, NULL))
+ {
+ GNUNET_break_op (0);
+ hr.ec = TALER_EC_INVALID_RESPONSE;
+ hr.http_status = 0;
+ hr.hint = "sig field missing in response";
+ break;
+ }
+
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_PAYMENT_OK,
+ &pr,
+ &merchant_sig.eddsa_sig,
+ &oph->merchant_pub.eddsa_pub))
+ {
+ GNUNET_break_op (0);
+ hr.ec = TALER_EC_INVALID_RESPONSE;
+ hr.http_status = 0;
+ hr.hint = "signature invalid";
+ }
+ }
break;
/* Tolerating Not Acceptable because sometimes
* - especially in tests - we might want to POST
@@ -623,14 +678,24 @@ TALER_MERCHANT_order_pay (struct GNUNET_CURL_Context *ctx,
p->amount_without_fee = coin->amount_without_fee;
p->exchange_url = coin->exchange_url;
}
- return TALER_MERCHANT_order_pay_frontend (ctx,
- merchant_url,
- order_id,
- session_id,
- num_coins,
- pc,
- pay_cb,
- pay_cb_cls);
+ {
+ struct TALER_MERCHANT_OrderPayHandle *oph;
+
+ oph = TALER_MERCHANT_order_pay_frontend (ctx,
+ merchant_url,
+ order_id,
+ session_id,
+ num_coins,
+ pc,
+ pay_cb,
+ pay_cb_cls);
+ if (NULL == oph)
+ return NULL;
+ oph->h_contract_terms = *h_contract_terms;
+ oph->merchant_pub = *merchant_pub;
+ oph->am_wallet = true;
+ return oph;
+ }
}
}