Skip to content

Commit

Permalink
Handle child-domain group membership
Browse files Browse the repository at this point in the history
In AD, a user from a domain can be a member of a group that is
from a child of the domain.

The old code did not account for this and created a cache object
with incorrect DNs when ldap_use_tokengoups is set to False.

This patch looks up the correct domain before saving
group and membership attributes.

Resolves: #7084
  • Loading branch information
thalman committed Dec 21, 2023
1 parent fbff098 commit 2687836
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 15 deletions.
9 changes: 8 additions & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -2357,7 +2357,10 @@ ipa_ldap_opt_tests_LDADD = \
$(LDB_LIBS) \
$(SSSD_INTERNAL_LTLIBS) \
$(OPENLDAP_LIBS) \
libsss_test_common.la
libsss_test_common.la \
libsss_ldap_common.la \
libdlopen_test_providers.la \
$(NULL)

ad_ldap_opt_tests_SOURCES = \
src/providers/ldap/ldap_opts.c \
Expand Down Expand Up @@ -2919,6 +2922,8 @@ nestedgroups_tests_LDADD = \
$(SSSD_INTERNAL_LTLIBS) \
libsss_idmap.la \
libsss_test_common.la \
libsss_ldap_common.la \
libdlopen_test_providers.la \
$(NULL)
if BUILD_SYSTEMTAP
nestedgroups_tests_LDADD += stap_generated_probes.lo
Expand Down Expand Up @@ -3165,6 +3170,8 @@ sdap_tests_LDADD = \
$(SSSD_INTERNAL_LTLIBS) \
$(OPENLDAP_LIBS) \
libsss_test_common.la \
libsss_ldap_common.la \
libdlopen_test_providers.la \
$(NULL)

