exchange_api_handle.c (74964B)
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 37 39 40 /** 41 * How many versions are we backwards compatible with? 42 */ 43 #define EXCHANGE_PROTOCOL_AGE 3 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->denom_keys 521 = GNUNET_new_array (json_array_size (keys), 522 struct TALER_EXCHANGE_AuditorDenominationInfo); 523 pos = 0; 524 json_array_foreach (keys, off, key) { 525 struct TALER_AuditorSignatureP auditor_sig; 526 struct TALER_DenominationHashP denom_h; 527 const struct TALER_EXCHANGE_DenomPublicKey *dk = NULL; 528 unsigned int dk_off = UINT_MAX; 529 struct GNUNET_JSON_Specification kspec[] = { 530 GNUNET_JSON_spec_fixed_auto ("auditor_sig", 531 &auditor_sig), 532 GNUNET_JSON_spec_fixed_auto ("denom_pub_h", 533 &denom_h), 534 GNUNET_JSON_spec_end () 535 }; 536 537 if (GNUNET_OK != 538 GNUNET_JSON_parse (key, 539 kspec, 540 NULL, NULL)) 541 { 542 GNUNET_break_op (0); 543 continue; 544 } 545 for (unsigned int j = 0; j<key_data->num_denom_keys; j++) 546 { 547 if (0 == GNUNET_memcmp (&denom_h, 548 &key_data->denom_keys[j].h_key)) 549 { 550 dk = &key_data->denom_keys[j]; 551 dk_off = j; 552 break; 553 } 554 } 555 if (NULL == dk) 556 { 557 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 558 "Auditor signed denomination %s, which we do not know. Ignoring signature.\n", 559 GNUNET_h2s (&denom_h.hash)); 560 continue; 561 } 562 if (check_sigs) 563 { 564 if (GNUNET_OK != 565 TALER_auditor_denom_validity_verify ( 566 auditor_url, 567 &dk->h_key, 568 &key_data->master_pub, 569 dk->valid_from, 570 dk->withdraw_valid_until, 571 dk->expire_deposit, 572 dk->expire_legal, 573 &dk->value, 574 &dk->fees, 575 &auditor->auditor_pub, 576 &auditor_sig)) 577 { 578 GNUNET_break_op (0); 579 GNUNET_free (auditor->denom_keys); 580 return GNUNET_SYSERR; 581 } 582 } 583 auditor->denom_keys[pos].denom_key_offset = dk_off; 584 auditor->denom_keys[pos].auditor_sig = auditor_sig; 585 pos++; 586 } 587 if (pos > UINT_MAX) 588 { 589 GNUNET_break (0); 590 GNUNET_free (auditor->denom_keys); 591 return GNUNET_SYSERR; 592 } 593 auditor->num_denom_keys = (unsigned int) pos; 594 auditor->auditor_url = GNUNET_strdup (auditor_url); 595 auditor->auditor_name = GNUNET_strdup (auditor_name); 596 return GNUNET_OK; 597 } 598 599 600 /** 601 * Parse a exchange's global fee information encoded in JSON. 602 * 603 * @param[out] gf where to return the result 604 * @param check_sigs should we check signatures 605 * @param fee_obj json to parse 606 * @param key_data already parsed information about the exchange 607 * @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if the signature is 608 * invalid or the json malformed. 609 */ 610 static enum GNUNET_GenericReturnValue 611 parse_global_fee (struct TALER_EXCHANGE_GlobalFee *gf, 612 bool check_sigs, 613 const json_t *fee_obj, 614 const struct TALER_EXCHANGE_Keys *key_data) 615 { 616 struct GNUNET_JSON_Specification spec[] = { 617 GNUNET_JSON_spec_timestamp ("start_date", 618 &gf->start_date), 619 GNUNET_JSON_spec_timestamp ("end_date", 620 &gf->end_date), 621 GNUNET_JSON_spec_relative_time ("purse_timeout", 622 &gf->purse_timeout), 623 GNUNET_JSON_spec_relative_time ("history_expiration", 624 &gf->history_expiration), 625 GNUNET_JSON_spec_uint32 ("purse_account_limit", 626 &gf->purse_account_limit), 627 TALER_JSON_SPEC_GLOBAL_FEES (key_data->currency, 628 &gf->fees), 629 GNUNET_JSON_spec_fixed_auto ("master_sig", 630 &gf->master_sig), 631 GNUNET_JSON_spec_end () 632 }; 633 634 if (GNUNET_OK != 635 GNUNET_JSON_parse (fee_obj, 636 spec, 637 NULL, NULL)) 638 { 639 GNUNET_break_op (0); 640 #if DEBUG 641 json_dumpf (fee_obj, 642 stderr, 643 JSON_INDENT (2)); 644 #endif 645 return GNUNET_SYSERR; 646 } 647 if (check_sigs) 648 { 649 if (GNUNET_OK != 650 TALER_exchange_offline_global_fee_verify ( 651 gf->start_date, 652 gf->end_date, 653 &gf->fees, 654 gf->purse_timeout, 655 gf->history_expiration, 656 gf->purse_account_limit, 657 &key_data->master_pub, 658 &gf->master_sig)) 659 { 660 GNUNET_break_op (0); 661 GNUNET_JSON_parse_free (spec); 662 return GNUNET_SYSERR; 663 } 664 } 665 GNUNET_JSON_parse_free (spec); 666 return GNUNET_OK; 667 } 668 669 670 /** 671 * Compare two denomination keys. Ignores revocation data. 672 * 673 * @param denom1 first denomination key 674 * @param denom2 second denomination key 675 * @return 0 if the two keys are equal (not necessarily 676 * the same object), non-zero otherwise. 677 */ 678 static unsigned int 679 denoms_cmp (const struct TALER_EXCHANGE_DenomPublicKey *denom1, 680 const struct TALER_EXCHANGE_DenomPublicKey *denom2) 681 { 682 struct TALER_EXCHANGE_DenomPublicKey tmp1; 683 struct TALER_EXCHANGE_DenomPublicKey tmp2; 684 685 if (0 != 686 TALER_denom_pub_cmp (&denom1->key, 687 &denom2->key)) 688 return 1; 689 tmp1 = *denom1; 690 tmp2 = *denom2; 691 tmp1.revoked = false; 692 tmp2.revoked = false; 693 memset (&tmp1.key, 694 0, 695 sizeof (tmp1.key)); 696 memset (&tmp2.key, 697 0, 698 sizeof (tmp2.key)); 699 return GNUNET_memcmp (&tmp1, 700 &tmp2); 701 } 702 703 704 /** 705 * Decode the JSON array in @a hard_limits from the /keys response 706 * and store the data in `hard_limits` array the @a key_data. 707 * 708 * @param[in] hard_limits JSON array to parse 709 * @param[out] key_data where to store the results we decoded 710 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 711 * (malformed JSON) 712 */ 713 static enum GNUNET_GenericReturnValue 714 parse_hard_limits (const json_t *hard_limits, 715 struct TALER_EXCHANGE_Keys *key_data) 716 { 717 json_t *obj; 718 size_t off; 719 720 key_data->hard_limits_length 721 = (unsigned int) json_array_size (hard_limits); 722 if ( ((size_t) key_data->hard_limits_length) 723 != json_array_size (hard_limits)) 724 { 725 GNUNET_break (0); 726 return GNUNET_SYSERR; 727 } 728 key_data->hard_limits 729 = GNUNET_new_array (key_data->hard_limits_length, 730 struct TALER_EXCHANGE_AccountLimit); 731 732 json_array_foreach (hard_limits, off, obj) 733 { 734 struct TALER_EXCHANGE_AccountLimit *al 735 = &key_data->hard_limits[off]; 736 struct GNUNET_JSON_Specification spec[] = { 737 TALER_JSON_spec_kycte ("operation_type", 738 &al->operation_type), 739 TALER_JSON_spec_amount_any ("threshold", 740 &al->threshold), 741 GNUNET_JSON_spec_relative_time ("timeframe", 742 &al->timeframe), 743 GNUNET_JSON_spec_mark_optional ( 744 GNUNET_JSON_spec_bool ("soft_limit", 745 &al->soft_limit), 746 NULL), 747 GNUNET_JSON_spec_end () 748 }; 749 750 if (GNUNET_OK != 751 GNUNET_JSON_parse (obj, 752 spec, 753 NULL, NULL)) 754 { 755 GNUNET_break_op (0); 756 return GNUNET_SYSERR; 757 } 758 } 759 return GNUNET_OK; 760 } 761 762 763 /** 764 * Decode the JSON array in @a zero_limits from the /keys response 765 * and store the data in `zero_limits` array the @a key_data. 766 * 767 * @param[in] zero_limits JSON array to parse 768 * @param[out] key_data where to store the results we decoded 769 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 770 * (malformed JSON) 771 */ 772 static enum GNUNET_GenericReturnValue 773 parse_zero_limits (const json_t *zero_limits, 774 struct TALER_EXCHANGE_Keys *key_data) 775 { 776 json_t *obj; 777 size_t off; 778 779 key_data->zero_limits_length 780 = (unsigned int) json_array_size (zero_limits); 781 if ( ((size_t) key_data->zero_limits_length) 782 != json_array_size (zero_limits)) 783 { 784 GNUNET_break (0); 785 return GNUNET_SYSERR; 786 } 787 key_data->zero_limits 788 = GNUNET_new_array (key_data->zero_limits_length, 789 struct TALER_EXCHANGE_ZeroLimitedOperation); 790 791 json_array_foreach (zero_limits, off, obj) 792 { 793 struct TALER_EXCHANGE_ZeroLimitedOperation *zol 794 = &key_data->zero_limits[off]; 795 struct GNUNET_JSON_Specification spec[] = { 796 TALER_JSON_spec_kycte ("operation_type", 797 &zol->operation_type), 798 GNUNET_JSON_spec_end () 799 }; 800 801 if (GNUNET_OK != 802 GNUNET_JSON_parse (obj, 803 spec, 804 NULL, NULL)) 805 { 806 GNUNET_break_op (0); 807 return GNUNET_SYSERR; 808 } 809 } 810 return GNUNET_OK; 811 } 812 813 814 /** 815 * Parse the wads (partner exchange) array from /keys and store the 816 * data in @a key_data. 817 * 818 * @param[in] wads_array JSON array to parse 819 * @param check_sig true if we should verify signatures 820 * @param[out] key_data where to store the results 821 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 822 */ 823 static enum GNUNET_GenericReturnValue 824 parse_wads (const json_t *wads_array, 825 bool check_sig, 826 struct TALER_EXCHANGE_Keys *key_data) 827 { 828 size_t n = json_array_size (wads_array); 829 json_t *wad_obj; 830 size_t index; 831 832 if (n > UINT_MAX) 833 { 834 GNUNET_break (0); 835 return GNUNET_SYSERR; 836 } 837 if (0 == n) 838 return GNUNET_OK; 839 key_data->num_wad_partners = (unsigned int) n; 840 key_data->wad_partners 841 = GNUNET_new_array (n, 842 struct TALER_EXCHANGE_WadPartner); 843 json_array_foreach (wads_array, index, wad_obj) 844 { 845 struct TALER_EXCHANGE_WadPartner *wp 846 = &key_data->wad_partners[index]; 847 const char *partner_base_url; 848 struct GNUNET_JSON_Specification spec[] = { 849 TALER_JSON_spec_web_url ("partner_base_url", 850 &partner_base_url), 851 GNUNET_JSON_spec_fixed_auto ("partner_master_pub", 852 &wp->partner_master_pub), 853 TALER_JSON_spec_amount ("wad_fee", 854 key_data->currency, 855 &wp->wad_fee), 856 GNUNET_JSON_spec_relative_time ("wad_frequency", 857 &wp->wad_frequency), 858 GNUNET_JSON_spec_timestamp ("start_date", 859 &wp->start_date), 860 GNUNET_JSON_spec_timestamp ("end_date", 861 &wp->end_date), 862 GNUNET_JSON_spec_fixed_auto ("master_sig", 863 &wp->master_sig), 864 GNUNET_JSON_spec_end () 865 }; 866 867 if (GNUNET_OK != 868 GNUNET_JSON_parse (wad_obj, 869 spec, 870 NULL, NULL)) 871 { 872 GNUNET_break_op (0); 873 return GNUNET_SYSERR; 874 } 875 wp->partner_base_url = GNUNET_strdup (partner_base_url); 876 if (check_sig && 877 GNUNET_OK != 878 TALER_exchange_offline_partner_details_verify ( 879 &wp->partner_master_pub, 880 wp->start_date, 881 wp->end_date, 882 wp->wad_frequency, 883 &wp->wad_fee, 884 partner_base_url, 885 &key_data->master_pub, 886 &wp->master_sig)) 887 { 888 GNUNET_break_op (0); 889 return GNUNET_SYSERR; 890 } 891 } 892 return GNUNET_OK; 893 } 894 895 896 /** 897 * Decode the JSON in @a resp_obj from the /keys response 898 * and store the data in the @a key_data. 899 * 900 * @param[in] resp_obj JSON object to parse 901 * @param check_sig true if we should check the signature 902 * @param[out] key_data where to store the results we decoded 903 * @param[out] vc where to store version compatibility data 904 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 905 * (malformed JSON); on #GNUNET_SYSERR, the @a key_data 906 * structure may be partially initialized and must still 907 * be released using #TALER_EXCHANGE_keys_decref()! 908 */ 909 enum GNUNET_GenericReturnValue 910 TALER_EXCHANGE_decode_keys_json_ ( 911 const json_t *resp_obj, 912 bool check_sig, 913 struct TALER_EXCHANGE_Keys *key_data, 914 enum TALER_EXCHANGE_VersionCompatibility *vc) 915 { 916 struct TALER_ExchangeSignatureP exchange_sig; 917 struct TALER_ExchangePublicKeyP exchange_pub; 918 const json_t *wblwk = NULL; 919 const json_t *global_fees; 920 const json_t *sign_keys_array; 921 const json_t *denominations_by_group; 922 const json_t *auditors_array; 923 const json_t *recoup_array = NULL; 924 const json_t *accounts; 925 const json_t *fees; 926 const json_t *wads; 927 const char *shopping_url = NULL; 928 const char *bank_compliance_language = NULL; 929 struct SignatureContext sig_ctx = { 0 }; 930 931 if (JSON_OBJECT != json_typeof (resp_obj)) 932 { 933 GNUNET_break_op (0); 934 return GNUNET_SYSERR; 935 } 936 #if DEBUG 937 json_dumpf (resp_obj, 938 stderr, 939 JSON_INDENT (2)); 940 #endif 941 /* check the version first */ 942 { 943 struct TALER_JSON_ProtocolVersion pv; 944 struct GNUNET_JSON_Specification spec[] = { 945 TALER_JSON_spec_version ("version", 946 &pv), 947 GNUNET_JSON_spec_end () 948 }; 949 950 if (GNUNET_OK != 951 GNUNET_JSON_parse (resp_obj, 952 spec, 953 NULL, NULL)) 954 { 955 GNUNET_break_op (0); 956 return GNUNET_SYSERR; 957 } 958 *vc = TALER_EXCHANGE_VC_MATCH; 959 if (EXCHANGE_PROTOCOL_CURRENT < pv.current) 960 { 961 *vc |= TALER_EXCHANGE_VC_NEWER; 962 if (EXCHANGE_PROTOCOL_CURRENT < pv.current - pv.age) 963 *vc |= TALER_EXCHANGE_VC_INCOMPATIBLE; 964 } 965 if (EXCHANGE_PROTOCOL_CURRENT > pv.current) 966 { 967 *vc |= TALER_EXCHANGE_VC_OLDER; 968 if (EXCHANGE_PROTOCOL_CURRENT - EXCHANGE_PROTOCOL_AGE > pv.current) 969 *vc |= TALER_EXCHANGE_VC_INCOMPATIBLE; 970 } 971 } 972 973 { 974 const char *ver; 975 const char *currency; 976 const char *asset_type; 977 struct GNUNET_JSON_Specification mspec[] = { 978 GNUNET_JSON_spec_fixed_auto ( 979 "exchange_sig", 980 &exchange_sig), 981 GNUNET_JSON_spec_fixed_auto ( 982 "exchange_pub", 983 &exchange_pub), 984 GNUNET_JSON_spec_fixed_auto ( 985 "master_public_key", 986 &key_data->master_pub), 987 GNUNET_JSON_spec_array_const ("accounts", 988 &accounts), 989 GNUNET_JSON_spec_object_const ("wire_fees", 990 &fees), 991 GNUNET_JSON_spec_array_const ("wads", 992 &wads), 993 GNUNET_JSON_spec_timestamp ( 994 "list_issue_date", 995 &key_data->list_issue_date), 996 GNUNET_JSON_spec_relative_time ( 997 "reserve_closing_delay", 998 &key_data->reserve_closing_delay), 999 GNUNET_JSON_spec_mark_optional ( 1000 GNUNET_JSON_spec_relative_time ( 1001 "default_p2p_push_expiration", 1002 &key_data->default_p2p_push_expiration), 1003 NULL), 1004 GNUNET_JSON_spec_string ( 1005 "currency", 1006 ¤cy), 1007 GNUNET_JSON_spec_string ( 1008 "asset_type", 1009 &asset_type), 1010 GNUNET_JSON_spec_array_const ( 1011 "global_fees", 1012 &global_fees), 1013 GNUNET_JSON_spec_array_const ( 1014 "signkeys", 1015 &sign_keys_array), 1016 GNUNET_JSON_spec_array_const ( 1017 "denominations", 1018 &denominations_by_group), 1019 GNUNET_JSON_spec_mark_optional ( 1020 GNUNET_JSON_spec_array_const ( 1021 "recoup", 1022 &recoup_array), 1023 NULL), 1024 GNUNET_JSON_spec_array_const ( 1025 "auditors", 1026 &auditors_array), 1027 GNUNET_JSON_spec_bool ( 1028 "kyc_enabled", 1029 &key_data->kyc_enabled), 1030 GNUNET_JSON_spec_string ("version", 1031 &ver), 1032 GNUNET_JSON_spec_mark_optional ( 1033 GNUNET_JSON_spec_array_const ( 1034 "wallet_balance_limit_without_kyc", 1035 &wblwk), 1036 NULL), 1037 GNUNET_JSON_spec_mark_optional ( 1038 GNUNET_JSON_spec_string ("shopping_url", 1039 &shopping_url), 1040 NULL), 1041 GNUNET_JSON_spec_mark_optional ( 1042 GNUNET_JSON_spec_string ("bank_compliance_language", 1043 &bank_compliance_language), 1044 NULL), 1045 GNUNET_JSON_spec_mark_optional ( 1046 GNUNET_JSON_spec_bool ("disable_direct_deposit", 1047 &key_data->disable_direct_deposit), 1048 NULL), 1049 GNUNET_JSON_spec_mark_optional ( 1050 GNUNET_JSON_spec_bool ("kyc_swap_tos_acceptance", 1051 &key_data->kyc_swap_tos_acceptance), 1052 NULL), 1053 GNUNET_JSON_spec_end () 1054 }; 1055 const char *emsg; 1056 unsigned int eline; 1057 1058 if (GNUNET_OK != 1059 GNUNET_JSON_parse (resp_obj, 1060 (check_sig) ? mspec : &mspec[2], 1061 &emsg, 1062 &eline)) 1063 { 1064 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1065 "Parsing /keys failed for `%s' (%u)\n", 1066 emsg, 1067 eline); 1068 EXITIF (1); 1069 } 1070 { 1071 const json_t *hard_limits = NULL; 1072 const json_t *zero_limits = NULL; 1073 bool no_tiny_amount = false; 1074 struct GNUNET_JSON_Specification sspec[] = { 1075 TALER_JSON_spec_currency_specification ( 1076 "currency_specification", 1077 currency, 1078 &key_data->cspec), 1079 TALER_JSON_spec_amount ( 1080 "stefan_abs", 1081 currency, 1082 &key_data->stefan_abs), 1083 TALER_JSON_spec_amount ( 1084 "stefan_log", 1085 currency, 1086 &key_data->stefan_log), 1087 GNUNET_JSON_spec_mark_optional ( 1088 TALER_JSON_spec_amount ( 1089 "tiny_amount", 1090 currency, 1091 &key_data->tiny_amount), 1092 &no_tiny_amount), 1093 GNUNET_JSON_spec_mark_optional ( 1094 GNUNET_JSON_spec_array_const ( 1095 "hard_limits", 1096 &hard_limits), 1097 NULL), 1098 GNUNET_JSON_spec_mark_optional ( 1099 GNUNET_JSON_spec_array_const ( 1100 "zero_limits", 1101 &zero_limits), 1102 NULL), 1103 GNUNET_JSON_spec_double ( 1104 "stefan_lin", 1105 &key_data->stefan_lin), 1106 GNUNET_JSON_spec_end () 1107 }; 1108 1109 if (GNUNET_OK != 1110 GNUNET_JSON_parse (resp_obj, 1111 sspec, 1112 &emsg, 1113 &eline)) 1114 { 1115 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1116 "Parsing /keys failed for `%s' (%u)\n", 1117 emsg, 1118 eline); 1119 EXITIF (1); 1120 } 1121 if ( (NULL != hard_limits) && 1122 (GNUNET_OK != 1123 parse_hard_limits (hard_limits, 1124 key_data)) ) 1125 { 1126 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1127 "Parsing hard limits of /keys failed\n"); 1128 EXITIF (1); 1129 } 1130 if ( (NULL != zero_limits) && 1131 (GNUNET_OK != 1132 parse_zero_limits (zero_limits, 1133 key_data)) ) 1134 { 1135 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1136 "Parsing hard limits of /keys failed\n"); 1137 EXITIF (1); 1138 } 1139 key_data->tiny_amount_available = ! no_tiny_amount; 1140 } 1141 1142 key_data->currency = GNUNET_strdup (currency); 1143 key_data->version = GNUNET_strdup (ver); 1144 key_data->asset_type = GNUNET_strdup (asset_type); 1145 if (NULL != shopping_url) 1146 key_data->shopping_url = GNUNET_strdup (shopping_url); 1147 if (NULL != bank_compliance_language) 1148 key_data->bank_compliance_language 1149 = GNUNET_strdup (bank_compliance_language); 1150 } 1151 1152 /* parse the global fees */ 1153 EXITIF (json_array_size (global_fees) > UINT_MAX); 1154 key_data->num_global_fees 1155 = (unsigned int) json_array_size (global_fees); 1156 if (0 != key_data->num_global_fees) 1157 { 1158 json_t *global_fee; 1159 size_t index; 1160 1161 key_data->global_fees 1162 = GNUNET_new_array (key_data->num_global_fees, 1163 struct TALER_EXCHANGE_GlobalFee); 1164 json_array_foreach (global_fees, index, global_fee) 1165 { 1166 EXITIF (GNUNET_SYSERR == 1167 parse_global_fee (&key_data->global_fees[index], 1168 check_sig, 1169 global_fee, 1170 key_data)); 1171 } 1172 } 1173 1174 /* parse the signing keys */ 1175 EXITIF (json_array_size (sign_keys_array) > UINT_MAX); 1176 key_data->num_sign_keys 1177 = (unsigned int) json_array_size (sign_keys_array); 1178 if (0 != key_data->num_sign_keys) 1179 { 1180 json_t *sign_key_obj; 1181 size_t index; 1182 1183 key_data->sign_keys 1184 = GNUNET_new_array (key_data->num_sign_keys, 1185 struct TALER_EXCHANGE_SigningPublicKey); 1186 json_array_foreach (sign_keys_array, index, sign_key_obj) { 1187 EXITIF (GNUNET_SYSERR == 1188 parse_json_signkey (&key_data->sign_keys[index], 1189 check_sig, 1190 sign_key_obj, 1191 &key_data->master_pub)); 1192 } 1193 } 1194 1195 /* Parse balance limits */ 1196 if (NULL != wblwk) 1197 { 1198 EXITIF (json_array_size (wblwk) > UINT_MAX); 1199 key_data->wblwk_length 1200 = (unsigned int) json_array_size (wblwk); 1201 key_data->wallet_balance_limit_without_kyc 1202 = GNUNET_new_array (key_data->wblwk_length, 1203 struct TALER_Amount); 1204 for (unsigned int i = 0; i<key_data->wblwk_length; i++) 1205 { 1206 struct TALER_Amount *a = &key_data->wallet_balance_limit_without_kyc[i]; 1207 const json_t *aj = json_array_get (wblwk, 1208 i); 1209 struct GNUNET_JSON_Specification spec[] = { 1210 TALER_JSON_spec_amount (NULL, 1211 key_data->currency, 1212 a), 1213 GNUNET_JSON_spec_end () 1214 }; 1215 1216 EXITIF (GNUNET_OK != 1217 GNUNET_JSON_parse (aj, 1218 spec, 1219 NULL, NULL)); 1220 } 1221 } 1222 1223 /* Parse wire accounts */ 1224 key_data->fees = parse_fees (&key_data->master_pub, 1225 key_data->currency, 1226 fees, 1227 &key_data->fees_len); 1228 EXITIF (NULL == key_data->fees); 1229 /* parse accounts */ 1230 EXITIF (json_array_size (accounts) > UINT_MAX); 1231 GNUNET_array_grow (key_data->accounts, 1232 key_data->accounts_len, 1233 json_array_size (accounts)); 1234 EXITIF (GNUNET_OK != 1235 TALER_EXCHANGE_parse_accounts (&key_data->master_pub, 1236 accounts, 1237 key_data->accounts_len, 1238 key_data->accounts)); 1239 1240 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1241 "Parsed %u wire accounts from JSON\n", 1242 key_data->accounts_len); 1243 1244 /* Parse wad partners */ 1245 EXITIF (GNUNET_OK != 1246 parse_wads (wads, 1247 check_sig, 1248 key_data)); 1249 1250 1251 /* 1252 * Parse the denomination keys, merging with the 1253 * possibly EXISTING array as required (/keys cherry picking). 1254 * 1255 * The denominations are grouped by common values of 1256 * {cipher, value, fee, age_mask}. 1257 */ 1258 { 1259 json_t *group_obj; 1260 unsigned int group_idx; 1261 1262 json_array_foreach (denominations_by_group, 1263 group_idx, 1264 group_obj) 1265 { 1266 /* First, parse { cipher, fees, value, age_mask, hash } of the current 1267 group. */ 1268 struct TALER_DenominationGroup group = {0}; 1269 const json_t *denom_keys_array; 1270 struct GNUNET_JSON_Specification group_spec[] = { 1271 TALER_JSON_spec_denomination_group (NULL, 1272 key_data->currency, 1273 &group), 1274 GNUNET_JSON_spec_array_const ("denoms", 1275 &denom_keys_array), 1276 GNUNET_JSON_spec_end () 1277 }; 1278 json_t *denom_key_obj; 1279 unsigned int index; 1280 1281 EXITIF (GNUNET_SYSERR == 1282 GNUNET_JSON_parse (group_obj, 1283 group_spec, 1284 NULL, 1285 NULL)); 1286 1287 /* Now, parse the individual denominations */ 1288 json_array_foreach (denom_keys_array, 1289 index, 1290 denom_key_obj) 1291 { 1292 /* Set the common fields from the group for this particular 1293 denomination. Required to make the validity check inside 1294 parse_json_denomkey_partially pass */ 1295 struct TALER_EXCHANGE_DenomPublicKey dk = { 1296 .value = group.value, 1297 .fees = group.fees, 1298 .key.age_mask = group.age_mask 1299 }; 1300 bool found = false; 1301 1302 EXITIF (GNUNET_SYSERR == 1303 parse_json_denomkey_partially (&dk, 1304 group.cipher, 1305 check_sig, 1306 denom_key_obj, 1307 &key_data->master_pub, 1308 group_idx, 1309 index, 1310 check_sig 1311 ? &sig_ctx 1312 : NULL)); 1313 for (unsigned int j = 0; 1314 j<key_data->num_denom_keys; 1315 j++) 1316 { 1317 if (0 == denoms_cmp (&dk, 1318 &key_data->denom_keys[j])) 1319 { 1320 found = true; 1321 break; 1322 } 1323 } 1324 1325 if (found) 1326 { 1327 /* 0:0:0 did not support /keys cherry picking */ 1328 TALER_LOG_DEBUG ("Skipping denomination key: already know it\n"); 1329 TALER_denom_pub_free (&dk.key); 1330 continue; 1331 } 1332 1333 if (key_data->denom_keys_size == key_data->num_denom_keys) 1334 GNUNET_array_grow (key_data->denom_keys, 1335 key_data->denom_keys_size, 1336 key_data->denom_keys_size * 2 + 2); 1337 GNUNET_assert (key_data->denom_keys_size > 1338 key_data->num_denom_keys); 1339 GNUNET_assert (key_data->num_denom_keys < UINT_MAX); 1340 key_data->denom_keys[key_data->num_denom_keys++] = dk; 1341 1342 /* Update "last_denom_issue_date" */ 1343 TALER_LOG_DEBUG ("Adding denomination key that is valid_until %s\n", 1344 GNUNET_TIME_timestamp2s (dk.valid_from)); 1345 key_data->last_denom_issue_date 1346 = GNUNET_TIME_timestamp_max (key_data->last_denom_issue_date, 1347 dk.valid_from); 1348 }; /* end of json_array_foreach over denominations */ 1349 } /* end of json_array_foreach over groups of denominations */ 1350 } /* end of scope for group_ojb/group_idx */ 1351 1352 /* Derive global age_mask from denomination keys */ 1353 for (unsigned int i = 0; i < key_data->num_denom_keys; i++) 1354 { 1355 if (0 != key_data->denom_keys[i].key.age_mask.bits) 1356 { 1357 key_data->age_mask = key_data->denom_keys[i].key.age_mask; 1358 break; 1359 } 1360 } 1361 1362 /* parse the auditor information */ 1363 { 1364 json_t *auditor_info; 1365 unsigned int index; 1366 1367 /* Merge with the existing auditor information we have (/keys cherry picking) */ 1368 json_array_foreach (auditors_array, index, auditor_info) 1369 { 1370 struct TALER_EXCHANGE_AuditorInformation ai; 1371 bool found = false; 1372 1373 memset (&ai, 1374 0, 1375 sizeof (ai)); 1376 EXITIF (GNUNET_SYSERR == 1377 parse_json_auditor (&ai, 1378 check_sig, 1379 auditor_info, 1380 key_data)); 1381 for (unsigned int j = 0; j<key_data->num_auditors; j++) 1382 { 1383 struct TALER_EXCHANGE_AuditorInformation *aix = &key_data->auditors[j]; 1384 1385 if (0 == GNUNET_memcmp (&ai.auditor_pub, 1386 &aix->auditor_pub)) 1387 { 1388 found = true; 1389 /* Merge denomination key signatures of downloaded /keys into existing 1390 auditor information 'aix'. */ 1391 TALER_LOG_DEBUG ( 1392 "Merging %u new audited keys with %u known audited keys\n", 1393 aix->num_denom_keys, 1394 ai.num_denom_keys); 1395 for (unsigned int i = 0; i<ai.num_denom_keys; i++) 1396 { 1397 bool kfound = false; 1398 1399 for (unsigned int k = 0; k<aix->num_denom_keys; k++) 1400 { 1401 if (aix->denom_keys[k].denom_key_offset == 1402 ai.denom_keys[i].denom_key_offset) 1403 { 1404 kfound = true; 1405 break; 1406 } 1407 } 1408 if (! kfound) 1409 GNUNET_array_append (aix->denom_keys, 1410 aix->num_denom_keys, 1411 ai.denom_keys[i]); 1412 } 1413 break; 1414 } 1415 } 1416 if (found) 1417 { 1418 GNUNET_array_grow (ai.denom_keys, 1419 ai.num_denom_keys, 1420 0); 1421 GNUNET_free (ai.auditor_url); 1422 GNUNET_free (ai.auditor_name); 1423 continue; /* we are done */ 1424 } 1425 if (key_data->auditors_size == key_data->num_auditors) 1426 GNUNET_array_grow (key_data->auditors, 1427 key_data->auditors_size, 1428 key_data->auditors_size * 2 + 2); 1429 GNUNET_assert (key_data->auditors_size > 1430 key_data->num_auditors); 1431 GNUNET_assert (NULL != ai.auditor_url); 1432 GNUNET_assert (key_data->num_auditors < UINT_MAX); 1433 key_data->auditors[key_data->num_auditors++] = ai; 1434 }; 1435 } 1436 1437 /* parse the revocation/recoup information */ 1438 if (NULL != recoup_array) 1439 { 1440 json_t *recoup_info; 1441 unsigned int index; 1442 1443 json_array_foreach (recoup_array, index, recoup_info) 1444 { 1445 struct TALER_DenominationHashP h_denom_pub; 1446 struct GNUNET_JSON_Specification spec[] = { 1447 GNUNET_JSON_spec_fixed_auto ("h_denom_pub", 1448 &h_denom_pub), 1449 GNUNET_JSON_spec_end () 1450 }; 1451 1452 EXITIF (GNUNET_OK != 1453 GNUNET_JSON_parse (recoup_info, 1454 spec, 1455 NULL, NULL)); 1456 for (unsigned int j = 0; 1457 j<key_data->num_denom_keys; 1458 j++) 1459 { 1460 if (0 == GNUNET_memcmp (&h_denom_pub, 1461 &key_data->denom_keys[j].h_key)) 1462 { 1463 key_data->denom_keys[j].revoked = true; 1464 break; 1465 } 1466 } 1467 } 1468 } 1469 1470 if (check_sig) 1471 { 1472 struct GNUNET_HashContext *hash_context; 1473 struct GNUNET_HashCode hc; 1474 1475 hash_context = GNUNET_CRYPTO_hash_context_start (); 1476 qsort (sig_ctx.elements, 1477 sig_ctx.elements_pos, 1478 sizeof (struct SignatureElement), 1479 &signature_context_sort_cb); 1480 for (unsigned int i = 0; i<sig_ctx.elements_pos; i++) 1481 { 1482 struct SignatureElement *element = &sig_ctx.elements[i]; 1483 1484 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1485 "Adding %u,%u,%s\n", 1486 element->group_offset, 1487 element->offset, 1488 TALER_B2S (&element->master_sig)); 1489 GNUNET_CRYPTO_hash_context_read (hash_context, 1490 &element->master_sig, 1491 sizeof (element->master_sig)); 1492 } 1493 GNUNET_array_grow (sig_ctx.elements, 1494 sig_ctx.elements_size, 1495 0); 1496 GNUNET_CRYPTO_hash_context_finish (hash_context, 1497 &hc); 1498 EXITIF (GNUNET_OK != 1499 TALER_EXCHANGE_test_signing_key (key_data, 1500 &exchange_pub)); 1501 EXITIF (GNUNET_OK != 1502 TALER_exchange_online_key_set_verify ( 1503 key_data->list_issue_date, 1504 &hc, 1505 &exchange_pub, 1506 &exchange_sig)); 1507 } 1508 return GNUNET_OK; 1509 1510 EXITIF_exit: 1511 GNUNET_array_grow (sig_ctx.elements, 1512 sig_ctx.elements_size, 1513 0); 1514 *vc = TALER_EXCHANGE_VC_PROTOCOL_ERROR; 1515 return GNUNET_SYSERR; 1516 } 1517 1518 1519 enum GNUNET_GenericReturnValue 1520 TALER_EXCHANGE_test_signing_key ( 1521 const struct TALER_EXCHANGE_Keys *keys, 1522 const struct TALER_ExchangePublicKeyP *pub) 1523 { 1524 struct GNUNET_TIME_Absolute now; 1525 1526 /* we will check using a tolerance of 1h for the time */ 1527 now = GNUNET_TIME_absolute_get (); 1528 for (unsigned int i = 0; i<keys->num_sign_keys; i++) 1529 if ( (GNUNET_TIME_absolute_cmp ( 1530 keys->sign_keys[i].valid_from.abs_time, 1531 <=, 1532 GNUNET_TIME_absolute_add (now, 1533 LIFETIME_TOLERANCE))) && 1534 (GNUNET_TIME_absolute_cmp ( 1535 keys->sign_keys[i].valid_until.abs_time, 1536 >, 1537 GNUNET_TIME_absolute_subtract (now, 1538 LIFETIME_TOLERANCE))) && 1539 (0 == GNUNET_memcmp (pub, 1540 &keys->sign_keys[i].key)) ) 1541 return GNUNET_OK; 1542 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1543 "Signing key not valid at time %s\n", 1544 GNUNET_TIME_absolute2s (now)); 1545 return GNUNET_SYSERR; 1546 } 1547 1548 1549 const struct TALER_EXCHANGE_DenomPublicKey * 1550 TALER_EXCHANGE_get_denomination_key ( 1551 const struct TALER_EXCHANGE_Keys *keys, 1552 const struct TALER_DenominationPublicKey *pk) 1553 { 1554 for (unsigned int i = 0; i<keys->num_denom_keys; i++) 1555 if (0 == 1556 TALER_denom_pub_cmp (pk, 1557 &keys->denom_keys[i].key)) 1558 return &keys->denom_keys[i]; 1559 return NULL; 1560 } 1561 1562 1563 const struct TALER_EXCHANGE_GlobalFee * 1564 TALER_EXCHANGE_get_global_fee ( 1565 const struct TALER_EXCHANGE_Keys *keys, 1566 struct GNUNET_TIME_Timestamp ts) 1567 { 1568 for (unsigned int i = 0; i<keys->num_global_fees; i++) 1569 { 1570 const struct TALER_EXCHANGE_GlobalFee *gf = &keys->global_fees[i]; 1571 1572 if (GNUNET_TIME_timestamp_cmp (ts, 1573 >=, 1574 gf->start_date) && 1575 GNUNET_TIME_timestamp_cmp (ts, 1576 <, 1577 gf->end_date)) 1578 return gf; 1579 } 1580 return NULL; 1581 } 1582 1583 1584 struct TALER_EXCHANGE_DenomPublicKey * 1585 TALER_EXCHANGE_copy_denomination_key ( 1586 const struct TALER_EXCHANGE_DenomPublicKey *key) 1587 { 1588 struct TALER_EXCHANGE_DenomPublicKey *copy; 1589 1590 copy = GNUNET_new (struct TALER_EXCHANGE_DenomPublicKey); 1591 *copy = *key; 1592 TALER_denom_pub_copy (©->key, 1593 &key->key); 1594 return copy; 1595 } 1596 1597 1598 void 1599 TALER_EXCHANGE_destroy_denomination_key ( 1600 struct TALER_EXCHANGE_DenomPublicKey *key) 1601 { 1602 TALER_denom_pub_free (&key->key); 1603 GNUNET_free (key); 1604 } 1605 1606 1607 const struct TALER_EXCHANGE_DenomPublicKey * 1608 TALER_EXCHANGE_get_denomination_key_by_hash ( 1609 const struct TALER_EXCHANGE_Keys *keys, 1610 const struct TALER_DenominationHashP *hc) 1611 { 1612 /* FIXME-optimization: should we maybe use a hash map here? */ 1613 for (unsigned int i = 0; i<keys->num_denom_keys; i++) 1614 if (0 == GNUNET_memcmp (hc, 1615 &keys->denom_keys[i].h_key)) 1616 return &keys->denom_keys[i]; 1617 return NULL; 1618 } 1619 1620 1621 struct TALER_EXCHANGE_Keys * 1622 TALER_EXCHANGE_keys_incref (struct TALER_EXCHANGE_Keys *keys) 1623 { 1624 GNUNET_assert (keys->rc < UINT_MAX); 1625 keys->rc++; 1626 return keys; 1627 } 1628 1629 1630 void 1631 TALER_EXCHANGE_keys_decref (struct TALER_EXCHANGE_Keys *keys) 1632 { 1633 if (NULL == keys) 1634 return; 1635 GNUNET_assert (0 < keys->rc); 1636 keys->rc--; 1637 if (0 != keys->rc) 1638 return; 1639 GNUNET_array_grow (keys->sign_keys, 1640 keys->num_sign_keys, 1641 0); 1642 for (unsigned int i = 0; i<keys->num_denom_keys; i++) 1643 TALER_denom_pub_free (&keys->denom_keys[i].key); 1644 keys->num_denom_keys = 0; 1645 GNUNET_array_grow (keys->denom_keys, 1646 keys->denom_keys_size, 1647 0); 1648 for (unsigned int i = 0; i<keys->num_auditors; i++) 1649 { 1650 GNUNET_array_grow (keys->auditors[i].denom_keys, 1651 keys->auditors[i].num_denom_keys, 1652 0); 1653 GNUNET_free (keys->auditors[i].auditor_url); 1654 GNUNET_free (keys->auditors[i].auditor_name); 1655 } 1656 GNUNET_array_grow (keys->auditors, 1657 keys->auditors_size, 1658 0); 1659 TALER_EXCHANGE_free_accounts (keys->accounts_len, 1660 keys->accounts); 1661 GNUNET_array_grow (keys->accounts, 1662 keys->accounts_len, 1663 0); 1664 free_fees (keys->fees, 1665 keys->fees_len); 1666 GNUNET_array_grow (keys->hard_limits, 1667 keys->hard_limits_length, 1668 0); 1669 GNUNET_array_grow (keys->zero_limits, 1670 keys->zero_limits_length, 1671 0); 1672 GNUNET_free (keys->cspec.name); 1673 json_decref (keys->cspec.map_alt_unit_names); 1674 GNUNET_array_grow (keys->cspec.common_amounts, 1675 keys->cspec.num_common_amounts, 1676 0); 1677 GNUNET_free (keys->wallet_balance_limit_without_kyc); 1678 GNUNET_free (keys->version); 1679 GNUNET_free (keys->currency); 1680 GNUNET_free (keys->asset_type); 1681 GNUNET_free (keys->shopping_url); 1682 GNUNET_free (keys->bank_compliance_language); 1683 for (unsigned int i = 0; i < keys->num_wad_partners; i++) 1684 GNUNET_free (keys->wad_partners[i].partner_base_url); 1685 GNUNET_free (keys->wad_partners); 1686 GNUNET_free (keys->global_fees); 1687 GNUNET_free (keys->exchange_url); 1688 GNUNET_free (keys); 1689 } 1690 1691 1692 struct TALER_EXCHANGE_Keys * 1693 TALER_EXCHANGE_keys_from_json (const json_t *j) 1694 { 1695 const json_t *jkeys; 1696 const char *url; 1697 uint32_t version; 1698 struct GNUNET_TIME_Timestamp expire 1699 = GNUNET_TIME_UNIT_ZERO_TS; 1700 struct GNUNET_JSON_Specification spec[] = { 1701 GNUNET_JSON_spec_uint32 ("version", 1702 &version), 1703 GNUNET_JSON_spec_object_const ("keys", 1704 &jkeys), 1705 TALER_JSON_spec_web_url ("exchange_url", 1706 &url), 1707 GNUNET_JSON_spec_mark_optional ( 1708 GNUNET_JSON_spec_timestamp ("expire", 1709 &expire), 1710 NULL), 1711 GNUNET_JSON_spec_end () 1712 }; 1713 struct TALER_EXCHANGE_Keys *keys; 1714 enum TALER_EXCHANGE_VersionCompatibility compat; 1715 1716 if (NULL == j) 1717 return NULL; 1718 if (GNUNET_OK != 1719 GNUNET_JSON_parse (j, 1720 spec, 1721 NULL, NULL)) 1722 { 1723 GNUNET_break_op (0); 1724 return NULL; 1725 } 1726 if (0 != version) 1727 { 1728 return NULL; /* unsupported version */ 1729 } 1730 keys = GNUNET_new (struct TALER_EXCHANGE_Keys); 1731 keys->rc = 1; 1732 keys->key_data_expiration = expire; 1733 keys->exchange_url = GNUNET_strdup (url); 1734 if (GNUNET_OK != 1735 TALER_EXCHANGE_decode_keys_json_ (jkeys, 1736 false, 1737 keys, 1738 &compat)) 1739 { 1740 GNUNET_break (0); 1741 TALER_EXCHANGE_keys_decref (keys); 1742 return NULL; 1743 } 1744 return keys; 1745 } 1746 1747 1748 /** 1749 * Data we track per denomination group. 1750 */ 1751 struct GroupData 1752 { 1753 /** 1754 * The json blob with the group meta-data and list of denominations 1755 */ 1756 json_t *json; 1757 1758 /** 1759 * Meta data for this group. 1760 */ 1761 struct TALER_DenominationGroup meta; 1762 }; 1763 1764 1765 /** 1766 * Add denomination group represented by @a value 1767 * to list of denominations in @a cls. Also frees 1768 * the @a value. 1769 * 1770 * @param[in,out] cls a `json_t *` with an array to build 1771 * @param key unused 1772 * @param value a `struct GroupData *` 1773 * @return #GNUNET_OK (continue to iterate) 1774 */ 1775 static enum GNUNET_GenericReturnValue 1776 add_grp (void *cls, 1777 const struct GNUNET_HashCode *key, 1778 void *value) 1779 { 1780 json_t *denominations_by_group = cls; 1781 struct GroupData *gd = value; 1782 const char *cipher; 1783 json_t *ge; 1784 bool age_restricted = gd->meta.age_mask.bits != 0; 1785 1786 (void) key; 1787 switch (gd->meta.cipher) 1788 { 1789 case GNUNET_CRYPTO_BSA_RSA: 1790 cipher = age_restricted ? "RSA+age_restricted" : "RSA"; 1791 break; 1792 case GNUNET_CRYPTO_BSA_CS: 1793 cipher = age_restricted ? "CS+age_restricted" : "CS"; 1794 break; 1795 default: 1796 GNUNET_assert (false); 1797 } 1798 1799 ge = GNUNET_JSON_PACK ( 1800 GNUNET_JSON_pack_string ("cipher", 1801 cipher), 1802 GNUNET_JSON_pack_array_steal ("denoms", 1803 gd->json), 1804 TALER_JSON_PACK_DENOM_FEES ("fee", 1805 &gd->meta.fees), 1806 GNUNET_JSON_pack_allow_null ( 1807 age_restricted 1808 ? GNUNET_JSON_pack_uint64 ("age_mask", 1809 gd->meta.age_mask.bits) 1810 : GNUNET_JSON_pack_string ("dummy", 1811 NULL)), 1812 TALER_JSON_pack_amount ("value", 1813 &gd->meta.value)); 1814 GNUNET_assert (0 == 1815 json_array_append_new (denominations_by_group, 1816 ge)); 1817 GNUNET_free (gd); 1818 return GNUNET_OK; 1819 } 1820 1821 1822 /** 1823 * Convert array of account restrictions @a ars to JSON. 1824 * 1825 * @param ar_len length of @a ars 1826 * @param ars account restrictions to convert 1827 * @return JSON representation 1828 */ 1829 static json_t * 1830 ar_to_json (unsigned int ar_len, 1831 const struct TALER_EXCHANGE_AccountRestriction ars[static ar_len]) 1832 { 1833 json_t *rval; 1834 1835 rval = json_array (); 1836 GNUNET_assert (NULL != rval); 1837 for (unsigned int i = 0; i<ar_len; i++) 1838 { 1839 const struct TALER_EXCHANGE_AccountRestriction *ar = &ars[i]; 1840 1841 switch (ar->type) 1842 { 1843 case TALER_EXCHANGE_AR_INVALID: 1844 GNUNET_break (0); 1845 json_decref (rval); 1846 return NULL; 1847 case TALER_EXCHANGE_AR_DENY: 1848 GNUNET_assert ( 1849 0 == 1850 json_array_append_new ( 1851 rval, 1852 GNUNET_JSON_PACK ( 1853 GNUNET_JSON_pack_string ("type", 1854 "deny")))); 1855 break; 1856 case TALER_EXCHANGE_AR_REGEX: 1857 GNUNET_assert ( 1858 0 == 1859 json_array_append_new ( 1860 rval, 1861 GNUNET_JSON_PACK ( 1862 GNUNET_JSON_pack_string ( 1863 "type", 1864 "regex"), 1865 GNUNET_JSON_pack_string ( 1866 "payto_regex", 1867 ar->details.regex.posix_egrep), 1868 GNUNET_JSON_pack_string ( 1869 "human_hint", 1870 ar->details.regex.human_hint), 1871 GNUNET_JSON_pack_object_incref ( 1872 "human_hint_i18n", 1873 (json_t *) ar->details.regex.human_hint_i18n) 1874 ))); 1875 break; 1876 } 1877 } 1878 return rval; 1879 } 1880 1881 1882 json_t * 1883 TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd) 1884 { 1885 struct GNUNET_TIME_Timestamp now; 1886 json_t *keys; 1887 json_t *signkeys; 1888 json_t *denominations_by_group; 1889 json_t *auditors; 1890 json_t *recoup; 1891 json_t *wire_fees; 1892 json_t *accounts; 1893 json_t *global_fees; 1894 json_t *wblwk = NULL; 1895 json_t *wads_json; 1896 json_t *hard_limits; 1897 json_t *zero_limits; 1898 1899 now = GNUNET_TIME_timestamp_get (); 1900 signkeys = json_array (); 1901 GNUNET_assert (NULL != signkeys); 1902 for (unsigned int i = 0; i<kd->num_sign_keys; i++) 1903 { 1904 const struct TALER_EXCHANGE_SigningPublicKey *sk = &kd->sign_keys[i]; 1905 json_t *signkey; 1906 1907 if (GNUNET_TIME_timestamp_cmp (now, 1908 >, 1909 sk->valid_until)) 1910 continue; /* skip keys that have expired */ 1911 signkey = GNUNET_JSON_PACK ( 1912 GNUNET_JSON_pack_data_auto ("key", 1913 &sk->key), 1914 GNUNET_JSON_pack_data_auto ("master_sig", 1915 &sk->master_sig), 1916 GNUNET_JSON_pack_timestamp ("stamp_start", 1917 sk->valid_from), 1918 GNUNET_JSON_pack_timestamp ("stamp_expire", 1919 sk->valid_until), 1920 GNUNET_JSON_pack_timestamp ("stamp_end", 1921 sk->valid_legal)); 1922 GNUNET_assert (NULL != signkey); 1923 GNUNET_assert (0 == 1924 json_array_append_new (signkeys, 1925 signkey)); 1926 } 1927 1928 denominations_by_group = json_array (); 1929 GNUNET_assert (NULL != denominations_by_group); 1930 { 1931 struct GNUNET_CONTAINER_MultiHashMap *dbg; 1932 1933 dbg = GNUNET_CONTAINER_multihashmap_create (128, 1934 false); 1935 for (unsigned int i = 0; i<kd->num_denom_keys; i++) 1936 { 1937 const struct TALER_EXCHANGE_DenomPublicKey *dk = &kd->denom_keys[i]; 1938 struct TALER_DenominationGroup meta = { 1939 .cipher = dk->key.bsign_pub_key->cipher, 1940 .value = dk->value, 1941 .fees = dk->fees, 1942 .age_mask = dk->key.age_mask 1943 }; 1944 struct GNUNET_HashCode key; 1945 struct GroupData *gd; 1946 json_t *denom; 1947 struct GNUNET_JSON_PackSpec key_spec; 1948 1949 if (GNUNET_TIME_timestamp_cmp (now, 1950 >, 1951 dk->expire_deposit)) 1952 continue; /* skip keys that have expired */ 1953 TALER_denomination_group_get_key (&meta, 1954 &key); 1955 gd = GNUNET_CONTAINER_multihashmap_get (dbg, 1956 &key); 1957 if (NULL == gd) 1958 { 1959 gd = GNUNET_new (struct GroupData); 1960 gd->meta = meta; 1961 gd->json = json_array (); 1962 GNUNET_assert (NULL != gd->json); 1963 GNUNET_assert ( 1964 GNUNET_OK == 1965 GNUNET_CONTAINER_multihashmap_put (dbg, 1966 &key, 1967 gd, 1968 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 1969 1970 } 1971 switch (meta.cipher) 1972 { 1973 case GNUNET_CRYPTO_BSA_RSA: 1974 key_spec = 1975 GNUNET_JSON_pack_rsa_public_key ( 1976 "rsa_pub", 1977 dk->key.bsign_pub_key->details.rsa_public_key); 1978 break; 1979 case GNUNET_CRYPTO_BSA_CS: 1980 key_spec = 1981 GNUNET_JSON_pack_data_varsize ( 1982 "cs_pub", 1983 &dk->key.bsign_pub_key->details.cs_public_key, 1984 sizeof (dk->key.bsign_pub_key->details.cs_public_key)); 1985 break; 1986 default: 1987 GNUNET_assert (false); 1988 } 1989 denom = GNUNET_JSON_PACK ( 1990 GNUNET_JSON_pack_timestamp ("stamp_expire_deposit", 1991 dk->expire_deposit), 1992 GNUNET_JSON_pack_timestamp ("stamp_expire_withdraw", 1993 dk->withdraw_valid_until), 1994 GNUNET_JSON_pack_timestamp ("stamp_start", 1995 dk->valid_from), 1996 GNUNET_JSON_pack_timestamp ("stamp_expire_legal", 1997 dk->expire_legal), 1998 GNUNET_JSON_pack_data_auto ("master_sig", 1999 &dk->master_sig), 2000 key_spec 2001 ); 2002 GNUNET_assert (0 == 2003 json_array_append_new (gd->json, 2004 denom)); 2005 } 2006 GNUNET_CONTAINER_multihashmap_iterate (dbg, 2007 &add_grp, 2008 denominations_by_group); 2009 GNUNET_CONTAINER_multihashmap_destroy (dbg); 2010 } 2011 2012 auditors = json_array (); 2013 GNUNET_assert (NULL != auditors); 2014 for (unsigned int i = 0; i<kd->num_auditors; i++) 2015 { 2016 const struct TALER_EXCHANGE_AuditorInformation *ai = &kd->auditors[i]; 2017 json_t *a; 2018 json_t *adenoms; 2019 2020 adenoms = json_array (); 2021 GNUNET_assert (NULL != adenoms); 2022 for (unsigned int j = 0; j<ai->num_denom_keys; j++) 2023 { 2024 const struct TALER_EXCHANGE_AuditorDenominationInfo *adi = 2025 &ai->denom_keys[j]; 2026 const struct TALER_EXCHANGE_DenomPublicKey *dk = 2027 &kd->denom_keys[adi->denom_key_offset]; 2028 json_t *k; 2029 2030 GNUNET_assert (adi->denom_key_offset < kd->num_denom_keys); 2031 if (GNUNET_TIME_timestamp_cmp (now, 2032 >, 2033 dk->expire_deposit)) 2034 continue; /* skip auditor signatures for denomination keys that have expired */ 2035 GNUNET_assert (adi->denom_key_offset < kd->num_denom_keys); 2036 k = GNUNET_JSON_PACK ( 2037 GNUNET_JSON_pack_data_auto ("denom_pub_h", 2038 &dk->h_key), 2039 GNUNET_JSON_pack_data_auto ("auditor_sig", 2040 &adi->auditor_sig)); 2041 GNUNET_assert (0 == 2042 json_array_append_new (adenoms, 2043 k)); 2044 } 2045 2046 a = GNUNET_JSON_PACK ( 2047 GNUNET_JSON_pack_data_auto ("auditor_pub", 2048 &ai->auditor_pub), 2049 GNUNET_JSON_pack_string ("auditor_url", 2050 ai->auditor_url), 2051 GNUNET_JSON_pack_string ("auditor_name", 2052 ai->auditor_name), 2053 GNUNET_JSON_pack_array_steal ("denomination_keys", 2054 adenoms)); 2055 GNUNET_assert (0 == 2056 json_array_append_new (auditors, 2057 a)); 2058 } 2059 2060 global_fees = json_array (); 2061 GNUNET_assert (NULL != global_fees); 2062 for (unsigned int i = 0; i<kd->num_global_fees; i++) 2063 { 2064 const struct TALER_EXCHANGE_GlobalFee *gf 2065 = &kd->global_fees[i]; 2066 2067 if (GNUNET_TIME_absolute_is_past (gf->end_date.abs_time)) 2068 continue; 2069 GNUNET_assert ( 2070 0 == 2071 json_array_append_new ( 2072 global_fees, 2073 GNUNET_JSON_PACK ( 2074 GNUNET_JSON_pack_timestamp ("start_date", 2075 gf->start_date), 2076 GNUNET_JSON_pack_timestamp ("end_date", 2077 gf->end_date), 2078 TALER_JSON_PACK_GLOBAL_FEES (&gf->fees), 2079 GNUNET_JSON_pack_time_rel ("history_expiration", 2080 gf->history_expiration), 2081 GNUNET_JSON_pack_time_rel ("purse_timeout", 2082 gf->purse_timeout), 2083 GNUNET_JSON_pack_uint64 ("purse_account_limit", 2084 gf->purse_account_limit), 2085 GNUNET_JSON_pack_data_auto ("master_sig", 2086 &gf->master_sig)))); 2087 } 2088 2089 accounts = json_array (); 2090 GNUNET_assert (NULL != accounts); 2091 for (unsigned int i = 0; i<kd->accounts_len; i++) 2092 { 2093 const struct TALER_EXCHANGE_WireAccount *acc 2094 = &kd->accounts[i]; 2095 json_t *credit_restrictions; 2096 json_t *debit_restrictions; 2097 2098 credit_restrictions 2099 = ar_to_json (acc->credit_restrictions_length, 2100 acc->credit_restrictions); 2101 GNUNET_assert (NULL != credit_restrictions); 2102 debit_restrictions 2103 = ar_to_json (acc->debit_restrictions_length, 2104 acc->debit_restrictions); 2105 GNUNET_assert (NULL != debit_restrictions); 2106 GNUNET_assert ( 2107 0 == 2108 json_array_append_new ( 2109 accounts, 2110 GNUNET_JSON_PACK ( 2111 TALER_JSON_pack_full_payto ("payto_uri", 2112 acc->fpayto_uri), 2113 GNUNET_JSON_pack_allow_null ( 2114 GNUNET_JSON_pack_string ("conversion_url", 2115 acc->conversion_url)), 2116 GNUNET_JSON_pack_allow_null ( 2117 GNUNET_JSON_pack_string ("open_banking_gateway", 2118 acc->open_banking_gateway)), 2119 GNUNET_JSON_pack_allow_null ( 2120 GNUNET_JSON_pack_string ("prepared_transfer_url", 2121 acc->prepared_transfer_url)), 2122 GNUNET_JSON_pack_int64 ("priority", 2123 acc->priority), 2124 GNUNET_JSON_pack_allow_null ( 2125 GNUNET_JSON_pack_string ("bank_label", 2126 acc->bank_label)), 2127 GNUNET_JSON_pack_array_steal ("debit_restrictions", 2128 debit_restrictions), 2129 GNUNET_JSON_pack_array_steal ("credit_restrictions", 2130 credit_restrictions), 2131 GNUNET_JSON_pack_data_auto ("master_sig", 2132 &acc->master_sig)))); 2133 } 2134 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2135 "Serialized %u/%u wire accounts to JSON\n", 2136 (unsigned int) json_array_size (accounts), 2137 kd->accounts_len); 2138 2139 wire_fees = json_object (); 2140 GNUNET_assert (NULL != wire_fees); 2141 for (unsigned int i = 0; i<kd->fees_len; i++) 2142 { 2143 const struct TALER_EXCHANGE_WireFeesByMethod *fbw 2144 = &kd->fees[i]; 2145 json_t *wf; 2146 2147 wf = json_array (); 2148 GNUNET_assert (NULL != wf); 2149 for (struct TALER_EXCHANGE_WireAggregateFees *p = fbw->fees_head; 2150 NULL != p; 2151 p = p->next) 2152 { 2153 GNUNET_assert ( 2154 0 == 2155 json_array_append_new ( 2156 wf, 2157 GNUNET_JSON_PACK ( 2158 TALER_JSON_pack_amount ("wire_fee", 2159 &p->fees.wire), 2160 TALER_JSON_pack_amount ("closing_fee", 2161 &p->fees.closing), 2162 GNUNET_JSON_pack_timestamp ("start_date", 2163 p->start_date), 2164 GNUNET_JSON_pack_timestamp ("end_date", 2165 p->end_date), 2166 GNUNET_JSON_pack_data_auto ("sig", 2167 &p->master_sig)))); 2168 } 2169 GNUNET_assert (0 == 2170 json_object_set_new (wire_fees, 2171 fbw->method, 2172 wf)); 2173 } 2174 2175 recoup = json_array (); 2176 GNUNET_assert (NULL != recoup); 2177 for (unsigned int i = 0; i<kd->num_denom_keys; i++) 2178 { 2179 const struct TALER_EXCHANGE_DenomPublicKey *dk 2180 = &kd->denom_keys[i]; 2181 if (! dk->revoked) 2182 continue; 2183 GNUNET_assert (0 == 2184 json_array_append_new ( 2185 recoup, 2186 GNUNET_JSON_PACK ( 2187 GNUNET_JSON_pack_data_auto ("h_denom_pub", 2188 &dk->h_key)))); 2189 } 2190 2191 wblwk = json_array (); 2192 GNUNET_assert (NULL != wblwk); 2193 for (unsigned int i = 0; i<kd->wblwk_length; i++) 2194 { 2195 const struct TALER_Amount *a = &kd->wallet_balance_limit_without_kyc[i]; 2196 2197 GNUNET_assert (0 == 2198 json_array_append_new ( 2199 wblwk, 2200 TALER_JSON_from_amount (a))); 2201 } 2202 2203 hard_limits = json_array (); 2204 for (unsigned int i = 0; i < kd->hard_limits_length; i++) 2205 { 2206 const struct TALER_EXCHANGE_AccountLimit *al 2207 = &kd->hard_limits[i]; 2208 json_t *j; 2209 2210 j = GNUNET_JSON_PACK ( 2211 TALER_JSON_pack_amount ("threshold", 2212 &al->threshold), 2213 GNUNET_JSON_pack_time_rel ("timeframe", 2214 al->timeframe), 2215 TALER_JSON_pack_kycte ("operation_type", 2216 al->operation_type), 2217 GNUNET_JSON_pack_bool ("soft_limit", 2218 al->soft_limit) 2219 ); 2220 GNUNET_assert (0 == 2221 json_array_append_new ( 2222 hard_limits, 2223 j)); 2224 } 2225 2226 zero_limits = json_array (); 2227 for (unsigned int i = 0; i < kd->zero_limits_length; i++) 2228 { 2229 const struct TALER_EXCHANGE_ZeroLimitedOperation *zol 2230 = &kd->zero_limits[i]; 2231 json_t *j; 2232 2233 j = GNUNET_JSON_PACK ( 2234 TALER_JSON_pack_kycte ("operation_type", 2235 zol->operation_type) 2236 ); 2237 GNUNET_assert (0 == 2238 json_array_append_new ( 2239 zero_limits, 2240 j)); 2241 } 2242 2243 wads_json = json_array (); 2244 GNUNET_assert (NULL != wads_json); 2245 for (unsigned int i = 0; i < kd->num_wad_partners; i++) 2246 { 2247 const struct TALER_EXCHANGE_WadPartner *wp 2248 = &kd->wad_partners[i]; 2249 2250 GNUNET_assert ( 2251 0 == 2252 json_array_append_new ( 2253 wads_json, 2254 GNUNET_JSON_PACK ( 2255 GNUNET_JSON_pack_string ("partner_base_url", 2256 wp->partner_base_url), 2257 GNUNET_JSON_pack_data_auto ("partner_master_pub", 2258 &wp->partner_master_pub), 2259 TALER_JSON_pack_amount ("wad_fee", 2260 &wp->wad_fee), 2261 GNUNET_JSON_pack_time_rel ("wad_frequency", 2262 wp->wad_frequency), 2263 GNUNET_JSON_pack_timestamp ("start_date", 2264 wp->start_date), 2265 GNUNET_JSON_pack_timestamp ("end_date", 2266 wp->end_date), 2267 GNUNET_JSON_pack_data_auto ("master_sig", 2268 &wp->master_sig)))); 2269 } 2270 2271 keys = GNUNET_JSON_PACK ( 2272 GNUNET_JSON_pack_string ("version", 2273 kd->version), 2274 GNUNET_JSON_pack_string ("currency", 2275 kd->currency), 2276 GNUNET_JSON_pack_object_steal ("currency_specification", 2277 TALER_JSON_currency_specs_to_json ( 2278 &kd->cspec)), 2279 TALER_JSON_pack_amount ("stefan_abs", 2280 &kd->stefan_abs), 2281 TALER_JSON_pack_amount ("stefan_log", 2282 &kd->stefan_log), 2283 GNUNET_JSON_pack_double ("stefan_lin", 2284 kd->stefan_lin), 2285 GNUNET_JSON_pack_allow_null ( 2286 kd->tiny_amount_available 2287 ? TALER_JSON_pack_amount ("tiny_amount", 2288 &kd->tiny_amount) 2289 : GNUNET_JSON_pack_string ("dummy", 2290 NULL)), 2291 GNUNET_JSON_pack_string ("asset_type", 2292 kd->asset_type), 2293 GNUNET_JSON_pack_allow_null ( 2294 GNUNET_JSON_pack_string ("shopping_url", 2295 kd->shopping_url)), 2296 GNUNET_JSON_pack_allow_null ( 2297 GNUNET_JSON_pack_string ("bank_compliance_language", 2298 kd->bank_compliance_language)), 2299 GNUNET_JSON_pack_bool ("disable_direct_deposit", 2300 kd->disable_direct_deposit), 2301 GNUNET_JSON_pack_bool ("kyc_swap_tos_acceptance", 2302 kd->kyc_swap_tos_acceptance), 2303 GNUNET_JSON_pack_data_auto ("master_public_key", 2304 &kd->master_pub), 2305 GNUNET_JSON_pack_time_rel ("reserve_closing_delay", 2306 kd->reserve_closing_delay), 2307 GNUNET_JSON_pack_allow_null ( 2308 GNUNET_TIME_relative_is_zero (kd->default_p2p_push_expiration) 2309 ? GNUNET_JSON_pack_string ("dummy", 2310 NULL) 2311 : GNUNET_JSON_pack_time_rel ("default_p2p_push_expiration", 2312 kd->default_p2p_push_expiration)), 2313 GNUNET_JSON_pack_timestamp ("list_issue_date", 2314 kd->list_issue_date), 2315 GNUNET_JSON_pack_array_steal ("global_fees", 2316 global_fees), 2317 GNUNET_JSON_pack_array_steal ("signkeys", 2318 signkeys), 2319 GNUNET_JSON_pack_object_steal ("wire_fees", 2320 wire_fees), 2321 GNUNET_JSON_pack_array_steal ("accounts", 2322 accounts), 2323 GNUNET_JSON_pack_array_steal ("wads", 2324 wads_json), 2325 GNUNET_JSON_pack_array_steal ("hard_limits", 2326 hard_limits), 2327 GNUNET_JSON_pack_array_steal ("zero_limits", 2328 zero_limits), 2329 GNUNET_JSON_pack_array_steal ("denominations", 2330 denominations_by_group), 2331 GNUNET_JSON_pack_allow_null ( 2332 GNUNET_JSON_pack_array_steal ("recoup", 2333 recoup)), 2334 GNUNET_JSON_pack_array_steal ("auditors", 2335 auditors), 2336 GNUNET_JSON_pack_bool ("kyc_enabled", 2337 kd->kyc_enabled), 2338 GNUNET_JSON_pack_allow_null ( 2339 GNUNET_JSON_pack_array_steal ("wallet_balance_limit_without_kyc", 2340 wblwk)) 2341 2342 ); 2343 return GNUNET_JSON_PACK ( 2344 GNUNET_JSON_pack_uint64 ("version", 2345 EXCHANGE_SERIALIZATION_FORMAT_VERSION), 2346 GNUNET_JSON_pack_allow_null ( 2347 GNUNET_JSON_pack_timestamp ("expire", 2348 kd->key_data_expiration)), 2349 GNUNET_JSON_pack_string ("exchange_url", 2350 kd->exchange_url), 2351 GNUNET_JSON_pack_object_steal ("keys", 2352 keys)); 2353 } 2354 2355 2356 /* end of exchange_api_handle.c */