From 115241b0eeedd033d34d9721a896f031140944d7 Mon Sep 17 00:00:00 2001 From: Pavel Březina Date: Wed, 28 Aug 2013 11:35:27 +0200 Subject: simple provider: support subdomain groups Resolves: https://fedorahosted.org/sssd/ticket/2034 --- src/providers/simple/simple_access_check.c | 87 ++++++++++++++++++++++-------- 1 file changed, 64 insertions(+), 23 deletions(-) diff --git a/src/providers/simple/simple_access_check.c b/src/providers/simple/simple_access_check.c index 5c2884ab..b401aef9 100644 --- a/src/providers/simple/simple_access_check.c +++ b/src/providers/simple/simple_access_check.c @@ -152,6 +152,7 @@ simple_check_groups(struct simple_ctx *ctx, const char **group_names, } struct simple_resolve_group_state { + struct sss_domain_info *domain; gid_t gid; struct simple_ctx *ctx; @@ -166,6 +167,7 @@ static struct tevent_req * simple_resolve_group_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct simple_ctx *ctx, + struct sss_domain_info *domain, gid_t gid) { errno_t ret; @@ -178,6 +180,7 @@ simple_resolve_group_send(TALLOC_CTX *mem_ctx, struct simple_resolve_group_state); if (!req) return NULL; + state->domain = domain; state->gid = gid; state->ctx = ctx; @@ -206,7 +209,7 @@ simple_resolve_group_send(TALLOC_CTX *mem_ctx, ar->attr_type = BE_ATTR_CORE; ar->filter_type = BE_FILTER_IDNUM; ar->filter_value = talloc_asprintf(ar, "%llu", (unsigned long long) gid); - ar->domain = talloc_strdup(ar, ctx->domain->name); + ar->domain = talloc_strdup(ar, state->domain->name); if (!ar->domain || !ar->filter_value) { ret = ENOMEM; goto done; @@ -240,10 +243,13 @@ simple_resolve_group_check(struct simple_resolve_group_state *state) SYSDB_GIDNUM, NULL }; /* Check the cache by GID again and fetch the name */ - ret = sysdb_search_group_by_gid(state, state->ctx->domain->sysdb, - state->ctx->domain, state->gid, + ret = sysdb_search_group_by_gid(state, state->domain->sysdb, + state->domain, state->gid, group_attrs, &group); - if (ret != EOK) { + if (ret == ENOENT) { + /* The group is missing, we will try to update it. */ + return EAGAIN; + } else if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, ("Could not look up group by gid [%"SPRIgid"]: [%d][%s]\n", state->gid, ret, sss_strerror(ret))); @@ -321,12 +327,18 @@ simple_resolve_group_recv(struct tevent_req *req, return EOK; } +struct simple_group { + struct sss_domain_info *domain; + gid_t gid; +}; + struct simple_check_groups_state { struct tevent_context *ev; struct simple_ctx *ctx; + struct sss_domain_info *domain; - gid_t *lookup_gids; - size_t num_gids; + struct simple_group *lookup_groups; + size_t num_groups; size_t giter; const char **group_names; @@ -352,7 +364,8 @@ simple_check_get_groups_send(TALLOC_CTX *mem_ctx, struct tevent_req *req; struct tevent_req *subreq; struct simple_check_groups_state *state; - const char *attrs[] = { SYSDB_NAME, SYSDB_POSIX, SYSDB_GIDNUM, NULL }; + const char *attrs[] = { SYSDB_NAME, SYSDB_POSIX, SYSDB_GIDNUM, + SYSDB_SID_STR, NULL }; size_t group_count; struct ldb_message *user; struct ldb_message **groups; @@ -368,7 +381,15 @@ simple_check_get_groups_send(TALLOC_CTX *mem_ctx, DEBUG(SSSDBG_TRACE_LIBS, ("Looking up groups for user %s\n", username)); - ret = sysdb_search_user_by_name(state, ctx->domain->sysdb, ctx->domain, + /* get domain from username */ + state->domain = find_subdomain_by_object_name(ctx->domain, username); + if (state->domain == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid user %s!\n", username)); + ret = EINVAL; + goto done; + } + + ret = sysdb_search_user_by_name(state, state->domain->sysdb, state->domain, username, attrs, &user); if (ret == ENOENT) { DEBUG(SSSDBG_MINOR_FAILURE, ("No such user %s\n", username)); @@ -381,7 +402,7 @@ simple_check_get_groups_send(TALLOC_CTX *mem_ctx, goto done; } - ret = sysdb_asq_search(state, ctx->domain->sysdb, + ret = sysdb_asq_search(state, state->domain->sysdb, user->dn, NULL, SYSDB_MEMBEROF, attrs, &group_count, &groups); if (ret != EOK) { @@ -394,8 +415,9 @@ simple_check_get_groups_send(TALLOC_CTX *mem_ctx, /* One extra space for terminator, one extra space for private group */ state->group_names = talloc_zero_array(state, const char *, group_count + 2); - state->lookup_gids = talloc_zero_array(state, gid_t, group_count + 2); - if (!state->group_names || !state->lookup_gids) { + state->lookup_groups = talloc_zero_array(state, struct simple_group, + group_count + 2); + if (!state->group_names || !state->lookup_groups) { ret = ENOMEM; goto done; } @@ -426,7 +448,7 @@ simple_check_get_groups_send(TALLOC_CTX *mem_ctx, goto done; } - if (state->num_gids == 0) { + if (state->num_groups == 0) { /* If all groups could have been resolved by name, we are * done */ @@ -435,10 +457,12 @@ simple_check_get_groups_send(TALLOC_CTX *mem_ctx, goto done; } - DEBUG(SSSDBG_TRACE_FUNC, ("Need to resolve %zu groups\n", state->num_gids)); + DEBUG(SSSDBG_TRACE_FUNC, ("Need to resolve %zu groups\n", + state->num_groups)); state->giter = 0; subreq = simple_resolve_group_send(req, state->ev, state->ctx, - state->lookup_gids[state->giter]); + state->lookup_groups[state->giter].domain, + state->lookup_groups[state->giter].gid); if (!subreq) { ret = ENOMEM; goto done; @@ -471,7 +495,7 @@ static void simple_check_get_groups_next(struct tevent_req *subreq) if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, ("Could not resolve name of group with GID %"SPRIgid"\n", - state->lookup_gids[state->giter])); + state->lookup_groups[state->giter].gid)); tevent_req_error(req, ret); return; } @@ -479,9 +503,10 @@ static void simple_check_get_groups_next(struct tevent_req *subreq) state->num_names++; state->giter++; - if (state->giter < state->num_gids) { + if (state->giter < state->num_groups) { subreq = simple_resolve_group_send(req, state->ev, state->ctx, - state->lookup_gids[state->giter]); + state->lookup_groups[state->giter].domain, + state->lookup_groups[state->giter].gid); if (!subreq) { tevent_req_error(req, ENOMEM); return; @@ -499,6 +524,8 @@ simple_check_process_group(struct simple_check_groups_state *state, struct ldb_message *group) { const char *name; + const char *group_sid; + struct sss_domain_info *domain; gid_t gid; bool posix; @@ -543,10 +570,25 @@ simple_check_process_group(struct simple_check_groups_state *state, return EOK; } - /* Non-posix group with a GID. Needs resolving */ - state->lookup_gids[state->num_gids] = gid; + /* Try to get group SID and assign it a domain */ + group_sid = ldb_msg_find_attr_as_string(group, SYSDB_SID_STR, NULL); + if (group_sid == NULL) { + /* We will look it up in main domain. */ + domain = state->ctx->domain; + } else { + domain = find_subdomain_by_sid(state->ctx->domain, group_sid); + if (domain == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, ("There is no domain information for " + "SID %s\n", group_sid)); + return ENOENT; + } + } + + /* It is a non-posix group with a GID. Needs resolving */ + state->lookup_groups[state->num_groups].domain = domain; + state->lookup_groups[state->num_groups].gid = gid; DEBUG(SSSDBG_TRACE_INTERNAL, ("Adding GID %"SPRIgid"\n", gid)); - state->num_gids++; + state->num_groups++; return EOK; } @@ -556,11 +598,10 @@ simple_check_get_groups_primary(struct simple_check_groups_state *state, { errno_t ret; const char *group_attrs[] = { SYSDB_NAME, SYSDB_POSIX, - SYSDB_GIDNUM, NULL }; + SYSDB_GIDNUM, SYSDB_SID_STR, NULL }; struct ldb_message *msg; - ret = sysdb_search_group_by_gid(state, state->ctx->domain->sysdb, - state->ctx->domain, + ret = sysdb_search_group_by_gid(state, state->domain->sysdb, state->domain, gid, group_attrs, &msg); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, -- cgit