]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.9-20110814
authorWietse Venema <wietse@porcupine.org>
Sun, 14 Aug 2011 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:37:24 +0000 (06:37 +0000)
19 files changed:
postfix/HISTORY
postfix/WISHLIST
postfix/html/postconf.1.html
postfix/makedefs
postfix/man/man1/postconf.1
postfix/src/global/Makefile.in
postfix/src/global/mail_version.h
postfix/src/global/mypwd.c
postfix/src/global/mypwd.h
postfix/src/global/user_acl.c
postfix/src/local/Makefile.in
postfix/src/local/alias.c
postfix/src/local/dotforward.c
postfix/src/local/include.c
postfix/src/local/mailbox.c
postfix/src/local/recipient.c
postfix/src/postconf/postconf.c
postfix/src/smtpd/smtpd_state.c
postfix/src/util/sys_defs.h

index e2dd02635485d4a52e3e9e34bf31f5c64d82c3c8..ccdbaa2964730c54f3aae243daad58484d279040 100644 (file)
@@ -16850,3 +16850,34 @@ Apologies for any names omitted.
        permit_tls_all_clientcerts, and check_address_map (the last
        one is used in local_header_rewrite_clients only).  File:
        smtpd/smtpd_check.c.
+
+20110729
+
+       Workaround: some getpwnam() and getpwuid() implementations
+       cause mail to bounce ("user unknown") after LDAP etc. lookup
+       error. Postfix now uses POSIX getpwnam_r() and getpwuid_r()
+       where available. Initially, this workaround supports FreeBSD,
+       Solaris and Linux. Files: makedefs, util/sys_defs.h,
+       global/mypwd.[hc], local/alias.c, local/dotforward.c,
+       local/include.c, local/mailbox.c, local/recipient.c.
+
+20110731
+
+       MacOS X 10.5 supports POSIX getpwnam_r() and getpwuid_r()
+       (source: MacOS manpages at www.freebsd.org). If MacOS turns
+       out to make a false promise, then we will undo this change.
+       Files: makedefs, util/sys_defs.h.
+
+20110810
+
+       Cleanup: optimize an optimization to avoid uid->name lookup
+       when all users are authorized with authorized_submit_users,
+       authorized_mailq_users, authorized_flush_users.  File:
+       global/user_acl.c.
+
+20110811
+
+       Workaround: report a {client_connections} Milter macro value
+       of zero instead of garbage, when the remote SMTP client is
+       excluded from connection count limits. Problem reported by
+       Christian Roessner. File: smtpd/smtpd_state,c,
index 0f11b8c6b577b6f9405743a816c2a3142a9c75ac..4c2ee9666ff95c2a8962491260e99bb6ad575bb7 100644 (file)
@@ -8,6 +8,8 @@ Wish list:
 
        Make the rules for how to use close-on-exec more explicit.
 
+       Add SASL / TLS note to BASIC_CONFIGURATION_README.html#relay_from.
+
        Trick from amavisd: save listen socket/fifo/etc state, clear
        their close-on-exec flags, exec the same program file to
        re-initialize (with saved socket state on command line or
index 1e351dcb6e9ebb113e183d0bb9d1b6ef5c967a85..ea7d041443c4b7f9d06400f361957033d33a1dea 100644 (file)
@@ -21,9 +21,9 @@ POSTCONF(1)                                                        POSTCONF(1)
        <b>postconf</b> [<b>-btv</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<i>template</i><b>_</b><i>file</i>]
 
 <b>DESCRIPTION</b>
-       The <a href="postconf.1.html"><b>postconf</b>(1)</a> command displays the actual values of con-
-       figuration  parameters,  changes  configuration  parameter
-       values,  or displays other configuration information about
+       The  <a href="postconf.1.html"><b>postconf</b>(1)</a> command displays the values of configura-
+       tion parameters by default. It can also  change  parameter
+       values,  or  display other configuration information about
        the Postfix mail system.
 
        Options:
@@ -88,8 +88,8 @@ POSTCONF(1)                                                        POSTCONF(1)
               With  Postfix  version  2.8 and later, the <b>-e</b> is no
               longer needed.
 
-       <b>-h</b>     Show parameter values only, not the "<i>name =</i> " label
-              that normally precedes the value.
+       <b>-h</b>     Show parameter values  only;  do  not  prepend  the
+              "<i>name =</i> " label that normally precedes the value.
 
        <b>-l</b>     List  the  names  of  all supported mailbox locking
               methods.  Postfix supports the following methods:
index bdfb150da30aba35c96cdeb3570632ffb769d153..0f83e7275bc4a4a86eab44b75562c290bef28fd9 100644 (file)
@@ -48,6 +48,8 @@
 #      Do not build with PCRE support.
 #      By default, PCRE support is compiled in when the \fBpcre-config\fR
 #      utility is installed.
+# .IP \fB-DNO_POSIX_GETPW_R\fR
+#      Disable support for POSIX getpwnam_r/getpwuid_r.
 # .IP \fB-DNO_SIGSETJMP\fR
 #      Use setjmp()/longjmp() instead of sigsetjmp()/siglongjmp().
 #      By default, Postfix uses sigsetjmp()/siglongjmp() when they
@@ -152,6 +154,8 @@ case "$SYSTEM.$RELEASE" in
                ;;
   OpenBSD.4*)  SYSTYPE=OPENBSD4
                ;;
