gnunet-svn
[Top][All Lists]
Advanced

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

[taler-anastasis] branch master updated: implement routine to download m


From: gnunet
Subject: [taler-anastasis] branch master updated: implement routine to download meta data and decrypt to libanastasis; improve API to include timestamp
Date: Wed, 19 Jan 2022 14:38:59 +0100

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

grothoff pushed a commit to branch master
in repository anastasis.

The following commit(s) were added to refs/heads/master by this push:
     new 21e28d6  implement routine to download meta data and decrypt to 
libanastasis; improve API to include timestamp
21e28d6 is described below

commit 21e28d6d049a948fe71817da7cb3e3b0f1639eb6
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Wed Jan 19 14:38:57 2022 +0100

    implement routine to download meta data and decrypt to libanastasis; 
improve API to include timestamp
---
 doc/sphinx/rest.rst                               |  15 +-
 src/backend/anastasis-httpd_policy-meta.c         |  16 +-
 src/include/anastasis.h                           |  67 +++++++-
 src/include/anastasis_database_plugin.h           |   2 +
 src/include/anastasis_service.h                   |   5 +
 src/lib/Makefile.am                               |   1 +
 src/lib/anastasis_backup.c                        |  27 +++-
 src/lib/anastasis_meta.c                          | 180 ++++++++++++++++++++++
 src/restclient/anastasis_api_policy_meta_lookup.c |  33 ++--
 src/stasis/plugin_anastasis_postgres.c            |  13 +-
 src/stasis/stasis-0001.sql                        |   3 +
 11 files changed, 324 insertions(+), 38 deletions(-)

diff --git a/doc/sphinx/rest.rst b/doc/sphinx/rest.rst
index 7341992..b5ab50d 100644
--- a/doc/sphinx/rest.rst
+++ b/doc/sphinx/rest.rst
@@ -167,11 +167,18 @@ In the following, UUID is always defined and used 
according to `RFC 4122`_.
   .. ts:def:: RecoveryMetaSummary
 
     interface RecoveryMetaSummary {
-      // Version numbers as a string (!) are used as keys,
-      // the value being the base32-encoded encrypted meta data
-      // for that version. A value can be NULL if the document
+      // Version numbers as a string (!) are used as keys.
+      "$VERSION": MetaData;
+    }
+
+    interface MetaData {
+      // The meta value can be NULL if the document
       // exists but no meta data was provided.
-      "$VERSION": EncryptedMetaData;
+      meta?: String;
+
+      // Server-time indicative of when the recovery
+      // document was uploaded.
+      upload_time: Timestamp;
     }
 
 .. http:get:: /policy/$ACCOUNT_PUB[?version=$NUMBER]
diff --git a/src/backend/anastasis-httpd_policy-meta.c 
b/src/backend/anastasis-httpd_policy-meta.c
index a786c68..7d143ef 100644
--- a/src/backend/anastasis-httpd_policy-meta.c
+++ b/src/backend/anastasis-httpd_policy-meta.c
@@ -36,6 +36,7 @@
  *
  * @param cls closure with a `json_t *` to build up
  * @param version the version of the recovery document
+ * @param ts timestamp when the document was created
  * @param recovery_meta_data contains meta data about the encrypted recovery 
document
  * @param recovery_meta_data_size size of @a recovery_meta_data blob
  * @return #GNUNET_OK to continue to iterate, #GNUNET_NO to abort iteration
@@ -43,6 +44,7 @@
 static enum GNUNET_GenericReturnValue
 build_meta_result (void *cls,
                    uint32_t version,
+                   struct GNUNET_TIME_Timestamp ts,
                    const void *recovery_meta_data,
                    size_t recovery_meta_data_size)
 {
@@ -57,11 +59,15 @@ build_meta_result (void *cls,
                  json_object_set_new (
                    result,
                    version_s,
-                   (NULL == recovery_meta_data)
-                                      ? json_null ()
-                                      : GNUNET_JSON_from_data (
-                     recovery_meta_data,
-                     recovery_meta_data_size)));
+                   GNUNET_JSON_PACK (
+                     GNUNET_JSON_pack_allow_null (
+                       GNUNET_JSON_pack_data_varsize (
+                         "meta",
+                         recovery_meta_data,
+                         recovery_meta_data_size)),
+                     GNUNET_JSON_pack_timestamp (
+                       "upload_time",
+                       ts))));
   return GNUNET_OK;
 }
 
