/* 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 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with Anastasis; see the file COPYING.GPL. If not, see */ /** * @file testing/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 #include /** * 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[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 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) { return GNUNET_JSON_PACK ( GNUNET_JSON_pack_string ("id_data", id_data)); } 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 */