+  OpenBSD.5*)  SYSTYPE=OPENBSD5
+               ;;
   ekkoBSD.1*)  SYSTYPE=EKKOBSD1
                ;;
    NetBSD.1*)  SYSTYPE=NETBSD1
@@ -184,9 +188,9 @@ case "$SYSTEM.$RELEASE" in
                SYSLIBS="-lresolv -lsocket -lnsl"
                # Stock awk breaks with >10 files.
                test -x /usr/xpg4/bin/awk && AWK=/usr/xpg4/bin/awk
-               # Solaris 2.5 added usleep() and POSIX regular expressions
+               # Solaris 2.5 added usleep(), POSIX regexp, POSIX getpwnam/uid_r
                case $RELEASE in
-                   5.[0-4]) CCARGS="$CCARGS -DMISSING_USLEEP -DNO_POSIX_REGEXP";;
+                   5.[0-4]) CCARGS="$CCARGS -DMISSING_USLEEP -DNO_POSIX_REGEXP -DNO_POSIX_GETPW_R";;
                esac
                # Solaris 8 added IPv6 and /dev/poll
                case $RELEASE in
@@ -454,6 +458,10 @@ ReliantUNIX-?.5.43) SYSTYPE=ReliantUnix543
                 [1-6].*) CCARGS="$CCARGS -DNO_IPV6";;
                       *) CCARGS="$CCARGS -DBIND_8_COMPAT -DNO_NETINFO";;
                esac
+               # Darwin 9.0 (MacOS X 10.5) adds POSIX getpwnam_r/getpwuid_r
+               case $RELEASE in
+                [1-8].*) CCARGS="$CCARGS -DNO_POSIX_GETPW_R";;
+               esac
                # Darwin 10.3.0 no longer has <nameser8_compat.h>.
                case $RELEASE in
                     ?.*) CCARGS="$CCARGS -DRESOLVE_H_NEEDS_NAMESER8_COMPAT_H";;
index 6e57e8d2ee2cb9084097af2b56560729df8dd9e1..eed34eb542c38f07955aa1821e8687773a5e5217 100644 (file)
@@ -24,10 +24,10 @@ Postfix configuration utility
 .SH DESCRIPTION
 .ad
 .fi
-The \fBpostconf\fR(1) command displays the actual values
-of configuration parameters, changes configuration parameter
-values, or displays other configuration information about
-the Postfix mail system.
+The \fBpostconf\fR(1) command displays the values of
+configuration parameters by default. It can also change
+parameter values, or display other configuration information
+about the Postfix mail system.
 
 Options:
 .IP \fB-a\fR
@@ -83,8 +83,8 @@ to protect shell metacharacters and whitespace.
 With Postfix version 2.8 and later, the \fB-e\fR is no
 longer needed.
 .IP \fB-h\fR
-Show parameter values only, not the "\fIname = \fR" label
-that normally precedes the value.
+Show parameter values only; do not prepend the "\fIname =
+\fR" label that normally precedes the value.
 .IP \fB-l\fR
 List the names of all supported mailbox locking methods.
 Postfix supports the following methods:
index 123944275cf773c349034897c3fde37713fb650e..4e168bde929ba5ba92b88e350071ddb17f3cde13 100644 (file)
@@ -2001,12 +2001,12 @@ trace.o: rcpt_print.h
 trace.o: recipient_list.h
 trace.o: trace.c
 trace.o: trace.h
+user_acl.o: ../../include/dict_static.h
 user_acl.o: ../../include/match_list.h
 user_acl.o: ../../include/match_ops.h
 user_acl.o: ../../include/sys_defs.h
 user_acl.o: ../../include/vbuf.h
 user_acl.o: ../../include/vstring.h
-user_acl.o: mail_params.h
 user_acl.o: mypwd.h
 user_acl.o: string_list.h
 user_acl.o: user_acl.c
index 697904f2accee656aa5d9328c2d94c6754f21a80..fc1b0e90ca4176dcc2e18e6dfd111824f738b7bd 100644 (file)
@@ -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      "20110706"
+#define MAIL_RELEASE_DATE      "20110814"
 #define MAIL_VERSION_NUMBER    "2.9"
 
 #ifdef SNAPSHOT
