gnunet-svn
[Top][All Lists]
Advanced

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

[taler-anastasis] branch master updated: work on payment service


From: gnunet
Subject: [taler-anastasis] branch master updated: work on payment service
Date: Wed, 11 Nov 2020 18:56:23 +0100

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

ds-meister pushed a commit to branch master
in repository anastasis.

The following commit(s) were added to refs/heads/master by this push:
     new 9ad9564  work on payment service
9ad9564 is described below

commit 9ad9564c22b06ea4c6f3c5a456e26ad61f4fd124
Author: Dominik Meister <dominik.meister@hotmail.ch>
AuthorDate: Wed Nov 11 18:56:06 2020 +0100

    work on payment service
---
 src/backend/anastasis-httpd_truth.c       | 564 ++++++++++++++++++++----------
 src/include/anastasis_service.h           |  31 +-
 src/include/anastasis_testing_lib.h       |   4 +
 src/lib/anastasis_api_keyshare_lookup.c   |  47 ++-
 src/lib/test_anastasis_api.c              |  26 +-
 src/lib/test_anastasis_api.conf           |  19 +-
 src/lib/testing_api_cmd_challenge_run.c   |  67 +++-
 src/lib/testing_api_cmd_keyshare_lookup.c |  17 +
 8 files changed, 577 insertions(+), 198 deletions(-)

diff --git a/src/backend/anastasis-httpd_truth.c 
b/src/backend/anastasis-httpd_truth.c
index a30f77c..e229d2a 100644
--- a/src/backend/anastasis-httpd_truth.c
+++ b/src/backend/anastasis-httpd_truth.c
@@ -103,6 +103,14 @@ struct GetContext
    */
   struct ANASTASIS_DB_ChallengePayment cp;
 
+  /**
+   * true if client provided a payment secret / order ID?
+   */
+  bool payment_identifier_provided;
+  /**
+   * true if client provided a payment secret / order ID?
+   */
+  struct TALER_Amount challenge_cost;
 };
 
 /**
@@ -370,7 +378,7 @@ check_payment_cb (void *cls,
 
     qs = db->update_challenge_payment (db->cls,
                                        &gc->truth_public_key,
-                                       &gc->payment_identifier); /* FIXME: 
always annual ?*/
+                                       &gc->payment_identifier);
     if (0 <= qs)
       return; /* continue as planned */
     GNUNET_break (0);
@@ -488,7 +496,7 @@ begin_payment (struct GetContext *gc,
               AH_backend_url);
   MHD_suspend_connection (gc->connection);
   order = json_pack ("{s:o, s:s, s:s, s:s}",
-                     "amount", TALER_JSON_from_amount (&AH_annual_fee),
+                     "amount", TALER_JSON_from_amount (&gc->challenge_cost),
                      "summary", "annual fee for anastasis service",
                      "fulfillment_url", AH_fulfillment_url,
                      "order_id", order_id);
@@ -511,6 +519,70 @@ begin_payment (struct GetContext *gc,
   return MHD_YES;
 }
 
