gnunet-svn
[Top][All Lists]
Advanced

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

[taler-merchant] branch master updated (25abbe8b -> 72695e8e)


From: gnunet
Subject: [taler-merchant] branch master updated (25abbe8b -> 72695e8e)
Date: Wed, 29 Jun 2022 14:43:36 +0200

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

oec pushed a change to branch master
in repository merchant.

    from 25abbe8b make sure Debian packages created on Ubuntu 21+ still work 
with Debian reprepro: force Debian standard compression algorithm
     new e3690a9e use age commitment parser from libtalerexchange
     new 72695e8e Handle age restricted coin when minimum age was not required

The 2 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:
 .../taler-merchant-httpd_post-orders-ID-pay.c      | 189 ++++++++++-----------
 1 file changed, 87 insertions(+), 102 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 bbd74822..43b68ff4 100644
--- a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
+++ b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
@@ -129,6 +129,9 @@ struct DepositConfirmation
    */
   struct TALER_AgeAttestation minimum_age_sig;
 
+  /* true, if no field "minimum_age_sig" was found in the JSON blob */
+  bool no_minimum_age_sig;
+
   /**
    * If a minimum age was required (i. e. pc->minimum_age is large enough),
    * this is the age commitment (i. e. age mask and vector of EdDSA public
@@ -136,7 +139,21 @@ struct DepositConfirmation
    * SHA256 hash of the mask and the vector of public keys was bound to the
    * key.
    */
-  struct TALER_AgeCommitment *age_commitment;
+  struct TALER_AgeCommitment age_commitment;
+
+  /* true, if no field "age_commitment" was found in the JSON blob */
+  bool no_age_commitment;
+
+  /**
+   * In the case that somebody pays with a coin that is age restricted, but the
+   * the contract did not ask for a minimum age, the merchant still needs the
+   * hash of the age commitment in order to a) verify the coin and b) deposit
+   * it.
+   */
+  struct TALER_AgeCommitmentHash h_age_commitment;
+
+  /* true, if no field "h_age_commitment" was found in the JSON blob */
+  bool no_h_age_commitment;
 
   /**
    * Age mask in the denomination that defines the age groups.  Only
@@ -1069,7 +1086,6 @@ process_pay_with_exchange (
   struct PayContext *pc = cls;
   struct TMH_HandlerContext *hc = pc->hc;
   const struct TALER_EXCHANGE_Keys *keys;
-  struct TALER_AgeCommitmentHash h_age_commitment = {0};
 
   (void) payto_uri;
   pc->fo = NULL;
@@ -1115,7 +1131,9 @@ 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;
 
     if (NULL != dc->dh)
       continue; /* we were here before (can happen due to
@@ -1158,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,
@@ -1192,23 +1211,27 @@ 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 (NULL == dc->age_commitment)
+      if (dc->no_age_commitment)
       {
+        GNUNET_break_op (0);
         code = TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AGE_COMMITMENT_MISSING;
         goto AGE_FAIL;
       }
 
-      dc->age_commitment->mask = denom_details->key.age_mask;
-      if ((dc->age_commitment->num + 1) !=
-          __builtin_popcount (dc->age_commitment->mask.bits))
+      dc->age_commitment.mask = denom_details->key.age_mask;
+      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;
@@ -1216,7 +1239,7 @@ process_pay_with_exchange (
 
       if (GNUNET_OK !=
           TALER_age_commitment_verify (
-            dc->age_commitment,
+            &dc->age_commitment,
             pc->minimum_age,
             &dc->minimum_age_sig))
         code = TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AGE_VERIFICATION_FAILED;
@@ -1224,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,
@@ -1236,8 +1260,32 @@ AGE_FAIL:
 
       /* Age restriction successfully verified!
        * Calculate the hash of the age commitment. */