index 2b7821382c1316df88d3cabcc876ed220dd849d8..ef5928120419deb59a9bf30a05e909027d0d1955 100644 (file)
@@ -2,35 +2,53 @@
 /* NAME
 /*     mypwd 3
 /* SUMMARY
-/*     caching getpwnam()/getpwuid()
+/*     caching getpwnam_r()/getpwuid_r()
 /* SYNOPSIS
 /*     #include <mypwd.h>
 /*
-/*     struct mypasswd *mypwuid(uid)
+/*     int     mypwuid_err(uid, pwd)
 /*     uid_t   uid;
+/*     struct mypasswd **pwd;
 /*
-/*     struct mypasswd *mypwnam(name)
+/*     int     mypwnam_err(name, pwd)
 /*     const char *name;
+/*     struct mypasswd **pwd;
 /*
 /*     void    mypwfree(pwd)
 /*     struct mypasswd *pwd;
+/* BACKWARDS COMPATIBILITY
+/*     struct mypasswd *mypwuid(uid)
+/*     uid_t   uid;
+/*
+/*     struct mypasswd *mypwnam(name)
+/*     const char *name;
 /* DESCRIPTION
 /*     This module maintains a reference-counted cache of password
-/*     database lookup results. The idea is to avoid surprises by
-/*     getpwnam() or getpwuid() overwriting a previous result, while
-/*     at the same time avoiding duplicate copies of password
-/*     information in memory, and to avoid making repeated getpwxxx()
-/*     calls for the same information.
+/*     database lookup results. The idea is to avoid making repeated
+/*     getpw*() calls for the same information.
+/*
+/*     mypwnam_err() and mypwuid_err() are wrappers that cache a
+/*     private copy of results from the getpwnam_r() and getpwuid_r()
+/*     library routines (on legacy systems: from getpwnam() and
+/*     getpwuid(). Note: cache updates are not protected by mutex.
 /*
-/*     mypwnam() and mypwuid() are wrappers that cache a private copy
-/*     of results from the getpwnam() and getpwuid() library routines.
 /*     Results are shared between calls with the same \fIname\fR
 /*     or \fIuid\fR argument, so changing results is verboten.
 /*
-/*     mypwfree() cleans up the result of mypwnam() and mypwuid().
+/*     mypwnam() and mypwuid() are binary-compatibility wrappers
+/*     for legacy applications.
+/*
+/*     mypwfree() cleans up the result of mypwnam*() and mypwuid*().
 /* BUGS
 /*     This module is security sensitive and complex at the same
 /*     time, which is bad.
+/* DIAGNOSTICS
+/*     mypwnam_err() and mypwuid_err() return a non-zero system
+/*     error code when the lookup could not be performed. They 
+/*     return zero, plus a null struct mypasswd pointer, when the
+/*     requested information was not found.
+/*
+/*     Fatal error: out of memory.
 /* LICENSE
 /* .ad
 /* .fi
 /* System library. */
 
 #include <sys_defs.h>
-#include <pwd.h>
+#include <unistd.h>
 #include <string.h>
 #ifdef USE_PATHS_H
 #include <paths.h>
 #endif
+#include <errno.h>
 
 /* Utility library. */
 
 
 #include "mypwd.h"
 
+ /*
+  * Workaround: Solaris >= 2.5.1 provides two getpwnam_r() and getpwuid_r()
+  * implementations. The default variant is compatible with historical
+  * Solaris implementations. The non-default variant is POSIX-compliant.
+  * 
+  * To get the POSIX-compliant variant, we include the file <pwd.h> after
+  * defining _POSIX_PTHREAD_SEMANTICS. We do this after all other includes,
+  * so that we won't unexpectedly affect any other APIs.
+  * 
+  * This happens to work because nothing above this includes <pwd.h>, and
+  * because of the specific way that Solaris redefines getpwnam_r() and
+  * getpwuid_r() for POSIX compliance. We know the latter from peeking under
+  * the hood. What we do is only marginally better than directly invoking
+  * __posix_getpwnam_r() and __posix_getpwuid_r().
+  */
+#ifdef GETPW_R_NEEDS_POSIX_PTHREAD_SEMANTICS
+#define _POSIX_PTHREAD_SEMANTICS
+#endif
+#include <pwd.h>
+
  /*
   * The private cache. One for lookups by name, one for lookups by uid, and
-  * one for the last looked up result.
+  * one for the last looked up result. There is a minor problem: multiple
+  * cache entries may have the same uid value, but the cache that is indexed
+  * by uid can store only one entry per uid value.
   */
 static HTABLE *mypwcache_name = 0;
 static BINHASH *mypwcache_uid = 0;
 static struct mypasswd *last_pwd;
 
