]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.5-20071216
authorWietse Venema <wietse@porcupine.org>
Sun, 16 Dec 2007 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:33:43 +0000 (06:33 +0000)
postfix/HISTORY
postfix/RELEASE_NOTES
postfix/html/ldap_table.5.html
postfix/man/man5/ldap_table.5
postfix/proto/ldap_table
postfix/src/global/db_common.c
postfix/src/global/dict_ldap.c
postfix/src/global/mail_version.h
postfix/src/smtp/smtp_chat.c
postfix/src/smtp/smtp_sasl_glue.c
postfix/src/smtp/smtp_sasl_proto.c

index 628bda4cdba170d22886b38e9a46f54857ae2843..a5f766d978210daa2bfe38520e9674506c05ae3d 100644 (file)
@@ -13998,3 +13998,14 @@ Apologies for any names omitted.
 
        Bugfix: qmqpd ignored the qmqpd_client_port_logging parameter
        setting. File: qmqpd/qmqpd.c.
+
+20071216
+
+       Cleanup: show the remote SMTP server port in verbose logging,
+       warnings and postmaster notices.  Still don't show the port
+       in delivery status notifications. Files: smtp/smtp_chat.c,
+       smtp/smtp_sasl_glue.c, smtp/smtp_sasl_proto.c.
+
+       The "tls_require_cert" is now compatible with OpenLDAP 2.1
+       and later. Victor Duchovni. Files: proto/ldap_table,
+       global/dict_ldap.c.
index c87cf65cc990ce752b4e827c5cd78c632ec4aa90..0425bc5b2fc3ba94ebad5c96ee2cd54d913db83f 100644 (file)
@@ -17,6 +17,16 @@ Incompatibility with Postfix 2.3 and earlier
 If you upgrade from Postfix 2.3 or earlier, read RELEASE_NOTES-2.4
 before proceeding.
 
+Incompatibility with Postfix snapshot 20071216
+==============================================
+
+Due to an incompatible API change between OpenLDAP 2.0.11 and 2.0.12,
+an LDAP client compiled for OpenLDAP version <= 2.0.11 will refuse
+to work with an OpenLDAP library version >= 2.0.12 and vice versa.
+
+The SMTP "transcript of session" email now includes the remote SMTP
+server TCP port number.
+
 Incompatibility with Postfix snapshot 20071212
 ==============================================
 
index 9653b1a1f9c0622b0e707b2bc2b8e47e604bc48f..1c0e35f2cefbc2508fd001e08e5eb96b237221b5 100644 (file)
@@ -583,18 +583,56 @@ LDAP_TABLE(5)                                                    LDAP_TABLE(5)
        <b>tls_require_cert (default: no)</b>
               Whether or not to request server's X509 certificate
               and  check  its  validity when establishing SSL/TLS
-              connections.
+              connections.  The supported values are <b>no</b> and  <b>yes</b>.
+
+              With  <b>no</b>, the server certificate trust chain is not
+              checked, but with OpenLDAP  prior  to  2.1.13,  the
+              name in the server certificate must still match the
+              LDAP server name. With OpenLDAP 2.0.0 to 2.0.11 the
+              server  name is not necessarily what you specified,
+              rather it is determined (by  reverse  lookup)  from
+              the  IP address of the LDAP server connection. With
+              OpenLDAP prior  to  2.0.13,  subjectAlternativeName
+              extensions  in  the  LDAP  server  certificate  are
+              ignored: the server name  must  match  the  subject
+              CommonName. The <b>no</b> setting corresponds to the <b>never</b>
+              value of <b>TLS_REQCERT</b> in LDAP  client  configuration
+              files.
+
+              Don't  use  TLS with OpenLDAP 2.0.x (and especially
+              with x &lt;= 11) if you can avoid it.
+
+              With <b>yes</b>, the server certificate must be issued  by
+              a  trusted  CA, and not be expired. The LDAP server
+              name must match one of the  name(s)  found  in  the
+              certificate (see above for OpenLDAP library version
+              dependent behavior). The <b>yes</b> setting corresponds to
+              the <b>demand</b> value of <b>TLS_REQCERT</b> in LDAP client con-
+              figuration files.
+
+              The "try" and "never" values of <b>TLS_REQCERT</b> have no
+              equivalents  here.  They  are  not  available  with
+              OpenLDAP 2.0, and in  any  case  have  questionable
+              security  properties.  Either you want TLS verified
+              LDAP connections, or you don't.
+
+              The <b>yes</b> value only works correctly with Postfix 2.5
+              and  later,  or  with OpenLDAP 2.0. Earlier Postfix
+              releases or  later  OpenLDAP  releases  don't  work
+              together  with  this setting. Support for LDAP over
+              TLS was added to Postfix based on the OpenLDAP  2.0
+              API.
 
        <b>tls_random_file (No default)</b>