+/**
+ * We got some query status from the DB.  Handle the error cases.
+ * May perform asynchronous operations by suspending the connection
+ * if required.
+ *
+ * @param gc connection to handle status for
+ * @param qs query status to handle
+ * @return #MHD_YES or #MHD_NO
+ */
+static MHD_RESULT
+handle_database_error (struct GetContext *gc,
+                       enum ANASTASIS_DB_QueryStatus qs)
+{
+  switch (qs)
+  {
+  case ANASTASIS_DB_STATUS_PAYMENT_REQUIRED:
+    {
+      if (! gc->payment_identifier_provided)
+      {
+        GNUNET_CRYPTO_random_block (
+          GNUNET_CRYPTO_QUALITY_NONCE,
+          &gc->payment_identifier,
+          sizeof (struct ANASTASIS_PaymentSecretP));
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "Payment-Identifier generated: %s, starting payment 
process\n",
+                    TALER_B2S (&gc->payment_identifier));
+        return begin_payment (gc,
+                              GNUNET_NO);
+      }
+
+      {
+        char *order_id;
+
+        order_id = GNUNET_STRINGS_data_to_string_alloc (
+          &gc->payment_identifier,
+          sizeof (gc->payment_identifier));
+        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                    "Payment required, awaiting completion of `%s'\n",
+                    order_id);
+        await_payment (gc,
+                       CHECK_PAYMENT_GENERIC_TIMEOUT,
+                       order_id);
+        GNUNET_free (order_id);
+      }
+    }
+    return MHD_YES;
+  case ANASTASIS_DB_STATUS_HARD_ERROR:
+  case ANASTASIS_DB_STATUS_SOFT_ERROR:
+    GNUNET_break (0);
+    return TALER_MHD_reply_with_error (puc->con,
+                                       MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                       TALER_EC_GENERIC_DB_FETCH_FAILED,
+                                       NULL);
+  case ANASTASIS_DB_STATUS_NO_RESULTS:
+    GNUNET_assert (0);
+    return MHD_NO;
+  /* intentional fall-through! */
+  case ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT:
+    GNUNET_assert (0);
+    return MHD_NO;
+  }
+  GNUNET_break (0);
+  return MHD_NO;
+}
 
 /**
  * @param connection the MHD connection to handle
@@ -537,6 +609,9 @@ AH_handler_truth_get (struct MHD_Connection *connection,
   size_t decrypted_truth_size;
   char *truth_mime;
   char *method;
+  struct TALER_Amount zero_amount;
+  TALER_amount_get_zero (AH_currency, &zero_amount);
+  bool zero_cost = false;
 
   if (NULL != gc)
   {
@@ -579,11 +654,31 @@ AH_handler_truth_get (struct MHD_Connection *connection,
       return MHD_NO;
     }
   }
+  {
+    const char *pay_id;
 
-  /* extract public key from url */
-  GNUNET_assert (0 == strncmp (url,
-                               "/truth/",
-                               strlen ("/truth/")));
+    pay_id = MHD_lookup_connection_value (connection,
+                                          MHD_HEADER_KIND,
+                                          "Payment-Identifier");
+    if (NULL != pay_id)
+    {
+      if (GNUNET_OK !=
+          GNUNET_STRINGS_string_to_data (pay_id,
+                                         strlen (pay_id),
+                                         &gc->payment_identifier,
+                                         sizeof (struct
+                                                 ANASTASIS_PaymentSecretP)))
+      {
+        GNUNET_break_op (0);
+        return TALER_MHD_reply_with_error (connection,
+                                           MHD_HTTP_BAD_REQUEST,
+                                           // FIXME: find error code
+                                           TALER_EC_SYNC_BAD_IF_MATCH,
+                                           "Payment-Identifier does not 
include a base32-encoded Payment-Secret");
+      }
+      gc->payment_identifier_provided = true;
+    }
+  }
   {
     const char *pub_key_str;
 
@@ -666,198 +761,309 @@ AH_handler_truth_get (struct MHD_Connection *connection,
                                     &decrypted_truth,
                                     &decrypted_truth_size);
   }
-  if (0 == strcmp ("question",
-                   method))
-  {
-    if (NULL == challenge_response_s)
-    {
-      // FIXME: queue PROPER reply...
-      GNUNET_free (decrypted_truth);
-      return MHD_NO;
-    }
-
-    GNUNET_CRYPTO_hash_from_string (challenge_response_s,
-                                    &challenge_response);
-
-    if (0 != GNUNET_memcmp (&challenge_response,
-                            decrypted_truth))
-    {
-      GNUNET_break (0);
-      return TALER_MHD_reply_with_error (connection,
-                                         MHD_HTTP_BAD_REQUEST,
-                                         // FIXME: find error code
-                                         TALER_EC_SYNC_BAD_IF_MATCH,
-                                         "Authentication failed");   // FIXME: 
How much should we tell?
-    }
-    else
-    {
-      return return_key_share (&truth_public_key,
-                               connection);
-    }
-  }
-
-  /* Not security question, check for answer in DB */
-  if (NULL != challenge_response_s)
+  /* Check database to see if the transaction is permissible */
   {
+    struct GNUNET_HashCode hc;
     enum ANASTASIS_DB_QueryStatus qs;
-    unsigned long long code;
-    char dummy;
 
-    if (1 != sscanf (challenge_response_s,
-                     "%llu%c",
-                     &code,
-                     &dummy))
+    if (gc->payment_identifier_provided)
     {
-      // FIXME: queue PROPER reply...
-      GNUNET_free (decrypted_truth);
-      return MHD_NO;
-    }
-
-    qs = db->verify_challenge_code (db->cls,
-                                    &truth_public_key,
-                                    code);
+      // check if payment identifier is valid (existing and paid)
+      bool paid;
 
-    switch (qs)
-    {
-    case ANASTASIS_DB_STATUS_HARD_ERROR:
-      GNUNET_free (decrypted_truth);
-      return MHD_NO;
-    case ANASTASIS_DB_STATUS_SOFT_ERROR:
-      GNUNET_free (decrypted_truth);
-      return MHD_NO;
-    case ANASTASIS_DB_STATUS_NO_RESULTS:
-      GNUNET_free (decrypted_truth);
-      return MHD_NO;
-    case ANASTASIS_DB_STATUS_VALID_CODE_STORED:
-      break;
-    default:
-      GNUNET_free (decrypted_truth);
-      return MHD_NO;
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "At %s:%d Payment-Identifier from header is: %s\n",
+                  __FILE__,
+                  __LINE__,
+                  TALER_B2S (&gc->payment_identifier));
+
+      qs = db->check_challenge_payment (db->cls,
+                                        &puc->payment_identifier,
+                                        &paid);
+      if (qs < 0)
+        return handle_database_error (puc,
+                                      qs);
+
+      if ((qs >= 0) && (! paid))
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "At %s:%d paid is: '%d'\n",
+                    __FILE__,
+                    __LINE__,
+                    paid);
+        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                    "At %s:%d Payment is required, starting payment 
process.\n",
+                    __FILE__,
+                    __LINE__);
+        return begin_payment (gc,
+                              GNUNET_YES);
+      }
     }
 
