gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [taler-merchant] branch master updated: fix proposal test c


From: gnunet
Subject: [GNUnet-SVN] [taler-merchant] branch master updated: fix proposal test cases, fix use after free in refunds
Date: Tue, 16 Jan 2018 01:31:05 +0100

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

dold pushed a commit to branch master
in repository merchant.

The following commit(s) were added to refs/heads/master by this push:
     new c4fe61a  fix proposal test cases, fix use after free in refunds
c4fe61a is described below

commit c4fe61ac6d1a74320638eb4f40de7c18d30a4d8c
Author: Florian Dold <address@hidden>
AuthorDate: Tue Jan 16 01:30:57 2018 +0100

    fix proposal test cases, fix use after free in refunds
---
 src/backend/taler-merchant-httpd.c                 |   5 +-
 src/backend/taler-merchant-httpd.h                 |   2 +-
 src/backend/taler-merchant-httpd_proposal.c        |  84 ++++++++----
 src/backend/taler-merchant-httpd_refund.c          |   9 +-
 src/backenddb/plugin_merchantdb_postgres.c         |   1 +
 src/include/taler_merchant_service.h               |  20 +--
 src/lib/merchant_api_proposal.c                    | 144 ++++++++++++++++-----
 src/lib/test_merchant_api.c                        |  99 +++++++++++---
 src/lib/test_merchant_api.conf                     |   5 +
 .../taler-merchant-generate-payments.c             |  75 +++++++++--
 10 files changed, 349 insertions(+), 95 deletions(-)

diff --git a/src/backend/taler-merchant-httpd.c 
b/src/backend/taler-merchant-httpd.c
index 2bf927d..998d3b0 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -269,7 +269,8 @@ url_handler (void *cls,
       &TMH_MHD_handler_static_response, MHD_HTTP_NOT_FOUND
     };
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Handling request for URL `%s'\n",
+              "Handling request (%s) for URL `%s'\n",
+              method,
               url);
   for (unsigned int i=0;NULL != handlers[i].url;i++)
   {
@@ -857,6 +858,8 @@ run (void *cls,
   char *wireformat;
   int fh;
 
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "running taler-merchant-httpd\n");
+
   result = GNUNET_SYSERR;
   GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
                                  NULL);
diff --git a/src/backend/taler-merchant-httpd.h 
b/src/backend/taler-merchant-httpd.h
index 1e917e7..a1b0f84 100644
--- a/src/backend/taler-merchant-httpd.h
+++ b/src/backend/taler-merchant-httpd.h
@@ -72,7 +72,7 @@ struct IterateInstancesCls
 
 
 /**
- * Information that defines a merchant "instance". That way, a single
+ * Information that defines a merchant "instance". Tha4673t way, a single
  * backend can account for several merchants, as used to do in donation
  * shops
  */