-              Path of a file to  obtain  random  bits  from  when
-              /dev/[u]random  is not available, to be used by the
+              Path  of  a  file  to  obtain random bits from when
+              /dev/[u]random is not available, to be used by  the
               client in SSL/TLS connections.
 
        <b>tls_cipher_suite (No default)</b>
               Cipher suite to use in SSL/TLS negotiations.
 
 <b>EXAMPLE</b>
-       Here's a basic example for using LDAP to look up  <a href="local.8.html">local(8)</a>
+       Here's  a basic example for using LDAP to look up <a href="local.8.html">local(8)</a>
        aliases.  Assume that in <a href="postconf.5.html">main.cf</a>, you have:
 
            <a href="postconf.5.html#alias_maps">alias_maps</a> = hash:/etc/aliases,
@@ -605,14 +643,14 @@ LDAP_TABLE(5)                                                    LDAP_TABLE(5)
            server_host = ldap.example.com
            search_base = dc=example, dc=com
 
-       Upon  receiving  mail  for a local address "ldapuser" that
-       isn't found in the  /etc/aliases  database,  Postfix  will
+       Upon receiving mail for a local  address  "ldapuser"  that
+       isn't  found  in  the  /etc/aliases database, Postfix will
        search the LDAP server listening at port 389 on ldap.exam-
-       ple.com.  It will bind anonymously, search for any  direc-
-       tory  entries  whose  mailacceptinggeneralid  attribute is
+       ple.com.   It will bind anonymously, search for any direc-
+       tory entries  whose  mailacceptinggeneralid  attribute  is
        "ldapuser", read the "maildrop" attributes of those found,
        and build a list of their maildrops, which will be treated
-       as <a href="http://tools.ietf.org/html/rfc822">RFC822</a> addresses to which the message  will  be  deliv-
+       as  <a href="http://tools.ietf.org/html/rfc822">RFC822</a>  addresses  to which the message will be deliv-
        ered.
 
 <b>SEE ALSO</b>
@@ -626,13 +664,13 @@ LDAP_TABLE(5)                                                    LDAP_TABLE(5)
        <a href="LDAP_README.html">LDAP_README</a>, Postfix LDAP client guide
 
 <b>LICENSE</b>
-       The Secure Mailer license must be  distributed  with  this
+       The  Secure  Mailer  license must be distributed with this
        software.
 
 <b>AUTHOR(S)</b>
-       Carsten  Hoeger,  Hery  Rakotoarisoa,  John Hensley, Keith
-       Stevenson, LaMont Jones, Liviu Daia, Manuel Guesdon,  Mike
-       Mattice,  Prabhat K Singh, Sami Haahtinen, Samuel Tardieu,
+       Carsten Hoeger, Hery  Rakotoarisoa,  John  Hensley,  Keith
+       Stevenson,  LaMont Jones, Liviu Daia, Manuel Guesdon, Mike
+       Mattice, Prabhat K Singh, Sami Haahtinen, Samuel  Tardieu,
        Victor Duchovni, and many others.
 
                                                                  LDAP_TABLE(5)
index 63e516b12154ae8bd4478c35de407bf3ec47bde2..043ab1b794f26261eb2e9c9951763ec1e58acd48 100644 (file)
@@ -547,6 +547,38 @@ tls_cert.
 .IP "\fBtls_require_cert (default: no)\fR"
 Whether or not to request server's X509 certificate and
 check its validity when establishing SSL/TLS connections.
