From ea9a1b158585b3626b8e25ed79b92c579502e58c Mon Sep 17 00:00:00 2001 From: Jan Zeleny Date: Mon, 23 May 2011 07:08:01 -0400 Subject: Handle non-POSIX groups in nesting Added sysdb_attrs_get_bool() function Non-posix group processing - sysdb changes Non-posix group processing - ldap provider and nss responder --- src/db/sysdb.c | 22 ++++++++++ src/db/sysdb.h | 7 ++- src/db/sysdb_ops.c | 40 +++++++++-------- src/providers/ldap/ldap_id_cleanup.c | 24 +++++------ src/providers/ldap/sdap_async_accounts.c | 73 +++++++++++++++++++++++++------- src/responder/nss/nsssrv_cmd.c | 14 ++++-- src/tests/sysdb-tests.c | 4 +- 7 files changed, 132 insertions(+), 52 deletions(-) diff --git a/src/db/sysdb.c b/src/db/sysdb.c index b23bac145..40b7c26c6 100644 --- a/src/db/sysdb.c +++ b/src/db/sysdb.c @@ -333,6 +333,28 @@ int sysdb_attrs_get_uint32_t(struct sysdb_attrs *attrs, const char *name, return EOK; } +errno_t sysdb_attrs_get_bool(struct sysdb_attrs *attrs, const char *name, + bool *value) +{ + struct ldb_message_element *el; + int ret; + + ret = sysdb_attrs_get_el_int(attrs, name, false, &el); + if (ret) { + return ret; + } + + if (el->num_values != 1) { + return ERANGE; + } + + if (strcmp((const char *)el->values[0].data, "TRUE") == 0) + *value = true; + else + *value = false; + return EOK; +} + int sysdb_attrs_get_string_array(struct sysdb_attrs *attrs, const char *name, TALLOC_CTX *mem_ctx, const char ***string) { diff --git a/src/db/sysdb.h b/src/db/sysdb.h index b7256911a..68d3021ee 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -62,6 +62,7 @@ #define SYSDB_MEMBER "member" #define SYSDB_MEMBERUID "memberUid" +#define SYSDB_POSIX "isPosix" #define SYSDB_DEFAULTGROUP "defaultGroup" #define SYSDB_GECOS "gecos" @@ -153,7 +154,7 @@ NULL} #define SYSDB_INITGR_ATTR SYSDB_MEMBEROF -#define SYSDB_INITGR_ATTRS {SYSDB_GIDNUM, \ +#define SYSDB_INITGR_ATTRS {SYSDB_GIDNUM, SYSDB_POSIX, \ SYSDB_DEFAULT_ATTRS, \ NULL} @@ -200,6 +201,8 @@ int sysdb_attrs_get_string(struct sysdb_attrs *attrs, const char *name, const char **string); int sysdb_attrs_get_string_array(struct sysdb_attrs *attrs, const char *name, TALLOC_CTX *mem_ctx, const char ***string); +errno_t sysdb_attrs_get_bool(struct sysdb_attrs *attrs, const char *name, + bool *value); int sysdb_attrs_get_uint32_t(struct sysdb_attrs *attrs, const char *name, uint32_t *value); @@ -503,7 +506,7 @@ int sysdb_add_incomplete_group(struct sysdb_ctx *ctx, struct sss_domain_info *domain, const char *name, gid_t gid, - const char *original_dn); + const char *original_dn, bool posix); /* Add netgroup (only basic attrs and w/o checks) */ int sysdb_add_basic_netgroup(struct sysdb_ctx *ctx, diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c index ba1f6672c..08437f6dd 100644 --- a/src/db/sysdb_ops.c +++ b/src/db/sysdb_ops.c @@ -1047,6 +1047,7 @@ int sysdb_add_group(TALLOC_CTX *mem_ctx, uint32_t id; time_t now; int ret; + bool posix; if (domain->id_max != 0 && gid != 0 && (gid < domain->id_min || gid > domain->id_max)) { @@ -1095,22 +1096,6 @@ int sysdb_add_group(TALLOC_CTX *mem_ctx, ret = sysdb_add_basic_group(tmpctx, ctx, domain, name, gid); if (ret) goto done; - if (gid == 0) { - ret = sysdb_get_new_id(tmpctx, ctx, domain, &id); - if (ret) goto done; - - if (!attrs) { - attrs = sysdb_new_attrs(tmpctx); - if (!attrs) { - ret = ENOMEM; - goto done; - } - } - - ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, id); - if (ret) goto done; - } - if (!attrs) { attrs = sysdb_new_attrs(tmpctx); if (!attrs) { @@ -1119,6 +1104,23 @@ int sysdb_add_group(TALLOC_CTX *mem_ctx, } } + ret = sysdb_attrs_get_bool(attrs, SYSDB_POSIX, &posix); + if (ret == ENOENT) { + posix = true; + ret = sysdb_attrs_add_bool(attrs, SYSDB_POSIX, true); + if (ret) goto done; + } else if (ret != EOK) { + goto done; + } + + if (posix && gid == 0) { + ret = sysdb_get_new_id(tmpctx, ctx, domain, &id); + if (ret) goto done; + + ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, id); + if (ret) goto done; + } + now = time(NULL); ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now); @@ -1148,7 +1150,8 @@ int sysdb_add_incomplete_group(struct sysdb_ctx *ctx, struct sss_domain_info *domain, const char *name, gid_t gid, - const char *original_dn) + const char *original_dn, + bool posix) { TALLOC_CTX *tmpctx; time_t now; @@ -1179,6 +1182,9 @@ int sysdb_add_incomplete_group(struct sysdb_ctx *ctx, now-1); if (ret) goto done; + ret = sysdb_attrs_add_bool(attrs, SYSDB_POSIX, posix); + if (ret) goto done; + if (original_dn) { ret = sysdb_attrs_add_string(attrs, SYSDB_ORIG_DN, original_dn); if (ret) goto done; diff --git a/src/providers/ldap/ldap_id_cleanup.c b/src/providers/ldap/ldap_id_cleanup.c index 293681cf4..a457f60b8 100644 --- a/src/providers/ldap/ldap_id_cleanup.c +++ b/src/providers/ldap/ldap_id_cleanup.c @@ -374,6 +374,7 @@ static int cleanup_groups(TALLOC_CTX *memctx, size_t u_count; int ret; int i; + const char *posix; tmpctx = talloc_new(memctx); if (!tmpctx) { @@ -412,19 +413,18 @@ static int cleanup_groups(TALLOC_CTX *memctx, goto done; } - gid = (gid_t) ldb_msg_find_attr_as_uint(msgs[i], SYSDB_GIDNUM, 0); - if (!gid) { - DEBUG(2, ("Entry has no GID\n")); - ret = EIO; - goto done; + posix = ldb_msg_find_attr_as_string(msgs[i], SYSDB_POSIX, NULL); + if (!posix || strcmp(posix, "TRUE") == 0) { + /* Search for users that are members of this group, or + * that have this group as their primary GID + */ + gid = (gid_t) ldb_msg_find_attr_as_uint(msgs[i], SYSDB_GIDNUM, 0); + subfilter = talloc_asprintf(tmpctx, "(|(%s=%s)(%s=%lu))", + SYSDB_MEMBEROF, dn, + SYSDB_GIDNUM, (long unsigned) gid); + } else { + subfilter = talloc_asprintf(tmpctx, "(%s=%s)", SYSDB_MEMBEROF, dn); } - - /* Search for users that are members of this group, or - * that have this group as their primary GID - */ - subfilter = talloc_asprintf(tmpctx, "(|(%s=%s)(%s=%lu))", - SYSDB_MEMBEROF, dn, - SYSDB_GIDNUM, (long unsigned) gid); if (!subfilter) { DEBUG(2, ("Failed to build filter\n")); ret = ENOMEM; diff --git a/src/providers/ldap/sdap_async_accounts.c b/src/providers/ldap/sdap_async_accounts.c index 4c909408b..0f5990e62 100644 --- a/src/providers/ldap/sdap_async_accounts.c +++ b/src/providers/ldap/sdap_async_accounts.c @@ -679,6 +679,7 @@ static int sdap_save_group(TALLOC_CTX *memctx, int ret; char *usn_value = NULL; TALLOC_CTX *tmpctx = NULL; + bool posix_group; tmpctx = talloc_new(memctx); if (!tmpctx) { @@ -700,6 +701,19 @@ static int sdap_save_group(TALLOC_CTX *memctx, goto fail; } + ret = sysdb_attrs_get_bool(attrs, SYSDB_POSIX, &posix_group); + if (ret == ENOENT) { + posix_group = true; + } else if (ret != EOK) { + goto fail; + } + + DEBUG(8, ("This is%s a posix group\n", (posix_group)?"":" not")); + ret = sysdb_attrs_add_bool(group_attrs, SYSDB_POSIX, posix_group); + if (ret != EOK) { + goto fail; + } + ret = sysdb_attrs_get_uint32_t(attrs, opts->group_map[SDAP_AT_GROUP_GID].sys_name, &gid); @@ -711,7 +725,8 @@ static int sdap_save_group(TALLOC_CTX *memctx, } /* check that the gid is valid for this domain */ - if (OUT_OF_ID_RANGE(gid, dom->id_min, dom->id_max)) { + if ((posix_group || gid != 0) && + OUT_OF_ID_RANGE(gid, dom->id_min, dom->id_max)) { DEBUG(2, ("Group [%s] filtered out! (id out of range)\n", name)); ret = EINVAL; @@ -1918,6 +1933,7 @@ static errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb, gid_t gid; int ret; bool in_transaction = false; + bool posix; /* There are no groups in LDAP but we should add user to groups ?? */ if (ldap_groups_count == 0) return EOK; @@ -1977,11 +1993,15 @@ static errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb, } if (strcmp(name, missing[i]) == 0) { + posix = true; ret = sysdb_attrs_get_uint32_t(ldap_groups[ai], SYSDB_GIDNUM, &gid); - if (ret) { - DEBUG(1, ("The GID attribute is missing or malformed\n")); + if (ret == ENOENT) { + gid = 0; + posix = false; + } else if (ret) { + DEBUG(1, ("The GID attribute is malformed\n")); goto fail; } @@ -1995,7 +2015,7 @@ static errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb, DEBUG(8, ("Adding fake group %s to sysdb\n", name)); ret = sysdb_add_incomplete_group(sysdb, dom, name, - gid, original_dn); + gid, original_dn, posix); if (ret != EOK) { goto fail; } @@ -2331,10 +2351,9 @@ static struct tevent_req *sdap_initgr_nested_send(TALLOC_CTX *memctx, return NULL; } - state->filter = talloc_asprintf(state, "(&(objectclass=%s)(%s=*)(%s=*))", + state->filter = talloc_asprintf(state, "(&(objectclass=%s)(%s=*))", opts->group_map[SDAP_OC_GROUP].name, - opts->group_map[SDAP_AT_GROUP_NAME].name, - opts->group_map[SDAP_AT_GROUP_GID].name); + opts->group_map[SDAP_AT_GROUP_NAME].name); if (!state->filter) { talloc_zfree(req); return NULL; @@ -3181,6 +3200,7 @@ static struct tevent_req *sdap_nested_group_process_send( const char *groupname; hash_key_t key; hash_value_t value; + gid_t gid; req = tevent_req_create(mem_ctx, &state, struct sdap_nested_group_ctx); if (!req) { @@ -3229,6 +3249,28 @@ static struct tevent_req *sdap_nested_group_process_send( goto immediate; } + ret = sysdb_attrs_get_uint32_t(group, + opts->group_map[SDAP_AT_GROUP_GID].name, + &gid); + if (ret == ENOENT) { + DEBUG(8, ("Marking group as non-posix and setting GID=0!\n")); + ret = sysdb_attrs_add_uint32(group, + opts->group_map[SDAP_AT_GROUP_GID].name, + 0); + if (ret != EOK) { + DEBUG(1, ("Failed to add a GID to non-posix group!\n")); + goto immediate; + } + + ret = sysdb_attrs_add_bool(group, SYSDB_POSIX, false); + if (ret != EOK) { + DEBUG(2, ("Error: Failed to mark group as non-posix!\n")); + goto immediate; + } + } else if (ret) { + goto immediate; + } + value.type = HASH_VALUE_PTR; value.ptr = talloc_steal(groups, group); @@ -3507,10 +3549,9 @@ static errno_t sdap_nested_group_lookup_group(struct tevent_req *req) } filter = talloc_asprintf( - sdap_attrs, "(&(objectclass=%s)(%s=*)(%s=*))", + sdap_attrs, "(&(objectclass=%s)(%s=*))", state->opts->group_map[SDAP_OC_GROUP].name, - state->opts->group_map[SDAP_AT_GROUP_NAME].name, - state->opts->group_map[SDAP_AT_GROUP_GID].name); + state->opts->group_map[SDAP_AT_GROUP_NAME].name); if (!filter) { talloc_free(sdap_attrs); return ENOMEM; @@ -3842,12 +3883,11 @@ static struct tevent_req *sdap_initgr_rfc2307bis_send( return NULL; } - filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s)(%s=*)(%s=*))", + filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s)(%s=*))", opts->group_map[SDAP_AT_GROUP_MEMBER].name, clean_orig_dn, opts->group_map[SDAP_OC_GROUP].name, - opts->group_map[SDAP_AT_GROUP_NAME].name, - opts->group_map[SDAP_AT_GROUP_GID].name); + opts->group_map[SDAP_AT_GROUP_NAME].name); if (!filter) { talloc_zfree(req); return NULL; @@ -4043,6 +4083,7 @@ errno_t save_rfc2307bis_user_memberships( goto error; } + DEBUG(8, ("Updating memberships for %s\n", state->name)); ret = sysdb_update_members(state->sysdb, state->dom, state->name, SYSDB_MEMBER_USER, (const char *const *)add_groups, @@ -4253,12 +4294,11 @@ static errno_t rfc2307bis_nested_groups_step(struct tevent_req *req) } filter = talloc_asprintf( - tmp_ctx, "(&(%s=%s)(objectclass=%s)(%s=*)(%s=*))", + tmp_ctx, "(&(%s=%s)(objectclass=%s)(%s=*))", state->opts->group_map[SDAP_AT_GROUP_MEMBER].name, clean_orig_dn, state->opts->group_map[SDAP_OC_GROUP].name, - state->opts->group_map[SDAP_AT_GROUP_NAME].name, - state->opts->group_map[SDAP_AT_GROUP_GID].name); + state->opts->group_map[SDAP_AT_GROUP_NAME].name); if (!filter) { ret = ENOMEM; goto error; @@ -4537,6 +4577,7 @@ static errno_t rfc2307bis_nested_groups_update_sysdb( talloc_free(ldap_grouplist); talloc_free(sysdb_grouplist); + DEBUG(8, ("Updating memberships for %s\n", name)); ret = sysdb_update_members(state->sysdb, state->dom, name, SYSDB_MEMBER_GROUP, (const char *const *)add_groups, diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c index 74c56a311..db7edd023 100644 --- a/src/responder/nss/nsssrv_cmd.c +++ b/src/responder/nss/nsssrv_cmd.c @@ -2922,6 +2922,8 @@ static int fill_initgr(struct sss_packet *packet, struct ldb_result *res) size_t blen; gid_t gid; int ret, i, num; + int skipped = 0; + const char *posix; if (res->count == 0) { return ENOENT; @@ -2939,14 +2941,20 @@ static int fill_initgr(struct sss_packet *packet, struct ldb_result *res) /* skip first entry, it's the user entry */ for (i = 0; i < num; i++) { gid = ldb_msg_find_attr_as_uint64(res->msgs[i + 1], SYSDB_GIDNUM, 0); + posix = ldb_msg_find_attr_as_string(res->msgs[i + 1], SYSDB_POSIX, NULL); if (!gid) { - DEBUG(1, ("Incomplete group object for initgroups! Aborting\n")); - return EFAULT; + if (posix && strcmp(posix, "FALSE") == 0) { + skipped++; + continue; + } else { + DEBUG(1, ("Incomplete group object for initgroups! Aborting\n")); + return EFAULT; + } } ((uint32_t *)body)[2 + i] = gid; } - ((uint32_t *)body)[0] = num; /* num results */ + ((uint32_t *)body)[0] = num-skipped; /* num results */ ((uint32_t *)body)[1] = 0; /* reserved */ return EOK; diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c index b856c093b..540fba3d5 100644 --- a/src/tests/sysdb-tests.c +++ b/src/tests/sysdb-tests.c @@ -268,7 +268,7 @@ static int test_add_incomplete_group(struct test_data *data) int ret; ret = sysdb_add_incomplete_group(data->ctx->sysdb, data->ctx->domain, - data->groupname, data->gid, NULL); + data->groupname, data->gid, NULL, true); return ret; } @@ -2743,7 +2743,7 @@ START_TEST(test_odd_characters) /* Add */ ret = sysdb_add_incomplete_group(test_ctx->sysdb, test_ctx->domain, - odd_groupname, 20000, NULL); + odd_groupname, 20000, NULL, true); fail_unless(ret == EOK, "sysdb_add_incomplete_group error [%d][%s]", ret, strerror(ret)); -- cgit