summaryrefslogtreecommitdiff
path: root/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
diff options
context:
space:
mode:
authorÖzgür Kesim <oec-taler@kesim.org>2022-06-29 14:40:15 +0200
committerÖzgür Kesim <oec-taler@kesim.org>2022-06-29 14:43:16 +0200
commit72695e8e41bb75b44d3d09ad5316eb9d48ac25d7 (patch)
treedb2ad0db48d12408a48d4cadfb0772deea896a6e /src/backend/taler-merchant-httpd_post-orders-ID-pay.c
parente3690a9eb44d5feb0a44dc995612a601aa95aacd (diff)
downloadmerchant-72695e8e41bb75b44d3d09ad5316eb9d48ac25d7.tar.gz
merchant-72695e8e41bb75b44d3d09ad5316eb9d48ac25d7.tar.bz2
merchant-72695e8e41bb75b44d3d09ad5316eb9d48ac25d7.zip
Handle age restricted coin when minimum age was not required
When a customer pays with a coin that is age restricted while the contract did not ask for a minimum age, it is required that the customer provides 'h_age_commitment', the hash of the age commitment that went into the FDH of the coin. This is needed for the deposit of the age restricted coin. Fixes #7252
Diffstat (limited to 'src/backend/taler-merchant-httpd_post-orders-ID-pay.c')
-rw-r--r--src/backend/taler-merchant-httpd_post-orders-ID-pay.c73
1 files changed, 44 insertions, 29 deletions
diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
index 2e78c10d..43b68ff4 100644
--- a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
+++ b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
@@ -1131,7 +1131,7 @@ process_pay_with_exchange (
const struct TALER_EXCHANGE_DenomPublicKey *denom_details;
enum TALER_ErrorCode ec;
unsigned int http_status;
- bool age_verification_required = false;
+ bool is_age_restricted_denom = false;
struct TALER_AgeCommitmentHash ach = {0};
struct TALER_AgeCommitmentHash *achp = NULL;
@@ -1176,6 +1176,7 @@ process_pay_with_exchange (
(json_t *) TALER_EXCHANGE_get_keys_raw (exchange_handle)))));
return;
}
+
if (GNUNET_OK !=
TMH_AUDITORS_check_dk (exchange_handle,
denom_details,
@@ -1210,15 +1211,18 @@ process_pay_with_exchange (
/* Now that we have the details about the denomination, we can verify age
* restriction requirements, if applicable. Note that denominations with an
* age_mask equal to zero always pass the age verification. */
- age_verification_required = 0 < pc->minimum_age &&
- 0 < denom_details->key.age_mask.bits;
+ is_age_restricted_denom = 0 < denom_details->key.age_mask.bits;
- if (age_verification_required)
+ if (is_age_restricted_denom
+ && (0 < pc->minimum_age))
{
+ /* Minimum age given and restricted coind provided: We need to verify the
+ * minimum age */
unsigned int code = 0;
if (dc->no_age_commitment)
{
+ GNUNET_break_op (0);
code = TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_MISSING;
goto AGE_FAIL;
}
@@ -1227,6 +1231,7 @@ process_pay_with_exchange (
if ((dc->age_commitment.num + 1) !=
__builtin_popcount (dc->age_commitment.mask.bits))
{
+ GNUNET_break_op (0);
code =
TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_SIZE_MISMATCH;
goto AGE_FAIL;
@@ -1242,6 +1247,7 @@ process_pay_with_exchange (
AGE_FAIL:
if (0 < code)
{
+ GNUNET_free (dc->age_commitment.keys);
resume_pay_with_response (
pc,
MHD_HTTP_BAD_REQUEST,
@@ -1256,9 +1262,31 @@ AGE_FAIL:
* Calculate the hash of the age commitment. */
TALER_age_commitment_hash (&dc->age_commitment,
&ach);
-
+ GNUNET_free (dc->age_commitment.keys);
achp = &ach;
}
+ else if (is_age_restricted_denom)
+ {
+ /* The contract did not ask for a minimum_age but the client paid
+ * with a coin that has age restriction enabled. We need the hash
+ * of the age commitment in this case in order to verify the coin
+ * and to deposit it with the exchange. */
+ if (dc->no_h_age_commitment)
+ {
+ GNUNET_break_op (0);
+ resume_pay_with_response (
+ pc,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_MHD_MAKE_JSON_PACK (
+ TALER_JSON_pack_ec (
+ TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_HASH_MISSING),
+ GNUNET_JSON_pack_data_auto ("h_denom_pub",
+ &denom_details->h_key)));
+ return;
+ }
+
+ achp = &dc->h_age_commitment;
+ }
dc->deposit_fee = denom_details->fees.deposit;
dc->refund_fee = denom_details->fees.refund;
@@ -2066,7 +2094,6 @@ parse_pay (struct PayContext *pc)
{
struct DepositConfirmation *dc = &pc->dc[coins_index];
const char *exchange_url;
- bool no_minimum_age_sig;
struct GNUNET_JSON_Specification ispec[] = {
GNUNET_JSON_spec_fixed_auto ("coin_sig",
&dc->coin_sig),
@@ -2086,7 +2113,7 @@ parse_pay (struct PayContext *pc)
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_fixed_auto ("minimum_age_sig",
&dc->minimum_age_sig),
- &no_minimum_age_sig),
+ &dc->no_minimum_age_sig),
GNUNET_JSON_spec_mark_optional (
TALER_JSON_spec_age_commitment ("age_commitment",
&dc->age_commitment),
@@ -2149,32 +2176,20 @@ parse_pay (struct PayContext *pc)
// Check the consistency of the (potential) age restriction
// information.
+ if (dc->no_age_commitment != dc->no_minimum_age_sig)
{
- char *error = NULL;
-
- if (0 < dc->pc->minimum_age &&
- dc->no_minimum_age_sig &&
- dc->no_age_commitment)
- error = "required: 'mininum_age_sig' and 'age_commitment'";
-
- if (! dc->no_age_commitment &&
- dc->no_h_age_commitment)
- error = "only one allowed: 'age_commitment' vs. 'h_age_commitment'";
-
- if (NULL != error)
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- return (MHD_YES ==
- TALER_MHD_reply_with_error (
- pc->connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- error)
+ GNUNET_break_op (0);
+ GNUNET_JSON_parse_free (spec);
+ return (MHD_YES ==
+ TALER_MHD_reply_with_error (
+ pc->connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "inconsistent: 'age_commitment' vs. 'minimum_age_sig'"
)
+ )
? GNUNET_NO
: GNUNET_SYSERR;
- }
}
}
}