From a3d69a8b435df9ab0da845a268aa49dc30773473 Mon Sep 17 00:00:00 2001 From: cvs2git Date: Sat, 15 May 2004 11:01:15 +0000 Subject: [PATCH] This commit was manufactured by cvs2git to create branch 'POSTFIX_2_1'. Sprout from master 2004-05-15 11:01:15 UTC Tomek Orzechowski '- updated' Delete: postfix-authinfo.patch postfix-dict_ldap.patch postfix-ipv6.patch postfix-ns-mx-acl.patch postfix-pgsql.patch postfix-pl.patch postfix-sasl2.patch --- postfix-authinfo.patch | 48 - postfix-dict_ldap.patch | 1162 --------------- postfix-ipv6.patch | 3031 --------------------------------------- postfix-ns-mx-acl.patch | 478 ------ postfix-pgsql.patch | 916 ------------ postfix-pl.patch | 386 ----- postfix-sasl2.patch | 298 ---- 7 files changed, 6319 deletions(-) delete mode 100644 postfix-authinfo.patch delete mode 100644 postfix-dict_ldap.patch delete mode 100644 postfix-ipv6.patch delete mode 100644 postfix-ns-mx-acl.patch delete mode 100644 postfix-pgsql.patch delete mode 100644 postfix-pl.patch delete mode 100644 postfix-sasl2.patch diff --git a/postfix-authinfo.patch b/postfix-authinfo.patch deleted file mode 100644 index 85c1b53..0000000 --- a/postfix-authinfo.patch +++ /dev/null @@ -1,48 +0,0 @@ -diff -Nur snapshot-20011114.orig/src/global/mail_params.h snapshot-20011114/src/global/mail_params.h ---- snapshot-20011114.orig/src/global/mail_params.h Thu Nov 15 15:13:42 2001 -+++ snapshot-20011114/src/global/mail_params.h Thu Nov 15 15:15:21 2001 -@@ -961,6 +961,10 @@ - #define DEF_SMTPD_SASL_REALM "$myhostname" - extern char *var_smtpd_sasl_realm; - -+#define VAR_PUBLISH_SASL_USERNAME "publish_sasl_username" -+#define DEF_PUBLISH_SASL_USERNAME 0 -+extern bool var_publish_sasl_username; -+ - /* - * SASL authentication support, SMTP client side. - */ -Binary files snapshot-20011114.orig/src/smtpd/.smtpd.c.rej.swp and snapshot-20011114/src/smtpd/.smtpd.c.rej.swp differ -diff -Nur snapshot-20011114.orig/src/smtpd/smtpd.c snapshot-20011114/src/smtpd/smtpd.c ---- snapshot-20011114.orig/src/smtpd/smtpd.c Thu Nov 15 15:13:42 2001 -+++ snapshot-20011114/src/smtpd/smtpd.c Thu Nov 15 15:20:19 2001 -@@ -359,6 +359,7 @@ - bool var_smtpd_sasl_enable; - char *var_smtpd_sasl_opts; - char *var_smtpd_sasl_realm; -+bool var_publish_sasl_username; - char *var_filter_xport; - bool var_broken_auth_clients; - char *var_perm_mx_networks; -@@ -1011,6 +1012,13 @@ - "Received: from %s (%s [%s])", - state->helo_name ? state->helo_name : state->name, - state->name, state->addr); -+#ifdef USE_SASL_AUTH -+ if (var_publish_sasl_username) -+ rec_fprintf(state->cleanup, REC_TYPE_NORM, -+ "\tsender authenticated as: \"%s\"", -+ state->sasl_username ? state->sasl_username : ""); -+#endif -+ - if (var_smtpd_tls_received_header && state->tls_active) { - rec_fprintf(state->cleanup, REC_TYPE_NORM, - "\t(using %s with cipher %s (%d/%d bits))", -@@ -1839,6 +1847,7 @@ - VAR_DISABLE_VRFY_CMD, DEF_DISABLE_VRFY_CMD, &var_disable_vrfy_cmd, - VAR_ALLOW_UNTRUST_ROUTE, DEF_ALLOW_UNTRUST_ROUTE, &var_allow_untrust_route, - VAR_SMTPD_SASL_ENABLE, DEF_SMTPD_SASL_ENABLE, &var_smtpd_sasl_enable, -+ VAR_PUBLISH_SASL_USERNAME, DEF_PUBLISH_SASL_USERNAME, &var_publish_sasl_username, - VAR_BROKEN_AUTH_CLNTS, DEF_BROKEN_AUTH_CLNTS, &var_broken_auth_clients, - VAR_SMTPD_TLS_WRAPPER, DEF_SMTPD_TLS_WRAPPER, &var_smtpd_tls_wrappermode, - VAR_SMTPD_USE_TLS, DEF_SMTPD_USE_TLS, &var_smtpd_use_tls, diff --git a/postfix-dict_ldap.patch b/postfix-dict_ldap.patch deleted file mode 100644 index 185d098..0000000 --- a/postfix-dict_ldap.patch +++ /dev/null @@ -1,1162 +0,0 @@ ---- postfix-2.0.19.old/src/util/dict_ldap.c 2002-10-17 02:26:41.000000000 +0200 -+++ postfix-2.0.19.new/src/util/dict_ldap.c 2004-04-10 21:08:37.000000000 +0200 -@@ -26,7 +26,9 @@ - /* .PP - /* Configuration parameters: - /* .IP \fIldapsource_\fRserver_host --/* The host at which all LDAP queries are directed. -+/* List of hosts at which all LDAP queries are directed. -+/* The host names can also be LDAP URLs if the LDAP client library used -+/* is OpenLDAP. - /* .IP \fIldapsource_\fRserver_port - /* The port the LDAP server listens on. - /* .IP \fIldapsource_\fRsearch_base -@@ -57,14 +59,56 @@ - /* If you must bind to the server, do it with this distinguished name ... - /* .IP \fIldapsource_\fRbind_pw - /* \&... and this password. --/* .IP \fIldapsource_\fRcache -+/* .IP \fIldapsource_\fRcache (no longer supported) - /* Whether or not to turn on client-side caching. --/* .IP \fIldapsource_\fRcache_expiry -+/* .IP \fIldapsource_\fRcache_expiry (no longer supported) - /* If you do cache results, expire them after this many seconds. --/* .IP \fIldapsource_\fRcache_size -+/* .IP \fIldapsource_\fRcache_size (no longer supported) - /* The cache size in bytes. Does nothing if the cache is off, of course. -+/* .IP \fIldapsource_\fRrecursion_limit -+/* Maximum recursion depth when expanding DN or URL references. -+/* Queries which exceed the recursion limit fail with -+/* dict_errno = DICT_ERR_RETRY. -+/* .IP \fIldapsource_\fRexpansion_limit -+/* Limit (if any) on the total number of lookup result values. Lookups which -+/* exceed the limit fail with dict_errno=DICT_ERR_RETRY. Note that -+/* each value of a multivalued result attribute counts as one result. -+/* .IP \fIldapsource_\fRsize_limit -+/* Limit on the number of entries returned by individual LDAP queries. -+/* Queries which exceed the limit fail with dict_errno=DICT_ERR_RETRY. -+/* This is an *entry* count, for any single query performed during the -+/* possibly recursive lookup. -+/* .IP \fIldapsource_\fRchase_referrals -+/* Controls whether LDAP referrals are obeyed. - /* .IP \fIldapsource_\fRdereference - /* How to handle LDAP aliases. See ldap.h or ldap_open(3) man page. -+/* .IP \fIldapsource_\fRversion -+/* Specifies the LDAP protocol version to use. Default is version -+/* \fI2\fR. -+/* .IP \fIldapsource_\fRstart_tls -+/* Whether or not to issue STARTTLS upon connection to the server. -+/* At this time, STARTTLS and LDAP SSL are only available if the -+/* LDAP client library used is OpenLDAP. Default is \fIno\fR. -+/* .IP \fIldapsource_\fRtls_ca_cert_file -+/* File containing certificates for all of the X509 Certificate -+/* Authorities the client will recognize. Takes precedence over -+/* tls_ca_cert_dir. -+/* .IP \fIldapsource_\fRtls_ca_cert_dir -+/* Directory containing X509 Certificate Authority certificates -+/* in separate individual files. -+/* .IP \fIldapsource_\fRtls_cert -+/* File containing client's X509 certificate. -+/* .IP \fIldapsource_\fRtls_key -+/* File containing the private key corresponding to -+/* tls_cert. -+/* .IP \fIldapsource_\fRtls_require_cert -+/* Whether or not to request server's X509 certificate and check its -+/* validity. -+/* .IP \fIldapsource_\fRtls_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. -+/* .IP \fIldapsource_\fRtls_cipher_suite -+/* Cipher suite to use in SSL/TLS negotiations. - /* .IP \fIldapsource_\fRdebuglevel - /* Debug level. See 'loglevel' option in slapd.conf(5) man page. - /* Currently only in openldap libraries (and derivatives). -@@ -102,6 +146,8 @@ - #include - #include - #include -+#include -+#include - - /* - * Older APIs have weird memory freeing behavior. -@@ -126,12 +172,22 @@ - #include "mymalloc.h" - #include "vstring.h" - #include "dict.h" -+#include "stringops.h" -+#include "binhash.h" -+ - #include "dict_ldap.h" - - /* AAARGH!! */ - - #include "../global/mail_conf.h" - -+#include "dict_ldap.h" -+ -+typedef struct { -+ LDAP *conn_ld; -+ int conn_refcount; -+} LDAP_CONN; -+ - /* - * Structure containing all the configuration parameters for a given - * LDAP source, plus its connection handle. -@@ -152,17 +208,33 @@ - char *bind_dn; - char *bind_pw; - int timeout; -- int cache; -- long cache_expiry; -- long cache_size; - int dereference; -+ long recursion_limit; -+ long expansion_limit; -+ long size_limit; - int chase_referrals; - int debuglevel; - int version; -+#ifdef LDAP_API_FEATURE_X_OPENLDAP -+ int ldap_ssl; -+ int start_tls; -+ int tls_require_cert; -+ char *tls_ca_cert_file; -+ char *tls_ca_cert_dir; -+ char *tls_cert; -+ char *tls_key; -+ char *tls_random_file; -+ char *tls_cipher_suite; -+#endif -+ BINHASH_INFO *ht; /* hash entry for LDAP connection */ - LDAP *ld; - } DICT_LDAP; - --#ifndef LDAP_OPT_NETWORK_TIMEOUT -+#define DICT_LDAP_CONN(d) ((LDAP_CONN *)((d)->ht->value)) -+ -+static BINHASH *conn_hash = 0; -+ -+#if defined(LDAP_API_FEATURE_X_OPENLDAP) || !defined(LDAP_OPT_NETWORK_TIMEOUT) - /* - * LDAP connection timeout support. - */ -@@ -178,8 +250,17 @@ - static void dict_ldap_logprint(LDAP_CONST char *data) - { - char *myname = "dict_ldap_debug"; -+ char *buf, -+ *p; - -- msg_info("%s: %s", myname, data); -+ buf = mystrdup(data); -+ if (*buf) { -+ p = buf + strlen(buf) - 1; -+ while (p - buf >= 0 && ISSPACE(*p)) -+ *p-- = 0; -+ } -+ msg_info("%s: %s", myname, buf); -+ myfree(buf); - } - - -@@ -225,24 +306,97 @@ - return (ldap_result2error(dict_ldap->ld, res, 1)); - } - -+#ifdef LDAP_API_FEATURE_X_OPENLDAP -+static void dict_ldap_set_tls_options(DICT_LDAP *dict_ldap) -+{ -+ char *myname = "dict_ldap_set_tls_options"; -+ int rc; -+ -+ if (dict_ldap->start_tls || dict_ldap->ldap_ssl) { -+ if (*dict_ldap->tls_random_file) { -+ if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_RANDOM_FILE, -+ dict_ldap->tls_random_file)) != LDAP_SUCCESS) -+ msg_warn("%s: Unable to set tls_random_file to %s: %d: %s", -+ myname, dict_ldap->tls_random_file, -+ rc, ldap_err2string(rc)); -+ } -+ if (*dict_ldap->tls_ca_cert_file) { -+ if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, -+ dict_ldap->tls_ca_cert_file)) != LDAP_SUCCESS) -+ 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)); -+ } -+ if (*dict_ldap->tls_ca_cert_dir) { -+ if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTDIR, -+ dict_ldap->tls_ca_cert_dir)) != LDAP_SUCCESS) -+ 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)); -+ } -+ if (*dict_ldap->tls_cert) { -+ if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CERTFILE, -+ dict_ldap->tls_cert)) != LDAP_SUCCESS) -+ msg_warn("%s: Unable to set tls_cert to %s: %d: %s", -+ myname, dict_ldap->tls_cert, -+ rc, ldap_err2string(rc)); -+ } -+ if (*dict_ldap->tls_key) { -+ if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_KEYFILE, -+ dict_ldap->tls_key)) != LDAP_SUCCESS) -+ msg_warn("%s: Unable to set tls_key to %s: %d: %s", -+ myname, dict_ldap->tls_key, -+ rc, ldap_err2string(rc)); -+ } -+ if (*dict_ldap->tls_cipher_suite) { -+ if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CIPHER_SUITE, -+ dict_ldap->tls_cipher_suite)) != LDAP_SUCCESS) -+ msg_warn("%s: Unable to set tls_cipher_suite to %s: %d: %s", -+ myname, dict_ldap->tls_cipher_suite, -+ rc, ldap_err2string(rc)); -+ } -+ if (dict_ldap->tls_require_cert) { -+ if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, -+ &(dict_ldap->tls_require_cert))) != LDAP_SUCCESS) -+ msg_warn("%s: Unable to set tls_require_cert to %d: %d: %s", -+ myname, dict_ldap->tls_require_cert, -+ rc, ldap_err2string(rc)); -+ } -+ } -+} -+ -+#endif -+ -+ - /* Establish a connection to the LDAP server. */ - static int dict_ldap_connect(DICT_LDAP *dict_ldap) - { - char *myname = "dict_ldap_connect"; - int rc = 0; - --#ifdef LDAP_API_FEATURE_X_MEMCACHE -- LDAPMemCache *dircache; -- --#endif -- - #ifdef LDAP_OPT_NETWORK_TIMEOUT - struct timeval mytimeval; - --#else -+#endif -+ -+#if defined(LDAP_API_FEATURE_X_OPENLDAP) || !defined(LDAP_OPT_NETWORK_TIMEOUT) - void (*saved_alarm) (int); - - #endif -+#if defined(LDAP_OPT_DEBUG_LEVEL) && defined(LBER_OPT_LOG_PRINT_FN) -+ if (dict_ldap->debuglevel > 0 && -+ ber_set_option(NULL, LBER_OPT_LOG_PRINT_FN, -+ (LDAP_CONST *) dict_ldap_logprint) != LBER_OPT_SUCCESS) -+ msg_warn("%s: Unable to set ber logprint function.", myname); -+#if defined(LBER_OPT_DEBUG_LEVEL) -+ if (ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, -+ &(dict_ldap->debuglevel)) != LBER_OPT_SUCCESS) -+ msg_warn("%s: Unable to set BER debug level.", myname); -+#endif -+ if (ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, -+ &(dict_ldap->debuglevel)) != LDAP_OPT_SUCCESS) -+ msg_warn("%s: Unable to set LDAP debug level.", myname); -+#endif - - dict_errno = 0; - -@@ -251,8 +405,13 @@ - dict_ldap->server_host); - - #ifdef LDAP_OPT_NETWORK_TIMEOUT -+#ifdef LDAP_API_FEATURE_X_OPENLDAP -+ dict_ldap_set_tls_options(dict_ldap); -+ ldap_initialize(&(dict_ldap->ld), dict_ldap->server_host); -+#else - dict_ldap->ld = ldap_init(dict_ldap->server_host, - (int) dict_ldap->server_port); -+#endif - if (dict_ldap->ld == NULL) { - msg_warn("%s: Unable to init LDAP server %s", - myname, dict_ldap->server_host); -@@ -308,12 +467,22 @@ - &dict_ldap->version) != LDAP_OPT_SUCCESS) - msg_warn("%s: Unable to get LDAP protocol version", myname); - else -- msg_warn("%s: Actual Protocol version used is %d.", -+ msg_info("%s: Actual Protocol version used is %d.", - myname, dict_ldap->version); - } - #endif - - /* -+ * Limit the number of entries returned by each query. -+ */ -+ if (dict_ldap->size_limit) { -+ if (ldap_set_option(dict_ldap->ld, LDAP_OPT_SIZELIMIT, -+ &dict_ldap->size_limit) != LDAP_OPT_SUCCESS) -+ msg_warn("%s: %s: Unable to set query result size limit to %ld.", -+ myname, dict_ldap->ldapsource, dict_ldap->size_limit); -+ } -+ -+ /* - * Configure alias dereferencing for this connection. Thanks to Mike - * Mattice for this, and to Hery Rakotoarisoa for the v3 update. - */ -@@ -321,16 +490,6 @@ - &(dict_ldap->dereference)) != LDAP_OPT_SUCCESS) - msg_warn("%s: Unable to set dereference option.", myname); - --#if defined(LDAP_OPT_DEBUG_LEVEL) && defined(LBER_OPT_LOG_PRINT_FN) -- if (dict_ldap->debuglevel > 0 && -- ber_set_option(NULL, LBER_OPT_LOG_PRINT_FN, -- (LDAP_CONST *) dict_ldap_logprint) != LBER_OPT_SUCCESS) -- msg_warn("%s: Unable to set ber logprint function.", myname); -- if (ldap_set_option(dict_ldap->ld, LDAP_OPT_DEBUG_LEVEL, -- &(dict_ldap->debuglevel)) != LDAP_OPT_SUCCESS) -- msg_warn("%s: Unable to set LDAP debug level.", myname); --#endif -- - /* Chase referrals. */ - - /* -@@ -348,6 +507,36 @@ - } - #endif - -+#ifdef LDAP_API_FEATURE_X_OPENLDAP -+ if (dict_ldap->start_tls) { -+ 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); -+ } -+ alarm(dict_ldap->timeout); -+ if (setjmp(env) == 0) -+ rc = ldap_start_tls_s(dict_ldap->ld, NULL, NULL); -+ else -+ rc = LDAP_TIMEOUT; -+ alarm(0); -+ -+ if (signal(SIGALRM, saved_alarm) == SIG_ERR) { -+ msg_warn("%s: Error resetting signal handler after STARTTLS: %m", -+ myname); -+ dict_errno = DICT_ERR_RETRY; -+ return (-1); -+ } -+ if (rc != LDAP_SUCCESS) { -+ msg_error("%s: Unable to set STARTTLS: %d: %s", myname, -+ rc, ldap_err2string(rc)); -+ dict_errno = DICT_ERR_RETRY; -+ return (-1); -+ } -+ } -+#endif -+ - /* - * If this server requires a bind, do so. Thanks to Sam Tardieu for - * noticing that the original bind call was broken. -@@ -370,52 +559,9 @@ - msg_info("%s: Successful bind to server %s as %s ", - myname, dict_ldap->server_host, dict_ldap->bind_dn); - } -+ /* Save connection handle in shared container */ -+ DICT_LDAP_CONN(dict_ldap)->conn_ld = dict_ldap->ld; - -- /* -- * Set up client-side caching if it's configured. -- */ -- if (dict_ldap->cache) { -- if (msg_verbose) -- msg_info -- ("%s: Enabling %ld-byte cache for %s with %ld-second expiry", -- myname, dict_ldap->cache_size, dict_ldap->ldapsource, -- dict_ldap->cache_expiry); -- --#ifdef LDAP_API_FEATURE_X_MEMCACHE -- rc = ldap_memcache_init(dict_ldap->cache_expiry, dict_ldap->cache_size, -- NULL, NULL, &dircache); -- if (rc != LDAP_SUCCESS) { -- msg_warn -- ("%s: Unable to configure cache for %s: %d (%s) -- continuing", -- myname, dict_ldap->ldapsource, rc, ldap_err2string(rc)); -- } else { -- rc = ldap_memcache_set(dict_ldap->ld, dircache); -- if (rc != LDAP_SUCCESS) { -- msg_warn -- ("%s: Unable to configure cache for %s: %d (%s) -- continuing", -- myname, dict_ldap->ldapsource, rc, ldap_err2string(rc)); -- } else { -- if (msg_verbose) -- msg_info("%s: Caching enabled for %s", -- myname, dict_ldap->ldapsource); -- } -- } --#else -- -- rc = ldap_enable_cache(dict_ldap->ld, dict_ldap->cache_expiry, -- dict_ldap->cache_size); -- if (rc != LDAP_SUCCESS) { -- msg_warn -- ("%s: Unable to configure cache for %s: %d (%s) -- continuing", -- myname, dict_ldap->ldapsource, rc, ldap_err2string(rc)); -- } else { -- if (msg_verbose) -- msg_info("%s: Caching enabled for %s", -- myname, dict_ldap->ldapsource); -- } -- --#endif -- } - if (msg_verbose) - msg_info("%s: Cached connection handle for LDAP source %s", - myname, dict_ldap->ldapsource); -@@ -424,9 +570,65 @@ - } - - /* -+ * Locate or allocate connection cache entry. -+ */ -+static void dict_ldap_conn_find(DICT_LDAP *dict_ldap) -+{ -+ VSTRING *keybuf = vstring_alloc(10); -+ char *key; -+ int len; -+ -+#ifdef LDAP_API_FEATURE_X_OPENLDAP -+ int sslon = dict_ldap->start_tls || dict_ldap->ldap_ssl; -+ -+#endif -+ LDAP_CONN *conn; -+ -+#define ADDSTR(vp, s) vstring_memcat((vp), (s), strlen((s))+1) -+#define ADDINT(vp, i) vstring_sprintf_append((vp), "%lu", (unsigned long)(i)) -+ -+ ADDSTR(keybuf, dict_ldap->server_host); -+ ADDINT(keybuf, dict_ldap->server_port); -+ ADDINT(keybuf, dict_ldap->bind); -+ ADDSTR(keybuf, dict_ldap->bind ? dict_ldap->bind_dn : ""); -+ ADDSTR(keybuf, dict_ldap->bind ? dict_ldap->bind_pw : ""); -+ ADDINT(keybuf, dict_ldap->dereference); -+ ADDINT(keybuf, dict_ldap->chase_referrals); -+ ADDINT(keybuf, dict_ldap->debuglevel); -+ ADDINT(keybuf, dict_ldap->version); -+#ifdef LDAP_API_FEATURE_X_OPENLDAP -+ ADDINT(keybuf, dict_ldap->ldap_ssl); -+ ADDINT(keybuf, dict_ldap->start_tls); -+ ADDINT(keybuf, sslon ? dict_ldap->tls_require_cert : 0); -+ ADDSTR(keybuf, sslon ? dict_ldap->tls_ca_cert_file : ""); -+ ADDSTR(keybuf, sslon ? dict_ldap->tls_ca_cert_dir : ""); -+ ADDSTR(keybuf, sslon ? dict_ldap->tls_cert : ""); -+ ADDSTR(keybuf, sslon ? dict_ldap->tls_key : ""); -+ ADDSTR(keybuf, sslon ? dict_ldap->tls_random_file : ""); -+ ADDSTR(keybuf, sslon ? dict_ldap->tls_cipher_suite : ""); -+#endif -+ -+ key = vstring_str(keybuf); -+ len = VSTRING_LEN(keybuf); -+ -+ if (conn_hash == 0) -+ conn_hash = binhash_create(0); -+ -+ if ((dict_ldap->ht = binhash_locate(conn_hash, key, len)) == 0) { -+ conn = (LDAP_CONN *) mymalloc(sizeof(LDAP_CONN)); -+ conn->conn_ld = 0; -+ conn->conn_refcount = 0; -+ dict_ldap->ht = binhash_enter(conn_hash, key, len, (char *) conn); -+ } -+ ++DICT_LDAP_CONN(dict_ldap)->conn_refcount; -+ -+ vstring_free(keybuf); -+} -+ -+/* - * expand a filter (lookup or result) - */ --static void dict_ldap_expand_filter(char *filter, char *value, VSTRING *out) -+static void dict_ldap_expand_filter(char *ldapsource, char *filter, char *value, VSTRING *out) - { - char *myname = "dict_ldap_expand_filter"; - char *sub, -@@ -462,8 +664,8 @@ - break; - default: - msg_warn -- ("%s: Invalid filter substitution format '%%%c'!", -- myname, *(sub + 1)); -+ ("%s: %s: Invalid filter substitution format '%%%c'!", -+ myname, ldapsource, *(sub + 1)); - /* fall through */ - case 's': - vstring_strcat(out, u); -@@ -486,6 +688,9 @@ - static void dict_ldap_get_values(DICT_LDAP *dict_ldap, LDAPMessage * res, - VSTRING *result) - { -+ static int recursion = 0; -+ static int expansion; -+ long entries = 0; - long i = 0; - int rc = 0; - LDAPMessage *resloop = 0; -@@ -500,13 +705,27 @@ - tv.tv_sec = dict_ldap->timeout; - tv.tv_usec = 0; - -+ if (++recursion == 1) -+ expansion = 0; -+ - if (msg_verbose) -- msg_info("%s: Search found %d match(es)", myname, -+ msg_info("%s[%d]: Search found %d match(es)", myname, recursion, - ldap_count_entries(dict_ldap->ld, res)); - - for (entry = ldap_first_entry(dict_ldap->ld, res); entry != NULL; - entry = ldap_next_entry(dict_ldap->ld, entry)) { - ber = NULL; -+ -+ /* -+ * LDAP should not, but may produce more than the requested maximum -+ * number of entries. -+ */ -+ if (dict_errno == 0 && ++entries > dict_ldap->size_limit -+ && dict_ldap->size_limit) { -+ msg_warn("%s[%d]: %s: Query size limit (%ld) exceeded", myname, -+ recursion, dict_ldap->ldapsource, dict_ldap->size_limit); -+ dict_errno = DICT_ERR_RETRY; -+ } - for (attr = ldap_first_attribute(dict_ldap->ld, entry, &ber); - attr != NULL; - ldap_memfree(attr), attr = ldap_next_attribute(dict_ldap->ld, -@@ -514,17 +733,38 @@ - vals = ldap_get_values(dict_ldap->ld, entry, attr); - if (vals == NULL) { - if (msg_verbose) -- msg_info("%s: Entry doesn't have any values for %s", -- myname, attr); -+ msg_info("%s[%d]: Entry doesn't have any values for %s", -+ myname, recursion, attr); - continue; - } -+ -+ /* -+ * If we previously encountered an error, we still continue -+ * through the loop, to avoid memory leaks, but we don't waste -+ * time accumulating any further results. -+ * -+ * XXX: There may be a more efficient way to exit the loop with no -+ * leaks, but it will likely be more fragile and not worth the -+ * extra code. -+ */ -+ if (dict_errno != 0 || vals[0] == 0) { -+ ldap_value_free(vals); -+ continue; -+ } -+ -+ /* -+ * The "result_attributes" list enumerates all the requested -+ * attributes, first the ordinary result attribtutes and then the -+ * special result attributes that hold DN or LDAP URL values. -+ * -+ * The number of ordinary attributes is "num_attributes". -+ * -+ * We compute the attribute type (ordinary or special) from its -+ * index on the "result_attributes" list. -+ */ - for (i = 0; dict_ldap->result_attributes->argv[i]; i++) { -- if (strcasecmp(dict_ldap->result_attributes->argv[i], -- attr) == 0) { -- if (msg_verbose) -- msg_info("%s: search returned %ld value(s) for requested result attribute %s", myname, i, attr); -+ if (strcasecmp(dict_ldap->result_attributes->argv[i], attr) == 0) - break; -- } - } - - /* -@@ -532,20 +772,38 @@ - * recursing (for dn or url attributes). - */ - if (i < dict_ldap->num_attributes) { -+ /* Ordinary result attribute */ - for (i = 0; vals[i] != NULL; i++) { -+ if (++expansion > dict_ldap->expansion_limit && -+ dict_ldap->expansion_limit) { -+ msg_warn("%s[%d]: %s: Expansion limit exceeded at" -+ " result attribute %s=%s", myname, recursion, -+ dict_ldap->ldapsource, attr, vals[i]); -+ dict_errno = DICT_ERR_RETRY; -+ break; -+ } - if (VSTRING_LEN(result) > 0) - vstring_strcat(result, ","); - if (dict_ldap->result_filter == NULL) - vstring_strcat(result, vals[i]); - else -- dict_ldap_expand_filter(dict_ldap->result_filter, -+ dict_ldap_expand_filter(dict_ldap->ldapsource, -+ dict_ldap->result_filter, - vals[i], result); - } -- } else if (dict_ldap->result_attributes->argv[i]) { -+ if (dict_errno != 0) -+ continue; -+ if (msg_verbose) -+ msg_info("%s[%d]: search returned %ld value(s) for" -+ " requested result attribute %s", -+ myname, recursion, i, attr); -+ } else if (recursion < dict_ldap->recursion_limit -+ && dict_ldap->result_attributes->argv[i]) { -+ /* Special result attribute */ - for (i = 0; vals[i] != NULL; i++) { - if (ldap_is_ldap_url(vals[i])) { - if (msg_verbose) -- msg_info("%s: looking up URL %s", myname, -+ msg_info("%s[%d]: looking up URL %s", myname, recursion, - vals[i]); - rc = ldap_url_parse(vals[i], &url); - if (rc == 0) { -@@ -557,7 +815,7 @@ - } - } else { - if (msg_verbose) -- msg_info("%s: looking up DN %s", myname, vals[i]); -+ msg_info("%s[%d]: looking up DN %s", myname, recursion, vals[i]); - rc = ldap_search_st(dict_ldap->ld, vals[i], - LDAP_SCOPE_BASE, "objectclass=*", - dict_ldap->result_attributes->argv, -@@ -573,11 +831,11 @@ - * Go ahead and treat this as though the DN existed - * and just didn't have any result attributes. - */ -- msg_warn("%s: DN %s not found, skipping ", myname, -- vals[i]); -+ msg_warn("%s[%d]: DN %s not found, skipping ", myname, -+ recursion, vals[i]); - break; - default: -- msg_warn("%s: search error %d: %s ", myname, rc, -+ msg_warn("%s[%d]: search error %d: %s ", myname, recursion, rc, - ldap_err2string(rc)); - dict_errno = DICT_ERR_RETRY; - break; -@@ -585,7 +843,21 @@ - - if (resloop != 0) - ldap_msgfree(resloop); -+ if (dict_errno != 0) -+ break; - } -+ if (dict_errno != 0) -+ continue; -+ if (msg_verbose) -+ msg_info("%s[%d]: search returned %ld value(s) for" -+ " special result attribute %s", -+ myname, recursion, i, attr); -+ } else if (recursion >= dict_ldap->recursion_limit -+ && dict_ldap->result_attributes->argv[i]) { -+ msg_warn("%s[%d]: %s: Recursion limit exceeded" -+ " for special attribute %s=%s", -+ myname, recursion, dict_ldap->ldapsource, attr, vals[0]); -+ dict_errno = DICT_ERR_RETRY; - } - ldap_value_free(vals); - } -@@ -593,7 +865,8 @@ - ber_free(ber, 0); - } - if (msg_verbose) -- msg_info("%s: Leaving %s", myname, myname); -+ msg_info("%s[%d]: Leaving %s", myname, recursion, myname); -+ --recursion; - } - - /* dict_ldap_lookup - find database entry */ -@@ -608,6 +881,7 @@ - VSTRING *escaped_name = 0, - *filter_buf = 0; - int rc = 0; -+ int sizelimit; - char *sub, - *end; - -@@ -624,11 +898,8 @@ - if (dict_ldap->domain) { - const char *p = strrchr(name, '@'); - -- if (p != 0) -- p = p + 1; -- else -- p = name; -- if (match_list_match(dict_ldap->domain, p) == 0) { -+ if (p == 0 || p == name || -+ match_list_match(dict_ldap->domain, ++p) == 0) { - if (msg_verbose) - msg_info("%s: domain of %s not found in domain list", myname, - name); -@@ -644,6 +915,13 @@ - vstring_strcpy(result, ""); - - /* -+ * Because the connection may be shared and invalidated via queries for -+ * another map, update private copy of "ld" from shared connection -+ * container. -+ */ -+ dict_ldap->ld = DICT_LDAP_CONN(dict_ldap)->conn_ld; -+ -+ /* - * Connect to the LDAP server, if necessary. - */ - if (dict_ldap->ld == NULL) { -@@ -663,6 +941,18 @@ - msg_info("%s: Using existing connection for LDAP source %s", - myname, dict_ldap->ldapsource); - -+ /* -+ * Connection caching, means that the connection handle may have the -+ * wrong size limit. Re-adjust before each query. This is cheap, just -+ * sets a field in the ldap connection handle. We also do this in the -+ * connect code, because we sometimes reconnect (below) in the middle of -+ * a query. -+ */ -+ 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) -+ msg_warn("%s: %s: Unable to set query result size limit to %ld.", -+ myname, dict_ldap->ldapsource, dict_ldap->size_limit); - - /* - * Prepare the query. -@@ -720,11 +1010,11 @@ - /* - * No, log the fact and continue. - */ -- msg_warn("%s: Fixed query_filter %s is probably useless", myname, -- dict_ldap->query_filter); -+ msg_warn("%s: %s: Fixed query_filter %s is probably useless", myname, -+ dict_ldap->ldapsource, dict_ldap->query_filter); - vstring_strcpy(filter_buf, dict_ldap->query_filter); - } else { -- dict_ldap_expand_filter(dict_ldap->query_filter, -+ dict_ldap_expand_filter(dict_ldap->ldapsource, dict_ldap->query_filter, - vstring_str(escaped_name), filter_buf); - } - -@@ -747,7 +1037,7 @@ - myname, dict_ldap->ldapsource); - - ldap_unbind(dict_ldap->ld); -- dict_ldap->ld = NULL; -+ dict_ldap->ld = DICT_LDAP_CONN(dict_ldap)->conn_ld = 0; - dict_ldap_connect(dict_ldap); - - /* -@@ -799,7 +1089,7 @@ - * next lookup. - */ - ldap_unbind(dict_ldap->ld); -- dict_ldap->ld = NULL; -+ dict_ldap->ld = DICT_LDAP_CONN(dict_ldap)->conn_ld = 0; - - /* - * And tell the caller to try again later. -@@ -830,9 +1120,18 @@ - { - char *myname = "dict_ldap_close"; - DICT_LDAP *dict_ldap = (DICT_LDAP *) dict; -+ LDAP_CONN *conn = DICT_LDAP_CONN(dict_ldap); -+ BINHASH_INFO *ht = dict_ldap->ht; - -- if (dict_ldap->ld) -- ldap_unbind(dict_ldap->ld); -+ if (--conn->conn_refcount == 0) { -+ if (conn->conn_ld) { -+ if (msg_verbose) -+ msg_info("%s: Closed connection handle for LDAP source %s", -+ myname, dict_ldap->ldapsource); -+ ldap_unbind(conn->conn_ld); -+ } -+ binhash_delete(conn_hash, ht->key, ht->key_len, myfree); -+ } - - myfree(dict_ldap->ldapsource); - myfree(dict_ldap->server_host); -@@ -845,19 +1144,32 @@ - argv_free(dict_ldap->result_attributes); - myfree(dict_ldap->bind_dn); - myfree(dict_ldap->bind_pw); -+#ifdef LDAP_API_FEATURE_X_OPENLDAP -+ myfree(dict_ldap->tls_ca_cert_file); -+ myfree(dict_ldap->tls_ca_cert_dir); -+ myfree(dict_ldap->tls_cert); -+ myfree(dict_ldap->tls_key); -+ myfree(dict_ldap->tls_random_file); -+ myfree(dict_ldap->tls_cipher_suite); -+#endif - dict_free(dict); - } - - /* dict_ldap_open - create association with data base */ - --DICT *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags) -+DICT *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags) - { - char *myname = "dict_ldap_open"; - DICT_LDAP *dict_ldap; - VSTRING *config_param; -+ VSTRING *url_list; -+ char *s; -+ char *h; - char *domainlist; -+ char *server_host; - char *scope; - char *attr; -+ int tmp; - - if (msg_verbose) - msg_info("%s: Using LDAP source %s", myname, ldapsource); -@@ -870,15 +1182,14 @@ - - dict_ldap->ldapsource = mystrdup(ldapsource); - -+ dict_ldap->ld = NULL; -+ - config_param = vstring_alloc(15); - vstring_sprintf(config_param, "%s_server_host", ldapsource); - -- dict_ldap->server_host = -+ server_host = - mystrdup((char *) get_mail_conf_str(vstring_str(config_param), -- "localhost", 0, 0)); -- if (msg_verbose) -- msg_info("%s: %s is %s", myname, vstring_str(config_param), -- dict_ldap->server_host); -+ "localhost", 1, 0)); - - /* - * get configured value of "ldapsource_server_port"; default to LDAP_PORT -@@ -892,11 +1203,87 @@ - dict_ldap->server_port); - - /* -+ * Define LDAP Version. -+ */ -+ vstring_sprintf(config_param, "%s_version", ldapsource); -+ dict_ldap->version = get_mail_conf_int(vstring_str(config_param), 2, 2, 0); -+ switch (dict_ldap->version) { -+ case 2: -+ dict_ldap->version = LDAP_VERSION2; -+ break; -+ case 3: -+ dict_ldap->version = LDAP_VERSION3; -+ break; -+ default: -+ msg_warn("%s: Unknown version %d.", myname, dict_ldap->version); -+ dict_ldap->version = LDAP_VERSION2; -+ } -+ -+#if defined(LDAP_API_FEATURE_X_OPENLDAP) -+ dict_ldap->ldap_ssl = 0; -+#endif -+ -+ url_list = vstring_alloc(32); -+ s = server_host; -+ while ((h = mystrtok(&s, " \t\n\r,")) != NULL) { -+#if defined(LDAP_API_FEATURE_X_OPENLDAP) -+ -+ /* -+ * Convert (host, port) pairs to LDAP URLs -+ */ -+ if (ldap_is_ldap_url(h)) { -+ LDAPURLDesc *url_desc; -+ int rc; -+ -+ if ((rc = ldap_url_parse(h, &url_desc)) != 0) { -+ msg_error("%s: error parsing URL %s: %d: %s; skipping", myname, -+ h, rc, ldap_err2string(rc)); -+ continue; -+ } -+ if (strcasecmp(url_desc->lud_scheme, "ldap") != 0 && -+ dict_ldap->version != LDAP_VERSION3) { -+ msg_warn("%s: URL scheme %s requires protocol version 3", myname, -+ url_desc->lud_scheme); -+ dict_ldap->version = LDAP_VERSION3; -+ } -+ if (strcasecmp(url_desc->lud_scheme, "ldaps") == 0) -+ dict_ldap->ldap_ssl = 1; -+ ldap_free_urldesc(url_desc); -+ vstring_sprintf_append(url_list, " %s", h); -+ } else { -+ if (strrchr(h, ':')) -+ vstring_sprintf_append(url_list, " ldap://%s", h); -+ else -+ vstring_sprintf_append(url_list, " ldap://%s:%d", h, -+ dict_ldap->server_port); -+ } -+#else -+ vstring_sprintf_append(url_list, " %s", h); -+#endif -+ } -+ -+ dict_ldap->server_host = -+ mystrdup(VSTRING_LEN(url_list) > 0 ? vstring_str(url_list) + 1 : ""); -+ -+#if defined(LDAP_API_FEATURE_X_OPENLDAP) -+ /* -+ * With URL scheme, clear port to normalize connection cache key -+ */ -+ -+ dict_ldap->server_port = LDAP_PORT; -+ if (msg_verbose) -+ msg_info("%s: %s server_host URL is %s", myname, ldapsource, -+ dict_ldap->server_host); -+#endif -+ myfree(server_host); -+ vstring_free(url_list); -+ -+ /* - * Scope handling thanks to Carsten Hoeger of SuSE. - */ - vstring_sprintf(config_param, "%s_scope", ldapsource); - scope = -- (char *) get_mail_conf_str(vstring_str(config_param), "sub", 0, 0); -+ (char *) get_mail_conf_str(vstring_str(config_param), "sub", 1, 0); - - if (strcasecmp(scope, "one") == 0) { - dict_ldap->scope = LDAP_SCOPE_ONELEVEL; -@@ -910,12 +1297,15 @@ - msg_info("%s: %s is LDAP_SCOPE_BASE", myname, - vstring_str(config_param)); - -- } else { -+ } else if (strcasecmp(scope, "sub") == 0) { - dict_ldap->scope = LDAP_SCOPE_SUBTREE; - if (msg_verbose) - msg_info("%s: %s is LDAP_SCOPE_SUBTREE", myname, - vstring_str(config_param)); -- -+ } else { -+ dict_ldap->scope = LDAP_SCOPE_SUBTREE; -+ msg_warn("%s: %s: Unrecognized value %s specified for scope; using sub", -+ myname, vstring_str(config_param), scope); - } - - myfree(scope); -@@ -992,6 +1382,8 @@ - msg_info("%s: %s is %s", myname, vstring_str(config_param), attr);; - dict_ldap->result_attributes = argv_split(attr, " ,\t\r\n"); - dict_ldap->num_attributes = dict_ldap->result_attributes->argc; -+ -+ myfree(attr); - - vstring_sprintf(config_param, "%s_special_result_attribute", ldapsource); - attr = mystrdup((char *) get_mail_conf_str(vstring_str(config_param), -@@ -1003,6 +1395,8 @@ - argv_split_append(dict_ldap->result_attributes, attr, " ,\t\r\n"); - } - -+ myfree(attr); -+ - /* - * get configured value of "ldapsource_bind"; default to true - */ -@@ -1040,31 +1434,60 @@ - * get configured value of "ldapsource_cache"; default to false - */ - vstring_sprintf(config_param, "%s_cache", ldapsource); -- dict_ldap->cache = get_mail_conf_bool(vstring_str(config_param), 0); -- if (msg_verbose) -- msg_info("%s: %s is %d", myname, vstring_str(config_param), -- dict_ldap->cache); -+ tmp = get_mail_conf_bool(vstring_str(config_param), 0); -+ if (tmp) -+ msg_warn("%s: %s ignoring cache", myname, vstring_str(config_param)); - - /* - * get configured value of "ldapsource_cache_expiry"; default to 30 - * seconds - */ - vstring_sprintf(config_param, "%s_cache_expiry", ldapsource); -- dict_ldap->cache_expiry = get_mail_conf_int(vstring_str(config_param), -- 30, 0, 0); -- if (msg_verbose) -- msg_info("%s: %s is %ld", myname, vstring_str(config_param), -- dict_ldap->cache_expiry); -+ tmp = get_mail_conf_int(vstring_str(config_param), -1, 0, 0); -+ -+ if (tmp >= 0) -+ msg_warn("%s: %s ignoring cache_expiry", myname, vstring_str(config_param)); - - /* - * get configured value of "ldapsource_cache_size"; default to 32k - */ - vstring_sprintf(config_param, "%s_cache_size", ldapsource); -- dict_ldap->cache_size = get_mail_conf_int(vstring_str(config_param), -- 32768, 0, 0); -+ tmp = get_mail_conf_int(vstring_str(config_param), -+ -1, 0, 0); -+ if (tmp >= 0) -+ msg_warn("%s: %s ignoring cache_size", myname, vstring_str(config_param)); -+ -+ /* -+ * get configured value of "recursion_limit"; default to 1000 -+ */ -+ vstring_sprintf(config_param, "%s_recursion_limit", ldapsource); -+ dict_ldap->recursion_limit = get_mail_conf_int(vstring_str(config_param), -+ 1000, 1, 0); -+ -+ if (msg_verbose) -+ msg_info("%s: %s is %ld", myname, vstring_str(config_param), -+ dict_ldap->recursion_limit); -+ -+ /* -+ * Define LDAP Version. -+ * get configured value of "expansion_limit"; default to 0 -+ */ -+ -+ vstring_sprintf(config_param, "%s_expansion_limit", ldapsource); -+ dict_ldap->expansion_limit = get_mail_conf_int(vstring_str(config_param), -+ 0, 0, 0); -+ if (msg_verbose) -+ msg_info("%s: %s is %ld", myname, vstring_str(config_param), -+ dict_ldap->expansion_limit); -+ /* -+ * get configured value of "size_limit"; default to expansion_limit -+ */ -+ vstring_sprintf(config_param, "%s_size_limit", ldapsource); -+ dict_ldap->size_limit = get_mail_conf_int(vstring_str(config_param), -+ dict_ldap->expansion_limit, 0, 0); - if (msg_verbose) -- msg_info("%s: %s is %ld", myname, vstring_str(config_param), -- dict_ldap->cache_size); -+ msg_info("%s: %s is %ld", myname, vstring_str(config_param), -+ dict_ldap->size_limit); - - /* - * Alias dereferencing suggested by Mike Mattice. -@@ -1074,29 +1497,11 @@ - 0); - - /* -- * Define LDAP Version. -- */ -- vstring_sprintf(config_param, "%s_version", ldapsource); -- dict_ldap->version = get_mail_conf_int(vstring_str(config_param), 2, 0, -- 0); -- switch (dict_ldap->version) { -- case 2: -- dict_ldap->version = LDAP_VERSION2; -- break; -- case 3: -- dict_ldap->version = LDAP_VERSION3; -- break; -- default: -- msg_warn("%s: Unknown version %d.", myname, dict_ldap->version); -- dict_ldap->version = LDAP_VERSION2; -- } -- -- /* - * Make sure only valid options for alias dereferencing are used. - */ - if (dict_ldap->dereference < 0 || dict_ldap->dereference > 3) { -- msg_warn("%s: Unrecognized value %d specified for %s; using 0", -- myname, dict_ldap->dereference, vstring_str(config_param)); -+ msg_warn("%s: %s: Unrecognized value %d specified for %s; using 0", -+ myname, ldapsource, dict_ldap->dereference, vstring_str(config_param)); - dict_ldap->dereference = 0; - } - if (msg_verbose) -@@ -1110,6 +1515,68 @@ - msg_info("%s: %s is %d", myname, vstring_str(config_param), - dict_ldap->chase_referrals); - -+#ifdef LDAP_API_FEATURE_X_OPENLDAP -+ -+ /* -+ * TLS options -+ */ -+ /* get configured value of "start_tls"; default to no */ -+ vstring_sprintf(config_param, "%s_start_tls", ldapsource); -+ dict_ldap->start_tls = get_mail_conf_bool(vstring_str(config_param), 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; -+ } -+ -+ /* get configured value of "tls_require_cert"; default to no */ -+ vstring_sprintf(config_param, "%s_tls_require_cert", ldapsource); -+ dict_ldap->tls_require_cert = get_mail_conf_bool(vstring_str(config_param), 0); -+ -+ /* get configured value of "tls_ca_cert_file"; default "" */ -+ vstring_sprintf(config_param, "%s_tls_ca_cert_file", ldapsource); -+ dict_ldap->tls_ca_cert_file = mystrdup((char *) -+ get_mail_conf_str(vstring_str -+ (config_param), "", 0, -+ 0)); -+ -+ /* get configured value of "tls_ca_cert_dir"; default "" */ -+ vstring_sprintf(config_param, "%s_tls_ca_cert_dir", ldapsource); -+ dict_ldap->tls_ca_cert_dir = mystrdup((char *) -+ get_mail_conf_str(vstring_str -+ (config_param), "", 0, -+ 0)); -+ -+ /* get configured value of "tls_cert"; default "" */ -+ vstring_sprintf(config_param, "%s_tls_cert", ldapsource); -+ dict_ldap->tls_cert = mystrdup((char *) -+ get_mail_conf_str(vstring_str -+ (config_param), "", 0, -+ 0)); -+ -+ /* get configured value of "tls_key"; default "" */ -+ vstring_sprintf(config_param, "%s_tls_key", ldapsource); -+ dict_ldap->tls_key = mystrdup((char *) -+ get_mail_conf_str(vstring_str -+ (config_param), "", 0, -+ 0)); -+ -+ /* get configured value of "tls_random_file"; default "" */ -+ vstring_sprintf(config_param, "%s_tls_random_file", ldapsource); -+ dict_ldap->tls_random_file = mystrdup((char *) -+ get_mail_conf_str(vstring_str -+ (config_param), "", 0, -+ 0)); -+ -+ /* get configured value of "tls_cipher_suite"; default "" */ -+ vstring_sprintf(config_param, "%s_tls_cipher_suite", ldapsource); -+ dict_ldap->tls_cipher_suite = mystrdup((char *) -+ get_mail_conf_str(vstring_str -+ (config_param), "", 0, -+ 0)); -+#endif -+ -+ - /* - * Debug level. - */ -@@ -1122,21 +1589,13 @@ - dict_ldap->debuglevel); - #endif - -- dict_ldap_connect(dict_ldap); -- - /* -- * if dict_ldap_connect() set dict_errno, free dict_ldap and abort. -+ * Find or allocate shared LDAP connection container. - */ -- if (dict_errno) { -- if (dict_ldap->ld) -- ldap_unbind(dict_ldap->ld); -- -- myfree((char *) dict_ldap); -- return (0); -- } -+ dict_ldap_conn_find(dict_ldap); - - /* -- * Otherwise, we're all set. Return the new dict_ldap structure. -+ * Return the new dict_ldap structure. - */ - return (DICT_DEBUG (&dict_ldap->dict)); - } diff --git a/postfix-ipv6.patch b/postfix-ipv6.patch deleted file mode 100644 index f2bff74..0000000 --- a/postfix-ipv6.patch +++ /dev/null @@ -1,3031 +0,0 @@ -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/makedefs postfix-2.0.16/makedefs ---- postfix-2.0.16.orig/makedefs 2003-01-23 14:45:02.000000000 +0100 -+++ postfix-2.0.16/makedefs 2005-01-07 18:25:30.197331464 +0100 -@@ -52,6 +52,21 @@ - SYSTEM=`(uname -s) 2>/dev/null` - RELEASE=`(uname -r) 2>/dev/null` - VERSION=`(uname -v) 2>/dev/null` -+if test -f /usr/include/netinet6/in6.h; then -+ grep __KAME__ /usr/include/netinet6/in6.h 2>&1 >/dev/null -+ if [ $? = 1 ]; then -+ INET6= -+ else -+ if [ -f /usr/local/v6/lib/libinet6.a ]; then -+ INET6=kame -+ else -+ INET6=kame-merged -+ fi -+ fi -+fi -+if [ -z "$INET6" -a -f /usr/include/netinet/ip6.h -a -f /usr/include/linux/icmpv6.h ]; then -+ INET6=linux -+fi - - case "$VERSION" in - dcosx*) SYSTEM=$VERSION;; -@@ -318,6 +333,26 @@ - - : ${CC='gcc $(WARN)'} ${OPT='-O'} ${DEBUG='-g'} ${AWK=awk} - -+case "$INET6" in -+kame) -+ CCARGS="$CCARGS -DINET6 -D__ss_family=ss_family -D__ss_len=ss_len" -+ if test -f /usr/local/v6/lib/libinet6.a; then -+ SYSLIBS="$SYSLIBS -L/usr/local/v6/lib -linet6" -+ fi -+ ;; -+kame-merged) -+ CCARGS="$CCARGS -DINET6 -D__ss_family=ss_family -D__ss_len=ss_len" -+ ;; -+linux) -+ CCARGS="$CCARGS -DINET6 -D__ss_family=ss_family" -+ if test -f /usr/include/libinet6/netinet/ip6.h -+ then -+ CCARGS="$CCARGS -I/usr/include/libinet6 -DUSAGI_LIBINET6" -+ SYSLIBS="$SYSLIBS -linet6" -+ fi -+ ;; -+esac -+ - export SYSTYPE AR ARFL RANLIB SYSLIBS CC OPT DEBUG AWK OPTS - - sed 's/ / /g' < - #include - #include -+#ifdef INET6 -+#include -+#include -+#include -+#endif -+#include - - /* Global library. */ - -@@ -75,6 +81,9 @@ - const char *mynetworks(void) - { - static VSTRING *result; -+#ifdef INET6 -+ char hbuf[NI_MAXHOST]; -+#endif - - if (result == 0) { - char *myname = "mynetworks"; -@@ -87,6 +96,13 @@ - int junk; - int i; - int mask_style; -+#ifdef INET6 -+ struct sockaddr *sa; -+ struct sockaddr_in6 *addr6; -+ struct sockaddr_in6 *mask6; -+ struct in6_addr net6; -+ int j; -+#endif - - mask_style = name_mask("mynetworks mask style", mask_styles, - var_mynetworks_style); -@@ -96,8 +112,45 @@ - my_mask_list = own_inet_mask_list(); - - for (i = 0; i < my_addr_list->used; i++) { -+#ifdef INET6 -+ sa = (struct sockaddr *)&my_addr_list->addrs[i]; -+ if (sa->sa_family == AF_INET6) { -+ addr6 = (struct sockaddr_in6 *)sa; -+ mask6 = (struct sockaddr_in6 *)&my_mask_list->addrs[i]; -+ -+ switch (mask_style) { -+ case MASK_STYLE_CLASS: -+ /* treat as subnet for IPv6 */ -+ case MASK_STYLE_SUBNET: -+ for (j=0; j<16; j++) -+ net6.s6_addr[j] = addr6->sin6_addr.s6_addr[j] & mask6->sin6_addr.s6_addr[j]; -+ for(shift=128; shift>0; shift--) -+ if ((mask6->sin6_addr.s6_addr[(shift-1) / 8]) & (0x80 >> ((shift-1) % 8))) -+ break; -+ break; -+ case MASK_STYLE_HOST: -+ memcpy (&net6, &(addr6->sin6_addr), sizeof(net6)); -+ shift=128; -+ break; -+ default: -+ msg_panic("unknown mynetworks mask style: %s", -+ var_mynetworks_style); -+ } -+ inet_ntop(AF_INET6, &net6, hbuf, sizeof(hbuf)); -+ if (!shift) -+ msg_warn("%s: skipped network with zero mask: [%s/0]", myname, hbuf); -+ else -+ vstring_sprintf_append(result, "[%s/%d] ", hbuf, shift); -+ continue; -+ } else if (sa->sa_family != AF_INET) { -+ continue; -+ } -+ addr = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr); -+ mask = ntohl(((struct sockaddr_in *)&my_mask_list->addrs[i])->sin_addr.s_addr); -+#else - addr = ntohl(my_addr_list->addrs[i].s_addr); - mask = ntohl(my_mask_list->addrs[i].s_addr); -+#endif - - switch (mask_style) { - -@@ -119,8 +172,15 @@ - mask = IN_CLASSD_NET; - shift = IN_CLASSD_NSHIFT; - } else { -+#ifdef INET6 -+ if (getnameinfo(sa, SA_LEN(sa), hbuf, sizeof(hbuf), NULL, 0, -+ NI_NUMERICHOST)) -+ strncpy(hbuf, "???", sizeof(hbuf)); -+ msg_fatal("%s: bad address class: %s", myname, hbuf); -+#else - msg_fatal("%s: bad address class: %s", - myname, inet_ntoa(my_addr_list->addrs[i])); -+#endif - } - break; - -@@ -146,6 +206,18 @@ - var_mynetworks_style); - } - net.s_addr = htonl(addr & mask); -+ if (shift == BITS_PER_ADDR) { -+#ifdef INET6 -+ if (getnameinfo(sa, SA_LEN(sa), hbuf, sizeof(hbuf), NULL, 0, -+ NI_NUMERICHOST)) -+ strncpy(hbuf, "???", sizeof(hbuf)); -+ msg_warn("%s: skipped network with zero mask: %s/0", myname, hbuf); -+#else -+ msg_warn("%s: skipped network with zero mask: %s/0", -+ myname, inet_ntoa(my_addr_list->addrs[i])); -+#endif -+ continue; -+ } - vstring_sprintf_append(result, "%s/%d ", - inet_ntoa(net), BITS_PER_ADDR - shift); - } -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/global/own_inet_addr.c postfix-2.0.16/src/global/own_inet_addr.c ---- postfix-2.0.16.orig/src/global/own_inet_addr.c 2002-10-25 01:19:19.000000000 +0200 -+++ postfix-2.0.16/src/global/own_inet_addr.c 2005-01-07 18:25:30.198331312 +0100 -@@ -50,6 +50,10 @@ - #include - #include - #include -+#ifdef INET6 -+#include -+#include -+#endif - - #ifdef STRCASECMP_IN_STRINGS_H - #include -@@ -113,10 +117,11 @@ - */ - else { - bufp = hosts = mystrdup(var_inet_interfaces); -- while ((host = mystrtok(&bufp, sep)) != 0) -+ while ((host = mystrtok(&bufp, sep)) != 0) { - if (inet_addr_host(addr_list, host) == 0) - msg_fatal("config variable %s: host not found: %s", - VAR_INET_INTERFACES, host); -+ } - myfree(hosts); - - /* -@@ -133,15 +138,39 @@ - msg_fatal("could not find any active network interfaces"); - for (nvirtual = 0; nvirtual < addr_list->used; nvirtual++) { - for (nlocal = 0; /* see below */ ; nlocal++) { -- if (nlocal >= local_addrs.used) -+ if (nlocal >= local_addrs.used) { -+#ifdef INET6 -+ char hbuf[NI_MAXHOST]; -+ if (getnameinfo((struct sockaddr *)&addr_list->addrs[nvirtual], -+ SS_LEN(addr_list->addrs[nvirtual]), hbuf, -+ sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) -+ strncpy(hbuf, "???", sizeof(hbuf)); -+ msg_fatal("parameter %s: no local interface found for %s", -+ VAR_INET_INTERFACES, hbuf); -+#else - msg_fatal("parameter %s: no local interface found for %s", - VAR_INET_INTERFACES, - inet_ntoa(addr_list->addrs[nvirtual])); -+#endif -+ } -+#ifdef INET6 -+ if (addr_list->addrs[nvirtual].ss_family == -+ local_addrs.addrs[nlocal].ss_family && -+ SS_LEN(addr_list->addrs[nvirtual]) == -+ SS_LEN(local_addrs.addrs[nlocal]) && -+ memcmp(&addr_list->addrs[nvirtual], -+ &local_addrs.addrs[nlocal], -+ SS_LEN(local_addrs.addrs[nlocal])) == 0) { -+ inet_addr_list_append(mask_list, (struct sockaddr *)&local_masks.addrs[nlocal]); -+ break; -+ } -+#else - if (addr_list->addrs[nvirtual].s_addr - == local_addrs.addrs[nlocal].s_addr) { - inet_addr_list_append(mask_list, &local_masks.addrs[nlocal]); - break; - } -+#endif - } - } - inet_addr_list_free(&local_addrs); -@@ -151,6 +180,42 @@ - - /* own_inet_addr - is this my own internet address */ - -+#ifdef INET6 -+int own_inet_addr(struct sockaddr * addr) -+{ -+ int i; -+ char *p, *q; -+ int l; -+ struct sockaddr *sa; -+ -+ if (addr_list.used == 0) -+ own_inet_addr_init(&addr_list, &mask_list); -+ -+ for (i = 0; i < addr_list.used; i++) { -+ sa = (struct sockaddr *)&addr_list.addrs[i]; -+ if (addr->sa_family != sa->sa_family) -+ continue; -+ switch (addr->sa_family) { -+ case AF_INET: -+ p = (char *)&((struct sockaddr_in *)addr)->sin_addr; -+ q = (char *)&((struct sockaddr_in *)&addr_list.addrs[i])->sin_addr; -+ l = sizeof(struct in_addr); -+ break; -+ case AF_INET6: -+ /* XXX scope */ -+ p = (char *)&((struct sockaddr_in6 *)addr)->sin6_addr; -+ q = (char *)&((struct sockaddr_in6 *)&addr_list.addrs[i])->sin6_addr; -+ l = sizeof(struct in6_addr); -+ break; -+ default: -+ continue; -+ } -+ if (memcmp(p, q, l) == 0) -+ return (1); -+ } -+ return (0); -+} -+#else - int own_inet_addr(struct in_addr * addr) - { - int i; -@@ -161,8 +226,8 @@ - for (i = 0; i < addr_list.used; i++) - if (addr->s_addr == addr_list.addrs[i].s_addr) - return (1); -- return (0); - } -+#endif - - /* own_inet_addr_list - return list of addresses */ - -@@ -213,6 +278,45 @@ - - /* proxy_inet_addr - is this my proxy internet address */ - -+#ifdef INET6 -+int proxy_inet_addr(struct sockaddr * addr) -+{ -+ int i; -+ char *p, *q; -+ int l; -+ struct sockaddr *sa; -+ -+ if (*var_proxy_interfaces == 0) -+ return (0); -+ -+ if (proxy_list.used == 0) -+ proxy_inet_addr_init(&proxy_list); -+ -+ for (i = 0; i < proxy_list.used; i++) { -+ sa = (struct sockaddr *)&proxy_list.addrs[i]; -+ if (addr->sa_family != sa->sa_family) -+ continue; -+ switch (addr->sa_family) { -+ case AF_INET: -+ p = (char *)&((struct sockaddr_in *)addr)->sin_addr; -+ q = (char *)&((struct sockaddr_in *)&addr_list.addrs[i])->sin_addr; -+ l = sizeof(struct in_addr); -+ break; -+ case AF_INET6: -+ /* XXX scope */ -+ p = (char *)&((struct sockaddr_in6 *)addr)->sin6_addr; -+ q = (char *)&((struct sockaddr_in6 *)&addr_list.addrs[i])->sin6_addr; -+ l = sizeof(struct in6_addr); -+ break; -+ default: -+ continue; -+ } -+ if (memcmp(p, q, l) == 0) -+ return (1); -+ } -+ return (0); -+} -+#else - int proxy_inet_addr(struct in_addr * addr) - { - int i; -@@ -228,6 +332,7 @@ - return (1); - return (0); - } -+#endif - - /* proxy_inet_addr_list - return list of addresses */ - -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/global/own_inet_addr.h postfix-2.0.16/src/global/own_inet_addr.h ---- postfix-2.0.16.orig/src/global/own_inet_addr.h 2002-10-25 01:07:05.000000000 +0200 -+++ postfix-2.0.16/src/global/own_inet_addr.h 2005-01-07 18:25:30.199331160 +0100 -@@ -15,14 +15,25 @@ - * System library. - */ - #include -+#ifdef INET6 -+#include -+#endif - - /* - * External interface. - */ -+#ifdef INET6 -+extern int own_inet_addr(struct sockaddr *); -+#else - extern int own_inet_addr(struct in_addr *); -+#endif - extern struct INET_ADDR_LIST *own_inet_addr_list(void); - extern struct INET_ADDR_LIST *own_inet_mask_list(void); -+#ifdef INET6 -+extern int proxy_inet_addr(struct sockaddr *); -+#else - extern int proxy_inet_addr(struct in_addr *); -+#endif - extern struct INET_ADDR_LIST *proxy_inet_addr_list(void); - - /* LICENSE -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/global/peer_name.c postfix-2.0.16/src/global/peer_name.c ---- postfix-2.0.16.orig/src/global/peer_name.c 2001-01-28 16:23:02.000000000 +0100 -+++ postfix-2.0.16/src/global/peer_name.c 2005-01-07 18:25:30.199331160 +0100 -@@ -69,12 +69,32 @@ - PEER_NAME *peer_name(int sock) - { - static PEER_NAME peer; -- struct sockaddr_in sin; -- SOCKADDR_SIZE len = sizeof(sin); -+ union sockunion { -+ struct { -+ u_char si_len; -+ u_char si_family; -+ u_short si_port; -+ } su_si; -+ struct sockaddr peer_un; -+ struct sockaddr_in peer_un4; -+#ifdef INET6 -+ struct sockaddr_in6 peer_un6; -+#endif -+ } p_un; -+#define sun p_un.peer_un -+#define sin p_un.peer_un4 -+#ifdef INET6 -+#define sin6 p_un.peer_un6 -+ static char hbuf[NI_MAXHOST]; -+ static char abuf[NI_MAXHOST]; -+#else - struct hostent *hp; -+#endif -+ SOCKADDR_SIZE len = sizeof(p_un); - -- if (getpeername(sock, (struct sockaddr *) & sin, &len) == 0) { -- switch (sin.sin_family) { -+ if (getpeername(sock, (struct sockaddr *)&p_un, &len) == 0) { -+ switch (p_un.peer_un.sa_family) { -+#ifndef INET6 - case AF_INET: - peer.type = PEER_TYPE_INET; - hp = gethostbyaddr((char *) &(sin.sin_addr), -@@ -83,6 +103,24 @@ - hp->h_name : "unknown"); - peer.addr = inet_ntoa(sin.sin_addr); - return (&peer); -+#else -+ case AF_INET: -+ peer.type = PEER_TYPE_INET; -+ if (getnameinfo(&sun, len, hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD) != 0) -+ peer.name = "unknown"; -+ else -+ peer.name = hbuf; -+ peer.addr = abuf; -+ return (&peer); -+ case AF_INET6: -+ peer.type = PEER_TYPE_INET6; -+ if (getnameinfo(&sun, len, hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD) != 0) -+ peer.name = "unknown"; -+ else -+ peer.name = hbuf; -+ peer.addr = abuf; -+ return (&peer); -+#endif - case AF_UNSPEC: - case AF_UNIX: - peer.type = PEER_TYPE_LOCAL; -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/global/peer_name.h postfix-2.0.16/src/global/peer_name.h ---- postfix-2.0.16.orig/src/global/peer_name.h 1998-12-11 19:55:32.000000000 +0100 -+++ postfix-2.0.16/src/global/peer_name.h 2005-01-07 18:25:30.199331160 +0100 -@@ -22,6 +22,9 @@ - #define PEER_TYPE_UNKNOWN 0 - #define PEER_TYPE_INET 1 - #define PEER_TYPE_LOCAL 2 -+#ifdef INET6 -+#define PEER_TYPE_INET6 3 -+#endif - - extern PEER_NAME *peer_name(int); - -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/global/resolve_local.c postfix-2.0.16/src/global/resolve_local.c ---- postfix-2.0.16.orig/src/global/resolve_local.c 2002-10-25 01:21:20.000000000 +0200 -+++ postfix-2.0.16/src/global/resolve_local.c 2005-01-07 18:25:30.199331160 +0100 -@@ -43,6 +43,7 @@ - #include - #include - #include -+#include - - #ifndef INADDR_NONE - #define INADDR_NONE 0xffffffff -@@ -80,7 +81,12 @@ - { - char *saved_addr = mystrdup(addr); - char *dest; -+#ifdef INET6 -+ struct addrinfo hints, *res, *res0; -+ int error; -+#else - struct in_addr ipaddr; -+#endif - int len; - - #define RETURN(x) { myfree(saved_addr); return(x); } -@@ -118,9 +124,25 @@ - if (*dest == '[' && dest[len - 1] == ']') { - dest++; - dest[len -= 2] = 0; -+#ifdef INET6 -+ memset(&hints, 0, sizeof(hints)); -+ hints.ai_family = PF_UNSPEC; -+ hints.ai_socktype = SOCK_DGRAM; -+ error = getaddrinfo(dest, NULL, &hints, &res0); -+ if (!error) { -+ for (res = res0; res; res = res->ai_next) { -+ if (own_inet_addr(res->ai_addr)) { -+ freeaddrinfo(res0); -+ RETURN(1); -+ } -+ } -+ freeaddrinfo(res0); -+ } -+#else - if ((ipaddr.s_addr = inet_addr(dest)) != INADDR_NONE - && (own_inet_addr(&ipaddr) || proxy_inet_addr(&ipaddr))) - RETURN(1); -+#endif - } - - /* -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/global/wildcard_inet_addr.c postfix-2.0.16/src/global/wildcard_inet_addr.c ---- postfix-2.0.16.orig/src/global/wildcard_inet_addr.c 1970-01-01 01:00:00.000000000 +0100 -+++ postfix-2.0.16/src/global/wildcard_inet_addr.c 2005-01-07 18:25:30.200331008 +0100 -@@ -0,0 +1,82 @@ -+/* System library. */ -+ -+#include -+#include -+#include -+#include -+#ifdef INET6 -+#include -+#endif -+#include -+ -+#ifdef STRCASECMP_IN_STRINGS_H -+#include -+#endif -+ -+/* Utility library. */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Global library. */ -+ -+#include -+#include -+ -+/* Application-specific. */ -+static INET_ADDR_LIST addr_list; -+ -+/* wildcard_inet_addr_init - initialize my own address list */ -+ -+static void wildcard_inet_addr_init(INET_ADDR_LIST *addr_list) -+{ -+#ifdef INET6 -+ struct addrinfo hints, *res, *res0; -+ char hbuf[NI_MAXHOST]; -+ int error; -+#ifdef NI_WITHSCOPEID -+ const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID; -+#else -+ const int niflags = NI_NUMERICHOST; -+#endif -+ -+ inet_addr_list_init(addr_list); -+ -+ memset(&hints, 0, sizeof(hints)); -+ hints.ai_family = PF_UNSPEC; -+ hints.ai_socktype = SOCK_STREAM; -+ hints.ai_flags = AI_PASSIVE; -+ error = getaddrinfo(NULL, "0", &hints, &res0); -+ if (error) -+ msg_fatal("could not get list of wildcard addresses"); -+ for (res = res0; res; res = res->ai_next) { -+ if (res->ai_family != AF_INET && res->ai_family != AF_INET6) -+ continue; -+ if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf), -+ NULL, 0, niflags) != 0) -+ continue; -+ if (inet_addr_host(addr_list, hbuf) == 0) -+ continue; /* msg_fatal("config variable %s: host not found: %s", -+ VAR_INET_INTERFACES, hbuf); */ -+ } -+ freeaddrinfo(res0); -+#else -+ if (inet_addr_host(addr_list, "0.0.0.0") == 0) -+ msg_fatal("config variable %s: host not found: %s", -+ VAR_INET_INTERFACES, "0.0.0.0"); -+#endif -+} -+ -+/* wildcard_inet_addr_list - return list of addresses */ -+ -+INET_ADDR_LIST *wildcard_inet_addr_list(void) -+{ -+ if (addr_list.used == 0) -+ wildcard_inet_addr_init(&addr_list); -+ -+ return (&addr_list); -+} -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/global/wildcard_inet_addr.h postfix-2.0.16/src/global/wildcard_inet_addr.h ---- postfix-2.0.16.orig/src/global/wildcard_inet_addr.h 1970-01-01 01:00:00.000000000 +0100 -+++ postfix-2.0.16/src/global/wildcard_inet_addr.h 2005-01-07 18:25:30.200331008 +0100 -@@ -0,0 +1,36 @@ -+#ifndef _WILDCARD_INET_ADDR_H_INCLUDED_ -+#define _WILDCARD_INET_ADDR_H_INCLUDED_ -+ -+/*++ -+/* NAME -+/* wildcard_inet_addr_list 3h -+/* SUMMARY -+/* grab the list of wildcard IP addresses. -+/* SYNOPSIS -+/* #include -+/* DESCRIPTION -+/* .nf -+/*--*/ -+ -+ /* -+ * System library. -+ */ -+#include -+#ifdef INET6 -+#include -+#endif -+ -+ /* -+ * External interface. -+ */ -+extern struct INET_ADDR_LIST *wildcard_inet_addr_list(void); -+ -+/* LICENSE -+/* .ad -+/* .fi -+/* foo -+/* AUTHOR(S) -+/* Jun-ichiro itojun Hagino -+/*--*/ -+ -+#endif -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/master/master_ent.c postfix-2.0.16/src/master/master_ent.c ---- postfix-2.0.16.orig/src/master/master_ent.c 2003-06-18 21:19:46.000000000 +0200 -+++ postfix-2.0.16/src/master/master_ent.c 2005-01-07 18:35:28.571364784 +0100 -@@ -92,6 +92,7 @@ - #include - #include - #include -+#include - - /* Local stuff. */ - -@@ -307,8 +308,13 @@ - inet_addr_list_uniq(MASTER_INET_ADDRLIST(serv)); - serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used; - } else if (strcasecmp(saved_interfaces, DEF_INET_INTERFACES) == 0) { -+#ifdef INET6 -+ MASTER_INET_ADDRLIST(serv) = wildcard_inet_addr_list(); -+ serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used; -+#else - MASTER_INET_ADDRLIST(serv) = 0; /* wild-card */ - serv->listen_fd_count = 1; -+#endif - } else { - MASTER_INET_ADDRLIST(serv) = own_inet_addr_list(); /* virtual */ - inet_addr_list_uniq(MASTER_INET_ADDRLIST(serv)); -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/master/master_listen.c postfix-2.0.16/src/master/master_listen.c ---- postfix-2.0.16.orig/src/master/master_listen.c 2001-05-01 00:47:57.000000000 +0200 -+++ postfix-2.0.16/src/master/master_listen.c 2005-01-07 18:25:30.201330856 +0100 -@@ -64,13 +64,22 @@ - - #include "master.h" - -+#ifdef INET6 -+#include -+#include -+#endif -+ - /* master_listen_init - enable connection requests */ - - void master_listen_init(MASTER_SERV *serv) - { - char *myname = "master_listen_init"; - char *end_point; -- int n; -+ int n,m,tmpfd; -+#ifdef INET6 -+ char hbuf[NI_MAXHOST]; -+ SOCKADDR_SIZE salen; -+#endif - - /* - * Find out what transport we should use, then create one or more -@@ -111,18 +120,31 @@ - serv->listen_fd[0] = - inet_listen(MASTER_INET_PORT(serv), - serv->max_proc > var_proc_limit ? -- serv->max_proc : var_proc_limit, NON_BLOCKING); -+ serv->max_proc : var_proc_limit, NON_BLOCKING, 1); - close_on_exec(serv->listen_fd[0], CLOSE_ON_EXEC); - } else { /* virtual or host:port */ -- for (n = 0; n < serv->listen_fd_count; n++) { -+ for (m = n = 0; n < serv->listen_fd_count; n++) { -+#ifdef INET6 -+ if (getnameinfo((struct sockaddr *)&MASTER_INET_ADDRLIST(serv)->addrs[n], -+ SA_LEN((struct sockaddr *)&MASTER_INET_ADDRLIST(serv)->addrs[n]), -+ hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST)) { -+ strncpy(hbuf, "?????", sizeof(hbuf)); -+ } -+ end_point = concatenate(hbuf, ":", MASTER_INET_PORT(serv), (char *) 0); -+#else - end_point = concatenate(inet_ntoa(MASTER_INET_ADDRLIST(serv)->addrs[n]), - ":", MASTER_INET_PORT(serv), (char *) 0); -- serv->listen_fd[n] -+#endif -+ tmpfd - = inet_listen(end_point, serv->max_proc > var_proc_limit ? -- serv->max_proc : var_proc_limit, NON_BLOCKING); -- close_on_exec(serv->listen_fd[n], CLOSE_ON_EXEC); -+ serv->max_proc : var_proc_limit, NON_BLOCKING, 0); -+ if (tmpfd >= 0) { -+ serv->listen_fd[m] = tmpfd; -+ close_on_exec(serv->listen_fd[m++], CLOSE_ON_EXEC); -+ } - myfree(end_point); - } -+ serv->listen_fd_count=m; - } - break; - default: -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/smtp/Makefile.in postfix-2.0.16/src/smtp/Makefile.in ---- postfix-2.0.16.orig/src/smtp/Makefile.in 2005-01-07 18:22:25.253447208 +0100 -+++ postfix-2.0.16/src/smtp/Makefile.in 2005-01-07 18:25:30.201330856 +0100 -@@ -144,6 +144,7 @@ - smtp_connect.o: ../../include/mail_params.h - smtp_connect.o: ../../include/own_inet_addr.h - smtp_connect.o: ../../include/dns.h -+smtp_connect.o: ../../include/get_port.h - smtp_connect.o: smtp.h - smtp_connect.o: ../../include/argv.h - smtp_connect.o: ../../include/deliver_request.h -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/smtp/smtp_addr.c postfix-2.0.16/src/smtp/smtp_addr.c ---- postfix-2.0.16.orig/src/smtp/smtp_addr.c 2002-10-25 01:03:11.000000000 +0200 -+++ postfix-2.0.16/src/smtp/smtp_addr.c 2005-01-07 18:25:30.201330856 +0100 -@@ -134,18 +134,68 @@ - static void smtp_print_addr(char *what, DNS_RR *addr_list) - { - DNS_RR *addr; -- struct in_addr in_addr; -+#ifdef INET6 -+ struct sockaddr_storage ss; -+#else -+ struct sockaddr ss; -+#endif -+ struct sockaddr_in *sin; -+#ifdef INET6 -+ struct sockaddr_in6 *sin6; -+ char hbuf[NI_MAXHOST]; -+#else -+ char hbuf[sizeof("255.255.255.255") + 1]; -+#endif - - msg_info("begin %s address list", what); - for (addr = addr_list; addr; addr = addr->next) { -- if (addr->data_len > sizeof(addr)) { -- msg_warn("skipping address length %d", addr->data_len); -- } else { -- memcpy((char *) &in_addr, addr->data, sizeof(in_addr)); -- msg_info("pref %4d host %s/%s", -- addr->pref, addr->name, -- inet_ntoa(in_addr)); -+ if (addr->class != C_IN) { -+ msg_warn("skipping unsupported address (class=%u)", addr->class); -+ continue; - } -+ switch (addr->type) { -+ case T_A: -+ if (addr->data_len != sizeof(sin->sin_addr)) { -+ msg_warn("skipping invalid address (AAAA, len=%u)", -+ addr->data_len); -+ continue; -+ } -+ sin = (struct sockaddr_in *)&ss; -+ memset(sin, 0, sizeof(*sin)); -+ sin->sin_family = AF_INET; -+#ifdef HAS_SA_LEN -+ sin->sin_len = sizeof(*sin); -+#endif -+ memcpy(&sin->sin_addr, addr->data, sizeof(sin->sin_addr)); -+ break; -+#ifdef INET6 -+ case T_AAAA: -+ if (addr->data_len != sizeof(sin6->sin6_addr)) { -+ msg_warn("skipping invalid address (AAAA, len=%u)", -+ addr->data_len); -+ continue; -+ } -+ sin6 = (struct sockaddr_in6 *)&ss; -+ memset(sin6, 0, sizeof(*sin6)); -+ sin6->sin6_family = AF_INET6; -+#ifdef HAS_SA_LEN -+ sin6->sin6_len = sizeof(*sin6); -+#endif -+ memcpy(&sin6->sin6_addr, addr->data, sizeof(sin6->sin6_addr)); -+ break; -+#endif -+ default: -+ msg_warn("skipping unsupported address (type=%u)", addr->type); -+ continue; -+ } -+ -+#ifdef INET6 -+ (void)getnameinfo((struct sockaddr *)&ss, SS_LEN(ss), -+ hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST); -+#else -+ (void)inet_ntop(AF_INET, &sin->sin_addr, hbuf, sizeof(hbuf)); -+#endif -+ msg_info("pref %4d host %s/%s", addr->pref, addr->name, hbuf); - } - msg_info("end %s address list", what); - } -@@ -155,15 +205,23 @@ - static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref, VSTRING *why) - { - char *myname = "smtp_addr_one"; -+#ifndef INET6 - struct in_addr inaddr; -- DNS_FIXED fixed; - DNS_RR *addr = 0; - DNS_RR *rr; - struct hostent *hp; -+#else -+ struct addrinfo hints, *res0, *res; -+ int error = -1; -+ char *addr; -+ size_t addrlen; -+#endif -+ DNS_FIXED fixed; - - if (msg_verbose) - msg_info("%s: host %s", myname, host); - -+#ifndef INET6 - /* - * Interpret a numerical name as an address. - */ -@@ -216,6 +274,48 @@ - smtp_errno = SMTP_FAIL; - break; - } -+#else -+ memset(&hints, 0, sizeof(hints)); -+ hints.ai_family = PF_UNSPEC; -+ hints.ai_socktype = SOCK_STREAM; -+ error = getaddrinfo(host, NULL, &hints, &res0); -+ if (error) { -+ switch (error) { -+ case EAI_AGAIN: -+ smtp_errno = SMTP_RETRY; -+ break; -+ default: -+ vstring_sprintf(why, "[%s]: %s",host,gai_strerror(error)); -+ smtp_errno = SMTP_FAIL; -+ break; -+ } -+ return (addr_list); -+ } -+ for (res = res0; res; res = res->ai_next) { -+ memset((char *) &fixed, 0, sizeof(fixed)); -+ switch(res->ai_family) { -+ case AF_INET6: -+ /* XXX not scope friendly */ -+ fixed.type = T_AAAA; -+ addr = (char *)&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr; -+ addrlen = sizeof(struct in6_addr); -+ break; -+ case AF_INET: -+ fixed.type = T_A; -+ addr = (char *)&((struct sockaddr_in *)res->ai_addr)->sin_addr; -+ addrlen = sizeof(struct in_addr); -+ break; -+ default: -+ msg_warn("%s: unknown address family %d for %s", -+ myname, res->ai_family, host); -+ continue; -+ } -+ addr_list = dns_rr_append(addr_list, -+ dns_rr_create(host, &fixed, pref, addr, addrlen)); -+ } -+ if (res0) -+ freeaddrinfo(res0); -+#endif - return (addr_list); - } - -@@ -251,6 +351,9 @@ - INET_ADDR_LIST *self; - DNS_RR *addr; - int i; -+#ifdef INET6 -+ struct sockaddr *sa; -+#endif - - /* - * Find the first address that lists any address that this mail system is -@@ -260,12 +363,36 @@ - - self = own_inet_addr_list(); - for (addr = addr_list; addr; addr = addr->next) { -- for (i = 0; i < self->used; i++) -+ for (i = 0; i < self->used; i++) { -+#ifdef INET6 -+ sa = (struct sockaddr *)&self->addrs[i]; -+ switch(addr->type) { -+ case T_AAAA: -+ /* XXX scope */ -+ if (sa->sa_family != AF_INET6) -+ break; -+ if (memcmp(&((struct sockaddr_in6 *)sa)->sin6_addr, -+ addr->data, sizeof(struct in6_addr)) == 0) { -+ return(addr); -+ } -+ break; -+ case T_A: -+ if (sa->sa_family != AF_INET) -+ break; -+ if (memcmp(&((struct sockaddr_in *)sa)->sin_addr, -+ addr->data, sizeof(struct in_addr)) == 0) { -+ return(addr); -+ } -+ break; -+ } -+#else - if (INADDRP(addr->data)->s_addr == self->addrs[i].s_addr) { - if (msg_verbose) - msg_info("%s: found at pref %d", myname, addr->pref); - return (addr); - } -+#endif -+ } - } - - /* -@@ -273,12 +400,36 @@ - */ - self = proxy_inet_addr_list(); - for (addr = addr_list; addr; addr = addr->next) { -- for (i = 0; i < self->used; i++) -+ for (i = 0; i < self->used; i++) { -+#ifdef INET6 -+ sa = (struct sockaddr *)&self->addrs[i]; -+ switch(addr->type) { -+ case T_AAAA: -+ /* XXX scope */ -+ if (sa->sa_family != AF_INET6) -+ break; -+ if (memcmp(&((struct sockaddr_in6 *)sa)->sin6_addr, -+ addr->data, sizeof(struct in6_addr)) == 0) { -+ return(addr); -+ } -+ break; -+ case T_A: -+ if (sa->sa_family != AF_INET) -+ break; -+ if (memcmp(&((struct sockaddr_in *)sa)->sin_addr, -+ addr->data, sizeof(struct in_addr)) == 0) { -+ return(addr); -+ } -+ break; -+ } -+#else - if (INADDRP(addr->data)->s_addr == self->addrs[i].s_addr) { - if (msg_verbose) - msg_info("%s: found at pref %d", myname, addr->pref); - return (addr); - } -+#endif -+ } - } - - /* -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/smtp/smtp_connect.c postfix-2.0.16/src/smtp/smtp_connect.c ---- postfix-2.0.16.orig/src/smtp/smtp_connect.c 2005-01-07 18:22:25.254447056 +0100 -+++ postfix-2.0.16/src/smtp/smtp_connect.c 2005-01-07 18:25:30.202330704 +0100 -@@ -81,6 +81,7 @@ - /* System library. */ - - #include -+#include - #include - #include - #include -@@ -110,6 +111,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -135,19 +137,45 @@ - VSTRING *why) - { - char *myname = "smtp_connect_addr"; -- struct sockaddr_in sin; -- int sock; -+#ifdef INET6 -+ struct sockaddr_storage ss; -+#else -+ struct sockaddr ss; -+#endif -+ struct sockaddr *sa; -+ struct sockaddr_in *sin; -+#ifdef INET6 -+ struct sockaddr_in6 *sin6; -+#endif -+ SOCKADDR_SIZE salen; -+#ifdef INET6 -+ char hbuf[NI_MAXHOST]; -+#else -+ char hbuf[sizeof("255.255.255.255") + 1]; -+#endif -+ int sock = -1; - INET_ADDR_LIST *addr_list; - int conn_stat; - int saved_errno; - VSTREAM *stream; - int ch; -- unsigned long inaddr; -+ -+ sa = (struct sockaddr *)&ss; -+ sin = (struct sockaddr_in *)&ss; -+#ifdef INET6 -+ sin6 = (struct sockaddr_in6 *)&ss; -+#endif - - /* - * Sanity checks. - */ -- if (addr->data_len > sizeof(sin.sin_addr)) { -+#ifdef INET6 -+ if (((addr->type==T_A) && (addr->data_len > sizeof(sin->sin_addr))) || -+ ((addr->type==T_AAAA) && (addr->data_len > sizeof(sin6->sin6_addr)))) -+#else -+ if (addr->data_len > sizeof(sin->sin_addr)) -+#endif -+ { - msg_warn("%s: skip address with length %d", myname, addr->data_len); - smtp_errno = SMTP_RETRY; - return (0); -@@ -156,17 +184,39 @@ - /* - * Initialize. - */ -- memset((char *) &sin, 0, sizeof(sin)); -- sin.sin_family = AF_INET; -- -- if ((sock = socket(sin.sin_family, SOCK_STREAM, 0)) < 0) -- msg_fatal("%s: socket: %m", myname); -- -+ switch (addr->type) { -+#ifdef INET6 -+ case T_AAAA: -+ memset(sin6, 0, sizeof(*sin6)); -+ sin6->sin6_family = AF_INET6; -+ salen = sizeof(*sin6); -+ break; -+#endif -+ default: /* T_A: */ -+ memset(sin, 0, sizeof(*sin)); -+ sin->sin_family = AF_INET; -+ salen = sizeof(*sin); -+ break; -+ } -+#ifdef HAS_SA_LEN -+ sa->sa_len = salen; -+#endif -+ if ((sock = socket(sa->sa_family, SOCK_STREAM, 0)) < 0) -+ msg_warn("%s: socket: %m", myname); -+ - /* - * Allow the sysadmin to specify the source address, for example, as "-o - * smtp_bind_address=x.x.x.x" in the master.cf file. - */ - if (*var_smtp_bind_addr) { -+#ifndef INET6 -+ struct sockaddr_in sin; -+ -+ memset(&sin, 0, sizeof(sin)); -+ sin.sin_family = AF_INET; -+#ifdef HAS_SA_LEN -+ sin.sin_len = sizeof(sin); -+#endif - sin.sin_addr.s_addr = inet_addr(var_smtp_bind_addr); - if (sin.sin_addr.s_addr == INADDR_NONE) - msg_fatal("%s: bad %s parameter: %s", -@@ -175,6 +225,25 @@ - msg_warn("%s: bind %s: %m", myname, inet_ntoa(sin.sin_addr)); - if (msg_verbose) - msg_info("%s: bind %s", myname, inet_ntoa(sin.sin_addr)); -+#else -+ char hbufl[NI_MAXHOST]; -+ struct addrinfo hints, *res; -+ -+ memset(&hints, 0, sizeof(hints)); -+ hints.ai_family = sa->sa_family; -+ hints.ai_socktype = SOCK_STREAM; -+ hints.ai_flags = AI_PASSIVE|AI_NUMERICHOST; -+ snprintf(hbufl, sizeof(hbufl)-1, "%s", var_smtp_bind_addr); -+ if (getaddrinfo(hbufl, NULL, &hints, &res) == 0) { -+ (void)getnameinfo(res->ai_addr, res->ai_addrlen, hbufl, -+ sizeof(hbufl), NULL, 0, NI_NUMERICHOST); -+ if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) -+ msg_warn("%s: bind %s: %m", myname, hbufl); -+ freeaddrinfo(res); -+ if (msg_verbose) -+ msg_info("%s: bind %s", myname, hbufl); -+ } -+#endif - } - - /* -@@ -182,8 +251,17 @@ - * the mail appears to come from the "right" machine address. - */ - else if ((addr_list = own_inet_addr_list())->used == 1) { -+#ifndef INET6 -+ struct sockaddr_in sin; -+ unsigned long inaddr; /*XXX BAD!*/ -+ -+ memset(&sin, 0, sizeof(sin)); -+ sin.sin_family = AF_INET; -+#ifdef HAS_SA_LEN -+ sin.sin_len = sizeof(sin); -+#endif - memcpy((char *) &sin.sin_addr, addr_list->addrs, sizeof(sin.sin_addr)); -- inaddr = ntohl(sin.sin_addr.s_addr); -+ inaddr = (unsigned long)ntohl(sin.sin_addr.s_addr); - if (!IN_CLASSA(inaddr) - || !(((inaddr & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)) { - if (bind(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0) -@@ -191,30 +269,85 @@ - if (msg_verbose) - msg_info("%s: bind %s", myname, inet_ntoa(sin.sin_addr)); - } -+#else -+ char hbufl[NI_MAXHOST]; -+ struct addrinfo hints, *res = NULL, *loopback = NULL; -+ -+ memset(&hints, 0, sizeof(hints)); -+ hints.ai_family = sa->sa_family; -+ hints.ai_socktype = SOCK_STREAM; -+ if (getaddrinfo(NULL, "0", &hints, &loopback) != 0) -+ loopback = NULL; -+ -+ /* -+ * getnameinfo -> getaddrinfo loop is here so that we can -+ * get rid of port. -+ */ -+ (void)getnameinfo((struct sockaddr *)addr_list->addrs, SA_LEN((struct sockaddr *)addr_list->addrs), -+ hbufl, sizeof(hbufl), NULL, 0, NI_NUMERICHOST); -+ hbufl[sizeof(hbufl)-1] = 0; -+ memset(&hints, 0, sizeof(hints)); -+ hints.ai_family = sa->sa_family; -+ hints.ai_socktype = SOCK_STREAM; -+ hints.ai_flags = AI_PASSIVE|AI_NUMERICHOST; -+ if (getaddrinfo(hbufl, NULL, &hints, &res) == 0 && -+ !(res->ai_addrlen == loopback->ai_addrlen && -+ memcmp(res->ai_addr, loopback->ai_addr, res->ai_addrlen) == 0)) { -+ if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) -+ msg_warn("%s: bind %s: %m", myname, hbufl); -+ if (msg_verbose) -+ msg_info("%s: bind %s", myname, hbufl); -+ } -+ if (res) -+ freeaddrinfo(res); -+ if (loopback) -+ freeaddrinfo(loopback); -+#endif - } - - /* - * Connect to the SMTP server. - */ -- sin.sin_port = port; -- memcpy((char *) &sin.sin_addr, addr->data, sizeof(sin.sin_addr)); -+ switch (addr->type) { -+#ifdef INET6 -+ case T_AAAA: -+ /* XXX scope unfriendly */ -+ memset(sin6, 0, sizeof(*sin6)); -+ sin6->sin6_port = port; -+ sin6->sin6_family = AF_INET6; -+ salen = sizeof(*sin6); -+ memcpy(&sin6->sin6_addr, addr->data, sizeof(sin6->sin6_addr)); -+ inet_ntop(AF_INET6, &sin6->sin6_addr, hbuf, sizeof(hbuf)); -+ break; -+#endif -+ default: /* T_A */ -+ memset(sin, 0, sizeof(*sin)); -+ sin->sin_port = port; -+ sin->sin_family = AF_INET; -+ salen = sizeof(*sin); -+ memcpy(&sin->sin_addr, addr->data, sizeof(sin->sin_addr)); -+ inet_ntop(AF_INET, &sin->sin_addr, hbuf, sizeof(hbuf)); -+ break; -+ } -+#ifdef HAS_SA_LEN -+ sa->sa_len = salen; -+#endif - - if (msg_verbose) - msg_info("%s: trying: %s[%s] port %d...", -- myname, addr->name, inet_ntoa(sin.sin_addr), ntohs(port)); -+ myname, addr->name, hbuf, ntohs(port)); - if (var_smtp_conn_tmout > 0) { - non_blocking(sock, NON_BLOCKING); -- conn_stat = timed_connect(sock, (struct sockaddr *) & sin, -- sizeof(sin), var_smtp_conn_tmout); -+ conn_stat = timed_connect(sock, sa, salen, var_smtp_conn_tmout); - saved_errno = errno; - non_blocking(sock, BLOCKING); - errno = saved_errno; - } else { -- conn_stat = sane_connect(sock, (struct sockaddr *) & sin, sizeof(sin)); -+ conn_stat = connect(sock, sa, salen); - } - if (conn_stat < 0) { - vstring_sprintf(why, "connect to %s[%s]: %m", -- addr->name, inet_ntoa(sin.sin_addr)); -+ addr->name, hbuf); - smtp_errno = SMTP_RETRY; - close(sock); - return (0); -@@ -224,8 +357,8 @@ - * Skip this host if it takes no action within some time limit. - */ - if (read_wait(sock, var_smtp_helo_tmout) < 0) { -- vstring_sprintf(why, "connect to %s[%s]: read timeout", -- addr->name, inet_ntoa(sin.sin_addr)); -+ vstring_sprintf(why, "connect to %s [%s]: read timeout", -+ addr->name, hbuf); - smtp_errno = SMTP_RETRY; - close(sock); - return (0); -@@ -237,7 +370,7 @@ - stream = vstream_fdopen(sock, O_RDWR); - if ((ch = VSTREAM_GETC(stream)) == VSTREAM_EOF) { - vstring_sprintf(why, "connect to %s[%s]: server dropped connection without sending the initial greeting", -- addr->name, inet_ntoa(sin.sin_addr)); -+ addr->name, hbuf); - smtp_errno = SMTP_RETRY; - vstream_fclose(stream); - return (0); -@@ -249,7 +382,7 @@ - */ - if (ch == '4' && var_smtp_skip_4xx_greeting) { - vstring_sprintf(why, "connect to %s[%s]: server refused mail service", -- addr->name, inet_ntoa(sin.sin_addr)); -+ addr->name, hbuf); - smtp_errno = SMTP_RETRY; - vstream_fclose(stream); - return (0); -@@ -260,12 +393,12 @@ - */ - if (ch == '5' && var_smtp_skip_5xx_greeting) { - vstring_sprintf(why, "connect to %s[%s]: server refused mail service", -- addr->name, inet_ntoa(sin.sin_addr)); -+ addr->name, hbuf); - smtp_errno = SMTP_RETRY; - vstream_fclose(stream); - return (0); - } -- return (smtp_session_alloc(dest, stream, addr->name, inet_ntoa(sin.sin_addr))); -+ return (smtp_session_alloc(dest, stream, addr->name, hbuf)); - } - - /* smtp_connect_host - direct connection to host */ -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/smtp/smtp_unalias.c postfix-2.0.16/src/smtp/smtp_unalias.c ---- postfix-2.0.16.orig/src/smtp/smtp_unalias.c 2000-09-28 19:06:09.000000000 +0200 -+++ postfix-2.0.16/src/smtp/smtp_unalias.c 2005-01-07 18:25:30.202330704 +0100 -@@ -86,7 +86,11 @@ - if ((result = htable_find(cache, name)) == 0) { - fqdn = vstring_alloc(10); - if (dns_lookup_types(name, smtp_unalias_flags, (DNS_RR **) 0, -- fqdn, (VSTRING *) 0, T_MX, T_A, 0) != DNS_OK) -+ fqdn, (VSTRING *) 0, T_MX, T_A, -+#ifdef INET6 -+ T_AAAA, -+#endif -+ 0) != DNS_OK) - vstring_strcpy(fqdn, name); - htable_enter(cache, name, result = vstring_export(fqdn)); - } -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/smtpd/smtpd_check.c postfix-2.0.16/src/smtpd/smtpd_check.c ---- postfix-2.0.16.orig/src/smtpd/smtpd_check.c 2005-01-07 18:22:25.302439760 +0100 -+++ postfix-2.0.16/src/smtpd/smtpd_check.c 2005-01-07 18:25:30.218328272 +0100 -@@ -1393,6 +1393,49 @@ - static int has_my_addr(SMTPD_STATE *state, const char *host, - const char *reply_name, const char *reply_class) - { -+#ifdef INET6 -+ char *myname = "has_my_addr"; -+ struct addrinfo hints, *res, *res0; -+ int error; -+ char hbuf[NI_MAXHOST]; -+ -+ if (msg_verbose) -+ msg_info("%s: host %s", myname, host); -+ -+ /* -+ * If we can't lookup the host, play safe and assume it is OK. -+ */ -+#define YUP 1 -+#define NOPE 0 -+ -+ memset(&hints, 0, sizeof(hints)); -+ hints.ai_family = PF_UNSPEC; -+ hints.ai_socktype = SOCK_DGRAM; -+ error = getaddrinfo(host, NULL, &hints, &res0); -+ if (error) { -+ if (msg_verbose) -+ msg_info("%s: host %s: %s", myname, host, gai_strerror(error)); -+ return (YUP); -+ } -+ for (res = res0; res; res = res->ai_next) { -+ if (msg_verbose) { -+ if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf), -+ NULL, 0, NI_NUMERICHOST)) { -+ strncpy(hbuf, "???", sizeof(hbuf)); -+ } -+ msg_info("%s: addr %s", myname, hbuf); -+ } -+ if (own_inet_addr(res->ai_addr)) { -+ freeaddrinfo(res0); -+ return (YUP); -+ } -+ } -+ freeaddrinfo(res0); -+ if (msg_verbose) -+ msg_info("%s: host %s: no match", myname, host); -+ -+ return (NOPE); -+#else - char *myname = "has_my_addr"; - struct in_addr addr; - char **cpp; -@@ -1431,6 +1474,7 @@ - msg_info("%s: host %s: no match", myname, host); - - return (NOPE); -+#endif - } - - /* i_am_mx - is this machine listed as MX relay */ -@@ -2015,11 +2059,28 @@ - #define CHK_ADDR_RETURN(x,y) { *found = y; return(x); } - - addr = STR(vstring_strcpy(error_text, address)); -- -+#ifdef INET6 -+ if (strncmp(addr, "::ffff:", 7) == 0 && msg_verbose) -+ msg_info("%s: %s v6 addr in v4 compat-mode, " -+ "converted to v4 for map checking compatibility (%s)", \ -+ myname, addr, addr+7); -+#endif -+ - if ((dict = dict_handle(table)) == 0) - msg_panic("%s: dictionary not found: %s", myname, table); - do { - if (flags == 0 || (flags & dict->flags) != 0) { -+#ifdef INET6 -+ if (strncmp(addr, "::ffff:", 7) == 0) { -+ /* try if ::ffff: formati is present in map, if not, try -+ traditional IPv4 format striping :ffff: part */ -+ if ((value = dict_get(dict, addr)) != 0 || \ -+ (value = dict_get(dict, addr+7)) != 0) -+ CHK_ADDR_RETURN(check_table_result(state, table, value, address, -+ reply_name, reply_class, -+ def_acl), FOUND); -+ } else -+#endif - if ((value = dict_get(dict, addr)) != 0) - CHK_ADDR_RETURN(check_table_result(state, table, value, address, - reply_name, reply_class, -@@ -2579,16 +2640,32 @@ - VSTRING *query; - int i; - SMTPD_RBL_STATE *rbl; -+#ifdef INET6 -+ struct in_addr a; -+#else -+ struct in6_addr a; -+#endif - - if (msg_verbose) - msg_info("%s: %s %s", myname, reply_class, addr); - -- /* -- * IPv4 only for now -- */ --#ifdef INET6 -+#ifndef INET6 -+ /* IPv4 only for now */ - if (inet_pton(AF_INET, addr, &a) != 1) - return SMTPD_CHECK_DUNNO; -+ octets = argv_split(state->addr, "."); -+#else -+ /* IPv4 and IPv6-mapped IPv4 only for now */ -+ if (inet_pton(AF_INET, state->addr, &a) == 1) -+ octets = argv_split(state->addr, "."); -+ else { -+ struct in6_addr a6; -+ if (inet_pton(AF_INET6, state->addr, &a6) != 1) -+ return SMTPD_CHECK_DUNNO; -+ if (!IN6_IS_ADDR_V4MAPPED(&a6) || (strrchr(state->addr,':') == NULL)) -+ return SMTPD_CHECK_DUNNO; -+ octets = argv_split(strrchr(state->addr,':')+1, "."); -+ } - #endif - - /* -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/smtpd/smtpd_peer.c postfix-2.0.16/src/smtpd/smtpd_peer.c ---- postfix-2.0.16.orig/src/smtpd/smtpd_peer.c 2002-08-22 19:50:51.000000000 +0200 -+++ postfix-2.0.16/src/smtpd/smtpd_peer.c 2005-01-07 18:25:30.205330248 +0100 -@@ -63,6 +63,15 @@ - #include - #include - -+/* Utility library. */ -+ -+#include -+#include -+#include -+#include -+ -+/* Global library. */ -+ - /* - * Older systems don't have h_errno. Even modern systems don't have - * hstrerror(). -@@ -84,16 +93,11 @@ - ) - #endif - --/* Utility library. */ -- --#include --#include --#include --#include -- --/* Global library. */ -- -- -+#ifdef INET6 -+#define GAI_STRERROR(error) \ -+ ((error = EAI_SYSTEM) ? gai_strerror(error) : strerror(errno)) -+#endif -+ - /* Application-specific. */ - - #include "smtpd.h" -@@ -102,21 +106,28 @@ - - void smtpd_peer_init(SMTPD_STATE *state) - { -- struct sockaddr_in sin; -- SOCKADDR_SIZE len = sizeof(sin); -+#ifdef INET6 -+ struct sockaddr_storage ss; -+#else -+ struct sockaddr ss; -+ struct in_addr *in; - struct hostent *hp; -- int i; -+#endif -+ struct sockaddr *sa; -+ SOCKADDR_SIZE len; -+ -+ sa = (struct sockaddr *)&ss; -+ len = sizeof(ss); - - /* - * Avoid suprious complaints from Purify on Solaris. - */ -- memset((char *) &sin, 0, len); -+ memset((char *) sa, 0, len); - - /* - * Look up the peer address information. - */ -- if (getpeername(vstream_fileno(state->client), -- (struct sockaddr *) & sin, &len) >= 0) { -+ if (getpeername(vstream_fileno(state->client), sa, &len) >= 0) { - errno = 0; - } - -@@ -132,23 +143,56 @@ - /* - * Look up and "verify" the client hostname. - */ -- else if (errno == 0 && sin.sin_family == AF_INET) { -- state->addr = mystrdup(inet_ntoa(sin.sin_addr)); -- hp = gethostbyaddr((char *) &(sin.sin_addr), -- sizeof(sin.sin_addr), AF_INET); -- if (hp == 0) { -+ else if (errno == 0 && (sa->sa_family == AF_INET -+#ifdef INET6 -+ || sa->sa_family == AF_INET6 -+#endif -+ )) { -+#ifdef INET6 -+ char hbuf[NI_MAXHOST]; -+ char abuf[NI_MAXHOST]; -+ struct addrinfo hints, *rnull = NULL; -+#else -+ char abuf[sizeof("255.255.255.255") + 1]; -+ char *hbuf; -+#endif -+ int error = -1; -+ -+#ifdef INET6 -+ (void)getnameinfo(sa, len, abuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST); -+#else -+ in = &((struct sockaddr_in *)sa)->sin_addr; -+ inet_ntop(AF_INET, in, abuf, sizeof(hbuf)); -+#endif -+ state->addr = mystrdup(abuf); -+#ifdef INET6 -+ error = getnameinfo(sa, len, hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD); -+#else -+ hbuf = NULL; -+ hp = gethostbyaddr((char *)in, sizeof(*in), AF_INET); -+ if (hp) { -+ error = 0; -+ hbuf = mystrdup(hp->h_name); -+ } else -+ error = 1; -+#endif -+ if (error) { - state->name = mystrdup("unknown"); -+#ifdef INET6 -+ state->peer_code = (error == EAI_AGAIN ? 4 : 5); -+#else - state->peer_code = (h_errno == TRY_AGAIN ? 4 : 5); -- } else if (valid_hostaddr(hp->h_name, DONT_GRIPE)) { -+#endif -+ } else if (valid_hostaddr(hbuf, DONT_GRIPE)) { - msg_warn("numeric result %s in address->name lookup for %s", -- hp->h_name, state->addr); -+ hbuf, state->addr); - state->name = mystrdup("unknown"); - state->peer_code = 5; -- } else if (!valid_hostname(hp->h_name, DONT_GRIPE)) { -+ } else if (!valid_hostname(hbuf, DONT_GRIPE)) { - state->name = mystrdup("unknown"); - state->peer_code = 5; - } else { -- state->name = mystrdup(hp->h_name); /* hp->name is clobbered!! */ -+ state->name = mystrdup(hbuf); /* hp->name is clobbered!! */ - state->peer_code = 2; - - /* -@@ -160,16 +204,31 @@ - state->peer_code = code; \ - } - -+#ifdef INET6 -+ memset(&hints, 0, sizeof(hints)); -+ hints.ai_family = AF_UNSPEC; -+ hints.ai_socktype = SOCK_STREAM; -+ error = getaddrinfo(state->name, NULL, &hints, &rnull); -+ if (error) { -+ msg_warn("%s: hostname %s verification failed: %s", -+ state->addr, state->name, GAI_STRERROR(error)); -+ REJECT_PEER_NAME(state, (error == EAI_AGAIN ? 4 : 5)); -+ } -+ /* memcmp() isn't needed if we use getaddrinfo */ -+ if (rnull) -+ freeaddrinfo(rnull); -+#else - hp = gethostbyname(state->name); /* clobbers hp->name!! */ - if (hp == 0) { - msg_warn("%s: hostname %s verification failed: %s", - state->addr, state->name, HSTRERROR(h_errno)); - REJECT_PEER_NAME(state, (h_errno == TRY_AGAIN ? 4 : 5)); -- } else if (hp->h_length != sizeof(sin.sin_addr)) { -+ } else if (hp->h_length != sizeof(*in)) { - msg_warn("%s: hostname %s verification failed: bad address size %d", - state->addr, state->name, hp->h_length); - REJECT_PEER_NAME(state, 5); - } else { -+ int i; - for (i = 0; /* void */ ; i++) { - if (hp->h_addr_list[i] == 0) { - msg_warn("%s: address not listed for hostname %s", -@@ -177,12 +236,11 @@ - REJECT_PEER_NAME(state, 5); - break; - } -- if (memcmp(hp->h_addr_list[i], -- (char *) &sin.sin_addr, -- sizeof(sin.sin_addr)) == 0) -+ if (memcmp(hp->h_addr_list[i], (char *)in, sizeof(*in)) == 0) - break; /* keep peer name */ - } - } -+#endif - } - } - -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/smtpstone/smtp-sink.c postfix-2.0.16/src/smtpstone/smtp-sink.c ---- postfix-2.0.16.orig/src/smtpstone/smtp-sink.c 2003-09-13 02:46:56.000000000 +0200 -+++ postfix-2.0.16/src/smtpstone/smtp-sink.c 2005-01-07 18:25:30.205330248 +0100 -@@ -607,7 +607,7 @@ - } else { - if (strncmp(argv[optind], "inet:", 5) == 0) - argv[optind] += 5; -- sock = inet_listen(argv[optind], backlog, BLOCKING); -+ sock = inet_listen(argv[optind], backlog, BLOCKING, 1); - } - - /* -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/util/Makefile.in postfix-2.0.16/src/util/Makefile.in ---- postfix-2.0.16.orig/src/util/Makefile.in 2005-01-07 18:22:25.293441128 +0100 -+++ postfix-2.0.16/src/util/Makefile.in 2005-01-07 18:25:30.209329640 +0100 -@@ -8,7 +8,7 @@ - dict_tcp.c dict_unix.c dir_forest.c doze.c duplex_pipe.c \ - environ.c events.c exec_command.c fifo_listen.c fifo_trigger.c \ - file_limit.c find_inet.c fsspace.c fullname.c get_domainname.c \ -- get_hostname.c hex_quote.c htable.c inet_addr_host.c \ -+ get_hostname.c get_port.c hex_quote.c htable.c inet_addr_host.c \ - inet_addr_list.c inet_addr_local.c inet_connect.c inet_listen.c \ - inet_trigger.c inet_util.c intv.c line_wrap.c lowercase.c \ - lstat_as.c mac_expand.c mac_parse.c make_dirs.c match_list.c \ -@@ -37,7 +37,7 @@ - dict_tcp.o dict_unix.o dir_forest.o doze.o duplex_pipe.o \ - environ.o events.o exec_command.o fifo_listen.o fifo_trigger.o \ - file_limit.o find_inet.o fsspace.o fullname.o get_domainname.o \ -- get_hostname.o hex_quote.o htable.o inet_addr_host.o \ -+ get_hostname.o get_port.o hex_quote.o htable.o inet_addr_host.o \ - inet_addr_list.o inet_addr_local.o inet_connect.o inet_listen.o \ - inet_trigger.o inet_util.o intv.o line_wrap.o lowercase.o \ - lstat_as.o mac_expand.o mac_parse.o make_dirs.o match_list.o \ -@@ -62,7 +62,7 @@ - dict_ht.h dict_ldap.h dict_mysql.h dict_ni.h dict_nis.h \ - dict_nisplus.h dict_pcre.h dict_pgsql.h dict_regexp.h dict_static.h dict_tcp.h \ - dict_unix.h dir_forest.h events.h exec_command.h find_inet.h \ -- fsspace.h fullname.h get_domainname.h get_hostname.h hex_quote.h \ -+ fsspace.h fullname.h get_domainname.h get_hostname.h get_port.h hex_quote.h \ - htable.h inet_addr_host.h inet_addr_list.h inet_addr_local.h \ - inet_util.h intv.h iostuff.h line_wrap.h listen.h lstat_as.h \ - mac_expand.h mac_parse.h make_dirs.h match_list.h match_ops.h \ -@@ -785,6 +785,7 @@ - get_domainname.o: mymalloc.h - get_domainname.o: get_hostname.h - get_domainname.o: get_domainname.h -+get_port.o: sys_defs.h - get_hostname.o: get_hostname.c - get_hostname.o: sys_defs.h - get_hostname.o: mymalloc.h -@@ -911,6 +912,7 @@ - match_list.o: stringops.h - match_list.o: argv.h - match_list.o: dict.h -+match_list.o: inet_util.h - match_list.o: match_ops.h - match_list.o: match_list.h - match_ops.o: match_ops.c -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/util/get_port.c postfix-2.0.16/src/util/get_port.c ---- postfix-2.0.16.orig/src/util/get_port.c 1970-01-01 01:00:00.000000000 +0100 -+++ postfix-2.0.16/src/util/get_port.c 2005-01-07 18:25:30.206330096 +0100 -@@ -0,0 +1,65 @@ -+/*++ -+/* NAME -+/* get_port 3 -+/* SUMMARY -+/* trivial host and port extracter -+/* SYNOPSIS -+/* #include -+/* -+/* char *get_port(data) -+/* char *data; -+/* -+/* DESCRIPTION -+/* get_port() extract host name or ip address from -+/* strings such as [3ffe:902:12::10]:25, [::1] -+/* or 192.168.0.1:25, and null-terminates the -+/* \fIdata\fR at the first occurrence of port separator. -+/* DIAGNOSTICS -+/* If port not found return null pointer. -+/* LICENSE -+/* .ad -+/* .fi -+/* BSD Style (or BSD like) license. -+/* AUTHOR(S) -+/* Arkadiusz Mi¶kiewicz -+/* Wroclaw, POLAND -+/*--*/ -+ -+/* System libraries */ -+ -+#include -+#include -+ -+/* Utility library. */ -+ -+#include "get_port.h" -+ -+/* get_port - extract port number from string */ -+ -+char *get_port(char *data) -+{ -+ const char *escl=strchr(data,'['); -+ const char *sepl=strchr(data,':'); -+ char *escr=strrchr(data,']'); -+ char *sepr=strrchr(data,':'); -+ -+ /* extract from "[address]:port" or "[address]"*/ -+ if (escl && escr) -+ { -+ memmove(data, data + 1, strlen(data) - strlen(escr)); -+ data[strlen(data) - strlen(escr) - 1] = 0; -+ *escr++ = 0; -+ if (*escr == ':') -+ escr++; -+ return (*escr ? escr : NULL); -+ } -+ /* extract from "address:port" or "address" */ -+ if ((sepl == sepr) && sepr && sepl) -+ { -+ *sepr++ = 0; -+ return sepr; -+ } -+ -+ /* return empty string */ -+ return NULL; -+} -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/util/get_port.h postfix-2.0.16/src/util/get_port.h ---- postfix-2.0.16.orig/src/util/get_port.h 1970-01-01 01:00:00.000000000 +0100 -+++ postfix-2.0.16/src/util/get_port.h 2005-01-07 18:25:30.206330096 +0100 -@@ -0,0 +1,28 @@ -+#ifndef _GET_PORT_H_INCLUDED_ -+#define _GET_PORT_H_INCLUDED_ -+ -+/*++ -+/* NAME -+/* get_port 3h -+/* SUMMARY -+/* trivial host and port extracter -+/* SYNOPSIS -+/* #include -+/* DESCRIPTION -+/* .nf -+ -+ /* External interface. */ -+ -+extern char *get_port(char *); -+ -+ -+/* LICENSE -+/* .ad -+/* .fi -+/* BSD Style (or BSD like) license. -+/* AUTHOR(S) -+/* Arkadiusz Mi¶kiewicz -+/* Wroclaw, POLAND -+/*--*/ -+ -+#endif -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/util/inet_addr_host.c postfix-2.0.16/src/util/inet_addr_host.c ---- postfix-2.0.16.orig/src/util/inet_addr_host.c 1998-12-11 19:55:35.000000000 +0100 -+++ postfix-2.0.16/src/util/inet_addr_host.c 2005-01-07 18:28:55.469125408 +0100 -@@ -38,7 +38,11 @@ - #include - #include - #include -+#include - #include -+#include -+#include -+#include - - #ifndef INADDR_NONE - #define INADDR_NONE 0xffffffff -@@ -48,15 +52,47 @@ - - #include - #include -+#ifdef TEST -+#include -+#endif - - /* inet_addr_host - look up address list for host */ - - int inet_addr_host(INET_ADDR_LIST *addr_list, const char *hostname) - { -+#ifdef INET6 -+ int s; -+ struct addrinfo hints, *res0, *res; -+#ifdef TEST -+ char buforhosta[1024]; -+#endif -+ int error; -+#else - struct hostent *hp; - struct in_addr addr; -+#endif - int initial_count = addr_list->used; - -+#ifdef INET6 -+ memset(&hints, 0, sizeof(hints)); -+ hints.ai_family = PF_UNSPEC; -+ hints.ai_socktype = SOCK_DGRAM; -+ error = getaddrinfo(hostname, NULL, &hints, &res0); -+ if (error == 0) { -+ for (res = res0; res; res = res->ai_next) { -+ if(res->ai_family != AF_INET && res->ai_family != AF_INET6) -+ continue; -+ /* filter out address families that are not supported */ -+ s = socket(res->ai_family, SOCK_DGRAM, 0); -+ if (s < 0) -+ continue; -+ close(s); -+ -+ inet_addr_list_append(addr_list, res->ai_addr); -+ } -+ freeaddrinfo(res0); -+ } -+#else - if ((addr.s_addr = inet_addr(hostname)) != INADDR_NONE) { - inet_addr_list_append(addr_list, &addr); - } else { -@@ -65,9 +101,12 @@ - inet_addr_list_append(addr_list, - (struct in_addr *) * hp->h_addr_list++); - } -+#endif -+ - return (addr_list->used - initial_count); - } - -+ - #ifdef TEST - - #include -@@ -78,6 +117,8 @@ - { - INET_ADDR_LIST addr_list; - int i; -+ struct sockaddr *sa; -+ char hbuf[NI_MAXHOST]; - - msg_vstream_init(argv[0], VSTREAM_ERR); - -@@ -89,8 +130,12 @@ - if (inet_addr_host(&addr_list, *argv) == 0) - msg_fatal("not found: %s", *argv); - -- for (i = 0; i < addr_list.used; i++) -- vstream_printf("%s\n", inet_ntoa(addr_list.addrs[i])); -+ for (i = 0; i < addr_list.used; i++) { -+ sa = (struct sockaddr *)&addr_list.addrs[i]; -+ getnameinfo(sa, SA_LEN(sa), hbuf, sizeof(hbuf), NULL, 0, -+ NI_NUMERICHOST); -+ vstream_printf("%s\n", hbuf); -+ } - vstream_fflush(VSTREAM_OUT); - } - inet_addr_list_free(&addr_list); -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/util/inet_addr_list.c postfix-2.0.16/src/util/inet_addr_list.c ---- postfix-2.0.16.orig/src/util/inet_addr_list.c 2001-07-31 20:13:41.000000000 +0200 -+++ postfix-2.0.16/src/util/inet_addr_list.c 2005-01-07 18:25:30.207329944 +0100 -@@ -51,6 +51,13 @@ - #include - #include - -+#include -+ -+#ifdef INET6 -+#include -+#include -+#endif -+ - /* Utility library. */ - - #include -@@ -63,12 +70,39 @@ - { - list->used = 0; - list->size = 2; -+#ifdef INET6 -+ list->addrs = (struct sockaddr_storage *) -+#else - list->addrs = (struct in_addr *) -+#endif - mymalloc(sizeof(*list->addrs) * list->size); - } - - /* inet_addr_list_append - append address to internet address list */ - -+#ifdef INET6 -+void inet_addr_list_append(INET_ADDR_LIST *list, -+ struct sockaddr * addr) -+{ -+ char *myname = "inet_addr_list_append"; -+ char hbuf[NI_MAXHOST]; -+ -+ if (msg_verbose > 1) { -+ if (getnameinfo(addr, SA_LEN(addr), hbuf, sizeof(hbuf), NULL, 0, -+ NI_NUMERICHOST)) { -+ strncpy(hbuf, "??????", sizeof(hbuf)); -+ } -+ msg_info("%s: %s", myname, hbuf); -+ } -+ -+ if (list->used >= list->size) -+ list->size *= 2; -+ list->addrs = (struct sockaddr_storage *) -+ myrealloc((char *) list->addrs, -+ sizeof(*list->addrs) * list->size); -+ memcpy(&list->addrs[list->used++], addr, SA_LEN(addr)); -+} -+#else - void inet_addr_list_append(INET_ADDR_LIST *list, struct in_addr * addr) - { - char *myname = "inet_addr_list_append"; -@@ -83,15 +117,22 @@ - sizeof(*list->addrs) * list->size); - list->addrs[list->used++] = *addr; - } -+#endif - - /* inet_addr_list_comp - compare addresses */ - - static int inet_addr_list_comp(const void *a, const void *b) - { -+#ifdef INET6 -+ if(((struct sockaddr*)a)->sa_family != ((struct sockaddr*)b)->sa_family) -+ return ( ((struct sockaddr*)a)->sa_family - ((struct sockaddr*)b)->sa_family ); -+ return memcmp(a,b,SA_LEN((struct sockaddr*)a)); -+#else - const struct in_addr *a_addr = (const struct in_addr *) a; - const struct in_addr *b_addr = (const struct in_addr *) b; - - return (a_addr->s_addr - b_addr->s_addr); -+#endif - } - - /* inet_addr_list_uniq - weed out duplicates */ -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/util/inet_addr_list.h postfix-2.0.16/src/util/inet_addr_list.h ---- postfix-2.0.16.orig/src/util/inet_addr_list.h 2001-07-31 19:56:47.000000000 +0200 -+++ postfix-2.0.16/src/util/inet_addr_list.h 2005-01-07 18:25:30.207329944 +0100 -@@ -16,19 +16,38 @@ - */ - #include - -+#ifndef SA_LEN -+#ifndef HAS_SA_LEN -+#define SA_LEN(x) (((x)->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) -+#define SS_LEN(x) (((x).ss_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) -+#else -+#define SA_LEN(x) ((x)->sa_len) -+#define SS_LEN(x) ((x).ss_len) -+#endif -+#endif -+ - /* - * External interface. - */ - typedef struct INET_ADDR_LIST { - int used; /* nr of elements in use */ - int size; /* actual list size */ -+#ifdef INET6 -+ struct sockaddr_storage *addrs; /* payload */ -+#else - struct in_addr *addrs; /* payload */ -+#endif - } INET_ADDR_LIST; - - extern void inet_addr_list_init(INET_ADDR_LIST *); - extern void inet_addr_list_free(INET_ADDR_LIST *); - extern void inet_addr_list_uniq(INET_ADDR_LIST *); -+#ifdef INET6 -+struct sockaddr; -+extern void inet_addr_list_append(INET_ADDR_LIST *, struct sockaddr *); -+#else - extern void inet_addr_list_append(INET_ADDR_LIST *, struct in_addr *); -+#endif - - /* LICENSE - /* .ad -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/util/inet_addr_local.c postfix-2.0.16/src/util/inet_addr_local.c ---- postfix-2.0.16.orig/src/util/inet_addr_local.c 2001-02-25 19:20:19.000000000 +0100 -+++ postfix-2.0.16/src/util/inet_addr_local.c 2005-01-07 18:25:30.207329944 +0100 -@@ -47,6 +47,13 @@ - #endif - #include - #include -+#if defined(INET6) && (defined (LINUX) || defined (LINUX2)) -+#include -+#include -+#endif -+#ifdef HAVE_GETIFADDRS -+#include -+#endif - - /* Utility library. */ - -@@ -78,18 +85,104 @@ - - int inet_addr_local(INET_ADDR_LIST *addr_list, INET_ADDR_LIST *mask_list) - { -+#ifdef HAVE_GETIFADDRS -+ char *myname = "inet_addr_local"; -+ struct ifaddrs *ifap, *ifa; -+ int initial_count = addr_list->used; -+ struct sockaddr *sa, *sam; -+#ifdef INET6 -+#ifdef __KAME__ -+ struct sockaddr_in6 addr6; -+#endif -+#else -+ void *addr,*addrm; -+#endif -+ -+ if (getifaddrs(&ifap) < 0) -+ msg_fatal("%s: getifaddrs: %m", myname); -+ -+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) { -+ if ((!(ifa->ifa_flags & IFF_RUNNING)) || (ifa->ifa_addr == NULL) || (ifa->ifa_netmask == NULL)) -+ continue; -+ sa = ifa->ifa_addr; -+ sam = ifa->ifa_netmask; -+ switch (ifa->ifa_addr->sa_family) { -+ case AF_INET: -+#ifndef INET6 -+ addr = (void *)&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr; -+ addrm = (void *)&((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr; -+#endif -+ break; -+#ifdef INET6 -+ case AF_INET6: -+#ifdef __KAME__ -+ memcpy(&addr6, ifa->ifa_addr, ifa->ifa_addr->sa_len); -+ /* decode scoped address notation */ -+ if ((IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr) || -+ IN6_IS_ADDR_SITELOCAL(&addr6.sin6_addr)) && -+ addr6.sin6_scope_id == 0) { -+ addr6.sin6_scope_id = ntohs(addr6.sin6_addr.s6_addr[3] | -+ (unsigned int)addr6.sin6_addr.s6_addr[2] << 8); -+ addr6.sin6_addr.s6_addr[2] = addr6.sin6_addr.s6_addr[3] = 0; -+ sa = (struct sockaddr *)&addr6; -+ } -+#endif -+ break; -+#endif -+ default: -+ continue; -+ } -+ -+#ifdef INET6 -+ inet_addr_list_append(addr_list, sa); -+ if (mask_list != NULL) -+ inet_addr_list_append(mask_list, sam); -+#else -+ inet_addr_list_append(addr_list, (struct in_addr *)addr); -+ if (mask_list != NULL) -+ inet_addr_list_append(mask_list, (struct in_addr *)addrm); -+#endif -+ } -+ -+ freeifaddrs(ifap); -+ return (addr_list->used - initial_count); -+#else - char *myname = "inet_addr_local"; - struct ifconf ifc; - struct ifreq *ifr; - struct ifreq *the_end; - int sock; -- VSTRING *buf = vstring_alloc(1024); -+ VSTRING *buf; - int initial_count = addr_list->used; - struct in_addr addr; - struct ifreq *ifr_mask; -+ int af = AF_INET; -+#ifdef INET6 -+#if defined (LINUX) || defined (LINUX2) -+#define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6" -+ FILE *f; -+ char addr6p[8][5], addr6res[40], devname[20]; -+ int plen, scope, dad_status, if_idx, gaierror; -+ struct addrinfo hints, *res, *res0; -+#endif -+ struct sockaddr_in6 addr6; - -- if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) -+other_socket_type: -+#endif -+ buf = vstring_alloc(1024); -+ -+ if ((sock = socket(af, SOCK_DGRAM, 0)) < 0) { -+#ifdef INET6 -+ if (af == AF_INET6) -+ { -+ if (msg_verbose) -+ msg_warn("%s: socket: %m", myname); -+ goto end; -+ } -+ else -+#endif - msg_fatal("%s: socket: %m", myname); -+ } - - /* - * Get the network interface list. XXX The socket API appears to have no -@@ -126,10 +219,15 @@ - */ - the_end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); - for (ifr = ifc.ifc_req; ifr < the_end;) { -- if (ifr->ifr_addr.sa_family == AF_INET) { /* IP interface */ -+ if ((ifr->ifr_addr.sa_family == AF_INET) && -+ (ifr->ifr_addr.sa_family == af)) { /* IP interface */ - addr = ((struct sockaddr_in *) & ifr->ifr_addr)->sin_addr; - if (addr.s_addr != INADDR_ANY) { /* has IP address */ -+#ifdef INET6 -+ inet_addr_list_append(addr_list, &ifr->ifr_addr); -+#else - inet_addr_list_append(addr_list, &addr); -+#endif - if (mask_list) { - ifr_mask = (struct ifreq *) mymalloc(IFREQ_SIZE(ifr)); - memcpy((char *) ifr_mask, (char *) ifr, IFREQ_SIZE(ifr)); -@@ -141,11 +239,70 @@ - } - } - } -+#ifdef INET6 -+ else if ((ifr->ifr_addr.sa_family == AF_INET6) && -+ (ifr->ifr_addr.sa_family == af)) { /* IPv6 interface */ -+ addr6 = *((struct sockaddr_in6 *) & ifr->ifr_addr); -+#ifdef __KAME__ -+ /* decode scoped address notation */ -+ if ((IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr) || -+ IN6_IS_ADDR_SITELOCAL(&addr6.sin6_addr)) && -+ addr6.sin6_scope_id == 0) { -+ addr6.sin6_scope_id = ntohs(addr6.sin6_addr.s6_addr[3] | -+ (unsigned int)addr6.sin6_addr.s6_addr[2] << 8); -+ addr6.sin6_addr.s6_addr[2] = addr6.sin6_addr.s6_addr[3] = 0; -+ } -+#endif -+ if (!(IN6_IS_ADDR_UNSPECIFIED(&addr6.sin6_addr))) { -+ inet_addr_list_append(addr_list, (struct sockaddr *)&addr6); -+ if (mask_list) { -+#error "mask_list for IPv6 without libinet6 not done yet (error to avoid open-relay)" -+ /* TODO: how to get netmask here? */ -+ } -+ } -+ } -+#endif - ifr = NEXT_INTERFACE(ifr); - } - vstring_free(buf); - (void) close(sock); -+#ifdef INET6 -+end: -+ if (af != AF_INET6) { -+ af = AF_INET6; -+ goto other_socket_type; -+ } -+#if defined (LINUX) || defined (LINUX2) -+ if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) { -+ while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n", -+ addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], -+ addr6p[5], addr6p[6], addr6p[7], -+ &if_idx, &plen, &scope, &dad_status, devname) != EOF) { -+ sprintf(addr6res, "%s:%s:%s:%s:%s:%s:%s:%s", -+ addr6p[0], addr6p[1], addr6p[2], addr6p[3], -+ addr6p[4], addr6p[5], addr6p[6], addr6p[7]); -+ addr6res[sizeof(addr6res) - 1] = 0; -+ memset(&hints, 0, sizeof(hints)); -+ hints.ai_flags = AI_NUMERICHOST; -+ hints.ai_family = AF_UNSPEC; -+ hints.ai_socktype = SOCK_DGRAM; -+ gaierror = getaddrinfo(addr6res, NULL, &hints, &res0); -+ if (!gaierror) { -+ for (res = res0; res; res = res->ai_next) { -+ inet_addr_list_append(addr_list, res->ai_addr); -+ if (mask_list) { -+#error "mask_list for IPv6 without libinet6 not done yet (error to avoid open-relay)" -+ /* TODO: calculate netmask basing on plen */ -+ } -+ } -+ freeaddrinfo(res0); -+ } -+ } -+ } -+#endif /* linux */ -+#endif - return (addr_list->used - initial_count); -+#endif - } - - #ifdef TEST -@@ -158,6 +315,8 @@ - INET_ADDR_LIST addr_list; - INET_ADDR_LIST mask_list; - int i; -+ char abuf[NI_MAXHOST], mbuf[NI_MAXHOST]; -+ struct sockaddr *sa; - - msg_vstream_init(argv[0], VSTREAM_ERR); - -@@ -172,8 +331,17 @@ - msg_warn("found only one active network interface"); - - for (i = 0; i < addr_list.used; i++) { -- vstream_printf("%s/", inet_ntoa(addr_list.addrs[i])); -- vstream_printf("%s\n", inet_ntoa(mask_list.addrs[i])); -+ sa = (struct sockaddr *)&addr_list.addrs[i]; -+ if (getnameinfo(sa, SA_LEN(sa), abuf, sizeof(abuf), NULL, 0, -+ NI_NUMERICHOST)) { -+ strncpy(abuf, "???", sizeof(abuf)); -+ } -+ sa = (struct sockaddr *)&mask_list.addrs[i]; -+ if (getnameinfo(sa, SA_LEN(sa), mbuf, sizeof(mbuf), NULL, 0, -+ NI_NUMERICHOST)) { -+ strncpy(mbuf, "???", sizeof(mbuf)); -+ } -+ vstream_printf("%s/%s\n", abuf, mbuf); - } - vstream_fflush(VSTREAM_OUT); - inet_addr_list_free(&addr_list); -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/util/inet_connect.c postfix-2.0.16/src/util/inet_connect.c ---- postfix-2.0.16.orig/src/util/inet_connect.c 2003-09-13 03:04:12.000000000 +0200 -+++ postfix-2.0.16/src/util/inet_connect.c 2005-01-07 18:25:30.208329792 +0100 -@@ -55,6 +55,9 @@ - #include - #include - #include -+#ifdef INET6 -+#include -+#endif - - /* Utility library. */ - -@@ -74,7 +77,12 @@ - char *buf; - char *host; - char *port; -+#ifdef INET6 -+ struct addrinfo hints, *res, *res0; -+ int error; -+#else - struct sockaddr_in sin; -+#endif - int sock; - - /* -@@ -82,14 +90,58 @@ - * the local host. - */ - buf = inet_parse(addr, &host, &port); -+#ifdef INET6 -+ if (*host == 0) -+ host = NULL; -+ memset(&hints, 0, sizeof(hints)); -+ hints.ai_family = PF_UNSPEC; -+ hints.ai_socktype = SOCK_STREAM; -+ hints.ai_flags = AI_NUMERICHOST; /* find_inet_addr is numeric only */ -+ if (getaddrinfo(host, port, &hints, &res0)) -+ msg_fatal("host not found: %s", host); -+#else - if (*host == 0) - host = "localhost"; - memset((char *) &sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = find_inet_addr(host); - sin.sin_port = find_inet_port(port, "tcp"); -+#endif - myfree(buf); - -+#ifdef INET6 -+ sock = -1; -+ for (res = res0; res; res = res->ai_next) { -+ if ((res->ai_family != AF_INET) && (res->ai_family != AF_INET6)) -+ continue; -+ -+ sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); -+ if (sock < 0) -+ continue; -+ if (timeout > 0) { -+ non_blocking(sock, NON_BLOCKING); -+ if (timed_connect(sock, res->ai_addr, res->ai_addrlen, timeout) < 0) { -+ close(sock); -+ sock = -1; -+ continue; -+ } -+ if (block_mode != NON_BLOCKING) -+ non_blocking(sock, block_mode); -+ break; -+ } else { -+ non_blocking(sock, block_mode); -+ if (connect(sock, res->ai_addr, res->ai_addrlen) < 0 -+ && errno != EINPROGRESS) { -+ close(sock); -+ sock = -1; -+ continue; -+ } -+ break; -+ } -+ } -+ freeaddrinfo(res0); -+ return sock; -+#else - /* - * Create a client socket. - */ -@@ -122,4 +174,5 @@ - } - return (sock); - } -+#endif - } -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/util/inet_listen.c postfix-2.0.16/src/util/inet_listen.c ---- postfix-2.0.16.orig/src/util/inet_listen.c 2003-09-13 01:50:50.000000000 +0200 -+++ postfix-2.0.16/src/util/inet_listen.c 2005-01-07 18:25:30.208329792 +0100 -@@ -6,7 +6,7 @@ - /* SYNOPSIS - /* #include - /* --/* int inet_listen(addr, backlog, block_mode) -+/* int inet_listen(addr, backlog, block_mode, addinuse_fatal) - /* const char *addr; - /* int backlog; - /* int block_mode; -@@ -51,11 +51,17 @@ - #include - #include - #include -+#ifdef INET6 -+#if (! __GLIBC__ >= 2 && __GLIBC_MINOR__ >=1 ) -+#include -+#endif -+#endif - #include - #include - #ifndef MAXHOSTNAMELEN - #include - #endif -+#include - #include - #include - -@@ -77,35 +83,116 @@ - - /* inet_listen - create inet-domain listener */ - --int inet_listen(const char *addr, int backlog, int block_mode) -+int inet_listen(const char *addr, int backlog, int block_mode, int addrinuse_fatal) - { -+#ifdef INET6 -+ struct addrinfo *res, *res0, hints; -+ int error; -+#else -+ struct ai { -+ int ai_family; -+ int ai_socktype; -+ int ai_protocol; -+ struct sockaddr *ai_addr; -+ SOCKADDR_SIZE ai_addrlen; -+ struct ai *ai_next; -+ } *res, *res0, resbody; - struct sockaddr_in sin; -+#endif - int sock; - int t = 1; -+ int addrinuse = 0; - char *buf; - char *host; - char *port; -+#ifdef INET6 -+ char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; -+#else -+ char hbuf[sizeof("255.255.255.255") + 1]; -+ char pbuf[sizeof("255.255.255.255") + 1]; -+#endif -+ char *cause = "unknown"; - - /* - * Translate address information to internal form. - */ - buf = inet_parse(addr, &host, &port); -- memset((char *) &sin, 0, sizeof(sin)); -+#ifdef INET6 -+ memset(&hints, 0, sizeof(hints)); -+ hints.ai_flags = AI_PASSIVE; -+ hints.ai_family = AF_UNSPEC; -+ hints.ai_socktype = SOCK_STREAM; -+ error = getaddrinfo(*host ? host : NULL, *port ? port : "0", &hints, &res0); -+ if (error) { -+ msg_fatal("getaddrinfo: %s", gai_strerror(error)); -+ } -+ myfree(buf); -+#else -+ memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; -+#ifdef HAS_SA_LEN -+ sin.sin_len = sizeof(sin); -+#endif - sin.sin_port = find_inet_port(port, "tcp"); - sin.sin_addr.s_addr = (*host ? find_inet_addr(host) : INADDR_ANY); -- myfree(buf); - -- /* -- * Create a listener socket. -- */ -- if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) -- msg_fatal("socket: %m"); -- if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &t, sizeof(t)) < 0) -- msg_fatal("setsockopt: %m"); -- if (bind(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0) -- msg_fatal("bind %s port %d: %m", sin.sin_addr.s_addr == INADDR_ANY ? -- "INADDR_ANY" : inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); -+ memset(&resbody, 0, sizeof(resbody)); -+ resbody.ai_socktype = SOCK_STREAM; -+ resbody.ai_family = AF_INET; -+ resbody.ai_addr = (struct sockaddr *)&sin; -+ resbody.ai_addrlen = sizeof(sin); -+ -+ res0 = &resbody; -+#endif -+ -+ sock = -1; -+ for (res = res0; res; res = res->ai_next) { -+ if ((res->ai_family != AF_INET) && (res->ai_family != AF_INET6)) -+ continue; -+ -+ /* -+ * Create a listener socket. -+ */ -+ if ((sock = socket(res->ai_family, res->ai_socktype, 0)) < 0) { -+ cause = "socket"; -+ continue; -+ } -+#ifdef IPV6_V6ONLY -+ if (res->ai_family == AF_INET6 && -+ setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &t, sizeof(t)) < 0) { -+ /* if kernel/libc don't support this simple ignore it -+ cause = "setsockopt(IPV6_V6ONLY)"; -+ close(sock); -+ sock = -1; -+ continue; -+ */ -+ ; -+ } -+#endif -+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &t, sizeof(t)) < 0) { -+ cause = "setsockopt(SO_REUSEADDR)"; -+ close(sock); -+ sock = -1; -+ continue; -+ } -+ -+ if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) { -+ cause = "bind"; -+ if (errno == EADDRINUSE) -+ addrinuse = 1; -+ close(sock); -+ sock = -1; -+ continue; -+ } -+ break; -+ } -+ if (sock < 0 && (addrinuse_fatal || !addrinuse)) -+ msg_fatal("%s: %m", cause); -+#ifdef INET6 -+ freeaddrinfo(res0); -+#endif -+ if (sock < 0) -+ return -1; - non_blocking(sock, block_mode); - if (listen(sock, backlog) < 0) - msg_fatal("listen: %m"); -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/util/listen.h postfix-2.0.16/src/util/listen.h ---- postfix-2.0.16.orig/src/util/listen.h 1999-03-22 02:57:11.000000000 +0100 -+++ postfix-2.0.16/src/util/listen.h 2005-01-07 18:25:30.208329792 +0100 -@@ -20,7 +20,7 @@ - * Listener external interface. - */ - extern int unix_listen(const char *, int, int); --extern int inet_listen(const char *, int, int); -+extern int inet_listen(const char *, int, int, int); - extern int fifo_listen(const char *, int, int); - extern int stream_listen(const char *, int, int); - -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/util/match_list.c postfix-2.0.16/src/util/match_list.c ---- postfix-2.0.16.orig/src/util/match_list.c 2001-11-20 21:07:15.000000000 +0100 -+++ postfix-2.0.16/src/util/match_list.c 2005-01-07 18:25:30.209329640 +0100 -@@ -118,7 +118,7 @@ - list = match_list_parse(list, vstring_str(buf)); - if (vstream_fclose(fp)) - msg_fatal("%s: read file %s: %m", myname, pattern); -- } else if (strchr(pattern, ':') != 0) { /* type:table */ -+ } else if ((strchr(pattern, ']') == 0) && (strchr(pattern, ':') != 0)) { /* type:table */ - for (cp = pattern; *cp == '!'; cp++) - /* void */ ; - if (dict_handle(pattern) == 0) -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/util/match_ops.c postfix-2.0.16/src/util/match_ops.c ---- postfix-2.0.16.orig/src/util/match_ops.c 2003-04-14 16:44:19.000000000 +0200 -+++ postfix-2.0.16/src/util/match_ops.c 2005-01-07 18:25:30.210329488 +0100 -@@ -81,6 +81,308 @@ - #include - #include - -+#ifdef INET6 -+/* -+ * $Id$ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ * -+ * Authors: Alexey Kuznetsov, -+ * -+ * Modifications: -+ * Artur Frysiak -+ * Arkadiusz Mi¶kiewicz -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifndef AF_DECnet -+#define AF_DECnet 12 -+#endif -+ -+#ifndef PF_PACKET -+#define PF_PACKET 17 -+#endif -+ -+typedef struct -+{ -+ unsigned char family; -+ unsigned char bytelen; -+ signed short bitlen; -+ unsigned int data[4]; -+} inet_prefix; -+ -+/* prototypes */ -+int masked_match(char *, char *, char *); -+int get_integer(int *, char *, int); -+int get_addr_1(inet_prefix *, char *, int); -+int get_prefix_1(inet_prefix *, char *, int); -+int get_addr(inet_prefix *, char *, int); -+int get_prefix(inet_prefix *, char *, int); -+unsigned int get_addr32(char *); -+int matches(char *, char *); -+int inet_addr_match(inet_prefix *, inet_prefix *, int); -+int mask_match(char *, char *, char *); -+ -+int get_integer(int *val, char *arg, int base) -+{ -+ long res; -+ char *ptr; -+ -+ if (!arg || !*arg) -+ return -1; -+ res = strtol(arg, &ptr, base); -+ if (!ptr || ptr == arg || *ptr || res > INT_MAX || res < INT_MIN) -+ return -1; -+ *val = res; -+ return 0; -+} -+ -+int get_addr_1(inet_prefix *addr, char *name, int family) -+{ -+ char *cp; -+ unsigned char *ap = (unsigned char*)addr->data; -+ int i; -+ -+ memset(addr, 0, sizeof(*addr)); -+ -+ if (strcmp(name, "default") == 0 || strcmp(name, "any") == 0) { -+ if (family == AF_DECnet) -+ return -1; -+ addr->family = family; -+ addr->bytelen = (family == AF_INET6 ? 16 : 4); -+ addr->bitlen = -1; -+ return 0; -+ } -+ -+ if (strchr(name, ':')) { -+ addr->family = AF_INET6; -+ if (family != AF_UNSPEC && family != AF_INET6) -+ return -1; -+ if (inet_pton(AF_INET6, name, addr->data) <= 0) -+ return -1; -+ addr->bytelen = 16; -+ addr->bitlen = -1; -+ return 0; -+ } -+ addr->family = AF_INET; -+ if (family != AF_UNSPEC && family != AF_INET) -+ return -1; -+ addr->bytelen = 4; -+ addr->bitlen = -1; -+ for (cp = name, i = 0; *cp; cp++) { -+ if (*cp <= '9' && *cp >= '0') { -+ ap[i] = 10*ap[i] + (*cp-'0'); -+ continue; -+ } -+ if (*cp == '.' && ++i <= 3) -+ continue; -+ return -1; -+ } -+ return 0; -+} -+ -+int get_prefix_1(inet_prefix *dst, char *arg, int family) -+{ -+ int err; -+ unsigned plen; -+ char *slash; -+ -+ memset(dst, 0, sizeof(*dst)); -+ -+ if (strcmp(arg, "default") == 0 || strcmp(arg, "any") == 0) { -+ if (family == AF_DECnet) -+ return -1; -+ dst->family = family; -+ dst->bytelen = 0; -+ dst->bitlen = 0; -+ return 0; -+ } -+ -+ slash = strchr(arg, '/'); -+ if (slash) -+ *slash = 0; -+ err = get_addr_1(dst, arg, family); -+ if (err == 0) { -+ switch(dst->family) { -+ case AF_INET6: -+ dst->bitlen = 128; -+ break; -+ case AF_DECnet: -+ dst->bitlen = 16; -+ break; -+ default: -+ case AF_INET: -+ dst->bitlen = 32; -+ } -+ if (slash) { -+ if (get_integer(&plen, slash+1, 0) || plen > dst->bitlen) { -+ err = -1; -+ goto done; -+ } -+ dst->bitlen = plen; -+ } -+ } -+done: -+ if (slash) -+ *slash = '/'; -+ return err; -+} -+ -+int get_addr(inet_prefix *dst, char *arg, int family) -+{ -+#ifdef AF_PACKET -+ if (family == AF_PACKET) -+ return -1; -+#endif -+ if (get_addr_1(dst, arg, family)) -+ return -1; -+ return 0; -+} -+ -+int get_prefix(inet_prefix *dst, char *arg, int family) -+{ -+#ifdef AF_PACKET -+ if (family == AF_PACKET) -+ return -1; -+#endif -+ if (get_prefix_1(dst, arg, family)) -+ return -1; -+ return 0; -+} -+ -+unsigned int get_addr32(char *name) -+{ -+ inet_prefix addr; -+ if (get_addr_1(&addr, name, AF_INET)) -+ return -1; -+ return addr.data[0]; -+} -+ -+int matches(char *cmd, char *pattern) -+{ -+ int len = strlen(cmd); -+ if (len > strlen(pattern)) -+ return -1; -+ return memcmp(pattern, cmd, len); -+} -+ -+int inet_addr_match(inet_prefix *a, inet_prefix *b, int bits) -+{ -+ unsigned int *a1 = a->data; -+ unsigned int *a2 = b->data; -+ int words = bits >> 0x05; -+ -+ bits &= 0x1f; -+ -+ if (words) -+ if (memcmp(a1, a2, words << 2)) -+ return -1; -+ -+ if (bits) { -+ unsigned int w1, w2; -+ unsigned int mask; -+ -+ w1 = a1[words]; -+ w2 = a2[words]; -+ -+ mask = htonl((0xffffffff) << (0x20 - bits)); -+ -+ if ((w1 ^ w2) & mask) -+ return 1; -+ } -+ -+ return 0; -+} -+ -+/* zero if matches */ -+int mask_match(char *network, char *cprefix, char *address) -+{ -+ inet_prefix *inetwork; -+ inet_prefix *iaddress; -+ int ret, prefix; -+ -+ if (!(network && address && cprefix)) -+ return -1; -+ prefix = strtol(cprefix, (char **)NULL, 10); -+ if ((prefix < 0) || (prefix > 128)) -+ return -1; -+ if ((strlen(network) == 0) || (strlen(address) == 0)) -+ return -1; -+ -+ inetwork = malloc(sizeof(inet_prefix)); -+ iaddress = malloc(sizeof(inet_prefix)); -+ -+ if ((get_addr(iaddress, address, AF_UNSPEC) >= 0) -+ && (get_addr(inetwork, network, AF_UNSPEC) >= 0)) -+ ret = inet_addr_match(inetwork, iaddress, prefix); -+ else -+ ret = -1; -+ free(inetwork); -+ free(iaddress); -+ -+ /* 1 if matches */ -+ /* return (!ret); */ -+ /* 0 if matches */ -+ return ret; -+} -+ -+/* -+ * masked_match() - universal for IPv4 and IPv6 - 1 if matches -+ */ -+int masked_match(net_tok, mask_tok, string) -+char *net_tok; -+char *mask_tok; -+char *string; -+{ -+#ifdef INET6 -+ struct in6_addr in6[2]; -+ char v4addr[2][INET_ADDRSTRLEN]; -+ char newmask[6]; -+ int plen; -+#endif -+ -+ /* Check for NULL */ -+ if (!(net_tok && mask_tok && string)) -+ return 0; /* doesn't match!!! */ -+ -+ /* If IPv6 mapped convert to native-IPv4 */ -+#ifdef INET6 -+ if (inet_pton(AF_INET6, net_tok, &in6[0]) == 1 && -+ inet_pton(AF_INET6, string, &in6[1]) == 1 && -+ IN6_IS_ADDR_V4MAPPED(&in6[0]) && IN6_IS_ADDR_V4MAPPED(&in6[1])) { -+ plen = atoi(mask_tok); -+ if (32 < plen && plen < 129) { -+ sprintf(newmask, "%d", plen - 96); -+ mask_tok = newmask; -+ } -+ -+ (void)inet_ntop(AF_INET, &in6[0].s6_addr[12], v4addr[0], -+ sizeof(v4addr[0])); -+ net_tok = v4addr[0]; -+ (void)inet_ntop(AF_INET, &in6[1].s6_addr[12], v4addr[1], -+ sizeof(v4addr[1])); -+ string = v4addr[1]; -+ } -+#endif -+ return (!mask_match(net_tok, mask_tok, string)); -+} -+#endif -+ -+ - /* match_string - match a string literal */ - - int match_string(int unused_flags, const char *string, const char *pattern) -@@ -177,6 +479,7 @@ - return (0); - } - -+#ifndef INET6 - /* match_parse_mask - parse net/mask pattern */ - - static int match_parse_mask(const char *pattern, unsigned long *net_bits, -@@ -198,28 +501,55 @@ - return (mask != 0); - } - -+#endif - /* match_hostaddr - match host by address */ - - int match_hostaddr(int unused_flags, const char *addr, const char *pattern) - { - char *myname = "match_hostaddr"; -+#ifdef INET6 -+ char *network, *mask, *escl, *escr, *patternx; -+ struct in6_addr in6; -+ char v4addr[INET_ADDRSTRLEN]; -+#else - int mask_shift; - unsigned long mask_bits; - unsigned long net_bits; - unsigned long addr_bits; - struct in_addr net_addr; -+#endif - - if (msg_verbose) - msg_info("%s: %s ~? %s", myname, addr, pattern); - -+#ifdef INET6 -+ if (addr[strspn(addr, "01234567890./:abcdef")] != 0) -+#else - if (addr[strspn(addr, "01234567890./:")] != 0) -+#endif - return (0); - -+#ifdef INET6 -+ patternx = mystrdup(pattern); -+ escl = strchr(patternx,'['); -+ escr = strrchr(patternx,']'); -+ if (escl && escr) { -+ *escr = 0; -+ sprintf(patternx, "%s%s", escl + 1, escr + 1); -+ pattern = patternx; -+ } -+#endif -+ - /* - * Try dictionary lookup. This can be case insensitive. XXX Probably - * should also try again after stripping least significant octets. - */ -- if (strchr(pattern, ':') != 0) { -+#ifdef INET6 -+ if (!(escl && escr) && strchr(pattern, ':') != 0) -+#else -+ if (strchr(pattern, ':') != 0) -+#endif -+ { - if (dict_lookup(pattern, addr) != 0) - return (1); - if (dict_errno != 0) -@@ -230,6 +560,12 @@ - /* - * Try an exact match with the host address. - */ -+#ifdef INET6 -+ if (inet_pton(AF_INET6, addr, &in6) == 1 && IN6_IS_ADDR_V4MAPPED(&in6)) { -+ (void)inet_ntop(AF_INET, &in6.s6_addr[12], v4addr, sizeof(v4addr)); -+ addr = v4addr; -+ } -+#endif - if (strcasecmp(addr, pattern) == 0) { - return (1); - } -@@ -238,6 +574,20 @@ - * In a net/mask pattern, the mask is specified as the number of bits of - * the network part. - */ -+#ifdef INET6 -+ network = mystrdup(patternx); -+ mask = split_at(network, '/'); -+ -+ if (masked_match(network, mask, (char *)addr)) { -+ myfree(network); -+ myfree(patternx); -+ return (1); -+ } else { -+ myfree(network); -+ myfree(patternx); -+ } -+#else -+ - if (match_parse_mask(pattern, &net_bits, &mask_shift)) { - addr_bits = inet_addr(addr); - if (addr_bits == INADDR_NONE) -@@ -252,5 +602,6 @@ - pattern, inet_ntoa(net_addr), mask_shift); - } - } -+#endif - return (0); - } -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/util/sys_defs.h postfix-2.0.16/src/util/sys_defs.h ---- postfix-2.0.16.orig/src/util/sys_defs.h 2005-01-07 18:22:25.289441736 +0100 -+++ postfix-2.0.16/src/util/sys_defs.h 2005-01-07 18:25:30.211329336 +0100 -@@ -73,6 +73,10 @@ - #define DEF_MAILBOX_LOCK "flock, dotlock" - #endif - -+#if ((defined(__NetBSD_Version__) && __NetBSD_Version__ >= 105000000) || defined(USAGI_LIBINET6)) -+#define HAVE_GETIFADDRS -+#endif -+ - /* - * UNIX on MAC. - */ -diff -durN -x '*~' -x '*.orig' postfix-2.0.16.orig/src/util/valid_hostname.c postfix-2.0.16/src/util/valid_hostname.c ---- postfix-2.0.16.orig/src/util/valid_hostname.c 2002-12-20 02:33:41.000000000 +0100 -+++ postfix-2.0.16/src/util/valid_hostname.c 2005-01-07 18:25:30.211329336 +0100 -@@ -53,6 +53,13 @@ - #include - #include - -+#ifdef INET6 -+#include -+#include -+#include -+#include -+#endif -+ - /* Utility library. */ - - #include "msg.h" -@@ -109,7 +116,23 @@ - msg_warn("%s: misplaced hyphen: %.100s", myname, name); - return (0); - } -- } else { -+ } -+#ifdef INET6 -+ else if (ch == ':') { -+ struct addrinfo hints, *res; -+ -+ memset(&hints, 0, sizeof(hints)); -+ hints.ai_family = AF_INET6; -+ hints.ai_socktype = SOCK_STREAM; /*dummy*/ -+ hints.ai_flags = AI_NUMERICHOST; -+ if (getaddrinfo(name, "0", &hints, &res) == 0) { -+ freeaddrinfo(res); -+ return 1; -+ } else -+ return 0; -+ } -+#endif -+ else { - if (gripe) - msg_warn("%s: invalid character %d(decimal): %.100s", - myname, ch, name); -@@ -141,6 +164,9 @@ - int byte_count = 0; - int byte_val = 0; - int ch; -+#ifdef INET6 -+ struct addrinfo hints, *res; -+#endif - - #define BYTES_NEEDED 4 - -@@ -166,6 +192,17 @@ - return (1); - } - -+#ifdef INET6 -+ memset(&hints, 0, sizeof(hints)); -+ hints.ai_family = AF_INET6; -+ hints.ai_socktype = SOCK_STREAM; /*dummy*/ -+ hints.ai_flags = AI_NUMERICHOST; -+ if (getaddrinfo(addr, "0", &hints, &res) == 0) { -+ freeaddrinfo(res); -+ return 1; -+ } -+#endif -+ - /* - * Scary code to avoid sscanf() overflow nasties. - */ diff --git a/postfix-ns-mx-acl.patch b/postfix-ns-mx-acl.patch deleted file mode 100644 index 6c29adc..0000000 --- a/postfix-ns-mx-acl.patch +++ /dev/null @@ -1,478 +0,0 @@ -This is an unofficial patch for Postfix stable release 2.0 that -back-ports a new feature from the after-2.0 snapshot releases. - -This feature can be used to block mail from so-called spammer -havens, from sender addresses that resolve to Verisign's wild-card -mail responder, or from domains that claim to have mail servers in -reserved networks such as 127.0.0.1. - -This patch is a revised version; the first implementation of the -check_{helo,sender,recipient}_ns_access feature did not correctly -look up name server records and caused mail to be deferred with a -450 status code; the second revision no longer defers mail when -some NS or MX host lookup fails. - ------------------ - -The check_{helo,sender,recipient}_{ns,mx}_access maptype:mapname -restriction applies the specified access table to the NS or MX -hosts of the host/domain given in HELO, EHLO, MAIL FROM or RCPT TO -commands. - - /etc/postfix/main.cf: - smtpd_mumble_restrictions = - ... - reject_unknown_sender_domain - check_sender_mx_access hash:/etc/postfix/mx_access - ... - - /etc/postfix/mx_access: - spammer.haven.tld reject spammer mx host - 64.94.110.11 reject mail server in verisign wild-card domain - 127 reject mail server in loopback network - 0 reject mail server in broadcast network - -The following entries block mail from domains that claim to have -have mail servers or domain servers in reserved networks. - - 10 reject mail server in RFC 1918 private network - 169.254 reject mail server in link local network - 172.16 reject mail server in RFC 1918 private network - ...similar entries for 172.17...172.31 - 192.0.2 reject mail server in TEST-NET network - 192.168 reject mail server in RFC 1918 private network - 224 reject mail server in class D multicast network - ...similar entries for 225...239 - 240 reject mail server in class E reserved network - ...similar entries for 241...247 - 248 reject mail server in reserved network - ...similar entries for 249...255 - -diff -cr /tmp/postfix-2.0.16/conf/sample-smtpd.cf ./conf/sample-smtpd.cf -*** /tmp/postfix-2.0.16/conf/sample-smtpd.cf Tue Aug 12 12:28:46 2003 ---- ./conf/sample-smtpd.cf Fri Sep 19 11:17:34 2003 -*************** -*** 311,316 **** ---- 311,321 ---- - # check_helo_access maptype:mapname - # look up HELO hostname or parent domains. - # see access(5) for possible lookup results. -+ # check_helo_mx_access maptype:mapname -+ # check_helo_ns_access maptype:mapname -+ # look up the helo hostname MX hosts (or name servers) and apply the -+ # specified access table to those hosts. -+ # Note: the OK result is not allowed here for security reasons. - # reject: reject the request. Place this at the end of a restriction. - # permit: permit the request. Place this at the end of a restriction. - # warn_if_reject: next restriction logs a warning instead of rejecting. -*************** -*** 343,348 **** ---- 348,358 ---- - # check_sender_access maptype:mapname - # look up sender address, parent domain, or localpart@. - # see access(5) for possible lookup results. -+ # check_sender_mx_access maptype:mapname -+ # check_sender_ns_access maptype:mapname -+ # look up sender address MX hosts (or name servers) and apply the -+ # specified access table to those hosts. -+ # Note: the OK result is not allowed here for security reasons. - # reject_sender_login_mismatch: reject if $smtpd_sender_login_maps specifies - # a MAIL FROM address owner, but the client is not (SASL) logged in as - # that MAIL FROM address owner; or if the client is (SASL) logged in, but -*************** -*** 409,414 **** ---- 419,429 ---- - # check_recipient_access maptype:mapname - # look up recipient address, parent domain, or localpart@. - # see access(5) for possible lookup results. -+ # check_recipient_mx_access maptype:mapname -+ # check_recipient_ns_access maptype:mapname -+ # look up the recipient address MX hosts (or name servers) and apply the -+ # specified access table to those hosts. -+ # Note: the OK result is not allowed here for security reasons. - # reject_non_fqdn_recipient: reject recipient address that is not in FQDN form - # reject: reject the request. Place this at the end of a restriction. - # permit: permit the request. Place this at the end of a restriction. -diff -cr /tmp/postfix-2.0.16/html/uce.html ./html/uce.html -*** /tmp/postfix-2.0.16/html/uce.html Mon Aug 25 09:54:11 2003 ---- ./html/uce.html Fri Sep 19 11:17:34 2003 -*************** -*** 567,572 **** ---- 567,588 ---- - -