-    return return_key_share (&truth_public_key,
-                             connection);
-  }
-
-  /* Not security question and no answer: use plugin to generate challenge! */
-  {
-    struct ANASTASIS_AuthorizationPlugin *authorization;
-    enum GNUNET_GenericReturnValue ret;
-    struct ANASTASIS_AUTHORIZATION_State *as;
-    enum ANASTASIS_AUTHORIZATION_Result aret;
-    enum ANASTASIS_DB_QueryStatus qs;
-    struct GNUNET_TIME_Relative challenge_expiration;
-    challenge_expiration = GNUNET_TIME_UNIT_HOURS;
-
-    authorization = ANASTASIS_authorization_plugin_load (method);
-    if (NULL == authorization)
+    if (! gc->payment_identifier_provided)
     {
+      // generate new payment identifier
+      GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+                                  &gc->payment_identifier,
+                                  sizeof (
+                                    struct ANASTASIS_PaymentSecretP));
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Plugin not found: %s",method);
-      GNUNET_free (decrypted_truth);
-      return MHD_NO;
+                  "At %s:%d Payment-Identifier generated is: %s\n",
+                  __FILE__,
+                  __LINE__,
+                  TALER_B2S (&gc->payment_identifier));
+
+
+
+      if (0 == strcmp ("question",
+                       method))
+      {
+        if (0 == TALER_amount_cmp (&AH_question_cost, &zero_amount))
+          zero_cost = true;
+        gc->challenge_cost = AH_question_cost;
+      }
+      if (0 == strcmp ("file",
+                       method))
+      {
+        if (0 == TALER_amount_cmp (&AH_file_cost, &zero_amount))
+          zero_cost = true;
+        gc->challenge_cost = AH_file_cost;
+      }
+
+      if (zero_cost)
+      {
+        qs = db->record_challenge_payment (db->cls,
+                                           &truth_public_key,
+                                           &puc->payment_identifier,
+                                           &gc->challenge_cost);
+        if (qs >= 0)
+        {
+          qs = db->update_challenge_payment (db->cls,
+                                             truth_public_key,
+                                             &gc->payment_identifier);
+        }
+        if (qs < 0)
+          return handle_database_error (gc,
+                                        qs);
+      }
+      else
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                    "At %s:%d Payment is required, starting payment process\n",
+                    __FILE__,
+                    __LINE__);
+        return begin_payment (gc,
+                              GNUNET_YES);
+      }
     }
-
-    ret = authorization->validate (authorization->cls,
-                                   connection,
-                                   decrypted_truth,
-                                   decrypted_truth_size);
-
-    switch (ret)
+    /* check if the client insists on paying */
     {
-    case GNUNET_OK:
-      /* data valid, continued below */
-      break;
-    case GNUNET_NO:
-      /* data invalid, reply was queued */
-      GNUNET_free (decrypted_truth);
-      return MHD_YES;
-    case GNUNET_SYSERR:
-      /* data invalid, reply was NOT queued */
-      GNUNET_free (decrypted_truth);
-      return MHD_NO;
+      const char *order_req;
+
+      order_req = MHD_lookup_connection_value (connection,
+                                               MHD_GET_ARGUMENT_KIND,
+                                               "pay");
+      if (NULL != order_req)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                    "Payment requested, starting payment process\n");
+        return begin_payment (gc,
+                              GNUNET_YES);
+      }
     }
-    // FIXME:
-    // RANDOM! -- or from DB if recent one in DB!
-    uint64_t code = 42;
-    // FIXME TIME where to put this?
-    // FIXME retry counter where to put it?
-    qs = db->store_challenge_code (db->cls,
-                                   &truth_public_key,
-                                   code,
-                                   challenge_expiration,
-                                   3);
 
