gnunet-svn
[Top][All Lists]
Advanced

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

[taler-anastasis] branch master updated: reworked keyshare lookup


From: gnunet
Subject: [taler-anastasis] branch master updated: reworked keyshare lookup
Date: Mon, 19 Oct 2020 16:27:32 +0200

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 c991b80  reworked keyshare lookup
c991b80 is described below

commit c991b80f48d3922bbb23e343c33fa78570295641
Author: Dominik Meister <dominik.meister@hotmail.ch>
AuthorDate: Mon Oct 19 16:27:22 2020 +0200

    reworked keyshare lookup
---
 src/include/anastasis_service.h                    |  47 ++++
 src/include/anastasis_testing_lib.h                |  19 +-
 src/lib/Makefile.am                                |   2 +
 ...hare_lookup.c => anastasis_api_challenge_run.c} | 146 +++++--------
 src/lib/anastasis_api_keyshare_lookup.c            |   5 +-
 src/lib/test_anastasis_api.c                       |   7 +
 src/lib/testing_api_cmd_challenge_run.c            | 239 +++++++++++++++++++++
 7 files changed, 375 insertions(+), 90 deletions(-)

diff --git a/src/include/anastasis_service.h b/src/include/anastasis_service.h
index 30b5b86..9bcb028 100644
--- a/src/include/anastasis_service.h
+++ b/src/include/anastasis_service.h
@@ -451,6 +451,53 @@ ANASTASIS_policy_store_cancel (
 
 /****** TRUTH API ******/
 
+/**
+ * Handle for a GET /truth which starts a challenge.
+ */
+struct ANASTASIS_ChallengeRunOperation;
+
+/**
+ * Callback to process a GET /truth request
+ *
+ * @param cls closure
+ * @param http_status HTTP status code for this request
+ * @param ec anastasis-specific error code
+ * @param obj the response body
+ */
+typedef void
+(*ANASTASIS_ChallengeRunCallback) (
+  void *cls,
+  unsigned int http_status);
+
+/**
+ * Cancel a GET /truth request.
+ *
+ * @param tlo cancel the truth lookup operation
+*/
+void
+ANASTASIS_challenge_run_cancel (
+  struct ANASTASIS_ChallengeRunOperation *cro);
+
+/**
+ * Does a GET /truth to start a challenge (not question)
+ *
+ * @param ctx execution context
+ * @param backend_url base URL of the backend
+ * @param truth_public_key identification of the Truth
+ * @param truth_key Key used to Decrypt the Truth on the Server
+ * @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_ChallengeRunOperation *
+ANASTASIS_challenge_run (
+  struct GNUNET_CURL_Context *ctx,
+  const char *backend_url,
+  const struct ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
+  const struct ANASTASIS_CRYPTO_TruthKeyP *truth_key,
+  ANASTASIS_ChallengeRunCallback cb,
+  void *cb_cls);
+
 /**
  * Handle for a GET /truth operation.
  */
diff --git a/src/include/anastasis_testing_lib.h 
b/src/include/anastasis_testing_lib.h
index 8591cd8..6eb1926 100644
--- a/src/include/anastasis_testing_lib.h
+++ b/src/include/anastasis_testing_lib.h
@@ -421,7 +421,24 @@ ANASTASIS_TESTING_cmd_keyshare_lookup (const char *label,
                                        const struct
                                        ANASTASIS_CRYPTO_TruthKeyP key,
                                        const char *upload_ref);
-
+/**
+ * Make the "challenge run" command.
+ *
+ * @param label command label
+ * @param anastasis_url base URL of the ANASTASIS serving
+ *        the challenge run request.
+ * @param http_status expected HTTP status.
+ * @param key key to decrypt truth
+ * @param upload_ref reference to upload command
+ * @return the command
+ */
+struct TALER_TESTING_Command
+ANASTASIS_TESTING_cmd_challenge_run (const char *label,
+                                     const char *anastasis_url,
+                                     unsigned int http_status,
+                                     const struct
+                                     ANASTASIS_CRYPTO_TruthKeyP key,
+                                     const char *upload_ref);
 
 /**
  * Obtain a salt from @a cmd.
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 2b93137..7c2d0c6 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -24,6 +24,7 @@ libanastasisrest_la_SOURCES = \
   anastasis_api_truth_store.c \
   anastasis_api_policy_lookup.c \
   anastasis_api_keyshare_lookup.c \
+  anastasis_api_challenge_run.c \
   anastasis_api_curl_defaults.c anastasis_api_curl_defaults.h
 libanastasisrest_la_LIBADD = \
   -lgnunetcurl \
@@ -64,6 +65,7 @@ libanastasistesting_la_SOURCES = \
   testing_api_cmd_truth_store.c \
   testing_api_cmd_policy_lookup.c \
   testing_api_cmd_keyshare_lookup.c \
+  testing_api_cmd_challenge_run.c \
   testing_api_cmd_salt.c \
   testing_api_helpers.c \
   testing_api_trait_account_pub.c \
diff --git a/src/lib/anastasis_api_keyshare_lookup.c 
b/src/lib/anastasis_api_challenge_run.c
similarity index 64%
copy from src/lib/anastasis_api_keyshare_lookup.c
copy to src/lib/anastasis_api_challenge_run.c
index e1ec1a4..7d989f4 100644
--- a/src/lib/anastasis_api_keyshare_lookup.c
+++ b/src/lib/anastasis_api_challenge_run.c
@@ -14,8 +14,8 @@
   Anastasis; see the file COPYING.GPL.  If not, see 
<http://www.gnu.org/licenses/>
 */
 /**
- * @file lib/anastasis_api_policy_lookup.c
- * @brief Implementation of the /policy GET
+ * @file lib/anastasis_api_challenge_run.c
+ * @brief Implementation of the /truth GET
  * @author Christian Grothoff
  * @author Dennis Neufeld
  * @author Dominik Meister
@@ -37,7 +37,7 @@
 /**
  * @brief A Contract Operation Handle
  */
-struct ANASTASIS_KeyShareLookupOperation
+struct ANASTASIS_ChallengeRunOperation
 {
   /**
    * The url for this request, including parameters.
@@ -52,7 +52,7 @@ struct ANASTASIS_KeyShareLookupOperation
   /**
    * Function to call with the result.
    */
-  ANASTASIS_KeyShareLookupCallback cb;
+  ANASTASIS_ChallengeRunCallback cb;
 
   /**
    * Closure for @a cb.
@@ -73,11 +73,6 @@ struct ANASTASIS_KeyShareLookupOperation
    * Key to decrypt the truth on the server
    */
   const struct ANASTASIS_CRYPTO_TruthKeyP *truth_key;
-
-  /**
-   * Hash of the response (security question)
-   */
-  const struct GNUNET_HashCode *hashed_answer;
 };
 
 
@@ -87,16 +82,16 @@ struct ANASTASIS_KeyShareLookupOperation
  * @param handle from the operation to cancel
  */
 void
-ANASTASIS_keyshare_lookup_cancel (struct
-                                  ANASTASIS_KeyShareLookupOperation *kslo)
+ANASTASIS_challenge_run_cancel (
+  struct ANASTASIS_ChallengeRunOperation *cro)
 {
-  if (NULL != kslo->job)
+  if (NULL != cro->job)
   {
-    GNUNET_CURL_job_cancel (kslo->job);
-    kslo->job = NULL;
+    GNUNET_CURL_job_cancel (cro->job);
+    cro->job = NULL;
   }
-  GNUNET_free (kslo->url);
-  GNUNET_free (kslo);
+  GNUNET_free (cro->url);
+  GNUNET_free (cro);
 }
 
 
@@ -104,14 +99,14 @@ ANASTASIS_keyshare_lookup_cancel (struct
  * Process GET /truth response
  */
 static void
-handle_keyshare_lookup_finished (void *cls,
-                                 long response_code,
-                                 const void *data,
-                                 size_t data_size)
+handle_challenge_run_finished (void *cls,
+                               long response_code,
+                               const void *data,
+                               size_t data_size)
 {
-  struct ANASTASIS_KeyShareLookupOperation *kslo = cls;
+  struct ANASTASIS_ChallengeRunOperation *cro = cls;
 
-  kslo->job = NULL;
+  cro->job = NULL;
   switch (response_code)
   {
   case 0:
@@ -122,17 +117,8 @@ handle_keyshare_lookup_finished (void *cls,
 
   case MHD_HTTP_OK:
     {
-      struct ANASTASIS_KeyShareDownloadDetails kdd;
-
-      /* Success, call callback with all details! */
-      memset (&kdd, 0, sizeof (kdd));
-      kdd.encrypted_key_share = data;
-      kdd.encrypted_keyshare_size = data_size;
-      kslo->cb (kslo->cb_cls,
-                (unsigned int) response_code,
-                &kdd);
-      kslo->cb = NULL;
-      ANASTASIS_keyshare_lookup_cancel (kslo);
+      cro->cb = NULL;
+      ANASTASIS_challenge_run_cancel (cro);
       return;
     }
   case MHD_HTTP_BAD_REQUEST:
@@ -155,14 +141,13 @@ handle_keyshare_lookup_finished (void *cls,
     response_code = 0;
     break;
   }
-  if (NULL != kslo->cb)
+  if (NULL != cro->cb)
   {
-    kslo->cb (kslo->cb_cls,
-              response_code,
-              NULL);
-    kslo->cb = NULL;
+    cro->cb (cro->cb_cls,
+             response_code);
+    cro->cb = NULL;
   }
-  ANASTASIS_keyshare_lookup_cancel (kslo);
+  ANASTASIS_challenge_run_cancel (cro);
 }
 
 
@@ -181,7 +166,7 @@ handle_header (char *buffer,
                size_t nitems,
                void *userdata)
 {
-  struct ANASTASIS_KeyShareLookupOperation *kslo = userdata;
+  struct ANASTASIS_ChallengeRunOperation *cro = userdata;
   size_t total = size * nitems;
   char *ndup;
   const char *hdr_type;
@@ -214,7 +199,7 @@ handle_header (char *buffer,
     if (GNUNET_OK !=
         GNUNET_STRINGS_string_to_data (hdr_val,
                                        strlen (hdr_val),
-                                       &kslo->truth_key,
+                                       &cro->truth_key,
                                        sizeof (struct
                                                ANASTASIS_CRYPTO_TruthKeyP)))
     {
@@ -229,29 +214,26 @@ handle_header (char *buffer,
 
 
 /**
- * Does a GET /truth.
+ * Does a GET /truth to start a challenge (non question challenges).
  *
  * @param ctx execution context
- * @param backend_url base URL of the merchant backend
+ * @param backend_url base URL of the 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)
- * @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)
+struct ANASTASIS_ChallengeRunOperation *
+ANASTASIS_challenge_run (
+  struct GNUNET_CURL_Context *ctx,
+  const char *backend_url,
+  const struct ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
+  const struct ANASTASIS_CRYPTO_TruthKeyP *truth_key,
+  ANASTASIS_ChallengeRunCallback cb,
+  void *cb_cls)
 {
-  struct ANASTASIS_KeyShareLookupOperation *kslo;
+  struct ANASTASIS_ChallengeRunOperation *cro;
   CURL *eh;
   struct curl_slist *job_headers;
   char *path;
@@ -280,55 +262,45 @@ ANASTASIS_keyshare_lookup (struct GNUNET_CURL_Context 
*ctx,
     }
     job_headers = ext;
   }
-  kslo = GNUNET_new (struct ANASTASIS_KeyShareLookupOperation);
-  kslo->ctx = ctx;
-  /** FIXME duplicate? see line 323
-  kslo->cb = cb;
-  kslo->cb_cls = cb_cls;
-  */
-  kslo->truth_key = truth_key;
+  cro = GNUNET_new (struct ANASTASIS_ChallengeRunOperation);
+  cro->ctx = ctx;
+  cro->truth_key = truth_key;
   char *pub_key_str;
 
   pub_key_str = GNUNET_STRINGS_data_to_string_alloc (truth_public_key,
                                                      sizeof 
(*truth_public_key));
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "truth public key in keyshare lookup:  %s\n",
+              "truth public key in challenge run:  %s\n",
               pub_key_str);
-  /*FIXME */
-
 
-  GNUNET_assert (NULL != answer);
   GNUNET_asprintf (&path,
                    "truth/%s",
                    pub_key_str);
-  // GNUNET_free (uuid_str);
-  kslo->url = TALER_url_join (backend_url,
-                              path,
-                              "response",
-                              answer,
-                              NULL);
+
+  cro->url = TALER_url_join (backend_url,
+                             path,
+                             NULL);
+
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Url get request (keyshare lookup): %s\n",
-              kslo->url);
-  eh = ANASTASIS_curl_easy_get_ (kslo->url);
+              "Url get request (challenge run): %s\n",
+              cro->url);
+  eh = ANASTASIS_curl_easy_get_ (cro->url);
   GNUNET_assert (CURLE_OK ==
                  curl_easy_setopt (eh,
                                    CURLOPT_HEADERFUNCTION,
                                    &handle_header));
   GNUNET_assert ((CURLE_OK == curl_easy_setopt (eh,
                                                 CURLOPT_HEADERDATA,
-                                                kslo)));
-  kslo->cb = cb;
-  kslo->cb_cls = cb_cls;
-  kslo->job = GNUNET_CURL_job_add_raw (ctx,
-                                       eh,
-                                       job_headers,
-                                       &handle_keyshare_lookup_finished,
-                                       kslo);
+                                                cro)));
+  cro->cb = cb;
+  cro->cb_cls = cb_cls;
+  cro->job = GNUNET_CURL_job_add_raw (ctx,
+                                      eh,
+                                      job_headers,
+                                      &handle_challenge_run_finished,
+                                      cro);
   GNUNET_free (path);
   curl_slist_free_all (job_headers);
-  return kslo;
+  return cro;
 }
-
-
-/* end of anastasis_api_keyshare_lookup.c */
+/* end of anastasis_api_challenge_run.c */
diff --git a/src/lib/anastasis_api_keyshare_lookup.c 
b/src/lib/anastasis_api_keyshare_lookup.c
index e1ec1a4..2666a06 100644
--- a/src/lib/anastasis_api_keyshare_lookup.c
+++ b/src/lib/anastasis_api_keyshare_lookup.c
@@ -297,16 +297,17 @@ ANASTASIS_keyshare_lookup (struct GNUNET_CURL_Context 
*ctx,
   /*FIXME */
 
 
-  GNUNET_assert (NULL != answer);
+
   GNUNET_asprintf (&path,
                    "truth/%s",
                    pub_key_str);
-  // GNUNET_free (uuid_str);
+
   kslo->url = TALER_url_join (backend_url,
                               path,
                               "response",
                               answer,
                               NULL);
+
   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 2562ab3..6226646 100644
--- a/src/lib/test_anastasis_api.c
+++ b/src/lib/test_anastasis_api.c
@@ -280,6 +280,13 @@ run (void *cls,
                                          ANASTASIS_TESTING_make_truthkey (
                                            "Truth-Key"))),
 
+    ANASTASIS_TESTING_cmd_challenge_run ("challenge-run-1",
+                                         anastasis_url,
+                                         MHD_HTTP_NO_CONTENT,
+                                         ANASTASIS_TESTING_make_truthkey (
+                                           "Truth-Key"),
+                                         "truth-store-2"),
+
     ANASTASIS_TESTING_cmd_keyshare_lookup ("keyshare-lookup-2",
                                            anastasis_url,
                                            MHD_HTTP_OK,
diff --git a/src/lib/testing_api_cmd_challenge_run.c 
b/src/lib/testing_api_cmd_challenge_run.c
new file mode 100644
index 0000000..defa013
--- /dev/null
+++ b/src/lib/testing_api_cmd_challenge_run.c
@@ -0,0 +1,239 @@
+/*
+  This file is part of Anastasis
+  Copyright (C) 2020 Taler Systems SA
+
+  Anastasis is free software; you can redistribute it and/or modify it under 
the
+  terms of the GNU Lesser General Public License as published by the Free 
Software
+  Foundation; either version 3, or (at your option) any later version.
+
+  Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along with
+  Anastasis; see the file COPYING.GPL.  If not, see 
<http://www.gnu.org/licenses/>
+*/
+/**
+ * @file lib/testing_api_cmd_challenge_run.c
+ * @brief Testing of Implementation of the /truth GET
+ * @author Christian Grothoff
+ * @author Dennis Neufeld
+ * @author Dominik Meister
+ */
+
+#include "platform.h"
+#include "anastasis_testing_lib.h"
+#include <taler/taler_util.h>
+#include <taler/taler_testing_lib.h>
+
+
+/**
+ * State for a "Challenge run state" CMD.
+ */
+struct ChallengeRunState
+{
+  /**
+   * The interpreter state.
+   */
+  struct TALER_TESTING_Interpreter *is;
+
+  /**
+   * URL of the anastasis backend.
+   */
+  const char *anastasis_url;
+
+  /**
+   * Expected status code.
+   */
+  unsigned int http_status;
+
+  /**
+   * The /truth GET operation handle.
+   */
+  struct ANASTASIS_ChallengeRunOperation *cro;
+
+  /**
+   * Key to decrypt truth
+   */
+  struct ANASTASIS_CRYPTO_TruthKeyP truth_key;
+
+  /**
+   * Identification of the Truth Object
+   */
+  const struct ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key;
+
+  /**
+   * Reference to upload command we expect to lookup.
+   */
+  const char *upload_reference;
+};
+
+/**
+ * Function called with the results of a #ANASTASIS_challenge_run().
+ *
+ * @param cls closure
+ * @param http_status HTTP status of the request
+ */
+static void
+challenge_run_cb (void *cls,
+                  unsigned int http_status)
+{
+  struct ChallengeRunState *crs = cls;
+
+  crs->cro = NULL;
+  if (http_status != crs->http_status)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unexpected response code %u to command %s in %s:%u\n",
+                http_status,
+                crs->is->commands[crs->is->ip].label,
+                __FILE__,
+                __LINE__);
+    TALER_TESTING_interpreter_fail (crs->is);
+    return;
+  }
+  TALER_TESTING_interpreter_next (crs->is);
+}
+
+
+/**
+ * Run a "challenge run" CMD.
+ *
+ * @param cls closure.
+ * @param cmd command currently being run.
+ * @param is interpreter state.
+ */
+static void
+challenge_run (void *cls,
+               const struct TALER_TESTING_Command *cmd,
+               struct TALER_TESTING_Interpreter *is)
+{
+  struct ChallengeRunState *crs = cls;
+
+  crs->is = is;
+  if (NULL != crs->upload_reference)
+  {
+    const struct TALER_TESTING_Command *upload_cmd;
+
+    upload_cmd = TALER_TESTING_interpreter_lookup_command
+                   (is,
+                   crs->upload_reference);
+    if (NULL == upload_cmd)
+    {
+      GNUNET_break (0);
+      TALER_TESTING_interpreter_fail (crs->is);
+      return;
+    }
+    {
+      if (GNUNET_OK !=
+          ANASTASIS_TESTING_get_trait_truth_public_key (upload_cmd,
+                                                        0,
+                                                        
&crs->truth_public_key))
+      {
+        GNUNET_break (0);
+        TALER_TESTING_interpreter_fail (crs->is);
+        return;
+      }
+      if (NULL == crs->truth_public_key)
+      {
+        GNUNET_break (0);
+        TALER_TESTING_interpreter_fail (crs->is);
+        return;
+      }
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Truth public key from trait: %s\n",
+                  TALER_B2S (crs->truth_public_key));
+    }
+  }
+
+  char *pub_key_str;
+  pub_key_str = GNUNET_STRINGS_data_to_string_alloc (crs->truth_public_key,
+                                                     sizeof (*crs->
+                                                             
truth_public_key));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "truth public key in challenge run testing cmd:  %s\n",
+              pub_key_str);
+
+  crs->cro = ANASTASIS_challenge_run (is->ctx,
+                                      crs->anastasis_url,
+                                      crs->truth_public_key,
+                                      &crs->truth_key,
+                                      &challenge_run_cb,
+                                      crs);
+  if (NULL == crs->cro)
+  {
+    GNUNET_break (0);
+    TALER_TESTING_interpreter_fail (crs->is);
+    return;
+  }
+}
+
+
+/**
+ * Free the state of a "keyshare lookup" CMD, and possibly
+ * cancel it if it did not complete.
+ *
+ * @param cls closure.
+ * @param cmd command being freed.
+ */
+static void
+challenge_run_cleanup (void *cls,
+                       const struct TALER_TESTING_Command *cmd)
+{
+  struct ChallengeRunState *crs = cls;
+
+  if (NULL != crs->cro)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Command '%s' did not complete (challenge run)\n",
+                cmd->label);
+    ANASTASIS_challenge_run_cancel (crs->cro);
+    crs->cro = NULL;
+  }
+  GNUNET_free (crs);
+}
+
+/**
+ * Make the "challenge run" command.
+ *
+ * @param label command label
+ * @param anastasis_url base URL of the ANASTASIS serving
+ *        the keyshare lookup request.
+ * @param http_status expected HTTP status.
+ * @param key key to decrypt truth
+ * @param upload_ref reference to upload command
+ * @return the command
+ */
+struct TALER_TESTING_Command
+ANASTASIS_TESTING_cmd_challenge_run
+  (const char *label,
+  const char *anastasis_url,
+  unsigned int http_status,
+  const struct ANASTASIS_CRYPTO_TruthKeyP key,
+  const char *upload_ref)
+{
+  struct ChallengeRunState *crs;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "TruthKey in keyshare lookup cmd: %s\n",
+              TALER_B2S (&key));
+
+  GNUNET_assert (NULL != upload_ref);
+  crs = GNUNET_new (struct ChallengeRunState);
+  crs->http_status = http_status;
+  crs->anastasis_url = anastasis_url;
+  crs->upload_reference = upload_ref;
+  crs->truth_key = key;
+  {
+    struct TALER_TESTING_Command cmd = {
+      .cls = crs,
+      .label = label,
+      .run = &challenge_run,
+      .cleanup = &challenge_run_cleanup
+    };
+    return cmd;
+  }
+}
+
+
+/* end of testing_api_cmd_keyshare_lookup.c */

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