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