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