anastasis

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

testing_cmd_secret_share.c (10595B)


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