anastasis

Credential backup and recovery protocol and service
Log | Files | Refs | Submodules | README | LICENSE

testing_cmd_secret_share.c (10699B)


      1 /*
      2   This file is part of Anastasis
      3   Copyright (C) 2020 Anastasis SARL
      4 
      5   Anastasis is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU 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 testing/testing_cmd_secret_share.c
     18  * @brief command to execute the anastasis secret share service
     19  * @author Christian Grothoff
     20  * @author Dennis Neufeld
     21  * @author Dominik Meister
     22  */
     23 
     24 #include "platform.h"
     25 struct SecretShareState;
     26 #define ANASTASIS_SHARE_RESULT_CLOSURE struct SecretShareState
     27 #include "anastasis_testing_lib.h"
     28 #include <taler/taler_util.h>
     29 #include <taler/taler_testing_lib.h>
     30 #include <taler/taler_merchant_service.h>
     31 
     32 
     33 /**
     34  * State for a "secret share" CMD.
     35  */
     36 struct SecretShareState
     37 {
     38   /**
     39    * Claim token we got back, if any. Otherwise all zeros.
     40    */
     41   struct TALER_ClaimTokenP token;
     42 
     43   /**
     44    * The interpreter state.
     45    */
     46   struct TALER_TESTING_Interpreter *is;
     47 
     48   /**
     49    * Label of this command.
     50    */
     51   const char *label;
     52 
     53   /**
     54    * References to commands of previous policy creations.
     55    */
     56   const char **cmd_label_array;
     57 
     58   /**
     59    * Data to derive user identifier from.
     60    */
     61   json_t *id_data;
     62 
     63   /**
     64    * The core secret to backup/recover.
     65    */
     66   const void *core_secret;
     67 
     68   /**
     69    * URL of the anastasis backend.
     70    */
     71   const char *anastasis_url;
     72 
     73   /**
     74    * URL of a /config command for the @e anastasis_url.
     75    */
     76   const char *config_ref;
     77 
     78   /**
     79    * The /truth GET operation handle.
     80    */
     81   struct ANASTASIS_SecretShare *sso;
     82 
     83   /**
     84    * Reference to previous secret share command we expect to lookup.
     85    */
     86   const char *prev_secret_share;
     87 
     88   /**
     89    * closure for the payment callback
     90    */
     91   void *spc_cls;
     92 
     93   /**
     94    * closure for the result callback
     95    */
     96   void *src_cls;
     97 
     98   /**
     99    * Payment order ID we got back, if any. Otherwise NULL.
    100    */
    101   char *payment_order_id;
    102 
    103   /**
    104    * Size of core_secret.
    105    */
    106   size_t core_secret_size;
    107 
    108   /**
    109    * Length of array of command labels (cmd_label_array).
    110    */
    111   unsigned int cmd_label_array_length;
    112 
    113   /**
    114    * Expected status code.
    115    */
    116   enum ANASTASIS_ShareStatus want_status;
    117 
    118   /**
    119    * Options for how we are supposed to do the upload.
    120    */
    121   enum ANASTASIS_TESTING_SecretShareOption ssopt;
    122 };
    123 
    124 
    125 /**
    126  * Function called with the results of a #ANASTASIS_secret_share().
    127  *
    128  * @param sss closure
    129  * @param sr result from the operation
    130  */
    131 static void
    132 secret_share_result_cb (struct SecretShareState *sss,
    133                         const struct ANASTASIS_ShareResult *sr)
    134 {
    135   sss->sso = NULL;
    136   if (sr->ss != sss->want_status)
    137   {
    138     TALER_TESTING_interpreter_fail (sss->is);
    139     return;
    140   }
    141   switch (sr->ss)
    142   {
    143   case ANASTASIS_SHARE_STATUS_SUCCESS:
    144     break;
    145   case ANASTASIS_SHARE_STATUS_PAYMENT_REQUIRED:
    146     {
    147       struct TALER_MERCHANT_PayUriData pd;
    148 
    149       GNUNET_assert (0 < sr->details.payment_required.payment_requests_length);
    150       if (GNUNET_OK !=
    151           TALER_MERCHANT_parse_pay_uri (
    152             sr->details.payment_required.payment_requests[0].payment_request_url
    153             ,
    154             &pd))
    155       {
    156         GNUNET_break (0);
    157         TALER_TESTING_interpreter_fail (sss->is);
    158         return;
    159       }
    160       sss->payment_order_id = GNUNET_strdup (pd.order_id);
    161       TALER_MERCHANT_parse_pay_uri_free (&pd);
    162       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    163                   "Order ID from Anastasis service is `%s'\n",
    164                   sss->payment_order_id);
    165     }
    166     break;
    167   case ANASTASIS_SHARE_STATUS_PROVIDER_FAILED:
    168     break;
    169   }
    170   TALER_TESTING_interpreter_next (sss->is);
    171 }
    172 
    173 
    174 /**
    175  * Run a "secret share" CMD.
    176  *
    177  * @param cls closure.
    178  * @param cmd command currently being run.
    179  * @param is interpreter state.
    180  */
    181 static void
    182 secret_share_run (void *cls,
    183                   const struct TALER_TESTING_Command *cmd,
    184                   struct TALER_TESTING_Interpreter *is)
    185 {
    186   struct SecretShareState *sss = cls;
    187   const struct ANASTASIS_Policy *policies[sss->cmd_label_array_length];
    188   struct ANASTASIS_ProviderDetails pds;
    189 
    190   GNUNET_assert (sss->cmd_label_array_length > 0);
    191   GNUNET_assert (NULL != sss->cmd_label_array);
    192   sss->is = is;
    193   if (NULL != sss->cmd_label_array)
    194   {
    195     for (unsigned int i = 0; i < sss->cmd_label_array_length; i++)
    196     {
    197       const struct TALER_TESTING_Command *ref;
    198       const struct ANASTASIS_Policy **policy;
    199 
    200       ref = TALER_TESTING_interpreter_lookup_command (is,
    201                                                       sss->cmd_label_array[i]);
    202       if (NULL == ref)
    203       {
    204         GNUNET_break (0);
    205         TALER_TESTING_interpreter_fail (sss->is);
    206         return;
    207       }
    208       if (GNUNET_OK !=
    209           ANASTASIS_TESTING_get_trait_policy (ref,
    210                                               &policy))
    211       {
    212         GNUNET_break (0);
    213         TALER_TESTING_interpreter_fail (sss->is);
    214         return;
    215       }
    216       GNUNET_assert (NULL != *policy);
    217       policies[i] = *policy;
    218     }
    219   }
    220 
    221   if (NULL != sss->prev_secret_share)
    222   {
    223     const struct TALER_TESTING_Command *ref;
    224     const char *order_id;
    225 
    226     ref = TALER_TESTING_interpreter_lookup_command (is,
    227                                                     sss->prev_secret_share);
    228     if (NULL == ref)
    229     {
    230       GNUNET_break (0);
    231       TALER_TESTING_interpreter_fail (sss->is);
    232       return;
    233     }
    234     if (GNUNET_OK !=
    235         TALER_TESTING_get_trait_order_id (ref,
    236                                           &order_id))
    237     {
    238       GNUNET_break (0);
    239       TALER_TESTING_interpreter_fail (sss->is);
    240       return;
    241     }
    242     sss->payment_order_id = GNUNET_strdup (order_id);
    243     if (NULL == sss->payment_order_id)
    244     {
    245       GNUNET_break (0);
    246       TALER_TESTING_interpreter_fail (sss->is);
    247       return;
    248     }
    249   }
    250 
    251   memset (&pds,
    252           0,
    253           sizeof (pds));
    254   if (NULL != sss->payment_order_id)
    255   {
    256     if (GNUNET_OK !=
    257         GNUNET_STRINGS_string_to_data (
    258           sss->payment_order_id,
    259           strlen (sss->payment_order_id),
    260           &pds.payment_secret,
    261           sizeof (struct ANASTASIS_PaymentSecretP)))
    262     {
    263       GNUNET_break (0);
    264       TALER_TESTING_interpreter_fail (sss->is);
    265       GNUNET_free (sss->payment_order_id);
    266       return;
    267     }
    268     GNUNET_free (sss->payment_order_id);
    269   }
    270   pds.provider_url = sss->anastasis_url;
    271   {
    272     const struct TALER_TESTING_Command *ref;
    273     const struct ANASTASIS_CRYPTO_ProviderSaltP *provider_salt;
    274 
    275     ref = TALER_TESTING_interpreter_lookup_command (is,
    276                                                     sss->config_ref);
    277     if (NULL == ref)
    278     {
    279       GNUNET_break (0);
    280       TALER_TESTING_interpreter_fail (sss->is);
    281       return;
    282     }
    283     if (GNUNET_OK !=
    284         ANASTASIS_TESTING_get_trait_provider_salt (ref,
    285                                                    &provider_salt))
    286     {
    287       GNUNET_break (0);
    288       TALER_TESTING_interpreter_fail (sss->is);
    289       return;
    290     }
    291     pds.provider_salt = *provider_salt;
    292   }
    293 
    294   sss->sso = ANASTASIS_secret_share (
    295     TALER_TESTING_interpreter_get_context (is),
    296     sss->id_data,
    297     &pds,
    298     1,
    299     policies,
    300     sss->cmd_label_array_length,
    301     false,
    302     GNUNET_TIME_UNIT_ZERO,
    303     &secret_share_result_cb,
    304     sss,
    305     "test-case",
    306     sss->core_secret,
    307     sss->core_secret_size);
    308   if (NULL == sss->sso)
    309   {
    310     GNUNET_break (0);
    311     TALER_TESTING_interpreter_fail (sss->is);
    312     return;
    313   }
    314 }
    315 
    316 
    317 /**
    318  * Free the state of a "secret share" CMD, and possibly
    319  * cancel it if it did not complete.
    320  *
    321  * @param cls closure.
    322  * @param cmd command being freed.
    323  */
    324 static void
    325 secret_share_cleanup (void *cls,
    326                       const struct TALER_TESTING_Command *cmd)
    327 {
    328   struct SecretShareState *sss = cls;
    329 
    330   if (NULL != sss->cmd_label_array)
    331   {
    332     GNUNET_free (sss->cmd_label_array);
    333   }
    334   if (NULL != sss->sso)
    335   {
    336     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    337                 "Command '%s' did not complete\n",
    338                 cmd->label);
    339     ANASTASIS_secret_share_cancel (sss->sso);
    340     sss->sso = NULL;
    341   }
    342   json_decref (sss->id_data);
    343   GNUNET_free (sss);
    344 }
    345 
    346 
    347 /**
    348  * Offer internal data to other commands.
    349  *
    350  * @param cls closure
    351  * @param[out] ret result (could be anything)
    352  * @param trait name of the trait
    353  * @param index index number of the object to extract.
    354  * @return #GNUNET_OK on success
    355  */
    356 static int
    357 secret_share_traits (void *cls,
    358                      const void **ret,
    359                      const char *trait,
    360                      unsigned int index)
    361 {
    362   struct SecretShareState *sss = cls;
    363   struct TALER_TESTING_Trait traits[] = {
    364     TALER_TESTING_make_trait_claim_token (&sss->token),
    365     ANASTASIS_TESTING_make_trait_core_secret (sss->core_secret),
    366     TALER_TESTING_make_trait_order_id (sss->payment_order_id),
    367     TALER_TESTING_trait_end ()
    368   };
    369 
    370   return TALER_TESTING_get_trait (traits,
    371                                   ret,
    372                                   trait,
    373                                   index);
    374 }
    375 
    376 
    377 struct TALER_TESTING_Command
    378 ANASTASIS_TESTING_cmd_secret_share (
    379   const char *label,
    380   const char *anastasis_url,
    381   const char *config_ref,
    382   const char *prev_secret_share,
    383   const json_t *id_data,
    384   const void *core_secret,
    385   size_t core_secret_size,
    386   enum ANASTASIS_ShareStatus want_status,
    387   enum ANASTASIS_TESTING_SecretShareOption sso,
    388   ...)
    389 {
    390   struct SecretShareState *sss;
    391 
    392   sss = GNUNET_new (struct SecretShareState);
    393   sss->want_status = want_status;
    394   sss->ssopt = sso;
    395   sss->anastasis_url = anastasis_url;
    396   sss->config_ref = config_ref;
    397   sss->label = label;
    398   sss->id_data = json_incref ((json_t *) id_data);
    399   sss->core_secret = core_secret;
    400   sss->core_secret_size = core_secret_size;
    401   sss->prev_secret_share = prev_secret_share;
    402 
    403   {
    404     const char *policy_create_cmd;
    405     va_list ap;
    406 
    407     va_start (ap,
    408               sso);
    409     while (NULL != (policy_create_cmd = va_arg (ap, const char *)))
    410     {
    411       GNUNET_array_append (sss->cmd_label_array,
    412                            sss->cmd_label_array_length,
    413                            policy_create_cmd);
    414     }
    415     va_end (ap);
    416   }
    417   {
    418     struct TALER_TESTING_Command cmd = {
    419       .cls = sss,
    420       .label = label,
    421       .run = &secret_share_run,
    422       .cleanup = &secret_share_cleanup,
    423       .traits = &secret_share_traits
    424     };
    425 
    426     return cmd;
    427   }
    428 }
    429 
    430 
    431 /* end of testing_cmd_secret_share.c */