1/*++ 2/* NAME 3/* master_wakeup 3 4/* SUMMARY 5/* Postfix master - start/stop service wakeup timers 6/* SYNOPSIS 7/* #include "master.h" 8/* 9/* void master_wakeup_init(serv) 10/* MASTER_SERV *serv; 11/* 12/* void master_wakeup_cleanup(serv) 13/* MASTER_SERV *serv; 14/* DESCRIPTION 15/* This module implements automatic service wakeup. In order to 16/* wakeup a service, a wakeup trigger is sent to the corresponding 17/* service port or FIFO, and a timer is started to repeat this sequence 18/* after a configurable amount of time. 19/* 20/* master_wakeup_init() wakes up the named service. No wakeup 21/* is done or scheduled when a zero wakeup time is given, or when 22/* the service has been throttled in the mean time. 23/* It is OK to call master_wakeup_init() while a timer is already 24/* running for the named service. The effect is to restart the 25/* wakeup timer. 26/* 27/* master_wakeup_cleanup() cancels the wakeup timer for the named 28/* service. It is an error to disable a service while it still has 29/* an active wakeup timer (doing so would cause a dangling reference 30/* to a non-existent service). 31/* It is OK to call master_wakeup_cleanup() even when no timer is 32/* active for the named service. 33/* DIAGNOSTICS 34/* BUGS 35/* SEE ALSO 36/* inet_trigger(3), internet-domain client 37/* unix_trigger(3), unix-domain client 38/* fifo_trigger(3), fifo client 39/* upass_trigger(3), file descriptor passing client 40/* LICENSE 41/* .ad 42/* .fi 43/* The Secure Mailer license must be distributed with this software. 44/* AUTHOR(S) 45/* Wietse Venema 46/* IBM T.J. Watson Research 47/* P.O. Box 704 48/* Yorktown Heights, NY 10598, USA 49/*--*/ 50 51/* System library. */ 52 53#include <sys_defs.h> 54#include <unistd.h> 55#include <string.h> 56 57/* Utility library. */ 58 59#include <msg.h> 60#include <trigger.h> 61#include <events.h> 62#include <set_eugid.h> 63#include <set_ugid.h> 64 65/* Global library. */ 66 67#include <mail_proto.h> /* triggers */ 68#include <mail_params.h> 69 70/* Application-specific. */ 71 72#include "mail_server.h" 73#include "master.h" 74 75/* master_wakeup_timer_event - wakeup event handler */ 76 77static void master_wakeup_timer_event(int unused_event, char *context) 78{ 79 const char *myname = "master_wakeup_timer_event"; 80 MASTER_SERV *serv = (MASTER_SERV *) context; 81 int status; 82 static char wakeup = TRIGGER_REQ_WAKEUP; 83 84 /* 85 * Don't wakeup services whose automatic wakeup feature was turned off in 86 * the mean time. 87 */ 88 if (serv->wakeup_time == 0) 89 return; 90 91 /* 92 * Don't wake up services that are throttled. Find out what transport to 93 * use. We can't block here so we choose a short timeout. 94 */ 95#define BRIEFLY 1 96 97 if (MASTER_THROTTLED(serv) == 0) { 98 if (msg_verbose) 99 msg_info("%s: service %s", myname, serv->name); 100 101 switch (serv->type) { 102 case MASTER_SERV_TYPE_INET: 103 status = inet_trigger(serv->name, &wakeup, sizeof(wakeup), BRIEFLY); 104 break; 105 case MASTER_SERV_TYPE_UNIX: 106 status = LOCAL_TRIGGER(serv->name, &wakeup, sizeof(wakeup), BRIEFLY); 107 break; 108#ifdef MASTER_SERV_TYPE_PASS 109 case MASTER_SERV_TYPE_PASS: 110 status = pass_trigger(serv->name, &wakeup, sizeof(wakeup), BRIEFLY); 111 break; 112#endif 113 114 /* 115 * If someone compromises the postfix account then this must not 116 * overwrite files outside the chroot jail. Countermeasures: 117 * 118 * - Limit the damage by accessing the FIFO as postfix not root. 119 * 120 * - Have fifo_trigger() call safe_open() so we won't follow 121 * arbitrary hard/symlinks to files in/outside the chroot jail. 122 * 123 * - All non-chroot postfix-related files must be root owned (or 124 * postfix check complains). 125 * 126 * - The postfix user and group ID must not be shared with other 127 * applications (says the INSTALL documentation). 128 * 129 * Result of a discussion with Michael Tokarev, who received his 130 * insights from Solar Designer, who tested Postfix with a kernel 131 * module that is paranoid about open() calls. 132 */ 133 case MASTER_SERV_TYPE_FIFO: 134 set_eugid(var_owner_uid, var_owner_gid); 135 status = fifo_trigger(serv->name, &wakeup, sizeof(wakeup), BRIEFLY); 136 set_ugid(getuid(), getgid()); 137 break; 138 default: 139 msg_panic("%s: unknown service type: %d", myname, serv->type); 140 } 141 if (status < 0) 142 msg_warn("%s: service %s(%s): %m", 143 myname, serv->ext_name, serv->name); 144 } 145 146 /* 147 * Schedule another wakeup event. 148 */ 149 event_request_timer(master_wakeup_timer_event, (char *) serv, 150 serv->wakeup_time); 151} 152 153/* master_wakeup_init - start automatic service wakeup */ 154 155void master_wakeup_init(MASTER_SERV *serv) 156{ 157 const char *myname = "master_wakeup_init"; 158 159 if (serv->wakeup_time == 0 || (serv->flags & MASTER_FLAG_CONDWAKE)) 160 return; 161 if (msg_verbose) 162 msg_info("%s: service %s time %d", 163 myname, serv->name, serv->wakeup_time); 164 master_wakeup_timer_event(0, (char *) serv); 165} 166 167/* master_wakeup_cleanup - cancel wakeup timer */ 168 169void master_wakeup_cleanup(MASTER_SERV *serv) 170{ 171 const char *myname = "master_wakeup_cleanup"; 172 173 /* 174 * Cleanup, even when the wakeup feature has been turned off. There might 175 * still be a pending timer. Don't depend on the code that reloads the 176 * config file to reset the wakeup timer when things change. 177 */ 178 if (msg_verbose) 179 msg_info("%s: service %s", myname, serv->name); 180 181 event_cancel_timer(master_wakeup_timer_event, (char *) serv); 182} 183