-    switch (qs)
+    if (0 == strcmp ("question",
+                     method))
     {
-    case ANASTASIS_DB_STATUS_HARD_ERROR:
-      /* data invalid, reply was NOT queued */
-      GNUNET_free (decrypted_truth);
-      return MHD_NO;
-    case ANASTASIS_DB_STATUS_SOFT_ERROR:
-      /* data invalid, reply was NOT queued */
-      GNUNET_free (decrypted_truth);
-      return MHD_NO;
-    case ANASTASIS_DB_STATUS_VALID_CODE_STORED:
-      /*FIXME already code stored message */
-      return MHD_NO;
-    case ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT:
-      /*challengecode was stored successfully*/
-      break;
-    default:
-      GNUNET_free (decrypted_truth);
-      return MHD_NO;
+      if (NULL == challenge_response_s)
+      {
+        // FIXME: queue PROPER reply...
+        GNUNET_free (decrypted_truth);
+        return MHD_NO;
+      }
+
+      GNUNET_CRYPTO_hash_from_string (challenge_response_s,
+                                      &challenge_response);
+
+      if (0 != GNUNET_memcmp (&challenge_response,
+                              decrypted_truth))
+      {
+        GNUNET_break (0);
+        return TALER_MHD_reply_with_error (connection,
+                                           MHD_HTTP_BAD_REQUEST,
+                                           // FIXME: find error code
+                                           TALER_EC_SYNC_BAD_IF_MATCH,
+                                           "Authentication failed"); // FIXME: 
How much should we tell?
+      }
+      else
+      {
+        return return_key_share (&truth_public_key,
+                                 connection);
+      }
     }
 
-    as = authorization->start (authorization->cls,
-                               &truth_public_key,
-                               code,
-                               decrypted_truth,
-                               decrypted_truth_size);
-    GNUNET_free (decrypted_truth);
-    if (NULL == as)
+    /* Not security question, check for answer in DB */
+    if (NULL != challenge_response_s)
     {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  ("AUTHORIZATION START FAILED"));
-      // FIXME: queue PROPER reply...
-      return MHD_NO;
+      enum ANASTASIS_DB_QueryStatus qs;
+      unsigned long long code;
+      char dummy;
+
+      if (1 != sscanf (challenge_response_s,
+                       "%llu%c",
+                       &code,
+                       &dummy))
+      {
+        // FIXME: queue PROPER reply...
+        GNUNET_free (decrypted_truth);
+        return MHD_NO;
+      }
+
+      qs = db->verify_challenge_code (db->cls,
+                                      &truth_public_key,
+                                      code);
+
+      switch (qs)
+      {
+      case ANASTASIS_DB_STATUS_HARD_ERROR:
+        GNUNET_free (decrypted_truth);
+        return MHD_NO;
+      case ANASTASIS_DB_STATUS_SOFT_ERROR:
+        GNUNET_free (decrypted_truth);
+        return MHD_NO;
+      case ANASTASIS_DB_STATUS_NO_RESULTS:
+        GNUNET_free (decrypted_truth);
+        return MHD_NO;
+      case ANASTASIS_DB_STATUS_VALID_CODE_STORED:
+        break;
+      default:
+        GNUNET_free (decrypted_truth);
+        return MHD_NO;
+      }
+
+      return return_key_share (&truth_public_key,
+                               connection);
     }
