xref: /netbsd-src/external/ibm-public/postfix/dist/src/master/master_wakeup.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: master_wakeup.c,v 1.2 2017/02/14 01:16:45 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 
53 /* System library. */
54 
55 #include <sys_defs.h>
56 #include <unistd.h>
57 #include <string.h>
58 
59 /* Utility library. */
60 
61 #include <msg.h>
62 #include <trigger.h>
63 #include <events.h>
64 #include <set_eugid.h>
65 #include <set_ugid.h>
66 
67 /* Global library. */
68 
69 #include <mail_proto.h>			/* triggers */
70 #include <mail_params.h>
71 
72 /* Application-specific. */
73 
74 #include "mail_server.h"
75 #include "master.h"
76 
77 /* master_wakeup_timer_event - wakeup event handler */
78 
79 static void master_wakeup_timer_event(int unused_event, void *context)
80 {
81     const char *myname = "master_wakeup_timer_event";
82     MASTER_SERV *serv = (MASTER_SERV *) context;
83     int     status;
84     static char wakeup = TRIGGER_REQ_WAKEUP;
85 
86     /*
87      * Don't wakeup services whose automatic wakeup feature was turned off in
88      * the mean time.
89      */
90     if (serv->wakeup_time == 0)
91 	return;
92 
93     /*
94      * Don't wake up services that are throttled. Find out what transport to
95      * use. We can't block here so we choose a short timeout.
96      */
97 #define BRIEFLY	1
98 
99     if (MASTER_THROTTLED(serv) == 0) {
100 	if (msg_verbose)
101 	    msg_info("%s: service %s", myname, serv->name);
102 
103 	switch (serv->type) {
104 	case MASTER_SERV_TYPE_INET:
105 	    status = inet_trigger(serv->name, &wakeup, sizeof(wakeup), BRIEFLY);
106 	    break;
107 	case MASTER_SERV_TYPE_UNIX:
108 	    status = LOCAL_TRIGGER(serv->name, &wakeup, sizeof(wakeup), BRIEFLY);
109 	    break;
110 #ifdef MASTER_SERV_TYPE_PASS
111 	case MASTER_SERV_TYPE_PASS:
112 	    status = pass_trigger(serv->name, &wakeup, sizeof(wakeup), BRIEFLY);
113 	    break;
114 #endif
115 
116 	    /*
117 	     * If someone compromises the postfix account then this must not
118 	     * overwrite files outside the chroot jail. Countermeasures:
119 	     *
120 	     * - Limit the damage by accessing the FIFO as postfix not root.
121 	     *
122 	     * - Have fifo_trigger() call safe_open() so we won't follow
123 	     * arbitrary hard/symlinks to files in/outside the chroot jail.
124 	     *
125 	     * - All non-chroot postfix-related files must be root owned (or
126 	     * postfix check complains).
127 	     *
128 	     * - The postfix user and group ID must not be shared with other
129 	     * applications (says the INSTALL documentation).
130 	     *
131 	     * Result of a discussion with Michael Tokarev, who received his
132 	     * insights from Solar Designer, who tested Postfix with a kernel
133 	     * module that is paranoid about open() calls.
134 	     */
135 	case MASTER_SERV_TYPE_FIFO:
136 	    set_eugid(var_owner_uid, var_owner_gid);
137 	    status = fifo_trigger(serv->name, &wakeup, sizeof(wakeup), BRIEFLY);
138 	    set_ugid(getuid(), getgid());
139 	    break;
140 	default:
141 	    msg_panic("%s: unknown service type: %d", myname, serv->type);
142 	}
143 	if (status < 0)
144 	    msg_warn("%s: service %s(%s): %m",
145 		     myname, serv->ext_name, serv->name);
146     }
147 
148     /*
149      * Schedule another wakeup event.
150      */
151     event_request_timer(master_wakeup_timer_event, (void *) serv,
152 			serv->wakeup_time);
153 }
154 
155 /* master_wakeup_init - start automatic service wakeup */
156 
157 void    master_wakeup_init(MASTER_SERV *serv)
158 {
159     const char *myname = "master_wakeup_init";
160 
161     if (serv->wakeup_time == 0 || (serv->flags & MASTER_FLAG_CONDWAKE))
162 	return;
163     if (msg_verbose)
164 	msg_info("%s: service %s time %d",
165 		 myname, serv->name, serv->wakeup_time);
166     master_wakeup_timer_event(0, (void *) serv);
167 }
168 
169 /* master_wakeup_cleanup - cancel wakeup timer */
170 
171 void    master_wakeup_cleanup(MASTER_SERV *serv)
172 {
173     const char *myname = "master_wakeup_cleanup";
174 
175     /*
176      * Cleanup, even when the wakeup feature has been turned off. There might
177      * still be a pending timer. Don't depend on the code that reloads the
178      * config file to reset the wakeup timer when things change.
179      */
180     if (msg_verbose)
181 	msg_info("%s: service %s", myname, serv->name);
182 
183     event_cancel_timer(master_wakeup_timer_event, (void *) serv);
184 }
185