gnunet-svn
[Top][All Lists]
Advanced

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

[taler-challenger] branch master updated: work on challenger


From: gnunet
Subject: [taler-challenger] branch master updated: work on challenger
Date: Thu, 27 Apr 2023 11:38:13 +0200

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

grothoff pushed a commit to branch master
in repository challenger.

The following commit(s) were added to refs/heads/master by this push:
     new b8a0d6f  work on challenger
b8a0d6f is described below

commit b8a0d6f5602e0b019eddb706cf7306d1fb217022
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Thu Apr 27 11:38:08 2023 +0200

    work on challenger
---
 src/challenger/challenger-httpd_login.c            |  51 +++++-----
 src/challengerdb/Makefile.am                       |   7 +-
 .../pg_challenge_set_address_and_pin.c             | 103 +++++++++++++++++++++
 .../pg_challenge_set_address_and_pin.h             |  58 ++++++++++++
 src/challengerdb/pg_login_start.c                  |  73 +++++++++++++++
 src/challengerdb/pg_login_start.h                  |  60 ++++++++++++
 .../{pg_validation_setup.c => pg_setup_nonce.c}    |  10 +-
 .../{pg_validation_setup.h => pg_setup_nonce.h}    |  10 +-
 src/include/challenger_database_plugin.h           |  16 ++--
 9 files changed, 339 insertions(+), 49 deletions(-)

