dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina/*
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina SSSD
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina proxy_init.c
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina Authors:
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina Stephen Gallagher <sgallagh@redhat.com>
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina Copyright (C) 2010 Red Hat
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina This program is free software; you can redistribute it and/or modify
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina it under the terms of the GNU General Public License as published by
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina the Free Software Foundation; either version 3 of the License, or
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina (at your option) any later version.
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina This program is distributed in the hope that it will be useful,
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina but WITHOUT ANY WARRANTY; without even the implied warranty of
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina GNU General Public License for more details.
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina You should have received a copy of the GNU General Public License
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina along with this program. If not, see <http://www.gnu.org/licenses/>.
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina*/
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina#include "util/util.h"
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina#include "providers/proxy/proxy_iface_generated.h"
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina#include "providers/proxy/proxy.h"
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březinastruct proxy_client {
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina struct proxy_auth_ctx *proxy_auth_ctx;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina struct sbus_connection *conn;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina struct tevent_timer *timeout;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina bool initialized;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina};
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březinastatic int proxy_client_register(struct sbus_request *sbus_req,
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina void *data,
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina uint32_t cli_id)
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina{
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina struct sbus_connection *conn;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina struct proxy_client *proxy_cli;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina int hret;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina hash_key_t key;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina hash_value_t value;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina struct tevent_req *req;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina struct proxy_child_ctx *child_ctx;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina struct pc_init_ctx *init_ctx;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina conn = sbus_req->conn;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina proxy_cli = talloc_get_type(data, struct proxy_client);
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina if (proxy_cli == NULL) {
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina DEBUG(SSSDBG_FATAL_FAILURE, "Connection holds no valid init data\n");
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina return EINVAL;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina }
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina /* First thing, cancel the timeout */
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina DEBUG(SSSDBG_CONF_SETTINGS,
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina "Cancel proxy client ID timeout [%p]\n", proxy_cli->timeout);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina talloc_zfree(proxy_cli->timeout);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina DEBUG(SSSDBG_FUNC_DATA, "Proxy client [%"PRIu32"] connected\n", cli_id);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina /* Check the hash table */
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina key.type = HASH_KEY_ULONG;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina key.ul = cli_id;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina if (!hash_has_key(proxy_cli->proxy_auth_ctx->request_table, &key)) {
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE,
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina "Unknown child ID. Killing the connection\n");
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina sbus_disconnect(proxy_cli->conn);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina return EIO;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina }
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina iface_proxy_client_Register_finish(sbus_req);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina hret = hash_lookup(proxy_cli->proxy_auth_ctx->request_table, &key, &value);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina if (hret != HASH_SUCCESS) {
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE,
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina "Hash error [%d]: %s\n", hret, hash_error_string(hret));
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina sbus_disconnect(conn);
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina return EIO;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina }
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina /* Signal that the child is up and ready to receive the request */
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina req = talloc_get_type(value.ptr, struct tevent_req);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina child_ctx = tevent_req_data(req, struct proxy_child_ctx);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina if (!child_ctx->running) {
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina /* This should hopefully be impossible, but protect
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina * against it anyway. If we're not marked running, then
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina * the init_req will be NULL below and things will
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina * break.
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina */
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "Client connection from a request "
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina "that's not marked as running\n");
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina return EIO;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina }
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina init_ctx = tevent_req_data(child_ctx->init_req, struct pc_init_ctx);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina init_ctx->conn = conn;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina tevent_req_done(child_ctx->init_req);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina child_ctx->init_req = NULL;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina return EOK;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina}
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březinastatic void proxy_client_timeout(struct tevent_context *ev,
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina struct tevent_timer *te,
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina struct timeval t,
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina void *ptr)
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina{
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina struct proxy_client *proxy_cli;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina DEBUG(SSSDBG_OP_FAILURE,
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina "Client timed out before Identification [%p]!\n", te);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina proxy_cli = talloc_get_type(ptr, struct proxy_client);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina sbus_disconnect(proxy_cli->conn);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina talloc_zfree(proxy_cli);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina /* If we time out here, we will also time out to
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina * pc_init_timeout(), so we'll finish the request
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina * there.
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina */
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina}
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březinaint proxy_client_init(struct sbus_connection *conn, void *data)
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina{
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina struct proxy_auth_ctx *auth_ctx;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina struct proxy_client *proxy_cli;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina struct timeval tv;
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina errno_t ret;
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina static struct iface_proxy_client iface_proxy_client = {
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina { &iface_proxy_client_meta, 0 },
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina .Register = proxy_client_register,
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina };
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina auth_ctx = talloc_get_type(data, struct proxy_auth_ctx);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina /* When connection is lost we also free the client. */
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina proxy_cli = talloc_zero(conn, struct proxy_client);
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina if (proxy_cli == NULL) {
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory, killing connection.\n");
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina talloc_free(conn);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina return ENOMEM;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina }
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina proxy_cli->proxy_auth_ctx = auth_ctx;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina proxy_cli->conn = conn;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina proxy_cli->initialized = false;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina /* Setup timeout in case client fails to register himself in time. */
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina tv = tevent_timeval_current_ofs(5, 0);
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina proxy_cli->timeout = tevent_add_timer(auth_ctx->be->ev, proxy_cli, tv,
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina proxy_client_timeout, proxy_cli);
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina if (proxy_cli->timeout == NULL) {
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina /* Connection is closed in the caller. */
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory, killing connection\n");
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina return ENOMEM;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina }
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina DEBUG(SSSDBG_CONF_SETTINGS,
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina "Set-up proxy client ID timeout [%p]\n", proxy_cli->timeout);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina /* Setup D-Bus interfaces and methods. */
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina ret = sbus_conn_register_iface(conn, &iface_proxy_client.vtable,
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina PROXY_CHILD_PATH, proxy_cli);
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina if (ret != EOK) {
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina /* Connection is closed in the caller. */
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina DEBUG(SSSDBG_FATAL_FAILURE, "Unable to register D-Bus interface, "
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina "killing connection [%d]: %s\n", ret, sss_strerror(ret));
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina return ret;
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina }
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina return ret;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina}