URL: https://github.com/SSSD/sssd/pull/5590
Author: sumit-bose
 Title: #5590: nss: prefer homedir overrides over override_homedir option
Action: synchronized

To pull the PR as Git branch:
git remote add ghsssd https://github.com/SSSD/sssd
git fetch ghsssd pull/5590/head:pr5590
git checkout pr5590
From 27047a71c4424e7cef8819c7d30585b2b00b6a89 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Fri, 12 Feb 2021 13:58:07 +0100
Subject: [PATCH] nss: prefer homedir overrides over override_homedir option

Currently the override_homedir option will overwrite every home
directory even if a dedicated user override exists. With this patch a
home directory from a dedicated override will be preferred.

Resolves: https://github.com/SSSD/sssd/issues/5589

:relnote: A home directory from a dedicated user override, either local
    or centrally managed by IPA, will have a higher precedence than the
    override_homedir option.
---
 src/db/sysdb.h                             |  6 ++
 src/db/sysdb_views.c                       | 25 ++++++--
 src/man/include/override_homedir.xml       |  8 +++
 src/responder/nss/nss_protocol_pwent.c     | 12 +++-
 src/tests/intg/ldap_local_override_test.py | 75 +++++++++++++++++++++-
 5 files changed, 119 insertions(+), 7 deletions(-)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 37a2c41244..0043ca01d8 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -725,6 +725,12 @@ sss_view_ldb_msg_find_element(struct sss_domain_info *dom,
                               const struct ldb_message *msg,
                               const char *attr_name);
 
