Blob Blame History Raw
From f024b5e46b62ad49f0099ed8db8155e7ea475639 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Wed, 28 Nov 2018 21:22:22 +0100
Subject: [PATCH 22/23] KCM: Configurable quotas for the secdb ccache back end
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Related:
https://pagure.io/SSSD/sssd/issue/3386

Exposes three new options for the [kcm] responder to set the global
ccache limit, the per-uid ccache limit and the payload size.

Reviewed-by: Michal Židek <mzidek@redhat.com>
---
 src/confdb/confdb.h                     |  3 ++
 src/config/cfg_rules.ini                |  3 ++
 src/man/sssd-kcm.8.xml                  | 37 +++++++++++++++
 src/responder/kcm/kcmsrv_ccache_secdb.c | 61 ++++++++++++++++++++++++-
 4 files changed, 103 insertions(+), 1 deletion(-)

diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index d09d6b4c3..727841659 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -266,6 +266,9 @@
 #define CONFDB_KCM_CONF_ENTRY "config/kcm"
 #define CONFDB_KCM_SOCKET "socket_path"
 #define CONFDB_KCM_DB "ccache_storage" /* Undocumented on purpose */
+#define CONFDB_KCM_MAX_CCACHES "max_ccaches"
+#define CONFDB_KCM_MAX_UID_CCACHES "max_uid_ccaches"
+#define CONFDB_KCM_MAX_CCACHE_SIZE "max_ccache_size"
 
 /* Certificate mapping rules */
 #define CONFDB_CERTMAP_BASEDN "cn=certmap,cn=config"
diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini
index 30040b595..59d6cc512 100644
--- a/src/config/cfg_rules.ini
+++ b/src/config/cfg_rules.ini
@@ -312,6 +312,9 @@ option = description
 option = socket_path
 option = ccache_storage
 option = responder_idle_timeout
+option = max_ccaches
+option = max_uid_ccaches
+option = max_ccache_size
 
 # Session recording
 [rule/allowed_session_recording_options]
diff --git a/src/man/sssd-kcm.8.xml b/src/man/sssd-kcm.8.xml
index 4e4aaa38e..2f66e56a4 100644
--- a/src/man/sssd-kcm.8.xml
+++ b/src/man/sssd-kcm.8.xml
@@ -201,6 +201,43 @@ systemctl restart sssd-kcm.service
                     </para>
                 </listitem>
             </varlistentry>
+            <varlistentry>
+                <term>max_ccaches (integer)</term>
+                <listitem>
+                    <para>
+                        How many credential caches does the KCM database allow
+                        for all users.
+                    </para>
+                    <para>
+                        Default: 0 (unlimited, only the per-UID quota is enforced)
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>max_uid_ccaches (integer)</term>
+                <listitem>
+                    <para>
+                        How many credential caches does the KCM database allow
+                        per UID. This is equivalent to <quote>with how many
+                        principals you can kinit</quote>.
+                    </para>
+                    <para>
+                        Default: 64
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>max_ccache_size (integer)</term>
+                <listitem>
+                    <para>
+                        How big can a credential cache be per ccache. Each
+                        service ticket accounts into this quota.
+                    </para>
+                    <para>
+                        Default: 65536
+                    </para>
+                </listitem>
+            </varlistentry>
         </variablelist>
     </refsect1>
 
diff --git a/src/responder/kcm/kcmsrv_ccache_secdb.c b/src/responder/kcm/kcmsrv_ccache_secdb.c
index d0d9a7e4c..dc9cefb32 100644
--- a/src/responder/kcm/kcmsrv_ccache_secdb.c
+++ b/src/responder/kcm/kcmsrv_ccache_secdb.c
@@ -526,13 +526,72 @@ static errno_t ccdb_secdb_init(struct kcm_ccdb *db,
 {
     struct ccdb_secdb *secdb = NULL;
     errno_t ret;
+    struct sss_sec_hive_config **kcm_section_quota;
+    struct sss_sec_quota_opt dfl_kcm_nest_level = {
+        .opt_name = CONFDB_SEC_CONTAINERS_NEST_LEVEL,
+        .default_value = DEFAULT_SEC_CONTAINERS_NEST_LEVEL,
+    };
+    struct sss_sec_quota_opt dfl_kcm_max_secrets = {
+        .opt_name = CONFDB_KCM_MAX_CCACHES,
+        .default_value = DEFAULT_SEC_KCM_MAX_SECRETS,
+    };
+    struct sss_sec_quota_opt dfl_kcm_max_uid_secrets = {
+        .opt_name = CONFDB_KCM_MAX_UID_CCACHES,
+        .default_value = DEFAULT_SEC_KCM_MAX_UID_SECRETS,
+    };
+    struct sss_sec_quota_opt dfl_kcm_max_payload_size = {
+        .opt_name = CONFDB_KCM_MAX_CCACHE_SIZE,
+        .default_value = DEFAULT_SEC_KCM_MAX_PAYLOAD_SIZE,
+    };
+
 
     secdb = talloc_zero(db, struct ccdb_secdb);
     if (secdb == NULL) {
         return ENOMEM;
     }
 
-    ret = sss_sec_init(db, NULL, &secdb->sctx);
+    kcm_section_quota = talloc_zero_array(secdb,
+                                          struct sss_sec_hive_config *,
+                                          2);
+    if (kcm_section_quota == NULL) {
+        talloc_free(secdb);
+        return ENOMEM;
+    }
+
+    kcm_section_quota[0] = talloc_zero(kcm_section_quota,
+                                       struct sss_sec_hive_config);
+    if (kcm_section_quota == NULL) {
+        talloc_free(secdb);
+        return ENOMEM;
+    }
+    kcm_section_quota[0]->hive_name = "kcm";
+
+    ret = sss_sec_get_quota(cdb,
+                            confdb_service_path,
+                            &dfl_kcm_nest_level,
+                            &dfl_kcm_max_secrets,
+                            &dfl_kcm_max_uid_secrets,
+                            &dfl_kcm_max_payload_size,
+                            &kcm_section_quota[0]->quota);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_FATAL_FAILURE,
+              "Failed to get KCM global quotas [%d]: %s\n",
+              ret, sss_strerror(ret));
+        talloc_free(secdb);
+        return ret;
+    }
+
+    if (kcm_section_quota[0]->quota.max_uid_secrets > 0) {
+        /* Even cn=default is considered a secret that adds up to
+         * the quota. To avoid off-by-one-confusion, increase
+         * the quota by two to 1) account for the cn=default object
+         * and 2) always allow writing to cn=defaults even if we
+         * are exactly at the quota limit
+         */
+        kcm_section_quota[0]->quota.max_uid_secrets += 2;
+    }
+
+    ret = sss_sec_init(db, kcm_section_quota, &secdb->sctx);
     if (ret != EOK) {
         DEBUG(SSSDBG_CRIT_FAILURE,
               "Cannot initialize the security database\n");
-- 
2.20.1