+ /*
+  * XXX Solaris promises that we can determine the getpw*_r() buffer size by
+  * calling sysconf(_SC_GETPW_R_SIZE_MAX). Many systems promise that they
+  * will return an ERANGE error when the buffer is too small. However, not
+  * all systems make such promises. Therefore, we settle for the dumbest
+  * option: a large buffer. This is acceptable because the buffer is used
+  * only for short-term storage.
+  */
+#ifdef HAVE_POSIX_GETPW_R
+#define GETPW_R_BUFSIZ         1024
+#endif
+#define MYPWD_ERROR_DELAY      (30)
+
 /* mypwenter - enter password info into cache */
 
-static struct mypasswd *mypwenter(struct passwd * pwd)
+static struct mypasswd *mypwenter(const struct passwd * pwd)
 {
     struct mypasswd *mypwd;
 
@@ -92,15 +146,36 @@ static struct mypasswd *mypwenter(struct passwd * pwd)
     mypwd->pw_gecos = mystrdup(pwd->pw_gecos);
     mypwd->pw_dir = mystrdup(pwd->pw_dir);
     mypwd->pw_shell = mystrdup(*pwd->pw_shell ? pwd->pw_shell : _PATH_BSHELL);
+
+    /*
+     * Avoid mypwcache_uid memory leak when multiple names have the same UID.
+     * This makes the lookup result dependent on program history. But, it was
+     * already history-dependent before we added this extra check.
+     */
     htable_enter(mypwcache_name, mypwd->pw_name, (char *) mypwd);
-    binhash_enter(mypwcache_uid, (char *) &mypwd->pw_uid,
-                 sizeof(mypwd->pw_uid), (char *) mypwd);
+    if (binhash_locate(mypwcache_uid, (char *) &mypwd->pw_uid,
+                      sizeof(mypwd->pw_uid)) == 0)
+       binhash_enter(mypwcache_uid, (char *) &mypwd->pw_uid,
+                     sizeof(mypwd->pw_uid), (char *) mypwd);
     return (mypwd);
 }
 
 /* mypwuid - caching getpwuid() */
 
 struct mypasswd *mypwuid(uid_t uid)
+{
+    struct mypasswd *mypwd;
+
+    while ((errno = mypwuid_err(uid, &mypwd)) != 0) {
+       msg_warn("getpwuid_r: %m");
+       sleep(MYPWD_ERROR_DELAY);
+    }
+    return (mypwd);
+}
+
+/* mypwuid_err - caching getpwuid_r(), minus thread safety */
+
+int     mypwuid_err(uid_t uid, struct mypasswd ** result)
 {
     struct passwd *pwd;
     struct mypasswd *mypwd;
@@ -113,30 +188,58 @@ struct mypasswd *mypwuid(uid_t uid)
            mypwfree(last_pwd);
            last_pwd = 0;
        } else {
-           mypwd = last_pwd;
+           *result = mypwd = last_pwd;
            mypwd->refcount++;
-           return (mypwd);
+           return (0);
        }
     }
 
     /*
-     * Find the info in the cache or in the password database. Make a copy,
-     * so that repeated getpwnam() calls will not clobber our result.
+     * Find the info in the cache or in the password database.
      */
     if ((mypwd = (struct mypasswd *)
         binhash_find(mypwcache_uid, (char *) &uid, sizeof(uid))) == 0) {
-       if ((pwd = getpwuid(uid)) == 0)
+#ifdef HAVE_POSIX_GETPW_R
+       char    pwstore[GETPW_R_BUFSIZ];
+       struct passwd pwbuf;
+       int     err;
+
+       err = getpwuid_r(uid, &pwbuf, pwstore, sizeof(pwstore), &pwd);
+       if (err != 0)
+           return (err);
+       if (pwd == 0) {
+           *result = 0;
+           return (0);
+       }
+#else
+       if ((pwd = getpwuid(uid)) == 0) {
+           *result = 0;
            return (0);
+       }
+#endif
        mypwd = mypwenter(pwd);
     }
-    last_pwd = mypwd;
+    *result = last_pwd = mypwd;
     mypwd->refcount += 2;
-    return (mypwd);
+    return (0);
 }
 
 /* mypwnam - caching getpwnam() */
 
 struct mypasswd *mypwnam(const char *name)
