diff --git a/src/db/sysdb.h b/src/db/sysdb.h index a049460f0ee..427495181be 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -875,12 +875,6 @@ int sysdb_getpwuid(TALLOC_CTX *mem_ctx, uid_t uid, struct ldb_result **res); -int sysdb_getpwupn(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domain, - bool domain_scope, - const char *upn, - struct ldb_result **res); - int sysdb_enumpwent(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, struct ldb_result **res); @@ -1070,6 +1064,13 @@ int sysdb_search_user_by_upn_res(TALLOC_CTX *mem_ctx, const char **attrs, struct ldb_result **out_res); +int sysdb_search_user_by_upn_with_view_res(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + bool domain_scope, + const char *upn, + const char **attrs, + struct ldb_result **out_res); + int sysdb_search_user_by_upn(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, bool domain_scope, diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c index cfc3b9e54ac..5090ae52f2f 100644 --- a/src/db/sysdb_ops.c +++ b/src/db/sysdb_ops.c @@ -712,6 +712,44 @@ int sysdb_search_user_by_upn_res(TALLOC_CTX *mem_ctx, return ret; } +int sysdb_search_user_by_upn_with_view_res(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + bool domain_scope, + const char *upn, + const char **attrs, + struct ldb_result **out_res) +{ + int ret; + struct ldb_result *orig_obj = NULL; + + /* The UPN or the email address cannot be overwritten and we can search + * directly the original object. */ + ret = sysdb_search_user_by_upn_res(mem_ctx, domain, domain_scope, upn, + attrs, &orig_obj); + if (ret != EOK) { + DEBUG(ret == ENOENT ? SSSDBG_MINOR_FAILURE : SSSDBG_OP_FAILURE, + "Failed to find UPN [%s] in cache [%d][%s].\n", + upn, ret, sss_strerror(ret)); + return ret; + } + + /* If there are views we have to check if override values must be added to + * the original object. */ + if (DOM_HAS_VIEWS(domain)) { + ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0], NULL, + attrs); + if (ret != EOK && ret != ENOENT) { + talloc_free(orig_obj); + DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object failed.\n"); + return ret; + } + ret = EOK; + } + + *out_res = orig_obj; + return ret; +} + int sysdb_search_user_by_upn(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, bool domain_scope, diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c index 513e721ca45..645871354fe 100644 --- a/src/db/sysdb_search.c +++ b/src/db/sysdb_search.c @@ -598,36 +598,6 @@ static char *enum_filter(TALLOC_CTX *mem_ctx, return filter; } -int sysdb_getpwupn(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domain, - bool domain_scope, - const char *upn, - struct ldb_result **_res) -{ - TALLOC_CTX *tmp_ctx; - struct ldb_result *res; - static const char *attrs[] = SYSDB_PW_ATTRS; - errno_t ret; - - tmp_ctx = talloc_new(NULL); - if (tmp_ctx == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); - return ENOMEM; - } - - ret = sysdb_search_user_by_upn_res(tmp_ctx, domain, domain_scope, upn, attrs, &res); - if (ret != EOK && ret != ENOENT) { - DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_user_by_upn_res() failed.\n"); - goto done; - } - - *_res = talloc_steal(mem_ctx, res); - -done: - talloc_free(tmp_ctx); - return ret; -} - errno_t sysdb_search_ts_matches(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb, const char *attrs[], diff --git a/src/responder/common/cache_req/plugins/cache_req_user_by_upn.c b/src/responder/common/cache_req/plugins/cache_req_user_by_upn.c index 037994c8c2a..cfcaf491606 100644 --- a/src/responder/common/cache_req/plugins/cache_req_user_by_upn.c +++ b/src/responder/common/cache_req/plugins/cache_req_user_by_upn.c @@ -84,13 +84,14 @@ cache_req_user_by_upn_lookup(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, struct ldb_result **_result) { - if (data->attrs == NULL) { - return sysdb_getpwupn(mem_ctx, domain, true, data->name.lookup, _result); - } - - return sysdb_search_user_by_upn_res(mem_ctx, domain, true, - data->name.lookup, data->attrs, - _result); + static const char *def_attrs[] = SYSDB_PW_ATTRS; + + return sysdb_search_user_by_upn_with_view_res(mem_ctx, domain, true, + data->name.lookup, + data->attrs == NULL + ? def_attrs + : data->attrs, + _result); } static struct tevent_req * diff --git a/src/tests/cmocka/test_sysdb_ts_cache.c b/src/tests/cmocka/test_sysdb_ts_cache.c index f349b706197..531de72abed 100644 --- a/src/tests/cmocka/test_sysdb_ts_cache.c +++ b/src/tests/cmocka/test_sysdb_ts_cache.c @@ -1303,12 +1303,6 @@ static void test_user_byupn(void **state) TEST_NOW_2); assert_int_equal(ret, EOK); - ret = sysdb_getpwupn(test_ctx, test_ctx->tctx->dom, false, TEST_USER_UPN, &res); - assert_int_equal(ret, EOK); - assert_int_equal(res->count, 1); - assert_ts_attrs_res(res, TEST_NOW_2 + TEST_CACHE_TIMEOUT, TEST_NOW_2); - talloc_free(res); - ret = sysdb_search_user_by_upn_res(test_ctx, test_ctx->tctx->dom, false, TEST_USER_UPN, pw_fetch_attrs, &res); diff --git a/src/tests/system/tests/test_sss_override.py b/src/tests/system/tests/test_sss_override.py index 9e5389fd82c..ea61ad6bb1f 100644 --- a/src/tests/system/tests/test_sss_override.py +++ b/src/tests/system/tests/test_sss_override.py @@ -116,6 +116,63 @@ def test_sss_override__user_attributes(client: Client, provider: GenericProvider assert result.home == "/home/o-user1", "User's override name homedir does not match override value!" +@pytest.mark.importance("high") +@pytest.mark.topology([KnownTopology.LDAP, KnownTopology.AD, KnownTopology.Samba]) +def test_sss_overrides__overriding_username_and_attributes_lookup_by_email(client: Client, provider: GenericProvider): + """ + :title: Locally overriding the name and POSIX attributes of a user and lookup with the email address + :setup: + 1. Create POSIX user "user1" with email "email@example.com", email is + used because the UPN is not supported in all roles of the framework + 2. Configure SSSD with "ldap_id_mapping = false" and start SSSD + 3. Create local override for "user1" + 4. Restart SSSD, this is necessary to enable local overrides + :steps: + 1. Lookup user by the original name, check the uid and gid + 2. Lookup user by the overridden name, check the uid and gid + 3. Lookup user by email, check the uid and gid + :expectedresults: + 1. User is found and uid and gid match new values + 2. User is found and uid and gid match new values + 3. User is found and uid and gid match new values + :customerscenario: True + """ + provider.user("user1").add( + uid=999011, + gid=999011, + home="/home/user1", + gecos="user", + shell="/bin/bash", + password="Secret123", + email="email@example.com", + ) + + client.sssd.domain["ldap_id_mapping"] = "False" + client.sssd.start() + + client.sss_override.user("user1").add(name="o-user1", uid=999999, gid=888888, home="/home/o-user1") + + client.sssd.restart() + + result = client.tools.getent.passwd("user1") + assert result is not None, "User not found!" + assert result.uid == 999999, "User's uid does not match override value!" + assert result.gid == 888888, "User's gid does not match override value!" + assert result.home == "/home/o-user1", "User's homedir does not match override value!" + + result = client.tools.getent.passwd("o-user1") + assert result is not None, "User not found by override name!" + assert result.uid == 999999, "Local override uid does not match override value!" + assert result.gid == 888888, "Local override gid does not match override value!" + assert result.home == "/home/o-user1", "User's override name homedir does not match override value!" + + result = client.tools.getent.passwd("email@example.com") + assert result is not None, "User not found by email!" + assert result.uid == 999999, "Local override uid does not match override value!" + assert result.gid == 888888, "Local override gid does not match override value!" + assert result.home == "/home/o-user1", "User's override name homedir does not match override value!" + + @pytest.mark.importance("high") @pytest.mark.topology([KnownTopology.LDAP, KnownTopology.AD, KnownTopology.Samba]) @pytest.mark.preferred_topology(KnownTopology.LDAP)