gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated: -fix kycaid logic issues


From: gnunet
Subject: [taler-exchange] branch master updated: -fix kycaid logic issues
Date: Wed, 17 Aug 2022 14:36:18 +0200

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

grothoff pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new b2a67fcf -fix kycaid logic issues
b2a67fcf is described below

commit b2a67fcff9b5a7e056b2acd6a3a8343365ab35c0
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Wed Aug 17 14:36:16 2022 +0200

    -fix kycaid logic issues
---
 src/kyclogic/kyclogic_api.c              |   3 +
 src/kyclogic/plugin_kyclogic_kycaid.c    | 110 ++++++++++++++++++++++++-------
 src/kyclogic/taler-exchange-kyc-tester.c |  47 +++++++++----
 3 files changed, 123 insertions(+), 37 deletions(-)

diff --git a/src/kyclogic/kyclogic_api.c b/src/kyclogic/kyclogic_api.c
index 2b4ce0d3..18707a18 100644
--- a/src/kyclogic/kyclogic_api.c
+++ b/src/kyclogic/kyclogic_api.c
@@ -748,6 +748,9 @@ TALER_KYCLOGIC_kyc_done (void)
   {
     struct TALER_KYCLOGIC_KycCheck *kc = kyc_checks[i];
 
+    GNUNET_array_grow (kc->providers,
+                       kc->num_providers,
+                       0);
     GNUNET_free (kc->name);
     GNUNET_free (kc);
   }
diff --git a/src/kyclogic/plugin_kyclogic_kycaid.c 
b/src/kyclogic/plugin_kyclogic_kycaid.c
index 933c0d35..449dac51 100644
--- a/src/kyclogic/plugin_kyclogic_kycaid.c
+++ b/src/kyclogic/plugin_kyclogic_kycaid.c
@@ -720,10 +720,54 @@ kycaid_webhook_cancel (struct 
TALER_KYCLOGIC_WebhookHandle *wh)
   }
   GNUNET_free (wh->verification_id);
   GNUNET_free (wh->applicant_id);
+  GNUNET_free (wh->url);
   GNUNET_free (wh);
 }
 
 
+/**
+ * Extract KYC failure reasons and log those
+ *
+ * @param verifications JSON object with failure details
+ */
+static void
+log_failure (json_t *verifications)
+{
+  json_t *member;
+  const char *name;
+  json_object_foreach (verifications, name, member)
+  {
+    bool iverified;
+    const char *comment;
+    struct GNUNET_JSON_Specification spec[] = {
+      GNUNET_JSON_spec_bool ("verified",
+                             &iverified),
+      GNUNET_JSON_spec_string ("comment",
+                               &comment),
+      GNUNET_JSON_spec_end ()
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_JSON_parse (member,
+                           spec,
+                           NULL, NULL))
+    {
+      GNUNET_break_op (0);
+      json_dumpf (member,
+                  stderr,
+                  JSON_INDENT (2));
+      continue;
+    }
+    if (iverified)
+      continue;
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "KYC verification of attribute `%s' failed: %s\n",
+                name,
+                comment);
+  }
+}
+
+
 /**
  * Function called when we're done processing the
  * HTTP "/verifications/{verification_id}" request.
@@ -749,7 +793,6 @@ handle_webhook_finished (void *cls,
       const char *applicant_id;
       const char *verification_id;
       const char *status;
-      const char *type;
       bool verified;
       json_t *verifications;
       struct GNUNET_JSON_Specification spec[] = {
@@ -757,10 +800,8 @@ handle_webhook_finished (void *cls,
                                  &applicant_id),
         GNUNET_JSON_spec_string ("verification_id",
                                  &verification_id),
-        GNUNET_JSON_spec_string ("type",
-                                 &type),
         GNUNET_JSON_spec_string ("status",
-                                 &status),
+                                 &status), /* completed, pending, ... */
         GNUNET_JSON_spec_bool ("verified",
                                &verified),
         GNUNET_JSON_spec_json ("verifications",
@@ -794,12 +835,10 @@ handle_webhook_finished (void *cls,
                 resp);
         break;
       }
-      /* FIXME: comment out, unless debugging ... */
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "The provider returned the following verifications:\n");
-      json_dumpf (verifications,
-                  stderr,
-                  JSON_INDENT (2));
+      if (! verified)
+      {
+        log_failure (verifications);
+      }
       resp = MHD_create_response_from_buffer (0,
                                               "",
                                               MHD_RESPMEM_PERSISTENT);