-    gc = GNUNET_new (struct GetContext);
-    gc->connection = connection;
-    gc->authorization = authorization;
-    gc->as = as;
-    hc->ctx = gc;
-    hc->cc = &request_done;
-    GNUNET_CONTAINER_DLL_insert (gc_head,
-                                 gc_tail,
-                                 gc);
-    aret = authorization->process (as,
-                                   connection);
-    switch (aret)
+
+    /* Not security question and no answer: use plugin to generate challenge! 
*/
     {
-    case ANASTASIS_AUTHORIZATION_RES_SUCCESS:
-      /* all good, challenge sent! */
-      // FIXME: mark in DB that we did it (now, for 
code_retransmission_frequency!)
-      break;
-    case ANASTASIS_AUTHORIZATION_RES_FAILED:
-      /* sending challenge failed */
-      // FIXME: give at least a refund!?
-      break;
-    case ANASTASIS_AUTHORIZATION_RES_SUSPENDED:
-      /* we have been suspended, see you later */
-      return MHD_YES;
-    case ANASTASIS_AUTHORIZATION_RES_SUCCESS_REPLY_FAILED:
-      /* Challenge sent successfully */
-      // FIXME: mark in DB that we did it (now, for 
code_retransmission_frequency!)
-      authorization->cleanup (gc->as);
-      return MHD_NO;
-    case ANASTASIS_AUTHORIZATION_RES_FAILED_REPLY_FAILED:
-      /* failure to queue reply, kill connection */
+      struct ANASTASIS_AuthorizationPlugin *authorization;
+      enum GNUNET_GenericReturnValue ret;
+      struct ANASTASIS_AUTHORIZATION_State *as;
+      enum ANASTASIS_AUTHORIZATION_Result aret;
+      enum ANASTASIS_DB_QueryStatus qs;
+      struct GNUNET_TIME_Relative challenge_expiration;
+      challenge_expiration = GNUNET_TIME_UNIT_HOURS;
+
+      authorization = ANASTASIS_authorization_plugin_load (method);
+      if (NULL == authorization)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "Plugin not found: %s",method);
+        GNUNET_free (decrypted_truth);
+        return MHD_NO;
+      }
+
+      ret = authorization->validate (authorization->cls,
+                                     connection,
+                                     decrypted_truth,
+                                     decrypted_truth_size);
+
+      switch (ret)
+      {
+      case GNUNET_OK:
+        /* data valid, continued below */
+        break;
+      case GNUNET_NO:
+        /* data invalid, reply was queued */
+        GNUNET_free (decrypted_truth);
+        return MHD_YES;
+      case GNUNET_SYSERR:
+        /* data invalid, reply was NOT queued */
+        GNUNET_free (decrypted_truth);
+        return MHD_NO;
+      }
+      // FIXME:
+      // RANDOM! -- or from DB if recent one in DB!
+      uint64_t code = 42;
+      // FIXME TIME where to put this?
+      // FIXME retry counter where to put it?
+      qs = db->store_challenge_code (db->cls,
+                                     &truth_public_key,
+                                     code,
+                                     challenge_expiration,
+                                     3);
+
+      switch (qs)
+      {
+      case ANASTASIS_DB_STATUS_HARD_ERROR:
+        /* data invalid, reply was NOT queued */
+        GNUNET_free (decrypted_truth);
+        return MHD_NO;
+      case ANASTASIS_DB_STATUS_SOFT_ERROR:
+        /* data invalid, reply was NOT queued */
+        GNUNET_free (decrypted_truth);
+        return MHD_NO;
+      case ANASTASIS_DB_STATUS_VALID_CODE_STORED:
+        /*FIXME already code stored message */
+        return MHD_NO;
+      case ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT:
+        /*challengecode was stored successfully*/
+        break;
+      default:
+        GNUNET_free (decrypted_truth);
+        return MHD_NO;
+      }
+
+      as = authorization->start (authorization->cls,
+                                 &truth_public_key,
+                                 code,
+                                 decrypted_truth,
+                                 decrypted_truth_size);
+      GNUNET_free (decrypted_truth);
+      if (NULL == as)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    ("AUTHORIZATION START FAILED"));
+        // FIXME: queue PROPER reply...
+        return MHD_NO;
+      }
+      gc = GNUNET_new (struct GetContext);
+      gc->connection = connection;
+      gc->authorization = authorization;
+      gc->as = as;
+      hc->ctx = gc;
+      hc->cc = &request_done;
+      GNUNET_CONTAINER_DLL_insert (gc_head,
+                                   gc_tail,
+                                   gc);
+      aret = authorization->process (as,
+                                     connection);
+      switch (aret)
+      {
+      case ANASTASIS_AUTHORIZATION_RES_SUCCESS:
+        /* all good, challenge sent! */
+        // FIXME: mark in DB that we did it (now, for 
code_retransmission_frequency!)
+        break;
+      case ANASTASIS_AUTHORIZATION_RES_FAILED:
+        /* sending challenge failed */
+        // FIXME: give at least a refund!?
+        break;
+      case ANASTASIS_AUTHORIZATION_RES_SUSPENDED:
+        /* we have been suspended, see you later */
+        return MHD_YES;
+      case ANASTASIS_AUTHORIZATION_RES_SUCCESS_REPLY_FAILED:
+        /* Challenge sent successfully */
+        // FIXME: mark in DB that we did it (now, for 
code_retransmission_frequency!)
+        authorization->cleanup (gc->as);
+        return MHD_NO;
+      case ANASTASIS_AUTHORIZATION_RES_FAILED_REPLY_FAILED:
+        /* failure to queue reply, kill connection */
+        authorization->cleanup (gc->as);
+        return MHD_NO;
+      }
       authorization->cleanup (gc->as);
-      return MHD_NO;
+      gc->as = NULL;
+      return MHD_YES;
     }
-    authorization->cleanup (gc->as);
-    gc->as = NULL;
-    return MHD_YES;
   }
-}
diff --git a/src/include/anastasis_service.h b/src/include/anastasis_service.h
index 52bb12f..6b24934 100644
--- a/src/include/anastasis_service.h
+++ b/src/include/anastasis_service.h
@@ -237,6 +237,12 @@ struct ANASTASIS_UploadDetails
   } details;
 };
 
