summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2012-01-23 11:03:17 +0100
committerStephen Gallagher <sgallagh@redhat.com>2012-01-27 09:02:02 -0500
commit3b121852048a7931f8a608527b760963e2ed2bb4 (patch)
treefb75788fbced0a8a5d191c5fae987e0a6999bdc1 /src
parent3b09b74bf65867d882af87ec60e2a517b15264a6 (diff)
downloadsssd-3b121852048a7931f8a608527b760963e2ed2bb4.tar.gz
sssd-3b121852048a7931f8a608527b760963e2ed2bb4.tar.bz2
sssd-3b121852048a7931f8a608527b760963e2ed2bb4.zip
Use the new SUDO request in DP and sudo responder
Also remove the old request implementation https://fedorahosted.org/sssd/ticket/1115
Diffstat (limited to 'src')
-rw-r--r--src/providers/data_provider_be.c67
-rw-r--r--src/responder/sudo/sudosrv_dp.c191
-rw-r--r--src/responder/sudo/sudosrv_get_sudorules.c84
-rw-r--r--src/responder/sudo/sudosrv_private.h8
4 files changed, 115 insertions, 235 deletions
diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
index f3e35f62..801dbd5f 100644
--- a/src/providers/data_provider_be.c
+++ b/src/providers/data_provider_be.c
@@ -662,6 +662,7 @@ static void be_sudo_handler_callback(struct be_req *req,
DBUS_TYPE_INVALID);
if (!dbret) {
DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to generate dbus reply\n"));
+ talloc_free(req);
return;
}
@@ -677,15 +678,17 @@ static void be_sudo_handler_callback(struct be_req *req,
static int be_sudo_handler(DBusMessage *message, struct sbus_connection *conn)
{
- dbus_bool_t dbus_ret;
DBusError dbus_error;
- DBusMessageIter iter;
DBusMessage *reply = NULL;
struct be_client *be_cli = NULL;
struct be_req *be_req = NULL;
struct be_sudo_req *be_sudo_req = NULL;
void *user_data = NULL;
int ret = 0;
+ uint32_t type;
+ char *filter;
+ const char *err_msg = NULL;
+ char *filter_val;
DEBUG(SSSDBG_TRACE_FUNC, ("Entering be_sudo_handler()\n"));
@@ -719,29 +722,54 @@ static int be_sudo_handler(DBusMessage *message, struct sbus_connection *conn)
be_req->pvt = reply;
be_req->fn = be_sudo_handler_callback;
- /* get and set sudo request data */
- be_sudo_req = talloc_zero(be_req, struct be_sudo_req);
- if (be_sudo_req == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_zero failed.\n"));
+ dbus_error_init(&dbus_error);
+
+ ret = dbus_message_get_args(message, &dbus_error,
+ DBUS_TYPE_UINT32, &type,
+ DBUS_TYPE_STRING, &filter,
+ DBUS_TYPE_INVALID);
+ if (!ret) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Failed, to parse message!\n"));
+ if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error);
+ ret = EIO;
+ err_msg = "dbus_message_get_args failed";
goto fail;
}
- if (dbus_message_iter_init(message, &iter)) {
- dbus_error_init(&dbus_error);
- dbus_ret = dbus_message_get_args(message, &dbus_error,
- DBUS_TYPE_STRING, &(be_sudo_req->username),
- DBUS_TYPE_INVALID);
-
- if (!dbus_ret) {
- if (dbus_error_is_set(&dbus_error)) {
- dbus_error_free(&dbus_error);
- }
+ if (type != BE_REQ_SUDO) {
+ /* No other are supported at the moment */
+ ret = EINVAL;
+ err_msg = "Invalid DP request type";
+ goto fail;
+ }
- DEBUG(SSSDBG_CRIT_FAILURE, ("dbus_message_get_args failed.\n"));
+ if (filter) {
+ if (strncmp(filter, "name=", 5) == 0) {
+ filter_val = &filter[5];
+ } else {
ret = EINVAL;
+ err_msg = "Invalid Filter";
goto fail;
}
+ } else {
+ ret = EINVAL;
+ err_msg = "Missing Filter Parameter";
+ goto fail;
}
+
+ /* get and set sudo request data */
+ be_sudo_req = talloc_zero(be_req, struct be_sudo_req);
+ if (be_sudo_req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_zero failed.\n"));
+ goto fail;
+ }
+
+ be_sudo_req->username = talloc_strdup(be_sudo_req, filter_val);
+ if (be_sudo_req->username == NULL) {
+ ret = ENOMEM;
+ goto fail;
+ }
+
be_req->req_data = be_sudo_req;
/* return an error if corresponding backend target is not configured */
@@ -756,6 +784,7 @@ static int be_sudo_handler(DBusMessage *message, struct sbus_connection *conn)
be_req);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, ("be_file_request failed.\n"));
+ err_msg = "Cannot file back end request";
goto fail;
}
@@ -763,8 +792,8 @@ static int be_sudo_handler(DBusMessage *message, struct sbus_connection *conn)
fail:
/* send reply back immediately */
- be_sudo_handler_callback(be_req, DP_ERR_FATAL, ret, strerror(ret));
-
+ be_sudo_handler_callback(be_req, DP_ERR_FATAL, ret,
+ err_msg ? err_msg : strerror(ret));
return EOK;
}
diff --git a/src/responder/sudo/sudosrv_dp.c b/src/responder/sudo/sudosrv_dp.c
index a5f2fdda..f544d293 100644
--- a/src/responder/sudo/sudosrv_dp.c
+++ b/src/responder/sudo/sudosrv_dp.c
@@ -30,197 +30,6 @@
#include "responder/common/responder.h"
#include "responder/sudo/sudosrv_private.h"
-struct sudo_dp_refresh_state {
- dbus_uint16_t err_maj;
- dbus_uint32_t err_min;
-};
-
-/* FIXME -- need to keep track of a running request
- * and just queue a callback
- * OR reuse the common dp requests
- */
-static void sudosrv_dp_process_reply(DBusPendingCall *pending, void *ptr);
-
-struct tevent_req * sudosrv_dp_refresh_send(struct resp_ctx *rctx,
- struct sss_domain_info *dom,
- const char *username)
-{
- struct be_conn *be_conn;
- struct sudo_dp_refresh_state *state;
- DBusMessage *msg;
- dbus_bool_t dbret;
- int ret;
- const int timeout = SSS_CLI_SOCKET_TIMEOUT / 2;
- struct tevent_req *req;
-
- /* Cache refresh requests need to be allocated on the responder context
- * so that they don't go away if a client disconnects. The worst-
- * case scenario here is that the cache is updated without any
- * client expecting a response.
- */
- req = tevent_req_create(rctx, &state, struct sudo_dp_refresh_state);
- if (!req) return NULL;
-
- /* double check dp_ctx has actually been initialized.
- * in some pathological cases it may happen that sudo starts up before
- * dp connection code is actually able to establish a connection.
- */
- ret = sss_dp_get_domain_conn(rctx, dom->name, &be_conn);
- if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- ("The Data Provider connection for %s is not available! "
- "This maybe a bug, it shouldn't happen!\n",
- dom->name));
- ret = EIO;
- goto error;
- }
-
- msg = dbus_message_new_method_call(NULL,
- DP_PATH,
- DP_INTERFACE,
- DP_METHOD_SUDOHANDLER);
- if (msg == NULL) {
- DEBUG(SSSDBG_FATAL_FAILURE, ("Out of memory?!\n"));
- ret = ENOMEM;
- goto error;
- }
-
- if (username != NULL) {
- dbret = dbus_message_append_args(msg,
- DBUS_TYPE_STRING, &username,
- DBUS_TYPE_INVALID);
- if (!dbret) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to generate dbus reply\n"));
- ret = EIO;
- goto error;
- }
- }
-
- DEBUG(SSSDBG_TRACE_FUNC, ("Sending SUDOers refresh request\n"));
- ret = sbus_conn_send(be_conn->conn, msg,
- timeout, sudosrv_dp_process_reply,
- req, NULL);
- dbus_message_unref(msg);
-
- return req;
-
-error:
- tevent_req_error(req, ret);
- tevent_req_post(req, rctx->ev);
- dbus_message_unref(msg);
-
- return req;
-}
-
-static int sudosrv_dp_get_reply(DBusPendingCall *pending,
- dbus_uint16_t *err_maj,
- dbus_uint32_t *err_min,
- char **err_msg)
-{
- DBusMessage *reply;
- DBusError dbus_error;
- dbus_bool_t ret;
- int type;
- int err = EOK;
-
- dbus_error_init(&dbus_error);
-
- reply = dbus_pending_call_steal_reply(pending);
- if (!reply) {
- /* reply should never be null. This function shouldn't be called
- * until reply is valid or timeout has occurred. If reply is NULL
- * here, something is seriously wrong and we should bail out.
- */
- DEBUG(0, ("Severe error. A reply callback was called but no reply was received and no timeout occurred\n"));
-
- err = EIO;
- goto done;
- }
-
- type = dbus_message_get_type(reply);
- switch (type) {
- case DBUS_MESSAGE_TYPE_METHOD_RETURN:
- ret = dbus_message_get_args(reply, &dbus_error,
- DBUS_TYPE_UINT16, err_maj,
- DBUS_TYPE_UINT32, err_min,
- DBUS_TYPE_STRING, err_msg,
- DBUS_TYPE_INVALID);
- if (!ret) {
- DEBUG(1,("Failed to parse message\n"));
- if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error);
- err = EIO;
- goto done;
- }
-
- DEBUG(4, ("Got reply (%u, %u, %s) from Data Provider\n",
- (unsigned int)*err_maj, (unsigned int)*err_min, *err_msg));
-
- break;
-
- case DBUS_MESSAGE_TYPE_ERROR:
- if (strcmp(dbus_message_get_error_name(reply),
- DBUS_ERROR_NO_REPLY) == 0) {
- err = ETIME;
- goto done;
- }
- DEBUG(0,("The Data Provider returned an error [%s]\n",
- dbus_message_get_error_name(reply)));
- /* Falling through to default intentionally*/
- default:
- /*
- * Timeout or other error occurred or something
- * unexpected happened.
- * It doesn't matter which, because either way we
- * know that this connection isn't trustworthy.
- * We'll destroy it now.
- */
-
- err = EIO;
- }
-
-done:
- dbus_pending_call_unref(pending);
- dbus_message_unref(reply);
-
- return err;
-}
-
-static void sudosrv_dp_process_reply(DBusPendingCall *pending, void *ptr)
-{
- struct tevent_req *req;
- errno_t ret;
- char *err_msg;
- struct sudo_dp_refresh_state *state;
-
- req = talloc_get_type(ptr, struct tevent_req);
- state = tevent_req_data(req, struct sudo_dp_refresh_state);
-
- ret = sudosrv_dp_get_reply(pending, &state->err_maj, &state->err_min, &err_msg);
- if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to get a reply from DP! "
- "err_maj: %d err_min: %d err_msg: [%s]\n",
- state->err_maj, state->err_min, err_msg ? err_msg : "none set"));
- tevent_req_error(req, EIO);
- return;
- }
-
- tevent_req_done(req);
-}
-
-errno_t sudosrv_dp_refresh_recv(struct tevent_req *req,
- dbus_uint16_t *_err_maj,
- dbus_uint32_t *_err_min)
-{
- struct sudo_dp_refresh_state *state;
- state = tevent_req_data(req, struct sudo_dp_refresh_state);
-
- if (_err_maj) *_err_maj = state->err_maj;
- if (_err_min) *_err_min = state->err_min;
-
- TEVENT_REQ_RETURN_ON_ERROR(req);
- return EOK;
-}
-
struct sss_dp_get_sudoers_info {
struct sss_domain_info *dom;
diff --git a/src/responder/sudo/sudosrv_get_sudorules.c b/src/responder/sudo/sudosrv_get_sudorules.c
index 45eecf56..fba8a85e 100644
--- a/src/responder/sudo/sudosrv_get_sudorules.c
+++ b/src/responder/sudo/sudosrv_get_sudorules.c
@@ -205,7 +205,8 @@ static void sudosrv_check_user_dp_callback(uint16_t err_maj, uint32_t err_min,
(unsigned int)err_maj, (unsigned int)err_min, err_msg));
}
- DEBUG(SSSDBG_TRACE_INTERNAL, ("Data Provider returned, check the cache again\n"));
+ DEBUG(SSSDBG_TRACE_INTERNAL,
+ ("Data Provider returned, check the cache again\n"));
dctx->check_provider = false;
ret = sudosrv_get_user(dctx);
/* FIXME - set entry into cache so that we don't perform initgroups too often */
@@ -236,46 +237,95 @@ done:
}
static errno_t sudosrv_get_sudorules_from_cache(struct sudo_dom_ctx *dctx);
-static void sudosrv_get_sudorules_dp_callback(struct tevent_req *req);
+static void
+sudosrv_get_sudorules_dp_callback(uint16_t err_maj, uint32_t err_min,
+ const char *err_msg, void *ptr);
+static void
+sudosrv_dp_req_done(struct tevent_req *req);
static errno_t sudosrv_get_rules(struct sudo_dom_ctx *dctx)
{
struct tevent_req *dpreq;
struct sudo_cmd_ctx *cmd_ctx = dctx->cmd_ctx;
+ struct dp_callback_ctx *cb_ctx = NULL;
/* FIXME - cache logic will be here. For now, just refresh
* the cache unconditionally */
- dpreq = sudosrv_dp_refresh_send(cmd_ctx->cli_ctx->rctx,
- dctx->domain, cmd_ctx->username);
+ dpreq = sss_dp_get_sudoers_send(cmd_ctx->cli_ctx,
+ cmd_ctx->cli_ctx->rctx,
+ dctx->domain, false,
+ SSS_DP_SUDO,
+ cmd_ctx->username);
if (dpreq == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
- ("Fatal: Sysdb CTX not found for this domain!\n"));
+ ("Cannot issue DP request.\n"));
return EIO;
}
- tevent_req_set_callback(dpreq, sudosrv_get_sudorules_dp_callback, dctx);
+
+ cb_ctx = talloc_zero(dctx, struct dp_callback_ctx);
+ if (!cb_ctx) {
+ talloc_zfree(dpreq);
+ return ENOMEM;
+ }
+
+ cb_ctx->callback = sudosrv_get_sudorules_dp_callback;
+ cb_ctx->ptr = dctx;
+ cb_ctx->cctx = dctx->cmd_ctx->cli_ctx;
+ cb_ctx->mem_ctx = dctx;
+
+ tevent_req_set_callback(dpreq, sudosrv_dp_req_done, cb_ctx);
return EAGAIN;
}
-static void sudosrv_get_sudorules_dp_callback(struct tevent_req *req)
+static void
+sudosrv_dp_req_done(struct tevent_req *req)
{
- struct sudo_dom_ctx *dctx;
+ struct dp_callback_ctx *cb_ctx =
+ tevent_req_callback_data(req, struct dp_callback_ctx);
+ struct sudo_dom_ctx *dctx =
+ talloc_get_type(cb_ctx->ptr, struct sudo_dom_ctx);
+
errno_t ret;
dbus_uint16_t err_maj;
dbus_uint32_t err_min;
+ char *err_msg;
- dctx = tevent_req_callback_data(req, struct sudo_dom_ctx);
-
- ret = sudosrv_dp_refresh_recv(req, &err_maj, &err_min);
- talloc_zfree(req);
+ ret = sss_dp_get_sudoers_recv(cb_ctx->mem_ctx, req,
+ &err_maj, &err_min,
+ &err_msg);
+ talloc_free(req);
if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE,
- ("Data provider returned an error [%d]: %s "
- "DBus error min: %d maj %d\n",
- ret, strerror(ret), err_maj, err_min));
- sudosrv_cmd_done(dctx, EIO);
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Fatal error, killing connection!\n"));
+ talloc_free(dctx->cmd_ctx->cli_ctx);
return;
}
+ cb_ctx->callback(err_maj, err_min, err_msg, cb_ctx->ptr);
+}
+
+static void
+sudosrv_get_sudorules_dp_callback(uint16_t err_maj, uint32_t err_min,
+ const char *err_msg, void *ptr)
+{
+ struct sudo_dom_ctx *dctx =
+ talloc_get_type(ptr, struct sudo_dom_ctx);
+ errno_t ret;
+
+ if (err_maj) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("Unable to get information from Data Provider\n"
+ "Error: %u, %u, %s\n"
+ "Will try to return what we have in cache\n",
+ (unsigned int)err_maj, (unsigned int)err_min, err_msg));
+
+ /* FIXME - cache or next domain? */
+ /* Loop to the next domain if possible */
+ if (dctx->domain->next && dctx->cmd_ctx->check_next) {
+ dctx->domain = dctx->domain->next;
+ dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
+ }
+ }
+
DEBUG(SSSDBG_TRACE_INTERNAL, ("About to get sudo rules from cache\n"));
ret = sudosrv_get_sudorules_from_cache(dctx);
if (ret != EOK) {
diff --git a/src/responder/sudo/sudosrv_private.h b/src/responder/sudo/sudosrv_private.h
index 82948fdc..fc4134b6 100644
--- a/src/responder/sudo/sudosrv_private.h
+++ b/src/responder/sudo/sudosrv_private.h
@@ -61,14 +61,6 @@ struct sss_cmd_table *get_sudo_cmds(void);
errno_t sudosrv_cmd_done(struct sudo_dom_ctx *dctx, int ret);
-struct tevent_req * sudosrv_dp_refresh_send(struct resp_ctx *rctx,
- struct sss_domain_info *dom,
- const char *username);
-
-errno_t sudosrv_dp_refresh_recv(struct tevent_req *req,
- dbus_uint16_t *_err_maj,
- dbus_uint32_t *_err_min);
-
errno_t sudosrv_get_sudorules(struct sudo_dom_ctx *dctx);
char * sudosrv_get_sudorules_parse_query(TALLOC_CTX *mem_ctx,