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