summaryrefslogtreecommitdiff
path: root/src/reducer/anastasis_api_backup_redux.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/reducer/anastasis_api_backup_redux.c')
-rw-r--r--src/reducer/anastasis_api_backup_redux.c658
1 files changed, 441 insertions, 217 deletions
diff --git a/src/reducer/anastasis_api_backup_redux.c b/src/reducer/anastasis_api_backup_redux.c
index cfef852..6ca6de7 100644
--- a/src/reducer/anastasis_api_backup_redux.c
+++ b/src/reducer/anastasis_api_backup_redux.c
@@ -1,16 +1,16 @@
/*
This file is part of Anastasis
- Copyright (C) 2020, 2021 Anastasis SARL
+ Copyright (C) 2020-2023 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,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
@@ -131,7 +131,7 @@ ANASTASIS_backup_state_from_string_ (const char *state_string)
if (0 == strcmp (state_string,
backup_strings[i]))
return i;
- return ANASTASIS_BACKUP_STATE_ERROR;
+ return ANASTASIS_BACKUP_STATE_INVALID;
}
@@ -177,11 +177,78 @@ json_t *
ANASTASIS_backup_start (const struct GNUNET_CONFIGURATION_Handle *cfg)
{
json_t *initial_state;
+ const char *external_reducer = ANASTASIS_REDUX_probe_external_reducer ();
+
+ if (NULL != external_reducer)
+ {
+ int pipefd_stdout[2];
+ pid_t pid = 0;
+ int status;
+ FILE *reducer_stdout;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Using external reducer '%s' for backup start status\n",
+ external_reducer);
+
+ GNUNET_assert (0 == pipe (pipefd_stdout));
+ pid = fork ();
+ if (pid == 0)
+ {
+ close (pipefd_stdout[0]);
+ dup2 (pipefd_stdout[1], STDOUT_FILENO);
+ execlp (external_reducer,
+ external_reducer,
+ "-b",
+ NULL);
+ GNUNET_assert (0);
+ }
+
+ close (pipefd_stdout[1]);
+ reducer_stdout = fdopen (pipefd_stdout[0],
+ "r");
+ {
+ json_error_t err;
+
+ initial_state = json_loadf (reducer_stdout,
+ 0,
+ &err);
+
+ if (NULL == initial_state)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "External reducer did not output valid JSON: %s:%d:%d %s\n",
+ err.source,
+ err.line,
+ err.column,
+ err.text);
+ GNUNET_assert (0 == fclose (reducer_stdout));
+ waitpid (pid, &status, 0);
+ return NULL;
+ }
+ }
+
+ GNUNET_assert (NULL != initial_state);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Waiting for external reducer to terminate.\n");
+ GNUNET_assert (0 == fclose (reducer_stdout));
+ reducer_stdout = NULL;
+ waitpid (pid, &status, 0);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "External reducer finished with exit status '%d'\n",
+ status);
+ return initial_state;
+ }
(void) cfg;
initial_state = ANASTASIS_REDUX_load_continents_ ();
if (NULL == initial_state)
return NULL;
+ GNUNET_assert (
+ 0 ==
+ json_object_set_new (initial_state,
+ "reducer_type",
+ json_string ("backup")));
set_state (initial_state,
ANASTASIS_BACKUP_STATE_CONTINENT_SELECTING);
return initial_state;
@@ -286,22 +353,30 @@ add_authentication (json_t *state,
json_object_foreach (auth_providers, url, details)
{
- json_t *methods;
+ const json_t *methods = NULL;
json_t *method;
size_t index;
- uint32_t size_limit_in_mb;
+ uint32_t size_limit_in_mb = 0;
+ const char *status;
+ uint32_t http_status = 0;
struct GNUNET_JSON_Specification ispec[] = {
- GNUNET_JSON_spec_uint32 ("storage_limit_in_megabytes",
- &size_limit_in_mb),
- GNUNET_JSON_spec_json ("methods",
- &methods),
+ GNUNET_JSON_spec_string ("status",
+ &status),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_uint32 ("storage_limit_in_megabytes",
+ &size_limit_in_mb),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_uint32 ("http_status",
+ &http_status),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_array_const ("methods",
+ &methods),
+ NULL),
GNUNET_JSON_spec_end ()
};
- if (MHD_HTTP_OK !=
- json_integer_value (json_object_get (details,
- "http_status")))
- continue; /* skip providers that are down */
if (GNUNET_OK !=
GNUNET_JSON_parse (details,
ispec,
@@ -310,6 +385,17 @@ add_authentication (json_t *state,
GNUNET_break (0);
continue;
}
+ if (0 != strcmp (status,
+ "ok"))
+ continue;
+ if (MHD_HTTP_OK != http_status)
+ continue; /* skip providers that are down */
+ if ( (NULL == methods) ||
+ (0 == size_limit_in_mb) )
+ {
+ GNUNET_break (0);
+ continue;
+ }
json_array_foreach (methods, index, method)
{
const char *type;
@@ -325,7 +411,6 @@ add_authentication (json_t *state,
break;
}
}
- GNUNET_JSON_parse_free (ispec);
if (! challenge_size_ok (size_limit_in_mb,
challenge_size))
{
@@ -681,17 +766,20 @@ free_costs (struct Costs *costs)
* Check if providers @a p1 and @a p2 have equivalent
* methods and cost structures.
*
+ * @param pb policy builder with list of providers
+ * @param p1 name of provider to compare
+ * @param p2 name of provider to compare
* @return true if the providers are fully equivalent
*/
static bool
-equiv_provider (struct PolicyBuilder *pb,
+equiv_provider (const struct PolicyBuilder *pb,
const char *p1,
const char *p2)
{
- json_t *j1;
- json_t *j2;
- json_t *m1;
- json_t *m2;
+ const json_t *j1;
+ const json_t *j2;
+ const json_t *m1;
+ const json_t *m2;
struct TALER_Amount uc1;
struct TALER_Amount uc2;
@@ -708,8 +796,8 @@ equiv_provider (struct PolicyBuilder *pb,
{
struct GNUNET_JSON_Specification s1[] = {
- GNUNET_JSON_spec_json ("methods",
- &m1),
+ GNUNET_JSON_spec_array_const ("methods",
+ &m1),
TALER_JSON_spec_amount_any ("truth_upload_fee",
&uc1),
GNUNET_JSON_spec_end ()
@@ -727,8 +815,8 @@ equiv_provider (struct PolicyBuilder *pb,
{
struct GNUNET_JSON_Specification s2[] = {
- GNUNET_JSON_spec_json ("methods",
- &m2),
+ GNUNET_JSON_spec_array_const ("methods",
+ &m2),
TALER_JSON_spec_amount_any ("truth_upload_fee",
&uc2),
GNUNET_JSON_spec_end ()
@@ -847,7 +935,7 @@ eval_provider_selection (struct PolicyBuilder *pb,
pb->m_idx[i]);
const json_t *provider_cfg = json_object_get (pb->providers,
prov_sel[i]);
- json_t *provider_methods;
+ const json_t *provider_methods;
const char *method_type;
json_t *md;
size_t index;
@@ -857,8 +945,8 @@ eval_provider_selection (struct PolicyBuilder *pb,
struct GNUNET_JSON_Specification pspec[] = {
GNUNET_JSON_spec_uint32 ("storage_limit_in_megabytes",
&size_limit_in_mb),
- GNUNET_JSON_spec_json ("methods",
- &provider_methods),
+ GNUNET_JSON_spec_array_const ("methods",
+ &provider_methods),
TALER_JSON_spec_amount_any ("truth_upload_fee",
&upload_cost),
GNUNET_JSON_spec_end ()
@@ -930,7 +1018,6 @@ eval_provider_selection (struct PolicyBuilder *pb,
GNUNET_break (0);
pb->ec = TALER_EC_ANASTASIS_REDUCER_STATE_INVALID;
pb->hint = "'methods' of provider";
- GNUNET_JSON_parse_free (pspec);
for (unsigned int i = 0; i<pb->req_methods; i++)
free_costs (policy_ent[i].usage_fee);
return;
@@ -952,14 +1039,12 @@ eval_provider_selection (struct PolicyBuilder *pb,
{
/* Provider does not OFFER this method, combination not possible.
Cost is basically 'infinite', but we simply then skip this. */
- GNUNET_JSON_parse_free (pspec);
GNUNET_JSON_parse_free (mspec);
for (unsigned int i = 0; i<pb->req_methods; i++)
free_costs (policy_ent[i].usage_fee);
return;
}
GNUNET_JSON_parse_free (mspec);
- GNUNET_JSON_parse_free (pspec);
}
/* calculate provider diversity by counting number of different
@@ -1082,6 +1167,34 @@ provider_candidate (struct PolicyBuilder *pb,
json_object_foreach (pb->providers, url, pconfig)
{
+ const char *status;
+ uint32_t http_status = 0;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_string ("status",
+ &status),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_uint32 ("http_status",
+ &http_status),
+ NULL),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (pconfig,
+ spec,
+ NULL, NULL))
+ {
+ GNUNET_break (0);
+ continue;
+ }
+ if ( (MHD_HTTP_OK != http_status) ||
+ (0 == strcmp (status,
+ "disabled")) )
+ {
+ GNUNET_JSON_parse_free (spec);
+ continue;
+ }
+ GNUNET_JSON_parse_free (spec);
prov_sel[i] = url;
if (i == pb->req_methods - 1)
{
@@ -1171,58 +1284,6 @@ method_candidate (struct PolicyBuilder *pb,
/**
- * 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
- */
-static int
-lookup_salt (const json_t *state,
- const char *provider_url,
- struct ANASTASIS_CRYPTO_ProviderSaltP *salt)
-{
- const json_t *aps;
- const json_t *cfg;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("salt",
- salt),
- GNUNET_JSON_spec_end ()
- };
-
- aps = json_object_get (state,
- "authentication_providers");
- if (NULL == aps)
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- cfg = json_object_get (aps,
- provider_url);
- if (NULL == cfg)
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- if (MHD_HTTP_OK !=
- json_integer_value (json_object_get (cfg,
- "http_status")))
- return GNUNET_NO; /* skip providers that are down */
- if (GNUNET_OK !=
- GNUNET_JSON_parse (cfg,
- spec,
- NULL, NULL))
- {
- /* provider not working */
- GNUNET_break_op (0);
- return GNUNET_NO;
- }
- return GNUNET_OK;
-}
-
-
-/**
* Compare two cost lists.
*
* @param my cost to compare
@@ -1604,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,
@@ -1612,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:
@@ -1622,6 +1685,11 @@ done_authentication (json_t *state,
"'authentication_methods' must not be empty");
return NULL;
case 1:
+ ANASTASIS_redux_fail_ (cb,
+ cb_cls,
+ TALER_EC_ANASTASIS_REDUCER_STATE_INVALID,
+ "Two factor authentication (2-FA) is required");
+ return NULL;
case 2:
pb.req_methods = pb.num_methods;
break;
@@ -1685,9 +1753,9 @@ done_authentication (json_t *state,
struct ANASTASIS_CRYPTO_ProviderSaltP salt;
if (GNUNET_OK !=
- lookup_salt (state,
- url,
- &salt))
+ ANASTASIS_reducer_lookup_salt (state,
+ url,
+ &salt))
continue; /* skip providers that are down */
provider = GNUNET_JSON_PACK (
GNUNET_JSON_pack_string ("provider_url",
@@ -1714,9 +1782,9 @@ done_authentication (json_t *state,
url_str = json_string_value (url);
if ( (NULL == url_str) ||
(GNUNET_OK !=
- lookup_salt (state,
- url_str,
- &salt)) )
+ ANASTASIS_reducer_lookup_salt (state,
+ url_str,
+ &salt)) )
{
GNUNET_break (0);
ANASTASIS_redux_fail_ (cb,
@@ -1877,8 +1945,8 @@ add_policy (json_t *state,
{
const char *provider_url;
uint32_t method_idx;
- json_t *prov_methods;
const char *method_type;
+ const json_t *prov_methods;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_string ("provider",
&provider_url),
@@ -1904,11 +1972,19 @@ add_policy (json_t *state,
{
const json_t *prov_cfg;
uint32_t limit;
+ const char *status;
+ uint32_t http_status = 0;
struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_string ("status",
+ &status),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_uint32 ("http_status",
+ &http_status),
+ NULL),
GNUNET_JSON_spec_uint32 ("storage_limit_in_megabytes",
&limit),
- GNUNET_JSON_spec_json ("methods",
- &prov_methods),
+ GNUNET_JSON_spec_array_const ("methods",
+ &prov_methods),
GNUNET_JSON_spec_end ()
};
@@ -1924,10 +2000,6 @@ add_policy (json_t *state,
"provider URL unknown");
return NULL;
}
- if (MHD_HTTP_OK !=
- json_integer_value (json_object_get (prov_cfg,
- "http_status")))
- continue;
if (GNUNET_OK !=
GNUNET_JSON_parse (prov_cfg,
spec,
@@ -1937,16 +2009,13 @@ add_policy (json_t *state,
json_decref (methods);
continue;
}
- if (! json_is_array (prov_methods))
+ if ( (MHD_HTTP_OK != http_status) ||
+ (0 != strcmp (status,
+ "ok")) )
{
- GNUNET_break (0);
+ /* skip provider, disabled or down */
json_decref (methods);
- json_decref (prov_methods);
- ANASTASIS_redux_fail_ (cb,
- cb_cls,
- TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
- "provider lacks authentication methods");
- return NULL;
+ continue;
}
}
@@ -1959,7 +2028,6 @@ add_policy (json_t *state,
{
GNUNET_break (0);
json_decref (methods);
- json_decref (prov_methods);
ANASTASIS_redux_fail_ (cb,
cb_cls,
TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
@@ -1972,7 +2040,6 @@ add_policy (json_t *state,
{
GNUNET_break (0);
json_decref (methods);
- json_decref (prov_methods);
ANASTASIS_redux_fail_ (cb,
cb_cls,
TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
@@ -2004,7 +2071,6 @@ add_policy (json_t *state,
{
GNUNET_break (0);
json_decref (methods);
- json_decref (prov_methods);
ANASTASIS_redux_fail_ (cb,
cb_cls,
TALER_EC_ANASTASIS_REDUCER_STATE_INVALID,
@@ -2021,7 +2087,6 @@ add_policy (json_t *state,
{
GNUNET_break (0);
json_decref (methods);
- json_decref (prov_methods);
ANASTASIS_redux_fail_ (cb,
cb_cls,
TALER_EC_ANASTASIS_REDUCER_STATE_INVALID,
@@ -2032,7 +2097,6 @@ add_policy (json_t *state,
GNUNET_assert (0 ==
json_array_append (methods,
method));
- json_decref (prov_methods);
} /* end of json_array_foreach (arg_array, index, method) */
}
@@ -2323,12 +2387,12 @@ del_challenge (json_t *state,
* @return number of years of service to pay for
*/
static unsigned int
-expiration_to_years (struct GNUNET_TIME_Absolute expiration)
+expiration_to_years (struct GNUNET_TIME_Timestamp expiration)
{
struct GNUNET_TIME_Relative rem;
unsigned int years;
- rem = GNUNET_TIME_absolute_get_remaining (expiration);
+ rem = GNUNET_TIME_absolute_get_remaining (expiration.abs_time);
years = rem.rel_value_us / GNUNET_TIME_UNIT_YEARS.rel_value_us;
if (0 != rem.rel_value_us % GNUNET_TIME_UNIT_YEARS.rel_value_us)
years++;
@@ -2348,7 +2412,7 @@ expiration_to_years (struct GNUNET_TIME_Absolute expiration)
*/
static enum GNUNET_GenericReturnValue
update_expiration_cost (json_t *state,
- struct GNUNET_TIME_Absolute expiration)
+ struct GNUNET_TIME_Timestamp expiration)
{
struct Costs *costs = NULL;
unsigned int years;
@@ -2373,26 +2437,33 @@ update_expiration_cost (json_t *state,
json_object_foreach (providers, url, provider)
{
struct TALER_Amount annual_fee;
+ const char *status;
+ uint32_t http_status = 0;
struct GNUNET_JSON_Specification pspec[] = {
+ GNUNET_JSON_spec_string ("status",
+ &status),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_uint32 ("http_status",
+ &http_status),
+ NULL),
TALER_JSON_spec_amount_any ("annual_fee",
&annual_fee),
GNUNET_JSON_spec_end ()
};
struct TALER_Amount fee;
- if (MHD_HTTP_OK !=
- json_integer_value (json_object_get (provider,
- "http_status")))
- continue; /* skip providers that are down */
if (GNUNET_OK !=
GNUNET_JSON_parse (provider,
pspec,
NULL, NULL))
{
- /* strange, skip as well */
- GNUNET_break_op (0);
+ /* likely down, skip */
continue;
}
+ if ( (MHD_HTTP_OK != http_status) ||
+ (0 != strcmp (status,
+ "ok")) )
+ continue; /* skip providers that are down or disabled */
if (0 >
TALER_amount_multiply (&fee,
&annual_fee,
@@ -2473,7 +2544,15 @@ update_expiration_cost (json_t *state,
off++;
{
struct TALER_Amount upload_cost;
+ const char *status;
+ uint32_t http_status = 0;
struct GNUNET_JSON_Specification pspec[] = {
+ GNUNET_JSON_spec_string ("status",
+ &status),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_uint32 ("http_status",
+ &http_status),
+ NULL),
TALER_JSON_spec_amount_any ("truth_upload_fee",
&upload_cost),
GNUNET_JSON_spec_end ()
@@ -2491,6 +2570,13 @@ update_expiration_cost (json_t *state,
GNUNET_break (0);
return GNUNET_SYSERR;
}
+ if ( (MHD_HTTP_OK != http_status) ||
+ (0 != strcmp (status,
+ "ok")) )
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
if (0 >
TALER_amount_multiply (&fee,
&upload_cost,
@@ -2519,8 +2605,7 @@ update_expiration_cost (json_t *state,
{
struct Costs *nxt = costs->next;
- if ( (0 != costs->cost.value) ||
- (0 != costs->cost.fraction) )
+ if (! TALER_amount_is_zero (&costs->cost))
{
json_t *ao;
@@ -2542,13 +2627,12 @@ update_expiration_cost (json_t *state,
}
if (is_free)
- expiration = GNUNET_TIME_relative_to_absolute (ANASTASIS_FREE_STORAGE);
+ expiration = GNUNET_TIME_relative_to_timestamp (ANASTASIS_FREE_STORAGE);
/* update 'expiration' in state */
{
json_t *eo;
- (void) GNUNET_TIME_round_abs (&expiration);
- eo = GNUNET_JSON_from_time_abs (expiration);
+ eo = GNUNET_JSON_from_timestamp (expiration);
GNUNET_assert (0 ==
json_object_set_new (state,
"expiration",
@@ -2589,11 +2673,13 @@ done_policy_review (json_t *state,
return NULL;
}
{
- struct GNUNET_TIME_Absolute exp = {0};
+ struct GNUNET_TIME_Timestamp exp
+ = GNUNET_TIME_UNIT_ZERO_TS;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_absolute_time ("expiration",
- &exp)),
+ GNUNET_JSON_spec_timestamp ("expiration",
+ &exp),
+ NULL),
GNUNET_JSON_spec_end ()
};
@@ -2608,8 +2694,8 @@ done_policy_review (json_t *state,
"invalid expiration specified");
return NULL;
}
- if (0 == exp.abs_value_us)
- exp = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_YEARS);
+ if (GNUNET_TIME_absolute_is_zero (exp.abs_time))
+ exp = GNUNET_TIME_relative_to_timestamp (GNUNET_TIME_UNIT_YEARS);
if (GNUNET_OK !=
update_expiration_cost (state,
exp))
@@ -2869,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 *`
@@ -2901,8 +3043,8 @@ secret_share_result_cb (void *cls,
d = GNUNET_JSON_PACK (
GNUNET_JSON_pack_uint64 ("policy_version",
pssi->policy_version),
- GNUNET_JSON_pack_time_abs ("policy_expiration",
- pssi->policy_expiration));
+ GNUNET_JSON_pack_timestamp ("policy_expiration",
+ pssi->policy_expiration));
GNUNET_assert (NULL != d);
GNUNET_assert (0 ==
json_object_set_new (sa,
@@ -2952,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)
{
@@ -2993,13 +3136,53 @@ 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_string ("backup_state",
- "ERROR"),
GNUNET_JSON_pack_uint64 ("http_status",
sr->details.provider_failure.http_status),
- GNUNET_JSON_pack_uint64 ("upload_status",
+ GNUNET_JSON_pack_uint64 ("code",
sr->details.provider_failure.ec),
+ GNUNET_JSON_pack_string ("hint",
+ TALER_ErrorCode_get_hint (
+ sr->details.provider_failure.ec)),
GNUNET_JSON_pack_string ("provider_url",
sr->details.provider_failure.provider_url));
uc->cb (uc->cb_cls,
@@ -3028,26 +3211,29 @@ secret_share_result_cb (void *cls,
static void
share_secret (struct UploadContext *uc)
{
- json_t *user_id;
- json_t *core_secret;
- json_t *jpolicies;
- json_t *providers = NULL;
+ const json_t *user_id;
+ const json_t *core_secret;
+ const json_t *jpolicies;
+ const json_t *providers = NULL;
size_t policies_len;
const char *secret_name = NULL;
unsigned int pds_len;
struct GNUNET_TIME_Relative timeout = GNUNET_TIME_UNIT_ZERO;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_json ("identity_attributes",
- &user_id),
- GNUNET_JSON_spec_json ("policies",
- &jpolicies),
- GNUNET_JSON_spec_json ("policy_providers",
- &providers),
- GNUNET_JSON_spec_json ("core_secret",
- &core_secret),
+ GNUNET_JSON_spec_object_const ("identity_attributes",
+ &user_id),
+ GNUNET_JSON_spec_array_const ("policies",
+ &jpolicies),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_array_const ("policy_providers",
+ &providers),
+ NULL),
+ GNUNET_JSON_spec_object_const ("core_secret",
+ &core_secret),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string ("secret_name",
- &secret_name)),
+ &secret_name),
+ NULL),
GNUNET_JSON_spec_end ()
};
@@ -3069,12 +3255,13 @@ share_secret (struct UploadContext *uc)
struct GNUNET_JSON_Specification pspec[] = {
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_relative_time ("timeout",
- &timeout)),
+ &timeout),
+ NULL),
GNUNET_JSON_spec_end ()
};
args = json_object_get (uc->state,
- "pay-arguments");
+ "pay_arguments");
if ( (NULL != args) &&
(GNUNET_OK !=
GNUNET_JSON_parse (args,
@@ -3094,40 +3281,43 @@ share_secret (struct UploadContext *uc)
}
}
- if ( (! json_is_object (user_id)) ||
- (! json_is_array (jpolicies)) ||
- (0 == json_array_size (jpolicies)) ||
- ( (NULL != providers) &&
- (! json_is_array (providers)) ) )
+ policies_len = json_array_size (jpolicies);
+ if (0 == policies_len)
{
ANASTASIS_redux_fail_ (uc->cb,
uc->cb_cls,
TALER_EC_ANASTASIS_REDUCER_STATE_INVALID,
"State parsing failed checks when preparing to share secret");
- GNUNET_JSON_parse_free (spec);
upload_cancel_cb (uc);
return;
}
- policies_len = json_array_size (jpolicies);
- 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,
uc->cb_cls,
TALER_EC_ANASTASIS_REDUCER_STATE_INVALID,
"no workable providers in state");
- GNUNET_JSON_parse_free (spec);
upload_cancel_cb (uc);
return;
}
-
{
struct ANASTASIS_Policy *vpolicies[policies_len];
const struct ANASTASIS_Policy *policies[policies_len];
- struct ANASTASIS_ProviderDetails pds[GNUNET_NZL (pds_len)];
+ struct ANASTASIS_ProviderDetails pds[pds_len];
/* initialize policies/vpolicies arrays */
memset (pds,
@@ -3142,18 +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");
- GNUNET_JSON_parse_free (spec);
+ "'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];
@@ -3163,13 +3354,14 @@ share_secret (struct UploadContext *uc)
{
const json_t *jmethod = json_array_get (jmethods,
j);
- json_t *jtruth = NULL;
+ const json_t *jtruth = NULL;
uint32_t truth_index;
const char *provider_url;
struct GNUNET_JSON_Specification ispec[] = {
GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_json ("truth",
- &jtruth)),
+ GNUNET_JSON_spec_object_const ("truth",
+ &jtruth),
+ NULL),
GNUNET_JSON_spec_string ("provider",
&provider_url),
GNUNET_JSON_spec_uint32 ("authentication_method",
@@ -3190,7 +3382,6 @@ share_secret (struct UploadContext *uc)
uc->cb_cls,
TALER_EC_ANASTASIS_REDUCER_STATE_INVALID,
"'truth' failed to decode");
- GNUNET_JSON_parse_free (spec);
upload_cancel_cb (uc);
return;
}
@@ -3207,8 +3398,6 @@ share_secret (struct UploadContext *uc)
uc->cb_cls,
TALER_EC_ANASTASIS_REDUCER_STATE_INVALID,
"'truth' failed to decode");
- GNUNET_JSON_parse_free (ispec);
- GNUNET_JSON_parse_free (spec);
upload_cancel_cb (uc);
return;
}
@@ -3246,13 +3435,10 @@ share_secret (struct UploadContext *uc)
uc->cb_cls,
TALER_EC_ANASTASIS_REDUCER_STATE_INVALID,
"'truth' failed to decode");
- GNUNET_JSON_parse_free (ispec);
- GNUNET_JSON_parse_free (spec);
upload_cancel_cb (uc);
return;
}
}
- GNUNET_JSON_parse_free (ispec);
ctruths[j] = truths[j];
}
p = ANASTASIS_policy_create (ctruths,
@@ -3272,7 +3458,8 @@ share_secret (struct UploadContext *uc)
struct GNUNET_JSON_Specification ispec[] = {
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_fixed_auto ("payment_secret",
- &pds[i].payment_secret)),
+ &pds[i].payment_secret),
+ NULL),
GNUNET_JSON_spec_string ("provider_url",
&pds[i].provider_url),
GNUNET_JSON_spec_end ()
@@ -3283,9 +3470,9 @@ share_secret (struct UploadContext *uc)
ispec,
NULL, NULL)) ||
(GNUNET_OK !=
- lookup_salt (uc->state,
- pds[i].provider_url,
- &pds[i].provider_salt)) )
+ ANASTASIS_reducer_lookup_salt (uc->state,
+ pds[i].provider_url,
+ &pds[i].provider_salt)) )
{
GNUNET_break (0);
ANASTASIS_redux_fail_ (uc->cb,
@@ -3295,7 +3482,6 @@ share_secret (struct UploadContext *uc)
for (unsigned int i = 0; i<policies_len; i++)
ANASTASIS_policy_destroy (vpolicies[i]);
upload_cancel_cb (uc);
- GNUNET_JSON_parse_free (spec);
return;
}
}
@@ -3326,7 +3512,6 @@ share_secret (struct UploadContext *uc)
for (unsigned int i = 0; i<policies_len; i++)
ANASTASIS_policy_destroy (vpolicies[i]);
}
- GNUNET_JSON_parse_free (spec);
if (NULL == uc->ss)
{
GNUNET_break (0);
@@ -3519,7 +3704,8 @@ add_truth_object (struct UploadContext *uc,
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_uint32 ("upload_status",
- &status)),
+ &status),
+ NULL),
GNUNET_JSON_spec_end ()
};
if (GNUNET_OK !=
@@ -3568,9 +3754,9 @@ add_truth_object (struct UploadContext *uc,
};
if (GNUNET_OK !=
- lookup_salt (uc->state,
- provider_url,
- &salt))
+ ANASTASIS_reducer_lookup_salt (uc->state,
+ provider_url,
+ &salt))
{
GNUNET_break (0);
return GNUNET_SYSERR;
@@ -3703,10 +3889,12 @@ check_truth_upload (struct UploadContext *uc,
&type),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string ("mime_type",
- &mime_type)),
+ &mime_type),
+ NULL),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string ("instructions",
- &instructions)),
+ &instructions),
+ NULL),
GNUNET_JSON_spec_varsize ("challenge",
&truth_data,
&truth_data_size),
@@ -3737,9 +3925,9 @@ check_truth_upload (struct UploadContext *uc,
tue->am_idx = am_idx;
tue->policies_length = 1;
if (GNUNET_OK !=
- lookup_salt (uc->state,
- provider_url,
- &provider_salt))
+ ANASTASIS_reducer_lookup_salt (uc->state,
+ provider_url,
+ &provider_salt))
{
GNUNET_break (0);
GNUNET_JSON_parse_free (spec);
@@ -3755,7 +3943,6 @@ check_truth_upload (struct UploadContext *uc,
struct ANASTASIS_CRYPTO_TruthKeyP truth_key;
struct ANASTASIS_CRYPTO_KeyShareP key_share;
struct ANASTASIS_CRYPTO_NonceP nonce;
-
struct GNUNET_JSON_Specification jspec[] = {
GNUNET_JSON_spec_fixed_auto ("salt",
&question_salt),
@@ -3841,10 +4028,10 @@ upload (json_t *state,
struct UploadContext *uc;
json_t *auth_methods;
json_t *policies;
- struct GNUNET_TIME_Absolute expiration;
+ struct GNUNET_TIME_Timestamp expiration;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_absolute_time ("expiration",
- &expiration),
+ GNUNET_JSON_spec_timestamp ("expiration",
+ &expiration),
GNUNET_JSON_spec_end ()
};
@@ -3895,12 +4082,13 @@ upload (json_t *state,
struct GNUNET_JSON_Specification pspec[] = {
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_relative_time ("timeout",
- &uc->timeout)),
+ &uc->timeout),
+ NULL),
GNUNET_JSON_spec_end ()
};
args = json_object_get (uc->state,
- "pay-arguments");
+ "pay_arguments");
if ( (NULL != args) &&
(GNUNET_OK !=
GNUNET_JSON_parse (args,
@@ -3954,7 +4142,8 @@ upload (json_t *state,
&am_idx),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_json ("truth",
- &truth)),
+ &truth),
+ NULL),
GNUNET_JSON_spec_end ()
};
@@ -4111,17 +4300,23 @@ check_upload_size_limit (json_t *state,
see #6760. */
json_object_foreach (aps, url, ap)
{
- uint32_t limit;
+ uint32_t limit = 0;
+ const char *status;
+ uint32_t http_status = 0;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_uint32 ("storage_limit_in_megabytes",
- &limit),
+ GNUNET_JSON_spec_string ("status",
+ &status),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_uint32 ("http_status",
+ &http_status),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_uint32 ("storage_limit_in_megabytes",
+ &limit),
+ NULL),
GNUNET_JSON_spec_end ()
};
- if (MHD_HTTP_OK !=
- json_integer_value (json_object_get (ap,
- "http_status")))
- continue; /* skip providers that are down */
if (GNUNET_OK !=
GNUNET_JSON_parse (ap,
spec,
@@ -4131,6 +4326,10 @@ check_upload_size_limit (json_t *state,
GNUNET_break_op (0);
continue;
}
+ if ( (MHD_HTTP_OK != http_status) ||
+ (0 != strcmp (status,
+ "ok")) )
+ continue;
if (0 == limit)
return GNUNET_SYSERR;
min_limit = GNUNET_MIN (min_limit,
@@ -4161,13 +4360,15 @@ enter_secret (json_t *state,
void *cb_cls)
{
json_t *jsecret;
- struct GNUNET_TIME_Absolute expiration = {0};
+ struct GNUNET_TIME_Timestamp expiration
+ = GNUNET_TIME_UNIT_ZERO_TS;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_json ("secret",
&jsecret),
GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_absolute_time ("expiration",
- &expiration)),
+ GNUNET_JSON_spec_timestamp ("expiration",
+ &expiration),
+ NULL),
GNUNET_JSON_spec_end ()
};
@@ -4215,7 +4416,7 @@ enter_secret (json_t *state,
break;
}
}
- if (0 != expiration.abs_value_us)
+ if (! GNUNET_TIME_absolute_is_zero (expiration.abs_time))
{
if (GNUNET_OK !=
update_expiration_cost (state,
@@ -4346,10 +4547,10 @@ update_expiration (json_t *state,
ANASTASIS_ActionCallback cb,
void *cb_cls)
{
- struct GNUNET_TIME_Absolute expiration;
+ struct GNUNET_TIME_Timestamp expiration;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_absolute_time ("expiration",
- &expiration),
+ GNUNET_JSON_spec_timestamp ("expiration",
+ &expiration),
GNUNET_JSON_spec_end ()
};
@@ -4483,7 +4684,7 @@ pay_truths_backup (json_t *state,
if (NULL != arguments)
GNUNET_assert (0 ==
json_object_set (state,
- "pay-arguments",
+ "pay_arguments",
(json_t *) arguments));
return upload (state,
cb,
@@ -4513,7 +4714,7 @@ pay_policies_backup (json_t *state,
if (NULL != arguments)
GNUNET_assert (0 ==
json_object_set (state,
- "pay-arguments",
+ "pay_arguments",
(json_t *) arguments));
return upload (state,
cb,
@@ -4596,6 +4797,11 @@ ANASTASIS_backup_action_ (json_t *state,
},
{
ANASTASIS_BACKUP_STATE_AUTHENTICATIONS_EDITING,
+ "poll_providers",
+ &ANASTASIS_REDUX_poll_providers_
+ },
+ {
+ ANASTASIS_BACKUP_STATE_AUTHENTICATIONS_EDITING,
"back",
&ANASTASIS_back_generic_decrement_
},
@@ -4674,7 +4880,7 @@ ANASTASIS_backup_action_ (json_t *state,
"back",
&back_finished
},
- { ANASTASIS_BACKUP_STATE_ERROR, NULL, NULL }
+ { ANASTASIS_BACKUP_STATE_INVALID, NULL, NULL }
};
const char *s = json_string_value (json_object_get (state,
"backup_state"));
@@ -4682,7 +4888,7 @@ ANASTASIS_backup_action_ (json_t *state,
GNUNET_assert (NULL != s); /* holds as per invariant of caller */
bs = ANASTASIS_backup_state_from_string_ (s);
- if (ANASTASIS_BACKUP_STATE_ERROR == bs)
+ if (ANASTASIS_BACKUP_STATE_INVALID == bs)
{
ANASTASIS_redux_fail_ (cb,
cb_cls,
@@ -4935,7 +5141,25 @@ ANASTASIS_REDUX_backup_begin_ (json_t *state,
json_object_foreach (provider_list, url, prov) {
struct BackupStartStateProviderEntry *pe;
json_t *istate;
+ const char *status;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_string ("status",
+ &status),
+ GNUNET_JSON_spec_end ()
+ };
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (prov,
+ spec,
+ NULL, NULL))
+ {
+ /* skip malformed provider entry */
+ GNUNET_break_op (0);
+ continue;
+ }
+ if (0 == strcmp (status,
+ "disabled"))
+ continue;
pe = GNUNET_new (struct BackupStartStateProviderEntry);
pe->bss = bss;
istate = json_object ();