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