diff --git a/src/include/anastasis.h b/src/include/anastasis.h
index b957f18..92c0745 100644
--- a/src/include/anastasis.h
+++ b/src/include/anastasis.h
@@ -373,6 +373,67 @@ void
 ANASTASIS_challenge_abort (struct ANASTASIS_Challenge *c);
 
 
+/**
+ * Handle for an operation to get available recovery
+ * document versions.
+ */
+struct ANASTASIS_VersionCheck;
+
+
+/**
+ * Callback which passes back meta data about one of the
+ * recovery documents available at the provider.
+ *
+ * @param cls closure for the callback
+ * @param version version number of the policy document,
+ *                0 for the end of the list
+ * @param server_time time of the backup at the provider
+ * @param recdoc_id hash of the compressed recovery document, uniquely
+ *                  identifies the document; NULL for the end of the list
+ * @param secret_name name of the secret as chosen by the user,
+ *                  or NULL if the user did not provide a name
+ */
+typedef void
+(*ANASTASIS_MetaPolicyCallback)(void *cls,
+                                uint32_t version,
+                                struct GNUNET_TIME_Timestamp server_time,
+                                const struct GNUNET_HashCode *recdoc_id,
+                                const char *secret_name);
+
+
+/**
+ * Obtain an overview of available recovery policies from the
+ * specified provider.
+ *
+ * @param ctx context for making HTTP requests
+ * @param id_data contains the users identity, (user account on providers)
+ * @param version defines the version which will be downloaded, 0 for latest 
version
+ * @param anastasis_provider_url provider url
+ * @param provider_salt the server salt
+ * @param mpc function called with the available versions
+ * @param mpc_cls closure for @a mpc callback
+ * @return recovery operation handle
+ */
+struct ANASTASIS_VersionCheck *
+ANASTASIS_recovery_get_versions (
+  struct GNUNET_CURL_Context *ctx,
+  const json_t *id_data,
+  unsigned int max_version,
+  const char *anastasis_provider_url,
+  const struct ANASTASIS_CRYPTO_ProviderSaltP *provider_salt,
+  ANASTASIS_MetaPolicyCallback mpc,
+  void *mpc_cls);
+
+
+/**
+ * Cancel version check operation.
+ *
+ * @param vc operation to cancel
+ */
+void
+ANASTASIS_recovery_get_versions_cancel (struct ANASTASIS_VersionCheck *vc);
+
+
 /**
  * Defines a Decryption Policy with multiple escrow methods
  */
@@ -528,9 +589,9 @@ struct ANASTASIS_Recovery;
  *
  * @param ctx context for making HTTP requests
  * @param id_data contains the users identity, (user account on providers)
- * @param version defines the version which will be downloaded NULL for latest 
version
- * @param anastasis_provider_url NULL terminated list of possible provider urls
- * @param provider_salt the server salt
+ * @param version defines the version which will be downloaded, 0 for latest 
version
+ * @param anastasis_provider_url provider REST API endpoint url
+ * @param provider_salt the provider's salt
  * @param pc opens the policy call back which holds the downloaded version and 
the policies
  * @param pc_cls closure for callback
  * @param csc core secret callback is opened, with this the core secert is 
passed to the client after the authentication
diff --git a/src/include/anastasis_database_plugin.h 
b/src/include/anastasis_database_plugin.h
index 20e87d1..2082bf9 100644
--- a/src/include/anastasis_database_plugin.h
+++ b/src/include/anastasis_database_plugin.h
@@ -165,6 +165,7 @@ typedef bool
  *
  * @param cls closure
  * @param version the version of the recovery document
+ * @param ts timestamp when the document was uploaded
  * @param recovery_meta_data contains meta data about the encrypted recovery 
