From efc65e78fa4e01e6cecc8690a9899af61213be62 Mon Sep 17 00:00:00 2001 From: Fabiano FidĂȘncio Date: Fri, 23 Sep 2016 15:23:23 +0200 Subject: SECRETS: Add a configurable depth limit for nested containers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves: https://fedorahosted.org/sssd/ticket/3168 Signed-off-by: Fabiano FidĂȘncio Reviewed-by: Jakub Hrozek --- src/confdb/confdb.h | 1 + src/config/SSSDConfig/__init__.py.in | 1 + src/config/cfg_rules.ini | 1 + src/config/etc/sssd.api.conf | 1 + src/man/sssd-secrets.5.xml | 12 ++++++++++++ src/responder/secrets/local.c | 26 ++++++++++++++++++++++++++ src/responder/secrets/providers.c | 1 + src/responder/secrets/secsrv.c | 13 +++++++++++++ src/responder/secrets/secsrv.h | 1 + src/tests/intg/test_secrets.py | 12 ++++++++++++ src/util/util_errors.c | 1 + src/util/util_errors.h | 1 + 12 files changed, 71 insertions(+) (limited to 'src') diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h index 36a2f21a0..dfbdbc7b9 100644 --- a/src/confdb/confdb.h +++ b/src/confdb/confdb.h @@ -223,6 +223,7 @@ /* Secrets Service */ #define CONFDB_SEC_CONF_ENTRY "config/secrets" +#define CONFDB_SEC_CONTAINERS_NEST_LEVEL "containers_nest_level" struct confdb_ctx; diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in index 15b9cd195..74c2ca5a7 100644 --- a/src/config/SSSDConfig/__init__.py.in +++ b/src/config/SSSDConfig/__init__.py.in @@ -120,6 +120,7 @@ option_strings = { # [secrets] 'provider': _('The provider where the secrets will be stored in'), + 'containers_nest_level': _('The maximum allowed number of nested containers'), # secrets - proxy 'proxy_url': _('The URL Custodia server is listening on'), 'auth_type': _('The method to use when authenticating to a Custodia server'), diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini index 4d9acf8da..e6f23ff34 100644 --- a/src/config/cfg_rules.ini +++ b/src/config/cfg_rules.ini @@ -228,6 +228,7 @@ option = description # Secrets service option = provider +option = containers_nest_level # Secrets service - proxy option = proxy_url option = auth_type diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf index f94c8d17f..a7757dc13 100644 --- a/src/config/etc/sssd.api.conf +++ b/src/config/etc/sssd.api.conf @@ -97,6 +97,7 @@ user_attributes = str, None, false [secrets] # Secrets service provider = str, None, false +containers_nest_level = int, None, false # Secrets service - proxy proxy_url = str, None, false auth_type = str, None, false diff --git a/src/man/sssd-secrets.5.xml b/src/man/sssd-secrets.5.xml index 71a79f5dd..1acaa987b 100644 --- a/src/man/sssd-secrets.5.xml +++ b/src/man/sssd-secrets.5.xml @@ -144,6 +144,18 @@ systemctl enable sssd-secrets.service + + containers_nest_level (integer) + + + This option specifies the maximum allowed number of nested + containers. + + + Default: 4 + + + The following options are only applicable for configurations that diff --git a/src/responder/secrets/local.c b/src/responder/secrets/local.c index 484e40643..ec8453798 100644 --- a/src/responder/secrets/local.c +++ b/src/responder/secrets/local.c @@ -29,6 +29,7 @@ struct local_context { struct ldb_context *ldb; struct sec_data master_key; + int containers_nest_level; }; static int local_decrypt(struct local_context *lctx, TALLOC_CTX *mem_ctx, @@ -332,6 +333,26 @@ done: return ret; } +static int local_db_check_containers_nest_level(struct local_context *lctx, + struct ldb_dn *leaf_dn) +{ + int nest_level; + + /* We need do not care for the synthetic containers that constitute the + * base path (cn=,cn=user,cn=secrets). */ + nest_level = ldb_dn_get_comp_num(leaf_dn) - 3; + if (nest_level > lctx->containers_nest_level) { + DEBUG(SSSDBG_OP_FAILURE, + "Cannot create a nested container of depth %d as the maximum" + "allowed number of nested containers is %d.\n", + nest_level, lctx->containers_nest_level); + + return ERR_SEC_INVALID_CONTAINERS_NEST_LEVEL; + } + + return EOK; +} + static int local_db_put_simple(TALLOC_CTX *mem_ctx, struct local_context *lctx, const char *req_path, @@ -447,6 +468,9 @@ static int local_db_create(TALLOC_CTX *mem_ctx, ret = local_db_check_containers(msg, lctx, msg->dn); if (ret != EOK) goto done; + ret = local_db_check_containers_nest_level(lctx, msg->dn); + if (ret != EOK) goto done; + ret = ldb_msg_add_string(msg, "type", "container"); if (ret != EOK) goto done; @@ -708,6 +732,8 @@ int local_secrets_provider_handle(struct sec_ctx *sctx, return EIO; } + lctx->containers_nest_level = sctx->containers_nest_level; + lctx->master_key.data = talloc_size(lctx, MKEY_SIZE); if (!lctx->master_key.data) return ENOMEM; lctx->master_key.length = MKEY_SIZE; diff --git a/src/responder/secrets/providers.c b/src/responder/secrets/providers.c index 4c6019886..aedb49a15 100644 --- a/src/responder/secrets/providers.c +++ b/src/responder/secrets/providers.c @@ -306,6 +306,7 @@ enum sec_http_status_codes sec_errno_to_http_status(errno_t err) case EISDIR: return STATUS_405; case EMEDIUMTYPE: + case ERR_SEC_INVALID_CONTAINERS_NEST_LEVEL: return STATUS_406; case EEXIST: return STATUS_409; diff --git a/src/responder/secrets/secsrv.c b/src/responder/secrets/secsrv.c index eb194a179..4bbc1dc90 100644 --- a/src/responder/secrets/secsrv.c +++ b/src/responder/secrets/secsrv.c @@ -29,6 +29,7 @@ #include "resolv/async_resolv.h" #define DEFAULT_SEC_FD_LIMIT 2048 +#define DEFAULT_SEC_CONTAINERS_NEST_LEVEL 4 static int sec_get_config(struct sec_ctx *sctx) { @@ -45,6 +46,18 @@ static int sec_get_config(struct sec_ctx *sctx) goto fail; } + ret = confdb_get_int(sctx->rctx->cdb, + sctx->rctx->confdb_service_path, + CONFDB_SEC_CONTAINERS_NEST_LEVEL, + DEFAULT_SEC_CONTAINERS_NEST_LEVEL, + &sctx->containers_nest_level); + + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, + "Failed to get containers' maximum depth\n"); + goto fail; + } + ret = confdb_get_int(sctx->rctx->cdb, sctx->rctx->confdb_service_path, CONFDB_RESPONDER_CLI_IDLE_TIMEOUT, CONFDB_RESPONDER_CLI_IDLE_DEFAULT_TIMEOUT, diff --git a/src/responder/secrets/secsrv.h b/src/responder/secrets/secsrv.h index ace30f86a..8ef89ab2e 100644 --- a/src/responder/secrets/secsrv.h +++ b/src/responder/secrets/secsrv.h @@ -38,6 +38,7 @@ struct sec_ctx { struct resolv_ctx *resctx; struct resp_ctx *rctx; int fd_limit; + int containers_nest_level; struct provider_handle **providers; }; diff --git a/src/tests/intg/test_secrets.py b/src/tests/intg/test_secrets.py index e394d1275..c77c2a470 100644 --- a/src/tests/intg/test_secrets.py +++ b/src/tests/intg/test_secrets.py @@ -160,3 +160,15 @@ def test_containers(setup_for_secrets, secrets_cli): # Try removing the secret first, then the container cli.del_secret("mycontainer/foo") cli.del_secret("mycontainer/") + + # Don't allow creating a container after reaching the max nested level + DEFAULT_CONTAINERS_NEST_LEVEL = 4 + container = "mycontainer" + for x in xrange(DEFAULT_CONTAINERS_NEST_LEVEL): + container += "%s/" % str(x) + cli.create_container(container) + + container += "%s/" % str(DEFAULT_CONTAINERS_NEST_LEVEL) + with pytest.raises(HTTPError) as err406: + cli.create_container(container) + assert str(err406.value).startswith("406") diff --git a/src/util/util_errors.c b/src/util/util_errors.c index 620be3c0a..7d4a7f559 100644 --- a/src/util/util_errors.c +++ b/src/util/util_errors.c @@ -98,6 +98,7 @@ struct err_string error_to_str[] = { { "Dereference threshold reached" }, /* ERR_DEREF_THRESHOLD */ { "The user is not handled by SSSD" }, /* ERR_NON_SSSD_USER */ { "The internal name format cannot be parsed" }, /* ERR_WRONG_NAME_FORMAT */ + { "The maximum level of nested containers has been reached" }, /* ERR_SEC_INVALID_CONTAINERS_NEST_LEVEL */ { "ERR_LAST" } /* ERR_LAST */ }; diff --git a/src/util/util_errors.h b/src/util/util_errors.h index 1f00ba348..2cd55e19a 100644 --- a/src/util/util_errors.h +++ b/src/util/util_errors.h @@ -120,6 +120,7 @@ enum sssd_errors { ERR_DEREF_THRESHOLD, ERR_NON_SSSD_USER, ERR_WRONG_NAME_FORMAT, + ERR_SEC_INVALID_CONTAINERS_NEST_LEVEL, ERR_LAST /* ALWAYS LAST */ }; -- cgit