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