- -+ -+ -+

check_helo_ns_access maptype:mapname -+ -+ -+ -+
check_helo_mx_access maptype:mapname -+ -+
Apply the specified access database -+ to the DNS (or MX) servers for the host or domain name given with -+ the HELO (or EHLO) command. -+ -+
Note: an OK result is not allowed for safety reasons. -+ -+

-+ -

permit - -
defer -*************** -*** 714,719 **** ---- 730,751 ---- - -

- -+ -+ -+

check_sender_ns_access maptype:mapname -+ -+ -+ -+
check_sender_mx_access maptype:mapname -+ -+
Apply the specified access database -+ to the DNS (or MX) servers for the host or domain name given with -+ the MAIL FROM command. -+ -+
Note: an OK result is not allowed for safety reasons. -+ -+

-+ - - -

reject_non_fqdn_sender
Reject the request when -*************** -*** 921,926 **** ---- 953,974 ---- -
maptype:mapname
Search the named access database for the resolved destination - address, recipient domain or parent domain, or localpart@. -+ -+

-+ -+ -+ -+

check_recipient_ns_access maptype:mapname -+ -+ -+ -+
check_recipient_mx_access maptype:mapname -+ -+
Apply the specified access database -+ to the DNS servers (or MX hosts) for the host or domain name given -+ with the RCPT TO command. -+ -+
Note: an OK result is not allowed for safety reasons. - -

