LCOV - code coverage report
Current view: top level - lib - auditor_api_get_config.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 55.8 % 86 48
Test Date: 2025-12-28 14:06:02 Functions: 100.0 % 4 4

            Line data    Source code
       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            5 : 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            5 :     TALER_JSON_spec_version ("version",
     112              :                              &pv),
     113            5 :     GNUNET_JSON_spec_string ("version",
     114              :                              &ver),
     115            5 :     GNUNET_JSON_spec_fixed_auto ("exchange_master_public_key",
     116              :                                  &vi->exchange_master_public_key),
     117            5 :     GNUNET_JSON_spec_fixed_auto ("auditor_public_key",
     118              :                                  &vi->auditor_pub),
     119            5 :     GNUNET_JSON_spec_end ()
     120              :   };
     121              : 
     122            5 :   if (JSON_OBJECT != json_typeof (resp_obj))
     123              :   {
     124            0 :     GNUNET_break_op (0);
     125            0 :     return TALER_EC_GENERIC_JSON_INVALID;
     126              :   }
     127              :   /* check the config */
     128            5 :   if (GNUNET_OK !=
     129            5 :       GNUNET_JSON_parse (resp_obj,
     130              :                          spec,
     131              :                          NULL, NULL))
     132              :   {
     133            0 :     GNUNET_break_op (0);
     134            0 :     return TALER_EC_GENERIC_JSON_INVALID;
     135              :   }
     136            5 :   vi->version = ver;
     137            5 :   *vc = TALER_AUDITOR_VC_MATCH;
     138            5 :   if (TALER_PROTOCOL_CURRENT < pv.current)
     139              :   {
     140            0 :     *vc |= TALER_AUDITOR_VC_NEWER;
     141            0 :     if (TALER_PROTOCOL_CURRENT < pv.current - pv.age)
     142            0 :       *vc |= TALER_AUDITOR_VC_INCOMPATIBLE;
     143              :   }
     144            5 :   if (TALER_PROTOCOL_CURRENT > pv.current)
     145              :   {
     146            0 :     *vc |= TALER_AUDITOR_VC_OLDER;
     147            0 :     if (TALER_PROTOCOL_CURRENT - TALER_PROTOCOL_AGE > pv.current)
     148            0 :       *vc |= TALER_AUDITOR_VC_INCOMPATIBLE;
     149              :   }
     150            5 :   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            5 : config_completed_cb (void *cls,
     164              :                      long response_code,
     165              :                      const void *gresp_obj)
     166              : {
     167            5 :   struct TALER_AUDITOR_GetConfigHandle *auditor = cls;
     168            5 :   const json_t *resp_obj = gresp_obj;
     169            5 :   struct TALER_AUDITOR_ConfigResponse vr = {
     170              :     .hr.reply = resp_obj,
     171            5 :     .hr.http_status = (unsigned int) response_code
     172              :   };
     173              : 
     174            5 :   auditor->vr = NULL;
     175            5 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     176              :               "Received config from URL `%s' with status %ld.\n",
     177              :               auditor->vr_url,
     178              :               response_code);
     179            5 :   switch (response_code)
     180              :   {
     181            0 :   case 0:
     182            0 :     GNUNET_break_op (0);
     183            0 :     vr.hr.ec = TALER_EC_INVALID;
     184            0 :     break;
     185            5 :   case MHD_HTTP_OK:
     186            5 :     if (NULL == resp_obj)
     187              :     {
     188            0 :       GNUNET_break_op (0);
     189            0 :       vr.hr.http_status = 0;
     190            0 :       vr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
     191            0 :       break;
     192              :     }
     193            5 :     vr.hr.ec = decode_config_json (resp_obj,
     194              :                                    &vr.details.ok.vi,
     195              :                                    &vr.details.ok.compat);
     196            5 :     if (TALER_EC_NONE != vr.hr.ec)
     197              :     {
     198            0 :       GNUNET_break_op (0);
     199            0 :       vr.hr.http_status = 0;
     200            0 :       break;
     201              :     }
     202            5 :     break;
     203            0 :   case MHD_HTTP_INTERNAL_SERVER_ERROR:
     204            0 :     vr.hr.ec = TALER_JSON_get_error_code (resp_obj);
     205            0 :     vr.hr.hint = TALER_JSON_get_error_hint (resp_obj);
     206            0 :     break;
     207            0 :   default:
     208            0 :     vr.hr.ec = TALER_JSON_get_error_code (resp_obj);
     209            0 :     vr.hr.hint = TALER_JSON_get_error_hint (resp_obj);
     210            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     211              :                 "Unexpected response code %u/%d\n",
     212              :                 (unsigned int) response_code,
     213              :                 (int) vr.hr.ec);
     214            0 :     break;
     215              :   }
     216            5 :   auditor->config_cb (auditor->config_cb_cls,
     217              :                       &vr);
     218            5 :   TALER_AUDITOR_get_config_cancel (auditor);
     219            5 : }
     220              : 
     221              : 
     222              : struct TALER_AUDITOR_GetConfigHandle *
     223            5 : 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            5 :   auditor = GNUNET_new (struct TALER_AUDITOR_GetConfigHandle);
     232            5 :   auditor->config_cb = config_cb;
     233            5 :   auditor->config_cb_cls = config_cb_cls;
     234            5 :   auditor->ctx = ctx;
     235            5 :   auditor->vr_url = TALER_url_join (url,
     236              :                                     "config",
     237              :                                     NULL);
     238            5 :   if (NULL == auditor->vr_url)
     239              :   {
     240            0 :     GNUNET_break (0);
     241            0 :     GNUNET_free (auditor);
     242            0 :     return NULL;
     243              :   }
     244            5 :   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     245              :               "Requesting auditor config with URL `%s'.\n",
     246              :               auditor->vr_url);
     247            5 :   eh = TALER_AUDITOR_curl_easy_get_ (auditor->vr_url);
     248            5 :   if (NULL == eh)
     249              :   {
     250            0 :     GNUNET_break (0);
     251            0 :     TALER_AUDITOR_get_config_cancel (auditor);
     252            0 :     return NULL;
     253              :   }
     254            5 :   GNUNET_break (CURLE_OK ==
     255              :                 curl_easy_setopt (eh,
     256              :                                   CURLOPT_TIMEOUT,
     257              :                                   (long) 300));
     258            5 :   auditor->vr = GNUNET_CURL_job_add (auditor->ctx,
     259              :                                      eh,
     260              :                                      &config_completed_cb,
     261              :                                      auditor);
     262            5 :   return auditor;
     263              : }
     264              : 
     265              : 
     266              : void
     267            5 : TALER_AUDITOR_get_config_cancel (struct TALER_AUDITOR_GetConfigHandle *auditor)
     268              : {
     269            5 :   if (NULL != auditor->vr)
     270              :   {
     271            0 :     GNUNET_CURL_job_cancel (auditor->vr);
     272            0 :     auditor->vr = NULL;
     273              :   }
     274            5 :   GNUNET_free (auditor->vr_url);
     275            5 :   GNUNET_free (auditor);
     276            5 : }
     277              : 
     278              : 
     279              : /* end of auditor_api_get_config.c */
        

Generated by: LCOV version 2.0-1