Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LDAP/AD: resolve domain local groups for remote users #57

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/db/sysdb.h
Expand Up @@ -225,6 +225,7 @@
SYSDB_OVERRIDE_OBJECT_DN, \
SYSDB_DEFAULT_OVERRIDE_NAME, \
SYSDB_UUID, \
SYSDB_ORIG_DN, \
NULL}

#define SYSDB_GRSRC_ATTRS {SYSDB_NAME, SYSDB_GIDNUM, \
Expand Down Expand Up @@ -1137,8 +1138,29 @@ errno_t sysdb_remove_attrs(struct sss_domain_info *domain,
enum sysdb_member_type type,
char **remove_attrs);

/**
* @brief Return direct parents of an object in the cache
*
* @param[in] mem_ctx Memory context the result should be allocated
* on
* @param[in] dom domain the object is in
* @param[in] parent_dom domain which should be searched for direct
* parents if NULL all domains in the given cache
* are searched
* @param[in] mtype Type of the object, SYSDB_MEMBER_USER or
* SYSDB_MEMBER_GROUP
* @param[in] name Name of the object
* @param[out] _direct_parents List of names of the direct parent groups
*
*
* @return
* - EOK: success
* - EINVAL: wrong mtype
* - ENOMEM: Memory allocation failed
*/
errno_t sysdb_get_direct_parents(TALLOC_CTX *mem_ctx,
struct sss_domain_info *dom,
struct sss_domain_info *parent_dom,
enum sysdb_member_type mtype,
const char *name,
char ***_direct_parents);
Expand Down
7 changes: 6 additions & 1 deletion src/db/sysdb_search.c
Expand Up @@ -1981,6 +1981,7 @@ int sysdb_get_netgroup_attr(TALLOC_CTX *mem_ctx,

errno_t sysdb_get_direct_parents(TALLOC_CTX *mem_ctx,
struct sss_domain_info *dom,
struct sss_domain_info *parent_dom,
enum sysdb_member_type mtype,
const char *name,
char ***_direct_parents)
Expand Down Expand Up @@ -2029,7 +2030,11 @@ errno_t sysdb_get_direct_parents(TALLOC_CTX *mem_ctx,
goto done;
}

basedn = sysdb_group_base_dn(tmp_ctx, dom);
if (parent_dom == NULL) {
basedn = sysdb_base_dn(dom->sysdb, tmp_ctx);
} else {
basedn = sysdb_group_base_dn(tmp_ctx, parent_dom);
}
if (!basedn) {
ret = ENOMEM;
goto done;
Expand Down
181 changes: 160 additions & 21 deletions src/providers/ldap/sdap_async_initgroups.c
Expand Up @@ -622,7 +622,7 @@ static int sdap_initgr_rfc2307_recv(struct tevent_req *req)
}

/* ==Common code for pure RFC2307bis and IPA/AD========================= */
static errno_t
errno_t
sdap_nested_groups_store(struct sysdb_ctx *sysdb,
struct sss_domain_info *domain,
struct sdap_options *opts,
Expand Down Expand Up @@ -1301,7 +1301,8 @@ sdap_initgr_store_user_memberships(struct sdap_initgr_nested_state *state)
}
}

