]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.3.1 v3.3.1
authorWietse Venema <wietse@porcupine.org>
Sat, 19 May 2018 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Mon, 21 May 2018 20:52:17 +0000 (16:52 -0400)
15 files changed:
postfix/HISTORY
postfix/conf/postfix-script
postfix/html/master.8.html
postfix/html/postfix.1.html
postfix/man/man1/postfix.1
postfix/man/man8/master.8
postfix/src/global/mail_version.h
postfix/src/local/unknown.c
postfix/src/master/master.c
postfix/src/master/master.h
postfix/src/master/master_sig.c
postfix/src/postconf/postconf_dbms.c
postfix/src/postfix/postfix.c
postfix/src/tlsproxy/tlsproxy.c
postfix/src/util/killme_after.c

index f73f89960f000ebf42ef62addbe47df10fa1c650..2aeef0986d6467e4797a0c5aa6b0f6e8f07acd2e 100644 (file)
@@ -23334,3 +23334,33 @@ Apologies for any names omitted.
        built-in or service-defined parameters for ldap, *sql, etc.
        database names. Problem reported by Christian Rößner. Files:
        postconf/postconf_user.c.
+
+20180306
+
+       Bugfix (introduced: 19990302): when luser_relay specifies
+       a non-existent local address, the luser_relay feature becomes
+       a black hole. Reported by Jørgen Thomsen. File: local/unknown.c.
+
+20180422
+
+       Bugfix (introduced: Postfix 2.8): missing tls_server_start()
+       error propagation in tlsproxy(8) resulting in segfault after
+       TLS handshake error. Found during code maintenance. File:
+       tlsproxy/tlsproxy.c.
+
+20180509
+
+       Bugfix (introduced: 20170617): postconf(1) command segfault
+       if unable to open a Postfix database configuration file due
+       to a file permission error. Report by Andreas Hasenack, fix
+       by Viktor Dukhovni.  File: postconf/postconf_dbms.c.
+
+20180519
+
+       Cleanup: Postfix did not support running as a PID=1 process,
+       which complicated Postfix management in containers. The
+       "postfix start-fg" command will now run the Postfix master
+       daemon as a PID=1 process if possible. Thanks to inputs
+       from Andreas Schulze, Eray Aslan, and Viktor Dukhovni.
+       Files: postfix/postfix.c, master/master.c, master/master.h,
+       master/master_sig.c, conf/postfix-script.
index cd77dd9735c368b3949d633fc955229fa5ee37d5..104e7dd1e70fca1ed51e20c8acd464ebf99d6fca 100755 (executable)
@@ -150,11 +150,16 @@ start|start-fg)
            ;;
        start-fg)
            # Foreground start-up is incompatible with multi-instance mode.
-           # We can't use "exec $daemon_directory/master" here: that would
-           # break process group management, and "postfix stop" would kill
-           # too many processes.
+           # Use "exec $daemon_directory/master" only if PID == 1.
+           # Otherwise, doing so would break process group management,
+           # and "postfix stop" would kill too many processes.
            case $instances in
-           "") $daemon_directory/master
+           "") case $$ in
+                1) exec $daemon_directory/master -i
+                   $FATAL "cannot start-fg the master daemon"
+                   exit 1;;
+                *) $daemon_directory/master;;
+               esac
                ;;
             *) $FATAL "start-fg does not support multi_instance_directories"
                exit 1
index 4a064c784e4d70cd76da7a896dda361a6a5531c7..7d52be65cc44c4dcc2996273b8831d1ea3bd3006 100644 (file)
@@ -10,7 +10,7 @@ MASTER(8)                                                            MASTER(8)
        master - Postfix master process
 
 <b>SYNOPSIS</b>