+The supported values are \fBno\fR and \fByes\fR.
+.sp
+With \fBno\fR, the server certificate trust chain is not checked,
+but with OpenLDAP prior to 2.1.13, the name in the server
+certificate must still match the LDAP server name. With OpenLDAP
+2.0.0 to 2.0.11 the server name is not necessarily what you
+specified, rather it is determined (by reverse lookup) from the
+IP address of the LDAP server connection. With OpenLDAP prior to
+2.0.13, subjectAlternativeName extensions in the LDAP server
+certificate are ignored: the server name must match the subject
+CommonName. The \fBno\fR setting corresponds to the \fBnever\fR
+value of \fBTLS_REQCERT\fR in LDAP client configuration files.
+.sp
+Don't use TLS with OpenLDAP 2.0.x (and especially with x <= 11)
+if you can avoid it.
+.sp
+With \fByes\fR, the server certificate must be issued by a trusted
+CA, and not be expired. The LDAP server name must match one of the
+name(s) found in the certificate (see above for OpenLDAP library
+version dependent behavior). The \fByes\fR setting corresponds to the
+\fBdemand\fR value of \fBTLS_REQCERT\fR in LDAP client configuration
+files.
+.sp
+The "try" and "never" values of \fBTLS_REQCERT\fR have no equivalents
+here. They are not available with OpenLDAP 2.0, and in any case have
+questionable security properties. Either you want TLS verified LDAP
+connections, or you don't.
+.sp
+The \fByes\fR value only works correctly with Postfix 2.5 and later,
+or with OpenLDAP 2.0. Earlier Postfix releases or later OpenLDAP
+releases don't work together with this setting. Support for LDAP
+over TLS was added to Postfix based on the OpenLDAP 2.0 API.
 .IP "\fBtls_random_file (No default)\fR"
 Path of a file to obtain random bits from when /dev/[u]random
 is not available, to be used by the client in SSL/TLS
index 1e392d9b45da0d5bb98f19684d18d537aa3dfd8c..43fcbd6db5f152e9e39290d84db6767f4ccb35d8 100644 (file)
 # .IP "\fBtls_require_cert (default: no)\fR"
 #      Whether or not to request server's X509 certificate and
 #      check its validity when establishing SSL/TLS connections.
+#      The supported values are \fBno\fR and \fByes\fR.
+# .sp
+#      With \fBno\fR, the server certificate trust chain is not checked,
+#      but with OpenLDAP prior to 2.1.13, the name in the server
+#      certificate must still match the LDAP server name. With OpenLDAP
+#      2.0.0 to 2.0.11 the server name is not necessarily what you
+#      specified, rather it is determined (by reverse lookup) from the
+#      IP address of the LDAP server connection. With OpenLDAP prior to
+#      2.0.13, subjectAlternativeName extensions in the LDAP server
+#      certificate are ignored: the server name must match the subject
+#      CommonName. The \fBno\fR setting corresponds to the \fBnever\fR
+#      value of \fBTLS_REQCERT\fR in LDAP client configuration files.
+# .sp
+#      Don't use TLS with OpenLDAP 2.0.x (and especially with x <= 11)
+#      if you can avoid it.
+# .sp
+#      With \fByes\fR, the server certificate must be issued by a trusted
+#      CA, and not be expired. The LDAP server name must match one of the
+#      name(s) found in the certificate (see above for OpenLDAP library
+#      version dependent behavior). The \fByes\fR setting corresponds to the
+#      \fBdemand\fR value of \fBTLS_REQCERT\fR in LDAP client configuration
+#      files.
+# .sp
+#      The "try" and "never" values of \fBTLS_REQCERT\fR have no equivalents
+#      here. They are not available with OpenLDAP 2.0, and in any case have
+#      questionable security properties. Either you want TLS verified LDAP
+#      connections, or you don't.
+# .sp
+#      The \fByes\fR value only works correctly with Postfix 2.5 and later,
+#      or with OpenLDAP 2.0. Earlier Postfix releases or later OpenLDAP
+#      releases don't work together with this setting. Support for LDAP
+#      over TLS was added to Postfix based on the OpenLDAP 2.0 API.
 # .IP "\fBtls_random_file (No default)\fR"
 #      Path of a file to obtain random bits from when /dev/[u]random
 #      is not available, to be used by the client in SSL/TLS
