anastasis_api_redux_state.h (36661B)
1 /* 2 This file is part of Anastasis 3 Copyright (C) 2020, 2021, 2022 Anastasis SARL 4 5 Anastasis 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 Anastasis 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 Anastasis; see the file COPYING.GPL. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file reducer/anastasis_api_redux_state.h 18 * @brief typed representation of the reducer state 19 * @author Christian Grothoff 20 * 21 * The reducer's public API (`anastasis_redux.h`) speaks JSON, but the reducer 22 * logic itself does not: every entry point parses the incoming JSON into a 23 * `struct ANASTASIS_ReduxState` exactly once, operates on that, and serializes 24 * it back exactly once on the way out. The three generic routines at the 25 * bottom of this file are the only places that know the JSON encoding. 26 * 27 * Parsing is strict: a field that is not described here is an error 28 * (#TALER_EC_ANASTASIS_REDUCER_STATE_INVALID). There are two deliberate 29 * exceptions, both marked `json_t *` below, where the exact bytes the user 30 * supplied are cryptographically load-bearing and must not be normalized: 31 * @e identity_attributes (PoW-hashed to derive the account key) and 32 * @e core_secret (its serialization *is* the uploaded secret). 33 */ 34 #ifndef ANASTASIS_API_REDUX_STATE_H 35 #define ANASTASIS_API_REDUX_STATE_H 36 37 #include "anastasis_redux.h" 38 #include "anastasis_api_redux.h" 39 40 41 /* ************************ Wrapped primitives *********************** */ 42 43 /** 44 * URL of an Anastasis provider. Wrapped so that it cannot be confused 45 * with the many other strings floating around the reducer (business 46 * names, payto URIs, display hints, ...). 47 */ 48 struct ANASTASIS_ProviderUrl 49 { 50 /** 51 * The URL itself. Owned by the containing structure. 52 */ 53 char *url; 54 }; 55 56 57 /** 58 * Index into the @e policies array of a backup state. 59 */ 60 struct ANASTASIS_PolicyIndex 61 { 62 /** 63 * The index. 64 */ 65 unsigned int idx; 66 }; 67 68 69 /** 70 * Index into the @e methods array of a policy, or into the 71 * @e authentication_methods array of a backup state. 72 */ 73 struct ANASTASIS_MethodIndex 74 { 75 /** 76 * The index. 77 */ 78 unsigned int idx; 79 }; 80 81 82 /** 83 * Bitmask selecting which optional identity attributes were used. 84 */ 85 struct ANASTASIS_AttributeMask 86 { 87 /** 88 * The mask. 89 */ 90 uint64_t mask; 91 }; 92 93 94 /* ************************ Geography ******************************** */ 95 96 /** 97 * A continent the user may select. 98 */ 99 struct ANASTASIS_ReduxContinent 100 { 101 /** 102 * Name of the continent, e.g. "Europe". 103 */ 104 char *name; 105 106 /** 107 * Translations of @e name, NULL if not given. An object mapping 108 * language tags to strings, kept verbatim: the reducer only carries 109 * translations from the resource files to the user interface and 110 * never interprets them. 111 */ 112 json_t *name_i18n; 113 114 /** 115 * True if this continent was given as a bare string rather than as 116 * an object. Both forms occur: the reducer itself emits objects, 117 * but hand-written states use plain names. 118 */ 119 bool bare; 120 }; 121 122 123 /** 124 * A country the user may select. Copied verbatim from 125 * `contrib/redux.countries.json`. 126 */ 127 struct ANASTASIS_ReduxCountry 128 { 129 /** 130 * Two-letter country code, e.g. "ch". 131 */ 132 char *code; 133 134 /** 135 * Name of the country. 136 */ 137 char *name; 138 139 /** 140 * Continent the country is on. 141 */ 142 char *continent; 143 144 /** 145 * International dialling prefix, e.g. "+41". 146 */ 147 char *call_code; 148 149 /** 150 * Translations of @e name, NULL if not given. Kept verbatim, see 151 * #ANASTASIS_ReduxContinent. 152 */ 153 json_t *name_i18n; 154 155 /** 156 * Translations of @e continent, NULL if not given. Kept verbatim, 157 * see #ANASTASIS_ReduxContinent. 158 */ 159 json_t *continent_i18n; 160 161 /** 162 * Currency used in this country, NULL if not given. Carried through 163 * for the benefit of user interfaces; the reducer does not use it. 164 */ 165 char *currency; 166 }; 167 168 169 /** 170 * Specification of one identity attribute we ask the user for. 171 * Copied verbatim from `contrib/redux.$CC.json`. 172 */ 173 struct ANASTASIS_ReduxAttributeSpec 174 { 175 /** 176 * Type of the attribute, e.g. "string" or "date". 177 */ 178 char *type; 179 180 /** 181 * Name of the attribute; the key under which the user's answer 182 * appears in @e identity_attributes. 183 */ 184 char *name; 185 186 /** 187 * Human-readable label. 188 */ 189 char *label; 190 191 /** 192 * Widget the GTK UI should use to ask for this attribute. 193 */ 194 char *widget; 195 196 /** 197 * UUID identifying this attribute. 198 */ 199 char *uuid; 200 201 /** 202 * Tooltip for the UI, NULL if not given. 203 */ 204 char *tooltip; 205 206 /** 207 * Regular expression the value must match, NULL if not given. 208 */ 209 char *validation_regex; 210 211 /** 212 * Name of a validation function, resolved against the fixed table in 213 * reducer/validation.c. NULL if not given. 214 */ 215 char *validation_logic; 216 217 /** 218 * Input mask for autocompletion, NULL if not given. 219 */ 220 char *autocomplete; 221 222 /** 223 * Translations of @e label, NULL if not given. Kept verbatim, see 224 * #ANASTASIS_ReduxContinent. 225 */ 226 json_t *label_i18n; 227 228 /** 229 * True if the user may leave this attribute blank. 230 */ 231 bool optional; 232 233 /** 234 * True if @e optional was explicitly present in the JSON. Needed so 235 * that serialization does not invent an `"optional": false` field 236 * where the resource file had none. 237 */ 238 bool have_optional; 239 }; 240 241 242 /* ************************ Providers ******************************** */ 243 244 /** 245 * Status of an Anastasis provider in the reducer state. 246 */ 247 enum ANASTASIS_ReduxProviderStatus 248 { 249 /** 250 * We have not (yet) talked to this provider. 251 */ 252 ANASTASIS_RPS_NOT_CONTACTED = 0, 253 254 /** 255 * We obtained the provider's /config successfully. 256 */ 257 ANASTASIS_RPS_OK = 1, 258 259 /** 260 * The provider was taken out of consideration, typically because an 261 * upload to it failed. Note that any configuration we obtained 262 * earlier is retained (and re-serialized), matching the behaviour of 263 * the JSON-based implementation this replaced. 264 */ 265 ANASTASIS_RPS_DISABLED = 2, 266 267 /** 268 * Talking to the provider failed. 269 */ 270 ANASTASIS_RPS_ERROR = 3 271 }; 272 273 274 /** 275 * One authentication method offered by a provider, with its price. 276 */ 277 struct ANASTASIS_ReduxMethodSpec 278 { 279 /** 280 * Type of the method, e.g. "question" or "sms". 281 */ 282 char *type; 283 284 /** 285 * Fee charged for using this method during recovery. 286 */ 287 struct TALER_Amount usage_fee; 288 }; 289 290 291 /** 292 * Configuration of a provider, as obtained from its /config endpoint. 293 */ 294 struct ANASTASIS_ReduxProviderConfig 295 { 296 /** 297 * Methods the provider supports. 298 */ 299 struct ANASTASIS_ReduxMethodSpec *methods; 300 301 /** 302 * Length of the @e methods array. 303 */ 304 unsigned int methods_len; 305 306 /** 307 * Fee for storing a policy for a year. 308 */ 309 struct TALER_Amount annual_fee; 310 311 /** 312 * Fee for uploading one truth. 313 */ 314 struct TALER_Amount truth_upload_fee; 315 316 /** 317 * Maximum liability the provider accepts for data loss. 318 */ 319 struct TALER_Amount liability_limit; 320 321 /** 322 * Salt of this provider. 323 */ 324 struct ANASTASIS_CRYPTO_ProviderSaltP provider_salt; 325 326 /** 327 * Business name of the provider. 328 */ 329 char *business_name; 330 331 /** 332 * Currency the provider charges in, NULL if not given. Carried 333 * through for the benefit of user interfaces. 334 */ 335 char *currency; 336 337 /** 338 * Maximum upload size the provider accepts, in megabytes. 339 */ 340 uint32_t storage_limit_in_megabytes; 341 342 /** 343 * HTTP status of the /config request. 344 */ 345 uint32_t http_status; 346 }; 347 348 349 /** 350 * Why we could not use a provider. 351 */ 352 struct ANASTASIS_ReduxProviderError 353 { 354 /** 355 * Error code of the failed request. 356 */ 357 enum TALER_ErrorCode ec; 358 359 /** 360 * HTTP status of the failed request, 0 if we never got one. 361 */ 362 uint32_t http_status; 363 }; 364 365 366 /** 367 * An Anastasis provider we know about. Serializes as one entry of the 368 * `authentication_providers` object, keyed by @e url. 369 */ 370 struct ANASTASIS_ReduxProvider 371 { 372 /** 373 * URL of the provider; the key this entry is stored under. 374 */ 375 struct ANASTASIS_ProviderUrl url; 376 377 /** 378 * What we know about this provider. 379 */ 380 enum ANASTASIS_ReduxProviderStatus status; 381 382 /** 383 * True if @e config is valid. Set whenever a /config reply was 384 * obtained, and *not* cleared when @e status becomes 385 * #ANASTASIS_RPS_DISABLED. 386 */ 387 bool have_config; 388 389 /** 390 * Configuration of the provider; valid iff @e have_config. 391 */ 392 struct ANASTASIS_ReduxProviderConfig config; 393 394 /** 395 * Failure details; valid iff @e status is #ANASTASIS_RPS_ERROR. 396 */ 397 struct ANASTASIS_ReduxProviderError error; 398 }; 399 400 401 /* ******************** Backup-specific state ************************ */ 402 403 /** 404 * An authentication method the user configured. 405 */ 406 struct ANASTASIS_ReduxAuthMethod 407 { 408 /** 409 * Type of the method, e.g. "question". 410 */ 411 char *type; 412 413 /** 414 * Instructions to show the user during recovery. 415 */ 416 char *instructions; 417 418 /** 419 * The challenge itself (answer, phone number, e-mail address, ...). 420 */ 421 void *challenge; 422 423 /** 424 * Number of bytes in @e challenge. 425 */ 426 size_t challenge_size; 427 428 /** 429 * MIME type of @e challenge, NULL if not given. 430 */ 431 char *mime_type; 432 }; 433 434 435 /** 436 * One member of a policy: authenticate with method 437 * @e authentication_method at provider @e provider. 438 */ 439 struct ANASTASIS_ReduxPolicyMethod 440 { 441 /** 442 * Index into the backup state's @e authentication_methods array. 443 */ 444 struct ANASTASIS_MethodIndex authentication_method; 445 446 /** 447 * Provider that stores the key share for this method. 448 */ 449 struct ANASTASIS_ProviderUrl provider; 450 451 /** 452 * Truth uploaded for this method, NULL until the upload happened. 453 * Owned by this structure; freed with ANASTASIS_truth_free(). 454 */ 455 struct ANASTASIS_Truth *truth; 456 457 /** 458 * Status of the upload of @e truth; only meaningful if @e truth is 459 * non-NULL. 460 */ 461 enum ANASTASIS_UploadStatus upload_status; 462 }; 463 464 465 /** 466 * A recovery policy: a set of methods that together recover the secret. 467 */ 468 struct ANASTASIS_ReduxPolicy 469 { 470 /** 471 * Methods that make up this policy. 472 */ 473 struct ANASTASIS_ReduxPolicyMethod *methods; 474 475 /** 476 * Length of the @e methods array. 477 */ 478 unsigned int methods_len; 479 480 /** 481 * What recovering via this policy would cost; only valid if 482 * @e have_recovery_cost. Carried through for user interfaces. 483 */ 484 struct TALER_Amount recovery_cost; 485 486 /** 487 * True if @e recovery_cost was given. 488 */ 489 bool have_recovery_cost; 490 }; 491 492 493 /** 494 * A provider we intend to store the recovery document at. 495 */ 496 struct ANASTASIS_ReduxPolicyProvider 497 { 498 /** 499 * URL of the provider. 500 */ 501 struct ANASTASIS_ProviderUrl provider_url; 502 503 /** 504 * Payment secret remembered from an earlier payment request; only 505 * valid if @e have_payment_secret. 506 */ 507 struct ANASTASIS_PaymentSecretP payment_secret; 508 509 /** 510 * True if @e payment_secret is set. 511 */ 512 bool have_payment_secret; 513 }; 514 515 516 /** 517 * Result of a successful policy upload at one provider. 518 */ 519 struct ANASTASIS_ReduxSuccessDetail 520 { 521 /** 522 * URL of the provider; the key this entry is stored under. 523 */ 524 struct ANASTASIS_ProviderUrl provider_url; 525 526 /** 527 * When the stored policy expires. 528 */ 529 struct GNUNET_TIME_Timestamp policy_expiration; 530 531 /** 532 * Version the policy was stored under. 533 */ 534 uint32_t policy_version; 535 }; 536 537 538 /** 539 * A payment we are asking the application to make for a policy upload. 540 */ 541 struct ANASTASIS_ReduxPolicyPaymentRequest 542 { 543 /** 544 * Payment request URI. 545 */ 546 char *payto; 547 548 /** 549 * Provider that wants to be paid. 550 */ 551 struct ANASTASIS_ProviderUrl provider; 552 }; 553 554 555 /** 556 * Arguments the application passed to the most recent "pay" action. 557 */ 558 struct ANASTASIS_ReduxPayArguments 559 { 560 /** 561 * How long to wait for the payment to go through. 562 */ 563 struct GNUNET_TIME_Relative timeout; 564 565 /** 566 * True if @e timeout was given. 567 */ 568 bool have_timeout; 569 }; 570 571 572 /** 573 * The `backup` variant of the reducer state. 574 */ 575 struct ANASTASIS_ReduxBackup 576 { 577 /** 578 * Which step of the backup process we are at. 579 */ 580 enum ANASTASIS_BackupState state; 581 582 /** 583 * Authentication methods the user configured. 584 */ 585 struct ANASTASIS_ReduxAuthMethod *authentication_methods; 586 587 /** 588 * Length of the @e authentication_methods array. 589 */ 590 unsigned int authentication_methods_len; 591 592 /** 593 * Policies over the @e authentication_methods. 594 */ 595 struct ANASTASIS_ReduxPolicy *policies; 596 597 /** 598 * Length of the @e policies array. 599 */ 600 unsigned int policies_len; 601 602 /** 603 * Providers we will store the recovery document at. 604 */ 605 struct ANASTASIS_ReduxPolicyProvider *policy_providers; 606 607 /** 608 * Length of the @e policy_providers array. 609 */ 610 unsigned int policy_providers_len; 611 612 /** 613 * Per-currency total of what the backup will cost. 614 */ 615 struct TALER_Amount *upload_fees; 616 617 /** 618 * Length of the @e upload_fees array. 619 */ 620 unsigned int upload_fees_len; 621 622 /** 623 * Taler pay URIs the application must settle before we can continue 624 * uploading truths. 625 */ 626 char **payments; 627 628 /** 629 * Length of the @e payments array. 630 */ 631 unsigned int payments_len; 632 633 /** 634 * Payments the application must settle before we can upload the 635 * recovery document. 636 */ 637 struct ANASTASIS_ReduxPolicyPaymentRequest *policy_payment_requests; 638 639 /** 640 * Length of the @e policy_payment_requests array. 641 */ 642 unsigned int policy_payment_requests_len; 643 644 /** 645 * Where the recovery document ended up, per provider. 646 */ 647 struct ANASTASIS_ReduxSuccessDetail *success_details; 648 649 /** 650 * Length of the @e success_details array. 651 */ 652 unsigned int success_details_len; 653 654 /** 655 * The secret to back up. Deliberately untyped: its serialization is 656 * literally the secret that gets uploaded, so the reducer must never 657 * normalize it. NULL if not (yet) set. 658 */ 659 json_t *core_secret; 660 661 /** 662 * Name the user gave the secret, NULL if not set. 663 */ 664 char *secret_name; 665 666 /** 667 * When the backup should expire. 668 */ 669 struct GNUNET_TIME_Timestamp expiration; 670 671 /** 672 * True if @e expiration is set. 673 */ 674 bool have_expiration; 675 676 /** 677 * Arguments of the last "pay" action. 678 */ 679 struct ANASTASIS_ReduxPayArguments pay_arguments; 680 681 /** 682 * True if @e pay_arguments is set. 683 */ 684 bool have_pay_arguments; 685 686 /** 687 * True if the state has an @e authentication_methods field at all. 688 * As in #ANASTASIS_ReduxCommon, presence is tracked separately from 689 * the length because an empty array is meaningful. 690 */ 691 bool have_authentication_methods; 692 693 /** 694 * True if the state has a @e policies field at all. 695 */ 696 bool have_policies; 697 698 /** 699 * True if the state has a @e policy_providers field at all. 700 */ 701 bool have_policy_providers; 702 703 /** 704 * True if the state has an @e upload_fees field at all. 705 */ 706 bool have_upload_fees; 707 708 /** 709 * True if the state has a @e payments field at all. 710 */ 711 bool have_payments; 712 713 /** 714 * True if the state has a @e policy_payment_requests field at all. 715 */ 716 bool have_policy_payment_requests; 717 718 /** 719 * True if the state has a @e success_details field at all. 720 */ 721 bool have_success_details; 722 }; 723 724 725 /* ******************* Recovery-specific state *********************** */ 726 727 /** 728 * A challenge the user could solve to recover a key share. 729 */ 730 struct ANASTASIS_ReduxChallengeInfo 731 { 732 /** 733 * UUID of the truth behind this challenge. 734 */ 735 struct ANASTASIS_CRYPTO_TruthUUIDP uuid; 736 737 /** 738 * Type of the challenge, e.g. "question". 739 */ 740 char *type; 741 742 /** 743 * Instructions to show the user. 744 */ 745 char *instructions; 746 747 /** 748 * Answer the user gave to a secure question, NULL if none. Kept so 749 * that the answer survives the round-trip through the application 750 * when the provider demands payment before accepting it. 751 */ 752 char *answer; 753 754 /** 755 * Payment secret remembered from a payment request for this 756 * challenge; only valid if @e have_payment_secret. 757 */ 758 struct ANASTASIS_PaymentSecretP payment_secret; 759 760 /** 761 * True if @e payment_secret is set. 762 */ 763 bool have_payment_secret; 764 }; 765 766 767 /** 768 * A decryption policy: solving all of its challenges recovers the 769 * secret. 770 */ 771 struct ANASTASIS_ReduxRecoveryPolicy 772 { 773 /** 774 * UUIDs of the challenges in this policy; each refers to an entry of 775 * the recovery information's @e challenges array. 776 */ 777 struct ANASTASIS_CRYPTO_TruthUUIDP *uuids; 778 779 /** 780 * Length of the @e uuids array. 781 */ 782 unsigned int uuids_len; 783 }; 784 785 786 /** 787 * What we learned about the recovery document we are recovering from. 788 */ 789 struct ANASTASIS_ReduxRecoveryInfo 790 { 791 /** 792 * All challenges referenced by any policy. 793 */ 794 struct ANASTASIS_ReduxChallengeInfo *challenges; 795 796 /** 797 * Length of the @e challenges array. 798 */ 799 unsigned int challenges_len; 800 801 /** 802 * Alternative ways to recover the secret. 803 */ 804 struct ANASTASIS_ReduxRecoveryPolicy *policies; 805 806 /** 807 * Length of the @e policies array. 808 */ 809 unsigned int policies_len; 810 811 /** 812 * Name the user gave the secret, NULL if unknown. 813 */ 814 char *secret_name; 815 816 /** 817 * Provider we downloaded the recovery document from. 818 */ 819 struct ANASTASIS_ProviderUrl provider_url; 820 821 /** 822 * Version of the recovery document. 823 */ 824 uint32_t version; 825 }; 826 827 828 /** 829 * State of a challenge, as reported back to the application. 830 */ 831 enum ANASTASIS_ReduxFeedbackStatus 832 { 833 /** 834 * The TAN was written to a file (test setups only). 835 */ 836 ANASTASIS_RFS_CODE_IN_FILE = 0, 837 838 /** 839 * The TAN was sent to the user out-of-band. 840 */ 841 ANASTASIS_RFS_SEND_TO_ADDRESS = 1, 842 843 /** 844 * A Taler payment is required first. 845 */ 846 ANASTASIS_RFS_TALER_PAYMENT = 2, 847 848 /** 849 * The provider failed. 850 */ 851 ANASTASIS_RFS_SERVER_FAILURE = 3, 852 853 /** 854 * The provider does not know this truth. 855 */ 856 ANASTASIS_RFS_TRUTH_UNKNOWN = 4, 857 858 /** 859 * A wire transfer is required first. 860 */ 861 ANASTASIS_RFS_IBAN_INSTRUCTIONS = 5, 862 863 /** 864 * The challenge was solved. 865 */ 866 ANASTASIS_RFS_SOLVED = 6, 867 868 /** 869 * The answer the user gave was wrong. 870 */ 871 ANASTASIS_RFS_INCORRECT_ANSWER = 7, 872 873 /** 874 * Too many attempts. 875 */ 876 ANASTASIS_RFS_RATE_LIMIT_EXCEEDED = 8 877 }; 878 879 880 /** 881 * Feedback on one challenge. Serializes as one entry of the 882 * `challenge_feedback` object, keyed by @e uuid. 883 */ 884 struct ANASTASIS_ReduxFeedback 885 { 886 /** 887 * Challenge this feedback is about; the key this entry is stored 888 * under. 889 */ 890 struct ANASTASIS_CRYPTO_TruthUUIDP uuid; 891 892 /** 893 * Which variant of @e details is valid. 894 */ 895 enum ANASTASIS_ReduxFeedbackStatus status; 896 897 /** 898 * Human-readable, translated hint for the user. NULL for the 899 * variants that do not produce one. 900 */ 901 char *display_hint; 902 903 /** 904 * Variant-specific details. 905 */ 906 union 907 { 908 909 /** 910 * Details for #ANASTASIS_RFS_CODE_IN_FILE. 911 */ 912 struct 913 { 914 /** 915 * File the TAN was written to. 916 */ 917 char *filename; 918 } code_in_file; 919 920 /** 921 * Details for #ANASTASIS_RFS_SEND_TO_ADDRESS. 922 */ 923 struct 924 { 925 /** 926 * Redacted address the TAN went to, NULL if the provider did not 927 * say (because it had already sent the TAN earlier). 928 */ 929 char *address_hint; 930 } send_to_address; 931 932 /** 933 * Details for #ANASTASIS_RFS_TALER_PAYMENT. 934 */ 935 struct 936 { 937 /** 938 * URI the application must pay. 939 */ 940 char *taler_pay_uri; 941 942 /** 943 * Provider that wants to be paid. 944 */ 945 struct ANASTASIS_ProviderUrl provider; 946 947 /** 948 * Secret identifying the payment. 949 */ 950 struct ANASTASIS_PaymentSecretP payment_secret; 951 } taler_payment; 952 953 /** 954 * Details for #ANASTASIS_RFS_SERVER_FAILURE and 955 * #ANASTASIS_RFS_TRUTH_UNKNOWN. 956 */ 957 struct 958 { 959 /** 960 * Error code reported. 961 */ 962 enum TALER_ErrorCode ec; 963 964 /** 965 * HTTP status reported. 966 */ 967 uint32_t http_status; 968 } server_failure; 969 970 /** 971 * Details for #ANASTASIS_RFS_IBAN_INSTRUCTIONS. 972 */ 973 struct 974 { 975 /** 976 * IBAN to wire the money to. 977 */ 978 char *target_iban; 979 980 /** 981 * Name of the account holder. 982 */ 983 char *target_business_name; 984 985 /** 986 * Subject to use for the wire transfer. 987 */ 988 char *wire_transfer_subject; 989 990 /** 991 * Amount to wire. 992 */ 993 struct TALER_Amount amount; 994 } iban_instructions; 995 996 /** 997 * Details for #ANASTASIS_RFS_INCORRECT_ANSWER. 998 */ 999 struct 1000 { 1001 /** 1002 * Error code reported. 1003 */ 1004 enum TALER_ErrorCode ec; 1005 } incorrect_answer; 1006 1007 /** 1008 * Details for #ANASTASIS_RFS_RATE_LIMIT_EXCEEDED. 1009 */ 1010 struct 1011 { 1012 /** 1013 * Error code reported. 1014 */ 1015 enum TALER_ErrorCode ec; 1016 1017 /** 1018 * How many attempts are permitted per @e request_frequency. 1019 */ 1020 uint64_t request_limit; 1021 1022 /** 1023 * Length of the rate-limiting window. 1024 */ 1025 struct GNUNET_TIME_Relative request_frequency; 1026 } rate_limit_exceeded; 1027 1028 } details; 1029 }; 1030 1031 1032 /** 1033 * The `recovery` variant of the reducer state. 1034 */ 1035 struct ANASTASIS_ReduxRecovery 1036 { 1037 /** 1038 * Which step of the recovery process we are at. 1039 */ 1040 enum ANASTASIS_RecoveryState state; 1041 1042 /** 1043 * The recovery operation itself. This replaces what used to be the 1044 * `recovery_document` field: it is deserialized on parse (inert, no 1045 * network activity until ANASTASIS_recovery_resume() is called) and 1046 * serialized back on the way out. NULL before the recovery starts. 1047 */ 1048 struct ANASTASIS_Recovery *r; 1049 1050 /** 1051 * What we told the application about the recovery document, NULL 1052 * before the recovery starts. 1053 */ 1054 struct ANASTASIS_ReduxRecoveryInfo *ri; 1055 1056 /** 1057 * Feedback on challenges the user tried, keyed by truth UUID. 1058 */ 1059 struct ANASTASIS_ReduxFeedback *challenge_feedback; 1060 1061 /** 1062 * Length of the @e challenge_feedback array. 1063 */ 1064 unsigned int challenge_feedback_len; 1065 1066 /** 1067 * Challenge the user is currently working on; only valid if 1068 * @e have_selected_challenge. 1069 */ 1070 struct ANASTASIS_CRYPTO_TruthUUIDP selected_challenge; 1071 1072 /** 1073 * True if @e selected_challenge is set. 1074 */ 1075 bool have_selected_challenge; 1076 1077 /** 1078 * True if the state has a @e challenge_feedback field at all. 1079 */ 1080 bool have_challenge_feedback; 1081 1082 /** 1083 * The recovered secret. Deliberately untyped, see 1084 * ANASTASIS_ReduxBackup::core_secret. NULL until recovery succeeds. 1085 */ 1086 json_t *core_secret; 1087 }; 1088 1089 1090 /* ********************** Error state ******************************** */ 1091 1092 /** 1093 * The `error` variant of the reducer state. 1094 */ 1095 struct ANASTASIS_ReduxError 1096 { 1097 /** 1098 * The error that occurred. 1099 */ 1100 enum TALER_ErrorCode code; 1101 1102 /** 1103 * Hint derived from @e code, NULL if none. 1104 */ 1105 char *hint; 1106 1107 /** 1108 * Additional detail, NULL if none. 1109 */ 1110 char *detail; 1111 }; 1112 1113 1114 /* ********************** Top-level state **************************** */ 1115 1116 /** 1117 * Which variant of a #ANASTASIS_ReduxState is in use. 1118 */ 1119 enum ANASTASIS_ReduxType 1120 { 1121 /** 1122 * A backup is in progress; `reducer_type` is "backup". 1123 */ 1124 ANASTASIS_RT_BACKUP = 0, 1125 1126 /** 1127 * A recovery is in progress; `reducer_type` is "recovery". 1128 */ 1129 ANASTASIS_RT_RECOVERY = 1, 1130 1131 /** 1132 * Something went wrong; `reducer_type` is "error". 1133 */ 1134 ANASTASIS_RT_ERROR = 2 1135 }; 1136 1137 1138 /** 1139 * Fields shared by the backup and recovery variants. 1140 */ 1141 struct ANASTASIS_ReduxCommon 1142 { 1143 /** 1144 * Continents the user may pick from. 1145 */ 1146 struct ANASTASIS_ReduxContinent *continents; 1147 1148 /** 1149 * Length of the @e continents array. 1150 */ 1151 unsigned int continents_len; 1152 1153 /** 1154 * Countries on the selected continent. 1155 */ 1156 struct ANASTASIS_ReduxCountry *countries; 1157 1158 /** 1159 * Length of the @e countries array. 1160 */ 1161 unsigned int countries_len; 1162 1163 /** 1164 * Identity attributes we need from the user in the selected country. 1165 */ 1166 struct ANASTASIS_ReduxAttributeSpec *required_attributes; 1167 1168 /** 1169 * Length of the @e required_attributes array. 1170 */ 1171 unsigned int required_attributes_len; 1172 1173 /** 1174 * Providers we know about, keyed by URL. 1175 */ 1176 struct ANASTASIS_ReduxProvider *providers; 1177 1178 /** 1179 * Length of the @e providers array. 1180 */ 1181 unsigned int providers_len; 1182 1183 /** 1184 * The user's answers to @e required_attributes. Deliberately 1185 * untyped: this object is dumped with sorted keys and PoW-hashed to 1186 * derive the account key, so the reducer must not normalize it. NULL 1187 * if the user has not answered yet. 1188 */ 1189 json_t *identity_attributes; 1190 1191 /** 1192 * Continent the user selected, NULL if none. 1193 */ 1194 char *selected_continent; 1195 1196 /** 1197 * Country the user selected, NULL if none. 1198 */ 1199 char *selected_country; 1200 1201 /** 1202 * True if the state has a @e continents field at all. An array can 1203 * legitimately be present but empty, which is different from being 1204 * absent, so presence is tracked separately from the length. 1205 */ 1206 bool have_continents; 1207 1208 /** 1209 * True if the state has a @e countries field at all. 1210 */ 1211 bool have_countries; 1212 1213 /** 1214 * True if the state has a @e required_attributes field at all. 1215 */ 1216 bool have_required_attributes; 1217 1218 /** 1219 * True if the state has an @e authentication_providers field at all. 1220 */ 1221 bool have_providers; 1222 1223 /** 1224 * Currencies in play, carried through for user interfaces. 1225 */ 1226 char **currencies; 1227 1228 /** 1229 * Length of the @e currencies array. 1230 */ 1231 unsigned int currencies_len; 1232 1233 /** 1234 * True if the state has a @e currencies field at all. 1235 */ 1236 bool have_currencies; 1237 }; 1238 1239 1240 /** 1241 * A fully parsed reducer state. 1242 */ 1243 struct ANASTASIS_ReduxState 1244 { 1245 /** 1246 * Which variant of @e details is valid. 1247 */ 1248 enum ANASTASIS_ReduxType type; 1249 1250 /** 1251 * Fields common to the backup and recovery variants; unused when 1252 * @e type is #ANASTASIS_RT_ERROR. 1253 */ 1254 struct ANASTASIS_ReduxCommon common; 1255 1256 /** 1257 * Variant-specific state. 1258 */ 1259 union 1260 { 1261 1262 /** 1263 * Valid if @e type is #ANASTASIS_RT_BACKUP. 1264 */ 1265 struct ANASTASIS_ReduxBackup backup; 1266 1267 /** 1268 * Valid if @e type is #ANASTASIS_RT_RECOVERY. 1269 */ 1270 struct ANASTASIS_ReduxRecovery recovery; 1271 1272 /** 1273 * Valid if @e type is #ANASTASIS_RT_ERROR. 1274 */ 1275 struct ANASTASIS_ReduxError error; 1276 1277 } details; 1278 }; 1279 1280 1281 /* ******************* The three generic routines ******************** */ 1282 1283 /** 1284 * Parse @a json into a typed reducer state. This is the only routine 1285 * that reads the JSON encoding of a state. 1286 * 1287 * Parsing is strict: unknown fields, missing mandatory fields and 1288 * values of the wrong type all fail. 1289 * 1290 * @param json the state to parse 1291 * @param[out] ec set to the error that occurred, on failure 1292 * @param[out] detail set to a static string naming the offending field, 1293 * or NULL; never needs to be freed 1294 * @return NULL on failure, otherwise the parsed state, to be freed with 1295 * ANASTASIS_REDUX_state_free_() 1296 */ 1297 struct ANASTASIS_ReduxState * 1298 ANASTASIS_REDUX_state_parse_ (const json_t *json, 1299 enum TALER_ErrorCode *ec, 1300 const char **detail); 1301 1302 1303 /** 1304 * Serialize @a rs back into its JSON encoding. This is the only 1305 * routine that writes the JSON encoding of a state. 1306 * 1307 * @param rs the state to serialize 1308 * @return the JSON encoding, caller must json_decref() it; 1309 * NULL on failure 1310 */ 1311 json_t * 1312 ANASTASIS_REDUX_state_serialize_ (const struct ANASTASIS_ReduxState *rs); 1313 1314 1315 /** 1316 * Release all resources held by @a rs, including any live 1317 * `struct ANASTASIS_Recovery` and `struct ANASTASIS_Truth` handles. 1318 * 1319 * @param[in] rs the state to free, may be NULL 1320 */ 1321 void 1322 ANASTASIS_REDUX_state_free_ (struct ANASTASIS_ReduxState *rs); 1323 1324 1325 /** 1326 * Serialize @a rs, hand the result to @a cb, and free @a rs. This is 1327 * how every action returns its result: it guarantees that the JSON 1328 * encoding is produced in exactly one place and that the state is not 1329 * leaked on any path. 1330 * 1331 * @param[in] rs state to return and free 1332 * @param cb callback to invoke 1333 * @param cb_cls closure for @a cb 1334 * @param ec error code to report alongside the state 1335 */ 1336 void 1337 ANASTASIS_REDUX_return_ (struct ANASTASIS_ReduxState *rs, 1338 ANASTASIS_ActionCallback cb, 1339 void *cb_cls, 1340 enum TALER_ErrorCode ec); 1341 1342 1343 /** 1344 * Report @a ec to @a cb and free @a rs. The counterpart of 1345 * #ANASTASIS_REDUX_return_ for the failure path: the reducer replies 1346 * with a freshly built `error` state, so whatever @a rs held is 1347 * discarded rather than serialized. 1348 * 1349 * @param[in] rs state to free, may be NULL 1350 * @param cb callback to invoke 1351 * @param cb_cls closure for @a cb 1352 * @param ec error to report 1353 * @param detail human-readable detail, may be NULL 1354 */ 1355 void 1356 ANASTASIS_REDUX_fail_ (struct ANASTASIS_ReduxState *rs, 1357 ANASTASIS_ActionCallback cb, 1358 void *cb_cls, 1359 enum TALER_ErrorCode ec, 1360 const char *detail); 1361 1362 1363 /* #ANASTASIS_REDUX_StateCallback, the internal counterpart of 1364 #ANASTASIS_ActionCallback, is declared in `anastasis_api_redux.h`. */ 1365 1366 1367 /* ************************ Small helpers **************************** */ 1368 1369 /** 1370 * Find the provider with the given @a url in @a common. 1371 * 1372 * @param common state to search 1373 * @param url provider URL to look for 1374 * @return NULL if not found 1375 */ 1376 struct ANASTASIS_ReduxProvider * 1377 ANASTASIS_REDUX_provider_find_ (const struct ANASTASIS_ReduxCommon *common, 1378 const char *url); 1379 1380 1381 /** 1382 * Drop all providers from @a common, freeing them. Used when the set 1383 * of applicable providers changes wholesale, e.g. because the user 1384 * picked a different country. 1385 * 1386 * @param[in,out] common state to clear 1387 */ 1388 void 1389 ANASTASIS_REDUX_providers_clear_ (struct ANASTASIS_ReduxCommon *common); 1390 1391 1392 /** 1393 * Free the contents of @a cfg and zero it. 1394 * 1395 * @param[in,out] cfg provider configuration to clear 1396 */ 1397 void 1398 ANASTASIS_REDUX_provider_config_clear_ ( 1399 struct ANASTASIS_ReduxProviderConfig *cfg); 1400 1401 1402 /** 1403 * Drop all continents from @a common, freeing them. 1404 * 1405 * @param[in,out] common state to clear 1406 */ 1407 void 1408 ANASTASIS_REDUX_continents_clear_ (struct ANASTASIS_ReduxCommon *common); 1409 1410 1411 /** 1412 * Drop all countries from @a common, freeing them. 1413 * 1414 * @param[in,out] common state to clear 1415 */ 1416 void 1417 ANASTASIS_REDUX_countries_clear_ (struct ANASTASIS_ReduxCommon *common); 1418 1419 1420 /** 1421 * Drop all required attributes from @a common, freeing them. 1422 * 1423 * @param[in,out] common state to clear 1424 */ 1425 void 1426 ANASTASIS_REDUX_required_attributes_clear_ ( 1427 struct ANASTASIS_ReduxCommon *common); 1428 1429 1430 /* ****************** Importing from resource files ****************** */ 1431 1432 /* 1433 * The reducer's resource files (`redux.countries.json`, `redux.$CC.json`) 1434 * and the `add_provider` action supply data in exactly the JSON encoding 1435 * the parser already understands. Rather than have a second, subtly 1436 * different reader for them, the relevant parser fragments are exposed 1437 * here. Each replaces whatever the state held before. 1438 */ 1439 1440 /** 1441 * Replace the countries of @a common with those in @a arr. 1442 * 1443 * @param[in,out] common state to update 1444 * @param arr array of countries in the state's JSON encoding 1445 * @param[out] detail set to the offending field on failure 1446 * @return #GNUNET_OK on success 1447 */ 1448 enum GNUNET_GenericReturnValue 1449 ANASTASIS_REDUX_countries_set_ (struct ANASTASIS_ReduxCommon *common, 1450 const json_t *arr, 1451 const char **detail); 1452 1453 1454 /** 1455 * Replace the required attributes of @a common with those in @a arr. 1456 * 1457 * @param[in,out] common state to update 1458 * @param arr array of attribute specifications in the state's JSON 1459 * encoding 1460 * @param[out] detail set to the offending field on failure 1461 * @return #GNUNET_OK on success 1462 */ 1463 enum GNUNET_GenericReturnValue 1464 ANASTASIS_REDUX_required_attributes_set_ (struct ANASTASIS_ReduxCommon *common, 1465 const json_t *arr, 1466 const char **detail); 1467 1468 1469 /** 1470 * Replace the entry for provider @a url in @a common with @a val, 1471 * adding the provider if it was not known yet. 1472 * 1473 * @param[in,out] common state to update 1474 * @param url provider the entry is about 1475 * @param val the entry in the state's JSON encoding 1476 * @param[out] detail set to the offending field on failure 1477 * @return #GNUNET_OK on success 1478 */ 1479 enum GNUNET_GenericReturnValue 1480 ANASTASIS_REDUX_provider_set_ (struct ANASTASIS_ReduxCommon *common, 1481 const char *url, 1482 const json_t *val, 1483 const char **detail); 1484 1485 1486 /** 1487 * Find, or create, the provider with the given @a url in @a common. 1488 * 1489 * @param[in,out] common state to search and possibly grow 1490 * @param url provider URL to look for 1491 * @return the existing or newly added (and #ANASTASIS_RPS_NOT_CONTACTED) 1492 * provider entry 1493 */ 1494 struct ANASTASIS_ReduxProvider * 1495 ANASTASIS_REDUX_provider_get_ (struct ANASTASIS_ReduxCommon *common, 1496 const char *url); 1497 1498 1499 /** 1500 * Find the feedback for challenge @a uuid in @a rr. 1501 * 1502 * @param rr recovery state to search 1503 * @param uuid challenge to look for 1504 * @return NULL if not found 1505 */ 1506 struct ANASTASIS_ReduxFeedback * 1507 ANASTASIS_REDUX_feedback_find_ (const struct ANASTASIS_ReduxRecovery *rr, 1508 const struct ANASTASIS_CRYPTO_TruthUUIDP *uuid); 1509 1510 1511 /** 1512 * Find, or create, the feedback entry for challenge @a uuid in @a rr. 1513 * An existing entry is reset (its variant-specific fields freed) so 1514 * that the caller can fill in a fresh variant. 1515 * 1516 * @param[in,out] rr recovery state to search and possibly grow 1517 * @param uuid challenge to look for 1518 * @return the entry to fill in 1519 */ 1520 struct ANASTASIS_ReduxFeedback * 1521 ANASTASIS_REDUX_feedback_get_ (struct ANASTASIS_ReduxRecovery *rr, 1522 const struct ANASTASIS_CRYPTO_TruthUUIDP *uuid); 1523 1524 1525 /** 1526 * Free the variant-specific contents of @a fb (including the display 1527 * hint), but not @a fb itself, and zero them. Used both when freeing 1528 * a state and when overwriting a feedback entry with a new variant. 1529 * 1530 * @param[in,out] fb feedback to reset 1531 */ 1532 void 1533 ANASTASIS_REDUX_feedback_clear_ (struct ANASTASIS_ReduxFeedback *fb); 1534 1535 1536 /** 1537 * Find the challenge with the given @a uuid in the recovery 1538 * information of @a rr. 1539 * 1540 * @param rr recovery state to search 1541 * @param uuid challenge to look for 1542 * @return NULL if not found 1543 */ 1544 struct ANASTASIS_ReduxChallengeInfo * 1545 ANASTASIS_REDUX_challenge_find_ (const struct ANASTASIS_ReduxRecovery *rr, 1546 const struct 1547 ANASTASIS_CRYPTO_TruthUUIDP *uuid); 1548 1549 1550 /** 1551 * Free the contents of the policy @a p and zero it. 1552 * 1553 * @param[in,out] p policy to clear 1554 */ 1555 void 1556 ANASTASIS_REDUX_policy_clear_ (struct ANASTASIS_ReduxPolicy *p); 1557 1558 1559 /** 1560 * Drop all policies from @a backup, freeing them. 1561 * 1562 * @param[in,out] backup state to clear 1563 */ 1564 void 1565 ANASTASIS_REDUX_policies_clear_ (struct ANASTASIS_ReduxBackup *backup); 1566 1567 1568 /** 1569 * Drop all policy providers from @a backup, freeing them. 1570 * 1571 * @param[in,out] backup state to clear 1572 */ 1573 void 1574 ANASTASIS_REDUX_policy_providers_clear_ (struct ANASTASIS_ReduxBackup *backup); 1575 1576 1577 /** 1578 * Drop the pending truth payments from @a backup, freeing them, and 1579 * mark the field as absent. 1580 * 1581 * @param[in,out] backup state to clear 1582 */ 1583 void 1584 ANASTASIS_REDUX_payments_clear_ (struct ANASTASIS_ReduxBackup *backup); 1585 1586 1587 /** 1588 * Drop the pending policy payments from @a backup, freeing them, and 1589 * mark the field as absent. 1590 * 1591 * @param[in,out] backup state to clear 1592 */ 1593 void 1594 ANASTASIS_REDUX_policy_payment_requests_clear_ ( 1595 struct ANASTASIS_ReduxBackup *backup); 1596 1597 1598 /** 1599 * Free the recovery information @a ri. 1600 * 1601 * @param[in] ri recovery information to free, may be NULL 1602 */ 1603 void 1604 ANASTASIS_REDUX_recovery_info_free_ (struct ANASTASIS_ReduxRecoveryInfo *ri); 1605 1606 1607 /** 1608 * Free the contents of @a pu and set it to NULL. 1609 * 1610 * @param[in,out] pu provider URL to clear 1611 */ 1612 void 1613 ANASTASIS_REDUX_provider_url_clear_ (struct ANASTASIS_ProviderUrl *pu); 1614 1615 1616 /** 1617 * Set @a pu to a copy of @a url, freeing any previous value. 1618 * 1619 * @param[in,out] pu provider URL to set 1620 * @param url the URL to copy 1621 */ 1622 void 1623 ANASTASIS_REDUX_provider_url_set_ (struct ANASTASIS_ProviderUrl *pu, 1624 const char *url); 1625 1626 1627 #endif 1628 1629 /* end of anastasis_api_redux_state.h */