LCOV - code coverage report
Current view: top level - lib - exchange_api_common.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 38.8 % 286 111
Test Date: 2026-04-14 15:39:31 Functions: 57.1 % 14 8

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   Copyright (C) 2015-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/exchange_api_common.c
      19              :  * @brief common functions for the exchange API
      20              :  * @author Christian Grothoff
      21              :  */
      22              : #include "taler/taler_json_lib.h"
      23              : #include <gnunet/gnunet_curl_lib.h>
      24              : #include "exchange_api_common.h"
      25              : #include "exchange_api_handle.h"
      26              : #include "taler/taler_signatures.h"
      27              : 
      28              : 
      29              : const struct TALER_EXCHANGE_SigningPublicKey *
      30            2 : TALER_EXCHANGE_get_signing_key_info (
      31              :   const struct TALER_EXCHANGE_Keys *keys,
      32              :   const struct TALER_ExchangePublicKeyP *exchange_pub)
      33              : {
      34            2 :   for (unsigned int i = 0; i<keys->num_sign_keys; i++)
      35              :   {
      36            2 :     const struct TALER_EXCHANGE_SigningPublicKey *spk
      37            2 :       = &keys->sign_keys[i];
      38              : 
      39            2 :     if (0 == GNUNET_memcmp (exchange_pub,
      40              :                             &spk->key))
      41            2 :       return spk;
      42              :   }
      43            0 :   return NULL;
      44              : }
      45              : 
      46              : 
      47              : enum GNUNET_GenericReturnValue
      48            0 : TALER_EXCHANGE_check_purse_create_conflict_ (
      49              :   const struct TALER_PurseContractSignatureP *cpurse_sig,
      50              :   const struct TALER_PurseContractPublicKeyP *purse_pub,
      51              :   const json_t *proof)
      52              : {
      53              :   struct TALER_Amount amount;
      54              :   uint32_t min_age;
      55              :   struct GNUNET_TIME_Timestamp purse_expiration;
      56              :   struct TALER_PurseContractSignatureP purse_sig;
      57              :   struct TALER_PrivateContractHashP h_contract_terms;
      58              :   struct TALER_PurseMergePublicKeyP merge_pub;
      59              :   struct GNUNET_JSON_Specification spec[] = {
      60            0 :     TALER_JSON_spec_amount_any ("amount",
      61              :                                 &amount),
      62            0 :     GNUNET_JSON_spec_uint32 ("min_age",
      63              :                              &min_age),
      64            0 :     GNUNET_JSON_spec_timestamp ("purse_expiration",
      65              :                                 &purse_expiration),
      66            0 :     GNUNET_JSON_spec_fixed_auto ("purse_sig",
      67              :                                  &purse_sig),
      68            0 :     GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
      69              :                                  &h_contract_terms),
      70            0 :     GNUNET_JSON_spec_fixed_auto ("merge_pub",
      71              :                                  &merge_pub),
      72            0 :     GNUNET_JSON_spec_end ()
      73              :   };
      74              : 
      75            0 :   if (GNUNET_OK !=
      76            0 :       GNUNET_JSON_parse (proof,
      77              :                          spec,
      78              :                          NULL, NULL))
      79              :   {
      80            0 :     GNUNET_break_op (0);
      81            0 :     return GNUNET_SYSERR;
      82              :   }
      83            0 :   if (GNUNET_OK !=
      84            0 :       TALER_wallet_purse_create_verify (purse_expiration,
      85              :                                         &h_contract_terms,
      86              :                                         &merge_pub,
      87              :                                         min_age,
      88              :                                         &amount,
      89              :                                         purse_pub,
      90              :                                         &purse_sig))
      91              :   {
      92            0 :     GNUNET_break_op (0);
      93            0 :     return GNUNET_SYSERR;
      94              :   }
      95            0 :   if (0 ==
      96            0 :       GNUNET_memcmp (&purse_sig,
      97              :                      cpurse_sig))
      98              :   {
      99              :     /* Must be the SAME data, not a conflict! */
     100            0 :     GNUNET_break_op (0);
     101            0 :     return GNUNET_SYSERR;
     102              :   }
     103            0 :   return GNUNET_OK;
     104              : }
     105              : 
     106              : 
     107              : enum GNUNET_GenericReturnValue
     108            2 : TALER_EXCHANGE_check_purse_merge_conflict_ (
     109              :   const struct TALER_PurseMergeSignatureP *cmerge_sig,
     110              :   const struct TALER_PurseMergePublicKeyP *merge_pub,
     111              :   const struct TALER_PurseContractPublicKeyP *purse_pub,
     112              :   const char *exchange_url,
     113              :   const json_t *proof)
     114              : {
     115              :   struct TALER_PurseMergeSignatureP merge_sig;
     116              :   struct GNUNET_TIME_Timestamp merge_timestamp;
     117            2 :   const char *partner_url = NULL;
     118              :   struct TALER_ReservePublicKeyP reserve_pub;
     119              :   struct GNUNET_JSON_Specification spec[] = {
     120            2 :     GNUNET_JSON_spec_mark_optional (
     121              :       TALER_JSON_spec_web_url ("partner_url",
     122              :                                &partner_url),
     123              :       NULL),
     124            2 :     GNUNET_JSON_spec_timestamp ("merge_timestamp",
     125              :                                 &merge_timestamp),
     126            2 :     GNUNET_JSON_spec_fixed_auto ("merge_sig",
     127              :                                  &merge_sig),
     128            2 :     GNUNET_JSON_spec_fixed_auto ("reserve_pub",
     129              :                                  &reserve_pub),
     130            2 :     GNUNET_JSON_spec_end ()
     131              :   };
     132              :   struct TALER_NormalizedPayto payto_uri;
     133              : 
     134            2 :   if (GNUNET_OK !=
     135            2 :       GNUNET_JSON_parse (proof,
     136              :                          spec,
     137              :                          NULL, NULL))
     138              :   {
     139            0 :     GNUNET_break_op (0);
     140            0 :     return GNUNET_SYSERR;
     141              :   }
     142            2 :   if (NULL == partner_url)
     143            2 :     partner_url = exchange_url;
     144            2 :   payto_uri = TALER_reserve_make_payto (partner_url,
     145              :                                         &reserve_pub);
     146            2 :   if (GNUNET_OK !=
     147            2 :       TALER_wallet_purse_merge_verify (
     148              :         payto_uri,
     149              :         merge_timestamp,
     150              :         purse_pub,
     151              :         merge_pub,
     152              :         &merge_sig))
     153              :   {
     154            0 :     GNUNET_break_op (0);
     155            0 :     GNUNET_free (payto_uri.normalized_payto);
     156            0 :     return GNUNET_SYSERR;
     157              :   }
     158            2 :   GNUNET_free (payto_uri.normalized_payto);
     159            2 :   if (0 ==
     160            2 :       GNUNET_memcmp (&merge_sig,
     161              :                      cmerge_sig))
     162              :   {
     163              :     /* Must be the SAME data, not a conflict! */
     164            0 :     GNUNET_break_op (0);
     165            0 :     return GNUNET_SYSERR;
     166              :   }
     167            2 :   return GNUNET_OK;
     168              : }
     169              : 
     170              : 
     171              : enum GNUNET_GenericReturnValue
     172            0 : TALER_EXCHANGE_check_purse_coin_conflict_ (
     173              :   const struct TALER_PurseContractPublicKeyP *purse_pub,
     174              :   const char *exchange_url,
     175              :   const json_t *proof,
     176              :   struct TALER_DenominationHashP *h_denom_pub,
     177              :   struct TALER_AgeCommitmentHashP *phac,
     178              :   struct TALER_CoinSpendPublicKeyP *coin_pub,
     179              :   struct TALER_CoinSpendSignatureP *coin_sig)
     180              : {
     181            0 :   const char *partner_url = NULL;
     182              :   struct TALER_Amount amount;
     183              :   struct GNUNET_JSON_Specification spec[] = {
     184            0 :     GNUNET_JSON_spec_fixed_auto ("h_denom_pub",
     185              :                                  h_denom_pub),
     186            0 :     GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
     187              :                                  phac),
     188            0 :     GNUNET_JSON_spec_fixed_auto ("coin_sig",
     189              :                                  coin_sig),
     190            0 :     GNUNET_JSON_spec_fixed_auto ("coin_pub",
     191              :                                  coin_pub),
     192            0 :     GNUNET_JSON_spec_mark_optional (
     193              :       TALER_JSON_spec_web_url ("partner_url",
     194              :                                &partner_url),
     195              :       NULL),
     196            0 :     TALER_JSON_spec_amount_any ("amount",
     197              :                                 &amount),
     198            0 :     GNUNET_JSON_spec_end ()
     199              :   };
     200              : 
     201            0 :   if (GNUNET_OK !=
     202            0 :       GNUNET_JSON_parse (proof,
     203              :                          spec,
     204              :                          NULL, NULL))
     205              :   {
     206            0 :     GNUNET_break_op (0);
     207            0 :     return GNUNET_SYSERR;
     208              :   }
     209            0 :   if (NULL == partner_url)
     210            0 :     partner_url = exchange_url;
     211            0 :   if (GNUNET_OK !=
     212            0 :       TALER_wallet_purse_deposit_verify (
     213              :         partner_url,
     214              :         purse_pub,
     215              :         &amount,
     216              :         h_denom_pub,
     217              :         phac,
     218              :         coin_pub,
     219              :         coin_sig))
     220              :   {
     221            0 :     GNUNET_break_op (0);
     222            0 :     return GNUNET_SYSERR;
     223              :   }
     224            0 :   return GNUNET_OK;
     225              : }
     226              : 
     227              : 
     228              : enum GNUNET_GenericReturnValue
     229            0 : TALER_EXCHANGE_check_purse_econtract_conflict_ (
     230              :   const struct TALER_PurseContractSignatureP *ccontract_sig,
     231              :   const struct TALER_PurseContractPublicKeyP *purse_pub,
     232              :   const json_t *proof)
     233              : {
     234              :   struct TALER_ContractDiffiePublicP contract_pub;
     235              :   struct TALER_PurseContractSignatureP contract_sig;
     236              :   struct GNUNET_HashCode h_econtract;
     237              :   struct GNUNET_JSON_Specification spec[] = {
     238            0 :     GNUNET_JSON_spec_fixed_auto ("h_econtract",
     239              :                                  &h_econtract),
     240            0 :     GNUNET_JSON_spec_fixed_auto ("econtract_sig",
     241              :                                  &contract_sig),
     242            0 :     GNUNET_JSON_spec_fixed_auto ("contract_pub",
     243              :                                  &contract_pub),
     244            0 :     GNUNET_JSON_spec_end ()
     245              :   };
     246              : 
     247            0 :   if (GNUNET_OK !=
     248            0 :       GNUNET_JSON_parse (proof,
     249              :                          spec,
     250              :                          NULL, NULL))
     251              :   {
     252            0 :     GNUNET_break_op (0);
     253            0 :     return GNUNET_SYSERR;
     254              :   }
     255            0 :   if (GNUNET_OK !=
     256            0 :       TALER_wallet_econtract_upload_verify2 (
     257              :         &h_econtract,
     258              :         &contract_pub,
     259              :         purse_pub,
     260              :         &contract_sig))
     261              :   {
     262            0 :     GNUNET_break_op (0);
     263            0 :     return GNUNET_SYSERR;
     264              :   }
     265            0 :   if (0 ==
     266            0 :       GNUNET_memcmp (&contract_sig,
     267              :                      ccontract_sig))
     268              :   {
     269              :     /* Must be the SAME data, not a conflict! */
     270            0 :     GNUNET_break_op (0);
     271            0 :     return GNUNET_SYSERR;
     272              :   }
     273            0 :   return GNUNET_OK;
     274              : }
     275              : 
     276              : 
     277              : // FIXME: should be used... - #9422
     278              : enum GNUNET_GenericReturnValue
     279            0 : TALER_EXCHANGE_check_coin_denomination_conflict_ (
     280              :   const json_t *proof,
     281              :   const struct TALER_DenominationHashP *ch_denom_pub)
     282              : {
     283              :   struct TALER_DenominationHashP h_denom_pub;
     284              :   struct GNUNET_JSON_Specification spec[] = {
     285            0 :     GNUNET_JSON_spec_fixed_auto ("h_denom_pub",
     286              :                                  &h_denom_pub),
     287            0 :     GNUNET_JSON_spec_end ()
     288              :   };
     289              : 
     290            0 :   if (GNUNET_OK !=
     291            0 :       GNUNET_JSON_parse (proof,
     292              :                          spec,
     293              :                          NULL, NULL))
     294              :   {
     295            0 :     GNUNET_break_op (0);
     296            0 :     return GNUNET_SYSERR;
     297              :   }
     298            0 :   if (0 ==
     299            0 :       GNUNET_memcmp (ch_denom_pub,
     300              :                      &h_denom_pub))
     301              :   {
     302            0 :     GNUNET_break_op (0);
     303            0 :     return GNUNET_OK;
     304              :   }
     305              :   /* indeed, proof with different denomination key provided */
     306            0 :   return GNUNET_OK;
     307              : }
     308              : 
     309              : 
     310              : enum GNUNET_GenericReturnValue
     311            0 : TALER_EXCHANGE_get_min_denomination_ (
     312              :   const struct TALER_EXCHANGE_Keys *keys,
     313              :   struct TALER_Amount *min)
     314              : {
     315            0 :   bool have_min = false;
     316            0 :   for (unsigned int i = 0; i<keys->num_denom_keys; i++)
     317              :   {
     318            0 :     const struct TALER_EXCHANGE_DenomPublicKey *dk = &keys->denom_keys[i];
     319              : 
     320            0 :     if (! have_min)
     321              :     {
     322            0 :       *min = dk->value;
     323            0 :       have_min = true;
     324            0 :       continue;
     325              :     }
     326            0 :     if (1 != TALER_amount_cmp (min,
     327              :                                &dk->value))
     328            0 :       continue;
     329            0 :     *min = dk->value;
     330              :   }
     331            0 :   if (! have_min)
     332              :   {
     333            0 :     GNUNET_break (0);
     334            0 :     return GNUNET_SYSERR;
     335              :   }
     336            0 :   return GNUNET_OK;
     337              : }
     338              : 
     339              : 
     340              : enum GNUNET_GenericReturnValue
     341          100 : TALER_EXCHANGE_verify_deposit_signature_ (
     342              :   const struct TALER_EXCHANGE_DepositContractDetail *dcd,
     343              :   const struct TALER_ExtensionPolicyHashP *ech,
     344              :   const struct TALER_MerchantWireHashP *h_wire,
     345              :   const struct TALER_EXCHANGE_CoinDepositDetail *cdd,
     346              :   const struct TALER_EXCHANGE_DenomPublicKey *dki)
     347              : {
     348          100 :   if (GNUNET_OK !=
     349          100 :       TALER_wallet_deposit_verify (&cdd->amount,
     350              :                                    &dki->fees.deposit,
     351              :                                    h_wire,
     352              :                                    &dcd->h_contract_terms,
     353              :                                    &dcd->wallet_data_hash,
     354              :                                    &cdd->h_age_commitment,
     355              :                                    ech,
     356              :                                    &cdd->h_denom_pub,
     357              :                                    dcd->wallet_timestamp,
     358              :                                    &dcd->merchant_pub,
     359              :                                    dcd->refund_deadline,
     360              :                                    &cdd->coin_pub,
     361              :                                    &cdd->coin_sig))
     362              :   {
     363            0 :     GNUNET_break_op (0);
     364            0 :     TALER_LOG_WARNING ("Invalid coin signature on /deposit request!\n");
     365            0 :     TALER_LOG_DEBUG ("... amount_with_fee was %s\n",
     366              :                      TALER_amount2s (&cdd->amount));
     367            0 :     TALER_LOG_DEBUG ("... deposit_fee was %s\n",
     368              :                      TALER_amount2s (&dki->fees.deposit));
     369            0 :     return GNUNET_SYSERR;
     370              :   }
     371              : 
     372              :   /* check coin signature */
     373              :   {
     374          100 :     struct TALER_CoinPublicInfo coin_info = {
     375              :       .coin_pub = cdd->coin_pub,
     376              :       .denom_pub_hash = cdd->h_denom_pub,
     377              :       .denom_sig = cdd->denom_sig,
     378              :       .h_age_commitment = cdd->h_age_commitment,
     379              :     };
     380              : 
     381          100 :     if (GNUNET_YES !=
     382          100 :         TALER_test_coin_valid (&coin_info,
     383              :                                &dki->key))
     384              :     {
     385            0 :       GNUNET_break_op (0);
     386            0 :       TALER_LOG_WARNING ("Invalid coin passed for /deposit\n");
     387            0 :       return GNUNET_SYSERR;
     388              :     }
     389              :   }
     390              : 
     391              :   /* Check coin does make a contribution */
     392          100 :   if (0 < TALER_amount_cmp (&dki->fees.deposit,
     393              :                             &cdd->amount))
     394              :   {
     395            0 :     GNUNET_break_op (0);
     396            0 :     TALER_LOG_WARNING ("Deposit amount smaller than fee\n");
     397            0 :     return GNUNET_SYSERR;
     398              :   }
     399          100 :   return GNUNET_OK;
     400              : }
     401              : 
     402              : 
     403              : /**
     404              :  * Parse account restriction in @a jrest into @a rest.
     405              :  *
     406              :  * @param jresta array of account restrictions in JSON
     407              :  * @param[out] resta_len set to length of @a resta
     408              :  * @param[out] resta account restriction array to set
     409              :  * @return #GNUNET_OK on success
     410              :  */
     411              : static enum GNUNET_GenericReturnValue
     412           92 : parse_restrictions (const json_t *jresta,
     413              :                     unsigned int *resta_len,
     414              :                     struct TALER_EXCHANGE_AccountRestriction **resta)
     415              : {
     416              :   size_t alen;
     417              : 
     418           92 :   if (! json_is_array (jresta))
     419              :   {
     420            0 :     GNUNET_break_op (0);
     421            0 :     return GNUNET_SYSERR;
     422              :   }
     423           92 :   alen = json_array_size (jresta);
     424           92 :   if (0 == alen)
     425              :   {
     426              :     /* no restrictions, perfectly OK */
     427           92 :     *resta = NULL;
     428           92 :     return GNUNET_OK;
     429              :   }
     430            0 :   *resta_len = (unsigned int) alen;
     431            0 :   GNUNET_assert (alen == *resta_len);
     432            0 :   *resta = GNUNET_new_array (*resta_len,
     433              :                              struct TALER_EXCHANGE_AccountRestriction);
     434            0 :   for (unsigned int i = 0; i<*resta_len; i++)
     435              :   {
     436            0 :     const json_t *jr = json_array_get (jresta,
     437              :                                        i);
     438            0 :     struct TALER_EXCHANGE_AccountRestriction *ar = &(*resta)[i];
     439            0 :     const char *type = json_string_value (json_object_get (jr,
     440              :                                                            "type"));
     441              : 
     442            0 :     if (NULL == type)
     443              :     {
     444            0 :       GNUNET_break (0);
     445            0 :       goto fail;
     446              :     }
     447            0 :     if (0 == strcmp (type,
     448              :                      "deny"))
     449              :     {
     450            0 :       ar->type = TALER_EXCHANGE_AR_DENY;
     451            0 :       continue;
     452              :     }
     453            0 :     if (0 == strcmp (type,
     454              :                      "regex"))
     455            0 :     {
     456              :       const char *regex;
     457              :       const char *hint;
     458              :       struct GNUNET_JSON_Specification spec[] = {
     459            0 :         GNUNET_JSON_spec_string (
     460              :           "payto_regex",
     461              :           &regex),
     462            0 :         GNUNET_JSON_spec_string (
     463              :           "human_hint",
     464              :           &hint),
     465            0 :         GNUNET_JSON_spec_mark_optional (
     466              :           GNUNET_JSON_spec_json (
     467              :             "human_hint_i18n",
     468              :             &ar->details.regex.human_hint_i18n),
     469              :           NULL),
     470            0 :         GNUNET_JSON_spec_end ()
     471              :       };
     472              : 
     473            0 :       if (GNUNET_OK !=
     474            0 :           GNUNET_JSON_parse (jr,
     475              :                              spec,
     476              :                              NULL, NULL))
     477              :       {
     478              :         /* bogus reply */
     479            0 :         GNUNET_break_op (0);
     480            0 :         goto fail;
     481              :       }
     482            0 :       ar->type = TALER_EXCHANGE_AR_REGEX;
     483            0 :       ar->details.regex.posix_egrep = GNUNET_strdup (regex);
     484            0 :       ar->details.regex.human_hint = GNUNET_strdup (hint);
     485            0 :       continue;
     486              :     }
     487              :     /* unsupported type */
     488            0 :     GNUNET_break (0);
     489            0 :     return GNUNET_SYSERR;
     490              :   }
     491            0 :   return GNUNET_OK;
     492            0 : fail:
     493            0 :   GNUNET_free (*resta);
     494            0 :   *resta_len = 0;
     495            0 :   return GNUNET_SYSERR;
     496              : }
     497              : 
     498              : 
     499              : enum GNUNET_GenericReturnValue
     500           42 : TALER_EXCHANGE_parse_accounts (
     501              :   const struct TALER_MasterPublicKeyP *master_pub,
     502              :   const json_t *accounts,
     503              :   unsigned int was_length,
     504              :   struct TALER_EXCHANGE_WireAccount was[static was_length])
     505           42 : {
     506           42 :   memset (was,
     507              :           0,
     508              :           sizeof (struct TALER_EXCHANGE_WireAccount) * was_length);
     509           42 :   GNUNET_assert (was_length ==
     510              :                  json_array_size (accounts));
     511           42 :   for (unsigned int i = 0;
     512           88 :        i<was_length;
     513           46 :        i++)
     514              :   {
     515           46 :     struct TALER_EXCHANGE_WireAccount *wa = &was[i];
     516              :     struct TALER_FullPayto payto_uri;
     517           46 :     const char *conversion_url = NULL;
     518           46 :     const char *open_banking_gateway = NULL;
     519           46 :     const char *wire_transfer_gateway = NULL;
     520           46 :     const char *bank_label = NULL;
     521           46 :     int64_t priority = 0;
     522              :     const json_t *credit_restrictions;
     523              :     const json_t *debit_restrictions;
     524              :     struct GNUNET_JSON_Specification spec_account[] = {
     525           46 :       TALER_JSON_spec_full_payto_uri ("payto_uri",
     526              :                                       &payto_uri),
     527           46 :       GNUNET_JSON_spec_mark_optional (
     528              :         TALER_JSON_spec_web_url ("conversion_url",
     529              :                                  &conversion_url),
     530              :         NULL),
     531           46 :       GNUNET_JSON_spec_mark_optional (
     532              :         GNUNET_JSON_spec_string ("open_banking_gateway",
     533              :                                  &open_banking_gateway),
     534              :         NULL),
     535           46 :       GNUNET_JSON_spec_mark_optional (
     536              :         GNUNET_JSON_spec_string ("wire_transfer_gateway",
     537              :                                  &wire_transfer_gateway),
     538              :         NULL),
     539           46 :       GNUNET_JSON_spec_mark_optional (
     540              :         GNUNET_JSON_spec_int64 ("priority",
     541              :                                 &priority),
     542              :         NULL),
     543           46 :       GNUNET_JSON_spec_mark_optional (
     544              :         GNUNET_JSON_spec_string ("bank_label",
     545              :                                  &bank_label),
     546              :         NULL),
     547           46 :       GNUNET_JSON_spec_array_const ("credit_restrictions",
     548              :                                     &credit_restrictions),
     549           46 :       GNUNET_JSON_spec_array_const ("debit_restrictions",
     550              :                                     &debit_restrictions),
     551           46 :       GNUNET_JSON_spec_fixed_auto ("master_sig",
     552              :                                    &wa->master_sig),
     553           46 :       GNUNET_JSON_spec_end ()
     554              :     };
     555              :     json_t *account;
     556              : 
     557           46 :     account = json_array_get (accounts,
     558              :                               i);
     559           46 :     if (GNUNET_OK !=
     560           46 :         GNUNET_JSON_parse (account,
     561              :                            spec_account,
     562              :                            NULL, NULL))
     563              :     {
     564              :       /* bogus reply */
     565            0 :       GNUNET_break_op (0);
     566            0 :       return GNUNET_SYSERR;
     567              :     }
     568           46 :     if ( (NULL != master_pub) &&
     569           92 :          (! ( ( (NULL == open_banking_gateway) &&
     570           92 :                 (NULL == wire_transfer_gateway) &&
     571              :                 (GNUNET_OK ==
     572           46 :                  TALER_exchange_wire_signature_check32 (
     573              :                    payto_uri,
     574              :                    conversion_url,
     575              :                    debit_restrictions,
     576              :                    credit_restrictions,
     577              :                    master_pub,
     578           46 :                    &wa->master_sig)) ) ||
     579              :               (GNUNET_OK ==
     580           46 :                TALER_exchange_wire_signature_check (
     581              :                  payto_uri,
     582              :                  conversion_url,
     583              :                  open_banking_gateway,
     584              :                  wire_transfer_gateway,
     585              :                  debit_restrictions,
     586              :                  credit_restrictions,
     587              :                  master_pub,
     588           46 :                  &wa->master_sig)) ) ) )
     589              :     {
     590              :       /* bogus reply */
     591            0 :       GNUNET_break_op (0);
     592            0 :       return GNUNET_SYSERR;
     593              :     }
     594           46 :     if ( (GNUNET_OK !=
     595           46 :           parse_restrictions (credit_restrictions,
     596              :                               &wa->credit_restrictions_length,
     597           46 :                               &wa->credit_restrictions)) ||
     598              :          (GNUNET_OK !=
     599           46 :           parse_restrictions (debit_restrictions,
     600              :                               &wa->debit_restrictions_length,
     601              :                               &wa->debit_restrictions)) )
     602              :     {
     603              :       /* bogus reply */
     604            0 :       GNUNET_break_op (0);
     605            0 :       return GNUNET_SYSERR;
     606              :     }
     607              :     wa->fpayto_uri.full_payto
     608           46 :       = GNUNET_strdup (payto_uri.full_payto);
     609           46 :     wa->priority = priority;
     610           46 :     if (NULL != conversion_url)
     611            0 :       wa->conversion_url = GNUNET_strdup (conversion_url);
     612           46 :     if (NULL != open_banking_gateway)
     613            0 :       wa->open_banking_gateway = GNUNET_strdup (open_banking_gateway);
     614           46 :     if (NULL != wire_transfer_gateway)
     615            0 :       wa->wire_transfer_gateway = GNUNET_strdup (wire_transfer_gateway);
     616           46 :     if (NULL != bank_label)
     617            4 :       wa->bank_label = GNUNET_strdup (bank_label);
     618              :   }       /* end 'for all accounts */
     619           42 :   return GNUNET_OK;
     620              : }
     621              : 
     622              : 
     623              : /**
     624              :  * Free array of account restrictions.
     625              :  *
     626              :  * @param ar_len length of @a ar
     627              :  * @param[in] ar array to free contents of (but not @a ar itself)
     628              :  */
     629              : static void
     630           92 : free_restrictions (unsigned int ar_len,
     631              :                    struct TALER_EXCHANGE_AccountRestriction ar[static ar_len])
     632           92 : {
     633           92 :   for (unsigned int i = 0; i<ar_len; i++)
     634              :   {
     635            0 :     struct TALER_EXCHANGE_AccountRestriction *a = &ar[i];
     636            0 :     switch (a->type)
     637              :     {
     638            0 :     case TALER_EXCHANGE_AR_INVALID:
     639            0 :       GNUNET_break (0);
     640            0 :       break;
     641            0 :     case TALER_EXCHANGE_AR_DENY:
     642            0 :       break;
     643            0 :     case TALER_EXCHANGE_AR_REGEX:
     644            0 :       GNUNET_free (ar->details.regex.posix_egrep);
     645            0 :       GNUNET_free (ar->details.regex.human_hint);
     646            0 :       json_decref (ar->details.regex.human_hint_i18n);
     647            0 :       break;
     648              :     }
     649              :   }
     650           92 : }
     651              : 
     652              : 
     653              : void
     654           42 : TALER_EXCHANGE_free_accounts (
     655              :   unsigned int was_len,
     656              :   struct TALER_EXCHANGE_WireAccount was[static was_len])
     657           42 : {
     658           88 :   for (unsigned int i = 0; i<was_len; i++)
     659              :   {
     660           46 :     struct TALER_EXCHANGE_WireAccount *wa = &was[i];
     661              : 
     662           46 :     GNUNET_free (wa->fpayto_uri.full_payto);
     663           46 :     GNUNET_free (wa->conversion_url);
     664           46 :     GNUNET_free (wa->open_banking_gateway);
     665           46 :     GNUNET_free (wa->wire_transfer_gateway);
     666           46 :     GNUNET_free (wa->bank_label);
     667           46 :     free_restrictions (wa->credit_restrictions_length,
     668              :                        wa->credit_restrictions);
     669           46 :     GNUNET_array_grow (wa->credit_restrictions,
     670              :                        wa->credit_restrictions_length,
     671              :                        0);
     672           46 :     free_restrictions (wa->debit_restrictions_length,
     673              :                        wa->debit_restrictions);
     674           46 :     GNUNET_array_grow (wa->debit_restrictions,
     675              :                        wa->debit_restrictions_length,
     676              :                        0);
     677              :   }
     678           42 : }
     679              : 
     680              : 
     681              : enum GNUNET_GenericReturnValue
     682            0 : TALER_EXCHANGE_keys_test_account_allowed (
     683              :   const struct TALER_EXCHANGE_Keys *keys,
     684              :   bool check_credit,
     685              :   const struct TALER_NormalizedPayto payto_uri)
     686              : {
     687              :   /* For all accounts of the exchange */
     688            0 :   for (unsigned int i = 0; i<keys->accounts_len; i++)
     689              :   {
     690            0 :     const struct TALER_EXCHANGE_WireAccount *account
     691            0 :       = &keys->accounts[i];
     692              : 
     693              :     /* KYC auth transfers are never supported with conversion */
     694            0 :     if (NULL != account->conversion_url)
     695            0 :       continue;
     696              :     /* filter by source account by credit_restrictions */
     697            0 :     if (GNUNET_YES !=
     698            0 :         TALER_EXCHANGE_test_account_allowed (account,
     699              :                                              check_credit,
     700              :                                              payto_uri))
     701            0 :       continue;
     702              :     /* exchange account is allowed, add it */
     703            0 :     return true;
     704              :   }
     705            0 :   return false;
     706              : }
     707              : 
     708              : 
     709              : /**
     710              :  * We received an #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS response code.
     711              :  * Parse the JSON response and initialize the @a uflr object.
     712              :  *
     713              :  * @param[out] uflr data structure to initialize
     714              :  * @param j JSON response to parse
     715              :  * @return #GNUNET_OK on success
     716              :  */
     717              : enum GNUNET_GenericReturnValue
     718           18 : TALER_EXCHANGE_parse_451 (struct TALER_EXCHANGE_KycNeededRedirect *uflr,
     719              :                           const json_t *j)
     720              : {
     721              :   struct GNUNET_JSON_Specification spec[] = {
     722           18 :     GNUNET_JSON_spec_fixed_auto (
     723              :       "h_payto",
     724              :       &uflr->h_payto),
     725           18 :     GNUNET_JSON_spec_uint64 (
     726              :       "requirement_row",
     727              :       &uflr->requirement_row),
     728           18 :     GNUNET_JSON_spec_mark_optional (
     729           18 :       GNUNET_JSON_spec_fixed_auto (
     730              :         "account_pub",
     731              :         &uflr->account_pub),
     732              :       NULL),
     733           18 :     GNUNET_JSON_spec_mark_optional (
     734              :       GNUNET_JSON_spec_bool (
     735              :         "bad_kyc_auth",
     736              :         &uflr->bad_kyc_auth),
     737              :       NULL),
     738           18 :     GNUNET_JSON_spec_end ()
     739              :   };
     740              : 
     741           18 :   if (GNUNET_OK !=
     742           18 :       GNUNET_JSON_parse (j,
     743              :                          spec,
     744              :                          NULL,
     745              :                          NULL))
     746              :   {
     747            0 :     GNUNET_break_op (0);
     748            0 :     return GNUNET_SYSERR;
     749              :   }
     750           18 :   return GNUNET_OK;
     751              : }
     752              : 
     753              : 
     754              : /* end of exchange_api_common.c */
        

Generated by: LCOV version 2.0-1