json_helper.c (54811B)
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 under the 6 terms of the GNU General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License along with 14 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file json/json_helper.c 18 * @brief helper functions to generate specifications to parse 19 * Taler-specific JSON objects with libgnunetjson 20 * @author Sree Harsha Totakura <sreeharsha@totakura.in> 21 * @author Christian Grothoff 22 */ 23 #include "taler/platform.h" 24 #include <gnunet/gnunet_util_lib.h> 25 #include "taler/taler_util.h" 26 #include "taler/taler_json_lib.h" 27 28 29 /** 30 * Convert string value to numeric cipher value. 31 * 32 * @param cipher_s input string 33 * @return numeric cipher value 34 */ 35 static enum GNUNET_CRYPTO_BlindSignatureAlgorithm 36 string_to_cipher (const char *cipher_s) 37 { 38 if ((0 == strcasecmp (cipher_s, 39 "RSA")) || 40 (0 == strcasecmp (cipher_s, 41 "RSA+age_restricted"))) 42 return GNUNET_CRYPTO_BSA_RSA; 43 if ((0 == strcasecmp (cipher_s, 44 "CS")) || 45 (0 == strcasecmp (cipher_s, 46 "CS+age_restricted"))) 47 return GNUNET_CRYPTO_BSA_CS; 48 return GNUNET_CRYPTO_BSA_INVALID; 49 } 50 51 52 json_t * 53 TALER_JSON_from_amount (const struct TALER_Amount *amount) 54 { 55 char *amount_str = TALER_amount_to_string (amount); 56 57 GNUNET_assert (NULL != amount_str); 58 { 59 json_t *j = json_string (amount_str); 60 61 GNUNET_free (amount_str); 62 return j; 63 } 64 } 65 66 67 /** 68 * Parse given JSON object to Amount 69 * 70 * @param cls closure, expected currency, or NULL 71 * @param root the json object representing data 72 * @param[out] spec where to write the data 73 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 74 */ 75 static enum GNUNET_GenericReturnValue 76 parse_amount (void *cls, 77 json_t *root, 78 struct GNUNET_JSON_Specification *spec) 79 { 80 const char *currency = cls; 81 struct TALER_Amount *r_amount = spec->ptr; 82 83 (void) cls; 84 if (! json_is_string (root)) 85 { 86 GNUNET_break_op (0); 87 return GNUNET_SYSERR; 88 } 89 if (GNUNET_OK != 90 TALER_string_to_amount (json_string_value (root), 91 r_amount)) 92 { 93 GNUNET_break_op (0); 94 return GNUNET_SYSERR; 95 } 96 if ( (NULL != currency) && 97 (0 != 98 strcasecmp (currency, 99 r_amount->currency)) ) 100 { 101 GNUNET_break_op (0); 102 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 103 "Expected currency `%s', but amount used currency `%s' in field `%s'\n", 104 currency, 105 r_amount->currency, 106 spec->field); 107 return GNUNET_SYSERR; 108 } 109 return GNUNET_OK; 110 } 111 112 113 struct GNUNET_JSON_Specification 114 TALER_JSON_spec_amount (const char *name, 115 const char *currency, 116 struct TALER_Amount *r_amount) 117 { 118 struct GNUNET_JSON_Specification ret = { 119 .parser = &parse_amount, 120 .cleaner = NULL, 121 .cls = (void *) currency, 122 .field = name, 123 .ptr = r_amount, 124 .ptr_size = 0, 125 .size_ptr = NULL 126 }; 127 128 GNUNET_assert (NULL != currency); 129 return ret; 130 } 131 132 133 struct GNUNET_JSON_Specification 134 TALER_JSON_spec_amount_any (const char *name, 135 struct TALER_Amount *r_amount) 136 { 137 struct GNUNET_JSON_Specification ret = { 138 .parser = &parse_amount, 139 .cleaner = NULL, 140 .cls = NULL, 141 .field = name, 142 .ptr = r_amount, 143 .ptr_size = 0, 144 .size_ptr = NULL 145 }; 146 147 return ret; 148 } 149 150 151 /** 152 * Closure for parsing amount arrays. 153 */ 154 struct AmountArrayCtx 155 { 156 /** 157 * Pointer where to store the resulting array length. 158 */ 159 size_t *len; 160 }; 161 162 163 /** 164 * Parse a JSON array of arbitrary amounts. 165 */ 166 static enum GNUNET_GenericReturnValue 167 parse_amount_any_array (void *cls, 168 json_t *root, 169 struct GNUNET_JSON_Specification *spec) 170 { 171 struct AmountArrayCtx *ctx = cls; 172 struct TALER_Amount **out = spec->ptr; 173 174 GNUNET_assert (NULL != ctx); 175 GNUNET_assert (NULL != out); 176 *out = NULL; 177 if (NULL != ctx->len) 178 *ctx->len = 0; 179 180 if (! json_is_array (root)) 181 { 182 GNUNET_break_op (0); 183 return GNUNET_SYSERR; 184 } 185 186 { 187 size_t len = json_array_size (root); 188 json_t *entry; 189 size_t idx; 190 191 if (NULL != ctx->len) 192 *ctx->len = len; 193 if (0 == len) 194 { 195 GNUNET_break_op (0); 196 return GNUNET_SYSERR; 197 } 198 *out = GNUNET_new_array (len, 199 struct TALER_Amount); 200 json_array_foreach (root, idx, entry) { 201 const char *amount_str; 202 203 if (! json_is_string (entry)) 204 { 205 GNUNET_break_op (0); 206 return GNUNET_SYSERR; 207 } 208 amount_str = json_string_value (entry); 209 if (GNUNET_OK != 210 TALER_string_to_amount (amount_str, 211 &(*out)[idx])) 212 { 213 GNUNET_break_op (0); 214 return GNUNET_SYSERR; 215 } 216 } 217 } 218 return GNUNET_OK; 219 } 220 221 222 /** 223 * Cleanup helper for the amount array parser. 224 */ 225 static void 226 clean_amount_any_array (void *cls, 227 struct GNUNET_JSON_Specification *spec) 228 { 229 struct AmountArrayCtx *ctx = cls; 230 231 if (NULL != spec->ptr) 232 { 233 GNUNET_free (*(void **) spec->ptr); 234 *(void **) spec->ptr = NULL; 235 } 236 if ( (NULL != ctx) && 237 (NULL != ctx->len) ) 238 *ctx->len = 0; 239 GNUNET_free (ctx); 240 } 241 242 243 struct GNUNET_JSON_Specification 244 TALER_JSON_spec_amount_any_array (const char *field, 245 size_t *amounts_len, 246 struct TALER_Amount **amounts) 247 { 248 struct AmountArrayCtx *ctx; 249 250 GNUNET_assert (NULL != amounts_len); 251 GNUNET_assert (NULL != amounts); 252 ctx = GNUNET_new (struct AmountArrayCtx); 253 ctx->len = amounts_len; 254 { 255 struct GNUNET_JSON_Specification ret = { 256 .parser = &parse_amount_any_array, 257 .cleaner = &clean_amount_any_array, 258 .cls = ctx, 259 .field = field, 260 .ptr = amounts 261 }; 262 263 return ret; 264 } 265 } 266 267 268 /** 269 * Parse given JSON object to currency spec. 270 * 271 * @param cls closure, NULL 272 * @param root the json object representing data 273 * @param[out] spec where to write the data 274 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 275 */ 276 static enum GNUNET_GenericReturnValue 277 parse_cspec (void *cls, 278 json_t *root, 279 struct GNUNET_JSON_Specification *spec) 280 { 281 struct TALER_CurrencySpecification *r_cspec = spec->ptr; 282 const char *currency = spec->cls; 283 const char *name; 284 uint32_t fid; 285 uint32_t fnd; 286 uint32_t ftzd; 287 const json_t *map; 288 const json_t *ca = NULL; 289 struct GNUNET_JSON_Specification gspec[] = { 290 GNUNET_JSON_spec_string ("name", 291 &name), 292 GNUNET_JSON_spec_uint32 ("num_fractional_input_digits", 293 &fid), 294 GNUNET_JSON_spec_uint32 ("num_fractional_normal_digits", 295 &fnd), 296 GNUNET_JSON_spec_uint32 ("num_fractional_trailing_zero_digits", 297 &ftzd), 298 GNUNET_JSON_spec_object_const ("alt_unit_names", 299 &map), 300 GNUNET_JSON_spec_mark_optional ( 301 GNUNET_JSON_spec_array_const ("common_amounts", 302 &ca), 303 NULL), 304 GNUNET_JSON_spec_end () 305 }; 306 const char *emsg; 307 unsigned int eline; 308 309 memset (r_cspec->currency, 310 0, 311 sizeof (r_cspec->currency)); 312 if (GNUNET_OK != 313 GNUNET_JSON_parse (root, 314 gspec, 315 &emsg, 316 &eline)) 317 { 318 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 319 "Failed to parse %s at %u: %s\n", 320 spec[eline].field, 321 eline, 322 emsg); 323 GNUNET_break_op (0); 324 return GNUNET_SYSERR; 325 } 326 if (strlen (currency) >= TALER_CURRENCY_LEN) 327 { 328 GNUNET_break_op (0); 329 return GNUNET_SYSERR; 330 } 331 if ( (fid > TALER_AMOUNT_FRAC_LEN) || 332 (fnd > TALER_AMOUNT_FRAC_LEN) || 333 (ftzd > TALER_AMOUNT_FRAC_LEN) ) 334 { 335 GNUNET_break_op (0); 336 return GNUNET_SYSERR; 337 } 338 if (GNUNET_OK != 339 TALER_check_currency (currency)) 340 { 341 GNUNET_break_op (0); 342 return GNUNET_SYSERR; 343 } 344 strcpy (r_cspec->currency, 345 currency); 346 if (GNUNET_OK != 347 TALER_check_currency_scale_map (map)) 348 { 349 GNUNET_break_op (0); 350 return GNUNET_SYSERR; 351 } 352 r_cspec->name = GNUNET_strdup (name); 353 r_cspec->map_alt_unit_names = json_incref ((json_t *) map); 354 if (NULL != ca) 355 { 356 size_t i; 357 json_t *v; 358 359 json_array_foreach ((json_t *) ca, i, v) 360 { 361 struct TALER_Amount val; 362 const char *vstr; 363 364 vstr = json_string_value (v); 365 if ( (NULL == vstr) || 366 (GNUNET_OK != 367 TALER_string_to_amount (vstr, 368 &val)) ) 369 { 370 GNUNET_break_op (0); 371 return GNUNET_SYSERR; 372 } 373 if (0 != strcasecmp (val.currency, 374 r_cspec->currency)) 375 { 376 GNUNET_break_op (0); 377 return GNUNET_SYSERR; 378 } 379 GNUNET_array_append (r_cspec->common_amounts, 380 r_cspec->num_common_amounts, 381 val); 382 } 383 } 384 return GNUNET_OK; 385 } 386 387 388 /** 389 * Cleanup data left from parsing encrypted contract. 390 * 391 * @param cls closure, NULL 392 * @param[out] spec where to free the data 393 */ 394 static void 395 clean_cspec (void *cls, 396 struct GNUNET_JSON_Specification *spec) 397 { 398 struct TALER_CurrencySpecification *cspec = spec->ptr; 399 400 (void) cls; 401 GNUNET_array_grow (cspec->common_amounts, 402 cspec->num_common_amounts, 403 0); 404 GNUNET_free (cspec->name); 405 json_decref (cspec->map_alt_unit_names); 406 } 407 408 409 struct GNUNET_JSON_Specification 410 TALER_JSON_spec_currency_specification ( 411 const char *name, 412 const char *currency, 413 struct TALER_CurrencySpecification *r_cspec) 414 { 415 struct GNUNET_JSON_Specification ret = { 416 .parser = &parse_cspec, 417 .cleaner = &clean_cspec, 418 .cls = (void *) currency, 419 .field = name, 420 .ptr = r_cspec, 421 .ptr_size = sizeof (*r_cspec), 422 .size_ptr = NULL 423 }; 424 425 memset (r_cspec, 426 0, 427 sizeof (*r_cspec)); 428 return ret; 429 } 430 431 432 static enum GNUNET_GenericReturnValue 433 parse_denomination_group (void *cls, 434 json_t *root, 435 struct GNUNET_JSON_Specification *spec) 436 { 437 struct TALER_DenominationGroup *group = spec->ptr; 438 const char *cipher; 439 const char *currency = cls; 440 bool age_mask_missing = false; 441 bool has_age_restricted_suffix = false; 442 struct GNUNET_JSON_Specification gspec[] = { 443 GNUNET_JSON_spec_string ("cipher", 444 &cipher), 445 TALER_JSON_spec_amount ("value", 446 currency, 447 &group->value), 448 TALER_JSON_SPEC_DENOM_FEES ("fee", 449 currency, 450 &group->fees), 451 GNUNET_JSON_spec_mark_optional ( 452 GNUNET_JSON_spec_uint32 ("age_mask", 453 &group->age_mask.bits), 454 &age_mask_missing), 455 GNUNET_JSON_spec_end () 456 }; 457 const char *emsg; 458 unsigned int eline; 459 460 if (GNUNET_OK != 461 GNUNET_JSON_parse (root, 462 gspec, 463 &emsg, 464 &eline)) 465 { 466 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 467 "Failed to parse %s at %u: %s\n", 468 spec[eline].field, 469 eline, 470 emsg); 471 GNUNET_break_op (0); 472 return GNUNET_SYSERR; 473 } 474 475 group->cipher = string_to_cipher (cipher); 476 if (GNUNET_CRYPTO_BSA_INVALID == group->cipher) 477 { 478 GNUNET_break_op (0); 479 return GNUNET_SYSERR; 480 } 481 482 /* age_mask and suffix must be consistent */ 483 has_age_restricted_suffix = 484 (NULL != strstr (cipher, "+age_restricted")); 485 if (has_age_restricted_suffix && age_mask_missing) 486 { 487 GNUNET_break_op (0); 488 return GNUNET_SYSERR; 489 } 490 491 if (age_mask_missing) 492 group->age_mask.bits = 0; 493 494 return GNUNET_OK; 495 } 496 497 498 struct GNUNET_JSON_Specification 499 TALER_JSON_spec_denomination_group (const char *name, 500 const char *currency, 501 struct TALER_DenominationGroup *group) 502 { 503 struct GNUNET_JSON_Specification ret = { 504 .cls = (void *) currency, 505 .parser = &parse_denomination_group, 506 .field = name, 507 .ptr = group, 508 .ptr_size = sizeof(*group) 509 }; 510 511 return ret; 512 } 513 514 515 /** 516 * Parse given JSON object to an encrypted contract. 517 * 518 * @param cls closure, NULL 519 * @param root the json object representing data 520 * @param[out] spec where to write the data 521 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 522 */ 523 static enum GNUNET_GenericReturnValue 524 parse_econtract (void *cls, 525 json_t *root, 526 struct GNUNET_JSON_Specification *spec) 527 { 528 struct TALER_EncryptedContract *econtract = spec->ptr; 529 struct GNUNET_JSON_Specification ispec[] = { 530 GNUNET_JSON_spec_varsize ("econtract", 531 &econtract->econtract, 532 &econtract->econtract_size), 533 GNUNET_JSON_spec_fixed_auto ("econtract_sig", 534 &econtract->econtract_sig), 535 GNUNET_JSON_spec_fixed_auto ("contract_pub", 536 &econtract->contract_pub), 537 GNUNET_JSON_spec_end () 538 }; 539 const char *emsg; 540 unsigned int eline; 541 542 (void) cls; 543 if (GNUNET_OK != 544 GNUNET_JSON_parse (root, 545 ispec, 546 &emsg, 547 &eline)) 548 { 549 GNUNET_break_op (0); 550 return GNUNET_SYSERR; 551 } 552 return GNUNET_OK; 553 } 554 555 556 /** 557 * Cleanup data left from parsing encrypted contract. 558 * 559 * @param cls closure, NULL 560 * @param[out] spec where to free the data 561 */ 562 static void 563 clean_econtract (void *cls, 564 struct GNUNET_JSON_Specification *spec) 565 { 566 struct TALER_EncryptedContract *econtract = spec->ptr; 567 568 (void) cls; 569 GNUNET_free (econtract->econtract); 570 } 571 572 573 struct GNUNET_JSON_Specification 574 TALER_JSON_spec_econtract (const char *name, 575 struct TALER_EncryptedContract *econtract) 576 { 577 struct GNUNET_JSON_Specification ret = { 578 .parser = &parse_econtract, 579 .cleaner = &clean_econtract, 580 .field = name, 581 .ptr = econtract 582 }; 583 584 return ret; 585 } 586 587 588 /** 589 * Parse given JSON object to an age commitmnet 590 * 591 * @param cls closure, NULL 592 * @param root the json object representing data 593 * @param[out] spec where to write the data 594 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 595 */ 596 static enum GNUNET_GenericReturnValue 597 parse_age_commitment (void *cls, 598 json_t *root, 599 struct GNUNET_JSON_Specification *spec) 600 { 601 struct TALER_AgeCommitment *age_commitment = spec->ptr; 602 json_t *pk; 603 unsigned int idx; 604 size_t num; 605 606 (void) cls; 607 if ( (NULL == root) || 608 (! json_is_array (root))) 609 { 610 GNUNET_break_op (0); 611 return GNUNET_SYSERR; 612 } 613 614 num = json_array_size (root); 615 if (32 <= num || 0 == num) 616 { 617 GNUNET_break_op (0); 618 return GNUNET_SYSERR; 619 } 620 621 age_commitment->num = num; 622 age_commitment->pubs = 623 GNUNET_new_array (num, 624 struct TALER_AgeCommitmentPublicKeyP); 625 626 json_array_foreach (root, idx, pk) { 627 const char *emsg; 628 unsigned int eline; 629 struct GNUNET_JSON_Specification pkspec[] = { 630 GNUNET_JSON_spec_fixed_auto ( 631 NULL, 632 &age_commitment->pubs[idx].pub), 633 GNUNET_JSON_spec_end () 634 }; 635 636 if (GNUNET_OK != 637 GNUNET_JSON_parse (pk, 638 pkspec, 639 &emsg, 640 &eline)) 641 { 642 GNUNET_break_op (0); 643 GNUNET_JSON_parse_free (spec); 644 return GNUNET_SYSERR; 645 } 646 }; 647 648 return GNUNET_OK; 649 } 650 651 652 /** 653 * Cleanup data left from parsing age commitment 654 * 655 * @param cls closure, NULL 656 * @param[out] spec where to free the data 657 */ 658 static void 659 clean_age_commitment (void *cls, 660 struct GNUNET_JSON_Specification *spec) 661 { 662 struct TALER_AgeCommitment *age_commitment = spec->ptr; 663 664 (void) cls; 665 666 if (NULL == age_commitment || 667 NULL == age_commitment->pubs) 668 return; 669 670 age_commitment->num = 0; 671 GNUNET_free (age_commitment->pubs); 672 age_commitment->pubs = NULL; 673 } 674 675 676 struct GNUNET_JSON_Specification 677 TALER_JSON_spec_age_commitment (const char *name, 678 struct TALER_AgeCommitment *age_commitment) 679 { 680 struct GNUNET_JSON_Specification ret = { 681 .parser = &parse_age_commitment, 682 .cleaner = &clean_age_commitment, 683 .field = name, 684 .ptr = age_commitment 685 }; 686 687 return ret; 688 } 689 690 691 struct GNUNET_JSON_Specification 692 TALER_JSON_spec_token_issue_sig (const char *field, 693 struct TALER_TokenIssueSignature *sig) 694 { 695 sig->signature = NULL; 696 return GNUNET_JSON_spec_unblinded_signature (field, 697 &sig->signature); 698 } 699 700 701 struct GNUNET_JSON_Specification 702 TALER_JSON_spec_blinded_token_issue_sig ( 703 const char *field, 704 struct TALER_BlindedTokenIssueSignature *sig) 705 { 706 sig->signature = NULL; 707 return GNUNET_JSON_spec_blinded_signature (field, 708 &sig->signature); 709 } 710 711 712 struct GNUNET_JSON_Specification 713 TALER_JSON_spec_token_envelope (const char *field, 714 struct TALER_TokenEnvelope *env) 715 { 716 env->blinded_pub = NULL; 717 return GNUNET_JSON_spec_blinded_message (field, 718 &env->blinded_pub); 719 } 720 721 722 /** 723 * Parse given JSON object to denomination public key. 724 * 725 * @param cls closure, NULL 726 * @param root the json object representing data 727 * @param[out] spec where to write the data 728 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 729 */ 730 static enum GNUNET_GenericReturnValue 731 parse_denom_pub (void *cls, 732 json_t *root, 733 struct GNUNET_JSON_Specification *spec) 734 { 735 struct TALER_DenominationPublicKey *denom_pub = spec->ptr; 736 struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub; 737 const char *cipher; 738 bool age_mask_missing = false; 739 struct GNUNET_JSON_Specification dspec[] = { 740 GNUNET_JSON_spec_string ("cipher", 741 &cipher), 742 GNUNET_JSON_spec_mark_optional ( 743 GNUNET_JSON_spec_uint32 ("age_mask", 744 &denom_pub->age_mask.bits), 745 &age_mask_missing), 746 GNUNET_JSON_spec_end () 747 }; 748 const char *emsg; 749 unsigned int eline; 750 751 (void) cls; 752 if (GNUNET_OK != 753 GNUNET_JSON_parse (root, 754 dspec, 755 &emsg, 756 &eline)) 757 { 758 GNUNET_break_op (0); 759 return GNUNET_SYSERR; 760 } 761 762 if (age_mask_missing) 763 denom_pub->age_mask.bits = 0; 764 bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey); 765 bsign_pub->rc = 1; 766 bsign_pub->cipher = string_to_cipher (cipher); 767 switch (bsign_pub->cipher) 768 { 769 case GNUNET_CRYPTO_BSA_INVALID: 770 break; 771 case GNUNET_CRYPTO_BSA_RSA: 772 { 773 struct GNUNET_JSON_Specification ispec[] = { 774 GNUNET_JSON_spec_rsa_public_key ( 775 "rsa_pub", 776 &bsign_pub->details.rsa_public_key), 777 GNUNET_JSON_spec_end () 778 }; 779 780 if (GNUNET_OK != 781 GNUNET_JSON_parse (root, 782 ispec, 783 &emsg, 784 &eline)) 785 { 786 GNUNET_break_op (0); 787 GNUNET_free (bsign_pub); 788 return GNUNET_SYSERR; 789 } 790 denom_pub->bsign_pub_key = bsign_pub; 791 return GNUNET_OK; 792 } 793 case GNUNET_CRYPTO_BSA_CS: 794 { 795 struct GNUNET_JSON_Specification ispec[] = { 796 GNUNET_JSON_spec_fixed ("cs_pub", 797 &bsign_pub->details.cs_public_key, 798 sizeof (bsign_pub->details.cs_public_key)), 799 GNUNET_JSON_spec_end () 800 }; 801 802 if (GNUNET_OK != 803 GNUNET_JSON_parse (root, 804 ispec, 805 &emsg, 806 &eline)) 807 { 808 GNUNET_break_op (0); 809 GNUNET_free (bsign_pub); 810 return GNUNET_SYSERR; 811 } 812 denom_pub->bsign_pub_key = bsign_pub; 813 return GNUNET_OK; 814 } 815 } 816 GNUNET_break_op (0); 817 GNUNET_free (bsign_pub); 818 return GNUNET_SYSERR; 819 } 820 821 822 /** 823 * Cleanup data left from parsing denomination public key. 824 * 825 * @param cls closure, NULL 826 * @param[out] spec where to free the data 827 */ 828 static void 829 clean_denom_pub (void *cls, 830 struct GNUNET_JSON_Specification *spec) 831 { 832 struct TALER_DenominationPublicKey *denom_pub = spec->ptr; 833 834 (void) cls; 835 TALER_denom_pub_free (denom_pub); 836 } 837 838 839 struct GNUNET_JSON_Specification 840 TALER_JSON_spec_denom_pub (const char *field, 841 struct TALER_DenominationPublicKey *pk) 842 { 843 struct GNUNET_JSON_Specification ret = { 844 .parser = &parse_denom_pub, 845 .cleaner = &clean_denom_pub, 846 .field = field, 847 .ptr = pk 848 }; 849 850 pk->bsign_pub_key = NULL; 851 return ret; 852 } 853 854 855 /** 856 * Parse given JSON object to token issue public key. 857 * 858 * @param cls closure, NULL 859 * @param root the json object representing data 860 * @param[out] spec where to write the data 861 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 862 */ 863 static enum GNUNET_GenericReturnValue 864 parse_token_pub (void *cls, 865 json_t *root, 866 struct GNUNET_JSON_Specification *spec) 867 { 868 struct TALER_TokenIssuePublicKey *token_pub = spec->ptr; 869 struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub; 870 const char *cipher; 871 struct GNUNET_JSON_Specification dspec[] = { 872 GNUNET_JSON_spec_string ("cipher", 873 &cipher), 874 GNUNET_JSON_spec_end () 875 }; 876 const char *emsg; 877 unsigned int eline; 878 879 (void) cls; 880 if (GNUNET_OK != 881 GNUNET_JSON_parse (root, 882 dspec, 883 &emsg, 884 &eline)) 885 { 886 GNUNET_break_op (0); 887 return GNUNET_SYSERR; 888 } 889 890 bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey); 891 bsign_pub->rc = 1; 892 bsign_pub->cipher = string_to_cipher (cipher); 893 switch (bsign_pub->cipher) 894 { 895 case GNUNET_CRYPTO_BSA_INVALID: 896 break; 897 case GNUNET_CRYPTO_BSA_RSA: 898 { 899 struct GNUNET_JSON_Specification ispec[] = { 900 GNUNET_JSON_spec_rsa_public_key ( 901 "rsa_pub", 902 &bsign_pub->details.rsa_public_key), 903 GNUNET_JSON_spec_end () 904 }; 905 906 if (GNUNET_OK != 907 GNUNET_JSON_parse (root, 908 ispec, 909 &emsg, 910 &eline)) 911 { 912 GNUNET_break_op (0); 913 GNUNET_free (bsign_pub); 914 return GNUNET_SYSERR; 915 } 916 GNUNET_CRYPTO_rsa_public_key_hash (bsign_pub->details.rsa_public_key, 917 &bsign_pub->pub_key_hash); 918 token_pub->public_key = bsign_pub; 919 return GNUNET_OK; 920 } 921 case GNUNET_CRYPTO_BSA_CS: 922 { 923 struct GNUNET_JSON_Specification ispec[] = { 924 GNUNET_JSON_spec_fixed ("cs_pub", 925 &bsign_pub->details.cs_public_key, 926 sizeof (bsign_pub->details.cs_public_key)), 927 GNUNET_JSON_spec_end () 928 }; 929 930 if (GNUNET_OK != 931 GNUNET_JSON_parse (root, 932 ispec, 933 &emsg, 934 &eline)) 935 { 936 GNUNET_break_op (0); 937 GNUNET_free (bsign_pub); 938 return GNUNET_SYSERR; 939 } 940 GNUNET_CRYPTO_hash (&bsign_pub->details.cs_public_key, 941 sizeof(bsign_pub->details.cs_public_key), 942 &bsign_pub->pub_key_hash); 943 token_pub->public_key = bsign_pub; 944 return GNUNET_OK; 945 } 946 } 947 GNUNET_break_op (0); 948 GNUNET_free (bsign_pub); 949 return GNUNET_SYSERR; 950 } 951 952 953 /** 954 * Cleanup data left from parsing token issue public key. 955 * 956 * @param cls closure, NULL 957 * @param[out] spec where to free the data 958 */ 959 static void 960 clean_token_pub (void *cls, 961 struct GNUNET_JSON_Specification *spec) 962 { 963 struct TALER_TokenIssuePublicKey *token_pub = spec->ptr; 964 965 (void) cls; 966 TALER_token_issue_pub_free (token_pub); 967 } 968 969 970 struct GNUNET_JSON_Specification 971 TALER_JSON_spec_token_pub (const char *field, 972 struct TALER_TokenIssuePublicKey *pk) 973 { 974 struct GNUNET_JSON_Specification ret = { 975 .field = field, 976 .parser = &parse_token_pub, 977 .cleaner = &clean_token_pub, 978 .ptr = pk 979 }; 980 981 pk->public_key = NULL; 982 return ret; 983 } 984 985 986 /** 987 * Parse given JSON object partially into a denomination public key. 988 * 989 * Depending on the cipher in cls, it parses the corresponding public key type. 990 * 991 * @param cls closure, enum GNUNET_CRYPTO_BlindSignatureAlgorithm 992 * @param root the json object representing data 993 * @param[out] spec where to write the data 994 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 995 */ 996 static enum GNUNET_GenericReturnValue 997 parse_denom_pub_cipher (void *cls, 998 json_t *root, 999 struct GNUNET_JSON_Specification *spec) 1000 { 1001 struct TALER_DenominationPublicKey *denom_pub = spec->ptr; 1002 enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher = 1003 (enum GNUNET_CRYPTO_BlindSignatureAlgorithm) (long) cls; 1004 struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub; 1005 const char *emsg; 1006 unsigned int eline; 1007 1008 bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey); 1009 bsign_pub->cipher = cipher; 1010 bsign_pub->rc = 1; 1011 switch (cipher) 1012 { 1013 case GNUNET_CRYPTO_BSA_INVALID: 1014 break; 1015 case GNUNET_CRYPTO_BSA_RSA: 1016 { 1017 struct GNUNET_JSON_Specification ispec[] = { 1018 GNUNET_JSON_spec_rsa_public_key ( 1019 "rsa_pub", 1020 &bsign_pub->details.rsa_public_key), 1021 GNUNET_JSON_spec_end () 1022 }; 1023 1024 if (GNUNET_OK != 1025 GNUNET_JSON_parse (root, 1026 ispec, 1027 &emsg, 1028 &eline)) 1029 { 1030 GNUNET_break_op (0); 1031 GNUNET_free (bsign_pub); 1032 return GNUNET_SYSERR; 1033 } 1034 denom_pub->bsign_pub_key = bsign_pub; 1035 return GNUNET_OK; 1036 } 1037 case GNUNET_CRYPTO_BSA_CS: 1038 { 1039 struct GNUNET_JSON_Specification ispec[] = { 1040 GNUNET_JSON_spec_fixed ("cs_pub", 1041 &bsign_pub->details.cs_public_key, 1042 sizeof (bsign_pub->details.cs_public_key)), 1043 GNUNET_JSON_spec_end () 1044 }; 1045 1046 if (GNUNET_OK != 1047 GNUNET_JSON_parse (root, 1048 ispec, 1049 &emsg, 1050 &eline)) 1051 { 1052 GNUNET_break_op (0); 1053 GNUNET_free (bsign_pub); 1054 return GNUNET_SYSERR; 1055 } 1056 denom_pub->bsign_pub_key = bsign_pub; 1057 return GNUNET_OK; 1058 } 1059 } 1060 GNUNET_break_op (0); 1061 GNUNET_free (bsign_pub); 1062 return GNUNET_SYSERR; 1063 } 1064 1065 1066 struct GNUNET_JSON_Specification 1067 TALER_JSON_spec_denom_pub_cipher ( 1068 const char *field, 1069 enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher, 1070 struct TALER_DenominationPublicKey *pk) 1071 { 1072 struct GNUNET_JSON_Specification ret = { 1073 .parser = &parse_denom_pub_cipher, 1074 .cleaner = &clean_denom_pub, 1075 .field = field, 1076 .cls = (void *) cipher, 1077 .ptr = pk 1078 }; 1079 1080 return ret; 1081 } 1082 1083 1084 struct GNUNET_JSON_Specification 1085 TALER_JSON_spec_denom_sig (const char *field, 1086 struct TALER_DenominationSignature *sig) 1087 { 1088 sig->unblinded_sig = NULL; 1089 return GNUNET_JSON_spec_unblinded_signature (field, 1090 &sig->unblinded_sig); 1091 } 1092 1093 1094 struct GNUNET_JSON_Specification 1095 TALER_JSON_spec_blinded_denom_sig ( 1096 const char *field, 1097 struct TALER_BlindedDenominationSignature *sig) 1098 { 1099 sig->blinded_sig = NULL; 1100 return GNUNET_JSON_spec_blinded_signature (field, 1101 &sig->blinded_sig); 1102 } 1103 1104 1105 struct GNUNET_JSON_Specification 1106 TALER_JSON_spec_blinded_planchet ( 1107 const char *field, 1108 struct TALER_BlindedPlanchet *blinded_planchet) 1109 { 1110 blinded_planchet->blinded_message = NULL; 1111 return GNUNET_JSON_spec_blinded_message (field, 1112 &blinded_planchet->blinded_message); 1113 } 1114 1115 1116 /** 1117 * Parse given JSON object to exchange withdraw values (/csr). 1118 * 1119 * @param cls closure, NULL 1120 * @param root the json object representing data 1121 * @param[out] spec where to write the data 1122 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1123 */ 1124 static enum GNUNET_GenericReturnValue 1125 parse_exchange_blinding_values (void *cls, 1126 json_t *root, 1127 struct GNUNET_JSON_Specification *spec) 1128 { 1129 struct TALER_ExchangeBlindingValues *ewv = spec->ptr; 1130 struct GNUNET_CRYPTO_BlindingInputValues *bi; 1131 const char *cipher; 1132 struct GNUNET_JSON_Specification dspec[] = { 1133 GNUNET_JSON_spec_string ("cipher", 1134 &cipher), 1135 GNUNET_JSON_spec_end () 1136 }; 1137 const char *emsg; 1138 unsigned int eline; 1139 enum GNUNET_CRYPTO_BlindSignatureAlgorithm ci; 1140 1141 (void) cls; 1142 if (GNUNET_OK != 1143 GNUNET_JSON_parse (root, 1144 dspec, 1145 &emsg, 1146 &eline)) 1147 { 1148 GNUNET_break_op (0); 1149 return GNUNET_SYSERR; 1150 } 1151 ci = string_to_cipher (cipher); 1152 switch (ci) 1153 { 1154 case GNUNET_CRYPTO_BSA_INVALID: 1155 break; 1156 case GNUNET_CRYPTO_BSA_RSA: 1157 ewv->blinding_inputs = TALER_denom_ewv_rsa_singleton ()->blinding_inputs; 1158 return GNUNET_OK; 1159 case GNUNET_CRYPTO_BSA_CS: 1160 bi = GNUNET_new (struct GNUNET_CRYPTO_BlindingInputValues); 1161 bi->cipher = GNUNET_CRYPTO_BSA_CS; 1162 bi->rc = 1; 1163 { 1164 struct GNUNET_JSON_Specification ispec[] = { 1165 GNUNET_JSON_spec_fixed ( 1166 "r_pub_0", 1167 &bi->details.cs_values.r_pub[0], 1168 sizeof (struct GNUNET_CRYPTO_CsRPublic)), 1169 GNUNET_JSON_spec_fixed ( 1170 "r_pub_1", 1171 &bi->details.cs_values.r_pub[1], 1172 sizeof (struct GNUNET_CRYPTO_CsRPublic)), 1173 GNUNET_JSON_spec_end () 1174 }; 1175 1176 if (GNUNET_OK != 1177 GNUNET_JSON_parse (root, 1178 ispec, 1179 &emsg, 1180 &eline)) 1181 { 1182 GNUNET_break_op (0); 1183 GNUNET_free (bi); 1184 return GNUNET_SYSERR; 1185 } 1186 ewv->blinding_inputs = bi; 1187 return GNUNET_OK; 1188 } 1189 } 1190 GNUNET_break_op (0); 1191 return GNUNET_SYSERR; 1192 } 1193 1194 1195 /** 1196 * Cleanup data left from parsing withdraw values 1197 * 1198 * @param cls closure, NULL 1199 * @param[out] spec where to free the data 1200 */ 1201 static void 1202 clean_exchange_blinding_values ( 1203 void *cls, 1204 struct GNUNET_JSON_Specification *spec) 1205 { 1206 struct TALER_ExchangeBlindingValues *ewv = spec->ptr; 1207 1208 (void) cls; 1209 TALER_denom_ewv_free (ewv); 1210 } 1211 1212 1213 struct GNUNET_JSON_Specification 1214 TALER_JSON_spec_exchange_blinding_values ( 1215 const char *field, 1216 struct TALER_ExchangeBlindingValues *ewv) 1217 { 1218 struct GNUNET_JSON_Specification ret = { 1219 .parser = &parse_exchange_blinding_values, 1220 .cleaner = &clean_exchange_blinding_values, 1221 .field = field, 1222 .ptr = ewv 1223 }; 1224 1225 ewv->blinding_inputs = NULL; 1226 return ret; 1227 } 1228 1229 1230 /** 1231 * Closure for #parse_i18n_string. 1232 */ 1233 struct I18nContext 1234 { 1235 /** 1236 * Language pattern to match. 1237 */ 1238 char *lp; 1239 1240 /** 1241 * Name of the field to match. 1242 */ 1243 const char *field; 1244 }; 1245 1246 1247 /** 1248 * Parse given JSON object to internationalized string. 1249 * 1250 * @param cls closure, our `struct I18nContext *` 1251 * @param root the json object representing data 1252 * @param[out] spec where to write the data 1253 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1254 */ 1255 static enum GNUNET_GenericReturnValue 1256 parse_i18n_string (void *cls, 1257 json_t *root, 1258 struct GNUNET_JSON_Specification *spec) 1259 { 1260 struct I18nContext *ctx = cls; 1261 json_t *i18n; 1262 json_t *val; 1263 1264 { 1265 char *i18nf; 1266 1267 GNUNET_asprintf (&i18nf, 1268 "%s_i18n", 1269 ctx->field); 1270 i18n = json_object_get (root, 1271 i18nf); 1272 GNUNET_free (i18nf); 1273 } 1274 1275 val = json_object_get (root, 1276 ctx->field); 1277 if ( (NULL != i18n) && 1278 (NULL != ctx->lp) ) 1279 { 1280 double best = 0.0; 1281 json_t *pos; 1282 const char *lang; 1283 1284 json_object_foreach (i18n, lang, pos) 1285 { 1286 double score; 1287 1288 score = TALER_pattern_matches (ctx->lp, 1289 lang); 1290 if (score > best) 1291 { 1292 best = score; 1293 val = pos; 1294 } 1295 } 1296 } 1297 1298 { 1299 const char *str; 1300 1301 str = json_string_value (val); 1302 *(const char **) spec->ptr = str; 1303 } 1304 return GNUNET_OK; 1305 } 1306 1307 1308 /** 1309 * Function called to clean up data from earlier parsing. 1310 * 1311 * @param cls closure 1312 * @param spec our specification entry with data to clean. 1313 */ 1314 static void 1315 i18n_cleaner (void *cls, 1316 struct GNUNET_JSON_Specification *spec) 1317 { 1318 struct I18nContext *ctx = cls; 1319 1320 (void) spec; 1321 if (NULL != ctx) 1322 { 1323 GNUNET_free (ctx->lp); 1324 GNUNET_free (ctx); 1325 } 1326 } 1327 1328 1329 struct GNUNET_JSON_Specification 1330 TALER_JSON_spec_i18n_string (const char *name, 1331 const char *language_pattern, 1332 const char **strptr) 1333 { 1334 struct I18nContext *ctx = GNUNET_new (struct I18nContext); 1335 struct GNUNET_JSON_Specification ret = { 1336 .parser = &parse_i18n_string, 1337 .cleaner = &i18n_cleaner, 1338 .cls = ctx, 1339 .field = NULL, /* we want the main object */ 1340 .ptr = strptr, 1341 .ptr_size = 0, 1342 .size_ptr = NULL 1343 }; 1344 1345 ctx->lp = (NULL != language_pattern) 1346 ? GNUNET_strdup (language_pattern) 1347 : NULL; 1348 ctx->field = name; 1349 *strptr = NULL; 1350 return ret; 1351 } 1352 1353 1354 struct GNUNET_JSON_Specification 1355 TALER_JSON_spec_i18n_str (const char *name, 1356 const char **strptr) 1357 { 1358 const char *lang = getenv ("LANG"); 1359 char *dot; 1360 char *l; 1361 struct GNUNET_JSON_Specification ret; 1362 1363 if (NULL != lang) 1364 { 1365 dot = strchr (lang, 1366 '.'); 1367 if (NULL == dot) 1368 l = GNUNET_strdup (lang); 1369 else 1370 l = GNUNET_strndup (lang, 1371 dot - lang); 1372 } 1373 else 1374 { 1375 l = NULL; 1376 } 1377 ret = TALER_JSON_spec_i18n_string (name, 1378 l, 1379 strptr); 1380 GNUNET_free (l); 1381 return ret; 1382 } 1383 1384 1385 /** 1386 * Parse given JSON object with Taler error code. 1387 * 1388 * @param cls closure, NULL 1389 * @param root the json object representing data 1390 * @param[out] spec where to write the data 1391 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1392 */ 1393 static enum GNUNET_GenericReturnValue 1394 parse_ec (void *cls, 1395 json_t *root, 1396 struct GNUNET_JSON_Specification *spec) 1397 { 1398 enum TALER_ErrorCode *ec = spec->ptr; 1399 json_int_t num; 1400 1401 (void) cls; 1402 if (! json_is_integer (root)) 1403 { 1404 GNUNET_break_op (0); 1405 return GNUNET_SYSERR; 1406 } 1407 num = json_integer_value (root); 1408 if (num < 0) 1409 { 1410 GNUNET_break_op (0); 1411 *ec = TALER_EC_INVALID; 1412 return GNUNET_SYSERR; 1413 } 1414 *ec = (enum TALER_ErrorCode) num; 1415 return GNUNET_OK; 1416 } 1417 1418 1419 struct GNUNET_JSON_Specification 1420 TALER_JSON_spec_ec (const char *field, 1421 enum TALER_ErrorCode *ec) 1422 { 1423 struct GNUNET_JSON_Specification ret = { 1424 .parser = &parse_ec, 1425 .field = field, 1426 .ptr = ec 1427 }; 1428 1429 *ec = TALER_EC_NONE; 1430 return ret; 1431 } 1432 1433 1434 /** 1435 * Parse given JSON object to web URL. 1436 * 1437 * @param cls closure, NULL 1438 * @param root the json object representing data 1439 * @param[out] spec where to write the data 1440 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1441 */ 1442 static enum GNUNET_GenericReturnValue 1443 parse_web_url (void *cls, 1444 json_t *root, 1445 struct GNUNET_JSON_Specification *spec) 1446 { 1447 const char *str; 1448 1449 (void) cls; 1450 str = json_string_value (root); 1451 if (NULL == str) 1452 { 1453 GNUNET_break_op (0); 1454 return GNUNET_SYSERR; 1455 } 1456 if (! TALER_is_web_url (str)) 1457 { 1458 GNUNET_break_op (0); 1459 return GNUNET_SYSERR; 1460 } 1461 *(const char **) spec->ptr = str; 1462 return GNUNET_OK; 1463 } 1464 1465 1466 struct GNUNET_JSON_Specification 1467 TALER_JSON_spec_web_url (const char *field, 1468 const char **url) 1469 { 1470 struct GNUNET_JSON_Specification ret = { 1471 .parser = &parse_web_url, 1472 .field = field, 1473 .ptr = url 1474 }; 1475 1476 *url = NULL; 1477 return ret; 1478 } 1479 1480 1481 /** 1482 * Parse given JSON object to payto:// URI. 1483 * 1484 * @param cls closure, NULL 1485 * @param root the json object representing data 1486 * @param[out] spec where to write the data 1487 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1488 */ 1489 static enum GNUNET_GenericReturnValue 1490 parse_full_payto_uri (void *cls, 1491 json_t *root, 1492 struct GNUNET_JSON_Specification *spec) 1493 { 1494 struct TALER_FullPayto *payto_uri = spec->ptr; 1495 const char *str; 1496 char *err; 1497 1498 (void) cls; 1499 str = json_string_value (root); 1500 if (NULL == str) 1501 { 1502 GNUNET_break_op (0); 1503 return GNUNET_SYSERR; 1504 } 1505 payto_uri->full_payto = (char *) str; 1506 err = TALER_payto_validate (*payto_uri); 1507 if (NULL != err) 1508 { 1509 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1510 "payto:// malformed: %s\n", 1511 err); 1512 GNUNET_free (err); 1513 payto_uri->full_payto = NULL; 1514 return GNUNET_SYSERR; 1515 } 1516 return GNUNET_OK; 1517 } 1518 1519 1520 struct GNUNET_JSON_Specification 1521 TALER_JSON_spec_full_payto_uri ( 1522 const char *field, 1523 struct TALER_FullPayto *payto_uri) 1524 { 1525 struct GNUNET_JSON_Specification ret = { 1526 .parser = &parse_full_payto_uri, 1527 .field = field, 1528 .ptr = payto_uri 1529 }; 1530 1531 payto_uri->full_payto = NULL; 1532 return ret; 1533 } 1534 1535 1536 /** 1537 * Parse given JSON object to payto:// URI. 1538 * 1539 * @param cls closure, NULL 1540 * @param root the json object representing data 1541 * @param[out] spec where to write the data 1542 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1543 */ 1544 static enum GNUNET_GenericReturnValue 1545 parse_normalized_payto_uri (void *cls, 1546 json_t *root, 1547 struct GNUNET_JSON_Specification *spec) 1548 { 1549 struct TALER_NormalizedPayto *payto_uri = spec->ptr; 1550 const char *str; 1551 1552 (void) cls; 1553 str = json_string_value (root); 1554 if (NULL == str) 1555 { 1556 GNUNET_break_op (0); 1557 return GNUNET_SYSERR; 1558 } 1559 payto_uri->normalized_payto = (char *) str; 1560 { 1561 char *err; 1562 1563 err = TALER_normalized_payto_validate (*payto_uri); 1564 if (NULL != err) 1565 { 1566 GNUNET_break_op (0); 1567 GNUNET_free (err); 1568 payto_uri->normalized_payto = NULL; 1569 return GNUNET_SYSERR; 1570 } 1571 } 1572 return GNUNET_OK; 1573 } 1574 1575 1576 struct GNUNET_JSON_Specification 1577 TALER_JSON_spec_normalized_payto_uri ( 1578 const char *field, 1579 struct TALER_NormalizedPayto *payto_uri) 1580 { 1581 struct GNUNET_JSON_Specification ret = { 1582 .parser = &parse_normalized_payto_uri, 1583 .field = field, 1584 .ptr = payto_uri 1585 }; 1586 1587 payto_uri->normalized_payto = NULL; 1588 return ret; 1589 } 1590 1591 1592 /** 1593 * Parse given JSON object with protocol version. 1594 * 1595 * @param cls closure, NULL 1596 * @param root the json object representing data 1597 * @param[out] spec where to write the data 1598 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1599 */ 1600 static enum GNUNET_GenericReturnValue 1601 parse_protocol_version (void *cls, 1602 json_t *root, 1603 struct GNUNET_JSON_Specification *spec) 1604 { 1605 struct TALER_JSON_ProtocolVersion *pv = spec->ptr; 1606 const char *ver; 1607 char dummy; 1608 1609 (void) cls; 1610 if (! json_is_string (root)) 1611 { 1612 GNUNET_break_op (0); 1613 return GNUNET_SYSERR; 1614 } 1615 ver = json_string_value (root); 1616 if (3 != sscanf (ver, 1617 "%u:%u:%u%c", 1618 &pv->current, 1619 &pv->revision, 1620 &pv->age, 1621 &dummy)) 1622 { 1623 GNUNET_break_op (0); 1624 return GNUNET_SYSERR; 1625 } 1626 return GNUNET_OK; 1627 } 1628 1629 1630 struct GNUNET_JSON_Specification 1631 TALER_JSON_spec_version (const char *field, 1632 struct TALER_JSON_ProtocolVersion *ver) 1633 { 1634 struct GNUNET_JSON_Specification ret = { 1635 .parser = &parse_protocol_version, 1636 .field = field, 1637 .ptr = ver 1638 }; 1639 1640 return ret; 1641 } 1642 1643 1644 /** 1645 * Parse given JSON object to an OTP key. 1646 * 1647 * @param cls closure, NULL 1648 * @param root the json object representing data 1649 * @param[out] spec where to write the data 1650 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1651 */ 1652 static enum GNUNET_GenericReturnValue 1653 parse_otp_key (void *cls, 1654 json_t *root, 1655 struct GNUNET_JSON_Specification *spec) 1656 { 1657 const char *pos_key; 1658 1659 (void) cls; 1660 pos_key = json_string_value (root); 1661 if (NULL == pos_key) 1662 { 1663 GNUNET_break_op (0); 1664 return GNUNET_SYSERR; 1665 } 1666 { 1667 size_t pos_key_length = strlen (pos_key); 1668 void *key; /* pos_key in binary */ 1669 size_t key_len; /* length of the key */ 1670 int dret; 1671 1672 key_len = pos_key_length * 5 / 8; 1673 key = GNUNET_malloc (key_len); 1674 dret = TALER_rfc3548_base32decode (pos_key, 1675 pos_key_length, 1676 key, 1677 key_len); 1678 if (-1 == dret) 1679 { 1680 GNUNET_free (key); 1681 GNUNET_break_op (0); 1682 return GNUNET_SYSERR; 1683 } 1684 GNUNET_free (key); 1685 } 1686 *(const char **) spec->ptr = pos_key; 1687 return GNUNET_OK; 1688 } 1689 1690 1691 struct GNUNET_JSON_Specification 1692 TALER_JSON_spec_otp_key (const char *name, 1693 const char **otp_key) 1694 { 1695 struct GNUNET_JSON_Specification ret = { 1696 .parser = &parse_otp_key, 1697 .field = name, 1698 .ptr = otp_key 1699 }; 1700 1701 *otp_key = NULL; 1702 return ret; 1703 } 1704 1705 1706 /** 1707 * Parse given JSON object to `enum TALER_MerchantConfirmationAlgorithm` 1708 * 1709 * @param cls closure, NULL 1710 * @param root the json object representing data 1711 * @param[out] spec where to write the data 1712 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1713 */ 1714 static enum GNUNET_GenericReturnValue 1715 parse_otp_type (void *cls, 1716 json_t *root, 1717 struct GNUNET_JSON_Specification *spec) 1718 { 1719 static const struct Entry 1720 { 1721 const char *name; 1722 enum TALER_MerchantConfirmationAlgorithm val; 1723 } lt [] = { 1724 { .name = "NONE", 1725 .val = TALER_MCA_NONE }, 1726 { .name = "TOTP_WITHOUT_PRICE", 1727 .val = TALER_MCA_WITHOUT_PRICE }, 1728 { .name = "TOTP_WITH_PRICE", 1729 .val = TALER_MCA_WITH_PRICE }, 1730 { .name = NULL, 1731 .val = TALER_MCA_NONE }, 1732 }; 1733 enum TALER_MerchantConfirmationAlgorithm *res 1734 = (enum TALER_MerchantConfirmationAlgorithm *) spec->ptr; 1735 1736 (void) cls; 1737 if (json_is_string (root)) 1738 { 1739 const char *str; 1740 1741 str = json_string_value (root); 1742 if (NULL == str) 1743 { 1744 GNUNET_break_op (0); 1745 return GNUNET_SYSERR; 1746 } 1747 for (unsigned int i = 0; NULL != lt[i].name; i++) 1748 { 1749 if (0 == strcasecmp (str, 1750 lt[i].name)) 1751 { 1752 *res = lt[i].val; 1753 return GNUNET_OK; 1754 } 1755 } 1756 GNUNET_break_op (0); 1757 } 1758 if (json_is_integer (root)) 1759 { 1760 json_int_t val; 1761 1762 val = json_integer_value (root); 1763 for (unsigned int i = 0; NULL != lt[i].name; i++) 1764 { 1765 if (val == lt[i].val) 1766 { 1767 *res = lt[i].val; 1768 return GNUNET_OK; 1769 } 1770 } 1771 GNUNET_break_op (0); 1772 return GNUNET_SYSERR; 1773 } 1774 GNUNET_break_op (0); 1775 return GNUNET_SYSERR; 1776 } 1777 1778 1779 struct GNUNET_JSON_Specification 1780 TALER_JSON_spec_otp_type (const char *name, 1781 enum TALER_MerchantConfirmationAlgorithm *mca) 1782 { 1783 struct GNUNET_JSON_Specification ret = { 1784 .parser = &parse_otp_type, 1785 .field = name, 1786 .ptr = mca 1787 }; 1788 1789 *mca = TALER_MCA_NONE; 1790 return ret; 1791 } 1792 1793 1794 /** 1795 * Parse given JSON object to `enum TALER_KYCLOGIC_KycTriggerEvent` 1796 * 1797 * @param cls closure, NULL 1798 * @param root the json object representing data 1799 * @param[out] spec where to write the data 1800 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1801 */ 1802 static enum GNUNET_GenericReturnValue 1803 parse_kycte (void *cls, 1804 json_t *root, 1805 struct GNUNET_JSON_Specification *spec) 1806 { 1807 static const struct Entry 1808 { 1809 const char *name; 1810 enum TALER_KYCLOGIC_KycTriggerEvent val; 1811 } lt [] = { 1812 { .name = "NONE", 1813 .val = TALER_KYCLOGIC_KYC_TRIGGER_NONE }, 1814 { .name = "WITHDRAW", 1815 .val = TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW }, 1816 { .name = "DEPOSIT", 1817 .val = TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT }, 1818 { .name = "MERGE", 1819 .val = TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE }, 1820 { .name = "BALANCE", 1821 .val = TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE }, 1822 { .name = "CLOSE", 1823 .val = TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE }, 1824 { .name = "AGGREGATE", 1825 .val = TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE }, 1826 { .name = "TRANSACTION", 1827 .val = TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION }, 1828 { .name = "REFUND", 1829 .val = TALER_KYCLOGIC_KYC_TRIGGER_REFUND }, 1830 { .name = NULL, 1831 .val = TALER_KYCLOGIC_KYC_TRIGGER_NONE }, 1832 }; 1833 enum TALER_KYCLOGIC_KycTriggerEvent *res 1834 = (enum TALER_KYCLOGIC_KycTriggerEvent *) spec->ptr; 1835 1836 (void) cls; 1837 if (json_is_string (root)) 1838 { 1839 const char *str; 1840 1841 str = json_string_value (root); 1842 if (NULL == str) 1843 { 1844 GNUNET_break_op (0); 1845 return GNUNET_SYSERR; 1846 } 1847 for (unsigned int i = 0; NULL != lt[i].name; i++) 1848 { 1849 if (0 == strcasecmp (str, 1850 lt[i].name)) 1851 { 1852 *res = lt[i].val; 1853 return GNUNET_OK; 1854 } 1855 } 1856 GNUNET_break_op (0); 1857 return GNUNET_SYSERR; 1858 } 1859 if (json_is_integer (root)) 1860 { 1861 json_int_t val; 1862 1863 val = json_integer_value (root); 1864 for (unsigned int i = 0; NULL != lt[i].name; i++) 1865 { 1866 if (val == lt[i].val) 1867 { 1868 *res = lt[i].val; 1869 return GNUNET_OK; 1870 } 1871 } 1872 GNUNET_break_op (0); 1873 return GNUNET_SYSERR; 1874 } 1875 GNUNET_break_op (0); 1876 return GNUNET_SYSERR; 1877 } 1878 1879 1880 struct GNUNET_JSON_Specification 1881 TALER_JSON_spec_kycte (const char *name, 1882 enum TALER_KYCLOGIC_KycTriggerEvent *kte) 1883 { 1884 struct GNUNET_JSON_Specification ret = { 1885 .parser = &parse_kycte, 1886 .field = name, 1887 .ptr = kte 1888 }; 1889 1890 *kte = TALER_KYCLOGIC_KYC_TRIGGER_NONE; 1891 return ret; 1892 } 1893 1894 1895 /** 1896 * Parser combinator of a tuple of parsers, for parsing 1897 * an array of expected size and element types. 1898 * 1899 * @param cls closure, array of specs, NULL terminated 1900 * @param root the json root 1901 * @param[out] spec where to write the data 1902 */ 1903 static enum GNUNET_GenericReturnValue 1904 parse_tuple_of (void *cls, 1905 json_t *root, 1906 struct GNUNET_JSON_Specification *spec) 1907 { 1908 struct GNUNET_JSON_Specification *specs = cls; 1909 static size_t max_specs = 100; 1910 bool found_end = false; 1911 1912 enum GNUNET_GenericReturnValue ret; 1913 1914 if (! json_is_array (root)) 1915 { 1916 return GNUNET_SYSERR; 1917 } 1918 1919 { 1920 size_t num; 1921 for (num = 0; num< max_specs; num++) 1922 { 1923 if (NULL == specs[num].parser) 1924 { 1925 found_end = true; 1926 break; 1927 } 1928 } 1929 GNUNET_assert (found_end); 1930 1931 if (num != json_array_size (root)) 1932 { 1933 GNUNET_break_op (0); 1934 return GNUNET_SYSERR; 1935 } 1936 } 1937 1938 { 1939 json_t *j_entry; 1940 size_t idx; 1941 1942 json_array_foreach (root, idx, j_entry) { 1943 ret = GNUNET_JSON_parse (j_entry, 1944 &specs[idx], 1945 NULL, 1946 NULL); 1947 if (GNUNET_OK != ret) 1948 { 1949 GNUNET_break_op (0); 1950 return GNUNET_SYSERR; 1951 } 1952 } 1953 } 1954 1955 return GNUNET_OK; 1956 } 1957 1958 1959 struct GNUNET_JSON_Specification 1960 TALER_JSON_spec_tuple_of ( 1961 const char *field, 1962 struct GNUNET_JSON_Specification specs[]) 1963 { 1964 struct GNUNET_JSON_Specification ret = { 1965 .parser = &parse_tuple_of, 1966 .field = field, 1967 .cls = specs 1968 }; 1969 1970 return ret; 1971 } 1972 1973 1974 /** 1975 * Parser for an array of unknown length but 1976 * of elements of the same type with the same 1977 * fixed length. 1978 * 1979 * @param cls closure, entry_size 1980 * @param root the json root 1981 * @param spec the output spec 1982 */ 1983 static enum GNUNET_GenericReturnValue 1984 parse_array_fixed (void *cls, 1985 json_t *root, 1986 struct GNUNET_JSON_Specification *spec) 1987 { 1988 enum GNUNET_GenericReturnValue ret; 1989 size_t entry_size = (size_t) cls; 1990 size_t num_entries; 1991 1992 GNUNET_assert (0< entry_size); 1993 num_entries = spec->ptr_size / entry_size; 1994 GNUNET_assert (0 < num_entries); 1995 1996 1997 if (! json_is_array (root)) 1998 { 1999 GNUNET_break_op (0); 2000 return GNUNET_SYSERR; 2001 } 2002 if (num_entries != json_array_size (root)) 2003 { 2004 GNUNET_break_op (0); 2005 return GNUNET_SYSERR; 2006 } 2007 2008 { 2009 json_t *j_entry; 2010 size_t idx; 2011 void *ptr = spec->ptr; 2012 void *end = spec->ptr + spec->ptr_size; 2013 2014 json_array_foreach (root, idx, j_entry) { 2015 struct GNUNET_JSON_Specification esp[] = { 2016 GNUNET_JSON_spec_fixed (NULL, 2017 ptr, 2018 entry_size), 2019 GNUNET_JSON_spec_end () 2020 }; 2021 GNUNET_assert (ptr < end); 2022 ret = GNUNET_JSON_parse (j_entry, 2023 esp, 2024 NULL, 2025 NULL); 2026 if (GNUNET_OK != ret) 2027 { 2028 GNUNET_break_op (0); 2029 return GNUNET_SYSERR; 2030 } 2031 ptr += entry_size; 2032 } 2033 } 2034 return GNUNET_OK; 2035 } 2036 2037 2038 struct GNUNET_JSON_Specification 2039 TALER_JSON_spec_array_fixed ( 2040 const char *field, 2041 size_t num_entries, 2042 void *entries, 2043 size_t entry_size) 2044 { 2045 struct GNUNET_JSON_Specification ret = { 2046 .parser = &parse_array_fixed, 2047 .ptr = entries, 2048 .ptr_size = entry_size * num_entries, 2049 .field = field, 2050 .cls = (void *) entry_size, 2051 }; 2052 2053 GNUNET_assert ((num_entries <= 1) || 2054 (entry_size * num_entries > entry_size)); 2055 return ret; 2056 } 2057 2058 2059 /** 2060 * Closure for the parser of arrays of fixed size data 2061 * of unknown array length 2062 */ 2063 struct closure_array_of_data 2064 { 2065 /** 2066 * Fixed (known) size per entry 2067 */ 2068 size_t entry_size; 2069 2070 /** 2071 * Pointer where to put the number of elements 2072 * allocated, i.e. the number of elements in the 2073 * json array. 2074 */ 2075 size_t *num_entries; 2076 }; 2077 2078 /** 2079 * Parser for an array of data of known element size, 2080 * but unknown array length 2081 */ 2082 static enum GNUNET_GenericReturnValue 2083 parse_array_of_data (void *cls, 2084 json_t *root, 2085 struct GNUNET_JSON_Specification *spec) 2086 { 2087 enum GNUNET_GenericReturnValue ret; 2088 struct closure_array_of_data *info = cls; 2089 size_t num_entries; 2090 2091 if (! json_is_array (root)) 2092 { 2093 GNUNET_break_op (0); 2094 return GNUNET_SYSERR; 2095 } 2096 num_entries = json_array_size (root); 2097 *info->num_entries = num_entries; 2098 if (0 == num_entries) 2099 { 2100 *(char **) spec->ptr = NULL; 2101 return GNUNET_OK; 2102 } 2103 2104 spec->ptr_size = num_entries * info->entry_size; 2105 GNUNET_assert (spec->ptr_size > num_entries); 2106 *((char **) spec->ptr) = GNUNET_malloc (spec->ptr_size); 2107 2108 { 2109 json_t *j_entry; 2110 size_t idx; 2111 char *ptr = *(char **) spec->ptr; 2112 char *end = ptr + spec->ptr_size; 2113 2114 json_array_foreach (root, idx, j_entry) { 2115 struct GNUNET_JSON_Specification esp[] = { 2116 GNUNET_JSON_spec_fixed (NULL, 2117 ptr, 2118 info->entry_size), 2119 GNUNET_JSON_spec_end () 2120 }; 2121 GNUNET_assert (ptr < end); 2122 ret = GNUNET_JSON_parse (j_entry, 2123 esp, 2124 NULL, 2125 NULL); 2126 if (GNUNET_OK != ret) 2127 { 2128 GNUNET_break_op (0); 2129 return GNUNET_SYSERR; 2130 } 2131 ptr += info->entry_size; 2132 } 2133 } 2134 return GNUNET_OK; 2135 } 2136 2137 2138 /** 2139 * Cleanup data left from parsing an array of fixed size (but unknown length). 2140 * 2141 * @param cls closure_of_array_data 2142 * @param[out] spec where to free the data 2143 */ 2144 static void 2145 cleaner_array_of_data (void *cls, 2146 struct GNUNET_JSON_Specification *spec) 2147 { 2148 struct closure_array_of_data *info = cls; 2149 2150 GNUNET_free (*(void **) spec->ptr); 2151 GNUNET_free (info); 2152 } 2153 2154 2155 struct GNUNET_JSON_Specification 2156 TALER_JSON_spec_array_of_data ( 2157 const char *field, 2158 size_t entry_size, 2159 size_t *num_entries, 2160 void **entries) 2161 { 2162 struct closure_array_of_data *cls; 2163 2164 GNUNET_assert (0< entry_size); 2165 GNUNET_assert (NULL != entries); 2166 cls = GNUNET_new (struct closure_array_of_data); 2167 cls->num_entries = num_entries; 2168 cls->entry_size = entry_size; 2169 { 2170 struct GNUNET_JSON_Specification ret = { 2171 .parser = &parse_array_of_data, 2172 .ptr = entries, 2173 .field = field, 2174 .cleaner = &cleaner_array_of_data, 2175 .cls = (void *) cls, 2176 }; 2177 2178 return ret; 2179 } 2180 } 2181 2182 2183 struct GNUNET_JSON_Specification 2184 TALER_JSON_spec_array_of_denom_pub_h ( 2185 const char *field, 2186 size_t *num_entries, 2187 struct TALER_DenominationHashP **entries) 2188 { 2189 return TALER_JSON_spec_array_of_data ( 2190 field, 2191 sizeof (struct TALER_DenominationHashP), 2192 num_entries, 2193 (void **) entries); 2194 } 2195 2196 2197 /** 2198 * Parser for an array of blinded denomination signatures, 2199 * of unknown array length 2200 */ 2201 static enum GNUNET_GenericReturnValue 2202 parse_array_of_blinded_denom_sigs (void *cls, 2203 json_t *root, 2204 struct GNUNET_JSON_Specification *spec) 2205 { 2206 enum GNUNET_GenericReturnValue ret; 2207 struct TALER_BlindedDenominationSignature *sigs = spec->ptr; 2208 size_t expected_num_entries = (size_t) cls; 2209 size_t num_entries; 2210 2211 if (! json_is_array (root)) 2212 { 2213 GNUNET_break_op (0); 2214 return GNUNET_SYSERR; 2215 } 2216 num_entries = json_array_size (root); 2217 if (num_entries != expected_num_entries) 2218 { 2219 GNUNET_break_op (0); 2220 return GNUNET_SYSERR; 2221 } 2222 2223 { 2224 json_t *j_entry; 2225 size_t idx; 2226 struct TALER_BlindedDenominationSignature *ptr = sigs; 2227 2228 json_array_foreach (root, idx, j_entry) { 2229 struct GNUNET_JSON_Specification esp[] = { 2230 TALER_JSON_spec_blinded_denom_sig (NULL, 2231 ptr), 2232 GNUNET_JSON_spec_end () 2233 }; 2234 ret = GNUNET_JSON_parse (j_entry, 2235 esp, 2236 NULL, 2237 NULL); 2238 if (GNUNET_OK != ret) 2239 { 2240 GNUNET_break_op (0); 2241 return GNUNET_SYSERR; 2242 } 2243 ptr++; 2244 } 2245 } 2246 return GNUNET_OK; 2247 } 2248 2249 2250 struct GNUNET_JSON_Specification 2251 TALER_JSON_spec_array_of_blinded_denom_sigs ( 2252 const char *field, 2253 size_t num_entries, 2254 struct TALER_BlindedDenominationSignature *entries) 2255 { 2256 struct GNUNET_JSON_Specification ret = { 2257 .parser = &parse_array_of_blinded_denom_sigs, 2258 .ptr = entries, 2259 .field = field, 2260 .cls = (void *) num_entries, 2261 }; 2262 return ret; 2263 } 2264 2265 2266 /* end of json/json_helper.c */