LCOV - code coverage report
Current view: top level - lib - exchange_api_management_get_keys.c (source / functions) Hit Total Coverage
Test: GNU Taler exchange coverage report Lines: 0 149 0.0 %
Date: 2022-08-25 06:15:09 Functions: 0 4 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   Copyright (C) 2015-2020 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_management_get_keys.c
      19             :  * @brief functions to obtain future online keys of the exchange
      20             :  * @author Christian Grothoff
      21             :  */
      22             : #include "platform.h"
      23             : #include "taler_json_lib.h"
      24             : #include <gnunet/gnunet_curl_lib.h>
      25             : #include "taler_exchange_service.h"
      26             : #include "exchange_api_curl_defaults.h"
      27             : #include "taler_signatures.h"
      28             : #include "taler_curl_lib.h"
      29             : #include "taler_crypto_lib.h"
      30             : #include "taler_json_lib.h"
      31             : 
      32             : /**
      33             :  * Set to 1 for extra debug logging.
      34             :  */
      35             : #define DEBUG 0
      36             : 
      37             : 
      38             : /**
      39             :  * @brief Handle for a GET /management/keys request.
      40             :  */
      41             : struct TALER_EXCHANGE_ManagementGetKeysHandle
      42             : {
      43             : 
      44             :   /**
      45             :    * The url for this request.
      46             :    */
      47             :   char *url;
      48             : 
      49             :   /**
      50             :    * Handle for the request.
      51             :    */
      52             :   struct GNUNET_CURL_Job *job;
      53             : 
      54             :   /**
      55             :    * Function to call with the result.
      56             :    */
      57             :   TALER_EXCHANGE_ManagementGetKeysCallback cb;
      58             : 
      59             :   /**
      60             :    * Closure for @a cb.
      61             :    */
      62             :   void *cb_cls;
      63             : 
      64             :   /**
      65             :    * Reference to the execution context.
      66             :    */
      67             :   struct GNUNET_CURL_Context *ctx;
      68             : };
      69             : 
      70             : 
      71             : /**
      72             :  * Handle the case that the response was of type #MHD_HTTP_OK.
      73             :  *
      74             :  * @param[in,out] gh request handle
      75             :  * @param response the response
      76             :  * @return #GNUNET_OK if the response was well-formed
      77             :  */
      78             : static int
      79           0 : handle_ok (struct TALER_EXCHANGE_ManagementGetKeysHandle *gh,
      80             :            const json_t *response)
      81             : {
      82             :   struct TALER_EXCHANGE_FutureKeys fk;
      83             :   json_t *sk;
      84             :   json_t *dk;
      85             :   bool ok;
      86             :   struct GNUNET_JSON_Specification spec[] = {
      87           0 :     GNUNET_JSON_spec_json ("future_denoms",
      88             :                            &dk),
      89           0 :     GNUNET_JSON_spec_json ("future_signkeys",
      90             :                            &sk),
      91           0 :     GNUNET_JSON_spec_fixed_auto ("master_pub",
      92             :                                  &fk.master_pub),
      93           0 :     GNUNET_JSON_spec_fixed_auto ("denom_secmod_public_key",
      94             :                                  &fk.denom_secmod_public_key),
      95           0 :     GNUNET_JSON_spec_fixed_auto ("denom_secmod_cs_public_key",
      96             :                                  &fk.denom_secmod_cs_public_key),
      97           0 :     GNUNET_JSON_spec_fixed_auto ("signkey_secmod_public_key",
      98             :                                  &fk.signkey_secmod_public_key),
      99           0 :     GNUNET_JSON_spec_end ()
     100             :   };
     101             : 
     102           0 :   if (GNUNET_OK !=
     103           0 :       GNUNET_JSON_parse (response,
     104             :                          spec,
     105             :                          NULL, NULL))
     106             :   {
     107           0 :     GNUNET_break_op (0);
     108           0 :     return GNUNET_SYSERR;
     109             :   }
     110           0 :   fk.num_sign_keys = json_array_size (sk);
     111           0 :   fk.num_denom_keys = json_array_size (dk);
     112           0 :   fk.sign_keys = GNUNET_new_array (
     113             :     fk.num_sign_keys,
     114             :     struct TALER_EXCHANGE_FutureSigningPublicKey);
     115           0 :   fk.denom_keys = GNUNET_new_array (
     116             :     fk.num_denom_keys,
     117             :     struct TALER_EXCHANGE_FutureDenomPublicKey);
     118           0 :   ok = true;
     119           0 :   for (unsigned int i = 0; i<fk.num_sign_keys; i++)
     120             :   {
     121           0 :     json_t *j = json_array_get (sk,
     122             :                                 i);
     123           0 :     struct TALER_EXCHANGE_FutureSigningPublicKey *sign_key
     124           0 :       = &fk.sign_keys[i];
     125             :     struct GNUNET_JSON_Specification spec[] = {
     126           0 :       GNUNET_JSON_spec_fixed_auto ("key",
     127             :                                    &sign_key->key),
     128           0 :       GNUNET_JSON_spec_fixed_auto ("signkey_secmod_sig",
     129             :                                    &sign_key->signkey_secmod_sig),
     130           0 :       GNUNET_JSON_spec_timestamp ("stamp_start",
     131             :                                   &sign_key->valid_from),
     132           0 :       GNUNET_JSON_spec_timestamp ("stamp_expire",
     133             :                                   &sign_key->valid_until),
     134           0 :       GNUNET_JSON_spec_timestamp ("stamp_end",
     135             :                                   &sign_key->valid_legal),
     136           0 :       GNUNET_JSON_spec_end ()
     137             :     };
     138             : 
     139           0 :     if (GNUNET_OK !=
     140           0 :         GNUNET_JSON_parse (j,
     141             :                            spec,
     142             :                            NULL, NULL))
     143             :     {
     144           0 :       GNUNET_break_op (0);
     145           0 :       ok = false;
     146           0 :       break;
     147             :     }
     148             :     {
     149             :       struct GNUNET_TIME_Relative duration
     150           0 :         = GNUNET_TIME_absolute_get_difference (sign_key->valid_from.abs_time,
     151             :                                                sign_key->valid_until.abs_time);
     152             : 
     153           0 :       if (GNUNET_OK !=
     154           0 :           TALER_exchange_secmod_eddsa_verify (
     155           0 :             &sign_key->key,
     156             :             sign_key->valid_from,
     157             :             duration,
     158             :             &fk.signkey_secmod_public_key,
     159           0 :             &sign_key->signkey_secmod_sig))
     160             :       {
     161           0 :         GNUNET_break_op (0);
     162           0 :         ok = false;
     163           0 :         break;
     164             :       }
     165             :     }
     166             :   }
     167           0 :   for (unsigned int i = 0; i<fk.num_denom_keys; i++)
     168             :   {
     169           0 :     json_t *j = json_array_get (dk,
     170             :                                 i);
     171           0 :     struct TALER_EXCHANGE_FutureDenomPublicKey *denom_key
     172           0 :       = &fk.denom_keys[i];
     173             :     const char *section_name;
     174             :     struct GNUNET_JSON_Specification spec[] = {
     175           0 :       TALER_JSON_spec_amount_any ("value",
     176             :                                   &denom_key->value),
     177           0 :       GNUNET_JSON_spec_timestamp ("stamp_start",
     178             :                                   &denom_key->valid_from),
     179           0 :       GNUNET_JSON_spec_timestamp ("stamp_expire_withdraw",
     180             :                                   &denom_key->withdraw_valid_until),
     181           0 :       GNUNET_JSON_spec_timestamp ("stamp_expire_deposit",
     182             :                                   &denom_key->expire_deposit),
     183           0 :       GNUNET_JSON_spec_timestamp ("stamp_expire_legal",
     184             :                                   &denom_key->expire_legal),
     185           0 :       TALER_JSON_spec_denom_pub ("denom_pub",
     186             :                                  &denom_key->key),
     187           0 :       TALER_JSON_spec_amount_any ("fee_withdraw",
     188             :                                   &denom_key->fee_withdraw),
     189           0 :       TALER_JSON_spec_amount_any ("fee_deposit",
     190             :                                   &denom_key->fee_deposit),
     191           0 :       TALER_JSON_spec_amount_any ("fee_refresh",
     192             :                                   &denom_key->fee_refresh),
     193           0 :       TALER_JSON_spec_amount_any ("fee_refund",
     194             :                                   &denom_key->fee_refund),
     195           0 :       GNUNET_JSON_spec_fixed_auto ("denom_secmod_sig",
     196             :                                    &denom_key->denom_secmod_sig),
     197           0 :       GNUNET_JSON_spec_string ("section_name",
     198             :                                &section_name),
     199           0 :       GNUNET_JSON_spec_end ()
     200             :     };
     201             : 
     202           0 :     if (GNUNET_OK !=
     203           0 :         GNUNET_JSON_parse (j,
     204             :                            spec,
     205             :                            NULL, NULL))
     206             :     {
     207           0 :       GNUNET_break_op (0);
     208             : #if DEBUG
     209             :       json_dumpf (j,
     210             :                   stderr,
     211             :                   JSON_INDENT (2));
     212             : #endif
     213           0 :       ok = false;
     214           0 :       break;
     215             :     }
     216             : 
     217             :     {
     218             :       struct TALER_DenominationHashP h_denom_pub;
     219             :       struct GNUNET_TIME_Relative duration
     220           0 :         = GNUNET_TIME_absolute_get_difference (
     221             :             denom_key->valid_from.abs_time,
     222             :             denom_key->withdraw_valid_until.abs_time);
     223             : 
     224           0 :       TALER_denom_pub_hash (&denom_key->key,
     225             :                             &h_denom_pub);
     226           0 :       switch (denom_key->key.cipher)
     227             :       {
     228           0 :       case TALER_DENOMINATION_RSA:
     229             :         {
     230             :           struct TALER_RsaPubHashP h_rsa;
     231             : 
     232           0 :           TALER_rsa_pub_hash (denom_key->key.details.rsa_public_key,
     233             :                               &h_rsa);
     234           0 :           if (GNUNET_OK !=
     235           0 :               TALER_exchange_secmod_rsa_verify (&h_rsa,
     236             :                                                 section_name,
     237             :                                                 denom_key->valid_from,
     238             :                                                 duration,
     239             :                                                 &fk.denom_secmod_public_key,
     240           0 :                                                 &denom_key->denom_secmod_sig))
     241             :           {
     242           0 :             GNUNET_break_op (0);
     243           0 :             ok = false;
     244           0 :             break;
     245             :           }
     246             :         }
     247           0 :         break;
     248           0 :       case TALER_DENOMINATION_CS:
     249             :         {
     250             :           struct TALER_CsPubHashP h_cs;
     251             : 
     252           0 :           TALER_cs_pub_hash (&denom_key->key.details.cs_public_key,
     253             :                              &h_cs);
     254           0 :           if (GNUNET_OK !=
     255           0 :               TALER_exchange_secmod_cs_verify (&h_cs,
     256             :                                                section_name,
     257             :                                                denom_key->valid_from,
     258             :                                                duration,
     259             :                                                &fk.denom_secmod_cs_public_key,
     260           0 :                                                &denom_key->denom_secmod_sig))
     261             :           {
     262           0 :             GNUNET_break_op (0);
     263           0 :             ok = false;
     264           0 :             break;
     265             :           }
     266             :         }
     267           0 :         break;
     268           0 :       default:
     269           0 :         GNUNET_break_op (0);
     270           0 :         ok = false;
     271           0 :         break;
     272             :       }
     273             :     }
     274           0 :     GNUNET_JSON_parse_free (spec);
     275           0 :     if (! ok)
     276           0 :       break;
     277             :   }
     278           0 :   if (ok)
     279             :   {
     280           0 :     struct TALER_EXCHANGE_HttpResponse hr = {
     281             :       .http_status = MHD_HTTP_OK,
     282             :       .reply = response
     283             :     };
     284             : 
     285           0 :     gh->cb (gh->cb_cls,
     286             :             &hr,
     287             :             &fk);
     288             :   }
     289           0 :   for (unsigned int i = 0; i<fk.num_denom_keys; i++)
     290           0 :     TALER_denom_pub_free (&fk.denom_keys[i].key);
     291           0 :   GNUNET_free (fk.sign_keys);
     292           0 :   GNUNET_free (fk.denom_keys);
     293           0 :   GNUNET_JSON_parse_free (spec);
     294           0 :   return (ok) ? GNUNET_OK : GNUNET_SYSERR;
     295             : }
     296             : 
     297             : 
     298             : /**
     299             :  * Function called when we're done processing the
     300             :  * HTTP GET /management/keys request.
     301             :  *
     302             :  * @param cls the `struct TALER_EXCHANGE_ManagementGetKeysHandle *`
     303             :  * @param response_code HTTP response code, 0 on error
     304             :  * @param response response body, NULL if not in JSON
     305             :  */
     306             : static void
     307           0 : handle_get_keys_finished (void *cls,
     308             :                           long response_code,
     309             :                           const void *response)
     310             : {
     311           0 :   struct TALER_EXCHANGE_ManagementGetKeysHandle *gh = cls;
     312           0 :   const json_t *json = response;
     313           0 :   struct TALER_EXCHANGE_HttpResponse hr = {
     314           0 :     .http_status = (unsigned int) response_code,
     315             :     .reply = json
     316             :   };
     317             : 
     318           0 :   gh->job = NULL;
     319           0 :   switch (response_code)
     320             :   {
     321           0 :   case MHD_HTTP_OK:
     322           0 :     if (GNUNET_OK ==
     323           0 :         handle_ok (gh,
     324             :                    response))
     325             :     {
     326           0 :       gh->cb = NULL;
     327             :     }
     328             :     else
     329             :     {
     330           0 :       response_code = 0;
     331             :     }
     332           0 :     break;
     333           0 :   default:
     334             :     /* unexpected response code */
     335           0 :     if (NULL != json)
     336             :     {
     337           0 :       hr.ec = TALER_JSON_get_error_code (json);
     338           0 :       hr.hint = TALER_JSON_get_error_hint (json);
     339             :     }
     340             :     else
     341             :     {
     342           0 :       hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
     343           0 :       hr.hint = TALER_ErrorCode_get_hint (hr.ec);
     344             :     }
     345           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     346             :                 "Unexpected response code %u/%d for exchange management get keys\n",
     347             :                 (unsigned int) response_code,
     348             :                 (int) hr.ec);
     349           0 :     break;
     350             :   }
     351           0 :   if (NULL != gh->cb)
     352             :   {
     353           0 :     gh->cb (gh->cb_cls,
     354             :             &hr,
     355             :             NULL);
     356           0 :     gh->cb = NULL;
     357             :   }
     358           0 :   TALER_EXCHANGE_get_management_keys_cancel (gh);
     359           0 : };
     360             : 
     361             : 
     362             : struct TALER_EXCHANGE_ManagementGetKeysHandle *
     363           0 : TALER_EXCHANGE_get_management_keys (struct GNUNET_CURL_Context *ctx,
     364             :                                     const char *url,
     365             :                                     TALER_EXCHANGE_ManagementGetKeysCallback cb,
     366             :                                     void *cb_cls)
     367             : {
     368             :   struct TALER_EXCHANGE_ManagementGetKeysHandle *gh;
     369             :   CURL *eh;
     370             : 
     371           0 :   gh = GNUNET_new (struct TALER_EXCHANGE_ManagementGetKeysHandle);
     372           0 :   gh->cb = cb;
     373           0 :   gh->cb_cls = cb_cls;
     374           0 :   gh->ctx = ctx;
     375           0 :   gh->url = TALER_url_join (url,
     376             :                             "management/keys",
     377             :                             NULL);
     378           0 :   if (NULL == gh->url)
     379             :   {
     380           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     381             :                 "Could not construct request URL.\n");
     382           0 :     GNUNET_free (gh);
     383           0 :     return NULL;
     384             :   }
     385           0 :   eh = TALER_EXCHANGE_curl_easy_get_ (gh->url);
     386           0 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     387             :               "Requesting URL '%s'\n",
     388             :               gh->url);
     389           0 :   gh->job = GNUNET_CURL_job_add (ctx,
     390             :                                  eh,
     391             :                                  &handle_get_keys_finished,
     392             :                                  gh);
     393           0 :   if (NULL == gh->job)
     394             :   {
     395           0 :     TALER_EXCHANGE_get_management_keys_cancel (gh);
     396           0 :     return NULL;
     397             :   }
     398           0 :   return gh;
     399             : }
     400             : 
     401             : 
     402             : void
     403           0 : TALER_EXCHANGE_get_management_keys_cancel (
     404             :   struct TALER_EXCHANGE_ManagementGetKeysHandle *gh)
     405             : {
     406           0 :   if (NULL != gh->job)
     407             :   {
     408           0 :     GNUNET_CURL_job_cancel (gh->job);
     409           0 :     gh->job = NULL;
     410             :   }
     411           0 :   GNUNET_free (gh->url);
     412           0 :   GNUNET_free (gh);
     413           0 : }

Generated by: LCOV version 1.14