+struct ANASTASIS_ChallengeRunDetails
+{
+  const char *response_string;
+  const char *payment_request;
+}
+
 
 typedef void
 (*ANASTASIS_ConfigCallback)(void *cls,
@@ -526,21 +532,26 @@ typedef void
  * @param backend_url base URL of the merchant backend
  * @param truth_public_key identification of the Truth
  * @param truth_key Key used to Decrypt the Truth on the Server
- * @param answer Answer for the different authentication methods(code, hash of 
answer as string)
+ * @param payment_request checks if payment was requested
+ * @param payment_secret secret from the previously done payment NULL to 
trigger payment
+ * @param answer Answer for the different authentication methods(code, hash)
+ * @param answer_length size of the answer
  * @param cb callback which will work the response gotten from the backend
  * @param cb_cls closure to pass to the callback
  * @return handle for this operation, NULL upon errors
  */
 struct ANASTASIS_KeyShareLookupOperation *
-ANASTASIS_keyshare_lookup (
-  struct GNUNET_CURL_Context *ctx,
-  const char *backend_url,
-  const struct ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
-  const struct ANASTASIS_CRYPTO_TruthKeyP *truth_key,
-  const char *answer,
-  ANASTASIS_KeyShareLookupCallback cb,
-  void *cb_cls);
-
+ANASTASIS_keyshare_lookup (struct GNUNET_CURL_Context *ctx,
+                           const char *backend_url,
+                           const struct
+                           ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
+                           const struct ANASTASIS_CRYPTO_TruthKeyP *truth_key,
+                           int payment_requested,
+                           const struct
+                           ANASTASIS_PaymentSecretP *payment_secret,
+                           const char *answer,
+                           ANASTASIS_KeyShareLookupCallback cb,
+                           void *cb_cls)
 
 /**
  * Cancel a GET /truth request.
diff --git a/src/include/anastasis_testing_lib.h 
b/src/include/anastasis_testing_lib.h
index 3fae5d5..f9cd892 100644
--- a/src/include/anastasis_testing_lib.h
+++ b/src/include/anastasis_testing_lib.h
@@ -433,6 +433,7 @@ ANASTASIS_TESTING_cmd_truth_store (const char *label,
  * @param http_status expected HTTP status.
  * @param answer (response to challenge)
  * @param key key to decrypt truth
+ * @param payment secret secret used to pay
  * @param upload_ref reference to upload command
  * @param lookup_mode defines the mode (0= secure question, 1 code based)
  * @return the command
@@ -444,6 +445,9 @@ ANASTASIS_TESTING_cmd_keyshare_lookup (const char *label,
                                        char *answer,
                                        const struct
                                        ANASTASIS_CRYPTO_TruthKeyP key,
+                                       const struct
+                                       ANASTASIS_PaymentSecretP 
*payment_secret,
+                                       int payment_requested,
                                        const char *upload_ref,
                                        int lookup_mode);
 /**
diff --git a/src/lib/anastasis_api_keyshare_lookup.c 
b/src/lib/anastasis_api_keyshare_lookup.c
index 06111ad..b3c96c0 100644
--- a/src/lib/anastasis_api_keyshare_lookup.c
+++ b/src/lib/anastasis_api_keyshare_lookup.c
@@ -235,6 +235,8 @@ handle_header (char *buffer,
  * @param backend_url base URL of the merchant backend
  * @param truth_public_key identification of the Truth
  * @param truth_key Key used to Decrypt the Truth on the Server
+ * @param payment_request checks if payment was requested
+ * @param payment_secret secret from the previously done payment NULL to 
trigger payment
  * @param answer Answer for the different authentication methods(code, hash)
  * @param answer_length size of the answer
  * @param cb callback which will work the response gotten from the backend
@@ -247,6 +249,9 @@ ANASTASIS_keyshare_lookup (struct GNUNET_CURL_Context *ctx,
                            const struct
                            ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
                            const struct ANASTASIS_CRYPTO_TruthKeyP *truth_key,
+                           int payment_requested,
+                           const struct
+                           ANASTASIS_PaymentSecretP *payment_secret,
                            const char *answer,
                            ANASTASIS_KeyShareLookupCallback cb,
                            void *cb_cls)
@@ -280,6 +285,29 @@ ANASTASIS_keyshare_lookup (struct GNUNET_CURL_Context *ctx,
     }
     job_headers = ext;
   }
+  /* Setup Payment-Identifier header */
+  if (NULL != payment_secret)
+  {
+    char *paid_order_id;
+
+    paid_order_id = GNUNET_STRINGS_data_to_string_alloc (
+      payment_secret,
+      sizeof (*payment_secret));
+    GNUNET_asprintf (&hdr,
+                     "Payment-Identifier: %s",
+                     paid_order_id);
+    GNUNET_free (paid_order_id);
+    ext = curl_slist_append (job_headers,
+                             hdr);
+    GNUNET_free (hdr);
+    if (NULL == ext)
+    {
+      GNUNET_break (0);
+      curl_slist_free_all (job_headers);
+      return NULL;
+    }
+    job_headers = ext;
+  }
   kslo = GNUNET_new (struct ANASTASIS_KeyShareLookupOperation);
   kslo->ctx = ctx;
   kslo->truth_key = truth_key;
@@ -293,11 +321,20 @@ ANASTASIS_keyshare_lookup (struct GNUNET_CURL_Context 
*ctx,
   GNUNET_asprintf (&path,
                    "truth/%s",
                    pub_key_str);
-  kslo->url = TALER_url_join (backend_url,
-                              path,
-                              "response",
-                              answer,
-                              NULL);
+
+  kslo->url = (GNUNET_YES == payment_requested)
+              ? TALER_url_join (backend_url,
+                                path,
+                                "pay",
+                                "y",
+                                NULL)
+              : TALER_url_join (backend_url,
+                                path,
+                                "response",
+                                answer,
+                                NULL);
+  GNUNET_free (path);
+
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Url get request (keyshare lookup): %s\n",
               kslo->url);
diff --git a/src/lib/test_anastasis_api.c b/src/lib/test_anastasis_api.c
index 0cd67df..0e1549b 100644
--- a/src/lib/test_anastasis_api.c
+++ b/src/lib/test_anastasis_api.c
@@ -264,6 +264,8 @@ run (void *cls,
                                            answer_str,
                                            ANASTASIS_TESTING_make_truthkey (
                                              "Truth-Key"),
+                                           NULL,
+                                           0,
                                            "truth-store-1",
                                            0),
 
@@ -282,6 +284,28 @@ run (void *cls,
                                            "Truth-Key-2"))),
 
     ANASTASIS_TESTING_cmd_challenge_run ("challenge-run-1",
+                                         anastasis_url,
+                                         MHD_HTTP_PAYMENT_REQUIRED,
+                                         ANASTASIS_TESTING_make_truthkey (
+                                           "Truth-Key-2"),
+                                         "truth-store-2"),
+    /* what would we have to pay? */
+    TALER_TESTING_cmd_merchant_claim_order ("fetch-proposal",
+                                            merchant_url,
+                                            MHD_HTTP_OK,
+                                            "challenge-run-1",
+                                            NULL),
+    /* make the payment */
+    TALER_TESTING_cmd_merchant_pay_order ("pay-account",
+                                          merchant_url,
+                                          MHD_HTTP_OK,
+                                          "fetch-proposal",
+                                          "withdraw-coin-1",
+                                          "EUR:1",
+                                          "EUR:1", /* must match ANNUAL_FEE in 
config! */
+                                          NULL),
+
+    ANASTASIS_TESTING_cmd_challenge_run ("challenge-run-2",
                                          anastasis_url,
                                          MHD_HTTP_OK,
                                          ANASTASIS_TESTING_make_truthkey (
@@ -291,7 +315,7 @@ run (void *cls,
     ANASTASIS_TESTING_cmd_keyshare_lookup ("keyshare-lookup-2",
                                            anastasis_url,
                                            MHD_HTTP_OK,
-                                           "challenge-run-1",
+                                           "challenge-run-2",
                                            ANASTASIS_TESTING_make_truthkey (
                                              "Truth-Key-2"),
                                            "truth-store-2",
diff --git a/src/lib/test_anastasis_api.conf b/src/lib/test_anastasis_api.conf
index 0821ffb..91db82a 100644
--- a/src/lib/test_anastasis_api.conf
+++ b/src/lib/test_anastasis_api.conf
@@ -44,11 +44,26 @@ PAYMENT_BACKEND_URL = http://localhost:8080/
 ANNUAL_FEE = EUR:4.99
 #ANNUAL_FEE = EUR:0
 
-# Cost of authentication by question
-#QUESTION_COST = EUR:0
+# Authentication costs
 
+# Cost of authentication by question
 QUESTION_COST = EUR:0
 
+# Cost of authentication by file (only for testing purposes)
+FILE_COST = EUR:1
+
+# Cost of authentication by E-Mail
+#EMAIL_COST = EUR:0
+
+# Cost of authentication by SMS
+#SMS_COST = EUR:0
+
+# Cost of authentication by postal
+#POSTAL_COST = EUR:0
+
+# Cost of authentication by video
+#VIDEO_COST = EUR:0
+
 # Upload limit
 UPLOAD_LIMIT_MB = 1
 
diff --git a/src/lib/testing_api_cmd_challenge_run.c 
b/src/lib/testing_api_cmd_challenge_run.c
index e59f38c..f1b9231 100644
--- a/src/lib/testing_api_cmd_challenge_run.c
+++ b/src/lib/testing_api_cmd_challenge_run.c
@@ -32,6 +32,26 @@
  */
 struct ChallengeRunState
 {
+  /**
+   * Claim token we got back, if any. Otherwise all zeros.
+   */
+  struct TALER_ClaimTokenP token;
+
+  /**
+   * Payment identifier.
+   */
+  struct ANASTASIS_PaymentSecretP payment_id;
+
+  /**
+   * Payment order ID we got back, if any. Otherwise NULL.
+   */
+  char *payment_order_id;
+
+  /**
+   * Payment order ID we are to provide in the request, may be NULL.
+   */
+  struct ANASTASIS_PaymentSecretP payment_order_req;
+
   /**
    * The interpreter state.
    */
@@ -81,7 +101,7 @@ struct ChallengeRunState
 static void
 challenge_run_cb (void *cls,
                   unsigned int http_status,
-                  char *response_string)
+                  const struct ANASTASIS_ChallengeRunDetails *crd)
 {
   struct ChallengeRunState *crs = cls;
   crs->cro = NULL;
@@ -96,6 +116,47 @@ challenge_run_cb (void *cls,
     TALER_TESTING_interpreter_fail (crs->is);
     return;
   }
+
+  if (http_status == MHD_HTTP_PAYMENT_REQUIRED)
+  {
+    const char *m;
+
+    if (0 != strncmp (crd->payment_request,
+                      "taler://pay/http",
+                      strlen ("taler://pay/http")))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Did not find `%s' in `%s'\n",
+                  "/-/-/",
+                  crd->payment_request);
+      TALER_TESTING_interpreter_fail (crs->is);
+      return;
+    }
+    m = strstr (crd->payment_request, "/-/-/");
+    if (NULL == m)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Did not find `%s' in `%s'\n",
+                  "/-/-/",
+                  crd->payment_request);
+      TALER_TESTING_interpreter_fail (pss->is);
+      /* NOTE: The above is a simplifying assumption for the
+         test-logic, hitting this code merely means that
+         the assumptions for the test (i.e. no instance) are
+         not satisfied, it is not inherently the case that
+         the above token must appear in the payment request!
+
+         So if you hit this, you might just want to modify
+         the code here to handle this better! */
+      return;
+    }
+    crs->payment_order_id = GNUNET_strdup (&m[strlen ("/-/-/")]);
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Order ID from Anastasis service is `%s'\n",
+                pss->payment_order_id);
+  }
+
+
   FILE *file;
   crs->code = malloc (sizeof(char) * 22);
   file = fopen (response_string, "r");
@@ -135,6 +196,10 @@ challenge_run_create_traits (void *cls,
   struct TALER_TESTING_Trait traits[] = {
     ANASTASIS_TESTING_make_trait_code (0,
                                        crs->code),
+    TALER_TESTING_make_trait_claim_token (0,
+                                          &pss->token),
+    TALER_TESTING_make_trait_order_id (0,
+                                       pss->payment_order_id),
     TALER_TESTING_trait_end ()
   };
 
diff --git a/src/lib/testing_api_cmd_keyshare_lookup.c 
b/src/lib/testing_api_cmd_keyshare_lookup.c
index a2d5574..dcd7796 100644
--- a/src/lib/testing_api_cmd_keyshare_lookup.c
+++ b/src/lib/testing_api_cmd_keyshare_lookup.c
@@ -76,6 +76,16 @@ struct KeyShareLookupState
    * Mode for the lookup(0 = question, 1 = code based)
    */
   int lookup_mode;
+  /**
+   * Payment secret used for the payment
+   */
+  const struct ANASTASIS_PaymentSecretP payment_secret;
+
+  /**
+   * if payment is needed or free
+   */
+  int payment_requested;
+
 };
 
 /**
@@ -198,6 +208,8 @@ keyshare_lookup_run (void *cls,
                                           ksls->anastasis_url,
                                           ksls->truth_public_key,
                                           &ksls->truth_key,
+                                          ksls->payment_requested,
+                                          &ksls->payment_secret,
                                           ksls->answer,
                                           &keyshare_lookup_cb,
                                           ksls);
@@ -276,6 +288,9 @@ ANASTASIS_TESTING_cmd_keyshare_lookup (const char *label,
                                        char *answer,
                                        const struct
                                        ANASTASIS_CRYPTO_TruthKeyP key,
+                                       const struct
+                                       ANASTASIS_PaymentSecretP 
*payment_secret,
+                                       int payment_requested,
                                        const char *upload_ref,
                                        int lookup_mode)
 {
@@ -293,6 +308,8 @@ ANASTASIS_TESTING_cmd_keyshare_lookup (const char *label,
   ksls->http_status = http_status;
   ksls->anastasis_url = anastasis_url;
   ksls->upload_reference = upload_ref;
+  ksls->payment_secret = payment_secret;
+  ksls->payment_requested = payment_requested;
   ksls->answer = answer;
   ksls->truth_key = key;
   ksls->lookup_mode = lookup_mode;

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