@@ -980,11 +1019,15 @@ async_webhook_reply (void *cls)
 {
   struct TALER_KYCLOGIC_WebhookHandle *wh = cls;
 
+  fprintf (stderr,
+           "async reply\n");
   wh->cb (wh->cb_cls,
-          0LLU, /* legitimization row ID (unknown) */
-          NULL, /* our account ID */
-          NULL, /* provider user ID */
-          NULL, /* provider legi ID */
+          wh->legi_row,
+          (0 == wh->legi_row)
+          ? NULL
+          : &wh->h_payto,
+          wh->applicant_id, /* provider user ID */
+          wh->verification_id, /* provider legi ID */
           TALER_KYCLOGIC_STATUS_PROVIDER_FAILED,
           GNUNET_TIME_UNIT_ZERO_ABS, /* expiration */
           wh->response_code,
@@ -994,7 +1037,11 @@ async_webhook_reply (void *cls)
 
 
 /**
- * Check KYC status and return result for Webhook.
+ * Check KYC status and return result for Webhook.  We do NOT implement the
+ * authentication check proposed by the KYCAID documentation, as it would
+ * allow an attacker who learns the access token to easily bypass the KYC
+ * checks. Instead, we insist on explicitly requesting the KYC status from the
+ * provider (at least on success).
  *
  * @param cls the @e cls of this struct with the plugin-specific state
  * @param pd provider configuration details
@@ -1085,6 +1132,7 @@ kycaid_webhook (void *cls,
     wh->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
     wh->task = GNUNET_SCHEDULER_add_now (&async_webhook_reply,
                                          wh);
+    GNUNET_JSON_parse_free (spec);
     return wh;
   }
   if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
@@ -1098,10 +1146,25 @@ kycaid_webhook (void *cls,
     wh->response_code = MHD_HTTP_NOT_FOUND;
     wh->task = GNUNET_SCHEDULER_add_now (&async_webhook_reply,
                                          wh);
+    GNUNET_JSON_parse_free (spec);
     return wh;
   }
   wh->verification_id = GNUNET_strdup (verification_id);
   wh->applicant_id = GNUNET_strdup (applicant_id);
+  if (! verified)
+  {
+    /* We don't need to re-confirm the failure by
+       asking the API again. */
+    log_failure (verifications);
+    wh->response_code = MHD_HTTP_NO_CONTENT;
+    wh->resp = MHD_create_response_from_buffer (0,
+                                                "",
+                                                MHD_RESPMEM_PERSISTENT);
+    wh->task = GNUNET_SCHEDULER_add_now (&async_webhook_reply,
+                                         wh);
+    GNUNET_JSON_parse_free (spec);
+    return wh;
+  }
 
   eh = curl_easy_init ();
   if (NULL == eh)
@@ -1113,6 +1176,7 @@ kycaid_webhook (void *cls,
     wh->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
     wh->task = GNUNET_SCHEDULER_add_now (&async_webhook_reply,
                                          wh);
+    GNUNET_JSON_parse_free (spec);
     return wh;
   }
 
@@ -1122,7 +1186,7 @@ kycaid_webhook (void *cls,
   GNUNET_break (CURLE_OK ==
                 curl_easy_setopt (eh,
                                   CURLOPT_VERBOSE,
-                                  1));
+                                  0));
   GNUNET_assert (CURLE_OK ==
                  curl_easy_setopt (eh,
                                    CURLOPT_MAXREDIRS,
@@ -1131,18 +1195,18 @@ kycaid_webhook (void *cls,
                 curl_easy_setopt (eh,
                                   CURLOPT_URL,
                                   wh->url));
-  wh->job = GNUNET_CURL_job_add (ps->curl_ctx,
-                                 eh,
-                                 &handle_webhook_finished,
-                                 wh);
-  GNUNET_CURL_extend_headers (wh->job,
-                              pd->slist);
+  wh->job = GNUNET_CURL_job_add2 (ps->curl_ctx,
+                                  eh,
+                                  pd->slist,
+                                  &handle_webhook_finished,
+                                  wh);
+  GNUNET_JSON_parse_free (spec);
   return wh;
 }
 
 
 /**
- * Initialize Kycaid.0 KYC logic plugin
+ * Initialize kycaid logic plugin
  *
  * @param cls a configuration instance
  * @return NULL on error, otherwise a `struct TALER_KYCLOGIC_Plugin`
diff --git a/src/kyclogic/taler-exchange-kyc-tester.c 
b/src/kyclogic/taler-exchange-kyc-tester.c
index 2f3fa561..40aadba1 100644
--- a/src/kyclogic/taler-exchange-kyc-tester.c
+++ b/src/kyclogic/taler-exchange-kyc-tester.c
@@ -81,6 +81,11 @@ struct TEKT_RequestContext
    */
   void *rh_ctx;
 
+  /**
+   * Uploaded JSON body, if any.
+   */
+  json_t *root;
+
   /**
    * HTTP status to return upon resume if @e response
    * is non-NULL.
@@ -555,6 +560,8 @@ handler_kyc_webhook_generic (
                                          
TALER_EC_EXCHANGE_KYC_GENERIC_LOGIC_UNKNOWN,
                                          "$LOGIC");
     }
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Calling KYC provider specific webhook\n");
     kwh->wh = kwh->plugin->webhook (kwh->plugin->cls,
                                     kwh->pd,
                                     &kyc_provider_account_lookup,
@@ -583,6 +590,8 @@ handler_kyc_webhook_generic (
 
   if (NULL != kwh->response)
   {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Returning queued reply for KWH\n");
     /* handle _failed_ resumed cases */
     return MHD_queue_response (rc->connection,
                                kwh->response_code,
@@ -845,7 +854,6 @@ proceed_with_handler (struct TEKT_RequestContext *rc,
   const struct TEKT_RequestHandler *rh = rc->rh;
   const char *args[rh->nargs + 2];
   size_t ulen = strlen (url) + 1;
-  json_t *root = NULL;
   MHD_RESULT ret;
 
   /* We do check for "ulen" here, because we'll later stack-allocate a buffer
@@ -866,8 +874,9 @@ proceed_with_handler (struct TEKT_RequestContext *rc,
 
   /* All POST endpoints come with a body in JSON format. So we parse
      the JSON here. */
-  if (0 == strcasecmp (rh->method,
-                       MHD_HTTP_METHOD_POST))
+  if ( (NULL == rc->root) &&
+       (0 == strcasecmp (rh->method,
+                         MHD_HTTP_METHOD_POST)) )
   {
     enum GNUNET_GenericReturnValue res;
 
@@ -875,16 +884,17 @@ proceed_with_handler (struct TEKT_RequestContext *rc,
                                      &rc->opaque_post_parsing_context,
                                      upload_data,
                                      upload_data_size,
-                                     &root);
+                                     &rc->root);
     if (GNUNET_SYSERR == res)
     {
-      GNUNET_assert (NULL == root);
+      GNUNET_assert (NULL == rc->root);
+      GNUNET_break (0);
       return MHD_NO; /* bad upload, could not even generate error */
     }
     if ( (GNUNET_NO == res) ||
-         (NULL == root) )
+         (NULL == rc->root) )
     {
-      GNUNET_assert (NULL == root);
+      GNUNET_assert (NULL == rc->root);
       return MHD_YES; /* so far incomplete upload or parser error */
     }
   }
@@ -921,7 +931,6 @@ proceed_with_handler (struct TEKT_RequestContext *rc,
                        rh->url,
                        url);
       GNUNET_break_op (0);
-      json_decref (root);
       return TALER_MHD_reply_with_error (rc->connection,
                                          MHD_HTTP_NOT_FOUND,
                                          
TALER_EC_EXCHANGE_GENERIC_WRONG_NUMBER_OF_SEGMENTS,
@@ -931,16 +940,15 @@ proceed_with_handler (struct TEKT_RequestContext *rc,
 
     /* Above logic ensures that 'root' is exactly non-NULL for POST operations,
        so we test for 'root' to decide which handler to invoke. */
-    if (NULL != root)
+    if (NULL != rc->root)
       ret = rh->handler.post (rc,
-                              root,
+                              rc->root,
                               args);
     else /* We also only have "POST" or "GET" in the API for at this point
       (OPTIONS/HEAD are taken care of earlier) */
       ret = rh->handler.get (rc,
                              args);
   }
-  json_decref (root);
   return ret;
 }
 
@@ -949,8 +957,15 @@ static void
 rh_cleaner_cb (struct TEKT_RequestContext *rc)
 {
   if (NULL != rc->response)
+  {
     MHD_destroy_response (rc->response);
-  GNUNET_free (rc);
+    rc->response = NULL;
+  }
+  if (NULL != rc->root)
+  {
+    json_decref (rc->root);
+    rc->root = NULL;
+  }
 }
 
 
@@ -1082,7 +1097,8 @@ handle_mhd_request (void *cls,
         continue;
       found = true;
       /* The URL is a match!  What we now do depends on the method. */
-      if (0 == strcasecmp (method, MHD_HTTP_METHOD_OPTIONS))
+      if (0 == strcasecmp (method,
+                           MHD_HTTP_METHOD_OPTIONS))
       {
         return TALER_MHD_reply_cors_preflight (connection);
       }
@@ -1276,7 +1292,7 @@ initiate_cb (
     return;
   }
   fprintf (stdout,
-           "Visit `%s' to begin KYC process (-u: '%s', -l: '%s')\n",
+           "Visit `%s' to begin KYC process (-u: '%s', -U: '%s')\n",
            redirect_url,
            provider_user_id,
            provider_legitimization_id);
@@ -1393,6 +1409,9 @@ run (void *cls,
       GNUNET_SCHEDULER_shutdown ();
       return;
     }
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Starting daemon on port %u\n",
+                (unsigned int) serve_port);
     mhd = MHD_start_daemon (MHD_USE_SUSPEND_RESUME
                             | MHD_USE_PIPE_FOR_SHUTDOWN
                             | MHD_USE_DEBUG | MHD_USE_DUAL_STACK

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