From b8f485636ac7ecd8cc7bc7d403c227fba0bedca3 Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Tue, 29 Jan 2019 00:00:00 -0500 Subject: [PATCH] postfix-3.4-20190129 --- postfix/.indent.pro | 3 +- postfix/HISTORY | 62 +++ postfix/Makefile.in | 2 +- postfix/RELEASE_NOTES | 79 +++ postfix/WISHLIST | 5 + postfix/conf/master.cf | 1 + postfix/conf/post-install | 10 + postfix/conf/postfix-files | 3 + postfix/conf/postfix-script | 16 +- postfix/html/Makefile.in | 6 +- postfix/html/master.5.html | 101 ++-- postfix/html/master.8.html | 73 +-- postfix/html/postconf.5.html | 49 +- postfix/html/postdrop.1.html | 12 +- postfix/html/postfix-manuals.html | 2 + postfix/html/postfix.1.html | 69 ++- postfix/html/postlog.1.html | 42 +- postfix/html/postlogd.8.html | 87 ++++ postfix/html/postmulti.1.html | 5 + postfix/man/Makefile.in | 7 +- postfix/man/man1/postdrop.1 | 10 +- postfix/man/man1/postfix.1 | 17 + postfix/man/man1/postlog.1 | 18 +- postfix/man/man1/postmulti.1 | 5 + postfix/man/man5/master.5 | 19 +- postfix/man/man5/postconf.5 | 31 +- postfix/man/man8/master.8 | 12 +- postfix/man/man8/postlogd.8 | 92 ++++ postfix/mantools/postlink | 6 + postfix/proto/master | 19 +- postfix/proto/postconf.proto | 37 +- postfix/src/global/Makefile.in | 27 +- postfix/src/global/mail_params.c | 10 +- postfix/src/global/mail_params.h | 19 +- postfix/src/global/mail_proto.h | 1 + postfix/src/global/mail_task.c | 33 +- postfix/src/global/mail_version.h | 2 +- postfix/src/global/maillog_client.c | 278 +++++++++++ postfix/src/global/maillog_client.h | 33 ++ postfix/src/master/Makefile.in | 55 +- postfix/src/master/dgram_server.c | 663 +++++++++++++++++++++++++ postfix/src/master/event_server.c | 14 +- postfix/src/master/mail_server.h | 8 + postfix/src/master/master.c | 33 +- postfix/src/master/master.h | 3 +- postfix/src/master/master_ent.c | 13 + postfix/src/master/master_listen.c | 16 + postfix/src/master/master_proto.h | 6 + postfix/src/master/master_wakeup.c | 10 + postfix/src/master/multi_server.c | 14 +- postfix/src/master/single_server.c | 11 +- postfix/src/master/trigger_server.c | 14 +- postfix/src/postalias/Makefile.in | 2 +- postfix/src/postalias/postalias.c | 18 +- postfix/src/postconf/postconf_master.c | 1 + postfix/src/postdrop/Makefile.in | 2 +- postfix/src/postdrop/postdrop.c | 32 +- postfix/src/postfix/Makefile.in | 2 +- postfix/src/postfix/postfix.c | 49 +- postfix/src/postkick/postkick.c | 5 +- postfix/src/postlog/Makefile.in | 2 +- postfix/src/postlog/postlog.c | 31 +- postfix/src/postlogd/Makefile.in | 74 +++ postfix/src/postlogd/postlogd.c | 251 ++++++++++ postfix/src/postmap/Makefile.in | 2 +- postfix/src/postmap/postmap.c | 10 +- postfix/src/postmulti/Makefile.in | 2 +- postfix/src/postmulti/postmulti.c | 28 +- postfix/src/postqueue/Makefile.in | 2 +- postfix/src/postqueue/postqueue.c | 13 +- postfix/src/postsuper/Makefile.in | 2 +- postfix/src/postsuper/postsuper.c | 8 +- postfix/src/sendmail/Makefile.in | 2 +- postfix/src/sendmail/sendmail.c | 13 +- postfix/src/tls/Makefile.in | 9 +- postfix/src/util/Makefile.in | 52 +- postfix/src/util/connect.h | 6 + postfix/src/util/listen.h | 1 + postfix/src/util/logwriter.c | 124 +++++ postfix/src/util/logwriter.h | 38 ++ postfix/src/util/msg_logger.c | 347 +++++++++++++ postfix/src/util/msg_logger.h | 60 +++ postfix/src/util/msg_output.c | 69 ++- postfix/src/util/msg_output.h | 6 +- postfix/src/util/msg_syslog.c | 56 ++- postfix/src/util/msg_syslog.h | 8 +- postfix/src/util/unix_dgram_connect.c | 90 ++++ postfix/src/util/unix_dgram_listen.c | 93 ++++ postfix/src/util/watchdog.c | 7 + 89 files changed, 3287 insertions(+), 393 deletions(-) create mode 100644 postfix/html/postlogd.8.html create mode 100644 postfix/man/man8/postlogd.8 create mode 100644 postfix/src/global/maillog_client.c create mode 100644 postfix/src/global/maillog_client.h create mode 100644 postfix/src/master/dgram_server.c create mode 100644 postfix/src/postlogd/Makefile.in create mode 100644 postfix/src/postlogd/postlogd.c create mode 100644 postfix/src/util/logwriter.c create mode 100644 postfix/src/util/logwriter.h create mode 100644 postfix/src/util/msg_logger.c create mode 100644 postfix/src/util/msg_logger.h create mode 100644 postfix/src/util/unix_dgram_connect.c create mode 100644 postfix/src/util/unix_dgram_listen.c diff --git a/postfix/.indent.pro b/postfix/.indent.pro index 531e12c1c..7e977406b 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -176,6 +176,7 @@ -TLMTP_STATE -TLOCAL_EXP -TLOCAL_STATE +-TLOGWRITER -TLONG_NAME_MASK -TMAC_EXP_CONTEXT -TMAC_EXP_OP_INFO @@ -399,6 +400,7 @@ -Tgeneral_name_stack_t -Tiana_digest -Toff_t +-Tpem_load_state_t -Tregex_t -Tregmatch_t -Tsasl_conn_t @@ -413,4 +415,3 @@ -Ttime_t -Ttlsa_filter -Tx509_stack_t --Tpem_load_state_t diff --git a/postfix/HISTORY b/postfix/HISTORY index 4a4958894..bfdb67446 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -23946,7 +23946,69 @@ Apologies for any names omitted. dict_open.c, and updated the -F description in the postmap manpage. Files: util/dict_open.c, postmap/postmap.c. +20190121 + + Logging: support for internal logging file, without using + syslog (it uses the new postlogd daemon instead). This + solves a usability problem for MacOS, may help getting + around systemd, and solves 99% of the problem for logging + to stdout in a container (hopefully we have 100% soon). + Enable by setting, for example, "maillog_file = + /var/log/postfix.log"). This works fine for daemons, and + with some limitations for non-daemon programs. See + RELEASE_NOTES for more details. Files: conf/master.cf, + conf/post-install, conf/postfix-files, conf/postfix-script, + mantools/postlink, proto/master, proto/postconf.proto, + global/mail_params.c, global/mail_params.h, global/mail_proto.h, + global/maillog_client.c, global/maillog_client.h, + master/dgram_server.c, master/event_server.c, master/mail_server.h, + master/master.c, master/master.h, master/master_ent.c, + master/master_listen.c, master/master_proto.h, + master/master_wakeup.c, master/multi_server.c, + master/single_server.c, master/trigger_server.c, + postalias/postalias.c, postconf/postconf_master.c, + postdrop/postdrop.c, postfix/postfix.c, postkick/postkick.c, + postlog/postlog.c, postlogd/postlogd.c, postmap/postmap.c, + postmulti/postmulti.c, postqueue/postqueue.c, + postsuper/postsuper.c, sendmail/sendmail.c, util/connect.h, + util/listen.h, util/logwriter.c, util/logwriter.h, + util/msg_logger.c, util/msg_logger.h, util/msg_output.c, + util/msg_output.h, util/unix_dgram_connect.c, + util/unix_dgram_listen.c. + + Safety: temporary postlogd fix to avoid recursion when main.cf + has "maillog_file =" but master(8) still still tells its child + processes to send logs to postlogd. File: postlogd/postlogd.c. + +20190126 + + Safety: Postfix programs will log to either syslog or postlog + but not both; and postlogd forwards postlog logging to + syslog, when a configuration change removes the maillog_file + pathname, but some programs still use the old configuration. + Files: util/msg_syslog.[hc], util/msg_logger.c, + global/maillog_client.c, postlogd/postlogd.c, + + Bugfix (introduced: Postfix 20110109, Postfix 2.10): watchdog + pipe file descriptor leak. This pipe provides one source + of liveness, data from this pipe is discarded, and therefore + this does not enable privilege escalation or DOS. File: + util/watchdog.c. + + Feature: stdout logging support; requires "postfix start-fg" + and "maillog_file = /dev/stdout". Files: master/master.c, + conf/postfix-script. + 20190127 + Safety: when maillog_file is specified, 'postfix check' now + requires that the postlog service is enabled in master.cf. + Otherwise 'postfix start' etc. will log a fatal error. File: + conf/postfix-script. + Documentation: added policy_context example. File: proto/SMTPD_POLICY_README.html. + +20190128 + + Testing: run libtls tests under Valgrind. File tls/Makefile.in. diff --git a/postfix/Makefile.in b/postfix/Makefile.in index f7c43fcc0..fa12b0443 100644 --- a/postfix/Makefile.in +++ b/postfix/Makefile.in @@ -10,7 +10,7 @@ DIRS = src/util src/global src/dns src/tls src/xsasl src/master src/milter \ src/postsuper src/qmqpd src/spawn src/flush src/verify \ src/virtual src/proxymap src/anvil src/scache src/discard src/tlsmgr \ src/postmulti src/postscreen src/dnsblog src/tlsproxy \ - src/posttls-finger + src/posttls-finger src/postlogd MANDIRS = proto man html LIBEXEC = libexec/post-install libexec/postfix-script libexec/postfix-wrapper \ libexec/postmulti-script libexec/postfix-tls-script diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 084382ba5..c87676085 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -30,6 +30,85 @@ Major changes with snapshot 20190127 [TODO: summary of SNI and chain-file support] +Incompatible changes with snapshot 20190126-nonprod +==================================================== + +This introduces a new master.cf service type 'unix-dgram' that is +used by the new postlogd(8) daemon. This type is not supported by +older Postfix versions. Before backing out to an Postfix 3.3 or +earlier, edit the master.cf file and remove the postlog entry. + +Major changes with snapshot 20190126-nonprod +============================================ + +Support for logging to file or stdout. This disables syslog logging. + +- Logging to file solves a usability problem for MacOS users, and + may also be useful on LINUX when systemd is getting in the way. + +- Logging to stdout is useful when Postfix runs in a container, as + it eliminates a syslogd dependency. + +To enable Postfix logging to file or stdout: +-------------------------------------------- + +Add the following line to master.cf (no whitespace at the start of the line): + postlog unix-dgram n - n - 1 postlogd + +To write logs to Postfix logfile: + # postfix stop + # postconf maillog_file=/var/log/postfix.log + # postfix start + +To write logs to stdout, typically while Postfix runs in a container: + # postconf maillog_file=/dev/stdout + # postfix start-fg + +To rotate a Postfix logfile with a daily cronjob: +------------------------------------------------- + +The following applies when the maillog_file parameter specifies a +reguar file. + +- Rename the current logfile in the same directory, appending the + current date to file file name. The following adds a suffix + of the form YYYYMMDD to file name: + # mv postfix.log postfix.log.$(date +%Y%M%d) + +- DO NOT YET COMPRESS THE FILE. POSTFIX STILL WRITES TO IT. + +- Reload Postfix, so that postlogd(8) will start writing to a new + file: + # postfix reload + +- Compress the old file, and move it elsewhere if needed. + +Limitations of logging to Postfix logfile or stdout: +---------------------------------------------------- + +Background: + +- Logging to Postfix logfile or stdout requires the Postfix postlogd(8) + service. This program ensures that simultaneous logging from + different programs will not get mixed up. + +Limitations: + +- Non-daemon Postfix programs may log to syslogd(8) before they + have processed command-line options and main.cf parameters. + +- If Postfix is down, the non-daemon programs postfix(1), postsuper(1), + postmulti(1), and postlog(1), will log directly to $maillog_file. + 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 + $maillog_file (also, logging to stdout would interfere with the + operation of some of these programs). These programs can log to + postlogd(8) if they are run by the super-user, or if their + executable file has set-gid permission. Do not set this permision + on programs other than postdrop(1) and postqueue(1). + Major changes with snapshot 20180826 ==================================== diff --git a/postfix/WISHLIST b/postfix/WISHLIST index 67a0abb8e..8d486fab0 100644 --- a/postfix/WISHLIST +++ b/postfix/WISHLIST @@ -1,5 +1,10 @@ Wish list: + Add maillog_file to postfix(1) exports? + + postfix rotate-log command: mv postfix.log postfix.log.$(date + +%Y%M%d-%H%M%S) to avoid data loss if called repeatedly. + In smtpd(8) and postscreen(8), set the ehlo_discard_mask to ~0 so that STARTTLS, BDAT, DSN, etc. work only for clients that send EHLO. diff --git a/postfix/conf/master.cf b/postfix/conf/master.cf index 5a75ae576..c0f250803 100644 --- a/postfix/conf/master.cf +++ b/postfix/conf/master.cf @@ -64,6 +64,7 @@ virtual unix - n n - - virtual lmtp unix - - n - - lmtp anvil unix - - n - 1 anvil scache unix - - n - 1 scache +postlog unix-dgram n - n - 1 postlogd # # ==================================================================== # Interfaces to non-Postfix software. Be sure to examine the manual diff --git a/postfix/conf/post-install b/postfix/conf/post-install index 25ef7e691..975266b8b 100644 --- a/postfix/conf/post-install +++ b/postfix/conf/post-install @@ -887,6 +887,16 @@ EOF # permit_mynetworks permit_sasl_authenticated \ # defer_unauth_destination" || exit 1 # } + + # Postfix 3.4 + # Add a postlog service entry. + + grep '^postlog' $config_directory/master.cf >/dev/null || { + echo Editing $config_directory/master.cf, adding missing entry for postlog unix-domain datagram service + cat >>$config_directory/master.cf </dev/null \ + | grep . >/dev/null || { + $FATAL "missing 'postlog' service in master.cf - run 'postfix upgrade-configuration'" + exit 1 + } + } + # See if all queue files are in the right place. This is slow. # We must scan all queues for mis-named queue files before the # mail system can run. diff --git a/postfix/html/Makefile.in b/postfix/html/Makefile.in index ecf0961be..c5481f8af 100644 --- a/postfix/html/Makefile.in +++ b/postfix/html/Makefile.in @@ -8,7 +8,7 @@ DAEMONS = bounce.8.html cleanup.8.html defer.8.html error.8.html local.8.html \ oqmgr.8.html spawn.8.html flush.8.html virtual.8.html qmqpd.8.html \ trace.8.html verify.8.html proxymap.8.html anvil.8.html \ scache.8.html discard.8.html tlsmgr.8.html postscreen.8.html \ - dnsblog.8.html tlsproxy.8.html + dnsblog.8.html tlsproxy.8.html postlogd.8.html COMMANDS= mailq.1.html newaliases.1.html postalias.1.html postcat.1.html \ postconf.1.html postfix.1.html postkick.1.html postlock.1.html \ postlog.1.html postdrop.1.html postmap.1.html postmulti.1.html \ @@ -101,6 +101,10 @@ pipe.8.html: ../src/pipe/pipe.c PATH=../mantools:$$PATH; \ srctoman $? | $(AWK) | $(NROFF) -man | uniq | $(MAN2HTML) | postlink >$@ +postlogd.8.html: ../src/postlogd/postlogd.c + PATH=../mantools:$$PATH; \ + srctoman $? | $(AWK) | $(NROFF) -man | uniq | $(MAN2HTML) | postlink >$@ + postscreen.8.html: ../src/postscreen/postscreen.c PATH=../mantools:$$PATH; \ srctoman $? | $(AWK) | $(NROFF) -man | uniq | $(MAN2HTML) | postlink >$@ diff --git a/postfix/html/master.5.html b/postfix/html/master.5.html index 626164b62..4e488fc02 100644 --- a/postfix/html/master.5.html +++ b/postfix/html/master.5.html @@ -81,8 +81,8 @@ MASTER(5) MASTER(5) hard-coding loopback IP address information in master.cf or in main.cf. - unix The service listens on a UNIX-domain socket and is acces- - sible for local clients only. + unix The service listens on a UNIX-domain stream socket and is + accessible for local clients only. The service name is a pathname relative to the Postfix queue directory (pathname controlled with the @@ -91,29 +91,38 @@ MASTER(5) MASTER(5) On Solaris 8 and earlier systems the unix type is imple- mented with streams sockets. - fifo The service listens on a FIFO (named pipe) and is acces- - sible for local clients only. + unix-dgram + The service listens on a UNIX-domain datagram socket and + is accessible for local clients only. The service name is a pathname relative to the Postfix queue directory (pathname controlled with the queue_directory configuration parameter in main.cf). - pass The service listens on a UNIX-domain socket, and is - accessible to local clients only. It receives one open - connection (file descriptor passing) per connection - request. + fifo (obsolete) + The service listens on a FIFO (named pipe) and is acces- + sible for local clients only. The service name is a pathname relative to the Postfix queue directory (pathname controlled with the queue_directory configuration parameter in main.cf). - On Solaris 8 and earlier systems the pass type is imple- + pass The service listens on a UNIX-domain stream socket, and + is accessible to local clients only. It receives one open + connection (file descriptor passing) per connection + request. + + The service name is a pathname relative to the Postfix + queue directory (pathname controlled with the + queue_directory configuration parameter in main.cf). + + On Solaris 8 and earlier systems the pass type is imple- mented with streams sockets. This feature is available as of Postfix version 2.5. Private (default: y) - Whether or not access is restricted to the mail system. Inter- + Whether or not access is restricted to the mail system. Inter- net (type inet) services can't be private. Unprivileged (default: y) @@ -121,80 +130,80 @@ MASTER(5) MASTER(5) the Postfix system (the owner name is controlled by the mail_owner configuration variable in the main.cf file). - The local(8), pipe(8), spawn(8), and virtual(8) daemons require + The local(8), pipe(8), spawn(8), and virtual(8) daemons require privileges. Chroot (default: Postfix >= 3.0: n, Postfix <3.0: y) - Whether or not the service runs chrooted to the mail queue + Whether or not the service runs chrooted to the mail queue directory (pathname is controlled by the queue_directory config- uration variable in the main.cf file). - Chroot should not be used with the local(8), pipe(8), spawn(8), + Chroot should not be used with the local(8), pipe(8), spawn(8), and virtual(8) daemons. Although the proxymap(8) server can run - chrooted, doing so defeats most of the purpose of having that + chrooted, doing so defeats most of the purpose of having that service in the first place. The files in the examples/chroot-setup subdirectory of the Post- - fix source show how to set up a Postfix chroot environment on a - variety of systems. See also BASIC_CONFIGURATION_README for + fix source show how to set up a Postfix chroot environment on a + variety of systems. See also BASIC_CONFIGURATION_README for issues related to running daemons chrooted. Wake up time (default: 0) Automatically wake up the named service after the specified num- - ber of seconds. The wake up is implemented by connecting to the - service and sending a wake up request. A ? at the end of the - wake-up time field requests that no wake up events be sent + ber of seconds. The wake up is implemented by connecting to the + service and sending a wake up request. A ? at the end of the + wake-up time field requests that no wake up events be sent before the first time a service is used. Specify 0 for no auto- matic wake up. - The pickup(8), qmgr(8) and flush(8) daemons require a wake up + The pickup(8), qmgr(8) and flush(8) daemons require a wake up timer. Process limit (default: $default_process_limit) - The maximum number of processes that may execute this service + The maximum number of processes that may execute this service simultaneously. Specify 0 for no process count limit. - NOTE: Some Postfix services must be configured as a sin- - gle-process service (for example, qmgr(8)) and some services - must be configured with no process limit (for example, + NOTE: Some Postfix services must be configured as a sin- + gle-process service (for example, qmgr(8)) and some services + must be configured with no process limit (for example, cleanup(8)). These limits must not be changed. Command name + arguments - The command to be executed. Characters that are special to the - shell such as ">" or "|" have no special meaning here, and - quotes cannot be used to protect arguments containing white- - space. To protect whitespace, use "{" and "}" as described + The command to be executed. Characters that are special to the + shell such as ">" or "|" have no special meaning here, and + quotes cannot be used to protect arguments containing white- + space. To protect whitespace, use "{" and "}" as described below. - The command name is relative to the Postfix daemon directory - (pathname is controlled by the daemon_directory configuration + The command name is relative to the Postfix daemon directory + (pathname is controlled by the daemon_directory configuration variable). - The command argument syntax for specific commands is specified + The command argument syntax for specific commands is specified in the respective daemon manual page. - The following command-line options have the same effect for all + The following command-line options have the same effect for all daemon programs: - -D Run the daemon under control by the command specified + -D Run the daemon under control by the command specified with the debugger_command variable in the main.cf config- uration file. See DEBUG_README for hints and tips. -o { name = value } (long form, Postfix >= 3.0) -o name=value (short form) - Override the named main.cf configuration parameter. The - parameter value can refer to other parameters as $name - etc., just like in main.cf. See postconf(5) for syntax. + Override the named main.cf configuration parameter. The + parameter value can refer to other parameters as $name + etc., just like in main.cf. See postconf(5) for syntax. - NOTE 1: With the "long form" shown above, whitespace - after "{", around "=", and before "}" is ignored, and + NOTE 1: With the "long form" shown above, whitespace + after "{", around "=", and before "}" is ignored, and whitespace within the parameter value is preserved. NOTE 2: with the "short form" shown above, do not specify - whitespace around the "=" or in parameter values. To - specify a parameter value that contains whitespace, use - the long form described above, or use commas instead of + whitespace around the "=" or in parameter values. To + specify a parameter value that contains whitespace, use + the long form described above, or use commas instead of spaces, or specify the value in main.cf. Example: /etc/postfix/master.cf: @@ -205,18 +214,18 @@ MASTER(5) MASTER(5) submission_xxx_yyy = text with whitespace... NOTE 3: Over-zealous use of parameter overrides makes the - Postfix configuration hard to understand and maintain. - At a certain point, it might be easier to configure mul- + Postfix configuration hard to understand and maintain. + At a certain point, it might be easier to configure mul- tiple instances of Postfix, instead of configuring multi- ple personalities via master.cf. - -v Increase the verbose logging level. Specify multiple -v - options to make a Postfix daemon process increasingly + -v Increase the verbose logging level. Specify multiple -v + options to make a Postfix daemon process increasingly verbose. Other command-line arguments Specify "{" and "}" around command arguments that contain - whitespace (Postfix 3.0 and later). Whitespace after "{" + whitespace (Postfix 3.0 and later). Whitespace after "{" and before "}" is ignored. SEE ALSO diff --git a/postfix/html/master.8.html b/postfix/html/master.8.html index 64d6735d4..66087d344 100644 --- a/postfix/html/master.8.html +++ b/postfix/html/master.8.html @@ -47,23 +47,26 @@ MASTER(8) MASTER(8) Terminate the master process after exit_time seconds. Child pro- cesses terminate at their convenience. - -i Enable init mode: do not attempt to become a session or process - group leader; and to force termination, set an explicit signal - handler instead of relying on the default signal action. This - mode is allowed only if the process ID equals 1. + -i Enable init mode: do not become a session or process group + leader; similar to -s, do not redirect stdout to /dev/null, so + that "maillog_file = /dev/stdout" works. This mode is allowed + only if the process ID equals 1. - -t Test mode. Return a zero exit status when the master.pid lock - file does not exist or when that file is not locked. This is + -s Do not redirect stdout to /dev/null, so that "maillog_file = + /dev/stdout" works. + + -t Test mode. Return a zero exit status when the master.pid lock + file does not exist or when that file is not locked. This is evidence that the master(8) daemon is not running. - -v Enable verbose logging for debugging purposes. This option is + -v Enable verbose logging for debugging purposes. This option is passed on to child processes. Multiple -v options make the soft- ware increasingly verbose. -w Wait in a dummy foreground process, while the real master daemon - initializes in a background process. The dummy foreground - process returns a zero exit status only if the master daemon - initialization is successful, and if it completes in a reason- + initializes in a background process. The dummy foreground + process returns a zero exit status only if the master daemon + initialization is successful, and if it completes in a reason- able amount of time. This feature is available in Postfix 2.10 and later. @@ -71,27 +74,27 @@ MASTER(8) MASTER(8) Signals: SIGHUP Upon receipt of a HUP signal (e.g., after "postfix reload"), the - master process re-reads its configuration files. If a service - has been removed from the master.cf file, its running processes - are terminated immediately. Otherwise, running processes are - allowed to terminate as soon as is convenient, so that changes + master process re-reads its configuration files. If a service + has been removed from the master.cf file, its running processes + are terminated immediately. Otherwise, running processes are + allowed to terminate as soon as is convenient, so that changes in configuration settings affect only new service requests. SIGTERM Upon receipt of a TERM signal (e.g., after "postfix abort"), the - master process passes the signal on to its child processes and - terminates. This is useful for an emergency shutdown. Normally - one would terminate only the master ("postfix stop") and allow + master process passes the signal on to its child processes and + terminates. This is useful for an emergency shutdown. Normally + one would terminate only the master ("postfix stop") and allow running processes to finish what they are doing. DIAGNOSTICS - Problems are reported to syslogd(8). The exit status is non-zero in - case of problems, including problems while initializing as a master + Problems are reported to syslogd(8). The exit status is non-zero in + case of problems, including problems while initializing as a master daemon process in the background. ENVIRONMENT MAIL_DEBUG - After initialization, start a debugger as specified with the + After initialization, start a debugger as specified with the debugger_command configuration parameter in the main.cf configu- ration file. @@ -99,18 +102,18 @@ MASTER(8) MASTER(8) Directory with Postfix configuration files. CONFIGURATION PARAMETERS - Unlike most Postfix daemon processes, the master(8) server does not - automatically pick up changes to main.cf. Changes to master.cf are - never picked up automatically. Use the "postfix reload" command after + Unlike most Postfix daemon processes, the master(8) server does not + automatically pick up changes to main.cf. Changes to master.cf are + never picked up automatically. Use the "postfix reload" command after a configuration change. RESOURCE AND RATE CONTROLS default_process_limit (100) - The default maximal number of Postfix child processes that pro- + The default maximal number of Postfix child processes that pro- vide a given service. max_idle (100s) - The maximum amount of time that an idle Postfix daemon process + The maximum amount of time that an idle Postfix daemon process waits for an incoming connection before terminating voluntarily. max_use (100) @@ -118,18 +121,18 @@ MASTER(8) MASTER(8) process will service before terminating voluntarily. service_throttle_time (60s) - How long the Postfix master(8) waits before forking a server + How long the Postfix master(8) waits before forking a server that appears to be malfunctioning. Available in Postfix version 2.6 and later: master_service_disable (empty) - Selectively disable master(8) listener ports by service type or + Selectively disable master(8) listener ports by service type or by service name and type. MISCELLANEOUS CONTROLS config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con- figuration files. daemon_directory (see 'postconf -d' output) @@ -140,20 +143,20 @@ MASTER(8) MASTER(8) invoked with the -D option. inet_interfaces (all) - The network interface addresses that this mail system receives + The network interface addresses that this mail system receives mail on. inet_protocols (all) - The Internet protocols Postfix will attempt to use when making + The Internet protocols Postfix will attempt to use when making or accepting connections. import_environment (see 'postconf -d' output) - The list of environment parameters that a privileged Postfix - process will import from a non-Postfix parent process, or + The list of environment parameters that a privileged Postfix + process will import from a non-Postfix parent process, or name=value environment overrides. mail_owner (postfix) - The UNIX system account that owns the Postfix queue and most + The UNIX system account that owns the Postfix queue and most Postfix daemon processes. process_id (read-only) @@ -169,7 +172,7 @@ MASTER(8) MASTER(8) The syslog facility of Postfix logging. syslog_name (see 'postconf -d' output) - A prefix that is prepended to the process name in syslog + A prefix that is prepended to the process name in syslog records, so that, for example, "smtpd" becomes "prefix/smtpd". Available in Postfix 3.3 and later: @@ -178,7 +181,7 @@ MASTER(8) MASTER(8) The master.cf service name of a Postfix daemon process. FILES - To expand the directory names below into their actual values, use the + To expand the directory names below into their actual values, use the command "postconf config_directory" etc. $config_directory/main.cf, global configuration file. diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index 17e67f0a7..6aa08434c 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -6235,6 +6235,23 @@ substitutions in regular expression maps.

