monitor.c revision 632fc5d8991d167eea20769c823163551c3f1d8c
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher Service monitor
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher Copyright (C) Simo Sorce 2008
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher This program is free software; you can redistribute it and/or modify
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher it under the terms of the GNU General Public License as published by
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher the Free Software Foundation; either version 3 of the License, or
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (at your option) any later version.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher This program is distributed in the hope that it will be useful,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher but WITHOUT ANY WARRANTY; without even the implied warranty of
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher GNU General Public License for more details.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher You should have received a copy of the GNU General Public License
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher along with this program. If not, see <http://www.gnu.org/licenses/>.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* Needed for res_init() */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#include "responder/common/responder_sbus.h"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* terminate the child after this interval by default if it
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * doesn't shutdown on receiving SIGTERM */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* TODO: get the restart related values from config */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#define MONITOR_RESTART_CNT_INTERVAL_RESET 30
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* maximum allowed number of service restarts if the restarts
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * were less than MONITOR_RESTART_CNT_INTERVAL_RESET apart, which would
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * indicate a crash after startup or after every request */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* The services are restarted with a delay in case the restart was
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * hitting a race condition where the DP is not ready yet either.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * The MONITOR_MAX_RESTART_DELAY defines the maximum delay between
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* name of the monitor server instance */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* Special value to leave the Kerberos Replay Cache set to use
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * the libkrb5 defaults
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#define KRB5_RCACHE_DIR_DISABLE "__LIBKRB5_DEFAULTS__"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* Warning messages */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#define CONF_FILE_PERM_ERROR_MSG "Cannot read config file %s. Please check "\
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "that the file is accessible only by the "\
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "owner and owned by root.root.\n"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* For running unprivileged services */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int start_service(struct mt_svc *mt_svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int monitor_service_init(struct sbus_connection *conn, void *data);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int service_signal_reset_offline(struct mt_svc *svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int get_service_config(struct mt_ctx *ctx, const char *name,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int get_provider_config(struct mt_ctx *ctx, const char *name,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int add_new_service(struct mt_ctx *ctx,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int add_new_provider(struct mt_ctx *ctx,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int mark_service_as_started(struct mt_svc *svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int monitor_cleanup(void);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void network_status_change_cb(void *cb_data)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mt_ctx *ctx = (struct mt_ctx *) cb_data;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_TRACE_INTERNAL, "A networking status change detected "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "signaling providers to reset offline status\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (iter = ctx->svc_list; iter; iter = iter->next) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Don't signal services, only providers */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* dbus_get_monitor_version
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * Return the monitor version over D-BUS */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int get_monitor_version(struct sbus_request *dbus_req, void *data)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return sbus_request_return_and_finish(dbus_req,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int add_svc_conn_spy(struct mt_svc *svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* registers a new client.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * if operation is successful also sends back the Monitor version */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int client_registration(struct sbus_request *dbus_req, void *data)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mini = talloc_get_type(data, struct mon_init_conn);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE, "Connection holds no valid init data\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* First thing, cancel the timeout */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher dbret = dbus_message_get_args(dbus_req->message, &dbus_error,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Failed to parse message, killing connection\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* FIXME: should we just talloc_zfree(conn) ? */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Received ID registration: (%s,%d)\n", svc_name, svc_ver);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* search this service in the list */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = strcasecmp(svc->identity, svc_name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Unable to find peer [%s] in list of services,"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* FIXME: should we just talloc_zfree(conn) ? */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Fill in svc structure with connection data */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_CRIT_FAILURE, "Failed to mark service [%s]!\n", svc_name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* reply that all is ok */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* init complete, get rid of temp init context */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mt_svc *svc = talloc_get_type(mem, struct mt_svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* try to delist service */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Cancel any pending calls */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* svc is being freed, neutralize the spy */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher talloc_set_destructor((TALLOC_CTX *)svc->conn_spy, NULL);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (svc->type == MT_SVC_SERVICE && svc->svc_started
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher && svc->mt_ctx != NULL && svc->mt_ctx->started_services > 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct svc_spy *spy = talloc_get_type(mem, struct svc_spy);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* svc->conn has been freed, NULL the pointer in svc */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int add_svc_conn_spy(struct mt_svc *svc)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher talloc_set_destructor((TALLOC_CTX *)spy, svc_spy_destructor);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void svc_child_info(struct mt_svc *svc, int wait_status)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Child [%d] exited with code [%d]\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Child [%d] terminated with signal [%d]\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Child [%d] did not exit cleanly\n", svc->pid);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Forcibly kill this child, just in case */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Let us get caught by another
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * call to the SIGCHLD handler
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int mark_service_as_started(struct mt_svc *svc)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_FUNC_DATA, "Marking %s as started.\n", svc->name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* we need to attach a spy to the connection structure so that if some code
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * frees it we can zero it out in the service structure. Otherwise we may
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * try to access or even free, freed memory. */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE, "Failed to attch spy\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* check if all providers are up */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (iter = ctx->svc_list; iter; iter = iter->next) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (iter->provider && !iter->svc_started) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Still waiting on %s provider.\n", iter->name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* there are still unstarted providers */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_CONF_SETTINGS, "Now starting services!\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* then start all services */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher add_new_service(ctx, ctx->services[i], 0);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (ctx->started_services == ctx->num_services) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Initialization is complete, terminate parent process if in daemon
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * mode. Make sure we send the signal to the right process */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (ctx->parent_pid <= 1 || ctx->parent_pid != getppid()) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* the parent process was already terminated */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_MINOR_FAILURE, "Invalid parent pid: %d\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_TRACE_FUNC, "SSSD is initialized, "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "terminating parent process\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE, "Unable to terminate parent "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "process [%d]: %s\n", ret, strerror(ret));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void services_startup_timeout(struct tevent_context *ev,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mt_ctx *ctx = talloc_get_type(ptr, struct mt_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_TRACE_FUNC, "Handling timeout\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_CRIT_FAILURE, "Providers did not start in time, "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "forcing services startup!\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_CONF_SETTINGS, "Now starting services!\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* then start all services */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher add_new_service(ctx, ctx->services[i], 0);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int add_services_startup_timeout(struct mt_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* 5 seconds should be plenty */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher to = tevent_add_timer(ctx->ev, ctx, tv, services_startup_timeout, ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE,"Out of memory?!\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* monitor_dbus_init
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * Set up the monitor service as a D-BUS Server */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int monitor_dbus_init(struct mt_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = monitor_get_sbus_address(ctx, &monitor_address);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* If a service is running as unprivileged user, we need to make sure this
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * user can access the monitor sbus server. root is still king, so we don't
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * lose any access.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = sbus_new_server(ctx, ctx->ev, monitor_address, ctx->uid, ctx->gid,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher false, &ctx->sbus_srv, monitor_service_init, ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void monitor_restart_service(struct mt_svc *svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void reload_reply(DBusPendingCall *pending, void *data)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mt_svc *svc = talloc_get_type(data, struct mt_svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher reply = dbus_pending_call_steal_reply(pending);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* reply should never be null. This function shouldn't be called
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * until reply is valid or timeout has occurred. If reply is NULL
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * here, something is seriously wrong and we should bail out.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "A reply callback was called but no reply was received"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher " and no timeout occurred\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Destroy this connection */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* TODO: Handle cases where the call has timed out or returned
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * with an error.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int service_signal_dns_reload(struct mt_svc *svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int monitor_update_resolv(struct config_file_ctx *file_ctx,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_OP_FAILURE, "Resolv.conf has been updated. Reloading.\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Signal all services to reload their DNS configuration */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for(cur_svc = file_ctx->mt_ctx->svc_list; cur_svc; cur_svc = cur_svc->next) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int service_signal(struct mt_svc *svc, const char *svc_signal)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (svc->provider && strcasecmp(svc->provider, "local") == 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* The local provider requires no signaling */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Avoid a race condition where we are trying to
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * order a service to reload that hasn't started
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Could not signal service [%s].\n", svc->name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Out of memory trying to allocate memory to invoke: %s\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int service_signal_dns_reload(struct mt_svc *svc)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return service_signal(svc, MON_CLI_IFACE_RESINIT);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int service_signal_offline(struct mt_svc *svc)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return service_signal(svc, MON_CLI_IFACE_GOOFFLINE);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int service_signal_reset_offline(struct mt_svc *svc)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return service_signal(svc, MON_CLI_IFACE_RESETOFFLINE);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int service_signal_rotate(struct mt_svc *svc)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return service_signal(svc, MON_CLI_IFACE_ROTATELOGS);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int service_signal_clear_memcache(struct mt_svc *svc)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return service_signal(svc, MON_CLI_IFACE_CLEARMEMCACHE);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int service_signal_clear_enum_cache(struct mt_svc *svc)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return service_signal(svc, MON_CLI_IFACE_CLEARENUMCACHE);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int service_signal_sysbus_reconnect(struct mt_svc *svc)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return service_signal(svc, MON_CLI_IFACE_SYSBUSRECONNECT);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int check_domain_ranges(struct sss_domain_info *domains)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct sss_domain_info *dom = domains, *other = NULL;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (dom->id_max && dom->id_min > dom->id_max) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Domain '%s' does not have a valid ID range\n", dom->name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher id_max = MIN((dom->id_max ? dom->id_max : UINT32_MAX),
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (other->id_max ? other->id_max : UINT32_MAX));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Domains '%s' and '%s' overlap in range %u - %u\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int check_local_domain_unique(struct sss_domain_info *domains)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (strcasecmp(dom->provider, "local") == 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic errno_t add_implicit_services(struct confdb_ctx *cdb, TALLOC_CTX *mem_ctx,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = confdb_get_string_as_list(cdb, tmp_ctx,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_OP_FAILURE, "No domains configured!\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (c = 0; domain_names[c] != NULL; c++) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher conf_path = talloc_asprintf(tmp_ctx, CONFDB_DOMAIN_PATH_TMPL,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = confdb_get_string(cdb, tmp_ctx, conf_path,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher CONFDB_DOMAIN_ID_PROVIDER, NULL, &id_provider);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_OP_FAILURE, "id_provider is not set for "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "domain [%s], trying next domain.\n", domain_names[c]);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (strcasecmp(id_provider, "IPA") == 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_OP_FAILURE, "Failed to get id_provider for " \
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "domain [%s], trying next domain.\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (BUILD_WITH_PAC_RESPONDER && add_pac &&
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher !string_in_list("pac", *_services, false)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = add_string_to_list(mem_ctx, "pac", _services);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_OP_FAILURE, "add_string_to_list failed.\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic char *check_services(char **services)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher const char * const *known_services = get_known_services();
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Check if services we are about to start are in the list if known */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (i = 0; services[i]; i++) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (strcasecmp(services[i], known_services[ii]) == 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int get_service_user(struct mt_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = confdb_get_string(ctx->cdb, ctx, CONFDB_MONITOR_CONF_ENTRY,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE, "Failed to get the user to run as\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = sss_user_by_name_or_uid(user_str, &ctx->uid, &ctx->gid);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE, "Failed to set allowed UIDs.\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int get_monitor_config(struct mt_ctx *ctx)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx->service_id_timeout = timeout_seconds * 1000; /* service_id_timeout is in ms */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = confdb_get_string_as_list(ctx->cdb, ctx,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE, "No services configured!\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = add_implicit_services(ctx->cdb, ctx, &ctx->services);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_OP_FAILURE, "Failed to add implicit configured "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "services. Some functionality might "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "be missing\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE, "Invalid service %s\n", badsrv);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (i = 0; ctx->services[i] != NULL; i++) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_CRIT_FAILURE, "Failed to get the unprivileged user\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = confdb_get_domains(ctx->cdb, &ctx->domains);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE, "No domains configured.\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = check_local_domain_unique(ctx->domains);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE, "More than one local domain configured.\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Check UID/GID overlaps */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher/* This is a temporary function that returns false if the service
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * being started was only tested when running as root.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic bool svc_supported_as_nonroot(const char *svc_name)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int get_service_config(struct mt_ctx *ctx, const char *name,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher talloc_set_destructor((TALLOC_CTX *)svc, svc_destructor);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher path = talloc_asprintf(svc, CONFDB_SERVICE_PATH_TMPL, svc->name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = confdb_get_string(ctx->cdb, svc, path,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE,"Failed to start service '%s'\n", svc->name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (svc_supported_as_nonroot(svc->name)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher svc, "%s/sssd_%s", SSSD_LIBEXEC_PATH, svc->name
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher svc->command = talloc_asprintf_append(svc->command,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (cmdline_debug_level != SSSDBG_UNRESOLVED) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher svc->command, " -d %#.4x", cmdline_debug_level
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (cmdline_debug_timestamps != SSSDBG_TIMESTAMP_UNRESOLVED) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher svc->command, " --debug-timestamps=%d", cmdline_debug_timestamps
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (cmdline_debug_microseconds != SSSDBG_MICROSECONDS_UNRESOLVED) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int add_new_service(struct mt_ctx *ctx,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = get_service_config(ctx, name, &svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE,"Failed to start service '%s'\n", svc->name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int get_provider_config(struct mt_ctx *ctx, const char *name,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher talloc_set_destructor((TALLOC_CTX *)svc, svc_destructor);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher svc->identity = talloc_asprintf(svc, "%%BE_%s", svc->name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher path = talloc_asprintf(svc, CONFDB_DOMAIN_PATH_TMPL, name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = confdb_get_string(ctx->cdb, svc, path,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Failed to find ID provider from [%s] configuration\n", name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = confdb_get_string(ctx->cdb, svc, path,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Failed to find command from [%s] configuration\n", name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* if no provider is present do not run the domain */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* if there are no custom commands, build a default one */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher svc, "%s/sssd_be --domain %s", SSSD_LIBEXEC_PATH, svc->name
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher svc->command = talloc_asprintf_append(svc->command,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (cmdline_debug_level != SSSDBG_UNRESOLVED) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher svc->command, " -d %#.4x", cmdline_debug_level
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (cmdline_debug_timestamps != SSSDBG_TIMESTAMP_UNRESOLVED) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher svc->command, " --debug-timestamps=%d", cmdline_debug_timestamps
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (cmdline_debug_microseconds != SSSDBG_MICROSECONDS_UNRESOLVED) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int add_new_provider(struct mt_ctx *ctx,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = get_provider_config(ctx, name, &svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Could not get provider configuration for [%s]\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (strcasecmp(svc->provider, "local") == 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* The LOCAL provider requires no back-end currently
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * We'll add it to the service list, but we don't need
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE,"Failed to start service '%s'\n", svc->name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void monitor_hup(struct tevent_context *ev,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mt_ctx *ctx = talloc_get_type(private_data, struct mt_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_CRIT_FAILURE, "Received SIGHUP.\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Send D-Bus message to other services to rotate their logs.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * NSS service receives also message to clear memory caches. */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for(cur_svc = ctx->svc_list; cur_svc; cur_svc = cur_svc->next) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (!strcmp(NSS_SBUS_SERVICE_NAME, cur_svc->name)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (!strcmp(SSS_AUTOFS_SBUS_SERVICE_NAME, cur_svc->name)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Error removing pidfile! (%d [%s])\n", ret, strerror(ret));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void monitor_quit(struct mt_ctx *mt_ctx, int ret)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_IMPORTANT_INFO, "Returned with: %d\n", ret);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Kill all of our known children manually */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* The local provider has no PID */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Terminating [%s][%d]\n", svc->name, svc->pid);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_CRIT_FAILURE, "Couldn't kill [%s][%d]: [%s]\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher pid = waitpid(svc->pid, &status, WNOHANG);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* An error occurred while waiting */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "[%d][%s] while waiting for [%s]\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Forcibly kill this child */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher } else if (pid != 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Child [%s] exited gracefully\n", svc->name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Child [%s] terminated with a signal\n", svc->name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Child [%s] did not exit cleanly\n", svc->name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Forcibly kill this child */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Sleep 10ms and try again */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Kill any remaining children in our process group, just in case
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * we have any leftover children we don't expect. For example, if
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * a krb5_child or ldap_child is running at the same moment.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void monitor_quit_signal(struct tevent_context *ev,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mt_ctx *mt_ctx = talloc_get_type(private_data, struct mt_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_TRACE_INTERNAL, "Received shutdown command\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_IMPORTANT_INFO, "Monitor received %s: terminating "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void signal_res_init(struct mt_ctx *monitor)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_OP_FAILURE, "Reloading Resolv.conf.\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for(cur_svc = monitor->svc_list; cur_svc; cur_svc = cur_svc->next) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void signal_offline(struct tevent_context *ev,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher monitor = talloc_get_type(private_data, struct mt_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Signaling providers to go offline immediately.\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Signal all providers to immediately go offline */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for(cur_svc = monitor->svc_list; cur_svc; cur_svc = cur_svc->next) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Don't signal services, only providers */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void signal_offline_reset(struct tevent_context *ev,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher monitor = talloc_get_type(private_data, struct mt_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Signaling providers to reset offline immediately.\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for(cur_svc = monitor->svc_list; cur_svc; cur_svc = cur_svc->next) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (strcmp(SSS_IFP_SBUS_SERVICE_NAME, cur_svc->name) == 0) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int monitor_ctx_destructor(void *mem)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mt_ctx *mon = talloc_get_type(mem, struct mt_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* zero out references in svcs so that they don't try
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * to access the monitor context on process shutdown */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (svc = mon->svc_list; svc; svc = svc->next) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * This function should not be static otherwise gcc does some special kind of
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * optimisations which should not happen according to code: chown (unlink)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * failed (return -1) but errno was zero.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * As a result of this * warning is printed ‘monitor’ may be used
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * uninitialized in this function. Instead of checking errno for 0
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * it's better to disable optimisation(in-lining) of this function.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallaghererrno_t load_configuration(TALLOC_CTX *mem_ctx,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx = talloc_zero(mem_ctx, struct mt_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher talloc_set_destructor((TALLOC_CTX *)ctx, monitor_ctx_destructor);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher cdb_file = talloc_asprintf(ctx, "%s/%s", DB_PATH, CONFDB_FILE);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE,"Out of memory, aborting!\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = confdb_setup(ctx, cdb_file, config_file, config_dir, &ctx->cdb);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE, "Unable to setup ConfDB [%d]: %s\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Validate the configuration in the database */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Read in the monitor's configuration */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Allow configuration database to be accessible
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * when SSSD runs as nonroot */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = chown(cdb_file, ctx->uid, ctx->gid);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "chown failed for [%s]: [%d][%s].\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic errno_t monitor_config_file_fallback(TALLOC_CTX *mem_ctx,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void process_config_file(struct tevent_context *ev,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void config_file_changed(struct tevent_context *ev,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher file_ctx = talloc_get_type(data, struct config_file_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Skip updating. It's already queued for update.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* We will queue the file for update in one second.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * This way, if there is a script writing to the file
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * repeatedly, we won't be attempting to update multiple
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher te = tevent_add_timer(ev, ev, tv, process_config_file, file_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Unable to queue config file update! Exiting.\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void rewatch_config_file(struct tevent_context *ev,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void process_config_file(struct tevent_context *ev,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher file_ctx = talloc_get_type(ptr, struct config_file_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_CRIT_FAILURE, "Processing config file changes\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher in_event = talloc(tmp_ctx, struct inotify_event);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher len = sss_atomic_read_s(file_ctx->mt_ctx->inotify_fd, in_event,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sizeof(struct inotify_event));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Critical error reading inotify file descriptor [%d]: %s\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Read in the name, even though we don't use it,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * so that read ptr is in the right place
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher name = talloc_size(tmp_ctx, in_event->len);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher len = sss_atomic_read_s(file_ctx->mt_ctx->inotify_fd, name, in_event->len);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Critical error reading inotify file descriptor [%d]: %s\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (cb = file_ctx->callbacks; cb; cb = cb->next) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE, "Unknown watch descriptor\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Some text editors will move a new file on top of the
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * existing one instead of modifying it. In this case,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * the kernel will send us an IN_IGNORE signal.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * We will try to open a new watch descriptor on the
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_FUNC_DATA, "Restoring inotify watch.\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rw_ctx = talloc(file_ctx, struct rewatch_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Could not restore inotify watch. Quitting!\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher tev = tevent_add_timer(ev, rw_ctx, tv, rewatch_config_file, rw_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Could not restore inotify watch. Quitting!\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Tell the monitor to signal the children */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void rewatch_config_file(struct tevent_context *ev,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher rw_ctx = talloc_get_type(ptr, struct rewatch_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Retry six times at five-second intervals before giving up */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Could not restore inotify watch. Switching to polling!\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher err = monitor_config_file_fallback(file_ctx->parent_ctx,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* A new callback was created in monitor_config_file_fallback()*/
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher cb->wd = inotify_add_watch(file_ctx->mt_ctx->inotify_fd,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Could not add inotify watch for file [%s]. Error [%d:%s]\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher tev = tevent_add_timer(ev, ev, tv, rewatch_config_file, rw_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Could not restore inotify watch. Quitting!\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Tell the monitor to signal the children */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#endif /* HAVE_INOTIFY */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void poll_config_file(struct tevent_context *ev,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher file_ctx = talloc_get_type(ptr,struct config_file_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (cb = file_ctx->callbacks; cb; cb = cb->next) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Could not stat file [%s]. Error [%d:%s]\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* TODO: If the config file is missing, should we shut down? */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Parse the configuration file and signal the children */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Note: this will fire if the modification time changes into the past
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * as well as the future.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_CRIT_FAILURE, "Config file changed\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Tell the monitor to signal the children */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher file_ctx->timer = tevent_add_timer(ev, file_ctx->parent_ctx, tv,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Error: Config file no longer monitored for changes!\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int try_inotify(struct config_file_ctx *file_ctx, const char *filename,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Monitoring the file descriptor should be global */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Set up inotify to monitor the config file for changes */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher file_ctx->mt_ctx->inotify_fd = inotify_init();
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Could not initialize inotify, error [%d:%s]\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher fd_args = fcntl(file_ctx->mt_ctx->inotify_fd, F_GETFL, NULL);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Could not set nonblocking */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = fcntl(file_ctx->mt_ctx->inotify_fd, F_SETFL, fd_args);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Could not set nonblocking */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Add the inotify file descriptor to the TEvent context */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher tfd = tevent_add_fd(file_ctx->mt_ctx->ev, file_ctx,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher cb = talloc_zero(file_ctx, struct config_file_callback);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher cb->filename = talloc_strdup(cb, filename);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher cb->wd = inotify_add_watch(file_ctx->mt_ctx->inotify_fd,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Could not add inotify watch for file [%s]. Error [%d:%s]\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#endif /* HAVE_INOTIFY */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int monitor_config_file(TALLOC_CTX *mem_ctx,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "file [%s] is missing. Will not update online status "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Could not stat file [%s]. Error [%d:%s]\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx->file_ctx = talloc_zero(mem_ctx, struct config_file_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = try_inotify(ctx->file_ctx, file, fn);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Could not monitor file with inotify, fall back to polling */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = monitor_config_file_fallback(mem_ctx, ctx, file, fn, true);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic errno_t monitor_config_file_fallback(TALLOC_CTX *mem_ctx,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "file [%s] is missing. Will not update online status "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Could not stat file [%s]. Error [%d:%s]\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher cb = talloc_zero(ctx->file_ctx, struct config_file_callback);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx->file_ctx->timer = tevent_add_timer(ctx->ev, mem_ctx, tv,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void missing_resolv_conf(struct tevent_context *ev,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mt_ctx *ctx = talloc_get_type(data, struct mt_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = monitor_config_file(ctx, ctx, RESOLV_CONF_PATH,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher tv = tevent_timeval_current_ofs(MISSING_RESOLV_CONF_POLL_TIME, 0);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher te = tevent_add_timer(ctx->ev, ctx, tv, missing_resolv_conf, ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "tevent_add_timer failed. resolv.conf will be ignored.\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Monitor_config_file failed. resolv.conf will be ignored.\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int monitor_process_init(struct mt_ctx *ctx,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Set up the environment variable for the Kerberos Replay Cache */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (strcmp(rcachedir, KRB5_RCACHE_DIR_DISABLE) != 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = setenv("KRB5RCACHEDIR", rcachedir, 1);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Unable to set KRB5RCACHEDIR: %s."
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Will attempt to use libkrb5 defaults\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Set up an event handler for a SIGHUP */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher tes = tevent_add_signal(ctx->ev, ctx, SIGHUP, 0,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Set up an event handler for a SIGINT */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher tes = tevent_add_signal(ctx->ev, ctx, SIGINT, 0,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Set up an event handler for a SIGTERM */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher tes = tevent_add_signal(ctx->ev, ctx, SIGTERM, 0,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Handle SIGUSR1 (tell all providers to go offline) */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher tes = tevent_add_signal(ctx->ev, ctx, SIGUSR1, 0,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Handle SIGUSR2 (tell all providers to go reset offline) */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher tes = tevent_add_signal(ctx->ev, ctx, SIGUSR2, 0,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Set up the SIGCHLD handler */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = sss_sigchld_init(ctx, ctx->ev, &ctx->sigchld_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher This feature is incomplete and can leave the SSSD in a bad state if the
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher config file is changed while the SSSD is running.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher Uncomment this once the backends are honoring reloadConfig()
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Watch for changes to the confdb config file */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = monitor_config_file(ctx, ctx, config_file, monitor_signal_reconf,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Watch for changes to the DNS resolv.conf */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = monitor_config_file(ctx, ctx, RESOLV_CONF_PATH,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher tv = tevent_timeval_current_ofs(MISSING_RESOLV_CONF_POLL_TIME, 0);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher te = tevent_add_timer(ctx->ev, ctx, tv, missing_resolv_conf, ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE, "resolv.conf will be ignored\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Avoid a startup race condition between process.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * We need to handle DB upgrades or DB creation only
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * in one process before all other start.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = sysdb_init_ext(tmp_ctx, ctx->domains, &db_up_ctx,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Initialize D-BUS Server
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * The monitor will act as a D-BUS server for all
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * SSSD processes */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = setup_netlink(ctx, ctx->ev, network_status_change_cb,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Cannot set up listening for network notifications\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* start providers */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher for (dom = ctx->domains; dom; dom = get_next_domain(dom, 0)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = add_new_provider(ctx, dom->name, 0);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* now set the services stratup timeout *
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * (responders will be started automatically when all
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * providers are up and running or when the tomeout
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* No providers start services immediately
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * Normally this means only LOCAL is configured */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher add_new_service(ctx, ctx->services[i], 0);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void init_timeout(struct tevent_context *ev,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_OP_FAILURE, "Client timed out before Identification!\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mini = talloc_get_type(ptr, struct mon_init_conn);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * monitor_service_init
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * Set up a timeout function and temporary connection structure.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * If the client does not identify before the timeout kicks in,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * the client is forcibly disconnected.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int monitor_service_init(struct sbus_connection *conn, void *data)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_TRACE_FUNC, "Initializing D-BUS Service\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ctx = talloc_get_type(data, struct mt_ctx);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mini = talloc(conn, struct mon_init_conn);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE,"Out of memory?!\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Allow access from the SSSD user */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* 10 seconds should be plenty */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mini->timeout = tevent_add_timer(ctx->ev, mini, tv, init_timeout, mini);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE,"Out of memory?!\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return sbus_conn_register_iface(conn, &monitor_methods.vtable,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void service_startup_handler(struct tevent_context *ev,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic int start_service(struct mt_svc *svc)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_CONF_SETTINGS,"Queueing service %s for startup\n", svc->name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Add a timed event to start up the service.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * We have to do this in order to avoid a race
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * condition where the service being started forks
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * and attempts to connect to the SBUS before
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * the monitor is serving it.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher te = tevent_add_timer(svc->mt_ctx->ev, svc, tv,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Unable to queue service %s for startup\n", svc->name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void mt_svc_exit_handler(int pid, int wait_status, void *pvt);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void service_startup_handler(struct tevent_context *ev,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher mt_svc = talloc_get_type(ptr, struct mt_svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Could not fork child to start service [%s]. "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Handle process exit */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Could not register sigchld handler.\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Should we exit here? For now, we'll hope this
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * child never dies, because we can't restart it.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DLIST_ADD(mt_svc->mt_ctx->svc_list, mt_svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* If we are here, exec() has failed
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * Print errno and abort quickly */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Could not exec %s, reason: %s\n", mt_svc->command, strerror(errno));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* We have to call _exit() instead of exit() here
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * because a bug in D-BUS will cause the server to
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * close its socket at exit() */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void mt_svc_restart(struct tevent_context *ev,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher svc = talloc_get_type(ptr, struct mt_svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_TRACE_FUNC, "Scheduling service %s for restart %d\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher add_new_service(svc->mt_ctx, svc->name, svc->restarts + 1);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher } else if (svc->type == MT_SVC_PROVIDER) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher add_new_provider(svc->mt_ctx, svc->name, svc->restarts + 1);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Invalid type? */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "BUG: Invalid child process type [%d]\n", svc->type);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Free the old service (which will also remove it
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * from the child list)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void mt_svc_exit_handler(int pid, int wait_status, void *pvt)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher struct mt_svc *svc = talloc_get_type(pvt, struct mt_svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "SIGCHLD handler of service %s called\n", svc->name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Check the number of restart tries and relaunch the service */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void monitor_restart_service(struct mt_svc *svc)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Handle the actual checks for how many times to restart this
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * service before giving up.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if ((now - svc->last_restart) > MONITOR_RESTART_CNT_INTERVAL_RESET) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Restart the service */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (svc->restarts > MONITOR_MAX_SVC_RESTARTS) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Process [%s], definitely stopped!\n", svc->name);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Exiting the SSSD. Could not restart critical service [%s].",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* exit the SSSD with an error, shutting down all
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * services and domains.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * We do this because if one of the responders is down
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * and can't come back up, this is the only way to
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * guarantee admin intervention.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* restarts are schedule after 0, 2, 4 seconds */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (restart_delay > MONITOR_MAX_RESTART_DELAY) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher restart_delay = MONITOR_MAX_RESTART_DELAY;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher tv = tevent_timeval_current_ofs(restart_delay, 0);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher te = tevent_add_timer(svc->mt_ctx->ev, svc, tv, mt_svc_restart, svc);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Nothing much we can do */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Failed to allocate timed event: mt_svc_restart.\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher {"daemon", 'D', POPT_ARG_NONE, &opt_daemon, 0, \
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher {"interactive", 'i', POPT_ARG_NONE, &opt_interactive, 0, \
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher _("Run interactive (not a daemon)"), NULL}, \
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher {"disable-netlink", '\0', POPT_ARG_NONE | POPT_ARGFLAG_DOC_HIDDEN,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher {"config", 'c', POPT_ARG_STRING, &opt_config_file, 0, \
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher _("Specify a non-default config file"), NULL}, \
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher {"genconf", 'g', POPT_ARG_NONE, &opt_genconf, 0, \
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher _("Refresh the configuration database, then exit"), \
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher {"version", '\0', POPT_ARG_NONE, &opt_version, 0, \
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher _("Print version number and exit"), NULL }, \
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Set debug level to invalid value so we can deside if -d 0 was used. */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher pc = poptGetContext(argv[0], argc, argv, long_options, 0);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher fprintf(stderr, "\nInvalid option %s: %s\n\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* If the level or timestamps was passed at the command-line, we want
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * to save it and pass it to the children later.
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher cmdline_debug_timestamps = debug_timestamps;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher cmdline_debug_microseconds = debug_microseconds;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher fprintf(stderr, "Option -i|--interactive is not allowed together with -D|--daemon\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (opt_genconf && (opt_daemon || opt_interactive)) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher fprintf(stderr, "Option -g is incompatible with -D or -i\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (!opt_daemon && !opt_interactive && !opt_genconf) {
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Running under %"SPRIuid", must be root\n", uid);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sss_log(SSS_LOG_ALERT, "sssd must be run as root");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher config_file = talloc_strdup(tmp_ctx, opt_config_file);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher config_file = talloc_strdup(tmp_ctx, SSSD_CONFIG_FILE);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Option --disable-netlink has been removed and "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "replaced as a monitor option in sssd.conf\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "--disable-netlink has been deprecated, tunable option "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "disable_netlink available as replacement(man sssd.conf)");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* we want a pid file check */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Open before server_setup() does to have logging
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * during configuration checking */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Do this before all the forks, it sets the session key ring so all
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * keys are private to the daemon and cannot be read by any other process
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* make a new session */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Could not create private keyring session. "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "If you store password there they may be easily accessible "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "to the root user. (%d, %s)", errno, strerror(errno));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = keyctl_setperm(KEY_SPEC_SESSION_KEYRING, KEY_POS_ALL);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Could not set permissions on private keyring. "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "If you store password there they may be easily accessible "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "to the root user. (%d, %s)", errno, strerror(errno));
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Warn if nscd seems to be running */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = sss_nscd_parse_conf(NSCD_CONF_PATH);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "NSCD socket was detected. NSCD caching capabilities "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "may conflict with SSSD for users and groups. It is "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "recommended not to run NSCD in parallel with SSSD, "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "unless NSCD is configured not to cache the passwd, "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "group, netgroup and services nsswitch maps.");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "NSCD socket was detected and seems to be configured "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "to cache some of the databases controlled by "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "SSSD [passwd,group,netgroup,services]. It is "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "recommended not to run NSCD in parallel with SSSD, "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "unless NSCD is configured not to cache these.");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher DEBUG(SSSDBG_TRACE_FUNC, "NSCD socket was detected and it "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "seems to be configured not to interfere with "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "SSSD's caching capabilities\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* Parse config file, fail if cannot be done */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = load_configuration(tmp_ctx, config_file, CONFDB_DEFAULT_CONFIG_DIR,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Configuration file: %s does not exist.\n", config_file);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "Configuration file: %s does not exist.\n", config_file);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher sss_log(SSS_LOG_ALERT, CONF_FILE_PERM_ERROR_MSG, config_file);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "SSSD couldn't load the configuration database.\n");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "SSSD couldn't load the configuration database [%d]: %s.\n",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* at this point we are done generating the config file, we may exit
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher * if that's all we were asked to do */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* set up things like debug , signals, daemonization, etc... */
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher monitor->conf_path = CONFDB_MONITOR_CONF_ENTRY;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = server_setup(MONITOR_NAME, flags, 0, 0,
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher monitor->parent_pid = main_ctx->parent_pid;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher ret = monitor_process_init(monitor, config_file);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* loop on main */