summaryrefslogtreecommitdiffstats
path: root/src/providers/ldap/sdap_async_accounts.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/providers/ldap/sdap_async_accounts.c')
-rw-r--r--src/providers/ldap/sdap_async_accounts.c315
1 files changed, 284 insertions, 31 deletions
diff --git a/src/providers/ldap/sdap_async_accounts.c b/src/providers/ldap/sdap_async_accounts.c
index 9dfde58f7..0b739c467 100644
--- a/src/providers/ldap/sdap_async_accounts.c
+++ b/src/providers/ldap/sdap_async_accounts.c
@@ -1476,6 +1476,206 @@ int sdap_get_groups_recv(struct tevent_req *req,
return EOK;
}
+/* ==Add-Incomplete-Groups====================================================== */
+struct sdap_add_incomplete_groups_state {
+ struct tevent_context *ev;
+ struct sysdb_ctx *sysdb;
+ struct sysdb_handle *handle;
+ struct sss_domain_info *dom;
+
+ char **groupnames;
+ int cur;
+
+ struct sysdb_attrs **ldap_groups;
+ int ldap_groups_count;
+};
+
+static void sdap_add_incomplete_groups_next(struct tevent_req *subreq);
+static void sdap_add_incomplete_groups_added(struct tevent_req *subreq);
+
+static
+struct tevent_req *sdap_add_incomplete_groups_send(TALLOC_CTX *memctx,
+ struct tevent_context *ev,
+ struct sysdb_ctx *sysdb,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *dom,
+ char **groupnames,
+ struct sysdb_attrs **ldap_groups,
+ int ldap_groups_count)
+{
+ struct tevent_req *req, *subreq;
+ struct sdap_add_incomplete_groups_state *state;
+
+ req = tevent_req_create(memctx, &state, struct sdap_add_incomplete_groups_state);
+ if (!req) return NULL;
+
+ state->ev = ev;
+ state->sysdb = sysdb;
+ state->handle = handle;
+ state->dom = dom;
+ state->groupnames = groupnames;
+ state->ldap_groups = ldap_groups;
+ state->ldap_groups_count = ldap_groups_count;
+ state->cur = 0;
+
+ subreq = sysdb_search_group_by_name_send(state, ev, sysdb, handle, dom,
+ state->groupnames[state->cur],
+ NULL);
+ if (!subreq) {
+ talloc_zfree(req);
+ return NULL;
+ }
+ tevent_req_set_callback(subreq, sdap_add_incomplete_groups_next, req);
+
+ return req;
+}
+
+static void sdap_add_incomplete_groups_next(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sdap_add_incomplete_groups_state *state = tevent_req_data(req,
+ struct sdap_add_incomplete_groups_state);
+ errno_t ret;
+ int ai;
+ const char *name;
+ gid_t gid;
+ struct ldb_message *msg = NULL;
+ struct ldb_message_element *el;
+ struct tevent_req *add_req = NULL;
+ struct tevent_req *next_req = NULL;
+
+ ret = sysdb_search_group_recv(subreq, state, &msg);
+ talloc_zfree(subreq);
+ if (ret == EOK) {
+ state->cur++;
+ if (state->groupnames[state->cur]) {
+ next_req = sysdb_search_group_by_name_send(state, state->ev,
+ state->sysdb,
+ state->handle,
+ state->dom,
+ state->groupnames[state->cur],
+ NULL);
+ if (!next_req) {
+ tevent_req_error(req, EIO);
+ return;
+ }
+ tevent_req_set_callback(next_req, sdap_add_incomplete_groups_next, req);
+ return;
+ }
+
+ tevent_req_done(req);
+ return;
+ } else if (ret == ENOENT) {
+ DEBUG(7, ("Group #%d [%s] is not cached, need to add a incomplete entry\n",
+ state->cur, state->groupnames[state->cur]));
+
+ /* The group is not in sysdb, need to add an incomplete entry */
+ for (ai=0; ai < state->ldap_groups_count; ai++) {
+ ret = sysdb_attrs_get_el(state->ldap_groups[ai],
+ SYSDB_NAME,
+ &el);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
+ if (el->num_values == 0) {
+ tevent_req_error(req, EINVAL);
+ return;
+ }
+ name = (const char *)el->values[0].data;
+
+ if (strcmp(name, state->groupnames[state->cur]) == 0) {
+ ret = sysdb_attrs_get_el(state->ldap_groups[ai],
+ SYSDB_GIDNUM,
+ &el);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
+ if (el->num_values == 0) {
+ DEBUG(1, ("no gid provided for [%s]\n",
+ name));
+ tevent_req_error(req, EINVAL);
+ return;
+ }
+
+ errno = 0;
+ gid = (gid_t) strtol((const char *)el->values[0].data, NULL, 0);
+ if (errno) {
+ tevent_req_error(req, errno);
+ return;
+ }
+
+ add_req = sysdb_add_incomplete_group_send(state,
+ state->ev,
+ state->handle,
+ state->dom,
+ state->groupnames[state->cur],
+ gid);
+ if (add_req == NULL) {
+ tevent_req_error(req, EIO);
+ return;
+ }
+
+ tevent_req_set_callback(add_req,
+ sdap_add_incomplete_groups_added,
+ req);
+ return;
+ }
+ }
+
+ if (ai == state->ldap_groups_count) {
+ tevent_req_error(req, EINVAL);
+ return;
+ }
+ }
+
+ DEBUG(2, ("Search failed: %s (%d)\n", strerror(ret), ret));
+ tevent_req_error(req, ret);
+}
+
+static void sdap_add_incomplete_groups_added(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sdap_add_incomplete_groups_state *state = tevent_req_data(req,
+ struct sdap_add_incomplete_groups_state);
+ errno_t ret;
+ struct tevent_req *next_req = NULL;
+
+ ret = sysdb_add_incomplete_group_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ state->cur++;
+ if (state->groupnames[state->cur]) {
+ next_req = sysdb_search_group_by_name_send(state, state->ev,
+ state->sysdb, state->handle,
+ state->dom,
+ state->groupnames[state->cur],
+ NULL);
+ if (!next_req) {
+ tevent_req_error(req, EIO);
+ return;
+ }
+ tevent_req_set_callback(next_req, sdap_add_incomplete_groups_next, req);
+ return;
+ }
+
+ tevent_req_done(req);
+ return;
+}
+
+int sdap_add_incomplete_groups_recv(struct tevent_req *req)
+{
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ return EOK;
+}
/* ==Initgr-call-(groups-a-user-is-member-of)-RFC2307-Classic/BIS========= */
@@ -1490,6 +1690,12 @@ struct sdap_initgr_rfc2307_state {
struct sysdb_handle *handle;
char **ldap_grouplist;
+ struct sysdb_attrs **ldap_groups;
+ size_t ldap_groups_count;
+
+ char **add_groups;
+ char **del_groups;
+
struct sdap_op *op;
};
@@ -1559,21 +1765,21 @@ static void sdap_initgr_rfc2307_process(struct tevent_req *subreq)
{
struct tevent_req *req;
struct sdap_initgr_rfc2307_state *state;
- struct sysdb_attrs **groups;
- size_t count;
int ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct sdap_initgr_rfc2307_state);
- ret = sdap_get_generic_recv(subreq, state, &count, &groups);
+ ret = sdap_get_generic_recv(subreq, state,
+ &state->ldap_groups_count,
+ &state->ldap_groups);
talloc_zfree(subreq);
if (ret) {
tevent_req_error(req, ret);
return;
}
- if (count == 0) {
+ if (state->ldap_groups_count == 0) {
/* No groups for this user in LDAP
* We need to ensure that there are no groups
* in the sysdb either.
@@ -1582,7 +1788,8 @@ static void sdap_initgr_rfc2307_process(struct tevent_req *subreq)
state->ldap_grouplist = NULL;
}
else {
- ret = sysdb_attrs_to_list(state, groups, count,
+ ret = sysdb_attrs_to_list(state,
+ state->ldap_groups, state->ldap_groups_count,
SYSDB_NAME,
&state->ldap_grouplist);
if (ret != EOK) {
@@ -1645,6 +1852,9 @@ static void sdap_initgr_rfc2307_get_sysdb_groups(struct tevent_req *subreq)
static void
sdap_initgr_rfc2307_update_sysdb_groups_done(struct tevent_req *subreq);
+static void
+sdap_initgr_rfc2307_update_sysdb_groups_step(struct tevent_req *subreq);
+
static void sdap_initgr_rfc2307_update_sysdb_groups(struct tevent_req *subreq)
{
struct tevent_req *req =
@@ -1655,8 +1865,6 @@ static void sdap_initgr_rfc2307_update_sysdb_groups(struct tevent_req *subreq)
struct ldb_message *reply;
struct ldb_message_element *groups;
char **sysdb_grouplist;
- char **add_groups;
- char **del_groups;
ret = sysdb_search_user_recv(subreq, state, &reply);
talloc_zfree(subreq);
@@ -1668,47 +1876,62 @@ static void sdap_initgr_rfc2307_update_sysdb_groups(struct tevent_req *subreq)
groups = ldb_msg_find_element(reply, SYSDB_MEMBEROF);
if (!groups || groups->num_values == 0) {
DEBUG(6, ("User is not a member of any groups\n"));
+ sysdb_grouplist = NULL;
+ } else {
+ sysdb_grouplist = talloc_array(state, char *,
+ groups->num_values+1);
+ if (!sysdb_grouplist) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
- tevent_req_done(req);
- return;
- }
-
- sysdb_grouplist = talloc_array(state, char *,
- groups->num_values+1);
- if (!sysdb_grouplist) {
- tevent_req_error(req, ENOMEM);
- return;
- }
+ /* Get a list of the groups by groupname only */
+ for (i=0; i < groups->num_values; i++) {
+ ret = sysdb_group_dn_name(state->sysdb,
+ sysdb_grouplist,
+ (const char *)groups->values[i].data,
+ &sysdb_grouplist[i]);
+ if (ret != EOK) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ }
- /* Get a list of the groups by groupname only */
- for (i=0; i < groups->num_values; i++) {
- ret = sysdb_group_dn_name(state->sysdb,
- sysdb_grouplist,
- (const char *)groups->values[i].data,
- &sysdb_grouplist[i]);
- if (ret != EOK) {
- tevent_req_error(req, ENOMEM);
- return;
- }
+ sysdb_grouplist[groups->num_values] = NULL;
}
- sysdb_grouplist[groups->num_values] = NULL;
-
/* Find the differences between the sysdb and ldap lists
* Groups in ldap only must be added to the sysdb;
* groups in the sysdb only must be removed.
*/
ret = diff_string_lists(state,
state->ldap_grouplist, sysdb_grouplist,
- &add_groups, &del_groups, NULL);
+ &state->add_groups, &state->del_groups, NULL);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
}
+ if (state->add_groups && state->add_groups[0]) {
+ subreq = sdap_add_incomplete_groups_send(state, state->ev, state->sysdb,
+ state->handle, state->dom,
+ state->add_groups,
+ state->ldap_groups,
+ state->ldap_groups_count);
+ if (!subreq) {
+ tevent_req_error(req, EIO);
+ return;
+ }
+
+ tevent_req_set_callback(subreq,
+ sdap_initgr_rfc2307_update_sysdb_groups_step,
+ req);
+ return;
+ }
+
subreq = sysdb_update_members_send(state, state->ev, state->handle,
state->dom, state->name,
- add_groups, del_groups);
+ state->add_groups, state->del_groups);
if (!subreq) {
tevent_req_error(req, EIO);
return;
@@ -1720,6 +1943,36 @@ static void sdap_initgr_rfc2307_update_sysdb_groups(struct tevent_req *subreq)
}
static void
+sdap_initgr_rfc2307_update_sysdb_groups_step(struct tevent_req *subreq)
+{
+ errno_t ret;
+ struct tevent_req *req =
+ tevent_req_callback_data(subreq, struct tevent_req);
+ struct sdap_initgr_rfc2307_state *state =
+ tevent_req_data(req, struct sdap_initgr_rfc2307_state);
+ struct tevent_req *updatereq;
+
+ ret = sdap_add_incomplete_groups_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ updatereq = sysdb_update_members_send(state, state->ev, state->handle,
+ state->dom, state->name,
+ state->add_groups, state->del_groups);
+ if (!updatereq) {
+ tevent_req_error(req, EIO);
+ return;
+ }
+
+ tevent_req_set_callback(updatereq,
+ sdap_initgr_rfc2307_update_sysdb_groups_done,
+ req);
+}
+
+static void
sdap_initgr_rfc2307_transaction_done(struct tevent_req *subreq);
static void
sdap_initgr_rfc2307_update_sysdb_groups_done(struct tevent_req *subreq)