diff options
author | Christian Grothoff <christian@grothoff.org> | 2021-07-30 10:38:27 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2021-07-30 10:38:27 +0200 |
commit | 7e669bcf6b6336ec429da949bcb4aa456971dba2 (patch) | |
tree | d19912f950d1cac1c38b857b7d5bdaba2289544e /src/testing | |
download | anastasis-7e669bcf6b6336ec429da949bcb4aa456971dba2.tar.gz anastasis-7e669bcf6b6336ec429da949bcb4aa456971dba2.tar.bz2 anastasis-7e669bcf6b6336ec429da949bcb4aa456971dba2.zip |
folding history in preparation of GNU Anastasis v0.0.0 release
Diffstat (limited to 'src/testing')
43 files changed, 6269 insertions, 0 deletions
diff --git a/src/testing/.gitignore b/src/testing/.gitignore new file mode 100644 index 0000000..a6eb294 --- /dev/null +++ b/src/testing/.gitignore @@ -0,0 +1,3 @@ +test_anastasis +test_anastasisrest_api +test_anastasis_api_home/.local/share/taler/crypto-* diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am new file mode 100644 index 0000000..8fc710b --- /dev/null +++ b/src/testing/Makefile.am @@ -0,0 +1,91 @@ +# This Makefile.am is in the public domain +AM_CPPFLAGS = -I$(top_srcdir)/src/include -I$(top_srcdir)/src/backend -I$(top_srcdir)/src/lib + +if USE_COVERAGE + AM_CFLAGS = --coverage -O0 + XLIB = -lgcov +endif + +lib_LTLIBRARIES = \ + libanastasistesting.la + +libanastasistesting_la_LDFLAGS = \ + -version-info 0:0:0 \ + -no-undefined +libanastasistesting_la_SOURCES = \ + testing_api_cmd_policy_store.c \ + testing_api_cmd_truth_store.c \ + testing_api_cmd_policy_lookup.c \ + testing_api_cmd_keyshare_lookup.c \ + testing_api_cmd_config.c \ + testing_api_helpers.c \ + testing_api_trait_account_pub.c \ + testing_api_trait_account_priv.c \ + testing_api_trait_eks.c \ + testing_api_trait_payment_secret.c \ + testing_api_trait_truth_key.c \ + testing_api_trait_truth_uuid.c \ + testing_api_trait_hash.c \ + testing_api_trait_salt.c \ + testing_api_trait_code.c \ + testing_cmd_truth_upload.c \ + testing_cmd_policy_create.c \ + testing_cmd_secret_share.c \ + testing_cmd_recover_secret.c \ + testing_cmd_challenge_answer.c \ + testing_trait_truth.c \ + testing_trait_policy.c \ + testing_trait_core_secret.c \ + testing_trait_challenge.c +libanastasistesting_la_LIBADD = \ + $(top_builddir)/src/restclient/libanastasisrest.la \ + $(top_builddir)/src/lib/libanastasis.la \ + $(top_builddir)/src/util/libanastasisutil.la \ + -ltalerexchange \ + -ltalermerchant \ + -ltalerjson \ + -ltalerutil \ + -lgnunetcurl \ + -lgnunetjson \ + -lgnunetutil \ + -ljansson \ + -luuid \ + -ltalertesting \ + $(XLIB) + + +check_PROGRAMS = \ + test_anastasisrest_api \ + test_anastasis + +AM_TESTS_ENVIRONMENT=export ANASTASIS_PREFIX=$${ANASTASIS_PREFIX:-@libdir@};export PATH=$${ANASTASIS_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; +TESTS = \ + $(check_PROGRAMS) + +test_anastasisrest_api_SOURCES = \ + test_anastasis_api.c +test_anastasisrest_api_LDADD = \ + libanastasistesting.la \ + -ltalermerchanttesting \ + -ltalertesting \ + -lgnunetutil \ + $(XLIB) + +test_anastasis_SOURCES = \ + test_anastasis.c +test_anastasis_LDADD = \ + libanastasistesting.la \ + -ltalermerchanttesting \ + -ltalertesting \ + -ltalerexchange \ + -lgnunetutil \ + $(XLIB) + +EXTRA_DIST = \ + test_anastasis_api.conf \ + test_anastasis_api_home/.config/taler/exchange/account-2.json \ + test_anastasis_api_home/.local/share/taler/exchange/offline-keys/master.priv \ + sms_authentication.sh + +MOSTLYCLEANFILES = \ + test_anastasis_api_home/.local/share/taler/exchange/offline-keys/secm_tofus.pub diff --git a/src/testing/sms_authentication.sh b/src/testing/sms_authentication.sh new file mode 100755 index 0000000..0c2c851 --- /dev/null +++ b/src/testing/sms_authentication.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +# Note: to use this script, you must set +# ANASTASIS_SMS_API_KEY and +# ANASTASIS_SMS_API_SECRET environment variables. +curl -X "POST" "https://rest.nexmo.com/sms/json" \ + -d "from=Vonage APIs" \ + -d "text=$1" \ + -d "to=$2" \ + -d "api_key=$ANASTASIS_SMS_API_KEY" \ + -d "api_secret=$ANASTASIS_SMS_API_SECRET" diff --git a/src/testing/test_anastasis.c b/src/testing/test_anastasis.c new file mode 100644 index 0000000..2ff7cb0 --- /dev/null +++ b/src/testing/test_anastasis.c @@ -0,0 +1,464 @@ +/* + This file is part of Anastasis + Copyright (C) 2020, 2021 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/test_anastasis.c + * @brief testcase to test anastasis + * @author Christian Grothoff + * @author Dennis Neufeld + * @author Dominik Meister + */ +#include "platform.h" +#include "anastasis_testing_lib.h" +#include <taler/taler_merchant_testing_lib.h> + + +/** + * Configuration file we use. One (big) configuration is used + * for the various components for this test. + */ +#define CONFIG_FILE "test_anastasis_api.conf" + +/** + * Exchange base URL. Could also be taken from config. + */ +#define EXCHANGE_URL "http://localhost:8081/" + +/** + * Account number of the exchange at the bank. + */ +#define EXCHANGE_ACCOUNT_NAME "2" + +/** + * Account number of some user. + */ +#define USER_ACCOUNT_NAME "62" + +/** + * Account number used by the merchant + */ +#define MERCHANT_ACCOUNT_NAME "3" + +/** + * Configuration of the bank. + */ +static struct TALER_TESTING_BankConfiguration bc; + +/** + * Configuration of the exchange. + */ +static struct TALER_TESTING_ExchangeConfiguration ec; + +/** + * Payto URI of the customer (payer). + */ +static char *payer_payto; + +/** + * Payto URI of the exchange (escrow account). + */ +static char *exchange_payto; + +/** + * Payto URI of the merchant (receiver). + */ +static char *merchant_payto; + +/** + * Merchant base URL. + */ +static char *merchant_url; + +/** + * Anastasis base URL. + */ +static char *anastasis_url; + +/** + * Name of the file for exchanging the secret. + */ +static char *file_secret; + +/** + * Merchant process. + */ +static struct GNUNET_OS_Process *merchantd; + +/** + * Anastasis process. + */ +static struct GNUNET_OS_Process *anastasisd; + +/** + * Identity to use for testing. + */ +static json_t *id_data; + + +/** + * Execute the taler-exchange-wirewatch command with + * our configuration file. + * + * @param label label to use for the command. + */ +static struct TALER_TESTING_Command +cmd_exec_wirewatch (char *label) +{ + return TALER_TESTING_cmd_exec_wirewatch (label, + CONFIG_FILE); +} + + +/** + * Run wire transfer of funds from some user's account to the + * exchange. + * + * @param label label to use for the command. + * @param amount amount to transfer, i.e. "EUR:1" + * @param url exchange_url + */ +static struct TALER_TESTING_Command +cmd_transfer_to_exchange (const char *label, + const char *amount) +{ + return TALER_TESTING_cmd_admin_add_incoming (label, + amount, + &bc.exchange_auth, + payer_payto); +} + + +/** + * Main function that will tell the interpreter what commands to + * run. + * + * @param cls closure + */ +static void +run (void *cls, + struct TALER_TESTING_Interpreter *is) +{ + struct TALER_TESTING_Command pay[] = { + /** + * Move money to the exchange's bank account. + */ + cmd_transfer_to_exchange ("create-reserve-1", + "EUR:10.02"), + /** + * Make a reserve exist, according to the previous + * transfer. + */ + cmd_exec_wirewatch ("wirewatch-1"), + TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-1", + "create-reserve-1", + "EUR:5", + MHD_HTTP_OK), + TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-2", + "create-reserve-1", + "EUR:5", + MHD_HTTP_OK), + /** + * Check the reserve is depleted. + */ + TALER_TESTING_cmd_status ("withdraw-status-1", + "create-reserve-1", + "EUR:0", + MHD_HTTP_OK), + TALER_TESTING_cmd_end () + }; + + struct TALER_TESTING_Command anastasis[] = { + ANASTASIS_TESTING_cmd_config ("salt-request-1", + anastasis_url, + MHD_HTTP_OK), + ANASTASIS_TESTING_cmd_truth_upload_question ("truth-create-1", + anastasis_url, + id_data, + "answer the question", + "text/plain", + "SomeTruth1", + MHD_HTTP_NO_CONTENT, + ANASTASIS_TESTING_TSO_NONE, + "salt-request-1"), + ANASTASIS_TESTING_cmd_truth_upload_question ("truth-create-2", + anastasis_url, + id_data, + "answer the question", + "text/plain", + "SomeTruth2", + MHD_HTTP_NO_CONTENT, + ANASTASIS_TESTING_TSO_NONE, + "salt-request-1"), + ANASTASIS_TESTING_cmd_truth_upload ("truth-create-3", + anastasis_url, + id_data, + "file", + "read the file", + "text/plain", + file_secret, + strlen (file_secret), + MHD_HTTP_NO_CONTENT, + ANASTASIS_TESTING_TSO_NONE, + "salt-request-1"), + ANASTASIS_TESTING_cmd_policy_create ("policy-create-1", + "truth-create-1", + "truth-create-2", + NULL), + ANASTASIS_TESTING_cmd_policy_create ("policy-create-2", + "truth-create-1", + "truth-create-3", + NULL), + ANASTASIS_TESTING_cmd_policy_create ("policy-create-3", + "truth-create-2", + "truth-create-3", + NULL), + ANASTASIS_TESTING_cmd_secret_share ("secret-share-1", + anastasis_url, + "salt-request-1", + NULL, + id_data, + "core secret", + strlen ("core secret"), + ANASTASIS_SHARE_STATUS_PAYMENT_REQUIRED, + ANASTASIS_TESTING_SSO_NONE, + "policy-create-1", + "policy-create-2", + "policy-create-3", + NULL), + /* what would we have to pay? */ + TALER_TESTING_cmd_merchant_claim_order ("fetch-proposal", + merchant_url, + MHD_HTTP_OK, + "secret-share-1", + NULL), + /* make the payment */ + TALER_TESTING_cmd_merchant_pay_order ("pay-account", + merchant_url, + MHD_HTTP_OK, + "fetch-proposal", + "withdraw-coin-1", + "EUR:5", + "EUR:4.99", /* must match ANNUAL_FEE in config! */ + NULL), + ANASTASIS_TESTING_cmd_secret_share ("secret-share-2", + anastasis_url, + "salt-request-1", + "secret-share-1", + id_data, + "core secret", + strlen ("core secret"), + ANASTASIS_SHARE_STATUS_SUCCESS, + ANASTASIS_TESTING_SSO_NONE, + "policy-create-1", + "policy-create-2", + "policy-create-3", + NULL), + ANASTASIS_TESTING_cmd_recover_secret ("recover-secret-1", + anastasis_url, + id_data, + 0, /* version */ + ANASTASIS_TESTING_RSO_NONE, + "salt-request-1", + "secret-share-2"), + ANASTASIS_TESTING_cmd_challenge_answer ("challenge-answer-1", + NULL, /* payment ref */ + "recover-secret-1", /* challenge ref */ + 0, /* challenge index */ + "SomeTruth1", + 0, /* mode */ + ANASTASIS_CHALLENGE_STATUS_SOLVED), +#if 0 + ANASTASIS_TESTING_cmd_challenge_answer ("challenge-answer-2", + NULL, /* payment ref */ + "recover-secret-1", + 1, /* challenge index */ + "SomeTruth2", + 0, /* mode */ + ANASTASIS_CHALLENGE_STATUS_SOLVED), +#endif + ANASTASIS_TESTING_cmd_challenge_start ("challenge-start-3-pay", + NULL, /* payment ref */ + "recover-secret-1", + 2, /* challenge index */ + ANASTASIS_CHALLENGE_STATUS_PAYMENT_REQUIRED), + TALER_TESTING_cmd_merchant_claim_order ("fetch-challenge-pay-proposal", + merchant_url, + MHD_HTTP_OK, + "challenge-start-3-pay", + NULL), + TALER_TESTING_cmd_merchant_pay_order ("pay-file-challenge", + merchant_url, + MHD_HTTP_OK, + "fetch-challenge-pay-proposal", + "withdraw-coin-2", + "EUR:1", + "EUR:1", /* must match COST in config! */ + NULL), + ANASTASIS_TESTING_cmd_challenge_start ("challenge-start-3-paid", + "challenge-start-3-pay", /* payment ref */ + "recover-secret-1", + 2, /* challenge index */ + ANASTASIS_CHALLENGE_STATUS_INSTRUCTIONS), + ANASTASIS_TESTING_cmd_challenge_answer ("challenge-answer-3", + "challenge-start-3-pay", /* payment ref */ + "recover-secret-1", + 2, /* challenge index */ + "challenge-start-3-paid", /* answer */ + 1, /* mode */ + ANASTASIS_CHALLENGE_STATUS_SOLVED), + ANASTASIS_TESTING_cmd_recover_secret_finish ("recover-finish-1", + "recover-secret-1", + GNUNET_TIME_UNIT_SECONDS), + TALER_TESTING_cmd_end () + }; + + struct TALER_TESTING_Command commands[] = { + /* general setup */ + TALER_TESTING_cmd_auditor_add ("add-auditor-OK", + MHD_HTTP_NO_CONTENT, + false), + TALER_TESTING_cmd_wire_add ("add-wire-account", + "payto://x-taler-bank/localhost/2", + MHD_HTTP_NO_CONTENT, + false), + TALER_TESTING_cmd_exec_offline_sign_keys ("offline-sign-future-keys", + CONFIG_FILE), + TALER_TESTING_cmd_exec_offline_sign_fees ("offline-sign-fees", + CONFIG_FILE, + "EUR:0.01", + "EUR:0.01"), + TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys", + 1), + TALER_TESTING_cmd_merchant_post_instances ("instance-create-default", + merchant_url, + "default", + merchant_payto, + "EUR", + MHD_HTTP_NO_CONTENT), + TALER_TESTING_cmd_batch ("pay", + pay), + TALER_TESTING_cmd_batch ("anastasis", + anastasis), + TALER_TESTING_cmd_end () + }; + + TALER_TESTING_run_with_fakebank (is, + commands, + bc.exchange_auth.wire_gateway_url); +} + + +int +main (int argc, + char *const *argv) +{ + unsigned int ret; + /* These environment variables get in the way... */ + unsetenv ("XDG_DATA_HOME"); + unsetenv ("XDG_CONFIG_HOME"); + + GNUNET_log_setup ("test-anastasis", + "DEBUG", + NULL); + if (GNUNET_OK != + TALER_TESTING_prepare_fakebank (CONFIG_FILE, + "exchange-account-exchange", + &bc)) + return 77; + { + char dir[] = "/tmp/test-anastasis-file-XXXXXX"; + + if (NULL == mkdtemp (dir)) + { + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, + "mkdtemp", + dir); + return 77; + } + GNUNET_asprintf (&file_secret, + "%s/.secret", + dir); + } + id_data = ANASTASIS_TESTING_make_id_data_example ( + "MaxMuster123456789"); + payer_payto = ("payto://x-taler-bank/localhost/" USER_ACCOUNT_NAME); + exchange_payto = ("payto://x-taler-bank/localhost/" EXCHANGE_ACCOUNT_NAME); + merchant_payto = ("payto://x-taler-bank/localhost/" MERCHANT_ACCOUNT_NAME); + if (NULL == + (merchant_url = TALER_TESTING_prepare_merchant (CONFIG_FILE))) + return 77; + TALER_TESTING_cleanup_files (CONFIG_FILE); + + if (NULL == + (anastasis_url = ANASTASIS_TESTING_prepare_anastasis (CONFIG_FILE))) + return 77; + TALER_TESTING_cleanup_files (CONFIG_FILE); + + switch (TALER_TESTING_prepare_exchange (CONFIG_FILE, + GNUNET_YES, + &ec)) + { + case GNUNET_SYSERR: + GNUNET_break (0); + return 1; + case GNUNET_NO: + return 77; + case GNUNET_OK: + if (NULL == (merchantd = + TALER_TESTING_run_merchant (CONFIG_FILE, + merchant_url))) + { + GNUNET_break (0); + return 1; + } + if (NULL == (anastasisd = + ANASTASIS_TESTING_run_anastasis (CONFIG_FILE, + anastasis_url))) + { + GNUNET_break (0); + GNUNET_OS_process_kill (merchantd, + SIGTERM); + GNUNET_OS_process_wait (merchantd); + GNUNET_OS_process_destroy (merchantd); + + return 1; + } + ret = TALER_TESTING_setup_with_exchange (&run, + NULL, + CONFIG_FILE); + + GNUNET_OS_process_kill (merchantd, + SIGTERM); + GNUNET_OS_process_kill (anastasisd, + SIGTERM); + GNUNET_OS_process_wait (merchantd); + GNUNET_OS_process_wait (anastasisd); + GNUNET_OS_process_destroy (merchantd); + GNUNET_OS_process_destroy (anastasisd); + GNUNET_free (merchant_url); + GNUNET_free (anastasis_url); + + if (GNUNET_OK != ret) + return 1; + break; + default: + GNUNET_break (0); + return 1; + } + return 0; +} + + +/* end of test_anastasis.c */ diff --git a/src/testing/test_anastasis_api.c b/src/testing/test_anastasis_api.c new file mode 100644 index 0000000..db18b41 --- /dev/null +++ b/src/testing/test_anastasis_api.c @@ -0,0 +1,421 @@ +/* + This file is part of Anastasis + Copyright (C) 2020, 2021 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/test_anastasis_api.c + * @brief testcase to test anastasis' HTTP API interface + * @author Christian Grothoff + * @author Dennis Neufeld + * @author Dominik Meister + */ +#include "platform.h" +#include "anastasis_testing_lib.h" +#include <taler/taler_merchant_testing_lib.h> + + +/** + * Configuration file we use. One (big) configuration is used + * for the various components for this test. + */ +#define CONFIG_FILE "test_anastasis_api.conf" + +/** + * Exchange base URL. Could also be taken from config. + */ +#define EXCHANGE_URL "http://localhost:8081/" + +/** + * Account number of the exchange at the bank. + */ +#define EXCHANGE_ACCOUNT_NAME "2" + +/** + * Account number of some user. + */ +#define USER_ACCOUNT_NAME "62" + +/** + * Account number used by the merchant + */ +#define MERCHANT_ACCOUNT_NAME "3" + +/** + * Configuration of the bank. + */ +static struct TALER_TESTING_BankConfiguration bc; + +/** + * Configuration of the exchange. + */ +static struct TALER_TESTING_ExchangeConfiguration ec; + +/** + * Payto URI of the customer (payer). + */ +static char *payer_payto; + +/** + * Payto URI of the exchange (escrow account). + */ +static char *exchange_payto; + +/** + * Payto URI of the merchant (receiver). + */ +static char *merchant_payto; + +/** + * Merchant base URL. + */ +static char *merchant_url; + +/** + * Anastasis base URL. + */ +static char *anastasis_url; + +/** + * Merchant process. + */ +static struct GNUNET_OS_Process *merchantd; + +/** + * Anastasis process. + */ +static struct GNUNET_OS_Process *anastasisd; + +/** + * Name of the file for exchanging the secret. + */ +static char *file_secret; + +/** + * Execute the taler-exchange-wirewatch command with our configuration + * file. + * + * @param label label to use for the command. + */ +static struct TALER_TESTING_Command +cmd_exec_wirewatch (char *label) +{ + return TALER_TESTING_cmd_exec_wirewatch (label, + CONFIG_FILE); +} + + +/** + * Run wire transfer of funds from some user's account to the + * exchange. + * + * @param label label to use for the command. + * @param amount amount to transfer, i.e. "EUR:1" + * @param url exchange_url + */ +static struct TALER_TESTING_Command +cmd_transfer_to_exchange (const char *label, + const char *amount) +{ + return TALER_TESTING_cmd_admin_add_incoming (label, + amount, + &bc.exchange_auth, + payer_payto); +} + + +/** + * Main function that will tell the interpreter what commands to run. + * + * @param cls closure + */ +static void +run (void *cls, + struct TALER_TESTING_Interpreter *is) +{ + struct TALER_TESTING_Command withdraw[] = { + cmd_transfer_to_exchange ("create-reserve-1", + "EUR:10.02"), + cmd_exec_wirewatch ("wirewatch-1"), + TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-1", + "create-reserve-1", + "EUR:5", + MHD_HTTP_OK), + TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-2", + "create-reserve-1", + "EUR:5", + MHD_HTTP_OK), + TALER_TESTING_cmd_status ("withdraw-status-1", + "create-reserve-1", + "EUR:0", + MHD_HTTP_OK), + TALER_TESTING_cmd_end () + }; + + struct TALER_TESTING_Command policy[] = { + ANASTASIS_TESTING_cmd_policy_store ("policy-store-1", + anastasis_url, + NULL /* prev upload */, + MHD_HTTP_PAYMENT_REQUIRED, + ANASTASIS_TESTING_PSO_NONE, + "Test-1", + strlen ("Test-1")), + /* what would we have to pay? */ + TALER_TESTING_cmd_merchant_claim_order ("fetch-proposal", + merchant_url, + MHD_HTTP_OK, + "policy-store-1", + NULL), + /* make the payment */ + TALER_TESTING_cmd_merchant_pay_order ("pay-account", + merchant_url, + MHD_HTTP_OK, + "fetch-proposal", + "withdraw-coin-1", + "EUR:5", + "EUR:4.99", /* must match ANNUAL_FEE in config! */ + NULL), + ANASTASIS_TESTING_cmd_policy_store ("policy-store-2", + anastasis_url, + "policy-store-1", + MHD_HTTP_NO_CONTENT, + ANASTASIS_TESTING_PSO_NONE, + "Test-1", + strlen ("Test-1")), + ANASTASIS_TESTING_cmd_policy_lookup ("policy-lookup-1", + anastasis_url, + MHD_HTTP_OK, + "policy-store-2"), + TALER_TESTING_cmd_end () + }; + + struct TALER_TESTING_Command truth[] = { + ANASTASIS_TESTING_cmd_truth_question ( + "truth-store-1", + anastasis_url, + NULL, + "The-Answer", + ANASTASIS_TESTING_TSO_NONE, + MHD_HTTP_NO_CONTENT), + ANASTASIS_TESTING_cmd_keyshare_lookup ( + "keyshare-lookup-1", + anastasis_url, + "The-Answer", + NULL, /* payment ref */ + "truth-store-1", + 0, + ANASTASIS_KSD_SUCCESS), + ANASTASIS_TESTING_cmd_truth_store ( + "truth-store-2", + anastasis_url, + NULL, + "file", + "text/plain", + strlen (file_secret), + file_secret, + ANASTASIS_TESTING_TSO_NONE, + MHD_HTTP_NO_CONTENT), + ANASTASIS_TESTING_cmd_keyshare_lookup ( + "challenge-fail-1", + anastasis_url, + "Wrong-Answer", + NULL, + "truth-store-1", + 0, + ANASTASIS_KSD_INVALID_ANSWER), + ANASTASIS_TESTING_cmd_keyshare_lookup ( + "file-challenge-run-1", + anastasis_url, + NULL, /* no answer */ + NULL, /* payment ref */ + "truth-store-2", /* upload ref */ + 0, + ANASTASIS_KSD_PAYMENT_REQUIRED), + /* what would we have to pay? */ + TALER_TESTING_cmd_merchant_claim_order ("fetch-proposal-2", + merchant_url, + MHD_HTTP_OK, + "file-challenge-run-1", + NULL), + /* make the payment */ + TALER_TESTING_cmd_merchant_pay_order ("pay-account-2", + merchant_url, + MHD_HTTP_OK, + "fetch-proposal-2", + "withdraw-coin-2", + "EUR:1.01", + "EUR:1", + NULL), + + ANASTASIS_TESTING_cmd_keyshare_lookup ( + "file-challenge-run-2", + anastasis_url, + NULL, /* no answer */ + "file-challenge-run-1", /* payment ref */ + "truth-store-2", + 0, + ANASTASIS_KSD_INVALID_ANSWER), + ANASTASIS_TESTING_cmd_keyshare_lookup ( + "file-challenge-run-3", + anastasis_url, + "file-challenge-run-2", /* answer */ + "file-challenge-run-1", /* payment ref */ + "truth-store-2", + 1, + ANASTASIS_KSD_SUCCESS), + TALER_TESTING_cmd_end () + }; + + struct TALER_TESTING_Command commands[] = { + /* general setup */ + TALER_TESTING_cmd_auditor_add ("add-auditor-OK", + MHD_HTTP_NO_CONTENT, + false), + TALER_TESTING_cmd_wire_add ("add-wire-account", + "payto://x-taler-bank/localhost/2", + MHD_HTTP_NO_CONTENT, + false), + TALER_TESTING_cmd_exec_offline_sign_keys ("offline-sign-future-keys", + CONFIG_FILE), + TALER_TESTING_cmd_exec_offline_sign_fees ("offline-sign-fees", + CONFIG_FILE, + "EUR:0.01", + "EUR:0.01"), + TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys", + 1), + TALER_TESTING_cmd_merchant_post_instances ("instance-create-default", + merchant_url, + "default", + merchant_payto, + "EUR", + MHD_HTTP_NO_CONTENT), + ANASTASIS_TESTING_cmd_config ("salt-request-1", + anastasis_url, + MHD_HTTP_OK), + TALER_TESTING_cmd_batch ("withdraw", + withdraw), + TALER_TESTING_cmd_batch ("policy", + policy), + TALER_TESTING_cmd_batch ("truth", + truth), + TALER_TESTING_cmd_end () + }; + + TALER_TESTING_run_with_fakebank (is, + commands, + bc.exchange_auth.wire_gateway_url); +} + + +int +main (int argc, + char *const *argv) +{ + int ret; + + /* These environment variables get in the way... */ + unsetenv ("XDG_DATA_HOME"); + unsetenv ("XDG_CONFIG_HOME"); + GNUNET_log_setup ("test-anastasis-api", + "DEBUG", + NULL); + if (GNUNET_OK != + TALER_TESTING_prepare_fakebank (CONFIG_FILE, + "exchange-account-exchange", + &bc)) + return 77; + { + char dir[] = "/tmp/test-anastasis-file-XXXXXX"; + + if (NULL == mkdtemp (dir)) + { + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, + "mkdtemp", + dir); + return 77; + } + GNUNET_asprintf (&file_secret, + "%s/.secret", + dir); + } + payer_payto = ("payto://x-taler-bank/localhost/" USER_ACCOUNT_NAME); + exchange_payto = ("payto://x-taler-bank/localhost/" EXCHANGE_ACCOUNT_NAME); + merchant_payto = ("payto://x-taler-bank/localhost/" MERCHANT_ACCOUNT_NAME); + if (NULL == + (merchant_url = TALER_TESTING_prepare_merchant (CONFIG_FILE))) + return 77; + TALER_TESTING_cleanup_files (CONFIG_FILE); + + if (NULL == + (anastasis_url = ANASTASIS_TESTING_prepare_anastasis (CONFIG_FILE))) + return 77; + TALER_TESTING_cleanup_files (CONFIG_FILE); + + switch (TALER_TESTING_prepare_exchange (CONFIG_FILE, + GNUNET_YES, + &ec)) + { + case GNUNET_SYSERR: + GNUNET_break (0); + return 1; + case GNUNET_NO: + return 77; + case GNUNET_OK: + if (NULL == (merchantd = + TALER_TESTING_run_merchant (CONFIG_FILE, + merchant_url))) + { + GNUNET_break (0); + return 1; + } + if (NULL == (anastasisd = + ANASTASIS_TESTING_run_anastasis (CONFIG_FILE, + anastasis_url))) + { + GNUNET_break (0); + GNUNET_OS_process_kill (merchantd, + SIGTERM); + GNUNET_OS_process_wait (merchantd); + GNUNET_OS_process_destroy (merchantd); + return 1; + } + ret = TALER_TESTING_setup_with_exchange (&run, + NULL, + CONFIG_FILE); + GNUNET_OS_process_kill (merchantd, + SIGTERM); + GNUNET_OS_process_kill (anastasisd, + SIGTERM); + GNUNET_OS_process_wait (merchantd); + GNUNET_OS_process_wait (anastasisd); + GNUNET_OS_process_destroy (merchantd); + GNUNET_OS_process_destroy (anastasisd); + GNUNET_free (merchant_url); + GNUNET_free (anastasis_url); + + if (GNUNET_OK != ret) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Test failed in interpreter\n"); + return 1; + } + break; + default: + GNUNET_break (0); + return 1; + } + return 0; +} + + +/* end of test_anastasis_api.c */ diff --git a/src/testing/test_anastasis_api.conf b/src/testing/test_anastasis_api.conf new file mode 100644 index 0000000..bde7ee1 --- /dev/null +++ b/src/testing/test_anastasis_api.conf @@ -0,0 +1,264 @@ +# This file is in the public domain. +# +[PATHS] +# Persistent data storage for the testcase +TALER_TEST_HOME = test_anastasis_api_home/ +TALER_RUNTIME_DIR = ${TMPDIR:-${TMP:-/tmp}}/${USER:-}/taler-system-runtime/ + +# Persistent data storage +TALER_DATA_HOME = $TALER_TEST_HOME/.local/share/taler/ + +# Configuration files +TALER_CONFIG_HOME = $TALER_TEST_HOME/.config/taler/ + +# Cached data, no big deal if lost +TALER_CACHE_HOME = $TALER_TEST_HOME/.cache/taler/ + +[taler] +# What currency do we use? +#currency = EUR +currency = EUR +#CURRENCY_ROUND_UNIT = EUR:0.01 +#CURRENCY_ROUND_UNIT = EUR:0.01 + +[taler-helper-crypto-rsa] +# Reduce from 1 year to speed up test +LOOKAHEAD_SIGN = 12 days + +[taler-helper-crypto-eddsa] +# Reduce from 1 year to speed up test +LOOKAHEAD_SIGN = 12 days +# Reduce from 12 weeks to ensure we have multiple +DURATION = 7 days + + +[bank] +HTTP_PORT = 8082 +#BASE_URL = https://bank.test.taler.net/ + +########################################## +# Configuration for Anastasis # +########################################## + +[anastasis] +PORT = 8086 + +DB = postgres + +BUSINESS_NAME = "Checker's Test Inc." + +# Upload limit +UPLOAD_LIMIT_MB = 1 + +ANNUAL_POLICY_UPLOAD_LIMIT = 64 + +INSURANCE = EUR:0 + +SERVER_SALT = salty + +# Base URL of anastasis. +# BASE_URL = http://localhost:8086/ + +# Where does our payment backend run? Must match PORT under [merchant] +PAYMENT_BACKEND_URL = http://localhost:8080/ + +# Annual fee we charge. +#ANNUAL_FEE = EUR:4.99 +ANNUAL_FEE = EUR:4.99 + +TRUTH_UPLOAD_FEE = EUR:0.0 + +# Authentication costs +[authorization-question] +# Cost of authentication by question +COST = EUR:0 + +[authorization-file] +# Cost of authentication by file (only for testing purposes) +COST = EUR:1 + +[authorization-email] +# Cost of authentication by E-Mail +COST = EUR:0 + +[authorization-sms] +# Cost of authentication by SMS +COST = EUR:0 + +# Command which is executed for the sms authentication +COMMAND = ./sms_authentication.sh + + + + +# This specifies which database the postgres backend uses. +[stasis-postgres] +CONFIG = postgres:///anastasischeck + +########################################## +# Configuration for the merchant backend # +########################################## + +[merchant] + +# Which port do we run the backend on? (HTTP server) +PORT = 8080 + +# How quickly do we want the exchange to send us our money? +# Used only if the frontend does not specify a value. +WIRE_TRANSFER_DELAY = 0 s + +# Which plugin (backend) do we use for the DB. +DB = postgres + +# Default choice for maximum wire fee. +DEFAULT_MAX_WIRE_FEE = EUR:0.10 + +# Default choice for maximum deposit fee. +DEFAULT_MAX_DEPOSIT_FEE = EUR:0.10 + + +# This specifies which database the postgres backend uses. +[merchantdb-postgres] +CONFIG = postgres:///talercheck + +# Sections starting with "exchange-" specify trusted exchanges +# (by the merchant) +[merchant-exchange-default] +MASTER_KEY = T1VVFQZZARQ1CMF4BN58EE7SKTW5AV2BS18S87ZEGYS4S29J6DNG +EXCHANGE_BASE_URL = http://localhost:8081/ +#MASTER_KEY = DY95EXAHQ2BKM2WK9YHZHYG1R7PPMMJPY14FNGP662DAKE35AKQG +#EXCHANGE_BASE_URL = https://exchange.test.taler.net/ +#CURRENCY = EUR +CURRENCY = EUR + +# only fixes skips. +[auditor] +BASE_URL = http://the.auditor/ +#BASE_URL = https://auditor.test.taler.net/ +#AUDITOR_KEY = DSDASDXAMDAARMNAD53ZA4AFAHA2QADAMAHHASWDAWXN84SDAA11 +# If currency does not match [TALER] section, the auditor +# will be ignored! +CURRENCY = EUR + +# Where do we store the auditor's private key? +AUDITOR_PRIV_FILE = ${TALER_DATA_HOME}/auditor/offline-keys/auditor.priv + +# Auditors must be in sections "auditor-", the rest of the section +# name could be anything. +[auditor-ezb] +# Informal name of the auditor. Just for the user. +NAME = European Central Bank + +# URL of the auditor (especially for in the future, when the +# auditor offers an automated issue reporting system). +# Not really used today. +URL = http://taler.ezb.eu/ + +# This is the important bit: the signing key of the auditor. +PUBLIC_KEY = 9QXF7XY7E9VPV47B5Z806NDFSX2VJ79SVHHD29QEQ3BG31ANHZ60 + +# Which currency is this auditor trusted for? +CURRENCY = EUR + + +################################################### +# Configuration for the exchange for the testcase # +################################################### + +[exchange] +# How to access our database +DB = postgres + +# HTTP port the exchange listens to +PORT = 8081 + +# how long are the signatures with the signkey valid? +SIGNKEY_LEGAL_DURATION = 2 years + +# Our public key +MASTER_PUBLIC_KEY = T1VVFQZZARQ1CMF4BN58EE7SKTW5AV2BS18S87ZEGYS4S29J6DNG + +# Base URL of the exchange. +BASE_URL = "http://localhost:8081/" +#BASE_URL = https://exchange.test.taler.net/ + +KEYDIR = ${TALER_DATA_HOME}/exchange/live-keys/ + +REVOCATION_DIR = ${TALER_DATA_HOME}/exchange/revocations/ + + +# Network configuration for the normal API/service HTTP server +# serve via tcp socket (on PORT) +SERVE = tcp + +[exchange-offline] + +# Where do we store the offline master private key of the exchange? +MASTER_PRIV_FILE = ${TALER_DATA_HOME}/exchange/offline-keys/master.priv + +# Where do we store the TOFU key material? +SECM_TOFU_FILE = ${TALER_DATA_HOME}/exchange/offline-keys/secm_tofus.pub + + +[exchangedb-postgres] +CONFIG = "postgres:///talercheck" + +[auditordb-postgres] +CONFIG = "postgres:///talercheck" + +# Account of the EXCHANGE +[exchange-account-exchange] +# What is the exchange's bank account (with the "Taler Bank" demo system)? +PAYTO_URI = "payto://x-taler-bank/localhost:8082/2" + +WIRE_GATEWAY_URL = "http://localhost:8082/2/" +WIRE_GATEWAY_AUTH_METHOD = NONE + +ENABLE_DEBIT = YES +ENABLE_CREDIT = YES + + +[coin_eur_ct_1] +value = EUR:0.01 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = EUR:0.00 +fee_deposit = EUR:0.00 +fee_refresh = EUR:0.01 +fee_refund = EUR:0.01 +rsa_keysize = 1024 + +[coin_eur_ct_10] +value = EUR:0.10 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = EUR:0.01 +fee_deposit = EUR:0.01 +fee_refresh = EUR:0.03 +fee_refund = EUR:0.01 +rsa_keysize = 1024 + +[coin_eur_1] +value = EUR:1 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = EUR:0.01 +fee_deposit = EUR:0.01 +fee_refresh = EUR:0.03 +fee_refund = EUR:0.01 +rsa_keysize = 1024 + +[coin_eur_5] +value = EUR:5 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = EUR:0.01 +fee_deposit = EUR:0.01 +fee_refresh = EUR:0.03 +fee_refund = EUR:0.01 +rsa_keysize = 1024 diff --git a/src/testing/test_anastasis_api_home/.config/taler/exchange/account-2.json b/src/testing/test_anastasis_api_home/.config/taler/exchange/account-2.json new file mode 100644 index 0000000..f798275 --- /dev/null +++ b/src/testing/test_anastasis_api_home/.config/taler/exchange/account-2.json @@ -0,0 +1,3 @@ +{ + "payto_uri": "payto://x-taler-bank/localhost:8082/2", + "master_sig": "AM32QB4RYMWK548PE63PJXJMWSA001TFFWTZZPSSD8HQ8JE4D5V5X8WTSYSX59ANF4YRTRMF5Q4Q12CE2KTA8KQ03CM11YDTK75SJ20"} diff --git a/src/testing/test_anastasis_api_home/.config/taler/merchant/account-3.json b/src/testing/test_anastasis_api_home/.config/taler/merchant/account-3.json new file mode 100644 index 0000000..016e133 --- /dev/null +++ b/src/testing/test_anastasis_api_home/.config/taler/merchant/account-3.json @@ -0,0 +1 @@ +{"salt":"ZSHKZ4DRFMFRFBMB10BX8M1GD16AZNG639AY8QMW26XBGECQRS1H7H8CQ4WETHT66PG99CYBVGFRKJ7ZENEDJJ4E0X0JHRY1QKPQ3W0","payto_uri":"payto://x-taler-bank/localhost:8082/3"} diff --git a/src/testing/test_anastasis_api_home/.config/taler/merchant/default.priv b/src/testing/test_anastasis_api_home/.config/taler/merchant/default.priv new file mode 100644 index 0000000..3ed8c04 --- /dev/null +++ b/src/testing/test_anastasis_api_home/.config/taler/merchant/default.priv @@ -0,0 +1 @@ +<!ÔÇ»³¶l¶Ú&…|ÇÆËSb¿¹0)hó8ö
\ No newline at end of file diff --git a/src/testing/test_anastasis_api_home/.config/taler/merchant/dtip.priv b/src/testing/test_anastasis_api_home/.config/taler/merchant/dtip.priv new file mode 100644 index 0000000..a72136d --- /dev/null +++ b/src/testing/test_anastasis_api_home/.config/taler/merchant/dtip.priv @@ -0,0 +1 @@ +æÍëÕð*¾šiWªLØ(ß:ZOtG…s41æ
\ No newline at end of file diff --git a/src/testing/test_anastasis_api_home/.config/taler/merchant/nulltip.priv b/src/testing/test_anastasis_api_home/.config/taler/merchant/nulltip.priv new file mode 100644 index 0000000..fe56b97 --- /dev/null +++ b/src/testing/test_anastasis_api_home/.config/taler/merchant/nulltip.priv @@ -0,0 +1 @@ +ç§l9h‡[èYÌÊ›‘ô"h1Àø—–žsÿÊB;¤Ð
\ No newline at end of file diff --git a/src/testing/test_anastasis_api_home/.config/taler/merchant/reserve/dtip.priv b/src/testing/test_anastasis_api_home/.config/taler/merchant/reserve/dtip.priv new file mode 100644 index 0000000..a5f982f --- /dev/null +++ b/src/testing/test_anastasis_api_home/.config/taler/merchant/reserve/dtip.priv @@ -0,0 +1 @@ +ò^Sz™êƒ5?éÌ<e?Ì[ÔY•ãs¨Âœ¿ûC$
\ No newline at end of file diff --git a/src/testing/test_anastasis_api_home/.config/taler/merchant/reserve/nulltip.priv b/src/testing/test_anastasis_api_home/.config/taler/merchant/reserve/nulltip.priv new file mode 100644 index 0000000..8b9f09c --- /dev/null +++ b/src/testing/test_anastasis_api_home/.config/taler/merchant/reserve/nulltip.priv @@ -0,0 +1 @@ +I4Z‹‹JxžuRFSþEJßãÙÚÍf7?0W
\ No newline at end of file diff --git a/src/testing/test_anastasis_api_home/.config/taler/merchant/reserve/tip.priv b/src/testing/test_anastasis_api_home/.config/taler/merchant/reserve/tip.priv new file mode 100644 index 0000000..16fecd6 --- /dev/null +++ b/src/testing/test_anastasis_api_home/.config/taler/merchant/reserve/tip.priv @@ -0,0 +1 @@ +òœÓËÌŒò?SwfJ¯")Dù²¶whšiôxK
\ No newline at end of file diff --git a/src/testing/test_anastasis_api_home/.config/taler/merchant/tip.priv b/src/testing/test_anastasis_api_home/.config/taler/merchant/tip.priv Binary files differnew file mode 100644 index 0000000..951d893 --- /dev/null +++ b/src/testing/test_anastasis_api_home/.config/taler/merchant/tip.priv diff --git a/src/testing/test_anastasis_api_home/.config/taler/merchant/tor.priv b/src/testing/test_anastasis_api_home/.config/taler/merchant/tor.priv Binary files differnew file mode 100644 index 0000000..007b02c --- /dev/null +++ b/src/testing/test_anastasis_api_home/.config/taler/merchant/tor.priv diff --git a/src/testing/test_anastasis_api_home/.config/taler/test.json b/src/testing/test_anastasis_api_home/.config/taler/test.json new file mode 100644 index 0000000..74cdc92 --- /dev/null +++ b/src/testing/test_anastasis_api_home/.config/taler/test.json @@ -0,0 +1,8 @@ +{ + "name": "The exchange", + "account_number": 3, + "bank_url": "http://localhost:8083/", + "salt": "6259MV4W9V8D2A75RSGGPKYHQRXRPQZ33EBG263JZRJ6SA5HK0RRKHV70TNA1RVRG77M57CCFVSK2B0EJN3SR8S21F0ZX2MR9DNVG50", + "type": "test", + "sig": "8C3D3J816S29AA2AJ7P9TS6W13KFNFS2RCVYJEWRBNHRRMTTRAWKY7WA1N3G54E4K3XAC2HN6JDHS42TWR5315J34JHHCKV618K221G" +} diff --git a/src/testing/test_anastasis_api_home/.local/share/taler/exchange/offline-keys/master.priv b/src/testing/test_anastasis_api_home/.local/share/taler/exchange/offline-keys/master.priv new file mode 100644 index 0000000..c20942d --- /dev/null +++ b/src/testing/test_anastasis_api_home/.local/share/taler/exchange/offline-keys/master.priv @@ -0,0 +1 @@ +åÊk;d³_Uû}£A.wÔ"!Gûçv_m "_ò
\ No newline at end of file diff --git a/src/testing/test_anastasis_api_home/.local/share/taler/merchant/merchant.priv b/src/testing/test_anastasis_api_home/.local/share/taler/merchant/merchant.priv new file mode 100644 index 0000000..fd6e5f7 --- /dev/null +++ b/src/testing/test_anastasis_api_home/.local/share/taler/merchant/merchant.priv @@ -0,0 +1 @@ +¶ù,åY%–FF<ßþR˜‰9ϳ5„¬v\þš×k4«6
\ No newline at end of file diff --git a/src/testing/testing_api_cmd_config.c b/src/testing/testing_api_cmd_config.c new file mode 100644 index 0000000..8906261 --- /dev/null +++ b/src/testing/testing_api_cmd_config.c @@ -0,0 +1,206 @@ +/* + This file is part of TALER + Copyright (C) 2019, 2021 Taler Systems SA + + TALER 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 + Foundation; either version 3, or (at your option) any later version. + + TALER 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +*/ +/** + * @file lib/testing_api_cmd_config.c + * @brief command to obtain the configuration of an anastasis backend service. + * @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 "config" CMD. + */ +struct ConfigState +{ + /** + * 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 /config GET operation handle. + */ + struct ANASTASIS_ConfigOperation *so; + + /** + * The salt value from server. + */ + struct ANASTASIS_CRYPTO_ProviderSaltP salt; +}; + + +/** + * Function called with the results of a #ANASTASIS_config(). + * + * @param cls closure + * @param http_status HTTP status of the request + * @param config config from the server + */ +static void +config_cb (void *cls, + unsigned int http_status, + const struct ANASTASIS_Config *config) +{ + struct ConfigState *ss = cls; + + ss->so = NULL; + if (http_status != ss->http_status) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected response code %u to command %s in %s:%u\n", + http_status, + ss->is->commands[ss->is->ip].label, + __FILE__, + __LINE__); + TALER_TESTING_interpreter_fail (ss->is); + return; + } + if (NULL == config) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Config is NULL, command %s in %s:%u\n", + ss->is->commands[ss->is->ip].label, + __FILE__, + __LINE__); + TALER_TESTING_interpreter_fail (ss->is); + return; + } + ss->salt = config->salt; + TALER_TESTING_interpreter_next (ss->is); +} + + +/** + * Run a "config" CMD. + * + * @param cls closure. + * @param cmd command currently being run. + * @param is interpreter state. + */ +static void +config_run (void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is) +{ + struct ConfigState *ss = cls; + + ss->is = is; + ss->so = ANASTASIS_get_config (is->ctx, + ss->anastasis_url, + &config_cb, + ss); + if (NULL == ss->so) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ss->is); + return; + } +} + + +/** + * Free the state of a "config" CMD, and possibly + * cancel it if it did not complete. + * + * @param cls closure. + * @param cmd command being freed. + */ +static void +config_cleanup (void *cls, + const struct TALER_TESTING_Command *cmd) +{ + struct ConfigState *ss = cls; + + if (NULL != ss->so) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Command '%s' did not complete (config)\n", + cmd->label); + ANASTASIS_config_cancel (ss->so); + ss->so = NULL; + } + GNUNET_free (ss); +} + + +/** + * Offer internal data to other commands. + * + * @param cls closure + * @param ret[out] result (could be anything) + * @param trait name of the trait + * @param index index number of the object to extract. + * @return #GNUNET_OK on success + */ +static int +config_traits (void *cls, + const void **ret, + const char *trait, + unsigned int index) +{ + struct ConfigState *ss = cls; + + struct TALER_TESTING_Trait traits[] = { + ANASTASIS_TESTING_make_trait_salt (0, + &ss->salt), + TALER_TESTING_trait_end () + }; + + return TALER_TESTING_get_trait (traits, + ret, + trait, + index); +} + + +struct TALER_TESTING_Command +ANASTASIS_TESTING_cmd_config (const char *label, + const char *anastasis_url, + unsigned int http_status) +{ + struct ConfigState *ss; + + ss = GNUNET_new (struct ConfigState); + ss->http_status = http_status; + ss->anastasis_url = anastasis_url; + { + struct TALER_TESTING_Command cmd = { + .cls = ss, + .label = label, + .run = &config_run, + .cleanup = &config_cleanup, + .traits = &config_traits + }; + + return cmd; + } +} diff --git a/src/testing/testing_api_cmd_keyshare_lookup.c b/src/testing/testing_api_cmd_keyshare_lookup.c new file mode 100644 index 0000000..895d321 --- /dev/null +++ b/src/testing/testing_api_cmd_keyshare_lookup.c @@ -0,0 +1,465 @@ +/* + 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/anastasis_api_keyshare_lookup.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> +#include <taler/taler_merchant_service.h> + + +/** + * State for a "keyshare lookup" CMD. + */ +struct KeyShareLookupState +{ + /** + * The interpreter state. + */ + struct TALER_TESTING_Interpreter *is; + + /** + * URL of the anastasis backend. + */ + const char *anastasis_url; + + /** + * Expected status code. + */ + enum ANASTASIS_KeyShareDownloadStatus expected_ksdd; + + /** + * The /truth GET operation handle. + */ + struct ANASTASIS_KeyShareLookupOperation *kslo; + + /** + * answer to a challenge + */ + const char *answer; + + /** + * Reference to upload command we expect to lookup. + */ + const char *upload_reference; + + /** + * Reference to upload command we expect to lookup. + */ + const char *payment_reference; + + /** + * Payment secret requested by the service, if any. + */ + struct ANASTASIS_PaymentSecretP payment_secret_response; + + /** + * Taler-URI with payment request, if any. + */ + char *pay_uri; + + /** + * Order ID for payment request, if any. + */ + char *order_id; + + /** + * Redirect-URI for challenge, if any. + */ + char *redirect_uri; + + /** + * "code" returned by service, if any. + */ + char *code; + + /** + * "instructions" for how to solve the challenge as returned by service, if any. + */ + char *instructions; + + /** + * Name of the file where the service will write the challenge, if method is "file". + * Otherwise NULL. + */ + char *filename; + + /** + * Mode for the lookup(0 = question, 1 = code based) + */ + int lookup_mode; + +}; + + +static void +keyshare_lookup_cb (void *cls, + const struct ANASTASIS_KeyShareDownloadDetails *dd) +{ + struct KeyShareLookupState *ksls = cls; + + ksls->kslo = NULL; + if (dd->status != ksls->expected_ksdd) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected response code %u to command %s in %s:%u\n", + dd->status, + ksls->is->commands[ksls->is->ip].label, + __FILE__, + __LINE__); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } + switch (dd->status) + { + case ANASTASIS_KSD_SUCCESS: + break; + case ANASTASIS_KSD_PAYMENT_REQUIRED: + ksls->pay_uri = GNUNET_strdup (dd->details.payment_required.taler_pay_uri); + ksls->payment_secret_response = dd->details.payment_required.payment_secret; + { + struct TALER_MERCHANT_PayUriData pd; + + if (GNUNET_OK != + TALER_MERCHANT_parse_pay_uri (ksls->pay_uri, + &pd)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } + ksls->order_id = GNUNET_strdup (pd.order_id); + TALER_MERCHANT_parse_pay_uri_free (&pd); + } + + break; + case ANASTASIS_KSD_INVALID_ANSWER: + if (ksls->filename) + { + FILE *file; + char code[22]; + + file = fopen (ksls->filename, + "r"); + if (NULL == file) + { + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, + "open", + ksls->filename); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } + if (0 == fscanf (file, + "%21s", + code)) + { + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, + "fscanf", + ksls->filename); + GNUNET_break (0 == fclose (file)); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } + GNUNET_break (0 == fclose (file)); + ksls->code = GNUNET_strdup (code); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Read code `%s'\n", + code); + } + else + { + ksls->instructions = GNUNET_strndup ( + dd->details.open_challenge.body, + dd->details.open_challenge.body_size); + } + break; + case ANASTASIS_KSD_REDIRECT_FOR_AUTHENTICATION: + ksls->redirect_uri = GNUNET_strdup (dd->details.redirect_url); + break; + case ANASTASIS_KSD_SERVER_ERROR: + break; + case ANASTASIS_KSD_CLIENT_FAILURE: + break; + case ANASTASIS_KSD_TRUTH_UNKNOWN: + break; + case ANASTASIS_KSD_RATE_LIMIT_EXCEEDED: + break; + } + TALER_TESTING_interpreter_next (ksls->is); +} + + +static void +keyshare_lookup_run (void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is) +{ + struct KeyShareLookupState *ksls = cls; + const struct ANASTASIS_CRYPTO_TruthKeyP *truth_key; + const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid; + const struct ANASTASIS_PaymentSecretP *payment_secret; + const char *answer; + + ksls->is = is; + if (NULL == ksls->upload_reference) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } + { + const struct TALER_TESTING_Command *upload_cmd; + + upload_cmd = TALER_TESTING_interpreter_lookup_command ( + is, + ksls->upload_reference); + if (NULL == upload_cmd) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } + { + const char *fn; + + if (GNUNET_OK != + TALER_TESTING_get_trait_string (upload_cmd, + 0, + &fn)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } + if (NULL != fn) + ksls->filename = GNUNET_strdup (fn); + } + if (GNUNET_OK != + ANASTASIS_TESTING_get_trait_truth_uuid (upload_cmd, + 0, + &truth_uuid)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } + if (NULL == truth_uuid) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } + if (GNUNET_OK != + ANASTASIS_TESTING_get_trait_truth_key (upload_cmd, + 0, + &truth_key)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } + if (NULL == truth_key) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } + } + + if (ksls->lookup_mode == 1) + { + const struct TALER_TESTING_Command *download_cmd; + + download_cmd = TALER_TESTING_interpreter_lookup_command (is, + ksls->answer); + if (NULL == download_cmd) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } + if (GNUNET_OK != + ANASTASIS_TESTING_get_trait_code (download_cmd, + 0, + &answer)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } + if (NULL == answer) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } + } + else + { + /* answer is the answer */ + answer = ksls->answer; + } + + if (NULL != ksls->payment_reference) + { + const struct TALER_TESTING_Command *payment_cmd; + + payment_cmd = TALER_TESTING_interpreter_lookup_command + (is, + ksls->payment_reference); + if (GNUNET_OK != + ANASTASIS_TESTING_get_trait_payment_secret (payment_cmd, + 0, + &payment_secret)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } + } + else + { + payment_secret = NULL; + } + + { + struct GNUNET_HashCode h_answer; + + if (NULL != answer) + GNUNET_CRYPTO_hash (answer, + strlen (answer), + &h_answer); + ksls->kslo = ANASTASIS_keyshare_lookup (is->ctx, + ksls->anastasis_url, + truth_uuid, + truth_key, + payment_secret, + GNUNET_TIME_UNIT_ZERO, + (NULL != answer) + ? &h_answer + : NULL, + &keyshare_lookup_cb, + ksls); + } + if (NULL == ksls->kslo) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } +} + + +static void +keyshare_lookup_cleanup (void *cls, + const struct TALER_TESTING_Command *cmd) +{ + struct KeyShareLookupState *ksls = cls; + + if (NULL != ksls->kslo) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Command '%s' did not complete (keyshare lookup)\n", + cmd->label); + ANASTASIS_keyshare_lookup_cancel (ksls->kslo); + ksls->kslo = NULL; + } + GNUNET_free (ksls->pay_uri); + GNUNET_free (ksls->order_id); + GNUNET_free (ksls->code); + GNUNET_free (ksls->instructions); + GNUNET_free (ksls->redirect_uri); + GNUNET_free (ksls); +} + + +/** + * Offer internal data to other commands. + * + * @param cls closure + * @param[out] ret result (could be anything) + * @param[out] trait name of the trait + * @param index index number of the object to extract. + * @return #GNUNET_OK on success + */ +static int +keyshare_lookup_traits (void *cls, + const void **ret, + const char *trait, + unsigned int index) +{ + struct KeyShareLookupState *ksls = cls; + struct TALER_TESTING_Trait traits[] = { + ANASTASIS_TESTING_make_trait_payment_secret (0, + &ksls->payment_secret_response), + TALER_TESTING_make_trait_url (TALER_TESTING_UT_TALER_URL, + ksls->pay_uri), + TALER_TESTING_make_trait_order_id (0, + ksls->order_id), + ANASTASIS_TESTING_make_trait_code (0, + ksls->code), + TALER_TESTING_trait_end () + }; + + return TALER_TESTING_get_trait (traits, + ret, + trait, + index); +} + + +struct TALER_TESTING_Command +ANASTASIS_TESTING_cmd_keyshare_lookup ( + const char *label, + const char *anastasis_url, + const char *answer, + const char *payment_ref, + const char *upload_ref, + int lookup_mode, + enum ANASTASIS_KeyShareDownloadStatus ksdd) +{ + struct KeyShareLookupState *ksls; + + GNUNET_assert (NULL != upload_ref); + ksls = GNUNET_new (struct KeyShareLookupState); + ksls->expected_ksdd = ksdd; + ksls->anastasis_url = anastasis_url; + ksls->upload_reference = upload_ref; + ksls->payment_reference = payment_ref; + ksls->answer = answer; + ksls->lookup_mode = lookup_mode; + { + struct TALER_TESTING_Command cmd = { + .cls = ksls, + .label = label, + .run = &keyshare_lookup_run, + .cleanup = &keyshare_lookup_cleanup, + .traits = &keyshare_lookup_traits + }; + + return cmd; + } +} + + +/* end of testing_api_cmd_keyshare_lookup.c */ diff --git a/src/testing/testing_api_cmd_policy_lookup.c b/src/testing/testing_api_cmd_policy_lookup.c new file mode 100644 index 0000000..e97f746 --- /dev/null +++ b/src/testing/testing_api_cmd_policy_lookup.c @@ -0,0 +1,267 @@ +/* + 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_policy_lookup.c + * @brief command to execute the anastasis backend service. + * @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 "policy lookup" CMD. + */ +struct PolicyLookupState +{ + /** + * The interpreter state. + */ + struct TALER_TESTING_Interpreter *is; + + /** + * Eddsa Publickey. + */ + struct ANASTASIS_CRYPTO_AccountPublicKeyP anastasis_pub; + + /** + * Hash of the upload (all zeros if there was no upload). + */ + const struct GNUNET_HashCode *upload_hash; + + /** + * URL of the anastasis backend. + */ + const char *anastasis_url; + + /** + * Expected status code. + */ + unsigned int http_status; + + /** + * Reference to upload command we expect to lookup. + */ + const char *upload_reference; + + /** + * The /policy GET operation handle. + */ + struct ANASTASIS_PolicyLookupOperation *plo; +}; + + +/** + * Function called with the results of a #ANASTASIS_lookup(). + * + * @param cls closure + * @param http_status HTTP status of the request + * @param ud details about the lookup operation + */ +static void +policy_lookup_cb (void *cls, + unsigned int http_status, + const struct ANASTASIS_DownloadDetails *dd) +{ + struct PolicyLookupState *pls = cls; + + pls->plo = NULL; + if (http_status != pls->http_status) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected response code %u to command %s in %s:%u\n", + http_status, + pls->is->commands[pls->is->ip].label, + __FILE__, + __LINE__); + TALER_TESTING_interpreter_fail (pls->is); + return; + } + if (NULL != pls->upload_reference) + { + if ( (MHD_HTTP_OK == http_status) && + (0 != GNUNET_memcmp (&dd->curr_policy_hash, + pls->upload_hash)) ) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (pls->is); + return; + } + } + TALER_TESTING_interpreter_next (pls->is); +} + + +/** + * Run a "policy lookup" CMD. + * + * @param cls closure. + * @param cmd command currently being run. + * @param is interpreter state. + */ +static void +policy_lookup_run (void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is) +{ + struct PolicyLookupState *pls = cls; + + pls->is = is; + if (NULL != pls->upload_reference) + { + const struct TALER_TESTING_Command *upload_cmd; + const struct ANASTASIS_CRYPTO_AccountPublicKeyP *anastasis_pub; + + upload_cmd = TALER_TESTING_interpreter_lookup_command + (is, + pls->upload_reference); + if (NULL == upload_cmd) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (pls->is); + return; + } + if (GNUNET_OK != + ANASTASIS_TESTING_get_trait_hash (upload_cmd, + ANASTASIS_TESTING_TRAIT_HASH_CURRENT, + &pls->upload_hash)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (pls->is); + return; + } + if (GNUNET_OK != + ANASTASIS_TESTING_get_trait_account_pub (upload_cmd, + 0, + &anastasis_pub)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (pls->is); + return; + } + pls->anastasis_pub = *anastasis_pub; + } + pls->plo = ANASTASIS_policy_lookup (is->ctx, + pls->anastasis_url, + &pls->anastasis_pub, + &policy_lookup_cb, + pls); + if (NULL == pls->plo) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (pls->is); + return; + } +} + + +/** + * Free the state of a "policy lookup" CMD, and possibly + * cancel it if it did not complete. + * + * @param cls closure. + * @param cmd command being freed. + */ +static void +policy_lookup_cleanup (void *cls, + const struct TALER_TESTING_Command *cmd) +{ + struct PolicyLookupState *pls = cls; + + if (NULL != pls->plo) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Command '%s' did not complete (policy lookup)\n", + cmd->label); + ANASTASIS_policy_lookup_cancel (pls->plo); + pls->plo = NULL; + } + GNUNET_free (pls); +} + + +/** + * Make the "policy lookup" command. + * + * @param label command label + * @param anastasis_url base URL of the ANASTASIS serving + * the policy store request. + * @param http_status expected HTTP status. + * @param upload_ref reference to upload command + * @return the command + */ +struct TALER_TESTING_Command +ANASTASIS_TESTING_cmd_policy_lookup (const char *label, + const char *anastasis_url, + unsigned int http_status, + const char *upload_ref) +{ + struct PolicyLookupState *pls; + + GNUNET_assert (NULL != upload_ref); + pls = GNUNET_new (struct PolicyLookupState); + pls->http_status = http_status; + pls->anastasis_url = anastasis_url; + pls->upload_reference = upload_ref; + { + struct TALER_TESTING_Command cmd = { + .cls = pls, + .label = label, + .run = &policy_lookup_run, + .cleanup = &policy_lookup_cleanup + }; + + return cmd; + } +} + + +/** + * Make the "policy lookup" command for a non-existent upload. + * + * @param label command label + * @param anastasis_url base URL of the ANASTASIS serving + * the policy lookup request. + * @return the command + */ +struct TALER_TESTING_Command +ANASTASIS_TESTING_cmd_policy_nx (const char *label, + const char *anastasis_url) +{ + struct PolicyLookupState *pls; + struct GNUNET_CRYPTO_EddsaPrivateKey priv; + + pls = GNUNET_new (struct PolicyLookupState); + pls->http_status = MHD_HTTP_NOT_FOUND; + pls->anastasis_url = anastasis_url; + GNUNET_CRYPTO_eddsa_key_create (&priv); + GNUNET_CRYPTO_eddsa_key_get_public (&priv, + &pls->anastasis_pub.pub); + { + struct TALER_TESTING_Command cmd = { + .cls = pls, + .label = label, + .run = &policy_lookup_run, + .cleanup = &policy_lookup_cleanup + }; + + return cmd; + } +} diff --git a/src/testing/testing_api_cmd_policy_store.c b/src/testing/testing_api_cmd_policy_store.c new file mode 100644 index 0000000..a8f0a70 --- /dev/null +++ b/src/testing/testing_api_cmd_policy_store.c @@ -0,0 +1,397 @@ +/* + This file is part of ANASTASIS + Copyright (C) 2014-2019 Taler Systems 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 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. If not, see + <http://www.gnu.org/licenses/> +*/ + +/** + * @file lib/testing_api_cmd_policy_store.c + * @brief command to execute the anastasis backend service. + * @author Christian Grothoff + * @author Dominik Meister + * @author Dennis Neufeld + */ + +#include "platform.h" +#include "anastasis_testing_lib.h" +#include <taler/taler_util.h> +#include <taler/taler_testing_lib.h> +#include <taler/taler_merchant_service.h> + + +/** + * State for a "policy store" CMD. + */ +struct PolicyStoreState +{ + /** + * Claim token we got back, if any. Otherwise all zeros. + */ + struct TALER_ClaimTokenP claim_token; + + /** + * The policy data. + */ + const void *recovery_data; + + /** + * Number of bytes in @e recovery_data + */ + size_t recovery_data_size; + + /** + * Expected status code. + */ + unsigned int http_status; + + /** + * Eddsa Publickey. + */ + struct ANASTASIS_CRYPTO_AccountPublicKeyP anastasis_pub; + + /** + * Eddsa Privatekey. + */ + struct ANASTASIS_CRYPTO_AccountPrivateKeyP anastasis_priv; + + /** + * Hash of uploaded data, used to verify the response. + */ + struct GNUNET_HashCode curr_hash; + + /** + * The /policy POST operation handle. + */ + struct ANASTASIS_PolicyStoreOperation *pso; + + /** + * The nonce. + */ + struct ANASTASIS_CRYPTO_NonceP nonce; + + /** + * URL of the anastasis backend. + */ + const char *anastasis_url; + + /** + * The interpreter state. + */ + struct TALER_TESTING_Interpreter *is; + + /** + * Previous upload, or NULL for none. Used to calculate what THIS + * upload is based on. + */ + const char *prev_upload; + + /** + * Payment order ID we are to provide in the request, or zero. + */ + struct ANASTASIS_PaymentSecretP payment_secret_request; + + /** + * The order ID, for making the payment. + */ + char *order_id; + + /** + * Payment order ID we are to provide in the response, or zero. + */ + struct ANASTASIS_PaymentSecretP payment_secret_response; + + /** + * Options for how we are supposed to do the upload. + */ + enum ANASTASIS_TESTING_PolicyStoreOption psopt; + + /** + * True if @e payment_secret_request is initialized. + */ + bool payment_secret_set; +}; + +/** + * Function called with the results of a #policy_store(). + * + * @param cls closure + * @param http_status HTTP status of the request + * @param ud details about the upload operation + */ +static void +policy_store_cb (void *cls, + const struct ANASTASIS_UploadDetails *ud) +{ + struct PolicyStoreState *pss = cls; + + pss->pso = NULL; + if (ud->http_status != pss->http_status) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected response code %u to command %s in %s:%u\n", + ud->http_status, + pss->is->commands[pss->is->ip].label, + __FILE__, + __LINE__); + TALER_TESTING_interpreter_fail (pss->is); + return; + } + switch (ud->us) + { + case ANASTASIS_US_SUCCESS: + if (0 != GNUNET_memcmp (&pss->curr_hash, + ud->details.success.curr_backup_hash)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (pss->is); + return; + } + break; + case ANASTASIS_US_PAYMENT_REQUIRED: + pss->payment_secret_response = ud->details.payment.ps; + { + struct TALER_MERCHANT_PayUriData pd; + + if (GNUNET_OK != + TALER_MERCHANT_parse_pay_uri (ud->details.payment.payment_request, + &pd)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (pss->is); + return; + } + pss->order_id = GNUNET_strdup (pd.order_id); + if (NULL != pd.claim_token) + pss->claim_token = *pd.claim_token; + TALER_MERCHANT_parse_pay_uri_free (&pd); + } + break; + case ANASTASIS_US_HTTP_ERROR: + break; + case ANASTASIS_US_CLIENT_ERROR: + GNUNET_break (0); + TALER_TESTING_interpreter_fail (pss->is); + return; + case ANASTASIS_US_SERVER_ERROR: + GNUNET_break (0); + TALER_TESTING_interpreter_fail (pss->is); + return; + default: + GNUNET_break (0); + TALER_TESTING_interpreter_fail (pss->is); + return; + } + TALER_TESTING_interpreter_next (pss->is); +} + + +/** + * Run a "policy store" CMD. + * + * @param cls closure. + * @param cmd command currently being run. + * @param is interpreter state. + */ +static void +policy_store_run (void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is) +{ + struct PolicyStoreState *pss = cls; + + pss->is = is; + if (NULL != pss->prev_upload) + { + const struct TALER_TESTING_Command *ref; + + ref = TALER_TESTING_interpreter_lookup_command (is, + pss->prev_upload); + if (NULL == ref) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (pss->is); + return; + } + { + const struct ANASTASIS_CRYPTO_AccountPrivateKeyP *priv; + + if (GNUNET_OK != + ANASTASIS_TESTING_get_trait_account_priv (ref, + 0, + &priv)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (pss->is); + return; + } + pss->anastasis_priv = *priv; + } + { + const struct ANASTASIS_CRYPTO_AccountPublicKeyP *pub; + + if (GNUNET_OK != + ANASTASIS_TESTING_get_trait_account_pub (ref, + 0, + &pub)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (pss->is); + return; + } + pss->anastasis_pub = *pub; + } + { + const struct ANASTASIS_PaymentSecretP *ps; + + if (GNUNET_OK != + ANASTASIS_TESTING_get_trait_payment_secret (ref, + 0, + &ps)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (pss->is); + return; + } + pss->payment_secret_request = *ps; + pss->payment_secret_set = true; + } + } + else + { + GNUNET_CRYPTO_eddsa_key_create (&pss->anastasis_priv.priv); + GNUNET_CRYPTO_eddsa_key_get_public (&pss->anastasis_priv.priv, + &pss->anastasis_pub.pub); + } + + GNUNET_CRYPTO_hash (pss->recovery_data, + pss->recovery_data_size, + &pss->curr_hash); + pss->pso = ANASTASIS_policy_store ( + is->ctx, + pss->anastasis_url, + &pss->anastasis_priv, + pss->recovery_data, + pss->recovery_data_size, + (0 != (ANASTASIS_TESTING_PSO_REQUEST_PAYMENT & pss->psopt)), + pss->payment_secret_set ? &pss->payment_secret_request : NULL, + GNUNET_TIME_UNIT_ZERO, + &policy_store_cb, + pss); + if (NULL == pss->pso) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (pss->is); + return; + } +} + + +/** + * Free the state of a "policy store" CMD, and possibly + * cancel it if it did not complete. + * + * @param cls closure. + * @param cmd command being freed. + */ +static void +policy_store_cleanup (void *cls, + const struct TALER_TESTING_Command *cmd) +{ + struct PolicyStoreState *pss = cls; + + if (NULL != pss->pso) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Command '%s' did not complete (policy post)\n", + cmd->label); + ANASTASIS_policy_store_cancel (pss->pso); + pss->pso = NULL; + } + GNUNET_free (pss->order_id); + GNUNET_free (pss); +} + + +/** + * Offer internal data to other commands. + * + * @param cls closure + * @param[out] ret result (could be anything) + * @param trait name of the trait + * @param index index number of the object to extract. + * @return #GNUNET_OK on success + */ +static int +policy_store_traits (void *cls, + const void **ret, + const char *trait, + unsigned int index) +{ + struct PolicyStoreState *pss = cls; + struct TALER_TESTING_Trait traits[] = { + TALER_TESTING_make_trait_claim_token (0, + &pss->claim_token), + TALER_TESTING_make_trait_order_id (0, + pss->order_id), + ANASTASIS_TESTING_make_trait_hash (0, + &pss->curr_hash), + ANASTASIS_TESTING_make_trait_account_pub (0, + &pss->anastasis_pub), + ANASTASIS_TESTING_make_trait_account_priv (0, + &pss->anastasis_priv), + ANASTASIS_TESTING_make_trait_payment_secret (0, + &pss->payment_secret_response), + TALER_TESTING_trait_end () + }; + + return TALER_TESTING_get_trait (traits, + ret, + trait, + index); +} + + +struct TALER_TESTING_Command +ANASTASIS_TESTING_cmd_policy_store ( + const char *label, + const char *anastasis_url, + const char *prev_upload, + unsigned int http_status, + enum ANASTASIS_TESTING_PolicyStoreOption pso, + const void *recovery_data, + size_t recovery_data_size) +{ + struct PolicyStoreState *pss; + + pss = GNUNET_new (struct PolicyStoreState); + pss->recovery_data = recovery_data; + pss->recovery_data_size = recovery_data_size; + pss->http_status = http_status; + pss->psopt = pso; + pss->anastasis_url = anastasis_url; + pss->prev_upload = prev_upload; + { + struct TALER_TESTING_Command cmd = { + .cls = pss, + .label = label, + .run = &policy_store_run, + .cleanup = &policy_store_cleanup, + .traits = &policy_store_traits + }; + + return cmd; + } +} diff --git a/src/testing/testing_api_cmd_truth_store.c b/src/testing/testing_api_cmd_truth_store.c new file mode 100644 index 0000000..0883406 --- /dev/null +++ b/src/testing/testing_api_cmd_truth_store.c @@ -0,0 +1,436 @@ +/* + 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_truth_store.c + * @brief command to execute the anastasis backend service. + * @author Dennis Neufeld + */ +#include "platform.h" +#include "anastasis_testing_lib.h" +#include <taler/taler_util.h> +#include <taler/taler_testing_lib.h> +#include <taler/taler_merchant_service.h> + +/** + * State for a "truth store" CMD. + */ +struct TruthStoreState +{ + /** + * UUID of the uploaded truth + */ + struct ANASTASIS_CRYPTO_TruthUUIDP uuid; + + /** + * Key used to encrypt the @e truth_data on the server. + */ + struct ANASTASIS_CRYPTO_TruthKeyP key; + + /** + * "Encrypted" key share data we store at the server. + */ + struct ANASTASIS_CRYPTO_EncryptedKeyShareP encrypted_keyshare; + + /** + * The /truth POST operation handle. + */ + struct ANASTASIS_TruthStoreOperation *tso; + + /** + * URL of the anastasis backend. + */ + const char *anastasis_url; + + /** + * The interpreter state. + */ + struct TALER_TESTING_Interpreter *is; + + /** + * Previous upload, or NULL for none. Used to calculate what THIS + * upload is based on. + */ + const char *prev_upload; + + /** + * Authorization method / plugin name. + */ + const char *method; + + /** + * Mimetype of @e truth_data. + */ + const char *mime_type; + + /** + * Number of bytes in @e truth_data + */ + size_t truth_data_size; + + /** + * Data used by the authorization process. + */ + void *truth_data; + + /** + * Name of the file where the service will write the challenge, or NULL. + */ + char *filename; + + /** + * Expected status code. + */ + unsigned int http_status; + + /** + * Payment request we got back, or NULL. + */ + char *pay_uri; + + /** + * Payment order ID we got back, or all zeros. + */ + struct ANASTASIS_PaymentSecretP payment_secret_response; + + /** + * Options for how we are supposed to do the upload. + */ + enum ANASTASIS_TESTING_TruthStoreOption tsopt; +}; + +/** + * Function called with the results of a #truth_store(). + * + * @param cls closure + * @param ec ANASTASIS error code + * @param http_status HTTP status of the request + * @param ud details about the upload operation + */ +static void +truth_store_cb (void *cls, + const struct ANASTASIS_UploadDetails *ud) +{ + struct TruthStoreState *tss = cls; + + tss->tso = NULL; + if ( (NULL == ud) || + (ud->http_status != tss->http_status) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected response code %u to command %s in %s:%u\n", + (NULL != ud) ? ud->http_status : 0, + tss->is->commands[tss->is->ip].label, + __FILE__, + __LINE__); + TALER_TESTING_interpreter_fail (tss->is); + return; + } + switch (ud->us) + { + case ANASTASIS_US_SUCCESS: + break; + case ANASTASIS_US_PAYMENT_REQUIRED: + tss->pay_uri = GNUNET_strdup (ud->details.payment.payment_request); + tss->payment_secret_response = ud->details.payment.ps; + break; + case ANASTASIS_US_CONFLICTING_TRUTH: + GNUNET_break (0); + TALER_TESTING_interpreter_fail (tss->is); + return; + case ANASTASIS_US_HTTP_ERROR: + GNUNET_break (0); + TALER_TESTING_interpreter_fail (tss->is); + return; + case ANASTASIS_US_CLIENT_ERROR: + GNUNET_break (0); + TALER_TESTING_interpreter_fail (tss->is); + return; + case ANASTASIS_US_SERVER_ERROR: + GNUNET_break (0); + TALER_TESTING_interpreter_fail (tss->is); + return; + default: + GNUNET_break (0); + TALER_TESTING_interpreter_fail (tss->is); + return; + } + TALER_TESTING_interpreter_next (tss->is); +} + + +/** + * Run a "truth store" CMD. + * + * @param cls closure. + * @param cmd command currently being run. + * @param is interpreter state. + */ +static void +truth_store_run (void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is) +{ + struct TruthStoreState *tss = cls; + + tss->is = is; + if (NULL != tss->prev_upload) + { + const struct TALER_TESTING_Command *ref; + + ref = TALER_TESTING_interpreter_lookup_command (is, + tss->prev_upload); + if (NULL == ref) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (tss->is); + return; + } + + if (0 != (ANASTASIS_TESTING_TSO_REFERENCE_UUID & tss->tsopt)) + { + const struct ANASTASIS_CRYPTO_TruthUUIDP *uuid; + const struct ANASTASIS_CRYPTO_EncryptedKeyShareP *eks; + + if (GNUNET_OK != + ANASTASIS_TESTING_get_trait_truth_uuid (ref, + 0, + &uuid)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (tss->is); + return; + } + tss->uuid = *uuid; + if (GNUNET_OK != + ANASTASIS_TESTING_get_trait_eks (ref, + 0, + &eks)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (tss->is); + return; + } + tss->encrypted_keyshare = *eks; + } + } + else + { + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, + &tss->uuid, + sizeof (struct ANASTASIS_CRYPTO_TruthUUIDP)); + GNUNET_CRYPTO_random_block ( + GNUNET_CRYPTO_QUALITY_WEAK, + &tss->encrypted_keyshare, + sizeof (struct ANASTASIS_CRYPTO_EncryptedKeyShareP)); + } + GNUNET_CRYPTO_random_block ( + GNUNET_CRYPTO_QUALITY_WEAK, + &tss->key, + sizeof (struct ANASTASIS_CRYPTO_TruthKeyP)); + + { + void *encrypted_truth; + size_t size_encrypted_truth; + struct ANASTASIS_CRYPTO_NonceP nonce; + + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, + &nonce, + sizeof (nonce)); + ANASTASIS_CRYPTO_truth_encrypt (&nonce, + &tss->key, + tss->truth_data, + tss->truth_data_size, + &encrypted_truth, + &size_encrypted_truth); + { + void *t; + size_t t_size; + + ANASTASIS_CRYPTO_truth_decrypt (&tss->key, + encrypted_truth, + size_encrypted_truth, + &t, + &t_size); + if ( (t_size != tss->truth_data_size) || + (0 != memcmp (tss->truth_data, + t, + t_size)) ) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (tss->is); + return; + } + GNUNET_free (t); + } + tss->tso = ANASTASIS_truth_store ( + is->ctx, + tss->anastasis_url, + &tss->uuid, + tss->method, + &tss->encrypted_keyshare, + tss->mime_type, + size_encrypted_truth, + encrypted_truth, + (0 != (ANASTASIS_TESTING_TSO_REQUEST_PAYMENT & tss->tsopt)), + GNUNET_TIME_UNIT_ZERO, + &truth_store_cb, + tss); + GNUNET_free (encrypted_truth); + } + if (NULL == tss->tso) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (tss->is); + return; + } +} + + +/** + * Free the state of a "truth store" CMD, and possibly + * cancel it if it did not complete. + * + * @param cls closure. + * @param cmd command being freed. + */ +static void +truth_store_cleanup (void *cls, + const struct TALER_TESTING_Command *cmd) +{ + struct TruthStoreState *tss = cls; + + if (NULL != tss->tso) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Command '%s' did not complete (truth post)\n", + cmd->label); + ANASTASIS_truth_store_cancel (tss->tso); + tss->tso = NULL; + } + GNUNET_free (tss->truth_data); + GNUNET_free (tss->pay_uri); + GNUNET_free (tss->filename); + GNUNET_free (tss); +} + + +/** + * Offer internal data to other commands. + * + * @param cls closure + * @param[out] ret result (could be anything) + * @param[out] trait name of the trait + * @param index index number of the object to extract. + * @return #GNUNET_OK on success + */ +static int +truth_store_traits (void *cls, + const void **ret, + const char *trait, + unsigned int index) +{ + struct TruthStoreState *tss = cls; + struct TALER_TESTING_Trait traits[] = { + ANASTASIS_TESTING_make_trait_truth_uuid (0, + &tss->uuid), + ANASTASIS_TESTING_make_trait_truth_key (0, + &tss->key), + ANASTASIS_TESTING_make_trait_eks (0, + &tss->encrypted_keyshare), + ANASTASIS_TESTING_make_trait_payment_secret (0, + &tss->payment_secret_response), + TALER_TESTING_make_trait_url (TALER_TESTING_UT_TALER_URL, + tss->pay_uri), + TALER_TESTING_make_trait_string (0, + tss->filename), + TALER_TESTING_trait_end () + }; + + return TALER_TESTING_get_trait (traits, + ret, + trait, + index); +} + + +struct TALER_TESTING_Command +ANASTASIS_TESTING_cmd_truth_store (const char *label, + const char *anastasis_url, + const char *prev_upload, + const char *method, + const char *mime_type, + size_t truth_data_size, + const void *truth_data, + enum ANASTASIS_TESTING_TruthStoreOption tso, + unsigned int http_status) +{ + struct TruthStoreState *tss; + + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Storing %u bytes of truth\n", + (unsigned int) truth_data_size); + tss = GNUNET_new (struct TruthStoreState); + tss->http_status = http_status; + tss->tsopt = tso; + tss->anastasis_url = anastasis_url; + tss->prev_upload = prev_upload; + tss->method = method; + tss->mime_type = mime_type; + tss->truth_data = GNUNET_memdup (truth_data, + truth_data_size); + tss->truth_data_size = truth_data_size; + if (0 == strcasecmp (method, + "file")) + tss->filename = GNUNET_strndup (truth_data, + truth_data_size); + { + struct TALER_TESTING_Command cmd = { + .cls = tss, + .label = label, + .run = &truth_store_run, + .cleanup = &truth_store_cleanup, + .traits = &truth_store_traits + }; + + return cmd; + } +} + + +struct TALER_TESTING_Command +ANASTASIS_TESTING_cmd_truth_question ( + const char *label, + const char *anastasis_url, + const char *prev_upload, + const char *answer, + enum ANASTASIS_TESTING_TruthStoreOption tso, + unsigned int http_status) +{ + struct GNUNET_HashCode h; + + GNUNET_CRYPTO_hash (answer, + strlen (answer), + &h); + return ANASTASIS_TESTING_cmd_truth_store (label, + anastasis_url, + prev_upload, + "question", + "binary/sha512", + sizeof (h), + &h, + tso, + http_status); +} diff --git a/src/testing/testing_api_helpers.c b/src/testing/testing_api_helpers.c new file mode 100644 index 0000000..66e7032 --- /dev/null +++ b/src/testing/testing_api_helpers.c @@ -0,0 +1,173 @@ +/* + This file is part of ANASTASIS + Copyright (C) 2014-2021 Taler Systems 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 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 + ANASTASISABILITY 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. If not, see + <http://www.gnu.org/licenses/> +*/ + +/** + * @file lib/testing_api_helpers.c + * @brief helper functions for test library. + * @author Christian Grothoff + * @author Marcello Stanisci + */ + +#include "platform.h" +#include "anastasis_testing_lib.h" +#include <gnunet/gnunet_curl_lib.h> + + +struct GNUNET_OS_Process * +ANASTASIS_TESTING_run_anastasis (const char *config_filename, + const char *anastasis_url) +{ + struct GNUNET_OS_Process *anastasis_proc; + unsigned int iter; + char *wget_cmd; + + anastasis_proc + = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL, + NULL, NULL, NULL, + "anastasis-httpd", + "anastasis-httpd", + "--log=INFO", + "-c", config_filename, + NULL); + if (NULL == anastasis_proc) + ANASTASIS_FAIL (); + + GNUNET_asprintf (&wget_cmd, + "wget -q -t 1 -T 1" + " %s" + " -o /dev/null -O /dev/null", + anastasis_url); + + /* give child time to start and bind against the socket */ + fprintf (stderr, + "Waiting for `anastasis-httpd' to be ready\n"); + iter = 0; + do + { + if (100 == iter) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to launch `anastasis-httpd' (or `wget')\n"); + GNUNET_OS_process_kill (anastasis_proc, + SIGTERM); + GNUNET_OS_process_wait (anastasis_proc); + GNUNET_OS_process_destroy (anastasis_proc); + ANASTASIS_FAIL (); + } + { + struct timespec req = { + .tv_nsec = 10000 + }; + + nanosleep (&req, + NULL); + } + iter++; + } + while (0 != system (wget_cmd)); + GNUNET_free (wget_cmd); + fprintf (stderr, + "\n"); + return anastasis_proc; +} + + +char * +ANASTASIS_TESTING_prepare_anastasis (const char *config_filename) +{ + struct GNUNET_CONFIGURATION_Handle *cfg; + unsigned long long port; + struct GNUNET_OS_Process *dbinit_proc; + enum GNUNET_OS_ProcessStatusType type; + unsigned long code; + char *base_url; + + cfg = GNUNET_CONFIGURATION_create (); + if (GNUNET_OK != + GNUNET_CONFIGURATION_load (cfg, + config_filename)) + ANASTASIS_FAIL (); + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_number (cfg, + "anastasis", + "PORT", + &port)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "anastasis", + "PORT"); + GNUNET_CONFIGURATION_destroy (cfg); + return NULL; + } + + GNUNET_CONFIGURATION_destroy (cfg); + + if (GNUNET_OK != + GNUNET_NETWORK_test_port_free (IPPROTO_TCP, + (uint16_t) port)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Required port %llu not available, skipping.\n", + port); + return NULL; + } + + /* DB preparation */ + if (NULL == (dbinit_proc = GNUNET_OS_start_process + (GNUNET_OS_INHERIT_STD_ALL, + NULL, NULL, NULL, + "anastasis-dbinit", + "anastasis-dbinit", + "-c", config_filename, + "-r", + NULL))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to run anastasis-dbinit. Check your PATH.\n"); + return NULL; + } + + if (GNUNET_SYSERR == + GNUNET_OS_process_wait_status (dbinit_proc, + &type, + &code)) + { + GNUNET_OS_process_destroy (dbinit_proc); + ANASTASIS_FAIL (); + } + if ( (type == GNUNET_OS_PROCESS_EXITED) && + (0 != code) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to setup database\n"); + return NULL; + } + if ( (type != GNUNET_OS_PROCESS_EXITED) || + (0 != code) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected error running `anastasis-dbinit'!\n"); + return NULL; + } + GNUNET_OS_process_destroy (dbinit_proc); + GNUNET_asprintf (&base_url, + "http://localhost:%llu/", + port); + return base_url; +} diff --git a/src/testing/testing_api_trait_account_priv.c b/src/testing/testing_api_trait_account_priv.c new file mode 100644 index 0000000..4860e82 --- /dev/null +++ b/src/testing/testing_api_trait_account_priv.c @@ -0,0 +1,72 @@ +/* + This file is part of TALER + Copyright (C) 2019 Taler Systems SA + + TALER 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. + + TALER 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 Privlic License for more details. + + You should have received a copy of the GNU General Privlic + License along with TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file lib/testing_api_trait_account_priv.c + * @brief traits to offer a account_priv + * @author Christian Grothoff + */ +#include "platform.h" +#include "anastasis_testing_lib.h" + +#define ANASTASIS_TESTING_TRAIT_ACCOUNT_PRIV "anastasis-account_priv" + + +/** + * Obtain an account private key from @a cmd. + * + * @param cmd command to extract the private key from. + * @param index the private key's index number. + * @param n[out] set to the private key coming from @a cmd. + * @return #GNUNET_OK on success. + */ +int +ANASTASIS_TESTING_get_trait_account_priv + (const struct TALER_TESTING_Command *cmd, + unsigned int index, + const struct ANASTASIS_CRYPTO_AccountPrivateKeyP **priv) +{ + return cmd->traits (cmd->cls, + (const void **) priv, + ANASTASIS_TESTING_TRAIT_ACCOUNT_PRIV, + index); +} + + +/** + * Offer an account private key. + * + * @param index usually zero + * @param priv the account_priv to offer. + * @return #GNUNET_OK on success. + */ +struct TALER_TESTING_Trait +ANASTASIS_TESTING_make_trait_account_priv + (unsigned int index, + const struct ANASTASIS_CRYPTO_AccountPrivateKeyP *priv) +{ + struct TALER_TESTING_Trait ret = { + .index = index, + .trait_name = ANASTASIS_TESTING_TRAIT_ACCOUNT_PRIV, + .ptr = (const void *) priv + }; + return ret; +} + + +/* end of testing_api_trait_account_priv.c */ diff --git a/src/testing/testing_api_trait_account_pub.c b/src/testing/testing_api_trait_account_pub.c new file mode 100644 index 0000000..5a3632e --- /dev/null +++ b/src/testing/testing_api_trait_account_pub.c @@ -0,0 +1,72 @@ +/* + This file is part of TALER + Copyright (C) 2019 Taler Systems SA + + TALER 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. + + TALER 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 TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file lib/testing_api_trait_account_pub.c + * @brief traits to offer a account_pub + * @author Christian Grothoff + */ +#include "platform.h" +#include "anastasis_testing_lib.h" + +#define ANASTASIS_TESTING_TRAIT_ACCOUNT_PUB "anastasis-account_pub" + + +/** + * Obtain an account public key from @a cmd. + * + * @param cmd command to extract the public key from. + * @param index the public key's index number. + * @param n[out] set to the public key coming from @a cmd. + * @return #GNUNET_OK on success. + */ +int +ANASTASIS_TESTING_get_trait_account_pub + (const struct TALER_TESTING_Command *cmd, + unsigned int index, + const struct ANASTASIS_CRYPTO_AccountPublicKeyP **pub) +{ + return cmd->traits (cmd->cls, + (const void **) pub, + ANASTASIS_TESTING_TRAIT_ACCOUNT_PUB, + index); +} + + +/** + * Offer an account public key. + * + * @param index usually zero + * @param h the account_pub to offer. + * @return #GNUNET_OK on success. + */ +struct TALER_TESTING_Trait +ANASTASIS_TESTING_make_trait_account_pub + (unsigned int index, + const struct ANASTASIS_CRYPTO_AccountPublicKeyP *h) +{ + struct TALER_TESTING_Trait ret = { + .index = index, + .trait_name = ANASTASIS_TESTING_TRAIT_ACCOUNT_PUB, + .ptr = (const void *) h + }; + return ret; +} + + +/* end of testing_api_trait_account_pub.c */ diff --git a/src/testing/testing_api_trait_code.c b/src/testing/testing_api_trait_code.c new file mode 100644 index 0000000..1a43cf8 --- /dev/null +++ b/src/testing/testing_api_trait_code.c @@ -0,0 +1,73 @@ +/* + This file is part of TALER + Copyright (C) 2019 Taler Systems SA + + TALER 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. + + TALER 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 TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file lib/testing_api_trait_string.c + * @brief traits to offers a code for a challenge + * @author Dominik Meister + * @author Christian Grothoff + */ +#include "platform.h" +#include "anastasis_testing_lib.h" + +#define ANASTASIS_TESTING_TRAIT_CODE "anastasis-code" + + +/** + * Obtain a code from @a cmd. + * + * @param cmd command to extract the number from. + * @param index the number's index number. + * @param n[out] set to the number coming from @a cmd. + * @return #GNUNET_OK on success. + */ +int +ANASTASIS_TESTING_get_trait_code + (const struct TALER_TESTING_Command *cmd, + unsigned int index, + const char **code) +{ + return cmd->traits (cmd->cls, + (const void **) code, + ANASTASIS_TESTING_TRAIT_CODE, + index); +} + + +/** + * Offer a code. + * + * @param index the number's index number. + * @param code the code to offer. + * @return #GNUNET_OK on success. + */ +struct TALER_TESTING_Trait +ANASTASIS_TESTING_make_trait_code + (unsigned int index, + const char *code) +{ + struct TALER_TESTING_Trait ret = { + .index = index, + .trait_name = ANASTASIS_TESTING_TRAIT_CODE, + .ptr = (const void *) code + }; + return ret; +} + + +/* end of testing_api_trait_string.c */ diff --git a/src/testing/testing_api_trait_eks.c b/src/testing/testing_api_trait_eks.c new file mode 100644 index 0000000..dc3f923 --- /dev/null +++ b/src/testing/testing_api_trait_eks.c @@ -0,0 +1,58 @@ +/* + This file is part of TALER + Copyright (C) 2021 Taler Systems SA + + TALER 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. + + TALER 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 TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file lib/testing_api_trait_eks.c + * @brief traits to offer a payment identifier + * @author Dennis Neufeld + */ +#include "platform.h" +#include "anastasis_testing_lib.h" + +#define ANASTASIS_TESTING_TRAIT_EKS \ + "anastasis-eks" + + +int +ANASTASIS_TESTING_get_trait_eks + (const struct TALER_TESTING_Command *cmd, + unsigned int index, + const struct ANASTASIS_CRYPTO_EncryptedKeyShareP **eks) +{ + return cmd->traits (cmd->cls, + (const void **) eks, + ANASTASIS_TESTING_TRAIT_EKS, + index); +} + + +struct TALER_TESTING_Trait +ANASTASIS_TESTING_make_trait_eks + (unsigned int index, + const struct ANASTASIS_CRYPTO_EncryptedKeyShareP *eks) +{ + struct TALER_TESTING_Trait ret = { + .index = index, + .trait_name = ANASTASIS_TESTING_TRAIT_EKS, + .ptr = (const void *) eks + }; + return ret; +} + + +/* end of testing_api_trait_eks.c */ diff --git a/src/testing/testing_api_trait_hash.c b/src/testing/testing_api_trait_hash.c new file mode 100644 index 0000000..18be1ea --- /dev/null +++ b/src/testing/testing_api_trait_hash.c @@ -0,0 +1,72 @@ +/* + This file is part of TALER + Copyright (C) 2019 Taler Systems SA + + TALER 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. + + TALER 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 TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file lib/testing_api_trait_hash.c + * @brief traits to offer a hash + * @author Christian Grothoff + */ +#include "platform.h" +#include "anastasis_testing_lib.h" + +#define ANASTASIS_TESTING_TRAIT_HASH "anastasis-hash" + + +/** + * Obtain a hash from @a cmd. + * + * @param cmd command to extract the number from. + * @param index the number's index number. + * @param n[out] set to the number coming from @a cmd. + * @return #GNUNET_OK on success. + */ +int +ANASTASIS_TESTING_get_trait_hash + (const struct TALER_TESTING_Command *cmd, + unsigned int index, + const struct GNUNET_HashCode **h) +{ + return cmd->traits (cmd->cls, + (const void **) h, + ANASTASIS_TESTING_TRAIT_HASH, + index); +} + + +/** + * Offer a hash. + * + * @param index the number's index number. + * @param h the hash to offer. + * @return #GNUNET_OK on success. + */ +struct TALER_TESTING_Trait +ANASTASIS_TESTING_make_trait_hash + (unsigned int index, + const struct GNUNET_HashCode *h) +{ + struct TALER_TESTING_Trait ret = { + .index = index, + .trait_name = ANASTASIS_TESTING_TRAIT_HASH, + .ptr = (const void *) h + }; + return ret; +} + + +/* end of testing_api_trait_hash.c */ diff --git a/src/testing/testing_api_trait_payment_secret.c b/src/testing/testing_api_trait_payment_secret.c new file mode 100644 index 0000000..6238879 --- /dev/null +++ b/src/testing/testing_api_trait_payment_secret.c @@ -0,0 +1,73 @@ +/* + This file is part of TALER + Copyright (C) 2019 Taler Systems SA + + TALER 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. + + TALER 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 TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file lib/testing_api_trait_payment_secret.c + * @brief traits to offer a payment identifier + * @author Dennis Neufeld + */ +#include "platform.h" +#include "anastasis_testing_lib.h" + +#define ANASTASIS_TESTING_TRAIT_PAYMENT_SECRET \ + "anastasis-payment_secret" + + +/** + * Obtain an account public key from @a cmd. + * + * @param cmd command to extract the payment identifier from. + * @param index the payment identifier's index number. + * @param n[out] set to the payment identifier coming from @a cmd. + * @return #GNUNET_OK on success. + */ +int +ANASTASIS_TESTING_get_trait_payment_secret + (const struct TALER_TESTING_Command *cmd, + unsigned int index, + const struct ANASTASIS_PaymentSecretP **payment_secret) +{ + return cmd->traits (cmd->cls, + (const void **) payment_secret, + ANASTASIS_TESTING_TRAIT_PAYMENT_SECRET, + index); +} + + +/** + * Offer a payment identifier. + * + * @param index usually zero + * @param h the payment identifier to offer. + * @return #GNUNET_OK on success. + */ +struct TALER_TESTING_Trait +ANASTASIS_TESTING_make_trait_payment_secret + (unsigned int index, + const struct ANASTASIS_PaymentSecretP *h) +{ + struct TALER_TESTING_Trait ret = { + .index = index, + .trait_name = ANASTASIS_TESTING_TRAIT_PAYMENT_SECRET, + .ptr = (const void *) h + }; + return ret; +} + + +/* end of testing_api_trait_payment_secret.c */ diff --git a/src/testing/testing_api_trait_salt.c b/src/testing/testing_api_trait_salt.c new file mode 100644 index 0000000..116742f --- /dev/null +++ b/src/testing/testing_api_trait_salt.c @@ -0,0 +1,74 @@ +/* + This file is part of TALER + Copyright (C) 2020 Taler Systems SA + + TALER 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. + + TALER 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 TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file lib/testing_api_trait_salt.c + * @brief traits to offer a hash + * @author Christian Grothoff + * @author Dominik Meister + * @author Dennis Neufeld + */ +#include "platform.h" +#include "anastasis_testing_lib.h" + +#define ANASTASIS_TESTING_TRAIT_SALT "anastasis-provider-salt" + + +/** + * Obtain a salt from @a cmd. + * + * @param cmd command to extract the salt from. + * @param index the salt's index number. + * @param s[out] set to the salt coming from @a cmd. + * @return #GNUNET_OK on success. + */ +int +ANASTASIS_TESTING_get_trait_salt + (const struct TALER_TESTING_Command *cmd, + unsigned int index, + const struct ANASTASIS_CRYPTO_ProviderSaltP **s) +{ + return cmd->traits (cmd->cls, + (const void **) s, + ANASTASIS_TESTING_TRAIT_SALT, + index); +} + + +/** + * Offer an salt. + * + * @param index the salt's index number. + * @param u the salt to offer. + * @return #GNUNET_OK on success. + */ +struct TALER_TESTING_Trait +ANASTASIS_TESTING_make_trait_salt + (unsigned int index, + const struct ANASTASIS_CRYPTO_ProviderSaltP *s) +{ + struct TALER_TESTING_Trait ret = { + .index = index, + .trait_name = ANASTASIS_TESTING_TRAIT_SALT, + .ptr = (const void *) s + }; + return ret; +} + + +/* end of testing_api_trait_salt.c */ diff --git a/src/testing/testing_api_trait_truth_key.c b/src/testing/testing_api_trait_truth_key.c new file mode 100644 index 0000000..55094c1 --- /dev/null +++ b/src/testing/testing_api_trait_truth_key.c @@ -0,0 +1,58 @@ +/* + This file is part of TALER + Copyright (C) 2019, 2021 Taler Systems SA + + TALER 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. + + TALER 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 TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file lib/testing_api_trait_truth_key.c + * @brief traits to offer a payment identifier + * @author Dennis Neufeld + */ +#include "platform.h" +#include "anastasis_testing_lib.h" + +#define ANASTASIS_TESTING_TRAIT_TRUTH_KEY \ + "anastasis-truth_key" + + +int +ANASTASIS_TESTING_get_trait_truth_key + (const struct TALER_TESTING_Command *cmd, + unsigned int index, + const struct ANASTASIS_CRYPTO_TruthKeyP **truth_key) +{ + return cmd->traits (cmd->cls, + (const void **) truth_key, + ANASTASIS_TESTING_TRAIT_TRUTH_KEY, + index); +} + + +struct TALER_TESTING_Trait +ANASTASIS_TESTING_make_trait_truth_key + (unsigned int index, + const struct ANASTASIS_CRYPTO_TruthKeyP *h) +{ + struct TALER_TESTING_Trait ret = { + .index = index, + .trait_name = ANASTASIS_TESTING_TRAIT_TRUTH_KEY, + .ptr = (const void *) h + }; + return ret; +} + + +/* end of testing_api_trait_truth_key.c */ diff --git a/src/testing/testing_api_trait_truth_uuid.c b/src/testing/testing_api_trait_truth_uuid.c new file mode 100644 index 0000000..38a7336 --- /dev/null +++ b/src/testing/testing_api_trait_truth_uuid.c @@ -0,0 +1,74 @@ +/* + This file is part of TALER + Copyright (C) 2020 Taler Systems SA + + TALER 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. + + TALER 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 TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file lib/testing_api_trait_truth_pub.c + * @brief traits to offer a UUID for some truth + * @author Christian Grothoff + * @author Dominik Meister + * @author Dennis Neufeld + */ +#include "platform.h" +#include "anastasis_testing_lib.h" + +#define ANASTASIS_TESTING_TRAIT_TRUTH_UUID "anastasis-truth-uuid" + + +/** + * Obtain an public key from @a cmd. + * + * @param cmd command to extract the number from. + * @param index the number's index number. + * @param u[out] set to the number coming from @a cmd. + * @return #GNUNET_OK on success. + */ +int +ANASTASIS_TESTING_get_trait_truth_uuid + (const struct TALER_TESTING_Command *cmd, + unsigned int index, + const struct ANASTASIS_CRYPTO_TruthUUIDP **tpk) +{ + return cmd->traits (cmd->cls, + (const void **) tpk, + ANASTASIS_TESTING_TRAIT_TRUTH_UUID, + index); +} + + +/** + * Offer a truth public key. + * + * @param index the number's index number. + * @param tpk the public key to offer. + * @return #GNUNET_OK on success. + */ +struct TALER_TESTING_Trait +ANASTASIS_TESTING_make_trait_truth_uuid + (unsigned int index, + const struct ANASTASIS_CRYPTO_TruthUUIDP *tpk) +{ + struct TALER_TESTING_Trait ret = { + .index = index, + .trait_name = ANASTASIS_TESTING_TRAIT_TRUTH_UUID, + .ptr = (const void *) tpk + }; + return ret; +} + + +/* end of testing_api_trait_truth_pub.c */ diff --git a/src/testing/testing_cmd_challenge_answer.c b/src/testing/testing_cmd_challenge_answer.c new file mode 100644 index 0000000..b243d61 --- /dev/null +++ b/src/testing/testing_cmd_challenge_answer.c @@ -0,0 +1,584 @@ +/* + 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_cmd_challenge_answer.c + * @brief command to execute the anastasis recovery service + * @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> +#include <taler/taler_merchant_service.h> + + +/** + * State for a "challenge answer" CMD. + */ +struct ChallengeState +{ + /** + * The interpreter state. + */ + struct TALER_TESTING_Interpreter *is; + + /** + * Reference to the challenge we are solving + */ + struct ANASTASIS_Challenge *c; + + /** + * Answer to the challenge we are solving + */ + const char *answer; + + /** + * Reference to the recovery process + */ + const char *challenge_ref; + + /** + * Reference to the payment + */ + const char *payment_ref; + + /** + * "taler://pay/" URL we got back, if any. Otherwise NULL. + */ + char *payment_uri; + + /** + * Order ID extracted from @e payment_uri, or NULL. + */ + char *order_id; + + /** + * Payment order ID we are to provide in the request. + */ + struct ANASTASIS_PaymentSecretP payment_order_req; + + /** + * Expected status code. + */ + enum ANASTASIS_ChallengeStatus expected_cs; + + /** + * Index of the challenge we are solving + */ + unsigned int challenge_index; + + /** + * 0 for no plugin needed 1 for plugin needed to authenticate + */ + unsigned int mode; + + /** + * code we read in the file generated by the plugin + */ + char code[22]; + +}; + + +static void +challenge_answer_cb (void *af_cls, + const struct ANASTASIS_ChallengeStartResponse *csr) +{ + struct ChallengeState *cs = af_cls; + + cs->c = NULL; + if (csr->cs != cs->expected_cs) + { + GNUNET_break (0); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Expected status %u, got %u\n", + cs->expected_cs, + csr->cs); + TALER_TESTING_interpreter_fail (cs->is); + return; + } + switch (csr->cs) + { + case ANASTASIS_CHALLENGE_STATUS_SOLVED: + break; + case ANASTASIS_CHALLENGE_STATUS_INSTRUCTIONS: + { + FILE *file; + char *fn; + + if (0 == strcasecmp (csr->details.open_challenge.content_type, + "application/json")) + { + const char *filename; + json_t *in; + + in = json_loadb (csr->details.open_challenge.body, + csr->details.open_challenge.body_size, + JSON_REJECT_DUPLICATES, + NULL); + if (NULL == in) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (cs->is); + return; + } + filename = json_string_value (json_object_get (in, + "filename")); + if (NULL == filename) + { + GNUNET_break (0); + json_decref (in); + TALER_TESTING_interpreter_fail (cs->is); + return; + } + fn = GNUNET_strdup (filename); + json_decref (in); + } + else + { + fn = GNUNET_strndup (csr->details.open_challenge.body, + csr->details.open_challenge.body_size); + } + file = fopen (fn, + "r"); + if (NULL == file) + { + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, + "open", + fn); + GNUNET_free (fn); + TALER_TESTING_interpreter_fail (cs->is); + return; + } + if (0 == fscanf (file, + "%21s", + cs->code)) + { + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, + "fscanf", + fn); + TALER_TESTING_interpreter_fail (cs->is); + fclose (file); + GNUNET_free (fn); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Read challenge answer `%s' from file `%s'\n", + cs->code, + fn); + TALER_TESTING_interpreter_next (cs->is); + GNUNET_break (0 == fclose (file)); + GNUNET_free (fn); + return; + } + case ANASTASIS_CHALLENGE_STATUS_PAYMENT_REQUIRED: + if (0 != strncmp (csr->details.payment_required.taler_pay_uri, + "taler+http://pay/", + strlen ("taler+http://pay/"))) + { + GNUNET_break (0); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Invalid payment URI `%s'\n", + csr->details.payment_required.taler_pay_uri); + TALER_TESTING_interpreter_fail (cs->is); + return; + } + cs->payment_uri = GNUNET_strdup ( + csr->details.payment_required.taler_pay_uri); + { + struct TALER_MERCHANT_PayUriData pud; + + if (GNUNET_OK != + TALER_MERCHANT_parse_pay_uri (cs->payment_uri, + &pud)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (cs->is); + return; + } + cs->order_id = GNUNET_strdup (pud.order_id); + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (cs->order_id, + strlen (cs->order_id), + &cs->payment_order_req, + sizeof (cs->payment_order_req))) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (cs->is); + return; + } + TALER_MERCHANT_parse_pay_uri_free (&pud); + } + TALER_TESTING_interpreter_next (cs->is); + return; + case ANASTASIS_CHALLENGE_STATUS_TRUTH_UNKNOWN: + break; + case ANASTASIS_CHALLENGE_STATUS_REDIRECT_FOR_AUTHENTICATION: + break; + case ANASTASIS_CHALLENGE_STATUS_SERVER_FAILURE: + GNUNET_break (0); + TALER_TESTING_interpreter_fail (cs->is); + return; + case ANASTASIS_CHALLENGE_STATUS_RATE_LIMIT_EXCEEDED: + break; + } + TALER_TESTING_interpreter_next (cs->is); +} + + +/** + * Run a "recover secret" CMD. + * + * @param cls closure. + * @param cmd command currently being run. + * @param is interpreter state. + */ +static void +challenge_answer_run (void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is) +{ + struct ChallengeState *cs = cls; + const struct ANASTASIS_Challenge *c; + const struct ANASTASIS_PaymentSecretP *ps; + + cs->is = is; + if (NULL != cs->challenge_ref) + { + const struct TALER_TESTING_Command *ref; + + ref = TALER_TESTING_interpreter_lookup_command ( + is, + cs->challenge_ref); + if (NULL == ref) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (cs->is); + return; + } + if (GNUNET_OK != + ANASTASIS_TESTING_get_trait_challenge (ref, + cs->challenge_index, + &c)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (cs->is); + return; + } + } + + if (NULL != cs->payment_ref) + { + const struct TALER_TESTING_Command *ref; + + ref = TALER_TESTING_interpreter_lookup_command (is, + cs->payment_ref); + if (NULL == ref) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (cs->is); + return; + } + if (GNUNET_OK != + ANASTASIS_TESTING_get_trait_payment_secret (ref, + 0, + &ps)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (cs->is); + return; + } + } + else + { + ps = NULL; + } + + cs->c = (struct ANASTASIS_Challenge *) c; + + if (1 == cs->mode) + { + const struct TALER_TESTING_Command *ref; + const char *answer; + unsigned long long code; + char dummy; + + ref = TALER_TESTING_interpreter_lookup_command (is, + cs->answer); + if (NULL == ref) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (cs->is); + return; + } + if (GNUNET_OK != + ANASTASIS_TESTING_get_trait_code (ref, + 0, + &answer)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (cs->is); + return; + } + if (1 != + sscanf (answer, + "%llu%c", + &code, + &dummy)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (cs->is); + return; + } + if (GNUNET_OK != + ANASTASIS_challenge_answer2 (cs->c, + ps, + GNUNET_TIME_UNIT_ZERO, + code, + &challenge_answer_cb, + cs)) + { + GNUNET_break (0); + cs->c = NULL; + TALER_TESTING_interpreter_fail (cs->is); + return; + } + + } + else + { + if (GNUNET_OK != + ANASTASIS_challenge_answer (cs->c, + ps, + GNUNET_TIME_UNIT_ZERO, + cs->answer, + &challenge_answer_cb, + cs)) + { + GNUNET_break (0); + cs->c = NULL; + TALER_TESTING_interpreter_fail (cs->is); + return; + } + } +} + + +/** + * Run a "recover secret" CMD. + * + * @param cls closure. + * @param cmd command currently being run. + * @param is interpreter state. + */ +static void +challenge_start_run (void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is) +{ + struct ChallengeState *cs = cls; + const struct ANASTASIS_Challenge *c; + const struct TALER_TESTING_Command *ref; + const struct ANASTASIS_PaymentSecretP *ps; + + cs->is = is; + ref = TALER_TESTING_interpreter_lookup_command ( + is, + cs->challenge_ref); + if (NULL == ref) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (cs->is); + return; + } + if (GNUNET_OK != + ANASTASIS_TESTING_get_trait_challenge (ref, + cs->challenge_index, + &c)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (cs->is); + return; + } + if (NULL != cs->payment_ref) + { + const struct TALER_TESTING_Command *ref; + + ref = TALER_TESTING_interpreter_lookup_command (is, + cs->payment_ref); + if (NULL == ref) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (cs->is); + return; + } + if (GNUNET_OK != + ANASTASIS_TESTING_get_trait_payment_secret (ref, + 0, + &ps)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (cs->is); + return; + } + } + else + { + ps = NULL; + } + if (GNUNET_OK != + ANASTASIS_challenge_start ((struct ANASTASIS_Challenge *) c, + ps, + GNUNET_TIME_UNIT_ZERO, + NULL, + &challenge_answer_cb, + cs)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (cs->is); + return; + } +} + + +/** + * Free the state of a "recover secret" CMD, and possibly + * cancel it if it did not complete. + * + * @param cls closure. + * @param cmd command being freed. + */ +static void +challenge_cleanup (void *cls, + const struct TALER_TESTING_Command *cmd) +{ + struct ChallengeState *cs = cls; + + if (NULL != cs->c) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Command '%s' did not complete (challenge answer)\n", + cmd->label); + ANASTASIS_challenge_abort (cs->c); + cs->c = NULL; + } + GNUNET_free (cs->payment_uri); + GNUNET_free (cs->order_id); + GNUNET_free (cs); +} + + +/** + * Offer internal data to other commands. + * + * @param cls closure + * @param ret[out] result (could be anything) + * @param trait name of the trait + * @param index index number of the object to extract. + * @return #GNUNET_OK on success + */ +static int +challenge_create_traits (void *cls, + const void **ret, + const char *trait, + unsigned int index) +{ + struct ChallengeState *cs = cls; + struct TALER_TESTING_Trait traits[] = { + ANASTASIS_TESTING_make_trait_code (0, + cs->code), + ANASTASIS_TESTING_make_trait_payment_secret (0, + &cs->payment_order_req), + TALER_TESTING_make_trait_url (TALER_TESTING_UT_TALER_URL, + cs->payment_uri), + TALER_TESTING_make_trait_order_id (0, + cs->order_id), + TALER_TESTING_trait_end () + }; + + return TALER_TESTING_get_trait (traits, + ret, + trait, + index); +} + + +struct TALER_TESTING_Command +ANASTASIS_TESTING_cmd_challenge_start ( + const char *label, + const char *payment_ref, + const char *challenge_ref, + unsigned int challenge_index, + enum ANASTASIS_ChallengeStatus expected_cs) +{ + struct ChallengeState *cs; + + cs = GNUNET_new (struct ChallengeState); + cs->expected_cs = expected_cs; + cs->challenge_ref = challenge_ref; + cs->payment_ref = payment_ref; + cs->challenge_index = challenge_index; + { + struct TALER_TESTING_Command cmd = { + .cls = cs, + .label = label, + .run = &challenge_start_run, + .cleanup = &challenge_cleanup, + .traits = &challenge_create_traits + }; + + return cmd; + } +} + + +struct TALER_TESTING_Command +ANASTASIS_TESTING_cmd_challenge_answer ( + const char *label, + const char *payment_ref, + const char *challenge_ref, + unsigned int challenge_index, + const char *answer, + unsigned int mode, + enum ANASTASIS_ChallengeStatus expected_cs) +{ + struct ChallengeState *cs; + + cs = GNUNET_new (struct ChallengeState); + cs->expected_cs = expected_cs; + cs->challenge_ref = challenge_ref; + cs->payment_ref = payment_ref; + cs->answer = answer; + cs->challenge_index = challenge_index; + cs->mode = mode; + { + struct TALER_TESTING_Command cmd = { + .cls = cs, + .label = label, + .run = &challenge_answer_run, + .cleanup = &challenge_cleanup, + .traits = &challenge_create_traits + }; + + return cmd; + } +} + + +/* end of testing_cmd_challenge_answer.c */ diff --git a/src/testing/testing_cmd_policy_create.c b/src/testing/testing_cmd_policy_create.c new file mode 100644 index 0000000..fc9ed44 --- /dev/null +++ b/src/testing/testing_cmd_policy_create.c @@ -0,0 +1,208 @@ +/* + 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_cmd_policy_create.c + * @brief command to execute the anastasis secret share service + * @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 "policy create" CMD. + */ +struct PolicyCreateState +{ + /** + * The interpreter state. + */ + struct TALER_TESTING_Interpreter *is; + + /** + * Label of this command. + */ + const char *label; + + /** + * References to upload commands of previous truth uploads. + */ + const char **cmd_label_array; + + /** + * Length of array of command labels (cmd_label_array). + */ + unsigned int cmd_label_array_length; + + /** + * Policy object + */ + struct ANASTASIS_Policy *policy; +}; + + +/** + * Run a "policy create" CMD. + * + * @param cls closure. + * @param cmd command currently being run. + * @param is interpreter state. + */ +static void +policy_create_run (void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is) +{ + struct PolicyCreateState *pcs = cls; + const struct ANASTASIS_Truth *truths[pcs->cmd_label_array_length]; + + GNUNET_assert (pcs->cmd_label_array_length > 0); + GNUNET_assert (NULL != pcs->cmd_label_array); + pcs->is = is; + if (NULL != pcs->cmd_label_array) + { + for (unsigned int i = 0; i < pcs->cmd_label_array_length; i++) + { + const struct TALER_TESTING_Command *ref; + const struct ANASTASIS_Truth *truth; + + ref = TALER_TESTING_interpreter_lookup_command (is, + pcs->cmd_label_array[i]); + if (NULL == ref) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (pcs->is); + return; + } + if (GNUNET_OK != + ANASTASIS_TESTING_get_trait_truth (ref, + 0, + &truth)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (pcs->is); + return; + } + GNUNET_assert (NULL != truth); + truths[i] = truth; + } + } + + pcs->policy = ANASTASIS_policy_create (truths, + pcs->cmd_label_array_length); + + if (NULL == pcs->policy) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (pcs->is); + return; + } + TALER_TESTING_interpreter_next (pcs->is); +} + + +/** + * Free the state of a "policy create" CMD, and possibly + * cancel it if it did not complete. + * + * @param cls closure. + * @param cmd command being freed. + */ +static void +policy_create_cleanup (void *cls, + const struct TALER_TESTING_Command *cmd) +{ + struct PolicyCreateState *pcs = cls; + + GNUNET_free (pcs->cmd_label_array); + if (NULL != pcs->policy) + { + ANASTASIS_policy_destroy (pcs->policy); + pcs->policy = NULL; + } + GNUNET_free (pcs); +} + + +/** + * Offer internal data to other commands. + * + * @param cls closure + * @param ret[out] result (could be anything) + * @param trait name of the trait + * @param index index number of the object to extract. + * @return #GNUNET_OK on success + */ +static int +policy_create_traits (void *cls, + const void **ret, + const char *trait, + unsigned int index) +{ + struct PolicyCreateState *pcs = cls; + struct TALER_TESTING_Trait traits[] = { + ANASTASIS_TESTING_make_trait_policy (0, + pcs->policy), + TALER_TESTING_trait_end () + }; + + return TALER_TESTING_get_trait (traits, + ret, + trait, + index); +} + + +struct TALER_TESTING_Command +ANASTASIS_TESTING_cmd_policy_create (const char *label, + ...) +{ + struct PolicyCreateState *pcs; + va_list ap; + const char *truth_upload_cmd; + + pcs = GNUNET_new (struct PolicyCreateState); + pcs->label = label; + + va_start (ap, + label); + while (NULL != (truth_upload_cmd = va_arg (ap, const char *))) + { + GNUNET_array_append (pcs->cmd_label_array, + pcs->cmd_label_array_length, + truth_upload_cmd); + } + va_end (ap); + { + struct TALER_TESTING_Command cmd = { + .cls = pcs, + .label = label, + .run = &policy_create_run, + .cleanup = &policy_create_cleanup, + .traits = &policy_create_traits + }; + + return cmd; + } +} + + +/* end of testing_cmd_policy_create.c */ diff --git a/src/testing/testing_cmd_recover_secret.c b/src/testing/testing_cmd_recover_secret.c new file mode 100644 index 0000000..a95bdd2 --- /dev/null +++ b/src/testing/testing_cmd_recover_secret.c @@ -0,0 +1,518 @@ +/* + This file is part of Anastasis + Copyright (C) 2020, 2021 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_cmd_recover_secret.c + * @brief command to execute the anastasis recovery service + * @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 "recover secret" CMD. + */ +struct RecoverSecretState +{ + /** + * The interpreter state. + */ + struct TALER_TESTING_Interpreter *is; + + /** + * URL of the anastasis backend. + */ + const char *anastasis_url; + + /** + * The /policy GET operation handle. + */ + struct ANASTASIS_Recovery *recovery; + + /** + * Reference to download command we expect to lookup. + */ + const char *download_reference; + + /** + * Reference to download command we expect to lookup. + */ + const char *core_secret_reference; + + /** + * Options for how we are supposed to do the download. + */ + enum ANASTASIS_TESTING_RecoverSecretOption rsopt; + + /** + * Identification data from the user + */ + json_t *id_data; + + /** + * Salt to be used to derive the id + */ + struct ANASTASIS_CRYPTO_ProviderSaltP *salt; + + /** + * Recovery information from the lookup + */ + struct ANASTASIS_RecoveryInformation *ri; + + /** + * Coresecret to check if decryption worked + */ + const void *core_secret; + + /** + * Task scheduled to wait for recovery to complete. + */ + struct GNUNET_SCHEDULER_Task *recovery_task; + + /** + * version of the recovery document + */ + unsigned int version; + + /** + * #GNUNET_OK if the secret was recovered, #GNUNET_SYSERR if + * recovery failed (yielded wrong secret). + */ + int recovered; +}; + + +/** + * Callback which passes back the recovery document and its possible + * policies. Also passes back the version of the document for the user + * to check. + * + * @param cls closure for the callback + * @param ri recovery information struct which contains the policies + */ +static void +policy_lookup_cb (void *cls, + const struct ANASTASIS_RecoveryInformation *ri) +{ + struct RecoverSecretState *rss = cls; + + rss->ri = (struct ANASTASIS_RecoveryInformation *) ri; + if (NULL == ri) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (rss->is); + return; + } + TALER_TESTING_interpreter_next (rss->is); +} + + +/** + * This function is called whenever the recovery process ends. + * On success, the secret is returned in @a secret. + * + * @param cls closure + * @param ec error code + * @param secret contains the core secret which is passed to the user + * @param secret_size defines the size of the core secret + */ +static void +core_secret_cb (void *cls, + enum ANASTASIS_RecoveryStatus rc, + const void *secret, + size_t secret_size) +{ + struct RecoverSecretState *rss = cls; + + rss->recovery = NULL; + if (ANASTASIS_RS_SUCCESS != rc) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Recovery failed with status %d\n", + rc); + TALER_TESTING_interpreter_fail (rss->is); + return; + } + if (0 != memcmp (secret, + rss->core_secret, + secret_size)) + { + GNUNET_break (0); + rss->recovered = GNUNET_SYSERR; + if (NULL != rss->recovery_task) + { + GNUNET_SCHEDULER_cancel (rss->recovery_task); + rss->recovery_task = NULL; + TALER_TESTING_interpreter_fail (rss->is); + } + return; + } + rss->recovered = GNUNET_OK; + if (NULL != rss->recovery_task) + { + GNUNET_SCHEDULER_cancel (rss->recovery_task); + rss->recovery_task = NULL; + TALER_TESTING_interpreter_next (rss->is); + } +} + + +/** + * Run a "recover secret" CMD. + * + * @param cls closure. + * @param cmd command currently being run. + * @param is interpreter state. + */ +static void +recover_secret_run (void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is) +{ + struct RecoverSecretState *rss = cls; + const struct TALER_TESTING_Command *ref; + const struct ANASTASIS_CRYPTO_ProviderSaltP *salt; + rss->is = is; + + if (NULL != rss->download_reference) + { + ref = TALER_TESTING_interpreter_lookup_command + (is, + rss->download_reference); + if (NULL == ref) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (rss->is); + return; + } + if (GNUNET_OK != + ANASTASIS_TESTING_get_trait_salt (ref, + 0, + &salt)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (rss->is); + return; + } + } + if (NULL != rss->core_secret_reference) + { + ref = TALER_TESTING_interpreter_lookup_command + (is, + rss->core_secret_reference); + if (NULL == ref) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (rss->is); + return; + } + if (GNUNET_OK != + ANASTASIS_TESTING_get_trait_core_secret (ref, + 0, + &rss->core_secret)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (rss->is); + return; + } + } + rss->recovery = ANASTASIS_recovery_begin (is->ctx, + rss->id_data, + rss->version, + rss->anastasis_url, + salt, + &policy_lookup_cb, + rss, + &core_secret_cb, + rss); + if (NULL == rss->recovery) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (rss->is); + return; + } +} + + +/** + * Task to run the abort routine on the given @a cls object + * after the stack has fully unwound. + * + * @param cls a `struct ANASTASIS_Recovery *` + */ +static void +delayed_abort (void *cls) +{ + struct ANASTASIS_Recovery *recovery = cls; + + ANASTASIS_recovery_abort (recovery); +} + + +/** + * Free the state of a "recover secret" CMD, and possibly + * cancel it if it did not complete. + * + * @param cls closure + * @param cmd command being freed. + */ +static void +recover_secret_cleanup (void *cls, + const struct TALER_TESTING_Command *cmd) +{ + struct RecoverSecretState *rss = cls; + + if (NULL != rss->recovery) + { + /* must run first, or at least before #core_secret_cb */ + (void) GNUNET_SCHEDULER_add_with_priority ( + GNUNET_SCHEDULER_PRIORITY_SHUTDOWN, + &delayed_abort, + rss->recovery); + rss->recovery = NULL; + } + if (NULL != rss->recovery_task) + { + GNUNET_SCHEDULER_cancel (rss->recovery_task); + rss->recovery_task = NULL; + } + json_decref (rss->id_data); + GNUNET_free (rss); +} + + +/** + * Offer internal data to other commands. + * + * @param cls closure + * @param ret[out] result (could be anything) + * @param trait name of the trait + * @param index index number of the object to extract. + * @return #GNUNET_OK on success + */ +static int +recover_secret_traits (void *cls, + const void **ret, + const char *trait, + unsigned int index) +{ + struct RecoverSecretState *rss = cls; + + if (NULL == rss->ri) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + if (index >= rss->ri->cs_len) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + { + struct TALER_TESTING_Trait traits[] = { + ANASTASIS_TESTING_make_trait_challenge (index, + rss->ri->cs[index]), + TALER_TESTING_trait_end () + }; + + return TALER_TESTING_get_trait (traits, + ret, + trait, + index); + } +} + + +/** + * Function called on timeout of the secret finishing operation. + * + * @param cls a `struct RecoverSecretState *` + */ +static void +recovery_fail (void *cls) +{ + struct RecoverSecretState *rss = cls; + + rss->recovery_task = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Timeout during secret recovery\n"); + TALER_TESTING_interpreter_fail (rss->is); +} + + +/** + * Wait @a delay for @a cmd to finish secret recovery. + * + * @param cmd command to wait on + * @param delay how long to wait at most + */ +static void +recover_secret_finish (struct TALER_TESTING_Command *cmd, + struct GNUNET_TIME_Relative delay) +{ + struct RecoverSecretState *rss = cmd->cls; + + GNUNET_assert (&recover_secret_run == cmd->run); + GNUNET_assert (NULL == rss->recovery_task); + switch (rss->recovered) + { + case GNUNET_OK: + TALER_TESTING_interpreter_next (rss->is); + break; + case GNUNET_NO: + rss->recovery_task = GNUNET_SCHEDULER_add_delayed (delay, + &recovery_fail, + rss); + break; + case GNUNET_SYSERR: + TALER_TESTING_interpreter_fail (rss->is); + break; + } +} + + +struct TALER_TESTING_Command +ANASTASIS_TESTING_cmd_recover_secret ( + const char *label, + const char *anastasis_url, + const json_t *id_data, + unsigned int version, + enum ANASTASIS_TESTING_RecoverSecretOption rso, + const char *download_ref, + const char *core_secret_ref) +{ + struct RecoverSecretState *rss; + + rss = GNUNET_new (struct RecoverSecretState); + rss->version = version; + rss->id_data = json_incref ((json_t *) id_data); + rss->rsopt = rso; + rss->anastasis_url = anastasis_url; + rss->download_reference = download_ref; + rss->core_secret_reference = core_secret_ref; + { + struct TALER_TESTING_Command cmd = { + .cls = rss, + .label = label, + .run = &recover_secret_run, + .cleanup = &recover_secret_cleanup, + .traits = &recover_secret_traits + }; + + return cmd; + } +} + + +/** + * State for a "recover secret finish" CMD. + */ +struct RecoverSecretFinishState +{ + /** + * The interpreter state. + */ + struct TALER_TESTING_Interpreter *is; + + /** + * URL of the anastasis backend. + */ + const char *recover_label; + + /** + * Timeout. + */ + struct GNUNET_TIME_Relative timeout; + +}; + + +/** + * Run a "recover secret finish" CMD. + * + * @param cls closure. + * @param cmd command currently being run. + * @param is interpreter state. + */ +static void +recover_secret_finish_run (void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is) +{ + struct RecoverSecretFinishState *rsfs = cls; + struct TALER_TESTING_Command *ref; + + rsfs->is = is; + ref = (struct TALER_TESTING_Command *) + TALER_TESTING_interpreter_lookup_command (is, + rsfs->recover_label); + if (NULL == ref) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (rsfs->is); + return; + } + recover_secret_finish (ref, + rsfs->timeout); +} + + +/** + * Free the state of a "recover secret finish" CMD, and possibly + * cancel it if it did not complete. + * + * @param cls closure + * @param cmd command being freed. + */ +static void +recover_secret_finish_cleanup (void *cls, + const struct TALER_TESTING_Command *cmd) +{ + struct RecoverSecretFinishState *rsfs = cls; + + GNUNET_free (rsfs); +} + + +struct TALER_TESTING_Command +ANASTASIS_TESTING_cmd_recover_secret_finish ( + const char *label, + const char *recover_label, + struct GNUNET_TIME_Relative timeout) +{ + struct RecoverSecretFinishState *rsfs; + + rsfs = GNUNET_new (struct RecoverSecretFinishState); + rsfs->recover_label = recover_label; + rsfs->timeout = timeout; + { + struct TALER_TESTING_Command cmd = { + .cls = rsfs, + .label = label, + .run = &recover_secret_finish_run, + .cleanup = &recover_secret_finish_cleanup + }; + + return cmd; + } +} + + +/* end of testing_cmd_recover_secret.c */ diff --git a/src/testing/testing_cmd_secret_share.c b/src/testing/testing_cmd_secret_share.c new file mode 100644 index 0000000..b80006e --- /dev/null +++ b/src/testing/testing_cmd_secret_share.c @@ -0,0 +1,441 @@ +/* + 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_cmd_secret_share.c + * @brief command to execute the anastasis secret share service + * @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> +#include <taler/taler_merchant_service.h> + + +/** + * State for a "secret share" CMD. + */ +struct SecretShareState +{ + /** + * Claim token we got back, if any. Otherwise all zeros. + */ + struct TALER_ClaimTokenP token; + + /** + * The interpreter state. + */ + struct TALER_TESTING_Interpreter *is; + + /** + * Label of this command. + */ + const char *label; + + /** + * References to commands of previous policy creations. + */ + const char **cmd_label_array; + + /** + * Data to derive user identifier from. + */ + json_t *id_data; + + /** + * The core secret to backup/recover. + */ + const void *core_secret; + + /** + * URL of the anastasis backend. + */ + const char *anastasis_url; + + /** + * URL of a /config command for the @e anastasis_url. + */ + const char *config_ref; + + /** + * The /truth GET operation handle. + */ + struct ANASTASIS_SecretShare *sso; + + /** + * Reference to previous secret share command we expect to lookup. + */ + const char *prev_secret_share; + + /** + * closure for the payment callback + */ + void *spc_cls; + + /** + * closure for the result callback + */ + void *src_cls; + + /** + * Payment order ID we got back, if any. Otherwise NULL. + */ + char *payment_order_id; + + /** + * Size of core_secret. + */ + size_t core_secret_size; + + /** + * Length of array of command labels (cmd_label_array). + */ + unsigned int cmd_label_array_length; + + /** + * Expected status code. + */ + enum ANASTASIS_ShareStatus want_status; + + /** + * Options for how we are supposed to do the upload. + */ + enum ANASTASIS_TESTING_SecretShareOption ssopt; +}; + + +/** + * Function called with the results of a #ANASTASIS_secret_share(). + * + * @param cls closure + * @param sr result from the operation + */ +static void +secret_share_result_cb (void *cls, + const struct ANASTASIS_ShareResult *sr) +{ + struct SecretShareState *sss = cls; + + sss->sso = NULL; + if (sr->ss != sss->want_status) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected response code %u to command %s in %s:%u\n", + sr->ss, + sss->is->commands[sss->is->ip].label, + __FILE__, + __LINE__); + TALER_TESTING_interpreter_fail (sss->is); + return; + } + switch (sr->ss) + { + case ANASTASIS_SHARE_STATUS_SUCCESS: + break; + case ANASTASIS_SHARE_STATUS_PAYMENT_REQUIRED: + { + struct TALER_MERCHANT_PayUriData pd; + + GNUNET_assert (0 < sr->details.payment_required.payment_requests_length); + if (GNUNET_OK != + TALER_MERCHANT_parse_pay_uri ( + sr->details.payment_required.payment_requests[0].payment_request_url, + &pd)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (sss->is); + return; + } + sss->payment_order_id = GNUNET_strdup (pd.order_id); + TALER_MERCHANT_parse_pay_uri_free (&pd); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Order ID from Anastasis service is `%s'\n", + sss->payment_order_id); + } + case ANASTASIS_SHARE_STATUS_PROVIDER_FAILED: + break; + } + TALER_TESTING_interpreter_next (sss->is); +} + + +/** + * Run a "secret share" CMD. + * + * @param cls closure. + * @param cmd command currently being run. + * @param is interpreter state. + */ +static void +secret_share_run (void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is) +{ + struct SecretShareState *sss = cls; + const struct ANASTASIS_Policy *policies[sss->cmd_label_array_length]; + struct ANASTASIS_ProviderDetails pds; + + GNUNET_assert (sss->cmd_label_array_length > 0); + GNUNET_assert (NULL != sss->cmd_label_array); + sss->is = is; + if (NULL != sss->cmd_label_array) + { + for (unsigned int i = 0; i < sss->cmd_label_array_length; i++) + { + const struct TALER_TESTING_Command *ref; + const struct ANASTASIS_Policy *policy; + + ref = TALER_TESTING_interpreter_lookup_command (is, + sss->cmd_label_array[i]); + if (NULL == ref) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (sss->is); + return; + } + if (GNUNET_OK != + ANASTASIS_TESTING_get_trait_policy (ref, + 0, + &policy)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (sss->is); + return; + } + GNUNET_assert (NULL != policy); + policies[i] = policy; + } + } + + if (NULL != sss->prev_secret_share) + { + const struct TALER_TESTING_Command *ref; + const char *order_id; + + ref = TALER_TESTING_interpreter_lookup_command (is, + sss->prev_secret_share); + if (NULL == ref) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (sss->is); + return; + } + if (GNUNET_OK != + TALER_TESTING_get_trait_order_id (ref, + 0, + &order_id)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (sss->is); + return; + } + sss->payment_order_id = (char *) order_id; + + if (NULL == sss->payment_order_id) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (sss->is); + return; + } + } + + memset (&pds, + 0, + sizeof (pds)); + if (NULL != sss->payment_order_id) + { + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data ( + sss->payment_order_id, + strlen (sss->payment_order_id), + &pds.payment_secret, + sizeof (struct ANASTASIS_PaymentSecretP))) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (sss->is); + GNUNET_free (sss->payment_order_id); + return; + } + GNUNET_free (sss->payment_order_id); + } + pds.provider_url = sss->anastasis_url; + { + const struct TALER_TESTING_Command *ref; + const struct ANASTASIS_CRYPTO_ProviderSaltP *salt; + + ref = TALER_TESTING_interpreter_lookup_command (is, + sss->config_ref); + if (NULL == ref) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (sss->is); + return; + } + if (GNUNET_OK != + ANASTASIS_TESTING_get_trait_salt (ref, + 0, + &salt)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (sss->is); + return; + } + pds.provider_salt = *salt; + } + + sss->sso = ANASTASIS_secret_share (is->ctx, + sss->id_data, + &pds, + 1, + policies, + sss->cmd_label_array_length, + false, + GNUNET_TIME_UNIT_ZERO, + &secret_share_result_cb, + sss, + "test-case", + sss->core_secret, + sss->core_secret_size); + if (NULL == sss->sso) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (sss->is); + return; + } +} + + +/** + * Free the state of a "secret share" CMD, and possibly + * cancel it if it did not complete. + * + * @param cls closure. + * @param cmd command being freed. + */ +static void +secret_share_cleanup (void *cls, + const struct TALER_TESTING_Command *cmd) +{ + struct SecretShareState *sss = cls; + + if (NULL != sss->cmd_label_array) + { + GNUNET_free (sss->cmd_label_array); + } + if (NULL != sss->sso) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Command '%s' did not complete\n", + cmd->label); + ANASTASIS_secret_share_cancel (sss->sso); + sss->sso = NULL; + } + json_decref (sss->id_data); + GNUNET_free (sss); +} + + +/** + * Offer internal data to other commands. + * + * @param cls closure + * @param ret[out] result (could be anything) + * @param trait name of the trait + * @param index index number of the object to extract. + * @return #GNUNET_OK on success + */ +static int +secret_share_traits (void *cls, + const void **ret, + const char *trait, + unsigned int index) +{ + struct SecretShareState *sss = cls; + struct TALER_TESTING_Trait traits[] = { + TALER_TESTING_make_trait_claim_token (0, + &sss->token), + ANASTASIS_TESTING_make_trait_core_secret (0, + sss->core_secret), + TALER_TESTING_make_trait_order_id (0, + sss->payment_order_id), + TALER_TESTING_trait_end () + }; + + return TALER_TESTING_get_trait (traits, + ret, + trait, + index); +} + + +struct TALER_TESTING_Command +ANASTASIS_TESTING_cmd_secret_share ( + const char *label, + const char *anastasis_url, + const char *config_ref, + const char *prev_secret_share, + const json_t *id_data, + const void *core_secret, + size_t core_secret_size, + enum ANASTASIS_ShareStatus want_status, + enum ANASTASIS_TESTING_SecretShareOption sso, + ...) +{ + struct SecretShareState *sss; + + sss = GNUNET_new (struct SecretShareState); + sss->want_status = want_status; + sss->ssopt = sso; + sss->anastasis_url = anastasis_url; + sss->config_ref = config_ref; + sss->label = label; + sss->id_data = json_incref ((json_t *) id_data); + sss->core_secret = core_secret; + sss->core_secret_size = core_secret_size; + sss->prev_secret_share = prev_secret_share; + + { + const char *policy_create_cmd; + va_list ap; + + va_start (ap, + sso); + while (NULL != (policy_create_cmd = va_arg (ap, const char *))) + { + GNUNET_array_append (sss->cmd_label_array, + sss->cmd_label_array_length, + policy_create_cmd); + } + va_end (ap); + } + { + struct TALER_TESTING_Command cmd = { + .cls = sss, + .label = label, + .run = &secret_share_run, + .cleanup = &secret_share_cleanup, + .traits = &secret_share_traits + }; + + return cmd; + } +} + + +/* end of testing_cmd_secret_share.c */ diff --git a/src/testing/testing_cmd_truth_upload.c b/src/testing/testing_cmd_truth_upload.c new file mode 100644 index 0000000..f9149d5 --- /dev/null +++ b/src/testing/testing_cmd_truth_upload.c @@ -0,0 +1,383 @@ +/* + 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_cmd_truth_upload.c + * @brief command to execute the anastasis secret share service + * @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 "truth upload" CMD. + */ +struct TruthUploadState +{ + /** + * The interpreter state. + */ + struct TALER_TESTING_Interpreter *is; + + /** + * URL of the anastasis backend. + */ + const char *anastasis_url; + + /** + * Label of this command. + */ + const char *label; + + /** + * The ID data to generate user identifier + */ + json_t *id_data; + + /** + * The escrow method + */ + const char *method; + + /** + * Instructions to be returned to client/user + * (e.g. "Look at your smartphone. SMS was sent to you") + */ + const char *instructions; + + /** + * Mime type of truth_data (eg. jpeg, string etc.) + */ + const char *mime_type; + + /** + * The truth_data (e.g. hash of answer to a secure question) + */ + void *truth_data; + + /** + * Requested order ID for this upload (if unpaid). + */ + struct ANASTASIS_PaymentSecretP payment_secret_response; + + /** + * Size of truth_data + */ + size_t truth_data_size; + + /** + * Expected status code. + */ + unsigned int http_status; + + /** + * The /truth POST operation handle. + */ + struct ANASTASIS_TruthUpload *tuo; + + /** + * closure for the payment callback + */ + void *tpc_cls; + + /** + * Reference to salt download. + */ + const char *salt_reference; + + /** + * Options for how we are supposed to do the upload. + */ + enum ANASTASIS_TESTING_TruthStoreOption tsopt; + + /** + * Truth object + */ + struct ANASTASIS_Truth *truth; +}; + + +/** + * Upload information + * caller MUST free 't' using ANASTASIS_truth_free() + * + * @param cls closure for callback + * @param t Truth object (contains provider url and truth public key) + * @param ud upload details, useful to continue in case of errors, NULL on success + */ +static void +truth_upload_cb (void *cls, + struct ANASTASIS_Truth *t, + const struct ANASTASIS_UploadDetails *ud) +{ + struct TruthUploadState *tus = cls; + + tus->tuo = NULL; + if (NULL == ud) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (tus->is); + return; + } + if (ud->http_status != tus->http_status) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (tus->is); + return; + } + if (MHD_HTTP_PAYMENT_REQUIRED == ud->http_status) + { + if (ANASTASIS_US_PAYMENT_REQUIRED != ud->us) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (tus->is); + return; + } + tus->payment_secret_response = ud->details.payment.ps; + TALER_TESTING_interpreter_next (tus->is); + return; + } + if ( (ANASTASIS_US_SUCCESS == ud->us) && + (NULL == t) ) + { + GNUNET_break (0); + TALER_TESTING_interpreter_next (tus->is); + return; + } + tus->truth = t; + TALER_TESTING_interpreter_next (tus->is); +} + + +/** + * Run a "truth upload" CMD. + * + * @param cls closure. + * @param cmd command currently being run. + * @param is interpreter state. + */ +static void +truth_upload_run (void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is) +{ + struct TruthUploadState *tus = cls; + const struct TALER_TESTING_Command *ref; + const struct ANASTASIS_CRYPTO_ProviderSaltP *salt; + struct ANASTASIS_CRYPTO_UserIdentifierP user_id; + + tus->is = is; + if (NULL != tus->salt_reference) + { + ref = TALER_TESTING_interpreter_lookup_command + (is, + tus->salt_reference); + if (NULL == ref) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (tus->is); + return; + } + if (GNUNET_OK != + ANASTASIS_TESTING_get_trait_salt (ref, + 0, + &salt)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (tus->is); + return; + } + } + + ANASTASIS_CRYPTO_user_identifier_derive (tus->id_data, + salt, + &user_id); + + tus->tuo = ANASTASIS_truth_upload (is->ctx, + &user_id, + tus->anastasis_url, + tus->method, + tus->instructions, + tus->mime_type, + salt, + tus->truth_data, + tus->truth_data_size, + false, /* force payment */ + GNUNET_TIME_UNIT_ZERO, + &truth_upload_cb, + tus); + if (NULL == tus->tuo) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (tus->is); + } +} + + +/** + * Free the state of a "truth upload" CMD, and possibly + * cancel it if it did not complete. + * + * @param cls closure. + * @param cmd command being freed. + */ +static void +truth_upload_cleanup (void *cls, + const struct TALER_TESTING_Command *cmd) +{ + struct TruthUploadState *tus = cls; + + if (NULL != tus->tuo) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Command '%s' did not complete\n", + cmd->label); + ANASTASIS_truth_upload_cancel (tus->tuo); + tus->tuo = NULL; + } + if (NULL != tus->id_data) + { + json_decref (tus->id_data); + tus->id_data = NULL; + } + if (NULL != tus->truth) + { + ANASTASIS_truth_free (tus->truth); + tus->truth = NULL; + } + GNUNET_free (tus->truth_data); + GNUNET_free (tus); +} + + +/** + * Offer internal data to other commands. + * + * @param cls closure + * @param ret[out] result (could be anything) + * @param trait name of the trait + * @param index index number of the object to extract. + * @return #GNUNET_OK on success + */ +static int +truth_upload_traits (void *cls, + const void **ret, + const char *trait, + unsigned int index) +{ + struct TruthUploadState *tus = cls; + struct TALER_TESTING_Trait traits[] = { + ANASTASIS_TESTING_make_trait_truth (0, + tus->truth), + ANASTASIS_TESTING_make_trait_payment_secret (0, + &tus->payment_secret_response), + TALER_TESTING_trait_end () + }; + + return TALER_TESTING_get_trait (traits, + ret, + trait, + index); +} + + +json_t * +ANASTASIS_TESTING_make_id_data_example (const char *id_data) +{ + json_t *id; + + id = json_pack ("{s:s}", + "id_data", id_data); + GNUNET_assert (NULL != id); + return id; +} + + +struct TALER_TESTING_Command +ANASTASIS_TESTING_cmd_truth_upload ( + const char *label, + const char *anastasis_url, + const json_t *id_data, + const char *method, + const char *instructions, + const char *mime_type, + const void *truth_data, + size_t truth_data_size, + unsigned int http_status, + enum ANASTASIS_TESTING_TruthStoreOption tso, + const char *salt_ref) +{ + struct TruthUploadState *tus; + + tus = GNUNET_new (struct TruthUploadState); + tus->label = label; + tus->http_status = http_status; + tus->tsopt = tso; + tus->anastasis_url = anastasis_url; + tus->salt_reference = salt_ref; + tus->id_data = json_incref ((json_t *) id_data); + tus->method = method; + tus->instructions = instructions; + tus->mime_type = mime_type; + tus->truth_data_size = truth_data_size; + tus->truth_data = GNUNET_memdup (truth_data, + truth_data_size); + { + struct TALER_TESTING_Command cmd = { + .cls = tus, + .label = label, + .run = &truth_upload_run, + .cleanup = &truth_upload_cleanup, + .traits = &truth_upload_traits + }; + + return cmd; + } +} + + +struct TALER_TESTING_Command +ANASTASIS_TESTING_cmd_truth_upload_question ( + const char *label, + const char *anastasis_url, + const json_t *id_data, + const char *instructions, + const char *mime_type, + const void *answer, + unsigned int http_status, + enum ANASTASIS_TESTING_TruthStoreOption tso, + const char *salt_ref) +{ + return ANASTASIS_TESTING_cmd_truth_upload (label, + anastasis_url, + id_data, + "question", + instructions, + mime_type, + answer, + strlen (answer), + http_status, + tso, + salt_ref); +} + + +/* end of testing_cmd_truth_upload.c */ diff --git a/src/testing/testing_trait_challenge.c b/src/testing/testing_trait_challenge.c new file mode 100644 index 0000000..5c40d8e --- /dev/null +++ b/src/testing/testing_trait_challenge.c @@ -0,0 +1,72 @@ +/* + This file is part of TALER + Copyright (C) 2020 Taler Systems SA + + TALER 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. + + TALER 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 TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file lib/testing_trait_challenge.c + * @brief traits to offer a challenge + * @author Christian Grothoff + * @author Dominik Meister + * @author Dennis Neufeld + */ +#include "platform.h" +#include "anastasis_testing_lib.h" + +#define ANASTASIS_TESTING_TRAIT_CHALLENGE "anastasis-challenge" + +/** + * Obtain a challenge from @a cmd. + * + * @param cmd command to extract the challenge from. + * @param index the index of the challenge + * @param c[out] set to the challenge coming from @a cmd. + * @return #GNUNET_OK on success. + */ +int +ANASTASIS_TESTING_get_trait_challenge (const struct TALER_TESTING_Command *cmd, + unsigned int index, + const struct ANASTASIS_Challenge **c) +{ + return cmd->traits (cmd->cls, + (const void **) c, + ANASTASIS_TESTING_TRAIT_CHALLENGE, + index); +} + + +/** + * Offer a challenge. + * + * @param index the challenge index number. + * @param c the challenge to offer. + * @return #GNUNET_OK on success. + */ +struct TALER_TESTING_Trait +ANASTASIS_TESTING_make_trait_challenge + (unsigned int index, + const struct ANASTASIS_Challenge *c) +{ + struct TALER_TESTING_Trait ret = { + .index = index, + .trait_name = ANASTASIS_TESTING_TRAIT_CHALLENGE, + .ptr = (const void *) c + }; + return ret; +} + + +/* end of testing_trait_challenge.c */ diff --git a/src/testing/testing_trait_core_secret.c b/src/testing/testing_trait_core_secret.c new file mode 100644 index 0000000..100a249 --- /dev/null +++ b/src/testing/testing_trait_core_secret.c @@ -0,0 +1,74 @@ +/* + This file is part of TALER + Copyright (C) 2020 Taler Systems SA + + TALER 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. + + TALER 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 TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file lib/testing_trait_core_secret.c + * @brief traits to offer the core secret + * @author Christian Grothoff + * @author Dominik Meister + * @author Dennis Neufeld + */ +#include "platform.h" +#include "anastasis_testing_lib.h" + +#define ANASTASIS_TESTING_TRAIT_CORE_SECRET "anastasis-core-secret" + + +/** + * Obtain the core secret from @a cmd. + * + * @param cmd command to extract the core secret from. + * @param index the index of the core secret (usually 0) + * @param s[out] set to the core secret coming from @a cmd. + * @return #GNUNET_OK on success. + */ +int +ANASTASIS_TESTING_get_trait_core_secret (const struct + TALER_TESTING_Command *cmd, + unsigned int index, + const void **s) +{ + return cmd->traits (cmd->cls, + s, + ANASTASIS_TESTING_TRAIT_CORE_SECRET, + index); +} + + +/** + * Offer the core secret. + * + * @param index the core secret's index number (usually 0). + * @param s the core secret to offer. + * @return #GNUNET_OK on success. + */ +struct TALER_TESTING_Trait +ANASTASIS_TESTING_make_trait_core_secret + (unsigned int index, + const void *s) +{ + struct TALER_TESTING_Trait ret = { + .index = index, + .trait_name = ANASTASIS_TESTING_TRAIT_CORE_SECRET, + .ptr = s + }; + return ret; +} + + +/* end of testing_trait_core_secret.c */ diff --git a/src/testing/testing_trait_policy.c b/src/testing/testing_trait_policy.c new file mode 100644 index 0000000..45e773c --- /dev/null +++ b/src/testing/testing_trait_policy.c @@ -0,0 +1,73 @@ +/* + This file is part of TALER + Copyright (C) 2020 Taler Systems SA + + TALER 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. + + TALER 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 TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file lib/testing_trait_policy.c + * @brief traits to offer a policy + * @author Christian Grothoff + * @author Dominik Meister + * @author Dennis Neufeld + */ +#include "platform.h" +#include "anastasis_testing_lib.h" + +#define ANASTASIS_TESTING_TRAIT_POLICY "anastasis-policy" + + +/** + * Obtain a policy from @a cmd. + * + * @param cmd command to extract the policy from. + * @param index the index of the policy + * @param t[out] set to the policy coming from @a cmd. + * @return #GNUNET_OK on success. + */ +int +ANASTASIS_TESTING_get_trait_policy (const struct TALER_TESTING_Command *cmd, + unsigned int index, + const struct ANASTASIS_Policy **p) +{ + return cmd->traits (cmd->cls, + (const void **) p, + ANASTASIS_TESTING_TRAIT_POLICY, + index); +} + + +/** + * Offer a policy. + * + * @param index the policy's index number. + * @param t the policy to offer. + * @return #GNUNET_OK on success. + */ +struct TALER_TESTING_Trait +ANASTASIS_TESTING_make_trait_policy + (unsigned int index, + const struct ANASTASIS_Policy *p) +{ + struct TALER_TESTING_Trait ret = { + .index = index, + .trait_name = ANASTASIS_TESTING_TRAIT_POLICY, + .ptr = (const void *) p + }; + return ret; +} + + +/* end of testing_trait_policy.c */ diff --git a/src/testing/testing_trait_truth.c b/src/testing/testing_trait_truth.c new file mode 100644 index 0000000..51696e1 --- /dev/null +++ b/src/testing/testing_trait_truth.c @@ -0,0 +1,73 @@ +/* + This file is part of TALER + Copyright (C) 2020 Taler Systems SA + + TALER 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. + + TALER 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 TALER; see the file COPYING. If not, see + <http://www.gnu.org/licenses/> +*/ +/** + * @file lib/testing_trait_truth.c + * @brief traits to offer a truth + * @author Christian Grothoff + * @author Dominik Meister + * @author Dennis Neufeld + */ +#include "platform.h" +#include "anastasis_testing_lib.h" + +#define ANASTASIS_TESTING_TRAIT_TRUTH "anastasis-truth" + + +/** + * Obtain a truth from @a cmd. + * + * @param cmd command to extract the truth from. + * @param index the index of the truth + * @param t[out] set to the truth coming from @a cmd. + * @return #GNUNET_OK on success. + */ +int +ANASTASIS_TESTING_get_trait_truth (const struct TALER_TESTING_Command *cmd, + unsigned int index, + const struct ANASTASIS_Truth **t) +{ + return cmd->traits (cmd->cls, + (const void **) t, + ANASTASIS_TESTING_TRAIT_TRUTH, + index); +} + + +/** + * Offer a truth. + * + * @param index the truth's index number. + * @param t the truth to offer. + * @return #GNUNET_OK on success. + */ +struct TALER_TESTING_Trait +ANASTASIS_TESTING_make_trait_truth + (unsigned int index, + const struct ANASTASIS_Truth *t) +{ + struct TALER_TESTING_Trait ret = { + .index = index, + .trait_name = ANASTASIS_TESTING_TRAIT_TRUTH, + .ptr = (const void *) t + }; + return ret; +} + + +/* end of testing_trait_truth.c */ |