diff options
author | Jakub Hrozek <jhrozek@redhat.com> | 2017-06-05 16:10:55 +0200 |
---|---|---|
committer | Lukas Slebodnik <lslebodn@redhat.com> | 2017-09-01 20:26:45 +0200 |
commit | 6b3bab516355fdf4cc81e6da9d87ec3818ab190f (patch) | |
tree | 8fb272ba1af45101d095bf36b20aab78d2c7f7c1 /src/responder | |
parent | 0558f270b3fbb0780e2a94602d455022b89f5381 (diff) | |
download | sssd-6b3bab516355fdf4cc81e6da9d87ec3818ab190f.tar.gz sssd-6b3bab516355fdf4cc81e6da9d87ec3818ab190f.tar.xz sssd-6b3bab516355fdf4cc81e6da9d87ec3818ab190f.zip |
SECRETS: Add a new option to control per-UID limits
Adds a new option max_uid_secrets that allows to set a limit of secrets
for this particular client so that the user cannot starve other users.
Resolves:
https://pagure.io/SSSD/sssd/issue/3363
Reviewed-by: Simo Sorce <simo@redhat.com>
Reviewed-by: Fabiano FidĂȘncio <fidencio@redhat.com>
Diffstat (limited to 'src/responder')
-rw-r--r-- | src/responder/secrets/local.c | 93 | ||||
-rw-r--r-- | src/responder/secrets/secsrv.c | 23 | ||||
-rw-r--r-- | src/responder/secrets/secsrv.h | 1 |
3 files changed, 116 insertions, 1 deletions
diff --git a/src/responder/secrets/local.c b/src/responder/secrets/local.c index 58e70f8b6..5e491ba98 100644 --- a/src/responder/secrets/local.c +++ b/src/responder/secrets/local.c @@ -412,6 +412,85 @@ static int local_db_check_containers_nest_level(struct local_db_req *lc_req, return EOK; } +static struct ldb_dn *per_uid_container(TALLOC_CTX *mem_ctx, + struct ldb_dn *req_dn) +{ + int user_comp; + int num_comp; + struct ldb_dn *uid_base_dn; + + uid_base_dn = ldb_dn_copy(mem_ctx, req_dn); + if (uid_base_dn == NULL) { + return NULL; + } + + /* Remove all the components up to the per-user base path which consists + * of three components: + * cn=<uidnumber>,cn=users,cn=secrets + */ + user_comp = ldb_dn_get_comp_num(uid_base_dn) - 3; + + if (!ldb_dn_remove_child_components(uid_base_dn, user_comp)) { + DEBUG(SSSDBG_OP_FAILURE, "Cannot remove child components\n"); + talloc_free(uid_base_dn); + return NULL; + } + + num_comp = ldb_dn_get_comp_num(uid_base_dn); + if (num_comp != 3) { + DEBUG(SSSDBG_OP_FAILURE, "Expected 3 components got %d\n", num_comp); + talloc_free(uid_base_dn); + return NULL; + } + + return uid_base_dn; +} + +static int local_db_check_peruid_number_of_secrets(TALLOC_CTX *mem_ctx, + struct local_context *lctx, + struct local_db_req *lc_req) +{ + TALLOC_CTX *tmp_ctx; + static const char *attrs[] = { NULL }; + struct ldb_result *res = NULL; + struct ldb_dn *cli_basedn = NULL; + int ret; + + tmp_ctx = talloc_new(mem_ctx); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + cli_basedn = per_uid_container(tmp_ctx, lc_req->req_dn); + if (cli_basedn == NULL) { + ret = ENOMEM; + goto done; + } + + ret = ldb_search(lctx->ldb, tmp_ctx, &res, cli_basedn, LDB_SCOPE_SUBTREE, + attrs, LOCAL_SIMPLE_FILTER); + if (ret != EOK) { + DEBUG(SSSDBG_TRACE_LIBS, + "ldb_search returned %d: %s\n", ret, ldb_strerror(ret)); + goto done; + } + + if (res->count >= lc_req->quota->max_uid_secrets) { + DEBUG(SSSDBG_OP_FAILURE, + "Cannot store any more secrets for this client (basedn %s) " + "as the maximum allowed limit (%d) has been reached\n", + ldb_dn_get_linearized(cli_basedn), + lc_req->quota->max_uid_secrets); + ret = ERR_SEC_INVALID_TOO_MANY_SECRETS; + goto done; + } + + ret = EOK; +done: + talloc_free(tmp_ctx); + return ret; +} + static int local_db_check_number_of_secrets(TALLOC_CTX *mem_ctx, struct local_context *lctx, struct local_db_req *lc_req) @@ -433,6 +512,12 @@ static int local_db_check_number_of_secrets(TALLOC_CTX *mem_ctx, ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_SUBTREE, attrs, LOCAL_SIMPLE_FILTER); + if (ret != EOK) { + DEBUG(SSSDBG_TRACE_LIBS, + "ldb_search returned %d: %s\n", ret, ldb_strerror(ret)); + goto done; + } + if (res->count >= lc_req->quota->max_secrets) { DEBUG(SSSDBG_OP_FAILURE, "Cannot store any more secrets as the maximum allowed limit (%d) " @@ -505,6 +590,14 @@ static int local_db_put_simple(TALLOC_CTX *mem_ctx, goto done; } + ret = local_db_check_peruid_number_of_secrets(msg, lctx, lc_req); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "local_db_check_number_of_secrets failed [%d]: %s\n", + ret, sss_strerror(ret)); + goto done; + } + ret = local_check_max_payload_size(lc_req, strlen(secret)); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, diff --git a/src/responder/secrets/secsrv.c b/src/responder/secrets/secsrv.c index 2fcdf8e6c..36b257c46 100644 --- a/src/responder/secrets/secsrv.c +++ b/src/responder/secrets/secsrv.c @@ -31,7 +31,8 @@ #define DEFAULT_SEC_FD_LIMIT 2048 #define DEFAULT_SEC_CONTAINERS_NEST_LEVEL 4 -#define DEFAULT_SEC_MAX_SECRETS 1024 +#define DEFAULT_SEC_MAX_SECRETS 1024 +#define DEFAULT_SEC_MAX_UID_SECRETS 256 #define DEFAULT_SEC_MAX_PAYLOAD_SIZE 16 /* The number of secrets in the /kcm hive should be quite small, @@ -39,12 +40,14 @@ * hive holds the whole ccache which consists of several credentials */ #define DEFAULT_SEC_KCM_MAX_SECRETS 256 +#define DEFAULT_SEC_KCM_MAX_UID_SECRETS 64 #define DEFAULT_SEC_KCM_MAX_PAYLOAD_SIZE 65536 static int sec_get_quota(struct sec_ctx *sctx, const char *section_config_path, int default_max_containers_nest_level, int default_max_num_secrets, + int default_max_num_uid_secrets, int default_max_payload, struct sec_quota *quota) { @@ -78,6 +81,19 @@ static int sec_get_quota(struct sec_ctx *sctx, ret = confdb_get_int(sctx->rctx->cdb, section_config_path, + CONFDB_SEC_MAX_UID_SECRETS, + default_max_num_uid_secrets, + "a->max_uid_secrets); + + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, + "Failed to get maximum number of per-UID entries for %s\n", + section_config_path); + return ret; + } + + ret = confdb_get_int(sctx->rctx->cdb, + section_config_path, CONFDB_SEC_MAX_PAYLOAD_SIZE, default_max_payload, "a->max_payload_size); @@ -97,6 +113,7 @@ static int sec_get_hive_config(struct sec_ctx *sctx, struct sec_hive_config *hive_config, int default_max_containers_nest_level, int default_max_num_secrets, + int default_max_num_uid_secrets, int default_max_payload) { int ret; @@ -119,6 +136,7 @@ static int sec_get_hive_config(struct sec_ctx *sctx, hive_config->confdb_section, default_max_containers_nest_level, default_max_num_secrets, + default_max_num_uid_secrets, default_max_payload, &hive_config->quota); if (ret != EOK) { @@ -158,6 +176,7 @@ static int sec_get_config(struct sec_ctx *sctx) sctx->rctx->confdb_service_path, DEFAULT_SEC_CONTAINERS_NEST_LEVEL, DEFAULT_SEC_MAX_SECRETS, + DEFAULT_SEC_MAX_UID_SECRETS, DEFAULT_SEC_MAX_PAYLOAD_SIZE, &sctx->sec_config.quota); if (ret != EOK) { @@ -172,6 +191,7 @@ static int sec_get_config(struct sec_ctx *sctx) &sctx->sec_config, sctx->sec_config.quota.containers_nest_level, sctx->sec_config.quota.max_secrets, + sctx->sec_config.quota.max_uid_secrets, sctx->sec_config.quota.max_payload_size); if (ret != EOK) { DEBUG(SSSDBG_FATAL_FAILURE, @@ -184,6 +204,7 @@ static int sec_get_config(struct sec_ctx *sctx) &sctx->kcm_config, DEFAULT_SEC_CONTAINERS_NEST_LEVEL, DEFAULT_SEC_KCM_MAX_SECRETS, + DEFAULT_SEC_KCM_MAX_UID_SECRETS, DEFAULT_SEC_KCM_MAX_PAYLOAD_SIZE); if (ret != EOK) { DEBUG(SSSDBG_FATAL_FAILURE, diff --git a/src/responder/secrets/secsrv.h b/src/responder/secrets/secsrv.h index afc092764..afdd731fb 100644 --- a/src/responder/secrets/secsrv.h +++ b/src/responder/secrets/secsrv.h @@ -32,6 +32,7 @@ struct sec_quota { int max_secrets; + int max_uid_secrets; int max_payload_size; int containers_nest_level; }; |