summaryrefslogtreecommitdiffstats
path: root/src/providers/ldap
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2013-05-19 23:01:41 +0200
committerJakub Hrozek <jhrozek@redhat.com>2013-06-07 00:14:12 +0200
commite6e129a40e69af52a12deed91f68fff3569c51ce (patch)
tree26356f8c7a5b30276842ebb7b59dd48a26ff1ab5 /src/providers/ldap
parentdcb44c39dda9699cdd6488fd116a51ced0687de3 (diff)
downloadsssd-e6e129a40e69af52a12deed91f68fff3569c51ce.tar.gz
sssd-e6e129a40e69af52a12deed91f68fff3569c51ce.tar.xz
sssd-e6e129a40e69af52a12deed91f68fff3569c51ce.zip
LDAP: Refactor account info handler into a tevent request
The sdap account handler was a function with its own private callback that directly called the back end handlers. This patch refactors the handler into a new tevent request that the current sdap handler calls. This refactoring would allow the caller to specify a custom sdap connection for use by the handler and optionally retry the same request with another connection inside a single per-provider handler. No functional changes are present in this patch.
Diffstat (limited to 'src/providers/ldap')
-rw-r--r--src/providers/ldap/ldap_common.h17
-rw-r--r--src/providers/ldap/ldap_id.c356
2 files changed, 210 insertions, 163 deletions
diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h
index 8c6083541..e22bff1ed 100644
--- a/src/providers/ldap/ldap_common.h
+++ b/src/providers/ldap/ldap_common.h
@@ -96,6 +96,15 @@ void sdap_account_info_handler(struct be_req *breq);
void sdap_handle_account_info(struct be_req *breq, struct sdap_id_ctx *ctx);
int sdap_id_setup_tasks(struct sdap_id_ctx *ctx);
+struct tevent_req *
+sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx,
+ struct be_req *breq,
+ struct be_acct_req *ar,
+ struct sdap_id_ctx *id_ctx);
+errno_t
+sdap_handle_acct_req_recv(struct tevent_req *req,
+ int *_dp_error, const char **_err);
+
/* auth */
void sdap_pam_auth_handler(struct be_req *breq);
@@ -160,14 +169,6 @@ struct tevent_req *ldap_id_enumerate_send(struct tevent_context *ev,
void sdap_mark_offline(struct sdap_id_ctx *ctx);
-struct tevent_req *users_get_send(TALLOC_CTX *memctx,
- struct tevent_context *ev,
- struct sdap_id_ctx *ctx,
- const char *name,
- int filter_type,
- int attrs_type);
-int users_get_recv(struct tevent_req *req, int *dp_error_out);
-
struct tevent_req *groups_get_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *ctx,
diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
index a7987810c..c04d90fba 100644
--- a/src/providers/ldap/ldap_id.c
+++ b/src/providers/ldap/ldap_id.c
@@ -971,11 +971,6 @@ static void sdap_check_online_reinit_done(struct tevent_req *req)
/* FIXME: embed this function in sssd_be and only call out
* specific functions from modules ? */
-static void sdap_account_info_users_done(struct tevent_req *req);
-static void sdap_account_info_groups_done(struct tevent_req *req);
-static void sdap_account_info_initgr_done(struct tevent_req *req);
-static void sdap_account_info_netgroups_done(struct tevent_req *req);
-static void sdap_account_info_services_done(struct tevent_req *req);
void sdap_handle_account_info(struct be_req *breq, struct sdap_id_ctx *ctx);
static struct tevent_req *get_user_and_group_send(TALLOC_CTX *memctx,
@@ -984,7 +979,8 @@ static struct tevent_req *get_user_and_group_send(TALLOC_CTX *memctx,
const char *name,
int filter_type,
int attrs_type);
-static void sdap_get_user_and_group_done(struct tevent_req *req);
+
+errno_t sdap_get_user_and_group_recv(struct tevent_req *req, int *dp_error_out);
void sdap_account_info_handler(struct be_req *breq)
{
@@ -1000,242 +996,304 @@ void sdap_account_info_handler(struct be_req *breq)
return sdap_handle_account_info(breq, ctx);
}
-void sdap_handle_account_info(struct be_req *breq, struct sdap_id_ctx *ctx)
-{
- struct be_ctx *be_ctx = be_req_get_be_ctx(breq);
+/* A generic LDAP account info handler */
+struct sdap_handle_acct_req_state {
+ struct be_req *breq;
struct be_acct_req *ar;
+ const char *err;
+ int dp_error;
+};
+
+static void sdap_handle_acct_req_done(struct tevent_req *subreq);
+
+struct tevent_req *
+sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx,
+ struct be_req *breq,
+ struct be_acct_req *ar,
+ struct sdap_id_ctx *id_ctx)
+{
struct tevent_req *req;
- const char *err = "Unknown Error";
- int ret = EOK;
+ struct tevent_req *subreq;
+ struct be_ctx *be_ctx;
+ struct sdap_handle_acct_req_state *state;
+ errno_t ret;
- if (be_is_offline(ctx->be)) {
- return sdap_handler_done(breq, DP_ERR_OFFLINE, EAGAIN, "Offline");
+ be_ctx = be_req_get_be_ctx(breq);
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct sdap_handle_acct_req_state);
+ if (!req) {
+ ret = ENOMEM;
+ goto done;
}
+ state->breq = breq;
+ state->ar = ar;
- ar = talloc_get_type(be_req_get_data(breq), struct be_acct_req);
+ if (ar == NULL) {
+ ret = EINVAL;
+ goto done;
+ }
switch (ar->entry_type & BE_REQ_TYPE_MASK) {
case BE_REQ_USER: /* user */
/* skip enumerations on demand */
if (ar->filter_type == BE_FILTER_ENUM) {
- return sdap_handler_done(breq, DP_ERR_OK, EOK, "Success");
- }
-
- req = users_get_send(breq, be_ctx->ev, ctx,
- ar->filter_value,
- ar->filter_type,
- ar->attr_type);
- if (!req) {
- return sdap_handler_done(breq, DP_ERR_FATAL, ENOMEM, "Out of memory");
+ DEBUG(SSSDBG_TRACE_LIBS,
+ ("Skipping user enumeration on demand\n"));
+ state->err = "Success";
+ ret = EOK;
+ goto done;
}
- tevent_req_set_callback(req, sdap_account_info_users_done, breq);
-
+ subreq = users_get_send(breq, be_ctx->ev, id_ctx,
+ ar->filter_value,
+ ar->filter_type,
+ ar->attr_type);
break;
case BE_REQ_GROUP: /* group */
/* skip enumerations on demand */
if (ar->filter_type == BE_FILTER_ENUM) {
- return sdap_handler_done(breq, DP_ERR_OK, EOK, "Success");
- }
-
- req = groups_get_send(breq, be_ctx->ev, ctx,
- ar->filter_value,
- ar->filter_type,
- ar->attr_type);
- if (!req) {
- return sdap_handler_done(breq, DP_ERR_FATAL, ENOMEM, "Out of memory");
+ DEBUG(SSSDBG_TRACE_LIBS,
+ ("Skipping group enumeration on demand\n"));
+ state->err = "Success";
+ ret = EOK;
+ goto done;
}
- tevent_req_set_callback(req, sdap_account_info_groups_done, breq);
-
+ subreq = groups_get_send(breq, be_ctx->ev, id_ctx,
+ ar->filter_value,
+ ar->filter_type,
+ ar->attr_type);
break;
case BE_REQ_INITGROUPS: /* init groups for user */
if (ar->filter_type != BE_FILTER_NAME) {
ret = EINVAL;
- err = "Invalid filter type";
- break;
+ state->err = "Invalid filter type";
+ goto done;
}
if (ar->attr_type != BE_ATTR_CORE) {
ret = EINVAL;
- err = "Invalid attr type";
- break;
+ state->err = "Invalid attr type";
+ goto done;
}
- req = groups_by_user_send(breq, be_ctx->ev, ctx,
- ar->filter_value);
- if (!req) ret = ENOMEM;
-
- tevent_req_set_callback(req, sdap_account_info_initgr_done, breq);
+ subreq = groups_by_user_send(breq, be_ctx->ev, id_ctx,
+ ar->filter_value);
break;
case BE_REQ_NETGROUP:
if (ar->filter_type != BE_FILTER_NAME) {
ret = EINVAL;
- err = "Invalid filter type";
- break;
- }
-
- req = ldap_netgroup_get_send(breq, be_ctx->ev, ctx, ar->filter_value);
- if (!req) {
- return sdap_handler_done(breq, DP_ERR_FATAL, ENOMEM, "Out of memory");
+ state->err = "Invalid filter type";
+ goto done;
}
- tevent_req_set_callback(req, sdap_account_info_netgroups_done, breq);
+ subreq = ldap_netgroup_get_send(breq, be_ctx->ev, id_ctx,
+ ar->filter_value);
break;
case BE_REQ_SERVICES:
/* skip enumerations on demand */
if (ar->filter_type == BE_FILTER_ENUM) {
- return sdap_handler_done(breq, DP_ERR_OK, EOK, "Success");
+ DEBUG(SSSDBG_TRACE_LIBS,
+ ("Skipping service enumeration on demand\n"));
+ state->err = "Success";
+ ret = EOK;
+ goto done;
}
if (ar->filter_type == BE_FILTER_SECID) {
ret = EINVAL;
- err = "Invalid filter type";
- break;
- }
-
- req = services_get_send(breq, be_ctx->ev, ctx,
- ar->filter_value,
- ar->extra_value,
- ar->filter_type);
- if (!req) {
- return sdap_handler_done(breq, DP_ERR_FATAL,
- ENOMEM, "Out of memory");
+ state->err = "Invalid filter type";
+ goto done;
}
- tevent_req_set_callback(req, sdap_account_info_services_done, breq);
+ subreq = services_get_send(breq, be_ctx->ev, id_ctx,
+ ar->filter_value,
+ ar->extra_value,
+ ar->filter_type);
break;
case BE_REQ_BY_SECID:
if (ar->filter_type != BE_FILTER_SECID) {
ret = EINVAL;
- err = "Invalid filter type";
- break;
- }
-
- req = get_user_and_group_send(breq, be_ctx->ev, ctx,
- ar->filter_value,
- ar->filter_type,
- ar->attr_type);
- if (!req) {
- return sdap_handler_done(breq, DP_ERR_FATAL,
- ENOMEM,"Out of memory");
+ state->err = "Invalid filter type";
+ goto done;
}
- tevent_req_set_callback(req, sdap_get_user_and_group_done, breq);
-
+ subreq = get_user_and_group_send(breq, be_ctx->ev, id_ctx,
+ ar->filter_value,
+ ar->filter_type,
+ ar->attr_type);
break;
case BE_REQ_USER_AND_GROUP:
if (!(ar->filter_type == BE_FILTER_NAME ||
ar->filter_type == BE_FILTER_IDNUM)) {
ret = EINVAL;
- err = "Invalid filter type";
- break;
- }
-
- req = get_user_and_group_send(breq, be_ctx->ev, ctx,
- ar->filter_value,
- ar->filter_type,
- ar->attr_type);
- if (!req) {
- return sdap_handler_done(breq, DP_ERR_FATAL,
- ENOMEM,"Out of memory");
+ state->err = "Invalid filter type";
+ goto done;
}
- tevent_req_set_callback(req, sdap_get_user_and_group_done, breq);
-
+ subreq = get_user_and_group_send(breq, be_ctx->ev, id_ctx,
+ ar->filter_value,
+ ar->filter_type,
+ ar->attr_type);
break;
+
default: /*fail*/
ret = EINVAL;
- err = "Invalid request type";
+ state->err = "Invalid request type";
+ goto done;
}
- if (ret != EOK) return sdap_handler_done(breq, DP_ERR_FATAL, ret, err);
-}
+ if (!subreq) {
+ ret = ENOMEM;
+ goto done;
+ }
-static void sdap_account_info_complete(struct be_req *breq, int dp_error,
- int ret, const char *default_error_text)
-{
- const char* error_text;
+ tevent_req_set_callback(subreq, sdap_handle_acct_req_done, req);
+ return req;
- if (dp_error == DP_ERR_OK) {
- if (ret == EOK) {
- error_text = NULL;
- } else {
- DEBUG(1, ("Bug: dp_error is OK on failed request"));
- dp_error = DP_ERR_FATAL;
- error_text = default_error_text;
- }
- } else if (dp_error == DP_ERR_OFFLINE) {
- error_text = "Offline";
- } else if (dp_error == DP_ERR_FATAL && ret == ENOMEM) {
- error_text = "Out of memory";
+done:
+ if (ret == EOK) {
+ tevent_req_done(req);
} else {
- error_text = default_error_text;
+ tevent_req_error(req, ret);
}
- sdap_handler_done(breq, dp_error, ret, error_text);
+ tevent_req_post(req, be_ctx->ev);
+ return req;
}
-static void sdap_account_info_users_done(struct tevent_req *req)
+static void
+sdap_handle_acct_req_done(struct tevent_req *subreq)
{
- struct be_req *breq = tevent_req_callback_data(req, struct be_req);
- int ret, dp_error;
+ struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req);
+ struct sdap_handle_acct_req_state *state;
+ errno_t ret;
+ const char *err = "Invalid request type";
- ret = users_get_recv(req, &dp_error);
- talloc_zfree(req);
+ state = tevent_req_data(req, struct sdap_handle_acct_req_state);
- sdap_account_info_complete(breq, dp_error, ret, "User lookup failed");
-}
-
-static void sdap_account_info_groups_done(struct tevent_req *req)
-{
- struct be_req *breq = tevent_req_callback_data(req, struct be_req);
- int ret, dp_error;
+ switch (state->ar->entry_type & BE_REQ_TYPE_MASK) {
+ case BE_REQ_USER: /* user */
+ err = "User lookup failed";
+ ret = users_get_recv(subreq, &state->dp_error);
+ break;
+ case BE_REQ_GROUP: /* group */
+ err = "Group lookup failed";
+ ret = groups_get_recv(subreq, &state->dp_error);
+ break;
+ case BE_REQ_INITGROUPS: /* init groups for user */
+ err = "Init group lookup failed";
+ ret = groups_by_user_recv(subreq, &state->dp_error);
+ break;
+ case BE_REQ_NETGROUP:
+ err = "Netgroup lookup failed";
+ ret = ldap_netgroup_get_recv(subreq, &state->dp_error);
+ break;
+ case BE_REQ_SERVICES:
+ err = "Service lookup failed";
+ ret = services_get_recv(subreq, &state->dp_error);
+ break;
+ case BE_REQ_BY_SECID:
+ /* Fallthrough */
+ case BE_REQ_USER_AND_GROUP:
+ err = "Lookup by SID failed";
+ ret = sdap_get_user_and_group_recv(subreq, &state->dp_error);
+ break;
+ default: /*fail*/
+ ret = EINVAL;
+ break;
+ }
+ talloc_zfree(subreq);
- ret = groups_get_recv(req, &dp_error);
- talloc_zfree(req);
+ if (ret != EOK) {
+ state->err = err;
+ tevent_req_error(req, ret);
+ return;
+ }
- sdap_account_info_complete(breq, dp_error, ret, "Group lookup failed");
+ state->err = "Success";
+ tevent_req_done(req);
}
-static void sdap_account_info_initgr_done(struct tevent_req *req)
+errno_t
+sdap_handle_acct_req_recv(struct tevent_req *req,
+ int *_dp_error, const char **_err)
{
- struct be_req *breq = tevent_req_callback_data(req, struct be_req);
- int ret, dp_error;
+ struct sdap_handle_acct_req_state *state;
- ret = groups_by_user_recv(req, &dp_error);
- talloc_zfree(req);
+ state = tevent_req_data(req, struct sdap_handle_acct_req_state);
- sdap_account_info_complete(breq, dp_error, ret, "Init Groups Failed");
+ if (_dp_error) {
+ *_dp_error = state->dp_error;
+ }
+
+ if (_err) {
+ *_err = state->err;
+ }
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+ return EOK;
}
-static void sdap_account_info_netgroups_done(struct tevent_req *req)
+static void sdap_account_info_complete(struct tevent_req *req);
+
+void sdap_handle_account_info(struct be_req *breq, struct sdap_id_ctx *ctx)
{
- struct be_req *breq = tevent_req_callback_data(req, struct be_req);
- int ret, dp_error;
+ struct be_acct_req *ar;
+ struct tevent_req *req;
- ret = ldap_netgroup_get_recv(req, &dp_error);
- talloc_zfree(req);
+ if (be_is_offline(ctx->be)) {
+ return sdap_handler_done(breq, DP_ERR_OFFLINE, EAGAIN, "Offline");
+ }
+
+ ar = talloc_get_type(be_req_get_data(breq), struct be_acct_req);
+ if (ar == NULL) {
+ return sdap_handler_done(breq, DP_ERR_FATAL,
+ EINVAL, "Invalid private data");
+ }
- sdap_account_info_complete(breq, dp_error, ret, "Netgroup lookup failed");
+ req = sdap_handle_acct_req_send(breq, breq, ar, ctx);
+ if (req == NULL) {
+ return sdap_handler_done(breq, DP_ERR_FATAL, ENOMEM, "Out of memory");
+ }
+ tevent_req_set_callback(req, sdap_account_info_complete, breq);
}
-static void sdap_account_info_services_done(struct tevent_req *req)
+static void sdap_account_info_complete(struct tevent_req *req)
{
+ const char *error_text;
+ const char *req_error_text;
struct be_req *breq = tevent_req_callback_data(req, struct be_req);
int ret, dp_error;
- ret = services_get_recv(req, &dp_error);
+ ret = sdap_handle_acct_req_recv(req, &dp_error, &req_error_text);
talloc_zfree(req);
+ if (dp_error == DP_ERR_OK) {
+ if (ret == EOK) {
+ error_text = NULL;
+ } else {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("Bug: dp_error is OK on failed request"));
+ dp_error = DP_ERR_FATAL;
+ error_text = req_error_text;
+ }
+ } else if (dp_error == DP_ERR_OFFLINE) {
+ error_text = "Offline";
+ } else if (dp_error == DP_ERR_FATAL && ret == ENOMEM) {
+ error_text = "Out of memory";
+ } else {
+ error_text = req_error_text;
+ }
- sdap_account_info_complete(breq, dp_error, ret, "Service lookup failed");
+ sdap_handler_done(breq, dp_error, ret, error_text);
}
struct get_user_and_group_state {
@@ -1371,15 +1429,3 @@ errno_t sdap_get_user_and_group_recv(struct tevent_req *req, int *dp_error_out)
return EOK;
}
-
-static void sdap_get_user_and_group_done(struct tevent_req *req)
-{
- struct be_req *breq = tevent_req_callback_data(req, struct be_req);
- int ret;
- int dp_error;
-
- ret = sdap_get_user_and_group_recv(req, &dp_error);
- talloc_zfree(req);
-
- sdap_account_info_complete(breq, dp_error, ret, "Lookup by SID failed");
-}