anastasis

Credential backup and recovery protocol and service
Log | Files | Refs | Submodules | README | LICENSE

commit 1ccd17d515d43b524dc06e3a4d206f19f873d0dd
parent a261b98c73643a16e70ce4f22ed7cd8838967689
Author: Christian Grothoff <christian@grothoff.org>
Date:   Wed, 19 Jan 2022 10:20:43 +0100

modify backend to support separate storage of meta data

Diffstat:
Msrc/backend/anastasis-httpd_policy_upload.c | 2++
Msrc/include/anastasis_database_plugin.h | 45++++++++++++++++++++++++++++++++++++++++++++-
Msrc/stasis/plugin_anastasis_postgres.c | 144++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Msrc/stasis/stasis-0001.sql | 5++++-
4 files changed, 185 insertions(+), 11 deletions(-)

diff --git a/src/backend/anastasis-httpd_policy_upload.c b/src/backend/anastasis-httpd_policy_upload.c @@ -1121,6 +1121,8 @@ AH_handler_policy_post ( &puc->new_policy_upload_hash, puc->upload, puc->upload_size, + NULL, /* FIXME: meta-data! */ + 0, &puc->payment_identifier, &version); GNUNET_snprintf (version_s, diff --git a/src/include/anastasis_database_plugin.h b/src/include/anastasis_database_plugin.h @@ -1,6 +1,6 @@ /* This file is part of Anastasis - Copyright (C) 2019-2021 Anastasis SARL + Copyright (C) 2019-2022 Anastasis SARL Anastasis is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software @@ -159,6 +159,24 @@ typedef bool /** + * Function called on matching meta data. Note that if the client did + * not provide meta data for @a version, the function will be called + * with @a recovery_meta_data being NULL. + * + * @param cls closure + * @param version the version of the recovery document + * @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 + */ +typedef enum GNUNET_GenericReturnValue +(*ANASTASIS_DB_RecoveryMetaCallback)(void *cls, + uint32_t version, + const void *recovery_meta_data, + size_t recovery_meta_data_size); + + +/** * Handle to interact with the database. * * Functions ending with "_TR" run their OWN transaction scope @@ -329,6 +347,8 @@ struct ANASTASIS_DatabasePlugin * @param recovery_data_hash hash of @a data * @param recovery_data contains encrypted recovery document * @param recovery_data_size size of @a recovery_data blob + * @param recovery_meta_data contains meta data about the encrypted recovery document + * @param recovery_meta_data_size size of @a recovery_meta_data blob * @param payment_secret identifier for the payment, used to later charge on uploads * @param[out] version set to the version assigned to the document by the database * @return transaction status, 0 if upload could not be finished because @a payment_secret @@ -342,11 +362,34 @@ struct ANASTASIS_DatabasePlugin const struct GNUNET_HashCode *recovery_data_hash, const void *recovery_data, size_t recovery_data_size, + const void *recovery_meta_data, + size_t recovery_meta_data_size, const struct ANASTASIS_PaymentSecretP *payment_secret, uint32_t *version); /** + * Fetch recovery document meta data for user. Returns + * meta data in descending order from @a max_version. + * The size of the result set may be limited. + * + * @param cls closure + * @param account_pub public key of the user's account + * @param max_version the maximum version number the user requests + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status + */ + enum GNUNET_DB_QueryStatus + (*get_recovery_meta_data)( + void *cls, + const struct ANASTASIS_CRYPTO_AccountPublicKeyP *account_pub, + uint32_t max_version, + ANASTASIS_DB_RecoveryMetaCallback cb, + void *cb_cls); + + + /** * Fetch recovery document for user according given version. * * @param cls closure diff --git a/src/stasis/plugin_anastasis_postgres.c b/src/stasis/plugin_anastasis_postgres.c @@ -1,6 +1,6 @@ /* This file is part of Anastasis - Copyright (C) 2020, 2021 Anastasis SARL + Copyright (C) 2020, 2021, 2022 Anastasis SARL Anastasis is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software @@ -15,8 +15,7 @@ */ /** * @file stasis/plugin_anastasis_postgres.c - * @brief database helper functions for postgres used by the anastasis - * @author Sree Harsha Totakura <sreeharsha@totakura.in> + * @brief database helper functions for postgres used by GNU Anastasis * @author Christian Grothoff * @author Marcello Stanisci */ @@ -306,7 +305,6 @@ prepare_statements (void *cls) ") VALUES " "($1, $2, $3, $4, $5, $6);", 6), - GNUNET_PQ_make_prepare ("test_auth_iban_payment", "SELECT" " credit_val" @@ -328,8 +326,6 @@ prepare_statements (void *cls) ") VALUES " "($1, $2, $3, $4, $5, $6, $7);", 7), - - GNUNET_PQ_make_prepare ("recovery_document_insert", "INSERT INTO anastasis_recoverydocument " "(user_id" @@ -337,9 +333,10 @@ prepare_statements (void *cls) ",account_sig" ",recovery_data_hash" ",recovery_data" + ",recovery_meta_data" ") VALUES " - "($1, $2, $3, $4, $5);", - 5), + "($1, $2, $3, $4, $5, $6);", + 6), GNUNET_PQ_make_prepare ("truth_select", "SELECT " " method_name" @@ -631,7 +628,7 @@ postgres_preflight (void *cls) * must point to a constant * @return #GNUNET_OK on success */ -static int +static enum GNUNET_GenericReturnValue begin_transaction (void *cls, const char *name) { @@ -834,6 +831,8 @@ postgres_store_recovery_document ( const struct GNUNET_HashCode *recovery_data_hash, const void *recovery_data, size_t recovery_data_size, + const void *recovery_meta_data, + size_t recovery_meta_data_size, const struct ANASTASIS_PaymentSecretP *payment_secret, uint32_t *version) { @@ -1017,6 +1016,10 @@ postgres_store_recovery_document ( GNUNET_PQ_query_param_auto_from_type (recovery_data_hash), GNUNET_PQ_query_param_fixed_size (recovery_data, recovery_data_size), + (NULL == recovery_meta_data) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_fixed_size (recovery_meta_data, + recovery_meta_data_size), GNUNET_PQ_query_param_end }; @@ -2193,6 +2196,128 @@ postgres_get_latest_recovery_document ( /** + * Closure for meta_iterator(). + */ +struct MetaIteratorContext +{ + /** + * Function to call on each result. + */ + ANASTASIS_DB_RecoveryMetaCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Set to true on database failure. + */ + bool db_failure; +}; + + +/** + * Helper function for #postgres_get_recovery_meta_data(). + * To be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls closure of type `struct MetaIteratorContext *` + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +meta_iterator (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct MetaIteratorContext *ctx = cls; + + for (unsigned int i = 0; i<num_results; i++) + { + uint32_t version; + void *meta_data = NULL; + size_t meta_data_size = 0; + bool unused = false; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint32 ("version", + &version), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_variable_size ("recovery_meta_data", + &meta_data, + &meta_data_size), + &unused), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_GenericReturnValue ret; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ctx->db_failure = true; + return; + } + ret = ctx->cb (ctx->cb_cls, + version, + meta_data, + meta_data_size); + GNUNET_PQ_cleanup_result (rs); + if (GNUNET_OK != ret) + break; + } +} + + +/** + * Fetch recovery document meta data for user. Returns + * meta data in descending order from @a max_version. + * The size of the result set may be limited. + * + * @param cls closure + * @param account_pub public key of the user's account + * @param max_version the maximum version number the user requests + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status + */ +static enum GNUNET_DB_QueryStatus +postgres_get_recovery_meta_data ( + void *cls, + const struct ANASTASIS_CRYPTO_AccountPublicKeyP *account_pub, + uint32_t max_version, + ANASTASIS_DB_RecoveryMetaCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct MetaIteratorContext ctx = { + .cb = cb, + .cb_cls = cb_cls + }; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (account_pub), + GNUNET_PQ_query_param_uint32 (&max_version), + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + check_connection (pg); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "recoverydocument_select_meta", + params, + &meta_iterator, + &ctx); + if (qs < 0) + return qs; + if (ctx.db_failure) + return GNUNET_DB_STATUS_HARD_ERROR; + return qs; +} + + +/** * Fetch recovery document for user according given version. * * @param cls closure @@ -2811,6 +2936,7 @@ libanastasis_plugin_db_postgres_init (void *cls) plugin->get_escrow_challenge = &postgres_get_escrow_challenge; plugin->get_key_share = &postgres_get_key_share; plugin->get_latest_recovery_document = &postgres_get_latest_recovery_document; + plugin->get_recovery_meta_data = &postgres_get_recovery_meta_data; plugin->get_recovery_document = &postgres_get_recovery_document; plugin->lookup_account = &postgres_lookup_account; plugin->check_payment_identifier = &postgres_check_payment_identifier; diff --git a/src/stasis/stasis-0001.sql b/src/stasis/stasis-0001.sql @@ -1,6 +1,6 @@ -- -- This file is part of Anastasis --- Copyright (C) 2020, 2021 Anastasis SARL SA +-- Copyright (C) 2020, 2021, 2022 Anastasis SARL SA -- -- 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 @@ -140,6 +140,7 @@ CREATE TABLE IF NOT EXISTS anastasis_recoverydocument account_sig BYTEA NOT NULL CHECK(LENGTH(account_sig)=64), recovery_data_hash BYTEA NOT NULL CHECK(length(recovery_data_hash)=64), recovery_data BYTEA NOT NULL, + recovery_meta_data BYTEA DEFAULT 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'; @@ -153,6 +154,8 @@ COMMENT ON COLUMN anastasis_recoverydocument.recovery_data_hash IS 'Hash of the recovery document to prevent unnecessary uploads'; COMMENT ON COLUMN anastasis_recoverydocument.recovery_data IS 'Contains the encrypted policy and core secret'; +COMMENT ON COLUMN anastasis_recoverydocument.recovery_meta_data + IS 'Contains an encrypted human-readable and sometimes user-generated description of the backup'; CREATE TABLE IF NOT EXISTS anastasis_challengecode