a patch by Victor Duchovni. Files: proto/TLS_README.html,
proto/postconf.proto, tls/tls.h, tls/tls_misc.c, tls/tls_client.c,
tls/tls_server.c.
+
+20120425
+
+ Workaround: bugs in 10-year old gcc versions break compilation
+ with #ifdef inside a macro invocation (NOT: definition).
+ This synchronizes the Postfix 2.9 TLS implementation with
+ Postfix 2.10 to simplify code maintenance. Files: tls/tls.h,
+ tls/tls_client.c, tls/tls_server.c.
+
+20120426
+
+ Bugfix (introduced Postfix 2.9): the postconf command flagged
+ parameters defined in master.cf as "unused" when they were
+ used only in main.cf. Problem reported by Michael Tokarev.
+ Files: postconf/postconf_user.c.
+
+20120516
+
+ Workaround: apparently, FreeBSD 8.3 kqueue notifications
+ sometimes break when a dnsblog(8) process loses an accept()
+ race on a shared socket, resulting in repeated "connect to
+ private/dnsblog service: Connection refused" warnings. This
+ condition is unique to dnsblog(8). The postscreen(8) daemon
+ closes a postscreen-to-dnsblog connection as soon as it
+ receives a dnsblog(8) reply, resulting in hundreds or
+ thousands of connection requests per second. All other
+ multi-server daemons such as anvil(8) or proxymap(8) have
+ connection lifetimes ranging from 5s to 1000s depending on
+ server load. The workaround is for dnsblog to use the
+ single_server driver instead of the multi_server driver.
+ This one-line code change eliminates the accept() race
+ without any Postfix performance impact. Problem reported
+ by Sahil Tandon. File: dnsblog/dnsblog.c.
+
+20120517
+
+ Workaround: to avoid crashes when the OpenSSL library is
+ updated without "postfix reload", the Postfix TLS session
+ cache ID now includes the OpenSSL library version number.
+ Note: this problem cannot be fixed in tlsmgr(8). Code by
+ Victor Duchovni. Files: tls/tls_server.c, tls_client.c.
+
+20120520
+
+ Bugfix (introduced Postfix 2.4): the event_drain() function
+ was comparing bitmasks incorrectly causing the program to
+ always wait for the full time limit. This error affected
+ the unused postkick command, but only after s/fifo/unix/
+ in master.cf. File: util/events.c.
+
+ Cleanup: laptop users have always been able to avoid
+ unnecessary disk spin-up by doing s/fifo/unix/ in master.cf
+ (this is currently not supported on Solaris systems).
+ However, to make this work reliably, the "postqueue -f"
+ command must wait until its requests have reached the pickup
+ and qmgr servers before closing the UNIX-domain request
+ sockets. Files: postqueue/postqueue.c, postqueue/Makefile.in.
query = vstring_alloc(100);
why = vstring_alloc(100);
result = vstring_alloc(100);
+ var_use_limit = 0;
}
MAIL_VERSION_STAMP_DECLARE;
*/
MAIL_VERSION_STAMP_ALLOCATE;
- multi_server_main(argc, argv, dnsblog_service,
- MAIL_SERVER_TIME_TABLE, time_table,
- MAIL_SERVER_POST_INIT, post_jail_init,
- MAIL_SERVER_UNLIMITED,
- 0);
+ single_server_main(argc, argv, dnsblog_service,
+ MAIL_SERVER_TIME_TABLE, time_table,
+ MAIL_SERVER_POST_INIT, post_jail_init,
+ MAIL_SERVER_UNLIMITED,
+ 0);
}
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20120424"
-#define MAIL_VERSION_NUMBER "2.9.2"
+#define MAIL_RELEASE_DATE "20120520"
+#define MAIL_VERSION_NUMBER "2.9.3"
#ifdef SNAPSHOT
# define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE
* compatibility after a feature name change.
*/
if (local_scope && dict_get(local_scope->all_params, mac_name)) {
+ /* $name in master.cf references name=value in master.cf. */
if (PC_PARAM_TABLE_LOCATE(local_scope->valid_names, mac_name) == 0)
PC_PARAM_TABLE_ENTER(local_scope->valid_names, mac_name,
PC_PARAM_FLAG_USER, PC_PARAM_NO_DATA,
convert_user_parameter);
} else if (mail_conf_lookup(mac_name) != 0) {
+ /* $name in main/master.cf references name=value in main.cf. */
if (PC_PARAM_TABLE_LOCATE(param_table, mac_name) == 0)
PC_PARAM_TABLE_ENTER(param_table, mac_name, PC_PARAM_FLAG_USER,
PC_PARAM_NO_DATA, convert_user_parameter);
}
+ if (local_scope == 0) {
+ for (local_scope = master_table; local_scope->argv; local_scope++) {
+ if (local_scope->all_params != 0
+ && dict_get(local_scope->all_params, mac_name) != 0
+ /* $name in main.cf references name=value in master.cf. */
+ && PC_PARAM_TABLE_LOCATE(local_scope->valid_names, mac_name) == 0)
+ PC_PARAM_TABLE_ENTER(local_scope->valid_names, mac_name,
+ PC_PARAM_FLAG_USER, PC_PARAM_NO_DATA,
+ convert_user_parameter);
+ }
+ }
return (0);
}
rest_class_table = htable_create(1);
/*
- * Scan parameter values that are left at their defaults in the global
- * name space. Some defaults contain the $name of an obsolete parameter
- * for backwards compatilility purposes. We might warn that an explicit
- * name=value is obsolete, but we must not warn that the parameter is
- * unused.
- */
- scan_default_parameter_values(param_table, CONFIG_DICT, (PC_MASTER_ENT *) 0);
-
- /*
- * Scan the explicit name=value entries in the global name space.
- */
- scan_user_parameter_namespace(CONFIG_DICT, (PC_MASTER_ENT *) 0);
-
- /*
- * Scan the "-o parameter=value" instances in each master.cf name space.
+ * Initialize the per-service parameter name spaces.
*/
for (masterp = master_table; (argv = masterp->argv) != 0; masterp++) {
for (field = PC_MASTER_MIN_FIELDS; argv->argv[field] != 0; field++) {
if ((dict = dict_handle(masterp->name_space)) != 0) {
masterp->all_params = dict;
masterp->valid_names = htable_create(1);
- scan_user_parameter_namespace(masterp->name_space, masterp);
}
}
+
+ /*
+ * Scan parameter values that are left at their defaults in the global
+ * name space. Some defaults contain the $name of an obsolete parameter
+ * for backwards compatilility purposes. We might warn that an explicit
+ * name=value is obsolete, but we must not warn that the parameter is
+ * unused.
+ */
+ scan_default_parameter_values(param_table, CONFIG_DICT, (PC_MASTER_ENT *) 0);
+
+ /*
+ * Scan the explicit name=value entries in the global name space.
+ */
+ scan_user_parameter_namespace(CONFIG_DICT, (PC_MASTER_ENT *) 0);
+
+ /*
+ * Scan the "-o parameter=value" instances in each master.cf name space.
+ */
+ for (masterp = master_table; masterp->argv != 0; masterp++)
+ if (masterp->all_params != 0)
+ scan_user_parameter_namespace(masterp->name_space, masterp);
}
postqueue.o: ../../include/attr.h
postqueue.o: ../../include/clean_env.h
postqueue.o: ../../include/connect.h
+postqueue.o: ../../include/events.h
postqueue.o: ../../include/flush_clnt.h
postqueue.o: ../../include/iostuff.h
postqueue.o: ../../include/mail_conf.h
#include <connect.h>
#include <valid_hostname.h>
#include <warn_stat.h>
+#include <events.h>
/* Global library. */
if (mail_flush_maildrop() < 0)
msg_fatal_status(EX_UNAVAILABLE,
"Cannot flush mail queue - mail system is down");
+ event_drain(2);
}
/* flush_site - flush mail for site */
#include <name_mask.h>
#include <name_code.h>
-#define TLS_BIO_BUFSIZE 8192
-
/*
* Names of valid tlsmgr(8) session caches.
*/
#define TLS_PROTOCOL_TLSv1_1 (1<<3) /* TLSv1_1 */
#else
#define TLS_PROTOCOL_TLSv1_1 0 /* Unknown */
+#undef SSL_OP_NO_TLSv1_1
+#define SSL_OP_NO_TLSv1_1 0L /* Noop */
#endif
#ifdef SSL_TXT_TLSV1_2
#define TLS_PROTOCOL_TLSv1_2 (1<<4) /* TLSv1_2 */
#else
#define TLS_PROTOCOL_TLSv1_2 0 /* Unknown */
+#undef SSL_OP_NO_TLSv1_2
+#define SSL_OP_NO_TLSv1_2 0L /* Noop */
#endif
#define TLS_KNOWN_PROTOCOLS \
( TLS_PROTOCOL_SSLv2 | TLS_PROTOCOL_SSLv3 | TLS_PROTOCOL_TLSv1 \
msg_info("%s: TLS cipher list \"%s\"", props->namaddr, cipher_list);
vstring_sprintf_append(myserverid, "&c=%s", cipher_list);
+ /*
+ * Finally, salt the session key with the OpenSSL library version,
+ * (run-time, rather than compile-time, just in case that matters).
+ */
+ vstring_sprintf_append(myserverid, "&l=%ld", (long) SSLeay());
+
/*
* Allocate a new TLScontext for the new connection and get an SSL
* structure. Add the location of TLScontext to the SSL to later retrieve
if (protomask != 0)
SSL_set_options(TLScontext->con,
((protomask & TLS_PROTOCOL_TLSv1) ? SSL_OP_NO_TLSv1 : 0L)
-#ifdef SSL_OP_NO_TLSv1_1
| ((protomask & TLS_PROTOCOL_TLSv1_1) ? SSL_OP_NO_TLSv1_1 : 0L)
-#endif
-#ifdef SSL_OP_NO_TLSv1_2
| ((protomask & TLS_PROTOCOL_TLSv1_2) ? SSL_OP_NO_TLSv1_2 : 0L)
-#endif
| ((protomask & TLS_PROTOCOL_SSLv3) ? SSL_OP_NO_SSLv3 : 0L)
| ((protomask & TLS_PROTOCOL_SSLv2) ? SSL_OP_NO_SSLv2 : 0L));
#define GEN_CACHE_ID(buf, id, len, service) \
do { \
- buf = vstring_alloc(2 * (len) + 1 + strlen(service) + 3); \
+ buf = vstring_alloc(2 * (len + strlen(service))); \
hex_encode(buf, (char *) (id), (len)); \
vstring_sprintf_append(buf, "&s=%s", (service)); \
+ vstring_sprintf_append(buf, "&l=%ld", (long) SSLeay()); \
} while (0)
if (protomask != 0)
SSL_CTX_set_options(server_ctx,
((protomask & TLS_PROTOCOL_TLSv1) ? SSL_OP_NO_TLSv1 : 0L)
-#ifdef SSL_OP_NO_TLSv1_1
| ((protomask & TLS_PROTOCOL_TLSv1_1) ? SSL_OP_NO_TLSv1_1 : 0L)
-#endif
-#ifdef SSL_OP_NO_TLSv1_2
| ((protomask & TLS_PROTOCOL_TLSv1_2) ? SSL_OP_NO_TLSv1_2 : 0L)
-#endif
| ((protomask & TLS_PROTOCOL_SSLv3) ? SSL_OP_NO_SSLv3 : 0L)
| ((protomask & TLS_PROTOCOL_SSLv2) ? SSL_OP_NO_SSLv2 : 0L));
#define EVENT_MASK_SET(fd, mask) FD_SET((fd), (mask))
#define EVENT_MASK_ISSET(fd, mask) FD_ISSET((fd), (mask))
#define EVENT_MASK_CLR(fd, mask) FD_CLR((fd), (mask))
+#define EVENT_MASK_CMP(m1, m2) memcmp((m1), (m2), EVENT_MASK_BYTE_COUNT(m1))
#else
/*
(EVENT_MASK_FD_BYTE((fd), (mask)) & EVENT_MASK_FD_BIT(fd))
#define EVENT_MASK_CLR(fd, mask) \
(EVENT_MASK_FD_BYTE((fd), (mask)) &= ~EVENT_MASK_FD_BIT(fd))
+#define EVENT_MASK_CMP(m1, m2) \
+ memcmp((m1)->data, (m2)->data, EVENT_MASK_BYTE_COUNT(m1))
#endif
/*
max_time = event_present + time_limit;
while (event_present < max_time
&& (event_timer_head.pred != &event_timer_head
- || memcmp(&zero_mask, &event_xmask,
- EVENT_MASK_BYTE_COUNT(&zero_mask)) != 0)) {
+ || EVENT_MASK_CMP(&zero_mask, &event_xmask) != 0)) {
event_loop(1);
#if (EVENTS_STYLE != EVENTS_STYLE_SELECT)
if (EVENT_MASK_BYTE_COUNT(&zero_mask)