diff --git a/src/backend/taler-merchant-httpd_proposal.c 
b/src/backend/taler-merchant-httpd_proposal.c
index c79e2a8..01d3c5a 100644
--- a/src/backend/taler-merchant-httpd_proposal.c
+++ b/src/backend/taler-merchant-httpd_proposal.c
@@ -135,8 +135,6 @@ proposal_put (struct MHD_Connection *connection,
 {
   int res;
   struct MerchantInstance *mi;
-  struct TALER_ProposalDataPS pdps;
-  struct GNUNET_CRYPTO_EddsaSignature merchant_sig;
   struct TALER_Amount total;
   const char *order_id;
   json_t *products;
@@ -317,9 +315,6 @@ proposal_put (struct MHD_Connection *connection,
                                         TALER_EC_CONTRACT_INSTANCE_UNKNOWN,
                                         "Unknown instance given");
   }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Signing contract on behalf of instance '%s'\n",
-              mi->id);
   /* add fields to the contract that the backend should provide */
   json_object_set (order,
                    "exchanges",
@@ -337,23 +332,31 @@ proposal_put (struct MHD_Connection *connection,
                        "merchant_pub",
                       GNUNET_JSON_from_data_auto (&mi->pubkey));
 
-  /* create proposal signature */
-  pdps.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT);
-  pdps.purpose.size = htonl (sizeof (pdps));
-  if (GNUNET_OK !=
-      TALER_JSON_hash (order,
-                       &pdps.hash))
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Inserting order '%s' for instance '%s'\n",
+              order_id,
+              mi->id);
+
+  json_t *dummy_contract_terms;
+  qs = db->find_orders (db->cls,
+                        &dummy_contract_terms,
+                        order_id,
+                        &mi->pubkey);
+  if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs)
   {
-    GNUNET_break (0);
-    GNUNET_JSON_parse_free (spec);
-    return TMH_RESPONSE_reply_internal_error (connection,
-                                              TALER_EC_INTERNAL_LOGIC_ERROR,
-                                              "Could not hash order");
+    if ( (GNUNET_DB_STATUS_SOFT_ERROR == qs) ||
+         (GNUNET_DB_STATUS_HARD_ERROR == qs) )
+    {
+      return TMH_RESPONSE_reply_internal_error (connection,
+                                                
TALER_EC_PROPOSAL_STORE_DB_ERROR,
+                                                "db error: could not check for 
existing order");
+    }
+    return TMH_RESPONSE_reply_external_error (connection,
+                                              TALER_EC_PROPOSAL_STORE_DB_ERROR,
+                                              "proposal already exists");
   }
 
-  GNUNET_CRYPTO_eddsa_sign (&mi->privkey.eddsa_priv,
-                            &pdps.purpose,
-                            &merchant_sig);
+
 
   for (unsigned int i=0;i<MAX_RETRIES;i++)
   {
@@ -377,9 +380,11 @@ proposal_put (struct MHD_Connection *connection,
                                               "db error: could not store this 
proposal's data into db");
   }
 
-  res = TMH_RESPONSE_reply_json (connection,
-                                 json_object (),
-                                 MHD_HTTP_OK);
+  res = TMH_RESPONSE_reply_json_pack (connection,
+                                      MHD_HTTP_OK,
+                                      "{s:s}",
+                                      "order_id",
+                                      order_id);
   GNUNET_JSON_parse_free (spec);
   return res;
 }
@@ -579,7 +584,9 @@ MH_handler_proposal_lookup (struct TMH_RequestHandler *rh,
     }
   }
 
-  const char *stored_nonce = json_string_value 
(json_object_get(contract_terms, "nonce"));
+  GNUNET_assert (NULL != contract_terms);
+
+  const char *stored_nonce = json_string_value (json_object_get 
(contract_terms, "nonce"));
 
   if (NULL == stored_nonce)
   {
@@ -596,10 +603,33 @@ MH_handler_proposal_lookup (struct TMH_RequestHandler *rh,
                                            "mismatched nonce");
   }
 
-  res = TMH_RESPONSE_reply_json (connection,
-                                 contract_terms,
-                                 MHD_HTTP_OK);
-  json_decref (contract_terms);
+  struct TALER_ProposalDataPS pdps;
+  struct GNUNET_CRYPTO_EddsaSignature merchant_sig;
+
+  /* create proposal signature */
+  pdps.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT);
+  pdps.purpose.size = htonl (sizeof (pdps));
+  if (GNUNET_OK !=
+      TALER_JSON_hash (contract_terms,
+                       &pdps.hash))
+  {
+    GNUNET_break (0);
+    return TMH_RESPONSE_reply_internal_error (connection,
+                                              TALER_EC_INTERNAL_LOGIC_ERROR,
+                                              "Could not hash order");
+  }
+
+  GNUNET_CRYPTO_eddsa_sign (&mi->privkey.eddsa_priv,
+                            &pdps.purpose,
+                            &merchant_sig);
+
+  res = TMH_RESPONSE_reply_json_pack (connection,
+                                      MHD_HTTP_OK,
+                                      "{ s:o, s:o }",
+                                      "contract_terms",
+                                      contract_terms,
+                                      "sig",
+                                      GNUNET_JSON_from_data_auto 
(&merchant_sig));
   return res;
 }
 