ret = sysdb_get_direct_parents(tmp_ctx, state->dom, SYSDB_MEMBER_USER,
ret = sysdb_get_direct_parents(tmp_ctx, state->dom, state->dom,
SYSDB_MEMBER_USER,
state->username, &sysdb_parent_name_list);
if (ret) {
DEBUG(SSSDBG_CRIT_FAILURE,
Expand Down Expand Up @@ -1388,7 +1389,7 @@ sdap_initgr_nested_get_membership_diff(TALLOC_CTX *mem_ctx,
goto done;
}

ret = sysdb_get_direct_parents(tmp_ctx, dom, SYSDB_MEMBER_GROUP,
ret = sysdb_get_direct_parents(tmp_ctx, dom, dom, SYSDB_MEMBER_GROUP,
group_name, &sysdb_parents_names_list);
if (ret) {
DEBUG(SSSDBG_CRIT_FAILURE,
Expand Down Expand Up @@ -1557,14 +1558,6 @@ static void sdap_initgr_rfc2307bis_process(struct tevent_req *subreq);
static void sdap_initgr_rfc2307bis_done(struct tevent_req *subreq);
errno_t save_rfc2307bis_user_memberships(
struct sdap_initgr_rfc2307bis_state *state);
struct tevent_req *rfc2307bis_nested_groups_send(
TALLOC_CTX *mem_ctx, struct tevent_context *ev,
struct sdap_options *opts, struct sysdb_ctx *sysdb,
struct sss_domain_info *dom, struct sdap_handle *sh,
struct sdap_search_base **search_bases,
struct sysdb_attrs **groups, size_t num_groups,
hash_table_t *group_hash, size_t nesting);
static errno_t rfc2307bis_nested_groups_recv(struct tevent_req *req);

static struct tevent_req *sdap_initgr_rfc2307bis_send(
TALLOC_CTX *memctx,
Expand Down Expand Up @@ -2070,7 +2063,8 @@ rfc2307bis_group_memberships_build(hash_entry_t *item, void *user_data)
goto done;
}

ret = sysdb_get_direct_parents(tmp_ctx, mstate->dom, SYSDB_MEMBER_GROUP,
ret = sysdb_get_direct_parents(tmp_ctx, mstate->dom, mstate->dom,
SYSDB_MEMBER_GROUP,
group_name, &sysdb_parents_names_list);
if (ret) {
DEBUG(SSSDBG_CRIT_FAILURE,
Expand Down Expand Up @@ -2130,7 +2124,8 @@ errno_t save_rfc2307bis_user_memberships(
}
in_transaction = true;

ret = sysdb_get_direct_parents(tmp_ctx, state->dom, SYSDB_MEMBER_USER,
ret = sysdb_get_direct_parents(tmp_ctx, state->dom, state->dom,
SYSDB_MEMBER_USER,
state->name, &sysdb_parent_name_list);
if (ret) {
DEBUG(SSSDBG_CRIT_FAILURE,
Expand Down Expand Up @@ -2322,16 +2317,29 @@ static errno_t rfc2307bis_nested_groups_step(struct tevent_req *req)
struct sdap_rfc2307bis_nested_ctx *state =
tevent_req_data(req, struct sdap_rfc2307bis_nested_ctx);
char *oc_list;
const char *class;

tmp_ctx = talloc_new(state);
if (!tmp_ctx) {
ret = ENOMEM;
goto done;
}

ret = sdap_get_group_primary_name(state, state->opts,
state->groups[state->group_iter],
state->dom, &state->primary_name);
ret = sysdb_attrs_get_string(state->groups[state->group_iter],
SYSDB_OBJECTCLASS, &class);
if (ret == EOK) {
/* If there is a objectClass attribute the object is coming from the
* cache and the name attribute of the object already has the primary
* name.
* If the objectClass attribute is missing the object is coming from
* LDAP and we have to find the primary name first. */
ret = sysdb_attrs_get_string(state->groups[state->group_iter],
SYSDB_NAME, &state->primary_name);
} else {
ret = sdap_get_group_primary_name(state, state->opts,
state->groups[state->group_iter],
state->dom, &state->primary_name);
}
if (ret != EOK) {
goto done;
}
Expand Down Expand Up @@ -2613,7 +2621,7 @@ static void rfc2307bis_nested_groups_process(struct tevent_req *subreq)
tevent_req_set_callback(subreq, rfc2307bis_nested_groups_done, req);
}

static errno_t rfc2307bis_nested_groups_recv(struct tevent_req *req)
errno_t rfc2307bis_nested_groups_recv(struct tevent_req *req)
{
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
Expand Down Expand Up @@ -3074,6 +3082,103 @@ static void sdap_get_initgr_user(struct tevent_req *subreq)
tevent_req_error(req, ret);
}

static void sdap_ad_check_domain_local_groups_done(struct tevent_req *subreq);

errno_t sdap_ad_check_domain_local_groups(struct tevent_req *req)
{
struct sdap_get_initgr_state *state = tevent_req_data(req,
struct sdap_get_initgr_state);
int ret;
struct sdap_domain *local_sdom;
const char *orig_name;
const char *sysdb_name;
struct ldb_result *res;
struct tevent_req *subreq;
struct sysdb_attrs **groups;

/* We only need to check for domain local groups in the AD case and if the
* user is not from our domain, i.e. if the user comes from a sub-domain.
*/
if (state->opts->schema_type != SDAP_SCHEMA_AD
|| !IS_SUBDOMAIN(state->dom)
|| !dp_target_enabled(state->id_ctx->be->provider, "ad", DPT_ID)) {
return EOK;
}

local_sdom = sdap_domain_get(state->id_ctx->opts, state->dom->parent);
if (local_sdom == NULL || local_sdom->pvt == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "No ID ctx available for [%s].\n",
state->dom->parent->name);
return EINVAL;
}

ret = sysdb_attrs_get_string(state->orig_user, SYSDB_NAME, &orig_name);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Missing name in user object.\n");
return ret;
}

sysdb_name = sss_create_internal_fqname(state, orig_name, state->dom->name);
if (sysdb_name == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "sss_create_internal_fqname failed.\n");
return ENOMEM;
}

ret = sysdb_initgroups(state, state->dom, sysdb_name, &res);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_initgroups failed for user [%s].\n",
sysdb_name);
return ret;
}

if (res->count == 0) {
DEBUG(SSSDBG_CRIT_FAILURE,
"sysdb_initgroups returned no results for user [%s].\n",
sysdb_name);
return EINVAL;
}

/* The user object, the first entry in the res->msgs, is included as well
* to cover the case where the remote user is directly added to
* a domain local group. */
ret = sysdb_msg2attrs(state, res->count, res->msgs, &groups);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sysdb_msg2attrs failed.\n");
return ret;
}

subreq = sdap_ad_get_domain_local_groups_send(state, state->ev, local_sdom,
state->opts, state->sysdb, state->dom->parent,
groups, res->count);
if (subreq == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "sdap_ad_get_domain_local_groups_send failed.\n");
return ENOMEM;
}

tevent_req_set_callback(subreq, sdap_ad_check_domain_local_groups_done,
req);

return EAGAIN;
}

static void sdap_ad_check_domain_local_groups_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,
struct tevent_req);
int ret;

ret = sdap_ad_get_domain_local_groups_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
}

tevent_req_done(req);

return;
}

static void sdap_get_initgr_pgid(struct tevent_req *req);
static void sdap_get_initgr_done(struct tevent_req *subreq)
{
Expand Down Expand Up @@ -3206,8 +3311,6 @@ static void sdap_get_initgr_done(struct tevent_req *subreq)
if (ret == EOK) {
DEBUG(SSSDBG_TRACE_FUNC,
"Primary group already cached, nothing to do.\n");
ret = EOK;
goto done;
} else {
gid = talloc_asprintf(state, "%lu", (unsigned long)primary_gid);
if (gid == NULL) {
Expand All @@ -3224,10 +3327,28 @@ static void sdap_get_initgr_done(struct tevent_req *subreq)
goto done;
}
tevent_req_set_callback(subreq, sdap_get_initgr_pgid, req);

talloc_free(tmp_ctx);
return;
}

talloc_free(tmp_ctx);
return;
ret = sdap_ad_check_domain_local_groups(req);
if (ret == EAGAIN) {
DEBUG(SSSDBG_TRACE_ALL,
"Checking for domain local group memberships.\n");
talloc_free(tmp_ctx);
return;
} else if (ret == EOK) {
DEBUG(SSSDBG_TRACE_ALL,
"No need to check for domain local group memberships.\n");
} else {
DEBUG(SSSDBG_OP_FAILURE,
"sdap_ad_check_domain_local_groups failed, "
"meberships to domain local groups might be missing.\n");
/* do not let the request fail completely because we already have at
* least "some" groups */
ret = EOK;
}

done:
talloc_free(tmp_ctx);
Expand All @@ -3252,7 +3373,25 @@ static void sdap_get_initgr_pgid(struct tevent_req *subreq)
return;
}

ret = sdap_ad_check_domain_local_groups(req);
if (ret == EAGAIN) {
DEBUG(SSSDBG_TRACE_ALL,
"Checking for domain local group memberships.\n");
return;
} else if (ret == EOK) {
DEBUG(SSSDBG_TRACE_ALL,
"No need to check for domain local group memberships.\n");
} else {
DEBUG(SSSDBG_OP_FAILURE, "sdap_ad_check_domain_local_groups failed.\n");
DEBUG(SSSDBG_OP_FAILURE,
"sdap_ad_check_domain_local_groups failed, "
"meberships to domain local groups might be missing.\n");
/* do not let the request fail completely because we already have at
* least "some" groups */
}

tevent_req_done(req);
return;
}

int sdap_get_initgr_recv(struct tevent_req *req)
Expand Down