+{
+    struct mypasswd *mypwd;
+
+    while ((errno = mypwnam_err(name, &mypwd)) != 0) {
+       msg_warn("getpwnam_r: %m");
+       sleep(MYPWD_ERROR_DELAY);
+    }
+    return (mypwd);
+}
+
+/* mypwnam_err - caching getpwnam_r(), minus thread safety */
+
+int     mypwnam_err(const char *name, struct mypasswd ** result)
 {
     struct passwd *pwd;
     struct mypasswd *mypwd;
@@ -149,24 +252,39 @@ struct mypasswd *mypwnam(const char *name)
            mypwfree(last_pwd);
            last_pwd = 0;
        } else {
-           mypwd = last_pwd;
+           *result = mypwd = last_pwd;
            mypwd->refcount++;
-           return (mypwd);
+           return (0);
        }
     }
 
     /*
-     * Find the info in the cache or in the password database. Make a copy,
-     * so that repeated getpwnam() calls will not clobber our result.
+     * Find the info in the cache or in the password database.
      */
     if ((mypwd = (struct mypasswd *) htable_find(mypwcache_name, name)) == 0) {
-       if ((pwd = getpwnam(name)) == 0)
+#ifdef HAVE_POSIX_GETPW_R
+       char    pwstore[GETPW_R_BUFSIZ];
+       struct passwd pwbuf;
+       int     err;
+
+       err = getpwnam_r(name, &pwbuf, pwstore, sizeof(pwstore), &pwd);
+       if (err != 0)
+           return (err);
+       if (pwd == 0) {
+           *result = 0;
+           return (0);
+       }
+#else
+       if ((pwd = getpwnam(name)) == 0) {
+           *result = 0;
            return (0);
+       }
+#endif
        mypwd = mypwenter(pwd);
     }
-    last_pwd = mypwd;
+    *result = last_pwd = mypwd;
     mypwd->refcount += 2;
-    return (mypwd);
+    return (0);
 }
 
 /* mypwfree - destroy password info */
@@ -176,10 +294,15 @@ void    mypwfree(struct mypasswd * mypwd)
     if (mypwd->refcount < 1)
        msg_panic("mypwfree: refcount %d", mypwd->refcount);
 
