/*
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)
{
TALER_TESTING_unexpected_status (ksls->is,
tcd->http_status,
ksls->expected_http_status);
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_TAN_ALREADY_SENT:
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 (
TALER_TESTING_interpreter_get_context (is),
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 (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_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 */