diff --git a/src/backend/taler-merchant-httpd_refund.c 
b/src/backend/taler-merchant-httpd_refund.c
index 47ebda0..8df1ea4 100644
--- a/src/backend/taler-merchant-httpd_refund.c
+++ b/src/backend/taler-merchant-httpd_refund.c
@@ -260,15 +260,16 @@ MH_handler_refund_increase (struct TMH_RequestHandler *rh,
    * the information needed to generate the right response.
    */
 
-  json_decref (contract_terms);
-  json_decref (root);
-  GNUNET_JSON_parse_free (spec);
-
   confirmation.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND_OK);
   confirmation.purpose.size = htonl (sizeof (struct 
TALER_MerchantRefundConfirmationPS));
   GNUNET_CRYPTO_hash (order_id,
                       strlen (order_id),
                       &confirmation.h_order_id);
+
+  json_decref (contract_terms);
+  json_decref (root);
+  GNUNET_JSON_parse_free (spec);
+
   if (GNUNET_OK !=
       GNUNET_CRYPTO_eddsa_sign (&mi->privkey.eddsa_priv,
                                &confirmation.purpose,
diff --git a/src/backenddb/plugin_merchantdb_postgres.c 
b/src/backenddb/plugin_merchantdb_postgres.c
index ee8a947..66a3529 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -76,6 +76,7 @@ postgres_drop_tables (void *cls)
     GNUNET_PQ_make_try_execute ("DROP TABLE IF EXISTS merchant_tip_pickups 
CASCADE;"),
     GNUNET_PQ_make_try_execute ("DROP TABLE IF EXISTS 
merchant_tip_reserve_credits CASCADE;"),
     GNUNET_PQ_make_try_execute ("DROP TABLE IF EXISTS merchant_tip_reserves 
CASCADE;"),
+    GNUNET_PQ_make_try_execute ("DROP TABLE IF EXISTS merchant_orders 
CASCADE;"),
     GNUNET_PQ_EXECUTE_STATEMENT_END
   };
 
diff --git a/src/include/taler_merchant_service.h 
b/src/include/taler_merchant_service.h
index 51db135..63c396a 100644
--- a/src/include/taler_merchant_service.h
+++ b/src/include/taler_merchant_service.h
@@ -147,18 +147,14 @@ struct TALER_MERCHANT_ProposalOperation;
  *                    0 if the backend's reply is bogus (fails to follow the 
protocol)
  * @param ec taler-specific error code
  * @param obj raw JSON reply, or error details if the request failed
- * @param contract_terms completed contract, NULL on error
- * @param sig merchant's signature over the contract, NULL on error
- * @param hash proposal data's hashcode, NULL on error
+ * @param order_id order id of the newly created order
  */
 typedef void
 (*TALER_MERCHANT_ProposalCallback) (void *cls,
                                     unsigned int http_status,
                                    enum TALER_ErrorCode ec,
                                     const json_t *obj,
-                                    const json_t *contract_terms,
-                                    const struct TALER_MerchantSignatureP *sig,
-                                    const struct GNUNET_HashCode *hash);
+                                    const char *order_id);
 
 
 /**
@@ -207,7 +203,10 @@ struct TALER_MERCHANT_ProposalLookupOperation;
 typedef void
 (*TALER_MERCHANT_ProposalLookupOperationCallback) (void *cls,
                                                    unsigned int http_status,
-                                                   const json_t *body);
+                                                   const json_t *body,
+                                                   const json_t 
*contract_terms,
+                                                   const struct 
TALER_MerchantSignatureP *sig,
+                                                   const struct 
GNUNET_HashCode *hash);
 
 
 /**
@@ -216,7 +215,9 @@ typedef void
  *
  * @param ctx execution context
  * @param backend_url base URL of the merchant backend
- * @param transaction_id transaction id used to perform the lookup
+ * @param order_id order id used to perform the lookup
+ * @param nonce nonce to use, only used when requesting the proposal the first 
time,
+ *              can be NULL to omit the nonce (after the first request)
  * @param plo_cb callback which will work the response gotten from the backend
  * @param plo_cb_cls closure to pass to @a history_cb
  * @return handle for this operation, NULL upon errors
@@ -224,8 +225,9 @@ typedef void
 struct TALER_MERCHANT_ProposalLookupOperation *
 TALER_MERCHANT_proposal_lookup (struct GNUNET_CURL_Context *ctx,
                                 const char *backend_url,
-                                const char *transaction_id,
+                                const char *order_id,
                                 const char *instance,
+                                const struct GNUNET_CRYPTO_EddsaPublicKey 
*nonce,
                                 TALER_MERCHANT_ProposalLookupOperationCallback 
plo_cb,
                                 void *plo_cb_cls);
 
diff --git a/src/lib/merchant_api_proposal.c b/src/lib/merchant_api_proposal.c
index fa7e6b6..88d902b 100644
--- a/src/lib/merchant_api_proposal.c
+++ b/src/lib/merchant_api_proposal.c
@@ -99,6 +99,16 @@ struct TALER_MERCHANT_ProposalLookupOperation
    */
   struct GNUNET_CURL_Context *ctx;
 
+  /**
+   * Should we send the lookup operation with a nonce?
+   */
+  int has_nonce;
+
+  /**
+   * Nonce, only initialized if has_nonce is GNUNET_YES.
+   */
+  struct GNUNET_CRYPTO_EddsaPublicKey nonce;
+
 };
 
 
@@ -116,29 +126,19 @@ handle_proposal_finished (void *cls,
                           const json_t *json)
 {
   struct TALER_MERCHANT_ProposalOperation *po = cls;
-  json_t *contract_terms;
-  const struct TALER_MerchantSignatureP *sigp;
-  const struct GNUNET_HashCode *hashp;
-  struct TALER_MerchantSignatureP sig;
-  struct GNUNET_HashCode hash;
+  const char *order_id;
+  struct GNUNET_JSON_Specification spec[] = {
+    GNUNET_JSON_spec_string ("order_id", &order_id),
+    GNUNET_JSON_spec_end()
+  };
 
   po->job = NULL;
-  contract_terms = NULL;
-  sigp = NULL;
-  hashp = NULL;
   switch (response_code)
   {
   case 0:
     break;
   case MHD_HTTP_OK:
     {
-      struct GNUNET_JSON_Specification spec[] = {
-        GNUNET_JSON_spec_json ("data", &contract_terms),
-        GNUNET_JSON_spec_fixed_auto ("sig", &sig),
-        GNUNET_JSON_spec_fixed_auto ("hash", &hash),
-        GNUNET_JSON_spec_end()
-      };
-
       if (GNUNET_OK !=
           GNUNET_JSON_parse (json,
                              spec,
@@ -148,8 +148,6 @@ handle_proposal_finished (void *cls,
         response_code = 0;
         break;
       }
-      hashp = &hash;
-      sigp = &sig;
     }
     break;
   case MHD_HTTP_BAD_REQUEST:
@@ -183,11 +181,8 @@ handle_proposal_finished (void *cls,
           response_code,
          TALER_JSON_get_error_code (json),
           json,
-          contract_terms,
-          sigp,
-          hashp);
-  if (NULL != contract_terms)
-    json_decref (contract_terms);
+          order_id);
+  GNUNET_JSON_parse_free (spec);
   TALER_MERCHANT_proposal_cancel (po);
 }
 
@@ -267,6 +262,70 @@ handle_proposal_lookup_finished (void *cls,
                                  const json_t *json)
 {
   struct TALER_MERCHANT_ProposalLookupOperation *plo = cls;
+  json_t *contract_terms;
+  struct TALER_MerchantSignatureP sig;
+  struct GNUNET_HashCode hash;
+  struct GNUNET_JSON_Specification spec[] = {
+    GNUNET_JSON_spec_json ("contract_terms", &contract_terms),
+    GNUNET_JSON_spec_fixed_auto ("sig", &sig),
+    GNUNET_JSON_spec_end()
+  };
+
+  if (MHD_HTTP_OK != response_code)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "proposal lookup failed with HTTP status code %u\n",
+                (unsigned int) response_code);
+    char *s = json_dumps (json, JSON_COMPACT);
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "error json: %s\n",
+                s);
+    GNUNET_free_non_null (s);
+    GNUNET_break_op (0);
+    plo->cb (plo->cb_cls,
+             response_code,
+             json,
+             NULL,
+             NULL,
+             NULL);
+    return;
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_JSON_parse (json,
+                         spec,
+                         NULL, NULL))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "proposal lookup failed to parse JSON\n");
+    char *s = json_dumps (json, JSON_COMPACT);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "proposal json was: %s\n",
+                s);
+    GNUNET_free_non_null (s);
+    GNUNET_break_op (0);
+    plo->cb (plo->cb_cls,
+             0,
+             json,
+             NULL,
+             NULL,
+             NULL);
+    return;
+  }
+
+  if (GNUNET_OK != TALER_JSON_hash (contract_terms, &hash))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "proposal lookup failed to hash proposal JSON\n");
+    GNUNET_break (0);
+    plo->cb (plo->cb_cls,
+             0,
+             json,
+             NULL,
+             NULL,
+             NULL);
+    return;
+  }
 
   plo->job = NULL;
   /**
@@ -275,7 +334,10 @@ handle_proposal_lookup_finished (void *cls,
    */
   plo->cb (plo->cb_cls,
            response_code,
-           json);
+           json,
+           contract_terms,
+           &sig,
+           &hash);
   TALER_MERCHANT_proposal_lookup_cancel (plo);
 }
 