- -diff -cr /tmp/postfix-2.0.16/src/dns/dns_lookup.c ./src/dns/dns_lookup.c -*** /tmp/postfix-2.0.16/src/dns/dns_lookup.c Sun Dec 8 09:09:11 2002 ---- ./src/dns/dns_lookup.c Fri Sep 19 11:17:34 2003 -*************** -*** 509,514 **** ---- 509,515 ---- - vstring_sprintf(why, - "Name service error for %s: invalid host or domain name", - name); -+ h_errno = HOST_NOT_FOUND; - return (DNS_NOTFOUND); - } - -*************** -*** 520,525 **** ---- 521,527 ---- - vstring_sprintf(why, - "Name service error for %s: invalid host or domain name", - name); -+ h_errno = HOST_NOT_FOUND; - return (DNS_NOTFOUND); - } - -diff -cr /tmp/postfix-2.0.16/src/global/mail_params.h ./src/global/mail_params.h -*** /tmp/postfix-2.0.16/src/global/mail_params.h Mon Mar 3 17:07:03 2003 ---- ./src/global/mail_params.h Fri Sep 19 11:17:35 2003 -*************** -*** 1249,1254 **** ---- 1249,1261 ---- - #define CHECK_RECIP_ACL "check_recipient_access" - #define CHECK_ETRN_ACL "check_etrn_access" - -+ #define CHECK_HELO_MX_ACL "check_helo_mx_access" -+ #define CHECK_SENDER_MX_ACL "check_sender_mx_access" -+ #define CHECK_RECIP_MX_ACL "check_recipient_mx_access" -+ #define CHECK_HELO_NS_ACL "check_helo_ns_access" -+ #define CHECK_SENDER_NS_ACL "check_sender_ns_access" -+ #define CHECK_RECIP_NS_ACL "check_recipient_ns_access" -+ - #define WARN_IF_REJECT "warn_if_reject" - - #define REJECT_RBL "reject_rbl" /* LaMont compatibility */ -diff -cr /tmp/postfix-2.0.16/src/smtpd/smtpd_check.c ./src/smtpd/smtpd_check.c -*** /tmp/postfix-2.0.16/src/smtpd/smtpd_check.c Tue Aug 12 10:53:25 2003 ---- ./src/smtpd/smtpd_check.c Fri Sep 19 11:17:52 2003 -*************** -*** 86,91 **** ---- 86,103 ---- - /* .IP "check_recipient_access maptype:mapname" - /* Look up the resolved recipient address in the named access table, - /* any parent domains of the recipient domain, and the localpart@. -+ /* .IP "check_helo_mx_access maptype:mapname" -+ /* .IP "check_sender_mx_access maptype:mapname" -+ /* .IP "check_recipient_mx_access maptype:mapname" -+ /* Apply the specified access table to the MX server host name and IP -+ /* addresses for the helo hostname, sender, or recipient, respectively. -+ /* If no MX record is found the A record is used instead. -+ /* .IP "check_helo_ns_access maptype:mapname" -+ /* .IP "check_sender_ns_access maptype:mapname" -+ /* .IP "check_recipient_ns_access maptype:mapname" -+ /* Apply the specified access table to the DNS server host name and IP -+ /* addresses for the helo hostname, sender, or recipient, respectively. -+ /* If no NS record is found, the parent domain is used instead. - /* .IP "check_recipient_maps" - /* Reject recipients not listed as valid local, virtual or relay - /* recipients. -*************** -*** 455,460 **** ---- 467,484 ---- - else \ - (void) smtpd_check_reject((state), (class), (fmt), (a1), (a2)); \ - } while (0) -+ #define DEFER_IF_PERMIT3(state, class, fmt, a1, a2, a3) do { \ -+ if ((state)->warn_if_reject == 0) \ -+ defer_if(&(state)->defer_if_permit, (class), (fmt), (a1), (a2), (a3)); \ -+ else \ -+ (void) smtpd_check_reject((state), (class), (fmt), (a1), (a2), (a3)); \ -+ } while (0) -+ #define DEFER_IF_PERMIT4(state, class, fmt, a1, a2, a3, a4) do { \ -+ if ((state)->warn_if_reject == 0) \ -+ defer_if(&(state)->defer_if_permit, (class), (fmt), (a1), (a2), (a3), (a4)); \ -+ else \ -+ (void) smtpd_check_reject((state), (class), (fmt), (a1), (a2), (a3), (a4)); \ -+ } while (0) - - /* - * Cached RBL lookup state. -*************** -*** 2005,2010 **** ---- 2029,2151 ---- - return (SMTPD_CHECK_DUNNO); - } - -+ /* check_server_access - access control by server host name or address */ -+ -+ static int check_server_access(SMTPD_STATE *state, const char *table, -+ const char *name, -+ int type, -+ const char *reply_name, -+ const char *reply_class, -+ const char *def_acl) -+ { -+ const char *myname = "check_server_access"; -+ const char *domain; -+ int dns_status; -+ DNS_RR *server_list; -+ DNS_RR *server; -+ int found = 0; -+ struct in_addr addr; -+ struct hostent *hp; -+ char *addr_string; -+ int status; -+ char **cpp; -+ static DNS_FIXED fixed; -+ -+ /* -+ * Sanity check. -+ */ -+ if (type != T_MX && type != T_NS) -+ msg_panic("%s: unexpected resource type \"%s\" in request", -+ myname, dns_strtype(type)); -+ -+ if (msg_verbose) -+ msg_info("%s: %s %s", myname, dns_strtype(type), name); -+ -+ /* -+ * Skip over local-part. -+ */ -+ if ((domain = strrchr(name, '@')) != 0) -+ domain += 1; -+ else -+ domain = name; -+ -+ /* -+ * If the domain name does not exist then we apply no restriction. -+ * -+ * If the domain name exists but no MX record exists, fabricate an MX record -+ * that points to the domain name itself. -+ * -+ * If the domain name exists but no NS record exists, look up parent domain -+ * NS records. -+ */ -+ dns_status = dns_lookup(domain, type, 0, &server_list, -+ (VSTRING *) 0, (VSTRING *) 0); -+ if (dns_status == DNS_NOTFOUND && h_errno == NO_DATA) { -+ if (type == T_MX) { -+ server_list = dns_rr_create(domain, &fixed, 0, -+ domain, strlen(domain) + 1); -+ dns_status = DNS_OK; -+ } else if (type == T_NS) { -+ while ((domain = strchr(domain, '.')) != 0 && domain[1]) { -+ domain += 1; -+ dns_status = dns_lookup(domain, type, 0, &server_list, -+ (VSTRING *) 0, (VSTRING *) 0); -+ if (dns_status != DNS_NOTFOUND || h_errno != NO_DATA) -+ break; -+ } -+ } -+ } -+ if (dns_status != DNS_OK) { -+ msg_warn("Unable to look up %s host for %s", dns_strtype(type), -+ domain && domain[1] ? domain : reply_name); -+ return (SMTPD_CHECK_DUNNO); -+ } -+ -+ /* -+ * No bare returns after this point or we have a memory leak. -+ */ -+ #define CHECK_SERVER_RETURN(x) { dns_rr_free(server_list); return(x); } -+ -+ /* -+ * Check the hostnames first, then the addresses. -+ */ -+ for (server = server_list; server != 0; server = server->next) { -+ if ((hp = gethostbyname((char *) server->data)) == 0) { -+ msg_warn("Unable to look up %s host %s for %s %s", -+ dns_strtype(type), (char *) server->data, -+ reply_class, reply_name); -+ continue; -+ } -+ if (hp->h_addrtype != AF_INET || hp->h_length != sizeof(addr)) { -+ if (msg_verbose) -+ msg_warn("address type %d length %d for %s", -+ hp->h_addrtype, hp->h_length, (char *) server->data); -+ continue; /* XXX */ -+ } -+ if (msg_verbose) -+ msg_info("%s: %s hostname check: %s", -+ myname, dns_strtype(type), (char *) server->data); -+ if ((status = check_domain_access(state, table, (char *) server->data, -+ FULL, &found, reply_name, reply_class, -+ def_acl)) != 0 || found) -+ CHECK_SERVER_RETURN(status); -+ if (msg_verbose) -+ msg_info("%s: %s host address check: %s", -+ myname, dns_strtype(type), (char *) server->data); -+ for (cpp = hp->h_addr_list; *cpp; cpp++) { -+ memcpy((char *) &addr, *cpp, sizeof(addr)); -+ addr_string = mystrdup(inet_ntoa(addr)); -+ status = check_addr_access(state, table, addr_string, FULL, -+ &found, reply_name, reply_class, -+ def_acl); -+ myfree(addr_string); -+ if (status != 0 || found) -+ CHECK_SERVER_RETURN(status); -+ } -+ } -+ CHECK_SERVER_RETURN(SMTPD_CHECK_DUNNO); -+ } -+ - /* check_mail_access - OK/FAIL based on mail address lookup */ - - static int check_mail_access(SMTPD_STATE *state, const char *table, -*************** -*** 2568,2573 **** ---- 2709,2728 ---- - } - } - -+ /* forbid_whitelist - disallow whitelisting */ -+ -+ static void forbid_whitelist(SMTPD_STATE *state, const char *name, -+ int status, const char *target) -+ { -+ if (status == SMTPD_CHECK_OK) { -+ msg_warn("restriction %s returns OK for %s", name, target); -+ msg_warn("this is not allowed for security reasons"); -+ msg_warn("use DUNNO instead of OK if you want to make an exception"); -+ longjmp(smtpd_check_buf, smtpd_check_reject(state, MAIL_ERROR_SOFTWARE, -+ "451 Server configuration error")); -+ } -+ } -+ - /* generic_checks - generic restrictions */ - - static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, -*************** -*** 2722,2727 **** ---- 2877,2896 ---- - state->helo_name, SMTPD_NAME_HELO)) == 0) - status = SMTPD_CHECK_OK; - } -+ } else if (is_map_command(state, name, CHECK_HELO_NS_ACL, &cpp)) { -+ if (state->helo_name) { -+ status = check_server_access(state, *cpp, state->helo_name, -+ T_NS, state->helo_name, -+ SMTPD_NAME_HELO, def_acl); -+ forbid_whitelist(state, name, status, state->helo_name); -+ } -+ } else if (is_map_command(state, name, CHECK_HELO_MX_ACL, &cpp)) { -+ if (state->helo_name) { -+ status = check_server_access(state, *cpp, state->helo_name, -+ T_MX, state->helo_name, -+ SMTPD_NAME_HELO, def_acl); -+ forbid_whitelist(state, name, status, state->helo_name); -+ } - } else if (strcasecmp(name, REJECT_NON_FQDN_HOSTNAME) == 0) { - if (state->helo_name) { - if (*state->helo_name != '[') -*************** -*** 2760,2765 **** ---- 2929,2948 ---- - } else if (strcasecmp(name, REJECT_SENDER_LOGIN_MISMATCH) == 0) { - if (state->sender && *state->sender) - status = reject_sender_login_mismatch(state, state->sender); -+ } else if (is_map_command(state, name, CHECK_SENDER_NS_ACL, &cpp)) { -+ if (state->sender && *state->sender) { -+ status = check_server_access(state, *cpp, state->sender, -+ T_NS, state->sender, -+ SMTPD_NAME_SENDER, def_acl); -+ forbid_whitelist(state, name, status, state->sender); -+ } -+ } else if (is_map_command(state, name, CHECK_SENDER_MX_ACL, &cpp)) { -+ if (state->sender && *state->sender) { -+ status = check_server_access(state, *cpp, state->sender, -+ T_MX, state->sender, -+ SMTPD_NAME_SENDER, def_acl); -+ forbid_whitelist(state, name, status, state->sender); -+ } - } else if (strcasecmp(name, REJECT_RHSBL_SENDER) == 0) { - if (cpp[1] == 0) - msg_warn("restriction %s requires domain name argument", name); -*************** -*** 2812,2817 **** ---- 2995,3014 ---- - if (state->recipient) - status = reject_non_fqdn_address(state, state->recipient, - state->recipient, SMTPD_NAME_RECIPIENT); -+ } else if (is_map_command(state, name, CHECK_RECIP_NS_ACL, &cpp)) { -+ if (state->recipient && *state->recipient) { -+ status = check_server_access(state, *cpp, state->recipient, -+ T_NS, state->recipient, -+ SMTPD_NAME_RECIPIENT, def_acl); -+ forbid_whitelist(state, name, status, state->recipient); -+ } -+ } else if (is_map_command(state, name, CHECK_RECIP_MX_ACL, &cpp)) { -+ if (state->recipient && *state->recipient) { -+ status = check_server_access(state, *cpp, state->recipient, -+ T_MX, state->recipient, -+ SMTPD_NAME_RECIPIENT, def_acl); -+ forbid_whitelist(state, name, status, state->recipient); -+ } - } else if (strcasecmp(name, REJECT_RHSBL_RECIPIENT) == 0) { - if (cpp[1] == 0) - msg_warn("restriction %s requires domain name argument", name); diff --git a/postfix-pgsql.patch b/postfix-pgsql.patch deleted file mode 100644 index 596624c..0000000 --- a/postfix-pgsql.patch +++ /dev/null @@ -1,916 +0,0 @@ ---- postfix-2.0.16.orig/PGSQL_README 1970-01-01 01:00:00.000000000 +0100 -+++ postfix-2.0.16/PGSQL_README 2003-11-08 20:11:44.000000000 +0100 -@@ -0,0 +1,88 @@ -+[Code contributed by Mathieu Arnold] -+ -+We've written code to add a pgsql map type. It utilizes the pgsql -+client library, which can be obtained from: -+ -+ http://www.postgresql.org/ -+ -+In order to build postfix with pgsql map support, you will need to add -+-DHAS_PGSQL and -I for the directory containing the postgres headers, and -+the libpq library (and libcrypt) to AUXLIBS, for example: -+ -+make -f Makefile.init makefiles \ -+ 'CCARGS=-DHAS_PGSQL -I/some/where/include/postgresql' \ -+ 'AUXLIBS=/some/where/lib/postgres/libpq.a -lcrypt' -+ -+then, just run 'make'. -+ -+Postfix installations which may benefit from using pgsql map types -+include sites that have a need for instantaneous updates of -+forwarding, and sites that may benefit from having mail exchangers -+reference a networked database, possibly working in conjunction with a -+customer database of sorts. -+ -+Once postfix is built with pgsql support, you can specify a map type -+in main.cf like this: -+ -+alias_maps = pgsql:/etc/postfix/pgsql-aliases.cf -+ -+The file /etc/postfix/pgsql-aliases.cf specifies lots of information -+telling postfix how to reference the postgresql database. An example -+postgresql map config file follows: -+ -+# -+# postgresql config file for alias lookups on postfix -+# comments are ok. -+# -+ -+# the user name and password to log into the pgsql server -+user = someone -+password = some_passwordd -+ -+# the database name on the servers -+dbname = customer_database -+ -+# the table name -+table = mxaliases -+ -+# -+select_field = forw_addr -+where_field = alias -+ -+# you may specify additional_conditions here -+additional_conditions = and status = 'paid' -+ -+# the above variables will result in a query of -+# the form: -+# select forw_addr from mxaliases where alias = '$lookup' and status = 'paid' -+# ($lookup is escaped so if it contains single quotes or other odd -+# characters, it will not cause a parse error in the sql). -+# -+# the hosts that postfix will try to connect to -+# and query from (in the order listed) -+hosts = host1.some.domain host2.some.domain -+ -+# end postgresql config file -+ -+Some notes: -+ -+This configuration interface setup allows for multiple postgresql -+databases: you can use one for a virtual table, one for an access -+table, and one for an aliases table if you want. -+ -+Since sites that have a need for multiple mail exchangers may enjoy -+the convenience of using a networked mailer database, but do not want -+to introduce a single point of failure to their system, we've included -+the ability to have postfix reference multiple hosts for access to a -+single pgsql map. This will work if sites set up mirrored pgsql -+databases on two or more hosts. Whenever queries fail with an error -+at one host, the rest of the hosts will be tried in order. Each host -+that is in an error state will undergo a reconnection attempt every so -+often, and if no pgsql server hosts are reachable, then mail will be -+deferred until atleast one of those hosts is reachable. -+ -+Performance of postfix with pgsql has not been thoroughly tested, -+however, we have found it to be stable. Busy mail servers using pgsql -+maps will generate lots of concurrent pgsql clients, so the pgsql -+server(s) should be run with this fact in mind. Any further -+performance information, in addition to any feedback is most welcome. ---- postfix-2.0.16.orig/src/util/dict_open.c 2003-11-08 20:10:08.000000000 +0100 -+++ postfix-2.0.16/src/util/dict_open.c 2003-11-08 20:11:44.000000000 +0100 -@@ -178,6 +178,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -230,6 +231,9 @@ - #ifdef HAS_MYSQL - DICT_TYPE_MYSQL, dict_mysql_open, - #endif -+#ifdef HAS_PGSQL -+ DICT_TYPE_PGSQL, dict_pgsql_open, -+#endif - #ifndef MAX_DYNAMIC_MAPS - #ifdef HAS_PCRE - DICT_TYPE_PCRE, dict_pcre_open, ---- postfix-2.0.16.orig/src/util/dict_pgsql.c 1970-01-01 01:00:00.000000000 +0100 -+++ postfix-2.0.16/src/util/dict_pgsql.c 2003-11-08 20:11:44.000000000 +0100 -@@ -0,0 +1,675 @@ -+ -+/*++ -+/* NAME -+/* dict_pgsql 3 -+/* SUMMARY -+/* dictionary manager interface to db files -+/* SYNOPSIS -+/* #include -+/* #include -+/* -+/* DICT *dict_pgsql_open(name, dummy, unused_dict_flags) -+/* const char *name; -+/* int dummy; -+/* int unused_dict_flags; -+/* DESCRIPTION -+/* dict_pgsql_open() creates a dictionary of type 'pg'. This -+/* dictionary is an interface for the postfix key->value mappings -+/* to pgsql. The result is a pointer to the installed dictionary, -+/* or a null pointer in case of problems. -+/* -+/* The pgsql dictionary can manage multiple connections to different -+/* sql servers on different hosts. It assumes that the underlying data -+/* on each host is identical (mirrored) and maintains one connection -+/* at any given time. If any connection fails, any other available -+/* ones will be opened and used. The intent of this feature is to eliminate -+/* a single point of failure for mail systems that would otherwise rely -+/* on a single pgsql server. -+/* -+/* Arguments: -+/* .IP name -+/* The path of the PostgreSQL configuration file. The file encodes a number of -+/* pieces of information: username, password, databasename, table, -+/* select_field, where_field, and hosts. For example, if you want the map to -+/* reference databases of the name "your_db" and execute a query like this: -+/* select forw_addr from aliases where alias like '' against -+/* any database called "vmailer_info" located on hosts host1.some.domain and -+/* host2.some.domain, logging in as user "vmailer" and password "passwd" then -+/* the configuration file should read: -+/* -+/* user = vmailer -+/* password = passwd -+/* DBname = vmailer_info -+/* table = aliases -+/* select_field = forw_addr -+/* where_field = alias -+/* hosts = host1.some.domain host2.some.domain -+/* -+/* .IP other_name -+/* reference for outside use. -+/* .IP unusued_flags -+/* unused flags -+/* SEE ALSO -+/* dict(3) generic dictionary manager -+/* AUTHOR(S) -+/* Mathieu Arnold -+/* Absolight -+/* mat@absolight.com -+/* -+/* based on dict_mysql by -+/* -+/* Scott Cotton -+/* IC Group, Inc. -+/* scott@icgroup.com -+/* -+/* Joshua Marcus -+/* IC Group, Inc. -+/* josh@icgroup.com -+/*--*/ -+ -+/* System library. */ -+#include "sys_defs.h" -+ -+#ifdef HAS_PGSQL -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Utility library. */ -+#include "dict.h" -+#include "msg.h" -+#include "mymalloc.h" -+#include "dict_pgsql.h" -+#include "argv.h" -+#include "vstring.h" -+#include "split_at.h" -+#include "find_inet.h" -+ -+/* need some structs to help organize things */ -+typedef struct -+{ -+ PGconn *db; -+ char *hostname; -+ int stat; /* STATUNTRIED | STATFAIL | STATCUR */ -+ time_t ts; /* used for attempting reconnection -+ * every so often if a host is down */ -+} HOST; -+ -+typedef struct -+{ -+ int len_hosts; /* number of hosts */ -+ HOST *db_hosts; /* the hosts on which the databases -+ * reside */ -+} PLPGSQL; -+ -+typedef struct -+{ -+ char *username; -+ char *password; -+ char *dbname; -+ char *table; -+ char *select_field; -+ char *where_field; -+ char *additional_conditions; -+ char **hostnames; -+ int len_hosts; -+} PGSQL_NAME; -+ -+typedef struct -+{ -+ DICT dict; -+ PLPGSQL *pldb; -+ PGSQL_NAME *name; -+} DICT_PGSQL; -+ -+#define STATACTIVE 0 -+#define STATFAIL 1 -+#define STATUNTRIED 2 -+#define RETRY_CONN_INTV 60 /* 1 minute */ -+ -+/* internal function declarations */ -+static PLPGSQL *plpgsql_init (char *hostnames[], int); -+static PGresult *plpgsql_query (PLPGSQL *, const char *, char *, char *, -+ -+ char *); -+static void plpgsql_dealloc (PLPGSQL *); -+static void plpgsql_down_host (HOST *); -+static void plpgsql_connect_single (HOST *, char *, char *, char *); -+static int plpgsql_ready_reconn (HOST *); -+static const char *dict_pgsql_lookup (DICT *, const char *); -+DICT *dict_pgsql_open (const char *, int, int); -+static void dict_pgsql_close (DICT *); -+static PGSQL_NAME *pgsqlname_parse (const char *); -+static HOST host_init (char *); -+void pgsql_escape_string (char *escaped, const char *name, int len); -+ -+ -+ -+/********************************************************************** -+ * public interface dict_pgsql_lookup -+ * find database entry return 0 if no alias found, set dict_errno -+ * on errors to DICT_ERRBO_RETRY and set dict_errno to 0 on success -+ *********************************************************************/ -+static const char *dict_pgsql_lookup (DICT *dict, const char *name) -+{ -+ PGresult *query_res; -+ char *field; -+ DICT_PGSQL *dict_pgsql; -+ PLPGSQL *pldb; -+ static VSTRING *result; -+ static VSTRING *query = 0; -+ int i, -+ j, -+ numrows; -+ char *name_escaped = 0; -+ -+ dict_pgsql = (DICT_PGSQL *) dict; -+ pldb = dict_pgsql->pldb; -+ /* initialization for query */ -+ query = vstring_alloc (24); -+ vstring_strcpy (query, ""); -+ if ( -+ (name_escaped = -+ (char *) mymalloc ((sizeof (char) * (strlen (name) * 2) + 1))) == -+ NULL) -+ { -+ msg_fatal ("dict_pgsql_lookup: out of memory."); -+ } -+ /* prepare the query */ -+ pgsql_escape_string (name_escaped, name, (unsigned int) strlen (name)); -+ vstring_sprintf (query, "select %s from %s where %s = '%s' %s", -+ dict_pgsql->name->select_field, dict_pgsql->name->table, -+ dict_pgsql->name->where_field, name_escaped, -+ dict_pgsql->name->additional_conditions); -+ if (msg_verbose) -+ msg_info ("dict_pgsql_lookup using sql query: %s", -+ vstring_str (query)); -+ /* free mem associated with preparing the query */ -+ myfree (name_escaped); -+ /* do the query - set dict_errno & cleanup if there's an error */ -+ if ((query_res = plpgsql_query (pldb, -+ vstring_str (query), -+ dict_pgsql->name->dbname, -+ dict_pgsql->name->username, -+ dict_pgsql->name->password)) == 0) -+ { -+ dict_errno = DICT_ERR_RETRY; -+ vstring_free (query); -+ return 0; -+ } -+ dict_errno = 0; -+ /* free the vstring query */ -+ vstring_free (query); -+ numrows = PQntuples (query_res); -+ if (msg_verbose) -+ msg_info ("dict_pgsql_lookup: retrieved %d rows", numrows); -+ if (numrows == 0) -+ { -+ PQclear (query_res); -+ return 0; -+ } -+ if (result == 0) -+ result = vstring_alloc (10); -+ vstring_strcpy (result, ""); -+ for (i = 0; i < numrows; i++) -+ { -+ if (i > 0) -+ vstring_strcat (result, ","); -+ for (j = 0; j < PQnfields (query_res); j++) -+ { -+ if (j > 0) -+ vstring_strcat (result, ","); -+ field = PQgetvalue (query_res, i, j); -+ vstring_strcat (result, field); -+ if (msg_verbose > 1) -+ msg_info ("dict_pgsql_lookup: retrieved field: %d: %s", j, -+ field); -+ } -+ } -+ PQclear (query_res); -+ return vstring_str (result); -+} -+ -+/* -+ * plpgsql_query - process a PGSQL query. Return PGresult* on success. -+ * On failure, log failure and try other db instances. -+ * on failure of all db instances, return 0; -+ * close unnecessary active connections -+ */ -+ -+static PGresult *plpgsql_query (PLPGSQL * PLDB, -+ const char *query, -+ char *dbname, char *username, char *password) -+{ -+ int i; -+ HOST *host; -+ PGresult *res = 0; -+ ExecStatusType status; -+ -+ for (i = 0; i < PLDB->len_hosts; i++) -+ { -+ /* can't deal with typing or reading PLDB->db_hosts[i] over & over */ -+ host = &(PLDB->db_hosts[i]); -+ if (msg_verbose > 1) -+ msg_info ("dict_pgsql: trying host %s stat %d, last res %p", -+ host->hostname, host->stat, res); -+ -+ /* answer already found */ -+ if (res != 0 && host->stat == STATACTIVE) -+ { -+ if (msg_verbose) -+ msg_info -+ ("dict_pgsql: closing unnessary connection to %s", -+ host->hostname); -+ plpgsql_down_host (host); -+ } -+ /* try to connect for the first time if we don't have a result yet */ -+ if (res == 0 && host->stat == STATUNTRIED) -+ { -+ if (msg_verbose) -+ msg_info ("dict_pgsql: attempting to connect to host %s", -+ host->hostname); -+ plpgsql_connect_single (host, dbname, username, password); -+ } -+ -+ /* -+ * try to reconnect if we don't have an answer and the host had a -+ * prob in the past and it's time for it to reconnect -+ */ -+ if (res == 0 && host->stat == STATFAIL -+ && host->ts < time ((time_t *) 0)) -+ { -+ if (msg_verbose) -+ msg_info -+ ("dict_pgsql: attempting to reconnect to host %s", -+ host->hostname); -+ plpgsql_connect_single (host, dbname, username, password); -+ } -+ -+ /* -+ * if we don't have a result and the current host is marked active, -+ * try the query. If the query fails, mark the host STATFAIL -+ */ -+ if (res == 0 && host->stat == STATACTIVE) -+ { -+ res = PQexec (host->db, query); -+ status = PQresultStatus (res); -+ if (res -+ && (status = PGRES_COMMAND_OK -+ || status == PGRES_TUPLES_OK)) -+ { -+ if (msg_verbose) -+ msg_info -+ ("dict_pgsql: successful query from host %s", -+ host->hostname); -+ } -+ else -+ { -+ msg_warn ("%s", PQerrorMessage (host->db)); -+ plpgsql_down_host (host); -+ } -+ } -+ } -+ return res; -+} -+ -+/* -+ * plpgsql_connect_single - -+ * used to reconnect to a single database when one is down or none is -+ * connected yet. Log all errors and set the stat field of host accordingly -+ */ -+static void -+plpgsql_connect_single (HOST *host, char *dbname, char *username, -+ char *password) -+{ -+ char *destination = host->hostname; -+ char *hostname = 0; -+ char *service; -+ VSTRING *conninfo = vstring_alloc (100); -+ char *conn; -+ unsigned port = 0; -+ -+ /* -+ * Ad-hoc parsing code. Expect "unix:pathname" or "inet:host:port", where -+ * both "inet:" and ":port" are optional. -+ */ -+ if (strncmp (destination, "unix:", 5) == 0) -+ { -+ vstring_sprintf_append (conninfo, "host=%s ", destination + 5); -+ } -+ else -+ { -+ if (strncmp (destination, "inet:", 5) == 0) -+ destination += 5; -+ hostname = mystrdup (destination); -+ if ((service = split_at (hostname, ':')) != 0) -+ { -+ port = ntohs (find_inet_port (service, "tcp")); -+ vstring_sprintf_append (conninfo, "host='%s' port='%d'", -+ hostname, port); -+ } -+ else -+ { -+ vstring_sprintf_append (conninfo, "host='%s'", hostname); -+ } -+ } -+ -+ vstring_sprintf_append (conninfo, " dbname='%s' user='%s' password='%s'", dbname, -+ username, password); -+ conn = vstring_export (conninfo); -+ -+ host->db = PQconnectdb (conn); -+ -+ if ((host->db != NULL) && (PQstatus (host->db) == CONNECTION_OK)) -+ { -+ if (msg_verbose) -+ msg_info ("dict_pgsql: successful connection to host %s", -+ host->hostname); -+ host->stat = STATACTIVE; -+ } -+ else -+ { -+ msg_warn ("%s", PQerrorMessage (host->db)); -+ plpgsql_down_host (host); -+ } -+ if (hostname) -+ myfree (hostname); -+ myfree (conn); -+} -+ -+/* -+ * plpgsql_down_host - mark a HOST down update ts if marked down -+ * for the first time so that we'll know when to retry the connection -+ */ -+static void plpgsql_down_host (HOST *host) -+{ -+ if (host->stat != STATFAIL) -+ { -+ host->ts = time ((time_t *) 0) + RETRY_CONN_INTV; -+ host->stat = STATFAIL; -+ } -+ PQfinish (host->db); -+ host->db = 0; -+} -+ -+/********************************************************************** -+ * public interface dict_pgsql_open -+ * create association with database with appropriate values -+ * parse the map's config file -+ * allocate memory -+ **********************************************************************/ -+DICT *dict_pgsql_open (const char *name, int unused_open_flags, -+ int dict_flags) -+{ -+ DICT_PGSQL *dict_pgsql; -+ int connections; -+ -+ dict_pgsql = (DICT_PGSQL *) dict_alloc (DICT_TYPE_PGSQL, name, -+ sizeof (DICT_PGSQL)); -+ dict_pgsql->dict.lookup = dict_pgsql_lookup; -+ dict_pgsql->dict.close = dict_pgsql_close; -+ dict_pgsql->dict.flags = dict_flags | DICT_FLAG_FIXED; -+ dict_pgsql->name = pgsqlname_parse (name); -+ dict_pgsql->pldb = plpgsql_init (dict_pgsql->name->hostnames, -+ dict_pgsql->name->len_hosts); -+ if (dict_pgsql->pldb == NULL) -+ msg_fatal ("couldn't intialize pldb!\n"); -+ dict_register (name, (DICT *) dict_pgsql); -+ return (DICT_DEBUG (&dict_pgsql->dict)); -+} -+ -+/* pgsqlname_parse - parse pgsql configuration file */ -+static PGSQL_NAME *pgsqlname_parse (const char *pgsqlcf_path) -+{ -+ int i; -+ char *nameval; -+ char *hosts; -+ PGSQL_NAME *name = (PGSQL_NAME *) mymalloc (sizeof (PGSQL_NAME)); -+ ARGV *hosts_argv; -+ VSTRING *opt_dict_name; -+ -+ /* -+ * setup a dict containing info in the pgsql cf file. the dict has a -+ * name, and a path. The name must be distinct from the path, or the -+ * dict interface gets confused. The name must be distinct for two -+ * different paths, or the configuration info will cache across different -+ * pgsql maps, which can be confusing. -+ */ -+ opt_dict_name = vstring_alloc (64); -+ vstring_sprintf (opt_dict_name, "pgsql opt dict %s", pgsqlcf_path); -+ dict_load_file (vstring_str (opt_dict_name), pgsqlcf_path); -+ /* pgsql username lookup */ -+ if ( -+ (nameval = -+ (char *) dict_lookup (vstring_str (opt_dict_name), "user")) == NULL) -+ name->username = mystrdup (""); -+ else -+ name->username = mystrdup (nameval); -+ if (msg_verbose) -+ msg_info ("pgsqlname_parse(): set username to '%s'", name->username); -+ /* password lookup */ -+ if ( -+ (nameval = -+ (char *) dict_lookup (vstring_str (opt_dict_name), -+ "password")) == NULL) -+ name->password = mystrdup (""); -+ else -+ name->password = mystrdup (nameval); -+ if (msg_verbose) -+ msg_info ("pgsqlname_parse(): set password to '%s'", name->password); -+ -+ /* database name lookup */ -+ if ( -+ (nameval = -+ (char *) dict_lookup (vstring_str (opt_dict_name), -+ "dbname")) == NULL) -+ -+ -+ -+ msg_fatal ("%s: pgsql options file does not include database name", -+ pgsqlcf_path); -+ else -+ name->dbname = mystrdup (nameval); -+ if (msg_verbose) -+ msg_info ("pgsqlname_parse(): set database name to '%s'", -+ name->dbname); -+ -+ /* table lookup */ -+ if ( -+ (nameval = -+ (char *) dict_lookup (vstring_str (opt_dict_name), "table")) == NULL) -+ msg_fatal ("%s: pgsql options file does not include table name", -+ pgsqlcf_path); -+ else -+ name->table = mystrdup (nameval); -+ if (msg_verbose) -+ msg_info ("pgsqlname_parse(): set table name to '%s'", name->table); -+ -+ /* select field lookup */ -+ if ( -+ (nameval = -+ (char *) dict_lookup (vstring_str (opt_dict_name), -+ "select_field")) == NULL) -+ -+ -+ -+ msg_fatal ("%s: pgsql options file does not include select field", -+ pgsqlcf_path); -+ else -+ name->select_field = mystrdup (nameval); -+ if (msg_verbose) -+ msg_info ("pgsqlname_parse(): set select_field to '%s'", -+ name->select_field); -+ -+ /* where field lookup */ -+ if ( -+ (nameval = -+ (char *) dict_lookup (vstring_str (opt_dict_name), -+ "where_field")) == NULL) -+ msg_fatal ("%s: pgsql options file does not include where field", -+ pgsqlcf_path); -+ else -+ name->where_field = mystrdup (nameval); -+ if (msg_verbose) -+ msg_info ("pgsqlname_parse(): set where_field to '%s'", -+ name->where_field); -+ -+ /* additional conditions */ -+ if ( -+ (nameval = -+ (char *) dict_lookup (vstring_str (opt_dict_name), -+ "additional_conditions")) == NULL) -+ name->additional_conditions = mystrdup (""); -+ else -+ name->additional_conditions = mystrdup (nameval); -+ if (msg_verbose) -+ msg_info ("pgsqlname_parse(): set additional_conditions to '%s'", -+ name->additional_conditions); -+ -+ /* pgsql server hosts */ -+ if ( -+ (nameval = -+ (char *) dict_lookup (vstring_str (opt_dict_name), "hosts")) == NULL) -+ hosts = mystrdup (""); -+ else -+ hosts = mystrdup (nameval); -+ /* coo argv interface */ -+ hosts_argv = argv_split (hosts, " ,\t\r\n"); -+ -+ if (hosts_argv->argc == 0) -+ { /* no hosts specified, -+ * default to 'localhost' */ -+ if (msg_verbose) -+ msg_info -+ ("pgsqlname_parse(): no hostnames specified, defaulting to 'localhost'"); -+ argv_add (hosts_argv, "localhost", ARGV_END); -+ argv_terminate (hosts_argv); -+ } -+ name->len_hosts = hosts_argv->argc; -+ name->hostnames = -+ -+ (char **) mymalloc ((sizeof (char *)) * name->len_hosts); -+ i = 0; -+ for (i = 0; hosts_argv->argv[i] != NULL; i++) -+ { -+ name->hostnames[i] = mystrdup (hosts_argv->argv[i]); -+ if (msg_verbose) -+ msg_info -+ ("pgsqlname_parse(): adding host '%s' to list of pgsql server hosts", -+ name->hostnames[i]); -+ } -+ myfree (hosts); -+ vstring_free (opt_dict_name); -+ argv_free (hosts_argv); -+ return name; -+} -+ -+ -+/* -+ * plpgsql_init - initalize a PGSQL database. -+ * Return NULL on failure, or a PLPGSQL * on success. -+ */ -+static PLPGSQL *plpgsql_init (char *hostnames[], int len_hosts) -+{ -+ PLPGSQL *PLDB; -+ int i; -+ HOST host; -+ -+ if ((PLDB = (PLPGSQL *) mymalloc (sizeof (PLPGSQL))) == NULL) -+ { -+ msg_fatal ("mymalloc of pldb failed"); -+ } -+ PLDB->len_hosts = len_hosts; -+ if ((PLDB->db_hosts = (HOST *) mymalloc (sizeof (HOST) * len_hosts)) -+ == NULL) -+ return NULL; -+ -+ for (i = 0; i < len_hosts; i++) -+ { -+ PLDB->db_hosts[i] = host_init (hostnames[i]); -+ } -+ return PLDB; -+} -+ -+ -+/* host_init - initialize HOST structure */ -+static HOST host_init (char *hostname) -+{ -+ HOST host; -+ -+ host.stat = STATUNTRIED; -+ host.hostname = mystrdup (hostname); -+ host.db = 0; -+ host.ts = 0; -+ return host; -+} -+ -+/********************************************************************** -+ * public interface dict_pgsql_close -+ * unregister, disassociate from database, freeing appropriate memory -+ **********************************************************************/ -+static void dict_pgsql_close (DICT *dict) -+{ -+ int i; -+ DICT_PGSQL *dict_pgsql = (DICT_PGSQL *) dict; -+ -+ plpgsql_dealloc (dict_pgsql->pldb); -+ myfree (dict_pgsql->name->username); -+ myfree (dict_pgsql->name->password); -+ myfree (dict_pgsql->name->dbname); -+ myfree (dict_pgsql->name->table); -+ myfree (dict_pgsql->name->select_field); -+ myfree (dict_pgsql->name->where_field); -+ myfree (dict_pgsql->name->additional_conditions); -+ for (i = 0; i < dict_pgsql->name->len_hosts; i++) -+ { -+ myfree (dict_pgsql->name->hostnames[i]); -+ } -+ myfree ((char *) dict_pgsql->name->hostnames); -+ myfree ((char *) dict_pgsql->name); -+ dict_free (dict); -+} -+ -+/* plpgsql_dealloc - free memory associated with PLPGSQL close databases */ -+static void plpgsql_dealloc (PLPGSQL * PLDB) -+{ -+ int i; -+ -+ for (i = 0; i < PLDB->len_hosts; i++) -+ { -+ if (PLDB->db_hosts[i].db) -+ PQfinish (PLDB->db_hosts[i].db); -+ myfree (PLDB->db_hosts[i].hostname); -+ } -+ myfree ((char *) PLDB->db_hosts); -+ myfree ((char *) (PLDB)); -+} -+ -+/* pgsql_escape_string - replace mysql_escape_string */ -+void pgsql_escape_string (char *escaped, const char *name, int len) -+{ -+ int i, -+ j; -+ -+ for (i = 0, j = 0; i <= len; i++, j++) -+ { -+ if ((name[i] == '\'') || (name[i] == '\\')) -+ { -+ escaped[j] = '\\'; -+ j++; -+ } -+ escaped[j] = name[i]; -+ } -+} -+ -+ -+ -+#endif -+ ---- postfix-2.0.16.orig/src/util/dict_pgsql.h 1970-01-01 01:00:00.000000000 +0100 -+++ postfix-2.0.16/src/util/dict_pgsql.h 2003-11-08 20:11:44.000000000 +0100 -@@ -0,0 +1,41 @@ -+#ifndef _DICT_PGSQL_H_INCLUDED_ -+#define _DICT_PGSQL_H_INCLUDED_ -+ -+/*++ -+/* NAME -+/* dict_pgsql 3h -+/* SUMMARY -+/* dictionary manager interface to pgsql databases -+/* SYNOPSIS -+/* #include -+/* DESCRIPTION -+/* .nf -+ -+ /* -+ * Utility library. -+ */ -+#include -+ -+ /* -+ * External interface. -+ */ -+#define DICT_TYPE_PGSQL "pgsql" -+ -+extern DICT *dict_pgsql_open (const char *, int, int); -+ -+/* LICENSE -+/* .ad -+/* .fi -+/* The Secure Mailer license must be distributed with this software. -+/* AUTHOR(S) -+/* Scott Cotton -+/* IC Group, Inc. -+/* scott@icgroup.com -+/* -+/* Joshua Marcus -+/* IC Group, Inc. -+/* josh@icgroup.com -+/*--*/ -+ -+#endif -+ ---- postfix-2.0.16.orig/src/util/Makefile.in 2003-11-08 20:10:08.000000000 +0100 -+++ postfix-2.0.16/src/util/Makefile.in 2003-11-08 20:12:29.000000000 +0100 -@@ -4,7 +4,7 @@ - chroot_uid.c clean_env.c close_on_exec.c concatenate.c ctable.c \ - dict.c dict_alloc.c dict_db.c dict_dbm.c dict_debug.c dict_env.c \ - dict_ht.c dict_mysql.c dict_ni.c dict_nis.c \ -- dict_nisplus.c dict_open.c dict_pcre.c dict_regexp.c dict_static.c \ -+ dict_nisplus.c dict_open.c dict_pcre.c dict_pgsql.c dict_regexp.c dict_static.c \ - dict_tcp.c dict_unix.c dir_forest.c doze.c duplex_pipe.c \ - environ.c events.c exec_command.c fifo_listen.c fifo_trigger.c \ - file_limit.c find_inet.c fsspace.c fullname.c get_domainname.c \ -@@ -60,7 +60,7 @@ - HDRS = argv.h attr.h base64_code.h binhash.h chroot_uid.h clean_env.h \ - connect.h ctable.h dict.h dict_db.h dict_dbm.h dict_env.h \ - dict_ht.h dict_ldap.h dict_mysql.h dict_ni.h dict_nis.h \ -- dict_nisplus.h dict_pcre.h dict_regexp.h dict_static.h dict_tcp.h \ -+ dict_nisplus.h dict_pcre.h dict_pgsql.h dict_regexp.h dict_static.h dict_tcp.h \ - dict_unix.h dir_forest.h events.h exec_command.h find_inet.h \ - fsspace.h fullname.h get_domainname.h get_hostname.h hex_quote.h \ - htable.h inet_addr_host.h inet_addr_list.h inet_addr_local.h \ -@@ -86,6 +86,7 @@ - INCL = - PCRESO = dict_pcre.so - MYSQLSO = dict_mysql.so -+PGSQLSO = dict_pgsql.so - LIB = libutil.a - TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \ - fifo_rdonly_bug fifo_rdwr_bug fifo_trigger fsspace fullname \ -@@ -98,7 +99,7 @@ - - LIB_DIR = ../../lib - INC_DIR = ../../include --LIBS = $(LIB_DIR)/$(LIB) $(LIB_DIR)/$(PCRESO) $(LIB_DIR)/$(MYSQLSO) -+LIBS = $(LIB_DIR)/$(LIB) $(LIB_DIR)/$(PCRESO) $(LIB_DIR)/$(MYSQLSO) $(LIB_DIR)/$(PGSQLSO) - - .c.o:; $(CC) -fPIC $(CFLAGS) -c $*.c - -@@ -115,6 +116,9 @@ - $(MYSQLSO): dict_mysql.o - gcc -shared -Wl,-soname,dict_mysql.so -o $@ $? -lmysqlclient -L. -lutil - -+$(PGSQLSO): dict_pgsql.o -+ gcc -shared -Wl,-soname,dict_pgsql.so -o $@ $? -lpq -lcrypt -L. -lutil -+ - $(LIB): $(OBJS) - gcc -shared -Wl,-soname,libpostfix-util.so.1 -o $(LIB) $(OBJS) -ldl - -@@ -127,6 +131,9 @@ - $(LIB_DIR)/$(MYSQLSO): $(MYSQLSO) - cp $(MYSQLSO) $(LIB_DIR) - -+$(LIB_DIR)/$(PGSQLSO): $(PGSQLSO) -+ cp $(PGSQLSO) $(LIB_DIR) -+ - update: $(LIBS) $(HDRS) - -for i in $(HDRS); \ - do \ -@@ -149,7 +156,7 @@ - lint $(SRCS) - - clean: -- rm -f *.o $(LIB) $(PCRESO) $(MYSQLSO) *core $(TESTPROG) \ -+ rm -f *.o $(LIB) $(PCRESO) $(MYSQLSO) $(PGSQLSO) *core $(TESTPROG) \ - junk $(MAKES) *.tmp - rm -rf printfck - -@@ -591,6 +598,8 @@ - dict_ldap.o: sys_defs.h - dict_mysql.o: dict_mysql.c - dict_mysql.o: sys_defs.h -+dict_pgsql.o: dict_pgsql.c -+dict_pgsql.o: sys_defs.h - dict_ni.o: dict_ni.c - dict_ni.o: sys_defs.h - dict_nis.o: dict_nis.c -@@ -632,6 +641,7 @@ - dict_open.o: dict_ni.h - dict_open.o: dict_ldap.h - dict_open.o: dict_mysql.h -+dict_open.o: dict_pgsql.h - dict_open.o: dict_pcre.h - dict_open.o: dict_regexp.h - dict_open.o: dict_static.h diff --git a/postfix-pl.patch b/postfix-pl.patch deleted file mode 100644 index 50a1448..0000000 --- a/postfix-pl.patch +++ /dev/null @@ -1,386 +0,0 @@ -diff -Nur postfix-1.1.2.orig/src/bounce/bounce_notify_util.c postfix-1.1.2/src/bounce/bounce_notify_util.c ---- postfix-1.1.2.orig/src/bounce/bounce_notify_util.c Mon Nov 26 22:47:05 2001 -+++ postfix-1.1.2/src/bounce/bounce_notify_util.c Mon Jan 28 12:33:52 2002 -@@ -275,7 +275,7 @@ - post_mail_fputs(bounce, dest == var_bounce_rcpt - || dest == var_2bounce_rcpt || dest == var_delay_rcpt ? - "Subject: Postmaster Copy: Undelivered Mail" : -- "Subject: Undelivered Mail Returned to Sender"); -+ "Subject: Zwrot niedostarczonej poczty / Undelivered Mail Returned to Sender"); - } - - /* -@@ -285,7 +285,7 @@ - post_mail_fputs(bounce, dest == var_bounce_rcpt - || dest == var_2bounce_rcpt || dest == var_delay_rcpt ? - "Subject: Postmaster Warning: Delayed Mail" : -- "Subject: Delayed Mail (still being retried)"); -+ "Subject: Opoznienie wyslania / Delayed Mail (still being retried)"); - } - post_mail_fprintf(bounce, "To: %s", - STR(quote_822_local(bounce_info->buf, dest))); -@@ -300,15 +300,6 @@ - post_mail_fputs(bounce, ""); - post_mail_fputs(bounce, "This is a MIME-encapsulated message."); - -- /* -- * MIME header. -- */ -- post_mail_fputs(bounce, ""); -- post_mail_fprintf(bounce, "--%s", bounce_info->mime_boundary); -- post_mail_fprintf(bounce, "Content-Description: %s", "Notification"); -- post_mail_fprintf(bounce, "Content-Type: %s", "text/plain"); -- post_mail_fputs(bounce, ""); -- - return (vstream_ferror(bounce)); - } - -@@ -324,6 +315,73 @@ - * word wrapping to make the text look nicer. No matter how hard we would - * try, receiving bounced mail will always suck. - */ -+ -+ -+ /* teraz po polsku */ -+ post_mail_fputs(bounce, ""); -+ post_mail_fprintf(bounce, "--%s", bounce_info->mime_boundary); -+ post_mail_fprintf(bounce, "Content-Description: %s", "Informacja"); -+ post_mail_fprintf(bounce, "Content-Type: %s", "text/plain; charset=iso-8859-2"); -+ post_mail_fprintf(bounce, "Content-Transfer-Encoding: %s", "8bit"); -+ post_mail_fputs(bounce, ""); -+ -+ post_mail_fprintf(bounce, "Informacja od systemu pocztowego %s.", -+ var_myhostname); -+ post_mail_fputs(bounce, ""); -+ if (bounce_info->flush) { -+ post_mail_fputs(bounce, -+ "Twój list nie móg³ byæ dostarczony do jednego"); -+ post_mail_fputs(bounce, -+ "lub wiêkszej liczby odbiorców."); -+ } else { -+ post_mail_fputs(bounce, -+ "########################################################################"); -+ post_mail_fputs(bounce, -+ "# TO JEST TYLKO OSTRZE¯ENIE. NIE MUSISZ PONOWNIE WYSY£AÆ SWOJEGO LISTU #"); -+ post_mail_fputs(bounce, -+ "########################################################################"); -+ post_mail_fputs(bounce, ""); -+ post_mail_fprintf(bounce, -+ "Twój list nie móg³ byæ dostarczony przez %.1f godzin.", -+ var_delay_warn_time); -+ post_mail_fprintf(bounce, -+ "Bêd± podejmowane próby wys³ania jeszcze przez %.1f dni.", -+ var_max_queue_time); -+ } -+ -+ post_mail_fputs(bounce, ""); -+ -+ /* FIXME */ -+#if 0 -+ post_mail_fprintf(bounce, -+ "For further assistance, please contact <%s>", -+ STR(canon_addr_external(buf, MAIL_ADDR_POSTMASTER))); -+ if (flush) { -+ post_mail_fputs(bounce, ""); -+ post_mail_fprintf(bounce, -+ "If you do so, please include this problem report. You can"); -+ post_mail_fprintf(bounce, -+ "delete your own text from the message returned below."); -+ post_mail_fprintf(bounce, -+ "If you do so, please include this problem report. You can"); -+ post_mail_fprintf(bounce, -+ "delete your own text from the message returned below."); -+ } -+ /* FIXME */ -+ post_mail_fputs(bounce, ""); -+ post_mail_fprintf(bounce, "\t\t\tProgram %s", var_mail_name); -+ post_mail_fputs(bounce, ""); -+#endif -+ -+ /* -+ * MIME header. -+ */ -+ post_mail_fputs(bounce, ""); -+ post_mail_fprintf(bounce, "--%s", bounce_info->mime_boundary); -+ post_mail_fprintf(bounce, "Content-Description: %s", "Notification"); -+ post_mail_fprintf(bounce, "Content-Type: %s", "text/plain"); -+ post_mail_fputs(bounce, ""); -+ - post_mail_fprintf(bounce, "This is the %s program at host %s.", - var_mail_name, var_myhostname); - post_mail_fputs(bounce, ""); -@@ -347,7 +405,7 @@ - "It will be retried until it is %.1f days old.", - var_max_queue_time / 86400.0); - } -- -+#if 0 - post_mail_fputs(bounce, ""); - post_mail_fprintf(bounce, - "For further assistance, please send mail to <%s>", -@@ -359,6 +417,7 @@ - post_mail_fprintf(bounce, - "delete your own text from the message returned below."); - } -+#endif - post_mail_fputs(bounce, ""); - post_mail_fprintf(bounce, "\t\t\tThe %s program", var_mail_name); - return (vstream_ferror(bounce)); -@@ -420,6 +479,7 @@ - if (bounce_info->log_handle == 0 - || bounce_log_rewind(bounce_info->log_handle)) { - post_mail_fputs(bounce, "\t--- Delivery error report unavailable ---"); -+ post_mail_fputs(bounce, "\t--- Raport dostarczenia niedostepny ---"); - } else { - while (bounce_log_read(bounce_info->log_handle) != 0) - if (bounce_recipient_log(bounce, bounce_info) != 0) -@@ -440,7 +500,8 @@ - post_mail_fprintf(bounce, "--%s", bounce_info->mime_boundary); - post_mail_fprintf(bounce, "Content-Description: %s", - "Delivery error report"); -- post_mail_fprintf(bounce, "Content-Type: %s", "message/delivery-status"); -+ post_mail_fprintf(bounce, "Content-Type: %s", "message/delivery-status; charset=iso-8859-2"); -+ post_mail_fprintf(bounce, "Content-Transfer-Encoding: %s", "8bit"); - - /* - * According to RFC 1894: The body of a message/delivery-status consists -@@ -529,6 +590,7 @@ - if (bounce_info->orig_offs == 0 || vstream_fseek(bounce_info->orig_fp, - bounce_info->orig_offs, SEEK_SET) < 0) { - post_mail_fputs(bounce, "\t--- Undelivered message unavailable ---"); -+ post_mail_fputs(bounce, "\t--- Niedostepna kopia niedostarczonego listu ---"); - return (vstream_ferror(bounce)); - } - -diff -Nur postfix-1.1.2.orig/src/global/pipe_command.c postfix-1.1.2/src/global/pipe_command.c ---- postfix-1.1.2.orig/src/global/pipe_command.c Tue Nov 27 02:02:17 2001 -+++ postfix-1.1.2/src/global/pipe_command.c Mon Jan 28 12:33:52 2002 -@@ -482,9 +482,9 @@ - if (pipe_command_wait_or_kill(pid, &wait_status, SIGKILL) < 0) - msg_fatal("wait: %m"); - if (pipe_command_timeout) { -- vstring_sprintf(why, "Command time limit exceeded: \"%s\"%s%s", -+ vstring_sprintf(why, "Przekroczony czas wykonania polecania / Command time limit exceeded: \"%s\"%s%s", - args.command, -- log_len ? ". Command output: " : "", log_buf); -+ log_len ? ". Wyniki polecenia / Command output: " : "", log_buf); - return (PIPE_STAT_BOUNCE); - } - -@@ -494,28 +494,28 @@ - */ - if (!NORMAL_EXIT_STATUS(wait_status)) { - if (WIFSIGNALED(wait_status)) { -- vstring_sprintf(why, "Command died with signal %d: \"%s\"%s%s", -+ vstring_sprintf(why, "Polecenia zakonczone blendem / Command died with signal %d: \"%s\"%s%s", - WTERMSIG(wait_status), - args.command, -- log_len ? ". Command output: " : "", log_buf); -+ log_len ? ". Wynik polecenia / Command output: " : "", log_buf); - return (PIPE_STAT_DEFER); - } else if (SYS_EXITS_CODE(WEXITSTATUS(wait_status))) { - vstring_sprintf(why, "%s%s%s", - sys_exits_strerror(WEXITSTATUS(wait_status)), -- log_len ? ". Command output: " : "", log_buf); -+ log_len ? ". Wynik polecenia / Command output: " : "", log_buf); - return (sys_exits_softerror(WEXITSTATUS(wait_status)) ? - PIPE_STAT_DEFER : PIPE_STAT_BOUNCE); - } else { -- vstring_sprintf(why, "Command died with status %d: \"%s\"%s%s", -+ vstring_sprintf(why, "Polecenie zakonczone bledem / Command died with status %d: \"%s\"%s%s", - WEXITSTATUS(wait_status), - args.command, -- log_len ? ". Command output: " : "", log_buf); -+ log_len ? ". Wynik polecenia / Command output: " : "", log_buf); - return (PIPE_STAT_BOUNCE); - } - } else if (write_status & MAIL_COPY_STAT_CORRUPT) { - return (PIPE_STAT_CORRUPT); - } else if (write_status && errno != EPIPE) { -- vstring_sprintf(why, "Command failed: %m: \"%s\"", args.command); -+ vstring_sprintf(why, "Polecenie niepowiodlo sie / Command failed: %m: \"%s\"", args.command); - return (PIPE_STAT_DEFER); - } else { - return (PIPE_STAT_OK); -diff -Nur postfix-1.1.2.orig/src/global/sys_exits.c postfix-1.1.2/src/global/sys_exits.c ---- postfix-1.1.2.orig/src/global/sys_exits.c Fri Dec 11 19:55:25 1998 -+++ postfix-1.1.2/src/global/sys_exits.c Mon Jan 28 12:33:52 2002 -@@ -60,21 +60,21 @@ - } SYS_EXITS_TABLE; - - static SYS_EXITS_TABLE sys_exits_table[] = { -- 0, EX_USAGE, "command line usage error", -- 0, EX_DATAERR, "data format error", -+ 0, EX_USAGE, "bledne wywylanie polecanie / command line usage error", -+ 0, EX_DATAERR, "blad formatu danych / data format error", - 0, EX_NOINPUT, "cannot open input", -- 0, EX_NOUSER, "user unknown", -+ 0, EX_NOUSER, "nieznany uzytkownik / user unknown", - 0, EX_NOHOST, "host name unknown", -- 0, EX_UNAVAILABLE, "service unavailable", -- 0, EX_SOFTWARE, "internal software error", -+ 0, EX_UNAVAILABLE, "niedostepny serwis / service unavailable", -+ 0, EX_SOFTWARE, "wewnetrzny blad oprogramowania / internal software error", - 1, EX_OSERR, "system resource problem", - 0, EX_OSFILE, "critical OS file missing", - 0, EX_CANTCREAT, "can't create user output file", - 0, EX_IOERR, "input/output error", -- 1, EX_TEMPFAIL, "temporary failure", -+ 1, EX_TEMPFAIL, "chwilowe niepowodzenie / temporary failure", - 0, EX_PROTOCOL, "remote error in protocol", -- 0, EX_NOPERM, "permission denied", -- 0, EX_CONFIG, "local configuration error", -+ 0, EX_NOPERM, "brak dostêpu / permission denied", -+ 0, EX_CONFIG, "blad lokalnej konfiguracji / local configuration error", - }; - - /* sys_exits_strerror - map exit status to error string */ - ---- postfix-2.0.10/src/smtpd/smtpd_check.c.orig Sun Jun 1 12:38:56 2003 -+++ postfix-2.0.10/src/smtpd/smtpd_check.c Sun Jun 1 12:57:27 2003 -@@ -988,7 +988,7 @@ - */ - if (!valid_hostaddr(test_addr, DONT_GRIPE)) - stat = smtpd_check_reject(state, MAIL_ERROR_POLICY, -- "%d <%s>: %s rejected: invalid ip address", -+ "%d <%s>: %s odrzucony/rejected: niepoprawny adres IP/invalid IP address", - var_bad_name_code, reply_name, reply_class); - else - stat = SMTPD_CHECK_DUNNO; -@@ -1024,7 +1024,7 @@ - */ - if (!valid_hostname(test_name, DONT_GRIPE)) - stat = smtpd_check_reject(state, MAIL_ERROR_POLICY, -- "%d <%s>: %s rejected: Invalid name", -+ "%d <%s>: %s odrzucony/rejected: Niepoprawna nazwa / Invalid name", - var_bad_name_code, reply_name, reply_class); - else - stat = SMTPD_CHECK_DUNNO; -@@ -1060,7 +1060,7 @@ - */ - if (!valid_hostname(test_name, DONT_GRIPE) || !strchr(test_name, '.')) - stat = smtpd_check_reject(state, MAIL_ERROR_POLICY, -- "%d <%s>: %s rejected: need fully-qualified hostname", -+ "%d <%s>: %s odrzucowny/rejected: need fully-qualified hostname", - var_non_fqdn_code, reply_name, reply_class); - else - stat = SMTPD_CHECK_DUNNO; -@@ -1095,7 +1095,7 @@ - (VSTRING *) 0, RR_ADDR_TYPES, T_MX, 0); - if (dns_status == DNS_NOTFOUND) - return (smtpd_check_reject(state, MAIL_ERROR_POLICY, -- "%d <%s>: %s rejected: Host not found", -+ "%d <%s>: %s odrzucony/rejected: Host not found", - var_unk_name_code, - reply_name, reply_class)); - else if (dns_status != DNS_OK) -@@ -1120,7 +1120,7 @@ - (VSTRING *) 0, RR_ADDR_TYPES, T_MX, 0); - if (dns_status == DNS_NOTFOUND) - return (smtpd_check_reject(state, MAIL_ERROR_POLICY, -- "%d <%s>: %s rejected: Domain not found", -+ "%d <%s>: %s odrzucony/rejected: Domain not found", - var_unk_addr_code, - reply_name, reply_class)); - else if (dns_status != DNS_OK) -@@ -1201,7 +1201,8 @@ - vstring_strcat(reply_msg, "%d <%s>: %s "); - vstring_strcat(reply_msg, var_reject_reply_msg_access_denied); - return (smtpd_check_reject(state, MAIL_ERROR_POLICY, -- vstring_export(reply_msg), var_relay_code, reply_name, reply_class)); -+ "%d <%s>: %s odrzucony/rejected: Relay access denied", -+ var_relay_code, reply_name, reply_class)); - } - - /* permit_auth_destination - OK for message relaying */ -@@ -1650,7 +1651,7 @@ - */ - if (!*test_dom || !valid_hostname(test_dom, DONT_GRIPE) || !strchr(test_dom, '.')) - stat = smtpd_check_reject(state, MAIL_ERROR_POLICY, -- "%d <%s>: %s rejected: need fully-qualified address", -+ "%d <%s>: %s odrzucony/rejected: need fully-qualified address", - var_non_fqdn_code, reply_name, reply_class); - else - stat = SMTPD_CHECK_DUNNO; -@@ -1766,9 +1767,9 @@ - */ - if (STREQUAL(value, "REJECT", cmd_len)) { - return (smtpd_check_reject(state, MAIL_ERROR_POLICY, -- "%d <%s>: %s rejected: %s", -+ "%d <%s>: %s odrzucony/rejected: %s", - var_access_map_code, reply_name, reply_class, -- *cmd_text ? cmd_text : "Access denied")); -+ *cmd_text ? cmd_text : "Brak dostepu / Access denied")); - } - - /* -@@ -1858,7 +1859,7 @@ - && ISDIGIT(value[0]) && ISDIGIT(value[1]) && ISDIGIT(value[2])) { - code = atoi(value); - return (smtpd_check_reject(state, MAIL_ERROR_POLICY, -- "%d <%s>: %s rejected: %s", -+ "%d <%s>: %s odrzucony/rejected: %s", - code, reply_name, reply_class, cmd_text)); - } - -@@ -2743,14 +2744,14 @@ - cpp[1], PERMIT_ALL); - } else if (strcasecmp(name, DEFER_ALL) == 0) { - status = smtpd_check_reject(state, MAIL_ERROR_POLICY, -- "%d <%s>: %s rejected: Try again later", -+ "%d <%s>: %s odrzucony/rejected: Sprobuj pozniej / Try again later", - var_defer_code, reply_name, reply_class); - if (cpp[1] != 0 && state->warn_if_reject == 0) - msg_warn("restriction `%s' after `%s' is ignored", - cpp[1], DEFER_ALL); - } else if (strcasecmp(name, REJECT_ALL) == 0) { - status = smtpd_check_reject(state, MAIL_ERROR_POLICY, -- "%d <%s>: %s rejected: Access denied", -+ "%d <%s>: %s odrzucony/rejected: Brak dostepu / Access denied", - var_reject_code, reply_name, reply_class); - if (cpp[1] != 0 && state->warn_if_reject == 0) - msg_warn("restriction `%s' after `%s' is ignored", -@@ -3356,10 +3357,10 @@ - strlen(MAIL_ADDR_MAIL_DAEMON)) - && NOMATCH(local_rcpt_maps, CONST_STR(reply->recipient))) - return (smtpd_check_reject(state, MAIL_ERROR_BOUNCE, -- "%d <%s>: User unknown%s", -+ "%d <%s>: Nieznany uzytkownik / User unknown%s", - var_local_rcpt_code, recipient, - var_show_unk_rcpt_table ? -- " in local recipient table" : "")); -+ " in local recipient table" : "")); - - /* - * Reject mail to unknown addresses in virtual mailbox domains. -@@ -3368,10 +3369,10 @@ - && *var_virt_mailbox_maps - && NOMATCHV8(virt_mailbox_maps, CONST_STR(reply->recipient))) - return (smtpd_check_reject(state, MAIL_ERROR_BOUNCE, -- "%d <%s>: User unknown%s", -+ "%d <%s>: Nieznany uzytkownik / User unknown%s", - var_virt_mailbox_code, recipient, - var_show_unk_rcpt_table ? -- " in virtual mailbox table" : "")); -+ " in virtual mailbox table" : "")); - - /* - * Reject mail to unknown addresses in relay domains. -@@ -3380,7 +3381,7 @@ - && *var_relay_rcpt_maps - && NOMATCH(relay_rcpt_maps, CONST_STR(reply->recipient))) - return (smtpd_check_reject(state, MAIL_ERROR_BOUNCE, -- "%d <%s>: User unknown%s", -+ "%d <%s>: Nieznany uzytkownik / User unknown%s", - var_relay_rcpt_code, recipient, - var_show_unk_rcpt_table ? - " in relay recipient table" : "")); -@@ -3415,7 +3416,7 @@ - - if (var_message_limit > 0 && size > var_message_limit) { - (void) smtpd_check_reject(state, MAIL_ERROR_POLICY, -- "552 Message size exceeds fixed limit"); -+ "552 Przekroczony rozmiar wiadomosci / Message size exceeds fixed limit"); - return (STR(error_text)); - } - fsspace(".", &fsbuf); diff --git a/postfix-sasl2.patch b/postfix-sasl2.patch deleted file mode 100644 index 4b745d4..0000000 --- a/postfix-sasl2.patch +++ /dev/null @@ -1,298 +0,0 @@ -diff -durN postfix-1.1.11.orig/src/lmtp/lmtp.h postfix-1.1.11/src/lmtp/lmtp.h ---- postfix-1.1.11.orig/src/lmtp/lmtp.h Tue May 22 20:37:14 2001 -+++ postfix-1.1.11/src/lmtp/lmtp.h Mon Jan 13 12:27:52 2003 -@@ -12,8 +12,8 @@ - * SASL library. - */ - #ifdef USE_SASL_AUTH --#include --#include -+#include -+#include - #endif - - /* -diff -durN postfix-1.1.11.orig/src/lmtp/lmtp_sasl_glue.c postfix-1.1.11/src/lmtp/lmtp_sasl_glue.c ---- postfix-1.1.11.orig/src/lmtp/lmtp_sasl_glue.c Fri Jan 19 22:46:44 2001 -+++ postfix-1.1.11/src/lmtp/lmtp_sasl_glue.c Mon Jan 13 12:31:32 2003 -@@ -138,10 +138,10 @@ - { - switch (priority) { - case SASL_LOG_ERR: -- case SASL_LOG_WARNING: -+ case SASL_LOG_WARN: - msg_warn("%s", message); - break; -- case SASL_LOG_INFO: -+ case SASL_LOG_NOTE: - if (msg_verbose) - msg_info("%s", message); - break; -@@ -318,6 +318,7 @@ - for (cp = state->sasl_callbacks; cp->id != SASL_CB_LIST_END; cp++) - cp->context = (void *) state; - if (sasl_client_new("smtp", state->session->host, -+ NULL, NULL, - state->sasl_callbacks, NULL_SECFLAGS, - (sasl_conn_t **) &state->sasl_conn) != SASL_OK) - msg_fatal("per-session SASL client initialization"); -@@ -354,7 +355,7 @@ - char *myname = "lmtp_sasl_authenticate"; - unsigned enc_length; - unsigned enc_length_out; -- char *clientout; -+ const char *clientout; - unsigned clientoutlen; - unsigned serverinlen; - LMTP_RESP *resp; -@@ -376,7 +377,7 @@ - */ - result = sasl_client_start((sasl_conn_t *) state->sasl_conn, - state->sasl_mechanism_list, -- NO_SASL_SECRET, NO_SASL_INTERACTION, -+ NO_SASL_INTERACTION, - &clientout, &clientoutlen, &mechanism); - if (result != SASL_OK && result != SASL_CONTINUE) { - vstring_sprintf(why, "cannot SASL authenticate to server %s: %s", -@@ -404,7 +405,6 @@ - STR(state->sasl_encoded), enc_length, - &enc_length_out) != SASL_OK) - msg_panic("%s: sasl_encode64 botch", myname); -- free(clientout); - lmtp_chat_cmd(state, "AUTH %s %s", mechanism, STR(state->sasl_encoded)); - } else { - lmtp_chat_cmd(state, "AUTH %s", mechanism); -@@ -424,7 +424,7 @@ - serverinlen = strlen(line); - VSTRING_SPACE(state->sasl_decoded, serverinlen); - if (sasl_decode64(line, serverinlen, -- STR(state->sasl_decoded), &enc_length) != SASL_OK) { -+ STR(state->sasl_decoded), serverinlen, &enc_length) != SASL_OK) { - vstring_sprintf(why, "malformed SASL challenge from server %s", - state->session->namaddr); - return (-1); -@@ -456,7 +456,6 @@ - STR(state->sasl_encoded), enc_length, - &enc_length_out) != SASL_OK) - msg_panic("%s: sasl_encode64 botch", myname); -- free(clientout); - } else { - vstring_strcat(state->sasl_encoded, ""); - } -diff -durN postfix-1.1.11.orig/src/smtp/smtp.h postfix-1.1.11/src/smtp/smtp.h ---- postfix-1.1.11.orig/src/smtp/smtp.h Mon Jan 13 12:33:43 2003 -+++ postfix-1.1.11/src/smtp/smtp.h Mon Jan 13 12:10:16 2003 -@@ -12,8 +12,8 @@ - * SASL library. - */ - #ifdef USE_SASL_AUTH --#include --#include -+#include -+#include - #endif - - /* -diff -durN postfix-1.1.11.orig/src/smtp/smtp_sasl_glue.c postfix-1.1.11/src/smtp/smtp_sasl_glue.c ---- postfix-1.1.11.orig/src/smtp/smtp_sasl_glue.c Mon Jul 2 21:12:54 2001 -+++ postfix-1.1.11/src/smtp/smtp_sasl_glue.c Mon Jan 13 12:17:57 2003 -@@ -138,10 +138,10 @@ - { - switch (priority) { - case SASL_LOG_ERR: -- case SASL_LOG_WARNING: -+ case SASL_LOG_WARN: - msg_warn("SASL authentication problem: %s", message); - break; -- case SASL_LOG_INFO: -+ case SASL_LOG_NOTE: - if (msg_verbose) - msg_info("SASL authentication info: %s", message); - break; -@@ -317,9 +317,10 @@ - memcpy((char *) state->sasl_callbacks, callbacks, sizeof(callbacks)); - for (cp = state->sasl_callbacks; cp->id != SASL_CB_LIST_END; cp++) - cp->context = (void *) state; -- if (sasl_client_new("smtp", state->session->host, -+ if (sasl_client_new("smtp", state->session->host, NULL, NULL, - state->sasl_callbacks, NULL_SECFLAGS, - (sasl_conn_t **) &state->sasl_conn) != SASL_OK) -+ - msg_fatal("per-session SASL client initialization"); - - /* -@@ -354,7 +355,7 @@ - char *myname = "smtp_sasl_authenticate"; - unsigned enc_length; - unsigned enc_length_out; -- char *clientout; -+ const char *clientout; - unsigned clientoutlen; - unsigned serverinlen; - SMTP_RESP *resp; -@@ -362,8 +363,7 @@ - int result; - char *line; - --#define NO_SASL_SECRET 0 --#define NO_SASL_INTERACTION 0 -+#define NO_SASL_INTERACTION NULL - #define NO_SASL_LANGLIST ((const char *) 0) - #define NO_SASL_OUTLANG ((const char **) 0) - -@@ -376,7 +376,7 @@ - */ - result = sasl_client_start((sasl_conn_t *) state->sasl_conn, - state->sasl_mechanism_list, -- NO_SASL_SECRET, NO_SASL_INTERACTION, -+ NO_SASL_INTERACTION, - &clientout, &clientoutlen, &mechanism); - if (result != SASL_OK && result != SASL_CONTINUE) { - vstring_sprintf(why, "cannot SASL authenticate to server %s: %s", -@@ -404,7 +404,6 @@ - STR(state->sasl_encoded), enc_length, - &enc_length_out) != SASL_OK) - msg_panic("%s: sasl_encode64 botch", myname); -- free(clientout); - smtp_chat_cmd(state, "AUTH %s %s", mechanism, STR(state->sasl_encoded)); - } else { - smtp_chat_cmd(state, "AUTH %s", mechanism); -@@ -424,7 +423,7 @@ - serverinlen = strlen(line); - VSTRING_SPACE(state->sasl_decoded, serverinlen); - if (sasl_decode64(line, serverinlen, -- STR(state->sasl_decoded), &enc_length) != SASL_OK) { -+ STR(state->sasl_decoded), serverinlen, &enc_length) != SASL_OK) { - vstring_sprintf(why, "malformed SASL challenge from server %s", - state->session->namaddr); - return (-1); -diff -durN postfix-1.1.11.orig/src/smtpd/smtpd.h postfix-1.1.11/src/smtpd/smtpd.h ---- postfix-1.1.11.orig/src/smtpd/smtpd.h Mon Jan 13 12:33:43 2003 -+++ postfix-1.1.11/src/smtpd/smtpd.h Mon Jan 13 12:26:29 2003 -@@ -17,8 +17,8 @@ - * SASL library. - */ - #ifdef USE_SASL_AUTH --#include --#include -+#include -+#include - #endif - - /* -@@ -69,7 +69,7 @@ - off_t msg_size; - int junk_cmds; - #ifdef USE_SASL_AUTH -- char *sasl_mechanism_list; -+ const char *sasl_mechanism_list; - char *sasl_method; - char *sasl_username; - char *sasl_sender; -diff -durN postfix-1.1.11.orig/src/smtpd/smtpd_sasl_glue.c postfix-1.1.11/src/smtpd/smtpd_sasl_glue.c ---- postfix-1.1.11.orig/src/smtpd/smtpd_sasl_glue.c Mon Nov 26 01:14:01 2001 -+++ postfix-1.1.11/src/smtpd/smtpd_sasl_glue.c Mon Jan 13 12:27:15 2003 -@@ -117,10 +117,10 @@ - { - switch (priority) { - case SASL_LOG_ERR: -- case SASL_LOG_WARNING: -+ case SASL_LOG_WARN: - msg_warn("SASL authentication problem: %s", message); - break; -- case SASL_LOG_INFO: -+ case SASL_LOG_NOTE: - if (msg_verbose) - msg_info("SASL authentication info: %s", message); - break; -@@ -196,6 +196,7 @@ - #define NO_SESSION_CALLBACKS ((sasl_callback_t *) 0) - - if (sasl_server_new("smtp", var_myhostname, var_smtpd_sasl_realm, -+ NULL, NULL, - NO_SESSION_CALLBACKS, NO_SECURITY_LAYERS, - &state->sasl_conn) != SASL_OK) - msg_fatal("SASL per-connection server initialization"); -@@ -238,10 +239,6 @@ - - void smtpd_sasl_disconnect(SMTPD_STATE *state) - { -- if (state->sasl_mechanism_list) { -- free(state->sasl_mechanism_list); -- state->sasl_mechanism_list = 0; -- } - if (state->sasl_conn) { - sasl_dispose(&state->sasl_conn); - state->sasl_conn = 0; -@@ -262,10 +259,9 @@ - unsigned enc_length; - unsigned enc_length_out; - unsigned reply_len; -- char *serverout = 0; -+ const char *serverout = 0; - unsigned serveroutlen; - int result; -- const char *errstr = 0; - - #define IFELSE(e1,e2,e3) ((e1) ? (e2) : (e3)) - -@@ -289,7 +285,7 @@ - VSTRING_SPACE(state->sasl_decoded, reply_len); - dec_buffer = STR(state->sasl_decoded); - if (sasl_decode64(init_response, reply_len, -- dec_buffer, &dec_length) != SASL_OK) -+ dec_buffer, reply_len, &dec_length) != SASL_OK) - return ("501 Authentication failed: malformed initial response"); - if (msg_verbose) - msg_info("%s: decoded initial response %s", myname, dec_buffer); -@@ -298,7 +294,7 @@ - dec_length = 0; - } - result = sasl_server_start(state->sasl_conn, sasl_method, dec_buffer, -- dec_length, &serverout, &serveroutlen, &errstr); -+ dec_length, &serverout, &serveroutlen); - - /* - * Repeat until done or until the client gives up. -@@ -327,7 +323,6 @@ - if (sasl_encode64(serverout, serveroutlen, STR(state->sasl_encoded), - enc_length, &enc_length_out) != SASL_OK) - msg_panic("%s: sasl_encode64 botch", myname); -- free(serverout); - serverout = 0; - smtpd_chat_reply(state, "334 %s", STR(state->sasl_encoded)); - -@@ -343,22 +338,16 @@ - reply_len = VSTRING_LEN(state->buffer); - VSTRING_SPACE(state->sasl_decoded, reply_len); - if (sasl_decode64(vstring_str(state->buffer), reply_len, -- STR(state->sasl_decoded), &dec_length) != SASL_OK) -+ STR(state->sasl_decoded), reply_len, &dec_length) != SASL_OK) - return ("501 Error: malformed authentication response"); - if (msg_verbose) - msg_info("%s: decoded response: %.*s", - myname, (int) dec_length, STR(state->sasl_decoded)); - result = sasl_server_step(state->sasl_conn, STR(state->sasl_decoded), -- dec_length, &serverout, &serveroutlen, &errstr); -+ dec_length, &serverout, &serveroutlen); - } - - /* -- * Cleanup. What an awful interface. -- */ -- if (serverout) -- free(serverout); -- -- /* - * The authentication protocol was completed. - */ - if (result != SASL_OK) -@@ -370,7 +359,7 @@ - * authentication method that was used. XXX Do not free(serverout). - */ - result = sasl_getprop(state->sasl_conn, SASL_USERNAME, -- (void **) &serverout); -+ (const void **) &serverout); - if (result != SASL_OK || serverout == 0) - msg_panic("%s: sasl_getprop SASL_USERNAME botch", myname); - state->sasl_username = mystrdup(serverout); -- 2.44.0