From: Wietse Z Venema
Specify a list of names and/or name=value pairs, separated by @@ -12497,6 +12502,12 @@ line.
/etc/postfix/reply_filter: + # Some Microsoft servers violate RFC 2554 section 4, causing Postfix + # to complain with "non-empty initial GSSAPI challenge from server" + /^334\s+GSSAPI\s+supported/ 334 ++ +
# Transform garbage into "250-filler..." so that it looks like
# one line from a multi-line reply. It does not matter what we
# substitute here as long it has the right syntax. The Postfix
diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5
index 8baada969..8c2039ecb 100644
--- a/postfix/man/man5/postconf.5
+++ b/postfix/man/man5/postconf.5
@@ -2633,14 +2633,17 @@ Needed for debugging Postfix daemons with an X\-windows debugger.
.IP "\fBMAIL_CONFIG\fR"
Needed to make "\fBpostfix \-c\fR" work.
.br
-.IP "\fBPOSTLOG_SERVICE\fR"
+.IP "\fBPOSTLOG_HOSTNAME\fR"
Needed to make "\fBmaillog_file\fR" work during daemon
process initialization.
.br
-.IP "\fBPOSTLOG_HOSTNAME\fR"
+.IP "\fBPOSTLOG_SERVICE\fR"
Needed to make "\fBmaillog_file\fR" work during daemon
process initialization.
.br
+.IP "\fBXDG_RUNTIME_DIR\fR"
+Needed for debugging Postfix daemons with an XDG\-style debugger.
+.br
.br
.PP
Specify a list of names and/or name=value pairs, separated by
@@ -7892,6 +7895,14 @@ Examples:
.nf
.na
/etc/postfix/reply_filter:
+ # Some Microsoft servers violate RFC 2554 section 4, causing Postfix
+ # to complain with "non\-empty initial GSSAPI challenge from server"
+ /^334\es+GSSAPI\es+supported/ 334
+.fi
+.ad
+.PP
+.nf
+.na
# Transform garbage into "250\-filler..." so that it looks like
# one line from a multi\-line reply. It does not matter what we
# substitute here as long it has the right syntax. The Postfix
diff --git a/postfix/mantools/check-spell-proto-html b/postfix/mantools/check-spell-proto-html
index b81ce1f97..ffd427f96 100755
--- a/postfix/mantools/check-spell-proto-html
+++ b/postfix/mantools/check-spell-proto-html
@@ -4,4 +4,4 @@
LANG=C; export LANG
-mantools/dehtml proto/*html proto/*.proto | spell | grep -F -vxf proto/stop | grep -F -vxf proto/stop.spell-proto-html
+mantools/dehtml proto/*html proto/*.proto | tr '+' ' ' | spell | grep -F -vxf proto/stop | grep -F -vxf proto/stop.spell-proto-html
diff --git a/postfix/proto/COMPATIBILITY_README.html b/postfix/proto/COMPATIBILITY_README.html
index 000f06269..20d72b423 100644
--- a/postfix/proto/COMPATIBILITY_README.html
+++ b/postfix/proto/COMPATIBILITY_README.html
@@ -614,7 +614,7 @@ make the backwards-compatible setting "smtp_tlsrpt_skip_reused_handshakes
default setting xxx_security_level=(empty)
Postfix version 3.11 changes the default value for client TLS
-security levels from "empty" to "yes". The backwards-compatibility
+security levels from "empty" to "may". The backwards-compatibility
safety net is designed to prevent an unexpected change in mail
sending behavior when Postfix is updated from an older version.
diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto
index e6aa3680b..0a4a9255e 100644
--- a/postfix/proto/postconf.proto
+++ b/postfix/proto/postconf.proto
@@ -1984,15 +1984,20 @@ environment. Examples of relevant environment variables:
/etc/postfix/reply_filter: + # Some Microsoft servers violate RFC 2554 section 4, causing Postfix + # to complain with "non-empty initial GSSAPI challenge from server" + /^334\s+GSSAPI\s+supported/ 334 ++ +
# Transform garbage into "250-filler..." so that it looks like
# one line from a multi-line reply. It does not matter what we
# substitute here as long it has the right syntax. The Postfix
diff --git a/postfix/proto/stop b/postfix/proto/stop
index c09b1c34e..5a7a3b12a 100644
--- a/postfix/proto/stop
+++ b/postfix/proto/stop
@@ -1683,3 +1683,4 @@ typofix
LD
PRELOAD
rhansen
+XDG
diff --git a/postfix/proto/stop.double-history b/postfix/proto/stop.double-history
index cf5da6405..6fb0842b7 100644
--- a/postfix/proto/stop.double-history
+++ b/postfix/proto/stop.double-history
@@ -179,3 +179,5 @@ proto proto COMPATIBILITY_README html
postconf Makefile in postconf postconf c
dict_open Files util dict hc proxymap proxymap c
proxymap proxymap c
+ postmap postmap c postalias postalias c
+ client Files dict h dict_proxy c proxymap proxymap c
diff --git a/postfix/proto/stop.spell-history b/postfix/proto/stop.spell-history
index da067ab97..42b996fab 100644
--- a/postfix/proto/stop.spell-history
+++ b/postfix/proto/stop.spell-history
@@ -106,3 +106,7 @@ Kozmenko
Oleksandr
Bataille
balancers
+Unbroke
+XDG
+ENOTSOCK
+FustÃ
diff --git a/postfix/src/global/dict_proxy.c b/postfix/src/global/dict_proxy.c
index 0157d01a2..a0ce1b2e0 100644
--- a/postfix/src/global/dict_proxy.c
+++ b/postfix/src/global/dict_proxy.c
@@ -113,6 +113,7 @@ static int dict_proxy_sequence(DICT *dict, int function,
VSTREAM *stream;
int status;
int count = 0;
+ int inst_flags;
int request_flags;
/*
@@ -126,8 +127,8 @@ static int dict_proxy_sequence(DICT *dict, int function,
VSTRING_TERMINATE(dict_proxy->reskey);
VSTRING_RESET(dict_proxy->result);
VSTRING_TERMINATE(dict_proxy->result);
- request_flags = dict_proxy->inst_flags
- | (dict->flags & DICT_FLAG_RQST_MASK);
+ inst_flags = dict_proxy->inst_flags;
+ request_flags = dict->flags;
for (;;) {
stream = clnt_stream_access(dict_proxy->clnt);
errno = 0;
@@ -136,15 +137,17 @@ static int dict_proxy_sequence(DICT *dict, int function,
|| attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_SEQUENCE),
SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name),
+ SEND_ATTR_INT(MAIL_ATTR_INST_FLAGS, inst_flags),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags),
SEND_ATTR_INT(MAIL_ATTR_FUNC, function),
ATTR_TYPE_END) != 0
|| vstream_fflush(stream)
|| attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &status),
+ RECV_ATTR_INT(MAIL_ATTR_FLAGS, &dict->flags),
RECV_ATTR_STR(MAIL_ATTR_KEY, dict_proxy->reskey),
RECV_ATTR_STR(MAIL_ATTR_VALUE, dict_proxy->result),
- ATTR_TYPE_END) != 3) {
+ ATTR_TYPE_END) != 4) {
if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT))
msg_warn("%s: service %s: %m", myname, dict_proxy->service);
} else {
@@ -194,6 +197,7 @@ static const char *dict_proxy_lookup(DICT *dict, const char *key)
VSTREAM *stream;
int status;
int count = 0;
+ int inst_flags;
int request_flags;
/*
@@ -205,8 +209,8 @@ static const char *dict_proxy_lookup(DICT *dict, const char *key)
*/
VSTRING_RESET(dict_proxy->result);
VSTRING_TERMINATE(dict_proxy->result);
- request_flags = dict_proxy->inst_flags
- | (dict->flags & DICT_FLAG_RQST_MASK);
+ inst_flags = dict_proxy->inst_flags;
+ request_flags = dict->flags;
for (;;) {
stream = clnt_stream_access(dict_proxy->clnt);
errno = 0;
@@ -215,14 +219,16 @@ static const char *dict_proxy_lookup(DICT *dict, const char *key)
|| attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_LOOKUP),
SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name),
+ SEND_ATTR_INT(MAIL_ATTR_INST_FLAGS, inst_flags),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags),
SEND_ATTR_STR(MAIL_ATTR_KEY, key),
ATTR_TYPE_END) != 0
|| vstream_fflush(stream)
|| attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &status),
+ RECV_ATTR_INT(MAIL_ATTR_FLAGS, &dict->flags),
RECV_ATTR_STR(MAIL_ATTR_VALUE, dict_proxy->result),
- ATTR_TYPE_END) != 2) {
+ ATTR_TYPE_END) != 3) {
if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT))
msg_warn("%s: service %s: %m", myname, dict_proxy->service);
} else {
@@ -267,6 +273,7 @@ static int dict_proxy_update(DICT *dict, const char *key, const char *value)
VSTREAM *stream;
int status;
int count = 0;
+ int inst_flags;
int request_flags;
/*
@@ -276,8 +283,8 @@ static int dict_proxy_update(DICT *dict, const char *key, const char *value)
* associated with a specific connection. Each lookup needs to specify
* the table and the flags that were specified to dict_proxy_open().
*/
- request_flags = dict_proxy->inst_flags
- | (dict->flags & DICT_FLAG_RQST_MASK);
+ inst_flags = dict_proxy->inst_flags;
+ request_flags = dict->flags;
for (;;) {
stream = clnt_stream_access(dict_proxy->clnt);
errno = 0;
@@ -286,6 +293,7 @@ static int dict_proxy_update(DICT *dict, const char *key, const char *value)
|| attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_UPDATE),
SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name),
+ SEND_ATTR_INT(MAIL_ATTR_INST_FLAGS, inst_flags),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags),
SEND_ATTR_STR(MAIL_ATTR_KEY, key),
SEND_ATTR_STR(MAIL_ATTR_VALUE, value),
@@ -293,7 +301,8 @@ static int dict_proxy_update(DICT *dict, const char *key, const char *value)
|| vstream_fflush(stream)
|| attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &status),
- ATTR_TYPE_END) != 1) {
+ RECV_ATTR_INT(MAIL_ATTR_FLAGS, &dict->flags),
+ ATTR_TYPE_END) != 2) {
if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT))
msg_warn("%s: service %s: %m", myname, dict_proxy->service);
} else {
@@ -337,6 +346,7 @@ static int dict_proxy_delete(DICT *dict, const char *key)
VSTREAM *stream;
int status;
int count = 0;
+ int inst_flags;
int request_flags;
/*
@@ -346,8 +356,8 @@ static int dict_proxy_delete(DICT *dict, const char *key)
* associated with a specific connection. Each lookup needs to specify
* the table and the flags that were specified to dict_proxy_open().
*/
- request_flags = dict_proxy->inst_flags
- | (dict->flags & DICT_FLAG_RQST_MASK);
+ inst_flags = dict_proxy->inst_flags;
+ request_flags = dict->flags;
for (;;) {
stream = clnt_stream_access(dict_proxy->clnt);
errno = 0;
@@ -356,13 +366,15 @@ static int dict_proxy_delete(DICT *dict, const char *key)
|| attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_DELETE),
SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name),
+ SEND_ATTR_INT(MAIL_ATTR_INST_FLAGS, inst_flags),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags),
SEND_ATTR_STR(MAIL_ATTR_KEY, key),
ATTR_TYPE_END) != 0
|| vstream_fflush(stream)
|| attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &status),
- ATTR_TYPE_END) != 1) {
+ RECV_ATTR_INT(MAIL_ATTR_FLAGS, &dict->flags),
+ ATTR_TYPE_END) != 2) {
if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno !=
ENOENT))
msg_warn("%s: service %s: %m", myname, dict_proxy->service);
@@ -478,16 +490,20 @@ DICT *dict_proxy_open(const char *map, int open_flags, int dict_flags)
dict_proxy->dict.delete = dict_proxy_delete;
dict_proxy->dict.sequence = dict_proxy_sequence;
dict_proxy->dict.close = dict_proxy_close;
- dict_proxy->inst_flags = (dict_flags & DICT_FLAG_INST_MASK);
+ dict_proxy->inst_flags = dict_flags;
dict_proxy->reskey = vstring_alloc(10);
dict_proxy->result = vstring_alloc(10);
dict_proxy->clnt = *pstream;
dict_proxy->service = service;
+#define DICT_PROXY_ERR_RETURN(d) do { \
+ DICT *_d = (d); \
+ dict_proxy_close(&dict_proxy->dict); \
+ return (_d); \
+ } while (0)
+
/*
* Establish initial contact and get the map type specific flags.
- *
- * XXX Should retrieve flags from local instance.
*/
for (;;) {
stream = clnt_stream_access(dict_proxy->clnt);
@@ -496,7 +512,7 @@ DICT *dict_proxy_open(const char *map, int open_flags, int dict_flags)
|| attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_OPEN),
SEND_ATTR_STR(MAIL_ATTR_TABLE, dict_proxy->dict.name),
- SEND_ATTR_INT(MAIL_ATTR_FLAGS, dict_proxy->inst_flags),
+ SEND_ATTR_INT(MAIL_ATTR_INST_FLAGS, dict_proxy->inst_flags),
ATTR_TYPE_END) != 0
|| vstream_fflush(stream)
|| attr_scan(stream, ATTR_FLAG_STRICT,
@@ -512,14 +528,17 @@ DICT *dict_proxy_open(const char *map, int open_flags, int dict_flags)
dict_flags_str(server_flags));
switch (status) {
case PROXY_STAT_BAD:
- msg_fatal("%s open failed for table \"%s\": invalid request",
- dict_proxy->service, dict_proxy->dict.name);
+ DICT_PROXY_ERR_RETURN(dict_surrogate(DICT_TYPE_PROXY,
+ dict_proxy->dict.name, open_flags, dict_flags,
+ "%s open failed for table \"%s\": invalid request",
+ dict_proxy->service, dict_proxy->dict.name));
case PROXY_STAT_DENY:
- msg_fatal("%s service is not configured for table \"%s\"",
- dict_proxy->service, dict_proxy->dict.name);
+ DICT_PROXY_ERR_RETURN(dict_surrogate(DICT_TYPE_PROXY,
+ dict_proxy->dict.name, open_flags, dict_flags,
+ "%s service is not configured for table \"%s\"",
+ dict_proxy->service, dict_proxy->dict.name));
case PROXY_STAT_OK:
- dict_proxy->dict.flags = (dict_flags & ~DICT_FLAG_IMPL_MASK)
- | (server_flags & DICT_FLAG_IMPL_MASK);
+ dict_proxy->dict.flags = server_flags;
return (&dict_proxy->dict);
default:
msg_warn("%s open failed for table \"%s\": unexpected status %d",
diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h
index 690256a60..cf7d791ea 100644
--- a/postfix/src/global/mail_params.h
+++ b/postfix/src/global/mail_params.h
@@ -2663,7 +2663,8 @@ extern int var_fflush_refresh;
#define VAR_IMPORT_ENVIRON "import_environment"
#define DEF_IMPORT_ENVIRON "MAIL_CONFIG MAIL_DEBUG MAIL_LOGTAG " \
"TZ XAUTHORITY DISPLAY LANG=C " \
- "POSTLOG_SERVICE POSTLOG_HOSTNAME"
+ "POSTLOG_SERVICE POSTLOG_HOSTNAME" \
+ "XDG_RUNTIME_DIR"
extern char *var_import_environ;
#define VAR_EXPORT_ENVIRON "export_environment"
diff --git a/postfix/src/global/mail_proto.h b/postfix/src/global/mail_proto.h
index 798de6694..d784ce42d 100644
--- a/postfix/src/global/mail_proto.h
+++ b/postfix/src/global/mail_proto.h
@@ -210,6 +210,8 @@ extern char *mail_pathname(const char *, const char *);
#define MAIL_ATTR_COMPAT_LEVEL "compatibility_level"
#define MAIL_ATTR_MAIL_VERSION "mail_version"
+#define MAIL_ATTR_INST_FLAGS "instance_flags"
+
/*
* Suffixes for sender_name, sender_domain etc.
*/
diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h
index f19314a40..a1d0ccefd 100644
--- a/postfix/src/global/mail_version.h
+++ b/postfix/src/global/mail_version.h
@@ -20,7 +20,7 @@
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20250709"
+#define MAIL_RELEASE_DATE "20250713"
#define MAIL_VERSION_NUMBER "3.11"
#ifdef SNAPSHOT
diff --git a/postfix/src/master/event_server.c b/postfix/src/master/event_server.c
index 9802bdf2f..30e80ba5e 100644
--- a/postfix/src/master/event_server.c
+++ b/postfix/src/master/event_server.c
@@ -273,6 +273,7 @@ static unsigned event_server_generation;
static void (*event_server_pre_disconn) (VSTREAM *, char *, char **);
static void (*event_server_slow_exit) (char *, char **);
static int event_server_watchdog = 1000;
+static int event_server_drain_was_called = 0;
/* event_server_exit - normal termination */
@@ -327,6 +328,9 @@ int event_server_drain(void)
const char *myname = "event_server_drain";
int fd;
+ if (event_server_drain_was_called)
+ return;
+
switch (fork()) {
/* Try again later. */
case -1:
@@ -343,6 +347,7 @@ int event_server_drain(void)
msg_warn("%s: dup2(%d, %d): %m", myname, STDIN_FILENO, fd);
}
var_use_limit = 1;
+ event_server_drain_was_called = 1;
return (0);
/* Let the master start a new process. */
default:
@@ -445,6 +450,9 @@ static void event_server_accept_local(int unused_event, void *context)
int time_left = -1;
int fd;
+ if (event_server_drain_was_called)
+ return;
+
/*
* Be prepared for accept() to fail because some other process already
* got the connection (the number of processes competing for clients is
@@ -457,6 +465,8 @@ static void event_server_accept_local(int unused_event, void *context)
if (event_server_pre_accept)
event_server_pre_accept(event_server_name, event_server_argv);
+ if (event_server_drain_was_called)
+ return;
fd = LOCAL_ACCEPT(listen_fd);
if (event_server_lock != 0
&& myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK,
@@ -483,6 +493,9 @@ static void event_server_accept_pass(int unused_event, void *context)
int fd;
HTABLE *attr = 0;
+ if (event_server_drain_was_called)
+ return;
+
/*
* Be prepared for accept() to fail because some other process already
* got the connection (the number of processes competing for clients is
@@ -495,6 +508,8 @@ static void event_server_accept_pass(int unused_event, void *context)
if (event_server_pre_accept)
event_server_pre_accept(event_server_name, event_server_argv);
+ if (event_server_drain_was_called)
+ return;
fd = pass_accept_attr(listen_fd, &attr);
if (event_server_lock != 0
&& myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK,
@@ -520,6 +535,9 @@ static void event_server_accept_inet(int unused_event, void *context)
int time_left = -1;
int fd;
+ if (event_server_drain_was_called)
+ return;
+
/*
* Be prepared for accept() to fail because some other process already
* got the connection (the number of processes competing for clients is
@@ -532,6 +550,8 @@ static void event_server_accept_inet(int unused_event, void *context)
if (event_server_pre_accept)
event_server_pre_accept(event_server_name, event_server_argv);
+ if (event_server_drain_was_called)
+ return;
fd = inet_accept(listen_fd);
if (event_server_lock != 0
&& myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK,
diff --git a/postfix/src/master/multi_server.c b/postfix/src/master/multi_server.c
index 6150f229a..51004d6d0 100644
--- a/postfix/src/master/multi_server.c
+++ b/postfix/src/master/multi_server.c
@@ -260,6 +260,7 @@ static VSTREAM *multi_server_lock;
static int multi_server_in_flow_delay;
static unsigned multi_server_generation;
static void (*multi_server_pre_disconn) (VSTREAM *, char *, char **);
+static int multi_server_drain_was_called = 0;
/* multi_server_exit - normal termination */
@@ -295,6 +296,9 @@ int multi_server_drain(void)
const char *myname = "multi_server_drain";
int fd;
+ if (multi_server_drain_was_called)
+ return;
+
switch (fork()) {
/* Try again later. */
case -1:
@@ -311,6 +315,7 @@ int multi_server_drain(void)
msg_warn("%s: dup2(%d, %d): %m", myname, STDIN_FILENO, fd);
}
var_use_limit = 1;
+ multi_server_drain_was_called = 1;
return (0);
/* Let the master start a new process. */
default:
@@ -429,6 +434,9 @@ static void multi_server_accept_local(int unused_event, void *context)
int time_left = -1;
int fd;
+ if (multi_server_drain_was_called)
+ return;
+
/*
* Be prepared for accept() to fail because some other process already
* got the connection (the number of processes competing for clients is
@@ -441,6 +449,8 @@ static void multi_server_accept_local(int unused_event, void *context)
if (multi_server_pre_accept)
multi_server_pre_accept(multi_server_name, multi_server_argv);
+ if (multi_server_drain_was_called)
+ return;
fd = LOCAL_ACCEPT(listen_fd);
if (multi_server_lock != 0
&& myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK,
@@ -467,6 +477,9 @@ static void multi_server_accept_pass(int unused_event, void *context)
int fd;
HTABLE *attr = 0;
+ if (multi_server_drain_was_called)
+ return;
+
/*
* Be prepared for accept() to fail because some other process already
* got the connection (the number of processes competing for clients is
@@ -479,6 +492,8 @@ static void multi_server_accept_pass(int unused_event, void *context)
if (multi_server_pre_accept)
multi_server_pre_accept(multi_server_name, multi_server_argv);
+ if (multi_server_drain_was_called)
+ return;
fd = pass_accept_attr(listen_fd, &attr);
if (multi_server_lock != 0
&& myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK,
@@ -504,6 +519,9 @@ static void multi_server_accept_inet(int unused_event, void *context)
int time_left = -1;
int fd;
+ if (multi_server_drain_was_called)
+ return;
+
/*
* Be prepared for accept() to fail because some other process already
* got the connection (the number of processes competing for clients is
@@ -516,6 +534,8 @@ static void multi_server_accept_inet(int unused_event, void *context)
if (multi_server_pre_accept)
multi_server_pre_accept(multi_server_name, multi_server_argv);
+ if (multi_server_drain_was_called)
+ return;
fd = inet_accept(listen_fd);
if (multi_server_lock != 0
&& myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK,
diff --git a/postfix/src/postalias/postalias.c b/postfix/src/postalias/postalias.c
index c17b6a1d6..9e77a6b20 100644
--- a/postfix/src/postalias/postalias.c
+++ b/postfix/src/postalias/postalias.c
@@ -690,8 +690,6 @@ static void postalias_seq(const char *map_type, const char *map_name,
const char *value;
int func;
- if (strcmp(map_type, DICT_TYPE_PROXY) == 0)
- msg_fatal("can't sequence maps via the proxy service");
dict = dict_open3(map_type, map_name, O_RDONLY, dict_flags);
for (func = DICT_SEQ_FUN_FIRST; /* void */ ; func = DICT_SEQ_FUN_NEXT) {
if (dict_seq(dict, func, &key, &value) != 0)
diff --git a/postfix/src/postmap/postmap.c b/postfix/src/postmap/postmap.c
index 9e8c78381..8f4a83c37 100644
--- a/postfix/src/postmap/postmap.c
+++ b/postfix/src/postmap/postmap.c
@@ -899,8 +899,6 @@ static void postmap_seq(const char *map_type, const char *map_name,
const char *value;
int func;
- if (strcmp(map_type, DICT_TYPE_PROXY) == 0)
- msg_fatal("can't sequence maps via the proxy service");
dict = dict_open3(map_type, map_name, O_RDONLY, dict_flags);
for (func = DICT_SEQ_FUN_FIRST; /* void */ ; func = DICT_SEQ_FUN_NEXT) {
if (dict_seq(dict, func, &key, &value) != 0)
diff --git a/postfix/src/proxymap/proxymap.c b/postfix/src/proxymap/proxymap.c
index 3a00c33c1..270e491a0 100644
--- a/postfix/src/proxymap/proxymap.c
+++ b/postfix/src/proxymap/proxymap.c
@@ -320,7 +320,7 @@ static char *get_nested_dict_name(char *type_name)
/* proxy_map_find - look up or open table */
-static DICT *proxy_map_find(const char *map_type_name, int request_flags,
+static DICT *proxy_map_find(const char *map_type_name, int inst_flags,
int *statp)
{
DICT *dict;
@@ -354,26 +354,12 @@ static DICT *proxy_map_find(const char *map_type_name, int request_flags,
/*
* Open one instance of a map for each combination of name+flags.
- *
- * Assume that a map instance can be shared among clients with different
- * paranoia flag settings and with different map lookup flag settings.
- *
- * XXX The open() flags are passed implicitly, via the selection of the
- * service name. For a more sophisticated interface, appropriate subsets
- * of open() flags should be received directly from the client.
*/
- vstring_sprintf(map_type_name_flags, "%s:%s", map_type_name,
- dict_flags_str(request_flags & DICT_FLAG_INST_MASK));
- if (msg_verbose)
- msg_info("proxy_map_find: %s", STR(map_type_name_flags));
- if ((dict = dict_handle(STR(map_type_name_flags))) == 0) {
- dict = dict_open(map_type_name, proxy_writer ?
- WRITE_OPEN_FLAGS : READ_OPEN_FLAGS,
- request_flags);
- if (dict == 0)
- msg_panic("proxy_map_find: dict_open null result");
- dict_register(STR(map_type_name_flags), dict);
- }
+ dict = dict_open(map_type_name, proxy_writer ?
+ WRITE_OPEN_FLAGS : READ_OPEN_FLAGS,
+ inst_flags);
+ if (dict == 0)
+ msg_panic("proxy_map_find: dict_open null result");
dict->error = 0;
return (dict);
}
@@ -382,6 +368,7 @@ static DICT *proxy_map_find(const char *map_type_name, int request_flags,
static void proxymap_sequence_service(VSTREAM *client_stream)
{
+ int inst_flags;
int request_flags;
DICT *dict;
int request_func;
@@ -395,19 +382,19 @@ static void proxymap_sequence_service(VSTREAM *client_stream)
*/
if (attr_scan(client_stream, ATTR_FLAG_STRICT,
RECV_ATTR_STR(MAIL_ATTR_TABLE, request_map),
+ RECV_ATTR_INT(MAIL_ATTR_INST_FLAGS, &inst_flags),
RECV_ATTR_INT(MAIL_ATTR_FLAGS, &request_flags),
RECV_ATTR_INT(MAIL_ATTR_FUNC, &request_func),
- ATTR_TYPE_END) != 3
+ ATTR_TYPE_END) != 4
|| (request_func != DICT_SEQ_FUN_FIRST
&& request_func != DICT_SEQ_FUN_NEXT)) {
reply_status = PROXY_STAT_BAD;
reply_key = reply_value = "";
- } else if ((dict = proxy_map_find(STR(request_map), request_flags,
+ } else if ((dict = proxy_map_find(STR(request_map), inst_flags,
&reply_status)) == 0) {
reply_key = reply_value = "";
} else {
- dict->flags = ((dict->flags & ~DICT_FLAG_RQST_MASK)
- | (request_flags & DICT_FLAG_RQST_MASK));
+ dict->flags = request_flags;
dict_status = dict_seq(dict, request_func, &reply_key, &reply_value);
if (dict_status == 0) {
reply_status = PROXY_STAT_OK;
@@ -426,6 +413,7 @@ static void proxymap_sequence_service(VSTREAM *client_stream)
*/
attr_print(client_stream, ATTR_FLAG_NONE,
SEND_ATTR_INT(MAIL_ATTR_STATUS, reply_status),
+ SEND_ATTR_INT(MAIL_ATTR_FLAGS, dict->flags),
SEND_ATTR_STR(MAIL_ATTR_KEY, reply_key),
SEND_ATTR_STR(MAIL_ATTR_VALUE, reply_value),
ATTR_TYPE_END);
@@ -435,6 +423,7 @@ static void proxymap_sequence_service(VSTREAM *client_stream)
static void proxymap_lookup_service(VSTREAM *client_stream)
{
+ int inst_flags;
int request_flags;
DICT *dict;
const char *reply_value;
@@ -445,16 +434,16 @@ static void proxymap_lookup_service(VSTREAM *client_stream)
*/
if (attr_scan(client_stream, ATTR_FLAG_STRICT,
RECV_ATTR_STR(MAIL_ATTR_TABLE, request_map),
+ RECV_ATTR_INT(MAIL_ATTR_INST_FLAGS, &inst_flags),
RECV_ATTR_INT(MAIL_ATTR_FLAGS, &request_flags),
RECV_ATTR_STR(MAIL_ATTR_KEY, request_key),
- ATTR_TYPE_END) != 3) {
+ ATTR_TYPE_END) != 4) {
reply_status = PROXY_STAT_BAD;
reply_value = "";
- } else if ((dict = proxy_map_find(STR(request_map), request_flags,
+ } else if ((dict = proxy_map_find(STR(request_map), inst_flags,
&reply_status)) == 0) {
reply_value = "";
- } else if (dict->flags = ((dict->flags & ~DICT_FLAG_RQST_MASK)
- | (request_flags & DICT_FLAG_RQST_MASK)),
+ } else if (dict->flags = request_flags,
(reply_value = dict_get(dict, STR(request_key))) != 0) {
reply_status = PROXY_STAT_OK;
} else if (dict->error == 0) {
@@ -471,6 +460,7 @@ static void proxymap_lookup_service(VSTREAM *client_stream)
*/
attr_print(client_stream, ATTR_FLAG_NONE,
SEND_ATTR_INT(MAIL_ATTR_STATUS, reply_status),
+ SEND_ATTR_INT(MAIL_ATTR_FLAGS, dict->flags),
SEND_ATTR_STR(MAIL_ATTR_VALUE, reply_value),
ATTR_TYPE_END);
}
@@ -479,6 +469,7 @@ static void proxymap_lookup_service(VSTREAM *client_stream)
static void proxymap_update_service(VSTREAM *client_stream)
{
+ int inst_flags;
int request_flags;
DICT *dict;
int dict_status;
@@ -495,21 +486,22 @@ static void proxymap_update_service(VSTREAM *client_stream)
*/
if (attr_scan(client_stream, ATTR_FLAG_STRICT,
RECV_ATTR_STR(MAIL_ATTR_TABLE, request_map),
+ RECV_ATTR_INT(MAIL_ATTR_INST_FLAGS, &inst_flags),
RECV_ATTR_INT(MAIL_ATTR_FLAGS, &request_flags),
RECV_ATTR_STR(MAIL_ATTR_KEY, request_key),
RECV_ATTR_STR(MAIL_ATTR_VALUE, request_value),
- ATTR_TYPE_END) != 4) {
+ ATTR_TYPE_END) != 5) {
reply_status = PROXY_STAT_BAD;
} else if (proxy_writer == 0) {
msg_warn("refusing %s update request on non-%s service",
STR(request_map), MAIL_SERVICE_PROXYWRITE);
reply_status = PROXY_STAT_DENY;
- } else if ((dict = proxy_map_find(STR(request_map), request_flags,
+ } else if ((dict = proxy_map_find(STR(request_map), inst_flags,
&reply_status)) == 0) {
/* void */ ;
} else {
- dict->flags = ((dict->flags & ~DICT_FLAG_RQST_MASK)
- | (request_flags & DICT_FLAG_RQST_MASK)
+ /* Sync the table now. Don't abort on duplicate update. */
+ dict->flags = (request_flags
| DICT_FLAG_SYNC_UPDATE | DICT_FLAG_DUP_REPLACE);
dict_status = dict_put(dict, STR(request_key), STR(request_value));
if (dict_status == 0) {
@@ -527,6 +519,7 @@ static void proxymap_update_service(VSTREAM *client_stream)
*/
attr_print(client_stream, ATTR_FLAG_NONE,
SEND_ATTR_INT(MAIL_ATTR_STATUS, reply_status),
+ SEND_ATTR_INT(MAIL_ATTR_FLAGS, dict->flags),
ATTR_TYPE_END);
}
@@ -534,6 +527,7 @@ static void proxymap_update_service(VSTREAM *client_stream)
static void proxymap_delete_service(VSTREAM *client_stream)
{
+ int inst_flags;
int request_flags;
DICT *dict;
int dict_status;
@@ -547,20 +541,21 @@ static void proxymap_delete_service(VSTREAM *client_stream)
*/
if (attr_scan(client_stream, ATTR_FLAG_STRICT,
RECV_ATTR_STR(MAIL_ATTR_TABLE, request_map),
+ RECV_ATTR_INT(MAIL_ATTR_INST_FLAGS, &inst_flags),
RECV_ATTR_INT(MAIL_ATTR_FLAGS, &request_flags),
RECV_ATTR_STR(MAIL_ATTR_KEY, request_key),
- ATTR_TYPE_END) != 3) {
+ ATTR_TYPE_END) != 4) {
reply_status = PROXY_STAT_BAD;
} else if (proxy_writer == 0) {
msg_warn("refusing %s delete request on non-%s service",
STR(request_map), MAIL_SERVICE_PROXYWRITE);
reply_status = PROXY_STAT_DENY;
- } else if ((dict = proxy_map_find(STR(request_map), request_flags,
+ } else if ((dict = proxy_map_find(STR(request_map), inst_flags,
&reply_status)) == 0) {
/* void */ ;
} else {
- dict->flags = ((dict->flags & ~DICT_FLAG_RQST_MASK)
- | (request_flags & DICT_FLAG_RQST_MASK)
+ /* Sync the table now. There is no close() request. */
+ dict->flags = (request_flags
| DICT_FLAG_SYNC_UPDATE);
dict_status = dict_del(dict, STR(request_key));
if (dict_status == 0) {
@@ -578,6 +573,7 @@ static void proxymap_delete_service(VSTREAM *client_stream)
*/
attr_print(client_stream, ATTR_FLAG_NONE,
SEND_ATTR_INT(MAIL_ATTR_STATUS, reply_status),
+ SEND_ATTR_INT(MAIL_ATTR_FLAGS, dict->flags),
ATTR_TYPE_END);
}
@@ -585,7 +581,7 @@ static void proxymap_delete_service(VSTREAM *client_stream)
static void proxymap_open_service(VSTREAM *client_stream)
{
- int request_flags;
+ int inst_flags;
DICT *dict;
int reply_status;
int reply_flags;
@@ -595,11 +591,11 @@ static void proxymap_open_service(VSTREAM *client_stream)
*/
if (attr_scan(client_stream, ATTR_FLAG_STRICT,
RECV_ATTR_STR(MAIL_ATTR_TABLE, request_map),
- RECV_ATTR_INT(MAIL_ATTR_FLAGS, &request_flags),
+ RECV_ATTR_INT(MAIL_ATTR_INST_FLAGS, &inst_flags),
ATTR_TYPE_END) != 2) {
reply_status = PROXY_STAT_BAD;
reply_flags = 0;
- } else if ((dict = proxy_map_find(STR(request_map), request_flags,
+ } else if ((dict = proxy_map_find(STR(request_map), inst_flags,
&reply_status)) == 0) {
reply_flags = 0;
} else {
@@ -843,14 +839,6 @@ int main(int argc, char **argv)
*/
MAIL_VERSION_STAMP_ALLOCATE;
- /*
- * Workaround for programs that make explicit dict_register() calls with
- * a table that is already registered under a different name. This is
- * safe only in programs that do not unregister or close a table that is
- * registered with multiple names.
- */
- dict_allow_multiple_dict_register_names = 1;
-
/*
* XXX When invoked with the master.cf service name "proxywrite", the
* proxymap daemon will allow update requests. To update a table that is
diff --git a/postfix/src/util/dict.c b/postfix/src/util/dict.c
index 87dee602f..943772325 100644
--- a/postfix/src/util/dict.c
+++ b/postfix/src/util/dict.c
@@ -82,8 +82,6 @@
/* const char *name,
/* int open_flags,
/* int dict_flags)
-/*
-/* int dict_allow_multiple_dict_register_names;
/* DESCRIPTION
/* This module maintains a collection of name-value dictionaries.
/* Each dictionary has its own name and has its own methods to read
@@ -187,14 +185,6 @@
/* This encourages consistent sharing of dictionary instances that
/* have the exact same type:name and (initial) flags. The result
/* value is the string value of the \fIout\fR VSTRING buffer.
-/*
-/* dict_allow_multiple_dict_register_names enables a temporary
-/* workaround for programs that make explicit dict_register()
-/* calls with a table that is already registered under a different
-/* name. Setting this to non-zero allows a dictionary to be
-/* registered under multiple names. This workaround is safe only
-/* in programs that do not unregister or close a table that is
-/* registered with multiple names.
/* TRUST AND PROVENANCE
/* .ad
/* .fi
@@ -339,14 +329,6 @@ typedef struct {
dict = node->dict; \
} while (0)
- /*
- * Workaround for programs that make explicit dict_register() calls with
- * tables that are already registered under a different name. This is safe
- * only in programs that do not unregister or close a table that is
- * registered with multiple names.
- */
-int dict_allow_multiple_dict_register_names = 0;
-
#define STR(x) vstring_str(x)
/* dict_register_close - trigger dictionary cleanup */
@@ -367,8 +349,7 @@ void dict_register(const char *dict_name, DICT *dict_info)
/*
* Enforce referential integrity.
*/
- if (dict_allow_multiple_dict_register_names == 0
- && dict_info->reg_name && strcmp(dict_name, dict_info->reg_name) != 0)
+ if (dict_info->reg_name && strcmp(dict_name, dict_info->reg_name) != 0)
msg_panic("%s: '%s:%s' is already registered under '%s' and cannot "
"also be registered under '%s'", myname, dict_info->type,
dict_info->name, dict_info->reg_name, dict_name);
diff --git a/postfix/src/util/dict.h b/postfix/src/util/dict.h
index 595f18ed0..36def9b3c 100644
--- a/postfix/src/util/dict.h
+++ b/postfix/src/util/dict.h
@@ -141,32 +141,12 @@ extern void dict_free(DICT *);
* The subsets of flags that control how a map is used. These are relevant
* mainly for proxymap support. Note: some categories overlap.
*
- * DICT_FLAG_IMPL_MASK - flags that are set by the map implementation itself.
- *
* DICT_FLAG_PARANOID - requestor flags that forbid the use of insecure map
* types for security-sensitive operations. These flags are checked by the
* map implementation itself upon open, lookup etc. requests.
- *
- * DICT_FLAG_RQST_MASK - all requestor flags, including paranoid flags, that
- * the requestor may change between open, lookup etc. requests. These
- * specify requestor properties, not map properties.
- *
- * DICT_FLAG_INST_MASK - none of the above flags. The requestor may not change
- * these flags between open, lookup, etc. requests (although a map may make
- * changes to its copy of some of these flags). The proxymap server opens
- * only one map instance for all client requests with the same values of
- * these flags, and the proxymap client uses its own saved copy of these
- * flags. DICT_FLAG_SRC_RHS_IS_FILE is an example of such a flag.
*/
#define DICT_FLAG_PARANOID \
(DICT_FLAG_NO_REGSUB | DICT_FLAG_NO_PROXY | DICT_FLAG_NO_UNAUTH)
-#define DICT_FLAG_IMPL_MASK (DICT_FLAG_FIXED | DICT_FLAG_PATTERN | \
- DICT_FLAG_MULTI_WRITER)
-#define DICT_FLAG_RQST_MASK (DICT_FLAG_FOLD_ANY | DICT_FLAG_LOCK | \
- DICT_FLAG_DUP_REPLACE | DICT_FLAG_DUP_WARN | \
- DICT_FLAG_DUP_IGNORE | DICT_FLAG_SYNC_UPDATE | \
- DICT_FLAG_PARANOID | DICT_FLAG_UTF8_MASK)
-#define DICT_FLAG_INST_MASK ~(DICT_FLAG_IMPL_MASK | DICT_FLAG_RQST_MASK)
/*
* Feature tests.
@@ -286,14 +266,6 @@ extern DICT *PRINTFLIKE(5, 6) dict_surrogate(const char *, const char *, int, in
extern char *dict_make_registered_name(VSTRING *, const char *, int, int);
extern char *dict_make_registered_name4(VSTRING *, const char *, const char *, int, int);
- /*
- * Workaround for programs that make explicit dict_register() calls with a
- * table that is already registered under a different name. This is safe
- * only in programs that do not unregister or close a table that is
- * registered with multiple names.
- */
-extern int dict_allow_multiple_dict_register_names;
-
/*
* This name is reserved for matchlist error handling.
*/
diff --git a/postfix/src/util/dict_alloc.c b/postfix/src/util/dict_alloc.c
index d780ecf97..bea8e7d7e 100644
--- a/postfix/src/util/dict_alloc.c
+++ b/postfix/src/util/dict_alloc.c
@@ -147,7 +147,7 @@ DICT *dict_alloc(const char *dict_type, const char *dict_name, ssize_t size)
dict->type = mystrdup(dict_type);
dict->name = mystrdup(dict_name);
- dict->flags = DICT_FLAG_FIXED;
+ dict->flags = 0;
dict->lookup = dict_default_lookup;
dict->update = dict_default_update;
dict->delete = dict_default_delete;
diff --git a/postfix/src/util/dict_test.c b/postfix/src/util/dict_test.c
index bd2cadd4d..26fcd0975 100644
--- a/postfix/src/util/dict_test.c
+++ b/postfix/src/util/dict_test.c
@@ -146,14 +146,8 @@ void dict_test(int argc, char **argv)
vstream_printf("dict flags %s\n",
dict_flags_str(dict->flags));
} else if (strcmp(cmd, "masks") == 0 && !key && !value) {
- vstream_printf("DICT_FLAG_IMPL_MASK %s\n",
- dict_flags_str(DICT_FLAG_IMPL_MASK));
vstream_printf("DICT_FLAG_PARANOID %s\n",
dict_flags_str(DICT_FLAG_PARANOID));
- vstream_printf("DICT_FLAG_RQST_MASK %s\n",
- dict_flags_str(DICT_FLAG_RQST_MASK));
- vstream_printf("DICT_FLAG_INST_MASK %s\n",
- dict_flags_str(DICT_FLAG_INST_MASK));
} else {
vstream_printf("usage: %s\n", USAGE);
}