diff options
Diffstat (limited to 'src/master/master_wakeup.c')
-rw-r--r-- | src/master/master_wakeup.c | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/src/master/master_wakeup.c b/src/master/master_wakeup.c new file mode 100644 index 0000000..cc50924 --- /dev/null +++ b/src/master/master_wakeup.c @@ -0,0 +1,192 @@ +/*++ +/* NAME +/* master_wakeup 3 +/* SUMMARY +/* Postfix master - start/stop service wakeup timers +/* SYNOPSIS +/* #include "master.h" +/* +/* void master_wakeup_init(serv) +/* MASTER_SERV *serv; +/* +/* void master_wakeup_cleanup(serv) +/* MASTER_SERV *serv; +/* DESCRIPTION +/* This module implements automatic service wakeup. In order to +/* wakeup a service, a wakeup trigger is sent to the corresponding +/* service port or FIFO, and a timer is started to repeat this sequence +/* after a configurable amount of time. +/* +/* master_wakeup_init() wakes up the named service. No wakeup +/* is done or scheduled when a zero wakeup time is given, or when +/* the service has been throttled in the mean time. +/* It is OK to call master_wakeup_init() while a timer is already +/* running for the named service. The effect is to restart the +/* wakeup timer. +/* +/* master_wakeup_cleanup() cancels the wakeup timer for the named +/* service. It is an error to disable a service while it still has +/* an active wakeup timer (doing so would cause a dangling reference +/* to a non-existent service). +/* It is OK to call master_wakeup_cleanup() even when no timer is +/* active for the named service. +/* DIAGNOSTICS +/* BUGS +/* SEE ALSO +/* inet_trigger(3), internet-domain client +/* unix_trigger(3), unix-domain client +/* fifo_trigger(3), fifo client +/* upass_trigger(3), file descriptor passing client +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/*--*/ + +/* System library. */ + +#include <sys_defs.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> + +/* Utility library. */ + +#include <msg.h> +#include <trigger.h> +#include <events.h> +#include <set_eugid.h> +#include <set_ugid.h> + +/* Global library. */ + +#include <mail_proto.h> /* triggers */ +#include <mail_params.h> + +/* Application-specific. */ + +#include "mail_server.h" +#include "master.h" + +/* master_wakeup_timer_event - wakeup event handler */ + +static void master_wakeup_timer_event(int unused_event, void *context) +{ + const char *myname = "master_wakeup_timer_event"; + MASTER_SERV *serv = (MASTER_SERV *) context; + int status; + static char wakeup = TRIGGER_REQ_WAKEUP; + + /* + * Don't wakeup services whose automatic wakeup feature was turned off in + * the mean time. + */ + if (serv->wakeup_time == 0) + return; + + /* + * Don't wake up services that are throttled. Find out what transport to + * use. We can't block here so we choose a short timeout. + */ +#define BRIEFLY 1 + + if (MASTER_THROTTLED(serv) == 0) { + if (msg_verbose) + msg_info("%s: service %s", myname, serv->name); + + switch (serv->type) { + case MASTER_SERV_TYPE_INET: + status = inet_trigger(serv->name, &wakeup, sizeof(wakeup), BRIEFLY); + break; + case MASTER_SERV_TYPE_UNIX: + status = LOCAL_TRIGGER(serv->name, &wakeup, sizeof(wakeup), BRIEFLY); + break; + case MASTER_SERV_TYPE_UXDG: + status = -1; + errno = EOPNOTSUPP; + break; +#ifdef MASTER_SERV_TYPE_PASS + case MASTER_SERV_TYPE_PASS: + status = pass_trigger(serv->name, &wakeup, sizeof(wakeup), BRIEFLY); + break; +#endif + + /* + * If someone compromises the postfix account then this must not + * overwrite files outside the chroot jail. Countermeasures: + * + * - Limit the damage by accessing the FIFO as postfix not root. + * + * - Have fifo_trigger() call safe_open() so we won't follow + * arbitrary hard/symlinks to files in/outside the chroot jail. + * + * - All non-chroot postfix-related files must be root owned (or + * postfix check complains). + * + * - The postfix user and group ID must not be shared with other + * applications (says the INSTALL documentation). + * + * Result of a discussion with Michael Tokarev, who received his + * insights from Solar Designer, who tested Postfix with a kernel + * module that is paranoid about open() calls. + */ + case MASTER_SERV_TYPE_FIFO: + set_eugid(var_owner_uid, var_owner_gid); + status = fifo_trigger(serv->name, &wakeup, sizeof(wakeup), BRIEFLY); + set_ugid(getuid(), getgid()); + break; + default: + msg_panic("%s: unknown service type: %d", myname, serv->type); + } + if (status < 0) + msg_warn("%s: service %s(%s): %m", + myname, serv->ext_name, serv->name); + } + + /* + * Schedule another wakeup event. + */ + event_request_timer(master_wakeup_timer_event, (void *) serv, + serv->wakeup_time); +} + +/* master_wakeup_init - start automatic service wakeup */ + +void master_wakeup_init(MASTER_SERV *serv) +{ + const char *myname = "master_wakeup_init"; + + if (serv->wakeup_time == 0 || (serv->flags & MASTER_FLAG_CONDWAKE)) + return; + if (msg_verbose) + msg_info("%s: service %s time %d", + myname, serv->name, serv->wakeup_time); + master_wakeup_timer_event(0, (void *) serv); +} + +/* master_wakeup_cleanup - cancel wakeup timer */ + +void master_wakeup_cleanup(MASTER_SERV *serv) +{ + const char *myname = "master_wakeup_cleanup"; + + /* + * Cleanup, even when the wakeup feature has been turned off. There might + * still be a pending timer. Don't depend on the code that reloads the + * config file to reset the wakeup timer when things change. + */ + if (msg_verbose) + msg_info("%s: service %s", myname, serv->name); + + event_cancel_timer(master_wakeup_timer_event, (void *) serv); +} |