1 /* $NetBSD: postlogd.c,v 1.3 2022/10/08 16:12:47 christos Exp $ */
2
3 /*++
4 /* NAME
5 /* postlogd 8
6 /* SUMMARY
7 /* Postfix internal log server
8 /* SYNOPSIS
9 /* \fBpostlogd\fR [generic Postfix daemon options]
10 /* DESCRIPTION
11 /* This program logs events on behalf of Postfix programs
12 /* when the maillog configuration parameter specifies a non-empty
13 /* value.
14 /* BUGS
15 /* Non-daemon Postfix programs don't know that they should log
16 /* to the internal logging service before they have processed
17 /* command-line options and main.cf parameters. These programs
18 /* still log earlier events to the syslog service.
19 /*
20 /* If Postfix is down, the non-daemon programs \fBpostfix\fR(1),
21 /* \fBpostsuper\fR(1), \fBpostmulti\fR(1), and \fBpostlog\fR(1),
22 /* will log directly to \fB$maillog_file\fR. These programs
23 /* expect to run with root privileges, for example during
24 /* Postfix start-up, reload, or shutdown.
25 /*
26 /* Other non-daemon Postfix programs will never write directly to
27 /* \fB$maillog_file\fR (also, logging to stdout would interfere
28 /* with the operation of some of these programs). These programs
29 /* can log to \fBpostlogd\fR(8) if they are run by the super-user,
30 /* or if their executable file has set-gid permission. Do not
31 /* set this permission on programs other than \fBpostdrop\fR(1),
32 /* \fBpostqueue\fR(1) and (Postfix >= 3.7) \fBpostlog\fR(1).
33 /* CONFIGURATION PARAMETERS
34 /* .ad
35 /* .fi
36 /* Changes to \fBmain.cf\fR are picked up automatically, as
37 /* \fBpostlogd\fR(8) processes run for only a limited amount
38 /* of time. Use the command "\fBpostfix reload\fR" to speed
39 /* up a change.
40 /*
41 /* The text below provides only a parameter summary. See
42 /* \fBpostconf\fR(5) for more details including examples.
43 /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
44 /* The default location of the Postfix main.cf and master.cf
45 /* configuration files.
46 /* .IP "\fBmaillog_file (empty)\fR"
47 /* The name of an optional logfile that is written by the Postfix
48 /* \fBpostlogd\fR(8) service.
49 /* .IP "\fBprocess_id (read-only)\fR"
50 /* The process ID of a Postfix command or daemon process.
51 /* .IP "\fBprocess_name (read-only)\fR"
52 /* The process name of a Postfix command or daemon process.
53 /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
54 /* A prefix that is prepended to the process name in syslog
55 /* records, so that, for example, "smtpd" becomes "prefix/smtpd".
56 /* .IP "\fBservice_name (read-only)\fR"
57 /* The master.cf service name of a Postfix daemon process.
58 /* .IP "\fBpostlogd_watchdog_timeout (10s)\fR"
59 /* How much time a \fBpostlogd\fR(8) process may take to process a request
60 /* before it is terminated by a built-in watchdog timer.
61 /* SEE ALSO
62 /* postconf(5), configuration parameters
63 /* syslogd(8), system logging
64 /* README_FILES
65 /* .ad
66 /* .fi
67 /* Use "\fBpostconf readme_directory\fR" or
68 /* "\fBpostconf html_directory\fR" to locate this information.
69 /* .na
70 /* .nf
71 /* MAILLOG_README, Postfix logging to file or stdout
72 /* LICENSE
73 /* .ad
74 /* .fi
75 /* The Secure Mailer license must be distributed with this software.
76 /* HISTORY
77 /* .ad
78 /* .fi
79 /* This service was introduced with Postfix version 3.4.
80 /* AUTHOR(S)
81 /* Wietse Venema
82 /* Google, Inc.
83 /* 111 8th Avenue
84 /* New York, NY 10011, USA
85 /*--*/
86
87 /*
88 * System library.
89 */
90 #include <sys_defs.h>
91
92 /*
93 * Utility library.
94 */
95 #include <logwriter.h>
96 #include <msg.h>
97 #include <msg_logger.h>
98 #include <stringops.h>
99 #include <vstream.h>
100
101 /*
102 * Global library.
103 */
104 #include <mail_params.h>
105 #include <mail_task.h>
106 #include <mail_version.h>
107 #include <maillog_client.h>
108
109 /*
110 * Server skeleton.
111 */
112 #include <mail_server.h>
113
114 /*
115 * Tunable parameters.
116 */
117 int var_postlogd_watchdog;
118
119 /*
120 * Silly little macros.
121 */
122 #define STR(x) vstring_str(x)
123 #define LEN(x) VSTRING_LEN(x)
124
125 /*
126 * Logfile stream.
127 */
128 static VSTREAM *postlogd_stream = 0;
129
130 /* postlogd_fallback - log messages from postlogd(8) itself */
131
postlogd_fallback(const char * buf)132 static void postlogd_fallback(const char *buf)
133 {
134 (void) logwriter_write(postlogd_stream, buf, strlen(buf));
135 }
136
137 /* postlogd_service - perform service for client */
138
postlogd_service(char * buf,ssize_t len,char * unused_service,char ** unused_argv)139 static void postlogd_service(char *buf, ssize_t len, char *unused_service,
140 char **unused_argv)
141 {
142
143 if (postlogd_stream) {
144 (void) logwriter_write(postlogd_stream, buf, len);
145 }
146
147 /*
148 * After a configuration change that removes the maillog_file pathname,
149 * this service may still receive messages (after "postfix reload" or
150 * after process refresh) from programs that use the old maillog_file
151 * setting. Redirect those messages to the current logging mechanism.
152 */
153 else {
154 char *bp = buf;
155 char *progname_pid;
156
157 /*
158 * Avoid surprises: strip off the date, time, host, and program[pid]:
159 * prefix that were prepended by msg_logger(3). Then, hope that the
160 * current logging driver suppresses its own PID, when it sees that
161 * there is a PID embedded in the 'program name'.
162 */
163 (void) mystrtok(&bp, CHARS_SPACE); /* month */
164 (void) mystrtok(&bp, CHARS_SPACE); /* day */
165 (void) mystrtok(&bp, CHARS_SPACE); /* time */
166 (void) mystrtok(&bp, CHARS_SPACE); /* host */
167 progname_pid = mystrtok(&bp, ":" CHARS_SPACE); /* name[pid] sans ':' */
168 bp += strspn(bp, CHARS_SPACE);
169 if (progname_pid)
170 maillog_client_init(progname_pid, MAILLOG_CLIENT_FLAG_NONE);
171 msg_info("%.*s", (int) (len - (bp - buf)), bp);
172
173 /*
174 * Restore the program name, in case postlogd(8) needs to log
175 * something about itself. We have to call maillog_client_init() in
176 * any case, because neither msg_syslog_init() nor openlog() make a
177 * copy of the name argument. We can't leave that pointing into the
178 * middle of the above message buffer.
179 */
180 maillog_client_init(mail_task((char *) 0), MAILLOG_CLIENT_FLAG_NONE);
181 }
182 }
183
184 /* pre_jail_init - pre-jail handling */
185
pre_jail_init(char * unused_service_name,char ** argv)186 static void pre_jail_init(char *unused_service_name, char **argv)
187 {
188
189 /*
190 * During process initialization, the postlogd daemon will log events to
191 * the postlog socket, so that they can be logged to file later. Once the
192 * postlogd daemon is handling requests, it will stop logging to the
193 * postlog socket and will instead write to the logfile, to avoid
194 * infinite recursion.
195 */
196
197 /*
198 * Sanity check. This service takes no command-line arguments.
199 */
200 if (argv[0])
201 msg_fatal("unexpected command-line argument: %s", argv[0]);
202
203 /*
204 * After a configuration change that removes the maillog_file pathname,
205 * this service may still receive messages from processes that still use
206 * the old configuration. Those messages will have to be redirected to
207 * the current logging subsystem.
208 */
209 if (*var_maillog_file != 0) {
210
211 /*
212 * Instantiate the logwriter or bust.
213 */
214 postlogd_stream = logwriter_open_or_die(var_maillog_file);
215
216 /*
217 * Inform the msg_logger client to stop using the postlog socket, and
218 * to call our logwriter.
219 */
220 msg_logger_control(CA_MSG_LOGGER_CTL_FALLBACK_ONLY,
221 CA_MSG_LOGGER_CTL_FALLBACK_FN(postlogd_fallback),
222 CA_MSG_LOGGER_CTL_END);
223 }
224 }
225
226 /* post_jail_init - post-jail initialization */
227
post_jail_init(char * unused_name,char ** unused_argv)228 static void post_jail_init(char *unused_name, char **unused_argv)
229 {
230
231 /*
232 * Prevent automatic process suicide after a limited number of client
233 * requests. It is OK to terminate after a limited amount of idle time.
234 */
235 var_use_limit = 0;
236 }
237
238 MAIL_VERSION_STAMP_DECLARE;
239
240 /* main - pass control to the multi-threaded skeleton */
241
main(int argc,char ** argv)242 int main(int argc, char **argv)
243 {
244 static const CONFIG_TIME_TABLE time_table[] = {
245 VAR_POSTLOGD_WATCHDOG, DEF_POSTLOGD_WATCHDOG, &var_postlogd_watchdog, 10, 0,
246 0,
247 };
248
249 /*
250 * Fingerprint executables and core dumps.
251 */
252 MAIL_VERSION_STAMP_ALLOCATE;
253
254 /*
255 * This is a datagram service, not a stream service, so that postlogd can
256 * restart immediately after "postfix reload" without requiring clients
257 * to resend messages. Those messages remain queued in the kernel until a
258 * new postlogd process retrieves them. It would be unreasonable to
259 * require that clients retransmit logs, especially in the case of a
260 * fatal or panic error.
261 */
262 dgram_server_main(argc, argv, postlogd_service,
263 CA_MAIL_SERVER_TIME_TABLE(time_table),
264 CA_MAIL_SERVER_PRE_INIT(pre_jail_init),
265 CA_MAIL_SERVER_POST_INIT(post_jail_init),
266 CA_MAIL_SERVER_SOLITARY,
267 CA_MAIL_SERVER_WATCHDOG(&var_postlogd_watchdog),
268 0);
269 }
270