summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2009-11-04 15:40:04 -0500
committerSimo Sorce <ssorce@redhat.com>2009-11-06 17:26:09 -0500
commitb520654440b8162c886bde0270b2b7fe9e191125 (patch)
tree82e207186473480624e981d945efd007e9f6ed34 /server
parent4bca21e23e0b0e2df610d7edb4b205698e8224c0 (diff)
downloadsssd-b520654440b8162c886bde0270b2b7fe9e191125.tar.gz
sssd-b520654440b8162c886bde0270b2b7fe9e191125.tar.bz2
sssd-b520654440b8162c886bde0270b2b7fe9e191125.zip
Fix and enhance initgroups call
This call was failing and was defective because it didn't properly handle the various different schemas we support. Now the function does 2 things: - Updates the user entry to make sure it is still valid - Retrieves every group the user is member of
Diffstat (limited to 'server')
-rw-r--r--server/providers/ldap/sdap_async.c807
1 files changed, 637 insertions, 170 deletions
diff --git a/server/providers/ldap/sdap_async.c b/server/providers/ldap/sdap_async.c
index d086e693..63445f55 100644
--- a/server/providers/ldap/sdap_async.c
+++ b/server/providers/ldap/sdap_async.c
@@ -1331,6 +1331,8 @@ static struct tevent_req *sdap_save_user_send(TALLOC_CTX *memctx,
int i;
char *val = NULL;
+ DEBUG(9, ("Save user\n"));
+
req = tevent_req_create(memctx, &state, struct sdap_save_user_state);
if (!req) return NULL;
@@ -1573,7 +1575,9 @@ static int sdap_save_user_recv(struct tevent_req *req,
return err;
}
- *timestamp = talloc_steal(mem_ctx, state->timestamp);
+ if (timestamp) {
+ *timestamp = talloc_steal(mem_ctx, state->timestamp);
+ }
return EOK;
}
@@ -2753,6 +2757,486 @@ int sdap_get_groups_recv(struct tevent_req *req,
return EOK;
}
+/* ==Initgr-call-(groups-a-user-is-member-of)-Save-Groups================= */
+
+struct sdap_save_groups_state {
+ struct tevent_context *ev;
+ struct sysdb_ctx *sysdb;
+ struct sdap_options *opts;
+ struct sss_domain_info *dom;
+
+ struct sysdb_attrs **groups;
+ int count;
+ int cur;
+ bool savemembers;
+
+ struct sysdb_handle *handle;
+};
+
+static void sdap_save_groups_trans(struct tevent_req *subreq);
+static void sdap_save_groups_store(struct tevent_req *req);
+static void sdap_save_groups_process(struct tevent_req *subreq);
+struct tevent_req *sdap_save_groups_send(TALLOC_CTX *memctx,
+ struct tevent_context *ev,
+ struct sss_domain_info *dom,
+ struct sysdb_ctx *sysdb,
+ struct sdap_options *opts,
+ struct sysdb_attrs **groups,
+ int num_groups)
+{
+ struct tevent_req *req, *subreq;
+ struct sdap_save_groups_state *state;
+
+ req = tevent_req_create(memctx, &state, struct sdap_save_groups_state);
+ if (!req) return NULL;
+
+ state->ev = ev;
+ state->opts = opts;
+ state->sysdb = sysdb;
+ state->dom = dom;
+ state->groups = groups;
+ state->count = 0;
+ state->cur = 0;
+ state->handle = NULL;
+
+ switch (opts->schema_type) {
+ case SDAP_SCHEMA_RFC2307:
+ case SDAP_SCHEMA_RFC2307BIS:
+ state->savemembers = true;
+ break;
+
+ case SDAP_SCHEMA_IPA_V1:
+ case SDAP_SCHEMA_AD:
+ state->savemembers = false;
+ break;
+
+ default:
+ tevent_req_error(req, EINVAL);
+ tevent_req_post(req, ev);
+ return req;
+ }
+
+ subreq = sysdb_transaction_send(state, state->ev, state->sysdb);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ tevent_req_post(req, ev);
+ return req;
+ }
+ tevent_req_set_callback(subreq, sdap_save_groups_trans, req);
+
+ return req;
+}
+
+static void sdap_save_groups_trans(struct tevent_req *subreq)
+{
+ struct tevent_req *req;
+ struct sdap_save_groups_state *state;
+ int ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sdap_save_groups_state);
+
+ ret = sysdb_transaction_recv(subreq, state, &state->handle);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ sdap_save_groups_store(req);
+}
+
+static void sdap_save_groups_store(struct tevent_req *req)
+{
+ struct tevent_req *subreq;
+ struct sdap_save_groups_state *state;
+
+ state = tevent_req_data(req, struct sdap_save_groups_state);
+
+ /* 1st pass savemembers = false */
+ /* 2nd pass savemembers = true */
+ subreq = sdap_save_group_send(state, state->ev, state->handle,
+ state->opts, state->dom,
+ state->groups[state->cur],
+ state->savemembers);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sdap_save_groups_process, req);
+}
+
+static void sdap_save_groups_process(struct tevent_req *subreq)
+{
+ struct tevent_req *req;
+ struct sdap_save_groups_state *state;
+ int ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sdap_save_groups_state);
+
+ ret = sdap_save_group_recv(subreq, NULL, NULL);
+ talloc_zfree(subreq);
+
+ /* Do not fail completely on errors.
+ * Just report the failure to save and go on */
+ if (ret) {
+ DEBUG(2, ("Failed to store group %d. Ignoring.\n", state->cur));
+ }
+
+ state->cur++;
+ if (state->cur < state->count) {
+ sdap_save_groups_store(req);
+ } else if (state->savemembers == false) {
+ state->savemembers = true;
+ state->cur = 0;
+ sdap_save_groups_store(req);
+ } else {
+ subreq = sysdb_transaction_commit_send(state, state->ev,
+ state->handle);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ /* sysdb_transaction_complete will call tevent_req_done(req) */
+ tevent_req_set_callback(subreq, sysdb_transaction_complete, req);
+ }
+}
+
+static int sdap_save_groups_recv(struct tevent_req *req)
+{
+ enum tevent_req_state tstate;
+ uint64_t err;
+
+ if (tevent_req_is_error(req, &tstate, &err)) {
+ if (err) return err;
+ return EIO;
+ }
+ return EOK;
+}
+
+
+/* ==Initgr-call-(groups-a-user-is-member-of)-RFC2307-Classic/BIS========= */
+
+struct sdap_initgr_rfc2307_state {
+ struct tevent_context *ev;
+ struct sysdb_ctx *sysdb;
+ struct sdap_options *opts;
+ struct sss_domain_info *dom;
+ struct sdap_handle *sh;
+
+ struct sdap_op *op;
+};
+
+static void sdap_initgr_rfc2307_process(struct tevent_req *subreq);
+static void sdap_initgr_rfc2307_done(struct tevent_req *subreq);
+struct tevent_req *sdap_initgr_rfc2307_send(TALLOC_CTX *memctx,
+ struct tevent_context *ev,
+ struct sdap_options *opts,
+ struct sysdb_ctx *sysdb,
+ struct sss_domain_info *dom,
+ struct sdap_handle *sh,
+ const char *base_dn,
+ const char *name,
+ const char **grp_attrs)
+{
+ struct tevent_req *req, *subreq;
+ struct sdap_initgr_rfc2307_state *state;
+ const char *filter;
+
+ req = tevent_req_create(memctx, &state, struct sdap_initgr_rfc2307_state);
+ if (!req) return NULL;
+
+ state->ev = ev;
+ state->opts = opts;
+ state->sysdb = sysdb;
+ state->dom = dom;
+ state->sh = sh;
+ state->op = NULL;
+
+ filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))",
+ opts->group_map[SDAP_AT_GROUP_MEMBER].name,
+ name, opts->group_map[SDAP_OC_GROUP].name);
+ if (!filter) {
+ talloc_zfree(req);
+ return NULL;
+ }
+
+ subreq = sdap_get_generic_send(state, state->ev, state->opts,
+ state->sh, base_dn, LDAP_SCOPE_SUBTREE,
+ filter, grp_attrs,
+ state->opts->group_map, SDAP_OPTS_GROUP);
+ if (!subreq) {
+ talloc_zfree(req);
+ return NULL;
+ }
+ tevent_req_set_callback(subreq, sdap_initgr_rfc2307_process, req);
+
+ return req;
+}
+
+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);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ if (count == 0) {
+ tevent_req_done(req);
+ return;
+ }
+
+ subreq = sdap_save_groups_send(state, state->ev, state->dom,
+ state->sysdb, state->opts,
+ groups, count);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sdap_initgr_rfc2307_done, req);
+}
+
+static void sdap_initgr_rfc2307_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req;
+ int ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+
+ ret = sdap_save_groups_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+static int sdap_initgr_rfc2307_recv(struct tevent_req *req)
+{
+ enum tevent_req_state tstate;
+ uint64_t err;
+
+ if (tevent_req_is_error(req, &tstate, &err)) {
+ if (err) return err;
+ return EIO;
+ }
+ return EOK;
+}
+
+
+/* ==Initgr-call-(groups-a-user-is-member-of)-nested-groups=============== */
+
+struct sdap_initgr_nested_state {
+ struct tevent_context *ev;
+ struct sysdb_ctx *sysdb;
+ struct sdap_options *opts;
+ struct sss_domain_info *dom;
+ struct sdap_handle *sh;
+
+ const char **grp_attrs;
+
+ char *filter;
+ char **group_dns;
+ int count;
+ int cur;
+
+ struct sdap_op *op;
+
+ struct sysdb_attrs **groups;
+ int groups_cur;
+};
+
+static void sdap_initgr_nested_search(struct tevent_req *subreq);
+static void sdap_initgr_nested_store(struct tevent_req *req);
+static void sdap_initgr_nested_done(struct tevent_req *subreq);
+static struct tevent_req *sdap_initgr_nested_send(TALLOC_CTX *memctx,
+ struct tevent_context *ev,
+ struct sdap_options *opts,
+ struct sysdb_ctx *sysdb,
+ struct sss_domain_info *dom,
+ struct sdap_handle *sh,
+ struct sysdb_attrs *user,
+ const char **grp_attrs)
+{
+ struct tevent_req *req, *subreq;
+ struct sdap_initgr_nested_state *state;
+ struct ldb_message_element *el;
+ int i, ret;
+
+ req = tevent_req_create(memctx, &state, struct sdap_initgr_nested_state);
+ if (!req) return NULL;
+
+ state->ev = ev;
+ state->opts = opts;
+ state->sysdb = sysdb;
+ state->dom = dom;
+ state->sh = sh;
+ state->grp_attrs = grp_attrs;
+ state->op = NULL;
+
+ state->filter = talloc_asprintf(state, "(objectclass=%s)",
+ opts->group_map[SDAP_OC_GROUP].name);
+ if (!state->filter) {
+ talloc_zfree(req);
+ return NULL;
+ }
+
+ /* TODO: test rootDSE for deref support and use it if available */
+ /* TODO: or test rootDSE for ASQ support and use it if available */
+
+ ret = sysdb_attrs_get_el(user, SYSDB_MEMBEROF, &el);
+ if (ret || !el || el->num_values == 0) {
+ DEBUG(4, ("User entry lacks original memberof ?\n"));
+ /* user with no groups ? */
+ tevent_req_error(req, ENOENT);
+ tevent_req_post(req, ev);
+ }
+ state->count = el->num_values;
+
+ state->groups = talloc_zero_array(state, struct sysdb_attrs *,
+ state->count + 1);;
+ if (!state->groups) {
+ talloc_zfree(req);
+ return NULL;
+ }
+ state->groups_cur = 0;
+
+ state->group_dns = talloc_array(state, char *, state->count + 1);
+ if (!state->group_dns) {
+ talloc_zfree(req);
+ return NULL;
+ }
+ for (i = 0; i < state->count; i++) {
+ state->group_dns[i] = talloc_strdup(state->group_dns,
+ (char *)el->values[i].data);
+ if (!state->group_dns[i]) {
+ talloc_zfree(req);
+ return NULL;
+ }
+ }
+ state->group_dns[i] = NULL; /* terminate */
+ state->cur = 0;
+
+ subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
+ state->group_dns[state->cur],
+ LDAP_SCOPE_BASE,
+ state->filter, state->grp_attrs,
+ state->opts->group_map, SDAP_OPTS_GROUP);
+ if (!subreq) {
+ talloc_zfree(req);
+ return NULL;
+ }
+ tevent_req_set_callback(subreq, sdap_initgr_nested_search, req);
+
+ return req;
+}
+
+static void sdap_initgr_nested_search(struct tevent_req *subreq)
+{
+ struct tevent_req *req;
+ struct sdap_initgr_nested_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_nested_state);
+
+ ret = sdap_get_generic_recv(subreq, state, &count, &groups);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ if (count == 1) {
+ state->groups[state->groups_cur] = groups[0];
+ state->groups_cur++;
+ } else {
+ DEBUG(2, ("Search for group %s, returned %d results. Skipping\n",
+ state->group_dns[state->cur], count));
+ }
+
+ state->cur++;
+ if (state->cur < state->count) {
+ subreq = sdap_get_generic_send(state, state->ev,
+ state->opts, state->sh,
+ state->group_dns[state->cur],
+ LDAP_SCOPE_BASE,
+ state->filter, state->grp_attrs,
+ state->opts->group_map,
+ SDAP_OPTS_GROUP);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sdap_initgr_nested_search, req);
+ } else {
+ sdap_initgr_nested_store(req);
+ }
+}
+
+static void sdap_initgr_nested_store(struct tevent_req *req)
+{
+ struct tevent_req *subreq;
+ struct sdap_initgr_nested_state *state;
+
+ state = tevent_req_data(req, struct sdap_initgr_nested_state);
+
+ subreq = sdap_save_groups_send(state, state->ev, state->dom,
+ state->sysdb, state->opts,
+ state->groups, state->groups_cur);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sdap_initgr_nested_done, req);
+}
+
+static void sdap_initgr_nested_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req;
+ int ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+
+ ret = sdap_save_groups_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+static int sdap_initgr_nested_recv(struct tevent_req *req)
+{
+ enum tevent_req_state tstate;
+ uint64_t err;
+
+ if (tevent_req_is_error(req, &tstate, &err)) {
+ if (err) return err;
+ return EIO;
+ }
+ return EOK;
+}
+
+
/* ==Initgr-call-(groups-a-user-is-member-of)============================= */
struct sdap_get_initgr_state {
@@ -2764,18 +3248,16 @@ struct sdap_get_initgr_state {
const char *name;
const char **grp_attrs;
- const char *filter;
+ struct sysdb_attrs *orig_user;
struct sysdb_handle *handle;
- struct sdap_op *op;
};
+static void sdap_get_initgr_user(struct tevent_req *subreq);
+static void sdap_get_initgr_store(struct tevent_req *subreq);
+static void sdap_get_initgr_commit(struct tevent_req *subreq);
static void sdap_get_initgr_process(struct tevent_req *subreq);
-static void sdap_get_initgr_transaction(struct tevent_req *subreq);
-static void sdap_get_initgr_done(struct sdap_op *op,
- struct sdap_msg *reply,
- int error, void *pvt);
-static void sdap_get_initgr_save_done(struct tevent_req *subreq);
+static void sdap_get_initgr_done(struct tevent_req *subreq);
struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
@@ -2788,10 +3270,13 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx,
{
struct tevent_req *req, *subreq;
struct sdap_get_initgr_state *state;
- struct timeval tv = {0, 0};
+ const char *base_dn;
+ char *filter;
const char **attrs;
int ret;
+ DEBUG(9, ("Retrieving info for initgroups call\n"));
+
req = tevent_req_create(memctx, &state, struct sdap_get_initgr_state);
if (!req) return NULL;
@@ -2802,124 +3287,89 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx,
state->sh = sh;
state->name = name;
state->grp_attrs = grp_attrs;
+ state->orig_user = NULL;
- switch (opts->schema_type) {
- case SDAP_SCHEMA_RFC2307:
-
- subreq = tevent_wakeup_send(state, ev, tv);
- if (!subreq) {
- ret = ENOMEM;
- goto fail;
- }
- tevent_req_set_callback(subreq, sdap_get_initgr_process, req);
- break;
-
- case SDAP_SCHEMA_RFC2307BIS:
-
- attrs = talloc_array(state, const char *, 2);
- if (!attrs) {
- ret = ENOMEM;
- goto fail;
- }
- attrs[0] = SYSDB_ORIG_DN;
- attrs[1] = NULL;
+ filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))",
+ state->opts->user_map[SDAP_AT_USER_NAME].name,
+ state->name,
+ state->opts->user_map[SDAP_OC_USER].name);
+ if (!filter) {
+ talloc_zfree(req);
+ return NULL;
+ }
- subreq = sysdb_search_user_by_name_send(state, ev, sysdb, NULL,
- dom, name, attrs);
- if (!subreq) {
- ret = ENOMEM;
- goto fail;
- }
- tevent_req_set_callback(subreq, sdap_get_initgr_process, req);
- break;
+ base_dn = dp_opt_get_string(state->opts->basic,
+ SDAP_USER_SEARCH_BASE);
+ if (!base_dn) {
+ talloc_zfree(req);
+ return NULL;
+ }
- default:
- ret = EINVAL;
- goto fail;
+ ret = build_attrs_from_map(state, state->opts->user_map,
+ SDAP_OPTS_USER, &attrs);
+ if (ret) {
+ talloc_zfree(req);
+ return NULL;
}
- return req;
+ subreq = sdap_get_generic_send(state, state->ev,
+ state->opts, state->sh,
+ base_dn, LDAP_SCOPE_SUBTREE,
+ filter, attrs,
+ state->opts->user_map, SDAP_OPTS_USER);
+ if (!subreq) {
+ talloc_zfree(req);
+ return NULL;
+ }
+ tevent_req_set_callback(subreq, sdap_get_initgr_user, req);
-fail:
- tevent_req_error(req, EIO);
- tevent_req_post(req, ev);
return req;
}
-static void sdap_get_initgr_process(struct tevent_req *subreq)
+static void sdap_get_initgr_user(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,
struct tevent_req);
struct sdap_get_initgr_state *state = tevent_req_data(req,
struct sdap_get_initgr_state);
- struct ldb_message *msg;
- const char *user_dn;
+ struct sysdb_attrs **usr_attrs;
+ size_t count;
int ret;
- switch (state->opts->schema_type) {
- case SDAP_SCHEMA_RFC2307:
-
- if (!tevent_wakeup_recv(subreq)) {
- tevent_req_error(req, EFAULT);
- return;
- }
- talloc_zfree(subreq);
-
- state->filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))",
- state->opts->group_map[SDAP_AT_GROUP_MEMBER].name,
- state->name,
- state->opts->group_map[SDAP_OC_GROUP].name);
- break;
-
- case SDAP_SCHEMA_RFC2307BIS:
-
- ret = sysdb_search_user_recv(subreq, state, &msg);
- talloc_zfree(subreq);
- if (ret) {
- tevent_req_error(req, ret);
- return;
- }
-
- user_dn = ldb_msg_find_attr_as_string(msg, SYSDB_ORIG_DN, NULL);
- if (!user_dn) {
- tevent_req_error(req, ENOENT);
- return;
- }
-
- state->filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))",
- state->opts->group_map[SDAP_AT_GROUP_MEMBER].name,
- user_dn,
- state->opts->group_map[SDAP_OC_GROUP].name);
+ DEBUG(9, ("Receiving info for the user\n"));
- talloc_free(msg);
- break;
-
- default:
- tevent_req_error(req, EINVAL);
+ ret = sdap_get_generic_recv(subreq, state, &count, &usr_attrs);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
return;
}
- if (!state->filter) {
- tevent_req_error(req, ENOMEM);
+ if (count != 1) {
+ DEBUG(2, ("Expected one user entry and got %d\n", count));
+ tevent_req_error(req, ENOENT);
return;
}
+ state->orig_user = usr_attrs[0];
+
subreq = sysdb_transaction_send(state, state->ev, state->sysdb);
if (!subreq) {
tevent_req_error(req, ENOMEM);
return;
}
- tevent_req_set_callback(subreq, sdap_get_initgr_transaction, req);
+ tevent_req_set_callback(subreq, sdap_get_initgr_store, req);
}
-static void sdap_get_initgr_transaction(struct tevent_req *subreq)
+static void sdap_get_initgr_store(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,
struct tevent_req);
struct sdap_get_initgr_state *state = tevent_req_data(req,
struct sdap_get_initgr_state);
- int ret, lret;
- int msgid;
+ int ret;
+
+ DEBUG(9, ("Storing the user\n"));
ret = sysdb_transaction_recv(subreq, state, &state->handle);
talloc_zfree(subreq);
@@ -2928,116 +3378,116 @@ static void sdap_get_initgr_transaction(struct tevent_req *subreq)
return;
}
- DEBUG(5, ("calling ldap_search_ext with filter:[%s].\n", state->filter));
-
- lret = ldap_search_ext(state->sh->ldap,
- dp_opt_get_string(state->opts->basic,
- SDAP_GROUP_SEARCH_BASE),
- LDAP_SCOPE_SUBTREE, state->filter,
- discard_const(state->grp_attrs),
- false, NULL, NULL, NULL, 0, &msgid);
- if (lret != LDAP_SUCCESS) {
- DEBUG(3, ("ldap_search_ext failed: %s\n", ldap_err2string(lret)));
- tevent_req_error(req, EIO);
+ subreq = sdap_save_user_send(state, state->ev, state->handle,
+ state->opts, state->dom,
+ state->sh, state->orig_user);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
return;
}
+ tevent_req_set_callback(subreq, sdap_get_initgr_commit, req);
+}
- DEBUG(8, ("ldap_search_ext called, msgid = %d\n", msgid));
+static void sdap_get_initgr_commit(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sdap_get_initgr_state *state = tevent_req_data(req,
+ struct sdap_get_initgr_state);
+ int ret;
- /* FIXME: get timeouts from configuration, for now 10 minutes */
- ret = sdap_op_add(state, state->ev, state->sh, msgid,
- sdap_get_initgr_done, req,
- dp_opt_get_int(state->opts->basic,
- SDAP_SEARCH_TIMEOUT),
- &state->op);
+ DEBUG(9, ("Commit change\n"));
+
+ ret = sdap_save_user_recv(subreq, NULL, NULL);
+ talloc_zfree(subreq);
if (ret) {
- DEBUG(1, ("Failed to set up operation!\n"));
tevent_req_error(req, ret);
+ return;
+ }
+
+ subreq = sysdb_transaction_commit_send(state, state->ev, state->handle);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
}
+ tevent_req_set_callback(subreq, sdap_get_initgr_process, req);
}
-static void sdap_get_initgr_done(struct sdap_op *op,
- struct sdap_msg *reply,
- int error, void *pvt)
+static void sdap_get_initgr_process(struct tevent_req *subreq)
{
- struct tevent_req *req = talloc_get_type(pvt, struct tevent_req);
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
struct sdap_get_initgr_state *state = tevent_req_data(req,
struct sdap_get_initgr_state);
- struct tevent_req *subreq;
- struct sysdb_attrs *grp_attrs;
- char *errmsg;
- int result;
+ const char *user_dn;
int ret;
- if (error) {
- tevent_req_error(req, error);
+ DEBUG(9, ("Process user's groups\n"));
+
+ ret = sysdb_transaction_commit_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
return;
}
- switch (ldap_msgtype(reply->msg)) {
- case LDAP_RES_SEARCH_REFERENCE:
- /* ignore references for now */
- talloc_free(reply);
-
- /* unlock the operation so that we can proceed with the next result */
- sdap_unlock_next_reply(state->op);
+ switch (state->opts->schema_type) {
+ case SDAP_SCHEMA_RFC2307:
+ subreq = sdap_initgr_rfc2307_send(state, state->ev, state->opts,
+ state->sysdb, state->dom, state->sh,
+ dp_opt_get_string(state->opts->basic,
+ SDAP_GROUP_SEARCH_BASE),
+ state->name, state->grp_attrs);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sdap_get_initgr_done, req);
break;
- case LDAP_RES_SEARCH_ENTRY:
+ case SDAP_SCHEMA_RFC2307BIS:
- /* allocate on reply so that it will be freed once the
- * reply is processed. Remember to steal if you need something
- * to stick longer */
- ret = sdap_parse_group(reply, state->opts, state->sh,
- reply, &grp_attrs, NULL);
- if (ret != EOK) {
- tevent_req_error(req, ret);
+ ret = sysdb_attrs_get_string(state->orig_user,
+ SYSDB_ORIG_DN, &user_dn);
+ if (ret) {
+ tevent_req_error(req, EINVAL);
return;
}
- subreq = sdap_save_group_send(state, state->ev, state->handle,
- state->opts, state->dom,
- grp_attrs, true);
+ subreq = sdap_initgr_rfc2307_send(state, state->ev, state->opts,
+ state->sysdb, state->dom,
+ state->sh, user_dn,
+ state->name, state->grp_attrs);
if (!subreq) {
tevent_req_error(req, ENOMEM);
return;
}
- tevent_req_set_callback(subreq, sdap_get_initgr_save_done, req);
-
- break;
-
- case LDAP_RES_SEARCH_RESULT:
- /* End of the story */
-
- ret = ldap_parse_result(state->sh->ldap, reply->msg,
- &result, NULL, &errmsg, NULL, NULL, 0);
- if (ret != LDAP_SUCCESS) {
- DEBUG(2, ("ldap_parse_result failed (%d)\n", state->op->msgid));
- tevent_req_error(req, EIO);
- return;
- }
+ tevent_req_set_callback(subreq, sdap_get_initgr_done, req);
+ return;
- DEBUG(3, ("Search result: %s(%d), %s\n",
- ldap_err2string(result), result, errmsg));
+ case SDAP_SCHEMA_IPA_V1:
+ case SDAP_SCHEMA_AD:
+ /* TODO: AD uses a different member/memberof schema
+ * We need an AD specific call that is able to unroll
+ * nested groups by doing extensive recursive searches */
- subreq = sysdb_transaction_commit_send(state, state->ev,
- state->handle);
+ subreq = sdap_initgr_nested_send(state, state->ev, state->opts,
+ state->sysdb, state->dom, state->sh,
+ state->orig_user, state->grp_attrs);
if (!subreq) {
tevent_req_error(req, ENOMEM);
return;
}
- /* sysdb_transaction_complete will call tevent_req_done(req) */
- tevent_req_set_callback(subreq, sysdb_transaction_complete, req);
- break;
+ tevent_req_set_callback(subreq, sdap_get_initgr_done, req);
+ return;
default:
- /* what is going on here !? */
- tevent_req_error(req, EIO);
+ tevent_req_error(req, EINVAL);
return;
}
}
-static void sdap_get_initgr_save_done(struct tevent_req *subreq)
+static void sdap_get_initgr_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,
struct tevent_req);
@@ -3045,17 +3495,34 @@ static void sdap_get_initgr_save_done(struct tevent_req *subreq)
struct sdap_get_initgr_state);
int ret;
- ret = sdap_save_group_recv(subreq, NULL, NULL);
- talloc_zfree(subreq);
+ DEBUG(9, ("Initgroups done\n"));
- /* Do not fail completely on errors.
- * Just report the failure to save and go on */
+ switch (state->opts->schema_type) {
+ case SDAP_SCHEMA_RFC2307:
+ case SDAP_SCHEMA_RFC2307BIS:
+
+ ret = sdap_initgr_rfc2307_recv(subreq);
+ break;
+
+ case SDAP_SCHEMA_IPA_V1:
+ case SDAP_SCHEMA_AD:
+
+ ret = sdap_initgr_nested_recv(subreq);
+ break;
+
+ default:
+
+ ret = EINVAL;
+ break;
+ }
+
+ talloc_zfree(subreq);
if (ret) {
- DEBUG(2, ("Failed to store group. Ignoring.\n"));
+ tevent_req_error(req, ret);
+ return;
}
- /* unlock the operation so that we can proceed with the next result */
- sdap_unlock_next_reply(state->op);
+ tevent_req_done(req);
}
int sdap_get_initgr_recv(struct tevent_req *req)