index e04f36696bdbf56c4298e9bcd4ad2fa6680250d0..92223b056f5aa410cdf9e88da9c6be40704cbc8b 100644 (file)
@@ -318,8 +318,8 @@ int     db_common_expand(void *ctxArg, const char *format, const char *value,
            if ((vdomain = strrchr(value, '@')) != 0)
                ++vdomain;
 
-       if ((!vdomain || !*vdomain) && (ctx->flags & DB_COMMON_VALUE_DOMAIN) != 0
-       || vdomain == value + 1 && (ctx->flags & DB_COMMON_VALUE_USER) != 0)
+       if (((!vdomain || !*vdomain) && (ctx->flags & DB_COMMON_VALUE_DOMAIN) != 0)
+           || (vdomain == value + 1 && (ctx->flags & DB_COMMON_VALUE_USER) != 0))
            return (0);
 
        /* The result format may use the local or domain part of the key */
@@ -331,8 +331,8 @@ int     db_common_expand(void *ctxArg, const char *format, const char *value,
         * The key should already be checked before the query. No harm if the
         * query did not get optimized out, so we just issue a warning.
         */
-       if ((!kdomain || !*kdomain) && (ctx->flags & DB_COMMON_KEY_DOMAIN) != 0
-         || kdomain == key + 1 && (ctx->flags & DB_COMMON_KEY_USER) != 0) {
+       if (((!kdomain || !*kdomain) && (ctx->flags & DB_COMMON_KEY_DOMAIN) != 0)
+       || (kdomain == key + 1 && (ctx->flags & DB_COMMON_KEY_USER) != 0)) {
            msg_warn("%s: %s: lookup key '%s' skipped after query", myname,
                     ctx->dict->name, value);
            return (0);
@@ -343,8 +343,8 @@ int     db_common_expand(void *ctxArg, const char *format, const char *value,
            if ((vdomain = strrchr(value, '@')) != 0)
                ++vdomain;
 
-       if ((!vdomain || !*vdomain) && (ctx->flags & DB_COMMON_KEY_DOMAIN) != 0
-         || vdomain == value + 1 && (ctx->flags & DB_COMMON_KEY_USER) != 0)
+       if (((!vdomain || !*vdomain) && (ctx->flags & DB_COMMON_KEY_DOMAIN) != 0)
+       || (vdomain == value + 1 && (ctx->flags & DB_COMMON_KEY_USER) != 0))
            return (0);
     }
 
index fd35579d26ed488e7b94283b6e23e93b79c425e0..8122a683a0e73869a854aac732f09682a777b0ae 100644 (file)
 /*     tls_cert.
 /* .IP tls_require_cert
 /*     Whether or not to request server's X509 certificate and check its
-/*     validity.
+/*     validity. The value "no" means don't check the cert trust chain
+/*     and (OpenLDAP 2.1+) don't check the peername. The value "yes" means
+/*     check both the trust chain and the peername (with OpenLDAP <= 2.0.11,
+/*     the peername checks use the reverse hostname from the LDAP servers's
+/*     IP address, not the user supplied servername).
 /* .IP tls_random_file
 /*     Path of a file to obtain random bits from when /dev/[u]random is
 /*     not available. Generally set to the name of the EGD/PRNGD socket.
 
 /* Utility library. */
 
-#include "msg.h"
-#include "mymalloc.h"
-#include "vstring.h"
-#include "dict.h"
-#include "stringops.h"
-#include "binhash.h"
+#include <msg.h>
+#include <mymalloc.h>
+#include <vstring.h>
+#include <dict.h>
+#include <stringops.h>
+#include <binhash.h>
 
 /* Global library. */
 
@@ -266,6 +270,13 @@ typedef struct {
 
 #define DICT_LDAP_CONN(d) ((LDAP_CONN *)((d)->ht->value))
 
+#define DICT_LDAP_UNBIND_RETURN(__ld, __err, __ret) do { \
+       dict_ldap_unbind(__ld); \
+       (__ld) = 0; \
+       dict_errno = (__err); \
+       return ((__ret)); \
+    } while (0)
+
  /*
   * Bitrot: LDAP_API 3000 and up (OpenLDAP 2.2.x) deprecated ldap_unbind()
   */
@@ -277,6 +288,31 @@ typedef struct {
 #define dict_ldap_abandon(ld, msg)     ldap_abandon((ld), (msg))
 #endif
 
+static int dict_ldap_vendor_version(void)
+{
+    const char *myname = "dict_ldap_api_info";
+    LDAPAPIInfo api;
+
+    /*
+     * We tell the library our version, and it tells us its version and/or
+     * may return an error code if the versions are not the same.
+     */
+    api.ldapai_info_version = LDAP_API_INFO_VERSION;
+    if (ldap_get_option(0, LDAP_OPT_API_INFO, &api) != LDAP_SUCCESS
+       || api.ldapai_info_version != LDAP_API_INFO_VERSION) {
+       if (api.ldapai_info_version != LDAP_API_INFO_VERSION)
+           msg_fatal("%s: run-time API_INFO version: %d, compiled with: %d",
+                   myname, api.ldapai_info_version, LDAP_API_INFO_VERSION);
+       else
+           msg_fatal("%s: ldap_get_option(API_INFO) failed", myname);
+    }
+    if (strcmp(api.ldapai_vendor_name, LDAP_VENDOR_NAME) != 0)
+       msg_fatal("%s: run-time API vendor: %s, compiled with: %s",
+                 myname, api.ldapai_vendor_name, LDAP_VENDOR_NAME);
+
+    return (api.ldapai_vendor_version);
+}
+
 /*
  * Quoting rules.
  */
@@ -444,7 +480,7 @@ static int search_st(LDAP *ld, char *base, int scope, char *query,
 }
 
 #ifdef LDAP_API_FEATURE_X_OPENLDAP
-static void dict_ldap_set_tls_options(DICT_LDAP *dict_ldap)
+static int dict_ldap_set_tls_options(DICT_LDAP *dict_ldap)
 {
     const char *myname = "dict_ldap_set_tls_options";
     int     rc;
@@ -456,6 +492,7 @@ static void dict_ldap_set_tls_options(DICT_LDAP *dict_ldap)
                msg_warn("%s: Unable to set tls_random_file to %s: %d: %s",
                         myname, dict_ldap->tls_random_file,
                         rc, ldap_err2string(rc));
+           return (-1);
        }
        if (*dict_ldap->tls_ca_cert_file) {
            if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
@@ -463,6 +500,7 @@ static void dict_ldap_set_tls_options(DICT_LDAP *dict_ldap)
                msg_warn("%s: Unable to set tls_ca_cert_file to %s: %d: %s",
                         myname, dict_ldap->tls_ca_cert_file,
                         rc, ldap_err2string(rc));
+           return (-1);
        }
        if (*dict_ldap->tls_ca_cert_dir) {
            if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTDIR,
@@ -470,6 +508,7 @@ static void dict_ldap_set_tls_options(DICT_LDAP *dict_ldap)
                msg_warn("%s: Unable to set tls_ca_cert_dir to %s: %d: %s",
                         myname, dict_ldap->tls_ca_cert_dir,
                         rc, ldap_err2string(rc));
+           return (-1);
        }
        if (*dict_ldap->tls_cert) {
            if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CERTFILE,
@@ -477,6 +516,7 @@ static void dict_ldap_set_tls_options(DICT_LDAP *dict_ldap)
                msg_warn("%s: Unable to set tls_cert to %s: %d: %s",
                         myname, dict_ldap->tls_cert,
                         rc, ldap_err2string(rc));
+           return (-1);
        }
        if (*dict_ldap->tls_key) {
            if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_KEYFILE,
@@ -484,6 +524,7 @@ static void dict_ldap_set_tls_options(DICT_LDAP *dict_ldap)
                msg_warn("%s: Unable to set tls_key to %s: %d: %s",
                         myname, dict_ldap->tls_key,
                         rc, ldap_err2string(rc));
+           return (-1);
        }
        if (*dict_ldap->tls_cipher_suite) {
            if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CIPHER_SUITE,
@@ -491,6 +532,7 @@ static void dict_ldap_set_tls_options(DICT_LDAP *dict_ldap)
                msg_warn("%s: Unable to set tls_cipher_suite to %s: %d: %s",
                         myname, dict_ldap->tls_cipher_suite,
                         rc, ldap_err2string(rc));
+           return (-1);
        }
        if (dict_ldap->tls_require_cert) {
            if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT,
@@ -498,8 +540,10 @@ static void dict_ldap_set_tls_options(DICT_LDAP *dict_ldap)
                msg_warn("%s: Unable to set tls_require_cert to %d: %d: %s",
                         myname, dict_ldap->tls_require_cert,
                         rc, ldap_err2string(rc));
+           return (-1);
        }
     }
+    return (0);
 }
 
 #endif
@@ -543,7 +587,10 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap)
 
 #ifdef LDAP_OPT_NETWORK_TIMEOUT
 #ifdef LDAP_API_FEATURE_X_OPENLDAP
-    dict_ldap_set_tls_options(dict_ldap);
+    if (dict_ldap_set_tls_options(dict_ldap) != 0) {
+       dict_errno = DICT_ERR_RETRY;
+       return (-1);
+    }
     ldap_initialize(&(dict_ldap->ld), dict_ldap->server_host);
 #else
     dict_ldap->ld = ldap_init(dict_ldap->server_host,
@@ -558,8 +605,10 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap)
     mytimeval.tv_sec = dict_ldap->timeout;
     mytimeval.tv_usec = 0;
     if (ldap_set_option(dict_ldap->ld, LDAP_OPT_NETWORK_TIMEOUT, &mytimeval) !=
-       LDAP_OPT_SUCCESS)
+       LDAP_OPT_SUCCESS) {
        msg_warn("%s: Unable to set network timeout.", myname);
+       DICT_LDAP_UNBIND_RETURN(dict_ldap->ld, DICT_ERR_RETRY, -1);
+    }
 #else
     if ((saved_alarm = signal(SIGALRM, dict_ldap_timeout)) == SIG_ERR) {
        msg_warn("%s: Error setting signal handler for open timeout: %m",
@@ -595,9 +644,10 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap)
      */
 #ifdef LDAP_OPT_PROTOCOL_VERSION
     if (ldap_set_option(dict_ldap->ld, LDAP_OPT_PROTOCOL_VERSION,
-                       &dict_ldap->version) != LDAP_OPT_SUCCESS)
+                       &dict_ldap->version) != LDAP_OPT_SUCCESS) {
        msg_warn("%s: Unable to set LDAP protocol version", myname);
-
+       DICT_LDAP_UNBIND_RETURN(dict_ldap->ld, DICT_ERR_RETRY, -1);
+    }
     if (msg_verbose) {
        if (ldap_get_option(dict_ldap->ld,
                            LDAP_OPT_PROTOCOL_VERSION,
@@ -614,9 +664,11 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap)
      */
     if (dict_ldap->size_limit) {
        if (ldap_set_option(dict_ldap->ld, LDAP_OPT_SIZELIMIT,
-                           &dict_ldap->size_limit) != LDAP_OPT_SUCCESS)
+                           &dict_ldap->size_limit) != LDAP_OPT_SUCCESS) {
            msg_warn("%s: %s: Unable to set query result size limit to %ld.",
                     myname, dict_ldap->parser->name, dict_ldap->size_limit);
+           DICT_LDAP_UNBIND_RETURN(dict_ldap->ld, DICT_ERR_RETRY, -1);
+       }
     }
 
     /*
@@ -629,15 +681,13 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap)
 
     /* Chase referrals. */
 
