On Fri, Jan 24, 2014 at 08:31:00PM +0100, Jakub Hrozek wrote:
On Wed, Jan 22, 2014 at 03:26:07PM +0100, Jakub Hrozek wrote:
> On Wed, Jan 22, 2014 at 12:02:34AM +0100, Jakub Hrozek wrote:
> > On Fri, Jan 10, 2014 at 02:54:46PM +0100, Sumit Bose wrote:
> > > On Fri, Jan 10, 2014 at 02:35:12PM +0100, Jakub Hrozek wrote:
> > > > On Fri, Jan 10, 2014 at 12:59:05PM +0100, Sumit Bose wrote:
> > > > > On Tue, Dec 17, 2013 at 09:00:25PM +0100, Jakub Hrozek wrote:
> > > > > > Hi,
> > > > > >
> > > > > > the attached patches address ticket
> > > > > >
https://fedorahosted.org/sssd/ticket/2142
> > > > > >
> > > > > > There are some things I'm still not satisfied with and
one of them is
> > > > > > refreshing subdomains. Currently the subdomain refresh
happens after
> > > > > > startup and then only if a direct lookup for a user or
group happens and
> > > > > > the timeout for subdomain refresh is over. So in theory
it's possible
> > > > > > that the user and group objects will be refreshed by the
enumeration
> > > > > > task only and there would be no lookup to trigger the
subdomain refresh.
> > > > > >
> > > > > > With master domain enumeration we've solved this
problem by
> > > > > > re-downloading master domain info before the enumeration
request. We
> > > > > > could do something similar with subdomains (although a
little more
> > > > > > involved becase there is always precisely one subdomain),
but I didn't
> > > > > > like doing all the changes in 1.11.3. I can code up
additional patch
> > > > > > only for master, though.
> > > > > >
> > > > > > Something similar is with fallback from GC to LDAP.
Although here I'm
> > > > > > not convinced we need to perform the fallback at all, since
there are
> > > > > > already patches on the list that implement the option to
disable GC
> > > > > > lookups and there will also be a patch to autodetect POSIX
attributes in
> > > > > > GC.
> > > > > >
> > > > > > These patches must be applied on top of my previous
patches.
> > > > >
> > > > > Can you rebase these patches and their prerequisites? They do
not apply
> > > > > to master anymore. I also cloud not apply "AD: Retry and
terminate
> > > > > sdap_id_op if possible".
> >
> > Hi,
> >
> > the "AD: Retry and terminate sdap_id_op if possible" patch is not
> > strictly required, so I haven't rebased and resent it yet.
> >
> > > >
> > > > Sure, will do.
> > > >
> > > > >
> > > > > Based on the experience with AD group-memberships and the
recent
> > > > > changes where we switch back from GC to LDAP to determine
> > > > > group-memberships I would suggest to use the LDAP connect for
the group
> > > > > enumeration as well.
> > > >
> > > > The last word in a private mini-thread with Simo was to use LDAP for
the
> > > > parent domain by default and GC elsewhere, right? I would also like
to
> > > > check all code is consistent when changing these patches.
> > >
> > > I think in the general only universal group can be retrieve correctly
> > > form the GC. If we read LDAP for the parent domain there are still the
> > > global groups from the other domains which might be incomplete in the
> > > GC.
> >
> > I've been testing the enumeration quite a bit and unfortunately I
> > found a defect that is not so easily fixed with the current enumeration
> > architecture. Because the original patches enumerated the primary domain and
> > subdomain separately, cross-domain memberships were hard, if not impossible
> > to maintain, at least because there was no guarantee on the order or
> > completeness of enumeration.
> >
> > So attached are rebased the original patches with the connections fixed
> > as you liked. But cross-domain memberships don't work.
> >
> > I have two additional patches, one finished and one WIP in my ad_enum branch:
> >
http://fedorapeople.org/cgit/jhrozek/public_git/sssd.git/log/?h=ad_enum
> >
> > The first makes sure the original_member contains the original DN and
> > not sysdb DN :-) The other is not finished but my intent was to
> > 1) check if any subdomains were enumerated. If not, do nothing
> > 2) if any of the groups saved had more original members than sysdb
> > members, check if members of these groups can be linked now that all
> > users and groups are saved.
> >
> > I hope this would be acceptable, because the cost is only incurred if
> > subdomains are enumerated and there are cross-domain memberships at the
> > same time.. Any other solution I could think of would require bigger
> > changes, but I'd welcome other ideas.
>
> Hi,
>
> all patches are attached now. With the attached patches, even
> cross-domain memberships are established in my testing if enumeration is
> on.
Hi,
Sumit found a rather embarrasing bug in the code, where a tevent_req was
terminated even if it shouldn't. I guess my testing only went fine
because the server and client are really close to one another and thus
the request completed quickly.
Thank you for the review. A new set of patches is attached.
Patches 1, 2, 3 and 5 are looking good.
In patch 4 you add ad_enum_subdom_send() and ad_enum_subdom_done()
(without calling them) and in patch 6 you remove them again.
Other comments for patch 6 are inline.
bye,
Sumit
From 066ce9945b6af3748f0ead06213f0180a742c542 Mon Sep 17 00:00:00
2001
From: Jakub Hrozek <jhrozek(a)redhat.com>
Date: Wed, 22 Jan 2014 15:21:24 +0100
Subject: [PATCH 6/6] AD: Establish cross-domain memberships after enumeration
finishes
Because domain enumeration currently works for each domain separately,
the code has to establish cross-domain memberships after all domains are
enumerated. The code works as follows:
1) check if any *sub*domains were enumerated. If not, do nothing
2) if any of the groups saved had more original members than
sysdb members, check if members of these groups can be linked now
that all users and groups are saved using the orig_member
attribute of the group matched against originalDN member of the
user.
Related:
https://fedorahosted.org/sssd/ticket/2142
---
src/providers/ad/ad_id.c | 515 +++++++++++++++++++++++++++++++++++------------
1 file changed, 390 insertions(+), 125 deletions(-)
diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
index 1bdacf74f0e6de2120603401bcf115549a03ac4f..8818869f73be4afa8b36c0da0341391b569aafd2
100644
--- a/src/providers/ad/ad_id.c
+++ b/src/providers/ad/ad_id.c
@@ -420,10 +420,13 @@ struct ad_enumeration_state {
struct tevent_context *ev;
struct sdap_domain *sdom;
+ struct sdap_domain *sditer;
};
static void ad_enumeration_conn_done(struct tevent_req *subreq);
static void ad_enumeration_master_done(struct tevent_req *subreq);
+static errno_t ad_enum_sdom(struct tevent_req *req, struct sdap_domain *sd,
+ struct ad_id_ctx *id_ctx);
static void ad_enumeration_done(struct tevent_req *subreq);
struct tevent_req *
@@ -452,6 +455,7 @@ ad_enumeration_send(TALLOC_CTX *mem_ctx,
state->ectx = ectx;
state->ev = ev;
state->sdom = ectx->sdom;
+ state->sditer = state->sdom;
state->id_ctx = talloc_get_type(ectx->pvt, struct ad_id_ctx);
state->sdap_op = sdap_id_op_create(state,
@@ -526,7 +530,6 @@ ad_enumeration_master_done(struct tevent_req *subreq)
char *flat_name;
char *master_sid;
char *forest;
- struct sdap_id_conn_ctx *user_conn;
ret = ad_master_domain_recv(subreq, state,
&flat_name, &master_sid, &forest);
@@ -545,32 +548,57 @@ ad_enumeration_master_done(struct tevent_req *subreq)
return;
}
- if (dp_opt_get_bool(state->id_ctx->ad_options->basic, AD_ENABLE_GC)) {
- user_conn = state->id_ctx->gc_ctx;
+ ret = ad_enum_sdom(req, state->sdom, state->id_ctx);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("Could not enumerate domain %s\n",
state->sdom->dom->name));
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ /* Execution will resume in ad_enumeration_done */
+}
+
+static errno_t
+ad_enum_sdom(struct tevent_req *req,
+ struct sdap_domain *sd,
+ struct ad_id_ctx *id_ctx)
+{
+ struct sdap_id_conn_ctx *user_conn;
+ struct tevent_req *subreq;
+ struct ad_enumeration_state *state = tevent_req_data(req,
+ struct ad_enumeration_state);
+
+ if (dp_opt_get_bool(id_ctx->ad_options->basic, AD_ENABLE_GC)) {
+ user_conn = id_ctx->gc_ctx;
} else {
- user_conn = state->id_ctx->ldap_ctx;
+ user_conn = id_ctx->ldap_ctx;
}
/* Groups are searched for in LDAP, users in GC. Services (if present,
* which is unlikely in AD) from LDAP as well
*/
subreq = sdap_dom_enum_ex_send(state, state->ev,
- state->id_ctx->sdap_id_ctx,
- state->sdom,
- user_conn, /* Users */
- state->id_ctx->ldap_ctx, /* Groups */
- state->id_ctx->ldap_ctx); /* Services */
+ id_ctx->sdap_id_ctx,
+ sd,
+ user_conn, /* Users */
+ id_ctx->ldap_ctx, /* Groups */
+ id_ctx->ldap_ctx); /* Services */
if (subreq == NULL) {
/* The ptask API will reschedule the enumeration on its own on
* failure */
DEBUG(SSSDBG_OP_FAILURE,
("Failed to schedule enumeration, retrying later!\n"));
- tevent_req_error(req, ENOMEM);
- return;
+ return ENOMEM;
}
tevent_req_set_callback(subreq, ad_enumeration_done, req);
+
+ return EOK;
}
+static errno_t ad_enum_cross_dom_members(struct sdap_options *opts,
+ struct sss_domain_info *dom);
+
static void
ad_enumeration_done(struct tevent_req *subreq)
{
@@ -579,121 +607,8 @@ ad_enumeration_done(struct tevent_req *subreq)
struct tevent_req);
struct ad_enumeration_state *state = tevent_req_data(req,
struct ad_enumeration_state);
-
- ret = sdap_dom_enum_ex_recv(subreq);
- talloc_zfree(subreq);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE,
- ("Could not enumerate domain %s\n",
state->sdom->dom->name));
- tevent_req_error(req, ret);
- return;
- }
-
- tevent_req_done(req);
-}
-
-errno_t
-ad_enumeration_recv(struct tevent_req *req)
-{
- TEVENT_REQ_RETURN_ON_ERROR(req);
- return EOK;
-}
-
-/* Enumerate a subdomain */
-struct ad_enum_subdom_state {
- struct ad_id_ctx *id_ctx;
struct ad_id_ctx *subdom_id_ctx;
- struct ldap_enum_ctx *ectx;
- struct tevent_context *ev;
-
- struct sdap_domain *sdom;
-};
-
-static void ad_enum_subdom_done(struct tevent_req *subreq);
-
-struct tevent_req *
-ad_enum_subdom_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct be_ctx *be_ctx,
- struct be_ptask *be_ptask,
- void *pvt)
-{
see above.
- struct tevent_req *req;
- struct tevent_req *subreq;
- struct ad_enum_subdom_state *state;
- struct ldap_enum_ctx *ectx;
- errno_t ret;
- struct sdap_id_conn_ctx *user_conn;
-
- req = tevent_req_create(mem_ctx, &state, struct ad_enum_subdom_state);
- if (req == NULL) return NULL;
-
- ectx = talloc_get_type(pvt, struct ldap_enum_ctx);
- if (ectx == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot retrieve ldap_enum_ctx!\n"));
- ret = EFAULT;
- goto fail;
- }
-
- state->ectx = ectx;
- state->ev = ev;
- state->sdom = ectx->sdom;
- state->id_ctx = talloc_get_type(ectx->pvt, struct ad_id_ctx);
- if (state->id_ctx == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot retrieve ad_id_ctx!\n"));
- ret = EFAULT;
- goto fail;
- }
-
- state->subdom_id_ctx = talloc_get_type(state->sdom->pvt, struct
ad_id_ctx);
- if (state->subdom_id_ctx == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot retrieve subdomain
ad_id_ctx!\n"));
- ret = EFAULT;
- goto fail;
- }
-
- if (dp_opt_get_bool(state->id_ctx->ad_options->basic, AD_ENABLE_GC)) {
- user_conn = state->id_ctx->gc_ctx;
- } else {
- user_conn = state->subdom_id_ctx->ldap_ctx;
- }
-
- /* Groups are searched for in LDAP, users in GC. Services (if present,
- * which is unlikely in AD) from LDAP as well
- */
- subreq = sdap_dom_enum_ex_send(state, state->ev,
state->id_ctx->sdap_id_ctx,
- state->sdom,
- user_conn, /* Users */
- state->subdom_id_ctx->ldap_ctx, /* Groups */
- state->subdom_id_ctx->ldap_ctx);/* svcs */
- if (subreq == NULL) {
- /* The ptask API will reschedule the enumeration on its own on
- * failure */
- DEBUG(SSSDBG_OP_FAILURE,
- ("Failed to schedule enumeration, retrying later!\n"));
- ret = ENOMEM;
- goto fail;
- }
- tevent_req_set_callback(subreq, ad_enum_subdom_done, req);
-
- return req;
-
-fail:
- tevent_req_error(req, ret);
- tevent_req_post(req, ev);
- return req;
-}
-
-static void
-ad_enum_subdom_done(struct tevent_req *subreq)
-{
- errno_t ret;
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct ad_enum_subdom_state *state = tevent_req_data(req,
- struct ad_enum_subdom_state);
-
ret = sdap_dom_enum_ex_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
@@ -703,11 +618,361 @@ ad_enum_subdom_done(struct tevent_req *subreq)
return;
}
+ state->sditer = state->sditer->next;
+ if (state->sditer != NULL) {
+ subdom_id_ctx = talloc_get_type(state->sdom->pvt, struct ad_id_ctx);
+ if (subdom_id_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot retrieve subdomain
ad_id_ctx!\n"));
+ tevent_req_error(req, EFAULT);
+ return;
+ }
+
+ ret = ad_enum_sdom(req, state->sditer, state->sditer->pvt);
ret is not checked here as well.
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("Could not enumerate domain %s\n",
state->sditer->dom->name));
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ /* No more subdomains to enumerate. Check if we need to fixup
+ * cross-domain membership
+ */
+ if (state->sditer != state->sdom) {
+ /* We did enumerate at least one subdomain. Walk the subdomains
+ * and fixup members for each of them
+ */
+ for (state->sditer = state->sdom;
+ state->sditer;
+ state->sditer = state->sditer->next) {
+ ret = ad_enum_cross_dom_members(state->id_ctx->ad_options->id,
+ state->sditer->dom);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE, ("Could not check cross-domain "
+ "memberships for %s, group memberships might be "
+ "incomplete!\n", state->sdom->dom->name));
+ continue;
+ }
+ }
+ }
+
tevent_req_done(req);
}
+static errno_t ad_group_extra_members(TALLOC_CTX *mem_ctx,
+ const struct ldb_message *group,
+ struct sss_domain_info *dom,
+ char ***_group_only);
+static errno_t ad_group_add_member(struct sdap_options *opts,
+ struct sss_domain_info *group_domain,
+ struct ldb_dn *group_dn,
+ const char *member);
+
+static errno_t
+ad_enum_cross_dom_members(struct sdap_options *opts,
+ struct sss_domain_info *dom)
+{
+ errno_t ret;
+ errno_t sret;
+ char *filter;
+ TALLOC_CTX *tmp_ctx;
+ const char *attrs[] = {
+ SYSDB_NAME,
+ SYSDB_MEMBER,
+ SYSDB_ORIG_MEMBER,
+ NULL
+ };
+ size_t count, i, mi;
+ struct ldb_message **msgs;
+ bool in_transaction = false;
+ char **group_only;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) return ENOMEM;
+
+ ret = sysdb_transaction_start(dom->sysdb);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n"));
+ goto done;
+ }
+ in_transaction = true;
+
+ filter = talloc_asprintf(tmp_ctx, "(%s=*)", SYSDB_NAME);
+ if (filter == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sysdb_search_groups(tmp_ctx, dom, filter, attrs, &count, &msgs);
+ if (ret != EOK) {
+ goto done;
+ }
You try to process all groups in a domain in a single batch. We might
run into performance/memory issues if there are a lot of groups. But I
think we can keep it as it is for the time being since the easy
workaround is to disable enumeration :-)
+
+ for (i = 0; i < count; i++) {
+ ret = ad_group_extra_members(tmp_ctx, msgs[i], dom, &group_only);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Failed to check extra members\n"));
+ } else if (group_only == NULL) {
+ DEBUG(SSSDBG_TRACE_INTERNAL, ("No extra members\n"));
+ continue;
+ }
+
+ /* Group has extra members */
+ for (mi = 0; group_only[mi]; mi++) {
+ ret = ad_group_add_member(opts, dom, msgs[i]->dn, group_only[mi]);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE, ("Failed to add [%s]: %s\n",
+ group_only[mi], strerror(ret)));
+ continue;
+ }
+ }
+ }
+
+ ret = sysdb_transaction_commit(dom->sysdb);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n"));
+ goto done;
+ }
+ in_transaction = false;
+
+ ret = EOK;
+done:
+ if (in_transaction) {
+ sret = sysdb_transaction_cancel(dom->sysdb);
+ if (sret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Could not cancel transaction\n"));
+ }
+ }
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+static char **
+ad_group_orig_members(TALLOC_CTX *mem_ctx, struct ldb_message_element *om);
+static errno_t
+ad_group_stored_orig_members(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom,
+ struct ldb_dn *dn, char ***_odn_list);
+
+static errno_t
+ad_group_extra_members(TALLOC_CTX *mem_ctx, const struct ldb_message *group,
+ struct sss_domain_info *dom, char ***_group_only)
+{
+ TALLOC_CTX *tmp_ctx;
+ struct ldb_message_element *m, *om;
+ const char *name;
+ errno_t ret;
+ char **sysdb_odn_list;
+ char **group_odn_list;
+ char **group_only = NULL;
+
+ if (_group_only == NULL) return EINVAL;
+ *_group_only = NULL;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) return ENOMEM;
+
+ om = ldb_msg_find_element(group, SYSDB_ORIG_MEMBER);
+ m = ldb_msg_find_element(group, SYSDB_MEMBER);
+ name = ldb_msg_find_attr_as_string(group, SYSDB_NAME, NULL);
+ if (name == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("A group with no name!\n"));
+ ret = EFAULT;
+ goto done;
+ }
+
+ if (om == NULL || om->num_values == 0) {
+ DEBUG(SSSDBG_TRACE_FUNC, ("Group %s has no original members\n",
name));
+ ret = EOK;
+ goto done;
+ }
+
+ if (m == NULL || (m->num_values < om->num_values)) {
+ DEBUG(SSSDBG_TRACE_FUNC,
+ ("Group %s has %d members but %d original members\n",
+ name, m ? m->num_values : 0, om->num_values));
+
+ /* Get the list of originalDN attributes that are already
+ * linked to the group
+ */
+ ret = ad_group_stored_orig_members(tmp_ctx, dom, group->dn,
+ &sysdb_odn_list);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("Could not retrieve list of original members for %s\n",
+ name));
+ goto done;
+ }
+
+ /* Get the list of original DN attributes the group had in AD */
+ group_odn_list = ad_group_orig_members(tmp_ctx, om);
+ if (group_odn_list == NULL) {
+ ret = EFAULT;
+ goto done;
+ }
+
+ /* Compare the two lists */
+ ret = diff_string_lists(tmp_ctx, group_odn_list, sysdb_odn_list,
+ &group_only, NULL, NULL);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("Could not compare lists of members for %s\n", name));
+ goto done;
+ }
+ }
+
+ ret = EOK;
+ *_group_only = talloc_steal(mem_ctx, group_only);
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+static char **
+ad_group_orig_members(TALLOC_CTX *mem_ctx, struct ldb_message_element *om)
this looks like a generic ldb_message_element_to_string_list call. I
would recommend to rename it and maybe move it to utils/ or db/ ebcause
it might be useful for others as well?
+{
+ char **odn_list;
+ size_t i;
+
+ /* Get the list of original DN attributes the group had in AD */
+ odn_list = talloc_zero_array(mem_ctx, char *, om->num_values + 1);
+ if (odn_list == NULL) {
+ return NULL;
+ }
+
+ for (i=0; i < om->num_values; i++) {
+ odn_list[i] = (char *) om->values[i].data;
+ }
+
+ return odn_list;
+}
+
+static errno_t
+ad_group_stored_orig_members(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom,
+ struct ldb_dn *dn, char ***_odn_list)
+{
+ errno_t ret;
+ TALLOC_CTX *tmp_ctx;
+ size_t m_count, i;
+ struct ldb_message **members;
+ const char *attrs[] = {
+ SYSDB_NAME,
+ SYSDB_ORIG_DN,
+ NULL
+ };
+ char **odn_list;
+ const char *odn;
+ size_t oi;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) return ENOMEM;
+
+ /* Get all entries member element points to */
+ ret = sysdb_asq_search(tmp_ctx, dom, dn, NULL, SYSDB_MEMBER,
+ attrs, &m_count, &members);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ odn_list = talloc_zero_array(tmp_ctx, char *, m_count + 1);
+ if (odn_list == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ /* Get a list of their original DNs */
+ oi = 0;
+ for (i = 0; i < m_count; i++) {
+ odn = ldb_msg_find_attr_as_string(members[i], SYSDB_ORIG_DN, NULL);
+ if (odn == NULL) {
+ continue;
+ }
+
+ odn_list[oi] = talloc_strdup(odn_list, odn);
+ if (odn_list[oi] == NULL) {
+ continue;
do you really want to continue if talloc_strdup() fails?
+ }
+ oi++;
+ DEBUG(SSSDBG_TRACE_INTERNAL, ("Member %s already in sysdb\n", odn));
+ }
+
+ ret = EOK;
+ *_odn_list = talloc_steal(mem_ctx, odn_list);
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+static errno_t
+ad_group_add_member(struct sdap_options *opts,
+ struct sss_domain_info *group_domain,
+ struct ldb_dn *group_dn,
+ const char *member)
+{
+ struct sdap_domain *sd;
+ struct ldb_dn *base_dn;
+ TALLOC_CTX *tmp_ctx;
+ errno_t ret;
+ const char *mem_filter;
+ size_t msgs_count;
+ struct ldb_message **msgs;
+
+ /* This member would be from a different domain */
+ sd = sdap_domain_get_by_dn(opts, member);
+ if (sd == NULL) {
+ DEBUG(SSSDBG_MINOR_FAILURE, ("No matching domain for %s\n", member));
+ return ENOENT;
+ }
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) return ENOMEM;
+
+ mem_filter = talloc_asprintf(tmp_ctx, "(%s=%s)",
+ SYSDB_ORIG_DN, member);
+ if (mem_filter == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ base_dn = sysdb_domain_dn(tmp_ctx, sd->dom);
+ if (base_dn == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sysdb_search_entry(tmp_ctx, sd->dom->sysdb, base_dn,
+ LDB_SCOPE_SUBTREE, mem_filter, NULL,
+ &msgs_count, &msgs);
+ if (ret == ENOENT) {
+ DEBUG(SSSDBG_TRACE_FUNC, ("No member [%s] in sysdb\n", member));
+ ret = EOK;
+ goto done;
+ } else if (ret != EOK) {
+ goto done;
+ }
+ DEBUG(SSSDBG_TRACE_INTERNAL, ("[%s] found in sysdb\n", member));
+
+ if (msgs_count != 1) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("Search by orig DN returned %zd results!\n", msgs_count));
+ ret = EFAULT;
+ goto done;
+ }
+
+ ret = sysdb_mod_group_member(group_domain, msgs[0]->dn, group_dn,
SYSDB_MOD_ADD);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Could not add [%s] as a member of [%s]\n",
+ ldb_dn_get_linearized(msgs[0]->dn),
+ ldb_dn_get_linearized(group_dn)));
+ goto done;
+ }
+
+ ret = EOK;
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
errno_t
-ad_enum_subdom_recv(struct tevent_req *req)
+ad_enumeration_recv(struct tevent_req *req)
{
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
--
1.8.4.2
_______________________________________________
sssd-devel mailing list
sssd-devel(a)lists.fedorahosted.org
https://lists.fedorahosted.org/mailman/listinfo/sssd-devel