summaryrefslogtreecommitdiffstats
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
parent4bca21e23e0b0e2df610d7edb4b205698e8224c0 (diff)
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
-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 d086e6936..63445f55b 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)