URL: https://github.com/SSSD/sssd/pull/36
Author: fidencio
 Title: #36: Partial fix for #3169
Action: synchronized

To pull the PR as Git branch:
git remote add ghsssd https://github.com/SSSD/sssd
git fetch ghsssd pull/36/head:pr36
git checkout pr36
From 3595d4c8f2ae2439c35ffe9401e3ca5f5ff19fd3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fiden...@redhat.com>
Date: Fri, 30 Sep 2016 16:48:47 +0200
Subject: [PATCH] SECRETS: Add a configurable limit of secrets that can be
 stored

Related:
https://fedorahosted.org/sssd/ticket/3169
---
 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          | 46 ++++++++++++++++++++++++++++++++++
 src/responder/secrets/providers.c      |  4 +++
 src/responder/secrets/secsrv.c         | 13 ++++++++++
 src/responder/secrets/secsrv.h         |  1 +
 src/responder/secrets/secsrv_private.h |  1 +
 src/tests/intg/test_secrets.py         | 16 ++++++++++++
 src/util/util_errors.c                 |  1 +
 src/util/util_errors.h                 |  1 +
 13 files changed, 99 insertions(+)

diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index dfbdbc7..011792f 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -224,6 +224,7 @@
 /* Secrets Service */
 #define CONFDB_SEC_CONF_ENTRY "config/secrets"
 #define CONFDB_SEC_CONTAINERS_NEST_LEVEL "containers_nest_level"
+#define CONFDB_SEC_MAX_SECRETS "max_secrets"
 
 
 struct confdb_ctx;
diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in
index 74c2ca5..cde1964 100644
--- a/src/config/SSSDConfig/__init__.py.in
+++ b/src/config/SSSDConfig/__init__.py.in
@@ -121,6 +121,7 @@ option_strings = {
     # [secrets]
     'provider': _('The provider where the secrets will be stored in'),
     'containers_nest_level': _('The maximum allowed number of nested containers'),
+    'max_secrets': _('The maximum number of secrets that can be stored'),
     # 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 e6f23ff..b6316be 100644
--- a/src/config/cfg_rules.ini
+++ b/src/config/cfg_rules.ini
@@ -229,6 +229,7 @@ option = description
 # Secrets service
 option = provider
 option = containers_nest_level
+option = max_secrets
 # 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 a7757dc..567d52e 100644
--- a/src/config/etc/sssd.api.conf
+++ b/src/config/etc/sssd.api.conf
@@ -98,6 +98,7 @@ user_attributes = str, None, false
 # Secrets service
 provider = str, None, false
 containers_nest_level = int, None, false
+max_secrets = 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 1acaa98..7ec54c2 100644
--- a/src/man/sssd-secrets.5.xml
+++ b/src/man/sssd-secrets.5.xml
@@ -156,6 +156,18 @@ systemctl enable sssd-secrets.service
                 </para>
                 </listitem>
             </varlistentry>
+            <varlistentry>
+                <term>max_secrets (integer)</term>
+                <listitem>
+                <para>
+                    This option specifies the maximum number of secrets that
+                    can be stored.
+                </para>
+                <para>
+                    Default: 1024
+                </para>
+                </listitem>
+            </varlistentry>
         </variablelist>
         <para>
             The following options are only applicable for configurations that
diff --git a/src/responder/secrets/local.c b/src/responder/secrets/local.c
index 295001c..f6c936f 100644
--- a/src/responder/secrets/local.c
+++ b/src/responder/secrets/local.c
@@ -30,6 +30,7 @@ struct local_context {
     struct ldb_context *ldb;
     struct sec_data master_key;
     int containers_nest_level;
+    int max_secrets;
 };
 
 static int local_decrypt(struct local_context *lctx, TALLOC_CTX *mem_ctx,
@@ -413,6 +414,42 @@ static int local_db_check_containers_nest_level(struct local_context *lctx,
     return EOK;
 }
 
+static int local_db_check_number_of_secrets(TALLOC_CTX *mem_ctx,
+                                            struct local_context *lctx)
+{
+    TALLOC_CTX *tmp_ctx;
+    static const char *attrs[] = { NULL };
+    struct ldb_result *res = NULL;
+    struct ldb_dn *dn;
+    int ret;
+
+    tmp_ctx = talloc_new(mem_ctx);
+    if (!tmp_ctx) return ENOMEM;
+
+    dn = ldb_dn_new(tmp_ctx, lctx->ldb, "cn=secrets");
+    if (!dn) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_SUBTREE,
+                     attrs, LOCAL_SIMPLE_FILTER);
+    if (res->count >= lctx->max_secrets) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              "Cannot store any more secrets as the maximum allowed limit (%d) "
+              "has been reached\n", lctx->max_secrets);
+
+        ret = ERR_SEC_INVALID_TOO_MANY_SECRETS;
+        goto done;
+    }
+
+    ret = EOK;
+
+done:
+    talloc_free(tmp_ctx);
+    return ret;
+}
+
 static int local_db_put_simple(TALLOC_CTX *mem_ctx,
                                struct local_context *lctx,
                                const char *req_path,
@@ -447,6 +484,14 @@ static int local_db_put_simple(TALLOC_CTX *mem_ctx,
         goto done;
     }
 
+    ret = local_db_check_number_of_secrets(msg, lctx);
+    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_encrypt(lctx, msg, secret, enctype, &enc_secret);
     if (ret != EOK) {
         DEBUG(SSSDBG_OP_FAILURE,
@@ -927,6 +972,7 @@ int local_secrets_provider_handle(struct sec_ctx *sctx,
     }
 
     lctx->containers_nest_level = sctx->containers_nest_level;
+    lctx->max_secrets = sctx->max_secrets;
 
     lctx->master_key.data = talloc_size(lctx, MKEY_SIZE);
     if (!lctx->master_key.data) return ENOMEM;
diff --git a/src/responder/secrets/providers.c b/src/responder/secrets/providers.c
index 8cbc615..5f4b0fc 100644
--- a/src/responder/secrets/providers.c
+++ b/src/responder/secrets/providers.c
@@ -182,6 +182,8 @@ static struct sec_http_status_format_table {
       "The server encountered an internal error." },
     { 504, "Gateway timeout",
       "No response from a proxy server." },
+    { 507, "Insufficient Storage",
+      "The server is unable to store the resource needed to complete the request." },
 };
 
 int sec_http_status_reply(TALLOC_CTX *mem_ctx, struct sec_data *reply,
@@ -352,6 +354,8 @@ enum sec_http_status_codes sec_errno_to_http_status(errno_t err)
         return STATUS_409;
     case ERR_SEC_NO_PROXY:
         return STATUS_504;
+    case ERR_SEC_INVALID_TOO_MANY_SECRETS:
+        return STATUS_507;
     default:
         return STATUS_500;
     }
diff --git a/src/responder/secrets/secsrv.c b/src/responder/secrets/secsrv.c
index 4bbc1dc..4c0824b 100644
--- a/src/responder/secrets/secsrv.c
+++ b/src/responder/secrets/secsrv.c
@@ -30,6 +30,7 @@
 
 #define DEFAULT_SEC_FD_LIMIT 2048
 #define DEFAULT_SEC_CONTAINERS_NEST_LEVEL 4
+#define DEFAULT_SEC_MAX_SECRETS 1024
 
 static int sec_get_config(struct sec_ctx *sctx)
 {
@@ -58,6 +59,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_MAX_SECRETS,
+                         DEFAULT_SEC_MAX_SECRETS,
+                         &sctx->max_secrets);
+
+    if (ret != EOK) {
+        DEBUG(SSSDBG_FATAL_FAILURE,
+              "Failed to get maximum number of entries\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 8ef89ab..972d342 100644
--- a/src/responder/secrets/secsrv.h
+++ b/src/responder/secrets/secsrv.h
@@ -39,6 +39,7 @@ struct sec_ctx {
     struct resp_ctx *rctx;
     int fd_limit;
     int containers_nest_level;
+    int max_secrets;
 
     struct provider_handle **providers;
 };
diff --git a/src/responder/secrets/secsrv_private.h b/src/responder/secrets/secsrv_private.h
index ef7e299..4129fe6 100644
--- a/src/responder/secrets/secsrv_private.h
+++ b/src/responder/secrets/secsrv_private.h
@@ -48,6 +48,7 @@ enum sec_http_status_codes {
     STATUS_409,
     STATUS_500,
     STATUS_504,
+    STATUS_507,
 };
 
 struct sec_proto_ctx {
diff --git a/src/tests/intg/test_secrets.py b/src/tests/intg/test_secrets.py
index c77c2a4..b2beb5b 100644
--- a/src/tests/intg/test_secrets.py
+++ b/src/tests/intg/test_secrets.py
@@ -84,6 +84,9 @@ def setup_for_secrets(request):
 
         [domain/local]
         id_provider = local
+
+        [secrets]
+        max_secrets = 10
     """).format(**locals())
 
     create_conf_fixture(request, conf)
@@ -136,6 +139,19 @@ def test_crd_ops(setup_for_secrets, secrets_cli):
         cli.del_secret("foo")
     assert str(err404.value).startswith("404")
 
+    # Don't allow storing more secrets after reaching the max
+    # number of entries.
+    MAX_SECRETS = 10
+
+    sec_value = "value"
+    for x in xrange(MAX_SECRETS):
+        cli.set_secret(str(x), sec_value)
+
+    with pytest.raises(HTTPError) as err507:
+        cli.set_secret(str(MAX_SECRETS), sec_value)
+        print >>stderr,str(err507.value)
+    assert str(err507.value).startswith("507")
+
 
 def test_containers(setup_for_secrets, secrets_cli):
     """
diff --git a/src/util/util_errors.c b/src/util/util_errors.c
index 9cd562c..db5130c 100644
--- a/src/util/util_errors.c
+++ b/src/util/util_errors.c
@@ -100,6 +100,7 @@ struct err_string error_to_str[] = {
     { "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 */
     { "No proxy server for secrets available"}, /* ERR_SEC_NO_PROXY */
+    { "The maximum number of stored secrets has been reached" }, /* ERR_SEC_INVALID_TOO_MANY_SECRETS */
     { "ERR_LAST" } /* ERR_LAST */
 };
 
diff --git a/src/util/util_errors.h b/src/util/util_errors.h
index ebb9920..3690b7e 100644
--- a/src/util/util_errors.h
+++ b/src/util/util_errors.h
@@ -122,6 +122,7 @@ enum sssd_errors {
     ERR_WRONG_NAME_FORMAT,
     ERR_SEC_INVALID_CONTAINERS_NEST_LEVEL,
     ERR_SEC_NO_PROXY,
+    ERR_SEC_INVALID_TOO_MANY_SECRETS,
     ERR_LAST            /* ALWAYS LAST */
 };
 
_______________________________________________
sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org
To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org

Reply via email to