-    /*
-     * I have no clue where this was originally added so i'm skipping all
-     * tests
-     */
 #ifdef LDAP_OPT_REFERRALS
     if (ldap_set_option(dict_ldap->ld, LDAP_OPT_REFERRALS,
                    dict_ldap->chase_referrals ? LDAP_OPT_ON : LDAP_OPT_OFF)
-       != LDAP_OPT_SUCCESS)
+       != LDAP_OPT_SUCCESS) {
        msg_warn("%s: Unable to set Referral chasing.", myname);
+       DICT_LDAP_UNBIND_RETURN(dict_ldap->ld, DICT_ERR_RETRY, -1);
+    }
 #else
     if (dict_ldap->chase_referrals) {
        msg_warn("%s: Unable to set Referral chasing.", myname);
@@ -649,14 +699,16 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap)
        if ((saved_alarm = signal(SIGALRM, dict_ldap_timeout)) == SIG_ERR) {
            msg_warn("%s: Error setting signal handler for STARTTLS timeout: %m",
                     myname);
-           dict_errno = DICT_ERR_RETRY;
-           return (-1);
+           DICT_LDAP_UNBIND_RETURN(dict_ldap->ld, DICT_ERR_RETRY, -1);
        }
        alarm(dict_ldap->timeout);
        if (setjmp(env) == 0)
            rc = ldap_start_tls_s(dict_ldap->ld, NULL, NULL);
