json_helper.c (55807B)
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 slug. 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_slug (void *cls, 1490 json_t *root, 1491 struct GNUNET_JSON_Specification *spec) 1492 { 1493 const char *str; 1494 1495 (void) cls; 1496 str = json_string_value (root); 1497 if (NULL == str) 1498 { 1499 GNUNET_break_op (0); 1500 return GNUNET_SYSERR; 1501 } 1502 if (! TALER_is_slug (str)) 1503 { 1504 GNUNET_break_op (0); 1505 return GNUNET_SYSERR; 1506 } 1507 *(const char **) spec->ptr = str; 1508 return GNUNET_OK; 1509 } 1510 1511 1512 struct GNUNET_JSON_Specification 1513 TALER_JSON_spec_slug (const char *field, 1514 const char **slug) 1515 { 1516 struct GNUNET_JSON_Specification ret = { 1517 .parser = &parse_slug, 1518 .field = field, 1519 .ptr = slug 1520 }; 1521 1522 *slug = NULL; 1523 return ret; 1524 } 1525 1526 1527 /** 1528 * Parse given JSON object to payto:// URI. 1529 * 1530 * @param cls closure, NULL 1531 * @param root the json object representing data 1532 * @param[out] spec where to write the data 1533 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1534 */ 1535 static enum GNUNET_GenericReturnValue 1536 parse_full_payto_uri (void *cls, 1537 json_t *root, 1538 struct GNUNET_JSON_Specification *spec) 1539 { 1540 struct TALER_FullPayto *payto_uri = spec->ptr; 1541 const char *str; 1542 char *err; 1543 1544 (void) cls; 1545 str = json_string_value (root); 1546 if (NULL == str) 1547 { 1548 GNUNET_break_op (0); 1549 return GNUNET_SYSERR; 1550 } 1551 payto_uri->full_payto = (char *) str; 1552 err = TALER_payto_validate (*payto_uri); 1553 if (NULL != err) 1554 { 1555 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1556 "payto:// malformed: %s\n", 1557 err); 1558 GNUNET_free (err); 1559 payto_uri->full_payto = NULL; 1560 return GNUNET_SYSERR; 1561 } 1562 return GNUNET_OK; 1563 } 1564 1565 1566 struct GNUNET_JSON_Specification 1567 TALER_JSON_spec_full_payto_uri ( 1568 const char *field, 1569 struct TALER_FullPayto *payto_uri) 1570 { 1571 struct GNUNET_JSON_Specification ret = { 1572 .parser = &parse_full_payto_uri, 1573 .field = field, 1574 .ptr = payto_uri 1575 }; 1576 1577 payto_uri->full_payto = NULL; 1578 return ret; 1579 } 1580 1581 1582 /** 1583 * Parse given JSON object to payto:// URI. 1584 * 1585 * @param cls closure, NULL 1586 * @param root the json object representing data 1587 * @param[out] spec where to write the data 1588 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1589 */ 1590 static enum GNUNET_GenericReturnValue 1591 parse_normalized_payto_uri (void *cls, 1592 json_t *root, 1593 struct GNUNET_JSON_Specification *spec) 1594 { 1595 struct TALER_NormalizedPayto *payto_uri = spec->ptr; 1596 const char *str; 1597 1598 (void) cls; 1599 str = json_string_value (root); 1600 if (NULL == str) 1601 { 1602 GNUNET_break_op (0); 1603 return GNUNET_SYSERR; 1604 } 1605 payto_uri->normalized_payto = (char *) str; 1606 { 1607 char *err; 1608 1609 err = TALER_normalized_payto_validate (*payto_uri); 1610 if (NULL != err) 1611 { 1612 GNUNET_break_op (0); 1613 GNUNET_free (err); 1614 payto_uri->normalized_payto = NULL; 1615 return GNUNET_SYSERR; 1616 } 1617 } 1618 return GNUNET_OK; 1619 } 1620 1621 1622 struct GNUNET_JSON_Specification 1623 TALER_JSON_spec_normalized_payto_uri ( 1624 const char *field, 1625 struct TALER_NormalizedPayto *payto_uri) 1626 { 1627 struct GNUNET_JSON_Specification ret = { 1628 .parser = &parse_normalized_payto_uri, 1629 .field = field, 1630 .ptr = payto_uri 1631 }; 1632 1633 payto_uri->normalized_payto = NULL; 1634 return ret; 1635 } 1636 1637 1638 /** 1639 * Parse given JSON object with protocol version. 1640 * 1641 * @param cls closure, NULL 1642 * @param root the json object representing data 1643 * @param[out] spec where to write the data 1644 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1645 */ 1646 static enum GNUNET_GenericReturnValue 1647 parse_protocol_version (void *cls, 1648 json_t *root, 1649 struct GNUNET_JSON_Specification *spec) 1650 { 1651 struct TALER_JSON_ProtocolVersion *pv = spec->ptr; 1652 const char *ver; 1653 char dummy; 1654 1655 (void) cls; 1656 if (! json_is_string (root)) 1657 { 1658 GNUNET_break_op (0); 1659 return GNUNET_SYSERR; 1660 } 1661 ver = json_string_value (root); 1662 if (3 != sscanf (ver, 1663 "%u:%u:%u%c", 1664 &pv->current, 1665 &pv->revision, 1666 &pv->age, 1667 &dummy)) 1668 { 1669 GNUNET_break_op (0); 1670 return GNUNET_SYSERR; 1671 } 1672 return GNUNET_OK; 1673 } 1674 1675 1676 struct GNUNET_JSON_Specification 1677 TALER_JSON_spec_version (const char *field, 1678 struct TALER_JSON_ProtocolVersion *ver) 1679 { 1680 struct GNUNET_JSON_Specification ret = { 1681 .parser = &parse_protocol_version, 1682 .field = field, 1683 .ptr = ver 1684 }; 1685 1686 return ret; 1687 } 1688 1689 1690 /** 1691 * Parse given JSON object to an OTP key. 1692 * 1693 * @param cls closure, NULL 1694 * @param root the json object representing data 1695 * @param[out] spec where to write the data 1696 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1697 */ 1698 static enum GNUNET_GenericReturnValue 1699 parse_otp_key (void *cls, 1700 json_t *root, 1701 struct GNUNET_JSON_Specification *spec) 1702 { 1703 const char *pos_key; 1704 1705 (void) cls; 1706 pos_key = json_string_value (root); 1707 if (NULL == pos_key) 1708 { 1709 GNUNET_break_op (0); 1710 return GNUNET_SYSERR; 1711 } 1712 { 1713 size_t pos_key_length = strlen (pos_key); 1714 void *key; /* pos_key in binary */ 1715 size_t key_len; /* length of the key */ 1716 int dret; 1717 1718 key_len = pos_key_length * 5 / 8; 1719 key = GNUNET_malloc (key_len); 1720 dret = TALER_rfc3548_base32decode (pos_key, 1721 pos_key_length, 1722 key, 1723 key_len); 1724 if (-1 == dret) 1725 { 1726 GNUNET_free (key); 1727 GNUNET_break_op (0); 1728 return GNUNET_SYSERR; 1729 } 1730 GNUNET_free (key); 1731 } 1732 *(const char **) spec->ptr = pos_key; 1733 return GNUNET_OK; 1734 } 1735 1736 1737 struct GNUNET_JSON_Specification 1738 TALER_JSON_spec_otp_key (const char *name, 1739 const char **otp_key) 1740 { 1741 struct GNUNET_JSON_Specification ret = { 1742 .parser = &parse_otp_key, 1743 .field = name, 1744 .ptr = otp_key 1745 }; 1746 1747 *otp_key = NULL; 1748 return ret; 1749 } 1750 1751 1752 /** 1753 * Parse given JSON object to `enum TALER_MerchantConfirmationAlgorithm` 1754 * 1755 * @param cls closure, NULL 1756 * @param root the json object representing data 1757 * @param[out] spec where to write the data 1758 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1759 */ 1760 static enum GNUNET_GenericReturnValue 1761 parse_otp_type (void *cls, 1762 json_t *root, 1763 struct GNUNET_JSON_Specification *spec) 1764 { 1765 static const struct Entry 1766 { 1767 const char *name; 1768 enum TALER_MerchantConfirmationAlgorithm val; 1769 } lt [] = { 1770 { .name = "NONE", 1771 .val = TALER_MCA_NONE }, 1772 { .name = "TOTP_WITHOUT_PRICE", 1773 .val = TALER_MCA_WITHOUT_PRICE }, 1774 { .name = "TOTP_WITH_PRICE", 1775 .val = TALER_MCA_WITH_PRICE }, 1776 { .name = NULL, 1777 .val = TALER_MCA_NONE }, 1778 }; 1779 enum TALER_MerchantConfirmationAlgorithm *res 1780 = (enum TALER_MerchantConfirmationAlgorithm *) spec->ptr; 1781 1782 (void) cls; 1783 if (json_is_string (root)) 1784 { 1785 const char *str; 1786 1787 str = json_string_value (root); 1788 if (NULL == str) 1789 { 1790 GNUNET_break_op (0); 1791 return GNUNET_SYSERR; 1792 } 1793 for (unsigned int i = 0; NULL != lt[i].name; i++) 1794 { 1795 if (0 == strcasecmp (str, 1796 lt[i].name)) 1797 { 1798 *res = lt[i].val; 1799 return GNUNET_OK; 1800 } 1801 } 1802 GNUNET_break_op (0); 1803 } 1804 if (json_is_integer (root)) 1805 { 1806 json_int_t val; 1807 1808 val = json_integer_value (root); 1809 for (unsigned int i = 0; NULL != lt[i].name; i++) 1810 { 1811 if (val == lt[i].val) 1812 { 1813 *res = lt[i].val; 1814 return GNUNET_OK; 1815 } 1816 } 1817 GNUNET_break_op (0); 1818 return GNUNET_SYSERR; 1819 } 1820 GNUNET_break_op (0); 1821 return GNUNET_SYSERR; 1822 } 1823 1824 1825 struct GNUNET_JSON_Specification 1826 TALER_JSON_spec_otp_type (const char *name, 1827 enum TALER_MerchantConfirmationAlgorithm *mca) 1828 { 1829 struct GNUNET_JSON_Specification ret = { 1830 .parser = &parse_otp_type, 1831 .field = name, 1832 .ptr = mca 1833 }; 1834 1835 *mca = TALER_MCA_NONE; 1836 return ret; 1837 } 1838 1839 1840 /** 1841 * Parse given JSON object to `enum TALER_KYCLOGIC_KycTriggerEvent` 1842 * 1843 * @param cls closure, NULL 1844 * @param root the json object representing data 1845 * @param[out] spec where to write the data 1846 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1847 */ 1848 static enum GNUNET_GenericReturnValue 1849 parse_kycte (void *cls, 1850 json_t *root, 1851 struct GNUNET_JSON_Specification *spec) 1852 { 1853 static const struct Entry 1854 { 1855 const char *name; 1856 enum TALER_KYCLOGIC_KycTriggerEvent val; 1857 } lt [] = { 1858 { .name = "NONE", 1859 .val = TALER_KYCLOGIC_KYC_TRIGGER_NONE }, 1860 { .name = "WITHDRAW", 1861 .val = TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW }, 1862 { .name = "DEPOSIT", 1863 .val = TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT }, 1864 { .name = "MERGE", 1865 .val = TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE }, 1866 { .name = "BALANCE", 1867 .val = TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE }, 1868 { .name = "CLOSE", 1869 .val = TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE }, 1870 { .name = "AGGREGATE", 1871 .val = TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE }, 1872 { .name = "TRANSACTION", 1873 .val = TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION }, 1874 { .name = "REFUND", 1875 .val = TALER_KYCLOGIC_KYC_TRIGGER_REFUND }, 1876 { .name = NULL, 1877 .val = TALER_KYCLOGIC_KYC_TRIGGER_NONE }, 1878 }; 1879 enum TALER_KYCLOGIC_KycTriggerEvent *res 1880 = (enum TALER_KYCLOGIC_KycTriggerEvent *) spec->ptr; 1881 1882 (void) cls; 1883 if (json_is_string (root)) 1884 { 1885 const char *str; 1886 1887 str = json_string_value (root); 1888 if (NULL == str) 1889 { 1890 GNUNET_break_op (0); 1891 return GNUNET_SYSERR; 1892 } 1893 for (unsigned int i = 0; NULL != lt[i].name; i++) 1894 { 1895 if (0 == strcasecmp (str, 1896 lt[i].name)) 1897 { 1898 *res = lt[i].val; 1899 return GNUNET_OK; 1900 } 1901 } 1902 GNUNET_break_op (0); 1903 return GNUNET_SYSERR; 1904 } 1905 if (json_is_integer (root)) 1906 { 1907 json_int_t val; 1908 1909 val = json_integer_value (root); 1910 for (unsigned int i = 0; NULL != lt[i].name; i++) 1911 { 1912 if (val == lt[i].val) 1913 { 1914 *res = lt[i].val; 1915 return GNUNET_OK; 1916 } 1917 } 1918 GNUNET_break_op (0); 1919 return GNUNET_SYSERR; 1920 } 1921 GNUNET_break_op (0); 1922 return GNUNET_SYSERR; 1923 } 1924 1925 1926 struct GNUNET_JSON_Specification 1927 TALER_JSON_spec_kycte (const char *name, 1928 enum TALER_KYCLOGIC_KycTriggerEvent *kte) 1929 { 1930 struct GNUNET_JSON_Specification ret = { 1931 .parser = &parse_kycte, 1932 .field = name, 1933 .ptr = kte 1934 }; 1935 1936 *kte = TALER_KYCLOGIC_KYC_TRIGGER_NONE; 1937 return ret; 1938 } 1939 1940 1941 /** 1942 * Parser combinator of a tuple of parsers, for parsing 1943 * an array of expected size and element types. 1944 * 1945 * @param cls closure, array of specs, NULL terminated 1946 * @param root the json root 1947 * @param[out] spec where to write the data 1948 */ 1949 static enum GNUNET_GenericReturnValue 1950 parse_tuple_of (void *cls, 1951 json_t *root, 1952 struct GNUNET_JSON_Specification *spec) 1953 { 1954 struct GNUNET_JSON_Specification *specs = cls; 1955 static size_t max_specs = 100; 1956 bool found_end = false; 1957 1958 enum GNUNET_GenericReturnValue ret; 1959 1960 if (! json_is_array (root)) 1961 { 1962 return GNUNET_SYSERR; 1963 } 1964 1965 { 1966 size_t num; 1967 for (num = 0; num< max_specs; num++) 1968 { 1969 if (NULL == specs[num].parser) 1970 { 1971 found_end = true; 1972 break; 1973 } 1974 } 1975 GNUNET_assert (found_end); 1976 1977 if (num != json_array_size (root)) 1978 { 1979 GNUNET_break_op (0); 1980 return GNUNET_SYSERR; 1981 } 1982 } 1983 1984 { 1985 json_t *j_entry; 1986 size_t idx; 1987 1988 json_array_foreach (root, idx, j_entry) { 1989 ret = GNUNET_JSON_parse (j_entry, 1990 &specs[idx], 1991 NULL, 1992 NULL); 1993 if (GNUNET_OK != ret) 1994 { 1995 GNUNET_break_op (0); 1996 return GNUNET_SYSERR; 1997 } 1998 } 1999 } 2000 2001 return GNUNET_OK; 2002 } 2003 2004 2005 struct GNUNET_JSON_Specification 2006 TALER_JSON_spec_tuple_of ( 2007 const char *field, 2008 struct GNUNET_JSON_Specification specs[]) 2009 { 2010 struct GNUNET_JSON_Specification ret = { 2011 .parser = &parse_tuple_of, 2012 .field = field, 2013 .cls = specs 2014 }; 2015 2016 return ret; 2017 } 2018 2019 2020 /** 2021 * Parser for an array of unknown length but 2022 * of elements of the same type with the same 2023 * fixed length. 2024 * 2025 * @param cls closure, entry_size 2026 * @param root the json root 2027 * @param spec the output spec 2028 */ 2029 static enum GNUNET_GenericReturnValue 2030 parse_array_fixed (void *cls, 2031 json_t *root, 2032 struct GNUNET_JSON_Specification *spec) 2033 { 2034 enum GNUNET_GenericReturnValue ret; 2035 size_t entry_size = (size_t) cls; 2036 size_t num_entries; 2037 2038 GNUNET_assert (0< entry_size); 2039 num_entries = spec->ptr_size / entry_size; 2040 GNUNET_assert (0 < num_entries); 2041 2042 2043 if (! json_is_array (root)) 2044 { 2045 GNUNET_break_op (0); 2046 return GNUNET_SYSERR; 2047 } 2048 if (num_entries != json_array_size (root)) 2049 { 2050 GNUNET_break_op (0); 2051 return GNUNET_SYSERR; 2052 } 2053 2054 { 2055 json_t *j_entry; 2056 size_t idx; 2057 void *ptr = spec->ptr; 2058 void *end = spec->ptr + spec->ptr_size; 2059 2060 json_array_foreach (root, idx, j_entry) { 2061 struct GNUNET_JSON_Specification esp[] = { 2062 GNUNET_JSON_spec_fixed (NULL, 2063 ptr, 2064 entry_size), 2065 GNUNET_JSON_spec_end () 2066 }; 2067 GNUNET_assert (ptr < end); 2068 ret = GNUNET_JSON_parse (j_entry, 2069 esp, 2070 NULL, 2071 NULL); 2072 if (GNUNET_OK != ret) 2073 { 2074 GNUNET_break_op (0); 2075 return GNUNET_SYSERR; 2076 } 2077 ptr += entry_size; 2078 } 2079 } 2080 return GNUNET_OK; 2081 } 2082 2083 2084 struct GNUNET_JSON_Specification 2085 TALER_JSON_spec_array_fixed ( 2086 const char *field, 2087 size_t num_entries, 2088 void *entries, 2089 size_t entry_size) 2090 { 2091 struct GNUNET_JSON_Specification ret = { 2092 .parser = &parse_array_fixed, 2093 .ptr = entries, 2094 .ptr_size = entry_size * num_entries, 2095 .field = field, 2096 .cls = (void *) entry_size, 2097 }; 2098 2099 GNUNET_assert ((num_entries <= 1) || 2100 (entry_size * num_entries > entry_size)); 2101 return ret; 2102 } 2103 2104 2105 /** 2106 * Closure for the parser of arrays of fixed size data 2107 * of unknown array length 2108 */ 2109 struct closure_array_of_data 2110 { 2111 /** 2112 * Fixed (known) size per entry 2113 */ 2114 size_t entry_size; 2115 2116 /** 2117 * Pointer where to put the number of elements 2118 * allocated, i.e. the number of elements in the 2119 * json array. 2120 */ 2121 size_t *num_entries; 2122 }; 2123 2124 /** 2125 * Parser for an array of data of known element size, 2126 * but unknown array length 2127 */ 2128 static enum GNUNET_GenericReturnValue 2129 parse_array_of_data (void *cls, 2130 json_t *root, 2131 struct GNUNET_JSON_Specification *spec) 2132 { 2133 enum GNUNET_GenericReturnValue ret; 2134 struct closure_array_of_data *info = cls; 2135 size_t num_entries; 2136 2137 if (! json_is_array (root)) 2138 { 2139 GNUNET_break_op (0); 2140 return GNUNET_SYSERR; 2141 } 2142 num_entries = json_array_size (root); 2143 *info->num_entries = num_entries; 2144 if (0 == num_entries) 2145 { 2146 *(char **) spec->ptr = NULL; 2147 return GNUNET_OK; 2148 } 2149 2150 spec->ptr_size = num_entries * info->entry_size; 2151 GNUNET_assert (spec->ptr_size > num_entries); 2152 *((char **) spec->ptr) = GNUNET_malloc (spec->ptr_size); 2153 2154 { 2155 json_t *j_entry; 2156 size_t idx; 2157 char *ptr = *(char **) spec->ptr; 2158 char *end = ptr + spec->ptr_size; 2159 2160 json_array_foreach (root, idx, j_entry) { 2161 struct GNUNET_JSON_Specification esp[] = { 2162 GNUNET_JSON_spec_fixed (NULL, 2163 ptr, 2164 info->entry_size), 2165 GNUNET_JSON_spec_end () 2166 }; 2167 GNUNET_assert (ptr < end); 2168 ret = GNUNET_JSON_parse (j_entry, 2169 esp, 2170 NULL, 2171 NULL); 2172 if (GNUNET_OK != ret) 2173 { 2174 GNUNET_break_op (0); 2175 return GNUNET_SYSERR; 2176 } 2177 ptr += info->entry_size; 2178 } 2179 } 2180 return GNUNET_OK; 2181 } 2182 2183 2184 /** 2185 * Cleanup data left from parsing an array of fixed size (but unknown length). 2186 * 2187 * @param cls closure_of_array_data 2188 * @param[out] spec where to free the data 2189 */ 2190 static void 2191 cleaner_array_of_data (void *cls, 2192 struct GNUNET_JSON_Specification *spec) 2193 { 2194 struct closure_array_of_data *info = cls; 2195 2196 GNUNET_free (*(void **) spec->ptr); 2197 GNUNET_free (info); 2198 } 2199 2200 2201 struct GNUNET_JSON_Specification 2202 TALER_JSON_spec_array_of_data ( 2203 const char *field, 2204 size_t entry_size, 2205 size_t *num_entries, 2206 void **entries) 2207 { 2208 struct closure_array_of_data *cls; 2209 2210 GNUNET_assert (0< entry_size); 2211 *entries = NULL; 2212 *num_entries = 0; 2213 cls = GNUNET_new (struct closure_array_of_data); 2214 cls->num_entries = num_entries; 2215 cls->entry_size = entry_size; 2216 { 2217 struct GNUNET_JSON_Specification ret = { 2218 .parser = &parse_array_of_data, 2219 .ptr = entries, 2220 .field = field, 2221 .cleaner = &cleaner_array_of_data, 2222 .cls = (void *) cls, 2223 }; 2224 2225 return ret; 2226 } 2227 } 2228 2229 2230 struct GNUNET_JSON_Specification 2231 TALER_JSON_spec_array_of_denom_pub_h ( 2232 const char *field, 2233 size_t *num_entries, 2234 struct TALER_DenominationHashP **entries) 2235 { 2236 *num_entries = 0; 2237 *entries = NULL; 2238 return TALER_JSON_spec_array_of_data ( 2239 field, 2240 sizeof (struct TALER_DenominationHashP), 2241 num_entries, 2242 (void **) entries); 2243 } 2244 2245 2246 /** 2247 * Parser for an array of blinded denomination signatures, 2248 * of unknown array length 2249 */ 2250 static enum GNUNET_GenericReturnValue 2251 parse_array_of_blinded_denom_sigs (void *cls, 2252 json_t *root, 2253 struct GNUNET_JSON_Specification *spec) 2254 { 2255 enum GNUNET_GenericReturnValue ret; 2256 struct TALER_BlindedDenominationSignature *sigs = spec->ptr; 2257 size_t expected_num_entries = (size_t) cls; 2258 size_t num_entries; 2259 2260 if (! json_is_array (root)) 2261 { 2262 GNUNET_break_op (0); 2263 return GNUNET_SYSERR; 2264 } 2265 num_entries = json_array_size (root); 2266 if (num_entries != expected_num_entries) 2267 { 2268 GNUNET_break_op (0); 2269 return GNUNET_SYSERR; 2270 } 2271 2272 { 2273 json_t *j_entry; 2274 size_t idx; 2275 struct TALER_BlindedDenominationSignature *ptr = sigs; 2276 2277 json_array_foreach (root, idx, j_entry) { 2278 struct GNUNET_JSON_Specification esp[] = { 2279 TALER_JSON_spec_blinded_denom_sig (NULL, 2280 ptr), 2281 GNUNET_JSON_spec_end () 2282 }; 2283 ret = GNUNET_JSON_parse (j_entry, 2284 esp, 2285 NULL, 2286 NULL); 2287 if (GNUNET_OK != ret) 2288 { 2289 GNUNET_break_op (0); 2290 return GNUNET_SYSERR; 2291 } 2292 ptr++; 2293 } 2294 } 2295 return GNUNET_OK; 2296 } 2297 2298 2299 struct GNUNET_JSON_Specification 2300 TALER_JSON_spec_array_of_blinded_denom_sigs ( 2301 const char *field, 2302 size_t num_entries, 2303 struct TALER_BlindedDenominationSignature *entries) 2304 { 2305 struct GNUNET_JSON_Specification ret = { 2306 .parser = &parse_array_of_blinded_denom_sigs, 2307 .ptr = entries, 2308 .field = field, 2309 .cls = (void *) num_entries, 2310 }; 2311 2312 for (size_t i = 0; i<num_entries; i++) 2313 entries[i].blinded_sig = NULL; 2314 return ret; 2315 } 2316 2317 2318 /* end of json/json_helper.c */