summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2016-09-07 11:36:51 +0200
committerSumit Bose <sbose@redhat.com>2016-09-07 12:42:35 +0200
commit254eeea82141851f3ff450d9a7e1b006f1929b76 (patch)
tree9dca5e07e7cea5be56b45b5fd86fafbc43215bd4
parent3f6aecfe5061e165c10829142854ec7189029407 (diff)
downloadsssd-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.h1
-rw-r--r--src/providers/ldap/sdap_async.h11
-rw-r--r--src/providers/ldap/sdap_async_initgroups.c168
-rw-r--r--src/providers/ldap/sdap_async_initgroups_ad.c239
-rw-r--r--src/providers/ldap/sdap_async_private.h15
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_ */