exchange

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

auditor_api_get_config.c (7974B)


      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 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/auditor_api_get_config.c
     19  * @brief Implementation of /config for the auditor's HTTP API
     20  * @author Sree Harsha Totakura <sreeharsha@totakura.in>
     21  * @author Christian Grothoff
     22  */
     23 #include "taler/platform.h"
     24 #include <microhttpd.h>
     25 #include <gnunet/gnunet_curl_lib.h>
     26 #include "taler/taler_json_lib.h"
     27 #include "taler/taler_auditor_service.h"
     28 #include "taler/taler_signatures.h"
     29 #include "auditor_api_curl_defaults.h"
     30 
     31 
     32 /**
     33  * Which revision of the Taler auditor protocol is implemented
     34  * by this library?  Used to determine compatibility.
     35  */
     36 #define TALER_PROTOCOL_CURRENT 1
     37 
     38 /**
     39  * How many revisions back are we compatible to?
     40  */
     41 #define TALER_PROTOCOL_AGE 0
     42 
     43 
     44 /**
     45  * Log error related to CURL operations.
     46  *
     47  * @param type log level
     48  * @param function which function failed to run
     49  * @param code what was the curl error code
     50  */
     51 #define CURL_STRERROR(type, function, code)      \
     52         GNUNET_log (type, \
     53                     "Curl function `%s' has failed at `%s:%d' with error: %s", \
     54                     function, __FILE__, __LINE__, curl_easy_strerror (code));
     55 
     56 
     57 /**
     58  * Handle for the get config request.
     59  */
     60 struct TALER_AUDITOR_GetConfigHandle
     61 {
     62   /**
     63    * The context of this handle
     64    */
     65   struct GNUNET_CURL_Context *ctx;
     66 
     67   /**
     68    * Function to call with the auditor's certification data,
     69    * NULL if this has already been done.
     70    */
     71   TALER_AUDITOR_ConfigCallback config_cb;
     72 
     73   /**
     74    * Closure to pass to @e config_cb.
     75    */
     76   void *config_cb_cls;
     77 
     78   /**
     79    * Data for the request to get the /config of a auditor,
     80    * NULL once we are past stage #MHS_INIT.
     81    */
     82   struct GNUNET_CURL_Job *vr;
     83 
     84   /**
     85    * The url for the @e vr job.
     86    */
     87   char *vr_url;
     88 
     89 };
     90 
     91 
     92 /* ***************** Internal /config fetching ************* */
     93 
     94 /**
     95  * Decode the JSON in @a resp_obj from the /config response and store the data
     96  * in the @a key_data.
     97  *
     98  * @param[in] resp_obj JSON object to parse
     99  * @param[in,out] vi where to store the results we decoded
    100  * @param[out] vc where to store config compatibility data
    101  * @return #TALER_EC_NONE on success
    102  */
    103 static enum TALER_ErrorCode
    104 decode_config_json (const json_t *resp_obj,
    105                     struct TALER_AUDITOR_ConfigInformation *vi,
    106                     enum TALER_AUDITOR_VersionCompatibility *vc)
    107 {
    108   struct TALER_JSON_ProtocolVersion pv;
    109   const char *ver;
    110   struct GNUNET_JSON_Specification spec[] = {
    111     TALER_JSON_spec_version ("version",
    112                              &pv),
    113     GNUNET_JSON_spec_string ("version",
    114                              &ver),
    115     GNUNET_JSON_spec_fixed_auto ("exchange_master_public_key",
    116                                  &vi->exchange_master_public_key),
    117     GNUNET_JSON_spec_fixed_auto ("auditor_public_key",
    118                                  &vi->auditor_pub),
    119     GNUNET_JSON_spec_end ()
    120   };
    121 
    122   if (JSON_OBJECT != json_typeof (resp_obj))
    123   {
    124     GNUNET_break_op (0);
    125     return TALER_EC_GENERIC_JSON_INVALID;
    126   }
    127   /* check the config */
    128   if (GNUNET_OK !=
    129       GNUNET_JSON_parse (resp_obj,
    130                          spec,
    131                          NULL, NULL))
    132   {
    133     GNUNET_break_op (0);
    134     return TALER_EC_GENERIC_JSON_INVALID;
    135   }
    136   vi->version = ver;
    137   *vc = TALER_AUDITOR_VC_MATCH;
    138   if (TALER_PROTOCOL_CURRENT < pv.current)
    139   {
    140     *vc |= TALER_AUDITOR_VC_NEWER;
    141     if (TALER_PROTOCOL_CURRENT < pv.current - pv.age)
    142       *vc |= TALER_AUDITOR_VC_INCOMPATIBLE;
    143   }
    144   if (TALER_PROTOCOL_CURRENT > pv.current)
    145   {
    146     *vc |= TALER_AUDITOR_VC_OLDER;
    147     if (TALER_PROTOCOL_CURRENT - TALER_PROTOCOL_AGE > pv.current)
    148       *vc |= TALER_AUDITOR_VC_INCOMPATIBLE;
    149   }
    150   return TALER_EC_NONE;
    151 }
    152 
    153 
    154 /**
    155  * Callback used when downloading the reply to a /config request
    156  * is complete.
    157  *
    158  * @param cls the `struct TALER_AUDITOR_GetConfigHandle`
    159  * @param response_code HTTP response code, 0 on error
    160  * @param gresp_obj parsed JSON result, NULL on error, must be a `const json_t *`
    161  */
    162 static void
    163 config_completed_cb (void *cls,
    164                      long response_code,
    165                      const void *gresp_obj)
    166 {
    167   struct TALER_AUDITOR_GetConfigHandle *auditor = cls;
    168   const json_t *resp_obj = gresp_obj;
    169   struct TALER_AUDITOR_ConfigResponse vr = {
    170     .hr.reply = resp_obj,
    171     .hr.http_status = (unsigned int) response_code
    172   };
    173 
    174   auditor->vr = NULL;
    175   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    176               "Received config from URL `%s' with status %ld.\n",
    177               auditor->vr_url,
    178               response_code);
    179   switch (response_code)
    180   {
    181   case 0:
    182     GNUNET_break_op (0);
    183     vr.hr.ec = TALER_EC_INVALID;
    184     break;
    185   case MHD_HTTP_OK:
    186     if (NULL == resp_obj)
    187     {
    188       GNUNET_break_op (0);
    189       vr.hr.http_status = 0;
    190       vr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
    191       break;
    192     }
    193     vr.hr.ec = decode_config_json (resp_obj,
    194                                    &vr.details.ok.vi,
    195                                    &vr.details.ok.compat);
    196     if (TALER_EC_NONE != vr.hr.ec)
    197     {
    198       GNUNET_break_op (0);
    199       vr.hr.http_status = 0;
    200       break;
    201     }
    202     break;
    203   case MHD_HTTP_INTERNAL_SERVER_ERROR:
    204     vr.hr.ec = TALER_JSON_get_error_code (resp_obj);
    205     vr.hr.hint = TALER_JSON_get_error_hint (resp_obj);
    206     break;
    207   default:
    208     vr.hr.ec = TALER_JSON_get_error_code (resp_obj);
    209     vr.hr.hint = TALER_JSON_get_error_hint (resp_obj);
    210     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    211                 "Unexpected response code %u/%d\n",
    212                 (unsigned int) response_code,
    213                 (int) vr.hr.ec);
    214     break;
    215   }
    216   auditor->config_cb (auditor->config_cb_cls,
    217                       &vr);
    218   TALER_AUDITOR_get_config_cancel (auditor);
    219 }
    220 
    221 
    222 struct TALER_AUDITOR_GetConfigHandle *
    223 TALER_AUDITOR_get_config (struct GNUNET_CURL_Context *ctx,
    224                           const char *url,
    225                           TALER_AUDITOR_ConfigCallback config_cb,
    226                           void *config_cb_cls)
    227 {
    228   struct TALER_AUDITOR_GetConfigHandle *auditor;
    229   CURL *eh;
    230 
    231   auditor = GNUNET_new (struct TALER_AUDITOR_GetConfigHandle);
    232   auditor->config_cb = config_cb;
    233   auditor->config_cb_cls = config_cb_cls;
    234   auditor->ctx = ctx;
    235   auditor->vr_url = TALER_url_join (url,
    236                                     "config",
    237                                     NULL);
    238   if (NULL == auditor->vr_url)
    239   {
    240     GNUNET_break (0);
    241     GNUNET_free (auditor);
    242     return NULL;
    243   }
    244   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    245               "Requesting auditor config with URL `%s'.\n",
    246               auditor->vr_url);
    247   eh = TALER_AUDITOR_curl_easy_get_ (auditor->vr_url);
    248   if (NULL == eh)
    249   {
    250     GNUNET_break (0);
    251     TALER_AUDITOR_get_config_cancel (auditor);
    252     return NULL;
    253   }
    254   GNUNET_break (CURLE_OK ==
    255                 curl_easy_setopt (eh,
    256                                   CURLOPT_TIMEOUT,
    257                                   (long) 300));
    258   auditor->vr = GNUNET_CURL_job_add (auditor->ctx,
    259                                      eh,
    260                                      &config_completed_cb,
    261                                      auditor);
    262   return auditor;
    263 }
    264 
    265 
    266 void
    267 TALER_AUDITOR_get_config_cancel (struct TALER_AUDITOR_GetConfigHandle *auditor)
    268 {
    269   if (NULL != auditor->vr)
    270   {
    271     GNUNET_CURL_job_cancel (auditor->vr);
    272     auditor->vr = NULL;
    273   }
    274   GNUNET_free (auditor->vr_url);
    275   GNUNET_free (auditor);
    276 }
    277 
    278 
    279 /* end of auditor_api_get_config.c */