exchange_api_handle.c (76270B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2014-2023 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it 6 under the terms of the GNU General Public License as published 7 by the Free Software Foundation; either version 3, or (at your 8 option) any later version. 9 10 TALER is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public 16 License along with TALER; see the file COPYING. If not, see 17 <http://www.gnu.org/licenses/> 18 */ 19 20 /** 21 * @file lib/exchange_api_handle.c 22 * @brief Implementation of the "handle" component of the exchange's HTTP API 23 * @author Sree Harsha Totakura <sreeharsha@totakura.in> 24 * @author Christian Grothoff 25 */ 26 #include "taler/platform.h" 27 #include <microhttpd.h> 28 #include <gnunet/gnunet_curl_lib.h> 29 #include "taler/taler_json_lib.h" 30 #include "taler/taler_exchange_service.h" 31 #include "taler/taler_auditor_service.h" 32 #include "taler/taler_signatures.h" 33 #include "taler/taler_extensions.h" 34 #include "exchange_api_handle.h" 35 #include "exchange_api_curl_defaults.h" 36 #include "taler/backoff.h" 37 #include "taler/taler_curl_lib.h" 38 39 /** 40 * Which version of the Taler protocol is implemented 41 * by this library? Used to determine compatibility. 42 */ 43 #define EXCHANGE_PROTOCOL_CURRENT 33 44 45 /** 46 * How many versions are we backwards compatible with? 47 */ 48 #define EXCHANGE_PROTOCOL_AGE 7 49 50 /** 51 * Set to 1 for extra debug logging. 52 */ 53 #define DEBUG 0 54 55 /** 56 * Current version for (local) JSON serialization of persisted 57 * /keys data. 58 */ 59 #define EXCHANGE_SERIALIZATION_FORMAT_VERSION 0 60 61 /** 62 * How far off do we allow key lifetimes to be? 63 */ 64 #define LIFETIME_TOLERANCE GNUNET_TIME_UNIT_HOURS 65 66 /** 67 * Element in the `struct SignatureContext` array. 68 */ 69 struct SignatureElement 70 { 71 72 /** 73 * Offset of the denomination in the group array, 74 * for sorting (2nd rank, ascending). 75 */ 76 unsigned int offset; 77 78 /** 79 * Offset of the group in the denominations array, 80 * for sorting (2nd rank, ascending). 81 */ 82 unsigned int group_offset; 83 84 /** 85 * Pointer to actual master signature to hash over. 86 */ 87 struct TALER_MasterSignatureP master_sig; 88 }; 89 90 /** 91 * Context for collecting the array of master signatures 92 * needed to verify the exchange_sig online signature. 93 */ 94 struct SignatureContext 95 { 96 /** 97 * Array of signatures to hash over. 98 */ 99 struct SignatureElement *elements; 100 101 /** 102 * Write offset in the @e elements array. 103 */ 104 unsigned int elements_pos; 105 106 /** 107 * Allocated space for @e elements. 108 */ 109 unsigned int elements_size; 110 }; 111 112 113 /** 114 * Determine order to sort two elements by before 115 * we hash the master signatures. Used for 116 * sorting with qsort(). 117 * 118 * @param a pointer to a `struct SignatureElement` 119 * @param b pointer to a `struct SignatureElement` 120 * @return 0 if equal, -1 if a < b, 1 if a > b. 121 */ 122 static int 123 signature_context_sort_cb (const void *a, 124 const void *b) 125 { 126 const struct SignatureElement *sa = a; 127 const struct SignatureElement *sb = b; 128 129 if (sa->group_offset < sb->group_offset) 130 return -1; 131 if (sa->group_offset > sb->group_offset) 132 return 1; 133 if (sa->offset < sb->offset) 134 return -1; 135 if (sa->offset > sb->offset) 136 return 1; 137 /* We should never have two disjoint elements 138 with same time and offset */ 139 GNUNET_assert (sa == sb); 140 return 0; 141 } 142 143 144 /** 145 * Append a @a master_sig to the @a sig_ctx using the 146 * given attributes for (later) sorting. 147 * 148 * @param[in,out] sig_ctx signature context to update 149 * @param group_offset offset for the group 150 * @param offset offset for the entry 151 * @param master_sig master signature for the entry 152 */ 153 static void 154 append_signature (struct SignatureContext *sig_ctx, 155 unsigned int group_offset, 156 unsigned int offset, 157 const struct TALER_MasterSignatureP *master_sig) 158 { 159 struct SignatureElement *element; 160 unsigned int new_size; 161 162 if (sig_ctx->elements_pos == sig_ctx->elements_size) 163 { 164 if (0 == sig_ctx->elements_size) 165 new_size = 1024; 166 else 167 new_size = sig_ctx->elements_size * 2; 168 GNUNET_array_grow (sig_ctx->elements, 169 sig_ctx->elements_size, 170 new_size); 171 } 172 element = &sig_ctx->elements[sig_ctx->elements_pos++]; 173 element->offset = offset; 174 element->group_offset = group_offset; 175 element->master_sig = *master_sig; 176 } 177 178 179 /** 180 * Frees @a wfm array. 181 * 182 * @param wfm fee array to release 183 * @param wfm_len length of the @a wfm array 184 */ 185 static void 186 free_fees (struct TALER_EXCHANGE_WireFeesByMethod *wfm, 187 unsigned int wfm_len) 188 { 189 for (unsigned int i = 0; i<wfm_len; i++) 190 { 191 struct TALER_EXCHANGE_WireFeesByMethod *wfmi = &wfm[i]; 192 193 while (NULL != wfmi->fees_head) 194 { 195 struct TALER_EXCHANGE_WireAggregateFees *fe 196 = wfmi->fees_head; 197 198 wfmi->fees_head = fe->next; 199 GNUNET_free (fe); 200 } 201 GNUNET_free (wfmi->method); 202 } 203 GNUNET_free (wfm); 204 } 205 206 207 /** 208 * Parse wire @a fees and return array. 209 * 210 * @param master_pub master public key to use to check signatures 211 * @param currency currency amounts are expected in 212 * @param fees json AggregateTransferFee to parse 213 * @param[out] fees_len set to length of returned array 214 * @return NULL on error 215 */ 216 static struct TALER_EXCHANGE_WireFeesByMethod * 217 parse_fees (const struct TALER_MasterPublicKeyP *master_pub, 218 const char *currency, 219 const json_t *fees, 220 unsigned int *fees_len) 221 { 222 struct TALER_EXCHANGE_WireFeesByMethod *fbm; 223 size_t fbml = json_object_size (fees); 224 unsigned int i = 0; 225 const char *key; 226 const json_t *fee_array; 227 228 if (UINT_MAX < fbml) 229 { 230 GNUNET_break (0); 231 return NULL; 232 } 233 fbm = GNUNET_new_array (fbml, 234 struct TALER_EXCHANGE_WireFeesByMethod); 235 *fees_len = (unsigned int) fbml; 236 json_object_foreach ((json_t *) fees, key, fee_array) { 237 struct TALER_EXCHANGE_WireFeesByMethod *fe = &fbm[i++]; 238 size_t idx; 239 json_t *fee; 240 241 fe->method = GNUNET_strdup (key); 242 fe->fees_head = NULL; 243 json_array_foreach (fee_array, idx, fee) 244 { 245 struct TALER_EXCHANGE_WireAggregateFees *wa 246 = GNUNET_new (struct TALER_EXCHANGE_WireAggregateFees); 247 struct GNUNET_JSON_Specification spec[] = { 248 GNUNET_JSON_spec_fixed_auto ("sig", 249 &wa->master_sig), 250 TALER_JSON_spec_amount ("wire_fee", 251 currency, 252 &wa->fees.wire), 253 TALER_JSON_spec_amount ("closing_fee", 254 currency, 255 &wa->fees.closing), 256 GNUNET_JSON_spec_timestamp ("start_date", 257 &wa->start_date), 258 GNUNET_JSON_spec_timestamp ("end_date", 259 &wa->end_date), 260 GNUNET_JSON_spec_end () 261 }; 262 263 wa->next = fe->fees_head; 264 fe->fees_head = wa; 265 if (GNUNET_OK != 266 GNUNET_JSON_parse (fee, 267 spec, 268 NULL, 269 NULL)) 270 { 271 GNUNET_break_op (0); 272 free_fees (fbm, 273 i); 274 return NULL; 275 } 276 if (GNUNET_OK != 277 TALER_exchange_offline_wire_fee_verify ( 278 key, 279 wa->start_date, 280 wa->end_date, 281 &wa->fees, 282 master_pub, 283 &wa->master_sig)) 284 { 285 GNUNET_break_op (0); 286 free_fees (fbm, 287 i); 288 return NULL; 289 } 290 } /* for all fees over time */ 291 } /* for all methods */ 292 GNUNET_assert (i == fbml); 293 return fbm; 294 } 295 296 297 void 298 TALER_EXCHANGE_get_auditors_for_dc_ ( 299 struct TALER_EXCHANGE_Keys *keys, 300 TEAH_AuditorCallback ac, 301 void *ac_cls) 302 { 303 if (0 == keys->num_auditors) 304 { 305 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 306 "No auditor available. Not submitting deposit confirmations.\n") 307 ; 308 return; 309 } 310 for (unsigned int i = 0; i<keys->num_auditors; i++) 311 { 312 const struct TALER_EXCHANGE_AuditorInformation *auditor 313 = &keys->auditors[i]; 314 315 ac (ac_cls, 316 auditor->auditor_url, 317 &auditor->auditor_pub); 318 } 319 } 320 321 322 #define EXITIF(cond) \ 323 do { \ 324 if (cond) { GNUNET_break (0); goto EXITIF_exit; } \ 325 } while (0) 326 327 328 /** 329 * Parse a exchange's signing key encoded in JSON. 330 * 331 * @param[out] sign_key where to return the result 332 * @param check_sigs should we check signatures? 333 * @param sign_key_obj json to parse 334 * @param master_key master key to use to verify signature 335 * @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if the signature is 336 * invalid or the @a sign_key_obj is malformed. 337 */ 338 static enum GNUNET_GenericReturnValue 339 parse_json_signkey (struct TALER_EXCHANGE_SigningPublicKey *sign_key, 340 bool check_sigs, 341 const json_t *sign_key_obj, 342 const struct TALER_MasterPublicKeyP *master_key) 343 { 344 struct GNUNET_JSON_Specification spec[] = { 345 GNUNET_JSON_spec_fixed_auto ("master_sig", 346 &sign_key->master_sig), 347 GNUNET_JSON_spec_fixed_auto ("key", 348 &sign_key->key), 349 GNUNET_JSON_spec_timestamp ("stamp_start", 350 &sign_key->valid_from), 351 GNUNET_JSON_spec_timestamp ("stamp_expire", 352 &sign_key->valid_until), 353 GNUNET_JSON_spec_timestamp ("stamp_end", 354 &sign_key->valid_legal), 355 GNUNET_JSON_spec_end () 356 }; 357 358 if (GNUNET_OK != 359 GNUNET_JSON_parse (sign_key_obj, 360 spec, 361 NULL, NULL)) 362 { 363 GNUNET_break_op (0); 364 return GNUNET_SYSERR; 365 } 366 if (! check_sigs) 367 return GNUNET_OK; 368 if (GNUNET_OK != 369 TALER_exchange_offline_signkey_validity_verify ( 370 &sign_key->key, 371 sign_key->valid_from, 372 sign_key->valid_until, 373 sign_key->valid_legal, 374 master_key, 375 &sign_key->master_sig)) 376 { 377 GNUNET_break_op (0); 378 return GNUNET_SYSERR; 379 } 380 return GNUNET_OK; 381 } 382 383 384 /** 385 * Parse a exchange's denomination key encoded in JSON partially. 386 * 387 * Only the values for master_sig, timestamps and the cipher-specific public 388 * key are parsed. All other fields (fees, age_mask, value) MUST have been set 389 * prior to calling this function, otherwise the signature verification 390 * performed within this function will fail. 391 * 392 * @param[out] denom_key where to return the result 393 * @param cipher cipher type to parse 394 * @param check_sigs should we check signatures? 395 * @param denom_key_obj json to parse 396 * @param master_key master key to use to verify signature 397 * @param group_offset offset for the group 398 * @param index index of this denomination key in the group 399 * @param sig_ctx where to write details about encountered 400 * master signatures, NULL if not used 401 * @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if the signature is 402 * invalid or the json malformed. 403 */ 404 static enum GNUNET_GenericReturnValue 405 parse_json_denomkey_partially ( 406 struct TALER_EXCHANGE_DenomPublicKey *denom_key, 407 enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher, 408 bool check_sigs, 409 const json_t *denom_key_obj, 410 struct TALER_MasterPublicKeyP *master_key, 411 unsigned int group_offset, 412 unsigned int index, 413 struct SignatureContext *sig_ctx) 414 { 415 struct GNUNET_JSON_Specification spec[] = { 416 GNUNET_JSON_spec_fixed_auto ("master_sig", 417 &denom_key->master_sig), 418 GNUNET_JSON_spec_timestamp ("stamp_expire_deposit", 419 &denom_key->expire_deposit), 420 GNUNET_JSON_spec_timestamp ("stamp_expire_withdraw", 421 &denom_key->withdraw_valid_until), 422 GNUNET_JSON_spec_timestamp ("stamp_start", 423 &denom_key->valid_from), 424 GNUNET_JSON_spec_timestamp ("stamp_expire_legal", 425 &denom_key->expire_legal), 426 GNUNET_JSON_spec_mark_optional ( 427 GNUNET_JSON_spec_bool ("lost", 428 &denom_key->lost), 429 NULL), 430 TALER_JSON_spec_denom_pub_cipher (NULL, 431 cipher, 432 &denom_key->key), 433 GNUNET_JSON_spec_end () 434 }; 435 436 if (GNUNET_OK != 437 GNUNET_JSON_parse (denom_key_obj, 438 spec, 439 NULL, NULL)) 440 { 441 GNUNET_break_op (0); 442 return GNUNET_SYSERR; 443 } 444 TALER_denom_pub_hash (&denom_key->key, 445 &denom_key->h_key); 446 if (NULL != sig_ctx) 447 append_signature (sig_ctx, 448 group_offset, 449 index, 450 &denom_key->master_sig); 451 if (! check_sigs) 452 return GNUNET_OK; 453 EXITIF (GNUNET_SYSERR == 454 TALER_exchange_offline_denom_validity_verify ( 455 &denom_key->h_key, 456 denom_key->valid_from, 457 denom_key->withdraw_valid_until, 458 denom_key->expire_deposit, 459 denom_key->expire_legal, 460 &denom_key->value, 461 &denom_key->fees, 462 master_key, 463 &denom_key->master_sig)); 464 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 465 "Learned denomination key %s\n", 466 GNUNET_h2s (&denom_key->h_key.hash)); 467 return GNUNET_OK; 468 EXITIF_exit: 469 GNUNET_JSON_parse_free (spec); 470 /* invalidate denom_key, just to be sure */ 471 memset (denom_key, 472 0, 473 sizeof (*denom_key)); 474 return GNUNET_SYSERR; 475 } 476 477 478 /** 479 * Parse a exchange's auditor information encoded in JSON. 480 * 481 * @param[out] auditor where to return the result 482 * @param check_sigs should we check signatures 483 * @param auditor_obj json to parse 484 * @param key_data information about denomination keys 485 * @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if the signature is 486 * invalid or the json malformed. 487 */ 488 static enum GNUNET_GenericReturnValue 489 parse_json_auditor (struct TALER_EXCHANGE_AuditorInformation *auditor, 490 bool check_sigs, 491 const json_t *auditor_obj, 492 const struct TALER_EXCHANGE_Keys *key_data) 493 { 494 const json_t *keys; 495 json_t *key; 496 size_t off; 497 size_t pos; 498 const char *auditor_url; 499 const char *auditor_name; 500 struct GNUNET_JSON_Specification spec[] = { 501 GNUNET_JSON_spec_fixed_auto ("auditor_pub", 502 &auditor->auditor_pub), 503 TALER_JSON_spec_web_url ("auditor_url", 504 &auditor_url), 505 GNUNET_JSON_spec_string ("auditor_name", 506 &auditor_name), 507 GNUNET_JSON_spec_array_const ("denomination_keys", 508 &keys), 509 GNUNET_JSON_spec_end () 510 }; 511 512 if (GNUNET_OK != 513 GNUNET_JSON_parse (auditor_obj, 514 spec, 515 NULL, NULL)) 516 { 517 GNUNET_break_op (0); 518 #if DEBUG 519 json_dumpf (auditor_obj, 520 stderr, 521 JSON_INDENT (2)); 522 #endif 523 return GNUNET_SYSERR; 524 } 525 auditor->auditor_url = GNUNET_strdup (auditor_url); 526 auditor->auditor_name = GNUNET_strdup (auditor_name); 527 auditor->denom_keys 528 = GNUNET_new_array (json_array_size (keys), 529 struct TALER_EXCHANGE_AuditorDenominationInfo); 530 pos = 0; 531 json_array_foreach (keys, off, key) { 532 struct TALER_AuditorSignatureP auditor_sig; 533 struct TALER_DenominationHashP denom_h; 534 const struct TALER_EXCHANGE_DenomPublicKey *dk = NULL; 535 unsigned int dk_off = UINT_MAX; 536 struct GNUNET_JSON_Specification kspec[] = { 537 GNUNET_JSON_spec_fixed_auto ("auditor_sig", 538 &auditor_sig), 539 GNUNET_JSON_spec_fixed_auto ("denom_pub_h", 540 &denom_h), 541 GNUNET_JSON_spec_end () 542 }; 543 544 if (GNUNET_OK != 545 GNUNET_JSON_parse (key, 546 kspec, 547 NULL, NULL)) 548 { 549 GNUNET_break_op (0); 550 continue; 551 } 552 for (unsigned int j = 0; j<key_data->num_denom_keys; j++) 553 { 554 if (0 == GNUNET_memcmp (&denom_h, 555 &key_data->denom_keys[j].h_key)) 556 { 557 dk = &key_data->denom_keys[j]; 558 dk_off = j; 559 break; 560 } 561 } 562 if (NULL == dk) 563 { 564 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 565 "Auditor signed denomination %s, which we do not know. Ignoring signature.\n", 566 GNUNET_h2s (&denom_h.hash)); 567 continue; 568 } 569 if (check_sigs) 570 { 571 if (GNUNET_OK != 572 TALER_auditor_denom_validity_verify ( 573 auditor_url, 574 &dk->h_key, 575 &key_data->master_pub, 576 dk->valid_from, 577 dk->withdraw_valid_until, 578 dk->expire_deposit, 579 dk->expire_legal, 580 &dk->value, 581 &dk->fees, 582 &auditor->auditor_pub, 583 &auditor_sig)) 584 { 585 GNUNET_break_op (0); 586 return GNUNET_SYSERR; 587 } 588 } 589 auditor->denom_keys[pos].denom_key_offset = dk_off; 590 auditor->denom_keys[pos].auditor_sig = auditor_sig; 591 pos++; 592 } 593 if (pos > UINT_MAX) 594 { 595 GNUNET_break (0); 596 return GNUNET_SYSERR; 597 } 598 auditor->num_denom_keys = (unsigned int) pos; 599 return GNUNET_OK; 600 } 601 602 603 /** 604 * Parse a exchange's global fee information encoded in JSON. 605 * 606 * @param[out] gf where to return the result 607 * @param check_sigs should we check signatures 608 * @param fee_obj json to parse 609 * @param key_data already parsed information about the exchange 610 * @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if the signature is 611 * invalid or the json malformed. 612 */ 613 static enum GNUNET_GenericReturnValue 614 parse_global_fee (struct TALER_EXCHANGE_GlobalFee *gf, 615 bool check_sigs, 616 const json_t *fee_obj, 617 const struct TALER_EXCHANGE_Keys *key_data) 618 { 619 struct GNUNET_JSON_Specification spec[] = { 620 GNUNET_JSON_spec_timestamp ("start_date", 621 &gf->start_date), 622 GNUNET_JSON_spec_timestamp ("end_date", 623 &gf->end_date), 624 GNUNET_JSON_spec_relative_time ("purse_timeout", 625 &gf->purse_timeout), 626 GNUNET_JSON_spec_relative_time ("history_expiration", 627 &gf->history_expiration), 628 GNUNET_JSON_spec_uint32 ("purse_account_limit", 629 &gf->purse_account_limit), 630 TALER_JSON_SPEC_GLOBAL_FEES (key_data->currency, 631 &gf->fees), 632 GNUNET_JSON_spec_fixed_auto ("master_sig", 633 &gf->master_sig), 634 GNUNET_JSON_spec_end () 635 }; 636 637 if (GNUNET_OK != 638 GNUNET_JSON_parse (fee_obj, 639 spec, 640 NULL, NULL)) 641 { 642 GNUNET_break_op (0); 643 #if DEBUG 644 json_dumpf (fee_obj, 645 stderr, 646 JSON_INDENT (2)); 647 #endif 648 return GNUNET_SYSERR; 649 } 650 if (check_sigs) 651 { 652 if (GNUNET_OK != 653 TALER_exchange_offline_global_fee_verify ( 654 gf->start_date, 655 gf->end_date, 656 &gf->fees, 657 gf->purse_timeout, 658 gf->history_expiration, 659 gf->purse_account_limit, 660 &key_data->master_pub, 661 &gf->master_sig)) 662 { 663 GNUNET_break_op (0); 664 GNUNET_JSON_parse_free (spec); 665 return GNUNET_SYSERR; 666 } 667 } 668 GNUNET_JSON_parse_free (spec); 669 return GNUNET_OK; 670 } 671 672 673 /** 674 * Compare two denomination keys. Ignores revocation data. 675 * 676 * @param denom1 first denomination key 677 * @param denom2 second denomination key 678 * @return 0 if the two keys are equal (not necessarily 679 * the same object), non-zero otherwise. 680 */ 681 static unsigned int 682 denoms_cmp (const struct TALER_EXCHANGE_DenomPublicKey *denom1, 683 const struct TALER_EXCHANGE_DenomPublicKey *denom2) 684 { 685 struct TALER_EXCHANGE_DenomPublicKey tmp1; 686 struct TALER_EXCHANGE_DenomPublicKey tmp2; 687 688 if (0 != 689 TALER_denom_pub_cmp (&denom1->key, 690 &denom2->key)) 691 return 1; 692 tmp1 = *denom1; 693 tmp2 = *denom2; 694 tmp1.revoked = false; 695 tmp2.revoked = false; 696 memset (&tmp1.key, 697 0, 698 sizeof (tmp1.key)); 699 memset (&tmp2.key, 700 0, 701 sizeof (tmp2.key)); 702 return GNUNET_memcmp (&tmp1, 703 &tmp2); 704 } 705 706 707 /** 708 * Decode the JSON array in @a hard_limits from the /keys response 709 * and store the data in `hard_limits` array the @a key_data. 710 * 711 * @param[in] hard_limits JSON array to parse 712 * @param[out] key_data where to store the results we decoded 713 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 714 * (malformed JSON) 715 */ 716 static enum GNUNET_GenericReturnValue 717 parse_hard_limits (const json_t *hard_limits, 718 struct TALER_EXCHANGE_Keys *key_data) 719 { 720 json_t *obj; 721 size_t off; 722 723 key_data->hard_limits_length 724 = (unsigned int) json_array_size (hard_limits); 725 if ( ((size_t) key_data->hard_limits_length) 726 != json_array_size (hard_limits)) 727 { 728 GNUNET_break (0); 729 return GNUNET_SYSERR; 730 } 731 key_data->hard_limits 732 = GNUNET_new_array (key_data->hard_limits_length, 733 struct TALER_EXCHANGE_AccountLimit); 734 735 json_array_foreach (hard_limits, off, obj) 736 { 737 struct TALER_EXCHANGE_AccountLimit *al 738 = &key_data->hard_limits[off]; 739 struct GNUNET_JSON_Specification spec[] = { 740 TALER_JSON_spec_kycte ("operation_type", 741 &al->operation_type), 742 TALER_JSON_spec_amount_any ("threshold", 743 &al->threshold), 744 GNUNET_JSON_spec_relative_time ("timeframe", 745 &al->timeframe), 746 GNUNET_JSON_spec_mark_optional ( 747 GNUNET_JSON_spec_bool ("soft_limit", 748 &al->soft_limit), 749 NULL), 750 GNUNET_JSON_spec_end () 751 }; 752 753 if (GNUNET_OK != 754 GNUNET_JSON_parse (obj, 755 spec, 756 NULL, NULL)) 757 { 758 GNUNET_break_op (0); 759 return GNUNET_SYSERR; 760 } 761 } 762 return GNUNET_OK; 763 } 764 765 766 /** 767 * Decode the JSON array in @a zero_limits from the /keys response 768 * and store the data in `zero_limits` array the @a key_data. 769 * 770 * @param[in] zero_limits JSON array to parse 771 * @param[out] key_data where to store the results we decoded 772 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 773 * (malformed JSON) 774 */ 775 static enum GNUNET_GenericReturnValue 776 parse_zero_limits (const json_t *zero_limits, 777 struct TALER_EXCHANGE_Keys *key_data) 778 { 779 json_t *obj; 780 size_t off; 781 782 key_data->zero_limits_length 783 = (unsigned int) json_array_size (zero_limits); 784 if ( ((size_t) key_data->zero_limits_length) 785 != json_array_size (zero_limits)) 786 { 787 GNUNET_break (0); 788 return GNUNET_SYSERR; 789 } 790 key_data->zero_limits 791 = GNUNET_new_array (key_data->zero_limits_length, 792 struct TALER_EXCHANGE_ZeroLimitedOperation); 793 794 json_array_foreach (zero_limits, off, obj) 795 { 796 struct TALER_EXCHANGE_ZeroLimitedOperation *zol 797 = &key_data->zero_limits[off]; 798 struct GNUNET_JSON_Specification spec[] = { 799 TALER_JSON_spec_kycte ("operation_type", 800 &zol->operation_type), 801 GNUNET_JSON_spec_end () 802 }; 803 804 if (GNUNET_OK != 805 GNUNET_JSON_parse (obj, 806 spec, 807 NULL, NULL)) 808 { 809 GNUNET_break_op (0); 810 return GNUNET_SYSERR; 811 } 812 } 813 return GNUNET_OK; 814 } 815 816 817 /** 818 * Parse the wads (partner exchange) array from /keys and store the 819 * data in @a key_data. 820 * 821 * @param[in] wads_array JSON array to parse 822 * @param check_sig true if we should verify signatures 823 * @param[out] key_data where to store the results 824 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 825 */ 826 static enum GNUNET_GenericReturnValue 827 parse_wads (const json_t *wads_array, 828 bool check_sig, 829 struct TALER_EXCHANGE_Keys *key_data) 830 { 831 size_t n = json_array_size (wads_array); 832 json_t *wad_obj; 833 size_t index; 834 835 if (n > UINT_MAX) 836 { 837 GNUNET_break (0); 838 return GNUNET_SYSERR; 839 } 840 if (0 == n) 841 return GNUNET_OK; 842 key_data->num_wad_partners = (unsigned int) n; 843 key_data->wad_partners 844 = GNUNET_new_array (n, 845 struct TALER_EXCHANGE_WadPartner); 846 json_array_foreach (wads_array, index, wad_obj) 847 { 848 struct TALER_EXCHANGE_WadPartner *wp 849 = &key_data->wad_partners[index]; 850 const char *partner_base_url; 851 struct GNUNET_JSON_Specification spec[] = { 852 TALER_JSON_spec_web_url ("partner_base_url", 853 &partner_base_url), 854 GNUNET_JSON_spec_fixed_auto ("partner_master_pub", 855 &wp->partner_master_pub), 856 TALER_JSON_spec_amount ("wad_fee", 857 key_data->currency, 858 &wp->wad_fee), 859 GNUNET_JSON_spec_relative_time ("wad_frequency", 860 &wp->wad_frequency), 861 GNUNET_JSON_spec_timestamp ("start_date", 862 &wp->start_date), 863 GNUNET_JSON_spec_timestamp ("end_date", 864 &wp->end_date), 865 GNUNET_JSON_spec_fixed_auto ("master_sig", 866 &wp->master_sig), 867 GNUNET_JSON_spec_end () 868 }; 869 870 if (GNUNET_OK != 871 GNUNET_JSON_parse (wad_obj, 872 spec, 873 NULL, NULL)) 874 { 875 GNUNET_break_op (0); 876 return GNUNET_SYSERR; 877 } 878 wp->partner_base_url = GNUNET_strdup (partner_base_url); 879 if (check_sig && 880 GNUNET_OK != 881 TALER_exchange_offline_partner_details_verify ( 882 &wp->partner_master_pub, 883 wp->start_date, 884 wp->end_date, 885 wp->wad_frequency, 886 &wp->wad_fee, 887 partner_base_url, 888 &key_data->master_pub, 889 &wp->master_sig)) 890 { 891 GNUNET_break_op (0); 892 return GNUNET_SYSERR; 893 } 894 } 895 return GNUNET_OK; 896 } 897 898 899 /** 900 * Decode the JSON in @a resp_obj from the /keys response 901 * and store the data in the @a key_data. 902 * 903 * @param[in] resp_obj JSON object to parse 904 * @param check_sig true if we should check the signature 905 * @param[out] key_data where to store the results we decoded 906 * @param[out] vc where to store version compatibility data 907 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 908 * (malformed JSON) 909 */ 910 enum GNUNET_GenericReturnValue 911 TALER_EXCHANGE_decode_keys_json_ ( 912 const json_t *resp_obj, 913 bool check_sig, 914 struct TALER_EXCHANGE_Keys *key_data, 915 enum TALER_EXCHANGE_VersionCompatibility *vc) 916 { 917 struct TALER_ExchangeSignatureP exchange_sig; 918 struct TALER_ExchangePublicKeyP exchange_pub; 919 const json_t *wblwk = NULL; 920 const json_t *global_fees; 921 const json_t *sign_keys_array; 922 const json_t *denominations_by_group; 923 const json_t *auditors_array; 924 const json_t *recoup_array = NULL; 925 const json_t *manifests = NULL; 926 bool no_extensions = false; 927 bool no_signature = false; 928 const json_t *accounts; 929 const json_t *fees; 930 const json_t *wads; 931 const char *shopping_url = NULL; 932 const char *open_banking_gateway = NULL; 933 const char *wire_transfer_gateway = NULL; 934 const char *bank_compliance_language = NULL; 935 struct SignatureContext sig_ctx = { 0 }; 936 937 if (JSON_OBJECT != json_typeof (resp_obj)) 938 { 939 GNUNET_break_op (0); 940 return GNUNET_SYSERR; 941 } 942 #if DEBUG 943 json_dumpf (resp_obj, 944 stderr, 945 JSON_INDENT (2)); 946 #endif 947 /* check the version first */ 948 { 949 struct TALER_JSON_ProtocolVersion pv; 950 struct GNUNET_JSON_Specification spec[] = { 951 TALER_JSON_spec_version ("version", 952 &pv), 953 GNUNET_JSON_spec_end () 954 }; 955 956 if (GNUNET_OK != 957 GNUNET_JSON_parse (resp_obj, 958 spec, 959 NULL, NULL)) 960 { 961 GNUNET_break_op (0); 962 return GNUNET_SYSERR; 963 } 964 *vc = TALER_EXCHANGE_VC_MATCH; 965 if (EXCHANGE_PROTOCOL_CURRENT < pv.current) 966 { 967 *vc |= TALER_EXCHANGE_VC_NEWER; 968 if (EXCHANGE_PROTOCOL_CURRENT < pv.current - pv.age) 969 *vc |= TALER_EXCHANGE_VC_INCOMPATIBLE; 970 } 971 if (EXCHANGE_PROTOCOL_CURRENT > pv.current) 972 { 973 *vc |= TALER_EXCHANGE_VC_OLDER; 974 if (EXCHANGE_PROTOCOL_CURRENT - EXCHANGE_PROTOCOL_AGE > pv.current) 975 *vc |= TALER_EXCHANGE_VC_INCOMPATIBLE; 976 } 977 } 978 979 { 980 const char *ver; 981 const char *currency; 982 const char *asset_type; 983 struct GNUNET_JSON_Specification mspec[] = { 984 GNUNET_JSON_spec_fixed_auto ( 985 "exchange_sig", 986 &exchange_sig), 987 GNUNET_JSON_spec_fixed_auto ( 988 "exchange_pub", 989 &exchange_pub), 990 GNUNET_JSON_spec_fixed_auto ( 991 "master_public_key", 992 &key_data->master_pub), 993 GNUNET_JSON_spec_array_const ("accounts", 994 &accounts), 995 GNUNET_JSON_spec_object_const ("wire_fees", 996 &fees), 997 GNUNET_JSON_spec_array_const ("wads", 998 &wads), 999 GNUNET_JSON_spec_timestamp ( 1000 "list_issue_date", 1001 &key_data->list_issue_date), 1002 GNUNET_JSON_spec_relative_time ( 1003 "reserve_closing_delay", 1004 &key_data->reserve_closing_delay), 1005 GNUNET_JSON_spec_string ( 1006 "currency", 1007 ¤cy), 1008 GNUNET_JSON_spec_string ( 1009 "asset_type", 1010 &asset_type), 1011 GNUNET_JSON_spec_array_const ( 1012 "global_fees", 1013 &global_fees), 1014 GNUNET_JSON_spec_array_const ( 1015 "signkeys", 1016 &sign_keys_array), 1017 GNUNET_JSON_spec_array_const ( 1018 "denominations", 1019 &denominations_by_group), 1020 GNUNET_JSON_spec_mark_optional ( 1021 GNUNET_JSON_spec_array_const ( 1022 "recoup", 1023 &recoup_array), 1024 NULL), 1025 GNUNET_JSON_spec_array_const ( 1026 "auditors", 1027 &auditors_array), 1028 GNUNET_JSON_spec_bool ( 1029 "kyc_enabled", 1030 &key_data->kyc_enabled), 1031 GNUNET_JSON_spec_mark_optional ( 1032 GNUNET_JSON_spec_object_const ("extensions", 1033 &manifests), 1034 &no_extensions), 1035 GNUNET_JSON_spec_mark_optional ( 1036 GNUNET_JSON_spec_fixed_auto ( 1037 "extensions_sig", 1038 &key_data->extensions_sig), 1039 &no_signature), 1040 GNUNET_JSON_spec_string ("version", 1041 &ver), 1042 GNUNET_JSON_spec_mark_optional ( 1043 GNUNET_JSON_spec_array_const ( 1044 "wallet_balance_limit_without_kyc", 1045 &wblwk), 1046 NULL), 1047 GNUNET_JSON_spec_mark_optional ( 1048 GNUNET_JSON_spec_string ("shopping_url", 1049 &shopping_url), 1050 NULL), 1051 GNUNET_JSON_spec_mark_optional ( 1052 GNUNET_JSON_spec_string ("open_banking_gateway", 1053 &open_banking_gateway), 1054 NULL), 1055 GNUNET_JSON_spec_mark_optional ( 1056 GNUNET_JSON_spec_string ("wire_transfer_gateway", 1057 &wire_transfer_gateway), 1058 NULL), 1059 GNUNET_JSON_spec_mark_optional ( 1060 GNUNET_JSON_spec_string ("bank_compliance_language", 1061 &bank_compliance_language), 1062 NULL), 1063 GNUNET_JSON_spec_mark_optional ( 1064 GNUNET_JSON_spec_bool ("disable_direct_deposit", 1065 &key_data->disable_direct_deposit), 1066 NULL), 1067 GNUNET_JSON_spec_end () 1068 }; 1069 const char *emsg; 1070 unsigned int eline; 1071 1072 if (GNUNET_OK != 1073 GNUNET_JSON_parse (resp_obj, 1074 (check_sig) ? mspec : &mspec[2], 1075 &emsg, 1076 &eline)) 1077 { 1078 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1079 "Parsing /keys failed for `%s' (%u)\n", 1080 emsg, 1081 eline); 1082 EXITIF (1); 1083 } 1084 { 1085 const json_t *hard_limits = NULL; 1086 const json_t *zero_limits = NULL; 1087 bool no_tiny_amount = false; 1088 struct GNUNET_JSON_Specification sspec[] = { 1089 TALER_JSON_spec_currency_specification ( 1090 "currency_specification", 1091 currency, 1092 &key_data->cspec), 1093 TALER_JSON_spec_amount ( 1094 "stefan_abs", 1095 currency, 1096 &key_data->stefan_abs), 1097 TALER_JSON_spec_amount ( 1098 "stefan_log", 1099 currency, 1100 &key_data->stefan_log), 1101 GNUNET_JSON_spec_mark_optional ( 1102 TALER_JSON_spec_amount ( 1103 "tiny_amount", 1104 currency, 1105 &key_data->tiny_amount), 1106 &no_tiny_amount), 1107 GNUNET_JSON_spec_mark_optional ( 1108 GNUNET_JSON_spec_array_const ( 1109 "hard_limits", 1110 &hard_limits), 1111 NULL), 1112 GNUNET_JSON_spec_mark_optional ( 1113 GNUNET_JSON_spec_array_const ( 1114 "zero_limits", 1115 &zero_limits), 1116 NULL), 1117 GNUNET_JSON_spec_double ( 1118 "stefan_lin", 1119 &key_data->stefan_lin), 1120 GNUNET_JSON_spec_end () 1121 }; 1122 1123 if (GNUNET_OK != 1124 GNUNET_JSON_parse (resp_obj, 1125 sspec, 1126 &emsg, 1127 &eline)) 1128 { 1129 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1130 "Parsing /keys failed for `%s' (%u)\n", 1131 emsg, 1132 eline); 1133 EXITIF (1); 1134 } 1135 if ( (NULL != hard_limits) && 1136 (GNUNET_OK != 1137 parse_hard_limits (hard_limits, 1138 key_data)) ) 1139 { 1140 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1141 "Parsing hard limits of /keys failed\n"); 1142 EXITIF (1); 1143 } 1144 if ( (NULL != zero_limits) && 1145 (GNUNET_OK != 1146 parse_zero_limits (zero_limits, 1147 key_data)) ) 1148 { 1149 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1150 "Parsing hard limits of /keys failed\n"); 1151 EXITIF (1); 1152 } 1153 key_data->tiny_amount_available = ! no_tiny_amount; 1154 } 1155 1156 key_data->currency = GNUNET_strdup (currency); 1157 key_data->version = GNUNET_strdup (ver); 1158 key_data->asset_type = GNUNET_strdup (asset_type); 1159 if (NULL != shopping_url) 1160 key_data->shopping_url = GNUNET_strdup (shopping_url); 1161 if (NULL != open_banking_gateway) 1162 key_data->open_banking_gateway = GNUNET_strdup (open_banking_gateway); 1163 if (NULL != wire_transfer_gateway) 1164 key_data->wire_transfer_gateway = GNUNET_strdup (wire_transfer_gateway); 1165 if (NULL != bank_compliance_language) 1166 key_data->bank_compliance_language 1167 = GNUNET_strdup (bank_compliance_language); 1168 if (! no_extensions) 1169 key_data->extensions = json_incref ((json_t *) manifests); 1170 } 1171 1172 /* parse the global fees */ 1173 EXITIF (json_array_size (global_fees) > UINT_MAX); 1174 key_data->num_global_fees 1175 = (unsigned int) json_array_size (global_fees); 1176 if (0 != key_data->num_global_fees) 1177 { 1178 json_t *global_fee; 1179 size_t index; 1180 1181 key_data->global_fees 1182 = GNUNET_new_array (key_data->num_global_fees, 1183 struct TALER_EXCHANGE_GlobalFee); 1184 json_array_foreach (global_fees, index, global_fee) 1185 { 1186 EXITIF (GNUNET_SYSERR == 1187 parse_global_fee (&key_data->global_fees[index], 1188 check_sig, 1189 global_fee, 1190 key_data)); 1191 } 1192 } 1193 1194 /* parse the signing keys */ 1195 EXITIF (json_array_size (sign_keys_array) > UINT_MAX); 1196 key_data->num_sign_keys 1197 = (unsigned int) json_array_size (sign_keys_array); 1198 if (0 != key_data->num_sign_keys) 1199 { 1200 json_t *sign_key_obj; 1201 size_t index; 1202 1203 key_data->sign_keys 1204 = GNUNET_new_array (key_data->num_sign_keys, 1205 struct TALER_EXCHANGE_SigningPublicKey); 1206 json_array_foreach (sign_keys_array, index, sign_key_obj) { 1207 EXITIF (GNUNET_SYSERR == 1208 parse_json_signkey (&key_data->sign_keys[index], 1209 check_sig, 1210 sign_key_obj, 1211 &key_data->master_pub)); 1212 } 1213 } 1214 1215 /* Parse balance limits */ 1216 if (NULL != wblwk) 1217 { 1218 EXITIF (json_array_size (wblwk) > UINT_MAX); 1219 key_data->wblwk_length 1220 = (unsigned int) json_array_size (wblwk); 1221 key_data->wallet_balance_limit_without_kyc 1222 = GNUNET_new_array (key_data->wblwk_length, 1223 struct TALER_Amount); 1224 for (unsigned int i = 0; i<key_data->wblwk_length; i++) 1225 { 1226 struct TALER_Amount *a = &key_data->wallet_balance_limit_without_kyc[i]; 1227 const json_t *aj = json_array_get (wblwk, 1228 i); 1229 struct GNUNET_JSON_Specification spec[] = { 1230 TALER_JSON_spec_amount (NULL, 1231 key_data->currency, 1232 a), 1233 GNUNET_JSON_spec_end () 1234 }; 1235 1236 EXITIF (GNUNET_OK != 1237 GNUNET_JSON_parse (aj, 1238 spec, 1239 NULL, NULL)); 1240 } 1241 } 1242 1243 /* Parse wire accounts */ 1244 key_data->fees = parse_fees (&key_data->master_pub, 1245 key_data->currency, 1246 fees, 1247 &key_data->fees_len); 1248 EXITIF (NULL == key_data->fees); 1249 /* parse accounts */ 1250 EXITIF (json_array_size (accounts) > UINT_MAX); 1251 GNUNET_array_grow (key_data->accounts, 1252 key_data->accounts_len, 1253 json_array_size (accounts)); 1254 EXITIF (GNUNET_OK != 1255 TALER_EXCHANGE_parse_accounts (&key_data->master_pub, 1256 accounts, 1257 key_data->accounts_len, 1258 key_data->accounts)); 1259 1260 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1261 "Parsed %u wire accounts from JSON\n", 1262 key_data->accounts_len); 1263 1264 /* Parse wad partners */ 1265 EXITIF (GNUNET_OK != 1266 parse_wads (wads, 1267 check_sig, 1268 key_data)); 1269 1270 1271 /* Parse the supported extension(s): age-restriction. */ 1272 /* FIXME[Oec]: maybe lift all this into a FP in TALER_Extension ? */ 1273 if (! no_extensions) 1274 { 1275 if (no_signature) 1276 { 1277 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1278 "found extensions without signature\n"); 1279 } 1280 else 1281 { 1282 /* We have an extensions object. Verify its signature. */ 1283 EXITIF (GNUNET_OK != 1284 TALER_extensions_verify_manifests_signature ( 1285 manifests, 1286 &key_data->extensions_sig, 1287 &key_data->master_pub)); 1288 1289 /* Parse and set the the configuration of the extensions accordingly */ 1290 EXITIF (GNUNET_OK != 1291 TALER_extensions_load_manifests (manifests)); 1292 } 1293 1294 /* Assuming we might have now a new value for age_mask, set it in key_data */ 1295 key_data->age_mask = TALER_extensions_get_age_restriction_mask (); 1296 } 1297 1298 /* 1299 * Parse the denomination keys, merging with the 1300 * possibly EXISTING array as required (/keys cherry picking). 1301 * 1302 * The denominations are grouped by common values of 1303 * {cipher, value, fee, age_mask}. 1304 */ 1305 { 1306 json_t *group_obj; 1307 unsigned int group_idx; 1308 1309 json_array_foreach (denominations_by_group, 1310 group_idx, 1311 group_obj) 1312 { 1313 /* First, parse { cipher, fees, value, age_mask, hash } of the current 1314 group. */ 1315 struct TALER_DenominationGroup group = {0}; 1316 const json_t *denom_keys_array; 1317 struct GNUNET_JSON_Specification group_spec[] = { 1318 TALER_JSON_spec_denomination_group (NULL, 1319 key_data->currency, 1320 &group), 1321 GNUNET_JSON_spec_array_const ("denoms", 1322 &denom_keys_array), 1323 GNUNET_JSON_spec_end () 1324 }; 1325 json_t *denom_key_obj; 1326 unsigned int index; 1327 1328 EXITIF (GNUNET_SYSERR == 1329 GNUNET_JSON_parse (group_obj, 1330 group_spec, 1331 NULL, 1332 NULL)); 1333 1334 /* Now, parse the individual denominations */ 1335 json_array_foreach (denom_keys_array, 1336 index, 1337 denom_key_obj) 1338 { 1339 /* Set the common fields from the group for this particular 1340 denomination. Required to make the validity check inside 1341 parse_json_denomkey_partially pass */ 1342 struct TALER_EXCHANGE_DenomPublicKey dk = { 1343 .value = group.value, 1344 .fees = group.fees, 1345 .key.age_mask = group.age_mask 1346 }; 1347 bool found = false; 1348 1349 EXITIF (GNUNET_SYSERR == 1350 parse_json_denomkey_partially (&dk, 1351 group.cipher, 1352 check_sig, 1353 denom_key_obj, 1354 &key_data->master_pub, 1355 group_idx, 1356 index, 1357 check_sig 1358 ? &sig_ctx 1359 : NULL)); 1360 for (unsigned int j = 0; 1361 j<key_data->num_denom_keys; 1362 j++) 1363 { 1364 if (0 == denoms_cmp (&dk, 1365 &key_data->denom_keys[j])) 1366 { 1367 found = true; 1368 break; 1369 } 1370 } 1371 1372 if (found) 1373 { 1374 /* 0:0:0 did not support /keys cherry picking */ 1375 TALER_LOG_DEBUG ("Skipping denomination key: already know it\n"); 1376 TALER_denom_pub_free (&dk.key); 1377 continue; 1378 } 1379 1380 if (key_data->denom_keys_size == key_data->num_denom_keys) 1381 GNUNET_array_grow (key_data->denom_keys, 1382 key_data->denom_keys_size, 1383 key_data->denom_keys_size * 2 + 2); 1384 GNUNET_assert (key_data->denom_keys_size > 1385 key_data->num_denom_keys); 1386 GNUNET_assert (key_data->num_denom_keys < UINT_MAX); 1387 key_data->denom_keys[key_data->num_denom_keys++] = dk; 1388 1389 /* Update "last_denom_issue_date" */ 1390 TALER_LOG_DEBUG ("Adding denomination key that is valid_until %s\n", 1391 GNUNET_TIME_timestamp2s (dk.valid_from)); 1392 key_data->last_denom_issue_date 1393 = GNUNET_TIME_timestamp_max (key_data->last_denom_issue_date, 1394 dk.valid_from); 1395 }; /* end of json_array_foreach over denominations */ 1396 } /* end of json_array_foreach over groups of denominations */ 1397 } /* end of scope for group_ojb/group_idx */ 1398 1399 /* parse the auditor information */ 1400 { 1401 json_t *auditor_info; 1402 unsigned int index; 1403 1404 /* Merge with the existing auditor information we have (/keys cherry picking) */ 1405 json_array_foreach (auditors_array, index, auditor_info) 1406 { 1407 struct TALER_EXCHANGE_AuditorInformation ai; 1408 bool found = false; 1409 1410 memset (&ai, 1411 0, 1412 sizeof (ai)); 1413 EXITIF (GNUNET_SYSERR == 1414 parse_json_auditor (&ai, 1415 check_sig, 1416 auditor_info, 1417 key_data)); 1418 for (unsigned int j = 0; j<key_data->num_auditors; j++) 1419 { 1420 struct TALER_EXCHANGE_AuditorInformation *aix = &key_data->auditors[j]; 1421 1422 if (0 == GNUNET_memcmp (&ai.auditor_pub, 1423 &aix->auditor_pub)) 1424 { 1425 found = true; 1426 /* Merge denomination key signatures of downloaded /keys into existing 1427 auditor information 'aix'. */ 1428 TALER_LOG_DEBUG ( 1429 "Merging %u new audited keys with %u known audited keys\n", 1430 aix->num_denom_keys, 1431 ai.num_denom_keys); 1432 for (unsigned int i = 0; i<ai.num_denom_keys; i++) 1433 { 1434 bool kfound = false; 1435 1436 for (unsigned int k = 0; k<aix->num_denom_keys; k++) 1437 { 1438 if (aix->denom_keys[k].denom_key_offset == 1439 ai.denom_keys[i].denom_key_offset) 1440 { 1441 kfound = true; 1442 break; 1443 } 1444 } 1445 if (! kfound) 1446 GNUNET_array_append (aix->denom_keys, 1447 aix->num_denom_keys, 1448 ai.denom_keys[i]); 1449 } 1450 break; 1451 } 1452 } 1453 if (found) 1454 { 1455 GNUNET_array_grow (ai.denom_keys, 1456 ai.num_denom_keys, 1457 0); 1458 GNUNET_free (ai.auditor_url); 1459 GNUNET_free (ai.auditor_name); 1460 continue; /* we are done */ 1461 } 1462 if (key_data->auditors_size == key_data->num_auditors) 1463 GNUNET_array_grow (key_data->auditors, 1464 key_data->auditors_size, 1465 key_data->auditors_size * 2 + 2); 1466 GNUNET_assert (key_data->auditors_size > 1467 key_data->num_auditors); 1468 GNUNET_assert (NULL != ai.auditor_url); 1469 GNUNET_assert (key_data->num_auditors < UINT_MAX); 1470 key_data->auditors[key_data->num_auditors++] = ai; 1471 }; 1472 } 1473 1474 /* parse the revocation/recoup information */ 1475 if (NULL != recoup_array) 1476 { 1477 json_t *recoup_info; 1478 unsigned int index; 1479 1480 json_array_foreach (recoup_array, index, recoup_info) 1481 { 1482 struct TALER_DenominationHashP h_denom_pub; 1483 struct GNUNET_JSON_Specification spec[] = { 1484 GNUNET_JSON_spec_fixed_auto ("h_denom_pub", 1485 &h_denom_pub), 1486 GNUNET_JSON_spec_end () 1487 }; 1488 1489 EXITIF (GNUNET_OK != 1490 GNUNET_JSON_parse (recoup_info, 1491 spec, 1492 NULL, NULL)); 1493 for (unsigned int j = 0; 1494 j<key_data->num_denom_keys; 1495 j++) 1496 { 1497 if (0 == GNUNET_memcmp (&h_denom_pub, 1498 &key_data->denom_keys[j].h_key)) 1499 { 1500 key_data->denom_keys[j].revoked = true; 1501 break; 1502 } 1503 } 1504 } 1505 } 1506 1507 if (check_sig) 1508 { 1509 struct GNUNET_HashContext *hash_context; 1510 struct GNUNET_HashCode hc; 1511 1512 hash_context = GNUNET_CRYPTO_hash_context_start (); 1513 qsort (sig_ctx.elements, 1514 sig_ctx.elements_pos, 1515 sizeof (struct SignatureElement), 1516 &signature_context_sort_cb); 1517 for (unsigned int i = 0; i<sig_ctx.elements_pos; i++) 1518 { 1519 struct SignatureElement *element = &sig_ctx.elements[i]; 1520 1521 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1522 "Adding %u,%u,%s\n", 1523 element->group_offset, 1524 element->offset, 1525 TALER_B2S (&element->master_sig)); 1526 GNUNET_CRYPTO_hash_context_read (hash_context, 1527 &element->master_sig, 1528 sizeof (element->master_sig)); 1529 } 1530 GNUNET_array_grow (sig_ctx.elements, 1531 sig_ctx.elements_size, 1532 0); 1533 GNUNET_CRYPTO_hash_context_finish (hash_context, 1534 &hc); 1535 EXITIF (GNUNET_OK != 1536 TALER_EXCHANGE_test_signing_key (key_data, 1537 &exchange_pub)); 1538 EXITIF (GNUNET_OK != 1539 TALER_exchange_online_key_set_verify ( 1540 key_data->list_issue_date, 1541 &hc, 1542 &exchange_pub, 1543 &exchange_sig)); 1544 } 1545 return GNUNET_OK; 1546 1547 EXITIF_exit: 1548 *vc = TALER_EXCHANGE_VC_PROTOCOL_ERROR; 1549 return GNUNET_SYSERR; 1550 } 1551 1552 1553 enum GNUNET_GenericReturnValue 1554 TALER_EXCHANGE_test_signing_key ( 1555 const struct TALER_EXCHANGE_Keys *keys, 1556 const struct TALER_ExchangePublicKeyP *pub) 1557 { 1558 struct GNUNET_TIME_Absolute now; 1559 1560 /* we will check using a tolerance of 1h for the time */ 1561 now = GNUNET_TIME_absolute_get (); 1562 for (unsigned int i = 0; i<keys->num_sign_keys; i++) 1563 if ( (GNUNET_TIME_absolute_cmp ( 1564 keys->sign_keys[i].valid_from.abs_time, 1565 <=, 1566 GNUNET_TIME_absolute_add (now, 1567 LIFETIME_TOLERANCE))) && 1568 (GNUNET_TIME_absolute_cmp ( 1569 keys->sign_keys[i].valid_until.abs_time, 1570 >, 1571 GNUNET_TIME_absolute_subtract (now, 1572 LIFETIME_TOLERANCE))) && 1573 (0 == GNUNET_memcmp (pub, 1574 &keys->sign_keys[i].key)) ) 1575 return GNUNET_OK; 1576 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1577 "Signing key not valid at time %s\n", 1578 GNUNET_TIME_absolute2s (now)); 1579 return GNUNET_SYSERR; 1580 } 1581 1582 1583 const struct TALER_EXCHANGE_DenomPublicKey * 1584 TALER_EXCHANGE_get_denomination_key ( 1585 const struct TALER_EXCHANGE_Keys *keys, 1586 const struct TALER_DenominationPublicKey *pk) 1587 { 1588 for (unsigned int i = 0; i<keys->num_denom_keys; i++) 1589 if (0 == 1590 TALER_denom_pub_cmp (pk, 1591 &keys->denom_keys[i].key)) 1592 return &keys->denom_keys[i]; 1593 return NULL; 1594 } 1595 1596 1597 const struct TALER_EXCHANGE_GlobalFee * 1598 TALER_EXCHANGE_get_global_fee ( 1599 const struct TALER_EXCHANGE_Keys *keys, 1600 struct GNUNET_TIME_Timestamp ts) 1601 { 1602 for (unsigned int i = 0; i<keys->num_global_fees; i++) 1603 { 1604 const struct TALER_EXCHANGE_GlobalFee *gf = &keys->global_fees[i]; 1605 1606 if (GNUNET_TIME_timestamp_cmp (ts, 1607 >=, 1608 gf->start_date) && 1609 GNUNET_TIME_timestamp_cmp (ts, 1610 <, 1611 gf->end_date)) 1612 return gf; 1613 } 1614 return NULL; 1615 } 1616 1617 1618 struct TALER_EXCHANGE_DenomPublicKey * 1619 TALER_EXCHANGE_copy_denomination_key ( 1620 const struct TALER_EXCHANGE_DenomPublicKey *key) 1621 { 1622 struct TALER_EXCHANGE_DenomPublicKey *copy; 1623 1624 copy = GNUNET_new (struct TALER_EXCHANGE_DenomPublicKey); 1625 *copy = *key; 1626 TALER_denom_pub_copy (©->key, 1627 &key->key); 1628 return copy; 1629 } 1630 1631 1632 void 1633 TALER_EXCHANGE_destroy_denomination_key ( 1634 struct TALER_EXCHANGE_DenomPublicKey *key) 1635 { 1636 TALER_denom_pub_free (&key->key); 1637 GNUNET_free (key); 1638 } 1639 1640 1641 const struct TALER_EXCHANGE_DenomPublicKey * 1642 TALER_EXCHANGE_get_denomination_key_by_hash ( 1643 const struct TALER_EXCHANGE_Keys *keys, 1644 const struct TALER_DenominationHashP *hc) 1645 { 1646 /* FIXME-optimization: should we maybe use a hash map here? */ 1647 for (unsigned int i = 0; i<keys->num_denom_keys; i++) 1648 if (0 == GNUNET_memcmp (hc, 1649 &keys->denom_keys[i].h_key)) 1650 return &keys->denom_keys[i]; 1651 return NULL; 1652 } 1653 1654 1655 struct TALER_EXCHANGE_Keys * 1656 TALER_EXCHANGE_keys_incref (struct TALER_EXCHANGE_Keys *keys) 1657 { 1658 GNUNET_assert (keys->rc < UINT_MAX); 1659 keys->rc++; 1660 return keys; 1661 } 1662 1663 1664 void 1665 TALER_EXCHANGE_keys_decref (struct TALER_EXCHANGE_Keys *keys) 1666 { 1667 if (NULL == keys) 1668 return; 1669 GNUNET_assert (0 < keys->rc); 1670 keys->rc--; 1671 if (0 != keys->rc) 1672 return; 1673 GNUNET_array_grow (keys->sign_keys, 1674 keys->num_sign_keys, 1675 0); 1676 for (unsigned int i = 0; i<keys->num_denom_keys; i++) 1677 TALER_denom_pub_free (&keys->denom_keys[i].key); 1678 keys->num_denom_keys = 0; 1679 GNUNET_array_grow (keys->denom_keys, 1680 keys->denom_keys_size, 1681 0); 1682 for (unsigned int i = 0; i<keys->num_auditors; i++) 1683 { 1684 GNUNET_array_grow (keys->auditors[i].denom_keys, 1685 keys->auditors[i].num_denom_keys, 1686 0); 1687 GNUNET_free (keys->auditors[i].auditor_url); 1688 GNUNET_free (keys->auditors[i].auditor_name); 1689 } 1690 GNUNET_array_grow (keys->auditors, 1691 keys->auditors_size, 1692 0); 1693 TALER_EXCHANGE_free_accounts (keys->accounts_len, 1694 keys->accounts); 1695 GNUNET_array_grow (keys->accounts, 1696 keys->accounts_len, 1697 0); 1698 free_fees (keys->fees, 1699 keys->fees_len); 1700 GNUNET_array_grow (keys->hard_limits, 1701 keys->hard_limits_length, 1702 0); 1703 GNUNET_array_grow (keys->zero_limits, 1704 keys->zero_limits_length, 1705 0); 1706 json_decref (keys->extensions); 1707 GNUNET_free (keys->cspec.name); 1708 json_decref (keys->cspec.map_alt_unit_names); 1709 GNUNET_array_grow (keys->cspec.common_amounts, 1710 keys->cspec.num_common_amounts, 1711 0); 1712 GNUNET_free (keys->wallet_balance_limit_without_kyc); 1713 GNUNET_free (keys->version); 1714 GNUNET_free (keys->currency); 1715 GNUNET_free (keys->asset_type); 1716 GNUNET_free (keys->shopping_url); 1717 GNUNET_free (keys->open_banking_gateway); 1718 GNUNET_free (keys->wire_transfer_gateway); 1719 GNUNET_free (keys->bank_compliance_language); 1720 for (unsigned int i = 0; i < keys->num_wad_partners; i++) 1721 GNUNET_free (keys->wad_partners[i].partner_base_url); 1722 GNUNET_free (keys->wad_partners); 1723 GNUNET_free (keys->global_fees); 1724 GNUNET_free (keys->exchange_url); 1725 GNUNET_free (keys); 1726 } 1727 1728 1729 struct TALER_EXCHANGE_Keys * 1730 TALER_EXCHANGE_keys_from_json (const json_t *j) 1731 { 1732 const json_t *jkeys; 1733 const char *url; 1734 uint32_t version; 1735 struct GNUNET_TIME_Timestamp expire 1736 = GNUNET_TIME_UNIT_ZERO_TS; 1737 struct GNUNET_JSON_Specification spec[] = { 1738 GNUNET_JSON_spec_uint32 ("version", 1739 &version), 1740 GNUNET_JSON_spec_object_const ("keys", 1741 &jkeys), 1742 TALER_JSON_spec_web_url ("exchange_url", 1743 &url), 1744 GNUNET_JSON_spec_mark_optional ( 1745 GNUNET_JSON_spec_timestamp ("expire", 1746 &expire), 1747 NULL), 1748 GNUNET_JSON_spec_end () 1749 }; 1750 struct TALER_EXCHANGE_Keys *keys; 1751 enum TALER_EXCHANGE_VersionCompatibility compat; 1752 1753 if (NULL == j) 1754 return NULL; 1755 if (GNUNET_OK != 1756 GNUNET_JSON_parse (j, 1757 spec, 1758 NULL, NULL)) 1759 { 1760 GNUNET_break_op (0); 1761 return NULL; 1762 } 1763 if (0 != version) 1764 { 1765 return NULL; /* unsupported version */ 1766 } 1767 keys = GNUNET_new (struct TALER_EXCHANGE_Keys); 1768 if (GNUNET_OK != 1769 TALER_EXCHANGE_decode_keys_json_ (jkeys, 1770 false, 1771 keys, 1772 &compat)) 1773 { 1774 GNUNET_break (0); 1775 return NULL; 1776 } 1777 keys->rc = 1; 1778 keys->key_data_expiration = expire; 1779 keys->exchange_url = GNUNET_strdup (url); 1780 return keys; 1781 } 1782 1783 1784 /** 1785 * Data we track per denomination group. 1786 */ 1787 struct GroupData 1788 { 1789 /** 1790 * The json blob with the group meta-data and list of denominations 1791 */ 1792 json_t *json; 1793 1794 /** 1795 * Meta data for this group. 1796 */ 1797 struct TALER_DenominationGroup meta; 1798 }; 1799 1800 1801 /** 1802 * Add denomination group represented by @a value 1803 * to list of denominations in @a cls. Also frees 1804 * the @a value. 1805 * 1806 * @param[in,out] cls a `json_t *` with an array to build 1807 * @param key unused 1808 * @param value a `struct GroupData *` 1809 * @return #GNUNET_OK (continue to iterate) 1810 */ 1811 static enum GNUNET_GenericReturnValue 1812 add_grp (void *cls, 1813 const struct GNUNET_HashCode *key, 1814 void *value) 1815 { 1816 json_t *denominations_by_group = cls; 1817 struct GroupData *gd = value; 1818 const char *cipher; 1819 json_t *ge; 1820 bool age_restricted = gd->meta.age_mask.bits != 0; 1821 1822 (void) key; 1823 switch (gd->meta.cipher) 1824 { 1825 case GNUNET_CRYPTO_BSA_RSA: 1826 cipher = age_restricted ? "RSA+age_restricted" : "RSA"; 1827 break; 1828 case GNUNET_CRYPTO_BSA_CS: 1829 cipher = age_restricted ? "CS+age_restricted" : "CS"; 1830 break; 1831 default: 1832 GNUNET_assert (false); 1833 } 1834 1835 ge = GNUNET_JSON_PACK ( 1836 GNUNET_JSON_pack_string ("cipher", 1837 cipher), 1838 GNUNET_JSON_pack_array_steal ("denoms", 1839 gd->json), 1840 TALER_JSON_PACK_DENOM_FEES ("fee", 1841 &gd->meta.fees), 1842 GNUNET_JSON_pack_allow_null ( 1843 age_restricted 1844 ? GNUNET_JSON_pack_uint64 ("age_mask", 1845 gd->meta.age_mask.bits) 1846 : GNUNET_JSON_pack_string ("dummy", 1847 NULL)), 1848 TALER_JSON_pack_amount ("value", 1849 &gd->meta.value)); 1850 GNUNET_assert (0 == 1851 json_array_append_new (denominations_by_group, 1852 ge)); 1853 GNUNET_free (gd); 1854 return GNUNET_OK; 1855 } 1856 1857 1858 /** 1859 * Convert array of account restrictions @a ars to JSON. 1860 * 1861 * @param ar_len length of @a ars 1862 * @param ars account restrictions to convert 1863 * @return JSON representation 1864 */ 1865 static json_t * 1866 ar_to_json (unsigned int ar_len, 1867 const struct TALER_EXCHANGE_AccountRestriction ars[static ar_len]) 1868 { 1869 json_t *rval; 1870 1871 rval = json_array (); 1872 GNUNET_assert (NULL != rval); 1873 for (unsigned int i = 0; i<ar_len; i++) 1874 { 1875 const struct TALER_EXCHANGE_AccountRestriction *ar = &ars[i]; 1876 1877 switch (ar->type) 1878 { 1879 case TALER_EXCHANGE_AR_INVALID: 1880 GNUNET_break (0); 1881 json_decref (rval); 1882 return NULL; 1883 case TALER_EXCHANGE_AR_DENY: 1884 GNUNET_assert ( 1885 0 == 1886 json_array_append_new ( 1887 rval, 1888 GNUNET_JSON_PACK ( 1889 GNUNET_JSON_pack_string ("type", 1890 "deny")))); 1891 break; 1892 case TALER_EXCHANGE_AR_REGEX: 1893 GNUNET_assert ( 1894 0 == 1895 json_array_append_new ( 1896 rval, 1897 GNUNET_JSON_PACK ( 1898 GNUNET_JSON_pack_string ( 1899 "type", 1900 "regex"), 1901 GNUNET_JSON_pack_string ( 1902 "payto_regex", 1903 ar->details.regex.posix_egrep), 1904 GNUNET_JSON_pack_string ( 1905 "human_hint", 1906 ar->details.regex.human_hint), 1907 GNUNET_JSON_pack_object_incref ( 1908 "human_hint_i18n", 1909 (json_t *) ar->details.regex.human_hint_i18n) 1910 ))); 1911 break; 1912 } 1913 } 1914 return rval; 1915 } 1916 1917 1918 json_t * 1919 TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd) 1920 { 1921 struct GNUNET_TIME_Timestamp now; 1922 json_t *keys; 1923 json_t *signkeys; 1924 json_t *denominations_by_group; 1925 json_t *auditors; 1926 json_t *recoup; 1927 json_t *wire_fees; 1928 json_t *accounts; 1929 json_t *global_fees; 1930 json_t *wblwk = NULL; 1931 json_t *wads_json; 1932 json_t *hard_limits; 1933 json_t *zero_limits; 1934 1935 now = GNUNET_TIME_timestamp_get (); 1936 signkeys = json_array (); 1937 GNUNET_assert (NULL != signkeys); 1938 for (unsigned int i = 0; i<kd->num_sign_keys; i++) 1939 { 1940 const struct TALER_EXCHANGE_SigningPublicKey *sk = &kd->sign_keys[i]; 1941 json_t *signkey; 1942 1943 if (GNUNET_TIME_timestamp_cmp (now, 1944 >, 1945 sk->valid_until)) 1946 continue; /* skip keys that have expired */ 1947 signkey = GNUNET_JSON_PACK ( 1948 GNUNET_JSON_pack_data_auto ("key", 1949 &sk->key), 1950 GNUNET_JSON_pack_data_auto ("master_sig", 1951 &sk->master_sig), 1952 GNUNET_JSON_pack_timestamp ("stamp_start", 1953 sk->valid_from), 1954 GNUNET_JSON_pack_timestamp ("stamp_expire", 1955 sk->valid_until), 1956 GNUNET_JSON_pack_timestamp ("stamp_end", 1957 sk->valid_legal)); 1958 GNUNET_assert (NULL != signkey); 1959 GNUNET_assert (0 == 1960 json_array_append_new (signkeys, 1961 signkey)); 1962 } 1963 1964 denominations_by_group = json_array (); 1965 GNUNET_assert (NULL != denominations_by_group); 1966 { 1967 struct GNUNET_CONTAINER_MultiHashMap *dbg; 1968 1969 dbg = GNUNET_CONTAINER_multihashmap_create (128, 1970 false); 1971 for (unsigned int i = 0; i<kd->num_denom_keys; i++) 1972 { 1973 const struct TALER_EXCHANGE_DenomPublicKey *dk = &kd->denom_keys[i]; 1974 struct TALER_DenominationGroup meta = { 1975 .cipher = dk->key.bsign_pub_key->cipher, 1976 .value = dk->value, 1977 .fees = dk->fees, 1978 .age_mask = dk->key.age_mask 1979 }; 1980 struct GNUNET_HashCode key; 1981 struct GroupData *gd; 1982 json_t *denom; 1983 struct GNUNET_JSON_PackSpec key_spec; 1984 1985 if (GNUNET_TIME_timestamp_cmp (now, 1986 >, 1987 dk->expire_deposit)) 1988 continue; /* skip keys that have expired */ 1989 TALER_denomination_group_get_key (&meta, 1990 &key); 1991 gd = GNUNET_CONTAINER_multihashmap_get (dbg, 1992 &key); 1993 if (NULL == gd) 1994 { 1995 gd = GNUNET_new (struct GroupData); 1996 gd->meta = meta; 1997 gd->json = json_array (); 1998 GNUNET_assert (NULL != gd->json); 1999 GNUNET_assert ( 2000 GNUNET_OK == 2001 GNUNET_CONTAINER_multihashmap_put (dbg, 2002 &key, 2003 gd, 2004 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 2005 2006 } 2007 switch (meta.cipher) 2008 { 2009 case GNUNET_CRYPTO_BSA_RSA: 2010 key_spec = 2011 GNUNET_JSON_pack_rsa_public_key ( 2012 "rsa_pub", 2013 dk->key.bsign_pub_key->details.rsa_public_key); 2014 break; 2015 case GNUNET_CRYPTO_BSA_CS: 2016 key_spec = 2017 GNUNET_JSON_pack_data_varsize ( 2018 "cs_pub", 2019 &dk->key.bsign_pub_key->details.cs_public_key, 2020 sizeof (dk->key.bsign_pub_key->details.cs_public_key)); 2021 break; 2022 default: 2023 GNUNET_assert (false); 2024 } 2025 denom = GNUNET_JSON_PACK ( 2026 GNUNET_JSON_pack_timestamp ("stamp_expire_deposit", 2027 dk->expire_deposit), 2028 GNUNET_JSON_pack_timestamp ("stamp_expire_withdraw", 2029 dk->withdraw_valid_until), 2030 GNUNET_JSON_pack_timestamp ("stamp_start", 2031 dk->valid_from), 2032 GNUNET_JSON_pack_timestamp ("stamp_expire_legal", 2033 dk->expire_legal), 2034 GNUNET_JSON_pack_data_auto ("master_sig", 2035 &dk->master_sig), 2036 key_spec 2037 ); 2038 GNUNET_assert (0 == 2039 json_array_append_new (gd->json, 2040 denom)); 2041 } 2042 GNUNET_CONTAINER_multihashmap_iterate (dbg, 2043 &add_grp, 2044 denominations_by_group); 2045 GNUNET_CONTAINER_multihashmap_destroy (dbg); 2046 } 2047 2048 auditors = json_array (); 2049 GNUNET_assert (NULL != auditors); 2050 for (unsigned int i = 0; i<kd->num_auditors; i++) 2051 { 2052 const struct TALER_EXCHANGE_AuditorInformation *ai = &kd->auditors[i]; 2053 json_t *a; 2054 json_t *adenoms; 2055 2056 adenoms = json_array (); 2057 GNUNET_assert (NULL != adenoms); 2058 for (unsigned int j = 0; j<ai->num_denom_keys; j++) 2059 { 2060 const struct TALER_EXCHANGE_AuditorDenominationInfo *adi = 2061 &ai->denom_keys[j]; 2062 const struct TALER_EXCHANGE_DenomPublicKey *dk = 2063 &kd->denom_keys[adi->denom_key_offset]; 2064 json_t *k; 2065 2066 GNUNET_assert (adi->denom_key_offset < kd->num_denom_keys); 2067 if (GNUNET_TIME_timestamp_cmp (now, 2068 >, 2069 dk->expire_deposit)) 2070 continue; /* skip auditor signatures for denomination keys that have expired */ 2071 GNUNET_assert (adi->denom_key_offset < kd->num_denom_keys); 2072 k = GNUNET_JSON_PACK ( 2073 GNUNET_JSON_pack_data_auto ("denom_pub_h", 2074 &dk->h_key), 2075 GNUNET_JSON_pack_data_auto ("auditor_sig", 2076 &adi->auditor_sig)); 2077 GNUNET_assert (0 == 2078 json_array_append_new (adenoms, 2079 k)); 2080 } 2081 2082 a = GNUNET_JSON_PACK ( 2083 GNUNET_JSON_pack_data_auto ("auditor_pub", 2084 &ai->auditor_pub), 2085 GNUNET_JSON_pack_string ("auditor_url", 2086 ai->auditor_url), 2087 GNUNET_JSON_pack_string ("auditor_name", 2088 ai->auditor_name), 2089 GNUNET_JSON_pack_array_steal ("denomination_keys", 2090 adenoms)); 2091 GNUNET_assert (0 == 2092 json_array_append_new (auditors, 2093 a)); 2094 } 2095 2096 global_fees = json_array (); 2097 GNUNET_assert (NULL != global_fees); 2098 for (unsigned int i = 0; i<kd->num_global_fees; i++) 2099 { 2100 const struct TALER_EXCHANGE_GlobalFee *gf 2101 = &kd->global_fees[i]; 2102 2103 if (GNUNET_TIME_absolute_is_past (gf->end_date.abs_time)) 2104 continue; 2105 GNUNET_assert ( 2106 0 == 2107 json_array_append_new ( 2108 global_fees, 2109 GNUNET_JSON_PACK ( 2110 GNUNET_JSON_pack_timestamp ("start_date", 2111 gf->start_date), 2112 GNUNET_JSON_pack_timestamp ("end_date", 2113 gf->end_date), 2114 TALER_JSON_PACK_GLOBAL_FEES (&gf->fees), 2115 GNUNET_JSON_pack_time_rel ("history_expiration", 2116 gf->history_expiration), 2117 GNUNET_JSON_pack_time_rel ("purse_timeout", 2118 gf->purse_timeout), 2119 GNUNET_JSON_pack_uint64 ("purse_account_limit", 2120 gf->purse_account_limit), 2121 GNUNET_JSON_pack_data_auto ("master_sig", 2122 &gf->master_sig)))); 2123 } 2124 2125 accounts = json_array (); 2126 GNUNET_assert (NULL != accounts); 2127 for (unsigned int i = 0; i<kd->accounts_len; i++) 2128 { 2129 const struct TALER_EXCHANGE_WireAccount *acc 2130 = &kd->accounts[i]; 2131 json_t *credit_restrictions; 2132 json_t *debit_restrictions; 2133 2134 credit_restrictions 2135 = ar_to_json (acc->credit_restrictions_length, 2136 acc->credit_restrictions); 2137 GNUNET_assert (NULL != credit_restrictions); 2138 debit_restrictions 2139 = ar_to_json (acc->debit_restrictions_length, 2140 acc->debit_restrictions); 2141 GNUNET_assert (NULL != debit_restrictions); 2142 GNUNET_assert ( 2143 0 == 2144 json_array_append_new ( 2145 accounts, 2146 GNUNET_JSON_PACK ( 2147 TALER_JSON_pack_full_payto ("payto_uri", 2148 acc->fpayto_uri), 2149 GNUNET_JSON_pack_allow_null ( 2150 GNUNET_JSON_pack_string ("conversion_url", 2151 acc->conversion_url)), 2152 GNUNET_JSON_pack_int64 ("priority", 2153 acc->priority), 2154 GNUNET_JSON_pack_allow_null ( 2155 GNUNET_JSON_pack_string ("bank_label", 2156 acc->bank_label)), 2157 GNUNET_JSON_pack_array_steal ("debit_restrictions", 2158 debit_restrictions), 2159 GNUNET_JSON_pack_array_steal ("credit_restrictions", 2160 credit_restrictions), 2161 GNUNET_JSON_pack_data_auto ("master_sig", 2162 &acc->master_sig)))); 2163 } 2164 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2165 "Serialized %u/%u wire accounts to JSON\n", 2166 (unsigned int) json_array_size (accounts), 2167 kd->accounts_len); 2168 2169 wire_fees = json_object (); 2170 GNUNET_assert (NULL != wire_fees); 2171 for (unsigned int i = 0; i<kd->fees_len; i++) 2172 { 2173 const struct TALER_EXCHANGE_WireFeesByMethod *fbw 2174 = &kd->fees[i]; 2175 json_t *wf; 2176 2177 wf = json_array (); 2178 GNUNET_assert (NULL != wf); 2179 for (struct TALER_EXCHANGE_WireAggregateFees *p = fbw->fees_head; 2180 NULL != p; 2181 p = p->next) 2182 { 2183 GNUNET_assert ( 2184 0 == 2185 json_array_append_new ( 2186 wf, 2187 GNUNET_JSON_PACK ( 2188 TALER_JSON_pack_amount ("wire_fee", 2189 &p->fees.wire), 2190 TALER_JSON_pack_amount ("closing_fee", 2191 &p->fees.closing), 2192 GNUNET_JSON_pack_timestamp ("start_date", 2193 p->start_date), 2194 GNUNET_JSON_pack_timestamp ("end_date", 2195 p->end_date), 2196 GNUNET_JSON_pack_data_auto ("sig", 2197 &p->master_sig)))); 2198 } 2199 GNUNET_assert (0 == 2200 json_object_set_new (wire_fees, 2201 fbw->method, 2202 wf)); 2203 } 2204 2205 recoup = json_array (); 2206 GNUNET_assert (NULL != recoup); 2207 for (unsigned int i = 0; i<kd->num_denom_keys; i++) 2208 { 2209 const struct TALER_EXCHANGE_DenomPublicKey *dk 2210 = &kd->denom_keys[i]; 2211 if (! dk->revoked) 2212 continue; 2213 GNUNET_assert (0 == 2214 json_array_append_new ( 2215 recoup, 2216 GNUNET_JSON_PACK ( 2217 GNUNET_JSON_pack_data_auto ("h_denom_pub", 2218 &dk->h_key)))); 2219 } 2220 2221 wblwk = json_array (); 2222 GNUNET_assert (NULL != wblwk); 2223 for (unsigned int i = 0; i<kd->wblwk_length; i++) 2224 { 2225 const struct TALER_Amount *a = &kd->wallet_balance_limit_without_kyc[i]; 2226 2227 GNUNET_assert (0 == 2228 json_array_append_new ( 2229 wblwk, 2230 TALER_JSON_from_amount (a))); 2231 } 2232 2233 hard_limits = json_array (); 2234 for (unsigned int i = 0; i < kd->hard_limits_length; i++) 2235 { 2236 const struct TALER_EXCHANGE_AccountLimit *al 2237 = &kd->hard_limits[i]; 2238 json_t *j; 2239 2240 j = GNUNET_JSON_PACK ( 2241 TALER_JSON_pack_amount ("threshold", 2242 &al->threshold), 2243 GNUNET_JSON_pack_time_rel ("timeframe", 2244 al->timeframe), 2245 TALER_JSON_pack_kycte ("operation_type", 2246 al->operation_type), 2247 GNUNET_JSON_pack_bool ("soft_limit", 2248 al->soft_limit) 2249 ); 2250 GNUNET_assert (0 == 2251 json_array_append_new ( 2252 hard_limits, 2253 j)); 2254 } 2255 2256 zero_limits = json_array (); 2257 for (unsigned int i = 0; i < kd->zero_limits_length; i++) 2258 { 2259 const struct TALER_EXCHANGE_ZeroLimitedOperation *zol 2260 = &kd->zero_limits[i]; 2261 json_t *j; 2262 2263 j = GNUNET_JSON_PACK ( 2264 TALER_JSON_pack_kycte ("operation_type", 2265 zol->operation_type) 2266 ); 2267 GNUNET_assert (0 == 2268 json_array_append_new ( 2269 zero_limits, 2270 j)); 2271 } 2272 2273 wads_json = json_array (); 2274 GNUNET_assert (NULL != wads_json); 2275 for (unsigned int i = 0; i < kd->num_wad_partners; i++) 2276 { 2277 const struct TALER_EXCHANGE_WadPartner *wp 2278 = &kd->wad_partners[i]; 2279 2280 GNUNET_assert ( 2281 0 == 2282 json_array_append_new ( 2283 wads_json, 2284 GNUNET_JSON_PACK ( 2285 GNUNET_JSON_pack_string ("partner_base_url", 2286 wp->partner_base_url), 2287 GNUNET_JSON_pack_data_auto ("partner_master_pub", 2288 &wp->partner_master_pub), 2289 TALER_JSON_pack_amount ("wad_fee", 2290 &wp->wad_fee), 2291 GNUNET_JSON_pack_time_rel ("wad_frequency", 2292 wp->wad_frequency), 2293 GNUNET_JSON_pack_timestamp ("start_date", 2294 wp->start_date), 2295 GNUNET_JSON_pack_timestamp ("end_date", 2296 wp->end_date), 2297 GNUNET_JSON_pack_data_auto ("master_sig", 2298 &wp->master_sig)))); 2299 } 2300 2301 keys = GNUNET_JSON_PACK ( 2302 GNUNET_JSON_pack_string ("version", 2303 kd->version), 2304 GNUNET_JSON_pack_string ("currency", 2305 kd->currency), 2306 GNUNET_JSON_pack_object_steal ("currency_specification", 2307 TALER_JSON_currency_specs_to_json ( 2308 &kd->cspec)), 2309 TALER_JSON_pack_amount ("stefan_abs", 2310 &kd->stefan_abs), 2311 TALER_JSON_pack_amount ("stefan_log", 2312 &kd->stefan_log), 2313 GNUNET_JSON_pack_double ("stefan_lin", 2314 kd->stefan_lin), 2315 GNUNET_JSON_pack_allow_null ( 2316 kd->tiny_amount_available 2317 ? TALER_JSON_pack_amount ("tiny_amount", 2318 &kd->tiny_amount) 2319 : GNUNET_JSON_pack_string ("dummy", 2320 NULL)), 2321 GNUNET_JSON_pack_string ("asset_type", 2322 kd->asset_type), 2323 GNUNET_JSON_pack_allow_null ( 2324 GNUNET_JSON_pack_string ("shopping_url", 2325 kd->shopping_url)), 2326 GNUNET_JSON_pack_allow_null ( 2327 GNUNET_JSON_pack_string ("open_banking_gateway", 2328 kd->open_banking_gateway)), 2329 GNUNET_JSON_pack_allow_null ( 2330 GNUNET_JSON_pack_string ("wire_transfer_gateway", 2331 kd->wire_transfer_gateway)), 2332 GNUNET_JSON_pack_allow_null ( 2333 GNUNET_JSON_pack_string ("bank_compliance_language", 2334 kd->bank_compliance_language)), 2335 GNUNET_JSON_pack_bool ("disable_direct_deposit", 2336 kd->disable_direct_deposit), 2337 GNUNET_JSON_pack_data_auto ("master_public_key", 2338 &kd->master_pub), 2339 GNUNET_JSON_pack_time_rel ("reserve_closing_delay", 2340 kd->reserve_closing_delay), 2341 GNUNET_JSON_pack_timestamp ("list_issue_date", 2342 kd->list_issue_date), 2343 GNUNET_JSON_pack_array_steal ("global_fees", 2344 global_fees), 2345 GNUNET_JSON_pack_array_steal ("signkeys", 2346 signkeys), 2347 GNUNET_JSON_pack_object_steal ("wire_fees", 2348 wire_fees), 2349 GNUNET_JSON_pack_array_steal ("accounts", 2350 accounts), 2351 GNUNET_JSON_pack_array_steal ("wads", 2352 wads_json), 2353 GNUNET_JSON_pack_array_steal ("hard_limits", 2354 hard_limits), 2355 GNUNET_JSON_pack_array_steal ("zero_limits", 2356 zero_limits), 2357 GNUNET_JSON_pack_array_steal ("denominations", 2358 denominations_by_group), 2359 GNUNET_JSON_pack_allow_null ( 2360 GNUNET_JSON_pack_array_steal ("recoup", 2361 recoup)), 2362 GNUNET_JSON_pack_array_steal ("auditors", 2363 auditors), 2364 GNUNET_JSON_pack_bool ("kyc_enabled", 2365 kd->kyc_enabled), 2366 GNUNET_JSON_pack_allow_null ( 2367 GNUNET_JSON_pack_object_incref ("extensions", 2368 kd->extensions)), 2369 GNUNET_JSON_pack_allow_null ( 2370 GNUNET_is_zero (&kd->extensions_sig) 2371 ? GNUNET_JSON_pack_string ("dummy", 2372 NULL) 2373 : GNUNET_JSON_pack_data_auto ("extensions_sig", 2374 &kd->extensions_sig)), 2375 GNUNET_JSON_pack_allow_null ( 2376 GNUNET_JSON_pack_array_steal ("wallet_balance_limit_without_kyc", 2377 wblwk)) 2378 2379 ); 2380 return GNUNET_JSON_PACK ( 2381 GNUNET_JSON_pack_uint64 ("version", 2382 EXCHANGE_SERIALIZATION_FORMAT_VERSION), 2383 GNUNET_JSON_pack_allow_null ( 2384 GNUNET_JSON_pack_timestamp ("expire", 2385 kd->key_data_expiration)), 2386 GNUNET_JSON_pack_string ("exchange_url", 2387 kd->exchange_url), 2388 GNUNET_JSON_pack_object_steal ("keys", 2389 keys)); 2390 } 2391 2392 2393 /* end of exchange_api_handle.c */