LCOV - code coverage report
Current view: top level - testing - testing_api_cmd_truth_store.c (source / functions) Hit Total Coverage
Test: GNU Taler anastasis coverage report Lines: 75 129 58.1 %
Date: 2021-06-16 06:33:01 Functions: 6 6 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   This file is part of Anastasis
       3             :   Copyright (C) 2020 Taler Systems SA
       4             : 
       5             :   Anastasis is free software; you can redistribute it and/or modify it under the
       6             :   terms of the GNU Lesser General Public License as published by the Free Software
       7             :   Foundation; either version 3, or (at your option) any later version.
       8             : 
       9             :   Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
      10             :   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
      11             :   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
      12             : 
      13             :   You should have received a copy of the GNU General Public License along with
      14             :   Anastasis; see the file COPYING.GPL.  If not, see <http://www.gnu.org/licenses/>
      15             : */
      16             : /**
      17             :  * @file lib/testing_api_cmd_truth_store.c
      18             :  * @brief command to execute the anastasis backend service.
      19             :  * @author Dennis Neufeld
      20             :  */
      21             : #include "platform.h"
      22             : #include "anastasis_testing_lib.h"
      23             : #include <taler/taler_util.h>
      24             : #include <taler/taler_testing_lib.h>
      25             : #include <taler/taler_merchant_service.h>
      26             : 
      27             : /**
      28             :  * State for a "truth store" CMD.
      29             :  */
      30             : struct TruthStoreState
      31             : {
      32             :   /**
      33             :    * UUID of the uploaded truth
      34             :    */
      35             :   struct ANASTASIS_CRYPTO_TruthUUIDP uuid;
      36             : 
      37             :   /**
      38             :    * Key used to encrypt the @e truth_data on the server.
      39             :    */
      40             :   struct ANASTASIS_CRYPTO_TruthKeyP key;
      41             : 
      42             :   /**
      43             :    * "Encrypted" key share data we store at the server.
      44             :    */
      45             :   struct ANASTASIS_CRYPTO_EncryptedKeyShareP encrypted_keyshare;
      46             : 
      47             :   /**
      48             :    * The /truth POST operation handle.
      49             :    */
      50             :   struct ANASTASIS_TruthStoreOperation *tso;
      51             : 
      52             :   /**
      53             :    * URL of the anastasis backend.
      54             :    */
      55             :   const char *anastasis_url;
      56             : 
      57             :   /**
      58             :    * The interpreter state.
      59             :    */
      60             :   struct TALER_TESTING_Interpreter *is;
      61             : 
      62             :   /**
      63             :    * Previous upload, or NULL for none. Used to calculate what THIS
      64             :    * upload is based on.
      65             :    */
      66             :   const char *prev_upload;
      67             : 
      68             :   /**
      69             :    * Authorization method / plugin name.
      70             :    */
      71             :   const char *method;
      72             : 
      73             :   /**
      74             :    * Mimetype of @e truth_data.
      75             :    */
      76             :   const char *mime_type;
      77             : 
      78             :   /**
      79             :    * Number of bytes in @e truth_data
      80             :    */
      81             :   size_t truth_data_size;
      82             : 
      83             :   /**
      84             :    * Data used by the authorization process.
      85             :    */
      86             :   void *truth_data;
      87             : 
      88             :   /**
      89             :    * Name of the file where the service will write the challenge, or NULL.
      90             :    */
      91             :   char *filename;
      92             : 
      93             :   /**
      94             :    * Expected status code.
      95             :    */
      96             :   unsigned int http_status;
      97             : 
      98             :   /**
      99             :    * Payment request we got back, or NULL.
     100             :    */
     101             :   char *pay_uri;
     102             : 
     103             :   /**
     104             :    * Payment order ID we got back, or all zeros.
     105             :    */
     106             :   struct ANASTASIS_PaymentSecretP payment_secret_response;
     107             : 
     108             :   /**
     109             :    * Options for how we are supposed to do the upload.
     110             :    */
     111             :   enum ANASTASIS_TESTING_TruthStoreOption tsopt;
     112             : };
     113             : 
     114             : /**
     115             :  * Function called with the results of a #truth_store().
     116             :  *
     117             :  * @param cls closure
     118             :  * @param ec ANASTASIS error code
     119             :  * @param http_status HTTP status of the request
     120             :  * @param ud details about the upload operation
     121             :  */
     122             : static void
     123           2 : truth_store_cb (void *cls,
     124             :                 const struct ANASTASIS_UploadDetails *ud)
     125             : {
     126           2 :   struct TruthStoreState *tss = cls;
     127             : 
     128           2 :   tss->tso = NULL;
     129           2 :   if ( (NULL == ud) ||
     130           2 :        (ud->http_status != tss->http_status) )
     131             :   {
     132           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     133             :                 "Unexpected response code %u to command %s in %s:%u\n",
     134             :                 (NULL != ud) ? ud->http_status : 0,
     135             :                 tss->is->commands[tss->is->ip].label,
     136             :                 __FILE__,
     137             :                 __LINE__);
     138           0 :     TALER_TESTING_interpreter_fail (tss->is);
     139           0 :     return;
     140             :   }
     141           2 :   switch (ud->us)
     142             :   {
     143           2 :   case ANASTASIS_US_SUCCESS:
     144           2 :     break;
     145           0 :   case ANASTASIS_US_PAYMENT_REQUIRED:
     146           0 :     tss->pay_uri = GNUNET_strdup (ud->details.payment.payment_request);
     147           0 :     tss->payment_secret_response = ud->details.payment.ps;
     148           0 :     break;
     149           0 :   case ANASTASIS_US_CONFLICTING_TRUTH:
     150           0 :     GNUNET_break (0);
     151           0 :     TALER_TESTING_interpreter_fail (tss->is);
     152           0 :     return;
     153           0 :   case ANASTASIS_US_HTTP_ERROR:
     154           0 :     GNUNET_break (0);
     155           0 :     TALER_TESTING_interpreter_fail (tss->is);
     156           0 :     return;
     157           0 :   case ANASTASIS_US_CLIENT_ERROR:
     158           0 :     GNUNET_break (0);
     159           0 :     TALER_TESTING_interpreter_fail (tss->is);
     160           0 :     return;
     161           0 :   case ANASTASIS_US_SERVER_ERROR:
     162           0 :     GNUNET_break (0);
     163           0 :     TALER_TESTING_interpreter_fail (tss->is);
     164           0 :     return;
     165           0 :   default:
     166           0 :     GNUNET_break (0);
     167           0 :     TALER_TESTING_interpreter_fail (tss->is);
     168           0 :     return;
     169             :   }
     170           2 :   TALER_TESTING_interpreter_next (tss->is);
     171             : }
     172             : 
     173             : 
     174             : /**
     175             :  * Run a "truth store" CMD.
     176             :  *
     177             :  * @param cls closure.
     178             :  * @param cmd command currently being run.
     179             :  * @param is interpreter state.
     180             :  */
     181             : static void
     182           2 : truth_store_run (void *cls,
     183             :                  const struct TALER_TESTING_Command *cmd,
     184             :                  struct TALER_TESTING_Interpreter *is)
     185             : {
     186           2 :   struct TruthStoreState *tss = cls;
     187             : 
     188           2 :   tss->is = is;
     189           2 :   if (NULL != tss->prev_upload)
     190             :   {
     191             :     const struct TALER_TESTING_Command *ref;
     192             : 
     193           0 :     ref = TALER_TESTING_interpreter_lookup_command (is,
     194             :                                                     tss->prev_upload);
     195           0 :     if (NULL == ref)
     196             :     {
     197           0 :       GNUNET_break (0);
     198           0 :       TALER_TESTING_interpreter_fail (tss->is);
     199           0 :       return;
     200             :     }
     201             : 
     202           0 :     if (0 != (ANASTASIS_TESTING_TSO_REFERENCE_UUID & tss->tsopt))
     203             :     {
     204             :       const struct ANASTASIS_CRYPTO_TruthUUIDP *uuid;
     205             :       const struct ANASTASIS_CRYPTO_EncryptedKeyShareP *eks;
     206             : 
     207           0 :       if (GNUNET_OK !=
     208           0 :           ANASTASIS_TESTING_get_trait_truth_uuid (ref,
     209             :                                                   0,
     210             :                                                   &uuid))
     211             :       {
     212           0 :         GNUNET_break (0);
     213           0 :         TALER_TESTING_interpreter_fail (tss->is);
     214           0 :         return;
     215             :       }
     216           0 :       tss->uuid = *uuid;
     217           0 :       if (GNUNET_OK !=
     218           0 :           ANASTASIS_TESTING_get_trait_eks (ref,
     219             :                                            0,
     220             :                                            &eks))
     221             :       {
     222           0 :         GNUNET_break (0);
     223           0 :         TALER_TESTING_interpreter_fail (tss->is);
     224           0 :         return;
     225             :       }
     226           0 :       tss->encrypted_keyshare = *eks;
     227             :     }
     228             :   }
     229             :   else
     230             :   {
     231           2 :     GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
     232           2 :                                 &tss->uuid,
     233             :                                 sizeof (struct ANASTASIS_CRYPTO_TruthUUIDP));
     234           2 :     GNUNET_CRYPTO_random_block (
     235             :       GNUNET_CRYPTO_QUALITY_WEAK,
     236           2 :       &tss->encrypted_keyshare,
     237             :       sizeof (struct ANASTASIS_CRYPTO_EncryptedKeyShareP));
     238             :   }
     239           2 :   GNUNET_CRYPTO_random_block (
     240             :     GNUNET_CRYPTO_QUALITY_WEAK,
     241           2 :     &tss->key,
     242             :     sizeof (struct ANASTASIS_CRYPTO_TruthKeyP));
     243             : 
     244             :   {
     245             :     void *encrypted_truth;
     246             :     size_t size_encrypted_truth;
     247             :     struct ANASTASIS_CRYPTO_NonceP nonce;
     248             : 
     249           2 :     GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
     250             :                                 &nonce,
     251             :                                 sizeof (nonce));
     252           2 :     ANASTASIS_CRYPTO_truth_encrypt (&nonce,
     253           2 :                                     &tss->key,
     254           2 :                                     tss->truth_data,
     255             :                                     tss->truth_data_size,
     256             :                                     &encrypted_truth,
     257             :                                     &size_encrypted_truth);
     258             :     {
     259             :       void *t;
     260             :       size_t t_size;
     261             : 
     262           2 :       ANASTASIS_CRYPTO_truth_decrypt (&tss->key,
     263             :                                       encrypted_truth,
     264             :                                       size_encrypted_truth,
     265             :                                       &t,
     266             :                                       &t_size);
     267           2 :       if ( (t_size != tss->truth_data_size) ||
     268           2 :            (0 != memcmp (tss->truth_data,
     269             :                          t,
     270             :                          t_size)) )
     271             :       {
     272           0 :         GNUNET_break (0);
     273           0 :         TALER_TESTING_interpreter_fail (tss->is);
     274           0 :         return;
     275             :       }
     276           2 :       GNUNET_free (t);
     277             :     }
     278           2 :     tss->tso = ANASTASIS_truth_store (
     279             :       is->ctx,
     280             :       tss->anastasis_url,
     281           2 :       &tss->uuid,
     282             :       tss->method,
     283           2 :       &tss->encrypted_keyshare,
     284             :       tss->mime_type,
     285             :       size_encrypted_truth,
     286             :       encrypted_truth,
     287           2 :       (0 != (ANASTASIS_TESTING_TSO_REQUEST_PAYMENT & tss->tsopt)),
     288             :       GNUNET_TIME_UNIT_ZERO,
     289             :       &truth_store_cb,
     290             :       tss);
     291           2 :     GNUNET_free (encrypted_truth);
     292             :   }
     293           2 :   if (NULL == tss->tso)
     294             :   {
     295           0 :     GNUNET_break (0);
     296           0 :     TALER_TESTING_interpreter_fail (tss->is);
     297           0 :     return;
     298             :   }
     299             : }
     300             : 
     301             : 
     302             : /**
     303             :  * Free the state of a "truth store" CMD, and possibly
     304             :  * cancel it if it did not complete.
     305             :  *
     306             :  * @param cls closure.
     307             :  * @param cmd command being freed.
     308             :  */
     309             : static void
     310           2 : truth_store_cleanup (void *cls,
     311             :                      const struct TALER_TESTING_Command *cmd)
     312             : {
     313           2 :   struct TruthStoreState *tss = cls;
     314             : 
     315           2 :   if (NULL != tss->tso)
     316             :   {
     317           0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     318             :                 "Command '%s' did not complete (truth post)\n",
     319             :                 cmd->label);
     320           0 :     ANASTASIS_truth_store_cancel (tss->tso);
     321           0 :     tss->tso = NULL;
     322             :   }
     323           2 :   GNUNET_free (tss->truth_data);
     324           2 :   GNUNET_free (tss->pay_uri);
     325           2 :   GNUNET_free (tss->filename);
     326           2 :   GNUNET_free (tss);
     327           2 : }
     328             : 
     329             : 
     330             : /**
     331             :  * Offer internal data to other commands.
     332             :  *
     333             :  * @param cls closure
     334             :  * @param[out] ret result (could be anything)
     335             :  * @param[out] trait name of the trait
     336             :  * @param index index number of the object to extract.
     337             :  * @return #GNUNET_OK on success
     338             :  */
     339             : static int
     340          15 : truth_store_traits (void *cls,
     341             :                     const void **ret,
     342             :                     const char *trait,
     343             :                     unsigned int index)
     344             : {
     345          15 :   struct TruthStoreState *tss = cls;
     346             :   struct TALER_TESTING_Trait traits[] = {
     347          15 :     ANASTASIS_TESTING_make_trait_truth_uuid (0,
     348          15 :                                              &tss->uuid),
     349          15 :     ANASTASIS_TESTING_make_trait_truth_key (0,
     350          15 :                                             &tss->key),
     351          15 :     ANASTASIS_TESTING_make_trait_eks (0,
     352          15 :                                       &tss->encrypted_keyshare),
     353          15 :     ANASTASIS_TESTING_make_trait_payment_secret (0,
     354          15 :                                                  &tss->payment_secret_response),
     355          15 :     TALER_TESTING_make_trait_url (TALER_TESTING_UT_TALER_URL,
     356          15 :                                   tss->pay_uri),
     357          15 :     TALER_TESTING_make_trait_string (0,
     358          15 :                                      tss->filename),
     359          15 :     TALER_TESTING_trait_end ()
     360             :   };
     361             : 
     362          15 :   return TALER_TESTING_get_trait (traits,
     363             :                                   ret,
     364             :                                   trait,
     365             :                                   index);
     366             : }
     367             : 
     368             : 
     369             : struct TALER_TESTING_Command
     370           2 : ANASTASIS_TESTING_cmd_truth_store (const char *label,
     371             :                                    const char *anastasis_url,
     372             :                                    const char *prev_upload,
     373             :                                    const char *method,
     374             :                                    const char *mime_type,
     375             :                                    size_t truth_data_size,
     376             :                                    const void *truth_data,
     377             :                                    enum ANASTASIS_TESTING_TruthStoreOption tso,
     378             :                                    unsigned int http_status)
     379             : {
     380             :   struct TruthStoreState *tss;
     381             : 
     382           2 :   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     383             :               "Storing %u bytes of truth\n",
     384             :               (unsigned int) truth_data_size);
     385           2 :   tss = GNUNET_new (struct TruthStoreState);
     386           2 :   tss->http_status = http_status;
     387           2 :   tss->tsopt = tso;
     388           2 :   tss->anastasis_url = anastasis_url;
     389           2 :   tss->prev_upload = prev_upload;
     390           2 :   tss->method = method;
     391           2 :   tss->mime_type = mime_type;
     392           2 :   tss->truth_data = GNUNET_memdup (truth_data,
     393             :                                    truth_data_size);
     394           2 :   tss->truth_data_size = truth_data_size;
     395           2 :   if (0 == strcasecmp (method,
     396             :                        "file"))
     397           1 :     tss->filename = GNUNET_strndup (truth_data,
     398             :                                     truth_data_size);
     399             :   {
     400           2 :     struct TALER_TESTING_Command cmd = {
     401             :       .cls = tss,
     402             :       .label = label,
     403             :       .run = &truth_store_run,
     404             :       .cleanup = &truth_store_cleanup,
     405             :       .traits = &truth_store_traits
     406             :     };
     407             : 
     408           2 :     return cmd;
     409             :   }
     410             : }
     411             : 
     412             : 
     413             : struct TALER_TESTING_Command
     414           1 : ANASTASIS_TESTING_cmd_truth_question (
     415             :   const char *label,
     416             :   const char *anastasis_url,
     417             :   const char *prev_upload,
     418             :   const char *answer,
     419             :   enum ANASTASIS_TESTING_TruthStoreOption tso,
     420             :   unsigned int http_status)
     421             : {
     422             :   struct GNUNET_HashCode h;
     423             : 
     424           1 :   GNUNET_CRYPTO_hash (answer,
     425             :                       strlen (answer),
     426             :                       &h);
     427           1 :   return ANASTASIS_TESTING_cmd_truth_store (label,
     428             :                                             anastasis_url,
     429             :                                             prev_upload,
     430             :                                             "question",
     431             :                                             "binary/sha512",
     432             :                                             sizeof (h),
     433             :                                             &h,
     434             :                                             tso,
     435             :                                             http_status);
     436             : }

Generated by: LCOV version 1.14