exchange

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

exchange_api_post-management-keys.c (8818B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2015-2026 Taler Systems SA
      4 
      5   TALER 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   TALER 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   TALER; see the file COPYING.  If not, see
     15   <http://www.gnu.org/licenses/>
     16 */
     17 /**
     18  * @file lib/exchange_api_post-management-keys.c
     19  * @brief functions to affirm the validity of exchange keys using the master private key
     20  * @author Christian Grothoff
     21  */
     22 #include "taler/taler_json_lib.h"
     23 #include <gnunet/gnunet_curl_lib.h>
     24 #include <microhttpd.h>
     25 #include "taler/exchange/post-management-keys.h"
     26 #include "exchange_api_curl_defaults.h"
     27 #include "taler/taler_curl_lib.h"
     28 
     29 
     30 /**
     31  * @brief Handle for a POST /management/keys request.
     32  */
     33 struct TALER_EXCHANGE_PostManagementKeysHandle
     34 {
     35 
     36   /**
     37    * The base URL for this request.
     38    */
     39   char *base_url;
     40 
     41   /**
     42    * The full URL for this request, set during _start.
     43    */
     44   char *url;
     45 
     46   /**
     47    * Minor context that holds body and headers.
     48    */
     49   struct TALER_CURL_PostContext post_ctx;
     50 
     51   /**
     52    * Handle for the request.
     53    */
     54   struct GNUNET_CURL_Job *job;
     55 
     56   /**
     57    * Function to call with the result.
     58    */
     59   TALER_EXCHANGE_PostManagementKeysCallback cb;
     60 
     61   /**
     62    * Closure for @a cb.
     63    */
     64   TALER_EXCHANGE_POST_MANAGEMENT_KEYS_RESULT_CLOSURE *cb_cls;
     65 
     66   /**
     67    * Reference to the execution context.
     68    */
     69   struct GNUNET_CURL_Context *ctx;
     70 
     71   /**
     72    * Array of master signatures for the exchange's online signing keys.
     73    */
     74   struct TALER_EXCHANGE_SigningKeySignature *sign_sigs;
     75 
     76   /**
     77    * Length of the @e sign_sigs array.
     78    */
     79   unsigned int num_sign_sigs;
     80 
     81   /**
     82    * Array of master signatures for the exchange's denomination keys.
     83    */
     84   struct TALER_EXCHANGE_DenominationKeySignature *denom_sigs;
     85 
     86   /**
     87    * Length of the @e denom_sigs array.
     88    */
     89   unsigned int num_denom_sigs;
     90 
     91 };
     92 
     93 
     94 /**
     95  * Function called when we're done processing the
     96  * HTTP POST /management/keys request.
     97  *
     98  * @param cls the `struct TALER_EXCHANGE_PostManagementKeysHandle`
     99  * @param response_code HTTP response code, 0 on error
    100  * @param response response body, NULL if not in JSON
    101  */
    102 static void
    103 handle_post_keys_finished (void *cls,
    104                            long response_code,
    105                            const void *response)
    106 {
    107   struct TALER_EXCHANGE_PostManagementKeysHandle *pmkh = cls;
    108   const json_t *json = response;
    109   struct TALER_EXCHANGE_PostManagementKeysResponse res = {
    110     .hr.http_status = (unsigned int) response_code,
    111     .hr.reply = json
    112   };
    113 
    114   pmkh->job = NULL;
    115   switch (response_code)
    116   {
    117   case MHD_HTTP_NO_CONTENT:
    118     break;
    119   case MHD_HTTP_FORBIDDEN:
    120     res.hr.ec = TALER_JSON_get_error_code (json);
    121     res.hr.hint = TALER_JSON_get_error_hint (json);
    122     break;
    123   case MHD_HTTP_NOT_FOUND:
    124     res.hr.ec = TALER_JSON_get_error_code (json);
    125     res.hr.hint = TALER_JSON_get_error_hint (json);
    126     break;
    127   case MHD_HTTP_CONFLICT:
    128     res.hr.ec = TALER_JSON_get_error_code (json);
    129     res.hr.hint = TALER_JSON_get_error_hint (json);
    130     break;
    131   case MHD_HTTP_CONTENT_TOO_LARGE:
    132     res.hr.ec = TALER_JSON_get_error_code (json);
    133     res.hr.hint = TALER_JSON_get_error_hint (json);
    134     break;
    135   default:
    136     /* unexpected response code */
    137     GNUNET_break_op (0);
    138     res.hr.ec = TALER_JSON_get_error_code (json);
    139     res.hr.hint = TALER_JSON_get_error_hint (json);
    140     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    141                 "Unexpected response code %u/%d for exchange management post keys\n",
    142                 (unsigned int) response_code,
    143                 (int) res.hr.ec);
    144     break;
    145   }
    146   if (NULL != pmkh->cb)
    147   {
    148     pmkh->cb (pmkh->cb_cls,
    149               &res);
    150     pmkh->cb = NULL;
    151   }
    152   TALER_EXCHANGE_post_management_keys_cancel (pmkh);
    153 }
    154 
    155 
    156 struct TALER_EXCHANGE_PostManagementKeysHandle *
    157 TALER_EXCHANGE_post_management_keys_create (
    158   struct GNUNET_CURL_Context *ctx,
    159   const char *url,
    160   const struct TALER_EXCHANGE_ManagementPostKeysData *pkd)
    161 {
    162   struct TALER_EXCHANGE_PostManagementKeysHandle *pmkh;
    163 
    164   pmkh = GNUNET_new (struct TALER_EXCHANGE_PostManagementKeysHandle);
    165   pmkh->ctx = ctx;
    166   pmkh->base_url = GNUNET_strdup (url);
    167   pmkh->num_sign_sigs = pkd->num_sign_sigs;
    168   pmkh->num_denom_sigs = pkd->num_denom_sigs;
    169   pmkh->sign_sigs = GNUNET_memdup (pkd->sign_sigs,
    170                                    pkd->num_sign_sigs
    171                                    * sizeof (struct
    172                                              TALER_EXCHANGE_SigningKeySignature)
    173                                    );
    174   pmkh->denom_sigs = GNUNET_memdup (pkd->denom_sigs,
    175                                     pkd->num_denom_sigs
    176                                     * sizeof (struct
    177                                               TALER_EXCHANGE_DenominationKeySignature));
    178   return pmkh;
    179 }
    180 
    181 
    182 enum TALER_ErrorCode
    183 TALER_EXCHANGE_post_management_keys_start (
    184   struct TALER_EXCHANGE_PostManagementKeysHandle *pmkh,
    185   TALER_EXCHANGE_PostManagementKeysCallback cb,
    186   TALER_EXCHANGE_POST_MANAGEMENT_KEYS_RESULT_CLOSURE *cb_cls)
    187 {
    188   CURL *eh;
    189   json_t *body;
    190   json_t *denom_sigs;
    191   json_t *signkey_sigs;
    192 
    193   pmkh->cb = cb;
    194   pmkh->cb_cls = cb_cls;
    195   pmkh->url = TALER_url_join (pmkh->base_url,
    196                               "management/keys",
    197                               NULL);
    198   if (NULL == pmkh->url)
    199   {
    200     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    201                 "Could not construct request URL.\n");
    202     return TALER_EC_GENERIC_CONFIGURATION_INVALID;
    203   }
    204   denom_sigs = json_array ();
    205   GNUNET_assert (NULL != denom_sigs);
    206   for (unsigned int i = 0; i < pmkh->num_denom_sigs; i++)
    207   {
    208     const struct TALER_EXCHANGE_DenominationKeySignature *dks
    209       = &pmkh->denom_sigs[i];
    210 
    211     GNUNET_assert (0 ==
    212                    json_array_append_new (
    213                      denom_sigs,
    214                      GNUNET_JSON_PACK (
    215                        GNUNET_JSON_pack_data_auto ("h_denom_pub",
    216                                                    &dks->h_denom_pub),
    217                        GNUNET_JSON_pack_data_auto ("master_sig",
    218                                                    &dks->master_sig))));
    219   }
    220   signkey_sigs = json_array ();
    221   GNUNET_assert (NULL != signkey_sigs);
    222   for (unsigned int i = 0; i < pmkh->num_sign_sigs; i++)
    223   {
    224     const struct TALER_EXCHANGE_SigningKeySignature *sks
    225       = &pmkh->sign_sigs[i];
    226 
    227     GNUNET_assert (0 ==
    228                    json_array_append_new (
    229                      signkey_sigs,
    230                      GNUNET_JSON_PACK (
    231                        GNUNET_JSON_pack_data_auto ("exchange_pub",
    232                                                    &sks->exchange_pub),
    233                        GNUNET_JSON_pack_data_auto ("master_sig",
    234                                                    &sks->master_sig))));
    235   }
    236   body = GNUNET_JSON_PACK (
    237     GNUNET_JSON_pack_array_steal ("denom_sigs",
    238                                   denom_sigs),
    239     GNUNET_JSON_pack_array_steal ("signkey_sigs",
    240                                   signkey_sigs));
    241   eh = TALER_EXCHANGE_curl_easy_get_ (pmkh->url);
    242   if ( (NULL == eh) ||
    243        (GNUNET_OK !=
    244         TALER_curl_easy_post (&pmkh->post_ctx,
    245                               eh,
    246                               body)) )
    247   {
    248     GNUNET_break (0);
    249     if (NULL != eh)
    250       curl_easy_cleanup (eh);
    251     json_decref (body);
    252     GNUNET_free (pmkh->url);
    253     pmkh->url = NULL;
    254     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
    255   }
    256   json_decref (body);
    257   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    258               "Requesting URL '%s'\n",
    259               pmkh->url);
    260   pmkh->job = GNUNET_CURL_job_add2 (pmkh->ctx,
    261                                     eh,
    262                                     pmkh->post_ctx.headers,
    263                                     &handle_post_keys_finished,
    264                                     pmkh);
    265   if (NULL == pmkh->job)
    266   {
    267     TALER_curl_easy_post_finished (&pmkh->post_ctx);
    268     GNUNET_free (pmkh->url);
    269     pmkh->url = NULL;
    270     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
    271   }
    272   return TALER_EC_NONE;
    273 }
    274 
    275 
    276 void
    277 TALER_EXCHANGE_post_management_keys_cancel (
    278   struct TALER_EXCHANGE_PostManagementKeysHandle *pmkh)
    279 {
    280   if (NULL != pmkh->job)
    281   {
    282     GNUNET_CURL_job_cancel (pmkh->job);
    283     pmkh->job = NULL;
    284   }
    285   TALER_curl_easy_post_finished (&pmkh->post_ctx);
    286   GNUNET_free (pmkh->sign_sigs);
    287   GNUNET_free (pmkh->denom_sigs);
    288   GNUNET_free (pmkh->url);
    289   GNUNET_free (pmkh->base_url);
    290   GNUNET_free (pmkh);
    291 }
    292 
    293 
    294 /* end of exchange_api_post-management-keys.c */