summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2010-09-22 10:54:44 -0400
committerStephen Gallagher <sgallagh@redhat.com>2010-10-08 19:26:55 -0400
commitee0b08aaf6a5324149d264e248a6d4ce89aa6c2a (patch)
tree717837ed4a75c2c213dacad20798b494074a105a /src
parentb302ec4cad436c8025675f74486e5d5f95730a20 (diff)
downloadsssd-ee0b08aaf6a5324149d264e248a6d4ce89aa6c2a.tar.gz
sssd-ee0b08aaf6a5324149d264e248a6d4ce89aa6c2a.tar.xz
sssd-ee0b08aaf6a5324149d264e248a6d4ce89aa6c2a.zip
Add fake groups during initgroups
If during initgroups operation we find out that any of the groups the user is a member of is not cached yet we add a incomplete, expired group entry. That way, we save ourselves from looking up and saving all the potential user entries the group may also consist of. Because the group is expired, it will be refreshed during the next getgrgid/getgrnam call and correct member list will be returned.
Diffstat (limited to 'src')
-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)