anastasis

Credential backup and recovery protocol and service
Log | Files | Refs | Submodules | README | LICENSE

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 */