diff options
Diffstat (limited to 'src/include')
-rw-r--r-- | src/include/anastasis.h | 370 | ||||
-rw-r--r-- | src/include/anastasis_authorization_lib.h | 2 | ||||
-rw-r--r-- | src/include/anastasis_authorization_plugin.h | 82 | ||||
-rw-r--r-- | src/include/anastasis_crypto_lib.h | 171 | ||||
-rw-r--r-- | src/include/anastasis_database_lib.h | 2 | ||||
-rw-r--r-- | src/include/anastasis_database_plugin.h | 69 | ||||
-rw-r--r-- | src/include/anastasis_eufin_lib.h | 2 | ||||
-rw-r--r-- | src/include/anastasis_redux.h | 113 | ||||
-rw-r--r-- | src/include/anastasis_service.h | 716 | ||||
-rw-r--r-- | src/include/anastasis_testing_lib.h | 484 | ||||
-rw-r--r-- | src/include/anastasis_util_lib.h | 39 | ||||
-rw-r--r-- | src/include/gettext.h | 4 | ||||
-rw-r--r-- | src/include/platform.h | 214 |
13 files changed, 1504 insertions, 764 deletions
diff --git a/src/include/anastasis.h b/src/include/anastasis.h index a950172..ea49ee7 100644 --- a/src/include/anastasis.h +++ b/src/include/anastasis.h @@ -3,14 +3,14 @@ Copyright (C) 2020, 2021 Anastasis SARL Anastasis is free software; you can redistribute it and/or modify it under the - terms of the GNU Lesser General Public License as published by the Free Software + terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU Affero General Public License along with + You should have received a copy of the GNU General Public License along with Anastasis; see the file COPYING.GPL. If not, see <http://www.gnu.org/licenses/> */ /** @@ -97,61 +97,43 @@ ANASTASIS_challenge_get_details (struct ANASTASIS_Challenge *challenge); /** * Possible outcomes of trying to start a challenge operation. */ -enum ANASTASIS_ChallengeStatus +enum ANASTASIS_ChallengeStartStatus { /** - * The challenge has been solved. - */ - ANASTASIS_CHALLENGE_STATUS_SOLVED, - - /** - * Instructions for how to solve the challenge are provided. Also - * used if the answer we provided was wrong (or if no answer was - * provided, but one is needed). - */ - ANASTASIS_CHALLENGE_STATUS_INSTRUCTIONS, - - /** - * A redirection URL needed to solve the challenge is provided. Also - * used if the answer we provided was wrong (or if no answer was - * provided, but one is needed). + * We encountered an error talking to the Anastasis service. */ - ANASTASIS_CHALLENGE_STATUS_REDIRECT_FOR_AUTHENTICATION, + ANASTASIS_CHALLENGE_START_STATUS_SERVER_FAILURE, /** * Payment is required before the challenge can be answered. */ - ANASTASIS_CHALLENGE_STATUS_PAYMENT_REQUIRED, + ANASTASIS_CHALLENGE_START_STATUS_PAYMENT_REQUIRED, /** - * We encountered an error talking to the Anastasis service. + * The server does not know this truth. */ - ANASTASIS_CHALLENGE_STATUS_SERVER_FAILURE, + ANASTASIS_CHALLENGE_START_STATUS_TRUTH_UNKNOWN, /** - * The server does not know this truth. + * A filename with the TAN has been provided. */ - ANASTASIS_CHALLENGE_STATUS_TRUTH_UNKNOWN, + ANASTASIS_CHALLENGE_START_STATUS_FILENAME_PROVIDED, /** - * The rate limit for solving the challenge was exceeded. + * A TAN has been send, address hint is provided. */ - ANASTASIS_CHALLENGE_STATUS_RATE_LIMIT_EXCEEDED, + ANASTASIS_CHALLENGE_START_STATUS_TAN_SENT_HINT_PROVIDED, /** - * The user did not satisfy the (external) authentication - * challenge in time. The request should be repeated - * later and may then succeed. + * A TAN has been sent before. */ - ANASTASIS_CHALLENGE_STATUS_AUTH_TIMEOUT, + ANASTASIS_CHALLENGE_START_STATUS_TAN_ALREADY_SENT, /** - * Plugin-specific ("external") instructions for how to solve the - * challenge are provided. + * Wire transfer required, banking details provided. */ - ANASTASIS_CHALLENGE_STATUS_EXTERNAL_INSTRUCTIONS - + ANASTASIS_CHALLENGE_START_STATUS_BANK_TRANSFER_REQUIRED }; @@ -161,10 +143,21 @@ enum ANASTASIS_ChallengeStatus */ struct ANASTASIS_ChallengeStartResponse { + + /** + * HTTP status returned by the server. + */ + unsigned int http_status; + + /** + * Taler-specific error code. + */ + enum TALER_ErrorCode ec; + /** * What is our status on satisfying this challenge. Determines @e details. */ - enum ANASTASIS_ChallengeStatus cs; + enum ANASTASIS_ChallengeStartStatus cs; /** * Which challenge is this about? @@ -179,50 +172,25 @@ struct ANASTASIS_ChallengeStartResponse /** * Challenge details provided if - * @e cs is #ANASTASIS_CHALLENGE_STATUS_INSTRUCTIONS + * @e cs is #ANASTASIS_CHALLENGE_START_STATUS_FILENAME_PROVIDED. */ - struct - { - - /** - * Response with server-side instructions for the user. - */ - const void *body; - - /** - * Mime type of the data in @e body. - */ - const char *content_type; - - /** - * Number of bytes in @e body - */ - size_t body_size; - - /** - * HTTP status returned by the server. #MHD_HTTP_ALREADY_REPORTED - * if the server did already send the challenge to the user, - * #MHD_HTTP_FORBIDDEN if the answer was wrong (or missing). - */ - unsigned int http_status; - } open_challenge; - + const char *tan_filename; /** - * Response with details if - * @e cs is #ANASTASIS_CHALLENGE_STATUS_EXTERNAL_INSTRUCTIONS. + * Challenge details provided if + * @e cs is #ANASTASIS_CHALLENGE_START_STATUS_TAN_SENT_HINT_PROVIDED. */ - const json_t *external_challenge; + const char *tan_address_hint; /** - * Response with URL to redirect the user to, if - * @e cs is #ANASTASIS_CHALLENGE_STATUS_REDIRECT_FOR_AUTHENTICATION. + * Challenge details provided if + * @e cs is #ANASTASIS_CHALLENGE_START_STATUS_BANK_TRANSFER_REQUIRED. */ - const char *redirect_url; + struct ANASTASIS_WireFundsDetails bank_transfer_required; /** * Response with instructions for how to pay, if - * @e cs is #ANASTASIS_CHALLENGE_STATUS_PAYMENT_REQUIRED. + * @e cs is #ANASTASIS_CHALLENGE_START_STATUS_PAYMENT_REQUIRED. */ struct { @@ -239,26 +207,6 @@ struct ANASTASIS_ChallengeStartResponse } payment_required; - - /** - * Response with details about a server-side failure, if - * @e cs is #ANASTASIS_CHALLENGE_STATUS_SERVER_FAILURE. - */ - struct - { - - /** - * HTTP status returned by the server. - */ - unsigned int http_status; - - /** - * Taler-specific error code. - */ - enum TALER_ErrorCode ec; - - } server_failure; - } details; }; @@ -271,7 +219,7 @@ struct ANASTASIS_ChallengeStartResponse * @param csr response details */ typedef void -(*ANASTASIS_AnswerFeedback)( +(*ANASTASIS_ChallengeStartFeedback)( void *cls, const struct ANASTASIS_ChallengeStartResponse *csr); @@ -285,22 +233,144 @@ typedef void * * @param c reference to the escrow challenge which is started * @param psp payment secret, NULL if no payment was yet made - * @param timeout how long to wait for payment - * @param hashed_answer answer to the challenge, NULL if we have none yet * @param af reference to the answerfeedback which is passed back to the user * @param af_cls closure for @a af * @return #GNUNET_OK if the challenge was successfully started */ -int +enum GNUNET_GenericReturnValue ANASTASIS_challenge_start (struct ANASTASIS_Challenge *c, const struct ANASTASIS_PaymentSecretP *psp, - struct GNUNET_TIME_Relative timeout, - const struct GNUNET_HashCode *hashed_answer, - ANASTASIS_AnswerFeedback af, + ANASTASIS_ChallengeStartFeedback af, void *af_cls); /** + * Possible outcomes of trying to start a challenge operation. + */ +enum ANASTASIS_ChallengeAnswerStatus +{ + + /** + * The challenge has been solved. + */ + ANASTASIS_CHALLENGE_ANSWER_STATUS_SOLVED, + + /** + * Payment is required before the challenge can be answered. + */ + ANASTASIS_CHALLENGE_ANSWER_STATUS_PAYMENT_REQUIRED, + + /** + * We encountered an error talking to the Anastasis service. + */ + ANASTASIS_CHALLENGE_ANSWER_STATUS_SERVER_FAILURE, + + /** + * The server does not know this truth. + */ + ANASTASIS_CHALLENGE_ANSWER_STATUS_TRUTH_UNKNOWN, + + /** + * The answer was wrong. + */ + ANASTASIS_CHALLENGE_ANSWER_STATUS_INVALID_ANSWER, + + /** + * The rate limit for solving the challenge was exceeded. + */ + ANASTASIS_CHALLENGE_ANSWER_STATUS_RATE_LIMIT_EXCEEDED + +}; + + +/** + * Response from an #ANASTASIS_challenge_start() operation. + */ +struct ANASTASIS_ChallengeAnswerResponse +{ + + /** + * HTTP status returned by the server. + */ + unsigned int http_status; + + /** + * Taler-specific error code. + */ + enum TALER_ErrorCode ec; + + /** + * What is our status on satisfying this challenge. Determines @e details. + */ + enum ANASTASIS_ChallengeAnswerStatus cs; + + /** + * Which challenge is this about? + */ + struct ANASTASIS_Challenge *challenge; + + /** + * Details depending on @e cs + */ + union + { + + /** + * Details for #ANASTASIS_CHALLENGE_ANSWER_STATUS_RATE_LIMIT_EXCEEDED. + */ + struct + { + + /** + * How many requests are allowed at most per @e request_frequency? + */ + uint32_t request_limit; + + /** + * Frequency at which requests are allowed / new challenges are + * created. + */ + struct GNUNET_TIME_Relative request_frequency; + + } rate_limit_exceeded; + + /** + * Response with instructions for how to pay, if + * @e cs is #ANASTASIS_CHALLENGE_ANSWER_STATUS_PAYMENT_REQUIRED. + */ + struct + { + + /** + * "taler://pay" URI with details how to pay for the challenge. + */ + const char *taler_pay_uri; + + /** + * Payment secret from @e taler_pay_uri. + */ + struct ANASTASIS_PaymentSecretP payment_secret; + + } payment_required; + + } details; +}; + + +/** + * Defines a callback for the response status for a challenge start + * operation. + * + * @param cls closure + * @param car response details + */ +typedef void +(*ANASTASIS_AnswerFeedback)( + void *cls, + const struct ANASTASIS_ChallengeAnswerResponse *car); + + +/** * Challenge answer for a security question. Is referenced to * a challenge and sends back an AnswerFeedback. Convenience * wrapper around #ANASTASIS_challenge_start that hashes @a answer @@ -310,17 +380,17 @@ ANASTASIS_challenge_start (struct ANASTASIS_Challenge *c, * @param psp information about payment made for the recovery * @param timeout how long to wait for payment * @param answer user input instruction defines which input is needed - * @param af reference to the answerfeedback which is passed back to the user - * @param af_cls closure for @a af + * @param csf function to call with the result + * @param csf_cls closure for @a csf * @return #GNUNET_OK on success */ -int +enum GNUNET_GenericReturnValue ANASTASIS_challenge_answer (struct ANASTASIS_Challenge *c, const struct ANASTASIS_PaymentSecretP *psp, struct GNUNET_TIME_Relative timeout, const char *answer, - ANASTASIS_AnswerFeedback af, - void *af_cls); + ANASTASIS_AnswerFeedback csf, + void *csf_cls); /** @@ -337,7 +407,7 @@ ANASTASIS_challenge_answer (struct ANASTASIS_Challenge *c, * @param af_cls closure for @a af * @return #GNUNET_OK on success */ -int +enum GNUNET_GenericReturnValue ANASTASIS_challenge_answer2 (struct ANASTASIS_Challenge *c, const struct ANASTASIS_PaymentSecretP *psp, struct GNUNET_TIME_Relative timeout, @@ -347,6 +417,30 @@ ANASTASIS_challenge_answer2 (struct ANASTASIS_Challenge *c, /** + * User starts a challenge which reponds out of bounds (E-Mail, SMS, + * Postal..) If the challenge is zero cost, the challenge + * instructions will be sent to the client. If the challenge needs + * payment a payment link is sent to the client. After payment the + * challenge start method has to be called again. + * + * @param c reference to the escrow challenge which is started + * @param psp payment secret, NULL if no payment was yet made + * @param timeout how long to wait for payment + * @param hashed_answer answer to the challenge + * @param af reference to the answerfeedback which is passed back to the user + * @param af_cls closure for @a af + * @return #GNUNET_OK if the challenge was successfully started + */ +enum GNUNET_GenericReturnValue +ANASTASIS_challenge_answer3 (struct ANASTASIS_Challenge *c, + const struct ANASTASIS_PaymentSecretP *psp, + struct GNUNET_TIME_Relative timeout, + const struct GNUNET_HashCode *hashed_answer, + ANASTASIS_AnswerFeedback af, + void *af_cls); + + +/** * Abort answering challenge. * * @param c reference to the escrow challenge which was started @@ -356,6 +450,67 @@ ANASTASIS_challenge_abort (struct ANASTASIS_Challenge *c); /** + * Handle for an operation to get available recovery + * document versions. + */ +struct ANASTASIS_VersionCheck; + + +/** + * Callback which passes back meta data about one of the + * recovery documents available at the provider. + * + * @param cls closure for the callback + * @param version version number of the policy document, + * 0 for the end of the list + * @param server_time time of the backup at the provider + * @param recdoc_id hash of the compressed recovery document, uniquely + * identifies the document; NULL for the end of the list + * @param secret_name name of the secret as chosen by the user, + * or NULL if the user did not provide a name + */ +typedef void +(*ANASTASIS_MetaPolicyCallback)(void *cls, + uint32_t version, + struct GNUNET_TIME_Timestamp server_time, + const struct GNUNET_HashCode *recdoc_id, + const char *secret_name); + + +/** + * Obtain an overview of available recovery policies from the + * specified provider. + * + * @param ctx context for making HTTP requests + * @param id_data contains the users identity, (user account on providers) + * @param version defines the version which will be downloaded, 0 for latest version + * @param anastasis_provider_url provider url + * @param provider_salt the server salt + * @param mpc function called with the available versions + * @param mpc_cls closure for @a mpc callback + * @return recovery operation handle + */ +struct ANASTASIS_VersionCheck * +ANASTASIS_recovery_get_versions ( + struct GNUNET_CURL_Context *ctx, + const json_t *id_data, + unsigned int max_version, + const char *anastasis_provider_url, + const struct ANASTASIS_CRYPTO_ProviderSaltP *provider_salt, + ANASTASIS_MetaPolicyCallback mpc, + void *mpc_cls); + + +/** + * Cancel version check operation. + * + * @param vc operation to cancel + */ +void +ANASTASIS_recovery_get_versions_cancel (struct ANASTASIS_VersionCheck *vc); + + +/** * Defines a Decryption Policy with multiple escrow methods */ struct ANASTASIS_DecryptionPolicy @@ -510,9 +665,9 @@ struct ANASTASIS_Recovery; * * @param ctx context for making HTTP requests * @param id_data contains the users identity, (user account on providers) - * @param version defines the version which will be downloaded NULL for latest version - * @param anastasis_provider_url NULL terminated list of possible provider urls - * @param provider_salt the server salt + * @param version defines the version which will be downloaded, 0 for latest version + * @param anastasis_provider_url provider REST API endpoint url + * @param provider_salt the provider's salt * @param pc opens the policy call back which holds the downloaded version and the policies * @param pc_cls closure for callback * @param csc core secret callback is opened, with this the core secert is passed to the client after the authentication @@ -845,7 +1000,7 @@ struct ANASTASIS_ProviderSuccessStatus /** * When will the policy expire? */ - struct GNUNET_TIME_Absolute policy_expiration; + struct GNUNET_TIME_Timestamp policy_expiration; /** * Version number of the policy at the provider. @@ -916,7 +1071,6 @@ struct ANASTASIS_ShareResult */ enum ANASTASIS_UploadStatus ec; - } provider_failure; } details; diff --git a/src/include/anastasis_authorization_lib.h b/src/include/anastasis_authorization_lib.h index 975dd5f..bcbd2e6 100644 --- a/src/include/anastasis_authorization_lib.h +++ b/src/include/anastasis_authorization_lib.h @@ -3,7 +3,7 @@ Copyright (C) 2019, 2021 Anastasis SARL Anastasis is free software; you can redistribute it and/or modify it under the - terms of the GNU Lesser General Public License as published by the Free Software + terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY diff --git a/src/include/anastasis_authorization_plugin.h b/src/include/anastasis_authorization_plugin.h index 91a88f8..a9d993d 100644 --- a/src/include/anastasis_authorization_plugin.h +++ b/src/include/anastasis_authorization_plugin.h @@ -3,7 +3,7 @@ Copyright (C) 2019 Anastasis SARL Anastasis is free software; you can redistribute it and/or modify it under the - terms of the GNU Lesser General Public License as published by the Free Software + terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY @@ -33,21 +33,21 @@ struct ANASTASIS_AUTHORIZATION_State; /** * Enumeration values indicating the various possible - * outcomes of the plugin's `process` function. + * outcomes of the plugin's `challenge` function. */ -enum ANASTASIS_AUTHORIZATION_Result +enum ANASTASIS_AUTHORIZATION_ChallengeResult { /** * We successfully sent the authorization challenge * and queued a reply to MHD. */ - ANASTASIS_AUTHORIZATION_RES_SUCCESS = 0, + ANASTASIS_AUTHORIZATION_CRES_SUCCESS = 0, /** * We failed to transmit the authorization challenge, * but successfully queued a failure response to MHD. */ - ANASTASIS_AUTHORIZATION_RES_FAILED = 1, + ANASTASIS_AUTHORIZATION_CRES_FAILED = 1, /** * The plugin suspended the MHD connection as it needs some more @@ -55,7 +55,7 @@ enum ANASTASIS_AUTHORIZATION_Result * plugin will resume the MHD connection when its work is done, and * then the `process` function should be called again. */ - ANASTASIS_AUTHORIZATION_RES_SUSPENDED = 2, + ANASTASIS_AUTHORIZATION_CRES_SUSPENDED = 2, /** * The plugin tried to queue a reply on the MHD connection and @@ -65,7 +65,7 @@ enum ANASTASIS_AUTHORIZATION_Result * However, we were successful at transmitting the challenge, * so the challenge should be marked as sent. */ - ANASTASIS_AUTHORIZATION_RES_SUCCESS_REPLY_FAILED = 4, + ANASTASIS_AUTHORIZATION_CRES_SUCCESS_REPLY_FAILED = 4, /** * The plugin tried to queue a reply on the MHD connection and @@ -74,14 +74,45 @@ enum ANASTASIS_AUTHORIZATION_Result * * Additionally, we failed to transmit the challenge. */ - ANASTASIS_AUTHORIZATION_RES_FAILED_REPLY_FAILED = 5, + ANASTASIS_AUTHORIZATION_CRES_FAILED_REPLY_FAILED = 5 +}; + + +/** + * Enumeration values indicating the various possible + * outcomes of the plugin's `solve` function. + */ +enum ANASTASIS_AUTHORIZATION_SolveResult +{ + /** + * We failed to transmit the authorization challenge, + * but successfully queued a failure response to MHD. + */ + ANASTASIS_AUTHORIZATION_SRES_FAILED = 0, + + /** + * The plugin suspended the MHD connection as it needs some more + * time to do its (asynchronous) work before we can proceed. The + * plugin will resume the MHD connection when its work is done, and + * then the `process` function should be called again. + */ + ANASTASIS_AUTHORIZATION_SRES_SUSPENDED = 1, + + /** + * The plugin tried to queue a reply on the MHD connection and + * failed to do so. We should return #MHD_NO to MHD to cause the + * HTTP connection to be closed without any reply. + * + * Additionally, we failed to transmit the challenge. + */ + ANASTASIS_AUTHORIZATION_SRES_FAILED_REPLY_FAILED = 2, /** * The authentication process completed successfully * and we should signal success to the client by * returning the truth. */ - ANASTASIS_AUTHORIZATION_RES_FINISHED = 6 + ANASTASIS_AUTHORIZATION_SRES_FINISHED = 3 }; @@ -127,6 +158,14 @@ struct ANASTASIS_AuthorizationPlugin bool payment_plugin_managed; /** + * The plugin expects the "code" in the "start" function to be + * provided by the user and not generated by the Anastasis + * backend. The plugin will then validate the code using its own + * means. Used by TOTP. + */ + bool user_provided_code; + + /** * How often are retries allowed for challenges created * by this plugin? */ @@ -202,18 +241,31 @@ struct ANASTASIS_AuthorizationPlugin /** * Continue issuing authentication challenge to user based on @a data. * I.e. check if the transmission of the challenge via SMS or e-mail - * has completed and/or manipulate @a connection to redirect the client - * to a video identification site. + * has completed and/or manipulate @a connection to direct the client towards solving the challenge. + * + * @param as authorization state + * @param connection HTTP client request (for queuing response, such as redirection to video portal) + * @return state of the request + */ + enum ANASTASIS_AUTHORIZATION_ChallengeResult + (*challenge)(struct ANASTASIS_AUTHORIZATION_State *as, + struct MHD_Connection *connection); + + + /** + * Check if the client has solved the challenge. * * @param as authorization state * @param timeout how long do we have to produce a reply + * @param challenge_response hash of the challenge response, or NULL * @param connection HTTP client request (for queuing response, such as redirection to video portal) * @return state of the request */ - enum ANASTASIS_AUTHORIZATION_Result - (*process)(struct ANASTASIS_AUTHORIZATION_State *as, - struct GNUNET_TIME_Absolute timeout, - struct MHD_Connection *connection); + enum ANASTASIS_AUTHORIZATION_SolveResult + (*solve)(struct ANASTASIS_AUTHORIZATION_State *as, + struct GNUNET_TIME_Absolute timeout, + const struct GNUNET_HashCode *challenge_response, + struct MHD_Connection *connection); /** diff --git a/src/include/anastasis_crypto_lib.h b/src/include/anastasis_crypto_lib.h index 6377baf..8cbc954 100644 --- a/src/include/anastasis_crypto_lib.h +++ b/src/include/anastasis_crypto_lib.h @@ -3,14 +3,14 @@ Copyright (C) 2020, 2021 Anastasis SARL Anastasis is free software; you can redistribute it and/or modify it under the - terms of the GNU Lesser General Public License as published by the Free Software + terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU Affero General Public License along with + You should have received a copy of the GNU General Public License along with Anastasis; see the file COPYING.GPL. If not, see <http://www.gnu.org/licenses/> */ /** @@ -21,7 +21,7 @@ * @author Dennis Neufeld */ #include <jansson.h> -#include <gnunet/gnunet_crypto_lib.h> +#include <gnunet/gnunet_util_lib.h> /** @@ -41,6 +41,12 @@ "Anastasis-Truth-Decryption-Key" /** + * Client to server: please store this meta data. + */ +#define ANASTASIS_HTTP_HEADER_POLICY_META_DATA "Anastasis-Policy-Meta-Data" + + +/** * Client to server: I paid using this payment secret. */ #define ANASTASIS_HTTP_HEADER_PAYMENT_IDENTIFIER "Anastasis-Payment-Identifier" @@ -133,34 +139,25 @@ struct ANASTASIS_CRYPTO_PolicyKeyP /** - * Specifies an encrypted master key, the key is used to encrypt the core secret from the user - */ -struct ANASTASIS_CRYPTO_EncryptedMasterKeyP -{ - struct GNUNET_HashCode key GNUNET_PACKED; -}; - - -/** - * Specifies a Nonce used for the AES encryption, here defined as 32Byte large. + * Nonce used for encryption, 24 bytes. */ struct ANASTASIS_CRYPTO_NonceP { - uint32_t nonce[8]; + uint8_t nonce[crypto_secretbox_NONCEBYTES]; }; /** - * Specifies an IV used for the AES encryption, here defined as 16Byte large. + * Header that is prepended to a ciphertext, consisting of nonce and MAC. */ -struct ANASTASIS_CRYPTO_IvP +struct ANASTASIS_CRYPTO_CiphertextHeaderP { - uint32_t iv[4]; + uint8_t header[crypto_secretbox_NONCEBYTES + crypto_secretbox_MACBYTES]; }; /** - * Specifies an symmetric key used for the AES encryption, here defined as 32Byte large. + * Specifies a key used for symmetric encryption, 32 bytes. */ struct ANASTASIS_CRYPTO_SymKeyP { @@ -169,15 +166,6 @@ struct ANASTASIS_CRYPTO_SymKeyP /** - * Specifies an AES Tag used for the AES authentication, here defined as 16 Byte large. - */ -struct ANASTASIS_CRYPTO_AesTagP -{ - uint32_t aes_tag[4]; -}; - - -/** * Specifies a Key Share from an escrow provider, the combined * keyshares generate the EscrowMasterKey which is used to decrypt the * Secret from the user. @@ -194,17 +182,12 @@ struct ANASTASIS_CRYPTO_KeyShareP struct ANASTASIS_CRYPTO_EncryptedKeyShareP { /** - * Nonce used for the symmetric encryption. - */ - struct ANASTASIS_CRYPTO_NonceP nonce; - - /** - * GCM tag to check authenticity. + * Ciphertext. */ - struct ANASTASIS_CRYPTO_AesTagP tag; + struct ANASTASIS_CRYPTO_CiphertextHeaderP header; /** - * The actual key share. + * The actual key share, encrypted. */ struct ANASTASIS_CRYPTO_KeyShareP keyshare; }; @@ -271,6 +254,33 @@ struct ANASTASIS_AccountSignatureP GNUNET_NETWORK_STRUCT_END +/** + * Result of encrypting the core secret. + */ +struct ANASTASIS_CoreSecretEncryptionResult +{ + /** + * Encrypted core secret. + */ + void *enc_core_secret; + + /** + * Size of the encrypted core secret. + */ + size_t enc_core_secret_size; + + /** + * Array of encrypted master keys. Each key is encrypted + * to a different policy key. + */ + void **enc_master_keys; + + /** + * Sizes of the encrypted master keys. + */ + size_t *enc_master_key_sizes; +}; + /** * Hash a numerical answer to compute the hash value to be submitted @@ -291,13 +301,13 @@ ANASTASIS_hash_answer (uint64_t code, * data. * * @param id_data JSON encoded data, which contains the raw user secret - * @param server_salt salt from the server (escrow provider) + * @param provider_salt salt from the server (escrow provider) * @param[out] id reference to the id which was created */ void ANASTASIS_CRYPTO_user_identifier_derive ( const json_t *id_data, - const struct ANASTASIS_CRYPTO_ProviderSaltP *server_salt, + const struct ANASTASIS_CRYPTO_ProviderSaltP *provider_salt, struct ANASTASIS_CRYPTO_UserIdentifierP *id); @@ -344,7 +354,7 @@ ANASTASIS_CRYPTO_secure_answer_hash ( /** - * Encrypt and signs the recovery document with AES256, the recovery + * Encrypt and signs the recovery document, the recovery * document is encrypted with a derivation from the user identifier * and the salt "erd". * @@ -365,7 +375,7 @@ ANASTASIS_CRYPTO_recovery_document_encrypt ( /** - * Decrypts the recovery document with AES256, the decryption key is generated with + * Decrypts the recovery document, the decryption key is generated with * the user identifier provided by the user and the salt "erd". The nonce and IV used for the encryption * are the first 48 bytes of the data. * @@ -386,6 +396,44 @@ ANASTASIS_CRYPTO_recovery_document_decrypt ( /** + * Encrypt recovery document meta data. + * + * @param id Hashed User input, used for the generation of the encryption key + * @param meta_data contains the recovery document meta data + * @param meta_data_size number of bytes in @a meta_data + * @param[out] enc_meta_data set to the encrypted meta data + * @param[out] enc_meta_data_size size of the result + */ +void +ANASTASIS_CRYPTO_recovery_metadata_encrypt ( + const struct ANASTASIS_CRYPTO_UserIdentifierP *id, + const void *meta_data, + size_t meta_data_size, + void **enc_meta_data, + size_t *enc_meta_data_size); + + +/** + * Decrypts the recovery meta data. + * + * @param id Hashed User input, used for the generation of the decryption key + * @param enc_meta_data encrypted meta data + * @param enc_meta_data_size number of bytes in @a enc_meta_data + * @param[out] meta_data decrypted meta data + * @param[out] meta_data_size size of the result in @a meta_data + * @return #GNUNET_OK on success, #GNUNET_NO if the authentication tag + * was wrong + */ +enum GNUNET_GenericReturnValue +ANASTASIS_CRYPTO_recovery_metadata_decrypt ( + const struct ANASTASIS_CRYPTO_UserIdentifierP *id, + const void *enc_meta_data, + size_t enc_meta_data_size, + void **meta_data, + size_t *meta_data_size); + + +/** * Encrypts a keyshare with a key generated with the user identification as entropy and the salt "eks". * * @param key_share the key share which is afterwards encrypted @@ -419,7 +467,7 @@ ANASTASIS_CRYPTO_keyshare_decrypt ( /** * Encrypts the truth data which contains the hashed answer or the - * phone number. It is encrypted with AES256, the key is generated + * phone number. It is encrypted with xsalsa20-poly1305, the key is generated * with the user identification as entropy source and the salt "ect". * * @param nonce value to use for the nonce @@ -442,7 +490,7 @@ ANASTASIS_CRYPTO_truth_encrypt ( /** * Decrypts the truth data which contains the hashed answer or the phone number.. - * It is decrypted with AES256, the key is generated with the user identification as + * It is decrypted with xsalsa20-poly1305, the key is generated with the user identification as * entropy source and the salt "ect". * * @param truth_enc_key master key used for encryption of the truth (see interface EscrowMethod) @@ -492,24 +540,30 @@ ANASTASIS_CRYPTO_policy_key_derive ( * The core secret is the user provided secret which will be saved with Anastasis. * The secret will be encrypted with the master key, the master key is a random key which will * be generated. The master key afterwards will be encrypted with the different policy keys. - * Encryption is performed with AES256 + * Encryption is performed with xsalsa20-poly1305. * * @param policy_keys an array of policy keys which are used to encrypt the master key * @param policy_keys_length defines the amount of policy keys and also the amount of encrypted master keys * @param core_secret the user provided core secret which is secured by anastasis * @param core_secret_size the size of the core secret - * @param[out] enc_core_secret the core secret is encrypted with the generated master key - * @param[out] encrypted_master_keys array of encrypted master keys which will be safed inside the policies one encrypted - * master key is created for each policy key + * @returns result of the encryption, must be freed with #ANASTASIS_CRYPTO_destroy_encrypted_core_secret */ -void +struct ANASTASIS_CoreSecretEncryptionResult * ANASTASIS_CRYPTO_core_secret_encrypt ( const struct ANASTASIS_CRYPTO_PolicyKeyP *policy_keys, unsigned int policy_keys_length, const void *core_secret, - size_t core_secret_size, - void **enc_core_secret, - struct ANASTASIS_CRYPTO_EncryptedMasterKeyP *encrypted_master_keys); + size_t core_secret_size); + + +/** + * Destroy a core secret encryption result. + * + * @param cser the result to destroy + */ +void +ANASTASIS_CRYPTO_destroy_encrypted_core_secret ( + struct ANASTASIS_CoreSecretEncryptionResult *cser); /** @@ -517,6 +571,7 @@ ANASTASIS_CRYPTO_core_secret_encrypt ( * Afterwards the core secret is encrypted with the master key. The core secret is returned. * * @param encrypted_master_key master key for decrypting the core secret, is itself encrypted by the policy key + * @param encrypted_master_key_size size of the encrypted master key * @param policy_key built policy key which will decrypt the master key * @param encrypted_core_secret the encrypted core secret from the user, will be encrypted with the policy key * @param encrypted_core_secret_size size of the encrypted core secret @@ -525,9 +580,23 @@ ANASTASIS_CRYPTO_core_secret_encrypt ( */ void ANASTASIS_CRYPTO_core_secret_recover ( - const struct ANASTASIS_CRYPTO_EncryptedMasterKeyP *encrypted_master_key, + const void *encrypted_master_key, + size_t encrypted_master_key_size, const struct ANASTASIS_CRYPTO_PolicyKeyP *policy_key, const void *encrypted_core_secret, size_t encrypted_core_secret_size, void **core_secret, size_t *core_secret_size); + + +/** + * Convert a @a uuid to a shortened, human-readable string + * useful to show to users to identify the truth. + * Note that the return value is in a global variable and + * only valid until the next invocation of this function. + * + * @param uuid UUID to convert + * @return string representation + */ +const char * +ANASTASIS_CRYPTO_uuid2s (const struct ANASTASIS_CRYPTO_TruthUUIDP *uuid); diff --git a/src/include/anastasis_database_lib.h b/src/include/anastasis_database_lib.h index 7de1612..896b039 100644 --- a/src/include/anastasis_database_lib.h +++ b/src/include/anastasis_database_lib.h @@ -3,7 +3,7 @@ Copyright (C) 2019 Anastasis SARL Anastasis is free software; you can redistribute it and/or modify it under the - terms of the GNU Lesser General Public License as published by the Free Software + terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY diff --git a/src/include/anastasis_database_plugin.h b/src/include/anastasis_database_plugin.h index 7bf91a2..2082bf9 100644 --- a/src/include/anastasis_database_plugin.h +++ b/src/include/anastasis_database_plugin.h @@ -1,9 +1,9 @@ /* This file is part of Anastasis - Copyright (C) 2019-2021 Anastasis SARL + Copyright (C) 2019-2022 Anastasis SARL Anastasis is free software; you can redistribute it and/or modify it under the - terms of the GNU Lesser General Public License as published by the Free Software + terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY @@ -136,7 +136,7 @@ enum ANASTASIS_DB_StoreStatus typedef void (*ANASTASIS_DB_PaymentPendingIterator)( void *cls, - struct GNUNET_TIME_Absolute timestamp, + struct GNUNET_TIME_Timestamp timestamp, const struct ANASTASIS_PaymentSecretP *payment_secret, const struct TALER_Amount *amount); @@ -159,6 +159,26 @@ typedef bool /** + * Function called on matching meta data. Note that if the client did + * not provide meta data for @a version, the function will be called + * with @a recovery_meta_data being NULL. + * + * @param cls closure + * @param version the version of the recovery document + * @param ts timestamp when the document was uploaded + * @param recovery_meta_data contains meta data about the encrypted recovery document + * @param recovery_meta_data_size size of @a recovery_meta_data blob + * @return #GNUNET_OK to continue to iterate, #GNUNET_NO to abort iteration + */ +typedef enum GNUNET_GenericReturnValue +(*ANASTASIS_DB_RecoveryMetaCallback)(void *cls, + uint32_t version, + struct GNUNET_TIME_Timestamp ts, + const void *recovery_meta_data, + size_t recovery_meta_data_size); + + +/** * Handle to interact with the database. * * Functions ending with "_TR" run their OWN transaction scope @@ -329,6 +349,8 @@ struct ANASTASIS_DatabasePlugin * @param recovery_data_hash hash of @a data * @param recovery_data contains encrypted recovery document * @param recovery_data_size size of @a recovery_data blob + * @param recovery_meta_data contains meta data about the encrypted recovery document + * @param recovery_meta_data_size size of @a recovery_meta_data blob * @param payment_secret identifier for the payment, used to later charge on uploads * @param[out] version set to the version assigned to the document by the database * @return transaction status, 0 if upload could not be finished because @a payment_secret @@ -342,11 +364,34 @@ struct ANASTASIS_DatabasePlugin const struct GNUNET_HashCode *recovery_data_hash, const void *recovery_data, size_t recovery_data_size, + const void *recovery_meta_data, + size_t recovery_meta_data_size, const struct ANASTASIS_PaymentSecretP *payment_secret, uint32_t *version); /** + * Fetch recovery document meta data for user. Returns + * meta data in descending order from @a max_version. + * The size of the result set may be limited. + * + * @param cls closure + * @param account_pub public key of the user's account + * @param max_version the maximum version number the user requests + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status + */ + enum GNUNET_DB_QueryStatus + (*get_recovery_meta_data)( + void *cls, + const struct ANASTASIS_CRYPTO_AccountPublicKeyP *account_pub, + uint32_t max_version, + ANASTASIS_DB_RecoveryMetaCallback cb, + void *cb_cls); + + + /** * Fetch recovery document for user according given version. * * @param cls closure @@ -468,7 +513,7 @@ struct ANASTASIS_DatabasePlugin (*lookup_account)( void *cls, const struct ANASTASIS_CRYPTO_AccountPublicKeyP *account_pub, - struct GNUNET_TIME_Absolute *paid_until, + struct GNUNET_TIME_Timestamp *paid_until, struct GNUNET_HashCode *recovery_data_hash, uint32_t *version); @@ -525,7 +570,7 @@ struct ANASTASIS_DatabasePlugin const struct ANASTASIS_CRYPTO_AccountPublicKeyP *account_pub, const struct ANASTASIS_PaymentSecretP *payment_identifier, struct GNUNET_TIME_Relative lifetime, - struct GNUNET_TIME_Absolute *paid_until); + struct GNUNET_TIME_Timestamp *paid_until); /** @@ -543,7 +588,7 @@ struct ANASTASIS_DatabasePlugin void *cls, const struct ANASTASIS_CRYPTO_AccountPublicKeyP *account_pub, const struct ANASTASIS_PaymentSecretP *payment_identifier, - struct GNUNET_TIME_Absolute eol); + struct GNUNET_TIME_Timestamp eol); /** @@ -596,7 +641,7 @@ struct ANASTASIS_DatabasePlugin (*check_truth_upload_paid)( void *cls, const struct ANASTASIS_CRYPTO_TruthUUIDP *uuid, - struct GNUNET_TIME_Absolute *paid_until); + struct GNUNET_TIME_Timestamp *paid_until); /** @@ -633,7 +678,7 @@ struct ANASTASIS_DatabasePlugin (*mark_challenge_code_satisfied)( void *cls, const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid, - const uint64_t code); + uint64_t code); /** @@ -653,7 +698,7 @@ struct ANASTASIS_DatabasePlugin void *cls, const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid, const uint64_t code, - struct GNUNET_TIME_Absolute after); + struct GNUNET_TIME_Timestamp after); /** @@ -679,7 +724,7 @@ struct ANASTASIS_DatabasePlugin struct GNUNET_TIME_Relative rotation_period, struct GNUNET_TIME_Relative validity_period, uint32_t retry_counter, - struct GNUNET_TIME_Absolute *retransmission_date, + struct GNUNET_TIME_Timestamp *retransmission_date, uint64_t *code); @@ -780,7 +825,7 @@ struct ANASTASIS_DatabasePlugin const struct TALER_Amount *amount, const char *debit_account, const char *credit_account, - struct GNUNET_TIME_Absolute execution_date); + struct GNUNET_TIME_Timestamp execution_date); /** @@ -802,7 +847,7 @@ struct ANASTASIS_DatabasePlugin (*test_auth_iban_payment)( void *cls, const char *debit_account, - struct GNUNET_TIME_Absolute earliest_date, + struct GNUNET_TIME_Timestamp earliest_date, ANASTASIS_DB_AuthIbanTransfercheck cb, void *cb_cls); diff --git a/src/include/anastasis_eufin_lib.h b/src/include/anastasis_eufin_lib.h index daff98a..91b9fe3 100644 --- a/src/include/anastasis_eufin_lib.h +++ b/src/include/anastasis_eufin_lib.h @@ -112,7 +112,7 @@ struct ANASTASIS_EUFIN_CreditDetails /** * Time of the the transfer */ - struct GNUNET_TIME_Absolute execution_date; + struct GNUNET_TIME_Timestamp execution_date; /** * The wire transfer subject. diff --git a/src/include/anastasis_redux.h b/src/include/anastasis_redux.h index dd28174..2adb74b 100644 --- a/src/include/anastasis_redux.h +++ b/src/include/anastasis_redux.h @@ -3,14 +3,14 @@ Copyright (C) 2020, 2021 Anastasis SARL Anastasis is free software; you can redistribute it and/or modify it under the - terms of the GNU Lesser General Public License as published by the Free Software + terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU Affero General Public License along with + You should have received a copy of the GNU General Public License along with Anastasis; see the file COPYING.GPL. If not, see <http://www.gnu.org/licenses/> */ /** @@ -111,4 +111,111 @@ void ANASTASIS_redux_action_cancel (struct ANASTASIS_ReduxAction *ra); +/** + * Handle for a policy discovery operation. + */ +struct ANASTASIS_PolicyDiscovery; + + +/** + * Function called on each discovered recovery policy. + * + * The client can then start a new policy discovery process, using the + * smallest (also most recent) @a version received per @a provider_url + * in the cursor to resume. Note that in this case, the application + * logic is responsible for de-duplication using @a hcpd, or it may show + * policies again if they are at different providers under versions not + * queried up to the cursor. + * + * @param cls closure + * @param hcpd hash of the compressed policy document (unique per policy) + * @param provider_url which provider claims to have this policy + * @param version version of the policy at this provider + * @param attribute_mask combination of optional identity attributes + * present in the state that was used to locate this version + * @param server_time when did the provider receive the upload + * @param secret_name name the user assigned to the backup + * @param providers json array of providers with this policy + */ +typedef void +(*ANASTASIS_PolicyDiscoveryCallback)(void *cls, + const struct GNUNET_HashCode *hcpd, + const char *provider_url, + uint32_t version, + json_int_t attribute_mask, + struct GNUNET_TIME_Timestamp server_time, + const char *secret_name, + const json_t *providers); + + +/** + * Start requesting providers for available policies for the + * recovery specified in @a state. + * + * @param state state to discover polices in + * @param cursor array containing "provider_url", attribute "mask", + * and "max_version" values (max_version is exclusive). + * Used for incremental discovery, NULL is allowed + * to begin from the latest version(s). + * @param cb function to call with results + * @param cb_cls closure for @a cb + * @return NULL on failure + */ +struct ANASTASIS_PolicyDiscovery * +ANASTASIS_policy_discovery_start (const json_t *state, + const json_t *cursor, + ANASTASIS_PolicyDiscoveryCallback cb, + void *cb_cls); + + +/** + * Add another provider to the list of providers to do discovery + * on. + * + * @param[in,out] pd policy discovery to expand + * @param provider_url the provider to add to the set of providers + * @param provider_state configuration state for that provider + */ +void +ANASTASIS_policy_discovery_more (struct ANASTASIS_PolicyDiscovery *pd, + const char *provider_url, + json_t *provider_state); + +/** + * Stop policy discovery. + * + * @param[in] pd operation to stop + */ +void +ANASTASIS_policy_discovery_stop (struct ANASTASIS_PolicyDiscovery *pd); + + +/** + * Compute a subset of @a master_id removing optional attributes + * based on the bits set in @a mask. + * + * @param state reducer state (tells us which attributes are optional) + * @param master_id set of identity attributes to mask + * @param mask bitmask to apply + * @return masked copy of the @a master_id + */ +json_t * +ANASTASIS_mask_id_data (const json_t *state, + const json_t *master_id, + json_int_t mask); + +/** + * Lookup @a salt of @a provider_url in @a state. + * + * @param state the state to inspect + * @param provider_url provider to look into + * @param[out] salt value to extract + * @return #GNUNET_OK on success + */ +enum GNUNET_GenericReturnValue +ANASTASIS_reducer_lookup_salt (const json_t *state, + const char *provider_url, + struct ANASTASIS_CRYPTO_ProviderSaltP *salt); + + #endif /* _ANASTASIS_REDUX_H */ diff --git a/src/include/anastasis_service.h b/src/include/anastasis_service.h index bec89d1..2f30a8b 100644 --- a/src/include/anastasis_service.h +++ b/src/include/anastasis_service.h @@ -1,16 +1,16 @@ /* This file is part of Anastasis - Copyright (C) 2019-2021 Anastasis SARL + Copyright (C) 2019-2022 Anastasis SARL Anastasis is free software; you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free Software + terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU Lesser General Public License along with + You should have received a copy of the GNU General Public License along with Anastasis; see the file COPYING.LIB. If not, see <http://www.gnu.org/licenses/> */ /** @@ -51,56 +51,82 @@ struct ANASTASIS_AuthorizationMethodConfig */ struct ANASTASIS_Config { - /** - * Protocol version supported by the server. - */ - const char *version; /** - * Business name of the anastasis provider. + * HTTP status returned. */ - const char *business_name; + unsigned int http_status; /** - * Currency used for payments by the server. + * Taler-specific error code, #TALER_EC_NONE on success. */ - const char *currency; + enum TALER_ErrorCode ec; /** - * Array of authorization methods supported by the server. + * Full response in JSON, if provided. */ - const struct ANASTASIS_AuthorizationMethodConfig *methods; + const json_t *response; /** - * Length of the @e methods array. + * Details depending on @e http_status. */ - unsigned int methods_length; + union + { - /** - * Maximum size of an upload in megabytes. - */ - uint32_t storage_limit_in_megabytes; + /** + * Details on #MHD_HTTP_OK. + */ + struct + { - /** - * Annual fee for an account / policy upload. - */ - struct TALER_Amount annual_fee; + /** + * Protocol version supported by the server. + */ + const char *version; - /** - * Fee for a truth upload. - */ - struct TALER_Amount truth_upload_fee; + /** + * Business name of the anastasis provider. + */ + const char *business_name; - /** - * Maximum legal liability for data loss covered by the - * provider. - */ - struct TALER_Amount liability_limit; + /** + * Array of authorization methods supported by the server. + */ + const struct ANASTASIS_AuthorizationMethodConfig *methods; - /** - * Server salt. - */ - struct ANASTASIS_CRYPTO_ProviderSaltP salt; + /** + * Length of the @e methods array. + */ + unsigned int methods_length; + + /** + * Maximum size of an upload in megabytes. + */ + uint32_t storage_limit_in_megabytes; + + /** + * Annual fee for an account / policy upload. + */ + struct TALER_Amount annual_fee; + + /** + * Fee for a truth upload. + */ + struct TALER_Amount truth_upload_fee; + + /** + * Maximum legal liability for data loss covered by the + * provider. + */ + struct TALER_Amount liability_limit; + + /** + * Provider salt. + */ + struct ANASTASIS_CRYPTO_ProviderSaltP provider_salt; + } ok; + + } details; }; @@ -112,12 +138,10 @@ struct ANASTASIS_Config * the server provided an acceptable response. * * @param cls closure - * @param http_status the HTTP status * @param acfg configuration obtained, NULL if we could not parse it */ typedef void (*ANASTASIS_ConfigCallback)(void *cls, - unsigned int http_status, const struct ANASTASIS_Config *acfg); @@ -156,34 +180,181 @@ ANASTASIS_config_cancel (struct ANASTASIS_ConfigOperation *co); /** - * Detailed results from the successful download. + * Detailed meta data result. */ -struct ANASTASIS_DownloadDetails +struct ANASTASIS_MetaDataEntry { + + /** + * Timestamp of the backup at the server. + */ + struct GNUNET_TIME_Timestamp server_time; + /** - * Signature (already verified). + * The encrypted meta data we downloaded. */ - struct ANASTASIS_AccountSignatureP sig; + const void *meta_data; /** - * Hash over @e policy and @e policy_size. + * Number of bytes in @e meta_data. */ - struct GNUNET_HashCode curr_policy_hash; + size_t meta_data_size; /** - * The backup we downloaded. + * Policy version this @e meta_data is for. */ - const void *policy; + uint32_t version; +}; + + +/** + * Detailed results for meta data download. + */ +struct ANASTASIS_MetaDownloadDetails +{ /** - * Number of bytes in @e backup. + * HTTP status returned. */ - size_t policy_size; + unsigned int http_status; /** - * Policy version returned by the service. + * Taler-specific error code, #TALER_EC_NONE on success. */ - uint32_t version; + enum TALER_ErrorCode ec; + + /** + * Full response in JSON, if provided. + */ + const json_t *response; + + /** + * Details depending on @e http_status. + */ + union + { + + /** + * Details on #MHD_HTTP_OK. + */ + struct + { + + /** + * Version-sorted array of meta data we downloaded. + */ + const struct ANASTASIS_MetaDataEntry *metas; + + /** + * Number of entries in @e metas. + */ + size_t metas_length; + + } ok; + + } details; +}; + + +/** + * Callback to process a GET /policy/$POL/meta request + * + * @param cls closure + * @param dd the response details + */ +typedef void +(*ANASTASIS_PolicyMetaLookupCallback) ( + void *cls, + const struct ANASTASIS_MetaDownloadDetails *dd); + + +/** + * Does a GET /policy/$POL/meta. + * + * @param ctx execution context + * @param backend_url base URL of the merchant backend + * @param anastasis_pub public key of the user's account + * @param max_version maximum version number to fetch + * @param cb callback which will work the response gotten from the backend + * @param cb_cls closure to pass to the callback + * @return handle for this operation, NULL upon errors + */ +struct ANASTASIS_PolicyMetaLookupOperation * +ANASTASIS_policy_meta_lookup ( + struct GNUNET_CURL_Context *ctx, + const char *backend_url, + const struct ANASTASIS_CRYPTO_AccountPublicKeyP *anastasis_pub, + uint32_t max_version, + ANASTASIS_PolicyMetaLookupCallback cb, + void *cb_cls); + + +/** + * Cancel a GET /policy/$POL/meta request. + * + * @param plo cancel the policy lookup operation + */ +void +ANASTASIS_policy_meta_lookup_cancel ( + struct ANASTASIS_PolicyMetaLookupOperation *plo); + + +/** + * Detailed results from the successful download. + */ +struct ANASTASIS_DownloadDetails +{ + + /** + * HTTP status returned. + */ + unsigned int http_status; + + /** + * Taler-specific error code, #TALER_EC_NONE on success. + */ + enum TALER_ErrorCode ec; + + /** + * Details depending on @e http_status. + */ + union + { + + /** + * Details on #MHD_HTTP_OK. + */ + struct + { + + /** + * Signature (already verified). + */ + struct ANASTASIS_AccountSignatureP sig; + + /** + * Hash over @e policy and @e policy_size. + */ + struct GNUNET_HashCode curr_policy_hash; + + /** + * The backup we downloaded. + */ + const void *policy; + + /** + * Number of bytes in @e backup. + */ + size_t policy_size; + + /** + * Policy version returned by the service. + */ + uint32_t version; + } ok; + + } details; + }; @@ -197,13 +368,10 @@ struct ANASTASIS_PolicyLookupOperation; * Callback to process a GET /policy request * * @param cls closure - * @param http_status HTTP status code for this request - * @param ec anastasis-specific error code - * @param obj the response body + * @param dd the response details */ typedef void (*ANASTASIS_PolicyLookupCallback) (void *cls, - unsigned int http_status, const struct ANASTASIS_DownloadDetails *dd); @@ -337,7 +505,7 @@ struct ANASTASIS_UploadDetails * At what time is the provider set to forget this * policy (because the account expires)? */ - struct GNUNET_TIME_Absolute policy_expiration; + struct GNUNET_TIME_Timestamp policy_expiration; /** * Version number of the resulting policy. @@ -371,8 +539,7 @@ struct ANASTASIS_UploadDetails * Callback to process a POST /policy request * * @param cls closure - * @param http_status HTTP status code for this request - * @param obj the decoded response body + * @param up the decoded response body */ typedef void (*ANASTASIS_PolicyStoreCallback) (void *cls, @@ -387,6 +554,8 @@ typedef void * @param anastasis_priv private key of the user's account * @param recovery_data policy data to be stored * @param recovery_data_size number of bytes in @a recovery_data + * @param recovery_meta_data policy meta data to be stored + * @param recovery_meta_data_size number of bytes in @a recovery_meta_data * @param payment_years_requested for how many years would the client like the service to store the truth? * @param payment_secret payment identifier of last payment * @param payment_timeout how long to wait for the payment, use @@ -402,6 +571,8 @@ ANASTASIS_policy_store ( const struct ANASTASIS_CRYPTO_AccountPrivateKeyP *anastasis_priv, const void *recovery_data, size_t recovery_data_size, + const void *recovery_meta_data, + size_t recovery_meta_data_size, uint32_t payment_years_requested, const struct ANASTASIS_PaymentSecretP *payment_secret, struct GNUNET_TIME_Relative payment_timeout, @@ -423,299 +594,418 @@ ANASTASIS_policy_store_cancel ( /** - * Operational status. + * Handle for a POST /truth operation. + */ +struct ANASTASIS_TruthStoreOperation; + + +/** + * Callback to process a POST /truth request + * + * @param cls closure + * @param obj the response body + */ +typedef void +(*ANASTASIS_TruthStoreCallback) (void *cls, + const struct ANASTASIS_UploadDetails *up); + + +/** + * Store Truth, does a POST /truth/$UUID + * + * @param ctx the CURL context used to connect to the backend + * @param backend_url backend's base URL, including final "/" + * @param uuid unique identfication of the Truth Upload + * @param type type of the authorization method + * @param encrypted_keyshare key material to return to the client upon authorization + * @param truth_mime mime type of @e encrypted_truth (after decryption) + * @param encrypted_truth_size number of bytes in @e encrypted_truth + * @param encrypted_truth contains the @a type-specific authorization data + * @param payment_years_requested for how many years would the client like the service to store the truth? + * @param payment_timeout how long to wait for the payment, use + * #GNUNET_TIME_UNIT_ZERO to let the server pick + * @param cb callback processing the response from /truth + * @param cb_cls closure for cb + * @return handle for the operation + */ +struct ANASTASIS_TruthStoreOperation * +ANASTASIS_truth_store ( + struct GNUNET_CURL_Context *ctx, + const char *backend_url, + const struct ANASTASIS_CRYPTO_TruthUUIDP *uuid, + const char *type, + const struct ANASTASIS_CRYPTO_EncryptedKeyShareP *encrypted_keyshare, + const char *truth_mime, + size_t encrypted_truth_size, + const void *encrypted_truth, + uint32_t payment_years_requested, + struct GNUNET_TIME_Relative payment_timeout, + ANASTASIS_TruthStoreCallback cb, + void *cb_cls); + + +/** + * Cancel a POST /truth request. + * + * @param tso the truth store operation + */ +void +ANASTASIS_truth_store_cancel ( + struct ANASTASIS_TruthStoreOperation *tso); + + +/** + * Possible ways how to proceed with a challenge. */ -enum ANASTASIS_KeyShareDownloadStatus +enum ANASTASIS_ChallengeDetailType { - /** - * We got the encrypted key share. - */ - ANASTASIS_KSD_SUCCESS = 0, /** - * Payment is needed to proceed with the recovery. + * A challenge TAN was written to a file. + * The name of the file is provided. */ - ANASTASIS_KSD_PAYMENT_REQUIRED, + ANASTASIS_CS_FILE_WRITTEN, /** - * The provided answer was wrong or missing. Instructions for - * getting a good answer may be provided. + * A challenge TAN was sent to the customer. + * A hint may be provided as to the address used. */ - ANASTASIS_KSD_INVALID_ANSWER, + ANASTASIS_CS_TAN_SENT, /** - * To answer the challenge, the client should be redirected to - * the given URL. + * A challenge TAN was already recently sent to the customer. + * A hint may be provided as to the address used. */ - ANASTASIS_KSD_REDIRECT_FOR_AUTHENTICATION, + ANASTASIS_CS_TAN_ALREADY_SENT, /** - * The provider had an error. + * The customer should wire funds to the bank + * account address provided. */ - ANASTASIS_KSD_SERVER_ERROR, + ANASTASIS_CS_WIRE_FUNDS + +}; + + +/** + * This structure contains information about where to wire the funds + * to authenticate as well as a hint as to which bank account to send + * the funds from. + */ +struct ANASTASIS_WireFundsDetails +{ /** - * The provider claims we made an error. + * Answer code expected. */ - ANASTASIS_KSD_CLIENT_FAILURE, + uint64_t answer_code; /** - * The provider does not know this truth. + * How much should be sent. */ - ANASTASIS_KSD_TRUTH_UNKNOWN, + struct TALER_Amount amount; /** - * Too many attempts to solve the challenge were made in a short - * time. Try again later. + * IBAN where to send the funds. */ - ANASTASIS_KSD_RATE_LIMIT_EXCEEDED, + const char *target_iban; /** - * The user did not satisfy the (external) - * authentication check until the request timeout - * was reached. The client should try again later. + * Name of the business receiving the funds. */ - ANASTASIS_KSD_AUTHENTICATION_TIMEOUT, + const char *target_business_name; /** - * The plugin provided external challenge instructions - * that should be followed. They are method-specific. + * Wire transfer subject to use. */ - ANASTASIS_KSD_EXTERNAL_CHALLENGE_INSTRUCTIONS + const char *wire_transfer_subject; }; /** - * Detailed results from the successful download. + * Information returned for a POST /truth/$TID/challenge request. */ -struct ANASTASIS_KeyShareDownloadDetails +struct ANASTASIS_TruthChallengeDetails { + /** + * HTTP status returned by the server. + */ + unsigned int http_status; /** - * Operational status. + * Taler-specific error code, #TALER_EC_NONE on success. */ - enum ANASTASIS_KeyShareDownloadStatus status; + enum TALER_ErrorCode ec; /** - * Anastasis URL that returned the @e status. + * Full response in JSON, if provided. */ - const char *server_url; + const json_t *response; /** - * Details depending on @e status. + * Details depending on @e http_status. */ union { /** - * The encrypted key share (if @e status is #ANASTASIS_KSD_SUCCESS). - */ - struct ANASTASIS_CRYPTO_EncryptedKeyShareP eks; - - /** - * Response if the challenge still needs to be answered, and the - * instructions are provided inline (no redirection). + * Information for @e http_status of #MHD_HTTP_OK. */ struct { - - /** - * HTTP status returned by the server. #MHD_HTTP_ALREADY_REPORTED - * if the server did already send the challenge to the user, - * #MHD_HTTP_FORBIDDEN if the answer was wrong (or missing). - */ - unsigned int http_status; - - /** - * Response with server-side reply containing instructions for the user - */ - const char *body; - /** - * Content-type: mime type of @e body, NULL if server did not provide any. + * Meta-state about how the challenge was + * initiated and what is to be done next. */ - const char *content_type; + enum ANASTASIS_ChallengeDetailType cs; /** - * Number of bytes in @e body. + * Details depending on @e cs. */ - size_t body_size; - - } open_challenge; + union + { + + /** + * If @e cs is #ANASTASIS_CS_FILE_WRITTEN, this + * is the filename with the challenge code. + */ + const char *challenge_filename; + + /** + * If @e cs is #ANASTASIS_CS_TAN_SENT, this + * is human-readable information as to where + * the TAN was sent. + */ + const char *tan_address_hint; + + /** + * If @e cs is #ANASTASIS_CS_WIRE_FUNDS, this + * structure contains information about where + * to wire the funds to authenticate as well + * as a hint as to which bank account to send + * the funds from. + */ + struct ANASTASIS_WireFundsDetails wire_funds; + + } details; - /** - * URL with instructions for the user to satisfy the challenge, if - * @e status is #ANASTASIS_KSD_REDIRECT_FOR_AUTHENTICATION. - */ - const char *redirect_url; + } success; /** - * Response with instructions for how to pay, if - * @e status is #ANASTASIS_KSD_PAYMENT_REQUIRED. + * Information returne if @e http_status is #MHD_HTTP_PAYMENT_REQUIRED */ struct { - - /** - * "taler://pay" URL with details how to pay for the challenge. - */ - const char *taler_pay_uri; - /** - * The order ID from @e taler_pay_uri. + * A taler://pay/-URI with a request to pay the annual fee for + * the service. Returned if @e us is #ANASTASIS_US_PAYMENT_REQUIRED. */ - struct ANASTASIS_PaymentSecretP payment_secret; - - } payment_required; - - - /** - * Response with details about a server-side failure, if - * @e status is #ANASTASIS_KSD_SERVER_ERROR, - * #ANASTASIS_KSD_CLIENT_FAILURE or #ANASTASIS_KSD_TRUTH_UNKNOWN. - */ - struct - { + const char *payment_request; /** - * HTTP status returned by the server. + * The payment secret (aka order ID) extracted from the @e payment_request. */ - unsigned int http_status; + struct ANASTASIS_PaymentSecretP ps; /** - * Taler-specific error code. + * Data extracted from the payto:// URI. */ - enum TALER_ErrorCode ec; - - } server_failure; + const struct TALER_MERCHANT_PayUriData *pd; - /** - * External challenge instructions, if @e status is - * #ANASTASIS_KSD_EXTERNAL_CHALLENGE_INSTRUCTIONS. - */ - const json_t *external_challenge; + } payment_required; } details; + }; /** - * Handle for a GET /truth operation. + * Handle for a POST /truth/$TID/challenge operation. */ -struct ANASTASIS_KeyShareLookupOperation; +struct ANASTASIS_TruthChallengeOperation; /** - * Callback to process a GET /truth request + * Callback to process a POST /truth/$TID/challenge response. * * @param cls closure - * @param http_status HTTP status code for this request - * @param kdd details about the key share + * @param tcd details about the key share */ typedef void -(*ANASTASIS_KeyShareLookupCallback) ( +(*ANASTASIS_TruthChallengeCallback) ( void *cls, - const struct ANASTASIS_KeyShareDownloadDetails *kdd); + const struct ANASTASIS_TruthChallengeDetails *tcd); /** - * Does a GET /truth. + * Makes a POST /truth/$TID/challenge request. * * @param ctx execution context * @param backend_url base URL of the merchant backend * @param truth_uuid identification of the Truth * @param truth_key Key used to Decrypt the Truth on the Server * @param payment_secret secret from the previously done payment NULL to trigger payment - * @param timeout how long to wait for the payment, use - * #GNUNET_TIME_UNIT_ZERO to let the server pick - * @param hashed_answer hashed answer to the challenge * @param cb callback which will work the response gotten from the backend * @param cb_cls closure to pass to the callback * @return handle for this operation, NULL upon errors */ -struct ANASTASIS_KeyShareLookupOperation * -ANASTASIS_keyshare_lookup ( +struct ANASTASIS_TruthChallengeOperation * +ANASTASIS_truth_challenge ( struct GNUNET_CURL_Context *ctx, const char *backend_url, const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid, const struct ANASTASIS_CRYPTO_TruthKeyP *truth_key, const struct ANASTASIS_PaymentSecretP *payment_secret, - struct GNUNET_TIME_Relative timeout, - const struct GNUNET_HashCode *hashed_answer, - ANASTASIS_KeyShareLookupCallback cb, + ANASTASIS_TruthChallengeCallback cb, void *cb_cls); /** - * Cancel a GET /truth request. + * Cancel a POST /truth/$TID/challenge request. * - * @param kslo cancel the key share lookup operation + * @param[in] tco operation to cancel */ void -ANASTASIS_keyshare_lookup_cancel ( - struct ANASTASIS_KeyShareLookupOperation *kslo); +ANASTASIS_truth_challenge_cancel ( + struct ANASTASIS_TruthChallengeOperation *tco); /** - * Handle for a POST /truth operation. + * Information returned for a POST /truth/$TID/solve request. */ -struct ANASTASIS_TruthStoreOperation; +struct ANASTASIS_TruthSolveReply +{ + + /** + * HTTP status returned by the server. + */ + unsigned int http_status; + + /** + * Taler-specific error code, #TALER_EC_NONE on success. + */ + enum TALER_ErrorCode ec; + + /** + * Details depending on @e http_status. + */ + union + { + + /** + * Information returned if @e http_status is #MHD_HTTP_OK. + */ + struct + { + + /** + * The encrypted key share. + */ + struct ANASTASIS_CRYPTO_EncryptedKeyShareP eks; + + } success; + + /** + * Information returne if @e http_status is #MHD_HTTP_PAYMENT_REQUIRED + */ + struct + { + /** + * A taler://pay/-URI with a request to pay the annual fee for + * the service. Returned if @e us is #ANASTASIS_US_PAYMENT_REQUIRED. + */ + const char *payment_request; + + /** + * The payment secret (aka order ID) extracted from the @e payment_request. + */ + struct ANASTASIS_PaymentSecretP ps; + + /** + * Data extracted from the payto:// URI. + */ + const struct TALER_MERCHANT_PayUriData *pd; + + } payment_required; + + /** + * Information returne if @e http_status is #MHD_HTTP_TOO_MANY_REQUESTS. + */ + struct + { + + /** + * How many requests are allowed at most per @e request_frequency? + */ + uint32_t request_limit; + + /** + * Frequency at which requests are allowed / new challenges are + * created. + */ + struct GNUNET_TIME_Relative request_frequency; + } too_many_requests; + + } details; + +}; /** - * Callback to process a POST /truth request + * Handle for a POST /truth/$TID/solve operation. + */ +struct ANASTASIS_TruthSolveOperation; + + +/** + * Callback to process a POST /truth/$TID/solve response. * * @param cls closure - * @param obj the response body + * @param kdd details about the key share */ typedef void -(*ANASTASIS_TruthStoreCallback) (void *cls, - const struct ANASTASIS_UploadDetails *up); +(*ANASTASIS_TruthSolveCallback) ( + void *cls, + const struct ANASTASIS_TruthSolveReply *trs); /** - * Store Truth, does a POST /truth/$UUID + * Makes a POST /truth/$TID/solve request. * - * @param ctx the CURL context used to connect to the backend - * @param backend_url backend's base URL, including final "/" - * @param uuid unique identfication of the Truth Upload - * @param type type of the authorization method - * @param encrypted_keyshare key material to return to the client upon authorization - * @param truth_mime mime type of @e encrypted_truth (after decryption) - * @param encrypted_truth_size number of bytes in @e encrypted_truth - * @param encrypted_truth contains the @a type-specific authorization data - * @param payment_years_requested for how many years would the client like the service to store the truth? - * @param payment_timeout how long to wait for the payment, use + * @param ctx execution context + * @param backend_url base URL of the merchant backend + * @param truth_uuid identification of the Truth + * @param truth_key Key used to Decrypt the Truth on the Server + * @param payment_secret secret from the previously done payment NULL to trigger payment + * @param timeout how long to wait for the payment, use * #GNUNET_TIME_UNIT_ZERO to let the server pick - * @param cb callback processing the response from /truth - * @param cb_cls closure for cb - * @return handle for the operation + * @param hashed_answer hashed answer to the challenge + * @param cb callback which will work the response gotten from the backend + * @param cb_cls closure to pass to the callback + * @return handle for this operation, NULL upon errors */ -struct ANASTASIS_TruthStoreOperation * -ANASTASIS_truth_store ( +struct ANASTASIS_TruthSolveOperation * +ANASTASIS_truth_solve ( struct GNUNET_CURL_Context *ctx, const char *backend_url, - const struct ANASTASIS_CRYPTO_TruthUUIDP *uuid, - const char *type, - const struct ANASTASIS_CRYPTO_EncryptedKeyShareP *encrypted_keyshare, - const char *truth_mime, - size_t encrypted_truth_size, - const void *encrypted_truth, - uint32_t payment_years_requested, - struct GNUNET_TIME_Relative payment_timeout, - ANASTASIS_TruthStoreCallback cb, + const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid, + const struct ANASTASIS_CRYPTO_TruthKeyP *truth_key, + const struct ANASTASIS_PaymentSecretP *payment_secret, + struct GNUNET_TIME_Relative timeout, + const struct GNUNET_HashCode *hashed_answer, + ANASTASIS_TruthSolveCallback cb, void *cb_cls); /** - * Cancel a POST /truth request. + * Cancel a POST /truth/$TID/solve request. * - * @param tso the truth store operation + * @param[in] tso handle of the operation to cancel */ void -ANASTASIS_truth_store_cancel ( - struct ANASTASIS_TruthStoreOperation *tso); +ANASTASIS_truth_solve_cancel ( + struct ANASTASIS_TruthSolveOperation *tso); #endif /* _ANASTASIS_SERVICE_H */ diff --git a/src/include/anastasis_testing_lib.h b/src/include/anastasis_testing_lib.h index a6c1fba..62cde06 100644 --- a/src/include/anastasis_testing_lib.h +++ b/src/include/anastasis_testing_lib.h @@ -3,14 +3,14 @@ Copyright (C) 2020 Anastasis SARL Anastasis is free software; you can redistribute it and/or modify it under the - terms of the GNU Lesser General Public License as published by the Free Software + terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU Affero General Public License along with + You should have received a copy of the GNU General Public License along with Anastasis; see the file COPYING.GPL. If not, see <http://www.gnu.org/licenses/> */ /** @@ -32,231 +32,125 @@ #define ANASTASIS_FAIL() \ do {GNUNET_break (0); return NULL; } while (0) -/** - * Index used in #ANASTASIS_TESTING_get_trait_hash() for the current hash. - */ -#define ANASTASIS_TESTING_TRAIT_HASH_CURRENT 0 - -/** - * Obtain a hash from @a cmd. - * - * @param cmd command to extract the number from. - * @param index the number's index number, use #ANASTASIS_TESTING_TRAIT_HASH_CURRENT - * @param[out] h set to the hash coming from @a cmd. - * @return #GNUNET_OK on success. - */ -int -ANASTASIS_TESTING_get_trait_hash (const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct GNUNET_HashCode **h); - - -/** - * Offer a hash. - * - * @param index the number's index number. - * @param h the hash to offer. - * @return trait on success. - */ -struct TALER_TESTING_Trait -ANASTASIS_TESTING_make_trait_hash (unsigned int index, - const struct GNUNET_HashCode *h); - - -/** - * Obtain a truth decryption key from @a cmd. - * - * @param cmd command to extract the public key from. - * @param index usually 0 - * @param[out] key set to the account public key used in @a cmd. - * @return #GNUNET_OK on success. - */ -int -ANASTASIS_TESTING_get_trait_truth_key ( - const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct ANASTASIS_CRYPTO_TruthKeyP **key); - - -/** - * Offer an truth decryption key. - * - * @param index usually zero - * @param h the account_pub to offer. - * @return trait on success. - */ -struct TALER_TESTING_Trait -ANASTASIS_TESTING_make_trait_truth_key ( - unsigned int index, - const struct ANASTASIS_CRYPTO_TruthKeyP *h); - - -/** - * Obtain an account public key from @a cmd. - * - * @param cmd command to extract the public key from. - * @param index usually 0 - * @param[out] pub set to the account public key used in @a cmd. - * @return #GNUNET_OK on success. - */ -int -ANASTASIS_TESTING_get_trait_account_pub ( - const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct ANASTASIS_CRYPTO_AccountPublicKeyP **pub); - - -/** - * Offer an account public key. - * - * @param index usually zero - * @param h the account_pub to offer. - * @return trait on success - */ -struct TALER_TESTING_Trait -ANASTASIS_TESTING_make_trait_account_pub ( - unsigned int index, - const struct ANASTASIS_CRYPTO_AccountPublicKeyP *h); - - -/** - * Obtain an account private key from @a cmd. - * - * @param cmd command to extract the number from. - * @param index must be 0 - * @param[out] priv set to the account private key used in @a cmd. - * @return #GNUNET_OK on success. - */ -int -ANASTASIS_TESTING_get_trait_account_priv ( - const struct - TALER_TESTING_Command *cmd, - unsigned int index, - const struct ANASTASIS_CRYPTO_AccountPrivateKeyP **priv); - /** - * Offer an account private key. - * - * @param index usually zero - * @param priv the account_priv to offer. - * @return trait on success - */ -struct TALER_TESTING_Trait -ANASTASIS_TESTING_make_trait_account_priv ( - unsigned int index, - const struct - ANASTASIS_CRYPTO_AccountPrivateKeyP *priv); - -/** - * Obtain an account public key from @a cmd. - * - * @param cmd command to extract the payment identifier from. - * @param index the payment identifier's index number. - * @param[out] payment_secret set to the payment secret coming from @a cmd. - * @return #GNUNET_OK on success. - */ -int -ANASTASIS_TESTING_get_trait_payment_secret ( - const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct ANASTASIS_PaymentSecretP **payment_secret); - - -/** - * Offer a payment secret. - * - * @param index usually zero - * @param h the payment secret to offer. - * @return trait on success - */ -struct TALER_TESTING_Trait -ANASTASIS_TESTING_make_trait_payment_secret ( - unsigned int index, - const struct ANASTASIS_PaymentSecretP *h); + * Create headers for a trait with name @a name for + * statically allocated data of type @a type. + */ +#define ANASTASIS_TESTING_MAKE_DECL_SIMPLE_TRAIT(name,type) \ + enum GNUNET_GenericReturnValue \ + ANASTASIS_TESTING_get_trait_ ## name ( \ + const struct TALER_TESTING_Command *cmd, \ + type **ret); \ + struct TALER_TESTING_Trait \ + ANASTASIS_TESTING_make_trait_ ## name ( \ + type * value); + + +/** + * Create C implementation for a trait with name @a name for statically + * allocated data of type @a type. + */ +#define ANASTASIS_TESTING_MAKE_IMPL_SIMPLE_TRAIT(name,type) \ + enum GNUNET_GenericReturnValue \ + ANASTASIS_TESTING_get_trait_ ## name ( \ + const struct TALER_TESTING_Command *cmd, \ + type **ret) \ + { \ + if (NULL == cmd->traits) return GNUNET_SYSERR; \ + return cmd->traits (cmd->cls, \ + (const void **) ret, \ + TALER_S (name), \ + 0); \ + } \ + struct TALER_TESTING_Trait \ + ANASTASIS_TESTING_make_trait_ ## name ( \ + type * value) \ + { \ + struct TALER_TESTING_Trait ret = { \ + .trait_name = TALER_S (name), \ + .ptr = (const void *) value \ + }; \ + return ret; \ + } /** - * Obtain an truth UUID from @a cmd. - * - * @param cmd command to extract the number from. - * @param index the number's index number. - * @param[out] tpk set to the number coming from @a cmd. - * @return #GNUNET_OK on success. + * Create headers for a trait with name @a name for + * statically allocated data of type @a type. */ -int -ANASTASIS_TESTING_get_trait_truth_uuid ( - const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct ANASTASIS_CRYPTO_TruthUUIDP **tpk); +#define ANASTASIS_TESTING_MAKE_DECL_INDEXED_TRAIT(name,type) \ + enum GNUNET_GenericReturnValue \ + ANASTASIS_TESTING_get_trait_ ## name ( \ + const struct TALER_TESTING_Command *cmd, \ + unsigned int index, \ + type **ret); \ + struct TALER_TESTING_Trait \ + ANASTASIS_TESTING_make_trait_ ## name ( \ + unsigned int index, \ + type * value); /** - * Offer a truth UUID. - * - * @param index the number's index number. - * @param tpk the UUID to offer. - * @return trait on success + * Create C implementation for a trait with name @a name for statically + * allocated data of type @a type. */ -struct TALER_TESTING_Trait -ANASTASIS_TESTING_make_trait_truth_uuid ( - unsigned int index, - const struct ANASTASIS_CRYPTO_TruthUUIDP *tpk); +#define ANASTASIS_TESTING_MAKE_IMPL_INDEXED_TRAIT(name,type) \ + enum GNUNET_GenericReturnValue \ + ANASTASIS_TESTING_get_trait_ ## name ( \ + const struct TALER_TESTING_Command *cmd, \ + unsigned int index, \ + type **ret) \ + { \ + if (NULL == cmd->traits) return GNUNET_SYSERR; \ + return cmd->traits (cmd->cls, \ + (const void **) ret, \ + TALER_S (name), \ + index); \ + } \ + struct TALER_TESTING_Trait \ + ANASTASIS_TESTING_make_trait_ ## name ( \ + unsigned int index, \ + type * value) \ + { \ + struct TALER_TESTING_Trait ret = { \ + .index = index, \ + .trait_name = TALER_S (name), \ + .ptr = (const void *) value \ + }; \ + return ret; \ + } /** - * Obtain an encrypted key share from @a cmd. - * - * @param cmd command to extract the number from. - * @param index the number's index number. - * @param[out] eks set to the key share coming from @a cmd. - * @return #GNUNET_OK on success. - */ -int -ANASTASIS_TESTING_get_trait_eks ( - const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct ANASTASIS_CRYPTO_EncryptedKeyShareP **eks); - - -/** - * Offer an encrypted key share. - * - * @param index the number's index number. - * @param eks the encrypted key share to offer. - * @return trait on success - */ -struct TALER_TESTING_Trait -ANASTASIS_TESTING_make_trait_eks ( - unsigned int index, - const struct ANASTASIS_CRYPTO_EncryptedKeyShareP *eks); - - -/** - * Obtain a code from @a cmd. - * - * @param cmd command to extract the number from. - * @param index the number's index number. - * @param[out] code set to the number coming from @a cmd. - * @return #GNUNET_OK on success. - */ -int -ANASTASIS_TESTING_get_trait_code ( - const struct TALER_TESTING_Command *cmd, - unsigned int index, - const char **code); - - -/** - * Offer an authentication code. - * - * @param index the number's index number. - * @param code the code to offer. - * @return trait on success + * Call #op on all simple traits. */ -struct TALER_TESTING_Trait -ANASTASIS_TESTING_make_trait_code (unsigned int index, - const char *code); +#define ANASTASIS_TESTING_SIMPLE_TRAITS(op) \ + op (hash, const struct GNUNET_HashCode) \ + op (truth, const struct ANASTASIS_Truth *) \ + op (policy, const struct ANASTASIS_Policy *) \ + op (provider_salt, const struct ANASTASIS_CRYPTO_ProviderSaltP) \ + op (core_secret, const void) \ + op (truth_key, const struct ANASTASIS_CRYPTO_TruthKeyP) \ + op (account_pub, const struct ANASTASIS_CRYPTO_AccountPublicKeyP) \ + op (account_priv, const struct ANASTASIS_CRYPTO_AccountPrivateKeyP) \ + op (payment_secret, const struct ANASTASIS_PaymentSecretP) \ + op (truth_uuid, const struct ANASTASIS_CRYPTO_TruthUUIDP) \ + op (eks, const struct ANASTASIS_CRYPTO_EncryptedKeyShareP) \ + op (code, const char) \ + op (filename, const char) + + +/** + * Call #op on all indexed traits. + */ +#define ANASTASIS_TESTING_INDEXED_TRAITS(op) \ + op (challenges, const struct ANASTASIS_Challenge *) + + +ANASTASIS_TESTING_SIMPLE_TRAITS (ANASTASIS_TESTING_MAKE_DECL_SIMPLE_TRAIT) + +ANASTASIS_TESTING_INDEXED_TRAITS (ANASTASIS_TESTING_MAKE_DECL_INDEXED_TRAIT) /** @@ -480,7 +374,7 @@ ANASTASIS_TESTING_cmd_truth_question ( /** - * Make the "keyshare lookup" command. + * Make a "truth challenge" command. * * @param label command label * @param anastasis_url base URL of the ANASTASIS serving @@ -488,48 +382,41 @@ ANASTASIS_TESTING_cmd_truth_question ( * @param answer (response to challenge) * @param payment_ref reference to the payment request * @param upload_ref reference to upload command - * @param lookup_mode 0 for security question, 1 for - * code-based - * @param ksdd expected status + * @param http_status expected HTTP status * @return the command */ struct TALER_TESTING_Command -ANASTASIS_TESTING_cmd_keyshare_lookup ( +ANASTASIS_TESTING_cmd_truth_challenge ( const char *label, const char *anastasis_url, - const char *answer, const char *payment_ref, const char *upload_ref, - int lookup_mode, - enum ANASTASIS_KeyShareDownloadStatus ksdd); - - -/** - * Obtain a salt from @a cmd. - * - * @param cmd command to extract the salt from. - * @param index the salt's index number. - * @param[out] s set to the salt coming from @a cmd. - * @return #GNUNET_OK on success. - */ -int -ANASTASIS_TESTING_get_trait_salt ( - const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct ANASTASIS_CRYPTO_ProviderSaltP **s); + unsigned int http_status); /** - * Offer an salt. + * Make a "truth solve" command. * - * @param index the salt's index number. - * @param s the salt to offer. - * @return trait on success + * @param label command label + * @param anastasis_url base URL of the ANASTASIS serving + * the keyshare lookup request. + * @param answer (response to challenge) + * @param payment_ref reference to the payment request + * @param upload_ref reference to upload command + * @param lookup_mode 0 for security question, 1 for + * code-based + * @param http_status expected HTTP status + * @return the command */ -struct TALER_TESTING_Trait -ANASTASIS_TESTING_make_trait_salt ( - unsigned int index, - const struct ANASTASIS_CRYPTO_ProviderSaltP *s); +struct TALER_TESTING_Command +ANASTASIS_TESTING_cmd_truth_solve ( + const char *label, + const char *anastasis_url, + const char *answer, + const char *payment_ref, + const char *upload_ref, + int lookup_mode, + unsigned int http_status); /** @@ -549,31 +436,6 @@ ANASTASIS_TESTING_cmd_config (const char *label, /* ********************* test truth upload ********************* */ /** - * Obtain a truth from @a cmd. - * - * @param cmd command to extract the truth from. - * @param index the index of the truth - * @param[out] t set to the truth coming from @a cmd. - * @return #GNUNET_OK on success. - */ -int -ANASTASIS_TESTING_get_trait_truth (const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct ANASTASIS_Truth **t); - - -/** - * Offer a truth. - * - * @param index the truth's index number. - * @param t the truth to offer. - * @return trait on success - */ -struct TALER_TESTING_Trait -ANASTASIS_TESTING_make_trait_truth (unsigned int index, - const struct ANASTASIS_Truth *t); - -/** * Creates a sample of id_data. * * @param id_data some sample data (e.g. AHV, name, surname, ...) @@ -642,31 +504,6 @@ ANASTASIS_TESTING_cmd_truth_upload_question ( /* ********************* test policy create ********************* */ -/** - * Obtain a policy from @a cmd. - * - * @param cmd command to extract the policy from. - * @param index the index of the policy - * @param[out] p set to the policy coming from @a cmd. - * @return #GNUNET_OK on success. - */ -int -ANASTASIS_TESTING_get_trait_policy (const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct ANASTASIS_Policy **p); - - -/** - * Offer a policy. - * - * @param index the policy's index number. - * @param p the policy to offer. - * @return trait on success - */ -struct TALER_TESTING_Trait -ANASTASIS_TESTING_make_trait_policy (unsigned int index, - const struct ANASTASIS_Policy *p); - /** * Make the "policy create" command. @@ -682,31 +519,6 @@ ANASTASIS_TESTING_cmd_policy_create (const char *label, /* ********************* test secret share ********************* */ -/** - * Obtain the core secret from @a cmd. - * - * @param cmd command to extract the core secret from. - * @param index the index of the core secret (usually 0) - * @param[out] s set to the core secret coming from @a cmd. - * @return #GNUNET_OK on success. - */ -int -ANASTASIS_TESTING_get_trait_core_secret (const struct - TALER_TESTING_Command *cmd, - unsigned int index, - const void **s); - - -/** - * Offer the core secret. - * - * @param index the core secret's index number (usually 0). - * @param s the core secret to offer. - * @return trait on success - */ -struct TALER_TESTING_Trait -ANASTASIS_TESTING_make_trait_core_secret (unsigned int index, - const void *s); /** * Types of options for performing the secret sharing. Used as a bitmask. @@ -740,7 +552,7 @@ enum ANASTASIS_TESTING_SecretShareOption * @param id_data ID data to generate user identifier * @param core_secret core secret to backup/recover * @param core_secret_size size of @a core_secret - * @param http_status expected HTTP status. + * @param want_status expected status. * @param sso secret share options * @param ... NULL-terminated list of policy create commands * @return the command @@ -754,7 +566,7 @@ ANASTASIS_TESTING_cmd_secret_share ( const json_t *id_data, const void *core_secret, size_t core_secret_size, - unsigned int http_status, + enum ANASTASIS_ShareStatus want_status, enum ANASTASIS_TESTING_SecretShareOption sso, ...); @@ -824,30 +636,6 @@ ANASTASIS_TESTING_cmd_recover_secret_finish ( /* ********************* test challenge answer ********************* */ -/** - * Obtain a challenge from @a cmd. - * - * @param cmd command to extract the challenge from. - * @param index the index of the challenge - * @param[out] c set to the challenge coming from @a cmd. - * @return #GNUNET_OK on success. - */ -int -ANASTASIS_TESTING_get_trait_challenge (const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct ANASTASIS_Challenge **c); - -/** - * Offer a challenge. - * - * @param index the challenge index number. - * @param r the challenge to offer. - * @return trait on success - */ -struct TALER_TESTING_Trait -ANASTASIS_TESTING_make_trait_challenge (unsigned int index, - const struct ANASTASIS_Challenge *r); - /** * Create a "challenge start" command. Suitable for the "file" @@ -866,7 +654,7 @@ ANASTASIS_TESTING_cmd_challenge_start ( const char *payment_ref, const char *challenge_ref, unsigned int challenge_index, - enum ANASTASIS_ChallengeStatus expected_cs); + enum ANASTASIS_ChallengeStartStatus expected_cs); /** @@ -890,7 +678,7 @@ ANASTASIS_TESTING_cmd_challenge_answer ( unsigned int challenge_index, const char *answer, unsigned int mode, - enum ANASTASIS_ChallengeStatus expected_cs); + enum ANASTASIS_ChallengeAnswerStatus expected_cs); #endif diff --git a/src/include/anastasis_util_lib.h b/src/include/anastasis_util_lib.h index e780d82..602e1cc 100644 --- a/src/include/anastasis_util_lib.h +++ b/src/include/anastasis_util_lib.h @@ -3,14 +3,14 @@ Copyright (C) 2020 Anastasis SARL Anastasis is free software; you can redistribute it and/or modify it under the - terms of the GNU Lesser General Public License as published by the Free Software + terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU Affero General Public License along with + You should have received a copy of the GNU General Public License along with Anastasis; see the file COPYING.GPL. If not, see <http://www.gnu.org/licenses/> */ /** @@ -30,6 +30,17 @@ /** + * Maximum value allowed for PINs. Limited to 10^15 < 2^52 to ensure the + * numeric value survives a conversion to float by JavaScript. + * + * NOTE: Do not change this value, we map it to a string like + * 42353-256-6521-241 and that mapping fails if the number + * does not have exactly 15 digits! + */ +#define ANASTASIS_PIN_MAX_VALUE 1000000000000000 + + +/** * Return default project data used by Anastasis. */ const struct GNUNET_OS_ProjectData * @@ -86,4 +97,26 @@ void ANASTASIS_wait_child_cancel (struct ANASTASIS_ChildWaitHandle *cwh); +/** + * Convert input string @a as into @a pin. + * + * @param as input of the form 42355-256-2262-265 + * @param[out] pin set to numeric pin + * @return false if @as is malformed + */ +bool +ANASTASIS_scan_pin (const char *as, + unsigned long long *pin); + + +/** + * Convert numeric pin to human-readable number for display. + * + * @param pin number to convert + * @return static (!) buffer with the text to show + */ +const char * +ANASTASIS_pin2s (uint64_t pin); + + #endif diff --git a/src/include/gettext.h b/src/include/gettext.h index 705487b..3929b11 100644 --- a/src/include/gettext.h +++ b/src/include/gettext.h @@ -73,8 +73,8 @@ # undef ngettext # define ngettext(Msgid1, Msgid2, N) \ ((N) == 1 \ - ? ((void) (Msgid2), (const char *) (Msgid1)) \ - : ((void) (Msgid1), (const char *) (Msgid2))) + ? ((void) (Msgid2), (const char *) (Msgid1)) \ + : ((void) (Msgid1), (const char *) (Msgid2))) # undef dngettext # define dngettext(Domainname, Msgid1, Msgid2, N) \ ((void) (Domainname), ngettext (Msgid1, Msgid2, N)) diff --git a/src/include/platform.h b/src/include/platform.h index 7667460..0fd6672 100644 --- a/src/include/platform.h +++ b/src/include/platform.h @@ -26,10 +26,10 @@ /* Include our configuration header */ #ifndef HAVE_USED_CONFIG_H -# define HAVE_USED_CONFIG_H -# ifdef HAVE_CONFIG_H -# include "anastasis_config.h" -# endif +#define HAVE_USED_CONFIG_H +#ifdef HAVE_CONFIG_H +#include "anastasis_config.h" +#endif #endif @@ -69,8 +69,210 @@ /* Include the features available for GNU source */ #define _GNU_SOURCE -/* Include GNUnet's platform file */ -#include <gnunet/platform.h> + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + +#ifdef __clang__ +#undef HAVE_STATIC_ASSERT +#endif + +/** + * These may be expensive, but good for debugging... + */ +#define ALLOW_EXTRA_CHECKS GNUNET_YES + +/** + * For strptime (glibc2 needs this). + */ +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 499 +#endif + +#ifndef _REENTRANT +#define _REENTRANT +#endif + +/* configuration options */ + +#define VERBOSE_STATS 0 + +#include <netdb.h> +#include <sys/socket.h> +#include <sys/un.h> +#if HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#if HAVE_NETINET_IN_SYSTM_H +#include <netinet/in_systm.h> +#endif +#if HAVE_NETINET_IP_H +#include <netinet/ip.h> /* superset of previous */ +#endif +#include <arpa/inet.h> +#include <netinet/tcp.h> +#include <pwd.h> +#include <sys/ioctl.h> +#include <sys/wait.h> +#include <grp.h> + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdarg.h> +#include <stdbool.h> +#include <errno.h> +#include <signal.h> +#include <libgen.h> +#ifdef HAVE_MALLOC_H +#include <malloc.h> /* for mallinfo on GNU */ +#endif +#include <unistd.h> /* KLB_FIX */ +#include <sys/stat.h> +#include <sys/types.h> +#include <dirent.h> /* KLB_FIX */ +#include <fcntl.h> +#include <math.h> +#if HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif +#if HAVE_SYS_TIME_H +#include <sys/time.h> +#endif +#include <time.h> +#ifdef BSD +#include <net/if.h> +#endif +#if defined(BSD) && defined(__FreeBSD__) && defined(__FreeBSD_kernel__) +#include <semaphore.h> +#endif +#ifdef DARWIN +#include <dlfcn.h> +#include <semaphore.h> +#include <net/if.h> +#endif +#if defined(__linux__) || defined(GNU) +#include <net/if.h> +#endif +#ifdef SOLARIS +#include <sys/sockio.h> +#include <sys/filio.h> +#include <sys/loadavg.h> +#include <semaphore.h> +#endif +#if HAVE_UCRED_H +#include <ucred.h> +#endif +#if HAVE_SYS_UCRED_H +#include <sys/ucred.h> +#endif +#if HAVE_IFADDRS_H +#include <ifaddrs.h> +#endif +#include <errno.h> +#include <limits.h> + +#if HAVE_VFORK_H +#include <vfork.h> +#endif + +#include <ctype.h> +#if HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif + +#if HAVE_ENDIAN_H +#include <endian.h> +#endif +#if HAVE_SYS_ENDIAN_H +#include <sys/endian.h> +#endif + +#define DIR_SEPARATOR '/' +#define DIR_SEPARATOR_STR "/" +#define PATH_SEPARATOR ':' +#define PATH_SEPARATOR_STR ":" +#define NEWLINE "\n" + +#include <locale.h> +#include "gettext.h" +/** + * GNU gettext support macro. + */ +#define _(String) dgettext (PACKAGE, String) +#define LIBEXTRACTOR_GETTEXT_DOMAIN "libextractor" + +#include <sys/mman.h> + +/* FreeBSD_kernel is not defined on the now discontinued kFreeBSD */ +#if defined(BSD) && defined(__FreeBSD__) && defined(__FreeBSD_kernel__) +#define __BYTE_ORDER BYTE_ORDER +#define __BIG_ENDIAN BIG_ENDIAN +#endif + +#ifdef DARWIN +#define __BYTE_ORDER BYTE_ORDER +#define __BIG_ENDIAN BIG_ENDIAN +/* not available on darwin, override configure */ +#undef HAVE_STAT64 +#undef HAVE_MREMAP +#endif + +#if ! HAVE_ATOLL +long long +atoll (const char *nptr); + +#endif + +#if ENABLE_NLS +#include "langinfo.h" +#endif + +#ifndef SIZE_MAX +#define SIZE_MAX ((size_t) (-1)) +#endif + +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif + +/** + * AI_NUMERICSERV not defined in windows. Then we just do without. + */ +#ifndef AI_NUMERICSERV +#define AI_NUMERICSERV 0 +#endif + + +#if defined(__sparc__) +#define MAKE_UNALIGNED(val) ({ __typeof__((val)) __tmp; memmove (&__tmp, &(val), \ + sizeof((val))); \ + __tmp; }) +#else +#define MAKE_UNALIGNED(val) val +#endif + +/** + * The termination signal + */ +#define GNUNET_TERM_SIG SIGTERM + + +#ifndef PATH_MAX +/** + * Assumed maximum path length. + */ +#define PATH_MAX 4096 +#endif + +#if HAVE_THREAD_LOCAL_GCC +#define ANASTASIS_THREAD_LOCAL __thread +#else +#define ANASTASIS_THREAD_LOCAL +#endif + /* Do not use shortcuts for gcrypt mpi */ #define GCRYPT_NO_MPI_MACROS 1 |