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