This feature is available in Postfix 2.3 and later.

+ + +
maillog_file +(default: empty)
+ +

The name of an optional logfile that is written by the Postfix +postlogd(8) service. A non-empty value disables logging to syslogd(8). +Specify "/dev/stdout" for logging to standard output. Stdout logging +requires that Postfix is started with "postfix start-fg".

+ +

Note: Some Postfix non-daemon programs may still log information +to syslogd(8), before they have processed their configuration +parameters and command-line options.

+ +

This feature is available in Postfix 3.4 and later.

+ +
mailq_path @@ -7619,6 +7636,36 @@ is rejected by the reject_

This feature is available in Postfix 2.3 and later.

+ + +
postlog_service_name +(default: postlog)
+ +

The name of the postlogd(8) service entry in master.cf. +This service appends logfile records to the file specified +with the maillog_file parameter.

+ +

This feature is available in Postfix 3.4 and later.

+ + +
+ +
postlogd_watchdog_timeout +(default: 10s)
+ +

How much time a postlogd(8) process may take to process a request +before it is terminated by a built-in watchdog timer. This is a +safety mechanism that prevents postlogd(8) from becoming non-responsive +due to a bug in Postfix itself or in system software. This limit +cannot be set under 10s.

+ +

Specify a non-zero time value (an integral value plus an optional +one-letter suffix that specifies the time unit). Time units: s +(seconds), m (minutes), h (hours), d (days), w (weeks).

+ +

This feature is available in Postfix 3.4 and later.

+ +
postmulti_control_commands @@ -19439,7 +19486,7 @@ cannot be set under 10s.

one-letter suffix that specifies the time unit). Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).

-

This feature is available in Postfix 2.8.

+

This feature is available in Postfix 2.8 and later

