exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

testing_api_cmd_revoke_sign_key.c (11253B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2014-2023 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify
      6   it under the terms of the GNU General Public License as
      7   published by the Free Software Foundation; either version 3, or
      8   (at your option) any later version.
      9 
     10   TALER is distributed in the hope that it will be useful, but
     11   WITHOUT ANY WARRANTY; without even the implied warranty of
     12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13   GNU General Public License for more details.
     14 
     15   You should have received a copy of the GNU General Public
     16   License along with TALER; see the file COPYING.  If not, see
     17   <http://www.gnu.org/licenses/>
     18 */
     19 /**
     20  * @file testing/testing_api_cmd_revoke_sign_key.c
     21  * @brief Implement the revoke test command.
     22  * @author Christian Grothoff
     23  */
     24 #include "taler/taler_json_lib.h"
     25 #include <gnunet/gnunet_curl_lib.h>
     26 struct RevokeState;
     27 #define TALER_EXCHANGE_POST_MANAGEMENT_SIGNKEYS_REVOKE_RESULT_CLOSURE \
     28         struct RevokeState
     29 #include "taler/exchange/post-management-signkeys-EXCHANGE_PUB-revoke.h"
     30 #include "taler/taler_testing_lib.h"
     31 
     32 
     33 /**
     34  * State for a "revoke" CMD.
     35  */
     36 struct RevokeState
     37 {
     38   /**
     39    * Expected HTTP status code.
     40    */
     41   unsigned int expected_response_code;
     42 
     43   /**
     44    * Command that offers a signination to revoke.
     45    */
     46   const char *coin_reference;
     47 
     48   /**
     49    * The interpreter state.
     50    */
     51   struct TALER_TESTING_Interpreter *is;
     52 
     53   /**
     54    * Handle for the operation.
     55    */
     56   struct TALER_EXCHANGE_PostManagementSignkeysRevokeHandle *kh;
     57 
     58   /**
     59    * Should we use a bogus signature?
     60    */
     61   bool bad_sig;
     62 
     63 };
     64 
     65 
     66 /**
     67  * Function called with information about the post revocation operation result.
     68  *
     69  * @param rs closure with a `struct RevokeState *`
     70  * @param rsr response data
     71  */
     72 static void
     73 success_cb (
     74   struct RevokeState *rs,
     75   const struct TALER_EXCHANGE_PostManagementSignkeysRevokeResponse *rsr)
     76 {
     77   const struct TALER_EXCHANGE_HttpResponse *hr = &rsr->hr;
     78 
     79   rs->kh = NULL;
     80   if (rs->expected_response_code != hr->http_status)
     81   {
     82     TALER_TESTING_unexpected_status (rs->is,
     83                                      hr->http_status,
     84                                      rs->expected_response_code);
     85     return;
     86   }
     87   TALER_TESTING_interpreter_next (rs->is);
     88 }
     89 
     90 
     91 /**
     92  * Cleanup the state.
     93  *
     94  * @param cls closure, must be a `struct RevokeState`.
     95  * @param cmd the command which is being cleaned up.
     96  */
     97 static void
     98 revoke_cleanup (void *cls,
     99                 const struct TALER_TESTING_Command *cmd)
    100 {
    101   struct RevokeState *rs = cls;
    102 
    103   if (NULL != rs->kh)
    104   {
    105     TALER_EXCHANGE_post_management_signkeys_revoke_cancel (rs->kh);
    106     rs->kh = NULL;
    107   }
    108   GNUNET_free (rs);
    109 }
    110 
    111 
    112 /**
    113  * Offer internal data from a "revoke" CMD to other CMDs.
    114  *
    115  * @param cls closure
    116  * @param[out] ret result (could be anything)
    117  * @param trait name of the trait
    118  * @param index index number of the object to offer.
    119  * @return #GNUNET_OK on success
    120  */
    121 static int
    122 revoke_traits (void *cls,
    123                const void **ret,
    124                const char *trait,
    125                unsigned int index)
    126 {
    127   struct RevokeState *rs = cls;
    128   struct TALER_TESTING_Trait traits[] = {
    129     TALER_TESTING_trait_end ()
    130   };
    131 
    132   (void) rs;
    133   return TALER_TESTING_get_trait (traits,
    134                                   ret,
    135                                   trait,
    136                                   index);
    137 }
    138 
    139 
    140 /**
    141  * Run the "revoke" command for a signing key.
    142  *
    143  * @param cls closure.
    144  * @param cmd the command to execute.
    145  * @param is the interpreter state.
    146  */
    147 static void
    148 revoke_run (void *cls,
    149             const struct TALER_TESTING_Command *cmd,
    150             struct TALER_TESTING_Interpreter *is)
    151 {
    152   struct RevokeState *rs = cls;
    153   const struct TALER_TESTING_Command *coin_cmd;
    154   const struct TALER_ExchangePublicKeyP *exchange_pub;
    155   struct TALER_MasterSignatureP master_sig;
    156   const char *exchange_url;
    157 
    158   {
    159     const struct TALER_TESTING_Command *exchange_cmd;
    160 
    161     exchange_cmd = TALER_TESTING_interpreter_get_command (is,
    162                                                           "exchange");
    163     if (NULL == exchange_cmd)
    164     {
    165       GNUNET_break (0);
    166       TALER_TESTING_interpreter_fail (is);
    167       return;
    168     }
    169     GNUNET_assert (GNUNET_OK ==
    170                    TALER_TESTING_get_trait_exchange_url (exchange_cmd,
    171                                                          &exchange_url));
    172   }
    173   rs->is = is;
    174   /* Get sign pub from trait */
    175   coin_cmd = TALER_TESTING_interpreter_lookup_command (is,
    176                                                        rs->coin_reference);
    177 
    178   if (NULL == coin_cmd)
    179   {
    180     GNUNET_break (0);
    181     TALER_TESTING_interpreter_fail (is);
    182     return;
    183   }
    184   GNUNET_assert (GNUNET_OK ==
    185                  TALER_TESTING_get_trait_exchange_pub (coin_cmd,
    186                                                        0,
    187                                                        &exchange_pub));
    188   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    189               "Trying to revoke sign '%s..'\n",
    190               TALER_B2S (exchange_pub));
    191   if (rs->bad_sig)
    192   {
    193     memset (&master_sig,
    194             42,
    195             sizeof (master_sig));
    196   }
    197   else
    198   {
    199     const struct TALER_TESTING_Command *exchange_cmd;
    200     const struct TALER_MasterPrivateKeyP *master_priv;
    201 
    202     exchange_cmd = TALER_TESTING_interpreter_get_command (is,
    203                                                           "exchange");
    204     if (NULL == exchange_cmd)
    205     {
    206       GNUNET_break (0);
    207       TALER_TESTING_interpreter_fail (is);
    208       return;
    209     }
    210     GNUNET_assert (GNUNET_OK ==
    211                    TALER_TESTING_get_trait_master_priv (exchange_cmd,
    212                                                         &master_priv));
    213     TALER_exchange_offline_signkey_revoke_sign (exchange_pub,
    214                                                 master_priv,
    215                                                 &master_sig);
    216   }
    217   rs->kh = TALER_EXCHANGE_post_management_signkeys_revoke_create (
    218     TALER_TESTING_interpreter_get_context (is),
    219     exchange_url,
    220     exchange_pub,
    221     &master_sig);
    222   if (NULL == rs->kh)
    223   {
    224     GNUNET_break (0);
    225     TALER_TESTING_interpreter_fail (is);
    226     return;
    227   }
    228   TALER_EXCHANGE_post_management_signkeys_revoke_start (rs->kh, &success_cb, rs)
    229   ;
    230 }
    231 
    232 
    233 struct TALER_TESTING_Command
    234 TALER_TESTING_cmd_revoke_sign_key (
    235   const char *label,
    236   unsigned int expected_response_code,
    237   bool bad_sig,
    238   const char *sign_ref)
    239 {
    240   struct RevokeState *rs;
    241 
    242   rs = GNUNET_new (struct RevokeState);
    243   rs->expected_response_code = expected_response_code;
    244   rs->coin_reference = sign_ref;
    245   rs->bad_sig = bad_sig;
    246   {
    247     struct TALER_TESTING_Command cmd = {
    248       .cls = rs,
    249       .label = label,
    250       .run = &revoke_run,
    251       .cleanup = &revoke_cleanup,
    252       .traits = &revoke_traits
    253     };
    254 
    255     return cmd;
    256   }
    257 }
    258 
    259 
    260 /**
    261  * State for a "check signkey revoked" CMD.
    262  */
    263 struct CheckRevokedState
    264 {
    265   /**
    266    * Command that offers the revoked signing key.
    267    */
    268   const char *signkey_ref;
    269 
    270   /**
    271    * "get exchange" command that downloaded /keys before the revocation.
    272    */
    273   const char *keys_before_ref;
    274 
    275   /**
    276    * "get exchange" command that downloaded /keys after the revocation.
    277    */
    278   const char *keys_after_ref;
    279 };
    280 
    281 
    282 /**
    283  * Obtain the /keys of the "get exchange" command @a label.
    284  *
    285  * @param is interpreter state
    286  * @param label label of the command
    287  * @return NULL on error
    288  */
    289 static const struct TALER_EXCHANGE_Keys *
    290 get_keys_of (struct TALER_TESTING_Interpreter *is,
    291              const char *label)
    292 {
    293   const struct TALER_TESTING_Command *cmd;
    294   struct TALER_EXCHANGE_Keys *keys;
    295 
    296   cmd = TALER_TESTING_interpreter_lookup_command (is,
    297                                                   label);
    298   if ( (NULL == cmd) ||
    299        (GNUNET_OK !=
    300         TALER_TESTING_get_trait_keys (cmd,
    301                                       &keys)) )
    302     return NULL;
    303   return keys;
    304 }
    305 
    306 
    307 /**
    308  * Run the "check signkey revoked" command.
    309  *
    310  * @param cls a `struct CheckRevokedState`
    311  * @param cmd the command currently being executed.
    312  * @param is the interpreter state.
    313  */
    314 static void
    315 check_revoked_run (void *cls,
    316                    const struct TALER_TESTING_Command *cmd,
    317                    struct TALER_TESTING_Interpreter *is)
    318 {
    319   struct CheckRevokedState *crs = cls;
    320   const struct TALER_TESTING_Command *sk_cmd;
    321   const struct TALER_ExchangePublicKeyP *exchange_pub;
    322   const struct TALER_EXCHANGE_Keys *before;
    323   const struct TALER_EXCHANGE_Keys *after;
    324 
    325   (void) cmd;
    326   sk_cmd = TALER_TESTING_interpreter_lookup_command (is,
    327                                                      crs->signkey_ref);
    328   before = get_keys_of (is,
    329                         crs->keys_before_ref);
    330   after = get_keys_of (is,
    331                        crs->keys_after_ref);
    332   if ( (NULL == sk_cmd) ||
    333        (GNUNET_OK !=
    334         TALER_TESTING_get_trait_exchange_pub (sk_cmd,
    335                                               0,
    336                                               &exchange_pub)) ||
    337        (NULL == before) ||
    338        (NULL == after) )
    339   {
    340     GNUNET_break (0);
    341     TALER_TESTING_interpreter_fail (is);
    342     return;
    343   }
    344   /* The key was valid before the revocation ... */
    345   if (GNUNET_OK !=
    346       TALER_EXCHANGE_test_signing_key (before,
    347                                        exchange_pub))
    348   {
    349     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    350                 "Signing key %s was not valid before its revocation\n",
    351                 TALER_B2S (exchange_pub));
    352     TALER_TESTING_interpreter_fail (is);
    353     return;
    354   }
    355   /* ... /keys no longer lists it after the revocation ... */
    356   for (unsigned int i = 0; i<after->num_sign_keys; i++)
    357   {
    358     if (0 ==
    359         GNUNET_memcmp (exchange_pub,
    360                        &after->sign_keys[i].key))
    361     {
    362       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    363                   "/keys still lists revoked signing key %s\n",
    364                   TALER_B2S (exchange_pub));
    365       TALER_TESTING_interpreter_fail (is);
    366       return;
    367     }
    368   }
    369   /* ... so the client rejects replies signed with it. */
    370   if (GNUNET_SYSERR !=
    371       TALER_EXCHANGE_test_signing_key (after,
    372                                        exchange_pub))
    373   {
    374     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    375                 "Client still accepts revoked signing key %s\n",
    376                 TALER_B2S (exchange_pub));
    377     TALER_TESTING_interpreter_fail (is);
    378     return;
    379   }
    380   TALER_TESTING_interpreter_next (is);
    381 }
    382 
    383 
    384 /**
    385  * Free the state of a "check signkey revoked" CMD.
    386  *
    387  * @param cls a `struct CheckRevokedState`
    388  * @param cmd the command which is being cleaned up.
    389  */
    390 static void
    391 check_revoked_cleanup (void *cls,
    392                        const struct TALER_TESTING_Command *cmd)
    393 {
    394   struct CheckRevokedState *crs = cls;
    395 
    396   (void) cmd;
    397   GNUNET_free (crs);
    398 }
    399 
    400 
    401 struct TALER_TESTING_Command
    402 TALER_TESTING_cmd_check_signkey_revoked (
    403   const char *label,
    404   const char *signkey_ref,
    405   const char *keys_before_ref,
    406   const char *keys_after_ref)
    407 {
    408   struct CheckRevokedState *crs;
    409 
    410   crs = GNUNET_new (struct CheckRevokedState);
    411   crs->signkey_ref = signkey_ref;
    412   crs->keys_before_ref = keys_before_ref;
    413   crs->keys_after_ref = keys_after_ref;
    414   {
    415     struct TALER_TESTING_Command cmd = {
    416       .cls = crs,
    417       .label = label,
    418       .run = &check_revoked_run,
    419       .cleanup = &check_revoked_cleanup
    420     };
    421 
    422     return cmd;
    423   }
    424 }