exchange_api_handle.c (75424B)
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 33 40 41 /** 42 * How many versions are we backwards compatible with? 43 */ 44 #define EXCHANGE_PROTOCOL_AGE 0 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_string ( 1000 "currency", 1001 ¤cy), 1002 GNUNET_JSON_spec_string ( 1003 "asset_type", 1004 &asset_type), 1005 GNUNET_JSON_spec_array_const ( 1006 "global_fees", 1007 &global_fees), 1008 GNUNET_JSON_spec_array_const ( 1009 "signkeys", 1010 &sign_keys_array), 1011 GNUNET_JSON_spec_array_const ( 1012 "denominations", 1013 &denominations_by_group), 1014 GNUNET_JSON_spec_mark_optional ( 1015 GNUNET_JSON_spec_array_const ( 1016 "recoup", 1017 &recoup_array), 1018 NULL), 1019 GNUNET_JSON_spec_array_const ( 1020 "auditors", 1021 &auditors_array), 1022 GNUNET_JSON_spec_bool ( 1023 "kyc_enabled", 1024 &key_data->kyc_enabled), 1025 GNUNET_JSON_spec_mark_optional ( 1026 GNUNET_JSON_spec_object_const ("extensions", 1027 &manifests), 1028 &no_extensions), 1029 GNUNET_JSON_spec_mark_optional ( 1030 GNUNET_JSON_spec_fixed_auto ( 1031 "extensions_sig", 1032 &key_data->extensions_sig), 1033 &no_signature), 1034 GNUNET_JSON_spec_string ("version", 1035 &ver), 1036 GNUNET_JSON_spec_mark_optional ( 1037 GNUNET_JSON_spec_array_const ( 1038 "wallet_balance_limit_without_kyc", 1039 &wblwk), 1040 NULL), 1041 GNUNET_JSON_spec_mark_optional ( 1042 GNUNET_JSON_spec_string ("shopping_url", 1043 &shopping_url), 1044 NULL), 1045 GNUNET_JSON_spec_mark_optional ( 1046 GNUNET_JSON_spec_string ("bank_compliance_language", 1047 &bank_compliance_language), 1048 NULL), 1049 GNUNET_JSON_spec_mark_optional ( 1050 GNUNET_JSON_spec_bool ("disable_direct_deposit", 1051 &key_data->disable_direct_deposit), 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 if (! no_extensions) 1151 key_data->extensions = json_incref ((json_t *) manifests); 1152 } 1153 1154 /* parse the global fees */ 1155 EXITIF (json_array_size (global_fees) > UINT_MAX); 1156 key_data->num_global_fees 1157 = (unsigned int) json_array_size (global_fees); 1158 if (0 != key_data->num_global_fees) 1159 { 1160 json_t *global_fee; 1161 size_t index; 1162 1163 key_data->global_fees 1164 = GNUNET_new_array (key_data->num_global_fees, 1165 struct TALER_EXCHANGE_GlobalFee); 1166 json_array_foreach (global_fees, index, global_fee) 1167 { 1168 EXITIF (GNUNET_SYSERR == 1169 parse_global_fee (&key_data->global_fees[index], 1170 check_sig, 1171 global_fee, 1172 key_data)); 1173 } 1174 } 1175 1176 /* parse the signing keys */ 1177 EXITIF (json_array_size (sign_keys_array) > UINT_MAX); 1178 key_data->num_sign_keys 1179 = (unsigned int) json_array_size (sign_keys_array); 1180 if (0 != key_data->num_sign_keys) 1181 { 1182 json_t *sign_key_obj; 1183 size_t index; 1184 1185 key_data->sign_keys 1186 = GNUNET_new_array (key_data->num_sign_keys, 1187 struct TALER_EXCHANGE_SigningPublicKey); 1188 json_array_foreach (sign_keys_array, index, sign_key_obj) { 1189 EXITIF (GNUNET_SYSERR == 1190 parse_json_signkey (&key_data->sign_keys[index], 1191 check_sig, 1192 sign_key_obj, 1193 &key_data->master_pub)); 1194 } 1195 } 1196 1197 /* Parse balance limits */ 1198 if (NULL != wblwk) 1199 { 1200 EXITIF (json_array_size (wblwk) > UINT_MAX); 1201 key_data->wblwk_length 1202 = (unsigned int) json_array_size (wblwk); 1203 key_data->wallet_balance_limit_without_kyc 1204 = GNUNET_new_array (key_data->wblwk_length, 1205 struct TALER_Amount); 1206 for (unsigned int i = 0; i<key_data->wblwk_length; i++) 1207 { 1208 struct TALER_Amount *a = &key_data->wallet_balance_limit_without_kyc[i]; 1209 const json_t *aj = json_array_get (wblwk, 1210 i); 1211 struct GNUNET_JSON_Specification spec[] = { 1212 TALER_JSON_spec_amount (NULL, 1213 key_data->currency, 1214 a), 1215 GNUNET_JSON_spec_end () 1216 }; 1217 1218 EXITIF (GNUNET_OK != 1219 GNUNET_JSON_parse (aj, 1220 spec, 1221 NULL, NULL)); 1222 } 1223 } 1224 1225 /* Parse wire accounts */ 1226 key_data->fees = parse_fees (&key_data->master_pub, 1227 key_data->currency, 1228 fees, 1229 &key_data->fees_len); 1230 EXITIF (NULL == key_data->fees); 1231 /* parse accounts */ 1232 EXITIF (json_array_size (accounts) > UINT_MAX); 1233 GNUNET_array_grow (key_data->accounts, 1234 key_data->accounts_len, 1235 json_array_size (accounts)); 1236 EXITIF (GNUNET_OK != 1237 TALER_EXCHANGE_parse_accounts (&key_data->master_pub, 1238 accounts, 1239 key_data->accounts_len, 1240 key_data->accounts)); 1241 1242 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1243 "Parsed %u wire accounts from JSON\n", 1244 key_data->accounts_len); 1245 1246 /* Parse wad partners */ 1247 EXITIF (GNUNET_OK != 1248 parse_wads (wads, 1249 check_sig, 1250 key_data)); 1251 1252 1253 /* Parse the supported extension(s): age-restriction. */ 1254 /* FIXME[Oec]: maybe lift all this into a FP in TALER_Extension ? */ 1255 if (! no_extensions) 1256 { 1257 if (no_signature) 1258 { 1259 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1260 "found extensions without signature\n"); 1261 } 1262 else 1263 { 1264 /* We have an extensions object. Verify its signature. */ 1265 EXITIF (GNUNET_OK != 1266 TALER_extensions_verify_manifests_signature ( 1267 manifests, 1268 &key_data->extensions_sig, 1269 &key_data->master_pub)); 1270 1271 /* Parse and set the the configuration of the extensions accordingly */ 1272 EXITIF (GNUNET_OK != 1273 TALER_extensions_load_manifests (manifests)); 1274 } 1275 1276 /* Assuming we might have now a new value for age_mask, set it in key_data */ 1277 key_data->age_mask = TALER_extensions_get_age_restriction_mask (); 1278 } 1279 1280 /* 1281 * Parse the denomination keys, merging with the 1282 * possibly EXISTING array as required (/keys cherry picking). 1283 * 1284 * The denominations are grouped by common values of 1285 * {cipher, value, fee, age_mask}. 1286 */ 1287 { 1288 json_t *group_obj; 1289 unsigned int group_idx; 1290 1291 json_array_foreach (denominations_by_group, 1292 group_idx, 1293 group_obj) 1294 { 1295 /* First, parse { cipher, fees, value, age_mask, hash } of the current 1296 group. */ 1297 struct TALER_DenominationGroup group = {0}; 1298 const json_t *denom_keys_array; 1299 struct GNUNET_JSON_Specification group_spec[] = { 1300 TALER_JSON_spec_denomination_group (NULL, 1301 key_data->currency, 1302 &group), 1303 GNUNET_JSON_spec_array_const ("denoms", 1304 &denom_keys_array), 1305 GNUNET_JSON_spec_end () 1306 }; 1307 json_t *denom_key_obj; 1308 unsigned int index; 1309 1310 EXITIF (GNUNET_SYSERR == 1311 GNUNET_JSON_parse (group_obj, 1312 group_spec, 1313 NULL, 1314 NULL)); 1315 1316 /* Now, parse the individual denominations */ 1317 json_array_foreach (denom_keys_array, 1318 index, 1319 denom_key_obj) 1320 { 1321 /* Set the common fields from the group for this particular 1322 denomination. Required to make the validity check inside 1323 parse_json_denomkey_partially pass */ 1324 struct TALER_EXCHANGE_DenomPublicKey dk = { 1325 .value = group.value, 1326 .fees = group.fees, 1327 .key.age_mask = group.age_mask 1328 }; 1329 bool found = false; 1330 1331 EXITIF (GNUNET_SYSERR == 1332 parse_json_denomkey_partially (&dk, 1333 group.cipher, 1334 check_sig, 1335 denom_key_obj, 1336 &key_data->master_pub, 1337 group_idx, 1338 index, 1339 check_sig 1340 ? &sig_ctx 1341 : NULL)); 1342 for (unsigned int j = 0; 1343 j<key_data->num_denom_keys; 1344 j++) 1345 { 1346 if (0 == denoms_cmp (&dk, 1347 &key_data->denom_keys[j])) 1348 { 1349 found = true; 1350 break; 1351 } 1352 } 1353 1354 if (found) 1355 { 1356 /* 0:0:0 did not support /keys cherry picking */ 1357 TALER_LOG_DEBUG ("Skipping denomination key: already know it\n"); 1358 TALER_denom_pub_free (&dk.key); 1359 continue; 1360 } 1361 1362 if (key_data->denom_keys_size == key_data->num_denom_keys) 1363 GNUNET_array_grow (key_data->denom_keys, 1364 key_data->denom_keys_size, 1365 key_data->denom_keys_size * 2 + 2); 1366 GNUNET_assert (key_data->denom_keys_size > 1367 key_data->num_denom_keys); 1368 GNUNET_assert (key_data->num_denom_keys < UINT_MAX); 1369 key_data->denom_keys[key_data->num_denom_keys++] = dk; 1370 1371 /* Update "last_denom_issue_date" */ 1372 TALER_LOG_DEBUG ("Adding denomination key that is valid_until %s\n", 1373 GNUNET_TIME_timestamp2s (dk.valid_from)); 1374 key_data->last_denom_issue_date 1375 = GNUNET_TIME_timestamp_max (key_data->last_denom_issue_date, 1376 dk.valid_from); 1377 }; /* end of json_array_foreach over denominations */ 1378 } /* end of json_array_foreach over groups of denominations */ 1379 } /* end of scope for group_ojb/group_idx */ 1380 1381 /* parse the auditor information */ 1382 { 1383 json_t *auditor_info; 1384 unsigned int index; 1385 1386 /* Merge with the existing auditor information we have (/keys cherry picking) */ 1387 json_array_foreach (auditors_array, index, auditor_info) 1388 { 1389 struct TALER_EXCHANGE_AuditorInformation ai; 1390 bool found = false; 1391 1392 memset (&ai, 1393 0, 1394 sizeof (ai)); 1395 EXITIF (GNUNET_SYSERR == 1396 parse_json_auditor (&ai, 1397 check_sig, 1398 auditor_info, 1399 key_data)); 1400 for (unsigned int j = 0; j<key_data->num_auditors; j++) 1401 { 1402 struct TALER_EXCHANGE_AuditorInformation *aix = &key_data->auditors[j]; 1403 1404 if (0 == GNUNET_memcmp (&ai.auditor_pub, 1405 &aix->auditor_pub)) 1406 { 1407 found = true; 1408 /* Merge denomination key signatures of downloaded /keys into existing 1409 auditor information 'aix'. */ 1410 TALER_LOG_DEBUG ( 1411 "Merging %u new audited keys with %u known audited keys\n", 1412 aix->num_denom_keys, 1413 ai.num_denom_keys); 1414 for (unsigned int i = 0; i<ai.num_denom_keys; i++) 1415 { 1416 bool kfound = false; 1417 1418 for (unsigned int k = 0; k<aix->num_denom_keys; k++) 1419 { 1420 if (aix->denom_keys[k].denom_key_offset == 1421 ai.denom_keys[i].denom_key_offset) 1422 { 1423 kfound = true; 1424 break; 1425 } 1426 } 1427 if (! kfound) 1428 GNUNET_array_append (aix->denom_keys, 1429 aix->num_denom_keys, 1430 ai.denom_keys[i]); 1431 } 1432 break; 1433 } 1434 } 1435 if (found) 1436 { 1437 GNUNET_array_grow (ai.denom_keys, 1438 ai.num_denom_keys, 1439 0); 1440 GNUNET_free (ai.auditor_url); 1441 GNUNET_free (ai.auditor_name); 1442 continue; /* we are done */ 1443 } 1444 if (key_data->auditors_size == key_data->num_auditors) 1445 GNUNET_array_grow (key_data->auditors, 1446 key_data->auditors_size, 1447 key_data->auditors_size * 2 + 2); 1448 GNUNET_assert (key_data->auditors_size > 1449 key_data->num_auditors); 1450 GNUNET_assert (NULL != ai.auditor_url); 1451 GNUNET_assert (key_data->num_auditors < UINT_MAX); 1452 key_data->auditors[key_data->num_auditors++] = ai; 1453 }; 1454 } 1455 1456 /* parse the revocation/recoup information */ 1457 if (NULL != recoup_array) 1458 { 1459 json_t *recoup_info; 1460 unsigned int index; 1461 1462 json_array_foreach (recoup_array, index, recoup_info) 1463 { 1464 struct TALER_DenominationHashP h_denom_pub; 1465 struct GNUNET_JSON_Specification spec[] = { 1466 GNUNET_JSON_spec_fixed_auto ("h_denom_pub", 1467 &h_denom_pub), 1468 GNUNET_JSON_spec_end () 1469 }; 1470 1471 EXITIF (GNUNET_OK != 1472 GNUNET_JSON_parse (recoup_info, 1473 spec, 1474 NULL, NULL)); 1475 for (unsigned int j = 0; 1476 j<key_data->num_denom_keys; 1477 j++) 1478 { 1479 if (0 == GNUNET_memcmp (&h_denom_pub, 1480 &key_data->denom_keys[j].h_key)) 1481 { 1482 key_data->denom_keys[j].revoked = true; 1483 break; 1484 } 1485 } 1486 } 1487 } 1488 1489 if (check_sig) 1490 { 1491 struct GNUNET_HashContext *hash_context; 1492 struct GNUNET_HashCode hc; 1493 1494 hash_context = GNUNET_CRYPTO_hash_context_start (); 1495 qsort (sig_ctx.elements, 1496 sig_ctx.elements_pos, 1497 sizeof (struct SignatureElement), 1498 &signature_context_sort_cb); 1499 for (unsigned int i = 0; i<sig_ctx.elements_pos; i++) 1500 { 1501 struct SignatureElement *element = &sig_ctx.elements[i]; 1502 1503 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1504 "Adding %u,%u,%s\n", 1505 element->group_offset, 1506 element->offset, 1507 TALER_B2S (&element->master_sig)); 1508 GNUNET_CRYPTO_hash_context_read (hash_context, 1509 &element->master_sig, 1510 sizeof (element->master_sig)); 1511 } 1512 GNUNET_array_grow (sig_ctx.elements, 1513 sig_ctx.elements_size, 1514 0); 1515 GNUNET_CRYPTO_hash_context_finish (hash_context, 1516 &hc); 1517 EXITIF (GNUNET_OK != 1518 TALER_EXCHANGE_test_signing_key (key_data, 1519 &exchange_pub)); 1520 EXITIF (GNUNET_OK != 1521 TALER_exchange_online_key_set_verify ( 1522 key_data->list_issue_date, 1523 &hc, 1524 &exchange_pub, 1525 &exchange_sig)); 1526 } 1527 return GNUNET_OK; 1528 1529 EXITIF_exit: 1530 *vc = TALER_EXCHANGE_VC_PROTOCOL_ERROR; 1531 return GNUNET_SYSERR; 1532 } 1533 1534 1535 enum GNUNET_GenericReturnValue 1536 TALER_EXCHANGE_test_signing_key ( 1537 const struct TALER_EXCHANGE_Keys *keys, 1538 const struct TALER_ExchangePublicKeyP *pub) 1539 { 1540 struct GNUNET_TIME_Absolute now; 1541 1542 /* we will check using a tolerance of 1h for the time */ 1543 now = GNUNET_TIME_absolute_get (); 1544 for (unsigned int i = 0; i<keys->num_sign_keys; i++) 1545 if ( (GNUNET_TIME_absolute_cmp ( 1546 keys->sign_keys[i].valid_from.abs_time, 1547 <=, 1548 GNUNET_TIME_absolute_add (now, 1549 LIFETIME_TOLERANCE))) && 1550 (GNUNET_TIME_absolute_cmp ( 1551 keys->sign_keys[i].valid_until.abs_time, 1552 >, 1553 GNUNET_TIME_absolute_subtract (now, 1554 LIFETIME_TOLERANCE))) && 1555 (0 == GNUNET_memcmp (pub, 1556 &keys->sign_keys[i].key)) ) 1557 return GNUNET_OK; 1558 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1559 "Signing key not valid at time %s\n", 1560 GNUNET_TIME_absolute2s (now)); 1561 return GNUNET_SYSERR; 1562 } 1563 1564 1565 const struct TALER_EXCHANGE_DenomPublicKey * 1566 TALER_EXCHANGE_get_denomination_key ( 1567 const struct TALER_EXCHANGE_Keys *keys, 1568 const struct TALER_DenominationPublicKey *pk) 1569 { 1570 for (unsigned int i = 0; i<keys->num_denom_keys; i++) 1571 if (0 == 1572 TALER_denom_pub_cmp (pk, 1573 &keys->denom_keys[i].key)) 1574 return &keys->denom_keys[i]; 1575 return NULL; 1576 } 1577 1578 1579 const struct TALER_EXCHANGE_GlobalFee * 1580 TALER_EXCHANGE_get_global_fee ( 1581 const struct TALER_EXCHANGE_Keys *keys, 1582 struct GNUNET_TIME_Timestamp ts) 1583 { 1584 for (unsigned int i = 0; i<keys->num_global_fees; i++) 1585 { 1586 const struct TALER_EXCHANGE_GlobalFee *gf = &keys->global_fees[i]; 1587 1588 if (GNUNET_TIME_timestamp_cmp (ts, 1589 >=, 1590 gf->start_date) && 1591 GNUNET_TIME_timestamp_cmp (ts, 1592 <, 1593 gf->end_date)) 1594 return gf; 1595 } 1596 return NULL; 1597 } 1598 1599 1600 struct TALER_EXCHANGE_DenomPublicKey * 1601 TALER_EXCHANGE_copy_denomination_key ( 1602 const struct TALER_EXCHANGE_DenomPublicKey *key) 1603 { 1604 struct TALER_EXCHANGE_DenomPublicKey *copy; 1605 1606 copy = GNUNET_new (struct TALER_EXCHANGE_DenomPublicKey); 1607 *copy = *key; 1608 TALER_denom_pub_copy (©->key, 1609 &key->key); 1610 return copy; 1611 } 1612 1613 1614 void 1615 TALER_EXCHANGE_destroy_denomination_key ( 1616 struct TALER_EXCHANGE_DenomPublicKey *key) 1617 { 1618 TALER_denom_pub_free (&key->key); 1619 GNUNET_free (key); 1620 } 1621 1622 1623 const struct TALER_EXCHANGE_DenomPublicKey * 1624 TALER_EXCHANGE_get_denomination_key_by_hash ( 1625 const struct TALER_EXCHANGE_Keys *keys, 1626 const struct TALER_DenominationHashP *hc) 1627 { 1628 /* FIXME-optimization: should we maybe use a hash map here? */ 1629 for (unsigned int i = 0; i<keys->num_denom_keys; i++) 1630 if (0 == GNUNET_memcmp (hc, 1631 &keys->denom_keys[i].h_key)) 1632 return &keys->denom_keys[i]; 1633 return NULL; 1634 } 1635 1636 1637 struct TALER_EXCHANGE_Keys * 1638 TALER_EXCHANGE_keys_incref (struct TALER_EXCHANGE_Keys *keys) 1639 { 1640 GNUNET_assert (keys->rc < UINT_MAX); 1641 keys->rc++; 1642 return keys; 1643 } 1644 1645 1646 void 1647 TALER_EXCHANGE_keys_decref (struct TALER_EXCHANGE_Keys *keys) 1648 { 1649 if (NULL == keys) 1650 return; 1651 GNUNET_assert (0 < keys->rc); 1652 keys->rc--; 1653 if (0 != keys->rc) 1654 return; 1655 GNUNET_array_grow (keys->sign_keys, 1656 keys->num_sign_keys, 1657 0); 1658 for (unsigned int i = 0; i<keys->num_denom_keys; i++) 1659 TALER_denom_pub_free (&keys->denom_keys[i].key); 1660 keys->num_denom_keys = 0; 1661 GNUNET_array_grow (keys->denom_keys, 1662 keys->denom_keys_size, 1663 0); 1664 for (unsigned int i = 0; i<keys->num_auditors; i++) 1665 { 1666 GNUNET_array_grow (keys->auditors[i].denom_keys, 1667 keys->auditors[i].num_denom_keys, 1668 0); 1669 GNUNET_free (keys->auditors[i].auditor_url); 1670 GNUNET_free (keys->auditors[i].auditor_name); 1671 } 1672 GNUNET_array_grow (keys->auditors, 1673 keys->auditors_size, 1674 0); 1675 TALER_EXCHANGE_free_accounts (keys->accounts_len, 1676 keys->accounts); 1677 GNUNET_array_grow (keys->accounts, 1678 keys->accounts_len, 1679 0); 1680 free_fees (keys->fees, 1681 keys->fees_len); 1682 GNUNET_array_grow (keys->hard_limits, 1683 keys->hard_limits_length, 1684 0); 1685 GNUNET_array_grow (keys->zero_limits, 1686 keys->zero_limits_length, 1687 0); 1688 json_decref (keys->extensions); 1689 GNUNET_free (keys->cspec.name); 1690 json_decref (keys->cspec.map_alt_unit_names); 1691 GNUNET_array_grow (keys->cspec.common_amounts, 1692 keys->cspec.num_common_amounts, 1693 0); 1694 GNUNET_free (keys->wallet_balance_limit_without_kyc); 1695 GNUNET_free (keys->version); 1696 GNUNET_free (keys->currency); 1697 GNUNET_free (keys->asset_type); 1698 GNUNET_free (keys->shopping_url); 1699 GNUNET_free (keys->bank_compliance_language); 1700 for (unsigned int i = 0; i < keys->num_wad_partners; i++) 1701 GNUNET_free (keys->wad_partners[i].partner_base_url); 1702 GNUNET_free (keys->wad_partners); 1703 GNUNET_free (keys->global_fees); 1704 GNUNET_free (keys->exchange_url); 1705 GNUNET_free (keys); 1706 } 1707 1708 1709 struct TALER_EXCHANGE_Keys * 1710 TALER_EXCHANGE_keys_from_json (const json_t *j) 1711 { 1712 const json_t *jkeys; 1713 const char *url; 1714 uint32_t version; 1715 struct GNUNET_TIME_Timestamp expire 1716 = GNUNET_TIME_UNIT_ZERO_TS; 1717 struct GNUNET_JSON_Specification spec[] = { 1718 GNUNET_JSON_spec_uint32 ("version", 1719 &version), 1720 GNUNET_JSON_spec_object_const ("keys", 1721 &jkeys), 1722 TALER_JSON_spec_web_url ("exchange_url", 1723 &url), 1724 GNUNET_JSON_spec_mark_optional ( 1725 GNUNET_JSON_spec_timestamp ("expire", 1726 &expire), 1727 NULL), 1728 GNUNET_JSON_spec_end () 1729 }; 1730 struct TALER_EXCHANGE_Keys *keys; 1731 enum TALER_EXCHANGE_VersionCompatibility compat; 1732 1733 if (NULL == j) 1734 return NULL; 1735 if (GNUNET_OK != 1736 GNUNET_JSON_parse (j, 1737 spec, 1738 NULL, NULL)) 1739 { 1740 GNUNET_break_op (0); 1741 return NULL; 1742 } 1743 if (0 != version) 1744 { 1745 return NULL; /* unsupported version */ 1746 } 1747 keys = GNUNET_new (struct TALER_EXCHANGE_Keys); 1748 if (GNUNET_OK != 1749 TALER_EXCHANGE_decode_keys_json_ (jkeys, 1750 false, 1751 keys, 1752 &compat)) 1753 { 1754 GNUNET_break (0); 1755 return NULL; 1756 } 1757 keys->rc = 1; 1758 keys->key_data_expiration = expire; 1759 keys->exchange_url = GNUNET_strdup (url); 1760 return keys; 1761 } 1762 1763 1764 /** 1765 * Data we track per denomination group. 1766 */ 1767 struct GroupData 1768 { 1769 /** 1770 * The json blob with the group meta-data and list of denominations 1771 */ 1772 json_t *json; 1773 1774 /** 1775 * Meta data for this group. 1776 */ 1777 struct TALER_DenominationGroup meta; 1778 }; 1779 1780 1781 /** 1782 * Add denomination group represented by @a value 1783 * to list of denominations in @a cls. Also frees 1784 * the @a value. 1785 * 1786 * @param[in,out] cls a `json_t *` with an array to build 1787 * @param key unused 1788 * @param value a `struct GroupData *` 1789 * @return #GNUNET_OK (continue to iterate) 1790 */ 1791 static enum GNUNET_GenericReturnValue 1792 add_grp (void *cls, 1793 const struct GNUNET_HashCode *key, 1794 void *value) 1795 { 1796 json_t *denominations_by_group = cls; 1797 struct GroupData *gd = value; 1798 const char *cipher; 1799 json_t *ge; 1800 bool age_restricted = gd->meta.age_mask.bits != 0; 1801 1802 (void) key; 1803 switch (gd->meta.cipher) 1804 { 1805 case GNUNET_CRYPTO_BSA_RSA: 1806 cipher = age_restricted ? "RSA+age_restricted" : "RSA"; 1807 break; 1808 case GNUNET_CRYPTO_BSA_CS: 1809 cipher = age_restricted ? "CS+age_restricted" : "CS"; 1810 break; 1811 default: 1812 GNUNET_assert (false); 1813 } 1814 1815 ge = GNUNET_JSON_PACK ( 1816 GNUNET_JSON_pack_string ("cipher", 1817 cipher), 1818 GNUNET_JSON_pack_array_steal ("denoms", 1819 gd->json), 1820 TALER_JSON_PACK_DENOM_FEES ("fee", 1821 &gd->meta.fees), 1822 GNUNET_JSON_pack_allow_null ( 1823 age_restricted 1824 ? GNUNET_JSON_pack_uint64 ("age_mask", 1825 gd->meta.age_mask.bits) 1826 : GNUNET_JSON_pack_string ("dummy", 1827 NULL)), 1828 TALER_JSON_pack_amount ("value", 1829 &gd->meta.value)); 1830 GNUNET_assert (0 == 1831 json_array_append_new (denominations_by_group, 1832 ge)); 1833 GNUNET_free (gd); 1834 return GNUNET_OK; 1835 } 1836 1837 1838 /** 1839 * Convert array of account restrictions @a ars to JSON. 1840 * 1841 * @param ar_len length of @a ars 1842 * @param ars account restrictions to convert 1843 * @return JSON representation 1844 */ 1845 static json_t * 1846 ar_to_json (unsigned int ar_len, 1847 const struct TALER_EXCHANGE_AccountRestriction ars[static ar_len]) 1848 { 1849 json_t *rval; 1850 1851 rval = json_array (); 1852 GNUNET_assert (NULL != rval); 1853 for (unsigned int i = 0; i<ar_len; i++) 1854 { 1855 const struct TALER_EXCHANGE_AccountRestriction *ar = &ars[i]; 1856 1857 switch (ar->type) 1858 { 1859 case TALER_EXCHANGE_AR_INVALID: 1860 GNUNET_break (0); 1861 json_decref (rval); 1862 return NULL; 1863 case TALER_EXCHANGE_AR_DENY: 1864 GNUNET_assert ( 1865 0 == 1866 json_array_append_new ( 1867 rval, 1868 GNUNET_JSON_PACK ( 1869 GNUNET_JSON_pack_string ("type", 1870 "deny")))); 1871 break; 1872 case TALER_EXCHANGE_AR_REGEX: 1873 GNUNET_assert ( 1874 0 == 1875 json_array_append_new ( 1876 rval, 1877 GNUNET_JSON_PACK ( 1878 GNUNET_JSON_pack_string ( 1879 "type", 1880 "regex"), 1881 GNUNET_JSON_pack_string ( 1882 "payto_regex", 1883 ar->details.regex.posix_egrep), 1884 GNUNET_JSON_pack_string ( 1885 "human_hint", 1886 ar->details.regex.human_hint), 1887 GNUNET_JSON_pack_object_incref ( 1888 "human_hint_i18n", 1889 (json_t *) ar->details.regex.human_hint_i18n) 1890 ))); 1891 break; 1892 } 1893 } 1894 return rval; 1895 } 1896 1897 1898 json_t * 1899 TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd) 1900 { 1901 struct GNUNET_TIME_Timestamp now; 1902 json_t *keys; 1903 json_t *signkeys; 1904 json_t *denominations_by_group; 1905 json_t *auditors; 1906 json_t *recoup; 1907 json_t *wire_fees; 1908 json_t *accounts; 1909 json_t *global_fees; 1910 json_t *wblwk = NULL; 1911 json_t *wads_json; 1912 json_t *hard_limits; 1913 json_t *zero_limits; 1914 1915 now = GNUNET_TIME_timestamp_get (); 1916 signkeys = json_array (); 1917 GNUNET_assert (NULL != signkeys); 1918 for (unsigned int i = 0; i<kd->num_sign_keys; i++) 1919 { 1920 const struct TALER_EXCHANGE_SigningPublicKey *sk = &kd->sign_keys[i]; 1921 json_t *signkey; 1922 1923 if (GNUNET_TIME_timestamp_cmp (now, 1924 >, 1925 sk->valid_until)) 1926 continue; /* skip keys that have expired */ 1927 signkey = GNUNET_JSON_PACK ( 1928 GNUNET_JSON_pack_data_auto ("key", 1929 &sk->key), 1930 GNUNET_JSON_pack_data_auto ("master_sig", 1931 &sk->master_sig), 1932 GNUNET_JSON_pack_timestamp ("stamp_start", 1933 sk->valid_from), 1934 GNUNET_JSON_pack_timestamp ("stamp_expire", 1935 sk->valid_until), 1936 GNUNET_JSON_pack_timestamp ("stamp_end", 1937 sk->valid_legal)); 1938 GNUNET_assert (NULL != signkey); 1939 GNUNET_assert (0 == 1940 json_array_append_new (signkeys, 1941 signkey)); 1942 } 1943 1944 denominations_by_group = json_array (); 1945 GNUNET_assert (NULL != denominations_by_group); 1946 { 1947 struct GNUNET_CONTAINER_MultiHashMap *dbg; 1948 1949 dbg = GNUNET_CONTAINER_multihashmap_create (128, 1950 false); 1951 for (unsigned int i = 0; i<kd->num_denom_keys; i++) 1952 { 1953 const struct TALER_EXCHANGE_DenomPublicKey *dk = &kd->denom_keys[i]; 1954 struct TALER_DenominationGroup meta = { 1955 .cipher = dk->key.bsign_pub_key->cipher, 1956 .value = dk->value, 1957 .fees = dk->fees, 1958 .age_mask = dk->key.age_mask 1959 }; 1960 struct GNUNET_HashCode key; 1961 struct GroupData *gd; 1962 json_t *denom; 1963 struct GNUNET_JSON_PackSpec key_spec; 1964 1965 if (GNUNET_TIME_timestamp_cmp (now, 1966 >, 1967 dk->expire_deposit)) 1968 continue; /* skip keys that have expired */ 1969 TALER_denomination_group_get_key (&meta, 1970 &key); 1971 gd = GNUNET_CONTAINER_multihashmap_get (dbg, 1972 &key); 1973 if (NULL == gd) 1974 { 1975 gd = GNUNET_new (struct GroupData); 1976 gd->meta = meta; 1977 gd->json = json_array (); 1978 GNUNET_assert (NULL != gd->json); 1979 GNUNET_assert ( 1980 GNUNET_OK == 1981 GNUNET_CONTAINER_multihashmap_put (dbg, 1982 &key, 1983 gd, 1984 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 1985 1986 } 1987 switch (meta.cipher) 1988 { 1989 case GNUNET_CRYPTO_BSA_RSA: 1990 key_spec = 1991 GNUNET_JSON_pack_rsa_public_key ( 1992 "rsa_pub", 1993 dk->key.bsign_pub_key->details.rsa_public_key); 1994 break; 1995 case GNUNET_CRYPTO_BSA_CS: 1996 key_spec = 1997 GNUNET_JSON_pack_data_varsize ( 1998 "cs_pub", 1999 &dk->key.bsign_pub_key->details.cs_public_key, 2000 sizeof (dk->key.bsign_pub_key->details.cs_public_key)); 2001 break; 2002 default: 2003 GNUNET_assert (false); 2004 } 2005 denom = GNUNET_JSON_PACK ( 2006 GNUNET_JSON_pack_timestamp ("stamp_expire_deposit", 2007 dk->expire_deposit), 2008 GNUNET_JSON_pack_timestamp ("stamp_expire_withdraw", 2009 dk->withdraw_valid_until), 2010 GNUNET_JSON_pack_timestamp ("stamp_start", 2011 dk->valid_from), 2012 GNUNET_JSON_pack_timestamp ("stamp_expire_legal", 2013 dk->expire_legal), 2014 GNUNET_JSON_pack_data_auto ("master_sig", 2015 &dk->master_sig), 2016 key_spec 2017 ); 2018 GNUNET_assert (0 == 2019 json_array_append_new (gd->json, 2020 denom)); 2021 } 2022 GNUNET_CONTAINER_multihashmap_iterate (dbg, 2023 &add_grp, 2024 denominations_by_group); 2025 GNUNET_CONTAINER_multihashmap_destroy (dbg); 2026 } 2027 2028 auditors = json_array (); 2029 GNUNET_assert (NULL != auditors); 2030 for (unsigned int i = 0; i<kd->num_auditors; i++) 2031 { 2032 const struct TALER_EXCHANGE_AuditorInformation *ai = &kd->auditors[i]; 2033 json_t *a; 2034 json_t *adenoms; 2035 2036 adenoms = json_array (); 2037 GNUNET_assert (NULL != adenoms); 2038 for (unsigned int j = 0; j<ai->num_denom_keys; j++) 2039 { 2040 const struct TALER_EXCHANGE_AuditorDenominationInfo *adi = 2041 &ai->denom_keys[j]; 2042 const struct TALER_EXCHANGE_DenomPublicKey *dk = 2043 &kd->denom_keys[adi->denom_key_offset]; 2044 json_t *k; 2045 2046 GNUNET_assert (adi->denom_key_offset < kd->num_denom_keys); 2047 if (GNUNET_TIME_timestamp_cmp (now, 2048 >, 2049 dk->expire_deposit)) 2050 continue; /* skip auditor signatures for denomination keys that have expired */ 2051 GNUNET_assert (adi->denom_key_offset < kd->num_denom_keys); 2052 k = GNUNET_JSON_PACK ( 2053 GNUNET_JSON_pack_data_auto ("denom_pub_h", 2054 &dk->h_key), 2055 GNUNET_JSON_pack_data_auto ("auditor_sig", 2056 &adi->auditor_sig)); 2057 GNUNET_assert (0 == 2058 json_array_append_new (adenoms, 2059 k)); 2060 } 2061 2062 a = GNUNET_JSON_PACK ( 2063 GNUNET_JSON_pack_data_auto ("auditor_pub", 2064 &ai->auditor_pub), 2065 GNUNET_JSON_pack_string ("auditor_url", 2066 ai->auditor_url), 2067 GNUNET_JSON_pack_string ("auditor_name", 2068 ai->auditor_name), 2069 GNUNET_JSON_pack_array_steal ("denomination_keys", 2070 adenoms)); 2071 GNUNET_assert (0 == 2072 json_array_append_new (auditors, 2073 a)); 2074 } 2075 2076 global_fees = json_array (); 2077 GNUNET_assert (NULL != global_fees); 2078 for (unsigned int i = 0; i<kd->num_global_fees; i++) 2079 { 2080 const struct TALER_EXCHANGE_GlobalFee *gf 2081 = &kd->global_fees[i]; 2082 2083 if (GNUNET_TIME_absolute_is_past (gf->end_date.abs_time)) 2084 continue; 2085 GNUNET_assert ( 2086 0 == 2087 json_array_append_new ( 2088 global_fees, 2089 GNUNET_JSON_PACK ( 2090 GNUNET_JSON_pack_timestamp ("start_date", 2091 gf->start_date), 2092 GNUNET_JSON_pack_timestamp ("end_date", 2093 gf->end_date), 2094 TALER_JSON_PACK_GLOBAL_FEES (&gf->fees), 2095 GNUNET_JSON_pack_time_rel ("history_expiration", 2096 gf->history_expiration), 2097 GNUNET_JSON_pack_time_rel ("purse_timeout", 2098 gf->purse_timeout), 2099 GNUNET_JSON_pack_uint64 ("purse_account_limit", 2100 gf->purse_account_limit), 2101 GNUNET_JSON_pack_data_auto ("master_sig", 2102 &gf->master_sig)))); 2103 } 2104 2105 accounts = json_array (); 2106 GNUNET_assert (NULL != accounts); 2107 for (unsigned int i = 0; i<kd->accounts_len; i++) 2108 { 2109 const struct TALER_EXCHANGE_WireAccount *acc 2110 = &kd->accounts[i]; 2111 json_t *credit_restrictions; 2112 json_t *debit_restrictions; 2113 2114 credit_restrictions 2115 = ar_to_json (acc->credit_restrictions_length, 2116 acc->credit_restrictions); 2117 GNUNET_assert (NULL != credit_restrictions); 2118 debit_restrictions 2119 = ar_to_json (acc->debit_restrictions_length, 2120 acc->debit_restrictions); 2121 GNUNET_assert (NULL != debit_restrictions); 2122 GNUNET_assert ( 2123 0 == 2124 json_array_append_new ( 2125 accounts, 2126 GNUNET_JSON_PACK ( 2127 TALER_JSON_pack_full_payto ("payto_uri", 2128 acc->fpayto_uri), 2129 GNUNET_JSON_pack_allow_null ( 2130 GNUNET_JSON_pack_string ("conversion_url", 2131 acc->conversion_url)), 2132 GNUNET_JSON_pack_allow_null ( 2133 GNUNET_JSON_pack_string ("open_banking_gateway", 2134 acc->open_banking_gateway)), 2135 GNUNET_JSON_pack_allow_null ( 2136 GNUNET_JSON_pack_string ("wire_transfer_gateway", 2137 acc->wire_transfer_gateway)), 2138 GNUNET_JSON_pack_int64 ("priority", 2139 acc->priority), 2140 GNUNET_JSON_pack_allow_null ( 2141 GNUNET_JSON_pack_string ("bank_label", 2142 acc->bank_label)), 2143 GNUNET_JSON_pack_array_steal ("debit_restrictions", 2144 debit_restrictions), 2145 GNUNET_JSON_pack_array_steal ("credit_restrictions", 2146 credit_restrictions), 2147 GNUNET_JSON_pack_data_auto ("master_sig", 2148 &acc->master_sig)))); 2149 } 2150 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2151 "Serialized %u/%u wire accounts to JSON\n", 2152 (unsigned int) json_array_size (accounts), 2153 kd->accounts_len); 2154 2155 wire_fees = json_object (); 2156 GNUNET_assert (NULL != wire_fees); 2157 for (unsigned int i = 0; i<kd->fees_len; i++) 2158 { 2159 const struct TALER_EXCHANGE_WireFeesByMethod *fbw 2160 = &kd->fees[i]; 2161 json_t *wf; 2162 2163 wf = json_array (); 2164 GNUNET_assert (NULL != wf); 2165 for (struct TALER_EXCHANGE_WireAggregateFees *p = fbw->fees_head; 2166 NULL != p; 2167 p = p->next) 2168 { 2169 GNUNET_assert ( 2170 0 == 2171 json_array_append_new ( 2172 wf, 2173 GNUNET_JSON_PACK ( 2174 TALER_JSON_pack_amount ("wire_fee", 2175 &p->fees.wire), 2176 TALER_JSON_pack_amount ("closing_fee", 2177 &p->fees.closing), 2178 GNUNET_JSON_pack_timestamp ("start_date", 2179 p->start_date), 2180 GNUNET_JSON_pack_timestamp ("end_date", 2181 p->end_date), 2182 GNUNET_JSON_pack_data_auto ("sig", 2183 &p->master_sig)))); 2184 } 2185 GNUNET_assert (0 == 2186 json_object_set_new (wire_fees, 2187 fbw->method, 2188 wf)); 2189 } 2190 2191 recoup = json_array (); 2192 GNUNET_assert (NULL != recoup); 2193 for (unsigned int i = 0; i<kd->num_denom_keys; i++) 2194 { 2195 const struct TALER_EXCHANGE_DenomPublicKey *dk 2196 = &kd->denom_keys[i]; 2197 if (! dk->revoked) 2198 continue; 2199 GNUNET_assert (0 == 2200 json_array_append_new ( 2201 recoup, 2202 GNUNET_JSON_PACK ( 2203 GNUNET_JSON_pack_data_auto ("h_denom_pub", 2204 &dk->h_key)))); 2205 } 2206 2207 wblwk = json_array (); 2208 GNUNET_assert (NULL != wblwk); 2209 for (unsigned int i = 0; i<kd->wblwk_length; i++) 2210 { 2211 const struct TALER_Amount *a = &kd->wallet_balance_limit_without_kyc[i]; 2212 2213 GNUNET_assert (0 == 2214 json_array_append_new ( 2215 wblwk, 2216 TALER_JSON_from_amount (a))); 2217 } 2218 2219 hard_limits = json_array (); 2220 for (unsigned int i = 0; i < kd->hard_limits_length; i++) 2221 { 2222 const struct TALER_EXCHANGE_AccountLimit *al 2223 = &kd->hard_limits[i]; 2224 json_t *j; 2225 2226 j = GNUNET_JSON_PACK ( 2227 TALER_JSON_pack_amount ("threshold", 2228 &al->threshold), 2229 GNUNET_JSON_pack_time_rel ("timeframe", 2230 al->timeframe), 2231 TALER_JSON_pack_kycte ("operation_type", 2232 al->operation_type), 2233 GNUNET_JSON_pack_bool ("soft_limit", 2234 al->soft_limit) 2235 ); 2236 GNUNET_assert (0 == 2237 json_array_append_new ( 2238 hard_limits, 2239 j)); 2240 } 2241 2242 zero_limits = json_array (); 2243 for (unsigned int i = 0; i < kd->zero_limits_length; i++) 2244 { 2245 const struct TALER_EXCHANGE_ZeroLimitedOperation *zol 2246 = &kd->zero_limits[i]; 2247 json_t *j; 2248 2249 j = GNUNET_JSON_PACK ( 2250 TALER_JSON_pack_kycte ("operation_type", 2251 zol->operation_type) 2252 ); 2253 GNUNET_assert (0 == 2254 json_array_append_new ( 2255 zero_limits, 2256 j)); 2257 } 2258 2259 wads_json = json_array (); 2260 GNUNET_assert (NULL != wads_json); 2261 for (unsigned int i = 0; i < kd->num_wad_partners; i++) 2262 { 2263 const struct TALER_EXCHANGE_WadPartner *wp 2264 = &kd->wad_partners[i]; 2265 2266 GNUNET_assert ( 2267 0 == 2268 json_array_append_new ( 2269 wads_json, 2270 GNUNET_JSON_PACK ( 2271 GNUNET_JSON_pack_string ("partner_base_url", 2272 wp->partner_base_url), 2273 GNUNET_JSON_pack_data_auto ("partner_master_pub", 2274 &wp->partner_master_pub), 2275 TALER_JSON_pack_amount ("wad_fee", 2276 &wp->wad_fee), 2277 GNUNET_JSON_pack_time_rel ("wad_frequency", 2278 wp->wad_frequency), 2279 GNUNET_JSON_pack_timestamp ("start_date", 2280 wp->start_date), 2281 GNUNET_JSON_pack_timestamp ("end_date", 2282 wp->end_date), 2283 GNUNET_JSON_pack_data_auto ("master_sig", 2284 &wp->master_sig)))); 2285 } 2286 2287 keys = GNUNET_JSON_PACK ( 2288 GNUNET_JSON_pack_string ("version", 2289 kd->version), 2290 GNUNET_JSON_pack_string ("currency", 2291 kd->currency), 2292 GNUNET_JSON_pack_object_steal ("currency_specification", 2293 TALER_JSON_currency_specs_to_json ( 2294 &kd->cspec)), 2295 TALER_JSON_pack_amount ("stefan_abs", 2296 &kd->stefan_abs), 2297 TALER_JSON_pack_amount ("stefan_log", 2298 &kd->stefan_log), 2299 GNUNET_JSON_pack_double ("stefan_lin", 2300 kd->stefan_lin), 2301 GNUNET_JSON_pack_allow_null ( 2302 kd->tiny_amount_available 2303 ? TALER_JSON_pack_amount ("tiny_amount", 2304 &kd->tiny_amount) 2305 : GNUNET_JSON_pack_string ("dummy", 2306 NULL)), 2307 GNUNET_JSON_pack_string ("asset_type", 2308 kd->asset_type), 2309 GNUNET_JSON_pack_allow_null ( 2310 GNUNET_JSON_pack_string ("shopping_url", 2311 kd->shopping_url)), 2312 GNUNET_JSON_pack_allow_null ( 2313 GNUNET_JSON_pack_string ("bank_compliance_language", 2314 kd->bank_compliance_language)), 2315 GNUNET_JSON_pack_bool ("disable_direct_deposit", 2316 kd->disable_direct_deposit), 2317 GNUNET_JSON_pack_data_auto ("master_public_key", 2318 &kd->master_pub), 2319 GNUNET_JSON_pack_time_rel ("reserve_closing_delay", 2320 kd->reserve_closing_delay), 2321 GNUNET_JSON_pack_timestamp ("list_issue_date", 2322 kd->list_issue_date), 2323 GNUNET_JSON_pack_array_steal ("global_fees", 2324 global_fees), 2325 GNUNET_JSON_pack_array_steal ("signkeys", 2326 signkeys), 2327 GNUNET_JSON_pack_object_steal ("wire_fees", 2328 wire_fees), 2329 GNUNET_JSON_pack_array_steal ("accounts", 2330 accounts), 2331 GNUNET_JSON_pack_array_steal ("wads", 2332 wads_json), 2333 GNUNET_JSON_pack_array_steal ("hard_limits", 2334 hard_limits), 2335 GNUNET_JSON_pack_array_steal ("zero_limits", 2336 zero_limits), 2337 GNUNET_JSON_pack_array_steal ("denominations", 2338 denominations_by_group), 2339 GNUNET_JSON_pack_allow_null ( 2340 GNUNET_JSON_pack_array_steal ("recoup", 2341 recoup)), 2342 GNUNET_JSON_pack_array_steal ("auditors", 2343 auditors), 2344 GNUNET_JSON_pack_bool ("kyc_enabled", 2345 kd->kyc_enabled), 2346 GNUNET_JSON_pack_allow_null ( 2347 GNUNET_JSON_pack_object_incref ("extensions", 2348 kd->extensions)), 2349 GNUNET_JSON_pack_allow_null ( 2350 GNUNET_is_zero (&kd->extensions_sig) 2351 ? GNUNET_JSON_pack_string ("dummy", 2352 NULL) 2353 : GNUNET_JSON_pack_data_auto ("extensions_sig", 2354 &kd->extensions_sig)), 2355 GNUNET_JSON_pack_allow_null ( 2356 GNUNET_JSON_pack_array_steal ("wallet_balance_limit_without_kyc", 2357 wblwk)) 2358 2359 ); 2360 return GNUNET_JSON_PACK ( 2361 GNUNET_JSON_pack_uint64 ("version", 2362 EXCHANGE_SERIALIZATION_FORMAT_VERSION), 2363 GNUNET_JSON_pack_allow_null ( 2364 GNUNET_JSON_pack_timestamp ("expire", 2365 kd->key_data_expiration)), 2366 GNUNET_JSON_pack_string ("exchange_url", 2367 kd->exchange_url), 2368 GNUNET_JSON_pack_object_steal ("keys", 2369 keys)); 2370 } 2371 2372 2373 /* end of exchange_api_handle.c */