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
master_wakeup_timer_event(int unused_event,void * context)85 static 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
master_wakeup_init(MASTER_SERV * serv)167 void 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
master_wakeup_cleanup(MASTER_SERV * serv)181 void 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