diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:18:56 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:18:56 +0000 |
commit | b7c15c31519dc44c1f691e0466badd556ffe9423 (patch) | |
tree | f944572f288bab482a615e09af627d9a2b6727d8 /src/postlog | |
parent | Initial commit. (diff) | |
download | postfix-upstream.tar.xz postfix-upstream.zip |
Adding upstream version 3.7.10.upstream/3.7.10upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
l--------- | src/postlog/.indent.pro | 1 | ||||
-rw-r--r-- | src/postlog/.printfck | 25 | ||||
-rw-r--r-- | src/postlog/Makefile.in | 84 | ||||
-rw-r--r-- | src/postlog/postlog.c | 372 | ||||
-rw-r--r-- | src/postlogd/Makefile.in | 79 | ||||
-rw-r--r-- | src/postlogd/postlogd.c | 267 |
6 files changed, 828 insertions, 0 deletions
diff --git a/src/postlog/.indent.pro b/src/postlog/.indent.pro new file mode 120000 index 0000000..5c837ec --- /dev/null +++ b/src/postlog/.indent.pro @@ -0,0 +1 @@ +../../.indent.pro
\ No newline at end of file diff --git a/src/postlog/.printfck b/src/postlog/.printfck new file mode 100644 index 0000000..66016ed --- /dev/null +++ b/src/postlog/.printfck @@ -0,0 +1,25 @@ +been_here_xt 2 0 +bounce_append 5 0 +cleanup_out_format 1 0 +defer_append 5 0 +mail_command 1 0 +mail_print 1 0 +msg_error 0 0 +msg_fatal 0 0 +msg_info 0 0 +msg_panic 0 0 +msg_warn 0 0 +opened 4 0 +post_mail_fprintf 1 0 +qmgr_message_bounce 2 0 +rec_fprintf 2 0 +sent 4 0 +smtp_cmd 1 0 +smtp_mesg_fail 2 0 +smtp_printf 1 0 +smtp_rcpt_fail 3 0 +smtp_site_fail 2 0 +udp_syslog 1 0 +vstream_fprintf 1 0 +vstream_printf 0 0 +vstring_sprintf 1 0 diff --git a/src/postlog/Makefile.in b/src/postlog/Makefile.in new file mode 100644 index 0000000..297eae2 --- /dev/null +++ b/src/postlog/Makefile.in @@ -0,0 +1,84 @@ +SHELL = /bin/sh +SRCS = postlog.c +OBJS = postlog.o +HDRS = +TESTSRC = +DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE) +CFLAGS = $(DEBUG) $(OPT) $(DEFS) +FILES = Makefile $(SRCS) $(HDRS) +INC_DIR = ../../include +TESTPROG= +PROG = postlog +LIBS = ../../lib/lib$(LIB_PREFIX)global$(LIB_SUFFIX) \ + ../../lib/lib$(LIB_PREFIX)util$(LIB_SUFFIX) + +.c.o:; $(CC) $(CFLAGS) -c $*.c + +$(PROG): $(OBJS) $(LIBS) + $(CC) $(CFLAGS) $(SHLIB_RPATH) -o $@ $(OBJS) $(LIBS) $(SYSLIBS) + +$(OBJS): ../../conf/makedefs.out + +Makefile: Makefile.in + cat ../../conf/makedefs.out $? >$@ + +test: $(TESTPROG) + +tests: + +root_tests: + +update: ../../bin/$(PROG) + +../../bin/$(PROG): $(PROG) + cp $(PROG) ../../bin + +printfck: $(OBJS) $(PROG) + rm -rf printfck + mkdir printfck + sed '1,/^# do not edit/!d' Makefile >printfck/Makefile + set -e; for i in *.c; do printfck -f .printfck $$i >printfck/$$i; done + cd printfck; make "INC_DIR=../../../include" `cd ..; ls *.o` + +shar: + @shar $(FILES) + +lint: + lint $(SRCS) + +clean: + rm -f *.o *core $(PROG) $(TESTPROG) junk + rm -rf printfck + +tidy: clean + +depend: $(MAKES) + (sed '1,/^# do not edit/!d' Makefile.in; \ + set -e; for i in [a-z][a-z0-9]*.c; do \ + $(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \ + -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' \ + -e 's/o: \.\//o: /' -e p -e '}' ; \ + done | LANG=C sort -u) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in + @$(EXPORT) make -f Makefile.in Makefile 1>&2 + +# do not edit below this line - it is generated by 'make depend' +postlog.o: ../../include/argv.h +postlog.o: ../../include/check_arg.h +postlog.o: ../../include/clean_env.h +postlog.o: ../../include/mail_conf.h +postlog.o: ../../include/mail_params.h +postlog.o: ../../include/mail_parm_split.h +postlog.o: ../../include/mail_task.h +postlog.o: ../../include/mail_version.h +postlog.o: ../../include/maillog_client.h +postlog.o: ../../include/msg.h +postlog.o: ../../include/msg_output.h +postlog.o: ../../include/msg_vstream.h +postlog.o: ../../include/stringops.h +postlog.o: ../../include/sys_defs.h +postlog.o: ../../include/vbuf.h +postlog.o: ../../include/vstream.h +postlog.o: ../../include/vstring.h +postlog.o: ../../include/vstring_vstream.h +postlog.o: ../../include/warn_stat.h +postlog.o: postlog.c diff --git a/src/postlog/postlog.c b/src/postlog/postlog.c new file mode 100644 index 0000000..eddc432 --- /dev/null +++ b/src/postlog/postlog.c @@ -0,0 +1,372 @@ +/*++ +/* NAME +/* postlog 1 +/* SUMMARY +/* Postfix-compatible logging utility +/* SYNOPSIS +/* .fi +/* .ad +/* \fBpostlog\fR [\fB-iv\fR] [\fB-c \fIconfig_dir\fR] +/* [\fB-p \fIpriority\fR] [\fB-t \fItag\fR] [\fItext...\fR] +/* DESCRIPTION +/* The \fBpostlog\fR(1) command implements a Postfix-compatible logging +/* interface for use in, for example, shell scripts. +/* +/* By default, \fBpostlog\fR(1) logs the \fItext\fR given on the command +/* line as one record. If no \fItext\fR is specified on the command +/* line, \fBpostlog\fR(1) reads from standard input and logs each input +/* line as one record. +/* +/* By default, logging is sent to \fBsyslogd\fR(8) or +/* \fBpostlogd\fR(8); when the +/* standard error stream is connected to a terminal, logging +/* is sent there as well. +/* +/* The following options are implemented: +/* .IP "\fB-c \fIconfig_dir\fR" +/* Read the \fBmain.cf\fR configuration file in the named directory +/* instead of the default configuration directory. +/* .IP "\fB-i\fR (obsolete)" +/* Include the process ID in the logging tag. This flag is ignored as +/* of Postfix 3.4, where the PID is always included. +/* .IP "\fB-p \fIpriority\fR (default: \fBinfo\fR)" +/* Specifies the logging severity: \fBinfo\fR, \fBwarn\fR, +/* \fBerror\fR, \fBfatal\fR, or \fBpanic\fR. With Postfix 3.1 +/* and later, the program will pause for 1 second after reporting +/* a \fBfatal\fR or \fBpanic\fR condition, just like other +/* Postfix programs. +/* .IP "\fB-t \fItag\fR" +/* Specifies the logging tag, that is, the identifying name that +/* appears at the beginning of each logging record. A default tag +/* is used when none is specified. +/* .IP \fB-v\fR +/* Enable verbose logging for debugging purposes. Multiple \fB-v\fR +/* options make the software increasingly verbose. +/* SECURITY +/* .ad +/* .fi +/* The \fBpostlog\fR(1) command is designed to run with +/* set-groupid privileges, so that it can connect to the +/* \fBpostlogd\fR(8) daemon process (Postfix 3.7 and later; +/* earlier implementations of this command must not have +/* set-groupid or set-userid permissions). +/* ENVIRONMENT +/* .ad +/* .fi +/* .IP MAIL_CONFIG +/* Directory with the \fBmain.cf\fR file. +/* CONFIGURATION PARAMETERS +/* .ad +/* .fi +/* The following \fBmain.cf\fR parameters are especially relevant to +/* this program. +/* +/* The text below provides only a parameter summary. See +/* \fBpostconf\fR(5) for more details including examples. +/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR" +/* The default location of the Postfix main.cf and master.cf +/* configuration files. +/* .IP "\fBimport_environment (see 'postconf -d' output)\fR" +/* The list of environment parameters that a privileged Postfix +/* process will import from a non-Postfix parent process, or name=value +/* environment overrides. +/* .IP "\fBsyslog_facility (mail)\fR" +/* The syslog facility of Postfix logging. +/* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". +/* .PP +/* Available in Postfix 3.4 and later: +/* .IP "\fBmaillog_file (empty)\fR" +/* The name of an optional logfile that is written by the Postfix +/* \fBpostlogd\fR(8) service. +/* .IP "\fBpostlog_service_name (postlog)\fR" +/* The name of the \fBpostlogd\fR(8) service entry in master.cf. +/* SEE ALSO +/* postconf(5), configuration parameters +/* postlogd(8), Postfix logging +/* syslogd(8), system logging +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* HISTORY +/* The \fBpostlog\fR(1) command was introduced with Postfix +/* version 3.4. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/*--*/ + +/* System library. */ + +#include <sys_defs.h> +#include <sys/stat.h> +#include <string.h> +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> + +#ifdef STRCASECMP_IN_STRINGS_H +#include <strings.h> +#endif + +/* Utility library. */ + +#include <msg.h> +#include <vstring.h> +#include <vstream.h> +#include <vstring_vstream.h> +#include <msg_output.h> +#include <msg_vstream.h> +#include <warn_stat.h> +#include <clean_env.h> +#include <stringops.h> + +/* Global library. */ + +#include <mail_params.h> /* XXX right place for LOG_FACILITY? */ +#include <mail_version.h> +#include <mail_conf.h> +#include <mail_task.h> +#include <mail_parm_split.h> +#include <maillog_client.h> + +/* Application-specific. */ + + /* + * WARNING WARNING WARNING + * + * This software is designed to run set-gid. In order to avoid exploitation of + * privilege, this software should not run any external commands, nor should + * it take any information from the user, unless that information can be + * properly sanitized. To get an idea of how much information a process can + * inherit from a potentially hostile user, examine all the members of the + * process structure (typically, in /usr/include/sys/proc.h): the current + * directory, open files, timers, signals, environment, command line, umask, + * and so on. + */ + + /* + * Access lists. + */ +#if 0 +char *var_postlog_acl; + +X static const CONFIG_STR_TABLE str_table[] = { + X VAR_POSTLOG_ACL, DEF_POSTLOG_ACL, &var_postlog_acl, 0, 0, + X 0, +X}; + +#endif + + /* + * Support for the severity level mapping. + */ +struct level_table { + char *name; + int level; +}; + +static struct level_table level_table[] = { + "info", MSG_INFO, + "warn", MSG_WARN, + "warning", MSG_WARN, + "error", MSG_ERROR, + "err", MSG_ERROR, + "fatal", MSG_FATAL, + "crit", MSG_FATAL, + "panic", MSG_PANIC, + 0, +}; + +#define POSTLOG_CMD "postlog" + +/* level_map - lookup facility or severity value */ + +static int level_map(char *name) +{ + struct level_table *t; + + for (t = level_table; t->name; t++) + if (strcasecmp(t->name, name) == 0) + return (t->level); + msg_fatal("bad severity: \"%s\"", name); +} + +/* log_argv - log the command line */ + +static void log_argv(int level, char **argv) +{ + VSTRING *buf = vstring_alloc(100); + + while (*argv) { + vstring_strcat(buf, *argv++); + if (*argv) + vstring_strcat(buf, " "); + } + msg_printf(level, "%s", vstring_str(buf)); + vstring_free(buf); +} + +/* log_stream - log lines from a stream */ + +static void log_stream(int level, VSTREAM *fp) +{ + VSTRING *buf = vstring_alloc(100); + + while (vstring_get_nonl(buf, fp) != VSTREAM_EOF) + msg_printf(level, "%s", vstring_str(buf)); + vstring_free(buf); +} + +MAIL_VERSION_STAMP_DECLARE; + +/* main - logger */ + +int main(int argc, char **argv) +{ + struct stat st; + int fd; + int ch; + const char *tag; + char *unsanitized_tag; + int level = MSG_INFO; + ARGV *import_env; + + /* + * Fingerprint executables and core dumps. + */ + MAIL_VERSION_STAMP_ALLOCATE; + + /* + * Be consistent with file permissions. + */ + umask(022); + + /* + * To minimize confusion, make sure that the standard file descriptors + * are open before opening anything else. XXX Work around for 44BSD where + * fstat can return EBADF on an open file descriptor. + */ + for (fd = 0; fd < 3; fd++) + if (fstat(fd, &st) == -1 + && (close(fd), open("/dev/null", O_RDWR, 0)) != fd) + msg_fatal("open /dev/null: %m"); + + /* + * Set up diagnostics. Censor the process name: it is provided by the + * user. + */ + argv[0] = POSTLOG_CMD; + tag = mail_task(argv[0]); + if (isatty(STDERR_FILENO)) + msg_vstream_init(tag, VSTREAM_ERR); + maillog_client_init(tag, MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); + + /* + * Check the Postfix library version as soon as we enable logging. + */ + MAIL_VERSION_CHECK; + + /* + * Parse switches. This program is set-gid and must sanitize all + * command-line parameters. The configuration directory argument is + * validated by the mail configuration read routine. Don't do complex + * things until we have completed initializations. + */ + unsanitized_tag = 0; + while ((ch = GETOPT(argc, argv, "c:ip:t:v")) > 0) { + switch (ch) { + default: + msg_fatal("usage: %s [-c config_dir] [-i] [-p priority] [-t tag] [-v] [text]", argv[0]); + break; + case 'c': + if (setenv(CONF_ENV_PATH, optarg, 1) < 0) + msg_fatal("out of memory"); + break; + case 'i': + break; + case 'p': + level = level_map(optarg); + break; + case 't': + unsanitized_tag = optarg; + break; + case 'v': + msg_verbose++; + break; + } + } + + /* + * Process the main.cf file. This may change the syslog_name setting and + * may require that mail_task() be re-evaluated. + */ + mail_conf_read(); + /* Re-evaluate mail_task() after reading main.cf. */ + maillog_client_init(mail_task(POSTLOG_CMD), MAILLOG_CLIENT_FLAG_NONE); +#if 0 + mail_dict_init(); /* proxy, sql, ldap */ + get_mail_conf_str_table(str_table); +#endif + + /* + * This program is designed to be set-gid, which makes it a potential + * target for attack. Strip and optionally override the process + * environment so that we don't have to trust the C library. + */ + import_env = mail_parm_split(VAR_IMPORT_ENVIRON, var_import_environ); + clean_env(import_env->argv); + argv_free(import_env); + + /* + * Sanitize the user-specified tag. The result depends on the value of + * var_smtputf8_enable, therefore this code is after the mail_conf_read() + * call. + */ + if (unsanitized_tag != 0) + tag = printable(unsanitized_tag, '?'); + + /* + * Re-initialize the logging, this time with the tag specified in main.cf + * or on the command line. + */ + if (isatty(STDERR_FILENO)) + msg_vstream_init(tag, VSTREAM_ERR); + maillog_client_init(tag, MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); + +#if 0 + uid_t uid = getuid(); + + if (uid != 0 && uid != var_owner_uid + && (errstr = check_user_acl_byuid(VAR_SHOWQ_ACL, var_showq_acl, + uid)) != 0) + msg_fatal_status(EX_NOPERM, + "User %s(%ld) is not allowed to invoke 'postlog'", + errstr, (long) uid); +#endif + + /* + * Log the command line or log lines from standard input. + */ + if (argc > optind) { + log_argv(level, argv + optind); + } else { + log_stream(level, VSTREAM_IN); + } + + /* + * Consistency with msg(3) functions. + */ + if (level >= MSG_FATAL) + sleep(1); + exit(0); +} diff --git a/src/postlogd/Makefile.in b/src/postlogd/Makefile.in new file mode 100644 index 0000000..21fad76 --- /dev/null +++ b/src/postlogd/Makefile.in @@ -0,0 +1,79 @@ +SHELL = /bin/sh +SRCS = postlogd.c +OBJS = postlogd.o +HDRS = +TESTSRC = +DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE) +CFLAGS = $(DEBUG) $(OPT) $(DEFS) +TESTPROG= +PROG = postlogd +INC_DIR = ../../include +LIBS = ../../lib/lib$(LIB_PREFIX)dns$(LIB_SUFFIX) \ + ../../lib/lib$(LIB_PREFIX)master$(LIB_SUFFIX) \ + ../../lib/lib$(LIB_PREFIX)global$(LIB_SUFFIX) \ + ../../lib/lib$(LIB_PREFIX)util$(LIB_SUFFIX) + +.c.o:; $(CC) $(CFLAGS) -c $*.c + +$(PROG): $(OBJS) $(LIBS) + $(CC) $(CFLAGS) $(SHLIB_RPATH) -o $@ $(OBJS) $(LIBS) $(SYSLIBS) + +$(OBJS): ../../conf/makedefs.out + +Makefile: Makefile.in + cat ../../conf/makedefs.out $? >$@ + +test: $(TESTPROG) + +tests: test + +root_tests: + +update: ../../libexec/$(PROG) + +../../libexec/$(PROG): $(PROG) + cp $(PROG) ../../libexec + +printfck: $(OBJS) $(PROG) + rm -rf printfck + mkdir printfck + sed '1,/^# do not edit/!d' Makefile >printfck/Makefile + set -e; for i in *.c; do printfck -f .printfck $$i >printfck/$$i; done + cd printfck; make "INC_DIR=../../../include" `cd ..; ls *.o` + +lint: + lint $(DEFS) $(SRCS) $(LINTFIX) + +clean: + rm -f *.o *core $(PROG) $(TESTPROG) junk + rm -rf printfck + +tidy: clean + +depend: $(MAKES) + (sed '1,/^# do not edit/!d' Makefile.in; \ + set -e; for i in [a-z][a-z0-9]*.c; do \ + $(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \ + -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' \ + -e 's/o: \.\//o: /' -e p -e '}' ; \ + done | LANG=C sort -u) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in + @$(EXPORT) make -f Makefile.in Makefile 1>&2 + +# do not edit below this line - it is generated by 'make depend' +postlogd.o: ../../include/check_arg.h +postlogd.o: ../../include/htable.h +postlogd.o: ../../include/logwriter.h +postlogd.o: ../../include/mail_conf.h +postlogd.o: ../../include/mail_params.h +postlogd.o: ../../include/mail_server.h +postlogd.o: ../../include/mail_task.h +postlogd.o: ../../include/mail_version.h +postlogd.o: ../../include/maillog_client.h +postlogd.o: ../../include/msg.h +postlogd.o: ../../include/msg_logger.h +postlogd.o: ../../include/stringops.h +postlogd.o: ../../include/sys_defs.h +postlogd.o: ../../include/vbuf.h +postlogd.o: ../../include/vstream.h +postlogd.o: ../../include/vstring.h +postlogd.o: postlogd.c diff --git a/src/postlogd/postlogd.c b/src/postlogd/postlogd.c new file mode 100644 index 0000000..902cbe5 --- /dev/null +++ b/src/postlogd/postlogd.c @@ -0,0 +1,267 @@ +/*++ +/* NAME +/* postlogd 8 +/* SUMMARY +/* Postfix internal log server +/* SYNOPSIS +/* \fBpostlogd\fR [generic Postfix daemon options] +/* DESCRIPTION +/* This program logs events on behalf of Postfix programs +/* when the maillog configuration parameter specifies a non-empty +/* value. +/* BUGS +/* Non-daemon Postfix programs don't know that they should log +/* to the internal logging service before they have processed +/* command-line options and main.cf parameters. These programs +/* still log earlier events to the syslog service. +/* +/* If Postfix is down, the non-daemon programs \fBpostfix\fR(1), +/* \fBpostsuper\fR(1), \fBpostmulti\fR(1), and \fBpostlog\fR(1), +/* will log directly to \fB$maillog_file\fR. These programs +/* expect to run with root privileges, for example during +/* Postfix start-up, reload, or shutdown. +/* +/* Other non-daemon Postfix programs will never write directly to +/* \fB$maillog_file\fR (also, logging to stdout would interfere +/* with the operation of some of these programs). These programs +/* can log to \fBpostlogd\fR(8) if they are run by the super-user, +/* or if their executable file has set-gid permission. Do not +/* set this permission on programs other than \fBpostdrop\fR(1), +/* \fBpostqueue\fR(1) and (Postfix >= 3.7) \fBpostlog\fR(1). +/* CONFIGURATION PARAMETERS +/* .ad +/* .fi +/* Changes to \fBmain.cf\fR are picked up automatically, as +/* \fBpostlogd\fR(8) processes run for only a limited amount +/* of time. Use the command "\fBpostfix reload\fR" to speed +/* up a change. +/* +/* The text below provides only a parameter summary. See +/* \fBpostconf\fR(5) for more details including examples. +/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR" +/* The default location of the Postfix main.cf and master.cf +/* configuration files. +/* .IP "\fBmaillog_file (empty)\fR" +/* The name of an optional logfile that is written by the Postfix +/* \fBpostlogd\fR(8) service. +/* .IP "\fBprocess_id (read-only)\fR" +/* The process ID of a Postfix command or daemon process. +/* .IP "\fBprocess_name (read-only)\fR" +/* The process name of a Postfix command or daemon process. +/* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" +/* A prefix that is prepended to the process name in syslog +/* records, so that, for example, "smtpd" becomes "prefix/smtpd". +/* .IP "\fBservice_name (read-only)\fR" +/* The master.cf service name of a Postfix daemon process. +/* .IP "\fBpostlogd_watchdog_timeout (10s)\fR" +/* How much time a \fBpostlogd\fR(8) process may take to process a request +/* before it is terminated by a built-in watchdog timer. +/* SEE ALSO +/* postconf(5), configuration parameters +/* syslogd(8), system logging +/* README_FILES +/* .ad +/* .fi +/* Use "\fBpostconf readme_directory\fR" or +/* "\fBpostconf html_directory\fR" to locate this information. +/* .na +/* .nf +/* MAILLOG_README, Postfix logging to file or stdout +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* HISTORY +/* .ad +/* .fi +/* This service was introduced with Postfix version 3.4. +/* AUTHOR(S) +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/*--*/ + + /* + * System library. + */ +#include <sys_defs.h> + + /* + * Utility library. + */ +#include <logwriter.h> +#include <msg.h> +#include <msg_logger.h> +#include <stringops.h> +#include <vstream.h> + + /* + * Global library. + */ +#include <mail_params.h> +#include <mail_task.h> +#include <mail_version.h> +#include <maillog_client.h> + + /* + * Server skeleton. + */ +#include <mail_server.h> + + /* + * Tunable parameters. + */ +int var_postlogd_watchdog; + + /* + * Silly little macros. + */ +#define STR(x) vstring_str(x) +#define LEN(x) VSTRING_LEN(x) + + /* + * Logfile stream. + */ +static VSTREAM *postlogd_stream = 0; + +/* postlogd_fallback - log messages from postlogd(8) itself */ + +static void postlogd_fallback(const char *buf) +{ + (void) logwriter_write(postlogd_stream, buf, strlen(buf)); +} + +/* postlogd_service - perform service for client */ + +static void postlogd_service(char *buf, ssize_t len, char *unused_service, + char **unused_argv) +{ + + if (postlogd_stream) { + (void) logwriter_write(postlogd_stream, buf, len); + } + + /* + * After a configuration change that removes the maillog_file pathname, + * this service may still receive messages (after "postfix reload" or + * after process refresh) from programs that use the old maillog_file + * setting. Redirect those messages to the current logging mechanism. + */ + else { + char *bp = buf; + char *progname_pid; + + /* + * Avoid surprises: strip off the date, time, host, and program[pid]: + * prefix that were prepended by msg_logger(3). Then, hope that the + * current logging driver suppresses its own PID, when it sees that + * there is a PID embedded in the 'program name'. + */ + (void) mystrtok(&bp, CHARS_SPACE); /* month */ + (void) mystrtok(&bp, CHARS_SPACE); /* day */ + (void) mystrtok(&bp, CHARS_SPACE); /* time */ + (void) mystrtok(&bp, CHARS_SPACE); /* host */ + progname_pid = mystrtok(&bp, ":" CHARS_SPACE); /* name[pid] sans ':' */ + bp += strspn(bp, CHARS_SPACE); + if (progname_pid) + maillog_client_init(progname_pid, MAILLOG_CLIENT_FLAG_NONE); + msg_info("%.*s", (int) (len - (bp - buf)), bp); + + /* + * Restore the program name, in case postlogd(8) needs to log + * something about itself. We have to call maillog_client_init() in + * any case, because neither msg_syslog_init() nor openlog() make a + * copy of the name argument. We can't leave that pointing into the + * middle of the above message buffer. + */ + maillog_client_init(mail_task((char *) 0), MAILLOG_CLIENT_FLAG_NONE); + } +} + +/* pre_jail_init - pre-jail handling */ + +static void pre_jail_init(char *unused_service_name, char **argv) +{ + + /* + * During process initialization, the postlogd daemon will log events to + * the postlog socket, so that they can be logged to file later. Once the + * postlogd daemon is handling requests, it will stop logging to the + * postlog socket and will instead write to the logfile, to avoid + * infinite recursion. + */ + + /* + * Sanity check. This service takes no command-line arguments. + */ + if (argv[0]) + msg_fatal("unexpected command-line argument: %s", argv[0]); + + /* + * After a configuration change that removes the maillog_file pathname, + * this service may still receive messages from processes that still use + * the old configuration. Those messages will have to be redirected to + * the current logging subsystem. + */ + if (*var_maillog_file != 0) { + + /* + * Instantiate the logwriter or bust. + */ + postlogd_stream = logwriter_open_or_die(var_maillog_file); + + /* + * Inform the msg_logger client to stop using the postlog socket, and + * to call our logwriter. + */ + msg_logger_control(CA_MSG_LOGGER_CTL_FALLBACK_ONLY, + CA_MSG_LOGGER_CTL_FALLBACK_FN(postlogd_fallback), + CA_MSG_LOGGER_CTL_END); + } +} + +/* post_jail_init - post-jail initialization */ + +static void post_jail_init(char *unused_name, char **unused_argv) +{ + + /* + * Prevent automatic process suicide after a limited number of client + * requests. It is OK to terminate after a limited amount of idle time. + */ + var_use_limit = 0; +} + +MAIL_VERSION_STAMP_DECLARE; + +/* main - pass control to the multi-threaded skeleton */ + +int main(int argc, char **argv) +{ + static const CONFIG_TIME_TABLE time_table[] = { + VAR_POSTLOGD_WATCHDOG, DEF_POSTLOGD_WATCHDOG, &var_postlogd_watchdog, 10, 0, + 0, + }; + + /* + * Fingerprint executables and core dumps. + */ + MAIL_VERSION_STAMP_ALLOCATE; + + /* + * This is a datagram service, not a stream service, so that postlogd can + * restart immediately after "postfix reload" without requiring clients + * to resend messages. Those messages remain queued in the kernel until a + * new postlogd process retrieves them. It would be unreasonable to + * require that clients retransmit logs, especially in the case of a + * fatal or panic error. + */ + dgram_server_main(argc, argv, postlogd_service, + CA_MAIL_SERVER_TIME_TABLE(time_table), + CA_MAIL_SERVER_PRE_INIT(pre_jail_init), + CA_MAIL_SERVER_POST_INIT(post_jail_init), + CA_MAIL_SERVER_SOLITARY, + CA_MAIL_SERVER_WATCHDOG(&var_postlogd_watchdog), + 0); +} |