From cf4b6ebd6de3370da4b16d2f1ef19a2a3d3d0b12 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 2 Mar 2022 23:39:26 +0100 Subject: push new /truth/ API through the entire implementation --- src/testing/Makefile.am | 3 +- src/testing/test_anastasis.c | 10 +- src/testing/test_anastasis_api.c | 30 +- src/testing/testing_api_cmd_keyshare_lookup.c | 465 -------------------------- src/testing/testing_api_cmd_truth_challenge.c | 372 +++++++++++++++++++++ src/testing/testing_api_cmd_truth_solve.c | 409 ++++++++++++++++++++++ src/testing/testing_cmd_challenge_answer.c | 230 +++++++------ 7 files changed, 936 insertions(+), 583 deletions(-) delete mode 100644 src/testing/testing_api_cmd_keyshare_lookup.c create mode 100644 src/testing/testing_api_cmd_truth_challenge.c create mode 100644 src/testing/testing_api_cmd_truth_solve.c (limited to 'src/testing') diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am index 9a98530..fec971a 100644 --- a/src/testing/Makefile.am +++ b/src/testing/Makefile.am @@ -14,9 +14,10 @@ libanastasistesting_la_LDFLAGS = \ -no-undefined libanastasistesting_la_SOURCES = \ testing_api_cmd_policy_store.c \ + testing_api_cmd_truth_challenge.c \ + testing_api_cmd_truth_solve.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_traits.c \ diff --git a/src/testing/test_anastasis.c b/src/testing/test_anastasis.c index 6ce6771..7b127ac 100644 --- a/src/testing/test_anastasis.c +++ b/src/testing/test_anastasis.c @@ -280,7 +280,7 @@ run (void *cls, 0, /* challenge index */ "SomeTruth1", 0, /* mode */ - ANASTASIS_CHALLENGE_STATUS_SOLVED), + ANASTASIS_CHALLENGE_ANSWER_STATUS_SOLVED), #if 0 ANASTASIS_TESTING_cmd_challenge_answer ("challenge-answer-2", NULL, /* payment ref */ @@ -288,13 +288,13 @@ run (void *cls, 1, /* challenge index */ "SomeTruth2", 0, /* mode */ - ANASTASIS_CHALLENGE_STATUS_SOLVED), + ANASTASIS_CHALLENGE_ANSWER_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), + ANASTASIS_CHALLENGE_START_STATUS_PAYMENT_REQUIRED), TALER_TESTING_cmd_merchant_claim_order ("fetch-challenge-pay-proposal", merchant_url, MHD_HTTP_OK, @@ -312,14 +312,14 @@ run (void *cls, "challenge-start-3-pay", /* payment ref */ "recover-secret-1", 2, /* challenge index */ - ANASTASIS_CHALLENGE_STATUS_INSTRUCTIONS), + ANASTASIS_CHALLENGE_START_STATUS_FILENAME_PROVIDED), 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_CHALLENGE_ANSWER_STATUS_SOLVED), ANASTASIS_TESTING_cmd_recover_secret_finish ("recover-finish-1", "recover-secret-1", GNUNET_TIME_UNIT_SECONDS), diff --git a/src/testing/test_anastasis_api.c b/src/testing/test_anastasis_api.c index b8d9608..caa59c8 100644 --- a/src/testing/test_anastasis_api.c +++ b/src/testing/test_anastasis_api.c @@ -209,14 +209,14 @@ run (void *cls, "The-Answer", ANASTASIS_TESTING_TSO_NONE, MHD_HTTP_NO_CONTENT), - ANASTASIS_TESTING_cmd_keyshare_lookup ( + ANASTASIS_TESTING_cmd_truth_solve ( "keyshare-lookup-1", anastasis_url, "The-Answer", NULL, /* payment ref */ "truth-store-1", 0, - ANASTASIS_KSD_SUCCESS), + MHD_HTTP_OK), ANASTASIS_TESTING_cmd_truth_store ( "truth-store-2", anastasis_url, @@ -227,22 +227,20 @@ run (void *cls, file_secret, ANASTASIS_TESTING_TSO_NONE, MHD_HTTP_NO_CONTENT), - ANASTASIS_TESTING_cmd_keyshare_lookup ( + ANASTASIS_TESTING_cmd_truth_solve ( "challenge-fail-1", anastasis_url, "Wrong-Answer", - NULL, - "truth-store-1", - 0, - ANASTASIS_KSD_INVALID_ANSWER), - ANASTASIS_TESTING_cmd_keyshare_lookup ( + NULL, /* payment ref */ + "truth-store-1", /* upload ref */ + 0, /* security question mode */ + MHD_HTTP_FORBIDDEN), + ANASTASIS_TESTING_cmd_truth_challenge ( "file-challenge-run-1", anastasis_url, - NULL, /* no answer */ NULL, /* payment ref */ "truth-store-2", /* upload ref */ - 0, - ANASTASIS_KSD_PAYMENT_REQUIRED), + MHD_HTTP_PAYMENT_REQUIRED), /* what would we have to pay? */ TALER_TESTING_cmd_merchant_claim_order ("fetch-proposal-2", merchant_url, @@ -259,22 +257,20 @@ run (void *cls, "EUR:1", NULL), - ANASTASIS_TESTING_cmd_keyshare_lookup ( + ANASTASIS_TESTING_cmd_truth_challenge ( "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 ( + MHD_HTTP_OK), + ANASTASIS_TESTING_cmd_truth_solve ( "file-challenge-run-3", anastasis_url, "file-challenge-run-2", /* answer */ "file-challenge-run-1", /* payment ref */ "truth-store-2", 1, - ANASTASIS_KSD_SUCCESS), + MHD_HTTP_OK), TALER_TESTING_cmd_end () }; diff --git a/src/testing/testing_api_cmd_keyshare_lookup.c b/src/testing/testing_api_cmd_keyshare_lookup.c deleted file mode 100644 index 8b06a67..0000000 --- a/src/testing/testing_api_cmd_keyshare_lookup.c +++ /dev/null @@ -1,465 +0,0 @@ -/* - This file is part of Anastasis - Copyright (C) 2020 Anastasis SARL - - Anastasis is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Anastasis; see the file COPYING.GPL. If not, see -*/ -/** - * @file testing/testing_api_cmd_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 -#include -#include - - -/** - * 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; - case ANASTASIS_KSD_AUTHENTICATION_TIMEOUT: - break; - case ANASTASIS_KSD_EXTERNAL_CHALLENGE_INSTRUCTIONS: - 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 **answerp; - - 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 != - ANASTASIS_TESTING_get_trait_filename (upload_cmd, - &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, - &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, - &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, - &answerp)) - { - GNUNET_break (0); - TALER_TESTING_interpreter_fail (ksls->is); - return; - } - if (NULL == *answerp) - { - GNUNET_break (0); - TALER_TESTING_interpreter_fail (ksls->is); - return; - } - } - else - { - /* answer is the answer */ - answerp = &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, - &payment_secret)) - { - GNUNET_break (0); - TALER_TESTING_interpreter_fail (ksls->is); - return; - } - } - else - { - payment_secret = NULL; - } - - { - struct GNUNET_HashCode h_answer; - - if (NULL != *answerp) - GNUNET_CRYPTO_hash (*answerp, - strlen (*answerp), - &h_answer); - ksls->kslo = ANASTASIS_keyshare_lookup (is->ctx, - ksls->anastasis_url, - truth_uuid, - truth_key, - payment_secret, - GNUNET_TIME_UNIT_ZERO, - (NULL != *answerp) - ? &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->filename); - 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 enum GNUNET_GenericReturnValue -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 ( - &ksls->payment_secret_response), - TALER_TESTING_make_trait_payto_uri ( - (const char **) ksls->pay_uri), - TALER_TESTING_make_trait_order_id ( - (const char **) &ksls->order_id), - ANASTASIS_TESTING_make_trait_code ( - (const char **) &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_truth_challenge.c b/src/testing/testing_api_cmd_truth_challenge.c new file mode 100644 index 0000000..c584d5f --- /dev/null +++ b/src/testing/testing_api_cmd_truth_challenge.c @@ -0,0 +1,372 @@ +/* + This file is part of Anastasis + Copyright (C) 2020, 2022 Anastasis SARL + + Anastasis is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Anastasis; see the file COPYING.GPL. If not, see +*/ +/** + * @file testing/testing_api_cmd_truth_challenge.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 +#include +#include + + +/** + * State for a "keyshare lookup" CMD. + */ +struct TruthChallengeState +{ + /** + * The interpreter state. + */ + struct TALER_TESTING_Interpreter *is; + + /** + * URL of the anastasis backend. + */ + const char *anastasis_url; + + /** + * Expected HTTP status code. + */ + unsigned int expected_http_status; + + /** + * The /truth GET operation handle. + */ + struct ANASTASIS_TruthChallengeOperation *tco; + + /** + * 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; + + /** + * "code" returned by service, if any. + */ + char *code; + + /** + * "instructions" for how to solve the challenge as returned by service, if any. + */ + char *instructions; + +}; + + +static void +truth_challenge_cb (void *cls, + const struct ANASTASIS_TruthChallengeDetails *tcd) +{ + struct TruthChallengeState *ksls = cls; + + ksls->tco = NULL; + if (tcd->http_status != ksls->expected_http_status) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected response code %u to command %s in %s:%u\n", + tcd->http_status, + ksls->is->commands[ksls->is->ip].label, + __FILE__, + __LINE__); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } + switch (tcd->http_status) + { + case MHD_HTTP_OK: + switch (tcd->details.success.cs) + { + case ANASTASIS_CS_FILE_WRITTEN: + { + FILE *file; + char code[22]; + + file = fopen (tcd->details.success.details.challenge_filename, + "r"); + if (NULL == file) + { + GNUNET_log_strerror_file ( + GNUNET_ERROR_TYPE_ERROR, + "open", + tcd->details.success.details.challenge_filename); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } + if (0 == fscanf (file, + "%21s", + code)) + { + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, + "fscanf", + tcd->details.success.details. + challenge_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); + } + break; + case ANASTASIS_CS_TAN_SENT: + ksls->instructions = GNUNET_strdup ( + tcd->details.success.details.tan_address_hint); + break; + case ANASTASIS_CS_WIRE_FUNDS: + /* FIXME: not implemented */ + GNUNET_break (0); + return; + } + break; + case MHD_HTTP_PAYMENT_REQUIRED: + ksls->pay_uri = GNUNET_strdup ( + tcd->details.payment_required.payment_request); + ksls->payment_secret_response = tcd->details.payment_required.ps; + { + 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; + default: + break; + } + TALER_TESTING_interpreter_next (ksls->is); +} + + +static void +truth_challenge_run (void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is) +{ + struct TruthChallengeState *ksls = cls; + const struct ANASTASIS_CRYPTO_TruthKeyP *truth_key; + const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid; + const struct ANASTASIS_PaymentSecretP *payment_secret; + + 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; + } + if (GNUNET_OK != + ANASTASIS_TESTING_get_trait_truth_uuid (upload_cmd, + &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, + &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 (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, + &payment_secret)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } + } + else + { + payment_secret = NULL; + } + + ksls->tco = ANASTASIS_truth_challenge (is->ctx, + ksls->anastasis_url, + truth_uuid, + truth_key, + payment_secret, + &truth_challenge_cb, + ksls); + if (NULL == ksls->tco) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } +} + + +static void +truth_challenge_cleanup (void *cls, + const struct TALER_TESTING_Command *cmd) +{ + struct TruthChallengeState *ksls = cls; + + if (NULL != ksls->tco) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Command '%s' did not complete (keyshare lookup)\n", + cmd->label); + ANASTASIS_truth_challenge_cancel (ksls->tco); + ksls->tco = NULL; + } + GNUNET_free (ksls->pay_uri); + GNUNET_free (ksls->order_id); + GNUNET_free (ksls->code); + GNUNET_free (ksls->instructions); + 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 enum GNUNET_GenericReturnValue +truth_challenge_traits (void *cls, + const void **ret, + const char *trait, + unsigned int index) +{ + struct TruthChallengeState *ksls = cls; + struct TALER_TESTING_Trait traits[] = { + ANASTASIS_TESTING_make_trait_payment_secret ( + &ksls->payment_secret_response), + TALER_TESTING_make_trait_payto_uri ( + (const char **) ksls->pay_uri), + TALER_TESTING_make_trait_order_id ( + (const char **) &ksls->order_id), + ANASTASIS_TESTING_make_trait_code ( + (const char **) &ksls->code), + TALER_TESTING_trait_end () + }; + + return TALER_TESTING_get_trait (traits, + ret, + trait, + index); +} + + +struct TALER_TESTING_Command +ANASTASIS_TESTING_cmd_truth_challenge ( + const char *label, + const char *anastasis_url, + const char *payment_ref, + const char *upload_ref, + unsigned int http_status) +{ + struct TruthChallengeState *ksls; + + GNUNET_assert (NULL != upload_ref); + ksls = GNUNET_new (struct TruthChallengeState); + ksls->expected_http_status = http_status; + ksls->anastasis_url = anastasis_url; + ksls->upload_reference = upload_ref; + ksls->payment_reference = payment_ref; + { + struct TALER_TESTING_Command cmd = { + .cls = ksls, + .label = label, + .run = &truth_challenge_run, + .cleanup = &truth_challenge_cleanup, + .traits = &truth_challenge_traits + }; + + return cmd; + } +} + + +/* end of testing_api_cmd_truth_challenge.c */ diff --git a/src/testing/testing_api_cmd_truth_solve.c b/src/testing/testing_api_cmd_truth_solve.c new file mode 100644 index 0000000..5c12b3f --- /dev/null +++ b/src/testing/testing_api_cmd_truth_solve.c @@ -0,0 +1,409 @@ +/* + This file is part of Anastasis + Copyright (C) 2020, 2022 Anastasis SARL + + Anastasis is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Anastasis; see the file COPYING.GPL. If not, see +*/ +/** + * @file testing/testing_api_cmd_truth_solve.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 +#include +#include + + +/** + * State for a "keyshare lookup" CMD. + */ +struct TruthSolveState +{ + /** + * The interpreter state. + */ + struct TALER_TESTING_Interpreter *is; + + /** + * URL of the anastasis backend. + */ + const char *anastasis_url; + + /** + * Expected status code. + */ + unsigned int expected_http_status; + + /** + * Resulting encrypted key share. + * Note: currently not used. + */ + struct ANASTASIS_CRYPTO_EncryptedKeyShareP eks; + + /** + * The /truth GET operation handle. + */ + struct ANASTASIS_TruthSolveOperation *tso; + + /** + * 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 +truth_solve_cb (void *cls, + const struct ANASTASIS_TruthSolveReply *tsr) +{ + struct TruthSolveState *ksls = cls; + + ksls->tso = NULL; + if (tsr->http_status != ksls->expected_http_status) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected response code %u to command %s in %s:%u\n", + tsr->http_status, + ksls->is->commands[ksls->is->ip].label, + __FILE__, + __LINE__); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } + switch (tsr->http_status) + { + case MHD_HTTP_OK: + ksls->eks = tsr->details.success.eks; + break; + case MHD_HTTP_PAYMENT_REQUIRED: + ksls->pay_uri = GNUNET_strdup ( + tsr->details.payment_required.payment_request); + ksls->payment_secret_response = tsr->details.payment_required.ps; + ksls->order_id = GNUNET_strdup (tsr->details.payment_required.pd->order_id); + break; + default: + break; + } + TALER_TESTING_interpreter_next (ksls->is); +} + + +static void +truth_solve_run (void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is) +{ + struct TruthSolveState *ksls = cls; + const struct ANASTASIS_CRYPTO_TruthKeyP *truth_key; + const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid; + const struct ANASTASIS_PaymentSecretP *payment_secret; + const char **answerp; + + 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 != + ANASTASIS_TESTING_get_trait_filename (upload_cmd, + &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, + &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, + &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, + &answerp)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } + if (NULL == *answerp) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } + } + else + { + /* answer is the answer */ + answerp = &ksls->answer; + } + if (NULL == answerp) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } + + 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, + &payment_secret)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } + } + else + { + payment_secret = NULL; + } + + { + struct GNUNET_HashCode h_answer; + + GNUNET_CRYPTO_hash (*answerp, + strlen (*answerp), + &h_answer); + ksls->tso = ANASTASIS_truth_solve (is->ctx, + ksls->anastasis_url, + truth_uuid, + truth_key, + payment_secret, + GNUNET_TIME_UNIT_ZERO, + &h_answer, + &truth_solve_cb, + ksls); + } + if (NULL == ksls->tso) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (ksls->is); + return; + } +} + + +static void +truth_solve_cleanup (void *cls, + const struct TALER_TESTING_Command *cmd) +{ + struct TruthSolveState *ksls = cls; + + if (NULL != ksls->tso) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Command '%s' did not complete (keyshare lookup)\n", + cmd->label); + ANASTASIS_truth_solve_cancel (ksls->tso); + ksls->tso = NULL; + } + GNUNET_free (ksls->pay_uri); + GNUNET_free (ksls->order_id); + GNUNET_free (ksls->code); + GNUNET_free (ksls->filename); + 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 enum GNUNET_GenericReturnValue +truth_solve_traits (void *cls, + const void **ret, + const char *trait, + unsigned int index) +{ + struct TruthSolveState *ksls = cls; + struct TALER_TESTING_Trait traits[] = { + ANASTASIS_TESTING_make_trait_payment_secret ( + &ksls->payment_secret_response), + TALER_TESTING_make_trait_payto_uri ( + (const char **) ksls->pay_uri), + TALER_TESTING_make_trait_order_id ( + (const char **) &ksls->order_id), + ANASTASIS_TESTING_make_trait_code ( + (const char **) &ksls->code), + TALER_TESTING_trait_end () + }; + + return TALER_TESTING_get_trait (traits, + ret, + trait, + index); +} + + +struct TALER_TESTING_Command +ANASTASIS_TESTING_cmd_truth_solve ( + const char *label, + const char *anastasis_url, + const char *answer, + const char *payment_ref, + const char *upload_ref, + int lookup_mode, + unsigned int http_status) +{ + struct TruthSolveState *ksls; + + GNUNET_assert (NULL != upload_ref); + ksls = GNUNET_new (struct TruthSolveState); + ksls->expected_http_status = http_status; + 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 = &truth_solve_run, + .cleanup = &truth_solve_cleanup, + .traits = &truth_solve_traits + }; + + return cmd; + } +} + + +/* end of testing_api_cmd_truth_solve.c */ diff --git a/src/testing/testing_cmd_challenge_answer.c b/src/testing/testing_cmd_challenge_answer.c index 78f7404..88c4c2f 100644 --- a/src/testing/testing_cmd_challenge_answer.c +++ b/src/testing/testing_cmd_challenge_answer.c @@ -1,6 +1,6 @@ /* This file is part of Anastasis - Copyright (C) 2020, 2021 Anastasis SARL + Copyright (C) 2020, 2021, 2022 Anastasis SARL Anastasis is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -20,7 +20,6 @@ * @author Dennis Neufeld * @author Dominik Meister */ - #include "platform.h" #include "anastasis_testing_lib.h" #include @@ -28,6 +27,8 @@ #include +// FIXME: break up into two files, one for start, one for answer! + /** * State for a "challenge answer" CMD. */ @@ -74,9 +75,14 @@ struct ChallengeState struct ANASTASIS_PaymentSecretP payment_order_req; /** - * Expected status code. + * Expected answer status code. + */ + enum ANASTASIS_ChallengeAnswerStatus expected_acs; + + /** + * Expected start status code. */ - enum ANASTASIS_ChallengeStatus expected_cs; + enum ANASTASIS_ChallengeStartStatus expected_scs; /** * Index of the challenge we are solving @@ -98,97 +104,28 @@ struct ChallengeState static void challenge_answer_cb (void *af_cls, - const struct ANASTASIS_ChallengeStartResponse *csr) + const struct ANASTASIS_ChallengeAnswerResponse *csr) { struct ChallengeState *cs = af_cls; cs->c = NULL; - if (csr->cs != cs->expected_cs) + if (csr->cs != cs->expected_acs) { GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected status %u, got %u\n", - cs->expected_cs, + cs->expected_acs, csr->cs); TALER_TESTING_interpreter_fail (cs->is); return; } switch (csr->cs) { - case ANASTASIS_CHALLENGE_STATUS_SOLVED: + case ANASTASIS_CHALLENGE_ANSWER_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; - } - cs->code = GNUNET_malloc (22); - 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: + case ANASTASIS_CHALLENGE_ANSWER_STATUS_INVALID_ANSWER: + break; + case ANASTASIS_CHALLENGE_ANSWER_STATUS_PAYMENT_REQUIRED: if (0 != strncmp (csr->details.payment_required.taler_pay_uri, "taler+http://pay/", strlen ("taler+http://pay/"))) @@ -228,19 +165,15 @@ challenge_answer_cb (void *af_cls, } TALER_TESTING_interpreter_next (cs->is); return; - case ANASTASIS_CHALLENGE_STATUS_TRUTH_UNKNOWN: - break; - case ANASTASIS_CHALLENGE_STATUS_REDIRECT_FOR_AUTHENTICATION: + case ANASTASIS_CHALLENGE_ANSWER_STATUS_TRUTH_UNKNOWN: break; - case ANASTASIS_CHALLENGE_STATUS_SERVER_FAILURE: + case ANASTASIS_CHALLENGE_ANSWER_STATUS_SERVER_FAILURE: GNUNET_break (0); TALER_TESTING_interpreter_fail (cs->is); return; - case ANASTASIS_CHALLENGE_STATUS_RATE_LIMIT_EXCEEDED: + case ANASTASIS_CHALLENGE_ANSWER_STATUS_RATE_LIMIT_EXCEEDED: break; - case ANASTASIS_CHALLENGE_STATUS_AUTH_TIMEOUT: - break; - case ANASTASIS_CHALLENGE_STATUS_EXTERNAL_INSTRUCTIONS: + case ANASTASIS_CHALLENGE_ANSWER_STATUS_AUTH_TIMEOUT: break; } TALER_TESTING_interpreter_next (cs->is); @@ -382,6 +315,115 @@ challenge_answer_run (void *cls, } +static void +challenge_start_cb (void *af_cls, + const struct ANASTASIS_ChallengeStartResponse *csr) +{ + struct ChallengeState *cs = af_cls; + + cs->c = NULL; + if (csr->cs != cs->expected_scs) + { + GNUNET_break (0); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Expected status %u, got %u\n", + cs->expected_scs, + csr->cs); + TALER_TESTING_interpreter_fail (cs->is); + return; + } + switch (csr->cs) + { + case ANASTASIS_CHALLENGE_START_STATUS_FILENAME_PROVIDED: + { + FILE *file; + char code[22]; + + file = fopen (csr->details.tan_filename, + "r"); + if (NULL == file) + { + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, + "open", + csr->details.tan_filename); + TALER_TESTING_interpreter_fail (cs->is); + return; + } + if (0 == fscanf (file, + "%21s", + code)) + { + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, + "fscanf", + csr->details.tan_filename); + GNUNET_break (0 == fclose (file)); + TALER_TESTING_interpreter_fail (cs->is); + return; + } + GNUNET_break (0 == fclose (file)); + cs->code = GNUNET_strdup (code); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Read code `%s'\n", + code); + } + break; + case ANASTASIS_CHALLENGE_START_STATUS_TAN_SENT_HINT_PROVIDED: + GNUNET_break (0); /* FIXME: not implemented */ + break; + case ANASTASIS_CHALLENGE_START_STATUS_BANK_TRANSFER_REQUIRED: + GNUNET_break (0); /* FIXME: not implemented */ + break; + case ANASTASIS_CHALLENGE_START_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_START_STATUS_TRUTH_UNKNOWN: + break; + case ANASTASIS_CHALLENGE_START_STATUS_SERVER_FAILURE: + GNUNET_break (0); + TALER_TESTING_interpreter_fail (cs->is); + return; + } + TALER_TESTING_interpreter_next (cs->is); +} + + /** * Run a "recover secret" CMD. * @@ -446,9 +488,7 @@ challenge_start_run (void *cls, if (GNUNET_OK != ANASTASIS_challenge_start ((struct ANASTASIS_Challenge *) *c, ps, - GNUNET_TIME_UNIT_ZERO, - NULL, - &challenge_answer_cb, + &challenge_start_cb, cs)) { GNUNET_break (0); @@ -527,12 +567,12 @@ ANASTASIS_TESTING_cmd_challenge_start ( const char *payment_ref, const char *challenge_ref, unsigned int challenge_index, - enum ANASTASIS_ChallengeStatus expected_cs) + enum ANASTASIS_ChallengeStartStatus expected_cs) { struct ChallengeState *cs; cs = GNUNET_new (struct ChallengeState); - cs->expected_cs = expected_cs; + cs->expected_scs = expected_cs; cs->challenge_ref = challenge_ref; cs->payment_ref = payment_ref; cs->challenge_index = challenge_index; @@ -558,12 +598,12 @@ ANASTASIS_TESTING_cmd_challenge_answer ( unsigned int challenge_index, const char *answer, unsigned int mode, - enum ANASTASIS_ChallengeStatus expected_cs) + enum ANASTASIS_ChallengeAnswerStatus expected_cs) { struct ChallengeState *cs; cs = GNUNET_new (struct ChallengeState); - cs->expected_cs = expected_cs; + cs->expected_acs = expected_cs; cs->challenge_ref = challenge_ref; cs->payment_ref = payment_ref; cs->answer = answer; -- cgit v1.2.3