diff options
author | Jakub Hrozek <jhrozek@redhat.com> | 2012-01-23 11:03:17 +0100 |
---|---|---|
committer | Stephen Gallagher <sgallagh@redhat.com> | 2012-01-27 09:02:02 -0500 |
commit | 3b121852048a7931f8a608527b760963e2ed2bb4 (patch) | |
tree | fb75788fbced0a8a5d191c5fae987e0a6999bdc1 /src | |
parent | 3b09b74bf65867d882af87ec60e2a517b15264a6 (diff) | |
download | sssd-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.c | 67 | ||||
-rw-r--r-- | src/responder/sudo/sudosrv_dp.c | 191 | ||||
-rw-r--r-- | src/responder/sudo/sudosrv_get_sudorules.c | 84 | ||||
-rw-r--r-- | src/responder/sudo/sudosrv_private.h | 8 |
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, |