@@ -286,7 +348,8 @@ handle_proposal_lookup_finished (void *cls,
  *
  * @param ctx execution context
  * @param backend_uri base URL of the merchant backend
- * @param transaction_id transaction id used to perform the lookup
+ * @param order_id order id used to perform the lookup
+ * @param nonce nonce used to perform the lookup
  * @param plo_cb callback which will work the response gotten from the backend
  * @param plo_cb_cls closure to pass to @a history_cb
  * @return handle for this operation, NULL upon errors
@@ -296,6 +359,7 @@ TALER_MERCHANT_proposal_lookup (struct GNUNET_CURL_Context 
*ctx,
                                 const char *backend_uri,
                                 const char *order_id,
                                 const char *instance,
+                                const struct GNUNET_CRYPTO_EddsaPublicKey 
*nonce,
                                 TALER_MERCHANT_ProposalLookupOperationCallback 
plo_cb,
                                 void *plo_cb_cls)
 {
@@ -309,11 +373,29 @@ TALER_MERCHANT_proposal_lookup (struct 
GNUNET_CURL_Context *ctx,
   plo->cb_cls = plo_cb_cls;
   base = MAH_path_to_url_ (backend_uri,
                           "/proposal");
-  GNUNET_asprintf (&plo->url,
-                   "%s?order_id=%s&instance=%s",
-                   base,
-                   order_id,
-                   instance);
+  if (NULL != nonce)
+  {
+    char *nonce_str;
+    plo->has_nonce = GNUNET_YES;
+    plo->nonce = *nonce;
+    nonce_str = GNUNET_STRINGS_data_to_string_alloc (nonce, sizeof (struct 
GNUNET_CRYPTO_EddsaPublicKey));
+    GNUNET_assert (NULL != nonce_str);
+    GNUNET_asprintf (&plo->url,
+                     "%s?order_id=%s&instance=%s&nonce=%s",
+                     base,
+                     order_id,
+                     instance,
+                     nonce_str);
+    GNUNET_free (nonce_str);
+  }
+  else
+  {
+    GNUNET_asprintf (&plo->url,
+                     "%s?order_id=%s&instance=%s",
+                     base,
+                     order_id,
+                     instance);
+  }
   GNUNET_free (base);
   eh = curl_easy_init ();
   if (CURLE_OK != curl_easy_setopt (eh,
@@ -324,6 +406,10 @@ TALER_MERCHANT_proposal_lookup (struct GNUNET_CURL_Context 
*ctx,
     return NULL;
   }
 
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "looking up proposal from %s\n",
+              plo->url);
+
   if (NULL == (plo->job = GNUNET_CURL_job_add (ctx,
                                                eh,
                                                GNUNET_YES,
diff --git a/src/lib/test_merchant_api.c b/src/lib/test_merchant_api.c
index b09d78a..ea119a1 100644
--- a/src/lib/test_merchant_api.c
+++ b/src/lib/test_merchant_api.c
@@ -500,6 +500,11 @@ struct Command
       struct TALER_MERCHANT_ProposalOperation *po;
 
       /**
+       * Handle to the active GET /proposal operation, or NULL.
+       */
+      struct TALER_MERCHANT_ProposalLookupOperation *plo;
+
+      /**
        * Full contract in JSON, set by the /contract operation.
        * FIXME: verify in the code that this bit is actually proposal
        * data and not the whole proposal.
@@ -516,6 +521,12 @@ struct Command
        */
       struct GNUNET_HashCode hash;
 
+      /**
+       * The nonce set by the customer looking up the contract
+       * the first time.
+       */
+      struct GNUNET_CRYPTO_EddsaPublicKey nonce;
+
     } proposal;
 
     /**
@@ -1538,6 +1549,39 @@ reserve_withdraw_cb (void *cls,
 
 
 /**
+ * Callback for GET /proposal issued at backend.
+ * Used to initialize the proposal after it was created.
+ *
+ * @param cls closure
+ * @param http_status HTTP status code we got
+ * @param json full response we got
+ */
+static void
+proposal_lookup_initial_cb (void *cls,
+                            unsigned int http_status,
+                            const json_t *json,
+                            const json_t *contract_terms,
+                            const struct TALER_MerchantSignatureP *sig,
+                            const struct GNUNET_HashCode *hash)
+{
+  struct InterpreterState *is = cls;
+  struct Command *cmd = &is->commands[is->ip];
+
+  if (cmd->expected_response_code != http_status)
+  {
+    fail (is);
+  }
+
+  cmd->details.proposal.hash = *hash;
+  cmd->details.proposal.merchant_sig = *sig;
+  cmd->details.proposal.contract_terms = json_deep_copy (contract_terms);
+
+  cmd->details.proposal.plo = NULL;
+  next_command (is);
+}
+
+
+/**
  * Callback that works POST /proposal's output.
  *
  * @param cls closure
@@ -1556,9 +1600,7 @@ proposal_cb (void *cls,
              unsigned int http_status,
             enum TALER_ErrorCode ec,
              const json_t *obj,
-             const json_t *contract_terms,
-             const struct TALER_MerchantSignatureP *sig,
-             const struct GNUNET_HashCode *hash)
+             const char *order_id)
 {
   struct InterpreterState *is = cls;
   struct Command *cmd = &is->commands[is->ip];
@@ -1567,22 +1609,32 @@ proposal_cb (void *cls,
   switch (http_status)
   {
   case MHD_HTTP_OK:
-    cmd->details.proposal.contract_terms = json_incref ((json_t *) 
contract_terms);
-    cmd->details.proposal.merchant_sig = *sig;
-    cmd->details.proposal.hash = *hash;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Hashed proposal is `%s'\n",
-                GNUNET_h2s (hash));
     break;
-  default:
+  default: {
+    char *s = json_dumps (obj, JSON_COMPACT);
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unexpected status code from /proposal: %u. Step %u\n",
+                "Unexpected status code from /proposal: %u. Step %u, response: 
%s\n",
                 http_status,
-                is->ip);
+                is->ip,
+                s);
+    GNUNET_free_non_null (s);
     fail (is);
+    }
     return;
   }
-  next_command (is);
+
+  if (NULL == (cmd->details.proposal.plo
+               = TALER_MERCHANT_proposal_lookup (ctx,
+                                                 MERCHANT_URL,
+                                                 order_id,
+                                                 instance,
+                                                 &cmd->details.proposal.nonce,
+                                                 proposal_lookup_initial_cb,
+                                                 is)))
+  {
+    GNUNET_break (0);
+    fail (is);
+  }
 }
 
 
@@ -2011,7 +2063,10 @@ track_transfer_cb (void *cls,
 static void
 proposal_lookup_cb (void *cls,
                     unsigned int http_status,
-                    const json_t *json)
+                    const json_t *json,
+                    const json_t *contract_terms,
+                    const struct TALER_MerchantSignatureP *sig,
+                    const struct GNUNET_HashCode *hash)
 {
   struct InterpreterState *is = cls;
   struct Command *cmd = &is->commands[is->ip];
@@ -2421,12 +2476,20 @@ cleanup_state (struct InterpreterState *is)
       if (NULL != cmd->details.proposal.po)
       {
         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                    "Command %u (%s) did not complete\n",
+                    "Command %u (%s) did not complete (proposal put)\n",
                     i,
                     cmd->label);
         TALER_MERCHANT_proposal_cancel (cmd->details.proposal.po);
         cmd->details.proposal.po = NULL;
       }
+      if (NULL != cmd->details.proposal.plo)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Command %u (%s) did not complete (proposal lookup)\n",
+                    i,
+                    cmd->label);
+        TALER_MERCHANT_proposal_lookup_cancel (cmd->details.proposal.plo);
+      }
       if (NULL != cmd->details.proposal.contract_terms)
       {
         json_decref (cmd->details.proposal.contract_terms);
@@ -2861,11 +2924,13 @@ interpreter_run (void *cls)
 
       order_id = json_string_value (json_object_get 
(ref->details.proposal.contract_terms,
                                                      "order_id"));
+
       if (NULL == (cmd->details.proposal_lookup.plo
                    = TALER_MERCHANT_proposal_lookup (ctx,
                                                      MERCHANT_URL,
                                                      order_id,
                                                      instance,
+                                                     
&ref->details.proposal.nonce,
                                                      proposal_lookup_cb,
                                                      is)))
       {
@@ -3034,6 +3099,10 @@ interpreter_run (void *cls)
       GNUNET_assert (NULL != (order = json_loads (cmd->details.proposal.order,
                                                   JSON_REJECT_DUPLICATES,
                                                   &error)));
+      GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+                                  &cmd->details.proposal.nonce,
+                                  sizeof (struct 
GNUNET_CRYPTO_EddsaPublicKey));
+
       if (NULL != instance)
       {
         json_t *merchant;
diff --git a/src/lib/test_merchant_api.conf b/src/lib/test_merchant_api.conf
index c4a4eb7..67ef46b 100644
--- a/src/lib/test_merchant_api.conf
+++ b/src/lib/test_merchant_api.conf
@@ -77,22 +77,27 @@ MASTER_KEY = 
98NJW3CQHZQGQXTY3K85K531XKPAPAVV4Q5V8PYYRR00NJGZWNVG
 
 [merchant-instance-default]
 KEYFILE = test_merchant.priv
+NAME = Kudos Inc.
 
 [merchant-instance-wireformat-default]
 TEST_RESPONSE_FILE = ${TALER_CONFIG_HOME}/merchant/wire/test.json
 
 [merchant-instance-tor]
 KEYFILE = tor_merchant.priv
+NAME = The Tor Project
 
 [merchant-instance-tip]
 KEYFILE = reserve_tip.priv
 TIP_EXCHANGE = http://localhost:8084/
 TIP_RESERVE_PRIV_FILENAME = reserve_key.priv
+NAME = Test Tipping Merchant
 
 [merchant-instance-dtip]
 KEYFILE = reserve_dtip.priv
 TIP_EXCHANGE = http://localhost:8084/
 TIP_RESERVE_PRIV_FILENAME = reserve_dkey.priv
+NAME = Test Tipping Merchant 2
+
 
 [merchant-instance-wireformat-tor]
 TEST_RESPONSE_FILE = ${TALER_CONFIG_HOME}/merchant/wire/test.json
diff --git a/src/merchant-tools/taler-merchant-generate-payments.c 
b/src/merchant-tools/taler-merchant-generate-payments.c
index 887b9db..7d40473 100644
--- a/src/merchant-tools/taler-merchant-generate-payments.c
+++ b/src/merchant-tools/taler-merchant-generate-payments.c
@@ -387,6 +387,11 @@ struct Command
       struct TALER_MERCHANT_ProposalOperation *po;
 
       /**
+       * Handle to the active GET /proposal operation, or NULL
+       */
+      struct TALER_MERCHANT_ProposalLookupOperation *plo;
+
+      /**
        * Full contract in JSON, set by the /contract operation.
        * FIXME: verify in the code that this bit is actually proposal
        * data and not the whole proposal.
@@ -519,7 +524,7 @@ next_command (struct InterpreterState *is)
 
 
 /**
- * Callback that works PUT /proposal's output.
+ * Callback that processes GET /proposal's output.
  *
  * @param cls closure
  * @param http_status HTTP response code, 200 indicates success;
@@ -533,18 +538,17 @@ next_command (struct InterpreterState *is)
  * @param h_contract hash of the contract, NULL on error
  */
 static void
-proposal_cb (void *cls,
-             unsigned int http_status,
-            enum TALER_ErrorCode ec,
-             const json_t *obj,
-             const json_t *contract_terms,
-             const struct TALER_MerchantSignatureP *sig,
-             const struct GNUNET_HashCode *hash)
+proposal_lookup_cb (void *cls,
+                    unsigned int http_status,
+                    const json_t *obj,
+                    const json_t *contract_terms,
+                    const struct TALER_MerchantSignatureP *sig,
+                    const struct GNUNET_HashCode *hash)
 {
   struct InterpreterState *is = cls;
   struct Command *cmd = &is->commands[is->ip];
 
-  cmd->details.proposal.po = NULL;
+  cmd->details.proposal.plo = NULL;
   switch (http_status)
   {
   case MHD_HTTP_OK:
@@ -568,6 +572,59 @@ proposal_cb (void *cls,
   next_command (is);
 }
 
+/**
+ * Callback that works PUT /proposal's output.
+ *
+ * @param cls closure
+ * @param http_status HTTP response code, 200 indicates success;
+ *                    0 if the backend's reply is bogus (fails to follow the 
protocol)
+ * @param ec taler-specific error code
+ * @param obj the full received JSON reply, or
+ *            error details if the request failed
+ */
+static void
+proposal_cb (void *cls,
+             unsigned int http_status,
+            enum TALER_ErrorCode ec,
+             const json_t *obj,
+             const char *order_id)
+{
+  struct InterpreterState *is = cls;
+  struct Command *cmd = &is->commands[is->ip];
+
+  cmd->details.proposal.po = NULL;
+  switch (http_status)
+  {
+  case MHD_HTTP_OK: {
+    struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
+    struct GNUNET_CRYPTO_EddsaPublicKey pub;
+
+    priv = GNUNET_CRYPTO_eddsa_key_create ();
+    GNUNET_CRYPTO_eddsa_key_get_public (priv, &pub);
+    GNUNET_free (priv);
+
+    cmd->details.proposal.plo
+        = TALER_MERCHANT_proposal_lookup (ctx,
+                                          merchant_url,
+                                          order_id,
+                                          instance,
+                                          &pub,
+                                          &proposal_lookup_cb,
+                                          is);
+    }
+    break;
+  default:
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "unexpected status code from /proposal: %u. Step %u\n",
+                http_status,
+                is->ip);
+    json_dumpf (obj, stderr, 0);
+    GNUNET_break (0);
+    fail (is);
+    return;
+  }
+}
+
 
 /**
  * Function called with the result of a /pay operation.

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]