LCOV - code coverage report
Current view: top level - lib - exchange_api_common.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 33.8 % 260 88
Test Date: 2025-12-28 14:06:02 Functions: 53.8 % 13 7

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

Generated by: LCOV version 2.0-1