-       else
+       else {
            rc = LDAP_TIMEOUT;
+           dict_ldap->ld = 0;                  /* Unknown state after
+                                                * longjmp() */
+       }
        alarm(0);
 
        if (signal(SIGALRM, saved_alarm) == SIG_ERR) {
@@ -689,8 +741,7 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap)
            msg_warn("%s: Unable to bind to server %s as %s: %d (%s)",
                     myname, dict_ldap->server_host, dict_ldap->bind_dn,
                     rc, ldap_err2string(rc));
-           dict_errno = DICT_ERR_RETRY;
-           return (-1);
+           DICT_LDAP_UNBIND_RETURN(dict_ldap->ld, DICT_ERR_RETRY, -1);
        }
        if (msg_verbose)
            msg_info("%s: Successful bind to server %s as %s ",
@@ -893,9 +944,9 @@ static void dict_ldap_get_values(DICT_LDAP *dict_ldap, LDAPMessage *res,
             * recursing (for dn or url attributes of non-terminal entries)
             */
            if (i < dict_ldap->num_attributes || is_terminal) {
-               if (is_terminal && i >= dict_ldap->num_terminal
-                   || !is_leaf &&
-                   i < dict_ldap->num_terminal + dict_ldap->num_leaf) {
+               if ((is_terminal && i >= dict_ldap->num_terminal)
+                   || (!is_leaf &&
+                       i < dict_ldap->num_terminal + dict_ldap->num_leaf)) {
                    if (msg_verbose)
                        msg_info("%s[%d]: skipping %ld value(s) of %s "
                                 "attribute %s", myname, recursion, i,
@@ -1084,9 +1135,12 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
      */
     sizelimit = dict_ldap->size_limit ? dict_ldap->size_limit : LDAP_NO_LIMIT;
     if (ldap_set_option(dict_ldap->ld, LDAP_OPT_SIZELIMIT, &sizelimit)
-       != LDAP_OPT_SUCCESS)
+       != LDAP_OPT_SUCCESS) {
        msg_warn("%s: %s: Unable to set query result size limit to %ld.",
                 myname, dict_ldap->parser->name, dict_ldap->size_limit);
+       dict_errno = DICT_ERR_RETRY;
+       return (0);
+    }
 
     /*
      * Expand the search base and query. Skip lookup when the input key lacks
@@ -1276,6 +1330,7 @@ DICT   *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags)
     char   *scope;
     char   *attr;
     int     tmp;
+    int     vendor_version = dict_ldap_vendor_version();
 
     if (msg_verbose)
        msg_info("%s: Using LDAP source %s", myname, ldapsource);
@@ -1299,7 +1354,7 @@ DICT   *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags)
        cfg_get_int(dict_ldap->parser, "server_port", LDAP_PORT, 0, 0);
 
     /*
-     * Define LDAP Version.
+     * Define LDAP Protocol Version.
      */
     dict_ldap->version = cfg_get_int(dict_ldap->parser, "version", 2, 2, 0);
     switch (dict_ldap->version) {
@@ -1310,7 +1365,7 @@ DICT   *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags)
        dict_ldap->version = LDAP_VERSION3;
        break;
     default:
-       msg_warn("%s: %s Unknown version %d.", myname, ldapsource,
+       msg_warn("%s: %s Unknown version %d, using 2.", myname, ldapsource,
                 dict_ldap->version);
        dict_ldap->version = LDAP_VERSION2;
     }
@@ -1542,14 +1597,24 @@ DICT   *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags)
      */
     /* get configured value of "start_tls"; default to no */
     dict_ldap->start_tls = cfg_get_bool(dict_ldap->parser, "start_tls", 0);
-    if (dict_ldap->start_tls && dict_ldap->version < LDAP_VERSION3) {
-       msg_warn("%s: %s start_tls requires protocol version 3",
-                myname, ldapsource);
-       dict_ldap->version = LDAP_VERSION3;
+    if (dict_ldap->start_tls) {
+       if (dict_ldap->version < LDAP_VERSION3) {
+           msg_warn("%s: %s start_tls requires protocol version 3",
+                    myname, ldapsource);
+           dict_ldap->version = LDAP_VERSION3;
+       }
+       /* Binary incompatibility in the OpenLDAP API from 2.0.11 to 2.0.12 */
+       if (((LDAP_VENDOR_VERSION <= 20011) && !(vendor_version <= 20011))
+         || (!(LDAP_VENDOR_VERSION <= 20011) && (vendor_version <= 20011)))
+           msg_fatal("%s: incompatible TLS support: "
+                     "compile-time OpenLDAP version %d, "
+                     "run-time OpenLDAP version %d",
+                     myname, LDAP_VENDOR_VERSION, vendor_version);
     }
     /* get configured value of "tls_require_cert"; default to no */
-    dict_ldap->tls_require_cert = cfg_get_bool(dict_ldap->parser,
-                                              "tls_require_cert", 0);
+    dict_ldap->tls_require_cert =
+       cfg_get_bool(dict_ldap->parser, "tls_require_cert", 0) ?
+       LDAP_OPT_X_TLS_DEMAND : LDAP_OPT_X_TLS_NEVER;
 
     /* get configured value of "tls_ca_cert_file"; default "" */
     dict_ldap->tls_ca_cert_file = cfg_get_str(dict_ldap->parser,
index 6259379e109ad419b76363e8d39f043b151b1cfc..ac343169c1f0804fdb4946cc6084a512ea1cf7f4 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      "20071215"
+#define MAIL_RELEASE_DATE      "20071216"
 #define MAIL_VERSION_NUMBER    "2.5"
 
 #ifdef SNAPSHOT
index 252924f92899cd6491f1cfb68d47281df396c616..08c9d7400c7be1b270e769a723d72106f6742177 100644 (file)
@@ -182,7 +182,7 @@ void    smtp_chat_cmd(SMTP_SESSION *session, char *fmt,...)
      * program is trying to do.
      */
     if (msg_verbose)
-       msg_info("> %s: %s", session->namaddr, STR(session->buffer));
+       msg_info("> %s: %s", session->namaddrport, STR(session->buffer));
 
     /*
      * Send the command to the SMTP server.
@@ -246,9 +246,9 @@ SMTP_RESP *smtp_chat_resp(SMTP_SESSION *session)
        printable(STR(session->buffer), '?');
        if (last_char != '\n')
            msg_warn("%s: response longer than %d: %.30s...",
-                    session->namaddr, var_line_limit, STR(session->buffer));
+               session->namaddrport, var_line_limit, STR(session->buffer));
        if (msg_verbose)
-           msg_info("< %s: %.100s", session->namaddr, STR(session->buffer));
+           msg_info("< %s: %.100s", session->namaddrport, STR(session->buffer));
 
        /*
         * Defend against a denial of service attack by limiting the amount
@@ -420,9 +420,10 @@ void    smtp_chat_notify(SMTP_SESSION *session)
                      var_mail_name,
                      (session->state->misc_flags &
                       SMTP_MISC_FLAG_USE_LMTP) ? "LMTP" : "SMTP",
-                     session->namaddr);
+                     session->namaddrport);
     post_mail_fputs(notice, "");
-    post_mail_fprintf(notice, "Unexpected response from %s.", session->namaddr);
+    post_mail_fprintf(notice, "Unexpected response from %s.",
+                     session->namaddrport);
     post_mail_fputs(notice, "");
     post_mail_fputs(notice, "Transcript of session follows.");
     post_mail_fputs(notice, "");
index 139f6fd5309b34451077c8de8800c1322f9e205a..7b225c3eed14b50270646f0708e8fabf842550b1 100644 (file)
@@ -277,7 +277,7 @@ int     smtp_sasl_authenticate(SMTP_SESSION *session, DSN_BUF *why)
 
     if (msg_verbose)
        msg_info("%s: %s: SASL mechanisms %s",
-                myname, session->namaddr, session->sasl_mechanism_list);
+                myname, session->namaddrport, session->sasl_mechanism_list);
 
     /*
      * Start the client side authentication protocol.
index 295c0fbd2e914065bd197d92186f9431eb122c21..ce0877a1d75ec7a8bb9e27e51cb5df07952a96bc 100644 (file)
@@ -139,7 +139,7 @@ void    smtp_sasl_helo_auth(SMTP_SESSION *session, const char *words)
     } else {
        msg_warn(*words ? "%s offered no supported AUTH mechanisms: '%s'" :
                 "%s offered null AUTH mechanism list",
-                session->namaddr, words);
+                session->namaddrport, words);
     }
     session->features |= SMTP_FEATURE_AUTH;
 }