-       <b>master</b> [<b>-Ddtvw</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<b>-e</b> <i>exit</i><b>_</b><i>time</i>]
+       <b>master</b> [<b>-Dditvw</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<b>-e</b> <i>exit</i><b>_</b><i>time</i>]
 
 <b>DESCRIPTION</b>
        The  <a href="master.8.html"><b>master</b>(8)</a> daemon is the resident process that runs Postfix daemons
@@ -47,6 +47,11 @@ MASTER(8)                                                            MASTER(8)
               Terminate the master process after <i>exit</i><b>_</b><i>time</i> seconds. Child pro-
               cesses terminate at their convenience.
 
+       <b>-i</b>     Enable  <b>init</b> 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.
+
        <b>-t</b>     Test  mode.  Return  a zero exit status when the <b>master.pid</b> lock
               file does not exist or when that file is not  locked.   This  is
               evidence that the <a href="master.8.html"><b>master</b>(8)</a> daemon is not running.
index cff351cc3bbb8393ec9eeb4b02538715961c2f23..a83385bc54fccf6de583e279146477048afa9495 100644 (file)
@@ -37,13 +37,14 @@ POSTFIX(1)                                                          POSTFIX(1)
               check described above.
 
        <b>start-fg</b>
-              Like <b>start</b>, but keep the master  daemon  running  in  the  fore-
-              ground.  This  requires  that multi-instance support is disabled
-              (i.e. the <a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a>  parameter  value  must  be
-              empty).  When running Postfix inside a container, mount the con-
-              tainer host's /dev/log socket  inside  the  container  (example:
-              "docker  run  -v /dev/log:/dev/log ...")  and specify a distinct
-              Postfix "<a href="postconf.5.html#syslog_name">syslog_name</a>" prefix that identifies  logging  from  the
+              Like <b>start</b>, but keep the <a href="master.8.html"><b>master</b>(8)</a> daemon running in  the  fore-
+              ground,  and enable <a href="master.8.html"><b>master</b>(8)</a> "init" mode when running as PID 1.
+              This command requires that multi-instance  support  is  disabled
+              (i.e.  the  <a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a>  parameter  value must be
+              empty). When running Postfix inside a container, mount the  con-
+              tainer  host's  /dev/log  socket  inside the container (example:
+              "docker run -v /dev/log:/dev/log ...")  and specify  a  distinct
+              Postfix  "<a href="postconf.5.html#syslog_name">syslog_name</a>"  prefix  that identifies logging from the
               Postfix instance.
 
        <b>stop</b>   Stop the Postfix mail system in an orderly fashion. If possible,
index fa0216050aef23323844e64cbbd7d1ea4f00f106..01c972e88a791a19d425948342c0b5921a934562 100644 (file)
@@ -38,8 +38,10 @@ and create missing directories.
 Start the Postfix mail system. This also runs the configuration
 check described above.
 .IP \fBstart\-fg\fR
-Like \fBstart\fR, but keep the master daemon running in the
-foreground. This requires that multi\-instance support is
+Like \fBstart\fR, but keep the \fBmaster\fR(8) daemon running
+in the foreground, and enable \fBmaster\fR(8) "init" mode
+when running as PID 1.
+This command requires that multi\-instance support is
 disabled (i.e. the multi_instance_directories parameter
 value must be empty). When running Postfix inside a container,
 mount the container host's /dev/log socket inside the
index 1eda9afe799d0821da809a8f2ab2e2a3e2b8a231..6594edc082df3e57801bb05b61970b3ce159b1ce 100644 (file)
@@ -8,7 +8,7 @@ Postfix master process
 .SH "SYNOPSIS"
 .na
 .nf
-\fBmaster\fR [\fB\-Ddtvw\fR] [\fB\-c \fIconfig_dir\fR] [\fB\-e \fIexit_time\fR]
+\fBmaster\fR [\fB\-Dditvw\fR] [\fB\-c \fIconfig_dir\fR] [\fB\-e \fIexit_time\fR]
 .SH DESCRIPTION
 .ad
 .fi
