summaryrefslogtreecommitdiffstats
path: root/src/responder
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2017-06-05 16:10:55 +0200
committerLukas Slebodnik <lslebodn@redhat.com>2017-09-01 20:26:45 +0200
commit6b3bab516355fdf4cc81e6da9d87ec3818ab190f (patch)
tree8fb272ba1af45101d095bf36b20aab78d2c7f7c1 /src/responder
parent0558f270b3fbb0780e2a94602d455022b89f5381 (diff)
downloadsssd-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.c93
-rw-r--r--src/responder/secrets/secsrv.c23
-rw-r--r--src/responder/secrets/secsrv.h1
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,
+ &quota->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,
&quota->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;
};