sssd/0093-SECRETS-Support-0-as-u...

252 lines
8.9 KiB
Diff

From 109ed7ca1a82420798efdc6a9b019675a5bd0f4f Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Wed, 7 Jun 2017 17:20:43 +0200
Subject: [PATCH 93/93] SECRETS: Support 0 as unlimited for the quotas
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add a special value for all the quota-like settings that means 'no
limit'.
Because the responder also had a global limit on the size of the
accepted body (64kiB), this patch also removes the hardcoded limit and
instead keep track of the biggest quota value on startup.
Reviewed-by: Simo Sorce <simo@redhat.com>
Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
---
src/man/sssd-secrets.5.xml | 3 +-
src/responder/secrets/local.c | 16 ++++++++++
src/responder/secrets/secsrv.c | 15 ++++++++++
src/responder/secrets/secsrv.h | 1 +
src/responder/secrets/secsrv_cmd.c | 6 +++-
src/responder/secrets/secsrv_private.h | 2 +-
src/tests/intg/test_secrets.py | 55 ++++++++++++++++++++++++++++++++++
7 files changed, 95 insertions(+), 3 deletions(-)
diff --git a/src/man/sssd-secrets.5.xml b/src/man/sssd-secrets.5.xml
index c74894c62ed70764ca680c3b1cfe7f903d280277..d43dcf21c6174f0e0780a76d831a1fd957358b51 100644
--- a/src/man/sssd-secrets.5.xml
+++ b/src/man/sssd-secrets.5.xml
@@ -173,7 +173,8 @@ systemctl enable sssd-secrets.service
</variablelist>
<para>
The following options affect only the secrets <quote>hive</quote>
- and therefore should be set in a per-hive subsection.
+ and therefore should be set in a per-hive subsection. Setting the
+ option to 0 means "unlimited".
</para>
<variablelist>
<varlistentry>
diff --git a/src/responder/secrets/local.c b/src/responder/secrets/local.c
index 5e491ba98fdc5612db0c303258513302c1f1d9e3..5a8b67731137dd2597211dedf817b8a92a62aa05 100644
--- a/src/responder/secrets/local.c
+++ b/src/responder/secrets/local.c
@@ -397,6 +397,10 @@ static int local_db_check_containers_nest_level(struct local_db_req *lc_req,
{
int nest_level;
+ if (lc_req->quota->containers_nest_level == 0) {
+ return EOK;
+ }
+
/* We need do not care for the synthetic containers that constitute the
* base path (cn=<uidnumber>,cn=user,cn=secrets). */
nest_level = ldb_dn_get_comp_num(leaf_dn) - 3;
@@ -456,6 +460,10 @@ static int local_db_check_peruid_number_of_secrets(TALLOC_CTX *mem_ctx,
struct ldb_dn *cli_basedn = NULL;
int ret;
+ if (lc_req->quota->max_uid_secrets == 0) {
+ return EOK;
+ }
+
tmp_ctx = talloc_new(mem_ctx);
if (tmp_ctx == NULL) {
return ENOMEM;
@@ -501,6 +509,10 @@ static int local_db_check_number_of_secrets(TALLOC_CTX *mem_ctx,
struct ldb_dn *dn;
int ret;
+ if (lc_req->quota->max_secrets == 0) {
+ return EOK;
+ }
+
tmp_ctx = talloc_new(mem_ctx);
if (!tmp_ctx) return ENOMEM;
@@ -538,6 +550,10 @@ static int local_check_max_payload_size(struct local_db_req *lc_req,
{
int max_payload_size;
+ if (lc_req->quota->max_payload_size == 0) {
+ return EOK;
+ }
+
max_payload_size = lc_req->quota->max_payload_size * 1024; /* kb */
if (payload_size > max_payload_size) {
DEBUG(SSSDBG_OP_FAILURE,
diff --git a/src/responder/secrets/secsrv.c b/src/responder/secrets/secsrv.c
index 36b257c463ccaa1f552b2b4985932dc0d3b125aa..2b661b165ef0c174557f53012b2dbaa236a6e359 100644
--- a/src/responder/secrets/secsrv.c
+++ b/src/responder/secrets/secsrv.c
@@ -146,6 +146,16 @@ static int sec_get_hive_config(struct sec_ctx *sctx,
goto done;
}
+ if (hive_config->quota.max_payload_size == 0
+ || (sctx->max_payload_size != 0
+ && hive_config->quota.max_payload_size > sctx->max_payload_size)) {
+ /* If the quota is unlimited or it's larger than what
+ * we already have, save the total limit so we know how much to
+ * accept from clients
+ */
+ sctx->max_payload_size = hive_config->quota.max_payload_size;
+ }
+
ret = EOK;
done:
@@ -168,6 +178,11 @@ static int sec_get_config(struct sec_ctx *sctx)
goto fail;
}
+ /* Set the global max_payload to ridiculously small value so that either 0 (unlimited)
+ * or any sensible value overwrite it
+ */
+ sctx->max_payload_size = 1;
+
/* Read the global quota first -- this should be removed in a future release */
/* Note that this sets the defaults for the sec_config quota to be used
* in sec_get_hive_config()
diff --git a/src/responder/secrets/secsrv.h b/src/responder/secrets/secsrv.h
index afdd731fbd44d7bb280ffc0e55db9c39a926bf22..3023116402f8540dcf4436dcc0b6ea030d892468 100644
--- a/src/responder/secrets/secsrv.h
+++ b/src/responder/secrets/secsrv.h
@@ -49,6 +49,7 @@ struct sec_ctx {
struct sec_hive_config sec_config;
struct sec_hive_config kcm_config;
+ int max_payload_size;
struct provider_handle **providers;
};
diff --git a/src/responder/secrets/secsrv_cmd.c b/src/responder/secrets/secsrv_cmd.c
index b88680c3d7c3105d160de5c78e6d981b852318b9..fa5970504d9f67c6341ebd8276da76f0b608fd55 100644
--- a/src/responder/secrets/secsrv_cmd.c
+++ b/src/responder/secrets/secsrv_cmd.c
@@ -178,7 +178,8 @@ static void sec_append_string(TALLOC_CTX *memctx, char **dest,
static bool sec_too_much_data(struct sec_req_ctx *req, size_t length)
{
req->total_size += length;
- if (req->total_size > SEC_REQUEST_MAX_SIZE) {
+ if (req->max_payload_size > 0
+ && req->total_size > req->max_payload_size) {
DEBUG(SSSDBG_FATAL_FAILURE,
"Request too big, aborting client!\n");
return true;
@@ -513,6 +514,8 @@ static void sec_recv(struct cli_ctx *cctx)
{
struct sec_proto_ctx *prctx;
struct sec_req_ctx *req;
+ struct sec_ctx *sec_ctx = talloc_get_type(cctx->rctx->pvt_ctx,
+ struct sec_ctx);
char buffer[SEC_PACKET_MAX_RECV_SIZE];
struct sec_data data = { buffer,
SEC_PACKET_MAX_RECV_SIZE };
@@ -531,6 +534,7 @@ static void sec_recv(struct cli_ctx *cctx)
return;
}
req->cctx = cctx;
+ req->max_payload_size = sec_ctx->max_payload_size;
cctx->state_ctx = req;
http_parser_init(&prctx->parser, HTTP_REQUEST);
prctx->parser.data = req;
diff --git a/src/responder/secrets/secsrv_private.h b/src/responder/secrets/secsrv_private.h
index 2e68628f61a0a8e79cd48fb5a510221e6fc36c70..c4a0c5745e8db092d28cf1ef9cb397af0c7314cb 100644
--- a/src/responder/secrets/secsrv_private.h
+++ b/src/responder/secrets/secsrv_private.h
@@ -75,6 +75,7 @@ struct sec_req_ctx {
bool complete;
size_t total_size;
+ size_t max_payload_size;
char *request_url;
char *mapped_path;
@@ -151,7 +152,6 @@ bool sec_req_has_header(struct sec_req_ctx *req,
const char *name, const char *value);
/* secsrv_cmd.c */
-#define SEC_REQUEST_MAX_SIZE 65536
#define SEC_PACKET_MAX_RECV_SIZE 8192
int sec_send_data(int fd, struct sec_data *data);
diff --git a/src/tests/intg/test_secrets.py b/src/tests/intg/test_secrets.py
index 957a0a8ff9ce5e966b77ddf048eefc282b2711b6..15caa69582ea6fe5031df8150343412f0e68bd5e 100644
--- a/src/tests/intg/test_secrets.py
+++ b/src/tests/intg/test_secrets.py
@@ -545,3 +545,58 @@ def test_per_uid_limit(setup_for_uid_limit, secrets_cli):
# FIXME - at this point, it would be nice to test that another UID can
# still store secrets, but sadly socket_wrapper doesn't allow us to fake
# UIDs yet
+
+
+@pytest.fixture
+def setup_for_unlimited_quotas(request):
+ conf = unindent("""\
+ [sssd]
+ domains = local
+ services = nss
+
+ [domain/local]
+ id_provider = local
+
+ [secrets]
+ debug_level = 10
+
+ [secrets/secrets]
+ max_secrets = 0
+ max_uid_secrets = 0
+ max_payload_size = 0
+ containers_nest_level = 0
+ """).format(**locals())
+
+ create_conf_fixture(request, conf)
+ create_sssd_secrets_fixture(request)
+ return None
+
+
+def test_unlimited_quotas(setup_for_unlimited_quotas, secrets_cli):
+ """
+ Test that setting quotas to zero disabled any checks and lets
+ store whatever.
+ """
+ cli = secrets_cli
+
+ # test much larger amount of secrets that we allow by default
+ sec_value = "value"
+ for i in range(2048):
+ cli.set_secret(str(i), sec_value)
+
+ # test a much larger secret size than the default one
+ KILOBYTE = 1024
+ payload_size = 32 * KILOBYTE
+
+ sec_value = "x" * payload_size
+ cli.set_secret("foo", sec_value)
+
+ fooval = cli.get_secret("foo")
+ assert fooval == sec_value
+
+ # test a deep secret nesting structure
+ DEFAULT_CONTAINERS_NEST_LEVEL = 128
+ container = "mycontainer"
+ for i in range(DEFAULT_CONTAINERS_NEST_LEVEL):
+ container += "%s/" % str(i)
+ cli.create_container(container)
--
2.14.1