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