+    /*
+     * See mypwenter() for the reason behind the binhash_locate() test.
+     */
     if (--mypwd->refcount == 0) {
        htable_delete(mypwcache_name, mypwd->pw_name, (void (*) (char *)) 0);
-       binhash_delete(mypwcache_uid, (char *) &mypwd->pw_uid,
-                      sizeof(mypwd->pw_uid), (void (*) (char *)) 0);
+       if (binhash_locate(mypwcache_uid, (char *) &mypwd->pw_uid,
+                          sizeof(mypwd->pw_uid)))
+           binhash_delete(mypwcache_uid, (char *) &mypwd->pw_uid,
+                          sizeof(mypwd->pw_uid), (void (*) (char *)) 0);
        myfree(mypwd->pw_name);
        myfree(mypwd->pw_passwd);
        myfree(mypwd->pw_gecos);
@@ -209,8 +332,11 @@ int     main(int argc, char **argv)
     if (argc == 1)
        msg_fatal("usage: %s name or uid ...", argv[0]);
 
-    mypwd = (struct mypasswd **) mymalloc((argc + 1) * sizeof(*mypwd));
+    mypwd = (struct mypasswd **) mymalloc((argc + 2) * sizeof(*mypwd));
 
+    /*
+     * Do a sequence of lookups.
+     */
     for (i = 1; i < argc; i++) {
        if (ISDIGIT(argv[i][0]))
            mypwd[i] = mypwuid(atoi(argv[i]));
@@ -218,14 +344,23 @@ int     main(int argc, char **argv)
            mypwd[i] = mypwnam(argv[i]);
        if (mypwd[i] == 0)
            msg_fatal("%s: not found", argv[i]);
-       msg_info("+ %s link=%d used=%d used=%d", argv[i], mypwd[i]->refcount,
-                mypwcache_name->used, mypwcache_uid->used);
+       msg_info("lookup %s %s/%d refcount=%d name_cache=%d uid_cache=%d",
+                argv[i], mypwd[i]->pw_name, mypwd[i]->pw_uid,
+            mypwd[i]->refcount, mypwcache_name->used, mypwcache_uid->used);
     }
-    for (i = 1; i < argc; i++) {
-       msg_info("- %s link=%d used=%d used=%d", argv[i], mypwd[i]->refcount,
+    mypwd[argc] = last_pwd;
+
+    /*
+     * The following should free all entries.
+     */
+    for (i = 1; i < argc + 1; i++) {
+       msg_info("free %s/%d refcount=%d name_cache=%d uid_cache=%d",
+                mypwd[i]->pw_name, mypwd[i]->pw_uid, mypwd[i]->refcount,
                 mypwcache_name->used, mypwcache_uid->used);
        mypwfree(mypwd[i]);
     }
+    msg_info("name_cache=%d uid_cache=%d",
+            mypwcache_name->used, mypwcache_uid->used);
 
     myfree((char *) mypwd);
     return (0);
index d5f8a892b9272f38f1f010c3faa0780414989709..82f2cd37bb5be52f148ed60105eda9f5824ae8d9 100644 (file)
@@ -5,7 +5,7 @@
 /* NAME
 /*     mypwnam 3h
 /* SUMMARY
-/*     caching getpwnam()/getpwuid()
+/*     caching getpwnam_r()/getpwuid_r()
 /* SYNOPSIS
 /*     #include <mypwd.h>
 /* DESCRIPTION
@@ -25,6 +25,8 @@ struct mypasswd {
     char   *pw_shell;
 };
 
+extern int mypwnam_err(const char *, struct mypasswd **);
+extern int mypwuid_err(uid_t, struct mypasswd **);
 extern struct mypasswd *mypwnam(const char *);
 extern struct mypasswd *mypwuid(uid_t);
 extern void mypwfree(struct mypasswd *);
index 0121c68dd1fc49ef3c1ef01de28e9681a22a3f86..9dd19c0f7e91dea9a988f1f745509c320bbc539e 100644 (file)
 /* Utility library. */
 
 #include <vstring.h>
+#include <dict_static.h>
 
 /* Global library. */
 
 #include <string_list.h>
 #include <mypwd.h>
-#include <mail_params.h>               /* STATIC_ANYONE_ACL */
 
 /* Application-specific. */
 
@@ -69,9 +69,10 @@ const char *check_user_acl_byuid(char *acl, uid_t uid)
 
     /*
      * Optimize for the most common case. This also makes Postfix a little
-     * more robust in the face of local infrastructure failures.
+     * more robust in the face of local infrastructure failures. Note that we
+     * only need to match the "static:" substring, not the result value.
      */
-    if (strcmp(acl, STATIC_ANYONE_ACL) == 0)
+    if (strncmp(acl, DICT_TYPE_STATIC ":", sizeof(DICT_TYPE_STATIC)) == 0)
        return (0);
 
     /*
@@ -89,6 +90,10 @@ const char *check_user_acl_byuid(char *acl, uid_t uid)
      * really suitable for mixing numerical and non-numerical user
      * information, because the numerical match is done in a separate pass
      * from the non-numerical match. This breaks when the ! operator is used.
+     * 
+     * XXX To avoid waiting until the lookup completes (e.g., LDAP or NIS down)
+     * invoke mypwuid_err(), and either change the user_acl() API to
+     * propagate the error to the caller, or treat lookup errors as fatal.
      */
     if ((mypwd = mypwuid(uid)) == 0) {
        name = "unknown";
index 291664b5aab7bae35163c558147cc6e8af8d577d..503e502e66b4243ef39cc0fc4b4ab7df5ac22f79 100644 (file)
@@ -191,6 +191,7 @@ dotforward.o: ../../include/argv.h
 dotforward.o: ../../include/attr.h
 dotforward.o: ../../include/been_here.h
 dotforward.o: ../../include/bounce.h
+dotforward.o: ../../include/defer.h
 dotforward.o: ../../include/deliver_request.h
 dotforward.o: ../../include/delivered_hdr.h
 dotforward.o: ../../include/dict.h
index 966a5dcb073efbcfe4e5166b8999090de1d7b5f4..a2ead57956fa142f42ea3a10fb45ffaffb15ff1e 100644 (file)
@@ -63,6 +63,7 @@
 #include <unistd.h>
 #include <string.h>
 #include <fcntl.h>
+#include <errno.h>
 
 #ifdef STRCASECMP_IN_STRINGS_H
 #include <strings.h>
@@ -218,8 +219,11 @@ int     deliver_alias(LOCAL_STATE state, USER_ATTR usr_attr,
                                            BOUNCE_ATTR(state.msg_attr));
                    return (YES);
                }
-               if ((alias_pwd = mypwuid(dict->owner.uid)) == 0) {
-                   msg_warn("cannot find alias database owner for %s", *cpp);
+               if ((errno = mypwuid_err(dict->owner.uid, &alias_pwd)) != 0
+                   || alias_pwd == 0) {
+                   msg_warn(errno ?
+                            "cannot find alias database owner for %s: %m" :
+                          "cannot find alias database owner for %s", *cpp);
                    dsb_simple(state.msg_attr.why, "4.3.0",
                               "cannot find alias database owner");
                    *statusp = defer_append(BOUNCE_FLAGS(state.request),
index e26d241ffce753224169bd279d1781586e7a4804..7b7309e40d24e38732cb95699ceff8b0d0ec623b 100644 (file)
@@ -74,6 +74,7 @@
 
 #include <mypwd.h>
 #include <bounce.h>
+#include <defer.h>
 #include <been_here.h>
 #include <mail_params.h>
 #include <mail_conf.h>
@@ -126,7 +127,15 @@ int     deliver_dotforward(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp)
      * Skip non-existing users. The mailbox delivery routine will catch the
      * error.
      */
-    if ((mypwd = mypwnam(state.msg_attr.user)) == 0)
+    if ((errno = mypwnam_err(state.msg_attr.user, &mypwd)) != 0) {
+       msg_warn("error looking up passwd info for %s: %m",
+                state.msg_attr.user);
+       dsb_simple(state.msg_attr.why, "4.0.0", "user lookup error");
+       *statusp = defer_append(BOUNCE_FLAGS(state.request),
+                               BOUNCE_ATTR(state.msg_attr));
+       return (YES);
+    }
+    if (mypwd == 0)
        return (NO);
 
     /*
index 1158832491dfd3083a951a8b0f271974cdfad7fd..a213d3c0888b5d5ca96b3e0b5c8c01163ee9a2ac 100644 (file)
@@ -49,6 +49,7 @@
 #include <unistd.h>
 #include <string.h>
 #include <fcntl.h>
+#include <errno.h>
 
 /* Utility library. */
 
@@ -156,8 +157,9 @@ int     deliver_include(LOCAL_STATE state, USER_ATTR usr_attr, char *path)
      * that is owned by their victim.
      */
     if (usr_attr.uid == 0) {
-       if ((file_pwd = mypwuid(st.st_uid)) == 0) {
-           msg_warn("cannot find username for uid %ld", (long) st.st_uid);
+       if ((errno = mypwuid_err(st.st_uid, &file_pwd)) != 0 || file_pwd == 0) {
+           msg_warn(errno ? "cannot find username for uid %ld: %m" :
+                    "cannot find username for uid %ld", (long) st.st_uid);
            msg_warn("%s: cannot find :include: file owner username", path);
            dsb_simple(state.msg_attr.why, "4.3.5",
                       "mail system configuration error");
index 58b01f79f2fb8f14fdab84ccf42ed893d9d66302..0cfb50e79c12082c0391f792efaf46c7cc391bd5 100644 (file)
@@ -302,8 +302,16 @@ int     deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp)
     /*
      * Skip delivery when this recipient does not exist.
      */
-    if ((mbox_pwd = mypwnam(state.msg_attr.user)) == 0)
-       return (NO);
+    if ((errno = mypwnam_err(state.msg_attr.user, &mbox_pwd)) != 0) {
+        msg_warn("error looking up passwd info for %s: %m",
+                 state.msg_attr.user);
+        dsb_simple(state.msg_attr.why, "4.0.0", "user lookup error");
+        *statusp = defer_append(BOUNCE_FLAGS(state.request),
+                                BOUNCE_ATTR(state.msg_attr));
+        return (YES);
+    }
+    if (mbox_pwd == 0)
+        return (NO);
 
     /*
      * No early returns or we have a memory leak.
index f6f34502c348ce18ea9f24ee58449f221c89307c..19214449366f52e6fad0800500ae91b2a829eee8 100644 (file)
@@ -63,6 +63,7 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <string.h>
+#include <errno.h>
 
 #ifdef STRCASECMP_IN_STRINGS_H
 #include <strings.h>
@@ -179,14 +180,25 @@ static int deliver_switch(LOCAL_STATE state, USER_ATTR usr_attr)
      * $HOME/.forward file, then mailbox delivery. Back off when the user's
      * home directory does not exist.
      */
+    mypwd = 0;
     if (var_stat_home_dir
-       && (mypwd = mypwnam(state.msg_attr.user)) != 0
-       && stat_as(mypwd->pw_dir, &st, mypwd->pw_uid, mypwd->pw_gid) < 0) {
-       dsb_simple(state.msg_attr.why, "4.3.0",
-                  "cannot access home directory %s: %m", mypwd->pw_dir);
+       && (errno = mypwnam_err(state.msg_attr.user, &mypwd)) != 0) {
+       msg_warn("error looking up passwd info for %s: %m",
+                state.msg_attr.user);
+       dsb_simple(state.msg_attr.why, "4.0.0", "user lookup error");
        return (defer_append(BOUNCE_FLAGS(state.request),
                             BOUNCE_ATTR(state.msg_attr)));
     }
+    if (mypwd != 0) {
+       if (stat_as(mypwd->pw_dir, &st, mypwd->pw_uid, mypwd->pw_gid) < 0) {
+           dsb_simple(state.msg_attr.why, "4.3.0",
+                      "cannot access home directory %s: %m", mypwd->pw_dir);
+           mypwfree(mypwd);
+           return (defer_append(BOUNCE_FLAGS(state.request),
+                                BOUNCE_ATTR(state.msg_attr)));
+       }
+       mypwfree(mypwd);
+    }
     if (deliver_dotforward(state, usr_attr, &status) == 0
        && deliver_mailbox(state, usr_attr, &status) == 0)
        status = deliver_unknown(state, usr_attr);
index 2ba32f1063ac4a989d40c6f1ad10a581ca9795e2..6acedeff41ff714e8afa8a1d5349b259116ef591 100644 (file)
 /*
 /*     \fBpostconf\fR [\fB-btv\fR] [\fB-c \fIconfig_dir\fR] [\fItemplate_file\fR]
 /* DESCRIPTION
-/*     The \fBpostconf\fR(1) command displays the actual values
-/*     of configuration parameters, changes configuration parameter
-/*     values, or displays other configuration information about
-/*     the Postfix mail system.
+/*     The \fBpostconf\fR(1) command displays the values of
+/*     configuration parameters by default. It can also change
+/*     parameter values, or display other configuration information
+/*     about the Postfix mail system.
 /*
 /*     Options:
 /* .IP \fB-a\fR
@@ -77,8 +77,8 @@
 /*     With Postfix version 2.8 and later, the \fB-e\fR is no
 /*     longer needed.
 /* .IP \fB-h\fR
-/*     Show parameter values only, not the "\fIname = \fR" label
-/*     that normally precedes the value.
+/*     Show parameter values only; do not prepend the "\fIname =
+/*     \fR" label that normally precedes the value.
 /* .IP \fB-l\fR
 /*     List the names of all supported mailbox locking methods.
 /*     Postfix supports the following methods:
index 98f2f5b830a4102520ebb63709908dc0877208f1..12bca30255fa785597a0d090d4c532e9dea61cec 100644 (file)
@@ -84,6 +84,7 @@ void    smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream,
     state->service = mystrdup(service);
     state->buffer = vstring_alloc(100);
     state->addr_buf = vstring_alloc(100);
+    state->conn_count = state->conn_rate = 0;
     state->error_count = 0;
     state->error_mask = 0;
     state->notify_mask = name_mask(VAR_NOTIFY_CLASSES, mail_error_masks,
index 422219055104404fdfc27ea31e7b460029b1cda2..757e56c69ea1f2e374eb1720c2b6cb001f48b67a 100644 (file)
@@ -28,6 +28,7 @@
     || defined(FREEBSD8) \
     || defined(BSDI2) || defined(BSDI3) || defined(BSDI4) \
     || defined(OPENBSD2) || defined(OPENBSD3) || defined(OPENBSD4) \
+    || defined(OPENBSD5) \
     || defined(NETBSD1) || defined(NETBSD2) || defined(NETBSD3) \
     || defined(NETBSD4) \
     || defined(EKKOBSD1)
 # endif
 #endif
 
+#ifndef NO_POSIX_GETPW_R
+# if (defined(__FreeBSD_version) && __FreeBSD_version >= 510000) \
+    || (defined(__NetBSD_Version__) && __NetBSD_Version__ >= 300000000) \
+    || (defined(OpenBSD) && OpenBSD >= 200811) /* OpenBSD 4.4 */
+#  define HAVE_POSIX_GETPW_R
+# endif
+#endif
+
 #endif
 
  /*
 # define EVENTS_STYLE  EVENTS_STYLE_KQUEUE
 # define USE_SYSV_POLL
 #endif
+#ifndef NO_POSIX_GETPW_R
+# define HAVE_POSIX_GETPW_R
+#endif
 
 #endif
 
@@ -443,6 +455,10 @@ extern int opterr;
 #ifndef NO_DEVPOLL
 # define EVENTS_STYLE  EVENTS_STYLE_DEVPOLL
 #endif
+#ifndef NO_POSIX_GETPW_R
+# define HAVE_POSIX_GETPW_R
+# define GETPW_R_NEEDS_POSIX_PTHREAD_SEMANTICS
+#endif
 
 /*
  * Allow build environment to override paths.
@@ -772,6 +788,16 @@ extern int initgroups(const char *, int);
 # define EVENTS_STYLE  EVENTS_STYLE_EPOLL      /* introduced in 2.5 */
 #endif
 #define USE_SYSV_POLL
+#ifndef NO_POSIX_GETPW_R
+# if (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 1) \
+       || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 1) \
+       || (defined(_BSD_SOURCE) && _BSD_SOURCE >= 1) \
+       || (defined(_SVID_SOURCE) && _SVID_SOURCE >= 1) \
+       || (defined(_POSIX_SOURCE) && _POSIX_SOURCE >= 1)
+#  define HAVE_POSIX_GETPW_R
+# endif
+#endif
+
 #endif
 
 #ifdef LINUX1
@@ -1358,6 +1384,10 @@ typedef int WAIT_STATUS_T;
 #define NORMAL_EXIT_STATUS(status)     ((status) == 0)
 #endif
 
+#ifdef NO_POSIX_GETPW_R
+#undef HAVE_POSIX_GETPW_R
+#endif
+
 #ifndef OCTAL_TO_UNSIGNED
 #define OCTAL_TO_UNSIGNED(res, str)    ((res) = strtoul((str), (char **) 0, 8))
 #endif