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