summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Březina <pbrezina@redhat.com>2013-08-28 11:35:27 +0200
committerJakub Hrozek <jhrozek@redhat.com>2013-09-17 16:02:20 +0200
commit115241b0eeedd033d34d9721a896f031140944d7 (patch)
tree0f696e5dffd07f3438cf94609f03f877b06c5618
parent0b81cc5d41ec6a1c58e610f402fd93a1fbda4aff (diff)
downloadsssd-115241b0eeedd033d34d9721a896f031140944d7.tar.gz
sssd-115241b0eeedd033d34d9721a896f031140944d7.tar.bz2
sssd-115241b0eeedd033d34d9721a896f031140944d7.zip
simple provider: support subdomain groups
Resolves: https://fedorahosted.org/sssd/ticket/2034
-rw-r--r--src/providers/simple/simple_access_check.c87
1 files 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,