2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher Stephen Gallagher <sgallagh@redhat.com>
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher Copyright (C) 2010 Red Hat
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher This program is free software; you can redistribute it and/or modify
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher it under the terms of the GNU General Public License as published by
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher the Free Software Foundation; either version 3 of the License, or
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher (at your option) any later version.
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher This program is distributed in the hope that it will be useful,
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher but WITHOUT ANY WARRANTY; without even the implied warranty of
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher GNU General Public License for more details.
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher You should have received a copy of the GNU General Public License
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher along with this program. If not, see <http://www.gnu.org/licenses/>.
e07d700ed9daf0cf96607fa2d72978cb2431b794Pavel Březina#include "providers/proxy/proxy_iface_generated.h"
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic int proxy_child_destructor(TALLOC_CTX *ctx)
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher talloc_get_type(ctx, struct proxy_child_ctx);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "Removing proxy child id [%d]\n", child_ctx->id);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher hret = hash_delete(child_ctx->auth_ctx->request_table, &key);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "Hash error [%d][%s]\n", hret, hash_error_string(hret));
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher /* Nothing we can do about this, so just continue */
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic struct tevent_req *proxy_child_init_send(TALLOC_CTX *mem_ctx,
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic void proxy_child_init_done(struct tevent_req *subreq);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic struct tevent_req *proxy_child_send(TALLOC_CTX *mem_ctx,
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher req = tevent_req_create(mem_ctx, &state, struct proxy_child_ctx);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Could not send PAM request to child\n");
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher /* Find an available key */
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher hash_has_key(auth_ctx->request_table, &key)) {
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher /* Handle overflow, zero is a reserved value
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher * Also handle the unlikely case where the next ID
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher * is still awaiting being run
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher /* We've looped through all possible integers! */
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_FATAL_FAILURE, "Serious error: queue is too long!\n");
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_TRACE_INTERNAL, "Queueing request [%lu]\n", key.ul);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher hret = hash_enter(auth_ctx->request_table,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Could not add request to the queue\n");
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher talloc_set_destructor((TALLOC_CTX *) state,
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher if (auth_ctx->running < auth_ctx->max_children) {
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher /* There's an available slot; start a child
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher * to handle the request
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher subreq = proxy_child_init_send(auth_ctx, state, auth_ctx);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Could not fork child process\n");
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher tevent_req_set_callback(subreq, proxy_child_init_done, req);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher /* If there was no available slot, it will be queued
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher * until a slot is available
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "All available child slots are full, queuing request\n");
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic int pc_init_destructor (TALLOC_CTX *ctx)
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher /* If the init request has died, forcibly kill the child */
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic void pc_init_sig_handler(struct tevent_context *ev,
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic void pc_init_timeout(struct tevent_context *ev,
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic struct tevent_req *proxy_child_init_send(TALLOC_CTX *mem_ctx,
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher req = tevent_req_create(mem_ctx, &state, struct pc_init_ctx);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Could not create tevent_req\n");
1a7529bf5f867b43e0475f7f9ac0cd8671fb16f1Pavel Březina "%s/proxy_child -d %#.4x --debug-timestamps=%d "
1a7529bf5f867b43e0475f7f9ac0cd8671fb16f1Pavel Březina "--debug-microseconds=%d%s --domain %s --id %d",
47db32cd9cb2147bb40909352569d7c8274365dbPavel Březina SSSD_LIBEXEC_PATH, debug_level, debug_timestamps,
1a7529bf5f867b43e0475f7f9ac0cd8671fb16f1Pavel Březina debug_microseconds, (debug_to_file ? " --debug-to-files" : ""),
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n");
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "Starting proxy child with args [%s]\n", state->command);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "fork failed [%d][%s].\n", ret, strerror(ret));
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher proxy_child_args = parse_args(state->command);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher execvp(proxy_child_args[0], proxy_child_args);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "Could not start proxy child [%s]: [%d][%s].\n",
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher else { /* parent */
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher /* Make sure to kill the child process if we abort */
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher talloc_set_destructor((TALLOC_CTX *)state, pc_init_destructor);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher state->sige = tevent_add_signal(auth_ctx->be->ev, req,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "tevent_add_signal failed.\n");
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher /* Save the init request to the child context.
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher * This is technically a layering violation,
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher * but it's the only sane way to be able to
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher * identify which client is which when it
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher * connects to the backend in
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher * client_registration()
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher /* Wait six seconds for the child to connect
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher * This is because the connection handler will add
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher * its own five-second timeout, and we don't want to
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher * be faster here.
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher state->timeout = tevent_add_timer(auth_ctx->be->ev, req,
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher /* processing will continue once the connection is received
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher * in proxy_client_init()
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic void pc_init_sig_handler(struct tevent_context *ev,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "SIGCHLD handler called with invalid child count\n");
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher req = talloc_get_type(pvt, struct tevent_req);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher init_ctx = tevent_req_data(req, struct pc_init_ctx);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_LIBS, "Waiting for child [%d].\n", init_ctx->pid);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher ret = waitpid(init_ctx->pid, &child_status, WNOHANG);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "waitpid failed [%d][%s].\n", ret, strerror(ret));
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher } else if (ret == 0) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "waitpid did not find a child with changed status.\n");
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "child [%d] exited with status [%d].\n", ret,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "child [%d] was terminate by signal [%d].\n", ret,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "child [%d] was stopped by signal [%d].\n", ret,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "child [%d] was resumed by delivery of SIGCONT.\n",
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "Child is still running, no new child is started.\n");
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic void pc_init_timeout(struct tevent_context *ev,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_OP_FAILURE, "Client timed out before Identification!\n");
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher req = talloc_get_type(ptr, struct tevent_req);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic errno_t proxy_child_init_recv(struct tevent_req *req,
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher state = tevent_req_data(req, struct pc_init_ctx);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher /* Unset the destructor since we initialized successfully.
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher * We don't want to kill the child now that it's properly
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher talloc_set_destructor((TALLOC_CTX *)state, NULL);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic void proxy_child_sig_handler(struct tevent_context *ev,
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic struct tevent_req *proxy_pam_conv_send(TALLOC_CTX *mem_ctx,
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic void proxy_pam_conv_done(struct tevent_req *subreq);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic void proxy_child_init_done(struct tevent_req *subreq) {
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher tevent_req_callback_data(subreq, struct tevent_req);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher tevent_req_data(req, struct proxy_child_ctx);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher ret = proxy_child_init_recv(subreq, &child_ctx->pid, &child_ctx->conn);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_FUNC, "Proxy child init failed [%d]\n", ret);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher /* An initialized child is available, awaiting the PAM command */
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher subreq = proxy_pam_conv_send(req, child_ctx->auth_ctx,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE,"Could not start PAM conversation\n");
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher tevent_req_set_callback(subreq, proxy_pam_conv_done, req);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher /* Add a signal handler for the child under the auth_ctx,
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher * that way if the child exits after completion of the
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher * request, it will still be handled.
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher sig_ctx = talloc_zero(child_ctx->auth_ctx, struct proxy_child_sig_ctx);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "tevent_add_signal failed.\n");
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher sige = tevent_add_signal(child_ctx->auth_ctx->be->ev,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "tevent_add_signal failed.\n");
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher /* Steal the signal context onto the signal event
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher * so that when the signal is freed, the context
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher * will go with it.
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic void remove_sige(struct tevent_context *ev,
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic void run_proxy_child_queue(struct tevent_context *ev,
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic void proxy_child_sig_handler(struct tevent_context *ev,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "SIGCHLD handler called with invalid child count\n");
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher sig_ctx = talloc_get_type(pvt, struct proxy_child_sig_ctx);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_LIBS, "Waiting for child [%d].\n", sig_ctx->pid);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher ret = waitpid(sig_ctx->pid, &child_status, WNOHANG);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "waitpid failed [%d][%s].\n", ret, strerror(ret));
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher } else if (ret == 0) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "waitpid did not found a child with changed status.\n");
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "child [%d] exited with status [%d].\n", ret,
5085d263f2f084778b1314fc5e808668c3758d82Lukas Slebodnik } else if (WIFSIGNALED(child_status) == true) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "child [%d] was terminated by signal [%d].\n", ret,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "child [%d] was stopped by signal [%d].\n", ret,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "child [%d] was resumed by delivery of SIGCONT.\n",
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "Child is still running, no new child is started.\n");
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "tevent_create_immediate failed.\n");
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher tevent_schedule_immediate(imm, ev, run_proxy_child_queue,
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher /* schedule another immediate timer to delete the sigchld handler */
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "tevent_create_immediate failed.\n");
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher tevent_schedule_immediate(imm2, ev, remove_sige, sige);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic void remove_sige(struct tevent_context *ev,
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic void proxy_pam_conv_reply(DBusPendingCall *pending, void *ptr);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic struct tevent_req *proxy_pam_conv_send(TALLOC_CTX *mem_ctx,
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher req = tevent_req_create(mem_ctx, &state, struct proxy_conv_ctx);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "dbus_message_new_method_call failed.\n");
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CONF_SETTINGS, "Sending request with the following data:\n");
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG_PAM_DATA(SSSDBG_CONF_SETTINGS, pd);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Failed to build message\n");
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher ret = sbus_conn_send(state->conn, msg, state->auth_ctx->timeout_ms,
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic void proxy_pam_conv_reply(DBusPendingCall *pending, void *ptr)
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_INTERNAL, "Handling pam conversation reply\n");
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher req = talloc_get_type(ptr, struct tevent_req);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher state = tevent_req_data(req, struct proxy_conv_ctx);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher reply = dbus_pending_call_steal_reply(pending);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "Severe error. A reply callback was called but no reply was"
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "received and no timeout occurred\n");
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher ret = dp_unpack_pam_response(reply, state->pd, &dbus_error);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_FATAL_FAILURE, "Failed to parse reply.\n");
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CONF_SETTINGS, "received: [%d][%s]\n",
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_FATAL_FAILURE, "Reply error [%s].\n",
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_FATAL_FAILURE, "Default... what now?.\n");
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher /* Kill the child */
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher /* Conversation is finished */
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic errno_t proxy_pam_conv_recv(struct tevent_req *req)
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic void proxy_pam_conv_done(struct tevent_req *subreq)
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher req = tevent_req_callback_data(subreq, struct tevent_req);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_FUNC, "Proxy PAM conversation failed [%d]\n", ret);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic int proxy_child_recv(struct tevent_req *req,
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher ctx = tevent_req_data(req, struct proxy_child_ctx);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagherstatic void run_proxy_child_queue(struct tevent_context *ev,
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher auth_ctx = talloc_get_type(pvt, struct proxy_auth_ctx);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher /* Launch next queued request */
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher iter = new_hash_iter_context(auth_ctx->request_table);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher while ((entry = iter->next(iter)) != NULL) {
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher req = talloc_get_type(entry->value.ptr, struct tevent_req);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher state = tevent_req_data(req, struct proxy_child_ctx);
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher /* Nothing pending on the queue */
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher if (auth_ctx->running < auth_ctx->max_children) {
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher /* There's an available slot; start a child
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher * to handle the request
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher subreq = proxy_child_init_send(auth_ctx, state, auth_ctx);
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Could not fork child process\n");
2dd3faebcd3cfd00efda38ffd2585d675e696b12Stephen Gallagher tevent_req_set_callback(subreq, proxy_child_init_done, req);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březinastatic void proxy_pam_handler_done(struct tevent_req *subreq);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina req = tevent_req_create(mem_ctx, &state, struct proxy_pam_handler_state);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina /* Queue the request and spawn a child if there is an available slot. */
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina subreq = proxy_child_send(state, proxy_auth_ctx, state->pd);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina tevent_req_set_callback(subreq, proxy_pam_handler_done, req);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported PAM task.\n");
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina /* TODO For backward compatibility we always return EOK to DP now. */
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březinastatic void proxy_pam_handler_done(struct tevent_req *subreq)
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina req = tevent_req_callback_data(subreq, struct tevent_req);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina state = tevent_req_data(req, struct proxy_pam_handler_state);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina ret = proxy_child_recv(subreq, state, &state->pd);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina /* Start the next auth in the queue, if any */
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina imm = tevent_create_immediate(state->be_ctx->ev);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "tevent_create_immediate failed.\n");
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina /* We'll still finish the current request, but we're
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina * likely to have problems if there are queued events
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina * if we've gotten into this state.
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina * Hopefully this is impossible, since freeing req
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina * above should guarantee that we have enough memory
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina * to create this immediate event.
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina tevent_schedule_immediate(imm, state->be_ctx->ev,
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina /* Check if we need to save the cached credentials */
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina if ((state->pd->cmd == SSS_PAM_AUTHENTICATE || state->pd->cmd == SSS_PAM_CHAUTHTOK)
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina && (state->pd->pam_status == PAM_SUCCESS) && state->be_ctx->domain->cache_credentials) {
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina ret = sss_authtok_get_password(state->pd->authtok, &password, NULL);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina /* password caching failures are not fatal errors */
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina DEBUG(SSSDBG_OP_FAILURE, "Failed to cache password\n");
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina ret = sysdb_cache_password(state->be_ctx->domain, state->pd->user, password);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina /* password caching failures are not fatal errors */
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina /* so we just log it any return */
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina DEBUG(SSSDBG_OP_FAILURE, "Failed to cache password (%d)[%s]!?\n",
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina /* TODO For backward compatibility we always return EOK to DP now. */