/* 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) { TALER_TESTING_unexpected_status (ksls->is, tsr->http_status, ksls->expected_http_status); 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 *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 != 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, &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 == answer) { 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 (answer, strlen (answer), &h_answer); ksls->tso = ANASTASIS_truth_solve ( TALER_TESTING_interpreter_get_context (is), 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 (ksls->pay_uri), TALER_TESTING_make_trait_order_id (ksls->order_id), ANASTASIS_TESTING_make_trait_code (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 */