Skip to content

Commit

Permalink
ipa: do not go offline if group does not have SID
Browse files Browse the repository at this point in the history
This happens during applying overrides on cached group
during initgroups of trusted user. If the group does not
have SID (it's GID is outside the sidgen range), SSSD goes
offline.

Only SSSD running in server_mode is affected.

This patch ignores error in single group and rather continues
processing the remaining groups.

Resolves: #6942
  • Loading branch information
pbrezina committed Sep 20, 2023
1 parent 233a846 commit 482cc40
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 49 deletions.
99 changes: 50 additions & 49 deletions src/providers/ipa/ipa_id.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,66 +291,67 @@ static int ipa_initgr_get_overrides_step(struct tevent_req *req)
int ret;
struct tevent_req *subreq;
const char *ipa_uuid;
const char *dn;
struct ipa_initgr_get_overrides_state *state = tevent_req_data(req,
struct ipa_initgr_get_overrides_state);

DEBUG(SSSDBG_TRACE_LIBS,
"Processing group %zu/%zu\n", state->group_idx, state->group_count);
for (; state->group_idx < state->group_count; state->group_idx++) {
dn = ldb_dn_get_linearized(state->groups[state->group_idx]->dn);

if (state->group_idx >= state->group_count) {
return EOK;
}
DEBUG(SSSDBG_TRACE_LIBS, "Processing group %s (%zu/%zu)\n",
dn, state->group_idx, state->group_count);

ipa_uuid = ldb_msg_find_attr_as_string(state->groups[state->group_idx],
state->groups_id_attr, NULL);
if (ipa_uuid == NULL) {
/* This should never happen, the search filter used to get the list
* of groups includes "uuid=*"
*/
DEBUG(SSSDBG_OP_FAILURE,
"The group %s has no UUID attribute %s, error!\n",
ldb_dn_get_linearized(state->groups[state->group_idx]->dn),
state->groups_id_attr);
return EINVAL;
}
ipa_uuid = ldb_msg_find_attr_as_string(state->groups[state->group_idx],
state->groups_id_attr, NULL);
if (ipa_uuid == NULL) {
/* This should never happen, the search filter used to get the list
* of groups includes "uuid=*" */
DEBUG(SSSDBG_OP_FAILURE,
"The group %s has no UUID attribute %s, error!\n",
dn, state->groups_id_attr);
continue;
}

talloc_free(state->ar); /* Avoid spiking memory with many groups */
talloc_free(state->ar); /* Avoid spiking memory with many groups */

if (strcmp(state->groups_id_attr, SYSDB_UUID) == 0) {
ret = get_dp_id_data_for_uuid(state, ipa_uuid,
state->user_dom->name, &state->ar);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "get_dp_id_data_for_sid failed.\n");
return ret;
}
} else if (strcmp(state->groups_id_attr, SYSDB_SID_STR) == 0) {
ret = get_dp_id_data_for_sid(state, ipa_uuid,
state->user_dom->name, &state->ar);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "get_dp_id_data_for_sid failed.\n");
return ret;
if (strcmp(state->groups_id_attr, SYSDB_UUID) == 0) {
ret = get_dp_id_data_for_uuid(state, ipa_uuid,
state->user_dom->name, &state->ar);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "get_dp_id_data_for_sid failed.\n");
return ret;
}
} else if (strcmp(state->groups_id_attr, SYSDB_SID_STR) == 0) {
ret = get_dp_id_data_for_sid(state, ipa_uuid,
state->user_dom->name, &state->ar);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "get_dp_id_data_for_sid failed.\n");
return ret;
}
} else {
DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported groups ID type [%s].\n",
state->groups_id_attr);
return EINVAL;
}
} else {
DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported groups ID type [%s].\n",
state->groups_id_attr);
return EINVAL;
}

DEBUG(SSSDBG_TRACE_LIBS, "Fetching group %s\n", ipa_uuid);
DEBUG(SSSDBG_TRACE_LIBS, "Fetching group %s: %s\n", dn, ipa_uuid);

subreq = ipa_get_ad_override_send(state, state->ev,
state->ipa_ctx->sdap_id_ctx,
state->ipa_ctx->ipa_options,
state->realm,
state->ipa_ctx->view_name,
state->ar);
if (subreq == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_override_send failed.\n");
return ENOMEM;
subreq = ipa_get_ad_override_send(state, state->ev,
state->ipa_ctx->sdap_id_ctx,
state->ipa_ctx->ipa_options,
state->realm,
state->ipa_ctx->view_name,
state->ar);
if (subreq == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_override_send failed.\n");
return ENOMEM;
}
tevent_req_set_callback(subreq,
ipa_initgr_get_overrides_override_done, req);
return EAGAIN;
}
tevent_req_set_callback(subreq,
ipa_initgr_get_overrides_override_done, req);
return EAGAIN;

return EOK;
}

static void ipa_initgr_get_overrides_override_done(struct tevent_req *subreq)
Expand Down
61 changes: 61 additions & 0 deletions src/tests/system/tests/test_trust_identity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""
Identity of trusted users and groups.
:requirement: todo
"""

from __future__ import annotations

import pytest
from sssd_test_framework.roles.ipa import IPA
from sssd_test_framework.roles.generic import GenericADProvider
from sssd_test_framework.topology import KnownTopologyGroup


@pytest.mark.importance("low")
@pytest.mark.ticket(jira="RHEL-3925", gh=6942)
@pytest.mark.topology(KnownTopologyGroup.IPATrust)
def test_trust_identity__group_without_sid(ipa: IPA, trusted: GenericADProvider):
"""
:title: Subdomain goes offline if IPA group is missing SID
:setup:
1. Create IPA external group "external-group" and add AD user "Administrator" as a member
2. Create IPA posix group "posix-group" and add "external-group" as a member
3. Clear SSSD cache and logs on IPA server
4. Restart SSSD on IPA server
:steps:
1. Resolve user "Administrator@addomain"
2. Expire user "Administrator@addomain"
3. Resolve user "Administrator@addomain"
4. Run "sssctl domain-status addomain"
:expectedresults:
1. User is resolved and member of posix-group
2. User is expired in SSSD cache
3. User is resolved and member of posix-group
4. The Active Directory domain is still online
:customerscenario: True
"""
username = trusted.fqn("administrator")
external = ipa.group("external-group").add(external=True).add_member(username)
ipa.group("posix-group").add(gid=5001).add_member(external)

ipa.sssd.clear(db=True, memcache=True, logs=True)
ipa.sssd.restart()

# Cache trusted user
result = ipa.tools.id(username)
assert result is not None
assert result.user.name == username
assert result.memberof("posix-group")

# Expire the user and resolve it again, this will trigger the affected code path
ipa.sssctl.cache_expire(user=username)
result = ipa.tools.id(username)
assert result is not None
assert result.user.name == username
assert result.memberof("posix-group")

# Check that SSSD did not go offline
result = ipa.sssctl.domain_status(trusted.domain, online=True)
assert "online status: offline" not in result.stdout.lower()
assert "online status: online" in result.stdout.lower()

0 comments on commit 482cc40

Please sign in to comment.