diff options
author | Sumit Bose <sbose@redhat.com> | 2016-09-07 11:36:51 +0200 |
---|---|---|
committer | Sumit Bose <sbose@redhat.com> | 2016-09-07 12:42:35 +0200 |
commit | 254eeea82141851f3ff450d9a7e1b006f1929b76 (patch) | |
tree | 9dca5e07e7cea5be56b45b5fd86fafbc43215bd4 | |
parent | 3f6aecfe5061e165c10829142854ec7189029407 (diff) | |
download | sssd-ad_domain_local_groups.tar.gz sssd-ad_domain_local_groups.tar.xz sssd-ad_domain_local_groups.zip |
-rw-r--r-- | src/db/sysdb.h | 1 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async.h | 11 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_initgroups.c | 168 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_initgroups_ad.c | 239 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_private.h | 15 |
5 files changed, 427 insertions, 7 deletions
diff --git a/src/db/sysdb.h b/src/db/sysdb.h index 8713efa6e..339799160 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -224,6 +224,7 @@ SYSDB_OVERRIDE_DN, \ SYSDB_OVERRIDE_OBJECT_DN, \ SYSDB_DEFAULT_OVERRIDE_NAME, \ + SYSDB_ORIG_DN, \ NULL} #define SYSDB_GRSRC_ATTRS {SYSDB_NAME, SYSDB_GIDNUM, \ diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h index 2ebde6b83..9d5207714 100644 --- a/src/providers/ldap/sdap_async.h +++ b/src/providers/ldap/sdap_async.h @@ -391,4 +391,15 @@ sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx, errno_t sdap_ad_tokengroups_initgroups_recv(struct tevent_req *req); +struct tevent_req * +sdap_ad_get_domain_local_groups_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sdap_id_conn_ctx *conn, + struct sdap_options *opts, + struct sysdb_ctx *sysdb, + struct sss_domain_info *dom, + struct sdap_search_base **search_bases, + struct sysdb_attrs **groups, + size_t num_groups); +errno_t sdap_ad_get_domain_local_groups_recv(struct tevent_req *req); #endif /* _SDAP_ASYNC_H_ */ diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c index f9593f0df..dffd0a5d4 100644 --- a/src/providers/ldap/sdap_async_initgroups.c +++ b/src/providers/ldap/sdap_async_initgroups.c @@ -28,6 +28,8 @@ #include "providers/ldap/sdap_idmap.h" #include "providers/ldap/sdap_users.h" +#include "providers/ad/ad_common.h" + /* ==Save-fake-group-list=====================================*/ errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb, struct sss_domain_info *domain, @@ -622,7 +624,7 @@ static int sdap_initgr_rfc2307_recv(struct tevent_req *req) } /* ==Common code for pure RFC2307bis and IPA/AD========================= */ -static errno_t +errno_t sdap_nested_groups_store(struct sysdb_ctx *sysdb, struct sss_domain_info *domain, struct sdap_options *opts, @@ -1564,7 +1566,7 @@ struct tevent_req *rfc2307bis_nested_groups_send( struct sdap_search_base **search_bases, struct sysdb_attrs **groups, size_t num_groups, hash_table_t *group_hash, size_t nesting); -static errno_t rfc2307bis_nested_groups_recv(struct tevent_req *req); +errno_t rfc2307bis_nested_groups_recv(struct tevent_req *req); static struct tevent_req *sdap_initgr_rfc2307bis_send( TALLOC_CTX *memctx, @@ -2613,7 +2615,7 @@ static void rfc2307bis_nested_groups_process(struct tevent_req *subreq) tevent_req_set_callback(subreq, rfc2307bis_nested_groups_done, req); } -static errno_t rfc2307bis_nested_groups_recv(struct tevent_req *req) +errno_t rfc2307bis_nested_groups_recv(struct tevent_req *req) { TEVENT_REQ_RETURN_ON_ERROR(req); return EOK; @@ -3074,6 +3076,124 @@ fail: tevent_req_error(req, ret); } +static void sdap_ad_check_domain_local_groups_done(struct tevent_req *subreq); + +errno_t sdap_ad_check_domain_local_groups(struct tevent_req *req) +{ + struct sdap_get_initgr_state *state = tevent_req_data(req, + struct sdap_get_initgr_state); + int ret; + struct ad_id_ctx *ad_id_ctx; + struct sdap_domain *local_sdom; + struct sdap_id_conn_ctx *local_conn; + const char *orig_name; + const char *sysdb_name; + struct ldb_result *res; + struct tevent_req *subreq; + struct sysdb_attrs **groups; + + /* We only need to check for domain local groups in the AD case and if the + * user is not from our domain, i.e. if the user comes from a sub-domain. + */ + if (state->opts->schema_type != SDAP_SCHEMA_AD + || !IS_SUBDOMAIN(state->dom)) { + return EOK; + } + + local_sdom = sdap_domain_get(state->id_ctx->opts, state->dom->parent); + if (local_sdom == NULL || local_sdom->pvt == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "No ID ctx available for [%s].\n", + state->dom->parent->name); + return EINVAL; + } + ad_id_ctx = talloc_get_type(local_sdom->pvt, struct ad_id_ctx); + local_conn = ad_id_ctx->ldap_ctx; + +#if 0 + if (state->sdom->pvt == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "AD specific connection data is missing, " + "cannot lookup domain local groups.\n"); + return EINVAL; + } + + ad_id_ctx = state->sdom->pvt; + + local_conn = ad_get_dom_ldap_conn(ad_id_ctx, state->dom->parent); + if (local_conn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "No connection to local DC available, " + "cannot lookup domain local groups.\n"); + return EINVAL; + } +#endif + + ret = sysdb_attrs_get_string(state->orig_user, SYSDB_NAME, &orig_name); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Missing name in user object.\n"); + return ret; + } + + sysdb_name = sss_create_internal_fqname(state, orig_name, state->dom->name); + if (sysdb_name == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "sss_create_internal_fqname failed.\n"); + return ENOMEM; + } + + ret = sysdb_initgroups(state, state->dom, sysdb_name, &res); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_initgroups failed for user [%s].\n", + sysdb_name); + return ret; + } + + if (res->count == 0) { + DEBUG(SSSDBG_CRIT_FAILURE, + "sysdb_initgroups returned no results for user [%s].\n", + sysdb_name); + return EINVAL; + } + + /* The user object, the first entry in the res->msgs, is included as well + * to cover the case where the remote user is directly added to + * a domain local group. */ + ret = sysdb_msg2attrs(state, res->count, res->msgs, &groups); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_msg2attrs failed.\n"); + return ret; + } + + subreq = sdap_ad_get_domain_local_groups_send(state, state->ev, local_conn, + state->opts, state->sysdb, state->dom->parent, + local_conn->id_ctx->opts->sdom->group_search_bases, + groups, res->count); + if (subreq == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "sdap_ad_get_domain_local_groups_send failed.\n"); + return ENOMEM; + } + + tevent_req_set_callback(subreq, sdap_ad_check_domain_local_groups_done, + req); + + return EAGAIN; +} + +static void sdap_ad_check_domain_local_groups_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + int ret; + + ret = sdap_ad_get_domain_local_groups_recv(subreq); + talloc_zfree(subreq); + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); + + return; +} + static void sdap_get_initgr_pgid(struct tevent_req *req); static void sdap_get_initgr_done(struct tevent_req *subreq) { @@ -3206,8 +3326,6 @@ static void sdap_get_initgr_done(struct tevent_req *subreq) if (ret == EOK) { DEBUG(SSSDBG_TRACE_FUNC, "Primary group already cached, nothing to do.\n"); - ret = EOK; - goto done; } else { gid = talloc_asprintf(state, "%lu", (unsigned long)primary_gid); if (gid == NULL) { @@ -3224,10 +3342,28 @@ static void sdap_get_initgr_done(struct tevent_req *subreq) goto done; } tevent_req_set_callback(subreq, sdap_get_initgr_pgid, req); + + talloc_free(tmp_ctx); + return; } - talloc_free(tmp_ctx); - return; + ret = sdap_ad_check_domain_local_groups(req); + if (ret == EAGAIN) { + DEBUG(SSSDBG_TRACE_ALL, + "Checking for domain local group memberships.\n"); + talloc_free(tmp_ctx); + return; + } else if (ret == EOK) { + DEBUG(SSSDBG_TRACE_ALL, + "No need to check for domain local group memberships.\n"); + } else { + DEBUG(SSSDBG_OP_FAILURE, + "sdap_ad_check_domain_local_groups failed, " + "meberships to domain local groups might be missing.\n"); + /* do not let the request fail completely because we already have at + * least "some" groups */ + ret = EOK; + } done: talloc_free(tmp_ctx); @@ -3252,7 +3388,25 @@ static void sdap_get_initgr_pgid(struct tevent_req *subreq) return; } + ret = sdap_ad_check_domain_local_groups(req); + if (ret == EAGAIN) { + DEBUG(SSSDBG_TRACE_ALL, + "Checking for domain local group memberships.\n"); + return; + } else if (ret == EOK) { + DEBUG(SSSDBG_TRACE_ALL, + "No need to check for domain local group memberships.\n"); + } else { + DEBUG(SSSDBG_OP_FAILURE, "sdap_ad_check_domain_local_groups failed.\n"); + DEBUG(SSSDBG_OP_FAILURE, + "sdap_ad_check_domain_local_groups failed, " + "meberships to domain local groups might be missing.\n"); + /* do not let the request fail completely because we already have at + * least "some" groups */ + } + tevent_req_done(req); + return; } int sdap_get_initgr_recv(struct tevent_req *req) diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c index ad54c1fb8..802c68871 100644 --- a/src/providers/ldap/sdap_async_initgroups_ad.c +++ b/src/providers/ldap/sdap_async_initgroups_ad.c @@ -1412,6 +1412,245 @@ static errno_t sdap_ad_tokengroups_initgr_posix_recv(struct tevent_req *req) return EOK; } +struct sdap_ad_get_domain_local_groups_state { + struct tevent_context *ev; + //struct sdap_id_ctx *ctx; + struct sdap_id_conn_ctx *conn; + struct sdap_options *opts; + struct sdap_id_op *op; + struct sysdb_ctx *sysdb; + struct sss_domain_info *dom; + int dp_error; + + struct sdap_search_base **search_bases; + struct sysdb_attrs **groups; + size_t num_groups; + hash_table_t *group_hash; +}; + +static void +sdap_ad_get_domain_local_groups_connect_done(struct tevent_req *subreq); +static void sdap_ad_get_domain_local_groups_done(struct tevent_req *subreq); + +struct tevent_req * +sdap_ad_get_domain_local_groups_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sdap_id_conn_ctx *conn, + struct sdap_options *opts, + struct sysdb_ctx *sysdb, + struct sss_domain_info *dom, + struct sdap_search_base **search_bases, + struct sysdb_attrs **groups, + size_t num_groups) +{ + struct sdap_ad_get_domain_local_groups_state *state; + struct tevent_req *req; + struct tevent_req *subreq; + errno_t ret; + + req = tevent_req_create(mem_ctx, &state, + struct sdap_ad_get_domain_local_groups_state); + if (req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); + return NULL; + } + + state->ev = ev; + state->conn = conn; + state->opts = opts; + state->sysdb = sysdb; + state->dom = dom; + state->search_bases = search_bases; + state->groups = groups; + state->num_groups = num_groups; + + ret = sss_hash_create(state, 32, &state->group_hash); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sss_hash_create failed.\n"); + goto fail; + } + + state->op = sdap_id_op_create(state, state->conn->conn_cache); + if (state->op == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); + ret = ENOMEM; + goto fail; + } + + subreq = sdap_id_op_connect_send(state->op, state, &ret); + if (subreq == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed.\n"); + goto fail; + } + + tevent_req_set_callback(subreq, + sdap_ad_get_domain_local_groups_connect_done, req); + + return req; + +fail: + tevent_req_error(req, ret); + tevent_req_post(req, ev); + return req; +} + +static void +sdap_ad_get_domain_local_groups_connect_done(struct tevent_req *subreq) +{ + + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct sdap_ad_get_domain_local_groups_state *state = tevent_req_data(req, + struct sdap_ad_get_domain_local_groups_state); + int dp_error = DP_ERR_FATAL; + int ret; + + ret = sdap_id_op_connect_recv(subreq, &dp_error); + talloc_zfree(subreq); + + if (ret != EOK) { + state->dp_error = dp_error; + tevent_req_error(req, ret); + return; + } + subreq = rfc2307bis_nested_groups_send(state, state->ev, state->opts, + state->sysdb, state->dom, + sdap_id_op_handle(state->op), + state->search_bases, + state->groups, state->num_groups, + state->group_hash, 0); + if (subreq == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "rfc2307bis_nested_groups_send failed.\n"); + state->dp_error = DP_ERR_FATAL; + tevent_req_error(req, ENOMEM); + return; + } + + tevent_req_set_callback(subreq, + sdap_ad_get_domain_local_groups_done, req); + + return; +} + +struct sdap_nested_group { + struct sysdb_attrs *group; + struct sysdb_attrs **ldap_parents; + size_t parents_count; +}; + +static void sdap_ad_get_domain_local_groups_done(struct tevent_req *subreq) +{ + + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct sdap_ad_get_domain_local_groups_state *state = tevent_req_data(req, + struct sdap_ad_get_domain_local_groups_state); + int ret; + int hret; + unsigned long count; + hash_value_t *values; + struct sysdb_attrs **groups = NULL; + struct sdap_nested_group *gr; + size_t c; + size_t d; + char **groupnamelist; + const char *sysdb_username; + size_t parents_count = 0; + size_t pc; + + ret = rfc2307bis_nested_groups_recv(subreq); + talloc_zfree(subreq); + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + /* FIXME: the resolved groups, if any, must still be saved. */ + hret = hash_values(state->group_hash, &count, &values); + if (hret != HASH_SUCCESS) { + DEBUG(SSSDBG_OP_FAILURE, "hash_values failed.\n"); + ret = EIO; + goto done; + } + + for (c = 0; c < count; c++) { + gr = talloc_get_type(values[c].ptr, struct sdap_nested_group); + parents_count += gr->parents_count; + } + + if (parents_count == 0) { + DEBUG(SSSDBG_TRACE_ALL, "No domain local groups found.\n"); + ret = EOK; + goto done; + } + + groups = talloc_array(state, struct sysdb_attrs *, parents_count); + if (groups == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n"); + ret = ENOMEM; + goto done; + } + + pc = 0; + for (c = 0; c < count; c++) { + gr = talloc_get_type(values[c].ptr, + struct sdap_nested_group); + for (d = 0; d < gr->parents_count; d++) { + groups[pc++] = gr->ldap_parents[d]; + } + } + talloc_zfree(values); + + ret = sdap_nested_groups_store(state->sysdb, state->dom, state->opts, + groups, parents_count); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, "Could not save groups [%d]: %s\n", + ret, strerror(ret)); + goto done; + } + + ret = sysdb_attrs_primary_fqdn_list(state->dom, state, + groups, parents_count, + state->opts->group_map[SDAP_AT_GROUP_NAME].name, + &groupnamelist); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_primary_fqdn_list failed.\n"); + goto done; + } + + ret = sysdb_attrs_get_string(state->groups[0], SYSDB_NAME, &sysdb_username); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "sysdb_attrs_get_string failed to get SYSDB_NAME.\n"); + goto done; + } + + DEBUG(SSSDBG_TRACE_INTERNAL, "Updating domain local memberships for %s\n", + sysdb_username); + ret = sysdb_update_members(state->dom, sysdb_username, SYSDB_MEMBER_USER, + (const char *const *) groupnamelist, NULL); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_members failed.\n"); + goto done; + } + + ret = EOK; +done: + if (ret == EOK) { + tevent_req_done(req); + } else { + tevent_req_error(req, ret); + } + + return; +} + +errno_t sdap_ad_get_domain_local_groups_recv(struct tevent_req *req) +{ + TEVENT_REQ_RETURN_ON_ERROR(req); + return EOK; +} + struct sdap_ad_tokengroups_initgroups_state { bool use_id_mapping; struct sss_domain_info *domain; diff --git a/src/providers/ldap/sdap_async_private.h b/src/providers/ldap/sdap_async_private.h index f09ddb71f..e11e959fd 100644 --- a/src/providers/ldap/sdap_async_private.h +++ b/src/providers/ldap/sdap_async_private.h @@ -157,4 +157,19 @@ errno_t sdap_check_ad_group_type(struct sss_domain_info *dom, struct sysdb_attrs *group_attrs, const char *group_name, bool *_need_filter); + +struct tevent_req *rfc2307bis_nested_groups_send( + TALLOC_CTX *mem_ctx, struct tevent_context *ev, + struct sdap_options *opts, struct sysdb_ctx *sysdb, + struct sss_domain_info *dom, struct sdap_handle *sh, + struct sdap_search_base **search_bases, + struct sysdb_attrs **groups, size_t num_groups, + hash_table_t *group_hash, size_t nesting); +errno_t rfc2307bis_nested_groups_recv(struct tevent_req *req); + +errno_t sdap_nested_groups_store(struct sysdb_ctx *sysdb, + struct sss_domain_info *domain, + struct sdap_options *opts, + struct sysdb_attrs **groups, + unsigned long count); #endif /* _SDAP_ASYNC_PRIVATE_H_ */ |