From 58d02e0d3d6d48c97fccdb2ad7212e065671ad6d Mon Sep 17 00:00:00 2001 From: Stephen Gallagher Date: Mon, 23 Apr 2012 08:55:58 -0400 Subject: LDAP: Add helper routine to convert LDAP blob to SID string --- src/providers/ldap/ldap_common.c | 37 +++++++ src/providers/ldap/ldap_common.h | 6 + src/providers/ldap/sdap_async_groups.c | 24 +--- src/providers/ldap/sdap_async_initgroups.c | 172 ++++++++++++++++++++++++----- src/providers/ldap/sdap_async_users.c | 24 +--- 5 files changed, 195 insertions(+), 68 deletions(-) diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c index 6b03451ad..8e117d267 100644 --- a/src/providers/ldap/ldap_common.c +++ b/src/providers/ldap/ldap_common.c @@ -34,6 +34,7 @@ #include "util/crypto/sss_crypto.h" #include "providers/ldap/ldap_opts.h" +#include "providers/ldap/sdap_idmap.h" /* a fd the child process would log into */ int ldap_child_debug_fd = -1; @@ -1409,3 +1410,39 @@ char *sdap_get_id_specific_filter(TALLOC_CTX *mem_ctx, } return filter; /* NULL or not */ } + +errno_t +sdap_attrs_get_sid_str(TALLOC_CTX *mem_ctx, + struct sdap_idmap_ctx *idmap_ctx, + struct sysdb_attrs *sysdb_attrs, + const char *sid_attr, + char **_sid_str) +{ + errno_t ret; + enum idmap_error_code err; + struct ldb_message_element *el; + char *sid_str; + + ret = sysdb_attrs_get_el(sysdb_attrs, sid_attr, &el); + if (ret != EOK || el->num_values != 1) { + DEBUG(SSSDBG_MINOR_FAILURE, + ("No [%s] attribute while id-mapping. [%d][%s]\n", + sid_attr, el->num_values, strerror(ret))); + return ret; + } + + err = sss_idmap_bin_sid_to_sid(idmap_ctx->map, + el->values[0].data, + el->values[0].length, + &sid_str); + if (err != IDMAP_SUCCESS) { + DEBUG(SSSDBG_MINOR_FAILURE, + ("Could not convert SID: [%s]\n", + idmap_error_string(err))); + return EIO; + } + + *_sid_str = talloc_steal(mem_ctx, sid_str); + + return EOK; +} diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h index 44c53ed94..8bd2584e1 100644 --- a/src/providers/ldap/ldap_common.h +++ b/src/providers/ldap/ldap_common.h @@ -209,4 +209,10 @@ errno_t common_parse_search_base(TALLOC_CTX *mem_ctx, const char *old_filter, struct sdap_search_base ***_search_bases); +errno_t +sdap_attrs_get_sid_str(TALLOC_CTX *mem_ctx, + struct sdap_idmap_ctx *idmap_ctx, + struct sysdb_attrs *sysdb_attrs, + const char *sid_attr, + char **_sid_str); #endif /* _LDAP_COMMON_H_ */ diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c index 89882be04..67720025a 100644 --- a/src/providers/ldap/sdap_async_groups.c +++ b/src/providers/ldap/sdap_async_groups.c @@ -198,7 +198,6 @@ static int sdap_save_group(TALLOC_CTX *memctx, TALLOC_CTX *tmpctx = NULL; bool posix_group; bool use_id_mapping = dp_opt_get_bool(opts->basic, SDAP_ID_MAPPING); - struct dom_sid *dom_sid; char *sid_str; char *dom_sid_str; enum idmap_error_code err; @@ -229,25 +228,10 @@ static int sdap_save_group(TALLOC_CTX *memctx, DEBUG(SSSDBG_TRACE_LIBS, ("Mapping group [%s] objectSID to unix ID\n", name)); - ret = sysdb_attrs_get_el(attrs, - opts->group_map[SDAP_AT_GROUP_OBJECTSID].sys_name, - &el); - if (ret != EOK || el->num_values != 1) { - DEBUG(SSSDBG_MINOR_FAILURE, - ("No [%s] attribute for group [%s] while id-mapping\n", - opts->group_map[SDAP_AT_GROUP_OBJECTSID].name, - name)); - goto fail; - } - - ret = binary_to_dom_sid(tmpctx, - el->values[0].data, - el->values[0].length, - &dom_sid); - if (ret != EOK) goto fail; - - ret = dom_sid_to_string(tmpctx, dom_sid, &sid_str); - talloc_zfree(dom_sid); + ret = sdap_attrs_get_sid_str( + tmpctx, opts->idmap_ctx, attrs, + opts->group_map[SDAP_AT_GROUP_OBJECTSID].sys_name, + &sid_str); if (ret != EOK) goto fail; /* Add string representation to the cache for easier diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c index b0b533242..ff9905f31 100644 --- a/src/providers/ldap/sdap_async_initgroups.c +++ b/src/providers/ldap/sdap_async_initgroups.c @@ -25,6 +25,7 @@ #include "db/sysdb.h" #include "providers/ldap/sdap_async_private.h" #include "providers/ldap/ldap_common.h" +#include "providers/ldap/sdap_idmap.h" /* ==Save-fake-group-list=====================================*/ static errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb, @@ -44,6 +45,9 @@ static errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb, bool in_transaction = false; bool posix; time_t now; + char *sid_str; + enum idmap_error_code err; + bool use_id_mapping = dp_opt_get_bool(opts->basic, SDAP_ID_MAPPING); /* There are no groups in LDAP but we should add user to groups ?? */ if (ldap_groups_count == 0) return EOK; @@ -104,18 +108,50 @@ 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 == ENOENT || (ret == EOK && gid == 0)) { - DEBUG(9, ("The group %s gid was %s\n", - name, ret == ENOENT ? "missing" : "zero")); - DEBUG(8, ("Marking group %s as non-posix and setting GID=0!\n", name)); - gid = 0; - posix = false; - } else if (ret) { - DEBUG(1, ("The GID attribute is malformed\n")); - goto fail; + + if (use_id_mapping) { + DEBUG(SSSDBG_TRACE_LIBS, + ("Mapping group [%s] objectSID to unix ID\n", name)); + + ret = sdap_attrs_get_sid_str( + tmp_ctx, opts->idmap_ctx, ldap_groups[ai], + opts->group_map[SDAP_AT_GROUP_OBJECTSID].sys_name, + &sid_str); + if (ret != EOK) goto fail; + + DEBUG(SSSDBG_TRACE_INTERNAL, + ("Group [%s] has objectSID [%s]\n", + name, sid_str)); + + /* Convert the SID into a UNIX group ID */ + err = sss_idmap_sid_to_unix(opts->idmap_ctx->map, + sid_str, + (uint32_t *)&gid); + if (err != IDMAP_SUCCESS && err != IDMAP_NO_DOMAIN) { + DEBUG(SSSDBG_MINOR_FAILURE, + ("Could not convert objectSID [%s] to a UNIX ID\n", + sid_str)); + ret = EIO; + goto fail; + } + + DEBUG(SSSDBG_TRACE_INTERNAL, + ("Group [%s] has mapped gid [%lu]\n", + name, (unsigned long)gid)); + } else { + ret = sysdb_attrs_get_uint32_t(ldap_groups[ai], + SYSDB_GIDNUM, + &gid); + if (ret == ENOENT || (ret == EOK && gid == 0)) { + DEBUG(9, ("The group %s gid was %s\n", + name, ret == ENOENT ? "missing" : "zero")); + DEBUG(8, ("Marking group %s as non-posix and setting GID=0!\n", name)); + gid = 0; + posix = false; + } else if (ret) { + DEBUG(1, ("The GID attribute is malformed\n")); + goto fail; + } } ret = sysdb_attrs_get_string(ldap_groups[ai], @@ -2627,6 +2663,11 @@ static void sdap_get_initgr_user(struct tevent_req *subreq) break; case SDAP_SCHEMA_RFC2307BIS: + case SDAP_SCHEMA_AD: + /* TODO: AD uses a different member/memberof schema + * We need an AD specific call that is able to unroll + * nested groups by doing extensive recursive searches */ + ret = sysdb_attrs_get_string(state->orig_user, SYSDB_ORIG_DN, &orig_dn); @@ -2647,11 +2688,6 @@ static void sdap_get_initgr_user(struct tevent_req *subreq) tevent_req_set_callback(subreq, sdap_get_initgr_done, req); break; case SDAP_SCHEMA_IPA_V1: - case SDAP_SCHEMA_AD: - /* TODO: AD uses a different member/memberof schema - * We need an AD specific call that is able to unroll - * nested groups by doing extensive recursive searches */ - subreq = sdap_initgr_nested_send(state, state->ev, state->opts, state->sysdb, state->dom, state->sh, state->orig_user, state->grp_attrs); @@ -2677,11 +2713,24 @@ static void sdap_get_initgr_done(struct tevent_req *subreq) struct sdap_get_initgr_state *state = tevent_req_data(req, struct sdap_get_initgr_state); int ret; + TALLOC_CTX *tmp_ctx; gid_t primary_gid; char *gid; + char *sid_str; + char *dom_sid_str; + char *group_sid_str; + enum idmap_error_code err; + struct sdap_options *opts = state->opts; + bool use_id_mapping = dp_opt_get_bool(opts->basic, SDAP_ID_MAPPING); DEBUG(9, ("Initgroups done\n")); + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + tevent_req_error(req, ENOMEM); + return; + } + switch (state->opts->schema_type) { case SDAP_SCHEMA_RFC2307: ret = sdap_initgr_rfc2307_recv(subreq); @@ -2706,35 +2755,102 @@ static void sdap_get_initgr_done(struct tevent_req *subreq) if (ret) { DEBUG(9, ("Error in initgroups: [%d][%s]\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; + goto fail; } /* We also need to update the user's primary group, since * the user may not be an explicit member of that group */ - ret = sysdb_attrs_get_uint32_t(state->orig_user, SYSDB_GIDNUM, &primary_gid); - if (ret != EOK) { - DEBUG(6, ("Could not find user's primary GID\n")); - tevent_req_error(req, ret); - return; + + if (use_id_mapping) { + DEBUG(SSSDBG_TRACE_LIBS, + ("Mapping primary group to unix ID\n")); + + /* The primary group ID is just the RID part of the objectSID + * of the group. Generate the GID by adding this to the domain + * SID value. + */ + + /* Get the user SID so we can extract the domain SID + * from it. + */ + ret = sdap_attrs_get_sid_str( + tmp_ctx, opts->idmap_ctx, state->orig_user, + opts->user_map[SDAP_AT_USER_OBJECTSID].sys_name, + &sid_str); + if (ret != EOK) goto fail; + + /* Get the domain SID from the user SID */ + ret = sdap_idmap_get_dom_sid_from_object(tmp_ctx, sid_str, + &dom_sid_str); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + ("Could not parse domain SID from [%s]\n", sid_str)); + goto fail; + } + + ret = sysdb_attrs_get_uint32_t( + state->orig_user, + opts->user_map[SDAP_AT_USER_PRIMARY_GROUP].sys_name, + &primary_gid); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + ("no primary group ID provided\n")); + ret = EINVAL; + goto fail; + } + + /* Add the RID to the end */ + group_sid_str = talloc_asprintf(tmp_ctx, "%s-%lu", + dom_sid_str, + (unsigned long)primary_gid); + if (!group_sid_str) { + ret = ENOMEM; + goto fail; + } + + /* Convert the SID into a UNIX group ID */ + err = sss_idmap_sid_to_unix(opts->idmap_ctx->map, + sid_str, + (uint32_t *)&primary_gid); + if (err != IDMAP_SUCCESS) { + DEBUG(SSSDBG_MINOR_FAILURE, + ("Could not convert objectSID [%s] to a UNIX ID\n", + sid_str)); + ret = EIO; + goto fail; + } + } else { + ret = sysdb_attrs_get_uint32_t(state->orig_user, SYSDB_GIDNUM, + &primary_gid); + if (ret != EOK) { + DEBUG(6, ("Could not find user's primary GID\n")); + goto fail; + } } gid = talloc_asprintf(state, "%lu", (unsigned long)primary_gid); if (gid == NULL) { - tevent_req_error(req, ENOMEM); - return; + ret = ENOMEM; + goto fail; } subreq = groups_get_send(req, state->ev, state->id_ctx, gid, BE_FILTER_IDNUM, BE_ATTR_ALL); if (!subreq) { - tevent_req_error(req, ENOMEM); - return; + ret = ENOMEM; + goto fail; } tevent_req_set_callback(subreq, sdap_get_initgr_pgid, req); + talloc_free(tmp_ctx); tevent_req_done(req); + return; + +fail: + talloc_free(tmp_ctx); + tevent_req_error(req, ret); + return; } static void sdap_get_initgr_pgid(struct tevent_req *subreq) diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c index c6534993a..c894e874b 100644 --- a/src/providers/ldap/sdap_async_users.c +++ b/src/providers/ldap/sdap_async_users.c @@ -56,7 +56,6 @@ int sdap_save_user(TALLOC_CTX *memctx, char **missing = NULL; TALLOC_CTX *tmpctx = NULL; bool use_id_mapping = dp_opt_get_bool(opts->basic, SDAP_ID_MAPPING); - struct dom_sid *dom_sid; char *sid_str; char *dom_sid_str = NULL; char *group_sid_str; @@ -122,25 +121,10 @@ int sdap_save_user(TALLOC_CTX *memctx, DEBUG(SSSDBG_TRACE_LIBS, ("Mapping user [%s] objectSID to unix ID\n", name)); - ret = sysdb_attrs_get_el(attrs, - opts->user_map[SDAP_AT_USER_OBJECTSID].sys_name, - &el); - if (ret != EOK || el->num_values != 1) { - DEBUG(SSSDBG_MINOR_FAILURE, - ("No [%s] attribute for user [%s] while id-mapping. [%d][%s]\n", - opts->user_map[SDAP_AT_USER_OBJECTSID].name, - name, el->num_values, strerror(ret))); - goto fail; - } - - ret = binary_to_dom_sid(tmpctx, - el->values[0].data, - el->values[0].length, - &dom_sid); - if (ret != EOK) goto fail; - - ret = dom_sid_to_string(tmpctx, dom_sid, &sid_str); - talloc_zfree(dom_sid); + ret = sdap_attrs_get_sid_str( + tmpctx, opts->idmap_ctx, attrs, + opts->user_map[SDAP_AT_USER_OBJECTSID].sys_name, + &sid_str); if (ret != EOK) goto fail; /* Add string representation to the cache for easier -- cgit