diff --git a/src/challenger/challenger-httpd_login.c 
b/src/challenger/challenger-httpd_login.c
index f8035f2..063546f 100644
--- a/src/challenger/challenger-httpd_login.c
+++ b/src/challenger/challenger-httpd_login.c
@@ -128,18 +128,18 @@ CH_handler_login (struct CH_HandlerContext *hc,
                                    "scope");
   (void) scope; /* ignored */
   {
-    struct GNUNET_TIME_Absolute last_tx_time;
-    uint32_t pin_attempts_left;
+    char *last_address;
+    uint32_t address_attempts_left;
     enum GNUNET_DB_QueryStatus qs;
-    struct GNUNET_TIME_Absolute next_tx_time;
 
-    qs = db->validate_login_start (db->cls,
-                                   &nonce,
-                                   client_scope,
-                                   client_state,
-                                   client_redirect_url,
-                                   &last_tx,
-                                   &pin_attempts_left);
+    qs = db->login_start (db->cls,
+                          &nonce,
+                          client_id,
+                          client_scope,
+                          client_state,
+                          client_redirect_url,
+                          &last_address,
+                          &address_attempts_left);
     switch (qs)
     {
     case GNUNET_DB_SUCCESS_HARD_ERROR:
@@ -160,30 +160,25 @@ CH_handler_login (struct CH_HandlerContext *hc,
     case GNUNET_DB_SUCCESS_ONE_RESULT:
       break;
     }
-    if (0 == pin_attempts_left)
-    {
-      /* FIXME: return human-readable HTML saying that they tried to often */
-      return TALER_MHD_reply_with_html (connection,
-                                        MHD_HTTP_FORBIDDEN,
-                                        "too-many-attempts.must",
-                                        NULL /* OK? or pass empty object? */);
-    }
-    next_tx_time = GNUNET_TIME_absolute_add (last_tx_time,
-                                             CH_pin_retransmission_frequency);
     {
       MHD_RESULT res;
       json_t *args;
 
       args = GNUNET_JSON_PACK (
-        GNUNET_JSON_pack_uint64 ("attempts_left",
-                                 pin_attempts_left),
-        GNUNET_JSON_pack_absolute_time ("next_tx_time",
-                                        next_tx_time),
+        GNUNET_JSON_pack_bool ("fix_address",
+                               0 == address_attempts_left),
+        GNUNET_JSON_pack_string ("last_address",
+                                 last_address),
+        GNUNET_JSON_pack_uint64 ("changes_left",
+                                 address_attempts_left),
         );
-      res = TALER_MHD_reply_with_html (hc->connection,
-                                       MHD_HTTP_OK,
-                                       "enter-address-form.must",
-                                       args);
+      res = TALER_MHD_reply_with_html (
+        hc->connection,
+        MHD_HTTP_OK,
+        "enter-address-form.must",
+
+        args);
+      json_decref (args);
       return res;
     }
   }
diff --git a/src/challengerdb/Makefile.am b/src/challengerdb/Makefile.am
index e36d5e5..d75b64b 100644
--- a/src/challengerdb/Makefile.am
+++ b/src/challengerdb/Makefile.am
@@ -60,10 +60,9 @@ libchallenger_plugin_db_postgres_la_SOURCES = \
   pg_client_add.h pg_client_add.c \
   pg_client_delete.h pg_client_delete.c \
   pg_client_check.h pg_client_check.c \
-  pg_validation_setup.h pg_validation_setup.c \
-  pg_validate_login_address.h pg_validate_login_address.c \
-  pg_validate_login_pin.h pg_validate_login_pin.c \
-  pg_validate_challenge_open.h pg_validate_challenge_open.c \
+  pg_setup_nonce.h pg_setup_nonce.c \
+  pg_login_start.h pg_login_start.c \
+  pg_challenge_set_address_and_pin.h pg_challenge_set_address_and_pin.c \
   pg_validate_solve_pin.h pg_validate_solve_pin.c \
   pg_validation_get.h pg_validation_get.c \
   plugin_challengerdb_postgres.c
diff --git a/src/challengerdb/pg_challenge_set_address_and_pin.c 
b/src/challengerdb/pg_challenge_set_address_and_pin.c
new file mode 100644
index 0000000..f30c5e9
--- /dev/null
+++ b/src/challengerdb/pg_challenge_set_address_and_pin.c
@@ -0,0 +1,103 @@
+/*
+   This file is part of Challenger
+   Copyright (C) 2023 Taler Systems SA
+
+   Challenger is free software; you can redistribute it and/or modify it under 
the
+   terms of the GNU General Public License as published by the Free Software
+   Foundation; either version 3, or (at your option) any later version.
+
+   Challenger 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
+   Challenger; see the file COPYING.  If not, see 
<http://www.gnu.org/licenses/>
+ */
+/**
+ * @file challengerdb/pg_challenge_set_address_and_pin.c
+ * @brief Implementation of the challenge_set_address_and_pin function for 
Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_challenge_set_address_and_pin.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+CH_PG_challenge_set_address_and_pin (
+  void *cls,
+  const struct CHALLENGER_ValidationNonceP *nonce,
+  const char *address,
+  struct GNUNET_TIME_Absolute next_tx_time,
+  struct GNUNET_TIME_Absolute *last_tx_time,
+  uint32_t *last_pin,
+  uint32_t *pin_transmissions_left)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (nonce),
+    GNUNET_PQ_query_param_string (address),
+    GNUNET_PQ_query_param_abs_time (&next_tx_time),
+    GNUNET_PQ_query_param_abs_time (last_tx_time),
+    GNUNET_PQ_query_param_uint32 (last_pin),
+    GNUNET_PQ_query_param_uint32 (pin_transmissions_left),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_absolute_time ("last_tx_time",
+                                         last_tx_time),
+    GNUNET_PQ_result_spec_uint32 ("last_pin",
+                                  last_pin),
+    GNUNET_PQ_result_spec_uint32 ("pin_attempts_left",
+                                  pin_attempts_left),
+    GNUNET_PQ_result_spec_end
+  };
+
+  // FIXME: review!!!
+  PREPARE (pg,
+           "challenge_set_address_and_pin",
+           "UPDATE validations SET"
+           "  address_attempts_left=CASE"
+           "    WHEN address != $2"
+           "    THEN address_attempts_left - 1"
+           "    ELSE address_attempts_left"
+           "  END"
+           " ,last_pin=CASE"
+           "    WHEN address != $2"
+           "    THEN $5"
+           "    ELSE last_pin"
+           " ,END"
+           " ,pin_transmissions_left=CASE"
+           "    WHEN address != $2"
+           "    THEN $6"
+           "    ELSE WHEN last_tx_time < 3"
+           "      THEN pin_transmissions_left - 1"
+           "      ELSE pin_transmissions_left"
+           "    END"
+           " ,END"
+           " ,last_tx_time=CASE"
+           "    WHEN last_tx_time < $3"
+           "    THEN $4"
+           "    ELSE last_tx_time"
+           "  END"
+           " ,address=$2"
+           " WHERE nonce=$1"
+           "   AND ( (address_attempts_left > 0)"
+           "      OR ( (address == $2) AND"
+           "           ( (pin_transmissions_left > 0) OR"
+           "             (last_tx_time >= $3) ) ) )"
+           " RETURNING"
+           "   last_tx_time"
+           "  ,(address != $2) OR"
+           "   ( (pin_transmissions_left > 0) AND"
+           "     (last_tx_time < $3) ) AS pin_transmit"
+           "  ,last_pin"
+           "  ,pin_attempts_left;");
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   
"challenge_set_address_and_pin",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/challengerdb/pg_challenge_set_address_and_pin.h 
b/src/challengerdb/pg_challenge_set_address_and_pin.h
new file mode 100644
index 0000000..206d07c
--- /dev/null
+++ b/src/challengerdb/pg_challenge_set_address_and_pin.h
@@ -0,0 +1,58 @@
+/*
+   This file is part of Challenger
+   Copyright (C) 2023 Taler Systems SA
+
+   Challenger is free software; you can redistribute it and/or modify it under 
the
+   terms of the GNU General Public License as published by the Free Software
+   Foundation; either version 3, or (at your option) any later version.
+
+   Challenger 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
+   Challenger; see the file COPYING.  If not, see 
<http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_challenge_set_address_and_pin.h
+ * @brief implementation of the challenge_set_address_and_pin function for 
Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_CHALLENGE_SET_ADDRESS_AND_PIN_H
+#define PG_CHALLENGE_SET_ADDRESS_AND_PIN_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "challenger_database_plugin.h"
+
+
+/**
+ * Set the user-provided address in a validation process. Updates
+ * the address and decrements the "addresses left" counter.  If the
+ * address did not change, the operation is successful even without
+ * the counter change.
+ *
+ * @param cls
+ * @param nonce unique nonce to use to identify the validation
+ * @param address the new address to validate
+ * @param next_tx_time tx time we must have sent earlier before to retransmit 
now
+ * @param[in,out] last_tx_time set to the last time when we (presumably) send 
a PIN to @a address, input should be current time to use if the existing value 
for tx_time is past @a next_tx_time
+ * @param[in,out] last_pin set to the PIN last send to @a address, input 
should be random PIN to use if address did not change
+ * @param[in,out] pin_transmissions_left set to number of PIN transmission 
attempts left for this address; input is value to be used if address is new, 
output is possibly different if address was not new
+ * @return transaction status:
+ *   #GNUNET_DB_SUCCESS_ONE_RESULT if the address was changed
+ *   #GNUNET_DB_SUCCESS_NO_RESULTS if we do not permit further changes to the 
address (attempts exhausted)
+ *   #GNUNET_DB_SUCCESS_HARD_ERROR on failure
+ */
+enum GNUNET_DB_QueryStatus
+CH_PG_challenge_set_address_and_pin (
+  void *cls,
+  const struct CHALLENGER_ValidationNonceP *nonce,
+  const char *address,
+  struct GNUNET_TIME_Absolute next_tx_time,
+  struct GNUNET_TIME_Absolute *last_tx_time,
+  uint32_t *last_pin,
+  uint32_t *pin_transmissions_left);
+
+
+#endif
diff --git a/src/challengerdb/pg_login_start.c 
b/src/challengerdb/pg_login_start.c
new file mode 100644
index 0000000..331536f
--- /dev/null
+++ b/src/challengerdb/pg_login_start.c
@@ -0,0 +1,73 @@
+/*
+   This file is part of Challenger
+   Copyright (C) 2023 Taler Systems SA
+
+   Challenger is free software; you can redistribute it and/or modify it under 
the
+   terms of the GNU General Public License as published by the Free Software
+   Foundation; either version 3, or (at your option) any later version.
+
+   Challenger 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
+   Challenger; see the file COPYING.  If not, see 
<http://www.gnu.org/licenses/>
+ */
+/**
+ * @file challengerdb/pg_login_start.c
+ * @brief Implementation of the login_start function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_login_start.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+CH_PG_login_start (void *cls,
+                   const struct CHALLENGER_ValidationNonceP *nonce,
+                   uint64_t client_id,
+                   const char *client_scope,
+                   const char *client_state,
+                   const char *client_redirect_url,
+                   char **last_address,
+                   uint32_t *address_attempts_left)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (nonce),
+    GNUNET_PQ_query_param_uint64 (&client_id),
+    GNUNET_PQ_query_param_string (client_scope),
+    GNUNET_PQ_query_param_string (client_state),
+    NULL != client_redirect_url
+    ? GNUNET_PQ_query_param_string (client_redirect_url)
+    : GNUNET_PQ_query_param_null (),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_string ("address",
+                                  last_address),
+    GNUNET_PQ_result_spec_uint32 ("address_attempts_left",
+                                  address_attempts_left),
+    GNUNET_PQ_result_spec_end
+  };
+
+  PREPARE (pg,
+           "login_start_validation",
+           "UPDATE validations SET"
+           "  client_scope=$3"
+           " ,client_state=$4"
+           " ,client_redirect_url=$5"
+           " WHERE nonce=$1"
+           "   AND client_id=$2"
+           " RETURNING"
+           "   address"
+           "  ,address_attempts_left;");
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "login_start_validation",
+                                                   params,
+                                                   rs);
+}
diff --git a/src/challengerdb/pg_login_start.h 
b/src/challengerdb/pg_login_start.h
new file mode 100644
index 0000000..e896569
--- /dev/null
+++ b/src/challengerdb/pg_login_start.h
@@ -0,0 +1,60 @@
+/*
+   This file is part of Challenger
+   Copyright (C) 2023 Taler Systems SA
+
+   Challenger is free software; you can redistribute it and/or modify it under 
the
+   terms of the GNU General Public License as published by the Free Software
+   Foundation; either version 3, or (at your option) any later version.
+
+   Challenger 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
+   Challenger; see the file COPYING.  If not, see 
<http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_login_start.h
+ * @brief implementation of the login_start function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_LOGIN_START_H
+#define PG_LOGIN_START_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "challenger_database_plugin.h"
+
+
+/**
+ * Set the user-provided address in a validation process. Updates
+ * the address and decrements the "addresses left" counter.  If the
+ * address did not change, the operation is successful even without
+ * the counter change.
+ *
+ * @param cls
+ * @param nonce unique nonce to use to identify the validation
+ * @param client_id client that initiated the validation
+ * @param client_scope scope of the validation
+ * @param client_state state of the client
+ * @param client_redirect_url where to redirect at the end, NULL to use a 
unique one registered for the client
+ * @param[out] last_address set to the last address used
+ * @param[out] address_attempts_left set to number of address changing 
attempts left for this address
+ * @return transaction status:
+ *   #GNUNET_DB_SUCCESS_ONE_RESULT if the address was changed
+ *   #GNUNET_DB_SUCCESS_NO_RESULTS if we do not permit further changes to the 
address (attempts exhausted)
+ *   #GNUNET_DB_SUCCESS_HARD_ERROR on failure
+ */
+enum GNUNET_DB_QueryStatus
+CH_PG_login_start (void *cls,
+                   const struct CHALLENGER_ValidationNonceP *nonce,
+                   uint64_t client_id,
+                   const char *client_scope,
+                   const char *client_state,
+                   const char *client_redirect_url,
+                   char **last_address,
+                   struct GNUNET_TIME_Absolute *last_tx_time,
+                   uint32_t *address_attempts_left);
+
+
+#endif
diff --git a/src/challengerdb/pg_validation_setup.c 
b/src/challengerdb/pg_setup_nonce.c
similarity index 86%
rename from src/challengerdb/pg_validation_setup.c
rename to src/challengerdb/pg_setup_nonce.c
index c4754a7..f387e53 100644
--- a/src/challengerdb/pg_validation_setup.c
+++ b/src/challengerdb/pg_setup_nonce.c
@@ -14,7 +14,7 @@
    Challenger; see the file COPYING.  If not, see 
<http://www.gnu.org/licenses/>
  */
 /**
- * @file challengerdb/pg_validation_setup.c
+ * @file challengerdb/pg_setup_nonce.c
  * @brief Implementation of the validation_setup function for Postgres
  * @author Christian Grothoff
  */
@@ -27,10 +27,10 @@
 
 
 enum GNUNET_DB_QueryStatus
-CH_PG_validation_setup (void *cls,
-                        uint64_t client_id,
-                        const struct CHALLENGER_ValidationNonceP *nonce,
-                        struct GNUNET_TIME_Absolute expiration_time)
+CH_PG_setup_nonce (void *cls,
+                   uint64_t client_id,
+                   const struct CHALLENGER_ValidationNonceP *nonce,
+                   struct GNUNET_TIME_Absolute expiration_time)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
diff --git a/src/challengerdb/pg_validation_setup.h 
b/src/challengerdb/pg_setup_nonce.h
similarity index 84%
rename from src/challengerdb/pg_validation_setup.h
rename to src/challengerdb/pg_setup_nonce.h
index 93110d8..31c3acf 100644
--- a/src/challengerdb/pg_validation_setup.h
+++ b/src/challengerdb/pg_setup_nonce.h
@@ -14,7 +14,7 @@
    Challenger; see the file COPYING.  If not, see 
<http://www.gnu.org/licenses/>
  */
 /**
- * @file backenddb/pg_validation_setup.h
+ * @file backenddb/pg_setup_nonce.h
  * @brief implementation of the validation_setup function for Postgres
  * @author Christian Grothoff
  */
@@ -37,9 +37,9 @@
  * @return transaction status
  */
 enum GNUNET_DB_QueryStatus
-CH_PG_validation_setup (void *cls,
-                        uint64_t client_id,
-                        const struct CHALLENGER_ValidationNonceP *nonce,
-                        struct GNUNET_TIME_Absolute expiration_time);
+CH_PG_setup_nonce (void *cls,
+                   uint64_t client_id,
+                   const struct CHALLENGER_ValidationNonceP *nonce,
+                   struct GNUNET_TIME_Absolute expiration_time);
 
 #endif
diff --git a/src/include/challenger_database_plugin.h 
b/src/include/challenger_database_plugin.h
index 8933427..a25b82c 100644
--- a/src/include/challenger_database_plugin.h
+++ b/src/include/challenger_database_plugin.h
@@ -213,11 +213,12 @@ struct CHALLENGER_DatabasePlugin
    *
    * @param cls
    * @param nonce unique nonce to use to identify the validation
+   * @param client_id client that initiated the validation
    * @param client_scope scope of the validation
    * @param client_state state of the client
    * @param client_redirect_url where to redirect at the end, NULL to use a 
unique one registered for the client
-   * @param[out] last_tx_time set to the last time when we (presumably) send a 
PIN to @a address; 0 if never sent
-   * @param[out] pin_attempts_left set to number of PIN transmission attempts 
left for this address; input is value to be used if address is new, output is 
possibly different if address was not new
+   * @param[out] last_address set to the last address used
+   * @param[out] address_attempts_left set to number change address operations 
left for this @a nonce
    * @return transaction status:
    *   #GNUNET_DB_SUCCESS_ONE_RESULT if the address was changed
    *   #GNUNET_DB_SUCCESS_NO_RESULTS if we do not permit further changes to 
the address (attempts exhausted)
@@ -226,11 +227,12 @@ struct CHALLENGER_DatabasePlugin
   enum GNUNET_DB_QueryStatus
   (*login_start)(void *cls,
                  const struct CHALLENGER_ValidationNonceP *nonce,
+                 uint64_t client_id,
                  const char *client_scope,
                  const char *client_state,
                  const char *client_redirect_url,
-                 struct GNUNET_TIME_Absolute *last_tx_time,
-                 uint32_t *pin_attempts_left);
+                 char **last_address,
+                 uint32_t *address_attempts_left);
 
 
   /**
@@ -239,13 +241,13 @@ struct CHALLENGER_DatabasePlugin
    * address did not change, the operation is successful even without
    * the counter change.
    *
-   * @param cls
+   * @param cls closure
    * @param nonce unique nonce to use to identify the validation
    * @param address the new address to validate
    * @param next_tx_time tx time we must have sent earlier before to 
retransmit now
    * @param[in,out] last_tx_time set to the last time when we (presumably) 
send a PIN to @a address, input should be current time to use if the existing 
value for tx_time is past @a next_tx_time
    * @param[in,out] last_pin set to the PIN last send to @a address, input 
should be random PIN to use if address did not change
-   * @param[in,out] pin_attempts_left set to number of PIN transmission 
attempts left for this address; input is value to be used if address is new, 
output is possibly different if address was not new
+   * @param[in,out] pin_transmissions_left set to number of PIN transmission 
attempts left for this address; input is value to be used if address is new, 
output is possibly different if address was not new
    * @return transaction status:
    *   #GNUNET_DB_SUCCESS_ONE_RESULT if the address was changed
    *   #GNUNET_DB_SUCCESS_NO_RESULTS if we do not permit further changes to 
the address (attempts exhausted)
@@ -259,7 +261,7 @@ struct CHALLENGER_DatabasePlugin
     struct GNUNET_TIME_Absolute next_tx_time,
     struct GNUNET_TIME_Absolute *last_tx_time,
     uint32_t *last_pin,
-    uint32_t *pin_attempts_left);
+    uint32_t *pin_transmissions_left);
 
 
   /**

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