summaryrefslogtreecommitdiffstats
path: root/src/providers/ldap/sdap_async.c
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2011-04-01 14:36:16 +0200
committerStephen Gallagher <sgallagh@redhat.com>2011-05-20 07:21:45 -0400
commit4dbc76b8784eed6dbf4d9b40c0f59fd0bceeeec7 (patch)
treefa2cb8bed2ccb89119f1e7af8f41e7018108ae30 /src/providers/ldap/sdap_async.c
parent068dbee9ca7bf5b37330eff91c94ae10f288d09f (diff)
downloadsssd-4dbc76b8784eed6dbf4d9b40c0f59fd0bceeeec7.tar.gz
sssd-4dbc76b8784eed6dbf4d9b40c0f59fd0bceeeec7.tar.xz
sssd-4dbc76b8784eed6dbf4d9b40c0f59fd0bceeeec7.zip
sdap_get_generic_ext
Add a private sdap_get_generic_ext_send()/_recv() request that exposes more of ldap_search_ext options, in particular the server contols. The existing sdap_generic_search_send()/_recv() request is now a thin wrapper around the new _ext request. The other important change is that an entry parsing is a callback now. That was done in order to allow custom parsing for results such as OpenLDAP deref or Attribute Scoped Queries.
Diffstat (limited to 'src/providers/ldap/sdap_async.c')
-rw-r--r--src/providers/ldap/sdap_async.c275
1 files changed, 202 insertions, 73 deletions
diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c
index 1e083553d..7c7e2699a 100644
--- a/src/providers/ldap/sdap_async.c
+++ b/src/providers/ldap/sdap_async.c
@@ -794,9 +794,39 @@ int sdap_get_rootdse_recv(struct tevent_req *req,
return EOK;
}
-/* ==Generic Search============================================ */
+/* ==Helpers for parsing replies============================== */
+struct sdap_reply {
+ size_t reply_max;
+ size_t reply_count;
+ struct sysdb_attrs **reply;
+};
-struct sdap_get_generic_state {
+static errno_t add_to_reply(TALLOC_CTX *mem_ctx,
+ struct sdap_reply *sreply,
+ struct sysdb_attrs *msg)
+{
+ if (sreply->reply == NULL || sreply->reply_max == sreply->reply_count) {
+ sreply->reply_max += REPLY_REALLOC_INCREMENT;
+ sreply->reply = talloc_realloc(mem_ctx, sreply->reply,
+ struct sysdb_attrs *,
+ sreply->reply_max);
+ if (sreply->reply == NULL) {
+ DEBUG(1, ("talloc_realloc failed.\n"));
+ return ENOMEM;
+ }
+ }
+
+ sreply->reply[sreply->reply_count++] = talloc_steal(sreply->reply, msg);
+
+ return EOK;
+}
+
+/* ==Generic Search exposing all options======================= */
+typedef errno_t (*sdap_parse_cb)(struct sdap_handle *sh,
+ struct sdap_msg *msg,
+ void *pvt);
+
+struct sdap_get_generic_ext_state {
struct tevent_context *ev;
struct sdap_options *opts;
struct sdap_handle *sh;
@@ -804,43 +834,52 @@ struct sdap_get_generic_state {
int scope;
const char *filter;
const char **attrs;
- struct sdap_attr_map *map;
- int map_num_attrs;
int timeout;
+ int attrsonly;
+ int sizelimit;
struct sdap_op *op;
struct berval cookie;
- size_t reply_max;
- size_t reply_count;
- struct sysdb_attrs **reply;
-};
+ LDAPControl **serverctrls;
+ int nserverctrls;
+ LDAPControl **clientctrls;
-static errno_t sdap_get_generic_step(struct tevent_req *req);
-static void sdap_get_generic_done(struct sdap_op *op,
- struct sdap_msg *reply,
- int error, void *pvt);
-static errno_t add_to_reply(struct sdap_get_generic_state *state,
- struct sysdb_attrs *msg);
+ sdap_parse_cb parse_cb;
+ void *cb_data;
-struct tevent_req *sdap_get_generic_send(TALLOC_CTX *memctx,
- struct tevent_context *ev,
- struct sdap_options *opts,
- struct sdap_handle *sh,
- const char *search_base,
- int scope,
- const char *filter,
- const char **attrs,
- struct sdap_attr_map *map,
- int map_num_attrs,
- int timeout)
+};
+
+static errno_t sdap_get_generic_ext_step(struct tevent_req *req);
+
+static void sdap_get_generic_ext_done(struct sdap_op *op,
+ struct sdap_msg *reply,
+ int error, void *pvt);
+
+static struct tevent_req *
+sdap_get_generic_ext_send(TALLOC_CTX *memctx,
+ struct tevent_context *ev,
+ struct sdap_options *opts,
+ struct sdap_handle *sh,
+ const char *search_base,
+ int scope,
+ const char *filter,
+ const char **attrs,
+ int attrsonly,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int sizelimit,
+ int timeout,
+ sdap_parse_cb parse_cb,
+ void *cb_data)
{
errno_t ret;
- struct sdap_get_generic_state *state;
+ struct sdap_get_generic_ext_state *state;
struct tevent_req *req;
+ int i;
- req = tevent_req_create(memctx, &state, struct sdap_get_generic_state);
+ req = tevent_req_create(memctx, &state, struct sdap_get_generic_ext_state);
if (!req) return NULL;
state->ev = ev;
@@ -850,17 +889,34 @@ struct tevent_req *sdap_get_generic_send(TALLOC_CTX *memctx,
state->scope = scope;
state->filter = filter;
state->attrs = attrs;
- state->map = map;
- state->map_num_attrs = map_num_attrs;
+ state->attrsonly = attrsonly;
state->op = NULL;
- state->reply_max = 0;
- state->reply_count = 0;
- state->reply = NULL;
state->timeout = timeout;
state->cookie.bv_len = 0;
state->cookie.bv_val = NULL;
+ state->parse_cb = parse_cb;
+ state->cb_data = cb_data;
+ state->clientctrls = clientctrls;
+
+ for (state->nserverctrls=0;
+ serverctrls && serverctrls[state->nserverctrls];
+ state->nserverctrls++) ;
+
+ /* One extra space for NULL, one for page control */
+ state->serverctrls = talloc_array(state, LDAPControl *,
+ state->nserverctrls+2);
+ if (!state->serverctrls) {
+ tevent_req_error(req, ENOMEM);
+ tevent_req_post(req, ev);
+ return req;
+ }
+
+ for (i=0; i < state->nserverctrls; i++) {
+ state->serverctrls[i] = serverctrls[i];
+ }
+ state->serverctrls[i] = NULL;
- ret = sdap_get_generic_step(req);
+ ret = sdap_get_generic_ext_step(req);
if (ret != EOK) {
tevent_req_error(req, ret);
tevent_req_post(req, ev);
@@ -870,10 +926,10 @@ struct tevent_req *sdap_get_generic_send(TALLOC_CTX *memctx,
return req;
}
-static errno_t sdap_get_generic_step(struct tevent_req *req)
+static errno_t sdap_get_generic_ext_step(struct tevent_req *req)
{
- struct sdap_get_generic_state *state =
- tevent_req_data(req, struct sdap_get_generic_state);
+ struct sdap_get_generic_ext_state *state =
+ tevent_req_data(req, struct sdap_get_generic_ext_state);
char *errmsg;
int lret;
int optret;
@@ -881,7 +937,6 @@ static errno_t sdap_get_generic_step(struct tevent_req *req)
int msgid;
LDAPControl *page_control = NULL;
- LDAPControl *m_controls[2] = { NULL, NULL };
/* Make sure to free any previous operations so
* if we are handling a large number of pages we
@@ -914,15 +969,17 @@ static errno_t sdap_get_generic_step(struct tevent_req *req)
ret = EIO;
goto done;
}
- m_controls[0] = page_control;
+ state->serverctrls[state->nserverctrls] = page_control;
+ state->serverctrls[state->nserverctrls+1] = NULL;
}
lret = ldap_search_ext(state->sh->ldap, state->search_base,
state->scope, state->filter,
discard_const(state->attrs),
- false, m_controls, NULL, NULL, 0, &msgid);
+ state->attrsonly, state->serverctrls,
+ state->clientctrls, NULL, state->sizelimit, &msgid);
ldap_control_free(page_control);
- m_controls[0] = NULL;
+ state->serverctrls[state->nserverctrls] = NULL;
if (lret != LDAP_SUCCESS) {
DEBUG(3, ("ldap_search_ext failed: %s\n", ldap_err2string(lret)));
if (lret == LDAP_SERVER_DOWN) {
@@ -947,7 +1004,7 @@ static errno_t sdap_get_generic_step(struct tevent_req *req)
DEBUG(8, ("ldap_search_ext called, msgid = %d\n", msgid));
ret = sdap_op_add(state, state->ev, state->sh, msgid,
- sdap_get_generic_done, req,
+ sdap_get_generic_ext_done, req,
state->timeout,
&state->op);
if (ret != EOK) {
@@ -959,14 +1016,13 @@ done:
return ret;
}
-static void sdap_get_generic_done(struct sdap_op *op,
- struct sdap_msg *reply,
- int error, void *pvt)
+static void sdap_get_generic_ext_done(struct sdap_op *op,
+ struct sdap_msg *reply,
+ int error, void *pvt)
{
struct tevent_req *req = talloc_get_type(pvt, struct tevent_req);
- struct sdap_get_generic_state *state = tevent_req_data(req,
- struct sdap_get_generic_state);
- struct sysdb_attrs *attrs;
+ struct sdap_get_generic_ext_state *state = tevent_req_data(req,
+ struct sdap_get_generic_ext_state);
char *errmsg = NULL;
int result;
int ret;
@@ -991,18 +1047,9 @@ static void sdap_get_generic_done(struct sdap_op *op,
break;
case LDAP_RES_SEARCH_ENTRY:
- ret = sdap_parse_entry(state, state->sh, reply,
- state->map, state->map_num_attrs,
- &attrs, NULL);
- if (ret != EOK) {
- DEBUG(1, ("sdap_parse_generic_entry failed.\n"));
- tevent_req_error(req, ENOMEM);
- return;
- }
-
- ret = add_to_reply(state, attrs);
+ ret = state->parse_cb(state->sh, reply, state->cb_data);
if (ret != EOK) {
- DEBUG(1, ("add_to_reply failed.\n"));
+ DEBUG(1, ("reply parsing callback failed.\n"));
tevent_req_error(req, ret);
return;
}
@@ -1063,7 +1110,7 @@ static void sdap_get_generic_done(struct sdap_op *op,
}
ber_memfree(cookie.bv_val);
- ret = sdap_get_generic_step(req);
+ ret = sdap_get_generic_ext_step(req);
if (ret != EOK) {
tevent_req_error(req, ENOMEM);
return;
@@ -1086,25 +1133,107 @@ static void sdap_get_generic_done(struct sdap_op *op,
}
}
-static errno_t add_to_reply(struct sdap_get_generic_state *state,
- struct sysdb_attrs *msg)
+static int
+sdap_get_generic_ext_recv(struct tevent_req *req)
{
- if (state->reply == NULL || state->reply_max == state->reply_count) {
- state->reply_max += REPLY_REALLOC_INCREMENT;
- state->reply = talloc_realloc(state, state->reply,
- struct sysdb_attrs *,
- state->reply_max);
- if (state->reply == NULL) {
- DEBUG(1, ("talloc_realloc failed.\n"));
- return ENOMEM;
- }
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+ return EOK;
+}
+
+/* ==Generic Search============================================ */
+struct sdap_get_generic_state {
+ struct sdap_attr_map *map;
+ int map_num_attrs;
+
+ struct sdap_reply sreply;
+};
+
+static void sdap_get_generic_done(struct tevent_req *subreq);
+static errno_t sdap_get_generic_parse_entry(struct sdap_handle *sh,
+ struct sdap_msg *msg,
+ void *pvt);
+
+struct tevent_req *sdap_get_generic_send(TALLOC_CTX *memctx,
+ struct tevent_context *ev,
+ struct sdap_options *opts,
+ struct sdap_handle *sh,
+ const char *search_base,
+ int scope,
+ const char *filter,
+ const char **attrs,
+ struct sdap_attr_map *map,
+ int map_num_attrs,
+ int timeout)
+{
+ struct tevent_req *req = NULL;
+ struct tevent_req *subreq = NULL;
+ struct sdap_get_generic_state *state = NULL;
+
+ req = tevent_req_create(memctx, &state, struct sdap_get_generic_state);
+ if (!req) return NULL;
+
+ state->map = map;
+ state->map_num_attrs = map_num_attrs;
+
+ subreq = sdap_get_generic_ext_send(state, ev, opts, sh, search_base,
+ scope, filter, attrs, false, NULL,
+ NULL, 0, timeout,
+ sdap_get_generic_parse_entry, state);
+ if (!subreq) {
+ talloc_zfree(req);
+ return NULL;
}
+ tevent_req_set_callback(subreq, sdap_get_generic_done, req);
+
+ return req;
+}
- state->reply[state->reply_count++] = talloc_steal(state->reply, msg);
+static errno_t sdap_get_generic_parse_entry(struct sdap_handle *sh,
+ struct sdap_msg *msg,
+ void *pvt)
+{
+ errno_t ret;
+ struct sysdb_attrs *attrs;
+ struct sdap_get_generic_state *state =
+ talloc_get_type(pvt, struct sdap_get_generic_state);
+
+ ret = sdap_parse_entry(state, sh, msg,
+ state->map, state->map_num_attrs,
+ &attrs, NULL);
+ if (ret != EOK) {
+ DEBUG(3, ("sdap_parse_entry failed [%d]: %s\n", ret, strerror(ret)));
+ return ret;
+ }
+
+ ret = add_to_reply(state, &state->sreply, attrs);
+ if (ret != EOK) {
+ talloc_free(attrs);
+ DEBUG(1, ("add_to_reply failed.\n"));
+ return ret;
+ }
+ /* add_to_reply steals attrs, no need to free them here */
return EOK;
}
+static void sdap_get_generic_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ int ret;
+
+ ret = sdap_get_generic_ext_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ DEBUG(4, ("sdap_get_generic_ext_recv failed [%d]: %s\n",
+ ret, strerror(ret)));
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
int sdap_get_generic_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
size_t *reply_count,
@@ -1115,8 +1244,8 @@ int sdap_get_generic_recv(struct tevent_req *req,
TEVENT_REQ_RETURN_ON_ERROR(req);
- *reply_count = state->reply_count;
- *reply = talloc_steal(mem_ctx, state->reply);
+ *reply_count = state->sreply.reply_count;
+ *reply = talloc_steal(mem_ctx, state->sreply.reply);
return EOK;
}