From 8d47f715ca63388f2dcbcdf3f2ccdb44e7d47b93 Mon Sep 17 00:00:00 2001 From: Michal Zidek Date: Wed, 10 Sep 2014 12:56:54 +0200 Subject: Use the alternative objectclass in group maps. Use the alternative group objectclass in queries. Fixes: https://fedorahosted.org/sssd/ticket/2436 Reviewed-by: Jakub Hrozek (cherry picked from commit 7ba70236daccb48432350147d0560b3302518cee) (cherry picked from commit 9e99c000a4e2647328e71b4db272b4b73a7189c5) --- src/providers/ldap/ldap_id.c | 18 ++++++---- src/providers/ldap/sdap.c | 40 ++++++++++++++++++--- src/providers/ldap/sdap.h | 2 ++ src/providers/ldap/sdap_async_enum.c | 12 +++++-- src/providers/ldap/sdap_async_initgroups.c | 50 +++++++++++++++++++++------ src/providers/ldap/sdap_async_initgroups_ad.c | 13 +++++-- src/providers/ldap/sdap_async_nested_groups.c | 11 ++++-- 7 files changed, 117 insertions(+), 29 deletions(-) diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c index 2d1ba5b5a..842381517 100644 --- a/src/providers/ldap/ldap_id.c +++ b/src/providers/ldap/ldap_id.c @@ -539,6 +539,7 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, enum idmap_error_code err; char *sid; const char *member_filter[2]; + char *oc_list; req = tevent_req_create(memctx, &state, struct groups_get_state); if (!req) return NULL; @@ -645,21 +646,26 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, goto fail; } + oc_list = sdap_make_oc_list(state, ctx->opts->group_map); + if (oc_list == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create objectClass list.\n"); + ret = ENOMEM; + goto fail; + } + if (state->use_id_mapping || filter_type == BE_FILTER_SECID) { /* When mapping IDs or looking for SIDs, we don't want to limit * ourselves to groups with a GID value */ state->filter = talloc_asprintf(state, - "(&(%s=%s)(objectclass=%s)(%s=*))", - attr_name, clean_name, - ctx->opts->group_map[SDAP_OC_GROUP].name, + "(&(%s=%s)(%s)(%s=*))", + attr_name, clean_name, oc_list, ctx->opts->group_map[SDAP_AT_GROUP_NAME].name); } else { state->filter = talloc_asprintf(state, - "(&(%s=%s)(objectclass=%s)(%s=*)(&(%s=*)(!(%s=0))))", - attr_name, clean_name, - ctx->opts->group_map[SDAP_OC_GROUP].name, + "(&(%s=%s)(%s)(%s=*)(&(%s=*)(!(%s=0))))", + attr_name, clean_name, oc_list, ctx->opts->group_map[SDAP_AT_GROUP_NAME].name, ctx->opts->group_map[SDAP_AT_GROUP_GID].name, ctx->opts->group_map[SDAP_AT_GROUP_GID].name); diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c index e8d23c9dc..fead21a4f 100644 --- a/src/providers/ldap/sdap.c +++ b/src/providers/ldap/sdap.c @@ -290,6 +290,8 @@ int sdap_get_map(TALLOC_CTX *memctx, /* =Parse-msg============================================================= */ +static bool objectclass_matched(struct sdap_attr_map *map, + const char *objcl, int len); int sdap_parse_entry(TALLOC_CTX *memctx, struct sdap_handle *sh, struct sdap_msg *sm, struct sdap_attr_map *map, int attrs_num, @@ -357,9 +359,7 @@ int sdap_parse_entry(TALLOC_CTX *memctx, } for (i = 0; vals[i]; i++) { - /* the objectclass is always the first name in the map */ - if (strncasecmp(map[0].name, - vals[i]->bv_val, vals[i]->bv_len) == 0) { + if (objectclass_matched(map, vals[i]->bv_val, vals[i]->bv_len)) { /* ok it's an entry of the right type */ break; } @@ -511,6 +511,25 @@ done: return ret; } +static bool objectclass_matched(struct sdap_attr_map *map, + const char *objcl, int len) +{ + if (len == 0) { + len = strlen(objcl) + 1; + } + + if (strncasecmp(map[SDAP_OC_GROUP].name, objcl, len) == 0) { + return true; + } + + if (map[SDAP_OC_GROUP_ALT].name != NULL + && strncasecmp(map[SDAP_OC_GROUP_ALT].name, objcl, len) == 0) { + return true; + } + + return false; +} + /* Parses an LDAPDerefRes into sdap_deref_attrs structure */ errno_t sdap_parse_deref(TALLOC_CTX *mem_ctx, struct sdap_attr_map_info *minfo, @@ -610,7 +629,7 @@ errno_t sdap_parse_deref(TALLOC_CTX *mem_ctx, for (i=0; ocs[i]; i++) { /* the objectclass is always the first name in the map */ - if (strcasecmp(minfo[mi].map[0].name, ocs[i]) == 0) { + if (objectclass_matched(minfo[mi].map, ocs[i], 0)) { DEBUG(SSSDBG_TRACE_ALL, "Found map for objectclass '%s'\n", ocs[i]); map = minfo[mi].map; @@ -1458,3 +1477,16 @@ errno_t sdap_get_netgroup_primary_name(TALLOC_CTX *memctx, opts->netgroup_map[SDAP_AT_NETGROUP_NAME].name, attrs, dom, _netgroup_name); } + +char *sdap_make_oc_list(TALLOC_CTX *mem_ctx, struct sdap_attr_map *map) +{ + if (map[SDAP_OC_GROUP_ALT].name == NULL) { + return talloc_asprintf(mem_ctx, "objectClass=%s", + map[SDAP_OC_GROUP].name); + } else { + return talloc_asprintf(mem_ctx, + "|(objectClass=%s)(objectClass=%s)", + map[SDAP_OC_GROUP].name, + map[SDAP_OC_GROUP_ALT].name); + } +} diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h index 64d718c1e..8d902f0d5 100644 --- a/src/providers/ldap/sdap.h +++ b/src/providers/ldap/sdap.h @@ -561,4 +561,6 @@ int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx, struct sdap_server_opts **srv_opts); void sdap_steal_server_opts(struct sdap_id_ctx *id_ctx, struct sdap_server_opts **srv_opts); + +char *sdap_make_oc_list(TALLOC_CTX *mem_ctx, struct sdap_attr_map *map); #endif /* _SDAP_H_ */ diff --git a/src/providers/ldap/sdap_async_enum.c b/src/providers/ldap/sdap_async_enum.c index 16ba953bb..83bdde3f7 100644 --- a/src/providers/ldap/sdap_async_enum.c +++ b/src/providers/ldap/sdap_async_enum.c @@ -717,6 +717,7 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx, struct enum_groups_state *state; int ret; bool use_mapping; + char *oc_list; req = tevent_req_create(memctx, &state, struct enum_groups_state); if (!req) return NULL; @@ -732,9 +733,14 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx, sdom->dom->domain_id); /* We always want to filter on objectclass and an available name */ - state->filter = talloc_asprintf(state, - "(&(objectclass=%s)(%s=*)", - ctx->opts->group_map[SDAP_OC_GROUP].name, + oc_list = sdap_make_oc_list(state, ctx->opts->group_map); + if (oc_list == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create objectClass list.\n"); + ret = ENOMEM; + goto fail; + } + + state->filter = talloc_asprintf(state, "(&(%s)(%s=*)", oc_list, ctx->opts->group_map[SDAP_AT_GROUP_NAME].name); if (!state->filter) { DEBUG(SSSDBG_MINOR_FAILURE, diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c index 7db280435..4b71d4d47 100644 --- a/src/providers/ldap/sdap_async_initgroups.c +++ b/src/providers/ldap/sdap_async_initgroups.c @@ -368,6 +368,7 @@ struct tevent_req *sdap_initgr_rfc2307_send(TALLOC_CTX *memctx, const char **attr_filter; char *clean_name; errno_t ret; + char *oc_list; req = tevent_req_create(memctx, &state, struct sdap_initgr_rfc2307_state); if (!req) return NULL; @@ -419,11 +420,17 @@ struct tevent_req *sdap_initgr_rfc2307_send(TALLOC_CTX *memctx, return NULL; } + oc_list = sdap_make_oc_list(state, opts->group_map); + if (oc_list == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create objectClass list.\n"); + ret = ENOMEM; + goto done; + } + state->base_filter = talloc_asprintf(state, - "(&(%s=%s)(objectclass=%s)(%s=*)(&(%s=*)(!(%s=0))))", + "(&(%s=%s)(%s)(%s=*)(&(%s=*)(!(%s=0))))", opts->group_map[SDAP_AT_GROUP_MEMBER].name, - clean_name, - opts->group_map[SDAP_OC_GROUP].name, + clean_name, oc_list, opts->group_map[SDAP_AT_GROUP_NAME].name, opts->group_map[SDAP_AT_GROUP_GID].name, opts->group_map[SDAP_AT_GROUP_GID].name); @@ -805,6 +812,7 @@ static errno_t sdap_initgr_nested_noderef_search(struct tevent_req *req) int i; struct tevent_req *subreq; struct sdap_initgr_nested_state *state; + char *oc_list; state = tevent_req_data(req, struct sdap_initgr_nested_state); @@ -823,8 +831,13 @@ static errno_t sdap_initgr_nested_noderef_search(struct tevent_req *req) state->group_dns[i] = NULL; /* terminate */ state->cur = 0; - state->filter = talloc_asprintf(state, "(&(objectclass=%s)(%s=*))", - state->opts->group_map[SDAP_OC_GROUP].name, + oc_list = sdap_make_oc_list(state, state->opts->group_map); + if (oc_list == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create objectClass list.\n"); + return ENOMEM; + } + + state->filter = talloc_asprintf(state, "(&(%s)(%s=*))", oc_list, state->opts->group_map[SDAP_AT_GROUP_NAME].name); if (!state->filter) { return ENOMEM; @@ -1515,6 +1528,7 @@ static struct tevent_req *sdap_initgr_rfc2307bis_send( const char **attr_filter; char *clean_orig_dn; bool use_id_mapping; + char *oc_list; req = tevent_req_create(memctx, &state, struct sdap_initgr_rfc2307bis_state); if (!req) return NULL; @@ -1567,11 +1581,18 @@ static struct tevent_req *sdap_initgr_rfc2307bis_send( sdom->dom->name, sdom->dom->domain_id); + oc_list = sdap_make_oc_list(state, opts->group_map); + if (oc_list == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create objectClass list.\n"); + ret = ENOMEM; + goto done; + } + state->base_filter = - talloc_asprintf(state, "(&(%s=%s)(objectclass=%s)(%s=*)", + talloc_asprintf(state, + "(&(%s=%s)(%s)(%s=*)", opts->group_map[SDAP_AT_GROUP_MEMBER].name, - clean_orig_dn, - opts->group_map[SDAP_OC_GROUP].name, + clean_orig_dn, oc_list, opts->group_map[SDAP_AT_GROUP_NAME].name); if (!state->base_filter) { ret = ENOMEM; @@ -2266,6 +2287,7 @@ static errno_t rfc2307bis_nested_groups_step(struct tevent_req *req) hash_value_t value; struct sdap_rfc2307bis_nested_ctx *state = tevent_req_data(req, struct sdap_rfc2307bis_nested_ctx); + char *oc_list; tmp_ctx = talloc_new(state); if (!tmp_ctx) { @@ -2342,11 +2364,17 @@ static errno_t rfc2307bis_nested_groups_step(struct tevent_req *req) goto done; } + oc_list = sdap_make_oc_list(state, state->opts->group_map); + if (oc_list == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create objectClass list.\n"); + ret = ENOMEM; + goto done; + } + state->base_filter = talloc_asprintf( - state, "(&(%s=%s)(objectclass=%s)(%s=*))", + state, "(&(%s=%s)(%s)(%s=*))", state->opts->group_map[SDAP_AT_GROUP_MEMBER].name, - clean_orig_dn, - state->opts->group_map[SDAP_OC_GROUP].name, + clean_orig_dn, oc_list, state->opts->group_map[SDAP_AT_GROUP_NAME].name); if (!state->base_filter) { ret = ENOMEM; diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c index 574579d9e..15855b4e3 100644 --- a/src/providers/ldap/sdap_async_initgroups_ad.c +++ b/src/providers/ldap/sdap_async_initgroups_ad.c @@ -70,6 +70,7 @@ sdap_get_ad_match_rule_initgroups_send(TALLOC_CTX *mem_ctx, struct sdap_ad_match_rule_initgr_state *state; const char **filter_members; char *sanitized_user_dn; + char *oc_list; req = tevent_req_create(mem_ctx, &state, struct sdap_ad_match_rule_initgr_state); @@ -122,13 +123,19 @@ sdap_get_ad_match_rule_initgroups_send(TALLOC_CTX *mem_ctx, /* Craft a special filter according to * http://msdn.microsoft.com/en-us/library/windows/desktop/aa746475%28v=vs.85%29.aspx */ + oc_list = sdap_make_oc_list(state, state->opts->group_map); + if (oc_list == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create objectClass list.\n"); + ret = ENOMEM; + goto immediate; + } + state->base_filter = talloc_asprintf(state, - "(&(%s:%s:=%s)(objectClass=%s))", + "(&(%s:%s:=%s)(%s))", state->opts->group_map[SDAP_AT_GROUP_MEMBER].name, SDAP_MATCHING_RULE_IN_CHAIN, - sanitized_user_dn, - state->opts->group_map[SDAP_OC_GROUP].name); + sanitized_user_dn, oc_list); talloc_zfree(sanitized_user_dn); if (!state->base_filter) { ret = ENOMEM; diff --git a/src/providers/ldap/sdap_async_nested_groups.c b/src/providers/ldap/sdap_async_nested_groups.c index 3dc2a9fd3..065eb1218 100644 --- a/src/providers/ldap/sdap_async_nested_groups.c +++ b/src/providers/ldap/sdap_async_nested_groups.c @@ -1688,6 +1688,7 @@ sdap_nested_group_lookup_group_send(TALLOC_CTX *mem_ctx, const char **attrs = NULL; const char *base_filter = NULL; const char *filter = NULL; + char *oc_list; errno_t ret; req = tevent_req_create(mem_ctx, &state, @@ -1704,8 +1705,14 @@ sdap_nested_group_lookup_group_send(TALLOC_CTX *mem_ctx, } /* create filter */ - base_filter = talloc_asprintf(attrs, "(&(objectclass=%s)(%s=*))", - map[SDAP_OC_GROUP].name, + oc_list = sdap_make_oc_list(state, map); + if (oc_list == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create objectClass list.\n"); + ret = ENOMEM; + goto immediately; + } + + base_filter = talloc_asprintf(attrs, "(&(%s)(%s=*))", oc_list, map[SDAP_AT_GROUP_NAME].name); if (base_filter == NULL) { ret = ENOMEM; -- cgit