json_helper.c (56626B)
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 gspec[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 gspec[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_free (age_commitment->pubs); 643 age_commitment->num = 0; 644 return GNUNET_SYSERR; 645 } 646 }; 647 648 return GNUNET_OK; 649 } 650 651 652 /** 653 * Cleanup data left from parsing age commitment 654 * 655 * @param cls closure, NULL 656 * @param[out] spec where to free the data 657 */ 658 static void 659 clean_age_commitment (void *cls, 660 struct GNUNET_JSON_Specification *spec) 661 { 662 struct TALER_AgeCommitment *age_commitment = spec->ptr; 663 664 (void) cls; 665 if ( (NULL == age_commitment) || 666 (NULL == age_commitment->pubs) ) 667 return; 668 age_commitment->num = 0; 669 GNUNET_free (age_commitment->pubs); 670 } 671 672 673 struct GNUNET_JSON_Specification 674 TALER_JSON_spec_age_commitment (const char *name, 675 struct TALER_AgeCommitment *age_commitment) 676 { 677 struct GNUNET_JSON_Specification ret = { 678 .parser = &parse_age_commitment, 679 .cleaner = &clean_age_commitment, 680 .field = name, 681 .ptr = age_commitment 682 }; 683 684 return ret; 685 } 686 687 688 struct GNUNET_JSON_Specification 689 TALER_JSON_spec_token_issue_sig (const char *field, 690 struct TALER_TokenIssueSignature *sig) 691 { 692 sig->signature = NULL; 693 return GNUNET_JSON_spec_unblinded_signature (field, 694 &sig->signature); 695 } 696 697 698 struct GNUNET_JSON_Specification 699 TALER_JSON_spec_blinded_token_issue_sig ( 700 const char *field, 701 struct TALER_BlindedTokenIssueSignature *sig) 702 { 703 sig->signature = NULL; 704 return GNUNET_JSON_spec_blinded_signature (field, 705 &sig->signature); 706 } 707 708 709 struct GNUNET_JSON_Specification 710 TALER_JSON_spec_token_envelope (const char *field, 711 struct TALER_TokenEnvelope *env) 712 { 713 env->blinded_pub = NULL; 714 return GNUNET_JSON_spec_blinded_message (field, 715 &env->blinded_pub); 716 } 717 718 719 /** 720 * Parse given JSON object to denomination public key. 721 * 722 * @param cls closure, NULL 723 * @param root the json object representing data 724 * @param[out] spec where to write the data 725 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 726 */ 727 static enum GNUNET_GenericReturnValue 728 parse_denom_pub (void *cls, 729 json_t *root, 730 struct GNUNET_JSON_Specification *spec) 731 { 732 struct TALER_DenominationPublicKey *denom_pub = spec->ptr; 733 struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub; 734 const char *cipher; 735 bool age_mask_missing = false; 736 struct GNUNET_JSON_Specification dspec[] = { 737 GNUNET_JSON_spec_string ("cipher", 738 &cipher), 739 GNUNET_JSON_spec_mark_optional ( 740 GNUNET_JSON_spec_uint32 ("age_mask", 741 &denom_pub->age_mask.bits), 742 &age_mask_missing), 743 GNUNET_JSON_spec_end () 744 }; 745 const char *emsg; 746 unsigned int eline; 747 748 (void) cls; 749 if (GNUNET_OK != 750 GNUNET_JSON_parse (root, 751 dspec, 752 &emsg, 753 &eline)) 754 { 755 GNUNET_break_op (0); 756 return GNUNET_SYSERR; 757 } 758 759 if (age_mask_missing) 760 denom_pub->age_mask.bits = 0; 761 bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey); 762 bsign_pub->rc = 1; 763 bsign_pub->cipher = string_to_cipher (cipher); 764 switch (bsign_pub->cipher) 765 { 766 case GNUNET_CRYPTO_BSA_INVALID: 767 break; 768 case GNUNET_CRYPTO_BSA_RSA: 769 { 770 struct GNUNET_JSON_Specification ispec[] = { 771 GNUNET_JSON_spec_rsa_public_key ( 772 "rsa_pub", 773 &bsign_pub->details.rsa_public_key), 774 GNUNET_JSON_spec_end () 775 }; 776 777 if (GNUNET_OK != 778 GNUNET_JSON_parse (root, 779 ispec, 780 &emsg, 781 &eline)) 782 { 783 GNUNET_break_op (0); 784 GNUNET_free (bsign_pub); 785 return GNUNET_SYSERR; 786 } 787 denom_pub->bsign_pub_key = bsign_pub; 788 return GNUNET_OK; 789 } 790 case GNUNET_CRYPTO_BSA_CS: 791 { 792 struct GNUNET_JSON_Specification ispec[] = { 793 GNUNET_JSON_spec_fixed ("cs_pub", 794 &bsign_pub->details.cs_public_key, 795 sizeof (bsign_pub->details.cs_public_key)), 796 GNUNET_JSON_spec_end () 797 }; 798 799 if (GNUNET_OK != 800 GNUNET_JSON_parse (root, 801 ispec, 802 &emsg, 803 &eline)) 804 { 805 GNUNET_break_op (0); 806 GNUNET_free (bsign_pub); 807 return GNUNET_SYSERR; 808 } 809 denom_pub->bsign_pub_key = bsign_pub; 810 return GNUNET_OK; 811 } 812 } 813 GNUNET_break_op (0); 814 GNUNET_free (bsign_pub); 815 return GNUNET_SYSERR; 816 } 817 818 819 /** 820 * Cleanup data left from parsing denomination public key. 821 * 822 * @param cls closure, NULL 823 * @param[out] spec where to free the data 824 */ 825 static void 826 clean_denom_pub (void *cls, 827 struct GNUNET_JSON_Specification *spec) 828 { 829 struct TALER_DenominationPublicKey *denom_pub = spec->ptr; 830 831 (void) cls; 832 TALER_denom_pub_free (denom_pub); 833 } 834 835 836 struct GNUNET_JSON_Specification 837 TALER_JSON_spec_denom_pub (const char *field, 838 struct TALER_DenominationPublicKey *pk) 839 { 840 struct GNUNET_JSON_Specification ret = { 841 .parser = &parse_denom_pub, 842 .cleaner = &clean_denom_pub, 843 .field = field, 844 .ptr = pk 845 }; 846 847 pk->bsign_pub_key = NULL; 848 return ret; 849 } 850 851 852 /** 853 * Parse given JSON object to token issue public key. 854 * 855 * @param cls closure, NULL 856 * @param root the json object representing data 857 * @param[out] spec where to write the data 858 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 859 */ 860 static enum GNUNET_GenericReturnValue 861 parse_token_pub (void *cls, 862 json_t *root, 863 struct GNUNET_JSON_Specification *spec) 864 { 865 struct TALER_TokenIssuePublicKey *token_pub = spec->ptr; 866 struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub; 867 const char *cipher; 868 struct GNUNET_JSON_Specification dspec[] = { 869 GNUNET_JSON_spec_string ("cipher", 870 &cipher), 871 GNUNET_JSON_spec_end () 872 }; 873 const char *emsg; 874 unsigned int eline; 875 876 (void) cls; 877 if (GNUNET_OK != 878 GNUNET_JSON_parse (root, 879 dspec, 880 &emsg, 881 &eline)) 882 { 883 GNUNET_break_op (0); 884 return GNUNET_SYSERR; 885 } 886 887 bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey); 888 bsign_pub->rc = 1; 889 bsign_pub->cipher = string_to_cipher (cipher); 890 switch (bsign_pub->cipher) 891 { 892 case GNUNET_CRYPTO_BSA_INVALID: 893 break; 894 case GNUNET_CRYPTO_BSA_RSA: 895 { 896 struct GNUNET_JSON_Specification ispec[] = { 897 GNUNET_JSON_spec_rsa_public_key ( 898 "rsa_pub", 899 &bsign_pub->details.rsa_public_key), 900 GNUNET_JSON_spec_end () 901 }; 902 903 if (GNUNET_OK != 904 GNUNET_JSON_parse (root, 905 ispec, 906 &emsg, 907 &eline)) 908 { 909 GNUNET_break_op (0); 910 GNUNET_free (bsign_pub); 911 return GNUNET_SYSERR; 912 } 913 GNUNET_CRYPTO_rsa_public_key_hash (bsign_pub->details.rsa_public_key, 914 &bsign_pub->pub_key_hash); 915 token_pub->public_key = bsign_pub; 916 return GNUNET_OK; 917 } 918 case GNUNET_CRYPTO_BSA_CS: 919 { 920 struct GNUNET_JSON_Specification ispec[] = { 921 GNUNET_JSON_spec_fixed ("cs_pub", 922 &bsign_pub->details.cs_public_key, 923 sizeof (bsign_pub->details.cs_public_key)), 924 GNUNET_JSON_spec_end () 925 }; 926 927 if (GNUNET_OK != 928 GNUNET_JSON_parse (root, 929 ispec, 930 &emsg, 931 &eline)) 932 { 933 GNUNET_break_op (0); 934 GNUNET_free (bsign_pub); 935 return GNUNET_SYSERR; 936 } 937 GNUNET_CRYPTO_hash (&bsign_pub->details.cs_public_key, 938 sizeof(bsign_pub->details.cs_public_key), 939 &bsign_pub->pub_key_hash); 940 token_pub->public_key = bsign_pub; 941 return GNUNET_OK; 942 } 943 } 944 GNUNET_break_op (0); 945 GNUNET_free (bsign_pub); 946 return GNUNET_SYSERR; 947 } 948 949 950 /** 951 * Cleanup data left from parsing token issue public key. 952 * 953 * @param cls closure, NULL 954 * @param[out] spec where to free the data 955 */ 956 static void 957 clean_token_pub (void *cls, 958 struct GNUNET_JSON_Specification *spec) 959 { 960 struct TALER_TokenIssuePublicKey *token_pub = spec->ptr; 961 962 (void) cls; 963 TALER_token_issue_pub_free (token_pub); 964 } 965 966 967 struct GNUNET_JSON_Specification 968 TALER_JSON_spec_token_pub (const char *field, 969 struct TALER_TokenIssuePublicKey *pk) 970 { 971 struct GNUNET_JSON_Specification ret = { 972 .field = field, 973 .parser = &parse_token_pub, 974 .cleaner = &clean_token_pub, 975 .ptr = pk 976 }; 977 978 pk->public_key = NULL; 979 return ret; 980 } 981 982 983 /** 984 * Parse given JSON object partially into a denomination public key. 985 * 986 * Depending on the cipher in cls, it parses the corresponding public key type. 987 * 988 * @param cls closure, enum GNUNET_CRYPTO_BlindSignatureAlgorithm 989 * @param root the json object representing data 990 * @param[out] spec where to write the data 991 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 992 */ 993 static enum GNUNET_GenericReturnValue 994 parse_denom_pub_cipher (void *cls, 995 json_t *root, 996 struct GNUNET_JSON_Specification *spec) 997 { 998 struct TALER_DenominationPublicKey *denom_pub = spec->ptr; 999 enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher = 1000 (enum GNUNET_CRYPTO_BlindSignatureAlgorithm) (long) cls; 1001 struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub; 1002 const char *emsg; 1003 unsigned int eline; 1004 1005 bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey); 1006 bsign_pub->cipher = cipher; 1007 bsign_pub->rc = 1; 1008 switch (cipher) 1009 { 1010 case GNUNET_CRYPTO_BSA_INVALID: 1011 break; 1012 case GNUNET_CRYPTO_BSA_RSA: 1013 { 1014 struct GNUNET_JSON_Specification ispec[] = { 1015 GNUNET_JSON_spec_rsa_public_key ( 1016 "rsa_pub", 1017 &bsign_pub->details.rsa_public_key), 1018 GNUNET_JSON_spec_end () 1019 }; 1020 1021 if (GNUNET_OK != 1022 GNUNET_JSON_parse (root, 1023 ispec, 1024 &emsg, 1025 &eline)) 1026 { 1027 GNUNET_break_op (0); 1028 GNUNET_free (bsign_pub); 1029 return GNUNET_SYSERR; 1030 } 1031 denom_pub->bsign_pub_key = bsign_pub; 1032 return GNUNET_OK; 1033 } 1034 case GNUNET_CRYPTO_BSA_CS: 1035 { 1036 struct GNUNET_JSON_Specification ispec[] = { 1037 GNUNET_JSON_spec_fixed ("cs_pub", 1038 &bsign_pub->details.cs_public_key, 1039 sizeof (bsign_pub->details.cs_public_key)), 1040 GNUNET_JSON_spec_end () 1041 }; 1042 1043 if (GNUNET_OK != 1044 GNUNET_JSON_parse (root, 1045 ispec, 1046 &emsg, 1047 &eline)) 1048 { 1049 GNUNET_break_op (0); 1050 GNUNET_free (bsign_pub); 1051 return GNUNET_SYSERR; 1052 } 1053 denom_pub->bsign_pub_key = bsign_pub; 1054 return GNUNET_OK; 1055 } 1056 } 1057 GNUNET_break_op (0); 1058 GNUNET_free (bsign_pub); 1059 return GNUNET_SYSERR; 1060 } 1061 1062 1063 struct GNUNET_JSON_Specification 1064 TALER_JSON_spec_denom_pub_cipher ( 1065 const char *field, 1066 enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher, 1067 struct TALER_DenominationPublicKey *pk) 1068 { 1069 struct GNUNET_JSON_Specification ret = { 1070 .parser = &parse_denom_pub_cipher, 1071 .cleaner = &clean_denom_pub, 1072 .field = field, 1073 .cls = (void *) cipher, 1074 .ptr = pk 1075 }; 1076 1077 pk->bsign_pub_key = NULL; 1078 return ret; 1079 } 1080 1081 1082 struct GNUNET_JSON_Specification 1083 TALER_JSON_spec_denom_sig (const char *field, 1084 struct TALER_DenominationSignature *sig) 1085 { 1086 sig->unblinded_sig = NULL; 1087 return GNUNET_JSON_spec_unblinded_signature (field, 1088 &sig->unblinded_sig); 1089 } 1090 1091 1092 struct GNUNET_JSON_Specification 1093 TALER_JSON_spec_blinded_denom_sig ( 1094 const char *field, 1095 struct TALER_BlindedDenominationSignature *sig) 1096 { 1097 sig->blinded_sig = NULL; 1098 return GNUNET_JSON_spec_blinded_signature (field, 1099 &sig->blinded_sig); 1100 } 1101 1102 1103 struct GNUNET_JSON_Specification 1104 TALER_JSON_spec_blinded_planchet ( 1105 const char *field, 1106 struct TALER_BlindedPlanchet *blinded_planchet) 1107 { 1108 blinded_planchet->blinded_message = NULL; 1109 return GNUNET_JSON_spec_blinded_message (field, 1110 &blinded_planchet->blinded_message); 1111 } 1112 1113 1114 /** 1115 * Parse given JSON object to exchange withdraw values (/csr). 1116 * 1117 * @param cls closure, NULL 1118 * @param root the json object representing data 1119 * @param[out] spec where to write the data 1120 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1121 */ 1122 static enum GNUNET_GenericReturnValue 1123 parse_exchange_blinding_values (void *cls, 1124 json_t *root, 1125 struct GNUNET_JSON_Specification *spec) 1126 { 1127 struct TALER_ExchangeBlindingValues *ewv = spec->ptr; 1128 struct GNUNET_CRYPTO_BlindingInputValues *bi; 1129 const char *cipher; 1130 struct GNUNET_JSON_Specification dspec[] = { 1131 GNUNET_JSON_spec_string ("cipher", 1132 &cipher), 1133 GNUNET_JSON_spec_end () 1134 }; 1135 const char *emsg; 1136 unsigned int eline; 1137 enum GNUNET_CRYPTO_BlindSignatureAlgorithm ci; 1138 1139 (void) cls; 1140 if (GNUNET_OK != 1141 GNUNET_JSON_parse (root, 1142 dspec, 1143 &emsg, 1144 &eline)) 1145 { 1146 GNUNET_break_op (0); 1147 return GNUNET_SYSERR; 1148 } 1149 ci = string_to_cipher (cipher); 1150 switch (ci) 1151 { 1152 case GNUNET_CRYPTO_BSA_INVALID: 1153 break; 1154 case GNUNET_CRYPTO_BSA_RSA: 1155 ewv->blinding_inputs = TALER_denom_ewv_rsa_singleton ()->blinding_inputs; 1156 return GNUNET_OK; 1157 case GNUNET_CRYPTO_BSA_CS: 1158 bi = GNUNET_new (struct GNUNET_CRYPTO_BlindingInputValues); 1159 bi->cipher = GNUNET_CRYPTO_BSA_CS; 1160 bi->rc = 1; 1161 { 1162 struct GNUNET_JSON_Specification ispec[] = { 1163 GNUNET_JSON_spec_fixed ( 1164 "r_pub_0", 1165 &bi->details.cs_values.r_pub[0], 1166 sizeof (struct GNUNET_CRYPTO_CsRPublic)), 1167 GNUNET_JSON_spec_fixed ( 1168 "r_pub_1", 1169 &bi->details.cs_values.r_pub[1], 1170 sizeof (struct GNUNET_CRYPTO_CsRPublic)), 1171 GNUNET_JSON_spec_end () 1172 }; 1173 1174 if (GNUNET_OK != 1175 GNUNET_JSON_parse (root, 1176 ispec, 1177 &emsg, 1178 &eline)) 1179 { 1180 GNUNET_break_op (0); 1181 GNUNET_free (bi); 1182 return GNUNET_SYSERR; 1183 } 1184 ewv->blinding_inputs = bi; 1185 return GNUNET_OK; 1186 } 1187 } 1188 GNUNET_break_op (0); 1189 return GNUNET_SYSERR; 1190 } 1191 1192 1193 /** 1194 * Cleanup data left from parsing withdraw values 1195 * 1196 * @param cls closure, NULL 1197 * @param[out] spec where to free the data 1198 */ 1199 static void 1200 clean_exchange_blinding_values ( 1201 void *cls, 1202 struct GNUNET_JSON_Specification *spec) 1203 { 1204 struct TALER_ExchangeBlindingValues *ewv = spec->ptr; 1205 1206 (void) cls; 1207 TALER_denom_ewv_free (ewv); 1208 } 1209 1210 1211 struct GNUNET_JSON_Specification 1212 TALER_JSON_spec_exchange_blinding_values ( 1213 const char *field, 1214 struct TALER_ExchangeBlindingValues *ewv) 1215 { 1216 struct GNUNET_JSON_Specification ret = { 1217 .parser = &parse_exchange_blinding_values, 1218 .cleaner = &clean_exchange_blinding_values, 1219 .field = field, 1220 .ptr = ewv 1221 }; 1222 1223 ewv->blinding_inputs = NULL; 1224 return ret; 1225 } 1226 1227 1228 /** 1229 * Closure for #parse_i18n_string. 1230 */ 1231 struct I18nContext 1232 { 1233 /** 1234 * Language pattern to match. 1235 */ 1236 char *lp; 1237 1238 /** 1239 * Name of the field to match. 1240 */ 1241 const char *field; 1242 }; 1243 1244 1245 /** 1246 * Parse given JSON object to internationalized string. 1247 * 1248 * @param cls closure, our `struct I18nContext *` 1249 * @param root the json object representing data 1250 * @param[out] spec where to write the data 1251 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1252 */ 1253 static enum GNUNET_GenericReturnValue 1254 parse_i18n_string (void *cls, 1255 json_t *root, 1256 struct GNUNET_JSON_Specification *spec) 1257 { 1258 struct I18nContext *ctx = cls; 1259 json_t *i18n; 1260 json_t *val; 1261 1262 { 1263 char *i18nf; 1264 1265 GNUNET_asprintf (&i18nf, 1266 "%s_i18n", 1267 ctx->field); 1268 i18n = json_object_get (root, 1269 i18nf); 1270 GNUNET_free (i18nf); 1271 } 1272 1273 val = json_object_get (root, 1274 ctx->field); 1275 if ( (NULL != i18n) && 1276 (NULL != ctx->lp) ) 1277 { 1278 double best = 0.0; 1279 json_t *pos; 1280 const char *lang; 1281 1282 json_object_foreach (i18n, lang, pos) 1283 { 1284 double score; 1285 1286 score = TALER_pattern_matches (ctx->lp, 1287 lang); 1288 if (score > best) 1289 { 1290 best = score; 1291 val = pos; 1292 } 1293 } 1294 } 1295 1296 { 1297 const char *str; 1298 1299 str = json_string_value (val); 1300 *(const char **) spec->ptr = str; 1301 } 1302 return GNUNET_OK; 1303 } 1304 1305 1306 /** 1307 * Function called to clean up data from earlier parsing. 1308 * 1309 * @param cls closure 1310 * @param spec our specification entry with data to clean. 1311 */ 1312 static void 1313 i18n_cleaner (void *cls, 1314 struct GNUNET_JSON_Specification *spec) 1315 { 1316 struct I18nContext *ctx = cls; 1317 1318 (void) spec; 1319 if (NULL != ctx) 1320 { 1321 GNUNET_free (ctx->lp); 1322 GNUNET_free (ctx); 1323 } 1324 } 1325 1326 1327 struct GNUNET_JSON_Specification 1328 TALER_JSON_spec_i18n_string (const char *name, 1329 const char *language_pattern, 1330 const char **strptr) 1331 { 1332 struct I18nContext *ctx = GNUNET_new (struct I18nContext); 1333 struct GNUNET_JSON_Specification ret = { 1334 .parser = &parse_i18n_string, 1335 .cleaner = &i18n_cleaner, 1336 .cls = ctx, 1337 .field = NULL, /* we want the main object */ 1338 .ptr = strptr, 1339 .ptr_size = 0, 1340 .size_ptr = NULL 1341 }; 1342 1343 ctx->lp = (NULL != language_pattern) 1344 ? GNUNET_strdup (language_pattern) 1345 : NULL; 1346 ctx->field = name; 1347 *strptr = NULL; 1348 return ret; 1349 } 1350 1351 1352 struct GNUNET_JSON_Specification 1353 TALER_JSON_spec_i18n_str (const char *name, 1354 const char **strptr) 1355 { 1356 const char *lang = getenv ("LANG"); 1357 char *dot; 1358 char *l; 1359 struct GNUNET_JSON_Specification ret; 1360 1361 if (NULL != lang) 1362 { 1363 dot = strchr (lang, 1364 '.'); 1365 if (NULL == dot) 1366 l = GNUNET_strdup (lang); 1367 else 1368 l = GNUNET_strndup (lang, 1369 dot - lang); 1370 } 1371 else 1372 { 1373 l = NULL; 1374 } 1375 ret = TALER_JSON_spec_i18n_string (name, 1376 l, 1377 strptr); 1378 GNUNET_free (l); 1379 return ret; 1380 } 1381 1382 1383 /** 1384 * Parse given JSON object with Taler error code. 1385 * 1386 * @param cls closure, NULL 1387 * @param root the json object representing data 1388 * @param[out] spec where to write the data 1389 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1390 */ 1391 static enum GNUNET_GenericReturnValue 1392 parse_ec (void *cls, 1393 json_t *root, 1394 struct GNUNET_JSON_Specification *spec) 1395 { 1396 enum TALER_ErrorCode *ec = spec->ptr; 1397 json_int_t num; 1398 1399 (void) cls; 1400 if (! json_is_integer (root)) 1401 { 1402 GNUNET_break_op (0); 1403 return GNUNET_SYSERR; 1404 } 1405 num = json_integer_value (root); 1406 if (num < 0) 1407 { 1408 GNUNET_break_op (0); 1409 *ec = TALER_EC_INVALID; 1410 return GNUNET_SYSERR; 1411 } 1412 *ec = (enum TALER_ErrorCode) num; 1413 return GNUNET_OK; 1414 } 1415 1416 1417 struct GNUNET_JSON_Specification 1418 TALER_JSON_spec_ec (const char *field, 1419 enum TALER_ErrorCode *ec) 1420 { 1421 struct GNUNET_JSON_Specification ret = { 1422 .parser = &parse_ec, 1423 .field = field, 1424 .ptr = ec 1425 }; 1426 1427 *ec = TALER_EC_NONE; 1428 return ret; 1429 } 1430 1431 1432 /** 1433 * Parse given JSON object to web URL. 1434 * 1435 * @param cls closure, NULL 1436 * @param root the json object representing data 1437 * @param[out] spec where to write the data 1438 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1439 */ 1440 static enum GNUNET_GenericReturnValue 1441 parse_web_url (void *cls, 1442 json_t *root, 1443 struct GNUNET_JSON_Specification *spec) 1444 { 1445 const char *str; 1446 1447 (void) cls; 1448 str = json_string_value (root); 1449 if (NULL == str) 1450 { 1451 GNUNET_break_op (0); 1452 return GNUNET_SYSERR; 1453 } 1454 if (! TALER_is_web_url (str)) 1455 { 1456 GNUNET_break_op (0); 1457 return GNUNET_SYSERR; 1458 } 1459 *(const char **) spec->ptr = str; 1460 return GNUNET_OK; 1461 } 1462 1463 1464 struct GNUNET_JSON_Specification 1465 TALER_JSON_spec_web_url (const char *field, 1466 const char **url) 1467 { 1468 struct GNUNET_JSON_Specification ret = { 1469 .parser = &parse_web_url, 1470 .field = field, 1471 .ptr = url 1472 }; 1473 1474 *url = NULL; 1475 return ret; 1476 } 1477 1478 1479 /** 1480 * Parse given JSON object to slug. 1481 * 1482 * @param cls closure, NULL 1483 * @param root the json object representing data 1484 * @param[out] spec where to write the data 1485 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1486 */ 1487 static enum GNUNET_GenericReturnValue 1488 parse_slug (void *cls, 1489 json_t *root, 1490 struct GNUNET_JSON_Specification *spec) 1491 { 1492 const char *str; 1493 1494 (void) cls; 1495 str = json_string_value (root); 1496 if (NULL == str) 1497 { 1498 GNUNET_break_op (0); 1499 return GNUNET_SYSERR; 1500 } 1501 if (! TALER_is_slug (str)) 1502 { 1503 GNUNET_break_op (0); 1504 return GNUNET_SYSERR; 1505 } 1506 *(const char **) spec->ptr = str; 1507 return GNUNET_OK; 1508 } 1509 1510 1511 struct GNUNET_JSON_Specification 1512 TALER_JSON_spec_slug (const char *field, 1513 const char **slug) 1514 { 1515 struct GNUNET_JSON_Specification ret = { 1516 .parser = &parse_slug, 1517 .field = field, 1518 .ptr = slug 1519 }; 1520 1521 *slug = NULL; 1522 return ret; 1523 } 1524 1525 1526 /** 1527 * Parse given JSON object to payto:// URI. 1528 * 1529 * @param cls closure, NULL 1530 * @param root the json object representing data 1531 * @param[out] spec where to write the data 1532 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1533 */ 1534 static enum GNUNET_GenericReturnValue 1535 parse_full_payto_uri (void *cls, 1536 json_t *root, 1537 struct GNUNET_JSON_Specification *spec) 1538 { 1539 struct TALER_FullPayto *payto_uri = spec->ptr; 1540 const char *str; 1541 char *err; 1542 1543 (void) cls; 1544 str = json_string_value (root); 1545 if (NULL == str) 1546 { 1547 GNUNET_break_op (0); 1548 return GNUNET_SYSERR; 1549 } 1550 payto_uri->full_payto = (char *) str; 1551 err = TALER_payto_validate (*payto_uri); 1552 if (NULL != err) 1553 { 1554 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1555 "payto:// malformed: %s\n", 1556 err); 1557 GNUNET_free (err); 1558 payto_uri->full_payto = NULL; 1559 return GNUNET_SYSERR; 1560 } 1561 return GNUNET_OK; 1562 } 1563 1564 1565 struct GNUNET_JSON_Specification 1566 TALER_JSON_spec_full_payto_uri ( 1567 const char *field, 1568 struct TALER_FullPayto *payto_uri) 1569 { 1570 struct GNUNET_JSON_Specification ret = { 1571 .parser = &parse_full_payto_uri, 1572 .field = field, 1573 .ptr = payto_uri 1574 }; 1575 1576 payto_uri->full_payto = NULL; 1577 return ret; 1578 } 1579 1580 1581 /** 1582 * Parse given JSON object to payto:// URI. 1583 * 1584 * @param cls closure, NULL 1585 * @param root the json object representing data 1586 * @param[out] spec where to write the data 1587 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1588 */ 1589 static enum GNUNET_GenericReturnValue 1590 parse_normalized_payto_uri (void *cls, 1591 json_t *root, 1592 struct GNUNET_JSON_Specification *spec) 1593 { 1594 struct TALER_NormalizedPayto *payto_uri = spec->ptr; 1595 const char *str; 1596 1597 (void) cls; 1598 str = json_string_value (root); 1599 if (NULL == str) 1600 { 1601 GNUNET_break_op (0); 1602 return GNUNET_SYSERR; 1603 } 1604 payto_uri->normalized_payto = (char *) str; 1605 { 1606 char *err; 1607 1608 err = TALER_normalized_payto_validate (*payto_uri); 1609 if (NULL != err) 1610 { 1611 GNUNET_break_op (0); 1612 GNUNET_free (err); 1613 payto_uri->normalized_payto = NULL; 1614 return GNUNET_SYSERR; 1615 } 1616 } 1617 return GNUNET_OK; 1618 } 1619 1620 1621 struct GNUNET_JSON_Specification 1622 TALER_JSON_spec_normalized_payto_uri ( 1623 const char *field, 1624 struct TALER_NormalizedPayto *payto_uri) 1625 { 1626 struct GNUNET_JSON_Specification ret = { 1627 .parser = &parse_normalized_payto_uri, 1628 .field = field, 1629 .ptr = payto_uri 1630 }; 1631 1632 payto_uri->normalized_payto = NULL; 1633 return ret; 1634 } 1635 1636 1637 /** 1638 * Parse given JSON object with protocol version. 1639 * 1640 * @param cls closure, NULL 1641 * @param root the json object representing data 1642 * @param[out] spec where to write the data 1643 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1644 */ 1645 static enum GNUNET_GenericReturnValue 1646 parse_protocol_version (void *cls, 1647 json_t *root, 1648 struct GNUNET_JSON_Specification *spec) 1649 { 1650 struct TALER_JSON_ProtocolVersion *pv = spec->ptr; 1651 const char *ver; 1652 char dummy; 1653 1654 (void) cls; 1655 if (! json_is_string (root)) 1656 { 1657 GNUNET_break_op (0); 1658 return GNUNET_SYSERR; 1659 } 1660 ver = json_string_value (root); 1661 if (3 != sscanf (ver, 1662 "%u:%u:%u%c", 1663 &pv->current, 1664 &pv->revision, 1665 &pv->age, 1666 &dummy)) 1667 { 1668 GNUNET_break_op (0); 1669 return GNUNET_SYSERR; 1670 } 1671 return GNUNET_OK; 1672 } 1673 1674 1675 struct GNUNET_JSON_Specification 1676 TALER_JSON_spec_version (const char *field, 1677 struct TALER_JSON_ProtocolVersion *ver) 1678 { 1679 struct GNUNET_JSON_Specification ret = { 1680 .parser = &parse_protocol_version, 1681 .field = field, 1682 .ptr = ver 1683 }; 1684 1685 return ret; 1686 } 1687 1688 1689 /** 1690 * Parse given JSON object to an OTP key. 1691 * 1692 * @param cls closure, NULL 1693 * @param root the json object representing data 1694 * @param[out] spec where to write the data 1695 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1696 */ 1697 static enum GNUNET_GenericReturnValue 1698 parse_otp_key (void *cls, 1699 json_t *root, 1700 struct GNUNET_JSON_Specification *spec) 1701 { 1702 const char *pos_key; 1703 1704 (void) cls; 1705 pos_key = json_string_value (root); 1706 if (NULL == pos_key) 1707 { 1708 GNUNET_break_op (0); 1709 return GNUNET_SYSERR; 1710 } 1711 { 1712 size_t pos_key_length = strlen (pos_key); 1713 void *key; /* pos_key in binary */ 1714 size_t key_len; /* length of the key */ 1715 int dret; 1716 1717 key_len = pos_key_length * 5 / 8; 1718 key = GNUNET_malloc (key_len); 1719 dret = TALER_rfc3548_base32decode (pos_key, 1720 pos_key_length, 1721 key, 1722 key_len); 1723 if (-1 == dret) 1724 { 1725 GNUNET_free (key); 1726 GNUNET_break_op (0); 1727 return GNUNET_SYSERR; 1728 } 1729 GNUNET_free (key); 1730 } 1731 *(const char **) spec->ptr = pos_key; 1732 return GNUNET_OK; 1733 } 1734 1735 1736 struct GNUNET_JSON_Specification 1737 TALER_JSON_spec_otp_key (const char *name, 1738 const char **otp_key) 1739 { 1740 struct GNUNET_JSON_Specification ret = { 1741 .parser = &parse_otp_key, 1742 .field = name, 1743 .ptr = otp_key 1744 }; 1745 1746 *otp_key = NULL; 1747 return ret; 1748 } 1749 1750 1751 /** 1752 * Parse given JSON object to `enum TALER_MerchantConfirmationAlgorithm` 1753 * 1754 * @param cls closure, NULL 1755 * @param root the json object representing data 1756 * @param[out] spec where to write the data 1757 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1758 */ 1759 static enum GNUNET_GenericReturnValue 1760 parse_otp_type (void *cls, 1761 json_t *root, 1762 struct GNUNET_JSON_Specification *spec) 1763 { 1764 static const struct Entry 1765 { 1766 const char *name; 1767 enum TALER_MerchantConfirmationAlgorithm val; 1768 } lt [] = { 1769 { .name = "NONE", 1770 .val = TALER_MCA_NONE }, 1771 { .name = "TOTP_WITHOUT_PRICE", 1772 .val = TALER_MCA_WITHOUT_PRICE }, 1773 { .name = "TOTP_WITH_PRICE", 1774 .val = TALER_MCA_WITH_PRICE }, 1775 { .name = NULL, 1776 .val = TALER_MCA_NONE }, 1777 }; 1778 enum TALER_MerchantConfirmationAlgorithm *res 1779 = (enum TALER_MerchantConfirmationAlgorithm *) spec->ptr; 1780 1781 (void) cls; 1782 if (json_is_string (root)) 1783 { 1784 const char *str; 1785 1786 str = json_string_value (root); 1787 if (NULL == str) 1788 { 1789 GNUNET_break_op (0); 1790 return GNUNET_SYSERR; 1791 } 1792 for (unsigned int i = 0; NULL != lt[i].name; i++) 1793 { 1794 if (0 == strcasecmp (str, 1795 lt[i].name)) 1796 { 1797 *res = lt[i].val; 1798 return GNUNET_OK; 1799 } 1800 } 1801 GNUNET_break_op (0); 1802 } 1803 if (json_is_integer (root)) 1804 { 1805 json_int_t val; 1806 1807 val = json_integer_value (root); 1808 for (unsigned int i = 0; NULL != lt[i].name; i++) 1809 { 1810 if (val == lt[i].val) 1811 { 1812 *res = lt[i].val; 1813 return GNUNET_OK; 1814 } 1815 } 1816 GNUNET_break_op (0); 1817 return GNUNET_SYSERR; 1818 } 1819 GNUNET_break_op (0); 1820 return GNUNET_SYSERR; 1821 } 1822 1823 1824 struct GNUNET_JSON_Specification 1825 TALER_JSON_spec_otp_type (const char *name, 1826 enum TALER_MerchantConfirmationAlgorithm *mca) 1827 { 1828 struct GNUNET_JSON_Specification ret = { 1829 .parser = &parse_otp_type, 1830 .field = name, 1831 .ptr = mca 1832 }; 1833 1834 *mca = TALER_MCA_NONE; 1835 return ret; 1836 } 1837 1838 1839 /** 1840 * Parse given JSON object to `enum TALER_KYCLOGIC_KycTriggerEvent` 1841 * 1842 * @param cls closure, NULL 1843 * @param root the json object representing data 1844 * @param[out] spec where to write the data 1845 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error 1846 */ 1847 static enum GNUNET_GenericReturnValue 1848 parse_kycte (void *cls, 1849 json_t *root, 1850 struct GNUNET_JSON_Specification *spec) 1851 { 1852 static const struct Entry 1853 { 1854 const char *name; 1855 enum TALER_KYCLOGIC_KycTriggerEvent val; 1856 } lt [] = { 1857 { .name = "NONE", 1858 .val = TALER_KYCLOGIC_KYC_TRIGGER_NONE }, 1859 { .name = "WITHDRAW", 1860 .val = TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW }, 1861 { .name = "DEPOSIT", 1862 .val = TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT }, 1863 { .name = "MERGE", 1864 .val = TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE }, 1865 { .name = "BALANCE", 1866 .val = TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE }, 1867 { .name = "CLOSE", 1868 .val = TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE }, 1869 { .name = "AGGREGATE", 1870 .val = TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE }, 1871 { .name = "TRANSACTION", 1872 .val = TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION }, 1873 { .name = "REFUND", 1874 .val = TALER_KYCLOGIC_KYC_TRIGGER_REFUND }, 1875 { .name = NULL, 1876 .val = TALER_KYCLOGIC_KYC_TRIGGER_NONE }, 1877 }; 1878 enum TALER_KYCLOGIC_KycTriggerEvent *res 1879 = (enum TALER_KYCLOGIC_KycTriggerEvent *) spec->ptr; 1880 1881 (void) cls; 1882 if (json_is_string (root)) 1883 { 1884 const char *str; 1885 1886 str = json_string_value (root); 1887 if (NULL == str) 1888 { 1889 GNUNET_break_op (0); 1890 return GNUNET_SYSERR; 1891 } 1892 for (unsigned int i = 0; NULL != lt[i].name; i++) 1893 { 1894 if (0 == strcasecmp (str, 1895 lt[i].name)) 1896 { 1897 *res = lt[i].val; 1898 return GNUNET_OK; 1899 } 1900 } 1901 GNUNET_break_op (0); 1902 return GNUNET_SYSERR; 1903 } 1904 if (json_is_integer (root)) 1905 { 1906 json_int_t val; 1907 1908 val = json_integer_value (root); 1909 for (unsigned int i = 0; NULL != lt[i].name; i++) 1910 { 1911 if (val == lt[i].val) 1912 { 1913 *res = lt[i].val; 1914 return GNUNET_OK; 1915 } 1916 } 1917 GNUNET_break_op (0); 1918 return GNUNET_SYSERR; 1919 } 1920 GNUNET_break_op (0); 1921 return GNUNET_SYSERR; 1922 } 1923 1924 1925 struct GNUNET_JSON_Specification 1926 TALER_JSON_spec_kycte (const char *name, 1927 enum TALER_KYCLOGIC_KycTriggerEvent *kte) 1928 { 1929 struct GNUNET_JSON_Specification ret = { 1930 .parser = &parse_kycte, 1931 .field = name, 1932 .ptr = kte 1933 }; 1934 1935 *kte = TALER_KYCLOGIC_KYC_TRIGGER_NONE; 1936 return ret; 1937 } 1938 1939 1940 /** 1941 * Parser combinator of a tuple of parsers, for parsing 1942 * an array of expected size and element types. 1943 * 1944 * @param cls closure, array of specs, NULL terminated 1945 * @param root the json root 1946 * @param[out] spec where to write the data 1947 */ 1948 static enum GNUNET_GenericReturnValue 1949 parse_tuple_of (void *cls, 1950 json_t *root, 1951 struct GNUNET_JSON_Specification *spec) 1952 { 1953 struct GNUNET_JSON_Specification *specs = cls; 1954 static size_t max_specs = 100; 1955 bool found_end = false; 1956 1957 enum GNUNET_GenericReturnValue ret; 1958 1959 if (! json_is_array (root)) 1960 { 1961 return GNUNET_SYSERR; 1962 } 1963 1964 { 1965 size_t num; 1966 for (num = 0; num< max_specs; num++) 1967 { 1968 if (NULL == specs[num].parser) 1969 { 1970 found_end = true; 1971 break; 1972 } 1973 } 1974 GNUNET_assert (found_end); 1975 1976 if (num != json_array_size (root)) 1977 { 1978 GNUNET_break_op (0); 1979 return GNUNET_SYSERR; 1980 } 1981 } 1982 1983 { 1984 json_t *j_entry; 1985 size_t idx; 1986 1987 json_array_foreach (root, idx, j_entry) { 1988 ret = GNUNET_JSON_parse (j_entry, 1989 &specs[idx], 1990 NULL, 1991 NULL); 1992 if (GNUNET_OK != ret) 1993 { 1994 GNUNET_break_op (0); 1995 return GNUNET_SYSERR; 1996 } 1997 } 1998 } 1999 2000 return GNUNET_OK; 2001 } 2002 2003 2004 struct GNUNET_JSON_Specification 2005 TALER_JSON_spec_tuple_of ( 2006 const char *field, 2007 struct GNUNET_JSON_Specification specs[]) 2008 { 2009 struct GNUNET_JSON_Specification ret = { 2010 .parser = &parse_tuple_of, 2011 .field = field, 2012 .cls = specs 2013 }; 2014 2015 return ret; 2016 } 2017 2018 2019 /** 2020 * Parser for an array of unknown length but 2021 * of elements of the same type with the same 2022 * fixed length. 2023 * 2024 * @param cls closure, entry_size 2025 * @param root the json root 2026 * @param spec the output spec 2027 */ 2028 static enum GNUNET_GenericReturnValue 2029 parse_array_fixed (void *cls, 2030 json_t *root, 2031 struct GNUNET_JSON_Specification *spec) 2032 { 2033 enum GNUNET_GenericReturnValue ret; 2034 size_t entry_size = (size_t) cls; 2035 size_t num_entries; 2036 2037 GNUNET_assert (0< entry_size); 2038 num_entries = spec->ptr_size / entry_size; 2039 GNUNET_assert (0 < num_entries); 2040 2041 2042 if (! json_is_array (root)) 2043 { 2044 GNUNET_break_op (0); 2045 return GNUNET_SYSERR; 2046 } 2047 if (num_entries != json_array_size (root)) 2048 { 2049 GNUNET_break_op (0); 2050 return GNUNET_SYSERR; 2051 } 2052 2053 { 2054 json_t *j_entry; 2055 size_t idx; 2056 void *ptr = spec->ptr; 2057 void *end = spec->ptr + spec->ptr_size; 2058 2059 json_array_foreach (root, idx, j_entry) { 2060 struct GNUNET_JSON_Specification esp[] = { 2061 GNUNET_JSON_spec_fixed (NULL, 2062 ptr, 2063 entry_size), 2064 GNUNET_JSON_spec_end () 2065 }; 2066 GNUNET_assert (ptr < end); 2067 ret = GNUNET_JSON_parse (j_entry, 2068 esp, 2069 NULL, 2070 NULL); 2071 if (GNUNET_OK != ret) 2072 { 2073 GNUNET_break_op (0); 2074 return GNUNET_SYSERR; 2075 } 2076 ptr += entry_size; 2077 } 2078 } 2079 return GNUNET_OK; 2080 } 2081 2082 2083 struct GNUNET_JSON_Specification 2084 TALER_JSON_spec_array_fixed ( 2085 const char *field, 2086 size_t num_entries, 2087 void *entries, 2088 size_t entry_size) 2089 { 2090 struct GNUNET_JSON_Specification ret = { 2091 .parser = &parse_array_fixed, 2092 .ptr = entries, 2093 .ptr_size = entry_size * num_entries, 2094 .field = field, 2095 .cls = (void *) entry_size, 2096 }; 2097 2098 GNUNET_assert ((num_entries <= 1) || 2099 (entry_size * num_entries > entry_size)); 2100 return ret; 2101 } 2102 2103 2104 /** 2105 * Closure for the parser of arrays of fixed size data 2106 * of unknown array length 2107 */ 2108 struct closure_array_of_data 2109 { 2110 /** 2111 * Fixed (known) size per entry 2112 */ 2113 size_t entry_size; 2114 2115 /** 2116 * Pointer where to put the number of elements 2117 * allocated, i.e. the number of elements in the 2118 * json array. 2119 */ 2120 size_t *num_entries; 2121 }; 2122 2123 /** 2124 * Parser for an array of data of known element size, 2125 * but unknown array length 2126 */ 2127 static enum GNUNET_GenericReturnValue 2128 parse_array_of_data (void *cls, 2129 json_t *root, 2130 struct GNUNET_JSON_Specification *spec) 2131 { 2132 enum GNUNET_GenericReturnValue ret; 2133 struct closure_array_of_data *info = cls; 2134 size_t num_entries; 2135 2136 if (! json_is_array (root)) 2137 { 2138 GNUNET_break_op (0); 2139 return GNUNET_SYSERR; 2140 } 2141 num_entries = json_array_size (root); 2142 *info->num_entries = num_entries; 2143 if (0 == num_entries) 2144 { 2145 *(char **) spec->ptr = NULL; 2146 return GNUNET_OK; 2147 } 2148 2149 spec->ptr_size = num_entries * info->entry_size; 2150 GNUNET_assert (spec->ptr_size > num_entries); 2151 *((char **) spec->ptr) = GNUNET_malloc (spec->ptr_size); 2152 2153 { 2154 json_t *j_entry; 2155 size_t idx; 2156 char *ptr = *(char **) spec->ptr; 2157 char *end = ptr + spec->ptr_size; 2158 2159 json_array_foreach (root, idx, j_entry) { 2160 struct GNUNET_JSON_Specification esp[] = { 2161 GNUNET_JSON_spec_fixed (NULL, 2162 ptr, 2163 info->entry_size), 2164 GNUNET_JSON_spec_end () 2165 }; 2166 GNUNET_assert (ptr < end); 2167 ret = GNUNET_JSON_parse (j_entry, 2168 esp, 2169 NULL, 2170 NULL); 2171 if (GNUNET_OK != ret) 2172 { 2173 GNUNET_break_op (0); 2174 return GNUNET_SYSERR; 2175 } 2176 ptr += info->entry_size; 2177 } 2178 } 2179 return GNUNET_OK; 2180 } 2181 2182 2183 /** 2184 * Cleanup data left from parsing an array of fixed size (but unknown length). 2185 * 2186 * @param cls closure_of_array_data 2187 * @param[out] spec where to free the data 2188 */ 2189 static void 2190 cleaner_array_of_data (void *cls, 2191 struct GNUNET_JSON_Specification *spec) 2192 { 2193 struct closure_array_of_data *info = cls; 2194 2195 GNUNET_free (*(void **) spec->ptr); 2196 GNUNET_free (info); 2197 } 2198 2199 2200 struct GNUNET_JSON_Specification 2201 TALER_JSON_spec_array_of_data ( 2202 const char *field, 2203 size_t entry_size, 2204 size_t *num_entries, 2205 void **entries) 2206 { 2207 struct closure_array_of_data *cls; 2208 2209 GNUNET_assert (0< entry_size); 2210 *entries = NULL; 2211 *num_entries = 0; 2212 cls = GNUNET_new (struct closure_array_of_data); 2213 cls->num_entries = num_entries; 2214 cls->entry_size = entry_size; 2215 { 2216 struct GNUNET_JSON_Specification ret = { 2217 .parser = &parse_array_of_data, 2218 .ptr = entries, 2219 .field = field, 2220 .cleaner = &cleaner_array_of_data, 2221 .cls = (void *) cls, 2222 }; 2223 2224 return ret; 2225 } 2226 } 2227 2228 2229 struct GNUNET_JSON_Specification 2230 TALER_JSON_spec_array_of_denom_pub_h ( 2231 const char *field, 2232 size_t *num_entries, 2233 struct TALER_DenominationHashP **entries) 2234 { 2235 *num_entries = 0; 2236 *entries = NULL; 2237 return TALER_JSON_spec_array_of_data ( 2238 field, 2239 sizeof (struct TALER_DenominationHashP), 2240 num_entries, 2241 (void **) entries); 2242 } 2243 2244 2245 /** 2246 * Parser for an array of blinded denomination signatures, 2247 * of unknown array length 2248 */ 2249 static enum GNUNET_GenericReturnValue 2250 parse_array_of_blinded_denom_sigs (void *cls, 2251 json_t *root, 2252 struct GNUNET_JSON_Specification *spec) 2253 { 2254 enum GNUNET_GenericReturnValue ret; 2255 struct TALER_BlindedDenominationSignature *sigs = spec->ptr; 2256 size_t expected_num_entries = (size_t) cls; 2257 size_t num_entries; 2258 2259 if (! json_is_array (root)) 2260 { 2261 GNUNET_break_op (0); 2262 return GNUNET_SYSERR; 2263 } 2264 num_entries = json_array_size (root); 2265 if (num_entries != expected_num_entries) 2266 { 2267 GNUNET_break_op (0); 2268 return GNUNET_SYSERR; 2269 } 2270 2271 { 2272 json_t *j_entry; 2273 size_t idx; 2274 struct TALER_BlindedDenominationSignature *ptr = sigs; 2275 2276 json_array_foreach (root, idx, j_entry) { 2277 struct GNUNET_JSON_Specification esp[] = { 2278 TALER_JSON_spec_blinded_denom_sig (NULL, 2279 ptr), 2280 GNUNET_JSON_spec_end () 2281 }; 2282 ret = GNUNET_JSON_parse (j_entry, 2283 esp, 2284 NULL, 2285 NULL); 2286 if (GNUNET_OK != ret) 2287 { 2288 GNUNET_break_op (0); 2289 for (size_t i = 0; i < idx; i++) 2290 { 2291 TALER_blinded_denom_sig_free (&sigs[i]); 2292 sigs[i].blinded_sig = NULL; 2293 } 2294 return GNUNET_SYSERR; 2295 } 2296 ptr++; 2297 } 2298 } 2299 return GNUNET_OK; 2300 } 2301 2302 2303 /** 2304 * Cleanup data left from parsing an array of blinded signatures. 2305 * 2306 * @param cls pointer to a size_t with the length of the array 2307 * @param[out] spec where to free the data 2308 */ 2309 static void 2310 cleaner_array_of_blinded_denom_sigs ( 2311 void *cls, 2312 struct GNUNET_JSON_Specification *spec) 2313 { 2314 struct TALER_BlindedDenominationSignature *sigs = spec->ptr; 2315 size_t num_entries = (size_t) cls; 2316 2317 for (size_t i = 0; i < num_entries; i++) 2318 { 2319 if (NULL != sigs[i].blinded_sig) 2320 { 2321 TALER_blinded_denom_sig_free (&sigs[i]); 2322 sigs[i].blinded_sig = NULL; 2323 } 2324 } 2325 } 2326 2327 2328 struct GNUNET_JSON_Specification 2329 TALER_JSON_spec_array_of_blinded_denom_sigs ( 2330 const char *field, 2331 size_t num_entries, 2332 struct TALER_BlindedDenominationSignature *entries) 2333 { 2334 struct GNUNET_JSON_Specification ret = { 2335 .parser = &parse_array_of_blinded_denom_sigs, 2336 .ptr = entries, 2337 .field = field, 2338 .cleaner = &cleaner_array_of_blinded_denom_sigs, 2339 .cls = (void *) num_entries, 2340 }; 2341 2342 for (size_t i = 0; i<num_entries; i++) 2343 entries[i].blinded_sig = NULL; 2344 return ret; 2345 } 2346 2347 2348 /* end of json/json_helper.c */