+const char *sss_view_ldb_msg_find_attr_as_string_ex(struct sss_domain_info *dom,
+                                                  const struct ldb_message *msg,
+                                                  const char *attr_name,
+                                                  const char *default_value,
+                                                  bool *is_override);
+
 const char *sss_view_ldb_msg_find_attr_as_string(struct sss_domain_info *dom,
                                                  const struct ldb_message *msg,
                                                  const char *attr_name,
diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c
index 269dab70f2..19c10977bf 100644
--- a/src/db/sysdb_views.c
+++ b/src/db/sysdb_views.c
@@ -1788,15 +1788,20 @@ uint64_t sss_view_ldb_msg_find_attr_as_uint64(struct sss_domain_info *dom,
     return val;
 }
 
-const char *sss_view_ldb_msg_find_attr_as_string(struct sss_domain_info *dom,
-                                                 const struct ldb_message *msg,
-                                                 const char *attr_name,
-                                                 const char * default_value)
+const char *sss_view_ldb_msg_find_attr_as_string_ex(struct sss_domain_info *dom,
+                                                  const struct ldb_message *msg,
+                                                  const char *attr_name,
+                                                  const char *default_value,
+                                                  bool *is_override)
 {
     TALLOC_CTX *tmp_ctx = NULL;
     const char *val;
     char *override_attr_name;
 
+    if (is_override != NULL) {
+        *is_override = false;
+    }
+
     if (DOM_HAS_VIEWS(dom)) {
         tmp_ctx = talloc_new(NULL);
         if (tmp_ctx == NULL) {
@@ -1816,6 +1821,9 @@ const char *sss_view_ldb_msg_find_attr_as_string(struct sss_domain_info *dom,
         if (ldb_msg_find_element(msg, override_attr_name) != NULL) {
             val = ldb_msg_find_attr_as_string(msg, override_attr_name,
                                               default_value);
+            if (is_override != NULL && val != default_value) {
+                *is_override = true;
+            }
             goto done;
         }
     }
@@ -1826,3 +1834,12 @@ const char *sss_view_ldb_msg_find_attr_as_string(struct sss_domain_info *dom,
     talloc_free(tmp_ctx);
     return val;
 }
+
+const char *sss_view_ldb_msg_find_attr_as_string(struct sss_domain_info *dom,
+                                                 const struct ldb_message *msg,
+                                                 const char *attr_name,
+                                                 const char *default_value)
+{
+    return sss_view_ldb_msg_find_attr_as_string_ex(dom, msg, attr_name,
+                                                   default_value, NULL);
+}
diff --git a/src/man/include/override_homedir.xml b/src/man/include/override_homedir.xml
index 803cd1980e..19114ef2f1 100644
--- a/src/man/include/override_homedir.xml
+++ b/src/man/include/override_homedir.xml
@@ -65,5 +65,13 @@ override_homedir = /home/%u
         Default: Not set (SSSD will use the value
         retrieved from LDAP)
     </para>
+    <para>
+        Please note, the home directory from a specific override for the user,
+        either locally (see
+        <citerefentry><refentrytitle>sss_override</refentrytitle>
+        <manvolnum>8</manvolnum></citerefentry>) or centrally managed IPA
+        id-overrides, has a higher precedence and will be used instead of the
+        value given by override_homedir.
+    </para>
 </listitem>
 </varlistentry>
diff --git a/src/responder/nss/nss_protocol_pwent.c b/src/responder/nss/nss_protocol_pwent.c
index c9926cdc99..9be5bf8ac1 100644
--- a/src/responder/nss/nss_protocol_pwent.c
+++ b/src/responder/nss/nss_protocol_pwent.c
@@ -53,9 +53,10 @@ nss_get_homedir_override(TALLOC_CTX *mem_ctx,
                          struct sss_nss_homedir_ctx *homedir_ctx)
 {
     const char *homedir;
+    bool is_override = false;
 
-    homedir = sss_view_ldb_msg_find_attr_as_string(dom, msg, SYSDB_HOMEDIR,
-                                                   NULL);
+    homedir = sss_view_ldb_msg_find_attr_as_string_ex(dom, msg, SYSDB_HOMEDIR,
+                                                      NULL, &is_override);
     homedir_ctx->original = homedir;
 
     /* Check to see which homedir_prefix to use. */
@@ -65,6 +66,13 @@ nss_get_homedir_override(TALLOC_CTX *mem_ctx,
         homedir_ctx->config_homedir_substr = nctx->homedir_substr;
     }
 
+    /* Individual overrides have the highest priority, only templates will be
+     * expanded and no further options will be evaluated. */
+    if (is_override) {
+        return expand_homedir_template(mem_ctx, homedir,
+                                       dom->case_preserve, homedir_ctx);
+    }
+
     /* Here we skip the files provider as it should always return *only*
      * what's in the files and nothing else.
      */
diff --git a/src/tests/intg/ldap_local_override_test.py b/src/tests/intg/ldap_local_override_test.py
index 4db4e5e96d..d960ac1392 100644
--- a/src/tests/intg/ldap_local_override_test.py
+++ b/src/tests/intg/ldap_local_override_test.py
@@ -141,8 +141,12 @@ def teardown():
 
 
 def prepare_sssd(request, ldap_conn, use_fully_qualified_names=False,
-                 case_sensitive=True):
+                 case_sensitive=True, override_homedir_option=False):
     """Prepare SSSD with defaults"""
+    conf_override_homedir_option = ""
+    if override_homedir_option:
+        conf_override_homedir_option = "override_homedir = /home/ov_option/%u"
+
     conf = unindent("""\
         [sssd]
         domains             = LDAP
@@ -150,6 +154,7 @@ def prepare_sssd(request, ldap_conn, use_fully_qualified_names=False,
 
         [nss]
         memcache_timeout = 1
+        {conf_override_homedir_option}
 
         [domain/LDAP]
         ldap_auth_disable_tls_never_use_in_production = true
@@ -1119,3 +1124,71 @@ def test_mix_cased_name_override(ldap_conn, env_mix_cased_name_override):
 
     ent.assert_passwd_by_name('user2@LDAP', user2)
     ent.assert_passwd_by_name('ov_user2@LDAP', user2)
+
+
+# Test with override_homedir option
+@pytest.fixture
+def env_override_homedir_option(request, ldap_conn):
+    """Setup test for override_homedir option and overrides"""
+
+    prepare_sssd(request, ldap_conn, override_homedir_option=True)
+
+    # Add entries
+    ent_list = ldap_ent.List(ldap_conn.ds_inst.base_dn)
+    ent_list.add_user("user1", 10001, 20001)
+    ent_list.add_user("user2", 10002, 20002)
+
+    create_ldap_fixture(request, ldap_conn, ent_list)
+
+    pwd.getpwnam('user1@LDAP')
+    pwd.getpwnam('user2@LDAP')
+    with pytest.raises(KeyError):
+        pwd.getpwnam('ov_user1@LDAP')
+    with pytest.raises(KeyError):
+        pwd.getpwnam('ov_user2@LDAP')
+
+    # Override
+    subprocess.check_call(["sss_override", "user-add", "user1@LDAP",
+                           "-u", "10010",
+                           "-g", "20010",
+                           "-n", "ov_user1",
+                           "-c", "Overriden User 1",
+                           # no homedir override
+                           "-s", "/bin/ov_user1_shell"])
+
+    subprocess.check_call(["sss_override", "user-add", "user2@LDAP",
+                           "-u", "10020",
+                           "-g", "20020",
+                           "-n", "ov_user2",
+                           "-c", "Overriden User 2",
+                           "-h", "/home/ov/user2",
+                           "-s", "/bin/ov_user2_shell"])
+
+    restart_sssd()
+
+
+def test_override_homedir_option(ldap_conn, env_override_homedir_option):
+    """Test if overrides will overwrite override_homedir option"""
+
+    # Assert entries are overridden, user1 has no homedir override and
+    # override_homedir option should be used, user2 has a homedir override
+    # which should be used.
+    user1 = dict(name='ov_user1', passwd='*', uid=10010, gid=20010,
+                 gecos='Overriden User 1',
+                 dir='/home/ov_option/ov_user1',
+                 shell='/bin/ov_user1_shell')
+
+    user2 = dict(name='ov_user2', passwd='*', uid=10020, gid=20020,
+                 gecos='Overriden User 2',
+                 dir='/home/ov/user2',
+                 shell='/bin/ov_user2_shell')
+
+    ent.assert_passwd_by_name('user1@LDAP', user1)
+    ent.assert_passwd_by_name('ov_user1@LDAP', user1)
+    ent.assert_passwd_by_name('user1', user1)
+    ent.assert_passwd_by_name('ov_user1', user1)
+
+    ent.assert_passwd_by_name('user2@LDAP', user2)
+    ent.assert_passwd_by_name('ov_user2@LDAP', user2)
+    ent.assert_passwd_by_name('user2', user2)
+    ent.assert_passwd_by_name('ov_user2', user2)
_______________________________________________
sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org
To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org
Fedora Code of Conduct: 
https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedorahosted.org/archives/list/sssd-devel@lists.fedorahosted.org
Do not reply to spam on the list, report it: 
https://pagure.io/fedora-infrastructure

Reply via email to