[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-anastasis] branch master updated: implement #6810: upload size li
From: |
gnunet |
Subject: |
[taler-anastasis] branch master updated: implement #6810: upload size limit checks |
Date: |
Sat, 10 Apr 2021 15:03:18 +0200 |
This is an automated email from the git hooks/post-receive script.
grothoff pushed a commit to branch master
in repository anastasis.
The following commit(s) were added to refs/heads/master by this push:
new 40d9e2f implement #6810: upload size limit checks
40d9e2f is described below
commit 40d9e2f08b27dab7789a848cb8cdff3f1abf23b0
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Sat Apr 10 15:03:16 2021 +0200
implement #6810: upload size limit checks
---
contrib/gana | 2 +-
src/reducer/anastasis_api_backup_redux.c | 236 +++++++++++++++++++++++++++----
src/reducer/anastasis_api_redux.c | 36 +++--
3 files changed, 232 insertions(+), 42 deletions(-)
diff --git a/contrib/gana b/contrib/gana
index df4206c..fd5f8ca 160000
--- a/contrib/gana
+++ b/contrib/gana
@@ -1 +1 @@
-Subproject commit df4206c1dc3481faa2e15d497036632229ac9071
+Subproject commit fd5f8ca01e319278ecdf7ee29df4ee4176f1e4c6
diff --git a/src/reducer/anastasis_api_backup_redux.c
b/src/reducer/anastasis_api_backup_redux.c
index b8f98f5..d771cd4 100644
--- a/src/reducer/anastasis_api_backup_redux.c
+++ b/src/reducer/anastasis_api_backup_redux.c
@@ -100,6 +100,26 @@ ANASTASIS_backup_start (const struct
GNUNET_CONFIGURATION_Handle *cfg)
}
+/**
+ * Test if @a challenge_size is small enough for the provider's
+ * @a size_limit_in_mb.
+ *
+ * We add 1024 to @a challenge_size here as a "safety margin" as
+ * the encrypted challenge has some additional headers around it
+ *
+ * @param size_limit_in_mb provider's upload limit
+ * @param challenge_size actual binary size of the challenge
+ * @return true if this fits
+ */
+static bool
+challenge_size_ok (uint32_t size_limit_in_mb,
+ size_t challenge_size)
+{
+ return (size_limit_in_mb * 1024LLU * 1024LLU >=
+ challenge_size + 1024LLU);
+}
+
+
/**
* DispatchHandler/Callback function which is called for a
* "add_authentication" action.
@@ -120,6 +140,16 @@ add_authentication (json_t *state,
json_t *auth_providers;
json_t *method;
const char *method_type;
+ void *challenge;
+ size_t challenge_size;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_string ("type",
+ &method_type),
+ GNUNET_JSON_spec_varsize ("challenge",
+ &challenge,
+ &challenge_size),
+ GNUNET_JSON_spec_end ()
+ };
auth_providers = json_object_get (state,
"authentication_providers");
@@ -142,28 +172,21 @@ add_authentication (json_t *state,
"'authentication_method' required");
return NULL;
}
- method_type = json_string_value (json_object_get (method,
- "type"));
- if (NULL == method_type)
- {
- ANASTASIS_redux_fail_ (cb,
- cb_cls,
- TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
- "'type' field must be a valid string");
- return NULL;
- }
- if (! json_object_get (method,
- "challenge"))
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (method,
+ spec,
+ NULL, NULL))
{
ANASTASIS_redux_fail_ (cb,
cb_cls,
TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
- "'challenge' field missing from
'authentication_method'");
+ "'authentication_method' content malformed");
return NULL;
}
/* Check we know at least one provider that supports this method */
{
bool found = false;
+ bool too_big = false;
json_t *details;
const char *url;
@@ -172,10 +195,19 @@ add_authentication (json_t *state,
json_t *methods;
json_t *method;
size_t index;
+ uint32_t size_limit_in_mb;
+ 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_end ()
+ };
- methods = json_object_get (details,
- "methods");
- if (NULL == methods)
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (details,
+ ispec,
+ NULL, NULL))
{
GNUNET_break (0);
continue;
@@ -195,18 +227,40 @@ add_authentication (json_t *state,
break;
}
}
+ GNUNET_JSON_parse_free (ispec);
+ if (! challenge_size_ok (size_limit_in_mb,
+ challenge_size))
+ {
+ /* Challenge data too big for this provider. Try to find another one.
+ Note: we add 1024 to challenge-size here as a "safety margin" as
+ the encrypted challenge has some additional headers around it */
+ too_big = true;
+ found = false;
+ }
if (found)
break;
}
if (! found)
{
- ANASTASIS_redux_fail_ (cb,
- cb_cls,
-
TALER_EC_ANASTASIS_REDUCER_AUTHENTICATION_METHOD_NOT_SUPPORTED,
- method_type);
+ if (too_big)
+ {
+ ANASTASIS_redux_fail_ (cb,
+ cb_cls,
+
TALER_EC_ANASTASIS_REDUCER_CHALLENGE_DATA_TOO_BIG,
+ method_type);
+ }
+ else
+ {
+ ANASTASIS_redux_fail_ (cb,
+ cb_cls,
+
TALER_EC_ANASTASIS_REDUCER_AUTHENTICATION_METHOD_NOT_SUPPORTED,
+ method_type);
+ }
+ GNUNET_JSON_parse_free (spec);
return NULL;
}
}
+ GNUNET_JSON_parse_free (spec);
/* append provided method to our array */
{
@@ -393,20 +447,50 @@ eval_provider_selection (struct PolicyBuilder *pb,
{
const json_t *method_obj = json_array_get (pb->methods,
pb->m_idx[i]);
- const char *method_type = json_string_value (json_object_get (method_obj,
- "type"));
const json_t *provider_cfg = json_object_get (pb->providers,
prov_sel[i]);
- json_t *provider_methods = json_object_get (provider_cfg,
- "methods");
+ json_t *provider_methods;
+ const char *method_type;
json_t *md;
size_t index;
bool found = false;
+ uint32_t size_limit_in_mb;
+ 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_end ()
+ };
+ void *challenge;
+ size_t challenge_size;
+ struct GNUNET_JSON_Specification mspec[] = {
+ GNUNET_JSON_spec_string ("type",
+ &method_type),
+ GNUNET_JSON_spec_varsize ("challenge",
+ &challenge,
+ &challenge_size),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (method_obj,
+ mspec,
+ NULL, NULL))
+ {
+ pb->ec = TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID;
+ pb->hint = "'authentication_method' content malformed";
+ return;
+ }
- if (NULL == provider_methods)
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (provider_cfg,
+ pspec,
+ NULL, NULL))
{
pb->ec = TALER_EC_ANASTASIS_REDUCER_STATE_INVALID;
pb->hint = "'methods' of provider not found";
+ GNUNET_JSON_parse_free (mspec);
return;
}
json_array_foreach (provider_methods, index, md)
@@ -428,10 +512,13 @@ eval_provider_selection (struct PolicyBuilder *pb,
{
pb->ec = TALER_EC_ANASTASIS_REDUCER_STATE_INVALID;
pb->hint = "'methods' of provider";
+ GNUNET_JSON_parse_free (pspec);
return;
}
- if (0 == strcmp (type,
- method_type))
+ if ( (0 == strcmp (type,
+ method_type)) &&
+ (challenge_size_ok (size_limit_in_mb,
+ challenge_size) ) )
{
found = true;
}
@@ -440,8 +527,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);
return;
}
+ GNUNET_JSON_parse_free (mspec);
+ GNUNET_JSON_parse_free (pspec);
}
/* calculate provider diversity by counting number of different providers
selected */
@@ -2441,6 +2532,36 @@ upload (json_t *state,
}
+/**
+ * Test if the core secret @a secret_size is small enough to be stored
+ * at all providers, which have a minimum upload limit of @a min_limit_in_mb.
+ *
+ * For now, we do not precisely calculate the size of the recovery document,
+ * and simply assume that the instructions (i.e. security questions) are all
+ * relatively small (aka sane), and that the number of authentication methods
+ * and recovery policies is similarly small so that all of this meta data
+ * fits in 512 kb (which is VERY big).
+ *
+ * Even with the minimum permitted upload limit of 1 MB (which is likely,
+ * given that there is hardly a reason for providers to offer more), this
+ * leaves 512 kb for the @a secret_size, which should be plenty (given
+ * that this is supposed to be for a master key, and not the actual data).
+ *
+ * @param state our state, could be used in the future to calculate the
+ * size of the recovery document without the core secret
+ * @param secret_size size of the core secret
+ * @param min_limit_in_mb minimum upload size of all providers
+ */
+static bool
+core_secret_fits (const json_t *state,
+ size_t secret_size,
+ uint32_t min_limit_in_mb)
+{
+ return (min_limit_in_mb * 1024LL * 1024LL >
+ 512LLU * 1024LLU + secret_size);
+}
+
+
/**
* DispatchHandler/Callback function which is called for a
* "enter_secret" action.
@@ -2489,12 +2610,73 @@ enter_secret (json_t *state,
JSON_COMPACT | JSON_SORT_KEYS);
GNUNET_assert (NULL != secret);
secret_size = strlen (secret);
+
+ /* check upload size limit */
+ {
+ uint32_t min_limit = UINT32_MAX;
+ json_t *aps = json_object_get (state,
+ "authentication_providers");
+ const char *url;
+ json_t *ap;
+
+ /* We calculate the minimum upload limit of all possible providers;
+ this is under the (simplified) assumption that we store the
+ recovery document at all providers; this may be changed later,
+ see #6760. */
+ json_object_foreach (aps, url, ap)
+ {
+ uint32_t limit;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_uint32 ("storage_limit_in_megabytes",
+ &limit),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (ap,
+ spec,
+ NULL, NULL))
+ {
+ ANASTASIS_redux_fail_ (cb,
+ cb_cls,
+ TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
+ "'authentication_method' content malformed");
+ GNUNET_free (secret);
+ return NULL;
+ }
+ if (0 == limit)
+ {
+ ANASTASIS_redux_fail_ (cb,
+ cb_cls,
+ TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
+ "provider has an upload limit of 0");
+ GNUNET_free (secret);
+ return NULL;
+ }
+ min_limit = GNUNET_MIN (min_limit,
+ limit);
+ }
+ if (! core_secret_fits (state,
+ secret_size,
+ min_limit))
+ {
+ ANASTASIS_redux_fail_ (cb,
+ cb_cls,
+ TALER_EC_ANASTASIS_REDUCER_SECRET_TOO_BIG,
+ NULL);
+ GNUNET_free (secret);
+ return NULL;
+ }
+ }
+
+
GNUNET_assert (0 ==
json_object_set_new (state,
"core_secret",
GNUNET_JSON_from_data (secret,
secret_size)));
GNUNET_free (secret);
+
GNUNET_JSON_parse_free (spec);
return upload (state,
cb,
diff --git a/src/reducer/anastasis_api_redux.c
b/src/reducer/anastasis_api_redux.c
index 2c93ad9..14712d8 100644
--- a/src/reducer/anastasis_api_redux.c
+++ b/src/reducer/anastasis_api_redux.c
@@ -570,22 +570,30 @@ config_cb (void *cls,
}
else if (NULL != acfg)
{
- cr->currency = GNUNET_strdup (acfg->currency);
- cr->business_name = GNUNET_strdup (acfg->business_name);
- cr->methods = GNUNET_new_array (acfg->methods_length,
- struct AuthorizationMethodConfig);
- for (unsigned int i = 0; i<acfg->methods_length; i++)
+ if (0 == acfg->storage_limit_in_megabytes)
{
- cr->methods[i].type = GNUNET_strdup (acfg->methods[i].type);
- cr->methods[i].usage_fee = acfg->methods[i].usage_fee;
+ cr->http_status = 0;
+ cr->ec = TALER_EC_ANASTASIS_REDUCER_PROVIDER_INVALID_CONFIG;
+ }
+ else
+ {
+ cr->currency = GNUNET_strdup (acfg->currency);
+ cr->business_name = GNUNET_strdup (acfg->business_name);
+ cr->methods = GNUNET_new_array (acfg->methods_length,
+ struct AuthorizationMethodConfig);
+ for (unsigned int i = 0; i<acfg->methods_length; i++)
+ {
+ cr->methods[i].type = GNUNET_strdup (acfg->methods[i].type);
+ cr->methods[i].usage_fee = acfg->methods[i].usage_fee;
+ }
+ cr->methods_length = acfg->methods_length;
+ cr->storage_limit_in_megabytes = acfg->storage_limit_in_megabytes;
+ cr->annual_fee = acfg->annual_fee;
+ cr->truth_upload_fee = acfg->truth_upload_fee;
+ cr->truth_lifetime = acfg->truth_lifetime;
+ cr->liability_limit = acfg->liability_limit;
+ cr->salt = acfg->salt;
}
- cr->methods_length = acfg->methods_length;
- cr->storage_limit_in_megabytes = acfg->storage_limit_in_megabytes;
- cr->annual_fee = acfg->annual_fee;
- cr->truth_upload_fee = acfg->truth_upload_fee;
- cr->truth_lifetime = acfg->truth_lifetime;
- cr->liability_limit = acfg->liability_limit;
- cr->salt = acfg->salt;
}
notify_waiting (cr);
}
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [taler-anastasis] branch master updated: implement #6810: upload size limit checks,
gnunet <=