@@ -43,6 +43,12 @@ for debugging only.
 .IP "\fB\-e \fIexit_time\fR"
 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.
 .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
index bf7e94de65b26f25c1a742cab10aff68052a289b..d3d039c406e52ba17551047f2e69df52ad6d70dc 100644 (file)
@@ -20,8 +20,8 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20180221"
-#define MAIL_VERSION_NUMBER    "3.3.0"
+#define MAIL_RELEASE_DATE      "20180519"
+#define MAIL_VERSION_NUMBER    "3.3.1"
 
 #ifdef SNAPSHOT
 #define MAIL_VERSION_DATE      "-" MAIL_RELEASE_DATE
index 733aa1350dbf00fb85048bbf1719b28b2ab9df3a..c97cef39bf1557c17614e32e12f0b5608385b7b4 100644 (file)
 #include <sent.h>
 #include <deliver_pass.h>
 #include <defer.h>
+#include <canon_addr.h>
 
 /* Application-specific. */
 
 #include "local.h"
 
+#define STREQ(x,y) (strcasecmp((x),(y)) == 0)
+
 /* deliver_unknown - delivery for unknown recipients */
 
 int     deliver_unknown(LOCAL_STATE state, USER_ATTR usr_attr)
@@ -85,6 +88,7 @@ int     deliver_unknown(LOCAL_STATE state, USER_ATTR usr_attr)
     const char *myname = "deliver_unknown";
     int     status;
     VSTRING *expand_luser;
+    VSTRING *canon_luser;
     static MAPS *transp_maps;
     const char *map_transport;
 
@@ -139,8 +143,20 @@ int     deliver_unknown(LOCAL_STATE state, USER_ATTR usr_attr)
     if (*var_luser_relay) {
        state.msg_attr.unmatched = 0;
        expand_luser = vstring_alloc(100);
+       canon_luser = vstring_alloc(100);
        local_expand(expand_luser, var_luser_relay, &state, &usr_attr, (void *) 0);
-       status = deliver_resolve_addr(state, usr_attr, STR(expand_luser));
+       /* In case luser_relay specifies a domain-less address. */
+       canon_addr_external(canon_luser, vstring_str(expand_luser));
+       /* Assumes that the address resolver won't change the address. */
+       if (STREQ(vstring_str(canon_luser), state.msg_attr.rcpt.address)) {
+           dsb_simple(state.msg_attr.why, "5.1.1",
+                      "unknown user: \"%s\"", state.msg_attr.user);
+           status = bounce_append(BOUNCE_FLAGS(state.request),
+                                  BOUNCE_ATTR(state.msg_attr));
+       } else {
+           status = deliver_resolve_addr(state, usr_attr, STR(expand_luser));
+       }
+       vstring_free(canon_luser);
        vstring_free(expand_luser);
        return (status);
     }
@@ -149,8 +165,6 @@ int     deliver_unknown(LOCAL_STATE state, USER_ATTR usr_attr)
      * If no alias was found for a required reserved name, toss the message
      * into the bit bucket, and issue a warning instead.
      */
