diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/authorization/anastasis-authorization-sms.sh | 2 | ||||
-rw-r--r-- | src/authorization/anastasis_authorization_plugin_sms.c | 2 | ||||
-rw-r--r-- | src/authorization/libanastasiseufin/lae_credit.c | 2 | ||||
-rw-r--r-- | src/backend/Makefile.am | 1 | ||||
-rw-r--r-- | src/backend/anastasis-httpd_config.c | 113 | ||||
-rw-r--r-- | src/include/anastasis.h | 1 | ||||
-rw-r--r-- | src/lib/anastasis_recovery.c | 119 | ||||
-rw-r--r-- | src/reducer/anastasis_api_backup_redux.c | 127 | ||||
-rw-r--r-- | src/restclient/anastasis_api_config.c | 15 | ||||
-rw-r--r-- | src/stasis/drop.sql | 10 |
10 files changed, 294 insertions, 98 deletions
diff --git a/src/authorization/anastasis-authorization-sms.sh b/src/authorization/anastasis-authorization-sms.sh index 1e38661..c3b1055 100755 --- a/src/authorization/anastasis-authorization-sms.sh +++ b/src/authorization/anastasis-authorization-sms.sh @@ -20,8 +20,6 @@ STATUS=$(curl --request POST \ --data message_type=OTP \ --data "phone_number=$1" \ -w "%{http_code}" -s -o $TMPFILE) -echo `cat $TMPFILE` >> /var/log/sms.log -rm -f $TMPFILE case $STATUS in 200|203|250|290|291|295) exit 0; diff --git a/src/authorization/anastasis_authorization_plugin_sms.c b/src/authorization/anastasis_authorization_plugin_sms.c index 51457b6..695e5d8 100644 --- a/src/authorization/anastasis_authorization_plugin_sms.c +++ b/src/authorization/anastasis_authorization_plugin_sms.c @@ -375,7 +375,7 @@ sms_challenge (struct ANASTASIS_AUTHORIZATION_State *as, GNUNET_assert (NULL != pipe_stdin); GNUNET_DISK_pipe_close (p); GNUNET_asprintf (&as->msg, - "%s\nAnastasis\n: %s", + "%s\nAnastasis:\n%s", ANASTASIS_pin2s (as->code), ANASTASIS_CRYPTO_uuid2s (&as->truth_uuid)); { diff --git a/src/authorization/libanastasiseufin/lae_credit.c b/src/authorization/libanastasiseufin/lae_credit.c index d3fd781..dd6687b 100644 --- a/src/authorization/libanastasiseufin/lae_credit.c +++ b/src/authorization/libanastasiseufin/lae_credit.c @@ -82,7 +82,7 @@ parse_account_history (struct ANASTASIS_EUFIN_CreditHistoryHandle *hh, GNUNET_break_op (0); return GNUNET_SYSERR; } - for (unsigned int i = 0; i<json_array_size (history_array); i++) + for (size_t i = 0; i<json_array_size (history_array); i++) { struct ANASTASIS_EUFIN_CreditDetails td; uint64_t row_id; diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am index 10edef5..c1b0931 100644 --- a/src/backend/Makefile.am +++ b/src/backend/Makefile.am @@ -37,7 +37,6 @@ anastasis_httpd_LDADD = \ -ltalerjson \ -ltalerutil \ -lgnunetcurl \ - -lgnunetrest \ -lgnunetjson \ -lgnunetutil \ -lmicrohttpd \ diff --git a/src/backend/anastasis-httpd_config.c b/src/backend/anastasis-httpd_config.c index 677c5dc..315419e 100644 --- a/src/backend/anastasis-httpd_config.c +++ b/src/backend/anastasis-httpd_config.c @@ -1,6 +1,6 @@ /* This file is part of Anastasis - Copyright (C) 2020, 2021 Anastasis SARL + Copyright (C) 2020, 2021, 2024 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 @@ -78,48 +78,83 @@ MHD_RESULT AH_handler_config (struct AH_RequestHandler *rh, struct MHD_Connection *connection) { - json_t *method_arr = json_array (); + static struct MHD_Response *response; + static struct GNUNET_TIME_Absolute a; - GNUNET_assert (NULL != method_arr); + if ( (GNUNET_TIME_absolute_is_past (a)) && + (NULL != response) ) { - json_t *method; + MHD_destroy_response (response); + response = NULL; + } + if (NULL == response) + { + json_t *method_arr = json_array (); + struct GNUNET_TIME_Timestamp km; + char dat[128]; + + GNUNET_assert (NULL != method_arr); + a = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_DAYS); + /* Round up to next full day to ensure the expiration + time does not become a fingerprint! */ + a = GNUNET_TIME_absolute_round_down (a, + GNUNET_TIME_UNIT_DAYS); + a = GNUNET_TIME_absolute_add (a, + GNUNET_TIME_UNIT_DAYS); + /* => /config response stays at most 48h in caches! */ + km = GNUNET_TIME_absolute_to_timestamp (a); + TALER_MHD_get_date_string (km.abs_time, + dat); + { + json_t *method; + + method = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ("type", + "question"), + TALER_JSON_pack_amount ("cost", + &AH_question_cost)); + GNUNET_assert ( + 0 == + json_array_append_new (method_arr, + method)); + } + GNUNET_CONFIGURATION_iterate_sections (AH_cfg, + &add_methods, + method_arr); - method = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("type", - "question"), - TALER_JSON_pack_amount ("cost", - &AH_question_cost)); - GNUNET_assert ( - 0 == - json_array_append_new (method_arr, - method)); + response = TALER_MHD_MAKE_JSON_PACK ( + GNUNET_JSON_pack_string ("name", + "anastasis"), + GNUNET_JSON_pack_string ("version", + "0:2:0"), + GNUNET_JSON_pack_string ("implementation", + "urn:net:taler:specs:anastasis:c-reference"), + GNUNET_JSON_pack_string ("business_name", + AH_business_name), + GNUNET_JSON_pack_array_steal ("methods", + method_arr), + GNUNET_JSON_pack_uint64 ("storage_limit_in_megabytes", + AH_upload_limit_mb), + TALER_JSON_pack_amount ("annual_fee", + &AH_annual_fee), + TALER_JSON_pack_amount ("truth_upload_fee", + &AH_truth_upload_fee), + TALER_JSON_pack_amount ("liability_limit", + &AH_insurance), + GNUNET_JSON_pack_data_auto ("provider_salt", + &AH_provider_salt)); + GNUNET_break (MHD_YES == + MHD_add_response_header (response, + MHD_HTTP_HEADER_EXPIRES, + dat)); + GNUNET_break (MHD_YES == + MHD_add_response_header (response, + MHD_HTTP_HEADER_CACHE_CONTROL, + "public,max-age=21600")); /* 6h */ } - GNUNET_CONFIGURATION_iterate_sections (AH_cfg, - &add_methods, - method_arr); - return TALER_MHD_REPLY_JSON_PACK ( - connection, - MHD_HTTP_OK, - GNUNET_JSON_pack_string ("name", - "anastasis"), - GNUNET_JSON_pack_string ("version", - "0:1:0"), - GNUNET_JSON_pack_string ("implementation", - "urn:net:taler:specs:anastasis:c-reference"), - GNUNET_JSON_pack_string ("business_name", - AH_business_name), - GNUNET_JSON_pack_array_steal ("methods", - method_arr), - GNUNET_JSON_pack_uint64 ("storage_limit_in_megabytes", - AH_upload_limit_mb), - TALER_JSON_pack_amount ("annual_fee", - &AH_annual_fee), - TALER_JSON_pack_amount ("truth_upload_fee", - &AH_truth_upload_fee), - TALER_JSON_pack_amount ("liability_limit", - &AH_insurance), - GNUNET_JSON_pack_data_auto ("provider_salt", - &AH_provider_salt)); + return MHD_queue_response (connection, + MHD_HTTP_OK, + response); } diff --git a/src/include/anastasis.h b/src/include/anastasis.h index fd1275c..ea49ee7 100644 --- a/src/include/anastasis.h +++ b/src/include/anastasis.h @@ -1071,7 +1071,6 @@ struct ANASTASIS_ShareResult */ enum ANASTASIS_UploadStatus ec; - } provider_failure; } details; diff --git a/src/lib/anastasis_recovery.c b/src/lib/anastasis_recovery.c index f164c93..41f35a5 100644 --- a/src/lib/anastasis_recovery.c +++ b/src/lib/anastasis_recovery.c @@ -782,13 +782,11 @@ policy_lookup_cb (void *cls, json_dumpf (recovery_document, stderr, 0); - json_decref (recovery_document); r->csc (r->csc_cls, ANASTASIS_RS_POLICY_MALFORMED_JSON, NULL, 0); - ANASTASIS_recovery_abort (r); - return; + goto cleanup; } if (NULL != secret_name) { @@ -799,19 +797,37 @@ policy_lookup_cb (void *cls, } } + if ( (json_array_size (esc_methods) > UINT_MAX) || + (json_array_size (dec_policies) > UINT_MAX) ) + { + GNUNET_break_op (0); + r->csc (r->csc_cls, + ANASTASIS_RS_POLICY_DOWNLOAD_TOO_BIG, + NULL, + 0); + goto cleanup; + } + r->ri.version = dd->details.ok.version; - r->ri.cs_len = json_array_size (esc_methods); - r->ri.dps_len = json_array_size (dec_policies); - r->ri.dps = GNUNET_new_array (r->ri.dps_len, - struct ANASTASIS_DecryptionPolicy *); - r->dps = GNUNET_new_array (r->ri.dps_len, - struct DecryptionPolicy); - r->solved_challenges = GNUNET_new_array (r->ri.cs_len, - struct ANASTASIS_Challenge *); - r->ri.cs = GNUNET_new_array (r->ri.cs_len, - struct ANASTASIS_Challenge *); - r->cs = GNUNET_new_array (r->ri.cs_len, - struct ANASTASIS_Challenge); + r->ri.cs_len + = (unsigned int) json_array_size (esc_methods); + r->ri.dps_len + = (unsigned int) json_array_size (dec_policies); + r->ri.dps + = GNUNET_new_array (r->ri.dps_len, + struct ANASTASIS_DecryptionPolicy *); + r->dps + = GNUNET_new_array (r->ri.dps_len, + struct DecryptionPolicy); + r->solved_challenges + = GNUNET_new_array (r->ri.cs_len, + struct ANASTASIS_Challenge *); + r->ri.cs + = GNUNET_new_array (r->ri.cs_len, + struct ANASTASIS_Challenge *); + r->cs + = GNUNET_new_array (r->ri.cs_len, + struct ANASTASIS_Challenge); for (unsigned int i = 0; i < r->ri.cs_len; i++) { struct ANASTASIS_Challenge *cs = &r->cs[i]; @@ -849,9 +865,7 @@ policy_lookup_cb (void *cls, ANASTASIS_RS_POLICY_MALFORMED_JSON, NULL, 0); - ANASTASIS_recovery_abort (r); - json_decref (recovery_document); - return; + goto cleanup; } cs->url = GNUNET_strdup (url); cs->type = GNUNET_strdup (escrow_type); @@ -890,15 +904,23 @@ policy_lookup_cb (void *cls, ANASTASIS_RS_POLICY_MALFORMED_JSON, NULL, 0); - ANASTASIS_recovery_abort (r); - json_decref (recovery_document); - return; + goto cleanup; } GNUNET_assert (NULL != dp->emk); GNUNET_assert (dp->emk_size > 0); - dp->pub_details.challenges_length = json_array_size (uuids); + if (json_array_size (uuids) > UINT_MAX) + { + GNUNET_break_op (0); + r->csc (r->csc_cls, + ANASTASIS_RS_POLICY_MALFORMED_JSON, + NULL, + 0); + goto cleanup; + } + dp->pub_details.challenges_length + = (unsigned int) json_array_size (uuids); dp->pub_details.challenges = GNUNET_new_array (dp->pub_details.challenges_length, struct ANASTASIS_Challenge *); @@ -921,9 +943,7 @@ policy_lookup_cb (void *cls, ANASTASIS_RS_POLICY_MALFORMED_JSON, NULL, 0); - ANASTASIS_recovery_abort (r); - json_decref (recovery_document); - return; + goto cleanup; } for (unsigned int i = 0; i<r->ri.cs_len; i++) { @@ -942,15 +962,17 @@ policy_lookup_cb (void *cls, ANASTASIS_RS_POLICY_MALFORMED_JSON, NULL, 0); - ANASTASIS_recovery_abort (r); - json_decref (recovery_document); - return; + goto cleanup; } } } r->pc (r->pc_cls, &r->ri); json_decref (recovery_document); + return; +cleanup: + ANASTASIS_recovery_abort (r); + json_decref (recovery_document); } @@ -1126,16 +1148,23 @@ parse_cs_array (struct ANASTASIS_Recovery *r, const json_t *cs_arr) { json_t *cs; - unsigned int n_index; + size_t n_index; if (! json_is_array (cs_arr)) { GNUNET_break_op (0); return GNUNET_SYSERR; } - r->ri.cs_len = json_array_size (cs_arr); - r->solved_challenges = GNUNET_new_array (r->ri.cs_len, - struct ANASTASIS_Challenge *); + if (json_array_size (cs_arr) > UINT_MAX) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + r->ri.cs_len + = (unsigned int) json_array_size (cs_arr); + r->solved_challenges + = GNUNET_new_array (r->ri.cs_len, + struct ANASTASIS_Challenge *); r->ri.cs = GNUNET_new_array (r->ri.cs_len, struct ANASTASIS_Challenge *); r->cs = GNUNET_new_array (r->ri.cs_len, @@ -1212,14 +1241,20 @@ parse_dps_array (struct ANASTASIS_Recovery *r, const json_t *dps_arr) { json_t *dps; - unsigned int n_index; + size_t n_index; if (! json_is_array (dps_arr)) { GNUNET_break_op (0); return GNUNET_SYSERR; } - r->ri.dps_len = json_array_size (dps_arr); + if (json_array_size (dps_arr) > UINT_MAX) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + r->ri.dps_len + = (unsigned int) json_array_size (dps_arr); r->dps = GNUNET_new_array (r->ri.dps_len, struct DecryptionPolicy); r->ri.dps = GNUNET_new_array (r->ri.dps_len, @@ -1259,14 +1294,20 @@ parse_dps_array (struct ANASTASIS_Recovery *r, } GNUNET_assert (NULL != dp->emk); GNUNET_assert (dp->emk_size > 0); - dp->pub_details.challenges_length = json_array_size (challenges); - dp->pub_details.challenges = GNUNET_new_array ( - dp->pub_details.challenges_length, - struct ANASTASIS_Challenge *); + if (json_array_size (challenges) > UINT_MAX) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + dp->pub_details.challenges_length + = (unsigned int) json_array_size (challenges); + dp->pub_details.challenges + = GNUNET_new_array (dp->pub_details.challenges_length, + struct ANASTASIS_Challenge *); { json_t *challenge; - unsigned int c_index; + size_t c_index; json_array_foreach (challenges, c_index, challenge) { struct ANASTASIS_CRYPTO_TruthUUIDP uuid; diff --git a/src/reducer/anastasis_api_backup_redux.c b/src/reducer/anastasis_api_backup_redux.c index 13b1dd6..6ca6de7 100644 --- a/src/reducer/anastasis_api_backup_redux.c +++ b/src/reducer/anastasis_api_backup_redux.c @@ -32,7 +32,7 @@ * anastasis-httpd.h. */ #define ANASTASIS_FREE_STORAGE GNUNET_TIME_relative_multiply ( \ - GNUNET_TIME_UNIT_YEARS, 5) + GNUNET_TIME_UNIT_YEARS, 5) /** * CPU limiter: do not evaluate more than 16k @@ -1665,7 +1665,8 @@ done_authentication (json_t *state, pb.methods = json_object_get (state, "authentication_methods"); if ( (NULL == pb.methods) || - (! json_is_array (pb.methods)) ) + (! json_is_array (pb.methods)) || + (json_array_size (pb.methods) > UINT_MAX) ) { ANASTASIS_redux_fail_ (cb, cb_cls, @@ -1673,7 +1674,8 @@ done_authentication (json_t *state, "'authentication_methods' must be provided"); return NULL; } - pb.num_methods = json_array_size (pb.methods); + pb.num_methods + = (unsigned int) json_array_size (pb.methods); switch (pb.num_methods) { case 0: @@ -2953,6 +2955,62 @@ serialize_truth (struct UploadContext *uc) /** + * Test if the given @a provider_url is used by any of the + * authentication methods and thus the provider should be + * considered mandatory for storing the policy. + * + * @param state state to inspect + * @param provider_url provider to test + * @return false if the provider can be removed from policy + * upload considerations without causing a problem + */ +static bool +provider_required (const json_t *state, + const char *provider_url) +{ + json_t *policies + = json_object_get (state, + "policies"); + size_t pidx; + json_t *policy; + + json_array_foreach (policies, pidx, policy) + { + json_t *methods = json_object_get (policy, + "methods"); + size_t midx; + json_t *method; + + json_array_foreach (methods, midx, method) + { + const char *provider + = json_string_value (json_object_get (method, + "provider")); + + if (NULL == provider) + { + GNUNET_break (0); + continue; + } + if (0 == strcmp (provider, + provider_url)) + return true; + } + } + return false; +} + + +/** + * All truth uploads are done, begin with uploading the policy. + * + * @param[in,out] uc context for the operation + */ +static void +share_secret (struct UploadContext *uc); + + +/** * Function called with the results of a #ANASTASIS_secret_share(). * * @param cls closure with a `struct UploadContext *` @@ -3036,7 +3094,8 @@ secret_share_result_cb (void *cls, json_array_foreach (providers, off, provider) { const char *purl = json_string_value (json_object_get (provider, - "provider_url")); + "provider_url") + ); if (NULL == purl) { @@ -3077,6 +3136,45 @@ secret_share_result_cb (void *cls, { json_t *details; + if (! provider_required (uc->state, + sr->details.provider_failure.provider_url)) + { + /* try again without that provider */ + json_t *provider; + json_t *providers; + size_t idx; + + provider + = json_object_get ( + json_object_get (uc->state, + "authentication_providers"), + sr->details.provider_failure.provider_url); + GNUNET_break (0 == + json_object_set_new (provider, + "status", + json_string ("disabled"))); + providers + = json_object_get (uc->state, + "policy_providers"); + json_array_foreach (providers, idx, provider) + { + const char *url + = json_string_value (json_object_get (provider, + "provider_url")); + + if ( (NULL != url) && + (0 == strcmp (sr->details.provider_failure.provider_url, + url)) ) + { + GNUNET_break (0 == + json_array_remove (providers, + idx)); + break; + } + } + share_secret (uc); + return; + } details = GNUNET_JSON_PACK ( GNUNET_JSON_pack_uint64 ("http_status", sr->details.provider_failure.http_status), @@ -3194,7 +3292,18 @@ share_secret (struct UploadContext *uc) return; } - pds_len = json_array_size (providers); + if (json_array_size (providers) > UINT_MAX) + { + GNUNET_break_op (0); + ANASTASIS_redux_fail_ (uc->cb, + uc->cb_cls, + TALER_EC_ANASTASIS_REDUCER_STATE_INVALID, + "provider array excessively long"); + upload_cancel_cb (uc); + return; + } + pds_len + = (unsigned int) json_array_size (providers); if (0 == pds_len) { ANASTASIS_redux_fail_ (uc->cb, @@ -3223,17 +3332,19 @@ share_secret (struct UploadContext *uc) unsigned int methods_len; if ( (! json_is_array (jmethods)) || - (0 == json_array_size (jmethods)) ) + (0 == json_array_size (jmethods)) || + (json_array_size (jmethods) > UINT_MAX) ) { GNUNET_break (0); ANASTASIS_redux_fail_ (uc->cb, uc->cb_cls, TALER_EC_ANASTASIS_REDUCER_STATE_INVALID, - "'methods' must be an array"); + "'methods' must be an array of sane length"); upload_cancel_cb (uc); return; } - methods_len = json_array_size (jmethods); + methods_len + = (unsigned int) json_array_size (jmethods); { struct ANASTASIS_Policy *p; struct ANASTASIS_Truth *truths[methods_len]; diff --git a/src/restclient/anastasis_api_config.c b/src/restclient/anastasis_api_config.c index fff4774..aee0357 100644 --- a/src/restclient/anastasis_api_config.c +++ b/src/restclient/anastasis_api_config.c @@ -169,11 +169,18 @@ handle_config_finished (void *cls, acfg.ec = TALER_EC_GENERIC_VERSION_MALFORMED; break; } - acfg.details.ok.methods_length = json_array_size (methods); + acfg.details.ok.methods_length = (unsigned int) json_array_size (methods); + if (((size_t) acfg.details.ok.methods_length) != + json_array_size (methods)) { - struct ANASTASIS_AuthorizationMethodConfig mcfg[GNUNET_NZL ( - acfg.details.ok. - methods_length)]; + GNUNET_break_op (0); + acfg.http_status = 0; + acfg.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + break; + } + { + struct ANASTASIS_AuthorizationMethodConfig mcfg[ + GNUNET_NZL (acfg.details.ok.methods_length)]; for (unsigned int i = 0; i<acfg.details.ok.methods_length; i++) { diff --git a/src/stasis/drop.sql b/src/stasis/drop.sql index 67aa4a1..357fa9d 100644 --- a/src/stasis/drop.sql +++ b/src/stasis/drop.sql @@ -17,8 +17,14 @@ -- Everything in one big transaction BEGIN; --- Unregister patch (0001.sql) -SELECT _v.unregister_patch('stasis-0001'); +WITH xpatches AS ( + SELECT patch_name + FROM _v.patches + WHERE starts_with(patch_name,'stasis-') +) + SELECT _v.unregister_patch(xpatches.patch_name) + FROM xpatches; + DROP SCHEMA anastasis CASCADE; -- And we're out of here... |