diff --git a/postfix/html/postdrop.1.html b/postfix/html/postdrop.1.html index 994432632..9d73c335b 100644 --- a/postfix/html/postdrop.1.html +++ b/postfix/html/postdrop.1.html @@ -60,16 +60,18 @@ POSTDROP(1) POSTDROP(1) alternate_config_directories (empty) A list of non-default Postfix configuration directories that may - be specified with "-c config_directory" on the command line, or - via the MAIL_CONFIG environment parameter. + be specified with "-c config_directory" on the command line (in + the case of sendmail(1), with the "-C" option), or via the + MAIL_CONFIG environment parameter. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con- figuration files. import_environment (see 'postconf -d' output) - The list of environment parameters that a Postfix process will - import from a non-Postfix parent process. + The list of environment parameters that a privileged Postfix + process will import from a non-Postfix parent process, or + name=value environment overrides. queue_directory (see 'postconf -d' output) The location of the Postfix top-level queue directory. diff --git a/postfix/html/postfix-manuals.html b/postfix/html/postfix-manuals.html index 18448053c..9b90c23df 100644 --- a/postfix/html/postfix-manuals.html +++ b/postfix/html/postfix-manuals.html @@ -208,6 +208,8 @@ the following convention:

  • pipe(8), deliver mail to non-Postfix command +
  • postlogd(8), Postfix internal logging service +
  • postscreen(8), Postfix zombie blocker
  • proxymap(8), Postfix lookup table proxy server diff --git a/postfix/html/postfix.1.html b/postfix/html/postfix.1.html index c7514f377..aeec1c36c 100644 --- a/postfix/html/postfix.1.html +++ b/postfix/html/postfix.1.html @@ -141,12 +141,23 @@ POSTFIX(1) POSTFIX(1) MAIL_DEBUG This is set when the -D command-line option is present. + When the internal logging service is enabled (by setting a non-empty + maillog_file parameter value) the postfix(1) command exports settings + that are used by child processes before they have processed main.cf or + command-line settings. + + POSTLOG_SERVICE + The name of the public postlog service endpoint. + + POSTLOG_HOSTNAME + The hostname to prepend to internal logging. + CONFIGURATION PARAMETERS The following main.cf configuration parameters are exported as environ- ment variables with the same names: config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con- figuration files. command_directory (see 'postconf -d' output) @@ -156,22 +167,22 @@ POSTFIX(1) POSTFIX(1) The directory with Postfix support programs and daemon programs. html_directory (see 'postconf -d' output) - The location of Postfix HTML files that describe how to build, + The location of Postfix HTML files that describe how to build, configure or operate a specific Postfix subsystem or feature. mail_owner (postfix) - The UNIX system account that owns the Postfix queue and most + The UNIX system account that owns the Postfix queue and most Postfix daemon processes. mailq_path (see 'postconf -d' output) - Sendmail compatibility feature that specifies where the Postfix + Sendmail compatibility feature that specifies where the Postfix mailq(1) command is installed. manpage_directory (see 'postconf -d' output) Where the Postfix manual pages are installed. newaliases_path (see 'postconf -d' output) - Sendmail compatibility feature that specifies the location of + Sendmail compatibility feature that specifies the location of the newaliases(1) command. queue_directory (see 'postconf -d' output) @@ -182,31 +193,31 @@ POSTFIX(1) POSTFIX(1) configure or operate a specific Postfix subsystem or feature. sendmail_path (see 'postconf -d' output) - A Sendmail compatibility feature that specifies the location of + A Sendmail compatibility feature that specifies the location of the Postfix sendmail(1) command. setgid_group (postdrop) - The group ownership of set-gid Postfix commands and of + The group ownership of set-gid Postfix commands and of group-writable Postfix directories. Available in Postfix version 2.5 and later: data_directory (see 'postconf -d' output) - The directory with Postfix-writable data files (for example: + The directory with Postfix-writable data files (for example: caches, pseudo-random numbers). Available in Postfix version 3.0 and later: meta_directory (see 'postconf -d' output) - The location of non-executable files that are shared among mul- - tiple Postfix instances, such as postfix-files, dynamicmaps.cf, - and the multi-instance template files main.cf.proto and mas- + The location of non-executable files that are shared among mul- + tiple Postfix instances, such as postfix-files, dynamicmaps.cf, + and the multi-instance template files main.cf.proto and mas- ter.cf.proto. shlib_directory (see 'postconf -d' output) - The location of Postfix dynamically-linked libraries (libpost- - fix-*.so), and the default location of Postfix database plugins - (postfix-*.so) that have a relative pathname in the dynam- + The location of Postfix dynamically-linked libraries (libpost- + fix-*.so), and the default location of Postfix database plugins + (postfix-*.so) that have a relative pathname in the dynam- icmaps.cf file. Available in Postfix version 3.1 and later: @@ -217,29 +228,29 @@ POSTFIX(1) POSTFIX(1) Other configuration parameters: import_environment (see 'postconf -d' output) - The list of environment parameters that a privileged Postfix - process will import from a non-Postfix parent process, or + The list of environment parameters that a privileged Postfix + process will import from a non-Postfix parent process, or name=value environment overrides. syslog_facility (mail) The syslog facility of Postfix logging. syslog_name (see 'postconf -d' output) - A prefix that is prepended to the process name in syslog + A prefix that is prepended to the process name in syslog records, so that, for example, "smtpd" becomes "prefix/smtpd". Available in Postfix version 2.6 and later: multi_instance_directories (empty) - An optional list of non-default Postfix configuration directo- - ries; these directories belong to additional Postfix instances - that share the Postfix executable files and documentation with - the default Postfix instance, and that are started, stopped, + An optional list of non-default Postfix configuration directo- + ries; these directories belong to additional Postfix instances + that share the Postfix executable files and documentation with + the default Postfix instance, and that are started, stopped, etc., together with the default Postfix instance. multi_instance_wrapper (empty) - The pathname of a multi-instance manager command that the post- - fix(1) command invokes when the multi_instance_directories + The pathname of a multi-instance manager command that the post- + fix(1) command invokes when the multi_instance_directories parameter value is non-empty. multi_instance_group (empty) @@ -249,9 +260,18 @@ POSTFIX(1) POSTFIX(1) The optional instance name of this Postfix instance. multi_instance_enable (no) - Allow this Postfix instance to be started, stopped, etc., by a + Allow this Postfix instance to be started, stopped, etc., by a multi-instance manager. + Available in Postfix version 3.4 and later: + + maillog_file (empty) + The name of an optional logfile that is written by the Postfix + postlogd(8) service. + + postlog_service_name (postlog) + The name of the postlogd(8) service entry in master.cf. + FILES Prior to Postfix version 2.6, all of the following files were in $con- fig_directory. Some files are now in $daemon_directory so that they can @@ -328,6 +348,7 @@ POSTFIX(1) POSTFIX(1) oqmgr(8), old Postfix queue manager pickup(8), Postfix local mail pickup pipe(8), deliver mail to non-Postfix command + postlogd(8), Postfix internal logging service postscreen(8), Postfix zombie blocker proxymap(8), Postfix lookup table proxy server qmgr(8), Postfix queue manager diff --git a/postfix/html/postlog.1.html b/postfix/html/postlog.1.html index bf3b0ad5a..672de9f58 100644 --- a/postfix/html/postlog.1.html +++ b/postfix/html/postlog.1.html @@ -20,8 +20,8 @@ POSTLOG(1) POSTLOG(1) record. If no text is specified on the command line, postlog(1) reads from standard input and logs each input line as one record. - Logging is sent to syslogd(8); when the standard error stream is con- - nected to a terminal, logging is sent there as well. + By default, logging is sent to syslogd(8); when the standard error + stream is connected to a terminal, logging is sent there as well. The following options are implemented: @@ -29,19 +29,21 @@ POSTLOG(1) POSTLOG(1) Read the main.cf configuration file in the named directory instead of the default configuration directory. - -i Include the process ID in the logging tag. + -i (obsolete) + Include the process ID in the logging tag. This flag is ignored + as of Postfix 3.4, where the PID is always included. -p priority (default: info) - Specifies the logging severity: info, warn, error, fatal, or - panic. With Postfix 3.1 and later, the program will pause for 1 - second after reporting a fatal or panic condition, just like + Specifies the logging severity: info, warn, error, fatal, or + panic. With Postfix 3.1 and later, the program will pause for 1 + second after reporting a fatal or panic condition, just like other Postfix programs. - -t tag Specifies the logging tag, that is, the identifying name that - appears at the beginning of each logging record. A default tag + -t tag 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. - -v Enable verbose logging for debugging purposes. Multiple -v + -v Enable verbose logging for debugging purposes. Multiple -v options make the software increasingly verbose. ENVIRONMENT @@ -49,31 +51,41 @@ POSTLOG(1) POSTLOG(1) Directory with the main.cf file. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant to this pro- + The following main.cf parameters are especially relevant to this pro- gram. - The text below provides only a parameter summary. See postconf(5) for + The text below provides only a parameter summary. See postconf(5) for more details including examples. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con- figuration files. import_environment (see 'postconf -d' output) - The list of environment parameters that a privileged Postfix - process will import from a non-Postfix parent process, or + The list of environment parameters that a privileged Postfix + process will import from a non-Postfix parent process, or name=value environment overrides. syslog_facility (mail) The syslog facility of Postfix logging. syslog_name (see 'postconf -d' output) - A prefix that is prepended to the process name in syslog + A prefix that is prepended to the process name in syslog records, so that, for example, "smtpd" becomes "prefix/smtpd". + Available in Postfix 3.4 and later: + + maillog_file (empty) + The name of an optional logfile that is written by the Postfix + postlogd(8) service. + + postlog_service_name (postlog) + The name of the postlogd(8) service entry in master.cf. + SEE ALSO postconf(5), configuration parameters syslogd(8), syslog daemon + postlogd(8), internal logging service LICENSE The Secure Mailer license must be distributed with this software. diff --git a/postfix/html/postlogd.8.html b/postfix/html/postlogd.8.html new file mode 100644 index 000000000..d41c55488 --- /dev/null +++ b/postfix/html/postlogd.8.html @@ -0,0 +1,87 @@ + + + + Postfix manual - postlogd(8) +
    +POSTLOGD(8)                                                        POSTLOGD(8)
    +
    +NAME
    +       postlogd - Postfix internal log server
    +
    +SYNOPSIS
    +       postlogd [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 postfix(1), postsuper(1),
    +       postmulti(1), and postlog(1), will log directly to $maillog_file. 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  $mail-
    +       log_file (also, logging to stdout would interfere with the operation of
    +       some of these programs). These programs can log to postlogd(8) if  they
    +       are run by the super-user, or if their executable file has set-gid per-
    +       mission. Do not set this permision on programs other  than  postdrop(1)
    +       and postqueue(1).
    +
    +CONFIGURATION PARAMETERS
    +       Changes  to  main.cf  are  picked up automatically, as postlogd(8) pro-
    +       cesses run for only a limited amount of time. Use the command  "postfix
    +       reload" to speed up a change.
    +
    +       The  text  below provides only a parameter summary. See postconf(5) for
    +       more details including examples.
    +
    +       config_directory (see 'postconf -d' output)
    +              The default location of the Postfix main.cf and  master.cf  con-
    +              figuration files.
    +
    +       maillog_file (empty)
    +              The  name  of an optional logfile that is written by the Postfix
    +              postlogd(8) service.
    +
    +       process_id (read-only)
    +              The process ID of a Postfix command or daemon process.
    +
    +       process_name (read-only)
    +              The process name of a Postfix command or daemon process.
    +
    +       syslog_name (see 'postconf -d' output)
    +              A prefix that  is  prepended  to  the  process  name  in  syslog
    +              records, so that, for example, "smtpd" becomes "prefix/smtpd".
    +
    +       service_name (read-only)
    +              The master.cf service name of a Postfix daemon process.
    +
    +       postlogd_watchdog_timeout (10s)
    +              How  much  time  a  postlogd(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(5), system logging
    +
    +LICENSE
    +       The Secure Mailer license must be distributed with this software.
    +
    +HISTORY
    +       This service was introduced with Postfix version 3.4.
    +
    +AUTHOR(S)
    +       Wietse Venema
    +       Google, Inc.
    +       111 8th Avenue
    +       New York, NY 10011, USA
    +
    +                                                                   POSTLOGD(8)
    +
    diff --git a/postfix/html/postmulti.1.html b/postfix/html/postmulti.1.html index c7c1f1570..0115b9fd8 100644 --- a/postfix/html/postmulti.1.html +++ b/postfix/html/postmulti.1.html @@ -399,5 +399,10 @@ POSTMULTI(1) POSTMULTI(1) P.O. Box 704 Yorktown Heights, NY 10598, USA + Wietse Venema + Google, Inc. + 111 8th Avenue + New York, NY 10011, USA + POSTMULTI(1) diff --git a/postfix/man/Makefile.in b/postfix/man/Makefile.in index 4fba8b61d..f98402ca9 100644 --- a/postfix/man/Makefile.in +++ b/postfix/man/Makefile.in @@ -8,7 +8,7 @@ DAEMONS = man8/bounce.8 man8/defer.8 man8/cleanup.8 man8/error.8 man8/local.8 \ man8/oqmgr.8 man8/spawn.8 man8/flush.8 man8/virtual.8 man8/qmqpd.8 \ man8/verify.8 man8/trace.8 man8/proxymap.8 man8/anvil.8 \ man8/scache.8 man8/discard.8 man8/tlsmgr.8 man8/postscreen.8 \ - man8/dnsblog.8 man8/tlsproxy.8 + man8/dnsblog.8 man8/tlsproxy.8 man8/postlogd.8 COMMANDS= man1/postalias.1 man1/postcat.1 man1/postconf.1 man1/postfix.1 \ man1/postkick.1 man1/postlock.1 man1/postlog.1 man1/postdrop.1 \ man1/postmap.1 man1/postmulti.1 man1/postqueue.1 man1/postsuper.1 \ @@ -109,6 +109,11 @@ man8/pipe.8: ../src/pipe/pipe.c (cmp -s junk $? || mv junk $?) && rm -f junk ../mantools/srctoman $? >$@ +man8/postlogd.8: ../src/postlogd/postlogd.c + ../mantools/fixman ../proto/postconf.proto $? >junk && \ + (cmp -s junk $? || mv junk $?) && rm -f junk + ../mantools/srctoman $? >$@ + man8/postscreen.8: ../src/postscreen/postscreen.c ../mantools/fixman ../proto/postconf.proto $? >junk && \ (cmp -s junk $? || mv junk $?) && rm -f junk diff --git a/postfix/man/man1/postdrop.1 b/postfix/man/man1/postdrop.1 index 483c0a474..674b0e57c 100644 --- a/postfix/man/man1/postdrop.1 +++ b/postfix/man/man1/postdrop.1 @@ -70,14 +70,16 @@ The text below provides only a parameter summary. See \fBpostconf\fR(5) for more details including examples. .IP "\fBalternate_config_directories (empty)\fR" A list of non\-default Postfix configuration directories that may -be specified with "\-c config_directory" on the command line, or -via the MAIL_CONFIG environment parameter. +be specified with "\-c config_directory" on the command line (in the +case of \fBsendmail\fR(1), with the "\-C" option), or via the MAIL_CONFIG +environment parameter. .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 Postfix process will -import from a non\-Postfix parent process. +The list of environment parameters that a privileged Postfix +process will import from a non\-Postfix parent process, or name=value +environment overrides. .IP "\fBqueue_directory (see 'postconf -d' output)\fR" The location of the Postfix top\-level queue directory. .IP "\fBsyslog_facility (mail)\fR" diff --git a/postfix/man/man1/postfix.1 b/postfix/man/man1/postfix.1 index 01c972e88..bc5775a62 100644 --- a/postfix/man/man1/postfix.1 +++ b/postfix/man/man1/postfix.1 @@ -136,6 +136,15 @@ commands that run as a descendant of the current process. This is set when the \-v command\-line option is present. .IP \fBMAIL_DEBUG\fR This is set when the \-D command\-line option is present. +.PP +When the internal logging service is enabled (by setting a +non\-empty maillog_file parameter value) the postfix(1) +command exports settings that are used by child processes +before they have processed main.cf or command\-line settings. +.IP \fBPOSTLOG_SERVICE +The name of the public postlog service endpoint. +.IP \fBPOSTLOG_HOSTNAME +The hostname to prepend to internal logging. .SH "CONFIGURATION PARAMETERS" .na .nf @@ -225,6 +234,13 @@ The optional instance name of this Postfix instance. .IP "\fBmulti_instance_enable (no)\fR" Allow this Postfix instance to be started, stopped, etc., by a multi\-instance manager. +.PP +Available in Postfix version 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. .SH "FILES" .na .nf @@ -310,6 +326,7 @@ master(8), Postfix master daemon oqmgr(8), old Postfix queue manager pickup(8), Postfix local mail pickup pipe(8), deliver mail to non\-Postfix command +postlogd(8), Postfix internal logging service postscreen(8), Postfix zombie blocker proxymap(8), Postfix lookup table proxy server qmgr(8), Postfix queue manager diff --git a/postfix/man/man1/postlog.1 b/postfix/man/man1/postlog.1 index 10b1eb826..435c49bdc 100644 --- a/postfix/man/man1/postlog.1 +++ b/postfix/man/man1/postlog.1 @@ -23,15 +23,17 @@ 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. -Logging is sent to \fBsyslogd\fR(8); when the standard error stream -is connected to a terminal, logging is sent there as well. +By default, logging is sent to \fBsyslogd\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 -Include the process ID in the logging tag. +.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 @@ -74,11 +76,19 @@ 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. .SH "SEE ALSO" .na .nf postconf(5), configuration parameters syslogd(8), syslog daemon +postlogd(8), internal logging service .SH "LICENSE" .na .nf diff --git a/postfix/man/man1/postmulti.1 b/postfix/man/man1/postmulti.1 index 4a35947ff..ad04dea1e 100644 --- a/postfix/man/man1/postmulti.1 +++ b/postfix/man/man1/postmulti.1 @@ -427,3 +427,8 @@ 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 diff --git a/postfix/man/man5/master.5 b/postfix/man/man5/master.5 index d37173b1c..008181f84 100644 --- a/postfix/man/man5/master.5 +++ b/postfix/man/man5/master.5 @@ -85,8 +85,8 @@ Note: with Postfix version 2.2 and later specify of hard\-coding loopback IP address information in master.cf or in main.cf. .IP \fBunix\fR -The service listens on a UNIX\-domain socket and is accessible -for local clients only. +The service listens on a UNIX\-domain stream socket and is +accessible for local clients only. The service name is a pathname relative to the Postfix queue directory (pathname controlled with the \fBqueue_directory\fR @@ -94,7 +94,14 @@ configuration parameter in main.cf). .sp On Solaris 8 and earlier systems the \fBunix\fR type is implemented with streams sockets. -.IP \fBfifo\fR +.IP \fBunix\-dgram\fR +The service listens on a UNIX\-domain datagram socket and is +accessible for local clients only. + +The service name is a pathname relative to the Postfix +queue directory (pathname controlled with the \fBqueue_directory\fR +configuration parameter in main.cf). +.IP "\fBfifo\fR (obsolete)" The service listens on a FIFO (named pipe) and is accessible for local clients only. @@ -102,9 +109,9 @@ The service name is a pathname relative to the Postfix queue directory (pathname controlled with the \fBqueue_directory\fR configuration parameter in main.cf). .IP \fBpass\fR -The service listens on a UNIX\-domain socket, and is accessible -to local clients only. It receives one open connection (file -descriptor passing) per connection request. +The service listens on a UNIX\-domain stream socket, and is +accessible to local clients only. It receives one open +connection (file descriptor passing) per connection request. The service name is a pathname relative to the Postfix queue directory (pathname controlled with the \fBqueue_directory\fR diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index 7263bbda8..fa01f867a 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -3748,6 +3748,17 @@ For safety reasons, this feature does not allow $number substitutions in regular expression maps. .PP This feature is available in Postfix 2.3 and later. +.SH maillog_file (default: empty) +The name of an optional logfile that is written by the Postfix +\fBpostlogd\fR(8) service. A non\-empty value disables logging to \fBsyslogd\fR(8). +Specify "/dev/stdout" for logging to standard output. Stdout logging +requires that Postfix is started with "postfix start\-fg". +.PP +Note: Some Postfix non\-daemon programs may still log information +to \fBsyslogd\fR(8), before they have processed their configuration +parameters and command\-line options. +.PP +This feature is available in Postfix 3.4 and later. .SH mailq_path (default: see "postconf \-d" output) Sendmail compatibility feature that specifies where the Postfix \fBmailq\fR(1) command is installed. This command can be used to @@ -4640,6 +4651,24 @@ The numerical Postfix SMTP server response code when a request is rejected by the \fBreject_plaintext_session\fR restriction. .PP This feature is available in Postfix 2.3 and later. +.SH postlog_service_name (default: postlog) +The name of the \fBpostlogd\fR(8) service entry in master.cf. +This service appends logfile records to the file specified +with the maillog_file parameter. +.PP +This feature is available in Postfix 3.4 and later. +.SH postlogd_watchdog_timeout (default: 10s) +How much time a \fBpostlogd\fR(8) process may take to process a request +before it is terminated by a built\-in watchdog timer. This is a +safety mechanism that prevents \fBpostlogd\fR(8) from becoming non\-responsive +due to a bug in Postfix itself or in system software. This limit +cannot be set under 10s. +.PP +Specify a non\-zero time value (an integral value plus an optional +one\-letter suffix that specifies the time unit). Time units: s +(seconds), m (minutes), h (hours), d (days), w (weeks). +.PP +This feature is available in Postfix 3.4 and later. .SH postmulti_control_commands (default: reload flush) The \fBpostfix\fR(1) commands that the \fBpostmulti\fR(1) instance manager treats as "control" commands, that operate on running instances. For @@ -13508,7 +13537,7 @@ Specify a non\-zero time value (an integral value plus an optional one\-letter suffix that specifies the time unit). Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). .PP -This feature is available in Postfix 2.8. +This feature is available in Postfix 2.8 and later .SH trace_service_name (default: trace) The name of the trace service. This service is implemented by the \fBbounce\fR(8) daemon and maintains a record diff --git a/postfix/man/man8/master.8 b/postfix/man/man8/master.8 index 6594edc08..c6790ea4a 100644 --- a/postfix/man/man8/master.8 +++ b/postfix/man/man8/master.8 @@ -44,11 +44,13 @@ for debugging only. Terminate the master process after \fIexit_time\fR seconds. Child processes terminate at their convenience. .IP \fB\-i\fR -Enable \fBinit\fR mode: do not attempt to become a session -or process group leader; and to force termination, set an -explicit signal handler instead of relying on the default -signal action. This mode is allowed only if the process ID -equals 1. +Enable \fBinit\fR mode: do not become a session or process +group leader; similar to \fB\-s\fR, do not redirect stdout +to /dev/null, so that "maillog_file = /dev/stdout" works. +This mode is allowed only if the process ID equals 1. +.IP \fB\-s\fR +Do not redirect stdout to /dev/null, so that "maillog_file += /dev/stdout" works. .IP \fB\-t\fR Test mode. Return a zero exit status when the \fBmaster.pid\fR lock file does not exist or when that file is not locked. This is evidence diff --git a/postfix/man/man8/postlogd.8 b/postfix/man/man8/postlogd.8 new file mode 100644 index 000000000..811b7f949 --- /dev/null +++ b/postfix/man/man8/postlogd.8 @@ -0,0 +1,92 @@ +.TH POSTLOGD 8 +.ad +.fi +.SH NAME +postlogd +\- +Postfix internal log server +.SH "SYNOPSIS" +.na +.nf +\fBpostlogd\fR [generic Postfix daemon options] +.SH DESCRIPTION +.ad +.fi +This program logs events on behalf of Postfix programs +when the maillog configuration parameter specifies a non\-empty +value. +.SH BUGS +.ad +.fi +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 permision on programs other than \fBpostdrop\fR(1) +and \fBpostqueue\fR(1). +.SH "CONFIGURATION PARAMETERS" +.na +.nf +.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. +.SH "SEE ALSO" +.na +.nf +postconf(5), configuration parameters +syslogd(5), system logging +.SH "LICENSE" +.na +.nf +.ad +.fi +The Secure Mailer license must be distributed with this software. +.SH HISTORY +.ad +.fi +.ad +.fi +This service was introduced with Postfix version 3.4. +.SH "AUTHOR(S)" +.na +.nf +Wietse Venema +Google, Inc. +111 8th Avenue +New York, NY 10011, USA diff --git a/postfix/mantools/postlink b/postfix/mantools/postlink index 806cf1a1a..8cd48b2ea 100755 --- a/postfix/mantools/postlink +++ b/postfix/mantools/postlink @@ -811,6 +811,7 @@ while (<>) { s/[]*mas[-<\/bB>]*\n* *[]*ter[<\/bB>]*\(8\)/$&<\/a>/g; s/[]*pickup[<\/bB>]*\(8\)/$&<\/a>/g; s/[]*pipe[<\/bB>]*\(8\)/$&<\/a>/g; + s/[]*postlogd[<\/bB>]*\(8\)/$&<\/a>/g; s/[]*postscreen[<\/bB>]*\(8\)/$&<\/a>/g; s/[]*oqmgr[<\/bB>]*\(8\)/$&<\/a>/g; s/[]*\bqmgr[<\/bB>]*\(8\)/$&<\/a>/g; @@ -1116,6 +1117,11 @@ while (<>) { s;\bsmtputf8_autodetect_classes\b;$&;g; s;\benable_idna2003_compatibility\b;$&;g; + # Internal logging. + s;\bmail[-]*\n*[ ]*log_file\b;$&;g; + s;\bpostlog_service_name\b;$&;g; + s;\bpostlogd_watchdog_timeout\b;$&;g; + # Service-defined parameters... s;\bpolicy_time_limit\b;$&;g; diff --git a/postfix/proto/master b/postfix/proto/master index dd4041c4d..670b800a1 100644 --- a/postfix/proto/master +++ b/postfix/proto/master @@ -79,8 +79,8 @@ # of hard-coding loopback IP address information in master.cf # or in main.cf. # .IP \fBunix\fR -# The service listens on a UNIX-domain socket and is accessible -# for local clients only. +# The service listens on a UNIX-domain stream socket and is +# accessible for local clients only. # # The service name is a pathname relative to the Postfix # queue directory (pathname controlled with the \fBqueue_directory\fR @@ -88,7 +88,14 @@ # .sp # On Solaris 8 and earlier systems the \fBunix\fR type is # implemented with streams sockets. -# .IP \fBfifo\fR +# .IP \fBunix-dgram\fR +# The service listens on a UNIX-domain datagram socket and is +# accessible for local clients only. +# +# The service name is a pathname relative to the Postfix +# queue directory (pathname controlled with the \fBqueue_directory\fR +# configuration parameter in main.cf). +# .IP "\fBfifo\fR (obsolete)" # The service listens on a FIFO (named pipe) and is accessible # for local clients only. # @@ -96,9 +103,9 @@ # queue directory (pathname controlled with the \fBqueue_directory\fR # configuration parameter in main.cf). # .IP \fBpass\fR -# The service listens on a UNIX-domain socket, and is accessible -# to local clients only. It receives one open connection (file -# descriptor passing) per connection request. +# The service listens on a UNIX-domain stream socket, and is +# accessible to local clients only. It receives one open +# connection (file descriptor passing) per connection request. # # The service name is a pathname relative to the Postfix # queue directory (pathname controlled with the \fBqueue_directory\fR diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index 979f422c0..5c53add8e 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -15041,7 +15041,7 @@ cannot be set under 10s.

    one-letter suffix that specifies the time unit). Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).

    -

    This feature is available in Postfix 2.8.

    +

    This feature is available in Postfix 2.8 and later

    %PARAM postscreen_discard_ehlo_keywords $smtpd_discard_ehlo_keywords @@ -17526,3 +17526,38 @@ as needed.

    parameter. See there for details.

    This feature is available in Postfix 3.4 and later.

    + +%PARAM maillog_file + +

    The name of an optional logfile that is written by the Postfix +postlogd(8) service. A non-empty value disables logging to syslogd(8). +Specify "/dev/stdout" for logging to standard output. Stdout logging +requires that Postfix is started with "postfix start-fg".

    + +

    Note: Some Postfix non-daemon programs may still log information +to syslogd(8), before they have processed their configuration +parameters and command-line options.

    + +

    This feature is available in Postfix 3.4 and later.

    + +%PARAM postlog_service_name postlog + +

    The name of the postlogd(8) service entry in master.cf. +This service appends logfile records to the file specified +with the maillog_file parameter.

    + +

    This feature is available in Postfix 3.4 and later.

    + +%PARAM postlogd_watchdog_timeout 10s + +

    How much time a postlogd(8) process may take to process a request +before it is terminated by a built-in watchdog timer. This is a +safety mechanism that prevents postlogd(8) from becoming non-responsive +due to a bug in Postfix itself or in system software. This limit +cannot be set under 10s.

    + +

    Specify a non-zero time value (an integral value plus an optional +one-letter suffix that specifies the time unit). Time units: s +(seconds), m (minutes), h (hours), d (days), w (weeks).

    + +

    This feature is available in Postfix 3.4 and later.

    diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in index 5d809d0a2..21caa0d97 100644 --- a/postfix/src/global/Makefile.in +++ b/postfix/src/global/Makefile.in @@ -34,7 +34,7 @@ SRCS = abounce.c anvil_clnt.c been_here.c bounce.c bounce_log.c \ dict_memcache.c mail_version.c memcache_proto.c server_acl.c \ mkmap_fail.c haproxy_srvr.c dsn_filter.c dynamicmaps.c uxtext.c \ smtputf8.c mail_conf_over.c mail_parm_split.c midna_adomain.c \ - mail_addr_form.c quote_flags.c + mail_addr_form.c quote_flags.c maillog_client.c OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \ canon_addr.o cfg_parser.o cleanup_strerror.o cleanup_strflags.o \ clnt_stream.o conv_time.o db_common.o debug_peer.o debug_process.o \ @@ -70,7 +70,7 @@ OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \ dict_memcache.o mail_version.o memcache_proto.o server_acl.o \ mkmap_fail.o haproxy_srvr.o dsn_filter.o dynamicmaps.o uxtext.o \ smtputf8.o attr_override.o mail_parm_split.o midna_adomain.o \ - $(NON_PLUGIN_MAP_OBJ) mail_addr_form.o quote_flags.o + $(NON_PLUGIN_MAP_OBJ) mail_addr_form.o quote_flags.o maillog_client.o # MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf. # When hard-linking these maps, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ), # otherwise it sets the PLUGIN_* macros. @@ -103,7 +103,8 @@ HDRS = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \ addr_match_list.h smtp_reply_footer.h safe_ultostr.h \ verify_sender_addr.h dict_memcache.h memcache_proto.h server_acl.h \ haproxy_srvr.h dsn_filter.h dynamicmaps.h uxtext.h smtputf8.h \ - attr_override.h mail_parm_split.h midna_adomain.h mail_addr_form.h + attr_override.h mail_parm_split.h midna_adomain.h mail_addr_form.h \ + maillog_client.h TESTSRC = rec2stream.c stream2rec.c recdump.c DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE) CFLAGS = $(DEBUG) $(OPT) $(DEFS) @@ -1909,6 +1910,26 @@ mail_version.o: ../../include/vbuf.h mail_version.o: ../../include/vstring.h mail_version.o: mail_version.c mail_version.o: mail_version.h +maillog_client.o: ../../include/attr.h +maillog_client.o: ../../include/check_arg.h +maillog_client.o: ../../include/htable.h +maillog_client.o: ../../include/iostuff.h +maillog_client.o: ../../include/logwriter.h +maillog_client.o: ../../include/msg.h +maillog_client.o: ../../include/msg_logger.h +maillog_client.o: ../../include/msg_syslog.h +maillog_client.o: ../../include/mymalloc.h +maillog_client.o: ../../include/nvtable.h +maillog_client.o: ../../include/safe.h +maillog_client.o: ../../include/stringops.h +maillog_client.o: ../../include/sys_defs.h +maillog_client.o: ../../include/vbuf.h +maillog_client.o: ../../include/vstream.h +maillog_client.o: ../../include/vstring.h +maillog_client.o: mail_params.h +maillog_client.o: mail_proto.h +maillog_client.o: maillog_client.c +maillog_client.o: maillog_client.h maps.o: ../../include/argv.h maps.o: ../../include/check_arg.h maps.o: ../../include/dict.h diff --git a/postfix/src/global/mail_params.c b/postfix/src/global/mail_params.c index 203e52fea..a504cce05 100644 --- a/postfix/src/global/mail_params.c +++ b/postfix/src/global/mail_params.c @@ -145,6 +145,9 @@ /* int warn_compat_break_relay_domains; /* int warn_compat_break_flush_domains; /* int warn_compat_break_mynetworks_style; +/* +/* char *var_maillog_file; +/* char *var_postlog_service; /* DESCRIPTION /* This module (actually the associated include file) defines /* the names and defaults of all mail configuration parameters. @@ -348,6 +351,9 @@ int var_compat_level; char *var_drop_hdrs; bool var_enable_orcpt; +char *var_maillog_file; +char *var_postlog_service; + const char null_format_string[1] = ""; /* @@ -670,6 +676,8 @@ void mail_params_init() /* multi_instance_wrapper may have dependencies but not dependents. */ VAR_MULTI_GROUP, DEF_MULTI_GROUP, &var_multi_group, 0, 0, VAR_MULTI_NAME, DEF_MULTI_NAME, &var_multi_name, 0, 0, + VAR_MAILLOG_FILE, DEF_MAILLOG_FILE, &var_maillog_file, 0, 0, + VAR_POSTLOG_SERVICE, DEF_POSTLOG_SERVICE, &var_postlog_service, 1, 0, 0, }; static const CONFIG_BOOL_TABLE first_bool_defaults[] = { @@ -822,7 +830,7 @@ void mail_params_init() */ get_mail_conf_str_table(first_str_defaults); - if (!msg_syslog_facility(var_syslog_facility)) + if (!msg_syslog_set_facility(var_syslog_facility)) msg_fatal("file %s/%s: parameter %s: unrecognized value: %s", var_config_dir, MAIN_CONF_FILE, VAR_SYSLOG_FACILITY, var_syslog_facility); diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 2edec94fb..05b7fc283 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -2532,7 +2532,9 @@ extern int var_fflush_refresh; * and what Postfix exports to the external world. */ #define VAR_IMPORT_ENVIRON "import_environment" -#define DEF_IMPORT_ENVIRON "MAIL_CONFIG MAIL_DEBUG MAIL_LOGTAG TZ XAUTHORITY DISPLAY LANG=C" +#define DEF_IMPORT_ENVIRON "MAIL_CONFIG MAIL_DEBUG MAIL_LOGTAG " \ + "TZ XAUTHORITY DISPLAY LANG=C " \ + "POSTLOG_SERVICE POSTLOG_HOSTNAME" extern char *var_import_environ; #define VAR_EXPORT_ENVIRON "export_environment" @@ -4171,6 +4173,21 @@ extern int var_idna2003_compat; #define DEF_DNS_NCACHE_TTL_FIX 0 extern bool var_dns_ncache_ttl_fix; + /* + * Logging. As systems evolve over time, logging becomes more challenging. + */ +#define VAR_MAILLOG_FILE "maillog_file" +#define DEF_MAILLOG_FILE "" +extern char *var_maillog_file; + +#define VAR_POSTLOG_SERVICE "postlog_service_name" +#define DEF_POSTLOG_SERVICE MAIL_SERVICE_POSTLOG +extern char *var_postlog_service; + +#define VAR_POSTLOGD_WATCHDOG "postlogd_watchdog_timeout" +#define DEF_POSTLOGD_WATCHDOG "10s" +extern int var_postlogd_watchdog; + /* LICENSE /* .ad /* .fi diff --git a/postfix/src/global/mail_proto.h b/postfix/src/global/mail_proto.h index 9fc9ab68e..3428374e3 100644 --- a/postfix/src/global/mail_proto.h +++ b/postfix/src/global/mail_proto.h @@ -60,6 +60,7 @@ #define MAIL_SERVICE_SCACHE "scache" #define MAIL_SERVICE_DNSBLOG "dnsblog" #define MAIL_SERVICE_TLSPROXY "tlsproxy" +#define MAIL_SERVICE_POSTLOG "postlog" /* * Mail source classes. Used to specify policy decisions for content diff --git a/postfix/src/global/mail_task.c b/postfix/src/global/mail_task.c index b1df611d4..543130a6e 100644 --- a/postfix/src/global/mail_task.c +++ b/postfix/src/global/mail_task.c @@ -15,8 +15,10 @@ /* are easier to recognize. The mail system name is specified /* with the "syslog_name" configuration parameter. /* -/* The result is volatile. Make a copy of the result if it is -/* to be used for any appreciable amount of time. +/* The result is overwritten with each call. +/* +/* A null argv0 argument requests that the current +/* result is returned. /* LICENSE /* .ad /* .fi @@ -26,6 +28,11 @@ /* 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. */ @@ -52,15 +59,17 @@ const char *mail_task(const char *argv0) const char *slash; const char *tag; - if (canon_name == 0) - canon_name = vstring_alloc(10); - if ((slash = strrchr(argv0, '/')) != 0 && slash[1]) - argv0 = slash + 1; - /* Setenv()-ed from main.cf, or inherited from master. */ - if ((tag = safe_getenv(CONF_ENV_LOGTAG)) == 0) - /* Check main.cf settings directly, in case set-gid. */ - tag = var_syslog_name ? var_syslog_name : - mail_conf_eval(DEF_SYSLOG_NAME); - vstring_sprintf(canon_name, "%s/%s", tag, argv0); + if (argv0) { + if (canon_name == 0) + canon_name = vstring_alloc(10); + if ((slash = strrchr(argv0, '/')) != 0 && slash[1]) + argv0 = slash + 1; + /* Setenv()-ed from main.cf, or inherited from master. */ + if ((tag = safe_getenv(CONF_ENV_LOGTAG)) == 0) + /* Check main.cf settings directly, in case set-gid. */ + tag = var_syslog_name ? var_syslog_name : + mail_conf_eval(DEF_SYSLOG_NAME); + vstring_sprintf(canon_name, "%s/%s", tag, argv0); + } return (vstring_str(canon_name)); } diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index c20785201..f4675fa95 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20190127" +#define MAIL_RELEASE_DATE "20190129" #define MAIL_VERSION_NUMBER "3.4" #ifdef SNAPSHOT diff --git a/postfix/src/global/maillog_client.c b/postfix/src/global/maillog_client.c new file mode 100644 index 000000000..ab8c91503 --- /dev/null +++ b/postfix/src/global/maillog_client.c @@ -0,0 +1,278 @@ +/*++ +/* NAME +/* maillog_client 3 +/* SUMMARY +/* choose between syslog client and postlog client +/* SYNOPSIS +/* #include +/* +/* int maillog_client_init( +/* const char *progname, +/* int flags) +/* DESCRIPTION +/* maillog_client_init() chooses between logging to the syslog +/* service or to the internal postlog service. +/* +/* maillog_client_init() may be called before configuration +/* parameters are initialized. During this time, logging is +/* controlled by the presence or absence of POSTLOG_SERVICE +/* in the process environment (this is ignored if a program +/* runs with set-uid or set-gid permissions). +/* +/* maillog_client_init() may also be called after configuration +/* parameters are initialized. During this time, logging is +/* controlled by the "maillog_file" parameter value. +/* +/* Arguments: +/* .IP progname +/* The program name that will be prepended to logfile records. +/* .IP flags +/* Specify one of the following: +/* .RS +/* .IP MAILLOG_CLIENT_FLAG_NONE +/* No special processing. +/* .IP MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK +/* Try to fall back to writing the "maillog_file" directly, +/* if logging to the internal postlog service is enabled, but +/* the postlog service is unavailable. If the fallback fails, +/* die with a fatal error. +/* .RE +/* ENVIRONMENT +/* .ad +/* .fi +/* When logging to the internal postlog service is enabled, +/* each process exports the following information, to help +/* initialize the logging in a child process, before the child +/* has initialized its configuration parameters. +/* .IP POSTLOG_SERVICE +/* The pathname of the public postlog service endpoint, usually +/* "$queue_directory/public/$postlog_service_name". +/* .IP POSTLOG_HOSTNAME +/* The hostname to prepend to information that is sent to the +/* internal postlog logging service, usually "$myhostname". +/* CONFIGURATION PARAMETERS +/* .ad +/* .fi +/* .IP "maillog_file (empty)" +/* The name of an optional logfile. If the value is empty, or +/* unitialized and the process environment does not specify +/* POSTLOG_SERVICE, the program will log to the syslog service +/* instead. +/* .IP "myhostname (default: see postconf -d output)" +/* The internet hostname of this mail system. +/* .IP "postlog_service_name (postlog)" +/* The name of the internal postlog logging service. +/* SEE ALSO +/* msg_syslog(3) syslog client +/* msg_logger(3) internal logger +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this +/* software. +/* AUTHOR(S) +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/*--*/ + + /* + * System library. + */ +#include + + /* + * Utility library. + */ +#include +#include +#include +#include +#include + + /* + * Global library. + */ +#include +#include +#include +#include + + /* + * Using logging to debug logging is painful. + */ +#define MAILLOG_CLIENT_DEBUG 0 + + /* + * Application-specific. + */ +static int maillog_client_flags; + +#define POSTLOG_SERVICE_ENV "POSTLOG_SERVICE" +#define POSTLOG_HOSTNAME_ENV "POSTLOG_HOSTNAME" + +/* maillog_client_logwriter_fallback - fall back to logfile writer or bust */ + +static void maillog_client_logwriter_fallback(const char *text) +{ + static int fallback_guard = 0; + + /* + * Guard against recursive calls. + * + * If an error happened before the maillog_file parameter was initialized, + * or if maillog_file logging is disabled, then we cannot fall back to a + * logfile. All we can do is to hope that stderr logging will bring out + * the bad news. + */ + if (fallback_guard == 0 && var_maillog_file && *var_maillog_file + && logwriter_one_shot(var_maillog_file, text, strlen(text)) < 0) { + fallback_guard = 1; + msg_fatal("logfile '%s' write error: %m", var_maillog_file); + } +} + +/* maillog_client_init - set up syslog or internal log client */ + +void maillog_client_init(const char *progname, int flags) +{ + char *import_service_path; + char *import_hostname; + + /* + * Crucially, only one logger mode can be in effect at any time, + * otherwise postlogd(8) may go into a loop. + */ + enum { + MAILLOG_CLIENT_MODE_SYSLOG, MAILLOG_CLIENT_MODE_POSTLOG, + } logger_mode; + + /* + * Security: this code may run before the import_environment setting has + * taken effect. It has to guard against privilege escalation attacks on + * setgid programs, using malicious environment settings. + * + * Import the postlog service name and hostname from the environment. + * + * - These will be used and kept if the process has not yet initialized its + * configuration parameters. + * + * - These will be set or updated if the configuration enables postlog + * logging. + * + * - These will be removed if the configuration does not enable postlog + * logging. + */ + if ((import_service_path = safe_getenv(POSTLOG_SERVICE_ENV)) != 0 + && *import_service_path == 0) + import_service_path = 0; + if ((import_hostname = safe_getenv(POSTLOG_HOSTNAME_ENV)) != 0 + && *import_hostname == 0) + import_hostname = 0; + +#if MAILLOG_CLIENT_DEBUG +#define STRING_OR_NULL(s) ((s) ? (s) : "(null)") + msg_syslog_init(progname, LOG_PID, LOG_FACILITY); + msg_info("import_service_path=%s", STRING_OR_NULL(import_service_path)); + msg_info("import_hostname=%s", STRING_OR_NULL(import_hostname)); +#endif + + /* + * Before configuration parameters are initialized, the logging mode is + * controlled by the presence or absence of POSTLOG_SERVICE in the + * process environment. After configuration parameters are initialized, + * the logging mode is controlled by the "maillog_file" parameter value. + * + * The configured mode may change after a process is started. The + * postlogd(8) server will proxy logging to syslogd where needed. + */ + if (var_maillog_file ? *var_maillog_file == 0 : import_service_path == 0) { + logger_mode = MAILLOG_CLIENT_MODE_SYSLOG; + } else { + /* var_maillog_file ? *var_maillog_file : import_service_path != 0 */ + logger_mode = MAILLOG_CLIENT_MODE_POSTLOG; + } + + /* + * Postlog logging is enabled. Update the 'progname' as that may have + * changed since an earlier call, and update the environment settings if + * they differ from configuration settings. This blends two code paths, + * one code path where configuration parameters are initialized (the + * preferred path), and one code path that uses imports from environment. + */ + if (logger_mode == MAILLOG_CLIENT_MODE_POSTLOG) { + char *myhostname; + char *service_path; + + if (var_myhostname && *var_myhostname) { + myhostname = var_myhostname; + } else if ((myhostname = import_hostname) == 0) { + myhostname = "amnesiac"; + } +#if MAILLOG_CLIENT_DEBUG + msg_info("myhostname=%s", STRING_OR_NULL(myhostname)); +#endif + if (var_postlog_service) { + service_path = concatenate(var_queue_dir, "/", MAIL_CLASS_PUBLIC, + "/", var_postlog_service, (char *) 0); + } else { + service_path = import_service_path; + } + maillog_client_flags = flags; + msg_logger_init(progname, myhostname, service_path, + (flags & MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK) ? + maillog_client_logwriter_fallback : + (MSG_LOGGER_FALLBACK_FN) 0); + + /* + * Export or update the exported postlog service pathname and the + * hostname, so that a child process can bootstrap postlog logging + * before it has processed main.cf and command-line options. + */ + if (import_service_path == 0 + || strcmp(service_path, import_service_path) != 0) { +#if MAILLOG_CLIENT_DEBUG + msg_info("export %s=%s", POSTLOG_SERVICE_ENV, service_path); +#endif + if (setenv(POSTLOG_SERVICE_ENV, service_path, 1) < 0) + msg_fatal("setenv: %m"); + } + if (import_hostname == 0 || strcmp(myhostname, import_hostname) != 0) { +#if MAILLOG_CLIENT_DEBUG + msg_info("export %s=%s", POSTLOG_HOSTNAME_ENV, myhostname); +#endif + if (setenv(POSTLOG_HOSTNAME_ENV, myhostname, 1) < 0) + msg_fatal("setenv: %m"); + } + if (service_path != import_service_path) + myfree(service_path); + } + + /* + * Postlog logging is disabled. Silence the msg_logger client, and remove + * the environment settings that bootstrap postlog logging in a child + * process. + */ + else { + msg_logger_control(CA_MSG_LOGGER_CTL_DISABLE, CA_MSG_LOGGER_CTL_END); + if ((import_service_path && unsetenv(POSTLOG_SERVICE_ENV)) + || (import_hostname && unsetenv(POSTLOG_HOSTNAME_ENV))) + msg_fatal("unsetenv: %m"); + } + + /* + * Syslog logging is enabled. Update the 'progname' as that may have + * changed since an earlier call. + */ + if (logger_mode == MAILLOG_CLIENT_MODE_SYSLOG) { + msg_syslog_init(progname, LOG_PID, LOG_FACILITY); + } + + /* + * Syslog logging is disabled, silence the syslog client. + */ + else { + msg_syslog_disable(); + } +} diff --git a/postfix/src/global/maillog_client.h b/postfix/src/global/maillog_client.h new file mode 100644 index 000000000..71601873b --- /dev/null +++ b/postfix/src/global/maillog_client.h @@ -0,0 +1,33 @@ +#ifndef _MAILLOG_CLIENT_H_INCLUDED_ +#define _MAILLOG_CLIENT_H_INCLUDED_ + +/*++ +/* NAME +/* maillog_client 3h +/* SUMMARY +/* choose between syslog client and postlog client +/* SYNOPSIS +/* #include +/* DESCRIPTION +/* .nf + + /* + * External interface. + */ +#define MAILLOG_CLIENT_FLAG_NONE (0) +#define MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK (1<<0) + +extern void maillog_client_init(const char *, int); + +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/*--*/ + +#endif diff --git a/postfix/src/master/Makefile.in b/postfix/src/master/Makefile.in index 9263920c2..1dd334d86 100644 --- a/postfix/src/master/Makefile.in +++ b/postfix/src/master/Makefile.in @@ -3,13 +3,13 @@ SRCS = master.c master_conf.c master_ent.c master_sig.c master_avail.c \ master_spawn.c master_service.c master_status.c master_listen.c \ master_proto.c single_server.c multi_server.c master_vars.c \ master_wakeup.c master_flow.c master_watch.c mail_flow.c \ - master_monitor.c + master_monitor.c dgram_server.c OBJS = master.o master_conf.o master_ent.o master_sig.o master_avail.o \ master_spawn.o master_service.o master_status.o master_listen.o \ master_vars.o master_wakeup.o master_watch.o master_flow.o \ master_monitor.o LIB_OBJ = single_server.o multi_server.o trigger_server.o master_proto.o \ - mail_flow.o event_server.o + mail_flow.o event_server.o dgram_server.o HDRS = mail_server.h master_proto.h mail_flow.h INT_HDR = master.h DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE) @@ -87,6 +87,47 @@ depend: $(MAKES) @$(EXPORT) make -f Makefile.in Makefile 1>&2 # do not edit below this line - it is generated by 'make depend' +dgram_server.o: ../../include/argv.h +dgram_server.o: ../../include/attr.h +dgram_server.o: ../../include/bounce.h +dgram_server.o: ../../include/check_arg.h +dgram_server.o: ../../include/chroot_uid.h +dgram_server.o: ../../include/debug_process.h +dgram_server.o: ../../include/deliver_request.h +dgram_server.o: ../../include/dict.h +dgram_server.o: ../../include/dsn.h +dgram_server.o: ../../include/dsn_buf.h +dgram_server.o: ../../include/events.h +dgram_server.o: ../../include/htable.h +dgram_server.o: ../../include/iostuff.h +dgram_server.o: ../../include/listen.h +dgram_server.o: ../../include/mail_conf.h +dgram_server.o: ../../include/mail_dict.h +dgram_server.o: ../../include/mail_params.h +dgram_server.o: ../../include/mail_task.h +dgram_server.o: ../../include/mail_version.h +dgram_server.o: ../../include/maillog_client.h +dgram_server.o: ../../include/msg.h +dgram_server.o: ../../include/msg_stats.h +dgram_server.o: ../../include/msg_vstream.h +dgram_server.o: ../../include/myflock.h +dgram_server.o: ../../include/mymalloc.h +dgram_server.o: ../../include/nvtable.h +dgram_server.o: ../../include/recipient_list.h +dgram_server.o: ../../include/resolve_local.h +dgram_server.o: ../../include/safe_open.h +dgram_server.o: ../../include/sane_accept.h +dgram_server.o: ../../include/split_at.h +dgram_server.o: ../../include/stringops.h +dgram_server.o: ../../include/sys_defs.h +dgram_server.o: ../../include/vbuf.h +dgram_server.o: ../../include/vstream.h +dgram_server.o: ../../include/vstring.h +dgram_server.o: ../../include/watchdog.h +dgram_server.o: dgram_server.c +dgram_server.o: mail_flow.h +dgram_server.o: mail_server.h +dgram_server.o: master_proto.h event_server.o: ../../include/argv.h event_server.o: ../../include/attr.h event_server.o: ../../include/bounce.h @@ -106,9 +147,9 @@ event_server.o: ../../include/mail_dict.h event_server.o: ../../include/mail_params.h event_server.o: ../../include/mail_task.h event_server.o: ../../include/mail_version.h +event_server.o: ../../include/maillog_client.h event_server.o: ../../include/msg.h event_server.o: ../../include/msg_stats.h -event_server.o: ../../include/msg_syslog.h event_server.o: ../../include/msg_vstream.h event_server.o: ../../include/myflock.h event_server.o: ../../include/mymalloc.h @@ -148,8 +189,8 @@ master.o: ../../include/mail_params.h master.o: ../../include/mail_parm_split.h master.o: ../../include/mail_task.h master.o: ../../include/mail_version.h +master.o: ../../include/maillog_client.h master.o: ../../include/msg.h -master.o: ../../include/msg_syslog.h master.o: ../../include/myflock.h master.o: ../../include/mymalloc.h master.o: ../../include/open_lock.h @@ -327,9 +368,9 @@ multi_server.o: ../../include/mail_dict.h multi_server.o: ../../include/mail_params.h multi_server.o: ../../include/mail_task.h multi_server.o: ../../include/mail_version.h +multi_server.o: ../../include/maillog_client.h multi_server.o: ../../include/msg.h multi_server.o: ../../include/msg_stats.h -multi_server.o: ../../include/msg_syslog.h multi_server.o: ../../include/msg_vstream.h multi_server.o: ../../include/myflock.h multi_server.o: ../../include/mymalloc.h @@ -369,9 +410,9 @@ single_server.o: ../../include/mail_dict.h single_server.o: ../../include/mail_params.h single_server.o: ../../include/mail_task.h single_server.o: ../../include/mail_version.h +single_server.o: ../../include/maillog_client.h single_server.o: ../../include/msg.h single_server.o: ../../include/msg_stats.h -single_server.o: ../../include/msg_syslog.h single_server.o: ../../include/msg_vstream.h single_server.o: ../../include/myflock.h single_server.o: ../../include/mymalloc.h @@ -411,9 +452,9 @@ trigger_server.o: ../../include/mail_dict.h trigger_server.o: ../../include/mail_params.h trigger_server.o: ../../include/mail_task.h trigger_server.o: ../../include/mail_version.h +trigger_server.o: ../../include/maillog_client.h trigger_server.o: ../../include/msg.h trigger_server.o: ../../include/msg_stats.h -trigger_server.o: ../../include/msg_syslog.h trigger_server.o: ../../include/msg_vstream.h trigger_server.o: ../../include/myflock.h trigger_server.o: ../../include/mymalloc.h diff --git a/postfix/src/master/dgram_server.c b/postfix/src/master/dgram_server.c new file mode 100644 index 000000000..c9b3ea63f --- /dev/null +++ b/postfix/src/master/dgram_server.c @@ -0,0 +1,663 @@ +/*++ +/* NAME +/* dgram_server 3 +/* SUMMARY +/* skeleton datagram server subsystem +/* SYNOPSIS +/* #include +/* +/* NORETURN dgram_server_main(argc, argv, service, key, value, ...) +/* int argc; +/* char **argv; +/* void (*service)(char *buf, int len, char *service_name, char **argv); +/* int key; +/* DESCRIPTION +/* This module implements a skeleton for mail subsystem programs +/* that wake up on client request and perform some activity +/* without further client interaction. This module supports +/* local IPC via a UNIX-domain datagram socket. The resulting +/* program expects to be run from the \fBmaster\fR process. +/* +/* dgram_server_main() is the skeleton entry point. It should +/* be called from the application main program. The skeleton +/* does the generic command-line options processing, initialization +/* of configurable parameters, and receiving datagrams. The +/* skeleton never returns. +/* +/* Arguments: +/* .IP "void (*service)(char *buf, int len, char *service_name, char **argv)" +/* A pointer to a function that is called by the skeleton each +/* time a client sends a datagram to the program's service +/* port. The function is run after the program has irrevocably +/* dropped its privileges. The buffer argument specifies the +/* data read from the datagram port; this data corresponds to +/* request. The len argument specifies how much client data +/* is available. The maximal size of the buffer is specified +/* via the DGRAM_BUF_SIZE manifest constant. The service name +/* argument corresponds to the service name in the master.cf +/* file. The argv argument specifies command-line arguments +/* left over after options processing. +/* .PP +/* Optional arguments are specified as a null-terminated list +/* with macros that have zero or more arguments: +/* .IP "CA_MAIL_SERVER_INT_TABLE(CONFIG_INT_TABLE *)" +/* A table with configurable parameters, to be loaded from the +/* global Postfix configuration file. Tables are loaded in the +/* order as specified, and multiple instances of the same type +/* are allowed. +/* .IP "CA_MAIL_SERVER_LONG_TABLE(CONFIG_LONG_TABLE *)" +/* A table with configurable parameters, to be loaded from the +/* global Postfix configuration file. Tables are loaded in the +/* order as specified, and multiple instances of the same type +/* are allowed. +/* .IP "CA_MAIL_SERVER_STR_TABLE(CONFIG_STR_TABLE *)" +/* A table with configurable parameters, to be loaded from the +/* global Postfix configuration file. Tables are loaded in the +/* order as specified, and multiple instances of the same type +/* are allowed. +/* .IP "CA_MAIL_SERVER_BOOL_TABLE(CONFIG_BOOL_TABLE *)" +/* A table with configurable parameters, to be loaded from the +/* global Postfix configuration file. Tables are loaded in the +/* order as specified, and multiple instances of the same type +/* are allowed. +/* .IP "CA_MAIL_SERVER_TIME_TABLE(CONFIG_TIME_TABLE *)" +/* A table with configurable parameters, to be loaded from the +/* global Postfix configuration file. Tables are loaded in the +/* order as specified, and multiple instances of the same type +/* are allowed. +/* .IP "CA_MAIL_SERVER_RAW_TABLE(CONFIG_RAW_TABLE *)" +/* A table with configurable parameters, to be loaded from the +/* global Postfix configuration file. Tables are loaded in the +/* order as specified, and multiple instances of the same type +/* are allowed. Raw parameters are not subjected to $name +/* evaluation. +/* .IP "CA_MAIL_SERVER_NINT_TABLE(CONFIG_NINT_TABLE *)" +/* A table with configurable parameters, to be loaded from the +/* global Postfix configuration file. Tables are loaded in the +/* order as specified, and multiple instances of the same type +/* are allowed. +/* .IP "CA_MAIL_SERVER_NBOOL_TABLE(CONFIG_NBOOL_TABLE *)" +/* A table with configurable parameters, to be loaded from the +/* global Postfix configuration file. Tables are loaded in the +/* order as specified, and multiple instances of the same type +/* are allowed. +/* .IP "CA_MAIL_SERVER_PRE_INIT(void *(char *service_name, char **argv))" +/* A pointer to a function that is called once +/* by the skeleton after it has read the global configuration file +/* and after it has processed command-line arguments, but before +/* the skeleton has optionally relinquished the process privileges. +/* .sp +/* Only the last instance of this parameter type is remembered. +/* .IP "CA_MAIL_SERVER_POST_INIT(void *(char *service_name, char **argv))" +/* A pointer to a function that is called once +/* by the skeleton after it has optionally relinquished the process +/* privileges, but before servicing client connection requests. +/* .sp +/* Only the last instance of this parameter type is remembered. +/* .IP "CA_MAIL_SERVER_LOOP(int *(char *service_name, char **argv))" +/* A pointer to function that is executed from +/* within the event loop, whenever an I/O or timer event has happened, +/* or whenever nothing has happened for a specified amount of time. +/* The result value of the function specifies how long to wait until +/* the next event. Specify -1 to wait for "as long as it takes". +/* .sp +/* Only the last instance of this parameter type is remembered. +/* .IP "CA_MAIL_SERVER_EXIT(void *(char *service_name, char **argv))" +/* A pointer to function that is executed immediately before normal +/* process termination. +/* .sp +/* Only the last instance of this parameter type is remembered. +/* .IP "CA_MAIL_SERVER_PRE_ACCEPT(void *(char *service_name, char **argv))" +/* Function to be executed prior to accepting a new request. +/* .sp +/* Only the last instance of this parameter type is remembered. +/* .IP "CA_MAIL_SERVER_IN_FLOW_DELAY(none)" +/* Pause $in_flow_delay seconds when no "mail flow control token" +/* is available. A token is consumed for each connection request. +/* .IP CA_MAIL_SERVER_SOLITARY +/* This service must be configured with process limit of 1. +/* .IP CA_MAIL_SERVER_UNLIMITED +/* This service must be configured with process limit of 0. +/* .IP CA_MAIL_SERVER_PRIVILEGED +/* This service must be configured as privileged. +/* .IP "CA_MAIL_SERVER_WATCHDOG(int *)" +/* Override the default 1000s watchdog timeout. The value is +/* used after command-line and main.cf file processing. +/* .IP "CA_MAIL_SERVER_BOUNCE_INIT(const char *, const char **)" +/* Initialize the DSN filter for the bounce/defer service +/* clients with the specified map source and map names. +/* .PP +/* The var_use_limit variable limits the number of clients that +/* a server can service before it commits suicide. +/* This value is taken from the global \fBmain.cf\fR configuration +/* file. Setting \fBvar_use_limit\fR to zero disables the client limit. +/* +/* The var_idle_limit variable limits the time that a service +/* receives no client connection requests before it commits suicide. +/* This value is taken from the global \fBmain.cf\fR configuration +/* file. Setting \fBvar_use_limit\fR to zero disables the idle limit. +/* DIAGNOSTICS +/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* SEE ALSO +/* master(8), master process +/* syslogd(8) system logging +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/*--*/ + +/* System library. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef STRCASECMP_IN_STRINGS_H +#include +#endif +#include + +/* Utility library. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Global library. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Process manager. */ + +#include "master_proto.h" + +/* Application-specific */ + +#include "mail_server.h" + + /* + * Global state. + */ +static int use_count; + +static DGRAM_SERVER_FN dgram_server_service; +static char *dgram_server_name; +static char **dgram_server_argv; +static void (*dgram_server_accept) (int, void *); +static void (*dgram_server_onexit) (char *, char **); +static void (*dgram_server_pre_accept) (char *, char **); +static VSTREAM *dgram_server_lock; +static int dgram_server_in_flow_delay; +static unsigned dgram_server_generation; +static int dgram_server_watchdog = 1000; + +/* dgram_server_exit - normal termination */ + +static NORETURN dgram_server_exit(void) +{ + if (dgram_server_onexit) + dgram_server_onexit(dgram_server_name, dgram_server_argv); + exit(0); +} + +/* dgram_server_abort - terminate after abnormal master exit */ + +static void dgram_server_abort(int unused_event, void *unused_context) +{ + if (msg_verbose) + msg_info("master disconnect -- exiting"); + dgram_server_exit(); +} + +/* dgram_server_timeout - idle time exceeded */ + +static void dgram_server_timeout(int unused_event, void *unused_context) +{ + if (msg_verbose) + msg_info("idle timeout -- exiting"); + dgram_server_exit(); +} + +/* dgram_server_wakeup - wake up application */ + +static void dgram_server_wakeup(int fd) +{ + char buf[DGRAM_BUF_SIZE]; + ssize_t len; + + /* + * Commit suicide when the master process disconnected from us, after + * handling the client request. + */ + if (master_notify(var_pid, dgram_server_generation, MASTER_STAT_TAKEN) < 0) + /* void */ ; + if (dgram_server_in_flow_delay && mail_flow_get(1) < 0) + doze(var_in_flow_delay * 1000000); + if ((len = recv(fd, buf, sizeof(buf), 0)) >= 0) + dgram_server_service(buf, len, dgram_server_name, dgram_server_argv); + if (master_notify(var_pid, dgram_server_generation, MASTER_STAT_AVAIL) < 0) + dgram_server_abort(EVENT_NULL_TYPE, EVENT_NULL_CONTEXT); + if (var_idle_limit > 0) + event_request_timer(dgram_server_timeout, (void *) 0, var_idle_limit); + /* Avoid integer wrap-around in a persistent process. */ + if (use_count < INT_MAX) + use_count++; +} + +/* dgram_server_accept_unix - handle UNIX-domain socket event */ + +static void dgram_server_accept_unix(int unused_event, void *context) +{ + const char *myname = "dgram_server_accept"; + int listen_fd = CAST_ANY_PTR_TO_INT(context); + + if (dgram_server_lock != 0 + && myflock(vstream_fileno(dgram_server_lock), INTERNAL_LOCK, + MYFLOCK_OP_NONE) < 0) + msg_fatal("select unlock: %m"); + + if (msg_verbose) + msg_info("%s: request arrived", myname); + + /* + * Read whatever the other side wrote. The socket is non-blocking so we + * won't get stuck when multiple processes wake up. + */ + if (dgram_server_pre_accept) + dgram_server_pre_accept(dgram_server_name, dgram_server_argv); + dgram_server_wakeup(listen_fd); +} + +/* dgram_server_main - the real main program */ + +NORETURN dgram_server_main(int argc, char **argv, DGRAM_SERVER_FN service,...) +{ + const char *myname = "dgram_server_main"; + char *root_dir = 0; + char *user_name = 0; + int debug_me = 0; + int daemon_mode = 1; + char *service_name = basename(argv[0]); + int delay; + int c; + int socket_count = 1; + int fd; + va_list ap; + MAIL_SERVER_INIT_FN pre_init = 0; + MAIL_SERVER_INIT_FN post_init = 0; + MAIL_SERVER_LOOP_FN loop = 0; + int key; + char *transport = 0; + char *lock_path; + VSTRING *why; + int alone = 0; + int zerolimit = 0; + WATCHDOG *watchdog; + char *oname_val; + char *oname; + char *oval; + const char *err; + char *generation; + int msg_vstream_needed = 0; + const char *dsn_filter_title; + const char **dsn_filter_maps; + + /* + * Process environment options as early as we can. + */ + if (getenv(CONF_ENV_VERB)) + msg_verbose = 1; + if (getenv(CONF_ENV_DEBUG)) + debug_me = 1; + + /* + * Don't die when a process goes away unexpectedly. + */ + signal(SIGPIPE, SIG_IGN); + + /* + * Don't die for frivolous reasons. + */ +#ifdef SIGXFSZ + signal(SIGXFSZ, SIG_IGN); +#endif + + /* + * May need this every now and then. + */ + var_procname = mystrdup(basename(argv[0])); + set_mail_conf_str(VAR_PROCNAME, var_procname); + + /* + * Initialize logging and exit handler. Do the syslog first, so that its + * initialization completes before we enter the optional chroot jail. + */ + maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE); + if (msg_verbose) + msg_info("daemon started"); + + /* + * Check the Postfix library version as soon as we enable logging. + */ + MAIL_VERSION_CHECK; + + /* + * Initialize from the configuration file. Allow command-line options to + * override compiled-in defaults or configured parameter values. + */ + mail_conf_suck(); + + /* + * After database open error, continue execution with reduced + * functionality. + */ + dict_allow_surrogate = 1; + + /* + * Pick up policy settings from master process. Shut up error messages to + * stderr, because no-one is going to see them. + */ + opterr = 0; + while ((c = GETOPT(argc, argv, "cdDi:lm:n:o:s:t:uvVz")) > 0) { + switch (c) { + case 'c': + root_dir = "setme"; + break; + case 'd': + daemon_mode = 0; + break; + case 'D': + debug_me = 1; + break; + case 'i': + mail_conf_update(VAR_MAX_IDLE, optarg); + break; + case 'l': + alone = 1; + break; + case 'm': + mail_conf_update(VAR_MAX_USE, optarg); + break; + case 'n': + service_name = optarg; + break; + case 'o': + oname_val = mystrdup(optarg); + if ((err = split_nameval(oname_val, &oname, &oval)) != 0) + msg_fatal("invalid \"-o %s\" option value: %s", optarg, err); + mail_conf_update(oname, oval); + myfree(oname_val); + break; + case 's': + if ((socket_count = atoi(optarg)) <= 0) + msg_fatal("invalid socket_count: %s", optarg); + break; + case 't': + transport = optarg; + break; + case 'u': + user_name = "setme"; + break; + case 'v': + msg_verbose++; + break; + case 'V': + if (++msg_vstream_needed == 1) + msg_vstream_init(mail_task(var_procname), VSTREAM_ERR); + break; + case 'z': + zerolimit = 1; + break; + default: + msg_fatal("invalid option: %c", optopt); + break; + } + } + set_mail_conf_str(VAR_SERVNAME, service_name); + + /* + * Initialize generic parameters and re-initialize logging in case of a + * non-default program name or logging destination. + */ + mail_params_init(); + maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE); + + /* + * Register higher-level dictionaries and initialize the support for + * dynamically-loaded dictionarles. + */ + mail_dict_init(); + + /* + * If not connected to stdin, stdin must not be a terminal. + */ + if (daemon_mode && isatty(STDIN_FILENO)) { + msg_vstream_init(var_procname, VSTREAM_ERR); + msg_fatal("do not run this command by hand"); + } + + /* + * Application-specific initialization. + */ + va_start(ap, service); + while ((key = va_arg(ap, int)) != 0) { + switch (key) { + case MAIL_SERVER_INT_TABLE: + get_mail_conf_int_table(va_arg(ap, CONFIG_INT_TABLE *)); + break; + case MAIL_SERVER_LONG_TABLE: + get_mail_conf_long_table(va_arg(ap, CONFIG_LONG_TABLE *)); + break; + case MAIL_SERVER_STR_TABLE: + get_mail_conf_str_table(va_arg(ap, CONFIG_STR_TABLE *)); + break; + case MAIL_SERVER_BOOL_TABLE: + get_mail_conf_bool_table(va_arg(ap, CONFIG_BOOL_TABLE *)); + break; + case MAIL_SERVER_TIME_TABLE: + get_mail_conf_time_table(va_arg(ap, CONFIG_TIME_TABLE *)); + break; + case MAIL_SERVER_RAW_TABLE: + get_mail_conf_raw_table(va_arg(ap, CONFIG_RAW_TABLE *)); + break; + case MAIL_SERVER_NINT_TABLE: + get_mail_conf_nint_table(va_arg(ap, CONFIG_NINT_TABLE *)); + break; + case MAIL_SERVER_NBOOL_TABLE: + get_mail_conf_nbool_table(va_arg(ap, CONFIG_NBOOL_TABLE *)); + break; + case MAIL_SERVER_PRE_INIT: + pre_init = va_arg(ap, MAIL_SERVER_INIT_FN); + break; + case MAIL_SERVER_POST_INIT: + post_init = va_arg(ap, MAIL_SERVER_INIT_FN); + break; + case MAIL_SERVER_LOOP: + loop = va_arg(ap, MAIL_SERVER_LOOP_FN); + break; + case MAIL_SERVER_EXIT: + dgram_server_onexit = va_arg(ap, MAIL_SERVER_EXIT_FN); + break; + case MAIL_SERVER_PRE_ACCEPT: + dgram_server_pre_accept = va_arg(ap, MAIL_SERVER_ACCEPT_FN); + break; + case MAIL_SERVER_IN_FLOW_DELAY: + dgram_server_in_flow_delay = 1; + break; + case MAIL_SERVER_SOLITARY: + if (!alone) + msg_fatal("service %s requires a process limit of 1", + service_name); + break; + case MAIL_SERVER_UNLIMITED: + if (!zerolimit) + msg_fatal("service %s requires a process limit of 0", + service_name); + break; + case MAIL_SERVER_PRIVILEGED: + if (user_name) + msg_fatal("service %s requires privileged operation", + service_name); + break; + case MAIL_SERVER_WATCHDOG: + dgram_server_watchdog = *va_arg(ap, int *); + break; + case MAIL_SERVER_BOUNCE_INIT: + dsn_filter_title = va_arg(ap, const char *); + dsn_filter_maps = va_arg(ap, const char **); + bounce_client_init(dsn_filter_title, *dsn_filter_maps); + break; + default: + msg_panic("%s: unknown argument type: %d", myname, key); + } + } + va_end(ap); + + if (root_dir) + root_dir = var_queue_dir; + if (user_name) + user_name = var_mail_owner; + + /* + * Can options be required? + */ + if (transport == 0) + msg_fatal("no transport type specified"); + else if (strcasecmp(transport, MASTER_XPORT_NAME_UXDG) == 0) + dgram_server_accept = dgram_server_accept_unix; + else + msg_fatal("unsupported transport type: %s", transport); + + /* + * Retrieve process generation from environment. + */ + if ((generation = getenv(MASTER_GEN_NAME)) != 0) { + if (!alldig(generation)) + msg_fatal("bad generation: %s", generation); + OCTAL_TO_UNSIGNED(dgram_server_generation, generation); + if (msg_verbose) + msg_info("process generation: %s (%o)", + generation, dgram_server_generation); + } + + /* + * Optionally start the debugger on ourself. + */ + if (debug_me) + debug_process(); + + /* + * Traditionally, BSD select() can't handle multiple processes selecting + * on the same socket, and wakes up every process in select(). See TCP/IP + * Illustrated volume 2 page 532. We avoid select() collisions with an + * external lock file. + */ + if (!alone) { + lock_path = concatenate(DEF_PID_DIR, "/", transport, + ".", service_name, (char *) 0); + why = vstring_alloc(1); + if ((dgram_server_lock = safe_open(lock_path, O_CREAT | O_RDWR, 0600, + (struct stat *) 0, -1, -1, why)) == 0) + msg_fatal("open lock file %s: %s", lock_path, vstring_str(why)); + close_on_exec(vstream_fileno(dgram_server_lock), CLOSE_ON_EXEC); + myfree(lock_path); + vstring_free(why); + } + + /* + * Set up call-back info. + */ + dgram_server_service = service; + dgram_server_name = service_name; + dgram_server_argv = argv + optind; + + /* + * Run pre-jail initialization. + */ + if (chdir(var_queue_dir) < 0) + msg_fatal("chdir(\"%s\"): %m", var_queue_dir); + if (pre_init) + pre_init(dgram_server_name, dgram_server_argv); + + /* + * Optionally, restrict the damage that this process can do. + */ + resolve_local_init(); + tzset(); + chroot_uid(root_dir, user_name); + + /* + * Run post-jail initialization. + */ + if (post_init) + post_init(dgram_server_name, dgram_server_argv); + + /* + * Running as a semi-resident server. Service requests. Terminate when we + * have serviced a sufficient number of requests, when no-one has been + * talking to us for a configurable amount of time, or when the master + * process terminated abnormally. + */ + if (var_idle_limit > 0) + event_request_timer(dgram_server_timeout, (void *) 0, var_idle_limit); + for (fd = MASTER_LISTEN_FD; fd < MASTER_LISTEN_FD + socket_count; fd++) { + event_enable_read(fd, dgram_server_accept, CAST_INT_TO_VOID_PTR(fd)); + close_on_exec(fd, CLOSE_ON_EXEC); + } + event_enable_read(MASTER_STATUS_FD, dgram_server_abort, (void *) 0); + close_on_exec(MASTER_STATUS_FD, CLOSE_ON_EXEC); + close_on_exec(MASTER_FLOW_READ, CLOSE_ON_EXEC); + close_on_exec(MASTER_FLOW_WRITE, CLOSE_ON_EXEC); + watchdog = watchdog_create(dgram_server_watchdog, + (WATCHDOG_FN) 0, (void *) 0); + + /* + * The event loop, at last. + */ + while (var_use_limit == 0 || use_count < var_use_limit) { + if (dgram_server_lock != 0) { + watchdog_stop(watchdog); + if (myflock(vstream_fileno(dgram_server_lock), INTERNAL_LOCK, + MYFLOCK_OP_EXCLUSIVE) < 0) + msg_fatal("select lock: %m"); + } + watchdog_start(watchdog); + delay = loop ? loop(dgram_server_name, dgram_server_argv) : -1; + event_loop(delay); + } + dgram_server_exit(); +} diff --git a/postfix/src/master/event_server.c b/postfix/src/master/event_server.c index a1c0d246a..b7b9a4ff6 100644 --- a/postfix/src/master/event_server.c +++ b/postfix/src/master/event_server.c @@ -195,7 +195,6 @@ #include /* select() */ #include #include -#include #include #include #include @@ -214,7 +213,6 @@ /* Utility library. */ #include -#include #include #include #include @@ -244,6 +242,7 @@ #include #include #include +#include /* Process manager. */ @@ -584,7 +583,6 @@ NORETURN event_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) const char *err; char *generation; int msg_vstream_needed = 0; - int redo_syslog_init = 0; const char *dsn_filter_title; const char **dsn_filter_maps; int retire_me_from_flags = 0; @@ -620,7 +618,7 @@ NORETURN event_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) * Initialize logging and exit handler. Do the syslog first, so that its * initialization completes before we enter the optional chroot jail. */ - msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE); if (msg_verbose) msg_info("daemon started"); @@ -674,8 +672,6 @@ NORETURN event_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) if ((err = split_nameval(oname_val, &oname, &oval)) != 0) msg_fatal("invalid \"-o %s\" option value: %s", optarg, err); mail_conf_update(oname, oval); - if (strcmp(oname, VAR_SYSLOG_NAME) == 0) - redo_syslog_init = 1; myfree(oname_val); break; case 'r': @@ -713,11 +709,11 @@ NORETURN event_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) set_mail_conf_str(VAR_SERVNAME, service_name); /* - * Initialize generic parameters. + * Initialize generic parameters and re-initialize logging in case of a + * non-default program name or logging destination. */ mail_params_init(); - if (redo_syslog_init) - msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE); /* * Register higher-level dictionaries and initialize the support for diff --git a/postfix/src/master/mail_server.h b/postfix/src/master/mail_server.h index 56a3072b7..7300b3f01 100644 --- a/postfix/src/master/mail_server.h +++ b/postfix/src/master/mail_server.h @@ -125,6 +125,14 @@ extern NORETURN trigger_server_main(int, char **, TRIGGER_SERVER_FN,...); #define TRIGGER_BUF_SIZE 1024 + /* + * dgram_server.c + */ +typedef void (*DGRAM_SERVER_FN) (char *, ssize_t, char *, char **); +extern NORETURN dgram_server_main(int, char **, DGRAM_SERVER_FN,...); + +#define DGRAM_BUF_SIZE 4096 + /* LICENSE /* .ad /* .fi diff --git a/postfix/src/master/master.c b/postfix/src/master/master.c index 4d77f1041..dbe880964 100644 --- a/postfix/src/master/master.c +++ b/postfix/src/master/master.c @@ -38,11 +38,13 @@ /* Terminate the master process after \fIexit_time\fR seconds. Child /* processes terminate at their convenience. /* .IP \fB-i\fR -/* Enable \fBinit\fR mode: do not attempt to become a session -/* or process group leader; and to force termination, set an -/* explicit signal handler instead of relying on the default -/* signal action. This mode is allowed only if the process ID -/* equals 1. +/* Enable \fBinit\fR mode: do not become a session or process +/* group leader; similar to \fB-s\fR, do not redirect stdout +/* to /dev/null, so that "maillog_file = /dev/stdout" works. +/* This mode is allowed only if the process ID equals 1. +/* .IP \fB-s\fR +/* Do not redirect stdout to /dev/null, so that "maillog_file +/* = /dev/stdout" works. /* .IP \fB-t\fR /* Test mode. Return a zero exit status when the \fBmaster.pid\fR lock /* file does not exist or when that file is not locked. This is evidence @@ -193,7 +195,6 @@ #include #include -#include #include #include #include @@ -205,7 +206,6 @@ #include #include -#include #include #include #include @@ -229,6 +229,7 @@ #include #include #include +#include /* Application-specific. */ @@ -264,6 +265,7 @@ int main(int argc, char **argv) VSTRING *data_lock_path; off_t inherited_limit; int debug_me = 0; + int keep_stdout = 0; int ch; int fd; int n; @@ -321,7 +323,8 @@ int main(int argc, char **argv) /* * Initialize logging and exit handler. */ - msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(var_procname), + MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); /* * Check the Postfix library version as soon as we enable logging. @@ -341,7 +344,7 @@ int main(int argc, char **argv) /* * Process JCL. */ - while ((ch = GETOPT(argc, argv, "c:Dde:itvw")) > 0) { + while ((ch = GETOPT(argc, argv, "c:Dde:istvw")) > 0) { switch (ch) { case 'c': if (setenv(CONF_ENV_PATH, optarg, 1) < 0) @@ -357,9 +360,13 @@ int main(int argc, char **argv) if (getpid() != 1) msg_fatal("-i is allowed only for PID 1 process"); init_mode = 1; + keep_stdout = 1; break; case 'D': - debug_me = 1; + debug_me = 1; + break; + case 's': + keep_stdout = 1; break; case 't': test_lock = 1; @@ -407,6 +414,8 @@ int main(int argc, char **argv) */ if (master_detach) for (fd = 0; fd < 3; fd++) { + if (fd == STDOUT_FILENO && keep_stdout) + continue; (void) close(fd); if (open("/dev/null", O_RDWR, 0) != fd) msg_fatal("open /dev/null: %m"); @@ -525,6 +534,8 @@ int main(int argc, char **argv) master_config(); master_sigsetup(); master_flow_init(); + maillog_client_init(mail_task(var_procname), + MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); msg_info("daemon started -- version %s, configuration %s", var_mail_version, var_config_dir); @@ -563,6 +574,8 @@ int main(int argc, char **argv) master_gotsighup = 0; /* this first */ master_vars_init(); /* then this */ master_refresh(); /* then this */ + maillog_client_init(mail_task(var_procname), + MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); } if (master_gotsigchld) { if (msg_verbose) diff --git a/postfix/src/master/master.h b/postfix/src/master/master.h index 55bdf74db..ce07ab779 100644 --- a/postfix/src/master/master.h +++ b/postfix/src/master/master.h @@ -73,12 +73,13 @@ typedef struct MASTER_SERV { #define MASTER_LIMIT_OK(limit, count) ((limit) == 0 || ((count) < (limit))) /* - * Service types. + * Service types, stream sockets unless indicated otherwise. */ #define MASTER_SERV_TYPE_UNIX 1 /* AF_UNIX domain socket */ #define MASTER_SERV_TYPE_INET 2 /* AF_INET domain socket */ #define MASTER_SERV_TYPE_FIFO 3 /* fifo (named pipe) */ #define MASTER_SERV_TYPE_PASS 4 /* AF_UNIX domain socket */ +#define MASTER_SERV_TYPE_UXDG 5 /* AF_UNIX domain datagram socket */ /* * Default process management policy values. This is only the bare minimum. diff --git a/postfix/src/master/master_ent.c b/postfix/src/master/master_ent.c index 20aec82d9..9f0f34c2e 100644 --- a/postfix/src/master/master_ent.c +++ b/postfix/src/master/master_ent.c @@ -57,6 +57,11 @@ /* 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 libraries. */ @@ -381,6 +386,10 @@ MASTER_SERV *get_master_ent() serv->type = MASTER_SERV_TYPE_UNIX; serv->listen_fd_count = 1; serv->flags |= MASTER_FLAG_LOCAL_ONLY; + } else if (STR_SAME(transport, MASTER_XPORT_NAME_UXDG)) { + serv->type = MASTER_SERV_TYPE_UXDG; + serv->listen_fd_count = 1; + serv->flags |= MASTER_FLAG_LOCAL_ONLY; } else if (STR_SAME(transport, MASTER_XPORT_NAME_FIFO)) { serv->type = MASTER_SERV_TYPE_FIFO; serv->listen_fd_count = 1; @@ -444,6 +453,9 @@ MASTER_SERV *get_master_ent() } else if (serv->type == MASTER_SERV_TYPE_UNIX) { serv->name = mail_pathname(private ? MAIL_CLASS_PRIVATE : MAIL_CLASS_PUBLIC, name); + } else if (serv->type == MASTER_SERV_TYPE_UXDG) { + serv->name = mail_pathname(private ? MAIL_CLASS_PRIVATE : + MAIL_CLASS_PUBLIC, name); } else if (serv->type == MASTER_SERV_TYPE_FIFO) { serv->name = mail_pathname(private ? MAIL_CLASS_PRIVATE : MAIL_CLASS_PUBLIC, name); @@ -593,6 +605,7 @@ void print_master_ent(MASTER_SERV *serv) #ifdef MASTER_SERV_TYPE_PASS serv->type == MASTER_SERV_TYPE_PASS ? MASTER_XPORT_NAME_PASS : #endif + serv->type == MASTER_SERV_TYPE_UXDG ? MASTER_XPORT_NAME_UXDG : "unknown transport type"); msg_info("listen_fd_count: %d", serv->listen_fd_count); msg_info("wakeup: %d", serv->wakeup_time); diff --git a/postfix/src/master/master_listen.c b/postfix/src/master/master_listen.c index a17bde1cb..1e7f6fabe 100644 --- a/postfix/src/master/master_listen.c +++ b/postfix/src/master/master_listen.c @@ -35,6 +35,11 @@ /* 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. */ @@ -97,6 +102,17 @@ void master_listen_init(MASTER_SERV *serv) set_ugid(getuid(), getgid()); break; + /* + * UNIX-domain datagram listener endpoints always come as singlets. + */ + case MASTER_SERV_TYPE_UXDG: + set_eugid(var_owner_uid, var_owner_gid); + serv->listen_fd[0] = + unix_dgram_listen(serv->name, NON_BLOCKING); + close_on_exec(serv->listen_fd[0], CLOSE_ON_EXEC); + set_ugid(getuid(), getgid()); + break; + /* * FIFO listener endpoints always come as singlets. */ diff --git a/postfix/src/master/master_proto.h b/postfix/src/master/master_proto.h index bfa0e04c6..608451474 100644 --- a/postfix/src/master/master_proto.h +++ b/postfix/src/master/master_proto.h @@ -16,6 +16,7 @@ #define MASTER_XPORT_NAME_FIFO "fifo" /* local IPC */ #define MASTER_XPORT_NAME_INET "inet" /* non-local IPC */ #define MASTER_XPORT_NAME_PASS "pass" /* local IPC */ +#define MASTER_XPORT_NAME_UXDG "unix-dgram" /* local IPC */ /* * Format of a status message sent by a child process to the process @@ -65,5 +66,10 @@ extern int master_notify(int, unsigned, int); /* encapsulate status msg */ /* 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 /*--*/ diff --git a/postfix/src/master/master_wakeup.c b/postfix/src/master/master_wakeup.c index e303dc2cc..cc5092420 100644 --- a/postfix/src/master/master_wakeup.c +++ b/postfix/src/master/master_wakeup.c @@ -46,6 +46,11 @@ /* 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. */ @@ -53,6 +58,7 @@ #include #include #include +#include /* Utility library. */ @@ -105,6 +111,10 @@ static void master_wakeup_timer_event(int unused_event, void *context) case MASTER_SERV_TYPE_UNIX: status = LOCAL_TRIGGER(serv->name, &wakeup, sizeof(wakeup), BRIEFLY); break; + case MASTER_SERV_TYPE_UXDG: + status = -1; + errno = EOPNOTSUPP; + break; #ifdef MASTER_SERV_TYPE_PASS case MASTER_SERV_TYPE_PASS: status = pass_trigger(serv->name, &wakeup, sizeof(wakeup), BRIEFLY); diff --git a/postfix/src/master/multi_server.c b/postfix/src/master/multi_server.c index 22dc4635c..273a07da8 100644 --- a/postfix/src/master/multi_server.c +++ b/postfix/src/master/multi_server.c @@ -178,7 +178,6 @@ #include /* select() */ #include #include -#include #include #include #include @@ -197,7 +196,6 @@ /* Utility library. */ #include -#include #include #include #include @@ -227,6 +225,7 @@ #include #include #include +#include /* Process manager. */ @@ -560,7 +559,6 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) const char *err; char *generation; int msg_vstream_needed = 0; - int redo_syslog_init = 0; const char *dsn_filter_title; const char **dsn_filter_maps; @@ -594,7 +592,7 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) * Initialize logging and exit handler. Do the syslog first, so that its * initialization completes before we enter the optional chroot jail. */ - msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE); if (msg_verbose) msg_info("daemon started"); @@ -648,8 +646,6 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) if ((err = split_nameval(oname_val, &oname, &oval)) != 0) msg_fatal("invalid \"-o %s\" option value: %s", optarg, err); mail_conf_update(oname, oval); - if (strcmp(oname, VAR_SYSLOG_NAME) == 0) - redo_syslog_init = 1; myfree(oname_val); break; case 's': @@ -683,11 +679,11 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) set_mail_conf_str(VAR_SERVNAME, service_name); /* - * Initialize generic parameters. + * Initialize generic parameters and re-initialize logging in case of a + * non-default program name or logging destination. */ mail_params_init(); - if (redo_syslog_init) - msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE); /* * Register higher-level dictionaries and initialize the support for diff --git a/postfix/src/master/single_server.c b/postfix/src/master/single_server.c index 7ef4ca0cc..a3176734f 100644 --- a/postfix/src/master/single_server.c +++ b/postfix/src/master/single_server.c @@ -165,7 +165,6 @@ #include #include #include -#include #include #include #include @@ -180,7 +179,6 @@ /* Utility library. */ #include -#include #include #include #include @@ -209,6 +207,7 @@ #include #include #include +#include /* Process manager. */ @@ -453,7 +452,6 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...) const char *err; char *generation; int msg_vstream_needed = 0; - int redo_syslog_init = 0; const char *dsn_filter_title; const char **dsn_filter_maps; int retire_me_from_flags = 0; @@ -489,7 +487,7 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...) * Initialize logging and exit handler. Do the syslog first, so that its * initialization completes before we enter the optional chroot jail. */ - msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE); if (msg_verbose) msg_info("daemon started"); @@ -543,8 +541,6 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...) if ((err = split_nameval(oname_val, &oname, &oval)) != 0) msg_fatal("invalid \"-o %s\" option value: %s", optarg, err); mail_conf_update(oname, oval); - if (strcmp(oname, VAR_SYSLOG_NAME) == 0) - redo_syslog_init = 1; myfree(oname_val); break; case 'r': @@ -585,8 +581,7 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...) * Initialize generic parameters. */ mail_params_init(); - if (redo_syslog_init) - msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE); /* * Register higher-level dictionaries and initialize the support for diff --git a/postfix/src/master/trigger_server.c b/postfix/src/master/trigger_server.c index 5762e1af6..efa73d126 100644 --- a/postfix/src/master/trigger_server.c +++ b/postfix/src/master/trigger_server.c @@ -168,7 +168,6 @@ #include #include #include -#include #include #include #include @@ -183,7 +182,6 @@ /* Utility library. */ #include -#include #include #include #include @@ -211,6 +209,7 @@ #include #include #include +#include /* Process manager. */ @@ -441,7 +440,6 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,.. const char *err; char *generation; int msg_vstream_needed = 0; - int redo_syslog_init = 0; const char *dsn_filter_title; const char **dsn_filter_maps; @@ -475,7 +473,7 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,.. * Initialize logging and exit handler. Do the syslog first, so that its * initialization completes before we enter the optional chroot jail. */ - msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE); if (msg_verbose) msg_info("daemon started"); @@ -529,8 +527,6 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,.. if ((err = split_nameval(oname_val, &oname, &oval)) != 0) msg_fatal("invalid \"-o %s\" option value: %s", optarg, err); mail_conf_update(oname, oval); - if (strcmp(oname, VAR_SYSLOG_NAME) == 0) - redo_syslog_init = 1; myfree(oname_val); break; case 's': @@ -564,11 +560,11 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,.. set_mail_conf_str(VAR_SERVNAME, service_name); /* - * Initialize generic parameters. + * Initialize generic parameters and re-initialize logging in case of a + * non-default program name or logging destination. */ mail_params_init(); - if (redo_syslog_init) - msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(var_procname), MAILLOG_CLIENT_FLAG_NONE); /* * Register higher-level dictionaries and initialize the support for diff --git a/postfix/src/postalias/Makefile.in b/postfix/src/postalias/Makefile.in index 16485bb40..5e5b72dca 100644 --- a/postfix/src/postalias/Makefile.in +++ b/postfix/src/postalias/Makefile.in @@ -100,9 +100,9 @@ postalias.o: ../../include/mail_params.h postalias.o: ../../include/mail_parm_split.h postalias.o: ../../include/mail_task.h postalias.o: ../../include/mail_version.h +postalias.o: ../../include/maillog_client.h postalias.o: ../../include/mkmap.h postalias.o: ../../include/msg.h -postalias.o: ../../include/msg_syslog.h postalias.o: ../../include/msg_vstream.h postalias.o: ../../include/myflock.h postalias.o: ../../include/mymalloc.h diff --git a/postfix/src/postalias/postalias.c b/postfix/src/postalias/postalias.c index 48d10a7ac..0cebc677f 100644 --- a/postfix/src/postalias/postalias.c +++ b/postfix/src/postalias/postalias.c @@ -79,8 +79,8 @@ /* found to the standard output stream. The exit status is zero /* when the requested information was found. /* -/* Note: this performs a single query with the key as specified, -/* and does not make iterative queries with substrings of the +/* Note: this performs a single query with the key as specified, +/* and does not make iterative queries with substrings of the /* key as described in the aliases(5) manual page. /* /* If a key value of \fB-\fR is specified, the program reads key @@ -247,7 +247,6 @@ #include #include #include -#include #include #include #include @@ -267,6 +266,7 @@ #include #include #include +#include /* Application-specific. */ @@ -509,8 +509,8 @@ static int postalias_queries(VSTREAM *in, char **maps, const int map_count, dicts[n] = 0; /* - * Perform all queries. Open maps on the fly, to avoid opening unnecessary - * maps. + * Perform all queries. Open maps on the fly, to avoid opening + * unnecessary maps. */ while (vstring_get_nonl(keybuf, in) != VSTREAM_EOF) { for (n = 0; n < map_count; n++) { @@ -740,13 +740,13 @@ int main(int argc, char **argv) msg_verbose = 1; /* - * Initialize. Set up logging, read the global configuration file and - * extract configuration information. + * Initialize. Set up logging. Read the global configuration file after + * parsing command-line arguments. */ if ((slash = strrchr(argv[0], '/')) != 0 && slash[1]) argv[0] = slash + 1; msg_vstream_init(argv[0], VSTREAM_ERR); - msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(argv[0]), MAILLOG_CLIENT_FLAG_NONE); /* * Check the Postfix library version as soon as we enable logging. @@ -822,7 +822,7 @@ int main(int argc, char **argv) update_env(import_env->argv); argv_free(import_env); /* Re-evaluate mail_task() after reading main.cf. */ - msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(argv[0]), MAILLOG_CLIENT_FLAG_NONE); mail_dict_init(); /* diff --git a/postfix/src/postconf/postconf_master.c b/postfix/src/postconf/postconf_master.c index 71d0daf02..3c169f728 100644 --- a/postfix/src/postconf/postconf_master.c +++ b/postfix/src/postconf/postconf_master.c @@ -190,6 +190,7 @@ static const char *pcf_valid_master_types[] = { MASTER_XPORT_NAME_FIFO, MASTER_XPORT_NAME_INET, MASTER_XPORT_NAME_PASS, + MASTER_XPORT_NAME_UXDG, 0, }; diff --git a/postfix/src/postdrop/Makefile.in b/postfix/src/postdrop/Makefile.in index 2e9c9e584..6ae3f7a9f 100644 --- a/postfix/src/postdrop/Makefile.in +++ b/postfix/src/postdrop/Makefile.in @@ -74,8 +74,8 @@ postdrop.o: ../../include/mail_queue.h postdrop.o: ../../include/mail_stream.h postdrop.o: ../../include/mail_task.h postdrop.o: ../../include/mail_version.h +postdrop.o: ../../include/maillog_client.h postdrop.o: ../../include/msg.h -postdrop.o: ../../include/msg_syslog.h postdrop.o: ../../include/msg_vstream.h postdrop.o: ../../include/mymalloc.h postdrop.o: ../../include/nvtable.h diff --git a/postfix/src/postdrop/postdrop.c b/postfix/src/postdrop/postdrop.c index 96e0bbe35..47b2e88b2 100644 --- a/postfix/src/postdrop/postdrop.c +++ b/postfix/src/postdrop/postdrop.c @@ -56,14 +56,16 @@ /* \fBpostconf\fR(5) for more details including examples. /* .IP "\fBalternate_config_directories (empty)\fR" /* A list of non-default Postfix configuration directories that may -/* be specified with "-c config_directory" on the command line, or -/* via the MAIL_CONFIG environment parameter. +/* be specified with "-c config_directory" on the command line (in the +/* case of \fBsendmail\fR(1), with the "-C" option), or via the MAIL_CONFIG +/* environment parameter. /* .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 Postfix process will -/* import from a non-Postfix parent process. +/* The list of environment parameters that a privileged Postfix +/* process will import from a non-Postfix parent process, or name=value +/* environment overrides. /* .IP "\fBqueue_directory (see 'postconf -d' output)\fR" /* The location of the Postfix top-level queue directory. /* .IP "\fBsyslog_facility (mail)\fR" @@ -111,7 +113,6 @@ #include #include #include -#include #include #include @@ -122,7 +123,6 @@ #include #include #include -#include #include #include #include @@ -144,6 +144,7 @@ #include #include #include +#include /* Application-specific. */ @@ -184,9 +185,11 @@ static void postdrop_sig(int sig) /* * This is the fatal error handler. Don't try to do anything fancy. * - * msg_vstream does not allocate memory, but msg_syslog may indirectly in - * syslog(), so it should not be called from a user-triggered signal - * handler. + * To avoid privilege escalation in a set-gid program, Postfix logging + * functions must not be called from a user-triggered signal handler, + * because Postfix logging functions may allocate memory on the fly (as + * does the syslog() library function), and the memory allocator is not + * reentrant. * * Assume atomic signal() updates, even when emulated with sigaction(). We * use the in-kernel SIGINT handler address as an atomic variable to @@ -270,7 +273,7 @@ int main(int argc, char **argv) */ argv[0] = "postdrop"; msg_vstream_init(argv[0], VSTREAM_ERR); - msg_syslog_init(mail_task("postdrop"), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task("postdrop"), MAILLOG_CLIENT_FLAG_NONE); set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0])); /* @@ -303,16 +306,11 @@ int main(int argc, char **argv) /* * Read the global configuration file and extract configuration - * information. Some claim that the user should supply the working - * directory instead. That might be OK, given that this command needs - * write permission in a subdirectory called "maildrop". However we still - * need to reliably detect incomplete input, and so we must perform - * record-level I/O. With that, we should also take the opportunity to - * perform some sanity checks on the input. + * information. */ mail_conf_read(); /* Re-evaluate mail_task() after reading main.cf. */ - msg_syslog_init(mail_task("postdrop"), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task("postdrop"), MAILLOG_CLIENT_FLAG_NONE); get_mail_conf_str_table(str_table); /* diff --git a/postfix/src/postfix/Makefile.in b/postfix/src/postfix/Makefile.in index 5f67eb7c7..56ff96b0b 100644 --- a/postfix/src/postfix/Makefile.in +++ b/postfix/src/postfix/Makefile.in @@ -69,8 +69,8 @@ postfix.o: ../../include/mail_conf.h postfix.o: ../../include/mail_params.h postfix.o: ../../include/mail_parm_split.h postfix.o: ../../include/mail_version.h +postfix.o: ../../include/maillog_client.h postfix.o: ../../include/msg.h -postfix.o: ../../include/msg_syslog.h postfix.o: ../../include/msg_vstream.h postfix.o: ../../include/safe.h postfix.o: ../../include/stringops.h diff --git a/postfix/src/postfix/postfix.c b/postfix/src/postfix/postfix.c index 1b7e64fea..1758c411d 100644 --- a/postfix/src/postfix/postfix.c +++ b/postfix/src/postfix/postfix.c @@ -128,6 +128,15 @@ /* This is set when the -v command-line option is present. /* .IP \fBMAIL_DEBUG\fR /* This is set when the -D command-line option is present. +/* .PP +/* When the internal logging service is enabled (by setting a +/* non-empty maillog_file parameter value) the postfix(1) +/* command exports settings that are used by child processes +/* before they have processed main.cf or command-line settings. +/* .IP \fBPOSTLOG_SERVICE +/* The name of the public postlog service endpoint. +/* .IP \fBPOSTLOG_HOSTNAME +/* The hostname to prepend to internal logging. /* CONFIGURATION PARAMETERS /* .ad /* .fi @@ -215,6 +224,13 @@ /* .IP "\fBmulti_instance_enable (no)\fR" /* Allow this Postfix instance to be started, stopped, etc., by a /* multi-instance manager. +/* .PP +/* Available in Postfix version 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. /* FILES /* .ad /* .fi @@ -296,6 +312,7 @@ /* oqmgr(8), old Postfix queue manager /* pickup(8), Postfix local mail pickup /* pipe(8), deliver mail to non-Postfix command +/* postlogd(8), Postfix internal logging service /* postscreen(8), Postfix zombie blocker /* proxymap(8), Postfix lookup table proxy server /* qmgr(8), Postfix queue manager @@ -380,7 +397,6 @@ #include #include #include -#include #ifdef USE_PATHS_H #include #endif @@ -389,7 +405,6 @@ #include #include -#include #include #include #include @@ -402,6 +417,7 @@ #include #include #include +#include /* Additional installation parameters. */ @@ -476,7 +492,7 @@ int main(int argc, char **argv) argv[0] = slash + 1; if (isatty(STDERR_FILENO)) msg_vstream_init(argv[0], VSTREAM_ERR); - msg_syslog_init(argv[0], LOG_PID, LOG_FACILITY); + maillog_client_init(argv[0], MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); /* * Check the Postfix library version as soon as we enable logging. @@ -525,6 +541,22 @@ int main(int argc, char **argv) mail_conf_read(); get_mail_conf_str_table(str_table); + /* + * Environment import filter, to enforce consistent behavior whether this + * command is started by hand, or at system boot time. This is necessary + * because some shell scripts use environment settings to override + * main.cf settings. + */ + import_env = mail_parm_split(VAR_IMPORT_ENVIRON, var_import_environ); + clean_env(import_env->argv); + argv_free(import_env); + + /* + * This is after calling clean_env(), to ensure that POSTLOG_XXX exports + * will work, even if import_environment would remove them. + */ + maillog_client_init(argv[0], MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); + /* * Alert the sysadmin that the backwards-compatible settings are still in * effect. @@ -538,17 +570,6 @@ int main(int argc, char **argv) VAR_COMPAT_LEVEL "=%d\" and \"postfix reload\"", CUR_COMPAT_LEVEL); } - - /* - * Environment import filter, to enforce consistent behavior whether this - * command is started by hand, or at system boot time. This is necessary - * because some shell scripts use environment settings to override - * main.cf settings. - */ - import_env = mail_parm_split(VAR_IMPORT_ENVIRON, var_import_environ); - clean_env(import_env->argv); - argv_free(import_env); - check_setenv("PATH", ROOT_PATH); /* sys_defs.h */ check_setenv(CONF_ENV_PATH, var_config_dir);/* mail_conf.h */ diff --git a/postfix/src/postkick/postkick.c b/postfix/src/postkick/postkick.c index 4adcf848c..dde3dbf9f 100644 --- a/postfix/src/postkick/postkick.c +++ b/postfix/src/postkick/postkick.c @@ -88,7 +88,6 @@ #include #include #include -#include #include #include @@ -151,8 +150,8 @@ int main(int argc, char **argv) msg_verbose = 1; /* - * Initialize. Set up logging, read the global configuration file and - * extract configuration information. + * Initialize. Set up logging. Read the global configuration file after + * parsing command-line arguments. */ if ((slash = strrchr(argv[0], '/')) != 0 && slash[1]) argv[0] = slash + 1; diff --git a/postfix/src/postlog/Makefile.in b/postfix/src/postlog/Makefile.in index 28f7276c8..84ee53e4b 100644 --- a/postfix/src/postlog/Makefile.in +++ b/postfix/src/postlog/Makefile.in @@ -70,9 +70,9 @@ 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_syslog.h postlog.o: ../../include/msg_vstream.h postlog.o: ../../include/sys_defs.h postlog.o: ../../include/vbuf.h diff --git a/postfix/src/postlog/postlog.c b/postfix/src/postlog/postlog.c index 9e3861a72..e7bb9b41e 100644 --- a/postfix/src/postlog/postlog.c +++ b/postfix/src/postlog/postlog.c @@ -17,15 +17,17 @@ /* line, \fBpostlog\fR(1) reads from standard input and logs each input /* line as one record. /* -/* Logging is sent to \fBsyslogd\fR(8); when the standard error stream -/* is connected to a terminal, logging is sent there as well. +/* By default, logging is sent to \fBsyslogd\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 -/* Include the process ID in the logging tag. +/* .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 @@ -64,9 +66,17 @@ /* .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 /* syslogd(8), syslog daemon +/* postlogd(8), internal logging service /* LICENSE /* .ad /* .fi @@ -88,7 +98,6 @@ #include #include #include -#include #include #include #include @@ -105,7 +114,6 @@ #include #include #include -#include #include #include @@ -116,6 +124,7 @@ #include #include #include +#include /* Application-specific. */ @@ -162,7 +171,7 @@ static void log_argv(int level, char **argv) if (*argv) vstring_strcat(buf, " "); } - msg_text(level, vstring_str(buf)); + msg_printf(level, "%s", vstring_str(buf)); vstring_free(buf); } @@ -173,7 +182,7 @@ static void log_stream(int level, VSTREAM *fp) VSTRING *buf = vstring_alloc(100); while (vstring_get_nonl(buf, fp) != VSTREAM_EOF) - msg_text(level, vstring_str(buf)); + msg_printf(level, "%s", vstring_str(buf)); vstring_free(buf); } @@ -187,7 +196,6 @@ int main(int argc, char **argv) int fd; int ch; const char *tag; - int log_flags = 0; int level = MSG_INFO; ARGV *import_env; @@ -217,7 +225,7 @@ int main(int argc, char **argv) tag = mail_task(argv[0]); if (isatty(STDERR_FILENO)) msg_vstream_init(tag, VSTREAM_ERR); - msg_syslog_init(tag, LOG_PID, LOG_FACILITY); + maillog_client_init(tag, MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); /* * Check the Postfix library version as soon as we enable logging. @@ -238,7 +246,6 @@ int main(int argc, char **argv) msg_fatal("out of memory"); break; case 'i': - log_flags |= LOG_PID; break; case 'p': level = level_map(optarg); @@ -270,7 +277,7 @@ int main(int argc, char **argv) */ if (isatty(STDERR_FILENO)) msg_vstream_init(tag, VSTREAM_ERR); - msg_syslog_init(tag, LOG_PID, LOG_FACILITY); + maillog_client_init(tag, MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); /* * Log the command line or log lines from standard input. diff --git a/postfix/src/postlogd/Makefile.in b/postfix/src/postlogd/Makefile.in new file mode 100644 index 000000000..bdf7d050f --- /dev/null +++ b/postfix/src/postlogd/Makefile.in @@ -0,0 +1,74 @@ +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/logwriter.h +postlogd.o: ../../include/mail_conf.h +postlogd.o: ../../include/mail_params.h +postlogd.o: ../../include/mail_server.h +postlogd.o: ../../include/mail_version.h +postlogd.o: ../../include/msg.h +postlogd.o: ../../include/msg_logger.h +postlogd.o: ../../include/sys_defs.h +postlogd.o: ../../include/vbuf.h +postlogd.o: ../../include/vstream.h +postlogd.o: postlogd.c diff --git a/postfix/src/postlogd/postlogd.c b/postfix/src/postlogd/postlogd.c new file mode 100644 index 000000000..5461e1a97 --- /dev/null +++ b/postfix/src/postlogd/postlogd.c @@ -0,0 +1,251 @@ +/*++ +/* 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 permision on programs other than \fBpostdrop\fR(1) +/* and \fBpostqueue\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(5), system logging +/* 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 + + /* + * Utility library. + */ +#include +#include +#include +#include +#include + + /* + * Global library. + */ +#include +#include +#include +#include + + /* + * Server skeleton. + */ +#include + + /* + * 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; + + 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); +} diff --git a/postfix/src/postmap/Makefile.in b/postfix/src/postmap/Makefile.in index 6850eb792..3667bb65b 100644 --- a/postfix/src/postmap/Makefile.in +++ b/postfix/src/postmap/Makefile.in @@ -113,10 +113,10 @@ postmap.o: ../../include/mail_params.h postmap.o: ../../include/mail_parm_split.h postmap.o: ../../include/mail_task.h postmap.o: ../../include/mail_version.h +postmap.o: ../../include/maillog_client.h postmap.o: ../../include/mime_state.h postmap.o: ../../include/mkmap.h postmap.o: ../../include/msg.h -postmap.o: ../../include/msg_syslog.h postmap.o: ../../include/msg_vstream.h postmap.o: ../../include/myflock.h postmap.o: ../../include/mymalloc.h diff --git a/postfix/src/postmap/postmap.c b/postfix/src/postmap/postmap.c index db40a38c3..3b520e3bf 100644 --- a/postfix/src/postmap/postmap.c +++ b/postfix/src/postmap/postmap.c @@ -321,7 +321,6 @@ #include #include #include -#include #include #include #include @@ -342,6 +341,7 @@ #include #include #include +#include /* Application-specific. */ @@ -959,13 +959,13 @@ int main(int argc, char **argv) msg_verbose = 1; /* - * Initialize. Set up logging, read the global configuration file and - * extract configuration information. + * Initialize. Set up logging. Read the global configuration file after + * parsing command-line arguments. */ if ((slash = strrchr(argv[0], '/')) != 0 && slash[1]) argv[0] = slash + 1; msg_vstream_init(argv[0], VSTREAM_ERR); - msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(argv[0]), MAILLOG_CLIENT_FLAG_NONE); /* * Check the Postfix library version as soon as we enable logging. @@ -1056,7 +1056,7 @@ int main(int argc, char **argv) update_env(import_env->argv); argv_free(import_env); /* Re-evaluate mail_task() after reading main.cf. */ - msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(argv[0]), MAILLOG_CLIENT_FLAG_NONE); mail_dict_init(); if ((query == 0 || strcmp(query, "-") != 0) && (postmap_flags & POSTMAP_FLAG_ANY_KEY)) diff --git a/postfix/src/postmulti/Makefile.in b/postfix/src/postmulti/Makefile.in index e6ea5d4fd..f2e3680bf 100644 --- a/postfix/src/postmulti/Makefile.in +++ b/postfix/src/postmulti/Makefile.in @@ -70,8 +70,8 @@ postmulti.o: ../../include/mail_conf.h postmulti.o: ../../include/mail_params.h postmulti.o: ../../include/mail_parm_split.h postmulti.o: ../../include/mail_version.h +postmulti.o: ../../include/maillog_client.h postmulti.o: ../../include/msg.h -postmulti.o: ../../include/msg_syslog.h postmulti.o: ../../include/msg_vstream.h postmulti.o: ../../include/mymalloc.h postmulti.o: ../../include/name_code.h diff --git a/postfix/src/postmulti/postmulti.c b/postfix/src/postmulti/postmulti.c index a6b132e4e..bffb8edfa 100644 --- a/postfix/src/postmulti/postmulti.c +++ b/postfix/src/postmulti/postmulti.c @@ -399,6 +399,11 @@ /* 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. */ @@ -411,7 +416,6 @@ #include #include #include -#include #include #include #ifdef USE_PATHS_H @@ -423,7 +427,6 @@ #include #include -#include #include #include #include @@ -442,6 +445,7 @@ #include #include #include +#include /* Application-specific. */ @@ -1687,20 +1691,30 @@ int main(int argc, char **argv) argv[0] = slash + 1; if (isatty(STDERR_FILENO)) msg_vstream_init(argv[0], VSTREAM_ERR); - msg_syslog_init(argv[0], LOG_PID, LOG_FACILITY); + maillog_client_init(argv[0], MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); /* * Check the Postfix library version as soon as we enable logging. */ MAIL_VERSION_CHECK; + /* + * Process main.cf parameters. This is done before the GETOPT() loop to + * improve logging. This assumes that no command-line option can affect + * parameter processing. + */ + mail_conf_read(); + get_mail_conf_str_table(str_table); + maillog_client_init(argv[0], MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); + if ((config_dir = getenv(CONF_ENV_PATH)) != 0 && strcmp(config_dir, DEF_CONFIG_DIR) != 0) msg_fatal("Non-default configuration directory: %s=%s", CONF_ENV_PATH, config_dir); /* - * Parse switches. + * Parse switches. Move the above mail_conf_read() block after this loop, + * if any command-line option can affect parameter processing. */ while ((ch = GETOPT(argc, argv, "ae:g:i:G:I:lpRvx")) > 0) { switch (ch) { @@ -1814,12 +1828,6 @@ int main(int argc, char **argv) EDIT_CMD_STR(cmd_mode)); } - /* - * Process main.cf parameters. - */ - mail_conf_read(); - get_mail_conf_str_table(str_table); - /* * Sanity checks. */ diff --git a/postfix/src/postqueue/Makefile.in b/postfix/src/postqueue/Makefile.in index e9f2bf23a..f01c3ae3d 100644 --- a/postfix/src/postqueue/Makefile.in +++ b/postfix/src/postqueue/Makefile.in @@ -77,8 +77,8 @@ postqueue.o: ../../include/mail_queue.h postqueue.o: ../../include/mail_run.h postqueue.o: ../../include/mail_task.h postqueue.o: ../../include/mail_version.h +postqueue.o: ../../include/maillog_client.h postqueue.o: ../../include/msg.h -postqueue.o: ../../include/msg_syslog.h postqueue.o: ../../include/msg_vstream.h postqueue.o: ../../include/mymalloc.h postqueue.o: ../../include/nvtable.h diff --git a/postfix/src/postqueue/postqueue.c b/postfix/src/postqueue/postqueue.c index 2cde36391..68d5b7342 100644 --- a/postfix/src/postqueue/postqueue.c +++ b/postfix/src/postqueue/postqueue.c @@ -247,7 +247,6 @@ #include #include #include -#include #include #include #include @@ -272,6 +271,7 @@ #include #include #include +#include /* Application-specific. */ @@ -566,15 +566,14 @@ int main(int argc, char **argv) msg_fatal_status(EX_UNAVAILABLE, "open /dev/null: %m"); /* - * Initialize. Set up logging, read the global configuration file and - * extract configuration information. Set up signal handlers so that we - * can clean up incomplete output. - * Censor the process name: it is provided by the user. + * Initialize. Set up logging. Read the global configuration file after + * parsing command-line arguments. Censor the process name: it is + * provided by the user. */ argv[0] = "postqueue"; msg_vstream_init(argv[0], VSTREAM_ERR); msg_cleanup(unavailable); - msg_syslog_init(mail_task("postqueue"), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task("postqueue"), MAILLOG_CLIENT_FLAG_NONE); set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0])); /* @@ -637,7 +636,7 @@ int main(int argc, char **argv) */ mail_conf_read(); /* Re-evaluate mail_task() after reading main.cf. */ - msg_syslog_init(mail_task("postqueue"), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task("postqueue"), MAILLOG_CLIENT_FLAG_NONE); mail_dict_init(); /* proxy, sql, ldap */ get_mail_conf_str_table(str_table); diff --git a/postfix/src/postsuper/Makefile.in b/postfix/src/postsuper/Makefile.in index e130daa55..38ae3a92f 100644 --- a/postfix/src/postsuper/Makefile.in +++ b/postfix/src/postsuper/Makefile.in @@ -69,8 +69,8 @@ postsuper.o: ../../include/mail_parm_split.h postsuper.o: ../../include/mail_queue.h postsuper.o: ../../include/mail_task.h postsuper.o: ../../include/mail_version.h +postsuper.o: ../../include/maillog_client.h postsuper.o: ../../include/msg.h -postsuper.o: ../../include/msg_syslog.h postsuper.o: ../../include/msg_vstream.h postsuper.o: ../../include/mymalloc.h postsuper.o: ../../include/myrand.h diff --git a/postfix/src/postsuper/postsuper.c b/postfix/src/postsuper/postsuper.c index 2bad6f320..3d356412e 100644 --- a/postfix/src/postsuper/postsuper.c +++ b/postfix/src/postsuper/postsuper.c @@ -280,7 +280,6 @@ #include #include -#include #include #include #include @@ -305,6 +304,7 @@ #include #include #include +#include /* Application-specific. */ @@ -1149,7 +1149,8 @@ int main(int argc, char **argv) if ((slash = strrchr(argv[0], '/')) != 0 && slash[1]) argv[0] = slash + 1; msg_vstream_init(argv[0], VSTREAM_ERR); - msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(argv[0]), + MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0])); /* @@ -1242,7 +1243,8 @@ int main(int argc, char **argv) update_env(import_env->argv); argv_free(import_env); /* Re-evaluate mail_task() after reading main.cf. */ - msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task(argv[0]), + MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); if (chdir(var_queue_dir)) msg_fatal("chdir %s: %m", var_queue_dir); diff --git a/postfix/src/sendmail/Makefile.in b/postfix/src/sendmail/Makefile.in index ee023f434..bb0298a2a 100644 --- a/postfix/src/sendmail/Makefile.in +++ b/postfix/src/sendmail/Makefile.in @@ -83,10 +83,10 @@ sendmail.o: ../../include/mail_run.h sendmail.o: ../../include/mail_stream.h sendmail.o: ../../include/mail_task.h sendmail.o: ../../include/mail_version.h +sendmail.o: ../../include/maillog_client.h sendmail.o: ../../include/mime_state.h sendmail.o: ../../include/msg.h sendmail.o: ../../include/msg_stats.h -sendmail.o: ../../include/msg_syslog.h sendmail.o: ../../include/msg_vstream.h sendmail.o: ../../include/mymalloc.h sendmail.o: ../../include/name_code.h diff --git a/postfix/src/sendmail/sendmail.c b/postfix/src/sendmail/sendmail.c index 0f9e580b8..f4f9d8df6 100644 --- a/postfix/src/sendmail/sendmail.c +++ b/postfix/src/sendmail/sendmail.c @@ -446,7 +446,6 @@ #include #include #include -#include #include #include #include @@ -459,7 +458,6 @@ #include #include #include -#include #include #include #include @@ -473,6 +471,7 @@ #include #include #include +#include /* Global library. */ @@ -1049,15 +1048,15 @@ int main(int argc, char **argv) debug_me = 1; /* - * Initialize. Set up logging, read the global configuration file and - * extract configuration information. Set up signal handlers so that we - * can clean up incomplete output. + * Initialize. Set up logging. Read the global configuration file after + * command-line processing. Set up signal handlers so that we can clean + * up incomplete output. */ if ((slash = strrchr(argv[0], '/')) != 0 && slash[1]) argv[0] = slash + 1; msg_vstream_init(argv[0], VSTREAM_ERR); msg_cleanup(tempfail); - msg_syslog_init(mail_task("sendmail"), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task("sendmail"), MAILLOG_CLIENT_FLAG_NONE); set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0])); /* @@ -1112,7 +1111,7 @@ int main(int argc, char **argv) update_env(import_env->argv); argv_free(import_env); /* Re-evaluate mail_task() after reading main.cf. */ - msg_syslog_init(mail_task("sendmail"), LOG_PID, LOG_FACILITY); + maillog_client_init(mail_task("sendmail"), MAILLOG_CLIENT_FLAG_NONE); get_mail_conf_str_table(str_table); mail_dict_init(); diff --git a/postfix/src/tls/Makefile.in b/postfix/src/tls/Makefile.in index f36c17a41..9f4a8f144 100644 --- a/postfix/src/tls/Makefile.in +++ b/postfix/src/tls/Makefile.in @@ -47,19 +47,18 @@ tests: tls_certkey_tests tls_certkey_tests: test @echo Testing loading of keys and certs - @export LD_LIBRARY_PATH=../../lib; \ - for pem in goodchains.pem; do \ - ./tls_certkey $$pem > $$pem.out 2>&1 || exit 1; \ + @for pem in goodchains.pem; do \ + $(SHLIB_ENV) $(VALGRIND) ./tls_certkey $$pem > $$pem.out 2>&1 || exit 1; \ diff $$pem.ref $$pem.out || exit 1; \ echo " $$pem: OK"; \ done; \ for pem in *-mixed-*.pem ; do \ - ./tls_certkey -m $$pem > $$pem.out 2>&1 || exit 1; \ + $(SHLIB_ENV) $(VALGRIND) ./tls_certkey -m $$pem > $$pem.out 2>&1 || exit 1; \ diff $$pem.ref $$pem.out || exit 1; \ echo " $$pem: OK"; \ done; \ for pem in bad-*.pem; do \ - ./tls_certkey $$pem > $$pem.out 2>&1 && exit 1 || : ok; \ + $(SHLIB_ENV) $(VALGRIND) ./tls_certkey $$pem > $$pem.out 2>&1 && exit 1 || : ok; \ egrep -v 'TLS library problem' $$pem.out | diff $$pem.ref - || \ exit 1; \ echo " $$pem: OK"; \ diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in index dec308109..381bb6e13 100644 --- a/postfix/src/util/Makefile.in +++ b/postfix/src/util/Makefile.in @@ -40,7 +40,8 @@ SRCS = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \ poll_fd.c timecmp.c slmdb.c dict_pipe.c dict_random.c \ valid_utf8_hostname.c midna_domain.c argv_splitq.c balpar.c dict_union.c \ extpar.c dict_inline.c casefold.c dict_utf8.c strcasecmp_utf8.c \ - split_qnameval.c argv_attr_print.c argv_attr_scan.c dict_file.c + split_qnameval.c argv_attr_print.c argv_attr_scan.c dict_file.c \ + msg_logger.c logwriter.c unix_dgram_connect.c unix_dgram_listen.c OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \ attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \ attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \ @@ -82,7 +83,8 @@ OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \ poll_fd.o timecmp.o $(NON_PLUGIN_MAP_OBJ) dict_pipe.o dict_random.o \ valid_utf8_hostname.o midna_domain.o argv_splitq.o balpar.o dict_union.o \ extpar.o dict_inline.o casefold.o dict_utf8.o strcasecmp_utf8.o \ - split_qnameval.o argv_attr_print.o argv_attr_scan.o dict_file.o + split_qnameval.o argv_attr_print.o argv_attr_scan.o dict_file.o \ + msg_logger.o logwriter.o unix_dgram_connect.o unix_dgram_listen.o # MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf. # When hard-linking these, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ), # otherwise it sets the PLUGIN_* macros. @@ -112,7 +114,7 @@ HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \ dict_fail.h warn_stat.h dict_sockmap.h line_number.h timecmp.h \ slmdb.h compat_va_copy.h dict_pipe.h dict_random.h \ valid_utf8_hostname.h midna_domain.h dict_union.h dict_inline.h \ - check_arg.h argv_attr.h + check_arg.h argv_attr.h msg_logger.h logwriter.h TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \ stream_test.c dup2_pass_on_exec.c DEFS = -I. -D$(SYSTYPE) @@ -132,7 +134,7 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \ myaddrinfo myaddrinfo4 inet_proto sane_basename format_tv \ valid_utf8_string ip_match base32_code msg_rate_delay netstring \ vstream timecmp dict_cache midna_domain casefold strcasecmp_utf8 \ - vbuf_print split_qnameval vstream + vbuf_print split_qnameval vstream msg_logger PLUGIN_MAP_SO = $(LIB_PREFIX)pcre$(LIB_SUFFIX) LIB_DIR = ../../lib @@ -217,6 +219,11 @@ vstring: $(LIB) $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) mv junk $@.o +msg_logger: msg_logger.c $(LIB) + mv $@.o junk + $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) + mv junk $@.o + msg_syslog: msg_syslog.c $(LIB) mv $@.o junk $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) @@ -1906,6 +1913,17 @@ load_lib.o: load_lib.c load_lib.o: load_lib.h load_lib.o: msg.h load_lib.o: sys_defs.h +logwriter.o: check_arg.h +logwriter.o: iostuff.h +logwriter.o: logwriter.c +logwriter.o: logwriter.h +logwriter.o: msg.h +logwriter.o: mymalloc.h +logwriter.o: safe_open.h +logwriter.o: sys_defs.h +logwriter.o: vbuf.h +logwriter.o: vstream.h +logwriter.o: vstring.h lowercase.o: check_arg.h lowercase.o: lowercase.c lowercase.o: stringops.h @@ -1996,6 +2014,20 @@ msg.o: msg.c msg.o: msg.h msg.o: msg_output.h msg.o: sys_defs.h +msg_logger.o: check_arg.h +msg_logger.o: connect.h +msg_logger.o: iostuff.h +msg_logger.o: logwriter.h +msg_logger.o: msg.h +msg_logger.o: msg_logger.c +msg_logger.o: msg_logger.h +msg_logger.o: msg_output.h +msg_logger.o: mymalloc.h +msg_logger.o: safe.h +msg_logger.o: sys_defs.h +msg_logger.o: vbuf.h +msg_logger.o: vstream.h +msg_logger.o: vstring.h msg_output.o: check_arg.h msg_output.o: msg_output.c msg_output.o: msg_output.h @@ -2019,6 +2051,7 @@ msg_syslog.o: msg.h msg_syslog.o: msg_output.h msg_syslog.o: msg_syslog.c msg_syslog.o: msg_syslog.h +msg_syslog.o: mymalloc.h msg_syslog.o: safe.h msg_syslog.o: stringops.h msg_syslog.o: sys_defs.h @@ -2410,6 +2443,17 @@ unix_connect.o: sane_connect.h unix_connect.o: sys_defs.h unix_connect.o: timed_connect.h unix_connect.o: unix_connect.c +unix_dgram_connect.o: connect.h +unix_dgram_connect.o: iostuff.h +unix_dgram_connect.o: msg.h +unix_dgram_connect.o: sys_defs.h +unix_dgram_connect.o: unix_dgram_connect.c +unix_dgram_listen.o: htable.h +unix_dgram_listen.o: iostuff.h +unix_dgram_listen.o: listen.h +unix_dgram_listen.o: msg.h +unix_dgram_listen.o: sys_defs.h +unix_dgram_listen.o: unix_dgram_listen.c unix_listen.o: htable.h unix_listen.o: iostuff.h unix_listen.o: listen.h diff --git a/postfix/src/util/connect.h b/postfix/src/util/connect.h index 080b99c06..1e8de1143 100644 --- a/postfix/src/util/connect.h +++ b/postfix/src/util/connect.h @@ -22,6 +22,7 @@ extern int unix_connect(const char *, int, int); extern int inet_connect(const char *, int, int); extern int stream_connect(const char *, int, int); +extern int unix_dgram_connect(const char *, int); /* LICENSE /* .ad @@ -32,6 +33,11 @@ extern int stream_connect(const char *, int, int); /* 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 /*--*/ #endif diff --git a/postfix/src/util/listen.h b/postfix/src/util/listen.h index cb73a33cf..131755c30 100644 --- a/postfix/src/util/listen.h +++ b/postfix/src/util/listen.h @@ -24,6 +24,7 @@ extern int unix_listen(const char *, int, int); extern int inet_listen(const char *, int, int); extern int fifo_listen(const char *, int, int); extern int stream_listen(const char *, int, int); +extern int unix_dgram_listen(const char *, int); extern int inet_accept(int); extern int unix_accept(int); diff --git a/postfix/src/util/logwriter.c b/postfix/src/util/logwriter.c new file mode 100644 index 000000000..aea2767f8 --- /dev/null +++ b/postfix/src/util/logwriter.c @@ -0,0 +1,124 @@ +/*++ +/* NAME +/* logwriter 3 +/* SUMMARY +/* logfile writer +/* SYNOPSIS +/* #include +/* +/* VSTREAM *logwriter_open_or_die( +/* const char *path) +/* +/* int logwriter_write( +/* VSTREAM *file, +/* const char *buffer. +/* ssize_t buflen) +/* +/* int logwriter_close( +/* VSTREAM *file) +/* +/* int logwriter_one_shot( +/* const char *path, +/* const char *buffer, +/* ssize_t buflen) +/* DESCRIPTION +/* This module manages a logfile writer. +/* +/* logwriter_open_or_die() safely opens the specified file in +/* write+append mode. File open/create errors are fatal. +/* +/* logwriter_write() writes the buffer plus newline to the +/* open logfile. The result is zero if successful, VSTREAM_EOF +/* if the operation failed. +/* +/* logwriter_close() closes the logfile and destroys the VSTREAM +/* instance. The result is zero if there were no errors writing +/* the file, VSTREAM_EOF otherwise. +/* +/* logwriter_one_shot() combines all the above operations. The +/* result is zero if successful, VSTREAM_EOF if any operation +/* failed. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/*--*/ + + /* + * System library. + */ +#include +#include +#include +#include + + /* + * Utility library. + */ +#include +#include +#include +#include +#include +#include + + /* + * Application-specific. + */ + +/* logwriter_open_or_die - open logfile */ + +VSTREAM *logwriter_open_or_die(const char *path) +{ + VSTREAM *fp; + VSTRING *why = vstring_alloc(100); + +#define NO_STATP ((struct stat *) 0) +#define NO_CHOWN (-1) +#define NO_CHGRP (-1) + + fp = safe_open(path, O_CREAT | O_WRONLY | O_APPEND, 0644, + NO_STATP, NO_CHOWN, NO_CHGRP, why); + if (fp == 0) + msg_fatal("open logfile '%s': %s", path, vstring_str(why)); + close_on_exec(vstream_fileno(fp), CLOSE_ON_EXEC); + vstring_free(why); + return (fp); +} + +/* logwriter_write - append to logfile */ + +int logwriter_write(VSTREAM *fp, const char *buf, ssize_t len) +{ + if (len < 0) + msg_panic("logwriter_write: negative length %ld", (long) len); + if (vstream_fwrite(fp, buf, len) != len) + return (VSTREAM_EOF); + VSTREAM_PUTC('\n', fp); + return (vstream_fflush(fp)); +} + +/* logwriter_close - close logfile */ + +int logwriter_close(VSTREAM *fp) +{ + return (vstream_fclose(fp)); +} + +/* logwriter_one_shot - one-shot logwriter */ + +int logwriter_one_shot(const char *path, const char *buf, ssize_t len) +{ + VSTREAM *fp; + int err; + + fp = logwriter_open_or_die(path); + err = logwriter_write(fp, buf, len); + err |= logwriter_close(fp); + return (err ? VSTREAM_EOF : 0); +} diff --git a/postfix/src/util/logwriter.h b/postfix/src/util/logwriter.h new file mode 100644 index 000000000..f5266e4b7 --- /dev/null +++ b/postfix/src/util/logwriter.h @@ -0,0 +1,38 @@ +#ifndef _LOGWRITER_H_INCLUDED_ +#define _LOGWRITER_H_INCLUDED_ + +/*++ +/* NAME +/* logwriter 3h +/* SUMMARY +/* logfile writer +/* SYNOPSIS +/* #include +/* DESCRIPTION +/* .nf + + /* + * Utility library. + */ +#include + + /* + * External interface. + */ +extern VSTREAM *logwriter_open_or_die(const char *); +extern int logwriter_write(VSTREAM *, const char *, ssize_t); +extern int logwriter_close(VSTREAM *); +extern int logwriter_one_shot(const char *, const char *, ssize_t); + +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/*--*/ + +#endif diff --git a/postfix/src/util/msg_logger.c b/postfix/src/util/msg_logger.c new file mode 100644 index 000000000..7c8f34dd6 --- /dev/null +++ b/postfix/src/util/msg_logger.c @@ -0,0 +1,347 @@ +/*++ +/* NAME +/* msg_logger 3 +/* SUMMARY +/* direct diagnostics to logger service +/* SYNOPSIS +/* #include +/* +/* void msg_logger_init( +/* const char *progname, +/* const char *hostname, +/* const char *unix_path, +/* void (*fallback)(const char *)) +/* +/* void msg_logger_control( +/* int key,...) +/* DESCRIPTION +/* This module implements support to report msg(3) diagnostics +/* through a logger daemon, with an optional fallback mechanism. +/* The log record format is like traditional syslog: +/* +/* .nf +/* Mmm dd host progname[pid]: text... +/* .fi +/* +/* msg_logger_init() arranges that subsequent msg(3) calls +/* will write to an internal logging service. This function +/* may also be used to update msg_logger settings. +/* +/* Arguments: +/* .IP progname +/* The program name that is prepended to a log record. +/* .IP hostname +/* The host name that is prepended to a log record. Only the +/* first hostname label will be used. +/* .IP unix_path +/* Pathname of a unix-domain datagram service endpoint. A +/* typical use case is the pathname of the postlog socket. +/* .IP fallback +/* Null pointer, or pointer to function that will be called +/* with a formatted message when the logger service is not +/* (yet) available. A typical use case is to pass the record +/* to the logwriter(3) module. +/* .PP +/* msg_logger_control() makes adjustments to the msg_logger +/* client. These adjustments remain in effect until the next +/* msg_logger_init() or msg_logger_control() call. The arguments +/* are a list of macros with zero or more arguments, terminated +/* with CA_MSG_LOGGER_CTL_END which has none. The following +/* lists the names and the types of the corresponding value +/* arguments. +/* +/* Arguments: +/* .IP CA_MSG_LOGGER_CTL_FALLBACK_ONLY +/* Disable the logging socket, and use the fallback function +/* only. This remains in effect until the next msg_logger_init() +/* call. +/* .IP CA_MSG_LOGGER_CTL_FALLBACK(void (*)(const char *)) +/* Override the fallback setting (see above) with the specified +/* function pointer. This remains in effect until the next +/* msg_logger_init() or msg_logger_control() call. +/* .IP CA_MSG_LOGGER_CTL_DISABLE +/* Disable the msg_logger. This remains in effect until the +/* next msg_logger_init() call. +/* SEE ALSO +/* msg(3) diagnostics module +/* BUGS +/* Output records are truncated to ~2000 characters, because +/* unlimited logging is a liability. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/*--*/ + + /* + * System libraries. + */ +#include +#include +#include +#include +#include +#include + + /* + * Application-specific. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + + /* + * Saved state from msg_logger_init(). + */ +static char *msg_logger_progname; +static char *msg_logger_hostname; +static char *msg_logger_unix_path; +static void (*msg_logger_fallback_fn) (const char *); +static int msg_logger_fallback_only_override = 0; +static int msg_logger_enable = 0; + + /* + * Other state. + */ +#define MSG_LOGGER_SOCK_NONE (-1) + +static VSTRING *msg_logger_buf; +static int msg_logger_sock = MSG_LOGGER_SOCK_NONE; + + /* + * Safety limit. + */ +#define MSG_LOGGER_RECLEN 2000 + + /* + * SLMs. + */ +#define STR(x) vstring_str(x) +#define LEN(x) VSTRING_LEN(x) + + +/* msg_logger_print - log info to service or file */ + +static void msg_logger_print(int level, const char *text) +{ + time_t now; + struct tm *lt; + ssize_t len; + + /* + * This test is simple enough that we don't bother with unregistering the + * msg_logger_print() function. + */ + if (msg_logger_enable == 0) + return; + + /* + * TODO: this should be a reusable NAME_CODE table plus lookup function. + */ + static int log_level[] = { + MSG_INFO, MSG_WARN, MSG_ERROR, MSG_FATAL, MSG_PANIC, + }; + static char *severity_name[] = { + "info", "warning", "error", "fatal", "panic", + }; + + /* + * Note: there is code in postlogd(8) that attempts to strip off + * information that is prepended here. If the formatting below is + * changed, then postlogd needs to be updated as well. + */ + + /* + * Format the time stamp. + */ + if (time(&now) < 0) + msg_fatal("no time: %m"); + lt = localtime(&now); + VSTRING_RESET(msg_logger_buf); + if ((len = strftime(vstring_str(msg_logger_buf), + vstring_avail(msg_logger_buf), + "%b %d %H:%M:%S ", lt)) == 0) + msg_fatal("strftime: %m"); + vstring_set_payload_size(msg_logger_buf, len); + + /* + * Format the host name (first name label only). + */ + vstring_sprintf_append(msg_logger_buf, "%.*s ", + (int) strcspn(msg_logger_hostname, "."), + msg_logger_hostname); + + /* + * Format the message. + */ + if (level < 0 || level >= (int) (sizeof(log_level) / sizeof(log_level[0]))) + msg_panic("msg_logger_print: invalid severity level: %d", level); + + if (level == MSG_INFO) { + vstring_sprintf_append(msg_logger_buf, "%s[%ld]: %.*s", + msg_logger_progname, (long) getpid(), + (int) MSG_LOGGER_RECLEN, text); + } else { + vstring_sprintf_append(msg_logger_buf, "%s[%ld]: %s: %.*s", + msg_logger_progname, (long) getpid(), + severity_name[level], (int) MSG_LOGGER_RECLEN, text); + } + + /* + * Connect to logging service, or fall back to direct log. Many systems + * will report ENOENT if the endpoint does not exist, ECONNREFUSED if no + * server has opened the endpoint. + */ + if (msg_logger_fallback_only_override == 0 + && msg_logger_sock == MSG_LOGGER_SOCK_NONE) { + msg_logger_sock = unix_dgram_connect(msg_logger_unix_path, BLOCKING); + if (msg_logger_sock >= 0) + close_on_exec(msg_logger_sock, CLOSE_ON_EXEC); + } + if (msg_logger_sock != MSG_LOGGER_SOCK_NONE) { + send(msg_logger_sock, STR(msg_logger_buf), LEN(msg_logger_buf), 0); + } else if (msg_logger_fallback_fn) { + msg_logger_fallback_fn(STR(msg_logger_buf)); + } +} + +/* msg_logger_init - initialize */ + +void msg_logger_init(const char *progname, const char *hostname, + const char *unix_path, void (*fallback) (const char *)) +{ + static int first_call = 1; + extern char **environ; + + /* + * XXX If this program is set-gid, then TZ must not be trusted. This + * scrubbing code is in the wrong place. + */ + if (first_call) { + if (unsafe()) + while (getenv("TZ")) /* There may be multiple. */ + if (unsetenv("TZ") < 0) { /* Desperate measures. */ + environ[0] = 0; + msg_fatal("unsetenv: %m"); + } + tzset(); + } + + /* + * Save the request info. Use free-after-update because this data will be + * accessed when mystrdup() runs out of memory. + */ +#define UPDATE_AND_FREE(dst, src) do { \ + if ((dst) == 0 || strcmp((dst), (src)) != 0) { \ + char *_bak = (dst); \ + (dst) = mystrdup(src); \ + if ((_bak)) myfree(_bak); \ + } \ + } while (0) + + UPDATE_AND_FREE(msg_logger_progname, progname); + UPDATE_AND_FREE(msg_logger_hostname, hostname); + UPDATE_AND_FREE(msg_logger_unix_path, unix_path); + msg_logger_fallback_fn = fallback; + + /* + * One-time activity: register the output handler, and allocate a buffer. + */ + if (first_call) { + first_call = 0; + msg_output(msg_logger_print); + msg_logger_buf = vstring_alloc(2048); + } + + /* + * Always. + */ + msg_logger_enable = 1; + msg_logger_fallback_only_override = 0; +} + +/* msg_logger_control - tweak the client */ + +void msg_logger_control(int name,...) +{ + const char *myname = "msg_logger_control"; + va_list ap; + + /* + * Overrides remain in effect until the next msg_logger_init() or + * msg_logger_control() call, + */ + for (va_start(ap, name); name != MSG_LOGGER_CTL_END; name = va_arg(ap, int)) { + switch (name) { + case MSG_LOGGER_CTL_FALLBACK_ONLY: + msg_logger_fallback_only_override = 1; + if (msg_logger_sock != MSG_LOGGER_SOCK_NONE) { + (void) close(msg_logger_sock); + msg_logger_sock = MSG_LOGGER_SOCK_NONE; + } + break; + case MSG_LOGGER_CTL_FALLBACK_FN: + msg_logger_fallback_fn = va_arg(ap, MSG_LOGGER_FALLBACK_FN); + break; + case MSG_LOGGER_CTL_DISABLE: + msg_logger_enable = 0; + break; + default: + msg_panic("%s: bad name %d", myname, name); + } + } + va_end(ap); +} + +#ifdef TEST + + /* + * Proof-of-concept program to test the msg_logger module. + * + * Usage: msg_logger hostname unix_path fallback_path text... + */ +static char *fallback_path; + +static void fallback(const char *msg) +{ + if (logwriter_one_shot(fallback_path, msg) != 0) + msg_fatal("unable to fall back to directly write %s: %m", + fallback_path); +} + +int main(int argc, char **argv) +{ + VSTRING *vp = vstring_alloc(256); + + if (argc < 4) + msg_fatal("usage: %s host port path text to log", argv[0]); + msg_logger_init(argv[0], argv[1], argv[2], fallback); + fallback_path = argv[3]; + argc -= 3; + argv += 3; + while (--argc && *++argv) { + vstring_strcat(vp, *argv); + if (argv[1]) + vstring_strcat(vp, " "); + } + msg_warn("static text"); + msg_warn("dynamic text: >%s<", vstring_str(vp)); + msg_warn("dynamic numeric: >%d<", 42); + msg_warn("error text: >%m<"); + msg_warn("dynamic: >%s<: error: >%m<", vstring_str(vp)); + vstring_free(vp); + return (0); +} + +#endif diff --git a/postfix/src/util/msg_logger.h b/postfix/src/util/msg_logger.h new file mode 100644 index 000000000..e135e7e38 --- /dev/null +++ b/postfix/src/util/msg_logger.h @@ -0,0 +1,60 @@ +#ifndef _MSG_LOGGER_H_INCLUDED_ +#define _MSG_LOGGER_H_INCLUDED_ + +/*++ +/* NAME +/* msg_logger 3h +/* SUMMARY +/* direct diagnostics to logger service +/* SYNOPSIS +/* #include +/* DESCRIPTION +/* .nf + + /* + * System library. + */ +#include + + /* + * Utility library. + */ +#include + + /* + * External interface. + */ +typedef void (*MSG_LOGGER_FALLBACK_FN) (const char *); + +extern void msg_logger_init(const char *, const char *, const char *, + MSG_LOGGER_FALLBACK_FN); +extern void msg_logger_control(int,...); + +/* Internal-only API: type-unchecked arguments. */ +#define MSG_LOGGER_CTL_END 0 +#define MSG_LOGGER_CTL_FALLBACK_ONLY 1 +#define MSG_LOGGER_CTL_FALLBACK_FN 2 +#define MSG_LOGGER_CTL_DISABLE 3 + +/* Safer API: type-checked arguments, external use. */ +#define CA_MSG_LOGGER_CTL_END MSG_LOGGER_CTL_END +#define CA_MSG_LOGGER_CTL_FALLBACK_ONLY MSG_LOGGER_CTL_FALLBACK_ONLY +#define CA_MSG_LOGGER_CTL_FALLBACK_FN(v) \ + MSG_LOGGER_CTL_FALLBACK_FN, CHECK_VAL(MSG_LOGGER_CTL, \ + MSG_LOGGER_FALLBACK_FN, (v)) +#define CA_MSG_LOGGER_CTL_DISABLE MSG_LOGGER_CTL_DISABLE + +CHECK_VAL_HELPER_DCL(MSG_LOGGER_CTL, MSG_LOGGER_FALLBACK_FN); + +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/*--*/ + +#endif diff --git a/postfix/src/util/msg_output.c b/postfix/src/util/msg_output.c index 93164bc4f..7031089a9 100644 --- a/postfix/src/util/msg_output.c +++ b/postfix/src/util/msg_output.c @@ -19,10 +19,6 @@ /* int level; /* const char *format; /* va_list ap; -/* -/* void msg_text(level, text) -/* int level; -/* const char *text; /* DESCRIPTION /* This module implements low-level output management for the /* msg(3) diagnostics interface. @@ -79,6 +75,11 @@ /* 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. */ @@ -100,26 +101,31 @@ /* * Global scope, to discourage the compiler from doing smart things. */ -volatile int msg_vprintf_lock; -volatile int msg_text_lock; +volatile int msg_vprintf_level; /* - * Private state. + * Private state. Allow one nested call, so that one logging error can be + * reported to stderr before bailing out. */ +#define MSG_OUT_NESTING_LIMIT 2 static MSG_OUTPUT_FN *msg_output_fn = 0; static int msg_output_fn_count = 0; -static VSTRING *msg_buffer = 0; +static VSTRING *msg_buffers[MSG_OUT_NESTING_LIMIT]; /* msg_output - specify output handler */ void msg_output(MSG_OUTPUT_FN output_fn) { + int i; /* - * Allocate all resources during initialization. + * Allocate all resources during initialization. This may result in a + * recursive call due to memory allocation error. */ - if (msg_buffer == 0) - msg_buffer = vstring_alloc(100); + if (msg_buffers[MSG_OUT_NESTING_LIMIT - 1] == 0) { + for (i = 0; i < MSG_OUT_NESTING_LIMIT; i++) + msg_buffers[i] = vstring_alloc(100); + } /* * We're not doing this often, so avoid complexity and allocate memory @@ -149,40 +155,21 @@ void msg_printf(int level, const char *format,...) void msg_vprintf(int level, const char *format, va_list ap) { int saved_errno = errno; + VSTRING *vp; + int i; - if (msg_vprintf_lock == 0) { - msg_vprintf_lock = 1; - /* On-the-fly initialization for debugging test programs only. */ + if (msg_vprintf_level < MSG_OUT_NESTING_LIMIT) { + msg_vprintf_level += 1; + /* On-the-fly initialization for test programs and startup errors. */ if (msg_output_fn_count == 0) msg_vstream_init("unknown", VSTREAM_ERR); + vp = msg_buffers[msg_vprintf_level - 1]; /* OK if terminating signal handler hijacks control before next stmt. */ - vstring_vsprintf(msg_buffer, percentm(format, errno), ap); - msg_text(level, vstring_str(msg_buffer)); - msg_vprintf_lock = 0; + vstring_vsprintf(vp, percentm(format, errno), ap); + printable(vstring_str(vp), '?'); + for (i = 0; i < msg_output_fn_count; i++) + msg_output_fn[i] (level, vstring_str(vp)); + msg_vprintf_level -= 1; } errno = saved_errno; } - -/* msg_text - sanitize and log pre-formatted text */ - -void msg_text(int level, const char *text) -{ - int i; - - /* - * Sanitize the text. Use a private copy if necessary. - */ - if (msg_text_lock == 0) { - msg_text_lock = 1; - /* OK if terminating signal handler hijacks control before next stmt. */ - if (text != vstring_str(msg_buffer)) - vstring_strcpy(msg_buffer, text); - printable(vstring_str(msg_buffer), '?'); - /* On-the-fly initialization for debugging test programs only. */ - if (msg_output_fn_count == 0) - msg_vstream_init("unknown", VSTREAM_ERR); - for (i = 0; i < msg_output_fn_count; i++) - msg_output_fn[i] (level, vstring_str(msg_buffer)); - msg_text_lock = 0; - } -} diff --git a/postfix/src/util/msg_output.h b/postfix/src/util/msg_output.h index ede7aff41..bd84276f6 100644 --- a/postfix/src/util/msg_output.h +++ b/postfix/src/util/msg_output.h @@ -23,7 +23,6 @@ typedef void (*MSG_OUTPUT_FN) (int, const char *); extern void msg_output(MSG_OUTPUT_FN); extern void PRINTFLIKE(2, 3) msg_printf(int, const char *,...); extern void msg_vprintf(int, const char *, va_list); -extern void msg_text(int, const char *); #define MSG_INFO 0 /* informative */ #define MSG_WARN 1 /* warning (non-fatal) */ @@ -42,6 +41,11 @@ extern void msg_text(int, const char *); /* 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 /*--*/ #endif diff --git a/postfix/src/util/msg_syslog.c b/postfix/src/util/msg_syslog.c index df3394b7b..7c979c66d 100644 --- a/postfix/src/util/msg_syslog.c +++ b/postfix/src/util/msg_syslog.c @@ -11,18 +11,26 @@ /* int log_opt; /* int facility; /* -/* int msg_syslog_facility(facility_name) +/* int msg_syslog_set_facility(facility_name) /* const char *facility_name; +/* +/* void msg_syslog_disable(void) /* DESCRIPTION /* This module implements support to report msg(3) diagnostics /* via the syslog daemon. /* /* msg_syslog_init() is a wrapper around the openlog(3) routine /* that directs subsequent msg(3) output to the syslog daemon. +/* This function may also be called to update msg_syslog +/* settings. If the program name appears to contain a process ID +/* then msg_syslog_init will attempt to suppress its own PID. /* -/* msg_syslog_facility() is a helper routine that overrides the +/* msg_syslog_set_facility() is a helper routine that overrides the /* logging facility that is specified with msg_syslog_init(). /* The result is zero in case of an unknown facility name. +/* +/* msg_syslog_disable() turns off the msg_syslog client, +/* until a subsequent msg_syslog_init() call. /* SEE ALSO /* syslog(3) syslog library /* msg(3) diagnostics module @@ -64,6 +72,7 @@ #include "msg_output.h" #include "msg_syslog.h" #include "safe.h" +#include /* * Stay a little below the 2048-byte limit of older syslog() @@ -143,7 +152,8 @@ static struct facility_list facility_list[] = { 0, }; -static int syslog_facility; +static int msg_syslog_facility; +static int msg_syslog_enable; /* msg_syslog_print - log info to syslog daemon */ @@ -156,14 +166,17 @@ static void msg_syslog_print(int level, const char *text) "info", "warning", "error", "fatal", "panic", }; + if (msg_syslog_enable == 0) + return; + if (level < 0 || level >= (int) (sizeof(log_level) / sizeof(log_level[0]))) msg_panic("msg_syslog_print: invalid severity level: %d", level); if (level == MSG_INFO) { - syslog(syslog_facility | log_level[level], "%.*s", + syslog(msg_syslog_facility | log_level[level], "%.*s", (int) MSG_SYSLOG_RECLEN, text); } else { - syslog(syslog_facility | log_level[level], "%s: %.*s", + syslog(msg_syslog_facility | log_level[level], "%s: %.*s", severity_name[level], (int) MSG_SYSLOG_RECLEN, text); } } @@ -179,35 +192,48 @@ void msg_syslog_init(const char *name, int logopt, int facility) * XXX If this program is set-gid, then TZ must not be trusted. This * scrubbing code is in the wrong place. */ - if (unsafe()) - while (getenv("TZ")) /* There may be multiple. */ - if (unsetenv("TZ") < 0) { /* Desperate measures. */ - environ[0] = 0; - msg_fatal("unsetenv: %m"); - } - tzset(); + if (first_call) { + if (unsafe()) + while (getenv("TZ")) /* There may be multiple. */ + if (unsetenv("TZ") < 0) { /* Desperate measures. */ + environ[0] = 0; + msg_fatal("unsetenv: %m"); + } + tzset(); + } + /* Hack for internal logging forwarding after config change. */ + if (strchr(name, '[') != 0) + logopt &= ~LOG_PID; openlog(name, LOG_NDELAY | logopt, facility); if (first_call) { first_call = 0; msg_output(msg_syslog_print); } + msg_syslog_enable = 1; } -/* msg_syslog_facility - set logging facility by name */ +/* msg_syslog_set_facility - set logging facility by name */ -int msg_syslog_facility(const char *facility_name) +int msg_syslog_set_facility(const char *facility_name) { struct facility_list *fnp; for (fnp = facility_list; fnp->name; ++fnp) { if (!strcmp(fnp->name, facility_name)) { - syslog_facility = fnp->facility; + msg_syslog_facility = fnp->facility; return (1); } } return 0; } +/* msg_syslog_disable - disable the msg_syslog client */ + +void msg_syslog_disable(void) +{ + msg_syslog_enable = 0; +} + #ifdef TEST /* diff --git a/postfix/src/util/msg_syslog.h b/postfix/src/util/msg_syslog.h index 614daaecf..d0441bbd6 100644 --- a/postfix/src/util/msg_syslog.h +++ b/postfix/src/util/msg_syslog.h @@ -19,7 +19,8 @@ * External interface. */ extern void msg_syslog_init(const char *, int, int); -extern int msg_syslog_facility(const char *); +extern int msg_syslog_set_facility(const char *); +extern void msg_syslog_disable(void); /* LICENSE /* .ad @@ -30,6 +31,11 @@ extern int msg_syslog_facility(const char *); /* 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 /*--*/ #endif diff --git a/postfix/src/util/unix_dgram_connect.c b/postfix/src/util/unix_dgram_connect.c new file mode 100644 index 000000000..b3492f731 --- /dev/null +++ b/postfix/src/util/unix_dgram_connect.c @@ -0,0 +1,90 @@ +/*++ +/* NAME +/* unix_dgram_connect 3 +/* SUMMARY +/* connect to UNIX-domain datagram server +/* SYNOPSIS +/* #include +/* +/* int unix_dgram_connect( +/* const char *path, +/* int block_mode) +/* DESCRIPTION +/* unix_dgram_connect() connects to the specified UNIX-domain +/* datagram server, and returns the resulting file descriptor. +/* +/* Arguments: +/* .IP path +/* Null-terminated string with connection destination.` +/* .IP block_mode +/* Either NON_BLOCKING for a non-blocking socket, or BLOCKING for +/* blocking mode. +/* DIAGNOSIICS +/* Fatal errors: path too large, can't create socket. +/* +/* Other errors result in a -1 result value, with errno indicating +/* why the service is unavailable. +/* .sp +/* ENOENT: the named socket does not exist. +/* .sp +/* ECONNREFUSED: the named socket is not open. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/*--*/ + + /* + * System library. + */ +#include +#include +#include +#include +#include + + /* + * Utility library. + */ +#include +#include +#include + +/* unix_dgram_connect - connect to UNIX-domain datagram service */ + +int unix_dgram_connect(const char *path, int block_mode) +{ + const char myname[] = "unix_dgram_connect"; + struct sockaddr_un sun; + ssize_t path_len; + int sock; + + /* + * Translate address information to internal form. + */ + if ((path_len = strlen(path)) >= sizeof(sun.sun_path)) + msg_fatal("%s: unix-domain name too long: %s", myname, path); + memset((void *) &sun, 0, sizeof(sun)); + sun.sun_family = AF_UNIX; +#ifdef HAS_SUN_LEN + sun.sun_len = path_len + 1; +#endif + memcpy(sun.sun_path, path, path_len + 1); + + /* + * Create a client socket. + */ + if ((sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) + msg_fatal("%s: socket: %m", myname); + if (connect(sock, (struct sockaddr *) &sun, sizeof(sun)) < 0) { + close(sock); + return (-1); + } + non_blocking(sock, block_mode); + return (sock); +} diff --git a/postfix/src/util/unix_dgram_listen.c b/postfix/src/util/unix_dgram_listen.c new file mode 100644 index 000000000..3dc677b1e --- /dev/null +++ b/postfix/src/util/unix_dgram_listen.c @@ -0,0 +1,93 @@ +/*++ +/* NAME +/* unix_dgram_listen 3 +/* SUMMARY +/* listen to UNIX-domain datagram server +/* SYNOPSIS +/* #include +/* +/* int unix_dgram_listen( +/* const char *path, +/* int block_mode) +/* DESCRIPTION +/* unix_dgram_listen() binds to the specified UNIX-domain +/* datagram endpoint, and returns the resulting file descriptor. +/* +/* Arguments: +/* .IP path +/* Null-terminated string with connection destination. +/* .IP backlog +/* Either NON_BLOCKING for a non-blocking socket, or BLOCKING for +/* blocking mode. +/* DIAGNOSIICS +/* Fatal errors: path too large, can't create socket. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/*--*/ + + /* + * System library. + */ +#include +#include +#include +#include +#include +#include +#include + + /* + * Utility library. + */ +#include +#include +#include + +/* unix_dgram_listen - bind to UNIX-domain datagram endpoint */ + +int unix_dgram_listen(const char *path, int block_mode) +{ + const char myname[] = "unix_dgram_listen"; +#undef sun + struct sockaddr_un sun; + ssize_t path_len; + int sock; + + /* + * Translate address information to internal form. + */ + if ((path_len = strlen(path)) >= sizeof(sun.sun_path)) + msg_fatal("%s: unix-domain name too long: %s", myname, path); + memset((void *) &sun, 0, sizeof(sun)); + sun.sun_family = AF_UNIX; +#ifdef HAS_SUN_LEN + sun.sun_len = path_len + 1; +#endif + memcpy(sun.sun_path, path, path_len + 1); + + /* + * Create a 'server' socket. + */ + if ((sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) + msg_fatal("%s: socket: %m", myname); + if (unlink(path) < 0 && errno != ENOENT) + msg_fatal( "remove %s: %m", path); + if (bind(sock, (struct sockaddr *) & sun, sizeof(sun)) < 0) + msg_fatal( "bind: %s: %m", path); +#ifdef FCHMOD_UNIX_SOCKETS + if (fchmod(sock, 0666) < 0) + msg_fatal("fchmod socket %s: %m", path); +#else + if (chmod(path, 0666) < 0) + msg_fatal("chmod socket %s: %m", path); +#endif + non_blocking(sock, block_mode); + return (sock); +} diff --git a/postfix/src/util/watchdog.c b/postfix/src/util/watchdog.c index 187932a48..3ec1fbc5f 100644 --- a/postfix/src/util/watchdog.c +++ b/postfix/src/util/watchdog.c @@ -74,6 +74,11 @@ /* 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. */ @@ -216,6 +221,8 @@ WATCHDOG *watchdog_create(unsigned timeout, WATCHDOG_FN action, char *context) msg_fatal("%s: pipe: %m", myname); non_blocking(watchdog_pipe[0], NON_BLOCKING); non_blocking(watchdog_pipe[1], NON_BLOCKING); + close_on_exec(watchdog_pipe[0], CLOSE_ON_EXEC); /* Fix 20190126 */ + close_on_exec(watchdog_pipe[1], CLOSE_ON_EXEC); /* Fix 20190126 */ event_enable_read(watchdog_pipe[0], watchdog_read, (void *) 0); } #endif