-      TALER_age_commitment_hash (dc->age_commitment,
-                                 &h_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;
@@ -1251,8 +1299,7 @@ AGE_FAIL:
                                      pc->wm->payto_uri,
                                      &pc->wm->wire_salt,
                                      &pc->h_contract_terms,
-                                     age_verification_required ?
-                                     &h_age_commitment: NULL,
+                                     achp,
                                      NULL, /* FIXME oec: extension json blob */
                                      &dc->coin_pub,
                                      &dc->ub_sig,
@@ -2042,11 +2089,11 @@ parse_pay (struct PayContext *pc)
   {
     unsigned int coins_index;
     json_t *coin;
+
     json_array_foreach (coins, coins_index, coin)
     {
       struct DepositConfirmation *dc = &pc->dc[coins_index];
       const char *exchange_url;
-      json_t *age_commitment = NULL;
       struct GNUNET_JSON_Specification ispec[] = {
         GNUNET_JSON_spec_fixed_auto ("coin_sig",
                                      &dc->coin_sig),
@@ -2061,14 +2108,22 @@ parse_pay (struct PayContext *pc)
                                 &dc->amount_with_fee),
         GNUNET_JSON_spec_string ("exchange_url",
                                  &exchange_url),
+        /* if a minimum age was required, the minimum_age_sig and
+         * age_commitment must be provided */
         GNUNET_JSON_spec_mark_optional (
           GNUNET_JSON_spec_fixed_auto ("minimum_age_sig",
                                        &dc->minimum_age_sig),
-          NULL),
+          &dc->no_minimum_age_sig),
+        GNUNET_JSON_spec_mark_optional (
+          TALER_JSON_spec_age_commitment ("age_commitment",
+                                          &dc->age_commitment),
+          &dc->no_age_commitment),
+        /* if minimum age was not required, but coin with age restriction set
+         * was used, h_age_commitment must be provided. */
         GNUNET_JSON_spec_mark_optional (
-          GNUNET_JSON_spec_json ("age_commitment",
-                                 &age_commitment),
-          NULL),
+          GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
+                                       &dc->h_age_commitment),
+          &dc->no_h_age_commitment),
         GNUNET_JSON_spec_end ()
       };
       enum GNUNET_GenericReturnValue res;
@@ -2119,83 +2174,22 @@ parse_pay (struct PayContext *pc)
               : GNUNET_SYSERR;
       }
 
+      // Check the consistency of the (potential) age restriction
+      // information.
+      if (dc->no_age_commitment != dc->no_minimum_age_sig)
       {
-        bool has_commitment = (NULL != age_commitment) &&
-                              json_is_array (age_commitment);
-        bool has_sig = ! GNUNET_is_zero_ (&dc->minimum_age_sig,
-                                          sizeof(dc->minimum_age_sig));
-        if (has_sig != has_commitment)
-        {
-          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,
-                    "inconsistency: 'mininum_age_sig' vs. 'age_commitment'")
+        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;
-        }
-
-        /* Parse the AgeCommitment, i. e. the public keys */
-        if (has_commitment)
-        {
-          json_t *pk;
-          unsigned int idx;
-          size_t num = json_array_size (age_commitment);
-
-          /* Sanity check the amount of AgeCommitment's public keys.  The
-           * actual check will be performed once we now the denominations. */
-          if (32 <= num)
-          {
-            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,
-                                                "'age_commitment' too large"
-                                                ))
-                ? GNUNET_NO
-                : GNUNET_SYSERR;
-          }
-
-          dc->age_commitment = GNUNET_new (struct TALER_AgeCommitment);
-          dc->age_commitment->num = num;
-          dc->age_commitment->keys =
-            GNUNET_new_array (num,
-                              struct TALER_AgeCommitmentPublicKeyP);
-          /* Note that dc->age_commitment.mask will be set later, based on
-           * the actual denomination. */
-
-          json_array_foreach (age_commitment, idx, pk) {
-            struct GNUNET_JSON_Specification pkspec[] = {
-              GNUNET_JSON_spec_fixed_auto (
-                NULL,
-                &dc->age_commitment->keys[idx].pub),
-              GNUNET_JSON_spec_end ()
-            };
-
-            if (GNUNET_OK !=
-                GNUNET_JSON_parse (pk,
-                                   pkspec,
-                                   NULL, NULL))
-            {
-              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,
-                        "age_commitment"))
-                  ? GNUNET_NO
-                  : GNUNET_SYSERR;
-            }
-          }
-        }
       }
     }
   }
@@ -2538,15 +2532,6 @@ check_contract (struct PayContext *pc)
     pc->wm = wm;
   }
 
-  if (0 < pc->minimum_age)
-  {
-    /* TODO oec: check
-     * 1. denomination are age restricted
-     * 2. consume their mask
-     * 3. valididate minimum age
-     */
-  }
-
   return GNUNET_OK;
 }
 

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