-#define STREQ(x,y) (strcasecmp(x,y) == 0)
-
     if (STREQ(state.msg_attr.user, MAIL_ADDR_MAIL_DAEMON)
        || STREQ(state.msg_attr.user, MAIL_ADDR_POSTMASTER)) {
        msg_warn("required alias not found: %s", state.msg_attr.user);
index 846b2a415a499bd21e01d3e3b07a7bc7d7e2f77e..4d77f1041d738144da2c62e8322b304e187a268a 100644 (file)
@@ -4,7 +4,7 @@
 /* SUMMARY
 /*     Postfix master process
 /* SYNOPSIS
-/*     \fBmaster\fR [\fB-Ddtvw\fR] [\fB-c \fIconfig_dir\fR] [\fB-e \fIexit_time\fR]
+/*     \fBmaster\fR [\fB-Dditvw\fR] [\fB-c \fIconfig_dir\fR] [\fB-e \fIexit_time\fR]
 /* DESCRIPTION
 /*     The \fBmaster\fR(8) daemon is the resident process that runs Postfix
 /*     daemons on demand: daemons to send or receive messages via the
 /* .IP "\fB-e \fIexit_time\fR"
 /*     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.
 /* .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
 #include "master.h"
 
 int     master_detach = 1;
+int     init_mode = 0;
 
 /* master_exit_event - exit for memory leak testing purposes */
 
@@ -334,7 +341,7 @@ int     main(int argc, char **argv)
     /*
      * Process JCL.
      */
-    while ((ch = GETOPT(argc, argv, "c:Dde:tvw")) > 0) {
+    while ((ch = GETOPT(argc, argv, "c:Dde:itvw")) > 0) {
        switch (ch) {
        case 'c':
            if (setenv(CONF_ENV_PATH, optarg, 1) < 0)
@@ -346,6 +353,11 @@ int     main(int argc, char **argv)
        case 'e':
            event_request_timer(master_exit_event, (void *) 0, atoi(optarg));
            break;
+       case 'i':
+           if (getpid() != 1)
+               msg_fatal("-i is allowed only for PID 1 process");
+           init_mode = 1;
+           break;
        case 'D':
            debug_me = 1;
            break;
@@ -375,6 +387,8 @@ int     main(int argc, char **argv)
      */
     if (test_lock && wait_flag)
        msg_fatal("the -t and -w options cannot be used together");
+    if (init_mode && (debug_me || !master_detach || wait_flag))
+       msg_fatal("the -i option cannot be used with -D, -d, or -w");
 
     /*
      * Run a foreground monitor process that returns an exit status of 0 when
@@ -403,7 +417,8 @@ int     main(int argc, char **argv)
      * all MTA processes cleanly. Give up if we can't separate from our
      * parent process. We're not supposed to blow away the parent.
      */
-    if (debug_me == 0 && master_detach != 0 && setsid() == -1 && getsid(0) != getpid())
+    if (init_mode == 0 && debug_me == 0 && master_detach != 0
+       && setsid() == -1 && getsid(0) != getpid())
        msg_fatal("unable to set session and process group ID: %m");
 
     /*
index baf5b143a52c86953881094daa609bcb6e69e726..60f5f81ec5156ea1fc1d3ce79346178575f9a815 100644 (file)
@@ -109,6 +109,7 @@ typedef struct MASTER_PROC {
   * master.c
   */
 extern int master_detach;
+extern int init_mode;
 
  /*
   * master_ent.c
index 81ae7f4606aa4412eee63d8e762216dd2e81a7cc..0560b1ab3efa05f9225fb5c4f1dae7c65639e0de 100644 (file)
@@ -199,6 +199,15 @@ static void master_sigdeath(int sig)
      */
     msg_info("terminating on signal %d", sig);
 
+    /*
+     * Undocumented: when a process runs with PID 1, Linux won't deliver a
+     * signal unless the process specifies a handler (i.e. SIG_DFL is treated
+     * as SIG_IGN).
+     */
+    if (init_mode)
+       /* Don't call exit() from a signal handler. */
+       _exit(0);
+
     /*
      * Deliver the signal to ourselves and clean up. XXX We're running as a
      * signal handler and really should not be doing complicated things...
index 707bafa54f3c1dad8c350fddb34e9a39032c6907..eddeab0a16f3369adea0b4ab193176cd028f02c1 100644 (file)
@@ -174,10 +174,10 @@ static void pcf_check_dbms_client(const PCF_DBMS_INFO *dp, const char *cf_file)
         */
        dict = dict_ht_open(dict_spec, O_CREAT | O_RDWR, 0);
        dict_register(dict_spec, dict);
-       if ((fp = vstream_fopen(cf_file, O_RDONLY, 0)) == 0
-           && errno != EACCES) {
-           msg_warn("open \"%s\" configuration \"%s\": %m",
-                    dp->db_type, cf_file);
+       if ((fp = vstream_fopen(cf_file, O_RDONLY, 0)) == 0) {
+           if (errno != EACCES)
+               msg_warn("open \"%s\" configuration \"%s\": %m",
+                        dp->db_type, cf_file);
            myfree(dict_spec);
            return;
        }
index c9b3174e838591cf7eca14a9d8be001f21b31323..1b7e64feaa66b128fcb8a32b036bd9770ca12272 100644 (file)
 /*     Start the Postfix mail system. This also runs the configuration
 /*     check described above.
 /* .IP \fBstart-fg\fR
-/*     Like \fBstart\fR, but keep the master daemon running in the
-/*     foreground. This requires that multi-instance support is
+/*     Like \fBstart\fR, but keep the \fBmaster\fR(8) daemon running
+/*     in the foreground, and enable \fBmaster\fR(8) "init" mode
+/*     when running as PID 1.
+/*     This command requires that multi-instance support is
 /*     disabled (i.e. the multi_instance_directories parameter
 /*     value must be empty). When running Postfix inside a container,
 /*     mount the container host's /dev/log socket inside the
index 808689c24a15a24fc8aeca2334574e23f2917ea4..2c855ffcc72077fb38a924f68c4de886d23c24ab 100644 (file)
@@ -663,7 +663,7 @@ static void tlsp_ciphertext_event(int event, void *context)
 
 /* tlsp_start_tls - turn on TLS or force disconnect */
 
-static void tlsp_start_tls(TLSP_STATE *state)
+static int tlsp_start_tls(TLSP_STATE *state)
 {
     TLS_SERVER_START_PROPS props;
     static char *cipher_grade;
@@ -716,7 +716,7 @@ static void tlsp_start_tls(TLSP_STATE *state)
 
     if (state->tls_context == 0) {
        tlsp_state_free(state);
-       return;
+       return (-1);
     }
 
     /*
@@ -729,6 +729,7 @@ static void tlsp_start_tls(TLSP_STATE *state)
      * XXX Do we care about certificate verification results? Not as long as
      * postscreen(8) doesn't actually receive email.
      */
+    return (0);
 }
 
 /* tlsp_get_fd_event - receive final postscreen(8) hand-off information */
@@ -776,7 +777,8 @@ static void tlsp_get_fd_event(int event, void *context)
      * Perform the TLS layer before-handshake initialization. We perform the
      * remainder after the TLS handshake completes.
      */
-    tlsp_start_tls(state);
+    if (tlsp_start_tls(state) < 0)
+       return;
 
     /*
      * Trigger the initial proxy server I/Os.
index 1ce06d675b08949554d53333e1e0393dcf3aae23..5d461706f5a15bd4194d04d055f16f9e41441132 100644 (file)
@@ -46,11 +46,17 @@ void    killme_after(unsigned int seconds)
      * Schedule an ALARM signal, and make sure the signal will be delivered
      * even if we are being called from a signal handler and SIGALRM delivery
      * is blocked.
+     * 
+     * Undocumented: when a process runs with PID 1, Linux won't deliver a
+     * signal unless the process specifies a handler (i.e. SIG_DFL is treated
+     * as SIG_IGN). Conveniently, _exit() can be used directly as a signal
+     * handler. This changes the wait status that a parent would see, but in
+     * the case of "init" mode on Linux, no-one would care.
      */
     alarm(0);
     sigemptyset(&sig_action.sa_mask);
     sig_action.sa_flags = 0;
-    sig_action.sa_handler = SIG_DFL;
+    sig_action.sa_handler = (getpid() == 1 ? _exit : SIG_DFL);
     sigaction(SIGALRM, &sig_action, (struct sigaction *) 0);
     alarm(seconds);
     sigaddset(&sig_action.sa_mask, SIGALRM);