if BUILD_IFP
Expand Down
13 changes: 12 additions & 1 deletion src/db/sysdb_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -2980,6 +2980,7 @@ sysdb_group_membership_mod(struct sss_domain_info *domain,
struct ldb_dn *member_dn;
char *member_domname;
struct sss_domain_info *member_dom;
struct sss_domain_info *group_dom;
int ret;
TALLOC_CTX *tmp_ctx = talloc_new(NULL);
if (!tmp_ctx) {
Expand Down Expand Up @@ -3019,7 +3020,17 @@ sysdb_group_membership_mod(struct sss_domain_info *domain,
}

if (!is_dn) {
group_dn = sysdb_group_dn(tmp_ctx, domain, group);
/* To create a correct DN we have to check if the group belongs to */
/* child domain */
group_dom = find_domain_by_object_name(domain, group);
if (group_dom == NULL) {
DEBUG(SSSDBG_OP_FAILURE,
"The right (sub)domain for the group [%s] was not found\n",
group);
ret = EINVAL;
goto done;
}
group_dn = sysdb_group_dn(tmp_ctx, group_dom, group);
} else {
group_dn = ldb_dn_new(tmp_ctx, domain->sysdb->ldb, group);
}
Expand Down
62 changes: 52 additions & 10 deletions src/providers/ldap/sdap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1843,7 +1843,9 @@ errno_t sdap_get_primary_name(const char *attr_name,

static errno_t
sdap_get_primary_fqdn(TALLOC_CTX *mem_ctx,
struct sdap_idmap_ctx *idmap_ctx,
const char *attr_name,
const char *sid_attr_name,
struct sysdb_attrs *attrs,
struct sss_domain_info *dom,
const char **_primary_fqdn)
Expand All @@ -1852,6 +1854,8 @@ sdap_get_primary_fqdn(TALLOC_CTX *mem_ctx,
const char *shortname = NULL;
const char *primary_fqdn = NULL;
TALLOC_CTX *tmp_ctx;
char *sid_str = NULL;
struct sss_domain_info *subdomain = NULL;

tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
Expand All @@ -1863,6 +1867,25 @@ sdap_get_primary_fqdn(TALLOC_CTX *mem_ctx,
goto done;
}

/* In AD scenarion, the object can be from subdomain - identify it by SID */
if (sid_attr_name != NULL) {
ret = sdap_attrs_get_sid_str(tmp_ctx,
idmap_ctx,
attrs,
sid_attr_name,
&sid_str);

if (ret == EOK) {
DEBUG(SSSDBG_TRACE_INTERNAL, "Group has objectSID [%s]\n", sid_str);
subdomain = find_domain_by_sid(dom, sid_str);
talloc_free(sid_str);
if (subdomain != NULL) {
dom = subdomain;
}
}
DEBUG(SSSDBG_TRACE_INTERNAL, "Group has name [%s]\n", dom->name);
}

primary_fqdn = sss_create_internal_fqname(tmp_ctx, shortname, dom->name);
if (primary_fqdn == NULL) {
ret = ENOMEM;
Expand All @@ -1883,7 +1906,9 @@ errno_t sdap_get_user_primary_name(TALLOC_CTX *memctx,
const char **_user_name)
{
return sdap_get_primary_fqdn(memctx,
opts->idmap_ctx,
opts->user_map[SDAP_AT_USER_NAME].name,
opts->group_map[SDAP_AT_USER_OBJECTSID].name,
attrs, dom, _user_name);
}

Expand All @@ -1894,7 +1919,9 @@ errno_t sdap_get_group_primary_name(TALLOC_CTX *memctx,
const char **_group_name)
{
return sdap_get_primary_fqdn(memctx,
opts->idmap_ctx,
opts->group_map[SDAP_AT_GROUP_NAME].name,
opts->group_map[SDAP_AT_GROUP_OBJECTSID].name,
attrs, dom, _group_name);
}

Expand All @@ -1913,6 +1940,8 @@ _sdap_get_primary_name_list(struct sss_domain_info *domain,
size_t attr_count,
const char *ldap_attr,
bool qualify_names,
const char *sid_attr,
struct sdap_idmap_ctx *idmap_ctx,
char ***name_list)
{
errno_t ret;
Expand All @@ -1928,17 +1957,28 @@ _sdap_get_primary_name_list(struct sss_domain_info *domain,

j = 0;
for (i = 0; i < attr_count; i++) {
ret = sdap_get_primary_name(ldap_attr, attr_list[i], &name);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Could not determine primary name\n");
/* Skip and continue. Don't advance 'j' */
continue;
}

if (qualify_names == false) {
ret = sdap_get_primary_name(ldap_attr, attr_list[i], &name);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Could not determine primary name\n");
/* Skip and continue. Don't advance 'j' */
continue;
}
list[j] = talloc_strdup(list, name);
} else {
list[j] = sss_create_internal_fqname(list, name, domain->name);
ret = sdap_get_primary_fqdn(mem_ctx,
idmap_ctx,
ldap_attr,
sid_attr,
attr_list[i],
domain,
&name);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Could not determine primary fqdn name\n");
/* Skip and continue. Don't advance 'j' */
continue;
}
list[j] = talloc_strdup(list, name);
}
if (!list[j]) {
ret = ENOMEM;
Expand Down Expand Up @@ -1970,18 +2010,20 @@ errno_t sdap_get_primary_name_list(struct sss_domain_info *domain,
char ***name_list)
{
return _sdap_get_primary_name_list(domain, mem_ctx, attr_list, attr_count,
ldap_attr, false, name_list);
ldap_attr, false, NULL, NULL, name_list);
}

errno_t sdap_get_primary_fqdn_list(struct sss_domain_info *domain,
TALLOC_CTX *mem_ctx,
struct sysdb_attrs **attr_list,
size_t attr_count,
const char *ldap_attr,
const char *sid_attr,
struct sdap_idmap_ctx *idmap_ctx,
char ***name_list)
{
return _sdap_get_primary_name_list(domain, mem_ctx, attr_list, attr_count,
ldap_attr, true, name_list);
ldap_attr, true, sid_attr, idmap_ctx, name_list);
}


Expand Down
2 changes: 2 additions & 0 deletions src/providers/ldap/sdap.h
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,8 @@ errno_t sdap_get_primary_fqdn_list(struct sss_domain_info *domain,
struct sysdb_attrs **attr_list,
size_t attr_count,
const char *ldap_attr,
const char *sid_attr,
struct sdap_idmap_ctx *idmap_ctx,
char ***name_list);

errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse,
Expand Down
2 changes: 2 additions & 0 deletions src/providers/ldap/sdap_async_groups.c
Original file line number Diff line number Diff line change
Expand Up @@ -2002,6 +2002,8 @@ static void sdap_get_groups_process(struct tevent_req *subreq)
ret = sdap_get_primary_fqdn_list(state->dom, state,
state->groups, state->count,
state->opts->group_map[SDAP_AT_GROUP_NAME].name,
state->opts->group_map[SDAP_AT_GROUP_OBJECTSID].name,
state->opts->idmap_ctx,
&sysdb_groupnamelist);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
Expand Down
23 changes: 20 additions & 3 deletions src/providers/ldap/sdap_async_initgroups.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,
char *sid_str = NULL;
bool use_id_mapping;
bool need_filter;
struct sss_domain_info *subdomain;

/* There are no groups in LDAP but we should add user to groups?? */
if (ldap_groups_count == 0) return EOK;
Expand All @@ -68,7 +69,11 @@ errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,
mi = 0;

for (i=0; sysdb_groupnames[i]; i++) {
ret = sysdb_search_group_by_name(tmp_ctx, domain, sysdb_groupnames[i], NULL,
subdomain = find_domain_by_object_name(domain, sysdb_groupnames[i]);
if (subdomain == NULL) {
subdomain = domain;
}
ret = sysdb_search_group_by_name(tmp_ctx, subdomain, sysdb_groupnames[i], NULL,
&msg);
if (ret == EOK) {
continue;
Expand Down Expand Up @@ -222,7 +227,11 @@ errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,

DEBUG(SSSDBG_TRACE_INTERNAL,
"Adding fake group %s to sysdb\n", groupname);
ret = sysdb_add_incomplete_group(domain, groupname, gid,
subdomain = find_domain_by_object_name(domain, groupname);
if (subdomain == NULL) {
subdomain = domain;
}
ret = sysdb_add_incomplete_group(subdomain, groupname, gid,
original_dn, sid_str,
uuid, posix, now);
if (ret == ERR_GID_DUPLICATED) {
Expand All @@ -233,7 +242,7 @@ errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,
* removed from the memory cache
*/
ret = sdap_handle_id_collision_for_incomplete_groups(
opts->dp, domain, groupname, gid,
opts->dp, subdomain, groupname, gid,
original_dn, sid_str, uuid, posix,
now);
}
Expand Down Expand Up @@ -667,6 +676,8 @@ sdap_nested_groups_store(struct sysdb_ctx *sysdb,
if (count > 0) {
ret = sdap_get_primary_fqdn_list(domain, tmp_ctx, groups, count,
opts->group_map[SDAP_AT_GROUP_NAME].name,
opts->group_map[SDAP_AT_GROUP_OBJECTSID].name,
opts->idmap_ctx,
&groupnamelist);
if (ret != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE,
Expand Down Expand Up @@ -1447,6 +1458,8 @@ sdap_initgr_nested_get_membership_diff(TALLOC_CTX *mem_ctx,
ret = sdap_get_primary_fqdn_list(dom, tmp_ctx, ldap_parentlist,
parents_count,
opts->group_map[SDAP_AT_GROUP_NAME].name,
opts->group_map[SDAP_AT_GROUP_OBJECTSID].name,
opts->idmap_ctx,
&ldap_parent_names_list);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
Expand Down Expand Up @@ -2105,6 +2118,8 @@ rfc2307bis_group_memberships_build(hash_entry_t *item, void *user_data)
ret = sdap_get_primary_fqdn_list(mstate->dom, tmp_ctx,
group->ldap_parents, group->parents_count,
mstate->opts->group_map[SDAP_AT_GROUP_NAME].name,
mstate->opts->group_map[SDAP_AT_GROUP_OBJECTSID].name,
mstate->opts->idmap_ctx,
&ldap_parents_names_list);
if (ret != EOK) {
goto done;
Expand Down Expand Up @@ -2169,6 +2184,8 @@ errno_t save_rfc2307bis_user_memberships(
ret = sdap_get_primary_fqdn_list(state->dom, tmp_ctx,
state->direct_groups, state->num_direct_parents,
state->opts->group_map[SDAP_AT_GROUP_NAME].name,
state->opts->group_map[SDAP_AT_GROUP_OBJECTSID].name,
state->opts->idmap_ctx,
&ldap_grouplist);
if (ret != EOK) {
goto error;
Expand Down
2 changes: 2 additions & 0 deletions src/providers/ldap/sdap_async_initgroups_ad.c
Original file line number Diff line number Diff line change
Expand Up @@ -1333,6 +1333,8 @@ sdap_ad_get_domain_local_groups_parse_parents(TALLOC_CTX *mem_ctx,
ret = sdap_get_primary_fqdn_list(dom, tmp_ctx, gr->ldap_parents,
gr->parents_count,
opts->group_map[SDAP_AT_GROUP_NAME].name,
opts->group_map[SDAP_AT_GROUP_OBJECTSID].name,
opts->idmap_ctx,
&groupnamelist);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_primary_fqdn_list failed.\n");
Expand Down

0 comments on commit 2687836

Please sign in to comment.