document
  * @param recovery_meta_data_size size of @a recovery_meta_data blob
  * @return #GNUNET_OK to continue to iterate, #GNUNET_NO to abort iteration
@@ -172,6 +173,7 @@ typedef bool
 typedef enum GNUNET_GenericReturnValue
 (*ANASTASIS_DB_RecoveryMetaCallback)(void *cls,
                                      uint32_t version,
+                                     struct GNUNET_TIME_Timestamp ts,
                                      const void *recovery_meta_data,
                                      size_t recovery_meta_data_size);
 
diff --git a/src/include/anastasis_service.h b/src/include/anastasis_service.h
index ee24b7a..3bc8f87 100644
--- a/src/include/anastasis_service.h
+++ b/src/include/anastasis_service.h
@@ -161,6 +161,11 @@ ANASTASIS_config_cancel (struct ANASTASIS_ConfigOperation 
*co);
 struct ANASTASIS_MetaDataEntry
 {
 
+  /**
+   * Timestamp of the backup at the server.
+   */
+  struct GNUNET_TIME_Timestamp server_time;
+
   /**
    * The encrypted meta data we downloaded.
    */
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 07460d4..6f71418 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -14,6 +14,7 @@ libanastasis_la_LDFLAGS = \
   -no-undefined
 libanastasis_la_SOURCES = \
   anastasis_backup.c \
+  anastasis_meta.c \
   anastasis_recovery.c
 libanastasis_la_LIBADD = \
   $(top_builddir)/src/util/libanastasisutil.la \
diff --git a/src/lib/anastasis_backup.c b/src/lib/anastasis_backup.c
index 20c77e4..2e769ca 100644
--- a/src/lib/anastasis_backup.c
+++ b/src/lib/anastasis_backup.c
@@ -734,6 +734,8 @@ ANASTASIS_secret_share (struct GNUNET_CURL_Context *ctx,
   json_t *esc_methods;
   size_t recovery_document_size;
   char *recovery_document_str;
+  size_t meta_size;
+  void *meta;
 
   if (0 == pss_length)
   {
@@ -889,6 +891,18 @@ ANASTASIS_secret_share (struct GNUNET_CURL_Context *ctx,
     recovery_document_str = (char *) cbuf;
   }
 
+  meta_size = sizeof (struct GNUNET_HashCode);
+  if (NULL != secret_name)
+    meta_size += strlen (secret_name) + 1;
+  meta = GNUNET_malloc (meta_size);
+  GNUNET_CRYPTO_hash (recovery_document_str,
+                      recovery_document_size,
+                      (struct GNUNET_HashCode *) meta);
+  if (NULL != secret_name)
+    memcpy (meta + sizeof (struct GNUNET_HashCode),
+            secret_name,
+            strlen (secret_name) + 1);
+
   for (unsigned int l = 0; l < ss->pss_length; l++)
   {
     struct PolicyStoreState *pss = &ss->pss[l];
@@ -905,12 +919,11 @@ ANASTASIS_secret_share (struct GNUNET_CURL_Context *ctx,
     ANASTASIS_CRYPTO_user_identifier_derive (id_data,
                                              &pss->server_salt,
                                              &pss->id);
-    if (NULL != secret_name)
-      ANASTASIS_CRYPTO_recovery_metadata_encrypt (&pss->id,
-                                                  secret_name,
-                                                  strlen (secret_name),
-                                                  &enc_meta,
-                                                  &enc_meta_size);
+    ANASTASIS_CRYPTO_recovery_metadata_encrypt (&pss->id,
+                                                meta,
+                                                meta_size,
+                                                &enc_meta,
+                                                &enc_meta_size);
     ANASTASIS_CRYPTO_account_private_key_derive (&pss->id,
                                                  &anastasis_priv);
     ANASTASIS_CRYPTO_recovery_document_encrypt (&pss->id,
@@ -943,9 +956,11 @@ ANASTASIS_secret_share (struct GNUNET_CURL_Context *ctx,
       GNUNET_break (0);
       ANASTASIS_secret_share_cancel (ss);
       GNUNET_free (recovery_document_str);
+      GNUNET_free (meta);
       return NULL;
     }
   }
+  GNUNET_free (meta);
   GNUNET_free (recovery_document_str);
   return ss;
 }
diff --git a/src/lib/anastasis_meta.c b/src/lib/anastasis_meta.c
new file mode 100644
index 0000000..7812f6b
--- /dev/null
+++ b/src/lib/anastasis_meta.c
@@ -0,0 +1,180 @@
+/*
+  This file is part of Anastasis
+  Copyright (C) 2022 Anastasis SARL
+
+  Anastasis 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.
+
+  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/>
+*/
+/**
+ * @brief anastasis client api to get recovery document meta data
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "anastasis.h"
+#include <taler/taler_json_lib.h>
+#include <gnunet/gnunet_util_lib.h>
+#include <taler/taler_merchant_service.h>
+
+
+/**
+ * Handle for a version check operation.
+ */
+struct ANASTASIS_VersionCheck
+{
+  /**
+   * Function to call with results.
+   */
+  ANASTASIS_MetaPolicyCallback mpc;
+
+  /**
+   * Closure for @e mpc.
+   */
+  void *mpc_cls;
+
+  /**
+   * Handle for the actual REST operation.
+   */
+  struct ANASTASIS_PolicyMetaLookupOperation *plm;
+
+  /**
+   * User identifier (needed to decrypt).
+   */
+  struct ANASTASIS_CRYPTO_UserIdentifierP id;
+};
+
+
+/**
+ * Function called with results from a GET /policy/$POL/meta request
+ *
+ * @param cls closure with the `struct ANASTASIS_VersionCheck *`
+ * @param http_status HTTP status code for this request
+ * @param dd the response details
+ */
+static void
+meta_cb (
+  void *cls,
+  unsigned int http_status,
+  const struct ANASTASIS_MetaDownloadDetails *dd)
+{
+  struct ANASTASIS_VersionCheck *vc = cls;
+
+  vc->plm = NULL;
+  if ( (MHD_HTTP_OK != http_status) ||
+       (NULL == dd) )
+  {
+    vc->mpc (vc->mpc_cls,
+             0,
+             GNUNET_TIME_UNIT_ZERO_TS,
+             NULL,
+             NULL);
+    ANASTASIS_recovery_get_versions_cancel (vc);
+    return;
+  }
+  for (size_t i = 0; i<dd->metas_length; i++)
+  {
+    const struct ANASTASIS_MetaDataEntry *meta = &dd->metas[i];
+    const char *secret_name = NULL;
+    const struct GNUNET_HashCode *eph;
+    void *dec;
+    size_t dec_len;
+
+    if (GNUNET_OK !=
+        ANASTASIS_CRYPTO_recovery_metadata_decrypt (
+          &vc->id,
+          meta->meta_data,
+          meta->meta_data_size,
+          &dec,
+          &dec_len))
+    {
+      GNUNET_break_op (0);
+      continue;
+    }
+    if (sizeof (*eph) > dec_len)
+    {
+      GNUNET_break_op (0);
+      GNUNET_free (dec);
+      continue;
+    }
+    eph = dec;
+    if (sizeof (*eph) < dec_len)
+    {
+      secret_name = (const char *) &eph[1];
+      dec_len -= sizeof (*eph);
+      if ('\0' != secret_name[dec_len - 1])
+      {
+        GNUNET_break_op (0);
+        GNUNET_free (dec);
+        continue;
+      }
+    }
+    vc->mpc (vc->mpc_cls,
+             meta->version,
+             meta->server_time,
+             eph,
+             secret_name);
+    GNUNET_free (dec);
+  }
+  vc->mpc (vc->mpc_cls,
+           0,
+           GNUNET_TIME_UNIT_ZERO_TS,
+           NULL,
+           NULL);
+  ANASTASIS_recovery_get_versions_cancel (vc);
+}
+
+
+struct ANASTASIS_VersionCheck *
+ANASTASIS_recovery_get_versions (
+  struct GNUNET_CURL_Context *ctx,
+  const json_t *id_data,
+  unsigned int max_version,
+  const char *anastasis_provider_url,
+  const struct ANASTASIS_CRYPTO_ProviderSaltP *provider_salt,
+  ANASTASIS_MetaPolicyCallback mpc,
+  void *mpc_cls)
+{
+  struct ANASTASIS_VersionCheck *vc;
+  struct ANASTASIS_CRYPTO_AccountPublicKeyP account_pub;
+
+  vc = GNUNET_new (struct ANASTASIS_VersionCheck);
+  vc->mpc = mpc;
+  vc->mpc_cls = mpc_cls;
+  ANASTASIS_CRYPTO_user_identifier_derive (id_data,
+                                           provider_salt,
+                                           &vc->id);
+  ANASTASIS_CRYPTO_account_public_key_derive (&vc->id,
+                                              &account_pub);
+  vc->plm = ANASTASIS_policy_meta_lookup (ctx,
+                                          anastasis_provider_url,
+                                          &account_pub,
+                                          max_version,
+                                          &meta_cb,
+                                          vc);
+  if (NULL == vc->plm)
+  {
+    GNUNET_break (0);
+    GNUNET_free (vc);
+    return NULL;
+  }
+  return vc;
+}
+
+
+void
+ANASTASIS_recovery_get_versions_cancel (struct ANASTASIS_VersionCheck *vc)
+{
+  if (NULL != vc->plm)
+  {
+    ANASTASIS_policy_meta_lookup_cancel (vc->plm);
+    vc->plm = NULL;
+  }
+  GNUNET_free (vc);
+}
diff --git a/src/restclient/anastasis_api_policy_meta_lookup.c 
b/src/restclient/anastasis_api_policy_meta_lookup.c
index 9be49ca..b49d1b8 100644
--- a/src/restclient/anastasis_api_policy_meta_lookup.c
+++ b/src/restclient/anastasis_api_policy_meta_lookup.c
@@ -28,6 +28,7 @@
 #include <microhttpd.h> /* just for HTTP status codes */
 #include "anastasis_service.h"
 #include "anastasis_api_curl_defaults.h"
+#include <gnunet/gnunet_json_lib.h>
 #include <taler/taler_signatures.h>
 
 
@@ -132,7 +133,15 @@ handle_policy_meta_lookup_finished (void *cls,
         {
           unsigned int ver;
           char dummy;
-          const char *vals;
+          struct GNUNET_JSON_Specification spec[] = {
+            GNUNET_JSON_spec_mark_optional (
+              GNUNET_JSON_spec_varsize ("meta",
+                                        &md[off],
+                                        &metas[off].meta_data_size)),
+            GNUNET_JSON_spec_timestamp ("upload_time",
+                                        &metas[off].server_time),
+            GNUNET_JSON_spec_end ()
+          };
 
           if (1 != sscanf (label,
                            "%u%c",
@@ -142,27 +151,15 @@ handle_policy_meta_lookup_finished (void *cls,
             GNUNET_break (0);
             break;
           }
-          metas[off].version = (uint32_t) ver;
-          if (json_is_null (val))
-          {
-            metas[off].meta_data = NULL;
-            metas[off].meta_data_size = 0;
-            off++;
-            continue;
-          }
-          vals = json_string_value (val);
-          if ( (NULL == vals) ||
-               (GNUNET_OK !=
-                GNUNET_STRINGS_string_to_data_alloc (vals,
-                                                     strlen (vals),
-                                                     &md[off],
-                                                     
&metas[off].meta_data_size)) )
+          if (GNUNET_OK !=
+              GNUNET_JSON_parse (val,
+                                 spec,
+                                 NULL, NULL))
           {
-            GNUNET_break (0);
+            GNUNET_break_op (0);
             break;
           }
           metas[off].version = (uint32_t) ver;
-          metas[off].meta_data = md[off];
           off++;
         }
         if (off < mlen)
diff --git a/src/stasis/plugin_anastasis_postgres.c 
b/src/stasis/plugin_anastasis_postgres.c
index ef13c6c..bfe86da 100644
--- a/src/stasis/plugin_anastasis_postgres.c
+++ b/src/stasis/plugin_anastasis_postgres.c
@@ -334,9 +334,10 @@ prepare_statements (void *cls)
                             ",recovery_data_hash"
                             ",recovery_data"
                             ",recovery_meta_data"
+                            ",creation_date"
                             ") VALUES "
-                            "($1, $2, $3, $4, $5, $6);",
-                            6),
+                            "($1, $2, $3, $4, $5, $6, $7);",
+                            7),
     GNUNET_PQ_make_prepare ("truth_select",
                             "SELECT "
                             " method_name"
@@ -348,6 +349,7 @@ prepare_statements (void *cls)
     GNUNET_PQ_make_prepare ("recoverydocument_select_meta",
                             "SELECT "
                             " version"
+                            ",creation_date"
                             ",recovery_meta_data"
                             " FROM anastasis_recoverydocument"
                             " WHERE user_id=$1"
@@ -1019,6 +1021,8 @@ postgres_store_recovery_document (
 
     /* finally, actually insert the recovery document */
     {
+      struct GNUNET_TIME_Timestamp now
+        = GNUNET_TIME_timestamp_get ();
       struct GNUNET_PQ_QueryParam params[] = {
         GNUNET_PQ_query_param_auto_from_type (account_pub),
         GNUNET_PQ_query_param_uint32 (version),
@@ -1030,6 +1034,7 @@ postgres_store_recovery_document (
         ? GNUNET_PQ_query_param_null ()
         : GNUNET_PQ_query_param_fixed_size (recovery_meta_data,
                                             recovery_meta_data_size),
+        GNUNET_PQ_query_param_timestamp (&now),
         GNUNET_PQ_query_param_end
       };
 
@@ -2248,10 +2253,13 @@ meta_iterator (void *cls,
     uint32_t version;
     void *meta_data = NULL;
     size_t meta_data_size = 0;
+    struct GNUNET_TIME_Timestamp ts;
     bool unused = false;
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_uint32 ("version",
                                     &version),
+      GNUNET_PQ_result_spec_timestamp ("creation_date",
+                                       &ts),
       GNUNET_PQ_result_spec_allow_null (
         GNUNET_PQ_result_spec_variable_size ("recovery_meta_data",
                                              &meta_data,
@@ -2272,6 +2280,7 @@ meta_iterator (void *cls,
     }
     ret = ctx->cb (ctx->cb_cls,
                    version,
+                   ts,
                    meta_data,
                    meta_data_size);
     GNUNET_PQ_cleanup_result (rs);
diff --git a/src/stasis/stasis-0001.sql b/src/stasis/stasis-0001.sql
index e3c9c5c..d512473 100644
--- a/src/stasis/stasis-0001.sql
+++ b/src/stasis/stasis-0001.sql
@@ -141,6 +141,7 @@ CREATE TABLE IF NOT EXISTS anastasis_recoverydocument
    recovery_data_hash BYTEA NOT NULL CHECK(length(recovery_data_hash)=64),
    recovery_data BYTEA NOT NULL,
    recovery_meta_data BYTEA DEFAULT NULL,
+   creation_date INT8 NOT NULL,
    PRIMARY KEY (user_id, version));
 COMMENT ON TABLE anastasis_recoverydocument
   IS 'Stores a recovery document which contains the policy and the encrypted 
core secret';
@@ -152,6 +153,8 @@ COMMENT ON COLUMN anastasis_recoverydocument.account_sig
   IS 'Signature of the recovery document';
 COMMENT ON COLUMN anastasis_recoverydocument.recovery_data_hash
   IS 'Hash of the recovery document to prevent unnecessary uploads';
+COMMENT ON COLUMN anastasis_recoverydocument.creation_date
+  IS 'Creation date of the recovery document (when it was uploaded)';
 COMMENT ON COLUMN anastasis_recoverydocument.recovery_data
   IS 'Contains the encrypted policy and core secret';
 COMMENT ON COLUMN anastasis_recoverydocument.recovery_meta_data

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